@snowcone-app/canvas 0.27.0 → 0.29.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 (73) hide show
  1. package/ERROR_CONTRACT.md +13 -0
  2. package/dist/{CanvasRenderer-yszzrDfo.js → CanvasRenderer-_lFoIoz5.js} +916 -848
  3. package/dist/CanvasRenderer-_lFoIoz5.js.map +1 -0
  4. package/dist/{CanvasStateV1-BTbCD_xC.js → CanvasStateV1-BMxr6xb8.js} +7 -4
  5. package/dist/{CanvasStateV1-BTbCD_xC.js.map → CanvasStateV1-BMxr6xb8.js.map} +1 -1
  6. package/dist/ContextualToolbars-0jWvnQgp.js +5833 -0
  7. package/dist/ContextualToolbars-0jWvnQgp.js.map +1 -0
  8. package/dist/{EditorCanvasImpl-Ui8Ceb-h.js → EditorCanvasImpl-BNz8TPFs.js} +8 -8
  9. package/dist/{EditorCanvasImpl-Ui8Ceb-h.js.map → EditorCanvasImpl-BNz8TPFs.js.map} +1 -1
  10. package/dist/{ExportManager-BTcyj4cf.js → ExportManager-B8Td7uR5.js} +1051 -976
  11. package/dist/ExportManager-B8Td7uR5.js.map +1 -0
  12. package/dist/{FontAnalyzer-EF3gLPr8.js → FontAnalyzer-D4Sg-P6_.js} +1410 -1329
  13. package/dist/FontAnalyzer-D4Sg-P6_.js.map +1 -0
  14. package/dist/{ImagePanel-CIk6z41z.js → ImagePanel-CN2Bu3hf.js} +6 -6
  15. package/dist/{ImagePanel-CIk6z41z.js.map → ImagePanel-CN2Bu3hf.js.map} +1 -1
  16. package/dist/{SnowconeCanvas-DuWALOAt.js → SnowconeCanvas-CR_LdRFP.js} +27 -27
  17. package/dist/{SnowconeCanvas-DuWALOAt.js.map → SnowconeCanvas-CR_LdRFP.js.map} +1 -1
  18. package/dist/{UnifiedFontService-CHVYDBDW.js → UnifiedFontService-CgYnYTj7.js} +755 -713
  19. package/dist/UnifiedFontService-CgYnYTj7.js.map +1 -0
  20. package/dist/advanced.mjs +14 -14
  21. package/dist/components/MultiSelectionToolbar.d.ts +18 -0
  22. package/dist/components/toolbars/SecondaryPanels.d.ts +11 -0
  23. package/dist/components/ui/toolbar-button.d.ts +2 -0
  24. package/dist/core/GestureConstraints.d.ts +92 -0
  25. package/dist/core/InteractionStateMachine.d.ts +16 -2
  26. package/dist/core/ResizeHandler.d.ts +4 -1
  27. package/dist/core/ResizePipeline.d.ts +3 -0
  28. package/dist/core/TextElement.d.ts +13 -0
  29. package/dist/core/TextMetrics.d.ts +17 -3
  30. package/dist/core/rich-text-layout.d.ts +2 -0
  31. package/dist/core/text-spacing.d.ts +74 -0
  32. package/dist/{custom-icons-CcLMyybv.js → custom-icons-B5TRC1Ed.js} +2 -2
  33. package/dist/{custom-icons-CcLMyybv.js.map → custom-icons-B5TRC1Ed.js.map} +1 -1
  34. package/dist/{design-builder-cZY958Rw.js → design-builder-COj0zkxu.js} +2 -2
  35. package/dist/{design-builder-cZY958Rw.js.map → design-builder-COj0zkxu.js.map} +1 -1
  36. package/dist/{editorErrors-BhrZ_nwj.js → editorErrors-CCvoKj_P.js} +2 -2
  37. package/dist/editorErrors-CCvoKj_P.js.map +1 -0
  38. package/dist/{embed-CJswRZte.js → embed-BTRtoktw.js} +10 -10
  39. package/dist/{embed-CJswRZte.js.map → embed-BTRtoktw.js.map} +1 -1
  40. package/dist/embed.mjs +6 -6
  41. package/dist/errors/editorError.d.ts +7 -1
  42. package/dist/{guards-DIX8aXWM.js → guards-uQtEQJbs.js} +2 -2
  43. package/dist/{guards-DIX8aXWM.js.map → guards-uQtEQJbs.js.map} +1 -1
  44. package/dist/hooks/index.d.ts +2 -0
  45. package/dist/hooks/useAlignDistribute.d.ts +19 -0
  46. package/dist/hooks/useTextToolbar.d.ts +8 -0
  47. package/dist/index.mjs +8 -8
  48. package/dist/internals.mjs +5 -5
  49. package/dist/rendering/renderer-types.d.ts +4 -0
  50. package/dist/rendering/rich-text-renderer.d.ts +4 -0
  51. package/dist/rendering/text-renderer.d.ts +4 -1
  52. package/dist/state/CanvasStateV1.d.ts +3 -0
  53. package/dist/{template-fields-BXl29sgh.js → template-fields-BLRp84Ny.js} +6 -6
  54. package/dist/{template-fields-BXl29sgh.js.map → template-fields-BLRp84Ny.js.map} +1 -1
  55. package/dist/testing.mjs +4 -4
  56. package/dist/types/index.d.ts +26 -0
  57. package/dist/{usePieceGuideBundle-DE21DQGZ.js → usePieceGuideBundle-CTQszfKA.js} +2 -2
  58. package/dist/{usePieceGuideBundle-DE21DQGZ.js.map → usePieceGuideBundle-CTQszfKA.js.map} +1 -1
  59. package/dist/utils/alignDistribute.d.ts +41 -0
  60. package/dist/utils/featureApplied.d.ts +6 -0
  61. package/dist/{validation-DGXAQmUC.js → validation-eCebhplp.js} +2991 -2956
  62. package/dist/validation-eCebhplp.js.map +1 -0
  63. package/dist/workers/export-worker.bundle.string.d.ts +1 -1
  64. package/example/package.json +1 -1
  65. package/package.json +1 -1
  66. package/dist/CanvasRenderer-yszzrDfo.js.map +0 -1
  67. package/dist/ContextualToolbars-BHjYsril.js +0 -5556
  68. package/dist/ContextualToolbars-BHjYsril.js.map +0 -1
  69. package/dist/ExportManager-BTcyj4cf.js.map +0 -1
  70. package/dist/FontAnalyzer-EF3gLPr8.js.map +0 -1
  71. package/dist/UnifiedFontService-CHVYDBDW.js.map +0 -1
  72. package/dist/editorErrors-BhrZ_nwj.js.map +0 -1
  73. package/dist/validation-DGXAQmUC.js.map +0 -1
package/dist/advanced.mjs CHANGED
@@ -1,21 +1,21 @@
1
- import { D as te, T as M, h as D, B as re, I as q, i as I, j as ne, e as se } from "./UnifiedFontService-CHVYDBDW.js";
2
- import { k as at, L as it, M as ct, l as lt, S as dt, m as ut, s as mt, n as ft } from "./UnifiedFontService-CHVYDBDW.js";
3
- import { r as oe, v as ae } from "./validation-DGXAQmUC.js";
4
- import { a as pt, b as xt, c as gt, d as bt, D as yt, e as vt, f as wt, G as St, K as Ct, g as Tt, L as Et, S as $t, T as kt, Z as At, h as Ft, i as Pt, j as Nt, k as Rt, l as Bt, m as Mt, n as Dt, u as It, o as zt, p as Ot } from "./validation-DGXAQmUC.js";
5
- import { ImagePanel as Wt } from "./ImagePanel-CIk6z41z.js";
6
- import { P as ie, a as ce, b as le } from "./ContextualToolbars-BHjYsril.js";
7
- import { A as Gt, B as _t, c as Ut, C as jt, d as Jt, e as qt, F as Zt, f as Vt, I as Xt, g as Yt, M as Ht, h as Qt, S as er, T as tr, i as rr, j as nr, k as sr, U as or, l as ar, u as ir, m as cr } from "./ContextualToolbars-BHjYsril.js";
8
- import { u as Z } from "./editorErrors-BhrZ_nwj.js";
9
- import { E as dr, P as ur, p as mr, s as fr, b as hr, c as pr, d as xr, e as gr, f as br, a as yr } from "./editorErrors-BhrZ_nwj.js";
1
+ import { D as te, T as M, h as D, B as re, I as q, i as I, j as ne, e as se } from "./UnifiedFontService-CgYnYTj7.js";
2
+ import { k as at, L as it, M as ct, l as lt, S as dt, m as ut, s as mt, n as ft } from "./UnifiedFontService-CgYnYTj7.js";
3
+ import { r as oe, v as ae } from "./validation-eCebhplp.js";
4
+ import { a as pt, b as xt, c as gt, d as bt, D as yt, e as vt, f as wt, G as St, K as Ct, g as Tt, L as Et, S as $t, T as kt, Z as At, h as Ft, i as Pt, j as Nt, k as Rt, l as Bt, m as Mt, n as Dt, u as It, o as zt, p as Ot } from "./validation-eCebhplp.js";
5
+ import { ImagePanel as Wt } from "./ImagePanel-CN2Bu3hf.js";
6
+ import { P as ie, a as ce, b as le } from "./ContextualToolbars-0jWvnQgp.js";
7
+ import { A as Gt, B as _t, c as Ut, C as jt, d as Jt, e as qt, F as Zt, f as Vt, I as Xt, g as Yt, M as Ht, h as Qt, S as er, T as tr, i as rr, j as nr, k as sr, U as or, l as ar, u as ir, m as cr } from "./ContextualToolbars-0jWvnQgp.js";
8
+ import { u as Z } from "./editorErrors-CCvoKj_P.js";
9
+ import { E as dr, P as ur, p as mr, s as fr, b as hr, c as pr, d as xr, e as gr, f as br, a as yr } from "./editorErrors-CCvoKj_P.js";
10
10
  import { T as wr, u as Sr } from "./ThemeContext-Rjz25x9X.js";
