@milktop/react-ui 0.0.0-stage → 0.1.2

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 (250) hide show
  1. package/README.md +173 -2
  2. package/dist/accordion/Accordion.d.ts +65 -0
  3. package/dist/accordion/Accordion.js +61 -0
  4. package/dist/accordion/accordion.css +17 -0
  5. package/dist/action-bar/ActionBar.d.ts +33 -0
  6. package/dist/action-bar/ActionBar.js +48 -0
  7. package/dist/action-bar/action-bar.css +22 -0
  8. package/dist/alert/Alert.d.ts +28 -0
  9. package/dist/alert/Alert.js +12 -0
  10. package/dist/alert/alert.css +32 -0
  11. package/dist/app-shell/AppShell.d.ts +38 -0
  12. package/dist/app-shell/AppShell.js +92 -0
  13. package/dist/app-shell/Topbar.d.ts +20 -0
  14. package/dist/app-shell/Topbar.js +13 -0
  15. package/dist/app-shell/app-shell.css +41 -0
  16. package/dist/app-shell/shell.d.ts +9 -0
  17. package/dist/app-shell/shell.js +3 -0
  18. package/dist/attachments/Attachments.d.ts +84 -0
  19. package/dist/attachments/Attachments.js +235 -0
  20. package/dist/attachments/attachments.css +86 -0
  21. package/dist/avatar/Avatar.d.ts +31 -0
  22. package/dist/avatar/Avatar.js +41 -0
  23. package/dist/avatar/AvatarGroup.d.ts +41 -0
  24. package/dist/avatar/AvatarGroup.js +17 -0
  25. package/dist/avatar/avatar.css +73 -0
  26. package/dist/badge/Badge.d.ts +26 -0
  27. package/dist/badge/Badge.js +10 -0
  28. package/dist/badge/badge.css +24 -0
  29. package/dist/banner/Banner.d.ts +33 -0
  30. package/dist/banner/Banner.js +14 -0
  31. package/dist/banner/banner.css +25 -0
  32. package/dist/breadcrumbs/Breadcrumbs.d.ts +39 -0
  33. package/dist/breadcrumbs/Breadcrumbs.js +28 -0
  34. package/dist/breadcrumbs/breadcrumbs.css +18 -0
  35. package/dist/button/Button.d.ts +40 -0
  36. package/dist/button/Button.js +19 -0
  37. package/dist/button/button.css +63 -0
  38. package/dist/card/Card.d.ts +355 -0
  39. package/dist/card/Card.js +56 -0
  40. package/dist/card/card.css +43 -0
  41. package/dist/chart/AreaChart.d.ts +19 -0
  42. package/dist/chart/AreaChart.js +61 -0
  43. package/dist/chart/BarChart.d.ts +3 -0
  44. package/dist/chart/BarChart.js +60 -0
  45. package/dist/chart/ChartFrame.d.ts +25 -0
  46. package/dist/chart/ChartFrame.js +22 -0
  47. package/dist/chart/DonutChart.d.ts +20 -0
  48. package/dist/chart/DonutChart.js +41 -0
  49. package/dist/chart/Sparkline.d.ts +26 -0
  50. package/dist/chart/Sparkline.js +36 -0
  51. package/dist/chart/chart.css +51 -0
  52. package/dist/chart/chart.d.ts +23 -0
  53. package/dist/chart/chart.js +19 -0
  54. package/dist/checkbox/Checkbox.d.ts +50 -0
  55. package/dist/checkbox/Checkbox.js +19 -0
  56. package/dist/checkbox/CheckboxGroup.d.ts +44 -0
  57. package/dist/checkbox/CheckboxGroup.js +80 -0
  58. package/dist/checkbox/checkbox.css +49 -0
  59. package/dist/collapsible/Collapsible.d.ts +41 -0
  60. package/dist/collapsible/Collapsible.js +15 -0
  61. package/dist/collapsible/collapsible.css +20 -0
  62. package/dist/color-scheme.d.ts +18 -0
  63. package/dist/color-scheme.js +84 -0
  64. package/dist/command/Command.d.ts +64 -0
  65. package/dist/command/Command.js +162 -0
  66. package/dist/command/command.css +47 -0
  67. package/dist/confirm/confirm.css +5 -0
  68. package/dist/confirm/confirm.d.ts +42 -0
  69. package/dist/confirm/confirm.js +115 -0
  70. package/dist/copy-button/CopyButton.d.ts +30 -0
  71. package/dist/copy-button/CopyButton.js +23 -0
  72. package/dist/copy-button/copy-button.css +12 -0
  73. package/dist/css.d.ts +2 -0
  74. package/dist/data-list/DataList.d.ts +55 -0
  75. package/dist/data-list/DataList.js +43 -0
  76. package/dist/data-list/data-list.css +19 -0
  77. package/dist/date-picker/DatePicker.d.ts +95 -0
  78. package/dist/date-picker/DatePicker.js +237 -0
  79. package/dist/date-picker/date-picker.css +53 -0
  80. package/dist/dialog/Dialog.d.ts +98 -0
  81. package/dist/dialog/Dialog.js +92 -0
  82. package/dist/dialog/dialog.css +31 -0
  83. package/dist/divider/Divider.d.ts +27 -0
  84. package/dist/divider/Divider.js +8 -0
  85. package/dist/divider/divider.css +12 -0
  86. package/dist/editable/Editable.d.ts +47 -0
  87. package/dist/editable/Editable.js +51 -0
  88. package/dist/editable/editable.css +25 -0
  89. package/dist/editor/Editor.d.ts +59 -0
  90. package/dist/editor/Editor.js +220 -0
  91. package/dist/editor/editor.css +42 -0
  92. package/dist/editor/image.d.ts +1 -0
  93. package/dist/editor/image.js +23 -0
  94. package/dist/empty-state/EmptyState.d.ts +22 -0
  95. package/dist/empty-state/EmptyState.js +9 -0
  96. package/dist/empty-state/empty-state.css +14 -0
  97. package/dist/event-calendar/EventCalendar.d.ts +213 -0
  98. package/dist/event-calendar/EventCalendar.js +686 -0
  99. package/dist/event-calendar/dates.d.ts +8 -0
  100. package/dist/event-calendar/dates.js +21 -0
  101. package/dist/event-calendar/event-calendar.css +157 -0
  102. package/dist/field/Field.d.ts +66 -0
  103. package/dist/field/Field.js +23 -0
  104. package/dist/field/field.css +26 -0
  105. package/dist/file-upload/FileUpload.d.ts +60 -0
  106. package/dist/file-upload/FileUpload.js +102 -0
  107. package/dist/file-upload/file-upload.css +32 -0
  108. package/dist/format/FormatNumber.d.ts +42 -0
  109. package/dist/format/FormatNumber.js +59 -0
  110. package/dist/format/LocaleProvider.d.ts +33 -0
  111. package/dist/format/LocaleProvider.js +48 -0
  112. package/dist/format/format.d.ts +37 -0
  113. package/dist/format/format.js +74 -0
  114. package/dist/format/messages.d.ts +211 -0
  115. package/dist/format/messages.js +202 -0
  116. package/dist/highlight/Highlight.d.ts +11 -0
  117. package/dist/highlight/Highlight.js +14 -0
  118. package/dist/highlight/highlight.css +17 -0
  119. package/dist/hover-card/HoverCard.d.ts +47 -0
  120. package/dist/hover-card/HoverCard.js +18 -0
  121. package/dist/hover-card/hover-card.css +19 -0
  122. package/dist/index.d.ts +84 -0
  123. package/dist/index.js +85 -0
  124. package/dist/input/Input.d.ts +41 -0
  125. package/dist/input/Input.js +48 -0
  126. package/dist/input/input.css +25 -0
  127. package/dist/kbd/Kbd.d.ts +19 -0
  128. package/dist/kbd/Kbd.js +20 -0
  129. package/dist/kbd/kbd.css +8 -0
  130. package/dist/menu/Menu.d.ts +223 -0
  131. package/dist/menu/Menu.js +275 -0
  132. package/dist/menu/menu.css +38 -0
  133. package/dist/native-select/NativeSelect.d.ts +36 -0
  134. package/dist/native-select/NativeSelect.js +51 -0
  135. package/dist/native-select/native-select.css +16 -0
  136. package/dist/number-input/NumberInput.d.ts +56 -0
  137. package/dist/number-input/NumberInput.js +67 -0
  138. package/dist/number-input/number-input.css +21 -0
  139. package/dist/page/Page.d.ts +30 -0
  140. package/dist/page/Page.js +9 -0
  141. package/dist/page/page.css +17 -0
  142. package/dist/pagination/Pagination.d.ts +31 -0
  143. package/dist/pagination/Pagination.js +58 -0
  144. package/dist/pagination/pagination.css +15 -0
  145. package/dist/password-input/PasswordInput.d.ts +47 -0
  146. package/dist/password-input/PasswordInput.js +35 -0
  147. package/dist/password-input/password-input.css +18 -0
  148. package/dist/pin-input/PinInput.d.ts +45 -0
  149. package/dist/pin-input/PinInput.js +22 -0
  150. package/dist/pin-input/pin-input.css +13 -0
  151. package/dist/popover/Popover.d.ts +65 -0
  152. package/dist/popover/Popover.js +26 -0
  153. package/dist/popover/popover.css +16 -0
  154. package/dist/progress/Progress.d.ts +56 -0
  155. package/dist/progress/Progress.js +28 -0
  156. package/dist/progress/progress.css +24 -0
  157. package/dist/prose/Prose.d.ts +23 -0
  158. package/dist/prose/Prose.js +10 -0
  159. package/dist/prose/prose.css +29 -0
  160. package/dist/radio-group/RadioGroup.d.ts +59 -0
  161. package/dist/radio-group/RadioGroup.js +37 -0
  162. package/dist/radio-group/radio-group.css +30 -0
  163. package/dist/rolling-number/RollingNumber.d.ts +27 -0
  164. package/dist/rolling-number/RollingNumber.js +18 -0
  165. package/dist/rolling-number/rolling-number.css +10 -0
  166. package/dist/segment-group/Segmented.d.ts +68 -0
  167. package/dist/segment-group/Segmented.js +79 -0
  168. package/dist/segment-group/segment-group.css +25 -0
  169. package/dist/select/ListSelect.d.ts +5 -0
  170. package/dist/select/ListSelect.js +82 -0
  171. package/dist/select/SearchSelect.d.ts +43 -0
  172. package/dist/select/SearchSelect.js +219 -0
  173. package/dist/select/Select.d.ts +147 -0
  174. package/dist/select/Select.js +32 -0
  175. package/dist/select/items.d.ts +17 -0
  176. package/dist/select/items.js +14 -0
  177. package/dist/select/search-select.css +45 -0
  178. package/dist/select/select.css +52 -0
  179. package/dist/sheet/Sheet.d.ts +88 -0
  180. package/dist/sheet/Sheet.js +66 -0
  181. package/dist/sheet/sheet.css +44 -0
  182. package/dist/sidebar/NavGroup.d.ts +29 -0
  183. package/dist/sidebar/NavGroup.js +78 -0
  184. package/dist/sidebar/NavItem.d.ts +33 -0
  185. package/dist/sidebar/NavItem.js +50 -0
  186. package/dist/sidebar/NavSection.d.ts +20 -0
  187. package/dist/sidebar/NavSection.js +44 -0
  188. package/dist/sidebar/Sidebar.d.ts +65 -0
  189. package/dist/sidebar/Sidebar.js +59 -0
  190. package/dist/sidebar/SidebarUser.d.ts +31 -0
  191. package/dist/sidebar/SidebarUser.js +14 -0
  192. package/dist/sidebar/context.d.ts +13 -0
  193. package/dist/sidebar/context.js +6 -0
  194. package/dist/sidebar/sidebar.css +109 -0
  195. package/dist/skeleton/Skeleton.d.ts +25 -0
  196. package/dist/skeleton/Skeleton.js +8 -0
  197. package/dist/skeleton/skeleton.css +13 -0
  198. package/dist/slider/Slider.d.ts +70 -0
  199. package/dist/slider/Slider.js +65 -0
  200. package/dist/slider/slider.css +17 -0
  201. package/dist/sortable-list/SortableList.d.ts +46 -0
  202. package/dist/sortable-list/SortableList.js +85 -0
  203. package/dist/sortable-list/sortable-list.css +25 -0
  204. package/dist/spinner/Spinner.d.ts +18 -0
  205. package/dist/spinner/Spinner.js +11 -0
  206. package/dist/spinner/spinner.css +9 -0
  207. package/dist/stat/Stat.d.ts +42 -0
  208. package/dist/stat/Stat.js +21 -0
  209. package/dist/stat/Stats.d.ts +23 -0
  210. package/dist/stat/Stats.js +8 -0
  211. package/dist/stat/stat.css +34 -0
  212. package/dist/swatch-picker/SwatchPicker.d.ts +45 -0
  213. package/dist/swatch-picker/SwatchPicker.js +54 -0
  214. package/dist/swatch-picker/swatch-picker.css +38 -0
  215. package/dist/switch/Switch.d.ts +39 -0
  216. package/dist/switch/Switch.js +17 -0
  217. package/dist/switch/switch.css +13 -0
  218. package/dist/table/Table.d.ts +90 -0
  219. package/dist/table/Table.js +145 -0
  220. package/dist/table/table.css +44 -0
  221. package/dist/tabs/Tabs.d.ts +87 -0
  222. package/dist/tabs/Tabs.js +90 -0
  223. package/dist/tabs/tabs.css +53 -0
  224. package/dist/tags-input/TagsInput.d.ts +69 -0
  225. package/dist/tags-input/TagsInput.js +95 -0
  226. package/dist/tags-input/tags-input.css +37 -0
  227. package/dist/textarea/Textarea.d.ts +24 -0
  228. package/dist/textarea/Textarea.js +51 -0
  229. package/dist/textarea/textarea.css +14 -0
  230. package/dist/theme-toggle/ThemeToggle.d.ts +49 -0
  231. package/dist/theme-toggle/ThemeToggle.js +71 -0
  232. package/dist/theme-toggle/theme-toggle.css +23 -0
  233. package/dist/theme.css +121 -0
  234. package/dist/time-input/TimeInput.d.ts +25 -0
  235. package/dist/time-input/TimeInput.js +20 -0
  236. package/dist/timeline/Timeline.d.ts +50 -0
  237. package/dist/timeline/Timeline.js +15 -0
  238. package/dist/timeline/timeline.css +29 -0
  239. package/dist/toast/Toaster.d.ts +36 -0
  240. package/dist/toast/Toaster.js +25 -0
  241. package/dist/toast/toast.css +33 -0
  242. package/dist/tooltip/Tooltip.d.ts +55 -0
  243. package/dist/tooltip/Tooltip.js +48 -0
  244. package/dist/tooltip/tooltip.css +18 -0
  245. package/dist/tree-view/TreeView.d.ts +86 -0
  246. package/dist/tree-view/TreeView.js +74 -0
  247. package/dist/tree-view/tree-view.css +29 -0
  248. package/dist/utils.d.ts +19 -0
  249. package/dist/utils.js +59 -0
  250. package/package.json +99 -4
