@molecule/app-ui 1.2.1 → 1.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -3,7 +3,7 @@ AUTO-GENERATED — DO NOT EDIT THIS FILE.
3
3
  Generated by `mlcl sync-docs` from the package's src/index.ts JSDoc + mlcl/registry.json.
4
4
  Edits here are overwritten on the next commit (molecule's pre-commit hook regenerates).
5
5
  To change this document, edit the module-level JSDoc in src/index.ts.
6
- Generated: 2026-09-26T19:12:00.625Z
6
+ Generated: 2026-09-27T09:13:41.545Z
7
7
  -->
8
8
 
9
9
  # @molecule/app-ui
@@ -1046,6 +1046,64 @@ interface ModalProps extends HTMLElementProps {
1046
1046
  }
1047
1047
  ```
1048
1048
 
1049
+ #### `MoleculeSpinnerColors`
1050
+
1051
+ Gradient-mode colors. Any CSS color string, including `var()` forms.
1052
+
1053
+ ```typescript
1054
+ interface MoleculeSpinnerColors {
1055
+ /** Bond base / glint tail color. */
1056
+ blue?: string
1057
+ /** Flow highlight / glint head color at rest. */
1058
+ light?: string
1059
+ /** Glint ignition color while an atom is in flight. */
1060
+ peach?: string
1061
+ }
1062
+ ```
1063
+
1064
+ #### `MoleculeSpinnerMarkOptions`
1065
+
1066
+ Options for {@link moleculeSpinnerMarkSvg}.
1067
+
1068
+ ```typescript
1069
+ interface MoleculeSpinnerMarkOptions {
1070
+ /** Motion timings; defaults to the shipped design (2.5s / 5s / 3s). */
1071
+ timings?: Partial<MoleculeSpinnerTimings>
1072
+ /** `gradient` (default) or `mono` — plain `currentColor` outline, no defs. */
1073
+ paint?: 'gradient' | 'mono'
1074
+ /** Gradient-mode colors; default the `var(--mol-spin-*, fallback)` set. */
1075
+ colors?: MoleculeSpinnerColors
1076
+ /**
1077
+ * Gradient id for url() references. Must be unique per rendered instance
1078
+ * on a page. Defaults to `mol-spinner-gradient`.
1079
+ */
1080
+ gradientId?: string
1081
+ /** Pixel size baked into width/height; omit when CSS sizes the svg. */
1082
+ size?: number
1083
+ /** Class attribute for the svg element. */
1084
+ className?: string
1085
+ /** Inline style attribute (already serialized, e.g. `color:re$d`). */
1086
+ style?: string
1087
+ /** Announce as `role="status"` with this label; omit for `aria-hidden`. */
1088
+ ariaLabel?: string
1089
+ }
1090
+ ```
1091
+
1092
+ #### `MoleculeSpinnerTimings`
1093
+
1094
+ The mark's timings, in CSS duration strings. Swap cycle → glint cycle.
1095
+
1096
+ ```typescript
1097
+ interface MoleculeSpinnerTimings {
1098
+ /** One full 3-phase atom-swap cycle (also drives bond fades + glints). */
1099
+ dur: string
1100
+ /** Whole-figure rotation. Keep at two swap cycles for the intended feel. */
1101
+ spin: string
1102
+ /** Bond gradient flow period (one full translate across the figure). */
1103
+ flow: string
1104
+ }
1105
+ ```
1106
+
1049
1107
  #### `PageHeaderProps`
1050
1108
 
1051
1109
  Props for the PageHeader component — consistent page title area.
@@ -2968,6 +3026,19 @@ function hasProvider(): boolean
2968
3026
 
2969
3027
  **Returns:** `true` if a UI provider is bonded.
2970
3028
 
3029
+ #### `moleculeSpinnerMarkSvg(options)`
3030
+
3031
+ The molecule spinner mark as a complete SVG element string (SMIL-animated,
3032
+ framework-agnostic). See the module docblock for usage and gotchas.
3033
+
3034
+ ```typescript
3035
+ function moleculeSpinnerMarkSvg(options?: MoleculeSpinnerMarkOptions): string
3036
+ ```
3037
+
3038
+ - `options` — Paint, timings, size, gradient id and a11y shape.
3039
+
3040
+ **Returns:** A `<svg>…</svg>` markup string.
3041
+
2971
3042
  #### `molId(component, context, qualifier)`
2972
3043
 
2973
3044
  Generate a semantic automation ID for a component.
package/dist/index.d.ts CHANGED
@@ -44,6 +44,7 @@
44
44
  export * from './automation.js';
45
45
  export * from './components.js';
46
46
  export * from './provider.js';
47
+ export * from './spinner.js';
47
48
  export * from './types.js';
48
49
  export * from './utilities.js';
49
50
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AAEH,cAAc,iBAAiB,CAAA;AAC/B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,eAAe,CAAA;AAC7B,cAAc,YAAY,CAAA;AAC1B,cAAc,gBAAgB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AAEH,cAAc,iBAAiB,CAAA;AAC/B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,eAAe,CAAA;AAC7B,cAAc,cAAc,CAAA;AAC5B,cAAc,YAAY,CAAA;AAC1B,cAAc,gBAAgB,CAAA"}
package/dist/index.js CHANGED
@@ -44,6 +44,7 @@
44
44
  export * from './automation.js';
45
45
  export * from './components.js';
46
46
  export * from './provider.js';
47
+ export * from './spinner.js';
47
48
  export * from './types.js';
48
49
  export * from './utilities.js';
49
50
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AAEH,cAAc,iBAAiB,CAAA;AAC/B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,eAAe,CAAA;AAC7B,cAAc,YAAY,CAAA;AAC1B,cAAc,gBAAgB,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AAEH,cAAc,iBAAiB,CAAA;AAC/B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,eAAe,CAAA;AAC7B,cAAc,cAAc,CAAA;AAC5B,cAAc,YAAY,CAAA;AAC1B,cAAc,gBAAgB,CAAA"}
@@ -0,0 +1,109 @@
1
+ /**
2
+ * The molecule spinner mark — the platform's animated loading glyph, as one
3
+ * framework-agnostic SVG string.
4
+ *
5
+ * This module is the SINGLE source of truth for the mark's geometry, motion
6
+ * and paint. Every surface that spins it — the IDE app's `MoleculeSpinner`,
7
+ * the AI streaming indicator (`@molecule/app-ide-react`), and the "Built with
8
+ * Molecule.dev" attribution badge injected into deployed apps — renders
9
+ * {@link moleculeSpinnerMarkSvg} output rather than keeping a copy. Before
10
+ * this existed, four hand-maintained copies drifted into three different
11
+ * looks; if you are tempted to inline this SVG somewhere, import this instead.
12
+ *
13
+ * @remarks
14
+ * **What it renders** — a complete `<svg>…</svg>` element string driven by
15
+ * SMIL (no JS runtime, no CSS keyframes), safe to inject with
16
+ * `innerHTML`/`insertAdjacentHTML` in any framework or none:
17
+ * - a 3-phase atom-swap cycle (one outer atom exchanges with the hub per
18
+ * phase; the connecting bond fades for the swap);
19
+ * - a slow hub-centered whole-figure rotation;
20
+ * - paint: a seamless one-way blue gradient flow on the bonds plus per-atom
21
+ * "glint" gradients whose light end warms exactly while that atom is in
22
+ * flight (keyed to the same keyTimes/easing as the motion), or a plain
23
+ * `currentColor` outline via `paint: 'mono'`.
24
+ *
25
+ * **Gotchas a weak executor gets wrong:**
26
+ * - `gradientId` must be unique per rendered instance on a page — two svgs
27
+ * sharing one id cross-reference each other's gradients. React wrappers
28
+ * should pass something derived from `useId()` (strip `:` first).
29
+ * - Default colors are CSS-var-with-fallback strings
30
+ * (`var(--mol-spin-blue, #4f86f0)`), which theme via `--mol-spin-*` where
31
+ * they exist (e.g. the molecule.dev landing page) and fall back to the
32
+ * literal palette elsewhere. Injected into third-party pages (the
33
+ * attribution badge) they must be overridden with literal hexes — the vars
34
+ * do not exist there.
35
+ * - The glyph matrix x-translate (`-.78879`) deliberately differs from the
36
+ * static favicon's (`.81594`): it puts the molecule's hub exactly on the
37
+ * rotation center (16,16) so the spin never wobbles. Do not "fix" it.
38
+ * - `ariaLabel` produces `role="status"`; omit it for decorative uses, which
39
+ * get `aria-hidden="true"` instead. Never emit both.
40
+ *
41
+ * @example
42
+ * ```ts
43
+ * import { moleculeSpinnerMarkSvg } from '@molecule/app-ui'
44
+ *
45
+ * // themed, unique per instance
46
+ * const svg = moleculeSpinnerMarkSvg({ size: 24, gradientId: 'spin-1', ariaLabel: 'Loading' })
47
+ *
48
+ * // monochrome, inherits the surrounding text color
49
+ * const mono = moleculeSpinnerMarkSvg({ size: 16, paint: 'mono' })
50
+ *
51
+ * // third-party page (no --mol-spin-* vars): literal colors, CSS-sized
52
+ * const badge = moleculeSpinnerMarkSvg({
53
+ * gradientId: 'mol-badge-grad',
54
+ * className: 'mol-badge-mark',
55
+ * colors: { blue: '#4f86f0', light: '#6e9bf5', peach: '#e0975a' },
56
+ * })
57
+ * ```
58
+ *
59
+ * @module
60
+ */
61
+ /** The mark's timings, in CSS duration strings. Swap cycle → glint cycle. */
62
+ export interface MoleculeSpinnerTimings {
63
+ /** One full 3-phase atom-swap cycle (also drives bond fades + glints). */
64
+ dur: string;
65
+ /** Whole-figure rotation. Keep at two swap cycles for the intended feel. */
66
+ spin: string;
67
+ /** Bond gradient flow period (one full translate across the figure). */
68
+ flow: string;
69
+ }
70
+ /** Gradient-mode colors. Any CSS color string, including `var()` forms. */
71
+ export interface MoleculeSpinnerColors {
72
+ /** Bond base / glint tail color. */
73
+ blue?: string;
74
+ /** Flow highlight / glint head color at rest. */
75
+ light?: string;
76
+ /** Glint ignition color while an atom is in flight. */
77
+ peach?: string;
78
+ }
79
+ /** Options for {@link moleculeSpinnerMarkSvg}. */
80
+ export interface MoleculeSpinnerMarkOptions {
81
+ /** Motion timings; defaults to the shipped design (2.5s / 5s / 3s). */
82
+ timings?: Partial<MoleculeSpinnerTimings>;
83
+ /** `gradient` (default) or `mono` — plain `currentColor` outline, no defs. */
84
+ paint?: 'gradient' | 'mono';
85
+ /** Gradient-mode colors; default the `var(--mol-spin-*, fallback)` set. */
86
+ colors?: MoleculeSpinnerColors;
87
+ /**
88
+ * Gradient id for url() references. Must be unique per rendered instance
89
+ * on a page. Defaults to `mol-spinner-gradient`.
90
+ */
91
+ gradientId?: string;
92
+ /** Pixel size baked into width/height; omit when CSS sizes the svg. */
93
+ size?: number;
94
+ /** Class attribute for the svg element. */
95
+ className?: string;
96
+ /** Inline style attribute (already serialized, e.g. `color:re$d`). */
97
+ style?: string;
98
+ /** Announce as `role="status"` with this label; omit for `aria-hidden`. */
99
+ ariaLabel?: string;
100
+ }
101
+ /**
102
+ * The molecule spinner mark as a complete SVG element string (SMIL-animated,
103
+ * framework-agnostic). See the module docblock for usage and gotchas.
104
+ *
105
+ * @param options - Paint, timings, size, gradient id and a11y shape.
106
+ * @returns A `<svg>…</svg>` markup string.
107
+ */
108
+ export declare function moleculeSpinnerMarkSvg(options?: MoleculeSpinnerMarkOptions): string;
109
+ //# sourceMappingURL=spinner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spinner.d.ts","sourceRoot":"","sources":["../src/spinner.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2DG;AAEH,6EAA6E;AAC7E,MAAM,WAAW,sBAAsB;IACrC,0EAA0E;IAC1E,GAAG,EAAE,MAAM,CAAA;IACX,4EAA4E;IAC5E,IAAI,EAAE,MAAM,CAAA;IACZ,wEAAwE;IACxE,IAAI,EAAE,MAAM,CAAA;CACb;AAED,2EAA2E;AAC3E,MAAM,WAAW,qBAAqB;IACpC,oCAAoC;IACpC,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,iDAAiD;IACjD,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,uDAAuD;IACvD,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED,kDAAkD;AAClD,MAAM,WAAW,0BAA0B;IACzC,uEAAuE;IACvE,OAAO,CAAC,EAAE,OAAO,CAAC,sBAAsB,CAAC,CAAA;IACzC,8EAA8E;IAC9E,KAAK,CAAC,EAAE,UAAU,GAAG,MAAM,CAAA;IAC3B,2EAA2E;IAC3E,MAAM,CAAC,EAAE,qBAAqB,CAAA;IAC9B;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,uEAAuE;IACvE,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,2CAA2C;IAC3C,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,sEAAsE;IACtE,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,2EAA2E;IAC3E,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AA0HD;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,GAAE,0BAA+B,GAAG,MAAM,CAsEvF"}
@@ -0,0 +1,235 @@
1
+ /**
2
+ * The molecule spinner mark — the platform's animated loading glyph, as one
3
+ * framework-agnostic SVG string.
4
+ *
5
+ * This module is the SINGLE source of truth for the mark's geometry, motion
6
+ * and paint. Every surface that spins it — the IDE app's `MoleculeSpinner`,
7
+ * the AI streaming indicator (`@molecule/app-ide-react`), and the "Built with
8
+ * Molecule.dev" attribution badge injected into deployed apps — renders
9
+ * {@link moleculeSpinnerMarkSvg} output rather than keeping a copy. Before
10
+ * this existed, four hand-maintained copies drifted into three different
11
+ * looks; if you are tempted to inline this SVG somewhere, import this instead.
12
+ *
13
+ * @remarks
14
+ * **What it renders** — a complete `<svg>…</svg>` element string driven by
15
+ * SMIL (no JS runtime, no CSS keyframes), safe to inject with
16
+ * `innerHTML`/`insertAdjacentHTML` in any framework or none:
17
+ * - a 3-phase atom-swap cycle (one outer atom exchanges with the hub per
18
+ * phase; the connecting bond fades for the swap);
19
+ * - a slow hub-centered whole-figure rotation;
20
+ * - paint: a seamless one-way blue gradient flow on the bonds plus per-atom
21
+ * "glint" gradients whose light end warms exactly while that atom is in
22
+ * flight (keyed to the same keyTimes/easing as the motion), or a plain
23
+ * `currentColor` outline via `paint: 'mono'`.
24
+ *
25
+ * **Gotchas a weak executor gets wrong:**
26
+ * - `gradientId` must be unique per rendered instance on a page — two svgs
27
+ * sharing one id cross-reference each other's gradients. React wrappers
28
+ * should pass something derived from `useId()` (strip `:` first).
29
+ * - Default colors are CSS-var-with-fallback strings
30
+ * (`var(--mol-spin-blue, #4f86f0)`), which theme via `--mol-spin-*` where
31
+ * they exist (e.g. the molecule.dev landing page) and fall back to the
32
+ * literal palette elsewhere. Injected into third-party pages (the
33
+ * attribution badge) they must be overridden with literal hexes — the vars
34
+ * do not exist there.
35
+ * - The glyph matrix x-translate (`-.78879`) deliberately differs from the
36
+ * static favicon's (`.81594`): it puts the molecule's hub exactly on the
37
+ * rotation center (16,16) so the spin never wobbles. Do not "fix" it.
38
+ * - `ariaLabel` produces `role="status"`; omit it for decorative uses, which
39
+ * get `aria-hidden="true"` instead. Never emit both.
40
+ *
41
+ * @example
42
+ * ```ts
43
+ * import { moleculeSpinnerMarkSvg } from '@molecule/app-ui'
44
+ *
45
+ * // themed, unique per instance
46
+ * const svg = moleculeSpinnerMarkSvg({ size: 24, gradientId: 'spin-1', ariaLabel: 'Loading' })
47
+ *
48
+ * // monochrome, inherits the surrounding text color
49
+ * const mono = moleculeSpinnerMarkSvg({ size: 16, paint: 'mono' })
50
+ *
51
+ * // third-party page (no --mol-spin-* vars): literal colors, CSS-sized
52
+ * const badge = moleculeSpinnerMarkSvg({
53
+ * gradientId: 'mol-badge-grad',
54
+ * className: 'mol-badge-mark',
55
+ * colors: { blue: '#4f86f0', light: '#6e9bf5', peach: '#e0975a' },
56
+ * })
57
+ * ```
58
+ *
59
+ * @module
60
+ */
61
+ const DEFAULT_TIMINGS = {
62
+ dur: '2.5s',
63
+ spin: '5s',
64
+ flow: '3s',
65
+ };
66
+ const DEFAULT_COLORS = {
67
+ blue: 'var(--mol-spin-blue, #4f86f0)',
68
+ light: 'var(--mol-spin-blue-light, #6e9bf5)',
69
+ peach: 'var(--mol-spin-peach, #e0975a)',
70
+ };
71
+ const EASE = '0.42 0 0.58 1';
72
+ const LIN = '0 0 1 1';
73
+ /** Bond fade keyframes, one per phase, phase-locked to the swap they serve. */
74
+ const BONDS = [
75
+ {
76
+ // Center–Left — fades during Phase 1
77
+ x1: 16.494,
78
+ x2: 8.563,
79
+ y1: 16,
80
+ y2: 16,
81
+ values: '1;0;0;1;1',
82
+ keyTimes: '0;0.033;0.167;0.217;1',
83
+ keySplines: [EASE, LIN, EASE, LIN].join(';'),
84
+ },
85
+ {
86
+ // Center–Bottom-right — fades during Phase 2
87
+ x1: 20.959,
88
+ x2: 24.924,
89
+ y1: 18.579,
90
+ y2: 25.446,
91
+ values: '1;1;0;0;1;1',
92
+ keyTimes: '0;0.333;0.367;0.500;0.550;1',
93
+ keySplines: [LIN, EASE, LIN, EASE, LIN].join(';'),
94
+ },
95
+ {
96
+ // Center–Top-right — fades during Phase 3
97
+ x1: 20.959,
98
+ x2: 24.924,
99
+ y1: 13.422,
100
+ y2: 6.555,
101
+ values: '1;1;0;0;1;1',
102
+ keyTimes: '0;0.667;0.700;0.833;0.883;1',
103
+ keySplines: [LIN, EASE, LIN, EASE, LIN].join(';'),
104
+ },
105
+ ];
106
+ /**
107
+ * Atom swap trajectories: cx/cy keyframe lists per atom, plus the glint pulse
108
+ * for its gradient (LIGHT at rest, peach at each flight's midpoint — the same
109
+ * anchors and easing the position animation uses, so the glint is frame-locked
110
+ * to every swap). Atoms are visually identical, so the loop-boundary jump is
111
+ * imperceptible.
112
+ */
113
+ const ATOMS = [
114
+ {
115
+ // Center → Left (Phase 1), holds
116
+ cx: 19.47,
117
+ cy: 16,
118
+ cxValues: '19.47;19.47;5.587;5.587',
119
+ cyValues: null,
120
+ keyTimes: '0;0.033;0.167;1',
121
+ keySplines: [LIN, EASE, LIN].join(';'),
122
+ glintValues: [1, 1, 0, 1, 1], // indexes into [light, peach]
123
+ glintKeyTimes: '0;0.033;0.1;0.167;1',
124
+ glintSplines: [LIN, EASE, EASE, LIN].join(';'),
125
+ },
126
+ {
127
+ // Left → Center (Phase 1), Center → BR (Phase 2), holds
128
+ cx: 5.587,
129
+ cy: 16,
130
+ cxValues: '5.587;5.587;19.47;19.47;26.412;26.412',
131
+ cyValues: '16;16;16;16;28.023;28.023',
132
+ keyTimes: '0;0.033;0.167;0.367;0.500;1',
133
+ keySplines: [LIN, EASE, LIN, EASE, LIN].join(';'),
134
+ glintValues: [1, 1, 0, 1, 1, 0, 1, 1],
135
+ glintKeyTimes: '0;0.033;0.1;0.167;0.367;0.434;0.5;1',
136
+ glintSplines: [LIN, EASE, EASE, LIN, EASE, EASE, LIN].join(';'),
137
+ },
138
+ {
139
+ // BR → Center (Phase 2), Center → TR (Phase 3), holds
140
+ cx: 26.412,
141
+ cy: 28.023,
142
+ cxValues: '26.412;26.412;19.47;19.47;26.412;26.412',
143
+ cyValues: '28.023;28.023;16;16;3.977;3.977',
144
+ keyTimes: '0;0.367;0.500;0.700;0.833;1',
145
+ keySplines: [LIN, EASE, LIN, EASE, LIN].join(';'),
146
+ glintValues: [1, 1, 0, 1, 1, 0, 1, 1],
147
+ glintKeyTimes: '0;0.367;0.434;0.5;0.7;0.767;0.833;1',
148
+ glintSplines: [LIN, EASE, EASE, LIN, EASE, EASE, LIN].join(';'),
149
+ },
150
+ {
151
+ // TR → Center (Phase 3), holds
152
+ cx: 26.412,
153
+ cy: 3.977,
154
+ cxValues: '26.412;26.412;19.47;19.47',
155
+ cyValues: '3.977;3.977;16;16',
156
+ keyTimes: '0;0.700;0.833;1',
157
+ keySplines: [LIN, EASE, LIN].join(';'),
158
+ glintValues: [1, 1, 0, 1, 1],
159
+ glintKeyTimes: '0;0.7;0.767;0.833;1',
160
+ glintSplines: [LIN, EASE, EASE, LIN].join(';'),
161
+ },
162
+ ];
163
+ /**
164
+ * Minimal attribute-value escaping for {@link MoleculeSpinnerMarkOptions.ariaLabel}
165
+ * — the one option that can carry free text. Developer-supplied options
166
+ * (`className`, `style`, `gradientId`, colors) are interpolated verbatim.
167
+ */
168
+ function escapeAttr(value) {
169
+ return value
170
+ .replace(/&/g, '&amp;')
171
+ .replace(/"/g, '&quot;')
172
+ .replace(/</g, '&lt;')
173
+ .replace(/>/g, '&gt;');
174
+ }
175
+ /**
176
+ * The molecule spinner mark as a complete SVG element string (SMIL-animated,
177
+ * framework-agnostic). See the module docblock for usage and gotchas.
178
+ *
179
+ * @param options - Paint, timings, size, gradient id and a11y shape.
180
+ * @returns A `<svg>…</svg>` markup string.
181
+ */
182
+ export function moleculeSpinnerMarkSvg(options = {}) {
183
+ const timings = { ...DEFAULT_TIMINGS, ...options.timings };
184
+ const colors = { ...DEFAULT_COLORS, ...options.colors };
185
+ const gradientId = options.gradientId ?? 'mol-spinner-gradient';
186
+ const gradient = (options.paint ?? 'gradient') === 'gradient';
187
+ const sizeAttrs = options.size !== undefined ? ` width="${options.size}" height="${options.size}"` : '';
188
+ const classAttrs = options.className ? ` class="${options.className}"` : '';
189
+ const styleAttr = options.style ? ` style="${options.style}"` : '';
190
+ const a11yAttrs = options.ariaLabel
191
+ ? ` role="status" aria-label="${escapeAttr(options.ariaLabel)}"`
192
+ : ' aria-hidden="true"';
193
+ const defs = gradient
194
+ ? '<defs>' +
195
+ `<linearGradient id="${gradientId}" gradientUnits="userSpaceOnUse" x1="0" y1="16" x2="32" y2="16" spreadMethod="repeat">` +
196
+ `<stop offset="0" stop-color="${colors.blue}"/>` +
197
+ `<stop offset="0.5" stop-color="${colors.light}"/>` +
198
+ `<stop offset="1" stop-color="${colors.blue}"/>` +
199
+ `<animateTransform attributeName="gradientTransform" type="translate" values="0 0; 32 0" dur="${timings.flow}" repeatCount="indefinite"/>` +
200
+ '</linearGradient>' +
201
+ ATOMS.map((atom, i) => `<linearGradient id="${gradientId}-a${i}" x1="0" y1="0" x2="1" y2="1">` +
202
+ // The warm glint animates stop-OPACITY of a peach head stop laid
203
+ // over the light base — NEVER stop-color. SMIL interpolates colors
204
+ // numerically, and `var()` color strings cannot interpolate, so a
205
+ // color animation silently dies and the gradient paints flat (the
206
+ // 1.3.0 production bug); opacity is numeric and always works, with
207
+ // any palette form (var() or literal).
208
+ `<stop offset="0" stop-color="${colors.peach}">` +
209
+ `<animate attributeName="stop-opacity" dur="${timings.dur}" repeatCount="indefinite" values="${atom.glintValues.map((v) => (v ? 0 : 1)).join(';')}" keyTimes="${atom.glintKeyTimes}" calcMode="spline" keySplines="${atom.glintSplines}"/>` +
210
+ '</stop>' +
211
+ `<stop offset="0.3" stop-color="${colors.light}"/>` +
212
+ `<stop offset="1" stop-color="${colors.blue}"/>` +
213
+ '</linearGradient>').join('') +
214
+ '</defs>'
215
+ : '';
216
+ const groupStroke = gradient ? `url(#${gradientId})` : 'currentColor';
217
+ const bonds = BONDS.map((bond) => `<line x1="${bond.x1}" x2="${bond.x2}" y1="${bond.y1}" y2="${bond.y2}">` +
218
+ `<animate attributeName="opacity" dur="${timings.dur}" repeatCount="indefinite" values="${bond.values}" keyTimes="${bond.keyTimes}" calcMode="spline" keySplines="${bond.keySplines}"/>` +
219
+ '</line>').join('');
220
+ const atoms = ATOMS.map((atom, i) => `<circle cx="${atom.cx}" cy="${atom.cy}" r="2.976"${gradient ? ` stroke="url(#${gradientId}-a${i})"` : ''}>` +
221
+ `<animate attributeName="cx" dur="${timings.dur}" repeatCount="indefinite" values="${atom.cxValues}" keyTimes="${atom.keyTimes}" calcMode="spline" keySplines="${atom.keySplines}"/>` +
222
+ (atom.cyValues
223
+ ? `<animate attributeName="cy" dur="${timings.dur}" repeatCount="indefinite" values="${atom.cyValues}" keyTimes="${atom.keyTimes}" calcMode="spline" keySplines="${atom.keySplines}"/>`
224
+ : '') +
225
+ '</circle>').join('');
226
+ return (`<svg xmlns="http://www.w3.org/2000/svg"${sizeAttrs}${classAttrs}${styleAttr}` +
227
+ ` viewBox="0 0 32 32"${a11yAttrs} focusable="false">` +
228
+ defs +
229
+ `<g><animateTransform attributeName="transform" type="rotate" from="0 16 16" to="360 16 16" dur="${timings.spin}" repeatCount="indefinite"/>` +
230
+ `<g transform="matrix(.86229 0 0 .86229 -.78879 2.2034)" stroke="${groupStroke}" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" stroke-width="2.4737" fill="none">` +
231
+ bonds +
232
+ atoms +
233
+ '</g></g></svg>');
234
+ }
235
+ //# sourceMappingURL=spinner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spinner.js","sourceRoot":"","sources":["../src/spinner.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@molecule/app-ui",
3
- "version": "1.2.1",
3
+ "version": "1.3.1",
4
4
  "description": "UI component interfaces for molecule.dev",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",