@usefidel/design-system 0.26.0 → 0.28.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1297,6 +1297,7 @@ function StackedCardsIllustration({ className }) {
1297
1297
  }
1298
1298
 
1299
1299
  // src/components/Callout/Callout.tsx
1300
+ import { X as X2 } from "lucide-react";
1300
1301
  import { jsx as jsx21, jsxs as jsxs19 } from "react/jsx-runtime";
1301
1302
  function Callout({
1302
1303
  tone = "neutral",
@@ -1305,6 +1306,8 @@ function Callout({
1305
1306
  titleAside,
1306
1307
  children,
1307
1308
  action,
1309
+ onDismiss,
1310
+ dismissLabel = "Dismiss",
1308
1311
  className,
1309
1312
  ...rest
1310
1313
  }) {
@@ -1318,7 +1321,8 @@ function Callout({
1318
1321
  ] }),
1319
1322
  children != null && /* @__PURE__ */ jsx21("div", { className: "fds-callout__text", children })
1320
1323
  ] }),
1321
- action != null && /* @__PURE__ */ jsx21("div", { className: "fds-callout__action", children: action })
1324
+ action != null && /* @__PURE__ */ jsx21("div", { className: "fds-callout__action", children: action }),
1325
+ onDismiss && /* @__PURE__ */ jsx21("button", { type: "button", className: "fds-callout__dismiss", "aria-label": dismissLabel, onClick: onDismiss, children: /* @__PURE__ */ jsx21(X2, { "aria-hidden": "true" }) })
1322
1326
  ] });
1323
1327
  }
1324
1328
 
@@ -2299,13 +2303,17 @@ var AppLayout = Object.assign(AppLayoutRoot, { Panel: AppLayoutPanel });
2299
2303
 
2300
2304
  // src/components/PageHeader/PageHeader.tsx
2301
2305
  import { jsx as jsx47, jsxs as jsxs38 } from "react/jsx-runtime";
