@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.
- package/dist/canvaskit.d.ts +9 -0
- package/dist/canvaskit.d.ts.map +1 -0
- package/dist/canvaskit.js +55 -0
- package/dist/canvaskit.js.map +1 -0
- package/dist/clipboard.d.ts +32 -0
- package/dist/clipboard.d.ts.map +1 -0
- package/dist/clipboard.js +345 -0
- package/dist/clipboard.js.map +1 -0
- package/dist/color.d.ts +28 -0
- package/dist/color.d.ts.map +1 -0
- package/dist/color.js +67 -0
- package/dist/color.js.map +1 -0
- package/dist/constants.d.ts +159 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +224 -0
- package/dist/constants.js.map +1 -0
- package/dist/copy.d.ts +20 -0
- package/dist/copy.d.ts.map +1 -0
- package/dist/copy.js +64 -0
- package/dist/copy.js.map +1 -0
- package/dist/fig-export-worker.d.ts +2 -0
- package/dist/fig-export-worker.d.ts.map +1 -0
- package/dist/fig-export-worker.js +17 -0
- package/dist/fig-export-worker.js.map +1 -0
- package/dist/fig-export.d.ts +13 -0
- package/dist/fig-export.d.ts.map +1 -0
- package/dist/fig-export.js +243 -0
- package/dist/fig-export.js.map +1 -0
- package/dist/figma-api.d.ts +268 -0
- package/dist/figma-api.d.ts.map +1 -0
- package/dist/figma-api.js +1074 -0
- package/dist/figma-api.js.map +1 -0
- package/dist/figma-rest-import.d.ts +122 -0
- package/dist/figma-rest-import.d.ts.map +1 -0
- package/dist/figma-rest-import.js +319 -0
- package/dist/figma-rest-import.js.map +1 -0
- package/dist/fonts.d.ts +24 -0
- package/dist/fonts.d.ts.map +1 -0
- package/dist/fonts.js +356 -0
- package/dist/fonts.js.map +1 -0
- package/dist/geometry.d.ts +14 -0
- package/dist/geometry.d.ts.map +1 -0
- package/dist/geometry.js +47 -0
- package/dist/geometry.js.map +1 -0
- package/dist/index.d.ts +38 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +32 -0
- package/dist/index.js.map +1 -0
- package/dist/kiwi/codec.d.ts +292 -0
- package/dist/kiwi/codec.d.ts.map +1 -0
- package/dist/kiwi/codec.js +340 -0
- package/dist/kiwi/codec.js.map +1 -0
- package/dist/kiwi/fig-file.d.ts +4 -0
- package/dist/kiwi/fig-file.d.ts.map +1 -0
- package/dist/kiwi/fig-file.js +236 -0
- package/dist/kiwi/fig-file.js.map +1 -0
- package/dist/kiwi/fig-import.d.ts +4 -0
- package/dist/kiwi/fig-import.d.ts.map +1 -0
- package/dist/kiwi/fig-import.js +248 -0
- package/dist/kiwi/fig-import.js.map +1 -0
- package/dist/kiwi/fig-parse-worker.d.ts +7 -0
- package/dist/kiwi/fig-parse-worker.d.ts.map +1 -0
- package/dist/kiwi/fig-parse-worker.js +184 -0
- package/dist/kiwi/fig-parse-worker.js.map +1 -0
- package/dist/kiwi/instance-overrides.d.ts +66 -0
- package/dist/kiwi/instance-overrides.d.ts.map +1 -0
- package/dist/kiwi/instance-overrides.js +644 -0
- package/dist/kiwi/instance-overrides.js.map +1 -0
- package/dist/kiwi/kiwi-convert.d.ts +19 -0
- package/dist/kiwi/kiwi-convert.d.ts.map +1 -0
- package/dist/kiwi/kiwi-convert.js +678 -0
- package/dist/kiwi/kiwi-convert.js.map +1 -0
- package/dist/kiwi/kiwi-schema/bb.d.ts +25 -0
- package/dist/kiwi/kiwi-schema/bb.d.ts.map +1 -0
- package/dist/kiwi/kiwi-schema/bb.js +225 -0
- package/dist/kiwi/kiwi-schema/bb.js.map +1 -0
- package/dist/kiwi/kiwi-schema/binary.d.ts +5 -0
- package/dist/kiwi/kiwi-schema/binary.d.ts.map +1 -0
- package/dist/kiwi/kiwi-schema/binary.js +86 -0
- package/dist/kiwi/kiwi-schema/binary.js.map +1 -0
- package/dist/kiwi/kiwi-schema/index.d.ts +6 -0
- package/dist/kiwi/kiwi-schema/index.d.ts.map +1 -0
- package/dist/kiwi/kiwi-schema/index.js +5 -0
- package/dist/kiwi/kiwi-schema/index.js.map +1 -0
- package/dist/kiwi/kiwi-schema/js.d.ts +4 -0
- package/dist/kiwi/kiwi-schema/js.d.ts.map +1 -0
- package/dist/kiwi/kiwi-schema/js.js +282 -0
- package/dist/kiwi/kiwi-schema/js.js.map +1 -0
- package/dist/kiwi/kiwi-schema/parser.d.ts +5 -0
- package/dist/kiwi/kiwi-schema/parser.d.ts.map +1 -0
- package/dist/kiwi/kiwi-schema/parser.js +228 -0
- package/dist/kiwi/kiwi-schema/parser.js.map +1 -0
- package/dist/kiwi/kiwi-schema/schema.d.ts +22 -0
- package/dist/kiwi/kiwi-schema/schema.d.ts.map +1 -0
- package/dist/kiwi/kiwi-schema/schema.js +2 -0
- package/dist/kiwi/kiwi-schema/schema.js.map +1 -0
- package/dist/kiwi/kiwi-schema/util.d.ts +3 -0
- package/dist/kiwi/kiwi-schema/util.d.ts.map +1 -0
- package/dist/kiwi/kiwi-schema/util.js +10 -0
- package/dist/kiwi/kiwi-schema/util.js.map +1 -0
- package/dist/kiwi/protocol.d.ts +172 -0
- package/dist/kiwi/protocol.d.ts.map +1 -0
- package/dist/kiwi/protocol.js +214 -0
- package/dist/kiwi/protocol.js.map +1 -0
- package/dist/kiwi/schema.d.ts +3 -0
- package/dist/kiwi/schema.d.ts.map +1 -0
- package/dist/kiwi/schema.js +2285 -0
- package/dist/kiwi/schema.js.map +1 -0
- package/dist/kiwi-serialize.d.ts +17 -0
- package/dist/kiwi-serialize.d.ts.map +1 -0
- package/dist/kiwi-serialize.js +419 -0
- package/dist/kiwi-serialize.js.map +1 -0
- package/dist/layout.d.ts +9 -0
- package/dist/layout.d.ts.map +1 -0
- package/dist/layout.js +533 -0
- package/dist/layout.js.map +1 -0
- package/dist/profiler/draw-call-counter.d.ts +9 -0
- package/dist/profiler/draw-call-counter.d.ts.map +1 -0
- package/dist/profiler/draw-call-counter.js +37 -0
- package/dist/profiler/draw-call-counter.js.map +1 -0
- package/dist/profiler/frame-capture.d.ts +34 -0
- package/dist/profiler/frame-capture.d.ts.map +1 -0
- package/dist/profiler/frame-capture.js +90 -0
- package/dist/profiler/frame-capture.js.map +1 -0
- package/dist/profiler/frame-stats.d.ts +33 -0
- package/dist/profiler/frame-stats.d.ts.map +1 -0
- package/dist/profiler/frame-stats.js +103 -0
- package/dist/profiler/frame-stats.js.map +1 -0
- package/dist/profiler/gpu-timer.d.ts +15 -0
- package/dist/profiler/gpu-timer.d.ts.map +1 -0
- package/dist/profiler/gpu-timer.js +77 -0
- package/dist/profiler/gpu-timer.js.map +1 -0
- package/dist/profiler/hud-renderer.d.ts +22 -0
- package/dist/profiler/hud-renderer.d.ts.map +1 -0
- package/dist/profiler/hud-renderer.js +200 -0
- package/dist/profiler/hud-renderer.js.map +1 -0
- package/dist/profiler/index.d.ts +9 -0
- package/dist/profiler/index.d.ts.map +1 -0
- package/dist/profiler/index.js +8 -0
- package/dist/profiler/index.js.map +1 -0
- package/dist/profiler/phase-timer.d.ts +9 -0
- package/dist/profiler/phase-timer.d.ts.map +1 -0
- package/dist/profiler/phase-timer.js +51 -0
- package/dist/profiler/phase-timer.js.map +1 -0
- package/dist/profiler/render-profiler.d.ts +41 -0
- package/dist/profiler/render-profiler.d.ts.map +1 -0
- package/dist/profiler/render-profiler.js +142 -0
- package/dist/profiler/render-profiler.js.map +1 -0
- package/dist/render/components.d.ts +25 -0
- package/dist/render/components.d.ts.map +1 -0
- package/dist/render/components.js +55 -0
- package/dist/render/components.js.map +1 -0
- package/dist/render/emoji-icons.d.ts +5 -0
- package/dist/render/emoji-icons.d.ts.map +1 -0
- package/dist/render/emoji-icons.js +55 -0
- package/dist/render/emoji-icons.js.map +1 -0
- package/dist/render/export-code.d.ts +9 -0
- package/dist/render/export-code.d.ts.map +1 -0
- package/dist/render/export-code.js +335 -0
- package/dist/render/export-code.js.map +1 -0
- package/dist/render/export-jsx.d.ts +5 -0
- package/dist/render/export-jsx.d.ts.map +1 -0
- package/dist/render/export-jsx.js +621 -0
- package/dist/render/export-jsx.js.map +1 -0
- package/dist/render/index.d.ts +8 -0
- package/dist/render/index.d.ts.map +1 -0
- package/dist/render/index.js +8 -0
- package/dist/render/index.js.map +1 -0
- package/dist/render/jsx-runtime.d.ts +31 -0
- package/dist/render/jsx-runtime.d.ts.map +1 -0
- package/dist/render/jsx-runtime.js +13 -0
- package/dist/render/jsx-runtime.js.map +1 -0
- package/dist/render/mini-react.d.ts +14 -0
- package/dist/render/mini-react.d.ts.map +1 -0
- package/dist/render/mini-react.js +16 -0
- package/dist/render/mini-react.js.map +1 -0
- package/dist/render/render-jsx.d.ts +24 -0
- package/dist/render/render-jsx.d.ts.map +1 -0
- package/dist/render/render-jsx.js +51 -0
- package/dist/render/render-jsx.js.map +1 -0
- package/dist/render/renderer.d.ts +16 -0
- package/dist/render/renderer.d.ts.map +1 -0
- package/dist/render/renderer.js +437 -0
- package/dist/render/renderer.js.map +1 -0
- package/dist/render/tailwind.d.ts +20 -0
- package/dist/render/tailwind.d.ts.map +1 -0
- package/dist/render/tailwind.js +115 -0
- package/dist/render/tailwind.js.map +1 -0
- package/dist/render/tree.d.ts +72 -0
- package/dist/render/tree.d.ts.map +1 -0
- package/dist/render/tree.js +63 -0
- package/dist/render/tree.js.map +1 -0
- package/dist/render-image.d.ts +19 -0
- package/dist/render-image.d.ts.map +1 -0
- package/dist/render-image.js +84 -0
- package/dist/render-image.js.map +1 -0
- package/dist/renderer/effects.d.ts +9 -0
- package/dist/renderer/effects.d.ts.map +1 -0
- package/dist/renderer/effects.js +44 -0
- package/dist/renderer/effects.js.map +1 -0
- package/dist/renderer/fills.d.ts +9 -0
- package/dist/renderer/fills.d.ts.map +1 -0
- package/dist/renderer/fills.js +189 -0
- package/dist/renderer/fills.js.map +1 -0
- package/dist/renderer/index.d.ts +2 -0
- package/dist/renderer/index.d.ts.map +1 -0
- package/dist/renderer/index.js +2 -0
- package/dist/renderer/index.js.map +1 -0
- package/dist/renderer/label-cache.d.ts +43 -0
- package/dist/renderer/label-cache.d.ts.map +1 -0
- package/dist/renderer/label-cache.js +85 -0
- package/dist/renderer/label-cache.js.map +1 -0
- package/dist/renderer/labels.d.ts +6 -0
- package/dist/renderer/labels.d.ts.map +1 -0
- package/dist/renderer/labels.js +126 -0
- package/dist/renderer/labels.js.map +1 -0
- package/dist/renderer/lru-cache.d.ts +20 -0
- package/dist/renderer/lru-cache.d.ts.map +1 -0
- package/dist/renderer/lru-cache.js +65 -0
- package/dist/renderer/lru-cache.js.map +1 -0
- package/dist/renderer/overlays.d.ts +25 -0
- package/dist/renderer/overlays.d.ts.map +1 -0
- package/dist/renderer/overlays.js +783 -0
- package/dist/renderer/overlays.js.map +1 -0
- package/dist/renderer/renderer.d.ts +229 -0
- package/dist/renderer/renderer.d.ts.map +1 -0
- package/dist/renderer/renderer.js +909 -0
- package/dist/renderer/renderer.js.map +1 -0
- package/dist/renderer/rulers.d.ts +8 -0
- package/dist/renderer/rulers.d.ts.map +1 -0
- package/dist/renderer/rulers.js +147 -0
- package/dist/renderer/rulers.js.map +1 -0
- package/dist/renderer/scene.d.ts +11 -0
- package/dist/renderer/scene.d.ts.map +1 -0
- package/dist/renderer/scene.js +392 -0
- package/dist/renderer/scene.js.map +1 -0
- package/dist/renderer/shapes.d.ts +13 -0
- package/dist/renderer/shapes.d.ts.map +1 -0
- package/dist/renderer/shapes.js +160 -0
- package/dist/renderer/shapes.js.map +1 -0
- package/dist/renderer/strokes.d.ts +9 -0
- package/dist/renderer/strokes.d.ts.map +1 -0
- package/dist/renderer/strokes.js +180 -0
- package/dist/renderer/strokes.js.map +1 -0
- package/dist/rpc/commands.d.ts +202 -0
- package/dist/rpc/commands.d.ts.map +1 -0
- package/dist/rpc/commands.js +429 -0
- package/dist/rpc/commands.js.map +1 -0
- package/dist/rpc/index.d.ts +3 -0
- package/dist/rpc/index.d.ts.map +1 -0
- package/dist/rpc/index.js +2 -0
- package/dist/rpc/index.js.map +1 -0
- package/dist/scene-graph.d.ts +318 -0
- package/dist/scene-graph.d.ts.map +1 -0
- package/dist/scene-graph.js +803 -0
- package/dist/scene-graph.js.map +1 -0
- package/dist/snap.d.ts +16 -0
- package/dist/snap.d.ts.map +1 -0
- package/dist/snap.js +97 -0
- package/dist/snap.js.map +1 -0
- package/dist/style-runs.d.ts +20 -0
- package/dist/style-runs.d.ts.map +1 -0
- package/dist/style-runs.js +168 -0
- package/dist/style-runs.js.map +1 -0
- package/dist/svg-export/defs.d.ts +19 -0
- package/dist/svg-export/defs.d.ts.map +1 -0
- package/dist/svg-export/defs.js +191 -0
- package/dist/svg-export/defs.js.map +1 -0
- package/dist/svg-export/index.d.ts +8 -0
- package/dist/svg-export/index.d.ts.map +1 -0
- package/dist/svg-export/index.js +318 -0
- package/dist/svg-export/index.js.map +1 -0
- package/dist/svg-export/paths.d.ts +9 -0
- package/dist/svg-export/paths.d.ts.map +1 -0
- package/dist/svg-export/paths.js +189 -0
- package/dist/svg-export/paths.js.map +1 -0
- package/dist/svg-node.d.ts +8 -0
- package/dist/svg-node.d.ts.map +1 -0
- package/dist/svg-node.js +48 -0
- package/dist/svg-node.js.map +1 -0
- package/dist/text-editor.d.ts +57 -0
- package/dist/text-editor.d.ts.map +1 -0
- package/dist/text-editor.js +337 -0
- package/dist/text-editor.js.map +1 -0
- package/dist/tools/ai-adapter.d.ts +22 -0
- package/dist/tools/ai-adapter.d.ts.map +1 -0
- package/dist/tools/ai-adapter.js +121 -0
- package/dist/tools/ai-adapter.js.map +1 -0
- package/dist/tools/analyze.d.ts +22 -0
- package/dist/tools/analyze.d.ts.map +1 -0
- package/dist/tools/analyze.js +677 -0
- package/dist/tools/analyze.js.map +1 -0
- package/dist/tools/create.d.ts +8 -0
- package/dist/tools/create.d.ts.map +1 -0
- package/dist/tools/create.js +204 -0
- package/dist/tools/create.js.map +1 -0
- package/dist/tools/describe.d.ts +9 -0
- package/dist/tools/describe.d.ts.map +1 -0
- package/dist/tools/describe.js +295 -0
- package/dist/tools/describe.js.map +1 -0
- package/dist/tools/export-code.d.ts +2 -0
- package/dist/tools/export-code.d.ts.map +1 -0
- package/dist/tools/export-code.js +34 -0
- package/dist/tools/export-code.js.map +1 -0
- package/dist/tools/export-tailwind-config.d.ts +27 -0
- package/dist/tools/export-tailwind-config.d.ts.map +1 -0
- package/dist/tools/export-tailwind-config.js +215 -0
- package/dist/tools/export-tailwind-config.js.map +1 -0
- package/dist/tools/icons.d.ts +5 -0
- package/dist/tools/icons.d.ts.map +1 -0
- package/dist/tools/icons.js +192 -0
- package/dist/tools/icons.js.map +1 -0
- package/dist/tools/index.d.ts +7 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +6 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/modify.d.ts +22 -0
- package/dist/tools/modify.d.ts.map +1 -0
- package/dist/tools/modify.js +653 -0
- package/dist/tools/modify.js.map +1 -0
- package/dist/tools/patterns.d.ts +2 -0
- package/dist/tools/patterns.d.ts.map +1 -0
- package/dist/tools/patterns.js +173 -0
- package/dist/tools/patterns.js.map +1 -0
- package/dist/tools/read.d.ts +17 -0
- package/dist/tools/read.d.ts.map +1 -0
- package/dist/tools/read.js +379 -0
- package/dist/tools/read.js.map +1 -0
- package/dist/tools/registry.d.ts +3 -0
- package/dist/tools/registry.d.ts.map +1 -0
- package/dist/tools/registry.js +124 -0
- package/dist/tools/registry.js.map +1 -0
- package/dist/tools/schema.d.ts +46 -0
- package/dist/tools/schema.d.ts.map +1 -0
- package/dist/tools/schema.js +17 -0
- package/dist/tools/schema.js.map +1 -0
- package/dist/tools/structure.d.ts +18 -0
- package/dist/tools/structure.d.ts.map +1 -0
- package/dist/tools/structure.js +345 -0
- package/dist/tools/structure.js.map +1 -0
- package/dist/tools/variables.d.ts +12 -0
- package/dist/tools/variables.d.ts.map +1 -0
- package/dist/tools/variables.js +190 -0
- package/dist/tools/variables.js.map +1 -0
- package/dist/tools/vector.d.ts +15 -0
- package/dist/tools/vector.d.ts.map +1 -0
- package/dist/tools/vector.js +312 -0
- package/dist/tools/vector.js.map +1 -0
- package/dist/types.d.ts +29 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/undo.d.ts +33 -0
- package/dist/undo.d.ts.map +1 -0
- package/dist/undo.js +98 -0
- package/dist/undo.js.map +1 -0
- package/dist/vector.d.ts +14 -0
- package/dist/vector.d.ts.map +1 -0
- package/dist/vector.js +334 -0
- package/dist/vector.js.map +1 -0
- package/dist/xpath.d.ts +8 -0
- package/dist/xpath.d.ts.map +1 -0
- package/dist/xpath.js +199 -0
- package/dist/xpath.js.map +1 -0
- package/package.json +54 -0
- package/src/canvaskit.ts +66 -0
- package/src/clipboard.ts +444 -0
- package/src/color.ts +83 -0
- package/src/constants.ts +277 -0
- package/src/copy.ts +75 -0
- package/src/fig-export-worker.ts +28 -0
- package/src/fig-export.ts +321 -0
- package/src/figma-api.ts +1297 -0
- package/src/figma-rest-import.ts +443 -0
- package/src/fonts.ts +369 -0
- package/src/geometry.ts +73 -0
- package/src/global.d.ts +20 -0
- package/src/index.ts +247 -0
- package/src/kiwi/codec.ts +614 -0
- package/src/kiwi/fig-file.ts +248 -0
- package/src/kiwi/fig-import.ts +300 -0
- package/src/kiwi/fig-parse-worker.ts +213 -0
- package/src/kiwi/instance-overrides.ts +682 -0
- package/src/kiwi/kiwi-convert.ts +771 -0
- package/src/kiwi/kiwi-schema/bb.ts +244 -0
- package/src/kiwi/kiwi-schema/binary.ts +102 -0
- package/src/kiwi/kiwi-schema/index.ts +5 -0
- package/src/kiwi/kiwi-schema/js.ts +339 -0
- package/src/kiwi/kiwi-schema/parser.ts +287 -0
- package/src/kiwi/kiwi-schema/schema.ts +24 -0
- package/src/kiwi/kiwi-schema/util.ts +10 -0
- package/src/kiwi/protocol.ts +237 -0
- package/src/kiwi/schema.ts +2286 -0
- package/src/kiwi-serialize.ts +467 -0
- package/src/layout.ts +608 -0
- package/src/profiler/draw-call-counter.ts +43 -0
- package/src/profiler/frame-capture.ts +139 -0
- package/src/profiler/frame-stats.ts +122 -0
- package/src/profiler/gpu-timer.ts +93 -0
- package/src/profiler/hud-renderer.ts +242 -0
- package/src/profiler/index.ts +8 -0
- package/src/profiler/phase-timer.ts +62 -0
- package/src/profiler/render-profiler.ts +163 -0
- package/src/render/components.ts +69 -0
- package/src/render/emoji-icons.ts +60 -0
- package/src/render/export-code.ts +366 -0
- package/src/render/export-jsx.ts +633 -0
- package/src/render/index.ts +38 -0
- package/src/render/jsx-runtime.ts +36 -0
- package/src/render/mini-react.ts +30 -0
- package/src/render/render-jsx.ts +74 -0
- package/src/render/renderer.ts +508 -0
- package/src/render/tailwind.ts +114 -0
- package/src/render/tree.ts +137 -0
- package/src/render-image.ts +139 -0
- package/src/renderer/effects.ts +64 -0
- package/src/renderer/fills.ts +248 -0
- package/src/renderer/index.ts +1 -0
- package/src/renderer/label-cache.ts +114 -0
- package/src/renderer/labels.ts +168 -0
- package/src/renderer/lru-cache.ts +71 -0
- package/src/renderer/overlays.ts +1089 -0
- package/src/renderer/renderer.ts +1226 -0
- package/src/renderer/rulers.ts +230 -0
- package/src/renderer/scene.ts +554 -0
- package/src/renderer/shapes.ts +193 -0
- package/src/renderer/strokes.ts +221 -0
- package/src/rpc/commands.ts +667 -0
- package/src/rpc/index.ts +25 -0
- package/src/scene-graph.ts +1254 -0
- package/src/snap.ts +122 -0
- package/src/style-runs.ts +234 -0
- package/src/svg-export/defs.ts +255 -0
- package/src/svg-export/index.ts +427 -0
- package/src/svg-export/paths.ts +212 -0
- package/src/svg-node.ts +62 -0
- package/src/text-editor.ts +349 -0
- package/src/tools/ai-adapter.ts +144 -0
- package/src/tools/analyze.ts +786 -0
- package/src/tools/create.ts +206 -0
- package/src/tools/describe.ts +280 -0
- package/src/tools/export-code.ts +41 -0
- package/src/tools/export-tailwind-config.ts +266 -0
- package/src/tools/icons.ts +213 -0
- package/src/tools/index.ts +6 -0
- package/src/tools/modify.ts +651 -0
- package/src/tools/patterns.ts +189 -0
- package/src/tools/read.ts +401 -0
- package/src/tools/registry.ts +155 -0
- package/src/tools/schema.ts +65 -0
- package/src/tools/structure.ts +348 -0
- package/src/tools/variables.ts +193 -0
- package/src/tools/vector.ts +311 -0
- package/src/types.ts +32 -0
- package/src/undo.ts +126 -0
- package/src/vector.ts +413 -0
- package/src/xpath.ts +259 -0
package/src/constants.ts
ADDED
|
@@ -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
|
+
}
|