@snowcone-app/canvas 0.36.3 → 0.36.7

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 (33) hide show
  1. package/dist/{CanvasRenderer-BHBCxI-B.js → CanvasRenderer-CTN4j-uO.js} +2 -2
  2. package/dist/{CanvasRenderer-BHBCxI-B.js.map → CanvasRenderer-CTN4j-uO.js.map} +1 -1
  3. package/dist/{CanvasStateV1-BoG8ld4D.js → CanvasStateV1-DLE5d1-d.js} +2 -2
  4. package/dist/{CanvasStateV1-BoG8ld4D.js.map → CanvasStateV1-DLE5d1-d.js.map} +1 -1
  5. package/dist/{ContextualToolbars-TCO7dzu6.js → ContextualToolbars-CG5Gmv_i.js} +4 -4
  6. package/dist/{ContextualToolbars-TCO7dzu6.js.map → ContextualToolbars-CG5Gmv_i.js.map} +1 -1
  7. package/dist/{EditorCanvasImpl-Ba6Lj6yQ.js → EditorCanvasImpl-BeeY09cA.js} +5 -5
  8. package/dist/{EditorCanvasImpl-Ba6Lj6yQ.js.map → EditorCanvasImpl-BeeY09cA.js.map} +1 -1
  9. package/dist/{ExportManager-D1PAlOiE.js → ExportManager-CDX5_up8.js} +39 -7
  10. package/dist/{ExportManager-D1PAlOiE.js.map → ExportManager-CDX5_up8.js.map} +1 -1
  11. package/dist/{ImagePanel-Duh1AMdF.js → ImagePanel-DLxIDKV-.js} +131 -131
  12. package/dist/ImagePanel-DLxIDKV-.js.map +1 -0
  13. package/dist/{SnowconeCanvas-h8cfofsO.js → SnowconeCanvas-BaFR8QXs.js} +8 -8
  14. package/dist/{SnowconeCanvas-h8cfofsO.js.map → SnowconeCanvas-BaFR8QXs.js.map} +1 -1
  15. package/dist/advanced.mjs +8 -8
  16. package/dist/{custom-icons-DYIOjjXt.js → custom-icons-D51KIAfz.js} +2 -2
  17. package/dist/{custom-icons-DYIOjjXt.js.map → custom-icons-D51KIAfz.js.map} +1 -1
  18. package/dist/{embed-DWDEtP0_.js → embed-D9n0deJ3.js} +7 -7
  19. package/dist/{embed-DWDEtP0_.js.map → embed-D9n0deJ3.js.map} +1 -1
  20. package/dist/embed.mjs +5 -5
  21. package/dist/index.mjs +7 -7
  22. package/dist/internals.mjs +4 -4
  23. package/dist/{template-fields-jgE6czak.js → template-fields-D8uOutD4.js} +3 -3
  24. package/dist/{template-fields-jgE6czak.js.map → template-fields-D8uOutD4.js.map} +1 -1
  25. package/dist/{useCommands-D16Tq-B-.js → useCommands-CQi4Pyd2.js} +5 -5
  26. package/dist/{useCommands-D16Tq-B-.js.map → useCommands-CQi4Pyd2.js.map} +1 -1
  27. package/dist/{validation-8QF2gWih.js → validation-THw5W6N_.js} +9 -9
  28. package/dist/{validation-8QF2gWih.js.map → validation-THw5W6N_.js.map} +1 -1
  29. package/dist/workers/export-protocol.d.ts +9 -2
  30. package/dist/workers/export-worker.bundle.string.d.ts +1 -1
  31. package/example/package.json +1 -1
  32. package/package.json +4 -4
  33. package/dist/ImagePanel-Duh1AMdF.js.map +0 -1
@@ -1,11 +1,11 @@
1
1
  import { jsx as m, jsxs as R, Fragment as $ } from "react/jsx-runtime";
2
2
  import { forwardRef as j, useContext as b, useSyncExternalStore as D, useMemo as G, useRef as y, useLayoutEffect as I } from "react";
3
- import { S as N } from "./SnowconeCanvas-h8cfofsO.js";
4
- import { d as U } from "./ContextualToolbars-TCO7dzu6.js";
3
+ import { S as N } from "./SnowconeCanvas-BaFR8QXs.js";
4
+ import { d as U } from "./ContextualToolbars-CG5Gmv_i.js";
5
5
  import { s as V, e as k, c as q } from "./design-builder-CqgTpp9B.js";
