@snowcone-app/canvas 0.27.0 → 0.28.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 (61) hide show
  1. package/ERROR_CONTRACT.md +13 -0
  2. package/dist/{CanvasRenderer-yszzrDfo.js → CanvasRenderer-B_3GISlW.js} +1124 -1068
  3. package/dist/CanvasRenderer-B_3GISlW.js.map +1 -0
  4. package/dist/{CanvasStateV1-BTbCD_xC.js → CanvasStateV1-kL09wsAn.js} +3 -3
  5. package/dist/{CanvasStateV1-BTbCD_xC.js.map → CanvasStateV1-kL09wsAn.js.map} +1 -1
  6. package/dist/ContextualToolbars-C69oYLdw.js +5771 -0
  7. package/dist/ContextualToolbars-C69oYLdw.js.map +1 -0
  8. package/dist/{EditorCanvasImpl-Ui8Ceb-h.js → EditorCanvasImpl-CrI9C_xM.js} +8 -8
  9. package/dist/{EditorCanvasImpl-Ui8Ceb-h.js.map → EditorCanvasImpl-CrI9C_xM.js.map} +1 -1
  10. package/dist/{ExportManager-BTcyj4cf.js → ExportManager-J2xK86uq.js} +12 -16
  11. package/dist/ExportManager-J2xK86uq.js.map +1 -0
  12. package/dist/{FontAnalyzer-EF3gLPr8.js → FontAnalyzer-PE6nysqE.js} +658 -639
  13. package/dist/FontAnalyzer-PE6nysqE.js.map +1 -0
  14. package/dist/{ImagePanel-CIk6z41z.js → ImagePanel-CmQCxBGm.js} +6 -6
  15. package/dist/{ImagePanel-CIk6z41z.js.map → ImagePanel-CmQCxBGm.js.map} +1 -1
  16. package/dist/{SnowconeCanvas-DuWALOAt.js → SnowconeCanvas-CQiFVR0X.js} +10 -10
  17. package/dist/{SnowconeCanvas-DuWALOAt.js.map → SnowconeCanvas-CQiFVR0X.js.map} +1 -1
  18. package/dist/{UnifiedFontService-CHVYDBDW.js → UnifiedFontService-BJzoqfBF.js} +755 -713
  19. package/dist/UnifiedFontService-BJzoqfBF.js.map +1 -0
  20. package/dist/advanced.mjs +14 -14
  21. package/dist/components/MultiSelectionToolbar.d.ts +18 -0
  22. package/dist/components/ui/toolbar-button.d.ts +2 -0
  23. package/dist/core/GestureConstraints.d.ts +92 -0
  24. package/dist/core/InteractionStateMachine.d.ts +16 -2
  25. package/dist/core/ResizeHandler.d.ts +4 -1
  26. package/dist/core/ResizePipeline.d.ts +3 -0
  27. package/dist/{custom-icons-CcLMyybv.js → custom-icons-BWiUGqD6.js} +2 -2
  28. package/dist/{custom-icons-CcLMyybv.js.map → custom-icons-BWiUGqD6.js.map} +1 -1
  29. package/dist/{design-builder-cZY958Rw.js → design-builder-bquxIHct.js} +2 -2
  30. package/dist/{design-builder-cZY958Rw.js.map → design-builder-bquxIHct.js.map} +1 -1
  31. package/dist/{editorErrors-BhrZ_nwj.js → editorErrors-8uDRMhow.js} +2 -2
  32. package/dist/editorErrors-8uDRMhow.js.map +1 -0
  33. package/dist/{embed-CJswRZte.js → embed-L3oRIgsj.js} +10 -10
  34. package/dist/{embed-CJswRZte.js.map → embed-L3oRIgsj.js.map} +1 -1
  35. package/dist/embed.mjs +6 -6
  36. package/dist/errors/editorError.d.ts +7 -1
  37. package/dist/{guards-DIX8aXWM.js → guards-BlbhM5MX.js} +2 -2
  38. package/dist/{guards-DIX8aXWM.js.map → guards-BlbhM5MX.js.map} +1 -1
  39. package/dist/hooks/index.d.ts +2 -0
  40. package/dist/hooks/useAlignDistribute.d.ts +19 -0
  41. package/dist/index.mjs +8 -8
  42. package/dist/internals.mjs +5 -5
  43. package/dist/{template-fields-BXl29sgh.js → template-fields-ai7vnW8g.js} +6 -6
  44. package/dist/{template-fields-BXl29sgh.js.map → template-fields-ai7vnW8g.js.map} +1 -1
  45. package/dist/testing.mjs +4 -4
  46. package/dist/{usePieceGuideBundle-DE21DQGZ.js → usePieceGuideBundle-CMe5br2a.js} +2 -2
  47. package/dist/{usePieceGuideBundle-DE21DQGZ.js.map → usePieceGuideBundle-CMe5br2a.js.map} +1 -1
  48. package/dist/utils/alignDistribute.d.ts +41 -0
  49. package/dist/{validation-DGXAQmUC.js → validation-B8kIYutI.js} +2592 -2562
  50. package/dist/validation-B8kIYutI.js.map +1 -0
  51. package/dist/workers/export-worker.bundle.string.d.ts +1 -1
  52. package/example/package.json +1 -1
  53. package/package.json +1 -1
  54. package/dist/CanvasRenderer-yszzrDfo.js.map +0 -1
  55. package/dist/ContextualToolbars-BHjYsril.js +0 -5556
  56. package/dist/ContextualToolbars-BHjYsril.js.map +0 -1
  57. package/dist/ExportManager-BTcyj4cf.js.map +0 -1
  58. package/dist/FontAnalyzer-EF3gLPr8.js.map +0 -1
  59. package/dist/UnifiedFontService-CHVYDBDW.js.map +0 -1
  60. package/dist/editorErrors-BhrZ_nwj.js.map +0 -1
  61. package/dist/validation-DGXAQmUC.js.map +0 -1
