@cystackapp/ui 1.5.0 → 2.0.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.
Files changed (170) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +77 -47
  3. package/dist/assets/background-pattern-grid.svg.js +7 -0
  4. package/dist/assets/empty-cloud.svg.js +5 -0
  5. package/dist/components/accordion/Accordion.d.ts +20 -0
  6. package/dist/components/accordion/Accordion.js +36 -0
  7. package/dist/components/accordion/AccordionTestStory.d.ts +3 -0
  8. package/dist/components/alert/Alert.d.ts +15 -0
  9. package/dist/components/alert/Alert.js +54 -0
  10. package/dist/components/avatar/Avatar.d.ts +13 -0
  11. package/dist/components/avatar/Avatar.js +64 -0
  12. package/dist/components/background-pattern/BackgroundPatternGrid.d.ts +1 -0
  13. package/dist/components/background-pattern/BackgroundPatternGrid.js +6 -0
  14. package/dist/components/badge/Badge.d.ts +1 -1
  15. package/dist/components/badge/BadgeTestStory.d.ts +1 -1
  16. package/dist/components/badge/variants/BadgeMore.d.ts +1 -1
  17. package/dist/components/badge/variants/BadgeMoreTestStory.d.ts +1 -1
  18. package/dist/components/badge/variants/BadgeTag.d.ts +1 -1
  19. package/dist/components/banner/Banner.d.ts +9 -0
  20. package/dist/components/banner/Banner.js +21 -0
  21. package/dist/components/breadcrumb/Breadcrumb.d.ts +13 -0
  22. package/dist/components/breadcrumb/Breadcrumb.js +36 -0
  23. package/dist/components/button/ButtonLoader.d.ts +1 -1
  24. package/dist/components/button/ButtonTestStory.d.ts +5 -5
  25. package/dist/components/card/Card.d.ts +1 -1
  26. package/dist/components/card/Card.stories-ct.d.ts +1 -1
  27. package/dist/components/card/CardBody.d.ts +1 -1
  28. package/dist/components/card/CardHeader.d.ts +1 -1
  29. package/dist/components/chart/chart-legend/ChartLegend.d.ts +38 -0
  30. package/dist/components/chart/chart-legend/ChartLegend.js +57 -0
  31. package/dist/components/chart/chart-legend/ChartLegendItem.d.ts +19 -0
  32. package/dist/components/chart/chart-legend/ChartLegendItem.js +30 -0
  33. package/dist/components/chart/chart-legend/types.d.ts +49 -0
  34. package/dist/components/chart/donut-chart/DonutChart.d.ts +55 -0
  35. package/dist/components/chart/donut-chart/DonutChart.js +110 -0
  36. package/dist/components/chart/donut-chart/DonutSegments.d.ts +25 -0
  37. package/dist/components/chart/donut-chart/DonutSegments.js +51 -0
  38. package/dist/components/chart/donut-chart/donut-tooltip.d.ts +20 -0
  39. package/dist/components/chart/donut-chart/donut-tooltip.js +37 -0
  40. package/dist/components/chart/types.d.ts +8 -0
  41. package/dist/components/checkbox/CheckboxTestStory.d.ts +7 -7
  42. package/dist/components/collapsible/Collapsible.d.ts +1 -1
  43. package/dist/components/combobox/Combobox.d.ts +1 -1
  44. package/dist/components/divider/Divider.d.ts +9 -0
  45. package/dist/components/divider/Divider.js +28 -0
  46. package/dist/components/drawer/Drawer.d.ts +8 -0
  47. package/dist/components/drawer/Drawer.js +68 -0
  48. package/dist/components/dropdown/Dropdown.d.ts +45 -0
  49. package/dist/components/dropdown/Dropdown.js +133 -0
  50. package/dist/components/dropdown/DropdownMenu.d.ts +20 -0
  51. package/dist/components/dropdown/DropdownMenu.js +78 -0
  52. package/dist/components/dropdown/DropdownMenuItem.d.ts +13 -0
  53. package/dist/components/dropdown/DropdownMenuItem.js +49 -0
  54. package/dist/components/dropdown/DropdownTestStory.d.ts +5 -0
  55. package/dist/components/dropdown/dropdown-utils.d.ts +4 -0
  56. package/dist/components/dropdown/dropdown-utils.js +14 -0
  57. package/dist/components/dropdown/types.d.ts +48 -0
  58. package/dist/components/dropdown/use-dropdown-keyboard.d.ts +12 -0
  59. package/dist/components/dropdown/use-dropdown-keyboard.js +49 -0
  60. package/dist/components/empty-state/EmptyState.d.ts +26 -0
  61. package/dist/components/empty-state/EmptyState.js +36 -0
  62. package/dist/components/error-state/ErrorState.d.ts +1 -1
  63. package/dist/components/featured-icon/FeaturedIcon.d.ts +12 -0
  64. package/dist/components/featured-icon/FeaturedIcon.js +44 -0
  65. package/dist/components/form-field/FormField.d.ts +13 -0
  66. package/dist/components/form-field/FormField.js +21 -0
  67. package/dist/components/keyboard-shortcut-label/KeyboardShortcutLabel.d.ts +8 -0
  68. package/dist/components/keyboard-shortcut-label/KeyboardShortcutLabel.js +18 -0
  69. package/dist/components/loading-state/Loader.d.ts +20 -0
  70. package/dist/components/loading-state/Loader.js +38 -0
  71. package/dist/components/loading-state/LoadingState.d.ts +15 -0
  72. package/dist/components/loading-state/LoadingState.js +47 -0
  73. package/dist/components/loading-state/locale/en.json.d.ts +6 -0
  74. package/dist/components/loading-state/locale/en.json.js +7 -0
  75. package/dist/components/loading-state/locale/vi.json.d.ts +6 -0
  76. package/dist/components/loading-state/locale/vi.json.js +7 -0
  77. package/dist/components/media/Media.d.ts +7 -0
  78. package/dist/components/media/Media.js +25 -0
  79. package/dist/components/modal/helpers/HeaderIcon.d.ts +1 -1
  80. package/dist/components/modal/helpers/Title.d.ts +1 -1
  81. package/dist/components/notification/NotificationBanner.d.ts +9 -0
  82. package/dist/components/notification/NotificationBanner.js +97 -0
  83. package/dist/components/notification/icons.d.ts +5 -0
  84. package/dist/components/notification/icons.js +29 -0
  85. package/dist/components/notification/index.d.ts +4 -0
  86. package/dist/components/notification/index.js +26 -0
  87. package/dist/components/notification/locale/en.json.d.ts +8 -0
  88. package/dist/components/notification/locale/en.json.js +7 -0
  89. package/dist/components/notification/locale/vi.json.d.ts +8 -0
  90. package/dist/components/notification/locale/vi.json.js +7 -0
  91. package/dist/components/operating-system-icon/OperatingSystemIcon.d.ts +6 -0
  92. package/dist/components/operating-system-icon/OperatingSystemIcon.js +19 -0
  93. package/dist/components/operating-system-icon/assets/logo-android.svg.js +5 -0
  94. package/dist/components/operating-system-icon/assets/logo-apple.svg.js +5 -0
  95. package/dist/components/operating-system-icon/assets/logo-ubuntu.svg.js +5 -0
  96. package/dist/components/operating-system-icon/assets/logo-windows-10.svg.js +5 -0
  97. package/dist/components/page-title/PageTitle.d.ts +1 -1
  98. package/dist/components/popover/Popover.d.ts +1 -1
  99. package/dist/components/progress-bar/ProgressBar.d.ts +9 -0
  100. package/dist/components/progress-bar/ProgressBar.js +31 -0
  101. package/dist/components/radio/Radio.d.ts +4 -0
  102. package/dist/components/radio/Radio.js +55 -0
  103. package/dist/components/searchbox/Searchbox.d.ts +7 -0
  104. package/dist/components/searchbox/Searchbox.js +15 -0
  105. package/dist/components/select/Select.d.ts +11 -0
  106. package/dist/components/select/Select.js +44 -0
  107. package/dist/components/sidebar/SidebarSecondMenu.d.ts +38 -0
  108. package/dist/components/sidebar/SidebarSecondMenu.js +50 -0
  109. package/dist/components/skeleton/Skeleton.d.ts +14 -0
  110. package/dist/components/skeleton/Skeleton.js +12 -0
  111. package/dist/components/stat-banner-card/StatBannerCard.d.ts +24 -0
  112. package/dist/components/stat-banner-card/StatBannerCard.js +49 -0
  113. package/dist/components/switch/Switch.d.ts +1 -1
  114. package/dist/components/table/Table.d.ts +32 -0
  115. package/dist/components/table/Table.js +128 -0
  116. package/dist/components/table/TableActionButton.d.ts +15 -0
  117. package/dist/components/table/TableActionButton.js +50 -0
  118. package/dist/components/table/TableCell.d.ts +8 -0
  119. package/dist/components/table/TableCell.js +26 -0
  120. package/dist/components/table/TableHeader.d.ts +15 -0
  121. package/dist/components/table/TableHeader.js +36 -0
  122. package/dist/components/table/TableHeaderCell.d.ts +10 -0
  123. package/dist/components/table/TableHeaderCell.js +35 -0
  124. package/dist/components/table/TablePagination.d.ts +6 -0
  125. package/dist/components/table/TablePagination.js +69 -0
  126. package/dist/components/table/TableRow.d.ts +12 -0
  127. package/dist/components/table/TableRow.js +9 -0
  128. package/dist/components/table/expandable/ExpandableTable.d.ts +30 -0
  129. package/dist/components/table/expandable/ExpandableTable.js +156 -0
  130. package/dist/components/table/hooks/use-fit-page-height.d.ts +14 -0
  131. package/dist/components/table/hooks/use-fit-page-height.js +21 -0
  132. package/dist/components/table/hooks/use-row-selection.d.ts +27 -0
  133. package/dist/components/table/hooks/use-row-selection.js +35 -0
  134. package/dist/components/table/locale/en.json.d.ts +13 -0
  135. package/dist/components/table/locale/en.json.js +21 -0
  136. package/dist/components/table/locale/vi.json.d.ts +13 -0
  137. package/dist/components/table/locale/vi.json.js +21 -0
  138. package/dist/components/table/table-utils.d.ts +10 -0
  139. package/dist/components/table/table-utils.js +10 -0
  140. package/dist/components/table/types.d.ts +84 -0
  141. package/dist/components/tabs/Tabs.d.ts +27 -0
  142. package/dist/components/tabs/Tabs.js +75 -0
  143. package/dist/components/tabs/TabsTestStory.d.ts +4 -0
  144. package/dist/components/tags-input/TagsInput.d.ts +18 -0
  145. package/dist/components/tags-input/TagsInput.js +78 -0
  146. package/dist/components/tags-input/TagsInputTestStory.d.ts +3 -0
  147. package/dist/components/textarea/Textarea.d.ts +7 -0
  148. package/dist/components/textarea/Textarea.js +36 -0
  149. package/dist/components/toast/ToastSlice.d.ts +1 -1
  150. package/dist/components/toast/index.d.ts +1 -1
  151. package/dist/components/tooltip/Tooltip.d.ts +1 -1
  152. package/dist/filters/FilterDropdown.d.ts +9 -0
  153. package/dist/filters/FilterDropdown.js +57 -0
  154. package/dist/filters/types.d.ts +11 -0
  155. package/dist/filters/url-params.d.ts +5 -0
  156. package/dist/filters/url-params.js +20 -0
  157. package/dist/filters/use-filters.d.ts +13 -0
  158. package/dist/filters/use-filters.js +63 -0
  159. package/dist/hooks/use-countdown.d.ts +4 -0
  160. package/dist/hooks/use-countdown.js +18 -0
  161. package/dist/i18n/resources.js +23 -0
  162. package/dist/index.d.ts +56 -0
  163. package/dist/index.js +126 -40
  164. package/dist/node_modules/tailwind-merge/dist/bundle-mjs.js +421 -350
  165. package/dist/utils/key-typeguard.d.ts +5 -0
  166. package/dist/utils/key-typeguard.js +6 -0
  167. package/dist/utils/use-debounce.d.ts +1 -0
  168. package/dist/utils/use-debounce.js +11 -0
  169. package/package.json +32 -10
  170. package/theme.css +4 -1
