@usefidel/design-system 0.24.0 → 0.25.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1248,15 +1248,18 @@ function Pagination({ page, pageCount, onPageChange, total, pageSize, variant =
1248
1248
 
1249
1249
  // src/components/EmptyState/EmptyState.tsx
1250
1250
  import { jsx as jsx20, jsxs as jsxs18 } from "react/jsx-runtime";
1251
- function EmptyState({ illustration, title, description, action, footer, size = "default", className, ...rest }) {
1251
+ function EmptyState({ illustration, title, description, action, secondaryAction, footer, size = "default", className, ...rest }) {
1252
1252
  return /* @__PURE__ */ jsxs18("div", { className: ["fds-empty", size === "compact" ? "fds-empty--compact" : "", className].filter(Boolean).join(" "), ...rest, children: [
1253
1253
  illustration != null && /* @__PURE__ */ jsx20("div", { className: "fds-empty__illustration", children: illustration }),
1254
1254
  /* @__PURE__ */ jsxs18("div", { className: "fds-empty__text", children: [
1255
1255
  /* @__PURE__ */ jsx20("h2", { className: "fds-empty__title", children: title }),
1256
1256
  description != null && /* @__PURE__ */ jsx20("p", { className: "fds-empty__description", children: description })
1257
1257
  ] }),
1258
- (action != null || footer != null) && /* @__PURE__ */ jsxs18("div", { className: "fds-empty__actions", children: [
1259
- action,
1258
+ (action != null || secondaryAction != null || footer != null) && /* @__PURE__ */ jsxs18("div", { className: "fds-empty__actions", children: [
1259
+ (action != null || secondaryAction != null) && /* @__PURE__ */ jsxs18("div", { className: "fds-empty__buttons", children: [
1260
+ action,
1261
+ secondaryAction
1262
+ ] }),
1260
1263
  footer != null && /* @__PURE__ */ jsx20("div", { className: "fds-empty__footer", children: footer })
1261
1264
  ] })
1262
1265
  ] });
@@ -1637,21 +1640,66 @@ import {
1637
1640
  useRef as useRef7,
1638
1641
  useState as useState8
1639
1642
  } from "react";
1643
+ import { Check, Search } from "lucide-react";
1640
1644
  import { jsx as jsx34, jsxs as jsxs29 } from "react/jsx-runtime";
1641
- function Menu({ trigger, items, align = "end", className }) {
1645
+ var isItem = (e) => !("type" in e);
1646
+ function searchText(it) {
1647
+ if (it.keywords) return it.keywords;
1648
+ return typeof it.label === "string" ? it.label : "";
1649
+ }
1650
+ function visibleEntries(items, query) {
1651
+ const q = query.trim().toLowerCase();
1652
+ if (!q) return items.map((_, i) => i);
1653
+ const matches = (i) => {
1654
+ const e = items[i];
1655
+ return isItem(e) && searchText(e).toLowerCase().includes(q);
1656
+ };
1657
+ const out = [];
1658
+ items.forEach((e, i) => {
1659
+ if (isItem(e)) {
1660
+ if (matches(i)) out.push(i);
1661
+ } else if (e.type === "label") {
1662
+ for (let j = i + 1; j < items.length && isItem(items[j]); j++) {
1663
+ if (matches(j)) {
1664
+ out.push(i);
1665
+ break;
1666
+ }
1667
+ }
1668
+ }
1669
+ });
1670
+ return out;
1671
+ }
1672
+ function Menu({
1673
+ trigger,
1674
+ items,
1675
+ align = "end",
1676
+ placement = "bottom",
1677
+ search,
1678
+ width = "auto",
1679
+ block = false,
1680
+ className
1681
+ }) {
1642
1682
  const listId = useId12();
1643
1683
  const rootRef = useRef7(null);
1644
1684
  const listRef = useRef7(null);
1685
+ const searchRef = useRef7(null);
1645
1686
  const [open, setOpen] = useState8(false);
1646
- const [active, setActive] = useState8(0);
1647
- const enabled = items.map((it, i) => it.disabled ? -1 : i).filter((i) => i >= 0);
1687
+ const [query, setQuery] = useState8("");
1688
+ const [active, setActive] = useState8(-1);
1689
+ const shown = visibleEntries(items, query);
1690
+ const enabled = shown.filter((i) => {
1691
+ const e = items[i];
1692
+ return isItem(e) && !e.disabled;
1693
+ });
1648
1694
  useEffect6(() => {
1649
1695
  if (!open) return;
1650
1696
  const onDown = (e) => {
1651
1697
  if (rootRef.current && !rootRef.current.contains(e.target)) setOpen(false);
1652
1698
  };
1653
1699
  document.addEventListener("mousedown", onDown);
1654
- const raf = requestAnimationFrame(() => listRef.current?.focus());
1700
+ const raf = requestAnimationFrame(
1701
+ () => (searchRef.current && !searchRef.current.disabled ? searchRef.current : listRef.current)?.focus()
1702
+ );
1655
1703
  return () => {
1656
1704
  document.removeEventListener("mousedown", onDown);
1657
1705
  cancelAnimationFrame(raf);
@@ -1662,20 +1710,26 @@ function Menu({ trigger, items, align = "end", className }) {
1662
1710
  setOpen(false);
1663
1711
  triggerEl()?.focus();
1664
1712
  };
1665
- const openAt = (index) => {
1666
- setActive(index);
1713
+ const openAt = (which) => {
1714
+ setQuery("");
1715
+ const all = visibleEntries(items, "").filter((i) => {
1716
+ const e = items[i];
1717
+ return isItem(e) && !e.disabled;
1718
+ });
1719
+ setActive((which === "first" ? all[0] : all[all.length - 1]) ?? -1);
1667
1720
  setOpen(true);
1668
1721
  };
1669
1722
  const choose = (i) => {
1670
- const it = items[i];
1671
- if (!it || it.disabled) return;
1723
+ const e = items[i];
1724
+ if (!e || !isItem(e) || e.disabled) return;
1672
1725
  close();
1673
- it.onSelect();
1726
+ e.onSelect();
1674
1727
  };
1675
1728
  const step = (dir) => {
1676
1729
  if (enabled.length === 0) return;
1677
1730
  const at = enabled.indexOf(active);
1678
- setActive(enabled[(at + dir + enabled.length) % enabled.length]);
1731
+ const next = at === -1 ? dir === 1 ? 0 : enabled.length - 1 : (at + dir + enabled.length) % enabled.length;
1732
+ setActive(enabled[next]);
1679
1733
  };
1680
1734
  const onListKeyDown = (e) => {
1681
1735
  if (e.key === "ArrowDown") {
@@ -1684,13 +1738,13 @@ function Menu({ trigger, items, align = "end", className }) {
1684
1738
  } else if (e.key === "ArrowUp") {
1685
1739
  e.preventDefault();
1686
1740
  step(-1);
1687
- } else if (e.key === "Home") {
1741
+ } else if (e.key === "Home" && !search) {
1688
1742
  e.preventDefault();
1689
- setActive(enabled[0] ?? 0);
1690
- } else if (e.key === "End") {
1743
+ setActive(enabled[0] ?? -1);
1744
+ } else if (e.key === "End" && !search) {
1691
1745
  e.preventDefault();
1692
- setActive(enabled[enabled.length - 1] ?? 0);
1693
- } else if (e.key === "Enter" || e.key === " ") {
1746
+ setActive(enabled[enabled.length - 1] ?? -1);
1747
+ } else if (e.key === "Enter" || e.key === " " && !search) {
1694
1748
  e.preventDefault();
1695
1749
  choose(active);
1696
1750
  } else if (e.key === "Escape") {
@@ -1698,6 +1752,14 @@ function Menu({ trigger, items, align = "end", className }) {
1698
1752
  close();
1699
1753
  } else if (e.key === "Tab") setOpen(false);
1700
1754
  };
1755
+ const onQuery = (value) => {
1756
+ setQuery(value);
1757
+ const first = visibleEntries(items, value).find((i) => {
1758
+ const e = items[i];
1759
+ return isItem(e) && !e.disabled;
1760
+ });
1761
+ setActive(first ?? -1);
1762
+ };
1701
1763
  const own = trigger.props;
1702
1764
  const wired = cloneElement(trigger, {
1703
1765
  "aria-haspopup": "menu",
@@ -1706,56 +1768,103 @@ function Menu({ trigger, items, align = "end", className }) {
1706
1768
  onClick: (e) => {
1707
1769
  own.onClick?.(e);
1708
1770
  if (open) setOpen(false);
1709
- else openAt(enabled[0] ?? 0);
1771
+ else openAt("first");
1710
1772
  },
1711
1773
  onKeyDown: (e) => {
1712
1774
  own.onKeyDown?.(e);
1713
1775
  if (!open && (e.key === "ArrowDown" || e.key === "Enter" || e.key === " ")) {
1714
1776
  e.preventDefault();
1715
- openAt(enabled[0] ?? 0);
1777
+ openAt("first");
1716
1778
  } else if (!open && e.key === "ArrowUp") {
1717
1779
  e.preventDefault();
1718
- openAt(enabled[enabled.length - 1] ?? 0);
1780
+ openAt("last");
1719
1781
  }
1720
1782
  }
1721
1783
  });
1722
- return /* @__PURE__ */ jsxs29("div", { ref: rootRef, className: ["fds-menu", className].filter(Boolean).join(" "), children: [
1723
- wired,
1724
- open && /* @__PURE__ */ jsx34(
1725
- "div",
1726
- {
1727
- ref: listRef,
1728
- id: listId,
1729
- role: "menu",
1730
- tabIndex: -1,
1731
- className: `fds-menu__list fds-menu__list--${align}`,
1732
- "aria-activedescendant": `${listId}-item-${active}`,
1733
- onKeyDown: onListKeyDown,
1734
- children: items.map((it, i) => /* @__PURE__ */ jsxs29(
1735
- "div",
1736
- {
1737
- id: `${listId}-item-${i}`,
1738
- role: "menuitem",
1739
- "aria-disabled": it.disabled || void 0,
1740
- className: [
1741
- "fds-menu__item",
1742
- it.tone === "danger" ? "fds-menu__item--danger" : "",
1743
- i === active ? "fds-menu__item--active" : "",
1744
- it.disabled ? "fds-menu__item--disabled" : ""
1745
- ].filter(Boolean).join(" "),
1746
- onMouseEnter: () => !it.disabled && setActive(i),
1747
- onMouseDown: (e) => e.preventDefault(),
1748
- onClick: () => choose(i),
1749
- children: [
1750
- it.icon != null && /* @__PURE__ */ jsx34("span", { className: "fds-menu__icon", "aria-hidden": "true", children: it.icon }),
1751
- it.label
1752
- ]
1753
- },
1754
- i
1755
- ))
1756
- }
1757
- )
1758
- ] });
1784
+ const listClasses = [
1785
+ "fds-menu__list",
1786
+ `fds-menu__list--${placement}`,
1787
+ placement === "right" ? "" : `fds-menu__list--${align}`,
1788
+ width === "wide" ? "fds-menu__list--wide" : ""
1789
+ ].filter(Boolean).join(" ");
1790
+ return /* @__PURE__ */ jsxs29(
1791
+ "div",
1792
+ {
1793
+ ref: rootRef,
1794
+ className: ["fds-menu", block ? "fds-menu--block" : "", className].filter(Boolean).join(" "),
1795
+ children: [
1796
+ wired,
1797
+ open && /* @__PURE__ */ jsxs29("div", { className: listClasses, onKeyDown: onListKeyDown, children: [
1798
+ search && /* @__PURE__ */ jsxs29("div", { className: "fds-menu__search", children: [
1799
+ /* @__PURE__ */ jsx34(Search, { "aria-hidden": "true" }),
1800
+ /* @__PURE__ */ jsx34(
1801
+ "input",
1802
+ {
1803
+ ref: searchRef,
1804
+ type: "text",
1805
+ value: query,
1806
+ placeholder: search.placeholder,
1807
+ disabled: search.disabled,
1808
+ "aria-label": search.placeholder,
1809
+ "aria-controls": listId,
1810
+ "aria-activedescendant": active >= 0 ? `${listId}-item-${active}` : void 0,
1811
+ onChange: (e) => onQuery(e.target.value)
1812
+ }
1813
+ )
1814
+ ] }),
1815
+ /* @__PURE__ */ jsxs29(
1816
+ "div",
1817
+ {
1818
+ ref: listRef,
1819
+ id: listId,
1820
+ role: "menu",
1821
+ tabIndex: -1,
1822
+ className: "fds-menu__items",
1823
+ "aria-activedescendant": (!search || search.disabled) && active >= 0 ? `${listId}-item-${active}` : void 0,
1824
+ children: [
1825
+ shown.length === 0 && search && /* @__PURE__ */ jsx34("div", { className: "fds-menu__empty", children: search.emptyLabel }),
1826
+ shown.map((i) => {
1827
+ const e = items[i];
1828
+ if (!isItem(e)) {
1829
+ return e.type === "label" ? /* @__PURE__ */ jsx34("div", { className: "fds-menu__label", role: "presentation", children: e.label }, i) : /* @__PURE__ */ jsx34("div", { className: "fds-menu__divider", role: "separator" }, i);
1830
+ }
1831
+ return /* @__PURE__ */ jsxs29(
1832
+ "div",
1833
+ {
1834
+ id: `${listId}-item-${i}`,
1835
+ role: "menuitem",
1836
+ "aria-disabled": e.disabled || void 0,
1837
+ "aria-current": e.selected || void 0,
1838
+ className: [
1839
+ "fds-menu__item",
1840
+ e.tone === "danger" ? "fds-menu__item--danger" : "",
1841
+ i === active ? "fds-menu__item--active" : "",
1842
+ e.disabled ? "fds-menu__item--disabled" : ""
1843
+ ].filter(Boolean).join(" "),
1844
+ onMouseEnter: () => !e.disabled && setActive(i),
1845
+ onMouseDown: (ev) => ev.preventDefault(),
1846
+ onClick: () => choose(i),
1847
+ children: [
1848
+ e.avatar != null && /* @__PURE__ */ jsx34("span", { className: "fds-menu__avatar", "aria-hidden": "true", children: e.avatar }),
1849
+ e.icon != null && /* @__PURE__ */ jsx34("span", { className: "fds-menu__icon", "aria-hidden": "true", children: e.icon }),
1850
+ /* @__PURE__ */ jsxs29("span", { className: "fds-menu__text", children: [
1851
+ /* @__PURE__ */ jsx34("span", { className: "fds-menu__title", children: e.label }),
1852
+ e.description != null && /* @__PURE__ */ jsx34("span", { className: "fds-menu__description", children: e.description })
1853
+ ] }),
1854
+ e.trailing != null && /* @__PURE__ */ jsx34("span", { className: "fds-menu__trailing", children: e.trailing }),
1855
+ e.selected && /* @__PURE__ */ jsx34(Check, { className: "fds-menu__check", "aria-hidden": "true" })
1856
+ ]
1857
+ },
1858
+ i
1859
+ );
1860
+ })
1861
+ ]
1862
+ }
1863
+ )
1864
+ ] })
1865
+ ]
1866
+ }
1867
+ );
1759
1868
  }
1760
1869
 
1761
1870
  // src/components/Table/Table.tsx
@@ -1824,11 +1933,402 @@ function PricingCard({
1824
1933
  ] })
1825
1934
  ] });
1826
1935
  }
1936
+
1937
+ // src/components/StatusDot/StatusDot.tsx
1938
+ import { jsx as jsx37 } from "react/jsx-runtime";
1939
+ function StatusDot({ status, label, className, ...rest }) {
1940
+ return /* @__PURE__ */ jsx37(
1941
+ "span",
1942
+ {
1943
+ className: ["fds-status-dot", `fds-status-dot--${status}`, className].filter(Boolean).join(" "),
1944
+ role: label ? "img" : void 0,
1945
+ "aria-label": label,
1946
+ "aria-hidden": label ? void 0 : true,
1947
+ ...rest
1948
+ }
1949
+ );
1950
+ }
1951
+
1952
+ // src/components/ListLabel/ListLabel.tsx
1953
+ import { jsx as jsx38 } from "react/jsx-runtime";
1954
+ function ListLabel({ className, children, ...rest }) {
1955
+ return /* @__PURE__ */ jsx38("div", { className: ["fds-list-label", className].filter(Boolean).join(" "), ...rest, children });
1956
+ }
1957
+
1958
+ // src/components/Divider/Divider.tsx
1959
+ import { jsx as jsx39 } from "react/jsx-runtime";
1960
+ function Divider({ orientation = "horizontal", className, ...rest }) {
1961
+ return /* @__PURE__ */ jsx39(
1962
+ "hr",
1963
+ {
1964
+ className: ["fds-divider", `fds-divider--${orientation}`, className].filter(Boolean).join(" "),
1965
+ "aria-orientation": orientation,
1966
+ ...rest
1967
+ }
1968
+ );
1969
+ }
1970
+
1971
+ // src/components/Tooltip/Tooltip.tsx
1972
+ import {
1973
+ cloneElement as cloneElement2,
1974
+ useEffect as useEffect7,
1975
+ useId as useId13,
1976
+ useRef as useRef8,
1977
+ useState as useState9
1978
+ } from "react";
1979
+ import { createPortal as createPortal2 } from "react-dom";
1980
+ import { Fragment as Fragment2, jsx as jsx40, jsxs as jsxs32 } from "react/jsx-runtime";
1981
+ var GAP = 8;
1982
+ function place(rect, side) {
1983
+ switch (side) {
1984
+ case "right":
1985
+ return { top: rect.top + rect.height / 2, left: rect.right + GAP };
1986
+ case "left":
1987
+ return { top: rect.top + rect.height / 2, left: rect.left - GAP };
1988
+ case "top":
1989
+ return { top: rect.top - GAP, left: rect.left + rect.width / 2 };
1990
+ case "bottom":
1991
+ return { top: rect.bottom + GAP, left: rect.left + rect.width / 2 };
1992
+ }
1993
+ }
1994
+ function Tooltip({ content, children, side = "right", delay = 400, disabled = false }) {
1995
+ const id = useId13();
1996
+ const timer = useRef8();
1997
+ const [pos, setPos] = useState9(null);
1998
+ useEffect7(() => () => window.clearTimeout(timer.current), []);
1999
+ useEffect7(() => {
2000
+ if (disabled) setPos(null);
2001
+ }, [disabled]);
2002
+ const show = (el, wait) => {
2003
+ window.clearTimeout(timer.current);
2004
+ timer.current = window.setTimeout(() => setPos(place(el.getBoundingClientRect(), side)), wait);
2005
+ };
2006
+ const hide = () => {
2007
+ window.clearTimeout(timer.current);
2008
+ setPos(null);
2009
+ };
2010
+ if (disabled) return children;
2011
+ const own = children.props;
2012
+ const trigger = cloneElement2(children, {
2013
+ "aria-describedby": pos ? id : own["aria-describedby"],
2014
+ onMouseEnter: (e) => {
2015
+ own.onMouseEnter?.(e);
2016
+ show(e.currentTarget, delay);
2017
+ },
2018
+ onMouseLeave: (e) => {
2019
+ own.onMouseLeave?.(e);
2020
+ hide();
2021
+ },
2022
+ onFocus: (e) => {
2023
+ own.onFocus?.(e);
2024
+ if (e.currentTarget.matches(":focus-visible")) show(e.currentTarget, 0);
2025
+ },
2026
+ onBlur: (e) => {
2027
+ own.onBlur?.(e);
2028
+ hide();
2029
+ }
2030
+ });
2031
+ return /* @__PURE__ */ jsxs32(Fragment2, { children: [
2032
+ trigger,
2033
+ pos && createPortal2(
2034
+ /* @__PURE__ */ jsx40(
2035
+ "div",
2036
+ {
2037
+ id,
2038
+ role: "tooltip",
2039
+ className: `fds-tooltip fds-tooltip--${side}`,
2040
+ style: { top: pos.top, left: pos.left },
2041
+ children: content
2042
+ }
2043
+ ),
2044
+ document.body
2045
+ )
2046
+ ] });
2047
+ }
2048
+
2049
+ // src/components/BrandButton/BrandButton.tsx
2050
+ import { PanelLeftOpen } from "lucide-react";
2051
+ import { jsx as jsx41, jsxs as jsxs33 } from "react/jsx-runtime";
2052
+ function BrandButton({ mark, hoverIcon, type = "button", className, ...rest }) {
2053
+ return /* @__PURE__ */ jsxs33("button", { type, className: ["fds-brand-button", className].filter(Boolean).join(" "), ...rest, children: [
2054
+ /* @__PURE__ */ jsx41("span", { className: "fds-brand-button__mark", "aria-hidden": "true", children: mark }),
2055
+ /* @__PURE__ */ jsx41("span", { className: "fds-brand-button__hover", "aria-hidden": "true", children: hoverIcon ?? /* @__PURE__ */ jsx41(PanelLeftOpen, {}) })
2056
+ ] });
2057
+ }
2058
+
2059
+ // src/components/Sidebar/SidebarContext.ts
2060
+ import { createContext, useContext } from "react";
2061
+ var SidebarContext = createContext(null);
2062
+ function useSidebar() {
2063
+ return useContext(SidebarContext);
2064
+ }
2065
+
2066
+ // src/components/SidebarItem/SidebarItem.tsx
2067
+ import { jsx as jsx42, jsxs as jsxs34 } from "react/jsx-runtime";
2068
+ function SidebarItem({
2069
+ as,
2070
+ icon,
2071
+ leading,
2072
+ active = false,
2073
+ iconOnly,
2074
+ className,
2075
+ children,
2076
+ ...rest
2077
+ }) {
2078
+ const sidebar = useSidebar();
2079
+ const compact = iconOnly ?? sidebar?.collapsed ?? false;
2080
+ const Component = as ?? "a";
2081
+ const classes = [
2082
+ "fds-sidebar-item",
2083
+ active ? "fds-sidebar-item--active" : "",
2084
+ compact ? "fds-sidebar-item--icon-only" : "",
2085
+ className
2086
+ ].filter(Boolean).join(" ");
2087
+ return /* @__PURE__ */ jsx42(Tooltip, { content: children, disabled: !compact, children: /* @__PURE__ */ jsxs34(Component, { className: classes, "aria-current": active ? "page" : void 0, ...rest, children: [
2088
+ (leading ?? icon) != null && /* @__PURE__ */ jsx42("span", { className: leading != null ? "fds-sidebar-item__leading" : "fds-sidebar-item__icon", "aria-hidden": "true", children: leading ?? icon }),
2089
+ /* @__PURE__ */ jsx42("span", { className: "fds-sidebar-item__label", children })
2090
+ ] }) });
2091
+ }
2092
+
2093
+ // src/components/Sidebar/Sidebar.tsx
2094
+ import {
2095
+ useCallback,
2096
+ useEffect as useEffect8,
2097
+ useMemo as useMemo2,
2098
+ useRef as useRef9,
2099
+ useState as useState10
2100
+ } from "react";
2101
+ import { PanelLeftClose } from "lucide-react";
2102
+ import { jsx as jsx43, jsxs as jsxs35 } from "react/jsx-runtime";
2103
+ function SidebarRoot({
2104
+ collapsed: controlled,
2105
+ defaultCollapsed = false,
2106
+ onCollapsedChange,
2107
+ shortcut = true,
2108
+ className,
2109
+ children,
2110
+ "aria-label": ariaLabel = "Main",
2111
+ ...rest
2112
+ }) {
2113
+ const [own, setOwn] = useState10(defaultCollapsed);
2114
+ const collapsed = controlled ?? own;
2115
+ const setCollapsed = useCallback(
2116
+ (next) => {
2117
+ if (controlled === void 0) setOwn(next);
2118
+ onCollapsedChange?.(next);
2119
+ },
2120
+ [controlled, onCollapsedChange]
2121
+ );
2122
+ const toggle = useCallback(() => setCollapsed(!collapsed), [collapsed, setCollapsed]);
2123
+ useEffect8(() => {
2124
+ if (!shortcut) return;
2125
+ const onKey = (e) => {
2126
+ if ((e.metaKey || e.ctrlKey) && e.key === "\\") {
2127
+ e.preventDefault();
2128
+ toggle();
2129
+ }
2130
+ };
2131
+ window.addEventListener("keydown", onKey);
2132
+ return () => window.removeEventListener("keydown", onKey);
2133
+ }, [shortcut, toggle]);
2134
+ const state = useMemo2(() => ({ collapsed, setCollapsed, toggle }), [collapsed, setCollapsed, toggle]);
2135
+ return /* @__PURE__ */ jsx43(SidebarContext.Provider, { value: state, children: /* @__PURE__ */ jsx43(
2136
+ "nav",
2137
+ {
2138
+ className: ["fds-sidebar", collapsed ? "fds-sidebar--collapsed" : "", className].filter(Boolean).join(" "),
2139
+ "aria-label": ariaLabel,
2140
+ "data-collapsed": collapsed || void 0,
2141
+ ...rest,
2142
+ children
2143
+ }
2144
+ ) });
2145
+ }
2146
+ function useInert(on) {
2147
+ const ref = useRef9(null);
2148
+ useEffect8(() => {
2149
+ if (ref.current) ref.current.inert = on;
2150
+ }, [on]);
2151
+ return ref;
2152
+ }
2153
+ function SidebarBrand({
2154
+ logo,
2155
+ mark,
2156
+ collapseLabel = "Collapse sidebar",
2157
+ expandLabel = "Expand sidebar"
2158
+ }) {
2159
+ const sidebar = useSidebar();
2160
+ const collapsed = sidebar?.collapsed ?? false;
2161
+ const collapseRef = useInert(collapsed);
2162
+ const expandRef = useInert(!collapsed);
2163
+ return /* @__PURE__ */ jsxs35("div", { className: "fds-sidebar__brand", children: [
2164
+ /* @__PURE__ */ jsx43("span", { className: "fds-sidebar__logo", "aria-hidden": collapsed || void 0, children: logo }),
2165
+ /* @__PURE__ */ jsx43("span", { ref: collapseRef, className: "fds-sidebar__collapse", children: /* @__PURE__ */ jsx43(Tooltip, { content: collapseLabel, side: "bottom", children: /* @__PURE__ */ jsx43(
2166
+ IconButton,
2167
+ {
2168
+ variant: "ghost",
2169
+ size: "small",
2170
+ icon: /* @__PURE__ */ jsx43(PanelLeftClose, {}),
2171
+ "aria-label": collapseLabel,
2172
+ "aria-keyshortcuts": "Meta+Backslash Control+Backslash",
2173
+ onClick: () => sidebar?.setCollapsed(true)
2174
+ }
2175
+ ) }) }),
2176
+ /* @__PURE__ */ jsx43("span", { ref: expandRef, className: "fds-sidebar__expand", children: /* @__PURE__ */ jsx43(Tooltip, { content: expandLabel, children: /* @__PURE__ */ jsx43(BrandButton, { mark, "aria-label": expandLabel, onClick: () => sidebar?.setCollapsed(false) }) }) })
2177
+ ] });
2178
+ }
2179
+ function SidebarAction({ icon, label, type = "button", className, ...rest }) {
2180
+ const sidebar = useSidebar();
2181
+ const collapsed = sidebar?.collapsed ?? false;
2182
+ return /* @__PURE__ */ jsx43(Tooltip, { content: label, disabled: !collapsed, children: /* @__PURE__ */ jsxs35(
2183
+ "button",
2184
+ {
2185
+ type,
2186
+ className: ["fds-sidebar__action", className].filter(Boolean).join(" "),
2187
+ "aria-label": collapsed ? label : void 0,
2188
+ ...rest,
2189
+ children: [
2190
+ /* @__PURE__ */ jsx43("span", { className: "fds-sidebar__action-icon", "aria-hidden": "true", children: icon }),
2191
+ /* @__PURE__ */ jsx43("span", { className: "fds-sidebar__action-label", children: label })
2192
+ ]
2193
+ }
2194
+ ) });
2195
+ }
2196
+ function SidebarSection({ hideWhenCollapsed = false, className, children, ...rest }) {
2197
+ const sidebar = useSidebar();
2198
+ const hidden = hideWhenCollapsed && (sidebar?.collapsed ?? false);
2199
+ const ref = useInert(hidden);
2200
+ return /* @__PURE__ */ jsx43(
2201
+ "div",
2202
+ {
2203
+ ref,
2204
+ className: ["fds-sidebar__section", hidden ? "fds-sidebar__section--hidden" : "", className].filter(Boolean).join(" "),
2205
+ "aria-hidden": hidden || void 0,
2206
+ ...rest,
2207
+ children
2208
+ }
2209
+ );
2210
+ }
2211
+ function SidebarHeader({ className, children, ...rest }) {
2212
+ return /* @__PURE__ */ jsx43("div", { className: ["fds-sidebar__header", className].filter(Boolean).join(" "), ...rest, children });
2213
+ }
2214
+ function SidebarFooter({ className, children, ...rest }) {
2215
+ return /* @__PURE__ */ jsx43("div", { className: ["fds-sidebar__footer", className].filter(Boolean).join(" "), ...rest, children });
2216
+ }
2217
+ var Sidebar = Object.assign(SidebarRoot, {
2218
+ Header: SidebarHeader,
2219
+ Brand: SidebarBrand,
2220
+ Action: SidebarAction,
2221
+ Section: SidebarSection,
2222
+ Item: SidebarItem,
2223
+ Footer: SidebarFooter
2224
+ });
2225
+
2226
+ // src/components/WorkspaceSwitcher/WorkspaceSwitcher.tsx
2227
+ import { forwardRef as forwardRef8 } from "react";
2228
+ import { ChevronDown } from "lucide-react";
2229
+ import { jsx as jsx44, jsxs as jsxs36 } from "react/jsx-runtime";
2230
+ function WorkspaceAvatar({ name }) {
2231
+ return /* @__PURE__ */ jsx44("span", { className: "fds-workspace-avatar", "aria-hidden": "true", children: name.trim().charAt(0).toUpperCase() || "?" });
2232
+ }
2233
+ var WorkspaceSwitcher = forwardRef8(function WorkspaceSwitcher2({ name, plan, avatar, compact, type = "button", className, ...rest }, ref) {
2234
+ const sidebar = useSidebar();
2235
+ const iconOnly = compact ?? sidebar?.collapsed ?? false;
2236
+ return /* @__PURE__ */ jsxs36(
2237
+ "button",
2238
+ {
2239
+ ref,
2240
+ type,
2241
+ className: ["fds-workspace-switcher", iconOnly ? "fds-workspace-switcher--compact" : "", className].filter(Boolean).join(" "),
2242
+ "aria-label": iconOnly ? `Workspace: ${name}` : void 0,
2243
+ ...rest,
2244
+ children: [
2245
+ avatar ?? /* @__PURE__ */ jsx44(WorkspaceAvatar, { name }),
2246
+ /* @__PURE__ */ jsxs36("span", { className: "fds-workspace-switcher__text", "aria-hidden": iconOnly || void 0, children: [
2247
+ /* @__PURE__ */ jsx44("span", { className: "fds-workspace-switcher__name", children: name }),
2248
+ plan && /* @__PURE__ */ jsx44("span", { className: "fds-workspace-switcher__plan", children: plan }),
2249
+ /* @__PURE__ */ jsx44(ChevronDown, { className: "fds-workspace-switcher__chevron", "aria-hidden": "true" })
2250
+ ] })
2251
+ ]
2252
+ }
2253
+ );
2254
+ });
2255
+
2256
+ // src/components/AvatarLabelGroup/AvatarLabelGroup.tsx
2257
+ import { forwardRef as forwardRef9 } from "react";
2258
+ import { jsx as jsx45, jsxs as jsxs37 } from "react/jsx-runtime";
2259
+ var AvatarLabelGroup = forwardRef9(function AvatarLabelGroup2({ name, detail, src, compact = false, type = "button", className, ...rest }, ref) {
2260
+ return /* @__PURE__ */ jsxs37(
2261
+ "button",
2262
+ {
2263
+ ref,
2264
+ type,
2265
+ className: ["fds-avatar-label-group", compact ? "fds-avatar-label-group--compact" : "", className].filter(Boolean).join(" "),
2266
+ "aria-label": compact ? name : void 0,
2267
+ ...rest,
2268
+ children: [
2269
+ /* @__PURE__ */ jsx45(Avatar, { name, src, size: "small" }),
2270
+ /* @__PURE__ */ jsxs37("span", { className: "fds-avatar-label-group__text", "aria-hidden": compact || void 0, children: [
2271
+ /* @__PURE__ */ jsx45("span", { className: "fds-avatar-label-group__name", children: name }),
2272
+ detail && /* @__PURE__ */ jsx45("span", { className: "fds-avatar-label-group__detail", children: detail })
2273
+ ] })
2274
+ ]
2275
+ }
2276
+ );
2277
+ });
2278
+
2279
+ // src/components/AppLayout/AppLayout.tsx
2280
+ import { jsx as jsx46 } from "react/jsx-runtime";
2281
+ function AppLayoutRoot({ className, children, ...rest }) {
2282
+ return /* @__PURE__ */ jsx46("div", { className: ["fds-app-layout", className].filter(Boolean).join(" "), ...rest, children });
2283
+ }
2284
+ function AppLayoutPanel({ className, children, ...rest }) {
2285
+ return /* @__PURE__ */ jsx46("main", { className: ["fds-app-layout__panel", className].filter(Boolean).join(" "), ...rest, children });
2286
+ }
2287
+ var AppLayout = Object.assign(AppLayoutRoot, { Panel: AppLayoutPanel });
2288
+
2289
+ // src/components/PageHeader/PageHeader.tsx
2290
+ import { jsx as jsx47, jsxs as jsxs38 } from "react/jsx-runtime";
2291
+ function PageHeader({ title, description, breadcrumb, actions, className, children, ...rest }) {
2292
+ return /* @__PURE__ */ jsxs38("header", { className: ["fds-page-header", className].filter(Boolean).join(" "), ...rest, children: [
2293
+ /* @__PURE__ */ jsxs38("div", { className: "fds-page-header__row", children: [
2294
+ /* @__PURE__ */ jsxs38("div", { className: "fds-page-header__text", children: [
2295
+ breadcrumb != null && /* @__PURE__ */ jsx47("div", { className: "fds-page-header__breadcrumb", children: breadcrumb }),
2296
+ /* @__PURE__ */ jsx47("h1", { className: "fds-page-header__title", children: title }),
2297
+ description != null && /* @__PURE__ */ jsx47("p", { className: "fds-page-header__description", children: description })
2298
+ ] }),
2299
+ actions != null && /* @__PURE__ */ jsx47("div", { className: "fds-page-header__actions", children: actions })
2300
+ ] }),
2301
+ children
2302
+ ] });
2303
+ }
2304
+
2305
+ // src/components/Toast/Toast.tsx
2306
+ import { useEffect as useEffect9 } from "react";
2307
+ import { X } from "lucide-react";
2308
+ import { jsx as jsx48, jsxs as jsxs39 } from "react/jsx-runtime";
2309
+ function ToastRegion({ className, children, ...rest }) {
2310
+ return /* @__PURE__ */ jsx48("div", { className: ["fds-toast-region", className].filter(Boolean).join(" "), "aria-live": "polite", ...rest, children });
2311
+ }
2312
+ function Toast({ children, action, onDismiss, duration, className, ...rest }) {
2313
+ useEffect9(() => {
2314
+ if (!duration || !onDismiss) return;
2315
+ const t = window.setTimeout(onDismiss, duration);
2316
+ return () => window.clearTimeout(t);
2317
+ }, [duration, onDismiss]);
2318
+ return /* @__PURE__ */ jsxs39("div", { role: "status", className: ["fds-toast", className].filter(Boolean).join(" "), ...rest, children: [
2319
+ /* @__PURE__ */ jsx48("span", { className: "fds-toast__message", children }),
2320
+ action && /* @__PURE__ */ jsx48("button", { type: "button", className: "fds-toast__action", onClick: action.onClick, children: action.label }),
2321
+ onDismiss && /* @__PURE__ */ jsx48("button", { type: "button", className: "fds-toast__close", "aria-label": "Dismiss", onClick: onDismiss, children: /* @__PURE__ */ jsx48(X, { "aria-hidden": "true" }) })
2322
+ ] });
2323
+ }
1827
2324
  export {
1828
2325
  Accordion,
2326
+ AppLayout,
1829
2327
  AppNav,
1830
2328
  Avatar,
2329
+ AvatarLabelGroup,
1831
2330
  Badge,
2331
+ BrandButton,
1832
2332
  Button,
1833
2333
  ButtonLink,
1834
2334
  Callout,
@@ -1836,13 +2336,16 @@ export {
1836
2336
  Checkbox,
1837
2337
  DiffPropertyList,
1838
2338
  DiffSection,
2339
+ Divider,
1839
2340
  EmptyState,
1840
2341
  IconButton,
1841
2342
  Input,
2343
+ ListLabel,
1842
2344
  Menu,
1843
2345
  MismatchCard,
1844
2346
  Modal,
1845
2347
  MultiSelect,
2348
+ PageHeader,
1846
2349
  Pagination,
1847
2350
  PricingCard,
1848
2351
  Radio,
@@ -1852,17 +2355,26 @@ export {
1852
2355
  SegmentedControl,
1853
2356
  Select,
1854
2357
  SettingsSection,
2358
+ Sidebar,
2359
+ SidebarItem,
1855
2360
  Skeleton,
1856
2361
  SkeletonGroup,
1857
2362
  Spinner,
1858
2363
  Split,
1859
2364
  StackedCardsIllustration,
1860
2365
  Stat,
2366
+ StatusDot,
1861
2367
  StepList,
1862
2368
  Swatch,
1863
2369
  TabNav,
1864
2370
  Table,
1865
2371
  Tag,
2372
+ Toast,
2373
+ ToastRegion,
1866
2374
  Toggle,
1867
- breakpoints
2375
+ Tooltip,
2376
+ WorkspaceAvatar,
2377
+ WorkspaceSwitcher,
2378
+ breakpoints,
2379
+ useSidebar
1868
2380
  };