package/dist/embed.mjs CHANGED
@@ -1,9 +1,9 @@
1
- import { C as a, a as r, b as t, u as i, d as o, f as n, g as d } from "./UnifiedFontService-CHVYDBDW.js";
2
- import { E as l, R as u, a as E, b as c, S as p, c as g, d as S, f, p as x, e as T, g as v, h as C, v as P } from "./embed-CJswRZte.js";
3
- import { g as B, i as h, u as y } from "./editorErrors-BhrZ_nwj.js";
4
- import { D as k, d as D, a as I, i as F } from "./design-builder-cZY958Rw.js";
5
- import { D as w, T as M, h as A, i as G, j as K, k as _, l as j, m as z, r as N, u as Y, a as q, b as H, c as J, d as O, e as Q, f as U, w as V } from "./template-fields-BXl29sgh.js";
6
- import { s as X } from "./CanvasStateV1-BTbCD_xC.js";
1
+ import { C as a, a as r, b as t, u as i, d as o, f as n, g as d } from "./UnifiedFontService-BJzoqfBF.js";
2
+ import { E as l, R as u, a as E, b as c, S as p, c as g, d as S, f, p as x, e as T, g as v, h as C, v as P } from "./embed-L3oRIgsj.js";
3
+ import { g as B, i as h, u as y } from "./editorErrors-8uDRMhow.js";
4
+ import { D as k, d as D, a as I, i as F } from "./design-builder-bquxIHct.js";
5
+ import { D as w, T as M, h as A, i as G, j as K, k as _, l as j, m as z, r as N, u as Y, a as q, b as H, c as J, d as O, e as Q, f as U, w as V } from "./template-fields-ai7vnW8g.js";
6
+ import { s as X } from "./CanvasStateV1-kL09wsAn.js";
7
7
  export {
8
8
  a as CanvasServicesProvider,
9
9
  k as DesignBuilder,
@@ -87,7 +87,13 @@ export type EditorErrorCode =
87
87
  | 'E_NO_MUTABLE_BINDING'
88
88
  /** `auditEditor()` called with no `<Editor.Root>` mounted — the imperative
89
89
  * audit reads the most-recent mounted Root's registry (#10). */
90
- | 'E_AUDIT_NO_ROOT';
90
+ | 'E_AUDIT_NO_ROOT'
91
+ /** `computeDistribute()` called with fewer than 3 movable elements —
92
+ * distributing needs something between the two ends. Gate the action on
93
+ * `useAlignDistribute().canDistribute` instead of calling below the
94
+ * threshold (the toolbar hides its distribute buttons for exactly this
95
+ * reason). */
96
+ | 'E_DISTRIBUTE_MIN_THREE';
91
97
  export interface EditorErrorData {
92
98
  code: EditorErrorCode;
93
99
  /** Slug under https://developers.snowcone.app/ for the violated contract. */
@@ -1,4 +1,4 @@
1
- import { G as n, I as t, P as a, S as s, T as i } from "./FontAnalyzer-EF3gLPr8.js";
1
+ import { G as n, I as t, P as a, S as s, T as i } from "./FontAnalyzer-PE6nysqE.js";
2
2
  function r(e) {
3
3
  return e instanceof i;
4
4
  }
@@ -21,4 +21,4 @@ export {
21
21
  r as d,
22
22
  u as i
23
23
  };
24
- //# sourceMappingURL=guards-DIX8aXWM.js.map
24
+ //# sourceMappingURL=guards-BlbhM5MX.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"guards-DIX8aXWM.js","sources":["../src/types/guards.ts"],"sourcesContent":["/**\n * Type guards for EditorElement discrimination\n *\n * These guards use instanceof checks against the concrete element classes,\n * matching the pattern established in EditorContext.tsx. They accept\n * BaseElement | EditorElement | undefined | null for maximum flexibility\n * at call sites.\n */\n\nimport { BaseElement } from '../core/BaseElement.js';\nimport { TextElement } from '../core/TextElement.js';\nimport { ImageElement } from '../core/ImageElement.js';\nimport { GroupElement } from '../core/GroupElement.js';\nimport { ShapeElement } from '../core/ShapeElement.js';\nimport { PathElement } from '../core/PathElement.js';\n\ntype Narrowable = BaseElement | TextElement | ImageElement | GroupElement | ShapeElement | PathElement | undefined | null;\n\n/**\n * Type guard: checks if an element is a TextElement (or any text-based transform subclass).\n *\n * TextElement is the base class for all text transforms (custom, circle, arch, wave, etc.),\n * so this returns true for any text-based element regardless of its specific transformType.\n */\nexport function isTextElement(element: Narrowable): element is TextElement {\n return element instanceof TextElement;\n}\n\n/**\n * Type guard: checks if an element is an ImageElement.\n */\nexport function isImageElement(element: Narrowable): element is ImageElement {\n return element instanceof ImageElement;\n}\n\n/**\n * Type guard: checks if an element is a GroupElement.\n */\nexport function isGroupElement(element: Narrowable): element is GroupElement {\n return element instanceof GroupElement;\n}\n\n/**\n * Type guard: checks if an element is a ShapeElement.\n */\nexport function isShapeElement(element: Narrowable): element is ShapeElement {\n return element instanceof ShapeElement;\n}\n\n/**\n * Type guard: checks if an element is a PathElement.\n */\nexport function isPathElement(element: Narrowable): element is PathElement {\n return element instanceof PathElement;\n}\n"],"names":["isTextElement","element","TextElement","isImageElement","ImageElement","isGroupElement","GroupElement","isShapeElement","ShapeElement","isPathElement","PathElement"],"mappings":";AAwBO,SAASA,EAAcC,GAA6C;AACzE,SAAOA,aAAmBC;AAC5B;AAKO,SAASC,EAAeF,GAA8C;AAC3E,SAAOA,aAAmBG;AAC5B;AAKO,SAASC,EAAeJ,GAA8C;AAC3E,SAAOA,aAAmBK;AAC5B;AAKO,SAASC,EAAeN,GAA8C;AAC3E,SAAOA,aAAmBO;AAC5B;AAKO,SAASC,EAAcR,GAA6C;AACzE,SAAOA,aAAmBS;AAC5B;"}
1
+ {"version":3,"file":"guards-BlbhM5MX.js","sources":["../src/types/guards.ts"],"sourcesContent":["/**\n * Type guards for EditorElement discrimination\n *\n * These guards use instanceof checks against the concrete element classes,\n * matching the pattern established in EditorContext.tsx. They accept\n * BaseElement | EditorElement | undefined | null for maximum flexibility\n * at call sites.\n */\n\nimport { BaseElement } from '../core/BaseElement.js';\nimport { TextElement } from '../core/TextElement.js';\nimport { ImageElement } from '../core/ImageElement.js';\nimport { GroupElement } from '../core/GroupElement.js';\nimport { ShapeElement } from '../core/ShapeElement.js';\nimport { PathElement } from '../core/PathElement.js';\n\ntype Narrowable = BaseElement | TextElement | ImageElement | GroupElement | ShapeElement | PathElement | undefined | null;\n\n/**\n * Type guard: checks if an element is a TextElement (or any text-based transform subclass).\n *\n * TextElement is the base class for all text transforms (custom, circle, arch, wave, etc.),\n * so this returns true for any text-based element regardless of its specific transformType.\n */\nexport function isTextElement(element: Narrowable): element is TextElement {\n return element instanceof TextElement;\n}\n\n/**\n * Type guard: checks if an element is an ImageElement.\n */\nexport function isImageElement(element: Narrowable): element is ImageElement {\n return element instanceof ImageElement;\n}\n\n/**\n * Type guard: checks if an element is a GroupElement.\n */\nexport function isGroupElement(element: Narrowable): element is GroupElement {\n return element instanceof GroupElement;\n}\n\n/**\n * Type guard: checks if an element is a ShapeElement.\n */\nexport function isShapeElement(element: Narrowable): element is ShapeElement {\n return element instanceof ShapeElement;\n}\n\n/**\n * Type guard: checks if an element is a PathElement.\n */\nexport function isPathElement(element: Narrowable): element is PathElement {\n return element instanceof PathElement;\n}\n"],"names":["isTextElement","element","TextElement","isImageElement","ImageElement","isGroupElement","GroupElement","isShapeElement","ShapeElement","isPathElement","PathElement"],"mappings":";AAwBO,SAASA,EAAcC,GAA6C;AACzE,SAAOA,aAAmBC;AAC5B;AAKO,SAASC,EAAeF,GAA8C;AAC3E,SAAOA,aAAmBG;AAC5B;AAKO,SAASC,EAAeJ,GAA8C;AAC3E,SAAOA,aAAmBK;AAC5B;AAKO,SAASC,EAAeN,GAA8C;AAC3E,SAAOA,aAAmBO;AAC5B;AAKO,SAASC,EAAcR,GAA6C;AACzE,SAAOA,aAAmBS;AAC5B;"}
@@ -40,3 +40,5 @@ export { useCanvasEvents } from './useCanvasEvents';
40
40
  export { useCommandHistory } from './useCommandHistory';
41
41
  export { useKeyboardShortcuts } from './useKeyboardShortcuts';
42
42
  export { useElementProperties } from './useElementProperties';
43
+ export { useAlignDistribute } from './useAlignDistribute';
44
+ export type { UseAlignDistributeResult, AlignMode, DistributeMode } from './useAlignDistribute';
@@ -0,0 +1,19 @@
1
+ import { AlignMode, DistributeMode } from '../utils/alignDistribute.js';
2
+ export type { AlignMode, DistributeMode } from '../utils/alignDistribute.js';
3
+ export interface UseAlignDistributeResult {
4
+ /** Number of movable (selected, unlocked) elements. */
5
+ movableCount: number;
6
+ /** True when align commands have something to act on. */
7
+ canAlign: boolean;
8
+ /** True when distribute commands are available (≥3 movable elements).
9
+ * UI must gate rendering of distribute affordances on this. */
10
+ canDistribute: boolean;
11
+ /** Align the movable selection. ≥2 elements: relative to the selection's
12
+ * combined bbox; exactly 1: relative to the active artboard. */
13
+ align: (mode: AlignMode) => void;
14
+ /** Distribute the movable selection with equal gaps between bbox edges.
15
+ * Throws `E_DISTRIBUTE_MIN_THREE` when `canDistribute` is false. */
16
+ distribute: (mode: DistributeMode) => void;
17
+ }
18
+ export declare function useAlignDistribute(): UseAlignDistributeResult;
19
+ export default useAlignDistribute;
package/dist/index.mjs CHANGED
@@ -1,12 +1,12 @@
1
- import { e as u } from "./UnifiedFontService-CHVYDBDW.js";
2
- import { C as l, c as x, a as I, b as v, u as A, d as T, f as g, g as B } from "./UnifiedFontService-CHVYDBDW.js";
3
- import { E as _, S as y, S as L, u as O, a as M } from "./SnowconeCanvas-DuWALOAt.js";
4
- import { u as d, a as m } from "./editorErrors-BhrZ_nwj.js";
5
- import { T as z, r as w, u as F, a as D, b as K, c as N, d as V, e as b, f as h, w as U } from "./template-fields-BXl29sgh.js";
6
- import { A as Z, C as G, E as H, M as j, P as k, r as q, v as J } from "./validation-DGXAQmUC.js";
7
- import { C as W, D as X, d as $, s as ee } from "./design-builder-cZY958Rw.js";
1
+ import { e as u } from "./UnifiedFontService-BJzoqfBF.js";
2
+ import { C as l, c as x, a as I, b as v, u as A, d as T, f as g, g as B } from "./UnifiedFontService-BJzoqfBF.js";
3
+ import { E as _, S as y, S as L, u as O, a as M } from "./SnowconeCanvas-CQiFVR0X.js";
4
+ import { u as d, a as m } from "./editorErrors-8uDRMhow.js";
5
+ import { T as z, r as w, u as F, a as D, b as K, c as N, d as V, e as b, f as h, w as U } from "./template-fields-ai7vnW8g.js";
6
+ import { A as Z, C as G, E as H, M as j, P as k, r as q, v as J } from "./validation-B8kIYutI.js";
7
+ import { C as W, D as X, d as $, s as ee } from "./design-builder-bquxIHct.js";
8
8
  import { c as se, e as te } from "./compose-DtQL_oit.js";
9
- import { d as oe, m as ie, s as ne, v as ue } from "./CanvasStateV1-BTbCD_xC.js";
9
+ import { d as oe, m as ie, s as ne, v as ue } from "./CanvasStateV1-kL09wsAn.js";
10
10
  function C() {
11
11
  const { isCanvasReady: e } = d();
12
12
  return e;
@@ -1,8 +1,8 @@
1
- import { A as w, a as b, C as I, I as R, R as W, S as A, T as E } from "./CanvasRenderer-yszzrDfo.js";
2
- import { r as p } from "./ExportManager-BTcyj4cf.js";
3
- import { D as O, E as F, I as L, W as X, a as z, b as K, c as Y, d as B, e as _, f as J, h as N, i as V, j, k as q, l as Q, m as U, n as Z, o as $, p as m, q as G, s as x, t as D, u as rr, v as or, w as sr, x as ir, y as er, z as ar, A as nr, B as tr, C as hr } from "./ExportManager-BTcyj4cf.js";
4
- import { D as cr, E as fr, H as pr, J as gr, K as lr, L as ur, M as Tr, N as kr, O as Mr, Q as yr, W as Cr, V as vr, X as Sr, Y as Pr, c as wr, Z as br, _ as Ir, $ as Rr, a0 as Wr, a1 as Ar } from "./FontAnalyzer-EF3gLPr8.js";
5
- import { A as Hr, e as Or, C as Fr, S as Lr } from "./CanvasStateV1-BTbCD_xC.js";
1
+ import { A as w, a as b, C as I, I as R, R as W, S as A, T as E } from "./CanvasRenderer-B_3GISlW.js";
2
+ import { r as p } from "./ExportManager-J2xK86uq.js";
3
+ import { D as O, E as F, I as L, W as X, a as z, b as K, c as Y, d as B, e as _, f as J, h as N, i as V, j, k as q, l as Q, m as U, n as Z, o as $, p as m, q as G, s as x, t as D, u as rr, v as or, w as sr, x as ir, y as er, z as ar, A as nr, B as tr, C as hr } from "./ExportManager-J2xK86uq.js";
4
+ import { D as cr, E as fr, H as pr, J as gr, K as lr, L as ur, M as Tr, N as kr, O as Mr, Q as yr, W as Cr, V as vr, X as Sr, Y as Pr, c as wr, Z as br, _ as Ir, $ as Rr, a0 as Wr, a1 as Ar } from "./FontAnalyzer-PE6nysqE.js";
5
+ import { A as Hr, e as Or, C as Fr, S as Lr } from "./CanvasStateV1-kL09wsAn.js";
6
6
  function y(r, o) {
7
7
  return !r.needsCropPixelConversion || r.cropWidth === void 0 ? r : {
8
8
  ...r,
@@ -1,10 +1,10 @@
1
- import { g as C, u as ut, c as Y, b as W } from "./editorErrors-BhrZ_nwj.js";
2
- import { l as it, i as gt, a as Nt } from "./design-builder-cZY958Rw.js";
1
+ import { g as C, u as ut, c as Y, b as W } from "./editorErrors-8uDRMhow.js";
2
+ import { l as it, i as gt, a as Nt } from "./design-builder-bquxIHct.js";
3
3
  import { toOptionAttributes as St, toCombinations as It, getMissingSelections as wt, validateProductSelection as Ot, findBestCombination as J, computeDisabledChoices as At } from "@snowcone-app/sdk";
4
4
  import { useRef as E, useCallback as I, useEffect as Tt, useContext as ht, useId as kt, useLayoutEffect as Dt, useMemo as V, useState as ot } from "react";
5
- import { G as Bt, I as z, P as _t, S as Ft, T as K, z as yt, U as st, c as Ut, y as rt } from "./FontAnalyzer-EF3gLPr8.js";
6
- import { p as pt, U as Rt } from "./UnifiedFontService-CHVYDBDW.js";
7
- import { a as Lt, o as R, b as d, n as Pt, l as b, u as at, c as Yt } from "./CanvasStateV1-BTbCD_xC.js";
5
+ import { G as Bt, I as z, P as _t, S as Ft, T as K, z as yt, U as st, c as Ut, y as rt } from "./FontAnalyzer-PE6nysqE.js";
6
+ import { p as pt, U as Rt } from "./UnifiedFontService-BJzoqfBF.js";
7
+ import { a as Lt, o as R, b as d, n as Pt, l as b, u as at, c as Yt } from "./CanvasStateV1-kL09wsAn.js";
8
8
  function X(e) {
9
9
  return e.text;
10
10
  }
@@ -713,4 +713,4 @@ export {
713
713
  Oe as u,
714
714
  De as w
715
715
  };
716
- //# sourceMappingURL=template-fields-BXl29sgh.js.map
716
+ //# sourceMappingURL=template-fields-ai7vnW8g.js.map