@llc3233149/core 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (457) hide show
  1. package/dist/canvaskit.d.ts +9 -0
  2. package/dist/canvaskit.d.ts.map +1 -0
  3. package/dist/canvaskit.js +55 -0
  4. package/dist/canvaskit.js.map +1 -0
  5. package/dist/clipboard.d.ts +32 -0
  6. package/dist/clipboard.d.ts.map +1 -0
  7. package/dist/clipboard.js +345 -0
  8. package/dist/clipboard.js.map +1 -0
  9. package/dist/color.d.ts +28 -0
  10. package/dist/color.d.ts.map +1 -0
  11. package/dist/color.js +67 -0
  12. package/dist/color.js.map +1 -0
  13. package/dist/constants.d.ts +159 -0
  14. package/dist/constants.d.ts.map +1 -0
  15. package/dist/constants.js +224 -0
  16. package/dist/constants.js.map +1 -0
  17. package/dist/copy.d.ts +20 -0
  18. package/dist/copy.d.ts.map +1 -0
  19. package/dist/copy.js +64 -0
  20. package/dist/copy.js.map +1 -0
  21. package/dist/fig-export-worker.d.ts +2 -0
  22. package/dist/fig-export-worker.d.ts.map +1 -0
  23. package/dist/fig-export-worker.js +17 -0
  24. package/dist/fig-export-worker.js.map +1 -0
  25. package/dist/fig-export.d.ts +13 -0
  26. package/dist/fig-export.d.ts.map +1 -0
  27. package/dist/fig-export.js +243 -0
  28. package/dist/fig-export.js.map +1 -0
  29. package/dist/figma-api.d.ts +268 -0
  30. package/dist/figma-api.d.ts.map +1 -0
  31. package/dist/figma-api.js +1074 -0
  32. package/dist/figma-api.js.map +1 -0
  33. package/dist/figma-rest-import.d.ts +122 -0
  34. package/dist/figma-rest-import.d.ts.map +1 -0
  35. package/dist/figma-rest-import.js +319 -0
  36. package/dist/figma-rest-import.js.map +1 -0
  37. package/dist/fonts.d.ts +24 -0
  38. package/dist/fonts.d.ts.map +1 -0
  39. package/dist/fonts.js +356 -0
  40. package/dist/fonts.js.map +1 -0
  41. package/dist/geometry.d.ts +14 -0
  42. package/dist/geometry.d.ts.map +1 -0
  43. package/dist/geometry.js +47 -0
  44. package/dist/geometry.js.map +1 -0
  45. package/dist/index.d.ts +38 -0
  46. package/dist/index.d.ts.map +1 -0
  47. package/dist/index.js +32 -0
  48. package/dist/index.js.map +1 -0
  49. package/dist/kiwi/codec.d.ts +292 -0
  50. package/dist/kiwi/codec.d.ts.map +1 -0
  51. package/dist/kiwi/codec.js +340 -0
  52. package/dist/kiwi/codec.js.map +1 -0
  53. package/dist/kiwi/fig-file.d.ts +4 -0
  54. package/dist/kiwi/fig-file.d.ts.map +1 -0
  55. package/dist/kiwi/fig-file.js +236 -0
  56. package/dist/kiwi/fig-file.js.map +1 -0
  57. package/dist/kiwi/fig-import.d.ts +4 -0
  58. package/dist/kiwi/fig-import.d.ts.map +1 -0
  59. package/dist/kiwi/fig-import.js +248 -0
  60. package/dist/kiwi/fig-import.js.map +1 -0
  61. package/dist/kiwi/fig-parse-worker.d.ts +7 -0
  62. package/dist/kiwi/fig-parse-worker.d.ts.map +1 -0
  63. package/dist/kiwi/fig-parse-worker.js +184 -0
  64. package/dist/kiwi/fig-parse-worker.js.map +1 -0
  65. package/dist/kiwi/instance-overrides.d.ts +66 -0
  66. package/dist/kiwi/instance-overrides.d.ts.map +1 -0
  67. package/dist/kiwi/instance-overrides.js +644 -0
  68. package/dist/kiwi/instance-overrides.js.map +1 -0
  69. package/dist/kiwi/kiwi-convert.d.ts +19 -0
  70. package/dist/kiwi/kiwi-convert.d.ts.map +1 -0
  71. package/dist/kiwi/kiwi-convert.js +678 -0
  72. package/dist/kiwi/kiwi-convert.js.map +1 -0
  73. package/dist/kiwi/kiwi-schema/bb.d.ts +25 -0
  74. package/dist/kiwi/kiwi-schema/bb.d.ts.map +1 -0
  75. package/dist/kiwi/kiwi-schema/bb.js +225 -0
  76. package/dist/kiwi/kiwi-schema/bb.js.map +1 -0
  77. package/dist/kiwi/kiwi-schema/binary.d.ts +5 -0
  78. package/dist/kiwi/kiwi-schema/binary.d.ts.map +1 -0
  79. package/dist/kiwi/kiwi-schema/binary.js +86 -0
  80. package/dist/kiwi/kiwi-schema/binary.js.map +1 -0
  81. package/dist/kiwi/kiwi-schema/index.d.ts +6 -0
  82. package/dist/kiwi/kiwi-schema/index.d.ts.map +1 -0
  83. package/dist/kiwi/kiwi-schema/index.js +5 -0
  84. package/dist/kiwi/kiwi-schema/index.js.map +1 -0
  85. package/dist/kiwi/kiwi-schema/js.d.ts +4 -0
  86. package/dist/kiwi/kiwi-schema/js.d.ts.map +1 -0
  87. package/dist/kiwi/kiwi-schema/js.js +282 -0
  88. package/dist/kiwi/kiwi-schema/js.js.map +1 -0
  89. package/dist/kiwi/kiwi-schema/parser.d.ts +5 -0
  90. package/dist/kiwi/kiwi-schema/parser.d.ts.map +1 -0
  91. package/dist/kiwi/kiwi-schema/parser.js +228 -0
  92. package/dist/kiwi/kiwi-schema/parser.js.map +1 -0
  93. package/dist/kiwi/kiwi-schema/schema.d.ts +22 -0
  94. package/dist/kiwi/kiwi-schema/schema.d.ts.map +1 -0
  95. package/dist/kiwi/kiwi-schema/schema.js +2 -0
  96. package/dist/kiwi/kiwi-schema/schema.js.map +1 -0
  97. package/dist/kiwi/kiwi-schema/util.d.ts +3 -0
  98. package/dist/kiwi/kiwi-schema/util.d.ts.map +1 -0
  99. package/dist/kiwi/kiwi-schema/util.js +10 -0
  100. package/dist/kiwi/kiwi-schema/util.js.map +1 -0
  101. package/dist/kiwi/protocol.d.ts +172 -0
  102. package/dist/kiwi/protocol.d.ts.map +1 -0
  103. package/dist/kiwi/protocol.js +214 -0
  104. package/dist/kiwi/protocol.js.map +1 -0
  105. package/dist/kiwi/schema.d.ts +3 -0
  106. package/dist/kiwi/schema.d.ts.map +1 -0
  107. package/dist/kiwi/schema.js +2285 -0
  108. package/dist/kiwi/schema.js.map +1 -0
  109. package/dist/kiwi-serialize.d.ts +17 -0
  110. package/dist/kiwi-serialize.d.ts.map +1 -0
  111. package/dist/kiwi-serialize.js +419 -0
  112. package/dist/kiwi-serialize.js.map +1 -0
  113. package/dist/layout.d.ts +9 -0
  114. package/dist/layout.d.ts.map +1 -0
  115. package/dist/layout.js +533 -0
  116. package/dist/layout.js.map +1 -0
  117. package/dist/profiler/draw-call-counter.d.ts +9 -0
  118. package/dist/profiler/draw-call-counter.d.ts.map +1 -0
  119. package/dist/profiler/draw-call-counter.js +37 -0
  120. package/dist/profiler/draw-call-counter.js.map +1 -0
  121. package/dist/profiler/frame-capture.d.ts +34 -0
  122. package/dist/profiler/frame-capture.d.ts.map +1 -0
  123. package/dist/profiler/frame-capture.js +90 -0
  124. package/dist/profiler/frame-capture.js.map +1 -0
  125. package/dist/profiler/frame-stats.d.ts +33 -0
  126. package/dist/profiler/frame-stats.d.ts.map +1 -0
  127. package/dist/profiler/frame-stats.js +103 -0
  128. package/dist/profiler/frame-stats.js.map +1 -0
  129. package/dist/profiler/gpu-timer.d.ts +15 -0
  130. package/dist/profiler/gpu-timer.d.ts.map +1 -0
  131. package/dist/profiler/gpu-timer.js +77 -0
  132. package/dist/profiler/gpu-timer.js.map +1 -0
  133. package/dist/profiler/hud-renderer.d.ts +22 -0
  134. package/dist/profiler/hud-renderer.d.ts.map +1 -0
  135. package/dist/profiler/hud-renderer.js +200 -0
  136. package/dist/profiler/hud-renderer.js.map +1 -0
  137. package/dist/profiler/index.d.ts +9 -0
  138. package/dist/profiler/index.d.ts.map +1 -0
  139. package/dist/profiler/index.js +8 -0
  140. package/dist/profiler/index.js.map +1 -0
  141. package/dist/profiler/phase-timer.d.ts +9 -0
  142. package/dist/profiler/phase-timer.d.ts.map +1 -0
  143. package/dist/profiler/phase-timer.js +51 -0
  144. package/dist/profiler/phase-timer.js.map +1 -0
  145. package/dist/profiler/render-profiler.d.ts +41 -0
  146. package/dist/profiler/render-profiler.d.ts.map +1 -0
  147. package/dist/profiler/render-profiler.js +142 -0
  148. package/dist/profiler/render-profiler.js.map +1 -0
  149. package/dist/render/components.d.ts +25 -0
  150. package/dist/render/components.d.ts.map +1 -0
  151. package/dist/render/components.js +55 -0
  152. package/dist/render/components.js.map +1 -0
  153. package/dist/render/emoji-icons.d.ts +5 -0
  154. package/dist/render/emoji-icons.d.ts.map +1 -0
  155. package/dist/render/emoji-icons.js +55 -0
  156. package/dist/render/emoji-icons.js.map +1 -0
  157. package/dist/render/export-code.d.ts +9 -0
  158. package/dist/render/export-code.d.ts.map +1 -0
  159. package/dist/render/export-code.js +335 -0
  160. package/dist/render/export-code.js.map +1 -0
  161. package/dist/render/export-jsx.d.ts +5 -0
  162. package/dist/render/export-jsx.d.ts.map +1 -0
  163. package/dist/render/export-jsx.js +621 -0
  164. package/dist/render/export-jsx.js.map +1 -0
  165. package/dist/render/index.d.ts +8 -0
  166. package/dist/render/index.d.ts.map +1 -0
  167. package/dist/render/index.js +8 -0
  168. package/dist/render/index.js.map +1 -0
  169. package/dist/render/jsx-runtime.d.ts +31 -0
  170. package/dist/render/jsx-runtime.d.ts.map +1 -0
  171. package/dist/render/jsx-runtime.js +13 -0
  172. package/dist/render/jsx-runtime.js.map +1 -0
  173. package/dist/render/mini-react.d.ts +14 -0
  174. package/dist/render/mini-react.d.ts.map +1 -0
  175. package/dist/render/mini-react.js +16 -0
  176. package/dist/render/mini-react.js.map +1 -0
  177. package/dist/render/render-jsx.d.ts +24 -0
  178. package/dist/render/render-jsx.d.ts.map +1 -0
  179. package/dist/render/render-jsx.js +51 -0
  180. package/dist/render/render-jsx.js.map +1 -0
  181. package/dist/render/renderer.d.ts +16 -0
  182. package/dist/render/renderer.d.ts.map +1 -0
  183. package/dist/render/renderer.js +437 -0
  184. package/dist/render/renderer.js.map +1 -0
  185. package/dist/render/tailwind.d.ts +20 -0
  186. package/dist/render/tailwind.d.ts.map +1 -0
  187. package/dist/render/tailwind.js +115 -0
  188. package/dist/render/tailwind.js.map +1 -0
  189. package/dist/render/tree.d.ts +72 -0
  190. package/dist/render/tree.d.ts.map +1 -0
  191. package/dist/render/tree.js +63 -0
  192. package/dist/render/tree.js.map +1 -0
  193. package/dist/render-image.d.ts +19 -0
  194. package/dist/render-image.d.ts.map +1 -0
  195. package/dist/render-image.js +84 -0
  196. package/dist/render-image.js.map +1 -0
  197. package/dist/renderer/effects.d.ts +9 -0
  198. package/dist/renderer/effects.d.ts.map +1 -0
  199. package/dist/renderer/effects.js +44 -0
  200. package/dist/renderer/effects.js.map +1 -0
  201. package/dist/renderer/fills.d.ts +9 -0
  202. package/dist/renderer/fills.d.ts.map +1 -0
  203. package/dist/renderer/fills.js +189 -0
  204. package/dist/renderer/fills.js.map +1 -0
  205. package/dist/renderer/index.d.ts +2 -0
  206. package/dist/renderer/index.d.ts.map +1 -0
  207. package/dist/renderer/index.js +2 -0
  208. package/dist/renderer/index.js.map +1 -0
  209. package/dist/renderer/label-cache.d.ts +43 -0
  210. package/dist/renderer/label-cache.d.ts.map +1 -0
  211. package/dist/renderer/label-cache.js +85 -0
  212. package/dist/renderer/label-cache.js.map +1 -0
  213. package/dist/renderer/labels.d.ts +6 -0
  214. package/dist/renderer/labels.d.ts.map +1 -0
  215. package/dist/renderer/labels.js +126 -0
  216. package/dist/renderer/labels.js.map +1 -0
  217. package/dist/renderer/lru-cache.d.ts +20 -0
  218. package/dist/renderer/lru-cache.d.ts.map +1 -0
  219. package/dist/renderer/lru-cache.js +65 -0
  220. package/dist/renderer/lru-cache.js.map +1 -0
  221. package/dist/renderer/overlays.d.ts +25 -0
  222. package/dist/renderer/overlays.d.ts.map +1 -0
  223. package/dist/renderer/overlays.js +783 -0
  224. package/dist/renderer/overlays.js.map +1 -0
  225. package/dist/renderer/renderer.d.ts +229 -0
  226. package/dist/renderer/renderer.d.ts.map +1 -0
  227. package/dist/renderer/renderer.js +909 -0
  228. package/dist/renderer/renderer.js.map +1 -0
  229. package/dist/renderer/rulers.d.ts +8 -0
  230. package/dist/renderer/rulers.d.ts.map +1 -0
  231. package/dist/renderer/rulers.js +147 -0
  232. package/dist/renderer/rulers.js.map +1 -0
  233. package/dist/renderer/scene.d.ts +11 -0
  234. package/dist/renderer/scene.d.ts.map +1 -0
  235. package/dist/renderer/scene.js +392 -0
  236. package/dist/renderer/scene.js.map +1 -0
  237. package/dist/renderer/shapes.d.ts +13 -0
  238. package/dist/renderer/shapes.d.ts.map +1 -0
  239. package/dist/renderer/shapes.js +160 -0
  240. package/dist/renderer/shapes.js.map +1 -0
  241. package/dist/renderer/strokes.d.ts +9 -0
  242. package/dist/renderer/strokes.d.ts.map +1 -0
  243. package/dist/renderer/strokes.js +180 -0
  244. package/dist/renderer/strokes.js.map +1 -0
  245. package/dist/rpc/commands.d.ts +202 -0
  246. package/dist/rpc/commands.d.ts.map +1 -0
  247. package/dist/rpc/commands.js +429 -0
  248. package/dist/rpc/commands.js.map +1 -0
  249. package/dist/rpc/index.d.ts +3 -0
  250. package/dist/rpc/index.d.ts.map +1 -0
  251. package/dist/rpc/index.js +2 -0
  252. package/dist/rpc/index.js.map +1 -0
  253. package/dist/scene-graph.d.ts +318 -0
  254. package/dist/scene-graph.d.ts.map +1 -0
  255. package/dist/scene-graph.js +803 -0
  256. package/dist/scene-graph.js.map +1 -0
  257. package/dist/snap.d.ts +16 -0
  258. package/dist/snap.d.ts.map +1 -0
  259. package/dist/snap.js +97 -0
  260. package/dist/snap.js.map +1 -0
  261. package/dist/style-runs.d.ts +20 -0
  262. package/dist/style-runs.d.ts.map +1 -0
  263. package/dist/style-runs.js +168 -0
  264. package/dist/style-runs.js.map +1 -0
  265. package/dist/svg-export/defs.d.ts +19 -0
  266. package/dist/svg-export/defs.d.ts.map +1 -0
  267. package/dist/svg-export/defs.js +191 -0
  268. package/dist/svg-export/defs.js.map +1 -0
  269. package/dist/svg-export/index.d.ts +8 -0
  270. package/dist/svg-export/index.d.ts.map +1 -0
  271. package/dist/svg-export/index.js +318 -0
  272. package/dist/svg-export/index.js.map +1 -0
  273. package/dist/svg-export/paths.d.ts +9 -0
  274. package/dist/svg-export/paths.d.ts.map +1 -0
  275. package/dist/svg-export/paths.js +189 -0
  276. package/dist/svg-export/paths.js.map +1 -0
  277. package/dist/svg-node.d.ts +8 -0
  278. package/dist/svg-node.d.ts.map +1 -0
  279. package/dist/svg-node.js +48 -0
  280. package/dist/svg-node.js.map +1 -0
  281. package/dist/text-editor.d.ts +57 -0
  282. package/dist/text-editor.d.ts.map +1 -0
  283. package/dist/text-editor.js +337 -0
  284. package/dist/text-editor.js.map +1 -0
  285. package/dist/tools/ai-adapter.d.ts +22 -0
  286. package/dist/tools/ai-adapter.d.ts.map +1 -0
  287. package/dist/tools/ai-adapter.js +121 -0
  288. package/dist/tools/ai-adapter.js.map +1 -0
  289. package/dist/tools/analyze.d.ts +22 -0
  290. package/dist/tools/analyze.d.ts.map +1 -0
  291. package/dist/tools/analyze.js +677 -0
  292. package/dist/tools/analyze.js.map +1 -0
  293. package/dist/tools/create.d.ts +8 -0
  294. package/dist/tools/create.d.ts.map +1 -0
  295. package/dist/tools/create.js +204 -0
  296. package/dist/tools/create.js.map +1 -0
  297. package/dist/tools/describe.d.ts +9 -0
  298. package/dist/tools/describe.d.ts.map +1 -0
  299. package/dist/tools/describe.js +295 -0
  300. package/dist/tools/describe.js.map +1 -0
  301. package/dist/tools/export-code.d.ts +2 -0
  302. package/dist/tools/export-code.d.ts.map +1 -0
  303. package/dist/tools/export-code.js +34 -0
  304. package/dist/tools/export-code.js.map +1 -0
  305. package/dist/tools/export-tailwind-config.d.ts +27 -0
  306. package/dist/tools/export-tailwind-config.d.ts.map +1 -0
  307. package/dist/tools/export-tailwind-config.js +215 -0
  308. package/dist/tools/export-tailwind-config.js.map +1 -0
  309. package/dist/tools/icons.d.ts +5 -0
  310. package/dist/tools/icons.d.ts.map +1 -0
  311. package/dist/tools/icons.js +192 -0
  312. package/dist/tools/icons.js.map +1 -0
  313. package/dist/tools/index.d.ts +7 -0
  314. package/dist/tools/index.d.ts.map +1 -0
  315. package/dist/tools/index.js +6 -0
  316. package/dist/tools/index.js.map +1 -0
  317. package/dist/tools/modify.d.ts +22 -0
  318. package/dist/tools/modify.d.ts.map +1 -0
  319. package/dist/tools/modify.js +653 -0
  320. package/dist/tools/modify.js.map +1 -0
  321. package/dist/tools/patterns.d.ts +2 -0
  322. package/dist/tools/patterns.d.ts.map +1 -0
  323. package/dist/tools/patterns.js +173 -0
  324. package/dist/tools/patterns.js.map +1 -0
  325. package/dist/tools/read.d.ts +17 -0
  326. package/dist/tools/read.d.ts.map +1 -0
  327. package/dist/tools/read.js +379 -0
  328. package/dist/tools/read.js.map +1 -0
  329. package/dist/tools/registry.d.ts +3 -0
  330. package/dist/tools/registry.d.ts.map +1 -0
  331. package/dist/tools/registry.js +124 -0
  332. package/dist/tools/registry.js.map +1 -0
  333. package/dist/tools/schema.d.ts +46 -0
  334. package/dist/tools/schema.d.ts.map +1 -0
  335. package/dist/tools/schema.js +17 -0
  336. package/dist/tools/schema.js.map +1 -0
  337. package/dist/tools/structure.d.ts +18 -0
  338. package/dist/tools/structure.d.ts.map +1 -0
  339. package/dist/tools/structure.js +345 -0
  340. package/dist/tools/structure.js.map +1 -0
  341. package/dist/tools/variables.d.ts +12 -0
  342. package/dist/tools/variables.d.ts.map +1 -0
  343. package/dist/tools/variables.js +190 -0
  344. package/dist/tools/variables.js.map +1 -0
  345. package/dist/tools/vector.d.ts +15 -0
  346. package/dist/tools/vector.d.ts.map +1 -0
  347. package/dist/tools/vector.js +312 -0
  348. package/dist/tools/vector.js.map +1 -0
  349. package/dist/types.d.ts +29 -0
  350. package/dist/types.d.ts.map +1 -0
  351. package/dist/types.js +2 -0
  352. package/dist/types.js.map +1 -0
  353. package/dist/undo.d.ts +33 -0
  354. package/dist/undo.d.ts.map +1 -0
  355. package/dist/undo.js +98 -0
  356. package/dist/undo.js.map +1 -0
  357. package/dist/vector.d.ts +14 -0
  358. package/dist/vector.d.ts.map +1 -0
  359. package/dist/vector.js +334 -0
  360. package/dist/vector.js.map +1 -0
  361. package/dist/xpath.d.ts +8 -0
  362. package/dist/xpath.d.ts.map +1 -0
  363. package/dist/xpath.js +199 -0
  364. package/dist/xpath.js.map +1 -0
  365. package/package.json +54 -0
  366. package/src/canvaskit.ts +66 -0
  367. package/src/clipboard.ts +444 -0
  368. package/src/color.ts +83 -0
  369. package/src/constants.ts +277 -0
  370. package/src/copy.ts +75 -0
  371. package/src/fig-export-worker.ts +28 -0
  372. package/src/fig-export.ts +321 -0
  373. package/src/figma-api.ts +1297 -0
  374. package/src/figma-rest-import.ts +443 -0
  375. package/src/fonts.ts +369 -0
  376. package/src/geometry.ts +73 -0
  377. package/src/global.d.ts +20 -0
  378. package/src/index.ts +247 -0
  379. package/src/kiwi/codec.ts +614 -0
  380. package/src/kiwi/fig-file.ts +248 -0
  381. package/src/kiwi/fig-import.ts +300 -0
  382. package/src/kiwi/fig-parse-worker.ts +213 -0
  383. package/src/kiwi/instance-overrides.ts +682 -0
  384. package/src/kiwi/kiwi-convert.ts +771 -0
  385. package/src/kiwi/kiwi-schema/bb.ts +244 -0
  386. package/src/kiwi/kiwi-schema/binary.ts +102 -0
  387. package/src/kiwi/kiwi-schema/index.ts +5 -0
  388. package/src/kiwi/kiwi-schema/js.ts +339 -0
  389. package/src/kiwi/kiwi-schema/parser.ts +287 -0
  390. package/src/kiwi/kiwi-schema/schema.ts +24 -0
  391. package/src/kiwi/kiwi-schema/util.ts +10 -0
  392. package/src/kiwi/protocol.ts +237 -0
  393. package/src/kiwi/schema.ts +2286 -0
  394. package/src/kiwi-serialize.ts +467 -0
  395. package/src/layout.ts +608 -0
  396. package/src/profiler/draw-call-counter.ts +43 -0
  397. package/src/profiler/frame-capture.ts +139 -0
  398. package/src/profiler/frame-stats.ts +122 -0
  399. package/src/profiler/gpu-timer.ts +93 -0
  400. package/src/profiler/hud-renderer.ts +242 -0
  401. package/src/profiler/index.ts +8 -0
  402. package/src/profiler/phase-timer.ts +62 -0
  403. package/src/profiler/render-profiler.ts +163 -0
  404. package/src/render/components.ts +69 -0
  405. package/src/render/emoji-icons.ts +60 -0
  406. package/src/render/export-code.ts +366 -0
  407. package/src/render/export-jsx.ts +633 -0
  408. package/src/render/index.ts +38 -0
  409. package/src/render/jsx-runtime.ts +36 -0
  410. package/src/render/mini-react.ts +30 -0
  411. package/src/render/render-jsx.ts +74 -0
  412. package/src/render/renderer.ts +508 -0
  413. package/src/render/tailwind.ts +114 -0
  414. package/src/render/tree.ts +137 -0
  415. package/src/render-image.ts +139 -0
  416. package/src/renderer/effects.ts +64 -0
  417. package/src/renderer/fills.ts +248 -0
  418. package/src/renderer/index.ts +1 -0
  419. package/src/renderer/label-cache.ts +114 -0
  420. package/src/renderer/labels.ts +168 -0
  421. package/src/renderer/lru-cache.ts +71 -0
  422. package/src/renderer/overlays.ts +1089 -0
  423. package/src/renderer/renderer.ts +1226 -0
  424. package/src/renderer/rulers.ts +230 -0
  425. package/src/renderer/scene.ts +554 -0
  426. package/src/renderer/shapes.ts +193 -0
  427. package/src/renderer/strokes.ts +221 -0
  428. package/src/rpc/commands.ts +667 -0
  429. package/src/rpc/index.ts +25 -0
  430. package/src/scene-graph.ts +1254 -0
  431. package/src/snap.ts +122 -0
  432. package/src/style-runs.ts +234 -0
  433. package/src/svg-export/defs.ts +255 -0
  434. package/src/svg-export/index.ts +427 -0
  435. package/src/svg-export/paths.ts +212 -0
  436. package/src/svg-node.ts +62 -0
  437. package/src/text-editor.ts +349 -0
  438. package/src/tools/ai-adapter.ts +144 -0
  439. package/src/tools/analyze.ts +786 -0
  440. package/src/tools/create.ts +206 -0
  441. package/src/tools/describe.ts +280 -0
  442. package/src/tools/export-code.ts +41 -0
  443. package/src/tools/export-tailwind-config.ts +266 -0
  444. package/src/tools/icons.ts +213 -0
  445. package/src/tools/index.ts +6 -0
  446. package/src/tools/modify.ts +651 -0
  447. package/src/tools/patterns.ts +189 -0
  448. package/src/tools/read.ts +401 -0
  449. package/src/tools/registry.ts +155 -0
  450. package/src/tools/schema.ts +65 -0
  451. package/src/tools/structure.ts +348 -0
  452. package/src/tools/variables.ts +193 -0
  453. package/src/tools/vector.ts +311 -0
  454. package/src/types.ts +32 -0
  455. package/src/undo.ts +126 -0
  456. package/src/vector.ts +413 -0
  457. package/src/xpath.ts +259 -0