@@ -0,0 +1,45 @@
1
+ import { DropdownProps } from './types';
2
+ /**
3
+ * Generic standalone dropdown for action menus, context menus, or selection lists.
4
+ *
5
+ * Supports controlled (`open`) and uncontrolled (`defaultOpen`) open state.
6
+ * When `selected` is provided, the dropdown shows checkmarks (selection mode).
7
+ * Otherwise it behaves as a plain action menu.
8
+ *
9
+ * @example
10
+ * // Action menu
11
+ * <Dropdown
12
+ * items={[
13
+ * { id: "edit", label: "Edit", icon: <Edit01 /> },
14
+ * { type: "divider" },
15
+ * { id: "delete", label: "Delete", danger: true },
16
+ * ]}
17
+ * onSelect={(item) => handleAction(item.id)}
18
+ * >
19
+ * <IconButton icon={<DotsVertical />} />
20
+ * </Dropdown>
21
+ *
22
+ * @example
23
+ * // Selection dropdown with checkmarks
24
+ * <Dropdown
25
+ * items={statusOptions}
26
+ * selected={currentStatus}
27
+ * onSelect={(item) => setStatus(item.id)}
28
+ * syncWidth
29
+ * >
30
+ * <Button>{currentStatusLabel} <ChevronDown /></Button>
31
+ * </Dropdown>
32
+ *
33
+ * @example
34
+ * // Custom item rendering
35
+ * <Dropdown
36
+ * items={[
37
+ * { id: "high", label: "High", render: () => <Badge color="error">High</Badge> },
38
+ * { id: "low", label: "Low", render: () => <Badge color="success">Low</Badge> },
39
+ * ]}
40
+ * onSelect={handleSelect}
41
+ * >
42
+ * <Button>Priority</Button>
43
+ * </Dropdown>
44
+ */
45
+ export declare const Dropdown: ({ items, onSelect, selected, open: openProp, defaultOpen, onOpenChange, placement, syncWidth, children, menuClassName, className, disabled, }: DropdownProps) => import("react").JSX.Element;
@@ -0,0 +1,133 @@
1
+ import { jsxs as C, Fragment as G, jsx as I } from "react/jsx-runtime";
2
+ import { useRef as b, useState as J, useMemo as P, useCallback as i, useEffect as g } from "react";
3
+ import { cn as Q } from "../../utils/cn.js";
4
+ import { usePopoverCoord as U } from "../popover/use-popover-coord.js";
5
+ import { DropdownMenu as V } from "./DropdownMenu.js";
6
+ import { flattenItems as W } from "./dropdown-utils.js";
7
+ import { useDropdownKeyboard as X } from "./use-dropdown-keyboard.js";
8
+ const oe = ({
9
+ items: d,
10
+ onSelect: m,
11
+ selected: r,
12
+ open: k,
13
+ defaultOpen: A = !1,
14
+ onOpenChange: p,
15
+ placement: K = "bottomLeft",
16
+ syncWidth: S = !1,
17
+ children: L,
18
+ menuClassName: R,
19
+ className: T,
20
+ disabled: a = !1
21
+ }) => {
22
+ const f = b(null), v = b(
23
+ `dropdown-menu-${Math.random().toString(36).slice(2, 9)}`
24
+ ).current, h = b(null), y = k !== void 0, [j, H] = J(A), n = y ? k : j, { style: N } = U(f, h, {
25
+ position: K,
26
+ syncWidth: S
27
+ }), { activeId: w, setActiveId: q, handleNavigationKeyDown: x, resetActive: c } = X(d), B = P(() => r === void 0 ? /* @__PURE__ */ new Set() : Array.isArray(r) ? new Set(r) : /* @__PURE__ */ new Set([r]), [r]), F = r !== void 0, s = i(
28
+ (e) => {
29
+ y || H(e), p == null || p(e);
30
+ },
31
+ [y, p]
32
+ ), t = i(() => {
33
+ s(!1), c();
34
+ }, [s, c]), D = i(
35
+ (e) => {
36
+ var o, u;
37
+ m == null || m(e), t(), (u = ((o = f.current) == null ? void 0 : o.querySelector(
38
+ 'button:not([disabled]), [href], input:not([disabled]), [tabindex]:not([tabindex="-1"])'
39
+ )) ?? f.current) == null || u.focus();
40
+ },
41
+ [m, t]
42
+ ), $ = i(() => {
43
+ a || s(!n);
44
+ }, [a, n, s]), E = i(
45
+ (e) => {
46
+ if (!a) {
47
+ if (!n && ["ArrowDown", "Enter", " "].includes(e.key)) {
48
+ e.preventDefault(), s(!0);
49
+ return;
50
+ }
51
+ if (n) {
52
+ if (e.key === "Escape") {
53
+ e.preventDefault(), t();
54
+ return;
55
+ }
56
+ if (e.key === "Tab") {
57
+ t();
58
+ return;
59
+ }
60
+ if ((e.key === "Enter" || e.key === " ") && w !== null) {
61
+ e.preventDefault();
62
+ const l = W(d).find((o) => o.id === w);
63
+ l && D(l);
64
+ return;
65
+ }
66
+ x(e);
67
+ }
68
+ }
69
+ },
70
+ [
71
+ a,
72
+ n,
73
+ s,
74
+ t,
75
+ D,
76
+ w,
77
+ x,
78
+ d
79
+ ]
80
+ ), z = i((e) => {
81
+ e.preventDefault();
82
+ }, []);
83
+ return g(() => {
84
+ if (!n) return;
85
+ function e(l) {
86
+ const o = l.target, u = f.current, M = document.getElementById(v);
87
+ u != null && u.contains(o) || M != null && M.contains(o) || t();
88
+ }
89
+ return document.addEventListener("mousedown", e), () => document.removeEventListener("mousedown", e);
90
+ }, [n, v, t]), g(() => {
91
+ n || c();
92
+ }, [n, c]), /* @__PURE__ */ C(G, { children: [
93
+ /* @__PURE__ */ I(
94
+ "span",
95
+ {
96
+ ref: f,
97
+ "aria-haspopup": "menu",
98
+ "aria-expanded": n,
99
+ "aria-controls": n ? v : void 0,
100
+ className: Q(
101
+ "inline-flex",
102
+ a && "cursor-not-allowed",
103
+ T
104
+ ),
105
+ onClick: $,
106
+ onKeyDown: E,
107
+ children: L
108
+ }
109
+ ),
110
+ /* @__PURE__ */ I(
111
+ V,
112
+ {
113
+ entries: d,
114
+ isOpen: n,
115
+ style: N,
116
+ menuRef: h,
117
+ menuClassName: R,
118
+ selectedSet: B,
119
+ selectionMode: F,
120
+ activeId: w,
121
+ menuId: v,
122
+ onSelect: D,
123
+ onHoverEnter: q,
124
+ onHoverLeave: c,
125
+ onKeyDown: E,
126
+ onMouseDown: z
127
+ }
128
+ )
129
+ ] });
130
+ };
131
+ export {
132
+ oe as Dropdown
133
+ };
@@ -0,0 +1,20 @@
1
+ import { CSSProperties, RefObject } from 'react';
2
+ import { DropdownEntry, DropdownItem } from './types';
3
+ interface DropdownMenuProps {
4
+ entries: DropdownEntry[];
5
+ isOpen: boolean;
6
+ style: CSSProperties | undefined;
7
+ menuRef: RefObject<HTMLDivElement>;
8
+ menuClassName?: string;
9
+ selectedSet: Set<string>;
10
+ selectionMode: boolean;
11
+ activeId: string | null;
12
+ menuId: string;
13
+ onSelect: (item: DropdownItem) => void;
14
+ onHoverEnter: (id: string) => void;
15
+ onHoverLeave: () => void;
16
+ onKeyDown: (e: React.KeyboardEvent) => void;
17
+ onMouseDown: (e: React.MouseEvent) => void;
18
+ }
19
+ export declare const DropdownMenu: ({ entries, isOpen, style, menuRef, menuClassName, selectedSet, selectionMode, activeId, menuId, onSelect, onHoverEnter, onHoverLeave, onKeyDown, onMouseDown, }: DropdownMenuProps) => import('react').ReactPortal;
20
+ export {};
@@ -0,0 +1,78 @@
1
+ import { jsx as r, jsxs as w } from "react/jsx-runtime";
2
+ import { createPortal as N } from "react-dom";
3
+ import { cn as $ } from "../../utils/cn.js";
4
+ import { DropdownMenuItem as m } from "./DropdownMenuItem.js";
5
+ const z = ({
6
+ entries: u,
7
+ isOpen: c,
8
+ style: n,
9
+ menuRef: v,
10
+ menuClassName: b,
11
+ selectedSet: d,
12
+ selectionMode: a,
13
+ activeId: e,
14
+ menuId: f,
15
+ onSelect: s,
16
+ onHoverEnter: p,
17
+ onHoverLeave: t,
18
+ onKeyDown: g,
19
+ onMouseDown: h
20
+ }) => {
21
+ const x = /* @__PURE__ */ r(
22
+ "div",
23
+ {
24
+ ref: v,
25
+ id: f,
26
+ role: "menu",
27
+ "aria-activedescendant": e ?? void 0,
28
+ className: $(
29
+ "z-50 rounded-lg border border-gray-v2-200 bg-white p-1 shadow-lg transition-all",
30
+ "max-h-[40vh] overflow-auto",
31
+ !c && "invisible pointer-events-none scale-95 opacity-0",
32
+ b
33
+ ),
34
+ style: n,
35
+ onKeyDown: g,
36
+ onMouseDown: h,
37
+ children: u.map((i, l) => "type" in i && i.type === "divider" ? /* @__PURE__ */ r(
38
+ "div",
39
+ {
40
+ role: "separator",
41
+ className: "my-1 border-t border-gray-v2-200"
42
+ },
43
+ `divider-${l}`
44
+ ) : "type" in i && i.type === "group" ? /* @__PURE__ */ w("div", { role: "group", children: [
45
+ /* @__PURE__ */ r("div", { className: "px-2 py-1.5 text-xs font-medium text-gray-v2-500", children: i.label }),
46
+ i.items.map((o) => /* @__PURE__ */ r(
47
+ m,
48
+ {
49
+ item: o,
50
+ isSelected: d.has(o.id),
51
+ isActive: e === o.id,
52
+ selectionMode: a,
53
+ onSelect: s,
54
+ onHoverEnter: p,
55
+ onHoverLeave: t
56
+ },
57
+ o.id
58
+ ))
59
+ ] }, `group-${i.label}-${l}`) : /* @__PURE__ */ r(
60
+ m,
61
+ {
62
+ item: i,
63
+ isSelected: d.has(i.id),
64
+ isActive: e === i.id,
65
+ selectionMode: a,
66
+ onSelect: s,
67
+ onHoverEnter: p,
68
+ onHoverLeave: t
69
+ },
70
+ i.id
71
+ ))
72
+ }
73
+ );
74
+ return N(x, document.body);
75
+ };
76
+ export {
77
+ z as DropdownMenu
78
+ };
@@ -0,0 +1,13 @@
1
+ import { DropdownItem } from './types';
2
+ interface DropdownMenuItemProps {
3
+ item: DropdownItem;
4
+ isSelected: boolean;
5
+ isActive: boolean;
6
+ /** Whether the dropdown is in selection mode (shows checkmarks). */
7
+ selectionMode: boolean;
8
+ onSelect: (item: DropdownItem) => void;
9
+ onHoverEnter: (id: string) => void;
10
+ onHoverLeave: () => void;
11
+ }
12
+ export declare const DropdownMenuItem: ({ item, isSelected, isActive, selectionMode, onSelect, onHoverEnter, onHoverLeave, }: DropdownMenuItemProps) => import("react").JSX.Element;
13
+ export {};
@@ -0,0 +1,49 @@
1
+ import { jsx as r, jsxs as a, Fragment as c } from "react/jsx-runtime";
2
+ import { Check as p } from "@untitled-ui/icons-react";
3
+ import { cn as b } from "../../utils/cn.js";
4
+ import { getDropdownItemId as f } from "./dropdown-utils.js";
5
+ const h = ({
6
+ item: e,
7
+ isSelected: n,
8
+ isActive: o,
9
+ selectionMode: l,
10
+ onSelect: s,
11
+ onHoverEnter: d,
12
+ onHoverLeave: t
13
+ }) => {
14
+ const i = e.render ? e.render() : /* @__PURE__ */ r(m, { item: e });
15
+ return /* @__PURE__ */ a(
16
+ "div",
17
+ {
18
+ role: "menuitem",
19
+ "aria-label": e.label,
20
+ "aria-disabled": e.disabled || void 0,
21
+ id: f(e.id),
22
+ className: b(
23
+ "flex items-center justify-between gap-2 rounded-md p-2 pr-2.5 text-sm font-semibold",
24
+ e.disabled ? "cursor-not-allowed opacity-50" : [
25
+ "cursor-pointer",
26
+ e.danger ? "text-error-v2-700" : "text-gray-v2-700",
27
+ n ? "bg-gray-v2-50 text-gray-v2-700" : o ? "bg-gray-v2-100" : "hover:bg-gray-v2-50"
28
+ ]
29
+ ),
30
+ onClick: () => {
31
+ e.disabled || s(e);
32
+ },
33
+ onMouseEnter: () => {
34
+ e.disabled || d(e.id);
35
+ },
36
+ onMouseLeave: t,
37
+ children: [
38
+ /* @__PURE__ */ r("div", { className: "flex min-w-0 items-center gap-2 overflow-hidden text-ellipsis", children: i }),
39
+ l ? n ? /* @__PURE__ */ r(p, { className: "h-5 w-5 min-w-5 text-brand-v2-600" }) : /* @__PURE__ */ r("div", { className: "w-5" }) : null
40
+ ]
41
+ }
42
+ );
43
+ }, m = ({ item: e }) => /* @__PURE__ */ a(c, { children: [
44
+ e.icon ? /* @__PURE__ */ r("span", { className: "flex h-5 w-5 items-center justify-center", children: e.icon }) : null,
45
+ /* @__PURE__ */ r("span", { className: "truncate", children: e.label })
46
+ ] });
47
+ export {
48
+ h as DropdownMenuItem
49
+ };
@@ -0,0 +1,5 @@
1
+ export declare const DropdownWithCallback: () => import("react").JSX.Element;
2
+ export declare const DropdownWithSelection: () => import("react").JSX.Element;
3
+ export declare const DropdownWithDisabledItem: () => import("react").JSX.Element;
4
+ export declare const DropdownWithGroups: () => import("react").JSX.Element;
5
+ export declare const DropdownDisabled: () => import("react").JSX.Element;
@@ -0,0 +1,4 @@
1
+ import { DropdownEntry, DropdownItem } from './types';
2
+ export declare function getDropdownItemId(id: string): string;
3
+ /** Flatten entries into a list of actionable (non-disabled) items. */
4
+ export declare function flattenItems(entries: DropdownEntry[]): DropdownItem[];
@@ -0,0 +1,14 @@
1
+ function i(e) {
2
+ return `dropdown-item-${e}`;
3
+ }
4
+ function o(e) {
5
+ return e.flatMap(
6
+ (t) => "type" in t && t.type === "group" ? t.items : [t]
7
+ ).filter(
8
+ (t) => !("type" in t) && !t.disabled
9
+ );
10
+ }
11
+ export {
12
+ o as flattenItems,
13
+ i as getDropdownItemId
14
+ };
@@ -0,0 +1,48 @@
1
+ import { ReactNode } from 'react';
2
+ export interface DropdownItem {
3
+ id: string;
4
+ /** Plain text label — used for accessibility and keyboard type-ahead. */
5
+ label: string;
6
+ /** Custom visual override. When provided, replaces the default icon + label rendering. */
7
+ render?: () => ReactNode;
8
+ icon?: ReactNode;
9
+ disabled?: boolean;
10
+ /** Render with destructive styling (red text). */
11
+ danger?: boolean;
12
+ }
13
+ export interface DropdownGroup {
14
+ type: "group";
15
+ label: string;
16
+ items: DropdownItem[];
17
+ }
18
+ export interface DropdownDivider {
19
+ type: "divider";
20
+ }
21
+ export type DropdownEntry = DropdownItem | DropdownGroup | DropdownDivider;
22
+ export type DropdownPlacement = "bottomLeft" | "bottomRight" | "topLeft" | "topRight";
23
+ export interface DropdownProps {
24
+ /** Menu entries: items, groups, and dividers. */
25
+ items: DropdownEntry[];
26
+ /** Called when an item is clicked. */
27
+ onSelect?: (item: DropdownItem) => void;
28
+ /** Currently selected item id(s). When provided, shows checkmarks. */
29
+ selected?: string | string[];
30
+ /** Controlled open state. */
31
+ open?: boolean;
32
+ /** Initial open state for uncontrolled mode. Default: false. */
33
+ defaultOpen?: boolean;
34
+ /** Callback when open state changes. */
35
+ onOpenChange?: (open: boolean) => void;
36
+ /** Preferred placement. Auto-flips when near viewport edge. Default: "bottomLeft". */
37
+ placement?: DropdownPlacement;
38
+ /** Sync menu width to trigger width. Default: false. */
39
+ syncWidth?: boolean;
40
+ /** The trigger element. */
41
+ children: ReactNode;
42
+ /** Additional classes on the menu panel. */
43
+ menuClassName?: string;
44
+ /** Additional classes on the trigger wrapper. */
45
+ className?: string;
46
+ /** Disable the dropdown entirely. */
47
+ disabled?: boolean;
48
+ }
@@ -0,0 +1,12 @@
1
+ import { DropdownEntry } from './types';
2
+ /**
3
+ * Manages keyboard navigation state for dropdown items.
4
+ * Only handles ArrowUp/Down/Home/End navigation — the parent is responsible
5
+ * for acting on Enter/Escape/Tab via the returned `activeId`.
6
+ */
7
+ export declare function useDropdownKeyboard(entries: DropdownEntry[]): {
8
+ activeId: string | null;
9
+ setActiveId: import('react').Dispatch<import('react').SetStateAction<string | null>>;
10
+ handleNavigationKeyDown: (e: React.KeyboardEvent) => void;
11
+ resetActive: () => void;
12
+ };
@@ -0,0 +1,49 @@
1
+ import { useState as f, useMemo as p, useCallback as l } from "react";
2
+ import { flattenItems as g, getDropdownItemId as m } from "./dropdown-utils.js";
3
+ function w(d) {
4
+ const [o, a] = f(null), e = p(() => g(d), [d]), c = l(() => o === null ? -1 : e.findIndex((t) => t.id === o), [o, e]), r = l(
5
+ (t) => {
6
+ if (e.length === 0) return;
7
+ const n = (t % e.length + e.length) % e.length;
8
+ a(e[n].id);
9
+ const s = document.getElementById(
10
+ m(e[n].id)
11
+ );
12
+ s == null || s.scrollIntoView({ block: "nearest" });
13
+ },
14
+ [e]
15
+ ), i = l(
16
+ (t) => {
17
+ if (e.length !== 0)
18
+ switch (t.key) {
19
+ case "ArrowDown": {
20
+ t.preventDefault();
21
+ const n = c();
22
+ r(n + 1);
23
+ break;
24
+ }
25
+ case "ArrowUp": {
26
+ t.preventDefault();
27
+ const n = c();
28
+ r(n === -1 ? e.length - 1 : n - 1);
29
+ break;
30
+ }
31
+ case "Home": {
32
+ t.preventDefault(), r(0);
33
+ break;
34
+ }
35
+ case "End": {
36
+ t.preventDefault(), r(e.length - 1);
37
+ break;
38
+ }
39
+ }
40
+ },
41
+ [e, c, r]
42
+ ), u = l(() => {
43
+ a(null);
44
+ }, []);
45
+ return { activeId: o, setActiveId: a, handleNavigationKeyDown: i, resetActive: u };
46
+ }
47
+ export {
48
+ w as useDropdownKeyboard
49
+ };
@@ -0,0 +1,26 @@
1
+ import { ReactNode } from 'react';
2
+ interface Props {
3
+ title: string;
4
+ supportingText?: string;
5
+ /**
6
+ * - `"illustration"`: cloud graphic with grid background (default)
7
+ * - `"featured-icon"`: icon in a bordered box with circles background
8
+ * @default "illustration"
9
+ */
10
+ type?: "featured-icon" | "illustration";
11
+ buttons?: ReactNode;
12
+ className?: string;
13
+ /** Override the default SearchLg icon for `type="featured-icon"`. */
14
+ icon?: ReactNode;
15
+ }
16
+ /**
17
+ * Generic empty state for lists, tables, and sections.
18
+ *
19
+ * @example
20
+ * ```tsx
21
+ * <EmptyState title="No results" supportingText="Try a different filter." type="featured-icon" />
22
+ * <EmptyState title="Nothing here yet" buttons={<Button>Add item</Button>} />
23
+ * ```
24
+ */
25
+ export declare const EmptyState: ({ title, supportingText, type, buttons, className, icon, }: Props) => import("react").JSX.Element;
26
+ export {};
@@ -0,0 +1,36 @@
1
+ import { jsxs as l, jsx as e } from "react/jsx-runtime";
2
+ import { SearchLg as o } from "@untitled-ui/icons-react";
3
+ import { cn as m } from "../../utils/cn.js";
4
+ import n from "../../assets/background-pattern-grid.svg.js";
5
+ import d from "../../assets/background-pattern-circles-md.svg.js";
6
+ import f from "../../assets/empty-cloud.svg.js";
7
+ const N = ({
8
+ title: s,
9
+ supportingText: r,
10
+ type: t = "illustration",
11
+ buttons: a,
12
+ className: i,
13
+ icon: c
14
+ }) => /* @__PURE__ */ l(
15
+ "div",
16
+ {
17
+ className: m(
18
+ "relative flex flex-1 flex-col items-center justify-center gap-8 overflow-hidden pb-6 pt-12",
19
+ i
20
+ ),
21
+ children: [
22
+ t === "illustration" ? /* @__PURE__ */ e(n, { className: "absolute -top-1/3 h-120 w-120" }) : /* @__PURE__ */ e(d, { className: "absolute -top-[10.55rem] h-120 w-120" }),
23
+ /* @__PURE__ */ l("div", { className: "z-10 flex flex-col items-center gap-5", children: [
24
+ t === "illustration" ? /* @__PURE__ */ e(f, { className: "h-32 w-43" }) : /* @__PURE__ */ e("div", { className: "flex h-12 w-12 items-center justify-center rounded-lg border border-gray-v2-200 bg-white shadow-xs", children: c ?? /* @__PURE__ */ e(o, { className: "h-6 w-6" }) }),
25
+ /* @__PURE__ */ l("div", { className: "flex flex-col items-center gap-2 px-3 text-center", children: [
26
+ /* @__PURE__ */ e("span", { className: "text-lg font-semibold text-gray-v2-700", children: s }),
27
+ r ? /* @__PURE__ */ e("span", { className: "text-sm text-gray-v2", children: r }) : null
28
+ ] })
29
+ ] }),
30
+ a ? /* @__PURE__ */ e("div", { className: "flex gap-3", children: a }) : null
31
+ ]
32
+ }
33
+ );
34
+ export {
35
+ N as EmptyState
36
+ };
@@ -5,5 +5,5 @@ interface Props {
5
5
  buttons?: ReactNode;
6
6
  className?: string;
7
7
  }
