@lavalogic/scoria 0.36.0 → 0.37.1
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/Components/AccordionGroup.svelte +6 -2
- package/dist/Components/AccordionGroupButton.svelte +78 -78
- package/dist/Components/AccordionGroupButtonProps.d.ts +27 -8
- package/dist/Components/AccordionGroupProps.d.ts +10 -2
- package/dist/Components/Action.svelte +31 -33
- package/dist/Components/ActionProps.d.ts +23 -3
- package/dist/Components/AlertModal.svelte +90 -39
- package/dist/Components/AppointmentCalendar/AppointmentCalendar.svelte +1126 -0
- package/dist/Components/AppointmentCalendar/AppointmentCalendar.svelte.d.ts +4 -0
- package/dist/Components/AppointmentCalendar/AppointmentCalendarProps.d.ts +92 -0
- package/dist/Components/AppointmentCalendar/AppointmentCalendarProps.js +12 -0
- package/dist/Components/Base/BaseModal.svelte +172 -0
- package/dist/Components/Base/BaseModal.svelte.d.ts +4 -0
- package/dist/Components/Base/BaseModalProps.d.ts +73 -0
- package/dist/Components/Base/BaseModalProps.js +1 -0
- package/dist/Components/Base/ContextWrapper.svelte +37 -15
- package/dist/Components/Base/ContextWrapper.svelte.d.ts +24 -5
- package/dist/Components/Base/ContextWrapperProps.d.ts +22 -0
- package/dist/Components/Base/Pagination.svelte +70 -62
- package/dist/Components/Base/Pagination.svelte.d.ts +12 -2
- package/dist/Components/Base/PaginationProps.d.ts +60 -3
- package/dist/Components/Base/Snippets.svelte +7 -0
- package/dist/Components/Base/Snippets.svelte.d.ts +5 -1
- package/dist/Components/BigRadioSet.svelte +18 -9
- package/dist/Components/BigRadioSetProps.d.ts +17 -1
- package/dist/Components/Bubble.svelte +67 -34
- package/dist/Components/Bubble.svelte.d.ts +23 -2
- package/dist/Components/BubbleProps.d.ts +55 -4
- package/dist/Components/Button.svelte +50 -38
- package/dist/Components/ButtonProps.d.ts +66 -1
- package/dist/Components/Checkbox.svelte +57 -29
- package/dist/Components/Checkbox.svelte.d.ts +1 -12
- package/dist/Components/CheckboxProps.d.ts +27 -0
- package/dist/Components/CheckboxProps.js +1 -0
- package/dist/Components/CollapsibleCard.svelte +53 -22
- package/dist/Components/CollapsibleCardProps.d.ts +22 -1
- package/dist/Components/Contexts/ContextMenu.svelte +53 -32
- package/dist/Components/Contexts/ContextMenu.svelte.d.ts +26 -0
- package/dist/Components/Contexts/ContextMenuDivider.svelte +15 -7
- package/dist/Components/Contexts/ContextMenuDivider.svelte.d.ts +9 -0
- package/dist/Components/Contexts/ContextMenuOption.svelte +27 -18
- package/dist/Components/Contexts/ContextMenuOption.svelte.d.ts +12 -1
- package/dist/Components/Contexts/ContextMenuOptionProps.d.ts +34 -2
- package/dist/Components/Contexts/Toast.svelte +28 -4
- package/dist/Components/Contexts/Toast.svelte.d.ts +14 -0
- package/dist/Components/Contexts/ToastContainer.svelte +30 -11
- package/dist/Components/Contexts/ToastContainer.svelte.d.ts +14 -0
- package/dist/Components/Contexts/ToastProps.d.ts +14 -1
- package/dist/Components/Contexts/Tooltip.svelte +21 -10
- package/dist/Components/Contexts/Tooltip.svelte.d.ts +10 -0
- package/dist/Components/DataMatrixIcon.svelte +82 -11
- package/dist/Components/DataMatrixIconProps.d.ts +73 -1
- package/dist/Components/DateInput.svelte +64 -29
- package/dist/Components/DateInput.svelte.d.ts +1 -1
- package/dist/Components/DateOnlyInputProps.d.ts +31 -5
- package/dist/Components/DatePicker.svelte +96 -108
- package/dist/Components/DatePickerProps.d.ts +18 -1
- package/dist/Components/DateTimeInputProps.d.ts +30 -5
- package/dist/Components/DesktopModal.svelte +14 -43
- package/dist/Components/DesktopModalProps.d.ts +5 -4
- package/dist/Components/Dial.svelte +103 -41
- package/dist/Components/DialProps.d.ts +74 -2
- package/dist/Components/DimensionInput.svelte +50 -64
- package/dist/Components/DimensionInput.svelte.d.ts +1 -1
- package/dist/Components/DimensionInputProps.d.ts +39 -4
- package/dist/Components/DragMenu/DragMenuHolder.svelte +41 -29
- package/dist/Components/DragMenu/DragMenuHolderProps.d.ts +30 -1
- package/dist/Components/DragMenu/DraggableCard.svelte +44 -8
- package/dist/Components/DragMenu/DraggableCardProps.d.ts +27 -1
- package/dist/Components/FileCard.svelte +6 -2
- package/dist/Components/FileCardProps.d.ts +17 -1
- package/dist/Components/FileUpload.svelte +82 -42
- package/dist/Components/FileUploadProps.d.ts +34 -4
- package/dist/Components/GridInput.svelte +27 -17
- package/dist/Components/GridInput.svelte.d.ts +5 -5
- package/dist/Components/GridInputProps.d.ts +4 -1
- package/dist/Components/GridInputSet.svelte +12 -5
- package/dist/Components/GridInputSet.svelte.d.ts +5 -5
- package/dist/Components/GridInputSetProps.d.ts +4 -2
- package/dist/Components/HorizontalTabGroup.svelte +13 -11
- package/dist/Components/HorizontalTabGroupButton.svelte +16 -68
- package/dist/Components/HorizontalTabGroupProps.d.ts +15 -2
- package/dist/Components/Icon.svelte +62 -21
- package/dist/Components/IconProps.d.ts +54 -6
- package/dist/Components/Icons.d.ts +8 -0
- package/dist/Components/Icons.js +234 -215
- package/dist/Components/LoadingAnimation.svelte +18 -18
- package/dist/Components/LoadingAnimation.svelte.d.ts +1 -3
- package/dist/Components/LoadingAnimationProps.d.ts +16 -0
- package/dist/Components/LoadingAnimationProps.js +1 -0
- package/dist/Components/LoadingModal.svelte +18 -20
- package/dist/Components/LoadingModal.svelte.d.ts +1 -4
- package/dist/Components/LoadingModalProps.d.ts +17 -0
- package/dist/Components/LoadingModalProps.js +1 -0
- package/dist/Components/LoadingOverlay.svelte +11 -13
- package/dist/Components/LoadingOverlay.svelte.d.ts +1 -5
- package/dist/Components/LoadingOverlayProps.d.ts +28 -0
- package/dist/Components/LoadingOverlayProps.js +1 -0
- package/dist/Components/Modal.svelte +77 -82
- package/dist/Components/Modal.svelte.d.ts +1 -25
- package/dist/Components/ModalProps.d.ts +65 -0
- package/dist/Components/ModalProps.js +1 -0
- package/dist/Components/MultiSelect.svelte +88 -76
- package/dist/Components/MultiSelectCommonProps.d.ts +33 -4
- package/dist/Components/MultiSelectPropsAsObject.d.ts +5 -0
- package/dist/Components/MultiSelectPropsAsPrimitive.d.ts +6 -0
- package/dist/Components/Nav/CallbackButtonWithIcon.d.ts +22 -1
- package/dist/Components/Nav/Nav.svelte +35 -30
- package/dist/Components/Nav/Nav.svelte.d.ts +23 -2
- package/dist/Components/Nav/NavProps.d.ts +50 -3
- package/dist/Components/Nav/NavServiceMenuList.svelte +12 -3
- package/dist/Components/Nav/NavServiceMenuListProps.d.ts +25 -1
- package/dist/Components/Nav/NavTab.svelte +19 -48
- package/dist/Components/Nav/NavTab.svelte.d.ts +23 -2
- package/dist/Components/Nav/NavTabProps.d.ts +16 -2
- package/dist/Components/Nav/ServiceMenuItem.svelte +29 -20
- package/dist/Components/Nav/ServicesNav.svelte +60 -34
- package/dist/Components/Nav/ServicesNav.svelte.d.ts +23 -2
- package/dist/Components/Nav/ServicesNavProps.d.ts +20 -4
- package/dist/Components/Nav/SideMenuItemProps.d.ts +16 -0
- package/dist/Components/NumberInput.svelte +37 -27
- package/dist/Components/NumberInputProps.d.ts +37 -0
- package/dist/Components/PageHeading.svelte +2 -13
- package/dist/Components/PageHeading.svelte.d.ts +1 -6
- package/dist/Components/PageHeadingProps.d.ts +23 -0
- package/dist/Components/PageHeadingProps.js +1 -0
- package/dist/Components/PasswordInput.svelte +27 -15
- package/dist/Components/PasswordInput.svelte.d.ts +2 -2
- package/dist/Components/PasswordInputProps.d.ts +21 -0
- package/dist/Components/PasswordInputProps.js +1 -0
- package/dist/Components/Portal.svelte +14 -3
- package/dist/Components/PortalProps.d.ts +20 -1
- package/dist/Components/ProgressBubble.svelte +98 -53
- package/dist/Components/ProgressBubbleProps.d.ts +23 -2
- package/dist/Components/QuerySelect.svelte +103 -159
- package/dist/Components/QuerySelect.svelte.d.ts +2 -29
- package/dist/Components/QuerySelectProps.d.ts +66 -0
- package/dist/Components/QuerySelectProps.js +1 -0
- package/dist/Components/SingleSelect.svelte +86 -108
- package/dist/Components/SingleSelectCommonProps.d.ts +43 -5
- package/dist/Components/SingleSelectPropsAsObject.d.ts +7 -0
- package/dist/Components/SingleSelectPropsAsPrimitive.d.ts +8 -0
- package/dist/Components/StepButton.svelte +19 -69
- package/dist/Components/StepForm.svelte +52 -52
- package/dist/Components/StepFormProps.d.ts +16 -2
- package/dist/Components/Switch.svelte +68 -31
- package/dist/Components/Switch.svelte.d.ts +1 -1
- package/dist/Components/SwitchProps.d.ts +46 -0
- package/dist/Components/Table/Body/HeightData.d.ts +1 -6
- package/dist/Components/Table/Body/HeightData.js +8 -0
- package/dist/Components/Table/Body/QuickSearchCell.svelte +106 -50
- package/dist/Components/Table/Body/QuickSearchCell.svelte.d.ts +12 -11
- package/dist/Components/Table/Body/QuickSearchCellProps.d.ts +6 -0
- package/dist/Components/Table/Body/Rows/ColumnHighlight.svelte +43 -9
- package/dist/Components/Table/Body/Rows/ColumnHighlight.svelte.d.ts +24 -2
- package/dist/Components/Table/Body/Rows/ColumnHighlightProps.d.ts +3 -0
- package/dist/Components/Table/Body/Rows/ColumnList.svelte +15 -5
- package/dist/Components/Table/Body/Rows/ColumnList.svelte.d.ts +12 -11
- package/dist/Components/Table/Body/Rows/ColumnListProps.d.ts +1 -0
- package/dist/Components/Table/Body/Rows/ColumnListRow.svelte +437 -91
- package/dist/Components/Table/Body/Rows/ColumnListRow.svelte.d.ts +12 -11
- package/dist/Components/Table/Body/Rows/ColumnListRowProps.d.ts +5 -0
- package/dist/Components/Table/Body/Rows/Columns/AccessorComponent.svelte +43 -13
- package/dist/Components/Table/Body/Rows/Columns/AccessorComponentProps.d.ts +12 -0
- package/dist/Components/Table/Body/Rows/Columns/ActionsCell.svelte +50 -38
- package/dist/Components/Table/Body/Rows/Columns/ActionsCell.svelte.d.ts +12 -12
- package/dist/Components/Table/Body/Rows/Columns/ActionsColumn.d.ts +9 -0
- package/dist/Components/Table/Body/Rows/Columns/ActionsTableCell.d.ts +5 -0
- package/dist/Components/Table/Body/Rows/Columns/BubbleCell.svelte +61 -26
- package/dist/Components/Table/Body/Rows/Columns/BubbleCell.svelte.d.ts +14 -13
- package/dist/Components/Table/Body/Rows/Columns/BubbleCellProps.d.ts +12 -0
- package/dist/Components/Table/Body/Rows/Columns/BubbleCellProps.js +1 -0
- package/dist/Components/Table/Body/Rows/Columns/ExpandCell.svelte +36 -16
- package/dist/Components/Table/Body/Rows/Columns/FocusableImmutableCell.svelte +133 -26
- package/dist/Components/Table/Body/Rows/Columns/FocusableImmutableCell.svelte.d.ts +12 -11
- package/dist/Components/Table/Body/Rows/Columns/FocusableImmutableCellProps.d.ts +7 -0
- package/dist/Components/Table/Body/Rows/Columns/ProgressCell.svelte +54 -20
- package/dist/Components/Table/Body/Rows/Columns/ProgressCell.svelte.d.ts +17 -11
- package/dist/Components/Table/Body/Rows/Columns/RowSelectionColumn.d.ts +8 -0
- package/dist/Components/Table/Body/Rows/Columns/RowSelectionTableCell.d.ts +5 -0
- package/dist/Components/Table/Body/Rows/Columns/SelectColumn.d.ts +11 -0
- package/dist/Components/Table/Body/Rows/Columns/SelectTableCell.d.ts +11 -0
- package/dist/Components/Table/Body/Rows/Columns/TableAction.svelte +55 -40
- package/dist/Components/Table/Body/Rows/Columns/TableAction.svelte.d.ts +11 -0
- package/dist/Components/Table/Body/Rows/Columns/TableCheckbox.svelte +38 -27
- package/dist/Components/Table/Body/Rows/Columns/TableCheckbox.svelte.d.ts +13 -18
- package/dist/Components/Table/Body/Rows/Columns/TableCheckboxProps.d.ts +17 -0
- package/dist/Components/Table/Body/Rows/Columns/TableCheckboxProps.js +1 -0
- package/dist/Components/Table/Body/Rows/Columns/TableColumn.svelte +22 -7
- package/dist/Components/Table/Body/Rows/Columns/TableColumn.svelte.d.ts +1 -7
- package/dist/Components/Table/Body/Rows/Columns/TableColumnProps.d.ts +16 -0
- package/dist/Components/Table/Body/Rows/Columns/TableColumnProps.js +1 -0
- package/dist/Components/Table/Body/Rows/Columns/TableDatePicker.svelte +61 -31
- package/dist/Components/Table/Body/Rows/Columns/TableDatePicker.svelte.d.ts +12 -11
- package/dist/Components/Table/Body/Rows/Columns/TableDatePickerProps.d.ts +9 -0
- package/dist/Components/Table/Body/Rows/Columns/TableNumberInput.svelte +123 -244
- package/dist/Components/Table/Body/Rows/Columns/TableNumberInput.svelte.d.ts +20 -12
- package/dist/Components/Table/Body/Rows/Columns/TableQueryCell.d.ts +8 -0
- package/dist/Components/Table/Body/Rows/Columns/TableQueryColumn.d.ts +9 -0
- package/dist/Components/Table/Body/Rows/Columns/TableQuerySelect.svelte +126 -189
- package/dist/Components/Table/Body/Rows/Columns/TableQuerySelect.svelte.d.ts +12 -11
- package/dist/Components/Table/Body/Rows/Columns/TableQuerySelectProps.d.ts +8 -0
- package/dist/Components/Table/Body/Rows/Columns/TableRowSelectionCheckbox.svelte +31 -19
- package/dist/Components/Table/Body/Rows/Columns/TableRowSelectionCheckbox.svelte.d.ts +2 -5
- package/dist/Components/Table/Body/Rows/Columns/TableRowSelectionCheckboxProps.d.ts +14 -0
- package/dist/Components/Table/Body/Rows/Columns/TableRowSelectionCheckboxProps.js +1 -0
- package/dist/Components/Table/Body/Rows/Columns/TableSelect.svelte +125 -187
- package/dist/Components/Table/Body/Rows/Columns/TableSelect.svelte.d.ts +13 -12
- package/dist/Components/Table/Body/Rows/Columns/TableSelectProps.d.ts +6 -0
- package/dist/Components/Table/Body/Rows/Columns/TableTextInput.svelte +119 -270
- package/dist/Components/Table/Body/Rows/Columns/TableTextInput.svelte.d.ts +12 -11
- package/dist/Components/Table/Body/Rows/Columns/TableTextInputProps.d.ts +6 -0
- package/dist/Components/Table/Body/Rows/Columns/ValidityCell.svelte +46 -23
- package/dist/Components/Table/Body/Rows/Columns/_helpers/useAsyncEditable.svelte.d.ts +104 -0
- package/dist/Components/Table/Body/Rows/Columns/_helpers/useAsyncEditable.svelte.js +215 -0
- package/dist/Components/Table/Body/Rows/TableRow.svelte +200 -132
- package/dist/Components/Table/Body/Rows/TableRow.svelte.d.ts +2 -10
- package/dist/Components/Table/Body/Rows/TableRowProps.d.ts +11 -2
- package/dist/Components/Table/Body/TableBody.svelte +170 -53
- package/dist/Components/Table/Body/TableBody.svelte.d.ts +15 -22
- package/dist/Components/Table/Body/TableBodyProps.d.ts +9 -7
- package/dist/Components/Table/ColumnDefinitions/ExampleItemColumnDefRepository.svelte.d.ts +2 -2
- package/dist/Components/Table/ColumnDefinitions/ExampleItemColumnDefRepository.svelte.js +18 -12
- package/dist/Components/Table/ColumnFactory.svelte.d.ts +43 -0
- package/dist/Components/Table/ColumnFactory.svelte.js +339 -0
- package/dist/Components/Table/Headers/HighlightAllHeader.svelte +5 -3
- package/dist/Components/Table/Headers/HighlightAllHeader.svelte.d.ts +12 -11
- package/dist/Components/Table/Headers/SelectAllHeader.svelte +5 -3
- package/dist/Components/Table/Headers/SelectAllHeader.svelte.d.ts +12 -11
- package/dist/Components/Table/Headers/TableHead.svelte +340 -200
- package/dist/Components/Table/Headers/TableHead.svelte.d.ts +13 -16
- package/dist/Components/Table/Headers/TableHeadProps.d.ts +10 -0
- package/dist/Components/Table/Headers/TableHeadProps.js +1 -0
- package/dist/Components/Table/Misc/ColumnPanel.svelte +108 -50
- package/dist/Components/Table/Misc/ColumnPanel.svelte.d.ts +12 -11
- package/dist/Components/Table/Misc/ColumnPanelModal.svelte +20 -7
- package/dist/Components/Table/Misc/ColumnPanelModal.svelte.d.ts +12 -11
- package/dist/Components/Table/Misc/ColumnPanelModalProps.d.ts +5 -0
- package/dist/Components/Table/Misc/FilterInput.svelte +30 -41
- package/dist/Components/Table/Misc/FilterInput.svelte.d.ts +12 -11
- package/dist/Components/Table/Misc/FilterPanel.svelte +387 -29
- package/dist/Components/Table/Misc/FilterPanel.svelte.d.ts +12 -11
- package/dist/Components/Table/Misc/FilterPanelModal.svelte +4 -51
- package/dist/Components/Table/Misc/FilterPanelModal.svelte.d.ts +2 -23
- package/dist/Components/Table/Misc/SidePanel.svelte +12 -9
- package/dist/Components/Table/Misc/SidePanel.svelte.d.ts +1 -7
- package/dist/Components/Table/Misc/SidePanelProps.d.ts +17 -0
- package/dist/Components/Table/Misc/SidePanelProps.js +1 -0
- package/dist/Components/Table/Misc/TableFooter.svelte +44 -35
- package/dist/Components/Table/Misc/TableFooter.svelte.d.ts +13 -14
- package/dist/Components/Table/Misc/TableFooterProps.d.ts +8 -0
- package/dist/Components/Table/Misc/TableFooterProps.js +1 -0
- package/dist/Components/Table/Misc/TableHorizontalBar.svelte +17 -48
- package/dist/Components/Table/Misc/TableHorizontalBar.svelte.d.ts +12 -11
- package/dist/Components/Table/Misc/TableSidebar.svelte +28 -47
- package/dist/Components/Table/Misc/TableSidebar.svelte.d.ts +12 -11
- package/dist/Components/Table/Misc/ToolboxPanel.svelte +121 -55
- package/dist/Components/Table/Misc/ToolboxPanel.svelte.d.ts +12 -11
- package/dist/Components/Table/Misc/ToolboxPanelModal.svelte +31 -24
- package/dist/Components/Table/Misc/ToolboxPanelModal.svelte.d.ts +12 -11
- package/dist/Components/Table/Misc/ToolboxPanelModalProps.d.ts +5 -0
- package/dist/Components/Table/Misc/numberDateFilterTypes.d.ts +7 -4
- package/dist/Components/Table/Misc/numberDateFilterTypes.js +8 -3
- package/dist/Components/Table/Misc/stringFilterTypes.d.ts +6 -4
- package/dist/Components/Table/Misc/stringFilterTypes.js +7 -3
- package/dist/Components/Table/NestedTable.svelte +85 -41
- package/dist/Components/Table/NestedTable.svelte.d.ts +2 -10
- package/dist/Components/Table/NestedTableProps.d.ts +25 -0
- package/dist/Components/Table/NestedTableProps.js +1 -0
- package/dist/Components/Table/SubApis.svelte.d.ts +24 -0
- package/dist/Components/Table/SubApis.svelte.js +380 -0
- package/dist/Components/Table/Table.svelte +345 -172
- package/dist/Components/Table/Table.svelte.d.ts +24 -1
- package/dist/Components/Table/TableHelpers.svelte.d.ts +58 -0
- package/dist/Components/Table/TableHelpers.svelte.js +88 -0
- package/dist/Components/Table/Types/Columns/Column.d.ts +10 -0
- package/dist/Components/Table/Types/Columns/ColumnPinningState.d.ts +12 -0
- package/dist/Components/Table/Types/Columns/ColumnSizingState.d.ts +8 -0
- package/dist/Components/Table/Types/Columns/ColumnType.d.ts +17 -0
- package/dist/Components/Table/Types/Columns/ColumnType.js +18 -1
- package/dist/Components/Table/Types/Columns/DateColumn.d.ts +6 -0
- package/dist/Components/Table/Types/Columns/DateTableCell.d.ts +7 -0
- package/dist/Components/Table/Types/Columns/Definitions/AccessorFn.d.ts +13 -0
- package/dist/Components/Table/Types/Columns/Definitions/Accessors/AccessorDef.svelte.d.ts +28 -3
- package/dist/Components/Table/Types/Columns/Definitions/Accessors/AccessorDef.svelte.js +15 -0
- package/dist/Components/Table/Types/Columns/Definitions/Accessors/AccessorType.d.ts +10 -0
- package/dist/Components/Table/Types/Columns/Definitions/Accessors/AccessorType.js +11 -1
- package/dist/Components/Table/Types/Columns/Definitions/Accessors/CheckboxDef.svelte.d.ts +23 -2
- package/dist/Components/Table/Types/Columns/Definitions/Accessors/CheckboxDef.svelte.js +9 -2
- package/dist/Components/Table/Types/Columns/Definitions/Accessors/DateInputDef.svelte.d.ts +21 -2
- package/dist/Components/Table/Types/Columns/Definitions/Accessors/DateInputDef.svelte.js +8 -0
- package/dist/Components/Table/Types/Columns/Definitions/Accessors/NumberInputDef.svelte.d.ts +29 -3
- package/dist/Components/Table/Types/Columns/Definitions/Accessors/NumberInputDef.svelte.js +11 -0
- package/dist/Components/Table/Types/Columns/Definitions/Accessors/QueryDef.svelte.d.ts +23 -0
- package/dist/Components/Table/Types/Columns/Definitions/Accessors/QueryDef.svelte.js +8 -0
- package/dist/Components/Table/Types/Columns/Definitions/Accessors/SelectDef.svelte.d.ts +31 -0
- package/dist/Components/Table/Types/Columns/Definitions/Accessors/SelectDef.svelte.js +17 -3
- package/dist/Components/Table/Types/Columns/Definitions/Accessors/TextInputDef.svelte.d.ts +21 -2
- package/dist/Components/Table/Types/Columns/Definitions/Accessors/TextInputDef.svelte.js +7 -0
- package/dist/Components/Table/Types/Columns/Definitions/Actions/ActionsDef.svelte.d.ts +29 -1
- package/dist/Components/Table/Types/Columns/Definitions/Actions/ActionsDef.svelte.js +17 -3
- package/dist/Components/Table/Types/Columns/Definitions/ColumnDef.svelte.d.ts +122 -11
- package/dist/Components/Table/Types/Columns/Definitions/ColumnDef.svelte.js +77 -11
- package/dist/Components/Table/Types/Columns/Definitions/ColumnDefSet.d.ts +9 -0
- package/dist/Components/Table/Types/Columns/Definitions/Display/AbstractDisplayDef.svelte.d.ts +30 -9
- package/dist/Components/Table/Types/Columns/Definitions/Display/AbstractDisplayDef.svelte.js +14 -0
- package/dist/Components/Table/Types/Columns/Definitions/Display/BubbleDef.svelte.d.ts +19 -1
- package/dist/Components/Table/Types/Columns/Definitions/Display/BubbleDef.svelte.js +12 -1
- package/dist/Components/Table/Types/Columns/Definitions/Display/DisplayDef.svelte.d.ts +11 -0
- package/dist/Components/Table/Types/Columns/Definitions/Display/DisplayDef.svelte.js +6 -3
- package/dist/Components/Table/Types/Columns/Definitions/Display/ProgressBarDef.svelte.d.ts +19 -0
- package/dist/Components/Table/Types/Columns/Definitions/Display/ProgressBarDef.svelte.js +25 -1
- package/dist/Components/Table/Types/Columns/Definitions/Display/ValidityDef.svelte.d.ts +26 -0
- package/dist/Components/Table/Types/Columns/Definitions/Display/ValidityDef.svelte.js +20 -5
- package/dist/Components/Table/Types/Columns/Definitions/Expand/ExpandDef.svelte.d.ts +43 -7
- package/dist/Components/Table/Types/Columns/Definitions/Expand/ExpandDef.svelte.js +18 -3
- package/dist/Components/Table/Types/Columns/Definitions/FilterOnly/FilterOnlyDef.svelte.d.ts +19 -5
- package/dist/Components/Table/Types/Columns/Definitions/FilterOnly/FilterOnlyDef.svelte.js +16 -5
- package/dist/Components/Table/Types/Columns/Definitions/JSONColumnDefSet.d.ts +14 -0
- package/dist/Components/Table/Types/Columns/Definitions/RowSelection/RowSelectionDef.svelte.d.ts +34 -2
- package/dist/Components/Table/Types/Columns/Definitions/RowSelection/RowSelectionDef.svelte.js +30 -7
- package/dist/Components/Table/Types/Columns/Definitions/ValidationFn.d.ts +17 -0
- package/dist/Components/Table/Types/Columns/DefsWrapper.d.ts +10 -0
- package/dist/Components/Table/Types/Columns/DisplayType.d.ts +13 -0
- package/dist/Components/Table/Types/Columns/DisplayType.js +14 -1
- package/dist/Components/Table/Types/Columns/ExpandColumn.d.ts +5 -0
- package/dist/Components/Table/Types/Columns/ExpandTableCell.d.ts +7 -0
- package/dist/Components/Table/Types/Columns/JSONColumnPinningState.d.ts +6 -0
- package/dist/Components/Table/Types/Columns/ProgressBarColumn.d.ts +5 -0
- package/dist/Components/Table/Types/Columns/ProgressBarTableCell.d.ts +9 -0
- package/dist/Components/Table/Types/Columns/TableActionButton.d.ts +12 -0
- package/dist/Components/Table/Types/Columns/TableCell.d.ts +16 -2
- package/dist/Components/Table/Types/Columns/VisibilityState.d.ts +12 -0
- package/dist/Components/Table/Types/Context/ColumnLayoutState.svelte.d.ts +173 -0
- package/dist/Components/Table/Types/Context/ColumnLayoutState.svelte.js +241 -0
- package/dist/Components/Table/Types/Context/FilteringState.svelte.d.ts +166 -0
- package/dist/Components/Table/Types/Context/FilteringState.svelte.js +180 -0
- package/dist/Components/Table/Types/Context/FocusState.svelte.d.ts +316 -0
- package/dist/Components/Table/Types/Context/FocusState.svelte.js +751 -0
- package/dist/Components/Table/Types/Context/ITable.d.ts +10 -0
- package/dist/Components/Table/Types/Context/PreferencesState.svelte.d.ts +242 -0
- package/dist/Components/Table/Types/Context/PreferencesState.svelte.js +317 -0
- package/dist/Components/Table/Types/Context/ReadonlyRowModel.d.ts +14 -3
- package/dist/Components/Table/Types/Context/Row.d.ts +18 -0
- package/dist/Components/Table/Types/Context/RowModel.d.ts +11 -0
- package/dist/Components/Table/Types/Context/SelectionState.svelte.d.ts +260 -0
- package/dist/Components/Table/Types/Context/SelectionState.svelte.js +613 -0
- package/dist/Components/Table/Types/Context/SortingState.svelte.d.ts +112 -0
- package/dist/Components/Table/Types/Context/SortingState.svelte.js +272 -0
- package/dist/Components/Table/Types/Context/TableContext.svelte.d.ts +580 -58
- package/dist/Components/Table/Types/Context/TableContext.svelte.js +984 -1278
- package/dist/Components/Table/Types/Context/TableInitOptions.d.ts +16 -0
- package/dist/Components/Table/Types/Context/TableSettings.d.ts +20 -0
- package/dist/Components/Table/Types/Context/VirtualisationState.svelte.d.ts +167 -0
- package/dist/Components/Table/Types/Context/VirtualisationState.svelte.js +226 -0
- package/dist/Components/Table/Types/Coordinates/CellCoordinates.d.ts +12 -0
- package/dist/Components/Table/Types/Coordinates/CellCoordinatesWithoutColumn.d.ts +5 -0
- package/dist/Components/Table/Types/Coordinates/ColumnIndices.d.ts +16 -2
- package/dist/Components/Table/Types/DataRepository/BuiltInRemoteRepository.svelte.d.ts +143 -0
- package/dist/Components/Table/Types/DataRepository/BuiltInRemoteRepository.svelte.js +454 -0
- package/dist/Components/Table/Types/DataRepository/IDataRepository.d.ts +21 -0
- package/dist/Components/Table/Types/DataRepository/ILocalDataRepository.d.ts +10 -0
- package/dist/Components/Table/Types/DataRepository/IRemoteDataRepository.d.ts +16 -0
- package/dist/Components/Table/Types/DataRepository/LocalTableDataRepository.svelte.d.ts +87 -3
- package/dist/Components/Table/Types/DataRepository/LocalTableDataRepository.svelte.js +112 -7
- package/dist/Components/Table/Types/DataRepository/SortingState.d.ts +12 -0
- package/dist/Components/Table/Types/DataRepository/TableDataRepository.svelte.d.ts +87 -2
- package/dist/Components/Table/Types/DataRepository/TableDataRepository.svelte.js +74 -1
- package/dist/Components/Table/Types/ExpandedPanel.d.ts +9 -0
- package/dist/Components/Table/Types/ExpandedPanel.js +10 -1
- package/dist/Components/Table/Types/Filtering/ColumnFiltersState.d.ts +17 -0
- package/dist/Components/Table/Types/Filtering/CustomFilter.d.ts +21 -0
- package/dist/Components/Table/Types/Filtering/CustomFilterType.d.ts +5 -0
- package/dist/Components/Table/Types/Filtering/CustomFilterType.js +6 -1
- package/dist/Components/Table/Types/Filtering/CustomRemoteFilters.d.ts +6 -0
- package/dist/Components/Table/Types/Filtering/FilterFn.d.ts +28 -0
- package/dist/Components/Table/Types/Filtering/FilterMode.d.ts +7 -0
- package/dist/Components/Table/Types/Filtering/FilterType.d.ts +8 -0
- package/dist/Components/Table/Types/Filtering/FilterType.js +9 -1
- package/dist/Components/Table/Types/Filtering/FilterValueType.d.ts +11 -0
- package/dist/Components/Table/Types/Filtering/FilterValueType.js +12 -1
- package/dist/Components/Table/Types/Filtering/HasCustomFilterFunction.d.ts +23 -2
- package/dist/Components/Table/Types/Filtering/NumberDateFilterMode.d.ts +19 -12
- package/dist/Components/Table/Types/Filtering/NumberDateFilterMode.js +18 -14
- package/dist/Components/Table/Types/Filtering/StringFilterMode.d.ts +22 -15
- package/dist/Components/Table/Types/Filtering/StringFilterMode.js +22 -16
- package/dist/Components/Table/Types/Focus/MultiFocusEdge.d.ts +8 -0
- package/dist/Components/Table/Types/Focus/MultiFocusEdge.js +9 -1
- package/dist/Components/Table/Types/Focus/TableFocusDetails.svelte.d.ts +22 -0
- package/dist/Components/Table/Types/Focus/TableFocusDetails.svelte.js +22 -0
- package/dist/Components/Table/Types/Header.d.ts +8 -0
- package/dist/Components/Table/Types/HeaderGroup.d.ts +7 -0
- package/dist/Components/Table/Types/Layout/CellPinning.d.ts +1 -0
- package/dist/Components/Table/Types/Layout/CellPinning.js +8 -0
- package/dist/Components/Table/Types/OnChangeFn.d.ts +11 -0
- package/dist/Components/Table/Types/Pagination/PaginationState.d.ts +9 -0
- package/dist/Components/Table/Types/Pagination/PaginationType.d.ts +10 -0
- package/dist/Components/Table/Types/Pagination/PaginationType.js +11 -1
- package/dist/Components/Table/Types/Public/AnyEditEvent.d.ts +30 -0
- package/dist/Components/Table/Types/Public/AnyEditEvent.js +1 -0
- package/dist/Components/Table/Types/Public/BaseColumnOptions.d.ts +44 -0
- package/dist/Components/Table/Types/Public/BaseColumnOptions.js +1 -0
- package/dist/Components/Table/Types/Public/ColumnFactory.d.ts +35 -0
- package/dist/Components/Table/Types/Public/ColumnFactory.js +1 -0
- package/dist/Components/Table/Types/Public/ColumnOptions.d.ts +244 -0
- package/dist/Components/Table/Types/Public/ColumnOptions.js +1 -0
- package/dist/Components/Table/Types/Public/ColumnSpec.d.ts +39 -0
- package/dist/Components/Table/Types/Public/ColumnSpec.js +1 -0
- package/dist/Components/Table/Types/Public/CreateTableOptions.d.ts +87 -0
- package/dist/Components/Table/Types/Public/CreateTableOptions.js +1 -0
- package/dist/Components/Table/Types/Public/KeyConstraints.d.ts +42 -0
- package/dist/Components/Table/Types/Public/KeyConstraints.js +22 -0
- package/dist/Components/Table/Types/Public/RowSource.d.ts +87 -0
- package/dist/Components/Table/Types/Public/RowSource.js +1 -0
- package/dist/Components/Table/Types/Public/SelectionOptions.d.ts +26 -0
- package/dist/Components/Table/Types/Public/SelectionOptions.js +1 -0
- package/dist/Components/Table/Types/Public/Table.d.ts +40 -0
- package/dist/Components/Table/Types/Public/Table.js +1 -0
- package/dist/Components/Table/Types/Public/TableInitialState.d.ts +26 -0
- package/dist/Components/Table/Types/Public/TableInitialState.js +1 -0
- package/dist/Components/Table/Types/Public/TablePersistence.d.ts +38 -0
- package/dist/Components/Table/Types/Public/TablePersistence.js +1 -0
- package/dist/Components/Table/Types/Public/TableSubApis.d.ts +190 -0
- package/dist/Components/Table/Types/Public/TableSubApis.js +1 -0
- package/dist/Components/Table/Types/Public/index.d.ts +20 -0
- package/dist/Components/Table/Types/Public/index.js +8 -0
- package/dist/Components/Table/Types/Toolbar/ToolbarPosition.d.ts +4 -0
- package/dist/Components/Table/Types/Toolbar/ToolbarPosition.js +5 -1
- package/dist/Components/Table/createTable.svelte.d.ts +53 -0
- package/dist/Components/Table/createTable.svelte.js +270 -0
- package/dist/Components/TextArea.svelte +37 -18
- package/dist/Components/TextAreaProps.d.ts +37 -0
- package/dist/Components/TextInput.svelte +41 -22
- package/dist/Components/TextInputProps.d.ts +58 -1
- package/dist/Components/ThreeStateRadio.svelte +61 -64
- package/dist/Components/ThreeStateRadioProps.d.ts +29 -1
- package/dist/Components/Touch/BoolCard.svelte +8 -15
- package/dist/Components/Touch/BoolCard.svelte.d.ts +1 -10
- package/dist/Components/Touch/BoolCardProps.d.ts +21 -0
- package/dist/Components/Touch/BoolCardProps.js +1 -0
- package/dist/Components/Touch/DateModal.svelte +17 -25
- package/dist/Components/Touch/DateModal.svelte.d.ts +1 -17
- package/dist/Components/Touch/DateModalProps.d.ts +36 -0
- package/dist/Components/Touch/DateModalProps.js +1 -0
- package/dist/Components/Touch/EditCard.svelte +10 -3
- package/dist/Components/Touch/EditCardProps.d.ts +21 -0
- package/dist/Components/Touch/InfoCard.svelte +14 -7
- package/dist/Components/Touch/InfoCardProps.d.ts +9 -0
- package/dist/Components/Touch/InfoTextCard.svelte +9 -2
- package/dist/Components/Touch/InfoTextCardProps.d.ts +8 -0
- package/dist/Components/Touch/ModalExplanation.svelte +9 -12
- package/dist/Components/Touch/ModalExplanation.svelte.d.ts +1 -6
- package/dist/Components/Touch/ModalExplanationProps.d.ts +22 -0
- package/dist/Components/Touch/ModalExplanationProps.js +1 -0
- package/dist/Components/Touch/NumberKeyboard.svelte +62 -105
- package/dist/Components/Touch/NumberKeyboardProps.d.ts +19 -0
- package/dist/Components/Touch/NumberModal.svelte +16 -6
- package/dist/Components/Touch/NumberModalProps.d.ts +23 -1
- package/dist/Components/Touch/PlusMinusCard.svelte +12 -16
- package/dist/Components/Touch/PlusMinusCard.svelte.d.ts +1 -6
- package/dist/Components/Touch/PlusMinusCardProps.d.ts +18 -0
- package/dist/Components/Touch/PlusMinusCardProps.js +1 -0
- package/dist/Components/Touch/SelectModal.svelte +33 -15
- package/dist/Components/Touch/SelectModalProps.d.ts +22 -1
- package/dist/Components/Touch/SummaryCard.svelte +56 -14
- package/dist/Components/Touch/SummaryCardProps.d.ts +16 -3
- package/dist/Components/Touch/TextAreaModal.svelte +18 -9
- package/dist/Components/Touch/TextAreaModalProps.d.ts +21 -0
- package/dist/Components/Touch/TextModal.svelte +15 -32
- package/dist/Components/Touch/TextModalProps.d.ts +28 -1
- package/dist/Components/Touch/TouchCard.svelte +9 -47
- package/dist/Components/Touch/TouchCardProps.d.ts +21 -0
- package/dist/Components/Touch/TouchModal.svelte +105 -99
- package/dist/Components/Touch/TouchModalProps.d.ts +35 -1
- package/dist/Components/Touch/UtilityButton.svelte +36 -18
- package/dist/Components/Touch/UtilityButtonProps.d.ts +16 -0
- package/dist/Components/VerticalTabGroup.svelte +18 -40
- package/dist/Components/VerticalTabGroupButton.svelte +11 -50
- package/dist/Components/VerticalTabGroupProps.d.ts +15 -2
- package/dist/Contexts/AlertContext.svelte.d.ts +92 -8
- package/dist/Contexts/AlertContext.svelte.js +69 -6
- package/dist/Contexts/ContextMenuContext.svelte.d.ts +54 -8
- package/dist/Contexts/ContextMenuContext.svelte.js +48 -2
- package/dist/Contexts/TestContext.svelte.d.ts +27 -1
- package/dist/Contexts/TestContext.svelte.js +29 -1
- package/dist/Contexts/ToastContext.svelte.d.ts +29 -1
- package/dist/Contexts/ToastContext.svelte.js +93 -24
- package/dist/Contexts/TooltipContext.svelte.d.ts +68 -1
- package/dist/Contexts/TooltipContext.svelte.js +70 -7
- package/dist/Contexts/UntypedInputContext.svelte.d.ts +54 -5
- package/dist/Contexts/UntypedInputContext.svelte.js +87 -34
- package/dist/Delay/Delay.js +1 -1
- package/dist/Helpers/AsyncFlag.svelte.d.ts +39 -0
- package/dist/Helpers/AsyncFlag.svelte.js +72 -0
- package/dist/Helpers/Datamatrix.d.ts +10 -1
- package/dist/Helpers/Datamatrix.js +290 -1
- package/dist/Helpers/Helpers.svelte.d.ts +252 -18
- package/dist/Helpers/Helpers.svelte.js +271 -75
- package/dist/Helpers/INamed.d.ts +6 -0
- package/dist/Helpers/Storage.d.ts +67 -0
- package/dist/Helpers/Storage.js +138 -0
- package/dist/Helpers/dropdownPortal.d.ts +52 -0
- package/dist/Helpers/dropdownPortal.js +232 -0
- package/dist/Helpers/dropdownPortal.svelte.d.ts +2 -0
- package/dist/Helpers/dropdownPortal.svelte.js +5 -0
- package/dist/Helpers/memoiseByRow.d.ts +45 -0
- package/dist/Helpers/memoiseByRow.js +78 -0
- package/dist/Helpers/prefersReducedMotion.svelte.d.ts +27 -0
- package/dist/Helpers/prefersReducedMotion.svelte.js +18 -0
- package/dist/Helpers/useTooltip.svelte.d.ts +53 -0
- package/dist/Helpers/useTooltip.svelte.js +62 -0
- package/dist/Types/Examples/ExampleModal.svelte +12 -11
- package/dist/Types/Examples/ExampleModal.svelte.d.ts +2 -2
- package/dist/Types/Examples/ExampleSelectEnum.js +1 -1
- package/dist/Types/Internal/AsyncFlag.d.ts +7 -0
- package/dist/Types/Internal/AsyncFlag.js +1 -0
- package/dist/Types/Internal/BigRadioOption.d.ts +8 -0
- package/dist/Types/Internal/ButtonProp.d.ts +24 -2
- package/dist/Types/Internal/CallbackButton.d.ts +12 -0
- package/dist/Types/Internal/DateChange.d.ts +8 -0
- package/dist/Types/Internal/DatePickerType.d.ts +5 -0
- package/dist/Types/Internal/DatePickerType.js +6 -1
- package/dist/Types/Internal/IdentifiableToastMessage.d.ts +8 -0
- package/dist/Types/Internal/InputVariant.d.ts +5 -0
- package/dist/Types/Internal/InputVariant.js +6 -1
- package/dist/Types/Internal/Misc.d.ts +91 -0
- package/dist/Types/Internal/RefWrapper.d.ts +6 -0
- package/dist/Types/Internal/SelectOption.d.ts +8 -0
- package/dist/Types/Internal/Shape.d.ts +1 -0
- package/dist/Types/Internal/Shape.js +2 -1
- package/dist/Types/Internal/Side.d.ts +1 -0
- package/dist/Types/Internal/Side.js +2 -1
- package/dist/Types/Internal/Size.d.ts +5 -0
- package/dist/Types/Internal/Size.js +6 -1
- package/dist/Types/Internal/TabOption.d.ts +15 -5
- package/dist/Types/Internal/Ternary.d.ts +6 -0
- package/dist/Types/Internal/Ternary.js +7 -1
- package/dist/Types/Internal/ToastMessage.d.ts +28 -0
- package/dist/Types/Internal/Validity.d.ts +6 -0
- package/dist/Types/Internal/Validity.js +7 -1
- package/dist/Types/Internal/ValidityWrapper.d.ts +8 -0
- package/dist/Types/Internal/Variant.d.ts +5 -0
- package/dist/Types/Internal/Variant.js +6 -1
- package/dist/index.d.ts +27 -82
- package/dist/index.js +24 -62
- package/dist/scss/_mixins.scss +451 -167
- package/dist/scss/_motion.scss +57 -0
- package/dist/scss/_sizing.scss +16 -0
- package/dist/scss/colours.js +2 -2
- package/dist/scss/sizing.d.ts +9 -0
- package/dist/scss/sizing.js +10 -1
- package/package.json +35 -31
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { browser, dev } from '$app/environment';
|
|
2
|
-
import { asyncAll,
|
|
2
|
+
import { asyncAll, asyncMap, devCatch, getCanvasContext, isKeyOf, } from '../../../../Helpers/Helpers.svelte.js';
|
|
3
|
+
import { PreferencesState } from './PreferencesState.svelte.js';
|
|
4
|
+
import { SelectionState } from './SelectionState.svelte.js';
|
|
3
5
|
import { tick, untrack } from 'svelte';
|
|
4
6
|
import { SvelteMap } from 'svelte/reactivity';
|
|
5
7
|
import { ColumnType } from '../Columns/ColumnType.js';
|
|
@@ -13,17 +15,41 @@ import { BubbleDef } from '../Columns/Definitions/Display/BubbleDef.svelte.js';
|
|
|
13
15
|
import { DisplayDef } from '../Columns/Definitions/Display/DisplayDef.svelte.js';
|
|
14
16
|
import { ProgressBarDef } from '../Columns/Definitions/Display/ProgressBarDef.svelte.js';
|
|
15
17
|
import { RowSelectionDef } from '../Columns/Definitions/RowSelection/RowSelectionDef.svelte.js';
|
|
18
|
+
import { SortingState } from './SortingState.svelte.js';
|
|
19
|
+
import { FilteringState } from './FilteringState.svelte.js';
|
|
20
|
+
import { ColumnLayoutState } from './ColumnLayoutState.svelte.js';
|
|
21
|
+
import { FocusState } from './FocusState.svelte.js';
|
|
22
|
+
import { VirtualisationState } from './VirtualisationState.svelte.js';
|
|
16
23
|
import { PaginationType } from '../Pagination/PaginationType.js';
|
|
17
24
|
import { ToolbarPosition } from '../Toolbar/ToolbarPosition.js';
|
|
18
25
|
const SORTING_ICON_WIDTH = 24;
|
|
19
26
|
const InternalSymbol = Symbol();
|
|
20
27
|
const uncopyableColumns = new Set([
|
|
21
|
-
//
|
|
28
|
+
// RowSelect column is a special case and is handled by tableContext directly
|
|
22
29
|
ColumnType.Expand,
|
|
23
30
|
ColumnType.Actions,
|
|
24
31
|
ColumnType.FilterOnly,
|
|
25
32
|
ColumnType.Custom,
|
|
26
33
|
]);
|
|
34
|
+
/**
|
|
35
|
+
* Default values applied by `TableContext.init` for any `TableInitOptions`
|
|
36
|
+
* field the consumer omits. Frozen so callers (notably `NestedTable`)
|
|
37
|
+
* can spread it without risking accidental shared-object mutation.
|
|
38
|
+
*
|
|
39
|
+
* Mirrors the default literals consumed inside `init`; both share this
|
|
40
|
+
* constant so the two cannot drift.
|
|
41
|
+
*/
|
|
42
|
+
export const DEFAULT_TABLE_INIT_OPTIONS = Object.freeze({
|
|
43
|
+
allowCopy: true,
|
|
44
|
+
enableResize: true,
|
|
45
|
+
allowColumnReordering: true,
|
|
46
|
+
allowQuickFiltering: true,
|
|
47
|
+
showQuickFilterByDefault: true,
|
|
48
|
+
allowAdvancedFiltering: true,
|
|
49
|
+
toolbar: ToolbarPosition.Right,
|
|
50
|
+
displayFooter: true,
|
|
51
|
+
debug: false,
|
|
52
|
+
});
|
|
27
53
|
export class TableContext {
|
|
28
54
|
defaultColumnDefs;
|
|
29
55
|
tableName;
|
|
@@ -40,8 +66,27 @@ export class TableContext {
|
|
|
40
66
|
_onEditCell;
|
|
41
67
|
debug;
|
|
42
68
|
static identifier = Symbol();
|
|
69
|
+
/**
|
|
70
|
+
* Factory for `TableContext`. Coalesces every optional flag from the
|
|
71
|
+
* caller-supplied `options` against `DEFAULT_TABLE_INIT_OPTIONS` so
|
|
72
|
+
* the constructor receives a complete set of values. The constructor
|
|
73
|
+
* itself is `protected` and gated by an internal symbol to make it
|
|
74
|
+
* impossible to construct a `TableContext` without going through
|
|
75
|
+
* `init`.
|
|
76
|
+
*/
|
|
43
77
|
static init(defaultColumnDefs, tableName, dataRepo, options) {
|
|
44
|
-
const context = new this(InternalSymbol, defaultColumnDefs, tableName, dataRepo, options.allowCopy ??
|
|
78
|
+
const context = new this(InternalSymbol, defaultColumnDefs, tableName, dataRepo, options.allowCopy ?? DEFAULT_TABLE_INIT_OPTIONS.allowCopy, options.enableResize ?? DEFAULT_TABLE_INIT_OPTIONS.enableResize, options.allowColumnReordering ?? DEFAULT_TABLE_INIT_OPTIONS.allowColumnReordering, options.allowQuickFiltering ?? DEFAULT_TABLE_INIT_OPTIONS.allowQuickFiltering, options.showQuickFilterByDefault ?? DEFAULT_TABLE_INIT_OPTIONS.showQuickFilterByDefault, options.allowAdvancedFiltering ?? DEFAULT_TABLE_INIT_OPTIONS.allowAdvancedFiltering, options.toolbar ?? DEFAULT_TABLE_INIT_OPTIONS.toolbar, options.displayFooter ?? DEFAULT_TABLE_INIT_OPTIONS.displayFooter,
|
|
79
|
+
// Fallback identity extractor when no `selectionExtractor`
|
|
80
|
+
// is supplied. The nested-table call path (see
|
|
81
|
+
// `ColumnFactory.expand`) always passes one through, but
|
|
82
|
+
// other consumers may construct an options object directly
|
|
83
|
+
// without it. Returning the row object itself preserves
|
|
84
|
+
// row identity (the cell wrappers use reference equality
|
|
85
|
+
// via the keying cache) and avoids the
|
|
86
|
+
// `tableContext.selectionExtractor is not a function`
|
|
87
|
+
// crash inside `SelectionState.cachedKey` /
|
|
88
|
+
// `TableRow.svelte`'s id-resolution effect.
|
|
89
|
+
options.selectionExtractor ?? ((row) => row), options.getUserId, options.onEditCell, options.debug ?? DEFAULT_TABLE_INIT_OPTIONS.debug);
|
|
45
90
|
return context;
|
|
46
91
|
}
|
|
47
92
|
// #region constructor
|
|
@@ -66,7 +111,6 @@ export class TableContext {
|
|
|
66
111
|
throw new Error('This class may only be instantiated through the static init() method');
|
|
67
112
|
}
|
|
68
113
|
this._dataRepo = $state(dataRepo);
|
|
69
|
-
// this.dataRepo.forceRefresh = this.forceVisibilityUpdate;
|
|
70
114
|
$effect(() => {
|
|
71
115
|
void this.currentPageData;
|
|
72
116
|
// void this.selectedItems;
|
|
@@ -77,7 +121,6 @@ export class TableContext {
|
|
|
77
121
|
this.resetHighlightedRows();
|
|
78
122
|
})
|
|
79
123
|
.catch(devCatch);
|
|
80
|
-
// this.recalculateAllSelectedInCurrentPage();
|
|
81
124
|
}
|
|
82
125
|
});
|
|
83
126
|
});
|
|
@@ -96,12 +139,11 @@ export class TableContext {
|
|
|
96
139
|
// throw new Error(`filtered indices are not in a tracking context`);
|
|
97
140
|
// }
|
|
98
141
|
if (!this.dataRepo.filtering.length) {
|
|
99
|
-
this.
|
|
142
|
+
this._filtering.setFilteredIndices(data.map((_item, index) => {
|
|
100
143
|
return index;
|
|
101
|
-
});
|
|
144
|
+
}));
|
|
102
145
|
}
|
|
103
146
|
else {
|
|
104
|
-
// await asyncSleep(300);
|
|
105
147
|
const filtered = [];
|
|
106
148
|
for (let index = 0; index < data.length; ++index) {
|
|
107
149
|
if (currentController.signal.aborted) {
|
|
@@ -133,7 +175,7 @@ export class TableContext {
|
|
|
133
175
|
filtered.push(index);
|
|
134
176
|
}
|
|
135
177
|
}
|
|
136
|
-
this.
|
|
178
|
+
this._filtering.setFilteredIndices(filtered);
|
|
137
179
|
}
|
|
138
180
|
})().catch((e) => {
|
|
139
181
|
devCatch(e);
|
|
@@ -144,7 +186,7 @@ export class TableContext {
|
|
|
144
186
|
void this.dataRepo.data.length;
|
|
145
187
|
void this.selectedItems;
|
|
146
188
|
void this.paginationRepo?.pageStartIndex;
|
|
147
|
-
const invalidValues = this.
|
|
189
|
+
const invalidValues = this.invalidValues;
|
|
148
190
|
const allSelectedInCurrentPage = [...this.selectedItems.keys()];
|
|
149
191
|
const currentIncrement = ++lastIncrement;
|
|
150
192
|
void this.allSelectedInCurrentPage;
|
|
@@ -165,9 +207,7 @@ export class TableContext {
|
|
|
165
207
|
const current = (latest_pageColData = latest_pageColData + 1);
|
|
166
208
|
if (!this.focusStart || !this.focusEnd) {
|
|
167
209
|
// eslint-disable-next-line svelte/prefer-svelte-reactivity
|
|
168
|
-
this.
|
|
169
|
-
// eslint-disable-next-line svelte/prefer-svelte-reactivity
|
|
170
|
-
this._focusedColumnIds = new Set();
|
|
210
|
+
this._focus.setFocusedDerived(new Set(), new Set());
|
|
171
211
|
return;
|
|
172
212
|
}
|
|
173
213
|
const { row: startRowIndexId } = this.focusStart;
|
|
@@ -178,9 +218,7 @@ export class TableContext {
|
|
|
178
218
|
const endRowIndex = model.rows.findIndex((row) => row.visibleIndex === endRowIndexId);
|
|
179
219
|
if (startRowIndex == -1 || endRowIndex == -1) {
|
|
180
220
|
// eslint-disable-next-line svelte/prefer-svelte-reactivity
|
|
181
|
-
this.
|
|
182
|
-
// eslint-disable-next-line svelte/prefer-svelte-reactivity
|
|
183
|
-
this._focusedColumnIds = new Set();
|
|
221
|
+
this._focus.setFocusedDerived(new Set(), new Set());
|
|
184
222
|
return;
|
|
185
223
|
}
|
|
186
224
|
const minRowIndex = Math.min(startRowIndex, endRowIndex);
|
|
@@ -199,8 +237,7 @@ export class TableContext {
|
|
|
199
237
|
for (let i = minRowIndex; i <= maxRowIndex; i++) {
|
|
200
238
|
indices.add(parseInt(model.rows[i].id));
|
|
201
239
|
}
|
|
202
|
-
this.
|
|
203
|
-
this._focusedColumnIds = affectedColumns;
|
|
240
|
+
this._focus.setFocusedDerived(indices, affectedColumns);
|
|
204
241
|
}
|
|
205
242
|
});
|
|
206
243
|
let latest_paginationRowModel = 0;
|
|
@@ -282,40 +319,36 @@ export class TableContext {
|
|
|
282
319
|
.catch(devCatch);
|
|
283
320
|
});
|
|
284
321
|
$effect(() => {
|
|
285
|
-
if (this.highlightedItems.size === 0) {
|
|
286
|
-
this.
|
|
322
|
+
if (this._selection.highlightedItems.size === 0) {
|
|
323
|
+
this._selection.setAllHighlighted(false);
|
|
287
324
|
return;
|
|
288
325
|
}
|
|
289
326
|
const pageStartIndex = this.paginationRepo ? this.paginationRepo.pageStartIndex : 0;
|
|
290
327
|
const pageEndIndexExclusive = this.paginationRepo
|
|
291
328
|
? Math.min(this.paginationRepo.pageEndIndexExclusive, this.sortedData.length)
|
|
292
329
|
: this.sortedData.length;
|
|
293
|
-
const allHighlightedResult = this.
|
|
330
|
+
const allHighlightedResult = this._selection.computeAllHighlightedInRange(pageStartIndex, pageEndIndexExclusive);
|
|
294
331
|
if (allHighlightedResult instanceof Promise) {
|
|
295
332
|
allHighlightedResult
|
|
296
333
|
.then((flag) => {
|
|
297
|
-
this.
|
|
334
|
+
this._selection.setAllHighlighted(flag);
|
|
298
335
|
})
|
|
299
336
|
.catch(devCatch);
|
|
300
337
|
}
|
|
301
338
|
else {
|
|
302
|
-
this.
|
|
339
|
+
this._selection.setAllHighlighted(allHighlightedResult);
|
|
303
340
|
}
|
|
304
341
|
});
|
|
305
342
|
if (defaultColumnDefs.remoteFilters) {
|
|
306
|
-
this.
|
|
343
|
+
this._filtering.setRemoteFilters(defaultColumnDefs.remoteFilters);
|
|
307
344
|
}
|
|
308
345
|
if (hasPagination(dataRepo)) {
|
|
309
346
|
this.paginationRepo = dataRepo;
|
|
310
|
-
// this.tableOptions.onSortingChange = dataRepo.updateSorting;
|
|
311
|
-
// this.tableOptions.manualSorting = dataRepo.manualSorting;
|
|
312
347
|
}
|
|
313
|
-
this.userId = $derived(getUserId());
|
|
314
348
|
if (browser) {
|
|
315
349
|
this._getUserDefaults();
|
|
316
350
|
const removeInvalidPresets = () => {
|
|
317
|
-
|
|
318
|
-
localStorage.removeItem(`${this.userId}-${tableName}-selected-preset-name`);
|
|
351
|
+
this._preferences.clearPresetsAndSelection();
|
|
319
352
|
const visibilityState = {};
|
|
320
353
|
this.columnDefs.forEach((def) => {
|
|
321
354
|
if (def.defaultHidden || def.columnType === ColumnType.FilterOnly) {
|
|
@@ -323,7 +356,7 @@ export class TableContext {
|
|
|
323
356
|
}
|
|
324
357
|
});
|
|
325
358
|
const defaultPreset = {
|
|
326
|
-
name: '
|
|
359
|
+
name: 'Default',
|
|
327
360
|
columnDefs: this.columnDefs,
|
|
328
361
|
sortingState: [],
|
|
329
362
|
visibilityState,
|
|
@@ -331,16 +364,15 @@ export class TableContext {
|
|
|
331
364
|
};
|
|
332
365
|
this.selectedPreset = defaultPreset;
|
|
333
366
|
this.columnVisibility = visibilityState;
|
|
334
|
-
this.
|
|
367
|
+
this._preferences.setPresets([...this.columnPresets, defaultPreset]);
|
|
335
368
|
};
|
|
336
369
|
this.setupDefaultColumnDefs()
|
|
337
370
|
.then((defs) => {
|
|
338
371
|
this.showQuickFiltering = this.showQuickFilterByDefault;
|
|
339
372
|
this.isSelectable = defs.some((it) => it.id.startsWith('is-selectable-'));
|
|
340
373
|
if (this.allowColumnReordering) {
|
|
341
|
-
const
|
|
342
|
-
if (
|
|
343
|
-
const presets = JSON.parse(savedPresets);
|
|
374
|
+
const presets = this._preferences.loadPresets();
|
|
375
|
+
if (presets.length > 0) {
|
|
344
376
|
if (presets[0] && areDefsEquivalent(defs, presets[0].columnDefs)) {
|
|
345
377
|
return this.reassignDefsToPresets(presets).then((p) => p);
|
|
346
378
|
}
|
|
@@ -356,7 +388,7 @@ export class TableContext {
|
|
|
356
388
|
removeInvalidPresets();
|
|
357
389
|
return;
|
|
358
390
|
}
|
|
359
|
-
const savedPresetName =
|
|
391
|
+
const savedPresetName = this._preferences.loadSelectedPresetName();
|
|
360
392
|
if (savedPresetName) {
|
|
361
393
|
const preset = presets.find((it) => it.name === savedPresetName);
|
|
362
394
|
if (preset && areDefsEquivalent(this.columnDefs, preset.columnDefs)) {
|
|
@@ -366,13 +398,13 @@ export class TableContext {
|
|
|
366
398
|
this.selectedPreset = preset;
|
|
367
399
|
}
|
|
368
400
|
else {
|
|
369
|
-
localStorage.removeItem(
|
|
401
|
+
localStorage.removeItem(this._preferences.storageKey('selected-preset-name'));
|
|
370
402
|
this.selectedPreset = presets[0];
|
|
371
403
|
if (presets.at(0)?.visibilityState) {
|
|
372
404
|
this.columnVisibility = presets[0].visibilityState;
|
|
373
405
|
}
|
|
374
406
|
}
|
|
375
|
-
this.
|
|
407
|
+
this._preferences.setPresets(presets);
|
|
376
408
|
}
|
|
377
409
|
})
|
|
378
410
|
.catch(devCatch);
|
|
@@ -380,7 +412,6 @@ export class TableContext {
|
|
|
380
412
|
}
|
|
381
413
|
// #endregion
|
|
382
414
|
// #region stores
|
|
383
|
-
userId;
|
|
384
415
|
isSelectable = $state(false);
|
|
385
416
|
_paginationRepo = $state();
|
|
386
417
|
get paginationRepo() {
|
|
@@ -389,20 +420,17 @@ export class TableContext {
|
|
|
389
420
|
set paginationRepo(v) {
|
|
390
421
|
this._paginationRepo = v;
|
|
391
422
|
}
|
|
392
|
-
|
|
423
|
+
/**
|
|
424
|
+
* Delegating accessor preserved for backwards compatibility; reads /
|
|
425
|
+
* writes through to `_filtering.showQuickFiltering`. The sub-context
|
|
426
|
+
* owns the `allowQuickFiltering` gate so the setter logic stays
|
|
427
|
+
* identical to the pre-extraction implementation.
|
|
428
|
+
*/
|
|
393
429
|
get showQuickFiltering() {
|
|
394
|
-
return this.
|
|
430
|
+
return this._filtering.showQuickFiltering;
|
|
395
431
|
}
|
|
396
432
|
set showQuickFiltering(v) {
|
|
397
|
-
|
|
398
|
-
if (!this.allowQuickFiltering) {
|
|
399
|
-
console.log(`attempted to toggle quick filtering when allowQuickFiltering = false`);
|
|
400
|
-
}
|
|
401
|
-
else {
|
|
402
|
-
console.log(`setting quick filtering = ${v}`);
|
|
403
|
-
}
|
|
404
|
-
}
|
|
405
|
-
this._showQuickFiltering = this.allowQuickFiltering && v;
|
|
433
|
+
this._filtering.showQuickFiltering = v;
|
|
406
434
|
}
|
|
407
435
|
_dataRepo;
|
|
408
436
|
get dataRepo() {
|
|
@@ -411,28 +439,49 @@ export class TableContext {
|
|
|
411
439
|
set dataRepo(v) {
|
|
412
440
|
this._dataRepo = v;
|
|
413
441
|
}
|
|
414
|
-
|
|
442
|
+
/**
|
|
443
|
+
* Delegating getter preserved for backwards compatibility. Reads
|
|
444
|
+
* through to `_filtering.remoteFilters`; the parent uses
|
|
445
|
+
* `_filtering.setRemoteFilters` during column-def setup to write the
|
|
446
|
+
* caller-supplied value.
|
|
447
|
+
*/
|
|
415
448
|
get remoteFilters() {
|
|
416
|
-
return this.
|
|
417
|
-
}
|
|
418
|
-
set remoteFilters(v) {
|
|
419
|
-
this._remoteFilters = v;
|
|
449
|
+
return this._filtering.remoteFilters;
|
|
420
450
|
}
|
|
421
|
-
|
|
451
|
+
/**
|
|
452
|
+
* Delegating accessor preserved for backwards compatibility; reads /
|
|
453
|
+
* writes through to `_filtering.showSelectedOnly`. The sub-context
|
|
454
|
+
* preserves the idempotency short-circuit (re-assigning the same
|
|
455
|
+
* value is a no-op).
|
|
456
|
+
*/
|
|
422
457
|
get showSelectedOnly() {
|
|
423
|
-
return this.
|
|
458
|
+
return this._filtering.showSelectedOnly;
|
|
424
459
|
}
|
|
425
460
|
set showSelectedOnly(v) {
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
461
|
+
this._filtering.showSelectedOnly = v;
|
|
462
|
+
}
|
|
463
|
+
/**
|
|
464
|
+
* Delegating getters that relay the per-type `FilterFn` from
|
|
465
|
+
* `_filtering`. The sub-context's `$derived` chain reads through
|
|
466
|
+
* `paginationRepo` via the thunk so the source of truth stays
|
|
467
|
+
* with the data repository; consumers that bind these getters
|
|
468
|
+
* (notably `setupDefaultColumnDefs`) need no migration.
|
|
469
|
+
*/
|
|
470
|
+
get dateFilter() {
|
|
471
|
+
return this._filtering.dateFilter;
|
|
472
|
+
}
|
|
473
|
+
get numberFilter() {
|
|
474
|
+
return this._filtering.numberFilter;
|
|
475
|
+
}
|
|
476
|
+
get selectFilter() {
|
|
477
|
+
return this._filtering.selectFilter;
|
|
478
|
+
}
|
|
479
|
+
get boolFilter() {
|
|
480
|
+
return this._filtering.boolFilter;
|
|
481
|
+
}
|
|
482
|
+
get stringFilter() {
|
|
483
|
+
return this._filtering.stringFilter;
|
|
430
484
|
}
|
|
431
|
-
dateFilter = $derived(this.paginationRepo?.dateFilter);
|
|
432
|
-
numberFilter = $derived(this.paginationRepo?.numberFilter);
|
|
433
|
-
selectFilter = $derived(this.paginationRepo?.selectFilter);
|
|
434
|
-
boolFilter = $derived(this.paginationRepo?.boolFilter);
|
|
435
|
-
stringFilter = $derived(this.paginationRepo?.stringFilter);
|
|
436
485
|
_limitFooter = $state(false);
|
|
437
486
|
get limitFooter() {
|
|
438
487
|
return this._limitFooter;
|
|
@@ -447,69 +496,104 @@ export class TableContext {
|
|
|
447
496
|
set dragTarget(v) {
|
|
448
497
|
this._dragTarget = v;
|
|
449
498
|
}
|
|
450
|
-
|
|
499
|
+
/**
|
|
500
|
+
* Delegating accessor preserved for backwards compatibility. The
|
|
501
|
+
* actual `$state` slot lives on `_columnLayout`; this getter / setter
|
|
502
|
+
* pair forwards reads and writes so existing consumers need no
|
|
503
|
+
* migration. See `_columnLayout` below for the sub-context.
|
|
504
|
+
*/
|
|
451
505
|
get columnDefs() {
|
|
452
|
-
return this.
|
|
506
|
+
return this._columnLayout.columnDefs;
|
|
453
507
|
}
|
|
454
508
|
set columnDefs(v) {
|
|
455
|
-
this.
|
|
509
|
+
this._columnLayout.columnDefs = v;
|
|
456
510
|
}
|
|
457
|
-
|
|
511
|
+
/**
|
|
512
|
+
* Delegating accessor preserved for backwards compatibility. The
|
|
513
|
+
* actual `$state` slot lives on `_preferences._columnPresets`
|
|
514
|
+
* (Phase 6.4). The setter is private because the consumer-facing
|
|
515
|
+
* write path goes through `saveColumnPreset` (which also persists
|
|
516
|
+
* the list to localStorage); internal call sites that need to
|
|
517
|
+
* mutate the list directly call `_preferences.setPresets(...)`.
|
|
518
|
+
*/
|
|
458
519
|
get columnPresets() {
|
|
459
|
-
return this.
|
|
460
|
-
}
|
|
461
|
-
set columnPresets(v) {
|
|
462
|
-
this._columnPresets = v;
|
|
520
|
+
return this._preferences.columnPresets;
|
|
463
521
|
}
|
|
464
|
-
|
|
465
|
-
|
|
522
|
+
/**
|
|
523
|
+
* Delegating accessor preserved for backwards compatibility. The
|
|
524
|
+
* actual `$state` slot lives on `_preferences._selectedPreset`
|
|
525
|
+
* (Phase 6.4). Reads / writes through to the sub-context.
|
|
526
|
+
*/
|
|
466
527
|
get selectedPreset() {
|
|
467
|
-
return this.
|
|
528
|
+
return this._preferences.selectedPreset;
|
|
468
529
|
}
|
|
469
530
|
set selectedPreset(v) {
|
|
470
|
-
this.
|
|
531
|
+
this._preferences.selectedPreset = v;
|
|
471
532
|
}
|
|
472
|
-
|
|
473
|
-
|
|
533
|
+
/**
|
|
534
|
+
* Delegating accessor preserved for backwards compatibility. The
|
|
535
|
+
* `$state` slot lives on `_focus._focusedRowIndices` (Phase 6.6).
|
|
536
|
+
* Populated by the parent's focus-derived `$effect` through
|
|
537
|
+
* `_focus.setFocusedDerived(rows, cols)`.
|
|
538
|
+
*/
|
|
474
539
|
get focusedRowIndices() {
|
|
475
|
-
return this.
|
|
540
|
+
return this._focus.focusedRowIndices;
|
|
476
541
|
}
|
|
477
|
-
|
|
542
|
+
/**
|
|
543
|
+
* Delegating accessor preserved for backwards compatibility. The
|
|
544
|
+
* actual `$state` slot lives on `_selection._highlightedItems`
|
|
545
|
+
* (Phase 6.5).
|
|
546
|
+
*/
|
|
478
547
|
get highlightedItems() {
|
|
479
|
-
return this.
|
|
548
|
+
return this._selection.highlightedItems;
|
|
480
549
|
}
|
|
481
|
-
|
|
482
|
-
|
|
550
|
+
/**
|
|
551
|
+
* Delegating accessor preserved for backwards compatibility. The
|
|
552
|
+
* `$state` slot lives on `_focus._focusedColumnIds` (Phase 6.6).
|
|
553
|
+
*/
|
|
483
554
|
get focusedColumnIds() {
|
|
484
|
-
return this.
|
|
555
|
+
return this._focus.focusedColumnIds;
|
|
485
556
|
}
|
|
486
|
-
|
|
557
|
+
/**
|
|
558
|
+
* Delegating accessor preserved for backwards compatibility. The
|
|
559
|
+
* `$state` slot lives on `_focus._isMousingDown` (Phase 6.6).
|
|
560
|
+
*/
|
|
487
561
|
get isMousingDown() {
|
|
488
|
-
return this.
|
|
562
|
+
return this._focus.isMousingDown;
|
|
489
563
|
}
|
|
490
564
|
set isMousingDown(v) {
|
|
491
|
-
this.
|
|
565
|
+
this._focus.isMousingDown = v;
|
|
492
566
|
}
|
|
493
|
-
|
|
567
|
+
/**
|
|
568
|
+
* Delegating accessor preserved for backwards compatibility. The
|
|
569
|
+
* `$state` slot lives on `_focus._focusStart` (Phase 6.6). The
|
|
570
|
+
* setter remains read-only at this surface; the write path is
|
|
571
|
+
* `moveFocus` / `unfocus` / `tabForward` / `tabBackward` /
|
|
572
|
+
* `endFocus` / `setFocusEnd` / `startFocus` (all delegated below).
|
|
573
|
+
*/
|
|
494
574
|
get focusStart() {
|
|
495
|
-
return this.
|
|
496
|
-
}
|
|
497
|
-
set focusStart(v) {
|
|
498
|
-
this._focusStart = v;
|
|
575
|
+
return this._focus.focusStart;
|
|
499
576
|
}
|
|
500
|
-
|
|
577
|
+
/**
|
|
578
|
+
* Delegating accessor preserved for backwards compatibility. The
|
|
579
|
+
* `$state` slot lives on `_focus._focusStartIsBeingEdited`
|
|
580
|
+
* (Phase 6.6).
|
|
581
|
+
*/
|
|
501
582
|
get focusStartIsBeingEdited() {
|
|
502
|
-
return this.
|
|
583
|
+
return this._focus.focusStartIsBeingEdited;
|
|
503
584
|
}
|
|
504
585
|
set focusStartIsBeingEdited(v) {
|
|
505
|
-
this.
|
|
586
|
+
this._focus.focusStartIsBeingEdited = v;
|
|
506
587
|
}
|
|
507
|
-
|
|
588
|
+
/**
|
|
589
|
+
* Delegating accessor preserved for backwards compatibility. The
|
|
590
|
+
* `$state` slot lives on `_focus._focusEnd` (Phase 6.6).
|
|
591
|
+
*/
|
|
508
592
|
get focusEnd() {
|
|
509
|
-
return this.
|
|
593
|
+
return this._focus.focusEnd;
|
|
510
594
|
}
|
|
511
595
|
set focusEnd(v) {
|
|
512
|
-
this.
|
|
596
|
+
this._focus.focusEnd = v;
|
|
513
597
|
}
|
|
514
598
|
_singleClickEditing = $state(false);
|
|
515
599
|
get singleClickEditing() {
|
|
@@ -553,159 +637,113 @@ export class TableContext {
|
|
|
553
637
|
set commaSeparatedCopy(v) {
|
|
554
638
|
this._commaSeparatedCopy = v;
|
|
555
639
|
}
|
|
556
|
-
|
|
640
|
+
/**
|
|
641
|
+
* Delegating accessor preserved for backwards compatibility. Reads
|
|
642
|
+
* through to `_columnLayout.columnSizing`. Per-key mutations (e.g.
|
|
643
|
+
* `this.columnSizing[id] = w` in `autoResize`) work because the
|
|
644
|
+
* underlying `$state` slot is a Svelte proxy.
|
|
645
|
+
*/
|
|
557
646
|
get columnSizing() {
|
|
558
|
-
return this.
|
|
647
|
+
return this._columnLayout.columnSizing;
|
|
559
648
|
}
|
|
560
649
|
set columnSizing(v) {
|
|
561
|
-
this.
|
|
650
|
+
this._columnLayout.columnSizing = v;
|
|
562
651
|
}
|
|
563
|
-
|
|
652
|
+
/**
|
|
653
|
+
* Delegating accessor preserved for backwards compatibility. Reads
|
|
654
|
+
* through to `_columnLayout.columnPinning`. The `setColumnPinning`
|
|
655
|
+
* updater below honours the `allowColumnReordering` master gate; the
|
|
656
|
+
* direct setter does not, by design (used for preset switches and
|
|
657
|
+
* the init flow where the gate has already been checked).
|
|
658
|
+
*/
|
|
564
659
|
get columnPinning() {
|
|
565
|
-
return this.
|
|
660
|
+
return this._columnLayout.columnPinning;
|
|
566
661
|
}
|
|
567
662
|
set columnPinning(v) {
|
|
568
|
-
this.
|
|
663
|
+
this._columnLayout.columnPinning = v;
|
|
569
664
|
}
|
|
570
|
-
|
|
665
|
+
/**
|
|
666
|
+
* Delegating accessor preserved for backwards compatibility. Reads
|
|
667
|
+
* through to `_columnLayout.columnVisibility`. Tri-state semantics
|
|
668
|
+
* (`true` / `false` / `undefined`) are preserved.
|
|
669
|
+
*/
|
|
571
670
|
get columnVisibility() {
|
|
572
|
-
return this.
|
|
671
|
+
return this._columnLayout.columnVisibility;
|
|
573
672
|
}
|
|
574
673
|
set columnVisibility(v) {
|
|
575
|
-
this.
|
|
674
|
+
this._columnLayout.columnVisibility = v;
|
|
576
675
|
}
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
676
|
+
/**
|
|
677
|
+
* Identifies the cell whose `col.validity({ modal })` /
|
|
678
|
+
* `col.display({ modal })` modal is currently open, or `null` when no
|
|
679
|
+
* modal is open.
|
|
680
|
+
*
|
|
681
|
+
* Keyed on the **row object reference**, not on visible index, so the
|
|
682
|
+
* open-modal state is stable across pagination, sort, and filter
|
|
683
|
+
* changes - the cell renderer matches via `cell.row.original ===
|
|
684
|
+
* openModalCell.row`. Visible-index-based keying (the old
|
|
685
|
+
* `CellCoordinatesWithoutColumn` shape) silently re-targeted the modal
|
|
686
|
+
* to whichever row happened to occupy the same index after a page
|
|
687
|
+
* change.
|
|
688
|
+
*/
|
|
689
|
+
_openModalCell = $state(null);
|
|
690
|
+
get openModalCell() {
|
|
691
|
+
return this._openModalCell;
|
|
580
692
|
}
|
|
581
|
-
set
|
|
582
|
-
this.
|
|
693
|
+
set openModalCell(v) {
|
|
694
|
+
this._openModalCell = v;
|
|
583
695
|
}
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
const pageStartIndex = this.paginationRepo ? this.paginationRepo.pageStartIndex : 0;
|
|
592
|
-
const pageEndIndexExclusive = this.paginationRepo
|
|
593
|
-
? Math.min(this.paginationRepo.pageEndIndexExclusive, sortedData.length)
|
|
594
|
-
: sortedData.length;
|
|
595
|
-
const selectableMethod = this.columnDefs.find((it) => it instanceof RowSelectionDef)?.isSelectable;
|
|
596
|
-
const result = this.allSelectedBySelectableMethod(pageStartIndex, pageEndIndexExclusive, selectableMethod);
|
|
597
|
-
if (result instanceof Promise) {
|
|
598
|
-
result
|
|
599
|
-
.then((flag) => {
|
|
600
|
-
this._allSelectedAsync = flag;
|
|
601
|
-
})
|
|
602
|
-
.catch(devCatch);
|
|
603
|
-
return this._allSelectedAsync;
|
|
604
|
-
}
|
|
605
|
-
return result;
|
|
606
|
-
});
|
|
607
|
-
get allSelectedInCurrentPage() {
|
|
608
|
-
return this._allSelectedInCurrentPage;
|
|
696
|
+
// Per-table identifier of the ActionsCell that currently has its popup open.
|
|
697
|
+
// Lives on the context rather than at module scope so multiple tables on the
|
|
698
|
+
// same page do not share open-popup state (security: cross-table state
|
|
699
|
+
// poisoning).
|
|
700
|
+
_shownActionsPopup = $state();
|
|
701
|
+
get shownActionsPopup() {
|
|
702
|
+
return this._shownActionsPopup;
|
|
609
703
|
}
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
const emptyPromise = new Promise(() => { });
|
|
613
|
-
if (selectableMethod) {
|
|
614
|
-
const pending = [];
|
|
615
|
-
for (let i = pageStartIndex; i < pageEndIndexExclusive; i++) {
|
|
616
|
-
const item = sortedData[i];
|
|
617
|
-
const relIdx = i - pageStartIndex;
|
|
618
|
-
const raw = this._cachedKey(item);
|
|
619
|
-
const checkUnselected = (key) => {
|
|
620
|
-
const selectable = selectableMethod(item, relIdx);
|
|
621
|
-
if (selectable instanceof Promise) {
|
|
622
|
-
return selectable.then((s) => s && !this.selectedItems.has(key));
|
|
623
|
-
}
|
|
624
|
-
return selectable && !this.selectedItems.has(key);
|
|
625
|
-
};
|
|
626
|
-
const r = raw instanceof Promise ? raw.then(checkUnselected) : checkUnselected(raw);
|
|
627
|
-
if (r === true) {
|
|
628
|
-
return false;
|
|
629
|
-
}
|
|
630
|
-
if (r instanceof Promise) {
|
|
631
|
-
pending.push(r);
|
|
632
|
-
}
|
|
633
|
-
}
|
|
634
|
-
if (pending.length === 0) {
|
|
635
|
-
return true;
|
|
636
|
-
}
|
|
637
|
-
return Promise.race([
|
|
638
|
-
Promise.race(pending.map(async (p) => ((await p) ? false : emptyPromise))),
|
|
639
|
-
Promise.all(pending).then((results) => {
|
|
640
|
-
return !results.some(Boolean);
|
|
641
|
-
}),
|
|
642
|
-
]);
|
|
643
|
-
}
|
|
644
|
-
else {
|
|
645
|
-
const pending = [];
|
|
646
|
-
for (let i = pageStartIndex; i < pageEndIndexExclusive; i++) {
|
|
647
|
-
const raw = this._cachedKey(sortedData[i]);
|
|
648
|
-
if (raw instanceof Promise) {
|
|
649
|
-
pending.push(raw.then((key) => !this.selectedItems.has(key)));
|
|
650
|
-
}
|
|
651
|
-
else if (!this.selectedItems.has(raw)) {
|
|
652
|
-
return false;
|
|
653
|
-
}
|
|
654
|
-
}
|
|
655
|
-
if (pending.length === 0) {
|
|
656
|
-
return true;
|
|
657
|
-
}
|
|
658
|
-
return Promise.race([
|
|
659
|
-
Promise.race(pending.map(async (p) => ((await p) ? false : emptyPromise))),
|
|
660
|
-
Promise.all(pending).then((results) => !results.some(Boolean)),
|
|
661
|
-
]);
|
|
662
|
-
}
|
|
704
|
+
set shownActionsPopup(v) {
|
|
705
|
+
this._shownActionsPopup = v;
|
|
663
706
|
}
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
if (!this.highlightedItems.has(key)) {
|
|
672
|
-
return false;
|
|
673
|
-
}
|
|
674
|
-
for (let j = index + 1; j < pageEndIndexExclusive; j++) {
|
|
675
|
-
const r = this._cachedKey(sortedData[j]);
|
|
676
|
-
const k = r instanceof Promise ? await r : r;
|
|
677
|
-
if (!this.highlightedItems.has(k)) {
|
|
678
|
-
return false;
|
|
679
|
-
}
|
|
680
|
-
}
|
|
681
|
-
return true;
|
|
682
|
-
});
|
|
683
|
-
}
|
|
684
|
-
if (!this.highlightedItems.has(raw)) {
|
|
685
|
-
return false;
|
|
686
|
-
}
|
|
687
|
-
}
|
|
688
|
-
return true;
|
|
707
|
+
/**
|
|
708
|
+
* Delegating getter preserved for backwards compatibility. The
|
|
709
|
+
* actual `$derived` chain (and the async-result cache) live on
|
|
710
|
+
* `_selection.allSelectedInCurrentPage` (Phase 6.5).
|
|
711
|
+
*/
|
|
712
|
+
get allSelectedInCurrentPage() {
|
|
713
|
+
return this._selection.allSelectedInCurrentPage;
|
|
689
714
|
}
|
|
690
|
-
|
|
715
|
+
/**
|
|
716
|
+
* Delegating getter preserved for backwards compatibility. Reads
|
|
717
|
+
* through to `_selection.allHighlighted`; the value is published by
|
|
718
|
+
* the `_allHighlightedEffect` below which lives on this class
|
|
719
|
+
* because it reads `paginationRepo.pageStartIndex` / `pageEndIndexExclusive`
|
|
720
|
+
* directly.
|
|
721
|
+
*/
|
|
691
722
|
get allHighlighted() {
|
|
692
|
-
return this.
|
|
723
|
+
return this._selection.allHighlighted;
|
|
693
724
|
}
|
|
694
|
-
|
|
725
|
+
/**
|
|
726
|
+
* Delegating getter preserved for backwards compatibility. The
|
|
727
|
+
* `$derived` lives on `_selection.hasHighlightedItems` (Phase 6.5).
|
|
728
|
+
*/
|
|
695
729
|
get hasHighlightedItems() {
|
|
696
|
-
return this.
|
|
730
|
+
return this._selection.hasHighlightedItems;
|
|
697
731
|
}
|
|
698
|
-
|
|
699
|
-
|
|
732
|
+
/**
|
|
733
|
+
* Delegating accessors preserved for backwards compatibility. The
|
|
734
|
+
* `$state` slots live on `_selection` (Phase 6.5). `selectedItems`
|
|
735
|
+
* is read-only at this surface; the consumer-facing writers are
|
|
736
|
+
* `toggleSelected` / `setSelected` / `resetSelectedItems` /
|
|
737
|
+
* `setSelectionMap` below.
|
|
738
|
+
*/
|
|
700
739
|
get selectedItems() {
|
|
701
|
-
return this.
|
|
740
|
+
return this._selection.selectedItems;
|
|
702
741
|
}
|
|
703
|
-
_invalidValues = $state(new SvelteMap());
|
|
704
742
|
get invalidValues() {
|
|
705
|
-
return this.
|
|
743
|
+
return this._selection.invalidValues;
|
|
706
744
|
}
|
|
707
745
|
set invalidValues(v) {
|
|
708
|
-
this.
|
|
746
|
+
this._selection.invalidValues = v;
|
|
709
747
|
}
|
|
710
748
|
_hasInvalidSelectedItems = $state(false);
|
|
711
749
|
get hasInvalidSelectedItems() {
|
|
@@ -714,116 +752,292 @@ export class TableContext {
|
|
|
714
752
|
set hasInvalidSelectedItems(v) {
|
|
715
753
|
this._hasInvalidSelectedItems = v;
|
|
716
754
|
}
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
755
|
+
/**
|
|
756
|
+
* Delegating accessor preserved for backwards compatibility. The
|
|
757
|
+
* id->def lookup map is owned by `_columnLayout.columnDefsById`
|
|
758
|
+
* (Phase 6.3); previously this was a `$derived` private field on
|
|
759
|
+
* `TableContext`. Made `public get` (instead of the previous
|
|
760
|
+
* `private` field) so the dependent sub-contexts (`SortingState`)
|
|
761
|
+
* and helpers (`generateTableOptions`) can read it through the
|
|
762
|
+
* legacy surface without piercing the sub-context boundary.
|
|
763
|
+
*/
|
|
764
|
+
get columnDefsById() {
|
|
765
|
+
return this._columnLayout.columnDefsById;
|
|
766
|
+
}
|
|
767
|
+
/**
|
|
768
|
+
* Phase 6.3 sub-context that owns the column-layout state:
|
|
769
|
+
* `columnDefs`, `columnSizing`, `columnPinning`, `columnVisibility`,
|
|
770
|
+
* the `columnDefsById` reverse-lookup map, the `visualColumns`
|
|
771
|
+
* cached array (and the paired `visualColumnIndexById` O(1) lookup),
|
|
772
|
+
* the gated `setColumnPinning` updater, the `updateDefsBasedOnPinning`
|
|
773
|
+
* helper, and the `setNewPinningState` helper.
|
|
774
|
+
*
|
|
775
|
+
* Dependencies are passed as thunks so the sub-context never holds
|
|
776
|
+
* a reference to the parent. The `allowColumnReordering` thunk
|
|
777
|
+
* gates the public `setColumnPinning` updater; the `debug` thunk
|
|
778
|
+
* mirrors the parent's logger gate.
|
|
779
|
+
*/
|
|
780
|
+
_columnLayout = new ColumnLayoutState({
|
|
781
|
+
getAllowColumnReordering: () => this.allowColumnReordering,
|
|
782
|
+
getDebug: () => this.debug,
|
|
783
|
+
});
|
|
784
|
+
/**
|
|
785
|
+
* Phase 6.2 sub-context that owns the filtering-related state: the
|
|
786
|
+
* per-row filter result (`filteredIndices`), the `filteredData`
|
|
787
|
+
* derived chain, the user-facing toggles (`showQuickFiltering`,
|
|
788
|
+
* `showSelectedOnly`), the per-type `FilterFn` relays, the
|
|
789
|
+
* remote-filter slot, and the `updateFilters` `OnChangeFn` slot.
|
|
790
|
+
*
|
|
791
|
+
* Dependencies are passed as thunks so the sub-context never holds
|
|
792
|
+
* a reference to the parent; the population effect for
|
|
793
|
+
* `_filteredIndices` stays in `TableContext` because it calls
|
|
794
|
+
* `this.createRow` (parent concern) - the effect publishes its
|
|
795
|
+
* result via `this._filtering.setFilteredIndices`.
|
|
796
|
+
*/
|
|
797
|
+
_filtering = new FilteringState({
|
|
798
|
+
getRepoData: () => this.dataRepo.data,
|
|
799
|
+
getPaginationType: () => this.paginationRepo?.paginationType,
|
|
800
|
+
getDateFilterFn: () => this.paginationRepo?.dateFilter,
|
|
801
|
+
getNumberFilterFn: () => this.paginationRepo?.numberFilter,
|
|
802
|
+
getSelectFilterFn: () => this.paginationRepo?.selectFilter,
|
|
803
|
+
getBoolFilterFn: () => this.paginationRepo?.boolFilter,
|
|
804
|
+
getStringFilterFn: () => this.paginationRepo?.stringFilter,
|
|
805
|
+
getSelectedItems: () => this.selectedItems,
|
|
806
|
+
getAllowQuickFiltering: () => this.allowQuickFiltering,
|
|
807
|
+
getDebug: () => this.debug,
|
|
808
|
+
});
|
|
809
|
+
/**
|
|
810
|
+
* Delegating getter preserved for backwards compatibility. Reads
|
|
811
|
+
* through to `_filtering.filteredIndices`, which is populated by
|
|
812
|
+
* the per-row filter `$effect` in this class (the effect calls
|
|
813
|
+
* `this.createRow` and must stay where `createRow` lives).
|
|
814
|
+
*/
|
|
752
815
|
get filteredIndices() {
|
|
753
|
-
return this.
|
|
754
|
-
}
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
816
|
+
return this._filtering.filteredIndices;
|
|
817
|
+
}
|
|
818
|
+
/**
|
|
819
|
+
* Delegating getter preserved for backwards compatibility. Reads
|
|
820
|
+
* through to `_filtering.filteredData`, which owns the local /
|
|
821
|
+
* remote / show-selected-only branching.
|
|
822
|
+
*/
|
|
823
|
+
get filteredData() {
|
|
824
|
+
return this._filtering.filteredData;
|
|
825
|
+
}
|
|
826
|
+
/**
|
|
827
|
+
* Phase 6.1 sub-context that owns the sort-related derived chain and
|
|
828
|
+
* the per-`ColumnDef` comparator dispatch. The dependency thunks
|
|
829
|
+
* close over `this.columnDefsById` / `this.filteredData` /
|
|
830
|
+
* `this.dataRepo` / `this.paginationRepo` / `this.debug`, so the
|
|
831
|
+
* sub-context never holds a direct reference to the parent and the
|
|
832
|
+
* reactivity graph remains threaded through `$derived` only.
|
|
833
|
+
*
|
|
834
|
+
* Exposed as a public field so future consumers can read sorting
|
|
835
|
+
* state directly; the legacy `sortedData` getter below preserves the
|
|
836
|
+
* pre-decomposition surface for backwards compatibility.
|
|
837
|
+
*/
|
|
838
|
+
_sorting = new SortingState({
|
|
839
|
+
getColumnDefsById: () => this.columnDefsById,
|
|
840
|
+
getFilteredData: () => this._filtering.filteredData,
|
|
841
|
+
getSortingArray: () => this.dataRepo.sorting,
|
|
842
|
+
getPaginationType: () => this.paginationRepo?.paginationType,
|
|
843
|
+
getDataLength: () => this.dataRepo.data.length,
|
|
844
|
+
getDebug: () => this.debug,
|
|
776
845
|
});
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
846
|
+
/**
|
|
847
|
+
* Phase 6.4 sub-context that owns every persistence / preferences
|
|
848
|
+
* concern previously held directly on `TableContext`:
|
|
849
|
+
*
|
|
850
|
+
* - the saved column-presets list and currently-selected preset
|
|
851
|
+
* (`columnPresets`, `selectedPreset`);
|
|
852
|
+
* - the `userIdSegment` `$derived` (used to namespace every
|
|
853
|
+
* `scoria-table:<user>:<tableName>:<suffix>` storage key);
|
|
854
|
+
* - the `saveColumnPreset` / `setSelectedPreset` writers (which
|
|
855
|
+
* apply the layout AND persist);
|
|
856
|
+
* - the `loadPresets` / `loadSelectedPresetName` /
|
|
857
|
+
* `loadSavedSettings` boot-time hydration helpers;
|
|
858
|
+
* - the `persistSettings` writer used by the in-app settings
|
|
859
|
+
* toggles (`setIsCompact`, `setAlternateRowColours`, etc.);
|
|
860
|
+
* - the schema-validation typeguards (exported alongside the
|
|
861
|
+
* sub-context for unit testing).
|
|
862
|
+
*
|
|
863
|
+
* The settings fields themselves (`isCompact`, `singleClickEditing`,
|
|
864
|
+
* `alternateRowColours`, etc.) stay on `TableContext` because each
|
|
865
|
+
* one drives reactive UI; only the localStorage round-trip moved.
|
|
866
|
+
* `TableContext` retains delegating getters/setters/methods for
|
|
867
|
+
* every legacy surface (`columnPresets`, `selectedPreset`,
|
|
868
|
+
* `saveColumnPreset`, `setSelectedPreset`, `setIsCompact`, etc.).
|
|
869
|
+
*/
|
|
870
|
+
_preferences = new PreferencesState({
|
|
871
|
+
getTableName: () => this.tableName,
|
|
872
|
+
getUserId: () => this.getUserId(),
|
|
873
|
+
getColumnDefs: () => this.columnDefs,
|
|
874
|
+
getColumnVisibility: () => this.columnVisibility,
|
|
875
|
+
getColumnPinning: () => this.columnPinning,
|
|
876
|
+
getSortingArray: () => this.paginationRepo?.sorting,
|
|
877
|
+
setColumnDefs: (defs) => {
|
|
878
|
+
this.columnDefs = defs;
|
|
879
|
+
},
|
|
880
|
+
setColumnVisibility: (state) => {
|
|
881
|
+
this.columnVisibility = state;
|
|
882
|
+
},
|
|
883
|
+
setColumnPinning: (state) => {
|
|
884
|
+
this.columnPinning = state;
|
|
885
|
+
},
|
|
886
|
+
applySortingState: (state) => {
|
|
887
|
+
this.paginationRepo?.updateSorting?.(state);
|
|
888
|
+
},
|
|
889
|
+
getDebug: () => this.debug,
|
|
890
|
+
});
|
|
891
|
+
/**
|
|
892
|
+
* Phase 6.5 sub-context that owns every selection + highlighting +
|
|
893
|
+
* key-cache concern previously held directly on `TableContext`:
|
|
894
|
+
*
|
|
895
|
+
* - `selectedItems` / `invalidValues` / `highlightedItems`
|
|
896
|
+
* (`SvelteMap` slots, keyed by `selectionExtractor(item)`);
|
|
897
|
+
* - the `WeakMap<T, RowIdType>` key-cache that memoises the
|
|
898
|
+
* extractor result for each row reference;
|
|
899
|
+
* - the pending-flush buffer and its debounced microtask
|
|
900
|
+
* (`_pendingSelectionChanges` -> `tick().then(flush)`);
|
|
901
|
+
* - the `allSelectedInCurrentPage` `$derived` (with the async-
|
|
902
|
+
* result cache for promise-returning `selectionExtractor` /
|
|
903
|
+
* `RowSelectionDef.isSelectable`);
|
|
904
|
+
* - the `selectAllInCurrentPage` / `updateSelectedItems` /
|
|
905
|
+
* `onHighlightAll` flows;
|
|
906
|
+
* - the `handleItemMutation` split that powers the parent's
|
|
907
|
+
* `onEditCell` - the sub-context owns the key-cache delete +
|
|
908
|
+
* selection rebind; the user-supplied callback stays on this
|
|
909
|
+
* class.
|
|
910
|
+
*
|
|
911
|
+
* Dependencies are passed as thunks so the sub-context never holds
|
|
912
|
+
* a direct reference to `TableContext`. The two `$effect`s that
|
|
913
|
+
* historically lived on this class continue to live here (they
|
|
914
|
+
* read `paginationRepo` directly) but publish their results
|
|
915
|
+
* through `_selection.setAllHighlighted(...)` and
|
|
916
|
+
* `_selection.updateSelectedItems()`.
|
|
917
|
+
*/
|
|
918
|
+
_selection = new SelectionState({
|
|
919
|
+
getSortedData: () => this.sortedData,
|
|
920
|
+
getCurrentPageData: () => this.currentPageData,
|
|
921
|
+
getColumnDefs: () => this.columnDefs,
|
|
922
|
+
getPageStartIndex: () => this.paginationRepo?.pageStartIndex,
|
|
923
|
+
getPageEndIndexExclusive: () => this.paginationRepo?.pageEndIndexExclusive,
|
|
924
|
+
getSelectionExtractor: () => this.selectionExtractor,
|
|
925
|
+
getIsSelectable: () => this.isSelectable,
|
|
926
|
+
getDebug: () => this.debug,
|
|
927
|
+
});
|
|
928
|
+
/**
|
|
929
|
+
* Phase 6.6 sub-context that owns every focus + keyboard-navigation
|
|
930
|
+
* concern previously held directly on `TableContext`:
|
|
931
|
+
*
|
|
932
|
+
* - `focusStart` / `focusEnd` / `focusStartIsBeingEdited` /
|
|
933
|
+
* `isMousingDown` (the `$state` slots that define the focused
|
|
934
|
+
* cell-range);
|
|
935
|
+
* - the `focusedRowIndices` / `focusedColumnIds` sets (populated
|
|
936
|
+
* by the parent's `$effect` through `setFocusedDerived(...)`);
|
|
937
|
+
* - every focus writer (`startFocus`, `moveFocus`, `unfocus`,
|
|
938
|
+
* `endFocus`, `setFocusEnd`, `focusToTop`, `focusToBottom`,
|
|
939
|
+
* `focusToStart`, `focusToEnd`, `moveToTop`, `moveToBottom`,
|
|
940
|
+
* `moveToStart`, `moveToEnd`, `setFocusUp` / `setFocusDown` /
|
|
941
|
+
* `setFocusLeft` / `setFocusRight`, and the
|
|
942
|
+
* `moveFocusUp` / `moveFocusDown` / `moveFocusLeft` /
|
|
943
|
+
* `moveFocusRight` range-extension variants);
|
|
944
|
+
* - `handleTdKeydown` (the root `onkeydown` router) and the
|
|
945
|
+
* private `handleKeystroke` dispatch.
|
|
946
|
+
*
|
|
947
|
+
* Dependencies are passed as thunks so the sub-context never holds
|
|
948
|
+
* a direct reference to `TableContext`. The Ctrl+F / Tab / Ctrl+C
|
|
949
|
+
* paths in `handleTdKeydown` and `handleKeystroke` call back into
|
|
950
|
+
* the parent through the `toggleQuickFiltering` / `tabForward` /
|
|
951
|
+
* `tabBackward` / `copyDataToClipboard` thunks because those
|
|
952
|
+
* methods read fields owned by other sub-contexts (or the parent
|
|
953
|
+
* directly) and would otherwise need to import them.
|
|
954
|
+
*
|
|
955
|
+
* The focus-derived `$effect` that publishes
|
|
956
|
+
* `focusedRowIndices` / `focusedColumnIds` lives on `TableContext`
|
|
957
|
+
* because it reads `paginationRowModel` + `_visualColumns` directly;
|
|
958
|
+
* it calls `_focus.setFocusedDerived(rows, cols)` to publish.
|
|
959
|
+
*
|
|
960
|
+
* Group 2 Item C (per-cell `TableFocusDetails` reuse cache) is
|
|
961
|
+
* deferred for Phase 6.6 - see the class-level JSDoc on
|
|
962
|
+
* `FocusState` for the deferral rationale.
|
|
963
|
+
*/
|
|
964
|
+
_focus = new FocusState({
|
|
965
|
+
getAllowCopy: () => this.allowCopy,
|
|
966
|
+
getAllowQuickFiltering: () => this.allowQuickFiltering,
|
|
967
|
+
getColumnDefs: () => this.columnDefs,
|
|
968
|
+
getColumnVisibility: () => this.columnVisibility,
|
|
969
|
+
getVisualColumns: () => this._visualColumns,
|
|
970
|
+
getVisualColumnIndexById: (id) => this.columnVisualIndex(id),
|
|
971
|
+
getSortedDataLength: () => this.sortedData.length,
|
|
972
|
+
getPaginationRowModel: () => this.paginationRowModel,
|
|
973
|
+
copyDataToClipboard: () => this.copyDataToClipboard(),
|
|
974
|
+
toggleQuickFiltering: () => {
|
|
975
|
+
this.toggleQuickFiltering();
|
|
976
|
+
},
|
|
977
|
+
tabForward: () => {
|
|
978
|
+
this.tabForward();
|
|
979
|
+
},
|
|
980
|
+
tabBackward: () => {
|
|
981
|
+
this.tabBackward();
|
|
982
|
+
},
|
|
983
|
+
getDebug: () => this.debug,
|
|
984
|
+
// Phase 7.1 Item C - `getFocusDetailsFor` needs the parent
|
|
985
|
+
// `TableContext` to construct `TableFocusDetails` on cache-miss.
|
|
986
|
+
// Pass via a thunk so the sub-context never closes over `this`
|
|
987
|
+
// at construction time.
|
|
988
|
+
getTableContextRef: () => this,
|
|
826
989
|
});
|
|
990
|
+
/**
|
|
991
|
+
* Phase 7.4 row-virtualisation sub-context. Owns the visible-row
|
|
992
|
+
* window plus the top / bottom spacer-height derived chain that
|
|
993
|
+
* `TableBody.svelte` renders. Threshold defaults to 100 rows
|
|
994
|
+
* (below that the legacy code path renders every row directly);
|
|
995
|
+
* overscan defaults to 10 rows above and below the viewport so a
|
|
996
|
+
* fast flick of the wheel does not surface a blank band before
|
|
997
|
+
* the next paint.
|
|
998
|
+
*
|
|
999
|
+
* Dependencies are thunks - the sub-context reads
|
|
1000
|
+
* `paginationRowModel.rows` through `getRows`, the max-side
|
|
1001
|
+
* observed height from the `_columnLayout` row-height pool
|
|
1002
|
+
* through `getRowHeight`, and the per-table-density estimate
|
|
1003
|
+
* through `getEstimatedRowHeight`.
|
|
1004
|
+
*/
|
|
1005
|
+
/**
|
|
1006
|
+
* Rendered widths of header cells, keyed by columnId. TableHead
|
|
1007
|
+
* observes each `<div role="columnheader">` with a `ResizeObserver`
|
|
1008
|
+
* and writes the actual rendered width here; TableRow / TableBody
|
|
1009
|
+
* read these widths when computing sticky pinning offsets so that
|
|
1010
|
+
* pinned columns can flex with `minmax(W, 1fr)` like centre columns
|
|
1011
|
+
* (matching width-preservation expectation on pinning) while the
|
|
1012
|
+
* sticky-cell offsets stay accurate.
|
|
1013
|
+
*
|
|
1014
|
+
* Fallback when a column has not yet been measured: 0. The first
|
|
1015
|
+
* frame after pinning toggles may render with stale offsets but the
|
|
1016
|
+
* resize observer fires immediately afterwards.
|
|
1017
|
+
*/
|
|
1018
|
+
// eslint-disable-next-line svelte/prefer-svelte-reactivity
|
|
1019
|
+
_columnRenderedWidths = new SvelteMap();
|
|
1020
|
+
_virtualisation = new VirtualisationState({
|
|
1021
|
+
getRows: () => this.paginationRowModel.rows,
|
|
1022
|
+
// Row alignment is browser-handled in the single-grid layout, so
|
|
1023
|
+
// the per-side height pool was deleted along with its observers.
|
|
1024
|
+
// VirtualisationState falls back to `getEstimatedRowHeight` when
|
|
1025
|
+
// no measured value is available, which is sufficient for
|
|
1026
|
+
// determining the spacer heights to within one overscan band.
|
|
1027
|
+
getRowHeight: () => 0,
|
|
1028
|
+
getEstimatedRowHeight: () => (this.isCompact ? 28 : 48),
|
|
1029
|
+
});
|
|
1030
|
+
/**
|
|
1031
|
+
* Delegating getter preserved for backwards compatibility. Reads
|
|
1032
|
+
* through to `_sorting.sortedData`, which owns the comparator-hoist
|
|
1033
|
+
* optimisation and the `AbortController` short-circuit. Consumers
|
|
1034
|
+
* inside `src/lib` already point at `tableContext.sortedData`; the
|
|
1035
|
+
* delegation will be removed once Phase 6 v-next migrates every
|
|
1036
|
+
* reader to `tableContext._sorting.sortedData` directly.
|
|
1037
|
+
*/
|
|
1038
|
+
get sortedData() {
|
|
1039
|
+
return this._sorting.sortedData;
|
|
1040
|
+
}
|
|
827
1041
|
// eslint-disable-next-line svelte/prefer-svelte-reactivity
|
|
828
1042
|
_sortedRowModel = $state({ rows: [], rowsById: new Map() });
|
|
829
1043
|
get sortedRowModel() {
|
|
@@ -965,490 +1179,139 @@ export class TableContext {
|
|
|
965
1179
|
},
|
|
966
1180
|
};
|
|
967
1181
|
};
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
const
|
|
977
|
-
const centerVisibleCells = $derived(this.columnDefs
|
|
1182
|
+
// Iterating `this.columnDefs.filter(...)` instead of
|
|
1183
|
+
// `this.columnPinning.left?.keys()` puts pinned-left body
|
|
1184
|
+
// cells in declaration order (matching the header rendering
|
|
1185
|
+
// and the `getVisualColumns` tab-order). Iterating the
|
|
1186
|
+
// pinning Map's keys produced *insertion* order so that
|
|
1187
|
+
// pinning Name then ID gave a body row of [Name, ID] while
|
|
1188
|
+
// the header above it stayed [ID, Name]. See the duplicate
|
|
1189
|
+
// factory in `createRow` below for the same fix.
|
|
1190
|
+
const leftVisibleCells = $derived(this.columnDefs
|
|
978
1191
|
.filter((it) => {
|
|
979
|
-
return
|
|
1192
|
+
return (this.columnVisibility[it.id] !== false && this.columnPinning.left?.has(it.id) === true);
|
|
980
1193
|
})
|
|
981
1194
|
.map(makeRow));
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
_flushScheduled = false;
|
|
1018
|
-
_flushPendingSelectionChanges() {
|
|
1019
|
-
if (this._pendingSelectionChanges.size === 0) {
|
|
1020
|
-
return;
|
|
1021
|
-
}
|
|
1022
|
-
// Mutate in place to preserve SvelteMap's per-key reactive tracking.
|
|
1023
|
-
// Replacing _selectedItems with a cloned map would invalidate every .has()/.get()
|
|
1024
|
-
// subscriber across all visible rows, not just the changed keys.
|
|
1025
|
-
for (const [key, item] of this._pendingSelectionChanges) {
|
|
1026
|
-
if (item === null) {
|
|
1027
|
-
this.selectedItems.delete(key);
|
|
1028
|
-
}
|
|
1029
|
-
else {
|
|
1030
|
-
this.selectedItems.set(key, item);
|
|
1031
|
-
}
|
|
1032
|
-
}
|
|
1033
|
-
this._pendingSelectionChanges.clear();
|
|
1034
|
-
this._flushScheduled = false;
|
|
1035
|
-
}
|
|
1036
|
-
_schedulePendingFlush() {
|
|
1037
|
-
if (this._flushScheduled) {
|
|
1038
|
-
return;
|
|
1039
|
-
}
|
|
1040
|
-
this._flushScheduled = true;
|
|
1041
|
-
tick()
|
|
1042
|
-
.then(() => {
|
|
1043
|
-
this._flushPendingSelectionChanges();
|
|
1044
|
-
})
|
|
1045
|
-
.catch(devCatch);
|
|
1046
|
-
}
|
|
1047
|
-
selectionContains = (item) => {
|
|
1048
|
-
void item;
|
|
1049
|
-
void this.isSelectable;
|
|
1050
|
-
void this.selectedItems.size;
|
|
1051
|
-
// if (!$effect.tracking()) {
|
|
1052
|
-
// throw new Error(`selectionContains is not ran in a tracking context`);
|
|
1053
|
-
// }
|
|
1054
|
-
if (!this.isSelectable) {
|
|
1055
|
-
return true;
|
|
1056
|
-
}
|
|
1057
|
-
const rawIdentity = this._cachedKey(item);
|
|
1058
|
-
return rawIdentity instanceof Promise
|
|
1059
|
-
? rawIdentity.then((identity) => this.selectedItems.has(identity))
|
|
1060
|
-
: this.selectedItems.has(rawIdentity);
|
|
1061
|
-
};
|
|
1062
|
-
addInvalidValue = (item) => {
|
|
1063
|
-
const raw = this._cachedKey(item);
|
|
1064
|
-
if (raw instanceof Promise) {
|
|
1065
|
-
return raw.then((key) => {
|
|
1066
|
-
this.invalidValues.set(key, item);
|
|
1067
|
-
});
|
|
1068
|
-
}
|
|
1069
|
-
this.invalidValues.set(raw, item);
|
|
1070
|
-
};
|
|
1071
|
-
removeInvalidValue = (item) => {
|
|
1072
|
-
const raw = this._cachedKey(item);
|
|
1073
|
-
if (raw instanceof Promise) {
|
|
1074
|
-
return raw.then((key) => {
|
|
1075
|
-
this.invalidValues.delete(key);
|
|
1076
|
-
});
|
|
1077
|
-
}
|
|
1078
|
-
this.invalidValues.delete(raw);
|
|
1079
|
-
};
|
|
1080
|
-
setOpenModalCoordinates = (coordinates) => {
|
|
1081
|
-
this.openModalCoordinates = coordinates ? { ...coordinates } : null;
|
|
1082
|
-
};
|
|
1083
|
-
toggleHighlightedRow = (item) => {
|
|
1084
|
-
const raw = this._cachedKey(item);
|
|
1085
|
-
if (raw instanceof Promise) {
|
|
1086
|
-
return raw.then((key) => {
|
|
1087
|
-
if (this.highlightedItems.has(key)) {
|
|
1088
|
-
this.highlightedItems.delete(key);
|
|
1089
|
-
}
|
|
1090
|
-
else {
|
|
1091
|
-
this.highlightedItems.set(key, item);
|
|
1092
|
-
}
|
|
1093
|
-
});
|
|
1094
|
-
}
|
|
1095
|
-
if (this.highlightedItems.has(raw)) {
|
|
1096
|
-
this.highlightedItems.delete(raw);
|
|
1097
|
-
}
|
|
1098
|
-
else {
|
|
1099
|
-
this.highlightedItems.set(raw, item);
|
|
1100
|
-
}
|
|
1101
|
-
};
|
|
1102
|
-
resetHighlightedRows = () => {
|
|
1103
|
-
this.highlightedItems.clear();
|
|
1104
|
-
};
|
|
1105
|
-
toggleSelected = (item) => {
|
|
1106
|
-
const raw = this._cachedKey(item);
|
|
1107
|
-
if (raw instanceof Promise) {
|
|
1108
|
-
return raw.then((key) => {
|
|
1109
|
-
const pendingValue = this._pendingSelectionChanges.get(key);
|
|
1110
|
-
const isSelected = pendingValue !== undefined ? pendingValue !== null : this.selectedItems.has(key);
|
|
1111
|
-
this._pendingSelectionChanges.set(key, isSelected ? null : item);
|
|
1112
|
-
this._schedulePendingFlush();
|
|
1113
|
-
});
|
|
1114
|
-
}
|
|
1115
|
-
const pendingValue = this._pendingSelectionChanges.get(raw);
|
|
1116
|
-
const isSelected = pendingValue !== undefined ? pendingValue !== null : this.selectedItems.has(raw);
|
|
1117
|
-
this._pendingSelectionChanges.set(raw, isSelected ? null : item);
|
|
1118
|
-
this._schedulePendingFlush();
|
|
1119
|
-
};
|
|
1120
|
-
setSelected = (item, selected) => {
|
|
1121
|
-
const raw = this._cachedKey(item);
|
|
1122
|
-
if (raw instanceof Promise) {
|
|
1123
|
-
return raw.then((key) => {
|
|
1124
|
-
this._pendingSelectionChanges.set(key, selected ? item : null);
|
|
1125
|
-
this._schedulePendingFlush();
|
|
1126
|
-
});
|
|
1127
|
-
}
|
|
1128
|
-
this._pendingSelectionChanges.set(raw, selected ? item : null);
|
|
1129
|
-
this._schedulePendingFlush();
|
|
1130
|
-
};
|
|
1131
|
-
setSelectionMap = (set) => {
|
|
1132
|
-
this._selectedItems = set;
|
|
1133
|
-
};
|
|
1134
|
-
updateSelectedItems = async () => {
|
|
1135
|
-
if (this.selectedItems.size === 0) {
|
|
1136
|
-
return;
|
|
1137
|
-
}
|
|
1138
|
-
const pageStartIndex = this.paginationRepo ? this.paginationRepo.pageStartIndex : 0;
|
|
1139
|
-
const sortedData = this.sortedData;
|
|
1140
|
-
const pageEndIndexExclusive = this.paginationRepo
|
|
1141
|
-
? Math.min(this.paginationRepo.pageEndIndexExclusive, sortedData.length)
|
|
1142
|
-
: sortedData.length;
|
|
1143
|
-
// Build key → item map for the current page (O(page_size) extractions)
|
|
1144
|
-
// eslint-disable-next-line svelte/prefer-svelte-reactivity
|
|
1145
|
-
const pageKeyMap = new Map();
|
|
1146
|
-
const pending = [];
|
|
1147
|
-
for (let i = pageStartIndex; i < pageEndIndexExclusive; i++) {
|
|
1148
|
-
const item = sortedData[i];
|
|
1149
|
-
const raw = this._cachedKey(item);
|
|
1150
|
-
if (raw instanceof Promise) {
|
|
1151
|
-
pending.push(raw.then((key) => {
|
|
1152
|
-
pageKeyMap.set(key, item);
|
|
1153
|
-
}));
|
|
1154
|
-
}
|
|
1155
|
-
else {
|
|
1156
|
-
pageKeyMap.set(raw, item);
|
|
1157
|
-
}
|
|
1158
|
-
}
|
|
1159
|
-
if (pending.length > 0) {
|
|
1160
|
-
await Promise.all(pending);
|
|
1161
|
-
}
|
|
1162
|
-
// Update only selected items that appear on this page (O(selected_size))
|
|
1163
|
-
for (const key of this.selectedItems.keys()) {
|
|
1164
|
-
const newItem = pageKeyMap.get(key);
|
|
1165
|
-
if (newItem !== undefined) {
|
|
1166
|
-
this.selectedItems.set(key, newItem);
|
|
1167
|
-
}
|
|
1168
|
-
}
|
|
1169
|
-
};
|
|
1170
|
-
resetSelectedItems = () => {
|
|
1171
|
-
this._selectedItems.clear();
|
|
1172
|
-
};
|
|
1173
|
-
selectAllInCurrentPage = async () => {
|
|
1174
|
-
void this.paginationRepo?.pageStartIndex;
|
|
1175
|
-
const sortedData = this.sortedData;
|
|
1176
|
-
const pageStartIndex = this.paginationRepo ? this.paginationRepo.pageStartIndex : 0;
|
|
1177
|
-
const pageEndIndexExclusive = this.paginationRepo
|
|
1178
|
-
? Math.min(this.paginationRepo.pageEndIndexExclusive, sortedData.length)
|
|
1179
|
-
: sortedData.length;
|
|
1180
|
-
// Will be doing one full reassignment to this.selectedItems to avoid svelteMap redraws
|
|
1181
|
-
// const cloned = new SvelteMap(this.selectedItems);
|
|
1182
|
-
const sel = this.selectedItems; // HACK: keep the same svelteMap going so that we can support setSelectionMap()
|
|
1183
|
-
// if this is deemed problematic, we'll need to find another way to ask for a new map from the context consumer
|
|
1184
|
-
const pending = [];
|
|
1185
|
-
if (this.allSelectedInCurrentPage) {
|
|
1186
|
-
for (let i = pageStartIndex; i < pageEndIndexExclusive; i++) {
|
|
1187
|
-
const raw = this._cachedKey(sortedData[i]);
|
|
1188
|
-
if (raw instanceof Promise) {
|
|
1189
|
-
pending.push(raw.then((key) => {
|
|
1190
|
-
sel.delete(key);
|
|
1191
|
-
}));
|
|
1192
|
-
}
|
|
1193
|
-
else {
|
|
1194
|
-
sel.delete(raw);
|
|
1195
|
-
}
|
|
1196
|
-
}
|
|
1197
|
-
}
|
|
1198
|
-
else {
|
|
1199
|
-
const selectableMethod = this.columnDefs.find((it) => it instanceof RowSelectionDef)?.isSelectable;
|
|
1200
|
-
if (selectableMethod) {
|
|
1201
|
-
for (let i = pageStartIndex; i < pageEndIndexExclusive; i++) {
|
|
1202
|
-
const item = sortedData[i];
|
|
1203
|
-
const relIdx = i - pageStartIndex;
|
|
1204
|
-
const s = selectableMethod(item, relIdx);
|
|
1205
|
-
const doSet = (ok) => {
|
|
1206
|
-
if (!ok) {
|
|
1207
|
-
return;
|
|
1208
|
-
}
|
|
1209
|
-
const raw = this._cachedKey(item);
|
|
1210
|
-
if (raw instanceof Promise) {
|
|
1211
|
-
return raw.then((key) => {
|
|
1212
|
-
sel.set(key, item);
|
|
1213
|
-
});
|
|
1214
|
-
}
|
|
1215
|
-
sel.set(raw, item);
|
|
1216
|
-
};
|
|
1217
|
-
const r = s instanceof Promise ? s.then(doSet) : doSet(s);
|
|
1218
|
-
if (r instanceof Promise) {
|
|
1219
|
-
pending.push(r);
|
|
1220
|
-
}
|
|
1221
|
-
}
|
|
1222
|
-
}
|
|
1223
|
-
else {
|
|
1224
|
-
for (let i = pageStartIndex; i < pageEndIndexExclusive; i++) {
|
|
1225
|
-
const item = sortedData[i];
|
|
1226
|
-
const raw = this._cachedKey(item);
|
|
1227
|
-
if (raw instanceof Promise) {
|
|
1228
|
-
pending.push(raw.then((key) => {
|
|
1229
|
-
sel.set(key, item);
|
|
1230
|
-
}));
|
|
1231
|
-
}
|
|
1232
|
-
else {
|
|
1233
|
-
sel.set(raw, item);
|
|
1234
|
-
}
|
|
1235
|
-
}
|
|
1236
|
-
}
|
|
1237
|
-
}
|
|
1238
|
-
if (pending.length > 0) {
|
|
1239
|
-
await Promise.all(pending);
|
|
1240
|
-
}
|
|
1241
|
-
// HACK
|
|
1242
|
-
// this._selectedItems = cloned;
|
|
1243
|
-
};
|
|
1244
|
-
onHighlightAll = () => {
|
|
1245
|
-
if (this.allHighlighted) {
|
|
1246
|
-
// console.debug('All were highlighted. Clearing');
|
|
1247
|
-
this.highlightedItems.clear();
|
|
1248
|
-
return Promise.resolve();
|
|
1249
|
-
}
|
|
1250
|
-
else {
|
|
1251
|
-
const items = this.currentPageData;
|
|
1252
|
-
return asyncForEach(items, (item) => {
|
|
1253
|
-
const raw = this._cachedKey(item);
|
|
1254
|
-
if (raw instanceof Promise) {
|
|
1255
|
-
return raw.then((key) => {
|
|
1256
|
-
this.highlightedItems.set(key, item);
|
|
1257
|
-
});
|
|
1258
|
-
}
|
|
1259
|
-
this.highlightedItems.set(raw, item);
|
|
1260
|
-
return;
|
|
1261
|
-
});
|
|
1262
|
-
}
|
|
1263
|
-
};
|
|
1264
|
-
onEditCell = async (item, coords, value) => {
|
|
1265
|
-
const rawOldKey = this._cachedKey(item);
|
|
1266
|
-
const oldKey = rawOldKey instanceof Promise ? await rawOldKey : rawOldKey;
|
|
1267
|
-
const wasSelected = this.selectedItems.has(oldKey);
|
|
1268
|
-
if (wasSelected) {
|
|
1269
|
-
this.selectedItems.delete(oldKey);
|
|
1270
|
-
}
|
|
1271
|
-
// Invalidate cache — _onEditCell may mutate the item's key field in-place
|
|
1272
|
-
this._keyCache.delete(item);
|
|
1273
|
-
await this._onEditCell?.(item, coords, value);
|
|
1274
|
-
if (wasSelected && this.isSelectable) {
|
|
1275
|
-
const rawNewKey = this._cachedKey(item);
|
|
1276
|
-
const newKey = rawNewKey instanceof Promise ? await rawNewKey : rawNewKey;
|
|
1277
|
-
if (newKey) {
|
|
1278
|
-
this.selectedItems.set(newKey, item);
|
|
1279
|
-
}
|
|
1280
|
-
// this.recalculateAllSelectedInCurrentPage();
|
|
1281
|
-
}
|
|
1282
|
-
};
|
|
1283
|
-
handleTdKeydown = (e) => {
|
|
1284
|
-
e.stopPropagation();
|
|
1285
|
-
if (e.key.toLocaleUpperCase() === 'F' && e.ctrlKey && this.allowQuickFiltering) {
|
|
1286
|
-
e.preventDefault();
|
|
1287
|
-
this.toggleQuickFiltering();
|
|
1288
|
-
}
|
|
1289
|
-
else if (e.key === 'Escape') {
|
|
1290
|
-
e.preventDefault();
|
|
1291
|
-
this.focusStartIsBeingEdited = false;
|
|
1292
|
-
}
|
|
1293
|
-
else if (e.key === 'Tab') {
|
|
1294
|
-
//allow regular operation in side panels
|
|
1295
|
-
const target = e.target;
|
|
1296
|
-
if (target?.closest('.side-panel') != null ||
|
|
1297
|
-
target?.attributes.getNamedItem('data-type')?.value === 'quicksearch') {
|
|
1298
|
-
return;
|
|
1299
|
-
}
|
|
1300
|
-
e.preventDefault();
|
|
1301
|
-
if (e.getModifierState('Shift')) {
|
|
1302
|
-
this.tabBackward();
|
|
1303
|
-
}
|
|
1304
|
-
else {
|
|
1305
|
-
this.tabForward();
|
|
1306
|
-
}
|
|
1307
|
-
}
|
|
1308
|
-
if (e.target.tagName === 'INPUT' &&
|
|
1309
|
-
e.target.attributes.getNamedItem('type')?.value !== 'checkbox') {
|
|
1310
|
-
return;
|
|
1311
|
-
}
|
|
1312
|
-
this.handleKeystroke(e).catch(devCatch);
|
|
1313
|
-
};
|
|
1314
|
-
async handleKeystroke(e) {
|
|
1315
|
-
switch (e.key) {
|
|
1316
|
-
case 'Enter':
|
|
1317
|
-
case 'F2':
|
|
1318
|
-
if (!e.target?.classList.contains('editable')) {
|
|
1319
|
-
break;
|
|
1320
|
-
}
|
|
1321
|
-
e.preventDefault();
|
|
1322
|
-
e.target?.dispatchEvent(new CustomEvent('edit', { detail: { selectAll: e.key === 'Enter' } }));
|
|
1323
|
-
// focusStartIsBeingEdited.set(true);
|
|
1324
|
-
break;
|
|
1325
|
-
case 'ArrowUp': {
|
|
1326
|
-
e.preventDefault();
|
|
1327
|
-
if (e.getModifierState('Control')) {
|
|
1328
|
-
if (e.getModifierState('Shift')) {
|
|
1329
|
-
if (!this.allowCopy) {
|
|
1330
|
-
return;
|
|
1331
|
-
}
|
|
1332
|
-
this.focusToTop();
|
|
1333
|
-
}
|
|
1334
|
-
else {
|
|
1335
|
-
this.moveToTop();
|
|
1336
|
-
}
|
|
1337
|
-
}
|
|
1338
|
-
else if (e.getModifierState('Shift')) {
|
|
1339
|
-
if (!this.allowCopy) {
|
|
1340
|
-
return;
|
|
1341
|
-
}
|
|
1342
|
-
this.moveFocusUp();
|
|
1343
|
-
}
|
|
1344
|
-
else {
|
|
1345
|
-
this.setFocusUp();
|
|
1346
|
-
}
|
|
1347
|
-
return;
|
|
1348
|
-
}
|
|
1349
|
-
case 'ArrowDown': {
|
|
1350
|
-
e.preventDefault();
|
|
1351
|
-
if (e.getModifierState('Control')) {
|
|
1352
|
-
if (e.getModifierState('Shift')) {
|
|
1353
|
-
if (!this.allowCopy) {
|
|
1354
|
-
return;
|
|
1355
|
-
}
|
|
1356
|
-
this.focusToBottom();
|
|
1357
|
-
}
|
|
1358
|
-
else {
|
|
1359
|
-
this.moveToBottom();
|
|
1360
|
-
}
|
|
1361
|
-
}
|
|
1362
|
-
else if (e.getModifierState('Shift')) {
|
|
1363
|
-
if (!this.allowCopy) {
|
|
1364
|
-
return;
|
|
1365
|
-
}
|
|
1366
|
-
this.moveFocusDown();
|
|
1367
|
-
}
|
|
1368
|
-
else {
|
|
1369
|
-
this.setFocusDown();
|
|
1370
|
-
}
|
|
1371
|
-
return;
|
|
1372
|
-
}
|
|
1373
|
-
// TODO add ctrl-home and ctrl-end as ways to get to top-left/bottom-right
|
|
1374
|
-
case 'ArrowLeft':
|
|
1375
|
-
case 'Home': {
|
|
1376
|
-
e.preventDefault();
|
|
1377
|
-
if (e.getModifierState('Control') || e.key === 'Home') {
|
|
1378
|
-
if (e.getModifierState('Shift')) {
|
|
1379
|
-
if (!this.allowCopy) {
|
|
1380
|
-
return;
|
|
1381
|
-
}
|
|
1382
|
-
this.focusToStart();
|
|
1383
|
-
}
|
|
1384
|
-
else {
|
|
1385
|
-
this.moveToStart();
|
|
1386
|
-
}
|
|
1387
|
-
//these two at the bottom shouldn't happen on a home press
|
|
1388
|
-
}
|
|
1389
|
-
else if (e.getModifierState('Shift') && this.allowCopy) {
|
|
1390
|
-
this.moveFocusLeft();
|
|
1391
|
-
}
|
|
1392
|
-
else {
|
|
1393
|
-
this.setFocusLeft();
|
|
1394
|
-
}
|
|
1395
|
-
return;
|
|
1396
|
-
}
|
|
1397
|
-
case 'ArrowRight':
|
|
1398
|
-
case 'End': {
|
|
1399
|
-
e.preventDefault();
|
|
1400
|
-
if (e.getModifierState('Control') || e.key === 'End') {
|
|
1401
|
-
if (e.getModifierState('Shift')) {
|
|
1402
|
-
if (!this.allowCopy) {
|
|
1403
|
-
return;
|
|
1404
|
-
}
|
|
1405
|
-
this.focusToEnd();
|
|
1406
|
-
}
|
|
1407
|
-
else {
|
|
1408
|
-
this.moveToEnd();
|
|
1409
|
-
}
|
|
1410
|
-
}
|
|
1411
|
-
else if (e.getModifierState('Shift') && this.allowCopy) {
|
|
1412
|
-
this.moveFocusRight();
|
|
1413
|
-
}
|
|
1414
|
-
else {
|
|
1415
|
-
this.setFocusRight();
|
|
1416
|
-
}
|
|
1417
|
-
return;
|
|
1418
|
-
}
|
|
1419
|
-
default: {
|
|
1420
|
-
if (this.debug) {
|
|
1421
|
-
console.log(`handleKeystroke: ignoring key ${e.key}`);
|
|
1422
|
-
}
|
|
1423
|
-
break;
|
|
1424
|
-
}
|
|
1425
|
-
}
|
|
1426
|
-
if (this.allowCopy) {
|
|
1427
|
-
switch (e.key) {
|
|
1428
|
-
case 'a': {
|
|
1429
|
-
if (e.ctrlKey) {
|
|
1430
|
-
e.preventDefault();
|
|
1431
|
-
this.moveToTop();
|
|
1432
|
-
this.moveToStart();
|
|
1433
|
-
this.focusToBottom();
|
|
1434
|
-
this.focusToEnd();
|
|
1435
|
-
}
|
|
1436
|
-
break;
|
|
1437
|
-
}
|
|
1438
|
-
case 'c':
|
|
1439
|
-
case 'C':
|
|
1440
|
-
if (e.getModifierState('Control')) {
|
|
1441
|
-
e.preventDefault();
|
|
1442
|
-
await this.copyDataToClipboard();
|
|
1443
|
-
}
|
|
1444
|
-
break;
|
|
1445
|
-
default: {
|
|
1446
|
-
//nothing
|
|
1447
|
-
break;
|
|
1448
|
-
}
|
|
1449
|
-
}
|
|
1450
|
-
}
|
|
1195
|
+
const rightVisibleCells = $derived(this.columnDefs
|
|
1196
|
+
.filter((it) => {
|
|
1197
|
+
return (this.columnVisibility[it.id] !== false &&
|
|
1198
|
+
this.columnPinning.right?.has(it.id) === true);
|
|
1199
|
+
})
|
|
1200
|
+
.map(makeRow));
|
|
1201
|
+
const centerVisibleCells = $derived(this.columnDefs
|
|
1202
|
+
.filter((it) => {
|
|
1203
|
+
return (this.columnVisibility[it.id] !== false &&
|
|
1204
|
+
!(this.columnPinning.left?.has(it.id) || this.columnPinning.right?.has(it.id)));
|
|
1205
|
+
})
|
|
1206
|
+
.map(makeRow));
|
|
1207
|
+
return row;
|
|
1208
|
+
});
|
|
1209
|
+
});
|
|
1210
|
+
_paginationRowModel = $state({
|
|
1211
|
+
rows: [],
|
|
1212
|
+
// eslint-disable-next-line svelte/prefer-svelte-reactivity
|
|
1213
|
+
rowsById: new Map(),
|
|
1214
|
+
});
|
|
1215
|
+
get paginationRowModel() {
|
|
1216
|
+
return this._paginationRowModel;
|
|
1217
|
+
}
|
|
1218
|
+
// #endregion
|
|
1219
|
+
// #region public methods
|
|
1220
|
+
/**
|
|
1221
|
+
* Delegating wrapper preserved for backwards compatibility. The
|
|
1222
|
+
* key-extraction cache lives on `_selection` (Phase 6.5); this
|
|
1223
|
+
* method forwards to `_selection.cachedKey(item)` so legacy call
|
|
1224
|
+
* sites in `getHighlightedRowData` / `getFocusElementData` /
|
|
1225
|
+
* `originalRowIndices` / `sortedRowModel` / `onHighlightAll` see
|
|
1226
|
+
* no behavioural change.
|
|
1227
|
+
*/
|
|
1228
|
+
_cachedKey(item) {
|
|
1229
|
+
return this._selection.cachedKey(item);
|
|
1451
1230
|
}
|
|
1231
|
+
/** Delegating accessor preserved for backwards compatibility. The
|
|
1232
|
+
* implementation lives on `_selection.selectionContains` (Phase 6.5). */
|
|
1233
|
+
selectionContains = (item) => {
|
|
1234
|
+
return this._selection.selectionContains(item);
|
|
1235
|
+
};
|
|
1236
|
+
/** Delegating accessor preserved for backwards compatibility. */
|
|
1237
|
+
addInvalidValue = (item) => {
|
|
1238
|
+
return this._selection.addInvalidValue(item);
|
|
1239
|
+
};
|
|
1240
|
+
/** Delegating accessor preserved for backwards compatibility. */
|
|
1241
|
+
removeInvalidValue = (item) => {
|
|
1242
|
+
return this._selection.removeInvalidValue(item);
|
|
1243
|
+
};
|
|
1244
|
+
/**
|
|
1245
|
+
* Stores or clears the cell whose per-cell modal is currently open.
|
|
1246
|
+
*
|
|
1247
|
+
* Pass `{ row, columnId }` to open; pass `null` to close. The `row`
|
|
1248
|
+
* value must be the same object reference the table holds for that row
|
|
1249
|
+
* (`cell.row.original`) - identity comparison is what the cell
|
|
1250
|
+
* renderers use to decide which one of them should render the modal.
|
|
1251
|
+
*/
|
|
1252
|
+
setOpenModalCell = (cell) => {
|
|
1253
|
+
this.openModalCell = cell ? { row: cell.row, columnId: cell.columnId } : null;
|
|
1254
|
+
};
|
|
1255
|
+
/** Delegating accessor preserved for backwards compatibility. */
|
|
1256
|
+
toggleHighlightedRow = (item) => {
|
|
1257
|
+
return this._selection.toggleHighlightedRow(item);
|
|
1258
|
+
};
|
|
1259
|
+
/** Delegating accessor preserved for backwards compatibility. */
|
|
1260
|
+
resetHighlightedRows = () => {
|
|
1261
|
+
this._selection.resetHighlightedRows();
|
|
1262
|
+
};
|
|
1263
|
+
/** Delegating accessor preserved for backwards compatibility. */
|
|
1264
|
+
toggleSelected = (item) => {
|
|
1265
|
+
return this._selection.toggleSelected(item);
|
|
1266
|
+
};
|
|
1267
|
+
/** Delegating accessor preserved for backwards compatibility. */
|
|
1268
|
+
setSelected = (item, selected) => {
|
|
1269
|
+
return this._selection.setSelected(item, selected);
|
|
1270
|
+
};
|
|
1271
|
+
/** Delegating accessor preserved for backwards compatibility. */
|
|
1272
|
+
setSelectionMap = (set) => {
|
|
1273
|
+
this._selection.setSelectionMap(set);
|
|
1274
|
+
};
|
|
1275
|
+
/** Delegating accessor preserved for backwards compatibility. */
|
|
1276
|
+
updateSelectedItems = async () => {
|
|
1277
|
+
await this._selection.updateSelectedItems();
|
|
1278
|
+
};
|
|
1279
|
+
/** Delegating accessor preserved for backwards compatibility. */
|
|
1280
|
+
resetSelectedItems = () => {
|
|
1281
|
+
this._selection.resetSelectedItems();
|
|
1282
|
+
};
|
|
1283
|
+
/** Delegating accessor preserved for backwards compatibility. */
|
|
1284
|
+
selectAllInCurrentPage = async () => {
|
|
1285
|
+
await this._selection.selectAllInCurrentPage();
|
|
1286
|
+
};
|
|
1287
|
+
/** Delegating accessor preserved for backwards compatibility. */
|
|
1288
|
+
onHighlightAll = () => {
|
|
1289
|
+
return this._selection.onHighlightAll();
|
|
1290
|
+
};
|
|
1291
|
+
/**
|
|
1292
|
+
* Invoked by every editable cell on commit. Split between this
|
|
1293
|
+
* class (the user-supplied edit callback) and `_selection`
|
|
1294
|
+
* (the key-cache invalidation + selection-rebind half). The
|
|
1295
|
+
* sub-context's `handleItemMutation` accepts a thunk that runs
|
|
1296
|
+
* the consumer callback between the pre- and post-edit selection
|
|
1297
|
+
* bookkeeping so the boundary stays explicit.
|
|
1298
|
+
*/
|
|
1299
|
+
onEditCell = async (item, coords, value) => {
|
|
1300
|
+
await this._selection.handleItemMutation(item, async () => {
|
|
1301
|
+
await this._onEditCell?.(item, coords, value);
|
|
1302
|
+
});
|
|
1303
|
+
};
|
|
1304
|
+
/**
|
|
1305
|
+
* Delegating accessor preserved for backwards compatibility. The
|
|
1306
|
+
* implementation lives on `_focus.handleTdKeydown` (Phase 6.6).
|
|
1307
|
+
* Bound to the root `<table>` container's `onkeydown` listener;
|
|
1308
|
+
* routes Ctrl+F / Escape / Tab synchronously and dispatches the
|
|
1309
|
+
* arrow-key / Home / End / Ctrl+A / Ctrl+C path asynchronously.
|
|
1310
|
+
*/
|
|
1311
|
+
handleTdKeydown = (e) => {
|
|
1312
|
+
this._focus.handleTdKeydown(e);
|
|
1313
|
+
};
|
|
1314
|
+
/** Toggles quick-filtering visibility and refocuses the matching cell. */
|
|
1452
1315
|
toggleQuickFiltering = () => {
|
|
1453
1316
|
if (this.allowQuickFiltering) {
|
|
1454
1317
|
const fs = this.focusStart;
|
|
@@ -1466,13 +1329,26 @@ export class TableContext {
|
|
|
1466
1329
|
.catch(devCatch);
|
|
1467
1330
|
}
|
|
1468
1331
|
};
|
|
1332
|
+
/**
|
|
1333
|
+
* Applies an updater to the column-pinning state (left / right
|
|
1334
|
+
* pins). Delegates to `_columnLayout.setColumnPinning`, which
|
|
1335
|
+
* enforces the `allowColumnReordering` master gate.
|
|
1336
|
+
*/
|
|
1469
1337
|
setColumnPinning = (updater) => {
|
|
1470
|
-
|
|
1471
|
-
return;
|
|
1472
|
-
}
|
|
1473
|
-
this.columnPinning = updater(this.columnPinning);
|
|
1338
|
+
this._columnLayout.setColumnPinning(updater);
|
|
1474
1339
|
};
|
|
1475
|
-
|
|
1340
|
+
/**
|
|
1341
|
+
* Delegating accessor preserved for backwards compatibility. The
|
|
1342
|
+
* actual `$state` slot lives on `_filtering`; this getter / setter
|
|
1343
|
+
* pair forwards reads and writes so existing consumers (notably
|
|
1344
|
+
* `generateTableOptions`) need no migration.
|
|
1345
|
+
*/
|
|
1346
|
+
get updateFilters() {
|
|
1347
|
+
return this._filtering.updateFilters;
|
|
1348
|
+
}
|
|
1349
|
+
set updateFilters(v) {
|
|
1350
|
+
this._filtering.updateFilters = v;
|
|
1351
|
+
}
|
|
1476
1352
|
updateVisibility = (stateOrCallback) => {
|
|
1477
1353
|
if (typeof stateOrCallback == 'function') {
|
|
1478
1354
|
this.columnVisibility = stateOrCallback(this.columnVisibility);
|
|
@@ -1495,6 +1371,7 @@ export class TableContext {
|
|
|
1495
1371
|
// return this._rowModel;
|
|
1496
1372
|
// }
|
|
1497
1373
|
lastPage = $derived(this.dataRepo.lastPage ?? 0);
|
|
1374
|
+
/** Canvas-measured width of a column header label, plus padding. */
|
|
1498
1375
|
measureHeaderWidth = (columnDef) => {
|
|
1499
1376
|
const label = columnDef.header;
|
|
1500
1377
|
if (typeof label === 'string' && browser) {
|
|
@@ -1516,6 +1393,7 @@ export class TableContext {
|
|
|
1516
1393
|
}
|
|
1517
1394
|
return 0;
|
|
1518
1395
|
};
|
|
1396
|
+
/** Sizes a column to fit its widest current-page cell label. */
|
|
1519
1397
|
autoResize = async (columnDef) => {
|
|
1520
1398
|
if (!browser) {
|
|
1521
1399
|
return;
|
|
@@ -1541,6 +1419,11 @@ export class TableContext {
|
|
|
1541
1419
|
}
|
|
1542
1420
|
this.columnSizing[colId] = maxWidth + 32; //standard extra cell padding
|
|
1543
1421
|
};
|
|
1422
|
+
/**
|
|
1423
|
+
* Drops the in-progress column drag onto the supplied target,
|
|
1424
|
+
* updating `columnDefs`, pinning state, and focus. No-op when
|
|
1425
|
+
* column reordering is disabled.
|
|
1426
|
+
*/
|
|
1544
1427
|
reorderColumn = (dropTarget) => {
|
|
1545
1428
|
if (!this.allowColumnReordering) {
|
|
1546
1429
|
return;
|
|
@@ -1602,6 +1485,41 @@ export class TableContext {
|
|
|
1602
1485
|
this.columnDefs = newDefs;
|
|
1603
1486
|
// this.forceVisibilityUpdate();
|
|
1604
1487
|
};
|
|
1488
|
+
/**
|
|
1489
|
+
* Programmatic column-reorder primitive used by keyboard accessibility
|
|
1490
|
+
* shortcuts in the column-management panel. Moves the column at
|
|
1491
|
+
* {@link currentIndex} to {@link newIndex} (both expressed in the
|
|
1492
|
+
* sorted-by-`index` order of {@link columnDefs}). No-op when column
|
|
1493
|
+
* reordering is disabled or indices are out of range / unchanged.
|
|
1494
|
+
*/
|
|
1495
|
+
moveColumnTo = (currentIndex, newIndex) => {
|
|
1496
|
+
if (!this.allowColumnReordering) {
|
|
1497
|
+
return;
|
|
1498
|
+
}
|
|
1499
|
+
const newDefs = this.columnDefs.concat();
|
|
1500
|
+
newDefs
|
|
1501
|
+
.sort((a, b) => a.index - b.index)
|
|
1502
|
+
.forEach((element, index) => {
|
|
1503
|
+
element.index = index;
|
|
1504
|
+
});
|
|
1505
|
+
if (currentIndex < 0 ||
|
|
1506
|
+
currentIndex >= newDefs.length ||
|
|
1507
|
+
newIndex < 0 ||
|
|
1508
|
+
newIndex >= newDefs.length ||
|
|
1509
|
+
currentIndex === newIndex) {
|
|
1510
|
+
return;
|
|
1511
|
+
}
|
|
1512
|
+
const [moved] = newDefs.splice(currentIndex, 1);
|
|
1513
|
+
newDefs.splice(newIndex, 0, moved);
|
|
1514
|
+
newDefs.forEach((element, index) => {
|
|
1515
|
+
element.index = index;
|
|
1516
|
+
});
|
|
1517
|
+
this._setNewPinningState();
|
|
1518
|
+
this.updateDefsBasedOnPinning();
|
|
1519
|
+
this.unfocus();
|
|
1520
|
+
this.columnDefs = newDefs;
|
|
1521
|
+
};
|
|
1522
|
+
/** Copies the highlighted rows to the OS clipboard as TSV / CSV. */
|
|
1605
1523
|
copyHighlightedRowsToClipboard = async () => {
|
|
1606
1524
|
// NOTE: False Positive. Clipboard does not exist in http environments
|
|
1607
1525
|
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
@@ -1611,6 +1529,7 @@ export class TableContext {
|
|
|
1611
1529
|
}
|
|
1612
1530
|
return this._performRowCopy(await this.getHighlightedRowData());
|
|
1613
1531
|
};
|
|
1532
|
+
/** Copies the currently focused cell range to the OS clipboard. */
|
|
1614
1533
|
copyDataToClipboard = async () => {
|
|
1615
1534
|
// NOTE: False Positive. Clipboard does not exist in http environments
|
|
1616
1535
|
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
@@ -1645,11 +1564,13 @@ export class TableContext {
|
|
|
1645
1564
|
const value = columnOptions?.find((it) => it.value === focusedElementData[0][0])?.label ??
|
|
1646
1565
|
focusedElementData[0][0]?.toString() ??
|
|
1647
1566
|
'';
|
|
1648
|
-
|
|
1567
|
+
// Single-cell copy bypasses TSV/CSV wrapping but still lands
|
|
1568
|
+
// in a spreadsheet; neutralise formula-injection prefixes.
|
|
1569
|
+
return escapeForSpreadsheet(value);
|
|
1649
1570
|
}
|
|
1650
1571
|
else {
|
|
1651
1572
|
const value = focusedElementData[0][0]?.toString().trim() ?? '';
|
|
1652
|
-
return value;
|
|
1573
|
+
return escapeForSpreadsheet(value);
|
|
1653
1574
|
}
|
|
1654
1575
|
}
|
|
1655
1576
|
return `${shouldCopyHeaders ? `${focusedColumnIds.join(separator)}\n` : ''}${focusedElementData
|
|
@@ -1678,238 +1599,124 @@ export class TableContext {
|
|
|
1678
1599
|
})();
|
|
1679
1600
|
navigator.clipboard.writeText(value).catch(devCatch);
|
|
1680
1601
|
};
|
|
1602
|
+
/** Delegating accessor preserved for backwards compatibility. The
|
|
1603
|
+
* implementation lives on `_focus.startFocus` (Phase 6.6). */
|
|
1681
1604
|
startFocus = (coords) => {
|
|
1682
|
-
this.
|
|
1683
|
-
this.moveFocus(coords);
|
|
1605
|
+
this._focus.startFocus(coords);
|
|
1684
1606
|
};
|
|
1607
|
+
/** Delegating accessor preserved for backwards compatibility. The
|
|
1608
|
+
* implementation lives on `_focus.moveFocus` (Phase 6.6). */
|
|
1685
1609
|
moveFocus = (coords, startEditing = false) => {
|
|
1686
|
-
this.
|
|
1687
|
-
this.focusEnd = { ...coords };
|
|
1688
|
-
if (startEditing) {
|
|
1689
|
-
tick()
|
|
1690
|
-
.then(() => {
|
|
1691
|
-
this.focusStartIsBeingEdited = true;
|
|
1692
|
-
})
|
|
1693
|
-
.catch(devCatch);
|
|
1694
|
-
}
|
|
1610
|
+
this._focus.moveFocus(coords, startEditing);
|
|
1695
1611
|
};
|
|
1612
|
+
/** Delegating accessor preserved for backwards compatibility. */
|
|
1696
1613
|
unfocus = () => {
|
|
1697
|
-
this.
|
|
1698
|
-
this.focusStart = null;
|
|
1699
|
-
this.focusEnd = null;
|
|
1614
|
+
this._focus.unfocus();
|
|
1700
1615
|
};
|
|
1616
|
+
/** Delegating accessor preserved for backwards compatibility. */
|
|
1701
1617
|
focusToTop = () => {
|
|
1702
|
-
|
|
1703
|
-
return;
|
|
1704
|
-
}
|
|
1705
|
-
this._moveFocusEndRow(-Infinity);
|
|
1618
|
+
this._focus.focusToTop();
|
|
1706
1619
|
};
|
|
1620
|
+
/** Delegating accessor preserved for backwards compatibility. */
|
|
1707
1621
|
focusToBottom = () => {
|
|
1708
|
-
|
|
1709
|
-
return;
|
|
1710
|
-
}
|
|
1711
|
-
this._moveFocusEndRow(Infinity);
|
|
1622
|
+
this._focus.focusToBottom();
|
|
1712
1623
|
};
|
|
1624
|
+
/** Delegating accessor preserved for backwards compatibility. */
|
|
1713
1625
|
moveToBottom = () => {
|
|
1714
|
-
this.
|
|
1626
|
+
this._focus.moveToBottom();
|
|
1715
1627
|
};
|
|
1628
|
+
/** Delegating accessor preserved for backwards compatibility. */
|
|
1716
1629
|
moveToTop = () => {
|
|
1717
|
-
this.
|
|
1630
|
+
this._focus.moveToTop();
|
|
1718
1631
|
};
|
|
1632
|
+
/** Delegating accessor preserved for backwards compatibility. */
|
|
1719
1633
|
moveFocusUp = () => {
|
|
1720
|
-
|
|
1721
|
-
return;
|
|
1722
|
-
}
|
|
1723
|
-
this._moveFocusEndRow(-1);
|
|
1634
|
+
this._focus.moveFocusUp();
|
|
1724
1635
|
};
|
|
1636
|
+
/** Delegating accessor preserved for backwards compatibility. */
|
|
1725
1637
|
setFocusUp = () => {
|
|
1726
|
-
this.
|
|
1638
|
+
this._focus.setFocusUp();
|
|
1727
1639
|
};
|
|
1640
|
+
/** Delegating accessor preserved for backwards compatibility. */
|
|
1728
1641
|
tabForward = () => {
|
|
1729
|
-
|
|
1730
|
-
return;
|
|
1731
|
-
}
|
|
1732
|
-
const defs = this.columnDefs;
|
|
1733
|
-
const visibility = this.columnVisibility;
|
|
1734
|
-
const indexBounds = defs.length;
|
|
1735
|
-
const rowBounds = this.sortedData.length;
|
|
1736
|
-
if (!this.focusStart || !rowBounds) {
|
|
1737
|
-
return;
|
|
1738
|
-
}
|
|
1739
|
-
let { column: index, row } = this.focusStart;
|
|
1740
|
-
++index;
|
|
1741
|
-
while (row < rowBounds) {
|
|
1742
|
-
while (index < indexBounds) {
|
|
1743
|
-
const newId = defs[index].id;
|
|
1744
|
-
if (newId && visibility[newId] !== false) {
|
|
1745
|
-
this.moveFocus({ id: newId, row, column: index }, this.focusStartIsBeingEdited);
|
|
1746
|
-
return;
|
|
1747
|
-
}
|
|
1748
|
-
++index;
|
|
1749
|
-
}
|
|
1750
|
-
index = 0;
|
|
1751
|
-
++row;
|
|
1752
|
-
}
|
|
1642
|
+
this._focus.tabForward();
|
|
1753
1643
|
};
|
|
1644
|
+
/** Delegating accessor preserved for backwards compatibility. */
|
|
1754
1645
|
tabBackward = () => {
|
|
1755
|
-
|
|
1756
|
-
return;
|
|
1757
|
-
}
|
|
1758
|
-
const maxIndexRight = this.columnDefs.length - 1;
|
|
1759
|
-
const defs = this.columnDefs;
|
|
1760
|
-
const visibility = this.columnVisibility;
|
|
1761
|
-
if (!this.focusStart) {
|
|
1762
|
-
return;
|
|
1763
|
-
}
|
|
1764
|
-
let { column: index, row } = this.focusStart;
|
|
1765
|
-
--index;
|
|
1766
|
-
while (row > -1) {
|
|
1767
|
-
while (index > -1) {
|
|
1768
|
-
const newId = defs[index].id;
|
|
1769
|
-
if (newId && visibility[newId] !== false) {
|
|
1770
|
-
this.moveFocus({ id: newId, row, column: index }, this.focusStartIsBeingEdited);
|
|
1771
|
-
return;
|
|
1772
|
-
}
|
|
1773
|
-
--index;
|
|
1774
|
-
}
|
|
1775
|
-
index = maxIndexRight;
|
|
1776
|
-
--row;
|
|
1777
|
-
}
|
|
1646
|
+
this._focus.tabBackward();
|
|
1778
1647
|
};
|
|
1648
|
+
/** Delegating accessor preserved for backwards compatibility. */
|
|
1779
1649
|
focusToStart = () => {
|
|
1780
|
-
|
|
1781
|
-
return;
|
|
1782
|
-
}
|
|
1783
|
-
if (!this.focusEnd) {
|
|
1784
|
-
return;
|
|
1785
|
-
}
|
|
1786
|
-
const visualCols = this._visualColumns;
|
|
1787
|
-
if (visualCols.length > 0) {
|
|
1788
|
-
const first = visualCols[0];
|
|
1789
|
-
this.focusEnd = { ...this.focusEnd, id: first.id, column: first.index };
|
|
1790
|
-
}
|
|
1650
|
+
this._focus.focusToStart();
|
|
1791
1651
|
};
|
|
1652
|
+
/** Delegating accessor preserved for backwards compatibility. */
|
|
1792
1653
|
moveToStart = () => {
|
|
1793
|
-
|
|
1794
|
-
return;
|
|
1795
|
-
}
|
|
1796
|
-
const visualCols = this._visualColumns;
|
|
1797
|
-
if (visualCols.length > 0) {
|
|
1798
|
-
const first = visualCols[0];
|
|
1799
|
-
this.moveFocus({ ...this.focusStart, id: first.id, column: first.index });
|
|
1800
|
-
}
|
|
1654
|
+
this._focus.moveToStart();
|
|
1801
1655
|
};
|
|
1656
|
+
/** Delegating accessor preserved for backwards compatibility. */
|
|
1802
1657
|
focusToEnd = () => {
|
|
1803
|
-
|
|
1804
|
-
return;
|
|
1805
|
-
}
|
|
1806
|
-
if (!this.focusEnd) {
|
|
1807
|
-
return;
|
|
1808
|
-
}
|
|
1809
|
-
const visualCols = this._visualColumns;
|
|
1810
|
-
if (visualCols.length > 0) {
|
|
1811
|
-
const last = visualCols[visualCols.length - 1];
|
|
1812
|
-
this.focusEnd = { ...this.focusEnd, id: last.id, column: last.index };
|
|
1813
|
-
}
|
|
1658
|
+
this._focus.focusToEnd();
|
|
1814
1659
|
};
|
|
1660
|
+
/** Delegating accessor preserved for backwards compatibility. */
|
|
1815
1661
|
moveToEnd = () => {
|
|
1816
|
-
|
|
1817
|
-
return;
|
|
1818
|
-
}
|
|
1819
|
-
const visualCols = this._visualColumns;
|
|
1820
|
-
if (visualCols.length > 0) {
|
|
1821
|
-
const last = visualCols[visualCols.length - 1];
|
|
1822
|
-
this.moveFocus({ ...this.focusStart, id: last.id, column: last.index });
|
|
1823
|
-
}
|
|
1662
|
+
this._focus.moveToEnd();
|
|
1824
1663
|
};
|
|
1664
|
+
/** Delegating accessor preserved for backwards compatibility. */
|
|
1825
1665
|
moveFocusDown = () => {
|
|
1826
|
-
|
|
1827
|
-
return;
|
|
1828
|
-
}
|
|
1829
|
-
this._moveFocusEndRow(1);
|
|
1666
|
+
this._focus.moveFocusDown();
|
|
1830
1667
|
};
|
|
1668
|
+
/** Delegating accessor preserved for backwards compatibility. */
|
|
1831
1669
|
setFocusDown = () => {
|
|
1832
|
-
this.
|
|
1670
|
+
this._focus.setFocusDown();
|
|
1833
1671
|
};
|
|
1672
|
+
/** Delegating accessor preserved for backwards compatibility. */
|
|
1834
1673
|
moveFocusLeft = () => {
|
|
1835
|
-
|
|
1836
|
-
return;
|
|
1837
|
-
}
|
|
1838
|
-
if (this.focusEnd != null) {
|
|
1839
|
-
const visualCols = this._visualColumns;
|
|
1840
|
-
const visualIndex = this.columnVisualIndex(this.focusEnd.id);
|
|
1841
|
-
if (visualIndex > 0) {
|
|
1842
|
-
const prev = visualCols[visualIndex - 1];
|
|
1843
|
-
this.focusEnd = { ...this.focusEnd, id: prev.id, column: prev.index };
|
|
1844
|
-
}
|
|
1845
|
-
}
|
|
1674
|
+
this._focus.moveFocusLeft();
|
|
1846
1675
|
};
|
|
1676
|
+
/** Delegating accessor preserved for backwards compatibility. */
|
|
1847
1677
|
setFocusLeft = () => {
|
|
1848
|
-
|
|
1849
|
-
return;
|
|
1850
|
-
}
|
|
1851
|
-
const visualCols = this._visualColumns;
|
|
1852
|
-
const visualIndex = this.columnVisualIndex(this.focusStart.id);
|
|
1853
|
-
if (visualIndex > 0) {
|
|
1854
|
-
const prev = visualCols[visualIndex - 1];
|
|
1855
|
-
this.moveFocus({ ...this.focusStart, id: prev.id, column: prev.index });
|
|
1856
|
-
}
|
|
1678
|
+
this._focus.setFocusLeft();
|
|
1857
1679
|
};
|
|
1680
|
+
/** Delegating accessor preserved for backwards compatibility. */
|
|
1858
1681
|
moveFocusRight = () => {
|
|
1859
|
-
|
|
1860
|
-
return;
|
|
1861
|
-
}
|
|
1862
|
-
if (this.focusEnd != null) {
|
|
1863
|
-
const visualCols = this._visualColumns;
|
|
1864
|
-
const visualIndex = this.columnVisualIndex(this.focusEnd.id);
|
|
1865
|
-
if (visualIndex < visualCols.length - 1) {
|
|
1866
|
-
const next = visualCols[visualIndex + 1];
|
|
1867
|
-
this.focusEnd = { ...this.focusEnd, id: next.id, column: next.index };
|
|
1868
|
-
}
|
|
1869
|
-
}
|
|
1682
|
+
this._focus.moveFocusRight();
|
|
1870
1683
|
};
|
|
1684
|
+
/** Delegating accessor preserved for backwards compatibility. */
|
|
1871
1685
|
setFocusRight = () => {
|
|
1872
|
-
|
|
1873
|
-
return;
|
|
1874
|
-
}
|
|
1875
|
-
const visualCols = this._visualColumns;
|
|
1876
|
-
const visualIndex = this.columnVisualIndex(this.focusStart.id);
|
|
1877
|
-
if (visualIndex < visualCols.length - 1) {
|
|
1878
|
-
const next = visualCols[visualIndex + 1];
|
|
1879
|
-
this.moveFocus({ ...this.focusStart, id: next.id, column: next.index });
|
|
1880
|
-
}
|
|
1686
|
+
this._focus.setFocusRight();
|
|
1881
1687
|
};
|
|
1688
|
+
/** Delegating accessor preserved for backwards compatibility. */
|
|
1882
1689
|
endFocus = (coords) => {
|
|
1883
|
-
|
|
1884
|
-
this.isMousingDown = false;
|
|
1885
|
-
if (!this.allowCopy) {
|
|
1886
|
-
return;
|
|
1887
|
-
}
|
|
1888
|
-
this.focusEnd = { ...coords };
|
|
1889
|
-
}
|
|
1690
|
+
this._focus.endFocus(coords);
|
|
1890
1691
|
};
|
|
1692
|
+
/** Toggles compact row sizing and persists to localStorage. */
|
|
1891
1693
|
setIsCompact = (value) => {
|
|
1892
1694
|
this.isCompact = value;
|
|
1893
1695
|
this._updateLocalStorageSettings();
|
|
1894
1696
|
};
|
|
1697
|
+
/** Toggles alternating row colours and persists to localStorage. */
|
|
1895
1698
|
setAlternateRowColours = (value) => {
|
|
1896
1699
|
this.alternateRowColours = value;
|
|
1897
1700
|
this._updateLocalStorageSettings();
|
|
1898
1701
|
};
|
|
1702
|
+
/** Toggles single-click editing and persists to localStorage. */
|
|
1899
1703
|
setSingleClickEditing = (value) => {
|
|
1900
1704
|
this.singleClickEditing = value;
|
|
1901
1705
|
this._updateLocalStorageSettings();
|
|
1902
1706
|
};
|
|
1707
|
+
/** Toggles row-hover colour change and persists to localStorage. */
|
|
1903
1708
|
setChangeColourOnHover = (value) => {
|
|
1904
1709
|
this.changeColourOnHover = value;
|
|
1905
1710
|
this._updateLocalStorageSettings();
|
|
1906
1711
|
};
|
|
1712
|
+
/** Toggles whether copy-to-clipboard prepends a header row and persists. */
|
|
1907
1713
|
setCopyWithHeaders = (value) => {
|
|
1908
1714
|
if (this.allowCopy) {
|
|
1909
1715
|
this.copyWithHeaders = value;
|
|
1910
1716
|
this._updateLocalStorageSettings();
|
|
1911
1717
|
}
|
|
1912
1718
|
};
|
|
1719
|
+
/** Toggles CSV vs TSV copy-to-clipboard separator and persists. */
|
|
1913
1720
|
setCommaSeparatedCopy = (value) => {
|
|
1914
1721
|
if (this.allowCopy) {
|
|
1915
1722
|
this.commaSeparatedCopy = value;
|
|
@@ -1929,63 +1736,41 @@ export class TableContext {
|
|
|
1929
1736
|
// });
|
|
1930
1737
|
// }
|
|
1931
1738
|
// };
|
|
1739
|
+
/**
|
|
1740
|
+
* Delegating method preserved for backwards compatibility. Applies
|
|
1741
|
+
* the preset to the live column layout, forwards the preset's
|
|
1742
|
+
* `sortingState` to the data-repository updater, and persists the
|
|
1743
|
+
* selected name. The underlying implementation lives on
|
|
1744
|
+
* `_preferences.setSelectedPreset` (Phase 6.4).
|
|
1745
|
+
*
|
|
1746
|
+
* The pre-extraction debug warning ("no sorting state found") was
|
|
1747
|
+
* emitted unconditionally when `paginationRepo.updateSorting` was
|
|
1748
|
+
* absent; the sub-context skips that warning because the
|
|
1749
|
+
* `applySortingState` thunk already no-ops in that case. The
|
|
1750
|
+
* warning is reinstated below so the surface is byte-identical.
|
|
1751
|
+
*/
|
|
1932
1752
|
setSelectedPreset = (preset) => {
|
|
1933
|
-
if (this.debug) {
|
|
1934
|
-
console.log('setting selected preset:', preset);
|
|
1935
|
-
}
|
|
1936
|
-
this.columnDefs = preset.columnDefs;
|
|
1937
1753
|
if (!this.paginationRepo?.updateSorting) {
|
|
1938
1754
|
console.warn('no sorting state found');
|
|
1939
1755
|
}
|
|
1940
|
-
this.
|
|
1941
|
-
this.columnVisibility = preset.visibilityState;
|
|
1942
|
-
this.columnPinning = preset.columnPinningState;
|
|
1943
|
-
this.selectedPreset = preset;
|
|
1944
|
-
localStorage.setItem(`${this.userId}-${this.tableName}-selected-preset-name`, preset.name);
|
|
1756
|
+
this._preferences.setSelectedPreset(preset);
|
|
1945
1757
|
};
|
|
1758
|
+
/**
|
|
1759
|
+
* Delegating method preserved for backwards compatibility. Adds or
|
|
1760
|
+
* replaces a saved preset for the current column layout and
|
|
1761
|
+
* persists the full preset list to localStorage. Delegates to
|
|
1762
|
+
* `_preferences.saveColumnPreset` (Phase 6.4).
|
|
1763
|
+
*/
|
|
1946
1764
|
saveColumnPreset = (name) => {
|
|
1947
|
-
|
|
1948
|
-
return;
|
|
1949
|
-
}
|
|
1950
|
-
const visibilityState = this.columnVisibility;
|
|
1951
|
-
const columnPinningState = this.columnPinning;
|
|
1952
|
-
const columnDefs = this.columnDefs;
|
|
1953
|
-
const sortingState = this.paginationRepo?.sorting || [];
|
|
1954
|
-
const newPreset = { columnDefs, name, visibilityState, columnPinningState, sortingState };
|
|
1955
|
-
const lowercasePresetname = name.toLocaleLowerCase();
|
|
1956
|
-
const indexToReplace = this.columnPresets.findIndex((oldPreset) => oldPreset.name.toLocaleLowerCase() === lowercasePresetname);
|
|
1957
|
-
const newPresets = this.columnPresets.concat();
|
|
1958
|
-
if (indexToReplace > -1) {
|
|
1959
|
-
newPresets[indexToReplace] = newPreset;
|
|
1960
|
-
}
|
|
1961
|
-
else {
|
|
1962
|
-
newPresets.push(newPreset);
|
|
1963
|
-
}
|
|
1964
|
-
this.columnPresets = newPresets;
|
|
1965
|
-
const jsonFriendly = newPresets.map((preset) => {
|
|
1966
|
-
return {
|
|
1967
|
-
...preset,
|
|
1968
|
-
columnDefs: preset.columnDefs.map((it) => {
|
|
1969
|
-
return { ...it.toJSON(), header: it.header.toString() };
|
|
1970
|
-
}),
|
|
1971
|
-
columnPinningState: {
|
|
1972
|
-
left: [...(preset.columnPinningState.left?.entries() ?? [])],
|
|
1973
|
-
right: [...(preset.columnPinningState.right?.entries() ?? [])],
|
|
1974
|
-
},
|
|
1975
|
-
};
|
|
1976
|
-
});
|
|
1977
|
-
const stringified = JSON.stringify(jsonFriendly);
|
|
1978
|
-
localStorage.setItem(`${this.userId}-${this.tableName}-presets`, stringified);
|
|
1979
|
-
this.setSelectedPreset(newPreset);
|
|
1765
|
+
this._preferences.saveColumnPreset(name);
|
|
1980
1766
|
};
|
|
1981
1767
|
/**
|
|
1982
1768
|
* This listener should be added and removed based on isMousingDown
|
|
1983
1769
|
*/
|
|
1770
|
+
/** Delegating accessor preserved for backwards compatibility. The
|
|
1771
|
+
* implementation lives on `_focus.setFocusEnd` (Phase 6.6). */
|
|
1984
1772
|
setFocusEnd = (coords) => {
|
|
1985
|
-
|
|
1986
|
-
return;
|
|
1987
|
-
}
|
|
1988
|
-
this.focusEnd = coords;
|
|
1773
|
+
this._focus.setFocusEnd(coords);
|
|
1989
1774
|
};
|
|
1990
1775
|
// #region private methods
|
|
1991
1776
|
createRow(item, index, unsortedIndex) {
|
|
@@ -2041,18 +1826,36 @@ export class TableContext {
|
|
|
2041
1826
|
},
|
|
2042
1827
|
};
|
|
2043
1828
|
};
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
1829
|
+
// Visibility filter applied to every cell collection so the cell
|
|
1830
|
+
// count in TableRow stays in sync with the visible-column count
|
|
1831
|
+
// that drives `--cols` in Table.svelte. Without this, a hidden
|
|
1832
|
+
// non-pinned column would still produce an empty cell wrapper in
|
|
1833
|
+
// the row, which would overflow the grid template and force the
|
|
1834
|
+
// extra cell onto an implicit grid row (visually splitting each
|
|
1835
|
+
// data row into two or three lines).
|
|
1836
|
+
//
|
|
1837
|
+
// Iterating `this.columnDefs.filter(...)` instead of
|
|
1838
|
+
// `this.columnPinning.left?.keys()` puts pinned-left body cells
|
|
1839
|
+
// in declaration order (matching the header rendering and the
|
|
1840
|
+
// `getVisualColumns` tab-order). Iterating the pinning Map's
|
|
1841
|
+
// keys produced *insertion* order: pinning Name then ID gave a
|
|
1842
|
+
// body row of [Name, ID] while the header row above it was
|
|
1843
|
+
// [ID, Name], and tab navigation walked [Name, ID] instead of
|
|
1844
|
+
// the visually-left-to-right [ID, Name].
|
|
1845
|
+
const leftVisibleCells = $derived(this.columnDefs
|
|
1846
|
+
.filter((it) => {
|
|
1847
|
+
return (this.columnVisibility[it.id] !== false && this.columnPinning.left?.has(it.id) === true);
|
|
1848
|
+
})
|
|
1849
|
+
.map(makeRow));
|
|
1850
|
+
const rightVisibleCells = $derived(this.columnDefs
|
|
1851
|
+
.filter((it) => {
|
|
1852
|
+
return (this.columnVisibility[it.id] !== false && this.columnPinning.right?.has(it.id) === true);
|
|
1853
|
+
})
|
|
1854
|
+
.map(makeRow));
|
|
2053
1855
|
const centerVisibleCells = $derived(this.columnDefs
|
|
2054
1856
|
.filter((it) => {
|
|
2055
|
-
return
|
|
1857
|
+
return (this.columnVisibility[it.id] !== false &&
|
|
1858
|
+
!(this.columnPinning.left?.has(it.id) || this.columnPinning.right?.has(it.id)));
|
|
2056
1859
|
})
|
|
2057
1860
|
.map(makeRow));
|
|
2058
1861
|
return row;
|
|
@@ -2062,87 +1865,57 @@ export class TableContext {
|
|
|
2062
1865
|
this.columnVisibility[it.id] !== false &&
|
|
2063
1866
|
!uncopyableColumns.has(it.columnType));
|
|
2064
1867
|
};
|
|
1868
|
+
/**
|
|
1869
|
+
* Builds the user-controlled settings blob from the current
|
|
1870
|
+
* `$state` slots and delegates the actual `localStorage.setItem`
|
|
1871
|
+
* call to `_preferences.persistSettings` (Phase 6.4). The settings
|
|
1872
|
+
* field set (`isCompact`, `singleClickEditing`, etc.) still lives
|
|
1873
|
+
* on `TableContext` because each one drives reactive UI; only the
|
|
1874
|
+
* persistence side of the boundary moved.
|
|
1875
|
+
*/
|
|
2065
1876
|
_updateLocalStorageSettings() {
|
|
2066
|
-
const isCompact = this.isCompact;
|
|
2067
|
-
const singleClickEditing = this.singleClickEditing;
|
|
2068
|
-
const alternateRowColours = this.alternateRowColours;
|
|
2069
|
-
const copyWithHeaders = this.copyWithHeaders;
|
|
2070
|
-
const commaSeparatedCopy = this.commaSeparatedCopy;
|
|
2071
|
-
const changeColourOnHover = this.changeColourOnHover;
|
|
2072
1877
|
const settingsObject = {
|
|
2073
|
-
isCompact,
|
|
2074
|
-
singleClickEditing,
|
|
2075
|
-
alternateRowColours,
|
|
2076
|
-
changeColourOnHover,
|
|
2077
|
-
copyWithHeaders,
|
|
2078
|
-
commaSeparatedCopy,
|
|
1878
|
+
isCompact: this.isCompact,
|
|
1879
|
+
singleClickEditing: this.singleClickEditing,
|
|
1880
|
+
alternateRowColours: this.alternateRowColours,
|
|
1881
|
+
changeColourOnHover: this.changeColourOnHover,
|
|
1882
|
+
copyWithHeaders: this.copyWithHeaders,
|
|
1883
|
+
commaSeparatedCopy: this.commaSeparatedCopy,
|
|
2079
1884
|
};
|
|
2080
|
-
|
|
1885
|
+
this._preferences.persistSettings(settingsObject);
|
|
2081
1886
|
}
|
|
2082
1887
|
/**
|
|
2083
|
-
*
|
|
2084
|
-
*
|
|
1888
|
+
* Delegating accessor preserved for backwards compatibility. The
|
|
1889
|
+
* cached visual-column array and its paired O(1) id->index map now
|
|
1890
|
+
* live on `_columnLayout` (Phase 6.3). The underscore prefix is
|
|
1891
|
+
* preserved on `TableContext` to keep the existing read sites in
|
|
1892
|
+
* `tabForward` / `focusToStart` / `moveFocusLeft` / etc. untouched.
|
|
2085
1893
|
*/
|
|
2086
1894
|
get _visualColumns() {
|
|
2087
|
-
|
|
2088
|
-
const pinLeft = this.columnPinning.left;
|
|
2089
|
-
const pinRight = this.columnPinning.right;
|
|
2090
|
-
const visible = this.columnDefs.filter((it) => visibility[it.id] !== false);
|
|
2091
|
-
return [
|
|
2092
|
-
...visible.filter((it) => pinLeft?.has(it.id)),
|
|
2093
|
-
...visible.filter((it) => !pinLeft?.has(it.id) && !pinRight?.has(it.id)),
|
|
2094
|
-
...visible.filter((it) => pinRight?.has(it.id)),
|
|
2095
|
-
];
|
|
1895
|
+
return this._columnLayout.visualColumns;
|
|
2096
1896
|
}
|
|
2097
|
-
/** Returns the visual index of the column with the given id, or
|
|
1897
|
+
/** Returns the visual index of the column with the given id, or
|
|
1898
|
+
* -1 if not found. Delegates to `_columnLayout.columnVisualIndex`
|
|
1899
|
+
* which provides the O(1) lookup. */
|
|
2098
1900
|
columnVisualIndex(id) {
|
|
2099
|
-
return this.
|
|
1901
|
+
return this._columnLayout.columnVisualIndex(id);
|
|
2100
1902
|
}
|
|
1903
|
+
/**
|
|
1904
|
+
* Delegating getter preserved for backwards compatibility. The
|
|
1905
|
+
* implementation lives on `_focus.focusStartVisualColumn`
|
|
1906
|
+
* (Phase 6.6); the visual-index lookup itself is owned by
|
|
1907
|
+
* `_columnLayout.columnVisualIndex` (Phase 6.3).
|
|
1908
|
+
*/
|
|
2101
1909
|
get focusStartVisualColumn() {
|
|
2102
|
-
|
|
2103
|
-
return -1;
|
|
2104
|
-
}
|
|
2105
|
-
return this.columnVisualIndex(this.focusStart.id);
|
|
1910
|
+
return this._focus.focusStartVisualColumn;
|
|
2106
1911
|
}
|
|
1912
|
+
/**
|
|
1913
|
+
* Delegating getter preserved for backwards compatibility. The
|
|
1914
|
+
* implementation lives on `_focus.focusEndVisualColumn`
|
|
1915
|
+
* (Phase 6.6).
|
|
1916
|
+
*/
|
|
2107
1917
|
get focusEndVisualColumn() {
|
|
2108
|
-
|
|
2109
|
-
return -1;
|
|
2110
|
-
}
|
|
2111
|
-
return this.columnVisualIndex(this.focusEnd.id);
|
|
2112
|
-
}
|
|
2113
|
-
_moveFocusEndRow(offset) {
|
|
2114
|
-
if (!this.allowCopy) {
|
|
2115
|
-
return;
|
|
2116
|
-
}
|
|
2117
|
-
if (!this.focusEnd) {
|
|
2118
|
-
console.warn('no focusEnd found');
|
|
2119
|
-
return;
|
|
2120
|
-
}
|
|
2121
|
-
// if (!$effect.tracking()) {
|
|
2122
|
-
// throw new Error(`_moveFocusEndRow is not in a tracking context.`);
|
|
2123
|
-
// }
|
|
2124
|
-
const focusEnd = this.focusEnd;
|
|
2125
|
-
const prm = this.paginationRowModel;
|
|
2126
|
-
const rows = prm.rows;
|
|
2127
|
-
const endRowIndex = rows.findIndex((row) => row.visibleIndex === focusEnd.row);
|
|
2128
|
-
this.focusEnd = {
|
|
2129
|
-
...this.focusEnd,
|
|
2130
|
-
row: rows[Math.max(Math.min(endRowIndex + offset, rows.length - 1), 0)].visibleIndex,
|
|
2131
|
-
};
|
|
2132
|
-
}
|
|
2133
|
-
_moveFocusRow(offset) {
|
|
2134
|
-
if (!this.focusStart) {
|
|
2135
|
-
console.warn('no focusStart found');
|
|
2136
|
-
return;
|
|
2137
|
-
}
|
|
2138
|
-
const focusStart = this.focusStart;
|
|
2139
|
-
const newEndRowIndex = (() => {
|
|
2140
|
-
const prm = this.paginationRowModel;
|
|
2141
|
-
const rows = prm.rows;
|
|
2142
|
-
const endRowIndex = rows.findIndex((row) => row.visibleIndex === focusStart.row);
|
|
2143
|
-
return rows[Math.max(Math.min(endRowIndex + offset, rows.length - 1), 0)].visibleIndex;
|
|
2144
|
-
})();
|
|
2145
|
-
this.moveFocus({ ...this.focusStart, row: newEndRowIndex });
|
|
1918
|
+
return this._focus.focusEndVisualColumn;
|
|
2146
1919
|
}
|
|
2147
1920
|
async getHighlightedRowData() {
|
|
2148
1921
|
const affectedColumns = this.columnDefs.filter(this.columnDefReturnsTextValue);
|
|
@@ -2289,28 +2062,7 @@ export class TableContext {
|
|
|
2289
2062
|
};
|
|
2290
2063
|
}
|
|
2291
2064
|
updateDefsBasedOnPinning = () => {
|
|
2292
|
-
|
|
2293
|
-
const midDefs = [];
|
|
2294
|
-
const rightDefs = [];
|
|
2295
|
-
this.columnDefs.forEach((def) => {
|
|
2296
|
-
if (this.columnPinning.left?.has(def.id)) {
|
|
2297
|
-
leftDefs.push(def);
|
|
2298
|
-
}
|
|
2299
|
-
else if (this.columnPinning.right?.has(def.id)) {
|
|
2300
|
-
rightDefs.push(def);
|
|
2301
|
-
}
|
|
2302
|
-
else {
|
|
2303
|
-
midDefs.push(def);
|
|
2304
|
-
}
|
|
2305
|
-
});
|
|
2306
|
-
leftDefs.sort((a, b) => a.index - b.index);
|
|
2307
|
-
midDefs.sort((a, b) => a.index - b.index);
|
|
2308
|
-
rightDefs.sort((a, b) => a.index - b.index);
|
|
2309
|
-
const allDefs = leftDefs.concat(midDefs, rightDefs);
|
|
2310
|
-
allDefs.forEach((def, index) => {
|
|
2311
|
-
def.index = index;
|
|
2312
|
-
});
|
|
2313
|
-
return allDefs;
|
|
2065
|
+
return this._columnLayout.updateDefsBasedOnPinning();
|
|
2314
2066
|
};
|
|
2315
2067
|
assertNoDuplicateIds() {
|
|
2316
2068
|
// eslint-disable-next-line svelte/prefer-svelte-reactivity
|
|
@@ -2322,10 +2074,8 @@ export class TableContext {
|
|
|
2322
2074
|
foundIds.add(def.id);
|
|
2323
2075
|
});
|
|
2324
2076
|
}
|
|
2325
|
-
// FIXME
|
|
2326
2077
|
// eslint-disable-next-line @typescript-eslint/require-await
|
|
2327
2078
|
async setupDefaultColumnDefs() {
|
|
2328
|
-
// const helper = createColumnHelper<T>();
|
|
2329
2079
|
this.assertNoDuplicateIds();
|
|
2330
2080
|
const adjustedDefsPromises = this.defaultColumnDefs.defs.map((def) => {
|
|
2331
2081
|
if (def instanceof AccessorDef) {
|
|
@@ -2460,47 +2210,44 @@ export class TableContext {
|
|
|
2460
2210
|
this.columnDefs = adjustedDefs;
|
|
2461
2211
|
return adjustedDefs;
|
|
2462
2212
|
}
|
|
2213
|
+
/**
|
|
2214
|
+
* Reads the persisted per-table user-settings blob through
|
|
2215
|
+
* `_preferences.loadSavedSettings` (Phase 6.4) and applies each
|
|
2216
|
+
* field to the live `$state` slot. Field defaults mirror the
|
|
2217
|
+
* pre-extraction behaviour:
|
|
2218
|
+
*
|
|
2219
|
+
* - missing slot: `singleClickEditing` defaults to `true`; every
|
|
2220
|
+
* other field keeps its constructor default.
|
|
2221
|
+
* - present slot: each field is applied if it would deviate from
|
|
2222
|
+
* the constructor default (the "only alter when the user
|
|
2223
|
+
* explicitly disabled" semantics are preserved verbatim).
|
|
2224
|
+
*/
|
|
2463
2225
|
_getUserDefaults() {
|
|
2464
|
-
const
|
|
2465
|
-
if (
|
|
2466
|
-
const saved = JSON.parse(savedSettings);
|
|
2467
|
-
this.singleClickEditing = saved.singleClickEditing ?? true;
|
|
2468
|
-
if (saved.alternateRowColours) {
|
|
2469
|
-
this.alternateRowColours = true;
|
|
2470
|
-
}
|
|
2471
|
-
if (saved.commaSeparatedCopy) {
|
|
2472
|
-
this.commaSeparatedCopy = true;
|
|
2473
|
-
}
|
|
2474
|
-
// these are true by default so we only want to alter them if the user wants them disabled
|
|
2475
|
-
if (saved.isCompact === false) {
|
|
2476
|
-
this.isCompact = false;
|
|
2477
|
-
}
|
|
2478
|
-
if (saved.copyWithHeaders === false) {
|
|
2479
|
-
this.copyWithHeaders = false;
|
|
2480
|
-
}
|
|
2481
|
-
if (saved.changeColourOnHover === false) {
|
|
2482
|
-
this.changeColourOnHover = false;
|
|
2483
|
-
}
|
|
2484
|
-
}
|
|
2485
|
-
else {
|
|
2226
|
+
const saved = this._preferences.loadSavedSettings();
|
|
2227
|
+
if (saved === null) {
|
|
2486
2228
|
this.singleClickEditing = true;
|
|
2229
|
+
return;
|
|
2230
|
+
}
|
|
2231
|
+
this.singleClickEditing = saved.singleClickEditing ?? true;
|
|
2232
|
+
if (saved.alternateRowColours) {
|
|
2233
|
+
this.alternateRowColours = true;
|
|
2234
|
+
}
|
|
2235
|
+
if (saved.commaSeparatedCopy) {
|
|
2236
|
+
this.commaSeparatedCopy = true;
|
|
2237
|
+
}
|
|
2238
|
+
// these are true by default so we only want to alter them if the user wants them disabled
|
|
2239
|
+
if (saved.isCompact === false) {
|
|
2240
|
+
this.isCompact = false;
|
|
2241
|
+
}
|
|
2242
|
+
if (saved.copyWithHeaders === false) {
|
|
2243
|
+
this.copyWithHeaders = false;
|
|
2244
|
+
}
|
|
2245
|
+
if (saved.changeColourOnHover === false) {
|
|
2246
|
+
this.changeColourOnHover = false;
|
|
2487
2247
|
}
|
|
2488
2248
|
}
|
|
2489
2249
|
_setNewPinningState() {
|
|
2490
|
-
this.
|
|
2491
|
-
// eslint-disable-next-line svelte/prefer-svelte-reactivity
|
|
2492
|
-
left: new Map(this.columnPinning.left &&
|
|
2493
|
-
this.columnDefs
|
|
2494
|
-
.filter((col) => {
|
|
2495
|
-
return this.columnPinning.left?.has(col.id);
|
|
2496
|
-
})
|
|
2497
|
-
.map((col, index) => [col.id, index])),
|
|
2498
|
-
// eslint-disable-next-line svelte/prefer-svelte-reactivity
|
|
2499
|
-
right: new Map(this.columnPinning.right &&
|
|
2500
|
-
this.columnDefs
|
|
2501
|
-
.filter((col) => this.columnPinning.right?.has(col.id))
|
|
2502
|
-
.map((col, index) => [col.id, index])),
|
|
2503
|
-
}; // TODO
|
|
2250
|
+
this._columnLayout.setNewPinningState();
|
|
2504
2251
|
}
|
|
2505
2252
|
getToggleSortingHandler = (def) => () => {
|
|
2506
2253
|
this.paginationRepo?.updateSorting?.((state) => {
|
|
@@ -2524,7 +2271,6 @@ export class TableContext {
|
|
|
2524
2271
|
return newState;
|
|
2525
2272
|
});
|
|
2526
2273
|
};
|
|
2527
|
-
// FIXME
|
|
2528
2274
|
// eslint-disable-next-line @typescript-eslint/require-await
|
|
2529
2275
|
async reassignDefsToPresets(presets) {
|
|
2530
2276
|
const adjustedDefs = this.columnDefs;
|
|
@@ -2591,9 +2337,51 @@ export function isSearchable(def) {
|
|
|
2591
2337
|
function hasPagination(repository) {
|
|
2592
2338
|
return 'setPage' in repository;
|
|
2593
2339
|
}
|
|
2340
|
+
/**
|
|
2341
|
+
* Neutralises CSV / TSV formula-injection prefixes recognised by Excel,
|
|
2342
|
+
* LibreOffice Calc, Google Sheets, and Apple Numbers.
|
|
2343
|
+
*
|
|
2344
|
+
* When a clipboard payload reaches a spreadsheet, any cell whose first
|
|
2345
|
+
* character is one of `=`, `+`, `-`, `@`, `\t`, `\r` is treated as a
|
|
2346
|
+
* formula and evaluated in the user's context. Untrusted row data
|
|
2347
|
+
* containing `=cmd|'/c calc'!A1` (or DDE / web-query equivalents) is the
|
|
2348
|
+
* canonical attack vector. Prefixing such a value with a single quote
|
|
2349
|
+
* (`'`) makes the spreadsheet interpret the cell as a literal string
|
|
2350
|
+
* instead.
|
|
2351
|
+
*
|
|
2352
|
+
* Trade-off: the leading apostrophe is invisible in the rendered cell of
|
|
2353
|
+
* every major spreadsheet, but the underlying cell value differs from the
|
|
2354
|
+
* source when read back by another formula referencing the cell. This is
|
|
2355
|
+
* the accepted industry mitigation (OWASP CSV Injection cheat sheet).
|
|
2356
|
+
*
|
|
2357
|
+
* Private helper - keep this colocated with `encapsulate` so every
|
|
2358
|
+
* clipboard-bound string flows through both functions before being
|
|
2359
|
+
* written to the OS clipboard.
|
|
2360
|
+
*/
|
|
2361
|
+
function escapeForSpreadsheet(value) {
|
|
2362
|
+
if (value.length === 0) {
|
|
2363
|
+
return value;
|
|
2364
|
+
}
|
|
2365
|
+
const first = value.charCodeAt(0);
|
|
2366
|
+
// '=' 61, '+' 43, '-' 45, '@' 64, '\t' 9, '\r' 13
|
|
2367
|
+
if (first === 61 || first === 43 || first === 45 || first === 64 || first === 9 || first === 13) {
|
|
2368
|
+
return `'${value}`;
|
|
2369
|
+
}
|
|
2370
|
+
return value;
|
|
2371
|
+
}
|
|
2594
2372
|
function encapsulate(value) {
|
|
2595
|
-
|
|
2373
|
+
const safe = escapeForSpreadsheet(value);
|
|
2374
|
+
return `"${safe.replace(/[\n]/gm, ' ').replace(/["]/g, '""')}"`;
|
|
2596
2375
|
}
|
|
2376
|
+
/**
|
|
2377
|
+
* Internal exports for tests. Not part of the public API; do not import
|
|
2378
|
+
* from consumer code. Allows the clipboard formula-escape regression test
|
|
2379
|
+
* to call the module-private helpers directly.
|
|
2380
|
+
*/
|
|
2381
|
+
export const _internal = {
|
|
2382
|
+
escapeForSpreadsheet,
|
|
2383
|
+
encapsulate,
|
|
2384
|
+
};
|
|
2597
2385
|
function generateTableOptions(contextObj) {
|
|
2598
2386
|
const _pagination = $derived.by(() => {
|
|
2599
2387
|
void contextObj.paginationRepo?.paginationState.pageSize;
|
|
@@ -2616,6 +2404,22 @@ function generateTableOptions(contextObj) {
|
|
|
2616
2404
|
let originalWidth = 0;
|
|
2617
2405
|
let mouseStartingPoint = 0;
|
|
2618
2406
|
function addOverrideResizeHandler(e) {
|
|
2407
|
+
// Capture the column's currently rendered width as the
|
|
2408
|
+
// drag's starting point, then mark this column as
|
|
2409
|
+
// user-resized. Going forward the grid template will use a
|
|
2410
|
+
// fixed `${width}px` track for this column (see
|
|
2411
|
+
// `Table.svelte` colsTemplate) so dragging the handle only
|
|
2412
|
+
// changes this column. Other columns that have not yet
|
|
2413
|
+
// been user-resized continue to flex via `minmax(W, 1fr)`,
|
|
2414
|
+
// which means they automatically take up any horizontal
|
|
2415
|
+
// space the resized column gives back when shrunk - the
|
|
2416
|
+
// table never ends up narrower than its container while
|
|
2417
|
+
// any column still flexes.
|
|
2418
|
+
const rendered = contextObj._columnRenderedWidths.get(def.id);
|
|
2419
|
+
if (rendered != null && rendered > 0) {
|
|
2420
|
+
def.width = rendered;
|
|
2421
|
+
}
|
|
2422
|
+
def.userResized = true;
|
|
2619
2423
|
originalWidth = def.width;
|
|
2620
2424
|
mouseStartingPoint = e.clientX;
|
|
2621
2425
|
def.isResizing = true;
|
|
@@ -2623,7 +2427,14 @@ function generateTableOptions(contextObj) {
|
|
|
2623
2427
|
window.addEventListener('mouseup', removeOverrideResizeHandler);
|
|
2624
2428
|
}
|
|
2625
2429
|
function onResize(e) {
|
|
2626
|
-
|
|
2430
|
+
// Clamp the resize floor so the column can never reach a
|
|
2431
|
+
// negative or zero width. With the div+grid layout a
|
|
2432
|
+
// non-positive `width` produces an invalid track size
|
|
2433
|
+
// in `grid-template-columns`, which makes the browser
|
|
2434
|
+
// fall back to single-column block layout and visually
|
|
2435
|
+
// collapses the row.
|
|
2436
|
+
const next = originalWidth - (mouseStartingPoint - e.clientX);
|
|
2437
|
+
def.width = Math.max(next, 20);
|
|
2627
2438
|
}
|
|
2628
2439
|
function removeOverrideResizeHandler() {
|
|
2629
2440
|
def.isResizing = false;
|
|
@@ -2753,111 +2564,6 @@ function generateTableOptions(contextObj) {
|
|
|
2753
2564
|
// }
|
|
2754
2565
|
};
|
|
2755
2566
|
}
|
|
2756
|
-
function checkboxSortingFn(id, desc) {
|
|
2757
|
-
return desc
|
|
2758
|
-
? (a, b) => {
|
|
2759
|
-
if (a[id] && !b[id]) {
|
|
2760
|
-
return 1;
|
|
2761
|
-
}
|
|
2762
|
-
if (!a[id] && b[id]) {
|
|
2763
|
-
return -1;
|
|
2764
|
-
}
|
|
2765
|
-
return 0;
|
|
2766
|
-
}
|
|
2767
|
-
: (a, b) => {
|
|
2768
|
-
if (a[id] && !b[id]) {
|
|
2769
|
-
return -1;
|
|
2770
|
-
}
|
|
2771
|
-
if (!a[id] && b[id]) {
|
|
2772
|
-
return 1;
|
|
2773
|
-
}
|
|
2774
|
-
return 0;
|
|
2775
|
-
};
|
|
2776
|
-
}
|
|
2777
|
-
function comparableSortingFn(id, desc) {
|
|
2778
|
-
return desc
|
|
2779
|
-
? (a, b) => {
|
|
2780
|
-
if (a[id] == undefined && b[id] != undefined) {
|
|
2781
|
-
return 1;
|
|
2782
|
-
}
|
|
2783
|
-
if (b[id] == undefined && a[id] != undefined) {
|
|
2784
|
-
return -1;
|
|
2785
|
-
}
|
|
2786
|
-
if (a[id] < b[id]) {
|
|
2787
|
-
return 1;
|
|
2788
|
-
}
|
|
2789
|
-
if (a[id] > b[id]) {
|
|
2790
|
-
return -1;
|
|
2791
|
-
}
|
|
2792
|
-
return 0;
|
|
2793
|
-
}
|
|
2794
|
-
: (a, b) => {
|
|
2795
|
-
if (a[id] == undefined && b[id] != undefined) {
|
|
2796
|
-
return 1;
|
|
2797
|
-
}
|
|
2798
|
-
if (b[id] == undefined && a[id] != undefined) {
|
|
2799
|
-
return -1;
|
|
2800
|
-
}
|
|
2801
|
-
if (a[id] < b[id]) {
|
|
2802
|
-
return -1;
|
|
2803
|
-
}
|
|
2804
|
-
if (a[id] > b[id]) {
|
|
2805
|
-
return 1;
|
|
2806
|
-
}
|
|
2807
|
-
return 0;
|
|
2808
|
-
};
|
|
2809
|
-
}
|
|
2810
|
-
function progressSortingFn(id, desc) {
|
|
2811
|
-
return desc
|
|
2812
|
-
? (a, b) => {
|
|
2813
|
-
const [minA, maxA] = a[id];
|
|
2814
|
-
const [minB, maxB] = b[id];
|
|
2815
|
-
if (minA == undefined || maxA == undefined || maxA == 0) {
|
|
2816
|
-
if (maxB != undefined && maxB != 0) {
|
|
2817
|
-
return 1;
|
|
2818
|
-
}
|
|
2819
|
-
else {
|
|
2820
|
-
return 0;
|
|
2821
|
-
}
|
|
2822
|
-
}
|
|
2823
|
-
if (minB == undefined || maxB == undefined || maxB == 0) {
|
|
2824
|
-
return -1;
|
|
2825
|
-
}
|
|
2826
|
-
const valueA = minA / maxA;
|
|
2827
|
-
const valueB = minB / maxB;
|
|
2828
|
-
if (valueA < valueB) {
|
|
2829
|
-
return 1;
|
|
2830
|
-
}
|
|
2831
|
-
if (valueB < valueA) {
|
|
2832
|
-
return -1;
|
|
2833
|
-
}
|
|
2834
|
-
return 0;
|
|
2835
|
-
}
|
|
2836
|
-
: (a, b) => {
|
|
2837
|
-
const [minA, maxA] = a[id];
|
|
2838
|
-
const [minB, maxB] = b[id];
|
|
2839
|
-
if (minA == undefined || maxA == undefined || maxA == 0) {
|
|
2840
|
-
if (maxB != undefined && maxB != 0) {
|
|
2841
|
-
return -1;
|
|
2842
|
-
}
|
|
2843
|
-
else {
|
|
2844
|
-
return 0;
|
|
2845
|
-
}
|
|
2846
|
-
}
|
|
2847
|
-
if (minB == undefined || maxB == undefined || maxB == 0) {
|
|
2848
|
-
return 1;
|
|
2849
|
-
}
|
|
2850
|
-
const valueA = minA / maxA;
|
|
2851
|
-
const valueB = minB / maxB;
|
|
2852
|
-
if (valueA < valueB) {
|
|
2853
|
-
return -1;
|
|
2854
|
-
}
|
|
2855
|
-
if (valueB < valueA) {
|
|
2856
|
-
return 1;
|
|
2857
|
-
}
|
|
2858
|
-
return 0;
|
|
2859
|
-
};
|
|
2860
|
-
}
|
|
2861
2567
|
function adaptJSONPinningState(state) {
|
|
2862
2568
|
//HACK ignore previously broken pinning states
|
|
2863
2569
|
return {
|