@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,667 @@
1
+ import { colorToHex, colorDistance as colorDist } from '../color'
2
+ import { queryByXPath } from '../xpath'
3
+ import type { Color } from '../types'
4
+ import type { SceneGraph, SceneNode, Variable } from '../scene-graph'
5
+
6
+ export interface RpcCommand<A = unknown, R = unknown> {
7
+ name: string
8
+ execute: (graph: SceneGraph, args: A) => R | Promise<R>
9
+ }
10
+
11
+ /** Walk descendants. Callback returns `false` to stop traversal. */
12
+ function walkNodes(graph: SceneGraph, rootId: string, fn: (node: SceneNode) => boolean): boolean {
13
+ const node = graph.getNode(rootId)
14
+ if (!node) return true
15
+ if (!fn(node)) return false
16
+ for (const childId of node.childIds) {
17
+ if (!walkNodes(graph, childId, fn)) return false
18
+ }
19
+ return true
20
+ }
21
+
22
+ function countNodes(graph: SceneGraph, pageId: string): number {
23
+ let count = 0
24
+ const page = graph.getNode(pageId)
25
+ if (page) for (const cid of page.childIds) walkNodes(graph, cid, () => { count++; return true })
26
+ return count
27
+ }
28
+
29
+ // ── info ──
30
+
31
+ export interface InfoResult {
32
+ pages: number
33
+ totalNodes: number
34
+ types: Record<string, number>
35
+ fonts: string[]
36
+ pageCounts: Record<string, number>
37
+ }
38
+
39
+ export const infoCommand: RpcCommand<void, InfoResult> = {
40
+ name: 'info',
41
+ execute: (graph) => {
42
+ const pages = graph.getPages()
43
+ let totalNodes = 0
44
+ const types: Record<string, number> = {}
45
+ const fonts = new Set<string>()
46
+ const pageCounts: Record<string, number> = {}
47
+
48
+ for (const page of pages) {
49
+ let pageCount = 0
50
+ for (const cid of page.childIds) {
51
+ walkNodes(graph, cid, (node) => {
52
+ totalNodes++
53
+ pageCount++
54
+ types[node.type] = (types[node.type] ?? 0) + 1
55
+ if (node.fontFamily) fonts.add(node.fontFamily)
56
+ return true
57
+ })
58
+ }
59
+ pageCounts[page.name] = pageCount
60
+ }
61
+
62
+ return { pages: pages.length, totalNodes, types, fonts: [...fonts].sort(), pageCounts }
63
+ }
64
+ }
65
+
66
+ // ── pages ──
67
+
68
+ export interface PageItem {
69
+ id: string
70
+ name: string
71
+ nodes: number
72
+ }
73
+
74
+ export const pagesCommand: RpcCommand<void, PageItem[]> = {
75
+ name: 'pages',
76
+ execute: (graph) => {
77
+ return graph.getPages().map((p) => ({ id: p.id, name: p.name, nodes: countNodes(graph, p.id) }))
78
+ }
79
+ }
80
+
81
+ // ── tree ──
82
+
83
+ export interface TreeArgs {
84
+ page?: string
85
+ depth?: number
86
+ }
87
+
88
+ export interface TreeNodeResult {
89
+ id: string
90
+ name: string
91
+ type: string
92
+ x: number
93
+ y: number
94
+ width: number
95
+ height: number
96
+ children?: TreeNodeResult[]
97
+ }
98
+
99
+ function buildTreeNode(graph: SceneGraph, id: string, depth: number, maxDepth: number): TreeNodeResult | null {
100
+ const node = graph.getNode(id)
101
+ if (!node) return null
102
+ const result: TreeNodeResult = {
103
+ id: node.id,
104
+ name: node.name,
105
+ type: node.type,
106
+ x: Math.round(node.x),
107
+ y: Math.round(node.y),
108
+ width: Math.round(node.width),
109
+ height: Math.round(node.height)
110
+ }
111
+ if (node.childIds.length > 0 && depth < maxDepth) {
112
+ result.children = node.childIds
113
+ .map((cid) => buildTreeNode(graph, cid, depth + 1, maxDepth))
114
+ .filter((n): n is TreeNodeResult => n !== null)
115
+ }
116
+ return result
117
+ }
118
+
119
+ export interface TreeResult {
120
+ page: { id: string; name: string; type: string }
121
+ children: TreeNodeResult[]
122
+ }
123
+
124
+ export const treeCommand: RpcCommand<TreeArgs, TreeResult | { error: string }> = {
125
+ name: 'tree',
126
+ execute: (graph, args) => {
127
+ const pages = graph.getPages()
128
+ const maxDepth = args.depth ?? Infinity
129
+ const page = args.page ? pages.find((p) => p.name === args.page) : pages[0]
130
+ if (!page) return { error: `Page "${args.page}" not found. Available: ${pages.map((p) => p.name).join(', ')}` }
131
+
132
+ return {
133
+ page: { id: page.id, name: page.name, type: page.type },
134
+ children: page.childIds
135
+ .map((cid) => buildTreeNode(graph, cid, 0, maxDepth))
136
+ .filter((n): n is TreeNodeResult => n !== null)
137
+ }
138
+ }
139
+ }
140
+
141
+ // ── find ──
142
+
143
+ export interface FindArgs {
144
+ name?: string
145
+ type?: string
146
+ page?: string
147
+ limit?: number
148
+ }
149
+
150
+ export interface FindNodeResult {
151
+ id: string
152
+ name: string
153
+ type: string
154
+ width: number
155
+ height: number
156
+ }
157
+
158
+ export const findCommand: RpcCommand<FindArgs, FindNodeResult[]> = {
159
+ name: 'find',
160
+ execute: (graph, args) => {
161
+ const pages = graph.getPages()
162
+ const max = args.limit ?? 100
163
+ const namePattern = args.name?.toLowerCase()
164
+ const typeFilter = args.type?.toUpperCase()
165
+ const results: FindNodeResult[] = []
166
+
167
+ const searchPage = (page: SceneNode) => {
168
+ for (const cid of page.childIds) {
169
+ const cont = walkNodes(graph, cid, (node) => {
170
+ if (results.length >= max) return false
171
+ const matchesName = !namePattern || node.name.toLowerCase().includes(namePattern)
172
+ const matchesType = !typeFilter || node.type === typeFilter
173
+ if (matchesName && matchesType) {
174
+ results.push({
175
+ id: node.id, name: node.name, type: node.type,
176
+ width: Math.round(node.width), height: Math.round(node.height)
177
+ })
178
+ }
179
+ return true
180
+ })
181
+ if (!cont) break
182
+ }
183
+ }
184
+
185
+ if (args.page) {
186
+ const page = pages.find((p) => p.name === args.page)
187
+ if (page) searchPage(page)
188
+ } else {
189
+ for (const page of pages) searchPage(page)
190
+ }
191
+
192
+ return results
193
+ }
194
+ }
195
+
196
+ // ── query (xpath) ──
197
+
198
+ export interface QueryArgs {
199
+ selector: string
200
+ page?: string
201
+ limit?: number
202
+ }
203
+
204
+ export interface QueryNodeResult {
205
+ id: string
206
+ name: string
207
+ type: string
208
+ x: number
209
+ y: number
210
+ width: number
211
+ height: number
212
+ }
213
+
214
+ export const queryCommand: RpcCommand<QueryArgs, QueryNodeResult[] | { error: string }> = {
215
+ name: 'query',
216
+ execute: async (graph, args) => {
217
+ try {
218
+ const nodes = await queryByXPath(graph, args.selector, {
219
+ page: args.page,
220
+ limit: args.limit
221
+ })
222
+ return nodes.map((n) => ({
223
+ id: n.id,
224
+ name: n.name,
225
+ type: n.type,
226
+ x: Math.round(n.x),
227
+ y: Math.round(n.y),
228
+ width: Math.round(n.width),
229
+ height: Math.round(n.height)
230
+ }))
231
+ } catch (err) {
232
+ return { error: `XPath error: ${err instanceof Error ? err.message : String(err)}` }
233
+ }
234
+ }
235
+ }
236
+
237
+ // ── node ──
238
+
239
+ export interface NodeArgs {
240
+ id: string
241
+ }
242
+
243
+ export interface NodeResult {
244
+ id: string
245
+ name: string
246
+ type: string
247
+ x: number
248
+ y: number
249
+ width: number
250
+ height: number
251
+ visible: boolean
252
+ locked: boolean
253
+ opacity: number
254
+ rotation: number
255
+ fills: unknown[]
256
+ strokes: unknown[]
257
+ effects: unknown[]
258
+ cornerRadius: number
259
+ blendMode: string
260
+ layoutMode: string
261
+ fontFamily: string
262
+ fontSize: number
263
+ fontWeight: number
264
+ text: string | null
265
+ parent: { id: string; name: string; type: string } | null
266
+ children: number
267
+ boundVariables: Record<string, string>
268
+ }
269
+
270
+ export const nodeCommand: RpcCommand<NodeArgs, NodeResult | { error: string }> = {
271
+ name: 'node',
272
+ execute: (graph, args) => {
273
+ const node = graph.getNode(args.id)
274
+ if (!node) return { error: `Node "${args.id}" not found` }
275
+
276
+ const parent = node.parentId ? graph.getNode(node.parentId) : undefined
277
+ const boundVars: Record<string, string> = {}
278
+ for (const [field, varId] of Object.entries(node.boundVariables)) {
279
+ const variable = graph.variables.get(varId)
280
+ boundVars[field] = variable?.name ?? varId
281
+ }
282
+
283
+ return {
284
+ id: node.id,
285
+ name: node.name,
286
+ type: node.type,
287
+ x: Math.round(node.x),
288
+ y: Math.round(node.y),
289
+ width: Math.round(node.width),
290
+ height: Math.round(node.height),
291
+ visible: node.visible,
292
+ locked: node.locked,
293
+ opacity: node.opacity,
294
+ rotation: node.rotation,
295
+ fills: node.fills,
296
+ strokes: node.strokes,
297
+ effects: node.effects,
298
+ cornerRadius: node.cornerRadius,
299
+ blendMode: node.blendMode,
300
+ layoutMode: node.layoutMode,
301
+ fontFamily: node.fontFamily,
302
+ fontSize: node.fontSize,
303
+ fontWeight: node.fontWeight,
304
+ text: node.text.length ? (node.text.length > 200 ? node.text.slice(0, 200) + '…' : node.text) : null,
305
+ parent: parent ? { id: parent.id, name: parent.name, type: parent.type } : null,
306
+ children: node.childIds.length,
307
+ boundVariables: boundVars
308
+ }
309
+ }
310
+ }
311
+
312
+ // ── variables ──
313
+
314
+ export interface VariablesArgs {
315
+ collection?: string
316
+ type?: string
317
+ }
318
+
319
+ function formatVariableValue(variable: Variable, graph: SceneGraph): string {
320
+ const modeId = graph.getActiveModeId(variable.collectionId)
321
+ const raw = variable.valuesByMode[modeId]
322
+
323
+ if (typeof raw === 'object' && 'aliasId' in raw) {
324
+ const alias = graph.variables.get(raw.aliasId)
325
+ return alias ? `→ ${alias.name}` : `→ ${raw.aliasId}`
326
+ }
327
+
328
+ if (typeof raw === 'object' && 'r' in raw) {
329
+ return colorToHex(raw).toLowerCase()
330
+ }
331
+
332
+ return String(raw)
333
+ }
334
+
335
+ export interface VariablesResult {
336
+ collections: Array<{
337
+ id: string
338
+ name: string
339
+ modes: string[]
340
+ variables: Array<{
341
+ id: string
342
+ name: string
343
+ type: string
344
+ value: string
345
+ }>
346
+ }>
347
+ totalVariables: number
348
+ totalCollections: number
349
+ }
350
+
351
+ export const variablesCommand: RpcCommand<VariablesArgs, VariablesResult> = {
352
+ name: 'variables',
353
+ execute: (graph, args) => {
354
+ const typeFilter = args.type?.toUpperCase()
355
+ const collFilter = args.collection?.toLowerCase()
356
+
357
+ const result: VariablesResult = {
358
+ collections: [],
359
+ totalVariables: graph.variables.size,
360
+ totalCollections: graph.variableCollections.size
361
+ }
362
+
363
+ for (const coll of graph.variableCollections.values()) {
364
+ if (collFilter && !coll.name.toLowerCase().includes(collFilter)) continue
365
+
366
+ const collVars = graph.getVariablesForCollection(coll.id)
367
+ .filter((v) => !typeFilter || v.type === typeFilter)
368
+
369
+ if (collVars.length === 0) continue
370
+
371
+ result.collections.push({
372
+ id: coll.id,
373
+ name: coll.name,
374
+ modes: coll.modes.map((m) => m.name),
375
+ variables: collVars.map((v) => ({
376
+ id: v.id,
377
+ name: v.name,
378
+ type: v.type,
379
+ value: formatVariableValue(v, graph)
380
+ }))
381
+ })
382
+ }
383
+
384
+ return result
385
+ }
386
+ }
387
+
388
+ // ── analyze colors ──
389
+
390
+ export interface AnalyzeColorsArgs {
391
+ threshold?: number
392
+ similar?: boolean
393
+ }
394
+
395
+ interface ColorInfo {
396
+ hex: string
397
+ color: Color
398
+ count: number
399
+ variableName: string | null
400
+ }
401
+
402
+ interface ColorCluster {
403
+ colors: ColorInfo[]
404
+ suggestedHex: string
405
+ totalCount: number
406
+ }
407
+
408
+ function clusterColors(colors: ColorInfo[], threshold: number): ColorCluster[] {
409
+ const clusters: ColorCluster[] = []
410
+ const used = new Set<string>()
411
+ const sorted = [...colors].sort((a, b) => b.count - a.count)
412
+
413
+ for (const color of sorted) {
414
+ if (used.has(color.hex)) continue
415
+ const cluster: ColorCluster = { colors: [color], suggestedHex: color.hex, totalCount: color.count }
416
+ used.add(color.hex)
417
+
418
+ for (const other of sorted) {
419
+ if (used.has(other.hex)) continue
420
+ if (colorDist(color.color, other.color) <= threshold) {
421
+ cluster.colors.push(other)
422
+ cluster.totalCount += other.count
423
+ used.add(other.hex)
424
+ }
425
+ }
426
+
427
+ if (cluster.colors.length > 1) clusters.push(cluster)
428
+ }
429
+
430
+ return clusters.sort((a, b) => b.colors.length - a.colors.length)
431
+ }
432
+
433
+ function collectColors(graph: SceneGraph): { colors: ColorInfo[]; totalNodes: number } {
434
+ const colorMap = new Map<string, ColorInfo>()
435
+ let totalNodes = 0
436
+
437
+ const addColor = (c: Color, variableName: string | null) => {
438
+ const hex = colorToHex(c).toLowerCase()
439
+ const existing = colorMap.get(hex)
440
+ if (existing) {
441
+ existing.count++
442
+ if (variableName && !existing.variableName) existing.variableName = variableName
443
+ } else {
444
+ colorMap.set(hex, { hex, color: c, count: 1, variableName })
445
+ }
446
+ }
447
+
448
+ for (const node of graph.getAllNodes()) {
449
+ if (node.type === 'CANVAS') continue
450
+ totalNodes++
451
+
452
+ for (const fill of node.fills) {
453
+ if (!fill.visible || fill.type !== 'SOLID') continue
454
+ addColor(fill.color, null)
455
+ }
456
+ for (const stroke of node.strokes) {
457
+ if (!stroke.visible) continue
458
+ addColor(stroke.color, null)
459
+ }
460
+ for (const effect of node.effects) {
461
+ if (!effect.visible) continue
462
+ addColor(effect.color, null)
463
+ }
464
+
465
+ for (const [field, varId] of Object.entries(node.boundVariables)) {
466
+ if (!field.includes('fill') && !field.includes('stroke') && !field.includes('color')) continue
467
+ const variable = graph.variables.get(varId)
468
+ if (variable) {
469
+ const resolvedColor = graph.resolveColorVariable(varId)
470
+ if (resolvedColor) {
471
+ const hex = colorToHex(resolvedColor).toLowerCase()
472
+ const existing = colorMap.get(hex)
473
+ if (existing) existing.variableName = variable.name
474
+ }
475
+ }
476
+ }
477
+ }
478
+
479
+ return { colors: [...colorMap.values()], totalNodes }
480
+ }
481
+
482
+ export interface AnalyzeColorsResult {
483
+ colors: ColorInfo[]
484
+ totalNodes: number
485
+ clusters: ColorCluster[]
486
+ }
487
+
488
+ export const analyzeColorsCommand: RpcCommand<AnalyzeColorsArgs, AnalyzeColorsResult> = {
489
+ name: 'analyze_colors',
490
+ execute: (graph, args) => {
491
+ const { colors, totalNodes } = collectColors(graph)
492
+ const clusters = args.similar ? clusterColors(colors.filter((c) => !c.variableName), args.threshold ?? 15) : []
493
+ return { colors: colors.sort((a, b) => b.count - a.count), totalNodes, clusters }
494
+ }
495
+ }
496
+
497
+ // ── analyze typography ──
498
+
499
+ export interface AnalyzeTypographyArgs {}
500
+
501
+ export interface TypographyStyle {
502
+ family: string
503
+ size: number
504
+ weight: number
505
+ lineHeight: string
506
+ count: number
507
+ }
508
+
509
+ export interface AnalyzeTypographyResult {
510
+ styles: TypographyStyle[]
511
+ totalTextNodes: number
512
+ }
513
+
514
+ export const analyzeTypographyCommand: RpcCommand<AnalyzeTypographyArgs, AnalyzeTypographyResult> = {
515
+ name: 'analyze_typography',
516
+ execute: (graph) => {
517
+ const styleMap = new Map<string, TypographyStyle>()
518
+ let totalTextNodes = 0
519
+
520
+ for (const node of graph.getAllNodes()) {
521
+ if (node.type !== 'TEXT') continue
522
+ totalTextNodes++
523
+
524
+ const lh = node.lineHeight === null ? 'auto' : `${node.lineHeight}px`
525
+ const key = `${node.fontFamily}|${node.fontSize}|${node.fontWeight}|${lh}`
526
+ const existing = styleMap.get(key)
527
+ if (existing) { existing.count++ } else {
528
+ styleMap.set(key, { family: node.fontFamily, size: node.fontSize, weight: node.fontWeight, lineHeight: lh, count: 1 })
529
+ }
530
+ }
531
+
532
+ return { styles: [...styleMap.values()].sort((a, b) => b.count - a.count), totalTextNodes }
533
+ }
534
+ }
535
+
536
+ // ── analyze spacing ──
537
+
538
+ export interface SpacingValue {
539
+ value: number
540
+ count: number
541
+ }
542
+
543
+ export interface AnalyzeSpacingResult {
544
+ gaps: SpacingValue[]
545
+ paddings: SpacingValue[]
546
+ totalNodes: number
547
+ }
548
+
549
+ export const analyzeSpacingCommand: RpcCommand<void, AnalyzeSpacingResult> = {
550
+ name: 'analyze_spacing',
551
+ execute: (graph) => {
552
+ const gapMap = new Map<number, number>()
553
+ const paddingMap = new Map<number, number>()
554
+ let totalNodes = 0
555
+
556
+ for (const node of graph.getAllNodes()) {
557
+ if (node.type === 'CANVAS' || node.layoutMode === 'NONE') continue
558
+ totalNodes++
559
+
560
+ if (node.itemSpacing > 0) gapMap.set(node.itemSpacing, (gapMap.get(node.itemSpacing) ?? 0) + 1)
561
+ if (node.counterAxisSpacing > 0) gapMap.set(node.counterAxisSpacing, (gapMap.get(node.counterAxisSpacing) ?? 0) + 1)
562
+
563
+ for (const pad of [node.paddingTop, node.paddingRight, node.paddingBottom, node.paddingLeft]) {
564
+ if (pad > 0) paddingMap.set(pad, (paddingMap.get(pad) ?? 0) + 1)
565
+ }
566
+ }
567
+
568
+ const toValues = (map: Map<number, number>) =>
569
+ [...map.entries()].map(([value, count]) => ({ value, count })).sort((a, b) => b.count - a.count)
570
+
571
+ return { gaps: toValues(gapMap), paddings: toValues(paddingMap), totalNodes }
572
+ }
573
+ }
574
+
575
+ // ── analyze clusters ──
576
+
577
+ export interface AnalyzeClustersArgs {
578
+ limit?: number
579
+ minSize?: number
580
+ minCount?: number
581
+ }
582
+
583
+ interface ClusterNode {
584
+ id: string
585
+ name: string
586
+ type: string
587
+ width: number
588
+ height: number
589
+ childCount: number
590
+ }
591
+
592
+ export interface AnalyzeClustersResult {
593
+ clusters: Array<{
594
+ signature: string
595
+ nodes: ClusterNode[]
596
+ }>
597
+ totalNodes: number
598
+ }
599
+
600
+ function buildSignature(graph: SceneGraph, node: SceneNode): string {
601
+ const childTypes = new Map<string, number>()
602
+ for (const childId of node.childIds) {
603
+ const child = graph.getNode(childId)
604
+ if (!child) continue
605
+ childTypes.set(child.type, (childTypes.get(child.type) ?? 0) + 1)
606
+ }
607
+ const childPart = [...childTypes.entries()].sort((a, b) => a[0].localeCompare(b[0])).map(([t, c]) => `${t}:${c}`).join(',')
608
+ const w = Math.round(node.width / 10) * 10
609
+ const h = Math.round(node.height / 10) * 10
610
+ return `${node.type}:${w}x${h}|${childPart}`
611
+ }
612
+
613
+ export const analyzeClustersCommand: RpcCommand<AnalyzeClustersArgs, AnalyzeClustersResult> = {
614
+ name: 'analyze_clusters',
615
+ execute: (graph, args) => {
616
+ const minSize = args.minSize ?? 30
617
+ const minCount = args.minCount ?? 2
618
+ const limit = args.limit ?? 20
619
+ const sigMap = new Map<string, ClusterNode[]>()
620
+ let totalNodes = 0
621
+
622
+ for (const node of graph.getAllNodes()) {
623
+ if (node.type === 'CANVAS') continue
624
+ totalNodes++
625
+ if (node.width < minSize || node.height < minSize) continue
626
+ if (node.childIds.length === 0) continue
627
+
628
+ const sig = buildSignature(graph, node)
629
+ const arr = sigMap.get(sig) ?? []
630
+ arr.push({
631
+ id: node.id, name: node.name, type: node.type,
632
+ width: Math.round(node.width), height: Math.round(node.height), childCount: node.childIds.length
633
+ })
634
+ sigMap.set(sig, arr)
635
+ }
636
+
637
+ const clusters = [...sigMap.entries()]
638
+ .filter(([, nodes]) => nodes.length >= minCount)
639
+ .map(([signature, nodes]) => ({ signature, nodes }))
640
+ .sort((a, b) => b.nodes.length - a.nodes.length)
641
+ .slice(0, limit)
642
+
643
+ return { clusters, totalNodes }
644
+ }
645
+ }
646
+
647
+ // ── registry ──
648
+
649
+ export const ALL_RPC_COMMANDS = [
650
+ infoCommand,
651
+ pagesCommand,
652
+ treeCommand,
653
+ findCommand,
654
+ queryCommand,
655
+ nodeCommand,
656
+ variablesCommand,
657
+ analyzeColorsCommand,
658
+ analyzeTypographyCommand,
659
+ analyzeSpacingCommand,
660
+ analyzeClustersCommand
661
+ ] as RpcCommand[]
662
+
663
+ export function executeRpcCommand(graph: SceneGraph, name: string, args: unknown): unknown {
664
+ const cmd = ALL_RPC_COMMANDS.find((c) => c.name === name)
665
+ if (!cmd) throw new Error(`Unknown command: ${name}`)
666
+ return cmd.execute(graph, args as never)
667
+ }
@@ -0,0 +1,25 @@
1
+ export { executeRpcCommand, ALL_RPC_COMMANDS } from './commands'
2
+ export type {
3
+ InfoResult,
4
+ PageItem,
5
+ TreeArgs,
6
+ TreeResult,
7
+ TreeNodeResult,
8
+ FindArgs,
9
+ FindNodeResult,
10
+ QueryArgs,
11
+ QueryNodeResult,
12
+ NodeArgs,
13
+ NodeResult,
14
+ VariablesArgs,
15
+ VariablesResult,
16
+ AnalyzeColorsArgs,
17
+ AnalyzeColorsResult,
18
+ AnalyzeTypographyArgs,
19
+ AnalyzeTypographyResult,
20
+ AnalyzeSpacingResult,
21
+ SpacingValue,
22
+ AnalyzeClustersArgs,
23
+ AnalyzeClustersResult,
24
+ TypographyStyle
25
+ } from './commands'