@cube-dev/ui-kit 0.156.0 → 0.157.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/dist/CHANGELOG.md +220 -0
- package/dist/_internal/hooks/use-chained-callback.js +1 -1
- package/dist/_internal/hooks/use-debounced-value.js +1 -1
- package/dist/_internal/hooks/use-deprecation-warning.js +1 -1
- package/dist/_internal/hooks/use-event.js +1 -1
- package/dist/_internal/hooks/use-is-first-render.js +1 -1
- package/dist/_internal/hooks/use-sync-ref.js +1 -1
- package/dist/_internal/hooks/use-timer/timer.js +1 -1
- package/dist/_internal/hooks/use-timer/use-timer.js +1 -1
- package/dist/_internal/hooks/use-warn.js +1 -1
- package/dist/components/Block.js +1 -1
- package/dist/components/CollectionItem.js +1 -1
- package/dist/components/GlobalStyles.js +1 -1
- package/dist/components/GridProvider.js +1 -1
- package/dist/components/HiddenInput.js +1 -1
- package/dist/components/Root.js +1 -1
- package/dist/components/actions/Action/Action.js +1 -1
- package/dist/components/actions/Banner/Banner.js +1 -1
- package/dist/components/actions/Button/Button.js +1 -1
- package/dist/components/actions/ButtonGroup/ButtonGroup.js +1 -1
- package/dist/components/actions/ButtonSplit/ButtonSplit.js +1 -1
- package/dist/components/actions/ButtonSplit/context.js +1 -1
- package/dist/components/actions/CommandMenu/CommandMenu.js +1 -1
- package/dist/components/actions/CommandMenu/styled.js +1 -1
- package/dist/components/actions/ItemAction/ItemAction.js +1 -1
- package/dist/components/actions/ItemActionContext.js +1 -1
- package/dist/components/actions/ItemButton/ItemButton.js +1 -1
- package/dist/components/actions/Link/Link.js +1 -1
- package/dist/components/actions/Menu/Menu.js +1 -1
- package/dist/components/actions/Menu/MenuItem.js +1 -1
- package/dist/components/actions/Menu/MenuSection.js +1 -1
- package/dist/components/actions/Menu/MenuTrigger.js +1 -1
- package/dist/components/actions/Menu/SubMenuTrigger.js +1 -1
- package/dist/components/actions/Menu/SubmenuTriggerContext.js +1 -1
- package/dist/components/actions/Menu/context.js +1 -1
- package/dist/components/actions/Menu/styled.js +1 -1
- package/dist/components/actions/index.js +1 -1
- package/dist/components/actions/use-action.js +1 -1
- package/dist/components/actions/use-anchored-menu.js +1 -1
- package/dist/components/actions/use-context-menu.js +42 -44
- package/dist/components/actions/use-context-menu.js.map +1 -1
- package/dist/components/content/ActiveZone/ActiveZone.js +1 -1
- package/dist/components/content/Alert/Alert.js +1 -1
- package/dist/components/content/Alert/use-alert.js +1 -1
- package/dist/components/content/Avatar/Avatar.js +1 -1
- package/dist/components/content/Badge/Badge.js +1 -1
- package/dist/components/content/Card/Card.js +1 -1
- package/dist/components/content/Content.js +1 -1
- package/dist/components/content/CopyPasteBlock/CopyPasteBlock.js +1 -1
- package/dist/components/content/CopySnippet/CopySnippet.js +1 -1
- package/dist/components/content/Disclosure/Disclosure.js +1 -1
- package/dist/components/content/Divider.js +1 -1
- package/dist/components/content/Footer.js +1 -1
- package/dist/components/content/Header.js +1 -1
- package/dist/components/content/HotKeys/HotKeys.js +1 -1
- package/dist/components/content/InfoBadge/InfoBadge.js +1 -1
- package/dist/components/content/InlineInput/InlineInput.js +1 -1
- package/dist/components/content/Item/Item.js +1 -1
- package/dist/components/content/ItemBadge/ItemBadge.js +1 -1
- package/dist/components/content/ItemCard/ItemCard.js +1 -1
- package/dist/components/content/Layout/GridLayout.js +1 -1
- package/dist/components/content/Layout/Layout.js +1 -1
- package/dist/components/content/Layout/LayoutBlock.js +1 -1
- package/dist/components/content/Layout/LayoutCenter.js +1 -1
- package/dist/components/content/Layout/LayoutContainer.js +1 -1
- package/dist/components/content/Layout/LayoutContent.js +1 -1
- package/dist/components/content/Layout/LayoutContext.js +1 -1
- package/dist/components/content/Layout/LayoutFlex.js +1 -1
- package/dist/components/content/Layout/LayoutFooter.js +1 -1
- package/dist/components/content/Layout/LayoutGrid.js +1 -1
- package/dist/components/content/Layout/LayoutHeader.js +1 -1
- package/dist/components/content/Layout/LayoutPane.js +1 -1
- package/dist/components/content/Layout/LayoutPanel.js +1 -1
- package/dist/components/content/Layout/LayoutPanelHeader.js +1 -1
- package/dist/components/content/Layout/LayoutToolbar.js +1 -1
- package/dist/components/content/Layout/hooks/useTinyScrollbar.js +1 -1
- package/dist/components/content/Layout/index.js +1 -1
- package/dist/components/content/Layout/utils.js +1 -1
- package/dist/components/content/Paragraph.js +1 -1
- package/dist/components/content/Placeholder/Placeholder.js +1 -1
- package/dist/components/content/PrismCode/PrismCode.js +1 -1
- package/dist/components/content/PrismCode/prismSetup.js +1 -1
- package/dist/components/content/PrismDiffCode/PrismDiffCode.js +1 -1
- package/dist/components/content/Result/Result.js +1 -1
- package/dist/components/content/Skeleton/Skeleton.js +1 -1
- package/dist/components/content/Tag/Tag.js +2 -2
- package/dist/components/content/Tag/Tag.js.map +1 -1
- package/dist/components/content/Text.d.ts +14 -14
- package/dist/components/content/Text.js +1 -1
- package/dist/components/content/TextItem/TextItem.js +1 -1
- package/dist/components/content/Title.js +1 -1
- package/dist/components/content/Tree/Tree.js +1 -1
- package/dist/components/content/Tree/TreeNode.js +1 -1
- package/dist/components/content/Tree/styled.js +1 -1
- package/dist/components/content/Tree/tree-index.js +1 -1
- package/dist/components/content/Tree/use-checkbox-tree.js +1 -1
- package/dist/components/content/Tree/use-load-data.js +1 -1
- package/dist/components/content/highlightText.js +1 -1
- package/dist/components/content/use-auto-tooltip.js +1 -1
- package/dist/components/data/DataTable/DataTable.d.ts +13 -0
- package/dist/components/data/DataTable/DataTable.js +246 -0
- package/dist/components/data/DataTable/DataTable.js.map +1 -0
- package/dist/components/data/DataTable/index.d.ts +3 -0
- package/dist/components/data/DataTable/types.d.ts +145 -0
- package/dist/components/data/ItemTable/ItemTable.d.ts +19 -0
- package/dist/components/data/ItemTable/ItemTable.js +350 -0
- package/dist/components/data/ItemTable/ItemTable.js.map +1 -0
- package/dist/components/data/ItemTable/ItemTableBulkBar.d.ts +23 -0
- package/dist/components/data/ItemTable/ItemTableBulkBar.js +131 -0
- package/dist/components/data/ItemTable/ItemTableBulkBar.js.map +1 -0
- package/dist/components/data/ItemTable/ItemTableDragPreview.js +46 -0
- package/dist/components/data/ItemTable/ItemTableDragPreview.js.map +1 -0
- package/dist/components/data/ItemTable/ItemTableFooter.js +79 -0
- package/dist/components/data/ItemTable/ItemTableFooter.js.map +1 -0
- package/dist/components/data/ItemTable/ItemTableToolbar.d.ts +34 -0
- package/dist/components/data/ItemTable/ItemTableToolbar.js +91 -0
- package/dist/components/data/ItemTable/ItemTableToolbar.js.map +1 -0
- package/dist/components/data/ItemTable/index.d.ts +4 -0
- package/dist/components/data/ItemTable/types.d.ts +327 -0
- package/dist/components/data/TableBase/ColumnResizer.js +70 -0
- package/dist/components/data/TableBase/ColumnResizer.js.map +1 -0
- package/dist/components/data/TableBase/RowCollection.js +99 -0
- package/dist/components/data/TableBase/RowCollection.js.map +1 -0
- package/dist/components/data/TableBase/TableRow.js +89 -0
- package/dist/components/data/TableBase/TableRow.js.map +1 -0
- package/dist/components/data/TableBase/TableView.d.ts +22 -0
- package/dist/components/data/TableBase/TableView.js +921 -0
- package/dist/components/data/TableBase/TableView.js.map +1 -0
- package/dist/components/data/TableBase/index.d.ts +5 -0
- package/dist/components/data/TableBase/row-menu.js +40 -0
- package/dist/components/data/TableBase/row-menu.js.map +1 -0
- package/dist/components/data/TableBase/styled.d.ts +5 -0
- package/dist/components/data/TableBase/styled.js +532 -0
- package/dist/components/data/TableBase/styled.js.map +1 -0
- package/dist/components/data/TableBase/types.d.ts +160 -0
- package/dist/components/data/TableBase/types.js +31 -0
- package/dist/components/data/TableBase/types.js.map +1 -0
- package/dist/components/data/TableBase/use-cell-selection.d.ts +3 -0
- package/dist/components/data/TableBase/use-cell-selection.js +0 -0
- package/dist/components/data/TableBase/use-cell-selection.js.map +1 -0
- package/dist/components/data/TableBase/use-container-width.js +35 -0
- package/dist/components/data/TableBase/use-container-width.js.map +1 -0
- package/dist/components/data/TableBase/use-row-move-animation.js +90 -0
- package/dist/components/data/TableBase/use-row-move-animation.js.map +1 -0
- package/dist/components/data/TableBase/use-scrollability.js +49 -0
- package/dist/components/data/TableBase/use-scrollability.js.map +1 -0
- package/dist/components/data/TableBase/use-table-columns.d.ts +2 -0
- package/dist/components/data/TableBase/use-table-columns.js +166 -0
- package/dist/components/data/TableBase/use-table-columns.js.map +1 -0
- package/dist/components/data/TableBase/use-table-search.js +64 -0
- package/dist/components/data/TableBase/use-table-search.js.map +1 -0
- package/dist/components/data/TableBase/use-table-selection.d.ts +4 -0
- package/dist/components/data/TableBase/use-table-selection.js +233 -0
- package/dist/components/data/TableBase/use-table-selection.js.map +1 -0
- package/dist/components/data/TableBase/use-table-sort.js +91 -0
- package/dist/components/data/TableBase/use-table-sort.js.map +1 -0
- package/dist/components/data/TableBase/use-table-sorts.js +97 -0
- package/dist/components/data/TableBase/use-table-sorts.js.map +1 -0
- package/dist/components/data/TableBase/use-table-storage.d.ts +8 -0
- package/dist/components/data/TableBase/use-table-storage.js +58 -0
- package/dist/components/data/TableBase/use-table-storage.js.map +1 -0
- package/dist/components/data/index.d.ts +10 -0
- package/dist/components/fields/Checkbox/Checkbox.js +1 -1
- package/dist/components/fields/Checkbox/CheckboxGroup.js +1 -1
- package/dist/components/fields/Checkbox/context.js +1 -1
- package/dist/components/fields/ColorInput/ColorInput.d.ts +67 -0
- package/dist/components/fields/ColorInput/ColorInput.js +230 -0
- package/dist/components/fields/ColorInput/ColorInput.js.map +1 -0
- package/dist/components/fields/ColorInput/index.d.ts +2 -0
- package/dist/components/fields/ColorPicker/ColorPicker.d.ts +34 -37
- package/dist/components/fields/ColorPicker/ColorPicker.js +131 -182
- package/dist/components/fields/ColorPicker/ColorPicker.js.map +1 -1
- package/dist/components/fields/ColorPicker/index.d.ts +1 -3
- package/dist/components/fields/ColorSwatchGroup/ColorSwatchGroup.d.ts +50 -0
- package/dist/components/fields/ColorSwatchGroup/ColorSwatchGroup.js +269 -0
- package/dist/components/fields/ColorSwatchGroup/ColorSwatchGroup.js.map +1 -0
- package/dist/components/fields/ColorSwatchGroup/index.d.ts +2 -0
- package/dist/components/fields/ComboBox/ComboBox.js +1 -1
- package/dist/components/fields/CommandTextArea/CommandTextArea.js +1 -1
- package/dist/components/fields/CommandTextArea/caretPosition.js +1 -1
- package/dist/components/fields/CommandTextArea/useCaretAnchor.js +1 -1
- package/dist/components/fields/DatePicker/DateInput.js +1 -1
- package/dist/components/fields/DatePicker/DateInputBase.js +1 -1
- package/dist/components/fields/DatePicker/DatePicker.js +1 -1
- package/dist/components/fields/DatePicker/DatePickerButton.js +1 -1
- package/dist/components/fields/DatePicker/DatePickerElement.js +1 -1
- package/dist/components/fields/DatePicker/DatePickerInput.js +1 -1
- package/dist/components/fields/DatePicker/DatePickerSegment.js +1 -1
- package/dist/components/fields/DatePicker/DateRangePicker.js +1 -1
- package/dist/components/fields/DatePicker/DateRangeSeparatedPicker.js +1 -1
- package/dist/components/fields/DatePicker/MonthPicker.js +1 -1
- package/dist/components/fields/DatePicker/PeriodPicker.js +1 -1
- package/dist/components/fields/DatePicker/QuarterPicker.js +1 -1
- package/dist/components/fields/DatePicker/TimeInput.js +1 -1
- package/dist/components/fields/DatePicker/WeekPicker.js +1 -1
- package/dist/components/fields/DatePicker/YearPicker.js +1 -1
- package/dist/components/fields/DatePicker/parseDate.js +1 -1
- package/dist/components/fields/DatePicker/period.js +1 -1
- package/dist/components/fields/DatePicker/props.js +1 -1
- package/dist/components/fields/DatePicker/utils.js +1 -1
- package/dist/components/fields/FileInput/FileInput.js +1 -1
- package/dist/components/fields/FilterListBox/FilterListBox.js +2 -1
- package/dist/components/fields/FilterListBox/FilterListBox.js.map +1 -1
- package/dist/components/fields/FilterPicker/FilterPicker.js +6 -1
- package/dist/components/fields/FilterPicker/FilterPicker.js.map +1 -1
- package/dist/components/fields/Input/Input.js +2 -2
- package/dist/components/fields/ListBox/DraggableListBox.js +1 -1
- package/dist/components/fields/ListBox/ListBox.d.ts +7 -0
- package/dist/components/fields/ListBox/ListBox.js +4 -3
- package/dist/components/fields/ListBox/ListBox.js.map +1 -1
- package/dist/components/fields/ListBoxPopover/ListBoxPopover.js +1 -1
- package/dist/components/fields/ListBoxPopover/listNavigation.js +1 -1
- package/dist/components/fields/ListBoxPopover/useCompositeFocus.js +1 -1
- package/dist/components/fields/NumberInput/NumberInput.js +1 -1
- package/dist/components/fields/NumberInput/StepButton.js +1 -1
- package/dist/components/fields/PasswordInput/PasswordInput.d.ts +2 -2
- package/dist/components/fields/PasswordInput/PasswordInput.js +12 -2
- package/dist/components/fields/PasswordInput/PasswordInput.js.map +1 -1
- package/dist/components/fields/Picker/Picker.js +6 -1
- package/dist/components/fields/Picker/Picker.js.map +1 -1
- package/dist/components/fields/RadioGroup/Radio.d.ts +2 -2
- package/dist/components/fields/RadioGroup/Radio.js +4 -4
- package/dist/components/fields/RadioGroup/Radio.js.map +1 -1
- package/dist/components/fields/RadioGroup/RadioGroup.js +1 -1
- package/dist/components/fields/RadioGroup/context.js +1 -1
- package/dist/components/fields/SearchComboBox/SearchComboBox.js +1 -1
- package/dist/components/fields/SearchInput/SearchInput.d.ts +2 -2
- package/dist/components/fields/SearchInput/SearchInput.js +17 -4
- package/dist/components/fields/SearchInput/SearchInput.js.map +1 -1
- package/dist/components/fields/Select/Select.js +1 -1
- package/dist/components/fields/Slider/Gradation.js +1 -1
- package/dist/components/fields/Slider/HueSlider.js +1 -1
- package/dist/components/fields/Slider/RangeSlider.js +1 -1
- package/dist/components/fields/Slider/Slider.js +1 -1
- package/dist/components/fields/Slider/SliderBase.js +1 -1
- package/dist/components/fields/Slider/SliderThumb.js +1 -1
- package/dist/components/fields/Slider/SliderTrack.js +1 -1
- package/dist/components/fields/Slider/elements.js +1 -1
- package/dist/components/fields/Slider/index.js +1 -1
- package/dist/components/fields/Switch/Switch.js +1 -1
- package/dist/components/fields/TextArea/TextArea.d.ts +2 -2
- package/dist/components/fields/TextArea/TextArea.js +12 -5
- package/dist/components/fields/TextArea/TextArea.js.map +1 -1
- package/dist/components/fields/TextInput/TextInput.d.ts +2 -2
- package/dist/components/fields/TextInput/TextInput.js +15 -3
- package/dist/components/fields/TextInput/TextInput.js.map +1 -1
- package/dist/components/fields/TextInput/TextInputBase.d.ts +17 -1
- package/dist/components/fields/TextInput/TextInputBase.js +1 -1
- package/dist/components/fields/TextInput/TextInputBase.js.map +1 -1
- package/dist/components/fields/TextInput/index.d.ts +1 -1
- package/dist/components/fields/TextInputMapper/TextInputMapper.js +1 -1
- package/dist/components/fields/{ColorPicker/ColorPickerPanel.js → color/ColorPanel.js} +14 -11
- package/dist/components/fields/color/ColorPanel.js.map +1 -0
- package/dist/components/fields/color/ColorSwatch.d.ts +22 -0
- package/dist/components/fields/color/ColorSwatch.js +58 -0
- package/dist/components/fields/color/ColorSwatch.js.map +1 -0
- package/dist/components/fields/{ColorPicker → color}/channels.d.ts +1 -1
- package/dist/components/fields/{ColorPicker → color}/channels.js +2 -2
- package/dist/components/fields/color/channels.js.map +1 -0
- package/dist/components/fields/color/color.d.ts +21 -0
- package/dist/components/fields/{ColorPicker → color}/color.js +2 -2
- package/dist/components/fields/color/color.js.map +1 -0
- package/dist/components/fields/color/context.js +20 -0
- package/dist/components/fields/color/context.js.map +1 -0
- package/dist/components/fields/color/index.d.ts +4 -0
- package/dist/components/fields/index.d.ts +10 -4
- package/dist/components/form/FieldWrapper/FieldWrapper.js +1 -1
- package/dist/components/form/Form/Field.js +1 -1
- package/dist/components/form/Form/Form.js +1 -1
- package/dist/components/form/Form/ResetButton/ResetButton.js +1 -1
- package/dist/components/form/Form/SubmitButton/SubmitButton.js +1 -1
- package/dist/components/form/Form/SubmitError.js +1 -1
- package/dist/components/form/Form/index.js +1 -1
- package/dist/components/form/Form/use-field/use-field-props.js +1 -1
- package/dist/components/form/Form/use-field/use-field.js +1 -1
- package/dist/components/form/Form/use-form.js +1 -1
- package/dist/components/form/Form/validation.js +1 -1
- package/dist/components/form/Label.js +1 -1
- package/dist/components/form/validation/ValidationIndicator.js +1 -1
- package/dist/components/form/validation/resolve-validation-props.js +1 -1
- package/dist/components/form/validation/use-validation-props.js +1 -1
- package/dist/components/form/wrapper.js +1 -1
- package/dist/components/helpers/DisplayTransition/DisplayTransition.js +1 -1
- package/dist/components/helpers/IconSwitch/IconSwitch.d.ts +26 -0
- package/dist/components/helpers/IconSwitch/IconSwitch.js +1 -1
- package/dist/components/layout/Board/Board.js +1 -1
- package/dist/components/layout/Board/BoardProvider.js +1 -1
- package/dist/components/layout/Board/BoardResponsive.js +1 -1
- package/dist/components/layout/Board/Widget.js +1 -1
- package/dist/components/layout/Board/WidgetHost.js +1 -1
- package/dist/components/layout/Board/board-context.js +1 -1
- package/dist/components/layout/Board/board-store.js +1 -1
- package/dist/components/layout/Board/grid-core/calculate.js +1 -1
- package/dist/components/layout/Board/grid-core/collision.js +1 -1
- package/dist/components/layout/Board/grid-core/compactors.js +1 -1
- package/dist/components/layout/Board/grid-core/constraints.js +1 -1
- package/dist/components/layout/Board/grid-core/group-move.js +1 -1
- package/dist/components/layout/Board/grid-core/layout.js +1 -1
- package/dist/components/layout/Board/grid-core/sort.js +1 -1
- package/dist/components/layout/Board/index.js +1 -1
- package/dist/components/layout/Board/responsive-utils.js +1 -1
- package/dist/components/layout/Board/use-board-layout.js +1 -1
- package/dist/components/layout/Board/use-board-registry.js +1 -1
- package/dist/components/layout/Board/use-board-select-modifier-key.js +1 -1
- package/dist/components/layout/Board/use-board-selection.js +1 -1
- package/dist/components/layout/Flex.js +1 -1
- package/dist/components/layout/Flow.js +1 -1
- package/dist/components/layout/Grid.js +1 -1
- package/dist/components/layout/Panel.js +1 -1
- package/dist/components/layout/Prefix.js +1 -1
- package/dist/components/layout/ResizablePanel.js +1 -1
- package/dist/components/layout/Space.js +1 -1
- package/dist/components/layout/Suffix.js +1 -1
- package/dist/components/navigation/Pagination/Pagination.d.ts +9 -0
- package/dist/components/navigation/Pagination/Pagination.js +258 -0
- package/dist/components/navigation/Pagination/Pagination.js.map +1 -0
- package/dist/components/navigation/Pagination/index.d.ts +4 -0
- package/dist/components/navigation/Pagination/types.d.ts +81 -0
- package/dist/components/navigation/Pagination/use-pagination.d.ts +52 -0
- package/dist/components/navigation/Pagination/use-pagination.js +83 -0
- package/dist/components/navigation/Pagination/use-pagination.js.map +1 -0
- package/dist/components/navigation/Tabs/DraggableTabList.js +1 -1
- package/dist/components/navigation/Tabs/TabButton.js +1 -1
- package/dist/components/navigation/Tabs/TabDropIndicator.js +1 -1
- package/dist/components/navigation/Tabs/TabPanel.js +1 -1
- package/dist/components/navigation/Tabs/TabPicker.js +1 -1
- package/dist/components/navigation/Tabs/Tabs.js +1 -1
- package/dist/components/navigation/Tabs/TabsAction.js +1 -1
- package/dist/components/navigation/Tabs/TabsContext.js +1 -1
- package/dist/components/navigation/Tabs/popover-placement.js +1 -1
- package/dist/components/navigation/Tabs/styled.js +1 -1
- package/dist/components/navigation/Tabs/types.js +1 -1
- package/dist/components/navigation/Tabs/use-tab-editing.js +1 -1
- package/dist/components/navigation/Tabs/use-tab-indicator.js +1 -1
- package/dist/components/navigation/index.d.ts +5 -1
- package/dist/components/organisms/StatsCard/StatsCard.js +1 -1
- package/dist/components/other/Calendar/Calendar.js +1 -1
- package/dist/components/other/Calendar/CalendarCell.js +1 -1
- package/dist/components/other/Calendar/CalendarGrid.js +1 -1
- package/dist/components/other/Calendar/PeriodCalendar.js +1 -1
- package/dist/components/other/Calendar/RangeCalendar.js +1 -1
- package/dist/components/other/CubeLogo/CubeLogo.js +1 -1
- package/dist/components/overlays/AlertDialog/AlertDialog.js +1 -1
- package/dist/components/overlays/AlertDialog/AlertDialogApiProvider.js +1 -1
- package/dist/components/overlays/AlertDialog/AlertDialogZone.js +1 -1
- package/dist/components/overlays/Dialog/Dialog.js +1 -1
- package/dist/components/overlays/Dialog/DialogContainer.js +1 -1
- package/dist/components/overlays/Dialog/DialogForm.js +1 -1
- package/dist/components/overlays/Dialog/DialogTrigger.js +1 -1
- package/dist/components/overlays/Dialog/context.js +1 -1
- package/dist/components/overlays/Dialog/use-dialog-container.js +1 -1
- package/dist/components/overlays/Modal/Modal.js +1 -1
- package/dist/components/overlays/Modal/OpenTransitionContext.js +1 -1
- package/dist/components/overlays/Modal/Overlay.js +1 -1
- package/dist/components/overlays/Modal/Popover.js +1 -1
- package/dist/components/overlays/Modal/Tray.js +1 -1
- package/dist/components/overlays/Modal/Underlay.js +1 -1
- package/dist/components/overlays/Notifications/Notification.js +1 -1
- package/dist/components/overlays/Notifications/NotificationAction.js +1 -1
- package/dist/components/overlays/Notifications/NotificationCard.js +1 -1
- package/dist/components/overlays/Notifications/NotificationContext.js +1 -1
- package/dist/components/overlays/Notifications/NotificationItem.js +1 -1
- package/dist/components/overlays/Notifications/OverlayContainer.js +1 -1
- package/dist/components/overlays/Notifications/OverlayProvider.js +1 -1
- package/dist/components/overlays/Notifications/PersistentNotificationsList.js +1 -1
- package/dist/components/overlays/Notifications/dismissed-storage.js +1 -1
- package/dist/components/overlays/Notifications/format-relative-time.js +1 -1
- package/dist/components/overlays/Notifications/index.js +1 -1
- package/dist/components/overlays/Notifications/use-notification-state.js +1 -1
- package/dist/components/overlays/Notifications/use-notifications.js +1 -1
- package/dist/components/overlays/Notifications/use-overlay-timers.js +1 -1
- package/dist/components/overlays/Notifications/use-persistent-notifications.js +1 -1
- package/dist/components/overlays/Notifications/use-persistent-state.js +1 -1
- package/dist/components/overlays/Notifications/use-toast-state.js +1 -1
- package/dist/components/overlays/Toast/ToastItem.js +1 -1
- package/dist/components/overlays/Toast/index.js +1 -1
- package/dist/components/overlays/Toast/useProgressToast.js +1 -1
- package/dist/components/overlays/Toast/useToast.js +1 -1
- package/dist/components/overlays/Tooltip/Tooltip.js +1 -1
- package/dist/components/overlays/Tooltip/TooltipProvider.js +1 -1
- package/dist/components/overlays/Tooltip/TooltipTrigger.js +1 -1
- package/dist/components/overlays/Tooltip/context.js +1 -1
- package/dist/components/portal/Portal.js +1 -1
- package/dist/components/portal/PortalProvider.js +1 -1
- package/dist/components/portal/usePortal.js +1 -1
- package/dist/components/shared/DraggableCollection.js +24 -8
- package/dist/components/shared/DraggableCollection.js.map +1 -1
- package/dist/components/shared/InvalidIcon.js +1 -1
- package/dist/components/shared/ValidIcon.js +1 -1
- package/dist/components/status/LoadingAnimation/LoadingAnimation.js +1 -1
- package/dist/components/status/Spin/Cube.js +1 -1
- package/dist/components/status/Spin/InternalSpinner.js +1 -1
- package/dist/components/status/Spin/Spin.js +1 -1
- package/dist/components/status/Spin/SpinsContainer.js +1 -1
- package/dist/data/item-themes.js +1 -1
- package/dist/data/themes.js +1 -1
- package/dist/eslint-plugin/defaults.generated.js +219 -5
- package/dist/eslint-plugin/defaults.generated.js.map +1 -1
- package/dist/eslint-plugin/index.js +1 -1
- package/dist/eslint-plugin/rules/no-redundant-default-prop.js +1 -1
- package/dist/i18n/I18nProvider.js +1 -1
- package/dist/i18n/createFormatter.js +1 -1
- package/dist/i18n/index.js +1 -1
- package/dist/i18n/instance.js +1 -1
- package/dist/i18n/locales/de-DE/uikit.js +36 -1
- package/dist/i18n/locales/en-US/uikit.js +36 -1
- package/dist/i18n/locales/en-US/uikit.json.d.ts +41 -1
- package/dist/i18n/locales/es-ES/uikit.js +36 -1
- package/dist/i18n/locales/es-MX/uikit.js +36 -1
- package/dist/i18n/locales/fr-FR/uikit.js +36 -1
- package/dist/i18n/locales/it-IT/uikit.js +36 -1
- package/dist/i18n/locales/ja-JP/uikit.js +36 -1
- package/dist/i18n/locales/nb-NO/uikit.js +36 -1
- package/dist/i18n/locales/pt-BR/uikit.js +36 -1
- package/dist/i18n/locales/pt-PT/uikit.js +36 -1
- package/dist/i18n/locales/sv-SE/uikit.js +36 -1
- package/dist/i18n/locales/vi-VN/uikit.js +36 -1
- package/dist/i18n/locales.js +1 -1
- package/dist/i18n/useFormatter.js +1 -1
- package/dist/i18n/useI18n.js +1 -1
- package/dist/icons/AdjustmentsHorizontalIcon.js +1 -1
- package/dist/icons/AdjustmentsIcon.js +1 -1
- package/dist/icons/AiIcon.js +1 -1
- package/dist/icons/AreaChartIcon.js +1 -1
- package/dist/icons/BackwardIcon.js +1 -1
- package/dist/icons/BarChartIcon.js +1 -1
- package/dist/icons/BellFilledIcon.js +1 -1
- package/dist/icons/BellIcon.js +1 -1
- package/dist/icons/BooleanIcon.js +1 -1
- package/dist/icons/CalendarEditIcon.js +1 -1
- package/dist/icons/CalendarIcon.js +1 -1
- package/dist/icons/CaretDownIcon.js +1 -1
- package/dist/icons/CaretUpIcon.js +1 -1
- package/dist/icons/ChartAreaStackedIcon.js +1 -1
- package/dist/icons/ChartAreaStackedPercentageIcon.js +1 -1
- package/dist/icons/ChartBarGroupedHorizontalIcon.js +1 -1
- package/dist/icons/ChartBarGroupedIcon.js +1 -1
- package/dist/icons/ChartBarHorizontalIcon.js +1 -1
- package/dist/icons/ChartBarLineIcon.js +1 -1
- package/dist/icons/ChartBarStackedHorizontalIcon.js +1 -1
- package/dist/icons/ChartBarStackedIcon.js +1 -1
- package/dist/icons/ChartBarStackedPercentageHorizontalIcon.js +1 -1
- package/dist/icons/ChartBarStackedPercentageIcon.js +1 -1
- package/dist/icons/ChartBoxPlot2Icon.js +1 -1
- package/dist/icons/ChartBoxPlotIcon.js +1 -1
- package/dist/icons/ChartBubbleIcon.js +1 -1
- package/dist/icons/ChartDonut2Icon.js +1 -1
- package/dist/icons/ChartFunnelIcon.js +1 -1
- package/dist/icons/ChartHeatmapIcon.js +1 -1
- package/dist/icons/ChartKPIIcon.js +1 -1
- package/dist/icons/ChartPie2Icon.js +1 -1
- package/dist/icons/ChartScatterIcon.js +1 -1
- package/dist/icons/CheckCircleFilledIcon.js +1 -1
- package/dist/icons/CheckCircleIcon.js +1 -1
- package/dist/icons/CheckIcon.js +1 -1
- package/dist/icons/CircleFilledIcon.js +1 -1
- package/dist/icons/ClearIcon.js +1 -1
- package/dist/icons/CloseCircleFilledIcon.js +1 -1
- package/dist/icons/CloseCircleIcon.js +1 -1
- package/dist/icons/CloseIcon.js +1 -1
- package/dist/icons/CodeIcon.js +1 -1
- package/dist/icons/ColumnTotalIcon.js +1 -1
- package/dist/icons/CopyIcon.js +1 -1
- package/dist/icons/CountIcon.js +1 -1
- package/dist/icons/CubeIcon.js +1 -1
- package/dist/icons/CubePauseIcon.js +1 -1
- package/dist/icons/CubePlayIcon.js +1 -1
- package/dist/icons/CurrencyDollarIcon.js +1 -1
- package/dist/icons/DangerIcon.js +1 -1
- package/dist/icons/DashboardIcon.js +1 -1
- package/dist/icons/DatabaseIcon.js +1 -1
- package/dist/icons/DecimalDecreaseIcon.js +1 -1
- package/dist/icons/DecimalIncreaseIcon.js +1 -1
- package/dist/icons/DirectionIcon.js +1 -1
- package/dist/icons/DonutIcon.js +1 -1
- package/dist/icons/DownIcon.js +1 -1
- package/dist/icons/EditIcon.js +1 -1
- package/dist/icons/ExclamationCircleFilledIcon.js +1 -1
- package/dist/icons/ExclamationCircleIcon.js +1 -1
- package/dist/icons/ExclamationIcon.js +1 -1
- package/dist/icons/EyeIcon.js +1 -1
- package/dist/icons/EyeInvisibleIcon.js +1 -1
- package/dist/icons/FilterIcon.js +1 -1
- package/dist/icons/FolderFilledIcon.js +1 -1
- package/dist/icons/FolderIcon.js +1 -1
- package/dist/icons/FolderOpenFilledIcon.js +1 -1
- package/dist/icons/FolderOpenIcon.js +1 -1
- package/dist/icons/ForwardIcon.js +1 -1
- package/dist/icons/GripVerticalIcon.js +1 -1
- package/dist/icons/HierarchyIcon.js +1 -1
- package/dist/icons/HierarchyOpenIcon.js +1 -1
- package/dist/icons/Icon.js +1 -1
- package/dist/icons/InfoCircleIcon.js +1 -1
- package/dist/icons/InfoIcon.js +1 -1
- package/dist/icons/KeyIcon.js +1 -1
- package/dist/icons/LeftIcon.js +1 -1
- package/dist/icons/LineChartIcon.js +1 -1
- package/dist/icons/LoadingIcon.js +1 -1
- package/dist/icons/LockFilledIcon.js +1 -1
- package/dist/icons/LockIcon.js +1 -1
- package/dist/icons/MoreIcon.js +1 -1
- package/dist/icons/NotAllowedIcon.js +1 -1
- package/dist/icons/Number123Icon.js +1 -1
- package/dist/icons/NumberIcon.js +1 -1
- package/dist/icons/PauseCircleFilledIcon.js +1 -1
- package/dist/icons/PauseCircleIcon.js +1 -1
- package/dist/icons/PauseIcon.js +1 -1
- package/dist/icons/PercentageIcon.js +1 -1
- package/dist/icons/PieChartIcon.js +1 -1
- package/dist/icons/PipetteIcon.js +1 -1
- package/dist/icons/PlayCircleIcon.js +1 -1
- package/dist/icons/PlayIcon.js +1 -1
- package/dist/icons/PlusIcon.js +1 -1
- package/dist/icons/ProgressBarIcon.js +1 -1
- package/dist/icons/ReloadIcon.js +1 -1
- package/dist/icons/ReportIcon.js +1 -1
- package/dist/icons/ReturnIcon.js +1 -1
- package/dist/icons/RightIcon.js +1 -1
- package/dist/icons/RowTotalsIcon.js +1 -1
- package/dist/icons/SchemeIcon.js +1 -1
- package/dist/icons/SearchIcon.js +1 -1
- package/dist/icons/SemanticQueryIcon.js +1 -1
- package/dist/icons/SettingsIcon.js +1 -1
- package/dist/icons/ShieldFilledIcon.js +1 -1
- package/dist/icons/ShieldIcon.js +1 -1
- package/dist/icons/SlashIcon.js +1 -1
- package/dist/icons/SparklesIcon.js +1 -1
- package/dist/icons/SqlIcon.js +1 -1
- package/dist/icons/StatsIcon.js +1 -1
- package/dist/icons/StopIcon.js +1 -1
- package/dist/icons/StringIcon.js +1 -1
- package/dist/icons/SubtotalsIcon.js +1 -1
- package/dist/icons/SwitchIcon.js +1 -1
- package/dist/icons/TableIcon.js +1 -1
- package/dist/icons/ThumbsDownIcon.js +1 -1
- package/dist/icons/ThumbsUpIcon.js +1 -1
- package/dist/icons/ThunderboltCrossedIcon.js +1 -1
- package/dist/icons/ThunderboltFilledIcon.js +1 -1
- package/dist/icons/ThunderboltIcon.js +1 -1
- package/dist/icons/TimeIcon.js +1 -1
- package/dist/icons/TrashIcon.js +1 -1
- package/dist/icons/UnlockIcon.js +1 -1
- package/dist/icons/UpIcon.js +1 -1
- package/dist/icons/UserGroupIcon.js +1 -1
- package/dist/icons/UserIcon.js +1 -1
- package/dist/icons/UserLockIcon.js +1 -1
- package/dist/icons/ViewIcon.js +1 -1
- package/dist/icons/WarningFilledIcon.js +1 -1
- package/dist/icons/WarningIcon.js +1 -1
- package/dist/icons/wrap-icon.js +1 -1
- package/dist/index.d.ts +28 -14
- package/dist/index.js +15 -7
- package/dist/index.js.map +1 -1
- package/dist/provider.js +1 -1
- package/dist/providers/TrackingProvider.js +1 -1
- package/dist/providers/navigationAdapter.default.js +1 -1
- package/dist/tokens/base.js +1 -1
- package/dist/tokens/colors.js +1 -1
- package/dist/tokens/index.js +1 -1
- package/dist/tokens/layout.js +1 -1
- package/dist/tokens/lazy-styles.js +1 -1
- package/dist/tokens/palette-config.js +1 -1
- package/dist/tokens/palette.js +1 -1
- package/dist/tokens/shadows.js +1 -1
- package/dist/tokens/sizes.js +1 -1
- package/dist/tokens/spacing.js +1 -1
- package/dist/tokens/typography.d.ts +1 -1
- package/dist/tokens/typography.js +11 -2
- package/dist/tokens/typography.js.map +1 -1
- package/dist/utils/ResizeSensor.js +1 -1
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/is-dev-env.js +1 -1
- package/dist/utils/modules.js +1 -1
- package/dist/utils/promise.js +1 -1
- package/dist/utils/raf.js +1 -1
- package/dist/utils/random.js +1 -1
- package/dist/utils/range.js +1 -1
- package/dist/utils/react/RenderCache.js +1 -1
- package/dist/utils/react/Slots.js +1 -1
- package/dist/utils/react/chain.js +1 -1
- package/dist/utils/react/forwardRefWithGenerics.js +1 -1
- package/dist/utils/react/index.d.ts +1 -0
- package/dist/utils/react/index.js +2 -1
- package/dist/utils/react/interactions.js +1 -1
- package/dist/utils/react/isTextOnly.js +1 -1
- package/dist/utils/react/mapProps.js +1 -1
- package/dist/utils/react/mergeProps.js +1 -1
- package/dist/utils/react/nullableValue.js +1 -1
- package/dist/utils/react/resolveIcon.js +1 -1
- package/dist/utils/react/sharedStore.js +1 -1
- package/dist/utils/react/useBufferedValue.d.ts +56 -0
- package/dist/utils/react/useBufferedValue.js +86 -0
- package/dist/utils/react/useBufferedValue.js.map +1 -0
- package/dist/utils/react/useCombinedRefs.js +1 -1
- package/dist/utils/react/useControlledFocusVisible.js +1 -1
- package/dist/utils/react/useEventBus.js +1 -1
- package/dist/utils/react/useId.js +1 -1
- package/dist/utils/react/useIsDarwin.js +1 -1
- package/dist/utils/react/useKeySymbols.js +1 -1
- package/dist/utils/react/useLayoutEffect.js +1 -1
- package/dist/utils/react/useLocalStorage.js +1 -1
- package/dist/utils/react/useMergeStyles.js +1 -1
- package/dist/utils/react/usePopoverSync.js +1 -1
- package/dist/utils/react/useQaProps.js +1 -1
- package/dist/utils/react/useViewportSize.js +1 -1
- package/dist/utils/react/wrapNodeIfPlain.js +1 -1
- package/dist/utils/selection.js +1 -1
- package/dist/utils/styles.js +1 -1
- package/dist/utils/tree.js +1 -1
- package/dist/utils/warnings.js +1 -1
- package/dist/version.js +2 -2
- package/docs/components/actions/ButtonGroup.md +1 -1
- package/docs/components/data/DataTable.md +298 -0
- package/docs/components/data/ItemTable.md +984 -0
- package/docs/components/fields/ColorInput.md +284 -0
- package/docs/components/fields/ColorPicker.md +85 -144
- package/docs/components/fields/ColorSwatchGroup.md +206 -0
- package/docs/components/fields/FilterPicker.md +1 -1
- package/docs/components/fields/ListBox.md +4 -0
- package/docs/components/fields/PasswordInput.md +1 -0
- package/docs/components/fields/Picker.md +1 -1
- package/docs/components/fields/SearchInput.md +1 -0
- package/docs/components/fields/TextArea.md +1 -0
- package/docs/components/fields/TextInput.md +1 -0
- package/docs/components/navigation/Pagination.md +245 -0
- package/package.json +8 -3
- package/dist/components/fields/ColorPicker/ColorPickerPanel.js.map +0 -1
- package/dist/components/fields/ColorPicker/channels.js.map +0 -1
- package/dist/components/fields/ColorPicker/color.d.ts +0 -15
- package/dist/components/fields/ColorPicker/color.js.map +0 -1
- package/dist/components/organisms/FileTabs/FileTabs.d.ts +0 -54
- package/dist/components/organisms/FileTabs/FileTabs.js +0 -282
- package/dist/components/organisms/FileTabs/FileTabs.js.map +0 -1
- package/docs/components/organisms/FileTabs.md +0 -51
|
@@ -0,0 +1,984 @@
|
|
|
1
|
+
# ItemTable
|
|
2
|
+
|
|
3
|
+
ItemTable renders a list of records as a table: one row per entity, columns
|
|
4
|
+
declared as data rather than JSX. It is the general-purpose table for list and
|
|
5
|
+
admin pages.
|
|
6
|
+
|
|
7
|
+
It renders a real `<table>` with `role="grid"`, and is styled entirely through
|
|
8
|
+
tasty sub-elements — `Row`, `Cell`, `HeaderCell` and friends are reachable from
|
|
9
|
+
the single `styles` prop.
|
|
10
|
+
|
|
11
|
+
> `ItemTable` and `DataTable` are siblings over one internal engine. `ItemTable`
|
|
12
|
+
> is for records; `DataTable` is for analytics results (pivoted columns, pinned
|
|
13
|
+
> totals, cell-range selection).
|
|
14
|
+
|
|
15
|
+
## When to Use
|
|
16
|
+
|
|
17
|
+
- Listing entities the user acts on: deployments, users, API keys, roles.
|
|
18
|
+
- Any table where a row is a *thing* — it can be opened, selected, or given a
|
|
19
|
+
menu.
|
|
20
|
+
- Tables that need a column header richer than a label: icon, description,
|
|
21
|
+
tooltip, actions.
|
|
22
|
+
|
|
23
|
+
Use `DataTable` instead when a *cell* is the unit of interest — query results,
|
|
24
|
+
pivots, totals. Use `ListBox` when there is only one column.
|
|
25
|
+
|
|
26
|
+
## Component
|
|
27
|
+
|
|
28
|
+
### Properties
|
|
29
|
+
|
|
30
|
+
- **`data`** `readonly T[]` — The rows to render.
|
|
31
|
+
- **`columns`** `CubeItemTableColumn<T>[]` — Column definitions. See below.
|
|
32
|
+
- **`rowKey`** `string` (default: `'id'`) — Property used as the row key.
|
|
33
|
+
- **`getRowKey`** `(row: T, index: number) => Key` — Wins over `rowKey`.
|
|
34
|
+
- **`isLoading`** `boolean` (default: `false`) — Marks a fetch in flight. What
|
|
35
|
+
the user sees depends on `loadingIndicator`.
|
|
36
|
+
- **`loadingIndicator`** `'overlay' | 'skeleton' | 'none'` (default: `'overlay'`)
|
|
37
|
+
— What to show while `isLoading` is true over rows the table already has.
|
|
38
|
+
`overlay` keeps them, faded under a sweeping band; `skeleton` replaces them with
|
|
39
|
+
placeholders; `none` paints nothing beyond `aria-busy`. With no rows yet,
|
|
40
|
+
`overlay` and `skeleton` both fall back to skeleton rows.
|
|
41
|
+
- **`skeletonRowCount`** `number` (default: `6`) — Skeleton rows to show while
|
|
42
|
+
loading.
|
|
43
|
+
- **`emptyLabel`** `ReactNode` — Shown when there is nothing at all. Defaults to
|
|
44
|
+
a localized "No items".
|
|
45
|
+
- **`noResultsLabel`** `ReactNode` — Shown instead of `emptyLabel` when
|
|
46
|
+
`isFiltered` is set. Defaults to a localized "No results found".
|
|
47
|
+
- **`isFiltered`** `boolean` — Marks the emptiness as the result of a filter, so
|
|
48
|
+
`noResultsLabel` is shown instead of `emptyLabel`. The built-in search sets it
|
|
49
|
+
on its own; pass it explicitly when you filter `data` yourself.
|
|
50
|
+
- **`error`** `ReactNode` — Takes precedence over both labels.
|
|
51
|
+
- **`shape`** `'plain' | 'card'` (default: `'plain'`) — `card` adds a border and
|
|
52
|
+
a card radius.
|
|
53
|
+
- **`size`** `'xsmall' | 'small' | 'medium' | 'large' | 'xlarge'` (default:
|
|
54
|
+
`'medium'`) — Drives both heights. At `medium` a row is 40px and the header
|
|
55
|
+
32px, each plus its 1px separator.
|
|
56
|
+
- **`rowHeight`** `number` — Row height in px, overriding the one `size`
|
|
57
|
+
implies. Excludes the 1px separator.
|
|
58
|
+
- **`headerHeight`** `number` — Header height in px, excluding its 1px border.
|
|
59
|
+
- **`headerPreset`** `string` (default: `'c3'`) — Typography preset for the
|
|
60
|
+
column header. `c3` is the small uppercase caption the Cloud list tables use;
|
|
61
|
+
pass `'t3m'` for body-sized headers.
|
|
62
|
+
- **`isRowMoveAnimated`** `boolean` (default: `true`) — Slide rows to their new positions when the order changes, instead of teleporting them. Respects `prefers-reduced-motion`.
|
|
63
|
+
- **`isStriped`** `boolean` (default: `false`) — Alternating row background.
|
|
64
|
+
- **`isHeaderHidden`** `boolean` (default: `false`) — Hides the column header
|
|
65
|
+
row and drops it from `aria-rowcount`.
|
|
66
|
+
- **`isHeaderSticky`** `boolean` (default: `true`) — Pins the column header
|
|
67
|
+
while the body scrolls.
|
|
68
|
+
- **`sortMode`** `'client' | 'server' | 'off'` (default: `'client'` when any
|
|
69
|
+
column is sortable, else `'off'`) — `client` reorders `data` itself; `server`
|
|
70
|
+
only reflects `sort` and fires `onSortChange`; `off` removes the affordance.
|
|
71
|
+
- **`sort`** `CubeTableSort | null` — Controlled sort, `{ columnKey, direction }`
|
|
72
|
+
with `direction` being `'asc' | 'desc'`.
|
|
73
|
+
- **`defaultSort`** `CubeTableSort | null` — Initial sort for uncontrolled usage.
|
|
74
|
+
- **`onSortChange`** `(sort: CubeTableSort | null) => void` — Fires on every step
|
|
75
|
+
of the cycle, including the return to unsorted.
|
|
76
|
+
- **`toolbar`** `ReactNode` — Replaces the entire toolbar row. Compose it from
|
|
77
|
+
`ItemTable.Search` / `ItemTable.Toolbar`, which read the table's state from
|
|
78
|
+
context.
|
|
79
|
+
- **`isSearchable`** `boolean` (default: `false`) — Render the built-in search
|
|
80
|
+
input in the toolbar.
|
|
81
|
+
- **`searchMode`** `'client' | 'server'` (default: `'client'`) — `client`
|
|
82
|
+
filters `data` with the built-in matcher; `server` only reports the term.
|
|
83
|
+
- **`searchPlaceholder`** `string` — Placeholder for the search input.
|
|
84
|
+
- **`searchValue`** `string` — Controlled term. Works with
|
|
85
|
+
`isSearchable={false}` too, so a page can render its own input anywhere and
|
|
86
|
+
still drive the table's matcher.
|
|
87
|
+
- **`defaultSearchValue`** `string` — Initial term for uncontrolled usage.
|
|
88
|
+
- **`onSearchChange`** `(value: string) => void` — Debounced.
|
|
89
|
+
- **`searchDelay`** `number` (default: `500`) — Debounces the filter **and** the
|
|
90
|
+
callback, in both modes. The input itself stays immediate.
|
|
91
|
+
- **`searchFilter`** `(row: T, query: string) => boolean` — Replaces the default
|
|
92
|
+
client matcher.
|
|
93
|
+
- **`filters`** `ReactNode` — Left group, after the search input.
|
|
94
|
+
- **`actions`** `ReactNode` — Right group. Arbitrary JSX.
|
|
95
|
+
- **`onRefresh`** `() => void` — Renders a refresh button at the end of the
|
|
96
|
+
toolbar.
|
|
97
|
+
- **`isVirtualized`** `boolean | 'auto'` (default: `'auto'`) — `'auto'` turns
|
|
98
|
+
virtualization on once the row count passes `virtualizeThreshold`. It needs a
|
|
99
|
+
bounded height to have a viewport to work against.
|
|
100
|
+
- **`virtualizeThreshold`** `number` (default: `50`) — Row count above which
|
|
101
|
+
`'auto'` virtualizes.
|
|
102
|
+
- **`overscan`** `number` (default: `12`) — Rows mounted beyond each viewport
|
|
103
|
+
edge while virtualized. Higher than a list's, because a fast flick outruns
|
|
104
|
+
React's re-render and the gap shows as blank rows.
|
|
105
|
+
- **`selectionMode`** `'none' | 'single' | 'multiple'` (default: `'none'`) —
|
|
106
|
+
`multiple` adds the checkbox column and a select-all header checkbox;
|
|
107
|
+
`single` adds the column without the header checkbox.
|
|
108
|
+
- **`selectedKeys`** `Key[] | 'all'` — Controlled selection. `'all'` is a
|
|
109
|
+
sentinel meaning "everything, including rows the client has not loaded".
|
|
110
|
+
- **`defaultSelectedKeys`** `Key[] | 'all'` — Initial selection.
|
|
111
|
+
- **`onSelectionChange`** `(keys: Key[] | 'all', rows: T[]) => void` — `rows`
|
|
112
|
+
holds only the rows the client has loaded.
|
|
113
|
+
- **`selectAllMode`** `'page' | 'filtered' | 'all'` (default: `'page'`) — What
|
|
114
|
+
the header checkbox acts on.
|
|
115
|
+
- **`isRowSelectable`** `(row: T) => boolean` — The row stays focusable and
|
|
116
|
+
clickable; only its checkbox goes inert.
|
|
117
|
+
- **`selectionTooltip`** `string | ((row: T) => string | undefined)` — Explains
|
|
118
|
+
an inert checkbox.
|
|
119
|
+
- **`disabledKeys`** `Key[]` — Rows that cannot be interacted with at all.
|
|
120
|
+
- **`rowLink`** `(row: T, index: number) => NavigateArg | undefined` — Turns the
|
|
121
|
+
row-header cell into a stretched link covering the whole row. Return
|
|
122
|
+
`undefined` for a row that should not navigate.
|
|
123
|
+
- **`onRowAction`** `(row: T, key: Key) => void` — Non-navigational activation:
|
|
124
|
+
Enter, or a click that did not land on a control inside a cell.
|
|
125
|
+
- **`rowMenu`** `ReactNode | ((row, ctx) => ReactNode | null)` — `Menu.Item`
|
|
126
|
+
children. Inert until `rowContextMenu` exposes it.
|
|
127
|
+
- **`rowContextMenu`** `boolean | 'context-only'` (default: `false`) — `true`
|
|
128
|
+
gives a `⋮` trigger column **and** right-click / Shift+F10;
|
|
129
|
+
`'context-only'` gives the keyboard and pointer paths without the column.
|
|
130
|
+
- **`onRowMenuAction`** `(action: string, row: T, key: Key) => void` — The
|
|
131
|
+
action key as written on `Menu.Item`.
|
|
132
|
+
- **`rowMenuTriggerProps`** `Partial<CubeItemActionProps>` — Forwarded to every
|
|
133
|
+
`⋮` trigger.
|
|
134
|
+
- **`bulkActions`** `CubeTableBulkAction<T>[]` — Actions offered while rows are
|
|
135
|
+
selected. Supplying any implies `selectionMode="multiple"`.
|
|
136
|
+
- **`bulkBarPlacement`** `'floating' | 'toolbar'` (default: `'floating'`) —
|
|
137
|
+
`floating` centres the bar over the body without changing the table's height;
|
|
138
|
+
`toolbar` replaces the `actions` group while a selection exists.
|
|
139
|
+
- **`bulkBarStyles`** `Styles` — Styles for the bar.
|
|
140
|
+
- **`paginationMode`** `'client' | 'server' | 'off'` (default: `'client'`) —
|
|
141
|
+
`client` slices the searched and sorted rows; `server` never slices and only
|
|
142
|
+
reflects `page` / `total`; `off` removes the control.
|
|
143
|
+
- **`pageSize`** `number` — Controlled page size.
|
|
144
|
+
- **`defaultPageSize`** `number` (default: `50`) — Initial page size.
|
|
145
|
+
- **`onPageSizeChange`** `(pageSize: number) => void` — Fires with the new size.
|
|
146
|
+
Changing the size returns to page 1.
|
|
147
|
+
- **`pageSizeOptions`** `number[]` (default: `[10, 20, 50, 100, 500]`) — Choices
|
|
148
|
+
in the page-size selector.
|
|
149
|
+
- **`page`** `number` — Controlled 1-based page.
|
|
150
|
+
- **`defaultPage`** `number` (default: `1`) — Initial page.
|
|
151
|
+
- **`onPageChange`** `(page: number) => void` — Fires with the clamped page.
|
|
152
|
+
- **`onLoadMore`** `() => void` — `paginationMode="infinite"` only. Fires once
|
|
153
|
+
the end of the list comes into view.
|
|
154
|
+
- **`hasMore`** `boolean` — Whether there is anything left to fetch.
|
|
155
|
+
- **`isLoadingMore`** `boolean` — Suppresses further calls while a batch is in
|
|
156
|
+
flight and shows a loading row.
|
|
157
|
+
- **`loadMoreMargin`** `number` (default: one viewport height) — How far before
|
|
158
|
+
the end to start fetching, in px.
|
|
159
|
+
- **`autoHidePagination`** `boolean` (default: `true`) — Hides the pagination
|
|
160
|
+
control when it cannot do anything: a single page whose total even the
|
|
161
|
+
smallest `pageSizeOptions` entry would not split. The footer still renders if
|
|
162
|
+
any slot has content.
|
|
163
|
+
- **`total`** `number` — Server mode: total row count behind the query.
|
|
164
|
+
- **`totalPages`** `number` — Server mode alternative to `total` when the count
|
|
165
|
+
is unknown.
|
|
166
|
+
- **`hasNextPage`** `boolean` — Server mode: keeps "next" enabled when neither
|
|
167
|
+
`total` nor `totalPages` is known.
|
|
168
|
+
- **`summary`** `boolean | ((info: CubeTablePageInfo) => ReactNode)` (default:
|
|
169
|
+
`true`) — The localized item range in the footer, e.g. "1–50 of 1,204".
|
|
170
|
+
- **`footer`** `ReactNode` — Replaces the entire footer row.
|
|
171
|
+
- **`footerStart`** `ReactNode` — Start footer slot. Renders even with
|
|
172
|
+
`paginationMode="off"` — this is where a "Load all results" button belongs.
|
|
173
|
+
- **`footerCenter`** `ReactNode` — Center footer slot.
|
|
174
|
+
- **`footerEnd`** `ReactNode` — End footer slot, before the pagination control.
|
|
175
|
+
- **`footerStyles`** `Styles` — Styles for the footer row.
|
|
176
|
+
- **`isReorderable`** `boolean` (default: `false`) — Lets rows be dragged into a
|
|
177
|
+
new order.
|
|
178
|
+
- **`onReorder`** `(keys: Key[], rows: T[]) => void` — The **whole** new order,
|
|
179
|
+
not just the moved row, so it can be persisted directly.
|
|
180
|
+
- **`dropOnRow`** `{ isTarget, isAllowed?, onDrop }` — Dropping rows *onto* a
|
|
181
|
+
row, e.g. a workbook into a folder. Enables dragging on its own, and composes
|
|
182
|
+
with `isReorderable`.
|
|
183
|
+
- **`getItemDragInfo`** `(row: T) => { label, icon? }` — What the cursor drags.
|
|
184
|
+
One row shows its icon and label; several show a count. Without it the browser
|
|
185
|
+
drags a screenshot of the row.
|
|
186
|
+
- **`isResizable`** `boolean` (default: `false`) — Adds a resize handle to every
|
|
187
|
+
column; a column overrides with its own `isResizable`.
|
|
188
|
+
- **`columnWidths`** `Record<string, number>` — Controlled widths by column key.
|
|
189
|
+
- **`defaultColumnWidths`** `Record<string, number>` — Initial widths.
|
|
190
|
+
- **`onColumnResize`** `(columnKey, width, all) => void` — Fires once the
|
|
191
|
+
gesture ends, not on every pixel.
|
|
192
|
+
- **`storageKey`** `string` — Persists the table's own state under
|
|
193
|
+
`cube-ui-kit:table:${storageKey}`. Controlled state is never stored — a
|
|
194
|
+
controlled `pageSize` or `sort` belongs to the page, and restoring it would
|
|
195
|
+
give the table a second, competing source of truth.
|
|
196
|
+
- **`persist`** `('pageSize' | 'columnWidths' | 'sort')[]` (default:
|
|
197
|
+
`['pageSize', 'columnWidths']`) — What `storageKey` covers. Sort is opt-in,
|
|
198
|
+
because a stored sort silently changes what the first screen of a table means.
|
|
199
|
+
- **`getRowProps`** `(ctx) => { isDimmed?, mods?, styles?, height?, qa?, tooltip? }`
|
|
200
|
+
— Per-row visuals.
|
|
201
|
+
- **`ariaLabel`** `string` — Labels the grid.
|
|
202
|
+
|
|
203
|
+
#### `CubeItemTableColumn<T>`
|
|
204
|
+
|
|
205
|
+
```ts
|
|
206
|
+
interface CubeItemTableColumn<T> {
|
|
207
|
+
key: string; // column id; also the data path — dots walk objects
|
|
208
|
+
title?: ReactNode; // header label
|
|
209
|
+
header?: CubeTableColumnHeader;
|
|
210
|
+
isRowHeader?: boolean; // renders <th scope="row"> and names the row
|
|
211
|
+
|
|
212
|
+
width?: number; // fixed px; mutually exclusive with `flex`
|
|
213
|
+
flex?: number; // weight for the leftover space (default 1)
|
|
214
|
+
minWidth?: number; // default 150
|
|
215
|
+
maxWidth?: number;
|
|
216
|
+
pin?: 'start' | 'end'; // sticky to an edge during horizontal scroll
|
|
217
|
+
isHidden?: boolean;
|
|
218
|
+
|
|
219
|
+
getValue?: (row, i) => unknown; // when `key` is not the data path
|
|
220
|
+
format?: (value, row, i) => string; // raw value → display text
|
|
221
|
+
compare?: (a, b, rowA, rowB) => number; // client-side comparator
|
|
222
|
+
|
|
223
|
+
render?: (value, row, i, ctx) => ReactNode;
|
|
224
|
+
cellStyles?: Styles | ((ctx) => Styles | undefined);
|
|
225
|
+
cellProps?: (ctx) => Record<string, any> | undefined;
|
|
226
|
+
|
|
227
|
+
align?: 'start' | 'center' | 'end';
|
|
228
|
+
isSortable?: boolean;
|
|
229
|
+
isSearchable?: boolean; // include in the built-in search (default true)
|
|
230
|
+
isCopyable?: boolean; // include in TSV copy (default true)
|
|
231
|
+
autoHeight?: boolean; // wrap text and let the row grow
|
|
232
|
+
meta?: Record<string, unknown>;
|
|
233
|
+
}
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
**The value pipeline is the escape hatch.** `getValue`, `format` and `compare`
|
|
237
|
+
exist so a column whose displayed text differs from its raw value stays
|
|
238
|
+
sortable, searchable and copyable. `render` is for appearance only — sorting and
|
|
239
|
+
searching never see its output, which is why an object-valued column with no
|
|
240
|
+
`format` renders empty rather than `"[object Object]"`.
|
|
241
|
+
|
|
242
|
+
#### `CubeTableColumnHeader`
|
|
243
|
+
|
|
244
|
+
Every slot maps 1:1 onto the `Item` rendered inside the header cell, so a header
|
|
245
|
+
gets an icon, a description, a tooltip and actions for free:
|
|
246
|
+
|
|
247
|
+
```jsx
|
|
248
|
+
{
|
|
249
|
+
key: 'owner',
|
|
250
|
+
title: 'Owner',
|
|
251
|
+
header: {
|
|
252
|
+
icon: <UserIcon />,
|
|
253
|
+
description: 'Who created it',
|
|
254
|
+
descriptionPlacement: 'block',
|
|
255
|
+
tooltip: true, // auto tooltip when the label truncates
|
|
256
|
+
actions: <ItemAction icon={<MoreIcon />} />,
|
|
257
|
+
},
|
|
258
|
+
}
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
`header.render(ctx)` takes over the cell's content entirely.
|
|
262
|
+
|
|
263
|
+
On a sortable column the sort arrow occupies the `rightIcon` slot — it is an
|
|
264
|
+
icon, and that slot is sized and aligned for one. The slot stays reserved while
|
|
265
|
+
unsorted, so toggling a sort never shifts the label. If you set
|
|
266
|
+
`header.rightIcon` yourself it keeps the slot and the arrow falls back to
|
|
267
|
+
`suffix`.
|
|
268
|
+
|
|
269
|
+
### Base Properties
|
|
270
|
+
|
|
271
|
+
Supports Base Properties.
|
|
272
|
+
|
|
273
|
+
### Styling Properties
|
|
274
|
+
|
|
275
|
+
#### styles
|
|
276
|
+
|
|
277
|
+
Customizes the root frame. Every internal part of the table is a **sub-element**
|
|
278
|
+
reachable from this one prop — that is the whole styling contract.
|
|
279
|
+
|
|
280
|
+
**Sub-elements:**
|
|
281
|
+
|
|
282
|
+
- `Scroller` — the single scroll container (both axes)
|
|
283
|
+
- `Table` — the `<table>`
|
|
284
|
+
- `Head`, `HeadRow`, `HeaderCell` — the column header
|
|
285
|
+
- `Body`, `Row`, `Cell` — the data rows
|
|
286
|
+
- `SortIndicator` — the sort arrow, inside the header `Item`'s suffix
|
|
287
|
+
- `Foot`, `FootRow`, `FootCell` — pinned totals
|
|
288
|
+
- `StateContent` — the empty / no-results / error content
|
|
289
|
+
|
|
290
|
+
```jsx
|
|
291
|
+
const Compact = tasty(ItemTable, {
|
|
292
|
+
styles: {
|
|
293
|
+
Cell: { padding: '1x' },
|
|
294
|
+
Row: { height: 'min 6x' },
|
|
295
|
+
},
|
|
296
|
+
});
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
Rows publish their paint as inherited custom properties — `#row-base`,
|
|
300
|
+
`#row-overlay`, `#row-text` and `$dim` — which cells consume. That is what lets
|
|
301
|
+
a pinned (and therefore opaque) cell match its row's state without duplicating
|
|
302
|
+
the state matrix.
|
|
303
|
+
|
|
304
|
+
Geometry runs through tokens too: `$row-height`, `$header-height`,
|
|
305
|
+
`$cell-padding-x` (16px) and `$cell-padding-y`. Height lives on the **cells**,
|
|
306
|
+
not the `<tr>` — table layout ignores `min-height` on a row and sizes it from
|
|
307
|
+
its cells instead.
|
|
308
|
+
|
|
309
|
+
#### toolbarStyles
|
|
310
|
+
|
|
311
|
+
The toolbar row. Sub-elements: `Start` (search + filters) and `End` (actions +
|
|
312
|
+
refresh).
|
|
313
|
+
|
|
314
|
+
#### searchStyles
|
|
315
|
+
|
|
316
|
+
The built-in search input.
|
|
317
|
+
|
|
318
|
+
#### headerStyles
|
|
319
|
+
|
|
320
|
+
The **column header row**. (The top chrome, when it arrives, is `toolbarStyles`
|
|
321
|
+
— a table has two things called "header" and this one is the columns.)
|
|
322
|
+
|
|
323
|
+
#### headerCellStyles
|
|
324
|
+
|
|
325
|
+
Every column header cell. Wins over `headerPreset`, so this is where you go for
|
|
326
|
+
anything the preset does not cover.
|
|
327
|
+
|
|
328
|
+
#### bodyStyles
|
|
329
|
+
|
|
330
|
+
The `<tbody>`.
|
|
331
|
+
|
|
332
|
+
#### rowStyles
|
|
333
|
+
|
|
334
|
+
Every body row.
|
|
335
|
+
|
|
336
|
+
#### cellStyles
|
|
337
|
+
|
|
338
|
+
Every body cell.
|
|
339
|
+
|
|
340
|
+
### Style Properties
|
|
341
|
+
|
|
342
|
+
These properties allow direct style application without using the `styles` prop:
|
|
343
|
+
|
|
344
|
+
- **Base:** `display`, `font`, `preset`, `hide`, `opacity`, `whiteSpace`, `transition`
|
|
345
|
+
- **Position:** `gridArea`, `order`, `gridColumn`, `gridRow`, `place`, `placeSelf`, `alignSelf`, `justifySelf`, `zIndex`, `margin`, `inset`, `position`, `scrollMargin`
|
|
346
|
+
- **Dimension:** `width`, `height`, `flexBasis`, `flexGrow`, `flexShrink`, `flex`
|
|
347
|
+
- **Block:** `padding`, `paddingInline`, `paddingBlock`, `border`, `radius`, `shadow`, `overflow`, `outline`, `scrollbar`, `textAlign`
|
|
348
|
+
- **Color:** `color`, `fill`, `fade`, `image`
|
|
349
|
+
- **Flow:** `flow`, `gap`, `columnGap`, `rowGap`, `placeItems`, `placeContent`, `alignItems`, `alignContent`, `justifyItems`, `justifyContent`, `align`, `justify`, `gridColumns`, `gridRows`, `gridTemplate`, `gridAreas`
|
|
350
|
+
|
|
351
|
+
`height` is the important one: there is no page-scroll mode, so
|
|
352
|
+
bounding the table is what turns the body into a scroller and pins the header.
|
|
353
|
+
An unbounded table simply sizes to its content.
|
|
354
|
+
|
|
355
|
+
### Modifiers
|
|
356
|
+
|
|
357
|
+
| Modifier | Type | Description |
|
|
358
|
+
| -------- | ---- | ----------- |
|
|
359
|
+
| `size` | `SizeName` | Row height scale |
|
|
360
|
+
| `shape` | `'plain' \| 'card'` | Frame treatment |
|
|
361
|
+
| `sticky-header` | `boolean` | Header is pinned |
|
|
362
|
+
|
|
363
|
+
Row-level modifiers, set on each `<tr>`: `odd`, `selected`, `focused`, `dimmed`,
|
|
364
|
+
`disabled`, `drop-target`, `placeholder`. Cell-level: `pin`, `pin-edge`,
|
|
365
|
+
`align`, `wrap`, `state`.
|
|
366
|
+
|
|
367
|
+
## Examples
|
|
368
|
+
|
|
369
|
+
### Basic Usage
|
|
370
|
+
|
|
371
|
+
```jsx
|
|
372
|
+
<ItemTable
|
|
373
|
+
data={deployments}
|
|
374
|
+
columns={[
|
|
375
|
+
{ key: 'name', title: 'Name', isRowHeader: true, flex: 2 },
|
|
376
|
+
{ key: 'status', title: 'Status', width: 140 },
|
|
377
|
+
{ key: 'owner.name', title: 'Owner' },
|
|
378
|
+
{ key: 'queries', title: 'Queries', width: 140, align: 'end',
|
|
379
|
+
format: (v) => v.toLocaleString() },
|
|
380
|
+
]}
|
|
381
|
+
ariaLabel="Deployments"
|
|
382
|
+
/>
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
### Custom Cells
|
|
386
|
+
|
|
387
|
+
```jsx
|
|
388
|
+
{
|
|
389
|
+
key: 'status',
|
|
390
|
+
title: 'Status',
|
|
391
|
+
width: 140,
|
|
392
|
+
render: (value) => <Tag theme={STATUS_THEME[value]}>{value}</Tag>,
|
|
393
|
+
}
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
### Appearance
|
|
397
|
+
|
|
398
|
+
`shape="card"` frames the table, `isStriped` bands the rows, `size` drives both
|
|
399
|
+
row and header height, and `isHeaderHidden` drops the header row.
|
|
400
|
+
|
|
401
|
+
### Empty, No-results and Error States
|
|
402
|
+
|
|
403
|
+
`isFiltered` is what separates "no matches" from "nothing exists"; the built-in
|
|
404
|
+
search sets it for you.
|
|
405
|
+
|
|
406
|
+
### Sorting
|
|
407
|
+
|
|
408
|
+
Mark columns `isSortable` and clicking a header cycles
|
|
409
|
+
`ascending → descending → unsorted`. The third state matters whenever the source
|
|
410
|
+
order is meaningful, which is why it is the default cycle; set
|
|
411
|
+
`disallowSortRemoval` on a column to reduce it to `asc ↔ desc`.
|
|
412
|
+
|
|
413
|
+
```jsx
|
|
414
|
+
<ItemTable
|
|
415
|
+
data={rows}
|
|
416
|
+
columns={[
|
|
417
|
+
{ key: 'name', title: 'Name', isSortable: true },
|
|
418
|
+
{ key: 'queries', title: 'Queries', isSortable: true,
|
|
419
|
+
format: (v) => v.toLocaleString() },
|
|
420
|
+
]}
|
|
421
|
+
defaultSort={{ columnKey: 'queries', direction: 'desc' }}
|
|
422
|
+
/>
|
|
423
|
+
```
|
|
424
|
+
|
|
425
|
+
Client-side sorting compares raw `getValue` results — numerically for numbers,
|
|
426
|
+
chronologically for dates — and falls back to a locale-aware collator over the
|
|
427
|
+
column's display text, so a formatted column sorts the way it reads. `compare`
|
|
428
|
+
overrides all of it. Nullish values sort first, then flip with the direction.
|
|
429
|
+
|
|
430
|
+
`sortMode="server"` reflects the state and reports changes without ever
|
|
431
|
+
reordering the rows. The second table below is server-sorted over a simulated
|
|
432
|
+
round trip:
|
|
433
|
+
|
|
434
|
+
```jsx
|
|
435
|
+
<ItemTable
|
|
436
|
+
sortMode="server"
|
|
437
|
+
sort={sort}
|
|
438
|
+
onSortChange={setSort}
|
|
439
|
+
isLoading={isFetching}
|
|
440
|
+
data={rowsFromQuery}
|
|
441
|
+
columns={columns}
|
|
442
|
+
/>
|
|
443
|
+
```
|
|
444
|
+
|
|
445
|
+
### Search
|
|
446
|
+
|
|
447
|
+
`isSearchable` puts the input in the toolbar and the table filters itself:
|
|
448
|
+
|
|
449
|
+
```jsx
|
|
450
|
+
<ItemTable
|
|
451
|
+
data={deployments}
|
|
452
|
+
columns={columns}
|
|
453
|
+
isSearchable
|
|
454
|
+
searchPlaceholder="Search deployments..."
|
|
455
|
+
noResultsLabel="No deployments match that search"
|
|
456
|
+
/>
|
|
457
|
+
```
|
|
458
|
+
|
|
459
|
+
The default matcher tests each column's **display text** — `format?.(value) ??
|
|
460
|
+
String(getValue(row))` — not the raw value. So a formatted column matches what
|
|
461
|
+
the user can actually see, a dotted `key` like `owner.name` is searchable, and a
|
|
462
|
+
column holding an object with no `format` is skipped rather than stringified
|
|
463
|
+
into `"[object Object]"` (which would make the query "object" match every row).
|
|
464
|
+
Opt a column out with `isSearchable: false`, or replace the matcher entirely
|
|
465
|
+
with `searchFilter`.
|
|
466
|
+
|
|
467
|
+
Searching also selects `noResultsLabel` over `emptyLabel` on its own, and resets
|
|
468
|
+
to page 1, so a client-search table distinguishes "no matches" from "nothing
|
|
469
|
+
exists" without the page owning the term.
|
|
470
|
+
|
|
471
|
+
### Server-side Search
|
|
472
|
+
|
|
473
|
+
`searchMode="server"` never filters — it reports the debounced term and the
|
|
474
|
+
query does the work.
|
|
475
|
+
|
|
476
|
+
### An External Search Box, and a Custom Toolbar
|
|
477
|
+
|
|
478
|
+
The input does not have to live in the table. `isSearchable={false}` hides the
|
|
479
|
+
built-in one while a controlled `searchValue` still drives the table's matcher —
|
|
480
|
+
a first-class path, not a workaround. The second table rebuilds the toolbar
|
|
481
|
+
entirely; `ItemTable.Search` reads the table's state from context, so the term
|
|
482
|
+
still has one owner.
|
|
483
|
+
|
|
484
|
+
```jsx
|
|
485
|
+
const [term, setTerm] = useState('');
|
|
486
|
+
|
|
487
|
+
<SearchInput value={term} onChange={setTerm} />
|
|
488
|
+
<ItemTable data={rows} columns={columns} isSearchable={false} searchValue={term} />
|
|
489
|
+
```
|
|
490
|
+
|
|
491
|
+
### Pagination
|
|
492
|
+
|
|
493
|
+
Pagination lives in the footer and is on by default (`paginationMode="client"`,
|
|
494
|
+
50 rows a page). The page-size selector appears whenever `pageSizeOptions` is
|
|
495
|
+
set, and `summary` prints the localized item range.
|
|
496
|
+
|
|
497
|
+
```jsx
|
|
498
|
+
<ItemTable data={rows} columns={columns} defaultPageSize={20} pageSizeOptions={[20, 50, 100]} />
|
|
499
|
+
```
|
|
500
|
+
|
|
501
|
+
Client pagination slices the **searched and sorted** rows, so a page always
|
|
502
|
+
reflects what the user is looking at, and the summary counts filtered rows
|
|
503
|
+
rather than the raw array. Changing the page size returns to page 1, because the
|
|
504
|
+
old page index points at different rows under a new size.
|
|
505
|
+
|
|
506
|
+
Pagination that cannot do anything hides itself. One page of five rows would
|
|
507
|
+
otherwise render "1–5 of 5", a page-size selector whose every option shows the
|
|
508
|
+
same five rows, and a solitary "1" button. The test is both conditions together
|
|
509
|
+
— a single page **and** a total the smallest page size would not split — so a
|
|
510
|
+
15-row single page keeps its control, because "10 / page" would genuinely
|
|
511
|
+
paginate it. Set `autoHidePagination={false}` to always show it.
|
|
512
|
+
|
|
513
|
+
Note that pagination and virtualization are alternatives: a 50-row page is well
|
|
514
|
+
under `virtualizeThreshold`, so a paginated table normally renders every row.
|
|
515
|
+
Set `paginationMode="off"` for the long-scroll case.
|
|
516
|
+
|
|
517
|
+
### Infinite Scroll
|
|
518
|
+
|
|
519
|
+
`paginationMode="infinite"` replaces the page control with load-on-scroll. The
|
|
520
|
+
table never slices in this mode — `data` is the list accumulated so far:
|
|
521
|
+
|
|
522
|
+
```jsx
|
|
523
|
+
<ItemTable
|
|
524
|
+
height="420px"
|
|
525
|
+
data={loaded}
|
|
526
|
+
columns={columns}
|
|
527
|
+
paginationMode="infinite"
|
|
528
|
+
hasMore={hasMore}
|
|
529
|
+
isLoadingMore={isFetching}
|
|
530
|
+
onLoadMore={fetchNextPage}
|
|
531
|
+
/>
|
|
532
|
+
```
|
|
533
|
+
|
|
534
|
+
It is driven by an `IntersectionObserver` on a sentinel at the end of the body
|
|
535
|
+
rather than a scroll handler: `loadMoreMargin` then expresses "prefetch this far
|
|
536
|
+
before the end" directly, and it costs nothing per scroll tick. The observer
|
|
537
|
+
re-arms only once `isLoadingMore` clears, so a request in flight is never fired
|
|
538
|
+
twice by a sentinel still sitting in view.
|
|
539
|
+
|
|
540
|
+
The fetch starts **a full screen before the end** — `loadMoreMargin` defaults to
|
|
541
|
+
the scroller's own height — so the request goes out while there is still a
|
|
542
|
+
viewport of rows left to read, and the batch has usually arrived by the time the
|
|
543
|
+
user gets there. A fixed 200px, about five rows, meant a fast scroll reached the
|
|
544
|
+
bottom before the response did, which is exactly the stall infinite scroll is
|
|
545
|
+
supposed to avoid.
|
|
546
|
+
|
|
547
|
+
While a batch is in flight the table appends **skeleton rows**, not a spinner.
|
|
548
|
+
They keep the row grid, read as "more rows of this shape are coming", and grow
|
|
549
|
+
the scroll height smoothly instead of a block that appears and vanishes — and it
|
|
550
|
+
matches what the first load already shows.
|
|
551
|
+
|
|
552
|
+
The burst is sized to **the batch that is coming**, measured from the last one
|
|
553
|
+
that arrived, so the list keeps its length through the load: the user can carry
|
|
554
|
+
on scrolling into it, and nothing lurches when the rows land. Measured rather
|
|
555
|
+
than read from `pageSize`, which infinite-scroll consumers often do not set —
|
|
556
|
+
and the first batch is the best predictor of the second. Capped at 50 rows,
|
|
557
|
+
which is taller than any viewport, because these particular rows are not
|
|
558
|
+
virtualized.
|
|
559
|
+
|
|
560
|
+
Under virtualization the trailing spacer holds the remaining height, so the
|
|
561
|
+
sentinel still marks the true end of the list rather than the end of the
|
|
562
|
+
rendered window.
|
|
563
|
+
|
|
564
|
+
### Footer Slots
|
|
565
|
+
|
|
566
|
+
The footer has three named slots, and they render whether or not pagination is
|
|
567
|
+
on. `footerStart` is where Cloud's "Load all results" button belongs — the thing
|
|
568
|
+
that today needs a `MutationObserver` to inject into ag-grid's paging panel,
|
|
569
|
+
because Community has no status bar.
|
|
570
|
+
|
|
571
|
+
```jsx
|
|
572
|
+
<ItemTable
|
|
573
|
+
data={rows}
|
|
574
|
+
columns={columns}
|
|
575
|
+
footerStart={<Button type="outline" size="small">Load all results</Button>}
|
|
576
|
+
footerCenter={<Text color="#dark-03">Partial result set</Text>}
|
|
577
|
+
/>
|
|
578
|
+
```
|
|
579
|
+
|
|
580
|
+
### Server-side Pagination
|
|
581
|
+
|
|
582
|
+
`paginationMode="server"` never slices — it reflects `page` and reports changes,
|
|
583
|
+
and `total` comes from the query. `data` is the current page.
|
|
584
|
+
|
|
585
|
+
```jsx
|
|
586
|
+
<ItemTable
|
|
587
|
+
data={pageFromQuery}
|
|
588
|
+
columns={columns}
|
|
589
|
+
paginationMode="server"
|
|
590
|
+
page={page}
|
|
591
|
+
pageSize={pageSize}
|
|
592
|
+
total={totalFromQuery}
|
|
593
|
+
isLoading={isFetching}
|
|
594
|
+
onPageChange={setPage}
|
|
595
|
+
onPageSizeChange={setPageSize}
|
|
596
|
+
/>
|
|
597
|
+
```
|
|
598
|
+
|
|
599
|
+
### Loading Behaviour
|
|
600
|
+
|
|
601
|
+
`loadingIndicator` chooses what happens while `isLoading` is true over rows the
|
|
602
|
+
table already has — the window that only exists once a query is involved:
|
|
603
|
+
|
|
604
|
+
| Value | Behaviour |
|
|
605
|
+
| --- | --- |
|
|
606
|
+
| `overlay` (default) | The previous rows stay readable and uncovered. The table fades — header included — and a band of lower opacity sweeps left to right across it, the way ag-grid marks a reloading grid. Nothing moves and nothing is drawn on top, so the eye keeps its place and the table does not change height. |
|
|
607
|
+
| `skeleton` | The previous rows are discarded for placeholders. Honest that the data is gone, but it flashes on every page and a short page makes the table jump. |
|
|
608
|
+
| `none` | No visuals beyond `aria-busy`. For pages that already show a top-level progress bar and do not want a second indicator. |
|
|
609
|
+
|
|
610
|
+
With no rows yet, `overlay` and `skeleton` both render skeleton rows — there is
|
|
611
|
+
nothing to keep — and `none` renders an empty body rather than flashing the
|
|
612
|
+
`emptyLabel` before the first response arrives.
|
|
613
|
+
|
|
614
|
+
### Bounded Height, Sticky Header and Pinned Columns
|
|
615
|
+
|
|
616
|
+
A bounded height turns the body into a scroller and pins the header. Pinned
|
|
617
|
+
columns are sticky `<th>`/`<td>` — one scroller, no lanes, no scroll sync. They
|
|
618
|
+
are moved to the edges in DOM order too, so `aria-colindex` stays truthful.
|
|
619
|
+
|
|
620
|
+
```jsx
|
|
621
|
+
<ItemTable
|
|
622
|
+
height="400px"
|
|
623
|
+
columns={[
|
|
624
|
+
{ key: 'name', title: 'Name', pin: 'start', width: 220 },
|
|
625
|
+
/* … */
|
|
626
|
+
{ key: 'status', title: 'Status', pin: 'end', width: 140 },
|
|
627
|
+
]}
|
|
628
|
+
data={rows}
|
|
629
|
+
/>
|
|
630
|
+
```
|
|
631
|
+
|
|
632
|
+
### Virtualization
|
|
633
|
+
|
|
634
|
+
Above `virtualizeThreshold` rows a bounded table virtualizes automatically. The
|
|
635
|
+
DOM and the styles are identical either way — only the number of mounted rows
|
|
636
|
+
changes, so sorting, search, pinned columns and the sticky header all behave the
|
|
637
|
+
same.
|
|
638
|
+
|
|
639
|
+
```jsx
|
|
640
|
+
<ItemTable height="420px" paginationMode="off" data={tenThousandRows} columns={columns} />
|
|
641
|
+
```
|
|
642
|
+
|
|
643
|
+
Overscroll is locked per axis, and only where the table can actually scroll, so
|
|
644
|
+
a table whose content fits never traps the wheel — the page behind it scrolls as
|
|
645
|
+
usual. On an axis that does scroll, a swipe at the edge neither chains to the
|
|
646
|
+
page (which is what would trigger browser back-navigation) nor rubber-bands,
|
|
647
|
+
since bouncing drags the rows off the sticky header and shows blank surface
|
|
648
|
+
behind them.
|
|
649
|
+
|
|
650
|
+
A native table cannot absolutely position a `<tr>` without breaking the table
|
|
651
|
+
box, so the offset comes from leading and trailing spacer rows. Those are
|
|
652
|
+
`aria-hidden`, and `aria-rowcount` / `aria-rowindex` continue to describe the
|
|
653
|
+
whole dataset rather than the mounted window.
|
|
654
|
+
|
|
655
|
+
Virtualization is skipped for the empty, error and loading states, and turns off
|
|
656
|
+
entirely with `isVirtualized={false}`.
|
|
657
|
+
|
|
658
|
+
### Wrapping Cells
|
|
659
|
+
|
|
660
|
+
Rows are **measured, not assumed**, so a column with `autoHeight` can wrap to a
|
|
661
|
+
different number of lines per row and the virtualized window still tracks
|
|
662
|
+
correctly.
|
|
663
|
+
|
|
664
|
+
### Selection
|
|
665
|
+
|
|
666
|
+
`selectionMode="multiple"` adds the checkbox column:
|
|
667
|
+
|
|
668
|
+
```jsx
|
|
669
|
+
const [keys, setKeys] = useState([]);
|
|
670
|
+
|
|
671
|
+
<ItemTable
|
|
672
|
+
data={deployments}
|
|
673
|
+
columns={columns}
|
|
674
|
+
selectionMode="multiple"
|
|
675
|
+
selectedKeys={keys}
|
|
676
|
+
onSelectionChange={(next) => setKeys(next)}
|
|
677
|
+
/>
|
|
678
|
+
```
|
|
679
|
+
|
|
680
|
+
Selection is **keyed, not indexed**, so it survives sorting, searching and
|
|
681
|
+
paging — the same row stays selected wherever it lands, and a row filtered out
|
|
682
|
+
by a search keeps its key rather than being silently deselected.
|
|
683
|
+
|
|
684
|
+
Shift-click a checkbox to extend the range from the last one you clicked
|
|
685
|
+
plainly. Shift-clicking back toward the anchor shrinks the range rather than
|
|
686
|
+
leaving the overshoot selected.
|
|
687
|
+
|
|
688
|
+
#### Three ways a row can be special
|
|
689
|
+
|
|
690
|
+
Deliberately distinct, and not interchangeable:
|
|
691
|
+
|
|
692
|
+
| Prop | Focusable | Interactive | Selectable |
|
|
693
|
+
| --- | --- | --- | --- |
|
|
694
|
+
| `disabledKeys` | no | no | no |
|
|
695
|
+
| `isRowSelectable` | yes | yes | no |
|
|
696
|
+
| `getRowProps().isDimmed` | yes | yes | **yes** — it is purely visual |
|
|
697
|
+
|
|
698
|
+
`selectionTooltip` explains an inert checkbox, which is the difference between
|
|
699
|
+
"this is broken" and "this row is still deploying".
|
|
700
|
+
|
|
701
|
+
#### What select-all reaches
|
|
702
|
+
|
|
703
|
+
`selectAllMode` decides the scope of the header checkbox:
|
|
704
|
+
|
|
705
|
+
- **`'page'`** (default) — the rows on the current page.
|
|
706
|
+
- **`'filtered'`** — every row passing the current search or filter, across
|
|
707
|
+
pages.
|
|
708
|
+
- **`'all'`** — emits the `'all'` sentinel instead of a key list. This is the
|
|
709
|
+
only mode that can mean rows the client has never loaded, so the consumer
|
|
710
|
+
decides what it means for its query — usually a `DELETE … WHERE <filter>`
|
|
711
|
+
rather than `WHERE id IN (…)`.
|
|
712
|
+
|
|
713
|
+
Unselectable rows are excluded from every scope. Pressing the header checkbox
|
|
714
|
+
while everything in scope is selected clears the **whole** selection, not just
|
|
715
|
+
the scope — leaving keys selected on other pages behind an unchecked-looking box
|
|
716
|
+
is how people delete things they did not mean to.
|
|
717
|
+
|
|
718
|
+
### Row Links and Row Actions
|
|
719
|
+
|
|
720
|
+
`rowLink` turns the row-header cell into a stretched anchor covering the whole
|
|
721
|
+
row:
|
|
722
|
+
|
|
723
|
+
```jsx
|
|
724
|
+
<ItemTable
|
|
725
|
+
data={deployments}
|
|
726
|
+
columns={columns}
|
|
727
|
+
rowLink={(row) => `/deployments/${row.id}`}
|
|
728
|
+
/>
|
|
729
|
+
```
|
|
730
|
+
|
|
731
|
+
Because it is a real `<a href>`, ⌘-click, middle-click and "Open in new tab"
|
|
732
|
+
all work natively — none of which an `onClick` handler can give you. The anchor
|
|
733
|
+
sits below the cells' own content in the stacking order, so a button or `⋮`
|
|
734
|
+
trigger inside a cell still takes its own clicks, and its accessible name comes
|
|
735
|
+
from the row-header cell rather than being announced as "link".
|
|
736
|
+
|
|
737
|
+
The row-header cell is styled as a link — `#purple-text` at weight 600, matching
|
|
738
|
+
the kit's `Link`, with an underline while the row is hovered. The anchor itself
|
|
739
|
+
is invisible, so without that the row would give no sign that it navigates.
|
|
740
|
+
|
|
741
|
+
`onRowAction` is the non-navigational alternative — Enter, or a click that did
|
|
742
|
+
not land on a control inside a cell. Use one or the other, not both.
|
|
743
|
+
|
|
744
|
+
### Row Menu
|
|
745
|
+
|
|
746
|
+
`rowMenu` supplies `Menu.Item` children, and `rowContextMenu` decides where they
|
|
747
|
+
are exposed. The split is deliberate: `rowMenu` alone renders nothing, so a row
|
|
748
|
+
never grows a `⋮` nobody asked for.
|
|
749
|
+
|
|
750
|
+
```jsx
|
|
751
|
+
<ItemTable
|
|
752
|
+
data={deployments}
|
|
753
|
+
columns={columns}
|
|
754
|
+
rowContextMenu
|
|
755
|
+
rowMenu={(row) => (
|
|
756
|
+
<>
|
|
757
|
+
<Menu.Item key="open">Open {row.name}</Menu.Item>
|
|
758
|
+
<Menu.Item key="delete">Delete</Menu.Item>
|
|
759
|
+
</>
|
|
760
|
+
)}
|
|
761
|
+
onRowMenuAction={(action, row) => run(action, row)}
|
|
762
|
+
/>
|
|
763
|
+
```
|
|
764
|
+
|
|
765
|
+
| `rowContextMenu` | `⋮` column | Right-click / Shift+F10 |
|
|
766
|
+
| --- | --- | --- |
|
|
767
|
+
| `false` (default) | no | no |
|
|
768
|
+
| `true` | yes | yes |
|
|
769
|
+
| `'context-only'` | no | yes |
|
|
770
|
+
|
|
771
|
+
A row whose resolver returns `null` gets no trigger, and right-clicking it falls
|
|
772
|
+
through to the browser's own context menu — more useful than an empty popover.
|
|
773
|
+
|
|
774
|
+
### Bulk Actions
|
|
775
|
+
|
|
776
|
+
`bulkActions` implies `selectionMode="multiple"` — a bulk action with no way to
|
|
777
|
+
select rows is a contradiction, not a configuration.
|
|
778
|
+
|
|
779
|
+
```jsx
|
|
780
|
+
<ItemTable
|
|
781
|
+
data={deployments}
|
|
782
|
+
columns={columns}
|
|
783
|
+
bulkActions={[
|
|
784
|
+
{
|
|
785
|
+
key: 'restart',
|
|
786
|
+
label: 'Restart',
|
|
787
|
+
onAction: async (rows, { setLoading }) => {
|
|
788
|
+
setLoading(true);
|
|
789
|
+
await restart(rows.map((row) => row.id));
|
|
790
|
+
},
|
|
791
|
+
},
|
|
792
|
+
{
|
|
793
|
+
key: 'delete',
|
|
794
|
+
label: 'Delete',
|
|
795
|
+
theme: 'danger',
|
|
796
|
+
isDisabled: (rows) => rows.some((row) => row.status === 'running'),
|
|
797
|
+
disabledTooltip: 'A running deployment cannot be deleted',
|
|
798
|
+
onAction: (rows) => remove(rows),
|
|
799
|
+
},
|
|
800
|
+
]}
|
|
801
|
+
/>
|
|
802
|
+
```
|
|
803
|
+
|
|
804
|
+
Each action drives its own spinner through `setLoading`, so one slow request
|
|
805
|
+
does not freeze the others, and the selection clears when the action resolves.
|
|
806
|
+
Opt out with `deselectAfter: false` for an action that only reads — the default
|
|
807
|
+
exists because the rows an action just deleted or moved are usually gone.
|
|
808
|
+
|
|
809
|
+
`bulkBarPlacement="floating"` (the default) centres the bar over the body
|
|
810
|
+
without changing the table's height, so the rows never shift under the cursor.
|
|
811
|
+
`"toolbar"` takes over the `actions` group instead, for a page whose toolbar is
|
|
812
|
+
already crowded — the two compete for the same space, and while rows are
|
|
813
|
+
selected the bulk actions are what the user is reaching for.
|
|
814
|
+
|
|
815
|
+
**Escape** clears the selection from anywhere inside the table.
|
|
816
|
+
|
|
817
|
+
`ItemTable.BulkBar` is available as a compound member for placing the bar
|
|
818
|
+
outside the default chrome; it reads the selection from context, so there is
|
|
819
|
+
still exactly one owner.
|
|
820
|
+
|
|
821
|
+
### Reordering Rows
|
|
822
|
+
|
|
823
|
+
`isReorderable` lets rows be dragged into a new order:
|
|
824
|
+
|
|
825
|
+
```jsx
|
|
826
|
+
<ItemTable
|
|
827
|
+
isReorderable
|
|
828
|
+
data={rows}
|
|
829
|
+
columns={columns}
|
|
830
|
+
onReorder={(keys, nextRows) => setRows(nextRows)}
|
|
831
|
+
/>
|
|
832
|
+
```
|
|
833
|
+
|
|
834
|
+
It is built on React Aria's collection drag-and-drop, through the same
|
|
835
|
+
`DraggableCollection` wrapper `Tabs` and `ListBox` use — `RowCollection` and the
|
|
836
|
+
table's own `SelectionManager` satisfy its contract unchanged.
|
|
837
|
+
|
|
838
|
+
That buys the keyboard path as well as the pointer one: the grid takes a single
|
|
839
|
+
tab stop, arrows move between rows, Enter picks a row up and drops it, Escape
|
|
840
|
+
cancels. The drop line is drawn **on** the row rather than between rows, because
|
|
841
|
+
a native table has nowhere to put an element between two `<tr>`s.
|
|
842
|
+
|
|
843
|
+
`onReorder` reports the whole key order rather than just the moved row, so the
|
|
844
|
+
result can be persisted without reconstructing it.
|
|
845
|
+
|
|
846
|
+
### Dropping Rows onto a Row
|
|
847
|
+
|
|
848
|
+
Some tables move rows *into* other rows rather than around them — a workbook
|
|
849
|
+
into a folder. `dropOnRow` covers that, and enables dragging on its own:
|
|
850
|
+
|
|
851
|
+
```jsx
|
|
852
|
+
<ItemTable
|
|
853
|
+
data={items}
|
|
854
|
+
columns={columns}
|
|
855
|
+
dropOnRow={{
|
|
856
|
+
isTarget: (row) => row.type === 'folder',
|
|
857
|
+
isAllowed: (dragged, target) => dragged.every((row) => row.id !== target.id),
|
|
858
|
+
onDrop: (dragged, target) => move(dragged, target),
|
|
859
|
+
}}
|
|
860
|
+
/>
|
|
861
|
+
```
|
|
862
|
+
|
|
863
|
+
This is a **different case from reordering**, and usually the only one a given
|
|
864
|
+
table wants: Cloud's Workbooks page drags items into folders and never reorders
|
|
865
|
+
them. The story below is that shape.
|
|
866
|
+
|
|
867
|
+
They do compose if you need it — set `isReorderable` as well and a row that
|
|
868
|
+
refuses a drop falls back to reordering — but that combination is rare. Cloud
|
|
869
|
+
has to treat them as mutually exclusive because ag-grid cannot express both at
|
|
870
|
+
once; that restriction does not carry over.
|
|
871
|
+
|
|
872
|
+
`dropOnRow` replaces Cloud's `isDropOnRowEnabled`, `isDropTarget`,
|
|
873
|
+
`isDropOnRowAllowed` and `onDropOnRow` with one object, and drops the two
|
|
874
|
+
ag-grid workarounds beside them (`dropTargetRowKeyRef`,
|
|
875
|
+
`dropTargetRefreshColumnKey`) that existed only because ag-grid cannot re-render
|
|
876
|
+
a single cell from React state. Here the hovered row is just
|
|
877
|
+
`ctx.isDropTarget`.
|
|
878
|
+
|
|
879
|
+
### Column Resize
|
|
880
|
+
|
|
881
|
+
`isResizable` puts a grab handle on each column's trailing edge:
|
|
882
|
+
|
|
883
|
+
```jsx
|
|
884
|
+
<ItemTable isResizable storageKey="deployments" data={rows} columns={columns} />
|
|
885
|
+
```
|
|
886
|
+
|
|
887
|
+
It is built on React Aria's `useMove` — the same hook behind `Board`'s widgets —
|
|
888
|
+
so the handle takes **keyboard** input for free: focus it and use the arrow
|
|
889
|
+
keys, or Home/End to jump to the column's minimum and maximum. Widths clamp to
|
|
890
|
+
each column's `minWidth` / `maxWidth`, and a column opts out with
|
|
891
|
+
`isResizable: false`.
|
|
892
|
+
|
|
893
|
+
`onColumnResize` fires once the gesture ends rather than on every pixel, and
|
|
894
|
+
`columnWidths` is in the default `persist` list, so pairing `isResizable` with
|
|
895
|
+
`storageKey` makes a resized table come back the way the user left it.
|
|
896
|
+
|
|
897
|
+
### Persisting State
|
|
898
|
+
|
|
899
|
+
`storageKey` remembers the parts of the table's state a user expects to survive
|
|
900
|
+
a reload:
|
|
901
|
+
|
|
902
|
+
```jsx
|
|
903
|
+
<ItemTable data={rows} columns={columns} storageKey="deployments" />
|
|
904
|
+
```
|
|
905
|
+
|
|
906
|
+
Only state the **table** owns is stored, so a controlled `pageSize` or `sort`
|
|
907
|
+
stays entirely the page's business. Sort is opt-in via `persist` — a stored sort
|
|
908
|
+
silently changes what the first screen of a table means, which is rarely what
|
|
909
|
+
you want by default:
|
|
910
|
+
|
|
911
|
+
```jsx
|
|
912
|
+
<ItemTable storageKey="deployments" persist={['pageSize', 'sort']} data={rows} columns={columns} />
|
|
913
|
+
```
|
|
914
|
+
|
|
915
|
+
Reads and writes are best-effort: private mode, a disabled store, a quota error
|
|
916
|
+
or a hand-edited value all degrade to "no persistence" rather than failing.
|
|
917
|
+
|
|
918
|
+
### Per-row Visuals
|
|
919
|
+
|
|
920
|
+
```jsx
|
|
921
|
+
<ItemTable
|
|
922
|
+
getRowProps={({ row }) => ({ isDimmed: row.status === 'stopped' })}
|
|
923
|
+
data={rows}
|
|
924
|
+
columns={columns}
|
|
925
|
+
/>
|
|
926
|
+
```
|
|
927
|
+
|
|
928
|
+
## Accessibility
|
|
929
|
+
|
|
930
|
+
### Screen Reader Support
|
|
931
|
+
|
|
932
|
+
- The `<table>` carries `role="grid"` with `aria-rowcount` and `aria-colcount`.
|
|
933
|
+
- Row and column indices are **1-based and document-absolute** — header rows are
|
|
934
|
+
counted, and the indices stay truthful when rows are virtualized or columns
|
|
935
|
+
are pinned.
|
|
936
|
+
- A column marked `isRowHeader` renders `<th scope="row">`, so a screen reader
|
|
937
|
+
announces the row by name when moving between cells.
|
|
938
|
+
- `aria-sort` is set on the sorted header only, never `"none"` on the rest.
|
|
939
|
+
- `aria-busy` is set while loading; skeleton rows keep the full cell structure so
|
|
940
|
+
nothing shifts when the data lands.
|
|
941
|
+
|
|
942
|
+
### ARIA Properties
|
|
943
|
+
|
|
944
|
+
| Property | Applied to |
|
|
945
|
+
| -------- | ---------- |
|
|
946
|
+
| `role="grid"` | the `<table>` |
|
|
947
|
+
| `aria-rowcount` / `aria-colcount` | the `<table>` |
|
|
948
|
+
| `aria-rowindex` | every `<tr>` |
|
|
949
|
+
| `aria-colindex` | every cell and column header |
|
|
950
|
+
| `aria-sort` | the sorted column header |
|
|
951
|
+
| `aria-busy` | the grid and its skeleton rows |
|
|
952
|
+
|
|
953
|
+
## Best Practices
|
|
954
|
+
|
|
955
|
+
- Do: mark one column `isRowHeader`. It names the row for assistive tech and is
|
|
956
|
+
where a row link will anchor.
|
|
957
|
+
- Do: give a column `format` when its display text differs from its raw value —
|
|
958
|
+
that is what keeps it sortable, searchable and copyable.
|
|
959
|
+
- Do: bound the table's height. Without a bound it grows to fit, the header
|
|
960
|
+
cannot stick, and virtualization has no viewport to work against.
|
|
961
|
+
- Do: leave the header preset alone unless you have a reason. `c3` is what the
|
|
962
|
+
Cloud list tables use, and the header `Item` inherits the cell's typography so
|
|
963
|
+
overriding `headerPreset` restyles the whole header consistently.
|
|
964
|
+
- Do: pass `isFiltered` when you filter `data` yourself, so the empty state says
|
|
965
|
+
"no matches".
|
|
966
|
+
- Don't: reach for `render` to reformat text. `format` does it in a way the rest
|
|
967
|
+
of the table understands — including sorting and search.
|
|
968
|
+
- Don't: filter `data` yourself *and* leave `isFiltered` unset, or an empty
|
|
969
|
+
result will read as "nothing exists".
|
|
970
|
+
- Don't: put an `Item` in every cell. `Item` runs a hotkey subscription per
|
|
971
|
+
instance; use `TextItem` (which the table does automatically for plain text)
|
|
972
|
+
and reserve `Item` for the row-header cell.
|
|
973
|
+
|
|
974
|
+
## Suggested Improvements
|
|
975
|
+
|
|
976
|
+
- Selection, pagination, row menus and drag & drop are arriving in follow-ups.
|
|
977
|
+
- Multi-column sorting (the sibling `DataTable` will take `sorts: []`).
|
|
978
|
+
|
|
979
|
+
## Related Components
|
|
980
|
+
|
|
981
|
+
- [Pagination](../navigation/Pagination.md) — pairs with the table footer
|
|
982
|
+
- [Item](../content/Item.md) — the header cell's content
|
|
983
|
+
- [TextItem](../content/TextItem.md) — truncating body text
|
|
984
|
+
- [ListBox](../fields/ListBox.md) — when there is only one column
|