@rotki/ui-library 2.23.5 → 2.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -2
- 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.map +1 -1
- package/dist/components/alerts/RuiAlert.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/avatars/RuiAvatar.vue.d.ts +1 -1
- package/dist/components/avatars/RuiAvatar.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/avatars/RuiAvatarGroup.js.map +1 -1
- package/dist/components/avatars/RuiAvatarGroup.vue.d.ts +1 -1
- package/dist/components/avatars/RuiAvatarGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/avatars/use-avatar-group.d.ts +1 -1
- package/dist/components/buttons/button/RuiButton.vue.d.ts +1 -1
- package/dist/components/buttons/button/RuiButton.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/buttons/button/button-styles.d.ts +40 -2
- package/dist/components/buttons/button/button-styles.js +38 -0
- package/dist/components/buttons/button/button-styles.js.map +1 -1
- package/dist/components/buttons/button-group/RuiButtonGroup.js.map +1 -1
- package/dist/components/buttons/button-group/RuiButtonGroup.vue.d.ts +1 -1
- package/dist/components/buttons/button-group/RuiButtonGroup.vue_vue_type_script_setup_true_lang.js +26 -14
- package/dist/components/buttons/button-group/RuiButtonGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/calendar/RuiCalendar.js.map +1 -1
- package/dist/components/calendar/RuiCalendar.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/calendar/RuiCalendarGrid.js.map +1 -1
- package/dist/components/calendar/RuiCalendarGrid.vue_vue_type_script_setup_true_lang.js +7 -0
- package/dist/components/calendar/RuiCalendarGrid.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/calendar/RuiCalendarHeader.vue.d.ts +1 -1
- package/dist/components/calendar/RuiCalendarHeader.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/calendar/RuiCalendarMenu.js.map +1 -1
- package/dist/components/calendar/RuiCalendarMenu.vue.d.ts +1 -1
- package/dist/components/calendar/RuiCalendarMenu.vue_vue_type_script_setup_true_lang.js +1 -0
- package/dist/components/calendar/RuiCalendarMenu.vue_vue_type_script_setup_true_lang.js.map +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.map +1 -1
- package/dist/components/chips/RuiChip.vue.d.ts +1 -1
- package/dist/components/chips/RuiChip.vue_vue_type_script_setup_true_lang.js.map +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.map +1 -1
- package/dist/components/color-picker/RuiColorHue.vue_vue_type_script_setup_true_lang.js +2 -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.map +1 -1
- package/dist/components/color-picker/RuiColorPicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/date-time-picker/RuiDateTimePicker.js.map +1 -1
- package/dist/components/date-time-picker/RuiDateTimePicker.vue.d.ts +18 -2
- package/dist/components/date-time-picker/RuiDateTimePicker.vue_vue_type_script_setup_true_lang.js +73 -28
- 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.d.ts +2 -2
- 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.d.ts +3 -3
- 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.d.ts +48 -3
- package/dist/components/date-time-picker/partial-time.d.ts +35 -0
- package/dist/components/date-time-picker/partial-time.js +82 -0
- package/dist/components/date-time-picker/partial-time.js.map +1 -0
- package/dist/components/date-time-picker/segment-config.d.ts +1 -1
- package/dist/components/date-time-picker/segment-utils.d.ts +2 -2
- package/dist/components/date-time-picker/segment-utils.js +17 -5
- 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/use-date-bounds.d.ts +28 -0
- package/dist/components/date-time-picker/use-date-bounds.js +60 -0
- package/dist/components/date-time-picker/use-date-bounds.js.map +1 -0
- package/dist/components/date-time-picker/use-date-time-selection.d.ts +16 -12
- package/dist/components/date-time-picker/use-date-time-selection.js +126 -115
- package/dist/components/date-time-picker/use-date-time-selection.js.map +1 -1
- package/dist/components/date-time-picker/use-input-handler.d.ts +1 -1
- package/dist/components/date-time-picker/use-keyboard-handler.d.ts +2 -2
- package/dist/components/date-time-picker/use-keyboard-handler.js +52 -13
- package/dist/components/date-time-picker/use-keyboard-handler.js.map +1 -1
- package/dist/components/date-time-picker/utils.d.ts +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.map +1 -1
- package/dist/components/forms/auto-complete/RuiAutoComplete.js.map +1 -1
- package/dist/components/forms/auto-complete/RuiAutoComplete.vue.d.ts +2 -2
- package/dist/components/forms/auto-complete/RuiAutoComplete.vue_vue_type_script_setup_true_lang.js +136 -158
- package/dist/components/forms/auto-complete/RuiAutoComplete.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/forms/auto-complete/RuiAutoCompleteOption.js +7 -0
- package/dist/components/forms/auto-complete/RuiAutoCompleteOption.js.map +1 -0
- package/dist/components/forms/auto-complete/RuiAutoCompleteOption.vue.d.ts +45 -0
- package/dist/components/forms/auto-complete/RuiAutoCompleteOption.vue_vue_type_script_setup_true_lang.js +58 -0
- package/dist/components/forms/auto-complete/RuiAutoCompleteOption.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/forms/auto-complete/RuiAutoCompleteOptionList.js +7 -0
- package/dist/components/forms/auto-complete/RuiAutoCompleteOptionList.js.map +1 -0
- package/dist/components/forms/auto-complete/RuiAutoCompleteOptionList.vue.d.ts +70 -0
- package/dist/components/forms/auto-complete/RuiAutoCompleteOptionList.vue_vue_type_script_setup_true_lang.js +140 -0
- package/dist/components/forms/auto-complete/RuiAutoCompleteOptionList.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/forms/auto-complete/RuiAutoCompleteSelection.js +7 -0
- package/dist/components/forms/auto-complete/RuiAutoCompleteSelection.js.map +1 -0
- package/dist/components/forms/auto-complete/RuiAutoCompleteSelection.vue.d.ts +39 -0
- package/dist/components/forms/auto-complete/RuiAutoCompleteSelection.vue_vue_type_script_setup_true_lang.js +56 -0
- package/dist/components/forms/auto-complete/RuiAutoCompleteSelection.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/forms/auto-complete/auto-complete-styles.d.ts +48 -3
- package/dist/components/forms/category-picker/RuiCategoryPicker.js.map +1 -1
- package/dist/components/forms/category-picker/RuiCategoryPicker.vue.d.ts +2 -2
- package/dist/components/forms/category-picker/RuiCategoryPicker.vue_vue_type_script_setup_true_lang.js +49 -5
- package/dist/components/forms/category-picker/RuiCategoryPicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/forms/category-picker/category-picker-styles.d.ts +69 -5
- package/dist/components/forms/category-picker/category-picker-styles.js +19 -0
- package/dist/components/forms/category-picker/category-picker-styles.js.map +1 -1
- package/dist/components/forms/check-control-styles.d.ts +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.map +1 -1
- package/dist/components/forms/file-upload/RuiFileUpload.js.map +1 -1
- package/dist/components/forms/file-upload/RuiFileUpload.vue.d.ts +1 -1
- 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.map +1 -1
- package/dist/components/forms/radio-button/radio-group/RuiRadioGroup.js.map +1 -1
- 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.d.ts +1 -1
- 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.js.map +1 -1
- package/dist/components/forms/select/RuiMenuSelect.vue.d.ts +2 -2
- package/dist/components/forms/select/RuiMenuSelect.vue_vue_type_script_setup_true_lang.js +10 -8
- 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.map +1 -1
- package/dist/components/forms/select/menu-select-styles.d.ts +48 -3
- package/dist/components/forms/slider/RuiSlider.js.map +1 -1
- package/dist/components/forms/slider/RuiSlider.vue_vue_type_script_setup_true_lang.js +22 -12
- package/dist/components/forms/slider/RuiSlider.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/forms/slider/RuiSliderTicks.js +7 -0
- package/dist/components/forms/slider/RuiSliderTicks.js.map +1 -0
- package/dist/components/forms/slider/RuiSliderTicks.vue.d.ts +15 -0
- package/dist/components/forms/slider/RuiSliderTicks.vue_vue_type_script_setup_true_lang.js +59 -0
- package/dist/components/forms/slider/RuiSliderTicks.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/forms/slider/slider-styles.d.ts +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.d.ts +1 -1
- 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.d.ts +3 -3
- package/dist/components/forms/text-area/text-area-styles.js.map +1 -1
- package/dist/components/forms/text-field/RuiTextField.vue.d.ts +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.d.ts +37 -4
- package/dist/components/forms/text-field/text-field-styles.js +34 -1
- package/dist/components/forms/text-field/text-field-styles.js.map +1 -1
- package/dist/components/forms/text-input-styles.d.ts +20 -5
- package/dist/components/forms/text-input-styles.js +16 -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.map +1 -1
- package/dist/components/icons/RuiIcon.js.map +1 -1
- package/dist/components/icons/RuiIcon.vue_vue_type_script_setup_true_lang.js +26 -0
- package/dist/components/icons/RuiIcon.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/index.d.ts +57 -53
- package/dist/components/index.js +5 -1
- package/dist/components/loaders/RuiSkeletonBase.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/loaders/RuiSkeletonLoader.vue.d.ts +2 -2
- package/dist/components/loaders/RuiSkeletonLoader.vue_vue_type_script_setup_true_lang.js.map +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.d.ts +1 -1
- package/dist/components/logos/use-logo-sources.js +6 -1
- package/dist/components/logos/use-logo-sources.js.map +1 -1
- package/dist/components/overlays/badge/RuiBadge.vue.d.ts +1 -1
- package/dist/components/overlays/badge/RuiBadge.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/overlays/bottom-sheet/RuiBottomSheet.js.map +1 -1
- package/dist/components/overlays/bottom-sheet/RuiBottomSheet.vue.d.ts +1 -0
- package/dist/components/overlays/bottom-sheet/RuiBottomSheet.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/overlays/dialog/RuiDialog.js.map +1 -1
- package/dist/components/overlays/dialog/RuiDialog.vue.d.ts +2 -0
- package/dist/components/overlays/dialog/RuiDialog.vue_vue_type_script_setup_true_lang.js +15 -1
- package/dist/components/overlays/dialog/RuiDialog.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/overlays/menu/RuiMenu.js.map +1 -1
- package/dist/components/overlays/menu/RuiMenu.vue_vue_type_script_setup_true_lang.js +20 -0
- package/dist/components/overlays/menu/RuiMenu.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/overlays/navigation-drawer/RuiNavigationDrawer.js.map +1 -1
- 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.map +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.d.ts +2 -2
- package/dist/components/progress/RuiProgress.js.map +1 -1
- package/dist/components/progress/RuiProgress.vue.d.ts +3 -3
- package/dist/components/progress/RuiProgress.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/steppers/RuiFooterStepper.vue.d.ts +1 -1
- package/dist/components/steppers/RuiFooterStepper.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/steppers/RuiStepper.js.map +1 -1
- package/dist/components/steppers/RuiStepper.vue_vue_type_script_setup_true_lang.js +8 -0
- 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.map +1 -1
- package/dist/components/steppers/RuiStepperIcon.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/tables/RuiDataTable.js.map +1 -1
- package/dist/components/tables/RuiDataTable.vue.d.ts +5 -6
- package/dist/components/tables/RuiDataTable.vue_vue_type_script_setup_true_lang.js +42 -22
- 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.map +1 -1
- package/dist/components/tables/RuiTable.js +7 -0
- package/dist/components/tables/RuiTable.js.map +1 -0
- package/dist/components/tables/RuiTable.vue.d.ts +40 -0
- package/dist/components/tables/RuiTable.vue_vue_type_script_setup_true_lang.js +95 -0
- package/dist/components/tables/RuiTable.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/tables/RuiTableEmptyState.js.map +1 -1
- package/dist/components/tables/RuiTableEmptyState.vue.d.ts +5 -0
- package/dist/components/tables/RuiTableEmptyState.vue_vue_type_script_setup_true_lang.js +25 -10
- package/dist/components/tables/RuiTableEmptyState.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/tables/RuiTableErrorState.js +7 -0
- package/dist/components/tables/RuiTableErrorState.js.map +1 -0
- package/dist/components/tables/RuiTableErrorState.vue.d.ts +28 -0
- package/dist/components/tables/RuiTableErrorState.vue_vue_type_script_setup_true_lang.js +44 -0
- package/dist/components/tables/RuiTableErrorState.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/tables/RuiTableHead.js.map +1 -1
- package/dist/components/tables/RuiTableHead.vue.d.ts +5 -9
- package/dist/components/tables/RuiTableHead.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/tables/RuiTableLoadingState.js +7 -0
- package/dist/components/tables/RuiTableLoadingState.js.map +1 -0
- package/dist/components/tables/RuiTableLoadingState.vue.d.ts +13 -0
- package/dist/components/tables/RuiTableLoadingState.vue_vue_type_script_setup_true_lang.js +40 -0
- package/dist/components/tables/RuiTableLoadingState.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/tables/RuiTablePagination.vue.d.ts +1 -1
- package/dist/components/tables/RuiTablePagination.vue_vue_type_script_setup_true_lang.js +2 -1
- package/dist/components/tables/RuiTablePagination.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/tables/data-table/RuiDataTableBody.vue.d.ts +1 -1
- package/dist/components/tables/data-table/RuiDataTableBody.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/tables/data-table/RuiDataTableCell.js.map +1 -1
- package/dist/components/tables/data-table/RuiDataTableCell.vue.d.ts +1 -1
- package/dist/components/tables/data-table/RuiDataTableCell.vue_vue_type_script_setup_true_lang.js +6 -0
- package/dist/components/tables/data-table/RuiDataTableCell.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/tables/data-table/RuiDataTableEmptyRow.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/tables/data-table/RuiDataTableExpandedRow.js.map +1 -1
- package/dist/components/tables/data-table/RuiDataTableExpandedRow.vue_vue_type_script_setup_true_lang.js +6 -0
- package/dist/components/tables/data-table/RuiDataTableExpandedRow.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/tables/data-table/RuiDataTableGroupRow.js.map +1 -1
- package/dist/components/tables/data-table/RuiDataTableGroupRow.vue_vue_type_script_setup_true_lang.js +5 -0
- package/dist/components/tables/data-table/RuiDataTableGroupRow.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/tables/data-table/RuiDataTableLoadingRow.js.map +1 -1
- package/dist/components/tables/data-table/RuiDataTableLoadingRow.vue_vue_type_script_setup_true_lang.js +2 -6
- package/dist/components/tables/data-table/RuiDataTableLoadingRow.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/tables/data-table/RuiDataTableMobileSort.js.map +1 -1
- package/dist/components/tables/data-table/RuiDataTableMobileSort.vue.d.ts +2 -2
- package/dist/components/tables/data-table/RuiDataTableMobileSort.vue_vue_type_script_setup_true_lang.js +4 -0
- package/dist/components/tables/data-table/RuiDataTableMobileSort.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/tables/data-table/RuiDataTableRow.js.map +1 -1
- package/dist/components/tables/data-table/RuiDataTableRow.vue.d.ts +1 -1
- package/dist/components/tables/data-table/RuiDataTableRow.vue_vue_type_script_setup_true_lang.js +25 -0
- package/dist/components/tables/data-table/RuiDataTableRow.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/tables/data-table/context.d.ts +2 -3
- package/dist/components/tables/data-table/context.js.map +1 -1
- package/dist/components/tables/data-table-styles.d.ts +2 -5
- package/dist/components/tables/data-table-styles.js +1 -2
- package/dist/components/tables/data-table-styles.js.map +1 -1
- package/dist/components/tabs/tab/RuiTab.js.map +1 -1
- package/dist/components/tabs/tab/RuiTab.vue.d.ts +1 -1
- package/dist/components/tabs/tab/RuiTab.vue_vue_type_script_setup_true_lang.js.map +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.d.ts +9 -0
- package/dist/components/tabs/tab-items/RuiTabItems.vue_vue_type_script_setup_true_lang.js +16 -0
- package/dist/components/tabs/tab-items/RuiTabItems.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/tabs/tabs/RuiTabs.js.map +1 -1
- package/dist/components/tabs/tabs/RuiTabs.vue.d.ts +6 -1
- package/dist/components/tabs/tabs/RuiTabs.vue_vue_type_script_setup_true_lang.js +12 -0
- 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.d.ts +1 -1
- 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.d.ts +2 -2
- package/dist/composables/colors/index.d.ts +3 -3
- package/dist/composables/dropdown-menu.d.ts +2 -2
- package/dist/composables/dropdown-menu.js +26 -23
- package/dist/composables/dropdown-menu.js.map +1 -1
- package/dist/composables/floating.d.ts +7 -8
- package/dist/composables/floating.js +19 -14
- package/dist/composables/floating.js.map +1 -1
- package/dist/composables/forms/auto-complete/focus.js +5 -0
- package/dist/composables/forms/auto-complete/focus.js.map +1 -1
- package/dist/composables/forms/auto-complete/keyboard-navigation.js +12 -5
- package/dist/composables/forms/auto-complete/keyboard-navigation.js.map +1 -1
- package/dist/composables/forms/auto-complete/search.d.ts +1 -1
- package/dist/composables/forms/auto-complete/search.js +5 -0
- 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 +1 -1
- package/dist/composables/forms/category-picker/use-category-picker.js +1 -0
- package/dist/composables/forms/category-picker/use-category-picker.js.map +1 -1
- package/dist/composables/forms/use-prepend-append-width.d.ts +18 -3
- package/dist/composables/forms/use-prepend-append-width.js +18 -3
- package/dist/composables/forms/use-prepend-append-width.js.map +1 -1
- package/dist/composables/index.d.ts +4 -3
- package/dist/composables/index.js +2 -1
- package/dist/composables/overlay-stack.d.ts +52 -0
- package/dist/composables/overlay-stack.js +93 -0
- package/dist/composables/overlay-stack.js.map +1 -0
- package/dist/composables/sticky-header.js.map +1 -1
- package/dist/composables/tables/data-table/expansion.js +7 -0
- package/dist/composables/tables/data-table/expansion.js.map +1 -1
- package/dist/composables/tables/data-table/grouping.d.ts +1 -1
- package/dist/composables/tables/data-table/pagination.d.ts +2 -2
- package/dist/composables/tables/data-table/selection.d.ts +1 -1
- package/dist/composables/tables/data-table/selection.js +37 -34
- package/dist/composables/tables/data-table/selection.js.map +1 -1
- package/dist/composables/theme.d.ts +4 -2
- package/dist/composables/theme.js +18 -24
- package/dist/composables/theme.js.map +1 -1
- package/dist/i18n/keys.d.ts +1 -1
- package/dist/i18n/keys.js +1 -1
- package/dist/i18n/keys.js.map +1 -1
- package/dist/icons/icons_1.d.ts +8 -8
- package/dist/icons/icons_1.js +246 -223
- package/dist/icons/icons_1.js.map +1 -1
- package/dist/icons/icons_2.d.ts +26 -26
- package/dist/icons/icons_2.js +320 -400
- package/dist/icons/icons_2.js.map +1 -1
- package/dist/icons/icons_3.d.ts +46 -46
- package/dist/icons/icons_3.js +661 -706
- package/dist/icons/icons_3.js.map +1 -1
- package/dist/icons/icons_4.d.ts +63 -63
- package/dist/icons/icons_4.js +4347 -4480
- package/dist/icons/icons_4.js.map +1 -1
- package/dist/icons/icons_5.d.ts +60 -1
- package/dist/icons/icons_5.js +774 -31
- package/dist/icons/icons_5.js.map +1 -1
- package/dist/icons/index.d.ts +1 -1
- package/dist/icons/index.js +84 -25
- package/dist/icons/index.js.map +1 -1
- package/dist/index.js +11 -6
- package/dist/index.js.map +1 -1
- package/dist/style.css +83 -10
- package/dist/theme/index.js +1 -0
- package/dist/theme/index.js.map +1 -1
- package/dist/types/theme.d.ts +1 -1
- package/dist/utils/assert.js +2 -2
- package/dist/utils/assert.js.map +1 -1
- package/dist/utils/blockie.d.ts +4 -0
- package/dist/utils/blockie.js +8 -0
- package/dist/utils/blockie.js.map +1 -1
- package/dist/utils/helpers.d.ts +24 -18
- package/dist/utils/helpers.js +28 -21
- package/dist/utils/helpers.js.map +1 -1
- package/dist/utils/is-equal.d.ts +9 -0
- package/dist/utils/is-equal.js +22 -15
- package/dist/utils/is-equal.js.map +1 -1
- package/dist/utils/tv.d.ts +6 -2
- package/dist/utils/tv.js +30 -14
- package/dist/utils/tv.js.map +1 -1
- package/dist/vite-plugin/client.d.ts +1 -1
- package/dist/vite-plugin/index.js +29 -21
- package/dist/vite-plugin/index.js.map +1 -1
- package/dist/vite-plugin/scanner.d.ts +5 -2
- package/dist/vite-plugin/scanner.js +5 -2
- package/dist/vite-plugin/scanner.js.map +1 -1
- package/dist/vite-plugin/types.d.ts +4 -8
- package/dist/web-types.json +872 -50
- package/package.json +32 -33
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RuiCategoryPicker.vue_vue_type_script_setup_true_lang.js","names":["$attrs","$slots"],"sources":["../../../../src/components/forms/category-picker/RuiCategoryPicker.vue"],"sourcesContent":["<script lang=\"ts\" setup generic=\"TValue, TItem\">\nimport type { KeyOfType } from '@/composables/dropdown-menu';\nimport type { VueClassValue } from '@/types/class-value';\nimport { breakpointsTailwind, useBreakpoints } from '@vueuse/core';\nimport RuiButton from '@/components/buttons/button/RuiButton.vue';\nimport { categoryPickerActivatorStyles, categoryPickerStyles, type CategoryPickerVariant } from '@/components/forms/category-picker/category-picker-styles';\nimport RuiTextField from '@/components/forms/text-field/RuiTextField.vue';\nimport RuiFormTextDetail from '@/components/helpers/RuiFormTextDetail.vue';\nimport RuiIcon from '@/components/icons/RuiIcon.vue';\nimport RuiDialog, { type DialogProps } from '@/components/overlays/dialog/RuiDialog.vue';\nimport RuiMenu from '@/components/overlays/menu/RuiMenu.vue';\nimport RuiProgress from '@/components/progress/RuiProgress.vue';\nimport { Placement } from '@/composables/floating';\nimport { useCategoryPicker } from '@/composables/forms/category-picker/use-category-picker';\nimport { useFormTextDetail } from '@/utils/form-text-detail';\nimport { cn } from '@/utils/tv';\n\nexport interface RuiCategoryPickerClassNames {\n root?: VueClassValue;\n rail?: VueClassValue;\n detail?: VueClassValue;\n search?: VueClassValue;\n}\n\nexport type CategoryPickerBreakpoint = 'sm' | 'md' | 'lg' | 'xl' | '2xl';\n\nexport interface RuiCategoryPickerProps<TValue, TItem> {\n /** The full catalogue of selectable items. */\n items: TItem[];\n /** Resolve an item's category label. Takes precedence over `categoryAttr`. */\n categoryOf?: (item: TItem) => string;\n /** Resolve an item's category from one of its own properties. */\n categoryAttr?: keyof TItem;\n /** Property whose value becomes the model value. Omit to use the item itself. */\n keyAttr?: KeyOfType<TItem, TValue extends (infer U)[] ? U : TValue>;\n /** Property that produces an item's display text. */\n textAttr?: keyof TItem;\n /** Field label, and the title of the mobile sheet. */\n label?: string;\n /** Placeholder shown in the field while it is empty or being searched. */\n placeholder?: string;\n /** Allow filtering: type in the field (desktop) or the sheet's search box (mobile). */\n searchable?: boolean;\n /**\n * Custom predicate. Receives the resolved category label as the third\n * argument, matching the `RuiAutoComplete` filter signature.\n */\n filter?: (item: TItem, query: string, category: string) => boolean;\n /** Show the synthetic \"All\" pseudo-category as the first rail entry. */\n showAll?: boolean;\n /** Label for the \"All\" pseudo-category. */\n allLabel?: string;\n /** Text shown when no item matches the current search. */\n emptyText?: string;\n disabled?: boolean;\n readOnly?: boolean;\n dense?: boolean;\n clearable?: boolean;\n loading?: boolean;\n /** Trigger field style: underline (`default`), `outlined`, or `filled`. */\n variant?: CategoryPickerVariant;\n /** Marks the trigger field as required (renders the asterisk). */\n required?: boolean;\n /** Validation errors rendered under the trigger field. */\n errorMessages?: string | string[];\n /** Success messages rendered under the trigger field. */\n successMessages?: string | string[];\n /** Hint rendered under the trigger field. */\n hint?: string;\n /** Hide the details row (errors/success/hint) under the trigger field. */\n hideDetails?: boolean;\n /** Below this breakpoint the picker collapses to a single-pane drill-in. */\n mobileBreakpoint?: CategoryPickerBreakpoint;\n /** Forwarded to the mobile bottom-sheet (`RuiDialog`). */\n dialogOptions?: DialogProps;\n classNames?: RuiCategoryPickerClassNames;\n}\n\ndefineOptions({\n name: 'RuiCategoryPicker',\n inheritAttrs: false,\n});\n\nconst modelValue = defineModel<TValue>();\nconst searchInput = defineModel<string>('search', { default: '' });\n\nconst {\n items,\n categoryOf = undefined,\n categoryAttr = undefined,\n keyAttr = undefined,\n textAttr = undefined,\n label = 'Select',\n placeholder = 'Search',\n searchable = true,\n filter = undefined,\n showAll = true,\n allLabel = 'All',\n emptyText = 'No results',\n disabled = false,\n readOnly = false,\n dense = false,\n clearable = false,\n loading = false,\n variant = 'outlined',\n required = false,\n errorMessages = [],\n successMessages = [],\n hint = '',\n hideDetails = false,\n mobileBreakpoint = 'md',\n dialogOptions = undefined,\n classNames = undefined,\n} = defineProps<RuiCategoryPickerProps<TValue, TItem>>();\n\nconst emit = defineEmits<{\n select: [item: TItem];\n}>();\n\ndefineSlots<{\n 'activator'?: (props: { attrs: { onClick?: () => void; onMouseover?: () => void; onMouseleave?: () => void }; isOpen: boolean; open: () => void; item: TItem | undefined; text: string | undefined }) => any;\n 'activator.label'?: (props: { item: TItem | undefined }) => any;\n 'selection'?: (props: { item: TItem }) => any;\n 'selection.prepend'?: (props: { item: TItem }) => any;\n 'category'?: (props: { category: string | null; label: string; active: boolean; count: number }) => any;\n 'item'?: (props: { item: TItem; active: boolean; selected: boolean }) => any;\n 'item.prepend'?: (props: { item: TItem; active: boolean; selected: boolean }) => any;\n 'item.append'?: (props: { item: TItem; active: boolean; selected: boolean }) => any;\n 'empty'?: () => any;\n 'header'?: () => any;\n 'footer'?: (props: { close: () => void }) => any;\n}>();\n\nconst isOpen = ref<boolean>(false);\nconst focusedPane = ref<'rail' | 'detail'>('rail');\nconst highlightedItemIndex = ref<number>(0);\nconst drillStep = ref<'category' | 'detail'>('category');\n\nconst railRef = useTemplateRef<HTMLDivElement>('railRef');\nconst detailRef = useTemplateRef<HTMLDivElement>('detailRef');\nconst activatorRef = useTemplateRef<HTMLInputElement>('activatorRef');\nconst fieldRef = useTemplateRef<HTMLElement>('fieldRef');\nconst isHovered = ref<boolean>(false);\n\nconst { focused } = useFocus(activatorRef);\nconst { hasError, hasSuccess } = useFormTextDetail(() => errorMessages, () => successMessages);\n\nconst baseId = useId();\nconst breakpoints = useBreakpoints(breakpointsTailwind);\n\nfunction resolveCategory(item: TItem): string {\n if (categoryOf)\n return categoryOf(item);\n if (categoryAttr !== undefined)\n return String(item[categoryAttr] ?? '');\n return '';\n}\n\nconst {\n activeCategory,\n detailItems,\n detailRows,\n getIdentifier,\n getText,\n isEmpty,\n isSelected,\n railEntries,\n setActiveCategory,\n syncActiveToSelection,\n} = useCategoryPicker<TValue, TItem>({\n allLabel: () => allLabel,\n categoryOf: resolveCategory,\n filter: () => filter,\n items: () => items,\n keyAttr,\n modelValue,\n search: searchInput,\n searchable: () => searchable,\n showAll: () => showAll,\n textAttr,\n});\n\nconst isMobile = computed<boolean>(() => get(breakpoints.smaller(mobileBreakpoint)));\n\nconst mode = computed<'twoPane' | 'drill'>(() => (get(isMobile) ? 'drill' : 'twoPane'));\n\n// Desktop anchors an outside-click popover under the field (RuiMenu); narrow\n// width shows a full-width bottom sheet (RuiDialog). Each branch returns only\n// its own shell's props so the other component's props never leak as attrs.\nconst shell = computed<typeof RuiMenu | typeof RuiDialog>(() => (get(isMobile) ? RuiDialog : RuiMenu));\n\nconst shellProps = computed<Record<string, unknown>>(() => {\n if (get(isMobile)) {\n return {\n ariaLabel: dialogOptions?.ariaLabel ?? label,\n bottomSheet: dialogOptions?.bottomSheet ?? true,\n maxWidth: dialogOptions?.maxWidth,\n persistent: dialogOptions?.persistent,\n width: dialogOptions?.width ?? '100%',\n };\n }\n return {\n // Anchor to the field box, not the wrapper, so the popover sits directly\n // under the input instead of below the reserved details row.\n anchorEl: get(fieldRef) ?? undefined,\n // Drop the menu's default vertical padding so the popover box equals our\n // panel: the size middleware caps the panel to the available height, and\n // any extra chrome padding would push the popover past the viewport edge.\n classNames: { content: 'py-0', menu: 'z-[9999]' },\n closeOnContentClick: false,\n disableAutoFocus: true,\n fullWidth: true,\n options: { placement: Placement.bottomStart, size: true },\n persistent: dialogOptions?.persistent,\n persistOnActivatorClick: true,\n };\n});\n\nconst ui = computed<ReturnType<typeof categoryPickerStyles>>(() => categoryPickerStyles({\n dense,\n mode: get(mode),\n}));\n\nconst selectedItem = computed<TItem | undefined>(() => {\n const value = get(modelValue);\n if (value === undefined)\n return undefined;\n return items.find(item => getIdentifier(item) === value);\n});\n\nconst selectedText = computed<string | undefined>(() => {\n const selected = get(selectedItem);\n return selected ? getText(selected) : undefined;\n});\n\nconst outlined = computed<boolean>(() => variant === 'outlined');\n\n// Desktop lets the user type in the field itself (no separate search box);\n// narrow width keeps a read-only trigger that opens the sheet's own search.\nconst canType = computed<boolean>(() => searchable && !get(isMobile) && !readOnly && !disabled);\n\nconst isTyping = computed<boolean>(() => get(isOpen) && get(canType));\n\nconst float = computed<boolean>(() => (get(isOpen) || get(selectedItem) !== undefined || get(focused)) && get(outlined));\n\nconst legendText = computed<string>(() => {\n if (!get(float) || !label)\n return '';\n return required ? `${label} ﹡` : label;\n});\n\n// Drives both the clear button itself and the room the selection overlay has\n// to leave for it, so the two can never disagree.\nconst showClear = computed<boolean>(() =>\n clearable && get(selectedItem) !== undefined && !disabled && !readOnly);\n\nconst activatorUi = computed<ReturnType<typeof categoryPickerActivatorStyles>>(() => categoryPickerActivatorStyles({\n dense,\n disabled,\n filled: variant === 'filled',\n float: get(float),\n hasError: get(hasError),\n hasSuccess: get(hasSuccess) && !get(hasError),\n hovered: get(isHovered),\n opened: get(isOpen),\n outlined: get(outlined),\n readonly: readOnly,\n withClear: get(showClear),\n}));\n\nconst activeRailIndex = computed<number>(() =>\n get(railEntries).findIndex(entry => entry.category === get(activeCategory)));\n\nconst showRail = computed<boolean>(() => get(mode) === 'twoPane' || get(drillStep) === 'category');\nconst showDetail = computed<boolean>(() => get(mode) === 'twoPane' || get(drillStep) === 'detail');\n\nfunction clamp(value: number, max: number): number {\n if (value < 0)\n return 0;\n if (value > max)\n return max;\n return value;\n}\n\nfunction open(): void {\n if (disabled)\n return;\n set(isOpen, true);\n}\n\nfunction close(): void {\n set(isOpen, false);\n}\n\nfunction onInput(event: Event): void {\n const target = event.target;\n if (!(target instanceof HTMLInputElement))\n return;\n set(searchInput, target.value);\n if (!get(isOpen))\n open();\n}\n\nfunction selectItem(item: TItem): void {\n if (readOnly)\n return;\n set(modelValue, getIdentifier(item));\n emit('select', item);\n close();\n}\n\nfunction clearSelection(): void {\n set(modelValue, undefined);\n}\n\nfunction onCategoryClick(category: string | null): void {\n setActiveCategory(category);\n if (get(mode) === 'drill')\n set(drillStep, 'detail');\n else\n focusPane('detail');\n}\n\nfunction focusPane(pane: 'rail' | 'detail'): void {\n set(focusedPane, pane);\n nextTick(() => {\n // preventScroll: focus moves between panes inside a teleported popover;\n // without it the browser scrolls the page behind to reveal the pane.\n (pane === 'rail' ? get(railRef) : get(detailRef))?.focus({ preventScroll: true });\n });\n}\n\nfunction moveRail(direction: 1 | -1): void {\n const entries = get(railEntries);\n if (entries.length === 0)\n return;\n const next = clamp(get(activeRailIndex) + direction, entries.length - 1);\n setActiveCategory(entries[next]?.category ?? null);\n}\n\nfunction moveItem(direction: 1 | -1): void {\n const total = get(detailItems).length;\n if (total === 0)\n return;\n set(highlightedItemIndex, clamp(get(highlightedItemIndex) + direction, total - 1));\n}\n\nfunction enterDetail(): void {\n if (get(detailItems).length === 0)\n return;\n resetHighlightToSelection();\n if (get(mode) === 'drill')\n set(drillStep, 'detail');\n focusPane('detail');\n}\n\nfunction selectHighlighted(): void {\n const item = get(detailItems)[get(highlightedItemIndex)];\n if (item !== undefined)\n selectItem(item);\n}\n\n// Enter from the field commits the best match for the current query, so a\n// type-to-pick flow (type a few letters, press Enter) works without leaving the\n// input. Does nothing when the field is empty.\nfunction selectTopResult(): void {\n if (!get(searchInput).trim())\n return;\n const item = get(detailItems)[0];\n if (item !== undefined)\n selectItem(item);\n}\n\nfunction resetHighlightToSelection(): void {\n const index = get(detailItems).findIndex(item => isSelected(item));\n set(highlightedItemIndex, index >= 0 ? index : 0);\n}\n\nfunction backToRail(): void {\n if (get(mode) === 'drill')\n set(drillStep, 'category');\n else\n focusPane('rail');\n}\n\nfunction scrollActiveDescendantIntoView(container: HTMLElement | null, id: string): void {\n if (!container)\n return;\n nextTick(() => {\n container.querySelector(`#${id}`)?.scrollIntoView({ block: 'nearest' });\n });\n}\n\n// Reset the item highlight whenever the active category changes.\nwatch(activeCategory, () => {\n resetHighlightToSelection();\n});\n\nwatch(highlightedItemIndex, (index) => {\n scrollActiveDescendantIntoView(get(detailRef), `${baseId}-opt-${index}`);\n});\n\nwatch(activeRailIndex, (index) => {\n if (index >= 0)\n scrollActiveDescendantIntoView(get(railRef), `${baseId}-cat-${index}`);\n});\n\nwatch(isOpen, (value) => {\n if (value) {\n syncActiveToSelection();\n set(focusedPane, 'rail');\n set(drillStep, 'category');\n resetHighlightToSelection();\n // Desktop is a combobox: keep focus in the field so the user can type\n // straight away (ArrowDown moves into the panes). The mobile sheet has no\n // typing field, so focus the rail instead.\n nextTick(() => (get(canType) ? get(activatorRef) : get(railRef))?.focus({ preventScroll: true }));\n }\n else {\n // Reset the query so the field shows the selection again next time, and\n // return focus to the trigger (APG dialog contract).\n set(searchInput, '');\n nextTick(() => get(activatorRef)?.focus({ preventScroll: true }));\n }\n});\n</script>\n\n<template>\n <component\n :is=\"shell\"\n v-model=\"isOpen\"\n v-bind=\"{ ...$attrs, ...shellProps }\"\n >\n <template #activator=\"{ attrs }\">\n <slot\n name=\"activator\"\n v-bind=\"{ attrs, isOpen, item: selectedItem, open, text: selectedText }\"\n >\n <div :class=\"activatorUi.wrapper()\">\n <div\n ref=\"fieldRef\"\n role=\"combobox\"\n data-id=\"activator\"\n :class=\"activatorUi.activator()\"\n aria-haspopup=\"dialog\"\n :aria-controls=\"isOpen ? `${baseId}-panel` : undefined\"\n :aria-expanded=\"isOpen\"\n :aria-disabled=\"disabled || undefined\"\n :aria-readonly=\"(readOnly || !canType) || undefined\"\n :aria-required=\"required || undefined\"\n :aria-invalid=\"hasError || undefined\"\n :aria-busy=\"loading || undefined\"\n v-bind=\"readOnly ? {} : attrs\"\n @mouseenter=\"isHovered = true\"\n @mouseleave=\"isHovered = false\"\n >\n <span\n v-if=\"outlined || (!selectedItem && !isTyping)\"\n :class=\"activatorUi.label()\"\n >\n <slot\n name=\"activator.label\"\n v-bind=\"{ item: selectedItem }\"\n >\n {{ label }}\n </slot>\n <span\n v-if=\"required\"\n :class=\"activatorUi.required()\"\n >\n ﹡\n </span>\n </span>\n <span\n v-if=\"selectedItem && !isTyping && $slots.selection\"\n data-id=\"selection\"\n :class=\"activatorUi.selection()\"\n >\n <slot\n name=\"selection.prepend\"\n v-bind=\"{ item: selectedItem }\"\n />\n <slot\n name=\"selection\"\n v-bind=\"{ item: selectedItem }\"\n />\n </span>\n <input\n ref=\"activatorRef\"\n data-id=\"search-input\"\n :value=\"isTyping ? searchInput : (($slots.selection && selectedItem) ? '' : (selectedText ?? ''))\"\n :placeholder=\"isTyping ? placeholder : ''\"\n :readonly=\"!canType\"\n :disabled=\"disabled\"\n :aria-invalid=\"hasError || undefined\"\n class=\"bg-transparent outline-none\"\n :class=\"[activatorUi.value(), !canType && 'cursor-pointer']\"\n @input=\"onInput($event)\"\n @keydown.down.prevent=\"focusPane('rail')\"\n @keydown.enter.prevent=\"selectTopResult()\"\n @keydown.esc=\"close()\"\n />\n <span\n v-if=\"showClear\"\n data-id=\"clear\"\n :class=\"[activatorUi.clear(), focused && '!visible', { 'mr-2': !dense }]\"\n @click.stop.prevent=\"clearSelection()\"\n >\n <RuiIcon\n color=\"error\"\n name=\"lu-x\"\n size=\"18\"\n />\n </span>\n <span\n data-id=\"chevron\"\n :class=\"activatorUi.iconWrapper()\"\n >\n <RuiIcon\n :class=\"activatorUi.icon()\"\n :size=\"dense ? 16 : 24\"\n name=\"lu-chevron-down\"\n />\n </span>\n <RuiProgress\n v-if=\"loading\"\n :class=\"activatorUi.progress()\"\n color=\"primary\"\n thickness=\"3\"\n variant=\"indeterminate\"\n />\n <fieldset\n v-if=\"outlined\"\n :class=\"activatorUi.fieldset()\"\n >\n <legend :class=\"activatorUi.legend()\">\n {{ legendText }}\n </legend>\n </fieldset>\n </div>\n <RuiFormTextDetail\n v-if=\"!hideDetails\"\n class=\"px-3 pt-1\"\n :error-messages=\"errorMessages\"\n :success-messages=\"successMessages\"\n :hint=\"hint\"\n />\n </div>\n </slot>\n </template>\n\n <div\n :id=\"`${baseId}-panel`\"\n :class=\"ui.root({ class: cn(classNames?.root) })\"\n data-id=\"panel\"\n >\n <!-- On desktop the field itself is the search input, so the panel only\n needs its own search box in the mobile sheet. -->\n <div\n v-if=\"isMobile || $slots.header\"\n :class=\"ui.header()\"\n >\n <slot name=\"header\">\n <div :class=\"ui.title()\">\n {{ label }}\n </div>\n </slot>\n <RuiTextField\n v-if=\"searchable && isMobile\"\n v-model=\"searchInput\"\n :class=\"cn(classNames?.search)\"\n :placeholder=\"placeholder\"\n :dense=\"dense\"\n variant=\"outlined\"\n prepend-icon=\"lu-search\"\n hide-details\n clearable\n data-id=\"search\"\n />\n </div>\n\n <div :class=\"ui.body()\">\n <!-- Category rail (master) -->\n <div\n v-show=\"showRail\"\n ref=\"railRef\"\n :class=\"ui.rail({ class: cn(classNames?.rail) })\"\n role=\"tablist\"\n aria-orientation=\"vertical\"\n :aria-label=\"label\"\n :aria-activedescendant=\"focusedPane === 'rail' && activeRailIndex >= 0 ? `${baseId}-cat-${activeRailIndex}` : undefined\"\n tabindex=\"0\"\n data-id=\"rail\"\n @focus=\"focusedPane = 'rail'\"\n @keydown.down.prevent=\"moveRail(1)\"\n @keydown.up.prevent=\"moveRail(-1)\"\n @keydown.right.prevent=\"enterDetail()\"\n @keydown.enter.prevent=\"enterDetail()\"\n @keydown.home.prevent=\"setActiveCategory(railEntries[0]?.category ?? null)\"\n @keydown.end.prevent=\"setActiveCategory(railEntries[railEntries.length - 1]?.category ?? null)\"\n >\n <RuiButton\n v-for=\"(entry, index) in railEntries\"\n :id=\"`${baseId}-cat-${index}`\"\n :key=\"entry.category ?? '__all__'\"\n role=\"tab\"\n variant=\"list\"\n :size=\"dense ? 'sm' : undefined\"\n :active=\"entry.category === activeCategory\"\n :aria-selected=\"entry.category === activeCategory\"\n tabindex=\"-1\"\n :data-highlighted=\"focusedPane === 'rail' && index === activeRailIndex\"\n :data-category=\"entry.category ?? '__all__'\"\n @click=\"onCategoryClick(entry.category)\"\n >\n <slot\n name=\"category\"\n v-bind=\"{ active: entry.category === activeCategory, category: entry.category, count: entry.count, label: entry.label }\"\n >\n <span class=\"truncate\">{{ entry.label }}</span>\n <span :class=\"ui.railCount()\">{{ entry.count }}</span>\n </slot>\n </RuiButton>\n </div>\n\n <!-- Detail pane -->\n <div\n v-show=\"showDetail\"\n ref=\"detailRef\"\n :class=\"ui.detail({ class: cn(classNames?.detail) })\"\n role=\"listbox\"\n :aria-label=\"activeCategory ?? allLabel\"\n :aria-activedescendant=\"focusedPane === 'detail' && !isEmpty ? `${baseId}-opt-${highlightedItemIndex}` : undefined\"\n tabindex=\"0\"\n data-id=\"detail\"\n @focus=\"focusedPane = 'detail'\"\n @keydown.down.prevent=\"moveItem(1)\"\n @keydown.up.prevent=\"moveItem(-1)\"\n @keydown.left.prevent=\"backToRail()\"\n @keydown.home.prevent=\"highlightedItemIndex = 0\"\n @keydown.end.prevent=\"highlightedItemIndex = detailItems.length - 1\"\n @keydown.enter.prevent=\"selectHighlighted()\"\n @keydown.space.prevent=\"selectHighlighted()\"\n >\n <template v-if=\"mode === 'drill' && showDetail\">\n <button\n type=\"button\"\n :class=\"ui.backButton()\"\n data-id=\"back\"\n @click=\"backToRail()\"\n >\n <RuiIcon\n name=\"lu-chevron-left\"\n size=\"18\"\n />\n <span>{{ activeCategory ?? allLabel }}</span>\n </button>\n </template>\n\n <slot\n v-if=\"isEmpty\"\n name=\"empty\"\n >\n <div :class=\"ui.empty()\">\n {{ emptyText }}\n </div>\n </slot>\n\n <template\n v-for=\"row in detailRows\"\n v-else\n :key=\"row.type === 'header' ? `h-${row.category}` : `i-${row.index}`\"\n >\n <div\n v-if=\"row.type === 'header'\"\n :class=\"ui.subheader()\"\n role=\"presentation\"\n >\n {{ row.category }}\n </div>\n <RuiButton\n v-else\n :id=\"`${baseId}-opt-${row.index}`\"\n role=\"option\"\n variant=\"list\"\n :size=\"dense ? 'sm' : undefined\"\n :active=\"isSelected(row.item)\"\n :aria-selected=\"isSelected(row.item)\"\n tabindex=\"-1\"\n :data-highlighted=\"focusedPane === 'detail' && row.index === highlightedItemIndex\"\n :class=\"{ [ui.highlighted()]: focusedPane === 'detail' && row.index === highlightedItemIndex && !isSelected(row.item) }\"\n @click=\"selectItem(row.item)\"\n >\n <template\n v-if=\"$slots['item.prepend']\"\n #prepend\n >\n <slot\n name=\"item.prepend\"\n v-bind=\"{ active: row.index === highlightedItemIndex, item: row.item, selected: isSelected(row.item) }\"\n />\n </template>\n <slot\n name=\"item\"\n v-bind=\"{ active: row.index === highlightedItemIndex, item: row.item, selected: isSelected(row.item) }\"\n >\n {{ getText(row.item) }}\n </slot>\n <template\n v-if=\"$slots['item.append']\"\n #append\n >\n <slot\n name=\"item.append\"\n v-bind=\"{ active: row.index === highlightedItemIndex, item: row.item, selected: isSelected(row.item) }\"\n />\n </template>\n </RuiButton>\n </template>\n </div>\n </div>\n\n <div\n v-if=\"$slots.footer\"\n :class=\"ui.footer()\"\n >\n <slot\n name=\"footer\"\n v-bind=\"{ close }\"\n />\n </div>\n </div>\n </component>\n</template>\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"RuiCategoryPicker.vue_vue_type_script_setup_true_lang.js","names":["$attrs","$slots"],"sources":["../../../../src/components/forms/category-picker/RuiCategoryPicker.vue"],"sourcesContent":["<script lang=\"ts\" setup generic=\"TValue, TItem\">\nimport type { KeyOfType } from '@/composables/dropdown-menu';\nimport type { VueClassValue } from '@/types/class-value';\nimport { breakpointsTailwind, useBreakpoints } from '@vueuse/core';\nimport RuiButton from '@/components/buttons/button/RuiButton.vue';\nimport { categoryPickerActivatorStyles, categoryPickerStyles, type CategoryPickerVariant } from '@/components/forms/category-picker/category-picker-styles';\nimport RuiTextField from '@/components/forms/text-field/RuiTextField.vue';\nimport RuiFormTextDetail from '@/components/helpers/RuiFormTextDetail.vue';\nimport RuiIcon from '@/components/icons/RuiIcon.vue';\nimport RuiDialog, { type DialogProps } from '@/components/overlays/dialog/RuiDialog.vue';\nimport RuiMenu from '@/components/overlays/menu/RuiMenu.vue';\nimport RuiProgress from '@/components/progress/RuiProgress.vue';\nimport { Placement } from '@/composables/floating';\nimport { useCategoryPicker } from '@/composables/forms/category-picker/use-category-picker';\nimport { useFormTextDetail } from '@/utils/form-text-detail';\nimport { cn } from '@/utils/tv';\n\nexport interface RuiCategoryPickerClassNames {\n root?: VueClassValue;\n rail?: VueClassValue;\n detail?: VueClassValue;\n search?: VueClassValue;\n}\n\nexport type CategoryPickerBreakpoint = 'sm' | 'md' | 'lg' | 'xl' | '2xl';\n\nexport interface RuiCategoryPickerProps<TValue, TItem> {\n /** The full catalogue of selectable items. */\n items: TItem[];\n /** Resolve an item's category label. Takes precedence over `categoryAttr`. */\n categoryOf?: (item: TItem) => string;\n /** Resolve an item's category from one of its own properties. */\n categoryAttr?: keyof TItem;\n /** Property whose value becomes the model value. Omit to use the item itself. */\n keyAttr?: KeyOfType<TItem, TValue extends (infer U)[] ? U : TValue>;\n /** Property that produces an item's display text. */\n textAttr?: keyof TItem;\n /** Field label, and the title of the mobile sheet. */\n label?: string;\n /** Placeholder shown in the field while it is empty or being searched. */\n placeholder?: string;\n /** Allow filtering: type in the field (desktop) or the sheet's search box (mobile). */\n searchable?: boolean;\n /**\n * Custom predicate. Receives the resolved category label as the third\n * argument, matching the `RuiAutoComplete` filter signature.\n */\n filter?: (item: TItem, query: string, category: string) => boolean;\n /** Show the synthetic \"All\" pseudo-category as the first rail entry. */\n showAll?: boolean;\n /** Label for the \"All\" pseudo-category. */\n allLabel?: string;\n /** Text shown when no item matches the current search. */\n emptyText?: string;\n disabled?: boolean;\n readOnly?: boolean;\n dense?: boolean;\n clearable?: boolean;\n loading?: boolean;\n /** Trigger field style: underline (`default`), `outlined`, or `filled`. */\n variant?: CategoryPickerVariant;\n /** Marks the trigger field as required (renders the asterisk). */\n required?: boolean;\n /** Validation errors rendered under the trigger field. */\n errorMessages?: string | string[];\n /** Success messages rendered under the trigger field. */\n successMessages?: string | string[];\n /** Hint rendered under the trigger field. */\n hint?: string;\n /** Hide the details row (errors/success/hint) under the trigger field. */\n hideDetails?: boolean;\n /** Below this breakpoint the picker collapses to a single-pane drill-in. */\n mobileBreakpoint?: CategoryPickerBreakpoint;\n /** Forwarded to the mobile bottom-sheet (`RuiDialog`). */\n dialogOptions?: DialogProps;\n classNames?: RuiCategoryPickerClassNames;\n}\n\ndefineOptions({\n name: 'RuiCategoryPicker',\n inheritAttrs: false,\n});\n\nconst modelValue = defineModel<TValue>();\nconst searchInput = defineModel<string>('search', { default: '' });\n\nconst {\n items,\n categoryOf = undefined,\n categoryAttr = undefined,\n keyAttr = undefined,\n textAttr = undefined,\n label = 'Select',\n placeholder = 'Search',\n searchable = true,\n filter = undefined,\n showAll = true,\n allLabel = 'All',\n emptyText = 'No results',\n disabled = false,\n readOnly = false,\n dense = false,\n clearable = false,\n loading = false,\n variant = 'outlined',\n required = false,\n errorMessages = [],\n successMessages = [],\n hint = '',\n hideDetails = false,\n mobileBreakpoint = 'md',\n dialogOptions = undefined,\n classNames = undefined,\n} = defineProps<RuiCategoryPickerProps<TValue, TItem>>();\n\nconst emit = defineEmits<{\n select: [item: TItem];\n}>();\n\ndefineSlots<{\n 'activator'?: (props: { attrs: { onClick?: () => void; onMouseover?: () => void; onMouseleave?: () => void }; isOpen: boolean; open: () => void; item: TItem | undefined; text: string | undefined }) => any;\n 'activator.label'?: (props: { item: TItem | undefined }) => any;\n 'selection'?: (props: { item: TItem }) => any;\n 'selection.prepend'?: (props: { item: TItem }) => any;\n 'category'?: (props: { category: string | null; label: string; active: boolean; count: number }) => any;\n 'item'?: (props: { item: TItem; active: boolean; selected: boolean }) => any;\n 'item.prepend'?: (props: { item: TItem; active: boolean; selected: boolean }) => any;\n 'item.append'?: (props: { item: TItem; active: boolean; selected: boolean }) => any;\n 'empty'?: () => any;\n 'header'?: () => any;\n 'footer'?: (props: { close: () => void }) => any;\n}>();\n\nconst isOpen = ref<boolean>(false);\nconst focusedPane = ref<'rail' | 'detail'>('rail');\nconst highlightedItemIndex = ref<number>(0);\nconst drillStep = ref<'category' | 'detail'>('category');\n\nconst railRef = useTemplateRef<HTMLDivElement>('railRef');\nconst detailRef = useTemplateRef<HTMLDivElement>('detailRef');\nconst activatorRef = useTemplateRef<HTMLInputElement>('activatorRef');\nconst fieldRef = useTemplateRef<HTMLElement>('fieldRef');\nconst isHovered = ref<boolean>(false);\n\nconst { focused } = useFocus(activatorRef);\nconst { hasError, hasSuccess } = useFormTextDetail(() => errorMessages, () => successMessages);\n\nconst baseId = useId();\nconst breakpoints = useBreakpoints(breakpointsTailwind);\n\nfunction resolveCategory(item: TItem): string {\n if (categoryOf)\n return categoryOf(item);\n if (categoryAttr !== undefined)\n return String(item[categoryAttr] ?? '');\n return '';\n}\n\nconst {\n activeCategory,\n detailItems,\n detailRows,\n getIdentifier,\n getText,\n isEmpty,\n isSelected,\n railEntries,\n setActiveCategory,\n syncActiveToSelection,\n} = useCategoryPicker<TValue, TItem>({\n allLabel: () => allLabel,\n categoryOf: resolveCategory,\n filter: () => filter,\n items: () => items,\n keyAttr,\n modelValue,\n search: searchInput,\n searchable: () => searchable,\n showAll: () => showAll,\n textAttr,\n});\n\nconst isMobile = computed<boolean>(() => get(breakpoints.smaller(mobileBreakpoint)));\n\nconst mode = computed<'twoPane' | 'drill'>(() => (get(isMobile) ? 'drill' : 'twoPane'));\n\n/**\n * Desktop anchors an outside-click popover under the field (RuiMenu); narrow\n * width shows a full-width bottom sheet (RuiDialog).\n */\nconst shell = computed<typeof RuiMenu | typeof RuiDialog>(() => (get(isMobile) ? RuiDialog : RuiMenu));\n\n/**\n * The bottom sheet's props. Each shell is given only its own props, so the\n * other component's never leak through as attributes.\n */\nfunction dialogShellProps(): Record<string, unknown> {\n return {\n ariaLabel: dialogOptions?.ariaLabel ?? label,\n bottomSheet: dialogOptions?.bottomSheet ?? true,\n maxWidth: dialogOptions?.maxWidth,\n persistent: dialogOptions?.persistent,\n width: dialogOptions?.width ?? '100%',\n };\n}\n\n/**\n * The popover's props. It anchors to the field box rather than the wrapper, so\n * it sits directly under the input instead of below the reserved details row,\n * and drops the menu's default vertical padding so the popover box equals the\n * panel: the size middleware caps the panel to the available height, and any\n * extra chrome padding would push the popover past the viewport edge.\n */\nfunction menuShellProps(): Record<string, unknown> {\n return {\n anchorEl: get(fieldRef) ?? undefined,\n classNames: { content: 'py-0', menu: 'z-[9999]' },\n closeOnContentClick: false,\n disableAutoFocus: true,\n fullWidth: true,\n options: { placement: Placement.bottomStart, size: true },\n persistent: dialogOptions?.persistent,\n persistOnActivatorClick: true,\n };\n}\n\nconst shellProps = computed<Record<string, unknown>>(() =>\n get(isMobile) ? dialogShellProps() : menuShellProps());\n\nconst ui = computed<ReturnType<typeof categoryPickerStyles>>(() => categoryPickerStyles({\n dense,\n mode: get(mode),\n}));\n\nconst selectedItem = computed<TItem | undefined>(() => {\n const value = get(modelValue);\n if (value === undefined)\n return undefined;\n return items.find(item => getIdentifier(item) === value);\n});\n\nconst selectedText = computed<string | undefined>(() => {\n const selected = get(selectedItem);\n return selected ? getText(selected) : undefined;\n});\n\nconst outlined = computed<boolean>(() => variant === 'outlined');\n\n/**\n * Desktop lets the user type in the field itself (no separate search box);\n * narrow width keeps a read-only trigger that opens the sheet's own search.\n */\nconst canType = computed<boolean>(() => searchable && !get(isMobile) && !readOnly && !disabled);\n\nconst isTyping = computed<boolean>(() => get(isOpen) && get(canType));\n\nconst float = computed<boolean>(() => (get(isOpen) || get(selectedItem) !== undefined || get(focused)) && get(outlined));\n\nconst legendText = computed<string>(() => {\n if (!get(float) || !label)\n return '';\n return required ? `${label} ﹡` : label;\n});\n\n/**\n * Drives both the clear button itself and the room the selection overlay has\n * to leave for it, so the two can never disagree.\n */\nconst showClear = computed<boolean>(() =>\n clearable && get(selectedItem) !== undefined && !disabled && !readOnly);\n\nconst activatorUi = computed<ReturnType<typeof categoryPickerActivatorStyles>>(() => categoryPickerActivatorStyles({\n dense,\n disabled,\n filled: variant === 'filled',\n float: get(float),\n hasError: get(hasError),\n hasSuccess: get(hasSuccess) && !get(hasError),\n hovered: get(isHovered),\n opened: get(isOpen),\n outlined: get(outlined),\n readonly: readOnly,\n withClear: get(showClear),\n}));\n\nconst activeRailIndex = computed<number>(() =>\n get(railEntries).findIndex(entry => entry.category === get(activeCategory)));\n\nconst showRail = computed<boolean>(() => get(mode) === 'twoPane' || get(drillStep) === 'category');\nconst showDetail = computed<boolean>(() => get(mode) === 'twoPane' || get(drillStep) === 'detail');\n\nfunction clamp(value: number, max: number): number {\n if (value < 0)\n return 0;\n if (value > max)\n return max;\n return value;\n}\n\nfunction open(): void {\n if (disabled)\n return;\n set(isOpen, true);\n}\n\nfunction close(): void {\n set(isOpen, false);\n}\n\nfunction onInput(event: Event): void {\n const target = event.target;\n if (!(target instanceof HTMLInputElement))\n return;\n set(searchInput, target.value);\n if (!get(isOpen))\n open();\n}\n\nfunction selectItem(item: TItem): void {\n if (readOnly)\n return;\n set(modelValue, getIdentifier(item));\n emit('select', item);\n close();\n}\n\nfunction clearSelection(): void {\n set(modelValue, undefined);\n}\n\nfunction onCategoryClick(category: string | null): void {\n setActiveCategory(category);\n if (get(mode) === 'drill')\n set(drillStep, 'detail');\n else\n focusPane('detail');\n}\n\n/**\n * Moves focus to one of the panes. The focus call prevents scrolling because\n * the panes sit inside a teleported popover, and without it the browser\n * scrolls the page behind to reveal the pane.\n */\nfunction focusPane(pane: 'rail' | 'detail'): void {\n set(focusedPane, pane);\n nextTick(() => {\n (pane === 'rail' ? get(railRef) : get(detailRef))?.focus({ preventScroll: true });\n });\n}\n\nfunction moveRail(direction: 1 | -1): void {\n const entries = get(railEntries);\n if (entries.length === 0)\n return;\n const next = clamp(get(activeRailIndex) + direction, entries.length - 1);\n setActiveCategory(entries[next]?.category ?? null);\n}\n\nfunction moveItem(direction: 1 | -1): void {\n const total = get(detailItems).length;\n if (total === 0)\n return;\n set(highlightedItemIndex, clamp(get(highlightedItemIndex) + direction, total - 1));\n}\n\nfunction enterDetail(): void {\n if (get(detailItems).length === 0)\n return;\n resetHighlightToSelection();\n if (get(mode) === 'drill')\n set(drillStep, 'detail');\n focusPane('detail');\n}\n\nfunction selectHighlighted(): void {\n const item = get(detailItems)[get(highlightedItemIndex)];\n if (item !== undefined)\n selectItem(item);\n}\n\n/**\n * Enter from the field commits the best match for the current query, so a\n * type-to-pick flow (type a few letters, press Enter) works without leaving\n * the input. Does nothing when the field is empty.\n */\nfunction selectTopResult(): void {\n if (!get(searchInput).trim())\n return;\n const item = get(detailItems)[0];\n if (item !== undefined)\n selectItem(item);\n}\n\nfunction resetHighlightToSelection(): void {\n const index = get(detailItems).findIndex(item => isSelected(item));\n set(highlightedItemIndex, index >= 0 ? index : 0);\n}\n\nfunction backToRail(): void {\n if (get(mode) === 'drill')\n set(drillStep, 'category');\n else\n focusPane('rail');\n}\n\nfunction scrollActiveDescendantIntoView(container: HTMLElement | null, id: string): void {\n if (!container)\n return;\n nextTick(() => {\n container.querySelector(`#${id}`)?.scrollIntoView({ block: 'nearest' });\n });\n}\n\n// Reset the item highlight whenever the active category changes.\nwatch(activeCategory, () => {\n resetHighlightToSelection();\n});\n\nwatch(highlightedItemIndex, (index) => {\n scrollActiveDescendantIntoView(get(detailRef), `${baseId}-opt-${index}`);\n});\n\nwatch(activeRailIndex, (index) => {\n if (index >= 0)\n scrollActiveDescendantIntoView(get(railRef), `${baseId}-cat-${index}`);\n});\n\n/**\n * Opening takes focus where the user types next: desktop is a combobox, so\n * focus stays in the field and ArrowDown moves into the panes, while the\n * mobile sheet has no typing field and focuses the rail instead. Closing\n * resets the query, so the field shows the selection again next time, and\n * returns focus to the trigger, which the APG dialog contract asks for.\n */\nfunction onOpenChanged(value: boolean): void {\n if (value) {\n syncActiveToSelection();\n set(focusedPane, 'rail');\n set(drillStep, 'category');\n resetHighlightToSelection();\n nextTick(() => (get(canType) ? get(activatorRef) : get(railRef))?.focus({ preventScroll: true }));\n }\n else {\n set(searchInput, '');\n nextTick(() => get(activatorRef)?.focus({ preventScroll: true }));\n }\n}\n\nwatch(isOpen, onOpenChanged);\n</script>\n\n<template>\n <component\n :is=\"shell\"\n v-model=\"isOpen\"\n v-bind=\"{ ...$attrs, ...shellProps }\"\n >\n <template #activator=\"{ attrs }\">\n <slot\n name=\"activator\"\n v-bind=\"{ attrs, isOpen, item: selectedItem, open, text: selectedText }\"\n >\n <div :class=\"activatorUi.wrapper()\">\n <div\n ref=\"fieldRef\"\n role=\"combobox\"\n data-id=\"activator\"\n :class=\"activatorUi.activator()\"\n aria-haspopup=\"dialog\"\n :aria-controls=\"isOpen ? `${baseId}-panel` : undefined\"\n :aria-expanded=\"isOpen\"\n :aria-disabled=\"disabled || undefined\"\n :aria-readonly=\"(readOnly || !canType) || undefined\"\n :aria-required=\"required || undefined\"\n :aria-invalid=\"hasError || undefined\"\n :aria-busy=\"loading || undefined\"\n v-bind=\"readOnly ? {} : attrs\"\n @mouseenter=\"isHovered = true\"\n @mouseleave=\"isHovered = false\"\n >\n <span\n v-if=\"outlined || (!selectedItem && !isTyping)\"\n :class=\"activatorUi.label()\"\n >\n <slot\n name=\"activator.label\"\n v-bind=\"{ item: selectedItem }\"\n >\n {{ label }}\n </slot>\n <span\n v-if=\"required\"\n :class=\"activatorUi.required()\"\n >\n ﹡\n </span>\n </span>\n <span\n v-if=\"selectedItem && !isTyping && $slots.selection\"\n data-id=\"selection\"\n :class=\"activatorUi.selection()\"\n >\n <slot\n name=\"selection.prepend\"\n v-bind=\"{ item: selectedItem }\"\n />\n <slot\n name=\"selection\"\n v-bind=\"{ item: selectedItem }\"\n />\n </span>\n <input\n ref=\"activatorRef\"\n data-id=\"search-input\"\n :value=\"isTyping ? searchInput : (($slots.selection && selectedItem) ? '' : (selectedText ?? ''))\"\n :placeholder=\"isTyping ? placeholder : ''\"\n :readonly=\"!canType\"\n :disabled=\"disabled\"\n :aria-invalid=\"hasError || undefined\"\n class=\"bg-transparent outline-none\"\n :class=\"[activatorUi.value(), !canType && 'cursor-pointer']\"\n @input=\"onInput($event)\"\n @keydown.down.prevent=\"focusPane('rail')\"\n @keydown.enter.prevent=\"selectTopResult()\"\n @keydown.esc=\"close()\"\n />\n <span\n v-if=\"showClear\"\n data-id=\"clear\"\n :class=\"[activatorUi.clear(), focused && '!visible', { 'mr-2': !dense }]\"\n @click.stop.prevent=\"clearSelection()\"\n >\n <RuiIcon\n color=\"error\"\n name=\"lu-x\"\n size=\"18\"\n />\n </span>\n <span\n data-id=\"chevron\"\n :class=\"activatorUi.iconWrapper()\"\n >\n <RuiIcon\n :class=\"activatorUi.icon()\"\n :size=\"dense ? 16 : 24\"\n name=\"lu-chevron-down\"\n />\n </span>\n <RuiProgress\n v-if=\"loading\"\n :class=\"activatorUi.progress()\"\n color=\"primary\"\n thickness=\"3\"\n variant=\"indeterminate\"\n />\n <fieldset\n v-if=\"outlined\"\n :class=\"activatorUi.fieldset()\"\n >\n <legend :class=\"activatorUi.legend()\">\n {{ legendText }}\n </legend>\n </fieldset>\n </div>\n <RuiFormTextDetail\n v-if=\"!hideDetails\"\n class=\"px-3 pt-1\"\n :error-messages=\"errorMessages\"\n :success-messages=\"successMessages\"\n :hint=\"hint\"\n />\n </div>\n </slot>\n </template>\n\n <div\n :id=\"`${baseId}-panel`\"\n :class=\"ui.root({ class: cn(classNames?.root) })\"\n data-id=\"panel\"\n >\n <!-- On desktop the field itself is the search input, so the panel only\n needs its own search box in the mobile sheet. -->\n <div\n v-if=\"isMobile || $slots.header\"\n :class=\"ui.header()\"\n >\n <slot name=\"header\">\n <div :class=\"ui.title()\">\n {{ label }}\n </div>\n </slot>\n <RuiTextField\n v-if=\"searchable && isMobile\"\n v-model=\"searchInput\"\n :class=\"cn(classNames?.search)\"\n :placeholder=\"placeholder\"\n :dense=\"dense\"\n variant=\"outlined\"\n prepend-icon=\"lu-search\"\n hide-details\n clearable\n data-id=\"search\"\n />\n </div>\n\n <div :class=\"ui.body()\">\n <!-- Category rail (master) -->\n <div\n v-show=\"showRail\"\n ref=\"railRef\"\n :class=\"ui.rail({ class: cn(classNames?.rail) })\"\n role=\"tablist\"\n aria-orientation=\"vertical\"\n :aria-label=\"label\"\n :aria-activedescendant=\"focusedPane === 'rail' && activeRailIndex >= 0 ? `${baseId}-cat-${activeRailIndex}` : undefined\"\n tabindex=\"0\"\n data-id=\"rail\"\n @focus=\"focusedPane = 'rail'\"\n @keydown.down.prevent=\"moveRail(1)\"\n @keydown.up.prevent=\"moveRail(-1)\"\n @keydown.right.prevent=\"enterDetail()\"\n @keydown.enter.prevent=\"enterDetail()\"\n @keydown.home.prevent=\"setActiveCategory(railEntries[0]?.category ?? null)\"\n @keydown.end.prevent=\"setActiveCategory(railEntries[railEntries.length - 1]?.category ?? null)\"\n >\n <RuiButton\n v-for=\"(entry, index) in railEntries\"\n :id=\"`${baseId}-cat-${index}`\"\n :key=\"entry.category ?? '__all__'\"\n role=\"tab\"\n variant=\"list\"\n :size=\"dense ? 'sm' : undefined\"\n :active=\"entry.category === activeCategory\"\n :aria-selected=\"entry.category === activeCategory\"\n tabindex=\"-1\"\n :data-highlighted=\"focusedPane === 'rail' && index === activeRailIndex\"\n :data-category=\"entry.category ?? '__all__'\"\n @click=\"onCategoryClick(entry.category)\"\n >\n <slot\n name=\"category\"\n v-bind=\"{ active: entry.category === activeCategory, category: entry.category, count: entry.count, label: entry.label }\"\n >\n <span class=\"truncate\">{{ entry.label }}</span>\n <span :class=\"ui.railCount()\">{{ entry.count }}</span>\n </slot>\n </RuiButton>\n </div>\n\n <!-- Detail pane -->\n <div\n v-show=\"showDetail\"\n ref=\"detailRef\"\n :class=\"ui.detail({ class: cn(classNames?.detail) })\"\n role=\"listbox\"\n :aria-label=\"activeCategory ?? allLabel\"\n :aria-activedescendant=\"focusedPane === 'detail' && !isEmpty ? `${baseId}-opt-${highlightedItemIndex}` : undefined\"\n tabindex=\"0\"\n data-id=\"detail\"\n @focus=\"focusedPane = 'detail'\"\n @keydown.down.prevent=\"moveItem(1)\"\n @keydown.up.prevent=\"moveItem(-1)\"\n @keydown.left.prevent=\"backToRail()\"\n @keydown.home.prevent=\"highlightedItemIndex = 0\"\n @keydown.end.prevent=\"highlightedItemIndex = detailItems.length - 1\"\n @keydown.enter.prevent=\"selectHighlighted()\"\n @keydown.space.prevent=\"selectHighlighted()\"\n >\n <template v-if=\"mode === 'drill' && showDetail\">\n <button\n type=\"button\"\n :class=\"ui.backButton()\"\n data-id=\"back\"\n @click=\"backToRail()\"\n >\n <RuiIcon\n name=\"lu-chevron-left\"\n size=\"18\"\n />\n <span>{{ activeCategory ?? allLabel }}</span>\n </button>\n </template>\n\n <slot\n v-if=\"isEmpty\"\n name=\"empty\"\n >\n <div :class=\"ui.empty()\">\n {{ emptyText }}\n </div>\n </slot>\n\n <template\n v-for=\"row in detailRows\"\n v-else\n :key=\"row.type === 'header' ? `h-${row.category}` : `i-${row.index}`\"\n >\n <div\n v-if=\"row.type === 'header'\"\n :class=\"ui.subheader()\"\n role=\"presentation\"\n >\n {{ row.category }}\n </div>\n <RuiButton\n v-else\n :id=\"`${baseId}-opt-${row.index}`\"\n role=\"option\"\n variant=\"list\"\n :size=\"dense ? 'sm' : undefined\"\n :active=\"isSelected(row.item)\"\n :aria-selected=\"isSelected(row.item)\"\n tabindex=\"-1\"\n :data-highlighted=\"focusedPane === 'detail' && row.index === highlightedItemIndex\"\n :class=\"{ [ui.highlighted()]: focusedPane === 'detail' && row.index === highlightedItemIndex && !isSelected(row.item) }\"\n @click=\"selectItem(row.item)\"\n >\n <template\n v-if=\"$slots['item.prepend']\"\n #prepend\n >\n <slot\n name=\"item.prepend\"\n v-bind=\"{ active: row.index === highlightedItemIndex, item: row.item, selected: isSelected(row.item) }\"\n />\n </template>\n <slot\n name=\"item\"\n v-bind=\"{ active: row.index === highlightedItemIndex, item: row.item, selected: isSelected(row.item) }\"\n >\n {{ getText(row.item) }}\n </slot>\n <template\n v-if=\"$slots['item.append']\"\n #append\n >\n <slot\n name=\"item.append\"\n v-bind=\"{ active: row.index === highlightedItemIndex, item: row.item, selected: isSelected(row.item) }\"\n />\n </template>\n </RuiButton>\n </template>\n </div>\n </div>\n\n <div\n v-if=\"$slots.footer\"\n :class=\"ui.footer()\"\n >\n <slot\n name=\"footer\"\n v-bind=\"{ close }\"\n />\n </div>\n </div>\n </component>\n</template>\n"],"mappings":"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"}
|
|
@@ -1,9 +1,23 @@
|
|
|
1
|
-
import { type TextInputVariant } from '
|
|
1
|
+
import { type TextInputVariant } from '../text-input-styles.js';
|
|
2
2
|
export type CategoryPickerVariant = TextInputVariant;
|
|
3
3
|
/**
|
|
4
4
|
* Form-field trigger, shared with `RuiAutoComplete` / `RuiMenuSelect` via
|
|
5
5
|
* `activatorStyles`: floating label, outlined/filled/underline variants,
|
|
6
6
|
* error + hint details, required marker.
|
|
7
|
+
*
|
|
8
|
+
* The `selection` slot draws over the emptied input, so it is positioned
|
|
9
|
+
* rather than laid out: `inset-y-0 left-4` lines it up with the field's own
|
|
10
|
+
* `pl-4` text box, and the right offset reserves the trailing controls. It
|
|
11
|
+
* must not take the `value` slot's `w-full`, because a width of 100% beats the
|
|
12
|
+
* right offset and leaves the layer a full field width shifted right by
|
|
13
|
+
* `left-4`, overflowing the field and covering the chevron it meant to clear
|
|
14
|
+
* (rotki/ui-library#559).
|
|
15
|
+
*
|
|
16
|
+
* Those right offsets come from the controls: the chevron sits at `right-3`
|
|
17
|
+
* and is 24px wide, reaching 36px in, which `right-10` clears; the clear
|
|
18
|
+
* button ends at the activator's `pr-8` padding edge plus its own `mr-2`, so
|
|
19
|
+
* its 18px icon reaches 58px in, which `right-16` clears. Right-aligned
|
|
20
|
+
* selection content then lands just left of whichever control is showing.
|
|
7
21
|
*/
|
|
8
22
|
export declare const categoryPickerActivatorStyles: import("tailwind-variants").TVReturnType<{
|
|
9
23
|
filled: {
|
|
@@ -74,6 +88,47 @@ export declare const categoryPickerActivatorStyles: import("tailwind-variants").
|
|
|
74
88
|
hovered: {
|
|
75
89
|
true: {};
|
|
76
90
|
};
|
|
91
|
+
} & {
|
|
92
|
+
focused: {
|
|
93
|
+
true: {
|
|
94
|
+
fieldset: string;
|
|
95
|
+
};
|
|
96
|
+
};
|
|
97
|
+
hovered: {
|
|
98
|
+
true: {
|
|
99
|
+
fieldset: string;
|
|
100
|
+
};
|
|
101
|
+
};
|
|
102
|
+
disabled: {
|
|
103
|
+
true: {
|
|
104
|
+
fieldset: string;
|
|
105
|
+
label: string;
|
|
106
|
+
};
|
|
107
|
+
};
|
|
108
|
+
active: {
|
|
109
|
+
true: {};
|
|
110
|
+
};
|
|
111
|
+
showLabel: {
|
|
112
|
+
true: {};
|
|
113
|
+
};
|
|
114
|
+
validation: {
|
|
115
|
+
error: {
|
|
116
|
+
fieldset: string;
|
|
117
|
+
label: string;
|
|
118
|
+
};
|
|
119
|
+
success: {
|
|
120
|
+
fieldset: string;
|
|
121
|
+
label: string;
|
|
122
|
+
};
|
|
123
|
+
};
|
|
124
|
+
color: {
|
|
125
|
+
primary: {};
|
|
126
|
+
secondary: {};
|
|
127
|
+
error: {};
|
|
128
|
+
warning: {};
|
|
129
|
+
info: {};
|
|
130
|
+
success: {};
|
|
131
|
+
};
|
|
77
132
|
}, {
|
|
78
133
|
fieldset: string;
|
|
79
134
|
legend: string;
|
|
@@ -88,6 +143,10 @@ export declare const categoryPickerActivatorStyles: import("tailwind-variants").
|
|
|
88
143
|
icon: string;
|
|
89
144
|
iconWrapper: string;
|
|
90
145
|
required: string;
|
|
146
|
+
} & {
|
|
147
|
+
label: string;
|
|
148
|
+
fieldset: string;
|
|
149
|
+
legend: string;
|
|
91
150
|
}, import("tailwind-variants").TVReturnType<{
|
|
92
151
|
dense: {
|
|
93
152
|
true: {
|
|
@@ -292,7 +351,7 @@ export declare const categoryPickerActivatorStyles: import("tailwind-variants").
|
|
|
292
351
|
label: string;
|
|
293
352
|
fieldset: string;
|
|
294
353
|
legend: string;
|
|
295
|
-
}, import("tailwind-variants").
|
|
354
|
+
}, import("tailwind-variants").TVReturnTypeLike<{
|
|
296
355
|
focused: {
|
|
297
356
|
true: {
|
|
298
357
|
fieldset: string;
|
|
@@ -337,11 +396,16 @@ export declare const categoryPickerActivatorStyles: import("tailwind-variants").
|
|
|
337
396
|
label: string;
|
|
338
397
|
fieldset: string;
|
|
339
398
|
legend: string;
|
|
340
|
-
}
|
|
399
|
+
}>>>>;
|
|
341
400
|
/**
|
|
342
401
|
* Layout styles for `RuiCategoryPicker`. Item and category rows lean on
|
|
343
402
|
* `RuiButton variant="list"` for their interactive/active visuals; these slots
|
|
344
403
|
* cover only the surrounding two-pane (and mobile drill-in) scaffold.
|
|
404
|
+
*
|
|
405
|
+
* The panel caps itself to the space the floating layer measured toward the
|
|
406
|
+
* viewport edge, which the menu's size middleware sets as
|
|
407
|
+
* `--rui-floating-max-height`, falling back to 60vh. The body flex-shrinks
|
|
408
|
+
* within that, so the footer stays put.
|
|
345
409
|
*/
|
|
346
410
|
export declare const categoryPickerStyles: import("tailwind-variants").TVReturnType<{
|
|
347
411
|
mode: {
|
|
@@ -407,7 +471,7 @@ export declare const categoryPickerStyles: import("tailwind-variants").TVReturnT
|
|
|
407
471
|
empty: string;
|
|
408
472
|
footer: string;
|
|
409
473
|
backButton: string;
|
|
410
|
-
}, import("tailwind-variants").
|
|
474
|
+
}, import("tailwind-variants").TVReturnTypeLike<{
|
|
411
475
|
mode: {
|
|
412
476
|
twoPane: {
|
|
413
477
|
root: string;
|
|
@@ -439,4 +503,4 @@ export declare const categoryPickerStyles: import("tailwind-variants").TVReturnT
|
|
|
439
503
|
empty: string;
|
|
440
504
|
footer: string;
|
|
441
505
|
backButton: string;
|
|
442
|
-
}
|
|
506
|
+
}>>;
|
|
@@ -5,6 +5,20 @@ import { activatorStyles } from "../text-input-styles.js";
|
|
|
5
5
|
* Form-field trigger, shared with `RuiAutoComplete` / `RuiMenuSelect` via
|
|
6
6
|
* `activatorStyles`: floating label, outlined/filled/underline variants,
|
|
7
7
|
* error + hint details, required marker.
|
|
8
|
+
*
|
|
9
|
+
* The `selection` slot draws over the emptied input, so it is positioned
|
|
10
|
+
* rather than laid out: `inset-y-0 left-4` lines it up with the field's own
|
|
11
|
+
* `pl-4` text box, and the right offset reserves the trailing controls. It
|
|
12
|
+
* must not take the `value` slot's `w-full`, because a width of 100% beats the
|
|
13
|
+
* right offset and leaves the layer a full field width shifted right by
|
|
14
|
+
* `left-4`, overflowing the field and covering the chevron it meant to clear
|
|
15
|
+
* (rotki/ui-library#559).
|
|
16
|
+
*
|
|
17
|
+
* Those right offsets come from the controls: the chevron sits at `right-3`
|
|
18
|
+
* and is 24px wide, reaching 36px in, which `right-10` clears; the clear
|
|
19
|
+
* button ends at the activator's `pr-8` padding edge plus its own `mr-2`, so
|
|
20
|
+
* its 18px icon reaches 58px in, which `right-16` clears. Right-aligned
|
|
21
|
+
* selection content then lands just left of whichever control is showing.
|
|
8
22
|
*/
|
|
9
23
|
var categoryPickerActivatorStyles = tv({
|
|
10
24
|
extend: activatorStyles,
|
|
@@ -22,6 +36,11 @@ var categoryPickerActivatorStyles = tv({
|
|
|
22
36
|
* Layout styles for `RuiCategoryPicker`. Item and category rows lean on
|
|
23
37
|
* `RuiButton variant="list"` for their interactive/active visuals; these slots
|
|
24
38
|
* cover only the surrounding two-pane (and mobile drill-in) scaffold.
|
|
39
|
+
*
|
|
40
|
+
* The panel caps itself to the space the floating layer measured toward the
|
|
41
|
+
* viewport edge, which the menu's size middleware sets as
|
|
42
|
+
* `--rui-floating-max-height`, falling back to 60vh. The body flex-shrinks
|
|
43
|
+
* within that, so the footer stays put.
|
|
25
44
|
*/
|
|
26
45
|
var categoryPickerStyles = tv({
|
|
27
46
|
slots: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"category-picker-styles.js","names":[],"sources":["../../../../src/components/forms/category-picker/category-picker-styles.ts"],"sourcesContent":["import { activatorStyles, type TextInputVariant } from '@/components/forms/text-input-styles';\nimport { tv } from '@/utils/tv';\n\nexport type CategoryPickerVariant = TextInputVariant;\n\n/**\n * Form-field trigger, shared with `RuiAutoComplete` / `RuiMenuSelect` via\n * `activatorStyles`: floating label, outlined/filled/underline variants,\n * error + hint details, required marker.\n
|
|
1
|
+
{"version":3,"file":"category-picker-styles.js","names":[],"sources":["../../../../src/components/forms/category-picker/category-picker-styles.ts"],"sourcesContent":["import { activatorStyles, type TextInputVariant } from '@/components/forms/text-input-styles';\nimport { tv } from '@/utils/tv';\n\nexport type CategoryPickerVariant = TextInputVariant;\n\n/**\n * Form-field trigger, shared with `RuiAutoComplete` / `RuiMenuSelect` via\n * `activatorStyles`: floating label, outlined/filled/underline variants,\n * error + hint details, required marker.\n *\n * The `selection` slot draws over the emptied input, so it is positioned\n * rather than laid out: `inset-y-0 left-4` lines it up with the field's own\n * `pl-4` text box, and the right offset reserves the trailing controls. It\n * must not take the `value` slot's `w-full`, because a width of 100% beats the\n * right offset and leaves the layer a full field width shifted right by\n * `left-4`, overflowing the field and covering the chevron it meant to clear\n * (rotki/ui-library#559).\n *\n * Those right offsets come from the controls: the chevron sits at `right-3`\n * and is 24px wide, reaching 36px in, which `right-10` clears; the clear\n * button ends at the activator's `pr-8` padding edge plus its own `mr-2`, so\n * its 18px icon reaches 58px in, which `right-16` clears. Right-aligned\n * selection content then lands just left of whichever control is showing.\n */\nexport const categoryPickerActivatorStyles = tv({\n extend: activatorStyles,\n slots: {\n selection: 'absolute inset-y-0 left-4 flex items-center gap-2 pointer-events-none truncate transition-all duration-75',\n },\n variants: {\n // Re-declared for type inference; the styles themselves live in activatorStyles\n filled: { true: {} },\n withClear: {\n false: { selection: 'right-10' },\n true: { selection: 'right-16' },\n },\n },\n defaultVariants: {\n withClear: false,\n },\n});\n\n/**\n * Layout styles for `RuiCategoryPicker`. Item and category rows lean on\n * `RuiButton variant=\"list\"` for their interactive/active visuals; these slots\n * cover only the surrounding two-pane (and mobile drill-in) scaffold.\n *\n * The panel caps itself to the space the floating layer measured toward the\n * viewport edge, which the menu's size middleware sets as\n * `--rui-floating-max-height`, falling back to 60vh. The body flex-shrinks\n * within that, so the footer stays put.\n */\nexport const categoryPickerStyles = tv({\n slots: {\n root: 'flex flex-col min-w-0 max-h-[var(--rui-floating-max-height,60vh)] bg-white dark:bg-rui-grey-900 rounded-md overflow-hidden',\n header: 'flex flex-col gap-3 p-4 border-b border-rui-grey-200 dark:border-rui-grey-800',\n title: 'text-h6 text-rui-text',\n body: 'grid min-h-0 flex-1',\n rail: 'flex flex-col gap-0.5 p-2 overflow-y-auto outline-none border-rui-grey-200 dark:border-rui-grey-800',\n railCount: 'ml-auto pl-2 text-caption tabular-nums text-rui-text-secondary',\n detail: 'flex flex-col gap-0.5 p-2 overflow-y-auto outline-none min-w-0',\n // Focus lives on the pane container, so this is the only per-item focus cue\n highlighted: '!bg-rui-grey-100 dark:!bg-rui-grey-800',\n subheader: 'px-3 pt-3 pb-1 text-overline text-rui-text-secondary uppercase',\n empty: 'flex flex-1 items-center justify-center p-8 text-body-2 text-rui-text-secondary text-center',\n // Opaque panel surface so a scrolled pane never bleeds through the footer.\n footer: 'shrink-0 p-3 border-t border-rui-grey-200 dark:border-rui-grey-800 bg-white dark:bg-rui-grey-900',\n backButton: 'flex items-center gap-2',\n },\n variants: {\n mode: {\n // Rail beside the detail pane in an anchored popover; the explicit width lets the `1fr` detail column resolve\n twoPane: {\n root: 'w-[40rem] max-w-[calc(100vw-2rem)]',\n body: 'grid-cols-[minmax(9.5rem,13rem)_1fr]',\n rail: 'border-r',\n },\n // One column at a time, drilled in and back out, inside a full-width bottom sheet\n drill: {\n root: 'w-full',\n body: 'grid-cols-1',\n rail: 'border-r-0',\n },\n },\n dense: {\n true: {\n header: 'p-3',\n title: 'text-subtitle-1',\n },\n },\n },\n defaultVariants: {\n mode: 'twoPane',\n dense: false,\n },\n});\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAwBA,IAAa,gCAAgC,GAAG;CAC9C,QAAQ;CACR,OAAO,EACL,WAAW,4GACb;CACA,UAAU;EAER,QAAQ,EAAE,MAAM,CAAC,EAAE;EACnB,WAAW;GACT,OAAO,EAAE,WAAW,WAAW;GAC/B,MAAM,EAAE,WAAW,WAAW;EAChC;CACF;CACA,iBAAiB,EACf,WAAW,MACb;AACF,CAAC;;;;;;;;;;;AAYD,IAAa,uBAAuB,GAAG;CACrC,OAAO;EACL,MAAM;EACN,QAAQ;EACR,OAAO;EACP,MAAM;EACN,MAAM;EACN,WAAW;EACX,QAAQ;EAER,aAAa;EACb,WAAW;EACX,OAAO;EAEP,QAAQ;EACR,YAAY;CACd;CACA,UAAU;EACR,MAAM;GAEJ,SAAS;IACP,MAAM;IACN,MAAM;IACN,MAAM;GACR;GAEA,OAAO;IACL,MAAM;IACN,MAAM;IACN,MAAM;GACR;EACF;EACA,OAAO,EACL,MAAM;GACJ,QAAQ;GACR,OAAO;EACT,EACF;CACF;CACA,iBAAiB;EACf,MAAM;EACN,OAAO;CACT;AACF,CAAC"}
|
|
@@ -89,7 +89,7 @@ export declare const checkControlStyles: import("tailwind-variants").TVReturnTyp
|
|
|
89
89
|
input: string;
|
|
90
90
|
control: string;
|
|
91
91
|
label: string;
|
|
92
|
-
}, import("tailwind-variants").
|
|
92
|
+
}, import("tailwind-variants").TVReturnTypeLike<{
|
|
93
93
|
size: {
|
|
94
94
|
sm: {
|
|
95
95
|
control: string;
|
|
@@ -132,4 +132,4 @@ export declare const checkControlStyles: import("tailwind-variants").TVReturnTyp
|
|
|
132
132
|
input: string;
|
|
133
133
|
control: string;
|
|
134
134
|
label: string;
|
|
135
|
-
}
|
|
135
|
+
}>>;
|
package/dist/components/forms/checkbox/RuiCheckbox.vue_vue_type_script_setup_true_lang.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RuiCheckbox.vue_vue_type_script_setup_true_lang.js","names":["$attrs","$slots"],"sources":["../../../../src/components/forms/checkbox/RuiCheckbox.vue"],"sourcesContent":["<script lang=\"ts\" setup generic=\"TValue\">\nimport type { ContextColorsType } from '@/consts/colors';\nimport { objectPick } from '@vueuse/shared';\nimport { checkControlStyles, getCheckControlIconSize } from '@/components/forms/check-control-styles';\nimport { RuiCheckboxGroupContextKey } from '@/components/forms/checkbox/checkbox-group/context';\nimport RuiFormTextDetail from '@/components/helpers/RuiFormTextDetail.vue';\nimport RuiIcon from '@/components/icons/RuiIcon.vue';\nimport { useFormTextDetail } from '@/utils/form-text-detail';\nimport { getNonRootAttrs, getRootAttrs } from '@/utils/helpers';\n\nexport interface Props<TValue> {\n value?: TValue;\n disabled?: boolean;\n color?: ContextColorsType;\n size?: 'sm' | 'lg';\n label?: string;\n hint?: string;\n errorMessages?: string | string[];\n successMessages?: string | string[];\n hideDetails?: boolean;\n required?: boolean;\n}\n\ndefineOptions({\n name: 'RuiCheckbox',\n inheritAttrs: false,\n});\n\nconst modelValue = defineModel<boolean>({ default: false });\n\nconst indeterminate = defineModel<boolean>('indeterminate', { default: false });\n\nconst {\n value = undefined,\n disabled: disabledProp = false,\n color: colorProp = undefined,\n size: sizeProp = undefined,\n label = '',\n hint = '',\n errorMessages = [],\n successMessages = [],\n hideDetails = false,\n required = false,\n} = defineProps<Props<TValue>>();\n\ndefineSlots<{\n default?: () => any;\n}>();\n\nconst el = useTemplateRef<HTMLInputElement>('el');\n\nconst group = inject(RuiCheckboxGroupContextKey, undefined);\n\nconst disabled = computed<boolean>(() => disabledProp || (group ? toValue(group.disabled) : false));\nconst color = computed<ContextColorsType | undefined>(() => colorProp ?? (group ? toValue(group.color) : undefined));\nconst size = computed<'sm' | 'lg' | undefined>(() => sizeProp ?? (group ? toValue(group.size) : undefined));\n// Suppress per-child details inside a group so the group's own hint/error wins.\nconst effectiveHideDetails = computed<boolean>(() => hideDetails || (group !== undefined && value !== undefined));\n\nconst { hasError, validation } = useFormTextDetail(\n () => errorMessages,\n () => successMessages,\n);\n\nconst internalModelValue = computed<boolean>({\n get: () => {\n if (group && value !== undefined)\n return group.isChecked(value);\n return get(modelValue);\n },\n set: (checked: boolean) => {\n if (checked)\n set(indeterminate, false);\n if (group && value !== undefined)\n group.toggle(value, checked);\n else\n set(modelValue, checked);\n },\n});\n\nconst ui = computed<ReturnType<typeof checkControlStyles>>(() => checkControlStyles({\n size: get(size),\n disabled: get(disabled),\n checked: get(internalModelValue) || get(indeterminate),\n validation: get(validation),\n color: get(color),\n}));\n\nconst iconSize = computed<number>(() => getCheckControlIconSize(get(size)));\n\nwatch(indeterminate, (val) => {\n const input = get(el);\n if (!input) {\n return;\n }\n input.checked = !val;\n input.value = val ? 'off' : 'on';\n});\n\nwatch(internalModelValue, (val) => {\n const input = get(el);\n if (input && input.checked !== val)\n input.checked = val;\n});\n</script>\n\n<template>\n <div v-bind=\"getRootAttrs($attrs)\">\n <label\n :class=\"ui.wrapper()\"\n v-bind=\"objectPick($attrs, ['onClick'])\"\n :data-disabled=\"disabled || undefined\"\n :data-checked=\"internalModelValue || indeterminate || undefined\"\n :data-error=\"hasError ? '' : undefined\"\n >\n <input\n ref=\"el\"\n v-model=\"internalModelValue\"\n type=\"checkbox\"\n :class=\"ui.input()\"\n :disabled=\"disabled\"\n :aria-invalid=\"hasError\"\n v-bind=\"getNonRootAttrs($attrs, ['onInput', 'onClick'])\"\n />\n <span :class=\"ui.control()\">\n <RuiIcon\n v-if=\"indeterminate\"\n name=\"lu-checkbox-indeterminate-fill\"\n :size=\"iconSize\"\n />\n <RuiIcon\n v-else-if=\"internalModelValue\"\n name=\"lu-checkbox-fill\"\n :size=\"iconSize\"\n />\n <RuiIcon\n v-else\n name=\"lu-checkbox-blank\"\n :size=\"iconSize\"\n />\n </span>\n <span\n v-if=\"label || $slots.default\"\n :class=\"ui.label()\"\n >\n <slot>{{ label }}</slot>\n <span\n v-if=\"required\"\n class=\"text-rui-error\"\n >\n ﹡\n </span>\n </span>\n </label>\n <RuiFormTextDetail\n v-if=\"!effectiveHideDetails\"\n :error-messages=\"errorMessages\"\n :success-messages=\"successMessages\"\n :hint=\"hint\"\n />\n </div>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA4BA,MAAM,aAAa,SAAoB,SAAA,YAAmB;EAE1D,MAAM,gBAAgB,SAAoB,SAAC,eAAmC;EAmB9E,MAAM,KAAK,eAAiC,IAAI;EAEhD,MAAM,QAAQ,OAAO,4BAA4B,KAAA,CAAS;EAE1D,MAAM,WAAW,eAAwB,QAAA,aAAiB,QAAQ,QAAQ,MAAM,QAAQ,IAAI,MAAM;EAClG,MAAM,QAAQ,eAA8C,QAAA,UAAc,QAAQ,QAAQ,MAAM,KAAK,IAAI,KAAA,EAAU;EACnH,MAAM,OAAO,eAAwC,QAAA,SAAa,QAAQ,QAAQ,MAAM,IAAI,IAAI,KAAA,EAAU;EAE1G,MAAM,uBAAuB,eAAwB,QAAA,eAAgB,UAAU,KAAA,KAAa,QAAA,UAAU,KAAA,CAAU;EAEhH,MAAM,EAAE,UAAU,eAAe,wBACzB,QAAA,qBACA,QAAA,eACR;EAEA,MAAM,qBAAqB,SAAkB;GAC3C,WAAW;IACT,IAAI,SAAS,QAAA,UAAU,KAAA,GACrB,OAAO,MAAM,UAAU,QAAA,KAAK;IAC9B,OAAO,IAAI,UAAU;GACvB;GACA,MAAM,YAAqB;IACzB,IAAI,SACF,IAAI,eAAe,KAAK;IAC1B,IAAI,SAAS,QAAA,UAAU,KAAA,GACrB,MAAM,OAAO,QAAA,OAAO,OAAO;SAE3B,IAAI,YAAY,OAAO;GAC3B;EACF,CAAC;EAED,MAAM,KAAK,eAAsD,mBAAmB;GAClF,MAAM,IAAI,IAAI;GACd,UAAU,IAAI,QAAQ;GACtB,SAAS,IAAI,kBAAkB,KAAK,IAAI,aAAa;GACrD,YAAY,IAAI,UAAU;GAC1B,OAAO,IAAI,KAAK;EAClB,CAAC,CAAC;EAEF,MAAM,WAAW,eAAuB,wBAAwB,IAAI,IAAI,CAAC,CAAC;EAE1E,MAAM,gBAAgB,QAAQ;GAC5B,MAAM,QAAQ,IAAI,EAAE;GACpB,IAAI,CAAC,OACH;GAEF,MAAM,UAAU,CAAC;GACjB,MAAM,QAAQ,MAAM,QAAQ;EAC9B,CAAC;EAED,MAAM,qBAAqB,QAAQ;GACjC,MAAM,QAAQ,IAAI,EAAE;GACpB,IAAI,SAAS,MAAM,YAAY,KAC7B,MAAM,UAAU;EACpB,CAAC;;
|
|
1
|
+
{"version":3,"file":"RuiCheckbox.vue_vue_type_script_setup_true_lang.js","names":["$attrs","$slots"],"sources":["../../../../src/components/forms/checkbox/RuiCheckbox.vue"],"sourcesContent":["<script lang=\"ts\" setup generic=\"TValue\">\nimport type { ContextColorsType } from '@/consts/colors';\nimport { objectPick } from '@vueuse/shared';\nimport { checkControlStyles, getCheckControlIconSize } from '@/components/forms/check-control-styles';\nimport { RuiCheckboxGroupContextKey } from '@/components/forms/checkbox/checkbox-group/context';\nimport RuiFormTextDetail from '@/components/helpers/RuiFormTextDetail.vue';\nimport RuiIcon from '@/components/icons/RuiIcon.vue';\nimport { useFormTextDetail } from '@/utils/form-text-detail';\nimport { getNonRootAttrs, getRootAttrs } from '@/utils/helpers';\n\nexport interface Props<TValue> {\n value?: TValue;\n disabled?: boolean;\n color?: ContextColorsType;\n size?: 'sm' | 'lg';\n label?: string;\n hint?: string;\n errorMessages?: string | string[];\n successMessages?: string | string[];\n hideDetails?: boolean;\n required?: boolean;\n}\n\ndefineOptions({\n name: 'RuiCheckbox',\n inheritAttrs: false,\n});\n\nconst modelValue = defineModel<boolean>({ default: false });\n\nconst indeterminate = defineModel<boolean>('indeterminate', { default: false });\n\nconst {\n value = undefined,\n disabled: disabledProp = false,\n color: colorProp = undefined,\n size: sizeProp = undefined,\n label = '',\n hint = '',\n errorMessages = [],\n successMessages = [],\n hideDetails = false,\n required = false,\n} = defineProps<Props<TValue>>();\n\ndefineSlots<{\n default?: () => any;\n}>();\n\nconst el = useTemplateRef<HTMLInputElement>('el');\n\nconst group = inject(RuiCheckboxGroupContextKey, undefined);\n\nconst disabled = computed<boolean>(() => disabledProp || (group ? toValue(group.disabled) : false));\nconst color = computed<ContextColorsType | undefined>(() => colorProp ?? (group ? toValue(group.color) : undefined));\nconst size = computed<'sm' | 'lg' | undefined>(() => sizeProp ?? (group ? toValue(group.size) : undefined));\n// Suppress per-child details inside a group so the group's own hint/error wins.\nconst effectiveHideDetails = computed<boolean>(() => hideDetails || (group !== undefined && value !== undefined));\n\nconst { hasError, validation } = useFormTextDetail(\n () => errorMessages,\n () => successMessages,\n);\n\nconst internalModelValue = computed<boolean>({\n get: () => {\n if (group && value !== undefined)\n return group.isChecked(value);\n return get(modelValue);\n },\n set: (checked: boolean) => {\n if (checked)\n set(indeterminate, false);\n if (group && value !== undefined)\n group.toggle(value, checked);\n else\n set(modelValue, checked);\n },\n});\n\nconst ui = computed<ReturnType<typeof checkControlStyles>>(() => checkControlStyles({\n size: get(size),\n disabled: get(disabled),\n checked: get(internalModelValue) || get(indeterminate),\n validation: get(validation),\n color: get(color),\n}));\n\nconst iconSize = computed<number>(() => getCheckControlIconSize(get(size)));\n\nwatch(indeterminate, (val) => {\n const input = get(el);\n if (!input) {\n return;\n }\n input.checked = !val;\n input.value = val ? 'off' : 'on';\n});\n\nwatch(internalModelValue, (val) => {\n const input = get(el);\n if (input && input.checked !== val)\n input.checked = val;\n});\n</script>\n\n<template>\n <div v-bind=\"getRootAttrs($attrs)\">\n <label\n :class=\"ui.wrapper()\"\n v-bind=\"objectPick($attrs, ['onClick'])\"\n :data-disabled=\"disabled || undefined\"\n :data-checked=\"internalModelValue || indeterminate || undefined\"\n :data-error=\"hasError ? '' : undefined\"\n >\n <input\n ref=\"el\"\n v-model=\"internalModelValue\"\n type=\"checkbox\"\n :class=\"ui.input()\"\n :disabled=\"disabled\"\n :aria-invalid=\"hasError\"\n v-bind=\"getNonRootAttrs($attrs, ['onInput', 'onClick'])\"\n />\n <span :class=\"ui.control()\">\n <RuiIcon\n v-if=\"indeterminate\"\n name=\"lu-checkbox-indeterminate-fill\"\n :size=\"iconSize\"\n />\n <RuiIcon\n v-else-if=\"internalModelValue\"\n name=\"lu-checkbox-fill\"\n :size=\"iconSize\"\n />\n <RuiIcon\n v-else\n name=\"lu-checkbox-blank\"\n :size=\"iconSize\"\n />\n </span>\n <span\n v-if=\"label || $slots.default\"\n :class=\"ui.label()\"\n >\n <slot>{{ label }}</slot>\n <span\n v-if=\"required\"\n class=\"text-rui-error\"\n >\n ﹡\n </span>\n </span>\n </label>\n <RuiFormTextDetail\n v-if=\"!effectiveHideDetails\"\n :error-messages=\"errorMessages\"\n :success-messages=\"successMessages\"\n :hint=\"hint\"\n />\n </div>\n</template>\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RuiCheckboxGroup.vue_vue_type_script_setup_true_lang.js","names":["$attrs"],"sources":["../../../../../src/components/forms/checkbox/checkbox-group/RuiCheckboxGroup.vue"],"sourcesContent":["<script lang=\"ts\" setup generic=\"TValue\">\nimport type { ContextColorsType } from '@/consts/colors';\nimport { RuiCheckboxGroupContextKey } from '@/components/forms/checkbox/checkbox-group/context';\nimport RuiFormTextDetail from '@/components/helpers/RuiFormTextDetail.vue';\n\nexport interface Props {\n inline?: boolean;\n label?: string;\n hint?: string;\n errorMessages?: string | string[];\n successMessages?: string | string[];\n hideDetails?: boolean;\n disabled?: boolean;\n color?: ContextColorsType;\n size?: 'sm' | 'lg';\n required?: boolean;\n}\n\ndefineOptions({\n name: 'RuiCheckboxGroup',\n inheritAttrs: false,\n});\n\nconst modelValue = defineModel<TValue[]>({ default: () => [] });\n\nconst {\n inline = false,\n label = '',\n hint = '',\n errorMessages = [],\n successMessages = [],\n hideDetails = false,\n disabled = false,\n color,\n size,\n required = false,\n} = defineProps<Props>();\n\ndefineSlots<{\n default?: () => any;\n}>();\n\nfunction arrayIncludes(arr: readonly TValue[], value: unknown): boolean {\n return Array.prototype.includes.call(arr, value);\n}\n\nprovide(RuiCheckboxGroupContextKey, {\n isChecked: (value: unknown): boolean => arrayIncludes(get(modelValue), value),\n toggle: (value: unknown, checked: boolean): void => {\n const current = get(modelValue);\n const present = arrayIncludes(current, value);\n if (checked === present)\n return;\n if (checked)\n set(modelValue, [...current, value as TValue]);\n else\n set(modelValue, current.filter(v => v !== value));\n },\n disabled: () => disabled,\n color: () => color,\n size: () => size,\n});\n</script>\n\n<template>\n <div\n role=\"group\"\n v-bind=\"$attrs\"\n >\n <div\n v-if=\"label\"\n class=\"text-rui-text-secondary text-body-1\"\n >\n {{ label }}\n <span\n v-if=\"required\"\n class=\"text-rui-error\"\n >\n ﹡\n </span>\n </div>\n <div :class=\"{ 'flex space-x-6': inline }\">\n <slot />\n </div>\n <RuiFormTextDetail\n v-if=\"!hideDetails\"\n :error-messages=\"errorMessages\"\n :success-messages=\"successMessages\"\n :hint=\"hint\"\n />\n </div>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAuBA,MAAM,aAAa,SAAqB,SAAA,YAAsB;EAmB9D,SAAS,cAAc,KAAwB,OAAyB;GACtE,OAAO,MAAM,UAAU,SAAS,KAAK,KAAK,KAAK;EACjD;EAEA,QAAQ,4BAA4B;GAClC,YAAY,UAA4B,cAAc,IAAI,UAAU,GAAG,KAAK;GAC5E,SAAS,OAAgB,YAA2B;IAClD,MAAM,UAAU,IAAI,UAAU;IAE9B,IAAI,YADY,cAAc,SAAS,KACvB,GACd;IACF,IAAI,SACF,IAAI,YAAY,CAAC,GAAG,SAAS,KAAe,CAAC;SAE7C,IAAI,YAAY,QAAQ,QAAO,MAAK,MAAM,KAAK,CAAC;GACpD;GACA,gBAAgB,QAAA;GAChB,aAAa,QAAA;GACb,YAAY,QAAA;EACd,CAAC;;
|
|
1
|
+
{"version":3,"file":"RuiCheckboxGroup.vue_vue_type_script_setup_true_lang.js","names":["$attrs"],"sources":["../../../../../src/components/forms/checkbox/checkbox-group/RuiCheckboxGroup.vue"],"sourcesContent":["<script lang=\"ts\" setup generic=\"TValue\">\nimport type { ContextColorsType } from '@/consts/colors';\nimport { RuiCheckboxGroupContextKey } from '@/components/forms/checkbox/checkbox-group/context';\nimport RuiFormTextDetail from '@/components/helpers/RuiFormTextDetail.vue';\n\nexport interface Props {\n inline?: boolean;\n label?: string;\n hint?: string;\n errorMessages?: string | string[];\n successMessages?: string | string[];\n hideDetails?: boolean;\n disabled?: boolean;\n color?: ContextColorsType;\n size?: 'sm' | 'lg';\n required?: boolean;\n}\n\ndefineOptions({\n name: 'RuiCheckboxGroup',\n inheritAttrs: false,\n});\n\nconst modelValue = defineModel<TValue[]>({ default: () => [] });\n\nconst {\n inline = false,\n label = '',\n hint = '',\n errorMessages = [],\n successMessages = [],\n hideDetails = false,\n disabled = false,\n color,\n size,\n required = false,\n} = defineProps<Props>();\n\ndefineSlots<{\n default?: () => any;\n}>();\n\nfunction arrayIncludes(arr: readonly TValue[], value: unknown): boolean {\n return Array.prototype.includes.call(arr, value);\n}\n\nprovide(RuiCheckboxGroupContextKey, {\n isChecked: (value: unknown): boolean => arrayIncludes(get(modelValue), value),\n toggle: (value: unknown, checked: boolean): void => {\n const current = get(modelValue);\n const present = arrayIncludes(current, value);\n if (checked === present)\n return;\n if (checked)\n set(modelValue, [...current, value as TValue]);\n else\n set(modelValue, current.filter(v => v !== value));\n },\n disabled: () => disabled,\n color: () => color,\n size: () => size,\n});\n</script>\n\n<template>\n <div\n role=\"group\"\n v-bind=\"$attrs\"\n >\n <div\n v-if=\"label\"\n class=\"text-rui-text-secondary text-body-1\"\n >\n {{ label }}\n <span\n v-if=\"required\"\n class=\"text-rui-error\"\n >\n ﹡\n </span>\n </div>\n <div :class=\"{ 'flex space-x-6': inline }\">\n <slot />\n </div>\n <RuiFormTextDetail\n v-if=\"!hideDetails\"\n :error-messages=\"errorMessages\"\n :success-messages=\"successMessages\"\n :hint=\"hint\"\n />\n </div>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAuBA,MAAM,aAAa,SAAqB,SAAA,YAAsB;EAmB9D,SAAS,cAAc,KAAwB,OAAyB;GACtE,OAAO,MAAM,UAAU,SAAS,KAAK,KAAK,KAAK;EACjD;EAEA,QAAQ,4BAA4B;GAClC,YAAY,UAA4B,cAAc,IAAI,UAAU,GAAG,KAAK;GAC5E,SAAS,OAAgB,YAA2B;IAClD,MAAM,UAAU,IAAI,UAAU;IAE9B,IAAI,YADY,cAAc,SAAS,KACvB,GACd;IACF,IAAI,SACF,IAAI,YAAY,CAAC,GAAG,SAAS,KAAe,CAAC;SAE7C,IAAI,YAAY,QAAQ,QAAO,MAAK,MAAM,KAAK,CAAC;GACpD;GACA,gBAAgB,QAAA;GAChB,aAAa,QAAA;GACb,YAAY,QAAA;EACd,CAAC;;GAIC,OAAA,UAAA,GAAA,mBAyBM,OAzBN,WAyBM,EAxBJ,MAAK,QAAO,GACJA,KAAAA,MAAM,GAAA;IAGN,QAAA,SADR,UAAA,GAAA,mBAWM,OAXN,YAWM,CAPD,gBAAA,gBAAA,QAAA,KAAK,IAAG,KACX,CAAA,GACQ,QAAA,YADR,UAAA,GAAA,mBAKO,QALP,YAGC,KAED,KAAA,mBAAA,IAAA,IAAA,CAAA,CAAA,KAAA,mBAAA,IAAA,IAAA;IAEF,mBAEM,OAAA,EAFA,OAAK,eAAA,EAAA,kBAAsB,QAAA,OAAM,CAAA,EAAA,GAAA,CACrC,WAAQ,KAAA,QAAA,SAAA,CAAA,GAAA,CAAA;IAGD,CAAA,QAAA,eADT,UAAA,GAAA,YAKE,2BAAA;;KAHC,kBAAgB,QAAA;KAChB,oBAAkB,QAAA;KAClB,MAAM,QAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RuiFileUpload.js","names":[],"sources":["../../../../src/components/forms/file-upload/RuiFileUpload.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport RuiFormTextDetail from '@/components/helpers/RuiFormTextDetail.vue';\nimport RuiIcon from '@/components/icons/RuiIcon.vue';\nimport RuiProgress from '@/components/progress/RuiProgress.vue';\nimport { useFormTextDetail } from '@/utils/form-text-detail';\nimport { formatFileSize, getNonRootAttrs, getRootAttrs } from '@/utils/helpers';\n\nexport interface FileUploadProps {\n /** File type filter (HTML accept attribute syntax). e.g. '.csv', 'image/*', '.png,.jpg' */\n accept?: string;\n /** Allow multiple file selection. */\n multiple?: boolean;\n disabled?: boolean;\n /** Shows a loading overlay (consumer-driven, e.g. while uploading). */\n loading?: boolean;\n /** Upload progress 0-100. When provided alongside `loading`, the overlay shows a determinate progress bar with percentage. */\n progress?: number;\n /** Renders the success state border/icon. Consumer toggles back to false. */\n uploaded?: boolean;\n /** Optional max size per file in bytes; failures emit `error` and set internal error state. */\n maxSize?: number;\n /** External error messages (e.g. from Vuelidate). Shown via the standard form detail block. */\n errorMessages?: string | string[];\n /** Hint text below the dropzone. */\n hint?: string;\n /** Disable drag-and-drop; the dropzone becomes click-only (matches rotki.com use case). */\n noDrop?: boolean;\n /** Replace the default \"Drag and drop or {button}\" copy. */\n uploadText?: string;\n /** Label shown on the inline button when no file is selected. */\n clickToUploadText?: string;\n /** Label shown on the inline button when one or more files are already selected. */\n replaceText?: string;\n /** Hide the bottom hint/error details strip. */\n hideDetails?: boolean;\n}\n\ndefineOptions({\n name: 'RuiFileUpload',\n inheritAttrs: false,\n});\n\nconst modelValue = defineModel<File | File[] | undefined>({ required: true });\n\nconst {\n accept = '*',\n multiple = false,\n disabled = false,\n loading = false,\n progress = undefined,\n uploaded = false,\n maxSize = undefined,\n errorMessages = [],\n hint = '',\n noDrop = false,\n uploadText = 'Drag and drop or',\n clickToUploadText = 'click to upload',\n replaceText = 'replace file',\n hideDetails = false,\n} = defineProps<FileUploadProps>();\n\nconst emit = defineEmits<{\n error: [message: string];\n}>();\n\ndefineSlots<{\n preview?: (props: { files: File[]; remove: () => void }) => any;\n icon?: () => any;\n description?: () => any;\n}>();\n\nconst wrapper = useTemplateRef<HTMLDivElement>('wrapper');\nconst input = useTemplateRef<HTMLInputElement>('input');\nconst internalError = ref<string>('');\n\nconst files = computed<File[]>(() => {\n const value = get(modelValue);\n if (!value)\n return [];\n return Array.isArray(value) ? value : [value];\n});\n\nconst hasFiles = computed<boolean>(() => get(files).length > 0);\n\nconst progressLabel = computed<string | undefined>(() => {\n const value = progress;\n return value === undefined ? undefined : `${Math.round(value)}%`;\n});\n\nconst combinedErrorMessages = computed<string[]>(() => {\n const external = Array.isArray(errorMessages) ? errorMessages : [errorMessages];\n const internal = get(internalError);\n return [...external.filter(Boolean), ...(internal ? [internal] : [])];\n});\n\nconst { hasError } = useFormTextDetail(combinedErrorMessages, () => []);\n\nfunction matchesAccept(file: File, acceptString: string): boolean {\n if (!acceptString || acceptString === '*' || acceptString === '*/*')\n return true;\n\n const fileName = file.name.toLowerCase();\n const fileExtension = fileName.includes('.') ? fileName.slice(fileName.lastIndexOf('.')) : '';\n const fileType = file.type.toLowerCase();\n const acceptTypes = acceptString.split(',').map(value => value.trim().toLowerCase()).filter(Boolean);\n\n return acceptTypes.some((type) => {\n if (type.startsWith('.'))\n return type === fileExtension;\n if (type.endsWith('/*'))\n return fileType.startsWith(type.slice(0, -1));\n return type === fileType;\n });\n}\n\nfunction reportError(message: string): void {\n set(internalError, message);\n emit('error', message);\n}\n\nfunction clearInternalError(): void {\n set(internalError, '');\n}\n\nfunction validate(candidates: File[]): File[] | undefined {\n if (candidates.length === 0)\n return undefined;\n\n if (!multiple && candidates.length > 1) {\n reportError('Only one file can be uploaded');\n return undefined;\n }\n\n for (const file of candidates) {\n if (!matchesAccept(file, accept)) {\n reportError(`Only ${accept} files are allowed`);\n return undefined;\n }\n if (maxSize !== undefined && file.size > maxSize) {\n reportError(`${file.name} exceeds the maximum size of ${formatFileSize(maxSize)}`);\n return undefined;\n }\n }\n\n return candidates;\n}\n\nfunction setFiles(candidates: File[]): void {\n const validated = validate(candidates);\n if (!validated)\n return;\n clearInternalError();\n set(modelValue, multiple ? validated : validated[0]);\n}\n\nfunction removeFile(target?: File): void {\n clearInternalError();\n const inputEl = get(input);\n if (inputEl)\n inputEl.value = '';\n\n if (!target || !multiple) {\n set(modelValue, multiple ? [] : undefined);\n return;\n }\n\n const remaining = get(files).filter(file => file !== target);\n set(modelValue, remaining);\n}\n\nfunction onSelect(event: Event): void {\n const target = event.target as HTMLInputElement;\n if (!target?.files)\n return;\n setFiles(Array.from(target.files));\n}\n\nfunction onDrop(dropped: File[] | null): void {\n if (disabled || noDrop || !dropped || dropped.length === 0)\n return;\n setFiles(dropped);\n}\n\nconst { isOverDropZone } = useDropZone(wrapper, {\n onDrop,\n});\n\nfunction openPicker(): void {\n if (disabled)\n return;\n get(input)?.click();\n}\n\nwatch(() => errorMessages, () => clearInternalError());\n\ndefineExpose({\n removeFile: () => removeFile(),\n openPicker,\n});\n</script>\n\n<template>\n <div v-bind=\"getRootAttrs($attrs)\">\n <div\n ref=\"wrapper\"\n class=\"p-4 border border-rui-grey-300 dark:border-rui-grey-800 rounded-md w-full relative border-dashed transition\"\n :class=\"{\n '!border-rui-primary bg-rui-primary/[0.08]': isOverDropZone && !disabled && !noDrop,\n '!border-rui-error !border-solid bg-rui-error/[0.08]': hasError,\n '!border-rui-success !border-solid bg-rui-success/[0.08]': uploaded,\n 'opacity-60 pointer-events-none': disabled,\n }\"\n :data-disabled=\"disabled || undefined\"\n :data-uploaded=\"uploaded || undefined\"\n :data-error=\"hasError ? '' : undefined\"\n :data-drop-active=\"isOverDropZone || undefined\"\n >\n <div\n class=\"flex flex-col items-center justify-center gap-3\"\n :class=\"{ 'opacity-0': loading }\"\n >\n <slot\n name=\"preview\"\n :files=\"files\"\n :remove=\"() => removeFile()\"\n >\n <div\n v-if=\"hasFiles\"\n class=\"flex flex-col gap-1 w-full\"\n data-id=\"file-list\"\n >\n <div\n v-for=\"file in files\"\n :key=\"`${file.name}-${file.lastModified}`\"\n class=\"flex items-center gap-2 bg-rui-primary/[0.08] rounded-full pl-3 pr-1 py-1\"\n data-id=\"file-item\"\n >\n <RuiIcon\n name=\"lu-file\"\n color=\"primary\"\n size=\"20\"\n />\n <div class=\"flex-1 overflow-hidden min-w-0\">\n <div\n class=\"text-sm leading-5 truncate\"\n :title=\"file.name\"\n >\n {{ file.name }}\n </div>\n <div class=\"text-rui-text-secondary text-xs leading-3\">\n {{ formatFileSize(file.size) }}\n </div>\n </div>\n <button\n type=\"button\"\n class=\"p-1 rounded-full hover:bg-rui-primary/[0.16] transition\"\n :disabled=\"disabled\"\n :aria-label=\"`Remove ${file.name}`\"\n data-id=\"remove-file\"\n @click=\"removeFile(file)\"\n >\n <RuiIcon\n name=\"lu-x\"\n size=\"16\"\n />\n </button>\n </div>\n </div>\n <div\n v-else\n class=\"h-10 w-10 rounded-full flex items-center justify-center\"\n :class=\"uploaded ? 'bg-rui-success/[0.12]' : 'bg-rui-primary/[0.12]'\"\n >\n <slot name=\"icon\">\n <RuiIcon\n :name=\"uploaded ? 'lu-circle-check' : 'lu-file-up'\"\n :color=\"uploaded ? 'success' : 'primary'\"\n />\n </slot>\n </div>\n </slot>\n\n <div class=\"text-center text-sm\">\n <slot name=\"description\">\n <div class=\"flex items-center justify-center gap-1 flex-wrap\">\n <span>{{ uploadText }}</span>\n <button\n type=\"button\"\n class=\"text-rui-primary underline disabled:no-underline disabled:text-rui-text-disabled\"\n :disabled=\"disabled\"\n data-id=\"open-picker\"\n @click=\"openPicker()\"\n >\n {{ hasFiles ? replaceText : clickToUploadText }}\n </button>\n </div>\n </slot>\n </div>\n\n <input\n ref=\"input\"\n type=\"file\"\n :accept=\"accept\"\n :multiple=\"multiple\"\n :disabled=\"disabled\"\n hidden\n data-id=\"file-input\"\n v-bind=\"getNonRootAttrs($attrs, ['class', 'onChange'])\"\n @change=\"onSelect($event)\"\n />\n </div>\n\n <div\n v-if=\"loading\"\n class=\"flex flex-col items-center justify-center absolute h-full w-full top-0 left-0 gap-2\"\n data-id=\"loading\"\n >\n <RuiProgress\n circular\n :variant=\"progress === undefined ? 'indeterminate' : 'determinate'\"\n :value=\"progress\"\n color=\"primary\"\n size=\"40\"\n />\n <div\n v-if=\"progressLabel\"\n class=\"text-xs text-rui-text-secondary\"\n data-id=\"progress-label\"\n v-text=\"progressLabel\"\n />\n </div>\n </div>\n <RuiFormTextDetail\n v-if=\"!hideDetails\"\n :error-messages=\"combinedErrorMessages\"\n :hint=\"hint\"\n />\n </div>\n</template>\n"],"mappings":""}
|
|
1
|
+
{"version":3,"file":"RuiFileUpload.js","names":[],"sources":["../../../../src/components/forms/file-upload/RuiFileUpload.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport RuiFormTextDetail from '@/components/helpers/RuiFormTextDetail.vue';\nimport RuiIcon from '@/components/icons/RuiIcon.vue';\nimport RuiProgress from '@/components/progress/RuiProgress.vue';\nimport { useFormTextDetail } from '@/utils/form-text-detail';\nimport { formatFileSize, getNonRootAttrs, getRootAttrs } from '@/utils/helpers';\n\nexport interface FileUploadProps {\n /** File type filter (HTML accept attribute syntax). e.g. '.csv', 'image/*', '.png,.jpg' */\n accept?: string;\n /** Allow multiple file selection. */\n multiple?: boolean;\n disabled?: boolean;\n /** Shows a loading overlay (consumer-driven, e.g. while uploading). */\n loading?: boolean;\n /** Upload progress 0-100. When provided alongside `loading`, the overlay shows a determinate progress bar with percentage. */\n progress?: number;\n /** Renders the success state border/icon. Consumer toggles back to false. */\n uploaded?: boolean;\n /** Optional max size per file in bytes; failures emit `error` and set internal error state. */\n maxSize?: number;\n /** External error messages (e.g. from Vuelidate). Shown via the standard form detail block. */\n errorMessages?: string | string[];\n /** Hint text below the dropzone. */\n hint?: string;\n /** Disable drag-and-drop; the dropzone becomes click-only (matches rotki.com use case). */\n noDrop?: boolean;\n /** Replace the default \"Drag and drop or \\{button\\}\" copy. */\n uploadText?: string;\n /** Label shown on the inline button when no file is selected. */\n clickToUploadText?: string;\n /** Label shown on the inline button when one or more files are already selected. */\n replaceText?: string;\n /** Hide the bottom hint/error details strip. */\n hideDetails?: boolean;\n}\n\ndefineOptions({\n name: 'RuiFileUpload',\n inheritAttrs: false,\n});\n\nconst modelValue = defineModel<File | File[] | undefined>({ required: true });\n\nconst {\n accept = '*',\n multiple = false,\n disabled = false,\n loading = false,\n progress = undefined,\n uploaded = false,\n maxSize = undefined,\n errorMessages = [],\n hint = '',\n noDrop = false,\n uploadText = 'Drag and drop or',\n clickToUploadText = 'click to upload',\n replaceText = 'replace file',\n hideDetails = false,\n} = defineProps<FileUploadProps>();\n\nconst emit = defineEmits<{\n error: [message: string];\n}>();\n\ndefineSlots<{\n preview?: (props: { files: File[]; remove: () => void }) => any;\n icon?: () => any;\n description?: () => any;\n}>();\n\nconst wrapper = useTemplateRef<HTMLDivElement>('wrapper');\nconst input = useTemplateRef<HTMLInputElement>('input');\nconst internalError = ref<string>('');\n\nconst files = computed<File[]>(() => {\n const value = get(modelValue);\n if (!value)\n return [];\n return Array.isArray(value) ? value : [value];\n});\n\nconst hasFiles = computed<boolean>(() => get(files).length > 0);\n\nconst progressLabel = computed<string | undefined>(() => {\n const value = progress;\n return value === undefined ? undefined : `${Math.round(value)}%`;\n});\n\nconst combinedErrorMessages = computed<string[]>(() => {\n const external = Array.isArray(errorMessages) ? errorMessages : [errorMessages];\n const internal = get(internalError);\n return [...external.filter(Boolean), ...(internal ? [internal] : [])];\n});\n\nconst { hasError } = useFormTextDetail(combinedErrorMessages, () => []);\n\nfunction matchesAccept(file: File, acceptString: string): boolean {\n if (!acceptString || acceptString === '*' || acceptString === '*/*')\n return true;\n\n const fileName = file.name.toLowerCase();\n const fileExtension = fileName.includes('.') ? fileName.slice(fileName.lastIndexOf('.')) : '';\n const fileType = file.type.toLowerCase();\n const acceptTypes = acceptString.split(',').map(value => value.trim().toLowerCase()).filter(Boolean);\n\n return acceptTypes.some((type) => {\n if (type.startsWith('.'))\n return type === fileExtension;\n if (type.endsWith('/*'))\n return fileType.startsWith(type.slice(0, -1));\n return type === fileType;\n });\n}\n\nfunction reportError(message: string): void {\n set(internalError, message);\n emit('error', message);\n}\n\nfunction clearInternalError(): void {\n set(internalError, '');\n}\n\nfunction validate(candidates: File[]): File[] | undefined {\n if (candidates.length === 0)\n return undefined;\n\n if (!multiple && candidates.length > 1) {\n reportError('Only one file can be uploaded');\n return undefined;\n }\n\n for (const file of candidates) {\n if (!matchesAccept(file, accept)) {\n reportError(`Only ${accept} files are allowed`);\n return undefined;\n }\n if (maxSize !== undefined && file.size > maxSize) {\n reportError(`${file.name} exceeds the maximum size of ${formatFileSize(maxSize)}`);\n return undefined;\n }\n }\n\n return candidates;\n}\n\nfunction setFiles(candidates: File[]): void {\n const validated = validate(candidates);\n if (!validated)\n return;\n clearInternalError();\n set(modelValue, multiple ? validated : validated[0]);\n}\n\nfunction removeFile(target?: File): void {\n clearInternalError();\n const inputEl = get(input);\n if (inputEl)\n inputEl.value = '';\n\n if (!target || !multiple) {\n set(modelValue, multiple ? [] : undefined);\n return;\n }\n\n const remaining = get(files).filter(file => file !== target);\n set(modelValue, remaining);\n}\n\nfunction onSelect(event: Event): void {\n const target = event.target as HTMLInputElement;\n if (!target?.files)\n return;\n setFiles(Array.from(target.files));\n}\n\nfunction onDrop(dropped: File[] | null): void {\n if (disabled || noDrop || !dropped || dropped.length === 0)\n return;\n setFiles(dropped);\n}\n\nconst { isOverDropZone } = useDropZone(wrapper, {\n onDrop,\n});\n\nfunction openPicker(): void {\n if (disabled)\n return;\n get(input)?.click();\n}\n\nwatch(() => errorMessages, () => clearInternalError());\n\ndefineExpose({\n removeFile: () => removeFile(),\n openPicker,\n});\n</script>\n\n<template>\n <div v-bind=\"getRootAttrs($attrs)\">\n <div\n ref=\"wrapper\"\n class=\"p-4 border border-rui-grey-300 dark:border-rui-grey-800 rounded-md w-full relative border-dashed transition\"\n :class=\"{\n '!border-rui-primary bg-rui-primary/[0.08]': isOverDropZone && !disabled && !noDrop,\n '!border-rui-error !border-solid bg-rui-error/[0.08]': hasError,\n '!border-rui-success !border-solid bg-rui-success/[0.08]': uploaded,\n 'opacity-60 pointer-events-none': disabled,\n }\"\n :data-disabled=\"disabled || undefined\"\n :data-uploaded=\"uploaded || undefined\"\n :data-error=\"hasError ? '' : undefined\"\n :data-drop-active=\"isOverDropZone || undefined\"\n >\n <div\n class=\"flex flex-col items-center justify-center gap-3\"\n :class=\"{ 'opacity-0': loading }\"\n >\n <slot\n name=\"preview\"\n :files=\"files\"\n :remove=\"() => removeFile()\"\n >\n <div\n v-if=\"hasFiles\"\n class=\"flex flex-col gap-1 w-full\"\n data-id=\"file-list\"\n >\n <div\n v-for=\"file in files\"\n :key=\"`${file.name}-${file.lastModified}`\"\n class=\"flex items-center gap-2 bg-rui-primary/[0.08] rounded-full pl-3 pr-1 py-1\"\n data-id=\"file-item\"\n >\n <RuiIcon\n name=\"lu-file\"\n color=\"primary\"\n size=\"20\"\n />\n <div class=\"flex-1 overflow-hidden min-w-0\">\n <div\n class=\"text-sm leading-5 truncate\"\n :title=\"file.name\"\n >\n {{ file.name }}\n </div>\n <div class=\"text-rui-text-secondary text-xs leading-3\">\n {{ formatFileSize(file.size) }}\n </div>\n </div>\n <button\n type=\"button\"\n class=\"p-1 rounded-full hover:bg-rui-primary/[0.16] transition\"\n :disabled=\"disabled\"\n :aria-label=\"`Remove ${file.name}`\"\n data-id=\"remove-file\"\n @click=\"removeFile(file)\"\n >\n <RuiIcon\n name=\"lu-x\"\n size=\"16\"\n />\n </button>\n </div>\n </div>\n <div\n v-else\n class=\"h-10 w-10 rounded-full flex items-center justify-center\"\n :class=\"uploaded ? 'bg-rui-success/[0.12]' : 'bg-rui-primary/[0.12]'\"\n >\n <slot name=\"icon\">\n <RuiIcon\n :name=\"uploaded ? 'lu-circle-check' : 'lu-file-up'\"\n :color=\"uploaded ? 'success' : 'primary'\"\n />\n </slot>\n </div>\n </slot>\n\n <div class=\"text-center text-sm\">\n <slot name=\"description\">\n <div class=\"flex items-center justify-center gap-1 flex-wrap\">\n <span>{{ uploadText }}</span>\n <button\n type=\"button\"\n class=\"text-rui-primary underline disabled:no-underline disabled:text-rui-text-disabled\"\n :disabled=\"disabled\"\n data-id=\"open-picker\"\n @click=\"openPicker()\"\n >\n {{ hasFiles ? replaceText : clickToUploadText }}\n </button>\n </div>\n </slot>\n </div>\n\n <input\n ref=\"input\"\n type=\"file\"\n :accept=\"accept\"\n :multiple=\"multiple\"\n :disabled=\"disabled\"\n hidden\n data-id=\"file-input\"\n v-bind=\"getNonRootAttrs($attrs, ['class', 'onChange'])\"\n @change=\"onSelect($event)\"\n />\n </div>\n\n <div\n v-if=\"loading\"\n class=\"flex flex-col items-center justify-center absolute h-full w-full top-0 left-0 gap-2\"\n data-id=\"loading\"\n >\n <RuiProgress\n circular\n :variant=\"progress === undefined ? 'indeterminate' : 'determinate'\"\n :value=\"progress\"\n color=\"primary\"\n size=\"40\"\n />\n <div\n v-if=\"progressLabel\"\n class=\"text-xs text-rui-text-secondary\"\n data-id=\"progress-label\"\n v-text=\"progressLabel\"\n />\n </div>\n </div>\n <RuiFormTextDetail\n v-if=\"!hideDetails\"\n :error-messages=\"combinedErrorMessages\"\n :hint=\"hint\"\n />\n </div>\n</template>\n"],"mappings":""}
|
|
@@ -18,7 +18,7 @@ export interface FileUploadProps {
|
|
|
18
18
|
hint?: string;
|
|
19
19
|
/** Disable drag-and-drop; the dropzone becomes click-only (matches rotki.com use case). */
|
|
20
20
|
noDrop?: boolean;
|
|
21
|
-
/** Replace the default "Drag and drop or {button}" copy. */
|
|
21
|
+
/** Replace the default "Drag and drop or \{button\}" copy. */
|
|
22
22
|
uploadText?: string;
|
|
23
23
|
/** Label shown on the inline button when no file is selected. */
|
|
24
24
|
clickToUploadText?: string;
|