8
- export declare const ErrorState: ({ title, supportingText, buttons, className, }: Props) => import("react/jsx-runtime").JSX.Element;
8
+ export declare const ErrorState: ({ title, supportingText, buttons, className, }: Props) => import("react").JSX.Element;
9
9
  export {};
@@ -0,0 +1,12 @@
1
+ import { ReactNode, SVGProps } from 'react';
2
+ type FeaturedIconSize = "md" | "lg";
3
+ interface Props {
4
+ Icon: (props: SVGProps<SVGSVGElement>) => ReactNode;
5
+ size?: FeaturedIconSize;
6
+ /** Use when the surrounding background is dark, so the glass overlay stays legible. */
7
+ darkMode?: boolean;
8
+ backgroundClassName?: string;
9
+ iconClassName?: string;
10
+ }
11
+ export declare const FeaturedIcon: ({ Icon, size, darkMode, backgroundClassName, iconClassName, }: Props) => import("react").JSX.Element;
12
+ export {};
@@ -0,0 +1,44 @@
1
+ import { jsxs as a, jsx as t } from "react/jsx-runtime";
2
+ import { cn as e } from "../../utils/cn.js";
3
+ const d = {
4
+ md: "size-10 min-w-10",
5
+ lg: "size-12 min-w-12"
6
+ }, u = ({
7
+ Icon: r,
8
+ size: l = "md",
9
+ darkMode: i = !1,
10
+ backgroundClassName: o,
11
+ iconClassName: s
12
+ }) => /* @__PURE__ */ a(
13
+ "div",
14
+ {
15
+ className: e(
16
+ "relative flex items-center justify-center",
17
+ d[l]
18
+ ),
19
+ children: [
20
+ /* @__PURE__ */ t(
21
+ "div",
22
+ {
23
+ className: e(
24
+ "absolute -top-[8%] left-[4%] origin-bottom-right rotate-15 h-full w-full rounded-lg bg-brand-v2-700",
25
+ o
26
+ )
27
+ }
28
+ ),
29
+ /* @__PURE__ */ t(
30
+ "div",
31
+ {
32
+ className: e(
33
+ "h-full w-full min-w-full border rounded-lg backdrop-blur-sm",
34
+ i ? "bg-white/40 border-white/40" : "bg-white/60 border-white/60"
35
+ )
36
+ }
37
+ ),
38
+ /* @__PURE__ */ t(r, { className: e("absolute h-1/2 w-1/2 text-white", s) })
39
+ ]
40
+ }
41
+ );
42
+ export {
43
+ u as FeaturedIcon
44
+ };
@@ -0,0 +1,13 @@
1
+ import { ReactNode } from 'react';
2
+ interface Props {
3
+ label: ReactNode;
4
+ children: ReactNode;
5
+ /** id of the associated control — wires up htmlFor for accessibility */
6
+ htmlFor: string;
7
+ required?: boolean;
8
+ error?: ReactNode;
9
+ hint?: ReactNode;
10
+ className?: string;
11
+ }
12
+ export declare const FormField: ({ label, children, htmlFor, required, error, hint, className, }: Props) => import("react").JSX.Element;
13
+ export {};
@@ -0,0 +1,21 @@
1
+ import { jsxs as t, jsx as e } from "react/jsx-runtime";
2
+ import { cn as n } from "../../utils/cn.js";
3
+ const o = ({
4
+ label: a,
5
+ children: m,
6
+ htmlFor: r,
7
+ required: c,
8
+ error: l,
9
+ hint: s,
10
+ className: x
11
+ }) => /* @__PURE__ */ t("div", { className: n("flex flex-col gap-1.5 w-full", x), children: [
12
+ /* @__PURE__ */ t("label", { htmlFor: r, className: "text-sm font-medium text-gray-v2-700", children: [
13
+ a,
14
+ c && /* @__PURE__ */ e("span", { className: "ml-0.5 text-brand-v2-600", children: "*" })
15
+ ] }),
16
+ m,
17
+ l ? /* @__PURE__ */ e("p", { className: "text-sm text-error-v2-600", children: l }) : s ? /* @__PURE__ */ e("p", { className: "text-sm text-gray-v2-600", children: s }) : null
18
+ ] });
19
+ export {
20
+ o as FormField
21
+ };
@@ -0,0 +1,8 @@
1
+ import { ReactNode, SVGProps } from 'react';
2
+ interface Props {
3
+ name: string;
4
+ Icon?: (props: SVGProps<SVGSVGElement>) => ReactNode;
5
+ className?: string;
6
+ }
7
+ export declare const KeyboardShortcutLabel: ({ name, Icon, className }: Props) => import("react").JSX.Element;
8
+ export {};