6
- import { u as z } from "./embed-DWDEtP0_.js";
6
+ import { u as z } from "./embed-D9n0deJ3.js";
7
7
  import { T as L } from "./FontAnalyzer-CEYA_6fY.js";
8
- import { q as h } from "./useCommands-D16Tq-B-.js";
8
+ import { q as h } from "./useCommands-CQi4Pyd2.js";
9
9
  const O = () => () => {
10
10
  };
11
11
  function P() {
@@ -78,4 +78,4 @@ const ee = j(
78
78
  export {
79
79
  ee as EditorCanvasImpl
80
80
  };
81
- //# sourceMappingURL=EditorCanvasImpl-Ba6Lj6yQ.js.map
81
+ //# sourceMappingURL=EditorCanvasImpl-BeeY09cA.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"EditorCanvasImpl-Ba6Lj6yQ.js","sources":["../src/components/editor/EditorCanvasImpl.tsx"],"sourcesContent":["'use client';\n\n/**\n * The heavy half of `Editor.Canvas` (and of the legacy `<RealtimeCanvas>`),\n * extracted from RealtimeCanvas's body. This module statically imports\n * `SnowconeCanvas` — i.e. the full rendering engine — and is therefore ONLY\n * ever reached through a dynamic `import()` (D9): the embed entry's static\n * import graph stays renderer-free, mechanically enforced by the\n * import-graph CI check.\n *\n * Beyond the original wiring (seed → SnowconeCanvas, edit →\n * `serializeStateForServer` → `pushRender`), this adds the ADR-0085 §3 store\n * wiring: every canvas change lands in the Root's {@link DesignStateStore}\n * (the ONE live design state), and a {@link CanvasBridge} is registered so\n * `Editor.TextField` writes route through the editor command path (undo/redo,\n * repaint) while a canvas is mounted — the editor document stays the single\n * write authority.\n */\n\nimport React, {\n forwardRef,\n useContext,\n useLayoutEffect,\n useMemo,\n useRef,\n useSyncExternalStore,\n type CSSProperties,\n type ReactNode,\n} from 'react';\nimport { SnowconeCanvas } from '../embed/SnowconeCanvas.js';\nimport { ContextualToolbars } from '../ContextualToolbars.js';\nimport type { CanvasState, SnowconeCanvasHandle } from '../embed/SnowconeCanvas.js';\nimport { serializeStateForServer } from '../../rendering/serialize-for-server.js';\nimport type { KitPresetId, KitDefinition } from '../../kits/types.js';\nimport type { CanvasServices } from '../../contexts/CanvasServicesContext.js';\nimport { useEmbedContext } from '../embed-realtime/context.js';\nimport { useElementsContext } from '../../contexts/ElementsContext.js';\nimport { useCommandContext } from '../../contexts/CommandContext.js';\nimport { TextElement } from '../../core/TextElement.js';\nimport { EditorRootInternalsContext } from './RootInternals.js';\n\nexport interface EditorCanvasImplProps {\n /** Your controls (toolbar, inputs). Rendered as an overlay inside the editor\n * context so binding hooks work. */\n children?: ReactNode;\n /** Editor chrome preset. `Editor.Canvas` pins the chrome-less `'embed-only'`;\n * the legacy `<RealtimeCanvas kit>` prop passes richer presets through. */\n kit?: KitPresetId | KitDefinition;\n /** Inherit the host app's theme instead of managing its own (default true). */\n inheritTheme?: boolean;\n /** Cap the canvas height in px. */\n maxHeight?: number;\n /** Privileged-service wiring override (usually inherited from Root). */\n services?: CanvasServices;\n /** Observe the live design state (the same {@link CanvasState} the Root's\n * state store tracks). Safe to pass inline — read through a ref. */\n onChange?: (state: CanvasState) => void;\n /** Whether the wrapping div self-applies `.sc-root`. The legacy\n * `<RealtimeCanvas>` always did (it could be the only Snowcone DOM on the\n * page); under `Editor.Root` the Root applies it once and parts never\n * self-apply (ADR-0085). Re-applying is harmless (same variables), so the\n * legacy wrapper keeps `true` for bit-identical back-compat. */\n selfScope?: boolean;\n /** `data-sc-part` value for the wrapping div (the parts contract). */\n partAttr?: string;\n /** Mount the built-in floating contextual toolbar (ADR-0085 §5: with no\n * `Editor.Controls` mounted, `Editor.Canvas` defaults to the floating\n * toolbar; a registered DOCKED Controls suppresses it). Set by\n * `Editor.Canvas` only — the legacy `<RealtimeCanvas>` wrapper keeps\n * today's chrome-less behavior. @internal */\n builtinControls?: boolean;\n className?: string;\n style?: CSSProperties;\n}\n\nconst noopSubscribe = (): (() => void) => () => {};\n\n/**\n * Runs INSIDE the canvas's editor context (the overlay slot) and registers\n * the imperative bridge sibling parts use to edit by layer name through the\n * command path. Generalizes `useTextBinding`'s write mechanics to a dynamic\n * name (a hook can't take names at call time).\n */\nfunction CanvasBindingBridge(): null {\n const { elementStore } = useElementsContext();\n const { executeElementUpdate } = useCommandContext();\n // Tolerant on purpose: the legacy <RealtimeCanvas> is supported inside a\n // bare EmbedContext (advanced consumers provide their own); only under an\n // <Editor.Root> is there a registry to bridge into.\n const internals = useContext(EditorRootInternalsContext);\n\n const latest = useRef({ elementStore, executeElementUpdate });\n latest.current = { elementStore, executeElementUpdate };\n\n const registry = internals?.registry ?? null;\n useLayoutEffect(() => {\n if (!registry) return;\n return registry.registerCanvasBridge({\n setTextByName(name: string, text: string): boolean {\n const { elementStore: store, executeElementUpdate: execute } = latest.current;\n const matches = store.getAllByName(name).filter((el): el is TextElement => el instanceof TextElement);\n if (matches.length === 0) return false;\n for (const el of matches) {\n const cloned = el.clone() as TextElement;\n cloned.setText(text);\n execute(el, cloned);\n }\n return true;\n },\n });\n }, [registry]);\n\n return null;\n}\n\nexport const EditorCanvasImpl = forwardRef<SnowconeCanvasHandle, EditorCanvasImplProps>(\n function EditorCanvasImpl(\n {\n children,\n kit = 'embed-only',\n inheritTheme = true,\n maxHeight,\n services,\n onChange,\n selfScope = false,\n partAttr,\n builtinControls = false,\n className,\n style,\n }: EditorCanvasImplProps,\n ref,\n ): React.ReactElement {\n const { placement, throttleMs, pieceGuides, pushRender, stateStore } = useEmbedContext();\n\n // Under an <Editor.Root> the editor document is mounted by the ROOT (P1\n // provider inversion, D9: state always) — SnowconeCanvas must write into\n // that document instead of mounting its own, and a REMOUNT of this part\n // must rebuild the (surviving) document from the live seed instead of\n // accreting onto the previous mount's artboards/elements. The legacy\n // <RealtimeCanvas> inside a bare EmbedContext (no Root) keeps mounting\n // its own provider, exactly as before.\n const rootInternals = useContext(EditorRootInternalsContext);\n const underRoot = rootInternals !== null;\n\n // ADR-0085 §5 (Controls placement resolution): with no Editor.Controls\n // mounted — or a `placement=\"floating\"` one — the canvas owns the\n // floating contextual toolbar; a registered DOCKED Controls suppresses\n // it. Subscribed to the part registry so the zones swap live when a\n // docked Controls mounts/unmounts.\n const partsRegistry = rootInternals?.registry ?? null;\n useSyncExternalStore(\n partsRegistry ? partsRegistry.subscribe : noopSubscribe,\n partsRegistry ? partsRegistry.getVersion : () => 0,\n partsRegistry ? partsRegistry.getVersion : () => 0,\n );\n const showBuiltinFloatingControls =\n builtinControls && underRoot && !(partsRegistry?.hasDockedControls() ?? false);\n\n // Seed from the LIVE store, not the original design (ADR-0085 §3): the\n // store starts as design.toJSON(), so a fresh mount is identical to the\n // old behavior — but edits made while this chunk was loading (e.g. a\n // TextField keystroke in the first second) survive instead of being\n // clobbered by a stale seed. Captured once per store identity; later\n // store changes flow through the editor document, not re-seeding.\n const seed = useMemo(() => stateStore.getState(), [stateStore]);\n\n // Latest-ref so a host's inline `onChange` identity never matters here\n // (SnowconeCanvas already refs ITS callback; this keeps ours symmetric).\n const onChangeRef = useRef(onChange);\n onChangeRef.current = onChange;\n\n const rootClass = selfScope ? 'sc-root' : 'sc-canvas-frame';\n\n return (\n <div className={`${rootClass}${className ? ` ${className}` : ''}`} style={style} data-sc-part={partAttr}>\n <SnowconeCanvas\n ref={ref}\n kit={kit}\n inheritTheme={inheritTheme}\n services={services}\n externalProvider={underRoot}\n resetDocumentOnMount={underRoot}\n artboards={seed.artboards}\n activeArtboard={placement}\n initialElements={seed.elements}\n layoutConfig={maxHeight ? { maxHeight } : undefined}\n overlay={\n <>\n <CanvasBindingBridge />\n {showBuiltinFloatingControls ? <ContextualToolbars mode=\"floating\" partAttr=\"controls\" /> : null}\n {children}\n </>\n }\n // #566: the product's printable-area / dead-zone overlay, fetched and\n // dims-gated by the Root — same overlay snowcone.app's editor\n // shows, so a buyer can't unknowingly edit under a camera cutout.\n pieceGuides={pieceGuides ?? undefined}\n onChange={(state) => {\n // ONE store, last-write-wins (ADR-0085 §3): the editor document is\n // the write authority while mounted; the Root store derives from\n // its onChange, then the render follows the store.\n stateStore.setState(state);\n pushRender(serializeStateForServer(state), throttleMs);\n onChangeRef.current?.(state);\n }}\n />\n </div>\n );\n },\n);\n\nexport type { CanvasState, SnowconeCanvasHandle };\n"],"names":["noopSubscribe","CanvasBindingBridge","elementStore","useElementsContext","executeElementUpdate","useCommandContext","internals","useContext","EditorRootInternalsContext","latest","useRef","registry","useLayoutEffect","name","text","store","execute","matches","el","TextElement","cloned","EditorCanvasImpl","forwardRef","children","kit","inheritTheme","maxHeight","services","onChange","selfScope","partAttr","builtinControls","className","style","ref","placement","throttleMs","pieceGuides","pushRender","stateStore","useEmbedContext","rootInternals","underRoot","partsRegistry","useSyncExternalStore","showBuiltinFloatingControls","seed","useMemo","onChangeRef","jsx","SnowconeCanvas","jsxs","Fragment","ContextualToolbars","state","serializeStateForServer","_a"],"mappings":"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"}
1
+ {"version":3,"file":"EditorCanvasImpl-BeeY09cA.js","sources":["../src/components/editor/EditorCanvasImpl.tsx"],"sourcesContent":["'use client';\n\n/**\n * The heavy half of `Editor.Canvas` (and of the legacy `<RealtimeCanvas>`),\n * extracted from RealtimeCanvas's body. This module statically imports\n * `SnowconeCanvas` — i.e. the full rendering engine — and is therefore ONLY\n * ever reached through a dynamic `import()` (D9): the embed entry's static\n * import graph stays renderer-free, mechanically enforced by the\n * import-graph CI check.\n *\n * Beyond the original wiring (seed → SnowconeCanvas, edit →\n * `serializeStateForServer` → `pushRender`), this adds the ADR-0085 §3 store\n * wiring: every canvas change lands in the Root's {@link DesignStateStore}\n * (the ONE live design state), and a {@link CanvasBridge} is registered so\n * `Editor.TextField` writes route through the editor command path (undo/redo,\n * repaint) while a canvas is mounted — the editor document stays the single\n * write authority.\n */\n\nimport React, {\n forwardRef,\n useContext,\n useLayoutEffect,\n useMemo,\n useRef,\n useSyncExternalStore,\n type CSSProperties,\n type ReactNode,\n} from 'react';\nimport { SnowconeCanvas } from '../embed/SnowconeCanvas.js';\nimport { ContextualToolbars } from '../ContextualToolbars.js';\nimport type { CanvasState, SnowconeCanvasHandle } from '../embed/SnowconeCanvas.js';\nimport { serializeStateForServer } from '../../rendering/serialize-for-server.js';\nimport type { KitPresetId, KitDefinition } from '../../kits/types.js';\nimport type { CanvasServices } from '../../contexts/CanvasServicesContext.js';\nimport { useEmbedContext } from '../embed-realtime/context.js';\nimport { useElementsContext } from '../../contexts/ElementsContext.js';\nimport { useCommandContext } from '../../contexts/CommandContext.js';\nimport { TextElement } from '../../core/TextElement.js';\nimport { EditorRootInternalsContext } from './RootInternals.js';\n\nexport interface EditorCanvasImplProps {\n /** Your controls (toolbar, inputs). Rendered as an overlay inside the editor\n * context so binding hooks work. */\n children?: ReactNode;\n /** Editor chrome preset. `Editor.Canvas` pins the chrome-less `'embed-only'`;\n * the legacy `<RealtimeCanvas kit>` prop passes richer presets through. */\n kit?: KitPresetId | KitDefinition;\n /** Inherit the host app's theme instead of managing its own (default true). */\n inheritTheme?: boolean;\n /** Cap the canvas height in px. */\n maxHeight?: number;\n /** Privileged-service wiring override (usually inherited from Root). */\n services?: CanvasServices;\n /** Observe the live design state (the same {@link CanvasState} the Root's\n * state store tracks). Safe to pass inline — read through a ref. */\n onChange?: (state: CanvasState) => void;\n /** Whether the wrapping div self-applies `.sc-root`. The legacy\n * `<RealtimeCanvas>` always did (it could be the only Snowcone DOM on the\n * page); under `Editor.Root` the Root applies it once and parts never\n * self-apply (ADR-0085). Re-applying is harmless (same variables), so the\n * legacy wrapper keeps `true` for bit-identical back-compat. */\n selfScope?: boolean;\n /** `data-sc-part` value for the wrapping div (the parts contract). */\n partAttr?: string;\n /** Mount the built-in floating contextual toolbar (ADR-0085 §5: with no\n * `Editor.Controls` mounted, `Editor.Canvas` defaults to the floating\n * toolbar; a registered DOCKED Controls suppresses it). Set by\n * `Editor.Canvas` only — the legacy `<RealtimeCanvas>` wrapper keeps\n * today's chrome-less behavior. @internal */\n builtinControls?: boolean;\n className?: string;\n style?: CSSProperties;\n}\n\nconst noopSubscribe = (): (() => void) => () => {};\n\n/**\n * Runs INSIDE the canvas's editor context (the overlay slot) and registers\n * the imperative bridge sibling parts use to edit by layer name through the\n * command path. Generalizes `useTextBinding`'s write mechanics to a dynamic\n * name (a hook can't take names at call time).\n */\nfunction CanvasBindingBridge(): null {\n const { elementStore } = useElementsContext();\n const { executeElementUpdate } = useCommandContext();\n // Tolerant on purpose: the legacy <RealtimeCanvas> is supported inside a\n // bare EmbedContext (advanced consumers provide their own); only under an\n // <Editor.Root> is there a registry to bridge into.\n const internals = useContext(EditorRootInternalsContext);\n\n const latest = useRef({ elementStore, executeElementUpdate });\n latest.current = { elementStore, executeElementUpdate };\n\n const registry = internals?.registry ?? null;\n useLayoutEffect(() => {\n if (!registry) return;\n return registry.registerCanvasBridge({\n setTextByName(name: string, text: string): boolean {\n const { elementStore: store, executeElementUpdate: execute } = latest.current;\n const matches = store.getAllByName(name).filter((el): el is TextElement => el instanceof TextElement);\n if (matches.length === 0) return false;\n for (const el of matches) {\n const cloned = el.clone() as TextElement;\n cloned.setText(text);\n execute(el, cloned);\n }\n return true;\n },\n });\n }, [registry]);\n\n return null;\n}\n\nexport const EditorCanvasImpl = forwardRef<SnowconeCanvasHandle, EditorCanvasImplProps>(\n function EditorCanvasImpl(\n {\n children,\n kit = 'embed-only',\n inheritTheme = true,\n maxHeight,\n services,\n onChange,\n selfScope = false,\n partAttr,\n builtinControls = false,\n className,\n style,\n }: EditorCanvasImplProps,\n ref,\n ): React.ReactElement {\n const { placement, throttleMs, pieceGuides, pushRender, stateStore } = useEmbedContext();\n\n // Under an <Editor.Root> the editor document is mounted by the ROOT (P1\n // provider inversion, D9: state always) — SnowconeCanvas must write into\n // that document instead of mounting its own, and a REMOUNT of this part\n // must rebuild the (surviving) document from the live seed instead of\n // accreting onto the previous mount's artboards/elements. The legacy\n // <RealtimeCanvas> inside a bare EmbedContext (no Root) keeps mounting\n // its own provider, exactly as before.\n const rootInternals = useContext(EditorRootInternalsContext);\n const underRoot = rootInternals !== null;\n\n // ADR-0085 §5 (Controls placement resolution): with no Editor.Controls\n // mounted — or a `placement=\"floating\"` one — the canvas owns the\n // floating contextual toolbar; a registered DOCKED Controls suppresses\n // it. Subscribed to the part registry so the zones swap live when a\n // docked Controls mounts/unmounts.\n const partsRegistry = rootInternals?.registry ?? null;\n useSyncExternalStore(\n partsRegistry ? partsRegistry.subscribe : noopSubscribe,\n partsRegistry ? partsRegistry.getVersion : () => 0,\n partsRegistry ? partsRegistry.getVersion : () => 0,\n );\n const showBuiltinFloatingControls =\n builtinControls && underRoot && !(partsRegistry?.hasDockedControls() ?? false);\n\n // Seed from the LIVE store, not the original design (ADR-0085 §3): the\n // store starts as design.toJSON(), so a fresh mount is identical to the\n // old behavior — but edits made while this chunk was loading (e.g. a\n // TextField keystroke in the first second) survive instead of being\n // clobbered by a stale seed. Captured once per store identity; later\n // store changes flow through the editor document, not re-seeding.\n const seed = useMemo(() => stateStore.getState(), [stateStore]);\n\n // Latest-ref so a host's inline `onChange` identity never matters here\n // (SnowconeCanvas already refs ITS callback; this keeps ours symmetric).\n const onChangeRef = useRef(onChange);\n onChangeRef.current = onChange;\n\n const rootClass = selfScope ? 'sc-root' : 'sc-canvas-frame';\n\n return (\n <div className={`${rootClass}${className ? ` ${className}` : ''}`} style={style} data-sc-part={partAttr}>\n <SnowconeCanvas\n ref={ref}\n kit={kit}\n inheritTheme={inheritTheme}\n services={services}\n externalProvider={underRoot}\n resetDocumentOnMount={underRoot}\n artboards={seed.artboards}\n activeArtboard={placement}\n initialElements={seed.elements}\n layoutConfig={maxHeight ? { maxHeight } : undefined}\n overlay={\n <>\n <CanvasBindingBridge />\n {showBuiltinFloatingControls ? <ContextualToolbars mode=\"floating\" partAttr=\"controls\" /> : null}\n {children}\n </>\n }\n // #566: the product's printable-area / dead-zone overlay, fetched and\n // dims-gated by the Root — same overlay snowcone.app's editor\n // shows, so a buyer can't unknowingly edit under a camera cutout.\n pieceGuides={pieceGuides ?? undefined}\n onChange={(state) => {\n // ONE store, last-write-wins (ADR-0085 §3): the editor document is\n // the write authority while mounted; the Root store derives from\n // its onChange, then the render follows the store.\n stateStore.setState(state);\n pushRender(serializeStateForServer(state), throttleMs);\n onChangeRef.current?.(state);\n }}\n />\n </div>\n );\n },\n);\n\nexport type { CanvasState, SnowconeCanvasHandle };\n"],"names":["noopSubscribe","CanvasBindingBridge","elementStore","useElementsContext","executeElementUpdate","useCommandContext","internals","useContext","EditorRootInternalsContext","latest","useRef","registry","useLayoutEffect","name","text","store","execute","matches","el","TextElement","cloned","EditorCanvasImpl","forwardRef","children","kit","inheritTheme","maxHeight","services","onChange","selfScope","partAttr","builtinControls","className","style","ref","placement","throttleMs","pieceGuides","pushRender","stateStore","useEmbedContext","rootInternals","underRoot","partsRegistry","useSyncExternalStore","showBuiltinFloatingControls","seed","useMemo","onChangeRef","jsx","SnowconeCanvas","jsxs","Fragment","ContextualToolbars","state","serializeStateForServer","_a"],"mappings":"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"}
@@ -26397,16 +26397,20 @@ const Ma = `"use strict";
26397
26397
  returnFormat = "dataUrl"
26398
26398
  } = request;
26399
26399
  try {
26400
+ const fontStartTime = performance.now();
26400
26401
  if (fonts && fonts.length > 0) {
26401
26402
  await loadFonts(fonts, customFonts);
26402
26403
  }
26403
- const width = artboardData.width * scale;
26404
- const height = artboardData.height * scale;
26404
+ const fontTime = performance.now() - fontStartTime;
26405
+ const width = Math.round(artboardData.width * scale);
26406
+ const height = Math.round(artboardData.height * scale);
26405
26407
  const canvas = new OffscreenCanvas(width, height);
26406
26408
  const ctx = canvas.getContext("2d");
26407
26409
  if (!ctx) {
26408
26410
  throw new Error("Failed to get 2D context from OffscreenCanvas");
26409
26411
  }
26412
+ ctx.imageSmoothingEnabled = true;
26413
+ ctx.imageSmoothingQuality = "high";
26410
26414
  if (scale !== 1) {
26411
26415
  ctx.scale(scale, scale);
26412
26416
  }
@@ -26434,14 +26438,36 @@ const Ma = `"use strict";
26434
26438
  }
26435
26439
  const renderEndTime = performance.now();
26436
26440
  const renderTime = renderEndTime - renderStartTime;
26441
+ if (format === "raw" && returnFormat === "blob") {
26442
+ const blobStartTime2 = performance.now();
26443
+ const imageData = ctx.getImageData(0, 0, width, height);
26444
+ const blobTime2 = performance.now() - blobStartTime2;
26445
+ const totalTime = performance.now() - startTime;
26446
+ const response = {
26447
+ type: "exportBlobComplete",
26448
+ requestId,
26449
+ artboardId: artboardData.id,
26450
+ artboardName: artboardData.name,
26451
+ blobData: imageData.data.buffer,
26452
+ mimeType: "application/x-raw-rgba",
26453
+ rawWidth: width,
26454
+ rawHeight: height,
26455
+ renderTime,
26456
+ totalTime,
26457
+ fontTime,
26458
+ blobTime: blobTime2
26459
+ };
26460
+ self.postMessage(response, { transfer: [imageData.data.buffer] });
26461
+ return;
26462
+ }
26437
26463
  const blobStartTime = performance.now();
26438
26464
  const mimeType = format === "png" ? "image/png" : format === "webp" ? "image/webp" : "image/jpeg";
26439
26465
  const blob = await canvas.convertToBlob({
26440
26466
  type: mimeType,
26441
- quality: format !== "png" ? quality : void 0
26467
+ quality: format !== "png" && format !== "raw" ? quality : void 0
26442
26468
  });
26443
26469
  const blobEndTime = performance.now();
26444
- void (blobEndTime - blobStartTime);
26470
+ const blobTime = blobEndTime - blobStartTime;
26445
26471
  if (returnFormat === "blob") {
26446
26472
  const arrayBuffer = await blob.arrayBuffer();
26447
26473
  const endTime = performance.now();
@@ -26454,7 +26480,9 @@ const Ma = `"use strict";
26454
26480
  blobData: arrayBuffer,
26455
26481
  mimeType,
26456
26482
  renderTime,
26457
- totalTime
26483
+ totalTime,
26484
+ fontTime,
26485
+ blobTime
26458
26486
  };
26459
26487
  self.postMessage(response, { transfer: [arrayBuffer] });
26460
26488
  } else {
@@ -26468,7 +26496,9 @@ const Ma = `"use strict";
26468
26496
  artboardName: artboardData.name,
26469
26497
  dataUrl,
26470
26498
  renderTime,
26471
- totalTime
26499
+ totalTime,
26500
+ fontTime,
26501
+ blobTime
26472
26502
  };
26473
26503
  self.postMessage(response);
26474
26504
  }
@@ -26741,6 +26771,8 @@ const Ma = `"use strict";
26741
26771
  if (offWidth <= 0 || offHeight <= 0) return;
26742
26772
  const offCanvas = new OffscreenCanvas(offWidth, offHeight);
26743
26773
  const offCtx = offCanvas.getContext("2d");
26774
+ offCtx.imageSmoothingEnabled = true;
26775
+ offCtx.imageSmoothingQuality = "high";
26744
26776
  offCtx.drawImage(
26745
26777
  ctx.canvas,
26746
26778
  pixelX,
@@ -27937,4 +27969,4 @@ export {
27937
27969
  St as y,
27938
27970
  qa as z
27939
27971
  };
27940
- //# sourceMappingURL=ExportManager-D1PAlOiE.js.map
27972
+ //# sourceMappingURL=ExportManager-CDX5_up8.js.map