@fabio.caffarello/react-design-system 3.13.0 → 4.1.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 (154) hide show
  1. package/dist/granular/ui/components/Autocomplete/Autocomplete.js +116 -88
  2. package/dist/granular/ui/components/Autocomplete/Autocomplete.js.map +1 -1
  3. package/dist/granular/ui/components/Autocomplete/AutocompleteList.js +57 -47
  4. package/dist/granular/ui/components/Autocomplete/AutocompleteList.js.map +1 -1
  5. package/dist/granular/ui/components/Autocomplete/AutocompleteOption.js +21 -20
  6. package/dist/granular/ui/components/Autocomplete/AutocompleteOption.js.map +1 -1
  7. package/dist/granular/ui/components/Breadcrumb/Breadcrumb.js.map +1 -1
  8. package/dist/granular/ui/components/ColorPicker/ColorPicker.js.map +1 -1
  9. package/dist/granular/ui/components/CommandPalette/CommandPalette.js +187 -149
  10. package/dist/granular/ui/components/CommandPalette/CommandPalette.js.map +1 -1
  11. package/dist/granular/ui/components/DataGrid/DataGrid.js +92 -92
  12. package/dist/granular/ui/components/DataGrid/DataGrid.js.map +1 -1
  13. package/dist/granular/ui/components/DatePicker/DatePickerCalendar.js +154 -139
  14. package/dist/granular/ui/components/DatePicker/DatePickerCalendar.js.map +1 -1
  15. package/dist/granular/ui/components/Dialog/AlertDialog.js +73 -40
  16. package/dist/granular/ui/components/Dialog/AlertDialog.js.map +1 -1
  17. package/dist/granular/ui/components/Dialog/DialogContent.js +54 -48
  18. package/dist/granular/ui/components/Dialog/DialogContent.js.map +1 -1
  19. package/dist/granular/ui/components/Dialog/DialogDescription.js +31 -31
  20. package/dist/granular/ui/components/Dialog/DialogDescription.js.map +1 -1
  21. package/dist/granular/ui/components/Dialog/DialogTitle.js +30 -30
  22. package/dist/granular/ui/components/Dialog/DialogTitle.js.map +1 -1
  23. package/dist/granular/ui/components/Drawer/Drawer.js.map +1 -1
  24. package/dist/granular/ui/components/Dropdown/Dropdown.js.map +1 -1
  25. package/dist/granular/ui/components/EmptyState/EmptyState.js.map +1 -1
  26. package/dist/granular/ui/components/FileUpload/FileUpload.js.map +1 -1
  27. package/dist/granular/ui/components/Form/Form.js +38 -37
  28. package/dist/granular/ui/components/Form/Form.js.map +1 -1
  29. package/dist/granular/ui/components/Form/FormField.js +28 -26
  30. package/dist/granular/ui/components/Form/FormField.js.map +1 -1
  31. package/dist/granular/ui/components/Header/Header.js.map +1 -1
  32. package/dist/granular/ui/components/Header/components/HeaderActions.js.map +1 -1
  33. package/dist/granular/ui/components/Header/components/HeaderHamburger.js.map +1 -1
  34. package/dist/granular/ui/components/Header/components/HeaderLogo.js.map +1 -1
  35. package/dist/granular/ui/components/Header/components/HeaderMobileMenu.js.map +1 -1
  36. package/dist/granular/ui/components/Header/components/HeaderNavigation.js.map +1 -1
  37. package/dist/granular/ui/components/Header/contexts/HeaderContext.js.map +1 -1
  38. package/dist/granular/ui/components/Menu/Menu.js.map +1 -1
  39. package/dist/granular/ui/components/Modal/Modal.js +98 -86
  40. package/dist/granular/ui/components/Modal/Modal.js.map +1 -1
  41. package/dist/granular/ui/components/MultiSelect/MultiSelect.js +122 -106
  42. package/dist/granular/ui/components/MultiSelect/MultiSelect.js.map +1 -1
  43. package/dist/granular/ui/components/Navigation/Navigation.js.map +1 -1
  44. package/dist/granular/ui/components/PageHeader/PageHeader.js.map +1 -1
  45. package/dist/granular/ui/components/Pagination/Pagination.js.map +1 -1
  46. package/dist/granular/ui/components/Popover/Popover.js.map +1 -1
  47. package/dist/granular/ui/components/Rating/Rating.js.map +1 -1
  48. package/dist/granular/ui/components/SearchInput/SearchInput.js.map +1 -1
  49. package/dist/granular/ui/components/SideNavbar/components/Navbar/NavbarGroup.js +82 -64
  50. package/dist/granular/ui/components/SideNavbar/components/Navbar/NavbarGroup.js.map +1 -1
  51. package/dist/granular/ui/components/SideNavbar/components/Navbar/NavbarItem.js +30 -29
  52. package/dist/granular/ui/components/SideNavbar/components/Navbar/NavbarItem.js.map +1 -1
  53. package/dist/granular/ui/components/SideNavbar/components/SideNavbarResizeHandle.js +37 -35
  54. package/dist/granular/ui/components/SideNavbar/components/SideNavbarResizeHandle.js.map +1 -1
  55. package/dist/granular/ui/components/SideNavbar/providers/SideNavbarStateProvider.js +57 -57
  56. package/dist/granular/ui/components/SideNavbar/providers/SideNavbarStateProvider.js.map +1 -1
  57. package/dist/granular/ui/components/Stepper/Stepper.js +102 -94
  58. package/dist/granular/ui/components/Stepper/Stepper.js.map +1 -1
  59. package/dist/granular/ui/components/Table/Table.js +41 -35
  60. package/dist/granular/ui/components/Table/Table.js.map +1 -1
  61. package/dist/granular/ui/components/Table/TableActions/TableActions.js.map +1 -1
  62. package/dist/granular/ui/components/Table/TableFilters/TableFilters.js +49 -46
  63. package/dist/granular/ui/components/Table/TableFilters/TableFilters.js.map +1 -1
  64. package/dist/granular/ui/components/Table/TablePagination/TablePagination.js.map +1 -1
  65. package/dist/granular/ui/components/Table/TableProvider.js +82 -80
  66. package/dist/granular/ui/components/Table/TableProvider.js.map +1 -1
  67. package/dist/granular/ui/components/Table/TableRow.js +57 -53
  68. package/dist/granular/ui/components/Table/TableRow.js.map +1 -1
  69. package/dist/granular/ui/components/Table/useColumnResizing.js +53 -53
  70. package/dist/granular/ui/components/Table/useColumnResizing.js.map +1 -1
  71. package/dist/granular/ui/components/TimePicker/TimePicker.js +149 -103
  72. package/dist/granular/ui/components/TimePicker/TimePicker.js.map +1 -1
  73. package/dist/granular/ui/components/Timeline/Timeline.js.map +1 -1
  74. package/dist/granular/ui/hooks/useFocusRestore.js +14 -15
  75. package/dist/granular/ui/hooks/useFocusRestore.js.map +1 -1
  76. package/dist/granular/ui/primitives/Badge/Badge.js.map +1 -1
  77. package/dist/granular/ui/primitives/Button/Button.js +86 -104
  78. package/dist/granular/ui/primitives/Button/Button.js.map +1 -1
  79. package/dist/granular/ui/primitives/Checkbox/Checkbox.js.map +1 -1
  80. package/dist/granular/ui/primitives/Chip/Chip.js +91 -71
  81. package/dist/granular/ui/primitives/Chip/Chip.js.map +1 -1
  82. package/dist/granular/ui/primitives/ErrorMessage/ErrorMessage.js.map +1 -1
  83. package/dist/granular/ui/primitives/Input/Input.js.map +1 -1
  84. package/dist/granular/ui/primitives/Label/Label.js.map +1 -1
  85. package/dist/granular/ui/primitives/NavLink/NavLink.js.map +1 -1
  86. package/dist/granular/ui/primitives/Radio/Radio.js.map +1 -1
  87. package/dist/granular/ui/primitives/Select/Select.js.map +1 -1
  88. package/dist/granular/ui/primitives/Separator/Separator.js.map +1 -1
  89. package/dist/granular/ui/primitives/Skeleton/Skeleton.js.map +1 -1
  90. package/dist/granular/ui/primitives/Slider/Slider.js.map +1 -1
  91. package/dist/granular/ui/primitives/Spinner/Spinner.js.map +1 -1
  92. package/dist/granular/ui/primitives/Switch/Switch.js.map +1 -1
  93. package/dist/granular/ui/primitives/Tooltip/Tooltip.js.map +1 -1
  94. package/dist/granular/ui/providers/DialogContext.js.map +1 -1
  95. package/dist/granular/ui/providers/DialogProvider.js +24 -20
  96. package/dist/granular/ui/providers/DialogProvider.js.map +1 -1
  97. package/dist/index.cjs +144 -144
  98. package/dist/index.cjs.map +1 -1
  99. package/dist/index.js +5896 -5609
  100. package/dist/index.js.map +1 -1
  101. package/dist/react-design-system.css +1 -1
  102. package/dist/server/index.cjs +13 -13
  103. package/dist/server/index.cjs.map +1 -1
  104. package/dist/server/index.js +1050 -789
  105. package/dist/server/index.js.map +1 -1
  106. package/dist/ui/components/Autocomplete/Autocomplete.d.ts +21 -0
  107. package/dist/ui/components/Autocomplete/AutocompleteList.d.ts +4 -0
  108. package/dist/ui/components/Autocomplete/AutocompleteOption.d.ts +8 -0
  109. package/dist/ui/components/Breadcrumb/Breadcrumb.d.ts +0 -1
  110. package/dist/ui/components/ColorPicker/ColorPicker.d.ts +0 -1
  111. package/dist/ui/components/CommandPalette/CommandPalette.d.ts +0 -1
  112. package/dist/ui/components/DataGrid/DataGrid.d.ts +0 -1
  113. package/dist/ui/components/Dialog/DialogContent.d.ts +20 -1
  114. package/dist/ui/components/Drawer/Drawer.d.ts +0 -1
  115. package/dist/ui/components/Dropdown/Dropdown.d.ts +0 -1
  116. package/dist/ui/components/EmptyState/EmptyState.d.ts +0 -1
  117. package/dist/ui/components/FileUpload/FileUpload.d.ts +0 -1
  118. package/dist/ui/components/Form/FormField.d.ts +7 -0
  119. package/dist/ui/components/Header/Header.d.ts +1 -1
  120. package/dist/ui/components/Header/components/HeaderActions.d.ts +1 -1
  121. package/dist/ui/components/Header/components/HeaderHamburger.d.ts +1 -1
  122. package/dist/ui/components/Header/components/HeaderLogo.d.ts +1 -1
  123. package/dist/ui/components/Header/components/HeaderMobileMenu.d.ts +1 -1
  124. package/dist/ui/components/Header/components/HeaderNavigation.d.ts +1 -1
  125. package/dist/ui/components/Header/contexts/HeaderContext.d.ts +1 -1
  126. package/dist/ui/components/Menu/Menu.d.ts +0 -1
  127. package/dist/ui/components/Modal/Modal.d.ts +1 -2
  128. package/dist/ui/components/Navigation/Navigation.d.ts +1 -1
  129. package/dist/ui/components/PageHeader/PageHeader.d.ts +1 -1
  130. package/dist/ui/components/Pagination/Pagination.d.ts +0 -1
  131. package/dist/ui/components/Popover/Popover.d.ts +0 -1
  132. package/dist/ui/components/Rating/Rating.d.ts +0 -1
  133. package/dist/ui/components/SearchInput/SearchInput.d.ts +0 -1
  134. package/dist/ui/components/Stepper/Stepper.d.ts +0 -1
  135. package/dist/ui/components/Table/TableActions/TableActions.d.ts +0 -1
  136. package/dist/ui/components/Table/TableFilters/TableFilters.d.ts +0 -1
  137. package/dist/ui/components/Table/TablePagination/TablePagination.d.ts +0 -1
  138. package/dist/ui/components/TimePicker/TimePicker.d.ts +0 -1
  139. package/dist/ui/components/Timeline/Timeline.d.ts +0 -1
  140. package/dist/ui/primitives/Checkbox/Checkbox.d.ts +0 -1
  141. package/dist/ui/primitives/Chip/Chip.d.ts +21 -0
  142. package/dist/ui/primitives/ErrorMessage/ErrorMessage.d.ts +0 -1
  143. package/dist/ui/primitives/Input/Input.d.ts +0 -1
  144. package/dist/ui/primitives/Label/Label.d.ts +0 -1
  145. package/dist/ui/primitives/NavLink/NavLink.d.ts +1 -1
  146. package/dist/ui/primitives/Radio/Radio.d.ts +0 -1
  147. package/dist/ui/primitives/Select/Select.d.ts +0 -1
  148. package/dist/ui/primitives/Skeleton/Skeleton.d.ts +0 -1
  149. package/dist/ui/primitives/Slider/Slider.d.ts +0 -1
  150. package/dist/ui/primitives/Switch/Switch.d.ts +0 -1
  151. package/dist/ui/primitives/Tooltip/Tooltip.d.ts +0 -1
  152. package/dist/ui/providers/DialogContext.d.ts +8 -0
  153. package/dist/ui/server.d.ts +2 -0
  154. package/package.json +7 -7
