@ratio-ui/core 0.1.1 → 0.3.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 (214) hide show
  1. package/README.md +2 -0
  2. package/dist/catalogue.json +2829 -72
  3. package/dist/components/alert/Alert.d.ts +18 -0
  4. package/dist/components/alert/Alert.js +67 -0
  5. package/dist/components/alert/index.d.ts +2 -0
  6. package/dist/components/alert/index.js +1 -0
  7. package/dist/components/alert-dialog/AlertDialog.d.ts +48 -0
  8. package/dist/components/alert-dialog/AlertDialog.js +76 -0
  9. package/dist/components/alert-dialog/index.d.ts +2 -0
  10. package/dist/components/alert-dialog/index.js +1 -0
  11. package/dist/components/app-shell/AppShell.d.ts +22 -0
  12. package/dist/components/app-shell/AppShell.js +39 -0
  13. package/dist/components/app-shell/context.js +5 -0
  14. package/dist/components/app-shell/index.d.ts +2 -0
  15. package/dist/components/app-shell/index.js +1 -0
  16. package/dist/components/avatar/Avatar.d.ts +22 -0
  17. package/dist/components/avatar/Avatar.js +38 -0
  18. package/dist/components/avatar/index.d.ts +2 -0
  19. package/dist/components/avatar/index.js +1 -0
  20. package/dist/components/button/Button.d.ts +37 -0
  21. package/dist/components/button/Button.js +41 -0
  22. package/dist/components/button/index.d.ts +2 -0
  23. package/dist/components/button/index.js +1 -0
  24. package/dist/components/calendar/Calendar.d.ts +20 -0
  25. package/dist/components/calendar/Calendar.js +119 -0
  26. package/dist/components/calendar/index.d.ts +2 -0
  27. package/dist/components/calendar/index.js +1 -0
  28. package/dist/components/card/Card.d.ts +33 -0
  29. package/dist/components/card/Card.js +53 -0
  30. package/dist/components/card/index.d.ts +2 -0
  31. package/dist/components/card/index.js +1 -0
  32. package/dist/components/checkbox/Checkbox.d.ts +10 -0
  33. package/dist/components/checkbox/Checkbox.js +28 -0
  34. package/dist/components/checkbox/index.d.ts +2 -0
  35. package/dist/components/checkbox/index.js +1 -0
  36. package/dist/components/checkbox-list/CheckboxList.d.ts +36 -0
  37. package/dist/components/checkbox-list/CheckboxList.js +93 -0
  38. package/dist/components/checkbox-list/index.d.ts +2 -0
  39. package/dist/components/checkbox-list/index.js +1 -0
  40. package/dist/components/collapsible/Collapsible.d.ts +24 -0
  41. package/dist/components/collapsible/Collapsible.js +58 -0
  42. package/dist/components/collapsible/index.d.ts +2 -0
  43. package/dist/components/collapsible/index.js +1 -0
  44. package/dist/components/data-table/DataTable.d.ts +65 -0
  45. package/dist/components/data-table/DataTable.js +141 -0
  46. package/dist/components/data-table/index.d.ts +2 -0
  47. package/dist/components/data-table/index.js +1 -0
  48. package/dist/components/date-picker/DatePicker.d.ts +33 -0
  49. package/dist/components/date-picker/DatePicker.js +104 -0
  50. package/dist/components/date-picker/index.d.ts +2 -0
  51. package/dist/components/date-picker/index.js +1 -0
  52. package/dist/components/date-range-picker/DateRangePicker.d.ts +39 -0
  53. package/dist/components/date-range-picker/DateRangePicker.js +142 -0
  54. package/dist/components/date-range-picker/index.d.ts +2 -0
  55. package/dist/components/date-range-picker/index.js +1 -0
  56. package/dist/components/definition/Definition.d.ts +14 -0
  57. package/dist/components/definition/Definition.js +29 -0
  58. package/dist/components/definition/index.d.ts +2 -0
  59. package/dist/components/definition/index.js +1 -0
  60. package/dist/components/dialog/Dialog.d.ts +44 -0
  61. package/dist/components/dialog/Dialog.js +79 -0
  62. package/dist/components/dialog/index.d.ts +2 -0
  63. package/dist/components/dialog/index.js +1 -0
  64. package/dist/components/dropdown-menu/DropdownMenu.d.ts +73 -0
  65. package/dist/components/dropdown-menu/DropdownMenu.js +116 -0
  66. package/dist/components/dropdown-menu/index.d.ts +2 -0
  67. package/dist/components/dropdown-menu/index.js +1 -0
  68. package/dist/components/empty-state/EmptyState.d.ts +15 -0
  69. package/dist/components/empty-state/EmptyState.js +30 -0
  70. package/dist/components/empty-state/index.d.ts +2 -0
  71. package/dist/components/empty-state/index.js +1 -0
  72. package/dist/components/field/Field.d.ts +35 -0
  73. package/dist/components/field/Field.js +67 -0
  74. package/dist/components/field/Label.d.ts +8 -0
  75. package/dist/components/field/Label.js +13 -0
  76. package/dist/components/field/index.d.ts +3 -0
  77. package/dist/components/field/index.js +3 -0
  78. package/dist/components/filter-tabs/FilterTabs.d.ts +28 -0
  79. package/dist/components/filter-tabs/FilterTabs.js +37 -0
  80. package/dist/components/filter-tabs/index.d.ts +2 -0
  81. package/dist/components/filter-tabs/index.js +1 -0
  82. package/dist/components/global-search/GlobalSearch.d.ts +51 -0
  83. package/dist/components/global-search/GlobalSearch.js +144 -0
  84. package/dist/components/global-search/index.d.ts +2 -0
  85. package/dist/components/global-search/index.js +1 -0
  86. package/dist/components/icon/registry.d.ts +3 -2
  87. package/dist/components/icon/registry.js +57 -1
  88. package/dist/components/input/Input.d.ts +19 -0
  89. package/dist/components/input/Input.js +26 -0
  90. package/dist/components/input/index.d.ts +2 -0
  91. package/dist/components/input/index.js +1 -0
  92. package/dist/components/input-group/InputGroup.d.ts +42 -0
  93. package/dist/components/input-group/InputGroup.js +83 -0
  94. package/dist/components/input-group/index.d.ts +2 -0
  95. package/dist/components/input-group/index.js +1 -0
  96. package/dist/components/kbd/Kbd.d.ts +17 -0
  97. package/dist/components/kbd/Kbd.js +21 -0
  98. package/dist/components/kbd/index.d.ts +2 -0
  99. package/dist/components/kbd/index.js +1 -0
  100. package/dist/components/link/Link.d.ts +22 -0
  101. package/dist/components/link/Link.js +31 -0
  102. package/dist/components/link/index.d.ts +2 -0
  103. package/dist/components/link/index.js +1 -0
  104. package/dist/components/link-provider/LinkProvider.d.ts +29 -0
  105. package/dist/components/link-provider/LinkProvider.js +15 -0
  106. package/dist/components/link-provider/RatioLink.js +18 -0
  107. package/dist/components/link-provider/context.js +4 -0
  108. package/dist/components/link-provider/index.d.ts +2 -0
  109. package/dist/components/link-provider/index.js +1 -0
  110. package/dist/components/media-grid/MediaGrid.d.ts +49 -0
  111. package/dist/components/media-grid/MediaGrid.js +303 -0
  112. package/dist/components/media-grid/index.d.ts +2 -0
  113. package/dist/components/media-grid/index.js +1 -0
  114. package/dist/components/metric-strip/MetricStrip.d.ts +23 -0
  115. package/dist/components/metric-strip/MetricStrip.js +39 -0
  116. package/dist/components/metric-strip/index.d.ts +2 -0
  117. package/dist/components/metric-strip/index.js +1 -0
  118. package/dist/components/money-input/MoneyInput.d.ts +30 -0
  119. package/dist/components/money-input/MoneyInput.js +72 -0
  120. package/dist/components/money-input/index.d.ts +2 -0
  121. package/dist/components/money-input/index.js +1 -0
  122. package/dist/components/page-header/PageHeader.d.ts +37 -0
  123. package/dist/components/page-header/PageHeader.js +62 -0
  124. package/dist/components/page-header/index.d.ts +2 -0
  125. package/dist/components/page-header/index.js +1 -0
  126. package/dist/components/pagination/Pagination.d.ts +18 -0
  127. package/dist/components/pagination/Pagination.js +59 -0
  128. package/dist/components/pagination/index.d.ts +2 -0
  129. package/dist/components/pagination/index.js +1 -0
  130. package/dist/components/popover/Popover.d.ts +27 -0
  131. package/dist/components/popover/Popover.js +47 -0
  132. package/dist/components/popover/index.d.ts +2 -0
  133. package/dist/components/popover/index.js +1 -0
  134. package/dist/components/save-bar/SaveBar.d.ts +27 -0
  135. package/dist/components/save-bar/SaveBar.js +37 -0
  136. package/dist/components/save-bar/index.d.ts +2 -0
  137. package/dist/components/save-bar/index.js +1 -0
  138. package/dist/components/search-field/SearchField.d.ts +23 -0
  139. package/dist/components/search-field/SearchField.js +66 -0
  140. package/dist/components/search-field/index.d.ts +2 -0
  141. package/dist/components/search-field/index.js +1 -0
  142. package/dist/components/select/Select.d.ts +40 -0
  143. package/dist/components/select/Select.js +84 -0
  144. package/dist/components/select/index.d.ts +2 -0
  145. package/dist/components/select/index.js +1 -0
  146. package/dist/components/side-nav/SideNav.d.ts +64 -0
  147. package/dist/components/side-nav/SideNav.js +194 -0
  148. package/dist/components/side-nav/index.d.ts +2 -0
  149. package/dist/components/side-nav/index.js +1 -0
  150. package/dist/components/skeleton/Skeleton.d.ts +13 -0
  151. package/dist/components/skeleton/Skeleton.js +21 -0
  152. package/dist/components/skeleton/index.d.ts +2 -0
  153. package/dist/components/skeleton/index.js +1 -0
  154. package/dist/components/spinner/Spinner.d.ts +11 -0
  155. package/dist/components/spinner/Spinner.js +16 -0
  156. package/dist/components/spinner/index.d.ts +2 -0
  157. package/dist/components/spinner/index.js +1 -0
  158. package/dist/components/status-pill/StatusPill.d.ts +14 -0
  159. package/dist/components/status-pill/StatusPill.js +19 -0
  160. package/dist/components/status-pill/index.d.ts +2 -0
  161. package/dist/components/status-pill/index.js +1 -0
  162. package/dist/components/summary-chips/SummaryChips.d.ts +17 -0
  163. package/dist/components/summary-chips/SummaryChips.js +19 -0
  164. package/dist/components/summary-chips/index.d.ts +2 -0
  165. package/dist/components/summary-chips/index.js +1 -0
  166. package/dist/components/switch/Switch.d.ts +10 -0
  167. package/dist/components/switch/Switch.js +20 -0
  168. package/dist/components/switch/index.d.ts +2 -0
  169. package/dist/components/switch/index.js +1 -0
  170. package/dist/components/table/Table.d.ts +46 -0
  171. package/dist/components/table/Table.js +87 -0
  172. package/dist/components/table/index.d.ts +2 -0
  173. package/dist/components/table/index.js +1 -0
  174. package/dist/components/table-loader/TableLoader.d.ts +31 -0
  175. package/dist/components/table-loader/TableLoader.js +35 -0
  176. package/dist/components/table-loader/index.d.ts +2 -0
  177. package/dist/components/table-loader/index.js +1 -0
  178. package/dist/components/tabs/Tabs.d.ts +23 -0
  179. package/dist/components/tabs/Tabs.js +41 -0
  180. package/dist/components/tabs/index.d.ts +2 -0
  181. package/dist/components/tabs/index.js +1 -0
  182. package/dist/components/tag-input/TagInput.d.ts +44 -0
  183. package/dist/components/tag-input/TagInput.js +102 -0
  184. package/dist/components/tag-input/index.d.ts +2 -0
  185. package/dist/components/tag-input/index.js +1 -0
  186. package/dist/components/textarea/Textarea.d.ts +15 -0
  187. package/dist/components/textarea/Textarea.js +21 -0
  188. package/dist/components/textarea/index.d.ts +2 -0
  189. package/dist/components/textarea/index.js +1 -0
  190. package/dist/components/toaster/Toaster.d.ts +32 -0
  191. package/dist/components/toaster/Toaster.js +89 -0
  192. package/dist/components/toaster/index.d.ts +2 -0
  193. package/dist/components/toaster/index.js +1 -0
  194. package/dist/components/tooltip/Tooltip.d.ts +18 -0
  195. package/dist/components/tooltip/Tooltip.js +35 -0
  196. package/dist/components/tooltip/index.d.ts +2 -0
  197. package/dist/components/tooltip/index.js +1 -0
  198. package/dist/components/top-bar/StoreSwitcher.d.ts +26 -0
  199. package/dist/components/top-bar/StoreSwitcher.js +48 -0
  200. package/dist/components/top-bar/TopBar.d.ts +24 -0
  201. package/dist/components/top-bar/TopBar.js +53 -0
  202. package/dist/components/top-bar/index.d.ts +3 -0
  203. package/dist/components/top-bar/index.js +3 -0
  204. package/dist/components/unit-input/UnitInput.d.ts +33 -0
  205. package/dist/components/unit-input/UnitInput.js +47 -0
  206. package/dist/components/unit-input/index.d.ts +2 -0
  207. package/dist/components/unit-input/index.js +1 -0
  208. package/dist/index.d.ts +102 -1
  209. package/dist/index.js +54 -2
  210. package/dist/lib/cn.js +38 -27
  211. package/dist/lib/format.d.ts +92 -0
  212. package/dist/lib/format.js +222 -0
  213. package/dist/styles.css +1 -1
  214. package/package.json +205 -3