11
- import { c as de, G as ue, F as me, g as fe, r as he, u as pe } from "./FontAnalyzer-EF3gLPr8.js";
12
- import { A as Tr, B as Er, I as $r, P as kr, R as Ar, S as Fr, T as Pr, h as Nr, a as Rr, b as Br, i as Mr, d as Dr, e as Ir, f as zr, j as Or, k as Lr, l as Wr, m as Kr, n as Gr, o as _r, p as Ur, q as jr, s as Jr, t as qr, v as Zr, w as Vr, x as Xr } from "./FontAnalyzer-EF3gLPr8.js";
13
- import { i as Hr, a as Qr, b as en, c as tn, d as rn } from "./guards-DIX8aXWM.js";
11
+ import { c as de, G as ue, F as me, g as fe, r as he, u as pe } from "./FontAnalyzer-D4Sg-P6_.js";
12
+ import { A as Tr, B as Er, I as $r, P as kr, R as Ar, S as Fr, T as Pr, h as Nr, a as Rr, b as Br, i as Mr, d as Dr, e as Ir, f as zr, j as Or, k as Lr, l as Wr, m as Kr, n as Gr, o as _r, p as Ur, q as jr, s as Jr, t as qr, v as Zr, w as Vr, x as Xr } from "./FontAnalyzer-D4Sg-P6_.js";
13
+ import { i as Hr, a as Qr, b as en, c as tn, d as rn } from "./guards-uQtEQJbs.js";
14
14
  import { useState as A, useCallback as y, useEffect as V, useMemo as X, useRef as B, memo as xe } from "react";
15
- import { I as ge } from "./ExportManager-BTcyj4cf.js";
15
+ import { I as ge } from "./ExportManager-B8Td7uR5.js";
16
16
  import { e as be, c as ye } from "./compose-DtQL_oit.js";
17
17
  import { jsxs as b, jsx as a, Fragment as ve } from "react/jsx-runtime";
