@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,677 @@
1
+ import { createTwoFilesPatch } from 'diff';
2
+ import { colorDistance, colorToHex, parseColor } from '../color.js';
3
+ import { defineTool } from './schema.js';
4
+ function trackColor(colorMap, color, variableName) {
5
+ const hex = colorToHex(color);
6
+ const entry = colorMap.get(hex);
7
+ if (entry) {
8
+ entry.count++;
9
+ if (!entry.variableName && variableName)
10
+ entry.variableName = variableName;
11
+ }
12
+ else {
13
+ colorMap.set(hex, { hex, color, count: 1, variableName });
14
+ }
15
+ }
16
+ // ─── Diff helpers ─────────────────────────────────────────────
17
+ function serializePaintProps(raw, lines) {
18
+ const solidFill = raw.fills.find((f) => f.type === 'SOLID' && f.visible);
19
+ if (solidFill)
20
+ lines.push(`fill: ${colorToHex(solidFill.color)}`);
21
+ const solidStroke = raw.strokes.find((s) => s.visible);
22
+ if (solidStroke) {
23
+ lines.push(`stroke: ${colorToHex(solidStroke.color)}`);
24
+ if (solidStroke.weight)
25
+ lines.push(`strokeWeight: ${solidStroke.weight}`);
26
+ }
27
+ }
28
+ function serializeCornerRadii(raw, lines) {
29
+ const tl = raw.topLeftRadius;
30
+ const tr = raw.topRightRadius;
31
+ const br = raw.bottomRightRadius;
32
+ const bl = raw.bottomLeftRadius;
33
+ if (tl || tr || br || bl) {
34
+ if (tl === tr && tr === br && br === bl) {
35
+ lines.push(`radius: ${tl}`);
36
+ }
37
+ else {
38
+ lines.push(`radii: ${tl} ${tr} ${br} ${bl}`);
39
+ }
40
+ }
41
+ }
42
+ function serializeEffects(raw, lines) {
43
+ for (const effect of raw.effects) {
44
+ const parts = [effect.type];
45
+ parts.push(`r=${effect.radius}`);
46
+ parts.push(`c=${colorToHex(effect.color)}`);
47
+ parts.push(`x=${effect.offset.x} y=${effect.offset.y}`);
48
+ parts.push(`s=${effect.spread}`);
49
+ lines.push(`effect: ${parts.join(' ')}`);
50
+ }
51
+ }
52
+ function serializeTextProps(raw, lines) {
53
+ if (raw.type !== 'TEXT')
54
+ return;
55
+ if (raw.text)
56
+ lines.push(`text: ${JSON.stringify(raw.text)}`);
57
+ if (raw.fontSize)
58
+ lines.push(`fontSize: ${raw.fontSize}`);
59
+ if (raw.fontFamily)
60
+ lines.push(`fontFamily: ${raw.fontFamily}`);
61
+ if (raw.fontWeight)
62
+ lines.push(`fontWeight: ${raw.fontWeight}`);
63
+ }
64
+ function serializeNodeProps(raw) {
65
+ const lines = [];
66
+ lines.push(`type: ${raw.type}`);
67
+ lines.push(`size: ${raw.width} ${raw.height}`);
68
+ lines.push(`pos: ${raw.x} ${raw.y}`);
69
+ serializePaintProps(raw, lines);
70
+ if (raw.opacity !== 1)
71
+ lines.push(`opacity: ${Math.round(raw.opacity * 100) / 100}`);
72
+ serializeCornerRadii(raw, lines);
73
+ if (raw.blendMode !== 'NORMAL')
74
+ lines.push(`blendMode: ${raw.blendMode}`);
75
+ if (raw.rotation !== 0)
76
+ lines.push(`rotation: ${Math.round(raw.rotation * 100) / 100}`);
77
+ if (raw.clipsContent)
78
+ lines.push(`clipsContent: true`);
79
+ serializeEffects(raw, lines);
80
+ serializeTextProps(raw, lines);
81
+ if (!raw.visible)
82
+ lines.push(`visible: false`);
83
+ if (raw.locked)
84
+ lines.push(`locked: true`);
85
+ return lines.join('\n');
86
+ }
87
+ function collectNodeTree(figma, nodeId, parentPath, depth, maxDepth) {
88
+ const result = new Map();
89
+ const raw = figma.graph.getNode(nodeId);
90
+ if (!raw)
91
+ return result;
92
+ const path = parentPath ? `${parentPath}/${raw.name}` : `/${raw.name}`;
93
+ result.set(path, { path, id: raw.id, serialized: serializeNodeProps(raw) });
94
+ if (depth < maxDepth) {
95
+ for (const childId of raw.childIds) {
96
+ const childNodes = collectNodeTree(figma, childId, path, depth + 1, maxDepth);
97
+ for (const [k, v] of childNodes)
98
+ result.set(k, v);
99
+ }
100
+ }
101
+ return result;
102
+ }
103
+ function createUnifiedDiff(oldFilename, newFilename, oldContent, newContent) {
104
+ const patch = createTwoFilesPatch(oldFilename, newFilename, oldContent, newContent, '', '');
105
+ return patch
106
+ .split('\n')
107
+ .filter((l) => !l.startsWith('Index:') && l !== '===================================================================')
108
+ .join('\n')
109
+ .trim();
110
+ }
111
+ // ─── Analyze tools ────────────────────────────────────────────
112
+ export const analyzeColors = defineTool({
113
+ name: 'analyze_colors',
114
+ description: 'Analyze color palette usage across the current page. Shows frequency, variable bindings, and optionally clusters similar colors.',
115
+ params: {
116
+ limit: { type: 'number', description: 'Max colors to return (default: 30)' },
117
+ show_similar: {
118
+ type: 'boolean',
119
+ description: 'Include similar-color clusters for potential merging'
120
+ },
121
+ threshold: {
122
+ type: 'number',
123
+ description: 'Distance threshold for clustering (0-50, default: 15)'
124
+ }
125
+ },
126
+ execute: (figma, args) => {
127
+ const limit = args.limit ?? 30;
128
+ const threshold = args.threshold ?? 15;
129
+ const page = figma.currentPage;
130
+ const colorMap = new Map();
131
+ let totalNodes = 0;
132
+ page.findAll((node) => {
133
+ totalNodes++;
134
+ const raw = figma.graph.getNode(node.id);
135
+ if (!raw)
136
+ return false;
137
+ const boundVars = raw.boundVariables;
138
+ for (const fill of raw.fills) {
139
+ if (fill.type === 'SOLID' && fill.visible) {
140
+ trackColor(colorMap, fill.color, boundVars['fills'] ? String(boundVars['fills']) : null);
141
+ }
142
+ }
143
+ for (const stroke of raw.strokes) {
144
+ if (stroke.visible) {
145
+ trackColor(colorMap, stroke.color, boundVars['strokes'] ? String(boundVars['strokes']) : null);
146
+ }
147
+ }
148
+ return false;
149
+ });
150
+ const colors = [...colorMap.values()].sort((a, b) => b.count - a.count).slice(0, limit);
151
+ const result = {
152
+ totalNodes,
153
+ uniqueColors: colorMap.size,
154
+ colors: colors.map((c) => ({ hex: c.hex, count: c.count, variableName: c.variableName }))
155
+ };
156
+ if (args.show_similar) {
157
+ const hardcoded = [...colorMap.values()]
158
+ .filter((c) => !c.variableName)
159
+ .sort((a, b) => b.count - a.count);
160
+ const used = new Set();
161
+ const clusters = [];
162
+ for (const color of hardcoded) {
163
+ if (used.has(color.hex))
164
+ continue;
165
+ const cluster = [color];
166
+ used.add(color.hex);
167
+ for (const other of hardcoded) {
168
+ if (used.has(other.hex))
169
+ continue;
170
+ if (colorDistance(color.color, other.color) <= threshold) {
171
+ cluster.push(other);
172
+ used.add(other.hex);
173
+ }
174
+ }
175
+ if (cluster.length > 1) {
176
+ clusters.push({
177
+ colors: cluster.map((c) => c.hex),
178
+ totalCount: cluster.reduce((sum, c) => sum + c.count, 0),
179
+ suggestedHex: color.hex
180
+ });
181
+ }
182
+ }
183
+ result.similarClusters = clusters.sort((a, b) => b.colors.length - a.colors.length);
184
+ }
185
+ return result;
186
+ }
187
+ });
188
+ export const analyzeTypography = defineTool({
189
+ name: 'analyze_typography',
190
+ description: 'Analyze typography usage across the current page. Shows font families, sizes, weights, and their frequencies.',
191
+ params: {
192
+ limit: { type: 'number', description: 'Max styles to return (default: 30)' },
193
+ group_by: {
194
+ type: 'string',
195
+ description: 'Group results by a property',
196
+ enum: ['family', 'size', 'weight']
197
+ }
198
+ },
199
+ execute: (figma, args) => {
200
+ const limit = args.limit ?? 30;
201
+ const page = figma.currentPage;
202
+ const styleMap = new Map();
203
+ let totalTextNodes = 0;
204
+ page.findAll((node) => {
205
+ if (node.type !== 'TEXT')
206
+ return false;
207
+ totalTextNodes++;
208
+ const raw = figma.graph.getNode(node.id);
209
+ if (!raw)
210
+ return false;
211
+ const lh = raw.lineHeight === null ? 'auto' : `${raw.lineHeight}`;
212
+ const key = `${raw.fontFamily}|${raw.fontSize}|${raw.fontWeight}|${lh}`;
213
+ const entry = styleMap.get(key);
214
+ if (entry) {
215
+ entry.count++;
216
+ }
217
+ else {
218
+ styleMap.set(key, {
219
+ family: raw.fontFamily,
220
+ size: raw.fontSize,
221
+ weight: raw.fontWeight,
222
+ lineHeight: lh,
223
+ count: 1
224
+ });
225
+ }
226
+ return false;
227
+ });
228
+ const styles = [...styleMap.values()].sort((a, b) => b.count - a.count);
229
+ if (args.group_by === 'family') {
230
+ const byFamily = new Map();
231
+ for (const s of styles)
232
+ byFamily.set(s.family, (byFamily.get(s.family) ?? 0) + s.count);
233
+ return {
234
+ totalTextNodes,
235
+ groups: [...byFamily.entries()]
236
+ .sort((a, b) => b[1] - a[1])
237
+ .map(([family, count]) => ({ family, count }))
238
+ };
239
+ }
240
+ if (args.group_by === 'size') {
241
+ const bySize = new Map();
242
+ for (const s of styles)
243
+ bySize.set(s.size, (bySize.get(s.size) ?? 0) + s.count);
244
+ return {
245
+ totalTextNodes,
246
+ groups: [...bySize.entries()]
247
+ .sort((a, b) => a[0] - b[0])
248
+ .map(([size, count]) => ({ size, count }))
249
+ };
250
+ }
251
+ if (args.group_by === 'weight') {
252
+ const byWeight = new Map();
253
+ for (const s of styles)
254
+ byWeight.set(s.weight, (byWeight.get(s.weight) ?? 0) + s.count);
255
+ return {
256
+ totalTextNodes,
257
+ groups: [...byWeight.entries()]
258
+ .sort((a, b) => b[1] - a[1])
259
+ .map(([weight, count]) => ({ weight, count }))
260
+ };
261
+ }
262
+ return {
263
+ totalTextNodes,
264
+ uniqueStyles: styleMap.size,
265
+ styles: styles.slice(0, limit)
266
+ };
267
+ }
268
+ });
269
+ export const analyzeSpacing = defineTool({
270
+ name: 'analyze_spacing',
271
+ description: 'Analyze spacing values (gap, padding) across the current page. Checks grid compliance.',
272
+ params: {
273
+ grid: { type: 'number', description: 'Base grid size to check against (default: 8)' }
274
+ },
275
+ execute: (figma, args) => {
276
+ const gridSize = args.grid ?? 8;
277
+ const page = figma.currentPage;
278
+ const gapMap = new Map();
279
+ const paddingMap = new Map();
280
+ let totalNodes = 0;
281
+ page.findAll((node) => {
282
+ totalNodes++;
283
+ const raw = figma.graph.getNode(node.id);
284
+ if (!raw)
285
+ return false;
286
+ if (raw.layoutMode !== 'NONE' && raw.itemSpacing > 0) {
287
+ gapMap.set(raw.itemSpacing, (gapMap.get(raw.itemSpacing) ?? 0) + 1);
288
+ }
289
+ for (const p of [raw.paddingTop, raw.paddingRight, raw.paddingBottom, raw.paddingLeft]) {
290
+ if (p > 0) {
291
+ paddingMap.set(p, (paddingMap.get(p) ?? 0) + 1);
292
+ }
293
+ }
294
+ return false;
295
+ });
296
+ const gaps = [...gapMap.entries()]
297
+ .sort((a, b) => b[1] - a[1])
298
+ .map(([value, count]) => ({ value, count, onGrid: value % gridSize === 0 }));
299
+ const paddings = [...paddingMap.entries()]
300
+ .sort((a, b) => b[1] - a[1])
301
+ .map(([value, count]) => ({ value, count, onGrid: value % gridSize === 0 }));
302
+ const offGridGaps = gaps.filter((g) => !g.onGrid);
303
+ const offGridPaddings = paddings.filter((p) => !p.onGrid);
304
+ return {
305
+ totalNodes,
306
+ gridSize,
307
+ gaps,
308
+ paddings,
309
+ offGridGaps: offGridGaps.map((g) => g.value),
310
+ offGridPaddings: offGridPaddings.map((p) => p.value)
311
+ };
312
+ }
313
+ });
314
+ export const analyzeClusters = defineTool({
315
+ name: 'analyze_clusters',
316
+ description: 'Find repeated design patterns (potential components). Groups nodes by structural signature — type, size, and child structure.',
317
+ params: {
318
+ min_count: { type: 'number', description: 'Min instances to form a cluster (default: 2)' },
319
+ min_size: { type: 'number', description: 'Min node size in px (default: 30)' },
320
+ limit: { type: 'number', description: 'Max clusters to return (default: 20)' }
321
+ },
322
+ execute: (figma, args) => {
323
+ const minCount = args.min_count ?? 2;
324
+ const minSize = args.min_size ?? 30;
325
+ const limit = args.limit ?? 20;
326
+ const page = figma.currentPage;
327
+ const signatureMap = new Map();
328
+ let totalNodes = 0;
329
+ page.findAll((node) => {
330
+ totalNodes++;
331
+ const raw = figma.graph.getNode(node.id);
332
+ if (!raw)
333
+ return false;
334
+ if (raw.width < minSize || raw.height < minSize)
335
+ return false;
336
+ if (raw.type === 'CANVAS' || raw.type === 'INSTANCE')
337
+ return false;
338
+ const childTypes = new Map();
339
+ for (const childId of raw.childIds) {
340
+ const child = figma.graph.getNode(childId);
341
+ if (child)
342
+ childTypes.set(child.type, (childTypes.get(child.type) ?? 0) + 1);
343
+ }
344
+ const w = Math.round(raw.width / 10) * 10;
345
+ const h = Math.round(raw.height / 10) * 10;
346
+ const childSig = [...childTypes.entries()]
347
+ .sort(([a], [b]) => a.localeCompare(b))
348
+ .map(([t, c]) => `${t}:${c}`)
349
+ .join(',');
350
+ const signature = `${raw.type}:${w}x${h}|${childSig}`;
351
+ const list = signatureMap.get(signature) ?? [];
352
+ list.push({
353
+ id: raw.id,
354
+ name: raw.name,
355
+ type: raw.type,
356
+ width: raw.width,
357
+ height: raw.height,
358
+ childCount: raw.childIds.length
359
+ });
360
+ signatureMap.set(signature, list);
361
+ return false;
362
+ });
363
+ const clusters = [...signatureMap.entries()]
364
+ .filter(([, nodes]) => nodes.length >= minCount)
365
+ .map(([signature, nodes]) => {
366
+ const avgW = nodes.reduce((s, n) => s + n.width, 0) / nodes.length;
367
+ const avgH = nodes.reduce((s, n) => s + n.height, 0) / nodes.length;
368
+ const widths = nodes.map((n) => n.width);
369
+ const heights = nodes.map((n) => n.height);
370
+ const widthRange = Math.max(...widths) - Math.min(...widths);
371
+ const heightRange = Math.max(...heights) - Math.min(...heights);
372
+ let confidence = 100;
373
+ if (nodes.length >= 2) {
374
+ const base = nodes[0];
375
+ let score = 0;
376
+ for (const n of nodes.slice(1)) {
377
+ const sizeDiff = Math.abs(n.width - base.width) + Math.abs(n.height - base.height);
378
+ const childDiff = Math.abs(n.childCount - base.childCount);
379
+ if (sizeDiff <= 4 && childDiff === 0)
380
+ score++;
381
+ else if (sizeDiff <= 10 && childDiff <= 1)
382
+ score += 0.8;
383
+ else if (sizeDiff <= 20 && childDiff <= 2)
384
+ score += 0.6;
385
+ else
386
+ score += 0.4;
387
+ }
388
+ confidence = Math.round((score / (nodes.length - 1)) * 100);
389
+ }
390
+ return {
391
+ signature,
392
+ count: nodes.length,
393
+ avgWidth: Math.round(avgW),
394
+ avgHeight: Math.round(avgH),
395
+ widthRange: Math.round(widthRange),
396
+ heightRange: Math.round(heightRange),
397
+ confidence,
398
+ examples: nodes.slice(0, 3).map((n) => ({ id: n.id, name: n.name }))
399
+ };
400
+ })
401
+ .sort((a, b) => b.count - a.count)
402
+ .slice(0, limit);
403
+ return { totalNodes, clusters };
404
+ }
405
+ });
406
+ // ─── Diff tools ───────────────────────────────────────────────
407
+ export const diffCreate = defineTool({
408
+ name: 'diff_create',
409
+ description: 'Create a structural diff between two node trees. Compares properties (fills, strokes, effects, text, size, position) in unified diff format.',
410
+ params: {
411
+ from: { type: 'string', description: 'Source node ID', required: true },
412
+ to: { type: 'string', description: 'Target node ID', required: true },
413
+ depth: { type: 'number', description: 'Max tree depth (default: 10)' }
414
+ },
415
+ execute: (figma, args) => {
416
+ const maxDepth = args.depth ?? 10;
417
+ const fromNode = figma.graph.getNode(args.from);
418
+ const toNode = figma.graph.getNode(args.to);
419
+ if (!fromNode)
420
+ return { error: `Node "${args.from}" not found` };
421
+ if (!toNode)
422
+ return { error: `Node "${args.to}" not found` };
423
+ const fromNodes = collectNodeTree(figma, args.from, '', 0, maxDepth);
424
+ const toNodes = collectNodeTree(figma, args.to, '', 0, maxDepth);
425
+ const allPaths = new Set([...fromNodes.keys(), ...toNodes.keys()]);
426
+ const patches = [];
427
+ for (const path of allPaths) {
428
+ const fromEntry = fromNodes.get(path);
429
+ const toEntry = toNodes.get(path);
430
+ if (!fromEntry && toEntry) {
431
+ const filename = `${path} #${toEntry.id}`;
432
+ const newLines = toEntry.serialized.split('\n');
433
+ patches.push(`--- /dev/null\n+++ ${filename}\n@@ -0,0 +1,${newLines.length} @@\n${newLines.map((l) => `+${l}`).join('\n')}`);
434
+ }
435
+ else if (fromEntry && !toEntry) {
436
+ const filename = `${path} #${fromEntry.id}`;
437
+ const oldLines = fromEntry.serialized.split('\n');
438
+ patches.push(`--- ${filename}\n+++ /dev/null\n@@ -1,${oldLines.length} +0,0 @@\n${oldLines.map((l) => `-${l}`).join('\n')}`);
439
+ }
440
+ else if (fromEntry && toEntry && fromEntry.serialized !== toEntry.serialized) {
441
+ patches.push(createUnifiedDiff(`${path} #${fromEntry.id}`, `${path} #${toEntry.id}`, fromEntry.serialized, toEntry.serialized));
442
+ }
443
+ }
444
+ if (patches.length === 0)
445
+ return { diff: null, message: 'No differences found' };
446
+ return { diff: patches.join('\n') };
447
+ }
448
+ });
449
+ export const diffShow = defineTool({
450
+ name: 'diff_show',
451
+ description: 'Preview what would change if properties were applied to a node. Shows a unified diff of current vs proposed state.',
452
+ params: {
453
+ id: { type: 'string', description: 'Node ID', required: true },
454
+ props: {
455
+ type: 'string',
456
+ description: 'JSON object of new properties, e.g. \'{"opacity": 1, "fill": "#FF0000", "width": 200}\'',
457
+ required: true
458
+ }
459
+ },
460
+ execute: (figma, args) => {
461
+ const raw = figma.graph.getNode(args.id);
462
+ if (!raw)
463
+ return { error: `Node "${args.id}" not found` };
464
+ const oldContent = serializeNodeProps(raw);
465
+ let newProps;
466
+ try {
467
+ newProps = JSON.parse(args.props);
468
+ }
469
+ catch {
470
+ return { error: 'Invalid JSON in props' };
471
+ }
472
+ const modified = structuredClone(raw);
473
+ if (newProps.fill) {
474
+ modified.fills = [
475
+ { type: 'SOLID', color: parseColor(newProps.fill), opacity: 1, visible: true }
476
+ ];
477
+ }
478
+ if (newProps.stroke) {
479
+ modified.strokes = [
480
+ {
481
+ color: parseColor(newProps.stroke),
482
+ weight: modified.strokes[0]?.weight ?? 1,
483
+ opacity: 1,
484
+ visible: true,
485
+ align: modified.strokes[0]?.align ?? 'INSIDE'
486
+ }
487
+ ];
488
+ }
489
+ if (newProps.opacity !== undefined)
490
+ modified.opacity = Number(newProps.opacity);
491
+ if (newProps.radius !== undefined) {
492
+ const r = Number(newProps.radius);
493
+ modified.cornerRadius = r;
494
+ modified.topLeftRadius = r;
495
+ modified.topRightRadius = r;
496
+ modified.bottomRightRadius = r;
497
+ modified.bottomLeftRadius = r;
498
+ }
499
+ if (newProps.width !== undefined)
500
+ modified.width = Number(newProps.width);
501
+ if (newProps.height !== undefined)
502
+ modified.height = Number(newProps.height);
503
+ if (newProps.x !== undefined)
504
+ modified.x = Number(newProps.x);
505
+ if (newProps.y !== undefined)
506
+ modified.y = Number(newProps.y);
507
+ if (newProps.visible !== undefined)
508
+ modified.visible = Boolean(newProps.visible);
509
+ if (newProps.locked !== undefined)
510
+ modified.locked = Boolean(newProps.locked);
511
+ if (newProps.rotation !== undefined)
512
+ modified.rotation = Number(newProps.rotation);
513
+ if (newProps.text !== undefined)
514
+ modified.text = newProps.text;
515
+ const newContent = serializeNodeProps(modified);
516
+ if (oldContent === newContent)
517
+ return { diff: null, message: 'No changes' };
518
+ const filename = `/${raw.name} #${args.id}`;
519
+ return { diff: createUnifiedDiff(filename, filename, oldContent, newContent) };
520
+ }
521
+ });
522
+ // ─── Eval escape hatch ────────────────────────────────────────
523
+ export const evalCode = defineTool({
524
+ name: 'eval',
525
+ description: 'Execute JavaScript with full Figma Plugin API access. Use for operations not covered by other tools. The `figma` global is available.',
526
+ params: {
527
+ code: { type: 'string', description: 'JavaScript code to execute', required: true }
528
+ },
529
+ execute: async (figma, { code }) => {
530
+ // eslint-disable-next-line no-empty-function
531
+ const AsyncFunction = Object.getPrototypeOf(async function () { }).constructor;
532
+ const wrapped = code.trim().startsWith('return') ? code : `return (async () => { ${code} })()`;
533
+ const fn = new AsyncFunction('figma', wrapped);
534
+ const result = await fn(figma);
535
+ if (result && typeof result === 'object' && 'toJSON' in result)
536
+ return result.toJSON();
537
+ return result ?? null;
538
+ }
539
+ });
540
+ // ── Design System Diff ──────────────────────────────────────
541
+ function serializeVariableValue(v) {
542
+ if (typeof v === 'object' && 'aliasId' in v)
543
+ return `alias(${v.aliasId})`;
544
+ if (typeof v === 'object' && 'r' in v) {
545
+ return colorToHex(v);
546
+ }
547
+ return String(v);
548
+ }
549
+ function serializeVariable(v) {
550
+ const lines = [
551
+ `name: ${v.name}`,
552
+ `type: ${v.type}`,
553
+ `collection: ${v.collectionId}`,
554
+ `description: ${v.description || '(none)'}`,
555
+ `hidden: ${v.hiddenFromPublishing}`
556
+ ];
557
+ for (const [modeId, val] of Object.entries(v.valuesByMode)) {
558
+ lines.push(`mode[${modeId}]: ${serializeVariableValue(val)}`);
559
+ }
560
+ return lines.join('\n');
561
+ }
562
+ function serializeCollection(c) {
563
+ const lines = [
564
+ `name: ${c.name}`,
565
+ `defaultMode: ${c.defaultModeId}`,
566
+ `modes: ${c.modes.map((m) => `${m.modeId}(${m.name})`).join(', ')}`,
567
+ `variables: [${c.variableIds.join(', ')}]`
568
+ ];
569
+ return lines.join('\n');
570
+ }
571
+ export function snapshotDesignSystem(figma) {
572
+ const variables = {};
573
+ for (const v of figma.getLocalVariables()) {
574
+ variables[v.id] = { name: v.name, serialized: serializeVariable(v) };
575
+ }
576
+ const collections = {};
577
+ for (const c of figma.getLocalVariableCollections()) {
578
+ collections[c.id] = { name: c.name, serialized: serializeCollection(c) };
579
+ }
580
+ return { variables, collections };
581
+ }
582
+ export const snapshotDesignSystemTool = defineTool({
583
+ name: 'snapshot_design_system',
584
+ description: 'Take a snapshot of the current design system (all variables and collections). Returns a snapshot ID that can be used with diff_design_system.',
585
+ params: {
586
+ label: { type: 'string', description: 'Optional label for this snapshot' }
587
+ },
588
+ execute: (figma, args) => {
589
+ const snapshot = snapshotDesignSystem(figma);
590
+ const id = `ds_${Date.now()}`;
591
+ const figmaRecord = figma;
592
+ const store = (figmaRecord._dsSnapshots ?? new Map());
593
+ figmaRecord._dsSnapshots = store;
594
+ store.set(id, { label: args.label ?? id, snapshot, timestamp: Date.now() });
595
+ return {
596
+ snapshotId: id,
597
+ label: args.label ?? id,
598
+ variableCount: Object.keys(snapshot.variables).length,
599
+ collectionCount: Object.keys(snapshot.collections).length
600
+ };
601
+ }
602
+ });
603
+ export const diffDesignSystem = defineTool({
604
+ name: 'diff_design_system',
605
+ description: 'Compare two design system snapshots. Shows added/removed/modified variables and collections in unified diff format.',
606
+ params: {
607
+ from: { type: 'string', description: 'Source snapshot ID', required: true },
608
+ to: {
609
+ type: 'string',
610
+ description: 'Target snapshot ID. Use "current" to compare against live state.'
611
+ }
612
+ },
613
+ execute: (figma, args) => {
614
+ const store = figma._dsSnapshots;
615
+ if (!store)
616
+ return { error: 'No snapshots found. Use snapshot_design_system first.' };
617
+ const fromEntry = store.get(args.from);
618
+ if (!fromEntry)
619
+ return { error: `Snapshot "${args.from}" not found` };
620
+ const toSnapshot = args.to === 'current' || !args.to ? snapshotDesignSystem(figma) : store.get(args.to)?.snapshot;
621
+ if (!toSnapshot)
622
+ return { error: `Snapshot "${args.to}" not found` };
623
+ const fromSnap = fromEntry.snapshot;
624
+ const patches = [];
625
+ const summary = { added: 0, removed: 0, modified: 0 };
626
+ // Diff collections
627
+ const allCollectionIds = new Set([
628
+ ...Object.keys(fromSnap.collections),
629
+ ...Object.keys(toSnapshot.collections)
630
+ ]);
631
+ for (const id of allCollectionIds) {
632
+ const from = fromSnap.collections[id];
633
+ const to = toSnapshot.collections[id];
634
+ if (!from && to) {
635
+ summary.added++;
636
+ const lines = to.serialized.split('\n');
637
+ patches.push(`--- /dev/null\n+++ collection/${to.name}\n@@ -0,0 +1,${lines.length} @@\n${lines.map((l) => `+${l}`).join('\n')}`);
638
+ }
639
+ else if (from && !to) {
640
+ summary.removed++;
641
+ const lines = from.serialized.split('\n');
642
+ patches.push(`--- collection/${from.name}\n+++ /dev/null\n@@ -1,${lines.length} +0,0 @@\n${lines.map((l) => `-${l}`).join('\n')}`);
643
+ }
644
+ else if (from && to && from.serialized !== to.serialized) {
645
+ summary.modified++;
646
+ patches.push(createTwoFilesPatch(`collection/${from.name}`, `collection/${to.name}`, from.serialized, to.serialized, '', '', { context: 2 }));
647
+ }
648
+ }
649
+ // Diff variables
650
+ const allVarIds = new Set([
651
+ ...Object.keys(fromSnap.variables),
652
+ ...Object.keys(toSnapshot.variables)
653
+ ]);
654
+ for (const id of allVarIds) {
655
+ const from = fromSnap.variables[id];
656
+ const to = toSnapshot.variables[id];
657
+ if (!from && to) {
658
+ summary.added++;
659
+ const lines = to.serialized.split('\n');
660
+ patches.push(`--- /dev/null\n+++ variable/${to.name}\n@@ -0,0 +1,${lines.length} @@\n${lines.map((l) => `+${l}`).join('\n')}`);
661
+ }
662
+ else if (from && !to) {
663
+ summary.removed++;
664
+ const lines = from.serialized.split('\n');
665
+ patches.push(`--- variable/${from.name}\n+++ /dev/null\n@@ -1,${lines.length} +0,0 @@\n${lines.map((l) => `-${l}`).join('\n')}`);
666
+ }
667
+ else if (from && to && from.serialized !== to.serialized) {
668
+ summary.modified++;
669
+ patches.push(createTwoFilesPatch(`variable/${from.name}`, `variable/${to.name}`, from.serialized, to.serialized, '', '', { context: 2 }));
670
+ }
671
+ }
672
+ if (patches.length === 0)
673
+ return { diff: null, summary, message: 'No differences found' };
674
+ return { diff: patches.join('\n'), summary };
675
+ }
676
+ });
677
+ //# sourceMappingURL=analyze.js.map