@mihcm/ui 0.14.1 → 0.15.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/CheckboxGrid.native.d.ts.map +1 -1
- package/dist/CheckboxGrid.native.js +2 -1
- package/dist/CheckboxGrid.native.js.map +1 -1
- package/dist/Combobox.native.d.ts.map +1 -1
- package/dist/Combobox.native.js +2 -1
- package/dist/Combobox.native.js.map +1 -1
- package/dist/DataTable/column-filter.d.ts +8 -0
- package/dist/DataTable/column-filter.d.ts.map +1 -0
- package/dist/DataTable/column-filter.js +67 -0
- package/dist/DataTable/column-filter.js.map +1 -0
- package/dist/DataTable/column-header.d.ts +16 -0
- package/dist/DataTable/column-header.d.ts.map +1 -0
- package/dist/DataTable/column-header.js +11 -0
- package/dist/DataTable/column-header.js.map +1 -0
- package/dist/DataTable/column-visibility.d.ts +7 -0
- package/dist/DataTable/column-visibility.d.ts.map +1 -0
- package/dist/DataTable/column-visibility.js +35 -0
- package/dist/DataTable/column-visibility.js.map +1 -0
- package/dist/DataTable/index.d.ts +5 -0
- package/dist/DataTable/index.d.ts.map +1 -0
- package/dist/DataTable/index.js +5 -0
- package/dist/DataTable/index.js.map +1 -0
- package/dist/DataTable/pinning.d.ts +13 -0
- package/dist/DataTable/pinning.d.ts.map +1 -0
- package/dist/DataTable/pinning.js +29 -0
- package/dist/DataTable/pinning.js.map +1 -0
- package/dist/DataTable.d.ts +3 -7
- package/dist/DataTable.d.ts.map +1 -1
- package/dist/DataTable.js +7 -126
- package/dist/DataTable.js.map +1 -1
- package/dist/Dialog.native.d.ts +3 -1
- package/dist/Dialog.native.d.ts.map +1 -1
- package/dist/Dialog.native.js +2 -2
- package/dist/Dialog.native.js.map +1 -1
- package/dist/Form/building-blocks.d.ts +26 -0
- package/dist/Form/building-blocks.d.ts.map +1 -0
- package/dist/Form/building-blocks.js +29 -0
- package/dist/Form/building-blocks.js.map +1 -0
- package/dist/Form/fields-choice.d.ts +72 -0
- package/dist/Form/fields-choice.d.ts.map +1 -0
- package/dist/Form/fields-choice.js +69 -0
- package/dist/Form/fields-choice.js.map +1 -0
- package/dist/Form/fields-complex.d.ts +28 -0
- package/dist/Form/fields-complex.d.ts.map +1 -0
- package/dist/Form/fields-complex.js +38 -0
- package/dist/Form/fields-complex.js.map +1 -0
- package/dist/Form/fields-date.d.ts +46 -0
- package/dist/Form/fields-date.d.ts.map +1 -0
- package/dist/Form/fields-date.js +41 -0
- package/dist/Form/fields-date.js.map +1 -0
- package/dist/Form/fields-text.d.ts +47 -0
- package/dist/Form/fields-text.d.ts.map +1 -0
- package/dist/Form/fields-text.js +46 -0
- package/dist/Form/fields-text.js.map +1 -0
- package/dist/Form/fields-toggle.d.ts +24 -0
- package/dist/Form/fields-toggle.d.ts.map +1 -0
- package/dist/Form/fields-toggle.js +32 -0
- package/dist/Form/fields-toggle.js.map +1 -0
- package/dist/Form/helpers.d.ts +66 -0
- package/dist/Form/helpers.d.ts.map +1 -0
- package/dist/Form/helpers.js +44 -0
- package/dist/Form/helpers.js.map +1 -0
- package/dist/Form/types.d.ts +25 -0
- package/dist/Form/types.d.ts.map +1 -0
- package/dist/Form/types.js +8 -0
- package/dist/Form/types.js.map +1 -0
- package/dist/Form.d.ts +24 -298
- package/dist/Form.d.ts.map +1 -1
- package/dist/Form.js +30 -246
- package/dist/Form.js.map +1 -1
- package/dist/IconSidebar.d.ts +6 -46
- package/dist/IconSidebar.d.ts.map +1 -1
- package/dist/IconSidebar.js +6 -116
- package/dist/IconSidebar.js.map +1 -1
- package/dist/MainSidebar/back-button.d.ts +14 -0
- package/dist/MainSidebar/back-button.d.ts.map +1 -0
- package/dist/MainSidebar/back-button.js +14 -0
- package/dist/MainSidebar/back-button.js.map +1 -0
- package/dist/MainSidebar/breadcrumb.d.ts +10 -0
- package/dist/MainSidebar/breadcrumb.d.ts.map +1 -0
- package/dist/MainSidebar/breadcrumb.js +24 -0
- package/dist/MainSidebar/breadcrumb.js.map +1 -0
- package/dist/MainSidebar/columns.d.ts +3 -0
- package/dist/MainSidebar/columns.d.ts.map +1 -0
- package/dist/MainSidebar/columns.js +198 -0
- package/dist/MainSidebar/columns.js.map +1 -0
- package/dist/MainSidebar/command.d.ts +3 -0
- package/dist/MainSidebar/command.d.ts.map +1 -0
- package/dist/MainSidebar/command.js +193 -0
- package/dist/MainSidebar/command.js.map +1 -0
- package/dist/MainSidebar/drilldown.d.ts +3 -0
- package/dist/MainSidebar/drilldown.d.ts.map +1 -0
- package/dist/MainSidebar/drilldown.js +154 -0
- package/dist/MainSidebar/drilldown.js.map +1 -0
- package/dist/MainSidebar/expanded.d.ts +7 -0
- package/dist/MainSidebar/expanded.d.ts.map +1 -0
- package/dist/MainSidebar/expanded.js +102 -0
- package/dist/MainSidebar/expanded.js.map +1 -0
- package/dist/MainSidebar/floating.d.ts +3 -0
- package/dist/MainSidebar/floating.d.ts.map +1 -0
- package/dist/MainSidebar/floating.js +116 -0
- package/dist/MainSidebar/floating.js.map +1 -0
- package/dist/MainSidebar/helpers.d.ts +50 -0
- package/dist/MainSidebar/helpers.d.ts.map +1 -0
- package/dist/MainSidebar/helpers.js +150 -0
- package/dist/MainSidebar/helpers.js.map +1 -0
- package/dist/MainSidebar/hover.d.ts +3 -0
- package/dist/MainSidebar/hover.d.ts.map +1 -0
- package/dist/MainSidebar/hover.js +177 -0
- package/dist/MainSidebar/hover.js.map +1 -0
- package/dist/MainSidebar/index.d.ts +6 -0
- package/dist/MainSidebar/index.d.ts.map +1 -0
- package/dist/MainSidebar/index.js +108 -0
- package/dist/MainSidebar/index.js.map +1 -0
- package/dist/MainSidebar/mobile.d.ts +29 -0
- package/dist/MainSidebar/mobile.d.ts.map +1 -0
- package/dist/MainSidebar/mobile.js +38 -0
- package/dist/MainSidebar/mobile.js.map +1 -0
- package/dist/MainSidebar/motion.d.ts +23 -0
- package/dist/MainSidebar/motion.d.ts.map +1 -0
- package/dist/MainSidebar/motion.js +40 -0
- package/dist/MainSidebar/motion.js.map +1 -0
- package/dist/MainSidebar/rail.d.ts +24 -0
- package/dist/MainSidebar/rail.d.ts.map +1 -0
- package/dist/MainSidebar/rail.js +29 -0
- package/dist/MainSidebar/rail.js.map +1 -0
- package/dist/MainSidebar/search.d.ts +19 -0
- package/dist/MainSidebar/search.d.ts.map +1 -0
- package/dist/MainSidebar/search.js +33 -0
- package/dist/MainSidebar/search.js.map +1 -0
- package/dist/MainSidebar/types.d.ts +161 -0
- package/dist/MainSidebar/types.d.ts.map +1 -0
- package/dist/MainSidebar/types.js +2 -0
- package/dist/MainSidebar/types.js.map +1 -0
- package/dist/MainSidebar.d.ts +6 -1
- package/dist/MainSidebar.d.ts.map +1 -1
- package/dist/MainSidebar.js +6 -1
- package/dist/MainSidebar.js.map +1 -1
- package/dist/NavigationMenu.js +1 -1
- package/dist/NavigationMenu.js.map +1 -1
- package/dist/RichTextEditor/theme.d.ts +44 -0
- package/dist/RichTextEditor/theme.d.ts.map +1 -0
- package/dist/RichTextEditor/theme.js +41 -0
- package/dist/RichTextEditor/theme.js.map +1 -0
- package/dist/RichTextEditor/toolbar-icons.d.ts +21 -0
- package/dist/RichTextEditor/toolbar-icons.d.ts.map +1 -0
- package/dist/RichTextEditor/toolbar-icons.js +21 -0
- package/dist/RichTextEditor/toolbar-icons.js.map +1 -0
- package/dist/RichTextEditor/toolbar.d.ts +5 -0
- package/dist/RichTextEditor/toolbar.d.ts.map +1 -0
- package/dist/RichTextEditor/toolbar.js +116 -0
- package/dist/RichTextEditor/toolbar.js.map +1 -0
- package/dist/RichTextEditor.d.ts +16 -9
- package/dist/RichTextEditor.d.ts.map +1 -1
- package/dist/RichTextEditor.js +18 -164
- package/dist/RichTextEditor.js.map +1 -1
- package/dist/Select/content.d.ts +9 -0
- package/dist/Select/content.d.ts.map +1 -0
- package/dist/Select/content.js +80 -0
- package/dist/Select/content.js.map +1 -0
- package/dist/Select/context.d.ts +27 -0
- package/dist/Select/context.d.ts.map +1 -0
- package/dist/Select/context.js +35 -0
- package/dist/Select/context.js.map +1 -0
- package/dist/Select/item.d.ts +13 -0
- package/dist/Select/item.d.ts.map +1 -0
- package/dist/Select/item.js +39 -0
- package/dist/Select/item.js.map +1 -0
- package/dist/Select/parts.d.ts +14 -0
- package/dist/Select/parts.d.ts.map +1 -0
- package/dist/Select/parts.js +17 -0
- package/dist/Select/parts.js.map +1 -0
- package/dist/Select/react-select.d.ts +25 -0
- package/dist/Select/react-select.d.ts.map +1 -0
- package/dist/Select/react-select.js +66 -0
- package/dist/Select/react-select.js.map +1 -0
- package/dist/Select/root.d.ts +15 -0
- package/dist/Select/root.d.ts.map +1 -0
- package/dist/Select/root.js +41 -0
- package/dist/Select/root.js.map +1 -0
- package/dist/Select/trigger.d.ts +15 -0
- package/dist/Select/trigger.d.ts.map +1 -0
- package/dist/Select/trigger.js +61 -0
- package/dist/Select/trigger.js.map +1 -0
- package/dist/Select.d.ts +14 -62
- package/dist/Select.d.ts.map +1 -1
- package/dist/Select.js +14 -293
- package/dist/Select.js.map +1 -1
- package/dist/Sidebar/context.d.ts +28 -0
- package/dist/Sidebar/context.d.ts.map +1 -0
- package/dist/Sidebar/context.js +37 -0
- package/dist/Sidebar/context.js.map +1 -0
- package/dist/Sidebar/group.d.ts +13 -0
- package/dist/Sidebar/group.d.ts.map +1 -0
- package/dist/Sidebar/group.js +20 -0
- package/dist/Sidebar/group.js.map +1 -0
- package/dist/Sidebar/icons.d.ts +7 -0
- package/dist/Sidebar/icons.d.ts.map +1 -0
- package/dist/Sidebar/icons.js +12 -0
- package/dist/Sidebar/icons.js.map +1 -0
- package/dist/Sidebar/layout.d.ts +9 -0
- package/dist/Sidebar/layout.d.ts.map +1 -0
- package/dist/Sidebar/layout.js +21 -0
- package/dist/Sidebar/layout.js.map +1 -0
- package/dist/Sidebar/menu.d.ts +29 -0
- package/dist/Sidebar/menu.d.ts.map +1 -0
- package/dist/Sidebar/menu.js +55 -0
- package/dist/Sidebar/menu.js.map +1 -0
- package/dist/Sidebar/provider.d.ts +33 -0
- package/dist/Sidebar/provider.d.ts.map +1 -0
- package/dist/Sidebar/provider.js +110 -0
- package/dist/Sidebar/provider.js.map +1 -0
- package/dist/Sidebar/sidebar.d.ts +17 -0
- package/dist/Sidebar/sidebar.d.ts.map +1 -0
- package/dist/Sidebar/sidebar.js +51 -0
- package/dist/Sidebar/sidebar.js.map +1 -0
- package/dist/Sidebar/submenu.d.ts +13 -0
- package/dist/Sidebar/submenu.d.ts.map +1 -0
- package/dist/Sidebar/submenu.js +17 -0
- package/dist/Sidebar/submenu.js.map +1 -0
- package/dist/Sidebar/trigger.d.ts +9 -0
- package/dist/Sidebar/trigger.d.ts.map +1 -0
- package/dist/Sidebar/trigger.js +33 -0
- package/dist/Sidebar/trigger.js.map +1 -0
- package/dist/Sidebar.d.ts +14 -104
- package/dist/Sidebar.d.ts.map +1 -1
- package/dist/Sidebar.js +14 -300
- package/dist/Sidebar.js.map +1 -1
- package/dist/StatCard.d.ts +67 -9
- package/dist/StatCard.d.ts.map +1 -1
- package/dist/StatCard.js +111 -9
- package/dist/StatCard.js.map +1 -1
- package/dist/TransferList.native.d.ts.map +1 -1
- package/dist/TransferList.native.js +2 -1
- package/dist/TransferList.native.js.map +1 -1
- package/package.json +2 -2
- package/src/CheckboxGrid.native.tsx +2 -1
- package/src/Combobox.native.tsx +2 -1
- package/src/DataTable/column-filter.tsx +134 -0
- package/src/DataTable/column-header.tsx +67 -0
- package/src/DataTable/column-visibility.tsx +87 -0
- package/src/DataTable/index.ts +4 -0
- package/src/DataTable/pinning.ts +40 -0
- package/src/DataTable.tsx +14 -297
- package/src/Dialog.native.tsx +4 -2
- package/src/Form/building-blocks.tsx +97 -0
- package/src/Form/fields-choice.tsx +312 -0
- package/src/Form/fields-complex.tsx +195 -0
- package/src/Form/fields-date.tsx +195 -0
- package/src/Form/fields-text.tsx +218 -0
- package/src/Form/fields-toggle.tsx +123 -0
- package/src/Form/helpers.tsx +189 -0
- package/src/Form/types.ts +26 -0
- package/src/Form.tsx +91 -1308
- package/src/IconSidebar.tsx +20 -442
- package/src/MainSidebar/back-button.tsx +58 -0
- package/src/MainSidebar/breadcrumb.tsx +53 -0
- package/src/MainSidebar/columns.tsx +350 -0
- package/src/MainSidebar/command.tsx +404 -0
- package/src/MainSidebar/drilldown.tsx +373 -0
- package/src/MainSidebar/expanded.tsx +414 -0
- package/src/MainSidebar/floating.tsx +268 -0
- package/src/MainSidebar/helpers.ts +166 -0
- package/src/MainSidebar/hover.tsx +334 -0
- package/src/MainSidebar/index.tsx +191 -0
- package/src/MainSidebar/mobile.tsx +117 -0
- package/src/MainSidebar/motion.ts +64 -0
- package/src/MainSidebar/rail.tsx +137 -0
- package/src/MainSidebar/search.tsx +99 -0
- package/src/MainSidebar/types.ts +208 -0
- package/src/MainSidebar.tsx +15 -4
- package/src/NavigationMenu.tsx +1 -1
- package/src/RichTextEditor/theme.ts +43 -0
- package/src/RichTextEditor/toolbar-icons.tsx +40 -0
- package/src/RichTextEditor/toolbar.tsx +271 -0
- package/src/RichTextEditor.tsx +23 -371
- package/src/Select/content.tsx +111 -0
- package/src/Select/context.tsx +66 -0
- package/src/Select/item.tsx +97 -0
- package/src/Select/parts.tsx +43 -0
- package/src/Select/react-select.tsx +216 -0
- package/src/Select/root.tsx +75 -0
- package/src/Select/trigger.tsx +122 -0
- package/src/Select.tsx +34 -692
- package/src/Sidebar/context.tsx +72 -0
- package/src/Sidebar/group.tsx +69 -0
- package/src/Sidebar/icons.tsx +42 -0
- package/src/Sidebar/layout.tsx +64 -0
- package/src/Sidebar/menu.tsx +171 -0
- package/src/Sidebar/provider.tsx +224 -0
- package/src/Sidebar/sidebar.tsx +178 -0
- package/src/Sidebar/submenu.tsx +58 -0
- package/src/Sidebar/trigger.tsx +104 -0
- package/src/Sidebar.tsx +44 -927
- package/src/StatCard.tsx +365 -20
- package/src/TransferList.native.tsx +2 -1
- package/dist/TiptapEditor.d.ts +0 -24
- package/dist/TiptapEditor.d.ts.map +0 -1
- package/dist/TiptapEditor.js +0 -84
- package/dist/TiptapEditor.js.map +0 -1
package/src/DataTable.tsx
CHANGED
|
@@ -15,7 +15,6 @@ import {
|
|
|
15
15
|
Fragment,
|
|
16
16
|
useState,
|
|
17
17
|
useMemo,
|
|
18
|
-
useCallback,
|
|
19
18
|
useEffect,
|
|
20
19
|
useRef,
|
|
21
20
|
type ReactNode,
|
|
@@ -64,268 +63,21 @@ import { Button } from './Button.js';
|
|
|
64
63
|
import { Checkbox } from './Checkbox.js';
|
|
65
64
|
import { Select, SelectTrigger, SelectContent, SelectItem } from './Select.js';
|
|
66
65
|
import { cn } from './internal/cn.js';
|
|
66
|
+
import {
|
|
67
|
+
ColumnFilterInput,
|
|
68
|
+
ColumnVisibilityDropdown,
|
|
69
|
+
DataTableColumnHeader,
|
|
70
|
+
getCellPinningStyles,
|
|
71
|
+
getPinningStyles,
|
|
72
|
+
} from './DataTable/index.js';
|
|
73
|
+
|
|
74
|
+
export { DataTableColumnHeader };
|
|
67
75
|
|
|
68
76
|
/* ── Re-export for consumer convenience ───────────────────────────── */
|
|
69
77
|
|
|
70
78
|
export { createColumnHelper };
|
|
71
79
|
export type { ColumnDef, Row, RowSelectionState, TableVariant };
|
|
72
80
|
|
|
73
|
-
/* ── DataTableColumnHeader ────────────────────────────────────────── */
|
|
74
|
-
|
|
75
|
-
interface DataTableColumnHeaderProps<TData, TValue> {
|
|
76
|
-
column: Column<TData, TValue>;
|
|
77
|
-
title: string;
|
|
78
|
-
className?: string;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
export function DataTableColumnHeader<TData, TValue>({
|
|
82
|
-
column,
|
|
83
|
-
title,
|
|
84
|
-
className,
|
|
85
|
-
}: DataTableColumnHeaderProps<TData, TValue>) {
|
|
86
|
-
if (!column.getCanSort()) {
|
|
87
|
-
return <span className={className}>{title}</span>;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
const sorted = column.getIsSorted();
|
|
91
|
-
|
|
92
|
-
return (
|
|
93
|
-
<button
|
|
94
|
-
type="button"
|
|
95
|
-
className={cn(
|
|
96
|
-
'inline-flex items-center gap-1 -ml-1 px-1 py-0.5 rounded-md',
|
|
97
|
-
'hover:bg-muted transition-colors duration-150',
|
|
98
|
-
'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring',
|
|
99
|
-
className,
|
|
100
|
-
)}
|
|
101
|
-
onClick={column.getToggleSortingHandler()}
|
|
102
|
-
aria-label={`Sort by ${title}`}
|
|
103
|
-
>
|
|
104
|
-
{title}
|
|
105
|
-
<span className="inline-flex flex-col" aria-hidden>
|
|
106
|
-
<svg
|
|
107
|
-
viewBox="0 0 8 4"
|
|
108
|
-
className={cn(
|
|
109
|
-
'h-1.5 w-2 transition-transform duration-200',
|
|
110
|
-
sorted === 'asc' ? 'text-foreground' : 'text-muted-foreground/40',
|
|
111
|
-
)}
|
|
112
|
-
fill="currentColor"
|
|
113
|
-
>
|
|
114
|
-
<path d="M4 0L8 4H0z" />
|
|
115
|
-
</svg>
|
|
116
|
-
<svg
|
|
117
|
-
viewBox="0 0 8 4"
|
|
118
|
-
className={cn(
|
|
119
|
-
'h-1.5 w-2 transition-transform duration-200',
|
|
120
|
-
sorted === 'desc' ? 'text-foreground' : 'text-muted-foreground/40',
|
|
121
|
-
)}
|
|
122
|
-
fill="currentColor"
|
|
123
|
-
>
|
|
124
|
-
<path d="M4 4L0 0h8z" />
|
|
125
|
-
</svg>
|
|
126
|
-
</span>
|
|
127
|
-
</button>
|
|
128
|
-
);
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
/* ── Column visibility dropdown ───────────────────────────────────── */
|
|
132
|
-
|
|
133
|
-
function ColumnVisibilityDropdown<TData>({
|
|
134
|
-
table,
|
|
135
|
-
}: {
|
|
136
|
-
table: TanStackTable<TData>;
|
|
137
|
-
}) {
|
|
138
|
-
const [open, setOpen] = useState(false);
|
|
139
|
-
const ref = useRef<HTMLDivElement>(null);
|
|
140
|
-
|
|
141
|
-
useEffect(() => {
|
|
142
|
-
if (!open) return;
|
|
143
|
-
function handleClick(e: MouseEvent) {
|
|
144
|
-
if (ref.current && !ref.current.contains(e.target as Node)) {
|
|
145
|
-
setOpen(false);
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
document.addEventListener('mousedown', handleClick);
|
|
149
|
-
return () => document.removeEventListener('mousedown', handleClick);
|
|
150
|
-
}, [open]);
|
|
151
|
-
|
|
152
|
-
return (
|
|
153
|
-
<div ref={ref} className="relative">
|
|
154
|
-
<Button
|
|
155
|
-
variant="outline"
|
|
156
|
-
size="sm"
|
|
157
|
-
onClick={() => setOpen(!open)}
|
|
158
|
-
aria-expanded={open}
|
|
159
|
-
aria-haspopup="true"
|
|
160
|
-
>
|
|
161
|
-
<svg
|
|
162
|
-
aria-hidden
|
|
163
|
-
viewBox="0 0 24 24"
|
|
164
|
-
fill="none"
|
|
165
|
-
stroke="currentColor"
|
|
166
|
-
strokeWidth={2}
|
|
167
|
-
className="h-4 w-4"
|
|
168
|
-
>
|
|
169
|
-
<path
|
|
170
|
-
strokeLinecap="round"
|
|
171
|
-
strokeLinejoin="round"
|
|
172
|
-
d="M10.5 6h9.75M10.5 6a1.5 1.5 0 11-3 0m3 0a1.5 1.5 0 10-3 0M3.75 6H7.5m3 12h9.75m-9.75 0a1.5 1.5 0 01-3 0m3 0a1.5 1.5 0 00-3 0m-3.75 0H7.5m9-6h3.75m-3.75 0a1.5 1.5 0 01-3 0m3 0a1.5 1.5 0 00-3 0m-9.75 0h9.75"
|
|
173
|
-
/>
|
|
174
|
-
</svg>
|
|
175
|
-
Columns
|
|
176
|
-
</Button>
|
|
177
|
-
{open && (
|
|
178
|
-
<div className="absolute right-0 top-full z-50 mt-1 min-w-[10rem] rounded-lg border border-border bg-card p-1 shadow-md">
|
|
179
|
-
{table.getAllLeafColumns().map((column) => {
|
|
180
|
-
if (column.id === 'select' || column.id === 'expand') return null;
|
|
181
|
-
return (
|
|
182
|
-
<label
|
|
183
|
-
key={column.id}
|
|
184
|
-
className="flex cursor-pointer items-center gap-2 rounded-md px-2 py-1.5 text-sm hover:bg-muted transition-colors duration-150"
|
|
185
|
-
>
|
|
186
|
-
<Checkbox
|
|
187
|
-
size="sm"
|
|
188
|
-
checked={column.getIsVisible()}
|
|
189
|
-
onCheckedChange={(v) => column.toggleVisibility(!!v)}
|
|
190
|
-
/>
|
|
191
|
-
<span className="capitalize">
|
|
192
|
-
{typeof column.columnDef.header === 'string'
|
|
193
|
-
? column.columnDef.header
|
|
194
|
-
: column.id}
|
|
195
|
-
</span>
|
|
196
|
-
</label>
|
|
197
|
-
);
|
|
198
|
-
})}
|
|
199
|
-
</div>
|
|
200
|
-
)}
|
|
201
|
-
</div>
|
|
202
|
-
);
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
/* ── Column filter input ──────────────────────────────────────────── */
|
|
206
|
-
|
|
207
|
-
function ColumnFilterInput<TData>({
|
|
208
|
-
column,
|
|
209
|
-
faceted,
|
|
210
|
-
}: {
|
|
211
|
-
column: Column<TData, unknown>;
|
|
212
|
-
faceted: boolean;
|
|
213
|
-
}) {
|
|
214
|
-
const columnFilterValue = column.getFilterValue();
|
|
215
|
-
const [open, setOpen] = useState(false);
|
|
216
|
-
const ref = useRef<HTMLDivElement>(null);
|
|
217
|
-
|
|
218
|
-
/* Close faceted dropdown on outside click */
|
|
219
|
-
useEffect(() => {
|
|
220
|
-
if (!open) return;
|
|
221
|
-
function handleClick(e: MouseEvent) {
|
|
222
|
-
if (ref.current && !ref.current.contains(e.target as Node)) {
|
|
223
|
-
setOpen(false);
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
document.addEventListener('mousedown', handleClick);
|
|
227
|
-
return () => document.removeEventListener('mousedown', handleClick);
|
|
228
|
-
}, [open]);
|
|
229
|
-
|
|
230
|
-
/* Faceted: number column → min/max range */
|
|
231
|
-
if (faceted) {
|
|
232
|
-
const facetedMinMax = column.getFacetedMinMaxValues?.();
|
|
233
|
-
const isNumberColumn =
|
|
234
|
-
facetedMinMax !== undefined &&
|
|
235
|
-
facetedMinMax[0] !== undefined &&
|
|
236
|
-
typeof facetedMinMax[0] === 'number';
|
|
237
|
-
|
|
238
|
-
if (isNumberColumn) {
|
|
239
|
-
const [min, max] = facetedMinMax as [number, number];
|
|
240
|
-
const currentRange = (columnFilterValue as [number, number] | undefined) ?? [
|
|
241
|
-
undefined,
|
|
242
|
-
undefined,
|
|
243
|
-
];
|
|
244
|
-
return (
|
|
245
|
-
<div className="grid min-w-[10rem] grid-cols-2 gap-1">
|
|
246
|
-
<Input
|
|
247
|
-
type="number"
|
|
248
|
-
value={currentRange[0] ?? ''}
|
|
249
|
-
onChange={(e) => {
|
|
250
|
-
const val = e.target.value ? Number(e.target.value) : undefined;
|
|
251
|
-
column.setFilterValue((old: [number, number] | undefined) => [
|
|
252
|
-
val,
|
|
253
|
-
old?.[1],
|
|
254
|
-
]);
|
|
255
|
-
}}
|
|
256
|
-
placeholder={`Min (${min})`}
|
|
257
|
-
className="h-8 min-w-0 bg-background px-2 text-xs shadow-mi-input"
|
|
258
|
-
/>
|
|
259
|
-
<Input
|
|
260
|
-
type="number"
|
|
261
|
-
value={currentRange[1] ?? ''}
|
|
262
|
-
onChange={(e) => {
|
|
263
|
-
const val = e.target.value ? Number(e.target.value) : undefined;
|
|
264
|
-
column.setFilterValue((old: [number, number] | undefined) => [
|
|
265
|
-
old?.[0],
|
|
266
|
-
val,
|
|
267
|
-
]);
|
|
268
|
-
}}
|
|
269
|
-
placeholder={`Max (${max})`}
|
|
270
|
-
className="h-8 min-w-0 bg-background px-2 text-xs shadow-mi-input"
|
|
271
|
-
/>
|
|
272
|
-
</div>
|
|
273
|
-
);
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
/* Faceted: string column → unique values list */
|
|
277
|
-
const uniqueValues = column.getFacetedUniqueValues?.();
|
|
278
|
-
if (uniqueValues && uniqueValues.size > 0) {
|
|
279
|
-
const sortedValues = Array.from(uniqueValues.keys())
|
|
280
|
-
.filter((v): v is string => typeof v === 'string')
|
|
281
|
-
.sort();
|
|
282
|
-
return (
|
|
283
|
-
<div ref={ref} className="relative">
|
|
284
|
-
<Input
|
|
285
|
-
type="text"
|
|
286
|
-
value={(columnFilterValue as string) ?? ''}
|
|
287
|
-
onChange={(e) => column.setFilterValue(e.target.value || undefined)}
|
|
288
|
-
onFocus={() => setOpen(true)}
|
|
289
|
-
placeholder="Filter..."
|
|
290
|
-
className="h-8 min-w-[8rem] bg-background px-2 text-xs shadow-mi-input"
|
|
291
|
-
/>
|
|
292
|
-
{open && sortedValues.length > 0 && (
|
|
293
|
-
<div className="absolute left-0 top-full z-50 mt-1 max-h-40 min-w-full overflow-y-auto rounded-md border border-border bg-card p-1 shadow-mi-modal">
|
|
294
|
-
{sortedValues.map((val) => (
|
|
295
|
-
<button
|
|
296
|
-
key={val}
|
|
297
|
-
type="button"
|
|
298
|
-
className="block w-full rounded px-2 py-1 text-left text-xs hover:bg-muted transition-colors duration-150"
|
|
299
|
-
onClick={() => {
|
|
300
|
-
column.setFilterValue(val);
|
|
301
|
-
setOpen(false);
|
|
302
|
-
}}
|
|
303
|
-
>
|
|
304
|
-
{val}{' '}
|
|
305
|
-
<span className="text-muted-foreground">
|
|
306
|
-
({uniqueValues.get(val)})
|
|
307
|
-
</span>
|
|
308
|
-
</button>
|
|
309
|
-
))}
|
|
310
|
-
</div>
|
|
311
|
-
)}
|
|
312
|
-
</div>
|
|
313
|
-
);
|
|
314
|
-
}
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
/* Default: simple text input */
|
|
318
|
-
return (
|
|
319
|
-
<Input
|
|
320
|
-
type="text"
|
|
321
|
-
value={(columnFilterValue as string) ?? ''}
|
|
322
|
-
onChange={(e) => column.setFilterValue(e.target.value || undefined)}
|
|
323
|
-
placeholder="Filter..."
|
|
324
|
-
className="h-8 min-w-[8rem] bg-background px-2 text-xs shadow-mi-input"
|
|
325
|
-
/>
|
|
326
|
-
);
|
|
327
|
-
}
|
|
328
|
-
|
|
329
81
|
/* ── DataTable ────────────────────────────────────────────────────── */
|
|
330
82
|
|
|
331
83
|
export interface DataTableProps<TData, TValue> {
|
|
@@ -608,41 +360,6 @@ export function DataTable<TData, TValue>({
|
|
|
608
360
|
? virtualRows.map((virtualRow) => regularRows[virtualRow.index]).filter((row): row is Row<TData> => Boolean(row))
|
|
609
361
|
: regularRows;
|
|
610
362
|
|
|
611
|
-
/* ── Pinning style helper ──────────────────────────────────────── */
|
|
612
|
-
const getPinningStyles = useCallback(
|
|
613
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
614
|
-
(header: Header<any, unknown>): React.CSSProperties => {
|
|
615
|
-
if (!columnPinnable) return {};
|
|
616
|
-
const isPinned = header.column.getIsPinned();
|
|
617
|
-
if (!isPinned) return {};
|
|
618
|
-
return {
|
|
619
|
-
position: 'sticky',
|
|
620
|
-
left: isPinned === 'left' ? `${header.getStart('left')}px` : undefined,
|
|
621
|
-
right: isPinned === 'right' ? `${header.getStart('right')}px` : undefined,
|
|
622
|
-
zIndex: 1,
|
|
623
|
-
backgroundColor: 'var(--color-card, #fff)',
|
|
624
|
-
};
|
|
625
|
-
},
|
|
626
|
-
[columnPinnable],
|
|
627
|
-
);
|
|
628
|
-
|
|
629
|
-
const getCellPinningStyles = useCallback(
|
|
630
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
631
|
-
(cell: { column: Column<any, unknown> }): React.CSSProperties => {
|
|
632
|
-
if (!columnPinnable) return {};
|
|
633
|
-
const isPinned = cell.column.getIsPinned();
|
|
634
|
-
if (!isPinned) return {};
|
|
635
|
-
return {
|
|
636
|
-
position: 'sticky',
|
|
637
|
-
left: isPinned === 'left' ? `${cell.column.getStart('left')}px` : undefined,
|
|
638
|
-
right: isPinned === 'right' ? `${cell.column.getStart('right')}px` : undefined,
|
|
639
|
-
zIndex: 1,
|
|
640
|
-
backgroundColor: 'var(--color-card, #fff)',
|
|
641
|
-
};
|
|
642
|
-
},
|
|
643
|
-
[columnPinnable],
|
|
644
|
-
);
|
|
645
|
-
|
|
646
363
|
/* ── Render ─────────────────────────────────────────────────────── */
|
|
647
364
|
return (
|
|
648
365
|
<div className={cn('w-full space-y-4', className)}>
|
|
@@ -705,7 +422,7 @@ export function DataTable<TData, TValue>({
|
|
|
705
422
|
colSpan={header.colSpan}
|
|
706
423
|
style={{
|
|
707
424
|
width: resizable ? header.getSize() : (header.getSize() !== 150 ? header.getSize() : undefined),
|
|
708
|
-
...getPinningStyles(header),
|
|
425
|
+
...getPinningStyles(header, columnPinnable),
|
|
709
426
|
}}
|
|
710
427
|
className={cn(
|
|
711
428
|
'h-12 whitespace-nowrap px-3 py-2 align-middle',
|
|
@@ -786,7 +503,7 @@ export function DataTable<TData, TValue>({
|
|
|
786
503
|
colSpan={header.colSpan}
|
|
787
504
|
style={{
|
|
788
505
|
width: resizable ? header.getSize() : (header.getSize() !== 150 ? header.getSize() : undefined),
|
|
789
|
-
...getPinningStyles(header),
|
|
506
|
+
...getPinningStyles(header, columnPinnable),
|
|
790
507
|
}}
|
|
791
508
|
className={cn(
|
|
792
509
|
'h-12 border-t border-border px-3 py-2 align-middle',
|
|
@@ -816,7 +533,7 @@ export function DataTable<TData, TValue>({
|
|
|
816
533
|
className="bg-muted/30"
|
|
817
534
|
>
|
|
818
535
|
{row.getVisibleCells().map((cell) => (
|
|
819
|
-
<TableCell key={cell.id} style={getCellPinningStyles(cell)}>
|
|
536
|
+
<TableCell key={cell.id} style={getCellPinningStyles(cell, columnPinnable)}>
|
|
820
537
|
{flexRender(cell.column.columnDef.cell, cell.getContext())}
|
|
821
538
|
</TableCell>
|
|
822
539
|
))}
|
|
@@ -838,7 +555,7 @@ export function DataTable<TData, TValue>({
|
|
|
838
555
|
data-state={row.getIsSelected() ? 'selected' : undefined}
|
|
839
556
|
>
|
|
840
557
|
{row.getVisibleCells().map((cell) => (
|
|
841
|
-
<TableCell key={cell.id} style={getCellPinningStyles(cell)}>
|
|
558
|
+
<TableCell key={cell.id} style={getCellPinningStyles(cell, columnPinnable)}>
|
|
842
559
|
{/* Grouped cell rendering */}
|
|
843
560
|
{groupable && cell.getIsGrouped() ? (
|
|
844
561
|
<button
|
|
@@ -913,7 +630,7 @@ export function DataTable<TData, TValue>({
|
|
|
913
630
|
className="bg-muted/30"
|
|
914
631
|
>
|
|
915
632
|
{row.getVisibleCells().map((cell) => (
|
|
916
|
-
<TableCell key={cell.id} style={getCellPinningStyles(cell)}>
|
|
633
|
+
<TableCell key={cell.id} style={getCellPinningStyles(cell, columnPinnable)}>
|
|
917
634
|
{flexRender(cell.column.columnDef.cell, cell.getContext())}
|
|
918
635
|
</TableCell>
|
|
919
636
|
))}
|
package/src/Dialog.native.tsx
CHANGED
|
@@ -38,9 +38,11 @@ export interface DialogProps {
|
|
|
38
38
|
open: boolean;
|
|
39
39
|
onOpenChange: (open: boolean) => void;
|
|
40
40
|
children: ReactNode;
|
|
41
|
+
/** Tailwind classes applied to the backdrop. Mirrors the web Dialog root. */
|
|
42
|
+
className?: string;
|
|
41
43
|
}
|
|
42
44
|
|
|
43
|
-
export function Dialog({ open, onOpenChange, children }: DialogProps) {
|
|
45
|
+
export function Dialog({ open, onOpenChange, children, className }: DialogProps) {
|
|
44
46
|
return (
|
|
45
47
|
<Modal
|
|
46
48
|
visible={open}
|
|
@@ -51,7 +53,7 @@ export function Dialog({ open, onOpenChange, children }: DialogProps) {
|
|
|
51
53
|
>
|
|
52
54
|
<Pressable
|
|
53
55
|
onPress={() => onOpenChange(false)}
|
|
54
|
-
className=
|
|
56
|
+
className={cn('flex-1 items-center justify-center bg-black/50', className)}
|
|
55
57
|
accessibilityRole="none"
|
|
56
58
|
>
|
|
57
59
|
<Pressable onPress={(e) => e.stopPropagation()}>
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Form building blocks — layout and accessibility scaffolding you compose
|
|
5
|
+
* freely around any control: FormItem, FormLabel, FormDescription, FormMessage.
|
|
6
|
+
*/
|
|
7
|
+
import { type HTMLAttributes } from 'react';
|
|
8
|
+
import { cn } from '../internal/cn.js';
|
|
9
|
+
import { Label } from '../Label.js';
|
|
10
|
+
|
|
11
|
+
/* ── FormItem ─────────────────────────────────────────────────────── */
|
|
12
|
+
|
|
13
|
+
export interface FormItemProps extends HTMLAttributes<HTMLDivElement> {}
|
|
14
|
+
|
|
15
|
+
/** Vertical stack container for label + control + description + error. */
|
|
16
|
+
export function FormItem({ className, children, ...props }: FormItemProps) {
|
|
17
|
+
return (
|
|
18
|
+
<div className={cn('flex flex-col gap-1.5', className)} {...props}>
|
|
19
|
+
{children}
|
|
20
|
+
</div>
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/* ── FormLabel ────────────────────────────────────────────────────── */
|
|
25
|
+
|
|
26
|
+
export interface FormLabelProps extends HTMLAttributes<HTMLLabelElement> {
|
|
27
|
+
htmlFor?: string;
|
|
28
|
+
required?: boolean;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/** Styled label with optional required asterisk. Delegates to the existing Label primitive. */
|
|
32
|
+
export function FormLabel({ htmlFor, required, className, children, ...props }: FormLabelProps) {
|
|
33
|
+
return (
|
|
34
|
+
<Label
|
|
35
|
+
{...(htmlFor !== undefined && { htmlFor })}
|
|
36
|
+
{...(required !== undefined && { required })}
|
|
37
|
+
{...(className !== undefined && { className })}
|
|
38
|
+
{...props}
|
|
39
|
+
>
|
|
40
|
+
{children}
|
|
41
|
+
</Label>
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/* ── FormDescription ──────────────────────────────────────────────── */
|
|
46
|
+
|
|
47
|
+
export interface FormDescriptionProps extends HTMLAttributes<HTMLParagraphElement> {}
|
|
48
|
+
|
|
49
|
+
/** Muted helper text rendered below the control. */
|
|
50
|
+
export function FormDescription({ className, children, ...props }: FormDescriptionProps) {
|
|
51
|
+
return (
|
|
52
|
+
<p className={cn('text-xs text-muted-foreground', className)} {...props}>
|
|
53
|
+
{children}
|
|
54
|
+
</p>
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/* ── FormMessage ──────────────────────────────────────────────────── */
|
|
59
|
+
|
|
60
|
+
export interface FormMessageProps extends HTMLAttributes<HTMLParagraphElement> {
|
|
61
|
+
/** Array of error strings — only the first is displayed. */
|
|
62
|
+
errors?: string[];
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/** Error message display with warning icon. Transitions in/out smoothly. */
|
|
66
|
+
export function FormMessage({ errors, className, ...props }: FormMessageProps) {
|
|
67
|
+
const firstError = errors?.filter(Boolean)[0];
|
|
68
|
+
if (!firstError) return null;
|
|
69
|
+
|
|
70
|
+
return (
|
|
71
|
+
<p
|
|
72
|
+
role="alert"
|
|
73
|
+
className={cn(
|
|
74
|
+
'flex items-center gap-1 text-xs text-destructive',
|
|
75
|
+
'transition-all duration-150',
|
|
76
|
+
className,
|
|
77
|
+
)}
|
|
78
|
+
{...props}
|
|
79
|
+
>
|
|
80
|
+
<svg
|
|
81
|
+
aria-hidden="true"
|
|
82
|
+
viewBox="0 0 16 16"
|
|
83
|
+
fill="none"
|
|
84
|
+
stroke="currentColor"
|
|
85
|
+
strokeWidth={1.5}
|
|
86
|
+
strokeLinecap="round"
|
|
87
|
+
strokeLinejoin="round"
|
|
88
|
+
className="h-3.5 w-3.5 shrink-0"
|
|
89
|
+
>
|
|
90
|
+
<path d="M8 2L1.5 13h13L8 2z" />
|
|
91
|
+
<path d="M8 6v3" />
|
|
92
|
+
<circle cx="8" cy="11" r="0.5" fill="currentColor" stroke="none" />
|
|
93
|
+
</svg>
|
|
94
|
+
{firstError}
|
|
95
|
+
</p>
|
|
96
|
+
);
|
|
97
|
+
}
|