@rotki/ui-library 3.0.0-beta.3 → 3.0.0-beta.4
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 +27 -14
- package/dist/components/accordions/accordion/RuiAccordion.js.map +1 -1
- package/dist/components/accordions/accordion/RuiAccordion.vue.d.ts +1 -1
- package/dist/components/accordions/accordion/RuiAccordion.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/accordions/accordions/RuiAccordions.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.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.js.map +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_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/buttons/button/RuiButton.js.map +1 -1
- package/dist/components/buttons/button/RuiButton.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/buttons/button-group/RuiButtonGroup.js.map +1 -1
- 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.map +1 -1
- package/dist/components/calendar/RuiCalendarHeader.js.map +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_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/cards/RuiCard.js.map +1 -1
- package/dist/components/cards/RuiCard.vue.d.ts +1 -1
- package/dist/components/cards/RuiCard.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/cards/RuiCardHeader.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.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.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.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.js.map +1 -1
- package/dist/components/color-picker/RuiColorHue.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/color-picker/RuiColorInput.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.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_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/date-time-picker/RuiDateTimePickerMenu.js.map +1 -1
- package/dist/components/date-time-picker/RuiDateTimePickerMenu.vue.d.ts +1 -1
- 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.js.map +1 -1
- package/dist/components/date-time-picker/RuiTimezoneSelect.vue.d.ts +2 -2
- package/dist/components/date-time-picker/RuiTimezoneSelect.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/divider/RuiDivider.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 +1 -1
- 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.map +1 -1
- package/dist/components/forms/auto-complete/RuiAutoCompleteOption.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/forms/auto-complete/RuiAutoCompleteOptionList.js.map +1 -1
- package/dist/components/forms/auto-complete/RuiAutoCompleteOptionList.vue.d.ts +1 -1
- package/dist/components/forms/auto-complete/RuiAutoCompleteOptionList.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/forms/auto-complete/RuiAutoCompleteSelection.js.map +1 -1
- package/dist/components/forms/auto-complete/RuiAutoCompleteSelection.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/forms/auto-complete/auto-complete-props.d.ts +2 -2
- 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 +6 -2
- package/dist/components/forms/category-picker/RuiCategoryPicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/forms/checkbox/RuiCheckbox.js.map +1 -1
- 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.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/field-defaults/RuiFieldDefaults.js.map +1 -1
- package/dist/components/forms/field-defaults/RuiFieldDefaults.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/forms/field-label/RuiFieldLabel.js.map +1 -1
- package/dist/components/forms/field-label/RuiFieldLabel.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 +4 -1
- package/dist/components/forms/file-upload/RuiFileUpload.vue_vue_type_script_setup_true_lang.js +17 -8
- 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.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.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.map +1 -1
- package/dist/components/forms/select/RuiSimpleSelect.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/slider/RuiSlider.js.map +1 -1
- package/dist/components/forms/slider/RuiSlider.vue.d.ts +1 -1
- package/dist/components/forms/slider/RuiSlider.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/forms/slider/RuiSliderTicks.js.map +1 -1
- package/dist/components/forms/slider/RuiSliderTicks.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/forms/switch/RuiSwitch.js.map +1 -1
- package/dist/components/forms/switch/RuiSwitch.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/forms/text-area/RuiTextArea.js.map +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-field/RuiTextField.js.map +1 -1
- package/dist/components/forms/text-field/RuiTextField.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/helpers/RuiFormTextDetail.js.map +1 -1
- package/dist/components/helpers/RuiFormTextDetail.vue_vue_type_script_setup_true_lang.js +1 -2
- 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 +11 -10
- package/dist/components/icons/RuiIcon.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/index.d.ts +57 -57
- package/dist/components/loaders/RuiSkeletonBase.js.map +1 -1
- package/dist/components/loaders/RuiSkeletonBase.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/loaders/RuiSkeletonLoader.js.map +1 -1
- package/dist/components/loaders/RuiSkeletonLoader.vue.d.ts +1 -1
- package/dist/components/loaders/RuiSkeletonLoader.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/logos/RuiLogo.js.map +1 -1
- package/dist/components/logos/RuiLogo.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/overlays/badge/RuiBadge.js.map +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_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 +1 -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.d.ts +1 -1
- 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.d.ts +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.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.js.map +1 -1
- package/dist/components/overlays/tooltip/RuiTooltip.vue.d.ts +1 -1
- package/dist/components/overlays/tooltip/RuiTooltip.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/progress/RuiProgress.js.map +1 -1
- package/dist/components/progress/RuiProgress.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/steppers/RuiFooterStepper.js.map +1 -1
- package/dist/components/steppers/RuiFooterStepper.vue_vue_type_script_setup_true_lang.js +6 -2
- 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.d.ts +1 -1
- package/dist/components/steppers/RuiStepper.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/steppers/RuiStepperIcon.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 +11 -2
- package/dist/components/tables/RuiDataTable.vue_vue_type_script_setup_true_lang.js +8 -3
- package/dist/components/tables/RuiDataTable.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/tables/RuiExpandButton.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.map +1 -1
- package/dist/components/tables/RuiTable.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/tables/RuiTableEmptyState.js.map +1 -1
- package/dist/components/tables/RuiTableEmptyState.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/tables/RuiTableErrorState.js.map +1 -1
- package/dist/components/tables/RuiTableErrorState.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/tables/RuiTableHead.js.map +1 -1
- package/dist/components/tables/RuiTableHead.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/tables/RuiTableLoadingState.js.map +1 -1
- package/dist/components/tables/RuiTableLoadingState.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/tables/RuiTablePagination.js.map +1 -1
- package/dist/components/tables/RuiTablePagination.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/tables/data-table/RuiDataTableAppendRow.js +7 -0
- package/dist/components/tables/data-table/RuiDataTableAppendRow.js.map +1 -0
- package/dist/components/tables/data-table/RuiDataTableAppendRow.vue.d.ts +26 -0
- package/dist/components/tables/data-table/RuiDataTableAppendRow.vue_vue_type_script_setup_true_lang.js +39 -0
- package/dist/components/tables/data-table/RuiDataTableAppendRow.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/tables/data-table/RuiDataTableBody.js.map +1 -1
- package/dist/components/tables/data-table/RuiDataTableBody.vue.d.ts +5 -1
- package/dist/components/tables/data-table/RuiDataTableBody.vue_vue_type_script_setup_true_lang.js +18 -10
- 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.map +1 -1
- package/dist/components/tables/data-table/RuiDataTableEmptyRow.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/RuiDataTableErrorRow.js.map +1 -1
- package/dist/components/tables/data-table/RuiDataTableErrorRow.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.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.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.map +1 -1
- package/dist/components/tables/data-table/RuiDataTableMobileSort.js.map +1 -1
- package/dist/components/tables/data-table/RuiDataTableMobileSort.vue.d.ts +1 -1
- 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 +5 -1
- package/dist/components/tables/data-table/RuiDataTableRow.vue_vue_type_script_setup_true_lang.js +144 -88
- 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 +1 -1
- package/dist/components/tables/data-table-styles.js +1 -1
- 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.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_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_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/time-picker/RuiTimePicker.js.map +1 -1
- package/dist/components/time-picker/RuiTimePicker.vue_vue_type_script_setup_true_lang.js +12 -8
- package/dist/components/time-picker/RuiTimePicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/composables/floating.d.ts +1 -1
- package/dist/composables/icons.d.ts +1 -1
- package/dist/composables/icons.js +1 -7
- package/dist/composables/icons.js.map +1 -1
- package/dist/composables/tables/data-table/columns.d.ts +1 -1
- package/dist/composables/tables/data-table/grouping.d.ts +1 -1
- package/dist/composables/tables/data-table/page-scroll.d.ts +1 -1
- package/dist/composables/tables/data-table/pagination.d.ts +2 -2
- package/dist/composables/tables/data-table/sort.d.ts +2 -2
- package/dist/composables/tables/data-table/types.d.ts +2 -2
- package/dist/i18n/keys.d.ts +9 -0
- package/dist/i18n/keys.js +9 -0
- package/dist/i18n/keys.js.map +1 -1
- package/dist/icons/icons_1.d.ts +26 -26
- package/dist/icons/icons_1.js +348 -365
- package/dist/icons/icons_1.js.map +1 -1
- package/dist/icons/icons_2.d.ts +28 -28
- package/dist/icons/icons_2.js +434 -323
- package/dist/icons/icons_2.js.map +1 -1
- package/dist/icons/icons_3.d.ts +32 -32
- package/dist/icons/icons_3.js +334 -364
- package/dist/icons/icons_3.js.map +1 -1
- package/dist/icons/icons_4.d.ts +64 -64
- package/dist/icons/icons_4.js +769 -669
- package/dist/icons/icons_4.js.map +1 -1
- package/dist/icons/icons_5.d.ts +66 -9
- package/dist/icons/icons_5.js +693 -83
- package/dist/icons/icons_5.js.map +1 -1
- package/dist/icons/index.d.ts +1 -1
- package/dist/icons/index.js +108 -51
- package/dist/icons/index.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +6 -6
- package/dist/style.css +22 -4
- package/dist/types/theme.d.ts +1 -1
- package/dist/utils/tv.d.ts +1 -1
- package/dist/vendor/@vueuse/core/dist/index.js +63 -55
- package/dist/vendor/@vueuse/core/dist/index.js.map +1 -1
- package/dist/vendor/@vueuse/shared/dist/index.js +4 -4
- package/dist/vendor/@vueuse/shared/dist/index.js.map +1 -1
- package/dist/web-types.json +88 -4
- package/package.json +26 -26
|
@@ -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 { ButtonGroupBoundary } from '@/components/buttons/button-group/button-group-context';\nimport RuiFormTextDetail from '@/components/helpers/RuiFormTextDetail.vue';\nimport { type FloatingOptions, useFloating } from '@/composables/floating';\nimport { useFormTextDetail } from '@/utils/form-text-detail';\nimport { cn, tv } from '@/utils/tv';\n\ninterface BaseMenuAttrs { onMouseover?: () => void; onMouseleave?: () => void }\n\n/**\n * What the activator slot binds onto its trigger. The ARIA keys belong on an\n * element that can carry them (a button, link or combobox), never on a plain\n * `div`; an activator that sets its own ARIA takes `activatorHandlers(attrs)`.\n */\ninterface MenuAttrs extends BaseMenuAttrs {\n 'onClick'?: () => void;\n 'aria-haspopup': RuiMenuRole | 'true';\n 'aria-expanded': boolean;\n 'aria-controls'?: string;\n}\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 /** Overrides applied to the hint and messages under the activator. */\n details?: 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 classNames?: RuiMenuClassNames;\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 * Accessible name of the teleported popover. A `dialog` popover needs one;\n * the other roles take it from their activator or options.\n */\n menuLabel?: string;\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 classNames,\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 menuLabel,\n} = defineProps<MenuProps>();\n\ndefineSlots<{\n activator?: (props: {\n // An inline type literal, so callers can pass it on as `Record<string, unknown>`\n attrs: {\n 'onMouseover'?: () => void;\n 'onMouseleave'?: () => void;\n 'onClick'?: () => void;\n 'aria-haspopup': RuiMenuRole | 'true';\n 'aria-expanded': boolean;\n 'aria-controls'?: string;\n };\n open: boolean;\n disabled: boolean;\n hasError: boolean;\n hasSuccess: boolean;\n }) => any;\n default?: (props: { width: number }) => any;\n /** Rendered above the activator, outside the element the menu positions against. */\n label?: () => any;\n}>();\n\nconst click = ref<boolean>(false);\nconst menuContent = useTemplateRef<HTMLElement>('menuContent');\nconst menuId = useId();\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 () => 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-rui-menu',\n // a hairline edge keeps the popup apart from a surface of nearly the same shade in dark mode\n content: 'rounded-rui-panel overflow-hidden shadow-rui-menu bg-rui-menu border border-rui-divider text-rui-text focus:outline-hidden p-1',\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 'aria-haspopup': get(ariaHasPopup),\n 'aria-expanded': get(open),\n // Only while the popover is in the DOM, so the reference never points at a missing element\n 'aria-controls': get(visible) ? menuId : undefined,\n}));\n\n/**\n * Moves focus into the open menu without scrolling the page. A menu taller than the space below its\n * activator would otherwise make the browser scroll the whole document to reveal the focused\n * container, sliding the page out from under the activator.\n */\nfunction focusOnContent() {\n const content = get(menuContent);\n if (!content)\n return;\n\n content.focus({ preventScroll: true });\n}\n\nfunction focusMenu(): void {\n if (disableAutoFocus)\n return;\n\n nextTick(() => focusOnContent());\n}\n\n/** Hands focus back to the activator on close, likewise without scrolling to it. */\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({ preventScroll: true });\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 <slot name=\"label\" />\n <div\n ref=\"activator\"\n :class=\"ui.wrapper({ class: cn(classNames?.wrapper) })\"\n :data-menu-disabled=\"disabled\"\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 :id=\"menuId\"\n ref=\"menu\"\n :class=\"ui.popover({ class: cn(classNames?.menu) })\"\n :role=\"role\"\n :aria-label=\"menuLabel\"\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 <ButtonGroupBoundary>\n <slot v-bind=\"{ width }\" />\n </ButtonGroupBoundary>\n </div>\n </TransitionGroup>\n </div>\n </Teleport>\n <RuiFormTextDetail\n v-if=\"showDetails\"\n :class=\"ui.details({ class: cn(classNames?.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":["_useModel","_openBlock","_createElementBlock","_normalizeClass","_withKeys","_renderSlot","_createElementVNode","_unref","_normalizeProps","_guardReactiveProps","_createBlock","_Teleport","_createVNode","_TransitionGroup","_withCtx","_mergeProps","_createCommentVNode","RuiFormTextDetail"],"sources":["../../../../src/components/overlays/menu/RuiMenu.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { VueClassValue } from '@/types/class-value';\nimport { ButtonGroupBoundary } from '@/components/buttons/button-group/button-group-context';\nimport RuiFormTextDetail from '@/components/helpers/RuiFormTextDetail.vue';\nimport { type FloatingOptions, useFloating } from '@/composables/floating';\nimport { useFormTextDetail } from '@/utils/form-text-detail';\nimport { cn, tv } from '@/utils/tv';\n\ninterface BaseMenuAttrs { onMouseover?: () => void; onMouseleave?: () => void }\n\n/**\n * What the activator slot binds onto its trigger. The ARIA keys belong on an\n * element that can carry them (a button, link or combobox), never on a plain\n * `div`; an activator that sets its own ARIA takes `activatorHandlers(attrs)`.\n */\ninterface MenuAttrs extends BaseMenuAttrs {\n 'onClick'?: () => void;\n 'aria-haspopup': RuiMenuRole | 'true';\n 'aria-expanded': boolean;\n 'aria-controls'?: string;\n}\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 /** Overrides applied to the hint and messages under the activator. */\n details?: 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 classNames?: RuiMenuClassNames;\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 * Accessible name of the teleported popover. A `dialog` popover needs one;\n * the other roles take it from their activator or options.\n */\n menuLabel?: string;\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 classNames,\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 menuLabel,\n} = defineProps<MenuProps>();\n\ndefineSlots<{\n activator?: (props: {\n // An inline type literal, so callers can pass it on as `Record<string, unknown>`\n attrs: {\n 'onMouseover'?: () => void;\n 'onMouseleave'?: () => void;\n 'onClick'?: () => void;\n 'aria-haspopup': RuiMenuRole | 'true';\n 'aria-expanded': boolean;\n 'aria-controls'?: string;\n };\n open: boolean;\n disabled: boolean;\n hasError: boolean;\n hasSuccess: boolean;\n }) => any;\n default?: (props: { width: number }) => any;\n /** Rendered above the activator, outside the element the menu positions against. */\n label?: () => any;\n}>();\n\nconst click = ref<boolean>(false);\nconst menuContent = useTemplateRef<HTMLElement>('menuContent');\nconst menuId = useId();\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 () => 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-rui-menu',\n // a hairline edge keeps the popup apart from a surface of nearly the same shade in dark mode\n content: 'rounded-rui-panel overflow-hidden shadow-rui-menu bg-rui-menu border border-rui-divider text-rui-text focus:outline-hidden p-1',\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 'aria-haspopup': get(ariaHasPopup),\n 'aria-expanded': get(open),\n // Only while the popover is in the DOM, so the reference never points at a missing element\n 'aria-controls': get(visible) ? menuId : undefined,\n}));\n\n/**\n * Moves focus into the open menu without scrolling the page. A menu taller than the space below its\n * activator would otherwise make the browser scroll the whole document to reveal the focused\n * container, sliding the page out from under the activator.\n */\nfunction focusOnContent() {\n const content = get(menuContent);\n if (!content)\n return;\n\n content.focus({ preventScroll: true });\n}\n\nfunction focusMenu(): void {\n if (disableAutoFocus)\n return;\n\n nextTick(() => focusOnContent());\n}\n\n/** Hands focus back to the activator on close, likewise without scrolling to it. */\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({ preventScroll: true });\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 <slot name=\"label\" />\n <div\n ref=\"activator\"\n :class=\"ui.wrapper({ class: cn(classNames?.wrapper) })\"\n :data-menu-disabled=\"disabled\"\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 :id=\"menuId\"\n ref=\"menu\"\n :class=\"ui.popover({ class: cn(classNames?.menu) })\"\n :role=\"role\"\n :aria-label=\"menuLabel\"\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 <ButtonGroupBoundary>\n <slot v-bind=\"{ width }\" />\n </ButtonGroupBoundary>\n </div>\n </TransitionGroup>\n </div>\n </Teleport>\n <RuiFormTextDetail\n v-if=\"showDetails\"\n :class=\"ui.details({ class: cn(classNames?.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 { ClassValue } from 'vue';\nimport type { VueClassValue } from '@/types/class-value';\nimport type { MaybeElement } from '@/types/dom';\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 ariaLabel?: string;\n /**\n * Starts the drawer, and its overlay, below the app bar (`--rui-app-bar-height`), so the app bar\n * stays uncovered and usable while the drawer is open. Without it the drawer runs the full height and\n * a modal one covers the app bar.\n */\n belowAppBar?: boolean;\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 ariaLabel,\n belowAppBar = false,\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 bottom-0 fixed text-rui-text',\n variants: {\n belowAppBar: {\n true: 'top-rui-app-bar',\n false: 'top-0',\n },\n // a temporary drawer floats on the overlay surface; a docked one is part of the page, edged by a hairline\n temporary: {\n true: 'bg-rui-overlay',\n false: 'bg-rui-surface',\n },\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 // a modal drawer covers the app bar; a docked one sits level with it\n withOverlay: {\n true: 'z-rui-drawer',\n false: 'z-rui-app-bar',\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 { temporary: false, position: 'left', class: 'border-r border-rui-divider' },\n { temporary: false, position: 'right', class: 'border-l border-rui-divider' },\n ],\n defaultVariants: { position: 'left', visible: false, mini: false, withOverlay: false, temporary: false, belowAppBar: false },\n});\n\n// the overlay dims what the drawer covers: the whole view, or only the part below the app bar\nconst overlayClass = computed<string>(() => cn([\n 'fixed inset-x-0 bottom-0 backdrop-blur-sm bg-rui-neutral-950/40 dark:bg-black/60 z-rui-drawer',\n belowAppBar ? 'top-rui-app-bar' : 'top-0',\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 temporary,\n belowAppBar,\n class: cn([\n temporary && modelValue.value && 'shadow-rui-drawer',\n classNames?.content,\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=\"overlayClass\"\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 v-bind=\"getRootAttrs($attrs, [])\"\n >\n <slot v-bind=\"{ attrs: activatorAttrs, close }\" />\n </aside>\n </Teleport>\n </div>\n</template>\n"],"mappings":""}
|
|
1
|
+
{"version":3,"file":"RuiNavigationDrawer.js","names":["_sfc_main"],"sources":["../../../../src/components/overlays/navigation-drawer/RuiNavigationDrawer.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { ClassValue } from 'vue';\nimport type { VueClassValue } from '@/types/class-value';\nimport type { MaybeElement } from '@/types/dom';\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 ariaLabel?: string;\n /**\n * Starts the drawer, and its overlay, below the app bar (`--rui-app-bar-height`), so the app bar\n * stays uncovered and usable while the drawer is open. Without it the drawer runs the full height and\n * a modal one covers the app bar.\n */\n belowAppBar?: boolean;\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 ariaLabel,\n belowAppBar = false,\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 bottom-0 fixed text-rui-text',\n variants: {\n belowAppBar: {\n true: 'top-rui-app-bar',\n false: 'top-0',\n },\n // a temporary drawer floats on the overlay surface; a docked one is part of the page, edged by a hairline\n temporary: {\n true: 'bg-rui-overlay',\n false: 'bg-rui-surface',\n },\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 // a modal drawer covers the app bar; a docked one sits level with it\n withOverlay: {\n true: 'z-rui-drawer',\n false: 'z-rui-app-bar',\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 { temporary: false, position: 'left', class: 'border-r border-rui-divider' },\n { temporary: false, position: 'right', class: 'border-l border-rui-divider' },\n ],\n defaultVariants: { position: 'left', visible: false, mini: false, withOverlay: false, temporary: false, belowAppBar: false },\n});\n\n// the overlay dims what the drawer covers: the whole view, or only the part below the app bar\nconst overlayClass = computed<string>(() => cn([\n 'fixed inset-x-0 bottom-0 backdrop-blur-sm bg-rui-neutral-950/40 dark:bg-black/60 z-rui-drawer',\n belowAppBar ? 'top-rui-app-bar' : 'top-0',\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 temporary,\n belowAppBar,\n class: cn([\n temporary && modelValue.value && 'shadow-rui-drawer',\n classNames?.content,\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=\"overlayClass\"\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 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 { ClassValue } from 'vue';\nimport type { VueClassValue } from '@/types/class-value';\nimport type { MaybeElement } from '@/types/dom';\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 ariaLabel?: string;\n /**\n * Starts the drawer, and its overlay, below the app bar (`--rui-app-bar-height`), so the app bar\n * stays uncovered and usable while the drawer is open. Without it the drawer runs the full height and\n * a modal one covers the app bar.\n */\n belowAppBar?: boolean;\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 ariaLabel,\n belowAppBar = false,\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 bottom-0 fixed text-rui-text',\n variants: {\n belowAppBar: {\n true: 'top-rui-app-bar',\n false: 'top-0',\n },\n // a temporary drawer floats on the overlay surface; a docked one is part of the page, edged by a hairline\n temporary: {\n true: 'bg-rui-overlay',\n false: 'bg-rui-surface',\n },\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 // a modal drawer covers the app bar; a docked one sits level with it\n withOverlay: {\n true: 'z-rui-drawer',\n false: 'z-rui-app-bar',\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 { temporary: false, position: 'left', class: 'border-r border-rui-divider' },\n { temporary: false, position: 'right', class: 'border-l border-rui-divider' },\n ],\n defaultVariants: { position: 'left', visible: false, mini: false, withOverlay: false, temporary: false, belowAppBar: false },\n});\n\n// the overlay dims what the drawer covers: the whole view, or only the part below the app bar\nconst overlayClass = computed<string>(() => cn([\n 'fixed inset-x-0 bottom-0 backdrop-blur-sm bg-rui-neutral-950/40 dark:bg-black/60 z-rui-drawer',\n belowAppBar ? 'top-rui-app-bar' : 'top-0',\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 temporary,\n belowAppBar,\n class: cn([\n temporary && modelValue.value && 'shadow-rui-drawer',\n classNames?.content,\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=\"overlayClass\"\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 v-bind=\"getRootAttrs($attrs, [])\"\n >\n <slot v-bind=\"{ attrs: activatorAttrs, close }\" />\n </aside>\n </Teleport>\n </div>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAmCA,MAAM,
|
|
1
|
+
{"version":3,"file":"RuiNavigationDrawer.vue_vue_type_script_setup_true_lang.js","names":["$attrs","_useModel","_openBlock","_createElementBlock","_renderSlot","_normalizeProps","_guardReactiveProps","_createBlock","_Teleport","_Transition","_withCtx","_normalizeClass","_unref","_withModifiers","_createCommentVNode","_mergeProps"],"sources":["../../../../src/components/overlays/navigation-drawer/RuiNavigationDrawer.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { ClassValue } from 'vue';\nimport type { VueClassValue } from '@/types/class-value';\nimport type { MaybeElement } from '@/types/dom';\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 ariaLabel?: string;\n /**\n * Starts the drawer, and its overlay, below the app bar (`--rui-app-bar-height`), so the app bar\n * stays uncovered and usable while the drawer is open. Without it the drawer runs the full height and\n * a modal one covers the app bar.\n */\n belowAppBar?: boolean;\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 ariaLabel,\n belowAppBar = false,\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 bottom-0 fixed text-rui-text',\n variants: {\n belowAppBar: {\n true: 'top-rui-app-bar',\n false: 'top-0',\n },\n // a temporary drawer floats on the overlay surface; a docked one is part of the page, edged by a hairline\n temporary: {\n true: 'bg-rui-overlay',\n false: 'bg-rui-surface',\n },\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 // a modal drawer covers the app bar; a docked one sits level with it\n withOverlay: {\n true: 'z-rui-drawer',\n false: 'z-rui-app-bar',\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 { temporary: false, position: 'left', class: 'border-r border-rui-divider' },\n { temporary: false, position: 'right', class: 'border-l border-rui-divider' },\n ],\n defaultVariants: { position: 'left', visible: false, mini: false, withOverlay: false, temporary: false, belowAppBar: false },\n});\n\n// the overlay dims what the drawer covers: the whole view, or only the part below the app bar\nconst overlayClass = computed<string>(() => cn([\n 'fixed inset-x-0 bottom-0 backdrop-blur-sm bg-rui-neutral-950/40 dark:bg-black/60 z-rui-drawer',\n belowAppBar ? 'top-rui-app-bar' : 'top-0',\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 temporary,\n belowAppBar,\n class: cn([\n temporary && modelValue.value && 'shadow-rui-drawer',\n classNames?.content,\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=\"overlayClass\"\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 v-bind=\"getRootAttrs($attrs, [])\"\n >\n <slot v-bind=\"{ attrs: activatorAttrs, close }\" />\n </aside>\n </Teleport>\n </div>\n</template>\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RuiNotification.js","names":[],"sources":["../../../../src/components/overlays/notification/RuiNotification.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport { useTimeoutFn } from '@vueuse/core';\nimport { transformPropsUnit } from '@/utils/helpers';\nimport { cn, tv } from '@/utils/tv';\n\nexport interface NotificationProps {\n timeout: number;\n width?: number | string;\n theme?: 'light' | 'dark';\n}\n\ndefineOptions({\n name: 'RuiNotification',\n inheritAttrs: false,\n});\n\nconst modelValue = defineModel<boolean>({ required: true });\n\nconst { timeout, width = 400, theme } = defineProps<NotificationProps>();\n\ndefineSlots<{\n default?: () => any;\n}>();\n\nconst style = computed<{ width: string | undefined }>(() => ({\n width: transformPropsUnit(width),\n}));\n\n// a popup like a menu: panel corners, a hairline edge for dark backgrounds, and never wider than the screen\nconst rootStyle = tv({ base: 'top-4 right-4 fixed z-rui-toast max-w-[calc(100vw-2rem)] overflow-hidden rounded-rui-panel border shadow-rui-menu' });\n\nconst { start, stop } = useTimeoutFn(() => {\n set(modelValue, false);\n}, timeout, { immediate: false });\n\nfunction dismiss(): void {\n if (timeout < 0)\n return;\n\n set(modelValue, false);\n}\n\nwatchImmediate(modelValue, (display) => {\n if (!display) {\n stop();\n return;\n }\n\n if (timeout > 0) {\n stop();\n start();\n }\n});\n</script>\n\n<template>\n <Teleport to=\"body\">\n <Transition\n enter-from-class=\"opacity-0\"\n enter-active-class=\"ease-out duration-150\"\n enter-to-class=\"opacity-100\"\n leave-from-class=\"opacity-100\"\n leave-active-class=\"ease-in duration-100\"\n leave-to-class=\"opacity-0\"\n >\n <div\n v-if=\"modelValue\"\n role=\"alert\"\n aria-live=\"polite\"\n :class=\"rootStyle({ class: cn([$attrs.class, {\n 'bg-rui-overlay border-rui-divider': !theme,\n 'bg-rui-light-overlay text-rui-light-text border-rui-light-divider': theme === 'light',\n 'bg-rui-dark-overlay text-rui-dark-text border-rui-dark-divider': theme === 'dark',\n }]) })\"\n :style=\"style\"\n v-bind=\"{ ...$attrs, class: undefined }\"\n @click=\"dismiss()\"\n >\n <slot />\n </div>\n </Transition>\n </Teleport>\n</template>\n"],"mappings":""}
|
|
1
|
+
{"version":3,"file":"RuiNotification.js","names":["_sfc_main"],"sources":["../../../../src/components/overlays/notification/RuiNotification.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport { useTimeoutFn } from '@vueuse/core';\nimport { transformPropsUnit } from '@/utils/helpers';\nimport { cn, tv } from '@/utils/tv';\n\nexport interface NotificationProps {\n timeout: number;\n width?: number | string;\n theme?: 'light' | 'dark';\n}\n\ndefineOptions({\n name: 'RuiNotification',\n inheritAttrs: false,\n});\n\nconst modelValue = defineModel<boolean>({ required: true });\n\nconst { timeout, width = 400, theme } = defineProps<NotificationProps>();\n\ndefineSlots<{\n default?: () => any;\n}>();\n\nconst style = computed<{ width: string | undefined }>(() => ({\n width: transformPropsUnit(width),\n}));\n\n// a popup like a menu: panel corners, a hairline edge for dark backgrounds, and never wider than the screen\nconst rootStyle = tv({ base: 'top-4 right-4 fixed z-rui-toast max-w-[calc(100vw-2rem)] overflow-hidden rounded-rui-panel border shadow-rui-menu' });\n\nconst { start, stop } = useTimeoutFn(() => {\n set(modelValue, false);\n}, timeout, { immediate: false });\n\nfunction dismiss(): void {\n if (timeout < 0)\n return;\n\n set(modelValue, false);\n}\n\nwatchImmediate(modelValue, (display) => {\n if (!display) {\n stop();\n return;\n }\n\n if (timeout > 0) {\n stop();\n start();\n }\n});\n</script>\n\n<template>\n <Teleport to=\"body\">\n <Transition\n enter-from-class=\"opacity-0\"\n enter-active-class=\"ease-out duration-150\"\n enter-to-class=\"opacity-100\"\n leave-from-class=\"opacity-100\"\n leave-active-class=\"ease-in duration-100\"\n leave-to-class=\"opacity-0\"\n >\n <div\n v-if=\"modelValue\"\n role=\"alert\"\n aria-live=\"polite\"\n :class=\"rootStyle({ class: cn([$attrs.class, {\n 'bg-rui-overlay border-rui-divider': !theme,\n 'bg-rui-light-overlay text-rui-light-text border-rui-light-divider': theme === 'light',\n 'bg-rui-dark-overlay text-rui-dark-text border-rui-dark-divider': theme === 'dark',\n }]) })\"\n :style=\"style\"\n v-bind=\"{ ...$attrs, class: undefined }\"\n @click=\"dismiss()\"\n >\n <slot />\n </div>\n </Transition>\n </Teleport>\n</template>\n"],"mappings":""}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RuiNotification.vue_vue_type_script_setup_true_lang.js","names":["$attrs"],"sources":["../../../../src/components/overlays/notification/RuiNotification.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport { useTimeoutFn } from '@vueuse/core';\nimport { transformPropsUnit } from '@/utils/helpers';\nimport { cn, tv } from '@/utils/tv';\n\nexport interface NotificationProps {\n timeout: number;\n width?: number | string;\n theme?: 'light' | 'dark';\n}\n\ndefineOptions({\n name: 'RuiNotification',\n inheritAttrs: false,\n});\n\nconst modelValue = defineModel<boolean>({ required: true });\n\nconst { timeout, width = 400, theme } = defineProps<NotificationProps>();\n\ndefineSlots<{\n default?: () => any;\n}>();\n\nconst style = computed<{ width: string | undefined }>(() => ({\n width: transformPropsUnit(width),\n}));\n\n// a popup like a menu: panel corners, a hairline edge for dark backgrounds, and never wider than the screen\nconst rootStyle = tv({ base: 'top-4 right-4 fixed z-rui-toast max-w-[calc(100vw-2rem)] overflow-hidden rounded-rui-panel border shadow-rui-menu' });\n\nconst { start, stop } = useTimeoutFn(() => {\n set(modelValue, false);\n}, timeout, { immediate: false });\n\nfunction dismiss(): void {\n if (timeout < 0)\n return;\n\n set(modelValue, false);\n}\n\nwatchImmediate(modelValue, (display) => {\n if (!display) {\n stop();\n return;\n }\n\n if (timeout > 0) {\n stop();\n start();\n }\n});\n</script>\n\n<template>\n <Teleport to=\"body\">\n <Transition\n enter-from-class=\"opacity-0\"\n enter-active-class=\"ease-out duration-150\"\n enter-to-class=\"opacity-100\"\n leave-from-class=\"opacity-100\"\n leave-active-class=\"ease-in duration-100\"\n leave-to-class=\"opacity-0\"\n >\n <div\n v-if=\"modelValue\"\n role=\"alert\"\n aria-live=\"polite\"\n :class=\"rootStyle({ class: cn([$attrs.class, {\n 'bg-rui-overlay border-rui-divider': !theme,\n 'bg-rui-light-overlay text-rui-light-text border-rui-light-divider': theme === 'light',\n 'bg-rui-dark-overlay text-rui-dark-text border-rui-dark-divider': theme === 'dark',\n }]) })\"\n :style=\"style\"\n v-bind=\"{ ...$attrs, class: undefined }\"\n @click=\"dismiss()\"\n >\n <slot />\n </div>\n </Transition>\n </Teleport>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;EAgBA,MAAM,
|
|
1
|
+
{"version":3,"file":"RuiNotification.vue_vue_type_script_setup_true_lang.js","names":["$attrs","_useModel","_openBlock","_createBlock","_Teleport","_createVNode","_Transition","_withCtx","_createElementBlock","_mergeProps","_unref","_renderSlot","_createCommentVNode"],"sources":["../../../../src/components/overlays/notification/RuiNotification.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport { useTimeoutFn } from '@vueuse/core';\nimport { transformPropsUnit } from '@/utils/helpers';\nimport { cn, tv } from '@/utils/tv';\n\nexport interface NotificationProps {\n timeout: number;\n width?: number | string;\n theme?: 'light' | 'dark';\n}\n\ndefineOptions({\n name: 'RuiNotification',\n inheritAttrs: false,\n});\n\nconst modelValue = defineModel<boolean>({ required: true });\n\nconst { timeout, width = 400, theme } = defineProps<NotificationProps>();\n\ndefineSlots<{\n default?: () => any;\n}>();\n\nconst style = computed<{ width: string | undefined }>(() => ({\n width: transformPropsUnit(width),\n}));\n\n// a popup like a menu: panel corners, a hairline edge for dark backgrounds, and never wider than the screen\nconst rootStyle = tv({ base: 'top-4 right-4 fixed z-rui-toast max-w-[calc(100vw-2rem)] overflow-hidden rounded-rui-panel border shadow-rui-menu' });\n\nconst { start, stop } = useTimeoutFn(() => {\n set(modelValue, false);\n}, timeout, { immediate: false });\n\nfunction dismiss(): void {\n if (timeout < 0)\n return;\n\n set(modelValue, false);\n}\n\nwatchImmediate(modelValue, (display) => {\n if (!display) {\n stop();\n return;\n }\n\n if (timeout > 0) {\n stop();\n start();\n }\n});\n</script>\n\n<template>\n <Teleport to=\"body\">\n <Transition\n enter-from-class=\"opacity-0\"\n enter-active-class=\"ease-out duration-150\"\n enter-to-class=\"opacity-100\"\n leave-from-class=\"opacity-100\"\n leave-active-class=\"ease-in duration-100\"\n leave-to-class=\"opacity-0\"\n >\n <div\n v-if=\"modelValue\"\n role=\"alert\"\n aria-live=\"polite\"\n :class=\"rootStyle({ class: cn([$attrs.class, {\n 'bg-rui-overlay border-rui-divider': !theme,\n 'bg-rui-light-overlay text-rui-light-text border-rui-light-divider': theme === 'light',\n 'bg-rui-dark-overlay text-rui-dark-text border-rui-dark-divider': theme === 'dark',\n }]) })\"\n :style=\"style\"\n v-bind=\"{ ...$attrs, class: undefined }\"\n @click=\"dismiss()\"\n >\n <slot />\n </div>\n </Transition>\n </Teleport>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;EAgBA,MAAM,aAAaC,SAAoB,SAAA,YAAmB;EAQ1D,MAAM,QAAQ,gBAA+C,EAC3D,OAAO,mBAAmB,QAAA,KAAK,EACjC,EAAE;EAGF,MAAM,YAAY,GAAG,EAAE,MAAM,oHAAoH,CAAC;EAElJ,MAAM,EAAE,OAAO,SAAS,mBAAmB;GACzC,IAAI,YAAY,KAAK;EACvB,GAAG,QAAA,SAAS,EAAE,WAAW,MAAM,CAAC;EAEhC,SAAS,UAAgB;GACvB,IAAI,QAAA,UAAU,GACZ;GAEF,IAAI,YAAY,KAAK;EACvB;EAEA,eAAe,aAAa,YAAY;GACtC,IAAI,CAAC,SAAS;IACZ,KAAK;IACL;GACF;GAEA,IAAI,QAAA,UAAU,GAAG;IACf,KAAK;IACL,MAAM;GACR;EACF,CAAC;;GAIC,OAAAC,UAAA,GAAAC,YAyBWC,UAAA,EAzBD,IAAG,OAAM,GAAA,CACjBC,YAuBaC,YAAA;IAtBX,oBAAiB;IACjB,sBAAmB;IACnB,kBAAe;IACf,oBAAiB;IACjB,sBAAmB;IACnB,kBAAe;;IAEf,SAAAC,cAcM,CAbE,WAAA,SADRL,UAAA,GAAAM,mBAcM,OAdNC,WAcM;;KAZJ,MAAK;KACL,aAAU;KACT,OAAOC,MAAA,SAAA,CAAS,CAAA,EAAA,OAAUA,MAAA,EAAA,CAAE,CAAA,CAAEV,KAAAA,OAAO,OAAK;MAAoD,qCAAA,CAAA,QAAA;MAAsF,qEAAA,QAAA,UAAK;MAA0F,kEAAA,QAAA,UAAK;;KAKxR,OAAOU,MAAA,KAAA;IACKV,GAAAA;KAAAA,GAAAA,KAAAA;KAAM,OAAS,KAAA;IAAS,GAAA,EACpC,SAAK,OAAA,OAAA,OAAA,MAAA,WAAE,QAAO,GAAA,CAAA,GAAA,CAEfW,WAAQ,KAAA,QAAA,SAAA,CAAA,GAAA,EAAA,KAAA,mBAAA,IAAA,IAAA,CAAA,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RuiTooltip.js","names":[],"sources":["../../../../src/components/overlays/tooltip/RuiTooltip.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { VueClassValue } from '@/types/class-value';\nimport { ButtonGroupBoundary } from '@/components/buttons/button-group/button-group-context';\nimport { type FloatingOptions, useFloating } from '@/composables/floating';\nimport { cn, tv } from '@/utils/tv';\nimport { tooltipStyles } from './tooltip-styles';\n\nexport interface RuiTooltipClassNames {\n root?: VueClassValue;\n tooltip?: VueClassValue;\n}\n\nexport interface Props {\n text?: string | null;\n disabled?: boolean;\n hideArrow?: boolean;\n openDelay?: number;\n closeDelay?: number;\n persistOnTooltipHover?: boolean;\n options?: FloatingOptions;\n classNames?: RuiTooltipClassNames;\n}\n\ndefineOptions({\n name: 'RuiTooltip',\n inheritAttrs: false,\n});\n\nconst {\n text = null,\n disabled = false,\n hideArrow = false,\n openDelay = 0,\n closeDelay = 500,\n persistOnTooltipHover = false,\n options,\n classNames,\n} = defineProps<Props>();\n\ndefineSlots<{\n activator?: (props: { open: boolean; close: () => void }) => any;\n default?: () => any;\n}>();\n\nconst rootStyle = tv({ base: 'relative inline-flex' });\n\n// wraps at `--rui-tooltip-max-width`; a `max-w-*` in `classNames.tooltip` replaces it\nconst popoverStyle = tv({ base: 'w-max max-w-rui-tooltip z-rui-tooltip' });\n\nconst tooltipId = useId();\n\nconst {\n reference: activator,\n popover: tooltip,\n open,\n visible,\n currentPlacement,\n onOpen,\n onClose,\n onLeaveComplete,\n updatePosition,\n} = useFloating(\n () => options ?? {},\n () => disabled,\n () => openDelay,\n () => closeDelay,\n);\n\ntype PlacementSide = 'bottom' | 'left' | 'right' | 'top';\n\nconst placementSide = computed<PlacementSide>(() => {\n const placement = get(currentPlacement);\n if (placement.startsWith('top'))\n return 'top';\n if (placement.startsWith('left'))\n return 'left';\n if (placement.startsWith('right'))\n return 'right';\n return 'bottom';\n});\n\ndefineExpose({\n onOpen,\n onClose,\n});\n</script>\n\n<template>\n <div\n ref=\"activator\"\n v-bind=\"{ ...$attrs, class: undefined }\"\n :class=\"rootStyle({ class: cn($attrs.class) })\"\n :data-tooltip-disabled=\"disabled\"\n :aria-describedby=\"!disabled && open ? tooltipId : undefined\"\n @mouseover=\"onOpen()\"\n @mouseleave=\"onClose()\"\n @focusin=\"onOpen()\"\n @focusout=\"onClose()\"\n >\n <slot\n name=\"activator\"\n :open=\"open\"\n :close=\"onClose\"\n />\n\n <Teleport\n v-if=\"!disabled\"\n to=\"body\"\n >\n <div\n v-if=\"visible\"\n :id=\"tooltipId\"\n ref=\"tooltip\"\n :class=\"popoverStyle({ class: cn(classNames?.tooltip) })\"\n :role=\"open ? 'tooltip' : undefined\"\n :data-placement=\"currentPlacement\"\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=\"onLeaveComplete()\"\n >\n <div\n v-if=\"open\"\n key=\"tooltip\"\n class=\"px-2 py-1.5 text-xs font-normal wrap-break-word bg-rui-neutral-900 dark:bg-rui-neutral-700 text-white rounded-rui-control shadow-rui-tooltip\"\n data-id=\"content\"\n @mouseover=\"persistOnTooltipHover && onOpen()\"\n @mouseleave=\"persistOnTooltipHover && onClose()\"\n >\n <ButtonGroupBoundary>\n <slot>\n {{ text }}\n </slot>\n </ButtonGroupBoundary>\n </div>\n <span\n v-if=\"!hideArrow\"\n key=\"arrow\"\n :class=\"tooltipStyles({ open, side: placementSide }).arrow()\"\n data-id=\"arrow\"\n >\n <span :class=\"tooltipStyles({ open, side: placementSide }).diamond()\" />\n </span>\n </TransitionGroup>\n </div>\n </Teleport>\n </div>\n</template>\n"],"mappings":""}
|
|
1
|
+
{"version":3,"file":"RuiTooltip.js","names":["_sfc_main"],"sources":["../../../../src/components/overlays/tooltip/RuiTooltip.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { VueClassValue } from '@/types/class-value';\nimport { ButtonGroupBoundary } from '@/components/buttons/button-group/button-group-context';\nimport { type FloatingOptions, useFloating } from '@/composables/floating';\nimport { cn, tv } from '@/utils/tv';\nimport { tooltipStyles } from './tooltip-styles';\n\nexport interface RuiTooltipClassNames {\n root?: VueClassValue;\n tooltip?: VueClassValue;\n}\n\nexport interface Props {\n text?: string | null;\n disabled?: boolean;\n hideArrow?: boolean;\n openDelay?: number;\n closeDelay?: number;\n persistOnTooltipHover?: boolean;\n options?: FloatingOptions;\n classNames?: RuiTooltipClassNames;\n}\n\ndefineOptions({\n name: 'RuiTooltip',\n inheritAttrs: false,\n});\n\nconst {\n text = null,\n disabled = false,\n hideArrow = false,\n openDelay = 0,\n closeDelay = 500,\n persistOnTooltipHover = false,\n options,\n classNames,\n} = defineProps<Props>();\n\ndefineSlots<{\n activator?: (props: { open: boolean; close: () => void }) => any;\n default?: () => any;\n}>();\n\nconst rootStyle = tv({ base: 'relative inline-flex' });\n\n// wraps at `--rui-tooltip-max-width`; a `max-w-*` in `classNames.tooltip` replaces it\nconst popoverStyle = tv({ base: 'w-max max-w-rui-tooltip z-rui-tooltip' });\n\nconst tooltipId = useId();\n\nconst {\n reference: activator,\n popover: tooltip,\n open,\n visible,\n currentPlacement,\n onOpen,\n onClose,\n onLeaveComplete,\n updatePosition,\n} = useFloating(\n () => options ?? {},\n () => disabled,\n () => openDelay,\n () => closeDelay,\n);\n\ntype PlacementSide = 'bottom' | 'left' | 'right' | 'top';\n\nconst placementSide = computed<PlacementSide>(() => {\n const placement = get(currentPlacement);\n if (placement.startsWith('top'))\n return 'top';\n if (placement.startsWith('left'))\n return 'left';\n if (placement.startsWith('right'))\n return 'right';\n return 'bottom';\n});\n\ndefineExpose({\n onOpen,\n onClose,\n});\n</script>\n\n<template>\n <div\n ref=\"activator\"\n v-bind=\"{ ...$attrs, class: undefined }\"\n :class=\"rootStyle({ class: cn($attrs.class) })\"\n :data-tooltip-disabled=\"disabled\"\n :aria-describedby=\"!disabled && open ? tooltipId : undefined\"\n @mouseover=\"onOpen()\"\n @mouseleave=\"onClose()\"\n @focusin=\"onOpen()\"\n @focusout=\"onClose()\"\n >\n <slot\n name=\"activator\"\n :open=\"open\"\n :close=\"onClose\"\n />\n\n <Teleport\n v-if=\"!disabled\"\n to=\"body\"\n >\n <div\n v-if=\"visible\"\n :id=\"tooltipId\"\n ref=\"tooltip\"\n :class=\"popoverStyle({ class: cn(classNames?.tooltip) })\"\n :role=\"open ? 'tooltip' : undefined\"\n :data-placement=\"currentPlacement\"\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=\"onLeaveComplete()\"\n >\n <div\n v-if=\"open\"\n key=\"tooltip\"\n class=\"px-2 py-1.5 text-xs font-normal wrap-break-word bg-rui-neutral-900 dark:bg-rui-neutral-700 text-white rounded-rui-control shadow-rui-tooltip\"\n data-id=\"content\"\n @mouseover=\"persistOnTooltipHover && onOpen()\"\n @mouseleave=\"persistOnTooltipHover && onClose()\"\n >\n <ButtonGroupBoundary>\n <slot>\n {{ text }}\n </slot>\n </ButtonGroupBoundary>\n </div>\n <span\n v-if=\"!hideArrow\"\n key=\"arrow\"\n :class=\"tooltipStyles({ open, side: placementSide }).arrow()\"\n data-id=\"arrow\"\n >\n <span :class=\"tooltipStyles({ open, side: placementSide }).diamond()\" />\n </span>\n </TransitionGroup>\n </div>\n </Teleport>\n </div>\n</template>\n"],"mappings":""}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { VueClassValue } from '../../../types/class-value';
|
|
1
|
+
import type { VueClassValue } from '../../../types/class-value.js';
|
|
2
2
|
import { type FloatingOptions } from '../../../composables/floating.js';
|
|
3
3
|
export interface RuiTooltipClassNames {
|
|
4
4
|
root?: VueClassValue;
|
package/dist/components/overlays/tooltip/RuiTooltip.vue_vue_type_script_setup_true_lang.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RuiTooltip.vue_vue_type_script_setup_true_lang.js","names":["$attrs"],"sources":["../../../../src/components/overlays/tooltip/RuiTooltip.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { VueClassValue } from '@/types/class-value';\nimport { ButtonGroupBoundary } from '@/components/buttons/button-group/button-group-context';\nimport { type FloatingOptions, useFloating } from '@/composables/floating';\nimport { cn, tv } from '@/utils/tv';\nimport { tooltipStyles } from './tooltip-styles';\n\nexport interface RuiTooltipClassNames {\n root?: VueClassValue;\n tooltip?: VueClassValue;\n}\n\nexport interface Props {\n text?: string | null;\n disabled?: boolean;\n hideArrow?: boolean;\n openDelay?: number;\n closeDelay?: number;\n persistOnTooltipHover?: boolean;\n options?: FloatingOptions;\n classNames?: RuiTooltipClassNames;\n}\n\ndefineOptions({\n name: 'RuiTooltip',\n inheritAttrs: false,\n});\n\nconst {\n text = null,\n disabled = false,\n hideArrow = false,\n openDelay = 0,\n closeDelay = 500,\n persistOnTooltipHover = false,\n options,\n classNames,\n} = defineProps<Props>();\n\ndefineSlots<{\n activator?: (props: { open: boolean; close: () => void }) => any;\n default?: () => any;\n}>();\n\nconst rootStyle = tv({ base: 'relative inline-flex' });\n\n// wraps at `--rui-tooltip-max-width`; a `max-w-*` in `classNames.tooltip` replaces it\nconst popoverStyle = tv({ base: 'w-max max-w-rui-tooltip z-rui-tooltip' });\n\nconst tooltipId = useId();\n\nconst {\n reference: activator,\n popover: tooltip,\n open,\n visible,\n currentPlacement,\n onOpen,\n onClose,\n onLeaveComplete,\n updatePosition,\n} = useFloating(\n () => options ?? {},\n () => disabled,\n () => openDelay,\n () => closeDelay,\n);\n\ntype PlacementSide = 'bottom' | 'left' | 'right' | 'top';\n\nconst placementSide = computed<PlacementSide>(() => {\n const placement = get(currentPlacement);\n if (placement.startsWith('top'))\n return 'top';\n if (placement.startsWith('left'))\n return 'left';\n if (placement.startsWith('right'))\n return 'right';\n return 'bottom';\n});\n\ndefineExpose({\n onOpen,\n onClose,\n});\n</script>\n\n<template>\n <div\n ref=\"activator\"\n v-bind=\"{ ...$attrs, class: undefined }\"\n :class=\"rootStyle({ class: cn($attrs.class) })\"\n :data-tooltip-disabled=\"disabled\"\n :aria-describedby=\"!disabled && open ? tooltipId : undefined\"\n @mouseover=\"onOpen()\"\n @mouseleave=\"onClose()\"\n @focusin=\"onOpen()\"\n @focusout=\"onClose()\"\n >\n <slot\n name=\"activator\"\n :open=\"open\"\n :close=\"onClose\"\n />\n\n <Teleport\n v-if=\"!disabled\"\n to=\"body\"\n >\n <div\n v-if=\"visible\"\n :id=\"tooltipId\"\n ref=\"tooltip\"\n :class=\"popoverStyle({ class: cn(classNames?.tooltip) })\"\n :role=\"open ? 'tooltip' : undefined\"\n :data-placement=\"currentPlacement\"\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=\"onLeaveComplete()\"\n >\n <div\n v-if=\"open\"\n key=\"tooltip\"\n class=\"px-2 py-1.5 text-xs font-normal wrap-break-word bg-rui-neutral-900 dark:bg-rui-neutral-700 text-white rounded-rui-control shadow-rui-tooltip\"\n data-id=\"content\"\n @mouseover=\"persistOnTooltipHover && onOpen()\"\n @mouseleave=\"persistOnTooltipHover && onClose()\"\n >\n <ButtonGroupBoundary>\n <slot>\n {{ text }}\n </slot>\n </ButtonGroupBoundary>\n </div>\n <span\n v-if=\"!hideArrow\"\n key=\"arrow\"\n :class=\"tooltipStyles({ open, side: placementSide }).arrow()\"\n data-id=\"arrow\"\n >\n <span :class=\"tooltipStyles({ open, side: placementSide }).diamond()\" />\n </span>\n </TransitionGroup>\n </div>\n </Teleport>\n </div>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA4CA,MAAM,YAAY,GAAG,EAAE,MAAM,uBAAuB,CAAC;EAGrD,MAAM,eAAe,GAAG,EAAE,MAAM,wCAAwC,CAAC;EAEzE,MAAM,YAAY,MAAM;EAExB,MAAM,EACJ,WAAW,WACX,SAAS,SACT,MACA,SACA,kBACA,QACA,SACA,iBACA,mBACE,kBACI,QAAA,WAAW,CAAC,SACZ,QAAA,gBACA,QAAA,iBACA,QAAA,UACR;EAIA,MAAM,gBAAgB,eAA8B;GAClD,MAAM,YAAY,IAAI,gBAAgB;GACtC,IAAI,UAAU,WAAW,KAAK,GAC5B,OAAO;GACT,IAAI,UAAU,WAAW,MAAM,GAC7B,OAAO;GACT,IAAI,UAAU,WAAW,OAAO,GAC9B,OAAO;GACT,OAAO;EACT,CAAC;EAED,SAAa;GACX;GACA;EACF,CAAC;;GAIC,
|
|
1
|
+
{"version":3,"file":"RuiTooltip.vue_vue_type_script_setup_true_lang.js","names":["$attrs","_openBlock","_createElementBlock","_mergeProps","_unref","_renderSlot","_createBlock","_Teleport","_normalizeClass","_createVNode","_TransitionGroup","_withCtx","_createTextVNode","_toDisplayString","_createCommentVNode","_createElementVNode"],"sources":["../../../../src/components/overlays/tooltip/RuiTooltip.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { VueClassValue } from '@/types/class-value';\nimport { ButtonGroupBoundary } from '@/components/buttons/button-group/button-group-context';\nimport { type FloatingOptions, useFloating } from '@/composables/floating';\nimport { cn, tv } from '@/utils/tv';\nimport { tooltipStyles } from './tooltip-styles';\n\nexport interface RuiTooltipClassNames {\n root?: VueClassValue;\n tooltip?: VueClassValue;\n}\n\nexport interface Props {\n text?: string | null;\n disabled?: boolean;\n hideArrow?: boolean;\n openDelay?: number;\n closeDelay?: number;\n persistOnTooltipHover?: boolean;\n options?: FloatingOptions;\n classNames?: RuiTooltipClassNames;\n}\n\ndefineOptions({\n name: 'RuiTooltip',\n inheritAttrs: false,\n});\n\nconst {\n text = null,\n disabled = false,\n hideArrow = false,\n openDelay = 0,\n closeDelay = 500,\n persistOnTooltipHover = false,\n options,\n classNames,\n} = defineProps<Props>();\n\ndefineSlots<{\n activator?: (props: { open: boolean; close: () => void }) => any;\n default?: () => any;\n}>();\n\nconst rootStyle = tv({ base: 'relative inline-flex' });\n\n// wraps at `--rui-tooltip-max-width`; a `max-w-*` in `classNames.tooltip` replaces it\nconst popoverStyle = tv({ base: 'w-max max-w-rui-tooltip z-rui-tooltip' });\n\nconst tooltipId = useId();\n\nconst {\n reference: activator,\n popover: tooltip,\n open,\n visible,\n currentPlacement,\n onOpen,\n onClose,\n onLeaveComplete,\n updatePosition,\n} = useFloating(\n () => options ?? {},\n () => disabled,\n () => openDelay,\n () => closeDelay,\n);\n\ntype PlacementSide = 'bottom' | 'left' | 'right' | 'top';\n\nconst placementSide = computed<PlacementSide>(() => {\n const placement = get(currentPlacement);\n if (placement.startsWith('top'))\n return 'top';\n if (placement.startsWith('left'))\n return 'left';\n if (placement.startsWith('right'))\n return 'right';\n return 'bottom';\n});\n\ndefineExpose({\n onOpen,\n onClose,\n});\n</script>\n\n<template>\n <div\n ref=\"activator\"\n v-bind=\"{ ...$attrs, class: undefined }\"\n :class=\"rootStyle({ class: cn($attrs.class) })\"\n :data-tooltip-disabled=\"disabled\"\n :aria-describedby=\"!disabled && open ? tooltipId : undefined\"\n @mouseover=\"onOpen()\"\n @mouseleave=\"onClose()\"\n @focusin=\"onOpen()\"\n @focusout=\"onClose()\"\n >\n <slot\n name=\"activator\"\n :open=\"open\"\n :close=\"onClose\"\n />\n\n <Teleport\n v-if=\"!disabled\"\n to=\"body\"\n >\n <div\n v-if=\"visible\"\n :id=\"tooltipId\"\n ref=\"tooltip\"\n :class=\"popoverStyle({ class: cn(classNames?.tooltip) })\"\n :role=\"open ? 'tooltip' : undefined\"\n :data-placement=\"currentPlacement\"\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=\"onLeaveComplete()\"\n >\n <div\n v-if=\"open\"\n key=\"tooltip\"\n class=\"px-2 py-1.5 text-xs font-normal wrap-break-word bg-rui-neutral-900 dark:bg-rui-neutral-700 text-white rounded-rui-control shadow-rui-tooltip\"\n data-id=\"content\"\n @mouseover=\"persistOnTooltipHover && onOpen()\"\n @mouseleave=\"persistOnTooltipHover && onClose()\"\n >\n <ButtonGroupBoundary>\n <slot>\n {{ text }}\n </slot>\n </ButtonGroupBoundary>\n </div>\n <span\n v-if=\"!hideArrow\"\n key=\"arrow\"\n :class=\"tooltipStyles({ open, side: placementSide }).arrow()\"\n data-id=\"arrow\"\n >\n <span :class=\"tooltipStyles({ open, side: placementSide }).diamond()\" />\n </span>\n </TransitionGroup>\n </div>\n </Teleport>\n </div>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA4CA,MAAM,YAAY,GAAG,EAAE,MAAM,uBAAuB,CAAC;EAGrD,MAAM,eAAe,GAAG,EAAE,MAAM,wCAAwC,CAAC;EAEzE,MAAM,YAAY,MAAM;EAExB,MAAM,EACJ,WAAW,WACX,SAAS,SACT,MACA,SACA,kBACA,QACA,SACA,iBACA,mBACE,kBACI,QAAA,WAAW,CAAC,SACZ,QAAA,gBACA,QAAA,iBACA,QAAA,UACR;EAIA,MAAM,gBAAgB,eAA8B;GAClD,MAAM,YAAY,IAAI,gBAAgB;GACtC,IAAI,UAAU,WAAW,KAAK,GAC5B,OAAO;GACT,IAAI,UAAU,WAAW,MAAM,GAC7B,OAAO;GACT,IAAI,UAAU,WAAW,OAAO,GAC9B,OAAO;GACT,OAAO;EACT,CAAC;EAED,SAAa;GACX;GACA;EACF,CAAC;;GAIC,OAAAC,UAAA,GAAAC,mBAgEM,OAhENC,WAgEM;IA/DA,SAAA;IAAJ,KAAI;GACSH,GAAAA;IAAAA,GAAAA,KAAAA;IAAM,OAAS,KAAA;GAAS,GAAA;IACpC,OAAOI,MAAA,SAAA,CAAS,CAAA,EAAA,OAAUA,MAAA,EAAA,CAAE,CAACJ,KAAAA,OAAO,KAAK,EAAA,CAAA;IACzC,yBAAuB,QAAA;IACvB,oBAAgB,CAAG,QAAA,YAAYI,MAAA,IAAA,IAAOA,MAAA,SAAA,IAAY,KAAA;IAClD,aAAS,OAAA,OAAA,OAAA,MAAA,WAAEA,MAAA,MAAA,CAAM,CAAA;IACjB,cAAU,OAAA,OAAA,OAAA,MAAA,WAAEA,MAAA,OAAA,CAAO,CAAA;IACnB,WAAO,OAAA,OAAA,OAAA,MAAA,WAAEA,MAAA,MAAA,CAAM,CAAA;IACf,YAAQ,OAAA,OAAA,OAAA,MAAA,WAAEA,MAAA,OAAA,CAAO,CAAA;GAElBC,CAAAA,GAAAA,CAAAA,WAIE,KAAA,QAAA,aAAA;IAFC,MAAMD,MAAA,IAAA;IACN,OAAOA,MAAA,OAAA;GAID,CAAA,GAAA,CAAA,QAAA,YADTH,UAAA,GAAAK,YA8CWC,UAAA;;IA5CT,IAAG;GAGKH,GAAAA,CAAAA,MAAA,OAAA,KADRH,UAAA,GAAAC,mBAyCM,OAAA;;IAvCH,IAAIE,MAAA,SAAA;IACD,SAAA;IAAJ,KAAI;IACH,OAAKI,eAAEJ,MAAA,YAAA,CAAY,CAAA,EAAA,OAAUA,MAAA,EAAA,CAAE,CAAC,QAAA,YAAY,OAAO,EAAA,CAAA,CAAA;IACnD,MAAMA,MAAA,IAAA,IAAI,YAAe,KAAA;IACzB,kBAAgBA,MAAA,gBAAA;GAEjBK,GAAAA,CAAAA,YAgCkBC,iBAAA;IA/BhB,sBAAmB;IACnB,oBAAiB;IACjB,kBAAe;IACf,sBAAmB;IACnB,oBAAiB;IACjB,kBAAe;IACd,eAAY,OAAA,OAAA,OAAA,MAAA,WAAEN,MAAA,cAAA,CAAc,CAAA;IAC5B,cAAW,OAAA,OAAA,OAAA,MAAA,WAAEA,MAAA,eAAA,CAAe,CAAA;;IAE7B,SAAAO,cAaM,CAZEP,MAAA,IAAA,KADRH,UAAA,GAAAC,mBAaM,OAAA;KAXJ,KAAI;KACJ,OAAM;KACN,WAAQ;KACP,aAAS,OAAA,OAAA,OAAA,MAAA,WAAE,QAAA,yBAAyBE,MAAA,MAAA,CAAM,CAAA;KAC1C,cAAU,OAAA,OAAA,OAAA,MAAA,WAAE,QAAA,yBAAyBA,MAAA,OAAA,CAAO,CAAA;IAE7CK,GAAAA,CAAAA,YAIsBL,MAAA,mBAAA,GAAA,MAAA;KAHpB,SAAAO,cAEO,CAFPN,WAEO,KAAA,QAAA,WAAA,CAAA,SAAA,CADFO,gBAAAC,gBAAA,QAAA,IAAI,GAAA,CAAA,CAAA,CAAA,CAAA,CAAA;;IAKJ,CAAA,CAAA,GAAA,EAAA,KAAA,mBAAA,IAAA,IAAA,GAAA,CAAA,QAAA,aADTZ,UAAA,GAAAC,mBAOO,QAAA;KALL,KAAI;KACH,OAAKM,eAAEJ,MAAA,aAAA,CAAa,CAAA;MAAA,MAAGA,MAAA,IAAA;MAAI,MAAQA,MAAA,aAAA;KAAa,CAAA,CAAA,CAAI,MAAK,CAAA;KAC1D,WAAQ;IAERW,GAAAA,CAAAA,mBAAwE,QAAA,EAAjE,OAAKP,eAAEJ,MAAA,aAAA,CAAa,CAAA;KAAA,MAAGA,MAAA,IAAA;KAAI,MAAQA,MAAA,aAAA;IAAa,CAAA,CAAA,CAAI,QAAO,CAAA,EAAA,GAAA,MAAA,CAAA,CAAA,GAAA,CAAA,KAAA,mBAAA,IAAA,IAAA,CAAA,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RuiProgress.js","names":[],"sources":["../../../src/components/progress/RuiProgress.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport type { ContextColorsType } from '@/consts/colors';\nimport { ProgressVariant } from '@/components/progress/progress-props';\nimport { tv } from '@/utils/tv';\n\nexport interface Props {\n /**\n * in percentage value, required when variant === determinate or buffer\n * Ranges from 0 to 100.\n */\n value?: number;\n /**\n * in percentage value, required when variant === buffer\n * Ranges from 0 to 100.\n */\n bufferValue?: number;\n variant?: ProgressVariant;\n color?: ContextColorsType | 'inherit';\n circular?: boolean;\n showLabel?: boolean;\n /**\n * Sets the stroke thickness in pixels\n */\n thickness?: number | string;\n /**\n * only used for circular progress\n */\n size?: number | string;\n /**\n * What is loading, as the progress bar's accessible name (\"Loading\" when not given)\n */\n ariaLabel?: string;\n}\n\ndefineOptions({\n name: 'RuiProgress',\n});\n\nconst {\n value = 0,\n bufferValue = 0,\n variant = ProgressVariant.determinate,\n color = 'inherit',\n circular = false,\n showLabel = false,\n thickness = 4,\n size = 40,\n ariaLabel = 'Loading',\n} = defineProps<Props>();\n\ndefineSlots<Record<string, never>>();\n\nconst CIRCLE_RADIUS = 20;\nconst CIRCLE_CIRCUMFERENCE = 2 * Math.PI * CIRCLE_RADIUS; // ~125.66\n/** width of `100%` in ems, measured with tabular figures */\nconst LABEL_WIDTH_EM = 2.95;\n/** keeps the label off the stroke rather than merely inside it */\nconst LABEL_BREATHING_ROOM = 0.9;\n/** below this font size a label inside the ring is unreadable, so the ring drops it rather than change its footprint */\nconst MIN_INSIDE_LABEL_PX = 9;\n\nfunction clampPercent(val: number | undefined): number {\n return Math.max(0, Math.min(val ?? 100, 100));\n}\n\nconst progressStyles = tv({\n slots: {\n wrapper: '',\n progressbar: 'w-full overflow-hidden relative rounded-full',\n rail: 'w-full h-full',\n bar: 'transition-all duration-150 ease-in-out absolute left-0 top-0 h-full w-full',\n indeterminateBar: 'absolute left-0 top-0 h-full w-auto transition-transform duration-200 ease-linear origin-left animate-slide-rail',\n bufferDots: 'absolute h-0 w-[200%] -top-px -left-full border-dashed border-y-[0.2rem] animate-buffer-pulse',\n bufferRail: 'w-full h-full transition-transform duration-200 ease-linear origin-left',\n circularContainer: 'inline-block relative',\n svg: 'block',\n circle: 'stroke-current',\n circleTrack: '',\n label: 'text-rui-text',\n },\n variants: {\n color: {\n primary: { circularContainer: 'text-rui-primary' },\n secondary: { circularContainer: 'text-rui-secondary' },\n error: { circularContainer: 'text-rui-error' },\n warning: { circularContainer: 'text-rui-warning' },\n info: { circularContainer: 'text-rui-info' },\n success: { circularContainer: 'text-rui-success' },\n inherit: { circularContainer: 'text-current' },\n },\n variant: {\n [ProgressVariant.determinate]: { svg: '-rotate-90' },\n [ProgressVariant.indeterminate]: {\n svg: 'animate-circular-spin',\n circle: 'animate-collapse-stroke [stroke-dasharray:80px,200px] [stroke-linecap:round]',\n },\n [ProgressVariant.buffer]: {},\n },\n circular: {\n true: { wrapper: 'inline-flex' },\n false: { wrapper: 'w-full' },\n },\n hasLabel: {\n true: { wrapper: 'inline-flex items-center relative' },\n },\n },\n compoundVariants: [\n // Linear label\n { circular: false, hasLabel: true, class: { label: 'block text-sm ml-4 text-rui-text-secondary tabular-nums' } },\n // Circular label (overlays the circle, font size derived from `size`)\n { circular: true, hasLabel: true, class: { label: 'absolute inset-0 flex items-center justify-center leading-none font-medium tabular-nums whitespace-nowrap' } },\n ],\n compoundSlots: [\n // Track behind the bar: one neutral for every named color, neutral-700 in dark like the footer stepper pills, which reads on a near-black page\n { slots: ['rail'], color: ['primary', 'secondary', 'error', 'warning', 'info', 'success'], class: 'bg-rui-neutral-200 dark:bg-rui-neutral-700' },\n { slots: ['bufferDots'], color: ['primary', 'secondary', 'error', 'warning', 'info', 'success'], class: 'border-rui-neutral-200 dark:border-rui-neutral-700' },\n { slots: ['circleTrack'], color: ['primary', 'secondary', 'error', 'warning', 'info', 'success'], class: 'stroke-rui-neutral-200 dark:stroke-rui-neutral-700' },\n // `inherit` keeps a tint of whatever color it is given\n { slots: ['rail', 'bufferDots'], color: 'inherit', class: 'bg-current opacity-20 border-current' },\n { slots: ['circleTrack'], color: 'inherit', class: 'stroke-current opacity-20' },\n\n // Bar fill (active progress)\n { slots: ['bar', 'indeterminateBar'], color: 'primary', class: 'bg-rui-primary' },\n { slots: ['bar', 'indeterminateBar'], color: 'secondary', class: 'bg-rui-secondary' },\n { slots: ['bar', 'indeterminateBar'], color: 'error', class: 'bg-rui-error' },\n { slots: ['bar', 'indeterminateBar'], color: 'warning', class: 'bg-rui-warning' },\n { slots: ['bar', 'indeterminateBar'], color: 'info', class: 'bg-rui-info' },\n { slots: ['bar', 'indeterminateBar'], color: 'success', class: 'bg-rui-success' },\n { slots: ['bar', 'indeterminateBar'], color: 'inherit', class: 'bg-current' },\n ],\n});\n\nconst hasLabel = computed<boolean>(() => showLabel && variant !== ProgressVariant.indeterminate);\n\n/**\n * The font size that fits the widest label (`100%`) inside the ring, solved against the chord\n * it spans. Always computed for that widest label so the text does not resize as the value climbs.\n */\nconst insideLabelFit = computed<number>(() => {\n const innerRadius = Math.max((+size - 2 * +thickness) / 2, 0);\n return (LABEL_BREATHING_ROOM * 2 * innerRadius) / Math.sqrt(LABEL_WIDTH_EM ** 2 + 1);\n});\n\nconst labelFits = computed<boolean>(() => get(insideLabelFit) >= MIN_INSIDE_LABEL_PX);\n\nconst ui = computed<ReturnType<typeof progressStyles>>(() => progressStyles({\n color,\n variant,\n circular,\n hasLabel: get(hasLabel),\n}));\n\nconst currentValue = computed<number>(() => clampPercent(value));\n\n/** An indeterminate bar has no value to report, so it leaves `aria-valuenow` off. */\nconst ariaValueNow = computed<number | undefined>(() =>\n variant === ProgressVariant.indeterminate ? undefined : get(currentValue));\n\nconst label = computed<string>(() => `${Math.floor(get(currentValue))}%`);\n\nconst progress = computed<number>(() => -100 + get(currentValue));\n\nconst barStyle = computed<Record<string, string>>(() => ({\n transform: `translateX(${get(progress)}%)`,\n}));\n\nconst bufferRailStyle = computed<Record<string, string>>(() => ({\n transform: `translateX(${-100 + clampPercent(bufferValue)}%)`,\n}));\n\nconst linearStyle = computed<Record<string, string>>(() => ({\n height: `${+thickness}px`,\n}));\n\nconst circularSize = computed<Record<string, string>>(() => ({\n width: `${+size}px`,\n height: `${+size}px`,\n}));\n\nconst circularGeometry = computed<{ scaledThickness: number; viewSize: number }>(() => {\n const scaledThickness = (+thickness * 32) / +size;\n return { scaledThickness, viewSize: 40 + scaledThickness };\n});\n\n/**\n * The label inside the ring scales with both `size` and `thickness`. The fit is capped by\n * a sublinear curve so large rings do not end up with an oversized number in the middle.\n */\nconst circularLabelStyle = computed<Record<string, string>>(() => ({\n fontSize: `${Math.min(get(insideLabelFit), +size * 0.15 + 6)}px`,\n}));\n\nconst circularStrokeStyle = computed<Record<string, string>>(() => ({\n strokeDasharray: `${CIRCLE_CIRCUMFERENCE}`,\n strokeDashoffset: `${(get(progress) / 100) * -CIRCLE_CIRCUMFERENCE}`,\n // the library's own motion, not Material's standard curve\n transition: 'stroke-dashoffset 200ms ease-out',\n}));\n</script>\n\n<template>\n <div :class=\"ui.wrapper()\">\n <!-- Circular progress (not supported for buffer variant) -->\n <div\n v-if=\"circular && variant !== ProgressVariant.buffer\"\n :aria-valuenow=\"ariaValueNow\"\n :class=\"ui.circularContainer()\"\n :style=\"circularSize\"\n :data-variant=\"variant\"\n :data-color=\"color\"\n :aria-label=\"ariaLabel\"\n :title=\"hasLabel && !labelFits ? label : undefined\"\n aria-valuemax=\"100\"\n aria-valuemin=\"0\"\n role=\"progressbar\"\n >\n <svg\n :class=\"ui.svg()\"\n :viewBox=\"`0 0 ${circularGeometry.viewSize} ${circularGeometry.viewSize}`\"\n >\n <!-- Track behind the arc, mirroring the linear rail. Indeterminate spins, so it gets no track. -->\n <circle\n v-if=\"variant === ProgressVariant.determinate\"\n cx=\"50%\"\n cy=\"50%\"\n fill=\"none\"\n :r=\"CIRCLE_RADIUS\"\n :class=\"ui.circleTrack()\"\n :stroke-width=\"circularGeometry.scaledThickness\"\n />\n <circle\n cx=\"50%\"\n cy=\"50%\"\n fill=\"none\"\n :r=\"CIRCLE_RADIUS\"\n :class=\"ui.circle()\"\n :style=\"variant === ProgressVariant.determinate ? circularStrokeStyle : undefined\"\n :stroke-width=\"circularGeometry.scaledThickness\"\n />\n </svg>\n <div\n v-if=\"hasLabel && labelFits\"\n :class=\"ui.label()\"\n :style=\"circularLabelStyle\"\n aria-hidden=\"true\"\n >\n {{ label }}\n </div>\n </div>\n\n <!-- Linear progress (also used as fallback for circular + buffer) -->\n <div\n v-else\n :aria-valuenow=\"ariaValueNow\"\n :class=\"ui.progressbar()\"\n :style=\"linearStyle\"\n :data-variant=\"variant\"\n :data-color=\"color\"\n :aria-label=\"ariaLabel\"\n aria-valuemax=\"100\"\n aria-valuemin=\"0\"\n role=\"progressbar\"\n >\n <div\n v-if=\"variant === ProgressVariant.buffer\"\n :class=\"ui.bufferDots()\"\n />\n <div\n :class=\"variant === ProgressVariant.buffer ? [ui.rail(), ui.bufferRail()] : ui.rail()\"\n :style=\"variant === ProgressVariant.buffer ? bufferRailStyle : undefined\"\n data-id=\"progress-rail\"\n />\n <div\n v-if=\"variant === ProgressVariant.indeterminate\"\n :class=\"ui.indeterminateBar()\"\n />\n <div\n v-else\n :class=\"ui.bar()\"\n :style=\"barStyle\"\n />\n </div>\n\n <!-- Linear label -->\n <div\n v-if=\"hasLabel && !circular\"\n :class=\"ui.label()\"\n >\n {{ label }}\n </div>\n </div>\n</template>\n"],"mappings":""}
|
|
1
|
+
{"version":3,"file":"RuiProgress.js","names":["_sfc_main"],"sources":["../../../src/components/progress/RuiProgress.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport type { ContextColorsType } from '@/consts/colors';\nimport { ProgressVariant } from '@/components/progress/progress-props';\nimport { tv } from '@/utils/tv';\n\nexport interface Props {\n /**\n * in percentage value, required when variant === determinate or buffer\n * Ranges from 0 to 100.\n */\n value?: number;\n /**\n * in percentage value, required when variant === buffer\n * Ranges from 0 to 100.\n */\n bufferValue?: number;\n variant?: ProgressVariant;\n color?: ContextColorsType | 'inherit';\n circular?: boolean;\n showLabel?: boolean;\n /**\n * Sets the stroke thickness in pixels\n */\n thickness?: number | string;\n /**\n * only used for circular progress\n */\n size?: number | string;\n /**\n * What is loading, as the progress bar's accessible name (\"Loading\" when not given)\n */\n ariaLabel?: string;\n}\n\ndefineOptions({\n name: 'RuiProgress',\n});\n\nconst {\n value = 0,\n bufferValue = 0,\n variant = ProgressVariant.determinate,\n color = 'inherit',\n circular = false,\n showLabel = false,\n thickness = 4,\n size = 40,\n ariaLabel = 'Loading',\n} = defineProps<Props>();\n\ndefineSlots<Record<string, never>>();\n\nconst CIRCLE_RADIUS = 20;\nconst CIRCLE_CIRCUMFERENCE = 2 * Math.PI * CIRCLE_RADIUS; // ~125.66\n/** width of `100%` in ems, measured with tabular figures */\nconst LABEL_WIDTH_EM = 2.95;\n/** keeps the label off the stroke rather than merely inside it */\nconst LABEL_BREATHING_ROOM = 0.9;\n/** below this font size a label inside the ring is unreadable, so the ring drops it rather than change its footprint */\nconst MIN_INSIDE_LABEL_PX = 9;\n\nfunction clampPercent(val: number | undefined): number {\n return Math.max(0, Math.min(val ?? 100, 100));\n}\n\nconst progressStyles = tv({\n slots: {\n wrapper: '',\n progressbar: 'w-full overflow-hidden relative rounded-full',\n rail: 'w-full h-full',\n bar: 'transition-all duration-150 ease-in-out absolute left-0 top-0 h-full w-full',\n indeterminateBar: 'absolute left-0 top-0 h-full w-auto transition-transform duration-200 ease-linear origin-left animate-slide-rail',\n bufferDots: 'absolute h-0 w-[200%] -top-px -left-full border-dashed border-y-[0.2rem] animate-buffer-pulse',\n bufferRail: 'w-full h-full transition-transform duration-200 ease-linear origin-left',\n circularContainer: 'inline-block relative',\n svg: 'block',\n circle: 'stroke-current',\n circleTrack: '',\n label: 'text-rui-text',\n },\n variants: {\n color: {\n primary: { circularContainer: 'text-rui-primary' },\n secondary: { circularContainer: 'text-rui-secondary' },\n error: { circularContainer: 'text-rui-error' },\n warning: { circularContainer: 'text-rui-warning' },\n info: { circularContainer: 'text-rui-info' },\n success: { circularContainer: 'text-rui-success' },\n inherit: { circularContainer: 'text-current' },\n },\n variant: {\n [ProgressVariant.determinate]: { svg: '-rotate-90' },\n [ProgressVariant.indeterminate]: {\n svg: 'animate-circular-spin',\n circle: 'animate-collapse-stroke [stroke-dasharray:80px,200px] [stroke-linecap:round]',\n },\n [ProgressVariant.buffer]: {},\n },\n circular: {\n true: { wrapper: 'inline-flex' },\n false: { wrapper: 'w-full' },\n },\n hasLabel: {\n true: { wrapper: 'inline-flex items-center relative' },\n },\n },\n compoundVariants: [\n // Linear label\n { circular: false, hasLabel: true, class: { label: 'block text-sm ml-4 text-rui-text-secondary tabular-nums' } },\n // Circular label (overlays the circle, font size derived from `size`)\n { circular: true, hasLabel: true, class: { label: 'absolute inset-0 flex items-center justify-center leading-none font-medium tabular-nums whitespace-nowrap' } },\n ],\n compoundSlots: [\n // Track behind the bar: one neutral for every named color, neutral-700 in dark like the footer stepper pills, which reads on a near-black page\n { slots: ['rail'], color: ['primary', 'secondary', 'error', 'warning', 'info', 'success'], class: 'bg-rui-neutral-200 dark:bg-rui-neutral-700' },\n { slots: ['bufferDots'], color: ['primary', 'secondary', 'error', 'warning', 'info', 'success'], class: 'border-rui-neutral-200 dark:border-rui-neutral-700' },\n { slots: ['circleTrack'], color: ['primary', 'secondary', 'error', 'warning', 'info', 'success'], class: 'stroke-rui-neutral-200 dark:stroke-rui-neutral-700' },\n // `inherit` keeps a tint of whatever color it is given\n { slots: ['rail', 'bufferDots'], color: 'inherit', class: 'bg-current opacity-20 border-current' },\n { slots: ['circleTrack'], color: 'inherit', class: 'stroke-current opacity-20' },\n\n // Bar fill (active progress)\n { slots: ['bar', 'indeterminateBar'], color: 'primary', class: 'bg-rui-primary' },\n { slots: ['bar', 'indeterminateBar'], color: 'secondary', class: 'bg-rui-secondary' },\n { slots: ['bar', 'indeterminateBar'], color: 'error', class: 'bg-rui-error' },\n { slots: ['bar', 'indeterminateBar'], color: 'warning', class: 'bg-rui-warning' },\n { slots: ['bar', 'indeterminateBar'], color: 'info', class: 'bg-rui-info' },\n { slots: ['bar', 'indeterminateBar'], color: 'success', class: 'bg-rui-success' },\n { slots: ['bar', 'indeterminateBar'], color: 'inherit', class: 'bg-current' },\n ],\n});\n\nconst hasLabel = computed<boolean>(() => showLabel && variant !== ProgressVariant.indeterminate);\n\n/**\n * The font size that fits the widest label (`100%`) inside the ring, solved against the chord\n * it spans. Always computed for that widest label so the text does not resize as the value climbs.\n */\nconst insideLabelFit = computed<number>(() => {\n const innerRadius = Math.max((+size - 2 * +thickness) / 2, 0);\n return (LABEL_BREATHING_ROOM * 2 * innerRadius) / Math.sqrt(LABEL_WIDTH_EM ** 2 + 1);\n});\n\nconst labelFits = computed<boolean>(() => get(insideLabelFit) >= MIN_INSIDE_LABEL_PX);\n\nconst ui = computed<ReturnType<typeof progressStyles>>(() => progressStyles({\n color,\n variant,\n circular,\n hasLabel: get(hasLabel),\n}));\n\nconst currentValue = computed<number>(() => clampPercent(value));\n\n/** An indeterminate bar has no value to report, so it leaves `aria-valuenow` off. */\nconst ariaValueNow = computed<number | undefined>(() =>\n variant === ProgressVariant.indeterminate ? undefined : get(currentValue));\n\nconst label = computed<string>(() => `${Math.floor(get(currentValue))}%`);\n\nconst progress = computed<number>(() => -100 + get(currentValue));\n\nconst barStyle = computed<Record<string, string>>(() => ({\n transform: `translateX(${get(progress)}%)`,\n}));\n\nconst bufferRailStyle = computed<Record<string, string>>(() => ({\n transform: `translateX(${-100 + clampPercent(bufferValue)}%)`,\n}));\n\nconst linearStyle = computed<Record<string, string>>(() => ({\n height: `${+thickness}px`,\n}));\n\nconst circularSize = computed<Record<string, string>>(() => ({\n width: `${+size}px`,\n height: `${+size}px`,\n}));\n\nconst circularGeometry = computed<{ scaledThickness: number; viewSize: number }>(() => {\n const scaledThickness = (+thickness * 32) / +size;\n return { scaledThickness, viewSize: 40 + scaledThickness };\n});\n\n/**\n * The label inside the ring scales with both `size` and `thickness`. The fit is capped by\n * a sublinear curve so large rings do not end up with an oversized number in the middle.\n */\nconst circularLabelStyle = computed<Record<string, string>>(() => ({\n fontSize: `${Math.min(get(insideLabelFit), +size * 0.15 + 6)}px`,\n}));\n\nconst circularStrokeStyle = computed<Record<string, string>>(() => ({\n strokeDasharray: `${CIRCLE_CIRCUMFERENCE}`,\n strokeDashoffset: `${(get(progress) / 100) * -CIRCLE_CIRCUMFERENCE}`,\n // the library's own motion, not Material's standard curve\n transition: 'stroke-dashoffset 200ms ease-out',\n}));\n</script>\n\n<template>\n <div :class=\"ui.wrapper()\">\n <!-- Circular progress (not supported for buffer variant) -->\n <div\n v-if=\"circular && variant !== ProgressVariant.buffer\"\n :aria-valuenow=\"ariaValueNow\"\n :class=\"ui.circularContainer()\"\n :style=\"circularSize\"\n :data-variant=\"variant\"\n :data-color=\"color\"\n :aria-label=\"ariaLabel\"\n :title=\"hasLabel && !labelFits ? label : undefined\"\n aria-valuemax=\"100\"\n aria-valuemin=\"0\"\n role=\"progressbar\"\n >\n <svg\n :class=\"ui.svg()\"\n :viewBox=\"`0 0 ${circularGeometry.viewSize} ${circularGeometry.viewSize}`\"\n >\n <!-- Track behind the arc, mirroring the linear rail. Indeterminate spins, so it gets no track. -->\n <circle\n v-if=\"variant === ProgressVariant.determinate\"\n cx=\"50%\"\n cy=\"50%\"\n fill=\"none\"\n :r=\"CIRCLE_RADIUS\"\n :class=\"ui.circleTrack()\"\n :stroke-width=\"circularGeometry.scaledThickness\"\n />\n <circle\n cx=\"50%\"\n cy=\"50%\"\n fill=\"none\"\n :r=\"CIRCLE_RADIUS\"\n :class=\"ui.circle()\"\n :style=\"variant === ProgressVariant.determinate ? circularStrokeStyle : undefined\"\n :stroke-width=\"circularGeometry.scaledThickness\"\n />\n </svg>\n <div\n v-if=\"hasLabel && labelFits\"\n :class=\"ui.label()\"\n :style=\"circularLabelStyle\"\n aria-hidden=\"true\"\n >\n {{ label }}\n </div>\n </div>\n\n <!-- Linear progress (also used as fallback for circular + buffer) -->\n <div\n v-else\n :aria-valuenow=\"ariaValueNow\"\n :class=\"ui.progressbar()\"\n :style=\"linearStyle\"\n :data-variant=\"variant\"\n :data-color=\"color\"\n :aria-label=\"ariaLabel\"\n aria-valuemax=\"100\"\n aria-valuemin=\"0\"\n role=\"progressbar\"\n >\n <div\n v-if=\"variant === ProgressVariant.buffer\"\n :class=\"ui.bufferDots()\"\n />\n <div\n :class=\"variant === ProgressVariant.buffer ? [ui.rail(), ui.bufferRail()] : ui.rail()\"\n :style=\"variant === ProgressVariant.buffer ? bufferRailStyle : undefined\"\n data-id=\"progress-rail\"\n />\n <div\n v-if=\"variant === ProgressVariant.indeterminate\"\n :class=\"ui.indeterminateBar()\"\n />\n <div\n v-else\n :class=\"ui.bar()\"\n :style=\"barStyle\"\n />\n </div>\n\n <!-- Linear label -->\n <div\n v-if=\"hasLabel && !circular\"\n :class=\"ui.label()\"\n >\n {{ label }}\n </div>\n </div>\n</template>\n"],"mappings":""}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RuiProgress.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../src/components/progress/RuiProgress.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport type { ContextColorsType } from '@/consts/colors';\nimport { ProgressVariant } from '@/components/progress/progress-props';\nimport { tv } from '@/utils/tv';\n\nexport interface Props {\n /**\n * in percentage value, required when variant === determinate or buffer\n * Ranges from 0 to 100.\n */\n value?: number;\n /**\n * in percentage value, required when variant === buffer\n * Ranges from 0 to 100.\n */\n bufferValue?: number;\n variant?: ProgressVariant;\n color?: ContextColorsType | 'inherit';\n circular?: boolean;\n showLabel?: boolean;\n /**\n * Sets the stroke thickness in pixels\n */\n thickness?: number | string;\n /**\n * only used for circular progress\n */\n size?: number | string;\n /**\n * What is loading, as the progress bar's accessible name (\"Loading\" when not given)\n */\n ariaLabel?: string;\n}\n\ndefineOptions({\n name: 'RuiProgress',\n});\n\nconst {\n value = 0,\n bufferValue = 0,\n variant = ProgressVariant.determinate,\n color = 'inherit',\n circular = false,\n showLabel = false,\n thickness = 4,\n size = 40,\n ariaLabel = 'Loading',\n} = defineProps<Props>();\n\ndefineSlots<Record<string, never>>();\n\nconst CIRCLE_RADIUS = 20;\nconst CIRCLE_CIRCUMFERENCE = 2 * Math.PI * CIRCLE_RADIUS; // ~125.66\n/** width of `100%` in ems, measured with tabular figures */\nconst LABEL_WIDTH_EM = 2.95;\n/** keeps the label off the stroke rather than merely inside it */\nconst LABEL_BREATHING_ROOM = 0.9;\n/** below this font size a label inside the ring is unreadable, so the ring drops it rather than change its footprint */\nconst MIN_INSIDE_LABEL_PX = 9;\n\nfunction clampPercent(val: number | undefined): number {\n return Math.max(0, Math.min(val ?? 100, 100));\n}\n\nconst progressStyles = tv({\n slots: {\n wrapper: '',\n progressbar: 'w-full overflow-hidden relative rounded-full',\n rail: 'w-full h-full',\n bar: 'transition-all duration-150 ease-in-out absolute left-0 top-0 h-full w-full',\n indeterminateBar: 'absolute left-0 top-0 h-full w-auto transition-transform duration-200 ease-linear origin-left animate-slide-rail',\n bufferDots: 'absolute h-0 w-[200%] -top-px -left-full border-dashed border-y-[0.2rem] animate-buffer-pulse',\n bufferRail: 'w-full h-full transition-transform duration-200 ease-linear origin-left',\n circularContainer: 'inline-block relative',\n svg: 'block',\n circle: 'stroke-current',\n circleTrack: '',\n label: 'text-rui-text',\n },\n variants: {\n color: {\n primary: { circularContainer: 'text-rui-primary' },\n secondary: { circularContainer: 'text-rui-secondary' },\n error: { circularContainer: 'text-rui-error' },\n warning: { circularContainer: 'text-rui-warning' },\n info: { circularContainer: 'text-rui-info' },\n success: { circularContainer: 'text-rui-success' },\n inherit: { circularContainer: 'text-current' },\n },\n variant: {\n [ProgressVariant.determinate]: { svg: '-rotate-90' },\n [ProgressVariant.indeterminate]: {\n svg: 'animate-circular-spin',\n circle: 'animate-collapse-stroke [stroke-dasharray:80px,200px] [stroke-linecap:round]',\n },\n [ProgressVariant.buffer]: {},\n },\n circular: {\n true: { wrapper: 'inline-flex' },\n false: { wrapper: 'w-full' },\n },\n hasLabel: {\n true: { wrapper: 'inline-flex items-center relative' },\n },\n },\n compoundVariants: [\n // Linear label\n { circular: false, hasLabel: true, class: { label: 'block text-sm ml-4 text-rui-text-secondary tabular-nums' } },\n // Circular label (overlays the circle, font size derived from `size`)\n { circular: true, hasLabel: true, class: { label: 'absolute inset-0 flex items-center justify-center leading-none font-medium tabular-nums whitespace-nowrap' } },\n ],\n compoundSlots: [\n // Track behind the bar: one neutral for every named color, neutral-700 in dark like the footer stepper pills, which reads on a near-black page\n { slots: ['rail'], color: ['primary', 'secondary', 'error', 'warning', 'info', 'success'], class: 'bg-rui-neutral-200 dark:bg-rui-neutral-700' },\n { slots: ['bufferDots'], color: ['primary', 'secondary', 'error', 'warning', 'info', 'success'], class: 'border-rui-neutral-200 dark:border-rui-neutral-700' },\n { slots: ['circleTrack'], color: ['primary', 'secondary', 'error', 'warning', 'info', 'success'], class: 'stroke-rui-neutral-200 dark:stroke-rui-neutral-700' },\n // `inherit` keeps a tint of whatever color it is given\n { slots: ['rail', 'bufferDots'], color: 'inherit', class: 'bg-current opacity-20 border-current' },\n { slots: ['circleTrack'], color: 'inherit', class: 'stroke-current opacity-20' },\n\n // Bar fill (active progress)\n { slots: ['bar', 'indeterminateBar'], color: 'primary', class: 'bg-rui-primary' },\n { slots: ['bar', 'indeterminateBar'], color: 'secondary', class: 'bg-rui-secondary' },\n { slots: ['bar', 'indeterminateBar'], color: 'error', class: 'bg-rui-error' },\n { slots: ['bar', 'indeterminateBar'], color: 'warning', class: 'bg-rui-warning' },\n { slots: ['bar', 'indeterminateBar'], color: 'info', class: 'bg-rui-info' },\n { slots: ['bar', 'indeterminateBar'], color: 'success', class: 'bg-rui-success' },\n { slots: ['bar', 'indeterminateBar'], color: 'inherit', class: 'bg-current' },\n ],\n});\n\nconst hasLabel = computed<boolean>(() => showLabel && variant !== ProgressVariant.indeterminate);\n\n/**\n * The font size that fits the widest label (`100%`) inside the ring, solved against the chord\n * it spans. Always computed for that widest label so the text does not resize as the value climbs.\n */\nconst insideLabelFit = computed<number>(() => {\n const innerRadius = Math.max((+size - 2 * +thickness) / 2, 0);\n return (LABEL_BREATHING_ROOM * 2 * innerRadius) / Math.sqrt(LABEL_WIDTH_EM ** 2 + 1);\n});\n\nconst labelFits = computed<boolean>(() => get(insideLabelFit) >= MIN_INSIDE_LABEL_PX);\n\nconst ui = computed<ReturnType<typeof progressStyles>>(() => progressStyles({\n color,\n variant,\n circular,\n hasLabel: get(hasLabel),\n}));\n\nconst currentValue = computed<number>(() => clampPercent(value));\n\n/** An indeterminate bar has no value to report, so it leaves `aria-valuenow` off. */\nconst ariaValueNow = computed<number | undefined>(() =>\n variant === ProgressVariant.indeterminate ? undefined : get(currentValue));\n\nconst label = computed<string>(() => `${Math.floor(get(currentValue))}%`);\n\nconst progress = computed<number>(() => -100 + get(currentValue));\n\nconst barStyle = computed<Record<string, string>>(() => ({\n transform: `translateX(${get(progress)}%)`,\n}));\n\nconst bufferRailStyle = computed<Record<string, string>>(() => ({\n transform: `translateX(${-100 + clampPercent(bufferValue)}%)`,\n}));\n\nconst linearStyle = computed<Record<string, string>>(() => ({\n height: `${+thickness}px`,\n}));\n\nconst circularSize = computed<Record<string, string>>(() => ({\n width: `${+size}px`,\n height: `${+size}px`,\n}));\n\nconst circularGeometry = computed<{ scaledThickness: number; viewSize: number }>(() => {\n const scaledThickness = (+thickness * 32) / +size;\n return { scaledThickness, viewSize: 40 + scaledThickness };\n});\n\n/**\n * The label inside the ring scales with both `size` and `thickness`. The fit is capped by\n * a sublinear curve so large rings do not end up with an oversized number in the middle.\n */\nconst circularLabelStyle = computed<Record<string, string>>(() => ({\n fontSize: `${Math.min(get(insideLabelFit), +size * 0.15 + 6)}px`,\n}));\n\nconst circularStrokeStyle = computed<Record<string, string>>(() => ({\n strokeDasharray: `${CIRCLE_CIRCUMFERENCE}`,\n strokeDashoffset: `${(get(progress) / 100) * -CIRCLE_CIRCUMFERENCE}`,\n // the library's own motion, not Material's standard curve\n transition: 'stroke-dashoffset 200ms ease-out',\n}));\n</script>\n\n<template>\n <div :class=\"ui.wrapper()\">\n <!-- Circular progress (not supported for buffer variant) -->\n <div\n v-if=\"circular && variant !== ProgressVariant.buffer\"\n :aria-valuenow=\"ariaValueNow\"\n :class=\"ui.circularContainer()\"\n :style=\"circularSize\"\n :data-variant=\"variant\"\n :data-color=\"color\"\n :aria-label=\"ariaLabel\"\n :title=\"hasLabel && !labelFits ? label : undefined\"\n aria-valuemax=\"100\"\n aria-valuemin=\"0\"\n role=\"progressbar\"\n >\n <svg\n :class=\"ui.svg()\"\n :viewBox=\"`0 0 ${circularGeometry.viewSize} ${circularGeometry.viewSize}`\"\n >\n <!-- Track behind the arc, mirroring the linear rail. Indeterminate spins, so it gets no track. -->\n <circle\n v-if=\"variant === ProgressVariant.determinate\"\n cx=\"50%\"\n cy=\"50%\"\n fill=\"none\"\n :r=\"CIRCLE_RADIUS\"\n :class=\"ui.circleTrack()\"\n :stroke-width=\"circularGeometry.scaledThickness\"\n />\n <circle\n cx=\"50%\"\n cy=\"50%\"\n fill=\"none\"\n :r=\"CIRCLE_RADIUS\"\n :class=\"ui.circle()\"\n :style=\"variant === ProgressVariant.determinate ? circularStrokeStyle : undefined\"\n :stroke-width=\"circularGeometry.scaledThickness\"\n />\n </svg>\n <div\n v-if=\"hasLabel && labelFits\"\n :class=\"ui.label()\"\n :style=\"circularLabelStyle\"\n aria-hidden=\"true\"\n >\n {{ label }}\n </div>\n </div>\n\n <!-- Linear progress (also used as fallback for circular + buffer) -->\n <div\n v-else\n :aria-valuenow=\"ariaValueNow\"\n :class=\"ui.progressbar()\"\n :style=\"linearStyle\"\n :data-variant=\"variant\"\n :data-color=\"color\"\n :aria-label=\"ariaLabel\"\n aria-valuemax=\"100\"\n aria-valuemin=\"0\"\n role=\"progressbar\"\n >\n <div\n v-if=\"variant === ProgressVariant.buffer\"\n :class=\"ui.bufferDots()\"\n />\n <div\n :class=\"variant === ProgressVariant.buffer ? [ui.rail(), ui.bufferRail()] : ui.rail()\"\n :style=\"variant === ProgressVariant.buffer ? bufferRailStyle : undefined\"\n data-id=\"progress-rail\"\n />\n <div\n v-if=\"variant === ProgressVariant.indeterminate\"\n :class=\"ui.indeterminateBar()\"\n />\n <div\n v-else\n :class=\"ui.bar()\"\n :style=\"barStyle\"\n />\n </div>\n\n <!-- Linear label -->\n <div\n v-if=\"hasLabel && !circular\"\n :class=\"ui.label()\"\n >\n {{ label }}\n </div>\n </div>\n</template>\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"RuiProgress.vue_vue_type_script_setup_true_lang.js","names":["_openBlock","_createElementBlock","_normalizeClass","_unref","_normalizeStyle","_createCommentVNode","_createElementVNode","_toDisplayString"],"sources":["../../../src/components/progress/RuiProgress.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport type { ContextColorsType } from '@/consts/colors';\nimport { ProgressVariant } from '@/components/progress/progress-props';\nimport { tv } from '@/utils/tv';\n\nexport interface Props {\n /**\n * in percentage value, required when variant === determinate or buffer\n * Ranges from 0 to 100.\n */\n value?: number;\n /**\n * in percentage value, required when variant === buffer\n * Ranges from 0 to 100.\n */\n bufferValue?: number;\n variant?: ProgressVariant;\n color?: ContextColorsType | 'inherit';\n circular?: boolean;\n showLabel?: boolean;\n /**\n * Sets the stroke thickness in pixels\n */\n thickness?: number | string;\n /**\n * only used for circular progress\n */\n size?: number | string;\n /**\n * What is loading, as the progress bar's accessible name (\"Loading\" when not given)\n */\n ariaLabel?: string;\n}\n\ndefineOptions({\n name: 'RuiProgress',\n});\n\nconst {\n value = 0,\n bufferValue = 0,\n variant = ProgressVariant.determinate,\n color = 'inherit',\n circular = false,\n showLabel = false,\n thickness = 4,\n size = 40,\n ariaLabel = 'Loading',\n} = defineProps<Props>();\n\ndefineSlots<Record<string, never>>();\n\nconst CIRCLE_RADIUS = 20;\nconst CIRCLE_CIRCUMFERENCE = 2 * Math.PI * CIRCLE_RADIUS; // ~125.66\n/** width of `100%` in ems, measured with tabular figures */\nconst LABEL_WIDTH_EM = 2.95;\n/** keeps the label off the stroke rather than merely inside it */\nconst LABEL_BREATHING_ROOM = 0.9;\n/** below this font size a label inside the ring is unreadable, so the ring drops it rather than change its footprint */\nconst MIN_INSIDE_LABEL_PX = 9;\n\nfunction clampPercent(val: number | undefined): number {\n return Math.max(0, Math.min(val ?? 100, 100));\n}\n\nconst progressStyles = tv({\n slots: {\n wrapper: '',\n progressbar: 'w-full overflow-hidden relative rounded-full',\n rail: 'w-full h-full',\n bar: 'transition-all duration-150 ease-in-out absolute left-0 top-0 h-full w-full',\n indeterminateBar: 'absolute left-0 top-0 h-full w-auto transition-transform duration-200 ease-linear origin-left animate-slide-rail',\n bufferDots: 'absolute h-0 w-[200%] -top-px -left-full border-dashed border-y-[0.2rem] animate-buffer-pulse',\n bufferRail: 'w-full h-full transition-transform duration-200 ease-linear origin-left',\n circularContainer: 'inline-block relative',\n svg: 'block',\n circle: 'stroke-current',\n circleTrack: '',\n label: 'text-rui-text',\n },\n variants: {\n color: {\n primary: { circularContainer: 'text-rui-primary' },\n secondary: { circularContainer: 'text-rui-secondary' },\n error: { circularContainer: 'text-rui-error' },\n warning: { circularContainer: 'text-rui-warning' },\n info: { circularContainer: 'text-rui-info' },\n success: { circularContainer: 'text-rui-success' },\n inherit: { circularContainer: 'text-current' },\n },\n variant: {\n [ProgressVariant.determinate]: { svg: '-rotate-90' },\n [ProgressVariant.indeterminate]: {\n svg: 'animate-circular-spin',\n circle: 'animate-collapse-stroke [stroke-dasharray:80px,200px] [stroke-linecap:round]',\n },\n [ProgressVariant.buffer]: {},\n },\n circular: {\n true: { wrapper: 'inline-flex' },\n false: { wrapper: 'w-full' },\n },\n hasLabel: {\n true: { wrapper: 'inline-flex items-center relative' },\n },\n },\n compoundVariants: [\n // Linear label\n { circular: false, hasLabel: true, class: { label: 'block text-sm ml-4 text-rui-text-secondary tabular-nums' } },\n // Circular label (overlays the circle, font size derived from `size`)\n { circular: true, hasLabel: true, class: { label: 'absolute inset-0 flex items-center justify-center leading-none font-medium tabular-nums whitespace-nowrap' } },\n ],\n compoundSlots: [\n // Track behind the bar: one neutral for every named color, neutral-700 in dark like the footer stepper pills, which reads on a near-black page\n { slots: ['rail'], color: ['primary', 'secondary', 'error', 'warning', 'info', 'success'], class: 'bg-rui-neutral-200 dark:bg-rui-neutral-700' },\n { slots: ['bufferDots'], color: ['primary', 'secondary', 'error', 'warning', 'info', 'success'], class: 'border-rui-neutral-200 dark:border-rui-neutral-700' },\n { slots: ['circleTrack'], color: ['primary', 'secondary', 'error', 'warning', 'info', 'success'], class: 'stroke-rui-neutral-200 dark:stroke-rui-neutral-700' },\n // `inherit` keeps a tint of whatever color it is given\n { slots: ['rail', 'bufferDots'], color: 'inherit', class: 'bg-current opacity-20 border-current' },\n { slots: ['circleTrack'], color: 'inherit', class: 'stroke-current opacity-20' },\n\n // Bar fill (active progress)\n { slots: ['bar', 'indeterminateBar'], color: 'primary', class: 'bg-rui-primary' },\n { slots: ['bar', 'indeterminateBar'], color: 'secondary', class: 'bg-rui-secondary' },\n { slots: ['bar', 'indeterminateBar'], color: 'error', class: 'bg-rui-error' },\n { slots: ['bar', 'indeterminateBar'], color: 'warning', class: 'bg-rui-warning' },\n { slots: ['bar', 'indeterminateBar'], color: 'info', class: 'bg-rui-info' },\n { slots: ['bar', 'indeterminateBar'], color: 'success', class: 'bg-rui-success' },\n { slots: ['bar', 'indeterminateBar'], color: 'inherit', class: 'bg-current' },\n ],\n});\n\nconst hasLabel = computed<boolean>(() => showLabel && variant !== ProgressVariant.indeterminate);\n\n/**\n * The font size that fits the widest label (`100%`) inside the ring, solved against the chord\n * it spans. Always computed for that widest label so the text does not resize as the value climbs.\n */\nconst insideLabelFit = computed<number>(() => {\n const innerRadius = Math.max((+size - 2 * +thickness) / 2, 0);\n return (LABEL_BREATHING_ROOM * 2 * innerRadius) / Math.sqrt(LABEL_WIDTH_EM ** 2 + 1);\n});\n\nconst labelFits = computed<boolean>(() => get(insideLabelFit) >= MIN_INSIDE_LABEL_PX);\n\nconst ui = computed<ReturnType<typeof progressStyles>>(() => progressStyles({\n color,\n variant,\n circular,\n hasLabel: get(hasLabel),\n}));\n\nconst currentValue = computed<number>(() => clampPercent(value));\n\n/** An indeterminate bar has no value to report, so it leaves `aria-valuenow` off. */\nconst ariaValueNow = computed<number | undefined>(() =>\n variant === ProgressVariant.indeterminate ? undefined : get(currentValue));\n\nconst label = computed<string>(() => `${Math.floor(get(currentValue))}%`);\n\nconst progress = computed<number>(() => -100 + get(currentValue));\n\nconst barStyle = computed<Record<string, string>>(() => ({\n transform: `translateX(${get(progress)}%)`,\n}));\n\nconst bufferRailStyle = computed<Record<string, string>>(() => ({\n transform: `translateX(${-100 + clampPercent(bufferValue)}%)`,\n}));\n\nconst linearStyle = computed<Record<string, string>>(() => ({\n height: `${+thickness}px`,\n}));\n\nconst circularSize = computed<Record<string, string>>(() => ({\n width: `${+size}px`,\n height: `${+size}px`,\n}));\n\nconst circularGeometry = computed<{ scaledThickness: number; viewSize: number }>(() => {\n const scaledThickness = (+thickness * 32) / +size;\n return { scaledThickness, viewSize: 40 + scaledThickness };\n});\n\n/**\n * The label inside the ring scales with both `size` and `thickness`. The fit is capped by\n * a sublinear curve so large rings do not end up with an oversized number in the middle.\n */\nconst circularLabelStyle = computed<Record<string, string>>(() => ({\n fontSize: `${Math.min(get(insideLabelFit), +size * 0.15 + 6)}px`,\n}));\n\nconst circularStrokeStyle = computed<Record<string, string>>(() => ({\n strokeDasharray: `${CIRCLE_CIRCUMFERENCE}`,\n strokeDashoffset: `${(get(progress) / 100) * -CIRCLE_CIRCUMFERENCE}`,\n // the library's own motion, not Material's standard curve\n transition: 'stroke-dashoffset 200ms ease-out',\n}));\n</script>\n\n<template>\n <div :class=\"ui.wrapper()\">\n <!-- Circular progress (not supported for buffer variant) -->\n <div\n v-if=\"circular && variant !== ProgressVariant.buffer\"\n :aria-valuenow=\"ariaValueNow\"\n :class=\"ui.circularContainer()\"\n :style=\"circularSize\"\n :data-variant=\"variant\"\n :data-color=\"color\"\n :aria-label=\"ariaLabel\"\n :title=\"hasLabel && !labelFits ? label : undefined\"\n aria-valuemax=\"100\"\n aria-valuemin=\"0\"\n role=\"progressbar\"\n >\n <svg\n :class=\"ui.svg()\"\n :viewBox=\"`0 0 ${circularGeometry.viewSize} ${circularGeometry.viewSize}`\"\n >\n <!-- Track behind the arc, mirroring the linear rail. Indeterminate spins, so it gets no track. -->\n <circle\n v-if=\"variant === ProgressVariant.determinate\"\n cx=\"50%\"\n cy=\"50%\"\n fill=\"none\"\n :r=\"CIRCLE_RADIUS\"\n :class=\"ui.circleTrack()\"\n :stroke-width=\"circularGeometry.scaledThickness\"\n />\n <circle\n cx=\"50%\"\n cy=\"50%\"\n fill=\"none\"\n :r=\"CIRCLE_RADIUS\"\n :class=\"ui.circle()\"\n :style=\"variant === ProgressVariant.determinate ? circularStrokeStyle : undefined\"\n :stroke-width=\"circularGeometry.scaledThickness\"\n />\n </svg>\n <div\n v-if=\"hasLabel && labelFits\"\n :class=\"ui.label()\"\n :style=\"circularLabelStyle\"\n aria-hidden=\"true\"\n >\n {{ label }}\n </div>\n </div>\n\n <!-- Linear progress (also used as fallback for circular + buffer) -->\n <div\n v-else\n :aria-valuenow=\"ariaValueNow\"\n :class=\"ui.progressbar()\"\n :style=\"linearStyle\"\n :data-variant=\"variant\"\n :data-color=\"color\"\n :aria-label=\"ariaLabel\"\n aria-valuemax=\"100\"\n aria-valuemin=\"0\"\n role=\"progressbar\"\n >\n <div\n v-if=\"variant === ProgressVariant.buffer\"\n :class=\"ui.bufferDots()\"\n />\n <div\n :class=\"variant === ProgressVariant.buffer ? [ui.rail(), ui.bufferRail()] : ui.rail()\"\n :style=\"variant === ProgressVariant.buffer ? bufferRailStyle : undefined\"\n data-id=\"progress-rail\"\n />\n <div\n v-if=\"variant === ProgressVariant.indeterminate\"\n :class=\"ui.indeterminateBar()\"\n />\n <div\n v-else\n :class=\"ui.bar()\"\n :style=\"barStyle\"\n />\n </div>\n\n <!-- Linear label -->\n <div\n v-if=\"hasLabel && !circular\"\n :class=\"ui.label()\"\n >\n {{ label }}\n </div>\n </div>\n</template>\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RuiFooterStepper.js","names":[],"sources":["../../../src/components/steppers/RuiFooterStepper.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport RuiButton from '@/components/buttons/button/RuiButton.vue';\nimport RuiIcon from '@/components/icons/RuiIcon.vue';\nimport RuiProgress from '@/components/progress/RuiProgress.vue';\nimport { FooterStepperVariant } from '@/components/steppers/footer-stepper-variant';\nimport { tv } from '@/utils/tv';\n\nexport interface Props {\n pages: number;\n variant?: FooterStepperVariant;\n arrowButtons?: boolean;\n hideButtons?: boolean;\n}\n\ndefineOptions({\n name: 'RuiFooterStepper',\n});\n\nconst modelValue = defineModel<number>({ default: 1 });\n\nconst {\n pages,\n variant: variantProp = FooterStepperVariant.numeric,\n arrowButtons = false,\n hideButtons = false,\n} = defineProps<Props>();\n\nconst footerStepper = {\n // the current bullet stretches into a short bar, so position reads without relying on color\n bullet: tv({\n base: [\n 'h-2 w-2 rounded-full bg-rui-neutral-300 transition-[width,background-color] duration-200 ease-out dark:bg-rui-neutral-600',\n 'hover:bg-rui-neutral-400 dark:hover:bg-rui-neutral-500 focus-visible:focus-ring outline-hidden',\n ].join(' '),\n variants: {\n active: {\n true: 'w-5 bg-rui-primary hover:bg-rui-primary dark:bg-rui-primary dark:hover:bg-rui-primary',\n },\n },\n }),\n pill: tv({\n base: 'rounded-full h-1.5 w-full bg-rui-neutral-200 dark:bg-rui-neutral-700 transition-colors',\n variants: {\n active: {\n true: 'bg-rui-primary dark:bg-rui-primary',\n },\n },\n }),\n};\n\nfunction onChange(delta: number): void {\n set(modelValue, get(modelValue) + delta);\n}\n\nfunction onPrev(): void {\n if (get(modelValue) > 1)\n onChange(-1);\n}\n\nfunction onNext(): void {\n if (get(modelValue) < pages)\n onChange(1);\n}\n\nfunction onClick(index: number): void {\n onChange(index - get(modelValue));\n}\n</script>\n\n<template>\n <div\n role=\"navigation\"\n aria-label=\"Step navigation\"\n class=\"flex items-center justify-between gap-x-4 transition-all duration-150\"\n :data-variant=\"variantProp\"\n >\n <template v-if=\"variantProp === FooterStepperVariant.pill\">\n <div\n data-id=\"pills\"\n class=\"flex w-full gap-x-3\"\n >\n <span\n v-for=\"i in pages\"\n :key=\"i\"\n :aria-current=\"modelValue === i ? 'step' : undefined\"\n :class=\"footerStepper.pill({ active: modelValue === i })\"\n />\n </div>\n </template>\n <template v-else>\n <RuiButton\n v-if=\"!hideButtons\"\n aria-label=\"Previous\"\n :disabled=\"modelValue <= 1\"\n :icon=\"arrowButtons\"\n :size=\"arrowButtons ? 'sm' : undefined\"\n :variant=\"arrowButtons ? 'outlined' : 'text'\"\n :color=\"arrowButtons ? undefined : 'primary'\"\n @click=\"onPrev()\"\n >\n <template\n v-if=\"!arrowButtons\"\n #prepend\n >\n <RuiIcon name=\"lu-chevron-left\" />\n </template>\n <span v-if=\"!arrowButtons\">Back</span>\n <RuiIcon\n v-else\n name=\"lu-chevron-left\"\n />\n </RuiButton>\n <span\n v-if=\"variantProp === FooterStepperVariant.numeric\"\n data-id=\"numeric\"\n class=\"text-sm tabular-nums text-rui-text-secondary\"\n >\n {{ modelValue }}/{{ pages }}\n </span>\n <div\n v-else-if=\"variantProp === FooterStepperVariant.bullet\"\n data-id=\"bullets\"\n class=\"flex items-center gap-x-1.5\"\n >\n <button\n v-for=\"i in pages\"\n :key=\"i\"\n type=\"button\"\n :aria-label=\"`Step ${i}`\"\n :aria-current=\"modelValue === i ? 'step' : undefined\"\n :class=\"footerStepper.bullet({ active: modelValue === i })\"\n @click=\"onClick(i)\"\n />\n </div>\n <RuiProgress\n v-else-if=\"variantProp === FooterStepperVariant.progress\"\n class=\"max-w-[60%]\"\n color=\"primary\"\n :value=\"(modelValue / pages) * 100\"\n />\n <RuiButton\n v-if=\"!hideButtons\"\n aria-label=\"Next\"\n :disabled=\"modelValue >= pages\"\n :icon=\"arrowButtons\"\n :size=\"arrowButtons ? 'sm' : undefined\"\n :variant=\"arrowButtons ? 'outlined' : 'text'\"\n :color=\"arrowButtons ? undefined : 'primary'\"\n @click=\"onNext()\"\n >\n <span v-if=\"!arrowButtons\">Next</span>\n <RuiIcon\n v-else\n name=\"lu-chevron-right\"\n />\n <template\n v-if=\"!arrowButtons\"\n #append\n >\n <RuiIcon name=\"lu-chevron-right\" />\n </template>\n </RuiButton>\n </template>\n </div>\n</template>\n"],"mappings":""}
|
|
1
|
+
{"version":3,"file":"RuiFooterStepper.js","names":["_sfc_main"],"sources":["../../../src/components/steppers/RuiFooterStepper.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport RuiButton from '@/components/buttons/button/RuiButton.vue';\nimport RuiIcon from '@/components/icons/RuiIcon.vue';\nimport RuiProgress from '@/components/progress/RuiProgress.vue';\nimport { FooterStepperVariant } from '@/components/steppers/footer-stepper-variant';\nimport { tv } from '@/utils/tv';\n\nexport interface Props {\n pages: number;\n variant?: FooterStepperVariant;\n arrowButtons?: boolean;\n hideButtons?: boolean;\n}\n\ndefineOptions({\n name: 'RuiFooterStepper',\n});\n\nconst modelValue = defineModel<number>({ default: 1 });\n\nconst {\n pages,\n variant: variantProp = FooterStepperVariant.numeric,\n arrowButtons = false,\n hideButtons = false,\n} = defineProps<Props>();\n\nconst footerStepper = {\n // the current bullet stretches into a short bar, so position reads without relying on color\n bullet: tv({\n base: [\n 'h-2 w-2 rounded-full bg-rui-neutral-300 transition-[width,background-color] duration-200 ease-out dark:bg-rui-neutral-600',\n 'hover:bg-rui-neutral-400 dark:hover:bg-rui-neutral-500 focus-visible:focus-ring outline-hidden',\n ].join(' '),\n variants: {\n active: {\n true: 'w-5 bg-rui-primary hover:bg-rui-primary dark:bg-rui-primary dark:hover:bg-rui-primary',\n },\n },\n }),\n pill: tv({\n base: 'rounded-full h-1.5 w-full bg-rui-neutral-200 dark:bg-rui-neutral-700 transition-colors',\n variants: {\n active: {\n true: 'bg-rui-primary dark:bg-rui-primary',\n },\n },\n }),\n};\n\nfunction onChange(delta: number): void {\n set(modelValue, get(modelValue) + delta);\n}\n\nfunction onPrev(): void {\n if (get(modelValue) > 1)\n onChange(-1);\n}\n\nfunction onNext(): void {\n if (get(modelValue) < pages)\n onChange(1);\n}\n\nfunction onClick(index: number): void {\n onChange(index - get(modelValue));\n}\n</script>\n\n<template>\n <div\n role=\"navigation\"\n aria-label=\"Step navigation\"\n class=\"flex items-center justify-between gap-x-4 transition-all duration-150\"\n :data-variant=\"variantProp\"\n >\n <template v-if=\"variantProp === FooterStepperVariant.pill\">\n <div\n data-id=\"pills\"\n class=\"flex w-full gap-x-3\"\n >\n <span\n v-for=\"i in pages\"\n :key=\"i\"\n :aria-current=\"modelValue === i ? 'step' : undefined\"\n :class=\"footerStepper.pill({ active: modelValue === i })\"\n />\n </div>\n </template>\n <template v-else>\n <RuiButton\n v-if=\"!hideButtons\"\n data-id=\"prev\"\n :aria-label=\"arrowButtons ? 'Previous' : undefined\"\n :disabled=\"modelValue <= 1\"\n :icon=\"arrowButtons\"\n :size=\"arrowButtons ? 'sm' : undefined\"\n :variant=\"arrowButtons ? 'outlined' : 'text'\"\n :color=\"arrowButtons ? undefined : 'primary'\"\n @click=\"onPrev()\"\n >\n <template\n v-if=\"!arrowButtons\"\n #prepend\n >\n <RuiIcon name=\"lu-chevron-left\" />\n </template>\n <span v-if=\"!arrowButtons\">Back</span>\n <RuiIcon\n v-else\n name=\"lu-chevron-left\"\n />\n </RuiButton>\n <span\n v-if=\"variantProp === FooterStepperVariant.numeric\"\n data-id=\"numeric\"\n class=\"text-sm tabular-nums text-rui-text-secondary\"\n >\n {{ modelValue }}/{{ pages }}\n </span>\n <div\n v-else-if=\"variantProp === FooterStepperVariant.bullet\"\n data-id=\"bullets\"\n class=\"flex items-center gap-x-1.5\"\n >\n <button\n v-for=\"i in pages\"\n :key=\"i\"\n type=\"button\"\n :aria-label=\"`Step ${i}`\"\n :aria-current=\"modelValue === i ? 'step' : undefined\"\n :class=\"footerStepper.bullet({ active: modelValue === i })\"\n @click=\"onClick(i)\"\n />\n </div>\n <RuiProgress\n v-else-if=\"variantProp === FooterStepperVariant.progress\"\n class=\"max-w-[60%]\"\n color=\"primary\"\n :value=\"(modelValue / pages) * 100\"\n />\n <RuiButton\n v-if=\"!hideButtons\"\n data-id=\"next\"\n :aria-label=\"arrowButtons ? 'Next' : undefined\"\n :disabled=\"modelValue >= pages\"\n :icon=\"arrowButtons\"\n :size=\"arrowButtons ? 'sm' : undefined\"\n :variant=\"arrowButtons ? 'outlined' : 'text'\"\n :color=\"arrowButtons ? undefined : 'primary'\"\n @click=\"onNext()\"\n >\n <span v-if=\"!arrowButtons\">Next</span>\n <RuiIcon\n v-else\n name=\"lu-chevron-right\"\n />\n <template\n v-if=\"!arrowButtons\"\n #append\n >\n <RuiIcon name=\"lu-chevron-right\" />\n </template>\n </RuiButton>\n </template>\n </div>\n</template>\n"],"mappings":""}
|
|
@@ -88,7 +88,8 @@ var RuiFooterStepper_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/
|
|
|
88
88
|
}), 128))])) : (openBlock(), createElementBlock(Fragment, { key: 1 }, [
|
|
89
89
|
!__props.hideButtons ? (openBlock(), createBlock(RuiButton_default, {
|
|
90
90
|
key: 0,
|
|
91
|
-
"
|
|
91
|
+
"data-id": "prev",
|
|
92
|
+
"aria-label": __props.arrowButtons ? "Previous" : void 0,
|
|
92
93
|
disabled: modelValue.value <= 1,
|
|
93
94
|
icon: __props.arrowButtons,
|
|
94
95
|
size: __props.arrowButtons ? "sm" : void 0,
|
|
@@ -106,6 +107,7 @@ var RuiFooterStepper_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/
|
|
|
106
107
|
fn: withCtx(() => [createVNode(RuiIcon_default, { name: "lu-chevron-left" })]),
|
|
107
108
|
key: "0"
|
|
108
109
|
} : void 0]), 1032, [
|
|
110
|
+
"aria-label",
|
|
109
111
|
"disabled",
|
|
110
112
|
"icon",
|
|
111
113
|
"size",
|
|
@@ -129,7 +131,8 @@ var RuiFooterStepper_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/
|
|
|
129
131
|
}, null, 8, ["value"])) : createCommentVNode("", true),
|
|
130
132
|
!__props.hideButtons ? (openBlock(), createBlock(RuiButton_default, {
|
|
131
133
|
key: 4,
|
|
132
|
-
"
|
|
134
|
+
"data-id": "next",
|
|
135
|
+
"aria-label": __props.arrowButtons ? "Next" : void 0,
|
|
133
136
|
disabled: modelValue.value >= __props.pages,
|
|
134
137
|
icon: __props.arrowButtons,
|
|
135
138
|
size: __props.arrowButtons ? "sm" : void 0,
|
|
@@ -147,6 +150,7 @@ var RuiFooterStepper_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/
|
|
|
147
150
|
fn: withCtx(() => [createVNode(RuiIcon_default, { name: "lu-chevron-right" })]),
|
|
148
151
|
key: "0"
|
|
149
152
|
} : void 0]), 1032, [
|
|
153
|
+
"aria-label",
|
|
150
154
|
"disabled",
|
|
151
155
|
"icon",
|
|
152
156
|
"size",
|
package/dist/components/steppers/RuiFooterStepper.vue_vue_type_script_setup_true_lang.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RuiFooterStepper.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../src/components/steppers/RuiFooterStepper.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport RuiButton from '@/components/buttons/button/RuiButton.vue';\nimport RuiIcon from '@/components/icons/RuiIcon.vue';\nimport RuiProgress from '@/components/progress/RuiProgress.vue';\nimport { FooterStepperVariant } from '@/components/steppers/footer-stepper-variant';\nimport { tv } from '@/utils/tv';\n\nexport interface Props {\n pages: number;\n variant?: FooterStepperVariant;\n arrowButtons?: boolean;\n hideButtons?: boolean;\n}\n\ndefineOptions({\n name: 'RuiFooterStepper',\n});\n\nconst modelValue = defineModel<number>({ default: 1 });\n\nconst {\n pages,\n variant: variantProp = FooterStepperVariant.numeric,\n arrowButtons = false,\n hideButtons = false,\n} = defineProps<Props>();\n\nconst footerStepper = {\n // the current bullet stretches into a short bar, so position reads without relying on color\n bullet: tv({\n base: [\n 'h-2 w-2 rounded-full bg-rui-neutral-300 transition-[width,background-color] duration-200 ease-out dark:bg-rui-neutral-600',\n 'hover:bg-rui-neutral-400 dark:hover:bg-rui-neutral-500 focus-visible:focus-ring outline-hidden',\n ].join(' '),\n variants: {\n active: {\n true: 'w-5 bg-rui-primary hover:bg-rui-primary dark:bg-rui-primary dark:hover:bg-rui-primary',\n },\n },\n }),\n pill: tv({\n base: 'rounded-full h-1.5 w-full bg-rui-neutral-200 dark:bg-rui-neutral-700 transition-colors',\n variants: {\n active: {\n true: 'bg-rui-primary dark:bg-rui-primary',\n },\n },\n }),\n};\n\nfunction onChange(delta: number): void {\n set(modelValue, get(modelValue) + delta);\n}\n\nfunction onPrev(): void {\n if (get(modelValue) > 1)\n onChange(-1);\n}\n\nfunction onNext(): void {\n if (get(modelValue) < pages)\n onChange(1);\n}\n\nfunction onClick(index: number): void {\n onChange(index - get(modelValue));\n}\n</script>\n\n<template>\n <div\n role=\"navigation\"\n aria-label=\"Step navigation\"\n class=\"flex items-center justify-between gap-x-4 transition-all duration-150\"\n :data-variant=\"variantProp\"\n >\n <template v-if=\"variantProp === FooterStepperVariant.pill\">\n <div\n data-id=\"pills\"\n class=\"flex w-full gap-x-3\"\n >\n <span\n v-for=\"i in pages\"\n :key=\"i\"\n :aria-current=\"modelValue === i ? 'step' : undefined\"\n :class=\"footerStepper.pill({ active: modelValue === i })\"\n />\n </div>\n </template>\n <template v-else>\n <RuiButton\n v-if=\"!hideButtons\"\n aria-label=\"Previous\"\n :disabled=\"modelValue <= 1\"\n :icon=\"arrowButtons\"\n :size=\"arrowButtons ? 'sm' : undefined\"\n :variant=\"arrowButtons ? 'outlined' : 'text'\"\n :color=\"arrowButtons ? undefined : 'primary'\"\n @click=\"onPrev()\"\n >\n <template\n v-if=\"!arrowButtons\"\n #prepend\n >\n <RuiIcon name=\"lu-chevron-left\" />\n </template>\n <span v-if=\"!arrowButtons\">Back</span>\n <RuiIcon\n v-else\n name=\"lu-chevron-left\"\n />\n </RuiButton>\n <span\n v-if=\"variantProp === FooterStepperVariant.numeric\"\n data-id=\"numeric\"\n class=\"text-sm tabular-nums text-rui-text-secondary\"\n >\n {{ modelValue }}/{{ pages }}\n </span>\n <div\n v-else-if=\"variantProp === FooterStepperVariant.bullet\"\n data-id=\"bullets\"\n class=\"flex items-center gap-x-1.5\"\n >\n <button\n v-for=\"i in pages\"\n :key=\"i\"\n type=\"button\"\n :aria-label=\"`Step ${i}`\"\n :aria-current=\"modelValue === i ? 'step' : undefined\"\n :class=\"footerStepper.bullet({ active: modelValue === i })\"\n @click=\"onClick(i)\"\n />\n </div>\n <RuiProgress\n v-else-if=\"variantProp === FooterStepperVariant.progress\"\n class=\"max-w-[60%]\"\n color=\"primary\"\n :value=\"(modelValue / pages) * 100\"\n />\n <RuiButton\n v-if=\"!hideButtons\"\n aria-label=\"Next\"\n :disabled=\"modelValue >= pages\"\n :icon=\"arrowButtons\"\n :size=\"arrowButtons ? 'sm' : undefined\"\n :variant=\"arrowButtons ? 'outlined' : 'text'\"\n :color=\"arrowButtons ? undefined : 'primary'\"\n @click=\"onNext()\"\n >\n <span v-if=\"!arrowButtons\">Next</span>\n <RuiIcon\n v-else\n name=\"lu-chevron-right\"\n />\n <template\n v-if=\"!arrowButtons\"\n #append\n >\n <RuiIcon name=\"lu-chevron-right\" />\n </template>\n </RuiButton>\n </template>\n </div>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAkBA,MAAM,
|
|
1
|
+
{"version":3,"file":"RuiFooterStepper.vue_vue_type_script_setup_true_lang.js","names":["_useModel","_openBlock","_createElementBlock","_unref","_Fragment","_renderList","_normalizeClass","_createBlock","RuiButton","_createSlots","_withCtx","RuiIcon","_createVNode","_createCommentVNode","_toDisplayString","RuiProgress"],"sources":["../../../src/components/steppers/RuiFooterStepper.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport RuiButton from '@/components/buttons/button/RuiButton.vue';\nimport RuiIcon from '@/components/icons/RuiIcon.vue';\nimport RuiProgress from '@/components/progress/RuiProgress.vue';\nimport { FooterStepperVariant } from '@/components/steppers/footer-stepper-variant';\nimport { tv } from '@/utils/tv';\n\nexport interface Props {\n pages: number;\n variant?: FooterStepperVariant;\n arrowButtons?: boolean;\n hideButtons?: boolean;\n}\n\ndefineOptions({\n name: 'RuiFooterStepper',\n});\n\nconst modelValue = defineModel<number>({ default: 1 });\n\nconst {\n pages,\n variant: variantProp = FooterStepperVariant.numeric,\n arrowButtons = false,\n hideButtons = false,\n} = defineProps<Props>();\n\nconst footerStepper = {\n // the current bullet stretches into a short bar, so position reads without relying on color\n bullet: tv({\n base: [\n 'h-2 w-2 rounded-full bg-rui-neutral-300 transition-[width,background-color] duration-200 ease-out dark:bg-rui-neutral-600',\n 'hover:bg-rui-neutral-400 dark:hover:bg-rui-neutral-500 focus-visible:focus-ring outline-hidden',\n ].join(' '),\n variants: {\n active: {\n true: 'w-5 bg-rui-primary hover:bg-rui-primary dark:bg-rui-primary dark:hover:bg-rui-primary',\n },\n },\n }),\n pill: tv({\n base: 'rounded-full h-1.5 w-full bg-rui-neutral-200 dark:bg-rui-neutral-700 transition-colors',\n variants: {\n active: {\n true: 'bg-rui-primary dark:bg-rui-primary',\n },\n },\n }),\n};\n\nfunction onChange(delta: number): void {\n set(modelValue, get(modelValue) + delta);\n}\n\nfunction onPrev(): void {\n if (get(modelValue) > 1)\n onChange(-1);\n}\n\nfunction onNext(): void {\n if (get(modelValue) < pages)\n onChange(1);\n}\n\nfunction onClick(index: number): void {\n onChange(index - get(modelValue));\n}\n</script>\n\n<template>\n <div\n role=\"navigation\"\n aria-label=\"Step navigation\"\n class=\"flex items-center justify-between gap-x-4 transition-all duration-150\"\n :data-variant=\"variantProp\"\n >\n <template v-if=\"variantProp === FooterStepperVariant.pill\">\n <div\n data-id=\"pills\"\n class=\"flex w-full gap-x-3\"\n >\n <span\n v-for=\"i in pages\"\n :key=\"i\"\n :aria-current=\"modelValue === i ? 'step' : undefined\"\n :class=\"footerStepper.pill({ active: modelValue === i })\"\n />\n </div>\n </template>\n <template v-else>\n <RuiButton\n v-if=\"!hideButtons\"\n data-id=\"prev\"\n :aria-label=\"arrowButtons ? 'Previous' : undefined\"\n :disabled=\"modelValue <= 1\"\n :icon=\"arrowButtons\"\n :size=\"arrowButtons ? 'sm' : undefined\"\n :variant=\"arrowButtons ? 'outlined' : 'text'\"\n :color=\"arrowButtons ? undefined : 'primary'\"\n @click=\"onPrev()\"\n >\n <template\n v-if=\"!arrowButtons\"\n #prepend\n >\n <RuiIcon name=\"lu-chevron-left\" />\n </template>\n <span v-if=\"!arrowButtons\">Back</span>\n <RuiIcon\n v-else\n name=\"lu-chevron-left\"\n />\n </RuiButton>\n <span\n v-if=\"variantProp === FooterStepperVariant.numeric\"\n data-id=\"numeric\"\n class=\"text-sm tabular-nums text-rui-text-secondary\"\n >\n {{ modelValue }}/{{ pages }}\n </span>\n <div\n v-else-if=\"variantProp === FooterStepperVariant.bullet\"\n data-id=\"bullets\"\n class=\"flex items-center gap-x-1.5\"\n >\n <button\n v-for=\"i in pages\"\n :key=\"i\"\n type=\"button\"\n :aria-label=\"`Step ${i}`\"\n :aria-current=\"modelValue === i ? 'step' : undefined\"\n :class=\"footerStepper.bullet({ active: modelValue === i })\"\n @click=\"onClick(i)\"\n />\n </div>\n <RuiProgress\n v-else-if=\"variantProp === FooterStepperVariant.progress\"\n class=\"max-w-[60%]\"\n color=\"primary\"\n :value=\"(modelValue / pages) * 100\"\n />\n <RuiButton\n v-if=\"!hideButtons\"\n data-id=\"next\"\n :aria-label=\"arrowButtons ? 'Next' : undefined\"\n :disabled=\"modelValue >= pages\"\n :icon=\"arrowButtons\"\n :size=\"arrowButtons ? 'sm' : undefined\"\n :variant=\"arrowButtons ? 'outlined' : 'text'\"\n :color=\"arrowButtons ? undefined : 'primary'\"\n @click=\"onNext()\"\n >\n <span v-if=\"!arrowButtons\">Next</span>\n <RuiIcon\n v-else\n name=\"lu-chevron-right\"\n />\n <template\n v-if=\"!arrowButtons\"\n #append\n >\n <RuiIcon name=\"lu-chevron-right\" />\n </template>\n </RuiButton>\n </template>\n </div>\n</template>\n"],"mappings":"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"}
|