@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,30 @@
1
+ export type ReactElement = {
2
+ type: string | Function
3
+ props: Record<string, unknown> & { children?: ReactNode[] }
4
+ }
5
+
6
+ export type ReactNode = ReactElement | string | number | null | undefined | ReactNode[]
7
+
8
+ export type FC<P = Record<string, unknown>> = (props: P) => ReactElement
9
+
10
+ export function createElement(
11
+ type: string | Function,
12
+ props: Record<string, unknown> | null,
13
+ ...children: ReactNode[]
14
+ ): ReactElement {
15
+ const flatChildren = children.flat()
16
+ return {
17
+ type,
18
+ props: {
19
+ ...props,
20
+ children:
21
+ flatChildren.length === 1
22
+ ? flatChildren
23
+ : (flatChildren.length > 0
24
+ ? flatChildren
25
+ : undefined)
26
+ }
27
+ }
28
+ }
29
+
30
+ export default { createElement }
@@ -0,0 +1,74 @@
1
+ import { transform } from 'sucrase'
2
+
3
+ import * as React from './mini-react'
4
+ import { renderTree, type RenderResult } from './renderer'
5
+ import { resolveToTree, type TreeNode } from './tree'
6
+
7
+ import type { SceneGraph } from '../scene-graph'
8
+
9
+ /**
10
+ * Build a component function from a JSX string using sucrase.
11
+ * Works in both Node/Bun and the browser (no native bindings).
12
+ */
13
+ export function buildComponent(jsxString: string): () => unknown {
14
+ const code = `
15
+ const h = React.createElement
16
+ const Frame = 'frame', Text = 'text', Rectangle = 'rectangle', Ellipse = 'ellipse'
17
+ const Line = 'line', Star = 'star', Polygon = 'polygon', Vector = 'vector'
18
+ const Group = 'group', Section = 'section', View = 'frame', Rect = 'rectangle'
19
+ return function Component() { return ${jsxString.trim()} }
20
+ `
21
+
22
+ const result = transform(code, {
23
+ transforms: ['typescript', 'jsx'],
24
+ jsxPragma: 'h',
25
+ production: true
26
+ })
27
+
28
+ // Shadow dangerous globals to prevent sandbox escape via new Function()
29
+ const shadowGlobals = [
30
+ 'fetch', 'XMLHttpRequest', 'document', 'window', 'localStorage',
31
+ 'sessionStorage', 'indexedDB', 'WebSocket', 'importScripts', 'eval'
32
+ ]
33
+ const shadowArgs = shadowGlobals.join(',')
34
+ const shadowVals = shadowGlobals.map(() => 'undefined').join(',')
35
+ const wrappedCode = `return (function(${shadowArgs}){${result.code}})(${shadowVals})`
36
+ return new Function('React', wrappedCode)(React) as () => unknown
37
+ }
38
+
39
+ interface RenderJSXOptions {
40
+ x?: number
41
+ y?: number
42
+ parentId?: string
43
+ }
44
+
45
+ /**
46
+ * Render a JSX string into the scene graph.
47
+ * Works in both Node/Bun and the browser.
48
+ */
49
+ export function renderJSX(
50
+ graph: SceneGraph,
51
+ jsxString: string,
52
+ options?: RenderJSXOptions
53
+ ): RenderResult {
54
+ const Component = buildComponent(jsxString)
55
+ const element = React.createElement(Component, null)
56
+ const tree = resolveToTree(element)
57
+
58
+ if (!tree) {
59
+ throw new Error('JSX must return a Figma element (Frame, Text, etc)')
60
+ }
61
+
62
+ return renderTree(graph, tree, options)
63
+ }
64
+
65
+ /**
66
+ * Render a pre-built TreeNode into the scene graph.
67
+ */
68
+ export function renderTreeNode(
69
+ graph: SceneGraph,
70
+ tree: TreeNode,
71
+ options?: RenderJSXOptions
72
+ ): RenderResult {
73
+ return renderTree(graph, tree, options)
74
+ }
@@ -0,0 +1,508 @@
1
+ import { parseColor, colorToFill } from '../color'
2
+ import { TRANSPARENT } from '../constants'
3
+ import { isTreeNode } from './tree'
4
+ import { stripEmoji, emojiToIconName, getIconNetwork } from './emoji-icons'
5
+
6
+ import type { SceneGraph, SceneNode, NodeType, LayoutMode, GridTrack, Stroke } from '../scene-graph'
7
+ import type { TreeNode } from './tree'
8
+
9
+ const TYPE_MAP: Partial<Record<string, NodeType>> = {
10
+ frame: 'FRAME',
11
+ view: 'FRAME',
12
+ rectangle: 'RECTANGLE',
13
+ rect: 'RECTANGLE',
14
+ ellipse: 'ELLIPSE',
15
+ text: 'TEXT',
16
+ line: 'LINE',
17
+ star: 'STAR',
18
+ polygon: 'POLYGON',
19
+ vector: 'VECTOR',
20
+ group: 'GROUP',
21
+ section: 'SECTION',
22
+ component: 'COMPONENT'
23
+ }
24
+
25
+ const WEIGHT_MAP: Record<string, number> = {
26
+ normal: 400,
27
+ medium: 500,
28
+ bold: 700
29
+ }
30
+
31
+ const ALIGN_MAP: Record<string, SceneNode['primaryAxisAlign']> = {
32
+ start: 'MIN',
33
+ end: 'MAX',
34
+ center: 'CENTER',
35
+ between: 'SPACE_BETWEEN'
36
+ }
37
+
38
+ const COUNTER_ALIGN_MAP: Record<string, 'MIN' | 'MAX' | 'CENTER' | 'STRETCH'> = {
39
+ start: 'MIN',
40
+ end: 'MAX',
41
+ center: 'CENTER',
42
+ stretch: 'STRETCH'
43
+ }
44
+
45
+ const TEXT_ALIGN_MAP: Record<string, SceneNode['textAlignHorizontal']> = {
46
+ left: 'LEFT',
47
+ center: 'CENTER',
48
+ right: 'RIGHT',
49
+ justified: 'JUSTIFIED'
50
+ }
51
+
52
+ const TEXT_AUTO_RESIZE_MAP: Record<string, SceneNode['textAutoResize']> = {
53
+ none: 'NONE',
54
+ width: 'WIDTH_AND_HEIGHT',
55
+ height: 'HEIGHT'
56
+ }
57
+
58
+ function parseStroke(value: string, width: number): Stroke {
59
+ const color = parseColor(value)
60
+ return {
61
+ color,
62
+ opacity: color.a,
63
+ visible: true,
64
+ weight: width,
65
+ align: 'INSIDE'
66
+ }
67
+ }
68
+
69
+ interface RenderOptions {
70
+ x?: number
71
+ y?: number
72
+ parentId?: string
73
+ }
74
+
75
+ export interface RenderResult {
76
+ id: string
77
+ name: string
78
+ type: NodeType
79
+ childIds: string[]
80
+ }
81
+
82
+ export function renderTree(
83
+ graph: SceneGraph,
84
+ tree: TreeNode,
85
+ options: RenderOptions = {}
86
+ ): RenderResult {
87
+ const parentId = options.parentId ?? graph.getPages()[0].id
88
+
89
+ const result = renderNode(graph, tree, parentId)
90
+
91
+ if (options.x !== undefined) graph.updateNode(result.id, { x: options.x })
92
+ if (options.y !== undefined) graph.updateNode(result.id, { y: options.y })
93
+
94
+ return {
95
+ id: result.id,
96
+ name: result.name,
97
+ type: result.type,
98
+ childIds: result.childIds
99
+ }
100
+ }
101
+
102
+ function renderNode(graph: SceneGraph, tree: TreeNode, parentId: string): SceneNode {
103
+ const nodeType = TYPE_MAP[tree.type]
104
+ if (!nodeType) throw new Error(`Unknown element: <${tree.type}>`)
105
+
106
+ const parent = graph.getNode(parentId)
107
+ const parentLayout = parent?.layoutMode ?? 'NONE'
108
+
109
+ const isText = nodeType === 'TEXT'
110
+ const overrides = propsToOverrides(tree.props, isText, parentLayout)
111
+
112
+ if (isText) {
113
+ const textContent = tree.children.filter((c): c is string => typeof c === 'string').join('')
114
+ if (textContent) {
115
+ // If text is purely emoji, replace with a vector icon
116
+ const iconName = emojiToIconName(textContent.trim())
117
+ if (iconName) {
118
+ return createIconNode(graph, parentId, iconName, overrides)
119
+ }
120
+ // Strip any remaining emoji from mixed text
121
+ overrides.text = stripEmoji(textContent)
122
+ }
123
+ }
124
+
125
+ const node = graph.createNode(nodeType, parentId, overrides)
126
+
127
+ for (const child of tree.children) {
128
+ if (typeof child === 'string') continue
129
+ if (isTreeNode(child)) {
130
+ renderNode(graph, child, node.id)
131
+ }
132
+ }
133
+
134
+ return node
135
+ }
136
+
137
+ function createIconNode(
138
+ graph: SceneGraph,
139
+ parentId: string,
140
+ iconName: string,
141
+ overrides: Partial<SceneNode>,
142
+ ): SceneNode {
143
+ const network = getIconNetwork(iconName)
144
+ if (!network) {
145
+ return graph.createNode('ELLIPSE', parentId, {
146
+ ...overrides, width: overrides.fontSize ?? 24, height: overrides.fontSize ?? 24,
147
+ name: iconName,
148
+ })
149
+ }
150
+ const size = overrides.fontSize ?? 24
151
+ const scale = size / 24
152
+ const scaled = {
153
+ vertices: network.vertices.map(v => ({ x: v.x * scale, y: v.y * scale })),
154
+ segments: network.segments.map(s => ({
155
+ ...s,
156
+ tangentStart: { x: s.tangentStart.x * scale, y: s.tangentStart.y * scale },
157
+ tangentEnd: { x: s.tangentEnd.x * scale, y: s.tangentEnd.y * scale },
158
+ })),
159
+ regions: network.regions,
160
+ }
161
+ const color = overrides.fills?.[0]?.color ?? parseColor('#374151')
162
+ return graph.createNode('VECTOR', parentId, {
163
+ name: iconName,
164
+ width: size,
165
+ height: size,
166
+ vectorNetwork: scaled,
167
+ strokes: [{ color, weight: scale * 2, opacity: 1, visible: true, align: 'CENTER' as const }],
168
+ fills: [],
169
+ })
170
+ }
171
+
172
+ function applySizeOverrides(
173
+ props: Record<string, unknown>,
174
+ o: Partial<SceneNode>,
175
+ parentLayout: SceneNode['layoutMode']
176
+ ): { w: unknown; h: unknown } {
177
+ const w = props.w ?? props.width
178
+ const h = props.h ?? props.height
179
+ if (typeof w === 'number') o.width = w
180
+ if (typeof h === 'number') o.height = h
181
+
182
+ const isParentRow = parentLayout === 'HORIZONTAL'
183
+ const isParentCol = parentLayout === 'VERTICAL'
184
+ const isParentGrid = parentLayout === 'GRID'
185
+
186
+ if (w === 'fill') {
187
+ if (isParentGrid) o.layoutAlignSelf = 'STRETCH'
188
+ else if (isParentRow) o.layoutGrow = 1
189
+ else if (isParentCol) o.layoutAlignSelf = 'STRETCH'
190
+ else { o.layoutGrow = 1; o.layoutAlignSelf = 'STRETCH' }
191
+ }
192
+ if (h === 'fill') {
193
+ if (isParentGrid) o.layoutAlignSelf = 'STRETCH'
194
+ else if (isParentCol) o.layoutGrow = 1
195
+ else if (isParentRow) o.layoutAlignSelf = 'STRETCH'
196
+ else o.layoutAlignSelf = 'STRETCH'
197
+ }
198
+
199
+ if (props.x !== undefined) o.x = props.x as number
200
+ if (props.y !== undefined) o.y = props.y as number
201
+
202
+ const hasExplicitPosition = props.x !== undefined || props.y !== undefined
203
+ const isInsideAutoLayout = parentLayout !== 'NONE'
204
+ if (hasExplicitPosition && isInsideAutoLayout) {
205
+ o.layoutPositioning = 'ABSOLUTE'
206
+ }
207
+
208
+ return { w, h }
209
+ }
210
+
211
+ function applyVisualOverrides(props: Record<string, unknown>, o: Partial<SceneNode>): void {
212
+ const bg = props.bg ?? props.fill
213
+ if (typeof bg === 'string') {
214
+ o.fills = [colorToFill(bg)]
215
+ }
216
+
217
+ if (typeof props.stroke === 'string') {
218
+ const strokeWidth = (props.strokeWidth as number | undefined) ?? 1
219
+ o.strokes = [parseStroke(props.stroke, strokeWidth)]
220
+ }
221
+
222
+ const rounded = props.rounded ?? props.cornerRadius
223
+ if (typeof rounded === 'number') {
224
+ o.cornerRadius = rounded
225
+ }
226
+ if (
227
+ props.roundedTL !== undefined ||
228
+ props.roundedTR !== undefined ||
229
+ props.roundedBL !== undefined ||
230
+ props.roundedBR !== undefined
231
+ ) {
232
+ o.independentCorners = true
233
+ if (props.roundedTL !== undefined) o.topLeftRadius = props.roundedTL as number
234
+ if (props.roundedTR !== undefined) o.topRightRadius = props.roundedTR as number
235
+ if (props.roundedBL !== undefined) o.bottomLeftRadius = props.roundedBL as number
236
+ if (props.roundedBR !== undefined) o.bottomRightRadius = props.roundedBR as number
237
+ }
238
+ if (props.cornerSmoothing !== undefined) o.cornerSmoothing = props.cornerSmoothing as number
239
+
240
+ if (props.opacity !== undefined) o.opacity = props.opacity as number
241
+ if (props.rotate !== undefined) o.rotation = props.rotate as number
242
+ if (props.blendMode !== undefined) {
243
+ o.blendMode = (props.blendMode as string).toUpperCase() as SceneNode['blendMode']
244
+ }
245
+ if (props.overflow === 'hidden') o.clipsContent = true
246
+ }
247
+
248
+ function applyPaddingOverrides(props: Record<string, unknown>, o: Partial<SceneNode>): void {
249
+ const p = props.p ?? props.padding
250
+ if (typeof p === 'number') {
251
+ o.paddingTop = p
252
+ o.paddingRight = p
253
+ o.paddingBottom = p
254
+ o.paddingLeft = p
255
+ }
256
+ const px = props.px as number | undefined
257
+ const py = props.py as number | undefined
258
+ if (px !== undefined) {
259
+ o.paddingLeft = px
260
+ o.paddingRight = px
261
+ }
262
+ if (py !== undefined) {
263
+ o.paddingTop = py
264
+ o.paddingBottom = py
265
+ }
266
+ if (props.pt !== undefined) o.paddingTop = props.pt as number
267
+ if (props.pr !== undefined) o.paddingRight = props.pr as number
268
+ if (props.pb !== undefined) o.paddingBottom = props.pb as number
269
+ if (props.pl !== undefined) o.paddingLeft = props.pl as number
270
+ }
271
+
272
+ const PADDING_KEYS = ['p', 'padding', 'px', 'py', 'pt', 'pr', 'pb', 'pl'] as const
273
+ const AUTO_LAYOUT_TRIGGER_KEYS = [...PADDING_KEYS, 'justify', 'items'] as const
274
+
275
+ function hasAutoLayoutTriggerProps(props: Record<string, unknown>): boolean {
276
+ return AUTO_LAYOUT_TRIGGER_KEYS.some((k) => props[k] !== undefined)
277
+ }
278
+
279
+ function parseTrack(token: string): GridTrack {
280
+ if (token.endsWith('fr')) {
281
+ return { sizing: 'FR', value: parseFloat(token) || 1 }
282
+ }
283
+ if (token === 'auto') {
284
+ return { sizing: 'AUTO', value: 0 }
285
+ }
286
+ return { sizing: 'FIXED', value: parseFloat(token) || 0 }
287
+ }
288
+
289
+ function parseTrackList(value: string): GridTrack[] {
290
+ return value.trim().split(/\s+/).map(parseTrack)
291
+ }
292
+
293
+ function applyGridOverrides(
294
+ props: Record<string, unknown>,
295
+ o: Partial<SceneNode>,
296
+ w: unknown,
297
+ h: unknown
298
+ ): void {
299
+ o.layoutMode = 'GRID'
300
+
301
+ if (typeof w === 'number') o.width = w
302
+ if (typeof h === 'number') o.height = h
303
+
304
+ if (typeof props.columns === 'string') {
305
+ o.gridTemplateColumns = parseTrackList(props.columns)
306
+ } else if (typeof props.columns === 'number') {
307
+ o.gridTemplateColumns = Array.from({ length: props.columns }, () => ({ sizing: 'FR' as const, value: 1 }))
308
+ }
309
+
310
+ if (typeof props.rows === 'string') {
311
+ o.gridTemplateRows = parseTrackList(props.rows)
312
+ } else if (typeof props.rows === 'number') {
313
+ o.gridTemplateRows = Array.from({ length: props.rows }, () => ({ sizing: 'FR' as const, value: 1 }))
314
+ }
315
+
316
+ if (typeof props.columnGap === 'number') o.gridColumnGap = props.columnGap
317
+ if (typeof props.rowGap === 'number') o.gridRowGap = props.rowGap
318
+ if (typeof props.gap === 'number') {
319
+ o.gridColumnGap = props.gap
320
+ o.gridRowGap = props.gap
321
+ }
322
+
323
+ if (props.rows === undefined && typeof h !== 'number') {
324
+ o.height = 0
325
+ }
326
+ }
327
+
328
+ function applyGridChildOverrides(props: Record<string, unknown>, o: Partial<SceneNode>): void {
329
+ const col = props.colStart ?? props.col
330
+ const row = props.rowStart ?? props.row
331
+ const colSpan = (props.colSpan as number | undefined) ?? 1
332
+ const rowSpan = (props.rowSpan as number | undefined) ?? 1
333
+
334
+ if (col !== undefined || row !== undefined) {
335
+ o.gridPosition = {
336
+ column: (col as number | undefined) ?? 0,
337
+ row: (row as number | undefined) ?? 0,
338
+ columnSpan: colSpan,
339
+ rowSpan: rowSpan
340
+ }
341
+ }
342
+ }
343
+
344
+ function applyAutoLayoutSizing(
345
+ o: Partial<SceneNode>,
346
+ props: Record<string, unknown>,
347
+ w: unknown,
348
+ h: unknown
349
+ ): void {
350
+ const dir = (props.flex as string | undefined) ?? 'col'
351
+ const isVertical = dir === 'col' || dir === 'column'
352
+ o.layoutMode = (isVertical ? 'VERTICAL' : 'HORIZONTAL') as LayoutMode
353
+
354
+ // Default to FIXED so users can freely resize elements on canvas.
355
+ // Only use HUG when explicitly requested via w="hug" or h="hug".
356
+ o.primaryAxisSizing = 'FIXED'
357
+ o.counterAxisSizing = 'FIXED'
358
+
359
+ const primaryDim = isVertical ? h : w
360
+ const counterDim = isVertical ? w : h
361
+
362
+ if (primaryDim === 'hug') o.primaryAxisSizing = 'HUG'
363
+ if (counterDim === 'hug') o.counterAxisSizing = 'HUG'
364
+ }
365
+
366
+ function applyLayoutOverrides(
367
+ props: Record<string, unknown>,
368
+ o: Partial<SceneNode>,
369
+ w: unknown,
370
+ h: unknown,
371
+ isText: boolean,
372
+ parentLayout: SceneNode['layoutMode']
373
+ ): void {
374
+ if (props.grid) {
375
+ applyGridOverrides(props, o, w, h)
376
+ applyPaddingOverrides(props, o)
377
+ if (props.grow !== undefined) o.layoutGrow = props.grow as number
378
+ return
379
+ }
380
+
381
+ if (parentLayout === 'GRID') {
382
+ applyGridChildOverrides(props, o)
383
+ }
384
+
385
+ const needsAutoLayout = props.flex !== undefined || (!isText && hasAutoLayoutTriggerProps(props))
386
+
387
+ if (needsAutoLayout) {
388
+ applyAutoLayoutSizing(o, props, w, h)
389
+ }
390
+
391
+ if (props.gap !== undefined) o.itemSpacing = props.gap as number
392
+
393
+ if (props.wrap) {
394
+ o.layoutWrap = 'WRAP'
395
+ if (props.rowGap !== undefined) o.counterAxisSpacing = props.rowGap as number
396
+ }
397
+
398
+ if (props.justify) {
399
+ o.primaryAxisAlign = ALIGN_MAP[props.justify as string] ?? 'MIN'
400
+ }
401
+ if (props.items) {
402
+ o.counterAxisAlign = COUNTER_ALIGN_MAP[props.items as string] ?? 'MIN'
403
+ }
404
+
405
+ applyPaddingOverrides(props, o)
406
+
407
+ if (props.grow !== undefined) o.layoutGrow = props.grow as number
408
+
409
+ if (props.minW !== undefined) o.width = Math.max(o.width ?? 0, props.minW as number)
410
+ if (props.maxW !== undefined) o.width = Math.min(o.width ?? Infinity, props.maxW as number)
411
+ }
412
+
413
+ function applyTextOverrides(
414
+ props: Record<string, unknown>,
415
+ o: Partial<SceneNode>,
416
+ parentLayout: SceneNode['layoutMode']
417
+ ): void {
418
+ const fontSize = props.size ?? props.fontSize
419
+ if (typeof fontSize === 'number') o.fontSize = fontSize
420
+
421
+ const fontFamily = props.font ?? props.fontFamily
422
+ if (typeof fontFamily === 'string') o.fontFamily = fontFamily
423
+
424
+ const weight = props.weight ?? props.fontWeight
425
+ if (typeof weight === 'number') {
426
+ o.fontWeight = weight
427
+ } else if (typeof weight === 'string') {
428
+ o.fontWeight = WEIGHT_MAP[weight] ?? 400
429
+ }
430
+
431
+ if (typeof props.color === 'string') {
432
+ o.fills = [colorToFill(props.color)]
433
+ }
434
+
435
+ if (props.textAlign) {
436
+ o.textAlignHorizontal = TEXT_ALIGN_MAP[props.textAlign as string] ?? 'LEFT'
437
+ }
438
+
439
+ const w = props.w ?? props.width
440
+ const hasExplicitWidth = w !== undefined
441
+ const fillsParent = w === 'fill' || (props.grow as number) > 0
442
+ const isInsideAutoLayout = parentLayout !== 'NONE'
443
+
444
+ // Coupled with estimateTextSize() in layout.ts — test headless layout after changes.
445
+ if (props.textAutoResize) {
446
+ o.textAutoResize = TEXT_AUTO_RESIZE_MAP[props.textAutoResize as string] ?? 'NONE'
447
+ } else if (hasExplicitWidth || (isInsideAutoLayout && fillsParent)) {
448
+ o.textAutoResize = 'HEIGHT'
449
+ } else {
450
+ o.textAutoResize = 'WIDTH_AND_HEIGHT'
451
+ }
452
+ }
453
+
454
+ function applyShapeAndEffectOverrides(props: Record<string, unknown>, o: Partial<SceneNode>): void {
455
+ if (props.points !== undefined) o.pointCount = props.points as number
456
+ if (props.innerRadius !== undefined) o.starInnerRadius = props.innerRadius as number
457
+ if (props.pointCount !== undefined) o.pointCount = props.pointCount as number
458
+
459
+ if (typeof props.shadow === 'string') {
460
+ const parts = props.shadow.split(/\s+/)
461
+ if (parts.length >= 4) {
462
+ const c = parseColor(parts.slice(3).join(' '))
463
+ o.effects = [
464
+ ...(o.effects ?? []),
465
+ {
466
+ type: 'DROP_SHADOW',
467
+ color: c,
468
+ offset: { x: parseFloat(parts[0]), y: parseFloat(parts[1]) },
469
+ radius: parseFloat(parts[2]),
470
+ spread: 0,
471
+ visible: true
472
+ }
473
+ ]
474
+ }
475
+ }
476
+
477
+ if (typeof props.blur === 'number') {
478
+ o.effects = [
479
+ ...(o.effects ?? []),
480
+ {
481
+ type: 'LAYER_BLUR',
482
+ radius: props.blur,
483
+ visible: true,
484
+ color: { ...TRANSPARENT },
485
+ offset: { x: 0, y: 0 },
486
+ spread: 0
487
+ }
488
+ ]
489
+ }
490
+ }
491
+
492
+ function propsToOverrides(
493
+ props: Record<string, unknown>,
494
+ isText: boolean,
495
+ parentLayout: SceneNode['layoutMode']
496
+ ): Partial<SceneNode> {
497
+ const o: Partial<SceneNode> = {}
498
+
499
+ if (props.name) o.name = props.name as string
500
+
501
+ const { w, h } = applySizeOverrides(props, o, parentLayout)
502
+ applyVisualOverrides(props, o)
503
+ applyLayoutOverrides(props, o, w, h, isText, parentLayout)
504
+ if (isText) applyTextOverrides(props, o, parentLayout)
505
+ applyShapeAndEffectOverrides(props, o)
506
+
507
+ return o
508
+ }