@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,277 @@
1
+ import type { Color } from './types'
2
+
3
+ export const IS_TAURI = typeof window !== 'undefined' && '__TAURI_INTERNALS__' in window
4
+
5
+ export const BLACK: Color = { r: 0, g: 0, b: 0, a: 1 }
6
+ export const TRANSPARENT: Color = { r: 0, g: 0, b: 0, a: 0 }
7
+ export const DEFAULT_SHADOW_COLOR: Color = { r: 0, g: 0, b: 0, a: 0.25 }
8
+ export const SELECTION_COLOR = { r: 0.23, g: 0.51, b: 0.96, a: 1 } satisfies Color
9
+ export const COMPONENT_COLOR = { r: 0.592, g: 0.278, b: 1, a: 1 } satisfies Color
10
+ export const SNAP_COLOR = { r: 1.0, g: 0.0, b: 0.56, a: 1 } satisfies Color
11
+ export const MEASUREMENT_COLOR = { r: 1.0, g: 0.3, b: 0.3, a: 1 } satisfies Color
12
+ export const CANVAS_BG_COLOR = { r: 0.96, g: 0.96, b: 0.96, a: 1 } satisfies Color
13
+
14
+ // Measurement overlay
15
+ export const MEASUREMENT_LINE_WIDTH = 1
16
+ export const MEASUREMENT_PILL_HEIGHT = 16
17
+ export const MEASUREMENT_PILL_PADDING_X = 5
18
+ export const MEASUREMENT_PILL_RADIUS = 3
19
+ export const MEASUREMENT_FONT_SIZE = 10
20
+ export const MEASUREMENT_DASH = [4, 3]
21
+ export const MEASUREMENT_ARROW_SIZE = 4
22
+
23
+ export const ROTATION_HANDLE_OFFSET = 20
24
+ export const SNAP_THRESHOLD = 5
25
+
26
+ export const RULER_SIZE = 20
27
+ export const RULER_BG_COLOR = { r: 0.14, g: 0.14, b: 0.14, a: 1 } satisfies Color
28
+ export const RULER_TICK_COLOR = { r: 0.4, g: 0.4, b: 0.4, a: 1 } satisfies Color
29
+ export const RULER_TEXT_COLOR = { r: 0.55, g: 0.55, b: 0.55, a: 1 } satisfies Color
30
+ export const RULER_BADGE_HEIGHT = 14
31
+ export const RULER_BADGE_PADDING = 3
32
+ export const RULER_BADGE_RADIUS = 2
33
+ export const RULER_BADGE_EXCLUSION = 30
34
+ export const RULER_TEXT_BASELINE = 0.65
35
+ export const RULER_MAJOR_TICK = 0.5
36
+ export const RULER_MINOR_TICK = 0.25
37
+ export const RULER_HIGHLIGHT_ALPHA = 0.3
38
+
39
+ export const PEN_HANDLE_RADIUS = 3
40
+ export const PEN_VERTEX_RADIUS = 4
41
+ export const PEN_CLOSE_RADIUS_BOOST = 2
42
+ export const PEN_PATH_STROKE_WIDTH = 2
43
+ export const PARENT_OUTLINE_ALPHA = 0.5
44
+ export const PARENT_OUTLINE_DASH = 4
45
+ export const DEFAULT_FONT_FAMILY = 'Inter'
46
+ export const DEFAULT_FONT_SIZE = 14
47
+ export const DEFAULT_STROKE_MITER_LIMIT = 4
48
+ export const LABEL_FONT_SIZE = 11
49
+ export const SIZE_FONT_SIZE = 10
50
+
51
+ export const ROTATION_HANDLE_RADIUS = 4
52
+
53
+ export const HANDLE_HALF_SIZE = 3
54
+
55
+ export const LABEL_OFFSET_Y = 8
56
+ export const SIZE_PILL_PADDING_X = 6
57
+ export const SIZE_PILL_PADDING_Y = 6
58
+ export const SIZE_PILL_HEIGHT = 18
59
+ export const SIZE_PILL_RADIUS = 4
60
+ export const SIZE_PILL_TEXT_OFFSET_Y = 13
61
+
62
+ export const MARQUEE_FILL_ALPHA = 0.08
63
+ export const SELECTION_DASH_ALPHA = 0.6
64
+ export const DROP_HIGHLIGHT_ALPHA = 0.8
65
+ export const DROP_HIGHLIGHT_STROKE = 2
66
+
67
+ export const LAYOUT_INDICATOR_STROKE = 2
68
+
69
+ export const SECTION_CORNER_RADIUS = 5
70
+ export const SECTION_TITLE_HEIGHT = 24
71
+ export const SECTION_TITLE_PADDING_X = 8
72
+ export const SECTION_TITLE_RADIUS = 5
73
+ export const SECTION_TITLE_FONT_SIZE = 12
74
+ export const SECTION_TITLE_GAP = 6
75
+
76
+ export const COMPONENT_SET_DASH = 6
77
+ export const COMPONENT_SET_DASH_GAP = 4
78
+ export const COMPONENT_SET_BORDER_WIDTH = 1.5
79
+ export const COMPONENT_LABEL_FONT_SIZE = 11
80
+ export const COMPONENT_LABEL_GAP = 6
81
+ export const COMPONENT_LABEL_ICON_SIZE = 10
82
+ export const COMPONENT_LABEL_ICON_GAP = 4
83
+
84
+ export const RULER_TARGET_PIXEL_SPACING = 100
85
+ export const RULER_MAJOR_TOLERANCE = 0.01
86
+
87
+ export const FLASH_COLOR = SELECTION_COLOR
88
+ export const FLASH_ATTACK_MS = 200
89
+ export const FLASH_HOLD_MS = 400
90
+ export const FLASH_RELEASE_MS = 300
91
+ export const FLASH_STROKE_WIDTH = 2
92
+ export const FLASH_PADDING = 5
93
+ export const FLASH_OVERSHOOT = 30
94
+ export const FLASH_RADIUS = 4
95
+
96
+ export const TEXT_SELECTION_COLOR = { r: 0.26, g: 0.52, b: 0.96, a: 0.3 }
97
+ export const TEXT_CARET_COLOR = BLACK
98
+ export const TEXT_CARET_WIDTH = 1
99
+
100
+ export type AIProviderID =
101
+ | 'openrouter'
102
+ | 'anthropic'
103
+ | 'openai'
104
+ | 'google'
105
+ | 'openai-compatible'
106
+ | 'zai'
107
+ | 'minimax'
108
+ | 'anthropic-compatible'
109
+
110
+ export interface ModelOption {
111
+ id: string
112
+ name: string
113
+ tag?: string
114
+ }
115
+
116
+ export interface AIProviderDef {
117
+ id: AIProviderID
118
+ name: string
119
+ keyPlaceholder: string
120
+ keyURL: string
121
+ models: ModelOption[]
122
+ defaultModel: string
123
+ supportsCustomBaseURL?: boolean
124
+ supportsCustomModel?: boolean
125
+ recommended?: boolean
126
+ }
127
+
128
+ export const AI_PROVIDERS: AIProviderDef[] = [
129
+ {
130
+ id: 'openrouter',
131
+ name: 'OpenRouter',
132
+ keyPlaceholder: 'sk-or-…',
133
+ keyURL: 'https://openrouter.ai/keys',
134
+ defaultModel: 'anthropic/claude-sonnet-4.6',
135
+ recommended: true,
136
+ models: [
137
+ { id: 'anthropic/claude-sonnet-4.6', name: 'Claude Sonnet 4.6', tag: 'Best for design' },
138
+ { id: 'anthropic/claude-opus-4.6', name: 'Claude Opus 4.6', tag: 'Smartest' },
139
+ { id: 'moonshotai/kimi-k2.5', name: 'Kimi K2.5', tag: 'Vision + code' },
140
+ {
141
+ id: 'google/gemini-3.1-pro-preview',
142
+ name: 'Gemini 3.1 Pro',
143
+ tag: '1M context'
144
+ },
145
+ { id: 'openai/gpt-5.3-codex', name: 'GPT-5.3 Codex' },
146
+ { id: 'google/gemini-3-flash-preview', name: 'Gemini 3 Flash', tag: 'Fast' },
147
+ { id: 'deepseek/deepseek-v3.2', name: 'DeepSeek V3.2', tag: 'Cheap' },
148
+ { id: 'qwen/qwen3.5-flash-02-23', name: 'Qwen 3.5 Flash', tag: 'Cheap' },
149
+ { id: 'qwen/qwen3-coder:free', name: 'Qwen3 Coder', tag: 'Free' },
150
+ { id: 'openai/gpt-oss-120b:free', name: 'GPT-OSS 120B', tag: 'Free' }
151
+ ]
152
+ },
153
+ {
154
+ id: 'anthropic',
155
+ name: 'Anthropic',
156
+ keyPlaceholder: 'sk-ant-…',
157
+ keyURL: 'https://console.anthropic.com/settings/keys',
158
+ defaultModel: 'claude-sonnet-4-6-20260301',
159
+ models: [
160
+ { id: 'claude-sonnet-4-6-20260301', name: 'Claude Sonnet 4.6', tag: 'Best for design' },
161
+ { id: 'claude-opus-4-6-20260301', name: 'Claude Opus 4.6', tag: 'Smartest' }
162
+ ]
163
+ },
164
+ {
165
+ id: 'openai',
166
+ name: 'OpenAI',
167
+ keyPlaceholder: 'sk-…',
168
+ keyURL: 'https://platform.openai.com/api-keys',
169
+ defaultModel: 'gpt-5.3-codex',
170
+ models: [
171
+ { id: 'gpt-5.3-codex', name: 'GPT-5.3 Codex' },
172
+ { id: 'gpt-4.1', name: 'GPT-4.1' },
173
+ { id: 'o3', name: 'o3', tag: 'Reasoning' },
174
+ { id: 'o4-mini', name: 'o4-mini', tag: 'Fast reasoning' }
175
+ ]
176
+ },
177
+ {
178
+ id: 'google',
179
+ name: 'Google AI',
180
+ keyPlaceholder: 'AIza…',
181
+ keyURL: 'https://aistudio.google.com/apikey',
182
+ defaultModel: 'gemini-3.1-pro-preview',
183
+ models: [
184
+ { id: 'gemini-3.1-pro-preview', name: 'Gemini 3.1 Pro', tag: '1M context' },
185
+ { id: 'gemini-3-flash-preview', name: 'Gemini 3 Flash', tag: 'Fast' }
186
+ ]
187
+ },
188
+ {
189
+ id: 'zai',
190
+ name: 'Z.ai',
191
+ keyPlaceholder: 'API key',
192
+ keyURL: 'https://docs.z.ai/api-reference/introduction',
193
+ defaultModel: 'glm-5',
194
+ models: [
195
+ { id: 'glm-5', name: 'GLM-5' },
196
+ { id: 'glm-5-code', name: 'GLM-5-Code' },
197
+ { id: 'glm-4.7', name: 'GLM-4.7' },
198
+ { id: 'glm-4.7-flashx', name: 'GLM-4.7-FlashX' },
199
+ { id: 'glm-4.6', name: 'GLM-4.6' },
200
+ { id: 'glm-4.5', name: 'GLM-4.5' },
201
+ { id: 'glm-4.5-x', name: 'GLM-4.5-X' },
202
+ { id: 'glm-4.5-air', name: 'GLM-4.5-Air' },
203
+ { id: 'glm-4.5-airx', name: 'GLM-4.5-AirX' },
204
+ { id: 'glm-4-32b-0414-128k', name: 'GLM-4-32B-0414-128K' },
205
+ { id: 'glm-4.7-flash', name: 'GLM-4.7-Flash', tag: 'Free' },
206
+ { id: 'glm-4.5-flash', name: 'GLM-4.5-Flash', tag: 'Free' }
207
+ ]
208
+ },
209
+ {
210
+ id: 'minimax',
211
+ name: 'MiniMax',
212
+ keyPlaceholder: 'API key',
213
+ keyURL: 'https://platform.minimax.io/user-center/basic-information/interface-key',
214
+ defaultModel: 'MiniMax-M2.5',
215
+ models: [
216
+ { id: 'MiniMax-M2.5', name: 'MiniMax-M2.5', tag: 'Best' },
217
+ { id: 'MiniMax-M2.5-highspeed', name: 'MiniMax-M2.5 Highspeed', tag: 'Fast' },
218
+ { id: 'MiniMax-M2.1', name: 'MiniMax-M2.1' },
219
+ { id: 'MiniMax-M2.1-highspeed', name: 'MiniMax-M2.1 Highspeed', tag: 'Fast' },
220
+ { id: 'MiniMax-M2', name: 'MiniMax-M2' }
221
+ ]
222
+ },
223
+ {
224
+ id: 'openai-compatible',
225
+ name: 'OpenAI-compatible',
226
+ keyPlaceholder: 'API key',
227
+ keyURL: '',
228
+ defaultModel: '',
229
+ models: [],
230
+ supportsCustomBaseURL: true,
231
+ supportsCustomModel: true
232
+ },
233
+ {
234
+ id: 'anthropic-compatible',
235
+ name: 'Anthropic-compatible',
236
+ keyPlaceholder: 'API key',
237
+ keyURL: '',
238
+ defaultModel: '',
239
+ models: [],
240
+ supportsCustomBaseURL: true,
241
+ supportsCustomModel: true
242
+ }
243
+ ]
244
+
245
+ export const DEFAULT_AI_PROVIDER: AIProviderID = 'openrouter'
246
+ export const DEFAULT_AI_MODEL = AI_PROVIDERS[0].defaultModel
247
+
248
+ export const AUTOMATION_HTTP_PORT = 7600
249
+ export const AUTOMATION_WS_PORT = 7601
250
+
251
+ export const GOOGLE_FONTS_API_KEY: string =
252
+ import.meta.env?.VITE_GOOGLE_FONTS_API_KEY ?? ''
253
+
254
+ export const CJK_FALLBACK_FAMILIES_MACOS = [
255
+ 'PingFang SC',
256
+ 'Hiragino Sans',
257
+ 'Apple SD Gothic Neo',
258
+ 'Heiti SC'
259
+ ]
260
+
261
+ export const CJK_FALLBACK_FAMILIES_WINDOWS = [
262
+ 'Microsoft YaHei',
263
+ 'Microsoft JhengHei',
264
+ 'Yu Gothic',
265
+ 'Malgun Gothic',
266
+ 'SimHei'
267
+ ]
268
+
269
+ export const CJK_FALLBACK_FAMILIES_LINUX = [
270
+ 'Noto Sans CJK SC',
271
+ 'Noto Sans CJK JP',
272
+ 'Noto Sans CJK KR',
273
+ 'WenQuanYi Micro Hei',
274
+ 'Droid Sans Fallback'
275
+ ]
276
+
277
+ export const CJK_GOOGLE_FONT = 'Noto Sans SC'
package/src/copy.ts ADDED
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Typed shallow-copy helpers for Fill, Stroke, Effect, and StyleRun.
3
+ *
4
+ * These replace `structuredClone` for known scene-graph array types,
5
+ * avoiding the ~24× overhead of the generic deep-clone algorithm.
6
+ * Each helper spreads the top-level object and any nested objects
7
+ * (color, offset, gradientStops, dashPattern, style) to ensure
8
+ * no shared references between source and copy.
9
+ */
10
+
11
+ import type { Effect, Fill, GeometryPath, GradientStop, Stroke, StyleRun } from './scene-graph'
12
+
13
+ // --- Individual copy functions ---
14
+
15
+ export function copyFill(f: Fill): Fill {
16
+ const copy: Fill = { ...f, color: { ...f.color } }
17
+ if (f.gradientStops) copy.gradientStops = f.gradientStops.map(copyGradientStop)
18
+ if (f.gradientTransform) copy.gradientTransform = { ...f.gradientTransform }
19
+ if (f.imageTransform) copy.imageTransform = { ...f.imageTransform }
20
+ return copy
21
+ }
22
+
23
+ export function copyStroke(s: Stroke): Stroke {
24
+ const copy: Stroke = { ...s, color: { ...s.color } }
25
+ if (s.dashPattern) {
26
+ copy.dashPattern = [...s.dashPattern]
27
+ }
28
+ return copy
29
+ }
30
+
31
+ export function copyEffect(e: Effect): Effect {
32
+ return {
33
+ ...e,
34
+ color: { ...e.color },
35
+ offset: { ...e.offset },
36
+ }
37
+ }
38
+
39
+ export function copyStyleRun(r: StyleRun): StyleRun {
40
+ return {
41
+ ...r,
42
+ style: { ...r.style },
43
+ }
44
+ }
45
+
46
+ // --- Array copy functions ---
47
+
48
+ export function copyFills(fills: Fill[]): Fill[] {
49
+ return fills.map(copyFill)
50
+ }
51
+
52
+ export function copyStrokes(strokes: Stroke[]): Stroke[] {
53
+ return strokes.map(copyStroke)
54
+ }
55
+
56
+ export function copyEffects(effects: Effect[]): Effect[] {
57
+ return effects.map(copyEffect)
58
+ }
59
+
60
+ export function copyStyleRuns(runs: StyleRun[]): StyleRun[] {
61
+ return runs.map(copyStyleRun)
62
+ }
63
+
64
+ export function copyGeometryPaths(paths: GeometryPath[]): GeometryPath[] {
65
+ return paths.map((p) => ({
66
+ windingRule: p.windingRule,
67
+ commandsBlob: p.commandsBlob.slice(),
68
+ }))
69
+ }
70
+
71
+ // --- Internal helpers ---
72
+
73
+ function copyGradientStop(gs: GradientStop): GradientStop {
74
+ return { color: { ...gs.color }, position: gs.position }
75
+ }
@@ -0,0 +1,28 @@
1
+ import { zipSync, type Zippable } from 'fflate'
2
+ import { buildFigKiwi } from './kiwi-serialize'
3
+
4
+ interface CompressMessage {
5
+ schemaDeflated: Uint8Array
6
+ kiwiData: Uint8Array
7
+ thumbnailPng: Uint8Array
8
+ metaJson: string
9
+ images: Array<{ name: string; data: Uint8Array }>
10
+ }
11
+
12
+ self.onmessage = (e: MessageEvent<CompressMessage>) => {
13
+ const { schemaDeflated, kiwiData, thumbnailPng, metaJson, images } = e.data
14
+
15
+ const canvasData = buildFigKiwi(schemaDeflated, kiwiData)
16
+
17
+ const zipEntries: Zippable = {
18
+ 'canvas.fig': [canvasData, { level: 0 }],
19
+ 'thumbnail.png': [thumbnailPng, { level: 0 }],
20
+ 'meta.json': new TextEncoder().encode(metaJson)
21
+ }
22
+ for (const entry of images) {
23
+ zipEntries[entry.name] = [entry.data, { level: 0 }]
24
+ }
25
+
26
+ const result = zipSync(zipEntries)
27
+ self.postMessage(result, { transfer: [result.buffer] })
28
+ }
@@ -0,0 +1,321 @@
1
+ import { zipSync, deflateSync, type Zippable } from 'fflate'
2
+
3
+ import { CANVAS_BG_COLOR, IS_TAURI } from './constants'
4
+ import { sceneNodeToKiwi, fractionalPosition, buildFigKiwi, buildFontDigestMap } from './kiwi-serialize'
5
+ import { initCodec, getCompiledSchema, getSchemaBytes } from './kiwi/codec'
6
+ import { stringToGuid } from './kiwi/kiwi-convert'
7
+ import { renderThumbnail } from './render-image'
8
+
9
+ import type { NodeChange } from './kiwi/codec'
10
+ import type { SkiaRenderer } from './renderer'
11
+ import type { SceneGraph, VariableValue } from './scene-graph'
12
+ import type { CanvasKit } from 'canvaskit-wasm'
13
+ import type { GUID } from './types'
14
+
15
+ const THUMBNAIL_1X1 = Uint8Array.from(
16
+ atob(
17
+ 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8/5+hHgAHggJ/PchI7wAAAABJRU5ErkJggg=='
18
+ ),
19
+ (c) => c.charCodeAt(0)
20
+ )
21
+
22
+ type KiwiNodeChange = NodeChange & Record<string, unknown>
23
+
24
+ function variableValueToKiwi(
25
+ value: VariableValue,
26
+ type: string
27
+ ): { value: Record<string, unknown>; dataType: string; resolvedDataType: string } {
28
+ if (typeof value === 'object' && 'aliasId' in value) {
29
+ return {
30
+ value: { alias: { guid: stringToGuid(value.aliasId) } },
31
+ dataType: 'ALIAS',
32
+ resolvedDataType: { COLOR: 'COLOR', BOOLEAN: 'BOOLEAN', STRING: 'STRING' }[type] ?? 'FLOAT'
33
+ }
34
+ }
35
+ if (type === 'COLOR' && typeof value === 'object' && 'r' in value) {
36
+ return {
37
+ value: { colorValue: { r: value.r, g: value.g, b: value.b, a: value.a } },
38
+ dataType: 'COLOR',
39
+ resolvedDataType: 'COLOR'
40
+ }
41
+ }
42
+ if (type === 'BOOLEAN') {
43
+ return { value: { boolValue: !!value }, dataType: 'BOOLEAN', resolvedDataType: 'BOOLEAN' }
44
+ }
45
+ if (type === 'STRING') {
46
+ return {
47
+ value: { textValue: typeof value === 'string' ? value : JSON.stringify(value) },
48
+ dataType: 'STRING',
49
+ resolvedDataType: 'STRING'
50
+ }
51
+ }
52
+ return { value: { floatValue: Number(value) }, dataType: 'FLOAT', resolvedDataType: 'FLOAT' }
53
+ }
54
+
55
+ function collectImageEntries(graph: SceneGraph): Array<{ name: string; data: Uint8Array }> {
56
+ const entries: Array<{ name: string; data: Uint8Array }> = []
57
+ for (const [hash, data] of graph.images) {
58
+ entries.push({ name: `images/${hash}`, data })
59
+ }
60
+ return entries
61
+ }
62
+
63
+ const THUMBNAIL_WIDTH = 400
64
+ const THUMBNAIL_HEIGHT = 225
65
+
66
+ export async function exportFigFile(
67
+ graph: SceneGraph,
68
+ ck?: CanvasKit,
69
+ renderer?: SkiaRenderer,
70
+ pageId?: string
71
+ ): Promise<Uint8Array> {
72
+ await initCodec()
73
+ const compiled = getCompiledSchema()
74
+ const schemaDeflated = deflateSync(getSchemaBytes())
75
+
76
+ const docGuid = { sessionID: 0, localID: 0 }
77
+ const localIdCounter = { value: 2 }
78
+
79
+ const nodeChanges: KiwiNodeChange[] = [
80
+ {
81
+ guid: docGuid,
82
+ type: 'DOCUMENT',
83
+ name: 'Document',
84
+ visible: true,
85
+ opacity: 1,
86
+ phase: 'CREATED',
87
+ transform: { m00: 1, m01: 0, m02: 0, m10: 0, m11: 1, m12: 0 },
88
+ strokeWeight: 1,
89
+ strokeAlign: 'CENTER',
90
+ strokeJoin: 'MITER',
91
+ documentColorProfile: 'SRGB'
92
+ }
93
+ ]
94
+
95
+ const blobs: Uint8Array[] = []
96
+ const pages = graph.getPages(true)
97
+ const nodeIdToGuid = new Map<string, GUID>()
98
+ const fontDigestMap = await buildFontDigestMap(graph)
99
+ let internalCanvasGuid: GUID | null = null
100
+
101
+ for (let p = 0; p < pages.length; p++) {
102
+ const page = pages[p]
103
+ const canvasLocalID = localIdCounter.value++
104
+ const canvasGuid = { sessionID: 0, localID: canvasLocalID }
105
+
106
+ if (page.internalOnly) internalCanvasGuid = canvasGuid
107
+
108
+ const canvasNc: KiwiNodeChange = {
109
+ guid: canvasGuid,
110
+ parentIndex: { guid: docGuid, position: fractionalPosition(p) },
111
+ type: 'CANVAS',
112
+ name: page.name,
113
+ visible: true,
114
+ opacity: 1,
115
+ phase: 'CREATED',
116
+ transform: { m00: 1, m01: 0, m02: 0, m10: 0, m11: 1, m12: 0 },
117
+ strokeWeight: 1,
118
+ strokeAlign: 'CENTER',
119
+ strokeJoin: 'MITER',
120
+ backgroundOpacity: 1,
121
+ backgroundColor: { ...CANVAS_BG_COLOR },
122
+ backgroundEnabled: true
123
+ }
124
+ if (page.internalOnly) canvasNc.internalOnly = true
125
+ nodeChanges.push(canvasNc)
126
+
127
+ const children = graph.getChildren(page.id)
128
+ for (let i = 0; i < children.length; i++) {
129
+ nodeChanges.push(
130
+ ...sceneNodeToKiwi(children[i], canvasGuid, i, localIdCounter, graph, blobs, nodeIdToGuid, fontDigestMap)
131
+ )
132
+ }
133
+ }
134
+
135
+ if (graph.variableCollections.size > 0) {
136
+ if (!internalCanvasGuid) {
137
+ const internalLocalID = localIdCounter.value++
138
+ internalCanvasGuid = { sessionID: 0, localID: internalLocalID }
139
+ nodeChanges.push({
140
+ guid: internalCanvasGuid,
141
+ parentIndex: { guid: docGuid, position: fractionalPosition(pages.length) },
142
+ type: 'CANVAS',
143
+ name: 'Internal Only Canvas',
144
+ visible: true,
145
+ opacity: 1,
146
+ phase: 'CREATED',
147
+ transform: { m00: 1, m01: 0, m02: 0, m10: 0, m11: 1, m12: 0 },
148
+ strokeWeight: 1,
149
+ strokeAlign: 'CENTER',
150
+ strokeJoin: 'MITER',
151
+ internalOnly: true
152
+ })
153
+ }
154
+
155
+ let collIdx = 0
156
+ for (const [colId, col] of graph.variableCollections) {
157
+ const colGuid = stringToGuid(colId)
158
+ const colNc: KiwiNodeChange = {
159
+ guid: colGuid,
160
+ parentIndex: { guid: internalCanvasGuid, position: fractionalPosition(collIdx++) },
161
+ type: 'VARIABLE_SET',
162
+ name: col.name,
163
+ phase: 'CREATED',
164
+ strokeAlign: 'CENTER',
165
+ strokeJoin: 'BEVEL',
166
+ variableSetModes: col.modes.map((m, i) => ({
167
+ id: stringToGuid(m.modeId),
168
+ name: m.name,
169
+ sortPosition: fractionalPosition(i)
170
+ }))
171
+ }
172
+ nodeChanges.push(colNc)
173
+
174
+ let varIdx = 0
175
+ for (const varId of col.variableIds) {
176
+ const variable = graph.variables.get(varId)
177
+ if (!variable) continue
178
+
179
+ const varGuid = stringToGuid(varId)
180
+ const typeMap: Record<string, string> = { COLOR: 'COLOR', BOOLEAN: 'BOOLEAN', STRING: 'STRING' }
181
+ const resolvedType = typeMap[variable.type] ?? 'FLOAT'
182
+
183
+ const entries = Object.entries(variable.valuesByMode).map(([modeId, value]) => ({
184
+ modeID: stringToGuid(modeId),
185
+ variableData: variableValueToKiwi(value, variable.type)
186
+ }))
187
+
188
+ const varNc: KiwiNodeChange = {
189
+ guid: varGuid,
190
+ parentIndex: { guid: internalCanvasGuid, position: fractionalPosition(varIdx++) },
191
+ type: 'VARIABLE',
192
+ name: variable.name,
193
+ phase: 'CREATED',
194
+ strokeAlign: 'CENTER',
195
+ strokeJoin: 'BEVEL',
196
+ variableSetID: { guid: colGuid },
197
+ variableResolvedType: resolvedType,
198
+ variableDataValues: { entries },
199
+ variableScopes: ['ALL_SCOPES']
200
+ }
201
+ nodeChanges.push(varNc)
202
+ }
203
+ }
204
+ }
205
+
206
+ const msg: Record<string, unknown> = {
207
+ type: 'NODE_CHANGES',
208
+ sessionID: 0,
209
+ ackID: 0,
210
+ nodeChanges
211
+ }
212
+
213
+ if (blobs.length > 0) {
214
+ msg.blobs = blobs.map((bytes) => ({ bytes }))
215
+ }
216
+
217
+ const kiwiData = compiled.encodeMessage(msg)
218
+
219
+ const currentPageId = pageId ?? pages[0]?.id
220
+ const thumbnailPng =
221
+ (ck && renderer && currentPageId
222
+ ? renderThumbnail(ck, renderer, graph, currentPageId, THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT)
223
+ : null) ?? THUMBNAIL_1X1
224
+
225
+ const metaJson = JSON.stringify({
226
+ version: 1,
227
+ app: 'Lutris',
228
+ createdAt: new Date().toISOString()
229
+ })
230
+
231
+ const imageEntries = collectImageEntries(graph)
232
+
233
+ if (IS_TAURI) {
234
+ const { invoke } = await import('@tauri-apps/api/core')
235
+ return new Uint8Array(
236
+ await invoke<number[]>('build_fig_file', {
237
+ schemaDeflated: Array.from(schemaDeflated),
238
+ kiwiData: Array.from(kiwiData),
239
+ thumbnailPng: Array.from(thumbnailPng),
240
+ metaJson,
241
+ images: imageEntries.map(e => ({ name: e.name, data: Array.from(e.data) }))
242
+ })
243
+ )
244
+ }
245
+
246
+ return compressFigData(schemaDeflated, kiwiData, thumbnailPng, metaJson, imageEntries)
247
+ }
248
+
249
+ export function compressFigDataSync(
250
+ schemaDeflated: Uint8Array,
251
+ kiwiData: Uint8Array,
252
+ thumbnailPng: Uint8Array,
253
+ metaJson: string,
254
+ imageEntries: Array<{ name: string; data: Uint8Array }>
255
+ ): Uint8Array {
256
+ const canvasData = buildFigKiwi(schemaDeflated, kiwiData)
257
+ const zipEntries: Zippable = {
258
+ 'canvas.fig': [canvasData, { level: 0 }],
259
+ 'thumbnail.png': [thumbnailPng, { level: 0 }],
260
+ 'meta.json': new TextEncoder().encode(metaJson)
261
+ }
262
+ for (const entry of imageEntries) {
263
+ zipEntries[entry.name] = [entry.data, { level: 0 }]
264
+ }
265
+ return zipSync(zipEntries)
266
+ }
267
+
268
+ function canUseWorker(): boolean {
269
+ return typeof Worker !== 'undefined' && typeof window !== 'undefined'
270
+ }
271
+
272
+ function compressViaWorker(
273
+ schemaDeflated: Uint8Array,
274
+ kiwiData: Uint8Array,
275
+ thumbnailPng: Uint8Array,
276
+ metaJson: string,
277
+ imageEntries: Array<{ name: string; data: Uint8Array }>
278
+ ): Promise<Uint8Array> {
279
+ return new Promise((resolve, reject) => {
280
+ const worker = new Worker(new URL('./fig-export-worker.ts', import.meta.url), { type: 'module' })
281
+
282
+ worker.onmessage = (e: MessageEvent<Uint8Array>) => {
283
+ resolve(e.data)
284
+ worker.terminate()
285
+ }
286
+ worker.onerror = (err) => {
287
+ reject(new Error(err.message))
288
+ worker.terminate()
289
+ }
290
+
291
+ const imgCopies = imageEntries.map((e) => ({
292
+ name: e.name,
293
+ data: new Uint8Array(e.data)
294
+ }))
295
+
296
+ const transferables = [
297
+ schemaDeflated.buffer,
298
+ kiwiData.buffer,
299
+ thumbnailPng.buffer,
300
+ ...imgCopies.map((e) => e.data.buffer)
301
+ ]
302
+
303
+ worker.postMessage(
304
+ { schemaDeflated, kiwiData, thumbnailPng, metaJson, images: imgCopies },
305
+ transferables
306
+ )
307
+ })
308
+ }
309
+
310
+ export function compressFigData(
311
+ schemaDeflated: Uint8Array,
312
+ kiwiData: Uint8Array,
313
+ thumbnailPng: Uint8Array,
314
+ metaJson: string,
315
+ imageEntries: Array<{ name: string; data: Uint8Array }>
316
+ ): Promise<Uint8Array> {
317
+ if (canUseWorker()) {
318
+ return compressViaWorker(schemaDeflated, kiwiData, thumbnailPng, metaJson, imageEntries)
319
+ }
320
+ return Promise.resolve(compressFigDataSync(schemaDeflated, kiwiData, thumbnailPng, metaJson, imageEntries))
321
+ }