[
  {
    "path": ".azuredevops/pull_request_template.md",
    "content": "# ⚠️ Before you merge ⚠️\n1. 👘 Ensure that your code follows the [codestyle](https://dev.azure.com/trackman/Golf/_wiki/wikis/Golf.wiki/35/Code-Style)\n2. 🧠 Ensure that you created PRs for ALL branches\n3. 🍄 Test your code by finishing one golf round (download fresh course if tools were changed)\n4. 🖼️ Submit a screenshot of a finished golf round\n5. 💾 Write a [proper](https://keepachangelog.com/en/1.0.0/) description"
  },
  {
    "path": ".gitattributes",
    "content": "# Default\n* text=auto\n\n# Unity\n*.cs      text\n*.shader  text\n*.hlsl    text\n*.cginc   text\n\n# Unity YAML\n*.anim              merge=unityyamlmerge auto\n*.asset             merge=unityyamlmerge auto\n*.controller        merge=unityyamlmerge auto\n*.mat               merge=unityyamlmerge auto\n*.meta              merge=unityyamlmerge auto\n*.physicsMaterial   merge=unityyamlmerge auto\n*.physicsMaterial2D merge=unityyamlmerge auto\n*.prefab            merge=unityyamlmerge auto\n*.unity             merge=unityyamlmerge auto\n\n# Unity LFS\n*.cubemap      filter=lfs diff=lfs merge=lfs\n*.unitypackage filter=lfs diff=lfs merge=lfs\n\n# Image\n*.ai   filter=lfs diff=lfs merge=lfs\n*.apng filter=lfs diff=lfs merge=lfs\n*.astc filter=lfs diff=lfs merge=lfs\n*.bmp  filter=lfs diff=lfs merge=lfs\n*.dds  filter=lfs diff=lfs merge=lfs\n*.eps  filter=lfs diff=lfs merge=lfs\n*.exr  filter=lfs diff=lfs merge=lfs\n*.gif  filter=lfs diff=lfs merge=lfs\n*.hdr  filter=lfs diff=lfs merge=lfs\n*.jpeg filter=lfs diff=lfs merge=lfs\n*.jpg  filter=lfs diff=lfs merge=lfs\n*.JPG  filter=lfs diff=lfs merge=lfs\n*.ktx  filter=lfs diff=lfs merge=lfs\n*.png  filter=lfs diff=lfs merge=lfs\n*.PNG  filter=lfs diff=lfs merge=lfs\n*.psd  filter=lfs diff=lfs merge=lfs\n*.pvr  filter=lfs diff=lfs merge=lfs\n*.svg  filter=lfs diff=lfs merge=lfs\n*.svgz filter=lfs diff=lfs merge=lfs\n*.tga  filter=lfs diff=lfs merge=lfs\n*.TGA  filter=lfs diff=lfs merge=lfs\n*.tif  filter=lfs diff=lfs merge=lfs\n*.tiff filter=lfs diff=lfs merge=lfs\n*.webm filter=lfs diff=lfs merge=lfs\n*.webp filter=lfs diff=lfs merge=lfs\n\n# Audio\n*.aif filter=lfs diff=lfs merge=lfs\n*.m4a filter=lfs diff=lfs merge=lfs\n*.mp3 filter=lfs diff=lfs merge=lfs\n*.ogg filter=lfs diff=lfs merge=lfs\n*.wav filter=lfs diff=lfs merge=lfs\n*.WAV filter=lfs diff=lfs merge=lfs\n\n# Video\n*.asf  filter=lfs diff=lfs merge=lfs\n*.avi  filter=lfs diff=lfs merge=lfs\n*.flv  filter=lfs diff=lfs merge=lfs\n*.mov  filter=lfs diff=lfs merge=lfs\n*.mp4  filter=lfs diff=lfs merge=lfs\n*.mpeg filter=lfs diff=lfs merge=lfs\n*.mpg  filter=lfs diff=lfs merge=lfs\n*.ogv  filter=lfs diff=lfs merge=lfs\n*.wmv  filter=lfs diff=lfs merge=lfs\n\n# 3D Object\n*.blend filter=lfs diff=lfs merge=lfs\n*.dxf   filter=lfs diff=lfs merge=lfs\n*.fbx   filter=lfs diff=lfs merge=lfs\n*.FBX   filter=lfs diff=lfs merge=lfs\n*.lxo   filter=lfs diff=lfs merge=lfs\n*.ma    filter=lfs diff=lfs merge=lfs\n*.max   filter=lfs diff=lfs merge=lfs\n*.mb    filter=lfs diff=lfs merge=lfs\n*.obj   filter=lfs diff=lfs merge=lfs\n*.raw   filter=lfs diff=lfs merge=lfs\n*.spm   filter=lfs diff=lfs merge=lfs\n*.sbk   filter=lfs diff=lfs merge=lfs\n\n# Compiled Dynamic Library\n*.dll    filter=lfs diff=lfs merge=lfs\n*.pdb    filter=lfs diff=lfs merge=lfs\n*.so     filter=lfs diff=lfs merge=lfs\n*.bundle filter=lfs diff=lfs merge=lfs\n\n# Compiled Static Library\n*.a           filter=lfs diff=lfs merge=lfs\n*.la          filter=lfs diff=lfs merge=lfs\n*.lai         filter=lfs diff=lfs merge=lfs\n*.lib         filter=lfs diff=lfs merge=lfs\n*.llblgenproj filter=lfs diff=lfs merge=lfs\n\n# Font\n*.otf filter=lfs diff=lfs merge=lfs\n*.OTF filter=lfs diff=lfs merge=lfs\n*.ttf filter=lfs diff=lfs merge=lfs\n*.TTF filter=lfs diff=lfs merge=lfs\n*.pdf filter=lfs diff=lfs merge=lfs\n\n# CommandLine Utility \n*.exe filter=lfs diff=lfs merge=lfs\n\n# Archives\n*.zip filter=lfs diff=lfs merge=lfs\n*.rar filter=lfs diff=lfs merge=lfs\n*.7z filter=lfs diff=lfs merge=lfs"
  },
  {
    "path": ".gitignore",
    "content": "/[Ll]ibrary/\n/[Tt]emp/\n/[Ll]ogs/\n/[Oo]bj/\n/[Bb]uild/\n/[Bb]uilds/\n/[Uu]ser[Ss]ettings/\n/Assets/StreamingAssets*\n/Assets/UnityEngine*\n/Assets/Temp*\n/Packages/com.*\n/ProjectSettings/Packages*\n/ProjectSettings/boot.config\n/ProjectSettings/SceneTemplateSettings.json\n\n# Visual Studio cache directory\n/.vs/\n/.vscode/\n.vsconfig\n\n# Rider cache directory\n/.idea/\n\n# Autogenerated VS/MD/Consulo solution and project files\nExportedObj/\n.consulo/\n*.csproj\n*.unityproj\n*.sln\n*.suo\n*.tmp\n*.user\n*.userprefs\n*.pidb\n*.booproj\n*.svd\n*.pdb\n*.code*\n\n# Unity3D generated meta files\n*.pidb.meta\n\n# Unity3D generated packages\npackages-lock.json\n\n# Unity3D generated file on crash reports\nsysinfo.txt\n\n# Builds\n*.apk\n*.aab\n*.unitypackage\n\n# OSX files\n.DS_Store\n\n# Generated by analyzers\n/Assets/Default.ruleset\n/Assets/Default.ruleset.meta\n\n# Pipeline files\n*.netrc"
  },
  {
    "path": "Assets/Panel Settings.asset",
    "content": "%YAML 1.1\n%TAG !u! tag:unity3d.com,2011:\n--- !u!114 &11400000\nMonoBehaviour:\n  m_ObjectHideFlags: 0\n  m_CorrespondingSourceObject: {fileID: 0}\n  m_PrefabInstance: {fileID: 0}\n  m_PrefabAsset: {fileID: 0}\n  m_GameObject: {fileID: 0}\n  m_Enabled: 1\n  m_EditorHideFlags: 0\n  m_Script: {fileID: 19101, guid: 0000000000000000e000000000000000, type: 0}\n  m_Name: Panel Settings\n  m_EditorClassIdentifier: \n  themeUss: {fileID: -4733365628477956816, guid: 999af05a3e7a25744b50c66afc0ac938, type: 3}\n  m_TargetTexture: {fileID: 0}\n  m_ScaleMode: 2\n  m_ReferenceSpritePixelsPerUnit: 100\n  m_Scale: 1\n  m_ReferenceDpi: 96\n  m_FallbackDpi: 96\n  m_ReferenceResolution: {x: 1920, y: 1080}\n  m_ScreenMatchMode: 0\n  m_Match: 0\n  m_SortingOrder: 0\n  m_TargetDisplay: 0\n  m_ClearDepthStencil: 1\n  m_ClearColor: 0\n  m_ColorClearValue: {r: 0, g: 0, b: 0, a: 0}\n  m_DynamicAtlasSettings:\n    m_MinAtlasSize: 64\n    m_MaxAtlasSize: 4096\n    m_MaxSubTextureSize: 64\n    m_ActiveFilters: 31\n  m_AtlasBlitShader: {fileID: 9101, guid: 0000000000000000f000000000000000, type: 0}\n  m_RuntimeShader: {fileID: 9100, guid: 0000000000000000f000000000000000, type: 0}\n  m_RuntimeWorldShader: {fileID: 9102, guid: 0000000000000000f000000000000000, type: 0}\n  textSettings: {fileID: 0}\n"
  },
  {
    "path": "Assets/Panel Settings.asset.meta",
    "content": "fileFormatVersion: 2\nguid: f486055d8ec653edc96c3f3c38380c8f\nNativeFormatImporter:\n  externalObjects: {}\n  mainObjectFileID: 11400000\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Assets/UI Theme.tss",
    "content": "@import url(\"unity-theme://default\");\n\n@import url(\"/Packages/com.trackman.figma/Assets/UnityBase.uss\");\n\nVisualElement {}\n"
  },
  {
    "path": "Assets/UI Theme.tss.meta",
    "content": "fileFormatVersion: 2\nguid: 999af05a3e7a25744b50c66afc0ac938\nScriptedImporter:\n  internalIDToNameTable: []\n  externalObjects: {}\n  serializedVersion: 2\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n  script: {fileID: 12388, guid: 0000000000000000e000000000000000, type: 0}\n  disableValidation: 0\n"
  },
  {
    "path": "Assets/UnityBase.uss",
    "content": ":root {\n  --selection-color: #5890DE;\n  --cursor-color: #FFFFFF;\n}\n\n.unity-base-field {\n    flex-direction: row;\n    margin: initial;\n    overflow: hidden;\n    flex-shrink: 0;\n    --unity-sync-text-editor-engine: true;\n}\n\n.unity-base-text-field {\n    white-space: nowrap;\n    --unity-selection-color: var(--selection-color);\n    --unity-cursor-color: var(--cursor-color);\n}\n\n.unity-base-field__input {\n    flex: 1 0 0;\n    overflow: hidden;\n    margin: initial;\n}\n\n.unity-base-text-field__input {\n    padding: initial;\n    border-radius: initial;\n    cursor: initial;\n    -unity-overflow-clip-box: content-box;\n    flex: 1 1 auto;\n    background-color: initial; \n    border-color: initial;\n    border-width: initial;\n    margin: initial;\n    --unity-sync-text-editor-engine: true;\n}\n\n.unity-base-text-field__input:focus,\n.unity-base-text-field__input:hover,\n.unity-base-text-field:focus > .unity-base-text-field__input,\n.unity-base-text-field:hover > .unity-base-text-field__input {\n    border-color: var(--selection-color);\n}\n\n.unity-base-slider,           .unity-base-slider__dragger, .unity-base-slider__tracker {\n    border-width: initial;\n    border-color: initial;\n    background-color: initial; \n}\n.unity-base-slider:focus,     .unity-base-slider__dragger, .unity-base-slider__tracker {\n    border-color: initial;\n}\n\n.unity-base-slider--vertical, .unity-base-slider__dragger, .unity-base-slider__tracker {\n    margin: initial;\n}\n\n.unity-scroller,    .unity-base-slider__dragger, .unity-base-slider__tracker {\n    border-color: initial;\n    background-color: initial; \n}\n\n.unity-scroller--vertical,    .unity-base-slider__dragger, .unity-base-slider__tracker {\n    left: initial;\n    top: initial;\n    margin: initial;\n    border-width: initial;\n    border-color: initial;\n    background-color: initial; \n}\n.unity-scroller--vertical > .unity-scroller__slider {\n    margin: initial;\n    width: initial;\n}"
  },
  {
    "path": "Assets/UnityBase.uss.meta",
    "content": "fileFormatVersion: 2\nguid: d97716672acb0ee45bf6697e5adadcdd\nScriptedImporter:\n  internalIDToNameTable: []\n  externalObjects: {}\n  serializedVersion: 2\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n  script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0}\n  disableValidation: 0\n"
  },
  {
    "path": "Assets.meta",
    "content": "fileFormatVersion: 2\nguid: 7eedcbb7c4cee534cb8f55eaaa55ee65\nfolderAsset: yes\nDefaultImporter:\n  externalObjects: {}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Editor/Assets/icon.png.meta",
    "content": "fileFormatVersion: 2\nguid: c0cc7a4d45c57758c894e807bb1af36b\nTextureImporter:\n  internalIDToNameTable: []\n  externalObjects: {}\n  serializedVersion: 13\n  mipmaps:\n    mipMapMode: 0\n    enableMipMap: 1\n    sRGBTexture: 1\n    linearTexture: 0\n    fadeOut: 0\n    borderMipMap: 0\n    mipMapsPreserveCoverage: 0\n    alphaTestReferenceValue: 0.5\n    mipMapFadeDistanceStart: 1\n    mipMapFadeDistanceEnd: 3\n  bumpmap:\n    convertToNormalMap: 0\n    externalNormalMap: 0\n    heightScale: 0.25\n    normalMapFilter: 0\n    flipGreenChannel: 0\n  isReadable: 0\n  streamingMipmaps: 0\n  streamingMipmapsPriority: 0\n  vTOnly: 0\n  ignoreMipmapLimit: 0\n  grayScaleToAlpha: 0\n  generateCubemap: 6\n  cubemapConvolution: 0\n  seamlessCubemap: 0\n  textureFormat: 1\n  maxTextureSize: 2048\n  textureSettings:\n    serializedVersion: 2\n    filterMode: 1\n    aniso: 1\n    mipBias: 0\n    wrapU: 0\n    wrapV: 0\n    wrapW: 0\n  nPOTScale: 1\n  lightmap: 0\n  compressionQuality: 50\n  spriteMode: 0\n  spriteExtrude: 1\n  spriteMeshType: 1\n  alignment: 0\n  spritePivot: {x: 0.5, y: 0.5}\n  spritePixelsToUnits: 100\n  spriteBorder: {x: 0, y: 0, z: 0, w: 0}\n  spriteGenerateFallbackPhysicsShape: 1\n  alphaUsage: 1\n  alphaIsTransparency: 0\n  spriteTessellationDetail: -1\n  textureType: 0\n  textureShape: 1\n  singleChannelComponent: 0\n  flipbookRows: 1\n  flipbookColumns: 1\n  maxTextureSizeSet: 0\n  compressionQualitySet: 0\n  textureFormatSet: 0\n  ignorePngGamma: 0\n  applyGammaDecoding: 0\n  swizzle: 50462976\n  cookieLightType: 0\n  platformSettings:\n  - serializedVersion: 3\n    buildTarget: DefaultTexturePlatform\n    maxTextureSize: 64\n    resizeAlgorithm: 1\n    textureFormat: -1\n    textureCompression: 1\n    compressionQuality: 50\n    crunchedCompression: 0\n    allowsAlphaSplitting: 0\n    overridden: 0\n    ignorePlatformSupport: 0\n    androidETC2FallbackOverride: 0\n    forceMaximumCompressionQuality_BC6H_BC7: 0\n  - serializedVersion: 3\n    buildTarget: Standalone\n    maxTextureSize: 2048\n    resizeAlgorithm: 0\n    textureFormat: -1\n    textureCompression: 1\n    compressionQuality: 50\n    crunchedCompression: 0\n    allowsAlphaSplitting: 0\n    overridden: 0\n    ignorePlatformSupport: 0\n    androidETC2FallbackOverride: 0\n    forceMaximumCompressionQuality_BC6H_BC7: 0\n  spriteSheet:\n    serializedVersion: 2\n    sprites: []\n    outline: []\n    physicsShape: []\n    bones: []\n    spriteID: \n    internalID: 0\n    vertices: []\n    indices: \n    edges: []\n    weights: []\n    secondaryTextures: []\n    nameFileIdTable: {}\n  mipmapLimitGroupName: \n  pSDRemoveMatte: 0\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Editor/Assets.meta",
    "content": "fileFormatVersion: 2\nguid: 5b1014bd7c33f18afb1f58ad7f928370\nfolderAsset: yes\nDefaultImporter:\n  externalObjects: {}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Editor/Core/Api.cs",
    "content": "using System;\nusing System.Net.Http;\nusing System.Threading;\nusing System.Threading.Tasks;\n\nnamespace Figma\n{\n    using Internals;\n\n    internal abstract class Api : IDisposable\n    {\n        #region Fields\n        protected readonly string fileKey;\n        protected readonly HttpClient httpClient;\n        #endregion\n\n        #region Constructors\n        protected Api(string personalAccessToken, string fileKey)\n        {\n            this.fileKey = fileKey;\n            httpClient = new HttpClient();\n            httpClient.DefaultRequestHeaders.Add(\"X-FIGMA-TOKEN\", personalAccessToken);\n        }\n        #endregion\n\n        #region Methods\n        void IDisposable.Dispose() => httpClient.Dispose();\n        #endregion\n\n        #region Support Methods\n        protected async Task<T> ConvertOnBackgroundAsync<T>(string json, CancellationToken token) where T : class => await Task.Run(() => Task.FromResult(JsonUtility.FromJson<T>(json)), token);\n        protected async Task<T> GetAsync<T>(string get, CancellationToken token = default) where T : class => await ConvertOnBackgroundAsync<T>(await GetJsonAsync(get, token), token);\n        protected async Task<string> GetJsonAsync(string get, CancellationToken token = default) => await HttpGetAsync($\"{Internals.Const.api}/{get}\", token);\n        async Task<string> HttpGetAsync(string url, CancellationToken token = default)\n        {\n            using HttpRequestMessage request = new(HttpMethod.Get, url);\n            HttpResponseMessage response = await httpClient.SendAsync(request, token);\n\n            if (response.IsSuccessStatusCode)\n                return await response.Content.ReadAsStringAsync();\n\n            throw new HttpRequestException($\"{HttpMethod.Get} {url} {response.StatusCode.ToString()}\");\n        }\n        #endregion\n    }\n}"
  },
  {
    "path": "Editor/Core/Api.cs.meta",
    "content": "fileFormatVersion: 2\nguid: 3206e4d9910843d38b90ab361b9a297b\ntimeCreated: 1696830500"
  },
  {
    "path": "Editor/Core/Assets/AssetsInfo.cs",
    "content": "using System;\nusing System.Collections.Concurrent;\nusing System.Collections.Generic;\nusing System.IO;\nusing UnityEditor;\n\nnamespace Figma.Core.Assets\n{\n    using Internals;\n    using static Internals.Const;\n\n    internal class AssetsInfo\n    {\n        #region Fields\n        internal readonly string directory;\n        internal readonly string relativeDirectory;\n        internal readonly CachedAssets cachedAssets;\n        internal readonly ConcurrentBag<string> modifiedContent;\n\n        readonly IReadOnlyList<string> fontDirectories;\n        #endregion\n\n        #region Constructors\n        internal AssetsInfo(string directory, string relativeDirectory, string remapsFileName, IReadOnlyList<string> fontDirectories)\n        {\n            this.directory = directory;\n            this.relativeDirectory = relativeDirectory;\n            this.fontDirectories = fontDirectories;\n\n            modifiedContent = new ConcurrentBag<string>();\n            cachedAssets = new CachedAssets(directory, remapsFileName);\n        }\n        #endregion\n\n        #region Methods\n        internal bool GetAssetPath(string name, string extension, out string path)\n        {\n            switch (extension)\n            {\n                case KnownFormats.otf or KnownFormats.ttf:\n                    path = GetFontPath(name, extension);\n                    return path.NotNullOrEmpty();\n\n                case KnownFormats.asset:\n                    string fontAssetPath = GetFontPath(name, extension);\n                    string fontDirectoryPath = Path.GetDirectoryName(fontAssetPath);\n                    string file = $\"{name} SDF.{extension}\";\n                    path = fontDirectoryPath.NotNullOrEmpty() ? file : PathExtensions.CombinePath(fontDirectoryPath, file);\n                    return fontAssetPath.NotNullOrEmpty();\n\n                case KnownFormats.png or KnownFormats.svg:\n                    string mappedName = cachedAssets[name];\n                    path = PathExtensions.CombinePath(imagesDirectoryName, $\"{mappedName}.{extension}\");\n                    return File.Exists(PathExtensions.CombinePath(directory, path));\n\n                default:\n                    throw new NotSupportedException(extension);\n            }\n        }\n        internal void AddModifiedFiles(params string[] items) => items.ForEach(item => modifiedContent.Add(item));\n        internal string GetAbsolutePath(string path) => PathExtensions.CombinePath(directory, path);\n        #endregion\n\n        #region Support Methods\n        string GetFontPath(string name, string extension)\n        {\n            string file = $\"{name}.{extension}\";\n            string localFontsPath = PathExtensions.CombinePath(fontsDirectoryName, file);\n\n            string relativePath = PathExtensions.CombinePath(relativeDirectory, localFontsPath);\n            if (File.Exists(FileUtil.GetPhysicalPath(relativePath)))\n                return PathExtensions.unixPathSeperator + relativePath;\n\n            foreach (string fontsDirectory in fontDirectories)\n            {\n                string projectFontPath = PathExtensions.CombinePath(fontsDirectory, file);\n                if (File.Exists(FileUtil.GetPhysicalPath(projectFontPath)))\n                    return PathExtensions.unixPathSeperator + projectFontPath;\n            }\n\n            return null;\n        }\n        #endregion\n    }\n}"
  },
  {
    "path": "Editor/Core/Assets/AssetsInfo.cs.meta",
    "content": "fileFormatVersion: 2\nguid: 45f0ac71191d448fb945cd8b96c71dd0\ntimeCreated: 1733916355"
  },
  {
    "path": "Editor/Core/Assets/CachedAssets.cs",
    "content": "using System.Collections.Generic;\nusing System.IO;\nusing System.Threading;\nusing System.Threading.Tasks;\n\nnamespace Figma.Core.Assets\n{\n    using Internals;\n    using static Internals.PathExtensions;\n\n    internal sealed class CachedAssets\n    {\n        #region Fields\n        readonly string targetFilePath;\n        #endregion\n\n        #region Constructor\n        internal CachedAssets(string directory, string name) => targetFilePath = CombinePath(directory, $\"{nameof(CachedAssets)}-{name}.{KnownFormats.json}\");\n        #endregion\n\n        #region Properties\n        internal Dictionary<string, string> Map { get; private set; }\n        #endregion\n\n        #region Operators\n        internal string this[string key]\n        {\n            get => Map.GetValueOrDefault(key, key);\n            set => Map[key] = value;\n        }\n        #endregion\n\n        #region Methods\n        internal async Task LoadAsync(CancellationToken token) => Map = File.Exists(targetFilePath) ? JsonUtility.FromJson<Dictionary<string, string>>(await File.ReadAllTextAsync(targetFilePath, token)) : new Dictionary<string, string>();\n        internal async Task SaveAsync() => await File.WriteAllTextAsync(targetFilePath, JsonUtility.ToJson(Map, prettyPrint: true));\n        #endregion\n    }\n}"
  },
  {
    "path": "Editor/Core/Assets/CachedAssets.cs.meta",
    "content": "fileFormatVersion: 2\nguid: 17a02e0c1cba42429bc345ea5794a854\ntimeCreated: 1733918400"
  },
  {
    "path": "Editor/Core/Assets/GradientWriter.cs",
    "content": "using System;\nusing System.Threading;\nusing System.Threading.Tasks;\nusing System.Xml;\nusing UnityEngine;\n\nnamespace Figma.Core.Assets\n{\n    using Internals;\n    using static Const;\n\n    internal class GradientWriter : IDisposable\n    {\n        #region Fields\n        static readonly XmlWriterSettings xmlWriterSettings = new()\n        {\n            Indent = true,\n            NewLineOnAttributes = true,\n            NewLineChars = Environment.NewLine,\n            IndentChars = indentCharacters,\n            Async = true\n        };\n\n        readonly XmlWriter writer;\n        #endregion\n\n        #region Constructors\n        public GradientWriter(string xmlPath) => writer = XmlWriter.Create(xmlPath, xmlWriterSettings);\n        #endregion\n\n        #region Methods\n        public async Task WriteAsync(GradientPaint gradient, CancellationToken token)\n        {\n            writer.WriteStartElement(KnownFormats.svg);\n            writer.WriteStartElement(\"defs\");\n            switch (gradient.type)\n            {\n                case PaintType.GRADIENT_LINEAR:\n                    writer.WriteStartElement(\"linearGradient\");\n                    writer.WriteAttributeString(\"id\", nameof(gradient));\n                    for (int i = 0; i < Mathf.Max(gradient.gradientHandlePositions.Length, 2); ++i)\n                    {\n                        writer.WriteAttributeString($\"x{i + 1}\", gradient.gradientHandlePositions[i].x.ToString(\"F2\", Culture));\n                        writer.WriteAttributeString($\"y{i + 1}\", gradient.gradientHandlePositions[i].y.ToString(\"F2\", Culture));\n                    }\n\n                    break;\n\n                case PaintType.GRADIENT_RADIAL:\n                case PaintType.GRADIENT_DIAMOND:\n                    writer.WriteStartElement(\"radialGradient\");\n                    writer.WriteAttributeString(\"id\", nameof(gradient));\n                    writer.WriteAttributeString(\"fx\", gradient.gradientHandlePositions[0].x.ToString(\"F2\", Culture));\n                    writer.WriteAttributeString(\"fy\", gradient.gradientHandlePositions[0].y.ToString(\"F2\", Culture));\n                    writer.WriteAttributeString(\"cx\", gradient.gradientHandlePositions[0].x.ToString(\"F2\", Culture));\n                    writer.WriteAttributeString(\"cy\", gradient.gradientHandlePositions[0].y.ToString(\"F2\", Culture));\n\n                    Vector2 a = new ((float)gradient.gradientHandlePositions[1].x, (float)gradient.gradientHandlePositions[1].y);\n                    Vector2 b = new ((float)gradient.gradientHandlePositions[0].x, (float)gradient.gradientHandlePositions[0].y);\n                    float radius = (a - b).magnitude;\n                    writer.WriteAttributeString(\"r\", radius.ToString(\"F2\", Culture));\n                    break;\n\n                default:\n                    throw new NotSupportedException();\n            }\n\n            foreach (ColorStop stop in gradient.gradientStops)\n            {\n                writer.WriteStartElement(nameof(stop));\n                writer.WriteAttributeString(\"offset\", stop.position.ToString(\"F2\", Culture));\n                writer.WriteAttributeString(\"style\", $\"stop-color:rgb({(byte)(stop.color.r * 255)},{(byte)(stop.color.g * 255)},{(byte)(stop.color.b * 255)});stop-opacity:{stop.color.a.ToString(\"F2\", Culture)}\");\n                await writer.WriteEndElementAsync();\n            }\n\n            await writer.WriteEndElementAsync();\n            token.ThrowIfCancellationRequested();\n\n            await writer.WriteEndElementAsync();\n            token.ThrowIfCancellationRequested();\n\n            writer.WriteStartElement(\"rect\");\n            writer.WriteAttributeString(\"width\", \"100\");\n            writer.WriteAttributeString(\"height\", \"100\");\n            writer.WriteAttributeString(\"fill\", \"url(#gradient)\");\n\n            if (gradient.opacity < 1.0)\n                writer.WriteAttributeString(\"fill-opacity\", gradient.opacity.ToString(\"F2\", Culture));\n\n            await writer.WriteEndElementAsync();\n            token.ThrowIfCancellationRequested();\n\n            await writer.WriteEndElementAsync();\n            token.ThrowIfCancellationRequested();\n        }\n        public void Dispose() => writer?.Close();\n        #endregion\n    }\n}"
  },
  {
    "path": "Editor/Core/Assets/GradientWriter.cs.meta",
    "content": "fileFormatVersion: 2\nguid: ec2d941c5d164f0b8887c69795bd3767\ntimeCreated: 1734429409"
  },
  {
    "path": "Editor/Core/Assets/ImagesPostprocessor.cs",
    "content": "using Unity.VectorGraphics.Editor;\nusing UnityEditor;\n\n#pragma warning disable S1144 // Called from Unity\n\nnamespace Figma.Core.Assets\n{\n    internal class ImagesPostprocessor : AssetPostprocessor\n    {\n        #region Methods\n        void OnPreprocessAsset()\n        {\n            if (!assetPath.Contains(\"UI/Assets/Images\")) return;\n\n            if (assetImporter is SVGImporter svgImporter)\n#if UNITY_6000_3_OR_NEWER\n                svgImporter.SvgType = SVGType.UISVGImage;\n#else\n                svgImporter.SvgType = SVGType.UIToolkit;\n#endif\n            if (assetImporter is not TextureImporter textureImporter)\n                return;\n\n            textureImporter.npotScale = TextureImporterNPOTScale.None;\n            textureImporter.mipmapEnabled = false;\n\n            TextureImporterPlatformSettings androidOverrides = textureImporter.GetPlatformTextureSettings(\"Android\");\n            androidOverrides.overridden = true;\n            androidOverrides.format = TextureImporterFormat.ETC2_RGBA8Crunched;\n            androidOverrides.compressionQuality = 90;\n            textureImporter.SetPlatformTextureSettings(androidOverrides);\n        }\n        #endregion\n    }\n}"
  },
  {
    "path": "Editor/Core/Assets/ImagesPostprocessor.cs.meta",
    "content": "fileFormatVersion: 2\nguid: 830782a47c09eebd4b66c78e8b91c6a7\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n  defaultReferences: []\n  executionOrder: 0\n  icon: {instanceID: 0}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Editor/Core/Assets.meta",
    "content": "fileFormatVersion: 2\nguid: 569bf8b4580a4bd792f747a7a503034c\ntimeCreated: 1733918411"
  },
  {
    "path": "Editor/Core/JsonUtility.cs",
    "content": "﻿using Newtonsoft.Json;\nusing Newtonsoft.Json.Linq;\nusing System;\nusing System.Buffers;\nusing System.IO;\nusing UnityEngine;\n\nnamespace Figma.Internals\n{\n    public class JsonUtility\n    {\n        class ArrayPool : IArrayPool<char>\n        {\n            #region Methods\n            public char[] Rent(int minimumLength) => ArrayPool<char>.Shared.Rent(minimumLength);\n            public void Return(char[] array) => ArrayPool<char>.Shared.Return(array);\n            #endregion\n        }\n\n        #region Properties\n        static JsonSerializer serializer = new();\n\n        static readonly IArrayPool<char> arrayPool = new ArrayPool();\n        #endregion\n\n        #region Constructors\n#if UNITY_EDITOR\n        [UnityEditor.InitializeOnLoadMethod]\n#endif\n        [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]\n        public static void Initialize()\n        {\n            JsonSerializerSettings settings = new()\n            {\n                NullValueHandling = NullValueHandling.Ignore,\n                MissingMemberHandling = MissingMemberHandling.Ignore,\n                Converters =\n                {\n                    new EffectArrayConverter(),\n                    new PaintArrayConverter(),\n                    new LayoutGridArrayConverter(),\n                    new ExportSettingsArrayConverter(),\n                    new TransitionConverter(),\n                    new BaseNodeArrayConverter(),\n                    new SceneNodeArrayConverter()\n                }\n            };\n            serializer = JsonSerializer.Create(settings);\n        }\n        public static string ToJson<T>(T value, bool prettyPrint)\n        {\n            using StringWriter stringWriter = new();\n            using JsonTextWriter jsonTextWriter = new(stringWriter) { Formatting = prettyPrint ? Formatting.Indented : Formatting.None };\n            serializer.Serialize(jsonTextWriter, value);\n            return stringWriter.ToString();\n        }\n        public static T FromJson<T>(string json, bool useArrayPool = true)\n        {\n            using StringReader stringReader = new(json);\n            using JsonTextReader jsonTextReader = new(stringReader);\n            if (useArrayPool)\n                jsonTextReader.ArrayPool = arrayPool;\n\n            return serializer.Deserialize<T>(jsonTextReader);\n        }\n        #endregion\n    }\n\n    public abstract class ArrayConverter<T, TEnum> : JsonConverter\n    {\n        #region Methods\n        public override bool CanConvert(Type objectType) => objectType == typeof(T[]);\n        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)\n        {\n            JArray array = JArray.Load(reader);\n            T[] result = new T[array.Count];\n\n            for (int i = 0; i < array.Count; ++i)\n                result[i] = ToObject((JObject)array[i], serializer);\n\n            return result;\n        }\n        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)\n        {\n            T[] array = (T[])value;\n            writer.WriteStartArray();\n\n            foreach (T node in array)\n                serializer.Serialize(writer, node);\n\n            writer.WriteEndArray();\n        }\n        protected TEnum GetValue(JObject obj, string name = \"type\") => (TEnum)Enum.Parse(typeof(TEnum), obj[name].Value<string>());\n        protected abstract T ToObject(JObject obj, JsonSerializer serializer);\n        #endregion\n    }\n\n    public class EffectArrayConverter : ArrayConverter<Effect, EffectType>\n    {\n        #region Methods\n        protected override Effect ToObject(JObject obj, JsonSerializer serializer) =>\n            GetValue(obj) switch\n            {\n                EffectType.INNER_SHADOW => obj.ToObject<ShadowEffect>(serializer),\n                EffectType.DROP_SHADOW => obj.ToObject<ShadowEffect>(serializer),\n                EffectType.LAYER_BLUR => obj.ToObject<BlurEffect>(serializer),\n                EffectType.BACKGROUND_BLUR => obj.ToObject<BlurEffect>(serializer),\n                _ => throw new NotSupportedException()\n            };\n        #endregion\n    }\n\n    public class PaintArrayConverter : ArrayConverter<Paint, PaintType>\n    {\n        #region Methods\n        protected override Paint ToObject(JObject obj, JsonSerializer serializer) =>\n            GetValue(obj) switch\n            {\n                PaintType.SOLID => obj.ToObject<SolidPaint>(serializer),\n                PaintType.GRADIENT_LINEAR => obj.ToObject<GradientPaint>(serializer),\n                PaintType.GRADIENT_RADIAL => obj.ToObject<GradientPaint>(serializer),\n                PaintType.GRADIENT_ANGULAR => obj.ToObject<GradientPaint>(serializer),\n                PaintType.GRADIENT_DIAMOND => obj.ToObject<GradientPaint>(serializer),\n                PaintType.IMAGE => obj.ToObject<ImagePaint>(serializer),\n                PaintType.EMOJI => obj.ToObject<ImagePaint>(serializer),\n                _ => throw new NotSupportedException()\n            };\n        #endregion\n    }\n\n    public class LayoutGridArrayConverter : ArrayConverter<LayoutGrid, Pattern>\n    {\n        #region Methods\n        protected override LayoutGrid ToObject(JObject obj, JsonSerializer serializer) =>\n            GetValue(obj, \"pattern\") switch\n            {\n                Pattern.COLUMNS => obj.ToObject<RowsColsLayoutGrid>(serializer),\n                Pattern.ROWS => obj.ToObject<RowsColsLayoutGrid>(serializer),\n                Pattern.GRID => obj.ToObject<GridLayoutGrid>(serializer),\n                _ => throw new NotSupportedException()\n            };\n        #endregion\n    }\n\n    public class ExportSettingsArrayConverter : ArrayConverter<ExportSettings, Format>\n    {\n        #region Methods\n        protected override ExportSettings ToObject(JObject obj, JsonSerializer serializer) =>\n            GetValue(obj, \"format\") switch\n            {\n                Format.JPG => obj.ToObject<ExportSettingsImage>(serializer),\n                Format.PNG => obj.ToObject<ExportSettingsImage>(serializer),\n                Format.SVG => obj.ToObject<ExportSettingsSVG>(serializer),\n                Format.PDF => obj.ToObject<ExportSettingsPDF>(serializer),\n                _ => throw new NotSupportedException()\n            };\n        #endregion\n    }\n\n    public class TransitionConverter : JsonConverter\n    {\n        #region Methods\n        public override bool CanConvert(Type objectType) => objectType == typeof(Transition);\n        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)\n        {\n            JObject obj = JObject.Load(reader);\n            return (TransitionType)Enum.Parse(typeof(TransitionType), obj[\"type\"]!.Value<string>()) switch\n            {\n                TransitionType.DISSOLVE => obj.ToObject<SimpleTransition>(serializer),\n                TransitionType.SMART_ANIMATE => obj.ToObject<SimpleTransition>(serializer),\n                TransitionType.MOVE_IN => obj.ToObject<DirectionalTransition>(serializer),\n                TransitionType.MOVE_OUT => obj.ToObject<DirectionalTransition>(serializer),\n                TransitionType.PUSH => obj.ToObject<DirectionalTransition>(serializer),\n                TransitionType.SLIDE_IN => obj.ToObject<DirectionalTransition>(serializer),\n                TransitionType.SLIDE_OUT => obj.ToObject<DirectionalTransition>(serializer),\n                _ => throw new NotSupportedException()\n            };\n        }\n        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) => throw new NotImplementedException();\n        #endregion\n    }\n\n    public class BaseNodeArrayConverter : ArrayConverter<BaseNode, NodeType>\n    {\n        #region Methods\n        protected override BaseNode ToObject(JObject obj, JsonSerializer serializer) =>\n            GetValue(obj) switch\n            {\n                NodeType.DOCUMENT => obj.ToObject<DocumentNode>(serializer),\n                NodeType.CANVAS => obj.ToObject<CanvasNode>(serializer),\n                _ => throw new NotSupportedException()\n            };\n        #endregion\n    }\n\n    public class SceneNodeArrayConverter : ArrayConverter<SceneNode, NodeType>\n    {\n        #region Methods\n        protected override SceneNode ToObject(JObject obj, JsonSerializer serializer) =>\n            GetValue(obj) switch\n            {\n                NodeType.SLICE => obj.ToObject<SliceNode>(serializer),\n                NodeType.FRAME => obj.ToObject<FrameNode>(serializer),\n                NodeType.GROUP => obj.ToObject<GroupNode>(serializer),\n                NodeType.COMPONENT_SET => obj.ToObject<ComponentSetNode>(serializer),\n                NodeType.COMPONENT => obj.ToObject<ComponentNode>(serializer),\n                NodeType.INSTANCE => obj.ToObject<InstanceNode>(serializer),\n                NodeType.BOOLEAN_OPERATION => obj.ToObject<BooleanOperationNode>(serializer),\n                NodeType.VECTOR => obj.ToObject<VectorNode>(serializer),\n                NodeType.STAR => obj.ToObject<StarNode>(serializer),\n                NodeType.LINE => obj.ToObject<LineNode>(serializer),\n                NodeType.ELLIPSE => obj.ToObject<EllipseNode>(serializer),\n                NodeType.REGULAR_POLYGON => obj.ToObject<RegularPolygonNode>(serializer),\n                NodeType.RECTANGLE => obj.ToObject<RectangleNode>(serializer),\n                NodeType.TEXT => obj.ToObject<TextNode>(serializer),\n                NodeType.SECTION => obj.ToObject<SectionNode>(serializer),\n                _ => throw new NotSupportedException()\n            };\n        #endregion\n    }\n\n    public class FigmaGeneration { }\n}"
  },
  {
    "path": "Editor/Core/JsonUtility.cs.meta",
    "content": "fileFormatVersion: 2\nguid: c03fe5a0d0b4de848ae40e0ab3bfaac6\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n  defaultReferences: []\n  executionOrder: 0\n  icon: {instanceID: 0}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Editor/Core/NodeMetadata.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Reflection;\nusing UnityEditor.UIElements;\nusing UnityEngine;\nusing UnityEngine.UIElements;\n\nnamespace Figma\n{\n    using Attributes;\n    using Internals;\n    using static Internals.PathExtensions;\n\n    internal class NodeMetadata\n    {\n        #region Consts\n        static readonly Dictionary<Type, ElementType> typeMap = new()\n        {\n            // Base elements\n            { typeof(VisualElement), ElementType.VisualElement },\n            { typeof(BindableElement), ElementType.BindableElement },\n\n            // Utilities\n            { typeof(Box), ElementType.Box },\n            { typeof(TextElement), ElementType.TextElement },\n            { typeof(Label), ElementType.Label },\n            { typeof(Image), ElementType.Image },\n            { typeof(IMGUIContainer), ElementType.IMGUIContainer },\n            { typeof(Foldout), ElementType.Foldout },\n\n            // Controls\n            { typeof(Button), ElementType.Button },\n            { typeof(RepeatButton), ElementType.RepeatButton },\n            { typeof(Toggle), ElementType.Toggle },\n            { typeof(Scroller), ElementType.Scroller },\n            { typeof(Slider), ElementType.Slider },\n            { typeof(SliderInt), ElementType.SliderInt },\n            { typeof(MinMaxSlider), ElementType.MinMaxSlider },\n            { typeof(EnumField), ElementType.EnumField },\n            { typeof(MaskField), ElementType.MaskField },\n            { typeof(LayerField), ElementType.LayerField },\n            { typeof(LayerMaskField), ElementType.LayerMaskField },\n            { typeof(TagField), ElementType.TagField },\n            { typeof(ProgressBar), ElementType.ProgressBar },\n\n            // Text input\n            { typeof(TextField), ElementType.TextField },\n            { typeof(IntegerField), ElementType.IntegerField },\n            { typeof(LongField), ElementType.LongField },\n            { typeof(FloatField), ElementType.FloatField },\n            { typeof(DoubleField), ElementType.DoubleField },\n            { typeof(Vector2Field), ElementType.Vector2Field },\n            { typeof(Vector2IntField), ElementType.Vector2IntField },\n            { typeof(Vector3Field), ElementType.Vector3Field },\n            { typeof(Vector3IntField), ElementType.Vector3IntField },\n            { typeof(Vector4Field), ElementType.Vector4Field },\n            { typeof(RectField), ElementType.RectField },\n            { typeof(RectIntField), ElementType.RectIntField },\n            { typeof(BoundsField), ElementType.BoundsField },\n            { typeof(BoundsIntField), ElementType.BoundsIntField },\n\n            // Complex widgets\n            { typeof(PropertyField), ElementType.PropertyField },\n            { typeof(ColorField), ElementType.ColorField },\n            { typeof(CurveField), ElementType.CurveField },\n            { typeof(GradientField), ElementType.GradientField },\n            { typeof(ObjectField), ElementType.ObjectField },\n\n            // Toolbar\n            { typeof(Toolbar), ElementType.Toolbar },\n            { typeof(ToolbarButton), ElementType.ToolbarButton },\n            { typeof(ToolbarToggle), ElementType.ToolbarToggle },\n            { typeof(ToolbarMenu), ElementType.ToolbarMenu },\n            { typeof(ToolbarSearchField), ElementType.ToolbarSearchField },\n            { typeof(ToolbarPopupSearchField), ElementType.ToolbarPopupSearchField },\n            { typeof(ToolbarSpacer), ElementType.ToolbarSpacer },\n\n            // Views and windows\n            { typeof(ListView), ElementType.ListView },\n            { typeof(ScrollView), ElementType.ScrollView },\n            { typeof(PopupWindow), ElementType.PopupWindow }\n        };\n        #endregion\n\n        #region Fields\n        readonly Dictionary<IBaseNodeMixin, RootMetadata> rootMetadata = new();\n        readonly Dictionary<IBaseNodeMixin, QueryMetadata> queryMetadata = new();\n        readonly List<IBaseNodeMixin> search = new(256);\n        #endregion\n\n        #region Properties\n        static BindingFlags FieldsFlags => BindingFlags.NonPublic | BindingFlags.Instance;\n        #endregion\n\n        #region Constructors\n        internal NodeMetadata(DocumentNode documentNode, IEnumerable<Type> elements, bool filter, bool throwExceptions = true, bool silent = false)\n        {\n            void InitializeRootElement(Type elementType)\n            {\n                void InitializeElement(Type type, IBaseNodeMixin rootNode)\n                {\n                    IBaseNodeMixin FindNodeByQuery(QueryAttribute queryRoot, QueryAttribute query, bool throwException) =>\n                        queryRoot != null && !ReferenceEquals(queryRoot, query) && Find(rootNode, queryRoot.Path, throwException, silent) is { } queryRootNode\n                            ? Find(queryRootNode, query.Path, throwException, silent)\n                            : Find(rootNode, query.Path, throwException, silent);\n\n                    QueryAttribute queryRoot = null;\n\n                    foreach (FieldInfo field in type.GetFields(FieldsFlags))\n                    {\n                        Type fieldType = field.FieldType;\n                        QueryAttribute query = field.GetCustomAttribute<QueryAttribute>();\n\n                        if (query is null)\n                            continue;\n\n                        if (query.StartRoot)\n                            queryRoot = query;\n\n                        IBaseNodeMixin node = FindNodeByQuery(queryRoot, query, throwExceptions &&\n                                                                                !query.Nullable &&\n                                                                                query.ReplaceElementPath.NullOrEmpty() &&\n                                                                                query.RebuildElementEvent.NullOrEmpty());\n\n                        if (node != null && !queryMetadata.ContainsKey(node))\n                            queryMetadata.Add(node, new QueryMetadata(fieldType, query));\n                        if (query.EndRoot)\n                            queryRoot = null;\n                        if (node != null && typeof(ISubElement).IsAssignableFrom(fieldType))\n                            InitializeElement(fieldType, node);\n                    }\n                }\n\n                UxmlAttribute uxml = elementType.GetCustomAttribute<UxmlAttribute>();\n                if (uxml is null)\n                    return;\n\n                IBaseNodeMixin elementRoot = Find(documentNode, uxml.Root);\n                IBaseNodeMixin[] elementPreserve = uxml.Preserve.Select(x => Find(documentNode, x)).ToArray();\n\n                rootMetadata.Add(elementRoot, new RootMetadata(filter, uxml, uxml.DownloadImages));\n\n                foreach (IBaseNodeMixin value in elementPreserve.Where(x => !rootMetadata.ContainsKey(x)))\n                    rootMetadata.Add(value, new RootMetadata(filter, uxml, UxmlDownloadImages.Everything));\n\n                InitializeElement(elementType, elementRoot);\n            }\n\n            elements.ForEach(InitializeRootElement);\n        }\n        #endregion\n\n        #region Methods\n        internal bool EnabledInHierarchy(IBaseNodeMixin node) => !rootMetadata.Any(x => x.Value.filter) || GetMetadata(node).root != null;\n        internal bool ShouldDownload(IBaseNodeMixin node, UxmlDownloadImages flag)\n        {\n            BaseNodeMetadata metadata = GetMetadata(node);\n            if (metadata.root is null || !metadata.root.filter)\n                return true;\n\n            bool shouldDownload = metadata.root.downloadImages == UxmlDownloadImages.Everything || metadata.root.downloadImages.HasFlag(flag);\n\n            if (!metadata.root.downloadImages.HasFlag(UxmlDownloadImages.ByElements) || metadata.query is null)\n                return shouldDownload;\n\n            return metadata.query.query.DownloadImage switch\n            {\n                ElementDownloadImage.Download => true,\n                ElementDownloadImage.Ignore => false,\n                _ => shouldDownload\n            };\n        }\n        internal (bool isHash, string templateName) GetTemplate(IBaseNodeMixin node)\n        {\n            string GetFullPath(IBaseNodeMixin x) => x.parent != null ? CombinePath(GetFullPath(x.parent), x.name) : x.name;\n\n            BaseNodeMetadata metadata = GetMetadata(node);\n\n            if (metadata.root is null || !metadata.root.filter || metadata.query is null)\n                return (false, null);\n\n            return !metadata.query.query.Hash ? (false, metadata.query.query.Template) : (true, $\"{metadata.query.fieldType.Name}-{Hash128.Compute(GetFullPath(node))}\");\n        }\n        internal (ElementType, string) GetElementType(IBaseNodeMixin node)\n        {\n            ElementType FieldTypeToElementType(Type type) => typeMap.TryGetValue(type, out ElementType elementType)\n                ? elementType\n                : typeof(VisualElement).IsAssignableFrom(type)\n                    ? ElementType.IElement\n                    : throw new ArgumentOutOfRangeException(type.FullName);\n\n            BaseNodeMetadata metadata = GetMetadata(node);\n            return metadata.root != null && metadata.root.filter && metadata.root.uxml.TypeIdentification == UxmlElementTypeIdentification.ByElementType && metadata.query != null\n                ? (FieldTypeToElementType(metadata.query.fieldType), metadata.query.fieldType!.FullName!.Replace(\"+\", \".\"))\n                : (ElementType.None, null);\n        }\n        #endregion\n\n        #region Support Methods\n        IBaseNodeMixin Find(IBaseNodeMixin value, string path, bool throwException = true, bool silent = false)\n        {\n            IEnumerable<IBaseNodeMixin> Search(IBaseNodeMixin value, string path)\n            {\n                bool StartsWith(string path, IBaseNodeMixin value, int startIndex)\n                {\n                    int endIndex = startIndex + value.name.Length;\n                    return path.BeginsWith(value.name, startIndex) && path.Length >= endIndex && (path.Length == endIndex || path[endIndex].IsSeparator());\n                }\n                int LastIndexOf(IBaseNodeMixin root, IBaseNodeMixin leaf, IBaseNodeMixin value, string path, int startIndex = 0)\n                {\n                    if (value.parent != null && value.parent != root)\n                        startIndex = LastIndexOf(root, leaf, value.parent, path, startIndex);\n\n                    if (startIndex < 0 || !StartsWith(path, value, startIndex))\n                        return -1;\n\n                    int endIndex = startIndex + value.name.Length;\n                    if (path.Length > endIndex && path[endIndex].IsSeparator() && value != leaf)\n                        endIndex++;\n\n                    return endIndex;\n                }\n                void SearchIn(IBaseNodeMixin value, string path, int startIndex = 0)\n                {\n                    static bool IsVisible(IBaseNodeMixin mixin)\n                    {\n                        if (mixin is ISceneNodeMixin { visible: false })\n                            return false;\n\n                        return mixin.parent is null || IsVisible(mixin.parent);\n                    }\n                    static IReadOnlyCollection<BaseNode> GetChildren(IBaseNodeMixin value)\n                    {\n                        List<BaseNode> children = new();\n                        switch (value)\n                        {\n                            case DocumentNode documentNode:\n                                children.AddRange(documentNode.children);\n                                break;\n\n                            case IChildrenMixin childrenMixin:\n                                children.AddRange(childrenMixin.children);\n                                break;\n                        }\n\n                        return children;\n                    }\n                    static bool EqualsTo(IBaseNodeMixin value, string path, int startIndex) => path.EqualsTo(value.name, startIndex);\n\n                    IReadOnlyCollection<BaseNode> children = GetChildren(value);\n\n                    search.AddRange(children.Where(child => IsVisible(child) && child.name.NotNullOrEmpty() && EqualsTo(child, path, startIndex)));\n                    children.Where(child => IsVisible(child) && child.name.NotNullOrEmpty() && StartsWith(path, child, startIndex)).ForEach(child => SearchIn(child, path, startIndex + child.name.Length + 1));\n                }\n                void SearchByFullPath(IBaseNodeMixin value, string path, int startIndex = 0)\n                {\n                    static bool IsVisible(IBaseNodeMixin mixin)\n                    {\n                        if (mixin is ISceneNodeMixin { visible: false })\n                            return false;\n\n                        return mixin.parent is null || IsVisible(mixin.parent);\n                    }\n                    static IReadOnlyCollection<BaseNode> GetChildren(IBaseNodeMixin value)\n                    {\n                        List<BaseNode> children = new();\n                        switch (value)\n                        {\n                            case DocumentNode documentNode:\n                                children.AddRange(documentNode.children);\n                                break;\n\n                            case IChildrenMixin childrenMixin:\n                                children.AddRange(childrenMixin.children);\n                                break;\n                        }\n\n                        return children;\n                    }\n                    IReadOnlyCollection<BaseNode> children = GetChildren(value);\n\n                    bool EqualsToFullPath(IBaseNodeMixin root, IBaseNodeMixin value, string path, int startIndex) => LastIndexOf(root, value, value, path, startIndex) == path.Length;\n                    bool StartsWithFullPath(IBaseNodeMixin root, IBaseNodeMixin value, string path, int startIndex)\n                    {\n                        int endIndex = LastIndexOf(root, value, value, path, startIndex);\n                        return endIndex >= 0 && path.Length > endIndex && path[endIndex].IsSeparator();\n                    }\n\n                    search.AddRange(children.Where(child => IsVisible(child) && child.name.NotNullOrEmpty() && EqualsToFullPath(value, child, path, startIndex)));\n\n                    foreach (IBaseNodeMixin child in children.Where(child => IsVisible(child) && child.name.NotNullOrEmpty() && StartsWithFullPath(value, child, path, startIndex)))\n                        SearchByFullPath(child, path, startIndex + child.name.Length + 1);\n                }\n\n                search.Clear();\n\n                IBaseNodeMixin root = FindRoot(value);\n                if (root != null)\n                {\n                    UxmlAttribute uxml = rootMetadata[root].uxml;\n                    if (path.BeginsWith(uxml.DocumentRoot) || uxml.DocumentPreserve.Any(x => path.BeginsWith(x)))\n                        SearchByFullPath(root.parent.parent, path, UxmlAttribute.prefix.Length + 1);\n                    else\n                        SearchIn(value, path);\n                }\n                else\n                    SearchByFullPath(value, path);\n\n                return search;\n            }\n\n            IBaseNodeMixin result = Search(value, path).FirstOrDefault();\n\n            if (result != null)\n                return result;\n\n            if (throwException)\n                throw new Exception(Internals.Extensions.BuildTargetMessage(\"Cannot find node at\", CombinePath(value.GetFullPath(), path)));\n\n            if (!silent)\n                Debug.LogWarning(Internals.Extensions.BuildTargetMessage(\"Cannot find node at\", CombinePath(value.GetFullPath(), path)));\n\n            return null;\n        }\n        IBaseNodeMixin FindRoot(IBaseNodeMixin value)\n        {\n            try\n            {\n                while (value != null)\n                {\n                    if (rootMetadata.ContainsKey(value))\n                        return value;\n                    value = value.parent;\n                }\n\n                return null;\n            }\n            catch (Exception exception)\n            {\n                Debug.LogWarning(exception);\n                throw;\n            }\n        }\n        BaseNodeMetadata GetMetadata(IBaseNodeMixin value)\n        {\n            IBaseNodeMixin FindRootInChildren(IBaseNodeMixin value)\n            {\n                if (rootMetadata.ContainsKey(value))\n                    return value;\n\n                switch (value)\n                {\n                    case DocumentNode documentNode:\n                        foreach (CanvasNode child in documentNode.children)\n                        {\n                            IBaseNodeMixin node = FindRootInChildren(child);\n                            if (node != null)\n                                return node;\n                        }\n\n                        break;\n\n                    case IChildrenMixin children:\n                        foreach (SceneNode child in children.children)\n                        {\n                            IBaseNodeMixin node = FindRootInChildren(child);\n                            if (node != null)\n                                return node;\n                        }\n\n                        break;\n                }\n\n                return null;\n            }\n\n            IBaseNodeMixin root = FindRoot(value) ?? FindRootInChildren(value);\n            return root != null ? new BaseNodeMetadata(rootMetadata[root], queryMetadata.GetValueOrDefault(value)) : new BaseNodeMetadata(null, null);\n        }\n        #endregion\n    }\n}"
  },
  {
    "path": "Editor/Core/NodeMetadata.cs.meta",
    "content": "fileFormatVersion: 2\nguid: 826eb9624b2845ffafc480902c5ed5d6\ntimeCreated: 1696228041"
  },
  {
    "path": "Editor/Core/NodesRegistry.cs",
    "content": "using System.Collections.Generic;\nusing System.Linq;\n\nnamespace Figma.Core\n{\n    using Internals;\n    using Const = Const;\n\n    internal sealed class NodesRegistry\n    {\n        #region Fields\n        internal List<string> MissingComponents { get; } = new(Const.initialCollectionCapacity);\n        internal List<IBaseNodeMixin> ImageFills { get; } = new(Const.initialCollectionCapacity);\n        internal List<IBaseNodeMixin> Pngs { get; } = new(Const.initialCollectionCapacity);\n        internal List<IBaseNodeMixin> Svgs { get; } = new(Const.initialCollectionCapacity);\n        internal Dictionary<string, GradientPaint> Gradients { get; } = new(Const.initialCollectionCapacity);\n        #endregion\n\n        public NodesRegistry(Data data, NodeMetadata nodeMetadata)\n        {\n            List<IBaseNodeMixin> nodes = data.document.children.SelectMany(canvas => canvas.Flatten(node => node.IsVisible() &&\n                                                                                                            nodeMetadata.EnabledInHierarchy(node) &&\n                                                                                                            node.parent is not BooleanOperationNode)).ToList();\n\n            MissingComponents.AddRange(nodes.OfType<InstanceNode>()\n                                            .Where(instance => data.document.Flatten().Any(node => node.id == instance.componentId))\n                                            .Select(instance => instance.componentId));\n\n            Pngs.AddRange(nodes.Where(node => node is not BooleanOperationNode && node.IsSvgNode() && node.HasImage()));\n            Svgs.AddRange(nodes.Where(node => node.IsSvgNode() && !node.HasImage()));\n            ImageFills.AddRange(nodes.Where(node => node is not BooleanOperationNode && !node.IsSvgNode() && node.HasImage()));\n\n            foreach (GradientPaint gradient in nodes.OfType<IGeometryMixin>()\n                                                    .Where(x => x is not BooleanOperationNode)\n                                                    .SelectMany(x => x.fills.OfType<GradientPaint>()))\n                Gradients.TryAdd(gradient.GetHash(), gradient);\n        }\n    }\n}"
  },
  {
    "path": "Editor/Core/NodesRegistry.cs.meta",
    "content": "fileFormatVersion: 2\nguid: e6f8d15f8d194578ad29c8c0a4a0d2e6\ntimeCreated: 1734424985"
  },
  {
    "path": "Editor/Core/RichText/RichTextBuilder.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing UnityEngine;\n\nnamespace Figma.Core.RichText\n{\n    using Internals;\n\n    internal sealed class TextBuilder\n    {\n        #region Container\n        enum TagType\n        {\n            Bold,\n            Italic,\n            Underline,\n            Strikethrough,\n            Color,\n            FontSize,\n            FontWeight,\n            Indent,\n        }\n\n        class Tag\n        {\n            #region Fields\n            readonly string tag;\n            readonly StringBuilder stringBuilder;\n\n            string value;\n            bool active;\n            #endregion\n\n            #region Constructor\n            public Tag(StringBuilder stringBuilder, string tag)\n            {\n                this.tag = tag;\n                this.stringBuilder = stringBuilder;\n            }\n            #endregion\n\n            #region Methods\n            public void Set(bool required)\n            {\n                if (!active && required)\n                    Open();\n                if (active && !required)\n                    Close();\n\n                if (!required)\n                    value = null;\n            }\n            public void Set(bool required, string value)\n            {\n                switch (required)\n                {\n                    case true when active && this.value != value && this.value != null:\n                        Close();\n                        this.value = value;\n                        Open();\n                        return;\n\n                    case false when !active:\n                        return;\n\n                    default:\n                        this.value = value;\n                        Set(required);\n                        break;\n                }\n            }\n\n            void Open()\n            {\n                stringBuilder.Append(string.IsNullOrEmpty(value) ? $\"<{tag}>\" : $\"<{tag}={value}>\");\n                active = true;\n            }\n            void Close()\n            {\n                stringBuilder.Append($\"</{tag}>\");\n                active = false;\n            }\n            #endregion\n        }\n        #endregion\n\n        #region Fields\n        readonly StringBuilder stringBuilder = new();\n        readonly Dictionary<TagType, Tag> tags;\n        readonly TextNode node;\n        #endregion\n\n        #region Constructors\n        public TextBuilder(TextNode textNode)\n        {\n            tags = new Dictionary<TagType, Tag>\n            {\n                { TagType.Bold, new Tag(stringBuilder, \"b\") },\n                { TagType.Italic, new Tag(stringBuilder, \"i\") },\n                { TagType.Underline, new Tag(stringBuilder, \"u\") },\n                { TagType.Strikethrough, new Tag(stringBuilder, \"strikethrough\") },\n                { TagType.Color, new Tag(stringBuilder, \"color\") },\n                { TagType.FontSize, new Tag(stringBuilder, \"size\") },\n                { TagType.FontWeight, new Tag(stringBuilder, \"font-weight\") },\n                { TagType.Indent, new Tag(stringBuilder, \"indent\") },\n            };\n            node = textNode;\n        }\n        #endregion\n\n        #region Methods\n        public string Build()\n        {\n            string text = node.characters;\n            TextNode.Style baseStyle = node.style;\n            int[] charOverrides = node.characterStyleOverrides;\n            Dictionary<int, TextNode.Style> styleTable = node.styleOverrideTable;\n            LineType[] lineTypes = node.lineTypes;\n            int[] lineIndents = node.lineIndentations ?? Array.Empty<int>();\n\n            int textLength = text.Length;\n            if (charOverrides.Length < textLength)\n            {\n                Array.Resize(ref charOverrides, textLength);\n                for (int j = node.characterStyleOverrides.Length; j < textLength; j++)\n                    charOverrides[j] = 0;\n            }\n\n            int listLineIndex = 0;\n\n            for (int i = 0, line = 0; i < textLength; i++)\n            {\n                char ch = text[i];\n\n                if (i == 0 || text[i - 1] == '\\n')\n                {\n                    if (i == 0)\n                        line = 0;\n                    else\n                        line++;\n\n                    int indentLevel = line < lineIndents.Length ? lineIndents[line] : 0;\n                    LineType lineType = line < lineTypes.Length ? lineTypes[line] : LineType.NONE;\n\n                    for (int s = 0; s < indentLevel; s++)\n                        tags[TagType.Indent].Set(lineType != LineType.NONE, (10 * indentLevel).ToString());\n\n                    if (lineType is LineType.UNORDERED or LineType.NONE) listLineIndex = 0;\n                    if (lineType is LineType.ORDERED) stringBuilder.Append($\"{++listLineIndex}. \");\n                    else if (lineType is LineType.UNORDERED) stringBuilder.Append(\"• \");\n                }\n\n                if (ch == '\\n')\n                {\n                    foreach (Tag tag in tags.Values)\n                        tag.Set(false);\n\n                    stringBuilder.Append('\\n');\n                    continue;\n                }\n\n                int styleOverrideId = i < charOverrides.Length ? charOverrides[i] : 0;\n                TextNode.Style charStyle = styleTable.GetValueOrDefault(styleOverrideId, baseStyle);\n\n                if (charStyle != null)\n                {\n                    tags[TagType.Bold].Set(charStyle.fontWeight >= (int)FontWeight.Bold);\n                    tags[TagType.Italic].Set(charStyle.italic);\n                    tags[TagType.Underline].Set(charStyle.textDecoration is TextDecoration.UNDERLINE);\n                    tags[TagType.Strikethrough].Set(charStyle.textDecoration is TextDecoration.STRIKETHROUGH);\n\n                    SolidPaint paint = charStyle.fills?.OfType<SolidPaint>().FirstOrDefault();\n                    tags[TagType.Color].Set(paint != null, paint == null ? null : \"#\" + ColorUtility.ToHtmlStringRGBA((Color)paint.color));\n                    tags[TagType.FontWeight].Set(charStyle.fontWeight != (double)FontWeight.Regular, charStyle.fontWeight.ToString());\n                    tags[TagType.FontSize].Set(true, charStyle.fontSize.ToString());\n                }\n\n                stringBuilder.Append(ch);\n            }\n\n            foreach (Tag tag in tags.Values)\n                tag.Set(false);\n\n            return stringBuilder.ToString();\n        }\n        #endregion\n    }\n}"
  },
  {
    "path": "Editor/Core/RichText/RichTextBuilder.cs.meta",
    "content": "fileFormatVersion: 2\nguid: 63d2b4dce6024b989f78957756f9f22f\ntimeCreated: 1743683644"
  },
  {
    "path": "Editor/Core/RichText.meta",
    "content": "fileFormatVersion: 2\nguid: b4773ce3ee3d4f9f817a7dca740b3afc\ntimeCreated: 1743683652"
  },
  {
    "path": "Editor/Core/RootNodes.cs",
    "content": "using System.Collections.Generic;\nusing System.Linq;\nusing UnityEngine;\n\nnamespace Figma.Core\n{\n    using Internals;\n    using Attributes;\n\n    internal class RootNodes\n    {\n        const int initialCollectionCapacity = 32;\n\n        #region Fields\n        readonly List<CanvasNode> canvases = new(initialCollectionCapacity);\n        readonly List<ComponentSetNode> componentSets = new(initialCollectionCapacity);\n        readonly List<FrameNode> frames = new(initialCollectionCapacity);\n        readonly List<(DefaultShapeNode, string hash)> elements = new(initialCollectionCapacity);\n        #endregion\n\n        #region Properties\n        public IReadOnlyList<CanvasNode> Canvases => canvases;\n        public IReadOnlyList<ComponentSetNode> ComponentSets => componentSets;\n        public IReadOnlyList<FrameNode> Frames => frames;\n        public IReadOnlyList<(DefaultShapeNode node, string hash)> Elements => elements;\n        #endregion\n\n        #region Constructors\n        public RootNodes(Data data, NodeMetadata nodeMetadata)\n        {\n            foreach (IBaseNodeMixin node in data.document.Flatten())\n            {\n                switch (node)\n                {\n                    case CanvasNode canvasNode:\n                        canvases.Add(canvasNode);\n                        break;\n\n                    case ComponentSetNode componentSetNode:\n                        componentSets.Add(componentSetNode);\n                        break;\n\n                    case FrameNode frameNode when node.parent is CanvasNode:\n                        frames.Add(frameNode);\n                        break;\n\n                    case DefaultShapeNode defaultShapeNode when nodeMetadata.GetTemplate(defaultShapeNode) is (var isHash, { } template) && template.NotNullOrEmpty():\n                        if (!isHash && elements.Any(x => x.hash == template))\n                        {\n                            Debug.LogWarning($\"Duplicate hash was found: {template}. This might happen when [{nameof(QueryAttribute)}] is inherited in multiple classes. \" +\n                                             \"This could also happen when you have a template with the same name. In order to fix that in that case, please use \\\"Hash = true\\\" parameter.\");\n                            break;\n                        }\n\n                        elements.Add((defaultShapeNode, template));\n                        break;\n                }\n            }\n        }\n        #endregion\n    }\n}"
  },
  {
    "path": "Editor/Core/RootNodes.cs.meta",
    "content": "fileFormatVersion: 2\nguid: 54369dcc94564417aee21cea7980006a\ntimeCreated: 1733321003"
  },
  {
    "path": "Editor/Core/StylesPreprocessor.cs",
    "content": "using System.Collections.Generic;\nusing System.Linq;\nusing System.Text.RegularExpressions;\n\nnamespace Figma.Core\n{\n    using Assets;\n    using Uss;\n    using Internals;\n    using static Const;\n\n    internal class StylesPreprocessor\n    {\n        static readonly Regex multipleDashesRegex = new(\"-{2,}\", RegexOptions.Compiled);\n        static readonly Regex invalidCharsRegex = new(\"[^a-zA-Z0-9]\", RegexOptions.Compiled);\n\n        #region Fields\n        readonly List<(StyleSlot slot, UssStyle style)> styles = new(initialCollectionCapacity);\n        readonly List<ComponentNode> components = new(initialCollectionCapacity);\n        readonly List<Dictionary<string, Style>> componentsStyles = new(initialCollectionCapacity);\n        readonly Dictionary<IBaseNodeMixin, UssStyle> componentStyleMap = new(initialCollectionCapacity);\n        readonly Dictionary<IBaseNodeMixin, UssStyle> nodeStyleMap = new(initialCollectionCapacity);\n\n        readonly AssetsInfo assetsInfo;\n        readonly Data data;\n        #endregion\n\n        #region Properties\n        internal IReadOnlyList<(StyleSlot slot, UssStyle style)> Styles => styles;\n        internal IReadOnlyDictionary<IBaseNodeMixin, UssStyle> NodeStyleMap => nodeStyleMap;\n        #endregion\n\n        internal StylesPreprocessor(Data data, AssetsInfo assetsInfo)\n        {\n            this.data = data;\n            this.assetsInfo = assetsInfo;\n\n            AddStyles(data.document, data.styles);\n            AddRichText(data.document);\n\n            for (int i = 0; i < components.Count; i++)\n            {\n                AddStyles(components[i], componentsStyles[i]);\n                AddRichText(components[i]);\n            }\n\n            InheritStyles(data.document);\n            AddTransitionStyles();\n        }\n\n        #region Methods\n        void AddStyles(IBaseNodeMixin root, Dictionary<string, Style> styles)\n        {\n            string GetClassName(string name, string prefix = \"n\")\n            {\n                const char separator = '-';\n\n                if (name.Length > 64)\n                    name = name[..64];\n\n                name = invalidCharsRegex.Replace(name, separator.ToString());\n                name = multipleDashesRegex.Replace(name, separator.ToString());\n                name = name.Trim(separator);\n\n                if (string.IsNullOrEmpty(name) || name.All(c => c == separator))\n                    name = prefix;\n\n                if (char.IsDigit(name[0]))\n                    name = $\"{prefix}-{name}\";\n\n                return name;\n            }\n\n            HashSet<IBaseNodeMixin> insideComponents = new();\n\n            foreach (IBaseNodeMixin node in root.Flatten())\n            {\n                bool insideComponent = node is ComponentNode || insideComponents.Contains(node.parent);\n\n                if (!insideComponent)\n                {\n                    UssStyle style = new(GetClassName(node.name), assetsInfo, (BaseNode)node);\n                    if (node is ComponentSetNode)\n                    {\n                        // Removing annoying borders for ComponentSetNode\n                        style.Attributes.Clear();\n                        style.Attributes.Add(\"overflow\", \"hidden\");\n                    }\n\n                    nodeStyleMap[node] = style;\n                }\n                else\n                {\n                    insideComponents.Add(node);\n                    componentStyleMap[node] = new UssStyle(GetClassName(node.name), assetsInfo, (BaseNode)node);\n                }\n\n                if (node is not IBlendMixin { styles: not null } blend)\n                    continue;\n\n                foreach ((string styleType, string styleId) in blend.styles)\n                {\n                    bool text = node.type == NodeType.TEXT;\n                    string slot = styleType;\n\n                    if (slot[^1] == 's') // Sometimes named 'fill' and sometimes 'fills'. We treat them equally.\n                        slot = slot[..^1];\n\n                    if (!this.styles.Any(x => x.slot.Text == text && x.slot.Slot == slot && x.slot.key == styles[styleId].key))\n                    {\n                        StyleSlot styleDescriptor = new StyleSlot(text, slot, styles[styleId]);\n                        string className = GetClassName(styleDescriptor.name, \"s\");\n                        UssStyle ussStyle = new UssStyle(className, assetsInfo, (BaseNode)node, styleDescriptor);\n                        this.styles.Add((styleDescriptor, ussStyle));\n                    }\n                }\n            }\n        }\n        void AddRichText(IBaseNodeMixin node)\n        {\n            foreach (TextNode textNode in node.Flatten().OfType<TextNode>().Where(x => x.lineTypes is { Length: > 1 } && x.lineTypes.Any(lineType => lineType is LineType.ORDERED or LineType.UNORDERED) ||\n                                                                                       (x.styleOverrideTable != null && x.styleOverrideTable.Any())))\n                textNode.characters = new RichText.TextBuilder(textNode).Build();\n        }\n        void AddTransitionStyles()\n        {\n            ComponentNode GetTransitionNode(ComponentSetNode componentSet, ComponentNode defaultComponent, TriggerType triggerType)\n            {\n                Action action = defaultComponent.interactions\n                                                .Where(interaction => interaction.trigger.type == triggerType)\n                                                .Select(interaction => interaction.actions.FirstOrDefault())\n                                                .FirstOrDefault(action => action?.destinationId != null);\n\n                string destinationId = action?.destinationId;\n\n                ComponentNode node = (ComponentNode)componentSet.children.FirstOrDefault(component => component is ComponentNode && component.id == destinationId);\n                return node;\n            }\n            UssStyle GetStyle(Dictionary<IBaseNodeMixin, UssStyle> componentStyleMap, ComponentSetNode componentSet, ComponentNode defaultComponent, TriggerType triggerType)\n            {\n                UssStyle style = null;\n                ComponentNode node = GetTransitionNode(componentSet, defaultComponent, triggerType);\n\n                if (node != null)\n                    componentStyleMap.TryGetValue(node, out style);\n\n                return style;\n            }\n\n            UssStyle visualElement = new(nameof(UnityEngine.UIElements.VisualElement));\n\n            foreach ((IBaseNodeMixin key, UssStyle componentSetStyle) in nodeStyleMap)\n            {\n                if (key is not ComponentSetNode componentSet)\n                    continue;\n\n                ComponentNode defaultComponent = null;\n                Action action = null;\n\n                foreach (SceneNode sceneNode in componentSet.children)\n                {\n                    if (sceneNode is not ComponentNode componentNode)\n                        continue;\n\n                    Interactions activeInteraction = componentNode.interactions.FirstOrDefault(interaction => interaction.trigger.type == TriggerType.ON_HOVER ||\n                                                                                                              interaction.trigger.type == TriggerType.ON_CLICK);\n                    if (activeInteraction == null)\n                        continue;\n\n                    action = activeInteraction.actions.FirstOrDefault(x => x.destinationId != null);\n\n                    if (action == null)\n                        continue;\n\n                    defaultComponent = componentNode;\n                    UssStyle subStyle = new(componentSetStyle.Name) { Target = visualElement };\n\n                    if (action.transition != null)\n                    {\n                        subStyle.transitionDuration = action.transition.duration * 1000;\n                        subStyle.transitionEasing = (EasingFunction)action.transition.easing.type;\n                    }\n\n                    componentSetStyle.SubStyles.Add(subStyle);\n                    break;\n                }\n\n                if (defaultComponent == null)\n                    continue;\n\n                componentStyleMap.TryGetValue(defaultComponent, out UssStyle idleStyle);\n\n                UssStyle hoverStyle = GetStyle(componentStyleMap, componentSet, defaultComponent, TriggerType.ON_HOVER);\n                UssStyle clickStyle = GetStyle(componentStyleMap, componentSet, defaultComponent, TriggerType.ON_CLICK);\n\n                if (idleStyle == null)\n                    continue;\n\n                void InjectSubStyles(ComponentNode node, IReadOnlyList<UssStyle> defaultStyles, PseudoClass pseudoClass)\n                {\n                    IReadOnlyList<UssStyle> styles = GetStyles(node);\n                    for (int i = 0; i < styles.Count; i++)\n                    {\n                        UssStyle style = styles[i];\n                        UssStyle defaultStyle = defaultStyles[i];\n                        componentSetStyle.SubStyles.Add(new UssStyle(componentSetStyle.Name) { PseudoClass = pseudoClass, Target = defaultStyle }.CopyFrom(style));\n                    }\n                }\n\n                if (action.transition is { type: TransitionType.SMART_ANIMATE })\n                {\n                    ComponentNode hoverNode = GetTransitionNode(componentSet, defaultComponent, TriggerType.ON_HOVER);\n                    ComponentNode clickNode = GetTransitionNode(componentSet, defaultComponent, TriggerType.ON_CLICK);\n                    IReadOnlyList<UssStyle> defaultStyles = GetStyles(defaultComponent);\n\n                    if (hoverNode != null) InjectSubStyles(hoverNode, defaultStyles, PseudoClass.Hover);\n                    if (clickNode != null) InjectSubStyles(clickNode, defaultStyles, PseudoClass.Active);\n                }\n\n                if (action.transition is { type: TransitionType.DISSOLVE })\n                    componentSetStyle.SubStyles.AddRange(UssStyle.MakeTransitionStyles(componentSetStyle, idleStyle, hoverStyle, clickStyle));\n            }\n        }\n        internal void AddMissingComponent(ComponentNode component, Dictionary<string, Style> componentStyles)\n        {\n            components.Add(component);\n            componentsStyles.Add(componentStyles);\n        }\n        #endregion\n\n        #region Support Methods\n        internal IReadOnlyList<UssStyle> GetStyles(IBaseNodeMixin root) =>\n            root.Flatten(node => node.IsVisible() && node is not ComponentSetNode)\n                .Select(node => componentStyleMap.TryGetValue(node, out UssStyle style) || nodeStyleMap.TryGetValue(node, out style) ? style : null)\n                .Where(style => style is not null)\n                .ToList();\n\n        void InheritStyles(IBaseNodeMixin root)\n        {\n            List<UssStyle> styles = new();\n\n            foreach (IBaseNodeMixin node in root.Flatten(x => x.parent is not BooleanOperationNode))\n            {\n                UssStyle style = GetStyle(node);\n                if (node is IBlendMixin { styles: not null } blend)\n                {\n                    foreach (KeyValuePair<string, string> keyValue in blend.styles)\n                    {\n                        bool text = node.type == NodeType.TEXT;\n                        string styleType = keyValue.Key;\n                        if (styleType[^1] == 's')\n                            styleType = styleType[..^1];\n\n                        string styleId = keyValue.Value;\n                        string key = null;\n\n                        if (data.styles.TryGetValue(styleId, out Style documentStyle))\n                            key = documentStyle.key;\n\n                        foreach (Dictionary<string, Style> componentStyle in componentsStyles)\n                            if (componentStyle.TryGetValue(styleId, out Style value))\n                                key = value.key;\n\n                        int index;\n                        if (key.NotNullOrEmpty() && (index = this.styles.FindIndex(x => x.slot.Text == text && x.slot.Slot == styleType && x.slot.key == key)) >= 0)\n                            styles.Add(this.styles[index].style);\n                    }\n                }\n\n                if (styles.Count > 0) style.Inherit(styles);\n                styles.Clear();\n            }\n        }\n        internal string GetClassList(IBaseNodeMixin node)\n        {\n            UssStyle style = GetStyle(node);\n\n            if (style == null)\n                return string.Empty;\n\n            List<string> styles = new List<string>();\n            if (node is IBlendMixin { styles: not null } blend)\n            {\n                foreach (KeyValuePair<string, string> keyValue in blend.styles)\n                {\n                    bool text = node.type == NodeType.TEXT;\n                    string styleType = keyValue.Key;\n\n                    if (styleType[^1] == 's')\n                        styleType = styleType[..^1];\n\n                    string styleId = keyValue.Value;\n                    string key = null;\n\n                    if (data.styles.TryGetValue(styleId, out Style documentStyle))\n                        key = documentStyle.key;\n\n                    foreach (Dictionary<string, Style> componentStyle in componentsStyles)\n                        if (componentStyle.TryGetValue(styleId, out Style value))\n                            key = value.key;\n\n                    int index;\n\n                    if (key.NotNullOrEmpty() && (index = this.styles.FindIndex(x => x.slot.Text == text && x.slot.Slot == styleType && x.slot.key == key)) >= 0)\n                        styles.Add(this.styles[index].style.Name);\n                }\n            }\n\n            if (node.IsSvgNode())\n                styles.Clear();\n\n            List<string> classes = new List<string>();\n            classes.Add(UssStyle.overrideClass.Name);\n            if (style.Attributes.Count > 0)\n                classes.Add(style.Name);\n            classes.AddRange(styles);\n            if (node.IsRootNode())\n                classes.Add(UssStyle.viewportClass.Name);\n\n            return string.Join(\" \", classes);\n        }\n        UssStyle GetStyle(IBaseNodeMixin node) => componentStyleMap.TryGetValue(node, out UssStyle style) || nodeStyleMap.TryGetValue(node, out style) ? style : null;\n        #endregion\n    }\n}"
  },
  {
    "path": "Editor/Core/StylesPreprocessor.cs.meta",
    "content": "fileFormatVersion: 2\nguid: 756f15f2e8e54ce6b41e0fdaa5aa7fe8\ntimeCreated: 1742559104"
  },
  {
    "path": "Editor/Core/Uss/BaseUssStyle.cs",
    "content": "using Figma.Internals;\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\n\nnamespace Figma.Core.Uss\n{\n    internal abstract class BaseUssStyle\n    {\n        #region Fields\n        readonly List<BaseUssStyle> inherited = new();\n        #endregion\n\n        #region Properties\n        public string Name { get; set; }\n        public PseudoClass PseudoClass { get; set; }\n        public BaseUssStyle Target { get; set; }\n\n        public List<BaseUssStyle> SubStyles { get; } = new();\n        public Dictionary<string, string> Attributes { get; } = new();\n        public bool HasAttributes => Attributes.Count > 0;\n        #endregion\n\n        #region Constructors\n        protected BaseUssStyle(string name) => Name = name;\n        #endregion\n\n        #region Methods\n        public string BuildName()\n        {\n            string result = $\".{Name}\";\n\n            if (PseudoClass is not PseudoClass.None)\n                result += $\":{PseudoClass.ToString().ToLower()}\";\n\n            if (Target == null)\n                return result;\n\n            result += \" > \";\n\n            if (Target.Name is not (nameof(UnityEngine.UIElements.VisualElement) or\n                                    nameof(UnityEngine.UIElements.Button)))\n                result += \".\";\n\n            result += Target.Name;\n\n            return result;\n        }\n\n        public bool DoesInherit(BaseUssStyle style) => inherited.Contains(style);\n        public void Inherit(IReadOnlyCollection<BaseUssStyle> styles)\n        {\n            inherited.AddRange(styles);\n            styles.SelectMany(style => style.Attributes.Where(keyValue => Attributes.TryGetValue(keyValue.Key, out string value) && value == keyValue.Value))\n                  .Select(x => x.Key)\n                  .ForEach(key => Attributes.Remove(key));\n        }\n        #endregion\n\n        #region Support Methods\n        protected string Get(string name) => Attributes[name];\n        protected string GetDefault(string name, string defaultValue) => Attributes.ContainsKey(name) ? Attributes[name] : defaultValue;\n        protected string Get1(string name, string group, int index)\n        {\n            if (Attributes.TryGetValue(group, out string groupValue))\n            {\n                Length4Property length4 = groupValue;\n                return length4[index];\n            }\n\n            if (Attributes.TryGetValue(name, out string nameValue))\n                return nameValue;\n\n            throw new NotSupportedException();\n        }\n        protected string Get4(string name, params string[] names)\n        {\n            if (Attributes.TryGetValue(name, out string value))\n                return value;\n\n            LengthProperty[] properties = new LengthProperty[4];\n\n            for (int i = 0; i < 4; ++i)\n                properties[i] = Attributes.TryGetValue(names[i], out string indexedValue) ? indexedValue : new LengthProperty(Unit.Pixel);\n\n            return new Length4Property(properties);\n        }\n        protected void Set(string name, string value) => Attributes[name] = value;\n        protected void Set1(string name, string value, params string[] names)\n        {\n            Attributes[name] = value;\n\n            for (int i = 0; i < 4; ++i)\n                Attributes.Remove(names[i]);\n        }\n        protected void Set4(string name, string value, string group, int index)\n        {\n            if (Attributes.TryGetValue(group, out string item))\n            {\n                Length4Property length4 = item;\n                length4[index] = value;\n                Set(group, length4);\n            }\n            else\n                Set(name, value);\n        }\n        protected static string Url(string url) => $\"url('{url}')\";\n        protected static string Resource(string resource) => $\"resource('{resource}')\";\n        #endregion\n    }\n}"
  },
  {
    "path": "Editor/Core/Uss/BaseUssStyle.cs.meta",
    "content": "fileFormatVersion: 2\nguid: 6a8ef63978cd415290c6cbe844cd7f9b\ntimeCreated: 1732193154"
  },
  {
    "path": "Editor/Core/Uss/Properties/AssetProperty.cs",
    "content": "using System;\n\nnamespace Figma.Core.Uss\n{\n    using Internals;\n\n    /// <summary>\n    /// Represents an asset in a Resources folder or represents an asset specified by a path, it can be expressed as either a relative path or an absolute path.\n    /// </summary>\n    internal struct AssetProperty\n    {\n        #region Fields\n        readonly string url;\n        readonly string resource;\n        readonly Unit unit;\n        #endregion\n\n        #region Constructors\n        AssetProperty(Unit unit)\n        {\n            url = null;\n            resource = null;\n            this.unit = unit;\n        }\n        AssetProperty(string value)\n        {\n            url = null;\n            resource = null;\n            unit = default;\n\n            if (value.StartsWith(nameof(url))) url = value;\n            else if (value.StartsWith(nameof(resource))) resource = value;\n            else throw new NotSupportedException();\n        }\n        #endregion\n\n        #region Operators\n        public static implicit operator AssetProperty(Unit value) => new(value);\n        public static implicit operator AssetProperty(string value) => Enum.TryParse(value, true, out Unit unit) ? new AssetProperty(unit) : new AssetProperty(value);\n        public static implicit operator string(AssetProperty value)\n        {\n            if (value.url.NotNullOrEmpty()) return value.url;\n            if (value.resource.NotNullOrEmpty()) return value.resource;\n\n            return value.unit switch\n            {\n                Unit.None => \"none\",\n                Unit.Initial => \"initial\",\n                _ => throw new ArgumentException(nameof(value))\n            };\n        }\n        #endregion\n    }\n}"
  },
  {
    "path": "Editor/Core/Uss/Properties/AssetProperty.cs.meta",
    "content": "fileFormatVersion: 2\nguid: b1d01eee68b444c88e74da4382b53373\ntimeCreated: 1727946243"
  },
  {
    "path": "Editor/Core/Uss/Properties/ColorProperty.cs",
    "content": "using System;\n\nnamespace Figma.Core.Uss\n{\n    using Internals;\n    using Const = Const;\n\n    /// <summary>\n    /// Represents a color. You can define a color with a #hexadecimal code, the rgb() or rgba() function, or a color keyword (for example, blue or transparent).\n    /// </summary>\n    internal readonly struct ColorProperty\n    {\n        #region Fields\n        readonly string rgba;\n        readonly string rgb;\n        readonly string hex;\n        readonly string name;\n        #endregion\n\n        #region Constructors\n        internal ColorProperty(RGBA color, Double? opacity = 1, float alphaMult = 1)\n        {\n            rgba = $\"rgba({(byte)(color.r * 255.0f)},{(byte)(color.g * 255.0f)},{(byte)(color.b * 255.0f)},{(color.a * (opacity ?? alphaMult)).ToString(\"F2\", Const.Culture).Replace(\".00\", string.Empty)})\";\n            rgb = null;\n            hex = null;\n            name = null;\n        }\n        ColorProperty(string value)\n        {\n            rgba = null;\n            rgb = null;\n            hex = null;\n            name = null;\n\n            if (value.StartsWith(nameof(rgba))) rgba = value;\n            else if (value.StartsWith(nameof(rgb))) rgb = value;\n            else if (value.StartsWith('#')) hex = value;\n            else name = value;\n        }\n        #endregion\n\n        #region Operators\n        public static implicit operator ColorProperty(Unit _) => new();\n        public static implicit operator ColorProperty(RGBA value) => new(value);\n        public static implicit operator ColorProperty(string value) => new(value);\n        public static implicit operator string(ColorProperty value)\n        {\n            if (value.rgba.NotNullOrEmpty()) return value.rgba;\n            if (value.rgb.NotNullOrEmpty()) return value.rgb;\n            if (value.hex.NotNullOrEmpty()) return value.hex;\n            if (value.name.NotNullOrEmpty()) return value.name;\n\n            return \"initial\";\n        }\n        public override string ToString() => this;\n        #endregion\n    }\n}"
  },
  {
    "path": "Editor/Core/Uss/Properties/ColorProperty.cs.meta",
    "content": "fileFormatVersion: 2\nguid: 11225bd9ebe040f49fab329a81bc3f88\ntimeCreated: 1727946232"
  },
  {
    "path": "Editor/Core/Uss/Properties/CursorProperty.cs",
    "content": "namespace Figma.Core.Uss\n{\n    internal struct CursorProperty\n    {\n        #region Operators\n        public static implicit operator CursorProperty(string _) => new();\n        public static implicit operator string(CursorProperty _) => null;\n        #endregion\n    }\n}"
  },
  {
    "path": "Editor/Core/Uss/Properties/CursorProperty.cs.meta",
    "content": "fileFormatVersion: 2\nguid: 688b2f12fd56420486ab60eaa3f520c7\ntimeCreated: 1727946311"
  },
  {
    "path": "Editor/Core/Uss/Properties/DurationProperty.cs",
    "content": "using System;\n\nnamespace Figma.Core.Uss\n{\n    /// <summary>\n    /// Represents a duration value from Figma API.\n    /// </summary>\n    internal readonly struct DurationProperty\n    {\n        #region Fields\n        readonly double value;\n        readonly TimeUnit unit;\n        #endregion\n\n        #region Constructors\n        internal DurationProperty(TimeUnit unit)\n        {\n            value = 0;\n            this.unit = unit;\n        }\n        internal DurationProperty(double value, TimeUnit unit)\n        {\n            this.value = value;\n            this.unit = unit;\n        }\n        #endregion\n\n        #region Operators\n        public static implicit operator DurationProperty(TimeUnit value) => new(0, value);\n        public static implicit operator DurationProperty(double? value) => new(value!.Value, TimeUnit.Millisecond);\n        public static implicit operator DurationProperty(double value) => new(value, TimeUnit.Millisecond);\n        public static implicit operator DurationProperty(string value)\n        {\n            if (Enum.TryParse(value, true, out TimeUnit unit)) return new DurationProperty(unit);\n            if (value.ToLower(Const.Culture).Contains(\"ms\")) return new DurationProperty(double.Parse(value.ToLower(Const.Culture).Replace(\"ms\", string.Empty), Const.Culture), TimeUnit.Millisecond);\n            if (value.ToLower(Const.Culture).Contains(\"s\")) return new DurationProperty(double.Parse(value.ToLower(Const.Culture).Replace(\"s\", string.Empty), Const.Culture), TimeUnit.Second);\n\n            return default;\n        }\n        public static implicit operator string(DurationProperty value)\n        {\n            return value.unit switch\n            {\n                TimeUnit.Default => $\"0ms\",\n                TimeUnit.Millisecond => $\"{value.value.ToString(\"F2\", Const.Culture).Replace(\".00\", string.Empty)}ms\",\n                TimeUnit.Second => $\"{value.value.ToString(\"F2\", Const.Culture).Replace(\".00\", string.Empty)}s\",\n                _ => throw new ArgumentException(nameof(value))\n            };\n        }\n\n        public static DurationProperty operator +(DurationProperty a) => a;\n        public static DurationProperty operator -(DurationProperty a) => new(-a.value, a.unit);\n        public static DurationProperty operator +(DurationProperty a, double b) => new(a.value + b, a.unit);\n        public static DurationProperty operator -(DurationProperty a, double b) => new(a.value - b, a.unit);\n\n        public static bool operator ==(DurationProperty a, TimeUnit b) => a.unit == b;\n        public static bool operator !=(DurationProperty a, TimeUnit b) => a.unit != b;\n\n        public override bool Equals(object obj) => obj is DurationProperty property && value == property.value && unit == property.unit;\n        public override int GetHashCode() => HashCode.Combine(value, unit);\n        public override string ToString() => this;\n        #endregion\n    }\n}"
  },
  {
    "path": "Editor/Core/Uss/Properties/DurationProperty.cs.meta",
    "content": "fileFormatVersion: 2\nguid: f01b58e2e2c44e75b07f54061e244f90\ntimeCreated: 1732271697"
  },
  {
    "path": "Editor/Core/Uss/Properties/EnumProperty.cs",
    "content": "using System;\nusing System.Text.RegularExpressions;\n\nnamespace Figma.Core.Uss\n{\n#pragma warning disable CS0660, CS0661\n    internal struct EnumProperty<T> where T : struct, Enum\n#pragma warning restore CS0660, CS0661\n    {\n        // ReSharper disable StaticMemberInGenericType\n        static readonly Regex enumParserRegexString = new(\"(?<name>([a-z]+\\\\-?))\", RegexOptions.Compiled);\n        static readonly Regex enumParserRegexValue = new(\"(?<name>([A-Z][a-z]+)?)\", RegexOptions.Compiled);\n        // ReSharper restore StaticMemberInGenericType\n\n        #region Fields\n        T value;\n        readonly Unit unit;\n        #endregion\n\n        #region Constructors\n        EnumProperty(T value)\n        {\n            this.value = value;\n            unit = Unit.None;\n        }\n        EnumProperty(Unit unit)\n        {\n            value = default;\n            this.unit = unit;\n        }\n        #endregion\n\n        #region Operators\n        public static implicit operator EnumProperty<T>(Unit unit) => new(unit);\n        public static implicit operator EnumProperty<T>(T value) => new(value);\n        public static implicit operator EnumProperty<T>(string value) => Enum.TryParse(enumParserRegexString.Replace(value, \"${name}\").Replace(\"-\", string.Empty), true, out T result) ? new EnumProperty<T>(result) : default;\n        public static implicit operator string(EnumProperty<T> value) => value.unit == Unit.None ? enumParserRegexValue.Replace(value.value.ToString(), \"${name}-\").ToLower().TrimEnd('-') : \"initial\";\n\n        public static bool operator ==(EnumProperty<T> a, T b) => a.value.Equals(b);\n        public static bool operator !=(EnumProperty<T> a, T b) => !a.value.Equals(b);\n\n        public override string ToString() => this;\n        #endregion\n    }\n}"
  },
  {
    "path": "Editor/Core/Uss/Properties/EnumProperty.cs.meta",
    "content": "fileFormatVersion: 2\nguid: 911a38bb38a64ff98a53324b53da101b\ntimeCreated: 1727946257"
  },
  {
    "path": "Editor/Core/Uss/Properties/FlexProperty.cs",
    "content": "namespace Figma.Core.Uss\n{\n    internal struct FlexProperty\n    {\n        #region Operators\n        public static implicit operator FlexProperty(string _) => new();\n        public static implicit operator string(FlexProperty _) => null;\n        #endregion\n    }\n}"
  },
  {
    "path": "Editor/Core/Uss/Properties/FlexProperty.cs.meta",
    "content": "fileFormatVersion: 2\nguid: c6e36b8acd8548b0add9ddf1a37509b0\ntimeCreated: 1727946301"
  },
  {
    "path": "Editor/Core/Uss/Properties/IntegerProperty.cs",
    "content": "namespace Figma.Core.Uss\n{\n    /// <summary>\n    /// Represents a whole number.\n    /// </summary>\n    internal struct IntegerProperty\n    {\n        #region Fields\n        readonly int value;\n        #endregion\n\n        #region Constructors\n        IntegerProperty(int value) => this.value = value;\n        #endregion\n\n        #region Operators\n        public static implicit operator IntegerProperty(int? value) => new(value!.Value);\n        public static implicit operator IntegerProperty(int value) => new(value);\n        public static implicit operator IntegerProperty(string value) => new(int.Parse(value));\n        public static implicit operator string(IntegerProperty value) => value.value.ToString(Const.Culture);\n\n        public static IntegerProperty operator +(IntegerProperty a) => a;\n        public static IntegerProperty operator -(IntegerProperty a) => new(-a.value);\n        public static IntegerProperty operator +(IntegerProperty a, int b) => new(a.value + b);\n        public static IntegerProperty operator -(IntegerProperty a, int b) => new(a.value - b);\n        #endregion\n    }\n}"
  },
  {
    "path": "Editor/Core/Uss/Properties/IntegerProperty.cs.meta",
    "content": "fileFormatVersion: 2\nguid: a466380f063f4ec98d082d2ec7cd1f20\ntimeCreated: 1727946212"
  },
  {
    "path": "Editor/Core/Uss/Properties/LayoutDouble4.cs",
    "content": "using System;\n\nnamespace Figma.Core.Uss\n{\n    struct LayoutDouble4\n    {\n        #region Fields\n        public double top;\n        public double right;\n        public double bottom;\n        public double left;\n        #endregion\n\n        #region Methods\n        public LayoutDouble4(double top, double right, double bottom, double left)\n        {\n            this.top = top;\n            this.right = right;\n            this.bottom = bottom;\n            this.left = left;\n        }\n        public LayoutDouble4(double value)\n        {\n            top = value;\n            right = value;\n            bottom = value;\n            left = value;\n        }\n\n        public LayoutDouble4 OnlyPositiveValues() => new(top > UssStyle.tolerance ? top : 0.0, right > UssStyle.tolerance ? right : 0.0, bottom > UssStyle.tolerance ? bottom : 0.0, left > UssStyle.tolerance ? left : 0.0);\n        public LayoutDouble4 OnlyNegativeValues() => new(top < UssStyle.tolerance ? top : 0.0, right < UssStyle.tolerance ? right : 0.0, bottom < UssStyle.tolerance ? bottom : 0.0, left < UssStyle.tolerance ? left : 0.0);\n\n        public Length4Property ToLength4Property() => new[] { top, right, bottom, left };\n        public bool Any() => Math.Abs(top) > UssStyle.tolerance || Math.Abs(right) > UssStyle.tolerance || Math.Abs(bottom) > UssStyle.tolerance || Math.Abs(left) > UssStyle.tolerance;\n\n        public static LayoutDouble4 operator +(LayoutDouble4 a, LayoutDouble4 b) => new(a.top + b.top, a.right + b.right, a.bottom + b.bottom, a.left + b.left);\n        public static LayoutDouble4 operator -(LayoutDouble4 a, LayoutDouble4 b) => new(a.top - b.top, a.right - b.right, a.bottom - b.bottom, a.left - b.left);\n        public static LayoutDouble4 operator -(LayoutDouble4 a) => new(-a.top, -a.right, -a.bottom, -a.left);\n        public static LayoutDouble4 operator *(LayoutDouble4 a, double k) => new(a.top * k, a.right * k, a.bottom * k, a.left * k);\n        #endregion\n    }\n}"
  },
  {
    "path": "Editor/Core/Uss/Properties/LayoutDouble4.cs.meta",
    "content": "fileFormatVersion: 2\nguid: 3c58a19efd2f4860a12c1aca6d120164\ntimeCreated: 1743523469"
  },
  {
    "path": "Editor/Core/Uss/Properties/Length2Property.cs",
    "content": "using System;\nusing System.Linq;\n\nnamespace Figma.Core.Uss\n{\n    internal readonly struct Length2Property\n    {\n        #region Fields\n        readonly Unit unit;\n        readonly LengthProperty[] properties;\n        #endregion\n\n        #region Properties\n        internal LengthProperty this[int index] { get => properties[index]; set => properties[index] = value; }\n        #endregion\n\n        #region Constructors\n        internal Length2Property(Unit unit)\n        {\n            this.unit = unit;\n            properties = new LengthProperty[] { new(unit), new(unit) };\n        }\n        internal Length2Property(LengthProperty[] properties)\n        {\n            unit = Unit.None;\n            this.properties = properties;\n        }\n        #endregion\n\n        #region Operators\n        public static implicit operator Length2Property(Unit unit) => new(unit);\n        public static implicit operator Length2Property(Double? value) => new(new LengthProperty[] { value!.Value });\n        public static implicit operator Length2Property(Double value) => new(new LengthProperty[] { value });\n        public static implicit operator Length2Property(Double[] values)\n        {\n            LengthProperty[] properties = new LengthProperty[values.Length];\n            for (int i = 0; i < values.Length; i++) properties[i] = values[i];\n            return new Length2Property(properties);\n        }\n        public static implicit operator Length2Property(string value)\n        {\n            string[] values = value.Split(\" \", StringSplitOptions.RemoveEmptyEntries);\n            LengthProperty[] properties = new LengthProperty[values.Length];\n            for (int i = 0; i < values.Length; i++) properties[i] = values[i];\n            return new Length2Property(properties);\n        }\n        public static implicit operator string(Length2Property value)\n        {\n            if (value is { unit: Unit.None, properties: not null })\n            {\n                string[] values = new string[value.properties.Length];\n                for (int i = 0; i < values.Length; i++) values[i] = value.properties[i];\n                return string.Join(\" \", values);\n            }\n\n            return new LengthProperty(value.unit);\n        }\n\n        public static Length2Property operator +(Length2Property a) => a;\n        public static Length2Property operator -(Length2Property a) => new(a.properties.Select(x => -x).ToArray());\n        public static Length2Property operator +(Length2Property a, Double b) => new(a.properties.Select(x => x + b).ToArray());\n        public static Length2Property operator -(Length2Property a, Double b) => new(a.properties.Select(x => x - b).ToArray());\n        #endregion\n    }\n}"
  },
  {
    "path": "Editor/Core/Uss/Properties/Length2Property.cs.meta",
    "content": "fileFormatVersion: 2\nguid: ac3787c7e7634fc9983559df65387add\ntimeCreated: 1738319788"
  },
  {
    "path": "Editor/Core/Uss/Properties/Length4Property.cs",
    "content": "using System;\nusing System.Linq;\n\nnamespace Figma.Core.Uss\n{\n    internal readonly struct Length4Property\n    {\n        #region Fields\n        readonly Unit unit;\n        readonly LengthProperty[] properties;\n        #endregion\n\n        #region Properties\n        internal LengthProperty this[int index] { get => properties[index]; set => properties[index] = value; }\n        #endregion\n\n        #region Constructors\n        internal Length4Property(Unit unit)\n        {\n            this.unit = unit;\n            properties = new LengthProperty[] { new(unit), new(unit), new(unit), new(unit) };\n        }\n        internal Length4Property(LengthProperty[] properties)\n        {\n            unit = Unit.None;\n            this.properties = properties;\n        }\n        #endregion\n\n        #region Operators\n        public static implicit operator Length4Property(Unit unit) => new(unit);\n        public static implicit operator Length4Property(double? value) => new(new LengthProperty[] { value!.Value });\n        public static implicit operator Length4Property(double value) => new(new LengthProperty[] { value });\n        public static implicit operator Length4Property(double[] values) => new(values.Select(x => (LengthProperty)x).ToArray());\n        public static implicit operator Length4Property(string value) => new(value.Split(\" \", StringSplitOptions.RemoveEmptyEntries).Select(x => (LengthProperty)x).ToArray());\n        public static implicit operator string(Length4Property value) => value is { unit: Unit.None, properties: not null } ? string.Join(\" \", value.properties.Select(p => (string)p)) : new LengthProperty(value.unit);\n\n        public static Length4Property operator +(Length4Property a) => a;\n        public static Length4Property operator -(Length4Property a) => new(a.properties.Select(x => -x).ToArray());\n        public static Length4Property operator +(Length4Property a, double b) => new(a.properties.Select(x => x + b).ToArray());\n        public static Length4Property operator -(Length4Property a, double b) => new(a.properties.Select(x => x - b).ToArray());\n        #endregion\n    }\n}"
  },
  {
    "path": "Editor/Core/Uss/Properties/Length4Property.cs.meta",
    "content": "fileFormatVersion: 2\nguid: 22ebc27065094f06894a5301834db528\ntimeCreated: 1727946288"
  },
  {
    "path": "Editor/Core/Uss/Properties/LengthProperty.cs",
    "content": "using System;\n\nnamespace Figma.Core.Uss\n{\n    /// <summary>\n    /// Represents a distance value.\n    /// </summary>\n    internal readonly struct LengthProperty\n    {\n        #region Fields\n        readonly double value;\n        readonly Unit unit;\n        #endregion\n\n        #region Constructors\n        internal LengthProperty(Unit unit)\n        {\n            value = 0;\n            this.unit = unit;\n        }\n        internal LengthProperty(double value, Unit unit)\n        {\n            this.value = value;\n            this.unit = unit;\n        }\n        #endregion\n\n        #region Operators\n        public static implicit operator LengthProperty(Unit value) => new(0, value);\n        public static implicit operator LengthProperty(double? value) => new(value!.Value, Unit.Pixel);\n        public static implicit operator LengthProperty(double value) => new(value, Unit.Pixel);\n        public static implicit operator LengthProperty(string value)\n        {\n            if (Enum.TryParse(value, true, out Unit unit)) return new LengthProperty(unit);\n            if (value.Contains(\"px\")) return new LengthProperty(double.Parse(value.ToLower().Replace(\"px\", string.Empty), Const.Culture), Unit.Pixel);\n            if (value.Contains(\"deg\")) return new LengthProperty(double.Parse(value.ToLower().Replace(\"deg\", string.Empty), Const.Culture), Unit.Degrees);\n            if (value.Contains('%')) return new LengthProperty(double.Parse(value.Replace(\"%\", string.Empty), Const.Culture), Unit.Percent);\n\n            return default;\n        }\n        public static implicit operator string(LengthProperty value)\n        {\n            return value.unit switch\n            {\n                Unit.Pixel => value.value == 0.0 ? \"0\" : $\"{(int)Math.Round(value.value)}px\",\n                Unit.Degrees => value.value == 0.0 ? \"0\" : $\"{value.value.ToString(\"F2\", Const.Culture).Replace(\".00\", string.Empty)}deg\",\n                Unit.Percent => value.value == 0.0 ? \"0\" : $\"{value.value.ToString(\"F2\", Const.Culture).Replace(\".00\", string.Empty)}%\",\n                Unit.Auto => \"auto\",\n                Unit.None => \"none\",\n                Unit.Initial => \"initial\",\n                Unit.Default => \"0\",\n                _ => throw new ArgumentException(nameof(value))\n            };\n        }\n\n        public static LengthProperty operator +(LengthProperty a) => a;\n        public static LengthProperty operator -(LengthProperty a) => new(-a.value, a.unit);\n        public static LengthProperty operator +(LengthProperty a, double b) => new(a.value + b, a.unit);\n        public static LengthProperty operator -(LengthProperty a, double b) => new(a.value - b, a.unit);\n\n        public static bool operator ==(LengthProperty a, Unit b) => a.unit == b;\n        public static bool operator !=(LengthProperty a, Unit b) => a.unit != b;\n\n        public override bool Equals(object obj) => obj is LengthProperty property && value == property.value && unit == property.unit;\n        public override int GetHashCode() => HashCode.Combine(value, unit);\n        public override string ToString() => this;\n        #endregion\n    }\n}"
  },
  {
    "path": "Editor/Core/Uss/Properties/LengthProperty.cs.meta",
    "content": "fileFormatVersion: 2\nguid: 50407f2db68e4ab3ac1c3fe00a5b98f7\ntimeCreated: 1727946151"
  },
  {
    "path": "Editor/Core/Uss/Properties/NumberProperty.cs",
    "content": "namespace Figma.Core.Uss\n{\n    /// <summary>\n    /// Represents either an integer or a number with a fractional component.\n    /// </summary>\n    internal struct NumberProperty\n    {\n        #region Fields\n        readonly double value;\n        #endregion\n\n        #region Constructors\n        NumberProperty(double value) => this.value = value;\n        #endregion\n\n        #region Operators\n        public static implicit operator NumberProperty(double? value) => new(value!.Value);\n        public static implicit operator NumberProperty(double value) => new(value);\n        public static implicit operator NumberProperty(string value) => new(double.Parse(value, Const.Culture));\n        public static implicit operator string(NumberProperty value) => value.value.ToString(\"F2\", Const.Culture).Replace(\".00\", string.Empty);\n\n        public static NumberProperty operator +(NumberProperty a) => a;\n        public static NumberProperty operator -(NumberProperty a) => new(-a.value);\n        public static NumberProperty operator +(NumberProperty a, double b) => new(a.value + b);\n        public static NumberProperty operator -(NumberProperty a, double b) => new(a.value - b);\n        #endregion\n    }\n}"
  },
  {
    "path": "Editor/Core/Uss/Properties/NumberProperty.cs.meta",
    "content": "fileFormatVersion: 2\nguid: 674b330b5aea49318570f61fabe5e9cb\ntimeCreated: 1727946179"
  },
  {
    "path": "Editor/Core/Uss/Properties/ShadowProperty.cs",
    "content": "using System.Text.RegularExpressions;\n\nnamespace Figma.Core.Uss\n{\n    internal struct ShadowProperty\n    {\n        static readonly Regex regex = new(@\"(?<offsetHorizontal>\\d+[px]*)\\s+(?<offsetVertical>\\d+[px]*)\\s+(?<blurRadius>\\d+[px]*)\\s+(?<color>(rgba\\([\\d,\\.\\s]+\\))|#\\w{2,8}|[^#][\\w-]+)\");\n\n        #region Fields\n        readonly LengthProperty offsetHorizontal;\n        readonly LengthProperty offsetVertical;\n        readonly LengthProperty blurRadius;\n        readonly ColorProperty color;\n        #endregion\n\n        #region Constructors\n        internal ShadowProperty(LengthProperty offsetHorizontal, LengthProperty offsetVertical, LengthProperty blurRadius, ColorProperty color)\n        {\n            this.offsetHorizontal = offsetHorizontal;\n            this.offsetVertical = offsetVertical;\n            this.blurRadius = blurRadius;\n            this.color = color;\n        }\n        ShadowProperty(string value)\n        {\n            Match match = regex.Match(value);\n            offsetHorizontal = match.Groups[nameof(offsetHorizontal)].Value;\n            offsetVertical = match.Groups[nameof(offsetVertical)].Value;\n            blurRadius = match.Groups[nameof(blurRadius)].Value;\n            color = match.Groups[nameof(color)].Value;\n        }\n        #endregion\n\n        #region Operators\n        public static implicit operator ShadowProperty(string value) => new(value);\n        public static implicit operator string(ShadowProperty value) => $\"{value.offsetHorizontal} {value.offsetVertical} {value.blurRadius} {value.color}\";\n        #endregion\n    }\n}"
  },
  {
    "path": "Editor/Core/Uss/Properties/ShadowProperty.cs.meta",
    "content": "fileFormatVersion: 2\nguid: c3584d21c614453fa132bc171f4420eb\ntimeCreated: 1727946275"
  },
  {
    "path": "Editor/Core/Uss/Properties.meta",
    "content": "fileFormatVersion: 2\nguid: 049f021dc7f44bb389f9f132ed103b7c\ntimeCreated: 1727946137"
  },
  {
    "path": "Editor/Core/Uss/StyleSlot.cs",
    "content": "namespace Figma.Core.Uss\n{\n    using Internals;\n\n    internal class StyleSlot : Style\n    {\n        #region Fields\n        public bool Text { get; }\n        public string Slot { get; }\n        #endregion\n\n        #region Constructors\n        public StyleSlot(bool text, string slot, Style style)\n        {\n            Text = text;\n            Slot = slot;\n            styleType = style.styleType;\n            key = style.key;\n            name = style.name;\n            description = style.description;\n        }\n        #endregion\n\n        #region Methods\n        public override string ToString() => $\"text={Text} slot={Slot} styleType={styleType} key={key} name={name} description={description}\";\n        #endregion\n    }\n}"
  },
  {
    "path": "Editor/Core/Uss/StyleSlot.cs.meta",
    "content": "fileFormatVersion: 2\nguid: 7cb6785b010e457392b9a283f2cd0e62\ntimeCreated: 1727945310"
  },
  {
    "path": "Editor/Core/Uss/UssStyle.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing UnityEngine;\nusing UnityEngine.UIElements;\n\nnamespace Figma.Core.Uss\n{\n    using Assets;\n    using Internals;\n\n    internal class UssStyle : BaseUssStyle\n    {\n        /// Problem with figma 2 Unity is that, Unity’s box-sizing property is always border-box, while figma's is a content-box with changing borders. See the MDN documentation https://developer.mozilla.org/en-US/docs/Web/CSS/box-sizing\n\n        #region Const\n        public const double tolerance = 0.01;\n\n        internal static readonly UssStyle overrideClass = new(\"unity-base-override\")\n        {\n            alignItems = Align.Center,\n            backgroundColor = Unit.Initial,\n            borderWidth = Unit.Initial,\n            justifyContent = JustifyContent.Center,\n            margin = Unit.Initial,\n            overflow = Unit.Initial,\n            padding = Unit.Initial,\n            unityBackgroundPositionX = BackgroundPositionKeyword.Center,\n            unityBackgroundPositionY = BackgroundPositionKeyword.Center,\n            unityBackgroundRepeat = Repeat.NoRepeat,\n            unityFontDefinition = Unit.Initial,\n        };\n\n        internal static readonly UssStyle viewportClass = new(\"unity-viewport\") { position = Position.Absolute, width = \"100%\", height = \"100%\" };\n        #endregion\n\n        #region Fields\n        readonly AssetsInfo assetsInfo;\n        #endregion\n\n        #region Properties\n        // Box model\n        // Dimensions\n        LengthProperty width { get => Get(nameof(width)); set => Set(nameof(width), value); }\n        LengthProperty height { get => Get(nameof(height)); set => Set(nameof(height), value); }\n        LengthProperty minWidth { get => Get(\"min-width\"); set => Set(\"min-width\", value); }\n        LengthProperty minHeight { get => Get(\"min-height\"); set => Set(\"min-height\", value); }\n        LengthProperty maxWidth { get => Get(\"max-width\"); set => Set(\"max-width\", value); }\n        LengthProperty maxHeight { get => Get(\"max-height\"); set => Set(\"max-height\", value); }\n        // Margins\n        LengthProperty marginLeft { get => Get1(\"margin-left\", nameof(margin), 0); set => Set4(\"margin-left\", value, nameof(margin), 0); }\n        LengthProperty marginTop { get => Get1(\"margin-top\", nameof(margin), 1); set => Set4(\"margin-top\", value, nameof(margin), 1); }\n        LengthProperty marginRight { get => Get1(\"margin-right\", nameof(margin), 2); set => Set4(\"margin-right\", value, nameof(margin), 2); }\n        LengthProperty marginBottom { get => Get1(\"margin-bottom\", nameof(margin), 3); set => Set4(\"margin-bottom\", value, nameof(margin), 3); }\n        Length4Property margin { get => Get4(nameof(margin), \"margin-left\", \"margin-top\", \"margin-right\", \"margin-bottom\"); set => Set1(nameof(margin), value, \"margin-left\", \"margin-top\", \"margin-right\", \"margin-bottom\"); }\n        // Borders\n        LengthProperty borderLeftWidth { get => Get1(\"border-left-width\", \"border-width\", 0); set => Set4(\"border-left-width\", value, \"border-width\", 0); }\n        LengthProperty borderTopWidth { get => Get1(\"border-top-width\", \"border-width\", 1); set => Set4(\"border-top-width\", value, \"border-width\", 1); }\n        LengthProperty borderRightWidth { get => Get1(\"border-right-width\", \"border-width\", 2); set => Set4(\"border-right-width\", value, \"border-width\", 2); }\n        LengthProperty borderBottomWidth { get => Get1(\"border-bottom-width\", \"border-width\", 3); set => Set4(\"border-bottom-width\", value, \"border-width\", 3); }\n        Length4Property borderWidth { get => Get4(\"border-width\", \"border-left-width\", \"border-top-width\", \"border-right-width\", \"border-bottom-width\"); set => Set1(\"border-width\", value, \"border-left-width\", \"border-top-width\", \"border-right-width\", \"border-bottom-width\"); }\n        // Padding\n        LengthProperty paddingLeft { get => Get1(\"padding-left\", nameof(padding), 0); set => Set4(\"padding-left\", value, nameof(padding), 0); }\n        LengthProperty paddingTop { get => Get1(\"padding-top\", nameof(padding), 1); set => Set4(\"padding-top\", value, nameof(padding), 1); }\n        LengthProperty paddingRight { get => Get1(\"padding-right\", nameof(padding), 2); set => Set4(\"padding-right\", value, nameof(padding), 2); }\n        LengthProperty paddingBottom { get => Get1(\"padding-bottom\", nameof(padding), 3); set => Set4(\"padding-bottom\", value, nameof(padding), 3); }\n        Length4Property padding { get => Get4(nameof(padding), \"padding-left\", \"padding-top\", \"padding-right\", \"padding-bottom\"); set => Set1(nameof(padding), value, \"padding-left\", \"padding-top\", \"padding-right\", \"padding-bottom\"); }\n\n        // Flex\n        // Items\n        NumberProperty flexGrow { get => Get(\"flex-grow\"); set => Set(\"flex-grow\", value); }\n        NumberProperty flexShrink { get => Get(\"flex-shrink\"); set => Set(\"flex-shrink\", value); }\n        LengthProperty flexBasis { get => Get(\"flex-basis\"); set => Set(\"flex-basis\", value); }\n        FlexProperty flex { get => Get(nameof(flex)); set => Set(nameof(flex), value); }\n        EnumProperty<Align> alignSelf { get => Get(\"align-self\"); set => Set(\"align-self\", value); }\n        NumberProperty itemSpacing { get => Get(\"--item-spacing\"); set => Set(\"--item-spacing\", value); }\n        // Containers\n        EnumProperty<FlexDirection> flexDirection { get => Get(\"flex-direction\"); set => Set(\"flex-direction\", value); }\n        EnumProperty<FlexWrap> flexWrap { get => Get(\"flex-wrap\"); set => Set(\"flex-wrap\", value); }\n        EnumProperty<Align> alignContent { get => Get(\"align-content\"); set => Set(\"align-content\", value); }\n        EnumProperty<Align> alignItems { get => Get(\"align-items\"); set => Set(\"align-items\", value); }\n        EnumProperty<JustifyContent> justifyContent { get => Get(\"justify-content\"); set => Set(\"justify-content\", value); }\n        // Positioning\n        EnumProperty<Position> position { get => Get(nameof(position)); set => Set(nameof(position), value); }\n        LengthProperty left { get => Get(nameof(left)); set => Set(nameof(left), value); }\n        LengthProperty top { get => Get(nameof(top)); set => Set(nameof(top), value); }\n        LengthProperty right { get => Get(nameof(right)); set => Set(nameof(right), value); }\n        LengthProperty bottom { get => Get(nameof(bottom)); set => Set(nameof(bottom), value); }\n        LengthProperty rotate { get => Get(nameof(rotate)); set => Set(nameof(rotate), value); }\n        Length2Property translate { get => GetDefault(nameof(translate), \"0 0\"); set => Set(nameof(translate), value); }\n\n        // Drawing\n        // Background\n        ColorProperty backgroundColor { get => Get(\"background-color\"); set => Set(\"background-color\", value); }\n        AssetProperty backgroundImage { get => Get(\"background-image\"); set => Set(\"background-image\", value); }\n        EnumProperty<BackgroundPositionKeyword> unityBackgroundPositionX { get => Get(\"background-position-x\"); set => Set(\"background-position-x\", value); }\n        EnumProperty<BackgroundPositionKeyword> unityBackgroundPositionY { get => Get(\"background-position-y\"); set => Set(\"background-position-y\", value); }\n        EnumProperty<Repeat> unityBackgroundRepeat { get => Get(\"background-repeat\"); set => Set(\"background-repeat\", value); }\n        EnumProperty<BackgroundSizeType> unityBackgroundSize { get => GetDefault(\"background-size\", \"auto\"); set => Set(\"background-size\", value); }\n        ColorProperty unityBackgroundImageTintColor { get => Get(\"-unity-background-image-tint-color\"); set => Set(\"-unity-background-image-tint-color\", value); }\n        // Slicing\n        IntegerProperty unitySliceLeft { get => Get(\"-unity-slice-left\"); set => Set(\"-unity-slice-left\", value); }\n        IntegerProperty unitySliceTop { get => Get(\"-unity-slice-top\"); set => Set(\"-unity-slice-top\", value); }\n        IntegerProperty unitySliceRight { get => Get(\"-unity-slice-right\"); set => Set(\"-unity-slice-right\", value); }\n        IntegerProperty unitySliceBottom { get => Get(\"-unity-slice-bottom\"); set => Set(\"-unity-slice-bottom\", value); }\n        // Borders\n        ColorProperty borderColor { get => Get(\"border-color\"); set => Set(\"border-color\", value); }\n        LengthProperty borderTopLeftRadius { get => Get1(\"border-top-left-radius\", \"border-radius\", 0); set => Set4(\"border-top-left-radius\", value, \"border-radius\", 0); }\n        LengthProperty borderTopRightRadius { get => Get1(\"border-top-right-radius\", \"border-radius\", 1); set => Set4(\"border-top-right-radius\", value, \"border-radius\", 1); }\n        LengthProperty borderBottomLeftRadius { get => Get1(\"border-bottom-left-radius\", \"border-radius\", 2); set => Set4(\"border-bottom-left-radius\", value, \"border-radius\", 2); }\n        LengthProperty borderBottomRightRadius { get => Get1(\"border-bottom-right-radius\", \"border-radius\", 3); set => Set4(\"border-bottom-right-radius\", value, \"border-radius\", 3); }\n        Length4Property borderRadius { get => Get4(\"border-radius\", \"border-top-left-radius\", \"border-top-right-radius\", \"border-bottom-left-radius\", \"border-bottom-right-radius\"); set => Set1(\"border-radius\", value, \"border-top-left-radius\", \"border-top-right-radius\", \"border-bottom-left-radius\", \"border-bottom-right-radius\"); }\n        // Appearance\n        EnumProperty<Visibility> overflow { get => Get(nameof(overflow)); set => Set(nameof(overflow), value); }\n        EnumProperty<OverflowClip> unityOverflowClipBox { get => Get(\"-unity-overflow-clip-box\"); set => Set(\"-unity-overflow-clip-box\", value); }\n        NumberProperty opacity { get => Get(nameof(opacity)); set => Set(nameof(opacity), value); }\n        EnumProperty<Visibility> visibility { get => Get(nameof(visibility)); set => Set(nameof(visibility), value); }\n        EnumProperty<Display> display { get => Get(nameof(display)); set => Set(nameof(display), value); }\n\n        // Text\n        ColorProperty color { get => Get(nameof(color)); set => Set(nameof(color), value); }\n        AssetProperty unityFont { get => Get(\"-unity-font\"); set => Set(\"-unity-font\", value); }\n        AssetProperty unityFontDefinition { get => Get(\"-unity-font-definition\"); set => Set(\"-unity-font-definition\", value); }\n        LengthProperty fontSize { get => Get(\"font-size\"); set => Set(\"font-size\", value); }\n        EnumProperty<FontStyle> unityFontStyle { get => Get(\"-unity-font-style\"); set => Set(\"-unity-font-style\", value); }\n        EnumProperty<TextAlign> unityTextAlign { get => Get(\"-unity-text-align\"); set => Set(\"-unity-text-align\", value); }\n        EnumProperty<Wrap> whiteSpace { get => Get(\"white-space\"); set => Set(\"white-space\", value); }\n        ShadowProperty textShadow { get => Get(\"text-shadow\"); set => Set(\"text-shadow\", value); }\n        EnumProperty<TextOverflow> textOverflow { get => Get(\"text-overflow\"); set => Set(\"text-overflow\", value); }\n\n        // Cursor\n        CursorProperty cursor { get => Get(nameof(cursor)); set => Set(nameof(cursor), value); }\n\n        // Effects\n        ShadowProperty boxShadow { get => Get(\"--box-shadow\"); set => Set(\"--box-shadow\", value); }\n\n        // Transitions\n        internal DurationProperty transitionDuration { get => Get(\"transition-duration\"); set => Set(\"transition-duration\", value); }\n        internal EnumProperty<EasingFunction> transitionEasing { get => Get(\"transition-timing-function\"); set => Set(\"transition-timing-function\", value); }\n        #endregion\n\n        #region Constructors\n        public UssStyle(string name) : base(name) { }\n        public UssStyle(string name, AssetsInfo assetsInfo) : this(name) => this.assetsInfo = assetsInfo;\n        public UssStyle(string name, AssetsInfo assetsInfo, BaseNode node, StyleSlot styleSlot) : this(name, assetsInfo)\n        {\n            switch (styleSlot.styleType)\n            {\n                case StyleType.FILL when node is IGeometryMixin geometry:\n                    switch (styleSlot.Slot)\n                    {\n                        case \"fill\":\n                        {\n                            if (node is TextNode)\n                                Name += \"-Text\";\n                            AddFill(geometry);\n                            break;\n                        }\n\n                        case \"stroke\":\n                            Name += node is TextNode ? \"-TextStroke\" : \"-Border\";\n                            AddStrokeColor(geometry);\n                            break;\n                    }\n\n                    break;\n\n                case StyleType.TEXT when node is TextNode text:\n                    AddSharedTextStyle(text.style);\n                    break;\n\n                case StyleType.EFFECT when node is IBlendMixin blend:\n                    AddBlend(blend);\n                    break;\n\n                case StyleType.GRID or StyleType.NONE:\n                    LogWarningIgnoredFigmaProperty(node, $\"{nameof(styleSlot)} {nameof(styleSlot.styleType)} with {styleSlot.styleType}\");\n                    break;\n\n                default:\n                    throw new NotSupportedException();\n            }\n        }\n        public UssStyle(string name, AssetsInfo assetsInfo, BaseNode node) : this(name, assetsInfo)\n        {\n            if (node.IsSvgNode())\n            {\n                AddSvg(assetsInfo, node); // AddSvg has to be called first in the constructor, because it overwrites its own boundingbox\n            }\n            else\n            {\n                if (node is IGeometryMixin geometry)\n                    AddGeometry(geometry);\n                AddBorderRadius(node);\n            }\n\n            if (node is IBlendMixin blend)\n                AddBlend(blend);\n            if (node is ILayoutMixin layout && !node.IsRootNode())\n                AddLayout(layout);\n            if (node is IDefaultFrameMixin frame)\n                AddFrame(frame);\n            if (node is TextNode text)\n                AddText(text);\n        }\n        #endregion\n\n        #region Methods\n        internal UssStyle CopyFrom(UssStyle style)\n        {\n            style.Attributes.ForEach(x => Attributes[x.Key] = x.Value);\n            return this;\n        }\n        void AddFrame(IDefaultFrameMixin frame)\n        {\n            if (frame.clipsContent)\n                overflow = Visibility.Hidden;\n\n            LayoutDouble4 correctedPadding = frame.GetCorrectedPadding();\n            if (correctedPadding.Any())\n                padding = correctedPadding.ToLength4Property();\n\n            if (frame.layoutMode is LayoutMode.NONE)\n                return;\n\n            if (frame.layoutWrap is LayoutWrap.WRAP)\n                flexWrap = FlexWrap.Wrap;\n            if (frame.layoutMode is LayoutMode.HORIZONTAL)\n                flexDirection = FlexDirection.Row;\n\n            justifyContent = frame.primaryAxisAlignItems switch\n            {\n                PrimaryAxisAlignItems.MIN => JustifyContent.FlexStart,\n                PrimaryAxisAlignItems.CENTER => JustifyContent.Center,\n                PrimaryAxisAlignItems.MAX => JustifyContent.FlexEnd,\n                PrimaryAxisAlignItems.SPACE_BETWEEN => JustifyContent.SpaceBetween,\n                _ => throw new NotSupportedException()\n            };\n\n            alignItems = frame.counterAxisAlignItems switch\n            {\n                CounterAxisAlignItems.MIN => Align.FlexStart,\n                CounterAxisAlignItems.CENTER => Align.Center,\n                CounterAxisAlignItems.MAX => Align.FlexEnd,\n                CounterAxisAlignItems.BASELINE => Align.Center,\n                _ => throw new NotSupportedException()\n            };\n\n            if (frame.itemSpacing > 0.0)\n                itemSpacing = frame.itemSpacing;\n        }\n        void AddGeometry(IGeometryMixin geometry)\n        {\n            AddFill(geometry);\n\n            if (!geometry.HasBorder())\n                return;\n\n            AddStrokeColor(geometry);\n            if (geometry.individualStrokeWeights != null)\n            {\n                if (geometry.individualStrokeWeights.left > 0)\n                    borderLeftWidth = geometry.individualStrokeWeights.left;\n                if (geometry.individualStrokeWeights.right > 0)\n                    borderRightWidth = geometry.individualStrokeWeights.right;\n                if (geometry.individualStrokeWeights.top > 0)\n                    borderTopWidth = geometry.individualStrokeWeights.top;\n                if (geometry.individualStrokeWeights.bottom > 0)\n                    borderBottomWidth = geometry.individualStrokeWeights.bottom;\n            }\n            else\n            {\n                borderWidth = geometry.strokeWeight;\n            }\n        }\n        void AddLayout(ILayoutMixin layout)\n        {\n            void SetPositioning(IDefaultFrameMixin parent)\n            {\n                Rect frameBorderBox = layout.GetBorderBox();\n                Rect parentContentBox = parent.GetContentBox();\n                double x = frameBorderBox.x - parentContentBox.x;\n                double y = frameBorderBox.y - parentContentBox.y;\n                double r = parentContentBox.width - frameBorderBox.width - x;\n                double b = parentContentBox.height - frameBorderBox.height - y;\n\n                switch (layout.constraints.horizontal)\n                {\n                    case ConstraintHorizontal.LEFT:\n                        left = x;\n                        break;\n\n                    case ConstraintHorizontal.RIGHT:\n                        right = r;\n                        break;\n\n                    case ConstraintHorizontal.LEFT_RIGHT:\n                        left = x;\n                        right = r;\n                        break;\n\n                    case ConstraintHorizontal.CENTER:\n                        if (parent.layoutMode is LayoutMode.VERTICAL or LayoutMode.NONE)\n                            alignSelf = Align.Center;\n                        else if (parent.primaryAxisAlignItems is not PrimaryAxisAlignItems.CENTER)\n                            LogWarningImpossibleDesign((IBaseNodeMixin)layout, $\"Has center constraint on {nameof(LayoutMode.HORIZONTAL)} axis, but parent doesnt align items center it has {parent.layoutMode}.\");\n                        if (parent.HasBorder() && parent.strokeAlign is not StrokeAlign.OUTSIDE)\n                            LogWarningImpossibleDesign((IBaseNodeMixin)layout, $\"Center constraint should only be combined with parent that has {nameof(StrokeAlign.OUTSIDE)} border. Parent has {parent.strokeAlign}. The scaling will be off by a few pixels when growing\");\n\n                        double cx = parentContentBox.halfWidth - frameBorderBox.halfWidth - x;\n                        if (Math.Abs(cx) >= tolerance)\n                            translate = new Length2Property(new LengthProperty[] { -cx, 0.0 });\n\n                        break;\n\n                    case ConstraintHorizontal.SCALE when parentContentBox.width > 0.0:\n                        left = new LengthProperty(100.0 * x / parentContentBox.width, Unit.Percent);\n                        right = new LengthProperty(100.0 * r / parentContentBox.width, Unit.Percent);\n                        break;\n\n                    case ConstraintHorizontal.SCALE:\n                        break;\n\n                    default:\n                        throw new NotSupportedException();\n                }\n\n                switch (layout.constraints.vertical)\n                {\n                    case ConstraintVertical.TOP:\n                        top = y;\n                        break;\n\n                    case ConstraintVertical.BOTTOM:\n                        bottom = b;\n                        break;\n\n                    case ConstraintVertical.TOP_BOTTOM:\n                        top = y;\n                        bottom = b;\n                        break;\n\n                    case ConstraintVertical.CENTER:\n                        if (parent.layoutMode is not LayoutMode.HORIZONTAL)\n                            alignSelf = Align.Center;\n                        else if (parent.primaryAxisAlignItems is not PrimaryAxisAlignItems.CENTER)\n                            LogWarningImpossibleDesign((IBaseNodeMixin)layout, $\"Has center constraint on {nameof(LayoutMode.VERTICAL)} axis, but parent doesnt align items center it has {parent.layoutMode}\");\n                        if (parent.HasBorder() && parent.strokeAlign is not StrokeAlign.OUTSIDE)\n                            LogWarningImpossibleDesign((IBaseNodeMixin)layout, $\"Center constraint should only be combined with parent that has {nameof(StrokeAlign.OUTSIDE)} border. Parent has {parent.strokeAlign}. The scaling will be off by a few pixels when growing\");\n\n                        double cy = parentContentBox.halfHeight - frameBorderBox.halfHeight - y;\n                        if (Math.Abs(cy) >= tolerance)\n                            translate = new Length2Property(new[] { translate[0], -cy });\n                        break;\n\n                    case ConstraintVertical.SCALE when parentContentBox.height > 0.0:\n                        top = new LengthProperty(100.0 * y / parentContentBox.height, Unit.Percent);\n                        bottom = new LengthProperty(100.0 * b / parentContentBox.height, Unit.Percent);\n                        break;\n\n                    case ConstraintVertical.SCALE:\n                        break;\n\n                    default:\n                        throw new NotSupportedException();\n                }\n            }\n            bool BoxSizingCorrection(IDefaultFrameMixin parent)\n            {\n                // When strokesIncludedInLayout it's the same as box-sizing: border-box\n                if (parent.strokesIncludedInLayout)\n                    return false;\n\n                // We modify position of elements to emulate negative padding. However, in UI Toolkit child cant to grow bigger than its parent.\n                LayoutDouble4 parentNegativePadding = parent.GetCorrectedPadding().OnlyNegativeValues();\n\n                bool anyHorizontal = parentNegativePadding.left < -tolerance || parentNegativePadding.right < -tolerance;\n                bool anyVertical = parentNegativePadding.top < -tolerance || parentNegativePadding.bottom < -tolerance;\n                bool wrongHorizontal = layout.layoutSizingHorizontal is LayoutSizing.FILL && anyHorizontal;\n                bool wrongVertical = layout.layoutSizingVertical is LayoutSizing.FILL && anyVertical;\n                if (wrongHorizontal || wrongVertical)\n                {\n                    LogWarningImpossibleDesign((IBaseNodeMixin)layout, $\"{nameof(LayoutSizing.FILL)} on node with child bounding box being outside parents content, Unity auto layout doesn't allow child to outgrow parents content. \" +\n                                                                       $\"Wrong {(wrongHorizontal && wrongVertical ? \"Horizontal and Vertical\" : wrongHorizontal ? \"Horizontal\" : \"Vertical\")} axis. \" +\n                                                                       $\"Element has ({layout.layoutSizingHorizontal}, {layout.layoutSizingVertical}), parent has border {parent.strokeAlign} with width {(string)parent.GetBorderWidths().ToLength4Property()}. \" +\n                                                                       \"Unity wont grow child above parent. Possible fixes:\" +\n                                                                       $\"\\n1: Change {nameof(IDefaultFrameMixin.strokesIncludedInLayout)} in Auto layout settings to included.\" +\n                                                                       $\"\\n2: Use {nameof(LayoutSizing.FIXED)} or {nameof(LayoutSizing.HUG)}\\n3: increase padding, currently missing {(string)(-parentNegativePadding).ToLength4Property()} more padding to make them not overlap.\" +\n                                                                       $\"\\n3: make parent border {nameof(StrokeAlign.OUTSIDE)}\");\n                    return false;\n                }\n\n                bool horizontal = parent.layoutMode is LayoutMode.HORIZONTAL;\n                double primary = parent.primaryAxisAlignItems switch\n                {\n                    PrimaryAxisAlignItems.MIN or PrimaryAxisAlignItems.SPACE_BETWEEN => 1.0 * (horizontal ? parentNegativePadding.left : parentNegativePadding.top),\n                    PrimaryAxisAlignItems.MAX => -1.0 * (horizontal ? parentNegativePadding.right : parentNegativePadding.bottom),\n                    PrimaryAxisAlignItems.CENTER => 0.5 * (horizontal ? parentNegativePadding.left - parentNegativePadding.right : parentNegativePadding.top - parentNegativePadding.bottom),\n                    _ => 0.0\n                };\n                double counter = parent.counterAxisAlignItems switch\n                {\n                    CounterAxisAlignItems.MIN => 1.0 * (horizontal ? parentNegativePadding.top : parentNegativePadding.left),\n                    CounterAxisAlignItems.MAX => -1.0 * (horizontal ? parentNegativePadding.bottom : parentNegativePadding.right),\n                    CounterAxisAlignItems.CENTER => 0.5 * (horizontal ? parentNegativePadding.top - parentNegativePadding.bottom : parentNegativePadding.left - parentNegativePadding.right),\n                    _ => 0.0\n                };\n\n                (double leftCorrection, double topCorrection) = horizontal ? (primary, counter) : (counter, primary);\n                if (Math.Abs(topCorrection) > tolerance)\n                    top = topCorrection;\n                if (Math.Abs(leftCorrection) > tolerance)\n                    left = leftCorrection;\n\n                return true;\n            }\n            IDefaultFrameMixin parent = (IDefaultFrameMixin)((IBaseNodeMixin)layout).parent;\n\n            bool forceAutoHorizontal = false;\n            bool forceAutoVertical = false;\n            if (parent.layoutMode is LayoutMode.NONE || layout.layoutPositioning is LayoutPositioning.ABSOLUTE)\n            {\n                forceAutoHorizontal = layout.constraints.horizontal is ConstraintHorizontal.SCALE or ConstraintHorizontal.LEFT_RIGHT;\n                forceAutoVertical = layout.constraints.vertical is ConstraintVertical.SCALE or ConstraintVertical.TOP_BOTTOM;\n\n                position = Position.Absolute;\n                SetPositioning(parent);\n            }\n            else\n            {\n                LayoutDouble4 margin4 = new();\n\n                if (BoxSizingCorrection(parent))\n                    margin4 -= (layout as IGeometryMixin).GetOutsideBorderWidths();\n                if (Math.Abs(parent.itemSpacing) > tolerance && parent.primaryAxisAlignItems is not PrimaryAxisAlignItems.SPACE_BETWEEN && layout != parent.children.LastOrDefault(x => x.IsVisible() && x is not ILayoutMixin { layoutPositioning: LayoutPositioning.ABSOLUTE }))\n                {\n                    if (parent.layoutMode is LayoutMode.HORIZONTAL)\n                        margin4.right += parent.itemSpacing;\n                    else\n                        margin4.bottom += parent.itemSpacing;\n                }\n\n                if (margin4.Any())\n                    margin = margin4.ToLength4Property();\n                LayoutSizing primarySizing = parent.layoutMode is LayoutMode.HORIZONTAL ? layout.layoutSizingHorizontal : layout.layoutSizingVertical;\n                if (primarySizing is LayoutSizing.FIXED or LayoutSizing.HUG)\n                    flexShrink = 0.0; // Shrink clamps child to parent. Figma ignores this when using fixed or hug.\n            }\n\n            if (layout.layoutGrow > 0)\n                flexGrow = 1;\n            if (layout.layoutAlign is LayoutAlign.STRETCH)\n                alignSelf = Align.Stretch;\n\n            Rect borderBox = layout.GetBorderBox(); // Unity uses border-box\n            if (layout.layoutSizingHorizontal is LayoutSizing.FIXED && !forceAutoHorizontal)\n                width = borderBox.width;\n            if (layout.layoutSizingVertical is LayoutSizing.FIXED && !forceAutoVertical)\n                height = borderBox.height;\n\n            if (layout.minWidth != null)\n                minWidth = layout.minWidth.Value;\n            if (layout.minHeight != null)\n                minHeight = layout.minHeight.Value;\n            if (layout.maxWidth != null)\n                maxWidth = layout.maxWidth.Value;\n            if (layout.maxHeight != null)\n                maxHeight = layout.maxHeight.Value;\n\n            const double rad2deg = 180.0 / Math.PI;\n            if (Math.Abs(layout.rotation) > tolerance && !((IBaseNodeMixin)layout).IsSvgNode())\n            {\n                LogWarningImpossibleDesign(layout as IBaseNodeMixin, \"Rotation and anchors are different in figma and unity. Its best to remove rotation from figma elements. In Figma rotation is applied and then constraints. In unity anchors are applied first. Meaning a full screen figma 1920x1080 becomes a 1080x1920 in unity.\");\n                rotate = new LengthProperty(layout.rotation * rad2deg, Unit.Degrees);\n            }\n\n            if (layout is TextNode { style: { textAutoResize: TextAutoResize.WIDTH_AND_HEIGHT } } text)\n            {\n                if (parent.counterAxisAlignItems is CounterAxisAlignItems.BASELINE) // Baseline is not supported by unity, so we emulate it\n                {\n                    double maxSize = parent.children.OfType<TextNode>().Max(x => x.style.fontSize);\n                    const double fontSizeToOffset = 1.0 / 2.75; // Approximate value gotten through trail and error. This works when parent is CounterAxisCenter, siblings have same font family and height is set to auto. Otherwise its random if it works or not\n                    double baselineOffset = (maxSize - text.style.fontSize) * fontSizeToOffset;\n                    if (Math.Abs(baselineOffset) > tolerance)\n                        top = baselineOffset;\n                }\n                else\n                {\n                    const double idealLineHeightFactor = 1.2;\n                    height = text.style.lineHeightPx;                                           // Unity text only aligns correctly when height is 1.2 times font size. Figma allows any text height\n                    if (text.style.lineHeightPx <= text.style.fontSize * idealLineHeightFactor) // Figma centers text when lineheight is too small\n                        text.style.textAlignVertical = TextAlignVertical.CENTER;\n                }\n            }\n        }\n        void AddText(TextNode text)\n        {\n            TextNode.Style style = text.style;\n            string horizontal = style.textAlignHorizontal switch\n            {\n                TextAlignHorizontal.LEFT => nameof(left),\n                TextAlignHorizontal.RIGHT => nameof(right),\n                TextAlignHorizontal.CENTER => \"center\",\n                TextAlignHorizontal.JUSTIFIED => throw new NotSupportedException(),\n                _ => throw new NotSupportedException()\n            };\n            string vertical = style.textAlignVertical switch\n            {\n                TextAlignVertical.TOP => \"upper\",\n                TextAlignVertical.BOTTOM => \"lower\",\n                TextAlignVertical.CENTER => \"middle\",\n                _ => throw new NotSupportedException()\n            };\n\n            unityTextAlign = (EnumProperty<TextAlign>)$\"{vertical}-{horizontal}\";\n\n            if (style.textTruncation is TextTruncation.ENDING)\n            {\n                textOverflow = TextOverflow.Ellipsis;\n                overflow = Visibility.Hidden;\n            }\n\n            switch (style.textAutoResize)\n            {\n                case TextAutoResize.NONE:\n                case TextAutoResize.HEIGHT when style.maxLines is not 1:\n                    whiteSpace = Wrap.Normal;\n                    break;\n\n                case TextAutoResize.TRUNCATE:\n                    LogWarningIgnoredFigmaProperty(text, $\"{nameof(TextAutoResize)}.{nameof(TextAutoResize.TRUNCATE)} is deprecated, should be changed for element in figma document to use either {nameof(TextAutoResize.HEIGHT)} or {nameof(TextAutoResize.WIDTH_AND_HEIGHT)}\");\n                    break;\n            }\n\n            AddSharedTextStyle(style);\n        }\n        void AddBlend(IBlendMixin blend)\n        {\n            if (blend.opacity < 1.0 - tolerance)\n                opacity = UssStyleExtension.AlphaCorrection(blend.opacity);\n\n            IEnumerable<ShadowEffect> effects = blend.effects.OfType<ShadowEffect>().Where(x => x.visible);\n            ShadowEffect effect = effects.FirstOrDefault();\n            if (effect == null)\n                return;\n\n            if (effects.Count() > 1)\n                LogWarningIgnoredFigmaProperty((IBaseNodeMixin)blend, $\"More than 1 effects, we support 1 effect per element, this has {effects.Count()}\");\n\n            ShadowProperty shadow = new(effect.offset.x, effect.offset.y, effect.radius, effect.color);\n            if (blend is TextNode text)\n            {\n                if (effect.type is EffectType.DROP_SHADOW)\n                    textShadow = shadow;\n                else\n                    LogWarningImpossibleDesign(text, $\"Cant use {effect.type} for text we can only use {nameof(EffectType.DROP_SHADOW)}\");\n            }\n            else\n            {\n                boxShadow = shadow;\n                LogWarningIgnoredFigmaProperty((IBaseNodeMixin)blend, \"Effects on elements, we support effects on text only\");\n            }\n        }\n        void AddBorderRadius(BaseNode node)\n        {\n            // Unity makes each corner as round as possible while figma limits borders to max 50% of size. In Figma when a corner is bigger than the rest that corner can make other corner less round, we dont know how to recreate that effect in unity\n            // Figma makes outside borders have radius equal to radius + border\n            double maxBorderRadius = node is ILayoutMixin layout ? Math.Min(layout.GetBorderBox().width, layout.GetBorderBox().height) * 0.5 : double.MaxValue;\n            LayoutDouble4 outsideBorder = node is IGeometryMixin geometry ? geometry.GetOutsideBorderWidths() : new LayoutDouble4();\n            if (node is ICornerMixin { cornerRadius: > 0 } corner)\n            {\n                LayoutDouble4 rad = outsideBorder + new LayoutDouble4(corner.cornerRadius.Value);\n                LayoutDouble4 radius = new(Math.Min(maxBorderRadius, rad.top), Math.Min(maxBorderRadius, rad.left), Math.Min(maxBorderRadius, rad.bottom), Math.Min(maxBorderRadius, rad.right));\n                borderRadius = radius.ToLength4Property();\n            }\n            else if (node is IRectangleCornerMixin { rectangleCornerRadii: not null } rectangleCorner && rectangleCorner.rectangleCornerRadii.Any(x => x > 0.0))\n            {\n                double GetBorderCorrection(double radius, double border) => radius == 0.0 ? 0.0 : Math.Min(maxBorderRadius, radius + border);\n                double[] radii = rectangleCorner.rectangleCornerRadii;\n                LayoutDouble4 radius = new(GetBorderCorrection(radii[0], outsideBorder.top), GetBorderCorrection(radii[1], outsideBorder.right), GetBorderCorrection(radii[2], outsideBorder.bottom), GetBorderCorrection(radii[3], outsideBorder.left));\n                borderRadius = radius.ToLength4Property();\n            }\n        }\n        void AddSvg(AssetsInfo assetsInfo, BaseNode svg)\n        {\n            IGeometryMixin geometry = (IGeometryMixin)svg;\n            ILayoutMixin layout = (ILayoutMixin)svg;\n            Rect boundingBox = layout.absoluteBoundingBox;\n            if (geometry.HasBorder())\n            {\n                boundingBox.x -= geometry.strokeWeight / 2.0;\n                if (geometry.strokeCap is not StrokeCap.NONE)\n                    boundingBox.y -= geometry.strokeWeight / 2.0;\n            }\n\n            layout.absoluteBoundingBox = boundingBox;\n            string extension = svg.HasImage() ? KnownFormats.png : KnownFormats.svg;\n            if (assetsInfo.GetAssetPath(svg.id, extension, out string url))\n                backgroundImage = Url(url);\n        }\n        #endregion\n\n        #region Support Methods\n        void AddSharedTextStyle(TextNode.Style style)\n        {\n            const string defaultFont = \"Inter-Regular\";\n\n            bool TryGetFontWithExtension(string font, out string resource)\n            {\n                if (assetsInfo.GetAssetPath(font, KnownFormats.ttf, out string ttfPath))\n                {\n                    resource = Url(ttfPath);\n                    return true;\n                }\n\n                if (assetsInfo.GetAssetPath(font, KnownFormats.otf, out string otfPath))\n                {\n                    resource = Url(otfPath);\n                    return true;\n                }\n\n                resource = Resource(defaultFont);\n                return false;\n            }\n\n            (string, string) GetFont()\n            {\n                if (string.IsNullOrEmpty(style.fontPostScriptName) && string.IsNullOrEmpty(style.fontFamily))\n                    return (null, null);\n\n                string fontPostScriptName = style.fontPostScriptName ?? $\"{style.fontFamily}-{style.fontStyle.Replace(\" \", string.Empty)}\";\n\n                string weightPostfix;\n\n                if (style.fontWeight > 0)\n                    weightPostfix = Enum.GetValues(typeof(FontWeight)).GetValue((int)(style.fontWeight / 100) - 1).ToString();\n                else\n                    weightPostfix = fontPostScriptName.Contains('-') ? fontPostScriptName.Split('-')[1].Replace(nameof(Index), string.Empty) : string.Empty;\n\n                string italicPostfix = style.italic || fontPostScriptName.Contains(nameof(FontStyle.Italic)) ? nameof(FontStyle.Italic) : string.Empty;\n                string fontName = $\"{style.fontFamily}-{weightPostfix}{italicPostfix}\";\n\n                if (!TryGetFontWithExtension(fontName, out string font) && !TryGetFontWithExtension(fontPostScriptName, out font))\n                    Debug.LogWarning(Extensions.BuildTargetMessage(\"Cannot find Font\", fontName, string.Empty));\n\n                bool exists = assetsInfo.GetAssetPath(fontName, KnownFormats.asset, out string path);\n                return (font, exists ? path : null);\n            }\n\n            fontSize = style.fontSize;\n            (string font, string fontDefinition) = GetFont();\n\n            if (font != null)\n                unityFont = font;\n\n            if (fontDefinition != null)\n                unityFontDefinition = Url(fontDefinition);\n\n            if (font == null && fontDefinition == null)\n            {\n                Debug.LogWarning($\"Font style {style.fontFamily} {style.fontStyle} {style.fontPostScriptName} is not resolved\");\n                unityFont = Url(defaultFont);\n            }\n        }\n        void AddFill(IGeometryMixin geometry)\n        {\n            bool urlExists = false;\n            string url = string.Empty;\n            RGBA finalColor = new RGBA();\n            foreach (Paint fill in geometry.fills.Where(x => x.visible).Reverse())\n            {\n                switch (fill)\n                {\n                    case SolidPaint solid:\n                        solid.color.a = solid.opacity;\n                        finalColor = finalColor.BlendWith(solid.color);\n                        break;\n\n                    case GradientPaint gradient:\n                        if (geometry is TextNode)\n                        {\n                            RGBA average = gradient.gradientStops.Select(stop => stop.color).GetAverageColor();\n                            average.a = gradient.opacity;\n                            finalColor = finalColor.BlendWith(average);\n                        }\n                        else\n                        {\n                            urlExists = assetsInfo.GetAssetPath(gradient.GetHash(), KnownFormats.svg, out url);\n                        }\n\n                        break;\n\n                    case ImagePaint image:\n                        if (geometry is TextNode text)\n                        {\n                            LogWarningImpossibleDesign(text, $\"{nameof(TextElement)} with images, unity places images in background, while figma puts them inside the text\");\n                            break;\n                        }\n\n                        urlExists = assetsInfo.GetAssetPath(image.imageRef, KnownFormats.png, out url);\n\n                        unityBackgroundSize = image.scaleMode switch\n                        {\n                            ScaleMode.FILL => BackgroundSizeType.Cover,\n                            ScaleMode.FIT => BackgroundSizeType.Contain,\n                            _ => unityBackgroundSize\n                        };\n                        break;\n                }\n\n                finalColor.a = UssStyleExtension.AlphaCorrection(finalColor.a);\n                if (geometry is TextNode)\n                    color = new ColorProperty(finalColor);\n                else\n                    backgroundColor = new ColorProperty(finalColor);\n                if (urlExists)\n                    backgroundImage = Url(url);\n            }\n        }\n        void AddStrokeColor(IGeometryMixin geometry)\n        {\n            if (geometry is TextNode)\n            {\n                LogWarningIgnoredFigmaProperty((IBaseNodeMixin)geometry, \"Stroke on text\"); // Stroke on text might not be possible at all as unity makes inside stroke and figma outside stroke\n                return;\n            }\n\n            RGBA finalColor = new();\n            foreach (Paint stroke in geometry.strokes.Where(x => x.visible).Reverse())\n            {\n                RGBA color = stroke switch\n                {\n                    SolidPaint solid => solid.color,\n                    GradientPaint gradient => gradient.gradientStops.Select(stop => stop.color).GetAverageColor(),\n                    _ => throw new NotSupportedException()\n                };\n                color.a = stroke.opacity;\n                finalColor = finalColor.BlendWith(color);\n            }\n\n            finalColor.a = UssStyleExtension.AlphaCorrection(finalColor.a);\n            borderColor = finalColor;\n        }\n        internal static List<UssStyle> MakeTransitionStyles(UssStyle root, UssStyle idle, UssStyle hover = null, UssStyle active = null)\n        {\n            List<UssStyle> transitions = new() { new UssStyle(root.Name) { Target = idle, opacity = 1 } };\n\n            if (hover != null)\n                transitions.Add(new UssStyle(root.Name) { Target = idle, PseudoClass = PseudoClass.Hover, opacity = 0 });\n            if (active != null)\n                transitions.Add(new UssStyle(root.Name) { Target = idle, PseudoClass = PseudoClass.Active, opacity = 0 });\n\n            if (hover != null)\n            {\n                transitions.Add(new UssStyle(root.Name) { Target = hover, opacity = 0 });\n                transitions.Add(new UssStyle(root.Name) { Target = hover, PseudoClass = PseudoClass.Hover, opacity = 1 });\n                if (active != null)\n                    transitions.Add(new UssStyle(root.Name) { Target = hover, PseudoClass = PseudoClass.Active, opacity = 0 });\n            }\n\n            if (active != null)\n            {\n                transitions.Add(new UssStyle(root.Name) { Target = active, opacity = 0 });\n\n                if (hover != null)\n                    transitions.Add(new UssStyle(root.Name) { Target = active, PseudoClass = PseudoClass.Hover, opacity = 0 });\n\n                transitions.Add(new UssStyle(root.Name) { Target = active, PseudoClass = PseudoClass.Active, opacity = 1 });\n            }\n\n            return transitions;\n        }\n        static void LogWarningIgnoredFigmaProperty(IBaseNodeMixin node, string message) => Debug.LogWarning(Extensions.BuildTargetMessage(\"Ignored figma property\", node.GetFullPath(), $\"No support for {message}. Not implemented.\"));\n        static void LogWarningImpossibleDesign(IBaseNodeMixin node, string message) => Debug.LogWarning(Extensions.BuildTargetMessage(\"Wrong figma design\", node.GetFullPath(), $\"{message}. We cant create this in Unity.\"));\n        #endregion\n    }\n}"
  },
  {
    "path": "Editor/Core/Uss/UssStyle.cs.meta",
    "content": "fileFormatVersion: 2\nguid: 8d258033e1644b1fa80fcdf1fb668783\ntimeCreated: 1727945365"
  },
  {
    "path": "Editor/Core/Uss/UssWriter.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing System.Text;\nusing System.Threading.Tasks;\n\nnamespace Figma.Core.Uss\n{\n    using Internals;\n\n    internal class UssWriter : IDisposable, IAsyncDisposable\n    {\n        #region Fields\n        readonly string rootDirectory;\n        readonly StreamWriter stream;\n        int count;\n        #endregion\n\n        #region Constructors\n        public UssWriter(string rootDirectory, string path)\n        {\n            this.rootDirectory = rootDirectory;\n            stream = new StreamWriter(Path = path, false, Encoding.UTF8, 1024);\n        }\n        #endregion\n\n        #region Properties\n        public string Path { get; }\n        #endregion\n\n        #region Methods\n        public void Write(BaseUssStyle style)\n        {\n            if (!style.HasAttributes)\n                return;\n\n            if (count > 0)\n            {\n                stream.WriteLine();\n                stream.WriteLine();\n            }\n\n            stream.Write(style.BuildName());\n            stream.WriteLine(\" {\");\n\n            foreach ((string key, string value) in style.Attributes)\n            {\n                switch (key)\n                {\n                    case \"background-image\" when value.Contains(\"url\"):\n                        // Getting a relative path to image to keep the reference.\n                        // Since images are located in a parent of a parent directory.\n                        // Assets/Images directory and frames are in Assets/Frames/CanvasName/\n                        // We need to calculate a relative path and the only way of doing this\n                        // is on write operation, since UssStyle is not aware of the path, where it\n                        // would be written.\n                        stream.WriteLine($\"\\t{key}: url('{System.IO.Path.GetRelativePath(System.IO.Path.GetDirectoryName(Path), PathExtensions.CombinePath(rootDirectory, value[5..^2]))?.Replace('\\\\', '/')}');\");\n                        continue;\n\n                    default:\n                        stream.WriteLine($\"\\t{key}: {value};\");\n                        break;\n                }\n            }\n\n            stream.Write(\"}\");\n\n            count++;\n\n            Write(style.SubStyles);\n        }\n        public void Write(IEnumerable<BaseUssStyle> styles) => styles.OrderBy(x => x.Name).ForEach(Write);\n\n        void IDisposable.Dispose() => stream?.Dispose();\n        async ValueTask IAsyncDisposable.DisposeAsync()\n        {\n            if (stream != null)\n                await stream.DisposeAsync();\n        }\n        #endregion\n    }\n}"
  },
  {
    "path": "Editor/Core/Uss/UssWriter.cs.meta",
    "content": "fileFormatVersion: 2\nguid: d732fb08b4e246c6bce62bad8551f8f8\ntimeCreated: 1727945385"
  },
  {
    "path": "Editor/Core/Uss.meta",
    "content": "fileFormatVersion: 2\nguid: eb2949d8c99346768cecb2a0968b2029\ntimeCreated: 1732192985"
  },
  {
    "path": "Editor/Core/Uxml/UxmlBuilder.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing UnityAsyncAwaitUtil;\nusing UnityEngine;\n\nnamespace Figma.Core.Uxml\n{\n    using Internals;\n    using static Const;\n    using static Internals.Extensions;\n    using static Internals.PathExtensions;\n\n    internal class UxmlBuilder\n    {\n        #region Fields\n        readonly Data data;\n        readonly NodeMetadata nodeMetadata;\n        readonly string globalUssFilePath;\n        readonly StylesPreprocessor stylesPreprocessor;\n        #endregion\n\n        #region Constructors\n        public UxmlBuilder(Data data, NodeMetadata nodeMetadata, string globalUssFilePath, StylesPreprocessor stylesPreprocessor)\n        {\n            this.data = data;\n            this.nodeMetadata = nodeMetadata;\n            this.globalUssFilePath = globalUssFilePath;\n            this.stylesPreprocessor = stylesPreprocessor;\n        }\n        #endregion\n\n        #region Methods\n        public void CreateDocument(string directory, string fileName, DocumentNode documentNode, IReadOnlyDictionary<string, IReadOnlyList<string>> framesPaths)\n        {\n            string CreateTemplateName(string path) => RemoveExtension(path).Replace('/', '-');\n\n            using UxmlWriter writer = new(directory, fileName);\n\n            writer.WriteUssStyleReference(GetRelativePath(writer.filePath, globalUssFilePath));\n            writer.StartElement(documentNode, stylesPreprocessor.GetClassList(documentNode), nodeMetadata.GetElementType(documentNode));\n\n            foreach (string templatePath in framesPaths.SelectMany(framesPath => framesPath.Value))\n            {\n                string path = GetRelativePath(writer.filePath, templatePath);\n                writer.WriteTemplate(CreateTemplateName(path), path);\n            }\n\n            foreach ((string name, IReadOnlyList<string> scope) in framesPaths)\n            {\n                if (scope.Count == 0)\n                    continue;\n\n                writer.StartElement(nameof(UnityEngine.UIElements.VisualElement), (\"picking-mode\", \"ignore\"), (\"class\", \"unity-viewport\"), (nameof(name), name));\n                foreach (string path in scope)\n                {\n                    string frameName = Path.GetFileNameWithoutExtension(path);\n                    string templateName = CreateTemplateName(GetRelativePath(writer.filePath, path));\n                    writer.WriteInstance(frameName, templateName, Uss.UssStyle.viewportClass.Name);\n                }\n\n                writer.EndElement();\n            }\n\n            writer.EndElement();\n        }\n        public string CreateFrame(string directory, string[] ussStyleFilesPath, IReadOnlyDictionary<string, string> templates, DefaultFrameNode frameNode)\n        {\n            using UxmlWriter writer = new(directory, frameNode.name);\n\n            WriteStyles(ussStyleFilesPath, writer);\n\n            foreach ((string templateName, string templatePath) in templates)\n                writer.WriteTemplate(templateName, GetRelativePath(writer.filePath, templatePath));\n\n            WriteNodesRecursively(frameNode, writer);\n\n            return writer.filePath;\n        }\n        public string CreateComponentSet(string directory, string[] ussStyleFilesPath, ComponentSetNode componentSetNode)\n        {\n            using UxmlWriter writer = new(directory, componentSetNode.name);\n\n            WriteStyles(ussStyleFilesPath, writer);\n            WriteNodesRecursively(componentSetNode, writer);\n\n            return writer.filePath;\n        }\n        public string CreateElement(string directory, string[] ussStyleFilesPath, DefaultShapeNode node, string template)\n        {\n            (bool isHash, string hashedTemplate) = nodeMetadata.GetTemplate(node);\n            using UxmlWriter writer = new(directory, isHash ? hashedTemplate : template);\n\n            WriteStyles(ussStyleFilesPath, writer);\n\n            if (node is DefaultFrameNode parent)\n                foreach (SceneNode child in parent.children)\n                    WriteNodesRecursively(child, writer);\n\n            return writer.filePath;\n        }\n\n        void WriteNodesRecursively(BaseNode node, UxmlWriter uxml, bool isComponent = false)\n        {\n            void WriteCanvasNode(CanvasNode canvasNode, UxmlWriter writer)\n            {\n                writer.StartElement(canvasNode, stylesPreprocessor.GetClassList(canvasNode), nodeMetadata.GetElementType(canvasNode));\n                canvasNode.children.ForEach(child => WriteNodesRecursively(child, writer));\n                writer.EndElement();\n            }\n            void WriteSectionNode(SectionNode sectionNode, UxmlWriter writer)\n            {\n                writer.StartElement(sectionNode, stylesPreprocessor.GetClassList(sectionNode), nodeMetadata.GetElementType(sectionNode));\n                sectionNode.children.ForEach(child => WriteNodesRecursively(child, writer));\n                writer.EndElement();\n\n                throw new NotImplementedException(nameof(WriteSectionNode));\n            }\n            void WriteSliceNode(SliceNode sliceNode, UxmlWriter writer)\n            {\n                writer.StartElement(sliceNode, stylesPreprocessor.GetClassList(sliceNode), nodeMetadata.GetElementType(sliceNode));\n                writer.EndElement();\n            }\n            void WriteTextNode(TextNode textNode, UxmlWriter writer)\n            {\n                writer.StartElement(textNode, stylesPreprocessor.GetClassList(textNode), nodeMetadata.GetElementType(textNode));\n\n                string text = textNode.style.textCase switch\n                {\n                    TextCase.UPPER => textNode.characters.ToUpper(Culture),\n                    TextCase.LOWER => textNode.characters.ToLower(Culture),\n                    _ => textNode.characters\n                };\n                writer.xmlWriter.WriteAttributeString(nameof(text), text);\n                writer.EndElement();\n            }\n            void WriteDefaultFrameNode(DefaultFrameNode defaultFrameNode, UxmlWriter writer)\n            {\n                WriteDefaultShapeNode(defaultFrameNode, writer, false);\n                defaultFrameNode.children.ForEach(child => WriteNodesRecursively(child, writer, isComponent));\n                writer.EndElement();\n            }\n            void WriteBooleanOperationNode(BooleanOperationNode node, UxmlWriter writer)\n            {\n                WriteDefaultShapeNode(node, writer); // We shouldn't process children for vector boolean operation\n            }\n            void WriteDefaultShapeNode(DefaultShapeNode defaultShapeNode, UxmlWriter writer, bool closeElement = true)\n            {\n                string tooltip = null;\n                if (nodeMetadata.GetTemplate(defaultShapeNode) is (var hash, { } template) && template.NotNullOrEmpty())\n                    tooltip = hash ? template : null;\n\n                writer.StartElement(defaultShapeNode, stylesPreprocessor.GetClassList(defaultShapeNode), nodeMetadata.GetElementType(defaultShapeNode));\n                if (tooltip.NotNullOrEmpty())\n                    writer.xmlWriter.WriteAttributeString(nameof(tooltip), tooltip!); // Use tooltip as a storage for hash template name\n                if (closeElement)\n                    writer.EndElement();\n            }\n            void WriteInstanceNode(InstanceNode instanceNode, UxmlWriter writer)\n            {\n                if (data.components.TryGetValue(instanceNode.componentId, out Component component) && !component.remote &&\n                    !string.IsNullOrEmpty(component.componentSetId) &&\n                    data.componentSets.TryGetValue(component.componentSetId, out Component target) && !target.remote)\n                {\n                    string componentSetName = target.name;\n                    string classList = stylesPreprocessor.GetClassList(instanceNode);\n\n                    writer.WriteInstance(instanceNode.name, componentSetName, classList);\n                }\n                else\n                {\n                    // Since this code only runs from Parallel, outside of Unity scope\n                    // We cannot use Debug.Log() without returning to Unity's thread\n                    SyncContextUtil.UnitySynchronizationContext.Post(_ => Debug.LogWarning(BuildTargetMessage($\"Target {nameof(Component)} for node\", instanceNode.GetFullPath(), \"is not found\")), null);\n                    WriteDefaultFrameNode(instanceNode, writer);\n                }\n            }\n\n            if (!node.IsVisible() || (!nodeMetadata.EnabledInHierarchy(node) && node is not ComponentSetNode && !isComponent))\n                return;\n\n            if (node is CanvasNode canvas) WriteCanvasNode(canvas, uxml);\n            if (node is FrameNode frame) WriteDefaultFrameNode(frame, uxml);\n            if (node is GroupNode group) WriteDefaultFrameNode(group, uxml);\n            if (node is ComponentSetNode componentSet) WriteDefaultFrameNode(componentSet, uxml);\n            if (node is SliceNode slice) WriteSliceNode(slice, uxml);\n            if (node is RectangleNode rectangle) WriteDefaultShapeNode(rectangle, uxml);\n            if (node is LineNode line) WriteDefaultShapeNode(line, uxml);\n            if (node is EllipseNode ellipse) WriteDefaultShapeNode(ellipse, uxml);\n            if (node is RegularPolygonNode regularPolygon) WriteDefaultShapeNode(regularPolygon, uxml);\n            if (node is StarNode star) WriteDefaultShapeNode(star, uxml);\n            if (node is VectorNode vector) WriteDefaultShapeNode(vector, uxml);\n            if (node is TextNode text) WriteTextNode(text, uxml);\n            if (node is ComponentNode component) WriteDefaultFrameNode(component, uxml);\n            if (node is InstanceNode instance) WriteInstanceNode(instance, uxml);\n            if (node is BooleanOperationNode booleanOperation) WriteBooleanOperationNode(booleanOperation, uxml);\n            if (node is SectionNode sectionNode) WriteDefaultFrameNode(sectionNode, uxml); // WriteSectionNode(sectionNode, uxml);\n        }\n        #endregion\n\n        #region Support Methods\n        void WriteStyles(string[] styles, UxmlWriter writer) => styles.ForEach(ussPath => writer.WriteUssStyleReference(CombinePath(GetRelativePath(writer.filePath, ussPath))));\n        #endregion\n    }\n}"
  },
  {
    "path": "Editor/Core/Uxml/UxmlBuilder.cs.meta",
    "content": "fileFormatVersion: 2\nguid: 501228cf0ce84dfda7160110c165f212\ntimeCreated: 1727945409"
  },
  {
    "path": "Editor/Core/Uxml/UxmlWriter.cs",
    "content": "using System;\nusing System.Text;\nusing System.Xml;\nusing UnityEngine.UIElements;\n\nnamespace Figma.Core.Uxml\n{\n    using Internals;\n    using static Const;\n    using static Internals.Const;\n    using static Internals.PathExtensions;\n\n    internal sealed class UxmlWriter : IDisposable\n    {\n        const string elementsNamespace = \"ui\";\n\n        static readonly XmlWriterSettings xmlWriterSettings = new()\n        {\n            OmitXmlDeclaration = true,\n            Indent = true,\n            IndentChars = indentCharacters,\n            NewLineOnAttributes = false,\n            Encoding = Encoding.UTF8\n        };\n\n        #region Fields\n        internal readonly string filePath;\n        internal readonly XmlWriter xmlWriter;\n        #endregion\n\n        #region Constructors\n        public UxmlWriter(string directory, string fileName)\n        {\n            filePath = CombinePath(directory, $\"{fileName}.{KnownFormats.uxml}\");\n            xmlWriter = XmlWriter.Create(filePath, xmlWriterSettings);\n            xmlWriter.WriteStartElement(elementsNamespace, \"UXML\", uxmlNamespace);\n        }\n        #endregion\n\n        #region Methods\n        public void Dispose()\n        {\n            xmlWriter.WriteEndElement();\n            xmlWriter?.Dispose();\n        }\n        public void StartElement(BaseNode node, string ussClasses, (ElementType type, string typeFullName) elementTypeInfo)\n        {\n            (string prefix, string elementName, string pickingMode) GetElementData(BaseNode node)\n            {\n                string prefix = elementsNamespace;\n                string elementName = nameof(VisualElement);\n                PickingMode pickingMode = PickingMode.Ignore;\n\n                if (elementTypeInfo.type == ElementType.IElement)\n                {\n                    prefix = null;\n                    elementName = elementTypeInfo.typeFullName;\n                    pickingMode = PickingMode.Position;\n                }\n                else if (elementTypeInfo.type == ElementType.None)\n                {\n                    if (node is not (DefaultFrameNode or TextNode or ComponentSetNode))\n                        return (prefix, elementName, pickingMode.ToString());\n\n                    const string inputsPrefix = \"Inputs\";\n                    const string buttonsPrefix = \"Buttons\";\n                    const string togglesPrefix = \"Toggles\";\n                    const string scrollViewsPrefix = \"ScrollViews\";\n\n                    if (node is TextNode) elementName = node.name.StartsWith(inputsPrefix) ? nameof(TextField) : nameof(Label);\n\n                    if (node.name.StartsWith(buttonsPrefix)) elementName = nameof(Button);\n                    else if (node.name.StartsWith(togglesPrefix)) elementName = nameof(Toggle);\n                    else if (node.name.StartsWith(scrollViewsPrefix)) elementName = nameof(ScrollView);\n\n                    pickingMode = node.name.StartsWith(buttonsPrefix) ||\n                                  node.name.StartsWith(togglesPrefix) ||\n                                  node.name.StartsWith(scrollViewsPrefix) ||\n                                  (node is TextNode && node.name.StartsWith(inputsPrefix))\n                        ? PickingMode.Position\n                        : pickingMode;\n                }\n                else\n                {\n                    elementName = elementTypeInfo.type.ToString();\n                    pickingMode = elementTypeInfo.type is ElementType.VisualElement or\n                                                          ElementType.BindableElement or\n                                                          ElementType.Box or\n                                                          ElementType.TextElement or\n                                                          ElementType.Label or\n                                                          ElementType.Image\n                        ? PickingMode.Ignore\n                        : PickingMode.Position;\n                }\n\n                return (prefix, elementName, pickingMode.ToString());\n            }\n\n            (string prefix, string elementName, string pickingMode) = GetElementData(node);\n\n            if (prefix.NotNullOrEmpty())\n                xmlWriter.WriteStartElement(prefix, elementName, uxmlNamespace);\n            else\n                xmlWriter.WriteStartElement(elementName);\n\n            xmlWriter.WriteAttributeString(\"name\", node.name);\n            xmlWriter.WriteAttributeString(\"id\", node.id);\n\n            if (ussClasses.NotNullOrEmpty())\n                xmlWriter.WriteAttributeString(\"class\", ussClasses);\n            if (pickingMode != nameof(PickingMode.Position))\n                xmlWriter.WriteAttributeString(\"picking-mode\", pickingMode);\n        }\n        public void StartElement(string type, params (string name, string value)[] attributes)\n        {\n            xmlWriter.WriteStartElement(elementsNamespace, type, uxmlNamespace);\n\n            foreach ((string name, string value) attribute in attributes)\n                xmlWriter.WriteAttributeString(attribute.name, attribute.value);\n        }\n        public void EndElement() => xmlWriter.WriteEndElement();\n\n        public void WriteUssStyleReference(string path)\n        {\n            StartElement(nameof(Style), (\"src\", path));\n            EndElement();\n        }\n        public void WriteTemplate(string templateName, string templatePath)\n        {\n            StartElement(\"Template\", (\"name\", templateName), (\"src\", templatePath));\n            EndElement();\n        }\n        public void WriteInstance(string instanceName, string templateName, string classList = null)\n        {\n            StartElement(\"Instance\", (\"name\", instanceName), (\"template\", templateName), (\"picking-mode\", \"ignore\"));\n            if (!string.IsNullOrEmpty(classList))\n                xmlWriter.WriteAttributeString(\"class\", classList);\n            EndElement();\n        }\n        #endregion\n    }\n}"
  },
  {
    "path": "Editor/Core/Uxml/UxmlWriter.cs.meta",
    "content": "fileFormatVersion: 2\nguid: 32914bba2eaf4c938f1c10a15860d6fa\ntimeCreated: 1733218152"
  },
  {
    "path": "Editor/Core/Uxml.meta",
    "content": "fileFormatVersion: 2\nguid: b264c8b3ae0846dc87a6a96ccb5c5dbf\ntimeCreated: 1733218052"
  },
  {
    "path": "Editor/Core.meta",
    "content": "fileFormatVersion: 2\nguid: 7101b854596dd674dad786dffc6936ab\nfolderAsset: yes\nDefaultImporter:\n  externalObjects: {}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Editor/Extensions/Extensions.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.Diagnostics;\nusing System.Linq;\n\nnamespace Figma\n{\n    using Internals;\n\n    [DebuggerStepThrough]\n    internal static class Extensions\n    {\n        #region Const\n        static readonly string[] unitsMap = { \"zero\", \"one\", \"two\", \"three\", \"four\", \"five\", \"six\", \"seven\", \"eight\", \"nine\", \"ten\", \"eleven\", \"twelve\", \"thirteen\", \"fourteen\", \"fifteen\", \"sixteen\", \"seventeen\", \"eighteen\", \"nineteen\" };\n        static readonly string[] tensMap = { \"zero\", \"ten\", \"twenty\", \"thirty\", \"forty\", \"fifty\", \"sixty\", \"seventy\", \"eighty\", \"ninety\" };\n        #endregion\n\n        #region Methods\n        internal static int ToBit(this bool value) => value ? 1 : 0;\n\n        internal static IEnumerable<T> IndexRedundantNames<T>(this IReadOnlyList<T> items, Func<T, string> getName, Action<T, string> setName, Func<int, string> postfixConverter)\n        {\n            foreach (IGrouping<string, T> group in items.GroupBy(getName).Where(y => y.Count() > 1))\n            {\n                int i = 0;\n                foreach (T item in group)\n                    setName(item, postfixConverter(i++));\n            }\n\n            return items;\n        }\n        internal static string NumberToWords(this int number)\n        {\n            switch (number)\n            {\n                case 0:\n                    return unitsMap[0];\n\n                case < 0:\n                    return $\"minus-{NumberToWords(Math.Abs(number))}\";\n            }\n\n            string words = string.Empty;\n\n            if (number / 1000000 > 0)\n            {\n                words += $\"{NumberToWords(number / 1000000)}-million \";\n                number %= 1000000;\n            }\n\n            if (number / 1000 > 0)\n            {\n                words += $\"{NumberToWords(number / 1000)}-thousand \";\n                number %= 1000;\n            }\n\n            if (number / 100 > 0)\n            {\n                words += $\"{NumberToWords(number / 100)}-hundred \";\n                number %= 100;\n            }\n\n            if (number <= 0)\n                return words;\n\n            if (words != string.Empty)\n                words += \"and-\";\n            if (number < 20)\n                words += unitsMap[number];\n            else\n            {\n                words += tensMap[number / 10];\n                if (number % 10 > 0)\n                    words += $\"-{unitsMap[number % 10]}\";\n            }\n\n            return words;\n        }\n        internal static RGBA GetAverageColor(this IEnumerable<RGBA> colors)\n        {\n            RGBA avgColor = new();\n            int count = 0;\n\n            foreach (RGBA color in colors)\n            {\n                avgColor.r += color.r;\n                avgColor.g += color.g;\n                avgColor.b += color.b;\n                avgColor.a += color.a;\n                count++;\n            }\n\n            if (count == 0) return avgColor;\n\n            avgColor.r /= count;\n            avgColor.g /= count;\n            avgColor.b /= count;\n            avgColor.a /= count;\n            return avgColor;\n        }\n        #endregion\n    }\n}"
  },
  {
    "path": "Editor/Extensions/Extensions.cs.meta",
    "content": "fileFormatVersion: 2\nguid: 7130aa1fa17b4bffa5e38dc5887c8364\ntimeCreated: 1732199774"
  },
  {
    "path": "Editor/Extensions/NodeExtensions.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.Diagnostics;\nusing System.IO;\nusing System.Linq;\nusing System.Security.Cryptography;\nusing System.Text;\n\nnamespace Figma\n{\n    using Internals;\n\n    [DebuggerStepThrough]\n    internal static class NodeExtensions\n    {\n        #region Methods\n        internal static IEnumerable<IBaseNodeMixin> Flatten(this IBaseNodeMixin root, Func<IBaseNodeMixin, bool> filter = null)\n        {\n            Stack<IBaseNodeMixin> nodes = new();\n            nodes.Push(root);\n\n            if (root is DocumentNode documentNode)\n                foreach (CanvasNode canvasNode in documentNode.children)\n                    nodes.Push(canvasNode);\n\n            for (int depth = 0; depth < Const.maximumAllowedDepthLimit; depth++)\n            {\n                if (nodes.Count == 0)\n                    yield break;\n\n                IBaseNodeMixin node = nodes.Pop();\n\n                if (filter != null && !filter(node))\n                    continue;\n\n                yield return node;\n\n                if (node is IChildrenMixin parent)\n                    foreach (SceneNode child in parent.children)\n                        nodes.Push(child);\n            }\n\n            throw new InvalidOperationException(Const.maximumDepthLimitReachedExceptionMessage);\n        }\n        internal static bool IsRootNode(this IBaseNodeMixin node) => node is DocumentNode or CanvasNode or ComponentNode || node.parent is CanvasNode or ComponentNode;\n        internal static bool IsSvgNode(this IBaseNodeMixin node) => node is LineNode or EllipseNode or RegularPolygonNode or StarNode or VectorNode ||\n                                                                    (node is BooleanOperationNode && node.Flatten().Any(x => x is not BooleanOperationNode && IsVisible(x) && IsSvgNode(x)));\n        internal static bool IsVisible(this IBaseNodeMixin node) => (node is not ISceneNodeMixin scene || scene.visible) && (node.parent == null || node.parent.IsVisible());\n        internal static bool HasImage(this IBaseNodeMixin node) => node is IGeometryMixin geometry && geometry.fills.Any(x => x is ImagePaint);\n\n        internal static void SetParent(this BaseNode node)\n        {\n            switch (node)\n            {\n                case DocumentNode document:\n                    foreach (CanvasNode canvas in document.children)\n                    {\n                        canvas.parent = node;\n                        SetParent(canvas);\n                    }\n\n                    break;\n\n                case IChildrenMixin { children: not null } children:\n                    foreach (SceneNode child in children.children)\n                    {\n                        child.parent = node;\n                        SetParent(child);\n                    }\n\n                    break;\n            }\n        }\n        internal static string GetHash(this GradientPaint gradient)\n        {\n            using SHA1CryptoServiceProvider sha1 = new();\n            using MemoryStream stream = new();\n            using BinaryWriter writer = new(stream);\n\n            writer.Write((int)gradient.type);\n            foreach (ColorStop stop in gradient.gradientStops)\n            {\n                writer.Write(stop.position);\n                writer.Write(stop.color.r);\n                writer.Write(stop.color.g);\n                writer.Write(stop.color.b);\n                writer.Write(stop.color.a);\n            }\n\n            foreach (Vector position in gradient.gradientHandlePositions)\n            {\n                writer.Write(position.x);\n                writer.Write(position.y);\n            }\n\n            byte[] bytes = stream.ToArray();\n            byte[] hashBytes = sha1.ComputeHash(bytes);\n\n            StringBuilder hashBuilder = new();\n            foreach (byte @byte in hashBytes)\n                hashBuilder.Append(@byte.ToString(\"x2\"));\n\n            return hashBuilder.ToString();\n        }\n        internal static string GetFullPath(this IBaseNodeMixin node)\n        {\n            string result = string.Empty;\n\n            for (int depth = 0; depth < Const.maximumAllowedDepthLimit; depth++)\n            {\n                if (node == null)\n                    return result;\n\n                result = string.IsNullOrEmpty(result) ? node.name : node.name + PathExtensions.unixPathSeperator + result;\n                node = node.parent;\n            }\n\n            throw new InvalidOperationException(Const.maximumDepthLimitReachedExceptionMessage);\n        }\n        #endregion\n    }\n}"
  },
  {
    "path": "Editor/Extensions/NodeExtensions.cs.meta",
    "content": "fileFormatVersion: 2\nguid: bc624b728724707428b12ccb11dd0658\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n  defaultReferences: []\n  executionOrder: 0\n  icon: {instanceID: 0}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Editor/Extensions/UssStyleExtensions.cs",
    "content": "using System;\nusing System.Linq;\n\nnamespace Figma\n{\n    using Core.Uss;\n    using Internals;\n    using UnityEngine;\n    using Rect = Internals.Rect;\n\n    static class UssStyleExtension\n    {\n        const bool forceAlphaCorrection = true;\n\n        #region Methods\n        internal static bool HasBorder(this IGeometryMixin geometry) => geometry.strokes.Any(x => x.visible) && geometry.strokeWeight > UssStyle.tolerance;\n        internal static LayoutDouble4 GetBorderWidths(this IGeometryMixin geometry)\n        {\n            if (geometry is null or TextNode || !HasBorder(geometry)) return new LayoutDouble4();\n\n            LayoutDouble4 borders = geometry.individualStrokeWeights != null\n                ? new LayoutDouble4(geometry.individualStrokeWeights.top, geometry.individualStrokeWeights.right, geometry.individualStrokeWeights.bottom, geometry.individualStrokeWeights.left)\n                : new LayoutDouble4(geometry.strokeWeight);\n\n            return borders;\n        }\n        internal static LayoutDouble4 GetOutsideBorderWidths(this IGeometryMixin geometry) => geometry.GetBorderWidths() * geometry.GetOutsideFraction();\n        internal static LayoutDouble4 GetInsideBorderWidths(this IGeometryMixin geometry) => geometry.GetBorderWidths() * (1 - geometry.GetOutsideFraction());\n        internal static Rect GetContentBox(this ILayoutMixin layout)\n        {\n            LayoutDouble4 border = GetInsideBorderWidths(layout as IGeometryMixin);\n            double x = layout.absoluteBoundingBox.x + border.left;\n            double y = layout.absoluteBoundingBox.y + border.top;\n            double width = layout.absoluteBoundingBox.width - border.left - border.right;\n            double height = layout.absoluteBoundingBox.height - border.top - border.bottom;\n            return new Rect(x, y, width, height);\n        }\n        internal static Rect GetBorderBox(this ILayoutMixin layout)\n        {\n            LayoutDouble4 border = GetOutsideBorderWidths(layout as IGeometryMixin);\n            double x = layout.absoluteBoundingBox.x - border.left;\n            double y = layout.absoluteBoundingBox.y - border.top;\n            double width = layout.absoluteBoundingBox.width + border.left + border.right;\n            double height = layout.absoluteBoundingBox.height + border.top + border.bottom;\n            return new Rect(x, y, width, height);\n        }\n        internal static LayoutDouble4 GetCorrectedPadding(this IDefaultFrameMixin frame) => new LayoutDouble4(frame.paddingTop, frame.paddingRight, frame.paddingBottom, frame.paddingLeft) - (frame.strokesIncludedInLayout ? new LayoutDouble4() : GetInsideBorderWidths(frame));\n        internal static RGBA BlendWith(this RGBA foreground, RGBA background)\n        {\n            double blend = background.a * (1.0 - foreground.a);\n            RGBA color = new();\n            color.a = foreground.a + blend;\n\n            const double alphaTolerance = 0.01;\n            if (color.a < alphaTolerance) return new RGBA();\n\n            color.r = (foreground.r * foreground.a + background.r * blend) / color.a;\n            color.g = (foreground.g * foreground.a + background.g * blend) / color.a;\n            color.b = (foreground.b * foreground.a + background.b * blend) / color.a;\n\n            return color;\n        }\n        // Magical formula found by testing different methods. including LinearToGammaSpaceExact(a), 1-GammaToLinearSpaceExact(1-a), pow(a, 1/2.2), pow(a, 1/1.8), 1.0-pow(1-a, 2.2). This method yielded results close to figma with only one layer of blending. However, with multiple semitransparent elements, this alpha correction makes them darker than figma\n        public static double AlphaCorrection(double a) => (forceAlphaCorrection || UnityEditor.PlayerSettings.colorSpace is UnityEngine.ColorSpace.Linear) && a is > 0.0 and < 1.0 ? 1.0f - Mathf.GammaToLinearSpace(1.0f - (float)a) : a;\n        #endregion\n\n        #region Support Methods\n        static double GetOutsideFraction(this IGeometryMixin geometry) => geometry.strokeAlign switch\n        {\n            StrokeAlign.OUTSIDE => 1.0,\n            StrokeAlign.CENTER => 0.5,\n            StrokeAlign.INSIDE => 0.0,\n            _ => throw new NotSupportedException()\n        };\n        #endregion\n    }\n}"
  },
  {
    "path": "Editor/Extensions/UssStyleExtensions.cs.meta",
    "content": "fileFormatVersion: 2\nguid: cd5b7b5e37724678a84ec7eb169a0c3d\ntimeCreated: 1744032663"
  },
  {
    "path": "Editor/Extensions.meta",
    "content": "fileFormatVersion: 2\nguid: 15d902d3df7e2ae40a71e11e3a45e807\nfolderAsset: yes\nDefaultImporter:\n  externalObjects: {}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Editor/Figma.Editor.asmdef",
    "content": "{\n    \"name\": \"Figma.Editor\",\n    \"rootNamespace\": \"Figma.Editor\",\n    \"references\": [\n        \"Unity.VectorGraphics.Editor\",\n        \"AsyncAwaitUtil\",\n        \"CommonUtils\",\n        \"Figma\"\n    ],\n    \"includePlatforms\": [\n        \"Editor\"\n    ]\n}"
  },
  {
    "path": "Editor/Figma.Editor.asmdef.meta",
    "content": "fileFormatVersion: 2\nguid: 5eb4f7c69a0b05842a5bd445fe8970e8\nAssemblyDefinitionImporter:\n  externalObjects: {}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Editor/FigmaDownloader.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing System.Net.Http;\nusing System.Threading;\nusing System.Threading.Tasks;\nusing UnityEngine;\nusing UnityEditor;\n\nnamespace Figma\n{\n    using Core;\n    using Core.Assets;\n    using Internals;\n    using static Internals.Const;\n    using static Internals.PathExtensions;\n\n    internal class FigmaDownloader : Api\n    {\n        #region Consts\n        const int maxConcurrentRequests = 5;\n        const int maxComponentsIdsInOneRequest = 400;\n        #endregion\n\n        #region Fields\n        readonly AssetsInfo assetsInfo;\n\n        string componentsDirectoryPath;\n        string elementsDirectoryPath;\n        string imagesDirectoryPath;\n        string framesDirectoryPath;\n\n        FigmaWriter figmaWriter;\n        NodeMetadata nodeMetadata;\n        NodesRegistry nodesRegistry;\n        StylesPreprocessor stylesPreprocessor;\n        #endregion\n\n        #region Constructors\n        internal FigmaDownloader(string personalAccessToken, string fileKey, AssetsInfo assetsInfo) : base(personalAccessToken, fileKey) => this.assetsInfo = assetsInfo;\n        #endregion\n\n        #region Methods\n        internal async Task Run(bool downloadImages, string uxmlName, IReadOnlyCollection<Type> frames, bool prune, bool filter, bool systemCopyBuffer, int progress, CancellationToken token)\n        {\n            Directory.CreateDirectory(framesDirectoryPath = assetsInfo.GetAbsolutePath(framesDirectoryName));\n            Directory.CreateDirectory(imagesDirectoryPath = assetsInfo.GetAbsolutePath(imagesDirectoryName));\n            Directory.CreateDirectory(elementsDirectoryPath = assetsInfo.GetAbsolutePath(elementsDirectoryName));\n            Directory.CreateDirectory(componentsDirectoryPath = assetsInfo.GetAbsolutePath(componentsDirectoryName));\n\n            int steps = downloadImages ? 5 : 4;\n\n            await assetsInfo.cachedAssets.LoadAsync(token);\n\n            Progress.Report(progress, 1, steps, \"Downloading file\");\n\n            List<string> visibleSceneNodes = new(32);\n\n            if (filter)\n            {\n                Progress.SetDescription(progress, \"Filtering nodes\");\n\n                Data shallowData = await GetAsync<Data>($\"files/{fileKey}?depth=2\", token);\n                shallowData.document.SetParent();\n\n                NodeMetadata shallowMetadata = new(shallowData.document, frames, true, false, true);\n                visibleSceneNodes.AddRange(shallowData.document.children.SelectMany(x => x.children).Where(shallowMetadata.EnabledInHierarchy).Select(node => node.id));\n\n                Progress.SetDescription(progress, string.Empty);\n            }\n\n            string idsString = string.Empty;\n\n            if (visibleSceneNodes.Any())\n                idsString = $\"?ids={string.Join(\",\", visibleSceneNodes)}\";\n\n            Progress.SetDescription(progress, \"Resolving Figma file\");\n            string json = await GetJsonAsync($\"files/{fileKey}{idsString}\", token);\n\n            if (systemCopyBuffer)\n                GUIUtility.systemCopyBuffer = json;\n\n            Progress.Report(progress, 2, steps, \"Parsing Figma file\");\n\n            Data data = await ConvertOnBackgroundAsync<Data>(json, token);\n            data.document.SetParent();\n\n            Progress.SetDescription(progress, \"Creating entities\");\n            nodeMetadata = new NodeMetadata(data.document, frames, filter);\n            nodesRegistry = new NodesRegistry(data, nodeMetadata);\n            stylesPreprocessor = new StylesPreprocessor(data, assetsInfo);\n            figmaWriter = new FigmaWriter(assetsInfo.directory, uxmlName, data, stylesPreprocessor, nodeMetadata, assetsInfo);\n\n            Progress.Report(progress, 3, steps, \"Downloading missing components\");\n            await DownloadDocumentsAsync(token);\n\n            if (downloadImages)\n            {\n                Progress.Report(progress, 4, steps, \"Downloading images\");\n                Progress.SetDescription(progress, \"Writing Gradients\");\n                await WriteGradientsAsync(token);\n                Progress.SetDescription(progress, \"Downloading image fills\");\n                await GetImageFillsAsync(progress, nodesRegistry.ImageFills, token);\n                Progress.SetDescription(progress, $\"Downloading {KnownFormats.png} files\");\n                await GetImageNodesAsync(progress, nodesRegistry.Pngs, UxmlDownloadImages.RenderAsPng, KnownFormats.png, token);\n                Progress.SetDescription(progress, $\"Downloading {KnownFormats.svg} files\");\n                await GetImageNodesAsync(progress, nodesRegistry.Svgs, UxmlDownloadImages.RenderAsSvg, KnownFormats.svg, token);\n                await assetsInfo.cachedAssets.SaveAsync();\n            }\n\n            Progress.SetStepLabel(progress, string.Empty);\n\n            Progress.Report(progress, steps, steps, \"Updating *.uss/*.uxml files\");\n            await figmaWriter.WriteAsync(prune);\n        }\n        internal void CleanUp(bool cleanImages = false)\n        {\n            void CleanDirectory(string directory, string[] filters)\n            {\n                IEnumerable<string> target = filters.SelectMany(filter => GetFiles(directory, filter, SearchOption.AllDirectories))\n                                                    .Where(fileName => !assetsInfo.modifiedContent.Contains(fileName));\n\n                foreach (string file in target)\n                {\n                    FileUtil.DeleteFileOrDirectory(file);\n\n                    string meta = $\"{file}.{KnownFormats.meta}\";\n\n                    if (File.Exists(meta))\n                        FileUtil.DeleteFileOrDirectory(meta);\n                }\n            }\n\n            string[] textExtensions = { $\"*.{KnownFormats.uxml}\", $\"*.{KnownFormats.uss}\" };\n            CleanDirectory(componentsDirectoryPath, textExtensions);\n            CleanDirectory(elementsDirectoryPath, textExtensions);\n            CleanDirectory(framesDirectoryPath, textExtensions);\n\n            if (!cleanImages)\n                return;\n\n            string[] imagesExtensions = { $\"*.{KnownFormats.svg}\", $\"*.{KnownFormats.png}\" };\n            CleanDirectory(imagesDirectoryPath, imagesExtensions);\n        }\n        public void RemoveEmptyDirectories()\n        {\n            void RemoveDirectoryWithMeta(string path)\n            {\n                FileUtil.DeleteFileOrDirectory(path);\n                string meta = $\"{path}.{KnownFormats.meta}\";\n\n                if (File.Exists(meta))\n                    FileUtil.DeleteFileOrDirectory(meta);\n            }\n\n            void RemoveEmptyDirectory(string path, bool recursive)\n            {\n                if (!Directory.Exists(path))\n                    return;\n\n                if (recursive)\n                {\n                    Stack<string> directories = new();\n                    directories.Push(path);\n\n                    for (int depth = 0; depth < Const.maximumAllowedDepthLimit; depth++)\n                    {\n                        if (directories.Count == 0)\n                            return;\n\n                        path = directories.Pop();\n\n                        if (!Directory.EnumerateFileSystemEntries(path).Any())\n                            RemoveDirectoryWithMeta(path);\n                        else\n                            foreach (string subDirectory in Directory.EnumerateDirectories(path))\n                                directories.Push(subDirectory);\n                    }\n\n                    throw new InvalidOperationException(Const.maximumDepthLimitReachedExceptionMessage);\n                }\n\n                if (Directory.EnumerateFileSystemEntries(path).Any())\n                    return;\n\n                RemoveDirectoryWithMeta(path);\n            }\n\n            RemoveEmptyDirectory(componentsDirectoryPath, false);\n            RemoveEmptyDirectory(elementsDirectoryPath, false);\n            RemoveEmptyDirectory(framesDirectoryPath, true);\n            RemoveEmptyDirectory(imagesDirectoryPath, false);\n        }\n        #endregion\n\n        #region Support Methods\n        async Task DownloadDocumentsAsync(CancellationToken token)\n        {\n            async Task<IEnumerable<Nodes.Document>> GetMissingComponentsAsync(IEnumerable<string> components) =>\n                (await Task.WhenAll(components.Chunk(maxComponentsIdsInOneRequest)\n                                              .Select(chunk => GetAsync<Nodes>($\"files/{fileKey}/nodes?ids={string.Join(\",\", chunk.Distinct())}\", token))))\n                .SelectMany(node => node.nodes.Values.Where(value => value != null));\n\n            if (nodesRegistry.MissingComponents.Count > 0)\n                foreach (Nodes.Document value in await GetMissingComponentsAsync(nodesRegistry.MissingComponents))\n                    stylesPreprocessor.AddMissingComponent(value.document, value.styles);\n        }\n        async Task GetImageFillsAsync(int progress, List<IBaseNodeMixin> imageFills, CancellationToken token)\n        {\n            IBaseNodeMixin[] nodes = imageFills.Where(x => nodeMetadata.ShouldDownload(x, UxmlDownloadImages.ImageFills)).ToArray();\n\n            if (!nodes.Any())\n                return;\n\n            Data.Images filesImages = await GetAsync<Data.Images>($\"files/{fileKey}/images\", token);\n            IEnumerable<string> imageRefs = nodes.OfType<IGeometryMixin>().Select(y => y.fills.OfType<ImagePaint>().First().imageRef);\n\n            IEnumerable<KeyValuePair<string, string>> urls = filesImages.meta.images.Where(item => imageRefs.Contains(item.Key));\n            await urls.ForEachParallelAsync(maxConcurrentRequests, x => GetImageAsync(x.Key, x.Value, KnownFormats.png, progress, token), token);\n        }\n        async Task GetImageNodesAsync(int progress, IEnumerable<IBaseNodeMixin> targetNodes, UxmlDownloadImages downloadImages, string extension, CancellationToken token)\n        {\n            IBaseNodeMixin[] nodes = targetNodes.Where(x => nodeMetadata.ShouldDownload(x, downloadImages)).ToArray();\n\n            if (!nodes.Any())\n                return;\n\n            int i = 0;\n            IEnumerable<IGrouping<int, string>> groups = nodes.Select(x => x.id).GroupBy(_ => i++ / 100);\n\n            Task<Images>[] tasks = groups.Select(x => GetAsync<Images>($\"images/{fileKey}?ids={string.Join(\",\", x)}&format={extension}\", token)).ToArray();\n            await Task.WhenAll(tasks);\n\n            IEnumerable<KeyValuePair<string, string>> urls = tasks.SelectMany(x => x.Result.images);\n            await urls.ForEachParallelAsync(maxConcurrentRequests, x => GetImageAsync(x.Key, x.Value, extension, progress, token), token);\n        }\n        async Task GetImageAsync(string nodeID, string url, string extension, int progress, CancellationToken token)\n        {\n            if (string.IsNullOrEmpty(url))\n            {\n                Debug.LogWarning($\"Node {nodeID} does not have any URL for image. Most likely, this node uses a mask.\");\n                return;\n            }\n\n            bool fileExists = assetsInfo.GetAssetPath(nodeID, extension, out string assetPath);\n\n            if (assetsInfo.modifiedContent.Contains(assetsInfo.GetAbsolutePath(assetPath)))\n                return;\n\n            Progress.SetStepLabel(progress, url);\n\n            using HttpRequestMessage request = new(HttpMethod.Get, url);\n\n            if (fileExists && assetsInfo.cachedAssets.Map.TryGetValue(nodeID, out string etag))\n                request.Headers.Add(\"If-None-Match\", $\"\\\"{etag}\\\"\");\n\n            HttpResponseMessage response = await httpClient.SendAsync(request, token);\n\n            bool isResolved = assetsInfo.cachedAssets.Map.ContainsValue(nodeID);\n            if (response.Headers.TryGetValues(\"ETag\", out IEnumerable<string> values))\n                assetsInfo.cachedAssets[nodeID] = values.First().Trim('\"');\n\n            assetsInfo.GetAssetPath(nodeID, extension, out assetPath);\n            string path = assetsInfo.GetAbsolutePath(assetPath);\n            if (assetsInfo.modifiedContent.Contains(path))\n                return;\n\n            assetsInfo.modifiedContent.Add(path);\n\n            if (response.IsSuccessStatusCode && !isResolved)\n            {\n                byte[] bytes = await response.Content.ReadAsByteArrayAsync();\n                if (bytes.Length == 0)\n                {\n                    Debug.LogWarning($\"Response is empty for node={nodeID}, url={url}\");\n                    if (extension == KnownFormats.svg)\n                        await File.WriteAllTextAsync(path, InvalidSvg, token);\n                    else\n                        await File.WriteAllBytesAsync(path, InvalidPng, token);\n                }\n                else\n                {\n                    try\n                    {\n                        await File.WriteAllBytesAsync(path, bytes, token);\n                    }\n                    catch (Exception exception)\n                    {\n                        Debug.LogException(exception);\n                    }\n                }\n            }\n        }\n        async Task WriteGradientsAsync(CancellationToken token)\n        {\n            foreach ((string key, GradientPaint gradient) in nodesRegistry.Gradients)\n            {\n                assetsInfo.GetAssetPath(key, KnownFormats.svg, out string relativePath);\n                string xmlPath = assetsInfo.GetAbsolutePath(relativePath);\n                using GradientWriter writer = new(xmlPath);\n                await writer.WriteAsync(gradient, token);\n                assetsInfo.modifiedContent.Add(xmlPath);\n            }\n        }\n        #endregion\n    }\n}"
  },
  {
    "path": "Editor/FigmaDownloader.cs.meta",
    "content": "fileFormatVersion: 2\nguid: 51ab4c8a6a174660b9a8bff7530d8631\ntimeCreated: 1695908086"
  },
  {
    "path": "Editor/FigmaWriter.cs",
    "content": "using System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing System.Threading.Tasks;\n\n// ReSharper disable UnusedMember.Local\n// ReSharper disable UnusedParameter.Local\n\n#pragma warning disable S1144 // Unused private types or members should be removed\n\nnamespace Figma\n{\n    using Core;\n    using Core.Assets;\n    using Core.Uss;\n    using Core.Uxml;\n    using Internals;\n    using static Internals.Const;\n    using static Internals.PathExtensions;\n\n    internal sealed class FigmaWriter\n    {\n        #region Fields\n        readonly string directory;\n        readonly string fileName;\n        readonly string ussPath;\n        readonly Data data;\n        readonly NodeMetadata nodeMetadata;\n        readonly AssetsInfo assetsInfo;\n        readonly StylesPreprocessor stylesPreprocessor;\n        #endregion\n\n        #region Properties\n        DocumentNode Document => data.document;\n        #endregion\n\n        #region Constructors\n        internal FigmaWriter(string directory, string fileName, Data data, StylesPreprocessor stylesPreprocessor, NodeMetadata nodeMetadata, AssetsInfo assetsInfo)\n        {\n            this.directory = directory;\n            this.fileName = fileName;\n            this.data = data;\n            this.nodeMetadata = nodeMetadata;\n            this.assetsInfo = assetsInfo;\n            this.stylesPreprocessor = stylesPreprocessor;\n\n            ussPath = CombinePath(directory, $\"{fileName}.{KnownFormats.uss}\");\n        }\n        #endregion\n\n        #region Methods\n        internal async Task WriteAsync(bool overrideGlobal = false)\n        {\n            RootNodes rootNodes = new(data, nodeMetadata);\n            // We do need this, since the Data.componentSets do not contain updated names.\n            Dictionary<string, ComponentSetNode> componentSets = rootNodes.ComponentSets\n                                                                          .OrderBy(x => x.id) // Ordering to avoid index confusion, since order in the Collection could vary from one request to another.\n                                                                          .ToArray()\n                                                                          .IndexRedundantNames(x => x.name,\n                                                                                               (componentSet, postfix) => componentSet.name += postfix,\n                                                                                               index => index == 0 ? string.Empty : \"-\" + index)\n                                                                          .ToDictionary(x => x.id);\n\n            KeyValuePair<IBaseNodeMixin, UssStyle>[] nodeStyleFiltered = stylesPreprocessor.NodeStyleMap.Where(x => x.Key.IsVisible() && (nodeMetadata.EnabledInHierarchy(x.Key) || x.Key is ComponentSetNode)).ToArray();\n            UssStyle[] nodeStyleStatelessFiltered = nodeStyleFiltered.Select(x => x.Value).ToArray();\n            UssStyle[] globalStaticStyles = stylesPreprocessor.Styles.Select(x => x.style).Where(x => nodeStyleStatelessFiltered.Any(y => y.DoesInherit(x))).ToArray();\n\n            if (overrideGlobal)\n            {\n                await using UssWriter globalUssWriter = new(directory, ussPath);\n                globalUssWriter.Write(UssStyle.overrideClass);\n                globalUssWriter.Write(UssStyle.viewportClass);\n                globalUssWriter.Write(globalStaticStyles.ToArray().IndexRedundantNames(x => x.Name, (style, postfix) => style.Name += postfix, index => \"-\" + (index + 1).NumberToWords()));\n            }\n\n            // Writing UXML files\n            UxmlBuilder uxmlBuilder = new(data, nodeMetadata, ussPath, stylesPreprocessor);\n            Dictionary<string, IReadOnlyList<string>> framesPaths = new(rootNodes.Frames.Count);\n\n            foreach (CanvasNode canvasNode in rootNodes.Canvases)\n                framesPaths.Add(canvasNode.name, new List<string>());\n\n            List<Task> tasks = new(rootNodes.Frames.Count + rootNodes.ComponentSets.Count + rootNodes.Elements.Count);\n            tasks.AddRange(rootNodes.Frames.Select(x => Task.Run(() => WriteFrame(uxmlBuilder, framesPaths, componentSets, x))));\n            tasks.AddRange(rootNodes.ComponentSets.Select(x => Task.Run(() => WriteComponentSet(uxmlBuilder, x))));\n            tasks.AddRange(rootNodes.Elements.Select(x => Task.Run(() => WriteTemplate(uxmlBuilder, x))));\n\n            await Task.WhenAll(tasks);\n\n            // Creating main UXML document\n            if (overrideGlobal)\n                uxmlBuilder.CreateDocument(directory, fileName, data.document, framesPaths);\n        }\n        #endregion\n\n        #region Support Methods\n        void WriteFrame(UxmlBuilder uxmlBuilder, Dictionary<string, IReadOnlyList<string>> framesPaths, Dictionary<string, ComponentSetNode> componentSets, FrameNode frameNode)\n        {\n            Dictionary<string, string> templates = new();\n\n            void FindTemplates(BaseNode root)\n            {\n                Stack<BaseNode> nodes = new();\n                nodes.Push(root);\n\n                for (int depth = 0; depth < Const.maximumAllowedDepthLimit; depth++)\n                {\n                    if (nodes.Count == 0)\n                        return;\n\n                    BaseNode node = nodes.Pop();\n\n                    if (!node.IsVisible() || !nodeMetadata.EnabledInHierarchy(node))\n                        continue;\n\n                    if (node is InstanceNode instanceNode)\n                    {\n                        Component component = data.components[instanceNode.componentId];\n\n                        if (component == null || component.remote || string.IsNullOrEmpty(component.componentSetId))\n                            continue;\n\n                        Component componentSet = data.componentSets[component.componentSetId];\n\n                        if (componentSet == null || componentSet.remote)\n                            continue;\n\n                        string template = componentSets[component.componentSetId].name;\n                        templates[template] = CombinePath(directory, componentsDirectoryName, $\"{template}.{KnownFormats.uxml}\");\n                    }\n                    else if (nodeMetadata.GetTemplate(node) is (_, { } template) && template.NotNullOrEmpty())\n                        templates[template] = CombinePath(directory, elementsDirectoryName, $\"{template}.{KnownFormats.uxml}\");\n\n                    if (node is DefaultFrameNode frameNode)\n                        foreach (SceneNode child in frameNode.children)\n                            nodes.Push(child);\n                }\n\n                throw new System.InvalidOperationException(Const.maximumDepthLimitReachedExceptionMessage);\n            }\n\n            string rootDirectory = CombinePath(directory, framesDirectoryName, frameNode.parent.name);\n\n            if (!Directory.Exists(rootDirectory))\n                Directory.CreateDirectory(rootDirectory);\n\n            using UssWriter ussWriter = new(directory, CombinePath(rootDirectory, $\"{frameNode.name}.{KnownFormats.uss}\"));\n            ussWriter.Write(stylesPreprocessor.GetStyles(frameNode).IndexRedundantNames(x => x.Name, (style, postfix) => style.Name += postfix, index => \"-\" + (index + 1).NumberToWords()));\n\n            FindTemplates(frameNode);\n\n            string uxmlPath = uxmlBuilder.CreateFrame(rootDirectory, new[] { ussPath, ussWriter.Path }, templates, frameNode);\n            framesPaths[frameNode.parent.name].As<List<string>>().Add(uxmlPath);\n\n            assetsInfo.AddModifiedFiles(uxmlPath, ussWriter.Path);\n            templates.Clear();\n        }\n        void WriteComponentSet(UxmlBuilder uxmlBuilder, ComponentSetNode componentSet)\n        {\n            using UssWriter ussWriter = new(directory, CombinePath(directory, componentsDirectoryName, $\"{componentSet.name}.{KnownFormats.uss}\"));\n            ussWriter.Write(stylesPreprocessor.GetStyles(componentSet).IndexRedundantNames(x => x.Name, (style, postfix) => style.Name += postfix, index => \"-\" + (index + 1).NumberToWords()));\n\n            string uxmlPath = uxmlBuilder.CreateComponentSet(CombinePath(directory, componentsDirectoryName), new[] { ussPath, ussWriter.Path }, componentSet);\n            assetsInfo.AddModifiedFiles(uxmlPath, ussWriter.Path);\n        }\n        void WriteTemplate(UxmlBuilder uxmlBuilder, (DefaultShapeNode element, string template) node)\n        {\n            (bool isHash, string hashedTemplates) = nodeMetadata.GetTemplate(node.element);\n\n            using UssWriter ussWriter = new(directory, CombinePath(directory, elementsDirectoryName, $\"{(isHash ? hashedTemplates : node.template)}.{KnownFormats.uss}\"));\n            ussWriter.Write(stylesPreprocessor.GetStyles(node.element).IndexRedundantNames(x => x.Name, (style, postfix) => style.Name += postfix, index => \"-\" + (index + 1).NumberToWords()));\n\n            string uxmlPath = uxmlBuilder.CreateElement(CombinePath(directory, elementsDirectoryName), new[] { ussPath, ussWriter.Path }, node.element, node.template);\n            assetsInfo.AddModifiedFiles(uxmlPath, ussWriter.Path);\n        }\n        #endregion\n    }\n}"
  },
  {
    "path": "Editor/FigmaWriter.cs.meta",
    "content": "fileFormatVersion: 2\nguid: cbfef092900681d478f7beff22ae8f28\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n  defaultReferences: []\n  executionOrder: 0\n  icon: {instanceID: 0}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Editor/Inspector/AuthTest.cs",
    "content": "using System.Threading;\nusing System.Threading.Tasks;\n\nnamespace Figma.Inspectors\n{\n    using Internals;\n\n    internal class AuthTest : Api\n    {\n        #region Properties\n        public Me me { get; private set; }\n        public bool IsAuthenticated => me != null && string.IsNullOrEmpty(me.err) && me.email.Contains(\"@\");\n        #endregion\n\n        #region Constructors\n        internal AuthTest(string personalAccessToken = null) : base(personalAccessToken, null) { }\n        #endregion\n\n        #region Methods\n        internal async Task AuthAsync() => me = await GetAsync<Me>(nameof(me), CancellationToken.None);\n        #endregion\n    }\n}"
  },
  {
    "path": "Editor/Inspector/AuthTest.cs.meta",
    "content": "fileFormatVersion: 2\nguid: b2f4d6368ca84ba2860d8499592a9019\ntimeCreated: 1696830428"
  },
  {
    "path": "Editor/Inspector/FigmaInspector.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Diagnostics;\nusing System.Diagnostics.CodeAnalysis;\nusing System.IO;\nusing System.Linq;\nusing System.Reflection;\nusing System.Text.RegularExpressions;\nusing System.Threading;\nusing System.Threading.Tasks;\nusing UnityEditor;\nusing UnityEngine;\nusing UnityEngine.UIElements;\nusing Debug = UnityEngine.Debug;\nusing PackageInfo = UnityEditor.PackageManager.PackageInfo;\n\n// ReSharper disable MemberCanBeMadeStatic.Local\n\nnamespace Figma.Inspectors\n{\n    using Core.Assets;\n    using Attributes;\n    using Internals;\n    using static Styles;\n\n    [CustomEditor(typeof(Figma), true)]\n    [SuppressMessage(\"Roslynator\", \"RCS1213:Remove unused member declaration.\")]\n    public class FigmaInspector : Editor\n    {\n        #region Const\n        static readonly Regex regex = new(@\"[^/\\\\]+$\", RegexOptions.Compiled);\n        static readonly string patKey = $\"{nameof(Figma)}/{nameof(PersonalAccessToken)}\";\n        #endregion\n\n        #region Fields\n        SerializedProperty fileKey;\n        SerializedProperty filter;\n        SerializedProperty reorder;\n        SerializedProperty fontDirectories;\n        SerializedProperty waitFrameBeforeRebuild;\n\n        UIDocument document;\n        new Figma target;\n        Texture2D icon;\n\n        Dictionary<MonoBehaviour, bool> selection;\n        bool updating;\n        bool resolvingName;\n        string username;\n        int progressId;\n\n        string searchBar;\n        #endregion\n\n        #region Properties\n        static string PersonalAccessToken { get => EditorPrefs.GetString(patKey, string.Empty); set => EditorPrefs.SetString(patKey, value); }\n        #endregion\n\n        #region Methods\n        void Awake() => icon = AssetDatabase.LoadAssetAtPath<Texture2D>($\"{PackageInfo.FindForAssembly(typeof(Figma).Assembly)?.assetPath}/Editor/Assets/icon.png\");\n        void OnEnable()\n        {\n            target = (Figma)base.target;\n            EditorGUIUtility.SetIconForObject(target, icon);\n\n            fileKey = serializedObject.FindProperty(nameof(fileKey));\n            filter = serializedObject.FindProperty(nameof(filter));\n            reorder = serializedObject.FindProperty(nameof(reorder));\n            fontDirectories = serializedObject.FindProperty(nameof(fontDirectories));\n            waitFrameBeforeRebuild = serializedObject.FindProperty(nameof(waitFrameBeforeRebuild));\n\n            document = target.GetComponent<UIDocument>();\n            selection = target.GetComponentsInChildren<IRootElement>().Cast<MonoBehaviour>().ToDictionary(key => key, _ => true);\n        }\n        public override void OnInspectorGUI()\n        {\n            serializedObject.Update();\n            DrawPersonalAccessTokenGUI();\n            DrawAssetGUI();\n            DrawFramesView();\n            DrawProperties();\n            serializedObject.ApplyModifiedProperties();\n        }\n\n        void DrawPersonalAccessTokenGUI()\n        {\n            // ReSharper disable once AsyncVoidMethod\n            async void GetNameAsync(string personalAccessToken)\n            {\n                resolvingName = true;\n                using AuthTest auth = new(personalAccessToken);\n                await auth.AuthAsync();\n\n                if (!auth.IsAuthenticated)\n                    return;\n\n                username = auth.me.handle;\n                PersonalAccessToken = personalAccessToken;\n                resolvingName = false;\n            }\n\n            using (new EditorGUILayout.HorizontalScope(GUI.skin.box))\n            {\n                if (PersonalAccessToken.NotNullOrEmpty())\n                {\n                    if (username.NullOrEmpty() && !resolvingName)\n                        GetNameAsync(PersonalAccessToken);\n\n                    EditorGUILayout.LabelField(EditorGUIUtility.TrIconContent(LoggedInIcon), GUILayout.Width(20));\n                    EditorGUILayout.LabelField(\"You're logged in as\", GUILayout.Width(108));\n                    EditorGUILayout.LabelField(username, EditorStyles.boldLabel);\n\n                    if (GUILayout.Button(new GUIContent(LogOutIcon, \"Log Out\"), GUILayout.Width(25), GUILayout.Height(25)))\n                        PersonalAccessToken = string.Empty;\n                }\n                else\n                {\n                    EditorGUILayout.PrefixLabel(\"Figma PAT\");\n\n                    string token = EditorGUILayout.TextField(PersonalAccessToken);\n\n                    if (GUI.changed)\n                        GetNameAsync(token);\n                }\n            }\n\n            if (PersonalAccessToken.NotNullOrEmpty())\n                return;\n\n            GUIStyle richTextHelpBox = new(EditorStyles.helpBox) { richText = true };\n\n            if (GUILayout.Button(EditorGUIUtility.TrTextContentWithIcon(\"You have to enter your personal access token in order to update.\\n\\n\" +\n                                                                        \"You can get your token at <a href=https://figma.com>https://figma.com</a>\",\n                                                                        \"console.warnicon\"), richTextHelpBox))\n                Application.OpenURL(\"https://www.figma.com\");\n        }\n        void DrawAssetGUI()\n        {\n            // ReSharper disable once AsyncVoidMethod\n            async void Update(bool downloadImages, bool pickDirectory)\n            {\n                try\n                {\n                    updating = true;\n\n                    string[] fontDirectories = new string[this.fontDirectories.arraySize];\n\n                    for (int index = 0; index < this.fontDirectories.arraySize; index++)\n                        fontDirectories[index] = this.fontDirectories.GetArrayElementAtIndex(index).stringValue;\n\n                    Type[] frames = selection.Where(x => x.Value).Select(x => x.Key.GetType()).ToArray();\n                    bool prune = selection.All(x => x.Value);\n\n                    document.visualTreeAsset = pickDirectory ? null : document.visualTreeAsset;\n\n                    await UpdateWithProgressAsync(document, target, frames, prune, fileKey.stringValue, downloadImages, fontDirectories, Event.current.modifiers == EventModifiers.Control);\n                }\n                finally\n                {\n                    updating = false;\n                }\n            }\n\n            using EditorGUILayout.VerticalScope __ = new(GUI.skin.box);\n            EditorGUILayout.PropertyField(fileKey);\n\n            VisualTreeAsset visualTreeAsset = document.visualTreeAsset;\n\n            using (new EditorGUI.DisabledScope(true))\n                EditorGUILayout.ObjectField(\"Asset\", visualTreeAsset, typeof(VisualTreeAsset), true);\n\n            if (string.IsNullOrEmpty(PersonalAccessToken))\n                return;\n\n            using (new EditorGUILayout.HorizontalScope())\n            {\n                const string downloadTooltip = \"Hold `Ctrl` to copy 'figma.json' into your clipboard\";\n\n                if (updating)\n                {\n                    using (new EditorGUI.DisabledScope(true))\n                        GUILayout.Button(\"Updating...\");\n                }\n                else if (selection.Any(x => x.Value))\n                {\n                    bool update = GUILayout.Button(new GUIContent(nameof(Update), DocumentsOnlyIcon, downloadTooltip), GUILayout.Height(20));\n                    bool downloadImages = GUILayout.Button(new GUIContent(\"Update with Images\", DocumentWithImagesIcon, downloadTooltip), GUILayout.Width(184), GUILayout.Height(20));\n                    bool resetTargetUxml = GUILayout.Button(new GUIContent(DirectoryIcon), GUILayout.Width(36));\n\n                    if (resetTargetUxml && EditorUtility.DisplayDialog(\"Figma Updater\", \"Do you want to update images as well?\", \"Yes\", \"No\"))\n                        downloadImages = true;\n\n                    if (update || downloadImages || resetTargetUxml)\n                    {\n                        Update(downloadImages, resetTargetUxml);\n                        GUIUtility.ExitGUI();\n                    }\n                }\n            }\n\n            if (selection.Any(x => !x.Value) && selection.Any(x => x.Value))\n                EditorGUILayout.HelpBox(\"Selection mode does not clean up unused content. In order to get rid of unused content, \\\"Select All\\\" and \\\"Update\\\"\", MessageType.Warning);\n\n            if (selection.Count > 0 && selection.All(x => !x.Value))\n                EditorGUILayout.HelpBox(\"Nothing is selected for Update.\", MessageType.Error);\n        }\n        void DrawFramesView()\n        {\n            if (!document || !document.visualTreeAsset)\n            {\n                EditorGUILayout.HelpBox(\"'UIDocument' not found or 'SourceAsset' is not referenced.\", MessageType.Error);\n                return;\n            }\n\n            using GUILayout.VerticalScope _ = new(GUI.skin.box);\n\n            searchBar = EditorGUILayout.TextField(searchBar, EditorStyles.toolbarSearchField);\n\n            bool clear = selection.All(x => x.Value);\n\n            using (new GUILayout.HorizontalScope())\n            {\n                GUILayout.FlexibleSpace();\n\n                if (GUILayout.Button(new GUIContent($\"{(clear ? \"Clear\" : \"Select All\")} ({selection.Sum(x => x.Value.ToBit())})\"), GUILayout.Width(100)))\n                    foreach (MonoBehaviour frame in selection.Keys.ToArray())\n                        selection[frame] = !clear;\n            }\n\n            foreach (MonoBehaviour frame in selection.Keys.OrderBy(x => x.GetType().GetCustomAttribute<UxmlAttribute>().Root))\n            {\n                Type elementType = frame.GetType();\n                UxmlAttribute uxml = elementType.GetCustomAttribute<UxmlAttribute>();\n\n                if (uxml is null || (!string.IsNullOrWhiteSpace(searchBar) && !uxml.Root.ToLower().Contains(searchBar.ToLower())))\n                    continue;\n\n                using (new EditorGUILayout.HorizontalScope())\n                {\n                    using (new EditorGUI.DisabledGroupScope(!selection[frame]))\n                        EditorGUILayout.LabelField(new GUIContent(uxml.Root, uxml.Preserve.Any() ? $\"Preserves {uxml.Preserve.Aggregate((x, y) => $\"{x} {y}\")}\" : null),\n                                                   uxml.Preserve.Any() ? EditorStyles.boldLabel : EditorStyles.label,\n                                                   GUILayout.Width(EditorGUIUtility.labelWidth));\n\n                    using (new EditorGUI.DisabledGroupScope(true))\n                        EditorGUI.ObjectField(EditorGUILayout.GetControlRect(), frame, typeof(MonoBehaviour), false);\n\n                    selection[frame] = EditorGUILayout.Toggle(selection[frame], GUILayout.Width(24));\n                }\n            }\n        }\n        void DrawProperties()\n        {\n            using EditorGUILayout.VerticalScope scope = new(GUI.skin.box);\n            EditorGUILayout.PropertyField(fontDirectories, new GUIContent(\"Additional Fonts Directories\"));\n            EditorGUILayout.PropertyField(reorder, new GUIContent(\"De-root and Re-order Hierarchy\"));\n            EditorGUILayout.PropertyField(filter, new GUIContent(\"Filter by Path\"));\n            EditorGUILayout.PropertyField(waitFrameBeforeRebuild, new GUIContent(\"Wait Frame Before Rebuild\"));\n        }\n        #endregion\n\n        #region Support Methods\n        static async Task UpdateWithProgressAsync(UIDocument document, Figma figma, IReadOnlyList<Type> frames, bool prune, string fileKey, bool downloadImages, IReadOnlyList<string> fontDirectories, bool systemCopyBuffer)\n        {\n            string GetAssetPath()\n            {\n                if (document.visualTreeAsset)\n                    return AssetDatabase.GetAssetPath(document.visualTreeAsset);\n\n                string path = EditorUtility.SaveFilePanel($\"Save {nameof(VisualTreeAsset)}\", Application.dataPath, document.name, KnownFormats.uxml);\n\n                if (path.NotNullOrEmpty() && Path.GetFullPath(path).StartsWith(Path.GetFullPath(Application.dataPath)))\n                    return path;\n\n                PackageInfo packageInfo = PackageInfo.GetAllRegisteredPackages().First(x => Path.GetFullPath(path).StartsWith(Path.GetFullPath(x.resolvedPath)));\n\n                return PathExtensions.CombinePath(packageInfo.assetPath, Path.GetFullPath(path).Replace(Path.GetFullPath(packageInfo.resolvedPath), string.Empty));\n            }\n\n            (string directory, string relativeDirectory, string product, string uxmlName) = GetDirectoryAndRelativeDirectory(GetAssetPath());\n            uxmlName = Path.GetFileNameWithoutExtension(uxmlName);\n\n            if (directory.NullOrEmpty() || relativeDirectory.NullOrEmpty())\n                return;\n\n            Stopwatch stopwatch = Stopwatch.StartNew();\n\n            string display = $\"Figma {product}\" + (downloadImages ? \" (Images)\" : string.Empty);\n            int progress = Progress.Start(display, null, Progress.Options.Managed);\n\n            using CancellationTokenSource cancellationToken = new();\n\n            try\n            {\n                Progress.RegisterCancelCallback(progress, () =>\n                {\n                    // ReSharper disable once AccessToDisposedClosure\n                    cancellationToken.Cancel();\n                    return true;\n                });\n\n                AssetDatabase.StartAssetEditing();\n                AssetsInfo info = new(directory, relativeDirectory, uxmlName, fontDirectories);\n                using FigmaDownloader figmaDownloader = new(PersonalAccessToken, fileKey, info);\n\n                try\n                {\n                    await figmaDownloader.Run(downloadImages, uxmlName, frames, prune, figma.Filter, systemCopyBuffer, progress, cancellationToken.Token);\n\n                    if (prune)\n                        figmaDownloader.CleanUp(downloadImages);\n                }\n                finally\n                {\n                    if (prune)\n                        figmaDownloader.RemoveEmptyDirectories();\n                }\n\n                document.visualTreeAsset = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>(PathExtensions.CombinePath(info.relativeDirectory, $\"{uxmlName}.{KnownFormats.uxml}\"));\n                stopwatch.Stop();\n                EditorUtility.SetDirty(document.visualTreeAsset);\n\n                Debug.Log($\"{display} is <color={SuccessColor}>updated successfully</color> in {(float)stopwatch.ElapsedMilliseconds / 1000}s\");\n                Progress.Finish(progress);\n            }\n            catch (Exception exception)\n            {\n                Progress.Finish(progress, Progress.Status.Failed);\n\n                if (!exception.Message.Contains(\"404\") || exception is not OperationCanceledException)\n                    throw;\n\n                Debug.LogException(exception);\n            }\n            finally\n            {\n                Progress.UnregisterCancelCallback(progress);\n\n                stopwatch.Reset();\n\n                AssetDatabase.StopAssetEditing();\n                AssetDatabase.Refresh();\n            }\n        }\n        static (string directory, string relativeDirectory, string product, string name) GetDirectoryAndRelativeDirectory(string assetPath)\n        {\n            if (!assetPath.StartsWith(\"Packages\"))\n                return (Path.GetDirectoryName(assetPath),\n                        Path.GetRelativePath(Directory.GetCurrentDirectory(), Path.GetDirectoryName(assetPath)),\n                        Application.productName,\n                        regex.Match(assetPath).Value);\n\n            PackageInfo packageInfo = PackageInfo.FindForAssetPath(assetPath);\n            return (packageInfo.resolvedPath + Path.GetDirectoryName(assetPath.Replace(packageInfo.assetPath, string.Empty)),\n                    Path.GetDirectoryName(assetPath),\n                    packageInfo.displayName,\n                    regex.Match(assetPath).Value);\n        }\n        #endregion\n    }\n}"
  },
  {
    "path": "Editor/Inspector/FigmaInspector.cs.meta",
    "content": "fileFormatVersion: 2\nguid: 79908b73109533b4d87fced3ad4caee7\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n  defaultReferences: []\n  executionOrder: 0\n  icon: {instanceID: 0}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Editor/Inspector/Styles.cs",
    "content": "using UnityEditor;\nusing UnityEngine;\n\nnamespace Figma.Inspectors\n{\n    public static class Styles\n    {\n        internal static readonly string SuccessColor = EditorGUIUtility.isProSkin ? \"#00ff00\" : \"#00aa00\";\n\n        static readonly string prefix = EditorGUIUtility.isProSkin ? \"d_\" : string.Empty;\n\n        internal static readonly Texture DirectoryIcon = EditorGUIUtility.IconContent($\"{prefix}Project\").image;\n        internal static readonly Texture LoggedInIcon = EditorGUIUtility.IconContent(\"TestPassed\").image;\n        internal static readonly Texture LogOutIcon = EditorGUIUtility.IconContent($\"{prefix}Import\").image;\n        internal static readonly Texture DocumentsOnlyIcon = EditorGUIUtility.IconContent($\"{prefix}Refresh@2x\").image;\n        internal static readonly Texture DocumentWithImagesIcon = EditorGUIUtility.IconContent($\"{prefix}RawImage Icon\").image;\n    }\n}"
  },
  {
    "path": "Editor/Inspector/Styles.cs.meta",
    "content": "fileFormatVersion: 2\nguid: 54fcfd1c480a4ad290dcae61139be13f\ntimeCreated: 1739275722"
  },
  {
    "path": "Editor/Inspector.meta",
    "content": "fileFormatVersion: 2\nguid: ee4e1dc47f503814581a191eb139e1b8\nfolderAsset: yes\nDefaultImporter:\n  externalObjects: {}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Editor/Interface/Const.cs",
    "content": "namespace Figma.Internals\n{\n    public static class Const\n    {\n        // Http API target\n        public const string api = \"https://api.figma.com/v1\";\n\n        // Directories\n        public const string fontsDirectoryName = \"Fonts\";\n        public const string framesDirectoryName = \"Frames\";\n        public const string imagesDirectoryName = nameof(Images);\n        public const string elementsDirectoryName = \"Elements\";\n        public const string componentsDirectoryName = \"Components\";\n\n        // Uxml\n        public const string uxmlNamespace = \"UnityEngine.UIElements\";\n\n        // Fallback written data\n        /// <summary>\n        /// Magenta colored image with resolution 2x2.\n        /// </summary>\n        public static readonly byte[] InvalidPng =\n        {\n            0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A, // PNG signature\n            // IHDR chunk\n            0x00, 0x00, 0x00, 0x0D, 0x49, 0x48, 0x44, 0x52,\n            0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02,\n            0x08, 0x06, 0x00, 0x00, 0x00, 0xF4, 0x78, 0x5A, 0xEE,\n            // IDAT chunk (compressed image data)\n            0x00, 0x00, 0x00, 0x11, 0x49, 0x44, 0x41, 0x54,\n            0x78, 0x9C, 0x63, 0xF8, 0xCF, 0xC0, 0xC0, 0xC0,\n            0xF0, 0x0F, 0x04, 0x00, 0x04, 0x00, 0x01, 0xF3,\n            0x0D, 0x0E, 0x43,\n            // IEND chunk\n            0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4E, 0x44,\n            0xAE, 0x42, 0x60, 0x82\n        };\n        /// <summary>\n        /// Warning sign in SVG.\n        /// </summary>\n        public const string InvalidSvg = @\"<svg width=\"\"128\"\" height=\"\"128\"\" viewBox=\"\"0 0 128 128\"\" xmlns=\"\"http://www.w3.org/2000/svg\"\">\n\t<defs>\n\t\t<linearGradient id=\"\"gradYellow\"\" x1=\"\"0%\"\" y1=\"\"0%\"\" x2=\"\"0%\"\" y2=\"\"100%\"\">\n\t\t\t<stop offset=\"\"0%\"\" stop-color=\"\"#FFEA00\"\" />\n\t\t\t<stop offset=\"\"100%\"\" stop-color=\"\"#FFC400\"\" />\n\t\t</linearGradient>\n\n\t\t<filter id=\"\"shadow\"\" x=\"\"-20%\"\" y=\"\"-20%\"\" width=\"\"140%\"\" height=\"\"140%\"\">\n\t\t\t<feDropShadow dx=\"\"4\"\" dy=\"\"4\"\" stdDeviation=\"\"4\"\" flood-color=\"\"rgba(0,0,0,0.5)\"\" />\n\t\t</filter>\n\t</defs>\n\t<polygon points=\"\"64,8 120,120 8,120\"\"\n\t\tfill=\"\"url(#gradYellow)\"\" stroke=\"\"#FFF\"\" stroke-width=\"\"4\"\"\n\t\tfilter=\"\"url(#shadow)\"\" />\n\t<line x1=\"\"64\"\" y1=\"\"40\"\" x2=\"\"64\"\" y2=\"\"80\"\"\n\t\tstroke=\"\"#FFF\"\" stroke-width=\"\"6\"\" stroke-linecap=\"\"round\"\" />\n\t<circle cx=\"\"64\"\" cy=\"\"100\"\" r=\"\"6\"\" fill=\"\"#FFF\"\" />\n</svg>\";\n    }\n\n    public static class KnownFormats\n    {\n        public const string png = nameof(png);\n        public const string svg = nameof(svg);\n        public const string ttf = nameof(ttf);\n        public const string otf = nameof(otf);\n        public const string asset = nameof(asset);\n        public const string uxml = nameof(uxml);\n        public const string uss = nameof(uss);\n        public const string json = nameof(json);\n        public const string meta = nameof(meta);\n    }\n}"
  },
  {
    "path": "Editor/Interface/Const.cs.meta",
    "content": "fileFormatVersion: 2\nguid: e79ce7b985a449c58c07592648c530b7\ntimeCreated: 1728029275"
  },
  {
    "path": "Editor/Interface/Enums.cs",
    "content": "namespace Figma\n{\n    enum Unit\n    {\n        Default,\n        None,\n        Initial,\n        Auto,\n        Pixel,\n        Degrees,\n        Percent\n    }\n\n    enum Align\n    {\n        Auto,\n        FlexStart,\n        FlexEnd,\n        Center,\n        Stretch\n    }\n\n    enum FlexDirection\n    {\n        Row,\n        RowReverse,\n        Column,\n        ColumnReverse\n    }\n\n    enum FlexWrap\n    {\n        Nowrap,\n        Wrap,\n        WrapReverse\n    }\n\n    enum JustifyContent\n    {\n        FlexStart,\n        FlexEnd,\n        Center,\n        SpaceBetween,\n        SpaceAround\n    }\n\n    enum Position\n    {\n        Absolute,\n        Relative\n    }\n\n    enum Visibility\n    {\n        Visible,\n        Hidden\n    }\n\n    enum OverflowClip\n    {\n        PaddingBox,\n        ContentBox\n    }\n\n    enum Display\n    {\n        Flex,\n        None\n    }\n\n    enum FontStyle\n    {\n        Normal,\n        Italic,\n        Bold,\n        BoldAndItalic\n    }\n\n    enum TextAlign\n    {\n        UpperLeft,\n        MiddleLeft,\n        LowerLeft,\n        UpperCenter,\n        MiddleCenter,\n        LowerCenter,\n        UpperRight,\n        MiddleRight,\n        LowerRight\n    }\n\n    enum EasingFunction\n    {\n        EaseIn,\n        EaseOut,\n        EaseInAndOut,\n        Linear,\n        Slow,\n        CustomSpring\n    }\n\n    enum Wrap\n    {\n        Normal,\n        Nowrap,\n    }\n\n    public enum ElementType\n    {\n        None,\n\n        //Base elements\n        VisualElement,\n        BindableElement,\n\n        //Utilities\n        Box,\n        TextElement,\n        Label,\n        Image,\n        IMGUIContainer,\n        Foldout,\n\n        //Templates\n        Template,\n        Instance,\n        TemplateContainer,\n\n        //Controls\n        Button,\n        RepeatButton,\n        Toggle,\n        Scroller,\n        Slider,\n        SliderInt,\n        MinMaxSlider,\n        EnumField,\n        MaskField,\n        LayerField,\n        LayerMaskField,\n        TagField,\n        ProgressBar,\n\n        //Text input\n        TextField,\n        IntegerField,\n        LongField,\n        FloatField,\n        DoubleField,\n        Vector2Field,\n        Vector2IntField,\n        Vector3Field,\n        Vector3IntField,\n        Vector4Field,\n        RectField,\n        RectIntField,\n        BoundsField,\n        BoundsIntField,\n\n        //Complex widgets\n        PropertyField,\n        PropertyControlInt,\n        PropertyControlLong,\n        PropertyControlFloat,\n        PropertyControlDouble,\n        PropertyControlString,\n        ColorField,\n        CurveField,\n        GradientField,\n        ObjectField,\n\n        //Toolbar\n        Toolbar,\n        ToolbarButton,\n        ToolbarToggle,\n        ToolbarMenu,\n        ToolbarSearchField,\n        ToolbarPopupSearchField,\n        ToolbarSpacer,\n\n        //Views and windows\n        ListView,\n        ScrollView,\n        TreeView,\n        PopupWindow,\n\n        IElement\n    }\n\n    enum TimeUnit\n    {\n        Default,\n        Millisecond,\n        Second\n    }\n\n    enum PseudoClass\n    {\n        None = 0,\n        Hover,\n        Active,\n        Inactive,\n        Focus,\n        Selected,\n        Disabled,\n        Enabled,\n        Checked,\n        Root\n    }\n\n    enum FontWeight\n    {\n        Thin = 100,\n        ExtraLight = 200,\n        Light = 300,\n        Regular = 400,\n        Medium = 500,\n        SemiBold = 600,\n        Bold = 700,\n        ExtraBold = 800,\n        Black = 900\n    }\n}"
  },
  {
    "path": "Editor/Interface/Enums.cs.meta",
    "content": "fileFormatVersion: 2\nguid: 772df3471b2405947abf34d0b8abcf8f\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n  defaultReferences: []\n  executionOrder: 0\n  icon: {instanceID: 0}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Editor/Interface/Figma.Enums.cs",
    "content": "﻿// ReSharper disable InconsistentNaming\n\nnamespace Figma.Internals\n{\n    public enum EffectType { INNER_SHADOW, DROP_SHADOW, LAYER_BLUR, BACKGROUND_BLUR }\n\n    public enum BlendMode { PASS_THROUGH, NORMAL, DARKEN, MULTIPLY, LINEAR_BURN, COLOR_BURN, LIGHTEN, SCREEN, LINEAR_DODGE, COLOR_DODGE, OVERLAY, SOFT_LIGHT, HARD_LIGHT, DIFFERENCE, EXCLUSION, HUE, SATURATION, COLOR, LUMINOSITY }\n\n    public enum ConstraintVertical { TOP, BOTTOM, CENTER, TOP_BOTTOM, SCALE }\n\n    public enum ConstraintHorizontal { LEFT, RIGHT, CENTER, LEFT_RIGHT, SCALE }\n\n    public enum PaintType { SOLID, GRADIENT_LINEAR, GRADIENT_RADIAL, GRADIENT_ANGULAR, GRADIENT_DIAMOND, IMAGE, EMOJI }\n\n    public enum Pattern { COLUMNS, ROWS, GRID }\n\n    public enum Alignment { MIN, MAX, STRETCH, CENTER }\n\n    public enum ScaleMode { FILL, FIT, TILE, STRETCH }\n\n    public enum ExportSettingsConstraintsType { SCALE, WIDTH, HEIGHT }\n\n    public enum Format { JPG, PNG, SVG, PDF }\n\n    public enum ActionType { BACK, CLOSE, URL, NODE }\n\n    public enum Navigation { NAVIGATE, SWAP, OVERLAY, CHANGE_TO }\n\n    public enum TransitionType { DISSOLVE, SMART_ANIMATE, MOVE_IN, MOVE_OUT, PUSH, SLIDE_IN, SLIDE_OUT }\n\n    public enum TransitionDirection { LEFT, RIGHT, TOP, BOTTOM }\n\n    public enum TriggerType { ON_CLICK, ON_HOVER, ON_PRESS, DRAG, AFTER_TIMEOUT, MOUSE_ENTER, MOUSE_LEAVE, MOUSE_UP, MOUSE_DOWN, ON_KEY_DOWN, ON_KEY_UP }\n\n    public enum TriggerDevice { KEYBOARD, XBOX_ONE, PS4, SWITCH_PRO, UNKNOWN_CONTROLLER }\n\n    public enum EasingType { EASE_IN, EASE_OUT, EASE_IN_AND_OUT, LINEAR, SLOW, CUSTOM_SPRING }\n\n    public enum LayoutAlign { CENTER, MIN, MAX, STRETCH, INHERIT }\n\n    public enum StrokeCap { NONE, ROUND, SQUARE, ARROW_LINES, ARROW_EQUILATERAL, LINE_ARROW }\n\n    public enum StrokeJoin { MITER, BEVEL, ROUND }\n\n    public enum StrokeAlign { INSIDE, OUTSIDE, CENTER }\n\n    public enum LayoutMode { NONE, HORIZONTAL, VERTICAL }\n\n    public enum PrimaryAxisSizingMode { AUTO, FIXED }\n\n    public enum CounterAxisSizingMode { AUTO, FIXED }\n\n    public enum PrimaryAxisAlignItems { MIN, CENTER, MAX, SPACE_BETWEEN }\n\n    public enum CounterAxisAlignItems { MIN, CENTER, MAX, BASELINE }\n\n    public enum OverflowDirection { NONE, HORIZONTAL_SCROLLING, VERTICAL_SCROLLING, HORIZONTAL_AND_VERTICAL_SCROLLING }\n\n    public enum TextCase { ORIGINAL, UPPER, LOWER, TITLE }\n\n    public enum TextDecoration { NONE, UNDERLINE, STRIKETHROUGH }\n\n    public enum TextAlignHorizontal { LEFT, CENTER, RIGHT, JUSTIFIED }\n\n    public enum TextAlignVertical { TOP, CENTER, BOTTOM }\n\n    public enum TextAutoResize { NONE, WIDTH_AND_HEIGHT, HEIGHT, TRUNCATE }\n\n    public enum BooleanOperation { UNION, INTERSECT, SUBTRACT, EXCLUDE }\n\n    public enum LayoutPositioning { AUTO, ABSOLUTE }\n\n    public enum StyleType { FILL, TEXT, EFFECT, GRID, NONE }\n\n    public enum NodeType { DOCUMENT, CANVAS, SLICE, FRAME, GROUP, COMPONENT_SET, COMPONENT, INSTANCE, BOOLEAN_OPERATION, VECTOR, STAR, LINE, ELLIPSE, REGULAR_POLYGON, RECTANGLE, TEXT, SECTION }\n\n    public enum ComponentPropertyType { BOOLEAN, TEXT, INSTANCE_SWAP, VARIANT }\n\n    public enum LayoutWrap { NO_WRAP, WRAP }\n\n    public enum MaskType { ALPHA, VECTOR, LUMINANCE }\n\n    public enum LayoutSizing { FIXED, HUG, FILL }\n\n    public enum CounterAxisAlignContent { AUTO, SPACE_BETWEEN }\n\n    public enum TextTruncation { DISABLED, ENDING }\n\n    public enum LineType { NONE, ORDERED, UNORDERED }\n\n    public enum TextWeight { BOLD, NORMAL }\n\n    public enum TextItalic { ITALIC, NORMAL }\n}"
  },
  {
    "path": "Editor/Interface/Figma.Enums.cs.meta",
    "content": "fileFormatVersion: 2\nguid: 04cc6de496b9b534d9dbdcfae4f2353e\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n  defaultReferences: []\n  executionOrder: 0\n  icon: {instanceID: 0}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Editor/Interface/Figma.Types.Interface.cs",
    "content": "using System.Collections.Generic;\nusing Newtonsoft.Json;\n\n// ReSharper disable InconsistentNaming\n// ReSharper disable BuiltInTypeReferenceStyle\n// ReSharper disable UnusedMember.Global\n// ReSharper disable CollectionNeverUpdated.Global\n// ReSharper disable UnassignedField.Global\n// ReSharper disable FieldCanBeMadeReadOnly.Global\n\n#pragma warning disable S101, S4004\n\nnamespace Figma.Internals\n{\n    public interface IBaseNodeMixin\n    {\n        NodeType type { get; set; }\n        string id { get; set; }\n        [JsonIgnore] BaseNode parent { get; set; }\n        string name { get; set; }\n    }\n\n    public interface ISceneNodeMixin\n    {\n        bool visible { get; set; }\n    }\n\n    public interface IChildrenMixin\n    {\n        SceneNode[] children { get; set; }\n    }\n\n    public interface ILayoutMixin\n    {\n        Constraints constraints { get; set; }\n        LayoutAlign layoutAlign { get; set; }\n        double layoutGrow { get; set; }\n        LayoutPositioning layoutPositioning { get; set; }\n        LayoutSizing layoutSizingHorizontal { get; set; }\n        LayoutSizing layoutSizingVertical { get; set; }\n        Rect absoluteBoundingBox { get; set; }\n        double rotation { get; set; }\n        double[][] relativeTransform { get; set; }\n        Vector? size { get; set; }\n        double? minWidth { get; set; }\n        double? minHeight { get; set; }\n        double? maxWidth { get; set; }\n        double? maxHeight { get; set; }\n    }\n\n    public interface IBlendMixin\n    {\n        double opacity { get; set; }\n        BlendMode blendMode { get; set; }\n        bool isMask { get; set; }\n        Effect[] effects { get; set; }\n        Dictionary<string, string> styles { get; set; }\n        bool preserveRatio { get; set; }\n    }\n\n    public interface IGeometryMixin\n    {\n        Paint[] fills { get; set; }\n        object[] fillGeometry { get; set; }\n        Paint[] strokes { get; set; }\n        double strokeWeight { get; set; }\n        StrokeAlign strokeAlign { get; set; }\n        StrokeCap strokeCap { get; set; }\n        StrokeJoin strokeJoin { get; set; }\n        object[] strokeGeometry { get; set; }\n        IndividualStrokeWeights individualStrokeWeights { get; set; }\n    }\n\n    public interface ICornerMixin\n    {\n        double? cornerRadius { get; set; }\n    }\n\n    public interface IRectangleCornerMixin\n    {\n        double[] rectangleCornerRadii { get; set; }\n    }\n\n    public interface IExportMixin\n    {\n        ExportSettings[] exportSettings { get; set; }\n    }\n\n    public interface IReactionMixin\n    {\n        Reaction[] reactions { get; set; }\n    }\n\n    public interface ITransitionMixin\n    {\n        string transitionNodeID { get; set; }\n        double? transitionDuration { get; set; }\n        EasingType? transitionEasing { get; set; }\n    }\n\n    public interface IDefaultShapeMixin : IBaseNodeMixin, ISceneNodeMixin, ILayoutMixin, IBlendMixin, IGeometryMixin, IReactionMixin, IExportMixin { }\n\n    public interface IDefaultFrameMixin : IDefaultShapeMixin, ICornerMixin, IRectangleCornerMixin, IChildrenMixin\n    {\n        LayoutMode layoutMode { get; set; }\n        PrimaryAxisSizingMode primaryAxisSizingMode { get; set; }\n        PrimaryAxisAlignItems primaryAxisAlignItems { get; set; }\n        CounterAxisSizingMode counterAxisSizingMode { get; set; }\n        CounterAxisAlignItems counterAxisAlignItems { get; set; }\n        CounterAxisAlignContent counterAxisAlignContent { get; set; }\n        double paddingLeft { get; set; }\n        double paddingTop { get; set; }\n        double paddingRight { get; set; }\n        double paddingBottom { get; set; }\n        double itemSpacing { get; set; }\n        LayoutGrid[] layoutGrids { get; set; }\n        bool clipsContent { get; set; }\n        OverflowDirection overflowDirection { get; set; }\n        LayoutWrap layoutWrap { get; set; }\n        bool itemReverseZIndex { get; set; }\n        bool strokesIncludedInLayout { get; set; }\n    }\n}"
  },
  {
    "path": "Editor/Interface/Figma.Types.Interface.cs.meta",
    "content": "fileFormatVersion: 2\nguid: d433f8c0bc1b474487e41e90ae1ffbd3\ntimeCreated: 1728645091"
  },
  {
    "path": "Editor/Interface/Figma.Types.Structs.cs",
    "content": "namespace Figma.Internals\n{\n    public struct Vector\n    {\n        public double x;\n        public double y;\n    }\n\n    public struct Rect\n    {\n        public double x;\n        public double y;\n        public double width;\n        public double height;\n\n        public double left => x;\n        public double right => x + width;\n        public double top => y;\n        public double bottom => y + height;\n        public double centerLeft => x - width / 2;\n        public double centerRight => x + width / 2;\n        public double centerTop => y - height / 2;\n        public double centerBottom => y + height / 2;\n        public double halfWidth => width / 2;\n        public double halfHeight => height / 2;\n\n        public Rect(double x, double y, double width, double height)\n        {\n            this.x = x;\n            this.y = y;\n            this.width = width;\n            this.height = height;\n        }\n\n        public static Rect operator +(Rect a, Rect b) => new(a.x + b.x, a.y + b.y, a.width + b.width, a.height + b.height);\n        public static Rect operator -(Rect a, Rect b) => new(a.x - b.x, a.y - b.y, a.width - b.width, a.height - b.height);\n    }\n\n    public struct RGBA\n    {\n        public double r;\n        public double g;\n        public double b;\n        public double a;\n\n        public static explicit operator UnityEngine.Color(RGBA color) => new((float) color.r, (float) color.g, (float) color.b, (float) color.a);\n    }\n}"
  },
  {
    "path": "Editor/Interface/Figma.Types.Structs.cs.meta",
    "content": "fileFormatVersion: 2\nguid: a20508fa20ef43dfb924e62827afe07d\ntimeCreated: 1729243214"
  },
  {
    "path": "Editor/Interface/Figma.Types.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\n\n// ReSharper disable InconsistentNaming\n// ReSharper disable BuiltInTypeReferenceStyle\n// ReSharper disable UnusedMember.Global\n// ReSharper disable CollectionNeverUpdated.Global\n// ReSharper disable UnassignedField.Global\n// ReSharper disable FieldCanBeMadeReadOnly.Global\n#pragma warning disable S101, S4004\n\nnamespace Figma.Internals\n{\n    using VariableAlias = Object;\n\n    #region Datatype\n    public class ShadowEffect : Effect\n    {\n        public EffectType type;\n        public RGBA color;\n        public Vector offset;\n        public double radius;\n        public double? spread;\n        public bool visible;\n        public BlendMode blendMode;\n        public bool? showShadowBehindNode;\n    }\n\n    public class BlurEffect : Effect\n    {\n        public EffectType type;\n        public double radius;\n        public bool visible;\n    }\n\n    public class Effect { }\n\n    public class IndividualStrokeWeights\n    {\n        public double top;\n        public double right;\n        public double bottom;\n        public double left;\n    }\n\n    public class Constraints\n    {\n        public ConstraintHorizontal horizontal;\n        public ConstraintVertical vertical;\n    }\n\n    public class ColorStop\n    {\n        public double position;\n        public RGBA color;\n    }\n\n    public class ImageFilter\n    {\n        public double? exposure;\n        public double? contrast;\n        public double? saturation;\n        public double? temperature;\n        public double? tint;\n        public double? highlights;\n        public double? shadows;\n    }\n\n    public class SolidPaint : Paint\n    {\n        public PaintType type;\n        public RGBA color;\n        public Dictionary<string, VariableAlias> boundVariables;\n    }\n\n    public class GradientPaint : Paint\n    {\n        public PaintType type;\n        public ColorStop[] gradientStops;\n        public Vector[] gradientHandlePositions;\n    }\n\n    public class ImagePaint : Paint\n    {\n        public PaintType type;\n        public ScaleMode scaleMode;\n        public double[,] imageTransform;\n        public string imageRef;\n        public ImageFilter filters;\n        public double? rotation;\n    }\n\n    public class Paint\n    {\n        public bool visible = true;\n        public double opacity = 1.0;\n        public BlendMode blendMode;\n    }\n\n    public class RowsColsLayoutGrid : LayoutGrid\n    {\n        public Pattern pattern;\n        public Alignment alignment;\n        public double gutterSize;\n        public double count;\n        public double? sectionSize;\n        public double? offset;\n        public bool? visible;\n        public RGBA? color;\n    }\n\n    public class GridLayoutGrid : LayoutGrid\n    {\n        public Pattern pattern;\n        public double sectionSize;\n        public bool? visible;\n        public RGBA? color;\n        public Alignment? alignment;\n        public double? gutterSize;\n        public double count;\n        public double? offset;\n    }\n\n    public class LayoutGrid { }\n\n    public class ExportSettingsConstraints\n    {\n        public ExportSettingsConstraintsType type;\n        public double value;\n    }\n\n    public class ExportSettingsImage : ExportSettings\n    {\n        public Format format;\n        public bool? contentsOnly;\n        public string suffix;\n        public ExportSettingsConstraints constraint;\n    }\n\n    public class ExportSettingsSVG : ExportSettings\n    {\n        public Format format = Format.SVG;\n        public bool? contentsOnly;\n        public string suffix;\n        public bool? svgOutlineText;\n        public bool? svgIdAttribute;\n        public bool? svgSimplifyStroke;\n        public ExportSettingsConstraints constraint;\n    }\n\n    public class ExportSettingsPDF : ExportSettings\n    {\n        public Format format = Format.PDF;\n        public bool? contentsOnly;\n        public string suffix;\n        public ExportSettingsConstraints constraint;\n    }\n\n    public class ExportSettings { }\n\n    public class Reaction\n    {\n        public Action action;\n        public Trigger trigger;\n    }\n\n    public class Action\n    {\n        public ActionType type;\n        public string url;\n        public string destinationId;\n        public Navigation? navigation;\n        public Transition transition;\n        public bool? preserveScrollPosition;\n        public Vector? overlayRelativePosition;\n        public bool resetVideoPosition;\n        public bool resetScrollPosition;\n        public bool resetInteractiveComponents;\n    }\n\n    public class SimpleTransition : Transition { }\n\n    public class DirectionalTransition : Transition\n    {\n        public TransitionDirection direction;\n        public bool matchLayers;\n    }\n\n    public class Transition\n    {\n        public TransitionType type;\n        public Easing easing;\n        public double? duration;\n    }\n\n    public class Trigger\n    {\n        public TriggerType type;\n        public double? delay;\n        public TriggerDevice? device;\n        public double[] keyCodes;\n        public double? timeout;\n        public double? mediaHitTime;\n    }\n\n    public class Easing\n    {\n        public EasingType type;\n        public EasingFunctionSpring easingFunctionSpring;\n    }\n\n    public class DocumentationLink\n    {\n        public string uri;\n    }\n\n    public class ArcData\n    {\n        public double startingAngle;\n        public double endingAngle;\n        public double innerRadius;\n    }\n\n    public class FlowStartingPoint\n    {\n        public string nodeId;\n        public string name;\n    }\n\n    public class ComponentPropertyReferences\n    {\n        public string visible;\n        public string characters;\n        public string mainComponent;\n    }\n    #endregion\n\n    #region Nodes\n    public class DocumentNode : BaseNode\n    {\n        public CanvasNode[] children;\n    }\n\n    public class CanvasNode : BaseNode, IChildrenMixin, IExportMixin\n    {\n        public RGBA backgroundColor;\n        public string prototypeStartNodeID;\n        public object prototypeDevice;\n        public FlowStartingPoint[] flowStartingPoints;\n\n        #region Mixin\n        public SceneNode[] children { get; set; }\n\n        public ExportSettings[] exportSettings { get; set; }\n        #endregion\n    }\n\n    public class FrameNode : DefaultFrameNode { }\n\n    public class GroupNode : DefaultFrameNode { }\n\n    public class SliceNode : SceneNode, ILayoutMixin, IExportMixin\n    {\n        #region Mixin\n        public Constraints constraints { get; set; }\n\n        public LayoutAlign layoutAlign { get; set; }\n        public double layoutGrow { get; set; }\n        public LayoutPositioning layoutPositioning { get; set; }\n        public LayoutSizing layoutSizingHorizontal { get; set; }\n        public LayoutSizing layoutSizingVertical { get; set; }\n        public Rect absoluteBoundingBox { get; set; }\n        public double rotation { get; set; }\n        public Rect absoluteRenderBounds { get; set; }\n        public double[][] relativeTransform { get; set; }\n        public Vector? size { get; set; }\n        public double? minWidth { get; set; }\n        public double? minHeight { get; set; }\n        public double? maxWidth { get; set; }\n        public double? maxHeight { get; set; }\n        public ExportSettings[] exportSettings { get; set; }\n        #endregion\n    }\n\n    public class RectangleNode : DefaultShapeNode, ICornerMixin, IRectangleCornerMixin\n    {\n        #region Mixin\n        public double? cornerRadius { get; set; }\n\n        public double[] rectangleCornerRadii { get; set; }\n        #endregion\n    }\n\n    public class LineNode : DefaultShapeNode { }\n\n    public class EllipseNode : DefaultShapeNode\n    {\n        public ArcData arcData { get; set; }\n    }\n\n    public class RegularPolygonNode : DefaultShapeNode, ICornerMixin, IRectangleCornerMixin\n    {\n        #region Mixin\n        public double? cornerRadius { get; set; }\n        public double[] rectangleCornerRadii { get; set; }\n        #endregion\n    }\n\n    public class StarNode : DefaultShapeNode, ICornerMixin, IRectangleCornerMixin\n    {\n        #region Mixin\n        public double? cornerRadius { get; set; }\n        public double[] rectangleCornerRadii { get; set; }\n        #endregion\n    }\n\n    public class VectorNode : DefaultShapeNode, ICornerMixin, IRectangleCornerMixin\n    {\n        #region Mixin\n        public double? cornerRadius { get; set; }\n        public double[] rectangleCornerRadii { get; set; }\n        public Dictionary<int, Paint> fillOverrideTable { get; set; }\n        #endregion\n    }\n\n    public class TextNode : DefaultShapeNode\n    {\n        public class Style\n        {\n            public string fontFamily; // not null\n            public string fontPostScriptName; // can be null\n            public double paragraphSpacing;\n            public bool italic;\n            public double fontWeight;\n            public double fontSize;\n            public TextCase textCase;\n            public TextDecoration textDecoration;\n            public TextAlignHorizontal textAlignHorizontal;\n            public TextAlignVertical textAlignVertical;\n            public TextAutoResize textAutoResize;\n            public double letterSpacing;\n            public Paint[] fills;\n            public Dictionary<string, double> opentypeFlags;\n            public double lineHeightPx;\n            public double? listSpacing;\n            public double? lineHeightPercentFontSize;\n            public string lineHeightUnit;\n            public Dictionary<string, string> hyperlink;\n            public string inheritFillStyleId;\n            public string inheritTextStyleId;\n            public string leadingTrim;\n            public TextTruncation textTruncation;\n            public int maxLines;\n            public string fontStyle;\n            public TextWeight? semanticWeight;\n            public TextItalic? semanticItalic;\n        }\n\n        public string characters;\n        public Style style;\n        public int[] characterStyleOverrides;\n        public Dictionary<int, Style> styleOverrideTable;\n        public double? layoutVersion;\n        public LineType[] lineTypes;\n        public int[] lineIndentations;\n    }\n\n    public class ComponentSetNode : DefaultFrameNode\n    {\n        public Dictionary<string, ComponentPropertyDefinition> componentPropertyDefinitions;\n    }\n\n    public class ComponentNode : DefaultFrameNode\n    {\n        public Dictionary<string, ComponentPropertyDefinition> componentPropertyDefinitions;\n    }\n\n    public class ComponentPropertyDefinition\n    {\n        public string type;\n        public string defaultValue;\n        public List<string> variantOptions;\n        public object boundVariables;\n        public PreferredValue[] preferredValues;\n    }\n\n    public class ComponentProperties : ComponentPropertyDefinition\n    {\n        public string value;\n    }\n\n    public class PreferredValue\n    {\n        public NodeType type;\n        public string key;\n    }\n\n    public class InstanceNode : DefaultFrameNode\n    {\n        public string componentId;\n        public Dictionary<string, ComponentProperties> componentProperties;\n        public bool isExposedInstance;\n        public string[] exposedInstances;\n        public Overrides[] overrides;\n    }\n\n    public class Overrides\n    {\n        public string id;\n        public string[] overriddenFields;\n    }\n\n    public class BooleanOperationNode : DefaultFrameNode\n    {\n        public BooleanOperation booleanOperation;\n    }\n\n    public class DefaultShapeNode : SceneNode, IDefaultShapeMixin, ITransitionMixin\n    {\n        public double[] strokeDashes;\n        public Rect absoluteRenderBounds;\n\n        #region Mixin\n        public LayoutSizing layoutSizingHorizontal { get; set; }\n        public LayoutSizing layoutSizingVertical { get; set; }\n        public Constraints constraints { get; set; }\n\n        public LayoutAlign layoutAlign { get; set; }\n        public double layoutGrow { get; set; }\n        public Rect absoluteBoundingBox { get; set; }\n        public double rotation { get; set; }\n\n        // only if geometry=paths\n        public double[][] relativeTransform { get; set; }\n        public Vector? size { get; set; }\n\n        public double opacity { get; set; } = 1.0;\n        public BlendMode blendMode { get; set; }\n        public bool isMask { get; set; }\n        public Effect[] effects { get; set; }\n        public Dictionary<string, string> styles { get; set; }\n        public bool preserveRatio { get; set; }\n\n        public Paint[] fills { get; set; }\n        public object[] fillGeometry { get; set; }\n        public Paint[] strokes { get; set; }\n        public double strokeWeight { get; set; }\n        public IndividualStrokeWeights individualStrokeWeights { get; set; }\n        public StrokeAlign strokeAlign { get; set; }\n        public StrokeCap strokeCap { get; set; }\n        public StrokeJoin strokeJoin { get; set; }\n        public object[] strokeGeometry { get; set; }\n        public double strokeMiterAngle { get; set; } = 28.96;\n        public double cornerSmoothing { get; set; }\n\n        public Reaction[] reactions { get; set; }\n\n        public ExportSettings[] exportSettings { get; set; }\n\n        public string transitionNodeID { get; set; }\n        public double? transitionDuration { get; set; }\n        public EasingType? transitionEasing { get; set; }\n        public Interactions[] interactions { get; set; }\n\n        public ComponentPropertyReferences componentPropertyReferences { get; set; }\n\n        public LayoutPositioning layoutPositioning { get; set; }\n        public MaskType? maskType { get; set; }\n        public double? minWidth { get; set; }\n        public double? minHeight { get; set; }\n        public double? maxWidth { get; set; }\n        public double? maxHeight { get; set; }\n        #endregion\n    }\n\n    public class DefaultFrameNode : DefaultShapeNode, IDefaultFrameMixin\n    {\n        #region Mixin\n        public LayoutMode layoutMode { get; set; }\n        public PrimaryAxisSizingMode primaryAxisSizingMode { get; set; }\n        public CounterAxisSizingMode counterAxisSizingMode { get; set; }\n        public PrimaryAxisAlignItems primaryAxisAlignItems { get; set; }\n        public CounterAxisAlignItems counterAxisAlignItems { get; set; }\n        public CounterAxisAlignContent counterAxisAlignContent { get; set; }\n        public double paddingLeft { get; set; }\n        public double paddingTop { get; set; }\n        public double paddingRight { get; set; }\n        public double paddingBottom { get; set; }\n        public double itemSpacing { get; set; }\n        public LayoutGrid[] layoutGrids { get; set; }\n        public bool clipsContent { get; set; }\n        public OverflowDirection overflowDirection { get; set; }\n        public LayoutWrap layoutWrap { get; set; }\n        public bool itemReverseZIndex { get; set; }\n        public bool strokesIncludedInLayout { get; set; }\n\n        public double? cornerRadius { get; set; }\n        public double[] rectangleCornerRadii { get; set; }\n\n        public SceneNode[] children { get; set; }\n        #endregion\n    }\n\n    public class BaseNode : IBaseNodeMixin\n    {\n        #region Mixin\n        public NodeType type { get; set; }\n        public string id { get; set; }\n        public BaseNode parent { get; set; }\n        public string name { get; set; }\n        public string scrollBehavior { get; set; }\n        #endregion\n\n        public override string ToString() => name;\n    }\n\n    public class SceneNode : BaseNode, ISceneNodeMixin\n    {\n        #region Properties\n        public bool visible { get; set; } = true;\n        public Dictionary<string, VariableAlias> boundVariables { get; set; }\n        #endregion\n    }\n\n    public class SectionNode : DefaultFrameNode, IChildrenMixin\n    {\n        #region Properties\n        public bool sectionContentsHidden { get; set; }\n        #endregion\n    }\n    #endregion\n\n    #region Api\n    public class Component\n    {\n        public string key;\n        public string name;\n        public string description;\n        public DocumentationLink[] documentationLinks;\n        public string componentSetId;\n        public bool remote;\n    }\n\n    public class Style\n    {\n        public StyleType styleType;\n        public string key;\n        public string name;\n        public string description;\n        public string remote;\n    }\n\n    public class Failure\n    {\n        public int status;\n        public string err;\n    }\n\n    public class Me : Failure\n    {\n        public string id;\n        public string email;\n        public string handle;\n        public string img_url;\n    }\n\n    public class Data : Failure\n    {\n        public class Images\n        {\n            public class Meta\n            {\n                public Dictionary<string, string> images;\n            }\n\n            public bool error;\n            public double status;\n            public Meta meta;\n            public string i18n;\n        }\n\n        public DocumentNode document;\n        public Dictionary<string, Component> components;\n        public Dictionary<string, Component> componentSets;\n        public double schemaVersion;\n        public Dictionary<string, Style> styles;\n        public string name;\n        public DateTime lastModified;\n        public string thumbnailUrl;\n        public string version;\n        public string role;\n        public string editorType;\n        public string linkAccess;\n    }\n\n    public class Images : Failure\n    {\n        public Dictionary<string, string> images;\n    }\n\n    public class Nodes : Failure\n    {\n        public class Document\n        {\n            public ComponentNode document;\n            public Dictionary<string, Component> components;\n            public Dictionary<string, Component> componentSets;\n            public double schemaVersion;\n            public Dictionary<string, Style> styles;\n        }\n\n        public string name;\n        public DateTime lastModified;\n        public string thumbnailUrl;\n        public string version;\n        public string role;\n        public Dictionary<string, Document> nodes;\n        public string editorType;\n        public string linkAccess;\n    }\n\n    public class Interactions\n    {\n        public Trigger trigger;\n        public List<Action> actions;\n    }\n\n    public class EasingFunctionSpring\n    {\n        public double? mass;\n        public double? stiffness;\n        public double? damping;\n    }\n    #endregion\n}"
  },
  {
    "path": "Editor/Interface/Figma.Types.cs.meta",
    "content": "fileFormatVersion: 2\nguid: f5f4947df342cf540b908c2dd2e2a2ee\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n  defaultReferences: []\n  executionOrder: 0\n  icon: {instanceID: 0}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Editor/Interface/Interface.Records.cs",
    "content": "using System;\n\nnamespace Figma\n{\n    using Attributes;\n\n    record RootMetadata(bool filter, UxmlAttribute uxml, UxmlDownloadImages downloadImages);\n\n    // ReSharper disable once NotAccessedPositionalProperty.Global\n    record QueryMetadata(Type fieldType, QueryAttribute query);\n\n    record BaseNodeMetadata(RootMetadata root, QueryMetadata query);\n}"
  },
  {
    "path": "Editor/Interface/Interface.Records.cs.meta",
    "content": "fileFormatVersion: 2\nguid: a02ced439c1547dea0ba054f881f0892\ntimeCreated: 1727941971"
  },
  {
    "path": "Editor/Interface.meta",
    "content": "fileFormatVersion: 2\nguid: 9d9c7aa8bf559004a898cba5d982b661\nfolderAsset: yes\nDefaultImporter:\n  externalObjects: {}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Editor.meta",
    "content": "fileFormatVersion: 2\nguid: 047c80ffe3f35194089fa29faafd00ff\nfolderAsset: yes\nDefaultImporter:\n  externalObjects: {}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "License.md",
    "content": "                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   4. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   5. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   6. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   7. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   8. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   Copyright 2023 Trackman A/S\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n\nNO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY\nTHIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND\nCONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\nLIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A\nPARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR\nCONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\nEXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\nPROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR\nBUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER\nIN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\nARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\nPOSSIBILITY OF SUCH DAMAGE.\n"
  },
  {
    "path": "License.md.meta",
    "content": "fileFormatVersion: 2\nguid: fdd2e558d847d528a87531ad64ba1e48\nTextScriptImporter:\n  externalObjects: {}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Prefabs/Figma.prefab",
    "content": "%YAML 1.1\n%TAG !u! tag:unity3d.com,2011:\n--- !u!1 &2916098490094507199\nGameObject:\n  m_ObjectHideFlags: 0\n  m_CorrespondingSourceObject: {fileID: 0}\n  m_PrefabInstance: {fileID: 0}\n  m_PrefabAsset: {fileID: 0}\n  serializedVersion: 6\n  m_Component:\n  - component: {fileID: 2492470867148571057}\n  - component: {fileID: 6641805578009137364}\n  - component: {fileID: -3369783722120399799}\n  m_Layer: 0\n  m_Name: Figma\n  m_TagString: Untagged\n  m_Icon: {fileID: 0}\n  m_NavMeshLayer: 0\n  m_StaticEditorFlags: 0\n  m_IsActive: 1\n--- !u!4 &2492470867148571057\nTransform:\n  m_ObjectHideFlags: 0\n  m_CorrespondingSourceObject: {fileID: 0}\n  m_PrefabInstance: {fileID: 0}\n  m_PrefabAsset: {fileID: 0}\n  m_GameObject: {fileID: 2916098490094507199}\n  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}\n  m_LocalPosition: {x: 0, y: 0, z: 0}\n  m_LocalScale: {x: 1, y: 1, z: 1}\n  m_ConstrainProportionsScale: 0\n  m_Children: []\n  m_Father: {fileID: 0}\n  m_RootOrder: 0\n  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}\n--- !u!114 &6641805578009137364\nMonoBehaviour:\n  m_ObjectHideFlags: 0\n  m_CorrespondingSourceObject: {fileID: 0}\n  m_PrefabInstance: {fileID: 0}\n  m_PrefabAsset: {fileID: 0}\n  m_GameObject: {fileID: 2916098490094507199}\n  m_Enabled: 1\n  m_EditorHideFlags: 0\n  m_Script: {fileID: 19102, guid: 0000000000000000e000000000000000, type: 0}\n  m_Name: \n  m_EditorClassIdentifier: \n  m_PanelSettings: {fileID: 11400000, guid: f486055d8ec653edc96c3f3c38380c8f, type: 2}\n  m_ParentUI: {fileID: 0}\n  sourceAsset: {fileID: 0}\n  m_SortingOrder: 0\n--- !u!114 &-3369783722120399799\nMonoBehaviour:\n  m_ObjectHideFlags: 0\n  m_CorrespondingSourceObject: {fileID: 0}\n  m_PrefabInstance: {fileID: 0}\n  m_PrefabAsset: {fileID: 0}\n  m_GameObject: {fileID: 2916098490094507199}\n  m_Enabled: 1\n  m_EditorHideFlags: 0\n  m_Script: {fileID: 11500000, guid: aaa4e5d0dd7bf25488b120aa854832eb, type: 3}\n  m_Name: \n  m_EditorClassIdentifier: \n  title: \n  filter: 0\n  reorder: 0\n  fontsDirs: []\n"
  },
  {
    "path": "Prefabs/Figma.prefab.meta",
    "content": "fileFormatVersion: 2\nguid: a1decc1df2e53b24285e24bfd721a22c\nPrefabImporter:\n  externalObjects: {}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Prefabs.meta",
    "content": "fileFormatVersion: 2\nguid: c4567610e8b246a43ac8ab4dce22b73b\nfolderAsset: yes\nDefaultImporter:\n  externalObjects: {}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Readme.md",
    "content": "> [!WARNING]\n> **Experimental Release**: This plugin is currently in an experimental phase and is provided \"as is\" without warranty of any kind. It was originally developed for internal use and may contain issues or limitations. Use it at your own risk. Feedback and contributions are welcome but please keep in mind the experimental nature of this tool.\n\n[output.webm](https://github.com/TrackMan/Unity.Package.FigmaForUnity/assets/22183046/59423710-61af-44b0-b233-47216881c051)\n\n# Overview\nFigmaToUnity is a Unity plugin that streamlines the UI development process by enabling the direct import of Figma page documents into Unity. The tool automatically converts Figma document into UI Toolkit assets, allowing for quick and accurate integration of UI interfaces into your Unity games.\n\n# Features\n\n| Name                            | Description                                                                                                                                         |\n|---------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------|\n| **Figma Import to UXML/USS**    | The tool imports and parses Figma page documents, transforming them into UXML and USS assets within Unity.                                          |\n| **Element Manipulation**        | Enables the manipulation of UI elements and the application of custom logic via Unity scripts, providing extensive control over the user interface. |\n| **Sync Changes**                | Changes made to UI elements in Figma can be readily fetched and updated in Unity, maintaining the integrity of the game's UI.                       |\n| **[Limitations](#limitations)** | Refer to the section below.                                                                                                                         |\n\n# Installing\n1. Open `Window > Package Manager`\n2. Click the `+` button in the top-left corner\n3. Choose `Add package from git URL...`\n4. Enter https://github.com/TrackMan/Unity.Package.AsyncAwaitUtil.git\n5. Click the `+` button in the top-left corner\n6. Click the `+` button in the top-left corner\n7. Choose `Add package from git URL...`\n8. Enter https://github.com/TrackMan/Unity.Package.FigmaForUnity.git\n\n## Dependencies\nTo integrate these dependencies, you must either manually include them in your project's manifest file or ensure they are automatically resolved through Unity's Package Manager registry.\n\n- [Async Await Util 1.0.6](https://github.com/TrackMan/Unity.Package.AsyncAwaitUtil)\n\n## Personal Access Token\nTo start using [Figma Inspector](#Figma-Inspector), a Figma Personal Access Token is needed for API calls.\n> [!WARNING]\n> The token is stored in raw format.\n\n1. Visit the [Figma API Authentication Page](https://www.figma.com/developers/api?fuid=797042793200923967#authentication).\n2. Click + Get personal access token to generate the token.\n3. Copy the generated token.\n4. Locate the Figma script in [Unity's Inspector](#Figma-Inspector).\n5. Paste the token into the designated field.\n\n# Quick Start\n- Finish [Installing](#Installing)\n- Open `~Samples` folder\n- Open `Test.unity`\n- Go to `Figma` GameObject\n- In the `Title`, enter the title of your Figma document (ie dfeQabSU71CHXVqweameSF) from Figma website ([some templates](https://www.figma.com/community/files))\n- Go to `Test.cs` and edit the UXML attribute to points to your Page/Element path\n- Configure [Personal Access Token](#Personal-Access-Token) in [Unity's Inspector](#Figma-Inspector)\n- Click `Update UI & Images`\n- Save the `VisualAssetTree` somewhere\n- Start `playmode` and enjoy!\n\n# Usage\nWorking with this plugin is done through using Figma component inspector FigmaInspector. \nIn addition, components derived from the Element class should be created and added to the same GameObject hierarchy.\nThese components serve a dual purpose:\n\n1. During the import phase, they assist in filtering and configuring various aspects of the document, such as frame selection and image handling.\n2. During runtime, they provide the functionality to manipulate UXML and USS data structures.\n\n## Figma Inspector\n![image](https://user-images.githubusercontent.com/22183046/270277550-bd127c6a-1e0f-4494-8b2b-cc9e87ed0448.png)\n\n| Property                           | Description                                                                                                                                                                                            |\n|------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| **Panel Settings**                 | A crucial asset enabling Unity to render UXML-based user interfaces within the Game View.                                                                                                              |\n| **Source Asset**                   | The UXML asset responsible for outlining the structural framework of the user interface.                                                                                                               |\n| **Sort Order**                     | Specifies the rendering sequence of UXML assets when multiple Panel Settings instances exist within a project.                                                                                         |\n| **Title**                          | Designates the title from the Figma document URL for identification purposes.                                                                                                                          |\n| **Asset**                          | Represents the UXML asset correlating with the corresponding asset within the UI document script. (Refer to the section above for further details)                                                     |\n| **Update Buttons**                 | Facilitates UI updates, offering options to include or exclude the downloading of all associated images.                                                                                               |\n| **De-root and Re-order Hierarchy** | Adjusts the organization of all frames based on each element's RootOrder property, optimizing the UI hierarchy.                                                                                        |\n| **Filter by Path**                 | When activated, this feature limits the download to only those UI frames that have associated scripts attached to the prefab, otherwise, all UI elements within the Figma document will be downloaded. |\n| **Additional Fonts Directories**   | Provides the capability to specify paths to any fonts that are incorporated within the UI, ensuring seamless visual consistency.                                                                       |\n\n## Folders Layout\nThis is how the final setup should look:\n```\n<UI folder>\n  ├── UI.uxml\n  ├── UI.uss\n  ├── CachedAssets_UI.json\n  ├── Elements\n  │   ├── CustomElement.uxml\n  │   └── CustomElement.uss\n  ├── Components\n  │   ├── Component.uxml  \n  │   └── Component.uss  \n  ├── Frames\n  │   └── Canvas1  \n  │       ├── Frame1.uxml  \n  │       ├── Frame1.uss\n  │       ├── Frame2.uxml  \n  │       └── Frame2.uss\n  ├── Images\n  │   ├── AmazingImage.svg\n  │   └── PerfectImage.png\n  └── Fonts\n      └── Inter-Regular.ttf\n```\nPlease note that you need to place your **custom fonts** in a **'Fonts' folder**. If you try to import a Figma document that includes a font which does not exist in the 'Fonts' folder, you will see a message in the console indicating which font is missing. You can also add an additional fonts directory using the appropriate property in the Figma object.\n\n## Figma class\nDuring the update process the Figma class retrieves data based on the Uxml and Query attributes of the Element scripts. It then utilizes this data while producing UXML asset.\n> [!WARNING]\n> Element scripts should be attached to the same game object to which the Figma script is also attached.\n\n## Element class (OnInitialize, OnRebuild, Custom Elements)\nThe Uxml and Query attributes define the structure of the Uxml asset and, consequently, the appearance of your UI.\nThe type of the field following the Query attribute defines the UI element itself and, consequently, its behavior (VisualElement, Button, Label, etc.). Field types are written into UXML. Therefore, if you change the field type (for example, from VisualElement to Button), you will need to perform a Figma Update to regenerate the UXML.\nEach element can override OnInitialize and OnRebuild methods which can be used to do any initial setup operations.\n\n``` csharp\n[Uxml(\"TestPage/TestFrame\", UxmlDownloadImages.Everything, UxmlElementTypeIdentification.ByElementType)]\n[AddComponentMenu(\"Figma/Samples/Test\")]\npublic class Test : Element\n{\n\tconst int minCircles = 1;\n\tconst int maxCircles = 7;\n\n\t#region Fields\n\t[Query(\"Header\")] Label header;\n\n\t[Query(\"CloneButton\", Clicked = nameof(Clone))] Button cloneButton;\n\t[Query(\"RemoveButton\", Clicked = nameof(Remove))] Button removeButton;\n\t[Query(\"CloneContainer\", StartRoot = true)] VisualElement cloneContainer;\n\t[Query(\"CloneCircle\", EndRoot = true)] PerfectCircle cloneCircle;\n\n\t[Query(\"SyncButton\", Clicked = nameof(Sync))] Button syncButton;\n\t[Query(\"SyncContainer\")] VisualElement syncContainer;\n\t[Query(\"SyncContainer/SyncCircle\")] PerfectCircle syncCircle;\n\n\t[Query(\"FunctionDescription\", Hide = true)] Label functionDescription;\n\t#endregion\n\n\t#region Methods\n\tprotected override void OnInitialize() => cloneContainer.style.flexWrap = Wrap.NoWrap;\n\tprotected override void OnRebuild() => header.text = \"Welcome to Figma Test Frame!\";\n\n\tvoid Clone()\n\t{\n\t\tif (cloneContainer.childCount == maxCircles) return;\n\n\t\tcloneCircle.Clone(cloneContainer);\n\t}\n\tvoid Remove()\n\t{\n\t\tif (cloneContainer.childCount == minCircles) return;\n\n\t\tcloneContainer.Remove(cloneContainer.Children().First());\n\t}\n\tvoid Sync()\n\t{\n\t\tvoid RandomColor(int index) => syncContainer.Children().ElementAt(index).style.backgroundColor = Random.ColorHSV();\n\n\t\tsyncCircle.Sync(syncContainer, RandomColor, Enumerable.Range(0, Random.Range(1, maxCircles + 1)));\n\t\tsyncCircle.Hide();\n\n\t\tfunctionDescription.Show();\n\t}\n\t#endregion\n}\n```\n### Custom element example\n``` csharp\npublic class PerfectCircle : SyncButtonSimple<int>\n{\n\tpublic new class UxmlFactory : UxmlFactory<PerfectCircle> { }\n\n\t#region Methods\n\tpublic override bool IsVisible(int index, int data) => true;\n\t#endregion\n}\n```\n\n## UxmlAttribute\nThis attribute specifies the Element (a frame, and it's children) that we want to import from Figma document.\n\n| Attribute              | Description                                                                                                                            |\n|------------------------|----------------------------------------------------------------------------------------------------------------------------------------|\n| **Root**               | Defines the root path within the Figma document where this frame originates, inclusive of the canvas path.                             |\n| **DownloadImages**     | Specifies the strategy for downloading images from the Figma document.                                                                 |\n| **TypeIdentification** | Indicates the method for identifying the types of elements, whether based on their name or their classification under Element classes. |\n| **Preserve**           | Lists any additional paths that should be maintained as-is in the imported document.                                                   |\n\n## QueryAttribute\nThis attribute specifies the sub element (inside of the Element) parameters (like path to element, or what should happen when you click button).\n\n| Event Name                      | Description                                                              |\n|---------------------------------|--------------------------------------------------------------------------|\n| **Path**                        | The path used in the UI query.                                           |\n| **ClassName**                   | The class name of the element.                                           |\n| **ImageFiltering**              | Enum specifying how images are downloaded or filtered.                   |\n| **ReplaceNodePath**             | Path to the node that will be replaced.                                  |\n| **ReplaceNodeEvent**            | Event that triggers the node replacement.                                |\n| **ReplaceElementPath**          | Path to the element that will be replaced.                               |\n| **RebuildElementEvent**         | Event that triggers the element to be rebuilt.                           |\n| **StartRoot**                   | Specifies that element path will be new root for the following elements. |\n| **EndRoot**                     | Specifies the end of StartRoot.                                          |\n| **Nullable**                    | Specifies if the element can be null.                                    |\n| **Clicked**                     | Name of the method to be invoked when the element is clicked.            |\n| **Template**                    | Template to be used for the element (creates a separate uxml file).      |\n| **Hash**                        | Create a template file using Hash.                                       |\n| **UseTrickleDown**              | Specifies if events should trickle down through the element hierarchy.   |\n| **ChangeEvent**                 | Event triggered when an element's state changes.                         |\n| **MouseCaptureOutEvent**        | Event triggered when mouse capture is lost.                              |\n| **ValidateCommandEvent**        | Event triggered to validate a command.                                   |\n| **ExecuteCommandEvent**         | Event triggered to execute a command.                                    |\n| **DragExitedEvent**             | Event triggered when a drag operation exits the element.                 |\n| **DragUpdatedEvent**            | Event triggered when a drag operation is updated.                        |\n| **DragPerformEvent**            | Event triggered when a drag operation is performed.                      |\n| **DragEnterEvent**              | Event triggered when a drag operation enters the element.                |\n| **DragLeaveEvent**              | Event triggered when a drag operation leaves the element.                |\n| **FocusOutEvent**               | Event triggered when the element loses focus.                            |\n| **BlurEvent**                   | Event triggered when the element is blurred.                             |\n| **FocusInEvent**                | Event triggered when the element gains focus.                            |\n| **FocusEvent**                  | Event triggered when the element is focused or loses focus.              |\n| **InputEvent**                  | Event triggered when the element receives input.                         |\n| **KeyDownEvent**                | Event triggered when a key is pressed down.                              |\n| **KeyUpEvent**                  | Event triggered when a key is released.                                  |\n| **GeometryChangedEvent**        | Event triggered when the element's geometry changes.                     |\n| **PointerDownEvent**            | Event triggered when a pointer is pressed down.                          |\n| **PointerUpEvent**              | Event triggered when a pointer is released.                              |\n| **PointerMoveEvent**            | Event triggered when a pointer is moved.                                 |\n| **MouseDownEvent**              | Event triggered when a mouse button is pressed.                          |\n| **MouseUpEvent**                | Event triggered when a mouse button is released.                         |\n| **MouseMoveEvent**              | Event triggered when the mouse is moved.                                 |\n| **ContextClickEvent**           | Event triggered on a context click (right-click).                        |\n| **WheelEvent**                  | Event triggered when the mouse wheel is moved.                           |\n| **MouseEnterEvent**             | Event triggered when the mouse enters the element.                       |\n| **MouseLeaveEvent**             | Event triggered when the mouse leaves the element.                       |\n| **MouseEnterWindowEvent**       | Event triggered when the mouse enters the window containing the element. |\n| **MouseLeaveWindowEvent**       | Event triggered when the mouse leaves the window containing the element. |\n| **MouseOverEvent**              | Event triggered when the mouse is over the element.                      |\n| **MouseOutEvent**               | Event triggered when the mouse is out of the element.                    |\n| **ContextualMenuPopulateEvent** | Event triggered to populate the contextual menu.                         |\n| **AttachToPanelEvent**          | Event triggered when the element is attached to a panel.                 |\n| **DetachFromPanelEvent**        | Event triggered when the element is detached from a panel.               |\n| **TooltipEvent**                | Event triggered to display a tooltip.                                    |\n| **IMGUIEvent**                  | Event triggered for IMGUI rendering.                                     |\n\n## ISubElement\nThis interface serves as an identifier, signifying that within the IRootElement hierarchy, an element exists which can function as a component based on the VisualElement class.\n\n## IRootElement\nThis interface acts as a marker, indicating that an element within the IRootElement hierarchy is capable of functioning as a component derived from the VisualElement class.\n\n## Visual Element Style\nThe imported USS file contains all the classes used by Visual Elements. USS is inspired by CSS and has a similar syntax. To manipulate properties in your code, you should use the techniques described below.\n### Changing Element Appearance\nTo change the appearance of a VisualElement, you should manipulate its style properties. For example, to set the top margin of an element to 3:\n```csharp\nelement.style.marginTop = 3;\n```\n### Reading Element Style Data\nIf you need to read style data from a VisualElement, you should use its resolved style properties. For example, to retrieve the value of the top margin:\n```csharp\nfloat margin = element.resolvedStyle.marginTop;\n```\n> You can find the list of all supported properties in the official Unity documentation.\n\n## Visual Element Extensions\nWhen working with VisualElements, there are various visual element extensions that allow you to find/clone/replace/etc elements:\n```csharp\nVisualElement rectangle = element.Find<VisualElement>(\"Rectangle\");\n```\n```csharp\nVisualElement elementClone = options.Clone();\n```\n```csharp\nelement.Replace(newElement);\n```\n\n# Limitations\n\n| Feature                      | Description                                                                                                                             |\n|------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------|\n| **Unique Frame Names**       | Each frame must have a unique name to ensure proper functionality.                                                                      |\n| **Vector Constraints**       | Vectors should be visible, should not contain Image Fills, and, where possible, should be grouped into Unions.                          |\n| **Fill Limitations**         | Each UI element can contain only a single Fill attribute.                                                                               |\n| **Auto-Layout Restrictions** | Stroke borders are not supported within Auto-Layout configurations.                                                                     |\n| **Alignment Constraints**    | Horizontal and vertical centering cannot be mixed within the same parent element; doing so will default the alignment to center-center. |\n| **Circle Representation**    | For optimal visual rendering, circles should be implemented using rectangles rather than ellipses.                                      |\n\n# Not implemented\n- Documentation (work in progress)\n- Flex-gap (Unity not supported)\n- Blur (Unity not supported)\n- Letter spacing (Unity not supported)\n- Line height (Unity not supported)\n- IndividualStrokeWeights (Unity not supported)\n- ComponentPropertyDefinitions\n- Various CodeGenerators\n- Dragging items for scroll-view\n- Generation of the various states of Elements with states - Generation of the various states of Elements with states- Generation of the various states of Elements with states"
  },
  {
    "path": "Readme.md.meta",
    "content": "fileFormatVersion: 2\nguid: 97c5af11bb3cfa4c4952aab609afcd17\nTextScriptImporter:\n  externalObjects: {}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Runtime/AssemblyInfo.cs",
    "content": "#pragma warning disable S2094\n\nusing System.Runtime.CompilerServices;\n\n[assembly: InternalsVisibleTo(\"Figma.Editor\")]\n\nnamespace System.Runtime.CompilerServices\n{\n    public class IsExternalInit { }\n}"
  },
  {
    "path": "Runtime/AssemblyInfo.cs.meta",
    "content": "fileFormatVersion: 2\nguid: d02acb23f49d34ad996232782b6f0270\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n  defaultReferences: []\n  executionOrder: 0\n  icon: {instanceID: 0}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Runtime/Core/Element.cs",
    "content": "﻿using UnityEngine;\nusing UnityEngine.UIElements;\n\n// ReSharper disable MemberCanBeProtected.Global\n\nnamespace Figma\n{\n    using Internals;\n\n    public abstract class Element : MonoBehaviour, IRootElement\n    {\n        #region Fields\n        string className;\n        #endregion\n\n        #region Properties\n        public virtual int RootOrder => 0;\n        public string ClassName => className.NotNullOrEmpty() ? className : GetType().Name;\n        public VisualElement Root { get; private set; }\n        public VisualElement[] RootsPreserved { get; private set; }\n        #endregion\n\n        #region Methods\n        void IRootElement.OnInitialize(VisualElement root, VisualElement[] rootsPreserved)\n        {\n            Root = root;\n            RootsPreserved = rootsPreserved;\n            OnInitialize();\n        }\n        void IRootElement.OnRebuild() => OnRebuild();\n\n        protected virtual void OnInitialize() { }\n        protected virtual void OnRebuild() { }\n        #endregion\n\n        #region Base Methods\n        protected virtual void Awake() => className = GetType().Name;\n        protected virtual void OnEnable() => className = GetType().Name;\n        protected virtual void OnDisable() { }\n        #endregion\n    }\n}"
  },
  {
    "path": "Runtime/Core/Element.cs.meta",
    "content": "fileFormatVersion: 2\nguid: c3d7de8bb8ca66b41a2a58e3c87acd68\ntimeCreated: 1524533501\nlicenseType: Store\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n  defaultReferences: []\n  executionOrder: 0\n  icon: {instanceID: 0}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Runtime/Core/QueryAttribute.cs",
    "content": "﻿using System;\nusing System.Diagnostics;\nusing UnityEngine.UIElements;\n\n// ReSharper disable UnusedAutoPropertyAccessor.Global\n// ReSharper disable MemberCanBeProtected.Global\n\nnamespace Figma.Attributes\n{\n    [DebuggerStepThrough]\n    [AttributeUsage(AttributeTargets.Field)]\n    public class QueryAttribute : Attribute\n    {\n        #region Properties\n        public string Path { get; }\n        public string ClassName { get; }\n        [Obsolete(\"Use 'DownloadImage' instead\")]\n        public ElementDownloadImage ImageFiltering { get => DownloadImage; set => DownloadImage = value; }\n        public ElementDownloadImage DownloadImage { get; set; }\n        public bool Hash { get; set; }\n        public string ReplaceElementPath { get; set; }\n        public string RebuildElementEvent { get; set; }\n        public bool StartRoot { get; set; }\n        public bool EndRoot { get; set; }\n        public bool Nullable { get; set; }\n        public bool Hide { get; set; }\n        public bool Localize { get; set; } = true;\n        public string Clicked { get; set; }\n        public string Template { get; set; }\n        public TrickleDown UseTrickleDown { get; set; }\n        public string MouseCaptureOutEvent { get; set; }\n        public string MouseCaptureEvent { get; set; }\n        public string ChangeEvent { get; set; }\n        public string ValidateCommandEvent { get; set; }\n        public string ExecuteCommandEvent { get; set; }\n        public string DragExitedEvent { get; set; }\n        public string DragUpdatedEvent { get; set; }\n        public string DragPerformEvent { get; set; }\n        public string DragEnterEvent { get; set; }\n        public string DragLeaveEvent { get; set; }\n        public string FocusOutEvent { get; set; }\n        public string BlurEvent { get; set; }\n        public string FocusInEvent { get; set; }\n        public string FocusEvent { get; set; }\n        public string InputEvent { get; set; }\n        public string KeyDownEvent { get; set; }\n        public string KeyUpEvent { get; set; }\n        public string GeometryChangedEvent { get; set; }\n        public string PointerDownEvent { get; set; }\n        public string PointerUpEvent { get; set; }\n        public string PointerMoveEvent { get; set; }\n        public string MouseDownEvent { get; set; }\n        public string MouseUpEvent { get; set; }\n        public string MouseMoveEvent { get; set; }\n        public string ContextClickEvent { get; set; }\n        public string WheelEvent { get; set; }\n        public string MouseEnterEvent { get; set; }\n        public string MouseLeaveEvent { get; set; }\n        public string MouseEnterWindowEvent { get; set; }\n        public string MouseLeaveWindowEvent { get; set; }\n        public string MouseOverEvent { get; set; }\n        public string MouseOutEvent { get; set; }\n        public string ContextualMenuPopulateEvent { get; set; }\n        public string AttachToPanelEvent { get; set; }\n        public string DetachFromPanelEvent { get; set; }\n        public string TooltipEvent { get; set; }\n        public string IMGUIEvent { get; set; }\n        #endregion\n\n        #region Constructors\n        public QueryAttribute(string path, string className = null)\n        {\n            Path = path;\n            ClassName = className;\n        }\n        #endregion\n    }\n}"
  },
  {
    "path": "Runtime/Core/QueryAttribute.cs.meta",
    "content": "fileFormatVersion: 2\nguid: ba43ed1a94fbe41469ea9d6f2b01ca1b\ntimeCreated: 1512009160\nlicenseType: Store\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n  defaultReferences: []\n  executionOrder: 0\n  icon: {instanceID: 0}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Runtime/Core/UxmlAttribute.cs",
    "content": "using System;\nusing System.Diagnostics;\n\nnamespace Figma.Attributes\n{\n    using static Internals.PathExtensions;\n\n    [DebuggerStepThrough]\n    [AttributeUsage(AttributeTargets.Class)]\n    public class UxmlAttribute : Attribute\n    {\n        public const string prefix = \"Document\";\n\n        #region Properties\n        public string Root { get; }\n        public string DocumentRoot { get; }\n        public string[] Preserve { get; }\n        public string[] DocumentPreserve { get; }\n        public UxmlDownloadImages DownloadImages { get; }\n        public UxmlElementTypeIdentification TypeIdentification { get; }\n        #endregion\n\n        #region Constructors\n        public UxmlAttribute(string root = null, UxmlDownloadImages downloadImages = UxmlDownloadImages.Everything, UxmlElementTypeIdentification typeIdentification = UxmlElementTypeIdentification.ByName, params string[] preserve)\n        {\n            Root = root;\n\n            DocumentRoot = CombinePath(prefix, root);\n            Preserve = preserve;\n            DocumentPreserve = (string[])preserve.Clone();\n\n            for (int i = 0; i < preserve.Length; ++i)\n                DocumentPreserve[i] = CombinePath(prefix, DocumentPreserve[i]);\n\n            DownloadImages = downloadImages;\n            TypeIdentification = typeIdentification;\n        }\n        #endregion\n    }\n}"
  },
  {
    "path": "Runtime/Core/UxmlAttribute.cs.meta",
    "content": "fileFormatVersion: 2\nguid: c1215fc5876343f49f128b37e1181924\ntimeCreated: 1728307231"
  },
  {
    "path": "Runtime/Core/VisualElementMetadata.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing System.Reflection;\nusing UnityEngine;\nusing UnityEngine.Pool;\nusing UnityEngine.UIElements;\nusing Debug = UnityEngine.Debug;\n\n// ReSharper disable MemberCanBePrivate.Global\n// ReSharper disable UnusedMember.Global\n\nnamespace Figma\n{\n    using Attributes;\n    using Internals;\n    using static Internals.PathExtensions;\n\n    public static class VisualElementMetadata\n    {\n        const int initialCollectionCapacity = 256;\n\n        record Metadata(UIDocument document, UxmlAttribute uxml, string path);\n\n        #region Fields\n        static readonly Dictionary<VisualElement, Metadata> rootMetadata = new(initialCollectionCapacity);\n        static readonly List<VisualElement> search = new(initialCollectionCapacity);\n        static readonly Dictionary<VisualElement, string> cloneMap = new(initialCollectionCapacity);\n        static readonly List<VisualElement> hide = new(initialCollectionCapacity);\n        #endregion\n\n        #region Properties\n        public static BindingFlags FieldsFlags => BindingFlags.NonPublic | BindingFlags.Instance;\n        public static BindingFlags MethodsFlags => BindingFlags.NonPublic | BindingFlags.Instance;\n        #endregion\n\n        #region Callbacks\n        public static Action<VisualElement, UIDocument, UxmlAttribute> OnInitializeRoot { get; set; }\n        public static Action<VisualElement, object, Type, FieldInfo, QueryAttribute, QueryAttribute> OnInitializeElement { get; set; }\n        public static Action<VisualElement> OnRebuildElement { get; set; }\n        #endregion\n\n        #region Methods\n        public static void Initialize(UIDocument document, IEnumerable<IRootElement> targets) => targets.Where(x => x != null).ForEach(x => Initialize(document, x));\n        public static void Initialize(UIDocument document, IRootElement target)\n        {\n            Type targetType = target.GetType();\n            UxmlAttribute uxml = targetType.GetCustomAttribute<UxmlAttribute>();\n            VisualElement targetRoot = document.rootVisualElement.Find(uxml.DocumentRoot, throwException: false, silent: false);\n\n            if (targetRoot == null)\n                return;\n\n            rootMetadata.Add(targetRoot, new Metadata(document, uxml, uxml.DocumentRoot));\n\n            (string path, VisualElement element)[] rootsPreserved = uxml.DocumentPreserve.Select(x => (x, document.rootVisualElement.Find(x, throwException: false, silent: false))).ToArray();\n\n            rootsPreserved.Where(x => !rootMetadata.ContainsKey(x.element))\n                          .ForEach(x => rootMetadata.Add(x.element, new Metadata(document, uxml, x.path)));\n\n            OnInitializeRoot?.Invoke(targetRoot, document, uxml);\n            Initialize(target, targetType, targetRoot);\n            target.OnInitialize(targetRoot, rootsPreserved.Select(x => x.element).ToArray());\n        }\n        public static void Initialize(ISubElement target, VisualElement targetRoot)\n        {\n            Initialize(target, target.GetType(), targetRoot);\n            target.OnInitialize();\n\n            if (target.GetType().GetCustomAttribute<QueryAttribute>() is { } queryAttribute)\n                OnInitializeElement?.Invoke(targetRoot, null, null, null, null, queryAttribute);\n        }\n        public static void Rebuild(IEnumerable<IRootElement> targets)\n        {\n            foreach (IRootElement target in targets.Where(x => x.Root != null))\n            {\n                target.OnRebuild();\n                target.Root.Children().ForEach(Rebuild);\n            }\n        }\n        public static void Rebuild(VisualElement target)\n        {\n            if (target is ISubElement targetSubElement)\n                targetSubElement.OnRebuild();\n\n            target.Children().ForEach(Rebuild);\n\n            OnRebuildElement?.Invoke(target);\n\n            if (hide.Contains(target))\n                target.Hide();\n        }\n\n        public static IEnumerable<T> Search<T>(this VisualElement value, string path, string className = null) where T : VisualElement\n        {\n            static bool StartsWith(string path, VisualElement value, int startIndex)\n            {\n                int endIndex = startIndex + value.name.Length;\n                return path.BeginsWith(value.name, startIndex) && path.Length >= endIndex && (path.Length == endIndex || path[endIndex].IsSeparator());\n            }\n            static int LastIndexOf(VisualElement root, VisualElement leaf, VisualElement value, string path, int startIndex = 0)\n            {\n                if (value.parent != null && value.parent != root)\n                    startIndex = LastIndexOf(root, leaf, value.parent, path, startIndex);\n\n                if (startIndex < 0 || !StartsWith(path, value, startIndex))\n                    return -1;\n\n                int endIndex = startIndex + value.name.Length;\n\n                if (path.Length > endIndex && path[endIndex].IsSeparator() && value != leaf)\n                    endIndex++;\n\n                return endIndex;\n            }\n            static void SearchIn(VisualElement value, string path, int startIndex = 0, string className = null)\n            {\n                static bool EqualsTo(VisualElement value, string path, int startIndex) => path.EqualsTo(value.name, startIndex);\n\n                search.AddRange(value.Children().Where(child => child.name.NotNullOrEmpty() && EqualsTo(child, path, startIndex) && (className.NullOrEmpty() || child.ClassListContains(className))));\n\n                value.Children()\n                     .Where(child => child.name.NotNullOrEmpty() && StartsWith(path, child, startIndex))\n                     .ForEach(child => SearchIn(child, path, startIndex + child.name.Length + 1, className));\n            }\n            static void SearchByFullPath(VisualElement value, string path, int startIndex = 0, string className = null)\n            {\n                static bool EqualsToFullPath(VisualElement root, VisualElement value, string path, int startIndex) => LastIndexOf(root, value, value, path, startIndex) == path.Length;\n                static bool StartsWithFullPath(VisualElement root, VisualElement value, string path, int startIndex)\n                {\n                    int endIndex = LastIndexOf(root, value, value, path, startIndex);\n                    return endIndex >= 0 && path.Length > endIndex && path[endIndex].IsSeparator();\n                }\n\n                search.AddRange(value.Children().Where(child => child.name.NotNullOrEmpty() && EqualsToFullPath(value, child, path, startIndex) && (className.NullOrEmpty() || child.ClassListContains(className))));\n\n                value.Children()\n                     .Where(child => child.name.NotNullOrEmpty() && StartsWithFullPath(value, child, path, startIndex))\n                     .ForEach(child => SearchByFullPath(child, path, startIndex + child.name.Length + 1, className));\n            }\n\n            search.Clear();\n\n            VisualElement root = FindRoot(value);\n\n            if (root != null)\n            {\n                UxmlAttribute uxml = rootMetadata[root].uxml;\n\n                if (path.BeginsWith(uxml.DocumentRoot) || uxml.DocumentPreserve.Any(x => path.BeginsWith(x)))\n                    SearchByFullPath(root.parent.parent.parent, path, 0, className);\n                else\n                    SearchIn(value, path, 0, className);\n            }\n            else\n            {\n                SearchByFullPath(value, path, 0, className);\n            }\n\n            foreach (T result in search.OfType<T>())\n                yield return result;\n        }\n        public static void Dispose()\n        {\n            VisualElementExtensions.cloneDictionary.Clear();\n            rootMetadata.Clear();\n            cloneMap.Clear();\n            search.Clear();\n            hide.Clear();\n        }\n        public static VisualElement FindByPath(this VisualElement root, string path)\n        {\n            foreach (VisualElement child in root.Children())\n            {\n                VisualElement result = FindByPathRecursive(child, path);\n                if (result != null) return result;\n            }\n\n            return null;\n        }\n        public static T Find<T>(this VisualElement value, string path, bool throwException = true, bool silent = false) where T : VisualElement\n        {\n            path = path.Replace('\\\\', unixPathSeperator);\n\n            T result = value.FindByPath(path).As<T>();\n\n            if (result == null && value is TemplateContainer)\n                result = value.Children().First().FindByPath(path).As<T>();\n\n            if (result != null)\n                return result;\n\n            if (throwException)\n                throw new KeyNotFoundException(Extensions.BuildTargetMessage($\"Cannot find {typeof(T).Name}\", $\"{value.GetFullPath()}{Path.DirectorySeparatorChar}{path}\"));\n\n            if (!silent)\n                Debug.LogWarning(Extensions.BuildTargetMessage($\"[{nameof(VisualElementMetadata)}] Cannot find {typeof(T).Name}\", $\"{value.GetFullPath()}{Path.DirectorySeparatorChar}{path}\"));\n\n            return null;\n        }\n        public static (T1, T2) Find<T1, T2>(this VisualElement value, string path1, string path2, bool throwException = true, bool silent = false) where T1 : VisualElement where T2 : VisualElement => (value.Find<T1>(path1, throwException: throwException, silent: silent), value.Find<T2>(path2, throwException: throwException, silent: silent));\n        public static (T1, T2, T3) Find<T1, T2, T3>(this VisualElement value, string path1, string path2, string path3, bool throwException = true, bool silent = false) where T1 : VisualElement where T2 : VisualElement where T3 : VisualElement => (value.Find<T1>(path1, throwException: throwException, silent: silent), value.Find<T2>(path2, throwException: throwException, silent: silent), value.Find<T3>(path3, throwException: throwException, silent: silent));\n        public static VisualElement Find(this VisualElement value, string path, bool throwException = true, bool silent = true) => Find<VisualElement>(value, path, throwException, silent);\n\n        public static T Clone<T>(this T value, VisualElement parent = null, int index = -1) where T : VisualElement\n        {\n            (TemplateContainer, string) GetNearestTemplate(VisualElement value, string path = \"\")\n            {\n                while (true)\n                {\n                    if (value is TemplateContainer template)\n                        return (template, path);\n\n                    if (value.parent is null)\n                        return (null, string.Empty);\n\n                    string subPath = CombinePath(value.name, path);\n                    value = value.parent;\n                    path = subPath;\n                }\n            }\n\n            parent ??= value.parent;\n\n            (VisualElement root, string pathToValue) = FindRoot(value, string.Empty);\n            Metadata metadata = rootMetadata[root];\n\n            VisualElement temporaryContainer = new();\n\n            try\n            {\n                T elementClone;\n\n                if (cloneMap.ContainsKey(value) &&\n                    cloneMap[value] is { } template &&\n                    metadata.document.visualTreeAsset.templateDependencies.FirstOrDefault(x => x.name == template) is { } treeAsset && treeAsset)\n                {\n                    treeAsset.CloneTree(temporaryContainer);\n                    elementClone = (T)temporaryContainer[0];\n                }\n                else\n                {\n                    (TemplateContainer nearestTemplate, string templatePath) = GetNearestTemplate(value);\n\n                    if (nearestTemplate != null)\n                    {\n                        string dependencyName = value.GetType().Name;\n                        VisualTreeAsset asset = nearestTemplate.templateSource.templateDependencies.FirstOrDefault(x => x.name == dependencyName);\n\n                        if (asset == null && cloneMap.ContainsKey(value) && cloneMap[value] is { } templateNameFallback)\n                            asset = nearestTemplate.templateSource.templateDependencies.FirstOrDefault(x => x.name == templateNameFallback);\n\n                        if (asset != null)\n                        {\n                            elementClone = (T)Activator.CreateInstance(value.GetType());\n                            asset.CloneTree(elementClone.contentContainer);\n                            elementClone.CopyStyle(value);\n                            value.GetClasses().ForEach(x => elementClone.AddToClassList(x));\n                        }\n                        else\n                        {\n                            nearestTemplate.templateSource.CloneTree(temporaryContainer);\n                            elementClone = temporaryContainer.Find<T>(pathToValue, false) ?? temporaryContainer.Find<T>(templatePath);\n                        }\n                    }\n                    else\n                    {\n                        Debug.LogWarning($\"[{nameof(VisualElementMetadata)}] Cloning directly {value.GetType().Name}\");\n                        metadata.document.visualTreeAsset.CloneTree(temporaryContainer);\n                        elementClone = temporaryContainer.Find(metadata.path).Find<T>(pathToValue);\n                    }\n                }\n\n                elementClone.RemoveFromHierarchy();\n\n                parent.Add(elementClone);\n\n                if (value.parent == elementClone.parent)\n                    elementClone.PlaceBehind(value);\n                if (index >= 0)\n                    elementClone.name = $\"{value.name} {nameof(VisualElement)}:{index}\";\n\n                parent.MarkDirtyRepaint();\n\n                if (elementClone is ISubElement subElement)\n                {\n                    Initialize(subElement, elementClone);\n                    Rebuild(elementClone);\n                }\n\n                elementClone.MarginMe();\n\n                return elementClone;\n            }\n            catch (Exception exception)\n            {\n                throw new ArgumentException(Extensions.BuildTargetMessage($\"Cannot clone {typeof(T).Name}\", value.name), exception);\n            }\n            finally\n            {\n                temporaryContainer.RemoveFromHierarchy();\n                temporaryContainer.Clear();\n                temporaryContainer.MarkDirtyRepaint();\n            }\n        }\n        public static VisualElement Clone(this VisualElement value, VisualElement parent = null, int index = -1) => Clone<VisualElement>(value, parent, index);\n\n        public static T Replace<T>(this VisualElement value, VisualElement prefab) where T : VisualElement\n        {\n            VisualElement parent = value.parent;\n            T elementClone = (T)prefab.Clone(parent);\n\n            if (value.resolvedStyle.position == Position.Relative)\n            {\n                elementClone.style.position = value.style.position;\n                elementClone.style.left = value.style.left;\n                elementClone.style.top = value.style.top;\n                elementClone.style.bottom = value.style.bottom;\n                elementClone.style.right = value.style.right;\n            }\n            else\n            {\n                elementClone.style.alignItems = value.resolvedStyle.alignItems;\n                elementClone.style.alignContent = value.resolvedStyle.alignContent;\n                elementClone.style.justifyContent = value.resolvedStyle.justifyContent;\n                elementClone.style.flexGrow = value.resolvedStyle.flexGrow;\n                elementClone.style.flexShrink = value.resolvedStyle.flexShrink;\n                elementClone.style.flexDirection = value.resolvedStyle.flexDirection;\n                elementClone.style.flexWrap = value.resolvedStyle.flexWrap;\n\n                elementClone.style.position = value.resolvedStyle.position;\n                elementClone.style.left = value.resolvedStyle.left;\n                elementClone.style.top = value.resolvedStyle.top;\n                elementClone.style.bottom = value.resolvedStyle.bottom;\n                elementClone.style.right = value.resolvedStyle.right;\n            }\n\n            elementClone.style.alignSelf = value.resolvedStyle.alignSelf;\n            elementClone.name = value.name;\n\n            elementClone.RemoveFromHierarchy();\n            parent.Insert(parent.IndexOf(value), elementClone);\n            parent.MarkDirtyRepaint();\n\n            value.RemoveFromHierarchy();\n            value.Clear();\n            value.MarkDirtyRepaint();\n\n            return elementClone;\n        }\n        public static VisualElement Replace(this VisualElement value, VisualElement prefab) => Replace<VisualElement>(value, prefab);\n\n        public static void CopyStyleList(this VisualElement value, VisualElement source)\n        {\n            value.ClearClassList();\n            source.GetClasses().ForEach(value.AddToClassList);\n        }\n        public static void CopyResolvedStyle(this VisualElement value, VisualElement source, CopyStyleMask copyMask = CopyStyleMask.All)\n        {\n            IStyle style = value.style;\n            IResolvedStyle valueResolvedStyle = value.resolvedStyle;\n            IResolvedStyle sourceResolvedStyle = source.resolvedStyle;\n\n            if (copyMask.HasFlag(CopyStyleMask.Position))\n            {\n                style.position = sourceResolvedStyle.position;\n                style.left = sourceResolvedStyle.left;\n                style.right = sourceResolvedStyle.right;\n                style.top = sourceResolvedStyle.top;\n                style.bottom = sourceResolvedStyle.bottom;\n                style.scale = sourceResolvedStyle.scale;\n                style.rotate = sourceResolvedStyle.rotate;\n            }\n\n            if (copyMask.HasFlag(CopyStyleMask.Size))\n            {\n                style.width = sourceResolvedStyle.width;\n                style.height = sourceResolvedStyle.height;\n            }\n\n            if (copyMask.HasFlag(CopyStyleMask.Flex))\n            {\n                if (valueResolvedStyle.justifyContent != sourceResolvedStyle.justifyContent) style.justifyContent = sourceResolvedStyle.justifyContent;\n                if (valueResolvedStyle.alignSelf != sourceResolvedStyle.alignSelf) style.alignSelf = sourceResolvedStyle.alignSelf;\n                if (valueResolvedStyle.alignItems != sourceResolvedStyle.alignItems) style.alignItems = sourceResolvedStyle.alignItems;\n                if (valueResolvedStyle.alignContent != sourceResolvedStyle.alignContent) style.alignContent = sourceResolvedStyle.alignContent;\n\n                if (valueResolvedStyle.flexWrap != sourceResolvedStyle.flexWrap) style.flexWrap = sourceResolvedStyle.flexWrap;\n                if (valueResolvedStyle.flexShrink != sourceResolvedStyle.flexShrink) style.flexShrink = sourceResolvedStyle.flexShrink;\n                if (valueResolvedStyle.flexGrow != sourceResolvedStyle.flexGrow) style.flexGrow = sourceResolvedStyle.flexGrow;\n                if (valueResolvedStyle.flexDirection != sourceResolvedStyle.flexDirection) style.flexDirection = sourceResolvedStyle.flexDirection;\n                if (valueResolvedStyle.flexBasis != sourceResolvedStyle.flexBasis) style.flexBasis = sourceResolvedStyle.flexBasis.value;\n            }\n\n            if (copyMask.HasFlag(CopyStyleMask.Display))\n            {\n                if (valueResolvedStyle.display != sourceResolvedStyle.display) style.display = sourceResolvedStyle.display;\n                if (valueResolvedStyle.opacity != sourceResolvedStyle.opacity) style.opacity = sourceResolvedStyle.opacity;\n                if (valueResolvedStyle.visibility != sourceResolvedStyle.visibility) style.visibility = sourceResolvedStyle.visibility;\n                if (valueResolvedStyle.unityBackgroundImageTintColor != sourceResolvedStyle.unityBackgroundImageTintColor) style.unityBackgroundImageTintColor = sourceResolvedStyle.unityBackgroundImageTintColor;\n                if (valueResolvedStyle.backgroundPositionX != sourceResolvedStyle.backgroundPositionX) style.backgroundPositionX = sourceResolvedStyle.backgroundPositionX;\n                if (valueResolvedStyle.backgroundPositionY != sourceResolvedStyle.backgroundPositionY) style.backgroundPositionY = sourceResolvedStyle.backgroundPositionY;\n                if (valueResolvedStyle.backgroundRepeat != sourceResolvedStyle.backgroundRepeat) style.backgroundRepeat = sourceResolvedStyle.backgroundRepeat;\n                if (valueResolvedStyle.backgroundSize != sourceResolvedStyle.backgroundSize) style.backgroundSize = sourceResolvedStyle.backgroundSize;\n                if (valueResolvedStyle.backgroundImage != sourceResolvedStyle.backgroundImage) style.backgroundImage = sourceResolvedStyle.backgroundImage;\n                if (valueResolvedStyle.backgroundColor != sourceResolvedStyle.backgroundColor) style.backgroundColor = sourceResolvedStyle.backgroundColor;\n                if (valueResolvedStyle.color != sourceResolvedStyle.color) style.color = sourceResolvedStyle.color;\n            }\n\n            if (copyMask.HasFlag(CopyStyleMask.Padding))\n            {\n                if (valueResolvedStyle.paddingTop != sourceResolvedStyle.paddingTop) style.paddingTop = sourceResolvedStyle.paddingTop;\n                if (valueResolvedStyle.paddingRight != sourceResolvedStyle.paddingRight) style.paddingRight = sourceResolvedStyle.paddingRight;\n                if (valueResolvedStyle.paddingLeft != sourceResolvedStyle.paddingLeft) style.paddingLeft = sourceResolvedStyle.paddingLeft;\n                if (valueResolvedStyle.paddingBottom != sourceResolvedStyle.paddingBottom) style.paddingBottom = sourceResolvedStyle.paddingBottom;\n            }\n\n            if (copyMask.HasFlag(CopyStyleMask.Margins))\n            {\n                if (valueResolvedStyle.marginTop != sourceResolvedStyle.marginTop) style.marginTop = sourceResolvedStyle.marginTop;\n                if (valueResolvedStyle.marginRight != sourceResolvedStyle.marginRight) style.marginRight = sourceResolvedStyle.marginRight;\n                if (valueResolvedStyle.marginLeft != sourceResolvedStyle.marginLeft) style.marginLeft = sourceResolvedStyle.marginLeft;\n                if (valueResolvedStyle.marginBottom != sourceResolvedStyle.marginBottom) style.marginBottom = sourceResolvedStyle.marginBottom;\n            }\n\n            if (copyMask.HasFlag(CopyStyleMask.Borders))\n            {\n                if (valueResolvedStyle.borderTopLeftRadius != sourceResolvedStyle.borderTopLeftRadius) style.borderTopLeftRadius = sourceResolvedStyle.borderTopLeftRadius;\n                if (valueResolvedStyle.borderTopColor != sourceResolvedStyle.borderTopColor) style.borderTopColor = sourceResolvedStyle.borderTopColor;\n                if (valueResolvedStyle.borderRightWidth != sourceResolvedStyle.borderRightWidth) style.borderRightWidth = sourceResolvedStyle.borderRightWidth;\n                if (valueResolvedStyle.borderRightColor != sourceResolvedStyle.borderRightColor) style.borderRightColor = sourceResolvedStyle.borderRightColor;\n                if (valueResolvedStyle.borderLeftWidth != sourceResolvedStyle.borderLeftWidth) style.borderLeftWidth = sourceResolvedStyle.borderLeftWidth;\n                if (valueResolvedStyle.borderLeftColor != sourceResolvedStyle.borderLeftColor) style.borderLeftColor = sourceResolvedStyle.borderLeftColor;\n                if (valueResolvedStyle.borderTopRightRadius != sourceResolvedStyle.borderTopRightRadius) style.borderTopRightRadius = sourceResolvedStyle.borderTopRightRadius;\n                if (valueResolvedStyle.borderBottomWidth != sourceResolvedStyle.borderBottomWidth) style.borderBottomWidth = sourceResolvedStyle.borderBottomWidth;\n                if (valueResolvedStyle.borderBottomLeftRadius != sourceResolvedStyle.borderBottomLeftRadius) style.borderBottomLeftRadius = sourceResolvedStyle.borderBottomLeftRadius;\n                if (valueResolvedStyle.borderBottomColor != sourceResolvedStyle.borderBottomColor) style.borderBottomColor = sourceResolvedStyle.borderBottomColor;\n                if (valueResolvedStyle.borderBottomRightRadius != sourceResolvedStyle.borderBottomRightRadius) style.borderBottomRightRadius = sourceResolvedStyle.borderBottomRightRadius;\n                if (valueResolvedStyle.borderTopWidth != sourceResolvedStyle.borderTopWidth) style.borderTopWidth = sourceResolvedStyle.borderTopWidth;\n            }\n\n            if (copyMask.HasFlag(CopyStyleMask.Slicing))\n            {\n                if (valueResolvedStyle.unitySliceTop != sourceResolvedStyle.unitySliceTop) style.unitySliceTop = sourceResolvedStyle.unitySliceTop;\n                if (valueResolvedStyle.unitySliceRight != sourceResolvedStyle.unitySliceRight) style.unitySliceRight = sourceResolvedStyle.unitySliceRight;\n                if (valueResolvedStyle.unitySliceLeft != sourceResolvedStyle.unitySliceLeft) style.unitySliceLeft = sourceResolvedStyle.unitySliceLeft;\n                if (valueResolvedStyle.unitySliceBottom != sourceResolvedStyle.unitySliceBottom) style.unitySliceBottom = sourceResolvedStyle.unitySliceBottom;\n            }\n\n            if (copyMask.HasFlag(CopyStyleMask.Font))\n            {\n                if (valueResolvedStyle.whiteSpace != sourceResolvedStyle.whiteSpace) style.whiteSpace = sourceResolvedStyle.whiteSpace;\n                if (valueResolvedStyle.wordSpacing != sourceResolvedStyle.wordSpacing) style.wordSpacing = sourceResolvedStyle.wordSpacing;\n                if (valueResolvedStyle.letterSpacing != sourceResolvedStyle.letterSpacing) style.letterSpacing = sourceResolvedStyle.letterSpacing;\n                if (valueResolvedStyle.textOverflow != sourceResolvedStyle.textOverflow) style.textOverflow = sourceResolvedStyle.textOverflow;\n                if (valueResolvedStyle.fontSize != sourceResolvedStyle.fontSize) style.fontSize = sourceResolvedStyle.fontSize;\n                if (valueResolvedStyle.unityFont != sourceResolvedStyle.unityFont) style.unityFont = new StyleFont { value = sourceResolvedStyle.unityFont };\n                if (valueResolvedStyle.unityFontDefinition != sourceResolvedStyle.unityFontDefinition) style.unityFontDefinition = sourceResolvedStyle.unityFontDefinition;\n                if (valueResolvedStyle.unityParagraphSpacing != sourceResolvedStyle.unityParagraphSpacing) style.unityParagraphSpacing = sourceResolvedStyle.unityParagraphSpacing;\n                if (valueResolvedStyle.unityTextAlign != sourceResolvedStyle.unityTextAlign) style.unityTextAlign = sourceResolvedStyle.unityTextAlign;\n                if (valueResolvedStyle.unityTextOverflowPosition != sourceResolvedStyle.unityTextOverflowPosition) style.unityTextOverflowPosition = sourceResolvedStyle.unityTextOverflowPosition;\n                if (valueResolvedStyle.unityTextOutlineWidth != sourceResolvedStyle.unityTextOutlineWidth) style.unityTextOutlineWidth = sourceResolvedStyle.unityTextOutlineWidth;\n                if (valueResolvedStyle.unityTextOutlineColor != sourceResolvedStyle.unityTextOutlineColor) style.unityTextOutlineColor = sourceResolvedStyle.unityTextOutlineColor;\n                if (valueResolvedStyle.unityFontStyleAndWeight != sourceResolvedStyle.unityFontStyleAndWeight) style.unityFontStyleAndWeight = sourceResolvedStyle.unityFontStyleAndWeight;\n            }\n        }\n        public static void CopyStyle(this VisualElement value, VisualElement source, CopyStyleMask copyMask = CopyStyleMask.All)\n        {\n            IStyle valueStyle = value.style;\n            IStyle sourceStyle = source.style;\n\n            if (copyMask.HasFlag(CopyStyleMask.Position))\n            {\n                if (sourceStyle.position.keyword != StyleKeyword.Null && valueStyle.position != sourceStyle.position) valueStyle.position = sourceStyle.position;\n                if (sourceStyle.top.keyword != StyleKeyword.Null && valueStyle.top != sourceStyle.top) valueStyle.top = sourceStyle.top;\n                if (sourceStyle.bottom.keyword != StyleKeyword.Null && valueStyle.bottom != sourceStyle.bottom) valueStyle.bottom = sourceStyle.bottom;\n                if (sourceStyle.left.keyword != StyleKeyword.Null && valueStyle.left != sourceStyle.left) valueStyle.left = sourceStyle.left;\n                if (sourceStyle.right.keyword != StyleKeyword.Null && valueStyle.right != sourceStyle.right) valueStyle.right = sourceStyle.right;\n                if (sourceStyle.translate.keyword != StyleKeyword.Null && valueStyle.translate != sourceStyle.translate) valueStyle.translate = valueStyle.translate = sourceStyle.translate;\n                if (sourceStyle.rotate.keyword != StyleKeyword.Null && valueStyle.rotate != sourceStyle.rotate) valueStyle.rotate = sourceStyle.rotate;\n                if (sourceStyle.scale.keyword != StyleKeyword.Null && valueStyle.scale != sourceStyle.scale) valueStyle.scale = sourceStyle.scale;\n                if (sourceStyle.transitionTimingFunction.keyword != StyleKeyword.Null && valueStyle.transitionTimingFunction != sourceStyle.transitionTimingFunction) valueStyle.transitionTimingFunction = sourceStyle.transitionTimingFunction;\n                if (sourceStyle.transitionProperty.keyword != StyleKeyword.Null && valueStyle.transitionProperty != sourceStyle.transitionProperty) valueStyle.transitionProperty = sourceStyle.transitionProperty;\n                if (sourceStyle.transitionDuration.keyword != StyleKeyword.Null && valueStyle.transitionDuration != sourceStyle.transitionDuration) valueStyle.transitionDuration = sourceStyle.transitionDuration;\n                if (sourceStyle.transitionDelay.keyword != StyleKeyword.Null && valueStyle.transitionDelay != sourceStyle.transitionDelay) valueStyle.transitionDelay = sourceStyle.transitionDelay;\n                if (sourceStyle.transformOrigin.keyword != StyleKeyword.Null && valueStyle.transformOrigin != sourceStyle.transformOrigin) valueStyle.transformOrigin = sourceStyle.transformOrigin;\n            }\n\n            if (copyMask.HasFlag(CopyStyleMask.Size))\n            {\n                if (sourceStyle.width.keyword != StyleKeyword.Null && valueStyle.width != sourceStyle.width) valueStyle.width = sourceStyle.width;\n                if (sourceStyle.minWidth.keyword != StyleKeyword.Null && valueStyle.minWidth != sourceStyle.minWidth) valueStyle.minWidth = sourceStyle.minWidth;\n                if (sourceStyle.maxWidth.keyword != StyleKeyword.Null && valueStyle.maxWidth != sourceStyle.maxWidth) valueStyle.maxWidth = sourceStyle.maxWidth;\n                if (sourceStyle.height.keyword != StyleKeyword.Null && valueStyle.height != sourceStyle.height) valueStyle.height = sourceStyle.height;\n                if (sourceStyle.minHeight.keyword != StyleKeyword.Null && valueStyle.minHeight != sourceStyle.minHeight) valueStyle.minHeight = sourceStyle.minHeight;\n                if (sourceStyle.maxHeight.keyword != StyleKeyword.Null && valueStyle.maxHeight != sourceStyle.maxHeight) valueStyle.maxHeight = sourceStyle.maxHeight;\n            }\n\n            if (copyMask.HasFlag(CopyStyleMask.Flex))\n            {\n                if (sourceStyle.alignSelf.keyword != StyleKeyword.Null && valueStyle.alignSelf != sourceStyle.alignSelf) valueStyle.alignSelf = sourceStyle.alignSelf;\n                if (sourceStyle.alignContent.keyword != StyleKeyword.Null && valueStyle.alignContent != sourceStyle.alignContent) valueStyle.alignContent = sourceStyle.alignContent;\n                if (sourceStyle.alignItems.keyword != StyleKeyword.Null && valueStyle.alignItems != sourceStyle.alignItems) valueStyle.alignItems = sourceStyle.alignItems;\n                if (sourceStyle.justifyContent.keyword != StyleKeyword.Null && valueStyle.justifyContent != sourceStyle.justifyContent) valueStyle.justifyContent = sourceStyle.justifyContent;\n\n                if (sourceStyle.flexDirection.keyword != StyleKeyword.Null && valueStyle.flexDirection != sourceStyle.flexDirection) valueStyle.flexDirection = sourceStyle.flexDirection;\n                if (sourceStyle.flexWrap.keyword != StyleKeyword.Null && valueStyle.flexWrap != sourceStyle.flexWrap) valueStyle.flexWrap = sourceStyle.flexWrap;\n                if (sourceStyle.flexBasis.keyword != StyleKeyword.Null && valueStyle.flexBasis != sourceStyle.flexBasis) valueStyle.flexBasis = sourceStyle.flexBasis.value;\n                if (sourceStyle.flexShrink.keyword != StyleKeyword.Null && valueStyle.flexShrink != sourceStyle.flexShrink) valueStyle.flexShrink = sourceStyle.flexShrink;\n                if (sourceStyle.flexGrow.keyword != StyleKeyword.Null && valueStyle.flexGrow != sourceStyle.flexGrow) valueStyle.flexGrow = sourceStyle.flexGrow;\n            }\n\n            if (copyMask.HasFlag(CopyStyleMask.Display))\n            {\n                if (sourceStyle.display.keyword != StyleKeyword.Null && valueStyle.display != sourceStyle.display) valueStyle.display = sourceStyle.display;\n                if (sourceStyle.visibility.keyword != StyleKeyword.Null && valueStyle.visibility != sourceStyle.visibility) valueStyle.visibility = sourceStyle.visibility;\n                if (sourceStyle.opacity.keyword != StyleKeyword.Null && valueStyle.opacity != sourceStyle.opacity) valueStyle.opacity = sourceStyle.opacity;\n                if (sourceStyle.color.keyword != StyleKeyword.Null && valueStyle.color != sourceStyle.color) valueStyle.color = sourceStyle.color;\n                if (sourceStyle.backgroundImage.keyword != StyleKeyword.Null && valueStyle.backgroundImage != sourceStyle.backgroundImage) valueStyle.backgroundImage = sourceStyle.backgroundImage;\n                if (sourceStyle.backgroundColor.keyword != StyleKeyword.Null && valueStyle.backgroundColor != sourceStyle.backgroundColor) valueStyle.backgroundColor = sourceStyle.backgroundColor;\n                if (sourceStyle.unityBackgroundImageTintColor.keyword != StyleKeyword.Null && valueStyle.unityBackgroundImageTintColor != sourceStyle.unityBackgroundImageTintColor) valueStyle.unityBackgroundImageTintColor = sourceStyle.unityBackgroundImageTintColor;\n                if (sourceStyle.backgroundPositionX.keyword != StyleKeyword.Null && valueStyle.backgroundPositionX != sourceStyle.backgroundPositionX) valueStyle.backgroundPositionX = sourceStyle.backgroundPositionX;\n                if (sourceStyle.backgroundPositionY.keyword != StyleKeyword.Null && valueStyle.backgroundPositionY != sourceStyle.backgroundPositionY) valueStyle.backgroundPositionY = sourceStyle.backgroundPositionY;\n                if (sourceStyle.backgroundRepeat.keyword != StyleKeyword.Null && valueStyle.backgroundRepeat != sourceStyle.backgroundRepeat) valueStyle.backgroundRepeat = sourceStyle.backgroundRepeat;\n                if (sourceStyle.backgroundSize.keyword != StyleKeyword.Null && valueStyle.backgroundSize != sourceStyle.backgroundSize) valueStyle.backgroundSize = sourceStyle.backgroundSize;\n            }\n\n            if (copyMask.HasFlag(CopyStyleMask.Padding))\n            {\n                if (sourceStyle.paddingTop.keyword != StyleKeyword.Null && valueStyle.paddingTop != sourceStyle.paddingTop) valueStyle.paddingTop = sourceStyle.paddingTop;\n                if (sourceStyle.paddingLeft.keyword != StyleKeyword.Null && valueStyle.paddingLeft != sourceStyle.paddingLeft) valueStyle.paddingLeft = sourceStyle.paddingLeft;\n                if (sourceStyle.paddingRight.keyword != StyleKeyword.Null && valueStyle.paddingRight != sourceStyle.paddingRight) valueStyle.paddingRight = sourceStyle.paddingRight;\n                if (sourceStyle.paddingBottom.keyword != StyleKeyword.Null && valueStyle.paddingBottom != sourceStyle.paddingBottom) valueStyle.paddingBottom = sourceStyle.paddingBottom;\n            }\n\n            if (copyMask.HasFlag(CopyStyleMask.Margins))\n            {\n                if (sourceStyle.marginTop.keyword != StyleKeyword.Null && valueStyle.marginTop != sourceStyle.marginTop) valueStyle.marginTop = sourceStyle.marginTop;\n                if (sourceStyle.marginLeft.keyword != StyleKeyword.Null && valueStyle.marginLeft != sourceStyle.marginLeft) valueStyle.marginLeft = sourceStyle.marginLeft;\n                if (sourceStyle.marginRight.keyword != StyleKeyword.Null && valueStyle.marginRight != sourceStyle.marginRight) valueStyle.marginRight = sourceStyle.marginRight;\n                if (sourceStyle.marginBottom.keyword != StyleKeyword.Null && valueStyle.marginBottom != sourceStyle.marginBottom) valueStyle.marginBottom = sourceStyle.marginBottom;\n            }\n\n            if (copyMask.HasFlag(CopyStyleMask.Borders))\n            {\n                if (sourceStyle.borderTopColor.keyword != StyleKeyword.Null && valueStyle.borderTopColor != sourceStyle.borderTopColor) valueStyle.borderTopColor = sourceStyle.borderTopColor;\n                if (sourceStyle.borderTopWidth.keyword != StyleKeyword.Null && valueStyle.borderTopWidth != sourceStyle.borderTopWidth) valueStyle.borderTopWidth = sourceStyle.borderTopWidth;\n                if (sourceStyle.borderRightWidth.keyword != StyleKeyword.Null && valueStyle.borderRightWidth != sourceStyle.borderRightWidth) valueStyle.borderRightWidth = sourceStyle.borderRightWidth;\n                if (sourceStyle.borderRightColor.keyword != StyleKeyword.Null && valueStyle.borderRightColor != sourceStyle.borderRightColor) valueStyle.borderRightColor = sourceStyle.borderRightColor;\n                if (sourceStyle.borderLeftWidth.keyword != StyleKeyword.Null && valueStyle.borderLeftWidth != sourceStyle.borderLeftWidth) valueStyle.borderLeftWidth = sourceStyle.borderLeftWidth;\n                if (sourceStyle.borderLeftColor.keyword != StyleKeyword.Null && valueStyle.borderLeftColor != sourceStyle.borderLeftColor) valueStyle.borderLeftColor = sourceStyle.borderLeftColor;\n                if (sourceStyle.borderBottomWidth.keyword != StyleKeyword.Null && valueStyle.borderBottomWidth != sourceStyle.borderBottomWidth) valueStyle.borderBottomWidth = sourceStyle.borderBottomWidth;\n                if (sourceStyle.borderBottomColor.keyword != StyleKeyword.Null && valueStyle.borderBottomColor != sourceStyle.borderBottomColor) valueStyle.borderBottomColor = sourceStyle.borderBottomColor;\n                if (sourceStyle.borderTopLeftRadius.keyword != StyleKeyword.Null && valueStyle.borderTopLeftRadius != sourceStyle.borderTopLeftRadius) valueStyle.borderTopLeftRadius = sourceStyle.borderTopLeftRadius;\n                if (sourceStyle.borderTopRightRadius.keyword != StyleKeyword.Null && valueStyle.borderTopRightRadius != sourceStyle.borderTopRightRadius) valueStyle.borderTopRightRadius = sourceStyle.borderTopRightRadius;\n                if (sourceStyle.borderBottomLeftRadius.keyword != StyleKeyword.Null && valueStyle.borderBottomLeftRadius != sourceStyle.borderBottomLeftRadius) valueStyle.borderBottomLeftRadius = sourceStyle.borderBottomLeftRadius;\n                if (sourceStyle.borderBottomRightRadius.keyword != StyleKeyword.Null && valueStyle.borderBottomRightRadius != sourceStyle.borderBottomRightRadius) valueStyle.borderBottomRightRadius = sourceStyle.borderBottomRightRadius;\n            }\n\n            if (copyMask.HasFlag(CopyStyleMask.Slicing))\n            {\n                if (sourceStyle.unitySliceLeft.keyword != StyleKeyword.Null && valueStyle.unitySliceLeft != sourceStyle.unitySliceLeft) valueStyle.unitySliceLeft = sourceStyle.unitySliceLeft;\n                if (sourceStyle.unitySliceTop.keyword != StyleKeyword.Null && valueStyle.unitySliceTop != sourceStyle.unitySliceTop) valueStyle.unitySliceTop = sourceStyle.unitySliceTop;\n                if (sourceStyle.unitySliceRight.keyword != StyleKeyword.Null && valueStyle.unitySliceRight != sourceStyle.unitySliceRight) valueStyle.unitySliceRight = sourceStyle.unitySliceRight;\n                if (sourceStyle.unitySliceBottom.keyword != StyleKeyword.Null && valueStyle.unitySliceBottom != sourceStyle.unitySliceBottom) valueStyle.unitySliceBottom = sourceStyle.unitySliceBottom;\n            }\n\n            if (copyMask.HasFlag(CopyStyleMask.Font))\n            {\n                if (sourceStyle.fontSize.keyword != StyleKeyword.Null && valueStyle.fontSize != sourceStyle.fontSize) valueStyle.fontSize = sourceStyle.fontSize;\n                if (sourceStyle.wordSpacing.keyword != StyleKeyword.Null && valueStyle.wordSpacing != sourceStyle.wordSpacing) valueStyle.wordSpacing = sourceStyle.wordSpacing;\n                if (sourceStyle.whiteSpace.keyword != StyleKeyword.Null && valueStyle.whiteSpace != sourceStyle.whiteSpace) valueStyle.whiteSpace = sourceStyle.whiteSpace;\n                if (sourceStyle.letterSpacing.keyword != StyleKeyword.Null && valueStyle.letterSpacing != sourceStyle.letterSpacing) valueStyle.letterSpacing = sourceStyle.letterSpacing;\n                if (sourceStyle.textOverflow.keyword != StyleKeyword.Null && valueStyle.textOverflow != sourceStyle.textOverflow) valueStyle.textOverflow = sourceStyle.textOverflow;\n                if (sourceStyle.unityFont.keyword != StyleKeyword.Null && valueStyle.unityFont != sourceStyle.unityFont) valueStyle.unityFont = sourceStyle.unityFont;\n                if (sourceStyle.unityFontDefinition.keyword != StyleKeyword.Null && valueStyle.unityFontDefinition != sourceStyle.unityFontDefinition) valueStyle.unityFontDefinition = sourceStyle.unityFontDefinition;\n                if (sourceStyle.unityTextOverflowPosition.keyword != StyleKeyword.Null && valueStyle.unityTextOverflowPosition != sourceStyle.unityTextOverflowPosition) valueStyle.unityTextOverflowPosition = sourceStyle.unityTextOverflowPosition;\n                if (sourceStyle.unityTextOutlineWidth.keyword != StyleKeyword.Null && valueStyle.unityTextOutlineWidth != sourceStyle.unityTextOutlineWidth) valueStyle.unityTextOutlineWidth = sourceStyle.unityTextOutlineWidth;\n                if (sourceStyle.unityTextOutlineColor.keyword != StyleKeyword.Null && valueStyle.unityTextOutlineColor != sourceStyle.unityTextOutlineColor) valueStyle.unityTextOutlineColor = sourceStyle.unityTextOutlineColor;\n                if (sourceStyle.unityTextAlign.keyword != StyleKeyword.Null && valueStyle.unityTextAlign != sourceStyle.unityTextAlign) valueStyle.unityTextAlign = sourceStyle.unityTextAlign;\n                if (sourceStyle.unityParagraphSpacing.keyword != StyleKeyword.Null && valueStyle.unityParagraphSpacing != sourceStyle.unityParagraphSpacing) valueStyle.unityParagraphSpacing = sourceStyle.unityParagraphSpacing;\n                if (sourceStyle.unityFontStyleAndWeight.keyword != StyleKeyword.Null && valueStyle.unityFontStyleAndWeight != sourceStyle.unityFontStyleAndWeight) valueStyle.unityFontStyleAndWeight = sourceStyle.unityFontStyleAndWeight;\n            }\n        }\n\n        public static float GetItemSpacing(this ICustomStyle style) => style.TryGetValue(new CustomStyleProperty<float>(\"--item-spacing\"), out float spacing) ? spacing : float.NaN;\n        public static async void MarginMe(this VisualElement value)\n        {\n            static int GetLines(VisualElement value, VisualElement parent, float spacing, bool horizontalDirection)\n            {\n                float valueSize = horizontalDirection ? value.resolvedStyle.width : value.resolvedStyle.height;\n                float parentSize = horizontalDirection ? parent.resolvedStyle.width : parent.resolvedStyle.height;\n\n                return valueSize.Invalid() || valueSize == 0 ? parent.childCount : (int)(parentSize / ((2 * valueSize + (spacing.Invalid() ? 0 : spacing)) / 2));\n            }\n\n            await Awaiters.EndOfFrame;\n\n            if (!value.IsShowing() || value.parent == null)\n                return;\n\n            VisualElement parent = value.parent;\n            float spacing = parent.customStyle.GetItemSpacing();\n\n            if (spacing.Invalid())\n                return;\n\n            using PooledObject<List<VisualElement>> pooledObject = ListPool<VisualElement>.Get(out List<VisualElement> children);\n\n            children.AddRange(parent.Children().Where(x => x.resolvedStyle.display is DisplayStyle.Flex && x.resolvedStyle.position is Position.Relative));\n\n            if (children.Count == 0)\n                return;\n\n            bool horizontalDirection = parent.resolvedStyle.flexDirection == FlexDirection.Row;\n            bool hasWrap = parent.resolvedStyle.flexWrap == Wrap.Wrap;\n\n            if (hasWrap)\n            {\n                for (float i = 0; i < 1; i += Time.deltaTime)\n                {\n                    await Awaiters.NextFrame;\n                    if (value.resolvedStyle.width > 0)\n                        break;\n                }\n            }\n\n            int lines = hasWrap ? GetLines(value, parent, spacing, horizontalDirection) : children.Count;\n            int index = children.IndexOf(value);\n            float primaryMargin = lines > 0 && (index - 1) % lines != lines - 1 ? spacing : 0;\n            float counterMargin = index >= lines ? spacing : 0;\n\n            if (index == children.Count - 1)\n            {\n                value.style.marginRight = 0;\n                value.style.marginBottom = 0;\n            }\n\n            if (horizontalDirection)\n            {\n                if (index > 0) children[index - 1].style.marginRight = primaryMargin;\n                if (index >= lines) children[index - lines].style.marginBottom = counterMargin;\n            }\n            else\n            {\n                if (index > 0) children[index - 1].style.marginBottom = primaryMargin;\n                if (index >= lines) children[index - lines].style.marginRight = counterMargin;\n            }\n        }\n\n        public static IEnumerable<(FieldInfo field, string path)> GetAllElementsPaths(Type targetType)\n        {\n            UxmlAttribute attribute = targetType.GetCustomAttribute<UxmlAttribute>();\n            string root = attribute == null ? string.Empty : attribute.Root;\n\n            QueryAttribute queryRoot = null;\n\n            foreach (FieldInfo field in targetType.GetFields(FieldsFlags))\n            {\n                QueryAttribute query = field.GetCustomAttribute<QueryAttribute>();\n\n                if (query == null)\n                    continue;\n\n                if (query.StartRoot)\n                    queryRoot = query;\n\n                yield return (field, CombinePath(root, queryRoot?.Path, query.Path));\n\n                if (query.EndRoot)\n                    queryRoot = null;\n            }\n        }\n        #endregion\n\n        #region Support Methods\n        static VisualElement FindByPathRecursive(this VisualElement root, string path, string subPath = \"\")\n        {\n            if (root == null)\n                return null;\n\n            subPath = !string.IsNullOrEmpty(subPath) ? CombinePath(subPath, root.name) : root.name;\n\n            if (path == subPath)\n                return root;\n\n            if (!path.StartsWith(subPath + unixPathSeperator) && path != subPath)\n                return null;\n\n            foreach (VisualElement child in root.Children())\n            {\n                VisualElement result = FindByPathRecursive(child, path, subPath);\n                if (result != null)\n                    return result;\n            }\n\n            switch (root)\n            {\n                case TemplateContainer { contentContainer: not null } templateContainer:\n                {\n                    foreach (VisualElement child in templateContainer.Children().First().Children())\n                    {\n                        VisualElement result = FindByPathRecursive(child, path, subPath);\n                        if (result != null)\n                            return result;\n                    }\n\n                    break;\n                }\n\n                case ScrollView view:\n                {\n                    foreach (VisualElement child in view.contentContainer.Children())\n                    {\n                        VisualElement result = FindByPathRecursive(child, path, subPath);\n                        if (result != null)\n                            return result;\n                    }\n\n                    break;\n                }\n            }\n\n            return null;\n        }\n        static VisualElement FindRoot(VisualElement value)\n        {\n\n            for (int depth = 0; depth < Const.maximumAllowedDepthLimit; depth++)\n            {\n                value = value.parent;\n\n                if (value == null)\n                    return null;\n\n                if (rootMetadata.ContainsKey(value))\n                    return value;\n            }\n\n            throw new InvalidOperationException(Const.maximumDepthLimitReachedExceptionMessage);\n        }\n        static (VisualElement value, string path) FindRoot(VisualElement value, string path)\n        {\n            while (true)\n            {\n                if (rootMetadata.ContainsKey(value))\n                    return (value, path);\n\n                if (value.parent == null)\n                    throw new ArgumentNullException(nameof(value));\n\n                string name = value.name.Split($\" {nameof(VisualElement)}:\", StringSplitOptions.RemoveEmptyEntries).FirstOrDefault() ?? value.name;\n                value = value.parent;\n                path = path.NotNullOrEmpty() ? CombinePath(name, path) : name;\n            }\n        }\n        static void Initialize(object target, Type targetType, VisualElement targetRoot, bool throwException = false, bool silent = false)\n        {\n            void RegisterCallback(VisualElement value, QueryAttribute query)\n            {\n                void Add<TEventType>(VisualElement element, string name, TrickleDown trickleDown) where TEventType : EventBase<TEventType>, new()\n                {\n                    if (name.NullOrEmpty())\n                        return;\n\n                    MethodInfo methodInfo = targetType.GetMethod(name, MethodsFlags);\n\n                    if (methodInfo != null)\n                        element.RegisterCallback((EventCallback<TEventType>)Delegate.CreateDelegate(typeof(EventCallback<TEventType>), target, methodInfo.Name, true), trickleDown);\n                    else\n                        Debug.LogWarning($\"Method '<color=yellow>{name}</color>' for element [{value.GetFullPath()}] not found. Maybe the method is private in the base class or does not exist.\");\n                }\n\n                Add<MouseCaptureOutEvent>(value, query.MouseCaptureOutEvent, query.UseTrickleDown);\n                Add<MouseCaptureEvent>(value, query.MouseCaptureEvent, query.UseTrickleDown);\n\n                Add<ValidateCommandEvent>(value, query.ValidateCommandEvent, query.UseTrickleDown);\n                Add<ExecuteCommandEvent>(value, query.ExecuteCommandEvent, query.UseTrickleDown);\n#if UNITY_EDITOR\n                Add<DragExitedEvent>(value, query.DragExitedEvent, query.UseTrickleDown);\n                Add<DragUpdatedEvent>(value, query.DragUpdatedEvent, query.UseTrickleDown);\n                Add<DragPerformEvent>(value, query.DragPerformEvent, query.UseTrickleDown);\n                Add<DragEnterEvent>(value, query.DragEnterEvent, query.UseTrickleDown);\n                Add<DragLeaveEvent>(value, query.DragLeaveEvent, query.UseTrickleDown);\n#endif\n                Add<FocusOutEvent>(value, query.FocusOutEvent, query.UseTrickleDown);\n                Add<BlurEvent>(value, query.BlurEvent, query.UseTrickleDown);\n                Add<FocusInEvent>(value, query.FocusInEvent, query.UseTrickleDown);\n                Add<FocusEvent>(value, query.FocusEvent, query.UseTrickleDown);\n                Add<InputEvent>(value, query.InputEvent, query.UseTrickleDown);\n                Add<KeyDownEvent>(value, query.KeyDownEvent, query.UseTrickleDown);\n                Add<KeyUpEvent>(value, query.KeyUpEvent, query.UseTrickleDown);\n                Add<GeometryChangedEvent>(value, query.GeometryChangedEvent, query.UseTrickleDown);\n                Add<PointerDownEvent>(value, query.PointerDownEvent, query.UseTrickleDown);\n                Add<PointerUpEvent>(value, query.PointerUpEvent, query.UseTrickleDown);\n                Add<PointerMoveEvent>(value, query.PointerMoveEvent, query.UseTrickleDown);\n                Add<MouseDownEvent>(value, query.MouseDownEvent, query.UseTrickleDown);\n                Add<MouseUpEvent>(value, query.MouseUpEvent, query.UseTrickleDown);\n                Add<MouseMoveEvent>(value, query.MouseMoveEvent, query.UseTrickleDown);\n                Add<ContextClickEvent>(value, query.ContextClickEvent, query.UseTrickleDown);\n                Add<WheelEvent>(value, query.WheelEvent, query.UseTrickleDown);\n                Add<MouseEnterEvent>(value, query.MouseEnterEvent, query.UseTrickleDown);\n                Add<MouseLeaveEvent>(value, query.MouseLeaveEvent, query.UseTrickleDown);\n                Add<MouseEnterWindowEvent>(value, query.MouseEnterWindowEvent, query.UseTrickleDown);\n                Add<MouseLeaveWindowEvent>(value, query.MouseLeaveWindowEvent, query.UseTrickleDown);\n                Add<MouseOverEvent>(value, query.MouseOverEvent, query.UseTrickleDown);\n                Add<MouseOutEvent>(value, query.MouseOutEvent, query.UseTrickleDown);\n                Add<ContextualMenuPopulateEvent>(value, query.ContextualMenuPopulateEvent, query.UseTrickleDown);\n                Add<AttachToPanelEvent>(value, query.AttachToPanelEvent, query.UseTrickleDown);\n                Add<DetachFromPanelEvent>(value, query.DetachFromPanelEvent, query.UseTrickleDown);\n                Add<TooltipEvent>(value, query.TooltipEvent, query.UseTrickleDown);\n                Add<IMGUIEvent>(value, query.IMGUIEvent, query.UseTrickleDown);\n            }\n            void RegisterValueChangedCallback(VisualElement value, QueryAttribute query)\n            {\n                EventCallback<TEventType> GetCallback<TEventType>(string name) where TEventType : EventBase<TEventType>, new()\n                {\n                    MethodInfo methodInfo = targetType.GetMethod(name, MethodsFlags);\n\n                    if (methodInfo != null)\n                        return (EventCallback<TEventType>)Delegate.CreateDelegate(typeof(EventCallback<TEventType>), target, methodInfo.Name, true);\n\n                    throw new NotSupportedException();\n                }\n\n                if (query.ChangeEvent.NotNullOrEmpty() && value is TextField textField)\n                    textField.RegisterValueChangedCallback(GetCallback<ChangeEvent<string>>(query.ChangeEvent));\n\n                if (query.ChangeEvent.NotNullOrEmpty() && value is Toggle toggleField)\n                    toggleField.RegisterValueChangedCallback(GetCallback<ChangeEvent<bool>>(query.ChangeEvent));\n\n                if (query.ChangeEvent.NotNullOrEmpty() && value is SliderInt sliderIntField)\n                    sliderIntField.RegisterValueChangedCallback(GetCallback<ChangeEvent<int>>(query.ChangeEvent));\n\n                if (query.ChangeEvent.NotNullOrEmpty() && value is INotifyValueChanged<float> notifyFloatValueChanged)\n                    notifyFloatValueChanged.RegisterValueChangedCallback(GetCallback<ChangeEvent<float>>(query.ChangeEvent));\n            }\n            void AddClicked(VisualElement value, QueryAttribute query)\n            {\n                if (query.Clicked.NullOrEmpty() || value is not Button button)\n                    return;\n\n                MethodInfo methodInfo = targetType.GetMethod(query.Clicked, BindingFlags.NonPublic | BindingFlags.Instance);\n\n                if (methodInfo != null)\n                    button.clicked += (Action)Delegate.CreateDelegate(typeof(Action), target, methodInfo.Name, true);\n                else\n                    Debug.LogWarning($\"Method '<color=yellow>{query.Clicked}</color>' for element [{value.GetFullPath()}] not found. Maybe the method is private in the base class or does not exist.\");\n            }\n            void AddTemplate(VisualElement value, QueryAttribute query)\n            {\n                if (query.Template.NullOrEmpty() && !query.Hash)\n                    return;\n\n                if (query.Hash)\n                {\n                    cloneMap.Add(value, value.tooltip);\n                    value.tooltip = null;\n                }\n                else\n                {\n                    cloneMap.Add(value, query.Template);\n                }\n            }\n            VisualElement InitializeElement(FieldInfo field, QueryAttribute queryRoot, QueryAttribute query)\n            {\n                VisualElement ResolveElement(QueryAttribute queryRoot, QueryAttribute query)\n                {\n                    VisualElement queryRootElement = targetRoot;\n                    if (queryRoot != null && !queryRoot.Path.NullOrEmpty() && queryRoot.Path != query.Path)\n                        queryRootElement = targetRoot.Find<VisualElement>(queryRoot.Path, false) ?? targetRoot;\n\n                    VisualElement value = queryRootElement.Find<VisualElement>(query.Path, !query.Nullable, query.Nullable);\n\n                    if (query.ReplaceElementPath.NotNullOrEmpty())\n                    {\n                        if (value != null)\n                        {\n                            value = value.Replace(targetRoot.Find(query.ReplaceElementPath));\n                        }\n                        else\n                        {\n                            string name = Path.GetFileName(query.Path);\n\n                            if (name == query.Path)\n                            {\n                                value = targetRoot.Find<VisualElement>(query.ReplaceElementPath, throwException, silent)?.Clone(targetRoot);\n                            }\n                            else\n                            {\n                                string path = query.Path.Remove(query.Path.Length - name.Length - 1, name.Length + 1);\n                                value = targetRoot.Find<VisualElement>(query.ReplaceElementPath, throwException, silent)?.Clone(targetRoot.Find<VisualElement>(path));\n                            }\n\n                            if (value != null)\n                                value.name = name;\n                        }\n                    }\n\n                    if (query.RebuildElementEvent.NotNullOrEmpty())\n                    {\n                        MethodInfo methodInfo = targetType.GetMethod(query.RebuildElementEvent, MethodsFlags);\n                        if (methodInfo != null)\n                            value = (VisualElement)methodInfo.Invoke(target, new object[] { value });\n                    }\n\n                    if (value == null)\n                        return null;\n\n                    Type valueType = value.GetType();\n\n                    if (valueType != field.FieldType && valueType.IsAssignableFrom(field.FieldType) && field.FieldType != typeof(VisualElement))\n                    {\n                        if (throwException)\n                            throw new InvalidOperationException($\"Element `{value.name}` of type=[{value.GetType()}] cannot be inserted into `{field.Name}` with type=[{field.FieldType}]\");\n\n                        if (!silent)\n                            Debug.LogWarning($\"[{nameof(VisualElementMetadata)}] Element `{value.name}` of type=[{value.GetType()}] cannot be inserted into `{field.Name}` with type=[{field.FieldType}]\");\n\n                        return null;\n                    }\n\n                    field.SetValue(target, value);\n\n                    return value;\n                }\n\n                if (query == null)\n                    throw new ArgumentNullException(nameof(query));\n\n                VisualElement element = ResolveElement(queryRoot, query);\n\n                if (element == null)\n                    return null;\n\n                RegisterCallback(element, query);\n                RegisterValueChangedCallback(element, query);\n                AddClicked(element, query);\n                AddTemplate(element, query);\n\n                return element;\n            }\n\n            QueryAttribute queryRoot = null;\n\n            foreach (FieldInfo field in targetType.GetFields(FieldsFlags))\n            {\n                QueryAttribute query = field.GetCustomAttribute<QueryAttribute>();\n\n                if (query == null)\n                    continue;\n\n                if (query.StartRoot)\n                    queryRoot = query;\n\n                VisualElement element = InitializeElement(field, queryRoot, query);\n\n                if (element != null)\n                    OnInitializeElement?.Invoke(element, target, targetType, field, queryRoot, query);\n\n                if (query.EndRoot)\n                    queryRoot = null;\n\n                if (element is ISubElement subElement)\n                {\n                    Initialize(subElement, field.FieldType, element, throwException, silent);\n                    subElement.OnInitialize();\n                }\n\n                if (query.Hide)\n                    hide.Add(element);\n            }\n        }\n        #endregion\n    }\n}"
  },
  {
    "path": "Runtime/Core/VisualElementMetadata.cs.meta",
    "content": "fileFormatVersion: 2\nguid: 46d8035533165cc498ba4642614403d3\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n  defaultReferences: []\n  executionOrder: 0\n  icon: {instanceID: 0}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Runtime/Core.meta",
    "content": "fileFormatVersion: 2\nguid: a2887f4413b54672bad1ba5d2c6d7350\ntimeCreated: 1728307245"
  },
  {
    "path": "Runtime/Extensions/EnumerableExtensions.cs",
    "content": "using System;\nusing System.Linq;\nusing System.Threading;\nusing System.Threading.Tasks;\nusing System.Collections.Generic;\n\nnamespace Figma\n{\n    internal static class EnumerableExtensions\n    {\n        #region Methods\n        internal static async Task ForEachParallelAsync<T>(this IEnumerable<T> elements, int maxConcurrentRequests, Func<T, Task> func, CancellationToken token)\n        {\n            using SemaphoreSlim semaphore = new(maxConcurrentRequests);\n            Task[] tasks = elements.Select(async x =>\n            {\n                await semaphore.WaitAsync(token);\n                await func(x);\n                semaphore.Release();\n            }).ToArray();\n            await Task.WhenAll(tasks);\n        }\n        internal static IEnumerable<List<TSource>> Chunk<TSource>(this IEnumerable<TSource> source, int size)\n        {\n            using IEnumerator<TSource> enumerator = source.GetEnumerator();\n            bool hasMoreElements = true;\n\n            do\n            {\n                List<TSource> chunk = new(size);\n                while (size > chunk.Count && (hasMoreElements = enumerator.MoveNext()))\n                    chunk.Add(enumerator.Current);\n                if (chunk.Count == 0)\n                    break;\n                yield return chunk;\n            } while (hasMoreElements);\n        }\n        #endregion\n    }\n}"
  },
  {
    "path": "Runtime/Extensions/EnumerableExtensions.cs.meta",
    "content": "fileFormatVersion: 2\nguid: a0dc8b85c82ec86fa8aa435da7d2c758\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n  defaultReferences: []\n  executionOrder: 0\n  icon: {instanceID: 0}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Runtime/Extensions/Extensions.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.Diagnostics;\n\nnamespace Figma.Internals\n{\n    [DebuggerStepThrough]\n    internal static class Extensions\n    {\n        #region Methods\n        internal static bool NullOrEmpty(this string value) => string.IsNullOrEmpty(value);\n        internal static bool NotNullOrEmpty(this string value) => !string.IsNullOrEmpty(value);\n        internal static bool Invalid(this float value) => float.IsNaN(value) || float.IsInfinity(value);\n        internal static void ForEach<T>(this IEnumerable<T> enumerable, Action<T> action)\n        {\n            foreach (T element in enumerable)\n                action(element);\n        }\n#if UNITY_EDITOR\n        internal static string BuildTargetMessage(string message, string target, string end = null) => $\"{message} [<color={(UnityEditor.EditorGUIUtility.isProSkin ? \"yellow\" : \"#aaaa00\")}>{target}</color>] {end ?? string.Empty}\";\n#else\n        internal static string BuildTargetMessage(string message, string target, string end = null) => $\"{message} [{target}] {end ?? string.Empty}\";\n#endif\n        #endregion\n    }\n}"
  },
  {
    "path": "Runtime/Extensions/Extensions.cs.meta",
    "content": "fileFormatVersion: 2\nguid: f333cb303f7c42e589d3a706dade2e0a\ntimeCreated: 1727960585"
  },
  {
    "path": "Runtime/Extensions/PathExtensions.cs",
    "content": "using System;\nusing System.IO;\nusing System.Linq;\nusing System.Text;\n\nnamespace Figma.Internals\n{\n    public static class PathExtensions\n    {\n        #region Const\n        public const char unixPathSeperator = '/';\n        #endregion\n\n        #region Methods\n        internal static string[] GetFiles(string path, string searchPattern, SearchOption searchOption) => Directory.GetFiles(path, searchPattern, searchOption).Select(x => x.Replace('\\\\', unixPathSeperator)).ToArray();\n        internal static string CombinePath(params string[] paths)\n        {\n            if (paths == null || paths.Length == 0)\n                throw new ArgumentNullException(nameof(paths));\n\n            StringBuilder path = new();\n\n            for (int i = 0; i < paths.Length; i++)\n            {\n                if (string.IsNullOrEmpty(paths[i]))\n                    continue;\n\n                path.Append(paths[i].Replace('\\\\', unixPathSeperator));\n\n                if (i < paths.Length - 1 && paths[i][paths[i].Length - 1] != unixPathSeperator && !string.IsNullOrEmpty(paths[i + 1]))\n                    path.Append(unixPathSeperator);\n            }\n\n            return path.ToString();\n        }\n        internal static string GetRelativePath(string from, string to) => CombinePath(Path.GetRelativePath(Path.GetDirectoryName(from), Path.GetDirectoryName(to))?.Replace('\\\\', unixPathSeperator), Path.GetFileName(to));\n        internal static string RemoveExtension(string path) => CombinePath(Path.GetDirectoryName(path)?.Replace('\\\\', unixPathSeperator), Path.GetFileNameWithoutExtension(path));\n\n        internal static bool IsSeparator(this char ch) => ch == Path.DirectorySeparatorChar || ch == Path.AltDirectorySeparatorChar;\n        internal static bool EqualsTo(this string path, string value, int startIndex = 0)\n        {\n            if (path.Length - startIndex != value.Length) return false;\n\n            int i, length = value.Length;\n            for (i = 0; i < length; ++i)\n            {\n                if (path[startIndex + i].IsSeparator() && value[i].IsSeparator() || path[startIndex + i] == value[i])\n                    continue;\n\n                return false;\n            }\n\n            return i == length;\n        }\n        internal static bool BeginsWith(this string path, string value, int startIndex = 0)\n        {\n            if (path.Length - startIndex < value.Length)\n                return false;\n\n            int i, length;\n            for (i = 0, length = value.Length; i < length; ++i)\n            {\n                if (path[startIndex + i].IsSeparator() && value[i].IsSeparator() || path[startIndex + i] == value[i])\n                    continue;\n\n                return false;\n            }\n\n            return startIndex + i == path.Length || path[startIndex + i].IsSeparator();\n        }\n        #endregion\n    }\n}"
  },
  {
    "path": "Runtime/Extensions/PathExtensions.cs.meta",
    "content": "fileFormatVersion: 2\nguid: 7967c428b3ee1604e8b5050a79c3278a\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n  defaultReferences: []\n  executionOrder: 0\n  icon: {instanceID: 0}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Runtime/Extensions/VisualElementExtensions.cs",
    "content": "using System;\nusing System.Collections;\nusing System.Collections.Generic;\nusing UnityEngine.UIElements;\n\nnamespace Figma\n{\n    using Internals;\n\n    public static class VisualElementExtensions\n    {\n        #region Fields\n        internal static readonly Dictionary<(VisualElement prefab, VisualElement parent), IList> cloneDictionary = new();\n        #endregion\n\n        #region Methods\n        public static bool HasVisibility(this VisualElement element) => element.style.visibility == Visibility.Visible;\n        public static void MakeVisible(this VisualElement element) => element.style.visibility = Visibility.Visible;\n        public static void MakeInvisible(this VisualElement element) => element.style.visibility = Visibility.Hidden;\n        public static void SetVisibility(this VisualElement element, bool visible) => element.style.visibility = visible ? Visibility.Visible : Visibility.Hidden;\n        public static bool IsShowing(this VisualElement element) => element.resolvedStyle.display == DisplayStyle.Flex;\n        public static void Show(this VisualElement element)\n        {\n            element.style.display = DisplayStyle.Flex;\n            element.MarginMe();\n        }\n        public static void Hide(this VisualElement element) => element.style.display = DisplayStyle.None;\n        public static void SetDisplay(this VisualElement element, bool visible)\n        {\n            element.style.display = visible ? DisplayStyle.Flex : DisplayStyle.None;\n            if (visible) element.MarginMe();\n        }\n        public static void Disable(this VisualElement element) => element.pickingMode = PickingMode.Ignore;\n        public static void Enable(this VisualElement element) => element.pickingMode = PickingMode.Position;\n        public static bool IsEnabled(this VisualElement element) => element.pickingMode == PickingMode.Position;\n        public static IList EnsureList<TVisualElement>(TVisualElement prefab, VisualElement parent) where TVisualElement : VisualElement\n        {\n            (TVisualElement prefab, VisualElement parent) identifier = (prefab, parent);\n\n            if (!cloneDictionary.TryGetValue(identifier, out IList elements))\n                cloneDictionary.Add(identifier, elements = (IList)Activator.CreateInstance(typeof(List<>).MakeGenericType(prefab.GetType())));\n\n            return elements;\n        }\n        public static TVisualElement GetElement<TVisualElement>(this TVisualElement prefab, int index) where TVisualElement : VisualElement => GetElements(prefab, prefab.parent)[index];\n        public static List<TVisualElement> GetElements<TVisualElement>(this TVisualElement prefab) where TVisualElement : VisualElement => GetElements(prefab, prefab.parent);\n        public static List<TVisualElement> GetElements<TVisualElement>(this TVisualElement prefab, VisualElement parent) where TVisualElement : VisualElement\n        {\n            if (EnsureList(prefab, parent) is List<TVisualElement> list) return list;\n\n            throw new ArgumentException($\"Casting from {typeof(List<TVisualElement>)} to {cloneDictionary[(prefab, parent)]}\");\n        }\n        public static List<VisualElement> GetElements(this VisualElement prefab) => GetElements<VisualElement>(prefab);\n        public static List<VisualElement> GetElements(this VisualElement prefab, VisualElement parent) => GetElements<VisualElement>(prefab, parent);\n        public static void Sync<TVisualElement, TData>(this TVisualElement prefab, VisualElement parent, IEnumerable<TData> data, Action<TVisualElement> onCreateElement = null) where TVisualElement : VisualElement, ISyncElement<TData>\n        {\n            IList elements = EnsureList(prefab, parent);\n\n            int i = 0;\n            foreach (TData value in data)\n            {\n                TVisualElement element;\n                if (i >= elements.Count)\n                {\n                    element = prefab.Clone(parent, i);\n                    element.Initialize(i);\n                    onCreateElement?.Invoke(element);\n                    elements.Add(element);\n                }\n                else\n                {\n                    element = (TVisualElement)elements[i];\n                    element.Cleanup();\n                }\n\n                if (element.IsVisible(i, value)) element.Show();\n                else element.Hide();\n\n                ++i;\n            }\n\n            for (int j = i; j < elements.Count; ++j)\n            {\n                elements[j].As<TVisualElement>().Cleanup();\n                elements[j].As<TVisualElement>().Hide();\n            }\n        }\n        public static void Sync<TVisualElement, TCreationData, TData>(this TVisualElement prefab, VisualElement parent, TCreationData creationData, IEnumerable<TData> data, Action<TVisualElement> onCreateElement = null) where TVisualElement : VisualElement, ISyncElement<TCreationData, TData>\n        {\n            IList elements = EnsureList(prefab, parent);\n\n            int i = 0;\n            foreach (TData value in data)\n            {\n                TVisualElement element;\n                if (i >= elements.Count)\n                {\n                    element = prefab.Clone(parent, i);\n                    element.Initialize(i, creationData);\n                    onCreateElement?.Invoke(element);\n                    elements.Add(element);\n                }\n                else\n                {\n                    element = (TVisualElement)elements[i];\n                    element.Cleanup();\n                }\n\n                if (element.IsVisible(i, value)) element.Show();\n                else element.Hide();\n\n                ++i;\n            }\n\n            for (int j = i; j < elements.Count; ++j)\n            {\n                elements[j].As<TVisualElement>().Cleanup();\n                elements[j].As<TVisualElement>().Hide();\n            }\n        }\n        public static T As<T>(this object value) => (T)value;\n        public static string GetFullPath(this VisualElement element)\n        {\n            string result = string.Empty;\n\n            for (int depth = 0; depth < Const.maximumAllowedDepthLimit; depth++)\n            {\n                if (element == null)\n                    return result;\n\n                result = string.IsNullOrEmpty(result) ? element.name : element.name + PathExtensions.unixPathSeperator + result;\n                element = element.parent;\n            }\n\n            throw new InvalidOperationException(Const.maximumDepthLimitReachedExceptionMessage);\n        }\n        #endregion\n    }\n}"
  },
  {
    "path": "Runtime/Extensions/VisualElementExtensions.cs.meta",
    "content": "fileFormatVersion: 2\nguid: 84fecb8572fb586409235bea58b5d37e\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n  defaultReferences: []\n  executionOrder: 0\n  icon: {instanceID: 0}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Runtime/Extensions.meta",
    "content": "fileFormatVersion: 2\nguid: 5919892104fee434aa143c8b3a125a90\nfolderAsset: yes\nDefaultImporter:\n  externalObjects: {}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Runtime/Figma.asmdef",
    "content": "{\n    \"name\": \"Figma\",\n    \"rootNamespace\": \"Figma\",\n    \"references\": [\n        \"AsyncAwaitUtil\"\n    ]\n}"
  },
  {
    "path": "Runtime/Figma.asmdef.meta",
    "content": "fileFormatVersion: 2\nguid: 8b8c60060cf03964dbd41b7237ae33c9\nAssemblyDefinitionImporter:\n  externalObjects: {}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Runtime/Figma.cs",
    "content": "﻿using System.Linq;\nusing UnityEngine;\nusing UnityEngine.UIElements;\n\nnamespace Figma\n{\n    using Attributes;\n    using System.Threading.Tasks;\n\n    [DefaultExecutionOrder(-10)]\n    [RequireComponent(typeof(UIDocument))]\n    public class Figma : MonoBehaviour\n    {\n        #region Fields\n        [SerializeField] string fileKey;\n        [SerializeField] bool filter;\n        [SerializeField] bool reorder;\n        [SerializeField] bool waitFrameBeforeRebuild = true;\n        [SerializeField] string[] fontDirectories;\n        #endregion\n\n        #region Properties\n        public string FileKey => fileKey;\n        public bool Filter => filter;\n        #endregion\n\n        #region Base Methods\n        void OnEnable()\n        {\n            if (Application.isBatchMode)\n                return;\n\n            UIDocument document = GetComponent<UIDocument>();\n\n            if (document.rootVisualElement is null)\n                return;\n\n            IRootElement[] elements = GetComponentsInChildren<IRootElement>();\n\n            VisualElementMetadata.Initialize(document, elements);\n\n            if (!Application.isPlaying)\n                return;\n\n#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed\n            OnEnableNextFrameAsync();\n#pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed\n            return;\n\n            // Do not make MonoBehaviour.OnEnable async because Unity calls async methods after non-async MonoBehaviour methods\n            async Task OnEnableNextFrameAsync()\n            {\n                // Do not change this to Awaiters, since it is breaking the loading.\n                if (waitFrameBeforeRebuild)\n                    await new WaitForEndOfFrame();\n\n                VisualElementMetadata.Rebuild(elements);\n\n                VisualElement root = document.rootVisualElement.Q(UxmlAttribute.prefix);\n\n                if (root is null || !reorder)\n                    return;\n\n                foreach (IRootElement element in elements.Where(x => x.Root is not null).OrderBy(x => x.RootOrder))\n                {\n                    element.Root.RemoveFromHierarchy();\n                    root.Add(element.Root);\n                }\n            }\n        }\n        void OnDestroy() => VisualElementMetadata.Dispose();\n        #endregion\n    }\n}"
  },
  {
    "path": "Runtime/Figma.cs.meta",
    "content": "fileFormatVersion: 2\nguid: aaa4e5d0dd7bf25488b120aa854832eb\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n  defaultReferences: []\n  executionOrder: 0\n  icon: {instanceID: 0}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Runtime/Interface/Const.cs",
    "content": "using System.Globalization;\n\nnamespace Figma\n{\n    public static class Const\n    {\n        public const int maximumAllowedDepthLimit = 0x10000; // This is a random big number.\n        public const string maximumDepthLimitReachedExceptionMessage = \"Maximum depth limit is exceeded.\";\n\n        public static readonly CultureInfo Culture = CultureInfo.GetCultureInfo(\"en-US\");\n        public const int initialCollectionCapacity = 128;\n\n        public const string indentCharacters = \"    \";\n    }\n}"
  },
  {
    "path": "Runtime/Interface/Const.cs.meta",
    "content": "fileFormatVersion: 2\nguid: b406df7817a64f298f19ebf7facbbdb8\ntimeCreated: 1747643661"
  },
  {
    "path": "Runtime/Interface/Core/SubElements.cs",
    "content": "using UnityEngine.UIElements;\n\nnamespace Figma\n{\n    public abstract class SubVisualElement : VisualElement, ISubElement\n    {\n        #region Methods\n        protected virtual void OnInitialize() { }\n        protected virtual void OnRebuild() { }\n\n        void ISubElement.OnInitialize() => OnInitialize();\n        void ISubElement.OnRebuild() => OnRebuild();\n        #endregion\n    }\n\n    public abstract class SubButton : Button, ISubElement\n    {\n        #region Methods\n        protected virtual void OnInitialize() { }\n        protected virtual void OnRebuild() { }\n\n        void ISubElement.OnInitialize() => OnInitialize();\n        void ISubElement.OnRebuild() => OnRebuild();\n        #endregion\n    }\n\n    public abstract class SubLabel : Label, ISubElement\n    {\n        #region Methods\n        protected virtual void OnInitialize() { }\n        protected virtual void OnRebuild() { }\n\n        void ISubElement.OnInitialize() => OnInitialize();\n        void ISubElement.OnRebuild() => OnRebuild();\n        #endregion\n    }\n\n    public abstract class SubScrollView : ScrollView, ISubElement\n    {\n        #region Methods\n        protected virtual void OnInitialize() { }\n        protected virtual void OnRebuild() { }\n\n        void ISubElement.OnInitialize() => OnInitialize();\n        void ISubElement.OnRebuild() => OnRebuild();\n        #endregion\n    }\n}"
  },
  {
    "path": "Runtime/Interface/Core/SubElements.cs.meta",
    "content": "fileFormatVersion: 2\nguid: 99f85b01fae873ffdac3884951113a85\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n  defaultReferences: []\n  executionOrder: 0\n  icon: {instanceID: 0}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Runtime/Interface/Core/SyncElements.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing UnityEngine.UIElements;\n\nnamespace Figma\n{\n    public abstract class SyncVisualElement<T> : SubVisualElement, ISyncElement<T>\n    {\n        #region Methods\n        public virtual void Sync(VisualElement parent, IEnumerable<T> data) => VisualElementExtensions.Sync(this, parent, data);\n        public abstract bool IsVisible(int index, T data);\n        #endregion\n    }\n\n    public abstract class SyncVisualElement<TCreationData, TData> : SubVisualElement, ISyncElement<TCreationData, TData>\n    {\n        #region Methods\n        public virtual void Sync(VisualElement parent, TCreationData creationData, IEnumerable<TData> data) => VisualElementExtensions.Sync(this, parent, creationData, data);\n        public abstract void Initialize(int index, TCreationData creationData);\n        public abstract bool IsVisible(int index, TData data);\n        #endregion\n    }\n\n    public abstract class SyncButton<TData> : SubButton, ISyncElement<TData>\n    {\n        #region Methods\n        public virtual void Sync(VisualElement parent, IEnumerable<TData> data) => VisualElementExtensions.Sync(this, parent, data);\n        public abstract bool IsVisible(int index, TData data);\n        #endregion\n    }\n\n    public abstract class SyncButton<TCreationData, TData> : SubButton, ISyncElement<TCreationData, TData>\n    {\n        #region Methods\n        public virtual void Sync(VisualElement parent, TCreationData creationData, IEnumerable<TData> data) => VisualElementExtensions.Sync(this, parent, creationData, data);\n        public abstract void Initialize(int index, TCreationData creationData);\n        public abstract bool IsVisible(int index, TData data);\n        #endregion\n    }\n\n    public abstract class SyncButtonSimple<TData> : SubButton, ISyncElement<Action<int>, TData>\n    {\n        #region Methods\n        public virtual void Sync(VisualElement parent, Action<int> creationData, IEnumerable<TData> data) => VisualElementExtensions.Sync(this, parent, creationData, data);\n        public virtual void Initialize(int index, Action<int> creationData) => clicked += () => creationData(index);\n        public abstract bool IsVisible(int index, TData data);\n        #endregion\n    }\n\n    public abstract class SyncLabel<TData> : SubLabel, ISyncElement<TData>\n    {\n        #region Methods\n        public virtual void Sync(VisualElement parent, IEnumerable<TData> data) => VisualElementExtensions.Sync(this, parent, data);\n        public abstract bool IsVisible(int index, TData data);\n        #endregion\n    }\n\n    public abstract class SyncLabel<TCreationData, TData> : SubLabel, ISyncElement<TCreationData, TData>\n    {\n        #region Methods\n        public virtual void Sync(VisualElement parent, TCreationData creationData, IEnumerable<TData> data) => VisualElementExtensions.Sync(this, parent, creationData, data);\n        public abstract void Initialize(int index, TCreationData creationData);\n        public abstract bool IsVisible(int index, TData data);\n        #endregion\n    }\n\n    public abstract class SyncScrollView<TData> : SubScrollView, ISyncElement<TData>\n    {\n        #region Methods\n        public virtual void Sync(VisualElement parent, IEnumerable<TData> data) => VisualElementExtensions.Sync(this, parent, data);\n        public abstract bool IsVisible(int index, TData data);\n        #endregion\n    }\n\n    public abstract class SyncScrollView<TCreationData, TData> : SubScrollView, ISyncElement<TCreationData, TData>\n    {\n        #region Methods\n        public virtual void Sync(VisualElement parent, TCreationData creationData, IEnumerable<TData> data) => VisualElementExtensions.Sync(this, parent, creationData, data);\n        public abstract void Initialize(int index, TCreationData creationData);\n        public abstract bool IsVisible(int index, TData data);\n        #endregion\n    }\n}"
  },
  {
    "path": "Runtime/Interface/Core/SyncElements.cs.meta",
    "content": "fileFormatVersion: 2\nguid: fd496d4ec1c37d7af931d627ebf86023\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n  defaultReferences: []\n  executionOrder: 0\n  icon: {instanceID: 0}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Runtime/Interface/Core.meta",
    "content": "fileFormatVersion: 2\nguid: 4f9a8b3c90b78d644a304baf92e4c76d\nfolderAsset: yes\nDefaultImporter:\n  externalObjects: {}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Runtime/Interface/Enums.cs",
    "content": "﻿using System;\n\nnamespace Figma\n{\n    [Flags]\n    public enum UxmlDownloadImages\n    {\n        Everything = 0,\n        Nothing = 1 << 0,\n        ImageFills = 1 << 1,\n        RenderAsPng = 1 << 2,\n        RenderAsSvg = 1 << 3,\n        ByElements = 1 << 4\n    }\n\n    public enum UxmlElementTypeIdentification\n    {\n        ByName,\n        ByElementType\n    }\n\n    public enum ElementDownloadImage\n    {\n        Auto,\n        Download,\n        Ignore\n    }\n\n    [Flags]\n    public enum CopyStyleMask\n    {\n        None = 0,\n        Text = 1 << 0,\n        Position = 1 << 1,\n        Size = 1 << 2,\n        Flex = 1 << 3,\n        Display = 1 << 4,\n        Padding = 1 << 5,\n        Margins = 1 << 6,\n        Borders = 1 << 7,\n        Slicing = 1 << 8,\n        Font = 1 << 9,\n        All = Text | Position | Size | Flex | Display | Padding | Margins | Borders | Slicing | Font\n    }\n}"
  },
  {
    "path": "Runtime/Interface/Enums.cs.meta",
    "content": "fileFormatVersion: 2\nguid: 801e83821cb9e5f408837586af0e8d8f\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n  defaultReferences: []\n  executionOrder: 0\n  icon: {instanceID: 0}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Runtime/Interface/Interface.Core.cs",
    "content": "using System.Collections.Generic;\nusing UnityEngine.UIElements;\n\n#pragma warning disable S1186 // Functions and closures should not be empty\n\nnamespace Figma\n{\n    public interface ISyncElement<TData>\n    {\n        #region Methods\n        void Sync(VisualElement parent, IEnumerable<TData> data);\n        void Initialize(int index) { }\n        bool IsVisible(int index, TData data);\n        void Cleanup() { }\n        #endregion\n    }\n\n    public interface ISyncElement<TCreationData, TData>\n    {\n        #region Methods\n        void Sync(VisualElement parent, TCreationData creationData, IEnumerable<TData> data);\n        void Initialize(int index, TCreationData creationData);\n        bool IsVisible(int index, TData data);\n        void Cleanup() { }\n        #endregion\n    }\n}"
  },
  {
    "path": "Runtime/Interface/Interface.Core.cs.meta",
    "content": "fileFormatVersion: 2\nguid: 0162e75c60e15fd4a9bd4da8ac0c62ed\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n  defaultReferences: []\n  executionOrder: 0\n  icon: {instanceID: 0}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Runtime/Interface/Interfaces.cs",
    "content": "using UnityEngine.UIElements;\n\nnamespace Figma\n{\n    public interface ISubElement\n    {\n        #region Methods\n        void OnInitialize() { } // Method is blank intentionally\n        void OnRebuild() { } // Method is blank intentionally\n        #endregion\n    }\n\n    public interface IRootElement\n    {\n        #region Properties\n        VisualElement Root { get; }\n        int RootOrder => 0;\n        #endregion\n\n        #region Methods\n        void OnInitialize(VisualElement root, VisualElement[] rootsPreserved) { } // Method is blank intentionally \n        void OnRebuild() { } // Method is blank intentionally\n        #endregion\n    }\n}"
  },
  {
    "path": "Runtime/Interface/Interfaces.cs.meta",
    "content": "fileFormatVersion: 2\nguid: e01966bb91b67f341809945497f0ff2c\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n  defaultReferences: []\n  executionOrder: 0\n  icon: {instanceID: 0}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Runtime/Interface.meta",
    "content": "fileFormatVersion: 2\nguid: 1f0b9b39faba9904dbefcb7c550f313d\nfolderAsset: yes\nDefaultImporter:\n  externalObjects: {}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "Runtime.meta",
    "content": "fileFormatVersion: 2\nguid: 70ee33d9a3494344ab4d51378a9f394f\nfolderAsset: yes\nDefaultImporter:\n  externalObjects: {}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"com.trackman.figma\",\n  \"description\": \"Figma to Unity uxml/uss converter, utilities for VisualTree management in runtime.\",\n  \"displayName\": \"Figma for Unity\",\n  \"version\": \"1.3.5\",\n  \"unity\": \"2022.3\",\n  \"dependencies\": {\n    \"com.unity.vectorgraphics\": \"2.0.0-preview.25\",\n    \"com.unity.nuget.newtonsoft-json\": \"3.2.1\",\n    \"com.trackman.asyncawaitutil\": \"1.0.7\"\n  },\n  \"author\": \"TrackMan\",\n  \"type\": \"trackman.package\",\n  \"hideInEditor\": false\n}"
  },
  {
    "path": "package.json.meta",
    "content": "fileFormatVersion: 2\nguid: 8054faacce927e54296a8be216631c8e\nTextScriptImporter:\n  externalObjects: {}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "~Samples/Scripts/Figma.Samples.asmdef",
    "content": "{\n    \"name\": \"Figma.Samples\",\n    \"rootNamespace\": \"\",\n    \"references\": [\n        \"Figma\"\n    ],\n    \"includePlatforms\": [],\n    \"excludePlatforms\": [],\n    \"allowUnsafeCode\": false,\n    \"overrideReferences\": false,\n    \"precompiledReferences\": [],\n    \"autoReferenced\": true,\n    \"defineConstraints\": [],\n    \"versionDefines\": [],\n    \"noEngineReferences\": false\n}"
  },
  {
    "path": "~Samples/Scripts/Figma.Samples.asmdef.meta",
    "content": "fileFormatVersion: 2\nguid: 40458b32386acba81b5009a08b0c7d40\nAssemblyDefinitionImporter:\n  externalObjects: {}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "~Samples/Scripts/Test.cs",
    "content": "using System.Linq;\nusing UnityEngine.UIElements;\nusing Random = UnityEngine.Random;\n\nnamespace Figma.Samples\n{\n    using Attributes;\n\n    [Uxml(\"TestPage/TestFrame\", UxmlDownloadImages.Everything, UxmlElementTypeIdentification.ByElementType)]\n    public class Test : Element\n    {\n        const int minCircles = 1;\n        const int maxCircles = 7;\n\n        #region Fields\n        [Query(\"Header\")] Label header;\n\n        [Query(\"CloneButton\", Clicked = nameof(Clone))] Button cloneButton;\n        [Query(\"RemoveButton\", Clicked = nameof(Remove))] Button removeButton;\n        [Query(\"CloneContainer\", StartRoot = true)] VisualElement cloneContainer;\n        [Query(\"CloneCircle\", EndRoot = true)] PerfectCircle cloneCircle;\n\n        [Query(\"SyncButton\", Clicked = nameof(Sync))] Button syncButton;\n        [Query(\"SyncContainer\")] VisualElement syncContainer;\n        [Query(\"SyncContainer/SyncCircle\")] PerfectCircle syncCircle;\n\n        [Query(\"FunctionDescription\", Hide = true)] Label functionDescription;\n        #endregion\n\n        #region Methods\n        protected override void OnInitialize() => cloneContainer.style.flexWrap = Wrap.NoWrap;\n        protected override void OnRebuild() => header.text = \"Welcome to Figma Test Frame!\";\n\n        void Clone()\n        {\n            if (cloneContainer.childCount == maxCircles) return;\n\n            cloneCircle.Clone(cloneContainer);\n        }\n        void Remove()\n        {\n            if (cloneContainer.childCount == minCircles) return;\n\n            cloneContainer.Remove(cloneContainer.Children().First());\n        }\n        void Sync()\n        {\n            void RandomColor(int index) => syncContainer.Children().ElementAt(index).style.backgroundColor = Random.ColorHSV();\n\n            syncCircle.Sync(syncContainer, RandomColor, Enumerable.Range(0, Random.Range(1, maxCircles + 1)));\n            syncCircle.Hide();\n\n            functionDescription.Show();\n        }\n        #endregion\n    }\n\n    public class PerfectCircle : SyncButtonSimple<int>\n    {\n        public new class UxmlFactory : UxmlFactory<PerfectCircle> { }\n\n        #region Methods\n        public override bool IsVisible(int index, int data) => true;\n        #endregion\n    }\n}"
  },
  {
    "path": "~Samples/Scripts/Test.cs.meta",
    "content": "fileFormatVersion: 2\nguid: 51bc2941ace5c496fbf512e17e9a1939\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n  defaultReferences: []\n  executionOrder: 0\n  icon: {instanceID: 0}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "~Samples/Scripts.meta",
    "content": "fileFormatVersion: 2\nguid: a8bf1e60512441341bdf13c14f151aef\nfolderAsset: yes\nDefaultImporter:\n  externalObjects: {}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "~Samples/Test.unity",
    "content": "%YAML 1.1\n%TAG !u! tag:unity3d.com,2011:\n--- !u!29 &1\nOcclusionCullingSettings:\n  m_ObjectHideFlags: 0\n  serializedVersion: 2\n  m_OcclusionBakeSettings:\n    smallestOccluder: 5\n    smallestHole: 0.25\n    backfaceThreshold: 100\n  m_SceneGUID: 00000000000000000000000000000000\n  m_OcclusionCullingData: {fileID: 0}\n--- !u!104 &2\nRenderSettings:\n  m_ObjectHideFlags: 0\n  serializedVersion: 9\n  m_Fog: 0\n  m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1}\n  m_FogMode: 3\n  m_FogDensity: 0.01\n  m_LinearFogStart: 0\n  m_LinearFogEnd: 300\n  m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1}\n  m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1}\n  m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1}\n  m_AmbientIntensity: 1\n  m_AmbientMode: 0\n  m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1}\n  m_SkyboxMaterial: {fileID: 10304, guid: 0000000000000000f000000000000000, type: 0}\n  m_HaloStrength: 0.5\n  m_FlareStrength: 1\n  m_FlareFadeSpeed: 3\n  m_HaloTexture: {fileID: 0}\n  m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0}\n  m_DefaultReflectionMode: 0\n  m_DefaultReflectionResolution: 128\n  m_ReflectionBounces: 1\n  m_ReflectionIntensity: 1\n  m_CustomReflection: {fileID: 0}\n  m_Sun: {fileID: 0}\n  m_IndirectSpecularColor: {r: 0.37311953, g: 0.38074014, b: 0.3587274, a: 1}\n  m_UseRadianceAmbientProbe: 0\n--- !u!157 &3\nLightmapSettings:\n  m_ObjectHideFlags: 0\n  serializedVersion: 12\n  m_GIWorkflowMode: 1\n  m_GISettings:\n    serializedVersion: 2\n    m_BounceScale: 1\n    m_IndirectOutputScale: 1\n    m_AlbedoBoost: 1\n    m_EnvironmentLightingMode: 0\n    m_EnableBakedLightmaps: 1\n    m_EnableRealtimeLightmaps: 0\n  m_LightmapEditorSettings:\n    serializedVersion: 12\n    m_Resolution: 2\n    m_BakeResolution: 40\n    m_AtlasSize: 1024\n    m_AO: 0\n    m_AOMaxDistance: 1\n    m_CompAOExponent: 1\n    m_CompAOExponentDirect: 0\n    m_ExtractAmbientOcclusion: 0\n    m_Padding: 2\n    m_LightmapParameters: {fileID: 0}\n    m_LightmapsBakeMode: 1\n    m_TextureCompression: 1\n    m_FinalGather: 0\n    m_FinalGatherFiltering: 1\n    m_FinalGatherRayCount: 256\n    m_ReflectionCompression: 2\n    m_MixedBakeMode: 2\n    m_BakeBackend: 1\n    m_PVRSampling: 1\n    m_PVRDirectSampleCount: 32\n    m_PVRSampleCount: 512\n    m_PVRBounces: 2\n    m_PVREnvironmentSampleCount: 256\n    m_PVREnvironmentReferencePointCount: 2048\n    m_PVRFilteringMode: 1\n    m_PVRDenoiserTypeDirect: 1\n    m_PVRDenoiserTypeIndirect: 1\n    m_PVRDenoiserTypeAO: 1\n    m_PVRFilterTypeDirect: 0\n    m_PVRFilterTypeIndirect: 0\n    m_PVRFilterTypeAO: 0\n    m_PVREnvironmentMIS: 1\n    m_PVRCulling: 1\n    m_PVRFilteringGaussRadiusDirect: 1\n    m_PVRFilteringGaussRadiusIndirect: 5\n    m_PVRFilteringGaussRadiusAO: 2\n    m_PVRFilteringAtrousPositionSigmaDirect: 0.5\n    m_PVRFilteringAtrousPositionSigmaIndirect: 2\n    m_PVRFilteringAtrousPositionSigmaAO: 1\n    m_ExportTrainingData: 0\n    m_TrainingDataDestination: TrainingData\n    m_LightProbeSampleCountMultiplier: 4\n  m_LightingDataAsset: {fileID: 0}\n  m_LightingSettings: {fileID: 0}\n--- !u!196 &4\nNavMeshSettings:\n  serializedVersion: 2\n  m_ObjectHideFlags: 0\n  m_BuildSettings:\n    serializedVersion: 2\n    agentTypeID: 0\n    agentRadius: 0.5\n    agentHeight: 2\n    agentSlope: 45\n    agentClimb: 0.4\n    ledgeDropHeight: 0\n    maxJumpAcrossDistance: 0\n    minRegionArea: 2\n    manualCellSize: 0\n    cellSize: 0.16666667\n    manualTileSize: 0\n    tileSize: 256\n    accuratePlacement: 0\n    maxJobWorkers: 0\n    preserveTilesOutsideBounds: 0\n    debug:\n      m_Flags: 0\n  m_NavMeshData: {fileID: 0}\n--- !u!1001 &1931369715\nPrefabInstance:\n  m_ObjectHideFlags: 0\n  serializedVersion: 2\n  m_Modification:\n    m_TransformParent: {fileID: 0}\n    m_Modifications:\n    - target: {fileID: -3369783722120399799, guid: a1decc1df2e53b24285e24bfd721a22c, type: 3}\n      propertyPath: title\n      value: 11EfaZFWQFIRh68VYRJMBo\n      objectReference: {fileID: 0}\n    - target: {fileID: -3369783722120399799, guid: a1decc1df2e53b24285e24bfd721a22c, type: 3}\n      propertyPath: filter\n      value: 1\n      objectReference: {fileID: 0}\n    - target: {fileID: 2492470867148571057, guid: a1decc1df2e53b24285e24bfd721a22c, type: 3}\n      propertyPath: m_RootOrder\n      value: 1\n      objectReference: {fileID: 0}\n    - target: {fileID: 2492470867148571057, guid: a1decc1df2e53b24285e24bfd721a22c, type: 3}\n      propertyPath: m_LocalPosition.x\n      value: 0\n      objectReference: {fileID: 0}\n    - target: {fileID: 2492470867148571057, guid: a1decc1df2e53b24285e24bfd721a22c, type: 3}\n      propertyPath: m_LocalPosition.y\n      value: 0\n      objectReference: {fileID: 0}\n    - target: {fileID: 2492470867148571057, guid: a1decc1df2e53b24285e24bfd721a22c, type: 3}\n      propertyPath: m_LocalPosition.z\n      value: 0\n      objectReference: {fileID: 0}\n    - target: {fileID: 2492470867148571057, guid: a1decc1df2e53b24285e24bfd721a22c, type: 3}\n      propertyPath: m_LocalRotation.w\n      value: 1\n      objectReference: {fileID: 0}\n    - target: {fileID: 2492470867148571057, guid: a1decc1df2e53b24285e24bfd721a22c, type: 3}\n      propertyPath: m_LocalRotation.x\n      value: 0\n      objectReference: {fileID: 0}\n    - target: {fileID: 2492470867148571057, guid: a1decc1df2e53b24285e24bfd721a22c, type: 3}\n      propertyPath: m_LocalRotation.y\n      value: 0\n      objectReference: {fileID: 0}\n    - target: {fileID: 2492470867148571057, guid: a1decc1df2e53b24285e24bfd721a22c, type: 3}\n      propertyPath: m_LocalRotation.z\n      value: 0\n      objectReference: {fileID: 0}\n    - target: {fileID: 2492470867148571057, guid: a1decc1df2e53b24285e24bfd721a22c, type: 3}\n      propertyPath: m_LocalEulerAnglesHint.x\n      value: 0\n      objectReference: {fileID: 0}\n    - target: {fileID: 2492470867148571057, guid: a1decc1df2e53b24285e24bfd721a22c, type: 3}\n      propertyPath: m_LocalEulerAnglesHint.y\n      value: 0\n      objectReference: {fileID: 0}\n    - target: {fileID: 2492470867148571057, guid: a1decc1df2e53b24285e24bfd721a22c, type: 3}\n      propertyPath: m_LocalEulerAnglesHint.z\n      value: 0\n      objectReference: {fileID: 0}\n    - target: {fileID: 2916098490094507199, guid: a1decc1df2e53b24285e24bfd721a22c, type: 3}\n      propertyPath: m_Name\n      value: Figma\n      objectReference: {fileID: 0}\n    - target: {fileID: 6641805578009137364, guid: a1decc1df2e53b24285e24bfd721a22c, type: 3}\n      propertyPath: sourceAsset\n      value: \n      objectReference: {fileID: 9197481963319205126, guid: 6b8f61c2c55889e47baab4478eacf725, type: 3}\n    - target: {fileID: 6641805578009137364, guid: a1decc1df2e53b24285e24bfd721a22c, type: 3}\n      propertyPath: m_PanelSettings\n      value: \n      objectReference: {fileID: 11400000, guid: f486055d8ec653edc96c3f3c38380c8f, type: 2}\n    m_RemovedComponents: []\n  m_SourcePrefab: {fileID: 100100000, guid: a1decc1df2e53b24285e24bfd721a22c, type: 3}\n--- !u!1 &2022604971 stripped\nGameObject:\n  m_CorrespondingSourceObject: {fileID: 2916098490094507199, guid: a1decc1df2e53b24285e24bfd721a22c, type: 3}\n  m_PrefabInstance: {fileID: 1931369715}\n  m_PrefabAsset: {fileID: 0}\n--- !u!114 &2022604975\nMonoBehaviour:\n  m_ObjectHideFlags: 0\n  m_CorrespondingSourceObject: {fileID: 0}\n  m_PrefabInstance: {fileID: 0}\n  m_PrefabAsset: {fileID: 0}\n  m_GameObject: {fileID: 2022604971}\n  m_Enabled: 1\n  m_EditorHideFlags: 0\n  m_Script: {fileID: 11500000, guid: 51bc2941ace5c496fbf512e17e9a1939, type: 3}\n  m_Name: \n  m_EditorClassIdentifier: \n--- !u!1 &2089345444\nGameObject:\n  m_ObjectHideFlags: 0\n  m_CorrespondingSourceObject: {fileID: 0}\n  m_PrefabInstance: {fileID: 0}\n  m_PrefabAsset: {fileID: 0}\n  serializedVersion: 6\n  m_Component:\n  - component: {fileID: 2089345447}\n  - component: {fileID: 2089345446}\n  - component: {fileID: 2089345445}\n  m_Layer: 0\n  m_Name: Camera\n  m_TagString: Untagged\n  m_Icon: {fileID: 0}\n  m_NavMeshLayer: 0\n  m_StaticEditorFlags: 0\n  m_IsActive: 1\n--- !u!81 &2089345445\nAudioListener:\n  m_ObjectHideFlags: 0\n  m_CorrespondingSourceObject: {fileID: 0}\n  m_PrefabInstance: {fileID: 0}\n  m_PrefabAsset: {fileID: 0}\n  m_GameObject: {fileID: 2089345444}\n  m_Enabled: 1\n--- !u!20 &2089345446\nCamera:\n  m_ObjectHideFlags: 0\n  m_CorrespondingSourceObject: {fileID: 0}\n  m_PrefabInstance: {fileID: 0}\n  m_PrefabAsset: {fileID: 0}\n  m_GameObject: {fileID: 2089345444}\n  m_Enabled: 1\n  serializedVersion: 2\n  m_ClearFlags: 1\n  m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0}\n  m_projectionMatrixMode: 1\n  m_GateFitMode: 2\n  m_FOVAxisMode: 0\n  m_SensorSize: {x: 36, y: 24}\n  m_LensShift: {x: 0, y: 0}\n  m_FocalLength: 50\n  m_NormalizedViewPortRect:\n    serializedVersion: 2\n    x: 0\n    y: 0\n    width: 1\n    height: 1\n  near clip plane: 0.3\n  far clip plane: 1000\n  field of view: 60\n  orthographic: 0\n  orthographic size: 5\n  m_Depth: 0\n  m_CullingMask:\n    serializedVersion: 2\n    m_Bits: 4294967295\n  m_RenderingPath: -1\n  m_TargetTexture: {fileID: 0}\n  m_TargetDisplay: 0\n  m_TargetEye: 3\n  m_HDR: 1\n  m_AllowMSAA: 1\n  m_AllowDynamicResolution: 0\n  m_ForceIntoRT: 0\n  m_OcclusionCulling: 1\n  m_StereoConvergence: 10\n  m_StereoSeparation: 0.022\n--- !u!4 &2089345447\nTransform:\n  m_ObjectHideFlags: 0\n  m_CorrespondingSourceObject: {fileID: 0}\n  m_PrefabInstance: {fileID: 0}\n  m_PrefabAsset: {fileID: 0}\n  m_GameObject: {fileID: 2089345444}\n  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}\n  m_LocalPosition: {x: 170.51552, y: 711.87164, z: 653.8373}\n  m_LocalScale: {x: 1, y: 1, z: 1}\n  m_ConstrainProportionsScale: 0\n  m_Children: []\n  m_Father: {fileID: 0}\n  m_RootOrder: 0\n  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}\n"
  },
  {
    "path": "~Samples/Test.unity.meta",
    "content": "fileFormatVersion: 2\nguid: 37c53d635728f3fe3aa97b1d07aa4a2a\nDefaultImporter:\n  externalObjects: {}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  },
  {
    "path": "~Samples.meta",
    "content": "fileFormatVersion: 2\nguid: f562b0f5dfae4abab3176961a5070e1f\nfolderAsset: yes\nDefaultImporter:\n  externalObjects: {}\n  userData: \n  assetBundleName: \n  assetBundleVariant: \n"
  }
]