@rotki/ui-library 2.21.0 → 2.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/accordions/accordion/RuiAccordion.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/components/accordions/accordion/RuiAccordion.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/accordions/accordions/RuiAccordions.vue_vue_type_script_setup_true_lang.js +2 -2
- package/dist/components/accordions/accordions/RuiAccordions.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/alerts/RuiAlert.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/components/alerts/RuiAlert.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/avatars/RuiAvatar.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/components/avatars/RuiAvatar.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/avatars/RuiAvatarGroup.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/components/avatars/RuiAvatarGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/avatars/avatar-props.js +1 -1
- package/dist/components/avatars/avatar-props.js.map +1 -1
- package/dist/components/avatars/use-avatar-group.js.map +1 -1
- package/dist/components/buttons/button/RuiButton.js.map +1 -1
- package/dist/components/buttons/button/RuiButton.vue.d.ts +2 -2
- package/dist/components/buttons/button/RuiButton.vue_vue_type_script_setup_true_lang.js +3 -3
- package/dist/components/buttons/button/RuiButton.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/buttons/button/button-props.js.map +1 -1
- package/dist/components/buttons/button/button-styles.js.map +1 -1
- package/dist/components/buttons/button-group/RuiButtonGroup.vue_vue_type_script_setup_true_lang.js +2 -2
- package/dist/components/buttons/button-group/RuiButtonGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/calendar/RuiCalendar.vue_vue_type_script_setup_true_lang.js +3 -3
- package/dist/components/calendar/RuiCalendar.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/calendar/RuiCalendarGrid.vue_vue_type_script_setup_true_lang.js +2 -2
- package/dist/components/calendar/RuiCalendarGrid.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/calendar/RuiCalendarHeader.vue_vue_type_script_setup_true_lang.js +3 -3
- package/dist/components/calendar/RuiCalendarHeader.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/calendar/RuiCalendarMenu.vue_vue_type_script_setup_true_lang.js +3 -3
- package/dist/components/calendar/RuiCalendarMenu.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/calendar/state.js.map +1 -1
- package/dist/components/cards/RuiCard.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/components/cards/RuiCard.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/cards/RuiCardHeader.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/components/cards/RuiCardHeader.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/chips/RuiChip.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/components/chips/RuiChip.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/chips/chip-props.js.map +1 -1
- package/dist/components/color-picker/RuiColorBoard.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/components/color-picker/RuiColorBoard.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/color-picker/RuiColorDisplay.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/components/color-picker/RuiColorDisplay.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/color-picker/RuiColorHue.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/components/color-picker/RuiColorHue.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/color-picker/RuiColorInput.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/components/color-picker/RuiColorInput.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/color-picker/RuiColorPicker.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/components/color-picker/RuiColorPicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/color-picker/utils.js.map +1 -1
- package/dist/components/date-time-picker/RuiDateTimePicker.vue_vue_type_script_setup_true_lang.js +2 -2
- package/dist/components/date-time-picker/RuiDateTimePicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/date-time-picker/RuiDateTimePickerMenu.vue_vue_type_script_setup_true_lang.js +3 -3
- package/dist/components/date-time-picker/RuiDateTimePickerMenu.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/date-time-picker/RuiTimezoneSelect.vue_vue_type_script_setup_true_lang.js +2 -2
- package/dist/components/date-time-picker/RuiTimezoneSelect.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/date-time-picker/date-time-picker-styles.js.map +1 -1
- package/dist/components/date-time-picker/dayjs-setup.js.map +1 -1
- package/dist/components/date-time-picker/segment-config.js.map +1 -1
- package/dist/components/date-time-picker/segment-utils.js.map +1 -1
- package/dist/components/date-time-picker/timezones.js.map +1 -1
- package/dist/components/date-time-picker/types.js +1 -1
- package/dist/components/date-time-picker/types.js.map +1 -1
- package/dist/components/date-time-picker/use-date-time-selection.js +2 -2
- package/dist/components/date-time-picker/use-date-time-selection.js.map +1 -1
- package/dist/components/date-time-picker/use-input-handler.js.map +1 -1
- package/dist/components/date-time-picker/use-keyboard-handler.js.map +1 -1
- package/dist/components/date-time-picker/utils.js.map +1 -1
- package/dist/components/divider/RuiDivider.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/components/divider/RuiDivider.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/forms/auto-complete/RuiAutoComplete.js.map +1 -1
- package/dist/components/forms/auto-complete/RuiAutoComplete.vue.d.ts +14 -1
- package/dist/components/forms/auto-complete/RuiAutoComplete.vue_vue_type_script_setup_true_lang.js +15 -5
- package/dist/components/forms/auto-complete/RuiAutoComplete.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/forms/auto-complete/auto-complete-styles.js.map +1 -1
- package/dist/components/forms/category-picker/RuiCategoryPicker.js +7 -0
- package/dist/components/forms/category-picker/RuiCategoryPicker.js.map +1 -0
- package/dist/components/forms/category-picker/RuiCategoryPicker.vue.d.ts +134 -0
- package/dist/components/forms/category-picker/RuiCategoryPicker.vue_vue_type_script_setup_true_lang.js +561 -0
- package/dist/components/forms/category-picker/RuiCategoryPicker.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/forms/category-picker/category-picker-styles.d.ts +432 -0
- package/dist/components/forms/category-picker/category-picker-styles.js +59 -0
- package/dist/components/forms/category-picker/category-picker-styles.js.map +1 -0
- package/dist/components/forms/check-control-styles.js.map +1 -1
- package/dist/components/forms/checkbox/RuiCheckbox.vue_vue_type_script_setup_true_lang.js +2 -2
- package/dist/components/forms/checkbox/RuiCheckbox.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/forms/checkbox/checkbox-group/RuiCheckboxGroup.vue_vue_type_script_setup_true_lang.js +2 -2
- package/dist/components/forms/checkbox/checkbox-group/RuiCheckboxGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/forms/checkbox/checkbox-group/context.js.map +1 -1
- package/dist/components/forms/file-upload/RuiFileUpload.js.map +1 -1
- package/dist/components/forms/file-upload/RuiFileUpload.vue_vue_type_script_setup_true_lang.js +5 -5
- package/dist/components/forms/file-upload/RuiFileUpload.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/forms/radio-button/radio/RuiRadio.vue_vue_type_script_setup_true_lang.js +2 -2
- package/dist/components/forms/radio-button/radio/RuiRadio.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/forms/radio-button/radio-group/RuiRadioGroup.vue_vue_type_script_setup_true_lang.js +2 -2
- package/dist/components/forms/radio-button/radio-group/RuiRadioGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/forms/revealable-text-field/RuiRevealableTextField.vue_vue_type_script_setup_true_lang.js +2 -2
- package/dist/components/forms/revealable-text-field/RuiRevealableTextField.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/forms/select/RuiMenuSelect.vue_vue_type_script_setup_true_lang.js +2 -2
- package/dist/components/forms/select/RuiMenuSelect.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/forms/select/RuiSimpleSelect.vue_vue_type_script_setup_true_lang.js +2 -2
- package/dist/components/forms/select/RuiSimpleSelect.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/forms/select/menu-select-styles.js.map +1 -1
- package/dist/components/forms/slider/RuiSlider.vue_vue_type_script_setup_true_lang.js +2 -2
- package/dist/components/forms/slider/RuiSlider.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/forms/slider/slider-styles.js.map +1 -1
- package/dist/components/forms/switch/RuiSwitch.vue_vue_type_script_setup_true_lang.js +2 -2
- package/dist/components/forms/switch/RuiSwitch.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/forms/text-area/RuiTextArea.vue_vue_type_script_setup_true_lang.js +3 -3
- package/dist/components/forms/text-area/RuiTextArea.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/forms/text-area/text-area-styles.js.map +1 -1
- package/dist/components/forms/text-field/RuiTextField.vue_vue_type_script_setup_true_lang.js +3 -3
- package/dist/components/forms/text-field/RuiTextField.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/forms/text-field/text-field-styles.js.map +1 -1
- package/dist/components/forms/text-input-styles.js.map +1 -1
- package/dist/components/helpers/RuiFormTextDetail.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/components/helpers/RuiFormTextDetail.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/icons/RuiIcon.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/components/icons/RuiIcon.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/index.d.ts +3 -2
- package/dist/components/index.js +3 -2
- package/dist/components/loaders/RuiSkeletonBase.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/components/loaders/RuiSkeletonBase.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/loaders/RuiSkeletonLoader.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/components/loaders/RuiSkeletonLoader.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/loaders/skeleton-type.js.map +1 -1
- package/dist/components/logos/RuiLogo.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/components/logos/RuiLogo.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/logos/use-logo-sources.js.map +1 -1
- package/dist/components/overlays/badge/RuiBadge.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/components/overlays/badge/RuiBadge.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/overlays/badge/badge-props.js.map +1 -1
- package/dist/components/overlays/bottom-sheet/RuiBottomSheet.vue_vue_type_script_setup_true_lang.js +2 -2
- package/dist/components/overlays/bottom-sheet/RuiBottomSheet.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/overlays/dialog/RuiDialog.vue_vue_type_script_setup_true_lang.js +3 -3
- package/dist/components/overlays/dialog/RuiDialog.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/overlays/menu/RuiMenu.vue_vue_type_script_setup_true_lang.js +2 -2
- package/dist/components/overlays/menu/RuiMenu.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/overlays/navigation-drawer/RuiNavigationDrawer.vue_vue_type_script_setup_true_lang.js +3 -3
- package/dist/components/overlays/navigation-drawer/RuiNavigationDrawer.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/overlays/notification/RuiNotification.vue_vue_type_script_setup_true_lang.js +2 -2
- package/dist/components/overlays/notification/RuiNotification.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/overlays/tooltip/RuiTooltip.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/components/overlays/tooltip/RuiTooltip.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/overlays/tooltip/tooltip-styles.js.map +1 -1
- package/dist/components/progress/RuiProgress.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/components/progress/RuiProgress.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/progress/progress-props.js.map +1 -1
- package/dist/components/steppers/RuiFooterStepper.vue_vue_type_script_setup_true_lang.js +2 -2
- package/dist/components/steppers/RuiFooterStepper.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/steppers/RuiStepper.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/components/steppers/RuiStepper.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/steppers/RuiStepperCustomIcon.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/components/steppers/RuiStepperCustomIcon.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/steppers/RuiStepperIcon.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/components/steppers/RuiStepperIcon.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/steppers/footer-stepper-variant.js.map +1 -1
- package/dist/components/tables/RuiDataTable.js.map +1 -1
- package/dist/components/tables/RuiDataTable.vue.d.ts +23 -2
- package/dist/components/tables/RuiDataTable.vue_vue_type_script_setup_true_lang.js +186 -217
- package/dist/components/tables/RuiDataTable.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/tables/RuiExpandButton.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/components/tables/RuiExpandButton.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/tables/RuiTableEmptyState.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/components/tables/RuiTableEmptyState.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/tables/RuiTableHead.js.map +1 -1
- package/dist/components/tables/RuiTableHead.vue.d.ts +11 -1
- package/dist/components/tables/RuiTableHead.vue_vue_type_script_setup_true_lang.js +1 -2
- package/dist/components/tables/RuiTableHead.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/tables/RuiTablePagination.js.map +1 -1
- package/dist/components/tables/RuiTablePagination.vue.d.ts +5 -0
- package/dist/components/tables/RuiTablePagination.vue_vue_type_script_setup_true_lang.js +24 -8
- package/dist/components/tables/RuiTablePagination.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/tables/data-table/RuiDataTableBody.js +7 -0
- package/dist/components/tables/data-table/RuiDataTableBody.js.map +1 -0
- package/dist/components/tables/data-table/RuiDataTableBody.vue.d.ts +55 -0
- package/dist/components/tables/data-table/RuiDataTableBody.vue_vue_type_script_setup_true_lang.js +78 -0
- package/dist/components/tables/data-table/RuiDataTableBody.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/tables/data-table/RuiDataTableCell.js +7 -0
- package/dist/components/tables/data-table/RuiDataTableCell.js.map +1 -0
- package/dist/components/tables/data-table/RuiDataTableCell.vue.d.ts +30 -0
- package/dist/components/tables/data-table/RuiDataTableCell.vue_vue_type_script_setup_true_lang.js +54 -0
- package/dist/components/tables/data-table/RuiDataTableCell.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/tables/data-table/RuiDataTableEmptyRow.js +7 -0
- package/dist/components/tables/data-table/RuiDataTableEmptyRow.js.map +1 -0
- package/dist/components/tables/data-table/RuiDataTableEmptyRow.vue.d.ts +19 -0
- package/dist/components/tables/data-table/RuiDataTableEmptyRow.vue_vue_type_script_setup_true_lang.js +43 -0
- package/dist/components/tables/data-table/RuiDataTableEmptyRow.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/tables/data-table/RuiDataTableExpandedRow.js +7 -0
- package/dist/components/tables/data-table/RuiDataTableExpandedRow.js.map +1 -0
- package/dist/components/tables/data-table/RuiDataTableExpandedRow.vue.d.ts +26 -0
- package/dist/components/tables/data-table/RuiDataTableExpandedRow.vue_vue_type_script_setup_true_lang.js +31 -0
- package/dist/components/tables/data-table/RuiDataTableExpandedRow.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/tables/data-table/RuiDataTableGroupRow.js +7 -0
- package/dist/components/tables/data-table/RuiDataTableGroupRow.js.map +1 -0
- package/dist/components/tables/data-table/RuiDataTableGroupRow.vue.d.ts +32 -0
- package/dist/components/tables/data-table/RuiDataTableGroupRow.vue_vue_type_script_setup_true_lang.js +85 -0
- package/dist/components/tables/data-table/RuiDataTableGroupRow.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/tables/data-table/RuiDataTableLoadingRow.js +7 -0
- package/dist/components/tables/data-table/RuiDataTableLoadingRow.js.map +1 -0
- package/dist/components/tables/data-table/RuiDataTableLoadingRow.vue.d.ts +3 -0
- package/dist/components/tables/data-table/RuiDataTableLoadingRow.vue_vue_type_script_setup_true_lang.js +26 -0
- package/dist/components/tables/data-table/RuiDataTableLoadingRow.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/tables/data-table/RuiDataTableMobileSort.js +7 -0
- package/dist/components/tables/data-table/RuiDataTableMobileSort.js.map +1 -0
- package/dist/components/tables/data-table/RuiDataTableMobileSort.vue.d.ts +33 -0
- package/dist/components/tables/data-table/RuiDataTableMobileSort.vue_vue_type_script_setup_true_lang.js +101 -0
- package/dist/components/tables/data-table/RuiDataTableMobileSort.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/tables/data-table/RuiDataTableRow.js +7 -0
- package/dist/components/tables/data-table/RuiDataTableRow.js.map +1 -0
- package/dist/components/tables/data-table/RuiDataTableRow.vue.d.ts +31 -0
- package/dist/components/tables/data-table/RuiDataTableRow.vue_vue_type_script_setup_true_lang.js +142 -0
- package/dist/components/tables/data-table/RuiDataTableRow.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/tables/data-table/context.d.ts +73 -0
- package/dist/components/tables/data-table/context.js +100 -0
- package/dist/components/tables/data-table/context.js.map +1 -0
- package/dist/components/tables/data-table-styles.d.ts +30 -1
- package/dist/components/tables/data-table-styles.js +9 -2
- package/dist/components/tables/data-table-styles.js.map +1 -1
- package/dist/components/tables/table-props.d.ts +5 -0
- package/dist/components/tables/table-props.js +5 -1
- package/dist/components/tables/table-props.js.map +1 -1
- package/dist/components/tables/use-pagination-navigation.js.map +1 -1
- package/dist/components/tabs/tab/RuiTab.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/components/tabs/tab/RuiTab.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/tabs/tab/use-tab-link.js.map +1 -1
- package/dist/components/tabs/tab-item/RuiTabItem.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/components/tabs/tab-item/RuiTabItem.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/tabs/tab-items/RuiTabItems.js.map +1 -1
- package/dist/components/tabs/tab-items/RuiTabItems.vue_vue_type_script_setup_true_lang.js +2 -2
- package/dist/components/tabs/tab-items/RuiTabItems.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/tabs/tab-props.js.map +1 -1
- package/dist/components/tabs/tabs/RuiTabs.vue_vue_type_script_setup_true_lang.js +2 -2
- package/dist/components/tabs/tabs/RuiTabs.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/tabs/tabs/use-tab-routing.js +1 -1
- package/dist/components/tabs/tabs/use-tab-routing.js.map +1 -1
- package/dist/components/tabs/tabs/use-tab-scroll.js.map +1 -1
- package/dist/components/time-picker/RuiTimePicker.vue_vue_type_script_setup_true_lang.js +2 -2
- package/dist/components/time-picker/RuiTimePicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/time-picker/time-picker-styles.js.map +1 -1
- package/dist/composables/breakpoint.js.map +1 -1
- package/dist/composables/defaults/table.d.ts +12 -0
- package/dist/composables/defaults/table.js.map +1 -1
- package/dist/composables/dropdown-menu.js.map +1 -1
- package/dist/composables/floating.js +1 -1
- package/dist/composables/floating.js.map +1 -1
- package/dist/composables/forms/auto-complete/focus.js.map +1 -1
- package/dist/composables/forms/auto-complete/index.js +5 -4
- package/dist/composables/forms/auto-complete/keyboard-navigation.js.map +1 -1
- package/dist/composables/forms/auto-complete/search.d.ts +6 -1
- package/dist/composables/forms/auto-complete/search.js +12 -1
- package/dist/composables/forms/auto-complete/search.js.map +1 -1
- package/dist/composables/forms/auto-complete/value.js.map +1 -1
- package/dist/composables/forms/category-picker/use-category-picker.d.ts +76 -0
- package/dist/composables/forms/category-picker/use-category-picker.js +141 -0
- package/dist/composables/forms/category-picker/use-category-picker.js.map +1 -0
- package/dist/composables/forms/use-prepend-append-width.js.map +1 -1
- package/dist/composables/icons.js.map +1 -1
- package/dist/composables/popper.js.map +1 -1
- package/dist/composables/sticky-header.js.map +1 -1
- package/dist/composables/tables/data-table/columns.d.ts +7 -1
- package/dist/composables/tables/data-table/columns.js +18 -10
- package/dist/composables/tables/data-table/columns.js.map +1 -1
- package/dist/composables/tables/data-table/expansion.js.map +1 -1
- package/dist/composables/tables/data-table/grouping.d.ts +4 -6
- package/dist/composables/tables/data-table/grouping.js +38 -24
- package/dist/composables/tables/data-table/grouping.js.map +1 -1
- package/dist/composables/tables/data-table/pagination.d.ts +4 -4
- package/dist/composables/tables/data-table/pagination.js +63 -21
- package/dist/composables/tables/data-table/pagination.js.map +1 -1
- package/dist/composables/tables/data-table/selection.js +16 -6
- package/dist/composables/tables/data-table/selection.js.map +1 -1
- package/dist/composables/tables/data-table/sort.d.ts +4 -3
- package/dist/composables/tables/data-table/sort.js +78 -40
- package/dist/composables/tables/data-table/sort.js.map +1 -1
- package/dist/composables/tables/data-table/types.d.ts +3 -1
- package/dist/composables/tables/data-table/types.js +6 -2
- package/dist/composables/tables/data-table/types.js.map +1 -1
- package/dist/composables/theme.js.map +1 -1
- package/dist/composables/timeout-manager.js.map +1 -1
- package/dist/composables/use-rui-i18n.js.map +1 -1
- package/dist/consts/colors.js.map +1 -1
- package/dist/consts/time-accuracy.js.map +1 -1
- package/dist/i18n/keys.js.map +1 -1
- package/dist/icons/icons_1.d.ts +12 -12
- package/dist/icons/icons_1.js +140 -157
- package/dist/icons/icons_1.js.map +1 -1
- package/dist/icons/icons_2.d.ts +13 -13
- package/dist/icons/icons_2.js +128 -149
- package/dist/icons/icons_2.js.map +1 -1
- package/dist/icons/icons_3.d.ts +18 -18
- package/dist/icons/icons_3.js +244 -282
- package/dist/icons/icons_3.js.map +1 -1
- package/dist/icons/icons_4.d.ts +251 -6
- package/dist/icons/icons_4.js +3016 -75
- package/dist/icons/icons_4.js.map +1 -1
- package/dist/icons/icons_5.d.ts +20 -0
- package/dist/icons/icons_5.js +221 -0
- package/dist/icons/icons_5.js.map +1 -0
- package/dist/icons/index.d.ts +2 -1
- package/dist/icons/index.js +297 -32
- package/dist/icons/index.js.map +1 -1
- package/dist/index.js +8 -6
- package/dist/index.js.map +1 -1
- package/dist/library-icons.json +1 -0
- package/dist/style.css +152 -0
- package/dist/theme/index.js.map +1 -1
- package/dist/types/stepper.js.map +1 -1
- package/dist/types/theme.js.map +1 -1
- package/dist/utils/assert.js.map +1 -1
- package/dist/utils/blockie.js.map +1 -1
- package/dist/utils/form-text-detail.js.map +1 -1
- package/dist/utils/helpers.js.map +1 -1
- package/dist/utils/is-equal.js.map +1 -1
- package/dist/utils/tv.js.map +1 -1
- package/dist/vite-plugin/index.js +6 -5
- package/dist/vite-plugin/index.js.map +1 -1
- package/dist/vite-plugin/scanner.d.ts +1 -1
- package/dist/vite-plugin/scanner.js +10 -7
- package/dist/vite-plugin/scanner.js.map +1 -1
- package/dist/vite-plugin/types.d.ts +9 -0
- package/dist/web-types.json +2042 -1108
- package/package.json +35 -35
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"grouping.js","names":[],"sources":["../../../../src/composables/tables/data-table/grouping.ts"],"sourcesContent":["import type { ComputedRef, Ref } from 'vue';\nimport type {
|
|
1
|
+
{"version":3,"file":"grouping.js","names":[],"sources":["../../../../src/composables/tables/data-table/grouping.ts"],"sourcesContent":["import type { ComputedRef, Ref } from 'vue';\nimport type { TableRowKey, TableRowKeyData } from '@/components/tables/RuiTableHead.vue';\nimport {\n GROUP_HEADER_BRAND,\n type GroupedTableRow,\n type GroupHeader,\n isRow,\n} from '@/composables/tables/data-table/types';\nimport { assert } from '@/utils/assert';\n\nexport interface UseTableGroupingOptions<T extends object, IdType extends keyof T> {\n /** The property on each row used as the unique row identifier. */\n rowAttr: IdType;\n}\n\nexport interface UseTableGroupingDeps<T extends object> {\n group: Ref<TableRowKeyData<T>>;\n collapsed: Ref<T[] | undefined>;\n sorted: ComputedRef<readonly T[]>;\n}\n\nexport interface UseTableGroupingReturn<T extends object> {\n groupKeys: ComputedRef<TableRowKey<T>[]>;\n groupKey: ComputedRef<string | undefined>;\n isGrouped: ComputedRef<boolean>;\n mappedGroups: ComputedRef<Record<string, GroupedTableRow<T>[]>>;\n grouped: ComputedRef<readonly GroupedTableRow<T>[]>;\n getRowGroup: (row: T) => Partial<T>;\n getGroupRows: (groupVal: string) => T[];\n compareGroupsFn: (a: T, b: Partial<T>) => boolean;\n isExpandedGroup: (value: Partial<T>) => boolean;\n isHiddenRow: (row: GroupedTableRow<T>) => boolean;\n onToggleExpandGroup: (group: Partial<T>, value?: string) => void;\n onUngroup: () => void;\n}\n\n// Null character separator prevents false collisions when group values contain commas\nconst GROUP_KEY_SEPARATOR = '\\0';\n\nexport function useTableGrouping<T extends object, IdType extends keyof T>(\n options: UseTableGroupingOptions<T, IdType>,\n deps: UseTableGroupingDeps<T>,\n): UseTableGroupingReturn<T> {\n const { rowAttr } = options;\n const { group, collapsed, sorted } = deps;\n\n const collapsedRows: Ref<T[]> = ref([]);\n\n watch(collapsed, value => set(collapsedRows, value ?? []), { immediate: true });\n\n const groupKeys: ComputedRef<TableRowKey<T>[]> = computed(() => {\n const groupBy = get(group);\n\n if (!groupBy)\n return [];\n\n if (!Array.isArray(groupBy))\n return [groupBy];\n\n return groupBy;\n });\n\n const groupKey = computed<string | undefined>(() => {\n const key = get(groupKeys).join(':');\n return key || undefined;\n });\n\n const isGrouped = computed<boolean>(() => get(groupKey) !== undefined);\n\n const collapsedIdentifierSet = computed<Set<T[IdType]>>(\n () => new Set(get(collapsedRows).map(row => row[rowAttr])),\n );\n\n const collapsedGroupKeySet = computed<Set<string>>(() => {\n const grouping = get(groupKeys);\n if (grouping.length === 0)\n return new Set<string>();\n\n const seen = new Set<string>();\n for (const row of get(collapsedRows))\n seen.add(computeGroupKey(row, grouping));\n return seen;\n });\n\n function getRowGroup(row: T): Partial<T> {\n const result: Partial<T> = {};\n for (const key of get(groupKeys)) {\n result[key] = row[key];\n }\n return result;\n }\n\n function compareGroupsFn(a: T, b: Partial<T>): boolean {\n const grouping = get(groupKeys);\n if (grouping.length === 0)\n return false;\n\n return grouping.every(key => a[key] === b[key]);\n }\n\n function isExpandedGroup(value: Partial<T>): boolean {\n const grouping = get(groupKeys);\n let groupVal = '';\n for (const gk of grouping) {\n if (groupVal)\n groupVal += GROUP_KEY_SEPARATOR;\n const val = value[gk];\n groupVal += isDefined(val) ? val : '';\n }\n return !get(collapsedGroupKeySet).has(groupVal);\n }\n\n function isHiddenRow(row: GroupedTableRow<T>): boolean {\n if (!get(isGrouped))\n return false;\n if (!isRow(row))\n return false;\n return get(collapsedIdentifierSet).has(row[rowAttr]);\n }\n\n function computeGroupKey(row: T, grouping: TableRowKey<T>[]): string {\n let key = '';\n for (const gk of grouping) {\n if (key)\n key += GROUP_KEY_SEPARATOR;\n const val = row[gk];\n key += isDefined(val) ? val : '';\n }\n return key;\n }\n\n const mappedGroups = computed<Record<string, GroupedTableRow<T>[]>>(() => {\n const grouping = get(groupKeys);\n if (grouping.length === 0)\n return {};\n\n const result = get(sorted);\n const identifier = rowAttr;\n const acc: Record<string, GroupedTableRow<T>[]> = {};\n\n for (const row of result) {\n if (!isDefined(row[identifier]) || row[identifier] === '')\n continue;\n\n const groupVal = computeGroupKey(row, grouping);\n if (!acc[groupVal]) {\n acc[groupVal] = [\n {\n [GROUP_HEADER_BRAND]: true,\n group: getRowGroup(row),\n identifier: groupVal,\n } satisfies GroupHeader<T>,\n ];\n }\n\n acc[groupVal].push(row);\n }\n\n return acc;\n });\n\n const grouped = computed<readonly GroupedTableRow<T>[]>(() => {\n const result = get(sorted);\n const groupByKey = get(groupKey);\n\n if (!groupByKey)\n return result;\n\n const groups = get(mappedGroups);\n const out: GroupedTableRow<T>[] = [];\n for (const items of Object.values(groups)) {\n for (const item of items)\n out.push(item);\n }\n return out;\n });\n\n function getGroupRows(groupVal: string): T[] {\n if (!get(isGrouped))\n return [];\n\n const groupRows = get(mappedGroups)[groupVal];\n assert(groupRows);\n return groupRows.filter(isRow);\n }\n\n function onToggleExpandGroup(groupPartial: Partial<T>, value?: string): void {\n if (!value)\n return;\n\n const currentCollapsed = get(collapsedRows);\n\n const groupExpanded = isExpandedGroup(groupPartial);\n\n const groupRows = getGroupRows(value);\n\n set(\n collapsedRows,\n groupExpanded\n ? [...currentCollapsed, ...groupRows]\n : currentCollapsed.filter(row => !compareGroupsFn(row, groupPartial)),\n );\n\n set(collapsed, get(collapsedRows));\n }\n\n function onUngroup(): void {\n set(collapsedRows, []);\n\n set(collapsed, []);\n set(group, Array.isArray(get(group)) ? [] : undefined);\n }\n\n return {\n groupKeys,\n groupKey,\n isGrouped,\n mappedGroups,\n grouped,\n getRowGroup,\n getGroupRows,\n compareGroupsFn,\n isExpandedGroup,\n isHiddenRow,\n onToggleExpandGroup,\n onUngroup,\n };\n}\n"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ComputedRef, Ref } from 'vue';
|
|
1
|
+
import type { ComputedRef, DeepReadonly, Ref, ShallowRef } from 'vue';
|
|
2
2
|
import type { TableSortData } from '../../../components/tables/RuiTableHead.vue';
|
|
3
3
|
import type { TablePaginationData } from '../../../components/tables/RuiTablePagination.vue';
|
|
4
4
|
import type { TableOptions as TableDefaultOptions } from '../../../composables/defaults/table.js';
|
|
@@ -13,7 +13,7 @@ export interface UseTablePaginationOptions {
|
|
|
13
13
|
}
|
|
14
14
|
export interface UseTablePaginationDeps<T extends object> {
|
|
15
15
|
pagination: Ref<TablePaginationData | undefined>;
|
|
16
|
-
grouped: ComputedRef<GroupedTableRow<T>[]>;
|
|
16
|
+
grouped: ComputedRef<readonly GroupedTableRow<T>[]>;
|
|
17
17
|
isHiddenRow: (row: GroupedTableRow<T>) => boolean;
|
|
18
18
|
sort: Ref<TableSortData<T>>;
|
|
19
19
|
emitUpdateOptions: (options: {
|
|
@@ -25,9 +25,9 @@ export interface UseTablePaginationDeps<T extends object> {
|
|
|
25
25
|
export interface UseTablePaginationReturn<T extends object> {
|
|
26
26
|
paginationData: Ref<TablePaginationData>;
|
|
27
27
|
filtered: ComputedRef<GroupedTableRow<T>[]>;
|
|
28
|
-
itemsLength:
|
|
28
|
+
itemsLength: DeepReadonly<ShallowRef<number>>;
|
|
29
29
|
globalItemsPerPageSettings: ComputedRef<boolean>;
|
|
30
|
-
setInternalTotal: (items: GroupedTableRow<T>[]) => void;
|
|
30
|
+
setInternalTotal: (items: readonly GroupedTableRow<T>[]) => void;
|
|
31
31
|
resetPagination: () => void;
|
|
32
32
|
}
|
|
33
33
|
export declare function useTablePagination<T extends object>(options: UseTablePaginationOptions, deps: UseTablePaginationDeps<T>): UseTablePaginationReturn<T>;
|
|
@@ -1,8 +1,62 @@
|
|
|
1
|
-
import { assert } from "../../../utils/assert.js";
|
|
2
1
|
import { isRow } from "./types.js";
|
|
3
|
-
import { computed, ref, shallowRef, watch } from "vue";
|
|
2
|
+
import { computed, readonly, ref, shallowRef, watch } from "vue";
|
|
4
3
|
import { get, set } from "@vueuse/shared";
|
|
5
4
|
//#region src/composables/tables/data-table/pagination.ts
|
|
5
|
+
/**
|
|
6
|
+
* Skip data rows until the page start offset, tracking the last group header seen.
|
|
7
|
+
* Returns the index where collection should begin and the last group header before the slice.
|
|
8
|
+
*/
|
|
9
|
+
function skipToPageStart(result, start) {
|
|
10
|
+
let dataCount = 0;
|
|
11
|
+
let lastGroupHeader;
|
|
12
|
+
for (const [i, item] of result.entries()) if (isRow(item)) {
|
|
13
|
+
dataCount++;
|
|
14
|
+
if (dataCount > start) return {
|
|
15
|
+
startIndex: i,
|
|
16
|
+
dataCount,
|
|
17
|
+
lastGroupHeader
|
|
18
|
+
};
|
|
19
|
+
} else if (dataCount < start) lastGroupHeader = item;
|
|
20
|
+
else return {
|
|
21
|
+
startIndex: i,
|
|
22
|
+
dataCount,
|
|
23
|
+
lastGroupHeader
|
|
24
|
+
};
|
|
25
|
+
return {
|
|
26
|
+
startIndex: result.length,
|
|
27
|
+
dataCount,
|
|
28
|
+
lastGroupHeader
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Collect data rows (and interleaved group headers) for the current page.
|
|
33
|
+
*/
|
|
34
|
+
function collectPageRows(items, limit) {
|
|
35
|
+
const data = [];
|
|
36
|
+
let collected = 0;
|
|
37
|
+
for (const item of items) {
|
|
38
|
+
data.push(item);
|
|
39
|
+
if (isRow(item)) {
|
|
40
|
+
collected++;
|
|
41
|
+
if (collected >= limit) break;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return data;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Single-pass pagination that counts only data rows while preserving group headers.
|
|
48
|
+
* Prepends the nearest group header when a page starts mid-group, and removes
|
|
49
|
+
* trailing group headers with no data rows after them.
|
|
50
|
+
*/
|
|
51
|
+
function paginateGroupedRows(result, start, limit) {
|
|
52
|
+
const { startIndex, lastGroupHeader } = skipToPageStart(result, start);
|
|
53
|
+
const data = collectPageRows(result.slice(startIndex), limit);
|
|
54
|
+
const firstItem = data[0];
|
|
55
|
+
if (firstItem && isRow(firstItem) && lastGroupHeader) data.unshift(lastGroupHeader);
|
|
56
|
+
const lastItem = data.at(-1);
|
|
57
|
+
if (lastItem && !isRow(lastItem)) data.pop();
|
|
58
|
+
return data;
|
|
59
|
+
}
|
|
6
60
|
function useTablePagination(options, deps) {
|
|
7
61
|
const { itemsPerPage, paginationModifiersExternal, globalItemsPerPage } = options;
|
|
8
62
|
const { pagination, grouped, isHiddenRow, sort, emitUpdateOptions, tableDefaults } = deps;
|
|
@@ -40,27 +94,15 @@ function useTablePagination(options, deps) {
|
|
|
40
94
|
const filtered = computed(() => {
|
|
41
95
|
const result = get(grouped);
|
|
42
96
|
const paginated = get(paginationData);
|
|
43
|
-
|
|
44
|
-
if (!paginationModifiersExternal) {
|
|
45
|
-
const start = (paginated.page - 1) * limit;
|
|
46
|
-
const end = start + limit;
|
|
47
|
-
const preGroups = result.slice(0, start + 1).filter((item) => !isRow(item));
|
|
48
|
-
const postGroups = result.slice(start + 1, end + preGroups.length).filter((item) => !isRow(item));
|
|
49
|
-
const data = result.slice(start + preGroups.length, end + preGroups.length + postGroups.length);
|
|
50
|
-
const nearestGroup = preGroups.at(-1);
|
|
51
|
-
if (data.length > 0) {
|
|
52
|
-
const firstItem = data[0];
|
|
53
|
-
assert(firstItem);
|
|
54
|
-
if (isRow(firstItem) && nearestGroup) data.unshift(nearestGroup);
|
|
55
|
-
const lastItem = data.at(-1);
|
|
56
|
-
if (lastItem && !isRow(lastItem)) data.pop();
|
|
57
|
-
}
|
|
58
|
-
return data.filter((row) => !isHiddenRow(row));
|
|
59
|
-
}
|
|
97
|
+
if (!paginationModifiersExternal) return paginateGroupedRows(result, (paginated.page - 1) * paginated.limit, paginated.limit).filter((row) => !isHiddenRow(row));
|
|
60
98
|
return result.filter((row) => !isHiddenRow(row));
|
|
61
99
|
});
|
|
62
100
|
function setInternalTotal(items) {
|
|
63
|
-
if (!paginationModifiersExternal)
|
|
101
|
+
if (!paginationModifiersExternal) {
|
|
102
|
+
let count = 0;
|
|
103
|
+
for (const item of items) if (isRow(item)) count++;
|
|
104
|
+
set(itemsLength, count);
|
|
105
|
+
}
|
|
64
106
|
}
|
|
65
107
|
function resetPagination() {
|
|
66
108
|
set(paginationData, {
|
|
@@ -90,7 +132,7 @@ function useTablePagination(options, deps) {
|
|
|
90
132
|
return {
|
|
91
133
|
paginationData,
|
|
92
134
|
filtered,
|
|
93
|
-
itemsLength,
|
|
135
|
+
itemsLength: readonly(itemsLength),
|
|
94
136
|
globalItemsPerPageSettings,
|
|
95
137
|
setInternalTotal,
|
|
96
138
|
resetPagination
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pagination.js","names":[],"sources":["../../../../src/composables/tables/data-table/pagination.ts"],"sourcesContent":["import type { ComputedRef, Ref } from 'vue';\nimport type { TableSortData } from '@/components/tables/RuiTableHead.vue';\nimport type { TablePaginationData } from '@/components/tables/RuiTablePagination.vue';\nimport type { TableOptions as TableDefaultOptions } from '@/composables/defaults/table';\nimport { type GroupedTableRow, isRow } from '@/composables/tables/data-table/types';\
|
|
1
|
+
{"version":3,"file":"pagination.js","names":[],"sources":["../../../../src/composables/tables/data-table/pagination.ts"],"sourcesContent":["import type { ComputedRef, DeepReadonly, Ref, ShallowRef } from 'vue';\nimport type { TableSortData } from '@/components/tables/RuiTableHead.vue';\nimport type { TablePaginationData } from '@/components/tables/RuiTablePagination.vue';\nimport type { TableOptions as TableDefaultOptions } from '@/composables/defaults/table';\nimport { type GroupedTableRow, isRow } from '@/composables/tables/data-table/types';\n\nexport interface UseTablePaginationOptions {\n /** The default number of items displayed per page. */\n itemsPerPage: number;\n /** Whether pagination is managed externally (e.g. server-side). */\n paginationModifiersExternal: boolean | undefined;\n /** Whether to share the items-per-page setting across all tables. */\n globalItemsPerPage: boolean | undefined;\n}\n\nexport interface UseTablePaginationDeps<T extends object> {\n pagination: Ref<TablePaginationData | undefined>;\n grouped: ComputedRef<readonly GroupedTableRow<T>[]>;\n isHiddenRow: (row: GroupedTableRow<T>) => boolean;\n sort: Ref<TableSortData<T>>;\n emitUpdateOptions: (options: {\n sort?: TableSortData<T>;\n pagination?: TablePaginationData;\n }) => void;\n tableDefaults: TableDefaultOptions;\n}\n\nexport interface UseTablePaginationReturn<T extends object> {\n paginationData: Ref<TablePaginationData>;\n filtered: ComputedRef<GroupedTableRow<T>[]>;\n itemsLength: DeepReadonly<ShallowRef<number>>;\n globalItemsPerPageSettings: ComputedRef<boolean>;\n setInternalTotal: (items: readonly GroupedTableRow<T>[]) => void;\n resetPagination: () => void;\n}\n\n/**\n * Skip data rows until the page start offset, tracking the last group header seen.\n * Returns the index where collection should begin and the last group header before the slice.\n */\nfunction skipToPageStart<T extends object>(\n result: readonly GroupedTableRow<T>[],\n start: number,\n): { startIndex: number; dataCount: number; lastGroupHeader: GroupedTableRow<T> | undefined } {\n let dataCount = 0;\n let lastGroupHeader: GroupedTableRow<T> | undefined;\n\n for (const [i, item] of result.entries()) {\n if (isRow(item)) {\n dataCount++;\n if (dataCount > start)\n return { startIndex: i, dataCount, lastGroupHeader };\n }\n else if (dataCount < start) {\n lastGroupHeader = item;\n }\n else {\n return { startIndex: i, dataCount, lastGroupHeader };\n }\n }\n\n return { startIndex: result.length, dataCount, lastGroupHeader };\n}\n\n/**\n * Collect data rows (and interleaved group headers) for the current page.\n */\nfunction collectPageRows<T extends object>(\n items: readonly GroupedTableRow<T>[],\n limit: number,\n): GroupedTableRow<T>[] {\n const data: GroupedTableRow<T>[] = [];\n let collected = 0;\n\n for (const item of items) {\n data.push(item);\n\n if (isRow(item)) {\n collected++;\n if (collected >= limit)\n break;\n }\n }\n\n return data;\n}\n\n/**\n * Single-pass pagination that counts only data rows while preserving group headers.\n * Prepends the nearest group header when a page starts mid-group, and removes\n * trailing group headers with no data rows after them.\n */\nfunction paginateGroupedRows<T extends object>(\n result: readonly GroupedTableRow<T>[],\n start: number,\n limit: number,\n): GroupedTableRow<T>[] {\n const { startIndex, lastGroupHeader } = skipToPageStart(result, start);\n const data = collectPageRows(result.slice(startIndex), limit);\n\n // Prepend the nearest group header if the first item is a data row\n const firstItem = data[0];\n if (firstItem && isRow(firstItem) && lastGroupHeader)\n data.unshift(lastGroupHeader);\n\n // Remove trailing group header with no data rows after it\n const lastItem = data.at(-1);\n if (lastItem && !isRow(lastItem))\n data.pop();\n\n return data;\n}\n\nexport function useTablePagination<T extends object>(\n options: UseTablePaginationOptions,\n deps: UseTablePaginationDeps<T>,\n): UseTablePaginationReturn<T> {\n const { itemsPerPage, paginationModifiersExternal, globalItemsPerPage } = options;\n const { pagination, grouped, isHiddenRow, sort, emitUpdateOptions, tableDefaults } = deps;\n\n const itemsLength = shallowRef<number>(0);\n const internalPaginationState: Ref<TablePaginationData | undefined> = ref();\n\n const globalItemsPerPageSettings = computed<boolean>(() => {\n if (globalItemsPerPage !== undefined)\n return globalItemsPerPage;\n\n return get(tableDefaults.globalItemsPerPage);\n });\n\n const paginationData: Ref<TablePaginationData> = computed({\n get(): TablePaginationData {\n const paginated = get(internalPaginationState);\n if (!paginated) {\n return {\n total: get(itemsLength),\n limit: itemsPerPage,\n page: 1,\n };\n }\n\n if (paginationModifiersExternal)\n return paginated;\n\n return {\n total: get(itemsLength),\n limit: paginated.limit,\n page: paginated.page,\n limits: paginated.limits,\n };\n },\n set(value: TablePaginationData) {\n set(internalPaginationState, value);\n set(pagination, value);\n emitUpdateOptions({\n pagination: value,\n sort: get(sort),\n });\n },\n });\n\n const filtered = computed<GroupedTableRow<T>[]>(() => {\n const result = get(grouped);\n\n const paginated = get(paginationData);\n if (!paginationModifiersExternal) {\n const start = (paginated.page - 1) * paginated.limit;\n const data = paginateGroupedRows(result, start, paginated.limit);\n return data.filter(row => !isHiddenRow(row));\n }\n\n return result.filter(row => !isHiddenRow(row));\n });\n\n function setInternalTotal(items: readonly GroupedTableRow<T>[]): void {\n if (!paginationModifiersExternal) {\n let count = 0;\n for (const item of items) {\n if (isRow(item))\n count++;\n }\n set(itemsLength, count);\n }\n }\n\n function resetPagination(): void {\n set(paginationData, {\n ...get(paginationData),\n page: 1,\n });\n }\n\n // Sync external pagination model to internal state\n watch(pagination, val => set(internalPaginationState, val), { immediate: true });\n\n // Sync pagination limit to global table defaults\n watch(internalPaginationState, (paginationState) => {\n if (paginationState?.limit && get(globalItemsPerPageSettings))\n set(tableDefaults.itemsPerPage, paginationState.limit);\n });\n\n // Sync global table defaults to pagination limit\n watch(\n tableDefaults.itemsPerPage,\n (perPage) => {\n if (!get(globalItemsPerPageSettings))\n return;\n\n set(paginationData, {\n ...get(paginationData),\n limit: perPage,\n });\n },\n { immediate: true },\n );\n\n // Auto-adjust page when current page exceeds max available pages\n watch(paginationData, (paginationState) => {\n const { total, limit, page } = paginationState;\n const maxPages = Math.ceil(total / limit);\n\n if (maxPages > 0 && page > maxPages) {\n set(paginationData, {\n ...paginationState,\n page: maxPages,\n });\n }\n });\n\n return {\n paginationData,\n filtered,\n itemsLength: readonly(itemsLength),\n globalItemsPerPageSettings,\n setInternalTotal,\n resetPagination,\n };\n}\n"],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { assert } from "../../../utils/assert.js";
|
|
2
2
|
import { useTimeoutManager } from "../../timeout-manager.js";
|
|
3
3
|
import { isRow } from "./types.js";
|
|
4
|
-
import { computed,
|
|
4
|
+
import { computed, shallowRef, toValue, watch } from "vue";
|
|
5
5
|
import { isDefined } from "@vueuse/core";
|
|
6
6
|
import { get as get$1, set as set$1 } from "@vueuse/shared";
|
|
7
7
|
//#region src/composables/tables/data-table/selection.ts
|
|
@@ -10,9 +10,9 @@ function useTableSelection(options, deps) {
|
|
|
10
10
|
const { selectedData, filtered } = deps;
|
|
11
11
|
const shiftClicked = shallowRef(false);
|
|
12
12
|
const lastSelectedIndex = shallowRef(-1);
|
|
13
|
-
const internalSelectedData =
|
|
13
|
+
const internalSelectedData = shallowRef([]);
|
|
14
14
|
const { create: scheduleShiftSelect } = useTimeoutManager();
|
|
15
|
-
watch(selectedData, (val) => set$1(internalSelectedData, val), { immediate: true });
|
|
15
|
+
watch(selectedData, (val) => set$1(internalSelectedData, val ?? []), { immediate: true });
|
|
16
16
|
const visibleIdentifiers = computed(() => get$1(filtered).filter(isRow).map((row) => row[rowAttr]));
|
|
17
17
|
const selectedSet = computed(() => new Set(get$1(selectedData) ?? []));
|
|
18
18
|
const disabledRowKeySet = computed(() => {
|
|
@@ -52,7 +52,7 @@ function useTableSelection(options, deps) {
|
|
|
52
52
|
if (!isDefined(selectedRows)) return;
|
|
53
53
|
if (!multiPageSelect) if (checked) set$1(selectedData, get$1(visibleIdentifiers).filter(isSelectable));
|
|
54
54
|
else set$1(selectedData, get$1(visibleIdentifiers).filter(mustSelect));
|
|
55
|
-
else if (checked) set$1(selectedData, Array.from(new Set([...selectedRows, ...get$1(visibleIdentifiers).filter(isSelectable)])));
|
|
55
|
+
else if (checked) set$1(selectedData, Array.from(/* @__PURE__ */ new Set([...selectedRows, ...get$1(visibleIdentifiers).filter(isSelectable)])));
|
|
56
56
|
else {
|
|
57
57
|
const visibleSet = new Set(get$1(visibleIdentifiers));
|
|
58
58
|
const mustSelectSet = new Set(get$1(visibleIdentifiers).filter(mustSelect));
|
|
@@ -65,7 +65,7 @@ function useTableSelection(options, deps) {
|
|
|
65
65
|
if (!selectedRows) return;
|
|
66
66
|
const selected = isSelected(value);
|
|
67
67
|
if (checked && !selected) set$1(internalSelectedData, [...selectedRows, value]);
|
|
68
|
-
else if (!checked && selected) set$1(internalSelectedData,
|
|
68
|
+
else if (!checked && selected) set$1(internalSelectedData, selectedRows.filter((r) => r !== value));
|
|
69
69
|
if (userAction) set$1(selectedData, get$1(internalSelectedData));
|
|
70
70
|
}
|
|
71
71
|
function onCheckboxClick(event, value, index) {
|
|
@@ -88,10 +88,20 @@ function useTableSelection(options, deps) {
|
|
|
88
88
|
else {
|
|
89
89
|
const from = Math.min(lastIndex, index);
|
|
90
90
|
const to = Math.max(lastIndex, index);
|
|
91
|
+
const currentSelected = get$1(internalSelectedData);
|
|
92
|
+
const rangeIds = [];
|
|
91
93
|
for (let i = from; i <= to; i++) {
|
|
92
94
|
const currSelectedData = tableData[i];
|
|
93
95
|
assert(currSelectedData);
|
|
94
|
-
if (isRow(currSelectedData) && !isDisabledRow(currSelectedData[rowAttr]))
|
|
96
|
+
if (isRow(currSelectedData) && !isDisabledRow(currSelectedData[rowAttr])) rangeIds.push(currSelectedData[rowAttr]);
|
|
97
|
+
}
|
|
98
|
+
if (valueToApply) {
|
|
99
|
+
const existing = new Set(currentSelected);
|
|
100
|
+
const toAdd = rangeIds.filter((id) => !existing.has(id));
|
|
101
|
+
set$1(internalSelectedData, [...currentSelected, ...toAdd]);
|
|
102
|
+
} else {
|
|
103
|
+
const toRemove = new Set(rangeIds);
|
|
104
|
+
set$1(internalSelectedData, currentSelected.filter((id) => !toRemove.has(id)));
|
|
95
105
|
}
|
|
96
106
|
}
|
|
97
107
|
set$1(lastSelectedIndex, index);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"selection.js","names":[],"sources":["../../../../src/composables/tables/data-table/selection.ts"],"sourcesContent":["import type { ComputedRef, MaybeRefOrGetter, Ref } from 'vue';\nimport { type GroupedTableRow, isRow } from '@/composables/tables/data-table/types';\nimport { useTimeoutManager } from '@/composables/timeout-manager';\nimport { assert } from '@/utils/assert';\n\nexport interface UseTableSelectionOptions<T extends object, IdType extends keyof T> {\n /** The property on each row used as the unique row identifier. */\n rowAttr: IdType;\n /** Whether selection persists across pages. */\n multiPageSelect: boolean;\n /** Rows that cannot be selected or deselected by the user. */\n disabledRows: MaybeRefOrGetter<readonly T[] | undefined>;\n}\n\nexport interface UseTableSelectionDeps<T extends object, IdType extends keyof T> {\n selectedData: Ref<T[IdType][] | undefined>;\n filtered: ComputedRef<GroupedTableRow<T>[]>;\n}\n\nexport interface UseTableSelectionReturn<T extends object, IdType extends keyof T> {\n visibleIdentifiers: ComputedRef<T[IdType][]>;\n isAllSelected: ComputedRef<boolean>;\n indeterminate: ComputedRef<boolean>;\n isSelected: (identifier: T[IdType]) => boolean;\n isDisabledRow: (rowKey: T[IdType]) => boolean;\n isSelectable: (rowKey: T[IdType]) => boolean;\n mustSelect: (rowKey: T[IdType]) => boolean;\n onToggleAll: (checked: boolean) => void;\n onSelect: (checked: boolean, value: T[IdType], userAction?: boolean) => void;\n onCheckboxClick: (event: MouseEvent, value: T[IdType], index: number) => void;\n deselectRemovedRows: () => void;\n resetCheckboxShiftState: () => void;\n}\n\nexport function useTableSelection<T extends object, IdType extends keyof T>(\n options: UseTableSelectionOptions<T, IdType>,\n deps: UseTableSelectionDeps<T, IdType>,\n): UseTableSelectionReturn<T, IdType> {\n const { rowAttr, multiPageSelect, disabledRows } = options;\n const { selectedData, filtered } = deps;\n\n const shiftClicked: Ref<boolean> = shallowRef(false);\n const lastSelectedIndex: Ref<number> = shallowRef(-1);\n const internalSelectedData: Ref<T[IdType][]> = ref([]);\n const { create: scheduleShiftSelect } = useTimeoutManager();\n\n // Sync external selection model to internal state\n watch(selectedData, val => set(internalSelectedData, val), { immediate: true });\n\n const visibleIdentifiers = computed<T[IdType][]>(() =>\n get(filtered)\n .filter(isRow)\n .map(row => row[rowAttr]),\n );\n\n const selectedSet = computed<Set<T[IdType]>>(() => new Set(get(selectedData) ?? []));\n\n const disabledRowKeySet = computed<Set<T[IdType]>>(() => {\n const currentDisabledRows = toValue(disabledRows);\n if (!currentDisabledRows || !rowAttr)\n return new Set<T[IdType]>();\n return new Set<T[IdType]>(currentDisabledRows.map((row: T) => row[rowAttr]));\n });\n\n const isAllSelected = computed<boolean>(() => {\n const selectedRows = get(selectedData);\n if (!selectedRows || selectedRows.length === 0)\n return false;\n\n const selected = get(selectedSet);\n return get(visibleIdentifiers).every(id => selected.has(id));\n });\n\n const indeterminate = computed<boolean>(() => {\n const selectedRows = get(selectedData);\n if (!selectedRows)\n return false;\n\n return selectedRows.length > 0 && !get(isAllSelected);\n });\n\n function isSelected(identifier: T[IdType]): boolean {\n return get(selectedSet).has(identifier);\n }\n\n function isDisabledRow(rowKey: T[IdType]): boolean {\n return get(disabledRowKeySet).has(rowKey);\n }\n\n function isSelectable(rowKey: T[IdType]): boolean {\n return isSelected(rowKey) || !isDisabledRow(rowKey);\n }\n\n function mustSelect(rowKey: T[IdType]): boolean {\n return isSelected(rowKey) && isDisabledRow(rowKey);\n }\n\n function resetCheckboxShiftState(): void {\n set(shiftClicked, false);\n set(lastSelectedIndex, -1);\n }\n\n function onToggleAll(checked: boolean): void {\n const selectedRows = get(selectedData);\n\n if (!isDefined(selectedRows))\n return;\n\n if (!multiPageSelect) {\n if (checked)\n set(selectedData, get(visibleIdentifiers).filter(isSelectable));\n else set(selectedData, get(visibleIdentifiers).filter(mustSelect));\n }\n else {\n if (checked) {\n set(\n selectedData,\n Array.from(new Set([...selectedRows, ...get(visibleIdentifiers).filter(isSelectable)])),\n );\n }\n else {\n const visibleSet = new Set(get(visibleIdentifiers));\n const mustSelectSet = new Set(get(visibleIdentifiers).filter(mustSelect));\n set(\n selectedData,\n selectedRows.filter(rowKey => !visibleSet.has(rowKey) || mustSelectSet.has(rowKey)),\n );\n }\n }\n }\n\n function onSelect(checked: boolean, value: T[IdType], userAction: boolean = false): void {\n if (get(shiftClicked) && userAction)\n return;\n\n const selectedRows = get(internalSelectedData);\n if (!selectedRows)\n return;\n\n const selected = isSelected(value);\n\n if (checked && !selected) {\n set(internalSelectedData, [...selectedRows, value]);\n }\n else if (!checked && selected) {\n set(\n internalSelectedData,\n [...selectedRows].filter(r => r !== value),\n );\n }\n\n if (userAction)\n set(selectedData, get(internalSelectedData));\n }\n\n function onCheckboxClick(event: MouseEvent, value: T[IdType], index: number): void {\n const currentTarget = event.currentTarget;\n if (!(currentTarget instanceof HTMLElement))\n return;\n\n const input = currentTarget.querySelector('input');\n const target = event.target;\n const nodeName = target instanceof HTMLElement ? target.nodeName : undefined;\n\n const shiftKey = event.shiftKey;\n set(shiftClicked, shiftKey);\n\n if (input && nodeName !== 'INPUT') {\n if (shiftKey) {\n scheduleShiftSelect(() => {\n let lastIndex = get(lastSelectedIndex);\n if (lastIndex === -1)\n lastIndex = index;\n const tableData = get(filtered);\n const lastSelectedData = tableData[lastIndex];\n assert(lastSelectedData);\n\n if (isRow(lastSelectedData)) {\n const valueToApply = isSelected(lastSelectedData[rowAttr]);\n\n if (lastIndex === index) {\n onSelect(!valueToApply, value);\n }\n else {\n const from = Math.min(lastIndex, index);\n const to = Math.max(lastIndex, index);\n\n for (let i = from; i <= to; i++) {\n const currSelectedData = tableData[i];\n assert(currSelectedData);\n if (isRow(currSelectedData) && !isDisabledRow(currSelectedData[rowAttr]))\n onSelect(valueToApply, currSelectedData[rowAttr]);\n }\n }\n\n set(lastSelectedIndex, index);\n set(selectedData, get(internalSelectedData));\n }\n }, 1);\n }\n else {\n set(lastSelectedIndex, index);\n }\n }\n }\n\n function deselectRemovedRows(): void {\n const currentSelected = get(selectedData);\n if (!currentSelected)\n return;\n\n const visibleSet = new Set(get(visibleIdentifiers));\n const remaining = currentSelected.filter(key => visibleSet.has(key));\n\n if (remaining.length !== currentSelected.length)\n set(selectedData, remaining);\n }\n\n return {\n visibleIdentifiers,\n isAllSelected,\n indeterminate,\n isSelected,\n isDisabledRow,\n isSelectable,\n mustSelect,\n onToggleAll,\n onSelect,\n onCheckboxClick,\n deselectRemovedRows,\n resetCheckboxShiftState,\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"selection.js","names":[],"sources":["../../../../src/composables/tables/data-table/selection.ts"],"sourcesContent":["import type { ComputedRef, MaybeRefOrGetter, Ref } from 'vue';\nimport { type GroupedTableRow, isRow } from '@/composables/tables/data-table/types';\nimport { useTimeoutManager } from '@/composables/timeout-manager';\nimport { assert } from '@/utils/assert';\n\nexport interface UseTableSelectionOptions<T extends object, IdType extends keyof T> {\n /** The property on each row used as the unique row identifier. */\n rowAttr: IdType;\n /** Whether selection persists across pages. */\n multiPageSelect: boolean;\n /** Rows that cannot be selected or deselected by the user. */\n disabledRows: MaybeRefOrGetter<readonly T[] | undefined>;\n}\n\nexport interface UseTableSelectionDeps<T extends object, IdType extends keyof T> {\n selectedData: Ref<T[IdType][] | undefined>;\n filtered: ComputedRef<GroupedTableRow<T>[]>;\n}\n\nexport interface UseTableSelectionReturn<T extends object, IdType extends keyof T> {\n visibleIdentifiers: ComputedRef<T[IdType][]>;\n isAllSelected: ComputedRef<boolean>;\n indeterminate: ComputedRef<boolean>;\n isSelected: (identifier: T[IdType]) => boolean;\n isDisabledRow: (rowKey: T[IdType]) => boolean;\n isSelectable: (rowKey: T[IdType]) => boolean;\n mustSelect: (rowKey: T[IdType]) => boolean;\n onToggleAll: (checked: boolean) => void;\n onSelect: (checked: boolean, value: T[IdType], userAction?: boolean) => void;\n onCheckboxClick: (event: MouseEvent, value: T[IdType], index: number) => void;\n deselectRemovedRows: () => void;\n resetCheckboxShiftState: () => void;\n}\n\nexport function useTableSelection<T extends object, IdType extends keyof T>(\n options: UseTableSelectionOptions<T, IdType>,\n deps: UseTableSelectionDeps<T, IdType>,\n): UseTableSelectionReturn<T, IdType> {\n const { rowAttr, multiPageSelect, disabledRows } = options;\n const { selectedData, filtered } = deps;\n\n const shiftClicked: Ref<boolean> = shallowRef(false);\n const lastSelectedIndex: Ref<number> = shallowRef(-1);\n const internalSelectedData: Ref<T[IdType][]> = shallowRef([]);\n const { create: scheduleShiftSelect } = useTimeoutManager();\n\n // Sync external selection model to internal state\n watch(selectedData, val => set(internalSelectedData, val ?? []), { immediate: true });\n\n const visibleIdentifiers = computed<T[IdType][]>(() =>\n get(filtered)\n .filter(isRow)\n .map(row => row[rowAttr]),\n );\n\n const selectedSet = computed<Set<T[IdType]>>(() => new Set(get(selectedData) ?? []));\n\n const disabledRowKeySet = computed<Set<T[IdType]>>(() => {\n const currentDisabledRows = toValue(disabledRows);\n if (!currentDisabledRows || !rowAttr)\n return new Set<T[IdType]>();\n return new Set<T[IdType]>(currentDisabledRows.map((row: T) => row[rowAttr]));\n });\n\n const isAllSelected = computed<boolean>(() => {\n const selectedRows = get(selectedData);\n if (!selectedRows || selectedRows.length === 0)\n return false;\n\n const selected = get(selectedSet);\n return get(visibleIdentifiers).every(id => selected.has(id));\n });\n\n const indeterminate = computed<boolean>(() => {\n const selectedRows = get(selectedData);\n if (!selectedRows)\n return false;\n\n return selectedRows.length > 0 && !get(isAllSelected);\n });\n\n function isSelected(identifier: T[IdType]): boolean {\n return get(selectedSet).has(identifier);\n }\n\n function isDisabledRow(rowKey: T[IdType]): boolean {\n return get(disabledRowKeySet).has(rowKey);\n }\n\n function isSelectable(rowKey: T[IdType]): boolean {\n return isSelected(rowKey) || !isDisabledRow(rowKey);\n }\n\n function mustSelect(rowKey: T[IdType]): boolean {\n return isSelected(rowKey) && isDisabledRow(rowKey);\n }\n\n function resetCheckboxShiftState(): void {\n set(shiftClicked, false);\n set(lastSelectedIndex, -1);\n }\n\n function onToggleAll(checked: boolean): void {\n const selectedRows = get(selectedData);\n\n if (!isDefined(selectedRows))\n return;\n\n if (!multiPageSelect) {\n if (checked)\n set(selectedData, get(visibleIdentifiers).filter(isSelectable));\n else set(selectedData, get(visibleIdentifiers).filter(mustSelect));\n }\n else {\n if (checked) {\n set(\n selectedData,\n Array.from(new Set([...selectedRows, ...get(visibleIdentifiers).filter(isSelectable)])),\n );\n }\n else {\n const visibleSet = new Set(get(visibleIdentifiers));\n const mustSelectSet = new Set(get(visibleIdentifiers).filter(mustSelect));\n set(\n selectedData,\n selectedRows.filter(rowKey => !visibleSet.has(rowKey) || mustSelectSet.has(rowKey)),\n );\n }\n }\n }\n\n function onSelect(checked: boolean, value: T[IdType], userAction: boolean = false): void {\n if (get(shiftClicked) && userAction)\n return;\n\n const selectedRows = get(internalSelectedData);\n if (!selectedRows)\n return;\n\n const selected = isSelected(value);\n\n if (checked && !selected) {\n set(internalSelectedData, [...selectedRows, value]);\n }\n else if (!checked && selected) {\n set(\n internalSelectedData,\n selectedRows.filter(r => r !== value),\n );\n }\n\n if (userAction)\n set(selectedData, get(internalSelectedData));\n }\n\n function onCheckboxClick(event: MouseEvent, value: T[IdType], index: number): void {\n const currentTarget = event.currentTarget;\n if (!(currentTarget instanceof HTMLElement))\n return;\n\n const input = currentTarget.querySelector('input');\n const target = event.target;\n const nodeName = target instanceof HTMLElement ? target.nodeName : undefined;\n\n const shiftKey = event.shiftKey;\n set(shiftClicked, shiftKey);\n\n if (input && nodeName !== 'INPUT') {\n if (shiftKey) {\n scheduleShiftSelect(() => {\n let lastIndex = get(lastSelectedIndex);\n if (lastIndex === -1)\n lastIndex = index;\n const tableData = get(filtered);\n const lastSelectedData = tableData[lastIndex];\n assert(lastSelectedData);\n\n if (isRow(lastSelectedData)) {\n const valueToApply = isSelected(lastSelectedData[rowAttr]);\n\n if (lastIndex === index) {\n onSelect(!valueToApply, value);\n }\n else {\n const from = Math.min(lastIndex, index);\n const to = Math.max(lastIndex, index);\n\n // Batch: collect all IDs in range, then update once\n const currentSelected = get(internalSelectedData);\n const rangeIds: T[IdType][] = [];\n for (let i = from; i <= to; i++) {\n const currSelectedData = tableData[i];\n assert(currSelectedData);\n if (isRow(currSelectedData) && !isDisabledRow(currSelectedData[rowAttr]))\n rangeIds.push(currSelectedData[rowAttr]);\n }\n\n if (valueToApply) {\n const existing = new Set(currentSelected);\n const toAdd = rangeIds.filter(id => !existing.has(id));\n set(internalSelectedData, [...currentSelected, ...toAdd]);\n }\n else {\n const toRemove = new Set(rangeIds);\n set(internalSelectedData, currentSelected.filter(id => !toRemove.has(id)));\n }\n }\n\n set(lastSelectedIndex, index);\n set(selectedData, get(internalSelectedData));\n }\n }, 1);\n }\n else {\n set(lastSelectedIndex, index);\n }\n }\n }\n\n function deselectRemovedRows(): void {\n const currentSelected = get(selectedData);\n if (!currentSelected)\n return;\n\n const visibleSet = new Set(get(visibleIdentifiers));\n const remaining = currentSelected.filter(key => visibleSet.has(key));\n\n if (remaining.length !== currentSelected.length)\n set(selectedData, remaining);\n }\n\n return {\n visibleIdentifiers,\n isAllSelected,\n indeterminate,\n isSelected,\n isDisabledRow,\n isSelectable,\n mustSelect,\n onToggleAll,\n onSelect,\n onCheckboxClick,\n deselectRemovedRows,\n resetCheckboxShiftState,\n };\n}\n"],"mappings":"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"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { ComputedRef, MaybeRefOrGetter, Ref } from 'vue';
|
|
2
2
|
import type { SortColumn, TableRowKey, TableSortData } from '../../../components/tables/RuiTableHead.vue';
|
|
3
3
|
import type { TablePaginationData } from '../../../components/tables/RuiTablePagination.vue';
|
|
4
|
+
import { SortDirection } from '../../../components/tables/table-props.js';
|
|
4
5
|
export interface UseTableSortOptions<T extends object> {
|
|
5
6
|
/** The data rows to sort. */
|
|
6
7
|
rows: MaybeRefOrGetter<readonly T[]>;
|
|
@@ -20,13 +21,13 @@ export interface UseTableSortDeps<T extends object> {
|
|
|
20
21
|
export interface UseTableSortReturn<T extends object> {
|
|
21
22
|
sortData: ComputedRef<TableSortData<T>>;
|
|
22
23
|
sortedMap: ComputedRef<Partial<Record<TableRowKey<T>, SortColumn<T>>>>;
|
|
23
|
-
searchData: ComputedRef<T[]>;
|
|
24
|
-
sorted: ComputedRef<T[]>;
|
|
24
|
+
searchData: ComputedRef<readonly T[]>;
|
|
25
|
+
sorted: ComputedRef<readonly T[]>;
|
|
25
26
|
isSortedBy: (key: TableRowKey<T>) => boolean;
|
|
26
27
|
getSortIndex: (key: TableRowKey<T>) => number;
|
|
27
28
|
onSort: (payload: {
|
|
28
29
|
key: TableRowKey<T>;
|
|
29
|
-
direction?:
|
|
30
|
+
direction?: SortDirection;
|
|
30
31
|
}) => void;
|
|
31
32
|
}
|
|
32
33
|
export declare function useTableSort<T extends object>(options: UseTableSortOptions<T>, deps: UseTableSortDeps<T>): UseTableSortReturn<T>;
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { assert } from "../../../utils/assert.js";
|
|
2
|
+
import { SortDirection } from "../../../components/tables/table-props.js";
|
|
3
|
+
import { getObjectKeys } from "./types.js";
|
|
2
4
|
import { computed, toValue } from "vue";
|
|
3
5
|
import { get, set } from "@vueuse/shared";
|
|
4
6
|
//#region src/composables/tables/data-table/sort.ts
|
|
@@ -6,10 +8,26 @@ var SORT_COLLATOR = new Intl.Collator(void 0, {
|
|
|
6
8
|
sensitivity: "accent",
|
|
7
9
|
usage: "sort"
|
|
8
10
|
});
|
|
11
|
+
function toggleDirection(direction) {
|
|
12
|
+
return direction === SortDirection.asc ? SortDirection.desc : SortDirection.asc;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Detect whether each column contains numeric data by sampling the first non-null value.
|
|
16
|
+
*/
|
|
17
|
+
function detectNumericColumns(activeColumns, data) {
|
|
18
|
+
const isNumericCol = /* @__PURE__ */ new Map();
|
|
19
|
+
for (const key of activeColumns) for (const row of data) {
|
|
20
|
+
const val = row[key];
|
|
21
|
+
if (val != null) {
|
|
22
|
+
isNumericCol.set(key, !Number.isNaN(Number(val)));
|
|
23
|
+
break;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return isNumericCol;
|
|
27
|
+
}
|
|
9
28
|
function useTableSort(options, deps) {
|
|
10
29
|
const { rows, search, sortModifiersExternal } = options;
|
|
11
30
|
const { sort, pagination, emitUpdateOptions } = deps;
|
|
12
|
-
const getKeys = (t) => Object.keys(t);
|
|
13
31
|
const sortData = computed({
|
|
14
32
|
get() {
|
|
15
33
|
return get(sort);
|
|
@@ -36,30 +54,47 @@ function useTableSort(options, deps) {
|
|
|
36
54
|
return acc;
|
|
37
55
|
}, mapped);
|
|
38
56
|
});
|
|
57
|
+
const searchIndex = computed(() => {
|
|
58
|
+
if (!toValue(search)) return /* @__PURE__ */ new Map();
|
|
59
|
+
const currentRows = toValue(rows);
|
|
60
|
+
const index = /* @__PURE__ */ new Map();
|
|
61
|
+
for (const row of currentRows) {
|
|
62
|
+
const parts = [];
|
|
63
|
+
for (const key of getObjectKeys(row)) parts.push(`${row[key]}`);
|
|
64
|
+
index.set(row, parts.join("\0").toLocaleLowerCase());
|
|
65
|
+
}
|
|
66
|
+
return index;
|
|
67
|
+
});
|
|
39
68
|
const searchData = computed(() => {
|
|
40
69
|
const currentRows = toValue(rows);
|
|
41
70
|
const query = toValue(search)?.toLocaleLowerCase();
|
|
42
|
-
if (!query) return
|
|
43
|
-
|
|
71
|
+
if (!query) return currentRows;
|
|
72
|
+
const index = get(searchIndex);
|
|
73
|
+
return currentRows.filter((row) => {
|
|
74
|
+
return index.get(row)?.includes(query) ?? false;
|
|
75
|
+
});
|
|
44
76
|
});
|
|
45
77
|
const sorted = computed(() => {
|
|
46
78
|
const sortBy = get(sortData);
|
|
47
79
|
if (!sortBy || sortModifiersExternal) return get(searchData);
|
|
48
80
|
const data = [...get(searchData)];
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
81
|
+
const sortColumns = Array.isArray(sortBy) ? sortBy : [sortBy];
|
|
82
|
+
const activeColumns = sortColumns.map((col) => col.column).filter((col) => !!col);
|
|
83
|
+
if (activeColumns.length === 0) return data;
|
|
84
|
+
const isNumericCol = detectNumericColumns(activeColumns, data);
|
|
85
|
+
const directionMap = /* @__PURE__ */ new Map();
|
|
86
|
+
for (const col of sortColumns) if (col.column) directionMap.set(col.column, col.direction ?? SortDirection.asc);
|
|
87
|
+
data.sort((a, b) => {
|
|
88
|
+
for (const key of activeColumns) {
|
|
89
|
+
let [aVal, bVal] = [a[key], b[key]];
|
|
90
|
+
if (directionMap.get(key) === SortDirection.desc) [aVal, bVal] = [bVal, aVal];
|
|
91
|
+
let result;
|
|
92
|
+
if (isNumericCol.get(key)) result = Number(aVal) - Number(bVal);
|
|
93
|
+
else result = SORT_COLLATOR.compare(`${aVal}`, `${bVal}`);
|
|
94
|
+
if (result !== 0) return result;
|
|
95
|
+
}
|
|
96
|
+
return 0;
|
|
97
|
+
});
|
|
63
98
|
return data;
|
|
64
99
|
});
|
|
65
100
|
function isSortedBy(key) {
|
|
@@ -70,42 +105,45 @@ function useTableSort(options, deps) {
|
|
|
70
105
|
if (!sortBy || !Array.isArray(sortBy) || !isSortedBy(key)) return -1;
|
|
71
106
|
return sortBy.findIndex((s) => s.column === key);
|
|
72
107
|
}
|
|
73
|
-
function
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
...sortBy,
|
|
81
|
-
column: void 0,
|
|
82
|
-
direction: "asc"
|
|
83
|
-
});
|
|
84
|
-
else set(sortData, {
|
|
85
|
-
...sortBy,
|
|
86
|
-
direction: sortBy.direction === "asc" ? "desc" : "asc"
|
|
87
|
-
});
|
|
88
|
-
} else set(sortData, {
|
|
89
|
-
column: key,
|
|
90
|
-
direction: direction || "asc"
|
|
108
|
+
function onSortSingle(sortBy, key, direction) {
|
|
109
|
+
if (isSortedBy(key)) {
|
|
110
|
+
const newDirection = toggleDirection(direction ?? SortDirection.asc);
|
|
111
|
+
if (sortBy.direction === newDirection) set(sortData, {
|
|
112
|
+
...sortBy,
|
|
113
|
+
column: void 0,
|
|
114
|
+
direction: SortDirection.asc
|
|
91
115
|
});
|
|
92
|
-
|
|
93
|
-
|
|
116
|
+
else set(sortData, {
|
|
117
|
+
...sortBy,
|
|
118
|
+
direction: toggleDirection(sortBy.direction)
|
|
119
|
+
});
|
|
120
|
+
} else set(sortData, {
|
|
121
|
+
column: key,
|
|
122
|
+
direction: direction ?? SortDirection.asc
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
function onSortMulti(sortBy, key, direction) {
|
|
94
126
|
if (isSortedBy(key)) {
|
|
95
|
-
const newDirection =
|
|
127
|
+
const newDirection = toggleDirection(direction ?? SortDirection.asc);
|
|
96
128
|
const index = getSortIndex(key);
|
|
97
129
|
const sortByCol = sortBy[index];
|
|
98
130
|
assert(sortByCol);
|
|
99
131
|
if (sortByCol.direction === newDirection) set(sortData, sortBy.filter((_, i) => i !== index));
|
|
100
132
|
else set(sortData, sortBy.map((col, i) => i === index ? {
|
|
101
133
|
...col,
|
|
102
|
-
direction: col.direction
|
|
134
|
+
direction: toggleDirection(col.direction)
|
|
103
135
|
} : col));
|
|
104
136
|
} else set(sortData, [...sortBy, {
|
|
105
137
|
column: key,
|
|
106
|
-
direction: direction
|
|
138
|
+
direction: direction ?? SortDirection.asc
|
|
107
139
|
}]);
|
|
108
140
|
}
|
|
141
|
+
function onSort({ key, direction }) {
|
|
142
|
+
const sortBy = get(sortData);
|
|
143
|
+
if (!sortBy) return;
|
|
144
|
+
if (Array.isArray(sortBy)) onSortMulti(sortBy, key, direction);
|
|
145
|
+
else onSortSingle(sortBy, key, direction);
|
|
146
|
+
}
|
|
109
147
|
return {
|
|
110
148
|
sortData,
|
|
111
149
|
sortedMap,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sort.js","names":[],"sources":["../../../../src/composables/tables/data-table/sort.ts"],"sourcesContent":["import type { ComputedRef, MaybeRefOrGetter, Ref } from 'vue';\nimport type { SortColumn, TableRowKey, TableSortData } from '@/components/tables/RuiTableHead.vue';\nimport type { TablePaginationData } from '@/components/tables/RuiTablePagination.vue';\nimport { assert } from '@/utils/assert';\n\nconst SORT_COLLATOR = new Intl.Collator(undefined, { sensitivity: 'accent', usage: 'sort' });\n\nexport interface UseTableSortOptions<T extends object> {\n /** The data rows to sort. */\n rows: MaybeRefOrGetter<readonly T[]>;\n /** The current search query used to filter rows before sorting. */\n search: MaybeRefOrGetter<string>;\n /** Whether sorting is managed externally (e.g. server-side). */\n sortModifiersExternal: boolean | undefined;\n}\n\nexport interface UseTableSortDeps<T extends object> {\n sort: Ref<TableSortData<T>>;\n pagination: Ref<TablePaginationData | undefined>;\n emitUpdateOptions: (options: {\n sort?: TableSortData<T>;\n pagination?: TablePaginationData;\n }) => void;\n}\n\nexport interface UseTableSortReturn<T extends object> {\n sortData: ComputedRef<TableSortData<T>>;\n sortedMap: ComputedRef<Partial<Record<TableRowKey<T>, SortColumn<T>>>>;\n searchData: ComputedRef<T[]>;\n sorted: ComputedRef<T[]>;\n isSortedBy: (key: TableRowKey<T>) => boolean;\n getSortIndex: (key: TableRowKey<T>) => number;\n onSort: (payload: { key: TableRowKey<T>; direction?: 'asc' | 'desc' }) => void;\n}\n\nexport function useTableSort<T extends object>(\n options: UseTableSortOptions<T>,\n deps: UseTableSortDeps<T>,\n): UseTableSortReturn<T> {\n const { rows, search, sortModifiersExternal } = options;\n const { sort, pagination, emitUpdateOptions } = deps;\n\n const getKeys = <O extends object>(t: O): TableRowKey<O>[] => Object.keys(t) as TableRowKey<O>[];\n\n const sortData = computed<TableSortData<T>>({\n get(): TableSortData<T> {\n return get(sort);\n },\n set(value: TableSortData<T>) {\n set(sort, value);\n emitUpdateOptions({\n sort: value,\n pagination: get(pagination),\n });\n },\n });\n\n const sortedMap = computed<Partial<Record<TableRowKey<T>, SortColumn<T>>>>(() => {\n const mapped: Partial<Record<TableRowKey<T>, SortColumn<T>>> = {};\n const sortBy = get(sortData);\n if (!sortBy)\n return mapped;\n\n if (!Array.isArray(sortBy)) {\n if (sortBy.column)\n mapped[sortBy.column] = sortBy;\n\n return mapped;\n }\n\n return sortBy.reduce((acc, curr) => {\n if (!curr.column)\n return acc;\n\n acc[curr.column] = curr;\n return acc;\n }, mapped);\n });\n\n const searchData = computed<T[]>(() => {\n const currentRows = toValue(rows);\n const query = toValue(search)?.toLocaleLowerCase();\n if (!query)\n return [...currentRows];\n\n return currentRows.filter(row =>\n getKeys(row).some(key => `${row[key]}`.toLocaleLowerCase().includes(query)),\n );\n });\n\n const sorted: ComputedRef<T[]> = computed(() => {\n const sortBy = get(sortData);\n if (!sortBy || sortModifiersExternal)\n return get(searchData);\n\n const data = [...get(searchData)];\n\n const sortFn = (by: SortColumn<T>): void => {\n data.sort((a, b) => {\n const column = by.column;\n if (!column)\n return 0;\n\n let [aValue, bValue] = [a[column], b[column]];\n if (by.direction === 'desc')\n [aValue, bValue] = [bValue, aValue];\n\n const aNumber = Number(aValue);\n const bNumber = Number(bValue);\n if (!isNaN(aNumber) && !isNaN(bNumber))\n return aNumber - bNumber;\n\n return SORT_COLLATOR.compare(`${aValue}`, `${bValue}`);\n });\n };\n\n if (!Array.isArray(sortBy))\n sortFn(sortBy);\n else [...sortBy].reverse().forEach(sortFn);\n\n return data;\n });\n\n function isSortedBy(key: TableRowKey<T>): boolean {\n return key in get(sortedMap);\n }\n\n function getSortIndex(key: TableRowKey<T>): number {\n const sortBy = get(sortData);\n\n if (!sortBy || !Array.isArray(sortBy) || !isSortedBy(key))\n return -1;\n\n return sortBy.findIndex(s => s.column === key);\n }\n\n function onSort({ key, direction }: { key: TableRowKey<T>; direction?: 'asc' | 'desc' }): void {\n const sortBy = get(sortData);\n if (!sortBy)\n return;\n\n if (!Array.isArray(sortBy)) {\n if (isSortedBy(key)) {\n const newDirection = !direction || direction === 'asc' ? 'desc' : 'asc';\n\n if (sortBy.direction === newDirection) {\n set(sortData, { ...sortBy, column: undefined, direction: 'asc' });\n }\n else {\n set(sortData, {\n ...sortBy,\n direction: sortBy.direction === 'asc' ? 'desc' : 'asc',\n });\n }\n }\n else {\n set(sortData, { column: key, direction: direction || 'asc' });\n }\n return;\n }\n\n if (isSortedBy(key)) {\n const newDirection = !direction || direction === 'asc' ? 'desc' : 'asc';\n\n const index = getSortIndex(key);\n const sortByCol = sortBy[index];\n assert(sortByCol);\n\n if (sortByCol.direction === newDirection) {\n set(\n sortData,\n sortBy.filter((_, i) => i !== index),\n );\n }\n else {\n set(\n sortData,\n sortBy.map((col, i) =>\n i === index ? { ...col, direction: col.direction === 'asc' ? 'desc' : 'asc' } : col,\n ),\n );\n }\n }\n else {\n set(sortData, [...sortBy, { column: key, direction: direction || 'asc' }]);\n }\n }\n\n return {\n sortData,\n sortedMap,\n searchData,\n sorted,\n isSortedBy,\n getSortIndex,\n onSort,\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"sort.js","names":[],"sources":["../../../../src/composables/tables/data-table/sort.ts"],"sourcesContent":["import type { ComputedRef, MaybeRefOrGetter, Ref } from 'vue';\nimport type { SortColumn, TableRowKey, TableSortData } from '@/components/tables/RuiTableHead.vue';\nimport type { TablePaginationData } from '@/components/tables/RuiTablePagination.vue';\nimport { SortDirection } from '@/components/tables/table-props';\nimport { getObjectKeys } from '@/composables/tables/data-table/types';\nimport { assert } from '@/utils/assert';\n\nconst SORT_COLLATOR = new Intl.Collator(undefined, { sensitivity: 'accent', usage: 'sort' });\n\nfunction toggleDirection(direction: SortDirection): SortDirection {\n return direction === SortDirection.asc ? SortDirection.desc : SortDirection.asc;\n}\n\nexport interface UseTableSortOptions<T extends object> {\n /** The data rows to sort. */\n rows: MaybeRefOrGetter<readonly T[]>;\n /** The current search query used to filter rows before sorting. */\n search: MaybeRefOrGetter<string>;\n /** Whether sorting is managed externally (e.g. server-side). */\n sortModifiersExternal: boolean | undefined;\n}\n\nexport interface UseTableSortDeps<T extends object> {\n sort: Ref<TableSortData<T>>;\n pagination: Ref<TablePaginationData | undefined>;\n emitUpdateOptions: (options: {\n sort?: TableSortData<T>;\n pagination?: TablePaginationData;\n }) => void;\n}\n\nexport interface UseTableSortReturn<T extends object> {\n sortData: ComputedRef<TableSortData<T>>;\n sortedMap: ComputedRef<Partial<Record<TableRowKey<T>, SortColumn<T>>>>;\n searchData: ComputedRef<readonly T[]>;\n sorted: ComputedRef<readonly T[]>;\n isSortedBy: (key: TableRowKey<T>) => boolean;\n getSortIndex: (key: TableRowKey<T>) => number;\n onSort: (payload: { key: TableRowKey<T>; direction?: SortDirection }) => void;\n}\n\n/**\n * Detect whether each column contains numeric data by sampling the first non-null value.\n */\nfunction detectNumericColumns<T extends object>(\n activeColumns: TableRowKey<T>[],\n data: readonly T[],\n): Map<TableRowKey<T>, boolean> {\n const isNumericCol = new Map<TableRowKey<T>, boolean>();\n for (const key of activeColumns) {\n for (const row of data) {\n const val = row[key];\n if (val != null) {\n isNumericCol.set(key, !Number.isNaN(Number(val)));\n break;\n }\n }\n }\n return isNumericCol;\n}\n\nexport function useTableSort<T extends object>(\n options: UseTableSortOptions<T>,\n deps: UseTableSortDeps<T>,\n): UseTableSortReturn<T> {\n const { rows, search, sortModifiersExternal } = options;\n const { sort, pagination, emitUpdateOptions } = deps;\n\n const sortData = computed<TableSortData<T>>({\n get(): TableSortData<T> {\n return get(sort);\n },\n set(value: TableSortData<T>) {\n set(sort, value);\n emitUpdateOptions({\n sort: value,\n pagination: get(pagination),\n });\n },\n });\n\n const sortedMap = computed<Partial<Record<TableRowKey<T>, SortColumn<T>>>>(() => {\n const mapped: Partial<Record<TableRowKey<T>, SortColumn<T>>> = {};\n const sortBy = get(sortData);\n if (!sortBy)\n return mapped;\n\n if (!Array.isArray(sortBy)) {\n if (sortBy.column)\n mapped[sortBy.column] = sortBy;\n\n return mapped;\n }\n\n return sortBy.reduce((acc, curr) => {\n if (!curr.column)\n return acc;\n\n acc[curr.column] = curr;\n return acc;\n }, mapped);\n });\n\n // Pre-compute a single lowercased searchable string per row, recomputed only when rows change\n const searchIndex = computed<Map<T, string>>(() => {\n if (!toValue(search))\n return new Map<T, string>();\n\n const currentRows = toValue(rows);\n const index = new Map<T, string>();\n for (const row of currentRows) {\n const parts: string[] = [];\n for (const key of getObjectKeys(row))\n parts.push(`${row[key]}`);\n index.set(row, parts.join('\\0').toLocaleLowerCase());\n }\n return index;\n });\n\n const searchData = computed<readonly T[]>(() => {\n const currentRows = toValue(rows);\n const query = toValue(search)?.toLocaleLowerCase();\n if (!query)\n return currentRows;\n\n const index = get(searchIndex);\n return currentRows.filter((row) => {\n const searchStr = index.get(row);\n return searchStr?.includes(query) ?? false;\n });\n });\n\n const sorted: ComputedRef<readonly T[]> = computed(() => {\n const sortBy = get(sortData);\n if (!sortBy || sortModifiersExternal)\n return get(searchData);\n\n const data = [...get(searchData)];\n const sortColumns = Array.isArray(sortBy) ? sortBy : [sortBy];\n const activeColumns = sortColumns\n .map(col => col.column)\n .filter((col): col is TableRowKey<T> => !!col);\n\n if (activeColumns.length === 0)\n return data;\n\n const isNumericCol = detectNumericColumns(activeColumns, data);\n\n // Build a lookup for direction per column\n const directionMap = new Map<TableRowKey<T>, SortDirection>();\n for (const col of sortColumns) {\n if (col.column)\n directionMap.set(col.column, col.direction ?? SortDirection.asc);\n }\n\n data.sort((a, b) => {\n for (const key of activeColumns) {\n let [aVal, bVal] = [a[key], b[key]];\n if (directionMap.get(key) === SortDirection.desc)\n [aVal, bVal] = [bVal, aVal];\n\n let result: number;\n if (isNumericCol.get(key))\n result = Number(aVal) - Number(bVal);\n else\n result = SORT_COLLATOR.compare(`${aVal}`, `${bVal}`);\n\n if (result !== 0)\n return result;\n }\n return 0;\n });\n\n return data;\n });\n\n function isSortedBy(key: TableRowKey<T>): boolean {\n return key in get(sortedMap);\n }\n\n function getSortIndex(key: TableRowKey<T>): number {\n const sortBy = get(sortData);\n\n if (!sortBy || !Array.isArray(sortBy) || !isSortedBy(key))\n return -1;\n\n return sortBy.findIndex(s => s.column === key);\n }\n\n function onSortSingle(\n sortBy: SortColumn<T>,\n key: TableRowKey<T>,\n direction?: SortDirection,\n ): void {\n if (isSortedBy(key)) {\n const newDirection = toggleDirection(direction ?? SortDirection.asc);\n\n if (sortBy.direction === newDirection) {\n set(sortData, { ...sortBy, column: undefined, direction: SortDirection.asc });\n }\n else {\n set(sortData, {\n ...sortBy,\n direction: toggleDirection(sortBy.direction),\n });\n }\n }\n else {\n set(sortData, { column: key, direction: direction ?? SortDirection.asc });\n }\n }\n\n function onSortMulti(\n sortBy: SortColumn<T>[],\n key: TableRowKey<T>,\n direction?: SortDirection,\n ): void {\n if (isSortedBy(key)) {\n const newDirection = toggleDirection(direction ?? SortDirection.asc);\n\n const index = getSortIndex(key);\n const sortByCol = sortBy[index];\n assert(sortByCol);\n\n if (sortByCol.direction === newDirection) {\n set(sortData, sortBy.filter((_, i) => i !== index));\n }\n else {\n set(\n sortData,\n sortBy.map((col, i) =>\n i === index ? { ...col, direction: toggleDirection(col.direction) } : col,\n ),\n );\n }\n }\n else {\n set(sortData, [...sortBy, { column: key, direction: direction ?? SortDirection.asc }]);\n }\n }\n\n function onSort({ key, direction }: { key: TableRowKey<T>; direction?: SortDirection }): void {\n const sortBy = get(sortData);\n if (!sortBy)\n return;\n\n if (Array.isArray(sortBy))\n onSortMulti(sortBy, key, direction);\n else\n onSortSingle(sortBy, key, direction);\n }\n\n return {\n sortData,\n sortedMap,\n searchData,\n sorted,\n isSortedBy,\n getSortIndex,\n onSort,\n };\n}\n"],"mappings":"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"}
|
|
@@ -4,11 +4,13 @@ export interface TableOptions<T> {
|
|
|
4
4
|
pagination?: TablePaginationData;
|
|
5
5
|
sort?: TableSortData<T>;
|
|
6
6
|
}
|
|
7
|
+
export declare const GROUP_HEADER_BRAND: unique symbol;
|
|
7
8
|
export interface GroupHeader<T> {
|
|
8
|
-
|
|
9
|
+
[GROUP_HEADER_BRAND]: true;
|
|
9
10
|
identifier: string;
|
|
10
11
|
group: Partial<T>;
|
|
11
12
|
}
|
|
12
13
|
export type GroupedTableRow<T> = T | GroupHeader<T>;
|
|
13
14
|
export declare function isRow<T extends object>(item: GroupedTableRow<T>): item is T;
|
|
14
15
|
export declare function isHeaderSlot(slotName: string): slotName is `header.${string}`;
|
|
16
|
+
export declare function getObjectKeys<O extends object>(obj: O): (string & keyof O)[];
|