@hraness/design-kit 0.36.5 → 0.39.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 (59) hide show
  1. package/MARKETING_COPY.md +2 -0
  2. package/README.md +77 -11
  3. package/dist/{chunk-xa28y4fg.js → chunk-1dgm85ta.js} +191 -55
  4. package/dist/chunk-6mx403v5.js +286 -0
  5. package/dist/{chunk-thv5t11w.js → chunk-dc8v05zh.js} +6 -137
  6. package/dist/{chunk-evb02bc1.js → chunk-fcs5qekr.js} +48 -1
  7. package/dist/chunk-fxwed3e5.js +775 -0
  8. package/dist/chunk-vy0pt84a.js +1807 -0
  9. package/dist/{chunk-sabcr66p.js → chunk-w1y1m3m7.js} +300 -1
  10. package/dist/index.js +24 -12
  11. package/dist/mockups/client.js +6 -654
  12. package/dist/mockups/index.js +29 -1797
  13. package/dist/provider-marks.js +1 -1
  14. package/dist/react/index.js +190 -5
  15. package/dist/react/server.js +5 -3
  16. package/dist/stylex-manifest.json +1 -1
  17. package/package.json +9 -5
  18. package/portfolio-inventory.json +1 -1
  19. package/src/compiler-foundation.css +2 -0
  20. package/src/design-gallery.css +12 -0
  21. package/src/index.ts +1 -0
  22. package/src/marketing-marquee.css +281 -0
  23. package/src/marketing-marquee.ts +206 -0
  24. package/src/mockups/client.tsx +157 -66
  25. package/src/mockups/core.tsx +30 -0
  26. package/src/mockups.css +158 -23
  27. package/src/provider-marks.generated.ts +92 -0
  28. package/src/provider-marks.ts +29 -4
  29. package/src/react/design-gallery.tsx +53 -0
  30. package/src/react/index.ts +1 -0
  31. package/src/react/marketing-marquee.tsx +71 -0
  32. package/src/react/server.ts +1 -0
  33. package/src/styles.css +2 -0
  34. package/vendor/provider-marks/BOOTSTRAP-ICONS-LICENSE +21 -0
  35. package/vendor/provider-marks/UPSTREAM.md +28 -0
  36. package/vendor/provider-marks/bootstrap-icons/calendar-event-fill.svg +3 -0
  37. package/vendor/provider-marks/bootstrap-icons/filetype-csv.svg +3 -0
  38. package/vendor/provider-marks/bootstrap-icons/globe2.svg +3 -0
  39. package/vendor/provider-marks/bootstrap-icons/linkedin.svg +3 -0
  40. package/vendor/provider-marks/bootstrap-icons/microsoft.svg +3 -0
  41. package/vendor/provider-marks/bootstrap-icons/person-vcard-fill.svg +3 -0
  42. package/vendor/provider-marks/bootstrap-icons/shop.svg +3 -0
  43. package/vendor/provider-marks/simple-icons/apple.svg +1 -0
  44. package/vendor/provider-marks/simple-icons/bluesky.svg +1 -0
  45. package/vendor/provider-marks/simple-icons/facebook.svg +1 -0
  46. package/vendor/provider-marks/simple-icons/github.svg +1 -0
  47. package/vendor/provider-marks/simple-icons/gmail.svg +1 -0
  48. package/vendor/provider-marks/simple-icons/google.svg +1 -0
  49. package/vendor/provider-marks/simple-icons/instagram.svg +1 -0
  50. package/vendor/provider-marks/simple-icons/reddit.svg +1 -0
  51. package/vendor/provider-marks/simple-icons/substack.svg +1 -0
  52. package/vendor/provider-marks/simple-icons/telegram.svg +1 -0
  53. package/vendor/provider-marks/simple-icons/threads.svg +1 -0
  54. package/vendor/provider-marks/simple-icons/tiktok.svg +1 -0
  55. package/vendor/provider-marks/simple-icons/twitch.svg +1 -0
  56. package/vendor/provider-marks/simple-icons/x.svg +1 -0
  57. package/vendor/provider-marks/simple-icons/ycombinator.svg +1 -0
  58. package/vendor/provider-marks/simple-icons/youtube.svg +1 -0
  59. package/dist/chunk-gmea6p0d.js +0 -13
