@stealthscale/component-feedback 0.2.1 → 0.2.3

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 (37) hide show
  1. package/dist/cyclonedx/bom.json +1 -1
  2. package/dist/index.js +1 -1825
  3. package/dist/pages/alert/alert.js +223 -0
  4. package/dist/pages/alert/alert.props.js +3 -0
  5. package/dist/pages/empty-state/empty-state.js +96 -0
  6. package/dist/pages/empty-state/empty-state.props.js +3 -0
  7. package/dist/pages/loader/loader.js +359 -0
  8. package/dist/pages/loader/loader.props.js +3 -0
  9. package/dist/pages/meter/meter.js +785 -0
  10. package/dist/pages/meter/meter.props.js +3 -0
  11. package/dist/pages/pages.json +115 -0
  12. package/dist/pages/progress/progress.js +550 -0
  13. package/dist/pages/progress/progress.props.js +3 -0
  14. package/dist/pages/progress-circle/progress-circle.js +329 -0
  15. package/dist/pages/progress-circle/progress-circle.props.js +3 -0
  16. package/dist/pages/skeleton/skeleton.js +94 -0
  17. package/dist/pages/skeleton/skeleton.props.js +3 -0
  18. package/dist/pages/skeleton-text/skeleton-text.js +81 -0
  19. package/dist/pages/skeleton-text/skeleton-text.props.js +3 -0
  20. package/dist/pages/spinner/spinner.js +186 -0
  21. package/dist/pages/spinner/spinner.props.js +3 -0
  22. package/dist/pages/toast/toast.js +427 -0
  23. package/dist/pages/toast/toast.props.js +3 -0
  24. package/dist/shared-Xc-n0bn7.js +1826 -0
  25. package/dist/theme.js +27 -13
  26. package/locales/en/specimen/alert.json +37 -0
  27. package/locales/en/specimen/empty-state.json +10 -0
  28. package/locales/en/specimen/loader.json +30 -0
  29. package/locales/en/specimen/meter.json +81 -0
  30. package/locales/en/specimen/progress-circle.json +41 -0
  31. package/locales/en/specimen/progress.json +66 -0
  32. package/locales/en/specimen/skeleton-text.json +12 -0
  33. package/locales/en/specimen/skeleton.json +18 -0
  34. package/locales/en/specimen/spinner.json +33 -0
  35. package/locales/en/specimen/toast.json +79 -0
  36. package/package.json +8 -7
  37. /package/dist/{recipe-CX1gSsN7.js → recipes-CX1gSsN7.js} +0 -0
