torch-glare 2.5.6 → 2.6.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 +4 -3
- package/dist/bin/index.js +9 -24
- package/dist/bin/index.js.map +1 -1
- package/dist/src/commands/add.d.ts +2 -2
- package/dist/src/commands/add.d.ts.map +1 -1
- package/dist/src/commands/add.js +4 -70
- package/dist/src/commands/add.js.map +1 -1
- package/dist/src/commands/hook.d.ts +5 -4
- package/dist/src/commands/hook.d.ts.map +1 -1
- package/dist/src/commands/hook.js +7 -75
- package/dist/src/commands/hook.js.map +1 -1
- package/dist/src/commands/init.js +1 -1
- package/dist/src/commands/init.js.map +1 -1
- package/dist/src/commands/layout.d.ts +5 -4
- package/dist/src/commands/layout.d.ts.map +1 -1
- package/dist/src/commands/layout.js +7 -75
- package/dist/src/commands/layout.js.map +1 -1
- package/dist/src/commands/provider.d.ts +5 -4
- package/dist/src/commands/provider.d.ts.map +1 -1
- package/dist/src/commands/provider.js +7 -75
- package/dist/src/commands/provider.js.map +1 -1
- package/dist/src/commands/update.d.ts.map +1 -1
- package/dist/src/commands/update.js +78 -43
- package/dist/src/commands/update.js.map +1 -1
- package/dist/src/commands/utils.d.ts +5 -4
- package/dist/src/commands/utils.d.ts.map +1 -1
- package/dist/src/commands/utils.js +7 -80
- package/dist/src/commands/utils.js.map +1 -1
- package/dist/src/shared/addFromRegistry.d.ts +16 -0
- package/dist/src/shared/addFromRegistry.d.ts.map +1 -0
- package/dist/src/shared/addFromRegistry.js +88 -0
- package/dist/src/shared/addFromRegistry.js.map +1 -0
- package/dist/src/shared/getInstallCommand.d.ts.map +1 -1
- package/dist/src/shared/getInstallCommand.js +5 -0
- package/dist/src/shared/getInstallCommand.js.map +1 -1
- package/dist/src/shared/installDependencies.d.ts +0 -10
- package/dist/src/shared/installDependencies.d.ts.map +1 -1
- package/dist/src/shared/installDependencies.js +0 -17
- package/dist/src/shared/installDependencies.js.map +1 -1
- package/dist/src/shared/installFromPlan.d.ts +7 -5
- package/dist/src/shared/installFromPlan.d.ts.map +1 -1
- package/dist/src/shared/installFromPlan.js +103 -36
- package/dist/src/shared/installFromPlan.js.map +1 -1
- package/dist/src/shared/loadRegistry.d.ts +12 -3
- package/dist/src/shared/loadRegistry.d.ts.map +1 -1
- package/dist/src/shared/loadRegistry.js +19 -20
- package/dist/src/shared/loadRegistry.js.map +1 -1
- package/dist/src/shared/registryClient.d.ts +19 -0
- package/dist/src/shared/registryClient.d.ts.map +1 -0
- package/dist/src/shared/registryClient.js +128 -0
- package/dist/src/shared/registryClient.js.map +1 -0
- package/dist/src/shared/resolveEntry.d.ts +10 -7
- package/dist/src/shared/resolveEntry.d.ts.map +1 -1
- package/dist/src/shared/resolveEntry.js +18 -13
- package/dist/src/shared/resolveEntry.js.map +1 -1
- package/dist/src/shared/suggestOtherCommand.d.ts +7 -1
- package/dist/src/shared/suggestOtherCommand.d.ts.map +1 -1
- package/dist/src/shared/suggestOtherCommand.js +29 -23
- package/dist/src/shared/suggestOtherCommand.js.map +1 -1
- package/dist/src/types/main.d.ts +31 -2
- package/dist/src/types/main.d.ts.map +1 -1
- package/package.json +6 -11
- package/apps/lib/components/ActionButton.tsx +0 -93
- package/apps/lib/components/ActionsGroup.tsx +0 -27
- package/apps/lib/components/AlertDialog.tsx +0 -204
- package/apps/lib/components/Avatar.tsx +0 -46
- package/apps/lib/components/Badge.tsx +0 -250
- package/apps/lib/components/BadgeField.tsx +0 -403
- package/apps/lib/components/Breadcrumb.tsx +0 -280
- package/apps/lib/components/Button.tsx +0 -325
- package/apps/lib/components/ButtonGroup.tsx +0 -190
- package/apps/lib/components/Calendar.tsx +0 -115
- package/apps/lib/components/Card.tsx +0 -95
- package/apps/lib/components/Checkbox.tsx +0 -42
- package/apps/lib/components/ColorPicker.tsx +0 -441
- package/apps/lib/components/ConclusionHeader.tsx +0 -148
- package/apps/lib/components/ContextMenu.tsx +0 -571
- package/apps/lib/components/CountBadge.tsx +0 -52
- package/apps/lib/components/DataTable.tsx +0 -213
- package/apps/lib/components/DataViews/badge.ts +0 -49
- package/apps/lib/components/DataViews/cell.tsx +0 -324
- package/apps/lib/components/DataViews/context.ts +0 -144
- package/apps/lib/components/DataViews/data-views.tsx +0 -395
- package/apps/lib/components/DataViews/filters/children.tsx +0 -98
- package/apps/lib/components/DataViews/filters/custom.tsx +0 -34
- package/apps/lib/components/DataViews/filters/filters.tsx +0 -157
- package/apps/lib/components/DataViews/filters/index.ts +0 -4
- package/apps/lib/components/DataViews/filters/labelled.tsx +0 -20
- package/apps/lib/components/DataViews/filters/presets.tsx +0 -65
- package/apps/lib/components/DataViews/filters/sync.tsx +0 -35
- package/apps/lib/components/DataViews/filters/values.ts +0 -173
- package/apps/lib/components/DataViews/header.tsx +0 -220
- package/apps/lib/components/DataViews/hooks/index.ts +0 -5
- package/apps/lib/components/DataViews/hooks/useActiveRow.ts +0 -22
- package/apps/lib/components/DataViews/hooks/useControllable.ts +0 -52
- package/apps/lib/components/DataViews/index.ts +0 -88
- package/apps/lib/components/DataViews/panel/columns.tsx +0 -153
- package/apps/lib/components/DataViews/panel/controls.tsx +0 -106
- package/apps/lib/components/DataViews/panel/index.ts +0 -3
- package/apps/lib/components/DataViews/panel/panel.tsx +0 -164
- package/apps/lib/components/DataViews/panel/saved-views.tsx +0 -67
- package/apps/lib/components/DataViews/panel/section.tsx +0 -81
- package/apps/lib/components/DataViews/panel/sort.tsx +0 -42
- package/apps/lib/components/DataViews/panel/tab.tsx +0 -31
- package/apps/lib/components/DataViews/slots.ts +0 -72
- package/apps/lib/components/DataViews/states.tsx +0 -73
- package/apps/lib/components/DataViews/types.ts +0 -510
- package/apps/lib/components/DataViews/views/board-view.tsx +0 -381
- package/apps/lib/components/DataViews/views/card-rows.tsx +0 -36
- package/apps/lib/components/DataViews/views/inbox-view.tsx +0 -260
- package/apps/lib/components/DataViews/views/pane-views.tsx +0 -196
- package/apps/lib/components/DataViews/views/table-view.tsx +0 -493
- package/apps/lib/components/DataViews/views/tree-view.tsx +0 -367
- package/apps/lib/components/DatePicker.tsx +0 -232
- package/apps/lib/components/Dialog.tsx +0 -116
- package/apps/lib/components/Divider.tsx +0 -28
- package/apps/lib/components/Drawer.tsx +0 -451
- package/apps/lib/components/DropdownMenu.tsx +0 -554
- package/apps/lib/components/FieldHint.tsx +0 -69
- package/apps/lib/components/Form.tsx +0 -182
- package/apps/lib/components/FormBuilder/context.ts +0 -85
- package/apps/lib/components/FormBuilder/field-kind.ts +0 -28
- package/apps/lib/components/FormBuilder/fields/ChoiceFields.tsx +0 -60
- package/apps/lib/components/FormBuilder/fields/ColorField.tsx +0 -59
- package/apps/lib/components/FormBuilder/fields/CustomField.tsx +0 -11
- package/apps/lib/components/FormBuilder/fields/DateField.tsx +0 -32
- package/apps/lib/components/FormBuilder/fields/FieldArray.tsx +0 -74
- package/apps/lib/components/FormBuilder/fields/FieldShell.tsx +0 -168
- package/apps/lib/components/FormBuilder/fields/FileField.tsx +0 -39
- package/apps/lib/components/FormBuilder/fields/OptionListFields.tsx +0 -132
- package/apps/lib/components/FormBuilder/fields/OtpField.tsx +0 -31
- package/apps/lib/components/FormBuilder/fields/PhoneField.tsx +0 -109
- package/apps/lib/components/FormBuilder/fields/RichTextEditorField.tsx +0 -31
- package/apps/lib/components/FormBuilder/fields/SelectField.tsx +0 -114
- package/apps/lib/components/FormBuilder/fields/SignatureField.tsx +0 -157
- package/apps/lib/components/FormBuilder/fields/SliderField.tsx +0 -67
- package/apps/lib/components/FormBuilder/fields/SwitchBoxField.tsx +0 -41
- package/apps/lib/components/FormBuilder/fields/TableField.tsx +0 -336
- package/apps/lib/components/FormBuilder/fields/TextField.tsx +0 -213
- package/apps/lib/components/FormBuilder/fields/TreeSelectField.tsx +0 -43
- package/apps/lib/components/FormBuilder/fields/countries.ts +0 -303
- package/apps/lib/components/FormBuilder/fields/index.ts +0 -25
- package/apps/lib/components/FormBuilder/form-builder.tsx +0 -198
- package/apps/lib/components/FormBuilder/index.ts +0 -31
- package/apps/lib/components/FormBuilder/numberFormat.ts +0 -16
- package/apps/lib/components/FormBuilder/submit.tsx +0 -67
- package/apps/lib/components/FormBuilder/types.ts +0 -316
- package/apps/lib/components/FormRenderer/FormDrawer.tsx +0 -250
- package/apps/lib/components/FormRenderer/detail.tsx +0 -256
- package/apps/lib/components/FormRenderer/form-renderer.tsx +0 -358
- package/apps/lib/components/FormRenderer/header.tsx +0 -88
- package/apps/lib/components/FormRenderer/index.ts +0 -17
- package/apps/lib/components/FormRenderer/notch-action.tsx +0 -64
- package/apps/lib/components/FormRenderer/section.tsx +0 -39
- package/apps/lib/components/FormRenderer/stepper.tsx +0 -393
- package/apps/lib/components/FormRenderer/types.ts +0 -115
- package/apps/lib/components/FormSummary.tsx +0 -282
- package/apps/lib/components/HeaderBar.tsx +0 -117
- package/apps/lib/components/ImageAttachment.tsx +0 -209
- package/apps/lib/components/InnerLabelField.tsx +0 -154
- package/apps/lib/components/Input.tsx +0 -224
- package/apps/lib/components/InputField.tsx +0 -147
- package/apps/lib/components/InputOTP.tsx +0 -84
- package/apps/lib/components/Label.tsx +0 -129
- package/apps/lib/components/LabelField.tsx +0 -76
- package/apps/lib/components/LabeledCheckBox.tsx +0 -51
- package/apps/lib/components/LabeledRadio.tsx +0 -51
- package/apps/lib/components/LinkButton.tsx +0 -94
- package/apps/lib/components/LoginButton.tsx +0 -51
- package/apps/lib/components/PasswordLevel.tsx +0 -58
- package/apps/lib/components/Popover.tsx +0 -312
- package/apps/lib/components/ProfileMenu.tsx +0 -85
- package/apps/lib/components/Radio.tsx +0 -59
- package/apps/lib/components/RadioCard.tsx +0 -50
- package/apps/lib/components/ScrollArea.tsx +0 -54
- package/apps/lib/components/SearchField.tsx +0 -62
- package/apps/lib/components/SearchableSelect.tsx +0 -318
- package/apps/lib/components/SearchableTable.tsx +0 -344
- package/apps/lib/components/SearchableTree.tsx +0 -485
- package/apps/lib/components/SearchableTreeDialog.tsx +0 -502
- package/apps/lib/components/SectionBlock.tsx +0 -168
- package/apps/lib/components/Select.tsx +0 -347
- package/apps/lib/components/SimpleSelect.tsx +0 -225
- package/apps/lib/components/Skeleton.tsx +0 -12
- package/apps/lib/components/SlideDatePicker.tsx +0 -255
- package/apps/lib/components/SpinLoading.tsx +0 -174
- package/apps/lib/components/Stepper.tsx +0 -480
- package/apps/lib/components/Switch.tsx +0 -82
- package/apps/lib/components/TabFormItem.tsx +0 -153
- package/apps/lib/components/TabSwitch.tsx +0 -172
- package/apps/lib/components/Table.tsx +0 -597
- package/apps/lib/components/TextEditor/ChartBlockTool.ts +0 -676
- package/apps/lib/components/TextEditor/RichTextField.tsx +0 -46
- package/apps/lib/components/TextEditor/TableDnDWrapper.ts +0 -462
- package/apps/lib/components/TextEditor/TextEditor.tsx +0 -1164
- package/apps/lib/components/TextEditor/TextEditorToolbar.tsx +0 -429
- package/apps/lib/components/TextEditor/editor-tools/AlignmentTune.ts +0 -70
- package/apps/lib/components/TextEditor/editor-tools/ColorInlineTool.ts +0 -50
- package/apps/lib/components/TextEditor/editor-tools/StrikethroughInlineTool.ts +0 -48
- package/apps/lib/components/TextEditor/editor-tools/inlineFormat.ts +0 -98
- package/apps/lib/components/TextEditor/editorjs.d.ts +0 -60
- package/apps/lib/components/TextEditor/index.ts +0 -7
- package/apps/lib/components/TextEditor/markdownParser.ts +0 -346
- package/apps/lib/components/Textarea.tsx +0 -117
- package/apps/lib/components/Timeline.tsx +0 -263
- package/apps/lib/components/Toast.tsx +0 -87
- package/apps/lib/components/Toggle.tsx +0 -125
- package/apps/lib/components/ToggleButton.tsx +0 -140
- package/apps/lib/components/Tooltip.tsx +0 -116
- package/apps/lib/components/TransparentLabel.tsx +0 -71
- package/apps/lib/components/TreeDropDown.tsx +0 -115
- package/apps/lib/components/TreeFolder/TreeFolder.tsx +0 -380
- package/apps/lib/components/TreeFolder/TreeFolderBreadcrumb.tsx +0 -75
- package/apps/lib/components/TreeFolder/TreeFolderRow.tsx +0 -354
- package/apps/lib/components/TreeFolder/TreeFolderStyles.tsx +0 -60
- package/apps/lib/components/TreeFolder/icons.tsx +0 -60
- package/apps/lib/components/TreeFolder/index.ts +0 -24
- package/apps/lib/components/TreeFolder/treeFolderUtils.ts +0 -109
- package/apps/lib/components/TreeFolder/types.ts +0 -77
- package/apps/lib/components/TreeFolder/useTreeFolderDnD.ts +0 -118
- package/apps/lib/hooks/useActiveTreeItem.ts +0 -61
- package/apps/lib/hooks/useClickOutside.ts +0 -27
- package/apps/lib/hooks/useDragDrop.tsx +0 -365
- package/apps/lib/hooks/useHtmlDir.ts +0 -31
- package/apps/lib/hooks/useInfiniteScroll.ts +0 -108
- package/apps/lib/hooks/useIsMobile.ts +0 -21
- package/apps/lib/hooks/useResize.ts +0 -67
- package/apps/lib/hooks/useTagSelection.ts +0 -300
- package/apps/lib/layouts/CNLayout.tsx +0 -372
- package/apps/lib/layouts/DataViewCard.tsx +0 -62
- package/apps/lib/layouts/FieldSection.tsx +0 -91
- package/apps/lib/layouts/TreeSubLayout.tsx +0 -173
- package/apps/lib/providers/ThemeProvider.tsx +0 -84
- package/apps/lib/registry.json +0 -1217
- package/apps/lib/tsconfig.json +0 -9
- package/apps/lib/tsconfig.tsbuildinfo +0 -1
- package/apps/lib/utils/cn.ts +0 -6
- package/apps/lib/utils/color.ts +0 -175
- package/apps/lib/utils/dataViews/path.ts +0 -67
- package/apps/lib/utils/dataViews/query.ts +0 -73
- package/apps/lib/utils/dataViews/types.ts +0 -187
- package/apps/lib/utils/dateFormat.ts +0 -108
- package/apps/lib/utils/resize.ts +0 -31
- package/apps/lib/utils/scroller.ts +0 -26
- package/apps/lib/utils/types.ts +0 -16
- package/docs/BLOCKS.md +0 -129
- package/docs/CHANGELOG-1.1.16.md +0 -108
- package/docs/Cover.png +0 -0
- package/docs/README.md +0 -215
- package/docs/components/action-button.md +0 -638
- package/docs/components/actions-group.md +0 -708
- package/docs/components/alert-dialog.md +0 -920
- package/docs/components/avatar.md +0 -709
- package/docs/components/badge-field.md +0 -738
- package/docs/components/badge.md +0 -301
- package/docs/components/breadcrumb.md +0 -930
- package/docs/components/button-group.md +0 -650
- package/docs/components/button.md +0 -639
- package/docs/components/calendar.md +0 -555
- package/docs/components/card.md +0 -622
- package/docs/components/chart-block-tool.md +0 -129
- package/docs/components/checkbox.md +0 -699
- package/docs/components/cn-layout.md +0 -854
- package/docs/components/color-picker.md +0 -101
- package/docs/components/conclusion-header.md +0 -80
- package/docs/components/context-menu.md +0 -483
- package/docs/components/count-badge.md +0 -560
- package/docs/components/data-table.md +0 -854
- package/docs/components/data-views/backend-response.md +0 -324
- package/docs/components/data-views/examples/a11y-rtl.md +0 -250
- package/docs/components/data-views/examples/api-orders-route.md +0 -130
- package/docs/components/data-views/examples/fields.md +0 -362
- package/docs/components/data-views/examples/filters.md +0 -307
- package/docs/components/data-views/examples/inbox-routing.md +0 -218
- package/docs/components/data-views/examples/index.md +0 -29
- package/docs/components/data-views/examples/overview.md +0 -244
- package/docs/components/data-views/examples/panel.md +0 -212
- package/docs/components/data-views/examples/scale.md +0 -231
- package/docs/components/data-views/examples/server-side.md +0 -210
- package/docs/components/data-views/examples/state.md +0 -250
- package/docs/components/data-views/examples/tree-custom.md +0 -388
- package/docs/components/data-views/examples/view-registry.md +0 -313
- package/docs/components/data-views/examples/views.md +0 -534
- package/docs/components/data-views/guide.md +0 -405
- package/docs/components/data-views/index.md +0 -1521
- package/docs/components/data-views/migration.md +0 -81
- package/docs/components/date-picker.md +0 -857
- package/docs/components/dialog.md +0 -929
- package/docs/components/divider.md +0 -766
- package/docs/components/drawer.md +0 -654
- package/docs/components/dropdown-menu.md +0 -668
- package/docs/components/field-hint.md +0 -898
- package/docs/components/field-section.md +0 -781
- package/docs/components/form-builder.md +0 -284
- package/docs/components/form-renderer.md +0 -396
- package/docs/components/form-summary.md +0 -138
- package/docs/components/form.md +0 -785
- package/docs/components/header-bar.md +0 -188
- package/docs/components/image-attachment.md +0 -906
- package/docs/components/inner-label-field.md +0 -819
- package/docs/components/input-field.md +0 -623
- package/docs/components/input-otp.md +0 -756
- package/docs/components/input.md +0 -634
- package/docs/components/label-field.md +0 -770
- package/docs/components/label.md +0 -761
- package/docs/components/labeled-check-box.md +0 -642
- package/docs/components/labeled-radio.md +0 -796
- package/docs/components/link-button.md +0 -685
- package/docs/components/login-button.md +0 -872
- package/docs/components/password-level.md +0 -803
- package/docs/components/popover.md +0 -649
- package/docs/components/profile-menu.md +0 -656
- package/docs/components/radio-card.md +0 -801
- package/docs/components/radio.md +0 -735
- package/docs/components/scroll-area.md +0 -691
- package/docs/components/search-field.md +0 -702
- package/docs/components/searchable-select.md +0 -368
- package/docs/components/searchable-table.md +0 -438
- package/docs/components/searchable-tree-dialog.md +0 -190
- package/docs/components/searchable-tree.md +0 -200
- package/docs/components/section-block.md +0 -483
- package/docs/components/select.md +0 -709
- package/docs/components/simple-select.md +0 -741
- package/docs/components/skeleton.md +0 -706
- package/docs/components/slide-date-picker.md +0 -837
- package/docs/components/spin-loading.md +0 -696
- package/docs/components/stepper.md +0 -316
- package/docs/components/switch.md +0 -770
- package/docs/components/tab-form-item.md +0 -773
- package/docs/components/tab-switch.md +0 -170
- package/docs/components/table-dnd-wrapper.md +0 -107
- package/docs/components/table.md +0 -1088
- package/docs/components/text-editor.md +0 -735
- package/docs/components/textarea.md +0 -681
- package/docs/components/timeline.md +0 -254
- package/docs/components/toast.md +0 -773
- package/docs/components/toggle-button.md +0 -643
- package/docs/components/toggle.md +0 -882
- package/docs/components/tooltip.md +0 -513
- package/docs/components/transparent-label.md +0 -721
- package/docs/components/tree-drop-down.md +0 -740
- package/docs/components/tree-folder.md +0 -110
- package/docs/components/tree-sub-layout.md +0 -707
- package/docs/explanation/architecture.md +0 -54
- package/docs/explanation/design-system.md +0 -52
- package/docs/how-to/form-and-list-recipes.md +0 -386
- package/docs/how-to/forms-with-form-builder.md +0 -472
- package/docs/how-to/guides.md +0 -1027
- package/docs/migration/changelog.md +0 -60
- package/docs/migration/form-builder-2.5.2.md +0 -113
- package/docs/reference/cli.md +0 -112
- package/docs/reference/components.md +0 -572
- package/docs/reference/hooks.md +0 -1523
- package/docs/reference/providers.md +0 -866
- package/docs/reference/tailwind-plugins.md +0 -942
- package/docs/reference/theme.md +0 -85
- package/docs/reference/types.md +0 -1016
- package/docs/reference/utilities.md +0 -726
- package/docs/tutorials/building-first-form.md +0 -846
- package/docs/tutorials/component-composition.md +0 -882
- package/docs/tutorials/getting-started.md +0 -302
- package/docs/tutorials/theming-basics.md +0 -785
|
@@ -1,854 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: DataTable
|
|
3
|
-
description: Advanced data table with sorting, selection, filtering, pagination, and drag-and-drop row reordering
|
|
4
|
-
group: Data Display
|
|
5
|
-
keywords: [table, datatable, grid, sorting, selection, drag-drop, reorder, pagination, filtering, tanstack]
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# DataTable
|
|
9
|
-
|
|
10
|
-
> A powerful, feature-rich data table component built on TanStack Table with drag-and-drop row reordering, multi-row selection, column sorting, pagination, and filtering capabilities.
|
|
11
|
-
|
|
12
|
-
## Installation
|
|
13
|
-
|
|
14
|
-
TORCH Glare is a copy-in library: the CLI copies this component's source into your project
|
|
15
|
-
(you do **not** install it from the npm package). Run `init` once, then `add`:
|
|
16
|
-
|
|
17
|
-
```bash
|
|
18
|
-
npx torch-glare@latest init
|
|
19
|
-
npx torch-glare@latest add DataTable
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
`add` also copies any components, hooks, and utilities that `DataTable` depends on.
|
|
23
|
-
|
|
24
|
-
## Import
|
|
25
|
-
|
|
26
|
-
Import from your project's local path — the alias configured in `glare.json` (e.g. `@/*`):
|
|
27
|
-
|
|
28
|
-
```tsx
|
|
29
|
-
import { DataTable } from "@/components/DataTable";
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
## Quick Examples
|
|
33
|
-
|
|
34
|
-
### Basic Usage
|
|
35
|
-
|
|
36
|
-
```typescript
|
|
37
|
-
import { DataTable } from "@/components/DataTable";
|
|
38
|
-
import { ColumnDef } from '@tanstack/react-table'
|
|
39
|
-
|
|
40
|
-
interface User {
|
|
41
|
-
id: string
|
|
42
|
-
name: string
|
|
43
|
-
email: string
|
|
44
|
-
role: string
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
const columns: ColumnDef<User>[] = [
|
|
48
|
-
{
|
|
49
|
-
accessorKey: 'name',
|
|
50
|
-
header: 'Name',
|
|
51
|
-
},
|
|
52
|
-
{
|
|
53
|
-
accessorKey: 'email',
|
|
54
|
-
header: 'Email',
|
|
55
|
-
},
|
|
56
|
-
{
|
|
57
|
-
accessorKey: 'role',
|
|
58
|
-
header: 'Role',
|
|
59
|
-
},
|
|
60
|
-
]
|
|
61
|
-
|
|
62
|
-
const data: User[] = [
|
|
63
|
-
{ id: '1', name: 'John Doe', email: 'john@example.com', role: 'Admin' },
|
|
64
|
-
{ id: '2', name: 'Jane Smith', email: 'jane@example.com', role: 'User' },
|
|
65
|
-
{ id: '3', name: 'Bob Johnson', email: 'bob@example.com', role: 'Editor' },
|
|
66
|
-
]
|
|
67
|
-
|
|
68
|
-
function Example() {
|
|
69
|
-
return <DataTable columns={columns} data={data} />
|
|
70
|
-
}
|
|
71
|
-
```
|
|
72
|
-
|
|
73
|
-
### With Row Reordering
|
|
74
|
-
|
|
75
|
-
```typescript
|
|
76
|
-
import { DataTable } from "@/components/DataTable";
|
|
77
|
-
import { useState } from 'react'
|
|
78
|
-
|
|
79
|
-
function ReorderableTable() {
|
|
80
|
-
const [data, setData] = useState([
|
|
81
|
-
{ id: '1', task: 'Design homepage', priority: 'High' },
|
|
82
|
-
{ id: '2', task: 'Write documentation', priority: 'Medium' },
|
|
83
|
-
{ id: '3', task: 'Fix bugs', priority: 'High' },
|
|
84
|
-
])
|
|
85
|
-
|
|
86
|
-
const columns = [
|
|
87
|
-
{ accessorKey: 'task', header: 'Task' },
|
|
88
|
-
{ accessorKey: 'priority', header: 'Priority' },
|
|
89
|
-
]
|
|
90
|
-
|
|
91
|
-
return (
|
|
92
|
-
<DataTable
|
|
93
|
-
columns={columns}
|
|
94
|
-
data={data}
|
|
95
|
-
onRowReorder={(newData) => {
|
|
96
|
-
setData(newData)
|
|
97
|
-
console.log('New order:', newData)
|
|
98
|
-
}}
|
|
99
|
-
/>
|
|
100
|
-
)
|
|
101
|
-
}
|
|
102
|
-
```
|
|
103
|
-
|
|
104
|
-
### With Custom Cell Rendering
|
|
105
|
-
|
|
106
|
-
```typescript
|
|
107
|
-
import { DataTable } from "@/components/DataTable";
|
|
108
|
-
import { Badge } from "@/components/Badge";
|
|
109
|
-
import { ColumnDef } from '@tanstack/react-table'
|
|
110
|
-
|
|
111
|
-
interface Task {
|
|
112
|
-
id: string
|
|
113
|
-
title: string
|
|
114
|
-
status: 'pending' | 'in-progress' | 'completed'
|
|
115
|
-
assignee: string
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
const columns: ColumnDef<Task>[] = [
|
|
119
|
-
{
|
|
120
|
-
accessorKey: 'title',
|
|
121
|
-
header: 'Title',
|
|
122
|
-
},
|
|
123
|
-
{
|
|
124
|
-
accessorKey: 'status',
|
|
125
|
-
header: 'Status',
|
|
126
|
-
cell: ({ row }) => {
|
|
127
|
-
const status = row.getValue('status') as string
|
|
128
|
-
const variant = {
|
|
129
|
-
pending: 'yellow',
|
|
130
|
-
'in-progress': 'blue',
|
|
131
|
-
completed: 'green',
|
|
132
|
-
}[status]
|
|
133
|
-
|
|
134
|
-
return <Badge color={variant} label={status} />
|
|
135
|
-
},
|
|
136
|
-
},
|
|
137
|
-
{
|
|
138
|
-
accessorKey: 'assignee',
|
|
139
|
-
header: 'Assignee',
|
|
140
|
-
},
|
|
141
|
-
]
|
|
142
|
-
|
|
143
|
-
function TaskTable() {
|
|
144
|
-
const data: Task[] = [
|
|
145
|
-
{ id: '1', title: 'Design UI', status: 'in-progress', assignee: 'Alice' },
|
|
146
|
-
{ id: '2', title: 'Write tests', status: 'pending', assignee: 'Bob' },
|
|
147
|
-
{ id: '3', title: 'Deploy', status: 'completed', assignee: 'Charlie' },
|
|
148
|
-
]
|
|
149
|
-
|
|
150
|
-
return <DataTable columns={columns} data={data} />
|
|
151
|
-
}
|
|
152
|
-
```
|
|
153
|
-
|
|
154
|
-
### With Sortable Columns
|
|
155
|
-
|
|
156
|
-
```typescript
|
|
157
|
-
import { DataTable } from "@/components/DataTable";
|
|
158
|
-
import { ColumnDef } from '@tanstack/react-table'
|
|
159
|
-
|
|
160
|
-
interface Product {
|
|
161
|
-
id: string
|
|
162
|
-
name: string
|
|
163
|
-
price: number
|
|
164
|
-
stock: number
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
const columns: ColumnDef<Product>[] = [
|
|
168
|
-
{
|
|
169
|
-
accessorKey: 'name',
|
|
170
|
-
header: 'Product',
|
|
171
|
-
enableSorting: true,
|
|
172
|
-
},
|
|
173
|
-
{
|
|
174
|
-
accessorKey: 'price',
|
|
175
|
-
header: 'Price',
|
|
176
|
-
enableSorting: true,
|
|
177
|
-
cell: ({ row }) => `$${row.getValue('price')}`,
|
|
178
|
-
},
|
|
179
|
-
{
|
|
180
|
-
accessorKey: 'stock',
|
|
181
|
-
header: 'Stock',
|
|
182
|
-
enableSorting: true,
|
|
183
|
-
},
|
|
184
|
-
]
|
|
185
|
-
|
|
186
|
-
function ProductTable() {
|
|
187
|
-
const data: Product[] = [
|
|
188
|
-
{ id: '1', name: 'Laptop', price: 999, stock: 15 },
|
|
189
|
-
{ id: '2', name: 'Mouse', price: 29, stock: 50 },
|
|
190
|
-
{ id: '3', name: 'Keyboard', price: 79, stock: 30 },
|
|
191
|
-
]
|
|
192
|
-
|
|
193
|
-
return <DataTable columns={columns} data={data} />
|
|
194
|
-
}
|
|
195
|
-
```
|
|
196
|
-
|
|
197
|
-
### With Actions Column
|
|
198
|
-
|
|
199
|
-
```typescript
|
|
200
|
-
import { DataTable } from "@/components/DataTable";
|
|
201
|
-
import { ActionButton } from "@/components/ActionButton";
|
|
202
|
-
import { ColumnDef } from '@tanstack/react-table'
|
|
203
|
-
|
|
204
|
-
interface User {
|
|
205
|
-
id: string
|
|
206
|
-
name: string
|
|
207
|
-
email: string
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
const columns: ColumnDef<User>[] = [
|
|
211
|
-
{
|
|
212
|
-
accessorKey: 'name',
|
|
213
|
-
header: 'Name',
|
|
214
|
-
},
|
|
215
|
-
{
|
|
216
|
-
accessorKey: 'email',
|
|
217
|
-
header: 'Email',
|
|
218
|
-
},
|
|
219
|
-
{
|
|
220
|
-
id: 'actions',
|
|
221
|
-
header: 'Actions',
|
|
222
|
-
cell: ({ row }) => (
|
|
223
|
-
<div className="flex gap-2">
|
|
224
|
-
<ActionButton
|
|
225
|
-
size="XS"
|
|
226
|
-
onClick={() => console.log('Edit', row.original.id)}
|
|
227
|
-
aria-label="Edit user"
|
|
228
|
-
>
|
|
229
|
-
<i className="ri-edit-line" />
|
|
230
|
-
</ActionButton>
|
|
231
|
-
<ActionButton
|
|
232
|
-
size="XS"
|
|
233
|
-
onClick={() => console.log('Delete', row.original.id)}
|
|
234
|
-
aria-label="Delete user"
|
|
235
|
-
>
|
|
236
|
-
<i className="ri-delete-bin-line" />
|
|
237
|
-
</ActionButton>
|
|
238
|
-
</div>
|
|
239
|
-
),
|
|
240
|
-
},
|
|
241
|
-
]
|
|
242
|
-
|
|
243
|
-
function UserTable() {
|
|
244
|
-
const data: User[] = [
|
|
245
|
-
{ id: '1', name: 'Alice', email: 'alice@example.com' },
|
|
246
|
-
{ id: '2', name: 'Bob', email: 'bob@example.com' },
|
|
247
|
-
]
|
|
248
|
-
|
|
249
|
-
return <DataTable columns={columns} data={data} />
|
|
250
|
-
}
|
|
251
|
-
```
|
|
252
|
-
|
|
253
|
-
### With Selection Handling
|
|
254
|
-
|
|
255
|
-
```typescript
|
|
256
|
-
import { DataTable } from "@/components/DataTable";
|
|
257
|
-
import { useState } from 'react'
|
|
258
|
-
|
|
259
|
-
function SelectableTable() {
|
|
260
|
-
const [selectedRows, setSelectedRows] = useState<string[]>([])
|
|
261
|
-
|
|
262
|
-
const data = [
|
|
263
|
-
{ id: '1', name: 'Item 1', value: 100 },
|
|
264
|
-
{ id: '2', name: 'Item 2', value: 200 },
|
|
265
|
-
{ id: '3', name: 'Item 3', value: 300 },
|
|
266
|
-
]
|
|
267
|
-
|
|
268
|
-
const columns = [
|
|
269
|
-
{ accessorKey: 'name', header: 'Name' },
|
|
270
|
-
{ accessorKey: 'value', header: 'Value' },
|
|
271
|
-
]
|
|
272
|
-
|
|
273
|
-
return (
|
|
274
|
-
<div>
|
|
275
|
-
<DataTable columns={columns} data={data} />
|
|
276
|
-
<div className="mt-4">
|
|
277
|
-
<p>Selected rows: {selectedRows.length}</p>
|
|
278
|
-
<button onClick={() => console.log('Process selected rows')}>
|
|
279
|
-
Process Selected
|
|
280
|
-
</button>
|
|
281
|
-
</div>
|
|
282
|
-
</div>
|
|
283
|
-
)
|
|
284
|
-
}
|
|
285
|
-
```
|
|
286
|
-
|
|
287
|
-
### Dark Theme
|
|
288
|
-
|
|
289
|
-
```typescript
|
|
290
|
-
import { DataTable } from "@/components/DataTable";
|
|
291
|
-
|
|
292
|
-
function DarkTable() {
|
|
293
|
-
const columns = [
|
|
294
|
-
{ accessorKey: 'name', header: 'Name' },
|
|
295
|
-
{ accessorKey: 'status', header: 'Status' },
|
|
296
|
-
]
|
|
297
|
-
|
|
298
|
-
const data = [
|
|
299
|
-
{ id: '1', name: 'Task 1', status: 'Active' },
|
|
300
|
-
{ id: '2', name: 'Task 2', status: 'Completed' },
|
|
301
|
-
]
|
|
302
|
-
|
|
303
|
-
return <DataTable columns={columns} data={data} theme="dark" />
|
|
304
|
-
}
|
|
305
|
-
```
|
|
306
|
-
|
|
307
|
-
### Complex Data with Nested Objects
|
|
308
|
-
|
|
309
|
-
```typescript
|
|
310
|
-
import { DataTable } from "@/components/DataTable";
|
|
311
|
-
import { ColumnDef } from '@tanstack/react-table'
|
|
312
|
-
|
|
313
|
-
interface Order {
|
|
314
|
-
id: string
|
|
315
|
-
orderNumber: string
|
|
316
|
-
customer: {
|
|
317
|
-
name: string
|
|
318
|
-
email: string
|
|
319
|
-
}
|
|
320
|
-
total: number
|
|
321
|
-
status: string
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
const columns: ColumnDef<Order>[] = [
|
|
325
|
-
{
|
|
326
|
-
accessorKey: 'orderNumber',
|
|
327
|
-
header: 'Order #',
|
|
328
|
-
},
|
|
329
|
-
{
|
|
330
|
-
accessorKey: 'customer.name',
|
|
331
|
-
header: 'Customer',
|
|
332
|
-
},
|
|
333
|
-
{
|
|
334
|
-
accessorKey: 'customer.email',
|
|
335
|
-
header: 'Email',
|
|
336
|
-
},
|
|
337
|
-
{
|
|
338
|
-
accessorKey: 'total',
|
|
339
|
-
header: 'Total',
|
|
340
|
-
cell: ({ row }) => `$${row.getValue('total')}`,
|
|
341
|
-
},
|
|
342
|
-
{
|
|
343
|
-
accessorKey: 'status',
|
|
344
|
-
header: 'Status',
|
|
345
|
-
},
|
|
346
|
-
]
|
|
347
|
-
|
|
348
|
-
function OrderTable() {
|
|
349
|
-
const data: Order[] = [
|
|
350
|
-
{
|
|
351
|
-
id: '1',
|
|
352
|
-
orderNumber: 'ORD-001',
|
|
353
|
-
customer: { name: 'John Doe', email: 'john@example.com' },
|
|
354
|
-
total: 299.99,
|
|
355
|
-
status: 'Shipped',
|
|
356
|
-
},
|
|
357
|
-
{
|
|
358
|
-
id: '2',
|
|
359
|
-
orderNumber: 'ORD-002',
|
|
360
|
-
customer: { name: 'Jane Smith', email: 'jane@example.com' },
|
|
361
|
-
total: 149.99,
|
|
362
|
-
status: 'Processing',
|
|
363
|
-
},
|
|
364
|
-
]
|
|
365
|
-
|
|
366
|
-
return <DataTable columns={columns} data={data} />
|
|
367
|
-
}
|
|
368
|
-
```
|
|
369
|
-
|
|
370
|
-
### Empty State
|
|
371
|
-
|
|
372
|
-
```typescript
|
|
373
|
-
import { DataTable } from "@/components/DataTable";
|
|
374
|
-
|
|
375
|
-
function EmptyTable() {
|
|
376
|
-
const columns = [
|
|
377
|
-
{ accessorKey: 'name', header: 'Name' },
|
|
378
|
-
{ accessorKey: 'email', header: 'Email' },
|
|
379
|
-
]
|
|
380
|
-
|
|
381
|
-
// Empty data array
|
|
382
|
-
const data = []
|
|
383
|
-
|
|
384
|
-
return (
|
|
385
|
-
<DataTable
|
|
386
|
-
columns={columns}
|
|
387
|
-
data={data}
|
|
388
|
-
// Shows "No results." message automatically
|
|
389
|
-
/>
|
|
390
|
-
)
|
|
391
|
-
}
|
|
392
|
-
```
|
|
393
|
-
|
|
394
|
-
## API Reference
|
|
395
|
-
|
|
396
|
-
### DataTable Props
|
|
397
|
-
|
|
398
|
-
| Prop | Type | Default | Description |
|
|
399
|
-
|------|------|---------|-------------|
|
|
400
|
-
| `columns` | `ColumnDef<TData, TValue>[]` | Required | Column definitions for the table |
|
|
401
|
-
| `data` | `TData[]` | Required | Array of data objects (must have `id` property) |
|
|
402
|
-
| `theme` | `'dark' \| 'light' \| 'default'` | `'default'` | Theme variant |
|
|
403
|
-
| `onRowReorder` | `(newData: TData[]) => void` | - | Callback when rows are reordered via drag-and-drop |
|
|
404
|
-
|
|
405
|
-
### Type Constraints
|
|
406
|
-
|
|
407
|
-
```typescript
|
|
408
|
-
// Data must extend an object with id property
|
|
409
|
-
interface DataTableProps<TData extends { id: string | number }, TValue> {
|
|
410
|
-
columns: ColumnDef<TData, TValue>[]
|
|
411
|
-
data: TData[]
|
|
412
|
-
theme?: "dark" | "light" | "default"
|
|
413
|
-
onRowReorder?: (newData: TData[]) => void
|
|
414
|
-
}
|
|
415
|
-
```
|
|
416
|
-
|
|
417
|
-
## TypeScript
|
|
418
|
-
|
|
419
|
-
### Full Type Definitions
|
|
420
|
-
|
|
421
|
-
```typescript
|
|
422
|
-
import { ColumnDef } from '@tanstack/react-table'
|
|
423
|
-
|
|
424
|
-
// Data type must have id property
|
|
425
|
-
interface YourDataType {
|
|
426
|
-
id: string | number
|
|
427
|
-
// ... other properties
|
|
428
|
-
}
|
|
429
|
-
|
|
430
|
-
// Column definition with all options
|
|
431
|
-
const columns: ColumnDef<YourDataType>[] = [
|
|
432
|
-
{
|
|
433
|
-
accessorKey: 'fieldName',
|
|
434
|
-
header: 'Header Label',
|
|
435
|
-
enableSorting: true,
|
|
436
|
-
enableHiding: true,
|
|
437
|
-
cell: ({ row, getValue }) => {
|
|
438
|
-
// Custom cell rendering
|
|
439
|
-
return <div>{getValue()}</div>
|
|
440
|
-
},
|
|
441
|
-
},
|
|
442
|
-
]
|
|
443
|
-
|
|
444
|
-
// Component usage with TypeScript
|
|
445
|
-
function TypedTable() {
|
|
446
|
-
const data: YourDataType[] = [
|
|
447
|
-
{ id: '1', /* ... */ },
|
|
448
|
-
]
|
|
449
|
-
|
|
450
|
-
const handleReorder = (newData: YourDataType[]) => {
|
|
451
|
-
// Type-safe reorder handler
|
|
452
|
-
console.log(newData)
|
|
453
|
-
}
|
|
454
|
-
|
|
455
|
-
return (
|
|
456
|
-
<DataTable<YourDataType, any>
|
|
457
|
-
columns={columns}
|
|
458
|
-
data={data}
|
|
459
|
-
onRowReorder={handleReorder}
|
|
460
|
-
/>
|
|
461
|
-
)
|
|
462
|
-
}
|
|
463
|
-
```
|
|
464
|
-
|
|
465
|
-
### Generic Type Parameters
|
|
466
|
-
|
|
467
|
-
```typescript
|
|
468
|
-
// TData: Your data type (must have id property)
|
|
469
|
-
// TValue: Value type for cells (usually inferred)
|
|
470
|
-
DataTable<TData extends { id: string | number }, TValue>
|
|
471
|
-
```
|
|
472
|
-
|
|
473
|
-
## Common Patterns
|
|
474
|
-
|
|
475
|
-
### Controlled Row Selection
|
|
476
|
-
|
|
477
|
-
```typescript
|
|
478
|
-
import { DataTable } from "@/components/DataTable";
|
|
479
|
-
import { useState } from 'react'
|
|
480
|
-
|
|
481
|
-
function ControlledSelectionTable() {
|
|
482
|
-
const [data, setData] = useState([
|
|
483
|
-
{ id: '1', name: 'Task 1', completed: false },
|
|
484
|
-
{ id: '2', name: 'Task 2', completed: false },
|
|
485
|
-
])
|
|
486
|
-
|
|
487
|
-
const columns = [
|
|
488
|
-
{ accessorKey: 'name', header: 'Task' },
|
|
489
|
-
{
|
|
490
|
-
accessorKey: 'completed',
|
|
491
|
-
header: 'Status',
|
|
492
|
-
cell: ({ row }) => (
|
|
493
|
-
<span>{row.getValue('completed') ? '✓ Done' : 'Pending'}</span>
|
|
494
|
-
),
|
|
495
|
-
},
|
|
496
|
-
]
|
|
497
|
-
|
|
498
|
-
return <DataTable columns={columns} data={data} />
|
|
499
|
-
}
|
|
500
|
-
```
|
|
501
|
-
|
|
502
|
-
### With Search/Filter
|
|
503
|
-
|
|
504
|
-
```typescript
|
|
505
|
-
import { DataTable } from "@/components/DataTable";
|
|
506
|
-
import { Input } from "@/components/Input";
|
|
507
|
-
import { useState, useMemo } from 'react'
|
|
508
|
-
|
|
509
|
-
function SearchableTable() {
|
|
510
|
-
const [searchTerm, setSearchTerm] = useState('')
|
|
511
|
-
|
|
512
|
-
const allData = [
|
|
513
|
-
{ id: '1', name: 'Apple', category: 'Fruit' },
|
|
514
|
-
{ id: '2', name: 'Banana', category: 'Fruit' },
|
|
515
|
-
{ id: '3', name: 'Carrot', category: 'Vegetable' },
|
|
516
|
-
]
|
|
517
|
-
|
|
518
|
-
const filteredData = useMemo(() => {
|
|
519
|
-
return allData.filter(item =>
|
|
520
|
-
item.name.toLowerCase().includes(searchTerm.toLowerCase())
|
|
521
|
-
)
|
|
522
|
-
}, [searchTerm])
|
|
523
|
-
|
|
524
|
-
const columns = [
|
|
525
|
-
{ accessorKey: 'name', header: 'Name' },
|
|
526
|
-
{ accessorKey: 'category', header: 'Category' },
|
|
527
|
-
]
|
|
528
|
-
|
|
529
|
-
return (
|
|
530
|
-
<div>
|
|
531
|
-
<Input
|
|
532
|
-
placeholder="Search..."
|
|
533
|
-
value={searchTerm}
|
|
534
|
-
onChange={(e) => setSearchTerm(e.target.value)}
|
|
535
|
-
className="mb-4"
|
|
536
|
-
/>
|
|
537
|
-
<DataTable columns={columns} data={filteredData} />
|
|
538
|
-
</div>
|
|
539
|
-
)
|
|
540
|
-
}
|
|
541
|
-
```
|
|
542
|
-
|
|
543
|
-
### Persisting Row Order
|
|
544
|
-
|
|
545
|
-
```typescript
|
|
546
|
-
import { DataTable } from "@/components/DataTable";
|
|
547
|
-
import { useState, useEffect } from 'react'
|
|
548
|
-
|
|
549
|
-
function PersistentOrderTable() {
|
|
550
|
-
const [data, setData] = useState(() => {
|
|
551
|
-
// Load from localStorage
|
|
552
|
-
const saved = localStorage.getItem('tableOrder')
|
|
553
|
-
return saved ? JSON.parse(saved) : defaultData
|
|
554
|
-
})
|
|
555
|
-
|
|
556
|
-
const handleReorder = (newData) => {
|
|
557
|
-
setData(newData)
|
|
558
|
-
// Persist to localStorage
|
|
559
|
-
localStorage.setItem('tableOrder', JSON.stringify(newData))
|
|
560
|
-
}
|
|
561
|
-
|
|
562
|
-
const columns = [
|
|
563
|
-
{ accessorKey: 'name', header: 'Name' },
|
|
564
|
-
{ accessorKey: 'position', header: 'Position' },
|
|
565
|
-
]
|
|
566
|
-
|
|
567
|
-
return (
|
|
568
|
-
<DataTable
|
|
569
|
-
columns={columns}
|
|
570
|
-
data={data}
|
|
571
|
-
onRowReorder={handleReorder}
|
|
572
|
-
/>
|
|
573
|
-
)
|
|
574
|
-
}
|
|
575
|
-
```
|
|
576
|
-
|
|
577
|
-
## Features
|
|
578
|
-
|
|
579
|
-
The component's props are `columns`, `data`, `theme`, and `onRowReorder` — see the API
|
|
580
|
-
Reference. Its built-in, rendered capabilities are:
|
|
581
|
-
|
|
582
|
-
- **Row Selection**: Multi-row selection checkboxes (select all / select individual) are
|
|
583
|
-
rendered and tracked internally. Selection state persists through reordering. Note: the
|
|
584
|
-
component does not expose a selection-change prop — selection is internal visual state.
|
|
585
|
-
- **Drag & Drop**: Reorder rows by dragging; `onRowReorder` returns the new data array
|
|
586
|
-
(keyboard drag supported via dnd-kit).
|
|
587
|
-
- **Column Sorting**: Click headers to sort ascending/descending.
|
|
588
|
-
- **Custom Cells**: Full control over cell rendering via each column's `cell`.
|
|
589
|
-
- **Type Safety**: Full TypeScript support with generics.
|
|
590
|
-
|
|
591
|
-
> The TanStack pagination and filtering **row models** are enabled internally, but the
|
|
592
|
-
> component renders **no** pagination or filter controls and exposes no page/filter props.
|
|
593
|
-
> To paginate or filter, wrap the data yourself or compose your own controls around it.
|
|
594
|
-
|
|
595
|
-
### Drag-and-Drop Behavior
|
|
596
|
-
|
|
597
|
-
- Drag icon appears in first column (dummy cell)
|
|
598
|
-
- Cursor changes to grab/grabbing during drag
|
|
599
|
-
- Row becomes semi-transparent (50% opacity) while dragging
|
|
600
|
-
- Selection state is preserved after reordering
|
|
601
|
-
- `onRowReorder` callback provides new data array
|
|
602
|
-
|
|
603
|
-
### Selection Management
|
|
604
|
-
|
|
605
|
-
- Select all checkbox in header
|
|
606
|
-
- Individual row checkboxes
|
|
607
|
-
- Selection state persists through reordering
|
|
608
|
-
- Selection mapping automatically updates after drag-and-drop
|
|
609
|
-
|
|
610
|
-
## Testing
|
|
611
|
-
|
|
612
|
-
### Unit Test Example
|
|
613
|
-
|
|
614
|
-
```typescript
|
|
615
|
-
import { render, screen, fireEvent } from '@testing-library/react'
|
|
616
|
-
import { DataTable } from "@/components/DataTable";
|
|
617
|
-
import { ColumnDef } from '@tanstack/react-table'
|
|
618
|
-
|
|
619
|
-
const mockData = [
|
|
620
|
-
{ id: '1', name: 'Item 1', value: 100 },
|
|
621
|
-
{ id: '2', name: 'Item 2', value: 200 },
|
|
622
|
-
]
|
|
623
|
-
|
|
624
|
-
const mockColumns: ColumnDef<typeof mockData[0]>[] = [
|
|
625
|
-
{ accessorKey: 'name', header: 'Name' },
|
|
626
|
-
{ accessorKey: 'value', header: 'Value' },
|
|
627
|
-
]
|
|
628
|
-
|
|
629
|
-
describe('DataTable', () => {
|
|
630
|
-
it('renders table with data', () => {
|
|
631
|
-
render(<DataTable columns={mockColumns} data={mockData} />)
|
|
632
|
-
|
|
633
|
-
expect(screen.getByText('Item 1')).toBeInTheDocument()
|
|
634
|
-
expect(screen.getByText('Item 2')).toBeInTheDocument()
|
|
635
|
-
})
|
|
636
|
-
|
|
637
|
-
it('shows empty state when no data', () => {
|
|
638
|
-
render(<DataTable columns={mockColumns} data={[]} />)
|
|
639
|
-
|
|
640
|
-
expect(screen.getByText('No results.')).toBeInTheDocument()
|
|
641
|
-
})
|
|
642
|
-
|
|
643
|
-
it('calls onRowReorder when rows are reordered', () => {
|
|
644
|
-
const handleReorder = jest.fn()
|
|
645
|
-
|
|
646
|
-
render(
|
|
647
|
-
<DataTable
|
|
648
|
-
columns={mockColumns}
|
|
649
|
-
data={mockData}
|
|
650
|
-
onRowReorder={handleReorder}
|
|
651
|
-
/>
|
|
652
|
-
)
|
|
653
|
-
|
|
654
|
-
// Simulate drag-and-drop (requires @dnd-kit testing utilities)
|
|
655
|
-
// ... drag and drop simulation
|
|
656
|
-
|
|
657
|
-
expect(handleReorder).toHaveBeenCalled()
|
|
658
|
-
})
|
|
659
|
-
})
|
|
660
|
-
```
|
|
661
|
-
|
|
662
|
-
### Testing Row Selection
|
|
663
|
-
|
|
664
|
-
```typescript
|
|
665
|
-
import { render, screen, fireEvent } from '@testing-library/react'
|
|
666
|
-
import { DataTable } from "@/components/DataTable";
|
|
667
|
-
|
|
668
|
-
test('row selection works correctly', () => {
|
|
669
|
-
const columns = [{ accessorKey: 'name', header: 'Name' }]
|
|
670
|
-
const data = [
|
|
671
|
-
{ id: '1', name: 'Row 1' },
|
|
672
|
-
{ id: '2', name: 'Row 2' },
|
|
673
|
-
]
|
|
674
|
-
|
|
675
|
-
render(<DataTable columns={columns} data={data} />)
|
|
676
|
-
|
|
677
|
-
const checkboxes = screen.getAllByRole('checkbox')
|
|
678
|
-
|
|
679
|
-
// Select first row
|
|
680
|
-
fireEvent.click(checkboxes[1]) // Skip header checkbox
|
|
681
|
-
|
|
682
|
-
expect(checkboxes[1]).toBeChecked()
|
|
683
|
-
})
|
|
684
|
-
```
|
|
685
|
-
|
|
686
|
-
## Accessibility
|
|
687
|
-
|
|
688
|
-
- **Keyboard Support**: Full keyboard navigation for drag-and-drop
|
|
689
|
-
- Space: Start/stop dragging
|
|
690
|
-
- Arrow keys: Move selected item
|
|
691
|
-
- Escape: Cancel drag operation
|
|
692
|
-
- **ARIA Attributes**:
|
|
693
|
-
- Checkboxes have proper `aria-checked` states
|
|
694
|
-
- Drag handles have `aria-label` (via dnd-kit)
|
|
695
|
-
- Sortable columns announce sort direction
|
|
696
|
-
- **Screen Readers**:
|
|
697
|
-
- Table structure announced correctly
|
|
698
|
-
- Selection changes announced
|
|
699
|
-
- Reorder operations announced
|
|
700
|
-
- **Focus Management**:
|
|
701
|
-
- Keyboard focus visible
|
|
702
|
-
- Focus trapped during drag operations
|
|
703
|
-
- **Color Contrast**: High contrast for text and interactive elements
|
|
704
|
-
|
|
705
|
-
### Accessibility Example
|
|
706
|
-
|
|
707
|
-
```typescript
|
|
708
|
-
// Ensure action buttons have labels
|
|
709
|
-
const columns: ColumnDef<User>[] = [
|
|
710
|
-
{
|
|
711
|
-
id: 'actions',
|
|
712
|
-
header: 'Actions',
|
|
713
|
-
cell: ({ row }) => (
|
|
714
|
-
<ActionButton
|
|
715
|
-
aria-label={`Edit ${row.original.name}`}
|
|
716
|
-
onClick={() => handleEdit(row.original.id)}
|
|
717
|
-
>
|
|
718
|
-
<i className="ri-edit-line" />
|
|
719
|
-
</ActionButton>
|
|
720
|
-
),
|
|
721
|
-
},
|
|
722
|
-
]
|
|
723
|
-
```
|
|
724
|
-
|
|
725
|
-
## Performance
|
|
726
|
-
|
|
727
|
-
| Metric | Value |
|
|
728
|
-
|--------|-------|
|
|
729
|
-
| Bundle size (minified) | ~45kb (excluding dependencies) |
|
|
730
|
-
| Dependencies | TanStack Table (~15kb), dnd-kit (~20kb) |
|
|
731
|
-
| First render | <20ms (100 rows) |
|
|
732
|
-
| Reorder operation | <10ms |
|
|
733
|
-
| Tree-shakeable | ✅ |
|
|
734
|
-
|
|
735
|
-
### Performance Tips
|
|
736
|
-
|
|
737
|
-
1. **Memoize columns**: Define columns outside component or use `useMemo`
|
|
738
|
-
```typescript
|
|
739
|
-
const columns = useMemo(() => [...], [])
|
|
740
|
-
```
|
|
741
|
-
|
|
742
|
-
2. **Virtual scrolling**: For large datasets (1000+ rows), use TanStack Virtual
|
|
743
|
-
```typescript
|
|
744
|
-
import { useVirtualizer } from '@tanstack/react-virtual'
|
|
745
|
-
```
|
|
746
|
-
|
|
747
|
-
3. **Pagination**: Enable pagination for better performance
|
|
748
|
-
```typescript
|
|
749
|
-
// Already included in DataTable
|
|
750
|
-
getPaginationRowModel: getPaginationRowModel()
|
|
751
|
-
```
|
|
752
|
-
|
|
753
|
-
4. **Optimize cell rendering**: Memoize expensive cell components
|
|
754
|
-
```typescript
|
|
755
|
-
const MemoizedCell = memo(({ value }) => <ExpensiveComponent value={value} />)
|
|
756
|
-
```
|
|
757
|
-
|
|
758
|
-
## Migration from Other Tables
|
|
759
|
-
|
|
760
|
-
### From HTML Table
|
|
761
|
-
|
|
762
|
-
```diff
|
|
763
|
-
- <table>
|
|
764
|
-
- <thead>
|
|
765
|
-
- <tr><th>Name</th></tr>
|
|
766
|
-
- </thead>
|
|
767
|
-
- <tbody>
|
|
768
|
-
- <tr><td>{item.name}</td></tr>
|
|
769
|
-
- </tbody>
|
|
770
|
-
- </table>
|
|
771
|
-
|
|
772
|
-
+ <DataTable
|
|
773
|
-
+ columns={[{ accessorKey: 'name', header: 'Name' }]}
|
|
774
|
-
+ data={items}
|
|
775
|
-
+ />
|
|
776
|
-
```
|
|
777
|
-
|
|
778
|
-
### From Material-UI DataGrid
|
|
779
|
-
|
|
780
|
-
```diff
|
|
781
|
-
- import { DataGrid } from '@mui/x-data-grid'
|
|
782
|
-
+ import { DataTable } from "@/components/DataTable";
|
|
783
|
-
+ import { ColumnDef } from '@tanstack/react-table'
|
|
784
|
-
|
|
785
|
-
- <DataGrid rows={data} columns={columns} />
|
|
786
|
-
+ <DataTable data={data} columns={columns} />
|
|
787
|
-
```
|
|
788
|
-
|
|
789
|
-
### From React Table v7
|
|
790
|
-
|
|
791
|
-
```diff
|
|
792
|
-
- import { useTable } from 'react-table'
|
|
793
|
-
+ import { DataTable } from "@/components/DataTable";
|
|
794
|
-
+ import { ColumnDef } from '@tanstack/react-table'
|
|
795
|
-
|
|
796
|
-
- const { getTableProps, rows } = useTable({ columns, data })
|
|
797
|
-
- return <table {...getTableProps()}>...</table>
|
|
798
|
-
|
|
799
|
-
+ return <DataTable columns={columns} data={data} />
|
|
800
|
-
```
|
|
801
|
-
|
|
802
|
-
## Best Practices
|
|
803
|
-
|
|
804
|
-
1. **Always provide unique IDs**: Ensure every data item has a unique `id` property
|
|
805
|
-
```typescript
|
|
806
|
-
const data = items.map((item, index) => ({
|
|
807
|
-
id: item.id || `row-${index}`,
|
|
808
|
-
...item
|
|
809
|
-
}))
|
|
810
|
-
```
|
|
811
|
-
|
|
812
|
-
2. **Memoize column definitions**: Prevent unnecessary re-renders
|
|
813
|
-
```typescript
|
|
814
|
-
const columns = useMemo<ColumnDef<Data>[]>(() => [...], [])
|
|
815
|
-
```
|
|
816
|
-
|
|
817
|
-
3. **Type your data**: Use TypeScript generics for type safety
|
|
818
|
-
```typescript
|
|
819
|
-
interface MyData { id: string; name: string }
|
|
820
|
-
<DataTable<MyData, any> columns={columns} data={data} />
|
|
821
|
-
```
|
|
822
|
-
|
|
823
|
-
4. **Handle reorder events**: Process the new data order when provided
|
|
824
|
-
```typescript
|
|
825
|
-
onRowReorder={(newData) => {
|
|
826
|
-
updateBackend(newData)
|
|
827
|
-
setData(newData)
|
|
828
|
-
}}
|
|
829
|
-
```
|
|
830
|
-
|
|
831
|
-
5. **Provide accessible labels**: Always add aria-labels for icon-only actions
|
|
832
|
-
```typescript
|
|
833
|
-
<ActionButton aria-label="Delete item">
|
|
834
|
-
<i className="ri-delete-bin-line" />
|
|
835
|
-
</ActionButton>
|
|
836
|
-
```
|
|
837
|
-
|
|
838
|
-
6. **Optimize for large datasets**: Use pagination, virtualization, or server-side operations
|
|
839
|
-
```typescript
|
|
840
|
-
// Consider using TanStack Virtual for 1000+ rows
|
|
841
|
-
```
|
|
842
|
-
|
|
843
|
-
7. **Custom empty states**: Provide helpful messages for empty tables
|
|
844
|
-
```typescript
|
|
845
|
-
// Default "No results." message is shown automatically
|
|
846
|
-
// Customize by modifying the table body rendering
|
|
847
|
-
```
|
|
848
|
-
|
|
849
|
-
## Related Components
|
|
850
|
-
|
|
851
|
-
- [Table](./table.md) - Base table components used by DataTable
|
|
852
|
-
- [Checkbox](./checkbox.md) - Used for row selection
|
|
853
|
-
- [Badge](./badge.md) - Useful for status columns
|
|
854
|
-
- [ActionButton](./action-button.md) - Perfect for action columns
|