@@ -0,0 +1,682 @@
1
+ import type { SceneGraph, SceneNode, GeometryPath } from '../scene-graph'
2
+ import { guidToString, convertOverrideToProps, resolveGeometryPaths } from './kiwi-convert'
3
+ import { copyFills, copyStrokes, copyEffects, copyStyleRuns, copyGeometryPaths } from '../copy'
4
+ import type { GUID } from './codec'
5
+ import type { Matrix, Vector } from '../types'
6
+
7
+ interface SymbolOverride {
8
+ guidPath?: { guids?: GUID[] }
9
+ overriddenSymbolID?: GUID
10
+ componentPropAssignments?: ComponentPropAssignment[]
11
+ [key: string]: unknown
12
+ }
13
+
14
+ interface SymbolData {
15
+ symbolID?: GUID
16
+ symbolOverrides?: SymbolOverride[]
17
+ }
18
+
19
+ interface ComponentPropRef {
20
+ defID?: GUID
21
+ componentPropNodeField: string
22
+ }
23
+
24
+ interface ComponentPropAssignment {
25
+ defID?: GUID
26
+ value: { boolValue?: boolean; textValue?: string; guidValue?: GUID }
27
+ }
28
+
29
+ interface DerivedSymbolOverride {
30
+ guidPath?: { guids?: GUID[] }
31
+ size?: Vector
32
+ transform?: Matrix
33
+ fillGeometry?: Array<{ windingRule?: string; commandsBlob?: number }>
34
+ strokeGeometry?: Array<{ windingRule?: string; commandsBlob?: number }>
35
+ }
36
+
37
+ export interface InstanceNodeChange {
38
+ type?: string
39
+ guid?: GUID
40
+ overrideKey?: GUID
41
+ symbolData?: SymbolData
42
+ componentPropRefs?: ComponentPropRef[]
43
+ componentPropAssignments?: ComponentPropAssignment[]
44
+ derivedSymbolData?: DerivedSymbolOverride[]
45
+ }
46
+
47
+ /**
48
+ * Populate empty instances from their components and apply symbol overrides.
49
+ *
50
+ * Shared between .fig file import and clipboard paste. Both paths produce
51
+ * a SceneGraph with INSTANCE nodes whose componentId references have been
52
+ * remapped to graph node IDs but whose children may be missing and whose
53
+ * overrides have not yet been applied.
54
+ *
55
+ * @param graph – the SceneGraph (mutated in place)
56
+ * @param changeMap – figmaGuid → raw kiwi node change (for overrideKey + symbolData)
57
+ * @param guidToNodeId – figmaGuid → graph node ID
58
+ */
59
+ export function populateAndApplyOverrides(
60
+ graph: SceneGraph,
61
+ changeMap: Map<string, InstanceNodeChange>,
62
+ guidToNodeId: Map<string, string>,
63
+ blobs: Uint8Array[] = []
64
+ ): void {
65
+ // Work-queue population: seed with empty instances, then discover newly
66
+ // cloned nested instances by walking the subtree (avoids full graph scan per round).
67
+ const populateQueue: string[] = []
68
+ for (const node of graph.getAllNodes()) {
69
+ if (node.type === 'INSTANCE' && node.componentId && node.childIds.length === 0) {
70
+ populateQueue.push(node.id)
71
+ }
72
+ }
73
+
74
+ function collectEmptyInstances(parentId: string, out: string[]) {
75
+ const parent = graph.getNode(parentId)
76
+ if (!parent) return
77
+ for (const childId of parent.childIds) {
78
+ const child = graph.getNode(childId)
79
+ if (!child) continue
80
+ if (child.type === 'INSTANCE' && child.componentId && child.childIds.length === 0) {
81
+ out.push(child.id)
82
+ } else if (child.childIds.length > 0) {
83
+ collectEmptyInstances(childId, out)
84
+ }
85
+ }
86
+ }
87
+
88
+ while (populateQueue.length > 0) {
89
+ const nodeId = populateQueue.pop()
90
+ if (!nodeId) continue
91
+ const node = graph.getNode(nodeId)
92
+ if (node?.type !== 'INSTANCE' || !node.componentId || node.childIds.length > 0) continue
93
+ const comp = graph.getNode(node.componentId)
94
+ if (comp && comp.childIds.length > 0) {
95
+ graph.populateInstanceChildren(nodeId, node.componentId)
96
+ collectEmptyInstances(nodeId, populateQueue)
97
+ }
98
+ }
99
+
100
+ // Build overrideKey → figmaGuid map
101
+ const overrideKeyToGuid = new Map<string, string>()
102
+ for (const [id, nc] of changeMap) {
103
+ if (nc.overrideKey) overrideKeyToGuid.set(guidToString(nc.overrideKey), id)
104
+ }
105
+
106
+ // Reverse map: graph node ID → figma GUID (used by getComponentRoot kiwi fallback)
107
+ const nodeIdToGuid = new Map<string, string>()
108
+ for (const [figmaId, nodeId] of guidToNodeId) {
109
+ nodeIdToGuid.set(nodeId, figmaId)
110
+ }
111
+
112
+ // Pre-compute componentId root for every node while all internal page nodes
113
+ // are still alive. After overrides, instance swaps delete intermediate clones,
114
+ // breaking the chain. DSD resolution uses this to match across clone levels.
115
+ const preComputedRoot = new Map<string, string>()
116
+ function getPreComputedRoot(nodeId: string, depth = 0): string {
117
+ if (preComputedRoot.has(nodeId)) return preComputedRoot.get(nodeId) ?? nodeId
118
+ if (depth > 20) return nodeId
119
+ const node = graph.getNode(nodeId)
120
+ if (node?.componentId && node.componentId !== nodeId) {
121
+ const root = getPreComputedRoot(node.componentId, depth + 1)
122
+ preComputedRoot.set(nodeId, root)
123
+ return root
124
+ }
125
+ preComputedRoot.set(nodeId, nodeId)
126
+ return nodeId
127
+ }
128
+ for (const node of graph.getAllNodes()) {
129
+ if (node.componentId) getPreComputedRoot(node.id)
130
+ }
131
+
132
+ // Component root resolution (walks componentId chain to the ultimate source)
133
+ const componentIdRoot = new Map<string, string>()
134
+ function getComponentRoot(nodeId: string, depth = 0): string {
135
+ if (componentIdRoot.has(nodeId)) return componentIdRoot.get(nodeId) ?? nodeId
136
+ if (depth > 20) {
137
+ componentIdRoot.set(nodeId, nodeId)
138
+ return nodeId
139
+ }
140
+
141
+ // Try graph first
142
+ const node = graph.getNode(nodeId)
143
+ if (node?.componentId) {
144
+ const root = getComponentRoot(node.componentId, depth + 1)
145
+ componentIdRoot.set(nodeId, root)
146
+ return root
147
+ }
148
+
149
+ // For deleted nodes (internal page), resolve via kiwi symbolData
150
+ const figmaId = nodeIdToGuid.get(nodeId)
151
+ if (figmaId) {
152
+ const nc = changeMap.get(figmaId)
153
+ const symId = nc?.symbolData?.symbolID
154
+ if (symId) {
155
+ const compNodeId = guidToNodeId.get(guidToString(symId))
156
+ if (compNodeId && compNodeId !== nodeId) {
157
+ const root = getComponentRoot(compNodeId, depth + 1)
158
+ componentIdRoot.set(nodeId, root)
159
+ return root
160
+ }
161
+ }
162
+ }
163
+
164
+ componentIdRoot.set(nodeId, nodeId)
165
+ return nodeId
166
+ }
167
+
168
+ function findNodeByComponentId(parentId: string, componentId: string): string | null {
169
+ const parent = graph.getNode(parentId)
170
+ if (!parent) return null
171
+
172
+ // Pass 1: exact componentId match on direct children
173
+ for (const childId of parent.childIds) {
174
+ const child = graph.getNode(childId)
175
+ if (child?.componentId === componentId) return childId
176
+ }
177
+
178
+ // Pass 2: root match — but only if exactly one child shares the root
179
+ // (multiple siblings with the same root are ambiguous)
180
+ const targetRoot = preComputedRoot.get(componentId) ?? getComponentRoot(componentId)
181
+ if (targetRoot) {
182
+ let rootMatch: string | null = null
183
+ let ambiguous = false
184
+ for (const childId of parent.childIds) {
185
+ const child = graph.getNode(childId)
186
+ if (!child?.componentId) continue
187
+ const childRoot = preComputedRoot.get(child.componentId) ?? getComponentRoot(child.componentId)
188
+ if (childRoot === targetRoot) {
189
+ if (rootMatch) { ambiguous = true; break }
190
+ rootMatch = childId
191
+ }
192
+ }
193
+ if (rootMatch && !ambiguous) return rootMatch
194
+ }
195
+
196
+ // Pass 3: recurse into children
197
+ for (const childId of parent.childIds) {
198
+ const deep = findNodeByComponentId(childId, componentId)
199
+ if (deep) return deep
200
+ }
201
+ return null
202
+ }
203
+
204
+ function resolveOverrideTarget(instanceId: string, guids: GUID[]): string | null {
205
+ let currentId = instanceId
206
+ for (const guid of guids) {
207
+ const key = guidToString(guid)
208
+ const figmaGuid = overrideKeyToGuid.get(key) ?? key
209
+ const remapped = guidToNodeId.get(figmaGuid)
210
+ if (!remapped) return null
211
+
212
+ // The override may target the current node itself (when it's an instance
213
+ // cloned from the component the override points to)
214
+ const current = graph.getNode(currentId)
215
+ if (current?.componentId === remapped) {
216
+ continue
217
+ }
218
+
219
+ const found = findNodeByComponentId(currentId, remapped)
220
+ if (!found) return null
221
+ currentId = found
222
+ }
223
+ return currentId
224
+ }
225
+
226
+ // Apply component property assignments (boolean visibility, instance swap).
227
+ // Component children reference property definitions via componentPropRefs.
228
+ // Instances set values via componentPropAssignments. After cloning, we walk
229
+ // each instance's descendants and apply the assignments.
230
+
231
+ function findPropRefs(nodeId: string, propRefsMap: Map<string, ComponentPropRef[]>): ComponentPropRef[] | undefined {
232
+ let sourceId: string | undefined = nodeId
233
+ for (let depth = 0; sourceId && depth < 10; depth++) {
234
+ const figmaId = nodeIdToGuid.get(sourceId)
235
+ if (figmaId) {
236
+ const refs = propRefsMap.get(figmaId)
237
+ if (refs) return refs
238
+ }
239
+ const node = graph.getNode(sourceId)
240
+ const nextId = node?.componentId ?? undefined
241
+ if (nextId === sourceId) break
242
+ sourceId = nextId
243
+ }
244
+ return undefined
245
+ }
246
+
247
+ function repopulateInstance(nodeId: string, compId: string) {
248
+ const node = graph.getNode(nodeId)
249
+ if (node?.type !== 'INSTANCE') return
250
+
251
+ for (const childId of Array.from(node.childIds)) graph.deleteNode(childId)
252
+ graph.updateNode(nodeId, { componentId: compId })
253
+ const comp = graph.getNode(compId)
254
+ if (comp && comp.childIds.length > 0) {
255
+ graph.populateInstanceChildren(nodeId, compId)
256
+ }
257
+ componentIdRoot.clear()
258
+ }
259
+
260
+ function assignmentsToValueMap(assignments: ComponentPropAssignment[]): Map<string, ComponentPropAssignment['value']> {
261
+ const valueByDef = new Map<string, ComponentPropAssignment['value']>()
262
+ for (const a of assignments) {
263
+ if (a.defID) valueByDef.set(guidToString(a.defID), a.value)
264
+ }
265
+ return valueByDef
266
+ }
267
+
268
+ function applyInstanceDirectAssignments(
269
+ assignmentSources: Map<string, ComponentPropAssignment[]>,
270
+ propRefsMap: Map<string, ComponentPropRef[]>
271
+ ) {
272
+ for (const node of graph.getAllNodes()) {
273
+ if (node.type !== 'INSTANCE') continue
274
+ // Apply assignments from the instance's own kiwi data first
275
+ const ownFigmaId = nodeIdToGuid.get(node.id)
276
+ if (ownFigmaId) {
277
+ const ownAssignments = assignmentSources.get(ownFigmaId)
278
+ if (ownAssignments) {
279
+ applyPropAssignments(node.id, assignmentsToValueMap(ownAssignments), propRefsMap)
280
+ }
281
+ }
282
+
283
+ // Also apply from cloned instance sources — after population, cloned
284
+ // instances have componentId pointing to the original kiwi node
285
+ if (!node.componentId) continue
286
+ const sourceFigmaId = nodeIdToGuid.get(node.componentId)
287
+ if (!sourceFigmaId) continue
288
+ const assignments = assignmentSources.get(sourceFigmaId)
289
+ if (!assignments) continue
290
+
291
+ applyPropAssignments(node.id, assignmentsToValueMap(assignments), propRefsMap)
292
+ }
293
+ }
294
+
295
+ function applySymbolOverrideAssignments(propRefsMap: Map<string, ComponentPropRef[]>) {
296
+ for (const [figmaId, nc] of changeMap) {
297
+ const instanceNodeId = guidToNodeId.get(figmaId)
298
+ if (!instanceNodeId) continue
299
+ if (graph.getNode(instanceNodeId)?.type !== 'INSTANCE') continue
300
+
301
+ const overrides = nc.symbolData?.symbolOverrides
302
+ if (!overrides) continue
303
+ for (const ov of overrides) {
304
+ if (!ov.componentPropAssignments?.length) continue
305
+
306
+ const guids = ov.guidPath?.guids
307
+ if (!guids?.length) continue
308
+
309
+ const targetId = resolveOverrideTarget(instanceNodeId, guids)
310
+ if (!targetId) continue
311
+
312
+ applyPropAssignments(targetId, assignmentsToValueMap(ov.componentPropAssignments), propRefsMap)
313
+ }
314
+ }
315
+ }
316
+
317
+ function applyComponentProperties() {
318
+ const propRefsMap = new Map<string, ComponentPropRef[]>()
319
+ for (const [figmaId, nc] of changeMap) {
320
+ if (nc.componentPropRefs?.length) {
321
+ propRefsMap.set(figmaId, nc.componentPropRefs)
322
+ }
323
+ }
324
+ if (propRefsMap.size === 0) return
325
+
326
+ const assignmentSources = new Map<string, ComponentPropAssignment[]>()
327
+ for (const [figmaId, nc] of changeMap) {
328
+ if (nc.componentPropAssignments?.length) {
329
+ assignmentSources.set(figmaId, nc.componentPropAssignments)
330
+ }
331
+ }
332
+
333
+ applyInstanceDirectAssignments(assignmentSources, propRefsMap)
334
+ applySymbolOverrideAssignments(propRefsMap)
335
+ }
336
+
337
+ function applyPropAssignments(
338
+ parentId: string,
339
+ valueByDef: Map<string, ComponentPropAssignment['value']>,
340
+ propRefsMap: Map<string, ComponentPropRef[]>
341
+ ) {
342
+ const parent = graph.getNode(parentId)
343
+ if (!parent) return
344
+
345
+ for (const childId of parent.childIds) {
346
+ const child = graph.getNode(childId)
347
+ if (!child?.componentId) {
348
+ applyPropAssignments(childId, valueByDef, propRefsMap)
349
+ continue
350
+ }
351
+
352
+ const refs = findPropRefs(child.componentId, propRefsMap)
353
+ if (refs) {
354
+ for (const ref of refs) {
355
+ if (!ref.defID) continue
356
+ const val = valueByDef.get(guidToString(ref.defID))
357
+ if (!val) continue
358
+
359
+ if (ref.componentPropNodeField === 'VISIBLE' && val.boolValue !== undefined) {
360
+ graph.updateNode(childId, { visible: val.boolValue })
361
+ } else if (ref.componentPropNodeField === 'OVERRIDDEN_SYMBOL_ID') {
362
+ const swapId = val.textValue ?? (val.guidValue ? guidToString(val.guidValue) : undefined)
363
+ if (!swapId) continue
364
+ const newCompId = guidToNodeId.get(swapId)
365
+ if (newCompId) repopulateInstance(childId, newCompId)
366
+ }
367
+ }
368
+ }
369
+
370
+ applyPropAssignments(childId, valueByDef, propRefsMap)
371
+ }
372
+ }
373
+
374
+ // Apply derivedSymbolData — pre-computed sizes for the current set of
375
+ // component property values. Uses the same guidPath resolution as
376
+ // symbolOverrides.
377
+ function scaleGeometryBlobs(geom: GeometryPath[], sx: number, sy: number): GeometryPath[] {
378
+ if (sx === 1 && sy === 1) return geom
379
+ return geom.map((g) => {
380
+ const src = g.commandsBlob
381
+ const scaled = new Uint8Array(src.length)
382
+ scaled.set(src)
383
+ const dv = new DataView(scaled.buffer, scaled.byteOffset, scaled.byteLength)
384
+ let o = 0
385
+ while (o < scaled.length) {
386
+ const cmd = scaled[o++]
387
+ if (cmd === 0) continue
388
+ const coords = cmd === 1 || cmd === 2 ? 1 : (cmd === 4 ? 3 : -1)
389
+ if (coords < 0) {
390
+ console.warn(`scaleGeometryBlobs: unknown path command ${cmd} at offset ${o - 1}`)
391
+ break
392
+ }
393
+ for (let i = 0; i < coords; i++) {
394
+ dv.setFloat32(o, dv.getFloat32(o, true) * sx, true)
395
+ dv.setFloat32(o + 4, dv.getFloat32(o + 4, true) * sy, true)
396
+ o += 8
397
+ }
398
+ }
399
+ return { windingRule: g.windingRule, commandsBlob: scaled }
400
+ })
401
+ }
402
+
403
+ function resolveDsdGeometry(
404
+ d: DerivedSymbolOverride,
405
+ target: SceneNode
406
+ ): Pick<Partial<SceneNode>, 'fillGeometry' | 'strokeGeometry'> {
407
+ const result: Pick<Partial<SceneNode>, 'fillGeometry' | 'strokeGeometry'> = {}
408
+ const fg = resolveGeometryPaths(d.fillGeometry, blobs)
409
+ const sg = resolveGeometryPaths(d.strokeGeometry, blobs)
410
+ if (fg.length > 0) {
411
+ result.fillGeometry = fg
412
+ } else if (d.size && target.fillGeometry.length > 0 && target.width > 0 && target.height > 0) {
413
+ result.fillGeometry = scaleGeometryBlobs(target.fillGeometry, d.size.x / target.width, d.size.y / target.height)
414
+ }
415
+ if (sg.length > 0) {
416
+ result.strokeGeometry = sg
417
+ } else if (d.size && target.strokeGeometry.length > 0 && target.width > 0 && target.height > 0) {
418
+ result.strokeGeometry = scaleGeometryBlobs(target.strokeGeometry, d.size.x / target.width, d.size.y / target.height)
419
+ }
420
+ return result
421
+ }
422
+
423
+ function resolveDsdUpdates(): { dsdModified: Set<string>; dsdSizeSet: Set<string> } {
424
+ const dsdModified = new Set<string>()
425
+ const dsdSizeSet = new Set<string>()
426
+
427
+ for (const [ncId, nc] of changeMap) {
428
+ if (nc.type !== 'INSTANCE') continue
429
+ const derived = nc.derivedSymbolData
430
+ if (!derived?.length) continue
431
+
432
+ const nodeId = guidToNodeId.get(ncId)
433
+ if (!nodeId) continue
434
+
435
+ for (const d of derived) {
436
+ const guids = d.guidPath?.guids
437
+ if (!guids?.length) continue
438
+
439
+ const targetId = resolveOverrideTarget(nodeId, guids)
440
+ if (!targetId) continue
441
+
442
+ const target = graph.getNode(targetId)
443
+ if (!target) continue
444
+
445
+ const updates: Partial<SceneNode> = {}
446
+ if (d.size) {
447
+ updates.width = d.size.x
448
+ updates.height = d.size.y
449
+ }
450
+ if (d.transform) {
451
+ updates.x = d.transform.m02
452
+ updates.y = d.transform.m12
453
+ }
454
+ Object.assign(updates, resolveDsdGeometry(d, target))
455
+
456
+ if (Object.keys(updates).length > 0) {
457
+ graph.updateNode(targetId, updates)
458
+ dsdModified.add(targetId)
459
+ if (d.size) dsdSizeSet.add(targetId)
460
+ }
461
+ }
462
+ }
463
+
464
+ return { dsdModified, dsdSizeSet }
465
+ }
466
+
467
+ // Propagate DSD changes through clone chains — each clone should match
468
+ // its source for size/position/geometry. Nodes whose size was explicitly
469
+ // set by DSD keep their own values; others inherit from their source.
470
+ function propagateDsdChanges(dsdModified: Set<string>, dsdSizeSet: Set<string>) {
471
+ if (dsdModified.size === 0) return
472
+
473
+ const clonesOf = buildClonesMap()
474
+
475
+ const queue = [...dsdModified]
476
+ const visited = new Set<string>()
477
+ for (let sourceId = queue.shift(); sourceId !== undefined; sourceId = queue.shift()) {
478
+ const source = graph.getNode(sourceId)
479
+ if (!source) continue
480
+ const clones = clonesOf.get(sourceId)
481
+ if (!clones) continue
482
+ for (const cloneId of clones) {
483
+ if (visited.has(cloneId)) continue
484
+ visited.add(cloneId)
485
+ const clone = graph.getNode(cloneId)
486
+ if (!clone) continue
487
+ if (!dsdSizeSet.has(cloneId)) {
488
+ const cu: Partial<SceneNode> = {}
489
+ if (source.width !== clone.width) cu.width = source.width
490
+ if (source.height !== clone.height) cu.height = source.height
491
+ if (source.x !== clone.x) cu.x = source.x
492
+ if (source.y !== clone.y) cu.y = source.y
493
+ if (source.fillGeometry !== clone.fillGeometry) cu.fillGeometry = copyGeometryPaths(source.fillGeometry)
494
+ if (source.strokeGeometry !== clone.strokeGeometry) cu.strokeGeometry = copyGeometryPaths(source.strokeGeometry)
495
+ if (Object.keys(cu).length > 0) graph.updateNode(cloneId, cu)
496
+ }
497
+ queue.push(cloneId)
498
+ }
499
+ }
500
+ }
501
+
502
+ function applyDerivedSymbolData() {
503
+ const { dsdModified, dsdSizeSet } = resolveDsdUpdates()
504
+ propagateDsdChanges(dsdModified, dsdSizeSet)
505
+ }
506
+
507
+ function applySymbolOverrides(): Set<string> {
508
+ const overriddenNodes = new Set<string>()
509
+ componentIdRoot.clear()
510
+
511
+ for (const [ncId, nc] of changeMap) {
512
+ if (nc.type !== 'INSTANCE') continue
513
+ const sd = nc.symbolData
514
+ if (!sd?.symbolOverrides?.length) continue
515
+
516
+ const nodeId = guidToNodeId.get(ncId)
517
+ if (!nodeId) continue
518
+
519
+ for (const ov of sd.symbolOverrides) {
520
+ const guids = ov.guidPath?.guids
521
+ if (!guids?.length) continue
522
+
523
+ const targetId = resolveOverrideTarget(nodeId, guids)
524
+ if (!targetId) continue
525
+
526
+ overriddenNodes.add(targetId)
527
+
528
+ if (ov.overriddenSymbolID) {
529
+ const newCompId = guidToNodeId.get(guidToString(ov.overriddenSymbolID))
530
+ if (newCompId) repopulateInstance(targetId, newCompId)
531
+ }
532
+
533
+ const { guidPath: _, overriddenSymbolID: _s, componentPropAssignments: _c, ...fields } = ov
534
+ if (Object.keys(fields).length === 0) continue
535
+
536
+ const updates = convertOverrideToProps(fields as Record<string, unknown>)
537
+ if (Object.keys(updates).length > 0) {
538
+ graph.updateNode(targetId, updates)
539
+ }
540
+ }
541
+ }
542
+ return overriddenNodes
543
+ }
544
+
545
+ function syncNodeProps(source: SceneNode, target: SceneNode) {
546
+ const updates: Partial<SceneNode> = {}
547
+ if (source.text !== target.text) updates.text = source.text
548
+ if (source.visible !== target.visible) updates.visible = source.visible
549
+ if (source.opacity !== target.opacity) updates.opacity = source.opacity
550
+ if (source.fills !== target.fills) updates.fills = copyFills(source.fills)
551
+ if (source.strokes !== target.strokes) updates.strokes = copyStrokes(source.strokes)
552
+ if (source.effects !== target.effects) updates.effects = copyEffects(source.effects)
553
+ if (source.styleRuns !== target.styleRuns) updates.styleRuns = copyStyleRuns(source.styleRuns)
554
+ if (source.layoutGrow !== target.layoutGrow) updates.layoutGrow = source.layoutGrow
555
+ if (source.textAutoResize !== target.textAutoResize) updates.textAutoResize = source.textAutoResize
556
+ if (source.locked !== target.locked) updates.locked = source.locked
557
+ if (Object.keys(updates).length > 0) graph.updateNode(target.id, updates)
558
+ }
559
+
560
+ function syncChildrenDeep(sourceId: string, targetId: string, skip?: Set<string>) {
561
+ const src = graph.getNode(sourceId)
562
+ const tgt = graph.getNode(targetId)
563
+ if (!src || !tgt) return
564
+ const len = Math.min(src.childIds.length, tgt.childIds.length)
565
+ for (let i = 0; i < len; i++) {
566
+ if (skip?.has(tgt.childIds[i])) continue
567
+ const srcNode = graph.getNode(src.childIds[i])
568
+ const tgtNode = graph.getNode(tgt.childIds[i])
569
+ if (!srcNode || !tgtNode || srcNode.type !== tgtNode.type) continue
570
+ syncNodeProps(srcNode, tgtNode)
571
+ syncChildrenDeep(src.childIds[i], tgt.childIds[i], skip)
572
+ }
573
+ }
574
+
575
+ function buildClonesMap(): Map<string, string[]> {
576
+ const clonesOf = new Map<string, string[]>()
577
+ for (const node of graph.getAllNodes()) {
578
+ if (!node.componentId) continue
579
+ let arr = clonesOf.get(node.componentId)
580
+ if (!arr) {
581
+ arr = []
582
+ clonesOf.set(node.componentId, arr)
583
+ }
584
+ arr.push(node.id)
585
+ }
586
+ return clonesOf
587
+ }
588
+
589
+ function expandSeedsToParents(seeds: Set<string>): Set<string> {
590
+ const expandedSeeds = new Set(seeds)
591
+ for (const seedId of seeds) {
592
+ let cur = graph.getNode(seedId)
593
+ while (cur?.parentId) {
594
+ const parent = graph.getNode(cur.parentId)
595
+ if (!parent) break
596
+ if (parent.type === 'INSTANCE' || parent.type === 'COMPONENT') {
597
+ expandedSeeds.add(parent.id)
598
+ }
599
+ cur = parent
600
+ }
601
+ }
602
+ return expandedSeeds
603
+ }
604
+
605
+ function buildNeedsSyncSet(expandedSeeds: Set<string>, clonesOf: Map<string, string[]>): Set<string> {
606
+ const needsSync = new Set<string>()
607
+ const queue = [...expandedSeeds]
608
+ for (let id = queue.pop(); id !== undefined; id = queue.pop()) {
609
+ const clones = clonesOf.get(id)
610
+ if (!clones) continue
611
+ for (const cloneId of clones) {
612
+ if (needsSync.has(cloneId)) continue
613
+ needsSync.add(cloneId)
614
+ queue.push(cloneId)
615
+ }
616
+ }
617
+ return needsSync
618
+ }
619
+
620
+ function syncCloneFromSource(sourceId: string, source: SceneNode, node: SceneNode, seeds: Set<string>) {
621
+ syncNodeProps(source, node)
622
+ if (source.childIds.length !== node.childIds.length) {
623
+ const childIds = [...node.childIds]
624
+ for (const childId of childIds) graph.deleteNode(childId)
625
+ if (source.childIds.length > 0) {
626
+ graph.populateInstanceChildren(node.id, sourceId)
627
+ }
628
+ } else if (source.childIds.length > 0 && node.childIds.length > 0) {
629
+ syncChildrenDeep(sourceId, node.id, seeds)
630
+ }
631
+ }
632
+
633
+ function propagateOverridesTransitively(seeds: Set<string>) {
634
+ if (seeds.size === 0) return
635
+
636
+ const clonesOf = buildClonesMap()
637
+ const expandedSeeds = expandSeedsToParents(seeds)
638
+ const needsSync = buildNeedsSyncSet(expandedSeeds, clonesOf)
639
+
640
+ const visited = new Set<string>()
641
+ const syncQueue = [...expandedSeeds]
642
+ for (let sourceId = syncQueue.shift(); sourceId !== undefined; sourceId = syncQueue.shift()) {
643
+ const clones = clonesOf.get(sourceId)
644
+ if (!clones) continue
645
+ const source = graph.getNode(sourceId)
646
+ if (!source) continue
647
+
648
+ for (const cloneId of clones) {
649
+ if (!needsSync.has(cloneId) || visited.has(cloneId)) continue
650
+ visited.add(cloneId)
651
+ const node = graph.getNode(cloneId)
652
+ if (!node) continue
653
+
654
+ // Don't overwrite nodes directly targeted by symbolOverrides
655
+ if (seeds.has(cloneId)) {
656
+ syncQueue.push(cloneId)
657
+ continue
658
+ }
659
+
660
+ syncCloneFromSource(sourceId, source, node, seeds)
661
+ syncQueue.push(cloneId)
662
+ }
663
+ }
664
+ }
665
+
666
+ // Order matters:
667
+ // 1. symbolOverrides — set property values and swap instances
668
+ // 2. transitive sync — propagate overrides through clone chains (may
669
+ // repopulate INSTANCE children, wiping any earlier property changes)
670
+ // 3. componentProperties — toggle visibility / swap via prop assignments
671
+ // (must run AFTER sync so repopulated children aren't lost)
672
+ // 4. derivedSymbolData — apply Figma's pre-computed sizes last
673
+ const overriddenNodes = applySymbolOverrides()
674
+
675
+ propagateOverridesTransitively(overriddenNodes)
676
+
677
+ applyComponentProperties()
678
+
679
+ // DSD resolution runs AFTER overrides so guidPaths can reach children
680
+ // of instance-swapped nodes (repopulateInstance replaces children).
681
+ applyDerivedSymbolData()
682
+ }