@@ -0,0 +1,785 @@
1
+ import { t as __exportAll } from "../../rolldown-runtime-D7D4PA-g.js";
2
+ import { a as recipe } from "../../recipes-CX1gSsN7.js";
3
+ import { A as Root, D as Range, E as Segment, O as Marker, T as Track, k as Label, w as ValueText } from "../../shared-Xc-n0bn7.js";
4
+ import { c } from "react/compiler-runtime";
5
+ import { jsx, jsxs } from "react/jsx-runtime";
6
+ import { useState } from "react";
7
+ import { Room, scenesOf, specimen, useWords } from "@stealthscale/specimen";
8
+ import { Stack } from "@stealthscale/component-layout";
9
+ import { Text } from "@stealthscale/component-typography";
10
+ import { ColorSwatch } from "@stealthscale/component-data";
11
+ import { Field } from "@stealthscale/component-forms";
12
+ //#region src/meter/examples/capacity.example.tsx
13
+ var capacity_example_exports = /* @__PURE__ */ __exportAll({
14
+ Capacity: () => Capacity,
15
+ source: () => source$5
16
+ });
17
+ const SIZE = 256;
18
+ const PARTS = [
19
+ {
20
+ key: "photos",
21
+ value: 88.2
22
+ },
23
+ {
24
+ key: "apps",
25
+ value: 41.5
26
+ },
27
+ {
28
+ key: "system",
29
+ value: 18.3
30
+ },
31
+ {
32
+ key: "other",
33
+ value: 9.6
34
+ }
35
+ ];
36
+ const USED = PARTS.reduce((sum, part) => sum + part.value, 0);
37
+ function Capacity() {
38
+ const $ = c(22);
39
+ const { t } = useWords("meter");
40
+ let t0;
41
+ if ($[0] !== t) {
42
+ t0 = t("capacity.value", {
43
+ size: SIZE,
44
+ used: USED
45
+ });
46
+ $[0] = t;
47
+ $[1] = t0;
48
+ } else t0 = $[1];
49
+ const words = t0;
50
+ let t1;
51
+ if ($[2] !== t) {
52
+ t1 = t("capacity.label");
53
+ $[2] = t;
54
+ $[3] = t1;
55
+ } else t1 = $[3];
56
+ let t2;
57
+ if ($[4] !== t1) {
58
+ t2 = /* @__PURE__ */ jsx(Label, { children: t1 });
59
+ $[4] = t1;
60
+ $[5] = t2;
61
+ } else t2 = $[5];
62
+ let t3;
63
+ if ($[6] !== words) {
64
+ t3 = /* @__PURE__ */ jsx(ValueText, { children: words });
65
+ $[6] = words;
66
+ $[7] = t3;
67
+ } else t3 = $[7];
68
+ let t4;
69
+ if ($[8] === Symbol.for("react.memo_cache_sentinel")) {
70
+ t4 = PARTS.map(_temp$1);
71
+ $[8] = t4;
72
+ } else t4 = $[8];
73
+ let t5;
74
+ if ($[9] !== words) {
75
+ t5 = /* @__PURE__ */ jsx(Track, {
76
+ "aria-valuetext": words,
77
+ children: t4
78
+ });
79
+ $[9] = words;
80
+ $[10] = t5;
81
+ } else t5 = $[10];
82
+ let t6;
83
+ if ($[11] !== t2 || $[12] !== t3 || $[13] !== t5) {
84
+ t6 = /* @__PURE__ */ jsxs(Root, {
85
+ max: SIZE,
86
+ value: USED,
87
+ children: [
88
+ t2,
89
+ t3,
90
+ t5
91
+ ]
92
+ });
93
+ $[11] = t2;
94
+ $[12] = t3;
95
+ $[13] = t5;
96
+ $[14] = t6;
97
+ } else t6 = $[14];
98
+ let t7;
99
+ if ($[15] !== t) {
100
+ t7 = PARTS.map((t8, at) => {
101
+ const { key: key_0, value: value_0 } = t8;
102
+ return /* @__PURE__ */ jsxs(Text, {
103
+ as: "span",
104
+ size: "xs",
105
+ children: [
106
+ /* @__PURE__ */ jsx(ColorSwatch, {
107
+ "aria-hidden": true,
108
+ shape: "circle",
109
+ size: "inherit",
110
+ value: `var(--colors-series-${String(at + 1)})`
111
+ }),
112
+ " ",
113
+ t(`capacity.${key_0}`, { value: value_0 })
114
+ ]
115
+ }, key_0);
116
+ });
117
+ $[15] = t;
118
+ $[16] = t7;
119
+ } else t7 = $[16];
120
+ let t8;
121
+ if ($[17] !== t7) {
122
+ t8 = /* @__PURE__ */ jsx(Stack, {
123
+ direction: "row",
124
+ gap: "md",
125
+ wrap: true,
126
+ children: t7
127
+ });
128
+ $[17] = t7;
129
+ $[18] = t8;
130
+ } else t8 = $[18];
131
+ let t9;
132
+ if ($[19] !== t6 || $[20] !== t8) {
133
+ t9 = /* @__PURE__ */ jsxs(Stack, {
134
+ gap: "sm",
135
+ children: [t6, t8]
136
+ });
137
+ $[19] = t6;
138
+ $[20] = t8;
139
+ $[21] = t9;
140
+ } else t9 = $[21];
141
+ return t9;
142
+ }
143
+ function _temp$1(t0) {
144
+ const { key, value } = t0;
145
+ return /* @__PURE__ */ jsx(Segment, { value }, key);
146
+ }
147
+ const source$5 = "import { type ReactElement } from \"react\";\n\nimport { ColorSwatch } from \"@stealthscale/component-data\";\nimport { Stack } from \"@stealthscale/component-layout\";\nimport { Text } from \"@stealthscale/component-typography\";\nimport { useWords } from \"@stealthscale/specimen\";\n\nimport { Meter } from \"@stealthscale/component-feedback\";\n\nconst SIZE = 256;\n\nconst PARTS = [\n { key: \"photos\", value: 88.2 },\n { key: \"apps\", value: 41.5 },\n { key: \"system\", value: 18.3 },\n { key: \"other\", value: 9.6 },\n] as const;\n\nconst USED = PARTS.reduce((sum, part) => sum + part.value, 0);\n\nexport function Capacity(): ReactElement {\n const { t } = useWords(\"meter\");\n const words = t(\"capacity.value\", { size: SIZE, used: USED });\n\n return (\n <Stack gap=\"sm\">\n <Meter.Root max={SIZE} value={USED}>\n <Meter.Label>{t(\"capacity.label\")}</Meter.Label>\n <Meter.ValueText>{words}</Meter.ValueText>\n <Meter.Track aria-valuetext={words}>\n {PARTS.map(({ key, value }) => (\n <Meter.Segment key={key} value={value} />\n ))}\n </Meter.Track>\n </Meter.Root>\n <Stack direction=\"row\" gap=\"md\" wrap>\n {PARTS.map(({ key, value }, at) => (\n <Text as=\"span\" key={key} size=\"xs\">\n <ColorSwatch\n aria-hidden\n shape=\"circle\"\n size=\"inherit\"\n value={`var(--colors-series-${String(at + 1)})`}\n />{\" \"}\n {t(`capacity.${key}`, { value })}\n </Text>\n ))}\n </Stack>\n </Stack>\n );\n}\n";
148
+ //#endregion
149
+ //#region src/meter/examples/shares.example.tsx
150
+ var shares_example_exports = /* @__PURE__ */ __exportAll({
151
+ Shares: () => Shares,
152
+ source: () => source$4
153
+ });
154
+ const PLANS = [
155
+ {
156
+ key: "starter",
157
+ value: 412
158
+ },
159
+ {
160
+ key: "growth",
161
+ value: 268
162
+ },
163
+ {
164
+ key: "scale",
165
+ value: 97
166
+ }
167
+ ];
168
+ const ACCOUNTS = PLANS.reduce((sum, plan) => sum + plan.value, 0);
169
+ function Shares() {
170
+ const $ = c(40);
171
+ const { i18n, t } = useWords("meter");
172
+ let T0;
173
+ let T1;
174
+ let T2;
175
+ let shares;
176
+ let t0;
177
+ let t1;
178
+ let t2;
179
+ let t3;
180
+ let t4;
181
+ let t5;
182
+ if ($[0] !== i18n.language || $[1] !== t) {
183
+ const percent = new Intl.NumberFormat(i18n.language, { style: "percent" });
184
+ shares = PLANS.map((t6) => {
185
+ const { key, value } = t6;
186
+ return t(`shares.${key}`, { share: percent.format(value / ACCOUNTS) });
187
+ });
188
+ T2 = Stack;
189
+ t5 = "sm";
190
+ T1 = Root;
191
+ t1 = ACCOUNTS;
192
+ t2 = ACCOUNTS;
193
+ let t7;
194
+ if ($[12] !== t) {
195
+ t7 = t("shares.label");
196
+ $[12] = t;
197
+ $[13] = t7;
198
+ } else t7 = $[13];
199
+ if ($[14] !== t7) {
200
+ t3 = /* @__PURE__ */ jsx(Label, { children: t7 });
201
+ $[14] = t7;
202
+ $[15] = t3;
203
+ } else t3 = $[15];
204
+ let t8;
205
+ if ($[16] !== t) {
206
+ t8 = t("shares.value", { count: ACCOUNTS });
207
+ $[16] = t;
208
+ $[17] = t8;
209
+ } else t8 = $[17];
210
+ if ($[18] !== t8) {
211
+ t4 = /* @__PURE__ */ jsx(ValueText, { children: t8 });
212
+ $[18] = t8;
213
+ $[19] = t4;
214
+ } else t4 = $[19];
215
+ T0 = Track;
216
+ t0 = new Intl.ListFormat(i18n.language).format(shares);
217
+ $[0] = i18n.language;
218
+ $[1] = t;
219
+ $[2] = T0;
220
+ $[3] = T1;
221
+ $[4] = T2;
222
+ $[5] = shares;
223
+ $[6] = t0;
224
+ $[7] = t1;
225
+ $[8] = t2;
226
+ $[9] = t3;
227
+ $[10] = t4;
228
+ $[11] = t5;
229
+ } else {
230
+ T0 = $[2];
231
+ T1 = $[3];
232
+ T2 = $[4];
233
+ shares = $[5];
234
+ t0 = $[6];
235
+ t1 = $[7];
236
+ t2 = $[8];
237
+ t3 = $[9];
238
+ t4 = $[10];
239
+ t5 = $[11];
240
+ }
241
+ let t6;
242
+ if ($[20] === Symbol.for("react.memo_cache_sentinel")) {
243
+ t6 = PLANS.map(_temp);
244
+ $[20] = t6;
245
+ } else t6 = $[20];
246
+ let t7;
247
+ if ($[21] !== T0 || $[22] !== t0) {
248
+ t7 = /* @__PURE__ */ jsx(T0, {
249
+ "aria-valuetext": t0,
250
+ children: t6
251
+ });
252
+ $[21] = T0;
253
+ $[22] = t0;
254
+ $[23] = t7;
255
+ } else t7 = $[23];
256
+ let t8;
257
+ if ($[24] !== T1 || $[25] !== t1 || $[26] !== t2 || $[27] !== t3 || $[28] !== t4 || $[29] !== t7) {
258
+ t8 = /* @__PURE__ */ jsxs(T1, {
259
+ max: t1,
260
+ value: t2,
261
+ children: [
262
+ t3,
263
+ t4,
264
+ t7
265
+ ]
266
+ });
267
+ $[24] = T1;
268
+ $[25] = t1;
269
+ $[26] = t2;
270
+ $[27] = t3;
271
+ $[28] = t4;
272
+ $[29] = t7;
273
+ $[30] = t8;
274
+ } else t8 = $[30];
275
+ let t9;
276
+ if ($[31] !== shares) {
277
+ t9 = PLANS.map((t10, at) => {
278
+ const { key: key_1 } = t10;
279
+ return /* @__PURE__ */ jsxs(Text, {
280
+ as: "span",
281
+ size: "xs",
282
+ children: [
283
+ /* @__PURE__ */ jsx(ColorSwatch, {
284
+ "aria-hidden": true,
285
+ shape: "circle",
286
+ size: "inherit",
287
+ value: `var(--colors-series-${String(at + 1)})`
288
+ }),
289
+ " ",
290
+ shares[at]
291
+ ]
292
+ }, key_1);
293
+ });
294
+ $[31] = shares;
295
+ $[32] = t9;
296
+ } else t9 = $[32];
297
+ let t10;
298
+ if ($[33] !== t9) {
299
+ t10 = /* @__PURE__ */ jsx(Stack, {
300
+ direction: "row",
301
+ gap: "md",
302
+ wrap: true,
303
+ children: t9
304
+ });
305
+ $[33] = t9;
306
+ $[34] = t10;
307
+ } else t10 = $[34];
308
+ let t11;
309
+ if ($[35] !== T2 || $[36] !== t10 || $[37] !== t5 || $[38] !== t8) {
310
+ t11 = /* @__PURE__ */ jsxs(T2, {
311
+ gap: t5,
312
+ children: [t8, t10]
313
+ });
314
+ $[35] = T2;
315
+ $[36] = t10;
316
+ $[37] = t5;
317
+ $[38] = t8;
318
+ $[39] = t11;
319
+ } else t11 = $[39];
320
+ return t11;
321
+ }
322
+ function _temp(t0) {
323
+ const { key: key_0, value: value_0 } = t0;
324
+ return /* @__PURE__ */ jsx(Segment, { value: value_0 }, key_0);
325
+ }
326
+ const source$4 = "import { type ReactElement } from \"react\";\n\nimport { ColorSwatch } from \"@stealthscale/component-data\";\nimport { Stack } from \"@stealthscale/component-layout\";\nimport { Text } from \"@stealthscale/component-typography\";\nimport { useWords } from \"@stealthscale/specimen\";\n\nimport { Meter } from \"@stealthscale/component-feedback\";\n\nconst PLANS = [\n { key: \"starter\", value: 412 },\n { key: \"growth\", value: 268 },\n { key: \"scale\", value: 97 },\n] as const;\n\nconst ACCOUNTS = PLANS.reduce((sum, plan) => sum + plan.value, 0);\n\nexport function Shares(): ReactElement {\n const { i18n, t } = useWords(\"meter\");\n const percent = new Intl.NumberFormat(i18n.language, { style: \"percent\" });\n const shares = PLANS.map(({ key, value }) =>\n t(`shares.${key}`, { share: percent.format(value / ACCOUNTS) }),\n );\n\n return (\n <Stack gap=\"sm\">\n <Meter.Root max={ACCOUNTS} value={ACCOUNTS}>\n <Meter.Label>{t(\"shares.label\")}</Meter.Label>\n <Meter.ValueText>{t(\"shares.value\", { count: ACCOUNTS })}</Meter.ValueText>\n <Meter.Track aria-valuetext={new Intl.ListFormat(i18n.language).format(shares)}>\n {PLANS.map(({ key, value }) => (\n <Meter.Segment key={key} value={value} />\n ))}\n </Meter.Track>\n </Meter.Root>\n <Stack direction=\"row\" gap=\"md\" wrap>\n {PLANS.map(({ key }, at) => (\n <Text as=\"span\" key={key} size=\"xs\">\n <ColorSwatch\n aria-hidden\n shape=\"circle\"\n size=\"inherit\"\n value={`var(--colors-series-${String(at + 1)})`}\n />{\" \"}\n {shares[at]}\n </Text>\n ))}\n </Stack>\n </Stack>\n );\n}\n";
327
+ //#endregion
328
+ //#region src/meter/examples/storage.example.tsx
329
+ var storage_example_exports = /* @__PURE__ */ __exportAll({
330
+ Storage: () => Storage,
331
+ source: () => source$3
332
+ });
333
+ const GIGABYTES = {
334
+ maximumFractionDigits: 1,
335
+ style: "unit",
336
+ unit: "gigabyte"
337
+ };
338
+ function Storage(props) {
339
+ const $ = c(9);
340
+ const { t } = useWords("meter");
341
+ let t0;
342
+ if ($[0] !== t) {
343
+ t0 = t("storage");
344
+ $[0] = t;
345
+ $[1] = t0;
346
+ } else t0 = $[1];
347
+ let t1;
348
+ if ($[2] !== t0) {
349
+ t1 = /* @__PURE__ */ jsx(Label, { children: t0 });
350
+ $[2] = t0;
351
+ $[3] = t1;
352
+ } else t1 = $[3];
353
+ let t2;
354
+ if ($[4] === Symbol.for("react.memo_cache_sentinel")) {
355
+ t2 = /* @__PURE__ */ jsx(ValueText, {});
356
+ $[4] = t2;
357
+ } else t2 = $[4];
358
+ let t3;
359
+ if ($[5] === Symbol.for("react.memo_cache_sentinel")) {
360
+ t3 = /* @__PURE__ */ jsx(Track, { children: /* @__PURE__ */ jsx(Range, {}) });
361
+ $[5] = t3;
362
+ } else t3 = $[5];
363
+ let t4;
364
+ if ($[6] !== props || $[7] !== t1) {
365
+ t4 = /* @__PURE__ */ jsxs(Root, {
366
+ formatOptions: GIGABYTES,
367
+ max: 50,
368
+ value: 38.2,
369
+ ...props,
370
+ children: [
371
+ t1,
372
+ t2,
373
+ t3
374
+ ]
375
+ });
376
+ $[6] = props;
377
+ $[7] = t1;
378
+ $[8] = t4;
379
+ } else t4 = $[8];
380
+ return t4;
381
+ }
382
+ const source$3 = "import { type ReactElement } from \"react\";\n\nimport { useWords } from \"@stealthscale/specimen\";\n\nimport { Meter } from \"@stealthscale/component-feedback\";\n\nconst GIGABYTES: Intl.NumberFormatOptions = {\n maximumFractionDigits: 1,\n style: \"unit\",\n unit: \"gigabyte\",\n};\n\nexport function Storage(props: Omit<Meter.RootProps, \"value\">): ReactElement {\n const { t } = useWords(\"meter\");\n\n return (\n <Meter.Root formatOptions={GIGABYTES} max={50} value={38.2} {...props}>\n <Meter.Label>{t(\"storage\")}</Meter.Label>\n <Meter.ValueText />\n <Meter.Track>\n <Meter.Range />\n </Meter.Track>\n </Meter.Root>\n );\n}\n";
383
+ //#endregion
384
+ //#region src/meter/examples/strength.example.tsx
385
+ var strength_example_exports = /* @__PURE__ */ __exportAll({
386
+ Strength: () => Strength,
387
+ source: () => source$2
388
+ });
389
+ const WORDS = [
390
+ "none",
391
+ "weak",
392
+ "fair",
393
+ "good",
394
+ "strong"
395
+ ];
396
+ const PALETTES = [
397
+ "neutral",
398
+ "error",
399
+ "warning",
400
+ "info",
401
+ "success"
402
+ ];
403
+ function scoreOf(password) {
404
+ const classes = [
405
+ /[a-z]/u,
406
+ /[A-Z]/u,
407
+ /\d/u,
408
+ /[^\dA-Za-z]/u
409
+ ].filter((kind) => kind.test(password)).length;
410
+ return Math.min(4, Number(password.length >= 8) + Number(password.length >= 12) + (classes > 2 ? 2 : 0));
411
+ }
412
+ function Strength() {
413
+ const $ = c(33);
414
+ const { t } = useWords("meter");
415
+ const [password, setPassword] = useState("");
416
+ let t0;
417
+ if ($[0] !== password) {
418
+ t0 = scoreOf(password);
419
+ $[0] = password;
420
+ $[1] = t0;
421
+ } else t0 = $[1];
422
+ const score = t0;
423
+ const t1 = `strength.${WORDS[score] ?? "none"}`;
424
+ let t2;
425
+ if ($[2] !== t || $[3] !== t1) {
426
+ t2 = t(t1);
427
+ $[2] = t;
428
+ $[3] = t1;
429
+ $[4] = t2;
430
+ } else t2 = $[4];
431
+ const words = t2;
432
+ let t3;
433
+ if ($[5] !== t) {
434
+ t3 = t("strength.password");
435
+ $[5] = t;
436
+ $[6] = t3;
437
+ } else t3 = $[6];
438
+ let t4;
439
+ if ($[7] !== t3) {
440
+ t4 = /* @__PURE__ */ jsx(Field.Label, { children: t3 });
441
+ $[7] = t3;
442
+ $[8] = t4;
443
+ } else t4 = $[8];
444
+ let t5;
445
+ if ($[9] === Symbol.for("react.memo_cache_sentinel")) {
446
+ t5 = (event) => {
447
+ setPassword(event.currentTarget.value);
448
+ };
449
+ $[9] = t5;
450
+ } else t5 = $[9];
451
+ let t6;
452
+ if ($[10] !== password) {
453
+ t6 = /* @__PURE__ */ jsx(Field.Control, {
454
+ autoComplete: "new-password",
455
+ onChange: t5,
456
+ type: "password",
457
+ value: password
458
+ });
459
+ $[10] = password;
460
+ $[11] = t6;
461
+ } else t6 = $[11];
462
+ let t7;
463
+ if ($[12] !== t4 || $[13] !== t6) {
464
+ t7 = /* @__PURE__ */ jsxs(Field.Root, { children: [t4, t6] });
465
+ $[12] = t4;
466
+ $[13] = t6;
467
+ $[14] = t7;
468
+ } else t7 = $[14];
469
+ const t8 = PALETTES[score] ?? "neutral";
470
+ let t9;
471
+ if ($[15] !== t) {
472
+ t9 = t("strength.label");
473
+ $[15] = t;
474
+ $[16] = t9;
475
+ } else t9 = $[16];
476
+ let t10;
477
+ if ($[17] !== t9) {
478
+ t10 = /* @__PURE__ */ jsx(Label, { children: t9 });
479
+ $[17] = t9;
480
+ $[18] = t10;
481
+ } else t10 = $[18];
482
+ let t11;
483
+ if ($[19] !== words) {
484
+ t11 = /* @__PURE__ */ jsx(ValueText, { children: words });
485
+ $[19] = words;
486
+ $[20] = t11;
487
+ } else t11 = $[20];
488
+ let t12;
489
+ if ($[21] === Symbol.for("react.memo_cache_sentinel")) {
490
+ t12 = /* @__PURE__ */ jsx(Range, {});
491
+ $[21] = t12;
492
+ } else t12 = $[21];
493
+ let t13;
494
+ if ($[22] !== words) {
495
+ t13 = /* @__PURE__ */ jsx(Track, {
496
+ "aria-valuetext": words,
497
+ children: t12
498
+ });
499
+ $[22] = words;
500
+ $[23] = t13;
501
+ } else t13 = $[23];
502
+ let t14;
503
+ if ($[24] !== score || $[25] !== t10 || $[26] !== t11 || $[27] !== t13 || $[28] !== t8) {
504
+ t14 = /* @__PURE__ */ jsxs(Root, {
505
+ max: 4,
506
+ palette: t8,
507
+ value: score,
508
+ children: [
509
+ t10,
510
+ t11,
511
+ t13
512
+ ]
513
+ });
514
+ $[24] = score;
515
+ $[25] = t10;
516
+ $[26] = t11;
517
+ $[27] = t13;
518
+ $[28] = t8;
519
+ $[29] = t14;
520
+ } else t14 = $[29];
521
+ let t15;
522
+ if ($[30] !== t14 || $[31] !== t7) {
523
+ t15 = /* @__PURE__ */ jsxs(Stack, {
524
+ gap: "md",
525
+ children: [t7, t14]
526
+ });
527
+ $[30] = t14;
528
+ $[31] = t7;
529
+ $[32] = t15;
530
+ } else t15 = $[32];
531
+ return t15;
532
+ }
533
+ const source$2 = "import { type ReactElement, useState } from \"react\";\n\nimport { Field } from \"@stealthscale/component-forms\";\nimport { Stack } from \"@stealthscale/component-layout\";\nimport { useWords } from \"@stealthscale/specimen\";\n\nimport { Meter } from \"@stealthscale/component-feedback\";\n\nconst WORDS = [\"none\", \"weak\", \"fair\", \"good\", \"strong\"] as const;\n\nconst PALETTES = [\"neutral\", \"error\", \"warning\", \"info\", \"success\"] as const;\n\nfunction scoreOf(password: string): number {\n const classes = [/[a-z]/u, /[A-Z]/u, /\\d/u, /[^\\dA-Za-z]/u].filter((kind) =>\n kind.test(password),\n ).length;\n\n return Math.min(\n 4,\n Number(password.length >= 8) + Number(password.length >= 12) + (classes > 2 ? 2 : 0),\n );\n}\n\nexport function Strength(): ReactElement {\n const { t } = useWords(\"meter\");\n const [password, setPassword] = useState(\"\");\n const score = scoreOf(password);\n const words = t(`strength.${WORDS[score] ?? \"none\"}`);\n\n return (\n <Stack gap=\"md\">\n <Field.Root>\n <Field.Label>{t(\"strength.password\")}</Field.Label>\n <Field.Control\n autoComplete=\"new-password\"\n onChange={(event) => {\n setPassword(event.currentTarget.value);\n }}\n type=\"password\"\n value={password}\n />\n </Field.Root>\n <Meter.Root max={4} palette={PALETTES[score] ?? \"neutral\"} value={score}>\n <Meter.Label>{t(\"strength.label\")}</Meter.Label>\n <Meter.ValueText>{words}</Meter.ValueText>\n <Meter.Track aria-valuetext={words}>\n <Meter.Range />\n </Meter.Track>\n </Meter.Root>\n </Stack>\n );\n}\n";
534
+ //#endregion
535
+ //#region src/meter/examples/target.example.tsx
536
+ var target_example_exports = /* @__PURE__ */ __exportAll({
537
+ Target: () => Target,
538
+ source: () => source$1
539
+ });
540
+ const MEASURES = [
541
+ {
542
+ key: "deals",
543
+ target: 250,
544
+ value: 268
545
+ },
546
+ {
547
+ key: "trials",
548
+ target: 60,
549
+ value: 41
550
+ },
551
+ {
552
+ key: "spend",
553
+ target: 9e3,
554
+ value: 8600
555
+ }
556
+ ];
557
+ function paletteOf$1(key, share) {
558
+ if (key === "spend") return share >= .9 ? "warning" : "primary";
559
+ return share >= 1 ? "success" : "primary";
560
+ }
561
+ function Target() {
562
+ const $ = c(4);
563
+ const { t } = useWords("meter");
564
+ let t0;
565
+ if ($[0] !== t) {
566
+ t0 = MEASURES.map((t1) => {
567
+ const { key, target, value } = t1;
568
+ return /* @__PURE__ */ jsxs(Root, {
569
+ max: Math.max(target, value),
570
+ palette: paletteOf$1(key, value / target),
571
+ value,
572
+ children: [
573
+ /* @__PURE__ */ jsx(Label, { children: t(`target.${key}`) }),
574
+ /* @__PURE__ */ jsx(ValueText, { children: t("target.value", {
575
+ target,
576
+ value
577
+ }) }),
578
+ /* @__PURE__ */ jsxs(Track, {
579
+ "aria-valuetext": t("target.spoken", {
580
+ target,
581
+ value
582
+ }),
583
+ children: [/* @__PURE__ */ jsx(Range, {}), /* @__PURE__ */ jsx(Marker, { value: target })]
584
+ })
585
+ ]
586
+ }, key);
587
+ });
588
+ $[0] = t;
589
+ $[1] = t0;
590
+ } else t0 = $[1];
591
+ let t1;
592
+ if ($[2] !== t0) {
593
+ t1 = /* @__PURE__ */ jsx(Stack, {
594
+ gap: "md",
595
+ children: t0
596
+ });
597
+ $[2] = t0;
598
+ $[3] = t1;
599
+ } else t1 = $[3];
600
+ return t1;
601
+ }
602
+ const source$1 = "import { type ReactElement } from \"react\";\n\nimport { Stack } from \"@stealthscale/component-layout\";\nimport { useWords } from \"@stealthscale/specimen\";\n\nimport { Meter } from \"@stealthscale/component-feedback\";\n\nconst MEASURES = [\n { key: \"deals\", target: 250, value: 268 },\n { key: \"trials\", target: 60, value: 41 },\n { key: \"spend\", target: 9000, value: 8600 },\n] as const;\n\nfunction paletteOf(key: string, share: number): \"primary\" | \"success\" | \"warning\" {\n if (key === \"spend\") return share >= 0.9 ? \"warning\" : \"primary\";\n\n return share >= 1 ? \"success\" : \"primary\";\n}\n\nexport function Target(): ReactElement {\n const { t } = useWords(\"meter\");\n\n return (\n <Stack gap=\"md\">\n {MEASURES.map(({ key, target, value }) => (\n <Meter.Root\n key={key}\n max={Math.max(target, value)}\n palette={paletteOf(key, value / target)}\n value={value}\n >\n <Meter.Label>{t(`target.${key}`)}</Meter.Label>\n <Meter.ValueText>{t(\"target.value\", { target, value })}</Meter.ValueText>\n <Meter.Track aria-valuetext={t(\"target.spoken\", { target, value })}>\n <Meter.Range />\n <Meter.Marker value={target} />\n </Meter.Track>\n </Meter.Root>\n ))}\n </Stack>\n );\n}\n";
603
+ //#endregion
604
+ //#region src/meter/examples/usage.example.tsx
605
+ var usage_example_exports = /* @__PURE__ */ __exportAll({
606
+ Usage: () => Usage,
607
+ source: () => source
608
+ });
609
+ const LIMITS = [
610
+ {
611
+ key: "seats",
612
+ max: 10,
613
+ value: 8
614
+ },
615
+ {
616
+ key: "storage",
617
+ max: 50,
618
+ value: 46
619
+ },
620
+ {
621
+ key: "requests",
622
+ max: 1e5,
623
+ value: 72400
624
+ }
625
+ ];
626
+ function paletteOf(share) {
627
+ if (share >= .9) return "error";
628
+ return share >= .75 ? "warning" : "primary";
629
+ }
630
+ function Usage() {
631
+ const $ = c(4);
632
+ const { t } = useWords("meter");
633
+ let t0;
634
+ if ($[0] !== t) {
635
+ t0 = LIMITS.map((t1) => {
636
+ const { key, max, value } = t1;
637
+ const words = t(`usage.${key}.value`, {
638
+ max,
639
+ value
640
+ });
641
+ return /* @__PURE__ */ jsxs(Root, {
642
+ max,
643
+ palette: paletteOf(value / max),
644
+ value,
645
+ children: [
646
+ /* @__PURE__ */ jsx(Label, { children: t(`usage.${key}.label`) }),
647
+ /* @__PURE__ */ jsx(ValueText, { children: words }),
648
+ /* @__PURE__ */ jsx(Track, {
649
+ "aria-valuetext": words,
650
+ children: /* @__PURE__ */ jsx(Range, {})
651
+ })
652
+ ]
653
+ }, key);
654
+ });
655
+ $[0] = t;
656
+ $[1] = t0;
657
+ } else t0 = $[1];
658
+ let t1;
659
+ if ($[2] !== t0) {
660
+ t1 = /* @__PURE__ */ jsx(Stack, {
661
+ gap: "md",
662
+ children: t0
663
+ });
664
+ $[2] = t0;
665
+ $[3] = t1;
666
+ } else t1 = $[3];
667
+ return t1;
668
+ }
669
+ const source = "import { type ReactElement } from \"react\";\n\nimport { Stack } from \"@stealthscale/component-layout\";\nimport { useWords } from \"@stealthscale/specimen\";\n\nimport { Meter } from \"@stealthscale/component-feedback\";\n\nconst LIMITS = [\n { key: \"seats\", max: 10, value: 8 },\n { key: \"storage\", max: 50, value: 46 },\n { key: \"requests\", max: 100_000, value: 72_400 },\n] as const;\n\nfunction paletteOf(share: number): \"error\" | \"primary\" | \"warning\" {\n if (share >= 0.9) return \"error\";\n\n return share >= 0.75 ? \"warning\" : \"primary\";\n}\n\nexport function Usage(): ReactElement {\n const { t } = useWords(\"meter\");\n\n return (\n <Stack gap=\"md\">\n {LIMITS.map(({ key, max, value }) => {\n const words = t(`usage.${key}.value`, { max, value });\n\n return (\n <Meter.Root key={key} max={max} palette={paletteOf(value / max)} value={value}>\n <Meter.Label>{t(`usage.${key}.label`)}</Meter.Label>\n <Meter.ValueText>{words}</Meter.ValueText>\n <Meter.Track aria-valuetext={words}>\n <Meter.Range />\n </Meter.Track>\n </Meter.Root>\n );\n })}\n </Stack>\n );\n}\n";
670
+ //#endregion
671
+ //#region src/meter/meter.specimen.tsx
672
+ /**
673
+ * Catalogue page for the meter.
674
+ *
675
+ * @remarks
676
+ * `scenesOf` generates one scene per axis of the progress recipe, which the meter renders, from
677
+ * the storage meter, each in a room at the `xs` measure, because a meter is as wide as its
678
+ * container. The palette scene crosses the looks, and the shape scene uses the thickest track.
679
+ * The page skips the axes of work under way, which a meter does not offer. Hand-written scenes
680
+ * render a plan's usage, each palette picked from its own threshold, a password's strength,
681
+ * whose words are the value text, measures against their targets, a disk's parts and a plan mix
682
+ * as shares. The words are keys under `meter` in `locales/en/specimen/meter.json`.
683
+ */
684
+ /**
685
+ * Axes of the progress recipe the meter does not offer, each with the reason.
686
+ */
687
+ const SKIPPED = {
688
+ animated: "a meter shows a measurement, not work under way, so its root takes no animated",
689
+ effect: "a meter is not a control, so its root takes no effect",
690
+ striped: "a meter shows a measurement, not work under way, so its root takes no striped"
691
+ };
692
+ /**
693
+ * Hand-written scene for a plan's usage, each meter in the palette its threshold picks.
694
+ */
695
+ const limits = {
696
+ about: "meter.limits.about",
697
+ draw: () => /* @__PURE__ */ jsx(Room, {
698
+ size: "xs",
699
+ children: /* @__PURE__ */ jsx(Usage, {})
700
+ }),
701
+ example: usage_example_exports,
702
+ title: "meter.limits.title"
703
+ };
704
+ /**
705
+ * Hand-written scene for a password's strength, stated in words.
706
+ */
707
+ const words = {
708
+ about: "meter.words.about",
709
+ draw: () => /* @__PURE__ */ jsx(Room, {
710
+ size: "xs",
711
+ children: /* @__PURE__ */ jsx(Strength, {})
712
+ }),
713
+ example: strength_example_exports,
714
+ title: "meter.words.title"
715
+ };
716
+ /**
717
+ * Hand-written scene for measures against their targets, each target a marker.
718
+ */
719
+ const targets = {
720
+ about: "meter.target.about",
721
+ draw: () => /* @__PURE__ */ jsx(Room, {
722
+ size: "xs",
723
+ children: /* @__PURE__ */ jsx(Target, {})
724
+ }),
725
+ example: target_example_exports,
726
+ title: "meter.target.title"
727
+ };
728
+ /**
729
+ * Hand-written scene for a disk's used space in parts, each part a segment.
730
+ */
731
+ const parts = {
732
+ about: "meter.capacity.about",
733
+ draw: () => /* @__PURE__ */ jsx(Room, {
734
+ size: "xs",
735
+ children: /* @__PURE__ */ jsx(Capacity, {})
736
+ }),
737
+ example: capacity_example_exports,
738
+ title: "meter.capacity.title"
739
+ };
740
+ /**
741
+ * Hand-written scene for a whole split into shares that fill the track.
742
+ */
743
+ const split = {
744
+ about: "meter.shares.about",
745
+ draw: () => /* @__PURE__ */ jsx(Room, {
746
+ size: "xs",
747
+ children: /* @__PURE__ */ jsx(Shares, {})
748
+ }),
749
+ example: shares_example_exports,
750
+ title: "meter.shares.title"
751
+ };
752
+ var meter_specimen_default = specimen({
753
+ about: "meter.about",
754
+ id: "components/feedback/meter",
755
+ imports: "import { Meter } from \"@stealthscale/component-feedback\";",
756
+ scenes: [
757
+ ...scenesOf(recipe, {
758
+ axes: {
759
+ palette: { across: "variant" },
760
+ shape: { with: { size: "xl" } }
761
+ },
762
+ draw: (props) => /* @__PURE__ */ jsx(Room, {
763
+ size: "xs",
764
+ children: /* @__PURE__ */ jsx(Storage, { ...props })
765
+ }),
766
+ example: storage_example_exports,
767
+ namespace: "meter",
768
+ order: [
769
+ "size",
770
+ "shape",
771
+ "palette",
772
+ "layout"
773
+ ],
774
+ skip: SKIPPED
775
+ }),
776
+ limits,
777
+ words,
778
+ targets,
779
+ parts,
780
+ split
781
+ ],
782
+ title: "meter.title"
783
+ });
784
+ //#endregion
785
+ export { SKIPPED, meter_specimen_default as default, limits, parts, split, targets, words };