@@ -0,0 +1,86 @@
1
+ /**
2
+ * A tree of nested items that open and close, e.g. folders, categories or a
3
+ * clinic's sites and rooms.
4
+ *
5
+ * <TreeView items={folders} onSelect={(node) => open(node)} />
6
+ * <TreeView items={permissions} checkable checked={granted} onCheckedChange={setGranted} />
7
+ *
8
+ * Arrow keys move through it (←→ close and open), typing jumps, Enter selects.
9
+ *
10
+ * - `items`: `{ value, label, icon, children, disabled }`; a node with
11
+ * `children` is a branch (an empty array still opens and closes)
12
+ * - `selected`, `defaultSelected`; `onSelectedChange`: the selected values;
13
+ * `selectionMode`: 'single' (default) or 'multiple'. `onSelect(node)`: an
14
+ * item (not a branch) was chosen
15
+ * - `expanded`, `defaultExpanded`; `onExpandedChange`: the open branches' values
16
+ * - `checkable`: a checkbox on each (ticking a branch ticks its children);
17
+ * `checked`, `defaultChecked`; `onCheckedChange`: the ticked values
18
+ * - `renderItem(node, { branch, expanded, selected, depth })`: a row's content
19
+ * - `label`: the tree's name (shown above it, and for assistive tech)
20
+ *
21
+ * By hand, Ark's parts are here too: TreeView.Root, Tree, Branch,
22
+ * BranchControl, BranchText, BranchIndicator, BranchContent, Item, ItemText,
23
+ * NodeProvider, NodeCheckbox… with `createTreeCollection`.
24
+ */
25
+ import { type ReactNode } from 'react';
26
+ import { TreeView as Ark, createTreeCollection } from '@ark-ui/react/tree-view';
27
+ import 'iconify-icon';
28
+ import { type Classes } from '../utils.js';
29
+ import '../theme.css';
30
+ import './tree-view.css';
31
+ export type TreeItem = {
32
+ value: string;
33
+ label: ReactNode;
34
+ icon?: string;
35
+ children?: TreeItem[];
36
+ disabled?: boolean;
37
+ [key: string]: unknown;
38
+ };
39
+ type Render = ((node: TreeItem, state: {
40
+ branch: boolean;
41
+ expanded: boolean;
42
+ selected: boolean;
43
+ depth: number;
44
+ }) => ReactNode) | undefined;
45
+ export type TreeViewProps = Omit<Ark.RootProps<TreeItem>, 'collection' | 'onSelect' | 'selectedValue' | 'defaultSelectedValue' | 'onSelectionChange' | 'expandedValue' | 'defaultExpandedValue' | 'onExpandedChange' | 'checkedValue' | 'defaultCheckedValue' | 'onCheckedChange'> & {
46
+ items: TreeItem[];
47
+ selected?: string[];
48
+ defaultSelected?: string[];
49
+ onSelectedChange?: (values: string[]) => void;
50
+ onSelect?: (node: TreeItem) => void;
51
+ expanded?: string[];
52
+ defaultExpanded?: string[];
53
+ onExpandedChange?: (values: string[]) => void;
54
+ checkable?: boolean;
55
+ checked?: string[];
56
+ defaultChecked?: string[];
57
+ onCheckedChange?: (values: string[]) => void;
58
+ renderItem?: Render;
59
+ label?: ReactNode;
60
+ classes?: Classes<'root' | 'label' | 'tree' | 'branch' | 'branchControl' | 'branchIndicator' | 'branchText' | 'branchContent' | 'indentGuide' | 'item' | 'itemText' | 'icon' | 'checkbox'>;
61
+ };
62
+ declare function TreeViewShortcut({ items, selected, defaultSelected, onSelectedChange, onSelect, expanded, defaultExpanded, onExpandedChange, checkable, checked, defaultChecked, onCheckedChange, renderItem, label, className, classes, ...rest }: TreeViewProps): import("react").JSX.Element;
63
+ export declare const TreeView: typeof TreeViewShortcut & {
64
+ Root: Ark.RootComponent<{}>;
65
+ RootProvider: Ark.RootProviderComponent<{}>;
66
+ Label: import("react").ForwardRefExoticComponent<Ark.LabelProps & import("react").RefAttributes<HTMLHeadingElement>>;
67
+ Tree: import("react").ForwardRefExoticComponent<Ark.TreeProps & import("react").RefAttributes<HTMLDivElement>>;
68
+ Branch: import("react").ForwardRefExoticComponent<Ark.BranchProps & import("react").RefAttributes<HTMLDivElement>>;
69
+ BranchControl: import("react").ForwardRefExoticComponent<Ark.BranchControlProps & import("react").RefAttributes<HTMLDivElement>>;
70
+ BranchText: import("react").ForwardRefExoticComponent<Ark.BranchTextProps & import("react").RefAttributes<HTMLSpanElement>>;
71
+ BranchIndicator: import("react").ForwardRefExoticComponent<Ark.BranchIndicatorProps & import("react").RefAttributes<HTMLDivElement>>;
72
+ BranchContent: import("react").ForwardRefExoticComponent<Ark.BranchContentProps & import("react").RefAttributes<HTMLDivElement>>;
73
+ BranchIndentGuide: import("react").ForwardRefExoticComponent<Ark.BranchIndentGuideProps & import("react").RefAttributes<HTMLDivElement>>;
74
+ BranchTrigger: import("react").ForwardRefExoticComponent<Ark.BranchTriggerProps & import("react").RefAttributes<HTMLDivElement>>;
75
+ Item: import("react").ForwardRefExoticComponent<Ark.ItemProps & import("react").RefAttributes<HTMLDivElement>>;
76
+ ItemText: import("react").ForwardRefExoticComponent<Ark.ItemTextProps & import("react").RefAttributes<HTMLSpanElement>>;
77
+ ItemIndicator: import("react").ForwardRefExoticComponent<Ark.ItemIndicatorProps & import("react").RefAttributes<HTMLDivElement>>;
78
+ NodeProvider: typeof Ark.NodeProvider;
79
+ NodeCheckbox: import("react").ForwardRefExoticComponent<Ark.NodeCheckboxProps & import("react").RefAttributes<HTMLSpanElement>>;
80
+ NodeCheckboxIndicator: {
81
+ (props: Ark.NodeCheckboxIndicatorProps): import("react").JSX.Element;
82
+ displayName: string;
83
+ };
84
+ Context: <T extends unknown>(props: Ark.ContextProps<T>) => ReactNode;
85
+ };
86
+ export { createTreeCollection };
@@ -0,0 +1,74 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ /**
3
+ * A tree of nested items that open and close, e.g. folders, categories or a
4
+ * clinic's sites and rooms.
5
+ *
6
+ * <TreeView items={folders} onSelect={(node) => open(node)} />
7
+ * <TreeView items={permissions} checkable checked={granted} onCheckedChange={setGranted} />
8
+ *
9
+ * Arrow keys move through it (←→ close and open), typing jumps, Enter selects.
10
+ *
11
+ * - `items`: `{ value, label, icon, children, disabled }`; a node with
12
+ * `children` is a branch (an empty array still opens and closes)
13
+ * - `selected`, `defaultSelected`; `onSelectedChange`: the selected values;
14
+ * `selectionMode`: 'single' (default) or 'multiple'. `onSelect(node)`: an
15
+ * item (not a branch) was chosen
16
+ * - `expanded`, `defaultExpanded`; `onExpandedChange`: the open branches' values
17
+ * - `checkable`: a checkbox on each (ticking a branch ticks its children);
18
+ * `checked`, `defaultChecked`; `onCheckedChange`: the ticked values
19
+ * - `renderItem(node, { branch, expanded, selected, depth })`: a row's content
20
+ * - `label`: the tree's name (shown above it, and for assistive tech)
21
+ *
22
+ * By hand, Ark's parts are here too: TreeView.Root, Tree, Branch,
23
+ * BranchControl, BranchText, BranchIndicator, BranchContent, Item, ItemText,
24
+ * NodeProvider, NodeCheckbox… with `createTreeCollection`.
25
+ */
26
+ import { useMemo } from 'react';
27
+ import { TreeView as Ark, createTreeCollection, useTreeViewNodeContext } from '@ark-ui/react/tree-view';
28
+ import 'iconify-icon';
29
+ import { cx, on, partsOf, withParts } from '../utils.js';
30
+ import { useMessages } from '../format/LocaleProvider.js';
31
+ import '../theme.css';
32
+ import './tree-view.css';
33
+ function TreeViewShortcut({ items, selected, defaultSelected, onSelectedChange, onSelect, expanded, defaultExpanded, onExpandedChange, checkable = false, checked, defaultChecked, onCheckedChange, renderItem, label = null, className, classes, ...rest }) {
34
+ const t = useMessages();
35
+ const part = partsOf('tree-view', classes);
36
+ const collection = useMemo(() => createTreeCollection({
37
+ nodeToValue: (node) => node.value,
38
+ nodeToString: (node) => (typeof node.label === 'string' ? node.label : node.value),
39
+ isNodeDisabled: (node) => !!node.disabled,
40
+ rootNode: { value: 'ROOT', label: '', children: items },
41
+ }), [items]);
42
+ return (_jsxs(Ark.Root, { ...(t.zag.treeView && { translations: t.zag.treeView }), ...rest, ...part('root'), className: cx(className, classes?.root), collection: collection, ...(selected !== undefined && { selectedValue: selected }), ...(defaultSelected && { defaultSelectedValue: defaultSelected }), ...(expanded !== undefined && { expandedValue: expanded }), ...(defaultExpanded && { defaultExpandedValue: defaultExpanded }), ...(checked !== undefined && { checkedValue: checked }), ...(defaultChecked && { defaultCheckedValue: defaultChecked }), ...((onSelectedChange || onSelect) && {
43
+ onSelectionChange: (details) => {
44
+ onSelectedChange?.(details.selectedValue);
45
+ // A single item chosen (not a branch): onSelect gets it.
46
+ // (The focused one, or the last chosen: Zag may not have moved focus yet.)
47
+ const nodes = details.selectedNodes;
48
+ const node = nodes.find((n) => n.value === details.focusedValue) ?? nodes[nodes.length - 1];
49
+ if (node && !node.children)
50
+ onSelect?.(node);
51
+ },
52
+ }), ...on('onExpandedChange', onExpandedChange, (d) => d.expandedValue), ...on('onCheckedChange', onCheckedChange, (d) => d.checkedValue), children: [label && _jsx(Ark.Label, { ...part('label'), children: label }), _jsx(Ark.Tree, { ...part('tree'), children: items.map((node, i) => _jsx(Node, { node: node, indexPath: [i], part: part, checkable: checkable, renderItem: renderItem }, node.value)) })] }));
53
+ }
54
+ function Node({ node, indexPath, part, checkable, renderItem }) {
55
+ return (_jsx(Ark.NodeProvider, { node: node, indexPath: indexPath, children: node.children
56
+ ? _jsxs(Ark.Branch, { ...part('branch'), children: [_jsxs(Ark.BranchControl, { ...part('branch-control'), children: [_jsx(Ark.BranchIndicator, { ...part('branch-indicator'), children: _jsx("iconify-icon", { icon: "lucide:chevron-right" }) }), _jsx(Row, { node: node, part: part, checkable: checkable, renderItem: renderItem })] }), _jsxs(Ark.BranchContent, { ...part('branch-content'), children: [_jsx(Ark.BranchIndentGuide, { ...part('indent-guide') }), node.children.map((child, i) => (_jsx(Node, { node: child, indexPath: [...indexPath, i], part: part, checkable: checkable, renderItem: renderItem }, child.value)))] })] })
57
+ : _jsx(Ark.Item, { ...part('item'), children: _jsx(Row, { node: node, part: part, checkable: checkable, renderItem: renderItem }) }) }));
58
+ }
59
+ // A row's checkbox, icon and text (or your render).
60
+ function Row({ node, part, checkable, renderItem }) {
61
+ const state = useTreeViewNodeContext();
62
+ const branch = !!node.children;
63
+ const Text = branch ? Ark.BranchText : Ark.ItemText;
64
+ return _jsxs(_Fragment, { children: [checkable && (_jsx(Ark.NodeCheckbox, { ...part('checkbox'), onClick: (e) => e.stopPropagation(), children: _jsx(Ark.NodeCheckboxIndicator, { indeterminate: _jsx("iconify-icon", { icon: "lucide:minus" }), children: _jsx("iconify-icon", { icon: "lucide:check" }) }) })), renderItem
65
+ ? _jsx(Text, { ...part(branch ? 'branch-text' : 'item-text'), children: renderItem(node, { branch, expanded: state.expanded, selected: state.selected, depth: state.depth }) })
66
+ : _jsxs(_Fragment, { children: [(node.icon ?? branch) && (_jsx("iconify-icon", { ...part('icon'), "aria-hidden": "true", icon: node.icon ?? (state.expanded ? 'lucide:folder-open' : 'lucide:folder') })), _jsx(Text, { ...part(branch ? 'branch-text' : 'item-text'), children: node.label })] })] });
67
+ }
68
+ export const TreeView = withParts(TreeViewShortcut, {
69
+ Root: Ark.Root, RootProvider: Ark.RootProvider, Label: Ark.Label, Tree: Ark.Tree, Branch: Ark.Branch, BranchControl: Ark.BranchControl,
70
+ BranchText: Ark.BranchText, BranchIndicator: Ark.BranchIndicator, BranchContent: Ark.BranchContent, BranchIndentGuide: Ark.BranchIndentGuide,
71
+ BranchTrigger: Ark.BranchTrigger, Item: Ark.Item, ItemText: Ark.ItemText, ItemIndicator: Ark.ItemIndicator, NodeProvider: Ark.NodeProvider,
72
+ NodeCheckbox: Ark.NodeCheckbox, NodeCheckboxIndicator: Ark.NodeCheckboxIndicator, Context: Ark.Context,
73
+ });
74
+ export { createTreeCollection };
@@ -0,0 +1,29 @@
1
+ @layer ui {
2
+ [data-scope=tree-view][data-part=root] { display: block; min-width: 0; color: var(--ui-text); font-family: var(--ui-font); font-size: 14px; }
3
+ [data-scope=tree-view][data-part=label] { display: block; margin-bottom: 0.375rem; font-size: 14px; font-weight: 500; }
4
+ [data-scope=tree-view][data-part=tree] { display: flex; flex-direction: column; gap: 1px; outline: none; }
5
+ /* A row: indented by its depth (Zag sets --depth), a chevron for branches, then checkbox, icon and text. */
6
+ [data-scope=tree-view]:is([data-part=branch-control], [data-part=item]) {
7
+ display: flex; align-items: center; gap: 0.375rem; min-height: 2rem; box-sizing: border-box;
8
+ padding: 0 0.5rem 0 calc(0.5rem + (var(--depth, 1) - 1) * 1.25rem); border-radius: var(--ui-radius);
9
+ cursor: pointer; user-select: none; outline: none;
10
+ &:hover { background: var(--ui-hover); }
11
+ &[data-selected] { background: var(--ui-accent-soft); color: var(--ui-accent-soft-text); }
12
+ &[data-focus]:focus-visible { box-shadow: inset 0 0 0 2px var(--ui-ring-soft); }
13
+ &[data-disabled] { opacity: 0.5; cursor: not-allowed; } }
14
+ /* Items line up with branch texts (past the chevron's room). */
15
+ [data-scope=tree-view][data-part=item] { padding-left: calc(0.5rem + (var(--depth, 1) - 1) * 1.25rem + 1.375rem); }
16
+ [data-scope=tree-view][data-part=branch-indicator] { display: grid; place-items: center; width: 1rem; color: var(--ui-muted); font-size: 14px;
17
+ transition: rotate 150ms;
18
+ &[data-state=open] { rotate: 90deg; } }
19
+ [data-scope=tree-view][data-part=icon] { flex-shrink: 0; color: var(--ui-muted); font-size: 16px;
20
+ [data-selected] > & { color: inherit; } }
21
+ [data-scope=tree-view]:is([data-part=branch-text], [data-part=item-text]) { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
22
+ [data-scope=tree-view][data-part=branch-content] { position: relative; display: flex; flex-direction: column; gap: 1px; }
23
+ /* A faint line down the open branch's children. */
24
+ [data-scope=tree-view][data-part=indent-guide] { position: absolute; top: 0; bottom: 0; width: 1px; background: var(--ui-border);
25
+ left: calc(0.5rem + (var(--depth, 1) - 1) * 1.25rem + 0.5rem); }
26
+ [data-scope=tree-view][data-part=checkbox] { display: grid; place-items: center; flex-shrink: 0; width: 1rem; height: 1rem; box-sizing: border-box;
27
+ border: 1px solid var(--ui-border); border-radius: 4px; background: var(--ui-surface); color: var(--ui-accent-text); font-size: 11px;
28
+ &:is([data-state=checked], [data-state=indeterminate]) { background: var(--ui-accent); border-color: var(--ui-accent); } }
29
+ }
@@ -0,0 +1,19 @@
1
+ import type { ComponentProps, ElementType, ReactNode } from 'react';
2
+ type ClassName = string | false | null | undefined | ClassName[];
3
+ export declare const cx: (...names: ClassName[]) => string | undefined;
4
+ export type Classes<Part extends string> = Partial<Record<Part, string>>;
5
+ export declare const partsOf: (scope: string, classes?: Partial<Record<string, string>>) => (name: string) => {
6
+ 'data-scope': string;
7
+ 'data-part': string;
8
+ className: string | undefined;
9
+ };
10
+ export declare function partOf<T extends ElementType = 'div'>(scope: string, name: string, tag?: T): {
11
+ (props: ComponentProps<T>): import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>>;
12
+ displayName: string;
13
+ };
14
+ export declare const withParts: <S extends object, P extends object>(Shortcut: S, parts: P) => S & P;
15
+ export type Slot<State> = ReactNode | ((state: State) => ReactNode);
16
+ export declare function slot<State>(value: Slot<State> | undefined, fallback: ReactNode, state: State): ReactNode;
17
+ export declare function useControllable<V>(value: V | undefined, defaultValue: V, onChange?: (value: V) => void): readonly [V, (next: V) => void];
18
+ export declare function on<Name extends string, Details, Value>(name: Name, handler: ((value: Value, details: Details) => void) | undefined, pick: (details: Details) => Value): Partial<Record<Name, (details: Details) => void>>;
19
+ export {};
package/dist/utils.js ADDED
@@ -0,0 +1,59 @@
1
+ import { createElement, useCallback, useState } from 'react';
2
+ // Joins the truthy class names (nested arrays too).
3
+ export const cx = (...names) => names.map((name) => (Array.isArray(name) ? cx(...name) : name)).filter(Boolean).join(' ') || undefined;
4
+ // A component's parts carry Zag-style data-scope and data-part attributes,
5
+ // which the library's CSS targets, so a part never matches another
6
+ // component's rules, and the library adds no classes of its own to collide
7
+ // with yours or Tailwind's. Each part also gets the caller's classes for it,
8
+ // from the `classes` prop, keyed by camelCased part name:
9
+ //
10
+ // const part = partsOf('select', classes)
11
+ // <Ark.Trigger {...part('trigger')}> // classes={{ trigger: '…' }}
12
+ //
13
+ // Ark merges our props over its own, so on an Ark part these win: that's
14
+ // how Sheet's parts say data-scope="sheet" on Ark's dialog. Where the scopes
15
+ // match they're the same values Ark sets anyway.
16
+ const camel = (name) => name.replace(/-(\w)/g, (_, c) => c.toUpperCase());
17
+ export const partsOf = (scope, classes) => (name) => ({
18
+ 'data-scope': scope,
19
+ 'data-part': name,
20
+ className: cx(classes?.[camel(name)]),
21
+ });
22
+ // A part of our own (not Ark's), for building a component by hand; it takes
23
+ // the props of its element (a div by default):
24
+ // Dialog.Footer = partOf('dialog', 'footer') // <Dialog.Footer>…</Dialog.Footer>
25
+ export function partOf(scope, name, tag = 'div') {
26
+ const Part = (props) => createElement(tag, { 'data-scope': scope, 'data-part': name, ...props });
27
+ Part.displayName = `${scope}.${name}`;
28
+ return Part;
29
+ }
30
+ // The shortcut component, with its parts on it for building it by hand:
31
+ // export const Checkbox = withParts(CheckboxShortcut, { Root: Ark.Root, … })
32
+ // <Checkbox label="…" /> or <Checkbox.Root>…</Checkbox.Root>
33
+ export const withParts = (Shortcut, parts) => Object.assign(Shortcut, parts);
34
+ // A slot's content: the default when it's absent.
35
+ // {slot(indicator, <CheckIcon />, { indeterminate })}
36
+ export function slot(value, fallback, state) {
37
+ if (value == null)
38
+ return fallback;
39
+ return typeof value === 'function' ? value(state) : value;
40
+ }
41
+ // A value that's controlled when `value` is given, and kept here otherwise
42
+ // (starting from `defaultValue`). Calls onChange either way.
43
+ export function useControllable(value, defaultValue, onChange) {
44
+ const [own, setOwn] = useState(defaultValue);
45
+ const controlled = value !== undefined;
46
+ const set = useCallback((next) => {
47
+ if (!controlled)
48
+ setOwn(next);
49
+ onChange?.(next);
50
+ }, [controlled, onChange]);
51
+ return [controlled ? value : own, set];
52
+ }
53
+ // A change handler given the value rather than Ark's details object, and
54
+ // left out when there's none: Zag reads a prop passed as undefined as a
55
+ // value, overriding its default.
56
+ // <Ark.Root {...rest} {...on('onCheckedChange', onCheckedChange, (d) => d.checked)}>
57
+ export function on(name, handler, pick) {
58
+ return handler ? { [name]: (details) => handler(pick(details), details) } : {};
59
+ }
package/package.json CHANGED
@@ -1,6 +1,101 @@
1
1
  {
2
2
  "name": "@milktop/react-ui",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.1.2",
4
+ "description": "React components on Ark UI (Zag state machines), with imba-ui's API and design",
5
+ "license": "MIT",
6
+ "author": "André Goldstein",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/milktop/react-ui.git"
10
+ },
11
+ "homepage": "https://github.com/milktop/react-ui#readme",
12
+ "bugs": {
13
+ "url": "https://github.com/milktop/react-ui/issues"
14
+ },
15
+ "keywords": [
16
+ "react",
17
+ "ui",
18
+ "components",
19
+ "ark-ui",
20
+ "zag",
21
+ "design-system"
22
+ ],
23
+ "type": "module",
24
+ "sideEffects": [
25
+ "*.css"
26
+ ],
27
+ "main": "./dist/index.js",
28
+ "types": "./dist/index.d.ts",
29
+ "exports": {
30
+ ".": {
31
+ "types": "./dist/index.d.ts",
32
+ "default": "./dist/index.js"
33
+ },
34
+ "./theme.css": "./dist/theme.css",
35
+ "./package.json": "./package.json"
36
+ },
37
+ "files": [
38
+ "dist",
39
+ "README.md"
40
+ ],
41
+ "publishConfig": {
42
+ "access": "public"
43
+ },
44
+ "engines": {
45
+ "node": ">=20"
46
+ },
47
+ "scripts": {
48
+ "dev": "vite playground --port 5194",
49
+ "build": "vite build playground",
50
+ "build:lib": "rm -rf dist && tsc -p tsconfig.build.json && node scripts/after-tsc.js",
51
+ "check": "tsc && eslint src playground",
52
+ "prepublishOnly": "npm run build:lib",
53
+ "preversion": "npm run check && npm run build:lib",
54
+ "postversion": "git push --follow-tags",
55
+ "release:patch": "npm version patch && npm publish",
56
+ "release:minor": "npm version minor && npm publish",
57
+ "release:major": "npm version major && npm publish",
58
+ "release:beta": "npm version prerelease --preid beta && npm publish --tag beta"
59
+ },
60
+ "peerDependencies": {
61
+ "react": "^19.0.0",
62
+ "react-dom": "^19.0.0"
63
+ },
64
+ "dependencies": {
65
+ "@ark-ui/react": "^5.39.3",
66
+ "@dnd-kit/core": "^6.3.1",
67
+ "@dnd-kit/sortable": "^10.0.0",
68
+ "@dnd-kit/utilities": "^3.2.2",
69
+ "@internationalized/date": "^3.12.4",
70
+ "@tiptap/core": "^3.31.4",
71
+ "@tiptap/extension-image": "^3.31.4",
72
+ "@tiptap/extensions": "^3.31.4",
73
+ "@tiptap/pm": "^3.31.4",
74
+ "@tiptap/starter-kit": "^3.31.4",
75
+ "@types/d3-scale": "^4.0.9",
76
+ "@types/d3-shape": "^3.2.0",
77
+ "@zag-js/date-utils": "^1.45.0",
78
+ "@zag-js/file-utils": "^1.45.0",
79
+ "d3-scale": "^4.0.2",
80
+ "d3-shape": "^3.2.0",
81
+ "iconify-icon": "^3.0.3"
82
+ },
83
+ "devDependencies": {
84
+ "@fontsource-variable/dm-sans": "^5.3.0",
85
+ "@fontsource-variable/geist": "^5.3.0",
86
+ "@fontsource-variable/inter": "^5.3.0",
87
+ "@fontsource-variable/plus-jakarta-sans": "^5.3.0",
88
+ "@tailwindcss/vite": "^4.3.3",
89
+ "@types/react": "^19.3.0",
90
+ "@types/react-dom": "^19.3.0",
91
+ "@vitejs/plugin-react": "^6.1.2",
92
+ "eslint": "^10.12.0",
93
+ "eslint-plugin-react-hooks": "^7.1.1",
94
+ "react": "^19.3.0",
95
+ "react-dom": "^19.3.0",
96
+ "tailwindcss": "^4.3.3",
97
+ "typescript": "^6.0.3",
98
+ "typescript-eslint": "^8.71.1",
99
+ "vite": "^8.3.4"
100
+ }
101
+ }