2302
- function PageHeader({ title, description, breadcrumb, actions, className, children, ...rest }) {
2306
+ function PageHeader({ title, description, leading, meta, breadcrumb, actions, className, children, ...rest }) {
2303
2307
  return /* @__PURE__ */ jsxs38("header", { className: ["fds-page-header", className].filter(Boolean).join(" "), ...rest, children: [
2308
+ breadcrumb != null && /* @__PURE__ */ jsx47("div", { className: "fds-page-header__breadcrumb", children: breadcrumb }),
2304
2309
  /* @__PURE__ */ jsxs38("div", { className: "fds-page-header__row", children: [
2305
- /* @__PURE__ */ jsxs38("div", { className: "fds-page-header__text", children: [
2306
- breadcrumb != null && /* @__PURE__ */ jsx47("div", { className: "fds-page-header__breadcrumb", children: breadcrumb }),
2307
- /* @__PURE__ */ jsx47("h1", { className: "fds-page-header__title", children: title }),
2308
- description != null && /* @__PURE__ */ jsx47("p", { className: "fds-page-header__description", children: description })
2310
+ /* @__PURE__ */ jsxs38("div", { className: "fds-page-header__lead", children: [
2311
+ leading != null && /* @__PURE__ */ jsx47("div", { className: "fds-page-header__leading", children: leading }),
2312
+ /* @__PURE__ */ jsxs38("div", { className: "fds-page-header__text", children: [
2313
+ /* @__PURE__ */ jsx47("h1", { className: "fds-page-header__title", children: title }),
2314
+ description != null && /* @__PURE__ */ jsx47("p", { className: "fds-page-header__description", children: description }),
2315
+ meta != null && /* @__PURE__ */ jsx47("div", { className: "fds-page-header__meta", children: meta })
2316
+ ] })
2309
2317
  ] }),
2310
2318
  actions != null && /* @__PURE__ */ jsx47("div", { className: "fds-page-header__actions", children: actions })
2311
2319
  ] }),
@@ -2315,7 +2323,7 @@ function PageHeader({ title, description, breadcrumb, actions, className, childr
2315
2323
 
2316
2324
  // src/components/Toast/Toast.tsx
2317
2325
  import { useEffect as useEffect9 } from "react";
2318
- import { X as X2 } from "lucide-react";
2326
+ import { X as X3 } from "lucide-react";
2319
2327
  import { jsx as jsx48, jsxs as jsxs39 } from "react/jsx-runtime";
2320
2328
  function ToastRegion({ className, children, ...rest }) {
2321
2329
  return /* @__PURE__ */ jsx48("div", { className: ["fds-toast-region", className].filter(Boolean).join(" "), "aria-live": "polite", ...rest, children });
@@ -2329,7 +2337,7 @@ function Toast({ children, action, onDismiss, duration, className, ...rest }) {
2329
2337
  return /* @__PURE__ */ jsxs39("div", { role: "status", className: ["fds-toast", className].filter(Boolean).join(" "), ...rest, children: [
2330
2338
  /* @__PURE__ */ jsx48("span", { className: "fds-toast__message", children }),
2331
2339
  action && /* @__PURE__ */ jsx48("button", { type: "button", className: "fds-toast__action", onClick: action.onClick, children: action.label }),
2332
- onDismiss && /* @__PURE__ */ jsx48("button", { type: "button", className: "fds-toast__close", "aria-label": "Dismiss", onClick: onDismiss, children: /* @__PURE__ */ jsx48(X2, { "aria-hidden": "true" }) })
2340
+ onDismiss && /* @__PURE__ */ jsx48("button", { type: "button", className: "fds-toast__close", "aria-label": "Dismiss", onClick: onDismiss, children: /* @__PURE__ */ jsx48(X3, { "aria-hidden": "true" }) })
2333
2341
  ] });
2334
2342
  }
2335
2343
 
@@ -2421,7 +2429,7 @@ var Checklist = Object.assign(ChecklistRoot, { Item: ChecklistItem });
2421
2429
  // src/components/Drawer/Drawer.tsx
2422
2430
  import { useEffect as useEffect10, useId as useId14, useRef as useRef10 } from "react";
2423
2431
  import { createPortal as createPortal3 } from "react-dom";
2424
- import { X as X3 } from "lucide-react";
2432
+ import { X as X4 } from "lucide-react";
2425
2433
  import { jsx as jsx53, jsxs as jsxs44 } from "react/jsx-runtime";
2426
2434
  var FOCUSABLE2 = 'a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])';
2427
2435
  function Drawer({ open, onClose, title, description, children, footer, dismissible = true }) {
@@ -2491,7 +2499,7 @@ function Drawer({ open, onClose, title, description, children, footer, dismissib
2491
2499
  /* @__PURE__ */ jsx53("h2", { id: titleId, className: "fds-drawer__title", children: title }),
2492
2500
  description != null && /* @__PURE__ */ jsx53("p", { id: descriptionId, className: "fds-drawer__description", children: description })
2493
2501
  ] }),
2494
- /* @__PURE__ */ jsx53("button", { type: "button", className: "fds-drawer__close", onClick: onClose, disabled: !dismissible, "aria-label": "Close", children: /* @__PURE__ */ jsx53(X3, { "aria-hidden": "true" }) })
2502
+ /* @__PURE__ */ jsx53("button", { type: "button", className: "fds-drawer__close", onClick: onClose, disabled: !dismissible, "aria-label": "Close", children: /* @__PURE__ */ jsx53(X4, { "aria-hidden": "true" }) })
2495
2503
  ] }),
2496
2504
  /* @__PURE__ */ jsx53("div", { className: "fds-drawer__body", children }),
2497
2505
  footer != null && /* @__PURE__ */ jsx53("footer", { className: "fds-drawer__footer", children: footer })
@@ -2577,6 +2585,316 @@ var PageSkeleton = Object.assign(PageSkeletonRoot, {
2577
2585
  Form: PageSkeletonForm,
2578
2586
  Split: PageSkeletonSplit
2579
2587
  });
2588
+
2589
+ // src/components/PreviewCard/PreviewCard.tsx
2590
+ import { jsx as jsx56, jsxs as jsxs47 } from "react/jsx-runtime";
2591
+ function PreviewCardRoot({ as, variant = "default", className, ...rest }) {
2592
+ const Root = as ?? "div";
2593
+ return /* @__PURE__ */ jsx56(Root, { className: ["fds-preview-card", `fds-preview-card--${variant}`, className].filter(Boolean).join(" "), ...rest });
2594
+ }
2595
+ function PreviewCardPreview({ label, className, children, ...rest }) {
2596
+ return /* @__PURE__ */ jsxs47("div", { className: ["fds-preview-card__preview", className].filter(Boolean).join(" "), ...rest, children: [
2597
+ label != null && /* @__PURE__ */ jsx56("span", { className: "fds-preview-card__label", children: label }),
2598
+ children
2599
+ ] });
2600
+ }
2601
+ function PreviewCardTitle({ aside, className, children, ...rest }) {
2602
+ return /* @__PURE__ */ jsxs47("div", { className: ["fds-preview-card__title", className].filter(Boolean).join(" "), ...rest, children: [
2603
+ /* @__PURE__ */ jsx56("span", { className: "fds-preview-card__name", children }),
2604
+ aside != null && /* @__PURE__ */ jsx56("span", { className: "fds-preview-card__aside", children: aside })
2605
+ ] });
2606
+ }
2607
+ function part(name) {
2608
+ return function PreviewCardPart({ className, ...rest }) {
2609
+ return /* @__PURE__ */ jsx56("div", { className: [`fds-preview-card__${name}`, className].filter(Boolean).join(" "), ...rest });
2610
+ };
2611
+ }
2612
+ var PreviewCard = Object.assign(PreviewCardRoot, {
2613
+ Preview: PreviewCardPreview,
2614
+ Body: part("body"),
2615
+ Title: PreviewCardTitle,
2616
+ Meta: part("meta"),
2617
+ Footer: part("footer")
2618
+ });
2619
+
2620
+ // src/components/Tile/Tile.tsx
2621
+ import { jsx as jsx57, jsxs as jsxs48 } from "react/jsx-runtime";
2622
+ function Tile({ label, aside, className, children, ...rest }) {
2623
+ return /* @__PURE__ */ jsxs48("section", { className: ["fds-tile", className].filter(Boolean).join(" "), ...rest, children: [
2624
+ /* @__PURE__ */ jsxs48("header", { className: "fds-tile__head", children: [
2625
+ /* @__PURE__ */ jsx57("span", { className: "fds-tile__label", children: label }),
2626
+ aside
2627
+ ] }),
2628
+ /* @__PURE__ */ jsx57("div", { className: "fds-tile__body", children })
2629
+ ] });
2630
+ }
2631
+
2632
+ // src/components/ListCard/ListCard.tsx
2633
+ import { jsx as jsx58, jsxs as jsxs49 } from "react/jsx-runtime";
2634
+ function ListCardRoot({ title, count, aside, footer, className, children, ...rest }) {
2635
+ return /* @__PURE__ */ jsxs49("section", { className: ["fds-list-card", className].filter(Boolean).join(" "), ...rest, children: [
2636
+ (title != null || aside != null) && /* @__PURE__ */ jsxs49("header", { className: "fds-list-card__head", children: [
2637
+ /* @__PURE__ */ jsxs49("span", { className: "fds-list-card__title", children: [
2638
+ title,
2639
+ count != null && /* @__PURE__ */ jsx58("span", { className: "fds-list-card__count", children: count })
2640
+ ] }),
2641
+ aside != null && /* @__PURE__ */ jsx58("span", { className: "fds-list-card__aside", children: aside })
2642
+ ] }),
2643
+ /* @__PURE__ */ jsx58("ul", { className: "fds-list-card__rows", children }),
2644
+ footer != null && /* @__PURE__ */ jsx58("footer", { className: "fds-list-card__footer", children: footer })
2645
+ ] });
2646
+ }
2647
+ function ListCardRow({ icon, tone = "neutral", title, description, trailing, muted, className, ...rest }) {
2648
+ return /* @__PURE__ */ jsxs49("li", { className: ["fds-list-card__row", muted ? "fds-list-card__row--muted" : "", className].filter(Boolean).join(" "), ...rest, children: [
2649
+ icon != null && /* @__PURE__ */ jsx58("span", { className: `fds-list-card__icon fds-list-card__icon--${tone}`, "aria-hidden": "true", children: icon }),
2650
+ /* @__PURE__ */ jsxs49("span", { className: "fds-list-card__text", children: [
2651
+ /* @__PURE__ */ jsx58("span", { className: "fds-list-card__row-title", children: title }),
2652
+ description != null && /* @__PURE__ */ jsx58("span", { className: "fds-list-card__description", children: description })
2653
+ ] }),
2654
+ trailing != null && /* @__PURE__ */ jsx58("span", { className: "fds-list-card__trailing", children: trailing })
2655
+ ] });
2656
+ }
2657
+ var ListCard = Object.assign(ListCardRoot, { Row: ListCardRow });
2658
+
2659
+ // src/components/DescriptionList/DescriptionList.tsx
2660
+ import { jsx as jsx59, jsxs as jsxs50 } from "react/jsx-runtime";
2661
+ function DescriptionList({ title, action, items = [], note, className, children, ...rest }) {
2662
+ return /* @__PURE__ */ jsxs50("section", { className: ["fds-description-list", className].filter(Boolean).join(" "), ...rest, children: [
2663
+ (title != null || action != null) && /* @__PURE__ */ jsxs50("header", { className: "fds-description-list__head", children: [
2664
+ /* @__PURE__ */ jsx59("span", { className: "fds-description-list__title", children: title }),
2665
+ action != null && /* @__PURE__ */ jsx59("span", { className: "fds-description-list__action", children: action })
2666
+ ] }),
2667
+ items.length > 0 && /* @__PURE__ */ jsx59("dl", { className: "fds-description-list__items", children: items.map((item, i) => /* @__PURE__ */ jsxs50("div", { className: "fds-description-list__item", children: [
2668
+ /* @__PURE__ */ jsx59("dt", { children: item.label }),
2669
+ /* @__PURE__ */ jsx59("dd", { children: item.value })
2670
+ ] }, i)) }),
2671
+ children,
2672
+ note != null && /* @__PURE__ */ jsx59("p", { className: "fds-description-list__note", children: note })
2673
+ ] });
2674
+ }
2675
+
2676
+ // src/components/ColorRamp/ColorRamp.tsx
2677
+ import { jsx as jsx60 } from "react/jsx-runtime";
2678
+ function ColorRamp({ colors, size = "md", className, ...rest }) {
2679
+ return /* @__PURE__ */ jsx60("div", { className: ["fds-color-ramp", `fds-color-ramp--${size}`, className].filter(Boolean).join(" "), "aria-hidden": "true", ...rest, children: colors.map((c, i) => /* @__PURE__ */ jsx60("span", { className: "fds-color-ramp__step", style: { "--fds-ramp-color": c } }, i)) });
2680
+ }
2681
+
2682
+ // src/components/SwatchList/SwatchList.tsx
2683
+ import { jsx as jsx61, jsxs as jsxs51 } from "react/jsx-runtime";
2684
+ function SwatchList({ items, className, ...rest }) {
2685
+ return /* @__PURE__ */ jsx61("ul", { className: ["fds-swatch-list", className].filter(Boolean).join(" "), ...rest, children: items.map((item, i) => /* @__PURE__ */ jsxs51("li", { className: "fds-swatch-list__item", children: [
2686
+ /* @__PURE__ */ jsx61(
2687
+ "span",
2688
+ {
2689
+ className: ["fds-swatch-list__dot", item.color ? "" : "fds-swatch-list__dot--empty"].filter(Boolean).join(" "),
2690
+ style: item.color ? { "--fds-swatch-list-color": item.color } : void 0,
2691
+ "aria-hidden": "true"
2692
+ }
2693
+ ),
2694
+ /* @__PURE__ */ jsx61("span", { className: "fds-swatch-list__name", children: item.name }),
2695
+ /* @__PURE__ */ jsx61("span", { className: "fds-swatch-list__value", children: item.value })
2696
+ ] }, i)) });
2697
+ }
2698
+
2699
+ // src/components/TypeSpecimen/TypeSpecimen.tsx
2700
+ import { jsx as jsx62, jsxs as jsxs52 } from "react/jsx-runtime";
2701
+ var ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz 0123456789";
2702
+ function TypeSpecimen({ family, fontFamily, tokens, sample, weights = [], footer, className, ...rest }) {
2703
+ const face = { "--fds-specimen-font": fontFamily };
2704
+ return /* @__PURE__ */ jsxs52("section", { className: ["fds-type-specimen", className].filter(Boolean).join(" "), style: face, ...rest, children: [
2705
+ /* @__PURE__ */ jsxs52("header", { className: "fds-type-specimen__head", children: [
2706
+ /* @__PURE__ */ jsxs52("div", { className: "fds-type-specimen__titles", children: [
2707
+ /* @__PURE__ */ jsx62("h3", { className: "fds-type-specimen__family", children: family }),
2708
+ tokens != null && /* @__PURE__ */ jsx62("div", { className: "fds-type-specimen__tokens", children: tokens })
2709
+ ] }),
2710
+ /* @__PURE__ */ jsx62("span", { className: "fds-type-specimen__glyph", "aria-hidden": "true", children: "Aa" })
2711
+ ] }),
2712
+ sample != null && /* @__PURE__ */ jsx62("p", { className: "fds-type-specimen__sample", children: sample }),
2713
+ /* @__PURE__ */ jsx62("p", { className: "fds-type-specimen__alphabet", children: ALPHABET }),
2714
+ weights.length > 0 && /* @__PURE__ */ jsx62("ul", { className: "fds-type-specimen__weights", children: weights.map((w) => /* @__PURE__ */ jsxs52("li", { children: [
2715
+ /* @__PURE__ */ jsx62("span", { style: { fontWeight: w.weight }, children: "Ag" }),
2716
+ /* @__PURE__ */ jsx62("small", { children: w.label })
2717
+ ] }, w.label)) }),
2718
+ footer != null && /* @__PURE__ */ jsx62("footer", { className: "fds-type-specimen__footer", children: footer })
2719
+ ] });
2720
+ }
2721
+ function TypeSample({ fontFamily, caption, className, ...rest }) {
2722
+ return /* @__PURE__ */ jsxs52("div", { className: ["fds-type-sample", className].filter(Boolean).join(" "), style: { "--fds-specimen-font": fontFamily }, ...rest, children: [
2723
+ /* @__PURE__ */ jsx62("span", { className: "fds-type-sample__glyph", "aria-hidden": "true", children: "Aa" }),
2724
+ caption != null && /* @__PURE__ */ jsx62("span", { className: "fds-type-sample__caption", children: caption })
2725
+ ] });
2726
+ }
2727
+
2728
+ // src/components/TypeScale/TypeScale.tsx
2729
+ import { jsx as jsx63, jsxs as jsxs53 } from "react/jsx-runtime";
2730
+ function TypeScaleRoot({ className, ...rest }) {
2731
+ return /* @__PURE__ */ jsx63("ul", { className: ["fds-type-scale", className].filter(Boolean).join(" "), ...rest });
2732
+ }
2733
+ function TypeScaleRow({ name, detail, sampleStyle, sample = "Check every pull request", className, ...rest }) {
2734
+ return /* @__PURE__ */ jsxs53("li", { className: ["fds-type-scale__row", className].filter(Boolean).join(" "), ...rest, children: [
2735
+ /* @__PURE__ */ jsxs53("span", { className: "fds-type-scale__label", children: [
2736
+ /* @__PURE__ */ jsx63("span", { className: "fds-type-scale__name", children: name }),
2737
+ detail != null && /* @__PURE__ */ jsx63("span", { className: "fds-type-scale__detail", children: detail })
2738
+ ] }),
2739
+ /* @__PURE__ */ jsx63("span", { className: "fds-type-scale__sample", style: sampleStyle, children: sample })
2740
+ ] });
2741
+ }
2742
+ var TypeScale = Object.assign(TypeScaleRoot, { Row: TypeScaleRow });
2743
+
2744
+ // src/components/MeasureList/MeasureList.tsx
2745
+ import { jsx as jsx64, jsxs as jsxs54 } from "react/jsx-runtime";
2746
+ function MeasureList({ items, max, tone = "accent", className, ...rest }) {
2747
+ const top = max ?? Math.max(1, ...items.map((i) => i.amount));
2748
+ return /* @__PURE__ */ jsx64("ul", { className: ["fds-measure-list", `fds-measure-list--${tone}`, className].filter(Boolean).join(" "), ...rest, children: items.map((item, i) => /* @__PURE__ */ jsxs54("li", { className: "fds-measure-list__item", children: [
2749
+ /* @__PURE__ */ jsx64("span", { className: "fds-measure-list__name", children: item.name }),
2750
+ /* @__PURE__ */ jsx64("span", { className: "fds-measure-list__value", children: item.value }),
2751
+ /* @__PURE__ */ jsx64("span", { className: "fds-measure-list__track", "aria-hidden": "true", children: /* @__PURE__ */ jsx64("span", { className: "fds-measure-list__bar", style: { "--fds-measure": `${Math.min(100, item.amount / top * 100)}%` } }) })
2752
+ ] }, i)) });
2753
+ }
2754
+
2755
+ // src/components/TokenSample/TokenSample.tsx
2756
+ import { jsx as jsx65, jsxs as jsxs55 } from "react/jsx-runtime";
2757
+ function TokenSample({ kind, value, name, detail, className, ...rest }) {
2758
+ const style = { [kind === "radius" ? "--fds-sample-radius" : "--fds-sample-shadow"]: value };
2759
+ return /* @__PURE__ */ jsxs55("div", { className: ["fds-token-sample", `fds-token-sample--${kind}`, className].filter(Boolean).join(" "), ...rest, children: [
2760
+ /* @__PURE__ */ jsx65("span", { className: "fds-token-sample__shape", style, "aria-hidden": "true" }),
2761
+ /* @__PURE__ */ jsx65("span", { className: "fds-token-sample__name", children: name }),
2762
+ detail != null && /* @__PURE__ */ jsx65("span", { className: "fds-token-sample__detail", children: detail })
2763
+ ] });
2764
+ }
2765
+
2766
+ // src/components/EasingCurve/EasingCurve.tsx
2767
+ import { jsx as jsx66, jsxs as jsxs56 } from "react/jsx-runtime";
2768
+ var BEZIER = /cubic-bezier\(\s*([-\d.]+)\s*,\s*([-\d.]+)\s*,\s*([-\d.]+)\s*,\s*([-\d.]+)\s*\)/;
2769
+ var W = 120;
2770
+ var H = 72;
2771
+ var PAD = 12;
2772
+ function easingPath(value) {
2773
+ const m = BEZIER.exec(value);
2774
+ const [x1, y1, x2, y2] = m ? m.slice(1).map(Number) : [0, 0, 1, 1];
2775
+ const x = (t) => PAD + t * (W - PAD * 2);
2776
+ const y = (t) => H - PAD - t * (H - PAD * 2);
2777
+ return `M${x(0)},${y(0)} C${x(x1)},${y(y1)} ${x(x2)},${y(y2)} ${x(1)},${y(1)}`;
2778
+ }
2779
+ function EasingCurve({ value, name, className, ...rest }) {
2780
+ return /* @__PURE__ */ jsxs56("div", { className: ["fds-easing-curve", className].filter(Boolean).join(" "), ...rest, children: [
2781
+ /* @__PURE__ */ jsx66("svg", { className: "fds-easing-curve__plot", viewBox: `0 0 ${W} ${H}`, "aria-hidden": "true", children: /* @__PURE__ */ jsx66("path", { d: easingPath(value) }) }),
2782
+ /* @__PURE__ */ jsx66("span", { className: "fds-easing-curve__name", children: name }),
2783
+ /* @__PURE__ */ jsx66("span", { className: "fds-easing-curve__value", children: value })
2784
+ ] });
2785
+ }
2786
+
2787
+ // src/components/FilterChips/FilterChips.tsx
2788
+ import { useRef as useRef11 } from "react";
2789
+ import { jsx as jsx67, jsxs as jsxs57 } from "react/jsx-runtime";
2790
+ function FilterChips({ options, value, onChange, "aria-label": ariaLabel, className }) {
2791
+ const refs = useRef11([]);
2792
+ const onKeyDown = (e, index) => {
2793
+ const step = e.key === "ArrowRight" || e.key === "ArrowDown" ? 1 : e.key === "ArrowLeft" || e.key === "ArrowUp" ? -1 : 0;
2794
+ if (!step) return;
2795
+ e.preventDefault();
2796
+ const next = (index + step + options.length) % options.length;
2797
+ onChange(options[next].value);
2798
+ refs.current[next]?.focus();
2799
+ };
2800
+ return /* @__PURE__ */ jsx67("div", { role: "radiogroup", "aria-label": ariaLabel, className: ["fds-filter-chips", className].filter(Boolean).join(" "), children: options.map((o, i) => {
2801
+ const selected = o.value === value;
2802
+ return /* @__PURE__ */ jsxs57(
2803
+ "button",
2804
+ {
2805
+ ref: (el) => {
2806
+ refs.current[i] = el;
2807
+ },
2808
+ type: "button",
2809
+ role: "radio",
2810
+ "aria-checked": selected,
2811
+ tabIndex: selected ? 0 : -1,
2812
+ className: ["fds-filter-chips__chip", selected ? "fds-filter-chips__chip--selected" : ""].filter(Boolean).join(" "),
2813
+ onClick: () => onChange(o.value),
2814
+ onKeyDown: (e) => onKeyDown(e, i),
2815
+ children: [
2816
+ o.label,
2817
+ o.count != null && /* @__PURE__ */ jsx67("span", { className: "fds-filter-chips__count", children: o.count })
2818
+ ]
2819
+ },
2820
+ o.value
2821
+ );
2822
+ }) });
2823
+ }
2824
+
2825
+ // src/components/Meter/Meter.tsx
2826
+ import { jsx as jsx68, jsxs as jsxs58 } from "react/jsx-runtime";
2827
+ function Meter({ value, max, label, className, ...rest }) {
2828
+ const pct = max > 0 ? Math.min(100, Math.max(0, value / max * 100)) : 0;
2829
+ return /* @__PURE__ */ jsxs58("div", { className: ["fds-meter", className].filter(Boolean).join(" "), ...rest, children: [
2830
+ /* @__PURE__ */ jsx68(
2831
+ "span",
2832
+ {
2833
+ className: "fds-meter__track",
2834
+ role: "meter",
2835
+ "aria-valuemin": 0,
2836
+ "aria-valuemax": max,
2837
+ "aria-valuenow": value,
2838
+ "aria-label": typeof label === "string" ? label : void 0,
2839
+ children: /* @__PURE__ */ jsx68("span", { className: "fds-meter__fill", style: { "--fds-meter": `${pct}%` } })
2840
+ }
2841
+ ),
2842
+ /* @__PURE__ */ jsx68("span", { className: "fds-meter__label", children: label })
2843
+ ] });
2844
+ }
2845
+
2846
+ // src/components/ConnectionCard/ConnectionCard.tsx
2847
+ import { jsx as jsx69, jsxs as jsxs59 } from "react/jsx-runtime";
2848
+ function ConnectionCard({ icon, iconTone = "light", title, subtitle, footer, className, children, ...rest }) {
2849
+ return /* @__PURE__ */ jsxs59("section", { className: ["fds-connection-card", className].filter(Boolean).join(" "), ...rest, children: [
2850
+ /* @__PURE__ */ jsxs59("header", { className: "fds-connection-card__head", children: [
2851
+ /* @__PURE__ */ jsx69("span", { className: `fds-connection-card__icon fds-connection-card__icon--${iconTone}`, "aria-hidden": "true", children: icon }),
2852
+ /* @__PURE__ */ jsxs59("span", { className: "fds-connection-card__titles", children: [
2853
+ /* @__PURE__ */ jsx69("span", { className: "fds-connection-card__title", children: title }),
2854
+ subtitle != null && /* @__PURE__ */ jsx69("span", { className: "fds-connection-card__subtitle", children: subtitle })
2855
+ ] })
2856
+ ] }),
2857
+ children != null && /* @__PURE__ */ jsx69("div", { className: "fds-connection-card__body", children }),
2858
+ footer != null && /* @__PURE__ */ jsx69("footer", { className: "fds-connection-card__footer", children: footer })
2859
+ ] });
2860
+ }
2861
+
2862
+ // src/components/ListRow/ListRow.tsx
2863
+ import { ChevronRight } from "lucide-react";
2864
+ import { jsx as jsx70, jsxs as jsxs60 } from "react/jsx-runtime";
2865
+ function ListRow({ as, leading, title, description, trailing, className, ...rest }) {
2866
+ const Root = as ?? "button";
2867
+ const extra = Root === "button" ? { type: "button" } : {};
2868
+ return /* @__PURE__ */ jsxs60(Root, { className: ["fds-list-row", className].filter(Boolean).join(" "), ...extra, ...rest, children: [
2869
+ leading != null && /* @__PURE__ */ jsx70("span", { className: "fds-list-row__leading", children: leading }),
2870
+ /* @__PURE__ */ jsxs60("span", { className: "fds-list-row__text", children: [
2871
+ /* @__PURE__ */ jsx70("span", { className: "fds-list-row__title", children: title }),
2872
+ description != null && /* @__PURE__ */ jsx70("span", { className: "fds-list-row__description", children: description })
2873
+ ] }),
2874
+ /* @__PURE__ */ jsx70("span", { className: "fds-list-row__trailing", "aria-hidden": trailing == null || void 0, children: trailing ?? /* @__PURE__ */ jsx70(ChevronRight, {}) })
2875
+ ] });
2876
+ }
2877
+
2878
+ // src/components/CodeBlock/CodeBlock.tsx
2879
+ import { useEffect as useEffect11, useState as useState11 } from "react";
2880
+ import { Check as Check4, Copy } from "lucide-react";
2881
+ import { jsx as jsx71, jsxs as jsxs61 } from "react/jsx-runtime";
2882
+ function CodeBlock({ code, copyLabel = "Copy", variant = "inline", className, ...rest }) {
2883
+ const [copied, setCopied] = useState11(false);
2884
+ useEffect11(() => {
2885
+ if (!copied) return;
2886
+ const t = window.setTimeout(() => setCopied(false), 1600);
2887
+ return () => window.clearTimeout(t);
2888
+ }, [copied]);
2889
+ const copy = () => {
2890
+ void navigator.clipboard?.writeText(code).then(() => setCopied(true), () => {
2891
+ });
2892
+ };
2893
+ return /* @__PURE__ */ jsxs61("div", { className: ["fds-code-block", `fds-code-block--${variant}`, className].filter(Boolean).join(" "), ...rest, children: [
2894
+ /* @__PURE__ */ jsx71("pre", { className: "fds-code-block__code", children: /* @__PURE__ */ jsx71("code", { children: code }) }),
2895
+ /* @__PURE__ */ jsx71("button", { type: "button", className: "fds-code-block__copy", "aria-label": copied ? "Copied" : copyLabel, onClick: copy, children: copied ? /* @__PURE__ */ jsx71(Check4, { "aria-hidden": "true" }) : /* @__PURE__ */ jsx71(Copy, { "aria-hidden": "true" }) })
2896
+ ] });
2897
+ }
2580
2898
  export {
2581
2899
  Accordion,
2582
2900
  AppLayout,
@@ -2591,15 +2909,25 @@ export {
2591
2909
  Card,
2592
2910
  Checkbox,
2593
2911
  Checklist,
2912
+ CodeBlock,
2913
+ ColorRamp,
2914
+ ConnectionCard,
2915
+ DescriptionList,
2594
2916
  DiffPropertyList,
2595
2917
  DiffSection,
2596
2918
  Divider,
2597
2919
  Drawer,
2920
+ EasingCurve,
2598
2921
  EmptyState,
2922
+ FilterChips,
2599
2923
  IconButton,
2600
2924
  Input,
2925
+ ListCard,
2601
2926
  ListLabel,
2927
+ ListRow,
2928
+ MeasureList,
2602
2929
  Menu,
2930
+ Meter,
2603
2931
  MismatchCard,
2604
2932
  Modal,
2605
2933
  MultiSelect,
@@ -2609,6 +2937,7 @@ export {
2609
2937
  PageHeader,
2610
2938
  PageSkeleton,
2611
2939
  Pagination,
2940
+ PreviewCard,
2612
2941
  PricingCard,
2613
2942
  Radio,
2614
2943
  RadioCard,
@@ -2630,13 +2959,19 @@ export {
2630
2959
  StepList,
2631
2960
  Stepper,
2632
2961
  Swatch,
2962
+ SwatchList,
2633
2963
  TabNav,
2634
2964
  Table,
2635
2965
  Tag,
2966
+ Tile,
2636
2967
  Toast,
2637
2968
  ToastRegion,
2638
2969
  Toggle,
2970
+ TokenSample,
2639
2971
  Tooltip,
2972
+ TypeSample,
2973
+ TypeScale,
2974
+ TypeSpecimen,
2640
2975
  WorkspaceAvatar,
2641
2976
  WorkspaceSwitcher,
2642
2977
  breakpoints,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@usefidel/design-system",
3
- "version": "0.26.0",
3
+ "version": "0.28.0",
4
4
  "description": "Fidel brand design tokens + React component library — DTCG token source of truth, generated per-surface CSS + Tailwind-v4 parser-compatibility output, and on-brand React components (Button, MismatchCard, DiffSection).",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -42,20 +42,25 @@
42
42
  "typecheck": "tsc --noEmit",
43
43
  "surface-check": "node build/surface-check.mjs",
44
44
  "test": "node --test test/*.test.mjs",
45
- "gitleaks": "gitleaks detect --no-banner --redact -v"
45
+ "gitleaks": "gitleaks detect --no-banner --redact -v",
46
+ "storybook": "storybook dev -p 6006",
47
+ "build-storybook": "storybook build -o storybook-static"
46
48
  },
47
49
  "peerDependencies": {
48
50
  "react": ">=18",
49
51
  "react-dom": ">=18"
50
52
  },
51
53
  "devDependencies": {
54
+ "@storybook/react-vite": "10.6.2",
52
55
  "@types/react": "^18.3.12",
53
56
  "@types/react-dom": "^18.3.1",
54
57
  "react": "^18.3.1",
55
58
  "react-dom": "^18.3.1",
59
+ "storybook": "10.6.2",
56
60
  "style-dictionary": "^4.3.0",
57
61
  "tsup": "^8.3.5",
58
- "typescript": "^5.6.3"
62
+ "typescript": "^5.6.3",
63
+ "vite": "8.3.4"
59
64
  },
60
65
  "dependencies": {
61
66
  "lucide-react": "^1.33.0"