@cube-dev/ui-kit 0.168.1 → 0.169.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 +24 -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/Root.js.map +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.d.ts +1 -0
- package/dist/components/actions/Button/Button.js +1 -1
- package/dist/components/actions/Button/Button.js.map +1 -1
- package/dist/components/actions/ButtonGroup/ButtonGroup.js +1 -1
- package/dist/components/actions/ButtonSplit/ButtonSplit.js +2 -2
- package/dist/components/actions/ButtonSplit/context.js +1 -1
- package/dist/components/actions/CommandMenu/CommandMenu.js +1 -1
- package/dist/components/actions/CommandMenu/CommandMenu.js.map +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 +2 -2
- package/dist/components/actions/Menu/MenuItem.js.map +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 +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/CopyPasteBlock/CopyPasteBlock.js.map +1 -1
- package/dist/components/content/CopySnippet/CopySnippet.js +1 -1
- package/dist/components/content/CopySnippet/CopySnippet.js.map +1 -1
- package/dist/components/content/Disclosure/Disclosure.js +1 -1
- package/dist/components/content/Disclosure/Disclosure.js.map +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/InfoBadge/InfoBadge.js.map +1 -1
- package/dist/components/content/InlineInput/InlineInput.d.ts +5 -0
- package/dist/components/content/InlineInput/InlineInput.js +3 -2
- package/dist/components/content/InlineInput/InlineInput.js.map +1 -1
- package/dist/components/content/Item/Item.js +1 -1
- package/dist/components/content/Item/Item.js.map +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 +2 -2
- 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 +2 -2
- 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 +1 -1
- package/dist/components/content/Tag/Tag.js.map +1 -1
- package/dist/components/content/Text.d.ts +1351 -1351
- 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 +2 -2
- package/dist/components/content/Tree/TreeNode.js.map +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.js +1 -1
- package/dist/components/data/ItemTable/ItemTable.js +1 -1
- package/dist/components/data/ItemTable/ItemTableBulkBar.js +2 -2
- package/dist/components/data/ItemTable/ItemTableBulkBar.js.map +1 -1
- package/dist/components/data/ItemTable/ItemTableDragPreview.js +1 -1
- package/dist/components/data/ItemTable/ItemTableFooter.js +1 -1
- package/dist/components/data/ItemTable/ItemTableToolbar.js +2 -2
- package/dist/components/data/ItemTable/ItemTableToolbar.js.map +1 -1
- package/dist/components/data/TableBase/ColumnResizer.js +1 -1
- package/dist/components/data/TableBase/RowCollection.js +1 -1
- package/dist/components/data/TableBase/TableHeaderCell.js +1 -1
- package/dist/components/data/TableBase/TableRow.js +1 -1
- package/dist/components/data/TableBase/TableView.js +4 -4
- package/dist/components/data/TableBase/TableView.js.map +1 -1
- package/dist/components/data/TableBase/column-menu.js +1 -1
- package/dist/components/data/TableBase/column-tint.js +1 -1
- package/dist/components/data/TableBase/row-menu.js +1 -1
- package/dist/components/data/TableBase/styled.d.ts +2 -1
- package/dist/components/data/TableBase/styled.js +1 -1
- package/dist/components/data/TableBase/table-tree.js +1 -1
- package/dist/components/data/TableBase/types.js +1 -1
- package/dist/components/data/TableBase/use-cell-selection.d.ts +1 -0
- package/dist/components/data/TableBase/use-cell-selection.js +0 -0
- package/dist/components/data/TableBase/use-column-order.js +1 -1
- package/dist/components/data/TableBase/use-container-width.js +1 -1
- package/dist/components/data/TableBase/use-row-move-animation.js +1 -1
- package/dist/components/data/TableBase/use-scrollability.js +1 -1
- package/dist/components/data/TableBase/use-table-columns.js +1 -1
- package/dist/components/data/TableBase/use-table-search.js +1 -1
- package/dist/components/data/TableBase/use-table-selection.js +1 -1
- package/dist/components/data/TableBase/use-table-sort.js +1 -1
- package/dist/components/data/TableBase/use-table-sorts.js +1 -1
- package/dist/components/data/TableBase/use-table-storage.js +1 -1
- package/dist/components/data/TableBase/use-table-tree-state.js +1 -1
- package/dist/components/fields/Checkbox/Checkbox.js +2 -2
- package/dist/components/fields/Checkbox/Checkbox.js.map +1 -1
- package/dist/components/fields/Checkbox/CheckboxGroup.js +2 -2
- package/dist/components/fields/Checkbox/context.js +1 -1
- package/dist/components/fields/ColorInput/ColorInput.js +4 -4
- package/dist/components/fields/ColorInput/ColorInput.js.map +1 -1
- package/dist/components/fields/ColorPicker/ColorPicker.js +2 -2
- package/dist/components/fields/ColorSwatch/ColorSwatch.js +1 -1
- package/dist/components/fields/ColorSwatchGroup/ColorSwatchGroup.js +1 -1
- package/dist/components/fields/ComboBox/ComboBox.js +5 -3
- package/dist/components/fields/ComboBox/ComboBox.js.map +1 -1
- package/dist/components/fields/CommandTextArea/CommandTextArea.js +2 -2
- 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 +2 -2
- package/dist/components/fields/DatePicker/DatePickerButton.js +1 -1
- package/dist/components/fields/DatePicker/DatePickerButton.js.map +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 +2 -2
- package/dist/components/fields/DatePicker/DateRangeSeparatedPicker.js +2 -2
- package/dist/components/fields/DatePicker/MonthPicker.js +1 -1
- package/dist/components/fields/DatePicker/PeriodPicker.js +2 -2
- 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 +1 -1
- package/dist/components/fields/FilterListBox/FilterListBox.js.map +1 -1
- package/dist/components/fields/FilterPicker/FilterPicker.js +3 -3
- package/dist/components/fields/FilterPicker/FilterPicker.js.map +1 -1
- package/dist/components/fields/Input/Input.js +1 -1
- package/dist/components/fields/ListBox/DraggableListBox.js +1 -1
- package/dist/components/fields/ListBox/ListBox.js +2 -2
- package/dist/components/fields/ListBox/ListBox.js.map +1 -1
- package/dist/components/fields/ListBoxPopover/ListBoxPopover.js +1 -1
- package/dist/components/fields/ListBoxPopover/index.d.ts +1 -0
- package/dist/components/fields/ListBoxPopover/listNavigation.js +1 -1
- package/dist/components/fields/ListBoxPopover/useCompositeFocus.d.ts +2 -0
- package/dist/components/fields/ListBoxPopover/useCompositeFocus.js +1 -1
- package/dist/components/fields/NumberInput/NumberInput.js +2 -2
- package/dist/components/fields/NumberInput/StepButton.js +1 -1
- package/dist/components/fields/NumberInput/StepButton.js.map +1 -1
- package/dist/components/fields/PasswordInput/PasswordInput.js +2 -2
- package/dist/components/fields/PasswordInput/PasswordInput.js.map +1 -1
- package/dist/components/fields/Picker/Picker.js +3 -3
- package/dist/components/fields/Picker/Picker.js.map +1 -1
- package/dist/components/fields/RadioGroup/Radio.js +1 -1
- package/dist/components/fields/RadioGroup/RadioGroup.js +2 -2
- package/dist/components/fields/RadioGroup/context.js +1 -1
- package/dist/components/fields/SearchComboBox/SearchComboBox.js +3 -3
- package/dist/components/fields/SearchComboBox/SearchComboBox.js.map +1 -1
- package/dist/components/fields/SearchInput/SearchInput.js +3 -3
- package/dist/components/fields/SearchInput/SearchInput.js.map +1 -1
- package/dist/components/fields/Select/Select.js +2 -2
- package/dist/components/fields/Select/Select.js.map +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 +2 -2
- package/dist/components/fields/Switch/Switch.js.map +1 -1
- package/dist/components/fields/TextArea/TextArea.js +2 -2
- package/dist/components/fields/TextInput/TextInput.js +2 -2
- package/dist/components/fields/TextInput/TextInputBase.d.ts +9 -0
- package/dist/components/fields/TextInput/TextInputBase.js +4 -3
- package/dist/components/fields/TextInput/TextInputBase.js.map +1 -1
- package/dist/components/fields/TextInput/useAutoSizeTextArea.js +1 -1
- package/dist/components/fields/TextInputMapper/TextInputMapper.d.ts +5 -0
- package/dist/components/fields/TextInputMapper/TextInputMapper.js +3 -3
- package/dist/components/fields/TextInputMapper/TextInputMapper.js.map +1 -1
- package/dist/components/fields/color/ColorPanel.js +1 -1
- package/dist/components/fields/color/channels.js +1 -1
- package/dist/components/fields/color/color.js +1 -1
- package/dist/components/fields/color/context.js +1 -1
- package/dist/components/form/FieldWrapper/FieldWrapper.js +6 -3
- package/dist/components/form/FieldWrapper/FieldWrapper.js.map +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.d.ts +28 -1
- package/dist/components/form/Label.js +35 -16
- package/dist/components/form/Label.js.map +1 -1
- package/dist/components/form/index.d.ts +1 -1
- package/dist/components/form/validation/ValidationIndicator.js +1 -1
- package/dist/components/form/validation/ValidationIndicator.js.map +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.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-modes.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/placement.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.js +4 -4
- package/dist/components/navigation/Pagination/Pagination.js.map +1 -1
- package/dist/components/navigation/Pagination/use-pagination.js +1 -1
- package/dist/components/navigation/Tabs/DraggableTabList.js +1 -1
- package/dist/components/navigation/Tabs/TabButton.js +3 -3
- package/dist/components/navigation/Tabs/TabButton.js.map +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/TabPicker.js.map +1 -1
- package/dist/components/navigation/Tabs/Tabs.js +1 -1
- package/dist/components/navigation/Tabs/Tabs.js.map +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/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/CalendarHeader.js +2 -2
- package/dist/components/other/Calendar/CalendarHeader.js.map +1 -1
- package/dist/components/other/Calendar/CalendarPanel.js +1 -1
- package/dist/components/other/Calendar/PeriodCalendar.js +1 -1
- package/dist/components/other/Calendar/PeriodGrid.js +1 -1
- package/dist/components/other/Calendar/RangeCalendar.js +1 -1
- package/dist/components/other/Calendar/styled.js +1 -1
- package/dist/components/other/CubeLogo/CubeLogo.js +1 -1
- package/dist/components/other/NoDataIcon/NoDataIcon.js +1 -1
- package/dist/components/overlays/AlertDialog/AlertDialog.d.ts +0 -1
- package/dist/components/overlays/AlertDialog/AlertDialog.js +2 -2
- package/dist/components/overlays/AlertDialog/AlertDialog.js.map +1 -1
- package/dist/components/overlays/AlertDialog/AlertDialogApiProvider.js +1 -1
- package/dist/components/overlays/AlertDialog/AlertDialogZone.js +1 -1
- package/dist/components/overlays/AlertDialog/AlertDialogZone.js.map +1 -1
- package/dist/components/overlays/Dialog/Dialog.js +2 -2
- package/dist/components/overlays/Dialog/Dialog.js.map +1 -1
- package/dist/components/overlays/Dialog/DialogContainer.js +1 -1
- package/dist/components/overlays/Dialog/DialogForm.js +2 -2
- package/dist/components/overlays/Dialog/DialogTrigger.js +3 -2
- package/dist/components/overlays/Dialog/DialogTrigger.js.map +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.d.ts +2 -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.d.ts +1 -0
- 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/Modal/types.d.ts +1 -0
- 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.d.ts +2 -0
- 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 +3 -3
- package/dist/components/overlays/Toast/useToast.js.map +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.d.ts +2 -0
- package/dist/components/portal/PortalProvider.js +1 -1
- package/dist/components/portal/index.d.ts +1 -0
- package/dist/components/portal/usePortal.js +1 -1
- package/dist/components/shared/DraggableCollection.js +1 -1
- package/dist/components/shared/InvalidIcon.js +1 -1
- package/dist/components/shared/InvalidIcon.js.map +1 -1
- package/dist/components/shared/ValidIcon.js +1 -1
- package/dist/components/shared/ValidIcon.js.map +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 +5 -1
- 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 +1 -1
- package/dist/i18n/locales/en-US/uikit.js +1 -1
- package/dist/i18n/locales/es-ES/uikit.js +1 -1
- package/dist/i18n/locales/es-MX/uikit.js +1 -1
- package/dist/i18n/locales/fr-FR/uikit.js +1 -1
- package/dist/i18n/locales/it-IT/uikit.js +1 -1
- package/dist/i18n/locales/ja-JP/uikit.js +1 -1
- package/dist/i18n/locales/nb-NO/uikit.js +1 -1
- package/dist/i18n/locales/pt-BR/uikit.js +1 -1
- package/dist/i18n/locales/pt-PT/uikit.js +1 -1
- package/dist/i18n/locales/sv-SE/uikit.js +1 -1
- package/dist/i18n/locales/vi-VN/uikit.js +1 -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/ArrowNarrowDownIcon.js +1 -1
- package/dist/icons/ArrowNarrowUpIcon.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 +2 -2
- package/dist/index.js +147 -147
- package/dist/probe/canonicalize.js +1 -1
- package/dist/probe/css.js +1 -1
- package/dist/probe/index.js +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/all-tokens.js +1 -1
- package/dist/tokens/base.js +1 -1
- package/dist/tokens/color-seed.js +1 -1
- package/dist/tokens/color-theme.js +1 -1
- package/dist/tokens/colors.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/resolve.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.js +1 -1
- package/dist/utils/ResizeSensor.js +1 -1
- 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/disabledProps.js +1 -1
- package/dist/utils/react/forwardRefWithGenerics.js +1 -1
- package/dist/utils/react/index.js +1 -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.js +1 -1
- 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/BaseProperties.md +1 -0
- package/docs/components/Block.md +2 -2
- package/docs/components/CollectionItem.md +2 -2
- package/docs/components/GridProvider.md +2 -2
- package/docs/components/actions/Action.md +2 -2
- package/docs/components/actions/Banner.md +2 -2
- package/docs/components/actions/Button.md +2 -2
- package/docs/components/actions/ButtonGroup.md +2 -2
- package/docs/components/actions/ButtonSplit.md +2 -2
- package/docs/components/actions/CommandMenu.md +2 -2
- package/docs/components/actions/Link.md +2 -2
- package/docs/components/actions/Menu.md +2 -2
- package/docs/components/actions/use-anchored-menu.md +2 -2
- package/docs/components/actions/use-context-menu.md +2 -2
- package/docs/components/content/ActiveZone.md +2 -2
- package/docs/components/content/Alert.md +15 -4
- package/docs/components/content/Avatar.md +2 -2
- package/docs/components/content/Card.md +2 -2
- package/docs/components/content/Content.md +2 -2
- package/docs/components/content/CopyPasteBlock.md +1 -1
- package/docs/components/content/CopySnippet.md +2 -2
- package/docs/components/content/Disclosure.md +1 -1
- package/docs/components/content/Divider.md +2 -2
- package/docs/components/content/Footer.md +2 -2
- package/docs/components/content/Header.md +2 -2
- package/docs/components/content/HotKeys.md +2 -2
- package/docs/components/content/InlineInput.md +1 -0
- package/docs/components/content/Item.md +8 -1
- package/docs/components/content/Layout.md +1 -1
- package/docs/components/content/Paragraph.md +2 -2
- package/docs/components/content/Placeholder.md +2 -2
- package/docs/components/content/Result.md +2 -2
- package/docs/components/content/Skeleton.md +2 -2
- package/docs/components/content/Title.md +2 -2
- package/docs/components/data/DataTable.md +4 -6
- package/docs/components/data/ItemTable.md +4 -6
- package/docs/components/fields/Checkbox.md +2 -2
- package/docs/components/fields/ComboBox.md +1 -1
- package/docs/components/fields/DatePicker.md +2 -2
- package/docs/components/fields/FileInput.md +2 -2
- package/docs/components/fields/FilterListBox.md +1 -1
- package/docs/components/fields/FilterPicker.md +1 -1
- package/docs/components/fields/HueSlider.md +1 -1
- package/docs/components/fields/ListBox.md +1 -1
- package/docs/components/fields/NumberInput.md +2 -2
- package/docs/components/fields/PasswordInput.md +2 -2
- package/docs/components/fields/Picker.md +1 -1
- package/docs/components/fields/RadioGroup.md +2 -2
- package/docs/components/fields/SearchInput.md +2 -2
- package/docs/components/fields/Select.md +1 -1
- package/docs/components/fields/Slider.md +1 -1
- package/docs/components/fields/Switch.md +1 -1
- package/docs/components/fields/TextArea.md +2 -2
- package/docs/components/fields/TextInput.md +2 -2
- package/docs/components/fields/TextInputMapper.md +2 -2
- package/docs/components/form/Field.md +2 -2
- package/docs/components/form/Form.md +2 -2
- package/docs/components/layout/Board.md +1 -1
- package/docs/components/layout/Flex.md +2 -2
- package/docs/components/layout/Flow.md +2 -2
- package/docs/components/layout/Grid.md +2 -2
- package/docs/components/layout/Panel.md +2 -2
- package/docs/components/layout/Prefix.md +2 -2
- package/docs/components/layout/ResizablePanel.md +2 -2
- package/docs/components/layout/Space.md +2 -2
- package/docs/components/layout/Suffix.md +2 -2
- package/docs/components/organisms/StatsCard.md +2 -2
- package/docs/components/overlays/AlertDialog.md +2 -2
- package/docs/components/overlays/Dialog.md +1 -1
- package/docs/components/overlays/DialogContainer.md +1 -1
- package/docs/components/overlays/DialogForm.md +1 -1
- package/docs/components/overlays/DialogTrigger.md +1 -1
- package/docs/components/overlays/Tooltip.md +2 -2
- package/docs/components/overlays/TooltipProvider.md +2 -2
- package/docs/components/overlays/TooltipTrigger.md +2 -2
- package/docs/components/status/LoadingAnimation.md +2 -2
- package/docs/components/status/Spin.md +2 -2
- package/package.json +4 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TableView.js","names":["mergeProps","Checkbox","MenuTrigger","Menu"],"sources":["../../../../src/components/data/TableBase/TableView.tsx"],"sourcesContent":["import { useVirtualizer } from '@tanstack/react-virtual';\nimport {\n Fragment,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { useTree, useTreeItem, VisuallyHidden } from 'react-aria';\n\nimport { useEvent } from '../../../_internal/hooks';\nimport { useI18n } from '../../../i18n';\nimport {\n ArrowNarrowDownIcon,\n ArrowNarrowUpIcon,\n DirectionIcon,\n MoreIcon,\n} from '../../../icons';\nimport { getColorTheme, useColorTheme } from '../../../tokens/color-theme';\nimport { usePaletteVersion } from '../../../tokens/palette-config';\nimport { SIZE_NAME_TO_KEY, SIZES } from '../../../tokens/sizes';\nimport { mergeProps } from '../../../utils/react';\nimport { Action } from '../../actions/Action/Action';\nimport { ItemAction } from '../../actions/ItemAction/ItemAction';\nimport { Menu, MenuTrigger } from '../../actions/Menu';\nimport { useContextMenu } from '../../actions/use-context-menu';\nimport { Placeholder } from '../../content/Placeholder/Placeholder';\nimport { Skeleton } from '../../content/Skeleton/Skeleton';\nimport { TextItem } from '../../content/TextItem';\nimport { Checkbox } from '../../fields/Checkbox';\nimport { useToast } from '../../overlays/Toast';\nimport { TooltipProvider } from '../../overlays/Tooltip/TooltipProvider';\n\nimport {\n COLUMN_MENU_SORT_DIRECTION,\n isColumnMenuSortKey,\n processColumnMenuItems,\n} from './column-menu';\nimport { buildColumnTints, tintSlot } from './column-tint';\nimport { ColumnResizer } from './ColumnResizer';\nimport {\n isMenuEmpty,\n normalizeMenuAction,\n ROW_MENU_COLUMN_KEY,\n} from './row-menu';\nimport {\n TableElement,\n TableHeaderItem,\n TableTreeToggle,\n TableTreeTogglePlaceholder,\n} from './styled';\nimport { TableHeaderCell } from './TableHeaderCell';\nimport { TableRow, TableRowDropIndicator } from './TableRow';\nimport { selectionRowKey } from './types';\nimport { toTsv } from './use-cell-selection';\nimport { getDraggableColumnKeys, isColumnDraggable } from './use-column-order';\nimport { useRowMoveAnimation } from './use-row-move-animation';\nimport { useScrollability } from './use-scrollability';\nimport { getColumnText, getColumnValue } from './use-table-columns';\nimport {\n ROW_NUMBER_COLUMN_KEY,\n SELECTION_COLUMN_KEY,\n} from './use-table-selection';\n\nimport type { Key, Node } from '@react-types/shared';\nimport type { Styles } from '@tenphi/tasty';\nimport type {\n CSSProperties,\n FocusEvent as ReactFocusEvent,\n KeyboardEvent as ReactKeyboardEvent,\n MouseEvent as ReactMouseEvent,\n ReactNode,\n PointerEvent as ReactPointerEvent,\n RefObject,\n} from 'react';\nimport type { TreeState } from 'react-stately';\nimport type { NavigateArg } from '../../../providers/navigation.types';\nimport type { ColorThemeConfig } from '../../../tokens/color-theme';\nimport type { CubeColumnMenuContext } from './column-menu';\nimport type { TableTreeNode } from './table-tree';\nimport type {\n CubeResolvedColumn,\n CubeTableCellContext,\n CubeTableColumnGroupHeader,\n CubeTableColumnLayout,\n CubeTableHeaderContext,\n CubeTableLayoutProps,\n CubeTableLoadingIndicator,\n CubeTableRowContext,\n CubeTableRowSection,\n CubeTableRowSize,\n CubeTableSort,\n CubeTableSortDirection,\n} from './types';\nimport type { useCellSelection } from './use-cell-selection';\nimport type { CubeTableSelectionState } from './use-table-selection';\n\n/** Visual/behavioural overrides a table adapter may attach to a single row. */\nexport interface CubeTableRowRenderProps {\n isDimmed?: boolean;\n mods?: Record<string, boolean | undefined>;\n styles?: Styles;\n height?: number;\n qa?: string;\n tooltip?: string;\n}\n\nexport interface TableViewProps<T = any> extends CubeTableLayoutProps {\n qa?: string;\n rows: readonly T[];\n /** Stable keys for `rows`; required when a tree was flattened for display. */\n rowKeys?: readonly Key[];\n getRowKey: (row: T, index: number) => Key;\n layout: CubeTableColumnLayout<T>;\n /** Group path for each leaf column, from the outermost header inward. */\n columnHeaderPaths?: ReadonlyMap<\n string,\n readonly CubeTableColumnGroupHeader[]\n >;\n /**\n * Receives the scroll container once it exists. A callback rather than a ref\n * because the virtualized path does not create the element itself — Virtuoso\n * does, and hands it over after mount.\n */\n onScrollerRef: (element: HTMLDivElement | null) => void;\n /** Attached to the table's root frame. */\n rootRef?: RefObject<HTMLDivElement | null>;\n\n size?: 'xsmall' | 'small' | 'medium' | 'large' | 'xlarge';\n shape?: 'plain' | 'card';\n /**\n * Row height as a named step — 28px / 32px / 40px.\n *\n * Only the rows: the header keeps whatever `size` gives it. Unset, the height\n * falls through to `size` as before. `rowHeight` wins over both, being the\n * most specific answer.\n */\n rowSize?: CubeTableRowSize;\n rowHeight?: number;\n headerHeight?: number;\n isHeaderHidden?: boolean;\n isStriped?: boolean;\n /**\n * Vertical rules between columns.\n *\n * A list reads across a row and wants nothing in the way; a grid is read down\n * a column, and the rule is what tells you which column a figure is in when\n * the header has scrolled far to the left. So `ItemTable` leaves it off and\n * `DataTable` turns it on — the same split ag-grid's `columnBorder` gives the\n * Cloud grids today.\n */\n hasColumnDividers?: boolean;\n /**\n * Slide rows to their new positions when the order changes, instead of\n * teleporting them.\n *\n * On by default, and only ever on a pure reorder — see\n * `use-row-move-animation`. Suppressed under `prefers-reduced-motion`.\n */\n isRowMoveAnimated?: boolean;\n /** @default true */\n isHeaderSticky?: boolean;\n /** @default 'auto' — on above `virtualizeThreshold` rows, needs a bounded height. */\n isVirtualized?: boolean | 'auto';\n /** @default 50 */\n virtualizeThreshold?: number;\n /** Rows rendered beyond each edge of the viewport. @default 20 */\n overscan?: number;\n\n /* status */\n isLoading?: boolean;\n loadingIndicator?: CubeTableLoadingIndicator;\n skeletonRowCount?: number;\n selection?: CubeTableSelectionState<T>;\n selectionTooltip?: string | ((row: T) => string | undefined);\n /** Rendered in the root frame, over the body. For the floating bulk bar. */\n overlay?: ReactNode;\n /** Already normalised by the adapter into a per-row resolver. */\n rowMenu?: (row: T, ctx: CubeTableRowContext<T>) => ReactNode | null;\n rowContextMenu?: boolean | 'context-only';\n onRowMenuAction?: (action: string, row: T, key: Key) => void;\n rowMenuTriggerProps?: Record<string, any>;\n rowLink?: (row: T, index: number) => NavigateArg | undefined;\n onRowAction?: (row: T, key: Key) => void;\n /** Infinite scroll: fires once the end of the list comes into view. */\n onLoadMore?: () => void;\n hasMore?: boolean;\n isLoadingMore?: boolean;\n /**\n * How far before the end to start fetching, in px.\n *\n * Defaults to one viewport height, so the next batch is requested a whole\n * screen before the user could reach the bottom. A fixed 200px — about five\n * rows — meant a fast scroll arrived at the end before the request did, which\n * is the stall this is meant to avoid.\n */\n loadMoreMargin?: number;\n /**\n * Rows pinned above and below the scrolling ones — totals, subtotals.\n *\n * Rendered inside `<tbody>` rather than `<thead>`/`<tfoot>` so they keep the\n * body's own row and cell styling; the sub-element chains are anchored to\n * `Body`. Stickiness comes from the row itself.\n */\n pinnedTopRows?: readonly T[];\n pinnedBottomRows?: readonly T[];\n /**\n * Rectangular cell selection, from `use-cell-selection`.\n *\n * `DataTable` only. A list is acted on by row; a result grid is read by cell,\n * and the block of figures is the thing the user wants out of it.\n */\n cellSelection?: ReturnType<typeof useCellSelection<T>> | null;\n /** 1-based number of the first row, so paging keeps the count continuous. */\n rowNumberOffset?: number;\n /**\n * Rows of the full result that precede this page, and the size of that full\n * result.\n *\n * ARIA row indices are document-absolute by contract: `aria-rowindex` is a\n * row's position in the WHOLE grid and `aria-rowcount` the whole grid's size,\n * so a paged grid has to say \"row 21 of 240\" rather than restarting at 1 and\n * claiming a count of 25. Without them a screen reader hears colliding\n * indices against a larger count, which is worse than saying nothing.\n *\n * Defaults keep an unpaged table correct: no offset, and a count taken from\n * the rows actually given.\n */\n rowIndexOffset?: number;\n totalRowCount?: number;\n /** React Aria treegrid state and the model entries matching `rows`. */\n tree?: {\n state: TreeState<TableTreeNode<T>>;\n ariaProps: Record<string, any>;\n nodes: Node<TableTreeNode<T>>[];\n entries: TableTreeNode<T>[];\n columnKey: string;\n };\n isReorderable?: boolean;\n /** Provided by `DraggableCollection` when reordering is on. */\n dragState?: any;\n dropState?: any;\n /* column reordering — named apart from the ROW drag props above, so a table\n * can eventually run both at once. */\n isColumnReorderable?: boolean;\n columnDragState?: any;\n columnDropState?: any;\n /**\n * Drop handling for the header. Must land on the element that directly\n * contains the header cells — the `<tr>` — or drops are never received.\n */\n headCollectionProps?: Record<string, any>;\n headRowRef?: RefObject<HTMLTableRowElement | null>;\n /** Keeps React Aria's `focusedKey` current, which Alt+Arrow reorder reads. */\n onColumnFocus?: (columnKey: string | null) => void;\n /**\n * Drop handling from `useDroppableCollection`. Must land on the element that\n * directly contains the rows — the `<tbody>` — or drops are never received.\n */\n collectionProps?: Record<string, any>;\n bodyRef?: RefObject<HTMLTableSectionElement | null>;\n isResizable?: boolean;\n onColumnResize?: (columnKey: string, width: number) => void;\n onColumnResizeEnd?: (columnKey: string) => void;\n emptyLabel?: ReactNode;\n noResultsLabel?: ReactNode;\n error?: ReactNode;\n /** Selects `noResultsLabel` over `emptyLabel` when there is nothing to show. */\n isFiltered?: boolean;\n\n /* sorting */\n /** @default 'off' */\n sortMode?: 'client' | 'server' | 'off';\n sort?: CubeTableSort | null;\n /**\n * Multi-column sort. Takes precedence over `sort` when given, and the array\n * order is the precedence — `DataTable` uses it, `ItemTable` uses `sort`.\n */\n sorts?: CubeTableSort[];\n onColumnSort?: (columnKey: string) => void;\n /**\n * Set a column's direction outright, for the column menu's reserved sort keys.\n *\n * Separate from `onColumnSort`, which is a cycle: reaching `desc` by toggling\n * twice never terminates under `disallowSortRemoval` and disturbs the\n * precedence of every other sorted column.\n */\n onColumnSortChange?: (\n columnKey: string,\n direction: CubeTableSortDirection | null,\n ) => void;\n\n /* column menu */\n /**\n * Where a column's `header.menu` is exposed.\n *\n * - `true` — a `⋮` trigger, plus right-click and Shift+F10.\n * - `'context-only'` — right-click and Shift+F10, no trigger.\n * - `false` — suppressed entirely.\n *\n * Defaults to `true`, unlike `rowContextMenu`: for rows the flag also decides\n * whether there is a menu at all, whereas here `header.menu` is that gate and\n * this only picks the surfaces.\n *\n * @default true\n */\n columnContextMenu?: boolean | 'context-only';\n onColumnMenuAction?: (action: string, columnKey: string) => void;\n columnMenuTriggerProps?: Record<string, any>;\n columnMenuProps?: Record<string, any>;\n\n /* per-row hooks */\n getRowProps?: (\n ctx: CubeTableRowContext<T>,\n ) => CubeTableRowRenderProps | undefined;\n\n /**\n * Typography preset for the column header. A per-adapter default rather than\n * a table-wide constant: `ItemTable` uses the uppercase caption look (`c2`),\n * while an analytics grid wants its headers to read at body size.\n * `headerCellStyles` still wins over it.\n */\n headerPreset?: string;\n /**\n * Typography for the body. `ItemTable` reads as a list at `t3`; a result grid\n * packs more in and wants `t4`.\n */\n contentPreset?: string;\n\n /** Chrome rendered above the table, in the frame's first grid row. */\n toolbar?: ReactNode;\n /** Chrome rendered below the table, in the frame's last grid row. */\n footer?: ReactNode;\n\n ariaLabel?: string;\n styles?: Styles;\n headerStyles?: Styles;\n headerCellStyles?: Styles;\n bodyStyles?: Styles;\n rowStyles?: Styles;\n cellStyles?: Styles;\n mods?: Record<string, boolean | undefined>;\n}\n\n/**\n * The same block as an HTML table, so a spreadsheet keeps the cell boundaries.\n *\n * Pasting `text/plain` TSV works, but Excel and Sheets then re-guess the types\n * of every field; the HTML flavour is what makes a value that looks like a date\n * stay the text it was on screen.\n */\nfunction toClipboardHtml(matrix: string[][]) {\n const rows = matrix\n .map(\n (row) =>\n `<tr>${row.map((cell) => `<td>${escapeHtml(cell)}</td>`).join('')}</tr>`,\n )\n .join('');\n\n return `<table>${rows}</table>`;\n}\n\nfunction escapeHtml(value: string) {\n return value\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>');\n}\n\nconst ARIA_SORT = { asc: 'ascending', desc: 'descending' } as const;\n\n/**\n * Registers one column tint's tokens.\n *\n * A component per theme rather than a loop of `useColorTheme` calls: the number\n * of tinted columns is data-dependent, and hooks cannot be called in a loop. Each\n * of these has a fixed hook count, and mounting a different NUMBER of them is\n * fine. Keyed on the theme name, so remounting only happens when the set of\n * colours actually changes.\n *\n * Renders nothing — `useColorTheme` injects into a global slot keyed by the\n * theme's own hash, so two tables sharing a colour share one injection and\n * neither can evict the other's.\n */\nfunction ColumnTintRegistrar({ config }: { config: ColorThemeConfig }) {\n useColorTheme(config);\n\n return null;\n}\n\n/**\n * Content height per size step, mirroring `$row-height` in `styled.ts`. Only the\n * initial estimate — every rendered row is measured, so a wrong guess costs a\n * scrollbar adjustment, not a layout bug. The `+ 1` is the row separator.\n */\n/** Enough to read as \"more is coming\" without pretending to know how much. */\n/**\n * Ceiling on the load-more placeholder burst.\n *\n * These rows are not virtualized — they sit after the window, at the end of the\n * body — so the count is real DOM. 50 rows is already taller than any viewport,\n * which is all the burst has to be.\n */\nconst MAX_LOAD_MORE_SKELETON_ROWS = 50;\n\n/**\n * Floor on the prefetch distance, for a table too short to measure usefully —\n * an unbounded one reports a viewport of nearly zero before it has any rows.\n */\nconst MIN_LOAD_MORE_MARGIN = 200;\n\nconst ESTIMATED_ROW_HEIGHT = {\n xsmall: 28,\n small: 32,\n medium: 40,\n large: 48,\n xlarge: 56,\n} as const;\n\nfunction pinStyle(column: CubeResolvedColumn): CSSProperties | undefined {\n if (column.pinOffset == null) return undefined;\n\n return { ['--pin-offset' as any]: `${column.pinOffset}px` };\n}\n\n/**\n * Hook boundary for the native table. Flat tables deliberately avoid this\n * component so their DOM and keyboard behaviour remain exactly as before.\n */\nfunction TreeGridTable<T>(props: {\n tree: NonNullable<TableViewProps<T>['tree']>;\n tableProps: Record<string, any>;\n style?: CSSProperties;\n children: ReactNode;\n}) {\n const { tree, tableProps, style, children } = props;\n const ref = useRef<HTMLTableElement>(null);\n const pendingFocusKey = useRef<Key | null>(null);\n const { gridProps } = useTree(tree.ariaProps as any, tree.state, ref);\n\n // A virtualized destination may not exist until the focused key makes the\n // parent virtualizer scroll and render another window. Retry after each\n // render until that row mounts, then complete the keyboard focus move.\n useEffect(() => {\n const key = pendingFocusKey.current;\n if (key == null) return;\n\n // A real focus move wins over the delayed virtual-row focus. Losing the\n // old row to virtualization leaves focus on <body>, whereas tabbing or\n // clicking elsewhere leaves a concrete active element we must respect.\n const activeElement = document.activeElement;\n if (\n activeElement &&\n activeElement !== document.body &&\n !ref.current?.contains(activeElement)\n ) {\n pendingFocusKey.current = null;\n return;\n }\n\n const target = Array.from(\n ref.current?.querySelectorAll<HTMLTableRowElement>(\n 'tbody tr[data-element=\"Row\"][data-key]',\n ) ?? [],\n ).find((element) => element.dataset.key === String(key));\n\n if (target) {\n pendingFocusKey.current = null;\n target.focus();\n }\n });\n\n const handleBlurCapture = (event: ReactFocusEvent<HTMLTableElement>) => {\n const pendingKey = pendingFocusKey.current;\n const nextTarget = event.relatedTarget;\n\n if (pendingKey != null && nextTarget instanceof Element) {\n const nextRow = nextTarget.closest<HTMLTableRowElement>(\n 'tbody tr[data-element=\"Row\"][data-key]',\n );\n\n if (nextRow?.dataset.key !== String(pendingKey)) {\n pendingFocusKey.current = null;\n }\n }\n\n (gridProps as any).onBlurCapture?.(event);\n };\n\n const handleKeyDownCapture = (\n event: ReactKeyboardEvent<HTMLTableElement>,\n ) => {\n const row = (event.target as HTMLElement).closest<HTMLTableRowElement>(\n 'tbody tr[data-element=\"Row\"][data-key]',\n );\n\n // Inputs, links and menus embedded in a row retain their own shortcuts.\n if (!row || event.target !== row) {\n (gridProps as any).onKeyDownCapture?.(event);\n return;\n }\n\n // While a virtual destination is still mounting, subsequent key presses\n // continue from that logical key rather than repeatedly targeting the old\n // DOM row that still owns focus.\n const currentKey = pendingFocusKey.current ?? row.dataset.key;\n const index = tree.entries.findIndex(\n (entry) => String(entry.key) === String(currentKey),\n );\n const entry = tree.entries[index];\n if (!entry) return;\n\n const focusEntry = (next: TableTreeNode<T> | undefined) => {\n if (!next) return false;\n tree.state.selectionManager.setFocusedKey(next.key);\n const target = Array.from(\n ref.current?.querySelectorAll<HTMLTableRowElement>(\n 'tbody tr[data-element=\"Row\"][data-key]',\n ) ?? [],\n ).find((element) => element.dataset.key === String(next.key));\n if (target) {\n pendingFocusKey.current = null;\n target.focus();\n } else pendingFocusKey.current = next.key;\n return true;\n };\n\n const hasChildren = entry.children.length > 0;\n const isExpanded = tree.state.expandedKeys.has(entry.key);\n let handled = false;\n\n if (event.key === 'ArrowRight' && hasChildren) {\n if (isExpanded) handled = focusEntry(entry.children[0]);\n else {\n tree.state.toggleKey(entry.key);\n handled = true;\n }\n } else if (event.key === 'ArrowLeft') {\n if (hasChildren && isExpanded) {\n tree.state.toggleKey(entry.key);\n handled = true;\n } else if (entry.parentKey != null) {\n handled = focusEntry(\n tree.entries.find((candidate) => candidate.key === entry.parentKey),\n );\n }\n } else if (event.key === 'ArrowDown') {\n handled = focusEntry(tree.entries[index + 1]);\n } else if (event.key === 'ArrowUp') {\n handled = focusEntry(tree.entries[index - 1]);\n }\n\n if (handled) {\n event.preventDefault();\n event.stopPropagation();\n return;\n }\n\n // React Aria still sees the DOM row that owned focus before the virtual\n // destination mounted. If a logical navigation key has no action there\n // (a boundary, leaf, or collapsed root), consuming it avoids falling\n // through and applying that key to the stale row instead.\n if (\n pendingFocusKey.current != null &&\n ['ArrowDown', 'ArrowUp', 'ArrowRight', 'ArrowLeft'].includes(event.key)\n ) {\n event.preventDefault();\n event.stopPropagation();\n return;\n }\n\n (gridProps as any).onKeyDownCapture?.(event);\n };\n\n return (\n <table\n {...mergeProps(gridProps, tableProps)}\n ref={ref}\n role=\"treegrid\"\n style={style}\n onBlurCapture={handleBlurCapture}\n onKeyDownCapture={handleKeyDownCapture}\n >\n {children}\n </table>\n );\n}\n\n/**\n * The one place table DOM exists. Both `ItemTable` and `DataTable` resolve their\n * props into the shape above and hand it here, so the markup, the ARIA\n * bookkeeping and the tasty sub-element contract have a single implementation.\n */\nexport function TableView<T = any>(props: TableViewProps<T>) {\n const {\n qa,\n rows,\n rowKeys,\n getRowKey,\n layout,\n columnHeaderPaths,\n onScrollerRef,\n rootRef,\n size = 'medium',\n shape = 'plain',\n rowSize,\n rowHeight,\n headerHeight,\n isHeaderHidden = false,\n isStriped = false,\n hasColumnDividers,\n isRowMoveAnimated = true,\n isHeaderSticky = true,\n isAutoHeight = false,\n isVirtualized = 'auto',\n virtualizeThreshold = 50,\n overscan = 20,\n isLoading = false,\n loadingIndicator = 'overlay',\n skeletonRowCount = 6,\n selection,\n selectionTooltip,\n overlay,\n rowMenu,\n rowContextMenu = false,\n onRowMenuAction,\n rowMenuTriggerProps,\n rowLink,\n onRowAction,\n onLoadMore,\n hasMore = false,\n isLoadingMore = false,\n loadMoreMargin,\n pinnedTopRows,\n pinnedBottomRows,\n cellSelection,\n rowNumberOffset = 0,\n rowIndexOffset = 0,\n totalRowCount,\n tree,\n isReorderable = false,\n dragState,\n dropState,\n collectionProps,\n isColumnReorderable = false,\n columnDragState,\n columnDropState,\n headCollectionProps,\n headRowRef,\n onColumnFocus,\n bodyRef,\n isResizable = false,\n onColumnResize,\n onColumnResizeEnd,\n emptyLabel,\n noResultsLabel,\n error,\n isFiltered = false,\n sortMode = 'off',\n sort,\n sorts,\n onColumnSort,\n onColumnSortChange,\n columnContextMenu = true,\n onColumnMenuAction,\n columnMenuTriggerProps,\n columnMenuProps,\n getRowProps,\n headerPreset,\n contentPreset,\n toolbar,\n footer,\n ariaLabel,\n styles,\n headerStyles,\n headerCellStyles,\n bodyStyles,\n rowStyles,\n cellStyles,\n mods,\n } = props;\n\n const { columns } = layout;\n const columnCount = columns.length;\n const headerGroupDepth = columns.reduce(\n (depth, column) =>\n Math.max(depth, columnHeaderPaths?.get(column.key)?.length ?? 0),\n 0,\n );\n\n /**\n * `rowSize` resolved to the size scale, or `null` when it was not given.\n *\n * Both halves come from `SIZE_NAME_TO_KEY` rather than being written out\n * twice: the CSS keeps the token so it follows the scale, and the virtualizer\n * needs the number, and the two must not drift.\n */\n const rowSizeKey = rowSize ? SIZE_NAME_TO_KEY[rowSize] : null;\n // Only the trailing draggable column carries an `after` indicator; every other\n // gap is covered by the next column's `before` one.\n const lastDraggableKey = isColumnReorderable\n ? getDraggableColumnKeys(columns, true).at(-1) ?? null\n : null;\n\n // The element is held here as well as reported upwards: the virtualizer needs\n // it locally, and the adapter needs it to measure column widths.\n const { t } = useI18n();\n const toast = useToast();\n\n const [scrollerEl, setScrollerEl] = useState<HTMLDivElement | null>(null);\n const scrollerRef = useRef<HTMLDivElement | null>(null);\n /**\n * The column whose menu is open, held for the whole table rather than per\n * header cell.\n *\n * `renderHeaderCell` is a closure inside this component, not a component of\n * its own, so it cannot hold state — and only one column menu can be open at a\n * time anyway. Controlled rather than letting `MenuTrigger` own it: Shift+F10\n * has to be able to open it from the `<th>`, and the trigger is not a tab stop.\n */\n const [openMenuColumnKey, setOpenMenuColumnKey] = useState<string | null>(\n null,\n );\n // `bodyRef` is optional — only the drag-and-drop path supplies one — but the\n // move animation needs the `<tbody>` either way, so it keeps its own and both\n // are filled from one callback.\n const localBodyRef = useRef<HTMLTableSectionElement | null>(null);\n const handleBodyRef = useCallback(\n (element: HTMLTableSectionElement | null) => {\n localBodyRef.current = element;\n if (bodyRef) bodyRef.current = element;\n },\n [bodyRef],\n );\n const handleScrollerRef = useCallback(\n (element: HTMLDivElement | null) => {\n scrollerRef.current = element;\n setScrollerEl(element);\n onScrollerRef(element);\n },\n [onScrollerRef],\n );\n\n // Header rows count towards `aria-rowcount`, which must be document-absolute.\n const headerRowCount = isHeaderHidden ? 0 : headerGroupDepth + 1;\n\n /* ── the ARIA row index space ───────────────────────────────────────────\n * Four bands, in the order a screen reader walks them:\n *\n * 1 the header row\n * 2 … 1+top pinned top rows\n * … the body, offset by the pages before this one\n * after the whole body pinned bottom rows\n *\n * Derived once here rather than at each of the four render sites, which is\n * how the body came to be numbered as though the pinned rows above it did\n * not exist while `aria-rowcount` counted them.\n * ─────────────────────────────────────────────────────────────────────── */\n const pinnedTopCount = pinnedTopRows?.length ?? 0;\n const pinnedBottomCount = pinnedBottomRows?.length ?? 0;\n // The whole result, not this page. `rows.length` is the honest fallback when\n // the adapter does not know a total.\n const bodyRowCount = Math.max(\n totalRowCount ?? rows.length,\n rowIndexOffset + rows.length,\n );\n\n /** 1-based `aria-rowindex` for the i-th body row of the current page. */\n const bodyRowIndex = (rowIndex: number) =>\n headerRowCount + pinnedTopCount + rowIndexOffset + rowIndex + 1;\n const bodyRowKey = (row: T, rowIndex: number) =>\n rowKeys?.[rowIndex] ?? getRowKey(row, rowIndex);\n const treeRowState = (rowIndex: number) => {\n const entry = tree?.entries[rowIndex];\n\n return entry\n ? {\n level: entry.level,\n parentKey: entry.parentKey,\n hasChildren: entry.children.length > 0,\n isExpanded: tree.state.expandedKeys.has(entry.key),\n }\n : undefined;\n };\n /** 1-based `aria-rowindex` for the i-th pinned row at `edge`. */\n const pinnedRowIndex = (index: number, edge: 'top' | 'bottom') =>\n edge === 'top'\n ? headerRowCount + index + 1\n : headerRowCount + pinnedTopCount + bodyRowCount + index + 1;\n\n /**\n * Per-column tints.\n *\n * The colour maths is `getColorTheme`'s, cached globally by a hash of its\n * config; `buildColumnTints` only maps columns onto `data-tint` slots and the\n * state maps that read them. `getColorTheme` rather than `useColorTheme` here\n * because the number of tinted columns is data-dependent and a hook cannot be\n * called in a loop — registration happens in `ColumnTintRegistrar` below, one\n * component per distinct theme, which is a legal fixed hook count each.\n */\n const paletteVersion = usePaletteVersion();\n const tints = useMemo(\n () => buildColumnTints(columns, { resolveTheme: getColorTheme }),\n // eslint-disable-next-line react-hooks/exhaustive-deps -- re-derive on a re-seed\n [columns, paletteVersion],\n );\n\n const mergedStyles = useMemo(\n () => ({\n // A table normally fills its flex pane. `min-height: 0` lets the scroller\n // become smaller than its contents instead of forcing that pane taller.\n height: 'min 0',\n flexGrow: 1,\n flexShrink: 1,\n ...styles,\n // Auto-height is a layout mode rather than a styling suggestion: its\n // rows determine the frame even when a wrapper supplied fixed sizing.\n ...(isAutoHeight\n ? { height: 'min 0', flexGrow: 0, flexShrink: 0 }\n : null),\n ...(contentPreset ? { Table: { preset: contentPreset } } : null),\n ...(headerStyles ? { HeadRow: headerStyles } : null),\n ...(headerPreset || headerCellStyles || tints.headerCellStyles\n ? {\n HeaderCell: {\n ...(headerPreset ? { preset: headerPreset } : null),\n ...tints.headerCellStyles,\n // The consumer's own overrides land last, so a `headerCellStyles`\n // that sets `#cell-base` outright still wins over a tint.\n ...headerCellStyles,\n },\n }\n : null),\n ...(headerPreset || headerCellStyles\n ? {\n HeaderGroupCell: {\n ...(headerPreset ? { preset: headerPreset } : null),\n ...headerCellStyles,\n },\n }\n : null),\n ...(bodyStyles ? { Body: bodyStyles } : null),\n ...(rowStyles ? { Row: rowStyles } : null),\n ...(cellStyles || tints.cellStyles\n ? { Cell: { ...tints.cellStyles, ...cellStyles } }\n : null),\n // `rowHeight` first — an exact px answer beats a named step.\n ...(rowHeight != null\n ? { '$row-height': `${rowHeight}px` }\n : rowSizeKey\n ? { '$row-height': `$size-${rowSizeKey.toLowerCase()}` }\n : null),\n ...(headerHeight != null\n ? { '$header-height': `${headerHeight}px` }\n : null),\n }),\n [\n styles,\n isAutoHeight,\n headerStyles,\n headerCellStyles,\n headerPreset,\n contentPreset,\n bodyStyles,\n rowStyles,\n cellStyles,\n rowSizeKey,\n rowHeight,\n headerHeight,\n tints,\n ],\n );\n\n /**\n * Whether a cell is inside the current range.\n *\n * Pinned rows take part: they sit in the range's row order at the position\n * they occupy on screen, so a selection down a column of figures reaches its\n * total instead of leaving it to be copied separately. (ag-grid excludes\n * pinned rows outright; this is a deliberate departure.)\n */\n function isCellSelected(rowKey: Key, columnKey: string) {\n if (!cellSelection?.isEnabled) return false;\n\n return cellSelection.isSelected(rowKey, columnKey);\n }\n\n /**\n * Press and drag for the range.\n *\n * `pointerdown` rather than `click`: the range has to start before the drag\n * does, and a click only lands after the button comes back up — by which time\n * the gesture is over. `pointerenter` grows it while the button is held, which\n * is the same shape ag-grid's `onCellMouseOver` gives the Cloud grids.\n */\n function cellSelectionProps(\n rowKey: Key,\n columnKey: string,\n pinnedEdge?: 'top' | 'bottom',\n ) {\n // A vetoed cell gets no handlers at all, so it is inert rather than merely\n // unpainted: pressing it neither starts a range nor disturbs the standing\n // one, which is how ag-grid treats a press on its row-number column.\n if (!cellSelection?.canSelectCell(rowKey, columnKey)) return undefined;\n\n return {\n onPointerDown: (event: ReactPointerEvent<HTMLTableCellElement>) => {\n // Right-click keeps whatever is selected, so a context menu can act on\n // the range the user has already built.\n if (event.button !== 0) return;\n\n if (event.shiftKey) {\n // Otherwise the browser paints a text selection from the anchor to\n // here, on top of the cell range.\n event.preventDefault();\n cellSelection.extendTo(rowKey, columnKey);\n } else {\n cellSelection.select(rowKey, columnKey);\n }\n\n // The range's keyboard affordances — Escape to clear, ⌘/Ctrl+C to copy\n // — are handled on the scroller, and a `<td>` takes no focus of its\n // own, so a press would otherwise leave focus on `<body>` and neither\n // would ever fire.\n scrollerRef.current?.focus({ preventScroll: true });\n\n cellSelection.isDraggingRef.current = true;\n setIsRangeDragging(true);\n },\n onPointerEnter: () => {\n if (!cellSelection.isDraggingRef.current) return;\n\n // Reachable by press and by shift-click, but never by dragging THROUGH.\n // A pinned row sits over the scrolling ones, so a downward drag brushes\n // it long before reaching the end of the data — and being last in the\n // row order, that would snap the range to the whole rest of the grid.\n if (pinnedEdge) return;\n\n cellSelection.extendTo(rowKey, columnKey);\n },\n };\n }\n\n /**\n * Marks the trailing column.\n *\n * Two things hang off it. Its resize handle tucks fully inside rather than\n * straddling a boundary that is not there — left hanging it puts half its\n * width past the table, and the scroller gains a few pixels of horizontal\n * scroll onto blank space. And it draws no vertical rule: that rule would\n * land flush against the frame and read as a doubled edge.\n */\n /** The pinned edge a row was rendered at, as the documented section name. */\n function sectionOf(pinnedEdge?: 'top' | 'bottom'): CubeTableRowSection {\n if (pinnedEdge === 'top') return 'pinnedTop';\n if (pinnedEdge === 'bottom') return 'pinnedBottom';\n\n return 'body';\n }\n\n function lastColumnFlag(column: CubeResolvedColumn<T>) {\n return column.index === columns.length - 1 ? '' : undefined;\n }\n\n /**\n * Which frame corner, if any, this cell sits in.\n *\n * Only the two bottom ones, and only when the card's rounded edge is what the\n * row actually meets — a footer below it means the row ends against a straight\n * line instead. Without this a selected cell in that row has its ring sliced\n * off at 45° by the frame's radius, which reads as a rendering fault rather\n * than as a corner.\n *\n * Decided here rather than in CSS: the renderer already knows about the\n * footer, the shape and the pinned rows, and expressing\n * `card × no-footer × visually-last-row × outer-column` as a state map is how\n * a border map turns into a combinatorial one.\n */\n function bottomCornerFlag(\n column: CubeResolvedColumn<T>,\n rowIndex: number,\n isLastRow: boolean,\n pinnedEdge?: 'top' | 'bottom',\n ) {\n if (shape !== 'card' || footer != null) return undefined;\n\n const pinnedBottomCount = pinnedBottomRows?.length ?? 0;\n const isVisualLastRow =\n pinnedEdge === 'bottom'\n ? rowIndex === pinnedBottomCount - 1\n : pinnedEdge == null && isLastRow && pinnedBottomCount === 0;\n\n if (!isVisualLastRow) return undefined;\n if (column.index === 0) return 'start';\n if (column.index === columns.length - 1) return 'end';\n\n return undefined;\n }\n\n /**\n * The row band, mirrored from the `<tr>` onto its cells.\n *\n * `Row` already carries `data-odd` and publishes `#row-base` from it, which is\n * all an untinted cell needs. A TINTED cell has to pick its own band, and a\n * sub-element's state keys resolve against the table root rather than its DOM\n * parent — so the flag has to be on the cell itself. Same reason `data-pinned`\n * is mirrored.\n *\n * Pinned rows are exempt: they carry no `data-odd` on the `<tr>` either, and\n * banding a totals row would be wrong.\n */\n function cellBandFlag(rowIndex: number, pinnedEdge?: 'top' | 'bottom') {\n return pinnedEdge == null && isStriped && rowIndex % 2 === 1\n ? ''\n : undefined;\n }\n\n function renderStateRow(content: ReactNode) {\n return (\n <tr data-element=\"Row\" role=\"row\" aria-rowindex={headerRowCount + 1}>\n <td\n data-element=\"StateCell\"\n data-state=\"\"\n role=\"gridcell\"\n colSpan={Math.max(columnCount, 1)}\n aria-colindex={1}\n >\n <div data-element=\"StateContent\">{content}</div>\n </td>\n </tr>\n );\n }\n\n function renderSkeletonRows(\n count = skeletonRowCount,\n keyPrefix = 'skeleton',\n ) {\n return Array.from({ length: count }, (_, rowIndex) => (\n <tr\n key={`${keyPrefix}-${rowIndex}`}\n data-element=\"Row\"\n data-placeholder=\"\"\n role=\"row\"\n aria-rowindex={bodyRowIndex(rowIndex)}\n aria-busy=\"true\"\n >\n {columns.map((column) => (\n <td\n key={column.key}\n data-element=\"Cell\"\n data-pin={column.pin}\n data-pin-edge={column.isPinEdge ? '' : undefined}\n data-align={column.align}\n role=\"gridcell\"\n aria-colindex={column.ariaColIndex}\n style={pinStyle(column)}\n >\n <Placeholder />\n </td>\n ))}\n </tr>\n ));\n }\n\n function renderSelectionHeaderCell(\n column: CubeResolvedColumn<T>,\n rowSpan = 1,\n ) {\n return (\n <th\n key={column.key}\n data-element=\"HeaderCell\"\n data-key={column.key}\n data-kind=\"selection\"\n data-pin={column.pin}\n data-pin-edge={column.isPinEdge ? '' : undefined}\n data-last-column={lastColumnFlag(column)}\n role=\"columnheader\"\n scope=\"col\"\n rowSpan={rowSpan > 1 ? rowSpan : undefined}\n tabIndex={-1}\n aria-colindex={column.ariaColIndex}\n style={pinStyle(column)}\n >\n {selection && selection.selectionMode === 'multiple' ? (\n <div data-element=\"SelectionBox\">\n <Checkbox\n aria-label={\n selection.selectAllState === 'all'\n ? t('itemTable.deselectAll', 'Deselect all')\n : t('itemTable.selectAll', 'Select all')\n }\n isSelected={selection.selectAllState === 'all'}\n isIndeterminate={selection.selectAllState === 'some'}\n onChange={selection.toggleSelectAll}\n />\n </div>\n ) : null}\n </th>\n );\n }\n\n function renderSelectionCell(\n column: CubeResolvedColumn<T>,\n row: T,\n rowIndex: number,\n rowKey: Key,\n isLastRow: boolean,\n pinnedEdge?: 'top' | 'bottom',\n ) {\n const canSelect = selection!.canSelect(rowKey);\n const tooltip =\n typeof selectionTooltip === 'function'\n ? selectionTooltip(row)\n : selectionTooltip;\n\n const checkbox = (\n <Checkbox\n aria-label={t('itemTable.selectRow', 'Select row')}\n isSelected={selection!.isSelected(rowKey)}\n isIndeterminate={selection!.isIndeterminate(rowKey)}\n isDisabled={!canSelect}\n onChange={() => selection!.toggleRow(rowKey)}\n />\n );\n\n return (\n <td\n key={column.key}\n data-element=\"Cell\"\n data-key={column.key}\n data-kind=\"selection\"\n data-pin={column.pin}\n data-pin-edge={column.isPinEdge ? '' : undefined}\n data-last-row={isLastRow ? '' : undefined}\n data-pinned={pinnedEdge}\n data-odd={cellBandFlag(rowIndex, pinnedEdge)}\n data-last-column={lastColumnFlag(column)}\n data-corner={bottomCornerFlag(column, rowIndex, isLastRow, pinnedEdge)}\n role=\"gridcell\"\n aria-colindex={column.ariaColIndex}\n style={pinStyle(column)}\n // `Checkbox` reports only the next value, so the modifier that decides\n // toggle-vs-extend is read off the event that produced it.\n //\n // `click` rather than `pointerdown`: capture on the cell still runs\n // before the checkbox's own `change` handler, and unlike pointer events\n // it carries the modifier state in every environment — including\n // keyboard activation and jsdom.\n onClickCapture={selection!.captureShift}\n onKeyDownCapture={selection!.captureShift}\n >\n <div data-element=\"SelectionBox\">\n {!canSelect && tooltip ? (\n <TooltipProvider title={tooltip}>{checkbox}</TooltipProvider>\n ) : (\n checkbox\n )}\n </div>\n </td>\n );\n }\n\n function renderRowMenuCell(\n column: CubeResolvedColumn<T>,\n row: T,\n rowIndex: number,\n rowKey: Key,\n isLastRow: boolean,\n pinnedEdge?: 'top' | 'bottom',\n ) {\n const items = resolveRowMenu(row, rowIndex, rowKey);\n\n return (\n <td\n key={column.key}\n data-element=\"Cell\"\n data-key={column.key}\n data-kind=\"actions\"\n data-pin={column.pin}\n data-pin-edge={column.isPinEdge ? '' : undefined}\n data-last-row={isLastRow ? '' : undefined}\n data-pinned={pinnedEdge}\n data-odd={cellBandFlag(rowIndex, pinnedEdge)}\n data-last-column={lastColumnFlag(column)}\n data-corner={bottomCornerFlag(column, rowIndex, isLastRow, pinnedEdge)}\n role=\"gridcell\"\n aria-colindex={column.ariaColIndex}\n style={pinStyle(column)}\n >\n {isMenuEmpty(items) ? null : (\n <div data-element=\"RowActions\">\n <MenuTrigger>\n <ItemAction\n // The grid is one tab stop; in-cell controls are reached with\n // arrow keys, matching `TreeNode`.\n tabIndex={-1}\n icon={<MoreIcon />}\n aria-label={t('itemTable.rowActions', 'Row actions')}\n {...rowMenuTriggerProps}\n />\n <Menu onAction={menuActionHandler(row, rowKey, false)}>\n {items}\n </Menu>\n </MenuTrigger>\n </div>\n )}\n </td>\n );\n }\n\n function renderHeaderCell(column: CubeResolvedColumn<T>, rowSpan = 1) {\n if (column.key === SELECTION_COLUMN_KEY) {\n return renderSelectionHeaderCell(column, rowSpan);\n }\n\n if (column.key === ROW_NUMBER_COLUMN_KEY) {\n // Deliberately unnamed: the numbers are a reading aid, not data, and a\n // column header would invite sorting by them.\n return (\n <th\n key={column.key}\n data-element=\"HeaderCell\"\n data-key={column.key}\n data-kind=\"row-number\"\n data-last-column={lastColumnFlag(column)}\n role=\"columnheader\"\n scope=\"col\"\n rowSpan={rowSpan > 1 ? rowSpan : undefined}\n tabIndex={-1}\n aria-colindex={column.ariaColIndex}\n style={pinStyle(column)}\n />\n );\n }\n\n if (column.key === ROW_MENU_COLUMN_KEY) {\n // An empty header keeps the column in the ARIA geometry without\n // announcing a name for a column that holds no data.\n return (\n <th\n key={column.key}\n data-element=\"HeaderCell\"\n data-key={column.key}\n data-kind=\"actions\"\n data-pin={column.pin}\n data-pin-edge={column.isPinEdge ? '' : undefined}\n data-last-column={lastColumnFlag(column)}\n role=\"columnheader\"\n scope=\"col\"\n rowSpan={rowSpan > 1 ? rowSpan : undefined}\n tabIndex={-1}\n aria-colindex={column.ariaColIndex}\n style={pinStyle(column)}\n />\n );\n }\n\n const header = column.header;\n // One resolution path for both shapes, so every consumer of `isSorted`\n // below stays unaware of which one the caller supplied.\n const activeSorts = sorts ?? (sort ? [sort] : []);\n const sortIndex = activeSorts.findIndex(\n (entry) => entry.columnKey === column.key,\n );\n const activeSort = sortIndex === -1 ? null : activeSorts[sortIndex];\n const isSorted = activeSort != null;\n // Only worth showing when more than one column is sorted — a lone \"1\"\n // beside an arrow is noise.\n const sortRank = activeSorts.length > 1 ? sortIndex + 1 : null;\n const isSortable =\n sortMode !== 'off' && !column.isStructural && column.isSortable === true;\n\n // A structural column has no content to make room for, and resizing needs\n // somewhere to write the result.\n const canResize =\n !column.isStructural &&\n (column.isResizable ?? isResizable) &&\n onColumnResize != null &&\n onColumnResizeEnd != null;\n\n const ctx: CubeTableHeaderContext = {\n columnKey: column.key,\n columnIndex: column.index,\n sort: activeSort?.direction ?? null,\n isSortable,\n isResizing: false,\n width: column.width,\n };\n\n // The arrow keeps its slot even when unsorted, so turning a sort on and off\n // never shifts the label.\n //\n // Two glyphs rather than one flipped with `scale`. A narrow arrow flipped\n // vertically does land on its own opposite, but rendering the real icon is\n // what keeps that true — a glyph that is not perfectly symmetric would come\n // out subtly wrong, and nothing would say why.\n //\n // Unsorted shows the UP arrow, because that is what the first press gives:\n // the hint predicts the press rather than advertising that one is possible.\n const sortIndicator = isSortable ? (\n <div\n data-element=\"SortIndicator\"\n data-rank={sortRank ?? undefined}\n data-sorted={isSorted ? '' : undefined}\n data-dir={activeSort?.direction}\n aria-hidden=\"true\"\n >\n {activeSort?.direction === 'desc' ? (\n <ArrowNarrowDownIcon />\n ) : (\n <ArrowNarrowUpIcon />\n )}\n </div>\n ) : null;\n\n // The arrow belongs in the `rightIcon` slot: that slot is sized and aligned\n // for an icon, while `suffix` is a text slot and puts the glyph on the\n // label's baseline.\n //\n // A `header.rightIcon` the consumer asked for keeps the slot, and the arrow\n // falls back to `suffix` — rare, and better than dropping either one.\n const hasCustomRightIcon = header?.rightIcon != null;\n const rightIcon = hasCustomRightIcon ? header!.rightIcon : sortIndicator;\n\n const suffixContent = hasCustomRightIcon ? sortIndicator : null;\n const suffix =\n header?.suffix != null || suffixContent ? (\n <>\n {header?.suffix}\n {suffixContent}\n </>\n ) : undefined;\n\n const menuItems = resolveColumnMenu(column);\n const hasMenu = menuItems != null;\n const isContextOnly = columnContextMenu === 'context-only';\n\n const menuAction =\n hasMenu && !isContextOnly ? (\n <MenuTrigger\n isOpen={openMenuColumnKey === column.key}\n // `bottom end`: the trigger sits at the column's trailing edge, so a\n // start-aligned popover hangs off the table on the last column.\n placement=\"bottom end\"\n onOpenChange={(open) =>\n setOpenMenuColumnKey(open ? column.key : null)\n }\n >\n <ItemAction\n // The grid is one tab stop; the trigger is reached from the header\n // cell with Shift+F10, matching the row menu.\n tabIndex={-1}\n icon={<MoreIcon />}\n aria-label={t('itemTable.columnMenu', 'Column menu')}\n {...columnMenuTriggerProps}\n {...header?.menuTriggerProps}\n />\n <Menu\n {...columnMenuProps}\n {...header?.menuProps}\n onAction={columnMenuActionHandler(column, false)}\n >\n {processColumnMenuItems(\n menuItems,\n columnMenuContext(column, isSortable, activeSort),\n )}\n </Menu>\n </MenuTrigger>\n ) : null;\n\n // The consumer's own actions first, the overflow menu last — matching Tabs.\n const actions =\n header?.actions != null || menuAction ? (\n <>\n {header?.actions}\n {menuAction}\n </>\n ) : undefined;\n\n const content = header?.render ? (\n header.render(ctx)\n ) : column.title == null && !header ? null : (\n <TableHeaderItem\n icon={header?.icon}\n rightIcon={rightIcon}\n prefix={header?.prefix}\n suffix={suffix}\n description={header?.description}\n descriptionPlacement={header?.descriptionPlacement}\n tooltip={header?.tooltip ?? true}\n theme={header?.theme}\n actions={actions}\n autoHideActions={header?.autoHideActions ?? true}\n // Without it the actions slot animates its width from 0 on hover, which\n // re-truncates the label — so the header text shifts under the cursor.\n // Only the opacity should move; `TabElement` reserves the space for the\n // same reason.\n preserveActionsSpace={actions != null}\n styles={header?.styles}\n >\n {column.title}\n </TableHeaderItem>\n );\n\n const isDraggable = isColumnDraggable(column, isColumnReorderable);\n\n return (\n <TableHeaderCell\n key={column.key}\n columnKey={column.key}\n // Enter belongs to the sort when there is one, so React Aria re-gates\n // its own Enter capture behind Alt.\n hasAction={isSortable}\n isLastDraggable={isDraggable && column.key === lastDraggableKey}\n dragState={isDraggable ? columnDragState : undefined}\n dropState={isDraggable ? columnDropState : undefined}\n cellProps={{\n 'data-element': 'HeaderCell',\n 'data-key': column.key,\n 'data-pin': column.pin,\n 'data-pin-edge': column.isPinEdge ? '' : undefined,\n 'data-align': header?.align ?? column.align,\n 'data-sortable': isSortable ? '' : undefined,\n 'data-resizable': canResize ? '' : undefined,\n 'data-last-column': lastColumnFlag(column),\n 'data-sorted': isSorted ? '' : undefined,\n 'data-menu-open': openMenuColumnKey === column.key ? '' : undefined,\n 'data-tint': tintSlot(tints, column.key, 'header'),\n role: 'columnheader',\n scope: 'col',\n rowSpan: rowSpan > 1 ? rowSpan : undefined,\n // A sortable header is a control, so it takes a tab stop — and so does\n // one carrying a menu (Shift+F10 needs somewhere to land) or one that\n // can be moved with Alt+Arrow. Row/cell keyboard navigation lands in a\n // follow-up and will move this to the grid's roving-tabindex model.\n tabIndex: isSortable || hasMenu || isDraggable ? 0 : -1,\n 'aria-colindex': column.ariaColIndex,\n 'aria-sort': activeSort ? ARIA_SORT[activeSort.direction] : undefined,\n 'aria-haspopup': hasMenu ? 'menu' : undefined,\n style: pinStyle(column),\n // React Aria's Alt+Arrow reorder reads `focusedKey`, and nothing else\n // sets it — `useDroppableCollection` only ever reads it.\n onFocus: isColumnReorderable\n ? () => onColumnFocus?.(isDraggable ? column.key : null)\n : undefined,\n onClick: isSortable ? () => onColumnSort?.(column.key) : undefined,\n // Both `true` and `'context-only'` answer to a right-click, and\n // `false` already made `hasMenu` false in `resolveColumnMenu`.\n onContextMenu: hasMenu\n ? (event: ReactMouseEvent) =>\n openColumnContextMenu(column, isSortable, activeSort, event)\n : undefined,\n onKeyDown:\n isSortable || hasMenu\n ? (event: ReactKeyboardEvent) => {\n // Shift+F10 is the standard keyboard route to a context menu,\n // and the only route to this one — the trigger is not a tab\n // stop.\n if (event.key === 'F10' && event.shiftKey && hasMenu) {\n if (isContextOnly) {\n openColumnContextMenu(\n column,\n isSortable,\n activeSort,\n event,\n );\n } else {\n event.preventDefault();\n // The Scroller listens for Shift+F10 too, for the row menu.\n event.stopPropagation();\n setOpenMenuColumnKey(column.key);\n }\n\n return;\n }\n\n if (!isSortable) return;\n if (event.key !== 'Enter' && event.key !== ' ') return;\n // Space would scroll the grid otherwise.\n event.preventDefault();\n onColumnSort?.(column.key);\n }\n : undefined,\n }}\n >\n {content}\n {canResize ? (\n <ColumnResizer<T>\n column={column}\n label={t('itemTable.resizeColumn', 'Resize column')}\n onResize={onColumnResize!}\n onResizeEnd={onColumnResizeEnd!}\n />\n ) : null}\n </TableHeaderCell>\n );\n }\n\n function renderCell(\n column: CubeResolvedColumn<T>,\n row: T,\n rowIndex: number,\n rowKey: Key,\n isLastRow: boolean,\n // The row's pinned edge, mirrored onto its cells. Cells are what draw the\n // borders and the fill, and a sub-element cannot ask about its DOM parent's\n // mods — state keys inside `Cell` resolve against the table root.\n pinnedEdge?: 'top' | 'bottom',\n treeItemAria?: ReturnType<typeof useTreeItem>,\n ) {\n // Section-qualified, because the same record is routinely pinned at both\n // edges. `rowKey` below stays the consumer's own — this identity is the\n // range's alone.\n const rangeKey = selectionRowKey(sectionOf(pinnedEdge), rowKey);\n if (column.key === SELECTION_COLUMN_KEY) {\n return renderSelectionCell(\n column,\n row,\n rowIndex,\n rowKey,\n isLastRow,\n pinnedEdge,\n );\n }\n\n if (column.key === ROW_NUMBER_COLUMN_KEY) {\n return (\n <td\n key={column.key}\n data-element=\"Cell\"\n data-key={column.key}\n data-kind=\"row-number\"\n data-last-row={isLastRow ? '' : undefined}\n data-pinned={pinnedEdge}\n data-odd={cellBandFlag(rowIndex, pinnedEdge)}\n data-last-column={lastColumnFlag(column)}\n data-corner={bottomCornerFlag(\n column,\n rowIndex,\n isLastRow,\n pinnedEdge,\n )}\n role=\"gridcell\"\n aria-colindex={column.ariaColIndex}\n style={pinStyle(column)}\n >\n {/*\n A pinned row is not numbered. It sits outside the sequence — a\n total is not row 1 — and numbering it would repeat a number the\n scrolling rows already own.\n */}\n {pinnedEdge ? null : rowNumberOffset + rowIndex + 1}\n </td>\n );\n }\n\n if (column.key === ROW_MENU_COLUMN_KEY) {\n return renderRowMenuCell(\n column,\n row,\n rowIndex,\n rowKey,\n isLastRow,\n pinnedEdge,\n );\n }\n\n const ctx: CubeTableCellContext<T> = {\n row,\n rowKey,\n rowIndex,\n columnKey: column.key,\n columnIndex: column.index,\n section: sectionOf(pinnedEdge),\n // The ROW's selection, matching the field's siblings (`isRowFocused`).\n // Cell-range membership is a different question and has its own answer in\n // `data-cell-selected`.\n isSelected: selection?.isSelected(rowKey) ?? false,\n tree: pinnedEdge == null ? treeRowState(rowIndex) : undefined,\n };\n\n const value = column.isStructural\n ? undefined\n : getColumnValue(column, row, rowIndex);\n\n // Without `render`, the cell shows the column's display text — which is\n // what `format` produces, and what client sort, search and copy all agree\n // on. `getColumnText` returns null for a value it cannot turn into text\n // (an object with no `format`), so we render nothing rather than\n // \"[object Object]\".\n const rendered = column.render\n ? column.render(value, row, rowIndex, ctx)\n : column.isStructural\n ? null\n : getColumnText(column, row, rowIndex);\n\n const isText =\n typeof rendered === 'string' ||\n typeof rendered === 'number' ||\n typeof rendered === 'bigint';\n\n // Bare text gets ellipsis + an automatic tooltip when it overflows.\n // `TextItem` rather than `Item` deliberately: `Item` runs `useHotkeys` on\n // every instance, which at one per cell would be hundreds of subscriptions\n // churned on every scroll tick.\n //\n // An `autoHeight` column skips it — `TextItem` exists to truncate, and this\n // column has opted into wrapping instead.\n const content =\n isText && !column.autoHeight ? (\n <TextItem>{String(rendered)}</TextItem>\n ) : isText ? (\n String(rendered)\n ) : (\n (rendered as ReactNode)\n );\n\n const treeEntry = pinnedEdge == null ? tree?.entries[rowIndex] : undefined;\n const displayContent =\n treeEntry && column.key === tree?.columnKey ? (\n <div\n data-element=\"TreeContent\"\n style={\n {\n '--tree-level': String(treeEntry.level),\n } as CSSProperties\n }\n >\n {treeEntry.children.length > 0 ? (\n <TableTreeToggle\n {...treeItemAria?.expandButtonProps}\n data-element=\"TreeToggle\"\n tabIndex={-1}\n >\n <DirectionIcon\n to={\n tree.state.expandedKeys.has(treeEntry.key)\n ? 'bottom'\n : 'right'\n }\n />\n </TableTreeToggle>\n ) : (\n <TableTreeTogglePlaceholder\n data-element=\"TreeToggle\"\n aria-hidden=\"true\"\n />\n )}\n <div data-element=\"TreeValue\">{content}</div>\n </div>\n ) : (\n content\n );\n\n const resolvedCellStyles =\n typeof column.cellStyles === 'function'\n ? column.cellStyles(ctx)\n : column.cellStyles;\n\n const CellTag = column.isRowHeader ? 'th' : 'td';\n\n // The link lives in the row-header cell but stretches over the whole row:\n // a `<tr>` cannot be wrapped in an `<a>`, and this is the one cell whose\n // text is the row's accessible name. ⌘-click, middle-click and \"Open in\n // new tab\" then work natively, which an onClick handler can never give.\n const link = column.isRowHeader ? rowLink?.(row, rowIndex) : undefined;\n\n return (\n <CellTag\n key={column.key}\n data-element=\"Cell\"\n data-key={column.key}\n data-pin={column.pin}\n data-pin-edge={column.isPinEdge ? '' : undefined}\n data-align={column.align}\n data-wrap={column.autoHeight ? '' : undefined}\n data-link={link !== undefined ? '' : undefined}\n data-last-row={isLastRow ? '' : undefined}\n data-pinned={pinnedEdge}\n data-odd={cellBandFlag(rowIndex, pinnedEdge)}\n data-tint={tintSlot(\n tints,\n column.key,\n pinnedEdge == null ? 'body' : 'totals',\n )}\n data-last-column={lastColumnFlag(column)}\n data-corner={bottomCornerFlag(column, rowIndex, isLastRow, pinnedEdge)}\n data-cell-selected={\n isCellSelected(rangeKey, column.key) ? '' : undefined\n }\n {...(column.isRowHeader\n ? { scope: 'row' as const }\n : { role: 'gridcell' as const })}\n {...cellSelectionProps(rangeKey, column.key, pinnedEdge)}\n aria-colindex={column.ariaColIndex}\n style={{\n ...pinStyle(column),\n ...(resolvedCellStyles as CSSProperties),\n }}\n {...column.cellProps?.(ctx)}\n >\n {displayContent}\n {link !== undefined ? (\n <Action\n data-element=\"RowLink\"\n to={link}\n // The row is the tab stop; the link is reached through it.\n tabIndex={-1}\n aria-label={getColumnText(column, row, rowIndex) ?? undefined}\n />\n ) : null}\n </CellTag>\n );\n }\n\n /**\n * A pinned row — a total or subtotal.\n *\n * Rendered inside `<tbody>` rather than `<thead>`/`<tfoot>` so it keeps the\n * body's own row and cell styling: the sub-element chains are anchored to\n * `Body`, and a row in the head would match none of them. `data-pinned`\n * carries the stickiness instead.\n */\n function renderPinnedRow(row: T, index: number, edge: 'top' | 'bottom') {\n // The consumer's own key, not a positional one: a cell range spans pinned\n // and scrolling rows alike, so both have to answer to the same identity.\n const rowKey = getRowKey(row, index);\n\n return (\n <tr\n key={`pinned-${edge}-${rowKey}`}\n data-element=\"Row\"\n data-pinned={edge}\n role=\"row\"\n aria-rowindex={pinnedRowIndex(index, edge)}\n >\n {columns.map((column) =>\n renderCell(column, row, index, rowKey, false, edge),\n )}\n </tr>\n );\n }\n\n /** The cells of one body row. Shared by both render paths. */\n function renderRowCells(\n row: T,\n rowIndex: number,\n treeItemAria?: ReturnType<typeof useTreeItem>,\n ) {\n const rowKey = bodyRowKey(row, rowIndex);\n\n return columns.map((column) =>\n renderCell(\n column,\n row,\n rowIndex,\n rowKey,\n rowIndex === rows.length - 1,\n undefined,\n treeItemAria,\n ),\n );\n }\n\n /**\n * The `<tr>` shell. Virtuoso owns the element in the virtualized path (it\n * needs its own `style` and measurement attributes), so this returns the\n * props rather than the element.\n */\n function getRowElementProps(row: T, rowIndex: number) {\n const rowKey = bodyRowKey(row, rowIndex);\n const isSelected = selection?.isSelected(rowKey) ?? false;\n const ctx: CubeTableRowContext<T> = {\n row,\n rowKey,\n rowIndex,\n section: 'body',\n isSelected,\n tree: treeRowState(rowIndex),\n };\n const extra = getRowProps?.(ctx);\n\n return {\n 'data-element': 'Row',\n 'data-key': String(rowKey),\n // Lets a pointer or keyboard event resolve back to its row without a\n // closure per row.\n 'data-row-index': rowIndex,\n 'data-qa': extra?.qa,\n 'data-odd': isStriped && rowIndex % 2 === 1 ? '' : undefined,\n 'data-dimmed': extra?.isDimmed ? '' : undefined,\n 'data-selected': isSelected ? '' : undefined,\n 'data-disabled': selection?.isRowDisabled(rowKey) ? '' : undefined,\n role: 'row',\n // Only the resting row takes a tab stop; the rest are reached with the\n // arrow keys. Off entirely when nothing on the row is operable.\n tabIndex:\n !tree && isReorderable\n ? rowIndex === focusedRowIndex\n ? 0\n : -1\n : undefined,\n // Only meaningful in a selectable grid; announcing \"not selected\" on\n // every row of a plain table is noise.\n 'aria-selected': selection?.isEnabled ? isSelected : undefined,\n 'aria-rowindex': bodyRowIndex(rowIndex),\n title: extra?.tooltip,\n height: extra?.height,\n 'data-clickable':\n onRowAction != null || rowLink?.(row, rowIndex) !== undefined\n ? ''\n : undefined,\n onClick:\n onRowAction != null\n ? (event: ReactMouseEvent) => {\n // A click that landed on a control inside the cell belongs to\n // that control — the row must not also act on it.\n if (\n (event.target as HTMLElement).closest(\n 'a, button, input, select, textarea, [role=\"button\"], [role=\"menuitem\"]',\n )\n ) {\n return;\n }\n\n onRowAction(row, rowKey);\n }\n : undefined,\n onContextMenu: isMenuEnabled\n ? (event: ReactMouseEvent) =>\n openContextMenuFor(row, rowIndex, rowKey, event)\n : undefined,\n ...Object.fromEntries(\n Object.entries(extra?.mods ?? {})\n .filter(([, active]) => active)\n .map(([name]) => [`data-${name}`, '']),\n ),\n } as Record<string, any>;\n }\n\n function renderRow(row: T, rowIndex: number, isVirtual = false) {\n const { height, ...rowProps } = getRowElementProps(row, rowIndex);\n const rowKey = bodyRowKey(row, rowIndex);\n const treeNode = tree?.nodes[rowIndex];\n const treeEntry = tree?.entries[rowIndex];\n\n return (\n <TableRow\n key={rowProps['data-key']}\n rowKey={rowKey}\n rowProps={rowProps}\n height={height}\n index={isVirtual ? rowIndex : undefined}\n measureRef={isVirtual ? virtualizer.measureElement : undefined}\n dragState={isReorderable ? dragState : undefined}\n dropState={isReorderable ? dropState : undefined}\n tree={\n treeNode && treeEntry\n ? {\n state: tree.state,\n node: treeNode,\n entry: treeEntry,\n isVirtualized: isVirtual,\n }\n : undefined\n }\n >\n {(treeItemAria) => renderRowCells(row, rowIndex, treeItemAria)}\n </TableRow>\n );\n }\n\n function renderSpacerRow(height: number, position: 'top' | 'bottom') {\n if (height <= 0) return null;\n\n return (\n <tr aria-hidden=\"true\" data-spacer={position}>\n <td colSpan={Math.max(columnCount, 1)} style={{ height }} />\n </tr>\n );\n }\n\n /**\n * A row, preceded by the line showing a drop above it — and followed by one\n * for the very last row, which has nothing after it to carry a \"before\".\n *\n * The indicators render nothing unless a drag is in flight, so a table that\n * is merely *capable* of dragging keeps its ordinary structure.\n */\n function withDropIndicators(row: T, index: number, isVirtual = false) {\n const rowKey = bodyRowKey(row, index);\n const rowNode = renderRow(row, index, isVirtual);\n\n if (!isReorderable || !dropState) return rowNode;\n\n return (\n <Fragment key={`row-${String(rowKey)}`}>\n <TableRowDropIndicator\n rowKey={rowKey}\n dropPosition=\"before\"\n dropState={dropState}\n columnCount={columnCount}\n />\n {rowNode}\n {index === rows.length - 1 ? (\n <TableRowDropIndicator\n rowKey={rowKey}\n dropPosition=\"after\"\n dropState={dropState}\n columnCount={columnCount}\n />\n ) : null}\n </Fragment>\n );\n }\n\n const hasRows = rows.length > 0;\n\n // How a refresh over an existing result is presented. `overlay` keeps the\n // previous rows on screen (dimmed, behind a spinner) so a server page or a\n // re-sort does not blank the table; `skeleton` discards them; `none` leaves\n // the visuals entirely to the consumer and only sets `aria-busy`.\n // `overlay` is the only behaviour that paints: the rows dim and a spinner\n // sits over them. `none` deliberately leaves them untouched.\n const isStale = isLoading && hasRows && loadingIndicator === 'overlay';\n const showSkeleton =\n isLoading &&\n loadingIndicator !== 'none' &&\n (!hasRows || loadingIndicator === 'skeleton');\n // Without rows and without an indicator there is nothing to say yet —\n // rendering the empty state would flash \"No items\" before the first response.\n const showBlank = isLoading && !hasRows && loadingIndicator === 'none';\n\n const shouldVirtualize =\n !isAutoHeight &&\n hasRows &&\n error == null &&\n (isVirtualized === true ||\n (isVirtualized === 'auto' && rows.length > virtualizeThreshold));\n\n const rowsRef = useRef(rows);\n\n rowsRef.current = rows;\n\n // `getScrollElement` is read from a ref, not the state value: the virtualizer\n // consults it from a layout effect, and a closure over state can still hold\n // the `null` from the first render.\n const virtualizer = useVirtualizer({\n count: shouldVirtualize ? rows.length : 0,\n getScrollElement: () => scrollerRef.current,\n getItemKey: (index) =>\n String(rowKeys?.[index] ?? getRowKey(rowsRef.current[index], index)),\n estimateSize: () =>\n (rowHeight ??\n (rowSizeKey\n ? SIZES[rowSizeKey]\n : ESTIMATED_ROW_HEIGHT[size ?? 'medium'])) + 1,\n measureElement: (element) => element.getBoundingClientRect().height,\n // Rows beyond each viewport edge. Higher than a list's, because a fast\n // flick outruns React's re-render and the gap shows as blank rows — and a\n // table row is one element, not one per column, so the extra ones are\n // cheap.\n overscan,\n });\n\n // `scrollerEl` is referenced only to re-render on the pass where the scroller\n // first exists, so the virtualizer re-reads `getScrollElement` and attaches.\n void scrollerEl;\n\n const focusedTreeKey = tree?.state.selectionManager.focusedKey;\n useEffect(() => {\n if (!shouldVirtualize || focusedTreeKey == null || !tree) return;\n\n const index = tree.entries.findIndex(\n (entry) => entry.key === focusedTreeKey,\n );\n if (index >= 0) virtualizer.scrollToIndex(index, { align: 'auto' });\n }, [focusedTreeKey, shouldVirtualize, tree, virtualizer]);\n\n const scrollability = useScrollability(scrollerEl);\n\n /**\n * Roving tabindex over the rows, so a reorderable table can be operated from\n * the keyboard at all.\n *\n * React Aria's `dragProps` already describe \"press Enter to start dragging\"\n * and implement the whole keyboard drag — but a `<tr>` is not focusable, so\n * without this the description is announced for a row nobody can reach. One\n * tab stop for the grid, arrows to move within it, matching how every other\n * collection in the kit behaves.\n */\n // Not while a drag is in flight: React Aria is already moving the row under\n // the pointer, and a second transform fighting it reads as a stutter.\n useRowMoveAnimation({\n isEnabled: isRowMoveAnimated && !dragState?.draggingKeys?.size,\n bodyRef: localBodyRef,\n });\n\n /**\n * How many rows the next batch is likely to bring, measured across the last\n * fetch that actually happened.\n *\n * The placeholder burst is sized to this so the scroll height is right both\n * before and after the load: a short burst under a long batch makes the\n * content jump the moment the rows land, and leaves the user stopped at the\n * bottom of the list in the meantime with nothing left to scroll into.\n *\n * Measured across `isLoadingMore`, not from any growth in `rows`. Plenty of\n * things lengthen the list without being a fetch — clearing a client search\n * over an infinite list restores every filtered-out row at once — and reading\n * that as a batch of ninety sized the next burst at ninety.\n *\n * Measured at all, rather than taken from `pageSize`, because infinite-scroll\n * consumers often do not set it.\n */\n const lastBatchSizeRef = useRef(0);\n const rowCountBeforeFetchRef = useRef<number | null>(null);\n\n useEffect(() => {\n if (isLoadingMore) {\n rowCountBeforeFetchRef.current = rows.length;\n\n return;\n }\n\n const before = rowCountBeforeFetchRef.current;\n\n if (before != null && rows.length > before) {\n lastBatchSizeRef.current = rows.length - before;\n }\n\n rowCountBeforeFetchRef.current = null;\n // Deliberately keyed on the flag alone: the row count wanted is the one at\n // each edge of the fetch, not every value it passes through.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [isLoadingMore]);\n\n const loadMoreSkeletonCount = Math.min(\n // Until a fetch has been measured, the rows already loaded are the best\n // guess at what the next batch brings — that IS the first page.\n Math.max(lastBatchSizeRef.current || rows.length || skeletonRowCount, 1),\n MAX_LOAD_MORE_SKELETON_ROWS,\n );\n\n const [focusedRowIndex, setFocusedRowIndex] = useState(0);\n // Only used to suppress text selection during the gesture; the range itself\n // lives in a ref so growing it does not re-render on every cell crossed.\n const [isRangeDragging, setIsRangeDragging] = useState(false);\n\n // The button can come up outside the grid — over the footer, over another\n // component, off the window entirely — so the end of the gesture is watched\n // globally rather than on the cell the drag started in.\n useEffect(() => {\n if (!isRangeDragging) return;\n\n const end = () => {\n if (cellSelection) cellSelection.isDraggingRef.current = false;\n setIsRangeDragging(false);\n };\n\n window.addEventListener('pointerup', end);\n window.addEventListener('pointercancel', end);\n\n return () => {\n window.removeEventListener('pointerup', end);\n window.removeEventListener('pointercancel', end);\n };\n }, [isRangeDragging, cellSelection]);\n\n const moveRowFocus = useEvent((from: HTMLElement, delta: number) => {\n const current = from.closest('tr[data-element=\"Row\"]');\n const all = Array.from(\n scrollerRef.current?.querySelectorAll<HTMLTableRowElement>(\n 'tbody tr[data-element=\"Row\"]:not([data-placeholder])',\n ) ?? [],\n );\n\n if (!all.length) return false;\n\n const index = current ? all.indexOf(current as HTMLTableRowElement) : -1;\n const next = Math.min(\n Math.max((index === -1 ? focusedRowIndex : index) + delta, 0),\n all.length - 1,\n );\n\n setFocusedRowIndex(next);\n all[next]?.focus();\n\n return true;\n });\n\n /* ── infinite scroll ────────────────────────────────────────────────────\n * An `IntersectionObserver` on a sentinel row rather than a scroll handler:\n * `rootMargin` expresses \"prefetch this far before the end\" directly, it\n * costs nothing per scroll tick, and it works on both render paths — under\n * virtualization the trailing spacer holds the remaining height, so the\n * sentinel after it still marks the true end of the list.\n * ──────────────────────────────────────────────────────────────────────── */\n const sentinelRef = useRef<HTMLDivElement>(null);\n const onLoadMoreEvent = useEvent(() => onLoadMore?.());\n\n useEffect(() => {\n const sentinel = sentinelRef.current;\n\n // Re-armed whenever `isLoadingMore` flips, so a request in flight cannot be\n // fired again by the sentinel still sitting in view.\n if (!onLoadMore || !hasMore || isLoadingMore || !scrollerEl || !sentinel) {\n return;\n }\n\n // One screen ahead by default: the request goes out while the user still\n // has a viewport of rows left to read, so the batch is usually there before\n // they arrive. Read at arm time rather than tracked — a resize mid-scroll\n // leaves the margin slightly stale, which costs nothing.\n const margin =\n loadMoreMargin ?? Math.max(scrollerEl.clientHeight, MIN_LOAD_MORE_MARGIN);\n\n const observer = new IntersectionObserver(\n (entries) => {\n if (entries.some((entry) => entry.isIntersecting)) onLoadMoreEvent();\n },\n { root: scrollerEl, rootMargin: `0px 0px ${margin}px 0px` },\n );\n\n observer.observe(sentinel);\n\n return () => observer.disconnect();\n }, [\n onLoadMore,\n hasMore,\n isLoadingMore,\n scrollerEl,\n loadMoreMargin,\n onLoadMoreEvent,\n rows.length,\n ]);\n\n /* ── row menu ───────────────────────────────────────────────────────────\n * One instance for the whole table rather than one per row: a table can hold\n * thousands of rows, and only ever one context menu is open.\n *\n * `targetRef` is deliberately left unattached, which keeps the hook's own\n * `contextmenu` listener unbound — it would open with fixed props, and the\n * items depend on which row was right-clicked. The handler below resolves the\n * row first and then opens with that row's items; with no target, the hook\n * positions from the event's viewport coordinates, which is what a\n * pointer-anchored menu wants anyway.\n * ──────────────────────────────────────────────────────────────────────── */\n const contextMenu = useContextMenu<HTMLDivElement, any>(Menu, {\n placement: 'bottom start',\n });\n\n const isMenuEnabled = rowMenu != null && rowContextMenu !== false;\n const hasMenuColumn = isMenuEnabled && rowContextMenu !== 'context-only';\n\n function resolveRowMenu(row: T, rowIndex: number, rowKey: Key) {\n if (!rowMenu) return null;\n\n return rowMenu(row, {\n row,\n rowKey,\n rowIndex,\n section: 'body',\n isSelected: selection?.isSelected(rowKey) ?? false,\n isFocused: false,\n isDropTarget: false,\n });\n }\n\n function menuActionHandler(row: T, rowKey: Key, closeAfter: boolean) {\n return (action: Key) => {\n onRowMenuAction?.(normalizeMenuAction(action), row, rowKey);\n\n // `useContextMenu` leaves its popover open after an action — the same\n // happens in `Tree`, so it is the hook's behaviour rather than this\n // table's. Closing here keeps the row menu correct meanwhile; drop this\n // once the hook closes on select itself.\n if (closeAfter) contextMenu.close();\n };\n }\n\n const openContextMenuFor = useEvent(\n (\n row: T,\n rowIndex: number,\n rowKey: Key,\n event: ReactMouseEvent | ReactKeyboardEvent,\n ) => {\n const items = resolveRowMenu(row, rowIndex, rowKey);\n\n // No items means no menu — falling through to the browser's own context\n // menu is more useful than opening an empty popover.\n if (isMenuEmpty(items)) return;\n\n event.preventDefault();\n contextMenu.open(\n { children: items, onAction: menuActionHandler(row, rowKey, true) },\n undefined,\n // Shift+F10 carries no coordinates; the hook then anchors on the\n // element that produced the event, which is the row.\n 'clientX' in event.nativeEvent\n ? (event.nativeEvent as MouseEvent)\n : undefined,\n );\n },\n );\n\n /* ── column menu ─────────────────────────────────────────────────────────\n * Shares the `contextMenu` instance above. A header right-click is the same\n * pointer-anchored popover with different children, and attaching the hook's\n * `targetRef` to a `<th>` would bind its listener with fixed props — the same\n * reason the row menu leaves it unattached.\n * ──────────────────────────────────────────────────────────────────────── */\n\n function resolveColumnMenu(column: CubeResolvedColumn<T>): ReactNode | null {\n if (columnContextMenu === false || column.isStructural) return null;\n\n const items = column.header?.menu;\n\n return isMenuEmpty(items) ? null : items;\n }\n\n /** The reserved sort keys, labelled here so `column-menu.ts` stays pure. */\n function columnMenuContext(\n column: CubeResolvedColumn<T>,\n isSortable: boolean,\n activeSort: CubeTableSort | null,\n ): CubeColumnMenuContext {\n return {\n isSortable,\n sort: activeSort?.direction ?? null,\n disallowSortRemoval: column.disallowSortRemoval === true,\n labels: {\n 'sort-asc': t('itemTable.sortAscending', 'Sort ascending'),\n 'sort-desc': t('itemTable.sortDescending', 'Sort descending'),\n 'clear-sort': t('itemTable.clearSort', 'Clear sort'),\n },\n };\n }\n\n function columnMenuActionHandler(\n column: CubeResolvedColumn<T>,\n closeAfter: boolean,\n ) {\n return (action: Key) => {\n const normalized = normalizeMenuAction(action);\n\n // The table's own keys are applied first, then the consumer hears about\n // them anyway — so a key can be both understood here and observed there.\n if (isColumnMenuSortKey(normalized)) {\n onColumnSortChange?.(\n column.key,\n COLUMN_MENU_SORT_DIRECTION[normalized],\n );\n }\n\n column.header?.onMenuAction?.(normalized);\n onColumnMenuAction?.(normalized, column.key);\n\n // `useContextMenu` leaves its popover open after an action; see\n // `menuActionHandler` above.\n if (closeAfter) contextMenu.close();\n };\n }\n\n const openColumnContextMenu = useEvent(\n (\n column: CubeResolvedColumn<T>,\n isSortable: boolean,\n activeSort: CubeTableSort | null,\n event: ReactMouseEvent | ReactKeyboardEvent,\n ) => {\n const items = resolveColumnMenu(column);\n\n if (items == null) return;\n\n event.preventDefault();\n // The Scroller listens for Shift+F10 too, for the row menu.\n event.stopPropagation();\n contextMenu.open(\n {\n ...columnMenuProps,\n ...column.header?.menuProps,\n children: processColumnMenuItems(\n items,\n columnMenuContext(column, isSortable, activeSort),\n ),\n onAction: columnMenuActionHandler(column, true),\n },\n undefined,\n 'clientX' in event.nativeEvent\n ? (event.nativeEvent as MouseEvent)\n : undefined,\n );\n },\n );\n\n /** Resolves the row a pointer or keyboard event landed in. */\n function rowFromEvent(target: EventTarget | null) {\n const element = (target as HTMLElement | null)?.closest?.(\n 'tr[data-element=\"Row\"][data-key]',\n );\n\n if (!element) return null;\n\n const index = Number(element.getAttribute('data-row-index'));\n\n if (!Number.isInteger(index)) return null;\n\n const row = rows[index];\n\n return row === undefined\n ? null\n : { row, index, key: bodyRowKey(row, index) };\n }\n\n const virtualItems = shouldVirtualize ? virtualizer.getVirtualItems() : [];\n const paddingTop = virtualItems.length ? virtualItems[0].start : 0;\n const paddingBottom = virtualItems.length\n ? virtualizer.getTotalSize() - virtualItems[virtualItems.length - 1].end\n : 0;\n\n const colGroup = (\n <colgroup>\n {columns.map((column) => (\n <col\n key={column.key}\n style={column.width != null ? { width: column.width } : undefined}\n />\n ))}\n </colgroup>\n );\n\n function pathsSharePrefix(\n left: readonly CubeTableColumnGroupHeader[],\n right: readonly CubeTableColumnGroupHeader[],\n depth: number,\n ) {\n for (let index = 0; index <= depth; index++) {\n if (left[index]?.key !== right[index]?.key) return false;\n }\n\n return true;\n }\n\n function renderHeaderGroupCell(\n group: CubeTableColumnGroupHeader,\n segment: readonly CubeResolvedColumn<T>[],\n depth: number,\n ) {\n const first = segment[0];\n const last = segment[segment.length - 1];\n const pin = segment.every((column) => column.pin === first.pin)\n ? first.pin\n : undefined;\n const pinOffset =\n pin === 'start' ? first.pinOffset : pin === 'end' ? last.pinOffset : null;\n\n return (\n <th\n key={`${depth}:${first.key}:${group.key}`}\n data-element=\"HeaderGroupCell\"\n data-key={group.key}\n data-pin={pin}\n data-pin-edge={\n segment.some((column) => column.isPinEdge) ? '' : undefined\n }\n data-last-column={last.index === columnCount - 1 ? '' : undefined}\n data-align=\"center\"\n role=\"columnheader\"\n scope=\"colgroup\"\n tabIndex={-1}\n aria-colindex={first.ariaColIndex}\n colSpan={segment.length}\n style={\n pinOffset == null\n ? undefined\n : { ['--pin-offset' as any]: `${pinOffset}px` }\n }\n >\n <TableHeaderItem>{group.title}</TableHeaderItem>\n </th>\n );\n }\n\n function renderHeaderRowCells(depth: number) {\n const cells: ReactNode[] = [];\n\n for (let columnIndex = 0; columnIndex < columns.length; ) {\n const column = columns[columnIndex];\n const path = columnHeaderPaths?.get(column.key) ?? [];\n\n // This column's leaf header began on an earlier row and spans this one.\n if (path.length < depth) {\n columnIndex++;\n continue;\n }\n\n if (path.length === depth) {\n cells.push(renderHeaderCell(column, headerRowCount - depth));\n columnIndex++;\n continue;\n }\n\n let segmentEnd = columnIndex + 1;\n\n while (segmentEnd < columns.length) {\n const nextPath = columnHeaderPaths?.get(columns[segmentEnd].key) ?? [];\n\n if (\n nextPath.length <= depth ||\n columns[segmentEnd].pin !== column.pin ||\n !pathsSharePrefix(path, nextPath, depth)\n ) {\n break;\n }\n\n segmentEnd++;\n }\n\n cells.push(\n renderHeaderGroupCell(\n path[depth],\n columns.slice(columnIndex, segmentEnd),\n depth,\n ),\n );\n columnIndex = segmentEnd;\n }\n\n return cells;\n }\n\n const headerRows = isHeaderHidden\n ? null\n : Array.from({ length: headerRowCount }, (_, depth) => {\n const isLeafRow = depth === headerRowCount - 1;\n\n return (\n <tr\n key={depth}\n data-element=\"HeadRow\"\n role=\"row\"\n aria-rowindex={depth + 1}\n ref={isLeafRow ? headRowRef : undefined}\n {...(isLeafRow ? headCollectionProps : undefined)}\n onKeyDownCapture={\n isLeafRow\n ? (event) => {\n // `DraggableCollection`'s Alt+Arrow reorder sits on this\n // row and fires in capture, so it would beat the resize\n // handle's own Alt+Arrow bubble handler.\n if (\n (event.target as HTMLElement)?.closest?.(\n '[data-element=\"Resizer\"]',\n )\n ) {\n return;\n }\n\n (headCollectionProps as any)?.onKeyDownCapture?.(event);\n }\n : undefined\n }\n >\n {renderHeaderRowCells(depth)}\n </tr>\n );\n });\n\n const tableProps = {\n 'data-element': 'Table',\n role: tree ? 'treegrid' : 'grid',\n 'aria-label': ariaLabel,\n 'aria-busy': isLoading || undefined,\n 'aria-rowcount':\n headerRowCount + pinnedTopCount + bodyRowCount + pinnedBottomCount,\n 'aria-colcount': columnCount,\n 'aria-multiselectable':\n selection?.selectionMode === 'multiple' ? true : undefined,\n } as const;\n\n let bodyContent: ReactNode;\n\n if (error != null) {\n bodyContent = renderStateRow(error);\n } else if (showSkeleton) {\n bodyContent = renderSkeletonRows();\n } else if (showBlank) {\n bodyContent = null;\n } else if (!hasRows) {\n bodyContent = renderStateRow(isFiltered ? noResultsLabel : emptyLabel);\n } else if (shouldVirtualize) {\n bodyContent = (\n <>\n {renderSpacerRow(paddingTop, 'top')}\n {virtualItems.map((v) =>\n withDropIndicators(rows[v.index], v.index, true),\n )}\n {renderSpacerRow(paddingBottom, 'bottom')}\n </>\n );\n } else {\n bodyContent = rows.map((row, index) => withDropIndicators(row, index));\n }\n\n const tableContent = (\n <>\n {colGroup}\n {isHeaderHidden ? null : <thead data-element=\"Head\">{headerRows}</thead>}\n <tbody data-element=\"Body\" {...collectionProps} ref={handleBodyRef}>\n {pinnedTopRows?.map((row, index) => renderPinnedRow(row, index, 'top'))}\n {bodyContent}\n {pinnedBottomRows?.map((row, index) =>\n renderPinnedRow(row, index, 'bottom'),\n )}\n {isLoadingMore\n ? renderSkeletonRows(loadMoreSkeletonCount, 'load-more')\n : null}\n {onLoadMore && hasRows ? (\n <tr data-sentinel=\"\" aria-hidden=\"true\">\n <td\n colSpan={Math.max(columnCount, 1)}\n style={{ height: 1, padding: 0, border: 0 }}\n >\n <div ref={sentinelRef} style={{ height: 1 }} />\n </td>\n </tr>\n ) : null}\n </tbody>\n </>\n );\n\n // Before the first measure there are no columns to lay out yet — show the\n // generic table skeleton rather than an empty frame.\n //\n // Returned HERE, below every hook, not at the point in the render where the\n // condition is known. Returning early skipped sixteen hooks — the virtualizer,\n // the scrollability observer, the move animation, the context menu, two\n // `useState`s — so the first render with columns called more hooks than the\n // last one without them, and React threw \"Rendered more hooks than during the\n // previous render\". A consumer that mounts with `columns={[]}` while loading\n // and fills them in from a response is the ordinary case, not an exotic one.\n if (columnCount === 0 && isLoading) {\n return (\n <TableElement\n ref={rootRef}\n qa={qa || 'Table'}\n styles={mergedStyles}\n mods={{ size, shape, ...mods }}\n >\n {toolbar}\n <div data-element=\"Scroller\" ref={handleScrollerRef}>\n <Skeleton layout=\"table\" />\n </div>\n </TableElement>\n );\n }\n\n return (\n <TableElement\n ref={rootRef}\n qa={qa || 'Table'}\n styles={mergedStyles}\n mods={{\n size,\n shape,\n 'sticky-header': isHeaderSticky,\n 'column-dividers': hasColumnDividers,\n 'range-dragging': isRangeDragging,\n // The footer's top border is the closing edge, so the last row must not\n // draw one as well.\n 'has-footer': footer != null,\n 'scroll-x': scrollability.x,\n 'scroll-y': scrollability.y,\n stale: isStale,\n ...mods,\n }}\n >\n {toolbar}\n <div\n data-element=\"Scroller\"\n ref={handleScrollerRef}\n // Focusable only programmatically: a cell press moves focus here so the\n // range's shortcuts land, but the grid stays a single tab stop.\n tabIndex={cellSelection?.isEnabled ? -1 : undefined}\n // Escape is the standard way out of a selection, and it must work from\n // wherever focus happens to be inside the table.\n onKeyDown={(event) => {\n // Shift+F10 is the standard way to reach a context menu from the\n // keyboard, and the only way when there is no `⋮` trigger.\n if (event.key === 'F10' && event.shiftKey && isMenuEnabled) {\n const found = rowFromEvent(event.target);\n\n if (found) {\n event.stopPropagation();\n openContextMenuFor(found.row, found.index, found.key, event);\n }\n\n return;\n }\n\n if (event.key === 'Enter' && onRowAction) {\n const found = rowFromEvent(event.target);\n\n // Enter on a control inside the cell belongs to that control.\n if (\n found &&\n !(event.target as HTMLElement).closest(\n 'a, button, input, select, textarea, [role=\"button\"]',\n )\n ) {\n onRowAction(found.row, found.key);\n }\n\n return;\n }\n\n if (\n !tree &&\n isReorderable &&\n (event.key === 'ArrowDown' || event.key === 'ArrowUp')\n ) {\n // Not while a drag is in flight — the arrows then belong to React\n // Aria, which uses them to choose the drop position.\n if (dragState?.draggingKeys?.size) return;\n\n if (\n moveRowFocus(\n event.target as HTMLElement,\n event.key === 'ArrowDown' ? 1 : -1,\n )\n ) {\n event.preventDefault();\n }\n\n return;\n }\n\n if (event.key === 'Escape') {\n if (cellSelection?.range) {\n event.stopPropagation();\n cellSelection.clear();\n\n return;\n }\n\n if (selection?.isEnabled && selection.selectedCount > 0) {\n event.stopPropagation();\n selection.clearSelection();\n }\n }\n }}\n // `onCopy` rather than a ⌘/Ctrl+C keydown: it is the event the browser\n // already fires for the shortcut AND for Edit ▸ Copy, and writing\n // through `clipboardData` needs no permission prompt. Both `text/plain`\n // and `text/html` go on, so Excel and Sheets paste a grid rather than\n // one run of text.\n onCopy={(event) => {\n if (!cellSelection?.range) return;\n\n const matrix = cellSelection.getSelectionMatrix(\n (column, row, rowIndex) =>\n column.isStructural\n ? ''\n : getColumnText(column, row, rowIndex) ?? '',\n );\n\n if (!matrix.length) return;\n\n // Both formats from the same matrix. Building the HTML by re-parsing\n // the TSV tore any cell whose value contained a tab or a newline —\n // exactly the values the TSV had to quote in the first place.\n event.preventDefault();\n event.clipboardData.setData('text/plain', toTsv(matrix));\n event.clipboardData.setData('text/html', toClipboardHtml(matrix));\n\n // A copy that writes to the clipboard leaves nothing on screen to say\n // it worked — the range looks the same before and after. The count is\n // what confirms the right block went, which matters most when the\n // selection runs past the bottom of the viewport.\n toast.success({\n title: t('itemTable.copiedToClipboard', 'Copied to clipboard'),\n description: t('itemTable.copiedCells', '{{count}} cells copied', {\n count: cellSelection.cellCount,\n }),\n });\n }}\n >\n {tree ? (\n <TreeGridTable\n tree={tree}\n tableProps={tableProps}\n style={\n layout.totalWidth != null\n ? { width: layout.totalWidth }\n : undefined\n }\n >\n {tableContent}\n </TreeGridTable>\n ) : (\n <table\n {...tableProps}\n style={\n layout.totalWidth != null\n ? { width: layout.totalWidth }\n : undefined\n }\n >\n {tableContent}\n </table>\n )}\n </div>\n {/*\n A refresh is shown by sweeping the table itself, not by parking a\n spinner over it — the rows stay readable, which is the whole point of\n keeping the previous result on screen. This is what announces it.\n\n Always mounted, with the TEXT appearing and disappearing: a live region\n announces changes to its CONTENT, so an empty node that merely carries\n an `aria-label` says nothing, and one that is inserted already-populated\n is unreliable across screen readers. The region has to be there first\n and then fill.\n */}\n <VisuallyHidden>\n <span role=\"status\">\n {isStale ? t('itemTable.refreshing', 'Refreshing') : ''}\n </span>\n </VisuallyHidden>\n {overlay}\n {contextMenu.rendered}\n {tints.configs.map((config, index) => (\n // Keyed positionally on purpose: `configs` is deduped and stable for a\n // given set of column colours, and the theme name is not on the config.\n // Remounting one of these is harmless anyway — the tokens it registers\n // live in a permanent global slot.\n <ColumnTintRegistrar key={index} config={config} />\n ))}\n {footer}\n </TableElement>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"TableView.js","names":["mergeProps","Checkbox","MenuTrigger","Menu"],"sources":["../../../../src/components/data/TableBase/TableView.tsx"],"sourcesContent":["import { useVirtualizer } from '@tanstack/react-virtual';\nimport {\n Fragment,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { useTree, useTreeItem, VisuallyHidden } from 'react-aria';\n\nimport { useEvent } from '../../../_internal/hooks';\nimport { useI18n } from '../../../i18n';\nimport { ArrowNarrowDownIcon } from '../../../icons/ArrowNarrowDownIcon';\nimport { ArrowNarrowUpIcon } from '../../../icons/ArrowNarrowUpIcon';\nimport { DirectionIcon } from '../../../icons/DirectionIcon';\nimport { MoreIcon } from '../../../icons/MoreIcon';\nimport { getColorTheme, useColorTheme } from '../../../tokens/color-theme';\nimport { usePaletteVersion } from '../../../tokens/palette-config';\nimport { SIZE_NAME_TO_KEY, SIZES } from '../../../tokens/sizes';\nimport { mergeProps } from '../../../utils/react';\nimport { Action } from '../../actions/Action/Action';\nimport { ItemAction } from '../../actions/ItemAction/ItemAction';\nimport { Menu, MenuTrigger } from '../../actions/Menu';\nimport { useContextMenu } from '../../actions/use-context-menu';\nimport { Placeholder } from '../../content/Placeholder/Placeholder';\nimport { Skeleton } from '../../content/Skeleton/Skeleton';\nimport { TextItem } from '../../content/TextItem';\nimport { Checkbox } from '../../fields/Checkbox';\nimport { useToast } from '../../overlays/Toast';\nimport { TooltipProvider } from '../../overlays/Tooltip/TooltipProvider';\n\nimport {\n COLUMN_MENU_SORT_DIRECTION,\n isColumnMenuSortKey,\n processColumnMenuItems,\n} from './column-menu';\nimport { buildColumnTints, tintSlot } from './column-tint';\nimport { ColumnResizer } from './ColumnResizer';\nimport {\n isMenuEmpty,\n normalizeMenuAction,\n ROW_MENU_COLUMN_KEY,\n} from './row-menu';\nimport {\n TableElement,\n TableHeaderItem,\n TableTreeToggle,\n TableTreeTogglePlaceholder,\n} from './styled';\nimport { TableHeaderCell } from './TableHeaderCell';\nimport { TableRow, TableRowDropIndicator } from './TableRow';\nimport { selectionRowKey } from './types';\nimport { toTsv } from './use-cell-selection';\nimport { getDraggableColumnKeys, isColumnDraggable } from './use-column-order';\nimport { useRowMoveAnimation } from './use-row-move-animation';\nimport { useScrollability } from './use-scrollability';\nimport { getColumnText, getColumnValue } from './use-table-columns';\nimport {\n ROW_NUMBER_COLUMN_KEY,\n SELECTION_COLUMN_KEY,\n} from './use-table-selection';\n\nimport type { Key, Node } from '@react-types/shared';\nimport type { Styles } from '@tenphi/tasty';\nimport type {\n CSSProperties,\n FocusEvent as ReactFocusEvent,\n KeyboardEvent as ReactKeyboardEvent,\n MouseEvent as ReactMouseEvent,\n ReactNode,\n PointerEvent as ReactPointerEvent,\n RefObject,\n} from 'react';\nimport type { TreeState } from 'react-stately';\nimport type { NavigateArg } from '../../../providers/navigation.types';\nimport type { ColorThemeConfig } from '../../../tokens/color-theme';\nimport type { CubeColumnMenuContext } from './column-menu';\nimport type { TableTreeNode } from './table-tree';\nimport type {\n CubeResolvedColumn,\n CubeTableCellContext,\n CubeTableColumnGroupHeader,\n CubeTableColumnLayout,\n CubeTableHeaderContext,\n CubeTableLayoutProps,\n CubeTableLoadingIndicator,\n CubeTableRowContext,\n CubeTableRowSection,\n CubeTableRowSize,\n CubeTableSort,\n CubeTableSortDirection,\n} from './types';\nimport type { useCellSelection } from './use-cell-selection';\nimport type { CubeTableSelectionState } from './use-table-selection';\n\n/** Visual/behavioural overrides a table adapter may attach to a single row. */\nexport interface CubeTableRowRenderProps {\n isDimmed?: boolean;\n mods?: Record<string, boolean | undefined>;\n styles?: Styles;\n height?: number;\n qa?: string;\n tooltip?: string;\n}\n\nexport interface TableViewProps<T = any> extends CubeTableLayoutProps {\n qa?: string;\n rows: readonly T[];\n /** Stable keys for `rows`; required when a tree was flattened for display. */\n rowKeys?: readonly Key[];\n getRowKey: (row: T, index: number) => Key;\n layout: CubeTableColumnLayout<T>;\n /** Group path for each leaf column, from the outermost header inward. */\n columnHeaderPaths?: ReadonlyMap<\n string,\n readonly CubeTableColumnGroupHeader[]\n >;\n /**\n * Receives the scroll container once it exists. A callback rather than a ref\n * because the virtualized path does not create the element itself — Virtuoso\n * does, and hands it over after mount.\n */\n onScrollerRef: (element: HTMLDivElement | null) => void;\n /** Attached to the table's root frame. */\n rootRef?: RefObject<HTMLDivElement | null>;\n\n size?: 'xsmall' | 'small' | 'medium' | 'large' | 'xlarge';\n shape?: 'plain' | 'card';\n /**\n * Row height as a named step — 28px / 32px / 40px.\n *\n * Only the rows: the header keeps whatever `size` gives it. Unset, the height\n * falls through to `size` as before. `rowHeight` wins over both, being the\n * most specific answer.\n */\n rowSize?: CubeTableRowSize;\n rowHeight?: number;\n headerHeight?: number;\n isHeaderHidden?: boolean;\n isStriped?: boolean;\n /**\n * Vertical rules between columns.\n *\n * A list reads across a row and wants nothing in the way; a grid is read down\n * a column, and the rule is what tells you which column a figure is in when\n * the header has scrolled far to the left. So `ItemTable` leaves it off and\n * `DataTable` turns it on — the same split ag-grid's `columnBorder` gives the\n * Cloud grids today.\n */\n hasColumnDividers?: boolean;\n /**\n * Slide rows to their new positions when the order changes, instead of\n * teleporting them.\n *\n * On by default, and only ever on a pure reorder — see\n * `use-row-move-animation`. Suppressed under `prefers-reduced-motion`.\n */\n isRowMoveAnimated?: boolean;\n /** @default true */\n isHeaderSticky?: boolean;\n /** @default 'auto' — on above `virtualizeThreshold` rows, needs a bounded height. */\n isVirtualized?: boolean | 'auto';\n /** @default 50 */\n virtualizeThreshold?: number;\n /** Rows rendered beyond each edge of the viewport. @default 20 */\n overscan?: number;\n\n /* status */\n isLoading?: boolean;\n loadingIndicator?: CubeTableLoadingIndicator;\n skeletonRowCount?: number;\n selection?: CubeTableSelectionState<T>;\n selectionTooltip?: string | ((row: T) => string | undefined);\n /** Rendered in the root frame, over the body. For the floating bulk bar. */\n overlay?: ReactNode;\n /** Already normalised by the adapter into a per-row resolver. */\n rowMenu?: (row: T, ctx: CubeTableRowContext<T>) => ReactNode | null;\n rowContextMenu?: boolean | 'context-only';\n onRowMenuAction?: (action: string, row: T, key: Key) => void;\n rowMenuTriggerProps?: Record<string, any>;\n rowLink?: (row: T, index: number) => NavigateArg | undefined;\n onRowAction?: (row: T, key: Key) => void;\n /** Infinite scroll: fires once the end of the list comes into view. */\n onLoadMore?: () => void;\n hasMore?: boolean;\n isLoadingMore?: boolean;\n /**\n * How far before the end to start fetching, in px.\n *\n * Defaults to one viewport height, so the next batch is requested a whole\n * screen before the user could reach the bottom. A fixed 200px — about five\n * rows — meant a fast scroll arrived at the end before the request did, which\n * is the stall this is meant to avoid.\n */\n loadMoreMargin?: number;\n /**\n * Rows pinned above and below the scrolling ones — totals, subtotals.\n *\n * Rendered inside `<tbody>` rather than `<thead>`/`<tfoot>` so they keep the\n * body's own row and cell styling; the sub-element chains are anchored to\n * `Body`. Stickiness comes from the row itself.\n */\n pinnedTopRows?: readonly T[];\n pinnedBottomRows?: readonly T[];\n /**\n * Rectangular cell selection, from `use-cell-selection`.\n *\n * `DataTable` only. A list is acted on by row; a result grid is read by cell,\n * and the block of figures is the thing the user wants out of it.\n */\n cellSelection?: ReturnType<typeof useCellSelection<T>> | null;\n /** 1-based number of the first row, so paging keeps the count continuous. */\n rowNumberOffset?: number;\n /**\n * Rows of the full result that precede this page, and the size of that full\n * result.\n *\n * ARIA row indices are document-absolute by contract: `aria-rowindex` is a\n * row's position in the WHOLE grid and `aria-rowcount` the whole grid's size,\n * so a paged grid has to say \"row 21 of 240\" rather than restarting at 1 and\n * claiming a count of 25. Without them a screen reader hears colliding\n * indices against a larger count, which is worse than saying nothing.\n *\n * Defaults keep an unpaged table correct: no offset, and a count taken from\n * the rows actually given.\n */\n rowIndexOffset?: number;\n totalRowCount?: number;\n /** React Aria treegrid state and the model entries matching `rows`. */\n tree?: {\n state: TreeState<TableTreeNode<T>>;\n ariaProps: Record<string, any>;\n nodes: Node<TableTreeNode<T>>[];\n entries: TableTreeNode<T>[];\n columnKey: string;\n };\n isReorderable?: boolean;\n /** Provided by `DraggableCollection` when reordering is on. */\n dragState?: any;\n dropState?: any;\n /* column reordering — named apart from the ROW drag props above, so a table\n * can eventually run both at once. */\n isColumnReorderable?: boolean;\n columnDragState?: any;\n columnDropState?: any;\n /**\n * Drop handling for the header. Must land on the element that directly\n * contains the header cells — the `<tr>` — or drops are never received.\n */\n headCollectionProps?: Record<string, any>;\n headRowRef?: RefObject<HTMLTableRowElement | null>;\n /** Keeps React Aria's `focusedKey` current, which Alt+Arrow reorder reads. */\n onColumnFocus?: (columnKey: string | null) => void;\n /**\n * Drop handling from `useDroppableCollection`. Must land on the element that\n * directly contains the rows — the `<tbody>` — or drops are never received.\n */\n collectionProps?: Record<string, any>;\n bodyRef?: RefObject<HTMLTableSectionElement | null>;\n isResizable?: boolean;\n onColumnResize?: (columnKey: string, width: number) => void;\n onColumnResizeEnd?: (columnKey: string) => void;\n emptyLabel?: ReactNode;\n noResultsLabel?: ReactNode;\n error?: ReactNode;\n /** Selects `noResultsLabel` over `emptyLabel` when there is nothing to show. */\n isFiltered?: boolean;\n\n /* sorting */\n /** @default 'off' */\n sortMode?: 'client' | 'server' | 'off';\n sort?: CubeTableSort | null;\n /**\n * Multi-column sort. Takes precedence over `sort` when given, and the array\n * order is the precedence — `DataTable` uses it, `ItemTable` uses `sort`.\n */\n sorts?: CubeTableSort[];\n onColumnSort?: (columnKey: string) => void;\n /**\n * Set a column's direction outright, for the column menu's reserved sort keys.\n *\n * Separate from `onColumnSort`, which is a cycle: reaching `desc` by toggling\n * twice never terminates under `disallowSortRemoval` and disturbs the\n * precedence of every other sorted column.\n */\n onColumnSortChange?: (\n columnKey: string,\n direction: CubeTableSortDirection | null,\n ) => void;\n\n /* column menu */\n /**\n * Where a column's `header.menu` is exposed.\n *\n * - `true` — a `⋮` trigger, plus right-click and Shift+F10.\n * - `'context-only'` — right-click and Shift+F10, no trigger.\n * - `false` — suppressed entirely.\n *\n * Defaults to `true`, unlike `rowContextMenu`: for rows the flag also decides\n * whether there is a menu at all, whereas here `header.menu` is that gate and\n * this only picks the surfaces.\n *\n * @default true\n */\n columnContextMenu?: boolean | 'context-only';\n onColumnMenuAction?: (action: string, columnKey: string) => void;\n columnMenuTriggerProps?: Record<string, any>;\n columnMenuProps?: Record<string, any>;\n\n /* per-row hooks */\n getRowProps?: (\n ctx: CubeTableRowContext<T>,\n ) => CubeTableRowRenderProps | undefined;\n\n /**\n * Typography preset for the column header. A per-adapter default rather than\n * a table-wide constant: `ItemTable` uses the uppercase caption look (`c2`),\n * while an analytics grid wants its headers to read at body size.\n * `headerCellStyles` still wins over it.\n */\n headerPreset?: string;\n /**\n * Typography for the body. `ItemTable` reads as a list at `t3`; a result grid\n * packs more in and wants `t4`.\n */\n contentPreset?: string;\n\n /** Chrome rendered above the table, in the frame's first grid row. */\n toolbar?: ReactNode;\n /** Chrome rendered below the table, in the frame's last grid row. */\n footer?: ReactNode;\n\n ariaLabel?: string;\n styles?: Styles;\n headerStyles?: Styles;\n headerCellStyles?: Styles;\n bodyStyles?: Styles;\n rowStyles?: Styles;\n cellStyles?: Styles;\n mods?: Record<string, boolean | undefined>;\n}\n\n/**\n * The same block as an HTML table, so a spreadsheet keeps the cell boundaries.\n *\n * Pasting `text/plain` TSV works, but Excel and Sheets then re-guess the types\n * of every field; the HTML flavour is what makes a value that looks like a date\n * stay the text it was on screen.\n */\nfunction toClipboardHtml(matrix: string[][]) {\n const rows = matrix\n .map(\n (row) =>\n `<tr>${row.map((cell) => `<td>${escapeHtml(cell)}</td>`).join('')}</tr>`,\n )\n .join('');\n\n return `<table>${rows}</table>`;\n}\n\nfunction escapeHtml(value: string) {\n return value\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>');\n}\n\nconst ARIA_SORT = { asc: 'ascending', desc: 'descending' } as const;\n\n/**\n * Registers one column tint's tokens.\n *\n * A component per theme rather than a loop of `useColorTheme` calls: the number\n * of tinted columns is data-dependent, and hooks cannot be called in a loop. Each\n * of these has a fixed hook count, and mounting a different NUMBER of them is\n * fine. Keyed on the theme name, so remounting only happens when the set of\n * colours actually changes.\n *\n * Renders nothing — `useColorTheme` injects into a global slot keyed by the\n * theme's own hash, so two tables sharing a colour share one injection and\n * neither can evict the other's.\n */\nfunction ColumnTintRegistrar({ config }: { config: ColorThemeConfig }) {\n useColorTheme(config);\n\n return null;\n}\n\n/**\n * Content height per size step, mirroring `$row-height` in `styled.ts`. Only the\n * initial estimate — every rendered row is measured, so a wrong guess costs a\n * scrollbar adjustment, not a layout bug. The `+ 1` is the row separator.\n */\n/** Enough to read as \"more is coming\" without pretending to know how much. */\n/**\n * Ceiling on the load-more placeholder burst.\n *\n * These rows are not virtualized — they sit after the window, at the end of the\n * body — so the count is real DOM. 50 rows is already taller than any viewport,\n * which is all the burst has to be.\n */\nconst MAX_LOAD_MORE_SKELETON_ROWS = 50;\n\n/**\n * Floor on the prefetch distance, for a table too short to measure usefully —\n * an unbounded one reports a viewport of nearly zero before it has any rows.\n */\nconst MIN_LOAD_MORE_MARGIN = 200;\n\nconst ESTIMATED_ROW_HEIGHT = {\n xsmall: 28,\n small: 32,\n medium: 40,\n large: 48,\n xlarge: 56,\n} as const;\n\nfunction pinStyle(column: CubeResolvedColumn): CSSProperties | undefined {\n if (column.pinOffset == null) return undefined;\n\n return { ['--pin-offset' as any]: `${column.pinOffset}px` };\n}\n\n/**\n * Hook boundary for the native table. Flat tables deliberately avoid this\n * component so their DOM and keyboard behaviour remain exactly as before.\n */\nfunction TreeGridTable<T>(props: {\n tree: NonNullable<TableViewProps<T>['tree']>;\n tableProps: Record<string, any>;\n style?: CSSProperties;\n children: ReactNode;\n}) {\n const { tree, tableProps, style, children } = props;\n const ref = useRef<HTMLTableElement>(null);\n const pendingFocusKey = useRef<Key | null>(null);\n const { gridProps } = useTree(tree.ariaProps as any, tree.state, ref);\n\n // A virtualized destination may not exist until the focused key makes the\n // parent virtualizer scroll and render another window. Retry after each\n // render until that row mounts, then complete the keyboard focus move.\n useEffect(() => {\n const key = pendingFocusKey.current;\n if (key == null) return;\n\n // A real focus move wins over the delayed virtual-row focus. Losing the\n // old row to virtualization leaves focus on <body>, whereas tabbing or\n // clicking elsewhere leaves a concrete active element we must respect.\n const activeElement = document.activeElement;\n if (\n activeElement &&\n activeElement !== document.body &&\n !ref.current?.contains(activeElement)\n ) {\n pendingFocusKey.current = null;\n return;\n }\n\n const target = Array.from(\n ref.current?.querySelectorAll<HTMLTableRowElement>(\n 'tbody tr[data-element=\"Row\"][data-key]',\n ) ?? [],\n ).find((element) => element.dataset.key === String(key));\n\n if (target) {\n pendingFocusKey.current = null;\n target.focus();\n }\n });\n\n const handleBlurCapture = (event: ReactFocusEvent<HTMLTableElement>) => {\n const pendingKey = pendingFocusKey.current;\n const nextTarget = event.relatedTarget;\n\n if (pendingKey != null && nextTarget instanceof Element) {\n const nextRow = nextTarget.closest<HTMLTableRowElement>(\n 'tbody tr[data-element=\"Row\"][data-key]',\n );\n\n if (nextRow?.dataset.key !== String(pendingKey)) {\n pendingFocusKey.current = null;\n }\n }\n\n (gridProps as any).onBlurCapture?.(event);\n };\n\n const handleKeyDownCapture = (\n event: ReactKeyboardEvent<HTMLTableElement>,\n ) => {\n const row = (event.target as HTMLElement).closest<HTMLTableRowElement>(\n 'tbody tr[data-element=\"Row\"][data-key]',\n );\n\n // Inputs, links and menus embedded in a row retain their own shortcuts.\n if (!row || event.target !== row) {\n (gridProps as any).onKeyDownCapture?.(event);\n return;\n }\n\n // While a virtual destination is still mounting, subsequent key presses\n // continue from that logical key rather than repeatedly targeting the old\n // DOM row that still owns focus.\n const currentKey = pendingFocusKey.current ?? row.dataset.key;\n const index = tree.entries.findIndex(\n (entry) => String(entry.key) === String(currentKey),\n );\n const entry = tree.entries[index];\n if (!entry) return;\n\n const focusEntry = (next: TableTreeNode<T> | undefined) => {\n if (!next) return false;\n tree.state.selectionManager.setFocusedKey(next.key);\n const target = Array.from(\n ref.current?.querySelectorAll<HTMLTableRowElement>(\n 'tbody tr[data-element=\"Row\"][data-key]',\n ) ?? [],\n ).find((element) => element.dataset.key === String(next.key));\n if (target) {\n pendingFocusKey.current = null;\n target.focus();\n } else pendingFocusKey.current = next.key;\n return true;\n };\n\n const hasChildren = entry.children.length > 0;\n const isExpanded = tree.state.expandedKeys.has(entry.key);\n let handled = false;\n\n if (event.key === 'ArrowRight' && hasChildren) {\n if (isExpanded) handled = focusEntry(entry.children[0]);\n else {\n tree.state.toggleKey(entry.key);\n handled = true;\n }\n } else if (event.key === 'ArrowLeft') {\n if (hasChildren && isExpanded) {\n tree.state.toggleKey(entry.key);\n handled = true;\n } else if (entry.parentKey != null) {\n handled = focusEntry(\n tree.entries.find((candidate) => candidate.key === entry.parentKey),\n );\n }\n } else if (event.key === 'ArrowDown') {\n handled = focusEntry(tree.entries[index + 1]);\n } else if (event.key === 'ArrowUp') {\n handled = focusEntry(tree.entries[index - 1]);\n }\n\n if (handled) {\n event.preventDefault();\n event.stopPropagation();\n return;\n }\n\n // React Aria still sees the DOM row that owned focus before the virtual\n // destination mounted. If a logical navigation key has no action there\n // (a boundary, leaf, or collapsed root), consuming it avoids falling\n // through and applying that key to the stale row instead.\n if (\n pendingFocusKey.current != null &&\n ['ArrowDown', 'ArrowUp', 'ArrowRight', 'ArrowLeft'].includes(event.key)\n ) {\n event.preventDefault();\n event.stopPropagation();\n return;\n }\n\n (gridProps as any).onKeyDownCapture?.(event);\n };\n\n return (\n <table\n {...mergeProps(gridProps, tableProps)}\n ref={ref}\n role=\"treegrid\"\n style={style}\n onBlurCapture={handleBlurCapture}\n onKeyDownCapture={handleKeyDownCapture}\n >\n {children}\n </table>\n );\n}\n\n/**\n * The one place table DOM exists. Both `ItemTable` and `DataTable` resolve their\n * props into the shape above and hand it here, so the markup, the ARIA\n * bookkeeping and the tasty sub-element contract have a single implementation.\n */\nexport function TableView<T = any>(props: TableViewProps<T>) {\n const {\n qa,\n rows,\n rowKeys,\n getRowKey,\n layout,\n columnHeaderPaths,\n onScrollerRef,\n rootRef,\n size = 'medium',\n shape = 'plain',\n rowSize,\n rowHeight,\n headerHeight,\n isHeaderHidden = false,\n isStriped = false,\n hasColumnDividers,\n isRowMoveAnimated = true,\n isHeaderSticky = true,\n isAutoHeight = false,\n isVirtualized = 'auto',\n virtualizeThreshold = 50,\n overscan = 20,\n isLoading = false,\n loadingIndicator = 'overlay',\n skeletonRowCount = 6,\n selection,\n selectionTooltip,\n overlay,\n rowMenu,\n rowContextMenu = false,\n onRowMenuAction,\n rowMenuTriggerProps,\n rowLink,\n onRowAction,\n onLoadMore,\n hasMore = false,\n isLoadingMore = false,\n loadMoreMargin,\n pinnedTopRows,\n pinnedBottomRows,\n cellSelection,\n rowNumberOffset = 0,\n rowIndexOffset = 0,\n totalRowCount,\n tree,\n isReorderable = false,\n dragState,\n dropState,\n collectionProps,\n isColumnReorderable = false,\n columnDragState,\n columnDropState,\n headCollectionProps,\n headRowRef,\n onColumnFocus,\n bodyRef,\n isResizable = false,\n onColumnResize,\n onColumnResizeEnd,\n emptyLabel,\n noResultsLabel,\n error,\n isFiltered = false,\n sortMode = 'off',\n sort,\n sorts,\n onColumnSort,\n onColumnSortChange,\n columnContextMenu = true,\n onColumnMenuAction,\n columnMenuTriggerProps,\n columnMenuProps,\n getRowProps,\n headerPreset,\n contentPreset,\n toolbar,\n footer,\n ariaLabel,\n styles,\n headerStyles,\n headerCellStyles,\n bodyStyles,\n rowStyles,\n cellStyles,\n mods,\n } = props;\n\n const { columns } = layout;\n const columnCount = columns.length;\n const headerGroupDepth = columns.reduce(\n (depth, column) =>\n Math.max(depth, columnHeaderPaths?.get(column.key)?.length ?? 0),\n 0,\n );\n\n /**\n * `rowSize` resolved to the size scale, or `null` when it was not given.\n *\n * Both halves come from `SIZE_NAME_TO_KEY` rather than being written out\n * twice: the CSS keeps the token so it follows the scale, and the virtualizer\n * needs the number, and the two must not drift.\n */\n const rowSizeKey = rowSize ? SIZE_NAME_TO_KEY[rowSize] : null;\n // Only the trailing draggable column carries an `after` indicator; every other\n // gap is covered by the next column's `before` one.\n const lastDraggableKey = isColumnReorderable\n ? getDraggableColumnKeys(columns, true).at(-1) ?? null\n : null;\n\n // The element is held here as well as reported upwards: the virtualizer needs\n // it locally, and the adapter needs it to measure column widths.\n const { t } = useI18n();\n const toast = useToast();\n\n const [scrollerEl, setScrollerEl] = useState<HTMLDivElement | null>(null);\n const scrollerRef = useRef<HTMLDivElement | null>(null);\n /**\n * The column whose menu is open, held for the whole table rather than per\n * header cell.\n *\n * `renderHeaderCell` is a closure inside this component, not a component of\n * its own, so it cannot hold state — and only one column menu can be open at a\n * time anyway. Controlled rather than letting `MenuTrigger` own it: Shift+F10\n * has to be able to open it from the `<th>`, and the trigger is not a tab stop.\n */\n const [openMenuColumnKey, setOpenMenuColumnKey] = useState<string | null>(\n null,\n );\n // `bodyRef` is optional — only the drag-and-drop path supplies one — but the\n // move animation needs the `<tbody>` either way, so it keeps its own and both\n // are filled from one callback.\n const localBodyRef = useRef<HTMLTableSectionElement | null>(null);\n const handleBodyRef = useCallback(\n (element: HTMLTableSectionElement | null) => {\n localBodyRef.current = element;\n if (bodyRef) bodyRef.current = element;\n },\n [bodyRef],\n );\n const handleScrollerRef = useCallback(\n (element: HTMLDivElement | null) => {\n scrollerRef.current = element;\n setScrollerEl(element);\n onScrollerRef(element);\n },\n [onScrollerRef],\n );\n\n // Header rows count towards `aria-rowcount`, which must be document-absolute.\n const headerRowCount = isHeaderHidden ? 0 : headerGroupDepth + 1;\n\n /* ── the ARIA row index space ───────────────────────────────────────────\n * Four bands, in the order a screen reader walks them:\n *\n * 1 the header row\n * 2 … 1+top pinned top rows\n * … the body, offset by the pages before this one\n * after the whole body pinned bottom rows\n *\n * Derived once here rather than at each of the four render sites, which is\n * how the body came to be numbered as though the pinned rows above it did\n * not exist while `aria-rowcount` counted them.\n * ─────────────────────────────────────────────────────────────────────── */\n const pinnedTopCount = pinnedTopRows?.length ?? 0;\n const pinnedBottomCount = pinnedBottomRows?.length ?? 0;\n // The whole result, not this page. `rows.length` is the honest fallback when\n // the adapter does not know a total.\n const bodyRowCount = Math.max(\n totalRowCount ?? rows.length,\n rowIndexOffset + rows.length,\n );\n\n /** 1-based `aria-rowindex` for the i-th body row of the current page. */\n const bodyRowIndex = (rowIndex: number) =>\n headerRowCount + pinnedTopCount + rowIndexOffset + rowIndex + 1;\n const bodyRowKey = (row: T, rowIndex: number) =>\n rowKeys?.[rowIndex] ?? getRowKey(row, rowIndex);\n const treeRowState = (rowIndex: number) => {\n const entry = tree?.entries[rowIndex];\n\n return entry\n ? {\n level: entry.level,\n parentKey: entry.parentKey,\n hasChildren: entry.children.length > 0,\n isExpanded: tree.state.expandedKeys.has(entry.key),\n }\n : undefined;\n };\n /** 1-based `aria-rowindex` for the i-th pinned row at `edge`. */\n const pinnedRowIndex = (index: number, edge: 'top' | 'bottom') =>\n edge === 'top'\n ? headerRowCount + index + 1\n : headerRowCount + pinnedTopCount + bodyRowCount + index + 1;\n\n /**\n * Per-column tints.\n *\n * The colour maths is `getColorTheme`'s, cached globally by a hash of its\n * config; `buildColumnTints` only maps columns onto `data-tint` slots and the\n * state maps that read them. `getColorTheme` rather than `useColorTheme` here\n * because the number of tinted columns is data-dependent and a hook cannot be\n * called in a loop — registration happens in `ColumnTintRegistrar` below, one\n * component per distinct theme, which is a legal fixed hook count each.\n */\n const paletteVersion = usePaletteVersion();\n const tints = useMemo(\n () => buildColumnTints(columns, { resolveTheme: getColorTheme }),\n // eslint-disable-next-line react-hooks/exhaustive-deps -- re-derive on a re-seed\n [columns, paletteVersion],\n );\n\n const mergedStyles = useMemo(\n () => ({\n // A table normally fills its flex pane. `min-height: 0` lets the scroller\n // become smaller than its contents instead of forcing that pane taller.\n height: 'min 0',\n flexGrow: 1,\n flexShrink: 1,\n ...styles,\n // Auto-height is a layout mode rather than a styling suggestion: its\n // rows determine the frame even when a wrapper supplied fixed sizing.\n ...(isAutoHeight\n ? { height: 'min 0', flexGrow: 0, flexShrink: 0 }\n : null),\n ...(contentPreset ? { Table: { preset: contentPreset } } : null),\n ...(headerStyles ? { HeadRow: headerStyles } : null),\n ...(headerPreset || headerCellStyles || tints.headerCellStyles\n ? {\n HeaderCell: {\n ...(headerPreset ? { preset: headerPreset } : null),\n ...tints.headerCellStyles,\n // The consumer's own overrides land last, so a `headerCellStyles`\n // that sets `#cell-base` outright still wins over a tint.\n ...headerCellStyles,\n },\n }\n : null),\n ...(headerPreset || headerCellStyles\n ? {\n HeaderGroupCell: {\n ...(headerPreset ? { preset: headerPreset } : null),\n ...headerCellStyles,\n },\n }\n : null),\n ...(bodyStyles ? { Body: bodyStyles } : null),\n ...(rowStyles ? { Row: rowStyles } : null),\n ...(cellStyles || tints.cellStyles\n ? { Cell: { ...tints.cellStyles, ...cellStyles } }\n : null),\n // `rowHeight` first — an exact px answer beats a named step.\n ...(rowHeight != null\n ? { '$row-height': `${rowHeight}px` }\n : rowSizeKey\n ? { '$row-height': `$size-${rowSizeKey.toLowerCase()}` }\n : null),\n ...(headerHeight != null\n ? { '$header-height': `${headerHeight}px` }\n : null),\n }),\n [\n styles,\n isAutoHeight,\n headerStyles,\n headerCellStyles,\n headerPreset,\n contentPreset,\n bodyStyles,\n rowStyles,\n cellStyles,\n rowSizeKey,\n rowHeight,\n headerHeight,\n tints,\n ],\n );\n\n /**\n * Whether a cell is inside the current range.\n *\n * Pinned rows take part: they sit in the range's row order at the position\n * they occupy on screen, so a selection down a column of figures reaches its\n * total instead of leaving it to be copied separately. (ag-grid excludes\n * pinned rows outright; this is a deliberate departure.)\n */\n function isCellSelected(rowKey: Key, columnKey: string) {\n if (!cellSelection?.isEnabled) return false;\n\n return cellSelection.isSelected(rowKey, columnKey);\n }\n\n /**\n * Press and drag for the range.\n *\n * `pointerdown` rather than `click`: the range has to start before the drag\n * does, and a click only lands after the button comes back up — by which time\n * the gesture is over. `pointerenter` grows it while the button is held, which\n * is the same shape ag-grid's `onCellMouseOver` gives the Cloud grids.\n */\n function cellSelectionProps(\n rowKey: Key,\n columnKey: string,\n pinnedEdge?: 'top' | 'bottom',\n ) {\n // A vetoed cell gets no handlers at all, so it is inert rather than merely\n // unpainted: pressing it neither starts a range nor disturbs the standing\n // one, which is how ag-grid treats a press on its row-number column.\n if (!cellSelection?.canSelectCell(rowKey, columnKey)) return undefined;\n\n return {\n onPointerDown: (event: ReactPointerEvent<HTMLTableCellElement>) => {\n // Right-click keeps whatever is selected, so a context menu can act on\n // the range the user has already built.\n if (event.button !== 0) return;\n\n if (event.shiftKey) {\n // Otherwise the browser paints a text selection from the anchor to\n // here, on top of the cell range.\n event.preventDefault();\n cellSelection.extendTo(rowKey, columnKey);\n } else {\n cellSelection.select(rowKey, columnKey);\n }\n\n // The range's keyboard affordances — Escape to clear, ⌘/Ctrl+C to copy\n // — are handled on the scroller, and a `<td>` takes no focus of its\n // own, so a press would otherwise leave focus on `<body>` and neither\n // would ever fire.\n scrollerRef.current?.focus({ preventScroll: true });\n\n cellSelection.isDraggingRef.current = true;\n setIsRangeDragging(true);\n },\n onPointerEnter: () => {\n if (!cellSelection.isDraggingRef.current) return;\n\n // Reachable by press and by shift-click, but never by dragging THROUGH.\n // A pinned row sits over the scrolling ones, so a downward drag brushes\n // it long before reaching the end of the data — and being last in the\n // row order, that would snap the range to the whole rest of the grid.\n if (pinnedEdge) return;\n\n cellSelection.extendTo(rowKey, columnKey);\n },\n };\n }\n\n /**\n * Marks the trailing column.\n *\n * Two things hang off it. Its resize handle tucks fully inside rather than\n * straddling a boundary that is not there — left hanging it puts half its\n * width past the table, and the scroller gains a few pixels of horizontal\n * scroll onto blank space. And it draws no vertical rule: that rule would\n * land flush against the frame and read as a doubled edge.\n */\n /** The pinned edge a row was rendered at, as the documented section name. */\n function sectionOf(pinnedEdge?: 'top' | 'bottom'): CubeTableRowSection {\n if (pinnedEdge === 'top') return 'pinnedTop';\n if (pinnedEdge === 'bottom') return 'pinnedBottom';\n\n return 'body';\n }\n\n function lastColumnFlag(column: CubeResolvedColumn<T>) {\n return column.index === columns.length - 1 ? '' : undefined;\n }\n\n /**\n * Which frame corner, if any, this cell sits in.\n *\n * Only the two bottom ones, and only when the card's rounded edge is what the\n * row actually meets — a footer below it means the row ends against a straight\n * line instead. Without this a selected cell in that row has its ring sliced\n * off at 45° by the frame's radius, which reads as a rendering fault rather\n * than as a corner.\n *\n * Decided here rather than in CSS: the renderer already knows about the\n * footer, the shape and the pinned rows, and expressing\n * `card × no-footer × visually-last-row × outer-column` as a state map is how\n * a border map turns into a combinatorial one.\n */\n function bottomCornerFlag(\n column: CubeResolvedColumn<T>,\n rowIndex: number,\n isLastRow: boolean,\n pinnedEdge?: 'top' | 'bottom',\n ) {\n if (shape !== 'card' || footer != null) return undefined;\n\n const pinnedBottomCount = pinnedBottomRows?.length ?? 0;\n const isVisualLastRow =\n pinnedEdge === 'bottom'\n ? rowIndex === pinnedBottomCount - 1\n : pinnedEdge == null && isLastRow && pinnedBottomCount === 0;\n\n if (!isVisualLastRow) return undefined;\n if (column.index === 0) return 'start';\n if (column.index === columns.length - 1) return 'end';\n\n return undefined;\n }\n\n /**\n * The row band, mirrored from the `<tr>` onto its cells.\n *\n * `Row` already carries `data-odd` and publishes `#row-base` from it, which is\n * all an untinted cell needs. A TINTED cell has to pick its own band, and a\n * sub-element's state keys resolve against the table root rather than its DOM\n * parent — so the flag has to be on the cell itself. Same reason `data-pinned`\n * is mirrored.\n *\n * Pinned rows are exempt: they carry no `data-odd` on the `<tr>` either, and\n * banding a totals row would be wrong.\n */\n function cellBandFlag(rowIndex: number, pinnedEdge?: 'top' | 'bottom') {\n return pinnedEdge == null && isStriped && rowIndex % 2 === 1\n ? ''\n : undefined;\n }\n\n function renderStateRow(content: ReactNode) {\n return (\n <tr data-element=\"Row\" role=\"row\" aria-rowindex={headerRowCount + 1}>\n <td\n data-element=\"StateCell\"\n data-state=\"\"\n role=\"gridcell\"\n colSpan={Math.max(columnCount, 1)}\n aria-colindex={1}\n >\n <div data-element=\"StateContent\">{content}</div>\n </td>\n </tr>\n );\n }\n\n function renderSkeletonRows(\n count = skeletonRowCount,\n keyPrefix = 'skeleton',\n ) {\n return Array.from({ length: count }, (_, rowIndex) => (\n <tr\n key={`${keyPrefix}-${rowIndex}`}\n data-element=\"Row\"\n data-placeholder=\"\"\n role=\"row\"\n aria-rowindex={bodyRowIndex(rowIndex)}\n aria-busy=\"true\"\n >\n {columns.map((column) => (\n <td\n key={column.key}\n data-element=\"Cell\"\n data-pin={column.pin}\n data-pin-edge={column.isPinEdge ? '' : undefined}\n data-align={column.align}\n role=\"gridcell\"\n aria-colindex={column.ariaColIndex}\n style={pinStyle(column)}\n >\n <Placeholder />\n </td>\n ))}\n </tr>\n ));\n }\n\n function renderSelectionHeaderCell(\n column: CubeResolvedColumn<T>,\n rowSpan = 1,\n ) {\n return (\n <th\n key={column.key}\n data-element=\"HeaderCell\"\n data-key={column.key}\n data-kind=\"selection\"\n data-pin={column.pin}\n data-pin-edge={column.isPinEdge ? '' : undefined}\n data-last-column={lastColumnFlag(column)}\n role=\"columnheader\"\n scope=\"col\"\n rowSpan={rowSpan > 1 ? rowSpan : undefined}\n tabIndex={-1}\n aria-colindex={column.ariaColIndex}\n style={pinStyle(column)}\n >\n {selection && selection.selectionMode === 'multiple' ? (\n <div data-element=\"SelectionBox\">\n <Checkbox\n aria-label={\n selection.selectAllState === 'all'\n ? t('itemTable.deselectAll', 'Deselect all')\n : t('itemTable.selectAll', 'Select all')\n }\n isSelected={selection.selectAllState === 'all'}\n isIndeterminate={selection.selectAllState === 'some'}\n onChange={selection.toggleSelectAll}\n />\n </div>\n ) : null}\n </th>\n );\n }\n\n function renderSelectionCell(\n column: CubeResolvedColumn<T>,\n row: T,\n rowIndex: number,\n rowKey: Key,\n isLastRow: boolean,\n pinnedEdge?: 'top' | 'bottom',\n ) {\n const canSelect = selection!.canSelect(rowKey);\n const tooltip =\n typeof selectionTooltip === 'function'\n ? selectionTooltip(row)\n : selectionTooltip;\n\n const checkbox = (\n <Checkbox\n aria-label={t('itemTable.selectRow', 'Select row')}\n isSelected={selection!.isSelected(rowKey)}\n isIndeterminate={selection!.isIndeterminate(rowKey)}\n isDisabled={!canSelect}\n onChange={() => selection!.toggleRow(rowKey)}\n />\n );\n\n return (\n <td\n key={column.key}\n data-element=\"Cell\"\n data-key={column.key}\n data-kind=\"selection\"\n data-pin={column.pin}\n data-pin-edge={column.isPinEdge ? '' : undefined}\n data-last-row={isLastRow ? '' : undefined}\n data-pinned={pinnedEdge}\n data-odd={cellBandFlag(rowIndex, pinnedEdge)}\n data-last-column={lastColumnFlag(column)}\n data-corner={bottomCornerFlag(column, rowIndex, isLastRow, pinnedEdge)}\n role=\"gridcell\"\n aria-colindex={column.ariaColIndex}\n style={pinStyle(column)}\n // `Checkbox` reports only the next value, so the modifier that decides\n // toggle-vs-extend is read off the event that produced it.\n //\n // `click` rather than `pointerdown`: capture on the cell still runs\n // before the checkbox's own `change` handler, and unlike pointer events\n // it carries the modifier state in every environment — including\n // keyboard activation and jsdom.\n onClickCapture={selection!.captureShift}\n onKeyDownCapture={selection!.captureShift}\n >\n <div data-element=\"SelectionBox\">\n {!canSelect && tooltip ? (\n <TooltipProvider title={tooltip}>{checkbox}</TooltipProvider>\n ) : (\n checkbox\n )}\n </div>\n </td>\n );\n }\n\n function renderRowMenuCell(\n column: CubeResolvedColumn<T>,\n row: T,\n rowIndex: number,\n rowKey: Key,\n isLastRow: boolean,\n pinnedEdge?: 'top' | 'bottom',\n ) {\n const items = resolveRowMenu(row, rowIndex, rowKey);\n\n return (\n <td\n key={column.key}\n data-element=\"Cell\"\n data-key={column.key}\n data-kind=\"actions\"\n data-pin={column.pin}\n data-pin-edge={column.isPinEdge ? '' : undefined}\n data-last-row={isLastRow ? '' : undefined}\n data-pinned={pinnedEdge}\n data-odd={cellBandFlag(rowIndex, pinnedEdge)}\n data-last-column={lastColumnFlag(column)}\n data-corner={bottomCornerFlag(column, rowIndex, isLastRow, pinnedEdge)}\n role=\"gridcell\"\n aria-colindex={column.ariaColIndex}\n style={pinStyle(column)}\n >\n {isMenuEmpty(items) ? null : (\n <div data-element=\"RowActions\">\n <MenuTrigger>\n <ItemAction\n // The grid is one tab stop; in-cell controls are reached with\n // arrow keys, matching `TreeNode`.\n tabIndex={-1}\n icon={<MoreIcon />}\n aria-label={t('itemTable.rowActions', 'Row actions')}\n {...rowMenuTriggerProps}\n />\n <Menu onAction={menuActionHandler(row, rowKey, false)}>\n {items}\n </Menu>\n </MenuTrigger>\n </div>\n )}\n </td>\n );\n }\n\n function renderHeaderCell(column: CubeResolvedColumn<T>, rowSpan = 1) {\n if (column.key === SELECTION_COLUMN_KEY) {\n return renderSelectionHeaderCell(column, rowSpan);\n }\n\n if (column.key === ROW_NUMBER_COLUMN_KEY) {\n // Deliberately unnamed: the numbers are a reading aid, not data, and a\n // column header would invite sorting by them.\n return (\n <th\n key={column.key}\n data-element=\"HeaderCell\"\n data-key={column.key}\n data-kind=\"row-number\"\n data-last-column={lastColumnFlag(column)}\n role=\"columnheader\"\n scope=\"col\"\n rowSpan={rowSpan > 1 ? rowSpan : undefined}\n tabIndex={-1}\n aria-colindex={column.ariaColIndex}\n style={pinStyle(column)}\n />\n );\n }\n\n if (column.key === ROW_MENU_COLUMN_KEY) {\n // An empty header keeps the column in the ARIA geometry without\n // announcing a name for a column that holds no data.\n return (\n <th\n key={column.key}\n data-element=\"HeaderCell\"\n data-key={column.key}\n data-kind=\"actions\"\n data-pin={column.pin}\n data-pin-edge={column.isPinEdge ? '' : undefined}\n data-last-column={lastColumnFlag(column)}\n role=\"columnheader\"\n scope=\"col\"\n rowSpan={rowSpan > 1 ? rowSpan : undefined}\n tabIndex={-1}\n aria-colindex={column.ariaColIndex}\n style={pinStyle(column)}\n />\n );\n }\n\n const header = column.header;\n // One resolution path for both shapes, so every consumer of `isSorted`\n // below stays unaware of which one the caller supplied.\n const activeSorts = sorts ?? (sort ? [sort] : []);\n const sortIndex = activeSorts.findIndex(\n (entry) => entry.columnKey === column.key,\n );\n const activeSort = sortIndex === -1 ? null : activeSorts[sortIndex];\n const isSorted = activeSort != null;\n // Only worth showing when more than one column is sorted — a lone \"1\"\n // beside an arrow is noise.\n const sortRank = activeSorts.length > 1 ? sortIndex + 1 : null;\n const isSortable =\n sortMode !== 'off' && !column.isStructural && column.isSortable === true;\n\n // A structural column has no content to make room for, and resizing needs\n // somewhere to write the result.\n const canResize =\n !column.isStructural &&\n (column.isResizable ?? isResizable) &&\n onColumnResize != null &&\n onColumnResizeEnd != null;\n\n const ctx: CubeTableHeaderContext = {\n columnKey: column.key,\n columnIndex: column.index,\n sort: activeSort?.direction ?? null,\n isSortable,\n isResizing: false,\n width: column.width,\n };\n\n // The arrow keeps its slot even when unsorted, so turning a sort on and off\n // never shifts the label.\n //\n // Two glyphs rather than one flipped with `scale`. A narrow arrow flipped\n // vertically does land on its own opposite, but rendering the real icon is\n // what keeps that true — a glyph that is not perfectly symmetric would come\n // out subtly wrong, and nothing would say why.\n //\n // Unsorted shows the UP arrow, because that is what the first press gives:\n // the hint predicts the press rather than advertising that one is possible.\n const sortIndicator = isSortable ? (\n <div\n data-element=\"SortIndicator\"\n data-rank={sortRank ?? undefined}\n data-sorted={isSorted ? '' : undefined}\n data-dir={activeSort?.direction}\n aria-hidden=\"true\"\n >\n {activeSort?.direction === 'desc' ? (\n <ArrowNarrowDownIcon />\n ) : (\n <ArrowNarrowUpIcon />\n )}\n </div>\n ) : null;\n\n // The arrow belongs in the `rightIcon` slot: that slot is sized and aligned\n // for an icon, while `suffix` is a text slot and puts the glyph on the\n // label's baseline.\n //\n // A `header.rightIcon` the consumer asked for keeps the slot, and the arrow\n // falls back to `suffix` — rare, and better than dropping either one.\n const hasCustomRightIcon = header?.rightIcon != null;\n const rightIcon = hasCustomRightIcon ? header!.rightIcon : sortIndicator;\n\n const suffixContent = hasCustomRightIcon ? sortIndicator : null;\n const suffix =\n header?.suffix != null || suffixContent ? (\n <>\n {header?.suffix}\n {suffixContent}\n </>\n ) : undefined;\n\n const menuItems = resolveColumnMenu(column);\n const hasMenu = menuItems != null;\n const isContextOnly = columnContextMenu === 'context-only';\n\n const menuAction =\n hasMenu && !isContextOnly ? (\n <MenuTrigger\n isOpen={openMenuColumnKey === column.key}\n // `bottom end`: the trigger sits at the column's trailing edge, so a\n // start-aligned popover hangs off the table on the last column.\n placement=\"bottom end\"\n onOpenChange={(open) =>\n setOpenMenuColumnKey(open ? column.key : null)\n }\n >\n <ItemAction\n // The grid is one tab stop; the trigger is reached from the header\n // cell with Shift+F10, matching the row menu.\n tabIndex={-1}\n icon={<MoreIcon />}\n aria-label={t('itemTable.columnMenu', 'Column menu')}\n {...columnMenuTriggerProps}\n {...header?.menuTriggerProps}\n />\n <Menu\n {...columnMenuProps}\n {...header?.menuProps}\n onAction={columnMenuActionHandler(column, false)}\n >\n {processColumnMenuItems(\n menuItems,\n columnMenuContext(column, isSortable, activeSort),\n )}\n </Menu>\n </MenuTrigger>\n ) : null;\n\n // The consumer's own actions first, the overflow menu last — matching Tabs.\n const actions =\n header?.actions != null || menuAction ? (\n <>\n {header?.actions}\n {menuAction}\n </>\n ) : undefined;\n\n const content = header?.render ? (\n header.render(ctx)\n ) : column.title == null && !header ? null : (\n <TableHeaderItem\n icon={header?.icon}\n rightIcon={rightIcon}\n prefix={header?.prefix}\n suffix={suffix}\n description={header?.description}\n descriptionPlacement={header?.descriptionPlacement}\n tooltip={header?.tooltip ?? true}\n theme={header?.theme}\n actions={actions}\n autoHideActions={header?.autoHideActions ?? true}\n // Without it the actions slot animates its width from 0 on hover, which\n // re-truncates the label — so the header text shifts under the cursor.\n // Only the opacity should move; `TabElement` reserves the space for the\n // same reason.\n preserveActionsSpace={actions != null}\n styles={header?.styles}\n >\n {column.title}\n </TableHeaderItem>\n );\n\n const isDraggable = isColumnDraggable(column, isColumnReorderable);\n\n return (\n <TableHeaderCell\n key={column.key}\n columnKey={column.key}\n // Enter belongs to the sort when there is one, so React Aria re-gates\n // its own Enter capture behind Alt.\n hasAction={isSortable}\n isLastDraggable={isDraggable && column.key === lastDraggableKey}\n dragState={isDraggable ? columnDragState : undefined}\n dropState={isDraggable ? columnDropState : undefined}\n cellProps={{\n 'data-element': 'HeaderCell',\n 'data-key': column.key,\n 'data-pin': column.pin,\n 'data-pin-edge': column.isPinEdge ? '' : undefined,\n 'data-align': header?.align ?? column.align,\n 'data-sortable': isSortable ? '' : undefined,\n 'data-resizable': canResize ? '' : undefined,\n 'data-last-column': lastColumnFlag(column),\n 'data-sorted': isSorted ? '' : undefined,\n 'data-menu-open': openMenuColumnKey === column.key ? '' : undefined,\n 'data-tint': tintSlot(tints, column.key, 'header'),\n role: 'columnheader',\n scope: 'col',\n rowSpan: rowSpan > 1 ? rowSpan : undefined,\n // A sortable header is a control, so it takes a tab stop — and so does\n // one carrying a menu (Shift+F10 needs somewhere to land) or one that\n // can be moved with Alt+Arrow. Row/cell keyboard navigation lands in a\n // follow-up and will move this to the grid's roving-tabindex model.\n tabIndex: isSortable || hasMenu || isDraggable ? 0 : -1,\n 'aria-colindex': column.ariaColIndex,\n 'aria-sort': activeSort ? ARIA_SORT[activeSort.direction] : undefined,\n 'aria-haspopup': hasMenu ? 'menu' : undefined,\n style: pinStyle(column),\n // React Aria's Alt+Arrow reorder reads `focusedKey`, and nothing else\n // sets it — `useDroppableCollection` only ever reads it.\n onFocus: isColumnReorderable\n ? () => onColumnFocus?.(isDraggable ? column.key : null)\n : undefined,\n onClick: isSortable ? () => onColumnSort?.(column.key) : undefined,\n // Both `true` and `'context-only'` answer to a right-click, and\n // `false` already made `hasMenu` false in `resolveColumnMenu`.\n onContextMenu: hasMenu\n ? (event: ReactMouseEvent) =>\n openColumnContextMenu(column, isSortable, activeSort, event)\n : undefined,\n onKeyDown:\n isSortable || hasMenu\n ? (event: ReactKeyboardEvent) => {\n // Shift+F10 is the standard keyboard route to a context menu,\n // and the only route to this one — the trigger is not a tab\n // stop.\n if (event.key === 'F10' && event.shiftKey && hasMenu) {\n if (isContextOnly) {\n openColumnContextMenu(\n column,\n isSortable,\n activeSort,\n event,\n );\n } else {\n event.preventDefault();\n // The Scroller listens for Shift+F10 too, for the row menu.\n event.stopPropagation();\n setOpenMenuColumnKey(column.key);\n }\n\n return;\n }\n\n if (!isSortable) return;\n if (event.key !== 'Enter' && event.key !== ' ') return;\n // Space would scroll the grid otherwise.\n event.preventDefault();\n onColumnSort?.(column.key);\n }\n : undefined,\n }}\n >\n {content}\n {canResize ? (\n <ColumnResizer<T>\n column={column}\n label={t('itemTable.resizeColumn', 'Resize column')}\n onResize={onColumnResize!}\n onResizeEnd={onColumnResizeEnd!}\n />\n ) : null}\n </TableHeaderCell>\n );\n }\n\n function renderCell(\n column: CubeResolvedColumn<T>,\n row: T,\n rowIndex: number,\n rowKey: Key,\n isLastRow: boolean,\n // The row's pinned edge, mirrored onto its cells. Cells are what draw the\n // borders and the fill, and a sub-element cannot ask about its DOM parent's\n // mods — state keys inside `Cell` resolve against the table root.\n pinnedEdge?: 'top' | 'bottom',\n treeItemAria?: ReturnType<typeof useTreeItem>,\n ) {\n // Section-qualified, because the same record is routinely pinned at both\n // edges. `rowKey` below stays the consumer's own — this identity is the\n // range's alone.\n const rangeKey = selectionRowKey(sectionOf(pinnedEdge), rowKey);\n if (column.key === SELECTION_COLUMN_KEY) {\n return renderSelectionCell(\n column,\n row,\n rowIndex,\n rowKey,\n isLastRow,\n pinnedEdge,\n );\n }\n\n if (column.key === ROW_NUMBER_COLUMN_KEY) {\n return (\n <td\n key={column.key}\n data-element=\"Cell\"\n data-key={column.key}\n data-kind=\"row-number\"\n data-last-row={isLastRow ? '' : undefined}\n data-pinned={pinnedEdge}\n data-odd={cellBandFlag(rowIndex, pinnedEdge)}\n data-last-column={lastColumnFlag(column)}\n data-corner={bottomCornerFlag(\n column,\n rowIndex,\n isLastRow,\n pinnedEdge,\n )}\n role=\"gridcell\"\n aria-colindex={column.ariaColIndex}\n style={pinStyle(column)}\n >\n {/*\n A pinned row is not numbered. It sits outside the sequence — a\n total is not row 1 — and numbering it would repeat a number the\n scrolling rows already own.\n */}\n {pinnedEdge ? null : rowNumberOffset + rowIndex + 1}\n </td>\n );\n }\n\n if (column.key === ROW_MENU_COLUMN_KEY) {\n return renderRowMenuCell(\n column,\n row,\n rowIndex,\n rowKey,\n isLastRow,\n pinnedEdge,\n );\n }\n\n const ctx: CubeTableCellContext<T> = {\n row,\n rowKey,\n rowIndex,\n columnKey: column.key,\n columnIndex: column.index,\n section: sectionOf(pinnedEdge),\n // The ROW's selection, matching the field's siblings (`isRowFocused`).\n // Cell-range membership is a different question and has its own answer in\n // `data-cell-selected`.\n isSelected: selection?.isSelected(rowKey) ?? false,\n tree: pinnedEdge == null ? treeRowState(rowIndex) : undefined,\n };\n\n const value = column.isStructural\n ? undefined\n : getColumnValue(column, row, rowIndex);\n\n // Without `render`, the cell shows the column's display text — which is\n // what `format` produces, and what client sort, search and copy all agree\n // on. `getColumnText` returns null for a value it cannot turn into text\n // (an object with no `format`), so we render nothing rather than\n // \"[object Object]\".\n const rendered = column.render\n ? column.render(value, row, rowIndex, ctx)\n : column.isStructural\n ? null\n : getColumnText(column, row, rowIndex);\n\n const isText =\n typeof rendered === 'string' ||\n typeof rendered === 'number' ||\n typeof rendered === 'bigint';\n\n // Bare text gets ellipsis + an automatic tooltip when it overflows.\n // `TextItem` rather than `Item` deliberately: `Item` runs `useHotkeys` on\n // every instance, which at one per cell would be hundreds of subscriptions\n // churned on every scroll tick.\n //\n // An `autoHeight` column skips it — `TextItem` exists to truncate, and this\n // column has opted into wrapping instead.\n const content =\n isText && !column.autoHeight ? (\n <TextItem>{String(rendered)}</TextItem>\n ) : isText ? (\n String(rendered)\n ) : (\n (rendered as ReactNode)\n );\n\n const treeEntry = pinnedEdge == null ? tree?.entries[rowIndex] : undefined;\n const displayContent =\n treeEntry && column.key === tree?.columnKey ? (\n <div\n data-element=\"TreeContent\"\n style={\n {\n '--tree-level': String(treeEntry.level),\n } as CSSProperties\n }\n >\n {treeEntry.children.length > 0 ? (\n <TableTreeToggle\n {...treeItemAria?.expandButtonProps}\n data-element=\"TreeToggle\"\n tabIndex={-1}\n >\n <DirectionIcon\n to={\n tree.state.expandedKeys.has(treeEntry.key)\n ? 'bottom'\n : 'right'\n }\n />\n </TableTreeToggle>\n ) : (\n <TableTreeTogglePlaceholder\n data-element=\"TreeToggle\"\n aria-hidden=\"true\"\n />\n )}\n <div data-element=\"TreeValue\">{content}</div>\n </div>\n ) : (\n content\n );\n\n const resolvedCellStyles =\n typeof column.cellStyles === 'function'\n ? column.cellStyles(ctx)\n : column.cellStyles;\n\n const CellTag = column.isRowHeader ? 'th' : 'td';\n\n // The link lives in the row-header cell but stretches over the whole row:\n // a `<tr>` cannot be wrapped in an `<a>`, and this is the one cell whose\n // text is the row's accessible name. ⌘-click, middle-click and \"Open in\n // new tab\" then work natively, which an onClick handler can never give.\n const link = column.isRowHeader ? rowLink?.(row, rowIndex) : undefined;\n\n return (\n <CellTag\n key={column.key}\n data-element=\"Cell\"\n data-key={column.key}\n data-pin={column.pin}\n data-pin-edge={column.isPinEdge ? '' : undefined}\n data-align={column.align}\n data-wrap={column.autoHeight ? '' : undefined}\n data-link={link !== undefined ? '' : undefined}\n data-last-row={isLastRow ? '' : undefined}\n data-pinned={pinnedEdge}\n data-odd={cellBandFlag(rowIndex, pinnedEdge)}\n data-tint={tintSlot(\n tints,\n column.key,\n pinnedEdge == null ? 'body' : 'totals',\n )}\n data-last-column={lastColumnFlag(column)}\n data-corner={bottomCornerFlag(column, rowIndex, isLastRow, pinnedEdge)}\n data-cell-selected={\n isCellSelected(rangeKey, column.key) ? '' : undefined\n }\n {...(column.isRowHeader\n ? { scope: 'row' as const }\n : { role: 'gridcell' as const })}\n {...cellSelectionProps(rangeKey, column.key, pinnedEdge)}\n aria-colindex={column.ariaColIndex}\n style={{\n ...pinStyle(column),\n ...(resolvedCellStyles as CSSProperties),\n }}\n {...column.cellProps?.(ctx)}\n >\n {displayContent}\n {link !== undefined ? (\n <Action\n data-element=\"RowLink\"\n to={link}\n // The row is the tab stop; the link is reached through it.\n tabIndex={-1}\n aria-label={getColumnText(column, row, rowIndex) ?? undefined}\n />\n ) : null}\n </CellTag>\n );\n }\n\n /**\n * A pinned row — a total or subtotal.\n *\n * Rendered inside `<tbody>` rather than `<thead>`/`<tfoot>` so it keeps the\n * body's own row and cell styling: the sub-element chains are anchored to\n * `Body`, and a row in the head would match none of them. `data-pinned`\n * carries the stickiness instead.\n */\n function renderPinnedRow(row: T, index: number, edge: 'top' | 'bottom') {\n // The consumer's own key, not a positional one: a cell range spans pinned\n // and scrolling rows alike, so both have to answer to the same identity.\n const rowKey = getRowKey(row, index);\n\n return (\n <tr\n key={`pinned-${edge}-${rowKey}`}\n data-element=\"Row\"\n data-pinned={edge}\n role=\"row\"\n aria-rowindex={pinnedRowIndex(index, edge)}\n >\n {columns.map((column) =>\n renderCell(column, row, index, rowKey, false, edge),\n )}\n </tr>\n );\n }\n\n /** The cells of one body row. Shared by both render paths. */\n function renderRowCells(\n row: T,\n rowIndex: number,\n treeItemAria?: ReturnType<typeof useTreeItem>,\n ) {\n const rowKey = bodyRowKey(row, rowIndex);\n\n return columns.map((column) =>\n renderCell(\n column,\n row,\n rowIndex,\n rowKey,\n rowIndex === rows.length - 1,\n undefined,\n treeItemAria,\n ),\n );\n }\n\n /**\n * The `<tr>` shell. Virtuoso owns the element in the virtualized path (it\n * needs its own `style` and measurement attributes), so this returns the\n * props rather than the element.\n */\n function getRowElementProps(row: T, rowIndex: number) {\n const rowKey = bodyRowKey(row, rowIndex);\n const isSelected = selection?.isSelected(rowKey) ?? false;\n const ctx: CubeTableRowContext<T> = {\n row,\n rowKey,\n rowIndex,\n section: 'body',\n isSelected,\n tree: treeRowState(rowIndex),\n };\n const extra = getRowProps?.(ctx);\n\n return {\n 'data-element': 'Row',\n 'data-key': String(rowKey),\n // Lets a pointer or keyboard event resolve back to its row without a\n // closure per row.\n 'data-row-index': rowIndex,\n 'data-qa': extra?.qa,\n 'data-odd': isStriped && rowIndex % 2 === 1 ? '' : undefined,\n 'data-dimmed': extra?.isDimmed ? '' : undefined,\n 'data-selected': isSelected ? '' : undefined,\n 'data-disabled': selection?.isRowDisabled(rowKey) ? '' : undefined,\n role: 'row',\n // Only the resting row takes a tab stop; the rest are reached with the\n // arrow keys. Off entirely when nothing on the row is operable.\n tabIndex:\n !tree && isReorderable\n ? rowIndex === focusedRowIndex\n ? 0\n : -1\n : undefined,\n // Only meaningful in a selectable grid; announcing \"not selected\" on\n // every row of a plain table is noise.\n 'aria-selected': selection?.isEnabled ? isSelected : undefined,\n 'aria-rowindex': bodyRowIndex(rowIndex),\n title: extra?.tooltip,\n height: extra?.height,\n 'data-clickable':\n onRowAction != null || rowLink?.(row, rowIndex) !== undefined\n ? ''\n : undefined,\n onClick:\n onRowAction != null\n ? (event: ReactMouseEvent) => {\n // A click that landed on a control inside the cell belongs to\n // that control — the row must not also act on it.\n if (\n (event.target as HTMLElement).closest(\n 'a, button, input, select, textarea, [role=\"button\"], [role=\"menuitem\"]',\n )\n ) {\n return;\n }\n\n onRowAction(row, rowKey);\n }\n : undefined,\n onContextMenu: isMenuEnabled\n ? (event: ReactMouseEvent) =>\n openContextMenuFor(row, rowIndex, rowKey, event)\n : undefined,\n ...Object.fromEntries(\n Object.entries(extra?.mods ?? {})\n .filter(([, active]) => active)\n .map(([name]) => [`data-${name}`, '']),\n ),\n } as Record<string, any>;\n }\n\n function renderRow(row: T, rowIndex: number, isVirtual = false) {\n const { height, ...rowProps } = getRowElementProps(row, rowIndex);\n const rowKey = bodyRowKey(row, rowIndex);\n const treeNode = tree?.nodes[rowIndex];\n const treeEntry = tree?.entries[rowIndex];\n\n return (\n <TableRow\n key={rowProps['data-key']}\n rowKey={rowKey}\n rowProps={rowProps}\n height={height}\n index={isVirtual ? rowIndex : undefined}\n measureRef={isVirtual ? virtualizer.measureElement : undefined}\n dragState={isReorderable ? dragState : undefined}\n dropState={isReorderable ? dropState : undefined}\n tree={\n treeNode && treeEntry\n ? {\n state: tree.state,\n node: treeNode,\n entry: treeEntry,\n isVirtualized: isVirtual,\n }\n : undefined\n }\n >\n {(treeItemAria) => renderRowCells(row, rowIndex, treeItemAria)}\n </TableRow>\n );\n }\n\n function renderSpacerRow(height: number, position: 'top' | 'bottom') {\n if (height <= 0) return null;\n\n return (\n <tr aria-hidden=\"true\" data-spacer={position}>\n <td colSpan={Math.max(columnCount, 1)} style={{ height }} />\n </tr>\n );\n }\n\n /**\n * A row, preceded by the line showing a drop above it — and followed by one\n * for the very last row, which has nothing after it to carry a \"before\".\n *\n * The indicators render nothing unless a drag is in flight, so a table that\n * is merely *capable* of dragging keeps its ordinary structure.\n */\n function withDropIndicators(row: T, index: number, isVirtual = false) {\n const rowKey = bodyRowKey(row, index);\n const rowNode = renderRow(row, index, isVirtual);\n\n if (!isReorderable || !dropState) return rowNode;\n\n return (\n <Fragment key={`row-${String(rowKey)}`}>\n <TableRowDropIndicator\n rowKey={rowKey}\n dropPosition=\"before\"\n dropState={dropState}\n columnCount={columnCount}\n />\n {rowNode}\n {index === rows.length - 1 ? (\n <TableRowDropIndicator\n rowKey={rowKey}\n dropPosition=\"after\"\n dropState={dropState}\n columnCount={columnCount}\n />\n ) : null}\n </Fragment>\n );\n }\n\n const hasRows = rows.length > 0;\n\n // How a refresh over an existing result is presented. `overlay` keeps the\n // previous rows on screen (dimmed, behind a spinner) so a server page or a\n // re-sort does not blank the table; `skeleton` discards them; `none` leaves\n // the visuals entirely to the consumer and only sets `aria-busy`.\n // `overlay` is the only behaviour that paints: the rows dim and a spinner\n // sits over them. `none` deliberately leaves them untouched.\n const isStale = isLoading && hasRows && loadingIndicator === 'overlay';\n const showSkeleton =\n isLoading &&\n loadingIndicator !== 'none' &&\n (!hasRows || loadingIndicator === 'skeleton');\n // Without rows and without an indicator there is nothing to say yet —\n // rendering the empty state would flash \"No items\" before the first response.\n const showBlank = isLoading && !hasRows && loadingIndicator === 'none';\n\n const shouldVirtualize =\n !isAutoHeight &&\n hasRows &&\n error == null &&\n (isVirtualized === true ||\n (isVirtualized === 'auto' && rows.length > virtualizeThreshold));\n\n const rowsRef = useRef(rows);\n\n rowsRef.current = rows;\n\n // `getScrollElement` is read from a ref, not the state value: the virtualizer\n // consults it from a layout effect, and a closure over state can still hold\n // the `null` from the first render.\n const virtualizer = useVirtualizer({\n count: shouldVirtualize ? rows.length : 0,\n getScrollElement: () => scrollerRef.current,\n getItemKey: (index) =>\n String(rowKeys?.[index] ?? getRowKey(rowsRef.current[index], index)),\n estimateSize: () =>\n (rowHeight ??\n (rowSizeKey\n ? SIZES[rowSizeKey]\n : ESTIMATED_ROW_HEIGHT[size ?? 'medium'])) + 1,\n measureElement: (element) => element.getBoundingClientRect().height,\n // Rows beyond each viewport edge. Higher than a list's, because a fast\n // flick outruns React's re-render and the gap shows as blank rows — and a\n // table row is one element, not one per column, so the extra ones are\n // cheap.\n overscan,\n });\n\n // `scrollerEl` is referenced only to re-render on the pass where the scroller\n // first exists, so the virtualizer re-reads `getScrollElement` and attaches.\n void scrollerEl;\n\n const focusedTreeKey = tree?.state.selectionManager.focusedKey;\n useEffect(() => {\n if (!shouldVirtualize || focusedTreeKey == null || !tree) return;\n\n const index = tree.entries.findIndex(\n (entry) => entry.key === focusedTreeKey,\n );\n if (index >= 0) virtualizer.scrollToIndex(index, { align: 'auto' });\n }, [focusedTreeKey, shouldVirtualize, tree, virtualizer]);\n\n const scrollability = useScrollability(scrollerEl);\n\n /**\n * Roving tabindex over the rows, so a reorderable table can be operated from\n * the keyboard at all.\n *\n * React Aria's `dragProps` already describe \"press Enter to start dragging\"\n * and implement the whole keyboard drag — but a `<tr>` is not focusable, so\n * without this the description is announced for a row nobody can reach. One\n * tab stop for the grid, arrows to move within it, matching how every other\n * collection in the kit behaves.\n */\n // Not while a drag is in flight: React Aria is already moving the row under\n // the pointer, and a second transform fighting it reads as a stutter.\n useRowMoveAnimation({\n isEnabled: isRowMoveAnimated && !dragState?.draggingKeys?.size,\n bodyRef: localBodyRef,\n });\n\n /**\n * How many rows the next batch is likely to bring, measured across the last\n * fetch that actually happened.\n *\n * The placeholder burst is sized to this so the scroll height is right both\n * before and after the load: a short burst under a long batch makes the\n * content jump the moment the rows land, and leaves the user stopped at the\n * bottom of the list in the meantime with nothing left to scroll into.\n *\n * Measured across `isLoadingMore`, not from any growth in `rows`. Plenty of\n * things lengthen the list without being a fetch — clearing a client search\n * over an infinite list restores every filtered-out row at once — and reading\n * that as a batch of ninety sized the next burst at ninety.\n *\n * Measured at all, rather than taken from `pageSize`, because infinite-scroll\n * consumers often do not set it.\n */\n const lastBatchSizeRef = useRef(0);\n const rowCountBeforeFetchRef = useRef<number | null>(null);\n\n useEffect(() => {\n if (isLoadingMore) {\n rowCountBeforeFetchRef.current = rows.length;\n\n return;\n }\n\n const before = rowCountBeforeFetchRef.current;\n\n if (before != null && rows.length > before) {\n lastBatchSizeRef.current = rows.length - before;\n }\n\n rowCountBeforeFetchRef.current = null;\n // Deliberately keyed on the flag alone: the row count wanted is the one at\n // each edge of the fetch, not every value it passes through.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [isLoadingMore]);\n\n const loadMoreSkeletonCount = Math.min(\n // Until a fetch has been measured, the rows already loaded are the best\n // guess at what the next batch brings — that IS the first page.\n Math.max(lastBatchSizeRef.current || rows.length || skeletonRowCount, 1),\n MAX_LOAD_MORE_SKELETON_ROWS,\n );\n\n const [focusedRowIndex, setFocusedRowIndex] = useState(0);\n // Only used to suppress text selection during the gesture; the range itself\n // lives in a ref so growing it does not re-render on every cell crossed.\n const [isRangeDragging, setIsRangeDragging] = useState(false);\n\n // The button can come up outside the grid — over the footer, over another\n // component, off the window entirely — so the end of the gesture is watched\n // globally rather than on the cell the drag started in.\n useEffect(() => {\n if (!isRangeDragging) return;\n\n const end = () => {\n if (cellSelection) cellSelection.isDraggingRef.current = false;\n setIsRangeDragging(false);\n };\n\n window.addEventListener('pointerup', end);\n window.addEventListener('pointercancel', end);\n\n return () => {\n window.removeEventListener('pointerup', end);\n window.removeEventListener('pointercancel', end);\n };\n }, [isRangeDragging, cellSelection]);\n\n const moveRowFocus = useEvent((from: HTMLElement, delta: number) => {\n const current = from.closest('tr[data-element=\"Row\"]');\n const all = Array.from(\n scrollerRef.current?.querySelectorAll<HTMLTableRowElement>(\n 'tbody tr[data-element=\"Row\"]:not([data-placeholder])',\n ) ?? [],\n );\n\n if (!all.length) return false;\n\n const index = current ? all.indexOf(current as HTMLTableRowElement) : -1;\n const next = Math.min(\n Math.max((index === -1 ? focusedRowIndex : index) + delta, 0),\n all.length - 1,\n );\n\n setFocusedRowIndex(next);\n all[next]?.focus();\n\n return true;\n });\n\n /* ── infinite scroll ────────────────────────────────────────────────────\n * An `IntersectionObserver` on a sentinel row rather than a scroll handler:\n * `rootMargin` expresses \"prefetch this far before the end\" directly, it\n * costs nothing per scroll tick, and it works on both render paths — under\n * virtualization the trailing spacer holds the remaining height, so the\n * sentinel after it still marks the true end of the list.\n * ──────────────────────────────────────────────────────────────────────── */\n const sentinelRef = useRef<HTMLDivElement>(null);\n const onLoadMoreEvent = useEvent(() => onLoadMore?.());\n\n useEffect(() => {\n const sentinel = sentinelRef.current;\n\n // Re-armed whenever `isLoadingMore` flips, so a request in flight cannot be\n // fired again by the sentinel still sitting in view.\n if (!onLoadMore || !hasMore || isLoadingMore || !scrollerEl || !sentinel) {\n return;\n }\n\n // One screen ahead by default: the request goes out while the user still\n // has a viewport of rows left to read, so the batch is usually there before\n // they arrive. Read at arm time rather than tracked — a resize mid-scroll\n // leaves the margin slightly stale, which costs nothing.\n const margin =\n loadMoreMargin ?? Math.max(scrollerEl.clientHeight, MIN_LOAD_MORE_MARGIN);\n\n const observer = new IntersectionObserver(\n (entries) => {\n if (entries.some((entry) => entry.isIntersecting)) onLoadMoreEvent();\n },\n { root: scrollerEl, rootMargin: `0px 0px ${margin}px 0px` },\n );\n\n observer.observe(sentinel);\n\n return () => observer.disconnect();\n }, [\n onLoadMore,\n hasMore,\n isLoadingMore,\n scrollerEl,\n loadMoreMargin,\n onLoadMoreEvent,\n rows.length,\n ]);\n\n /* ── row menu ───────────────────────────────────────────────────────────\n * One instance for the whole table rather than one per row: a table can hold\n * thousands of rows, and only ever one context menu is open.\n *\n * `targetRef` is deliberately left unattached, which keeps the hook's own\n * `contextmenu` listener unbound — it would open with fixed props, and the\n * items depend on which row was right-clicked. The handler below resolves the\n * row first and then opens with that row's items; with no target, the hook\n * positions from the event's viewport coordinates, which is what a\n * pointer-anchored menu wants anyway.\n * ──────────────────────────────────────────────────────────────────────── */\n const contextMenu = useContextMenu<HTMLDivElement, any>(Menu, {\n placement: 'bottom start',\n });\n\n const isMenuEnabled = rowMenu != null && rowContextMenu !== false;\n const hasMenuColumn = isMenuEnabled && rowContextMenu !== 'context-only';\n\n function resolveRowMenu(row: T, rowIndex: number, rowKey: Key) {\n if (!rowMenu) return null;\n\n return rowMenu(row, {\n row,\n rowKey,\n rowIndex,\n section: 'body',\n isSelected: selection?.isSelected(rowKey) ?? false,\n isFocused: false,\n isDropTarget: false,\n });\n }\n\n function menuActionHandler(row: T, rowKey: Key, closeAfter: boolean) {\n return (action: Key) => {\n onRowMenuAction?.(normalizeMenuAction(action), row, rowKey);\n\n // `useContextMenu` leaves its popover open after an action — the same\n // happens in `Tree`, so it is the hook's behaviour rather than this\n // table's. Closing here keeps the row menu correct meanwhile; drop this\n // once the hook closes on select itself.\n if (closeAfter) contextMenu.close();\n };\n }\n\n const openContextMenuFor = useEvent(\n (\n row: T,\n rowIndex: number,\n rowKey: Key,\n event: ReactMouseEvent | ReactKeyboardEvent,\n ) => {\n const items = resolveRowMenu(row, rowIndex, rowKey);\n\n // No items means no menu — falling through to the browser's own context\n // menu is more useful than opening an empty popover.\n if (isMenuEmpty(items)) return;\n\n event.preventDefault();\n contextMenu.open(\n { children: items, onAction: menuActionHandler(row, rowKey, true) },\n undefined,\n // Shift+F10 carries no coordinates; the hook then anchors on the\n // element that produced the event, which is the row.\n 'clientX' in event.nativeEvent\n ? (event.nativeEvent as MouseEvent)\n : undefined,\n );\n },\n );\n\n /* ── column menu ─────────────────────────────────────────────────────────\n * Shares the `contextMenu` instance above. A header right-click is the same\n * pointer-anchored popover with different children, and attaching the hook's\n * `targetRef` to a `<th>` would bind its listener with fixed props — the same\n * reason the row menu leaves it unattached.\n * ──────────────────────────────────────────────────────────────────────── */\n\n function resolveColumnMenu(column: CubeResolvedColumn<T>): ReactNode | null {\n if (columnContextMenu === false || column.isStructural) return null;\n\n const items = column.header?.menu;\n\n return isMenuEmpty(items) ? null : items;\n }\n\n /** The reserved sort keys, labelled here so `column-menu.ts` stays pure. */\n function columnMenuContext(\n column: CubeResolvedColumn<T>,\n isSortable: boolean,\n activeSort: CubeTableSort | null,\n ): CubeColumnMenuContext {\n return {\n isSortable,\n sort: activeSort?.direction ?? null,\n disallowSortRemoval: column.disallowSortRemoval === true,\n labels: {\n 'sort-asc': t('itemTable.sortAscending', 'Sort ascending'),\n 'sort-desc': t('itemTable.sortDescending', 'Sort descending'),\n 'clear-sort': t('itemTable.clearSort', 'Clear sort'),\n },\n };\n }\n\n function columnMenuActionHandler(\n column: CubeResolvedColumn<T>,\n closeAfter: boolean,\n ) {\n return (action: Key) => {\n const normalized = normalizeMenuAction(action);\n\n // The table's own keys are applied first, then the consumer hears about\n // them anyway — so a key can be both understood here and observed there.\n if (isColumnMenuSortKey(normalized)) {\n onColumnSortChange?.(\n column.key,\n COLUMN_MENU_SORT_DIRECTION[normalized],\n );\n }\n\n column.header?.onMenuAction?.(normalized);\n onColumnMenuAction?.(normalized, column.key);\n\n // `useContextMenu` leaves its popover open after an action; see\n // `menuActionHandler` above.\n if (closeAfter) contextMenu.close();\n };\n }\n\n const openColumnContextMenu = useEvent(\n (\n column: CubeResolvedColumn<T>,\n isSortable: boolean,\n activeSort: CubeTableSort | null,\n event: ReactMouseEvent | ReactKeyboardEvent,\n ) => {\n const items = resolveColumnMenu(column);\n\n if (items == null) return;\n\n event.preventDefault();\n // The Scroller listens for Shift+F10 too, for the row menu.\n event.stopPropagation();\n contextMenu.open(\n {\n ...columnMenuProps,\n ...column.header?.menuProps,\n children: processColumnMenuItems(\n items,\n columnMenuContext(column, isSortable, activeSort),\n ),\n onAction: columnMenuActionHandler(column, true),\n },\n undefined,\n 'clientX' in event.nativeEvent\n ? (event.nativeEvent as MouseEvent)\n : undefined,\n );\n },\n );\n\n /** Resolves the row a pointer or keyboard event landed in. */\n function rowFromEvent(target: EventTarget | null) {\n const element = (target as HTMLElement | null)?.closest?.(\n 'tr[data-element=\"Row\"][data-key]',\n );\n\n if (!element) return null;\n\n const index = Number(element.getAttribute('data-row-index'));\n\n if (!Number.isInteger(index)) return null;\n\n const row = rows[index];\n\n return row === undefined\n ? null\n : { row, index, key: bodyRowKey(row, index) };\n }\n\n const virtualItems = shouldVirtualize ? virtualizer.getVirtualItems() : [];\n const paddingTop = virtualItems.length ? virtualItems[0].start : 0;\n const paddingBottom = virtualItems.length\n ? virtualizer.getTotalSize() - virtualItems[virtualItems.length - 1].end\n : 0;\n\n const colGroup = (\n <colgroup>\n {columns.map((column) => (\n <col\n key={column.key}\n style={column.width != null ? { width: column.width } : undefined}\n />\n ))}\n </colgroup>\n );\n\n function pathsSharePrefix(\n left: readonly CubeTableColumnGroupHeader[],\n right: readonly CubeTableColumnGroupHeader[],\n depth: number,\n ) {\n for (let index = 0; index <= depth; index++) {\n if (left[index]?.key !== right[index]?.key) return false;\n }\n\n return true;\n }\n\n function renderHeaderGroupCell(\n group: CubeTableColumnGroupHeader,\n segment: readonly CubeResolvedColumn<T>[],\n depth: number,\n ) {\n const first = segment[0];\n const last = segment[segment.length - 1];\n const pin = segment.every((column) => column.pin === first.pin)\n ? first.pin\n : undefined;\n const pinOffset =\n pin === 'start' ? first.pinOffset : pin === 'end' ? last.pinOffset : null;\n\n return (\n <th\n key={`${depth}:${first.key}:${group.key}`}\n data-element=\"HeaderGroupCell\"\n data-key={group.key}\n data-pin={pin}\n data-pin-edge={\n segment.some((column) => column.isPinEdge) ? '' : undefined\n }\n data-last-column={last.index === columnCount - 1 ? '' : undefined}\n data-align=\"center\"\n role=\"columnheader\"\n scope=\"colgroup\"\n tabIndex={-1}\n aria-colindex={first.ariaColIndex}\n colSpan={segment.length}\n style={\n pinOffset == null\n ? undefined\n : { ['--pin-offset' as any]: `${pinOffset}px` }\n }\n >\n <TableHeaderItem>{group.title}</TableHeaderItem>\n </th>\n );\n }\n\n function renderHeaderRowCells(depth: number) {\n const cells: ReactNode[] = [];\n\n for (let columnIndex = 0; columnIndex < columns.length; ) {\n const column = columns[columnIndex];\n const path = columnHeaderPaths?.get(column.key) ?? [];\n\n // This column's leaf header began on an earlier row and spans this one.\n if (path.length < depth) {\n columnIndex++;\n continue;\n }\n\n if (path.length === depth) {\n cells.push(renderHeaderCell(column, headerRowCount - depth));\n columnIndex++;\n continue;\n }\n\n let segmentEnd = columnIndex + 1;\n\n while (segmentEnd < columns.length) {\n const nextPath = columnHeaderPaths?.get(columns[segmentEnd].key) ?? [];\n\n if (\n nextPath.length <= depth ||\n columns[segmentEnd].pin !== column.pin ||\n !pathsSharePrefix(path, nextPath, depth)\n ) {\n break;\n }\n\n segmentEnd++;\n }\n\n cells.push(\n renderHeaderGroupCell(\n path[depth],\n columns.slice(columnIndex, segmentEnd),\n depth,\n ),\n );\n columnIndex = segmentEnd;\n }\n\n return cells;\n }\n\n const headerRows = isHeaderHidden\n ? null\n : Array.from({ length: headerRowCount }, (_, depth) => {\n const isLeafRow = depth === headerRowCount - 1;\n\n return (\n <tr\n key={depth}\n data-element=\"HeadRow\"\n role=\"row\"\n aria-rowindex={depth + 1}\n ref={isLeafRow ? headRowRef : undefined}\n {...(isLeafRow ? headCollectionProps : undefined)}\n onKeyDownCapture={\n isLeafRow\n ? (event) => {\n // `DraggableCollection`'s Alt+Arrow reorder sits on this\n // row and fires in capture, so it would beat the resize\n // handle's own Alt+Arrow bubble handler.\n if (\n (event.target as HTMLElement)?.closest?.(\n '[data-element=\"Resizer\"]',\n )\n ) {\n return;\n }\n\n (headCollectionProps as any)?.onKeyDownCapture?.(event);\n }\n : undefined\n }\n >\n {renderHeaderRowCells(depth)}\n </tr>\n );\n });\n\n const tableProps = {\n 'data-element': 'Table',\n role: tree ? 'treegrid' : 'grid',\n 'aria-label': ariaLabel,\n 'aria-busy': isLoading || undefined,\n 'aria-rowcount':\n headerRowCount + pinnedTopCount + bodyRowCount + pinnedBottomCount,\n 'aria-colcount': columnCount,\n 'aria-multiselectable':\n selection?.selectionMode === 'multiple' ? true : undefined,\n } as const;\n\n let bodyContent: ReactNode;\n\n if (error != null) {\n bodyContent = renderStateRow(error);\n } else if (showSkeleton) {\n bodyContent = renderSkeletonRows();\n } else if (showBlank) {\n bodyContent = null;\n } else if (!hasRows) {\n bodyContent = renderStateRow(isFiltered ? noResultsLabel : emptyLabel);\n } else if (shouldVirtualize) {\n bodyContent = (\n <>\n {renderSpacerRow(paddingTop, 'top')}\n {virtualItems.map((v) =>\n withDropIndicators(rows[v.index], v.index, true),\n )}\n {renderSpacerRow(paddingBottom, 'bottom')}\n </>\n );\n } else {\n bodyContent = rows.map((row, index) => withDropIndicators(row, index));\n }\n\n const tableContent = (\n <>\n {colGroup}\n {isHeaderHidden ? null : <thead data-element=\"Head\">{headerRows}</thead>}\n <tbody data-element=\"Body\" {...collectionProps} ref={handleBodyRef}>\n {pinnedTopRows?.map((row, index) => renderPinnedRow(row, index, 'top'))}\n {bodyContent}\n {pinnedBottomRows?.map((row, index) =>\n renderPinnedRow(row, index, 'bottom'),\n )}\n {isLoadingMore\n ? renderSkeletonRows(loadMoreSkeletonCount, 'load-more')\n : null}\n {onLoadMore && hasRows ? (\n <tr data-sentinel=\"\" aria-hidden=\"true\">\n <td\n colSpan={Math.max(columnCount, 1)}\n style={{ height: 1, padding: 0, border: 0 }}\n >\n <div ref={sentinelRef} style={{ height: 1 }} />\n </td>\n </tr>\n ) : null}\n </tbody>\n </>\n );\n\n // Before the first measure there are no columns to lay out yet — show the\n // generic table skeleton rather than an empty frame.\n //\n // Returned HERE, below every hook, not at the point in the render where the\n // condition is known. Returning early skipped sixteen hooks — the virtualizer,\n // the scrollability observer, the move animation, the context menu, two\n // `useState`s — so the first render with columns called more hooks than the\n // last one without them, and React threw \"Rendered more hooks than during the\n // previous render\". A consumer that mounts with `columns={[]}` while loading\n // and fills them in from a response is the ordinary case, not an exotic one.\n if (columnCount === 0 && isLoading) {\n return (\n <TableElement\n ref={rootRef}\n qa={qa || 'Table'}\n styles={mergedStyles}\n mods={{ size, shape, ...mods }}\n >\n {toolbar}\n <div data-element=\"Scroller\" ref={handleScrollerRef}>\n <Skeleton layout=\"table\" />\n </div>\n </TableElement>\n );\n }\n\n return (\n <TableElement\n ref={rootRef}\n qa={qa || 'Table'}\n styles={mergedStyles}\n mods={{\n size,\n shape,\n 'sticky-header': isHeaderSticky,\n 'column-dividers': hasColumnDividers,\n 'range-dragging': isRangeDragging,\n // The footer's top border is the closing edge, so the last row must not\n // draw one as well.\n 'has-footer': footer != null,\n 'scroll-x': scrollability.x,\n 'scroll-y': scrollability.y,\n stale: isStale,\n ...mods,\n }}\n >\n {toolbar}\n <div\n data-element=\"Scroller\"\n ref={handleScrollerRef}\n // Focusable only programmatically: a cell press moves focus here so the\n // range's shortcuts land, but the grid stays a single tab stop.\n tabIndex={cellSelection?.isEnabled ? -1 : undefined}\n // Escape is the standard way out of a selection, and it must work from\n // wherever focus happens to be inside the table.\n onKeyDown={(event) => {\n // Shift+F10 is the standard way to reach a context menu from the\n // keyboard, and the only way when there is no `⋮` trigger.\n if (event.key === 'F10' && event.shiftKey && isMenuEnabled) {\n const found = rowFromEvent(event.target);\n\n if (found) {\n event.stopPropagation();\n openContextMenuFor(found.row, found.index, found.key, event);\n }\n\n return;\n }\n\n if (event.key === 'Enter' && onRowAction) {\n const found = rowFromEvent(event.target);\n\n // Enter on a control inside the cell belongs to that control.\n if (\n found &&\n !(event.target as HTMLElement).closest(\n 'a, button, input, select, textarea, [role=\"button\"]',\n )\n ) {\n onRowAction(found.row, found.key);\n }\n\n return;\n }\n\n if (\n !tree &&\n isReorderable &&\n (event.key === 'ArrowDown' || event.key === 'ArrowUp')\n ) {\n // Not while a drag is in flight — the arrows then belong to React\n // Aria, which uses them to choose the drop position.\n if (dragState?.draggingKeys?.size) return;\n\n if (\n moveRowFocus(\n event.target as HTMLElement,\n event.key === 'ArrowDown' ? 1 : -1,\n )\n ) {\n event.preventDefault();\n }\n\n return;\n }\n\n if (event.key === 'Escape') {\n if (cellSelection?.range) {\n event.stopPropagation();\n cellSelection.clear();\n\n return;\n }\n\n if (selection?.isEnabled && selection.selectedCount > 0) {\n event.stopPropagation();\n selection.clearSelection();\n }\n }\n }}\n // `onCopy` rather than a ⌘/Ctrl+C keydown: it is the event the browser\n // already fires for the shortcut AND for Edit ▸ Copy, and writing\n // through `clipboardData` needs no permission prompt. Both `text/plain`\n // and `text/html` go on, so Excel and Sheets paste a grid rather than\n // one run of text.\n onCopy={(event) => {\n if (!cellSelection?.range) return;\n\n const matrix = cellSelection.getSelectionMatrix(\n (column, row, rowIndex) =>\n column.isStructural\n ? ''\n : getColumnText(column, row, rowIndex) ?? '',\n );\n\n if (!matrix.length) return;\n\n // Both formats from the same matrix. Building the HTML by re-parsing\n // the TSV tore any cell whose value contained a tab or a newline —\n // exactly the values the TSV had to quote in the first place.\n event.preventDefault();\n event.clipboardData.setData('text/plain', toTsv(matrix));\n event.clipboardData.setData('text/html', toClipboardHtml(matrix));\n\n // A copy that writes to the clipboard leaves nothing on screen to say\n // it worked — the range looks the same before and after. The count is\n // what confirms the right block went, which matters most when the\n // selection runs past the bottom of the viewport.\n toast.success({\n title: t('itemTable.copiedToClipboard', 'Copied to clipboard'),\n description: t('itemTable.copiedCells', '{{count}} cells copied', {\n count: cellSelection.cellCount,\n }),\n });\n }}\n >\n {tree ? (\n <TreeGridTable\n tree={tree}\n tableProps={tableProps}\n style={\n layout.totalWidth != null\n ? { width: layout.totalWidth }\n : undefined\n }\n >\n {tableContent}\n </TreeGridTable>\n ) : (\n <table\n {...tableProps}\n style={\n layout.totalWidth != null\n ? { width: layout.totalWidth }\n : undefined\n }\n >\n {tableContent}\n </table>\n )}\n </div>\n {/*\n A refresh is shown by sweeping the table itself, not by parking a\n spinner over it — the rows stay readable, which is the whole point of\n keeping the previous result on screen. This is what announces it.\n\n Always mounted, with the TEXT appearing and disappearing: a live region\n announces changes to its CONTENT, so an empty node that merely carries\n an `aria-label` says nothing, and one that is inserted already-populated\n is unreliable across screen readers. The region has to be there first\n and then fill.\n */}\n <VisuallyHidden>\n <span role=\"status\">\n {isStale ? t('itemTable.refreshing', 'Refreshing') : ''}\n </span>\n </VisuallyHidden>\n {overlay}\n {contextMenu.rendered}\n {tints.configs.map((config, index) => (\n // Keyed positionally on purpose: `configs` is deduped and stable for a\n // given set of column colours, and the theme name is not on the config.\n // Remounting one of these is harmless anyway — the tokens it registers\n // live in a permanent global slot.\n <ColumnTintRegistrar key={index} config={config} />\n ))}\n {footer}\n </TableElement>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8VA,SAAS,gBAAgB,QAAoB;AAQ3C,QAAO,UAPM,OACV,KACE,QACC,OAAO,IAAI,KAAK,SAAS,OAAO,WAAW,KAAK,CAAC,OAAO,CAAC,KAAK,GAAG,CAAC,OACrE,CACA,KAAK,GAAG,CAEW;;AAGxB,SAAS,WAAW,OAAe;AACjC,QAAO,MACJ,QAAQ,MAAM,QAAQ,CACtB,QAAQ,MAAM,OAAO,CACrB,QAAQ,MAAM,OAAO;;AAG1B,MAAM,YAAY;CAAE,KAAK;CAAa,MAAM;CAAc;;;;;;;;;;;;;;AAe1D,SAAS,oBAAoB,EAAE,UAAwC;AACrE,eAAc,OAAO;AAErB,QAAO;;;;;;;;;;;;;;;AAgBT,MAAM,8BAA8B;;;;;AAMpC,MAAM,uBAAuB;AAE7B,MAAM,uBAAuB;CAC3B,QAAQ;CACR,OAAO;CACP,QAAQ;CACR,OAAO;CACP,QAAQ;CACT;AAED,SAAS,SAAS,QAAuD;AACvE,KAAI,OAAO,aAAa,KAAM,QAAO;AAErC,QAAO,GAAG,iBAAwB,GAAG,OAAO,UAAU,KAAK;;;;;;AAO7D,SAAS,cAAiB,OAKvB;CACD,MAAM,EAAE,MAAM,YAAY,OAAO,aAAa;CAC9C,MAAM,MAAM,OAAyB,KAAK;CAC1C,MAAM,kBAAkB,OAAmB,KAAK;CAChD,MAAM,EAAE,cAAc,QAAQ,KAAK,WAAkB,KAAK,OAAO,IAAI;AAKrE,iBAAgB;EACd,MAAM,MAAM,gBAAgB;AAC5B,MAAI,OAAO,KAAM;EAKjB,MAAM,gBAAgB,SAAS;AAC/B,MACE,iBACA,kBAAkB,SAAS,QAC3B,CAAC,IAAI,SAAS,SAAS,cAAc,EACrC;AACA,mBAAgB,UAAU;AAC1B;;EAGF,MAAM,SAAS,MAAM,KACnB,IAAI,SAAS,iBACX,2CACD,IAAI,EAAE,CACR,CAAC,MAAM,YAAY,QAAQ,QAAQ,QAAQ,OAAO,IAAI,CAAC;AAExD,MAAI,QAAQ;AACV,mBAAgB,UAAU;AAC1B,UAAO,OAAO;;GAEhB;CAEF,MAAM,qBAAqB,UAA6C;EACtE,MAAM,aAAa,gBAAgB;EACnC,MAAM,aAAa,MAAM;AAEzB,MAAI,cAAc,QAAQ,sBAAsB,SAK9C;OAJgB,WAAW,QACzB,2CACD,EAEY,QAAQ,QAAQ,OAAO,WAAW,CAC7C,iBAAgB,UAAU;;AAI9B,EAAC,UAAkB,gBAAgB,MAAM;;CAG3C,MAAM,wBACJ,UACG;EACH,MAAM,MAAO,MAAM,OAAuB,QACxC,2CACD;AAGD,MAAI,CAAC,OAAO,MAAM,WAAW,KAAK;AAChC,GAAC,UAAkB,mBAAmB,MAAM;AAC5C;;EAMF,MAAM,aAAa,gBAAgB,WAAW,IAAI,QAAQ;EAC1D,MAAM,QAAQ,KAAK,QAAQ,WACxB,UAAU,OAAO,MAAM,IAAI,KAAK,OAAO,WAAW,CACpD;EACD,MAAM,QAAQ,KAAK,QAAQ;AAC3B,MAAI,CAAC,MAAO;EAEZ,MAAM,cAAc,SAAuC;AACzD,OAAI,CAAC,KAAM,QAAO;AAClB,QAAK,MAAM,iBAAiB,cAAc,KAAK,IAAI;GACnD,MAAM,SAAS,MAAM,KACnB,IAAI,SAAS,iBACX,2CACD,IAAI,EAAE,CACR,CAAC,MAAM,YAAY,QAAQ,QAAQ,QAAQ,OAAO,KAAK,IAAI,CAAC;AAC7D,OAAI,QAAQ;AACV,oBAAgB,UAAU;AAC1B,WAAO,OAAO;SACT,iBAAgB,UAAU,KAAK;AACtC,UAAO;;EAGT,MAAM,cAAc,MAAM,SAAS,SAAS;EAC5C,MAAM,aAAa,KAAK,MAAM,aAAa,IAAI,MAAM,IAAI;EACzD,IAAI,UAAU;AAEd,MAAI,MAAM,QAAQ,gBAAgB,YAChC,KAAI,WAAY,WAAU,WAAW,MAAM,SAAS,GAAG;OAClD;AACH,QAAK,MAAM,UAAU,MAAM,IAAI;AAC/B,aAAU;;WAEH,MAAM,QAAQ,aACvB;OAAI,eAAe,YAAY;AAC7B,SAAK,MAAM,UAAU,MAAM,IAAI;AAC/B,cAAU;cACD,MAAM,aAAa,KAC5B,WAAU,WACR,KAAK,QAAQ,MAAM,cAAc,UAAU,QAAQ,MAAM,UAAU,CACpE;aAEM,MAAM,QAAQ,YACvB,WAAU,WAAW,KAAK,QAAQ,QAAQ,GAAG;WACpC,MAAM,QAAQ,UACvB,WAAU,WAAW,KAAK,QAAQ,QAAQ,GAAG;AAG/C,MAAI,SAAS;AACX,SAAM,gBAAgB;AACtB,SAAM,iBAAiB;AACvB;;AAOF,MACE,gBAAgB,WAAW,QAC3B;GAAC;GAAa;GAAW;GAAc;GAAY,CAAC,SAAS,MAAM,IAAI,EACvE;AACA,SAAM,gBAAgB;AACtB,SAAM,iBAAiB;AACvB;;AAGF,EAAC,UAAkB,mBAAmB,MAAM;;AAG9C,QACE,oBAAC;EACC,GAAIA,aAAW,WAAW,WAAW;EAChC;EACL,MAAK;EACE;EACP,eAAe;EACf,kBAAkB;EAEjB;GACK;;;;;;;AASZ,SAAgB,UAAmB,OAA0B;CAC3D,MAAM,EACJ,IACA,MACA,SACA,WACA,QACA,mBACA,eACA,SACA,OAAO,UACP,QAAQ,SACR,SACA,WACA,cACA,iBAAiB,OACjB,YAAY,OACZ,mBACA,oBAAoB,MACpB,iBAAiB,MACjB,eAAe,OACf,gBAAgB,QAChB,sBAAsB,IACtB,WAAW,IACX,YAAY,OACZ,mBAAmB,WACnB,mBAAmB,GACnB,WACA,kBACA,SACA,SACA,iBAAiB,OACjB,iBACA,qBACA,SACA,aACA,YACA,UAAU,OACV,gBAAgB,OAChB,gBACA,eACA,kBACA,eACA,kBAAkB,GAClB,iBAAiB,GACjB,eACA,MACA,gBAAgB,OAChB,WACA,WACA,iBACA,sBAAsB,OACtB,iBACA,iBACA,qBACA,YACA,eACA,SACA,cAAc,OACd,gBACA,mBACA,YACA,gBACA,OACA,aAAa,OACb,WAAW,OACX,MACA,OACA,cACA,oBACA,oBAAoB,MACpB,oBACA,wBACA,iBACA,aACA,cACA,eACA,SACA,QACA,WACA,QACA,cACA,kBACA,YACA,WACA,YACA,SACE;CAEJ,MAAM,EAAE,YAAY;CACpB,MAAM,cAAc,QAAQ;CAC5B,MAAM,mBAAmB,QAAQ,QAC9B,OAAO,WACN,KAAK,IAAI,OAAO,mBAAmB,IAAI,OAAO,IAAI,EAAE,UAAU,EAAE,EAClE,EACD;;;;;;;;CASD,MAAM,aAAa,UAAU,iBAAiB,WAAW;CAGzD,MAAM,mBAAmB,sBACrB,uBAAuB,SAAS,KAAK,CAAC,GAAG,GAAG,IAAI,OAChD;CAIJ,MAAM,EAAE,MAAM,SAAS;CACvB,MAAM,QAAQ,UAAU;CAExB,MAAM,CAAC,YAAY,iBAAiB,SAAgC,KAAK;CACzE,MAAM,cAAc,OAA8B,KAAK;;;;;;;;;;CAUvD,MAAM,CAAC,mBAAmB,wBAAwB,SAChD,KACD;CAID,MAAM,eAAe,OAAuC,KAAK;CACjE,MAAM,gBAAgB,aACnB,YAA4C;AAC3C,eAAa,UAAU;AACvB,MAAI,QAAS,SAAQ,UAAU;IAEjC,CAAC,QAAQ,CACV;CACD,MAAM,oBAAoB,aACvB,YAAmC;AAClC,cAAY,UAAU;AACtB,gBAAc,QAAQ;AACtB,gBAAc,QAAQ;IAExB,CAAC,cAAc,CAChB;CAGD,MAAM,iBAAiB,iBAAiB,IAAI,mBAAmB;CAc/D,MAAM,iBAAiB,eAAe,UAAU;CAChD,MAAM,oBAAoB,kBAAkB,UAAU;CAGtD,MAAM,eAAe,KAAK,IACxB,iBAAiB,KAAK,QACtB,iBAAiB,KAAK,OACvB;;CAGD,MAAM,gBAAgB,aACpB,iBAAiB,iBAAiB,iBAAiB,WAAW;CAChE,MAAM,cAAc,KAAQ,aAC1B,UAAU,aAAa,UAAU,KAAK,SAAS;CACjD,MAAM,gBAAgB,aAAqB;EACzC,MAAM,QAAQ,MAAM,QAAQ;AAE5B,SAAO,QACH;GACE,OAAO,MAAM;GACb,WAAW,MAAM;GACjB,aAAa,MAAM,SAAS,SAAS;GACrC,YAAY,KAAK,MAAM,aAAa,IAAI,MAAM,IAAI;GACnD,GACD;;;CAGN,MAAM,kBAAkB,OAAe,SACrC,SAAS,QACL,iBAAiB,QAAQ,IACzB,iBAAiB,iBAAiB,eAAe,QAAQ;CAa/D,MAAM,QAAQ,cACN,iBAAiB,SAAS,EAAE,cAAc,eAAe,CAAC,EAEhE,CAAC,SAJoB,mBAAmB,CAIf,CAC1B;CAED,MAAM,eAAe,eACZ;EAGL,QAAQ;EACR,UAAU;EACV,YAAY;EACZ,GAAG;EAGH,GAAI,eACA;GAAE,QAAQ;GAAS,UAAU;GAAG,YAAY;GAAG,GAC/C;EACJ,GAAI,gBAAgB,EAAE,OAAO,EAAE,QAAQ,eAAe,EAAE,GAAG;EAC3D,GAAI,eAAe,EAAE,SAAS,cAAc,GAAG;EAC/C,GAAI,gBAAgB,oBAAoB,MAAM,mBAC1C,EACE,YAAY;GACV,GAAI,eAAe,EAAE,QAAQ,cAAc,GAAG;GAC9C,GAAG,MAAM;GAGT,GAAG;GACJ,EACF,GACD;EACJ,GAAI,gBAAgB,mBAChB,EACE,iBAAiB;GACf,GAAI,eAAe,EAAE,QAAQ,cAAc,GAAG;GAC9C,GAAG;GACJ,EACF,GACD;EACJ,GAAI,aAAa,EAAE,MAAM,YAAY,GAAG;EACxC,GAAI,YAAY,EAAE,KAAK,WAAW,GAAG;EACrC,GAAI,cAAc,MAAM,aACpB,EAAE,MAAM;GAAE,GAAG,MAAM;GAAY,GAAG;GAAY,EAAE,GAChD;EAEJ,GAAI,aAAa,OACb,EAAE,eAAe,GAAG,UAAU,KAAK,GACnC,aACE,EAAE,eAAe,SAAS,WAAW,aAAa,IAAI,GACtD;EACN,GAAI,gBAAgB,OAChB,EAAE,kBAAkB,GAAG,aAAa,KAAK,GACzC;EACL,GACD;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACD,CACF;;;;;;;;;CAUD,SAAS,eAAe,QAAa,WAAmB;AACtD,MAAI,CAAC,eAAe,UAAW,QAAO;AAEtC,SAAO,cAAc,WAAW,QAAQ,UAAU;;;;;;;;;;CAWpD,SAAS,mBACP,QACA,WACA,YACA;AAIA,MAAI,CAAC,eAAe,cAAc,QAAQ,UAAU,CAAE,QAAO;AAE7D,SAAO;GACL,gBAAgB,UAAmD;AAGjE,QAAI,MAAM,WAAW,EAAG;AAExB,QAAI,MAAM,UAAU;AAGlB,WAAM,gBAAgB;AACtB,mBAAc,SAAS,QAAQ,UAAU;UAEzC,eAAc,OAAO,QAAQ,UAAU;AAOzC,gBAAY,SAAS,MAAM,EAAE,eAAe,MAAM,CAAC;AAEnD,kBAAc,cAAc,UAAU;AACtC,uBAAmB,KAAK;;GAE1B,sBAAsB;AACpB,QAAI,CAAC,cAAc,cAAc,QAAS;AAM1C,QAAI,WAAY;AAEhB,kBAAc,SAAS,QAAQ,UAAU;;GAE5C;;;;;;;;;;;;CAaH,SAAS,UAAU,YAAoD;AACrE,MAAI,eAAe,MAAO,QAAO;AACjC,MAAI,eAAe,SAAU,QAAO;AAEpC,SAAO;;CAGT,SAAS,eAAe,QAA+B;AACrD,SAAO,OAAO,UAAU,QAAQ,SAAS,IAAI,KAAK;;;;;;;;;;;;;;;;CAiBpD,SAAS,iBACP,QACA,UACA,WACA,YACA;AACA,MAAI,UAAU,UAAU,UAAU,KAAM,QAAO;EAE/C,MAAM,oBAAoB,kBAAkB,UAAU;AAMtD,MAAI,EAJF,eAAe,WACX,aAAa,oBAAoB,IACjC,cAAc,QAAQ,aAAa,sBAAsB,GAEzC,QAAO;AAC7B,MAAI,OAAO,UAAU,EAAG,QAAO;AAC/B,MAAI,OAAO,UAAU,QAAQ,SAAS,EAAG,QAAO;;;;;;;;;;;;;;CAiBlD,SAAS,aAAa,UAAkB,YAA+B;AACrE,SAAO,cAAc,QAAQ,aAAa,WAAW,MAAM,IACvD,KACA;;CAGN,SAAS,eAAe,SAAoB;AAC1C,SACE,oBAAC;GAAG,gBAAa;GAAM,MAAK;GAAM,iBAAe,iBAAiB;aAChE,oBAAC;IACC,gBAAa;IACb,cAAW;IACX,MAAK;IACL,SAAS,KAAK,IAAI,aAAa,EAAE;IACjC,iBAAe;cAEf,oBAAC;KAAI,gBAAa;eAAgB;MAAc;KAC7C;IACF;;CAIT,SAAS,mBACP,QAAQ,kBACR,YAAY,YACZ;AACA,SAAO,MAAM,KAAK,EAAE,QAAQ,OAAO,GAAG,GAAG,aACvC,oBAAC;GAEC,gBAAa;GACb,oBAAiB;GACjB,MAAK;GACL,iBAAe,aAAa,SAAS;GACrC,aAAU;aAET,QAAQ,KAAK,WACZ,oBAAC;IAEC,gBAAa;IACb,YAAU,OAAO;IACjB,iBAAe,OAAO,YAAY,KAAK;IACvC,cAAY,OAAO;IACnB,MAAK;IACL,iBAAe,OAAO;IACtB,OAAO,SAAS,OAAO;cAEvB,oBAAC,gBAAc;MATV,OAAO,IAUT,CACL;KApBG,GAAG,UAAU,GAAG,WAqBlB,CACL;;CAGJ,SAAS,0BACP,QACA,UAAU,GACV;AACA,SACE,oBAAC;GAEC,gBAAa;GACb,YAAU,OAAO;GACjB,aAAU;GACV,YAAU,OAAO;GACjB,iBAAe,OAAO,YAAY,KAAK;GACvC,oBAAkB,eAAe,OAAO;GACxC,MAAK;GACL,OAAM;GACN,SAAS,UAAU,IAAI,UAAU;GACjC,UAAU;GACV,iBAAe,OAAO;GACtB,OAAO,SAAS,OAAO;aAEtB,aAAa,UAAU,kBAAkB,aACxC,oBAAC;IAAI,gBAAa;cAChB,oBAACC;KACC,cACE,UAAU,mBAAmB,QACzB,EAAE,yBAAyB,eAAe,GAC1C,EAAE,uBAAuB,aAAa;KAE5C,YAAY,UAAU,mBAAmB;KACzC,iBAAiB,UAAU,mBAAmB;KAC9C,UAAU,UAAU;MACpB;KACE,GACJ;KA3BC,OAAO,IA4BT;;CAIT,SAAS,oBACP,QACA,KACA,UACA,QACA,WACA,YACA;EACA,MAAM,YAAY,UAAW,UAAU,OAAO;EAC9C,MAAM,UACJ,OAAO,qBAAqB,aACxB,iBAAiB,IAAI,GACrB;EAEN,MAAM,WACJ,oBAACA;GACC,cAAY,EAAE,uBAAuB,aAAa;GAClD,YAAY,UAAW,WAAW,OAAO;GACzC,iBAAiB,UAAW,gBAAgB,OAAO;GACnD,YAAY,CAAC;GACb,gBAAgB,UAAW,UAAU,OAAO;IAC5C;AAGJ,SACE,oBAAC;GAEC,gBAAa;GACb,YAAU,OAAO;GACjB,aAAU;GACV,YAAU,OAAO;GACjB,iBAAe,OAAO,YAAY,KAAK;GACvC,iBAAe,YAAY,KAAK;GAChC,eAAa;GACb,YAAU,aAAa,UAAU,WAAW;GAC5C,oBAAkB,eAAe,OAAO;GACxC,eAAa,iBAAiB,QAAQ,UAAU,WAAW,WAAW;GACtE,MAAK;GACL,iBAAe,OAAO;GACtB,OAAO,SAAS,OAAO;GAQvB,gBAAgB,UAAW;GAC3B,kBAAkB,UAAW;aAE7B,oBAAC;IAAI,gBAAa;cACf,CAAC,aAAa,UACb,oBAAC;KAAgB,OAAO;eAAU;MAA2B,GAE7D;KAEE;KA9BD,OAAO,IA+BT;;CAIT,SAAS,kBACP,QACA,KACA,UACA,QACA,WACA,YACA;EACA,MAAM,QAAQ,eAAe,KAAK,UAAU,OAAO;AAEnD,SACE,oBAAC;GAEC,gBAAa;GACb,YAAU,OAAO;GACjB,aAAU;GACV,YAAU,OAAO;GACjB,iBAAe,OAAO,YAAY,KAAK;GACvC,iBAAe,YAAY,KAAK;GAChC,eAAa;GACb,YAAU,aAAa,UAAU,WAAW;GAC5C,oBAAkB,eAAe,OAAO;GACxC,eAAa,iBAAiB,QAAQ,UAAU,WAAW,WAAW;GACtE,MAAK;GACL,iBAAe,OAAO;GACtB,OAAO,SAAS,OAAO;aAEtB,YAAY,MAAM,GAAG,OACpB,oBAAC;IAAI,gBAAa;cAChB,qBAACC,2BACC,oBAAC;KAGC,UAAU;KACV,MAAM,oBAAC,aAAW;KAClB,cAAY,EAAE,wBAAwB,cAAc;KACpD,GAAI;MACJ,EACF,oBAACC;KAAK,UAAU,kBAAkB,KAAK,QAAQ,MAAM;eAClD;MACI,IACK;KACV;KA9BH,OAAO,IAgCT;;CAIT,SAAS,iBAAiB,QAA+B,UAAU,GAAG;AACpE,MAAI,OAAO,QAAQ,qBACjB,QAAO,0BAA0B,QAAQ,QAAQ;AAGnD,MAAI,OAAO,QAAQ,sBAGjB,QACE,oBAAC;GAEC,gBAAa;GACb,YAAU,OAAO;GACjB,aAAU;GACV,oBAAkB,eAAe,OAAO;GACxC,MAAK;GACL,OAAM;GACN,SAAS,UAAU,IAAI,UAAU;GACjC,UAAU;GACV,iBAAe,OAAO;GACtB,OAAO,SAAS,OAAO;KAVlB,OAAO,IAWZ;AAIN,MAAI,OAAO,QAAQ,oBAGjB,QACE,oBAAC;GAEC,gBAAa;GACb,YAAU,OAAO;GACjB,aAAU;GACV,YAAU,OAAO;GACjB,iBAAe,OAAO,YAAY,KAAK;GACvC,oBAAkB,eAAe,OAAO;GACxC,MAAK;GACL,OAAM;GACN,SAAS,UAAU,IAAI,UAAU;GACjC,UAAU;GACV,iBAAe,OAAO;GACtB,OAAO,SAAS,OAAO;KAZlB,OAAO,IAaZ;EAIN,MAAM,SAAS,OAAO;EAGtB,MAAM,cAAc,UAAU,OAAO,CAAC,KAAK,GAAG,EAAE;EAChD,MAAM,YAAY,YAAY,WAC3B,UAAU,MAAM,cAAc,OAAO,IACvC;EACD,MAAM,aAAa,cAAc,KAAK,OAAO,YAAY;EACzD,MAAM,WAAW,cAAc;EAG/B,MAAM,WAAW,YAAY,SAAS,IAAI,YAAY,IAAI;EAC1D,MAAM,aACJ,aAAa,SAAS,CAAC,OAAO,gBAAgB,OAAO,eAAe;EAItE,MAAM,YACJ,CAAC,OAAO,iBACP,OAAO,eAAe,gBACvB,kBAAkB,QAClB,qBAAqB;EAEvB,MAAM,MAA8B;GAClC,WAAW,OAAO;GAClB,aAAa,OAAO;GACpB,MAAM,YAAY,aAAa;GAC/B;GACA,YAAY;GACZ,OAAO,OAAO;GACf;EAYD,MAAM,gBAAgB,aACpB,oBAAC;GACC,gBAAa;GACb,aAAW,YAAY;GACvB,eAAa,WAAW,KAAK;GAC7B,YAAU,YAAY;GACtB,eAAY;aAEX,YAAY,cAAc,SACzB,oBAAC,wBAAsB,GAEvB,oBAAC,sBAAoB;IAEnB,GACJ;EAQJ,MAAM,qBAAqB,QAAQ,aAAa;EAChD,MAAM,YAAY,qBAAqB,OAAQ,YAAY;EAE3D,MAAM,gBAAgB,qBAAqB,gBAAgB;EAC3D,MAAM,SACJ,QAAQ,UAAU,QAAQ,gBACxB,8CACG,QAAQ,QACR,iBACA,GACD;EAEN,MAAM,YAAY,kBAAkB,OAAO;EAC3C,MAAM,UAAU,aAAa;EAC7B,MAAM,gBAAgB,sBAAsB;EAE5C,MAAM,aACJ,WAAW,CAAC,gBACV,qBAACD;GACC,QAAQ,sBAAsB,OAAO;GAGrC,WAAU;GACV,eAAe,SACb,qBAAqB,OAAO,OAAO,MAAM,KAAK;cAGhD,oBAAC;IAGC,UAAU;IACV,MAAM,oBAAC,aAAW;IAClB,cAAY,EAAE,wBAAwB,cAAc;IACpD,GAAI;IACJ,GAAI,QAAQ;KACZ,EACF,oBAACC;IACC,GAAI;IACJ,GAAI,QAAQ;IACZ,UAAU,wBAAwB,QAAQ,MAAM;cAE/C,uBACC,WACA,kBAAkB,QAAQ,YAAY,WAAW,CAClD;KACI;IACK,GACZ;EAGN,MAAM,UACJ,QAAQ,WAAW,QAAQ,aACzB,8CACG,QAAQ,SACR,cACA,GACD;EAEN,MAAM,UAAU,QAAQ,SACtB,OAAO,OAAO,IAAI,GAChB,OAAO,SAAS,QAAQ,CAAC,SAAS,OACpC,oBAAC;GACC,MAAM,QAAQ;GACH;GACX,QAAQ,QAAQ;GACR;GACR,aAAa,QAAQ;GACrB,sBAAsB,QAAQ;GAC9B,SAAS,QAAQ,WAAW;GAC5B,OAAO,QAAQ;GACN;GACT,iBAAiB,QAAQ,mBAAmB;GAK5C,sBAAsB,WAAW;GACjC,QAAQ,QAAQ;aAEf,OAAO;IACQ;EAGpB,MAAM,cAAc,kBAAkB,QAAQ,oBAAoB;AAElE,SACE,qBAAC;GAEC,WAAW,OAAO;GAGlB,WAAW;GACX,iBAAiB,eAAe,OAAO,QAAQ;GAC/C,WAAW,cAAc,kBAAkB;GAC3C,WAAW,cAAc,kBAAkB;GAC3C,WAAW;IACT,gBAAgB;IAChB,YAAY,OAAO;IACnB,YAAY,OAAO;IACnB,iBAAiB,OAAO,YAAY,KAAK;IACzC,cAAc,QAAQ,SAAS,OAAO;IACtC,iBAAiB,aAAa,KAAK;IACnC,kBAAkB,YAAY,KAAK;IACnC,oBAAoB,eAAe,OAAO;IAC1C,eAAe,WAAW,KAAK;IAC/B,kBAAkB,sBAAsB,OAAO,MAAM,KAAK;IAC1D,aAAa,SAAS,OAAO,OAAO,KAAK,SAAS;IAClD,MAAM;IACN,OAAO;IACP,SAAS,UAAU,IAAI,UAAU;IAKjC,UAAU,cAAc,WAAW,cAAc,IAAI;IACrD,iBAAiB,OAAO;IACxB,aAAa,aAAa,UAAU,WAAW,aAAa;IAC5D,iBAAiB,UAAU,SAAS;IACpC,OAAO,SAAS,OAAO;IAGvB,SAAS,4BACC,gBAAgB,cAAc,OAAO,MAAM,KAAK,GACtD;IACJ,SAAS,mBAAmB,eAAe,OAAO,IAAI,GAAG;IAGzD,eAAe,WACV,UACC,sBAAsB,QAAQ,YAAY,YAAY,MAAM,GAC9D;IACJ,WACE,cAAc,WACT,UAA8B;AAI7B,SAAI,MAAM,QAAQ,SAAS,MAAM,YAAY,SAAS;AACpD,UAAI,cACF,uBACE,QACA,YACA,YACA,MACD;WACI;AACL,aAAM,gBAAgB;AAEtB,aAAM,iBAAiB;AACvB,4BAAqB,OAAO,IAAI;;AAGlC;;AAGF,SAAI,CAAC,WAAY;AACjB,SAAI,MAAM,QAAQ,WAAW,MAAM,QAAQ,IAAK;AAEhD,WAAM,gBAAgB;AACtB,oBAAe,OAAO,IAAI;QAE5B;IACP;cAEA,SACA,YACC,oBAAC;IACS;IACR,OAAO,EAAE,0BAA0B,gBAAgB;IACnD,UAAU;IACV,aAAa;KACb,GACA;KArFC,OAAO,IAsFI;;CAItB,SAAS,WACP,QACA,KACA,UACA,QACA,WAIA,YACA,cACA;EAIA,MAAM,WAAW,gBAAgB,UAAU,WAAW,EAAE,OAAO;AAC/D,MAAI,OAAO,QAAQ,qBACjB,QAAO,oBACL,QACA,KACA,UACA,QACA,WACA,WACD;AAGH,MAAI,OAAO,QAAQ,sBACjB,QACE,oBAAC;GAEC,gBAAa;GACb,YAAU,OAAO;GACjB,aAAU;GACV,iBAAe,YAAY,KAAK;GAChC,eAAa;GACb,YAAU,aAAa,UAAU,WAAW;GAC5C,oBAAkB,eAAe,OAAO;GACxC,eAAa,iBACX,QACA,UACA,WACA,WACD;GACD,MAAK;GACL,iBAAe,OAAO;GACtB,OAAO,SAAS,OAAO;aAOtB,aAAa,OAAO,kBAAkB,WAAW;KAvB7C,OAAO,IAwBT;AAIT,MAAI,OAAO,QAAQ,oBACjB,QAAO,kBACL,QACA,KACA,UACA,QACA,WACA,WACD;EAGH,MAAM,MAA+B;GACnC;GACA;GACA;GACA,WAAW,OAAO;GAClB,aAAa,OAAO;GACpB,SAAS,UAAU,WAAW;GAI9B,YAAY,WAAW,WAAW,OAAO,IAAI;GAC7C,MAAM,cAAc,OAAO,aAAa,SAAS,GAAG;GACrD;EAED,MAAM,QAAQ,OAAO,eACjB,SACA,eAAe,QAAQ,KAAK,SAAS;EAOzC,MAAM,WAAW,OAAO,SACpB,OAAO,OAAO,OAAO,KAAK,UAAU,IAAI,GACxC,OAAO,eACL,OACA,cAAc,QAAQ,KAAK,SAAS;EAE1C,MAAM,SACJ,OAAO,aAAa,YACpB,OAAO,aAAa,YACpB,OAAO,aAAa;EAStB,MAAM,UACJ,UAAU,CAAC,OAAO,aAChB,oBAAC,sBAAU,OAAO,SAAS,GAAY,GACrC,SACF,OAAO,SAAS,GAEf;EAGL,MAAM,YAAY,cAAc,OAAO,MAAM,QAAQ,YAAY;EACjE,MAAM,iBACJ,aAAa,OAAO,QAAQ,MAAM,YAChC,qBAAC;GACC,gBAAa;GACb,OACE,EACE,gBAAgB,OAAO,UAAU,MAAM,EACxC;cAGF,UAAU,SAAS,SAAS,IAC3B,oBAAC;IACC,GAAI,cAAc;IAClB,gBAAa;IACb,UAAU;cAEV,oBAAC,iBACC,IACE,KAAK,MAAM,aAAa,IAAI,UAAU,IAAI,GACtC,WACA,UAEN;KACc,GAElB,oBAAC;IACC,gBAAa;IACb,eAAY;KACZ,EAEJ,oBAAC;IAAI,gBAAa;cAAa;KAAc;IACzC,GAEN;EAGJ,MAAM,qBACJ,OAAO,OAAO,eAAe,aACzB,OAAO,WAAW,IAAI,GACtB,OAAO;EAEb,MAAM,UAAU,OAAO,cAAc,OAAO;EAM5C,MAAM,OAAO,OAAO,cAAc,UAAU,KAAK,SAAS,GAAG;AAE7D,SACE,qBAAC;GAEC,gBAAa;GACb,YAAU,OAAO;GACjB,YAAU,OAAO;GACjB,iBAAe,OAAO,YAAY,KAAK;GACvC,cAAY,OAAO;GACnB,aAAW,OAAO,aAAa,KAAK;GACpC,aAAW,SAAS,SAAY,KAAK;GACrC,iBAAe,YAAY,KAAK;GAChC,eAAa;GACb,YAAU,aAAa,UAAU,WAAW;GAC5C,aAAW,SACT,OACA,OAAO,KACP,cAAc,OAAO,SAAS,SAC/B;GACD,oBAAkB,eAAe,OAAO;GACxC,eAAa,iBAAiB,QAAQ,UAAU,WAAW,WAAW;GACtE,sBACE,eAAe,UAAU,OAAO,IAAI,GAAG,KAAK;GAE9C,GAAK,OAAO,cACR,EAAE,OAAO,OAAgB,GACzB,EAAE,MAAM,YAAqB;GACjC,GAAI,mBAAmB,UAAU,OAAO,KAAK,WAAW;GACxD,iBAAe,OAAO;GACtB,OAAO;IACL,GAAG,SAAS,OAAO;IACnB,GAAI;IACL;GACD,GAAI,OAAO,YAAY,IAAI;cAE1B,gBACA,SAAS,SACR,oBAAC;IACC,gBAAa;IACb,IAAI;IAEJ,UAAU;IACV,cAAY,cAAc,QAAQ,KAAK,SAAS,IAAI;KACpD,GACA;KAzCC,OAAO,IA0CJ;;;;;;;;;;CAYd,SAAS,gBAAgB,KAAQ,OAAe,MAAwB;EAGtE,MAAM,SAAS,UAAU,KAAK,MAAM;AAEpC,SACE,oBAAC;GAEC,gBAAa;GACb,eAAa;GACb,MAAK;GACL,iBAAe,eAAe,OAAO,KAAK;aAEzC,QAAQ,KAAK,WACZ,WAAW,QAAQ,KAAK,OAAO,QAAQ,OAAO,KAAK,CACpD;KARI,UAAU,KAAK,GAAG,SASpB;;;CAKT,SAAS,eACP,KACA,UACA,cACA;EACA,MAAM,SAAS,WAAW,KAAK,SAAS;AAExC,SAAO,QAAQ,KAAK,WAClB,WACE,QACA,KACA,UACA,QACA,aAAa,KAAK,SAAS,GAC3B,QACA,aACD,CACF;;;;;;;CAQH,SAAS,mBAAmB,KAAQ,UAAkB;EACpD,MAAM,SAAS,WAAW,KAAK,SAAS;EACxC,MAAM,aAAa,WAAW,WAAW,OAAO,IAAI;EACpD,MAAM,MAA8B;GAClC;GACA;GACA;GACA,SAAS;GACT;GACA,MAAM,aAAa,SAAS;GAC7B;EACD,MAAM,QAAQ,cAAc,IAAI;AAEhC,SAAO;GACL,gBAAgB;GAChB,YAAY,OAAO,OAAO;GAG1B,kBAAkB;GAClB,WAAW,OAAO;GAClB,YAAY,aAAa,WAAW,MAAM,IAAI,KAAK;GACnD,eAAe,OAAO,WAAW,KAAK;GACtC,iBAAiB,aAAa,KAAK;GACnC,iBAAiB,WAAW,cAAc,OAAO,GAAG,KAAK;GACzD,MAAM;GAGN,UACE,CAAC,QAAQ,gBACL,aAAa,kBACX,IACA,KACF;GAGN,iBAAiB,WAAW,YAAY,aAAa;GACrD,iBAAiB,aAAa,SAAS;GACvC,OAAO,OAAO;GACd,QAAQ,OAAO;GACf,kBACE,eAAe,QAAQ,UAAU,KAAK,SAAS,KAAK,SAChD,KACA;GACN,SACE,eAAe,QACV,UAA2B;AAG1B,QACG,MAAM,OAAuB,QAC5B,6EACD,CAED;AAGF,gBAAY,KAAK,OAAO;OAE1B;GACN,eAAe,iBACV,UACC,mBAAmB,KAAK,UAAU,QAAQ,MAAM,GAClD;GACJ,GAAG,OAAO,YACR,OAAO,QAAQ,OAAO,QAAQ,EAAE,CAAC,CAC9B,QAAQ,GAAG,YAAY,OAAO,CAC9B,KAAK,CAAC,UAAU,CAAC,QAAQ,QAAQ,GAAG,CAAC,CACzC;GACF;;CAGH,SAAS,UAAU,KAAQ,UAAkB,YAAY,OAAO;EAC9D,MAAM,EAAE,QAAQ,GAAG,aAAa,mBAAmB,KAAK,SAAS;EACjE,MAAM,SAAS,WAAW,KAAK,SAAS;EACxC,MAAM,WAAW,MAAM,MAAM;EAC7B,MAAM,YAAY,MAAM,QAAQ;AAEhC,SACE,oBAAC;GAES;GACE;GACF;GACR,OAAO,YAAY,WAAW;GAC9B,YAAY,YAAY,YAAY,iBAAiB;GACrD,WAAW,gBAAgB,YAAY;GACvC,WAAW,gBAAgB,YAAY;GACvC,MACE,YAAY,YACR;IACE,OAAO,KAAK;IACZ,MAAM;IACN,OAAO;IACP,eAAe;IAChB,GACD;cAGJ,iBAAiB,eAAe,KAAK,UAAU,aAAa;KAnBzD,SAAS,YAoBL;;CAIf,SAAS,gBAAgB,QAAgB,UAA4B;AACnE,MAAI,UAAU,EAAG,QAAO;AAExB,SACE,oBAAC;GAAG,eAAY;GAAO,eAAa;aAClC,oBAAC;IAAG,SAAS,KAAK,IAAI,aAAa,EAAE;IAAE,OAAO,EAAE,QAAQ;KAAI;IACzD;;;;;;;;;CAWT,SAAS,mBAAmB,KAAQ,OAAe,YAAY,OAAO;EACpE,MAAM,SAAS,WAAW,KAAK,MAAM;EACrC,MAAM,UAAU,UAAU,KAAK,OAAO,UAAU;AAEhD,MAAI,CAAC,iBAAiB,CAAC,UAAW,QAAO;AAEzC,SACE,qBAAC;GACC,oBAAC;IACS;IACR,cAAa;IACF;IACE;KACb;GACD;GACA,UAAU,KAAK,SAAS,IACvB,oBAAC;IACS;IACR,cAAa;IACF;IACE;KACb,GACA;OAfS,OAAO,OAAO,OAAO,GAgBzB;;CAIf,MAAM,UAAU,KAAK,SAAS;CAQ9B,MAAM,UAAU,aAAa,WAAW,qBAAqB;CAC7D,MAAM,eACJ,aACA,qBAAqB,WACpB,CAAC,WAAW,qBAAqB;CAGpC,MAAM,YAAY,aAAa,CAAC,WAAW,qBAAqB;CAEhE,MAAM,mBACJ,CAAC,gBACD,WACA,SAAS,SACR,kBAAkB,QAChB,kBAAkB,UAAU,KAAK,SAAS;CAE/C,MAAM,UAAU,OAAO,KAAK;AAE5B,SAAQ,UAAU;CAKlB,MAAM,cAAc,eAAe;EACjC,OAAO,mBAAmB,KAAK,SAAS;EACxC,wBAAwB,YAAY;EACpC,aAAa,UACX,OAAO,UAAU,UAAU,UAAU,QAAQ,QAAQ,QAAQ,MAAM,CAAC;EACtE,qBACG,cACE,aACG,MAAM,cACN,qBAAqB,QAAQ,cAAc;EACnD,iBAAiB,YAAY,QAAQ,uBAAuB,CAAC;EAK7D;EACD,CAAC;CAMF,MAAM,iBAAiB,MAAM,MAAM,iBAAiB;AACpD,iBAAgB;AACd,MAAI,CAAC,oBAAoB,kBAAkB,QAAQ,CAAC,KAAM;EAE1D,MAAM,QAAQ,KAAK,QAAQ,WACxB,UAAU,MAAM,QAAQ,eAC1B;AACD,MAAI,SAAS,EAAG,aAAY,cAAc,OAAO,EAAE,OAAO,QAAQ,CAAC;IAClE;EAAC;EAAgB;EAAkB;EAAM;EAAY,CAAC;CAEzD,MAAM,gBAAgB,iBAAiB,WAAW;;;;;;;;;;;AAclD,qBAAoB;EAClB,WAAW,qBAAqB,CAAC,WAAW,cAAc;EAC1D,SAAS;EACV,CAAC;;;;;;;;;;;;;;;;;;CAmBF,MAAM,mBAAmB,OAAO,EAAE;CAClC,MAAM,yBAAyB,OAAsB,KAAK;AAE1D,iBAAgB;AACd,MAAI,eAAe;AACjB,0BAAuB,UAAU,KAAK;AAEtC;;EAGF,MAAM,SAAS,uBAAuB;AAEtC,MAAI,UAAU,QAAQ,KAAK,SAAS,OAClC,kBAAiB,UAAU,KAAK,SAAS;AAG3C,yBAAuB,UAAU;IAIhC,CAAC,cAAc,CAAC;CAEnB,MAAM,wBAAwB,KAAK,IAGjC,KAAK,IAAI,iBAAiB,WAAW,KAAK,UAAU,kBAAkB,EAAE,EACxE,4BACD;CAED,MAAM,CAAC,iBAAiB,sBAAsB,SAAS,EAAE;CAGzD,MAAM,CAAC,iBAAiB,sBAAsB,SAAS,MAAM;AAK7D,iBAAgB;AACd,MAAI,CAAC,gBAAiB;EAEtB,MAAM,YAAY;AAChB,OAAI,cAAe,eAAc,cAAc,UAAU;AACzD,sBAAmB,MAAM;;AAG3B,SAAO,iBAAiB,aAAa,IAAI;AACzC,SAAO,iBAAiB,iBAAiB,IAAI;AAE7C,eAAa;AACX,UAAO,oBAAoB,aAAa,IAAI;AAC5C,UAAO,oBAAoB,iBAAiB,IAAI;;IAEjD,CAAC,iBAAiB,cAAc,CAAC;CAEpC,MAAM,eAAe,UAAU,MAAmB,UAAkB;EAClE,MAAM,UAAU,KAAK,QAAQ,2BAAyB;EACtD,MAAM,MAAM,MAAM,KAChB,YAAY,SAAS,iBACnB,yDACD,IAAI,EAAE,CACR;AAED,MAAI,CAAC,IAAI,OAAQ,QAAO;EAExB,MAAM,QAAQ,UAAU,IAAI,QAAQ,QAA+B,GAAG;EACtE,MAAM,OAAO,KAAK,IAChB,KAAK,KAAK,UAAU,KAAK,kBAAkB,SAAS,OAAO,EAAE,EAC7D,IAAI,SAAS,EACd;AAED,qBAAmB,KAAK;AACxB,MAAI,OAAO,OAAO;AAElB,SAAO;GACP;CASF,MAAM,cAAc,OAAuB,KAAK;CAChD,MAAM,kBAAkB,eAAe,cAAc,CAAC;AAEtD,iBAAgB;EACd,MAAM,WAAW,YAAY;AAI7B,MAAI,CAAC,cAAc,CAAC,WAAW,iBAAiB,CAAC,cAAc,CAAC,SAC9D;EAOF,MAAM,SACJ,kBAAkB,KAAK,IAAI,WAAW,cAAc,qBAAqB;EAE3E,MAAM,WAAW,IAAI,sBAClB,YAAY;AACX,OAAI,QAAQ,MAAM,UAAU,MAAM,eAAe,CAAE,kBAAiB;KAEtE;GAAE,MAAM;GAAY,YAAY,WAAW,OAAO;GAAS,CAC5D;AAED,WAAS,QAAQ,SAAS;AAE1B,eAAa,SAAS,YAAY;IACjC;EACD;EACA;EACA;EACA;EACA;EACA;EACA,KAAK;EACN,CAAC;CAaF,MAAM,cAAc,eAAoCA,QAAM,EAC5D,WAAW,gBACZ,CAAC;CAEF,MAAM,gBAAgB,WAAW,QAAQ,mBAAmB;CAG5D,SAAS,eAAe,KAAQ,UAAkB,QAAa;AAC7D,MAAI,CAAC,QAAS,QAAO;AAErB,SAAO,QAAQ,KAAK;GAClB;GACA;GACA;GACA,SAAS;GACT,YAAY,WAAW,WAAW,OAAO,IAAI;GAC7C,WAAW;GACX,cAAc;GACf,CAAC;;CAGJ,SAAS,kBAAkB,KAAQ,QAAa,YAAqB;AACnE,UAAQ,WAAgB;AACtB,qBAAkB,oBAAoB,OAAO,EAAE,KAAK,OAAO;AAM3D,OAAI,WAAY,aAAY,OAAO;;;CAIvC,MAAM,qBAAqB,UAEvB,KACA,UACA,QACA,UACG;EACH,MAAM,QAAQ,eAAe,KAAK,UAAU,OAAO;AAInD,MAAI,YAAY,MAAM,CAAE;AAExB,QAAM,gBAAgB;AACtB,cAAY,KACV;GAAE,UAAU;GAAO,UAAU,kBAAkB,KAAK,QAAQ,KAAK;GAAE,EACnE,QAGA,aAAa,MAAM,cACd,MAAM,cACP,OACL;GAEJ;CASD,SAAS,kBAAkB,QAAiD;AAC1E,MAAI,sBAAsB,SAAS,OAAO,aAAc,QAAO;EAE/D,MAAM,QAAQ,OAAO,QAAQ;AAE7B,SAAO,YAAY,MAAM,GAAG,OAAO;;;CAIrC,SAAS,kBACP,QACA,YACA,YACuB;AACvB,SAAO;GACL;GACA,MAAM,YAAY,aAAa;GAC/B,qBAAqB,OAAO,wBAAwB;GACpD,QAAQ;IACN,YAAY,EAAE,2BAA2B,iBAAiB;IAC1D,aAAa,EAAE,4BAA4B,kBAAkB;IAC7D,cAAc,EAAE,uBAAuB,aAAa;IACrD;GACF;;CAGH,SAAS,wBACP,QACA,YACA;AACA,UAAQ,WAAgB;GACtB,MAAM,aAAa,oBAAoB,OAAO;AAI9C,OAAI,oBAAoB,WAAW,CACjC,sBACE,OAAO,KACP,2BAA2B,YAC5B;AAGH,UAAO,QAAQ,eAAe,WAAW;AACzC,wBAAqB,YAAY,OAAO,IAAI;AAI5C,OAAI,WAAY,aAAY,OAAO;;;CAIvC,MAAM,wBAAwB,UAE1B,QACA,YACA,YACA,UACG;EACH,MAAM,QAAQ,kBAAkB,OAAO;AAEvC,MAAI,SAAS,KAAM;AAEnB,QAAM,gBAAgB;AAEtB,QAAM,iBAAiB;AACvB,cAAY,KACV;GACE,GAAG;GACH,GAAG,OAAO,QAAQ;GAClB,UAAU,uBACR,OACA,kBAAkB,QAAQ,YAAY,WAAW,CAClD;GACD,UAAU,wBAAwB,QAAQ,KAAK;GAChD,EACD,QACA,aAAa,MAAM,cACd,MAAM,cACP,OACL;GAEJ;;CAGD,SAAS,aAAa,QAA4B;EAChD,MAAM,UAAW,QAA+B,UAC9C,qCACD;AAED,MAAI,CAAC,QAAS,QAAO;EAErB,MAAM,QAAQ,OAAO,QAAQ,aAAa,iBAAiB,CAAC;AAE5D,MAAI,CAAC,OAAO,UAAU,MAAM,CAAE,QAAO;EAErC,MAAM,MAAM,KAAK;AAEjB,SAAO,QAAQ,SACX,OACA;GAAE;GAAK;GAAO,KAAK,WAAW,KAAK,MAAM;GAAE;;CAGjD,MAAM,eAAe,mBAAmB,YAAY,iBAAiB,GAAG,EAAE;CAC1E,MAAM,aAAa,aAAa,SAAS,aAAa,GAAG,QAAQ;CACjE,MAAM,gBAAgB,aAAa,SAC/B,YAAY,cAAc,GAAG,aAAa,aAAa,SAAS,GAAG,MACnE;CAEJ,MAAM,WACJ,oBAAC,wBACE,QAAQ,KAAK,WACZ,oBAAC,SAEC,OAAO,OAAO,SAAS,OAAO,EAAE,OAAO,OAAO,OAAO,GAAG,UADnD,OAAO,IAEZ,CACF,GACO;CAGb,SAAS,iBACP,MACA,OACA,OACA;AACA,OAAK,IAAI,QAAQ,GAAG,SAAS,OAAO,QAClC,KAAI,KAAK,QAAQ,QAAQ,MAAM,QAAQ,IAAK,QAAO;AAGrD,SAAO;;CAGT,SAAS,sBACP,OACA,SACA,OACA;EACA,MAAM,QAAQ,QAAQ;EACtB,MAAM,OAAO,QAAQ,QAAQ,SAAS;EACtC,MAAM,MAAM,QAAQ,OAAO,WAAW,OAAO,QAAQ,MAAM,IAAI,GAC3D,MAAM,MACN;EACJ,MAAM,YACJ,QAAQ,UAAU,MAAM,YAAY,QAAQ,QAAQ,KAAK,YAAY;AAEvE,SACE,oBAAC;GAEC,gBAAa;GACb,YAAU,MAAM;GAChB,YAAU;GACV,iBACE,QAAQ,MAAM,WAAW,OAAO,UAAU,GAAG,KAAK;GAEpD,oBAAkB,KAAK,UAAU,cAAc,IAAI,KAAK;GACxD,cAAW;GACX,MAAK;GACL,OAAM;GACN,UAAU;GACV,iBAAe,MAAM;GACrB,SAAS,QAAQ;GACjB,OACE,aAAa,OACT,SACA,GAAG,iBAAwB,GAAG,UAAU,KAAK;aAGnD,oBAAC,6BAAiB,MAAM,QAAwB;KApB3C,GAAG,MAAM,GAAG,MAAM,IAAI,GAAG,MAAM,MAqBjC;;CAIT,SAAS,qBAAqB,OAAe;EAC3C,MAAM,QAAqB,EAAE;AAE7B,OAAK,IAAI,cAAc,GAAG,cAAc,QAAQ,SAAU;GACxD,MAAM,SAAS,QAAQ;GACvB,MAAM,OAAO,mBAAmB,IAAI,OAAO,IAAI,IAAI,EAAE;AAGrD,OAAI,KAAK,SAAS,OAAO;AACvB;AACA;;AAGF,OAAI,KAAK,WAAW,OAAO;AACzB,UAAM,KAAK,iBAAiB,QAAQ,iBAAiB,MAAM,CAAC;AAC5D;AACA;;GAGF,IAAI,aAAa,cAAc;AAE/B,UAAO,aAAa,QAAQ,QAAQ;IAClC,MAAM,WAAW,mBAAmB,IAAI,QAAQ,YAAY,IAAI,IAAI,EAAE;AAEtE,QACE,SAAS,UAAU,SACnB,QAAQ,YAAY,QAAQ,OAAO,OACnC,CAAC,iBAAiB,MAAM,UAAU,MAAM,CAExC;AAGF;;AAGF,SAAM,KACJ,sBACE,KAAK,QACL,QAAQ,MAAM,aAAa,WAAW,EACtC,MACD,CACF;AACD,iBAAc;;AAGhB,SAAO;;CAGT,MAAM,aAAa,iBACf,OACA,MAAM,KAAK,EAAE,QAAQ,gBAAgB,GAAG,GAAG,UAAU;EACnD,MAAM,YAAY,UAAU,iBAAiB;AAE7C,SACE,oBAAC;GAEC,gBAAa;GACb,MAAK;GACL,iBAAe,QAAQ;GACvB,KAAK,YAAY,aAAa;GAC9B,GAAK,YAAY,sBAAsB;GACvC,kBACE,aACK,UAAU;AAIT,QACG,MAAM,QAAwB,UAC7B,6BACD,CAED;AAGF,IAAC,qBAA6B,mBAAmB,MAAM;OAEzD;aAGL,qBAAqB,MAAM;KAzBvB,MA0BF;GAEP;CAEN,MAAM,aAAa;EACjB,gBAAgB;EAChB,MAAM,OAAO,aAAa;EAC1B,cAAc;EACd,aAAa,aAAa;EAC1B,iBACE,iBAAiB,iBAAiB,eAAe;EACnD,iBAAiB;EACjB,wBACE,WAAW,kBAAkB,aAAa,OAAO;EACpD;CAED,IAAI;AAEJ,KAAI,SAAS,KACX,eAAc,eAAe,MAAM;UAC1B,aACT,eAAc,oBAAoB;UACzB,UACT,eAAc;UACL,CAAC,QACV,eAAc,eAAe,aAAa,iBAAiB,WAAW;UAC7D,iBACT,eACE;EACG,gBAAgB,YAAY,MAAM;EAClC,aAAa,KAAK,MACjB,mBAAmB,KAAK,EAAE,QAAQ,EAAE,OAAO,KAAK,CACjD;EACA,gBAAgB,eAAe,SAAS;KACxC;KAGL,eAAc,KAAK,KAAK,KAAK,UAAU,mBAAmB,KAAK,MAAM,CAAC;CAGxE,MAAM,eACJ;EACG;EACA,iBAAiB,OAAO,oBAAC;GAAM,gBAAa;aAAQ;IAAmB;EACxE,qBAAC;GAAM,gBAAa;GAAO,GAAI;GAAiB,KAAK;;IAClD,eAAe,KAAK,KAAK,UAAU,gBAAgB,KAAK,OAAO,MAAM,CAAC;IACtE;IACA,kBAAkB,KAAK,KAAK,UAC3B,gBAAgB,KAAK,OAAO,SAAS,CACtC;IACA,gBACG,mBAAmB,uBAAuB,YAAY,GACtD;IACH,cAAc,UACb,oBAAC;KAAG,iBAAc;KAAG,eAAY;eAC/B,oBAAC;MACC,SAAS,KAAK,IAAI,aAAa,EAAE;MACjC,OAAO;OAAE,QAAQ;OAAG,SAAS;OAAG,QAAQ;OAAG;gBAE3C,oBAAC;OAAI,KAAK;OAAa,OAAO,EAAE,QAAQ,GAAG;QAAI;OAC5C;MACF,GACH;;IACE;KACP;AAaL,KAAI,gBAAgB,KAAK,UACvB,QACE,qBAAC;EACC,KAAK;EACL,IAAI,MAAM;EACV,QAAQ;EACR,MAAM;GAAE;GAAM;GAAO,GAAG;GAAM;aAE7B,SACD,oBAAC;GAAI,gBAAa;GAAW,KAAK;aAChC,oBAAC,YAAS,QAAO,UAAU;IACvB;GACO;AAInB,QACE,qBAAC;EACC,KAAK;EACL,IAAI,MAAM;EACV,QAAQ;EACR,MAAM;GACJ;GACA;GACA,iBAAiB;GACjB,mBAAmB;GACnB,kBAAkB;GAGlB,cAAc,UAAU;GACxB,YAAY,cAAc;GAC1B,YAAY,cAAc;GAC1B,OAAO;GACP,GAAG;GACJ;;GAEA;GACD,oBAAC;IACC,gBAAa;IACb,KAAK;IAGL,UAAU,eAAe,YAAY,KAAK;IAG1C,YAAY,UAAU;AAGpB,SAAI,MAAM,QAAQ,SAAS,MAAM,YAAY,eAAe;MAC1D,MAAM,QAAQ,aAAa,MAAM,OAAO;AAExC,UAAI,OAAO;AACT,aAAM,iBAAiB;AACvB,0BAAmB,MAAM,KAAK,MAAM,OAAO,MAAM,KAAK,MAAM;;AAG9D;;AAGF,SAAI,MAAM,QAAQ,WAAW,aAAa;MACxC,MAAM,QAAQ,aAAa,MAAM,OAAO;AAGxC,UACE,SACA,CAAE,MAAM,OAAuB,QAC7B,wDACD,CAED,aAAY,MAAM,KAAK,MAAM,IAAI;AAGnC;;AAGF,SACE,CAAC,QACD,kBACC,MAAM,QAAQ,eAAe,MAAM,QAAQ,YAC5C;AAGA,UAAI,WAAW,cAAc,KAAM;AAEnC,UACE,aACE,MAAM,QACN,MAAM,QAAQ,cAAc,IAAI,GACjC,CAED,OAAM,gBAAgB;AAGxB;;AAGF,SAAI,MAAM,QAAQ,UAAU;AAC1B,UAAI,eAAe,OAAO;AACxB,aAAM,iBAAiB;AACvB,qBAAc,OAAO;AAErB;;AAGF,UAAI,WAAW,aAAa,UAAU,gBAAgB,GAAG;AACvD,aAAM,iBAAiB;AACvB,iBAAU,gBAAgB;;;;IAShC,SAAS,UAAU;AACjB,SAAI,CAAC,eAAe,MAAO;KAE3B,MAAM,SAAS,cAAc,oBAC1B,QAAQ,KAAK,aACZ,OAAO,eACH,KACA,cAAc,QAAQ,KAAK,SAAS,IAAI,GAC/C;AAED,SAAI,CAAC,OAAO,OAAQ;AAKpB,WAAM,gBAAgB;AACtB,WAAM,cAAc,QAAQ,cAAc,MAAM,OAAO,CAAC;AACxD,WAAM,cAAc,QAAQ,aAAa,gBAAgB,OAAO,CAAC;AAMjE,WAAM,QAAQ;MACZ,OAAO,EAAE,+BAA+B,sBAAsB;MAC9D,aAAa,EAAE,yBAAyB,0BAA0B,EAChE,OAAO,cAAc,WACtB,CAAC;MACH,CAAC;;cAGH,OACC,oBAAC;KACO;KACM;KACZ,OACE,OAAO,cAAc,OACjB,EAAE,OAAO,OAAO,YAAY,GAC5B;eAGL;MACa,GAEhB,oBAAC;KACC,GAAI;KACJ,OACE,OAAO,cAAc,OACjB,EAAE,OAAO,OAAO,YAAY,GAC5B;eAGL;MACK;KAEN;GAYN,oBAAC,4BACC,oBAAC;IAAK,MAAK;cACR,UAAU,EAAE,wBAAwB,aAAa,GAAG;KAChD,GACQ;GAChB;GACA,YAAY;GACZ,MAAM,QAAQ,KAAK,QAAQ,UAK1B,oBAAC,uBAAwC,UAAf,MAAyB,CACnD;GACD;;GACY"}
|