@usefidel/design-system 0.18.0 → 0.20.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
@@ -358,7 +358,11 @@ var Select = forwardRef(function Select2({
358
358
  id,
359
359
  name,
360
360
  className,
361
- containerClassName
361
+ containerClassName,
362
+ variant = "field",
363
+ size = "medium",
364
+ align = "start",
365
+ "aria-label": ariaLabel
362
366
  }, ref) {
363
367
  const genId = useId();
364
368
  const triggerId = id ?? genId;
@@ -377,7 +381,7 @@ var Select = forwardRef(function Select2({
377
381
  if (!searchable || !query.trim()) return options;
378
382
  const q = query.trim().toLowerCase();
379
383
  return options.filter(
380
- (o) => o.label.toLowerCase().includes(q) || (o.secondary?.toLowerCase().includes(q) ?? false)
384
+ (o) => o.label.toLowerCase().includes(q) || (o.secondary?.toLowerCase().includes(q) ?? false) || (o.description?.toLowerCase().includes(q) ?? false)
381
385
  );
382
386
  }, [options, searchable, query]);
383
387
  const hasMessage = Boolean(error ?? hint);
@@ -460,6 +464,8 @@ var Select = forwardRef(function Select2({
460
464
  };
461
465
  const triggerClasses = [
462
466
  "fds-select__trigger",
467
+ variant === "inline" ? "fds-select__trigger--inline" : "",
468
+ size === "small" ? "fds-select__trigger--small" : "",
463
469
  error ? "fds-select__trigger--error" : "",
464
470
  open ? "fds-select__trigger--open" : "",
465
471
  className
@@ -468,7 +474,7 @@ var Select = forwardRef(function Select2({
468
474
  "div",
469
475
  {
470
476
  ref: rootRef,
471
- className: ["fds-select-field", containerClassName].filter(Boolean).join(" "),
477
+ className: ["fds-select-field", variant === "inline" ? "fds-select-field--inline" : "", containerClassName].filter(Boolean).join(" "),
472
478
  children: [
473
479
  label != null && /* @__PURE__ */ jsx5("label", { htmlFor: triggerId, className: "fds-select__label", children: label }),
474
480
  /* @__PURE__ */ jsxs5("div", { className: "fds-select", children: [
@@ -485,6 +491,7 @@ var Select = forwardRef(function Select2({
485
491
  "aria-controls": open ? listId : void 0,
486
492
  "aria-invalid": error ? true : void 0,
487
493
  "aria-describedby": hasMessage ? msgId : void 0,
494
+ "aria-label": ariaLabel,
488
495
  onClick: () => !disabled && setOpen((o) => !o),
489
496
  onKeyDown,
490
497
  children: [
@@ -500,7 +507,7 @@ var Select = forwardRef(function Select2({
500
507
  ]
501
508
  }
502
509
  ),
503
- open && /* @__PURE__ */ jsxs5("div", { className: "fds-select__popover", children: [
510
+ open && /* @__PURE__ */ jsxs5("div", { className: `fds-select__popover fds-select__popover--${align}`, children: [
504
511
  searchable && /* @__PURE__ */ jsx5("div", { className: "fds-select__search", children: /* @__PURE__ */ jsx5(
505
512
  "input",
506
513
  {
@@ -545,9 +552,12 @@ var Select = forwardRef(function Select2({
545
552
  onClick: () => choose(i),
546
553
  children: [
547
554
  o.avatar != null && /* @__PURE__ */ jsx5("span", { className: "fds-select__optAvatar", children: o.avatar }),
548
- /* @__PURE__ */ jsxs5("span", { className: "fds-select__optText", children: [
549
- /* @__PURE__ */ jsx5("span", { className: "fds-select__optLabel", children: o.label }),
550
- o.secondary != null && /* @__PURE__ */ jsx5("span", { className: "fds-select__optSecondary", children: o.secondary })
555
+ /* @__PURE__ */ jsxs5("span", { className: "fds-select__optBody", children: [
556
+ /* @__PURE__ */ jsxs5("span", { className: "fds-select__optText", children: [
557
+ /* @__PURE__ */ jsx5("span", { className: "fds-select__optLabel", children: o.label }),
558
+ o.secondary != null && /* @__PURE__ */ jsx5("span", { className: "fds-select__optSecondary", children: o.secondary })
559
+ ] }),
560
+ o.description != null && /* @__PURE__ */ jsx5("span", { className: "fds-select__optDescription", children: o.description })
551
561
  ] }),
552
562
  o.value === value && /* @__PURE__ */ jsx5("span", { className: "fds-select__check", children: /* @__PURE__ */ jsx5(CheckIcon, {}) })
553
563
  ]
@@ -809,6 +819,7 @@ function SegmentedControl({
809
819
  value,
810
820
  onChange,
811
821
  "aria-label": ariaLabel,
822
+ variant = "underline",
812
823
  className
813
824
  }) {
814
825
  const refs = useRef4([]);
@@ -825,7 +836,7 @@ function SegmentedControl({
825
836
  onChange(options[next].value);
826
837
  refs.current[next]?.focus();
827
838
  };
828
- const classes = ["fds-segmented", className].filter(Boolean).join(" ");
839
+ const classes = ["fds-segmented", variant === "pill" ? "fds-segmented--pill" : "", className].filter(Boolean).join(" ");
829
840
  return /* @__PURE__ */ jsx11("div", { role: "tablist", "aria-label": ariaLabel, className: classes, children: options.map((option, i) => {
830
841
  const selected = option.value === value;
831
842
  return /* @__PURE__ */ jsxs10(
@@ -954,11 +965,17 @@ import { jsx as jsx17, jsxs as jsxs15 } from "react/jsx-runtime";
954
965
  function ChevronIcon2() {
955
966
  return /* @__PURE__ */ jsx17("svg", { viewBox: "0 0 20 20", width: "20", height: "20", fill: "none", "aria-hidden": "true", className: "fds-multiselect__chevronIcon", children: /* @__PURE__ */ jsx17("path", { d: "M6 8l4 4 4-4", stroke: "currentColor", strokeWidth: "1.6", strokeLinecap: "round", strokeLinejoin: "round" }) });
956
967
  }
968
+ function RemoveIcon() {
969
+ return /* @__PURE__ */ jsx17("svg", { viewBox: "0 0 12 12", width: "10", height: "10", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx17("path", { d: "M3 3l6 6M9 3L3 9", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" }) });
970
+ }
957
971
  function CheckIcon2() {
958
972
  return /* @__PURE__ */ jsx17("svg", { viewBox: "0 0 12 12", width: "12", height: "12", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx17("path", { d: "M10 3L4.5 8.5 2 6", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) });
959
973
  }
960
974
  function MultiSelect({
961
975
  label,
976
+ variant = "filter",
977
+ placeholder,
978
+ showActions,
962
979
  options,
963
980
  value,
964
981
  onChange,
@@ -1029,8 +1046,59 @@ function MultiSelect({
1029
1046
  }
1030
1047
  };
1031
1048
  const triggerClasses = ["fds-multiselect__trigger", open ? "fds-multiselect__trigger--open" : ""].filter(Boolean).join(" ");
1032
- return /* @__PURE__ */ jsxs15("div", { ref: rootRef, className: ["fds-multiselect", className].filter(Boolean).join(" "), children: [
1033
- /* @__PURE__ */ jsxs15(
1049
+ const isField = variant === "field";
1050
+ const withActions = showActions ?? !isField;
1051
+ const chosen = options.filter((o) => selected.has(o.value));
1052
+ const fieldBox = /* @__PURE__ */ jsxs15(
1053
+ "div",
1054
+ {
1055
+ className: ["fds-multiselect__fieldBox", open ? "fds-multiselect__fieldBox--open" : "", disabled ? "fds-multiselect__fieldBox--disabled" : ""].filter(Boolean).join(" "),
1056
+ onClick: (e) => {
1057
+ if (disabled || e.target.closest("button")) return;
1058
+ setActiveIndex(0);
1059
+ setOpen((o) => !o);
1060
+ },
1061
+ children: [
1062
+ /* @__PURE__ */ jsxs15("span", { className: "fds-multiselect__chips", children: [
1063
+ chosen.length === 0 && placeholder != null && /* @__PURE__ */ jsx17("span", { className: "fds-multiselect__placeholder", children: placeholder }),
1064
+ chosen.map((o) => /* @__PURE__ */ jsxs15("span", { className: "fds-multiselect__chip", children: [
1065
+ o.label,
1066
+ /* @__PURE__ */ jsx17(
1067
+ "button",
1068
+ {
1069
+ type: "button",
1070
+ className: "fds-multiselect__chipRemove",
1071
+ "aria-label": `Remove ${o.label}`,
1072
+ disabled,
1073
+ onClick: () => toggle(o),
1074
+ children: /* @__PURE__ */ jsx17(RemoveIcon, {})
1075
+ }
1076
+ )
1077
+ ] }, o.value))
1078
+ ] }),
1079
+ /* @__PURE__ */ jsx17(
1080
+ "button",
1081
+ {
1082
+ type: "button",
1083
+ id: triggerId,
1084
+ ref: triggerRef,
1085
+ className: "fds-multiselect__fieldBoxToggle",
1086
+ disabled,
1087
+ "aria-haspopup": "listbox",
1088
+ "aria-expanded": open,
1089
+ "aria-controls": open ? listId : void 0,
1090
+ "aria-label": `${label}: ${chosen.length === 0 ? "none chosen" : `${chosen.length} chosen`}`,
1091
+ onClick: () => setOpen((o) => !o),
1092
+ onKeyDown: onTriggerKeyDown,
1093
+ children: /* @__PURE__ */ jsx17("span", { className: `fds-multiselect__chevron${open ? " fds-multiselect__chevron--open" : ""}`, children: /* @__PURE__ */ jsx17(ChevronIcon2, {}) })
1094
+ }
1095
+ )
1096
+ ]
1097
+ }
1098
+ );
1099
+ return /* @__PURE__ */ jsxs15("div", { ref: rootRef, className: ["fds-multiselect", isField ? "fds-multiselect--field" : "", className].filter(Boolean).join(" "), children: [
1100
+ isField && /* @__PURE__ */ jsx17("label", { htmlFor: triggerId, className: "fds-multiselect__fieldLabel", children: label }),
1101
+ isField ? fieldBox : /* @__PURE__ */ jsxs15(
1034
1102
  "button",
1035
1103
  {
1036
1104
  type: "button",
@@ -1096,7 +1164,7 @@ function MultiSelect({
1096
1164
  })
1097
1165
  }
1098
1166
  ),
1099
- /* @__PURE__ */ jsxs15("div", { className: "fds-multiselect__footer", children: [
1167
+ withActions && /* @__PURE__ */ jsxs15("div", { className: "fds-multiselect__footer", children: [
1100
1168
  /* @__PURE__ */ jsx17("button", { type: "button", className: "fds-multiselect__action", onClick: () => onChange(enabled.map((o) => o.value)), children: selectAllLabel }),
1101
1169
  /* @__PURE__ */ jsx17("button", { type: "button", className: "fds-multiselect__action", onClick: () => onChange([]), children: clearLabel })
1102
1170
  ] })
@@ -1110,7 +1178,7 @@ import { jsx as jsx18, jsxs as jsxs16 } from "react/jsx-runtime";
1110
1178
  var SearchInput = forwardRef3(function SearchInput2({ shortcut, containerClassName, className, value, ...rest }, ref) {
1111
1179
  const empty = value === void 0 || value === "";
1112
1180
  return /* @__PURE__ */ jsxs16("div", { className: ["fds-search", containerClassName].filter(Boolean).join(" "), children: [
1113
- /* @__PURE__ */ jsxs16("svg", { className: "fds-search__icon", viewBox: "0 0 24 24", width: "20", height: "20", fill: "none", "aria-hidden": "true", children: [
1181
+ /* @__PURE__ */ jsxs16("svg", { className: "fds-search__icon", viewBox: "0 0 24 24", width: "16", height: "16", fill: "none", "aria-hidden": "true", children: [
1114
1182
  /* @__PURE__ */ jsx18("circle", { cx: "11", cy: "11", r: "8", stroke: "currentColor", strokeWidth: "2" }),
1115
1183
  /* @__PURE__ */ jsx18("path", { d: "m21 21-4.3-4.3", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" })
1116
1184
  ] }),
@@ -1180,8 +1248,8 @@ function Pagination({ page, pageCount, onPageChange, total, pageSize, variant =
1180
1248
 
1181
1249
  // src/components/EmptyState/EmptyState.tsx
1182
1250
  import { jsx as jsx20, jsxs as jsxs18 } from "react/jsx-runtime";
1183
- function EmptyState({ illustration, title, description, action, footer, className, ...rest }) {
1184
- return /* @__PURE__ */ jsxs18("div", { className: ["fds-empty", className].filter(Boolean).join(" "), ...rest, children: [
1251
+ function EmptyState({ illustration, title, description, action, footer, size = "default", className, ...rest }) {
1252
+ return /* @__PURE__ */ jsxs18("div", { className: ["fds-empty", size === "compact" ? "fds-empty--compact" : "", className].filter(Boolean).join(" "), ...rest, children: [
1185
1253
  illustration != null && /* @__PURE__ */ jsx20("div", { className: "fds-empty__illustration", children: illustration }),
1186
1254
  /* @__PURE__ */ jsxs18("div", { className: "fds-empty__text", children: [
1187
1255
  /* @__PURE__ */ jsx20("h2", { className: "fds-empty__title", children: title }),
@@ -1441,6 +1509,252 @@ function StepList({ steps, className, ...rest }) {
1441
1509
  step.id
1442
1510
  )) });
1443
1511
  }
1512
+
1513
+ // src/components/Input/Input.tsx
1514
+ import { forwardRef as forwardRef6, useId as useId10 } from "react";
1515
+ import { jsx as jsx29, jsxs as jsxs25 } from "react/jsx-runtime";
1516
+ var Input = forwardRef6(function Input2({ label, hint, error, leadingIcon, trailing, id, className, containerClassName, readOnly, disabled, ...rest }, ref) {
1517
+ const genId = useId10();
1518
+ const inputId = id ?? genId;
1519
+ const msgId = `${genId}-msg`;
1520
+ const message = error ?? hint;
1521
+ const boxClasses = [
1522
+ "fds-input__box",
1523
+ error ? "fds-input__box--error" : "",
1524
+ readOnly || disabled ? "fds-input__box--locked" : ""
1525
+ ].filter(Boolean).join(" ");
1526
+ return /* @__PURE__ */ jsxs25("div", { className: ["fds-input", containerClassName].filter(Boolean).join(" "), children: [
1527
+ label != null && /* @__PURE__ */ jsx29("label", { htmlFor: inputId, className: "fds-input__label", children: label }),
1528
+ /* @__PURE__ */ jsxs25("div", { className: boxClasses, children: [
1529
+ leadingIcon != null && /* @__PURE__ */ jsx29("span", { className: "fds-input__icon", "aria-hidden": "true", children: leadingIcon }),
1530
+ /* @__PURE__ */ jsx29(
1531
+ "input",
1532
+ {
1533
+ ref,
1534
+ id: inputId,
1535
+ className: ["fds-input__control", className].filter(Boolean).join(" "),
1536
+ readOnly,
1537
+ disabled,
1538
+ "aria-invalid": error ? true : void 0,
1539
+ "aria-describedby": message != null ? msgId : void 0,
1540
+ ...rest
1541
+ }
1542
+ ),
1543
+ trailing != null && /* @__PURE__ */ jsx29("span", { className: "fds-input__trailing", children: trailing })
1544
+ ] }),
1545
+ message != null && /* @__PURE__ */ jsx29("p", { id: msgId, className: error ? "fds-input__error" : "fds-input__hint", children: message })
1546
+ ] });
1547
+ });
1548
+
1549
+ // src/components/IconButton/IconButton.tsx
1550
+ import { jsx as jsx30 } from "react/jsx-runtime";
1551
+ function IconButton({
1552
+ icon,
1553
+ variant = "outlined",
1554
+ size = "medium",
1555
+ type = "button",
1556
+ className,
1557
+ ...rest
1558
+ }) {
1559
+ const classes = ["fds-icon-button", `fds-icon-button--${variant}`, `fds-icon-button--${size}`, className].filter(Boolean).join(" ");
1560
+ return /* @__PURE__ */ jsx30("button", { type, className: classes, ...rest, children: /* @__PURE__ */ jsx30("span", { className: "fds-icon-button__icon", "aria-hidden": "true", children: icon }) });
1561
+ }
1562
+
1563
+ // src/components/Menu/Menu.tsx
1564
+ import {
1565
+ cloneElement,
1566
+ useEffect as useEffect6,
1567
+ useId as useId11,
1568
+ useRef as useRef7,
1569
+ useState as useState8
1570
+ } from "react";
1571
+ import { jsx as jsx31, jsxs as jsxs26 } from "react/jsx-runtime";
1572
+ function Menu({ trigger, items, align = "end", className }) {
1573
+ const listId = useId11();
1574
+ const rootRef = useRef7(null);
1575
+ const listRef = useRef7(null);
1576
+ const [open, setOpen] = useState8(false);
1577
+ const [active, setActive] = useState8(0);
1578
+ const enabled = items.map((it, i) => it.disabled ? -1 : i).filter((i) => i >= 0);
1579
+ useEffect6(() => {
1580
+ if (!open) return;
1581
+ const onDown = (e) => {
1582
+ if (rootRef.current && !rootRef.current.contains(e.target)) setOpen(false);
1583
+ };
1584
+ document.addEventListener("mousedown", onDown);
1585
+ const raf = requestAnimationFrame(() => listRef.current?.focus());
1586
+ return () => {
1587
+ document.removeEventListener("mousedown", onDown);
1588
+ cancelAnimationFrame(raf);
1589
+ };
1590
+ }, [open]);
1591
+ const triggerEl = () => rootRef.current?.querySelector('[aria-haspopup="menu"]');
1592
+ const close = () => {
1593
+ setOpen(false);
1594
+ triggerEl()?.focus();
1595
+ };
1596
+ const openAt = (index) => {
1597
+ setActive(index);
1598
+ setOpen(true);
1599
+ };
1600
+ const choose = (i) => {
1601
+ const it = items[i];
1602
+ if (!it || it.disabled) return;
1603
+ close();
1604
+ it.onSelect();
1605
+ };
1606
+ const step = (dir) => {
1607
+ if (enabled.length === 0) return;
1608
+ const at = enabled.indexOf(active);
1609
+ setActive(enabled[(at + dir + enabled.length) % enabled.length]);
1610
+ };
1611
+ const onListKeyDown = (e) => {
1612
+ if (e.key === "ArrowDown") {
1613
+ e.preventDefault();
1614
+ step(1);
1615
+ } else if (e.key === "ArrowUp") {
1616
+ e.preventDefault();
1617
+ step(-1);
1618
+ } else if (e.key === "Home") {
1619
+ e.preventDefault();
1620
+ setActive(enabled[0] ?? 0);
1621
+ } else if (e.key === "End") {
1622
+ e.preventDefault();
1623
+ setActive(enabled[enabled.length - 1] ?? 0);
1624
+ } else if (e.key === "Enter" || e.key === " ") {
1625
+ e.preventDefault();
1626
+ choose(active);
1627
+ } else if (e.key === "Escape") {
1628
+ e.preventDefault();
1629
+ close();
1630
+ } else if (e.key === "Tab") setOpen(false);
1631
+ };
1632
+ const own = trigger.props;
1633
+ const wired = cloneElement(trigger, {
1634
+ "aria-haspopup": "menu",
1635
+ "aria-expanded": open,
1636
+ "aria-controls": open ? listId : void 0,
1637
+ onClick: (e) => {
1638
+ own.onClick?.(e);
1639
+ if (open) setOpen(false);
1640
+ else openAt(enabled[0] ?? 0);
1641
+ },
1642
+ onKeyDown: (e) => {
1643
+ own.onKeyDown?.(e);
1644
+ if (!open && (e.key === "ArrowDown" || e.key === "Enter" || e.key === " ")) {
1645
+ e.preventDefault();
1646
+ openAt(enabled[0] ?? 0);
1647
+ } else if (!open && e.key === "ArrowUp") {
1648
+ e.preventDefault();
1649
+ openAt(enabled[enabled.length - 1] ?? 0);
1650
+ }
1651
+ }
1652
+ });
1653
+ return /* @__PURE__ */ jsxs26("div", { ref: rootRef, className: ["fds-menu", className].filter(Boolean).join(" "), children: [
1654
+ wired,
1655
+ open && /* @__PURE__ */ jsx31(
1656
+ "div",
1657
+ {
1658
+ ref: listRef,
1659
+ id: listId,
1660
+ role: "menu",
1661
+ tabIndex: -1,
1662
+ className: `fds-menu__list fds-menu__list--${align}`,
1663
+ "aria-activedescendant": `${listId}-item-${active}`,
1664
+ onKeyDown: onListKeyDown,
1665
+ children: items.map((it, i) => /* @__PURE__ */ jsxs26(
1666
+ "div",
1667
+ {
1668
+ id: `${listId}-item-${i}`,
1669
+ role: "menuitem",
1670
+ "aria-disabled": it.disabled || void 0,
1671
+ className: [
1672
+ "fds-menu__item",
1673
+ it.tone === "danger" ? "fds-menu__item--danger" : "",
1674
+ i === active ? "fds-menu__item--active" : "",
1675
+ it.disabled ? "fds-menu__item--disabled" : ""
1676
+ ].filter(Boolean).join(" "),
1677
+ onMouseEnter: () => !it.disabled && setActive(i),
1678
+ onMouseDown: (e) => e.preventDefault(),
1679
+ onClick: () => choose(i),
1680
+ children: [
1681
+ it.icon != null && /* @__PURE__ */ jsx31("span", { className: "fds-menu__icon", "aria-hidden": "true", children: it.icon }),
1682
+ it.label
1683
+ ]
1684
+ },
1685
+ i
1686
+ ))
1687
+ }
1688
+ )
1689
+ ] });
1690
+ }
1691
+
1692
+ // src/components/Table/Table.tsx
1693
+ import { jsx as jsx32, jsxs as jsxs27 } from "react/jsx-runtime";
1694
+ function Table({ columns, rows, rowKey, empty, className, "aria-label": ariaLabel, ...rest }) {
1695
+ return /* @__PURE__ */ jsx32("div", { className: ["fds-table", className].filter(Boolean).join(" "), ...rest, children: /* @__PURE__ */ jsxs27("table", { className: "fds-table__table", "aria-label": ariaLabel, children: [
1696
+ /* @__PURE__ */ jsx32("thead", { children: /* @__PURE__ */ jsx32("tr", { children: columns.map((c) => /* @__PURE__ */ jsx32(
1697
+ "th",
1698
+ {
1699
+ scope: "col",
1700
+ className: c.align === "end" ? "fds-table__cell--end" : void 0,
1701
+ style: c.width ? { width: c.width } : void 0,
1702
+ children: c.header
1703
+ },
1704
+ c.key
1705
+ )) }) }),
1706
+ /* @__PURE__ */ jsxs27("tbody", { children: [
1707
+ rows.map((row) => /* @__PURE__ */ jsx32("tr", { children: columns.map((c) => /* @__PURE__ */ jsx32("td", { className: c.align === "end" ? "fds-table__cell--end" : void 0, children: c.cell(row) }, c.key)) }, rowKey(row))),
1708
+ rows.length === 0 && empty != null && /* @__PURE__ */ jsx32("tr", { children: /* @__PURE__ */ jsx32("td", { colSpan: columns.length, className: "fds-table__empty", children: empty }) })
1709
+ ] })
1710
+ ] }) });
1711
+ }
1712
+
1713
+ // src/components/PricingCard/PricingCard.tsx
1714
+ import { jsx as jsx33, jsxs as jsxs28 } from "react/jsx-runtime";
1715
+ function CheckIcon3() {
1716
+ return /* @__PURE__ */ jsx33("svg", { viewBox: "0 0 16 16", width: "12", height: "12", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx33("path", { d: "M3.5 8.5l3 3 6-7", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round", strokeLinejoin: "round" }) });
1717
+ }
1718
+ function PricingCard({
1719
+ eyebrow,
1720
+ title,
1721
+ badge,
1722
+ price,
1723
+ period,
1724
+ description,
1725
+ action,
1726
+ featuresTitle = "Features",
1727
+ featuresIntro,
1728
+ features = [],
1729
+ highlighted = false,
1730
+ className,
1731
+ ...rest
1732
+ }) {
1733
+ const classes = ["fds-pricing-card", highlighted ? "fds-pricing-card--highlighted" : "", className].filter(Boolean).join(" ");
1734
+ return /* @__PURE__ */ jsxs28("article", { className: classes, ...rest, children: [
1735
+ /* @__PURE__ */ jsxs28("div", { className: "fds-pricing-card__top", children: [
1736
+ eyebrow != null && /* @__PURE__ */ jsx33("span", { className: "fds-pricing-card__eyebrow", children: eyebrow }),
1737
+ /* @__PURE__ */ jsxs28("h3", { className: "fds-pricing-card__title", children: [
1738
+ title,
1739
+ badge
1740
+ ] }),
1741
+ /* @__PURE__ */ jsxs28("p", { className: "fds-pricing-card__price", children: [
1742
+ /* @__PURE__ */ jsx33("span", { className: "fds-pricing-card__amount", children: price }),
1743
+ period != null && /* @__PURE__ */ jsx33("span", { className: "fds-pricing-card__period", children: period })
1744
+ ] }),
1745
+ description != null && /* @__PURE__ */ jsx33("p", { className: "fds-pricing-card__description", children: description }),
1746
+ action != null && /* @__PURE__ */ jsx33("div", { className: "fds-pricing-card__action", children: action })
1747
+ ] }),
1748
+ features.length > 0 && /* @__PURE__ */ jsxs28("div", { className: "fds-pricing-card__features", children: [
1749
+ /* @__PURE__ */ jsx33("p", { className: "fds-pricing-card__featuresTitle", children: featuresTitle }),
1750
+ featuresIntro != null && /* @__PURE__ */ jsx33("p", { className: "fds-pricing-card__intro", children: featuresIntro }),
1751
+ /* @__PURE__ */ jsx33("ul", { className: "fds-pricing-card__list", children: features.map((f, i) => /* @__PURE__ */ jsxs28("li", { className: "fds-pricing-card__feature", children: [
1752
+ /* @__PURE__ */ jsx33("span", { className: "fds-pricing-card__check", children: /* @__PURE__ */ jsx33(CheckIcon3, {}) }),
1753
+ f
1754
+ ] }, i)) })
1755
+ ] })
1756
+ ] });
1757
+ }
1444
1758
  export {
1445
1759
  Accordion,
1446
1760
  AppNav,
@@ -1454,10 +1768,14 @@ export {
1454
1768
  DiffPropertyList,
1455
1769
  DiffSection,
1456
1770
  EmptyState,
1771
+ IconButton,
1772
+ Input,
1773
+ Menu,
1457
1774
  MismatchCard,
1458
1775
  Modal,
1459
1776
  MultiSelect,
1460
1777
  Pagination,
1778
+ PricingCard,
1461
1779
  Radio,
1462
1780
  SearchInput,
1463
1781
  SectionHeader,
@@ -1471,6 +1789,7 @@ export {
1471
1789
  Stat,
1472
1790
  StepList,
1473
1791
  TabNav,
1792
+ Table,
1474
1793
  Tag,
1475
1794
  Toggle,
1476
1795
  breakpoints
package/dist/landing.css CHANGED
@@ -48,9 +48,14 @@
48
48
  --color-info: #1d4ed8;
49
49
  --color-info-strong: #2563eb;
50
50
  --color-info-surface: #eff6ff;
51
+ --color-info-border: #bfdbfe;
51
52
  --color-text-on-neutral: #404040;
52
53
  --color-surface-subtle: #fafafa;
53
54
  --color-accent-pressed: #9a3412;
55
+ --color-primary-pressed: #000000;
56
+ --color-error-pressed: #7f1d1d;
57
+ --color-error-border-hover: #fca5a5;
58
+ --color-error-bg-pressed: #fee2e2;
54
59
  --font-display: 'Rethink Sans', system-ui, -apple-system, sans-serif;
55
60
  --font-body: 'Rethink Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
56
61
  --font-mono: 'JetBrains Mono', 'SF Mono', 'Fira Code', 'Cascadia Code', monospace;
@@ -75,6 +80,11 @@
75
80
  --spacing-10: 40px;
76
81
  --spacing-12: 48px;
77
82
  --spacing-16: 64px;
83
+ --size-control-xs: 28px;
84
+ --size-control-sm: 32px;
85
+ --size-control-md: 36px;
86
+ --size-control-lg: 44px;
87
+ --size-nav: 56px;
78
88
  --font-size-body: 14px;
79
89
  --font-size-display-2xl: 70px;
80
90
  --font-size-display-xl: 60px;
@@ -86,7 +96,9 @@
86
96
  --font-size-text-lg: 18px;
87
97
  --font-size-text-md: 16px;
88
98
  --font-size-text-sm: 14px;
99
+ --font-size-text-compact: 13px;
89
100
  --font-size-text-xs: 12px;
101
+ --font-size-text-2xs: 11px;
90
102
  --font-size-label-sm: 14px;
91
103
  --font-size-label-xs: 12px;
92
104
  --line-height-body: 1.6;
@@ -100,7 +112,9 @@
100
112
  --line-height-text-lg: 26px;
101
113
  --line-height-text-md: 24px;
102
114
  --line-height-text-sm: 22px;
115
+ --line-height-text-compact: 20px;
103
116
  --line-height-text-xs: 18px;
117
+ --line-height-text-2xs: 16px;
104
118
  --line-height-label-sm: 22px;
105
119
  --line-height-label-xs: 18px;
106
120
  --duration-instant: 80ms;
package/dist/theme.css CHANGED
@@ -50,9 +50,14 @@
50
50
  --color-info: #1d4ed8;
51
51
  --color-info-strong: #2563eb;
52
52
  --color-info-surface: #eff6ff;
53
+ --color-info-border: #bfdbfe;
53
54
  --color-text-on-neutral: #404040;
54
55
  --color-surface-subtle: #fafafa;
55
56
  --color-accent-pressed: #9a3412;
57
+ --color-primary-pressed: #000000;
58
+ --color-error-pressed: #7f1d1d;
59
+ --color-error-border-hover: #fca5a5;
60
+ --color-error-bg-pressed: #fee2e2;
56
61
  --font-display: 'Rethink Sans', system-ui, -apple-system, sans-serif;
57
62
  --font-body: 'Rethink Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
58
63
  --font-mono: 'JetBrains Mono', 'SF Mono', 'Fira Code', 'Cascadia Code', monospace;
@@ -77,6 +82,11 @@
77
82
  --spacing-10: 40px;
78
83
  --spacing-12: 48px;
79
84
  --spacing-16: 64px;
85
+ --size-control-xs: 28px;
86
+ --size-control-sm: 32px;
87
+ --size-control-md: 36px;
88
+ --size-control-lg: 44px;
89
+ --size-nav: 56px;
80
90
  --font-size-body: 14px;
81
91
  --font-size-display-2xl: 70px;
82
92
  --font-size-display-xl: 60px;
@@ -88,7 +98,9 @@
88
98
  --font-size-text-lg: 18px;
89
99
  --font-size-text-md: 16px;
90
100
  --font-size-text-sm: 14px;
101
+ --font-size-text-compact: 13px;
91
102
  --font-size-text-xs: 12px;
103
+ --font-size-text-2xs: 11px;
92
104
  --font-size-label-sm: 14px;
93
105
  --font-size-label-xs: 12px;
94
106
  --line-height-body: 1.6;
@@ -102,7 +114,9 @@
102
114
  --line-height-text-lg: 26px;
103
115
  --line-height-text-md: 24px;
104
116
  --line-height-text-sm: 22px;
117
+ --line-height-text-compact: 20px;
105
118
  --line-height-text-xs: 18px;
119
+ --line-height-text-2xs: 16px;
106
120
  --line-height-label-sm: 22px;
107
121
  --line-height-label-xs: 18px;
108
122
  --duration-instant: 80ms;
package/dist/webapp.css CHANGED
@@ -48,9 +48,14 @@
48
48
  --color-info: #1d4ed8;
49
49
  --color-info-strong: #2563eb;
50
50
  --color-info-surface: #eff6ff;
51
+ --color-info-border: #bfdbfe;
51
52
  --color-text-on-neutral: #404040;
52
53
  --color-surface-subtle: #fafafa;
53
54
  --color-accent-pressed: #9a3412;
55
+ --color-primary-pressed: #000000;
56
+ --color-error-pressed: #7f1d1d;
57
+ --color-error-border-hover: #fca5a5;
58
+ --color-error-bg-pressed: #fee2e2;
54
59
  --font-display: 'Rethink Sans', system-ui, -apple-system, sans-serif;
55
60
  --font-body: 'Rethink Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
56
61
  --font-mono: 'JetBrains Mono', 'SF Mono', 'Fira Code', 'Cascadia Code', monospace;
@@ -75,6 +80,11 @@
75
80
  --spacing-10: 40px;
76
81
  --spacing-12: 48px;
77
82
  --spacing-16: 64px;
83
+ --size-control-xs: 28px;
84
+ --size-control-sm: 32px;
85
+ --size-control-md: 36px;
86
+ --size-control-lg: 44px;
87
+ --size-nav: 56px;
78
88
  --font-size-body: 14px;
79
89
  --font-size-display-2xl: 70px;
80
90
  --font-size-display-xl: 60px;
@@ -86,7 +96,9 @@
86
96
  --font-size-text-lg: 18px;
87
97
  --font-size-text-md: 16px;
88
98
  --font-size-text-sm: 14px;
99
+ --font-size-text-compact: 13px;
89
100
  --font-size-text-xs: 12px;
101
+ --font-size-text-2xs: 11px;
90
102
  --font-size-label-sm: 14px;
91
103
  --font-size-label-xs: 12px;
92
104
  --line-height-body: 1.6;
@@ -100,7 +112,9 @@
100
112
  --line-height-text-lg: 26px;
101
113
  --line-height-text-md: 24px;
102
114
  --line-height-text-sm: 22px;
115
+ --line-height-text-compact: 20px;
103
116
  --line-height-text-xs: 18px;
117
+ --line-height-text-2xs: 16px;
104
118
  --line-height-label-sm: 22px;
105
119
  --line-height-label-xs: 18px;
106
120
  --duration-instant: 80ms;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@usefidel/design-system",
3
- "version": "0.18.0",
3
+ "version": "0.20.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",