@@ -1,126 +1,129 @@
1
1
  "use client";
2
- var te = Object.defineProperty, le = Object.defineProperties;
3
- var se = Object.getOwnPropertyDescriptors;
4
- var j = Object.getOwnPropertySymbols;
5
- var ie = Object.prototype.hasOwnProperty, re = Object.prototype.propertyIsEnumerable;
6
- var K = (c, l, r) => l in c ? te(c, l, { enumerable: !0, configurable: !0, writable: !0, value: r }) : c[l] = r, M = (c, l) => {
2
+ var re = Object.defineProperty, ne = Object.defineProperties;
3
+ var ae = Object.getOwnPropertyDescriptors;
4
+ var T = Object.getOwnPropertySymbols;
5
+ var ue = Object.prototype.hasOwnProperty, ce = Object.prototype.propertyIsEnumerable;
6
+ var U = (c, l, r) => l in c ? re(c, l, { enumerable: !0, configurable: !0, writable: !0, value: r }) : c[l] = r, q = (c, l) => {
7
7
  for (var r in l || (l = {}))
8
- ie.call(l, r) && K(c, r, l[r]);
9
- if (j)
10
- for (var r of j(l))
11
- re.call(l, r) && K(c, r, l[r]);
8
+ ue.call(l, r) && U(c, r, l[r]);
9
+ if (T)
10
+ for (var r of T(l))
11
+ ce.call(l, r) && U(c, r, l[r]);
12
12
  return c;
13
- }, B = (c, l) => le(c, se(l));
14
- import { jsxs as H, jsx as m } from "react/jsx-runtime";
15
- import { forwardRef as ne, useId as ue, useState as x, useRef as y, useEffect as ae } from "react";
16
- import ce from "../../primitives/Chip/Chip.js";
17
- import { Check as fe } from "lucide-react";
18
- import de from "../Autocomplete/AutocompleteList.js";
19
- import { cn as p } from "../../utils/cn.js";
20
- import { getSpacingClass as D } from "../../tokens/spacing.js";
21
- import { getRadiusClass as oe } from "../../tokens/radius.js";
22
- const me = ne(
13
+ }, z = (c, l) => ne(c, ae(l));
14
+ import { jsxs as G, jsx as h } from "react/jsx-runtime";
15
+ import { forwardRef as oe, useId as fe, useState as O, useRef as E, useEffect as de } from "react";
16
+ import me from "../../primitives/Chip/Chip.js";
17
+ import { Check as pe } from "lucide-react";
18
+ import ve from "../Autocomplete/AutocompleteList.js";
19
+ import { cn as w } from "../../utils/cn.js";
20
+ import { getSpacingClass as L } from "../../tokens/spacing.js";
21
+ import { getRadiusClass as he } from "../../tokens/radius.js";
22
+ const we = oe(
23
23
  function({
24
24
  options: l,
25
25
  value: r,
26
- defaultValue: T = [],
26
+ defaultValue: J = [],
27
27
  onChange: n,
28
- onSelect: u,
29
- placeholder: U = "Select options...",
30
- loading: A = !1,
31
- disabled: q = !1,
32
- emptyMessage: O = "No options found",
33
- maxSelected: R,
34
- showSelectAll: z = !1,
35
- className: G = "",
36
- inputClassName: J = "",
37
- size: I = "md",
38
- label: N
39
- }, v) {
40
- const E = ue(), [P, w] = x(T), [h, f] = x(!1), [b, d] = x(-1), [g, V] = x(""), k = y(null), Q = y(null), W = y(null), o = r !== void 0, i = o ? r : P, X = l.filter(
28
+ onSelect: a,
29
+ placeholder: P = "Select options...",
30
+ loading: F = !1,
31
+ disabled: A = !1,
32
+ emptyMessage: $ = "No options found",
33
+ maxSelected: d,
34
+ showSelectAll: Q = !1,
35
+ className: W = "",
36
+ inputClassName: X = "",
37
+ size: j = "md",
38
+ label: B
39
+ }, b) {
40
+ const I = fe(), R = `${I}-list`, [Y, g] = O(J), [k, p] = O(!1), [f, m] = O(-1), [V, N] = O(""), x = E(null), Z = E(null), K = E(null), v = r !== void 0, i = v ? r : Y, y = l.filter(
41
41
  (e) => i.includes(e.value)
42
- ), a = (() => {
42
+ ), u = (() => {
43
43
  let e = l;
44
- return g.trim() && (e = l.filter(
45
- (t) => t.label.toLowerCase().includes(g.toLowerCase())
44
+ return V.trim() && (e = l.filter(
45
+ (t) => t.label.toLowerCase().includes(V.toLowerCase())
46
46
  )), e;
47
- })(), Y = a.length > 0, Z = (e) => {
47
+ })(), _ = u.length > 0, C = (e) => {
48
48
  const t = e.target.value;
49
- V(t), f(!0), d(-1);
50
- }, L = (e) => {
51
- if (e.disabled || R && i.length >= R && !i.includes(e.value))
49
+ N(t), p(!0), m(-1);
50
+ }, M = (e) => {
51
+ if (e.disabled || d && i.length >= d && !i.includes(e.value))
52
52
  return;
53
53
  const t = i.includes(e.value) ? i.filter((s) => s !== e.value) : [...i, e.value];
54
- o || w(t), n == null || n(t), u == null || u(l.filter((s) => t.includes(s.value))), V("");
55
- }, _ = () => {
56
- const e = a.filter((s) => !s.disabled).map((s) => s.value), t = [.../* @__PURE__ */ new Set([...i, ...e])];
57
- o || w(t), n == null || n(t), u == null || u(l.filter((s) => t.includes(s.value)));
58
- }, $ = () => {
59
- const e = a.map((s) => s.value), t = i.filter(
54
+ v || g(t), n == null || n(t), a == null || a(l.filter((s) => t.includes(s.value))), N(""), m(-1);
55
+ }, S = () => {
56
+ const e = u.filter((o) => !o.disabled).map((o) => o.value), t = [.../* @__PURE__ */ new Set([...i, ...e])], s = d ? t.slice(0, d) : t;
57
+ v || g(s), n == null || n(s), a == null || a(l.filter((o) => s.includes(o.value)));
58
+ }, ee = () => {
59
+ const e = u.map((s) => s.value), t = i.filter(
60
60
  (s) => !e.includes(s)
61
61
  );
62
- o || w(t), n == null || n(t), u == null || u(l.filter((s) => t.includes(s.value)));
63
- }, F = (e) => {
62
+ v || g(t), n == null || n(t), a == null || a(l.filter((s) => t.includes(s.value)));
63
+ }, H = (e) => {
64
+ if (A) return;
64
65
  const t = i.filter((s) => s !== e);
65
- o || w(t), n == null || n(t), u == null || u(l.filter((s) => t.includes(s.value)));
66
- }, S = (e) => {
67
- if (!h || a.length === 0) {
68
- (e.key === "ArrowDown" || e.key === "Enter") && f(!0), e.key === "Backspace" && g === "" && i.length > 0 && F(i[i.length - 1]);
66
+ v || g(t), n == null || n(t), a == null || a(l.filter((s) => t.includes(s.value)));
67
+ }, te = (e) => {
68
+ if (!k || u.length === 0) {
69
+ (e.key === "ArrowDown" || e.key === "Enter") && p(!0), e.key === "Backspace" && V === "" && y.length > 0 && H(y[y.length - 1].value);
69
70
  return;
70
71
  }
71
72
  switch (e.key) {
72
73
  case "ArrowDown":
73
- e.preventDefault(), d(
74
- (t) => t < a.length - 1 ? t + 1 : 0
74
+ e.preventDefault(), m(
75
+ (t) => t < u.length - 1 ? t + 1 : 0
75
76
  );
76
77
  break;
77
78
  case "ArrowUp":
78
- e.preventDefault(), d(
79
- (t) => t > 0 ? t - 1 : a.length - 1
79
+ e.preventDefault(), m(
80
+ (t) => t > 0 ? t - 1 : u.length - 1
80
81
  );
81
82
  break;
82
83
  case "Enter":
83
- e.preventDefault(), b >= 0 && b < a.length && L(a[b]);
84
+ e.preventDefault(), f >= 0 && f < u.length && M(u[f]);
84
85
  break;
85
86
  case "Escape":
86
- e.preventDefault(), f(!1), d(-1);
87
+ e.preventDefault(), p(!1), m(-1);
87
88
  break;
88
89
  }
89
90
  };
90
- ae(() => {
91
- if (!h) return;
91
+ de(() => {
92
+ if (!k) return;
92
93
  const e = (t) => {
93
- k.current && !k.current.contains(t.target) && (f(!1), d(-1), V(""));
94
+ var o;
95
+ const s = t.target;
96
+ x.current && !x.current.contains(s) && !((o = K.current) != null && o.contains(s)) && (p(!1), m(-1), N(""));
94
97
  };
95
98
  return document.addEventListener("mousedown", e), () => document.removeEventListener("mousedown", e);
96
- }, [h]);
97
- const C = a.filter((e) => !e.disabled).every((e) => i.includes(e.value)), ee = h && (Y || A || O);
98
- return /* @__PURE__ */ H("div", { ref: k, className: p("relative", G), children: [
99
- /* @__PURE__ */ m(
99
+ }, [k]);
100
+ const le = u.filter((e) => !e.disabled).every((e) => i.includes(e.value)), D = k && (_ || F || !!$), se = d != null && i.length >= d, ie = D && f >= 0 && f < u.length ? `${R}-option-${f}` : void 0;
101
+ return /* @__PURE__ */ G("div", { ref: x, className: w("relative", W), children: [
102
+ /* @__PURE__ */ h(
100
103
  "label",
101
104
  {
102
- htmlFor: E,
103
- className: p(
105
+ htmlFor: I,
106
+ className: w(
104
107
  "block",
105
- D("sm", "mb"),
108
+ L("sm", "mb"),
106
109
  "text-sm",
107
110
  "font-medium",
108
111
  "text-fg-primary"
109
112
  ),
110
- children: N
113
+ children: B
111
114
  }
112
115
  ),
113
- /* @__PURE__ */ H(
116
+ /* @__PURE__ */ G(
114
117
  "div",
115
118
  {
116
- className: p(
119
+ className: w(
117
120
  "flex",
118
121
  "flex-wrap",
119
- D("sm", "gap"),
120
- D("sm", "p"),
122
+ L("sm", "gap"),
123
+ L("sm", "p"),
121
124
  "border",
122
125
  "border-line-default",
123
- oe("md"),
126
+ he("md"),
124
127
  "min-h-10",
125
128
  "focus-within:outline-none",
126
129
  "focus-within:ring-2",
@@ -129,65 +132,78 @@ const me = ne(
129
132
  "focus-within:ring-line-brand"
130
133
  ),
131
134
  children: [
132
- X.map((e) => /* @__PURE__ */ m(
133
- ce,
135
+ y.map((e) => /* @__PURE__ */ h(
136
+ me,
134
137
  {
135
- onRemove: () => F(e.value),
136
- size: I === "sm" ? "sm" : I === "lg" ? "lg" : "md",
138
+ disabled: A,
139
+ onRemove: () => H(e.value),
140
+ size: j === "sm" ? "sm" : j === "lg" ? "lg" : "md",
137
141
  children: e.label
138
142
  },
139
143
  e.value
140
144
  )),
141
- /* @__PURE__ */ m(
145
+ /* @__PURE__ */ h(
142
146
  "input",
143
147
  {
144
- id: E,
148
+ id: I,
145
149
  ref: (e) => {
146
- typeof v == "function" ? v(e) : v && (v.current = e), Q.current = e;
150
+ typeof b == "function" ? b(e) : b && (b.current = e), Z.current = e;
147
151
  },
148
152
  type: "text",
149
- value: g,
150
- onChange: Z,
151
- onKeyDown: S,
152
- onFocus: () => f(!0),
153
- placeholder: i.length === 0 ? U : "",
154
- disabled: q,
155
- className: p(
153
+ role: "combobox",
154
+ "aria-expanded": D,
155
+ "aria-haspopup": "listbox",
156
+ "aria-controls": D ? R : void 0,
157
+ "aria-autocomplete": "list",
158
+ "aria-activedescendant": ie,
159
+ value: V,
160
+ onChange: C,
161
+ onKeyDown: te,
162
+ onFocus: () => p(!0),
163
+ placeholder: i.length === 0 ? P : "",
164
+ disabled: A,
165
+ className: w(
156
166
  "flex-1",
157
167
  "min-w-32",
158
168
  "outline-none",
159
169
  "bg-transparent",
160
- J
170
+ X
161
171
  )
162
172
  }
163
173
  )
164
174
  ]
165
175
  }
166
176
  ),
167
- ee && /* @__PURE__ */ m(
168
- de,
177
+ D && /* @__PURE__ */ h(
178
+ ve,
169
179
  {
170
- ref: W,
171
- "aria-label": N,
172
- options: a.map((e) => B(M({}, e), {
173
- icon: i.includes(e.value) ? /* @__PURE__ */ m(fe, { className: p("h-4", "w-4", "text-fg-brand") }) : e.icon
180
+ ref: K,
181
+ id: R,
182
+ selectedValues: i,
183
+ "aria-label": B,
184
+ options: u.map((e) => z(q({}, e), {
185
+ // Once the cap is hit, not-yet-selected options are disabled
186
+ // so they stop accepting clicks silently (maxSelected was a
187
+ // no-op with no affordance before).
188
+ disabled: e.disabled || se && !i.includes(e.value),
189
+ icon: i.includes(e.value) ? /* @__PURE__ */ h(pe, { className: w("h-4", "w-4", "text-fg-brand") }) : e.icon
174
190
  })),
175
- highlightedIndex: b,
176
- onSelect: L,
177
- loading: A,
178
- emptyMessage: O,
179
- containerRef: k,
180
- showSelectAll: z && a.length > 0,
181
- allSelected: C,
182
- onSelectAll: _,
183
- onDeselectAll: $
191
+ highlightedIndex: f,
192
+ onSelect: M,
193
+ loading: F,
194
+ emptyMessage: $,
195
+ containerRef: x,
196
+ showSelectAll: Q && u.length > 0,
197
+ allSelected: le,
198
+ onSelectAll: S,
199
+ onDeselectAll: ee
184
200
  }
185
201
  )
186
202
  ] });
187
203
  }
188
204
  );
189
- me.displayName = "MultiSelect";
205
+ we.displayName = "MultiSelect";
190
206
  export {
191
- me as default
207
+ we as default
192
208
  };
193
209
  //# sourceMappingURL=MultiSelect.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"MultiSelect.js","sources":["../../../../../src/ui/components/MultiSelect/MultiSelect.tsx"],"sourcesContent":["\"use client\";\n\nimport { useState, useRef, useEffect, useId, forwardRef } from \"react\";\nimport Chip from \"../../primitives/Chip/Chip\";\nimport { Check } from \"lucide-react\";\nimport AutocompleteList from \"../Autocomplete/AutocompleteList\";\nimport type { AutocompleteOptionType } from \"../Autocomplete/AutocompleteOption\";\nimport { cn } from \"../../utils\";\nimport { getSpacingClass } from \"../../tokens\";\nimport { getRadiusClass } from \"../../tokens\";\n\nexport interface MultiSelectProps {\n options: AutocompleteOptionType[];\n value?: string[];\n defaultValue?: string[];\n onChange?: (values: string[]) => void;\n onSelect?: (options: AutocompleteOptionType[]) => void;\n placeholder?: string;\n loading?: boolean;\n disabled?: boolean;\n emptyMessage?: string;\n maxSelected?: number;\n showSelectAll?: boolean;\n className?: string;\n inputClassName?: string;\n size?: \"sm\" | \"md\" | \"lg\";\n /**\n * Required label for the multi-select input. Becomes the accessible\n * name via <label htmlFor>. Make this a real domain term (\"Tags\",\n * \"Select fruits\"), not the element type (\"multi-select\" / \"input\").\n */\n label: string;\n}\n\n/**\n * MultiSelect Component\n *\n * A multi-select component with chips for selected items.\n * Supports keyboard navigation, loading states, and custom filtering.\n *\n * @example\n * ```tsx\n * <MultiSelect\n * options={[\n * { value: '1', label: 'Option 1' },\n * { value: '2', label: 'Option 2' },\n * ]}\n * onSelect={(options) => console.log(options)}\n * />\n * ```\n */\nconst MultiSelect = forwardRef<HTMLInputElement, MultiSelectProps>(\n function MultiSelect(\n {\n options,\n value: controlledValue,\n defaultValue = [],\n onChange,\n onSelect,\n placeholder = \"Select options...\",\n loading = false,\n disabled = false,\n emptyMessage = \"No options found\",\n maxSelected,\n showSelectAll = false,\n className = \"\",\n inputClassName = \"\",\n size = \"md\",\n label,\n },\n ref,\n ) {\n const inputId = useId();\n const [internalValue, setInternalValue] = useState<string[]>(defaultValue);\n const [isOpen, setIsOpen] = useState(false);\n const [highlightedIndex, setHighlightedIndex] = useState(-1);\n const [searchValue, setSearchValue] = useState(\"\");\n const containerRef = useRef<HTMLDivElement>(null);\n const inputRef = useRef<HTMLInputElement>(null);\n const listRef = useRef<HTMLDivElement>(null);\n\n const isControlled = controlledValue !== undefined;\n const selectedValues = isControlled ? controlledValue : internalValue;\n\n // Get selected options\n const selectedOptions = options.filter((opt) =>\n selectedValues.includes(opt.value),\n );\n\n // Filter options (exclude already selected if needed, or show all)\n const getFilteredOptions = (): AutocompleteOptionType[] => {\n let filtered = options;\n\n if (searchValue.trim()) {\n filtered = options.filter((option) =>\n option.label.toLowerCase().includes(searchValue.toLowerCase()),\n );\n }\n\n return filtered;\n };\n\n const filteredOptions = getFilteredOptions();\n const hasOptions = filteredOptions.length > 0;\n\n // Handle input change\n const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const newValue = e.target.value;\n setSearchValue(newValue);\n setIsOpen(true);\n setHighlightedIndex(-1);\n };\n\n // Handle option toggle\n const handleToggleOption = (option: AutocompleteOptionType) => {\n if (option.disabled) return;\n if (\n maxSelected &&\n selectedValues.length >= maxSelected &&\n !selectedValues.includes(option.value)\n ) {\n return;\n }\n\n const newValues = selectedValues.includes(option.value)\n ? selectedValues.filter((v) => v !== option.value)\n : [...selectedValues, option.value];\n\n if (!isControlled) {\n setInternalValue(newValues);\n }\n\n onChange?.(newValues);\n onSelect?.(options.filter((opt) => newValues.includes(opt.value)));\n setSearchValue(\"\");\n };\n\n // Handle select all\n const handleSelectAll = () => {\n const allValues = filteredOptions\n .filter((opt) => !opt.disabled)\n .map((opt) => opt.value);\n const newValues = [...new Set([...selectedValues, ...allValues])];\n\n if (!isControlled) {\n setInternalValue(newValues);\n }\n\n onChange?.(newValues);\n onSelect?.(options.filter((opt) => newValues.includes(opt.value)));\n };\n\n // Handle deselect all\n const handleDeselectAll = () => {\n const filteredValues = filteredOptions.map((opt) => opt.value);\n const newValues = selectedValues.filter(\n (v) => !filteredValues.includes(v),\n );\n\n if (!isControlled) {\n setInternalValue(newValues);\n }\n\n onChange?.(newValues);\n onSelect?.(options.filter((opt) => newValues.includes(opt.value)));\n };\n\n // Handle remove chip\n const handleRemoveChip = (value: string) => {\n const newValues = selectedValues.filter((v) => v !== value);\n\n if (!isControlled) {\n setInternalValue(newValues);\n }\n\n onChange?.(newValues);\n onSelect?.(options.filter((opt) => newValues.includes(opt.value)));\n };\n\n // Handle keyboard navigation\n const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {\n if (!isOpen || filteredOptions.length === 0) {\n if (e.key === \"ArrowDown\" || e.key === \"Enter\") {\n setIsOpen(true);\n }\n // Remove last chip on backspace\n if (\n e.key === \"Backspace\" &&\n searchValue === \"\" &&\n selectedValues.length > 0\n ) {\n handleRemoveChip(selectedValues[selectedValues.length - 1]);\n }\n return;\n }\n\n switch (e.key) {\n case \"ArrowDown\":\n e.preventDefault();\n setHighlightedIndex((prev) =>\n prev < filteredOptions.length - 1 ? prev + 1 : 0,\n );\n break;\n case \"ArrowUp\":\n e.preventDefault();\n setHighlightedIndex((prev) =>\n prev > 0 ? prev - 1 : filteredOptions.length - 1,\n );\n break;\n case \"Enter\":\n e.preventDefault();\n if (\n highlightedIndex >= 0 &&\n highlightedIndex < filteredOptions.length\n ) {\n handleToggleOption(filteredOptions[highlightedIndex]);\n }\n break;\n case \"Escape\":\n e.preventDefault();\n setIsOpen(false);\n setHighlightedIndex(-1);\n break;\n }\n };\n\n // Close on click outside\n useEffect(() => {\n if (!isOpen) return;\n\n const handleClickOutside = (e: MouseEvent) => {\n if (\n containerRef.current &&\n !containerRef.current.contains(e.target as Node)\n ) {\n setIsOpen(false);\n setHighlightedIndex(-1);\n setSearchValue(\"\");\n }\n };\n\n document.addEventListener(\"mousedown\", handleClickOutside);\n return () =>\n document.removeEventListener(\"mousedown\", handleClickOutside);\n }, [isOpen]);\n\n // Check if all filtered options are selected\n const allSelected = filteredOptions\n .filter((opt) => !opt.disabled)\n .every((opt) => selectedValues.includes(opt.value));\n\n const shouldShowList = isOpen && (hasOptions || loading || emptyMessage);\n\n return (\n <div ref={containerRef} className={cn(\"relative\", className)}>\n <label\n htmlFor={inputId}\n className={cn(\n \"block\",\n getSpacingClass(\"sm\", \"mb\"),\n \"text-sm\",\n \"font-medium\",\n \"text-fg-primary\",\n )}\n >\n {label}\n </label>\n <div\n className={cn(\n \"flex\",\n \"flex-wrap\",\n getSpacingClass(\"sm\", \"gap\"),\n getSpacingClass(\"sm\", \"p\"),\n \"border\",\n \"border-line-default\",\n getRadiusClass(\"md\"),\n \"min-h-10\",\n \"focus-within:outline-none\",\n \"focus-within:ring-2\",\n \"focus-within:ring-offset-2\",\n \"focus-within:border-line-brand\",\n \"focus-within:ring-line-brand\",\n )}\n >\n {selectedOptions.map((option) => (\n <Chip\n key={option.value}\n onRemove={() => handleRemoveChip(option.value)}\n size={size === \"sm\" ? \"sm\" : size === \"lg\" ? \"lg\" : \"md\"}\n >\n {option.label}\n </Chip>\n ))}\n <input\n id={inputId}\n ref={(node) => {\n if (typeof ref === \"function\") {\n ref(node);\n } else if (ref) {\n (\n ref as React.MutableRefObject<HTMLInputElement | null>\n ).current = node;\n }\n inputRef.current = node;\n }}\n type=\"text\"\n value={searchValue}\n onChange={handleInputChange}\n onKeyDown={handleKeyDown}\n onFocus={() => setIsOpen(true)}\n placeholder={selectedValues.length === 0 ? placeholder : \"\"}\n disabled={disabled}\n className={cn(\n \"flex-1\",\n \"min-w-32\",\n \"outline-none\",\n \"bg-transparent\",\n inputClassName,\n )}\n />\n </div>\n\n {shouldShowList && (\n <AutocompleteList\n ref={listRef}\n // Cascade the input's accessible-name source to the\n // listbox portal — axe `aria-input-field-name` flags a\n // role=\"listbox\" without aria-label / aria-labelledby.\n // MultiSelect's `label` is TS-required, so the listbox\n // always inherits a name.\n aria-label={label}\n options={filteredOptions.map((opt) => ({\n ...opt,\n icon: selectedValues.includes(opt.value) ? (\n <Check className={cn(\"h-4\", \"w-4\", \"text-fg-brand\")} />\n ) : (\n opt.icon\n ),\n }))}\n highlightedIndex={highlightedIndex}\n onSelect={handleToggleOption}\n loading={loading}\n emptyMessage={emptyMessage}\n containerRef={containerRef}\n showSelectAll={showSelectAll && filteredOptions.length > 0}\n allSelected={allSelected}\n onSelectAll={handleSelectAll}\n onDeselectAll={handleDeselectAll}\n />\n )}\n </div>\n );\n },\n);\n\nMultiSelect.displayName = \"MultiSelect\";\n\nexport default MultiSelect;\n"],"names":["MultiSelect","forwardRef","options","controlledValue","defaultValue","onChange","onSelect","placeholder","loading","disabled","emptyMessage","maxSelected","showSelectAll","className","inputClassName","size","label","ref","inputId","useId","internalValue","setInternalValue","useState","isOpen","setIsOpen","highlightedIndex","setHighlightedIndex","searchValue","setSearchValue","containerRef","useRef","inputRef","listRef","isControlled","selectedValues","selectedOptions","opt","filteredOptions","filtered","option","hasOptions","handleInputChange","newValue","handleToggleOption","newValues","v","handleSelectAll","allValues","handleDeselectAll","filteredValues","handleRemoveChip","value","handleKeyDown","prev","useEffect","handleClickOutside","e","allSelected","shouldShowList","jsxs","cn","jsx","getSpacingClass","getRadiusClass","Chip","node","AutocompleteList","__spreadProps","__spreadValues","Check"],"mappings":"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"}
1
+ {"version":3,"file":"MultiSelect.js","sources":["../../../../../src/ui/components/MultiSelect/MultiSelect.tsx"],"sourcesContent":["\"use client\";\n\nimport { useState, useRef, useEffect, useId, forwardRef } from \"react\";\nimport Chip from \"../../primitives/Chip/Chip\";\nimport { Check } from \"lucide-react\";\nimport AutocompleteList from \"../Autocomplete/AutocompleteList\";\nimport type { AutocompleteOptionType } from \"../Autocomplete/AutocompleteOption\";\nimport { cn } from \"../../utils\";\nimport { getSpacingClass } from \"../../tokens\";\nimport { getRadiusClass } from \"../../tokens\";\n\nexport interface MultiSelectProps {\n options: AutocompleteOptionType[];\n value?: string[];\n defaultValue?: string[];\n onChange?: (values: string[]) => void;\n onSelect?: (options: AutocompleteOptionType[]) => void;\n placeholder?: string;\n loading?: boolean;\n disabled?: boolean;\n emptyMessage?: string;\n maxSelected?: number;\n showSelectAll?: boolean;\n className?: string;\n inputClassName?: string;\n size?: \"sm\" | \"md\" | \"lg\";\n /**\n * Required label for the multi-select input. Becomes the accessible\n * name via <label htmlFor>. Make this a real domain term (\"Tags\",\n * \"Select fruits\"), not the element type (\"multi-select\" / \"input\").\n */\n label: string;\n}\n\n/**\n * MultiSelect Component\n *\n * A multi-select component with chips for selected items.\n * Supports keyboard navigation, loading states, and custom filtering.\n *\n * @example\n * ```tsx\n * <MultiSelect\n * options={[\n * { value: '1', label: 'Option 1' },\n * { value: '2', label: 'Option 2' },\n * ]}\n * onSelect={(options) => console.log(options)}\n * />\n * ```\n */\nconst MultiSelect = forwardRef<HTMLInputElement, MultiSelectProps>(\n function MultiSelect(\n {\n options,\n value: controlledValue,\n defaultValue = [],\n onChange,\n onSelect,\n placeholder = \"Select options...\",\n loading = false,\n disabled = false,\n emptyMessage = \"No options found\",\n maxSelected,\n showSelectAll = false,\n className = \"\",\n inputClassName = \"\",\n size = \"md\",\n label,\n },\n ref,\n ) {\n const inputId = useId();\n const listId = `${inputId}-list`;\n const [internalValue, setInternalValue] = useState<string[]>(defaultValue);\n const [isOpen, setIsOpen] = useState(false);\n const [highlightedIndex, setHighlightedIndex] = useState(-1);\n const [searchValue, setSearchValue] = useState(\"\");\n const containerRef = useRef<HTMLDivElement>(null);\n const inputRef = useRef<HTMLInputElement>(null);\n const listRef = useRef<HTMLDivElement>(null);\n\n const isControlled = controlledValue !== undefined;\n const selectedValues = isControlled ? controlledValue : internalValue;\n\n // Get selected options\n const selectedOptions = options.filter((opt) =>\n selectedValues.includes(opt.value),\n );\n\n // Filter options (exclude already selected if needed, or show all)\n const getFilteredOptions = (): AutocompleteOptionType[] => {\n let filtered = options;\n\n if (searchValue.trim()) {\n filtered = options.filter((option) =>\n option.label.toLowerCase().includes(searchValue.toLowerCase()),\n );\n }\n\n return filtered;\n };\n\n const filteredOptions = getFilteredOptions();\n const hasOptions = filteredOptions.length > 0;\n\n // Handle input change\n const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const newValue = e.target.value;\n setSearchValue(newValue);\n setIsOpen(true);\n setHighlightedIndex(-1);\n };\n\n // Handle option toggle\n const handleToggleOption = (option: AutocompleteOptionType) => {\n if (option.disabled) return;\n if (\n maxSelected &&\n selectedValues.length >= maxSelected &&\n !selectedValues.includes(option.value)\n ) {\n return;\n }\n\n const newValues = selectedValues.includes(option.value)\n ? selectedValues.filter((v) => v !== option.value)\n : [...selectedValues, option.value];\n\n if (!isControlled) {\n setInternalValue(newValues);\n }\n\n onChange?.(newValues);\n onSelect?.(options.filter((opt) => newValues.includes(opt.value)));\n setSearchValue(\"\");\n // Clearing the search reverts filteredOptions to the full list, so a\n // stale highlightedIndex would point at a different row — reset it.\n setHighlightedIndex(-1);\n };\n\n // Handle select all\n const handleSelectAll = () => {\n const allValues = filteredOptions\n .filter((opt) => !opt.disabled)\n .map((opt) => opt.value);\n const merged = [...new Set([...selectedValues, ...allValues])];\n // Respect maxSelected — the single-toggle path enforces it, so\n // Select All must not be able to overshoot the cap.\n const newValues = maxSelected ? merged.slice(0, maxSelected) : merged;\n\n if (!isControlled) {\n setInternalValue(newValues);\n }\n\n onChange?.(newValues);\n onSelect?.(options.filter((opt) => newValues.includes(opt.value)));\n };\n\n // Handle deselect all\n const handleDeselectAll = () => {\n const filteredValues = filteredOptions.map((opt) => opt.value);\n const newValues = selectedValues.filter(\n (v) => !filteredValues.includes(v),\n );\n\n if (!isControlled) {\n setInternalValue(newValues);\n }\n\n onChange?.(newValues);\n onSelect?.(options.filter((opt) => newValues.includes(opt.value)));\n };\n\n // Handle remove chip\n const handleRemoveChip = (value: string) => {\n if (disabled) return;\n const newValues = selectedValues.filter((v) => v !== value);\n\n if (!isControlled) {\n setInternalValue(newValues);\n }\n\n onChange?.(newValues);\n onSelect?.(options.filter((opt) => newValues.includes(opt.value)));\n };\n\n // Handle keyboard navigation\n const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {\n if (!isOpen || filteredOptions.length === 0) {\n if (e.key === \"ArrowDown\" || e.key === \"Enter\") {\n setIsOpen(true);\n }\n // Remove last chip on backspace\n if (\n e.key === \"Backspace\" &&\n searchValue === \"\" &&\n selectedOptions.length > 0\n ) {\n // Remove the LAST VISIBLE chip — chips render from\n // selectedOptions (options order), which can differ from\n // selectedValues (insertion order).\n handleRemoveChip(selectedOptions[selectedOptions.length - 1].value);\n }\n return;\n }\n\n switch (e.key) {\n case \"ArrowDown\":\n e.preventDefault();\n setHighlightedIndex((prev) =>\n prev < filteredOptions.length - 1 ? prev + 1 : 0,\n );\n break;\n case \"ArrowUp\":\n e.preventDefault();\n setHighlightedIndex((prev) =>\n prev > 0 ? prev - 1 : filteredOptions.length - 1,\n );\n break;\n case \"Enter\":\n e.preventDefault();\n if (\n highlightedIndex >= 0 &&\n highlightedIndex < filteredOptions.length\n ) {\n handleToggleOption(filteredOptions[highlightedIndex]);\n }\n break;\n case \"Escape\":\n e.preventDefault();\n setIsOpen(false);\n setHighlightedIndex(-1);\n break;\n }\n };\n\n // Close on click outside\n useEffect(() => {\n if (!isOpen) return;\n\n const handleClickOutside = (e: MouseEvent) => {\n const target = e.target as Node;\n // The list is portalled to document.body (outside containerRef),\n // so without the listRef check a mousedown on an option closed the\n // list before its click toggled the selection.\n if (\n containerRef.current &&\n !containerRef.current.contains(target) &&\n !listRef.current?.contains(target)\n ) {\n setIsOpen(false);\n setHighlightedIndex(-1);\n setSearchValue(\"\");\n }\n };\n\n document.addEventListener(\"mousedown\", handleClickOutside);\n return () =>\n document.removeEventListener(\"mousedown\", handleClickOutside);\n }, [isOpen]);\n\n // Check if all filtered options are selected\n const allSelected = filteredOptions\n .filter((opt) => !opt.disabled)\n .every((opt) => selectedValues.includes(opt.value));\n\n const shouldShowList =\n isOpen && (hasOptions || loading || Boolean(emptyMessage));\n const atCap = maxSelected != null && selectedValues.length >= maxSelected;\n const activeOptionId =\n shouldShowList &&\n highlightedIndex >= 0 &&\n highlightedIndex < filteredOptions.length\n ? `${listId}-option-${highlightedIndex}`\n : undefined;\n\n return (\n <div ref={containerRef} className={cn(\"relative\", className)}>\n <label\n htmlFor={inputId}\n className={cn(\n \"block\",\n getSpacingClass(\"sm\", \"mb\"),\n \"text-sm\",\n \"font-medium\",\n \"text-fg-primary\",\n )}\n >\n {label}\n </label>\n <div\n className={cn(\n \"flex\",\n \"flex-wrap\",\n getSpacingClass(\"sm\", \"gap\"),\n getSpacingClass(\"sm\", \"p\"),\n \"border\",\n \"border-line-default\",\n getRadiusClass(\"md\"),\n \"min-h-10\",\n \"focus-within:outline-none\",\n \"focus-within:ring-2\",\n \"focus-within:ring-offset-2\",\n \"focus-within:border-line-brand\",\n \"focus-within:ring-line-brand\",\n )}\n >\n {selectedOptions.map((option) => (\n <Chip\n key={option.value}\n disabled={disabled}\n onRemove={() => handleRemoveChip(option.value)}\n size={size === \"sm\" ? \"sm\" : size === \"lg\" ? \"lg\" : \"md\"}\n >\n {option.label}\n </Chip>\n ))}\n <input\n id={inputId}\n ref={(node) => {\n if (typeof ref === \"function\") {\n ref(node);\n } else if (ref) {\n (\n ref as React.MutableRefObject<HTMLInputElement | null>\n ).current = node;\n }\n inputRef.current = node;\n }}\n type=\"text\"\n role=\"combobox\"\n aria-expanded={shouldShowList}\n aria-haspopup=\"listbox\"\n aria-controls={shouldShowList ? listId : undefined}\n aria-autocomplete=\"list\"\n aria-activedescendant={activeOptionId}\n value={searchValue}\n onChange={handleInputChange}\n onKeyDown={handleKeyDown}\n onFocus={() => setIsOpen(true)}\n placeholder={selectedValues.length === 0 ? placeholder : \"\"}\n disabled={disabled}\n className={cn(\n \"flex-1\",\n \"min-w-32\",\n \"outline-none\",\n \"bg-transparent\",\n inputClassName,\n )}\n />\n </div>\n\n {shouldShowList && (\n <AutocompleteList\n ref={listRef}\n // Cascade the input's accessible-name source to the\n // listbox portal — axe `aria-input-field-name` flags a\n // role=\"listbox\" without aria-label / aria-labelledby.\n // MultiSelect's `label` is TS-required, so the listbox\n // always inherits a name.\n id={listId}\n selectedValues={selectedValues}\n aria-label={label}\n options={filteredOptions.map((opt) => ({\n ...opt,\n // Once the cap is hit, not-yet-selected options are disabled\n // so they stop accepting clicks silently (maxSelected was a\n // no-op with no affordance before).\n disabled:\n opt.disabled || (atCap && !selectedValues.includes(opt.value)),\n icon: selectedValues.includes(opt.value) ? (\n <Check className={cn(\"h-4\", \"w-4\", \"text-fg-brand\")} />\n ) : (\n opt.icon\n ),\n }))}\n highlightedIndex={highlightedIndex}\n onSelect={handleToggleOption}\n loading={loading}\n emptyMessage={emptyMessage}\n containerRef={containerRef}\n showSelectAll={showSelectAll && filteredOptions.length > 0}\n allSelected={allSelected}\n onSelectAll={handleSelectAll}\n onDeselectAll={handleDeselectAll}\n />\n )}\n </div>\n );\n },\n);\n\nMultiSelect.displayName = \"MultiSelect\";\n\nexport default MultiSelect;\n"],"names":["MultiSelect","forwardRef","options","controlledValue","defaultValue","onChange","onSelect","placeholder","loading","disabled","emptyMessage","maxSelected","showSelectAll","className","inputClassName","size","label","ref","inputId","useId","listId","internalValue","setInternalValue","useState","isOpen","setIsOpen","highlightedIndex","setHighlightedIndex","searchValue","setSearchValue","containerRef","useRef","inputRef","listRef","isControlled","selectedValues","selectedOptions","opt","filteredOptions","filtered","option","hasOptions","handleInputChange","newValue","handleToggleOption","newValues","v","handleSelectAll","allValues","merged","handleDeselectAll","filteredValues","handleRemoveChip","value","handleKeyDown","prev","useEffect","handleClickOutside","e","target","_a","allSelected","shouldShowList","atCap","activeOptionId","jsxs","cn","jsx","getSpacingClass","getRadiusClass","Chip","node","AutocompleteList","__spreadProps","__spreadValues","Check"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"Navigation.js","sources":["../../../../../src/ui/components/Navigation/Navigation.tsx"],"sourcesContent":["/**\n * Navigation Component\n *\n * Horizontal or vertical navigation component using NavLink internally.\n *\n * @see EPIC-003: Navigation Component (Molecule)\n * @see RFC-005: Navigation Composition Pattern (APPROVED)\n */\n\n\"use client\";\n\nimport { useMemo } from \"react\";\nimport { NavLink } from \"../../primitives/NavLink\";\nimport type { NavigationProps } from \"./types\";\nimport { cn, cva } from \"../../utils\";\nimport { getSpacingClass } from \"../../tokens/spacing\";\n\n/**\n * Navigation Variants using CVA\n * Type-safe variant system for Navigation component\n */\nconst navigationVariants = cva(\n // Base classes\n cn(\"flex\", \"items-center\", getSpacingClass(\"sm\", \"gap\")),\n {\n variants: {\n orientation: {\n horizontal: \"flex-row\",\n vertical: \"flex-col\",\n },\n variant: {\n default: \"\",\n pills: \"\",\n tabs: \"\",\n },\n },\n defaultVariants: {\n orientation: \"horizontal\",\n variant: \"default\",\n },\n compoundVariants: [\n {\n orientation: \"vertical\",\n variant: \"default\",\n class: \"items-stretch\",\n },\n {\n orientation: \"vertical\",\n variant: \"pills\",\n class: \"items-stretch\",\n },\n {\n orientation: \"vertical\",\n variant: \"tabs\",\n class: \"items-stretch\",\n },\n ],\n },\n);\n\n/**\n * Navigation Component\n *\n * Navigation component that uses NavLink internally.\n * Supports horizontal and vertical orientations, variants, and icons.\n *\n * @example\n * ```tsx\n * <Navigation\n * items={[\n * { href: '/home', label: 'Home', active: true },\n * { href: '/about', label: 'About' },\n * ]}\n * orientation=\"horizontal\"\n * variant=\"default\"\n * />\n * ```\n */\n/**\n * Navigation Component (Internal with pathname detection)\n *\n * Internal component that can use Next.js usePathname hook.\n */\nfunction NavigationWithPathname({\n items,\n orientation = \"horizontal\",\n variant = \"default\",\n className,\n \"aria-label\": ariaLabel = \"Main navigation\",\n bare = false,\n pathname: providedPathname,\n ...props\n}: NavigationProps & { pathname?: string }) {\n // Pathname channel: explicit prop wins. Falls back to\n // window.location.pathname so a non-Next.js app still gets initial\n // active-state highlighting. Note: window.location does not re-render\n // on client-side navigation — Next.js apps should pass\n // `pathname={usePathname()}` explicitly for reactive updates.\n const currentPathname: string | undefined =\n providedPathname ??\n (typeof window !== \"undefined\" ? window.location.pathname : undefined);\n\n // Calculate active state for items\n const itemsWithActive = useMemo(() => {\n return items.map((item) => {\n // Manual active prop has priority\n if (item.active !== undefined) {\n return item;\n }\n\n // Auto-detect if pathname is available\n if (currentPathname) {\n const isActive =\n currentPathname === item.href ||\n (item.href !== \"/\" && currentPathname.startsWith(`${item.href}/`));\n return { ...item, active: isActive };\n }\n\n // Default to false\n return { ...item, active: false };\n });\n }, [items, currentPathname]);\n\n const content = (\n <>\n {itemsWithActive.map((item, index) => {\n // Map Navigation variants to NavLink variants\n const navLinkVariant =\n variant === \"pills\"\n ? \"background\"\n : variant === \"tabs\"\n ? \"underline\"\n : \"default\";\n\n return (\n <NavLink\n key={item.href || index}\n href={item.href}\n active={item.active}\n disabled={item.disabled}\n variant={navLinkVariant}\n className={cn(\n \"flex items-center\",\n getSpacingClass(\"sm\", \"gap\"),\n orientation === \"vertical\" && \"w-full justify-start\",\n item.className,\n )}\n >\n {item.icon && (\n <span className=\"flex-shrink-0\" aria-hidden=\"true\">\n {item.icon}\n </span>\n )}\n <span>{item.label}</span>\n {item.badge && <span className=\"ml-auto\">{item.badge}</span>}\n </NavLink>\n );\n })}\n </>\n );\n\n // Bare mode: Just render content without nav wrapper\n // Useful when used inside Header.Navigation which provides the nav wrapper\n if (bare) {\n return (\n <div\n className={cn(navigationVariants({ orientation, variant }), className)}\n {...props}\n >\n {content}\n </div>\n );\n }\n\n // Normal mode: Create nav element\n return (\n <nav\n className={cn(navigationVariants({ orientation, variant }), className)}\n aria-label={ariaLabel}\n {...props}\n >\n {content}\n </nav>\n );\n}\n\n/**\n * Navigation Component (Public API)\n *\n * Wrapper that handles Next.js integration safely.\n * Always uses NavigationWithPathname which will try to auto-detect pathname.\n */\nexport function Navigation(props: NavigationProps) {\n return <NavigationWithPathname {...props} pathname={props.pathname} />;\n}\n\nexport default Navigation;\n"],"names":["navigationVariants","cva","cn","getSpacingClass","NavigationWithPathname","_a","_b","items","orientation","variant","className","ariaLabel","bare","providedPathname","props","__objRest","currentPathname","itemsWithActive","useMemo","item","isActive","__spreadProps","__spreadValues","content","jsx","Fragment","index","navLinkVariant","jsxs","NavLink","Navigation"],"mappings":"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"}
1
+ {"version":3,"file":"Navigation.js","sources":["../../../../../src/ui/components/Navigation/Navigation.tsx"],"sourcesContent":["/**\n * Navigation Component\n *\n * Horizontal or vertical navigation component using NavLink internally.\n *\n * @see EPIC-003: Navigation Component\n * @see RFC-005: Navigation Composition Pattern (APPROVED)\n */\n\n\"use client\";\n\nimport { useMemo } from \"react\";\nimport { NavLink } from \"../../primitives/NavLink\";\nimport type { NavigationProps } from \"./types\";\nimport { cn, cva } from \"../../utils\";\nimport { getSpacingClass } from \"../../tokens/spacing\";\n\n/**\n * Navigation Variants using CVA\n * Type-safe variant system for Navigation component\n */\nconst navigationVariants = cva(\n // Base classes\n cn(\"flex\", \"items-center\", getSpacingClass(\"sm\", \"gap\")),\n {\n variants: {\n orientation: {\n horizontal: \"flex-row\",\n vertical: \"flex-col\",\n },\n variant: {\n default: \"\",\n pills: \"\",\n tabs: \"\",\n },\n },\n defaultVariants: {\n orientation: \"horizontal\",\n variant: \"default\",\n },\n compoundVariants: [\n {\n orientation: \"vertical\",\n variant: \"default\",\n class: \"items-stretch\",\n },\n {\n orientation: \"vertical\",\n variant: \"pills\",\n class: \"items-stretch\",\n },\n {\n orientation: \"vertical\",\n variant: \"tabs\",\n class: \"items-stretch\",\n },\n ],\n },\n);\n\n/**\n * Navigation Component\n *\n * Navigation component that uses NavLink internally.\n * Supports horizontal and vertical orientations, variants, and icons.\n *\n * @example\n * ```tsx\n * <Navigation\n * items={[\n * { href: '/home', label: 'Home', active: true },\n * { href: '/about', label: 'About' },\n * ]}\n * orientation=\"horizontal\"\n * variant=\"default\"\n * />\n * ```\n */\n/**\n * Navigation Component (Internal with pathname detection)\n *\n * Internal component that can use Next.js usePathname hook.\n */\nfunction NavigationWithPathname({\n items,\n orientation = \"horizontal\",\n variant = \"default\",\n className,\n \"aria-label\": ariaLabel = \"Main navigation\",\n bare = false,\n pathname: providedPathname,\n ...props\n}: NavigationProps & { pathname?: string }) {\n // Pathname channel: explicit prop wins. Falls back to\n // window.location.pathname so a non-Next.js app still gets initial\n // active-state highlighting. Note: window.location does not re-render\n // on client-side navigation — Next.js apps should pass\n // `pathname={usePathname()}` explicitly for reactive updates.\n const currentPathname: string | undefined =\n providedPathname ??\n (typeof window !== \"undefined\" ? window.location.pathname : undefined);\n\n // Calculate active state for items\n const itemsWithActive = useMemo(() => {\n return items.map((item) => {\n // Manual active prop has priority\n if (item.active !== undefined) {\n return item;\n }\n\n // Auto-detect if pathname is available\n if (currentPathname) {\n const isActive =\n currentPathname === item.href ||\n (item.href !== \"/\" && currentPathname.startsWith(`${item.href}/`));\n return { ...item, active: isActive };\n }\n\n // Default to false\n return { ...item, active: false };\n });\n }, [items, currentPathname]);\n\n const content = (\n <>\n {itemsWithActive.map((item, index) => {\n // Map Navigation variants to NavLink variants\n const navLinkVariant =\n variant === \"pills\"\n ? \"background\"\n : variant === \"tabs\"\n ? \"underline\"\n : \"default\";\n\n return (\n <NavLink\n key={item.href || index}\n href={item.href}\n active={item.active}\n disabled={item.disabled}\n variant={navLinkVariant}\n className={cn(\n \"flex items-center\",\n getSpacingClass(\"sm\", \"gap\"),\n orientation === \"vertical\" && \"w-full justify-start\",\n item.className,\n )}\n >\n {item.icon && (\n <span className=\"flex-shrink-0\" aria-hidden=\"true\">\n {item.icon}\n </span>\n )}\n <span>{item.label}</span>\n {item.badge && <span className=\"ml-auto\">{item.badge}</span>}\n </NavLink>\n );\n })}\n </>\n );\n\n // Bare mode: Just render content without nav wrapper\n // Useful when used inside Header.Navigation which provides the nav wrapper\n if (bare) {\n return (\n <div\n className={cn(navigationVariants({ orientation, variant }), className)}\n {...props}\n >\n {content}\n </div>\n );\n }\n\n // Normal mode: Create nav element\n return (\n <nav\n className={cn(navigationVariants({ orientation, variant }), className)}\n aria-label={ariaLabel}\n {...props}\n >\n {content}\n </nav>\n );\n}\n\n/**\n * Navigation Component (Public API)\n *\n * Wrapper that handles Next.js integration safely.\n * Always uses NavigationWithPathname which will try to auto-detect pathname.\n */\nexport function Navigation(props: NavigationProps) {\n return <NavigationWithPathname {...props} pathname={props.pathname} />;\n}\n\nexport default Navigation;\n"],"names":["navigationVariants","cva","cn","getSpacingClass","NavigationWithPathname","_a","_b","items","orientation","variant","className","ariaLabel","bare","providedPathname","props","__objRest","currentPathname","itemsWithActive","useMemo","item","isActive","__spreadProps","__spreadValues","content","jsx","Fragment","index","navLinkVariant","jsxs","NavLink","Navigation"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"PageHeader.js","sources":["../../../../../src/ui/components/PageHeader/PageHeader.tsx"],"sourcesContent":["/**\n * PageHeader Component\n *\n * Page header component with title, description, breadcrumb, and actions.\n *\n * @see EPIC-004: PageHeader Component (Molecule)\n */\n\nimport Breadcrumb from \"../Breadcrumb/Breadcrumb\";\nimport Text from \"../../primitives/Text/Text\";\nimport type { PageHeaderProps } from \"./types\";\nimport { cn, cva } from \"../../utils\";\nimport { getSpacingClass } from \"../../tokens/spacing\";\n\n/**\n * PageHeader Variants using CVA\n * Type-safe variant system for PageHeader component\n */\nconst pageHeaderVariants = cva(\n // Base classes\n cn(\"w-full\", \"flex\", \"flex-col\", getSpacingClass(\"sm\", \"gap\")),\n {\n variants: {\n variant: {\n default: cn(getSpacingClass(\"base\", \"mb\")),\n compact: cn(getSpacingClass(\"sm\", \"mb\")),\n },\n },\n defaultVariants: {\n variant: \"default\",\n },\n },\n);\n\n/**\n * PageHeader Component\n *\n * Page header with title, description, breadcrumb, and actions.\n *\n * @example\n * ```tsx\n * <PageHeader\n * title=\"Page Title\"\n * description=\"Page description\"\n * breadcrumb={[\n * { label: 'Home', href: '/' },\n * { label: 'Page', href: '/page' },\n * ]}\n * actions={<Button>Action</Button>}\n * />\n * ```\n */\nexport function PageHeader({\n title,\n description,\n breadcrumb,\n actions,\n variant = \"default\",\n className,\n ...props\n}: PageHeaderProps) {\n return (\n <div className={cn(pageHeaderVariants({ variant }), className)} {...props}>\n {/* Breadcrumb */}\n {breadcrumb && breadcrumb.length > 0 && <Breadcrumb items={breadcrumb} />}\n\n {/* Title and Actions Row */}\n <div\n className={`flex items-start justify-between ${getSpacingClass(\"base\", \"gap\")}`}\n >\n {/* Title and Description */}\n <div className=\"flex-1 min-w-0\">\n <Text\n variant=\"heading\"\n as=\"h1\"\n className={`${getSpacingClass(\"sm\", \"mb\")} text-2xl font-bold`}\n >\n {title}\n </Text>\n {description && (\n <Text variant=\"body\" className=\"text-fg-secondary\">\n {description}\n </Text>\n )}\n </div>\n\n {/* Actions */}\n {actions && (\n <div\n className={`flex items-center ${getSpacingClass(\"sm\", \"gap\")} flex-shrink-0`}\n >\n {actions}\n </div>\n )}\n </div>\n </div>\n );\n}\n\nexport default PageHeader;\n"],"names":["pageHeaderVariants","cva","cn","getSpacingClass","PageHeader","_a","_b","title","description","breadcrumb","actions","variant","className","props","__objRest","jsxs","__spreadProps","__spreadValues","jsx","Breadcrumb","Text"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkBA,MAAMA,IAAqBC;AAAA;AAAA,EAEzBC,EAAG,UAAU,QAAQ,YAAYC,EAAgB,MAAM,KAAK,CAAC;AAAA,EAC7D;AAAA,IACE,UAAU;AAAA,MACR,SAAS;AAAA,QACP,SAASD,EAAGC,EAAgB,QAAQ,IAAI,CAAC;AAAA,QACzC,SAASD,EAAGC,EAAgB,MAAM,IAAI,CAAC;AAAA,MAAA;AAAA,IACzC;AAAA,IAEF,iBAAiB;AAAA,MACf,SAAS;AAAA,IAAA;AAAA,EACX;AAEJ;AAoBO,SAASC,EAAWC,GAQP;AARO,MAAAC,IAAAD,GACzB;AAAA,WAAAE;AAAA,IACA,aAAAC;AAAA,IACA,YAAAC;AAAA,IACA,SAAAC;AAAA,IACA,SAAAC,IAAU;AAAA,IACV,WAAAC;AAAA,MANyBN,GAOtBO,IAAAC,EAPsBR,GAOtB;AAAA,IANH;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA;AAGA,SACE,gBAAAS,EAAC,OAAAC,EAAAC,EAAA,EAAI,WAAWf,EAAGF,EAAmB,EAAE,SAAAW,EAAA,CAAS,GAAGC,CAAS,KAAOC,IAAnE,EAEE,UAAA;AAAA,IAAAJ,KAAcA,EAAW,SAAS,KAAK,gBAAAS,EAACC,GAAA,EAAW,OAAOV,GAAY;AAAA,IAGvE,gBAAAM;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,WAAW,oCAAoCZ,EAAgB,QAAQ,KAAK,CAAC;AAAA,QAG7E,UAAA;AAAA,UAAA,gBAAAY,EAAC,OAAA,EAAI,WAAU,kBACb,UAAA;AAAA,YAAA,gBAAAG;AAAA,cAACE;AAAA,cAAA;AAAA,gBACC,SAAQ;AAAA,gBACR,IAAG;AAAA,gBACH,WAAW,GAAGjB,EAAgB,MAAM,IAAI,CAAC;AAAA,gBAExC,UAAAI;AAAA,cAAA;AAAA,YAAA;AAAA,YAEFC,KACC,gBAAAU,EAACE,GAAA,EAAK,SAAQ,QAAO,WAAU,qBAC5B,UAAAZ,EAAA,CACH;AAAA,UAAA,GAEJ;AAAA,UAGCE,KACC,gBAAAQ;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,WAAW,qBAAqBf,EAAgB,MAAM,KAAK,CAAC;AAAA,cAE3D,UAAAO;AAAA,YAAA;AAAA,UAAA;AAAA,QACH;AAAA,MAAA;AAAA,IAAA;AAAA,EAEJ,IACF;AAEJ;"}
1
+ {"version":3,"file":"PageHeader.js","sources":["../../../../../src/ui/components/PageHeader/PageHeader.tsx"],"sourcesContent":["/**\n * PageHeader Component\n *\n * Page header component with title, description, breadcrumb, and actions.\n *\n * @see EPIC-004: PageHeader Component\n */\n\nimport Breadcrumb from \"../Breadcrumb/Breadcrumb\";\nimport Text from \"../../primitives/Text/Text\";\nimport type { PageHeaderProps } from \"./types\";\nimport { cn, cva } from \"../../utils\";\nimport { getSpacingClass } from \"../../tokens/spacing\";\n\n/**\n * PageHeader Variants using CVA\n * Type-safe variant system for PageHeader component\n */\nconst pageHeaderVariants = cva(\n // Base classes\n cn(\"w-full\", \"flex\", \"flex-col\", getSpacingClass(\"sm\", \"gap\")),\n {\n variants: {\n variant: {\n default: cn(getSpacingClass(\"base\", \"mb\")),\n compact: cn(getSpacingClass(\"sm\", \"mb\")),\n },\n },\n defaultVariants: {\n variant: \"default\",\n },\n },\n);\n\n/**\n * PageHeader Component\n *\n * Page header with title, description, breadcrumb, and actions.\n *\n * @example\n * ```tsx\n * <PageHeader\n * title=\"Page Title\"\n * description=\"Page description\"\n * breadcrumb={[\n * { label: 'Home', href: '/' },\n * { label: 'Page', href: '/page' },\n * ]}\n * actions={<Button>Action</Button>}\n * />\n * ```\n */\nexport function PageHeader({\n title,\n description,\n breadcrumb,\n actions,\n variant = \"default\",\n className,\n ...props\n}: PageHeaderProps) {\n return (\n <div className={cn(pageHeaderVariants({ variant }), className)} {...props}>\n {/* Breadcrumb */}\n {breadcrumb && breadcrumb.length > 0 && <Breadcrumb items={breadcrumb} />}\n\n {/* Title and Actions Row */}\n <div\n className={`flex items-start justify-between ${getSpacingClass(\"base\", \"gap\")}`}\n >\n {/* Title and Description */}\n <div className=\"flex-1 min-w-0\">\n <Text\n variant=\"heading\"\n as=\"h1\"\n className={`${getSpacingClass(\"sm\", \"mb\")} text-2xl font-bold`}\n >\n {title}\n </Text>\n {description && (\n <Text variant=\"body\" className=\"text-fg-secondary\">\n {description}\n </Text>\n )}\n </div>\n\n {/* Actions */}\n {actions && (\n <div\n className={`flex items-center ${getSpacingClass(\"sm\", \"gap\")} flex-shrink-0`}\n >\n {actions}\n </div>\n )}\n </div>\n </div>\n );\n}\n\nexport default PageHeader;\n"],"names":["pageHeaderVariants","cva","cn","getSpacingClass","PageHeader","_a","_b","title","description","breadcrumb","actions","variant","className","props","__objRest","jsxs","__spreadProps","__spreadValues","jsx","Breadcrumb","Text"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkBA,MAAMA,IAAqBC;AAAA;AAAA,EAEzBC,EAAG,UAAU,QAAQ,YAAYC,EAAgB,MAAM,KAAK,CAAC;AAAA,EAC7D;AAAA,IACE,UAAU;AAAA,MACR,SAAS;AAAA,QACP,SAASD,EAAGC,EAAgB,QAAQ,IAAI,CAAC;AAAA,QACzC,SAASD,EAAGC,EAAgB,MAAM,IAAI,CAAC;AAAA,MAAA;AAAA,IACzC;AAAA,IAEF,iBAAiB;AAAA,MACf,SAAS;AAAA,IAAA;AAAA,EACX;AAEJ;AAoBO,SAASC,EAAWC,GAQP;AARO,MAAAC,IAAAD,GACzB;AAAA,WAAAE;AAAA,IACA,aAAAC;AAAA,IACA,YAAAC;AAAA,IACA,SAAAC;AAAA,IACA,SAAAC,IAAU;AAAA,IACV,WAAAC;AAAA,MANyBN,GAOtBO,IAAAC,EAPsBR,GAOtB;AAAA,IANH;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA;AAGA,SACE,gBAAAS,EAAC,OAAAC,EAAAC,EAAA,EAAI,WAAWf,EAAGF,EAAmB,EAAE,SAAAW,EAAA,CAAS,GAAGC,CAAS,KAAOC,IAAnE,EAEE,UAAA;AAAA,IAAAJ,KAAcA,EAAW,SAAS,KAAK,gBAAAS,EAACC,GAAA,EAAW,OAAOV,GAAY;AAAA,IAGvE,gBAAAM;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,WAAW,oCAAoCZ,EAAgB,QAAQ,KAAK,CAAC;AAAA,QAG7E,UAAA;AAAA,UAAA,gBAAAY,EAAC,OAAA,EAAI,WAAU,kBACb,UAAA;AAAA,YAAA,gBAAAG;AAAA,cAACE;AAAA,cAAA;AAAA,gBACC,SAAQ;AAAA,gBACR,IAAG;AAAA,gBACH,WAAW,GAAGjB,EAAgB,MAAM,IAAI,CAAC;AAAA,gBAExC,UAAAI;AAAA,cAAA;AAAA,YAAA;AAAA,YAEFC,KACC,gBAAAU,EAACE,GAAA,EAAK,SAAQ,QAAO,WAAU,qBAC5B,UAAAZ,EAAA,CACH;AAAA,UAAA,GAEJ;AAAA,UAGCE,KACC,gBAAAQ;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,WAAW,qBAAqBf,EAAgB,MAAM,KAAK,CAAC;AAAA,cAE3D,UAAAO;AAAA,YAAA;AAAA,UAAA;AAAA,QACH;AAAA,MAAA;AAAA,IAAA;AAAA,EAEJ,IACF;AAEJ;"}
@@ -1 +1 @@
1
- {"version":3,"file":"Pagination.js","sources":["../../../../../src/ui/components/Pagination/Pagination.tsx"],"sourcesContent":["\"use client\";\n\nimport type { HTMLAttributes } from \"react\";\nimport { Button } from \"../../primitives\";\nimport { cn } from \"../../utils\";\nimport { getSpacingClass, getTypographySizeFromFontSize } from \"../../tokens\";\n\ninterface Props extends HTMLAttributes<HTMLDivElement> {\n currentPage: number;\n totalPages: number;\n onPageChange: (page: number) => void;\n totalItems?: number;\n itemsPerPage?: number;\n showPageInfo?: boolean;\n}\n\n/**\n * Pagination Component\n *\n * A pagination component for navigating through pages of data.\n * Follows Atomic Design principles as a Molecule component.\n *\n * @example\n * ```tsx\n * <Pagination\n * currentPage={1}\n * totalPages={10}\n * onPageChange={(page) => setPage(page)}\n * totalItems={100}\n * itemsPerPage={10}\n * />\n * ```\n */\nexport default function Pagination({\n currentPage,\n totalPages,\n onPageChange,\n totalItems,\n itemsPerPage,\n showPageInfo = true,\n className = \"\",\n ...props\n}: Props) {\n const handlePrevious = () => {\n if (currentPage > 1) {\n onPageChange(currentPage - 1);\n }\n };\n\n const handleNext = () => {\n if (currentPage < totalPages) {\n onPageChange(currentPage + 1);\n }\n };\n\n const handlePageClick = (page: number) => {\n if (page >= 1 && page <= totalPages && page !== currentPage) {\n onPageChange(page);\n }\n };\n\n const getPageNumbers = () => {\n const pages: (number | string)[] = [];\n const maxVisible = 5;\n\n if (totalPages <= maxVisible) {\n for (let i = 1; i <= totalPages; i++) {\n pages.push(i);\n }\n } else {\n if (currentPage <= 3) {\n for (let i = 1; i <= 4; i++) {\n pages.push(i);\n }\n pages.push(\"ellipsis\");\n pages.push(totalPages);\n } else if (currentPage >= totalPages - 2) {\n pages.push(1);\n pages.push(\"ellipsis\");\n for (let i = totalPages - 3; i <= totalPages; i++) {\n pages.push(i);\n }\n } else {\n pages.push(1);\n pages.push(\"ellipsis\");\n for (let i = currentPage - 1; i <= currentPage + 1; i++) {\n pages.push(i);\n }\n pages.push(\"ellipsis\");\n pages.push(totalPages);\n }\n }\n\n return pages;\n };\n\n const startItem =\n totalItems && itemsPerPage\n ? (currentPage - 1) * itemsPerPage + 1\n : undefined;\n const endItem =\n totalItems && itemsPerPage\n ? Math.min(currentPage * itemsPerPage, totalItems)\n : undefined;\n\n const classes = cn(\n \"flex\",\n \"items-center\",\n \"justify-between\",\n getSpacingClass(\"base\", \"px\"),\n getSpacingClass(\"md\", \"py\"),\n className,\n );\n\n return (\n <nav className={classes} aria-label=\"Pagination\" {...props}>\n <div className={cn(\"flex\", \"items-center\", getSpacingClass(\"sm\", \"gap\"))}>\n <Button\n variant=\"secondary\"\n onClick={handlePrevious}\n disabled={currentPage === 1}\n size=\"sm\"\n >\n Previous\n </Button>\n <div\n className={cn(\"flex\", \"items-center\", getSpacingClass(\"xs\", \"gap\"))}\n >\n {getPageNumbers().map((page, index) => {\n if (page === \"ellipsis\") {\n return (\n <span\n key={`ellipsis-${index}`}\n className={cn(\n getSpacingClass(\"sm\", \"px\"),\n \"text-fg-tertiary\",\n )}\n >\n ...\n </span>\n );\n }\n\n const pageNum = page as number;\n const isActive = pageNum === currentPage;\n\n return (\n <Button\n key={pageNum}\n variant={isActive ? \"primary\" : \"ghost\"}\n onClick={() => handlePageClick(pageNum)}\n size=\"sm\"\n aria-current={isActive ? \"page\" : undefined}\n aria-label={`Go to page ${pageNum}`}\n >\n {pageNum}\n </Button>\n );\n })}\n </div>\n <Button\n variant=\"secondary\"\n onClick={handleNext}\n disabled={currentPage === totalPages}\n size=\"sm\"\n >\n Next\n </Button>\n </div>\n {showPageInfo && totalItems && itemsPerPage && (\n <div\n className={cn(getTypographySizeFromFontSize(\"sm\"), \"text-fg-primary\")}\n >\n Showing {startItem} to {endItem} of {totalItems} results\n </div>\n )}\n </nav>\n );\n}\n"],"names":["Pagination","_a","_b","currentPage","totalPages","onPageChange","totalItems","itemsPerPage","showPageInfo","className","props","__objRest","handlePrevious","handleNext","handlePageClick","page","getPageNumbers","pages","i","startItem","endItem","classes","cn","getSpacingClass","__spreadProps","__spreadValues","jsxs","jsx","Button","index","pageNum","isActive","getTypographySizeFromFontSize"],"mappings":"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"}
1
+ {"version":3,"file":"Pagination.js","sources":["../../../../../src/ui/components/Pagination/Pagination.tsx"],"sourcesContent":["\"use client\";\n\nimport type { HTMLAttributes } from \"react\";\nimport { Button } from \"../../primitives\";\nimport { cn } from \"../../utils\";\nimport { getSpacingClass, getTypographySizeFromFontSize } from \"../../tokens\";\n\ninterface Props extends HTMLAttributes<HTMLDivElement> {\n currentPage: number;\n totalPages: number;\n onPageChange: (page: number) => void;\n totalItems?: number;\n itemsPerPage?: number;\n showPageInfo?: boolean;\n}\n\n/**\n * Pagination Component\n *\n * A pagination component for navigating through pages of data.\n *\n * @example\n * ```tsx\n * <Pagination\n * currentPage={1}\n * totalPages={10}\n * onPageChange={(page) => setPage(page)}\n * totalItems={100}\n * itemsPerPage={10}\n * />\n * ```\n */\nexport default function Pagination({\n currentPage,\n totalPages,\n onPageChange,\n totalItems,\n itemsPerPage,\n showPageInfo = true,\n className = \"\",\n ...props\n}: Props) {\n const handlePrevious = () => {\n if (currentPage > 1) {\n onPageChange(currentPage - 1);\n }\n };\n\n const handleNext = () => {\n if (currentPage < totalPages) {\n onPageChange(currentPage + 1);\n }\n };\n\n const handlePageClick = (page: number) => {\n if (page >= 1 && page <= totalPages && page !== currentPage) {\n onPageChange(page);\n }\n };\n\n const getPageNumbers = () => {\n const pages: (number | string)[] = [];\n const maxVisible = 5;\n\n if (totalPages <= maxVisible) {\n for (let i = 1; i <= totalPages; i++) {\n pages.push(i);\n }\n } else {\n if (currentPage <= 3) {\n for (let i = 1; i <= 4; i++) {\n pages.push(i);\n }\n pages.push(\"ellipsis\");\n pages.push(totalPages);\n } else if (currentPage >= totalPages - 2) {\n pages.push(1);\n pages.push(\"ellipsis\");\n for (let i = totalPages - 3; i <= totalPages; i++) {\n pages.push(i);\n }\n } else {\n pages.push(1);\n pages.push(\"ellipsis\");\n for (let i = currentPage - 1; i <= currentPage + 1; i++) {\n pages.push(i);\n }\n pages.push(\"ellipsis\");\n pages.push(totalPages);\n }\n }\n\n return pages;\n };\n\n const startItem =\n totalItems && itemsPerPage\n ? (currentPage - 1) * itemsPerPage + 1\n : undefined;\n const endItem =\n totalItems && itemsPerPage\n ? Math.min(currentPage * itemsPerPage, totalItems)\n : undefined;\n\n const classes = cn(\n \"flex\",\n \"items-center\",\n \"justify-between\",\n getSpacingClass(\"base\", \"px\"),\n getSpacingClass(\"md\", \"py\"),\n className,\n );\n\n return (\n <nav className={classes} aria-label=\"Pagination\" {...props}>\n <div className={cn(\"flex\", \"items-center\", getSpacingClass(\"sm\", \"gap\"))}>\n <Button\n variant=\"secondary\"\n onClick={handlePrevious}\n disabled={currentPage === 1}\n size=\"sm\"\n >\n Previous\n </Button>\n <div\n className={cn(\"flex\", \"items-center\", getSpacingClass(\"xs\", \"gap\"))}\n >\n {getPageNumbers().map((page, index) => {\n if (page === \"ellipsis\") {\n return (\n <span\n key={`ellipsis-${index}`}\n className={cn(\n getSpacingClass(\"sm\", \"px\"),\n \"text-fg-tertiary\",\n )}\n >\n ...\n </span>\n );\n }\n\n const pageNum = page as number;\n const isActive = pageNum === currentPage;\n\n return (\n <Button\n key={pageNum}\n variant={isActive ? \"primary\" : \"ghost\"}\n onClick={() => handlePageClick(pageNum)}\n size=\"sm\"\n aria-current={isActive ? \"page\" : undefined}\n aria-label={`Go to page ${pageNum}`}\n >\n {pageNum}\n </Button>\n );\n })}\n </div>\n <Button\n variant=\"secondary\"\n onClick={handleNext}\n disabled={currentPage === totalPages}\n size=\"sm\"\n >\n Next\n </Button>\n </div>\n {showPageInfo && totalItems && itemsPerPage && (\n <div\n className={cn(getTypographySizeFromFontSize(\"sm\"), \"text-fg-primary\")}\n >\n Showing {startItem} to {endItem} of {totalItems} results\n </div>\n )}\n </nav>\n );\n}\n"],"names":["Pagination","_a","_b","currentPage","totalPages","onPageChange","totalItems","itemsPerPage","showPageInfo","className","props","__objRest","handlePrevious","handleNext","handlePageClick","page","getPageNumbers","pages","i","startItem","endItem","classes","cn","getSpacingClass","__spreadProps","__spreadValues","jsxs","jsx","Button","index","pageNum","isActive","getTypographySizeFromFontSize"],"mappings":"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"}