18
- import { P as sn, p as on, u as an } from "./usePieceGuideBundle-DE21DQGZ.js";
18
+ import { P as sn, p as on, u as an } from "./usePieceGuideBundle-CTQszfKA.js";
19
19
  const ze = ({
20
20
  title: e,
21
21
  icon: t,
@@ -0,0 +1,18 @@
1
+ import { default as React } from 'react';
2
+ export interface MultiSelectionToolbarProps {
3
+ /** Positioning mode — mirrors `ContextualToolbars`. */
4
+ mode?: 'floating' | 'embedded';
5
+ /** Artboard screen bounds fallback when no canvas ref is available. */
6
+ artboardScreenBounds?: {
7
+ left: number;
8
+ top: number;
9
+ width: number;
10
+ height: number;
11
+ bottom: number;
12
+ centerX: number;
13
+ };
14
+ /** `data-sc-part` value for the toolbar root (Editor.* parts contract). */
15
+ partAttr?: string;
16
+ }
17
+ export declare const MultiSelectionToolbar: React.FC<MultiSelectionToolbarProps>;
18
+ export default MultiSelectionToolbar;
@@ -20,6 +20,17 @@ export interface FontSizePanelProps {
20
20
  widthValue?: number | null;
21
21
  /** Called when the width slider moves. */
22
22
  onWidthChange?: (value: number) => void;
23
+ /** Letter-spacing in px (extra advance per character). When
24
+ * null/undefined the slider is hidden (curved transforms — they lay
25
+ * glyphs along a path and intentionally ignore letter-spacing). */
26
+ letterSpacingValue?: number | null;
27
+ /** Called when the letter-spacing slider moves. */
28
+ onLetterSpacingChange?: (value: number) => void;
29
+ /** Line-height multiplier (lineSpacing = fontSize × value). When
30
+ * null/undefined the slider is hidden (curved transforms). */
31
+ lineHeightValue?: number | null;
32
+ /** Called when the line-height slider moves. */
33
+ onLineHeightChange?: (value: number) => void;
23
34
  }
24
35
  export declare const FontSizePanel: React.FC<FontSizePanelProps>;
25
36
  export interface OpacityPanelProps {
@@ -20,5 +20,7 @@ export interface ToolbarButtonProps {
20
20
  className?: string;
21
21
  /** Optional mouse leave handler (for tooltip management) */
22
22
  onMouseLeave?: (e: React.MouseEvent<HTMLButtonElement>) => void;
23
+ /** Stable machine-readable hook for tests/agents (rendered on the button). */
24
+ 'data-testid'?: string;
23
25
  }
24
26
  export declare const ToolbarButton: React.ForwardRefExoticComponent<ToolbarButtonProps & React.RefAttributes<HTMLButtonElement>>;
@@ -0,0 +1,92 @@
1
+ /**
2
+ * GestureConstraints — pure shift-modifier constraint math for canvas gestures.
3
+ *
4
+ * Figma/Canva muscle memory: holding Shift during a gesture constrains it.
5
+ * - Shift + drag → axis lock to the dominant axis (re-evaluated per move,
6
+ * so the user can swing between axes mid-drag)
7
+ * - Shift + rotate → snap to 15° increments (in stored user-facing degrees;
8
+ * the rotation sign flip — CLAUDE.md gotcha #15 — is
9
+ * already baked into the value by the rotate handler)
10
+ * - Shift + resize → lock aspect ratio to the gesture-start ratio
11
+ * (see ResizeHandler.calculateResize, which consumes
12
+ * applyAspectLock)
13
+ *
14
+ * Everything here is pure and DOM-free. The modifier state must be read
15
+ * PER POINTER-MOVE EVENT by the caller (`e.shiftKey` on pointermove) —
16
+ * never captured at pointerdown — because users press and release Shift
17
+ * mid-gesture.
18
+ */
19
+ /** Modifier-key state sampled from the current pointer event. */
20
+ export interface GestureModifiers {
21
+ /** True while the Shift key is held on the CURRENT pointer event. */
22
+ shift: boolean;
23
+ }
24
+ export type DragAxis = 'x' | 'y';
25
+ /** Rotation snap increment applied while Shift is held, in degrees. */
26
+ export declare const ROTATION_SNAP_DEGREES = 15;
27
+ /**
28
+ * Which axis dominates a drag delta. Ties go to 'x' (horizontal).
29
+ * Re-evaluated every move so the user can swing between axes mid-drag
30
+ * (matching Figma — the lock follows the pointer, it isn't sticky).
31
+ */
32
+ export declare function dominantDragAxis(dx: number, dy: number): DragAxis;
33
+ export interface ConstrainedDragDelta {
34
+ dx: number;
35
+ dy: number;
36
+ /** The axis whose movement was zeroed, or null when unconstrained. */
37
+ lockedAxis: DragAxis | null;
38
+ }
39
+ /**
40
+ * Shift + drag → axis lock. The dominant axis (larger |delta| from
41
+ * gesture start) keeps its delta; the other axis is zeroed.
42
+ *
43
+ * Without shift (or without modifiers) the delta passes through
44
+ * untouched with `lockedAxis: null` — callers can use that to decide
45
+ * whether to suppress snapping on the locked axis.
46
+ */
47
+ export declare function constrainDragDelta(dx: number, dy: number, modifiers?: GestureModifiers | null): ConstrainedDragDelta;
48
+ /**
49
+ * Shift + rotate → snap to `increment`-degree steps (default 15°).
50
+ *
51
+ * Operates on STORED degrees — the codebase's user-facing, sign-flipped
52
+ * convention (`RotationUtils.toRadians(d) = -d·π/180`; gotcha #15).
53
+ * The snap itself is convention-agnostic: it rounds whatever stored
54
+ * value the rotate handler produced (`currentRotation - delta`), so the
55
+ * sign flip is already baked into the input. Result is normalized to
56
+ * the same (-180, 180] range `InteractionStateMachine.updateRotate`
57
+ * emits, so 187.5° → 195 → -165, and -172.6° → -180 → 180.
58
+ */
59
+ export declare function snapRotationDegrees(degrees: number, increment?: number): number;
60
+ export interface AspectLockInput {
61
+ /** Resize anchor being dragged (corner or middle-* edge). */
62
+ anchor: string;
63
+ /** Visual dims at gesture start — these define the locked ratio. */
64
+ startVisualWidth: number;
65
+ startVisualHeight: number;
66
+ /** Unconstrained new visual dims from the per-anchor delta math. */
67
+ newVisualWidth: number;
68
+ newVisualHeight: number;
69
+ }
70
+ export interface AspectLockResult {
71
+ /** The single uniform scale applied to both axes. */
72
+ scale: number;
73
+ newVisualWidth: number;
74
+ newVisualHeight: number;
75
+ }
76
+ /**
77
+ * Shift + resize → aspect lock to the gesture-start ratio.
78
+ *
79
+ * - Corner handles: the axis with the larger relative change drives;
80
+ * one uniform scale applies to both axes.
81
+ * - Edge handles (middle-*): the dragged axis drives and the
82
+ * perpendicular axis scales proportionally — Figma's shift+edge-drag
83
+ * behavior ("scale proportionally from the edge").
84
+ *
85
+ * For shapes that already aspect-lock by default (circle/polygon/star
86
+ * use `max(scaleX, scaleY)` in `ShapeElement.resize`), feeding equal
87
+ * scales through is a no-op — `max(s, s) === s` — so shift never
88
+ * changes their behavior. For averaged types (ImageElement/GroupElement
89
+ * use `(scaleX + scaleY) / 2`), equal scales collapse the average to
90
+ * the locked scale: `(s + s) / 2 === s`.
91
+ */
92
+ export declare function applyAspectLock({ anchor, startVisualWidth, startVisualHeight, newVisualWidth, newVisualHeight, }: AspectLockInput): AspectLockResult;
@@ -1,3 +1,4 @@
1
+ import { GestureModifiers } from './GestureConstraints.js';
1
2
  import { BaseElement } from './BaseElement.js';
2
3
  import { GroupElement } from './GroupElement.js';
3
4
  import { ResizePipeline } from './ResizePipeline.js';
@@ -96,8 +97,15 @@ export declare class InteractionStateMachine {
96
97
  /**
97
98
  * Update drag operation
98
99
  * Returns updated position { x, y }
100
+ *
101
+ * `modifiers.shift` axis-locks the drag to the dominant axis
102
+ * (re-evaluated each move). Alignment snapping still runs on the
103
+ * free axis; on the locked axis the position is clamped back to the
104
+ * gesture-start value AFTER snapping, so a snap can never move the
105
+ * element off the locked axis. Read modifiers from the CURRENT
106
+ * pointer event — users press/release Shift mid-gesture.
99
107
  */
100
- updateDrag(mouseX: number, mouseY: number, allElements?: BaseElement[] | null): Point;
108
+ updateDrag(mouseX: number, mouseY: number, allElements?: BaseElement[] | null, modifiers?: GestureModifiers | null): Point;
101
109
  /**
102
110
  * Start resize operation
103
111
  */
@@ -140,8 +148,14 @@ export declare class InteractionStateMachine {
140
148
  /**
141
149
  * Update rotation operation
142
150
  * Returns updated rotation angle in degrees
151
+ *
152
+ * `modifiers.shift` snaps the result to 15° increments in stored
153
+ * (user-facing, sign-flipped — gotcha #15) degrees. The shift snap
154
+ * REPLACES the snapHandler's rotation snap while held: the 15° grid
155
+ * is a superset of the usual 0/90/180 magnets and must win
156
+ * deterministically. Read modifiers from the CURRENT pointer event.
143
157
  */
144
- updateRotate(mouseX: number, mouseY: number, centerX: number, centerY: number): number;
158
+ updateRotate(mouseX: number, mouseY: number, centerX: number, centerY: number, modifiers?: GestureModifiers | null): number;
145
159
  /**
146
160
  * Get rotation context
147
161
  */
@@ -1,3 +1,4 @@
1
+ import { GestureModifiers } from './GestureConstraints.js';
1
2
  import { TextElement } from './TextElement.js';
2
3
  import { Point, ResizeAnchor, TransformStartData } from '../types/index.js';
3
4
  interface HandleInfo {
@@ -11,7 +12,7 @@ export declare class ResizeHandler {
11
12
  /**
12
13
  * Calculate new dimensions and position for a resize operation
13
14
  */
14
- static calculateResize({ element, handle, dx, dy, startData, snapSystem, }: {
15
+ static calculateResize({ element, handle, dx, dy, startData, snapSystem, modifiers, }: {
15
16
  element: TextElement;
16
17
  handle: HandleInfo;
17
18
  dx: number;
@@ -23,6 +24,8 @@ export declare class ResizeHandler {
23
24
  y?: unknown;
24
25
  };
25
26
  } | null;
27
+ /** Modifier-key state read per move event. `shift: true` locks the aspect ratio to the gesture-start ratio. */
28
+ modifiers?: GestureModifiers | null;
26
29
  }): {
27
30
  element: TextElement;
28
31
  isFrozen?: boolean;
@@ -1,3 +1,4 @@
1
+ import { GestureModifiers } from './GestureConstraints.js';
1
2
  import { BaseElement } from './BaseElement.js';
2
3
  import { TextElement } from './TextElement.js';
3
4
  import { TransformStartData, ResizeAnchor } from '../types/index.js';
@@ -22,6 +23,8 @@ interface ResizeParams {
22
23
  y?: unknown;
23
24
  };
24
25
  } | null;
26
+ /** Modifier-key state read per move event — `shift: true` aspect-locks the resize. */
27
+ modifiers?: GestureModifiers | null;
25
28
  }
26
29
  interface ResizeResult {
27
30
  element: TextElement;
@@ -11,6 +11,19 @@ export declare class TextElement extends BaseElement {
11
11
  italic: boolean;
12
12
  underline: boolean;
13
13
  strikethrough: boolean;
14
+ /**
15
+ * Element-level letter-spacing in world-space px (extra advance after each
16
+ * character, CSS model). Per-character override via
17
+ * `CharacterStyle.letterSpacing`. undefined = 0. Custom transform only —
18
+ * curved transforms intentionally ignore it.
19
+ */
20
+ letterSpacing?: number;
21
+ /**
22
+ * Line-height multiplier (lineSpacing = fontSize × lineHeight).
23
+ * undefined = LINE_HEIGHT_MULTIPLIER (1.2), the historical layout.
24
+ * Custom transform only.
25
+ */
26
+ lineHeight?: number;
14
27
  glyphOverrides?: GlyphOverride[];
15
28
  openTypeFeatures?: OpenTypeFeatures;
16
29
  constructor(config?: Partial<BaseTextElementConfig>);
@@ -2,6 +2,17 @@
2
2
  * TextMetrics - Shared utilities for text measurement and layout
3
3
  * Reduces duplication across transform types
4
4
  */
5
+ /**
6
+ * Optional typography knobs threaded through layout/measurement.
7
+ * Omitting them (or passing {}) reproduces the historical layout EXACTLY:
8
+ * letterSpacing 0, lineHeight LINE_HEIGHT_MULTIPLIER (1.2).
9
+ */
10
+ export interface TextLayoutOptions {
11
+ /** Extra advance per character in px (CSS letter-spacing model). */
12
+ letterSpacing?: number;
13
+ /** Line-height multiplier (lineSpacing = fontSize × lineHeight). */
14
+ lineHeight?: number;
15
+ }
5
16
  /**
6
17
  * Build font string with optional bold and italic
7
18
  * @param {number} fontSize - Font size
@@ -21,9 +32,10 @@ export declare function buildFontString(fontSize: number, fontFamily: string, bo
21
32
  * @param {boolean} italic - Whether text is italic
22
33
  * @param {number} lockedLineCount - Optional locked line count (forces exact number of lines during corner resize)
23
34
  * @param {boolean} strict - If true, disable tolerance (wrap exactly at maxWidth, matching richText behavior)
35
+ * @param {TextLayoutOptions} opts - Optional letterSpacing (affects wrap points); omitting = legacy layout
24
36
  * @returns {string[]} Array of lines
25
37
  */
26
- export declare function wrapText(text: string, maxWidth: number, fontSize: number, fontFamily: string, bold?: boolean, italic?: boolean, lockedLineCount?: number, strict?: boolean): string[];
38
+ export declare function wrapText(text: string, maxWidth: number, fontSize: number, fontFamily: string, bold?: boolean, italic?: boolean, lockedLineCount?: number, strict?: boolean, opts?: TextLayoutOptions): string[];
27
39
  /**
28
40
  * Measure width of text
29
41
  * @param {string} text - Text to measure
@@ -31,9 +43,10 @@ export declare function wrapText(text: string, maxWidth: number, fontSize: numbe
31
43
  * @param {string} fontFamily - Font family name
32
44
  * @param {boolean} bold - Whether text is bold
33
45
  * @param {boolean} italic - Whether text is italic
46
+ * @param {number} letterSpacing - Extra advance per character in px (default 0 — legacy width)
34
47
  * @returns {number} Width in pixels
35
48
  */
36
- export declare function measureTextWidth(text: string, fontSize: number, fontFamily: string, bold?: boolean, italic?: boolean): number;
49
+ export declare function measureTextWidth(text: string, fontSize: number, fontFamily: string, bold?: boolean, italic?: boolean, letterSpacing?: number): number;
37
50
  /**
38
51
  * Get font metrics for accurate text positioning
39
52
  * @param {number} fontSize - Font size
@@ -98,9 +111,10 @@ export declare function calculateContainerHeight(lineCount: number, fontSize: nu
98
111
  * @param {boolean} italic - Whether text is italic
99
112
  * @param {number} lockedLineCount - Optional locked line count (forces exact number of lines during corner resize)
100
113
  * @param {boolean} strict - If true, disable tolerance (wrap exactly at maxWidth)
114
+ * @param {TextLayoutOptions} opts - Optional letterSpacing/lineHeight; omitting = legacy layout
101
115
  * @returns {Object} {width, height, lines} - Adjusted dimensions and line array
102
116
  */
103
- export declare function calculateVisualBoundsWithSpaceCollapsing(text: string, maxWidth: number, fontSize: number, fontFamily: string, bold?: boolean, italic?: boolean, lockedLineCount?: number, strict?: boolean): {
117
+ export declare function calculateVisualBoundsWithSpaceCollapsing(text: string, maxWidth: number, fontSize: number, fontFamily: string, bold?: boolean, italic?: boolean, lockedLineCount?: number, strict?: boolean, opts?: TextLayoutOptions): {
104
118
  width: number;
105
119
  height: number;
106
120
  lines: string[];
@@ -15,6 +15,8 @@ export declare function wrapRichTextSpans(spans: Array<{
15
15
  fontFamily: string;
16
16
  bold?: boolean;
17
17
  italic?: boolean;
18
+ /** Element-level letter-spacing default (px per character). */
19
+ letterSpacing?: number;
18
20
  }): Array<{
19
21
  text: string;
20
22
  style: CharacterStyle;
@@ -0,0 +1,74 @@
1
+ /**
2
+ * text-spacing — the ONE advance computation for letter-spaced text.
3
+ *
4
+ * Letter-spacing model (CSS `letter-spacing` / canvas `ctx.letterSpacing`
5
+ * semantics): every character's advance grows by `letterSpacing` world-space
6
+ * pixels, INCLUDING the last character of a run. So:
7
+ *
8
+ * spacedWidth(text) = ctx.measureText(text).width + spacing × charCount
9
+ * advance(char at index i) = ctx.measureText(prefix(i+1)).width − measureText(prefix(i)).width + spacing
10
+ * cursor x after N chars = ctx.measureText(prefix(N)).width + spacing × N
11
+ *
12
+ * The uniform per-character `+spacing` is what keeps cursor math, selection
13
+ * rects, hover chrome, stroke outlines, and painted glyphs in lockstep — every
14
+ * site sums the SAME advances. Do not invent a second model (e.g. "between
15
+ * characters only", spacing × (n−1)); a mixed model drifts the caret.
16
+ *
17
+ * Painting is done per-character at kerning-preserving offsets (each glyph is
18
+ * positioned by the measured width of its prefix, so kerning pairs inside the
19
+ * run stay intact) rather than via the native `ctx.letterSpacing` property,
20
+ * which is not implemented across all engines we ship to. When spacing is 0
21
+ * the fast path is a single fillText/strokeText — byte-identical to the
22
+ * pre-letter-spacing renderer, which is what the "default unchanged" tests pin.
23
+ *
24
+ * Worker-compatible: no DOM access; operates on whatever 2D context (canvas or
25
+ * OffscreenCanvas) the caller already configured (`ctx.font` must be set).
26
+ *
27
+ * SCOPE: straight ('custom') text transform only. Curved transforms (circle,
28
+ * arch, wave, lean, ascend, flag) place glyphs along their own path math and
29
+ * intentionally ignore letter-spacing (pinned in transform-renderer.test.ts).
30
+ */
31
+ type AnyRenderContext = CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D;
32
+ /** Minimal context shape needed for measurement-only callers (tests, layout). */
33
+ export interface MeasureOnlyContext {
34
+ measureText(text: string): {
35
+ width: number;
36
+ };
37
+ }
38
+ /**
39
+ * Count user-perceived characters (code points, not UTF-16 units) so
40
+ * surrogate pairs (emoji, PUA glyphs) get ONE spacing slot, matching the
41
+ * per-character paint loop which iterates with Array.from.
42
+ */
43
+ export declare function countSpacedChars(text: string): number;
44
+ /**
45
+ * Add letter-spacing to a raw measured width.
46
+ * `spacedTextWidth(ctx.measureText(t).width, t, s)` — every char gets +s.
47
+ */
48
+ export declare function spacedTextWidth(rawWidth: number, text: string, letterSpacing: number | undefined): number;
49
+ /**
50
+ * Measure text with letter-spacing using an already-configured context
51
+ * (ctx.font must be set by the caller).
52
+ */
53
+ export declare function measureTextWithSpacing(ctx: MeasureOnlyContext, text: string, letterSpacing: number | undefined): number;
54
+ /**
55
+ * Per-character x offsets (relative to the run's left edge) for a
56
+ * letter-spaced run. offsets[i] is where character i is painted; a trailing
57
+ * entry offsets[n] is the total advance (== spacedTextWidth). Kerning inside
58
+ * the run is preserved because each offset is the measured width of the full
59
+ * prefix, not a sum of isolated char widths.
60
+ */
61
+ export declare function getSpacedCharOffsets(ctx: MeasureOnlyContext, text: string, letterSpacing: number): number[];
62
+ /**
63
+ * Drop-in replacement for `ctx.fillText(text, x, y)` that honors
64
+ * letter-spacing. Respects the ctx's current `textAlign` (the spaced total
65
+ * width — trailing spacing included — is what gets centered/right-aligned,
66
+ * matching CSS). Zero/undefined spacing calls fillText once, unchanged.
67
+ */
68
+ export declare function fillTextWithSpacing(ctx: AnyRenderContext, text: string, x: number, y: number, letterSpacing: number | undefined): void;
69
+ /**
70
+ * Drop-in replacement for `ctx.strokeText(text, x, y)` that honors
71
+ * letter-spacing. Same alignment semantics as fillTextWithSpacing.
72
+ */
73
+ export declare function strokeTextWithSpacing(ctx: AnyRenderContext, text: string, x: number, y: number, letterSpacing: number | undefined): void;
74
+ export {};
@@ -1,6 +1,6 @@
1
1
  import { jsx as i, jsxs as h } from "react/jsx-runtime";
2
2
  import * as c from "react";
3
- import { n as T, z as y, O as w } from "./UnifiedFontService-CHVYDBDW.js";
3
+ import { n as T, z as y, O as w } from "./UnifiedFontService-CgYnYTj7.js";
4
4
  import * as R from "@radix-ui/react-label";
5
5
  import { cva as S } from "class-variance-authority";
6
6
  import * as g from "@radix-ui/react-tabs";
@@ -233,4 +233,4 @@ export {
233
233
  z as T,
234
234
  A as a
235
235
  };
236
- //# sourceMappingURL=custom-icons-CcLMyybv.js.map
236
+ //# sourceMappingURL=custom-icons-B5TRC1Ed.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"custom-icons-CcLMyybv.js","sources":["../src/vendor/ui/primitives/input.tsx","../src/vendor/ui/primitives/label.tsx","../src/vendor/ui/primitives/tabs.tsx","../src/vendor/ui/primitives/text-field.tsx","../src/components/ui/custom-icons.tsx"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { cn } from '../lib/utils';\nimport { useSurface } from './surface';\n\nexport interface InputProps extends React.InputHTMLAttributes<HTMLInputElement> {\n /** Whether the input is in an invalid state */\n isInvalid?: boolean;\n /** Content to display at the start of the input */\n startContent?: React.ReactNode;\n /** Content to display at the end of the input */\n endContent?: React.ReactNode;\n /**\n * Visual variant - auto-detected from Surface context, or can be set explicitly\n * - `default`: Standard field styling for forms (bg-field)\n * - `filled`: Field on elevated surface (bg-field-on-surface)\n * - `subtle`: Blends with buttons/tabs in toolbars (bg-default)\n */\n variant?: 'default' | 'filled' | 'subtle';\n}\n\nconst Input = React.forwardRef<HTMLInputElement, InputProps>(\n (\n {\n className,\n type,\n isInvalid,\n startContent,\n endContent,\n disabled,\n readOnly,\n required,\n variant,\n ...props\n },\n ref\n ) => {\n // Auto-detect variant from Surface context\n const surface = useSurface();\n const isOnSurface = surface.variant === 'default' || surface.variant === 'secondary';\n const effectiveVariant = variant ?? (isOnSurface ? 'filled' : 'default');\n\n const inputElement = (\n <input\n type={type}\n className={cn(\n 'sc:flex sc:h-10 sc:w-full sc:rounded-input sc:px-2.5 sc:py-1.5 sc:text-sm sc:appearance-none',\n 'sc:text-foreground sc:border-none',\n 'sc:file:border-0 sc:file:bg-transparent sc:file:text-sm sc:file:font-medium sc:file:text-foreground',\n 'sc:placeholder:text-foreground/50',\n 'sc:transition-shadow sc:duration-200 sc:ease-out sc:focus-visible:outline-none sc:focus:ring-2 sc:focus:ring-focus sc:focus:ring-offset-1 sc:focus:ring-offset-background',\n 'sc:disabled:cursor-not-allowed sc:disabled:opacity-50',\n // Variant styles - semantic: field on page vs field on surface vs toolbar\n effectiveVariant === 'default' && 'sc:bg-field sc:shadow-soft sc:dark:shadow-none',\n effectiveVariant === 'filled' && 'sc:bg-[var(--color-field-on-surface)]',\n effectiveVariant === 'subtle' && 'sc:bg-default sc:dark:bg-[var(--color-default-on-surface)]',\n isInvalid && 'sc:ring-2 sc:ring-danger sc:focus-visible:ring-danger',\n startContent && 'sc:pl-10',\n endContent && 'sc:pr-10',\n className\n )}\n ref={ref}\n disabled={disabled}\n readOnly={readOnly}\n required={required}\n aria-invalid={isInvalid}\n {...props}\n />\n );\n\n if (startContent || endContent) {\n return (\n <div className=\"sc:relative\">\n {startContent && (\n <div className=\"sc:absolute sc:left-3 sc:top-1/2 sc:-translate-y-1/2 sc:text-foreground sc:opacity-40\">{startContent}</div>\n )}\n {inputElement}\n {endContent && (\n <div className=\"sc:absolute sc:right-3 sc:top-1/2 sc:-translate-y-1/2 sc:text-foreground sc:opacity-40\">{endContent}</div>\n )}\n </div>\n );\n }\n\n return inputElement;\n }\n);\nInput.displayName = 'Input';\n\nexport { Input };\n","'use client';\n\nimport * as React from 'react';\nimport * as LabelPrimitive from '@radix-ui/react-label';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { cn } from '../lib/utils';\n\nconst labelVariants = cva(\n 'sc:block sc:text-sm sc:leading-none sc:text-foreground sc:peer-disabled:cursor-not-allowed sc:peer-disabled:opacity-70 sc:font-label'\n);\n\nconst Label = React.forwardRef<\n React.ElementRef<typeof LabelPrimitive.Root>,\n React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root> & VariantProps<typeof labelVariants>\n>(({ className, ...props }, ref) => (\n <LabelPrimitive.Root ref={ref} className={cn(labelVariants(), className)} {...props} />\n));\nLabel.displayName = LabelPrimitive.Root.displayName;\n\nexport { Label };\n","\"use client\";\n\n'use client';\n\nimport * as React from 'react';\nimport * as TabsPrimitive from '@radix-ui/react-tabs';\nimport { cn } from '../lib/utils';\nimport { useSurface } from './surface';\n\ninterface TabsProps\n extends Omit<React.ComponentPropsWithoutRef<typeof TabsPrimitive.Root>, 'value' | 'onValueChange'> {\n value?: string;\n onValueChange?: (value: string) => void;\n}\n\nconst TabsRoot = React.forwardRef<React.ElementRef<typeof TabsPrimitive.Root>, TabsProps>(\n ({ value, onValueChange, ...props }, ref) => (\n <TabsPrimitive.Root ref={ref} value={value} onValueChange={onValueChange} {...props} />\n )\n);\nTabsRoot.displayName = 'Tabs';\n\nconst TabsList = React.forwardRef<\n React.ElementRef<typeof TabsPrimitive.List>,\n React.ComponentPropsWithoutRef<typeof TabsPrimitive.List>\n>(({ className, children, ...props }, ref) => {\n const listRef = React.useRef<HTMLDivElement>(null);\n const [indicatorStyle, setIndicatorStyle] = React.useState<React.CSSProperties>({\n opacity: 0,\n });\n\n // Update indicator position when active tab changes\n React.useEffect(() => {\n const listElement = listRef.current;\n if (!listElement) return;\n\n const updateIndicator = () => {\n const activeTab = listElement.querySelector('[data-state=\"active\"]') as HTMLElement;\n if (activeTab) {\n const listRect = listElement.getBoundingClientRect();\n const tabRect = activeTab.getBoundingClientRect();\n\n setIndicatorStyle({\n width: tabRect.width,\n height: tabRect.height,\n left: tabRect.left - listRect.left,\n opacity: 1,\n });\n }\n };\n\n // Initial position\n updateIndicator();\n\n // Use MutationObserver to detect when active tab changes\n const observer = new MutationObserver((mutations) => {\n for (const mutation of mutations) {\n if (mutation.type === 'attributes' && mutation.attributeName === 'data-state') {\n updateIndicator();\n break;\n }\n }\n });\n\n // Observe all trigger elements for data-state changes\n const triggers = listElement.querySelectorAll('[role=\"tab\"]');\n triggers.forEach((trigger) => {\n observer.observe(trigger, { attributes: true, attributeFilter: ['data-state'] });\n });\n\n // Also update on resize\n const resizeObserver = new ResizeObserver(updateIndicator);\n resizeObserver.observe(listElement);\n\n return () => {\n observer.disconnect();\n resizeObserver.disconnect();\n };\n }, [children]);\n\n return (\n <TabsPrimitive.List\n ref={(node) => {\n // Handle both refs\n (listRef as React.MutableRefObject<HTMLDivElement | null>).current = node;\n if (typeof ref === 'function') {\n ref(node);\n } else if (ref) {\n ref.current = node;\n }\n }}\n className={cn(\n 'sc:relative sc:inline-flex sc:h-10 sc:items-center sc:justify-center sc:rounded-full sc:px-1 sc:text-muted-foreground',\n // Consistent bg-default matches Button secondary variant for toolbar harmony\n 'sc:bg-default sc:dark:bg-[var(--color-default-on-surface)]',\n className\n )}\n {...props}\n >\n {/* Animated sliding indicator. In dark mode the previous `bg-muted`\n value resolved to the same color as `bg-default` on the container,\n so the active tab was invisible without relying purely on\n shadow-md. `bg-popover` lands ~0.08 lightness above `bg-default`\n in dark mode for a clearly visible elevation. */}\n <span\n className=\"sc:absolute sc:top-1/2 sc:-translate-y-1/2 sc:rounded-full sc:bg-surface sc:dark:bg-popover sc:shadow-md sc:transition-[left,width,opacity]\"\n style={{\n ...indicatorStyle,\n transitionDuration: '350ms',\n transitionTimingFunction: 'cubic-bezier(0.22, 1, 0.36, 1)',\n }}\n aria-hidden=\"true\"\n />\n {children}\n </TabsPrimitive.List>\n );\n});\nTabsList.displayName = TabsPrimitive.List.displayName;\n\ninterface TabsTriggerProps extends Omit<React.ComponentPropsWithoutRef<typeof TabsPrimitive.Trigger>, 'value'> {\n // HeroUI uses 'id' for tab identification, Radix uses 'value'\n // At least one must be provided\n id?: string;\n value?: string;\n}\n\nconst TabsTrigger = React.forwardRef<React.ElementRef<typeof TabsPrimitive.Trigger>, TabsTriggerProps>(\n ({ className, id, value, ...props }, ref) => {\n const { variant: surfaceVariant } = useSurface();\n const isOnSurface = surfaceVariant === 'default' || surfaceVariant === 'secondary';\n\n return (\n <TabsPrimitive.Trigger\n ref={ref}\n value={id ?? value ?? ''}\n className={cn(\n 'sc:relative sc:z-10 sc:inline-flex sc:h-8 sc:items-center sc:justify-center sc:gap-2 sc:whitespace-nowrap sc:rounded-full sc:px-4 sc:text-sm sc:font-label',\n 'sc:transition-[color,opacity]',\n 'sc:focus-visible:outline-none sc:focus-visible:ring-2 sc:focus-visible:ring-focus sc:focus-visible:ring-offset-2',\n 'sc:disabled:pointer-events-none sc:disabled:opacity-50',\n 'sc:data-[state=active]:text-foreground sc:data-[state=active]:opacity-100',\n // Inactive tabs use element opacity (not color opacity) to avoid SVG path overlap issues\n isOnSurface\n ? 'sc:data-[state=inactive]:text-foreground sc:data-[state=inactive]:opacity-30 sc:data-[state=inactive]:hover:opacity-50'\n : 'sc:data-[state=inactive]:text-foreground sc:data-[state=inactive]:opacity-50 sc:data-[state=inactive]:hover:opacity-70',\n className\n )}\n {...props}\n />\n );\n }\n);\nTabsTrigger.displayName = TabsPrimitive.Trigger.displayName;\n\ninterface TabsContentProps extends Omit<React.ComponentPropsWithoutRef<typeof TabsPrimitive.Content>, 'value'> {\n // HeroUI uses 'id' for panel identification, Radix uses 'value'\n // At least one must be provided\n id?: string;\n value?: string;\n}\n\nconst TabsContent = React.forwardRef<React.ElementRef<typeof TabsPrimitive.Content>, TabsContentProps>(\n ({ className, id, value, ...props }, ref) => (\n <TabsPrimitive.Content\n ref={ref}\n value={id ?? value ?? ''}\n className={cn(\n 'sc:mt-2 sc:ring-offset-background sc:focus-visible:outline-none sc:focus-visible:ring-2 sc:focus-visible:ring-focus sc:focus-visible:ring-offset-2',\n className\n )}\n {...props}\n />\n )\n);\nTabsContent.displayName = TabsPrimitive.Content.displayName;\n\n// HeroUI ListContainer - wrapper for the tabs list (passthrough div)\nconst TabsListContainer = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(\n ({ className, ...props }, ref) => <div ref={ref} className={className} {...props} />\n);\nTabsListContainer.displayName = 'TabsListContainer';\n\n// HeroUI Tab - alias for TabsTrigger\nconst TabsTab = TabsTrigger;\n\n// HeroUI Panel - alias for TabsContent\nconst TabsPanel = TabsContent;\n\n// HeroUI Indicator - now rendered automatically by TabsList, this is a no-op\nconst TabsIndicator = () => null;\n\n// Create compound component with all aliases\nconst TabsBase = TabsRoot;\n\n// HeroUI-compatible compound component\nconst Tabs = Object.assign(TabsBase, {\n List: TabsList,\n ListContainer: TabsListContainer,\n Tab: TabsTab,\n Trigger: TabsTrigger,\n Panel: TabsPanel,\n Content: TabsContent,\n Indicator: TabsIndicator,\n});\n\nexport { Tabs, TabsList, TabsTrigger, TabsContent, TabsRoot };\n","'use client';\n\nimport * as React from 'react';\nimport { cn } from '../lib/utils';\n\nexport interface TextFieldProps extends React.HTMLAttributes<HTMLDivElement> {\n /**\n * Accessible label for the input.\n * If not provided via children, use aria-label on the div.\n */\n 'aria-label'?: string;\n /**\n * Error state - applies error styling to children inputs\n */\n isInvalid?: boolean;\n /**\n * Disabled state - disables all children inputs\n */\n disabled?: boolean;\n /**\n * Required state - marks all children inputs as required\n */\n required?: boolean;\n}\n\n/**\n * TextField - A wrapper component that groups Label and Input together.\n *\n * Groups Label and Input with a convenient wrapper that can propagate\n * disabled, required, and invalid states to child inputs.\n *\n * @example\n * ```tsx\n * <TextField>\n * <Label>Email</Label>\n * <Input type=\"email\" placeholder=\"Enter email...\" />\n * </TextField>\n * ```\n */\nconst TextField = React.forwardRef<HTMLDivElement, TextFieldProps>(\n ({ className, children, isInvalid, disabled, required, ...props }, ref) => {\n // Clone children to pass through state props to Input/Textarea children\n const enhancedChildren = React.Children.map(children, (child) => {\n if (!React.isValidElement(child)) return child;\n\n // Get the display name or type name to check if it's an input component\n const childType = child.type;\n const displayName =\n typeof childType === 'function'\n ? (childType as React.ComponentType).displayName || childType.name\n : typeof childType === 'string'\n ? childType\n : '';\n\n // Check if this is an input-like element that should receive state props\n const isInputElement =\n displayName === 'Input' ||\n displayName === 'Textarea' ||\n displayName === 'TextArea' ||\n displayName === 'input' ||\n displayName === 'textarea';\n\n if (isInputElement) {\n const childProps = child.props as Record<string, unknown>;\n return React.cloneElement(child as React.ReactElement<Record<string, unknown>>, {\n isInvalid: (childProps.isInvalid as boolean) ?? isInvalid,\n disabled: (childProps.disabled as boolean) ?? disabled,\n required: (childProps.required as boolean) ?? required,\n });\n }\n\n return child;\n });\n\n return (\n <div ref={ref} className={cn('sc:flex sc:flex-col sc:gap-1.5', className)} {...props}>\n {enhancedChildren}\n </div>\n );\n }\n);\nTextField.displayName = 'TextField';\n\nexport { TextField };\n","/**\n * Custom Icons - Centered versions of icons from various sets\n *\n * These are copies of icons with adjusted viewBox to center properly.\n * Use these instead of the original iconify versions for consistent alignment.\n */\n\nimport React from 'react';\nimport { cn } from '../../lib/utils';\n\ninterface IconProps {\n className?: string;\n size?: number | string;\n}\n\n/**\n * Rotate Left icon (lucide-style stroked version)\n */\nexport const RotateLeftIcon: React.FC<IconProps> = ({ className, size = 24 }) => (\n <svg\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n width={size}\n height={size}\n className={cn('sc:inline-block iconify', className)}\n >\n <path d=\"M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8\" />\n <path d=\"M3 3v5h5\" />\n </svg>\n);\n\n/**\n * Rotate Right icon (lucide-style stroked version)\n */\nexport const RotateRightIcon: React.FC<IconProps> = ({ className, size = 24 }) => (\n <svg\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n width={size}\n height={size}\n className={cn('sc:inline-block iconify', className)}\n >\n <path d=\"M21 12a9 9 0 1 1-9-9c2.52 0 4.93 1 6.74 2.74L21 8\" />\n <path d=\"M21 3v5h-5\" />\n </svg>\n);\n\n/**\n * Sparkles icon (based on gravity-ui:sparkles)\n * Two sparkle shapes - main 4-point star and smaller accent\n */\nexport const SparklesIcon: React.FC<IconProps> = ({ className, size = 24 }) => (\n <svg\n viewBox=\"0 0 28 28\"\n fill=\"currentColor\"\n width={size}\n height={size}\n className={cn('sc:inline-block', className)}\n >\n <path d=\"M10.06 18.701a1.628 1.628 0 0 0 2.43-.676l.77-2.34a3.82 3.82 0 0 1 2.416-2.418l2.238-.727a1.6 1.6 0 0 0 .786-.595a1.62 1.62 0 0 0-.849-2.489l-2.215-.72a3.82 3.82 0 0 1-2.42-2.414l-.727-2.237a1.62 1.62 0 0 0-.594-.785a1.655 1.655 0 0 0-1.879 0a1.63 1.63 0 0 0-.6.8L8.68 6.365a3.82 3.82 0 0 1-2.359 2.37l-2.24.726a1.626 1.626 0 0 0 .02 3.073l2.216.72a3.86 3.86 0 0 1 1.816 1.286c.266.343.471.728.606 1.14l.728 2.234c.112.318.32.593.595.787m-3.273-6.873l-2.22-.72s-.085-.038-.085-.108a.14.14 0 0 1 .084-.115L6.8 10.16a5.34 5.34 0 0 0 3.32-3.375l.721-2.219s.043-.084.114-.084s.113.084.113.084l.723 2.223a5.32 5.32 0 0 0 3.377 3.372l2.27.735a.13.13 0 0 1 .078.11a.15.15 0 0 1-.083.113l-2.225.722a5.32 5.32 0 0 0-3.374 3.374l-.715 2.2a.11.11 0 0 1-.115.093c-.104 0-.118-.075-.118-.075l-.723-2.22a5.32 5.32 0 0 0-3.376-3.385m13.017 12.954A1.2 1.2 0 0 0 20.5 25a1.2 1.2 0 0 0 .692-.216a1.2 1.2 0 0 0 .446-.6l.372-1.143a1.61 1.61 0 0 1 1.017-1.02l1.166-.378A1.21 1.21 0 0 0 25 20.505a1.2 1.2 0 0 0-.844-1.146l-1.144-.37a1.61 1.61 0 0 1-1.02-1.018l-.38-1.163a1.2 1.2 0 0 0-2.274.016l-.374 1.146a1.61 1.61 0 0 1-.993 1.017l-1.166.378a1.21 1.21 0 0 0-.807 1.139a1.2 1.2 0 0 0 .823 1.138l1.144.372a1.6 1.6 0 0 1 1.02 1.023l.379 1.163a1.2 1.2 0 0 0 .44.582m-1.371-4.194l-.27-.088l.283-.096a3.12 3.12 0 0 0 1.943-1.974l.088-.27l.089.272a3.11 3.11 0 0 0 1.974 1.975l.293.1l-.271.087a3.12 3.12 0 0 0-1.974 1.977l-.088.27l-.088-.272a3.12 3.12 0 0 0-1.98-1.98\" />\n </svg>\n);\n\n// Map of icon names to components for easy lookup\nexport const CustomIcons = {\n 'rotate-left': RotateLeftIcon,\n 'rotate-right': RotateRightIcon,\n 'sparkles': SparklesIcon,\n} as const;\n\nexport type CustomIconName = keyof typeof CustomIcons;\n"],"names":["Input","React","className","type","isInvalid","startContent","endContent","disabled","readOnly","required","variant","props","ref","surface","useSurface","isOnSurface","effectiveVariant","inputElement","jsx","cn","jsxs","labelVariants","cva","Label","LabelPrimitive","TabsRoot","value","onValueChange","TabsPrimitive","TabsList","children","listRef","indicatorStyle","setIndicatorStyle","listElement","updateIndicator","activeTab","listRect","tabRect","observer","mutations","mutation","trigger","resizeObserver","node","TabsTrigger","id","surfaceVariant","TabsContent","TabsListContainer","TabsTab","TabsPanel","TabsIndicator","TabsBase","Tabs","TextField","enhancedChildren","child","childType","displayName","childProps","RotateLeftIcon","size","SparklesIcon"],"mappings":"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"}
1
+ {"version":3,"file":"custom-icons-B5TRC1Ed.js","sources":["../src/vendor/ui/primitives/input.tsx","../src/vendor/ui/primitives/label.tsx","../src/vendor/ui/primitives/tabs.tsx","../src/vendor/ui/primitives/text-field.tsx","../src/components/ui/custom-icons.tsx"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { cn } from '../lib/utils';\nimport { useSurface } from './surface';\n\nexport interface InputProps extends React.InputHTMLAttributes<HTMLInputElement> {\n /** Whether the input is in an invalid state */\n isInvalid?: boolean;\n /** Content to display at the start of the input */\n startContent?: React.ReactNode;\n /** Content to display at the end of the input */\n endContent?: React.ReactNode;\n /**\n * Visual variant - auto-detected from Surface context, or can be set explicitly\n * - `default`: Standard field styling for forms (bg-field)\n * - `filled`: Field on elevated surface (bg-field-on-surface)\n * - `subtle`: Blends with buttons/tabs in toolbars (bg-default)\n */\n variant?: 'default' | 'filled' | 'subtle';\n}\n\nconst Input = React.forwardRef<HTMLInputElement, InputProps>(\n (\n {\n className,\n type,\n isInvalid,\n startContent,\n endContent,\n disabled,\n readOnly,\n required,\n variant,\n ...props\n },\n ref\n ) => {\n // Auto-detect variant from Surface context\n const surface = useSurface();\n const isOnSurface = surface.variant === 'default' || surface.variant === 'secondary';\n const effectiveVariant = variant ?? (isOnSurface ? 'filled' : 'default');\n\n const inputElement = (\n <input\n type={type}\n className={cn(\n 'sc:flex sc:h-10 sc:w-full sc:rounded-input sc:px-2.5 sc:py-1.5 sc:text-sm sc:appearance-none',\n 'sc:text-foreground sc:border-none',\n 'sc:file:border-0 sc:file:bg-transparent sc:file:text-sm sc:file:font-medium sc:file:text-foreground',\n 'sc:placeholder:text-foreground/50',\n 'sc:transition-shadow sc:duration-200 sc:ease-out sc:focus-visible:outline-none sc:focus:ring-2 sc:focus:ring-focus sc:focus:ring-offset-1 sc:focus:ring-offset-background',\n 'sc:disabled:cursor-not-allowed sc:disabled:opacity-50',\n // Variant styles - semantic: field on page vs field on surface vs toolbar\n effectiveVariant === 'default' && 'sc:bg-field sc:shadow-soft sc:dark:shadow-none',\n effectiveVariant === 'filled' && 'sc:bg-[var(--color-field-on-surface)]',\n effectiveVariant === 'subtle' && 'sc:bg-default sc:dark:bg-[var(--color-default-on-surface)]',\n isInvalid && 'sc:ring-2 sc:ring-danger sc:focus-visible:ring-danger',\n startContent && 'sc:pl-10',\n endContent && 'sc:pr-10',\n className\n )}\n ref={ref}\n disabled={disabled}\n readOnly={readOnly}\n required={required}\n aria-invalid={isInvalid}\n {...props}\n />\n );\n\n if (startContent || endContent) {\n return (\n <div className=\"sc:relative\">\n {startContent && (\n <div className=\"sc:absolute sc:left-3 sc:top-1/2 sc:-translate-y-1/2 sc:text-foreground sc:opacity-40\">{startContent}</div>\n )}\n {inputElement}\n {endContent && (\n <div className=\"sc:absolute sc:right-3 sc:top-1/2 sc:-translate-y-1/2 sc:text-foreground sc:opacity-40\">{endContent}</div>\n )}\n </div>\n );\n }\n\n return inputElement;\n }\n);\nInput.displayName = 'Input';\n\nexport { Input };\n","'use client';\n\nimport * as React from 'react';\nimport * as LabelPrimitive from '@radix-ui/react-label';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { cn } from '../lib/utils';\n\nconst labelVariants = cva(\n 'sc:block sc:text-sm sc:leading-none sc:text-foreground sc:peer-disabled:cursor-not-allowed sc:peer-disabled:opacity-70 sc:font-label'\n);\n\nconst Label = React.forwardRef<\n React.ElementRef<typeof LabelPrimitive.Root>,\n React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root> & VariantProps<typeof labelVariants>\n>(({ className, ...props }, ref) => (\n <LabelPrimitive.Root ref={ref} className={cn(labelVariants(), className)} {...props} />\n));\nLabel.displayName = LabelPrimitive.Root.displayName;\n\nexport { Label };\n","\"use client\";\n\n'use client';\n\nimport * as React from 'react';\nimport * as TabsPrimitive from '@radix-ui/react-tabs';\nimport { cn } from '../lib/utils';\nimport { useSurface } from './surface';\n\ninterface TabsProps\n extends Omit<React.ComponentPropsWithoutRef<typeof TabsPrimitive.Root>, 'value' | 'onValueChange'> {\n value?: string;\n onValueChange?: (value: string) => void;\n}\n\nconst TabsRoot = React.forwardRef<React.ElementRef<typeof TabsPrimitive.Root>, TabsProps>(\n ({ value, onValueChange, ...props }, ref) => (\n <TabsPrimitive.Root ref={ref} value={value} onValueChange={onValueChange} {...props} />\n )\n);\nTabsRoot.displayName = 'Tabs';\n\nconst TabsList = React.forwardRef<\n React.ElementRef<typeof TabsPrimitive.List>,\n React.ComponentPropsWithoutRef<typeof TabsPrimitive.List>\n>(({ className, children, ...props }, ref) => {\n const listRef = React.useRef<HTMLDivElement>(null);\n const [indicatorStyle, setIndicatorStyle] = React.useState<React.CSSProperties>({\n opacity: 0,\n });\n\n // Update indicator position when active tab changes\n React.useEffect(() => {\n const listElement = listRef.current;\n if (!listElement) return;\n\n const updateIndicator = () => {\n const activeTab = listElement.querySelector('[data-state=\"active\"]') as HTMLElement;\n if (activeTab) {\n const listRect = listElement.getBoundingClientRect();\n const tabRect = activeTab.getBoundingClientRect();\n\n setIndicatorStyle({\n width: tabRect.width,\n height: tabRect.height,\n left: tabRect.left - listRect.left,\n opacity: 1,\n });\n }\n };\n\n // Initial position\n updateIndicator();\n\n // Use MutationObserver to detect when active tab changes\n const observer = new MutationObserver((mutations) => {\n for (const mutation of mutations) {\n if (mutation.type === 'attributes' && mutation.attributeName === 'data-state') {\n updateIndicator();\n break;\n }\n }\n });\n\n // Observe all trigger elements for data-state changes\n const triggers = listElement.querySelectorAll('[role=\"tab\"]');\n triggers.forEach((trigger) => {\n observer.observe(trigger, { attributes: true, attributeFilter: ['data-state'] });\n });\n\n // Also update on resize\n const resizeObserver = new ResizeObserver(updateIndicator);\n resizeObserver.observe(listElement);\n\n return () => {\n observer.disconnect();\n resizeObserver.disconnect();\n };\n }, [children]);\n\n return (\n <TabsPrimitive.List\n ref={(node) => {\n // Handle both refs\n (listRef as React.MutableRefObject<HTMLDivElement | null>).current = node;\n if (typeof ref === 'function') {\n ref(node);\n } else if (ref) {\n ref.current = node;\n }\n }}\n className={cn(\n 'sc:relative sc:inline-flex sc:h-10 sc:items-center sc:justify-center sc:rounded-full sc:px-1 sc:text-muted-foreground',\n // Consistent bg-default matches Button secondary variant for toolbar harmony\n 'sc:bg-default sc:dark:bg-[var(--color-default-on-surface)]',\n className\n )}\n {...props}\n >\n {/* Animated sliding indicator. In dark mode the previous `bg-muted`\n value resolved to the same color as `bg-default` on the container,\n so the active tab was invisible without relying purely on\n shadow-md. `bg-popover` lands ~0.08 lightness above `bg-default`\n in dark mode for a clearly visible elevation. */}\n <span\n className=\"sc:absolute sc:top-1/2 sc:-translate-y-1/2 sc:rounded-full sc:bg-surface sc:dark:bg-popover sc:shadow-md sc:transition-[left,width,opacity]\"\n style={{\n ...indicatorStyle,\n transitionDuration: '350ms',\n transitionTimingFunction: 'cubic-bezier(0.22, 1, 0.36, 1)',\n }}\n aria-hidden=\"true\"\n />\n {children}\n </TabsPrimitive.List>\n );\n});\nTabsList.displayName = TabsPrimitive.List.displayName;\n\ninterface TabsTriggerProps extends Omit<React.ComponentPropsWithoutRef<typeof TabsPrimitive.Trigger>, 'value'> {\n // HeroUI uses 'id' for tab identification, Radix uses 'value'\n // At least one must be provided\n id?: string;\n value?: string;\n}\n\nconst TabsTrigger = React.forwardRef<React.ElementRef<typeof TabsPrimitive.Trigger>, TabsTriggerProps>(\n ({ className, id, value, ...props }, ref) => {\n const { variant: surfaceVariant } = useSurface();\n const isOnSurface = surfaceVariant === 'default' || surfaceVariant === 'secondary';\n\n return (\n <TabsPrimitive.Trigger\n ref={ref}\n value={id ?? value ?? ''}\n className={cn(\n 'sc:relative sc:z-10 sc:inline-flex sc:h-8 sc:items-center sc:justify-center sc:gap-2 sc:whitespace-nowrap sc:rounded-full sc:px-4 sc:text-sm sc:font-label',\n 'sc:transition-[color,opacity]',\n 'sc:focus-visible:outline-none sc:focus-visible:ring-2 sc:focus-visible:ring-focus sc:focus-visible:ring-offset-2',\n 'sc:disabled:pointer-events-none sc:disabled:opacity-50',\n 'sc:data-[state=active]:text-foreground sc:data-[state=active]:opacity-100',\n // Inactive tabs use element opacity (not color opacity) to avoid SVG path overlap issues\n isOnSurface\n ? 'sc:data-[state=inactive]:text-foreground sc:data-[state=inactive]:opacity-30 sc:data-[state=inactive]:hover:opacity-50'\n : 'sc:data-[state=inactive]:text-foreground sc:data-[state=inactive]:opacity-50 sc:data-[state=inactive]:hover:opacity-70',\n className\n )}\n {...props}\n />\n );\n }\n);\nTabsTrigger.displayName = TabsPrimitive.Trigger.displayName;\n\ninterface TabsContentProps extends Omit<React.ComponentPropsWithoutRef<typeof TabsPrimitive.Content>, 'value'> {\n // HeroUI uses 'id' for panel identification, Radix uses 'value'\n // At least one must be provided\n id?: string;\n value?: string;\n}\n\nconst TabsContent = React.forwardRef<React.ElementRef<typeof TabsPrimitive.Content>, TabsContentProps>(\n ({ className, id, value, ...props }, ref) => (\n <TabsPrimitive.Content\n ref={ref}\n value={id ?? value ?? ''}\n className={cn(\n 'sc:mt-2 sc:ring-offset-background sc:focus-visible:outline-none sc:focus-visible:ring-2 sc:focus-visible:ring-focus sc:focus-visible:ring-offset-2',\n className\n )}\n {...props}\n />\n )\n);\nTabsContent.displayName = TabsPrimitive.Content.displayName;\n\n// HeroUI ListContainer - wrapper for the tabs list (passthrough div)\nconst TabsListContainer = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(\n ({ className, ...props }, ref) => <div ref={ref} className={className} {...props} />\n);\nTabsListContainer.displayName = 'TabsListContainer';\n\n// HeroUI Tab - alias for TabsTrigger\nconst TabsTab = TabsTrigger;\n\n// HeroUI Panel - alias for TabsContent\nconst TabsPanel = TabsContent;\n\n// HeroUI Indicator - now rendered automatically by TabsList, this is a no-op\nconst TabsIndicator = () => null;\n\n// Create compound component with all aliases\nconst TabsBase = TabsRoot;\n\n// HeroUI-compatible compound component\nconst Tabs = Object.assign(TabsBase, {\n List: TabsList,\n ListContainer: TabsListContainer,\n Tab: TabsTab,\n Trigger: TabsTrigger,\n Panel: TabsPanel,\n Content: TabsContent,\n Indicator: TabsIndicator,\n});\n\nexport { Tabs, TabsList, TabsTrigger, TabsContent, TabsRoot };\n","'use client';\n\nimport * as React from 'react';\nimport { cn } from '../lib/utils';\n\nexport interface TextFieldProps extends React.HTMLAttributes<HTMLDivElement> {\n /**\n * Accessible label for the input.\n * If not provided via children, use aria-label on the div.\n */\n 'aria-label'?: string;\n /**\n * Error state - applies error styling to children inputs\n */\n isInvalid?: boolean;\n /**\n * Disabled state - disables all children inputs\n */\n disabled?: boolean;\n /**\n * Required state - marks all children inputs as required\n */\n required?: boolean;\n}\n\n/**\n * TextField - A wrapper component that groups Label and Input together.\n *\n * Groups Label and Input with a convenient wrapper that can propagate\n * disabled, required, and invalid states to child inputs.\n *\n * @example\n * ```tsx\n * <TextField>\n * <Label>Email</Label>\n * <Input type=\"email\" placeholder=\"Enter email...\" />\n * </TextField>\n * ```\n */\nconst TextField = React.forwardRef<HTMLDivElement, TextFieldProps>(\n ({ className, children, isInvalid, disabled, required, ...props }, ref) => {\n // Clone children to pass through state props to Input/Textarea children\n const enhancedChildren = React.Children.map(children, (child) => {\n if (!React.isValidElement(child)) return child;\n\n // Get the display name or type name to check if it's an input component\n const childType = child.type;\n const displayName =\n typeof childType === 'function'\n ? (childType as React.ComponentType).displayName || childType.name\n : typeof childType === 'string'\n ? childType\n : '';\n\n // Check if this is an input-like element that should receive state props\n const isInputElement =\n displayName === 'Input' ||\n displayName === 'Textarea' ||\n displayName === 'TextArea' ||\n displayName === 'input' ||\n displayName === 'textarea';\n\n if (isInputElement) {\n const childProps = child.props as Record<string, unknown>;\n return React.cloneElement(child as React.ReactElement<Record<string, unknown>>, {\n isInvalid: (childProps.isInvalid as boolean) ?? isInvalid,\n disabled: (childProps.disabled as boolean) ?? disabled,\n required: (childProps.required as boolean) ?? required,\n });\n }\n\n return child;\n });\n\n return (\n <div ref={ref} className={cn('sc:flex sc:flex-col sc:gap-1.5', className)} {...props}>\n {enhancedChildren}\n </div>\n );\n }\n);\nTextField.displayName = 'TextField';\n\nexport { TextField };\n","/**\n * Custom Icons - Centered versions of icons from various sets\n *\n * These are copies of icons with adjusted viewBox to center properly.\n * Use these instead of the original iconify versions for consistent alignment.\n */\n\nimport React from 'react';\nimport { cn } from '../../lib/utils';\n\ninterface IconProps {\n className?: string;\n size?: number | string;\n}\n\n/**\n * Rotate Left icon (lucide-style stroked version)\n */\nexport const RotateLeftIcon: React.FC<IconProps> = ({ className, size = 24 }) => (\n <svg\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n width={size}\n height={size}\n className={cn('sc:inline-block iconify', className)}\n >\n <path d=\"M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8\" />\n <path d=\"M3 3v5h5\" />\n </svg>\n);\n\n/**\n * Rotate Right icon (lucide-style stroked version)\n */\nexport const RotateRightIcon: React.FC<IconProps> = ({ className, size = 24 }) => (\n <svg\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n width={size}\n height={size}\n className={cn('sc:inline-block iconify', className)}\n >\n <path d=\"M21 12a9 9 0 1 1-9-9c2.52 0 4.93 1 6.74 2.74L21 8\" />\n <path d=\"M21 3v5h-5\" />\n </svg>\n);\n\n/**\n * Sparkles icon (based on gravity-ui:sparkles)\n * Two sparkle shapes - main 4-point star and smaller accent\n */\nexport const SparklesIcon: React.FC<IconProps> = ({ className, size = 24 }) => (\n <svg\n viewBox=\"0 0 28 28\"\n fill=\"currentColor\"\n width={size}\n height={size}\n className={cn('sc:inline-block', className)}\n >\n <path d=\"M10.06 18.701a1.628 1.628 0 0 0 2.43-.676l.77-2.34a3.82 3.82 0 0 1 2.416-2.418l2.238-.727a1.6 1.6 0 0 0 .786-.595a1.62 1.62 0 0 0-.849-2.489l-2.215-.72a3.82 3.82 0 0 1-2.42-2.414l-.727-2.237a1.62 1.62 0 0 0-.594-.785a1.655 1.655 0 0 0-1.879 0a1.63 1.63 0 0 0-.6.8L8.68 6.365a3.82 3.82 0 0 1-2.359 2.37l-2.24.726a1.626 1.626 0 0 0 .02 3.073l2.216.72a3.86 3.86 0 0 1 1.816 1.286c.266.343.471.728.606 1.14l.728 2.234c.112.318.32.593.595.787m-3.273-6.873l-2.22-.72s-.085-.038-.085-.108a.14.14 0 0 1 .084-.115L6.8 10.16a5.34 5.34 0 0 0 3.32-3.375l.721-2.219s.043-.084.114-.084s.113.084.113.084l.723 2.223a5.32 5.32 0 0 0 3.377 3.372l2.27.735a.13.13 0 0 1 .078.11a.15.15 0 0 1-.083.113l-2.225.722a5.32 5.32 0 0 0-3.374 3.374l-.715 2.2a.11.11 0 0 1-.115.093c-.104 0-.118-.075-.118-.075l-.723-2.22a5.32 5.32 0 0 0-3.376-3.385m13.017 12.954A1.2 1.2 0 0 0 20.5 25a1.2 1.2 0 0 0 .692-.216a1.2 1.2 0 0 0 .446-.6l.372-1.143a1.61 1.61 0 0 1 1.017-1.02l1.166-.378A1.21 1.21 0 0 0 25 20.505a1.2 1.2 0 0 0-.844-1.146l-1.144-.37a1.61 1.61 0 0 1-1.02-1.018l-.38-1.163a1.2 1.2 0 0 0-2.274.016l-.374 1.146a1.61 1.61 0 0 1-.993 1.017l-1.166.378a1.21 1.21 0 0 0-.807 1.139a1.2 1.2 0 0 0 .823 1.138l1.144.372a1.6 1.6 0 0 1 1.02 1.023l.379 1.163a1.2 1.2 0 0 0 .44.582m-1.371-4.194l-.27-.088l.283-.096a3.12 3.12 0 0 0 1.943-1.974l.088-.27l.089.272a3.11 3.11 0 0 0 1.974 1.975l.293.1l-.271.087a3.12 3.12 0 0 0-1.974 1.977l-.088.27l-.088-.272a3.12 3.12 0 0 0-1.98-1.98\" />\n </svg>\n);\n\n// Map of icon names to components for easy lookup\nexport const CustomIcons = {\n 'rotate-left': RotateLeftIcon,\n 'rotate-right': RotateRightIcon,\n 'sparkles': SparklesIcon,\n} as const;\n\nexport type CustomIconName = keyof typeof CustomIcons;\n"],"names":["Input","React","className","type","isInvalid","startContent","endContent","disabled","readOnly","required","variant","props","ref","surface","useSurface","isOnSurface","effectiveVariant","inputElement","jsx","cn","jsxs","labelVariants","cva","Label","LabelPrimitive","TabsRoot","value","onValueChange","TabsPrimitive","TabsList","children","listRef","indicatorStyle","setIndicatorStyle","listElement","updateIndicator","activeTab","listRect","tabRect","observer","mutations","mutation","trigger","resizeObserver","node","TabsTrigger","id","surfaceVariant","TabsContent","TabsListContainer","TabsTab","TabsPanel","TabsIndicator","TabsBase","Tabs","TextField","enhancedChildren","child","childType","displayName","childProps","RotateLeftIcon","size","SparklesIcon"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { g as l } from "./editorErrors-BhrZ_nwj.js";
1
+ import { g as l } from "./editorErrors-CCvoKj_P.js";
2
2
  const x = 1;
3
3
  function d(e) {
4
4
  return typeof e == "number" && Number.isFinite(e) ? Math.round(e * 100) / 100 : e;
@@ -467,4 +467,4 @@ export {
467
467
  F as l,
468
468
  O as s
469
469
  };
470
- //# sourceMappingURL=design-builder-cZY958Rw.js.map
470
+ //# sourceMappingURL=design-builder-COj0zkxu.js.map