@@ -0,0 +1,194 @@
1
+ import { cn } from "../../lib/cn.js";
2
+ import { Icon } from "../icon/Icon.js";
3
+ import { ShellNavContext } from "../app-shell/context.js";
4
+ import { Avatar } from "../avatar/Avatar.js";
5
+ import { RatioLink } from "../link-provider/RatioLink.js";
6
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
7
+ import { use, useState, useSyncExternalStore } from "react";
8
+ import { Dialog } from "@base-ui/react/dialog";
9
+ // src/components/side-nav/SideNav.tsx
10
+ const PHONE_QUERY = "(max-width: 767px)";
11
+ function subscribe(notify) {
12
+ const mq = window.matchMedia(PHONE_QUERY);
13
+ mq.addEventListener("change", notify);
14
+ return () => mq.removeEventListener("change", notify);
15
+ }
16
+ function useIsPhone() {
17
+ return useSyncExternalStore(subscribe, () => window.matchMedia(PHONE_QUERY).matches, () => false);
18
+ }
19
+ const ROW = "rt:flex rt:h-sidenav-row rt:w-full rt:items-center rt:gap-2 rt:rounded-md rt:text-left rt:text-b3 rt:text-foreground rt:transition-colors rt:hover:bg-muted rt:focus-visible:focus-ring";
20
+ function containsActive(item, active) {
21
+ return item.children?.some((c) => c.id === active || containsActive(c, active)) ?? false;
22
+ }
23
+ function Row({ item, active, depth, onSelect }) {
24
+ const isActive = item.id === active;
25
+ const [toggled, setToggled] = useState(null);
26
+ const children = item.children ?? [];
27
+ const hasChildren = children.length > 0;
28
+ const open = toggled && toggled.forActive === active ? toggled.open : containsActive(item, active);
29
+ const cls = cn(ROW, depth > 0 && "rt:pl-8", isActive && "rt:bg-muted rt:text-primary rt:font-medium");
30
+ const inner = /* @__PURE__ */ jsxs(Fragment, { children: [
31
+ item.icon && /* @__PURE__ */ jsx(Icon, {
32
+ name: item.icon,
33
+ size: 16,
34
+ tone: isActive ? "primary" : "icon"
35
+ }),
36
+ /* @__PURE__ */ jsx("span", {
37
+ className: "rt:min-w-0 rt:flex-1 rt:truncate",
38
+ children: item.label
39
+ }),
40
+ item.count !== void 0 && /* @__PURE__ */ jsx("span", {
41
+ className: "rt:text-c1 rt:text-foreground-subdued",
42
+ children: item.count
43
+ }),
44
+ hasChildren && /* @__PURE__ */ jsx(Icon, {
45
+ name: "nav-chevron",
46
+ size: 8,
47
+ tone: "icon"
48
+ })
49
+ ] });
50
+ return /* @__PURE__ */ jsxs("li", { children: [hasChildren ? /* @__PURE__ */ jsx("button", {
51
+ type: "button",
52
+ className: cls,
53
+ "aria-expanded": open,
54
+ onClick: () => setToggled({
55
+ open: !open,
56
+ forActive: active
57
+ }),
58
+ children: inner
59
+ }) : item.href ? /* @__PURE__ */ jsx(RatioLink, {
60
+ href: item.href,
61
+ className: cls,
62
+ "aria-current": isActive ? "page" : void 0,
63
+ onClick: () => onSelect?.(item.id),
64
+ children: inner
65
+ }) : /* @__PURE__ */ jsx("button", {
66
+ type: "button",
67
+ className: cls,
68
+ "aria-current": isActive ? "page" : void 0,
69
+ onClick: () => onSelect?.(item.id),
70
+ children: inner
71
+ }), hasChildren && open && /* @__PURE__ */ jsx("ul", {
72
+ className: "rt:flex rt:flex-col",
73
+ children: children.map((c) => /* @__PURE__ */ jsx(Row, {
74
+ item: c,
75
+ active,
76
+ depth: depth + 1,
77
+ onSelect
78
+ }, c.id))
79
+ })] });
80
+ }
81
+ function Section({ section, active, onSelect }) {
82
+ const [collapsed, setCollapsed] = useState(!!section.defaultCollapsed);
83
+ const collapsible = !!section.collapsible && !!section.label;
84
+ return /* @__PURE__ */ jsxs("div", {
85
+ className: "rt:flex rt:flex-col",
86
+ children: [section.label && (collapsible ? /* @__PURE__ */ jsxs("button", {
87
+ type: "button",
88
+ "aria-expanded": !collapsed,
89
+ onClick: () => setCollapsed((c) => !c),
90
+ className: "rt:flex rt:h-sidenav-label rt:items-center rt:justify-between rt:text-c1 rt:text-foreground-subdued rt:focus-visible:focus-ring",
91
+ children: [section.label, /* @__PURE__ */ jsx(Icon, {
92
+ name: "nav-chevron",
93
+ size: 8,
94
+ tone: "icon"
95
+ })]
96
+ }) : /* @__PURE__ */ jsx("span", {
97
+ className: "rt:flex rt:h-sidenav-label rt:items-center rt:text-c1 rt:text-foreground-subdued",
98
+ children: section.label
99
+ })), !(collapsible && collapsed) && /* @__PURE__ */ jsx("ul", {
100
+ className: "rt:flex rt:flex-col",
101
+ children: section.items.map((item) => /* @__PURE__ */ jsx(Row, {
102
+ item,
103
+ active,
104
+ depth: 0,
105
+ onSelect
106
+ }, item.id))
107
+ })]
108
+ });
109
+ }
110
+ function Panel({ label, sections, active, onSelect, account, footer }) {
111
+ return /* @__PURE__ */ jsxs("div", {
112
+ "data-slot": "side-nav",
113
+ className: "rt:flex rt:h-full rt:w-60 rt:shrink-0 rt:flex-col rt:bg-sidebar rt:text-sidebar-foreground",
114
+ children: [
115
+ account && /* @__PURE__ */ jsx("div", {
116
+ className: "rt:flex rt:shrink-0 rt:items-start rt:px-3.5 rt:pt-2",
117
+ children: /* @__PURE__ */ jsxs("button", {
118
+ type: "button",
119
+ onClick: account.onClick,
120
+ className: "rt:flex rt:h-11 rt:w-full rt:items-center rt:gap-2 rt:rounded-lg rt:px-1.5 rt:text-left rt:hover:bg-muted rt:focus-visible:focus-ring",
121
+ children: [
122
+ /* @__PURE__ */ jsx(Avatar, {
123
+ name: account.name,
124
+ shape: "square",
125
+ size: "sm"
126
+ }),
127
+ /* @__PURE__ */ jsxs("span", {
128
+ className: "rt:flex rt:min-w-0 rt:flex-1 rt:flex-col rt:text-c1",
129
+ children: [/* @__PURE__ */ jsx("span", {
130
+ className: "rt:truncate rt:text-c2",
131
+ children: account.name
132
+ }), account.role && /* @__PURE__ */ jsx("span", {
133
+ className: "rt:truncate",
134
+ children: account.role
135
+ })]
136
+ }),
137
+ /* @__PURE__ */ jsx(Icon, {
138
+ name: "nav-caret-down",
139
+ size: 8,
140
+ tone: "icon"
141
+ })
142
+ ]
143
+ })
144
+ }),
145
+ /* @__PURE__ */ jsx("nav", {
146
+ "aria-label": label,
147
+ className: "rt:flex rt:min-h-0 rt:flex-1 rt:flex-col rt:sidenav-gap rt:overflow-y-auto rt:sidenav-pad-x rt:sidenav-pad-top rt:sidenav-pad-bottom",
148
+ children: sections.map((s) => /* @__PURE__ */ jsx(Section, {
149
+ section: s,
150
+ active,
151
+ onSelect
152
+ }, s.id))
153
+ }),
154
+ footer && /* @__PURE__ */ jsx("div", {
155
+ "data-slot": "side-nav-footer",
156
+ className: "rt:flex rt:shrink-0 rt:items-center rt:gap-2 rt:border-t rt:border-divider rt:px-6 rt:py-3 rt:text-b3",
157
+ children: footer
158
+ })
159
+ ]
160
+ });
161
+ }
162
+ /**
163
+ * The 240px side navigation of the admin: an account switcher, blocks of rows with nested groups, counts and collapsible
164
+ * labels, and a footer pinned at the bottom. On a phone it becomes a drawer: inside AppShell the menu button in TopBar opens it and choosing a row closes it; used alone, the caller opens it with `open` and closes it in `onOpenChange`.
165
+ */
166
+ function SideNav(props) {
167
+ const phone = useIsPhone();
168
+ const shell = use(ShellNavContext);
169
+ if (!phone) return /* @__PURE__ */ jsx(Panel, { ...props });
170
+ const open = props.open ?? shell?.open ?? false;
171
+ const onOpenChange = (next) => {
172
+ props.onOpenChange?.(next);
173
+ shell?.setOpen(next);
174
+ };
175
+ const onSelect = (id) => {
176
+ props.onSelect?.(id);
177
+ shell?.setOpen(false);
178
+ };
179
+ return /* @__PURE__ */ jsx(Dialog.Root, {
180
+ open,
181
+ onOpenChange,
182
+ children: /* @__PURE__ */ jsx(Dialog.Portal, { children: /* @__PURE__ */ jsx(Dialog.Popup, {
183
+ id: shell?.id,
184
+ "aria-label": props.label,
185
+ "data-slot": "side-nav-drawer",
186
+ className: "rt:fixed rt:inset-y-0 rt:left-0 rt:z-50 rt:h-full rt:shadow-ring-strong rt:focus-visible:focus-ring",
187
+ children: /* @__PURE__ */ jsx(Panel, {
188
+ ...props,
189
+ onSelect
190
+ })
191
+ }) })
192
+ });
193
+ }
194
+ export { SideNav };
@@ -0,0 +1,2 @@
1
+ import { SideNav, SideNavAccount, SideNavItem, SideNavProps, SideNavSection } from "./SideNav.js";
2
+ export { SideNav, type SideNavAccount, type SideNavItem, type SideNavProps, type SideNavSection };
@@ -0,0 +1 @@
1
+ export { SideNav } from "./SideNav.js";
@@ -0,0 +1,13 @@
1
+ import { HTMLAttributes, JSX } from "react";
2
+ /** The shape of a placeholder: a line of text, a block such as a tile or an image, or a round avatar. */
3
+ export type SkeletonShape = 'line' | 'block' | 'circle';
4
+ /** The props of Skeleton: the HTML attributes of its div, except className, style and children, with the shape. */
5
+ export type SkeletonProps = Omit<HTMLAttributes<HTMLDivElement>, 'className' | 'style' | 'children'> & {
6
+ /** The shape of the placeholder. Defaults to line. A line and a block fill the width of their parent. */
7
+ shape?: SkeletonShape;
8
+ };
9
+ /**
10
+ * A static placeholder for content that is still loading on a first load. It is hidden from assistive technology: the
11
+ * container that holds it says it is busy. Its fill and animation come from the loading tokens, so it does not move.
12
+ */
13
+ export declare function Skeleton({ shape, ...rest }: SkeletonProps): JSX.Element;
@@ -0,0 +1,21 @@
1
+ import { cn } from "../../lib/cn.js";
2
+ import { jsx } from "react/jsx-runtime";
3
+ // src/components/skeleton/Skeleton.tsx
4
+ const SHAPE_CLASSES = {
5
+ line: "rt:h-4 rt:w-full rt:rounded-sm",
6
+ block: "rt:h-24 rt:w-full rt:rounded-sm",
7
+ circle: "rt:size-8 rt:rounded-3xl"
8
+ };
9
+ /**
10
+ * A static placeholder for content that is still loading on a first load. It is hidden from assistive technology: the
11
+ * container that holds it says it is busy. Its fill and animation come from the loading tokens, so it does not move.
12
+ */
13
+ function Skeleton({ shape = "line", ...rest }) {
14
+ return /* @__PURE__ */ jsx("div", {
15
+ "data-slot": "skeleton",
16
+ "aria-hidden": "true",
17
+ ...rest,
18
+ className: cn("rt:skeleton", SHAPE_CLASSES[shape])
19
+ });
20
+ }
21
+ export { Skeleton };
@@ -0,0 +1,2 @@
1
+ import { Skeleton, SkeletonProps, SkeletonShape } from "./Skeleton.js";
2
+ export { Skeleton, type SkeletonProps, type SkeletonShape };
@@ -0,0 +1 @@
1
+ export { Skeleton } from "./Skeleton.js";
@@ -0,0 +1,11 @@
1
+ import { HTMLAttributes, JSX } from "react";
2
+ /** The props of Spinner: the HTML attributes of its span, except className, style and children, with the label. */
3
+ export type SpinnerProps = Omit<HTMLAttributes<HTMLSpanElement>, 'className' | 'style' | 'children'> & {
4
+ /** The accessible name, announced to assistive technology. Defaults to Loading. */
5
+ label?: string;
6
+ };
7
+ /**
8
+ * A small ring for a wait with no known shape. It is static until the designer answers question 5: its motion is the
9
+ * --rt-spinner-animation token, none for now, so the ring is drawn from the progress colours and the status role says what it means.
10
+ */
11
+ export declare function Spinner({ label, ...rest }: SpinnerProps): JSX.Element;
@@ -0,0 +1,16 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ // src/components/spinner/Spinner.tsx
3
+ /**
4
+ * A small ring for a wait with no known shape. It is static until the designer answers question 5: its motion is the
5
+ * --rt-spinner-animation token, none for now, so the ring is drawn from the progress colours and the status role says what it means.
6
+ */
7
+ function Spinner({ label = "Loading", ...rest }) {
8
+ return /* @__PURE__ */ jsx("span", {
9
+ "data-slot": "spinner",
10
+ role: "status",
11
+ "aria-label": label,
12
+ ...rest,
13
+ className: "rt:inline-block rt:size-4 rt:rounded-3xl rt:border-2 rt:border-progress-track rt:border-t-progress rt:spinner-motion"
14
+ });
15
+ }
16
+ export { Spinner };
@@ -0,0 +1,2 @@
1
+ import { Spinner, SpinnerProps } from "./Spinner.js";
2
+ export { Spinner, type SpinnerProps };
@@ -0,0 +1 @@
1
+ export { Spinner } from "./Spinner.js";
@@ -0,0 +1,14 @@
1
+ import { HTMLAttributes, JSX, Ref } from "react";
2
+ /** The tone of a status pill: success is green, warning is amber, neutral is plain text until the designer answers question 3. */
3
+ export type StatusPillTone = 'success' | 'warning' | 'neutral';
4
+ /** The props of StatusPill: the HTML attributes of a span, except className and style, with the tone. */
5
+ export type StatusPillProps = Omit<HTMLAttributes<HTMLSpanElement>, 'className' | 'style'> & {
6
+ /** The colour of the pill. Defaults to neutral. */
7
+ tone?: StatusPillTone;
8
+ /** The status, one word: Draft, Active, Hidden, Low, Pending. */
9
+ children: React.ReactNode;
10
+ /** Receives the rendered span. */
11
+ ref?: Ref<HTMLSpanElement>;
12
+ };
13
+ /** A 20px pill with a 4px radius and a 1px border that names the state of a row, such as a product's status in a listing. */
14
+ export declare function StatusPill({ tone, children, ref, ...rest }: StatusPillProps): JSX.Element;
@@ -0,0 +1,19 @@
1
+ import { cn } from "../../lib/cn.js";
2
+ import { jsx } from "react/jsx-runtime";
3
+ // src/components/status-pill/StatusPill.tsx
4
+ const TONE_CLASSES = {
5
+ success: "rt:bg-success-tint rt:text-success rt:border-success-border",
6
+ warning: "rt:bg-warning-tint rt:text-warning rt:border-warning-border",
7
+ neutral: "rt:bg-status-neutral-background rt:text-status-neutral-foreground rt:border-status-neutral-border"
8
+ };
9
+ /** A 20px pill with a 4px radius and a 1px border that names the state of a row, such as a product's status in a listing. */
10
+ function StatusPill({ tone = "neutral", children, ref, ...rest }) {
11
+ return /* @__PURE__ */ jsx("span", {
12
+ ...rest,
13
+ ref,
14
+ "data-tone": tone,
15
+ className: cn("rt:inline-flex rt:h-5 rt:w-fit rt:shrink-0 rt:items-center rt:justify-center rt:rounded-sm rt:border rt:px-2 rt:text-c2 rt:whitespace-nowrap", TONE_CLASSES[tone]),
16
+ children
17
+ });
18
+ }
19
+ export { StatusPill };
@@ -0,0 +1,2 @@
1
+ import { StatusPill, StatusPillProps, StatusPillTone } from "./StatusPill.js";
2
+ export { StatusPill, type StatusPillProps, type StatusPillTone };
@@ -0,0 +1 @@
1
+ export { StatusPill } from "./StatusPill.js";
@@ -0,0 +1,17 @@
1
+ import { HTMLAttributes, JSX, Ref } from "react";
2
+ /** One chip: a label, with an optional value after it ("Includes GST" and "Yes"). */
3
+ export interface SummaryChip {
4
+ /** The label, such as Cost price or HSN code. */
5
+ label: string;
6
+ /** The value, shown after the label in the foreground ink. Leave out for a chip that is only a name. */
7
+ value?: string;
8
+ }
9
+ /** The props of SummaryChips: the HTML attributes of a list, except className and style, with the chips. */
10
+ export type SummaryChipsProps = Omit<HTMLAttributes<HTMLUListElement>, 'className' | 'style' | 'children'> & {
11
+ /** The chips, in order. Nothing is rendered when empty. */
12
+ items: readonly SummaryChip[];
13
+ /** Receives the rendered list. */
14
+ ref?: Ref<HTMLUListElement>;
15
+ };
16
+ /** A row of 20px chips that summarise values, such as the ones a collapsed section still shows. */
17
+ export declare function SummaryChips({ items, ref, ...rest }: SummaryChipsProps): JSX.Element | null;
@@ -0,0 +1,19 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ // src/components/summary-chips/SummaryChips.tsx
3
+ /** A row of 20px chips that summarise values, such as the ones a collapsed section still shows. */
4
+ function SummaryChips({ items, ref, ...rest }) {
5
+ if (items.length === 0) return null;
6
+ return /* @__PURE__ */ jsx("ul", {
7
+ ...rest,
8
+ ref,
9
+ className: "rt:m-0 rt:flex rt:list-none rt:flex-wrap rt:gap-1 rt:p-0",
10
+ children: items.map((item) => /* @__PURE__ */ jsxs("li", {
11
+ className: "rt:inline-flex rt:h-5 rt:items-center rt:gap-1 rt:rounded-sm rt:border rt:border-status-neutral-border rt:bg-status-neutral-background rt:px-2 rt:text-c1 rt:whitespace-nowrap rt:text-status-neutral-foreground",
12
+ children: [/* @__PURE__ */ jsx("span", { children: item.label }), item.value !== void 0 ? /* @__PURE__ */ jsx("span", {
13
+ className: "rt:text-c2 rt:text-foreground",
14
+ children: item.value
15
+ }) : null]
16
+ }, item.label))
17
+ });
18
+ }
19
+ export { SummaryChips };
@@ -0,0 +1,2 @@
1
+ import { SummaryChip, SummaryChips, SummaryChipsProps } from "./SummaryChips.js";
2
+ export { type SummaryChip, SummaryChips, type SummaryChipsProps };
@@ -0,0 +1 @@
1
+ export { SummaryChips } from "./SummaryChips.js";
@@ -0,0 +1,10 @@
1
+ import { JSX } from "react";
2
+ import { Switch } from "@base-ui/react/switch";
3
+ /** The props of Switch: Base UI's switch props, except className, style and render. Give it an aria-label or a label that points to it. */
4
+ export type SwitchProps = Omit<Switch.Root.Props, 'className' | 'style' | 'render'>;
5
+ /**
6
+ * An on/off switch, 32px by 18px. Off it is drawn with the control hairline; on it is filled in the primary colour.
7
+ * In forced-colours mode the thumb keeps a system-colour outline, and its side shows the state. The thumb jumps to the other end with no slide, and colours fade over 120ms.
8
+ */
9
+ declare function Switch$1({ ...props }: SwitchProps): JSX.Element;
10
+ export { Switch$1 as Switch };
@@ -0,0 +1,20 @@
1
+ import { cn } from "../../lib/cn.js";
2
+ import { jsx } from "react/jsx-runtime";
3
+ import { Switch } from "@base-ui/react/switch";
4
+ // src/components/switch/Switch.tsx
5
+ /**
6
+ * An on/off switch, 32px by 18px. Off it is drawn with the control hairline; on it is filled in the primary colour.
7
+ * In forced-colours mode the thumb keeps a system-colour outline, and its side shows the state. The thumb jumps to the other end with no slide, and colours fade over 120ms.
8
+ */
9
+ function Switch$1({ ...props }) {
10
+ return /* @__PURE__ */ jsx(Switch.Root, {
11
+ "data-slot": "switch",
12
+ className: cn("rt:peer rt:relative rt:inline-flex rt:h-4.5 rt:w-8 rt:shrink-0 rt:cursor-pointer rt:items-center rt:justify-start rt:rounded-3xl rt:bg-background rt:shadow-ring-hairline rt:transition-colors rt:outline-none", "rt:after:absolute rt:after:-inset-x-1.5 rt:after:-inset-y-1.5", "rt:data-checked:justify-end rt:data-checked:bg-primary rt:data-checked:shadow-none", "rt:focus-visible:focus-ring rt:forced-outline", "rt:aria-invalid:shadow-ring-invalid rt:aria-invalid:focus-visible:shadow-ring-invalid", "rt:data-disabled:cursor-not-allowed rt:data-disabled:opacity-50"),
13
+ ...props,
14
+ children: /* @__PURE__ */ jsx(Switch.Thumb, {
15
+ "data-slot": "switch-thumb",
16
+ className: "rt:pointer-events-none rt:mx-0.5 rt:block rt:size-3.5 rt:rounded-3xl rt:forced-outline rt:bg-control rt:transition-colors rt:data-checked:bg-primary-foreground"
17
+ })
18
+ });
19
+ }
20
+ export { Switch$1 as Switch };
@@ -0,0 +1,2 @@
1
+ import { Switch, SwitchProps } from "./Switch.js";
2
+ export { Switch, type SwitchProps };
@@ -0,0 +1 @@
1
+ export { Switch } from "./Switch.js";
@@ -0,0 +1,46 @@
1
+ import { ComponentProps, JSX, ReactNode } from "react";
2
+ /** The props of Table: the attributes of a table element, except className and style. */
3
+ export type TableProps = Omit<ComponentProps<'table'>, 'className' | 'style'>;
4
+ /**
5
+ * A data table in the design system's Listing look: a 36px heading row over 48px rows split by 1px hairlines, 12px uppercase headings and a fill
6
+ * on the row under the pointer. It scrolls sideways inside its own box when the columns do not fit. Compose it from
7
+ * TableHeader, TableBody, TableRow, TableHead and TableCell.
8
+ */
9
+ export declare function Table(props: TableProps): JSX.Element;
10
+ /** The props of TableHeader: the attributes of a thead element, except className and style. */
11
+ export type TableHeaderProps = Omit<ComponentProps<'thead'>, 'className' | 'style'>;
12
+ /** The heading rows of a table. Its rows take no hover fill. */
13
+ export declare function TableHeader(props: TableHeaderProps): JSX.Element;
14
+ /** The props of TableBody: the attributes of a tbody element, except className and style. */
15
+ export type TableBodyProps = Omit<ComponentProps<'tbody'>, 'className' | 'style'>;
16
+ /** The data rows of a table. Its rows take the hover fill. */
17
+ export declare function TableBody(props: TableBodyProps): JSX.Element;
18
+ /** The props of TableFooter: the attributes of a tfoot element, except className and style. */
19
+ export type TableFooterProps = Omit<ComponentProps<'tfoot'>, 'className' | 'style'>;
20
+ /** The summary rows at the foot of a table, such as totals. Its rows take no hover fill. */
21
+ export declare function TableFooter(props: TableFooterProps): JSX.Element;
22
+ /** The props of TableRow: the attributes of a tr element, except className and style, and whether the row is selected. */
23
+ export type TableRowProps = Omit<ComponentProps<'tr'>, 'className' | 'style'> & {
24
+ /** Keeps the hover fill on the row to show it is chosen, for example when its checkbox is ticked. Defaults to false. */
25
+ selected?: boolean;
26
+ };
27
+ /** One row, 48px high (36px in the heading), with a hairline under it. A body row is filled when the pointer is over it or it is selected. */
28
+ export declare function TableRow({ selected, ...rest }: TableRowProps): JSX.Element;
29
+ /** The props of TableHead: the attributes of a th element, except className and style, and the alignment of its column. */
30
+ export type TableHeadProps = Omit<ComponentProps<'th'>, 'className' | 'style'> & {
31
+ /** Aligns the heading to the right, over a column of numbers. Defaults to false, which aligns it to the left. */
32
+ numeric?: boolean;
33
+ };
34
+ /** A column heading: 12px uppercase text in the subdued colour. It is a column header unless `scope` says otherwise. */
35
+ export declare function TableHead({ numeric, scope, ...rest }: TableHeadProps): JSX.Element;
36
+ /** The props of TableCell: the attributes of a td element, except className and style, and the alignment of its column. */
37
+ export type TableCellProps = Omit<ComponentProps<'td'>, 'className' | 'style'> & {
38
+ /** Aligns the cell to the right with tabular figures, for a number. Defaults to false, which aligns it to the left. */
39
+ numeric?: boolean;
40
+ };
41
+ /** One cell. Text stays on one line; a numeric cell is right aligned with tabular figures so digits line up. */
42
+ export declare function TableCell({ numeric, ...rest }: TableCellProps): JSX.Element;
43
+ /** The props of TableCaption: the attributes of a caption element, except className and style. */
44
+ export type TableCaptionProps = Omit<ComponentProps<'caption'>, 'className' | 'style'>;
45
+ /** The table's title for assistive technology, shown under the table in the subdued colour. */
46
+ export declare function TableCaption(props: TableCaptionProps): JSX.Element;
@@ -0,0 +1,87 @@
1
+ import { cn } from "../../lib/cn.js";
2
+ import { jsx } from "react/jsx-runtime";
3
+ import { createContext, use } from "react";
4
+ // src/components/table/Table.tsx
5
+ const SectionContext = createContext("body");
6
+ const BoxContext = createContext(false);
7
+ /** Draws the hairline box (1px border, 8px corners) round the Table inside it. For DataTable and TableLoader; not exported from the package. */
8
+ function TableBox({ children }) {
9
+ return /* @__PURE__ */ jsx(BoxContext, {
10
+ value: true,
11
+ children
12
+ });
13
+ }
14
+ /**
15
+ * A data table in the design system's Listing look: a 36px heading row over 48px rows split by 1px hairlines, 12px uppercase headings and a fill
16
+ * on the row under the pointer. It scrolls sideways inside its own box when the columns do not fit. Compose it from
17
+ * TableHeader, TableBody, TableRow, TableHead and TableCell.
18
+ */
19
+ function Table(props) {
20
+ const boxed = use(BoxContext);
21
+ return /* @__PURE__ */ jsx("div", {
22
+ role: "region",
23
+ tabIndex: 0,
24
+ "aria-label": props["aria-label"],
25
+ "aria-labelledby": props["aria-labelledby"],
26
+ "data-boxed": boxed ? "true" : void 0,
27
+ className: cn("rt:relative rt:w-full rt:overflow-x-auto rt:focus-visible:focus-ring", boxed && "rt:rounded-lg rt:border rt:border-border"),
28
+ children: /* @__PURE__ */ jsx("table", {
29
+ className: "rt:w-full rt:border-collapse rt:caption-bottom rt:bg-background rt:text-b3 rt:text-foreground",
30
+ ...props
31
+ })
32
+ });
33
+ }
34
+ /** The heading rows of a table. Its rows take no hover fill. */
35
+ function TableHeader(props) {
36
+ return /* @__PURE__ */ jsx(SectionContext, {
37
+ value: "head",
38
+ children: /* @__PURE__ */ jsx("thead", { ...props })
39
+ });
40
+ }
41
+ /** The data rows of a table. Its rows take the hover fill. */
42
+ function TableBody(props) {
43
+ return /* @__PURE__ */ jsx(SectionContext, {
44
+ value: "body",
45
+ children: /* @__PURE__ */ jsx("tbody", { ...props })
46
+ });
47
+ }
48
+ /** The summary rows at the foot of a table, such as totals. Its rows take no hover fill. */
49
+ function TableFooter(props) {
50
+ return /* @__PURE__ */ jsx(SectionContext, {
51
+ value: "foot",
52
+ children: /* @__PURE__ */ jsx("tfoot", { ...props })
53
+ });
54
+ }
55
+ /** One row, 48px high (36px in the heading), with a hairline under it. A body row is filled when the pointer is over it or it is selected. */
56
+ function TableRow({ selected = false, ...rest }) {
57
+ const section = use(SectionContext);
58
+ const boxed = use(BoxContext);
59
+ return /* @__PURE__ */ jsx("tr", {
60
+ "data-selected": selected ? "true" : void 0,
61
+ className: cn("rt:border-b rt:border-border rt:transition-colors", section === "head" ? "rt:h-9" : "rt:h-12", boxed && section === "body" && "rt:last:border-b-0", section === "body" && "rt:hover:bg-muted rt:data-selected:bg-muted"),
62
+ ...rest
63
+ });
64
+ }
65
+ /** A column heading: 12px uppercase text in the subdued colour. It is a column header unless `scope` says otherwise. */
66
+ function TableHead({ numeric = false, scope = "col", ...rest }) {
67
+ return /* @__PURE__ */ jsx("th", {
68
+ scope,
69
+ className: cn("rt:px-2 rt:align-middle rt:text-label rt:uppercase rt:whitespace-nowrap rt:text-foreground-subdued", numeric ? "rt:text-right" : "rt:text-left"),
70
+ ...rest
71
+ });
72
+ }
73
+ /** One cell. Text stays on one line; a numeric cell is right aligned with tabular figures so digits line up. */
74
+ function TableCell({ numeric = false, ...rest }) {
75
+ return /* @__PURE__ */ jsx("td", {
76
+ className: cn("rt:px-2 rt:align-middle rt:whitespace-nowrap", numeric ? "rt:text-right rt:tabular-nums" : "rt:text-left"),
77
+ ...rest
78
+ });
79
+ }
80
+ /** The table's title for assistive technology, shown under the table in the subdued colour. */
81
+ function TableCaption(props) {
82
+ return /* @__PURE__ */ jsx("caption", {
83
+ className: "rt:py-2 rt:text-left rt:text-c1 rt:text-foreground-subdued",
84
+ ...props
85
+ });
86
+ }
87
+ export { Table, TableBody, TableBox, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow };
@@ -0,0 +1,2 @@
1
+ import { Table, TableBody, TableBodyProps, TableCaption, TableCaptionProps, TableCell, TableCellProps, TableFooter, TableFooterProps, TableHead, TableHeadProps, TableHeader, TableHeaderProps, TableProps, TableRow, TableRowProps } from "./Table.js";
2
+ export { Table, TableBody, type TableBodyProps, TableCaption, type TableCaptionProps, TableCell, type TableCellProps, TableFooter, type TableFooterProps, TableHead, type TableHeadProps, TableHeader, type TableHeaderProps, type TableProps, TableRow, type TableRowProps };
@@ -0,0 +1 @@
1
+ export { Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow } from "./Table.js";
@@ -0,0 +1,31 @@
1
+ import { TableProps } from "../table/Table.js";
2
+ import "../table/index.js";
3
+ import { JSX } from "react";
4
+ /** One column of the loading table: its real heading, and whether it holds numbers. */
5
+ export type TableLoaderColumn = {
6
+ /** A stable key for the column. */
7
+ id: string;
8
+ /** The heading, shown for real so the layout does not jump when the data arrives. */
9
+ header: string;
10
+ /** Aligns the heading and the placeholder to the right. Defaults to false. */
11
+ numeric?: boolean;
12
+ };
13
+ /** The props of TableLoader: the attributes of Table, plus the columns, how many rows to fake and the count line. */
14
+ export type TableLoaderProps = Omit<TableProps, 'children' | 'aria-busy'> & {
15
+ /** The columns, in order. */
16
+ columns: TableLoaderColumn[];
17
+ /** How many placeholder rows to draw. Defaults to 5. */
18
+ rows?: number;
19
+ /** How many results the first page will hold, for the count line. */
20
+ shown: number;
21
+ /** How many results there are in all. */
22
+ total: number;
23
+ /** What the results are called, in the plural: "products". */
24
+ noun: string;
25
+ };
26
+ /**
27
+ * What a table shows on its first load: the real headings over static skeleton rows, and a count line such as
28
+ * "72 of 1000 products". The table is marked busy and the fake rows are hidden from screen readers. Use it for the first
29
+ * load only; later loads keep the old rows.
30
+ */
31
+ export declare function TableLoader({ columns, rows, shown, total, noun, ...rest }: TableLoaderProps): JSX.Element;
@@ -0,0 +1,35 @@
1
+ import { formatCount } from "../../lib/format.js";
2
+ import { Table, TableBody, TableBox, TableCell, TableHead, TableHeader, TableRow } from "../table/Table.js";
3
+ import { Skeleton } from "../skeleton/Skeleton.js";
4
+ import { jsx, jsxs } from "react/jsx-runtime";
5
+ // src/components/table-loader/TableLoader.tsx
6
+ /**
7
+ * What a table shows on its first load: the real headings over static skeleton rows, and a count line such as
8
+ * "72 of 1000 products". The table is marked busy and the fake rows are hidden from screen readers. Use it for the first
9
+ * load only; later loads keep the old rows.
10
+ */
11
+ function TableLoader({ columns, rows = 5, shown, total, noun, ...rest }) {
12
+ return /* @__PURE__ */ jsxs("div", {
13
+ "data-slot": "table-loader",
14
+ className: "rt:flex rt:w-full rt:flex-col",
15
+ children: [/* @__PURE__ */ jsx(TableBox, { children: /* @__PURE__ */ jsxs(Table, {
16
+ "aria-busy": "true",
17
+ ...rest,
18
+ children: [/* @__PURE__ */ jsx(TableHeader, { children: /* @__PURE__ */ jsx(TableRow, { children: columns.map((c) => /* @__PURE__ */ jsx(TableHead, {
19
+ numeric: c.numeric,
20
+ children: c.header
21
+ }, c.id)) }) }), /* @__PURE__ */ jsx(TableBody, { children: Array.from({ length: rows }, (_, i) => /* @__PURE__ */ jsx(TableRow, {
22
+ "aria-hidden": "true",
23
+ children: columns.map((c) => /* @__PURE__ */ jsx(TableCell, {
24
+ numeric: c.numeric,
25
+ children: /* @__PURE__ */ jsx(Skeleton, {})
26
+ }, c.id))
27
+ }, i)) })]
28
+ }) }), /* @__PURE__ */ jsx("p", {
29
+ role: "status",
30
+ className: "rt:py-3 rt:text-c1 rt:text-foreground-subdued",
31
+ children: `${formatCount(shown)} of ${formatCount(total)} ${noun}`
32
+ })]
33
+ });
34
+ }
35
+ export { TableLoader };
@@ -0,0 +1,2 @@
1
+ import { TableLoader, TableLoaderColumn, TableLoaderProps } from "./TableLoader.js";
2
+ export { TableLoader, type TableLoaderColumn, type TableLoaderProps };
@@ -0,0 +1 @@
1
+ export { TableLoader } from "./TableLoader.js";