@rotki/ui-library 2.24.0 → 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 +2 -2
- package/dist/components/date-time-picker/RuiDateTimePicker.vue_vue_type_script_setup_true_lang.js +54 -26
- 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 +1 -1
- package/dist/components/date-time-picker/partial-time.js +17 -6
- package/dist/components/date-time-picker/partial-time.js.map +1 -1
- 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 +2 -1
- package/dist/components/date-time-picker/use-date-bounds.js +7 -3
- package/dist/components/date-time-picker/use-date-bounds.js.map +1 -1
- package/dist/components/date-time-picker/use-date-time-selection.d.ts +13 -13
- package/dist/components/date-time-picker/use-date-time-selection.js +96 -86
- 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 +863 -50
- package/package.json +32 -33
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RuiLogo.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../src/components/logos/RuiLogo.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { isClient } from '@vueuse/shared';\nimport { useSSRContext } from 'vue';\nimport fallback from '@/components/logos/logo.svg';\nimport { getCachedLogoSources, getLogoSources, getVerifiedLogoUrl, removeVerifiedLogoUrl, setVerifiedLogoUrl } from '@/components/logos/use-logo-sources';\n\nexport interface ExternalLinks {\n drawer?: string;\n app?: string;\n website?: string;\n about?: string;\n emptyScreen?: string;\n [key: string]: string | undefined;\n}\n\nexport interface Props {\n text?: boolean;\n branch?: 'develop' | 'main' | string;\n logo?: keyof ExternalLinks;\n size?: string | number; // in rems\n uniqueKey?: string | number;\n src?: string;\n}\n\ndefineOptions({\n name: 'RuiLogo',\n});\n\nconst { text = false, branch = 'develop', logo, size = 3, uniqueKey, src } = defineProps<Props>();\n\nconst appName = 'rotki';\nconst emptyLinks: () => ExternalLinks = () => ({\n app: undefined,\n website: undefined,\n about: undefined,\n emptyScreen: undefined,\n});\n\nconst error = ref<boolean>(false);\nconst seasonalReady = ref<boolean>(false);\nconst externalSources = ref<ExternalLinks>(emptyLinks());\n\nconst customImageRef = useTemplateRef<HTMLImageElement>('customImageRef');\n\n// Synchronously hydrate from sessionStorage so the URL is available immediately on refresh\nif (isClient && logo && !src) {\n const cached = getCachedLogoSources(branch);\n if (cached)\n set(externalSources, cached);\n}\n\nfunction buildExternalUrl(sources: ExternalLinks): string | undefined {\n if (!logo || !sources[logo])\n return undefined;\n\n const url = `https://raw.githubusercontent.com/rotki/data/${branch}/assets/icons/${sources[logo]}`;\n\n if (uniqueKey !== undefined)\n return `${url}?key=${uniqueKey}`;\n\n return url;\n}\n\nconst externalSource = computed<string | undefined>(() => {\n if (src)\n return src;\n\n return buildExternalUrl(get(externalSources));\n});\n\nconst showCustom = computed<boolean>(() => !!src || (!!get(externalSource) && get(seasonalReady) && !get(error)));\n\n// If we have a previously verified URL that matches the current source, trust it immediately\nif (isClient && logo && !src) {\n const verifiedUrl = getVerifiedLogoUrl(branch, String(logo));\n const currentUrl = get(externalSource);\n if (verifiedUrl && currentUrl && verifiedUrl === currentUrl)\n set(seasonalReady, true);\n}\n\nfunction preloadImage(url: string): void {\n if (!isClient)\n return;\n\n const existing = document.head.querySelectorAll<HTMLLinkElement>('link[rel=\"preload\"][as=\"image\"]');\n for (const link of existing) {\n if (link.href === url)\n return;\n }\n\n const link = document.createElement('link');\n link.rel = 'preload';\n link.as = 'image';\n link.href = url;\n document.head.appendChild(link);\n}\n\n// Inject a preload hint for the seasonal image so the browser starts fetching early\nif (isClient && logo && !src) {\n const url = get(externalSource);\n if (url)\n preloadImage(url);\n}\n\nasync function fetchSources(): Promise<void> {\n if (!logo || src)\n return;\n\n const links = await getLogoSources(branch);\n\n if (links)\n set(externalSources, links);\n}\n\nfunction onImageError(): void {\n set(error, true);\n if (logo)\n removeVerifiedLogoUrl(branch, String(logo));\n}\n\nfunction onImageLoaded(): void {\n const img = get(customImageRef);\n if (!img)\n return;\n\n img.decode()\n .then(() => {\n set(seasonalReady, true);\n // Cache the verified URL so subsequent page loads can trust it immediately\n const url = get(externalSource);\n if (url && logo)\n setVerifiedLogoUrl(branch, String(logo), url);\n })\n .catch(() => set(error, true));\n}\n\nwatch(() => get(customImageRef)?.complete, (complete) => {\n if (complete)\n onImageLoaded();\n});\n\nwatchEffect(fetchSources);\n\nif (!isClient)\n useSSRContext();\n\nonServerPrefetch(async () => {\n await fetchSources();\n});\n</script>\n\n<template>\n <div\n class=\"gap-x-4 flex items-center relative\"\n :style=\"{ height: `${size}rem` }\"\n >\n <div\n class=\"relative\"\n :style=\"{ width: `${size}rem`, height: `${size}rem` }\"\n >\n <!-- Fallback: always in DOM, fades out when custom image is ready -->\n <img\n :src=\"fallback\"\n :alt=\"appName\"\n data-image=\"fallback\"\n class=\"absolute inset-0 h-full w-full transition ease-out duration-200\"\n :class=\"showCustom ? 'opacity-0' : 'opacity-100'\"\n />\n\n <!-- Custom/seasonal image: fades in when decoded -->\n <img\n v-if=\"externalSource && !error\"\n ref=\"customImageRef\"\n :src=\"externalSource\"\n :alt=\"appName\"\n data-image=\"custom\"\n class=\"absolute inset-0 h-full w-full transition ease-out duration-200\"\n :class=\"showCustom ? 'opacity-100' : 'opacity-0 pointer-events-none'\"\n @error=\"onImageError()\"\n @load=\"onImageLoaded()\"\n />\n </div>\n\n <div\n v-if=\"text\"\n class=\"text-h4 text-rui-primary dark:text-white\"\n >\n {{ appName }}\n </div>\n </div>\n</template>\n"],"mappings":";;;;;;;;;;;AA8BA,IAAM,UAAU;;;;;;;;;;;;;;;;EAChB,MAAM,oBAAyC;GAC7C,KAAK,KAAA;GACL,SAAS,KAAA;GACT,OAAO,KAAA;GACP,aAAa,KAAA;EACf;EAEA,MAAM,QAAQ,IAAa,KAAK;EAChC,MAAM,gBAAgB,IAAa,KAAK;EACxC,MAAM,kBAAkB,IAAmB,WAAW,CAAC;EAEvD,MAAM,iBAAiB,eAAiC,gBAAgB;EAGxE,IAAI,YAAY,QAAA,QAAQ,CAAC,QAAA,KAAK;GAC5B,MAAM,SAAS,qBAAqB,QAAA,MAAM;GAC1C,IAAI,QACF,IAAI,iBAAiB,MAAM;EAC/B;EAEA,SAAS,iBAAiB,SAA4C;GACpE,IAAI,CAAC,QAAA,QAAQ,CAAC,QAAQ,QAAA,OACpB,OAAO,KAAA;GAET,MAAM,MAAM,gDAAgD,QAAA,OAAO,gBAAgB,QAAQ,QAAA;GAE3F,IAAI,QAAA,cAAc,KAAA,GAChB,OAAO,GAAG,IAAI,OAAO,QAAA;GAEvB,OAAO;EACT;EAEA,MAAM,iBAAiB,eAAmC;GACxD,IAAI,QAAA,KACF,OAAO,QAAA;GAET,OAAO,iBAAiB,IAAI,eAAe,CAAC;EAC9C,CAAC;EAED,MAAM,aAAa,eAAwB,CAAC,CAAC,QAAA,OAAQ,CAAC,CAAC,IAAI,cAAc,KAAK,IAAI,aAAa,KAAK,CAAC,IAAI,KAAK,CAAE;EAGhH,IAAI,YAAY,QAAA,QAAQ,CAAC,QAAA,KAAK;GAC5B,MAAM,cAAc,mBAAmB,QAAA,QAAQ,OAAO,QAAA,IAAI,CAAC;GAC3D,MAAM,aAAa,IAAI,cAAc;GACrC,IAAI,eAAe,cAAc,gBAAgB,YAC/C,IAAI,eAAe,IAAI;EAC3B;EAEA,SAAS,aAAa,KAAmB;GACvC,IAAI,CAAC,UACH;GAEF,MAAM,WAAW,SAAS,KAAK,iBAAkC,qCAAiC;GAClG,KAAK,MAAM,QAAQ,UACjB,IAAI,KAAK,SAAS,KAChB;GAGJ,MAAM,OAAO,SAAS,cAAc,MAAM;GAC1C,KAAK,MAAM;GACX,KAAK,KAAK;GACV,KAAK,OAAO;GACZ,SAAS,KAAK,YAAY,IAAI;EAChC;EAGA,IAAI,YAAY,QAAA,QAAQ,CAAC,QAAA,KAAK;GAC5B,MAAM,MAAM,IAAI,cAAc;GAC9B,IAAI,KACF,aAAa,GAAG;EACpB;EAEA,eAAe,eAA8B;GAC3C,IAAI,CAAC,QAAA,QAAQ,QAAA,KACX;GAEF,MAAM,QAAQ,MAAM,eAAe,QAAA,MAAM;GAEzC,IAAI,OACF,IAAI,iBAAiB,KAAK;EAC9B;EAEA,SAAS,eAAqB;GAC5B,IAAI,OAAO,IAAI;GACf,IAAI,QAAA,MACF,sBAAsB,QAAA,QAAQ,OAAO,QAAA,IAAI,CAAC;EAC9C;EAEA,SAAS,gBAAsB;GAC7B,MAAM,MAAM,IAAI,cAAc;GAC9B,IAAI,CAAC,KACH;GAEF,IAAI,OAAO,CAAA,CACR,WAAW;IACV,IAAI,eAAe,IAAI;IAEvB,MAAM,MAAM,IAAI,cAAc;IAC9B,IAAI,OAAO,QAAA,MACT,mBAAmB,QAAA,QAAQ,OAAO,QAAA,IAAI,GAAG,GAAG;GAChD,CAAC,CAAA,CACA,YAAY,IAAI,OAAO,IAAI,CAAC;EACjC;EAEA,YAAY,IAAI,cAAc,CAAC,EAAE,WAAW,aAAa;GACvD,IAAI,UACF,cAAc;EAClB,CAAC;EAED,YAAY,YAAY;EAExB,IAAI,CAAC,UACH,cAAc;EAEhB,iBAAiB,YAAY;GAC3B,MAAM,aAAa;EACrB,CAAC;;
|
|
1
|
+
{"version":3,"file":"RuiLogo.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../src/components/logos/RuiLogo.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { isClient } from '@vueuse/shared';\nimport { useSSRContext } from 'vue';\nimport fallback from '@/components/logos/logo.svg';\nimport { getCachedLogoSources, getLogoSources, getVerifiedLogoUrl, removeVerifiedLogoUrl, setVerifiedLogoUrl } from '@/components/logos/use-logo-sources';\n\nexport interface ExternalLinks {\n drawer?: string;\n app?: string;\n website?: string;\n about?: string;\n emptyScreen?: string;\n [key: string]: string | undefined;\n}\n\nexport interface Props {\n text?: boolean;\n branch?: 'develop' | 'main' | string;\n logo?: keyof ExternalLinks;\n size?: string | number; // in rems\n uniqueKey?: string | number;\n src?: string;\n}\n\ndefineOptions({\n name: 'RuiLogo',\n});\n\nconst { text = false, branch = 'develop', logo, size = 3, uniqueKey, src } = defineProps<Props>();\n\nconst appName = 'rotki';\nconst emptyLinks: () => ExternalLinks = () => ({\n app: undefined,\n website: undefined,\n about: undefined,\n emptyScreen: undefined,\n});\n\nconst error = ref<boolean>(false);\nconst seasonalReady = ref<boolean>(false);\nconst externalSources = ref<ExternalLinks>(emptyLinks());\n\nconst customImageRef = useTemplateRef<HTMLImageElement>('customImageRef');\n\n// Synchronously hydrate from sessionStorage so the URL is available immediately on refresh\nif (isClient && logo && !src) {\n const cached = getCachedLogoSources(branch);\n if (cached)\n set(externalSources, cached);\n}\n\nfunction buildExternalUrl(sources: ExternalLinks): string | undefined {\n if (!logo || !sources[logo])\n return undefined;\n\n const url = `https://raw.githubusercontent.com/rotki/data/${branch}/assets/icons/${sources[logo]}`;\n\n if (uniqueKey !== undefined)\n return `${url}?key=${uniqueKey}`;\n\n return url;\n}\n\nconst externalSource = computed<string | undefined>(() => {\n if (src)\n return src;\n\n return buildExternalUrl(get(externalSources));\n});\n\nconst showCustom = computed<boolean>(() => !!src || (!!get(externalSource) && get(seasonalReady) && !get(error)));\n\n// If we have a previously verified URL that matches the current source, trust it immediately\nif (isClient && logo && !src) {\n const verifiedUrl = getVerifiedLogoUrl(branch, String(logo));\n const currentUrl = get(externalSource);\n if (verifiedUrl && currentUrl && verifiedUrl === currentUrl)\n set(seasonalReady, true);\n}\n\nfunction preloadImage(url: string): void {\n if (!isClient)\n return;\n\n const existing = document.head.querySelectorAll<HTMLLinkElement>('link[rel=\"preload\"][as=\"image\"]');\n for (const link of existing) {\n if (link.href === url)\n return;\n }\n\n const link = document.createElement('link');\n link.rel = 'preload';\n link.as = 'image';\n link.href = url;\n document.head.appendChild(link);\n}\n\n// Inject a preload hint for the seasonal image so the browser starts fetching early\nif (isClient && logo && !src) {\n const url = get(externalSource);\n if (url)\n preloadImage(url);\n}\n\nasync function fetchSources(): Promise<void> {\n if (!logo || src)\n return;\n\n const links = await getLogoSources(branch);\n\n if (links)\n set(externalSources, links);\n}\n\nfunction onImageError(): void {\n set(error, true);\n if (logo)\n removeVerifiedLogoUrl(branch, String(logo));\n}\n\nfunction onImageLoaded(): void {\n const img = get(customImageRef);\n if (!img)\n return;\n\n img.decode()\n .then(() => {\n set(seasonalReady, true);\n // Cache the verified URL so subsequent page loads can trust it immediately\n const url = get(externalSource);\n if (url && logo)\n setVerifiedLogoUrl(branch, String(logo), url);\n })\n .catch(() => set(error, true));\n}\n\nwatch(() => get(customImageRef)?.complete, (complete) => {\n if (complete)\n onImageLoaded();\n});\n\nwatchEffect(fetchSources);\n\nif (!isClient)\n useSSRContext();\n\nonServerPrefetch(async () => {\n await fetchSources();\n});\n</script>\n\n<template>\n <div\n class=\"gap-x-4 flex items-center relative\"\n :style=\"{ height: `${size}rem` }\"\n >\n <div\n class=\"relative\"\n :style=\"{ width: `${size}rem`, height: `${size}rem` }\"\n >\n <!-- Fallback: always in DOM, fades out when custom image is ready -->\n <img\n :src=\"fallback\"\n :alt=\"appName\"\n data-image=\"fallback\"\n class=\"absolute inset-0 h-full w-full transition ease-out duration-200\"\n :class=\"showCustom ? 'opacity-0' : 'opacity-100'\"\n />\n\n <!-- Custom/seasonal image: fades in when decoded -->\n <img\n v-if=\"externalSource && !error\"\n ref=\"customImageRef\"\n :src=\"externalSource\"\n :alt=\"appName\"\n data-image=\"custom\"\n class=\"absolute inset-0 h-full w-full transition ease-out duration-200\"\n :class=\"showCustom ? 'opacity-100' : 'opacity-0 pointer-events-none'\"\n @error=\"onImageError()\"\n @load=\"onImageLoaded()\"\n />\n </div>\n\n <div\n v-if=\"text\"\n class=\"text-h4 text-rui-primary dark:text-white\"\n >\n {{ appName }}\n </div>\n </div>\n</template>\n"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ExternalLinks } from '
|
|
1
|
+
import type { ExternalLinks } from './RuiLogo.vue';
|
|
2
2
|
/**
|
|
3
3
|
* Returns cached logo sources synchronously from sessionStorage.
|
|
4
4
|
* Returns undefined if nothing is cached or sessionStorage is unavailable.
|
|
@@ -3,6 +3,10 @@ import { transformCase } from "../../utils/helpers.js";
|
|
|
3
3
|
var ASSET_MAPPINGS_URL = "https://raw.githubusercontent.com/rotki/data";
|
|
4
4
|
var SESSION_SOURCES_PREFIX = "rui-logo-sources";
|
|
5
5
|
var SESSION_VERIFIED_PREFIX = "rui-logo-verified";
|
|
6
|
+
/**
|
|
7
|
+
* Deduplicates asset-mappings fetches across every RuiLogo, keyed by branch so
|
|
8
|
+
* two branches never share stale data.
|
|
9
|
+
*/
|
|
6
10
|
var sourcesCache = /* @__PURE__ */ new Map();
|
|
7
11
|
function isExternalLinks(value) {
|
|
8
12
|
if (typeof value !== "object" || value === null) return false;
|
|
@@ -58,7 +62,8 @@ async function fetchSourcesFromNetwork(branch) {
|
|
|
58
62
|
try {
|
|
59
63
|
const response = await fetch(`${ASSET_MAPPINGS_URL}/${branch}/constants/asset-mappings.json`);
|
|
60
64
|
if (!response.ok) return void 0;
|
|
61
|
-
const
|
|
65
|
+
const json = await response.json();
|
|
66
|
+
const links = transformCase(json?.logo, "camelCase");
|
|
62
67
|
if (isExternalLinks(links)) {
|
|
63
68
|
writeSessionStorage(`${SESSION_SOURCES_PREFIX}:${branch}`, JSON.stringify(links));
|
|
64
69
|
return links;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-logo-sources.js","names":[],"sources":["../../../src/components/logos/use-logo-sources.ts"],"sourcesContent":["import type { ExternalLinks } from '@/components/logos/RuiLogo.vue';\nimport { transformCase } from '@/utils/helpers';\n\nconst ASSET_MAPPINGS_URL = 'https://raw.githubusercontent.com/rotki/data';\nconst SESSION_SOURCES_PREFIX = 'rui-logo-sources';\nconst SESSION_VERIFIED_PREFIX = 'rui-logo-verified';\n\n
|
|
1
|
+
{"version":3,"file":"use-logo-sources.js","names":[],"sources":["../../../src/components/logos/use-logo-sources.ts"],"sourcesContent":["import type { ExternalLinks } from '@/components/logos/RuiLogo.vue';\nimport { transformCase } from '@/utils/helpers';\n\nconst ASSET_MAPPINGS_URL = 'https://raw.githubusercontent.com/rotki/data';\nconst SESSION_SOURCES_PREFIX = 'rui-logo-sources';\nconst SESSION_VERIFIED_PREFIX = 'rui-logo-verified';\n\n/**\n * Deduplicates asset-mappings fetches across every RuiLogo, keyed by branch so\n * two branches never share stale data.\n */\nconst sourcesCache = new Map<string, Promise<ExternalLinks | undefined>>();\n\nfunction isExternalLinks(value: unknown): value is ExternalLinks {\n if (typeof value !== 'object' || value === null)\n return false;\n\n return Object.values(value).every(v => v === undefined || typeof v === 'string');\n}\n\nfunction writeSessionStorage(key: string, value: string): void {\n try {\n sessionStorage.setItem(key, value);\n }\n catch {\n // sessionStorage may be full or unavailable\n }\n}\n\nfunction readSessionStorage(key: string): string | undefined {\n try {\n return sessionStorage.getItem(key) ?? undefined;\n }\n catch {\n return undefined;\n }\n}\n\nfunction clearSessionStorage(prefix: string): void {\n try {\n const keysToRemove: string[] = [];\n for (let i = 0; i < sessionStorage.length; i++) {\n const key = sessionStorage.key(i);\n if (key?.startsWith(prefix))\n keysToRemove.push(key);\n }\n keysToRemove.forEach(key => sessionStorage.removeItem(key));\n }\n catch {\n // sessionStorage may be unavailable\n }\n}\n\n/**\n * Returns cached logo sources synchronously from sessionStorage.\n * Returns undefined if nothing is cached or sessionStorage is unavailable.\n */\nexport function getCachedLogoSources(branch: string): ExternalLinks | undefined {\n const raw = readSessionStorage(`${SESSION_SOURCES_PREFIX}:${branch}`);\n if (!raw)\n return undefined;\n\n try {\n const parsed: unknown = JSON.parse(raw);\n if (isExternalLinks(parsed))\n return parsed;\n }\n catch {\n // Invalid JSON, ignore\n }\n return undefined;\n}\n\n/**\n * Returns a previously verified (successfully decoded) seasonal logo URL\n * for the given branch and logo type from sessionStorage.\n */\nexport function getVerifiedLogoUrl(branch: string, logo: string): string | undefined {\n return readSessionStorage(`${SESSION_VERIFIED_PREFIX}:${branch}:${logo}`);\n}\n\n/**\n * Stores a verified seasonal logo URL in sessionStorage after successful decode.\n */\nexport function setVerifiedLogoUrl(branch: string, logo: string, url: string): void {\n writeSessionStorage(`${SESSION_VERIFIED_PREFIX}:${branch}:${logo}`, url);\n}\n\n/**\n * Removes a previously verified seasonal logo URL from sessionStorage.\n * Called when an image fails to load so stale entries aren't trusted on next load.\n */\nexport function removeVerifiedLogoUrl(branch: string, logo: string): void {\n try {\n sessionStorage.removeItem(`${SESSION_VERIFIED_PREFIX}:${branch}:${logo}`);\n }\n catch {\n // sessionStorage may be unavailable\n }\n}\n\nasync function fetchSourcesFromNetwork(branch: string): Promise<ExternalLinks | undefined> {\n try {\n const response = await fetch(\n `${ASSET_MAPPINGS_URL}/${branch}/constants/asset-mappings.json`,\n );\n\n if (!response.ok)\n return undefined;\n\n const json = await response.json();\n const links = transformCase(json?.logo, 'camelCase');\n if (isExternalLinks(links)) {\n writeSessionStorage(`${SESSION_SOURCES_PREFIX}:${branch}`, JSON.stringify(links));\n return links;\n }\n\n return undefined;\n }\n catch {\n return undefined;\n }\n}\n\n/**\n * Fetches external logo sources for a given branch, deduplicating concurrent requests.\n * Uses a module-level cache so all RuiLogo instances share a single fetch per branch.\n */\nexport function getLogoSources(branch: string): Promise<ExternalLinks | undefined> {\n const cached = sourcesCache.get(branch);\n if (cached)\n return cached;\n\n const promise = fetchSourcesFromNetwork(branch);\n sourcesCache.set(branch, promise);\n return promise;\n}\n\n/**\n * Clears the module-level cache and sessionStorage entries. Exposed for testing only.\n */\nexport function clearLogoSourcesCache(): void {\n sourcesCache.clear();\n clearSessionStorage(SESSION_SOURCES_PREFIX);\n clearSessionStorage(SESSION_VERIFIED_PREFIX);\n}\n"],"mappings":";;AAGA,IAAM,qBAAqB;AAC3B,IAAM,yBAAyB;AAC/B,IAAM,0BAA0B;;;;;AAMhC,IAAM,+BAAe,IAAI,IAAgD;AAEzE,SAAS,gBAAgB,OAAwC;CAC/D,IAAI,OAAO,UAAU,YAAY,UAAU,MACzC,OAAO;CAET,OAAO,OAAO,OAAO,KAAK,CAAC,CAAC,OAAM,MAAK,MAAM,KAAA,KAAa,OAAO,MAAM,QAAQ;AACjF;AAEA,SAAS,oBAAoB,KAAa,OAAqB;CAC7D,IAAI;EACF,eAAe,QAAQ,KAAK,KAAK;CACnC,QACM,CAEN;AACF;AAEA,SAAS,mBAAmB,KAAiC;CAC3D,IAAI;EACF,OAAO,eAAe,QAAQ,GAAG,KAAK,KAAA;CACxC,QACM;EACJ;CACF;AACF;;;;;AAqBA,SAAgB,qBAAqB,QAA2C;CAC9E,MAAM,MAAM,mBAAmB,GAAG,uBAAuB,GAAG,QAAQ;CACpE,IAAI,CAAC,KACH,OAAO,KAAA;CAET,IAAI;EACF,MAAM,SAAkB,KAAK,MAAM,GAAG;EACtC,IAAI,gBAAgB,MAAM,GACxB,OAAO;CACX,QACM,CAEN;AAEF;;;;;AAMA,SAAgB,mBAAmB,QAAgB,MAAkC;CACnF,OAAO,mBAAmB,GAAG,wBAAwB,GAAG,OAAO,GAAG,MAAM;AAC1E;;;;AAKA,SAAgB,mBAAmB,QAAgB,MAAc,KAAmB;CAClF,oBAAoB,GAAG,wBAAwB,GAAG,OAAO,GAAG,QAAQ,GAAG;AACzE;;;;;AAMA,SAAgB,sBAAsB,QAAgB,MAAoB;CACxE,IAAI;EACF,eAAe,WAAW,GAAG,wBAAwB,GAAG,OAAO,GAAG,MAAM;CAC1E,QACM,CAEN;AACF;AAEA,eAAe,wBAAwB,QAAoD;CACzF,IAAI;EACF,MAAM,WAAW,MAAM,MACrB,GAAG,mBAAmB,GAAG,OAAO,+BAClC;EAEA,IAAI,CAAC,SAAS,IACZ,OAAO,KAAA;EAET,MAAM,OAAO,MAAM,SAAS,KAAK;EACjC,MAAM,QAAQ,cAAc,MAAM,MAAM,WAAW;EACnD,IAAI,gBAAgB,KAAK,GAAG;GAC1B,oBAAoB,GAAG,uBAAuB,GAAG,UAAU,KAAK,UAAU,KAAK,CAAC;GAChF,OAAO;EACT;EAEA;CACF,QACM;EACJ;CACF;AACF;;;;;AAMA,SAAgB,eAAe,QAAoD;CACjF,MAAM,SAAS,aAAa,IAAI,MAAM;CACtC,IAAI,QACF,OAAO;CAET,MAAM,UAAU,wBAAwB,MAAM;CAC9C,aAAa,IAAI,QAAQ,OAAO;CAChC,OAAO;AACT"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { ContextColorsType } from '../../../consts/colors.js';
|
|
2
2
|
import type { RuiIcons } from '../../../icons/index.js';
|
|
3
|
-
import { BadgePlacement, BadgeRounded, BadgeSize } from '
|
|
3
|
+
import { BadgePlacement, BadgeRounded, BadgeSize } from './badge-props.js';
|
|
4
4
|
export interface Props {
|
|
5
5
|
text?: string | null;
|
|
6
6
|
icon?: RuiIcons | null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RuiBadge.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../../src/components/overlays/badge/RuiBadge.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { ContextColorsType } from '@/consts/colors';\nimport type { RuiIcons } from '@/icons';\nimport RuiIcon from '@/components/icons/RuiIcon.vue';\nimport { BadgePlacement, BadgeRounded, BadgeSize } from '@/components/overlays/badge/badge-props';\nimport { tv } from '@/utils/tv';\n\ntype PosConfig = [left: number, right: string, edge: string, center: number];\n\nexport interface Props {\n text?: string | null;\n icon?: RuiIcons | null;\n modelValue?: boolean;\n dot?: boolean;\n left?: boolean;\n offsetX?: string | number;\n offsetY?: string | number;\n placement?: BadgePlacement;\n size?: BadgeSize;\n rounded?: BadgeRounded;\n color?: 'default' | ContextColorsType;\n}\n\ndefineOptions({\n name: 'RuiBadge',\n});\n\nconst {\n text = null,\n icon = null,\n modelValue = true,\n dot = false,\n placement = BadgePlacement.top,\n left = false,\n size = BadgeSize.md,\n rounded = BadgeRounded.full,\n color = 'primary',\n offsetX = 0,\n offsetY = 0,\n} = defineProps<Props>();\n\nconst slots = defineSlots<{\n default?: () => any;\n badge?: () => any;\n icon?: () => any;\n}>();\n\nconst badgeStyles = tv({\n slots: {\n wrapper: 'relative inline-block',\n badge: 'flex items-center justify-center text-xs font-medium absolute bg-transparent text-rui-light-text dark:text-rui-text',\n content: 'flex items-center px-1.5',\n },\n variants: {\n color: {\n default: {},\n primary: { badge: 'text-white bg-rui-primary' },\n secondary: { badge: 'text-white bg-rui-secondary' },\n error: { badge: 'text-white bg-rui-error' },\n warning: { badge: 'text-white bg-rui-warning' },\n info: { badge: 'text-white bg-rui-info' },\n success: { badge: 'text-white bg-rui-success' },\n },\n size: {\n sm: { badge: 'min-h-4 min-w-4' },\n md: { badge: 'min-h-5 min-w-5' },\n lg: { badge: 'min-h-6 min-w-6' },\n },\n rounded: {\n sm: { badge: 'rounded-sm' },\n md: { badge: 'rounded-md' },\n lg: { badge: 'rounded-lg' },\n full: { badge: 'rounded-full' },\n },\n dot: {\n true: {},\n },\n },\n compoundVariants: [\n // Dot default color\n { dot: true, color: 'default', class: { badge: 'bg-gray-500' } },\n\n // Dot sizes (smaller than normal badge)\n { dot: true, size: 'sm', class: { badge: 'min-w-1.5 min-h-1.5' } },\n { dot: true, size: 'md', class: { badge: 'min-w-2 min-h-2' } },\n { dot: true, size: 'lg', class: { badge: 'min-w-2.5 min-h-2.5' } },\n ],\n compoundSlots: [\n // Dark mode: warning/success/info keep light text on colored bg\n { slots: ['badge'], color: ['warning', 'success', 'info'], class: 'dark:text-rui-light-text' },\n ],\n defaultVariants: {\n color: 'primary',\n size: 'md',\n rounded: 'full',\n dot: false,\n },\n});\n\nconst hasText = computed<boolean>(() => !!text || !!slots.badge);\n\nconst hasIconAndText = computed<boolean>(() => (!!icon || !!slots.icon) && get(hasText));\n\nconst ui = computed<ReturnType<typeof badgeStyles>>(() => badgeStyles({\n color,\n size,\n rounded,\n dot,\n}));\n\n// Position configs: [leftOffset, rightBase, edgeBase, centerOffset] (rem / calc expressions)\nconst DOT_POS: PosConfig = [-0.25, '100% - 0.25rem', '100% - 0.25rem', 0.25];\nconst BADGE_POS: Record<BadgeSize, PosConfig> = {\n sm: [-0.85, '100% - 0.375rem', '100% - 0.375rem', 0.55],\n md: [-0.95, '100% - 0.5rem', '100% - 0.5rem', 0.65],\n lg: [-1.05, '100% - 0.5rem', '100% - 0.5rem', 0.75],\n};\n\nconst positionStyle = computed<Record<string, string>>(() => {\n const ox = Number(offsetX) * 0.0625;\n const oy = Number(offsetY) * 0.0625;\n const [l, r, edge, center] = dot ? DOT_POS : BADGE_POS[size];\n\n const horizontal = `calc(${left ? `${l}rem` : r} + ${ox}rem)`;\n const vertical = placement === 'center'\n ? `calc(50% - ${center}rem - ${oy}rem)`\n : `calc(${edge} - ${oy}rem)`;\n\n return {\n left: horizontal,\n [placement === 'top' ? 'bottom' : 'top']: vertical,\n };\n});\n</script>\n\n<template>\n <div :class=\"ui.wrapper()\">\n <slot />\n <Transition\n appear\n enter-active-class=\"transform ease-out duration-200\"\n enter-from-class=\"scale-0\"\n enter-to-class=\"scale-100\"\n leave-active-class=\"transform ease-in duration-150\"\n leave-from-class=\"scale-100\"\n leave-to-class=\"scale-0\"\n >\n <div\n v-if=\"modelValue\"\n :class=\"ui.badge()\"\n :style=\"positionStyle\"\n :data-placement=\"placement\"\n :data-dot=\"dot || undefined\"\n :data-left=\"left || undefined\"\n aria-atomic=\"true\"\n aria-label=\"Badge\"\n aria-live=\"polite\"\n role=\"status\"\n >\n <span\n v-if=\"!dot\"\n :class=\"ui.content({ class: hasIconAndText ? 'px-2.5' : undefined })\"\n >\n <slot name=\"badge\">\n {{ text }}\n </slot>\n <slot name=\"icon\">\n <RuiIcon\n v-if=\"icon\"\n :name=\"icon\"\n size=\"16\"\n :class=\"{ 'ml-0.5': hasText }\"\n />\n </slot>\n </span>\n </div>\n </Transition>\n </div>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAyCA,MAAM,QAAQ,SAAA;EAMd,MAAM,cAAc,GAAG;GACrB,OAAO;IACL,SAAS;IACT,OAAO;IACP,SAAS;GACX;GACA,UAAU;IACR,OAAO;KACL,SAAS,CAAC;KACV,SAAS,EAAE,OAAO,4BAA4B;KAC9C,WAAW,EAAE,OAAO,8BAA8B;KAClD,OAAO,EAAE,OAAO,0BAA0B;KAC1C,SAAS,EAAE,OAAO,4BAA4B;KAC9C,MAAM,EAAE,OAAO,yBAAyB;KACxC,SAAS,EAAE,OAAO,4BAA4B;IAChD;IACA,MAAM;KACJ,IAAI,EAAE,OAAO,kBAAkB;KAC/B,IAAI,EAAE,OAAO,kBAAkB;KAC/B,IAAI,EAAE,OAAO,kBAAkB;IACjC;IACA,SAAS;KACP,IAAI,EAAE,OAAO,aAAa;KAC1B,IAAI,EAAE,OAAO,aAAa;KAC1B,IAAI,EAAE,OAAO,aAAa;KAC1B,MAAM,EAAE,OAAO,eAAe;IAChC;IACA,KAAK,EACH,MAAM,CAAC,EACT;GACF;GACA,kBAAkB;IAEhB;KAAE,KAAK;KAAM,OAAO;KAAW,OAAO,EAAE,OAAO,cAAc;IAAE;IAG/D;KAAE,KAAK;KAAM,MAAM;KAAM,OAAO,EAAE,OAAO,sBAAsB;IAAE;IACjE;KAAE,KAAK;KAAM,MAAM;KAAM,OAAO,EAAE,OAAO,kBAAkB;IAAE;IAC7D;KAAE,KAAK;KAAM,MAAM;KAAM,OAAO,EAAE,OAAO,sBAAsB;IAAE;GACnE;GACA,eAAe,CAEb;IAAE,OAAO,CAAC,OAAO;IAAG,OAAO;KAAC;KAAW;KAAW;IAAM;IAAG,OAAO;GAA2B,CAC/F;GACA,iBAAiB;IACf,OAAO;IACP,MAAM;IACN,SAAS;IACT,KAAK;GACP;EACF,CAAC;EAED,MAAM,UAAU,eAAwB,CAAC,CAAC,QAAA,QAAQ,CAAC,CAAC,MAAM,KAAK;EAE/D,MAAM,iBAAiB,gBAAyB,CAAC,CAAC,QAAA,QAAQ,CAAC,CAAC,MAAM,SAAS,IAAI,OAAO,CAAC;EAEvF,MAAM,KAAK,eAA+C,YAAY;GACpE,OAAI,QAAA;GACJ,MAAG,QAAA;GACH,SAAM,QAAA;GACN,KAAE,QAAA;EACJ,CAAC,CAAC;EAGF,MAAM,UAAqB;GAAC;GAAO;GAAkB;GAAkB;EAAI;EAC3E,MAAM,YAA0C;GAC9C,IAAI;IAAC;IAAO;IAAmB;IAAmB;GAAI;GACtD,IAAI;IAAC;IAAO;IAAiB;IAAiB;GAAI;GAClD,IAAI;IAAC;IAAO;IAAiB;IAAiB;GAAI;EACpD;EAEA,MAAM,gBAAgB,eAAuC;GAC3D,MAAM,KAAK,OAAO,QAAA,OAAO,IAAI;GAC7B,MAAM,KAAK,OAAO,QAAA,OAAO,IAAI;GAC7B,MAAM,CAAC,GAAG,GAAG,MAAM,UAAU,QAAA,MAAM,UAAU,UAAU,QAAA;GAEvD,MAAM,aAAa,QAAQ,QAAA,OAAO,GAAG,EAAE,OAAO,EAAE,KAAK,GAAG;GACxD,MAAM,WAAW,QAAA,cAAc,WAC3B,cAAc,OAAO,QAAQ,GAAG,QAChC,QAAQ,KAAK,KAAK,GAAG;GAEzB,OAAO;IACL,MAAM;KACL,QAAA,cAAc,QAAQ,WAAW,QAAQ;GAC5C;EACF,CAAC;;
|
|
1
|
+
{"version":3,"file":"RuiBadge.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../../src/components/overlays/badge/RuiBadge.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { ContextColorsType } from '@/consts/colors';\nimport type { RuiIcons } from '@/icons';\nimport RuiIcon from '@/components/icons/RuiIcon.vue';\nimport { BadgePlacement, BadgeRounded, BadgeSize } from '@/components/overlays/badge/badge-props';\nimport { tv } from '@/utils/tv';\n\ntype PosConfig = [left: number, right: string, edge: string, center: number];\n\nexport interface Props {\n text?: string | null;\n icon?: RuiIcons | null;\n modelValue?: boolean;\n dot?: boolean;\n left?: boolean;\n offsetX?: string | number;\n offsetY?: string | number;\n placement?: BadgePlacement;\n size?: BadgeSize;\n rounded?: BadgeRounded;\n color?: 'default' | ContextColorsType;\n}\n\ndefineOptions({\n name: 'RuiBadge',\n});\n\nconst {\n text = null,\n icon = null,\n modelValue = true,\n dot = false,\n placement = BadgePlacement.top,\n left = false,\n size = BadgeSize.md,\n rounded = BadgeRounded.full,\n color = 'primary',\n offsetX = 0,\n offsetY = 0,\n} = defineProps<Props>();\n\nconst slots = defineSlots<{\n default?: () => any;\n badge?: () => any;\n icon?: () => any;\n}>();\n\nconst badgeStyles = tv({\n slots: {\n wrapper: 'relative inline-block',\n badge: 'flex items-center justify-center text-xs font-medium absolute bg-transparent text-rui-light-text dark:text-rui-text',\n content: 'flex items-center px-1.5',\n },\n variants: {\n color: {\n default: {},\n primary: { badge: 'text-white bg-rui-primary' },\n secondary: { badge: 'text-white bg-rui-secondary' },\n error: { badge: 'text-white bg-rui-error' },\n warning: { badge: 'text-white bg-rui-warning' },\n info: { badge: 'text-white bg-rui-info' },\n success: { badge: 'text-white bg-rui-success' },\n },\n size: {\n sm: { badge: 'min-h-4 min-w-4' },\n md: { badge: 'min-h-5 min-w-5' },\n lg: { badge: 'min-h-6 min-w-6' },\n },\n rounded: {\n sm: { badge: 'rounded-sm' },\n md: { badge: 'rounded-md' },\n lg: { badge: 'rounded-lg' },\n full: { badge: 'rounded-full' },\n },\n dot: {\n true: {},\n },\n },\n compoundVariants: [\n // Dot default color\n { dot: true, color: 'default', class: { badge: 'bg-gray-500' } },\n\n // Dot sizes (smaller than normal badge)\n { dot: true, size: 'sm', class: { badge: 'min-w-1.5 min-h-1.5' } },\n { dot: true, size: 'md', class: { badge: 'min-w-2 min-h-2' } },\n { dot: true, size: 'lg', class: { badge: 'min-w-2.5 min-h-2.5' } },\n ],\n compoundSlots: [\n // Dark mode: warning/success/info keep light text on colored bg\n { slots: ['badge'], color: ['warning', 'success', 'info'], class: 'dark:text-rui-light-text' },\n ],\n defaultVariants: {\n color: 'primary',\n size: 'md',\n rounded: 'full',\n dot: false,\n },\n});\n\nconst hasText = computed<boolean>(() => !!text || !!slots.badge);\n\nconst hasIconAndText = computed<boolean>(() => (!!icon || !!slots.icon) && get(hasText));\n\nconst ui = computed<ReturnType<typeof badgeStyles>>(() => badgeStyles({\n color,\n size,\n rounded,\n dot,\n}));\n\n// Position configs: [leftOffset, rightBase, edgeBase, centerOffset] (rem / calc expressions)\nconst DOT_POS: PosConfig = [-0.25, '100% - 0.25rem', '100% - 0.25rem', 0.25];\nconst BADGE_POS: Record<BadgeSize, PosConfig> = {\n sm: [-0.85, '100% - 0.375rem', '100% - 0.375rem', 0.55],\n md: [-0.95, '100% - 0.5rem', '100% - 0.5rem', 0.65],\n lg: [-1.05, '100% - 0.5rem', '100% - 0.5rem', 0.75],\n};\n\nconst positionStyle = computed<Record<string, string>>(() => {\n const ox = Number(offsetX) * 0.0625;\n const oy = Number(offsetY) * 0.0625;\n const [l, r, edge, center] = dot ? DOT_POS : BADGE_POS[size];\n\n const horizontal = `calc(${left ? `${l}rem` : r} + ${ox}rem)`;\n const vertical = placement === 'center'\n ? `calc(50% - ${center}rem - ${oy}rem)`\n : `calc(${edge} - ${oy}rem)`;\n\n return {\n left: horizontal,\n [placement === 'top' ? 'bottom' : 'top']: vertical,\n };\n});\n</script>\n\n<template>\n <div :class=\"ui.wrapper()\">\n <slot />\n <Transition\n appear\n enter-active-class=\"transform ease-out duration-200\"\n enter-from-class=\"scale-0\"\n enter-to-class=\"scale-100\"\n leave-active-class=\"transform ease-in duration-150\"\n leave-from-class=\"scale-100\"\n leave-to-class=\"scale-0\"\n >\n <div\n v-if=\"modelValue\"\n :class=\"ui.badge()\"\n :style=\"positionStyle\"\n :data-placement=\"placement\"\n :data-dot=\"dot || undefined\"\n :data-left=\"left || undefined\"\n aria-atomic=\"true\"\n aria-label=\"Badge\"\n aria-live=\"polite\"\n role=\"status\"\n >\n <span\n v-if=\"!dot\"\n :class=\"ui.content({ class: hasIconAndText ? 'px-2.5' : undefined })\"\n >\n <slot name=\"badge\">\n {{ text }}\n </slot>\n <slot name=\"icon\">\n <RuiIcon\n v-if=\"icon\"\n :name=\"icon\"\n size=\"16\"\n :class=\"{ 'ml-0.5': hasText }\"\n />\n </slot>\n </span>\n </div>\n </Transition>\n </div>\n</template>\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RuiBottomSheet.js","names":[],"sources":["../../../../src/components/overlays/bottom-sheet/RuiBottomSheet.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport RuiDialog from '@/components/overlays/dialog/RuiDialog.vue';\n\n
|
|
1
|
+
{"version":3,"file":"RuiBottomSheet.js","names":[],"sources":["../../../../src/components/overlays/bottom-sheet/RuiBottomSheet.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport RuiDialog from '@/components/overlays/dialog/RuiDialog.vue';\n\n/** The sheet's props, which stay in step with RuiDialog's. */\nexport interface BottomSheetProps {\n persistent?: boolean;\n width?: string | number;\n maxWidth?: string | number;\n}\n\ndefineOptions({\n name: 'RuiBottomSheet',\n inheritAttrs: false,\n});\n\nconst modelValue = defineModel<boolean>({ default: false });\n\nconst { persistent = false, width, maxWidth } = defineProps<BottomSheetProps>();\n</script>\n\n<template>\n <RuiDialog\n v-model=\"modelValue\"\n bottom-sheet\n v-bind=\"$attrs\"\n :persistent=\"persistent\"\n :width=\"width\"\n :max-width=\"maxWidth\"\n >\n <template\n v-for=\"slot in Object.keys($slots)\"\n #[slot]=\"scope\"\n >\n <slot\n v-bind=\"scope\"\n :name=\"slot\"\n />\n </template>\n </RuiDialog>\n</template>\n"],"mappings":""}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RuiBottomSheet.vue_vue_type_script_setup_true_lang.js","names":["$attrs","$slots"],"sources":["../../../../src/components/overlays/bottom-sheet/RuiBottomSheet.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport RuiDialog from '@/components/overlays/dialog/RuiDialog.vue';\n\n
|
|
1
|
+
{"version":3,"file":"RuiBottomSheet.vue_vue_type_script_setup_true_lang.js","names":["$attrs","$slots"],"sources":["../../../../src/components/overlays/bottom-sheet/RuiBottomSheet.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport RuiDialog from '@/components/overlays/dialog/RuiDialog.vue';\n\n/** The sheet's props, which stay in step with RuiDialog's. */\nexport interface BottomSheetProps {\n persistent?: boolean;\n width?: string | number;\n maxWidth?: string | number;\n}\n\ndefineOptions({\n name: 'RuiBottomSheet',\n inheritAttrs: false,\n});\n\nconst modelValue = defineModel<boolean>({ default: false });\n\nconst { persistent = false, width, maxWidth } = defineProps<BottomSheetProps>();\n</script>\n\n<template>\n <RuiDialog\n v-model=\"modelValue\"\n bottom-sheet\n v-bind=\"$attrs\"\n :persistent=\"persistent\"\n :width=\"width\"\n :max-width=\"maxWidth\"\n >\n <template\n v-for=\"slot in Object.keys($slots)\"\n #[slot]=\"scope\"\n >\n <slot\n v-bind=\"scope\"\n :name=\"slot\"\n />\n </template>\n </RuiDialog>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;EAeA,MAAM,aAAa,SAAoB,SAAA,YAAmB;;GAMxD,OAAA,UAAA,GAAA,YAiBY,mBAjBZ,WAiBY;IAhBD,YAAA,WAAA;IAAA,uBAAA,OAAA,OAAA,OAAA,MAAA,WAAA,WAAU,QAAA;IACnB,gBAAA;GACQA,GAAAA,KAAAA,QAAM;IACb,YAAY,QAAA;IACZ,OAAO,QAAA;IACP,aAAW,QAAA;GAGK,CAAA,GAAA,YAAA,EAAA,GAAA,EAAA,GAAA,CAAA,WAAA,OAAO,KAAKC,KAAAA,MAAM,IAA1B,SAAI;;KACV,MAAA;KAED,IAAA,SAFS,UAAK,CAEd,WAGE,KAAA,QADO,MAAI,eAAA,mBADH,KAAK,CAAA,CAAA,CAAA,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RuiDialog.js","names":[],"sources":["../../../../src/components/overlays/dialog/RuiDialog.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { VueClassValue } from '@/types/class-value';\nimport { useTimeoutManager } from '@/composables/timeout-manager';\nimport { getNonRootAttrs, getRootAttrs, transformPropsUnit } from '@/utils/helpers';\nimport { cn, tv } from '@/utils/tv';\n\nexport interface RuiDialogClassNames {\n root?: VueClassValue;\n content?: VueClassValue;\n}\n\nexport interface DialogProps {\n persistent?: boolean;\n width?: string | number;\n maxWidth?: string | number;\n bottomSheet?: boolean;\n classNames?: RuiDialogClassNames;\n /** @deprecated Use `classNames.content` instead */\n contentClass?: string | string[] | Record<string, boolean>;\n zIndex?: string | number;\n ariaLabel?: string;\n}\n\ndefineOptions({\n name: 'RuiDialog',\n inheritAttrs: false,\n});\n\nconst modelValue = defineModel<boolean>({ default: false });\n\nconst {\n persistent = false,\n width = '98%',\n maxWidth,\n bottomSheet = false,\n classNames,\n contentClass = '',\n zIndex = 9999,\n ariaLabel,\n} = defineProps<DialogProps>();\n\nconst emit = defineEmits<{\n 'closed': [];\n 'click:outside': [];\n 'click:esc': [];\n}>();\n\ndefineSlots<{\n activator?: (props: { attrs: { onClick: () => void }; isOpen: boolean }) => any;\n default?: (props: { isOpen: boolean; close: () => void }) => any;\n}>();\n\nconst transitioning = ref<boolean>(false);\nconst contentRef = useTemplateRef<HTMLDivElement>('contentRef');\n\nconst leaveTimeout = useTimeoutManager();\n\nconst alive = computed<boolean>(() => get(modelValue) || get(transitioning));\n\nconst style = computed<{ width: string | undefined; maxWidth: string | undefined }>(() => ({\n width: transformPropsUnit(width),\n maxWidth: transformPropsUnit(maxWidth),\n}));\n\nconst dialog = tv({\n slots: {\n root: 'fixed inset-0',\n overlay: 'absolute inset-0 backdrop-blur bg-rui-grey-500/50 dark:bg-black/50',\n content: 'absolute left-1/2 bottom-0 -translate-x-1/2 outline-none overflow-y-auto max-h-[90vh]',\n },\n variants: {\n bottomSheet: {\n true: { content: '' },\n false: { content: 'top-1/2 -translate-y-1/2 bottom-auto' },\n },\n },\n defaultVariants: { bottomSheet: false },\n});\n\nconst ui = computed<ReturnType<typeof dialog>>(() => dialog({ bottomSheet }));\n\nconst dialogAttrs: { onClick: () => void } = {\n onClick: toggle,\n};\n\nconst contentTransition = computed<Record<string, string>>(() => {\n if (!bottomSheet) {\n return {\n enterFromClass: 'opacity-0 scale-95',\n enterActiveClass: 'transition-all ease-out duration-200',\n enterToClass: 'opacity-100 scale-100',\n leaveFromClass: 'opacity-100 scale-100',\n leaveActiveClass: 'transition-all ease-in duration-150',\n leaveToClass: 'opacity-0 scale-95',\n };\n }\n\n return {\n enterFromClass: 'translate-y-full',\n enterActiveClass: 'transition-transform ease-out duration-300',\n enterToClass: 'translate-y-0',\n leaveFromClass: 'translate-y-0',\n leaveActiveClass: 'transition-transform ease-in duration-200',\n leaveToClass: 'translate-y-full',\n };\n});\n\nfunction toggle(): void {\n set(modelValue, !get(modelValue));\n}\n\nfunction close(): void {\n set(modelValue, false);\n}\n\nfunction onEscClick(): void {\n if (!persistent) {\n close();\n }\n emit('click:esc');\n}\n\nfunction onClickOutside(): void {\n if (!persistent) {\n close();\n }\n emit('click:outside');\n}\n\nfunction onLeaveComplete(): void {\n leaveTimeout.clear();\n if (get(transitioning)) {\n set(transitioning, false);\n emit('closed');\n }\n}\n\nwatch(modelValue, (value) => {\n if (!value) {\n set(transitioning, true);\n // Safety fallback if transitionend is not detected\n leaveTimeout.create(onLeaveComplete, 400);\n }\n});\n\nwatch(contentRef, (ref) => {\n if (ref) {\n nextTick(() => ref.focus());\n }\n else {\n onLeaveComplete();\n }\n});\n</script>\n\n<template>\n <div v-bind=\"getRootAttrs($attrs)\">\n <slot\n name=\"activator\"\n v-bind=\"{ attrs: dialogAttrs, isOpen: modelValue }\"\n />\n <Teleport to=\"body\">\n <div\n v-if=\"alive\"\n :class=\"ui.root({ class: cn(classNames?.root) })\"\n :style=\"{ zIndex }\"\n role=\"dialog\"\n aria-modal=\"true\"\n :aria-label=\"ariaLabel\"\n tabindex=\"0\"\n v-bind=\"getNonRootAttrs($attrs)\"\n @keydown.esc.stop=\"onEscClick()\"\n >\n <Transition\n enter-from-class=\"opacity-0\"\n enter-active-class=\"transition-opacity ease-out duration-200\"\n enter-to-class=\"opacity-100\"\n leave-from-class=\"opacity-100\"\n leave-active-class=\"transition-opacity ease-in duration-150\"\n leave-to-class=\"opacity-0\"\n >\n <div\n v-if=\"modelValue\"\n data-id=\"overlay\"\n :class=\"ui.overlay()\"\n @click.stop=\"onClickOutside()\"\n />\n </Transition>\n <Transition\n v-bind=\"contentTransition\"\n @after-leave=\"onLeaveComplete()\"\n >\n <div\n v-if=\"modelValue\"\n ref=\"contentRef\"\n data-id=\"content\"\n :style=\"style\"\n tabindex=\"0\"\n :data-bottom-sheet=\"bottomSheet || undefined\"\n :class=\"ui.content({ class: cn(classNames?.content) ?? cn(contentClass) })\"\n >\n <slot v-bind=\"{ isOpen: modelValue, close }\" />\n </div>\n </Transition>\n </div>\n </Teleport>\n </div>\n</template>\n"],"mappings":""}
|
|
1
|
+
{"version":3,"file":"RuiDialog.js","names":[],"sources":["../../../../src/components/overlays/dialog/RuiDialog.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { VueClassValue } from '@/types/class-value';\nimport { useDismissableOverlay } from '@/composables/overlay-stack';\nimport { useTimeoutManager } from '@/composables/timeout-manager';\nimport { getNonRootAttrs, getRootAttrs, transformPropsUnit } from '@/utils/helpers';\nimport { cn, tv } from '@/utils/tv';\n\nexport interface RuiDialogClassNames {\n root?: VueClassValue;\n content?: VueClassValue;\n}\n\nexport interface DialogProps {\n persistent?: boolean;\n width?: string | number;\n maxWidth?: string | number;\n bottomSheet?: boolean;\n classNames?: RuiDialogClassNames;\n /** @deprecated Use `classNames.content` instead */\n contentClass?: string | string[] | Record<string, boolean>;\n zIndex?: string | number;\n ariaLabel?: string;\n}\n\ndefineOptions({\n name: 'RuiDialog',\n inheritAttrs: false,\n});\n\nconst modelValue = defineModel<boolean>({ default: false });\n\nconst {\n persistent = false,\n width = '98%',\n maxWidth,\n bottomSheet = false,\n classNames,\n contentClass = '',\n zIndex = 9999,\n ariaLabel,\n} = defineProps<DialogProps>();\n\nconst emit = defineEmits<{\n 'closed': [];\n 'click:outside': [];\n 'click:esc': [];\n /**\n * The overlay stack asked this dialog to go, which is what a back gesture\n * reaches it as. Closes unless persistent, like escape does, so a dialog that\n * has to ask before discarding should bind `persistent` and answer here.\n */\n 'dismiss': [];\n}>();\n\ndefineSlots<{\n activator?: (props: { attrs: { onClick: () => void }; isOpen: boolean }) => any;\n default?: (props: { isOpen: boolean; close: () => void }) => any;\n}>();\n\nconst transitioning = ref<boolean>(false);\nconst contentRef = useTemplateRef<HTMLDivElement>('contentRef');\n\nconst leaveTimeout = useTimeoutManager();\n\nconst alive = computed<boolean>(() => get(modelValue) || get(transitioning));\n\nconst style = computed<{ width: string | undefined; maxWidth: string | undefined }>(() => ({\n width: transformPropsUnit(width),\n maxWidth: transformPropsUnit(maxWidth),\n}));\n\nconst dialog = tv({\n slots: {\n root: 'fixed inset-0',\n overlay: 'absolute inset-0 backdrop-blur bg-rui-grey-500/50 dark:bg-black/50',\n content: 'absolute left-1/2 bottom-0 -translate-x-1/2 outline-none overflow-y-auto max-h-[90vh]',\n },\n variants: {\n bottomSheet: {\n true: { content: '' },\n false: { content: 'top-1/2 -translate-y-1/2 bottom-auto' },\n },\n },\n defaultVariants: { bottomSheet: false },\n});\n\nconst ui = computed<ReturnType<typeof dialog>>(() => dialog({ bottomSheet }));\n\nconst dialogAttrs: { onClick: () => void } = {\n onClick: toggle,\n};\n\nconst contentTransition = computed<Record<string, string>>(() => {\n if (!bottomSheet) {\n return {\n enterFromClass: 'opacity-0 scale-95',\n enterActiveClass: 'transition-all ease-out duration-200',\n enterToClass: 'opacity-100 scale-100',\n leaveFromClass: 'opacity-100 scale-100',\n leaveActiveClass: 'transition-all ease-in duration-150',\n leaveToClass: 'opacity-0 scale-95',\n };\n }\n\n return {\n enterFromClass: 'translate-y-full',\n enterActiveClass: 'transition-transform ease-out duration-300',\n enterToClass: 'translate-y-0',\n leaveFromClass: 'translate-y-0',\n leaveActiveClass: 'transition-transform ease-in duration-200',\n leaveToClass: 'translate-y-full',\n };\n});\n\nfunction toggle(): void {\n set(modelValue, !get(modelValue));\n}\n\nfunction close(): void {\n set(modelValue, false);\n}\n\nfunction onEscClick(): void {\n if (!persistent) {\n close();\n }\n emit('click:esc');\n}\n\nfunction onClickOutside(): void {\n if (!persistent) {\n close();\n }\n emit('click:outside');\n}\n\nfunction onDismiss(): void {\n if (!persistent) {\n close();\n }\n emit('dismiss');\n}\n\n/**\n * Registration follows `modelValue` alone, never `persistent`: a dialog that\n * turns persistent partway through its life has to stay in the stack and refuse\n * in `onDismiss`, or the gesture starts passing through exactly once there is\n * work to lose. A dialog playing its leave transition is already on its way out\n * and does not hold the stack.\n */\nuseDismissableOverlay(modelValue, onDismiss);\n\nfunction onLeaveComplete(): void {\n leaveTimeout.clear();\n if (get(transitioning)) {\n set(transitioning, false);\n emit('closed');\n }\n}\n\nwatch(modelValue, (value) => {\n if (!value) {\n set(transitioning, true);\n // Safety fallback if transitionend is not detected\n leaveTimeout.create(onLeaveComplete, 400);\n }\n});\n\nwatch(contentRef, (ref) => {\n if (ref) {\n nextTick(() => ref.focus());\n }\n else {\n onLeaveComplete();\n }\n});\n</script>\n\n<template>\n <div v-bind=\"getRootAttrs($attrs)\">\n <slot\n name=\"activator\"\n v-bind=\"{ attrs: dialogAttrs, isOpen: modelValue }\"\n />\n <Teleport to=\"body\">\n <div\n v-if=\"alive\"\n :class=\"ui.root({ class: cn(classNames?.root) })\"\n :style=\"{ zIndex }\"\n role=\"dialog\"\n aria-modal=\"true\"\n :aria-label=\"ariaLabel\"\n tabindex=\"0\"\n v-bind=\"getNonRootAttrs($attrs)\"\n @keydown.esc.stop=\"onEscClick()\"\n >\n <Transition\n enter-from-class=\"opacity-0\"\n enter-active-class=\"transition-opacity ease-out duration-200\"\n enter-to-class=\"opacity-100\"\n leave-from-class=\"opacity-100\"\n leave-active-class=\"transition-opacity ease-in duration-150\"\n leave-to-class=\"opacity-0\"\n >\n <div\n v-if=\"modelValue\"\n data-id=\"overlay\"\n :class=\"ui.overlay()\"\n @click.stop=\"onClickOutside()\"\n />\n </Transition>\n <Transition\n v-bind=\"contentTransition\"\n @after-leave=\"onLeaveComplete()\"\n >\n <div\n v-if=\"modelValue\"\n ref=\"contentRef\"\n data-id=\"content\"\n :style=\"style\"\n tabindex=\"0\"\n :data-bottom-sheet=\"bottomSheet || undefined\"\n :class=\"ui.content({ class: cn(classNames?.content) ?? cn(contentClass) })\"\n >\n <slot v-bind=\"{ isOpen: modelValue, close }\" />\n </div>\n </Transition>\n </div>\n </Teleport>\n </div>\n</template>\n"],"mappings":""}
|
|
@@ -34,11 +34,13 @@ type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
|
|
|
34
34
|
declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
35
35
|
"update:modelValue": (value: boolean) => any;
|
|
36
36
|
closed: () => any;
|
|
37
|
+
dismiss: () => any;
|
|
37
38
|
"click:outside": () => any;
|
|
38
39
|
"click:esc": () => any;
|
|
39
40
|
}, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
|
|
40
41
|
"onUpdate:modelValue"?: ((value: boolean) => any) | undefined;
|
|
41
42
|
onClosed?: (() => any) | undefined;
|
|
43
|
+
onDismiss?: (() => any) | undefined;
|
|
42
44
|
"onClick:outside"?: (() => any) | undefined;
|
|
43
45
|
"onClick:esc"?: (() => any) | undefined;
|
|
44
46
|
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { cn, tv } from "../../../utils/tv.js";
|
|
2
2
|
import { useTimeoutManager } from "../../../composables/timeout-manager.js";
|
|
3
3
|
import { getNonRootAttrs, getRootAttrs, transformPropsUnit } from "../../../utils/helpers.js";
|
|
4
|
+
import { useDismissableOverlay } from "../../../composables/overlay-stack.js";
|
|
4
5
|
import { Teleport, Transition, computed, createBlock, createCommentVNode, createElementBlock, createVNode, defineComponent, guardReactiveProps, mergeModels, mergeProps, nextTick, normalizeClass, normalizeProps, normalizeStyle, openBlock, ref, renderSlot, unref, useModel, useTemplateRef, watch, withCtx, withKeys, withModifiers } from "vue";
|
|
5
6
|
import { get, set } from "@vueuse/shared";
|
|
6
7
|
//#region src/components/overlays/dialog/RuiDialog.vue?vue&type=script&setup=true&lang.ts
|
|
@@ -35,7 +36,8 @@ var RuiDialog_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ define
|
|
|
35
36
|
emits: /*@__PURE__*/ mergeModels([
|
|
36
37
|
"closed",
|
|
37
38
|
"click:outside",
|
|
38
|
-
"click:esc"
|
|
39
|
+
"click:esc",
|
|
40
|
+
"dismiss"
|
|
39
41
|
], ["update:modelValue"]),
|
|
40
42
|
setup(__props, { emit: __emit }) {
|
|
41
43
|
const modelValue = useModel(__props, "modelValue");
|
|
@@ -94,6 +96,18 @@ var RuiDialog_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ define
|
|
|
94
96
|
if (!__props.persistent) close();
|
|
95
97
|
emit("click:outside");
|
|
96
98
|
}
|
|
99
|
+
function onDismiss() {
|
|
100
|
+
if (!__props.persistent) close();
|
|
101
|
+
emit("dismiss");
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Registration follows `modelValue` alone, never `persistent`: a dialog that
|
|
105
|
+
* turns persistent partway through its life has to stay in the stack and refuse
|
|
106
|
+
* in `onDismiss`, or the gesture starts passing through exactly once there is
|
|
107
|
+
* work to lose. A dialog playing its leave transition is already on its way out
|
|
108
|
+
* and does not hold the stack.
|
|
109
|
+
*/
|
|
110
|
+
useDismissableOverlay(modelValue, onDismiss);
|
|
97
111
|
function onLeaveComplete() {
|
|
98
112
|
leaveTimeout.clear();
|
|
99
113
|
if (get(transitioning)) {
|
package/dist/components/overlays/dialog/RuiDialog.vue_vue_type_script_setup_true_lang.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RuiDialog.vue_vue_type_script_setup_true_lang.js","names":["$attrs"],"sources":["../../../../src/components/overlays/dialog/RuiDialog.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { VueClassValue } from '@/types/class-value';\nimport { useTimeoutManager } from '@/composables/timeout-manager';\nimport { getNonRootAttrs, getRootAttrs, transformPropsUnit } from '@/utils/helpers';\nimport { cn, tv } from '@/utils/tv';\n\nexport interface RuiDialogClassNames {\n root?: VueClassValue;\n content?: VueClassValue;\n}\n\nexport interface DialogProps {\n persistent?: boolean;\n width?: string | number;\n maxWidth?: string | number;\n bottomSheet?: boolean;\n classNames?: RuiDialogClassNames;\n /** @deprecated Use `classNames.content` instead */\n contentClass?: string | string[] | Record<string, boolean>;\n zIndex?: string | number;\n ariaLabel?: string;\n}\n\ndefineOptions({\n name: 'RuiDialog',\n inheritAttrs: false,\n});\n\nconst modelValue = defineModel<boolean>({ default: false });\n\nconst {\n persistent = false,\n width = '98%',\n maxWidth,\n bottomSheet = false,\n classNames,\n contentClass = '',\n zIndex = 9999,\n ariaLabel,\n} = defineProps<DialogProps>();\n\nconst emit = defineEmits<{\n 'closed': [];\n 'click:outside': [];\n 'click:esc': [];\n}>();\n\ndefineSlots<{\n activator?: (props: { attrs: { onClick: () => void }; isOpen: boolean }) => any;\n default?: (props: { isOpen: boolean; close: () => void }) => any;\n}>();\n\nconst transitioning = ref<boolean>(false);\nconst contentRef = useTemplateRef<HTMLDivElement>('contentRef');\n\nconst leaveTimeout = useTimeoutManager();\n\nconst alive = computed<boolean>(() => get(modelValue) || get(transitioning));\n\nconst style = computed<{ width: string | undefined; maxWidth: string | undefined }>(() => ({\n width: transformPropsUnit(width),\n maxWidth: transformPropsUnit(maxWidth),\n}));\n\nconst dialog = tv({\n slots: {\n root: 'fixed inset-0',\n overlay: 'absolute inset-0 backdrop-blur bg-rui-grey-500/50 dark:bg-black/50',\n content: 'absolute left-1/2 bottom-0 -translate-x-1/2 outline-none overflow-y-auto max-h-[90vh]',\n },\n variants: {\n bottomSheet: {\n true: { content: '' },\n false: { content: 'top-1/2 -translate-y-1/2 bottom-auto' },\n },\n },\n defaultVariants: { bottomSheet: false },\n});\n\nconst ui = computed<ReturnType<typeof dialog>>(() => dialog({ bottomSheet }));\n\nconst dialogAttrs: { onClick: () => void } = {\n onClick: toggle,\n};\n\nconst contentTransition = computed<Record<string, string>>(() => {\n if (!bottomSheet) {\n return {\n enterFromClass: 'opacity-0 scale-95',\n enterActiveClass: 'transition-all ease-out duration-200',\n enterToClass: 'opacity-100 scale-100',\n leaveFromClass: 'opacity-100 scale-100',\n leaveActiveClass: 'transition-all ease-in duration-150',\n leaveToClass: 'opacity-0 scale-95',\n };\n }\n\n return {\n enterFromClass: 'translate-y-full',\n enterActiveClass: 'transition-transform ease-out duration-300',\n enterToClass: 'translate-y-0',\n leaveFromClass: 'translate-y-0',\n leaveActiveClass: 'transition-transform ease-in duration-200',\n leaveToClass: 'translate-y-full',\n };\n});\n\nfunction toggle(): void {\n set(modelValue, !get(modelValue));\n}\n\nfunction close(): void {\n set(modelValue, false);\n}\n\nfunction onEscClick(): void {\n if (!persistent) {\n close();\n }\n emit('click:esc');\n}\n\nfunction onClickOutside(): void {\n if (!persistent) {\n close();\n }\n emit('click:outside');\n}\n\nfunction onLeaveComplete(): void {\n leaveTimeout.clear();\n if (get(transitioning)) {\n set(transitioning, false);\n emit('closed');\n }\n}\n\nwatch(modelValue, (value) => {\n if (!value) {\n set(transitioning, true);\n // Safety fallback if transitionend is not detected\n leaveTimeout.create(onLeaveComplete, 400);\n }\n});\n\nwatch(contentRef, (ref) => {\n if (ref) {\n nextTick(() => ref.focus());\n }\n else {\n onLeaveComplete();\n }\n});\n</script>\n\n<template>\n <div v-bind=\"getRootAttrs($attrs)\">\n <slot\n name=\"activator\"\n v-bind=\"{ attrs: dialogAttrs, isOpen: modelValue }\"\n />\n <Teleport to=\"body\">\n <div\n v-if=\"alive\"\n :class=\"ui.root({ class: cn(classNames?.root) })\"\n :style=\"{ zIndex }\"\n role=\"dialog\"\n aria-modal=\"true\"\n :aria-label=\"ariaLabel\"\n tabindex=\"0\"\n v-bind=\"getNonRootAttrs($attrs)\"\n @keydown.esc.stop=\"onEscClick()\"\n >\n <Transition\n enter-from-class=\"opacity-0\"\n enter-active-class=\"transition-opacity ease-out duration-200\"\n enter-to-class=\"opacity-100\"\n leave-from-class=\"opacity-100\"\n leave-active-class=\"transition-opacity ease-in duration-150\"\n leave-to-class=\"opacity-0\"\n >\n <div\n v-if=\"modelValue\"\n data-id=\"overlay\"\n :class=\"ui.overlay()\"\n @click.stop=\"onClickOutside()\"\n />\n </Transition>\n <Transition\n v-bind=\"contentTransition\"\n @after-leave=\"onLeaveComplete()\"\n >\n <div\n v-if=\"modelValue\"\n ref=\"contentRef\"\n data-id=\"content\"\n :style=\"style\"\n tabindex=\"0\"\n :data-bottom-sheet=\"bottomSheet || undefined\"\n :class=\"ui.content({ class: cn(classNames?.content) ?? cn(contentClass) })\"\n >\n <slot v-bind=\"{ isOpen: modelValue, close }\" />\n </div>\n </Transition>\n </div>\n </Teleport>\n </div>\n</template>\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"RuiDialog.vue_vue_type_script_setup_true_lang.js","names":["$attrs"],"sources":["../../../../src/components/overlays/dialog/RuiDialog.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { VueClassValue } from '@/types/class-value';\nimport { useDismissableOverlay } from '@/composables/overlay-stack';\nimport { useTimeoutManager } from '@/composables/timeout-manager';\nimport { getNonRootAttrs, getRootAttrs, transformPropsUnit } from '@/utils/helpers';\nimport { cn, tv } from '@/utils/tv';\n\nexport interface RuiDialogClassNames {\n root?: VueClassValue;\n content?: VueClassValue;\n}\n\nexport interface DialogProps {\n persistent?: boolean;\n width?: string | number;\n maxWidth?: string | number;\n bottomSheet?: boolean;\n classNames?: RuiDialogClassNames;\n /** @deprecated Use `classNames.content` instead */\n contentClass?: string | string[] | Record<string, boolean>;\n zIndex?: string | number;\n ariaLabel?: string;\n}\n\ndefineOptions({\n name: 'RuiDialog',\n inheritAttrs: false,\n});\n\nconst modelValue = defineModel<boolean>({ default: false });\n\nconst {\n persistent = false,\n width = '98%',\n maxWidth,\n bottomSheet = false,\n classNames,\n contentClass = '',\n zIndex = 9999,\n ariaLabel,\n} = defineProps<DialogProps>();\n\nconst emit = defineEmits<{\n 'closed': [];\n 'click:outside': [];\n 'click:esc': [];\n /**\n * The overlay stack asked this dialog to go, which is what a back gesture\n * reaches it as. Closes unless persistent, like escape does, so a dialog that\n * has to ask before discarding should bind `persistent` and answer here.\n */\n 'dismiss': [];\n}>();\n\ndefineSlots<{\n activator?: (props: { attrs: { onClick: () => void }; isOpen: boolean }) => any;\n default?: (props: { isOpen: boolean; close: () => void }) => any;\n}>();\n\nconst transitioning = ref<boolean>(false);\nconst contentRef = useTemplateRef<HTMLDivElement>('contentRef');\n\nconst leaveTimeout = useTimeoutManager();\n\nconst alive = computed<boolean>(() => get(modelValue) || get(transitioning));\n\nconst style = computed<{ width: string | undefined; maxWidth: string | undefined }>(() => ({\n width: transformPropsUnit(width),\n maxWidth: transformPropsUnit(maxWidth),\n}));\n\nconst dialog = tv({\n slots: {\n root: 'fixed inset-0',\n overlay: 'absolute inset-0 backdrop-blur bg-rui-grey-500/50 dark:bg-black/50',\n content: 'absolute left-1/2 bottom-0 -translate-x-1/2 outline-none overflow-y-auto max-h-[90vh]',\n },\n variants: {\n bottomSheet: {\n true: { content: '' },\n false: { content: 'top-1/2 -translate-y-1/2 bottom-auto' },\n },\n },\n defaultVariants: { bottomSheet: false },\n});\n\nconst ui = computed<ReturnType<typeof dialog>>(() => dialog({ bottomSheet }));\n\nconst dialogAttrs: { onClick: () => void } = {\n onClick: toggle,\n};\n\nconst contentTransition = computed<Record<string, string>>(() => {\n if (!bottomSheet) {\n return {\n enterFromClass: 'opacity-0 scale-95',\n enterActiveClass: 'transition-all ease-out duration-200',\n enterToClass: 'opacity-100 scale-100',\n leaveFromClass: 'opacity-100 scale-100',\n leaveActiveClass: 'transition-all ease-in duration-150',\n leaveToClass: 'opacity-0 scale-95',\n };\n }\n\n return {\n enterFromClass: 'translate-y-full',\n enterActiveClass: 'transition-transform ease-out duration-300',\n enterToClass: 'translate-y-0',\n leaveFromClass: 'translate-y-0',\n leaveActiveClass: 'transition-transform ease-in duration-200',\n leaveToClass: 'translate-y-full',\n };\n});\n\nfunction toggle(): void {\n set(modelValue, !get(modelValue));\n}\n\nfunction close(): void {\n set(modelValue, false);\n}\n\nfunction onEscClick(): void {\n if (!persistent) {\n close();\n }\n emit('click:esc');\n}\n\nfunction onClickOutside(): void {\n if (!persistent) {\n close();\n }\n emit('click:outside');\n}\n\nfunction onDismiss(): void {\n if (!persistent) {\n close();\n }\n emit('dismiss');\n}\n\n/**\n * Registration follows `modelValue` alone, never `persistent`: a dialog that\n * turns persistent partway through its life has to stay in the stack and refuse\n * in `onDismiss`, or the gesture starts passing through exactly once there is\n * work to lose. A dialog playing its leave transition is already on its way out\n * and does not hold the stack.\n */\nuseDismissableOverlay(modelValue, onDismiss);\n\nfunction onLeaveComplete(): void {\n leaveTimeout.clear();\n if (get(transitioning)) {\n set(transitioning, false);\n emit('closed');\n }\n}\n\nwatch(modelValue, (value) => {\n if (!value) {\n set(transitioning, true);\n // Safety fallback if transitionend is not detected\n leaveTimeout.create(onLeaveComplete, 400);\n }\n});\n\nwatch(contentRef, (ref) => {\n if (ref) {\n nextTick(() => ref.focus());\n }\n else {\n onLeaveComplete();\n }\n});\n</script>\n\n<template>\n <div v-bind=\"getRootAttrs($attrs)\">\n <slot\n name=\"activator\"\n v-bind=\"{ attrs: dialogAttrs, isOpen: modelValue }\"\n />\n <Teleport to=\"body\">\n <div\n v-if=\"alive\"\n :class=\"ui.root({ class: cn(classNames?.root) })\"\n :style=\"{ zIndex }\"\n role=\"dialog\"\n aria-modal=\"true\"\n :aria-label=\"ariaLabel\"\n tabindex=\"0\"\n v-bind=\"getNonRootAttrs($attrs)\"\n @keydown.esc.stop=\"onEscClick()\"\n >\n <Transition\n enter-from-class=\"opacity-0\"\n enter-active-class=\"transition-opacity ease-out duration-200\"\n enter-to-class=\"opacity-100\"\n leave-from-class=\"opacity-100\"\n leave-active-class=\"transition-opacity ease-in duration-150\"\n leave-to-class=\"opacity-0\"\n >\n <div\n v-if=\"modelValue\"\n data-id=\"overlay\"\n :class=\"ui.overlay()\"\n @click.stop=\"onClickOutside()\"\n />\n </Transition>\n <Transition\n v-bind=\"contentTransition\"\n @after-leave=\"onLeaveComplete()\"\n >\n <div\n v-if=\"modelValue\"\n ref=\"contentRef\"\n data-id=\"content\"\n :style=\"style\"\n tabindex=\"0\"\n :data-bottom-sheet=\"bottomSheet || undefined\"\n :class=\"ui.content({ class: cn(classNames?.content) ?? cn(contentClass) })\"\n >\n <slot v-bind=\"{ isOpen: modelValue, close }\" />\n </div>\n </Transition>\n </div>\n </Teleport>\n </div>\n</template>\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RuiMenu.js","names":[],"sources":["../../../../src/components/overlays/menu/RuiMenu.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { VueClassValue } from '@/types/class-value';\nimport RuiFormTextDetail from '@/components/helpers/RuiFormTextDetail.vue';\nimport { type FloatingOptions, useFloating } from '@/composables/floating';\nimport { type PopperOptions, toFloatingOptions } from '@/composables/popper';\nimport { useFormTextDetail } from '@/utils/form-text-detail';\nimport { cn, tv } from '@/utils/tv';\n\ninterface BaseMenuAttrs { onMouseover?: () => void; onMouseleave?: () => void }\n\ninterface MenuAttrs extends BaseMenuAttrs { onClick?: () => void }\n\nexport interface RuiMenuClassNames {\n root?: VueClassValue;\n wrapper?: VueClassValue;\n menu?: VueClassValue;\n /** Overrides applied to the popover content box (e.g. to drop its default padding). */\n content?: VueClassValue;\n}\n\n/**\n * Roles a popover container may take. These are the values `aria-haspopup`\n * accepts, which keeps the activator and the popover in agreement.\n */\nexport type RuiMenuRole = 'menu' | 'listbox' | 'tree' | 'grid' | 'dialog';\n\nexport interface MenuProps {\n openOnHover?: boolean;\n fullWidth?: boolean;\n disabled?: boolean;\n openDelay?: number;\n closeDelay?: number;\n options?: FloatingOptions;\n /** @deprecated Use `options` instead */\n popper?: PopperOptions;\n classNames?: RuiMenuClassNames;\n /** @deprecated Use `classNames.wrapper` instead */\n wrapperClass?: string | object | string[];\n /** @deprecated Use `classNames.menu` instead */\n menuClass?: string | object | string[];\n closeOnContentClick?: boolean;\n persistOnActivatorClick?: boolean;\n hint?: string;\n errorMessages?: string | string[];\n successMessages?: string | string[];\n showDetails?: boolean;\n dense?: boolean;\n /**\n * Keeps the menu open through the interactions that would otherwise dismiss\n * it: a click outside and an Escape press. A programmatic close (`v-model`\n * set to `false`) still applies.\n */\n persistent?: boolean;\n disableAutoFocus?: boolean;\n /**\n * Optional external element to anchor the menu to, instead of the\n * activator slot's wrapper. When set, the menu's position is computed\n * against this element.\n */\n anchorEl?: HTMLElement;\n /**\n * Role of the teleported popover. Defaults to `menu`, which is correct when\n * the content is made of `menuitem`s. Set it to `listbox` (or `tree`, `grid`,\n * `dialog`) when the content follows a different ARIA model, e.g. a selection\n * list opened by a `combobox`. The activator's `aria-haspopup` follows it.\n */\n role?: RuiMenuRole;\n}\n\ndefineOptions({\n name: 'RuiMenu',\n});\n\nconst modelValue = defineModel<boolean>({ default: false });\n\nconst {\n openOnHover = false,\n disabled = false,\n fullWidth = false,\n openDelay = 0,\n closeDelay = 0,\n options,\n popper,\n classNames,\n wrapperClass = '',\n menuClass = '',\n closeOnContentClick = false,\n persistOnActivatorClick = false,\n hint,\n errorMessages = [],\n successMessages = [],\n showDetails = false,\n dense = false,\n persistent = false,\n disableAutoFocus = false,\n anchorEl,\n role = 'menu',\n} = defineProps<MenuProps>();\n\ndefineSlots<{\n activator?: (props: {\n attrs: { onMouseover?: () => void; onMouseleave?: () => void; onClick?: () => void };\n open: boolean;\n disabled: boolean;\n hasError: boolean;\n hasSuccess: boolean;\n }) => any;\n default?: (props: { width: number }) => any;\n}>();\n\nconst click = ref<boolean>(false);\nconst menuContent = useTemplateRef<HTMLElement>('menuContent');\n\nconst FOCUSABLE_ELEMENTS_SELECTOR =\n 'button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])';\n\nconst {\n reference: activator,\n popover: menu,\n open,\n visible,\n currentPlacement,\n leavePending,\n onLeavePending,\n onOpen,\n onClose,\n onLeaveComplete,\n updatePosition,\n} = useFloating(\n () => popper ? toFloatingOptions(popper) : (options ?? {}),\n () => disabled,\n () => openDelay,\n () => closeDelay,\n () => anchorEl,\n);\n\nconst { width } = useElementSize(activator);\n\nconst { hasError, hasSuccess } = useFormTextDetail(\n () => errorMessages,\n () => successMessages,\n);\n\nconst menuStyles = tv({\n slots: {\n wrapper: 'relative inline-flex max-w-full',\n popover: 'w-max z-[9999]',\n content: 'rounded overflow-hidden shadow-8 bg-white dark:bg-[#2E2E2E] text-rui-text focus:outline-none py-2',\n details: 'pt-1',\n },\n variants: {\n fullWidth: {\n true: { wrapper: 'w-full' },\n },\n dense: {\n true: { details: 'px-2' },\n false: { details: 'px-4' },\n },\n },\n defaultVariants: { fullWidth: false, dense: false },\n});\n\nconst ui = computed<ReturnType<typeof menuStyles>>(() => menuStyles({\n fullWidth,\n dense,\n}));\n\n// `aria-haspopup=\"true\"` is equivalent to `\"menu\"`; keep emitting `true` for\n// the default so nothing changes for existing callers.\nconst ariaHasPopup = computed<RuiMenuRole | 'true'>(() => role === 'menu' ? 'true' : role);\n\n// NOTE: both computed functions must return the *same* object shape from\n// every branch — otherwise vue-tsc infers the slot's `attrs` type as a\n// discriminated union where each key is either \"all defined\" or \"all\n// undefined\", which breaks consumer code that types its own `attrs`\n// handler with individually-optional keys.\nconst baseMenuAttrs = computed<BaseMenuAttrs>(() => {\n const clickVal = get(click);\n return {\n onMouseover: disabled\n ? undefined\n : () => {\n if (openOnHover)\n onOpen();\n },\n onMouseleave: disabled\n ? undefined\n : () => {\n if (openOnHover && !clickVal)\n onClose();\n },\n };\n});\n\nconst menuAttrs = computed<MenuAttrs>(() => ({\n ...get(baseMenuAttrs),\n onClick: disabled ? undefined : checkClick,\n}));\n\nfunction focusOnContent() {\n const content = get(menuContent);\n if (!content)\n return;\n\n // Focus on the menu container itself\n content.focus();\n}\n\nfunction focusMenu(): void {\n if (disableAutoFocus)\n return;\n\n nextTick(() => focusOnContent());\n}\n\nfunction focusOnActivator() {\n const activatorEl = get(activator);\n if (!activatorEl) {\n return;\n }\n const focusableEl = activatorEl.querySelector<HTMLElement>(FOCUSABLE_ELEMENTS_SELECTOR);\n if (focusableEl) {\n focusableEl.focus();\n }\n}\n\nfunction onLeave(event?: KeyboardEvent): void {\n if (!get(open))\n return;\n onClose();\n set(click, false);\n event?.stopPropagation();\n\n // Return focus to activator when menu closes\n if (disableAutoFocus) {\n return;\n }\n\n nextTick(() => focusOnActivator());\n}\n\n// `persistent` blocks the outside interactions that would close the menu, and\n// Escape is one of them — `RuiDialog` and `RuiBottomSheet` already read it that\n// way. The guard sits here rather than in `onLeave` because `onLeave` also runs\n// for a programmatic close (`v-model` set to `false`), which must keep working.\n// A persistent menu leaves the key alone instead of swallowing it, so an inner\n// popover can close on Escape while the menu stays open, and an ancestor still\n// sees a key nothing consumed.\nfunction onEscape(event: KeyboardEvent): void {\n if (persistent)\n return;\n\n onLeave(event);\n}\n\nfunction checkClick(): void {\n if (get(open) && get(click)) {\n if (!persistOnActivatorClick)\n onLeave();\n }\n else {\n onOpen();\n set(click, true);\n }\n}\n\nwatch(modelValue, (value) => {\n if (get(open) === value)\n return;\n\n if (value) {\n onOpen();\n set(click, true);\n }\n else {\n onLeave();\n }\n});\n\nwatch(open, (open) => {\n set(modelValue, open);\n if (open) {\n focusMenu();\n }\n});\n\nonClickOutside(menu, () => {\n if (get(open) && !persistent)\n onLeave();\n}, { ignore: [activator] });\n</script>\n\n<template>\n <!--\n Escape is swallowed only while the menu is open and not persistent\n (`onLeave` stops the event itself); a closed or persistent menu must let it\n through, or a consumer that closes its own editor on Escape never sees the\n key.\n -->\n <div\n :class=\"classNames?.root\"\n @keydown.esc=\"onEscape($event)\"\n >\n <div\n ref=\"activator\"\n :class=\"ui.wrapper({ class: cn(classNames?.wrapper) ?? cn(wrapperClass as VueClassValue) })\"\n :data-menu-disabled=\"disabled\"\n :aria-haspopup=\"ariaHasPopup\"\n :aria-expanded=\"open\"\n >\n <slot\n name=\"activator\"\n v-bind=\"{ attrs: menuAttrs, open, disabled, hasError, hasSuccess }\"\n />\n </div>\n <Teleport\n v-if=\"!disabled\"\n to=\"body\"\n >\n <div\n v-if=\"visible\"\n ref=\"menu\"\n :class=\"ui.popover({ class: cn(classNames?.menu) ?? cn(menuClass as VueClassValue) })\"\n :role=\"role\"\n :data-placement=\"currentPlacement\"\n @click=\"closeOnContentClick ? onLeave() : undefined\"\n @keydown.esc=\"onEscape($event)\"\n >\n <TransitionGroup\n enter-active-class=\"transition ease-out duration-200\"\n enter-from-class=\"opacity-0 translate-y-1\"\n enter-to-class=\"opacity-100 translate-y-0\"\n leave-active-class=\"transition ease-in duration-150\"\n leave-from-class=\"opacity-100 translate-y-0\"\n leave-to-class=\"opacity-0 translate-y-1\"\n @before-enter=\"updatePosition()\"\n @after-leave=\"leavePending ? onLeaveComplete() : undefined\"\n @before-leave=\"onLeavePending()\"\n >\n <div\n v-if=\"open\"\n ref=\"menuContent\"\n key=\"menu\"\n data-id=\"content\"\n :class=\"ui.content({ class: cn(classNames?.content) })\"\n tabindex=\"-1\"\n v-bind=\"baseMenuAttrs\"\n >\n <slot v-bind=\"{ width }\" />\n </div>\n </TransitionGroup>\n </div>\n </Teleport>\n <RuiFormTextDetail\n v-if=\"showDetails\"\n :class=\"ui.details()\"\n :error-messages=\"errorMessages\"\n :success-messages=\"successMessages\"\n :hint=\"hint\"\n />\n </div>\n</template>\n"],"mappings":""}
|
|
1
|
+
{"version":3,"file":"RuiMenu.js","names":[],"sources":["../../../../src/components/overlays/menu/RuiMenu.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { VueClassValue } from '@/types/class-value';\nimport RuiFormTextDetail from '@/components/helpers/RuiFormTextDetail.vue';\nimport { type FloatingOptions, useFloating } from '@/composables/floating';\nimport { type PopperOptions, toFloatingOptions } from '@/composables/popper';\nimport { useFormTextDetail } from '@/utils/form-text-detail';\nimport { cn, tv } from '@/utils/tv';\n\ninterface BaseMenuAttrs { onMouseover?: () => void; onMouseleave?: () => void }\n\ninterface MenuAttrs extends BaseMenuAttrs { onClick?: () => void }\n\nexport interface RuiMenuClassNames {\n root?: VueClassValue;\n wrapper?: VueClassValue;\n menu?: VueClassValue;\n /** Overrides applied to the popover content box (e.g. to drop its default padding). */\n content?: VueClassValue;\n}\n\n/**\n * Roles a popover container may take. These are the values `aria-haspopup`\n * accepts, which keeps the activator and the popover in agreement.\n */\nexport type RuiMenuRole = 'menu' | 'listbox' | 'tree' | 'grid' | 'dialog';\n\nexport interface MenuProps {\n openOnHover?: boolean;\n fullWidth?: boolean;\n disabled?: boolean;\n openDelay?: number;\n closeDelay?: number;\n options?: FloatingOptions;\n /** @deprecated Use `options` instead */\n popper?: PopperOptions;\n classNames?: RuiMenuClassNames;\n /** @deprecated Use `classNames.wrapper` instead */\n wrapperClass?: string | object | string[];\n /** @deprecated Use `classNames.menu` instead */\n menuClass?: string | object | string[];\n closeOnContentClick?: boolean;\n persistOnActivatorClick?: boolean;\n hint?: string;\n errorMessages?: string | string[];\n successMessages?: string | string[];\n showDetails?: boolean;\n dense?: boolean;\n /**\n * Keeps the menu open through the interactions that would otherwise dismiss\n * it: a click outside and an Escape press. A programmatic close (`v-model`\n * set to `false`) still applies.\n */\n persistent?: boolean;\n disableAutoFocus?: boolean;\n /**\n * Optional external element to anchor the menu to, instead of the\n * activator slot's wrapper. When set, the menu's position is computed\n * against this element.\n */\n anchorEl?: HTMLElement;\n /**\n * Role of the teleported popover. Defaults to `menu`, which is correct when\n * the content is made of `menuitem`s. Set it to `listbox` (or `tree`, `grid`,\n * `dialog`) when the content follows a different ARIA model, e.g. a selection\n * list opened by a `combobox`. The activator's `aria-haspopup` follows it.\n */\n role?: RuiMenuRole;\n}\n\ndefineOptions({\n name: 'RuiMenu',\n});\n\nconst modelValue = defineModel<boolean>({ default: false });\n\nconst {\n openOnHover = false,\n disabled = false,\n fullWidth = false,\n openDelay = 0,\n closeDelay = 0,\n options,\n popper,\n classNames,\n wrapperClass = '',\n menuClass = '',\n closeOnContentClick = false,\n persistOnActivatorClick = false,\n hint,\n errorMessages = [],\n successMessages = [],\n showDetails = false,\n dense = false,\n persistent = false,\n disableAutoFocus = false,\n anchorEl,\n role = 'menu',\n} = defineProps<MenuProps>();\n\ndefineSlots<{\n activator?: (props: {\n attrs: { onMouseover?: () => void; onMouseleave?: () => void; onClick?: () => void };\n open: boolean;\n disabled: boolean;\n hasError: boolean;\n hasSuccess: boolean;\n }) => any;\n default?: (props: { width: number }) => any;\n}>();\n\nconst click = ref<boolean>(false);\nconst menuContent = useTemplateRef<HTMLElement>('menuContent');\n\nconst FOCUSABLE_ELEMENTS_SELECTOR =\n 'button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])';\n\nconst {\n reference: activator,\n popover: menu,\n open,\n visible,\n currentPlacement,\n leavePending,\n onLeavePending,\n onOpen,\n onClose,\n onLeaveComplete,\n updatePosition,\n} = useFloating(\n () => popper ? toFloatingOptions(popper) : (options ?? {}),\n () => disabled,\n () => openDelay,\n () => closeDelay,\n () => anchorEl,\n);\n\nconst { width } = useElementSize(activator);\n\nconst { hasError, hasSuccess } = useFormTextDetail(\n () => errorMessages,\n () => successMessages,\n);\n\nconst menuStyles = tv({\n slots: {\n wrapper: 'relative inline-flex max-w-full',\n popover: 'w-max z-[9999]',\n content: 'rounded overflow-hidden shadow-8 bg-white dark:bg-[#2E2E2E] text-rui-text focus:outline-none py-2',\n details: 'pt-1',\n },\n variants: {\n fullWidth: {\n true: { wrapper: 'w-full' },\n },\n dense: {\n true: { details: 'px-2' },\n false: { details: 'px-4' },\n },\n },\n defaultVariants: { fullWidth: false, dense: false },\n});\n\nconst ui = computed<ReturnType<typeof menuStyles>>(() => menuStyles({\n fullWidth,\n dense,\n}));\n\n// `aria-haspopup=\"true\"` means `\"menu\"`, and the default keeps emitting `true` for existing callers\nconst ariaHasPopup = computed<RuiMenuRole | 'true'>(() => role === 'menu' ? 'true' : role);\n\n/**\n * The activator attributes.\n *\n * This and the computed below it must return the same object shape from every\n * branch. Otherwise vue-tsc infers the slot's `attrs` type as a discriminated\n * union where each key is either all defined or all undefined, which breaks\n * consumer code typing its own `attrs` handler with individually optional\n * keys.\n */\nconst baseMenuAttrs = computed<BaseMenuAttrs>(() => {\n const clickVal = get(click);\n return {\n onMouseover: disabled\n ? undefined\n : () => {\n if (openOnHover)\n onOpen();\n },\n onMouseleave: disabled\n ? undefined\n : () => {\n if (openOnHover && !clickVal)\n onClose();\n },\n };\n});\n\nconst menuAttrs = computed<MenuAttrs>(() => ({\n ...get(baseMenuAttrs),\n onClick: disabled ? undefined : checkClick,\n}));\n\nfunction focusOnContent() {\n const content = get(menuContent);\n if (!content)\n return;\n\n // Focus on the menu container itself\n content.focus();\n}\n\nfunction focusMenu(): void {\n if (disableAutoFocus)\n return;\n\n nextTick(() => focusOnContent());\n}\n\nfunction focusOnActivator() {\n const activatorEl = get(activator);\n if (!activatorEl) {\n return;\n }\n const focusableEl = activatorEl.querySelector<HTMLElement>(FOCUSABLE_ELEMENTS_SELECTOR);\n if (focusableEl) {\n focusableEl.focus();\n }\n}\n\nfunction onLeave(event?: KeyboardEvent): void {\n if (!get(open))\n return;\n onClose();\n set(click, false);\n event?.stopPropagation();\n\n // Return focus to activator when menu closes\n if (disableAutoFocus) {\n return;\n }\n\n nextTick(() => focusOnActivator());\n}\n\n/**\n * `persistent` blocks the outside interactions that would close the menu, and\n * Escape is one of them, which is how `RuiDialog` and `RuiBottomSheet` already\n * read it. The guard sits here rather than in `onLeave`, because `onLeave`\n * also runs for a programmatic close through `v-model`, which must keep\n * working.\n *\n * A persistent menu leaves the key alone instead of swallowing it, so an inner\n * popover can close on Escape while the menu stays open, and an ancestor still\n * sees a key nothing consumed.\n */\nfunction onEscape(event: KeyboardEvent): void {\n if (persistent)\n return;\n\n onLeave(event);\n}\n\nfunction checkClick(): void {\n if (get(open) && get(click)) {\n if (!persistOnActivatorClick)\n onLeave();\n }\n else {\n onOpen();\n set(click, true);\n }\n}\n\nwatch(modelValue, (value) => {\n if (get(open) === value)\n return;\n\n if (value) {\n onOpen();\n set(click, true);\n }\n else {\n onLeave();\n }\n});\n\nwatch(open, (open) => {\n set(modelValue, open);\n if (open) {\n focusMenu();\n }\n});\n\nonClickOutside(menu, () => {\n if (get(open) && !persistent)\n onLeave();\n}, { ignore: [activator] });\n</script>\n\n<template>\n <!--\n Escape is swallowed only while the menu is open and not persistent\n (`onLeave` stops the event itself); a closed or persistent menu must let it\n through, or a consumer that closes its own editor on Escape never sees the\n key.\n -->\n <div\n :class=\"classNames?.root\"\n @keydown.esc=\"onEscape($event)\"\n >\n <div\n ref=\"activator\"\n :class=\"ui.wrapper({ class: cn(classNames?.wrapper) ?? cn(wrapperClass as VueClassValue) })\"\n :data-menu-disabled=\"disabled\"\n :aria-haspopup=\"ariaHasPopup\"\n :aria-expanded=\"open\"\n >\n <slot\n name=\"activator\"\n v-bind=\"{ attrs: menuAttrs, open, disabled, hasError, hasSuccess }\"\n />\n </div>\n <Teleport\n v-if=\"!disabled\"\n to=\"body\"\n >\n <div\n v-if=\"visible\"\n ref=\"menu\"\n :class=\"ui.popover({ class: cn(classNames?.menu) ?? cn(menuClass as VueClassValue) })\"\n :role=\"role\"\n :data-placement=\"currentPlacement\"\n @click=\"closeOnContentClick ? onLeave() : undefined\"\n @keydown.esc=\"onEscape($event)\"\n >\n <TransitionGroup\n enter-active-class=\"transition ease-out duration-200\"\n enter-from-class=\"opacity-0 translate-y-1\"\n enter-to-class=\"opacity-100 translate-y-0\"\n leave-active-class=\"transition ease-in duration-150\"\n leave-from-class=\"opacity-100 translate-y-0\"\n leave-to-class=\"opacity-0 translate-y-1\"\n @before-enter=\"updatePosition()\"\n @after-leave=\"leavePending ? onLeaveComplete() : undefined\"\n @before-leave=\"onLeavePending()\"\n >\n <div\n v-if=\"open\"\n ref=\"menuContent\"\n key=\"menu\"\n data-id=\"content\"\n :class=\"ui.content({ class: cn(classNames?.content) })\"\n tabindex=\"-1\"\n v-bind=\"baseMenuAttrs\"\n >\n <slot v-bind=\"{ width }\" />\n </div>\n </TransitionGroup>\n </div>\n </Teleport>\n <RuiFormTextDetail\n v-if=\"showDetails\"\n :class=\"ui.details()\"\n :error-messages=\"errorMessages\"\n :success-messages=\"successMessages\"\n :hint=\"hint\"\n />\n </div>\n</template>\n"],"mappings":""}
|
|
@@ -105,6 +105,15 @@ var RuiMenu_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineCo
|
|
|
105
105
|
dense: __props.dense
|
|
106
106
|
}));
|
|
107
107
|
const ariaHasPopup = computed(() => __props.role === "menu" ? "true" : __props.role);
|
|
108
|
+
/**
|
|
109
|
+
* The activator attributes.
|
|
110
|
+
*
|
|
111
|
+
* This and the computed below it must return the same object shape from every
|
|
112
|
+
* branch. Otherwise vue-tsc infers the slot's `attrs` type as a discriminated
|
|
113
|
+
* union where each key is either all defined or all undefined, which breaks
|
|
114
|
+
* consumer code typing its own `attrs` handler with individually optional
|
|
115
|
+
* keys.
|
|
116
|
+
*/
|
|
108
117
|
const baseMenuAttrs = computed(() => {
|
|
109
118
|
const clickVal = get$1(click);
|
|
110
119
|
return {
|
|
@@ -143,6 +152,17 @@ var RuiMenu_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineCo
|
|
|
143
152
|
if (__props.disableAutoFocus) return;
|
|
144
153
|
nextTick(() => focusOnActivator());
|
|
145
154
|
}
|
|
155
|
+
/**
|
|
156
|
+
* `persistent` blocks the outside interactions that would close the menu, and
|
|
157
|
+
* Escape is one of them, which is how `RuiDialog` and `RuiBottomSheet` already
|
|
158
|
+
* read it. The guard sits here rather than in `onLeave`, because `onLeave`
|
|
159
|
+
* also runs for a programmatic close through `v-model`, which must keep
|
|
160
|
+
* working.
|
|
161
|
+
*
|
|
162
|
+
* A persistent menu leaves the key alone instead of swallowing it, so an inner
|
|
163
|
+
* popover can close on Escape while the menu stays open, and an ancestor still
|
|
164
|
+
* sees a key nothing consumed.
|
|
165
|
+
*/
|
|
146
166
|
function onEscape(event) {
|
|
147
167
|
if (__props.persistent) return;
|
|
148
168
|
onLeave(event);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RuiMenu.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../../src/components/overlays/menu/RuiMenu.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { VueClassValue } from '@/types/class-value';\nimport RuiFormTextDetail from '@/components/helpers/RuiFormTextDetail.vue';\nimport { type FloatingOptions, useFloating } from '@/composables/floating';\nimport { type PopperOptions, toFloatingOptions } from '@/composables/popper';\nimport { useFormTextDetail } from '@/utils/form-text-detail';\nimport { cn, tv } from '@/utils/tv';\n\ninterface BaseMenuAttrs { onMouseover?: () => void; onMouseleave?: () => void }\n\ninterface MenuAttrs extends BaseMenuAttrs { onClick?: () => void }\n\nexport interface RuiMenuClassNames {\n root?: VueClassValue;\n wrapper?: VueClassValue;\n menu?: VueClassValue;\n /** Overrides applied to the popover content box (e.g. to drop its default padding). */\n content?: VueClassValue;\n}\n\n/**\n * Roles a popover container may take. These are the values `aria-haspopup`\n * accepts, which keeps the activator and the popover in agreement.\n */\nexport type RuiMenuRole = 'menu' | 'listbox' | 'tree' | 'grid' | 'dialog';\n\nexport interface MenuProps {\n openOnHover?: boolean;\n fullWidth?: boolean;\n disabled?: boolean;\n openDelay?: number;\n closeDelay?: number;\n options?: FloatingOptions;\n /** @deprecated Use `options` instead */\n popper?: PopperOptions;\n classNames?: RuiMenuClassNames;\n /** @deprecated Use `classNames.wrapper` instead */\n wrapperClass?: string | object | string[];\n /** @deprecated Use `classNames.menu` instead */\n menuClass?: string | object | string[];\n closeOnContentClick?: boolean;\n persistOnActivatorClick?: boolean;\n hint?: string;\n errorMessages?: string | string[];\n successMessages?: string | string[];\n showDetails?: boolean;\n dense?: boolean;\n /**\n * Keeps the menu open through the interactions that would otherwise dismiss\n * it: a click outside and an Escape press. A programmatic close (`v-model`\n * set to `false`) still applies.\n */\n persistent?: boolean;\n disableAutoFocus?: boolean;\n /**\n * Optional external element to anchor the menu to, instead of the\n * activator slot's wrapper. When set, the menu's position is computed\n * against this element.\n */\n anchorEl?: HTMLElement;\n /**\n * Role of the teleported popover. Defaults to `menu`, which is correct when\n * the content is made of `menuitem`s. Set it to `listbox` (or `tree`, `grid`,\n * `dialog`) when the content follows a different ARIA model, e.g. a selection\n * list opened by a `combobox`. The activator's `aria-haspopup` follows it.\n */\n role?: RuiMenuRole;\n}\n\ndefineOptions({\n name: 'RuiMenu',\n});\n\nconst modelValue = defineModel<boolean>({ default: false });\n\nconst {\n openOnHover = false,\n disabled = false,\n fullWidth = false,\n openDelay = 0,\n closeDelay = 0,\n options,\n popper,\n classNames,\n wrapperClass = '',\n menuClass = '',\n closeOnContentClick = false,\n persistOnActivatorClick = false,\n hint,\n errorMessages = [],\n successMessages = [],\n showDetails = false,\n dense = false,\n persistent = false,\n disableAutoFocus = false,\n anchorEl,\n role = 'menu',\n} = defineProps<MenuProps>();\n\ndefineSlots<{\n activator?: (props: {\n attrs: { onMouseover?: () => void; onMouseleave?: () => void; onClick?: () => void };\n open: boolean;\n disabled: boolean;\n hasError: boolean;\n hasSuccess: boolean;\n }) => any;\n default?: (props: { width: number }) => any;\n}>();\n\nconst click = ref<boolean>(false);\nconst menuContent = useTemplateRef<HTMLElement>('menuContent');\n\nconst FOCUSABLE_ELEMENTS_SELECTOR =\n 'button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])';\n\nconst {\n reference: activator,\n popover: menu,\n open,\n visible,\n currentPlacement,\n leavePending,\n onLeavePending,\n onOpen,\n onClose,\n onLeaveComplete,\n updatePosition,\n} = useFloating(\n () => popper ? toFloatingOptions(popper) : (options ?? {}),\n () => disabled,\n () => openDelay,\n () => closeDelay,\n () => anchorEl,\n);\n\nconst { width } = useElementSize(activator);\n\nconst { hasError, hasSuccess } = useFormTextDetail(\n () => errorMessages,\n () => successMessages,\n);\n\nconst menuStyles = tv({\n slots: {\n wrapper: 'relative inline-flex max-w-full',\n popover: 'w-max z-[9999]',\n content: 'rounded overflow-hidden shadow-8 bg-white dark:bg-[#2E2E2E] text-rui-text focus:outline-none py-2',\n details: 'pt-1',\n },\n variants: {\n fullWidth: {\n true: { wrapper: 'w-full' },\n },\n dense: {\n true: { details: 'px-2' },\n false: { details: 'px-4' },\n },\n },\n defaultVariants: { fullWidth: false, dense: false },\n});\n\nconst ui = computed<ReturnType<typeof menuStyles>>(() => menuStyles({\n fullWidth,\n dense,\n}));\n\n// `aria-haspopup=\"true\"` is equivalent to `\"menu\"`; keep emitting `true` for\n// the default so nothing changes for existing callers.\nconst ariaHasPopup = computed<RuiMenuRole | 'true'>(() => role === 'menu' ? 'true' : role);\n\n// NOTE: both computed functions must return the *same* object shape from\n// every branch — otherwise vue-tsc infers the slot's `attrs` type as a\n// discriminated union where each key is either \"all defined\" or \"all\n// undefined\", which breaks consumer code that types its own `attrs`\n// handler with individually-optional keys.\nconst baseMenuAttrs = computed<BaseMenuAttrs>(() => {\n const clickVal = get(click);\n return {\n onMouseover: disabled\n ? undefined\n : () => {\n if (openOnHover)\n onOpen();\n },\n onMouseleave: disabled\n ? undefined\n : () => {\n if (openOnHover && !clickVal)\n onClose();\n },\n };\n});\n\nconst menuAttrs = computed<MenuAttrs>(() => ({\n ...get(baseMenuAttrs),\n onClick: disabled ? undefined : checkClick,\n}));\n\nfunction focusOnContent() {\n const content = get(menuContent);\n if (!content)\n return;\n\n // Focus on the menu container itself\n content.focus();\n}\n\nfunction focusMenu(): void {\n if (disableAutoFocus)\n return;\n\n nextTick(() => focusOnContent());\n}\n\nfunction focusOnActivator() {\n const activatorEl = get(activator);\n if (!activatorEl) {\n return;\n }\n const focusableEl = activatorEl.querySelector<HTMLElement>(FOCUSABLE_ELEMENTS_SELECTOR);\n if (focusableEl) {\n focusableEl.focus();\n }\n}\n\nfunction onLeave(event?: KeyboardEvent): void {\n if (!get(open))\n return;\n onClose();\n set(click, false);\n event?.stopPropagation();\n\n // Return focus to activator when menu closes\n if (disableAutoFocus) {\n return;\n }\n\n nextTick(() => focusOnActivator());\n}\n\n// `persistent` blocks the outside interactions that would close the menu, and\n// Escape is one of them — `RuiDialog` and `RuiBottomSheet` already read it that\n// way. The guard sits here rather than in `onLeave` because `onLeave` also runs\n// for a programmatic close (`v-model` set to `false`), which must keep working.\n// A persistent menu leaves the key alone instead of swallowing it, so an inner\n// popover can close on Escape while the menu stays open, and an ancestor still\n// sees a key nothing consumed.\nfunction onEscape(event: KeyboardEvent): void {\n if (persistent)\n return;\n\n onLeave(event);\n}\n\nfunction checkClick(): void {\n if (get(open) && get(click)) {\n if (!persistOnActivatorClick)\n onLeave();\n }\n else {\n onOpen();\n set(click, true);\n }\n}\n\nwatch(modelValue, (value) => {\n if (get(open) === value)\n return;\n\n if (value) {\n onOpen();\n set(click, true);\n }\n else {\n onLeave();\n }\n});\n\nwatch(open, (open) => {\n set(modelValue, open);\n if (open) {\n focusMenu();\n }\n});\n\nonClickOutside(menu, () => {\n if (get(open) && !persistent)\n onLeave();\n}, { ignore: [activator] });\n</script>\n\n<template>\n <!--\n Escape is swallowed only while the menu is open and not persistent\n (`onLeave` stops the event itself); a closed or persistent menu must let it\n through, or a consumer that closes its own editor on Escape never sees the\n key.\n -->\n <div\n :class=\"classNames?.root\"\n @keydown.esc=\"onEscape($event)\"\n >\n <div\n ref=\"activator\"\n :class=\"ui.wrapper({ class: cn(classNames?.wrapper) ?? cn(wrapperClass as VueClassValue) })\"\n :data-menu-disabled=\"disabled\"\n :aria-haspopup=\"ariaHasPopup\"\n :aria-expanded=\"open\"\n >\n <slot\n name=\"activator\"\n v-bind=\"{ attrs: menuAttrs, open, disabled, hasError, hasSuccess }\"\n />\n </div>\n <Teleport\n v-if=\"!disabled\"\n to=\"body\"\n >\n <div\n v-if=\"visible\"\n ref=\"menu\"\n :class=\"ui.popover({ class: cn(classNames?.menu) ?? cn(menuClass as VueClassValue) })\"\n :role=\"role\"\n :data-placement=\"currentPlacement\"\n @click=\"closeOnContentClick ? onLeave() : undefined\"\n @keydown.esc=\"onEscape($event)\"\n >\n <TransitionGroup\n enter-active-class=\"transition ease-out duration-200\"\n enter-from-class=\"opacity-0 translate-y-1\"\n enter-to-class=\"opacity-100 translate-y-0\"\n leave-active-class=\"transition ease-in duration-150\"\n leave-from-class=\"opacity-100 translate-y-0\"\n leave-to-class=\"opacity-0 translate-y-1\"\n @before-enter=\"updatePosition()\"\n @after-leave=\"leavePending ? onLeaveComplete() : undefined\"\n @before-leave=\"onLeavePending()\"\n >\n <div\n v-if=\"open\"\n ref=\"menuContent\"\n key=\"menu\"\n data-id=\"content\"\n :class=\"ui.content({ class: cn(classNames?.content) })\"\n tabindex=\"-1\"\n v-bind=\"baseMenuAttrs\"\n >\n <slot v-bind=\"{ width }\" />\n </div>\n </TransitionGroup>\n </div>\n </Teleport>\n <RuiFormTextDetail\n v-if=\"showDetails\"\n :class=\"ui.details()\"\n :error-messages=\"errorMessages\"\n :success-messages=\"successMessages\"\n :hint=\"hint\"\n />\n </div>\n</template>\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"RuiMenu.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../../src/components/overlays/menu/RuiMenu.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { VueClassValue } from '@/types/class-value';\nimport RuiFormTextDetail from '@/components/helpers/RuiFormTextDetail.vue';\nimport { type FloatingOptions, useFloating } from '@/composables/floating';\nimport { type PopperOptions, toFloatingOptions } from '@/composables/popper';\nimport { useFormTextDetail } from '@/utils/form-text-detail';\nimport { cn, tv } from '@/utils/tv';\n\ninterface BaseMenuAttrs { onMouseover?: () => void; onMouseleave?: () => void }\n\ninterface MenuAttrs extends BaseMenuAttrs { onClick?: () => void }\n\nexport interface RuiMenuClassNames {\n root?: VueClassValue;\n wrapper?: VueClassValue;\n menu?: VueClassValue;\n /** Overrides applied to the popover content box (e.g. to drop its default padding). */\n content?: VueClassValue;\n}\n\n/**\n * Roles a popover container may take. These are the values `aria-haspopup`\n * accepts, which keeps the activator and the popover in agreement.\n */\nexport type RuiMenuRole = 'menu' | 'listbox' | 'tree' | 'grid' | 'dialog';\n\nexport interface MenuProps {\n openOnHover?: boolean;\n fullWidth?: boolean;\n disabled?: boolean;\n openDelay?: number;\n closeDelay?: number;\n options?: FloatingOptions;\n /** @deprecated Use `options` instead */\n popper?: PopperOptions;\n classNames?: RuiMenuClassNames;\n /** @deprecated Use `classNames.wrapper` instead */\n wrapperClass?: string | object | string[];\n /** @deprecated Use `classNames.menu` instead */\n menuClass?: string | object | string[];\n closeOnContentClick?: boolean;\n persistOnActivatorClick?: boolean;\n hint?: string;\n errorMessages?: string | string[];\n successMessages?: string | string[];\n showDetails?: boolean;\n dense?: boolean;\n /**\n * Keeps the menu open through the interactions that would otherwise dismiss\n * it: a click outside and an Escape press. A programmatic close (`v-model`\n * set to `false`) still applies.\n */\n persistent?: boolean;\n disableAutoFocus?: boolean;\n /**\n * Optional external element to anchor the menu to, instead of the\n * activator slot's wrapper. When set, the menu's position is computed\n * against this element.\n */\n anchorEl?: HTMLElement;\n /**\n * Role of the teleported popover. Defaults to `menu`, which is correct when\n * the content is made of `menuitem`s. Set it to `listbox` (or `tree`, `grid`,\n * `dialog`) when the content follows a different ARIA model, e.g. a selection\n * list opened by a `combobox`. The activator's `aria-haspopup` follows it.\n */\n role?: RuiMenuRole;\n}\n\ndefineOptions({\n name: 'RuiMenu',\n});\n\nconst modelValue = defineModel<boolean>({ default: false });\n\nconst {\n openOnHover = false,\n disabled = false,\n fullWidth = false,\n openDelay = 0,\n closeDelay = 0,\n options,\n popper,\n classNames,\n wrapperClass = '',\n menuClass = '',\n closeOnContentClick = false,\n persistOnActivatorClick = false,\n hint,\n errorMessages = [],\n successMessages = [],\n showDetails = false,\n dense = false,\n persistent = false,\n disableAutoFocus = false,\n anchorEl,\n role = 'menu',\n} = defineProps<MenuProps>();\n\ndefineSlots<{\n activator?: (props: {\n attrs: { onMouseover?: () => void; onMouseleave?: () => void; onClick?: () => void };\n open: boolean;\n disabled: boolean;\n hasError: boolean;\n hasSuccess: boolean;\n }) => any;\n default?: (props: { width: number }) => any;\n}>();\n\nconst click = ref<boolean>(false);\nconst menuContent = useTemplateRef<HTMLElement>('menuContent');\n\nconst FOCUSABLE_ELEMENTS_SELECTOR =\n 'button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])';\n\nconst {\n reference: activator,\n popover: menu,\n open,\n visible,\n currentPlacement,\n leavePending,\n onLeavePending,\n onOpen,\n onClose,\n onLeaveComplete,\n updatePosition,\n} = useFloating(\n () => popper ? toFloatingOptions(popper) : (options ?? {}),\n () => disabled,\n () => openDelay,\n () => closeDelay,\n () => anchorEl,\n);\n\nconst { width } = useElementSize(activator);\n\nconst { hasError, hasSuccess } = useFormTextDetail(\n () => errorMessages,\n () => successMessages,\n);\n\nconst menuStyles = tv({\n slots: {\n wrapper: 'relative inline-flex max-w-full',\n popover: 'w-max z-[9999]',\n content: 'rounded overflow-hidden shadow-8 bg-white dark:bg-[#2E2E2E] text-rui-text focus:outline-none py-2',\n details: 'pt-1',\n },\n variants: {\n fullWidth: {\n true: { wrapper: 'w-full' },\n },\n dense: {\n true: { details: 'px-2' },\n false: { details: 'px-4' },\n },\n },\n defaultVariants: { fullWidth: false, dense: false },\n});\n\nconst ui = computed<ReturnType<typeof menuStyles>>(() => menuStyles({\n fullWidth,\n dense,\n}));\n\n// `aria-haspopup=\"true\"` means `\"menu\"`, and the default keeps emitting `true` for existing callers\nconst ariaHasPopup = computed<RuiMenuRole | 'true'>(() => role === 'menu' ? 'true' : role);\n\n/**\n * The activator attributes.\n *\n * This and the computed below it must return the same object shape from every\n * branch. Otherwise vue-tsc infers the slot's `attrs` type as a discriminated\n * union where each key is either all defined or all undefined, which breaks\n * consumer code typing its own `attrs` handler with individually optional\n * keys.\n */\nconst baseMenuAttrs = computed<BaseMenuAttrs>(() => {\n const clickVal = get(click);\n return {\n onMouseover: disabled\n ? undefined\n : () => {\n if (openOnHover)\n onOpen();\n },\n onMouseleave: disabled\n ? undefined\n : () => {\n if (openOnHover && !clickVal)\n onClose();\n },\n };\n});\n\nconst menuAttrs = computed<MenuAttrs>(() => ({\n ...get(baseMenuAttrs),\n onClick: disabled ? undefined : checkClick,\n}));\n\nfunction focusOnContent() {\n const content = get(menuContent);\n if (!content)\n return;\n\n // Focus on the menu container itself\n content.focus();\n}\n\nfunction focusMenu(): void {\n if (disableAutoFocus)\n return;\n\n nextTick(() => focusOnContent());\n}\n\nfunction focusOnActivator() {\n const activatorEl = get(activator);\n if (!activatorEl) {\n return;\n }\n const focusableEl = activatorEl.querySelector<HTMLElement>(FOCUSABLE_ELEMENTS_SELECTOR);\n if (focusableEl) {\n focusableEl.focus();\n }\n}\n\nfunction onLeave(event?: KeyboardEvent): void {\n if (!get(open))\n return;\n onClose();\n set(click, false);\n event?.stopPropagation();\n\n // Return focus to activator when menu closes\n if (disableAutoFocus) {\n return;\n }\n\n nextTick(() => focusOnActivator());\n}\n\n/**\n * `persistent` blocks the outside interactions that would close the menu, and\n * Escape is one of them, which is how `RuiDialog` and `RuiBottomSheet` already\n * read it. The guard sits here rather than in `onLeave`, because `onLeave`\n * also runs for a programmatic close through `v-model`, which must keep\n * working.\n *\n * A persistent menu leaves the key alone instead of swallowing it, so an inner\n * popover can close on Escape while the menu stays open, and an ancestor still\n * sees a key nothing consumed.\n */\nfunction onEscape(event: KeyboardEvent): void {\n if (persistent)\n return;\n\n onLeave(event);\n}\n\nfunction checkClick(): void {\n if (get(open) && get(click)) {\n if (!persistOnActivatorClick)\n onLeave();\n }\n else {\n onOpen();\n set(click, true);\n }\n}\n\nwatch(modelValue, (value) => {\n if (get(open) === value)\n return;\n\n if (value) {\n onOpen();\n set(click, true);\n }\n else {\n onLeave();\n }\n});\n\nwatch(open, (open) => {\n set(modelValue, open);\n if (open) {\n focusMenu();\n }\n});\n\nonClickOutside(menu, () => {\n if (get(open) && !persistent)\n onLeave();\n}, { ignore: [activator] });\n</script>\n\n<template>\n <!--\n Escape is swallowed only while the menu is open and not persistent\n (`onLeave` stops the event itself); a closed or persistent menu must let it\n through, or a consumer that closes its own editor on Escape never sees the\n key.\n -->\n <div\n :class=\"classNames?.root\"\n @keydown.esc=\"onEscape($event)\"\n >\n <div\n ref=\"activator\"\n :class=\"ui.wrapper({ class: cn(classNames?.wrapper) ?? cn(wrapperClass as VueClassValue) })\"\n :data-menu-disabled=\"disabled\"\n :aria-haspopup=\"ariaHasPopup\"\n :aria-expanded=\"open\"\n >\n <slot\n name=\"activator\"\n v-bind=\"{ attrs: menuAttrs, open, disabled, hasError, hasSuccess }\"\n />\n </div>\n <Teleport\n v-if=\"!disabled\"\n to=\"body\"\n >\n <div\n v-if=\"visible\"\n ref=\"menu\"\n :class=\"ui.popover({ class: cn(classNames?.menu) ?? cn(menuClass as VueClassValue) })\"\n :role=\"role\"\n :data-placement=\"currentPlacement\"\n @click=\"closeOnContentClick ? onLeave() : undefined\"\n @keydown.esc=\"onEscape($event)\"\n >\n <TransitionGroup\n enter-active-class=\"transition ease-out duration-200\"\n enter-from-class=\"opacity-0 translate-y-1\"\n enter-to-class=\"opacity-100 translate-y-0\"\n leave-active-class=\"transition ease-in duration-150\"\n leave-from-class=\"opacity-100 translate-y-0\"\n leave-to-class=\"opacity-0 translate-y-1\"\n @before-enter=\"updatePosition()\"\n @after-leave=\"leavePending ? onLeaveComplete() : undefined\"\n @before-leave=\"onLeavePending()\"\n >\n <div\n v-if=\"open\"\n ref=\"menuContent\"\n key=\"menu\"\n data-id=\"content\"\n :class=\"ui.content({ class: cn(classNames?.content) })\"\n tabindex=\"-1\"\n v-bind=\"baseMenuAttrs\"\n >\n <slot v-bind=\"{ width }\" />\n </div>\n </TransitionGroup>\n </div>\n </Teleport>\n <RuiFormTextDetail\n v-if=\"showDetails\"\n :class=\"ui.details()\"\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":"RuiNavigationDrawer.js","names":[],"sources":["../../../../src/components/overlays/navigation-drawer/RuiNavigationDrawer.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { MaybeElement } from '@vueuse/core';\nimport type { ClassValue } from 'vue';\nimport type { VueClassValue } from '@/types/class-value';\nimport { useTimeoutManager } from '@/composables/timeout-manager';\nimport { getRootAttrs, transformPropsUnit } from '@/utils/helpers';\nimport { cn, tv } from '@/utils/tv';\n\nexport interface RuiNavigationDrawerClassNames {\n root?: VueClassValue;\n content?: VueClassValue;\n}\n\nexport interface NavigationDrawerProps {\n temporary?: boolean;\n stateless?: boolean;\n width?: string | number;\n miniVariant?: boolean;\n overlay?: boolean;\n position?: 'left' | 'right';\n classNames?: RuiNavigationDrawerClassNames;\n /** @deprecated Use `classNames.content` instead */\n contentClass?: string | object | string[];\n ariaLabel?: string;\n}\n\ndefineOptions({\n name: 'RuiNavigationDrawer',\n inheritAttrs: false,\n});\n\nconst modelValue = defineModel<boolean>({ default: false });\n\nconst {\n temporary = false,\n stateless = false,\n width = 360,\n miniVariant = false,\n overlay = false,\n position = 'left',\n classNames,\n contentClass = '',\n ariaLabel,\n} = defineProps<NavigationDrawerProps>();\n\nconst emit = defineEmits<{\n closed: [];\n}>();\n\ndefineSlots<{\n activator?: (props: { open: boolean; attrs: { onClick: () => void } }) => any;\n default?: (props: { attrs: { onClick: () => void }; close: () => void }) => any;\n}>();\n\nconst transitioning = ref<boolean>(false);\nconst content = useTemplateRef<MaybeElement>('content');\nconst leaveTimeout = useTimeoutManager();\nconst clickOutsideTimeout = useTimeoutManager();\n\nconst alive = computed<boolean>(() => get(modelValue) || get(transitioning) || miniVariant);\n\nconst style = computed<{ width: string | undefined }>(() => ({\n width: transformPropsUnit(width),\n}));\n\nconst activatorAttrs: { onClick: () => void } = {\n onClick: toggle,\n};\n\nconst drawer = tv({\n base: 'transition-[transform,width] duration-200 ease-in-out top-0 h-full fixed text-rui-text bg-white dark:bg-[#363636]',\n variants: {\n position: {\n left: 'left-0',\n right: 'right-0',\n },\n visible: {\n true: 'translate-x-0',\n false: '',\n },\n mini: {\n true: 'translate-x-0',\n false: '',\n },\n withOverlay: {\n true: 'z-[10000]',\n false: 'z-[7]',\n },\n },\n compoundVariants: [\n { position: 'left', visible: false, mini: false, class: '-translate-x-full' },\n { position: 'right', visible: false, mini: false, class: 'translate-x-full' },\n { mini: true, visible: false, class: '!w-14' },\n ],\n defaultVariants: { position: 'left', visible: false, mini: false, withOverlay: false },\n});\n\n/**\n * Consumer classes go through `drawer()` rather than alongside it, so\n * tailwind-variants' twMerge resolves conflicts in the consumer's favour.\n * Passed as an argument instead of read off `$attrs` here, so the template\n * keeps using `$attrs` directly.\n */\nfunction rootClass(attrsClass: ClassValue): string {\n return drawer({\n position,\n visible: modelValue.value,\n mini: miniVariant,\n withOverlay: overlay,\n class: cn([\n temporary && modelValue.value && 'shadow-5',\n classNames?.content ?? contentClass,\n classNames?.root,\n attrsClass,\n ]),\n });\n}\n\nfunction toggle(): void {\n set(modelValue, !get(modelValue));\n}\n\nfunction close(): void {\n set(modelValue, false);\n}\n\nfunction onLeaveComplete(): void {\n leaveTimeout.clear();\n if (get(transitioning)) {\n set(transitioning, false);\n emit('closed');\n }\n}\n\nwatch(modelValue, (value) => {\n if (!value) {\n set(transitioning, true);\n // Match CSS transition duration (200ms) + buffer\n leaveTimeout.create(onLeaveComplete, 250);\n }\n});\n\n//
|
|
1
|
+
{"version":3,"file":"RuiNavigationDrawer.js","names":[],"sources":["../../../../src/components/overlays/navigation-drawer/RuiNavigationDrawer.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { MaybeElement } from '@vueuse/core';\nimport type { ClassValue } from 'vue';\nimport type { VueClassValue } from '@/types/class-value';\nimport { useTimeoutManager } from '@/composables/timeout-manager';\nimport { getRootAttrs, transformPropsUnit } from '@/utils/helpers';\nimport { cn, tv } from '@/utils/tv';\n\nexport interface RuiNavigationDrawerClassNames {\n root?: VueClassValue;\n content?: VueClassValue;\n}\n\nexport interface NavigationDrawerProps {\n temporary?: boolean;\n stateless?: boolean;\n width?: string | number;\n miniVariant?: boolean;\n overlay?: boolean;\n position?: 'left' | 'right';\n classNames?: RuiNavigationDrawerClassNames;\n /** @deprecated Use `classNames.content` instead */\n contentClass?: string | object | string[];\n ariaLabel?: string;\n}\n\ndefineOptions({\n name: 'RuiNavigationDrawer',\n inheritAttrs: false,\n});\n\nconst modelValue = defineModel<boolean>({ default: false });\n\nconst {\n temporary = false,\n stateless = false,\n width = 360,\n miniVariant = false,\n overlay = false,\n position = 'left',\n classNames,\n contentClass = '',\n ariaLabel,\n} = defineProps<NavigationDrawerProps>();\n\nconst emit = defineEmits<{\n closed: [];\n}>();\n\ndefineSlots<{\n activator?: (props: { open: boolean; attrs: { onClick: () => void } }) => any;\n default?: (props: { attrs: { onClick: () => void }; close: () => void }) => any;\n}>();\n\nconst transitioning = ref<boolean>(false);\nconst content = useTemplateRef<MaybeElement>('content');\nconst leaveTimeout = useTimeoutManager();\nconst clickOutsideTimeout = useTimeoutManager();\n\nconst alive = computed<boolean>(() => get(modelValue) || get(transitioning) || miniVariant);\n\nconst style = computed<{ width: string | undefined }>(() => ({\n width: transformPropsUnit(width),\n}));\n\nconst activatorAttrs: { onClick: () => void } = {\n onClick: toggle,\n};\n\nconst drawer = tv({\n base: 'transition-[transform,width] duration-200 ease-in-out top-0 h-full fixed text-rui-text bg-white dark:bg-[#363636]',\n variants: {\n position: {\n left: 'left-0',\n right: 'right-0',\n },\n visible: {\n true: 'translate-x-0',\n false: '',\n },\n mini: {\n true: 'translate-x-0',\n false: '',\n },\n withOverlay: {\n true: 'z-[10000]',\n false: 'z-[7]',\n },\n },\n compoundVariants: [\n { position: 'left', visible: false, mini: false, class: '-translate-x-full' },\n { position: 'right', visible: false, mini: false, class: 'translate-x-full' },\n { mini: true, visible: false, class: '!w-14' },\n ],\n defaultVariants: { position: 'left', visible: false, mini: false, withOverlay: false },\n});\n\n/**\n * Consumer classes go through `drawer()` rather than alongside it, so\n * tailwind-variants' twMerge resolves conflicts in the consumer's favour.\n * Passed as an argument instead of read off `$attrs` here, so the template\n * keeps using `$attrs` directly.\n */\nfunction rootClass(attrsClass: ClassValue): string {\n return drawer({\n position,\n visible: modelValue.value,\n mini: miniVariant,\n withOverlay: overlay,\n class: cn([\n temporary && modelValue.value && 'shadow-5',\n classNames?.content ?? contentClass,\n classNames?.root,\n attrsClass,\n ]),\n });\n}\n\nfunction toggle(): void {\n set(modelValue, !get(modelValue));\n}\n\nfunction close(): void {\n set(modelValue, false);\n}\n\nfunction onLeaveComplete(): void {\n leaveTimeout.clear();\n if (get(transitioning)) {\n set(transitioning, false);\n emit('closed');\n }\n}\n\nwatch(modelValue, (value) => {\n if (!value) {\n set(transitioning, true);\n // Match CSS transition duration (200ms) + buffer\n leaveTimeout.create(onLeaveComplete, 250);\n }\n});\n\n// Debounced, so the activator's own click, which bubbles to the body, does not close it again\nonClickOutside(content, () => {\n if (get(modelValue) && temporary && !stateless) {\n clickOutsideTimeout.create(close, 50);\n }\n});\n</script>\n\n<template>\n <div>\n <slot\n name=\"activator\"\n v-bind=\"{ open: modelValue, attrs: activatorAttrs }\"\n />\n <Teleport to=\"body\">\n <Transition\n v-if=\"overlay\"\n enter-from-class=\"opacity-0\"\n enter-active-class=\"transition-opacity ease-out duration-200\"\n enter-to-class=\"opacity-100\"\n leave-from-class=\"opacity-100\"\n leave-active-class=\"transition-opacity ease-in duration-200\"\n leave-to-class=\"opacity-0\"\n >\n <div\n v-if=\"modelValue\"\n data-id=\"overlay\"\n class=\"absolute inset-0 backdrop-blur bg-rui-grey-500/50 dark:bg-black/50 z-[10000]\"\n @click.stop=\"close()\"\n />\n </Transition>\n <aside\n v-if=\"alive\"\n ref=\"content\"\n data-id=\"drawer-content\"\n :style=\"style\"\n :data-visible=\"modelValue || undefined\"\n :data-position=\"position\"\n :data-mini=\"miniVariant || undefined\"\n :class=\"rootClass($attrs.class)\"\n :aria-label=\"ariaLabel\"\n :aria-hidden=\"miniVariant && !modelValue ? 'true' : undefined\"\n v-bind=\"getRootAttrs($attrs, [])\"\n >\n <slot v-bind=\"{ attrs: activatorAttrs, close }\" />\n </aside>\n </Teleport>\n </div>\n</template>\n"],"mappings":""}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RuiNavigationDrawer.vue_vue_type_script_setup_true_lang.js","names":["$attrs"],"sources":["../../../../src/components/overlays/navigation-drawer/RuiNavigationDrawer.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { MaybeElement } from '@vueuse/core';\nimport type { ClassValue } from 'vue';\nimport type { VueClassValue } from '@/types/class-value';\nimport { useTimeoutManager } from '@/composables/timeout-manager';\nimport { getRootAttrs, transformPropsUnit } from '@/utils/helpers';\nimport { cn, tv } from '@/utils/tv';\n\nexport interface RuiNavigationDrawerClassNames {\n root?: VueClassValue;\n content?: VueClassValue;\n}\n\nexport interface NavigationDrawerProps {\n temporary?: boolean;\n stateless?: boolean;\n width?: string | number;\n miniVariant?: boolean;\n overlay?: boolean;\n position?: 'left' | 'right';\n classNames?: RuiNavigationDrawerClassNames;\n /** @deprecated Use `classNames.content` instead */\n contentClass?: string | object | string[];\n ariaLabel?: string;\n}\n\ndefineOptions({\n name: 'RuiNavigationDrawer',\n inheritAttrs: false,\n});\n\nconst modelValue = defineModel<boolean>({ default: false });\n\nconst {\n temporary = false,\n stateless = false,\n width = 360,\n miniVariant = false,\n overlay = false,\n position = 'left',\n classNames,\n contentClass = '',\n ariaLabel,\n} = defineProps<NavigationDrawerProps>();\n\nconst emit = defineEmits<{\n closed: [];\n}>();\n\ndefineSlots<{\n activator?: (props: { open: boolean; attrs: { onClick: () => void } }) => any;\n default?: (props: { attrs: { onClick: () => void }; close: () => void }) => any;\n}>();\n\nconst transitioning = ref<boolean>(false);\nconst content = useTemplateRef<MaybeElement>('content');\nconst leaveTimeout = useTimeoutManager();\nconst clickOutsideTimeout = useTimeoutManager();\n\nconst alive = computed<boolean>(() => get(modelValue) || get(transitioning) || miniVariant);\n\nconst style = computed<{ width: string | undefined }>(() => ({\n width: transformPropsUnit(width),\n}));\n\nconst activatorAttrs: { onClick: () => void } = {\n onClick: toggle,\n};\n\nconst drawer = tv({\n base: 'transition-[transform,width] duration-200 ease-in-out top-0 h-full fixed text-rui-text bg-white dark:bg-[#363636]',\n variants: {\n position: {\n left: 'left-0',\n right: 'right-0',\n },\n visible: {\n true: 'translate-x-0',\n false: '',\n },\n mini: {\n true: 'translate-x-0',\n false: '',\n },\n withOverlay: {\n true: 'z-[10000]',\n false: 'z-[7]',\n },\n },\n compoundVariants: [\n { position: 'left', visible: false, mini: false, class: '-translate-x-full' },\n { position: 'right', visible: false, mini: false, class: 'translate-x-full' },\n { mini: true, visible: false, class: '!w-14' },\n ],\n defaultVariants: { position: 'left', visible: false, mini: false, withOverlay: false },\n});\n\n/**\n * Consumer classes go through `drawer()` rather than alongside it, so\n * tailwind-variants' twMerge resolves conflicts in the consumer's favour.\n * Passed as an argument instead of read off `$attrs` here, so the template\n * keeps using `$attrs` directly.\n */\nfunction rootClass(attrsClass: ClassValue): string {\n return drawer({\n position,\n visible: modelValue.value,\n mini: miniVariant,\n withOverlay: overlay,\n class: cn([\n temporary && modelValue.value && 'shadow-5',\n classNames?.content ?? contentClass,\n classNames?.root,\n attrsClass,\n ]),\n });\n}\n\nfunction toggle(): void {\n set(modelValue, !get(modelValue));\n}\n\nfunction close(): void {\n set(modelValue, false);\n}\n\nfunction onLeaveComplete(): void {\n leaveTimeout.clear();\n if (get(transitioning)) {\n set(transitioning, false);\n emit('closed');\n }\n}\n\nwatch(modelValue, (value) => {\n if (!value) {\n set(transitioning, true);\n // Match CSS transition duration (200ms) + buffer\n leaveTimeout.create(onLeaveComplete, 250);\n }\n});\n\n//
|
|
1
|
+
{"version":3,"file":"RuiNavigationDrawer.vue_vue_type_script_setup_true_lang.js","names":["$attrs"],"sources":["../../../../src/components/overlays/navigation-drawer/RuiNavigationDrawer.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { MaybeElement } from '@vueuse/core';\nimport type { ClassValue } from 'vue';\nimport type { VueClassValue } from '@/types/class-value';\nimport { useTimeoutManager } from '@/composables/timeout-manager';\nimport { getRootAttrs, transformPropsUnit } from '@/utils/helpers';\nimport { cn, tv } from '@/utils/tv';\n\nexport interface RuiNavigationDrawerClassNames {\n root?: VueClassValue;\n content?: VueClassValue;\n}\n\nexport interface NavigationDrawerProps {\n temporary?: boolean;\n stateless?: boolean;\n width?: string | number;\n miniVariant?: boolean;\n overlay?: boolean;\n position?: 'left' | 'right';\n classNames?: RuiNavigationDrawerClassNames;\n /** @deprecated Use `classNames.content` instead */\n contentClass?: string | object | string[];\n ariaLabel?: string;\n}\n\ndefineOptions({\n name: 'RuiNavigationDrawer',\n inheritAttrs: false,\n});\n\nconst modelValue = defineModel<boolean>({ default: false });\n\nconst {\n temporary = false,\n stateless = false,\n width = 360,\n miniVariant = false,\n overlay = false,\n position = 'left',\n classNames,\n contentClass = '',\n ariaLabel,\n} = defineProps<NavigationDrawerProps>();\n\nconst emit = defineEmits<{\n closed: [];\n}>();\n\ndefineSlots<{\n activator?: (props: { open: boolean; attrs: { onClick: () => void } }) => any;\n default?: (props: { attrs: { onClick: () => void }; close: () => void }) => any;\n}>();\n\nconst transitioning = ref<boolean>(false);\nconst content = useTemplateRef<MaybeElement>('content');\nconst leaveTimeout = useTimeoutManager();\nconst clickOutsideTimeout = useTimeoutManager();\n\nconst alive = computed<boolean>(() => get(modelValue) || get(transitioning) || miniVariant);\n\nconst style = computed<{ width: string | undefined }>(() => ({\n width: transformPropsUnit(width),\n}));\n\nconst activatorAttrs: { onClick: () => void } = {\n onClick: toggle,\n};\n\nconst drawer = tv({\n base: 'transition-[transform,width] duration-200 ease-in-out top-0 h-full fixed text-rui-text bg-white dark:bg-[#363636]',\n variants: {\n position: {\n left: 'left-0',\n right: 'right-0',\n },\n visible: {\n true: 'translate-x-0',\n false: '',\n },\n mini: {\n true: 'translate-x-0',\n false: '',\n },\n withOverlay: {\n true: 'z-[10000]',\n false: 'z-[7]',\n },\n },\n compoundVariants: [\n { position: 'left', visible: false, mini: false, class: '-translate-x-full' },\n { position: 'right', visible: false, mini: false, class: 'translate-x-full' },\n { mini: true, visible: false, class: '!w-14' },\n ],\n defaultVariants: { position: 'left', visible: false, mini: false, withOverlay: false },\n});\n\n/**\n * Consumer classes go through `drawer()` rather than alongside it, so\n * tailwind-variants' twMerge resolves conflicts in the consumer's favour.\n * Passed as an argument instead of read off `$attrs` here, so the template\n * keeps using `$attrs` directly.\n */\nfunction rootClass(attrsClass: ClassValue): string {\n return drawer({\n position,\n visible: modelValue.value,\n mini: miniVariant,\n withOverlay: overlay,\n class: cn([\n temporary && modelValue.value && 'shadow-5',\n classNames?.content ?? contentClass,\n classNames?.root,\n attrsClass,\n ]),\n });\n}\n\nfunction toggle(): void {\n set(modelValue, !get(modelValue));\n}\n\nfunction close(): void {\n set(modelValue, false);\n}\n\nfunction onLeaveComplete(): void {\n leaveTimeout.clear();\n if (get(transitioning)) {\n set(transitioning, false);\n emit('closed');\n }\n}\n\nwatch(modelValue, (value) => {\n if (!value) {\n set(transitioning, true);\n // Match CSS transition duration (200ms) + buffer\n leaveTimeout.create(onLeaveComplete, 250);\n }\n});\n\n// Debounced, so the activator's own click, which bubbles to the body, does not close it again\nonClickOutside(content, () => {\n if (get(modelValue) && temporary && !stateless) {\n clickOutsideTimeout.create(close, 50);\n }\n});\n</script>\n\n<template>\n <div>\n <slot\n name=\"activator\"\n v-bind=\"{ open: modelValue, attrs: activatorAttrs }\"\n />\n <Teleport to=\"body\">\n <Transition\n v-if=\"overlay\"\n enter-from-class=\"opacity-0\"\n enter-active-class=\"transition-opacity ease-out duration-200\"\n enter-to-class=\"opacity-100\"\n leave-from-class=\"opacity-100\"\n leave-active-class=\"transition-opacity ease-in duration-200\"\n leave-to-class=\"opacity-0\"\n >\n <div\n v-if=\"modelValue\"\n data-id=\"overlay\"\n class=\"absolute inset-0 backdrop-blur bg-rui-grey-500/50 dark:bg-black/50 z-[10000]\"\n @click.stop=\"close()\"\n />\n </Transition>\n <aside\n v-if=\"alive\"\n ref=\"content\"\n data-id=\"drawer-content\"\n :style=\"style\"\n :data-visible=\"modelValue || undefined\"\n :data-position=\"position\"\n :data-mini=\"miniVariant || undefined\"\n :class=\"rootClass($attrs.class)\"\n :aria-label=\"ariaLabel\"\n :aria-hidden=\"miniVariant && !modelValue ? 'true' : undefined\"\n v-bind=\"getRootAttrs($attrs, [])\"\n >\n <slot v-bind=\"{ attrs: activatorAttrs, close }\" />\n </aside>\n </Teleport>\n </div>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA+BA,MAAM,aAAa,SAAoB,SAAA,YAAmB;EAc1D,MAAM,OAAO;EASb,MAAM,gBAAgB,IAAa,KAAK;EACxC,MAAM,UAAU,eAA6B,SAAS;EACtD,MAAM,eAAe,kBAAkB;EACvC,MAAM,sBAAsB,kBAAkB;EAE9C,MAAM,QAAQ,eAAwB,MAAI,UAAU,KAAK,MAAI,aAAa,KAAK,QAAA,WAAW;EAE1F,MAAM,QAAQ,gBAA+C,EAC3D,OAAO,mBAAmB,QAAA,KAAK,EACjC,EAAE;EAEF,MAAM,iBAA0C,EAC9C,SAAS,OACX;EAEA,MAAM,SAAS,GAAG;GAChB,MAAM;GACN,UAAU;IACR,UAAU;KACR,MAAM;KACN,OAAO;IACT;IACA,SAAS;KACP,MAAM;KACN,OAAO;IACT;IACA,MAAM;KACJ,MAAM;KACN,OAAO;IACT;IACA,aAAa;KACX,MAAM;KACN,OAAO;IACT;GACF;GACA,kBAAkB;IAChB;KAAE,UAAU;KAAQ,SAAS;KAAO,MAAM;KAAO,OAAO;IAAoB;IAC5E;KAAE,UAAU;KAAS,SAAS;KAAO,MAAM;KAAO,OAAO;IAAmB;IAC5E;KAAE,MAAM;KAAM,SAAS;KAAO,OAAO;IAAQ;GAC/C;GACA,iBAAiB;IAAE,UAAU;IAAQ,SAAS;IAAO,MAAM;IAAO,aAAa;GAAM;EACvF,CAAC;;;;;;;EAQD,SAAS,UAAU,YAAgC;GACjD,OAAO,OAAO;IACZ,UAAO,QAAA;IACP,SAAS,WAAW;IACpB,MAAM,QAAA;IACN,aAAa,QAAA;IACb,OAAO,GAAG;KACR,QAAA,aAAa,WAAW,SAAS;KACjC,QAAA,YAAY,WAAW,QAAA;KACvB,QAAA,YAAY;KACZ;IACF,CAAC;GACH,CAAC;EACH;EAEA,SAAS,SAAe;GACtB,MAAI,YAAY,CAAC,MAAI,UAAU,CAAC;EAClC;EAEA,SAAS,QAAc;GACrB,MAAI,YAAY,KAAK;EACvB;EAEA,SAAS,kBAAwB;GAC/B,aAAa,MAAM;GACnB,IAAI,MAAI,aAAa,GAAG;IACtB,MAAI,eAAe,KAAK;IACxB,KAAK,QAAQ;GACf;EACF;EAEA,MAAM,aAAa,UAAU;GAC3B,IAAI,CAAC,OAAO;IACV,MAAI,eAAe,IAAI;IAEvB,aAAa,OAAO,iBAAiB,GAAG;GAC1C;EACF,CAAC;EAGD,eAAe,eAAe;GAC5B,IAAI,MAAI,UAAU,KAAK,QAAA,aAAa,CAAC,QAAA,WACnC,oBAAoB,OAAO,OAAO,EAAE;EAExC,CAAC;;GAIC,OAAA,UAAA,GAAA,mBAsCM,OAAA,MAAA,CArCJ,WAGE,KAAA,QAAA,aAAA,eAAA,mBAAA;IAAA,MADgB,WAAA;IAAU,OAAS;GAAc,CAAA,CAAA,CAAA,IAEnD,UAAA,GAAA,YAgCW,UAAA,EAhCD,IAAG,OAAM,GAAA,CAET,QAAA,WADR,UAAA,GAAA,YAea,YAAA;;IAbX,oBAAiB;IACjB,sBAAmB;IACnB,kBAAe;IACf,oBAAiB;IACjB,sBAAmB;IACnB,kBAAe;;IAEf,SAAA,cAKE,CAJM,WAAA,SADR,UAAA,GAAA,mBAKE,OAAA;;KAHA,WAAQ;KACR,OAAM;KACL,SAAK,OAAA,OAAA,OAAA,KAAA,eAAA,WAAO,MAAK,GAAA,CAAA,MAAA,CAAA;;;GAId,CAAA,KAAA,mBAAA,IAAA,IAAA,GAAA,MAAA,KAAA,KADR,UAAA,GAAA,mBAcQ,SAdR,WAcQ;;IAZF,SAAA;IAAJ,KAAI;IACJ,WAAQ;IACP,OAAO,MAAA,KAAA;IACP,gBAAc,WAAA,SAAc,KAAA;IAC5B,iBAAe,QAAA;IACf,aAAW,QAAA,eAAe,KAAA;IAC1B,OAAO,UAAUA,KAAAA,OAAO,KAAK;IAC7B,cAAY,QAAA;IACZ,eAAa,QAAA,eAAW,CAAK,WAAA,QAAU,SAAY,KAAA;GAC5C,GAAA,MAAA,YAAA,CAAY,CAACA,KAAAA,QAAM,CAAA,CAAA,CAAA,GAAA,CAE3B,WAAkD,KAAA,QAAA,WAAA,eAAA,mBAAA;IAAA,OAA3B;IAAgB;GAAK,CAAA,CAAA,CAAA,CAAA,GAAA,IAAA,UAAA,KAAA,mBAAA,IAAA,IAAA,CAAA,CAAA,EAAA,CAAA"}
|