@multicomma/arkcn 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +78 -0
- package/bin/arkcn.mjs +78 -0
- package/cli/commands.mjs +251 -0
- package/cli/project.mjs +168 -0
- package/cli/registry.mjs +50 -0
- package/cli/ui.mjs +46 -0
- package/mcp/server.mjs +149 -0
- package/package.json +201 -0
- package/registry/base.css +680 -0
- package/registry/index.json +1833 -0
- package/registry/items/accordion.json +18 -0
- package/registry/items/activity-feed.json +18 -0
- package/registry/items/alert-dialog.json +18 -0
- package/registry/items/alert.json +17 -0
- package/registry/items/angle-slider.json +17 -0
- package/registry/items/app-shell.json +28 -0
- package/registry/items/aspect-ratio.json +13 -0
- package/registry/items/attachment.json +19 -0
- package/registry/items/avatar.json +17 -0
- package/registry/items/badge.json +18 -0
- package/registry/items/breadcrumb.json +18 -0
- package/registry/items/bubble.json +18 -0
- package/registry/items/button-group.json +19 -0
- package/registry/items/button.json +18 -0
- package/registry/items/calendar.json +19 -0
- package/registry/items/canvas.json +24 -0
- package/registry/items/card.json +15 -0
- package/registry/items/carousel.json +19 -0
- package/registry/items/cascader.json +23 -0
- package/registry/items/chart.json +17 -0
- package/registry/items/chat.json +23 -0
- package/registry/items/checkbox.json +18 -0
- package/registry/items/clipboard.json +19 -0
- package/registry/items/collapsible.json +15 -0
- package/registry/items/color-picker.json +19 -0
- package/registry/items/combobox.json +20 -0
- package/registry/items/command.json +21 -0
- package/registry/items/comment-thread.json +25 -0
- package/registry/items/context-menu.json +18 -0
- package/registry/items/controllable.json +14 -0
- package/registry/items/data-grid.json +24 -0
- package/registry/items/data-table-adapter.json +14 -0
- package/registry/items/data-table.json +32 -0
- package/registry/items/date-input.json +17 -0
- package/registry/items/dialog.json +19 -0
- package/registry/items/direction.json +13 -0
- package/registry/items/drag-preview.json +16 -0
- package/registry/items/drawer.json +18 -0
- package/registry/items/dropdown-menu.json +18 -0
- package/registry/items/editable.json +17 -0
- package/registry/items/empty.json +17 -0
- package/registry/items/field.json +19 -0
- package/registry/items/file-upload.json +19 -0
- package/registry/items/floating-panel.json +19 -0
- package/registry/items/floating-toolbar.json +16 -0
- package/registry/items/form.json +14 -0
- package/registry/items/format.json +15 -0
- package/registry/items/gantt.json +22 -0
- package/registry/items/history.json +14 -0
- package/registry/items/hotkeys.json +18 -0
- package/registry/items/hover-card.json +17 -0
- package/registry/items/image-cropper.json +17 -0
- package/registry/items/input-group.json +20 -0
- package/registry/items/input-otp.json +18 -0
- package/registry/items/input.json +15 -0
- package/registry/items/item.json +19 -0
- package/registry/items/json-tree-view.json +17 -0
- package/registry/items/kanban.json +26 -0
- package/registry/items/kbd.json +15 -0
- package/registry/items/label.json +15 -0
- package/registry/items/live-region.json +16 -0
- package/registry/items/marker.json +18 -0
- package/registry/items/marquee.json +17 -0
- package/registry/items/menubar.json +19 -0
- package/registry/items/message.json +15 -0
- package/registry/items/navigation-menu.json +19 -0
- package/registry/items/node-graph.json +22 -0
- package/registry/items/number-input.json +18 -0
- package/registry/items/pagination.json +18 -0
- package/registry/items/password-input.json +18 -0
- package/registry/items/popconfirm.json +20 -0
- package/registry/items/popover.json +18 -0
- package/registry/items/progress.json +17 -0
- package/registry/items/qr-code.json +17 -0
- package/registry/items/query-builder.json +23 -0
- package/registry/items/radio-group.json +17 -0
- package/registry/items/rating-group.json +18 -0
- package/registry/items/resizable.json +17 -0
- package/registry/items/rich-text-editor.json +37 -0
- package/registry/items/row-layout.json +15 -0
- package/registry/items/scheduler.json +23 -0
- package/registry/items/scroll-area.json +17 -0
- package/registry/items/segment-group.json +17 -0
- package/registry/items/select.json +19 -0
- package/registry/items/separator.json +15 -0
- package/registry/items/sheet.json +19 -0
- package/registry/items/sidebar.json +27 -0
- package/registry/items/signature-pad.json +19 -0
- package/registry/items/skeleton.json +15 -0
- package/registry/items/slider.json +17 -0
- package/registry/items/sonner.json +17 -0
- package/registry/items/spinner.json +17 -0
- package/registry/items/steps.json +19 -0
- package/registry/items/swap.json +17 -0
- package/registry/items/switch.json +17 -0
- package/registry/items/table.json +16 -0
- package/registry/items/tabs.json +18 -0
- package/registry/items/tags-input.json +18 -0
- package/registry/items/textarea.json +15 -0
- package/registry/items/time.json +14 -0
- package/registry/items/timer.json +18 -0
- package/registry/items/toc.json +17 -0
- package/registry/items/toggle-group.json +19 -0
- package/registry/items/toggle.json +18 -0
- package/registry/items/tooltip.json +17 -0
- package/registry/items/tour.json +19 -0
- package/registry/items/transfer-list.json +24 -0
- package/registry/items/tree-select.json +24 -0
- package/registry/items/tree-view.json +18 -0
- package/registry/items/use-mobile.json +13 -0
- package/registry/items/utils.json +17 -0
- package/registry/items/virtual-list.json +16 -0
- package/src/components/ui/accordion.tsx +111 -0
- package/src/components/ui/activity-feed.tsx +228 -0
- package/src/components/ui/alert-dialog.tsx +204 -0
- package/src/components/ui/alert.tsx +55 -0
- package/src/components/ui/angle-slider.tsx +117 -0
- package/src/components/ui/app-shell.tsx +985 -0
- package/src/components/ui/aspect-ratio.tsx +35 -0
- package/src/components/ui/attachment.tsx +193 -0
- package/src/components/ui/avatar.tsx +94 -0
- package/src/components/ui/badge.tsx +45 -0
- package/src/components/ui/breadcrumb.tsx +93 -0
- package/src/components/ui/bubble.tsx +119 -0
- package/src/components/ui/button-group.tsx +79 -0
- package/src/components/ui/button.tsx +65 -0
- package/src/components/ui/calendar.tsx +172 -0
- package/src/components/ui/canvas.tsx +723 -0
- package/src/components/ui/card.tsx +69 -0
- package/src/components/ui/carousel.tsx +228 -0
- package/src/components/ui/cascader.tsx +754 -0
- package/src/components/ui/chart.tsx +303 -0
- package/src/components/ui/chat.tsx +544 -0
- package/src/components/ui/checkbox.tsx +94 -0
- package/src/components/ui/clipboard.tsx +94 -0
- package/src/components/ui/collapsible.tsx +32 -0
- package/src/components/ui/color-picker.tsx +441 -0
- package/src/components/ui/combobox.tsx +400 -0
- package/src/components/ui/command.tsx +292 -0
- package/src/components/ui/comment-thread.tsx +923 -0
- package/src/components/ui/context-menu.tsx +331 -0
- package/src/components/ui/data-grid.tsx +1227 -0
- package/src/components/ui/data-table.tsx +993 -0
- package/src/components/ui/date-input.tsx +103 -0
- package/src/components/ui/dialog.tsx +159 -0
- package/src/components/ui/direction.tsx +32 -0
- package/src/components/ui/drawer.tsx +200 -0
- package/src/components/ui/dropdown-menu.tsx +329 -0
- package/src/components/ui/editable.tsx +90 -0
- package/src/components/ui/empty.tsx +86 -0
- package/src/components/ui/field.tsx +218 -0
- package/src/components/ui/file-upload.tsx +204 -0
- package/src/components/ui/floating-panel.tsx +199 -0
- package/src/components/ui/floating-toolbar.tsx +79 -0
- package/src/components/ui/format.tsx +22 -0
- package/src/components/ui/gantt.tsx +950 -0
- package/src/components/ui/hotkeys.tsx +340 -0
- package/src/components/ui/hover-card.tsx +83 -0
- package/src/components/ui/image-cropper.tsx +100 -0
- package/src/components/ui/input-group.tsx +133 -0
- package/src/components/ui/input-otp.tsx +82 -0
- package/src/components/ui/input.tsx +18 -0
- package/src/components/ui/item.tsx +174 -0
- package/src/components/ui/json-tree-view.tsx +37 -0
- package/src/components/ui/kanban.tsx +884 -0
- package/src/components/ui/kbd.tsx +20 -0
- package/src/components/ui/label.tsx +30 -0
- package/src/components/ui/live-region.tsx +54 -0
- package/src/components/ui/marker.tsx +66 -0
- package/src/components/ui/marquee.tsx +61 -0
- package/src/components/ui/menubar.tsx +456 -0
- package/src/components/ui/message.tsx +74 -0
- package/src/components/ui/navigation-menu.tsx +202 -0
- package/src/components/ui/node-graph.tsx +1723 -0
- package/src/components/ui/number-input.tsx +148 -0
- package/src/components/ui/pagination.tsx +88 -0
- package/src/components/ui/password-input.tsx +104 -0
- package/src/components/ui/popconfirm.tsx +149 -0
- package/src/components/ui/popover.tsx +126 -0
- package/src/components/ui/progress.tsx +114 -0
- package/src/components/ui/qr-code.tsx +51 -0
- package/src/components/ui/query-builder.tsx +938 -0
- package/src/components/ui/radio-group.tsx +108 -0
- package/src/components/ui/rating-group.tsx +91 -0
- package/src/components/ui/resizable.tsx +41 -0
- package/src/components/ui/rich-text-editor.tsx +845 -0
- package/src/components/ui/scheduler.tsx +1164 -0
- package/src/components/ui/scroll-area.tsx +82 -0
- package/src/components/ui/segment-group.tsx +95 -0
- package/src/components/ui/select.tsx +354 -0
- package/src/components/ui/separator.tsx +32 -0
- package/src/components/ui/sheet.tsx +130 -0
- package/src/components/ui/sidebar.tsx +665 -0
- package/src/components/ui/signature-pad.tsx +112 -0
- package/src/components/ui/skeleton.tsx +7 -0
- package/src/components/ui/slider.tsx +183 -0
- package/src/components/ui/sonner.tsx +37 -0
- package/src/components/ui/spinner.tsx +16 -0
- package/src/components/ui/steps.tsx +152 -0
- package/src/components/ui/swap.tsx +33 -0
- package/src/components/ui/switch.tsx +83 -0
- package/src/components/ui/table.tsx +72 -0
- package/src/components/ui/tabs.tsx +100 -0
- package/src/components/ui/tags-input.tsx +153 -0
- package/src/components/ui/textarea.tsx +17 -0
- package/src/components/ui/timer.tsx +67 -0
- package/src/components/ui/toc.tsx +64 -0
- package/src/components/ui/toggle-group.tsx +89 -0
- package/src/components/ui/toggle.tsx +46 -0
- package/src/components/ui/tooltip.tsx +113 -0
- package/src/components/ui/tour.tsx +168 -0
- package/src/components/ui/transfer-list.tsx +700 -0
- package/src/components/ui/tree-select.tsx +638 -0
- package/src/components/ui/tree-view.tsx +217 -0
- package/src/components/ui/virtual-list.tsx +343 -0
- package/src/hooks/use-mobile.ts +19 -0
- package/src/lib/controllable.ts +31 -0
- package/src/lib/data-table-adapter.ts +67 -0
- package/src/lib/drag-preview.ts +39 -0
- package/src/lib/form.ts +39 -0
- package/src/lib/history.ts +55 -0
- package/src/lib/row-layout.ts +81 -0
- package/src/lib/table.ts +483 -0
- package/src/lib/time.ts +37 -0
- package/src/lib/utils.ts +6 -0
- package/src/styles/arkcn.css +764 -0
- package/src/styles/index.css +3 -0
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import * as React from "react"
|
|
4
|
+
import { cn } from "@/lib/utils"
|
|
5
|
+
import { TreeView as TreeViewPrimitive, createTreeCollection, type TreeCollection, type TreeNode } from "@ark-ui/react"
|
|
6
|
+
import { CheckIcon, ChevronRightIcon, MinusIcon } from "lucide-react"
|
|
7
|
+
|
|
8
|
+
function TreeView<T extends TreeNode>({ className, ...props }: React.ComponentProps<typeof TreeViewPrimitive.Root<T>>) {
|
|
9
|
+
return <TreeViewPrimitive.Root data-slot="tree-view" className={cn("w-full text-sm", className)} {...props} />
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function TreeViewContext({ ...props }: React.ComponentProps<typeof TreeViewPrimitive.Context>) {
|
|
13
|
+
return <TreeViewPrimitive.Context {...props} />
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function TreeViewLabel({ className, ...props }: React.ComponentProps<typeof TreeViewPrimitive.Label>) {
|
|
17
|
+
return (
|
|
18
|
+
<TreeViewPrimitive.Label
|
|
19
|
+
data-slot="tree-view-label"
|
|
20
|
+
className={cn("mb-1 text-sm font-medium select-none", className)}
|
|
21
|
+
{...props}
|
|
22
|
+
/>
|
|
23
|
+
)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function TreeViewTree({ className, ...props }: React.ComponentProps<typeof TreeViewPrimitive.Tree>) {
|
|
27
|
+
return (
|
|
28
|
+
<TreeViewPrimitive.Tree
|
|
29
|
+
data-slot="tree-view-tree"
|
|
30
|
+
className={cn("flex flex-col gap-px outline-none", className)}
|
|
31
|
+
{...props}
|
|
32
|
+
/>
|
|
33
|
+
)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function TreeViewNodeProvider<T>({ ...props }: React.ComponentProps<typeof TreeViewPrimitive.NodeProvider<T>>) {
|
|
37
|
+
return <TreeViewPrimitive.NodeProvider {...props} />
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function TreeViewNodeContext({ ...props }: React.ComponentProps<typeof TreeViewPrimitive.NodeContext>) {
|
|
41
|
+
return <TreeViewPrimitive.NodeContext {...props} />
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const rowClassName =
|
|
45
|
+
"group/tree-row relative flex h-7 cursor-default items-center gap-1.5 rounded-md py-1 pr-2 pl-[calc(var(--depth)*--spacing(4)+--spacing(1.5))] outline-none select-none hover:bg-muted data-selected:bg-muted data-selected:text-foreground focus-visible:ring-2 focus-visible:ring-ring/50 focus-visible:ring-inset data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4"
|
|
46
|
+
|
|
47
|
+
function TreeViewBranch({ className, ...props }: React.ComponentProps<typeof TreeViewPrimitive.Branch>) {
|
|
48
|
+
return (
|
|
49
|
+
<TreeViewPrimitive.Branch
|
|
50
|
+
data-slot="tree-view-branch"
|
|
51
|
+
className={cn("flex flex-col gap-px", className)}
|
|
52
|
+
{...props}
|
|
53
|
+
/>
|
|
54
|
+
)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function TreeViewBranchControl({ className, ...props }: React.ComponentProps<typeof TreeViewPrimitive.BranchControl>) {
|
|
58
|
+
return (
|
|
59
|
+
<TreeViewPrimitive.BranchControl
|
|
60
|
+
data-slot="tree-view-branch-control"
|
|
61
|
+
className={cn(rowClassName, className)}
|
|
62
|
+
{...props}
|
|
63
|
+
/>
|
|
64
|
+
)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function TreeViewBranchTrigger({ className, ...props }: React.ComponentProps<typeof TreeViewPrimitive.BranchTrigger>) {
|
|
68
|
+
return (
|
|
69
|
+
<TreeViewPrimitive.BranchTrigger
|
|
70
|
+
data-slot="tree-view-branch-trigger"
|
|
71
|
+
className={cn("inline-flex", className)}
|
|
72
|
+
{...props}
|
|
73
|
+
/>
|
|
74
|
+
)
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function TreeViewBranchIndicator({
|
|
78
|
+
className,
|
|
79
|
+
children,
|
|
80
|
+
...props
|
|
81
|
+
}: React.ComponentProps<typeof TreeViewPrimitive.BranchIndicator>) {
|
|
82
|
+
return (
|
|
83
|
+
<TreeViewPrimitive.BranchIndicator
|
|
84
|
+
data-slot="tree-view-branch-indicator"
|
|
85
|
+
className={cn("text-muted-foreground transition-transform data-[state=open]:rotate-90", className)}
|
|
86
|
+
{...props}
|
|
87
|
+
>
|
|
88
|
+
{children ?? <ChevronRightIcon />}
|
|
89
|
+
</TreeViewPrimitive.BranchIndicator>
|
|
90
|
+
)
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function TreeViewBranchText({ className, ...props }: React.ComponentProps<typeof TreeViewPrimitive.BranchText>) {
|
|
94
|
+
return (
|
|
95
|
+
<TreeViewPrimitive.BranchText data-slot="tree-view-branch-text" className={cn("truncate", className)} {...props} />
|
|
96
|
+
)
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function TreeViewBranchContent({ className, ...props }: React.ComponentProps<typeof TreeViewPrimitive.BranchContent>) {
|
|
100
|
+
return (
|
|
101
|
+
<TreeViewPrimitive.BranchContent
|
|
102
|
+
data-slot="tree-view-branch-content"
|
|
103
|
+
className={cn("relative flex flex-col gap-px", className)}
|
|
104
|
+
{...props}
|
|
105
|
+
/>
|
|
106
|
+
)
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function TreeViewBranchIndentGuide({
|
|
110
|
+
className,
|
|
111
|
+
...props
|
|
112
|
+
}: React.ComponentProps<typeof TreeViewPrimitive.BranchIndentGuide>) {
|
|
113
|
+
return (
|
|
114
|
+
<TreeViewPrimitive.BranchIndentGuide
|
|
115
|
+
data-slot="tree-view-branch-indent-guide"
|
|
116
|
+
className={cn(
|
|
117
|
+
"absolute inset-y-0 left-[calc(var(--depth)*(--spacing(4))+(--spacing(3)))] w-px bg-border",
|
|
118
|
+
className
|
|
119
|
+
)}
|
|
120
|
+
{...props}
|
|
121
|
+
/>
|
|
122
|
+
)
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function TreeViewItem({ className, ...props }: React.ComponentProps<typeof TreeViewPrimitive.Item>) {
|
|
126
|
+
return <TreeViewPrimitive.Item data-slot="tree-view-item" className={cn(rowClassName, className)} {...props} />
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function TreeViewItemIndicator({
|
|
130
|
+
className,
|
|
131
|
+
children,
|
|
132
|
+
...props
|
|
133
|
+
}: React.ComponentProps<typeof TreeViewPrimitive.ItemIndicator>) {
|
|
134
|
+
return (
|
|
135
|
+
<TreeViewPrimitive.ItemIndicator
|
|
136
|
+
data-slot="tree-view-item-indicator"
|
|
137
|
+
className={cn("ml-auto text-muted-foreground", className)}
|
|
138
|
+
{...props}
|
|
139
|
+
>
|
|
140
|
+
{children ?? <CheckIcon />}
|
|
141
|
+
</TreeViewPrimitive.ItemIndicator>
|
|
142
|
+
)
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
function TreeViewItemText({ className, ...props }: React.ComponentProps<typeof TreeViewPrimitive.ItemText>) {
|
|
146
|
+
return <TreeViewPrimitive.ItemText data-slot="tree-view-item-text" className={cn("truncate", className)} {...props} />
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
function TreeViewNodeCheckbox({
|
|
150
|
+
className,
|
|
151
|
+
children,
|
|
152
|
+
...props
|
|
153
|
+
}: React.ComponentProps<typeof TreeViewPrimitive.NodeCheckbox>) {
|
|
154
|
+
return (
|
|
155
|
+
<TreeViewPrimitive.NodeCheckbox
|
|
156
|
+
data-slot="tree-view-node-checkbox"
|
|
157
|
+
className={cn(
|
|
158
|
+
"flex size-4 shrink-0 items-center justify-center rounded-lg border border-input text-primary-foreground data-indeterminate:border-primary data-indeterminate:bg-primary data-checked:border-primary data-checked:bg-primary [&_svg]:size-3",
|
|
159
|
+
className
|
|
160
|
+
)}
|
|
161
|
+
{...props}
|
|
162
|
+
>
|
|
163
|
+
{children ?? (
|
|
164
|
+
<TreeViewNodeCheckboxIndicator indeterminate={<MinusIcon />}>
|
|
165
|
+
<CheckIcon />
|
|
166
|
+
</TreeViewNodeCheckboxIndicator>
|
|
167
|
+
)}
|
|
168
|
+
</TreeViewPrimitive.NodeCheckbox>
|
|
169
|
+
)
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
function TreeViewNodeCheckboxIndicator({
|
|
173
|
+
...props
|
|
174
|
+
}: React.ComponentProps<typeof TreeViewPrimitive.NodeCheckboxIndicator>) {
|
|
175
|
+
return <TreeViewPrimitive.NodeCheckboxIndicator data-slot="tree-view-node-checkbox-indicator" {...props} />
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
function TreeViewNodeRenameInput({
|
|
179
|
+
className,
|
|
180
|
+
...props
|
|
181
|
+
}: React.ComponentProps<typeof TreeViewPrimitive.NodeRenameInput>) {
|
|
182
|
+
return (
|
|
183
|
+
<TreeViewPrimitive.NodeRenameInput
|
|
184
|
+
data-slot="tree-view-node-rename-input"
|
|
185
|
+
className={cn(
|
|
186
|
+
"h-6 min-w-0 flex-1 rounded-sm border border-input bg-background px-1 text-sm outline-none focus-visible:ring-2 focus-visible:ring-ring/50",
|
|
187
|
+
className
|
|
188
|
+
)}
|
|
189
|
+
{...props}
|
|
190
|
+
/>
|
|
191
|
+
)
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
export {
|
|
195
|
+
TreeView,
|
|
196
|
+
TreeViewBranch,
|
|
197
|
+
TreeViewBranchContent,
|
|
198
|
+
TreeViewBranchControl,
|
|
199
|
+
TreeViewBranchIndentGuide,
|
|
200
|
+
TreeViewBranchIndicator,
|
|
201
|
+
TreeViewBranchText,
|
|
202
|
+
TreeViewBranchTrigger,
|
|
203
|
+
TreeViewContext,
|
|
204
|
+
TreeViewItem,
|
|
205
|
+
TreeViewItemIndicator,
|
|
206
|
+
TreeViewItemText,
|
|
207
|
+
TreeViewLabel,
|
|
208
|
+
TreeViewNodeCheckbox,
|
|
209
|
+
TreeViewNodeCheckboxIndicator,
|
|
210
|
+
TreeViewNodeContext,
|
|
211
|
+
TreeViewNodeProvider,
|
|
212
|
+
TreeViewNodeRenameInput,
|
|
213
|
+
TreeViewTree,
|
|
214
|
+
createTreeCollection,
|
|
215
|
+
type TreeCollection,
|
|
216
|
+
type TreeNode,
|
|
217
|
+
}
|
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import * as React from "react"
|
|
4
|
+
import { cn } from "@/lib/utils"
|
|
5
|
+
|
|
6
|
+
/* -------------------------------- context -------------------------------- */
|
|
7
|
+
|
|
8
|
+
type VirtualItem = {
|
|
9
|
+
index: number
|
|
10
|
+
key: React.Key
|
|
11
|
+
/** Offset from the top of the content, in px. */
|
|
12
|
+
start: number
|
|
13
|
+
size: number
|
|
14
|
+
end: number
|
|
15
|
+
/** False until the row's real height has been measured. */
|
|
16
|
+
measured: boolean
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
type ScrollAlign = "auto" | "start" | "center" | "end"
|
|
20
|
+
|
|
21
|
+
type VirtualListContextValue = {
|
|
22
|
+
count: number
|
|
23
|
+
items: VirtualItem[]
|
|
24
|
+
totalSize: number
|
|
25
|
+
/** First and last rendered index (overscan included), or null when empty. */
|
|
26
|
+
range: { start: number; end: number } | null
|
|
27
|
+
measure: (index: number, size: number) => void
|
|
28
|
+
scrollToIndex: (index: number, options?: { align?: ScrollAlign; behavior?: ScrollBehavior }) => void
|
|
29
|
+
scrollToOffset: (offset: number, behavior?: ScrollBehavior) => void
|
|
30
|
+
viewportRef: React.RefObject<HTMLDivElement | null>
|
|
31
|
+
getItemKey: (index: number) => React.Key
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const VirtualListContext = React.createContext<VirtualListContextValue | null>(null)
|
|
35
|
+
|
|
36
|
+
function useVirtualList() {
|
|
37
|
+
const ctx = React.useContext(VirtualListContext)
|
|
38
|
+
if (!ctx) throw new Error("VirtualList parts must be used inside <VirtualList>")
|
|
39
|
+
return ctx
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/* -------------------------------- helpers -------------------------------- */
|
|
43
|
+
|
|
44
|
+
/** Largest index whose start is <= offset. */
|
|
45
|
+
function findIndex(starts: Float64Array, count: number, offset: number) {
|
|
46
|
+
let lo = 0
|
|
47
|
+
let hi = count - 1
|
|
48
|
+
while (lo < hi) {
|
|
49
|
+
const mid = (lo + hi + 1) >> 1
|
|
50
|
+
if (starts[mid] <= offset) lo = mid
|
|
51
|
+
else hi = mid - 1
|
|
52
|
+
}
|
|
53
|
+
return lo
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/* ---------------------------------- root --------------------------------- */
|
|
57
|
+
|
|
58
|
+
type VirtualListProps = Omit<React.ComponentProps<"div">, "children"> & {
|
|
59
|
+
count: number
|
|
60
|
+
/** Row height before measurement (a number, or per index). */
|
|
61
|
+
estimateSize?: number | ((index: number) => number)
|
|
62
|
+
/** Rows rendered beyond the visible window on each side. */
|
|
63
|
+
overscan?: number
|
|
64
|
+
gap?: number
|
|
65
|
+
paddingStart?: number
|
|
66
|
+
paddingEnd?: number
|
|
67
|
+
getItemKey?: (index: number) => React.Key
|
|
68
|
+
/** Fires when the rendered window changes. */
|
|
69
|
+
onRangeChange?: (range: { start: number; end: number } | null) => void
|
|
70
|
+
children: React.ReactNode
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function VirtualList({
|
|
74
|
+
count,
|
|
75
|
+
estimateSize = 36,
|
|
76
|
+
overscan = 6,
|
|
77
|
+
gap = 0,
|
|
78
|
+
paddingStart = 0,
|
|
79
|
+
paddingEnd = 0,
|
|
80
|
+
getItemKey = (index) => index,
|
|
81
|
+
onRangeChange,
|
|
82
|
+
className,
|
|
83
|
+
children,
|
|
84
|
+
...props
|
|
85
|
+
}: VirtualListProps) {
|
|
86
|
+
const viewportRef = React.useRef<HTMLDivElement | null>(null)
|
|
87
|
+
const sizes = React.useRef(new Map<number, number>())
|
|
88
|
+
const [version, setVersion] = React.useState(0)
|
|
89
|
+
const [scrollTop, setScrollTop] = React.useState(0)
|
|
90
|
+
const [viewportSize, setViewportSize] = React.useState(0)
|
|
91
|
+
const estimate = React.useCallback(
|
|
92
|
+
(index: number) => (typeof estimateSize === "function" ? estimateSize(index) : estimateSize),
|
|
93
|
+
[estimateSize]
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
// Prefix sums of row starts; recomputed when a measurement or the count changes.
|
|
97
|
+
const layout = React.useMemo(() => {
|
|
98
|
+
const starts = new Float64Array(count)
|
|
99
|
+
let offset = paddingStart
|
|
100
|
+
for (let i = 0; i < count; i++) {
|
|
101
|
+
starts[i] = offset
|
|
102
|
+
offset += (sizes.current.get(i) ?? estimate(i)) + (i < count - 1 ? gap : 0)
|
|
103
|
+
}
|
|
104
|
+
return { starts, totalSize: offset + paddingEnd }
|
|
105
|
+
// `version` is the measurement tick.
|
|
106
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
107
|
+
}, [count, estimate, gap, paddingStart, paddingEnd, version])
|
|
108
|
+
|
|
109
|
+
const range = React.useMemo(() => {
|
|
110
|
+
if (count === 0 || viewportSize === 0) return count === 0 ? null : { start: 0, end: Math.min(count - 1, overscan) }
|
|
111
|
+
const first = findIndex(layout.starts, count, scrollTop)
|
|
112
|
+
const last = findIndex(layout.starts, count, scrollTop + viewportSize)
|
|
113
|
+
return { start: Math.max(0, first - overscan), end: Math.min(count - 1, last + overscan) }
|
|
114
|
+
}, [count, viewportSize, scrollTop, layout, overscan])
|
|
115
|
+
|
|
116
|
+
const items = React.useMemo(() => {
|
|
117
|
+
if (!range) return []
|
|
118
|
+
const out: VirtualItem[] = []
|
|
119
|
+
for (let i = range.start; i <= range.end; i++) {
|
|
120
|
+
const measured = sizes.current.has(i)
|
|
121
|
+
const size = sizes.current.get(i) ?? estimate(i)
|
|
122
|
+
out.push({ index: i, key: getItemKey(i), start: layout.starts[i], size, end: layout.starts[i] + size, measured })
|
|
123
|
+
}
|
|
124
|
+
return out
|
|
125
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
126
|
+
}, [range, layout, estimate, getItemKey, version])
|
|
127
|
+
|
|
128
|
+
const onRangeRef = React.useRef(onRangeChange)
|
|
129
|
+
onRangeRef.current = onRangeChange
|
|
130
|
+
const lastRange = React.useRef<string>("")
|
|
131
|
+
React.useEffect(() => {
|
|
132
|
+
const key = range ? `${range.start}-${range.end}` : "none"
|
|
133
|
+
if (key === lastRange.current) return
|
|
134
|
+
lastRange.current = key
|
|
135
|
+
onRangeRef.current?.(range)
|
|
136
|
+
}, [range])
|
|
137
|
+
|
|
138
|
+
// Drop stale measurements when the list shrinks.
|
|
139
|
+
React.useEffect(() => {
|
|
140
|
+
let dirty = false
|
|
141
|
+
for (const index of sizes.current.keys()) {
|
|
142
|
+
if (index >= count) {
|
|
143
|
+
sizes.current.delete(index)
|
|
144
|
+
dirty = true
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
if (dirty) setVersion((v) => v + 1)
|
|
148
|
+
}, [count])
|
|
149
|
+
|
|
150
|
+
const measure = React.useCallback((index: number, size: number) => {
|
|
151
|
+
const prev = sizes.current.get(index)
|
|
152
|
+
if (prev !== undefined && Math.abs(prev - size) < 0.5) return
|
|
153
|
+
sizes.current.set(index, size)
|
|
154
|
+
setVersion((v) => v + 1)
|
|
155
|
+
}, [])
|
|
156
|
+
|
|
157
|
+
React.useLayoutEffect(() => {
|
|
158
|
+
const el = viewportRef.current
|
|
159
|
+
if (!el) return
|
|
160
|
+
const update = () => setViewportSize(el.clientHeight)
|
|
161
|
+
update()
|
|
162
|
+
const ro = new ResizeObserver(update)
|
|
163
|
+
ro.observe(el)
|
|
164
|
+
return () => ro.disconnect()
|
|
165
|
+
}, [])
|
|
166
|
+
|
|
167
|
+
const scrollToOffset = React.useCallback((offset: number, behavior: ScrollBehavior = "auto") => {
|
|
168
|
+
viewportRef.current?.scrollTo({ top: offset, behavior })
|
|
169
|
+
}, [])
|
|
170
|
+
|
|
171
|
+
const pending = React.useRef<{ index: number; align: ScrollAlign; tries: number } | null>(null)
|
|
172
|
+
const offsetFor = React.useCallback(
|
|
173
|
+
(index: number, align: ScrollAlign) => {
|
|
174
|
+
const el = viewportRef.current
|
|
175
|
+
if (!el) return 0
|
|
176
|
+
const start = layout.starts[index] ?? 0
|
|
177
|
+
const size = sizes.current.get(index) ?? estimate(index)
|
|
178
|
+
const height = el.clientHeight
|
|
179
|
+
let resolved = align
|
|
180
|
+
if (align === "auto") {
|
|
181
|
+
if (start < el.scrollTop) resolved = "start"
|
|
182
|
+
else if (start + size > el.scrollTop + height) resolved = "end"
|
|
183
|
+
else return el.scrollTop
|
|
184
|
+
}
|
|
185
|
+
if (resolved === "start") return start
|
|
186
|
+
if (resolved === "end") return start + size - height
|
|
187
|
+
return start + size / 2 - height / 2
|
|
188
|
+
},
|
|
189
|
+
[layout, estimate]
|
|
190
|
+
)
|
|
191
|
+
|
|
192
|
+
const scrollToIndex = React.useCallback(
|
|
193
|
+
(index: number, options?: { align?: ScrollAlign; behavior?: ScrollBehavior }) => {
|
|
194
|
+
const clamped = Math.max(0, Math.min(count - 1, index))
|
|
195
|
+
const align = options?.align ?? "auto"
|
|
196
|
+
pending.current = { index: clamped, align, tries: 0 }
|
|
197
|
+
scrollToOffset(offsetFor(clamped, align), options?.behavior)
|
|
198
|
+
},
|
|
199
|
+
[count, offsetFor, scrollToOffset]
|
|
200
|
+
)
|
|
201
|
+
|
|
202
|
+
// Estimated rows shift as they get measured: re-aim at the target a few times.
|
|
203
|
+
React.useLayoutEffect(() => {
|
|
204
|
+
const p = pending.current
|
|
205
|
+
const el = viewportRef.current
|
|
206
|
+
if (!p || !el) return
|
|
207
|
+
if (p.tries >= 4 || !sizes.current.has(p.index)) {
|
|
208
|
+
if (p.tries >= 4) pending.current = null
|
|
209
|
+
return
|
|
210
|
+
}
|
|
211
|
+
const target = offsetFor(p.index, p.align === "auto" ? "start" : p.align)
|
|
212
|
+
if (Math.abs(el.scrollTop - target) > 1) {
|
|
213
|
+
p.tries += 1
|
|
214
|
+
el.scrollTop = target
|
|
215
|
+
} else pending.current = null
|
|
216
|
+
})
|
|
217
|
+
|
|
218
|
+
const ctx: VirtualListContextValue = {
|
|
219
|
+
count,
|
|
220
|
+
items,
|
|
221
|
+
totalSize: layout.totalSize,
|
|
222
|
+
range,
|
|
223
|
+
measure,
|
|
224
|
+
scrollToIndex,
|
|
225
|
+
scrollToOffset,
|
|
226
|
+
viewportRef,
|
|
227
|
+
getItemKey,
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
return (
|
|
231
|
+
<VirtualListContext.Provider value={ctx}>
|
|
232
|
+
<VirtualListScroll onScroll={setScrollTop} />
|
|
233
|
+
<div data-slot="virtual-list" className={cn("flex min-h-0 flex-col", className)} {...props}>
|
|
234
|
+
{children}
|
|
235
|
+
</div>
|
|
236
|
+
</VirtualListContext.Provider>
|
|
237
|
+
)
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/** Attaches the scroll listener once the viewport mounts (kept out of the root's render). */
|
|
241
|
+
function VirtualListScroll({ onScroll }: { onScroll: (top: number) => void }) {
|
|
242
|
+
const ctx = useVirtualList()
|
|
243
|
+
React.useEffect(() => {
|
|
244
|
+
const el = ctx.viewportRef.current
|
|
245
|
+
if (!el) return
|
|
246
|
+
const handler = () => onScroll(el.scrollTop)
|
|
247
|
+
el.addEventListener("scroll", handler, { passive: true })
|
|
248
|
+
return () => el.removeEventListener("scroll", handler)
|
|
249
|
+
}, [ctx.viewportRef, onScroll])
|
|
250
|
+
return null
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/* --------------------------------- parts --------------------------------- */
|
|
254
|
+
|
|
255
|
+
function VirtualListViewport({ className, ...props }: React.ComponentProps<"div">) {
|
|
256
|
+
const ctx = useVirtualList()
|
|
257
|
+
return (
|
|
258
|
+
<div
|
|
259
|
+
ref={ctx.viewportRef}
|
|
260
|
+
data-slot="virtual-list-viewport"
|
|
261
|
+
className={cn("relative min-h-0 overflow-y-auto overscroll-contain", className)}
|
|
262
|
+
{...props}
|
|
263
|
+
/>
|
|
264
|
+
)
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/** Sized to the whole list so the scrollbar is right; rows position inside it. */
|
|
268
|
+
function VirtualListContent({ className, style, ...props }: React.ComponentProps<"div">) {
|
|
269
|
+
const ctx = useVirtualList()
|
|
270
|
+
return (
|
|
271
|
+
<div
|
|
272
|
+
data-slot="virtual-list-content"
|
|
273
|
+
className={cn("relative w-full", className)}
|
|
274
|
+
style={{ height: ctx.totalSize, ...style }}
|
|
275
|
+
{...props}
|
|
276
|
+
/>
|
|
277
|
+
)
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/** Renders the visible window. The child renders one row and must return a `VirtualListItem`. */
|
|
281
|
+
function VirtualListItems({ children }: { children: (item: VirtualItem) => React.ReactNode }) {
|
|
282
|
+
const ctx = useVirtualList()
|
|
283
|
+
return (
|
|
284
|
+
<>
|
|
285
|
+
{ctx.items.map((item) => (
|
|
286
|
+
<React.Fragment key={item.key}>{children(item)}</React.Fragment>
|
|
287
|
+
))}
|
|
288
|
+
</>
|
|
289
|
+
)
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
function VirtualListItem({ index, className, style, ...props }: React.ComponentProps<"div"> & { index: number }) {
|
|
293
|
+
const { items, measure } = useVirtualList()
|
|
294
|
+
const item = items.find((i) => i.index === index)
|
|
295
|
+
const ref = React.useCallback(
|
|
296
|
+
(el: HTMLDivElement | null) => {
|
|
297
|
+
if (!el) return
|
|
298
|
+
const run = () => measure(index, el.getBoundingClientRect().height)
|
|
299
|
+
run()
|
|
300
|
+
const ro = new ResizeObserver(run)
|
|
301
|
+
ro.observe(el)
|
|
302
|
+
// React 19 ref cleanup
|
|
303
|
+
return () => ro.disconnect()
|
|
304
|
+
},
|
|
305
|
+
[measure, index]
|
|
306
|
+
)
|
|
307
|
+
return (
|
|
308
|
+
<div
|
|
309
|
+
ref={ref}
|
|
310
|
+
data-slot="virtual-list-item"
|
|
311
|
+
data-index={index}
|
|
312
|
+
className={cn("absolute inset-x-0 top-0", className)}
|
|
313
|
+
style={{ transform: `translateY(${item?.start ?? 0}px)`, ...style }}
|
|
314
|
+
{...props}
|
|
315
|
+
/>
|
|
316
|
+
)
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
function VirtualListEmpty({ className, children, ...props }: React.ComponentProps<"div">) {
|
|
320
|
+
const ctx = useVirtualList()
|
|
321
|
+
if (ctx.count > 0) return null
|
|
322
|
+
return (
|
|
323
|
+
<div
|
|
324
|
+
data-slot="virtual-list-empty"
|
|
325
|
+
className={cn("flex flex-1 items-center justify-center py-8 text-sm text-muted-foreground", className)}
|
|
326
|
+
{...props}
|
|
327
|
+
>
|
|
328
|
+
{children ?? "Nothing to show"}
|
|
329
|
+
</div>
|
|
330
|
+
)
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
export {
|
|
334
|
+
VirtualList,
|
|
335
|
+
VirtualListContent,
|
|
336
|
+
VirtualListEmpty,
|
|
337
|
+
VirtualListItem,
|
|
338
|
+
VirtualListItems,
|
|
339
|
+
VirtualListViewport,
|
|
340
|
+
useVirtualList,
|
|
341
|
+
type VirtualItem,
|
|
342
|
+
type VirtualListProps,
|
|
343
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
|
|
3
|
+
const MOBILE_BREAKPOINT = 768
|
|
4
|
+
|
|
5
|
+
export function useIsMobile() {
|
|
6
|
+
const [isMobile, setIsMobile] = React.useState<boolean | undefined>(undefined)
|
|
7
|
+
|
|
8
|
+
React.useEffect(() => {
|
|
9
|
+
const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`)
|
|
10
|
+
const onChange = () => {
|
|
11
|
+
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)
|
|
12
|
+
}
|
|
13
|
+
mql.addEventListener("change", onChange)
|
|
14
|
+
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)
|
|
15
|
+
return () => mql.removeEventListener("change", onChange)
|
|
16
|
+
}, [])
|
|
17
|
+
|
|
18
|
+
return !!isMobile
|
|
19
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
|
|
3
|
+
type Updater<T> = T | ((prev: T) => T)
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Controlled-or-uncontrolled state. Pass the controlled value (or `undefined`), the
|
|
7
|
+
* uncontrolled default, and an optional change callback that fires in both modes.
|
|
8
|
+
*/
|
|
9
|
+
export function useControllable<T>(
|
|
10
|
+
controlled: T | undefined,
|
|
11
|
+
defaultValue: T,
|
|
12
|
+
onChange?: (value: T) => void
|
|
13
|
+
): [T, (next: Updater<T>) => void] {
|
|
14
|
+
const [internal, setInternal] = React.useState<T>(defaultValue)
|
|
15
|
+
const isControlled = controlled !== undefined
|
|
16
|
+
const value = isControlled ? (controlled as T) : internal
|
|
17
|
+
const valueRef = React.useRef(value)
|
|
18
|
+
valueRef.current = value
|
|
19
|
+
const onChangeRef = React.useRef(onChange)
|
|
20
|
+
onChangeRef.current = onChange
|
|
21
|
+
const set = React.useCallback(
|
|
22
|
+
(updater: Updater<T>) => {
|
|
23
|
+
const next = typeof updater === "function" ? (updater as (prev: T) => T)(valueRef.current) : updater
|
|
24
|
+
if (Object.is(next, valueRef.current)) return
|
|
25
|
+
if (!isControlled) setInternal(next)
|
|
26
|
+
onChangeRef.current?.(next)
|
|
27
|
+
},
|
|
28
|
+
[isControlled]
|
|
29
|
+
)
|
|
30
|
+
return [value, set]
|
|
31
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The contract the data table parts render against. `<DataTable>` accepts any
|
|
3
|
+
* object that satisfies it, so the parts are independent of where the rows,
|
|
4
|
+
* sorting, filtering, and paging come from.
|
|
5
|
+
*
|
|
6
|
+
* The built-in engine in `@/lib/table` satisfies it directly and is the
|
|
7
|
+
* default adapter. To drive the parts from another source (a server-side
|
|
8
|
+
* query, a different table library, a store), implement this interface over
|
|
9
|
+
* that source and pass the result to `<DataTable table={...}>`.
|
|
10
|
+
*
|
|
11
|
+
* Columns are data only: the adapter exposes ids, labels, sorting, visibility,
|
|
12
|
+
* and filtering. Headers and cells are composed in JSX on the page with
|
|
13
|
+
* `DataTableHead` / `DataTableCell`, keyed by column id.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
export type DataTableSortDirection = false | "asc" | "desc"
|
|
17
|
+
|
|
18
|
+
export interface DataTableColumn<TData, TValue = unknown> {
|
|
19
|
+
id: string
|
|
20
|
+
/** Human label for view options and headers; falls back to `id`. */
|
|
21
|
+
label?: string
|
|
22
|
+
/** Present on columns that read a value from the row (used by view options). */
|
|
23
|
+
accessorFn?: ((row: TData, index: number) => TValue) | undefined
|
|
24
|
+
getCanSort: () => boolean
|
|
25
|
+
getIsSorted: () => DataTableSortDirection
|
|
26
|
+
toggleSorting: (desc?: boolean) => void
|
|
27
|
+
getCanHide: () => boolean
|
|
28
|
+
getIsVisible: () => boolean
|
|
29
|
+
toggleVisibility: (visible?: boolean) => void
|
|
30
|
+
getFilterValue: () => unknown
|
|
31
|
+
setFilterValue: (value: unknown) => void
|
|
32
|
+
getFacetedUniqueValues: () => Map<unknown, number>
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface DataTableRow<TData> {
|
|
36
|
+
id: string
|
|
37
|
+
original: TData
|
|
38
|
+
getValue: <TValue = unknown>(columnId: string) => TValue
|
|
39
|
+
getIsSelected: () => boolean
|
|
40
|
+
toggleSelected: (selected?: boolean) => void
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export interface DataTableInstance<TData> {
|
|
44
|
+
getState: () => {
|
|
45
|
+
globalFilter: string
|
|
46
|
+
columnFilters: { id: string; value: unknown }[]
|
|
47
|
+
pagination: { pageIndex: number; pageSize: number }
|
|
48
|
+
}
|
|
49
|
+
getAllColumns: () => DataTableColumn<TData>[]
|
|
50
|
+
getColumn: (id: string) => DataTableColumn<TData> | undefined
|
|
51
|
+
/** The rows to render (already filtered, sorted, and paginated). */
|
|
52
|
+
getRowModel: () => { rows: DataTableRow<TData>[] }
|
|
53
|
+
getFilteredSelectedRowModel: () => { rows: DataTableRow<TData>[] }
|
|
54
|
+
setGlobalFilter: (value: string) => void
|
|
55
|
+
resetColumnFilters: () => void
|
|
56
|
+
setPageIndex: (index: number) => void
|
|
57
|
+
setPageSize: (size: number) => void
|
|
58
|
+
getPageCount: () => number
|
|
59
|
+
getCanPreviousPage: () => boolean
|
|
60
|
+
getCanNextPage: () => boolean
|
|
61
|
+
previousPage: () => void
|
|
62
|
+
nextPage: () => void
|
|
63
|
+
resetRowSelection: () => void
|
|
64
|
+
getIsAllPageRowsSelected: () => boolean
|
|
65
|
+
getIsSomePageRowsSelected: () => boolean
|
|
66
|
+
toggleAllPageRowsSelected: (selected?: boolean) => void
|
|
67
|
+
}
|