@@ -1,660 +1,12 @@
1
1
  "use client";
2
2
  import {
3
- joinMockupClasses
4
- } from "../chunk-evb02bc1.js";
3
+ FitToWidth,
4
+ ModeShowcase,
5
+ StepThrough
6
+ } from "../chunk-fxwed3e5.js";
7
+ import"../chunk-fcs5qekr.js";
8
+ import"../chunk-w1y1m3m7.js";
5
9
  import"../chunk-5gtx3pza.js";
6
-
7
- // src/mockups/client.tsx
8
- import { useId, useLayoutEffect, useMemo, useRef, useState } from "react";
9
- import { jsx, jsxs } from "react/jsx-runtime";
10
- var useIsomorphicLayoutEffect = typeof document === "undefined" ? () => {
11
- return;
12
- } : useLayoutEffect;
13
- function assertUniqueIds(items, what) {
14
- if (items.length === 0)
15
- throw new RangeError(`${what} needs at least one entry.`);
16
- const seen = new Set;
17
- for (const item of items) {
18
- if (typeof item.id !== "string" || !/^[a-z0-9][a-z0-9-]*$/u.test(item.id)) {
19
- throw new TypeError(`${what} ids must be lowercase letters, digits, and dashes: ${JSON.stringify(item.id)}`);
20
- }
21
- if (seen.has(item.id))
22
- throw new RangeError(`${what} ids must be unique: ${item.id}`);
23
- seen.add(item.id);
24
- }
25
- }
26
- function itemAt(items, index, what) {
27
- const item = items[index];
28
- if (item === undefined)
29
- throw new RangeError(`${what} has no entry at ${String(index)}.`);
30
- return item;
31
- }
32
- function optionalText(value, component) {
33
- if (value === undefined)
34
- return;
35
- if (typeof value !== "string")
36
- throw new TypeError(`${component} text must be a string.`);
37
- return value.trim() || undefined;
38
- }
39
- function nextTabIndex(key, index, count) {
40
- if (key === "ArrowRight" || key === "ArrowDown")
41
- return (index + 1) % count;
42
- if (key === "ArrowLeft" || key === "ArrowUp")
43
- return (index - 1 + count) % count;
44
- if (key === "Home")
45
- return 0;
46
- if (key === "End")
47
- return count - 1;
48
- return;
49
- }
50
- function FitToWidth({
51
- children,
52
- className,
53
- minWidth = 400
54
- }) {
55
- if (!(minWidth > 0))
56
- throw new RangeError("FitToWidth minWidth must be positive.");
57
- const outer = useRef(null);
58
- const inner = useRef(null);
59
- const [fit, setFit] = useState(null);
60
- useIsomorphicLayoutEffect(() => {
61
- const stage = outer.current;
62
- const content = inner.current;
63
- if (stage === null || content === null || typeof ResizeObserver === "undefined")
64
- return;
65
- const measure = () => {
66
- const available = stage.clientWidth;
67
- if (available <= 0)
68
- return;
69
- const width = Math.max(available, minWidth);
70
- const scale = available / width;
71
- const height = content.offsetHeight * scale;
72
- setFit((current) => current !== null && current.width === width && current.scale === scale && current.height === height ? current : {
73
- height,
74
- scale,
75
- width
76
- });
77
- };
78
- measure();
79
- const observer = new ResizeObserver(measure);
80
- observer.observe(stage);
81
- observer.observe(content);
82
- return () => observer.disconnect();
83
- }, [minWidth]);
84
- const scaled = fit !== null && fit.scale < 1;
85
- return /* @__PURE__ */ jsx("div", {
86
- className: joinMockupClasses("hkm-fit", className),
87
- "data-hkm-min-width": minWidth,
88
- ref: outer,
89
- style: scaled ? {
90
- height: fit.height
91
- } : undefined,
92
- children: /* @__PURE__ */ jsx("div", {
93
- className: "hkm-fit-inner",
94
- "data-hkm-scaled": scaled ? "" : undefined,
95
- ref: inner,
96
- style: scaled ? {
97
- transform: `scale(${fit.scale})`,
98
- width: fit.width
99
- } : undefined,
100
- children
101
- })
102
- });
103
- }
104
- function ModeShowcase({
105
- caption,
106
- className,
107
- fit = "natural",
108
- height = 440,
109
- initial,
110
- label,
111
- minWidth = 400,
112
- modeLabel = "Mode",
113
- modes,
114
- optionInactiveModes = [],
115
- optionLabel = "Option",
116
- options,
117
- status,
118
- surfaces,
119
- theme
120
- }) {
121
- assertUniqueIds(surfaces, "ModeShowcase surface");
122
- assertUniqueIds(modes, "ModeShowcase mode");
123
- if (options !== undefined)
124
- assertUniqueIds(options, "ModeShowcase option");
125
- const captionText = optionalText(caption, "ModeShowcase");
126
- if (!Number.isFinite(height) || !(height > 0))
127
- throw new RangeError("ModeShowcase height must be finite and positive.");
128
- if (fit !== "natural" && fit !== "fill")
129
- throw new RangeError("ModeShowcase fit must be natural or fill.");
130
- if (fit === "fill" && surfaces.length * modes.length * (options?.length ?? 1) > 128)
131
- throw new RangeError("ModeShowcase fill supports up to 128 surface, mode, and option combinations.");
132
- const id = useId();
133
- const firstSurface = surfaces.find((surface2) => surface2.id === initial?.surface) ?? itemAt(surfaces, 0, "ModeShowcase surfaces");
134
- const firstMode = modes.find((mode2) => mode2.id === initial?.mode) ?? itemAt(modes, 0, "ModeShowcase modes");
135
- const firstOption = options === undefined ? undefined : options.find((option2) => option2.id === initial?.option) ?? itemAt(options, 0, "ModeShowcase options");
136
- const [surfaceId, setSurfaceId] = useState(firstSurface.id);
137
- const [mode, setMode] = useState(firstMode.id);
138
- const [previousMode, setPreviousMode] = useState(firstMode.id);
139
- const [option, setOption] = useState(firstOption?.id);
140
- const [animated, setAnimated] = useState(false);
141
- const tabs = useRef(new Map);
142
- const surface = surfaces.find((entry) => entry.id === surfaceId) ?? itemAt(surfaces, 0, "ModeShowcase surfaces");
143
- const modeChoice = modes.find((entry) => entry.id === mode) ?? itemAt(modes, 0, "ModeShowcase modes");
144
- const optionChoice = options?.find((entry) => entry.id === option);
145
- const optionInactive = optionInactiveModes.includes(mode);
146
- const measurements = useMemo(() => fit !== "fill" ? null : surfaces.flatMap((entry) => modes.flatMap((choice) => (options ?? [{
147
- id: undefined
148
- }]).map((optionChoice2) => /* @__PURE__ */ jsx("div", {
149
- "aria-hidden": "true",
150
- className: "hkm-mode-surface",
151
- "data-hkm-measurement": "",
152
- hidden: true,
153
- inert: true,
154
- children: /* @__PURE__ */ jsx("div", {
155
- className: "hkm-fit",
156
- children: /* @__PURE__ */ jsx("div", {
157
- className: "hkm-fit-inner",
158
- children: entry.render({
159
- animated: false,
160
- mode: choice.id,
161
- option: optionChoice2.id,
162
- previousMode: choice.id,
163
- theme
164
- })
165
- })
166
- })
167
- }, JSON.stringify([entry.id, choice.id, optionChoice2.id]))))), [fit, modes, options, surfaces, theme]);
168
- const stage = useFittedShowcaseStage(fit, measurements, JSON.stringify([mode, option]), height);
169
- const chooseMode = (next) => {
170
- if (next === mode)
171
- return;
172
- setPreviousMode(mode);
173
- setMode(next);
174
- setAnimated(true);
175
- };
176
- const chooseOption = (next) => {
177
- if (next === option)
178
- return;
179
- setOption(next);
180
- setAnimated(true);
181
- };
182
- const onTabKey = (event) => {
183
- const index = surfaces.findIndex((entry) => entry.id === surface.id);
184
- const next = nextTabIndex(event.key, index, surfaces.length);
185
- if (next === undefined)
186
- return;
187
- event.preventDefault();
188
- const target = itemAt(surfaces, next, "ModeShowcase surfaces").id;
189
- setSurfaceId(target);
190
- tabs.current.get(target)?.focus();
191
- };
192
- const statusNode = status?.({
193
- mode,
194
- option,
195
- surface: surface.id
196
- });
197
- const hint = [modeChoice.hint, optionInactive ? undefined : optionChoice?.hint].map((text) => optionalText(text, "ModeShowcase hint")).filter((text) => text !== undefined).join(" ");
198
- const hasStatus = statusNode !== undefined && statusNode !== null && statusNode !== false && statusNode !== "";
199
- return /* @__PURE__ */ jsxs("figure", {
200
- "aria-label": label?.(surface) ?? `Illustration of ${surface.label.toLowerCase()}`,
201
- className: joinMockupClasses("hkm-showcase", "hkm-modes", className),
202
- "data-hkm-fit": fit === "fill" ? fit : undefined,
203
- "data-hkm-theme": theme,
204
- "data-nosnippet": "",
205
- children: [
206
- surfaces.length > 1 ? /* @__PURE__ */ jsx("div", {
207
- "aria-label": "Surface",
208
- className: "hkm-tabs hkm-folder-tabs",
209
- role: "tablist",
210
- children: surfaces.map((entry) => /* @__PURE__ */ jsx("button", {
211
- "aria-controls": `${id}-panel`,
212
- "aria-selected": entry.id === surface.id,
213
- className: "hkm-tab",
214
- id: `${id}-tab-${entry.id}`,
215
- onClick: () => setSurfaceId(entry.id),
216
- onKeyDown: onTabKey,
217
- ref: (element) => {
218
- if (element === null)
219
- tabs.current.delete(entry.id);
220
- else
221
- tabs.current.set(entry.id, element);
222
- },
223
- role: "tab",
224
- tabIndex: entry.id === surface.id ? 0 : -1,
225
- type: "button",
226
- children: entry.label
227
- }, entry.id))
228
- }) : null,
229
- /* @__PURE__ */ jsxs("div", {
230
- "aria-labelledby": surfaces.length > 1 ? `${id}-tab-${surface.id}` : undefined,
231
- className: "hkm-showcase-stage hkm-mode-panel",
232
- id: `${id}-panel`,
233
- role: surfaces.length > 1 ? "tabpanel" : undefined,
234
- style: {
235
- "--hkm-page-height": `${height}px`
236
- },
237
- children: [
238
- /* @__PURE__ */ jsxs("div", {
239
- className: "hkm-showcase-controls",
240
- children: [
241
- /* @__PURE__ */ jsxs("div", {
242
- className: "hkm-showcase-settings",
243
- children: [
244
- /* @__PURE__ */ jsxs("div", {
245
- className: "hkm-showcase-row",
246
- children: [
247
- /* @__PURE__ */ jsx("span", {
248
- className: "hkm-showcase-label",
249
- id: `${id}-mode`,
250
- children: modeLabel
251
- }),
252
- /* @__PURE__ */ jsx("div", {
253
- "aria-labelledby": `${id}-mode`,
254
- className: "hkm-segmented",
255
- role: "group",
256
- children: modes.map((entry) => /* @__PURE__ */ jsx("button", {
257
- "aria-pressed": entry.id === mode,
258
- onClick: () => chooseMode(entry.id),
259
- type: "button",
260
- children: entry.label
261
- }, entry.id))
262
- })
263
- ]
264
- }),
265
- options === undefined ? null : /* @__PURE__ */ jsxs("div", {
266
- className: "hkm-showcase-row",
267
- children: [
268
- /* @__PURE__ */ jsx("span", {
269
- className: "hkm-showcase-label",
270
- id: `${id}-option`,
271
- children: optionLabel
272
- }),
273
- /* @__PURE__ */ jsx("div", {
274
- "aria-labelledby": `${id}-option`,
275
- className: "hkm-segmented",
276
- role: "group",
277
- children: options.map((entry) => /* @__PURE__ */ jsx("button", {
278
- "aria-pressed": entry.id === option,
279
- disabled: optionInactive,
280
- onClick: () => chooseOption(entry.id),
281
- type: "button",
282
- children: entry.label
283
- }, entry.id))
284
- })
285
- ]
286
- })
287
- ]
288
- }),
289
- hint === "" ? null : /* @__PURE__ */ jsx("p", {
290
- className: "hkm-showcase-hint",
291
- children: hint
292
- })
293
- ]
294
- }),
295
- /* @__PURE__ */ jsxs("div", {
296
- className: "hkm-mode-stage",
297
- ref: stage,
298
- children: [
299
- measurements,
300
- surfaces.map((entry) => /* @__PURE__ */ jsx("div", {
301
- "aria-hidden": entry.id !== surface.id,
302
- className: "hkm-mode-surface",
303
- "data-hkm-animated": entry.id === surface.id && animated ? "" : undefined,
304
- "data-hkm-from": entry.id === surface.id && animated ? previousMode : undefined,
305
- inert: entry.id !== surface.id,
306
- children: /* @__PURE__ */ jsx(FitToWidth, {
307
- minWidth: fit === "fill" ? 1 : minWidth,
308
- children: entry.render({
309
- animated: entry.id === surface.id && animated,
310
- mode,
311
- option,
312
- previousMode,
313
- theme
314
- })
315
- })
316
- }, entry.id))
317
- ]
318
- })
319
- ]
320
- }),
321
- !hasStatus && captionText === undefined ? null : /* @__PURE__ */ jsxs("figcaption", {
322
- className: "hkm-showcase-caption",
323
- children: [
324
- hasStatus ? /* @__PURE__ */ jsx("span", {
325
- "aria-live": "polite",
326
- className: "hkm-showcase-status",
327
- children: statusNode
328
- }) : null,
329
- captionText === undefined ? null : /* @__PURE__ */ jsx("span", {
330
- children: captionText
331
- })
332
- ]
333
- })
334
- ]
335
- });
336
- }
337
- function fillFrames(stage) {
338
- const frames = [];
339
- for (const panel of stage.querySelectorAll(":scope > .hkm-step-panel, :scope > .hkm-mode-surface")) {
340
- const fit = panel.querySelector(":scope > .hkm-fit");
341
- if (fit === null)
342
- continue;
343
- for (const root of fit.querySelectorAll(".hkm-root")) {
344
- const enclosingRoot = root.parentElement?.closest(".hkm-root");
345
- if (root.closest(".hkm-fit") === fit && (enclosingRoot === null || enclosingRoot === undefined || !fit.contains(enclosingRoot)))
346
- frames.push(root);
347
- }
348
- }
349
- return frames;
350
- }
351
- function presentationBodies(stage) {
352
- return fillFrames(stage).flatMap((frame) => [...frame.querySelectorAll(':scope > .hkm-window > [data-hkm-density="presentation"]')]);
353
- }
354
- function measureNestedFits(stage) {
355
- const fits = [...stage.querySelectorAll("[data-hkm-min-width]")].filter((fit) => fit.parentElement?.classList.contains("hkm-step-panel") !== true && fit.parentElement?.classList.contains("hkm-mode-surface") !== true);
356
- for (const fit of fits) {
357
- const inner = fit.querySelector(":scope > .hkm-fit-inner");
358
- if (inner === null)
359
- continue;
360
- fit.style.removeProperty("height");
361
- inner.style.removeProperty("transform");
362
- inner.style.width = `${Math.max(fit.clientWidth, Number(fit.dataset.hkmMinWidth))}px`;
363
- }
364
- for (const fit of fits.reverse()) {
365
- const inner = fit.querySelector(":scope > .hkm-fit-inner");
366
- if (inner === null || inner.offsetWidth <= 0)
367
- continue;
368
- const scale = Math.min(1, fit.clientWidth / inner.offsetWidth);
369
- fit.style.height = `${inner.offsetHeight * scale}px`;
370
- inner.style.transform = `scale(${scale})`;
371
- }
372
- }
373
- function fitShowcaseStage(stage, minimumHeight) {
374
- const owner = stage.parentElement;
375
- if (owner === null || stage.clientWidth <= 0)
376
- return;
377
- for (const frame of fillFrames(stage))
378
- frame.setAttribute("data-hkm-fill-frame", "");
379
- const probe = stage.cloneNode(true);
380
- probe.setAttribute("aria-hidden", "true");
381
- probe.setAttribute("inert", "");
382
- probe.setAttribute("data-hkm-measuring", "");
383
- probe.style.cssText = `position:absolute;visibility:hidden;pointer-events:none;inset:0 auto auto 0;inline-size:${stage.getBoundingClientRect().width}px;block-size:auto;`;
384
- for (const sentinel of probe.querySelectorAll("[data-hkm-font-sentinel]"))
385
- sentinel.remove();
386
- for (const node of probe.querySelectorAll("[id]"))
387
- node.removeAttribute("id");
388
- for (const node of probe.querySelectorAll("[data-hkm-animated]"))
389
- node.removeAttribute("data-hkm-animated");
390
- for (const body of presentationBodies(probe))
391
- body.style.removeProperty("--hkm-terminal-presentation-size");
392
- for (const fixture of probe.querySelectorAll("[data-hkm-measurement]"))
393
- fixture.hidden = false;
394
- for (const node of [probe, ...probe.querySelectorAll("*")]) {
395
- node.style.setProperty("transition", "none", "important");
396
- node.style.setProperty("animation", "none", "important");
397
- }
398
- owner.append(probe);
399
- try {
400
- measureNestedFits(probe);
401
- const naturalHeight = Math.max(minimumHeight, Math.ceil(probe.getBoundingClientRect().height));
402
- stage.style.setProperty("--hkm-showcase-fill-height", `${naturalHeight}px`);
403
- for (const fixture of probe.querySelectorAll("[data-hkm-measurement]"))
404
- fixture.remove();
405
- probe.style.blockSize = `${naturalHeight}px`;
406
- probe.removeAttribute("data-hkm-measuring");
407
- const bodies = presentationBodies(stage).filter((body) => body.closest("[data-hkm-measurement]") === null);
408
- const copies = presentationBodies(probe);
409
- for (const [index, copy] of copies.entries()) {
410
- const body = bodies[index];
411
- if (body === undefined)
412
- continue;
413
- const lines = [...copy.querySelectorAll(".hkm-terminal-line")];
414
- const wrappedRows = (line) => Math.ceil((line.getBoundingClientRect().height - 0.5) / Number.parseFloat(getComputedStyle(line).lineHeight));
415
- const baselineRows = lines.map(wrappedRows);
416
- let low = 1;
417
- let high = 4;
418
- for (let attempt = 0;attempt < 9; attempt += 1) {
419
- const candidate = (low + high) / 2;
420
- copy.style.setProperty("--hkm-terminal-presentation-size", `${candidate}rem`);
421
- if (copy.scrollHeight <= copy.clientHeight + 1 && copy.scrollWidth <= copy.clientWidth + 1 && lines.every((line, index2) => {
422
- const baseline = baselineRows[index2];
423
- return baseline !== undefined && wrappedRows(line) <= baseline;
424
- }))
425
- low = candidate;
426
- else
427
- high = candidate;
428
- }
429
- body.style.setProperty("--hkm-terminal-presentation-size", `${Math.floor(low * 1000) / 1000}rem`);
430
- }
431
- stage.setAttribute("data-hkm-fitted", "");
432
- } finally {
433
- probe.remove();
434
- }
435
- }
436
- function useFittedShowcaseStage(fit, source, variation = "", minimumHeight = 0) {
437
- const stage = useRef(null);
438
- useIsomorphicLayoutEffect(() => {
439
- const node = stage.current;
440
- if (fit !== "fill" || node === null || typeof ResizeObserver === "undefined")
441
- return;
442
- const fontSentinel = document.createElement("span");
443
- fontSentinel.setAttribute("data-hkm-font-sentinel", "");
444
- fontSentinel.setAttribute("aria-hidden", "true");
445
- fontSentinel.inert = true;
446
- fontSentinel.style.cssText = "position:absolute;inline-size:1rem;block-size:1rem;visibility:hidden;pointer-events:none;inset:0 auto auto 0;";
447
- node.append(fontSentinel);
448
- let previous = "";
449
- let disposed = false;
450
- const measure = () => {
451
- if (disposed)
452
- return;
453
- const key = `${node.clientWidth}/${getComputedStyle(document.documentElement).fontSize}`;
454
- if (key === previous)
455
- return;
456
- previous = key;
457
- fitShowcaseStage(node, minimumHeight);
458
- };
459
- measure();
460
- const observer = new ResizeObserver(measure);
461
- observer.observe(node);
462
- observer.observe(document.documentElement);
463
- observer.observe(fontSentinel);
464
- document.fonts.ready.then(() => {
465
- previous = "";
466
- measure();
467
- });
468
- return () => {
469
- disposed = true;
470
- observer.disconnect();
471
- fontSentinel.remove();
472
- node.style.removeProperty("--hkm-showcase-fill-height");
473
- node.removeAttribute("data-hkm-fitted");
474
- for (const body of presentationBodies(node))
475
- body.style.removeProperty("--hkm-terminal-presentation-size");
476
- for (const frame of fillFrames(node))
477
- frame.removeAttribute("data-hkm-fill-frame");
478
- };
479
- }, [fit, source, variation, minimumHeight]);
480
- return stage;
481
- }
482
- function StepThrough({
483
- caption,
484
- className,
485
- initial,
486
- fit = "natural",
487
- label = "Steps",
488
- minWidth = 400,
489
- steps,
490
- theme
491
- }) {
492
- assertUniqueIds(steps, "StepThrough step");
493
- if (fit !== "natural" && fit !== "fill")
494
- throw new RangeError("StepThrough fit must be natural or fill.");
495
- const stage = useFittedShowcaseStage(fit, steps);
496
- const captionText = optionalText(caption, "StepThrough");
497
- const id = useId();
498
- const [index, setIndex] = useState(() => Math.max(0, steps.findIndex((step2) => step2.id === initial)));
499
- const [animated, setAnimated] = useState(false);
500
- const tabs = useRef(new Map);
501
- const current = Math.min(index, steps.length - 1);
502
- const step = itemAt(steps, current, "StepThrough steps");
503
- const go = (next, focus = false) => {
504
- if (next < 0 || next >= steps.length || next === current)
505
- return;
506
- setIndex(next);
507
- setAnimated(true);
508
- if (focus)
509
- tabs.current.get(next)?.focus();
510
- };
511
- const onTabKey = (event) => {
512
- const next = nextTabIndex(event.key, current, steps.length);
513
- if (next === undefined)
514
- return;
515
- event.preventDefault();
516
- go(next, true);
517
- };
518
- return /* @__PURE__ */ jsxs("figure", {
519
- "aria-label": `Illustration: ${label.toLowerCase()}`,
520
- className: joinMockupClasses("hkm-showcase", "hkm-steps", className),
521
- "data-hkm-fit": fit === "fill" ? fit : undefined,
522
- "data-hkm-theme": theme,
523
- "data-nosnippet": "",
524
- children: [
525
- /* @__PURE__ */ jsx("div", {
526
- className: "hkm-showcase-controls",
527
- children: /* @__PURE__ */ jsx("div", {
528
- "aria-label": label,
529
- className: "hkm-tabs hkm-folder-tabs hkm-step-tabs",
530
- role: "tablist",
531
- children: steps.map((entry, position) => /* @__PURE__ */ jsxs("button", {
532
- "aria-controls": `${id}-panel-${entry.id}`,
533
- "aria-selected": position === current,
534
- className: "hkm-tab",
535
- "data-hkm-done": position < current ? "" : undefined,
536
- id: `${id}-tab-${entry.id}`,
537
- onClick: () => go(position),
538
- onKeyDown: onTabKey,
539
- ref: (element) => {
540
- if (element === null)
541
- tabs.current.delete(position);
542
- else
543
- tabs.current.set(position, element);
544
- },
545
- role: "tab",
546
- tabIndex: position === current ? 0 : -1,
547
- type: "button",
548
- children: [
549
- /* @__PURE__ */ jsx("span", {
550
- "aria-hidden": "true",
551
- className: "hkm-step-number",
552
- children: position + 1
553
- }),
554
- entry.label
555
- ]
556
- }, entry.id))
557
- })
558
- }),
559
- /* @__PURE__ */ jsx("div", {
560
- className: "hkm-showcase-stage hkm-step-stage",
561
- ref: stage,
562
- children: steps.map((entry, position) => /* @__PURE__ */ jsx("div", {
563
- "aria-hidden": position !== current,
564
- "aria-labelledby": `${id}-tab-${entry.id}`,
565
- className: "hkm-step-panel",
566
- "data-hkm-animated": position === current && animated ? "" : undefined,
567
- id: `${id}-panel-${entry.id}`,
568
- inert: position !== current,
569
- role: "tabpanel",
570
- children: fit === "fill" ? /* @__PURE__ */ jsx("div", {
571
- className: "hkm-fit",
572
- children: /* @__PURE__ */ jsx("div", {
573
- className: "hkm-fit-inner",
574
- children: entry.render({
575
- animated: position === current && animated,
576
- theme
577
- })
578
- })
579
- }) : /* @__PURE__ */ jsx(FitToWidth, {
580
- minWidth,
581
- children: entry.render({
582
- animated: position === current && animated,
583
- theme
584
- })
585
- })
586
- }, entry.id))
587
- }),
588
- /* @__PURE__ */ jsxs("div", {
589
- className: "hkm-step-nav",
590
- children: [
591
- /* @__PURE__ */ jsx("button", {
592
- "aria-label": "Back",
593
- className: "hkm-step-button",
594
- disabled: current === 0,
595
- onClick: () => go(current - 1),
596
- type: "button",
597
- children: /* @__PURE__ */ jsx("svg", {
598
- "aria-hidden": "true",
599
- focusable: "false",
600
- height: "28",
601
- viewBox: "0 0 24 24",
602
- width: "28",
603
- children: /* @__PURE__ */ jsx("path", {
604
- d: "m14.5 5-7 7 7 7",
605
- fill: "none",
606
- stroke: "currentColor",
607
- strokeLinecap: "round",
608
- strokeLinejoin: "round",
609
- strokeWidth: "1.75"
610
- })
611
- })
612
- }),
613
- /* @__PURE__ */ jsxs("span", {
614
- "aria-live": "polite",
615
- className: "hkm-showcase-status hkm-step-announcement",
616
- children: [
617
- "Step ",
618
- current + 1,
619
- " of ",
620
- steps.length,
621
- step.hint === undefined ? "" : `. ${step.hint}`
622
- ]
623
- }),
624
- /* @__PURE__ */ jsx("button", {
625
- "aria-label": "Next",
626
- className: "hkm-step-button",
627
- "data-hkm-primary": "",
628
- disabled: current === steps.length - 1,
629
- onClick: () => go(current + 1),
630
- type: "button",
631
- children: /* @__PURE__ */ jsx("svg", {
632
- "aria-hidden": "true",
633
- focusable: "false",
634
- height: "28",
635
- viewBox: "0 0 24 24",
636
- width: "28",
637
- children: /* @__PURE__ */ jsx("path", {
638
- d: "m9.5 5 7 7-7 7",
639
- fill: "none",
640
- stroke: "currentColor",
641
- strokeLinecap: "round",
642
- strokeLinejoin: "round",
643
- strokeWidth: "1.75"
644
- })
645
- })
646
- })
647
- ]
648
- }),
649
- captionText === undefined ? null : /* @__PURE__ */ jsx("figcaption", {
650
- className: "hkm-showcase-caption",
651
- children: /* @__PURE__ */ jsx("span", {
652
- children: captionText
653
- })
654
- })
655
- ]
656
- });
657
- }
658
10
  export {
659
11
  StepThrough,
660
12
  ModeShowcase,