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,493 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
|
|
3
|
-
import React from "react";
|
|
4
|
-
import { Plus } from "lucide-react";
|
|
5
|
-
import { useVirtualizer } from "@tanstack/react-virtual";
|
|
6
|
-
import { cn } from "../../../utils/cn";
|
|
7
|
-
import { formatPathLabel } from "../../../utils/dataViews/path";
|
|
8
|
-
import type { Sort } from "../../../utils/dataViews/types";
|
|
9
|
-
import { Checkbox } from "../../Checkbox";
|
|
10
|
-
import {
|
|
11
|
-
Table,
|
|
12
|
-
TableBody,
|
|
13
|
-
TableCell,
|
|
14
|
-
TableEndAction,
|
|
15
|
-
TableHead,
|
|
16
|
-
TableHeader,
|
|
17
|
-
TableRow,
|
|
18
|
-
} from "../../Table";
|
|
19
|
-
import { DragList, useDragDrop, useDragItem } from "../../../hooks/useDragDrop";
|
|
20
|
-
import { Cell } from "../cell";
|
|
21
|
-
import { SkeletonBar, skeletonKeys } from "../states";
|
|
22
|
-
import { useInfiniteScroll } from "../../../hooks/useInfiniteScroll";
|
|
23
|
-
import { useDataViewsData, useDataViewsView } from "../context";
|
|
24
|
-
import { markView } from "../slots";
|
|
25
|
-
import type { TableViewProps } from "../types";
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* `DataViews.Table` — rows and columns.
|
|
29
|
-
*
|
|
30
|
-
* Built on the shared `Table` component rather than a bare `<table>`, which is where the 44px
|
|
31
|
-
* header band, the 50px rows, the cell grid, the right-edge fade and the drag-resize handles all
|
|
32
|
-
* come from. Rebuilding those by hand is how this view drifts away from every other table in the
|
|
33
|
-
* product.
|
|
34
|
-
*
|
|
35
|
-
* Columns come from `visibleFields`, which the root resolved once from `fields` + `columns`. The
|
|
36
|
-
* header cells are sort *buttons*: clicking one puts a `sort` in the query and nothing else. The table
|
|
37
|
-
* paints `rows` in the order you handed them over, always — if the arrow points down and the rows
|
|
38
|
-
* are not descending, that is your query's business, not the table's.
|
|
39
|
-
*/
|
|
40
|
-
function TableViewImpl({
|
|
41
|
-
selectable = false,
|
|
42
|
-
onRowClick,
|
|
43
|
-
onRowMove,
|
|
44
|
-
onAddRow,
|
|
45
|
-
addRowLabel = "Add New",
|
|
46
|
-
renderCell,
|
|
47
|
-
className,
|
|
48
|
-
}: TableViewProps) {
|
|
49
|
-
const { rows, visibleFields, getRowId, loading, loadingMore, hasMore, onLoadMore } =
|
|
50
|
-
useDataViewsData();
|
|
51
|
-
const { sort, setSort, selection, setSelection } = useDataViewsView();
|
|
52
|
-
|
|
53
|
-
const ids = rows.map((row, i) => getRowId(row, i));
|
|
54
|
-
|
|
55
|
-
const { DndContext, contextProps, activeId: activeDragId } = useDragDrop({
|
|
56
|
-
mode: "list",
|
|
57
|
-
disabled: !onRowMove,
|
|
58
|
-
onMove: ({ id, to }) => {
|
|
59
|
-
const index = ids.indexOf(String(to));
|
|
60
|
-
if (index < 0) return;
|
|
61
|
-
onRowMove?.({ id, from: null, to: null, index });
|
|
62
|
-
},
|
|
63
|
-
});
|
|
64
|
-
const allSelected = ids.length > 0 && ids.every((id) => selection.includes(id));
|
|
65
|
-
const someSelected = !allSelected && ids.some((id) => selection.includes(id));
|
|
66
|
-
|
|
67
|
-
const toggleRow = (id: string) =>
|
|
68
|
-
setSelection(selection.includes(id) ? selection.filter((s) => s !== id) : [...selection, id]);
|
|
69
|
-
|
|
70
|
-
const toggleAll = () => setSelection(allSelected ? [] : ids);
|
|
71
|
-
|
|
72
|
-
// asc → desc → unsorted, so a third click gets you back to the server's natural order.
|
|
73
|
-
const cycle = (path: string): Sort => {
|
|
74
|
-
if (sort?.path !== path) return { path, direction: "asc" };
|
|
75
|
-
return sort.direction === "asc" ? { path, direction: "desc" } : null;
|
|
76
|
-
};
|
|
77
|
-
|
|
78
|
-
// ── Virtualization ────────────────────────────────────────────────────────
|
|
79
|
-
//
|
|
80
|
-
// A mode the table *enters*, not how it always renders. Below the threshold this whole block is
|
|
81
|
-
// inert and the markup below is exactly what it has always been — which is what keeps the row
|
|
82
|
-
// drag, the column resize and every existing example untouched.
|
|
83
|
-
const scrollRef = React.useRef<HTMLDivElement | null>(null);
|
|
84
|
-
const tableRef = React.useRef<HTMLTableElement | null>(null);
|
|
85
|
-
const virtualize = rows.length > VIRTUALIZE_AFTER;
|
|
86
|
-
|
|
87
|
-
const virtualizer = useVirtualizer({
|
|
88
|
-
count: rows.length,
|
|
89
|
-
getScrollElement: () => scrollRef.current,
|
|
90
|
-
// Exact, not an estimate: rows are 40px by design (Figma's `Table-RowBackgroand-1.1`), so
|
|
91
|
-
// there is nothing to measure and no correction pass.
|
|
92
|
-
estimateSize: () => ROW_HEIGHT,
|
|
93
|
-
overscan: 8,
|
|
94
|
-
enabled: virtualize,
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
usePinnedColumnWidths(tableRef, virtualize);
|
|
98
|
-
|
|
99
|
-
const virtualItems = virtualizer.getVirtualItems();
|
|
100
|
-
const padTop = virtualItems.length ? virtualItems[0].start : 0;
|
|
101
|
-
const padBottom = virtualItems.length
|
|
102
|
-
? virtualizer.getTotalSize() - virtualItems[virtualItems.length - 1].end
|
|
103
|
-
: 0;
|
|
104
|
-
|
|
105
|
-
// Which rows to actually render. The dragged row is always included even when it has scrolled
|
|
106
|
-
// out of the window: dnd-kit tracks a live node, and unmounting it mid-drag drops the drag.
|
|
107
|
-
const windowIndexes = virtualize ? virtualItems.map((v) => v.index) : rows.map((_, i) => i);
|
|
108
|
-
const activeIndex = activeDragId ? ids.indexOf(activeDragId) : -1;
|
|
109
|
-
const renderIndexes =
|
|
110
|
-
activeIndex >= 0 && !windowIndexes.includes(activeIndex)
|
|
111
|
-
? [...windowIndexes, activeIndex].sort((a, b) => a - b)
|
|
112
|
-
: windowIndexes;
|
|
113
|
-
|
|
114
|
-
const { sentinelRef } = useInfiniteScroll({ onLoadMore, hasMore, loading: loading || loadingMore });
|
|
115
|
-
|
|
116
|
-
return (
|
|
117
|
-
<DndContext {...contextProps}>
|
|
118
|
-
{/* Its own edge, matching the inbox and tree panels: this view is a surface on the shell,
|
|
119
|
-
not a fill of it. `overflow-hidden` keeps the rows clipped to the radius. */}
|
|
120
|
-
<div
|
|
121
|
-
className={cn(
|
|
122
|
-
"bg-background-presentation-form-base flex h-full overflow-hidden",
|
|
123
|
-
"border-border-presentation-global-primary rounded-[16px] border",
|
|
124
|
-
className,
|
|
125
|
-
)}
|
|
126
|
-
>
|
|
127
|
-
<div className="flex flex-1 flex-col gap-4 overflow-hidden">
|
|
128
|
-
{/* The scroller and the end action are stacked here with NO gap, so the bar sits flush
|
|
129
|
-
under the table the way it does on the card. `min-h-0` lets the scroller actually
|
|
130
|
-
shrink — a flex item will not go below its content without it. */}
|
|
131
|
-
<div className="flex min-h-0 flex-1 flex-col">
|
|
132
|
-
<div
|
|
133
|
-
ref={scrollRef}
|
|
134
|
-
// `min-w-0` so the scroller can be narrower than the table inside it. Without it a flex
|
|
135
|
-
// item refuses to shrink below its content, so pinning the table to its natural width
|
|
136
|
-
// pushes the whole component wide instead of scrolling within it.
|
|
137
|
-
className="min-w-0 flex-1 overflow-auto rounded-lg"
|
|
138
|
-
>
|
|
139
|
-
{/* Sizes the table, not the footer — the end action now lives outside this scroller.
|
|
140
|
-
Inside an `overflow-auto` scroller a child's `w-full` resolves against the *visible*
|
|
141
|
-
width, so the table needs `w-max` to reach its natural width and scroll; `min-w-full`
|
|
142
|
-
keeps it filling the scroller when the table is narrower. */}
|
|
143
|
-
<div className="w-max min-w-full">
|
|
144
|
-
{/* `overflow-visible` opts out of the primitive's `overflow-hidden` (tailwind-merge
|
|
145
|
-
lets ours win). It has to: a clipping table is its own scrollport, and the sticky
|
|
146
|
-
header would then resolve against a box that never scrolls. Safe here because the
|
|
147
|
-
scroller above is `min-w-0 overflow-auto`, so a wide table scrolls inside it rather
|
|
148
|
-
than pushing the layout. */}
|
|
149
|
-
<Table ref={tableRef} className="w-full overflow-visible">
|
|
150
|
-
{/* The header sticks to the scroller above by default — that lives on `TableHeader`
|
|
151
|
-
in the primitive. Two things this view adds:
|
|
152
|
-
|
|
153
|
-
Opacity. The primitive's header token is translucent, so scrolling rows read
|
|
154
|
-
straight through it; the primitive can't fix that without naming a surface colour
|
|
155
|
-
it doesn't know. Here the surface *is* known — the view root above sets
|
|
156
|
-
`form-base` — so paint that as the background-color (tailwind-merge drops the
|
|
157
|
-
primitive's translucent one, same `bg-color` group) and re-apply the tint as a
|
|
158
|
-
background-image, which stacks above background-color. Composited that is the
|
|
159
|
-
exact colour the header already had, just no longer see-through.
|
|
160
|
-
|
|
161
|
-
And `shadow-none`, because the drop shadow reads as a seam now that the view
|
|
162
|
-
carries its own border. */}
|
|
163
|
-
<TableHeader className="bg-background-presentation-form-base bg-[image:linear-gradient(var(--background-presentation-form-header),var(--background-presentation-form-header))] shadow-none">
|
|
164
|
-
<TableRow>
|
|
165
|
-
{onRowMove && <TableHead isDummy className="w-8" />}
|
|
166
|
-
{selectable && (
|
|
167
|
-
<TableHead isDummy className="w-12">
|
|
168
|
-
{/* Size is stated on both this and the per-row checkbox rather than left to
|
|
169
|
-
`Checkbox`'s default — they have to agree, and relying on the default on
|
|
170
|
-
one side only is what previously made the select-all bigger than the
|
|
171
|
-
column it heads. */}
|
|
172
|
-
<Checkbox
|
|
173
|
-
size="M"
|
|
174
|
-
checked={allSelected ? true : someSelected ? "indeterminate" : false}
|
|
175
|
-
onCheckedChange={toggleAll}
|
|
176
|
-
aria-label="Select all rows"
|
|
177
|
-
/>
|
|
178
|
-
</TableHead>
|
|
179
|
-
)}
|
|
180
|
-
{/* Keyed by position: two fields may share a `path` — the same value shown two
|
|
181
|
-
ways — and keying on it would collide. */}
|
|
182
|
-
{visibleFields.map((field, i) => (
|
|
183
|
-
<TableHead
|
|
184
|
-
key={`${field.path}-${i}`}
|
|
185
|
-
size="M"
|
|
186
|
-
sortType={sort?.path === field.path ? sort.direction : undefined}
|
|
187
|
-
onSort={() => setSort(cycle(field.path))}
|
|
188
|
-
// Without this every sort control announces itself as a bare "Sort ascending",
|
|
189
|
-
// so a screen reader hears one identical button per column.
|
|
190
|
-
sortLabel={field.label ?? formatPathLabel(field.path)}
|
|
191
|
-
>
|
|
192
|
-
{/* Wrapped rather than handed to `Table` as bare text: `truncate` needs a box
|
|
193
|
-
to clip, and the label's parent in the primitive is already `flex min-w-0`
|
|
194
|
-
so this span shrinks and ellipsises instead of wrapping the header row
|
|
195
|
-
onto a second line. */}
|
|
196
|
-
<span className="truncate">{field.label ?? field.path}</span>
|
|
197
|
-
</TableHead>
|
|
198
|
-
))}
|
|
199
|
-
</TableRow>
|
|
200
|
-
</TableHeader>
|
|
201
|
-
|
|
202
|
-
<TableBody>
|
|
203
|
-
{loading && <SkeletonRows fields={visibleFields} grip={Boolean(onRowMove)} selectable={selectable} />}
|
|
204
|
-
{virtualize && padTop > 0 && (
|
|
205
|
-
<tr aria-hidden style={{ height: padTop }} />
|
|
206
|
-
)}
|
|
207
|
-
<DragList ids={ids}>
|
|
208
|
-
{renderIndexes.map((index) => {
|
|
209
|
-
const row = rows[index];
|
|
210
|
-
const id = ids[index];
|
|
211
|
-
const selected = selection.includes(id);
|
|
212
|
-
return (
|
|
213
|
-
<DraggableRow
|
|
214
|
-
key={id}
|
|
215
|
-
id={id}
|
|
216
|
-
draggable={Boolean(onRowMove)}
|
|
217
|
-
state={selected ? "selected" : undefined}
|
|
218
|
-
onClick={onRowClick ? () => onRowClick(row, id) : undefined}
|
|
219
|
-
// A clickable row has to be reachable without a mouse. `<tr>` carries no
|
|
220
|
-
// implicit role, so a bare `onClick` is invisible to the keyboard and to a
|
|
221
|
-
// screen reader; these only appear when the row is actually interactive.
|
|
222
|
-
tabIndex={onRowClick ? 0 : undefined}
|
|
223
|
-
role={onRowClick ? "button" : undefined}
|
|
224
|
-
onKeyDown={
|
|
225
|
-
onRowClick
|
|
226
|
-
? (e) => {
|
|
227
|
-
if (e.key !== "Enter" && e.key !== " ") return;
|
|
228
|
-
if (e.target !== e.currentTarget) return;
|
|
229
|
-
e.preventDefault();
|
|
230
|
-
onRowClick(row, id);
|
|
231
|
-
}
|
|
232
|
-
: undefined
|
|
233
|
-
}
|
|
234
|
-
className={cn(
|
|
235
|
-
// 40px per Figma's `Table-RowBackgroand-1.1`. `Table`'s body cells default
|
|
236
|
-
// to 50, and the two live on different elements, so the cells below must be
|
|
237
|
-
// told as well or CSS keeps the larger.
|
|
238
|
-
"h-[40px]",
|
|
239
|
-
"focus-visible:ring-border-presentation-state-focus outline-none focus-visible:ring-2",
|
|
240
|
-
onRowClick && "cursor-pointer",
|
|
241
|
-
)}
|
|
242
|
-
>
|
|
243
|
-
{onRowMove && <GripCell />}
|
|
244
|
-
{selectable && (
|
|
245
|
-
<TableCell isDummy className="min-h-[40px] w-12" onClick={(e) => e.stopPropagation()}>
|
|
246
|
-
{/* What `TableCheckbox` renders, inlined: its props are typed as button
|
|
247
|
-
attributes, so it cannot express a controlled checkbox. */}
|
|
248
|
-
<div className="flex items-center justify-center">
|
|
249
|
-
<Checkbox
|
|
250
|
-
size="M"
|
|
251
|
-
checked={selected}
|
|
252
|
-
onCheckedChange={() => toggleRow(id)}
|
|
253
|
-
aria-label="Select row"
|
|
254
|
-
/>
|
|
255
|
-
</div>
|
|
256
|
-
</TableCell>
|
|
257
|
-
)}
|
|
258
|
-
{visibleFields.map((field, i) => {
|
|
259
|
-
// `undefined` means "you paint it" — distinct from `null`, which is a
|
|
260
|
-
// deliberate blank.
|
|
261
|
-
const custom = renderCell?.({ field, row, id, index, fields: visibleFields });
|
|
262
|
-
// `fade={false}` and clip instead. The fade is a `mask-image` on every
|
|
263
|
-
// cell, close to free on its own but very expensive once a sticky header
|
|
264
|
-
// repaints the region each scroll frame: measured on this page,
|
|
265
|
-
// mask+sticky costs ~61ms/frame against ~29ms with the mask off and
|
|
266
|
-
// ~17ms with neither. `overflow-hidden` is passed back because
|
|
267
|
-
// `fade={false}` otherwise switches the cell to `overflow-visible`, and
|
|
268
|
-
// the text would spill into the next column.
|
|
269
|
-
return (
|
|
270
|
-
<TableCell
|
|
271
|
-
key={`${field.path}-${i}`}
|
|
272
|
-
className="min-h-[40px]"
|
|
273
|
-
fade={false}
|
|
274
|
-
childrenClassName="overflow-hidden"
|
|
275
|
-
>
|
|
276
|
-
{/* `isolate` confines the Badge's mix-blend-luminosity to a local
|
|
277
|
-
stacking context and `transform-gpu` promotes it to its own layer, so
|
|
278
|
-
the table's post-mount column reflow repaints cleanly instead of
|
|
279
|
-
leaving a ghosted badge frame. */}
|
|
280
|
-
<span className="isolate inline-flex transform-gpu">
|
|
281
|
-
{custom === undefined ? <Cell field={field} row={row} /> : custom}
|
|
282
|
-
</span>
|
|
283
|
-
</TableCell>
|
|
284
|
-
);
|
|
285
|
-
})}
|
|
286
|
-
</DraggableRow>
|
|
287
|
-
);
|
|
288
|
-
})}
|
|
289
|
-
</DragList>
|
|
290
|
-
{virtualize && padBottom > 0 && (
|
|
291
|
-
<tr aria-hidden style={{ height: padBottom }} />
|
|
292
|
-
)}
|
|
293
|
-
{/* The trigger. A row of its own rather than an element after the table, so it sits
|
|
294
|
-
inside the same scroller the rows do. */}
|
|
295
|
-
{hasMore && !loading && (
|
|
296
|
-
<tr ref={sentinelRef as React.Ref<HTMLTableRowElement>} aria-hidden>
|
|
297
|
-
<td style={{ height: 1, padding: 0, border: 0 }} colSpan={100} />
|
|
298
|
-
</tr>
|
|
299
|
-
)}
|
|
300
|
-
{loadingMore && (
|
|
301
|
-
<SkeletonRows
|
|
302
|
-
rows={2}
|
|
303
|
-
fields={visibleFields}
|
|
304
|
-
grip={Boolean(onRowMove)}
|
|
305
|
-
selectable={selectable}
|
|
306
|
-
/>
|
|
307
|
-
)}
|
|
308
|
-
</TableBody>
|
|
309
|
-
</Table>
|
|
310
|
-
</div>
|
|
311
|
-
</div>
|
|
312
|
-
{/* Outside the scroller, deliberately: as a sibling its width is the component's visible
|
|
313
|
-
width, so it spans the full outer container and stays put while the columns scroll
|
|
314
|
-
sideways under it — instead of stretching to the table's scrollable width and sliding
|
|
315
|
-
away like a normal row. Same placement the form Table field uses. */}
|
|
316
|
-
{onAddRow && (
|
|
317
|
-
<TableEndAction onClick={onAddRow}>
|
|
318
|
-
<Plus className="h-4 w-4" aria-hidden />
|
|
319
|
-
{addRowLabel}
|
|
320
|
-
</TableEndAction>
|
|
321
|
-
)}
|
|
322
|
-
</div>
|
|
323
|
-
</div>
|
|
324
|
-
</div>
|
|
325
|
-
</DndContext>
|
|
326
|
-
);
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
/**
|
|
330
|
-
* A row that can be picked up.
|
|
331
|
-
*
|
|
332
|
-
* `TableRow` forwards its ref, so the `<tr>` itself is the draggable — no wrapper element, which
|
|
333
|
-
* a table would not accept between `<tbody>` and `<tr>` anyway.
|
|
334
|
-
*
|
|
335
|
-
* The drag listeners go on the grip, not the row: a row is clickable, and a row that is also a
|
|
336
|
-
* drag handle makes selecting text or hitting a button inside it a gamble.
|
|
337
|
-
*/
|
|
338
|
-
function DraggableRow({
|
|
339
|
-
id,
|
|
340
|
-
draggable,
|
|
341
|
-
children,
|
|
342
|
-
...props
|
|
343
|
-
}: React.ComponentProps<typeof TableRow> & { id: string; draggable: boolean }) {
|
|
344
|
-
const { ref, handleProps, style, isDragging } = useDragItem(id, !draggable);
|
|
345
|
-
|
|
346
|
-
return (
|
|
347
|
-
<DragHandleContext.Provider value={draggable ? handleProps : null}>
|
|
348
|
-
<TableRow
|
|
349
|
-
ref={ref}
|
|
350
|
-
style={style}
|
|
351
|
-
{...props}
|
|
352
|
-
className={cn(props.className, isDragging && "opacity-40")}
|
|
353
|
-
>
|
|
354
|
-
{children}
|
|
355
|
-
</TableRow>
|
|
356
|
-
</DragHandleContext.Provider>
|
|
357
|
-
);
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
/** The listeners the grip needs, handed down from the row that owns them. */
|
|
361
|
-
const DragHandleContext = React.createContext<Record<string, unknown> | null>(null);
|
|
362
|
-
|
|
363
|
-
/** How many shimmer rows to lay down. Enough to fill the fold — not a guess at what is coming. */
|
|
364
|
-
const SKELETON_ROWS = 8;
|
|
365
|
-
|
|
366
|
-
/** Figma's `Table-RowBackgroand-1.1`. Exact, which is what makes virtualization measurement-free. */
|
|
367
|
-
const ROW_HEIGHT = 50;
|
|
368
|
-
|
|
369
|
-
/**
|
|
370
|
-
* Below this many rows the table renders every one of them, exactly as it always has.
|
|
371
|
-
*
|
|
372
|
-
* Virtualization is not free here: the table is `table-layout: auto` with a 200px per-cell
|
|
373
|
-
* minimum, so column widths are computed from whatever rows are currently mounted. Rendering only
|
|
374
|
-
* a window of them makes the widths change as you scroll — unless they are pinned first, which is
|
|
375
|
-
* what `usePinnedColumnWidths` does. None of that is worth doing to a table of 40 rows.
|
|
376
|
-
*/
|
|
377
|
-
const VIRTUALIZE_AFTER = 300;
|
|
378
|
-
|
|
379
|
-
/**
|
|
380
|
-
* Freeze the column widths before the rows start disappearing.
|
|
381
|
-
*
|
|
382
|
-
* The order matters and is the whole difficulty. `table-layout: auto` sizes columns from the rows
|
|
383
|
-
* that are *mounted*, so by the time virtualization has swapped thousands of rows for a window of
|
|
384
|
-
* thirty, the widths have already collapsed to fit that window — measuring then pins the collapsed
|
|
385
|
-
* numbers, and the table ends up about half its width with content spilling between columns. So
|
|
386
|
-
* the widths are remembered on every render while the table is still whole, and those remembered
|
|
387
|
-
* numbers are what get pinned at the moment it stops being whole.
|
|
388
|
-
*
|
|
389
|
-
* The table's own width is pinned too: under `fixed` the column widths are read as proportions of
|
|
390
|
-
* it, and the table is `w-full`, so leaving it alone squeezes every column into the container.
|
|
391
|
-
*/
|
|
392
|
-
function usePinnedColumnWidths(
|
|
393
|
-
tableRef: React.RefObject<HTMLTableElement | null>,
|
|
394
|
-
virtualize: boolean,
|
|
395
|
-
) {
|
|
396
|
-
const naturalWidths = React.useRef<number[] | null>(null);
|
|
397
|
-
const pinned = React.useRef(false);
|
|
398
|
-
|
|
399
|
-
// Deliberately no dependency array: the widths have to be re-read as rows accumulate, right up
|
|
400
|
-
// to the render before the threshold is crossed.
|
|
401
|
-
React.useLayoutEffect(() => {
|
|
402
|
-
const table = tableRef.current;
|
|
403
|
-
if (!table) return;
|
|
404
|
-
const heads = [...table.querySelectorAll("thead th")] as HTMLTableCellElement[];
|
|
405
|
-
|
|
406
|
-
if (!virtualize) {
|
|
407
|
-
naturalWidths.current = heads.map((th) => th.getBoundingClientRect().width);
|
|
408
|
-
if (pinned.current) {
|
|
409
|
-
table.style.tableLayout = "";
|
|
410
|
-
table.style.removeProperty("width");
|
|
411
|
-
heads.forEach((th) => th.style.removeProperty("width"));
|
|
412
|
-
pinned.current = false;
|
|
413
|
-
}
|
|
414
|
-
return;
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
if (pinned.current) return;
|
|
418
|
-
const widths = naturalWidths.current;
|
|
419
|
-
if (!widths || widths.length !== heads.length) return;
|
|
420
|
-
heads.forEach((th, i) => {
|
|
421
|
-
th.style.width = `${widths[i]}px`;
|
|
422
|
-
});
|
|
423
|
-
table.style.width = `${widths.reduce((sum, w) => sum + w, 0)}px`;
|
|
424
|
-
table.style.tableLayout = "fixed";
|
|
425
|
-
pinned.current = true;
|
|
426
|
-
});
|
|
427
|
-
}
|
|
428
|
-
|
|
429
|
-
/**
|
|
430
|
-
* The loading table.
|
|
431
|
-
*
|
|
432
|
-
* Built from the same `TableRow`/`TableCell` a real row uses, with one cell per visible field, so
|
|
433
|
-
* the columns sit at exactly the widths the data will land in and nothing shifts when it does.
|
|
434
|
-
* The header above is untouched — it comes from `visibleFields`, not from `rows`.
|
|
435
|
-
*/
|
|
436
|
-
function SkeletonRows({
|
|
437
|
-
fields,
|
|
438
|
-
grip,
|
|
439
|
-
selectable,
|
|
440
|
-
rows = SKELETON_ROWS,
|
|
441
|
-
}: {
|
|
442
|
-
fields: readonly { path: string }[];
|
|
443
|
-
grip: boolean;
|
|
444
|
-
selectable: boolean;
|
|
445
|
-
rows?: number;
|
|
446
|
-
}) {
|
|
447
|
-
return (
|
|
448
|
-
<>
|
|
449
|
-
{skeletonKeys(rows).map((row) => (
|
|
450
|
-
<TableRow key={`skeleton-${row}`} className="h-[40px]">
|
|
451
|
-
{grip && <TableCell isDummy className="h-[40px] w-8" />}
|
|
452
|
-
{selectable && <TableCell isDummy className="h-[40px] w-12" />}
|
|
453
|
-
{fields.map((field, i) => (
|
|
454
|
-
<TableCell
|
|
455
|
-
key={`${field.path}-${i}`}
|
|
456
|
-
className="min-h-[40px]"
|
|
457
|
-
fade={false}
|
|
458
|
-
childrenClassName="overflow-hidden"
|
|
459
|
-
>
|
|
460
|
-
{/* Widths cycle rather than repeat, so a column of bars reads as text that has not
|
|
461
|
-
arrived instead of as a grid. */}
|
|
462
|
-
<SkeletonBar className={["w-[70%]", "w-[45%]", "w-[85%]", "w-[60%]"][(row + i) % 4]} />
|
|
463
|
-
</TableCell>
|
|
464
|
-
))}
|
|
465
|
-
</TableRow>
|
|
466
|
-
))}
|
|
467
|
-
</>
|
|
468
|
-
);
|
|
469
|
-
}
|
|
470
|
-
|
|
471
|
-
/** The 2×3 grip. Only rendered when the table is reorderable. */
|
|
472
|
-
function GripCell() {
|
|
473
|
-
const handleProps = React.useContext(DragHandleContext);
|
|
474
|
-
return (
|
|
475
|
-
<TableCell isDummy className="h-[40px] w-8" onClick={(e) => e.stopPropagation()}>
|
|
476
|
-
<span
|
|
477
|
-
{...handleProps}
|
|
478
|
-
aria-label="Reorder row"
|
|
479
|
-
className={cn(
|
|
480
|
-
"text-content-presentation-global-tertiary flex cursor-grab items-center justify-center",
|
|
481
|
-
"active:cursor-grabbing",
|
|
482
|
-
)}
|
|
483
|
-
>
|
|
484
|
-
<i className="ri-draggable text-[16px]" aria-hidden />
|
|
485
|
-
</span>
|
|
486
|
-
</TableCell>
|
|
487
|
-
);
|
|
488
|
-
}
|
|
489
|
-
|
|
490
|
-
export const TableView = markView(TableViewImpl, {
|
|
491
|
-
defaultId: "table",
|
|
492
|
-
defaultLabel: "List",
|
|
493
|
-
});
|