@rotki/ui-library 3.0.0-beta.2 → 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 +1 -0
- 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/auto-complete/auto-complete-styles.d.ts +3 -53
- package/dist/components/forms/auto-complete/auto-complete-styles.js +2 -1
- package/dist/components/forms/auto-complete/auto-complete-styles.js.map +1 -1
- 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/forms/text-input-styles.js +1 -1
- package/dist/components/forms/text-input-styles.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 +26 -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":"data-table-styles.js","names":[],"sources":["../../../src/components/tables/data-table-styles.ts"],"sourcesContent":["import { tv } from '@/utils/tv';\n\n/** A 2px primary rail down the left edge of an open row and its panel; out of flow, so the cell keeps its padding. */\nconst OPEN_ROW_RAIL = '[&>td:first-child]:relative [&>td:first-child]:before:absolute [&>td:first-child]:before:inset-y-0 [&>td:first-child]:before:left-0 [&>td:first-child]:before:w-0.5 [&>td:first-child]:before:bg-rui-primary';\n\n/**\n * The band of an open row inside another table's panel: a step darker than the outer band, so the two\n * levels never share a grey while the rows between them keep the plain surface.\n */\nconst NESTED_BAND = '[[data-id=row-expanded]_&]:bg-rui-neutral-950/[0.11] dark:[[data-id=row-expanded]_&]:bg-white/[0.14]';\n\n/**\n * Header and pagination of a nested table, stepped by depth to stand off the band around them (about\n * 1.12:1 or more) as well as their own rows: past the lighter band one panel deep, short of the darker\n * band two deep. Nested bars never stick, so the tint can be translucent over the table's own surface.\n */\nexport const NESTED_BAR = '[[data-id=row-expanded]_&]:bg-rui-neutral-950/[0.13] dark:[[data-id=row-expanded]_&]:bg-white/[0.16] [[data-id=row-expanded]_[data-id=row-expanded]_&]:bg-rui-neutral-950/[0.06] dark:[[data-id=row-expanded]_[data-id=row-expanded]_&]:bg-white/[0.07]';\n\nexport const dataTableStyles = tv({\n slots: {\n // `clip`, not `hidden`, which may shrink the item below its rows; its own surface reads the same anywhere\n wrapper: 'relative between:border-t between:border-b-0 between:border-rui-divider overflow-clip bg-rui-surface',\n // focusable only while it scrolls with nothing to tab to (useKeyboardScroll), ring drawn inside\n scroller: 'overflow-x-auto overflow-y-hidden [clip-path:inset(0_0_0_0)] outline-hidden focus-visible:focus-ring focus-visible:-outline-offset-2',\n table: 'min-w-full table-fixed between:border-t between:border-b-0 between:border-rui-divider whitespace-nowrap mx-auto my-0 max-w-fit relative border-rui-divider',\n tbody: 'between:border-t between:border-b-0 between:border-rui-divider',\n tr: 'hover:bg-rui-hover',\n // numbers line up in columns; no slashed zero, which in Inter reads as a second, monospace font beside zero-free values\n td: '[:where(&)]:px-4 text-rui-text text-body-2 tabular-nums [text-wrap:initial]',\n checkbox: 'px-2 w-[3.625rem] max-w-[3.625rem] [&_label]:ml-0',\n tbodyLoader: 'text-center',\n // tinted like the column header, the pair framing the body; opaque, so rows scroll behind a stuck bar\n pagination: `bg-rui-surface-muted ${NESTED_BAR}`,\n },\n variants: {\n sticky: {\n true: { pagination: 'sticky bottom-0 z-rui-raised' },\n },\n outlined: {\n true: { wrapper: 'border border-rui-divider' },\n },\n rounded: {\n sm: { wrapper: 'rounded-rui-sm' },\n md: { wrapper: 'rounded-rui-card' },\n lg: { wrapper: 'rounded-rui-lg' },\n },\n dense: {\n true: {},\n false: {},\n },\n //
|
|
1
|
+
{"version":3,"file":"data-table-styles.js","names":[],"sources":["../../../src/components/tables/data-table-styles.ts"],"sourcesContent":["import { tv } from '@/utils/tv';\n\n/** A 2px primary rail down the left edge of an open row and its panel; out of flow, so the cell keeps its padding. */\nconst OPEN_ROW_RAIL = '[&>td:first-child]:relative [&>td:first-child]:before:absolute [&>td:first-child]:before:inset-y-0 [&>td:first-child]:before:left-0 [&>td:first-child]:before:w-0.5 [&>td:first-child]:before:bg-rui-primary';\n\n/**\n * The band of an open row inside another table's panel: a step darker than the outer band, so the two\n * levels never share a grey while the rows between them keep the plain surface.\n */\nconst NESTED_BAND = '[[data-id=row-expanded]_&]:bg-rui-neutral-950/[0.11] dark:[[data-id=row-expanded]_&]:bg-white/[0.14]';\n\n/**\n * Header and pagination of a nested table, stepped by depth to stand off the band around them (about\n * 1.12:1 or more) as well as their own rows: past the lighter band one panel deep, short of the darker\n * band two deep. Nested bars never stick, so the tint can be translucent over the table's own surface.\n */\nexport const NESTED_BAR = '[[data-id=row-expanded]_&]:bg-rui-neutral-950/[0.13] dark:[[data-id=row-expanded]_&]:bg-white/[0.16] [[data-id=row-expanded]_[data-id=row-expanded]_&]:bg-rui-neutral-950/[0.06] dark:[[data-id=row-expanded]_[data-id=row-expanded]_&]:bg-white/[0.07]';\n\nexport const dataTableStyles = tv({\n slots: {\n // `clip`, not `hidden`, which may shrink the item below its rows; its own surface reads the same anywhere\n wrapper: 'relative between:border-t between:border-b-0 between:border-rui-divider overflow-clip bg-rui-surface',\n // focusable only while it scrolls with nothing to tab to (useKeyboardScroll), ring drawn inside\n scroller: 'overflow-x-auto overflow-y-hidden [clip-path:inset(0_0_0_0)] outline-hidden focus-visible:focus-ring focus-visible:-outline-offset-2',\n table: 'min-w-full table-fixed between:border-t between:border-b-0 between:border-rui-divider whitespace-nowrap mx-auto my-0 max-w-fit relative border-rui-divider',\n tbody: 'between:border-t between:border-b-0 between:border-rui-divider',\n tr: 'hover:bg-rui-hover',\n // numbers line up in columns; no slashed zero, which in Inter reads as a second, monospace font beside zero-free values\n td: '[:where(&)]:px-4 text-rui-text text-body-2 tabular-nums [text-wrap:initial]',\n checkbox: 'px-2 w-[3.625rem] max-w-[3.625rem] [&_label]:ml-0',\n tbodyLoader: 'text-center',\n // tinted like the column header, the pair framing the body; opaque, so rows scroll behind a stuck bar\n pagination: `bg-rui-surface-muted ${NESTED_BAR}`,\n },\n variants: {\n sticky: {\n true: { pagination: 'sticky bottom-0 z-rui-raised' },\n },\n outlined: {\n true: { wrapper: 'border border-rui-divider' },\n },\n rounded: {\n sm: { wrapper: 'rounded-rui-sm' },\n md: { wrapper: 'rounded-rui-card' },\n lg: { wrapper: 'rounded-rui-lg' },\n },\n dense: {\n true: {},\n false: {},\n },\n // under every row state through `:where()`; set per item (`data-stripe`), so a follow-up row or open panel shifts none\n striped: {\n true: { tbody: '[:where(&>tr[data-stripe])]:bg-rui-neutral-950/[0.03] dark:[:where(&>tr[data-stripe])]:bg-white/[0.04]' },\n },\n rowVariant: {\n selected: { tr: 'bg-rui-primary-soft' },\n empty: { tr: 'hover:bg-transparent' },\n // a grey band darker than the header so the two never match, a step darker again inside another panel\n expandable: { tr: `bg-rui-neutral-950/[0.07] hover:bg-rui-neutral-950/[0.07] dark:bg-white/[0.09] dark:hover:bg-white/[0.09] ${NESTED_BAND} [[data-id=row-expanded]_&]:hover:bg-rui-neutral-950/[0.11] dark:[[data-id=row-expanded]_&]:hover:bg-white/[0.14] ${OPEN_ROW_RAIL} !border-t-0` },\n expandedParent: { tr: `bg-rui-neutral-950/[0.07] dark:bg-white/[0.09] ${NESTED_BAND} ${OPEN_ROW_RAIL}` },\n group: { tr: 'bg-rui-neutral-100 dark:bg-white/[0.05]' },\n },\n mobile: {\n true: {\n wrapper: 'between:border-t-0 border-0 rounded-none overflow-visible',\n scroller: 'overflow-visible [clip-path:none]',\n table: 'block min-w-0 max-w-none w-full whitespace-normal between:border-t-0 border-0',\n tbody: 'block between:border-t-0',\n tr: 'block',\n td: 'block px-4 py-2',\n },\n },\n },\n /**\n * A fixed row height keeps a row of plain text as tall as one holding an\n * icon button. Padding and floor sit in `:where()` so a consumer's `cellClass`\n * (`py-0` is common) still wins at any stylesheet order, and each density\n * sets its own because the class merger cannot dedupe these.\n */\n compoundVariants: [\n // a 4px inset under the height floor fits a 36px button in a 44px row (a 28px one in a dense 36px row)\n { dense: false, mobile: false, class: { td: '[:where(&)]:py-1 [:where(&)]:h-11' } },\n { dense: true, mobile: false, class: { td: '[:where(&)]:py-1 [:where(&)]:h-9' } },\n ],\n defaultVariants: {\n dense: false,\n mobile: false,\n },\n});\n"],"mappings":";;;AAGA,IAAM,gBAAgB;;;;;AAMtB,IAAM,cAAc;;;;;;AAOpB,IAAa,aAAa;AAE1B,IAAa,kBAAkB,GAAG;CAChC,OAAO;EAEL,SAAS;EAET,UAAU;EACV,OAAO;EACP,OAAO;EACP,IAAI;EAEJ,IAAI;EACJ,UAAU;EACV,aAAa;EAEb,YAAY,wBAAwB;CACtC;CACA,UAAU;EACR,QAAQ,EACN,MAAM,EAAE,YAAY,+BAA+B,EACrD;EACA,UAAU,EACR,MAAM,EAAE,SAAS,4BAA4B,EAC/C;EACA,SAAS;GACP,IAAI,EAAE,SAAS,iBAAiB;GAChC,IAAI,EAAE,SAAS,mBAAmB;GAClC,IAAI,EAAE,SAAS,iBAAiB;EAClC;EACA,OAAO;GACL,MAAM,CAAC;GACP,OAAO,CAAC;EACV;EAEA,SAAS,EACP,MAAM,EAAE,OAAO,yGAAyG,EAC1H;EACA,YAAY;GACV,UAAU,EAAE,IAAI,sBAAsB;GACtC,OAAO,EAAE,IAAI,uBAAuB;GAEpC,YAAY,EAAE,IAAI,6GAA6G,YAAY,oHAAoH,cAAc,cAAc;GAC3R,gBAAgB,EAAE,IAAI,kDAAkD,YAAY,GAAG,gBAAgB;GACvG,OAAO,EAAE,IAAI,0CAA0C;EACzD;EACA,QAAQ,EACN,MAAM;GACJ,SAAS;GACT,UAAU;GACV,OAAO;GACP,OAAO;GACP,IAAI;GACJ,IAAI;EACN,EACF;CACF;;;;;;;CAOA,kBAAkB,CAEhB;EAAE,OAAO;EAAO,QAAQ;EAAO,OAAO,EAAE,IAAI,oCAAoC;CAAE,GAClF;EAAE,OAAO;EAAM,QAAQ;EAAO,OAAO,EAAE,IAAI,mCAAmC;CAAE,CAClF;CACA,iBAAiB;EACf,OAAO;EACP,QAAQ;CACV;AACF,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RuiTab.js","names":[],"sources":["../../../../src/components/tabs/tab/RuiTab.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport type { RouteLocationRaw } from 'vue-router';\nimport type { ContextColorsType } from '@/consts/colors';\nimport type { VueClassValue } from '@/types/class-value';\nimport { TabAlignment, TabIndicatorPosition, TabLayout, TabVariant } from '@/components/tabs/tab-props';\nimport { useTabLink } from '@/components/tabs/tab/use-tab-link';\nimport { cn, tv } from '@/utils/tv';\n\nexport interface RuiTabClassNames {\n root?: VueClassValue;\n active?: VueClassValue;\n}\n\nexport interface Props {\n color?: ContextColorsType;\n disabled?: boolean;\n grow?: boolean;\n value?: number | string;\n active?: boolean;\n classNames?: RuiTabClassNames;\n link?: boolean;\n target?: string;\n to?: RouteLocationRaw;\n exact?: boolean;\n vertical?: boolean;\n align?: TabAlignment;\n indicatorPosition?: TabIndicatorPosition;\n variant?: TabVariant;\n}\n\ndefineOptions({\n name: 'RuiTab',\n inheritAttrs: false,\n});\n\nconst {\n color,\n disabled = false,\n grow = false,\n value = useId(),\n active = false,\n classNames,\n link = false,\n to = '',\n target = '_self',\n exact = false,\n vertical = false,\n align = TabAlignment.center,\n indicatorPosition = TabIndicatorPosition.end,\n variant = TabVariant.underline,\n} = defineProps<Props>();\n\nconst emit = defineEmits<{\n click: [value: string | number];\n}>();\n\nconst slots = defineSlots<{\n default?: (props?: object) => any;\n prepend?: (props?: object) => any;\n append?: (props?: object) => any;\n}>();\n\n/**\n * A tab is a plain button or link: RuiTabs draws the active indicator, so a tab\n * only sets its label color, and its hover fill. On the underline bar the fill\n * hugs the label rather than the 40px cell, so the bar stays calm.\n */\nconst tab = tv({\n slots: {\n root: [\n 'group relative inline-flex shrink-0 items-center whitespace-nowrap rounded-rui-control',\n 'text-sm font-medium text-rui-text-secondary transition-colors duration-150 [--rui-icon-size:1rem]',\n // inset, since the scrolling bar would clip a ring drawn outside the tab\n 'outline-hidden focus-visible:focus-ring focus-visible:-outline-offset-2',\n ].join(' '),\n content: 'inline-flex items-center gap-2 rounded-rui-control transition-colors duration-150',\n },\n variants: {\n variant: {\n [TabVariant.underline]: { root: 'px-1', content: 'h-8 px-2' },\n // above the sliding pill, which RuiTabs renders behind the tabs\n [TabVariant.segmented]: { root: 'z-1 h-8 px-3' },\n },\n layout: {\n [TabLayout.horizontal]: {},\n [TabLayout.vertical]: { root: 'w-full' },\n },\n align: {\n start: { root: 'justify-start text-left rtl:justify-end rtl:text-right' },\n center: { root: 'justify-center text-center' },\n end: { root: 'justify-end text-right rtl:justify-start rtl:text-left' },\n },\n grow: {\n true: { root: 'grow' },\n },\n active: {\n true: { root: 'text-rui-text' },\n false: {},\n },\n disabled: {\n true: { root: 'cursor-not-allowed text-rui-text-disabled' },\n false: { root: 'cursor-pointer hover:text-rui-text' },\n },\n },\n compoundVariants: [\n { variant: TabVariant.underline, layout: TabLayout.horizontal, class: { root: 'h-10' } },\n { variant: TabVariant.underline, layout: TabLayout.horizontal, disabled: false, class: { content: 'group-hover:bg-rui-hover' } },\n // a vertical list fills the whole row on hover and keeps that fill on the selected row\n { variant: TabVariant.underline, layout: TabLayout.vertical, class: { root: 'min-h-9 px-3', content: 'h-auto px-0 py-2' } },\n { variant: TabVariant.underline, layout: TabLayout.vertical, disabled: false, class: { root: 'hover:bg-rui-hover' } },\n { variant: TabVariant.underline, layout: TabLayout.vertical, active: true, class: { root: 'bg-rui-hover' } },\n ],\n defaultVariants: {\n variant: TabVariant.underline,\n layout: TabLayout.horizontal,\n align: 'center',\n active: false,\n disabled: false,\n },\n});\n\nconst { isRouteActive, href: linkHref, navigate, isLink } = useTabLink({\n link: () => link,\n to: () => to,\n exact: () => exact,\n});\n\nconst layout = computed<TabLayout>(() => vertical ? TabLayout.vertical : TabLayout.horizontal);\nconst isSelf = computed<boolean>(() => target === '_self');\nconst isEffectivelyActive = computed<boolean>(() => active || get(isRouteActive));\nconst ui = computed<ReturnType<typeof tab>>(() => tab({\n variant,\n layout: get(layout),\n align,\n grow,\n disabled,\n active: get(isEffectivelyActive),\n}));\n\nfunction onClick(event: MouseEvent): void {\n if (disabled) {\n event.preventDefault();\n return;\n }\n\n emit('click', value);\n if (navigate && get(isSelf))\n navigate(event);\n}\n</script>\n\n<template>\n <component\n :is=\"isLink ? 'a' : 'button'\"\n :type=\"isLink ? undefined : 'button'\"\n :class=\"[\n ui.root({ class: cn(classNames?.root) }),\n isEffectivelyActive && classNames?.active,\n ]\"\n :data-active-tab=\"isEffectivelyActive || undefined\"\n :data-align=\"align\"\n :data-indicator-position=\"indicatorPosition\"\n :data-vertical=\"vertical || undefined\"\n :data-variant=\"variant\"\n :data-color=\"isEffectivelyActive ? color : undefined\"\n :disabled=\"isLink ? undefined : disabled\"\n :aria-disabled=\"isLink && disabled ? 'true' : undefined\"\n :href=\"isLink && !isSelf && !disabled ? linkHref : undefined\"\n :target=\"isLink ? target : undefined\"\n role=\"tab\"\n :aria-selected=\"isEffectivelyActive\"\n :tabindex=\"isEffectivelyActive && !disabled ? 0 : -1\"\n v-bind=\"$attrs\"\n @click=\"onClick($event)\"\n >\n <span :class=\"ui.content()\">\n <slot\n v-if=\"slots.prepend\"\n name=\"prepend\"\n />\n <slot />\n <slot\n v-if=\"slots.append\"\n name=\"append\"\n />\n </span>\n </component>\n</template>\n"],"mappings":""}
|
|
1
|
+
{"version":3,"file":"RuiTab.js","names":["_sfc_main"],"sources":["../../../../src/components/tabs/tab/RuiTab.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport type { RouteLocationRaw } from 'vue-router';\nimport type { ContextColorsType } from '@/consts/colors';\nimport type { VueClassValue } from '@/types/class-value';\nimport { TabAlignment, TabIndicatorPosition, TabLayout, TabVariant } from '@/components/tabs/tab-props';\nimport { useTabLink } from '@/components/tabs/tab/use-tab-link';\nimport { cn, tv } from '@/utils/tv';\n\nexport interface RuiTabClassNames {\n root?: VueClassValue;\n active?: VueClassValue;\n}\n\nexport interface Props {\n color?: ContextColorsType;\n disabled?: boolean;\n grow?: boolean;\n value?: number | string;\n active?: boolean;\n classNames?: RuiTabClassNames;\n link?: boolean;\n target?: string;\n to?: RouteLocationRaw;\n exact?: boolean;\n vertical?: boolean;\n align?: TabAlignment;\n indicatorPosition?: TabIndicatorPosition;\n variant?: TabVariant;\n}\n\ndefineOptions({\n name: 'RuiTab',\n inheritAttrs: false,\n});\n\nconst {\n color,\n disabled = false,\n grow = false,\n value = useId(),\n active = false,\n classNames,\n link = false,\n to = '',\n target = '_self',\n exact = false,\n vertical = false,\n align = TabAlignment.center,\n indicatorPosition = TabIndicatorPosition.end,\n variant = TabVariant.underline,\n} = defineProps<Props>();\n\nconst emit = defineEmits<{\n click: [value: string | number];\n}>();\n\nconst slots = defineSlots<{\n default?: (props?: object) => any;\n prepend?: (props?: object) => any;\n append?: (props?: object) => any;\n}>();\n\n/**\n * A tab is a plain button or link: RuiTabs draws the active indicator, so a tab\n * only sets its label color, and its hover fill. On the underline bar the fill\n * hugs the label rather than the 40px cell, so the bar stays calm.\n */\nconst tab = tv({\n slots: {\n root: [\n 'group relative inline-flex shrink-0 items-center whitespace-nowrap rounded-rui-control',\n 'text-sm font-medium text-rui-text-secondary transition-colors duration-150 [--rui-icon-size:1rem]',\n // inset, since the scrolling bar would clip a ring drawn outside the tab\n 'outline-hidden focus-visible:focus-ring focus-visible:-outline-offset-2',\n ].join(' '),\n content: 'inline-flex items-center gap-2 rounded-rui-control transition-colors duration-150',\n },\n variants: {\n variant: {\n [TabVariant.underline]: { root: 'px-1', content: 'h-8 px-2' },\n // above the sliding pill, which RuiTabs renders behind the tabs\n [TabVariant.segmented]: { root: 'z-1 h-8 px-3' },\n },\n layout: {\n [TabLayout.horizontal]: {},\n [TabLayout.vertical]: { root: 'w-full' },\n },\n align: {\n start: { root: 'justify-start text-left rtl:justify-end rtl:text-right' },\n center: { root: 'justify-center text-center' },\n end: { root: 'justify-end text-right rtl:justify-start rtl:text-left' },\n },\n grow: {\n true: { root: 'grow' },\n },\n active: {\n true: { root: 'text-rui-text' },\n false: {},\n },\n disabled: {\n true: { root: 'cursor-not-allowed text-rui-text-disabled' },\n false: { root: 'cursor-pointer hover:text-rui-text' },\n },\n },\n compoundVariants: [\n { variant: TabVariant.underline, layout: TabLayout.horizontal, class: { root: 'h-10' } },\n { variant: TabVariant.underline, layout: TabLayout.horizontal, disabled: false, class: { content: 'group-hover:bg-rui-hover' } },\n // a vertical list fills the whole row on hover and keeps that fill on the selected row\n { variant: TabVariant.underline, layout: TabLayout.vertical, class: { root: 'min-h-9 px-3', content: 'h-auto px-0 py-2' } },\n { variant: TabVariant.underline, layout: TabLayout.vertical, disabled: false, class: { root: 'hover:bg-rui-hover' } },\n { variant: TabVariant.underline, layout: TabLayout.vertical, active: true, class: { root: 'bg-rui-hover' } },\n ],\n defaultVariants: {\n variant: TabVariant.underline,\n layout: TabLayout.horizontal,\n align: 'center',\n active: false,\n disabled: false,\n },\n});\n\nconst { isRouteActive, href: linkHref, navigate, isLink } = useTabLink({\n link: () => link,\n to: () => to,\n exact: () => exact,\n});\n\nconst layout = computed<TabLayout>(() => vertical ? TabLayout.vertical : TabLayout.horizontal);\nconst isSelf = computed<boolean>(() => target === '_self');\nconst isEffectivelyActive = computed<boolean>(() => active || get(isRouteActive));\nconst ui = computed<ReturnType<typeof tab>>(() => tab({\n variant,\n layout: get(layout),\n align,\n grow,\n disabled,\n active: get(isEffectivelyActive),\n}));\n\nfunction onClick(event: MouseEvent): void {\n if (disabled) {\n event.preventDefault();\n return;\n }\n\n emit('click', value);\n if (navigate && get(isSelf))\n navigate(event);\n}\n</script>\n\n<template>\n <component\n :is=\"isLink ? 'a' : 'button'\"\n :type=\"isLink ? undefined : 'button'\"\n :class=\"[\n ui.root({ class: cn(classNames?.root) }),\n isEffectivelyActive && classNames?.active,\n ]\"\n :data-active-tab=\"isEffectivelyActive || undefined\"\n :data-align=\"align\"\n :data-indicator-position=\"indicatorPosition\"\n :data-vertical=\"vertical || undefined\"\n :data-variant=\"variant\"\n :data-color=\"isEffectivelyActive ? color : undefined\"\n :disabled=\"isLink ? undefined : disabled\"\n :aria-disabled=\"isLink && disabled ? 'true' : undefined\"\n :href=\"isLink && !isSelf && !disabled ? linkHref : undefined\"\n :target=\"isLink ? target : undefined\"\n role=\"tab\"\n :aria-selected=\"isEffectivelyActive\"\n :tabindex=\"isEffectivelyActive && !disabled ? 0 : -1\"\n v-bind=\"$attrs\"\n @click=\"onClick($event)\"\n >\n <span :class=\"ui.content()\">\n <slot\n v-if=\"slots.prepend\"\n name=\"prepend\"\n />\n <slot />\n <slot\n v-if=\"slots.append\"\n name=\"append\"\n />\n </span>\n </component>\n</template>\n"],"mappings":""}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { RouteLocationRaw } from 'vue-router';
|
|
2
2
|
import type { ContextColorsType } from '../../../consts/colors.js';
|
|
3
|
-
import type { VueClassValue } from '../../../types/class-value';
|
|
3
|
+
import type { VueClassValue } from '../../../types/class-value.js';
|
|
4
4
|
import { TabAlignment, TabIndicatorPosition, TabVariant } from '../tab-props.js';
|
|
5
5
|
export interface RuiTabClassNames {
|
|
6
6
|
root?: VueClassValue;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RuiTab.vue_vue_type_script_setup_true_lang.js","names":["$attrs"],"sources":["../../../../src/components/tabs/tab/RuiTab.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport type { RouteLocationRaw } from 'vue-router';\nimport type { ContextColorsType } from '@/consts/colors';\nimport type { VueClassValue } from '@/types/class-value';\nimport { TabAlignment, TabIndicatorPosition, TabLayout, TabVariant } from '@/components/tabs/tab-props';\nimport { useTabLink } from '@/components/tabs/tab/use-tab-link';\nimport { cn, tv } from '@/utils/tv';\n\nexport interface RuiTabClassNames {\n root?: VueClassValue;\n active?: VueClassValue;\n}\n\nexport interface Props {\n color?: ContextColorsType;\n disabled?: boolean;\n grow?: boolean;\n value?: number | string;\n active?: boolean;\n classNames?: RuiTabClassNames;\n link?: boolean;\n target?: string;\n to?: RouteLocationRaw;\n exact?: boolean;\n vertical?: boolean;\n align?: TabAlignment;\n indicatorPosition?: TabIndicatorPosition;\n variant?: TabVariant;\n}\n\ndefineOptions({\n name: 'RuiTab',\n inheritAttrs: false,\n});\n\nconst {\n color,\n disabled = false,\n grow = false,\n value = useId(),\n active = false,\n classNames,\n link = false,\n to = '',\n target = '_self',\n exact = false,\n vertical = false,\n align = TabAlignment.center,\n indicatorPosition = TabIndicatorPosition.end,\n variant = TabVariant.underline,\n} = defineProps<Props>();\n\nconst emit = defineEmits<{\n click: [value: string | number];\n}>();\n\nconst slots = defineSlots<{\n default?: (props?: object) => any;\n prepend?: (props?: object) => any;\n append?: (props?: object) => any;\n}>();\n\n/**\n * A tab is a plain button or link: RuiTabs draws the active indicator, so a tab\n * only sets its label color, and its hover fill. On the underline bar the fill\n * hugs the label rather than the 40px cell, so the bar stays calm.\n */\nconst tab = tv({\n slots: {\n root: [\n 'group relative inline-flex shrink-0 items-center whitespace-nowrap rounded-rui-control',\n 'text-sm font-medium text-rui-text-secondary transition-colors duration-150 [--rui-icon-size:1rem]',\n // inset, since the scrolling bar would clip a ring drawn outside the tab\n 'outline-hidden focus-visible:focus-ring focus-visible:-outline-offset-2',\n ].join(' '),\n content: 'inline-flex items-center gap-2 rounded-rui-control transition-colors duration-150',\n },\n variants: {\n variant: {\n [TabVariant.underline]: { root: 'px-1', content: 'h-8 px-2' },\n // above the sliding pill, which RuiTabs renders behind the tabs\n [TabVariant.segmented]: { root: 'z-1 h-8 px-3' },\n },\n layout: {\n [TabLayout.horizontal]: {},\n [TabLayout.vertical]: { root: 'w-full' },\n },\n align: {\n start: { root: 'justify-start text-left rtl:justify-end rtl:text-right' },\n center: { root: 'justify-center text-center' },\n end: { root: 'justify-end text-right rtl:justify-start rtl:text-left' },\n },\n grow: {\n true: { root: 'grow' },\n },\n active: {\n true: { root: 'text-rui-text' },\n false: {},\n },\n disabled: {\n true: { root: 'cursor-not-allowed text-rui-text-disabled' },\n false: { root: 'cursor-pointer hover:text-rui-text' },\n },\n },\n compoundVariants: [\n { variant: TabVariant.underline, layout: TabLayout.horizontal, class: { root: 'h-10' } },\n { variant: TabVariant.underline, layout: TabLayout.horizontal, disabled: false, class: { content: 'group-hover:bg-rui-hover' } },\n // a vertical list fills the whole row on hover and keeps that fill on the selected row\n { variant: TabVariant.underline, layout: TabLayout.vertical, class: { root: 'min-h-9 px-3', content: 'h-auto px-0 py-2' } },\n { variant: TabVariant.underline, layout: TabLayout.vertical, disabled: false, class: { root: 'hover:bg-rui-hover' } },\n { variant: TabVariant.underline, layout: TabLayout.vertical, active: true, class: { root: 'bg-rui-hover' } },\n ],\n defaultVariants: {\n variant: TabVariant.underline,\n layout: TabLayout.horizontal,\n align: 'center',\n active: false,\n disabled: false,\n },\n});\n\nconst { isRouteActive, href: linkHref, navigate, isLink } = useTabLink({\n link: () => link,\n to: () => to,\n exact: () => exact,\n});\n\nconst layout = computed<TabLayout>(() => vertical ? TabLayout.vertical : TabLayout.horizontal);\nconst isSelf = computed<boolean>(() => target === '_self');\nconst isEffectivelyActive = computed<boolean>(() => active || get(isRouteActive));\nconst ui = computed<ReturnType<typeof tab>>(() => tab({\n variant,\n layout: get(layout),\n align,\n grow,\n disabled,\n active: get(isEffectivelyActive),\n}));\n\nfunction onClick(event: MouseEvent): void {\n if (disabled) {\n event.preventDefault();\n return;\n }\n\n emit('click', value);\n if (navigate && get(isSelf))\n navigate(event);\n}\n</script>\n\n<template>\n <component\n :is=\"isLink ? 'a' : 'button'\"\n :type=\"isLink ? undefined : 'button'\"\n :class=\"[\n ui.root({ class: cn(classNames?.root) }),\n isEffectivelyActive && classNames?.active,\n ]\"\n :data-active-tab=\"isEffectivelyActive || undefined\"\n :data-align=\"align\"\n :data-indicator-position=\"indicatorPosition\"\n :data-vertical=\"vertical || undefined\"\n :data-variant=\"variant\"\n :data-color=\"isEffectivelyActive ? color : undefined\"\n :disabled=\"isLink ? undefined : disabled\"\n :aria-disabled=\"isLink && disabled ? 'true' : undefined\"\n :href=\"isLink && !isSelf && !disabled ? linkHref : undefined\"\n :target=\"isLink ? target : undefined\"\n role=\"tab\"\n :aria-selected=\"isEffectivelyActive\"\n :tabindex=\"isEffectivelyActive && !disabled ? 0 : -1\"\n v-bind=\"$attrs\"\n @click=\"onClick($event)\"\n >\n <span :class=\"ui.content()\">\n <slot\n v-if=\"slots.prepend\"\n name=\"prepend\"\n />\n <slot />\n <slot\n v-if=\"slots.append\"\n name=\"append\"\n />\n </span>\n </component>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAoDA,MAAM,OAAO;EAIb,MAAM,
|
|
1
|
+
{"version":3,"file":"RuiTab.vue_vue_type_script_setup_true_lang.js","names":["$attrs","_useSlots","_openBlock","_createBlock","_resolveDynamicComponent","_unref","_mergeProps","_withCtx","_createElementVNode","_normalizeClass","_renderSlot","_createCommentVNode"],"sources":["../../../../src/components/tabs/tab/RuiTab.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport type { RouteLocationRaw } from 'vue-router';\nimport type { ContextColorsType } from '@/consts/colors';\nimport type { VueClassValue } from '@/types/class-value';\nimport { TabAlignment, TabIndicatorPosition, TabLayout, TabVariant } from '@/components/tabs/tab-props';\nimport { useTabLink } from '@/components/tabs/tab/use-tab-link';\nimport { cn, tv } from '@/utils/tv';\n\nexport interface RuiTabClassNames {\n root?: VueClassValue;\n active?: VueClassValue;\n}\n\nexport interface Props {\n color?: ContextColorsType;\n disabled?: boolean;\n grow?: boolean;\n value?: number | string;\n active?: boolean;\n classNames?: RuiTabClassNames;\n link?: boolean;\n target?: string;\n to?: RouteLocationRaw;\n exact?: boolean;\n vertical?: boolean;\n align?: TabAlignment;\n indicatorPosition?: TabIndicatorPosition;\n variant?: TabVariant;\n}\n\ndefineOptions({\n name: 'RuiTab',\n inheritAttrs: false,\n});\n\nconst {\n color,\n disabled = false,\n grow = false,\n value = useId(),\n active = false,\n classNames,\n link = false,\n to = '',\n target = '_self',\n exact = false,\n vertical = false,\n align = TabAlignment.center,\n indicatorPosition = TabIndicatorPosition.end,\n variant = TabVariant.underline,\n} = defineProps<Props>();\n\nconst emit = defineEmits<{\n click: [value: string | number];\n}>();\n\nconst slots = defineSlots<{\n default?: (props?: object) => any;\n prepend?: (props?: object) => any;\n append?: (props?: object) => any;\n}>();\n\n/**\n * A tab is a plain button or link: RuiTabs draws the active indicator, so a tab\n * only sets its label color, and its hover fill. On the underline bar the fill\n * hugs the label rather than the 40px cell, so the bar stays calm.\n */\nconst tab = tv({\n slots: {\n root: [\n 'group relative inline-flex shrink-0 items-center whitespace-nowrap rounded-rui-control',\n 'text-sm font-medium text-rui-text-secondary transition-colors duration-150 [--rui-icon-size:1rem]',\n // inset, since the scrolling bar would clip a ring drawn outside the tab\n 'outline-hidden focus-visible:focus-ring focus-visible:-outline-offset-2',\n ].join(' '),\n content: 'inline-flex items-center gap-2 rounded-rui-control transition-colors duration-150',\n },\n variants: {\n variant: {\n [TabVariant.underline]: { root: 'px-1', content: 'h-8 px-2' },\n // above the sliding pill, which RuiTabs renders behind the tabs\n [TabVariant.segmented]: { root: 'z-1 h-8 px-3' },\n },\n layout: {\n [TabLayout.horizontal]: {},\n [TabLayout.vertical]: { root: 'w-full' },\n },\n align: {\n start: { root: 'justify-start text-left rtl:justify-end rtl:text-right' },\n center: { root: 'justify-center text-center' },\n end: { root: 'justify-end text-right rtl:justify-start rtl:text-left' },\n },\n grow: {\n true: { root: 'grow' },\n },\n active: {\n true: { root: 'text-rui-text' },\n false: {},\n },\n disabled: {\n true: { root: 'cursor-not-allowed text-rui-text-disabled' },\n false: { root: 'cursor-pointer hover:text-rui-text' },\n },\n },\n compoundVariants: [\n { variant: TabVariant.underline, layout: TabLayout.horizontal, class: { root: 'h-10' } },\n { variant: TabVariant.underline, layout: TabLayout.horizontal, disabled: false, class: { content: 'group-hover:bg-rui-hover' } },\n // a vertical list fills the whole row on hover and keeps that fill on the selected row\n { variant: TabVariant.underline, layout: TabLayout.vertical, class: { root: 'min-h-9 px-3', content: 'h-auto px-0 py-2' } },\n { variant: TabVariant.underline, layout: TabLayout.vertical, disabled: false, class: { root: 'hover:bg-rui-hover' } },\n { variant: TabVariant.underline, layout: TabLayout.vertical, active: true, class: { root: 'bg-rui-hover' } },\n ],\n defaultVariants: {\n variant: TabVariant.underline,\n layout: TabLayout.horizontal,\n align: 'center',\n active: false,\n disabled: false,\n },\n});\n\nconst { isRouteActive, href: linkHref, navigate, isLink } = useTabLink({\n link: () => link,\n to: () => to,\n exact: () => exact,\n});\n\nconst layout = computed<TabLayout>(() => vertical ? TabLayout.vertical : TabLayout.horizontal);\nconst isSelf = computed<boolean>(() => target === '_self');\nconst isEffectivelyActive = computed<boolean>(() => active || get(isRouteActive));\nconst ui = computed<ReturnType<typeof tab>>(() => tab({\n variant,\n layout: get(layout),\n align,\n grow,\n disabled,\n active: get(isEffectivelyActive),\n}));\n\nfunction onClick(event: MouseEvent): void {\n if (disabled) {\n event.preventDefault();\n return;\n }\n\n emit('click', value);\n if (navigate && get(isSelf))\n navigate(event);\n}\n</script>\n\n<template>\n <component\n :is=\"isLink ? 'a' : 'button'\"\n :type=\"isLink ? undefined : 'button'\"\n :class=\"[\n ui.root({ class: cn(classNames?.root) }),\n isEffectivelyActive && classNames?.active,\n ]\"\n :data-active-tab=\"isEffectivelyActive || undefined\"\n :data-align=\"align\"\n :data-indicator-position=\"indicatorPosition\"\n :data-vertical=\"vertical || undefined\"\n :data-variant=\"variant\"\n :data-color=\"isEffectivelyActive ? color : undefined\"\n :disabled=\"isLink ? undefined : disabled\"\n :aria-disabled=\"isLink && disabled ? 'true' : undefined\"\n :href=\"isLink && !isSelf && !disabled ? linkHref : undefined\"\n :target=\"isLink ? target : undefined\"\n role=\"tab\"\n :aria-selected=\"isEffectivelyActive\"\n :tabindex=\"isEffectivelyActive && !disabled ? 0 : -1\"\n v-bind=\"$attrs\"\n @click=\"onClick($event)\"\n >\n <span :class=\"ui.content()\">\n <slot\n v-if=\"slots.prepend\"\n name=\"prepend\"\n />\n <slot />\n <slot\n v-if=\"slots.append\"\n name=\"append\"\n />\n </span>\n </component>\n</template>\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RuiTabItem.js","names":[],"sources":["../../../../src/components/tabs/tab-item/RuiTabItem.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nexport interface Props {\n active?: boolean;\n value?: number | string;\n eager?: boolean;\n}\n\ndefineOptions({\n name: 'RuiTabItem',\n});\n\nconst { active = false, value, eager = false } = defineProps<Props>();\n\ndefineSlots<{\n default?: () => any;\n}>();\n</script>\n\n<template>\n <div\n role=\"tabpanel\"\n class=\"w-full\"\n :data-value=\"value\"\n :data-active=\"active || undefined\"\n >\n <!-- the new panel fades in while the old one collapses at once, rather than Material's sideways swipe -->\n <Transition\n enter-from-class=\"opacity-0\"\n enter-active-class=\"w-full transition-opacity duration-150 ease-out motion-reduce:transition-none\"\n enter-to-class=\"opacity-100\"\n leave-active-class=\"w-full h-0! overflow-hidden\"\n >\n <div\n v-if=\"active\"\n class=\"w-full\"\n >\n <slot />\n </div>\n </Transition>\n <div\n v-if=\"eager && !active\"\n class=\"hidden\"\n >\n <slot />\n </div>\n </div>\n</template>\n"],"mappings":""}
|
|
1
|
+
{"version":3,"file":"RuiTabItem.js","names":["_sfc_main"],"sources":["../../../../src/components/tabs/tab-item/RuiTabItem.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nexport interface Props {\n active?: boolean;\n value?: number | string;\n eager?: boolean;\n}\n\ndefineOptions({\n name: 'RuiTabItem',\n});\n\nconst { active = false, value, eager = false } = defineProps<Props>();\n\ndefineSlots<{\n default?: () => any;\n}>();\n</script>\n\n<template>\n <div\n role=\"tabpanel\"\n class=\"w-full\"\n :data-value=\"value\"\n :data-active=\"active || undefined\"\n >\n <!-- the new panel fades in while the old one collapses at once, rather than Material's sideways swipe -->\n <Transition\n enter-from-class=\"opacity-0\"\n enter-active-class=\"w-full transition-opacity duration-150 ease-out motion-reduce:transition-none\"\n enter-to-class=\"opacity-100\"\n leave-active-class=\"w-full h-0! overflow-hidden\"\n >\n <div\n v-if=\"active\"\n class=\"w-full\"\n >\n <slot />\n </div>\n </Transition>\n <div\n v-if=\"eager && !active\"\n class=\"hidden\"\n >\n <slot />\n </div>\n </div>\n</template>\n"],"mappings":""}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RuiTabItem.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../../src/components/tabs/tab-item/RuiTabItem.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nexport interface Props {\n active?: boolean;\n value?: number | string;\n eager?: boolean;\n}\n\ndefineOptions({\n name: 'RuiTabItem',\n});\n\nconst { active = false, value, eager = false } = defineProps<Props>();\n\ndefineSlots<{\n default?: () => any;\n}>();\n</script>\n\n<template>\n <div\n role=\"tabpanel\"\n class=\"w-full\"\n :data-value=\"value\"\n :data-active=\"active || undefined\"\n >\n <!-- the new panel fades in while the old one collapses at once, rather than Material's sideways swipe -->\n <Transition\n enter-from-class=\"opacity-0\"\n enter-active-class=\"w-full transition-opacity duration-150 ease-out motion-reduce:transition-none\"\n enter-to-class=\"opacity-100\"\n leave-active-class=\"w-full h-0! overflow-hidden\"\n >\n <div\n v-if=\"active\"\n class=\"w-full\"\n >\n <slot />\n </div>\n </Transition>\n <div\n v-if=\"eager && !active\"\n class=\"hidden\"\n >\n <slot />\n </div>\n </div>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;GAmBE,
|
|
1
|
+
{"version":3,"file":"RuiTabItem.vue_vue_type_script_setup_true_lang.js","names":["_openBlock","_createElementBlock","_createVNode","_Transition","_withCtx","_renderSlot","_createCommentVNode"],"sources":["../../../../src/components/tabs/tab-item/RuiTabItem.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nexport interface Props {\n active?: boolean;\n value?: number | string;\n eager?: boolean;\n}\n\ndefineOptions({\n name: 'RuiTabItem',\n});\n\nconst { active = false, value, eager = false } = defineProps<Props>();\n\ndefineSlots<{\n default?: () => any;\n}>();\n</script>\n\n<template>\n <div\n role=\"tabpanel\"\n class=\"w-full\"\n :data-value=\"value\"\n :data-active=\"active || undefined\"\n >\n <!-- the new panel fades in while the old one collapses at once, rather than Material's sideways swipe -->\n <Transition\n enter-from-class=\"opacity-0\"\n enter-active-class=\"w-full transition-opacity duration-150 ease-out motion-reduce:transition-none\"\n enter-to-class=\"opacity-100\"\n leave-active-class=\"w-full h-0! overflow-hidden\"\n >\n <div\n v-if=\"active\"\n class=\"w-full\"\n >\n <slot />\n </div>\n </Transition>\n <div\n v-if=\"eager && !active\"\n class=\"hidden\"\n >\n <slot />\n </div>\n </div>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;GAmBE,OAAAA,UAAA,GAAAC,mBA0BM,OAAA;IAzBJ,MAAK;IACL,OAAM;IACL,cAAY,QAAA;IACZ,eAAa,QAAA,UAAU,KAAA;GAGxBC,GAAAA,CAAAA,YAYaC,YAAA;IAXX,oBAAiB;IACjB,sBAAmB;IACnB,kBAAe;IACf,sBAAmB;;IAEnB,SAAAC,cAKM,CAJE,QAAA,UADRJ,UAAA,GAAAC,mBAKM,OALN,YAKM,CADJI,WAAQ,KAAA,QAAA,SAAA,CAAA,CAAA,KAAA,mBAAA,IAAA,IAAA,CAAA,CAAA;;GAIJ,CAAA,GAAA,QAAA,SAAK,CAAK,QAAA,UADlBL,UAAA,GAAAC,mBAKM,OALN,YAKM,CADJI,WAAQ,KAAA,QAAA,SAAA,CAAA,CAAA,KAAA,mBAAA,IAAA,IAAA,CAAA,GAAA,GAAA,UAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RuiTabItems.js","names":[],"sources":["../../../../src/components/tabs/tab-items/RuiTabItems.vue"],"sourcesContent":["<script lang=\"ts\" setup generic=\"T extends string | number\">\nimport { Fragment, isVNode } from 'vue';\n\ndefineOptions({\n name: 'RuiTabItems',\n inheritAttrs: false,\n});\n\n/**\n * The tab whose panel is showing.\n *\n * The default matches RuiTabs. Without one, binding both components to the\n * same ref that starts as `undefined` leaves this component with\n * `modelValue === undefined`, so the `active = modelValue === value` check\n * fails for every tab: the panel renders but stays at height 0, which reads as\n * an element with no content.\n */\nconst modelValue = defineModel<T>({ default: () => 0 as T });\n\nconst slots = useSlots();\n\nconst currIndex = ref<number>(-1);\nconst activeIndex = ref<number>(-1);\nconst inner = useTemplateRef<HTMLDivElement>('inner');\n\nconst { height: innerHeight } = useElementSize(inner);\n\nconst children = computed<VNode[]>(() => {\n const slotContent = slots.default?.() ?? [];\n\n const tabs = getChildrenTabs(slotContent);\n\n let anyActive = false;\n const children = tabs.map((tab, index) => {\n const value = tab.props?.value ?? index;\n const active = get(modelValue) === value;\n if (active) {\n anyActive = true;\n if (index !== get(currIndex))\n set(currIndex, index);\n }\n\n return {\n ...tab,\n props: {\n value,\n ...tab.props,\n },\n };\n });\n\n if (!anyActive)\n set(currIndex, -1);\n\n return children;\n});\n\n/**\n * Unwraps the fragments a `v-for` in the slot produces, so only tab items come\n * back.\n *\n * @param children - the slot's vnodes\n * @returns the tab items among them\n */\nfunction getChildrenTabs(children: VNode[]): VNode[] {\n return children\n .flatMap((item) => {\n if (item.type === Fragment && Array.isArray(item.children) && item.children.length > 0)\n return getChildrenTabs(item.children.filter(isVNode));\n\n return [item];\n })\n .flat();\n}\n\nwatch(currIndex, (index) => {\n nextTick(() => {\n set(activeIndex, index);\n });\n});\n</script>\n\n<template>\n <div\n class=\"grow transition-[height] duration-200 ease-out overflow-hidden motion-reduce:transition-none\"\n :style=\"{ height: `${innerHeight}px` }\"\n v-bind=\"$attrs\"\n >\n <div ref=\"inner\">\n <Component\n :is=\"child\"\n v-for=\"(child, i) in children\"\n :key=\"i\"\n :active=\"i === activeIndex\"\n />\n </div>\n </div>\n</template>\n"],"mappings":""}
|
|
1
|
+
{"version":3,"file":"RuiTabItems.js","names":["_sfc_main"],"sources":["../../../../src/components/tabs/tab-items/RuiTabItems.vue"],"sourcesContent":["<script lang=\"ts\" setup generic=\"T extends string | number\">\nimport { Fragment, isVNode } from 'vue';\n\ndefineOptions({\n name: 'RuiTabItems',\n inheritAttrs: false,\n});\n\n/**\n * The tab whose panel is showing.\n *\n * The default matches RuiTabs. Without one, binding both components to the\n * same ref that starts as `undefined` leaves this component with\n * `modelValue === undefined`, so the `active = modelValue === value` check\n * fails for every tab: the panel renders but stays at height 0, which reads as\n * an element with no content.\n */\nconst modelValue = defineModel<T>({ default: () => 0 as T });\n\nconst slots = useSlots();\n\nconst currIndex = ref<number>(-1);\nconst activeIndex = ref<number>(-1);\nconst inner = useTemplateRef<HTMLDivElement>('inner');\n\nconst { height: innerHeight } = useElementSize(inner);\n\nconst children = computed<VNode[]>(() => {\n const slotContent = slots.default?.() ?? [];\n\n const tabs = getChildrenTabs(slotContent);\n\n let anyActive = false;\n const children = tabs.map((tab, index) => {\n const value = tab.props?.value ?? index;\n const active = get(modelValue) === value;\n if (active) {\n anyActive = true;\n if (index !== get(currIndex))\n set(currIndex, index);\n }\n\n return {\n ...tab,\n props: {\n value,\n ...tab.props,\n },\n };\n });\n\n if (!anyActive)\n set(currIndex, -1);\n\n return children;\n});\n\n/**\n * Unwraps the fragments a `v-for` in the slot produces, so only tab items come\n * back.\n *\n * @param children - the slot's vnodes\n * @returns the tab items among them\n */\nfunction getChildrenTabs(children: VNode[]): VNode[] {\n return children\n .flatMap((item) => {\n if (item.type === Fragment && Array.isArray(item.children) && item.children.length > 0)\n return getChildrenTabs(item.children.filter(isVNode));\n\n return [item];\n })\n .flat();\n}\n\nwatch(currIndex, (index) => {\n nextTick(() => {\n set(activeIndex, index);\n });\n});\n</script>\n\n<template>\n <div\n class=\"grow transition-[height] duration-200 ease-out overflow-hidden motion-reduce:transition-none\"\n :style=\"{ height: `${innerHeight}px` }\"\n v-bind=\"$attrs\"\n >\n <div ref=\"inner\">\n <Component\n :is=\"child\"\n v-for=\"(child, i) in children\"\n :key=\"i\"\n :active=\"i === activeIndex\"\n />\n </div>\n </div>\n</template>\n"],"mappings":""}
|
package/dist/components/tabs/tab-items/RuiTabItems.vue_vue_type_script_setup_true_lang.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RuiTabItems.vue_vue_type_script_setup_true_lang.js","names":["$attrs"],"sources":["../../../../src/components/tabs/tab-items/RuiTabItems.vue"],"sourcesContent":["<script lang=\"ts\" setup generic=\"T extends string | number\">\nimport { Fragment, isVNode } from 'vue';\n\ndefineOptions({\n name: 'RuiTabItems',\n inheritAttrs: false,\n});\n\n/**\n * The tab whose panel is showing.\n *\n * The default matches RuiTabs. Without one, binding both components to the\n * same ref that starts as `undefined` leaves this component with\n * `modelValue === undefined`, so the `active = modelValue === value` check\n * fails for every tab: the panel renders but stays at height 0, which reads as\n * an element with no content.\n */\nconst modelValue = defineModel<T>({ default: () => 0 as T });\n\nconst slots = useSlots();\n\nconst currIndex = ref<number>(-1);\nconst activeIndex = ref<number>(-1);\nconst inner = useTemplateRef<HTMLDivElement>('inner');\n\nconst { height: innerHeight } = useElementSize(inner);\n\nconst children = computed<VNode[]>(() => {\n const slotContent = slots.default?.() ?? [];\n\n const tabs = getChildrenTabs(slotContent);\n\n let anyActive = false;\n const children = tabs.map((tab, index) => {\n const value = tab.props?.value ?? index;\n const active = get(modelValue) === value;\n if (active) {\n anyActive = true;\n if (index !== get(currIndex))\n set(currIndex, index);\n }\n\n return {\n ...tab,\n props: {\n value,\n ...tab.props,\n },\n };\n });\n\n if (!anyActive)\n set(currIndex, -1);\n\n return children;\n});\n\n/**\n * Unwraps the fragments a `v-for` in the slot produces, so only tab items come\n * back.\n *\n * @param children - the slot's vnodes\n * @returns the tab items among them\n */\nfunction getChildrenTabs(children: VNode[]): VNode[] {\n return children\n .flatMap((item) => {\n if (item.type === Fragment && Array.isArray(item.children) && item.children.length > 0)\n return getChildrenTabs(item.children.filter(isVNode));\n\n return [item];\n })\n .flat();\n}\n\nwatch(currIndex, (index) => {\n nextTick(() => {\n set(activeIndex, index);\n });\n});\n</script>\n\n<template>\n <div\n class=\"grow transition-[height] duration-200 ease-out overflow-hidden motion-reduce:transition-none\"\n :style=\"{ height: `${innerHeight}px` }\"\n v-bind=\"$attrs\"\n >\n <div ref=\"inner\">\n <Component\n :is=\"child\"\n v-for=\"(child, i) in children\"\n :key=\"i\"\n :active=\"i === activeIndex\"\n />\n </div>\n </div>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;EAiBA,MAAM,
|
|
1
|
+
{"version":3,"file":"RuiTabItems.vue_vue_type_script_setup_true_lang.js","names":["$attrs","_useModel","_openBlock","_createElementBlock","_mergeProps","_unref","_createElementVNode","_Fragment","_renderList","_createBlock","_resolveDynamicComponent"],"sources":["../../../../src/components/tabs/tab-items/RuiTabItems.vue"],"sourcesContent":["<script lang=\"ts\" setup generic=\"T extends string | number\">\nimport { Fragment, isVNode } from 'vue';\n\ndefineOptions({\n name: 'RuiTabItems',\n inheritAttrs: false,\n});\n\n/**\n * The tab whose panel is showing.\n *\n * The default matches RuiTabs. Without one, binding both components to the\n * same ref that starts as `undefined` leaves this component with\n * `modelValue === undefined`, so the `active = modelValue === value` check\n * fails for every tab: the panel renders but stays at height 0, which reads as\n * an element with no content.\n */\nconst modelValue = defineModel<T>({ default: () => 0 as T });\n\nconst slots = useSlots();\n\nconst currIndex = ref<number>(-1);\nconst activeIndex = ref<number>(-1);\nconst inner = useTemplateRef<HTMLDivElement>('inner');\n\nconst { height: innerHeight } = useElementSize(inner);\n\nconst children = computed<VNode[]>(() => {\n const slotContent = slots.default?.() ?? [];\n\n const tabs = getChildrenTabs(slotContent);\n\n let anyActive = false;\n const children = tabs.map((tab, index) => {\n const value = tab.props?.value ?? index;\n const active = get(modelValue) === value;\n if (active) {\n anyActive = true;\n if (index !== get(currIndex))\n set(currIndex, index);\n }\n\n return {\n ...tab,\n props: {\n value,\n ...tab.props,\n },\n };\n });\n\n if (!anyActive)\n set(currIndex, -1);\n\n return children;\n});\n\n/**\n * Unwraps the fragments a `v-for` in the slot produces, so only tab items come\n * back.\n *\n * @param children - the slot's vnodes\n * @returns the tab items among them\n */\nfunction getChildrenTabs(children: VNode[]): VNode[] {\n return children\n .flatMap((item) => {\n if (item.type === Fragment && Array.isArray(item.children) && item.children.length > 0)\n return getChildrenTabs(item.children.filter(isVNode));\n\n return [item];\n })\n .flat();\n}\n\nwatch(currIndex, (index) => {\n nextTick(() => {\n set(activeIndex, index);\n });\n});\n</script>\n\n<template>\n <div\n class=\"grow transition-[height] duration-200 ease-out overflow-hidden motion-reduce:transition-none\"\n :style=\"{ height: `${innerHeight}px` }\"\n v-bind=\"$attrs\"\n >\n <div ref=\"inner\">\n <Component\n :is=\"child\"\n v-for=\"(child, i) in children\"\n :key=\"i\"\n :active=\"i === activeIndex\"\n />\n </div>\n </div>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;EAiBA,MAAM,aAAaC,SAAc,SAAA,YAA0B;EAE3D,MAAM,QAAQ,SAAS;EAEvB,MAAM,YAAY,IAAY,EAAE;EAChC,MAAM,cAAc,IAAY,EAAE;EAClC,MAAM,QAAQ,eAA+B,OAAO;EAEpD,MAAM,EAAE,QAAQ,gBAAgB,eAAe,KAAK;EAEpD,MAAM,WAAW,eAAwB;GAGvC,MAAM,OAAO,gBAFO,MAAM,UAAU,KAAK,CAAC,CAEF;GAExC,IAAI,YAAY;GAChB,MAAM,WAAW,KAAK,KAAK,KAAK,UAAU;IACxC,MAAM,QAAQ,IAAI,OAAO,SAAS;IAElC,IADe,IAAI,UAAU,MAAM,OACvB;KACV,YAAY;KACZ,IAAI,UAAU,IAAI,SAAS,GACzB,IAAI,WAAW,KAAK;IACxB;IAEA,OAAO;KACL,GAAG;KACH,OAAO;MACL;MACA,GAAG,IAAI;KACT;IACF;GACF,CAAC;GAED,IAAI,CAAC,WACH,IAAI,WAAW,EAAE;GAEnB,OAAO;EACT,CAAC;;;;;;;;EASD,SAAS,gBAAgB,UAA4B;GACnD,OAAO,SACJ,SAAS,SAAS;IACjB,IAAI,KAAK,SAAS,YAAY,MAAM,QAAQ,KAAK,QAAQ,KAAK,KAAK,SAAS,SAAS,GACnF,OAAO,gBAAgB,KAAK,SAAS,OAAO,OAAO,CAAC;IAEtD,OAAO,CAAC,IAAI;GACd,CAAC,CAAA,CACA,KAAK;EACV;EAEA,MAAM,YAAY,UAAU;GAC1B,eAAe;IACb,IAAI,aAAa,KAAK;GACxB,CAAC;EACH,CAAC;;GAIC,OAAAC,UAAA,GAAAC,mBAaM,OAbNC,WAaM;IAZJ,OAAM;IACL,OAAK,EAAA,QAAA,GAAeC,MAAA,WAAA,EAAW,IAAA;GACxBL,GAAAA,KAAAA,MAAM,GAAA,CAEdM,mBAOM,OAAA;IAPG,SAAA;IAAJ,KAAI;GACPJ,GAAAA,EAAAA,UAAA,IAAA,GAAAC,mBAKEI,UAAA,MAAAC,WAHqBH,MAAA,QAAA,IAAb,OAAO,MAAC;IAFlB,OAAAH,UAAA,GAAAO,YAKEC,wBAJK,KAAK,GAAA;KAET,KAAK;KACL,QAAQ,MAAML,MAAA,WAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RuiTabs.js","names":[],"sources":["../../../../src/components/tabs/tabs/RuiTabs.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport type { ContextColorsType } from '@/consts/colors';\nimport { Fragment, isVNode, type VNode } from 'vue';\nimport RuiButton from '@/components/buttons/button/RuiButton.vue';\nimport RuiIcon from '@/components/icons/RuiIcon.vue';\nimport { type TabAlignment, type TabIndicatorPosition, TabLayout, TabVariant } from '@/components/tabs/tab-props';\nimport { useTabIndicator } from '@/components/tabs/tabs/use-tab-indicator';\nimport { useTabKeyboard } from '@/components/tabs/tabs/use-tab-keyboard';\nimport { useTabRouting } from '@/components/tabs/tabs/use-tab-routing';\nimport { useTabScroll } from '@/components/tabs/tabs/use-tab-scroll';\nimport { useKeyboardScroll } from '@/composables/keyboard-scroll';\nimport { tv } from '@/utils/tv';\n\ntype ChildNode = VNode & { props: Record<string, any> };\n\ninterface ResolvedTabProps {\n value?: string | number;\n to?: unknown;\n link?: boolean;\n exact?: boolean;\n}\n\nexport interface Props {\n color?: ContextColorsType;\n vertical?: boolean;\n disabled?: boolean;\n grow?: boolean;\n align?: TabAlignment;\n indicatorPosition?: TabIndicatorPosition;\n variant?: TabVariant;\n}\n\ndefineOptions({\n name: 'RuiTabs',\n});\n\n/**\n * The selected tab, defaulting to the first one. The default also narrows the\n * `update:modelValue` payload to `number | string`, so a consumer's handler\n * needs no undefined in its signature.\n */\nconst modelValue = defineModel<number | string>({ default: 0 });\n\nconst {\n color,\n vertical = false,\n disabled = false,\n grow = false,\n align = 'center',\n indicatorPosition = 'end',\n variant = TabVariant.underline,\n} = defineProps<Props>();\n\nconst internalModelValue = ref<string | number>();\nconst bar = useTemplateRef<HTMLDivElement>('bar');\nconst wrapper = useTemplateRef<HTMLDivElement>('wrapper');\nconst barTabindex = useKeyboardScroll(bar);\n\n/**\n * The bar. The underline variant draws its 1px track as a `before` line along\n * the whole root, so the arrows sit on it too, and the 2px indicator, a layer\n * above, covers it under the active tab.\n */\nconst tabs = tv({\n slots: {\n root: '',\n arrow: 'flex shrink-0 items-center justify-center',\n // a tab stop only when it scrolls with every tab disabled (useKeyboardScroll)\n bar: 'no-scrollbar relative max-h-full overflow-auto outline-hidden focus-visible:focus-ring focus-visible:-outline-offset-2',\n wrapper: 'inline-flex max-w-none',\n indicator: 'pointer-events-none absolute',\n },\n variants: {\n variant: {\n [TabVariant.underline]: {\n root: `relative before:pointer-events-none before:absolute before:bg-rui-divider before:content-['']`,\n indicator: 'z-1 bg-rui-primary',\n },\n [TabVariant.segmented]: {\n // neutral-200, not 100: on a near-white page (`#fafafa`) the lighter track all but disappeared\n root: 'rounded-rui-panel bg-rui-neutral-200 p-0.5 dark:bg-rui-neutral-800',\n wrapper: 'gap-0.5',\n indicator: 'rounded-rui-control bg-rui-surface shadow-rui-control dark:bg-rui-neutral-700',\n },\n },\n layout: {\n [TabLayout.horizontal]: { root: 'flex h-fit', arrow: 'w-8' },\n [TabLayout.vertical]: { root: 'inline-flex flex-col', arrow: 'h-8 w-full', wrapper: 'flex-col w-full' },\n },\n indicatorPosition: {\n start: {},\n end: {},\n },\n color: {\n primary: {},\n secondary: {},\n error: {},\n warning: {},\n info: {},\n success: {},\n },\n wide: {\n true: { bar: 'w-full', wrapper: 'min-w-full' },\n false: {},\n },\n animated: {\n true: { indicator: 'transition-[left,top,width,height] duration-200 ease-out motion-reduce:transition-none' },\n false: {},\n },\n },\n compoundVariants: [\n { variant: TabVariant.underline, layout: TabLayout.horizontal, indicatorPosition: 'end', class: { root: 'before:inset-x-0 before:bottom-0 before:h-px', indicator: 'bottom-0 h-0.5 rounded-t-full' } },\n { variant: TabVariant.underline, layout: TabLayout.horizontal, indicatorPosition: 'start', class: { root: 'before:inset-x-0 before:top-0 before:h-px', indicator: 'top-0 h-0.5 rounded-b-full' } },\n { variant: TabVariant.underline, layout: TabLayout.vertical, indicatorPosition: 'end', class: { root: 'before:inset-y-0 before:right-0 before:w-px', indicator: 'right-0 w-0.5 rounded-l-full' } },\n { variant: TabVariant.underline, layout: TabLayout.vertical, indicatorPosition: 'start', class: { root: 'before:inset-y-0 before:left-0 before:w-px', indicator: 'left-0 w-0.5 rounded-r-full' } },\n // the underline track spans its row, while a segmented control hugs its options unless it grows\n { variant: TabVariant.segmented, layout: TabLayout.horizontal, wide: false, class: { root: 'w-fit max-w-full' } },\n // `color` picks the underline's color; the segmented pill stays a neutral surface\n { variant: TabVariant.underline, color: 'secondary', class: { indicator: 'bg-rui-secondary' } },\n { variant: TabVariant.underline, color: 'error', class: { indicator: 'bg-rui-error' } },\n { variant: TabVariant.underline, color: 'warning', class: { indicator: 'bg-rui-warning' } },\n { variant: TabVariant.underline, color: 'info', class: { indicator: 'bg-rui-info' } },\n { variant: TabVariant.underline, color: 'success', class: { indicator: 'bg-rui-success' } },\n ],\n defaultVariants: { variant: TabVariant.underline, layout: TabLayout.horizontal, indicatorPosition: 'end' },\n});\n\nconst slots = useSlots();\n\nconst {\n showArrows,\n prevArrowDisabled,\n nextArrowDisabled,\n onPrevSliderClick,\n onNextSliderClick,\n keepActiveTabVisible,\n} = useTabScroll({ bar, wrapper, vertical: () => vertical });\n\nconst { resolveRoute, isPathMatch } = useTabRouting({\n onRouteChange: () => applyNewValue(true),\n});\n\nconst { onKeydown } = useTabKeyboard({ wrapper, vertical: () => vertical });\n\nconst { style: indicatorStyle, animated, update: updateIndicator } = useTabIndicator({\n bar,\n wrapper,\n vertical: () => vertical,\n variant: () => variant,\n});\n\nconst layout = computed<TabLayout>(() => vertical ? TabLayout.vertical : TabLayout.horizontal);\nconst ui = computed<ReturnType<typeof tabs>>(() => tabs({\n variant,\n layout: get(layout),\n indicatorPosition,\n color,\n wide: vertical || grow,\n animated: get(animated),\n}));\n\nconst children = computed<ChildNode[]>(() => {\n const slotContent = slots.default?.() ?? [];\n\n const tabs = getChildrenTabs(slotContent);\n\n const currentModelValue = get(internalModelValue);\n const inheritedProps = {\n color,\n grow,\n disabled,\n vertical,\n align,\n indicatorPosition,\n variant,\n };\n\n return tabs.map((tab, index) => {\n let tabValue = tab.props?.value ?? index;\n if (tab.props?.link !== false && tab.props?.to)\n tabValue = tab.props.to;\n\n const active = currentModelValue === tabValue;\n return {\n ...tab,\n props: {\n value: tabValue,\n active,\n ...inheritedProps,\n ...tab.props,\n },\n };\n });\n});\n\n/**\n * Unwraps the fragments a `v-for` in the slot produces, so only tabs come\n * back.\n *\n * @param children - the slot's vnodes\n * @returns the tabs among them\n */\nfunction getChildrenTabs(children: VNode[]): VNode[] {\n return children.flatMap((item) => {\n if (item.type === Fragment && Array.isArray(item.children) && item.children.length > 0)\n return getChildrenTabs(item.children.filter(isVNode));\n\n return [item];\n }).flat();\n}\n\nfunction updateModelValue(newModelValue: string | number): void {\n set(modelValue, newModelValue);\n set(internalModelValue, newModelValue);\n}\n\nfunction getTabRouteProps(props: Record<string, unknown>): ResolvedTabProps {\n return {\n value: typeof props.value === 'string' || typeof props.value === 'number' ? props.value : undefined,\n to: props.to ?? undefined,\n link: typeof props.link === 'boolean' ? props.link : undefined,\n exact: typeof props.exact === 'boolean' ? props.exact : undefined,\n };\n}\n\nfunction resolveActiveValue(onlyLink: boolean): string | number | undefined {\n const enabledChildren = get(children).filter(child => !child.props?.disabled);\n if (enabledChildren.length === 0)\n return undefined;\n\n let result: string | number = get(modelValue) || 0;\n enabledChildren.forEach((child, index) => {\n const tabProps = getTabRouteProps(child.props);\n if (!onlyLink && index === 0 && tabProps.value)\n result = tabProps.value;\n\n const fullPath = resolveRoute(tabProps.to);\n\n if (tabProps.link !== false && fullPath && isPathMatch(fullPath, tabProps))\n result = fullPath;\n });\n return result;\n}\n\nfunction applyNewValue(onlyLink = false): void {\n const value = resolveActiveValue(onlyLink);\n if (value !== undefined)\n updateModelValue(value);\n\n keepActiveTabVisible();\n}\n\nwatchImmediate(() => get(modelValue), (modelValue) => {\n set(internalModelValue, modelValue);\n});\n\nwatch(internalModelValue, () => {\n keepActiveTabVisible();\n});\n\nwatch(() => [vertical, variant, grow, align], () => nextTick(updateIndicator), { flush: 'post' });\n\nonMounted(() => {\n if (get(modelValue) !== undefined)\n return;\n\n applyNewValue();\n});\n</script>\n\n<template>\n <div\n :class=\"ui.root()\"\n :data-vertical=\"vertical || undefined\"\n >\n <div\n v-if=\"showArrows\"\n :class=\"ui.arrow()\"\n >\n <RuiButton\n variant=\"text\"\n icon\n size=\"sm\"\n tabindex=\"-1\"\n aria-label=\"Scroll tabs back\"\n :disabled=\"prevArrowDisabled\"\n @click=\"onPrevSliderClick()\"\n >\n <RuiIcon :name=\"vertical ? 'lu-chevron-up' : 'lu-chevron-left'\" />\n </RuiButton>\n </div>\n <div\n ref=\"bar\"\n :class=\"ui.bar()\"\n :tabindex=\"barTabindex\"\n >\n <span\n v-if=\"indicatorStyle\"\n aria-hidden=\"true\"\n data-id=\"tabs-indicator\"\n :class=\"ui.indicator()\"\n :style=\"indicatorStyle\"\n />\n <div\n ref=\"wrapper\"\n role=\"tablist\"\n data-id=\"tabs-wrapper\"\n :aria-orientation=\"vertical ? 'vertical' : undefined\"\n :class=\"ui.wrapper()\"\n @keydown=\"onKeydown($event)\"\n >\n <Component\n :is=\"child\"\n v-for=\"(child, i) in children\"\n :key=\"i\"\n @click=\"updateModelValue($event)\"\n />\n </div>\n </div>\n <div\n v-if=\"showArrows\"\n :class=\"ui.arrow()\"\n >\n <RuiButton\n variant=\"text\"\n icon\n size=\"sm\"\n tabindex=\"-1\"\n aria-label=\"Scroll tabs forward\"\n :disabled=\"nextArrowDisabled\"\n @click=\"onNextSliderClick()\"\n >\n <RuiIcon :name=\"vertical ? 'lu-chevron-down' : 'lu-chevron-right'\" />\n </RuiButton>\n </div>\n </div>\n</template>\n"],"mappings":""}
|
|
1
|
+
{"version":3,"file":"RuiTabs.js","names":["_sfc_main"],"sources":["../../../../src/components/tabs/tabs/RuiTabs.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport type { ContextColorsType } from '@/consts/colors';\nimport { Fragment, isVNode, type VNode } from 'vue';\nimport RuiButton from '@/components/buttons/button/RuiButton.vue';\nimport RuiIcon from '@/components/icons/RuiIcon.vue';\nimport { type TabAlignment, type TabIndicatorPosition, TabLayout, TabVariant } from '@/components/tabs/tab-props';\nimport { useTabIndicator } from '@/components/tabs/tabs/use-tab-indicator';\nimport { useTabKeyboard } from '@/components/tabs/tabs/use-tab-keyboard';\nimport { useTabRouting } from '@/components/tabs/tabs/use-tab-routing';\nimport { useTabScroll } from '@/components/tabs/tabs/use-tab-scroll';\nimport { useKeyboardScroll } from '@/composables/keyboard-scroll';\nimport { tv } from '@/utils/tv';\n\ntype ChildNode = VNode & { props: Record<string, any> };\n\ninterface ResolvedTabProps {\n value?: string | number;\n to?: unknown;\n link?: boolean;\n exact?: boolean;\n}\n\nexport interface Props {\n color?: ContextColorsType;\n vertical?: boolean;\n disabled?: boolean;\n grow?: boolean;\n align?: TabAlignment;\n indicatorPosition?: TabIndicatorPosition;\n variant?: TabVariant;\n}\n\ndefineOptions({\n name: 'RuiTabs',\n});\n\n/**\n * The selected tab, defaulting to the first one. The default also narrows the\n * `update:modelValue` payload to `number | string`, so a consumer's handler\n * needs no undefined in its signature.\n */\nconst modelValue = defineModel<number | string>({ default: 0 });\n\nconst {\n color,\n vertical = false,\n disabled = false,\n grow = false,\n align = 'center',\n indicatorPosition = 'end',\n variant = TabVariant.underline,\n} = defineProps<Props>();\n\nconst internalModelValue = ref<string | number>();\nconst bar = useTemplateRef<HTMLDivElement>('bar');\nconst wrapper = useTemplateRef<HTMLDivElement>('wrapper');\nconst barTabindex = useKeyboardScroll(bar);\n\n/**\n * The bar. The underline variant draws its 1px track as a `before` line along\n * the whole root, so the arrows sit on it too, and the 2px indicator, a layer\n * above, covers it under the active tab.\n */\nconst tabs = tv({\n slots: {\n root: '',\n arrow: 'flex shrink-0 items-center justify-center',\n // a tab stop only when it scrolls with every tab disabled (useKeyboardScroll)\n bar: 'no-scrollbar relative max-h-full overflow-auto outline-hidden focus-visible:focus-ring focus-visible:-outline-offset-2',\n wrapper: 'inline-flex max-w-none',\n indicator: 'pointer-events-none absolute',\n },\n variants: {\n variant: {\n [TabVariant.underline]: {\n root: `relative before:pointer-events-none before:absolute before:bg-rui-divider before:content-['']`,\n indicator: 'z-1 bg-rui-primary',\n },\n [TabVariant.segmented]: {\n // neutral-200, not 100: on a near-white page (`#fafafa`) the lighter track all but disappeared\n root: 'rounded-rui-panel bg-rui-neutral-200 p-0.5 dark:bg-rui-neutral-800',\n wrapper: 'gap-0.5',\n indicator: 'rounded-rui-control bg-rui-surface shadow-rui-control dark:bg-rui-neutral-700',\n },\n },\n layout: {\n [TabLayout.horizontal]: { root: 'flex h-fit', arrow: 'w-8' },\n [TabLayout.vertical]: { root: 'inline-flex flex-col', arrow: 'h-8 w-full', wrapper: 'flex-col w-full' },\n },\n indicatorPosition: {\n start: {},\n end: {},\n },\n color: {\n primary: {},\n secondary: {},\n error: {},\n warning: {},\n info: {},\n success: {},\n },\n wide: {\n true: { bar: 'w-full', wrapper: 'min-w-full' },\n false: {},\n },\n animated: {\n true: { indicator: 'transition-[left,top,width,height] duration-200 ease-out motion-reduce:transition-none' },\n false: {},\n },\n },\n compoundVariants: [\n { variant: TabVariant.underline, layout: TabLayout.horizontal, indicatorPosition: 'end', class: { root: 'before:inset-x-0 before:bottom-0 before:h-px', indicator: 'bottom-0 h-0.5 rounded-t-full' } },\n { variant: TabVariant.underline, layout: TabLayout.horizontal, indicatorPosition: 'start', class: { root: 'before:inset-x-0 before:top-0 before:h-px', indicator: 'top-0 h-0.5 rounded-b-full' } },\n { variant: TabVariant.underline, layout: TabLayout.vertical, indicatorPosition: 'end', class: { root: 'before:inset-y-0 before:right-0 before:w-px', indicator: 'right-0 w-0.5 rounded-l-full' } },\n { variant: TabVariant.underline, layout: TabLayout.vertical, indicatorPosition: 'start', class: { root: 'before:inset-y-0 before:left-0 before:w-px', indicator: 'left-0 w-0.5 rounded-r-full' } },\n // the underline track spans its row, while a segmented control hugs its options unless it grows\n { variant: TabVariant.segmented, layout: TabLayout.horizontal, wide: false, class: { root: 'w-fit max-w-full' } },\n // `color` picks the underline's color; the segmented pill stays a neutral surface\n { variant: TabVariant.underline, color: 'secondary', class: { indicator: 'bg-rui-secondary' } },\n { variant: TabVariant.underline, color: 'error', class: { indicator: 'bg-rui-error' } },\n { variant: TabVariant.underline, color: 'warning', class: { indicator: 'bg-rui-warning' } },\n { variant: TabVariant.underline, color: 'info', class: { indicator: 'bg-rui-info' } },\n { variant: TabVariant.underline, color: 'success', class: { indicator: 'bg-rui-success' } },\n ],\n defaultVariants: { variant: TabVariant.underline, layout: TabLayout.horizontal, indicatorPosition: 'end' },\n});\n\nconst slots = useSlots();\n\nconst {\n showArrows,\n prevArrowDisabled,\n nextArrowDisabled,\n onPrevSliderClick,\n onNextSliderClick,\n keepActiveTabVisible,\n} = useTabScroll({ bar, wrapper, vertical: () => vertical });\n\nconst { resolveRoute, isPathMatch } = useTabRouting({\n onRouteChange: () => applyNewValue(true),\n});\n\nconst { onKeydown } = useTabKeyboard({ wrapper, vertical: () => vertical });\n\nconst { style: indicatorStyle, animated, update: updateIndicator } = useTabIndicator({\n bar,\n wrapper,\n vertical: () => vertical,\n variant: () => variant,\n});\n\nconst layout = computed<TabLayout>(() => vertical ? TabLayout.vertical : TabLayout.horizontal);\nconst ui = computed<ReturnType<typeof tabs>>(() => tabs({\n variant,\n layout: get(layout),\n indicatorPosition,\n color,\n wide: vertical || grow,\n animated: get(animated),\n}));\n\nconst children = computed<ChildNode[]>(() => {\n const slotContent = slots.default?.() ?? [];\n\n const tabs = getChildrenTabs(slotContent);\n\n const currentModelValue = get(internalModelValue);\n const inheritedProps = {\n color,\n grow,\n disabled,\n vertical,\n align,\n indicatorPosition,\n variant,\n };\n\n return tabs.map((tab, index) => {\n let tabValue = tab.props?.value ?? index;\n if (tab.props?.link !== false && tab.props?.to)\n tabValue = tab.props.to;\n\n const active = currentModelValue === tabValue;\n return {\n ...tab,\n props: {\n value: tabValue,\n active,\n ...inheritedProps,\n ...tab.props,\n },\n };\n });\n});\n\n/**\n * Unwraps the fragments a `v-for` in the slot produces, so only tabs come\n * back.\n *\n * @param children - the slot's vnodes\n * @returns the tabs among them\n */\nfunction getChildrenTabs(children: VNode[]): VNode[] {\n return children.flatMap((item) => {\n if (item.type === Fragment && Array.isArray(item.children) && item.children.length > 0)\n return getChildrenTabs(item.children.filter(isVNode));\n\n return [item];\n }).flat();\n}\n\nfunction updateModelValue(newModelValue: string | number): void {\n set(modelValue, newModelValue);\n set(internalModelValue, newModelValue);\n}\n\nfunction getTabRouteProps(props: Record<string, unknown>): ResolvedTabProps {\n return {\n value: typeof props.value === 'string' || typeof props.value === 'number' ? props.value : undefined,\n to: props.to ?? undefined,\n link: typeof props.link === 'boolean' ? props.link : undefined,\n exact: typeof props.exact === 'boolean' ? props.exact : undefined,\n };\n}\n\nfunction resolveActiveValue(onlyLink: boolean): string | number | undefined {\n const enabledChildren = get(children).filter(child => !child.props?.disabled);\n if (enabledChildren.length === 0)\n return undefined;\n\n let result: string | number = get(modelValue) || 0;\n enabledChildren.forEach((child, index) => {\n const tabProps = getTabRouteProps(child.props);\n if (!onlyLink && index === 0 && tabProps.value)\n result = tabProps.value;\n\n const fullPath = resolveRoute(tabProps.to);\n\n if (tabProps.link !== false && fullPath && isPathMatch(fullPath, tabProps))\n result = fullPath;\n });\n return result;\n}\n\nfunction applyNewValue(onlyLink = false): void {\n const value = resolveActiveValue(onlyLink);\n if (value !== undefined)\n updateModelValue(value);\n\n keepActiveTabVisible();\n}\n\nwatchImmediate(() => get(modelValue), (modelValue) => {\n set(internalModelValue, modelValue);\n});\n\nwatch(internalModelValue, () => {\n keepActiveTabVisible();\n});\n\nwatch(() => [vertical, variant, grow, align], () => nextTick(updateIndicator), { flush: 'post' });\n\nonMounted(() => {\n if (get(modelValue) !== undefined)\n return;\n\n applyNewValue();\n});\n</script>\n\n<template>\n <div\n :class=\"ui.root()\"\n :data-vertical=\"vertical || undefined\"\n >\n <div\n v-if=\"showArrows\"\n :class=\"ui.arrow()\"\n >\n <RuiButton\n variant=\"text\"\n icon\n size=\"sm\"\n tabindex=\"-1\"\n aria-label=\"Scroll tabs back\"\n :disabled=\"prevArrowDisabled\"\n @click=\"onPrevSliderClick()\"\n >\n <RuiIcon :name=\"vertical ? 'lu-chevron-up' : 'lu-chevron-left'\" />\n </RuiButton>\n </div>\n <div\n ref=\"bar\"\n :class=\"ui.bar()\"\n :tabindex=\"barTabindex\"\n >\n <span\n v-if=\"indicatorStyle\"\n aria-hidden=\"true\"\n data-id=\"tabs-indicator\"\n :class=\"ui.indicator()\"\n :style=\"indicatorStyle\"\n />\n <div\n ref=\"wrapper\"\n role=\"tablist\"\n data-id=\"tabs-wrapper\"\n :aria-orientation=\"vertical ? 'vertical' : undefined\"\n :class=\"ui.wrapper()\"\n @keydown=\"onKeydown($event)\"\n >\n <Component\n :is=\"child\"\n v-for=\"(child, i) in children\"\n :key=\"i\"\n @click=\"updateModelValue($event)\"\n />\n </div>\n </div>\n <div\n v-if=\"showArrows\"\n :class=\"ui.arrow()\"\n >\n <RuiButton\n variant=\"text\"\n icon\n size=\"sm\"\n tabindex=\"-1\"\n aria-label=\"Scroll tabs forward\"\n :disabled=\"nextArrowDisabled\"\n @click=\"onNextSliderClick()\"\n >\n <RuiIcon :name=\"vertical ? 'lu-chevron-down' : 'lu-chevron-right'\" />\n </RuiButton>\n </div>\n </div>\n</template>\n"],"mappings":""}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RuiTabs.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../../src/components/tabs/tabs/RuiTabs.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport type { ContextColorsType } from '@/consts/colors';\nimport { Fragment, isVNode, type VNode } from 'vue';\nimport RuiButton from '@/components/buttons/button/RuiButton.vue';\nimport RuiIcon from '@/components/icons/RuiIcon.vue';\nimport { type TabAlignment, type TabIndicatorPosition, TabLayout, TabVariant } from '@/components/tabs/tab-props';\nimport { useTabIndicator } from '@/components/tabs/tabs/use-tab-indicator';\nimport { useTabKeyboard } from '@/components/tabs/tabs/use-tab-keyboard';\nimport { useTabRouting } from '@/components/tabs/tabs/use-tab-routing';\nimport { useTabScroll } from '@/components/tabs/tabs/use-tab-scroll';\nimport { useKeyboardScroll } from '@/composables/keyboard-scroll';\nimport { tv } from '@/utils/tv';\n\ntype ChildNode = VNode & { props: Record<string, any> };\n\ninterface ResolvedTabProps {\n value?: string | number;\n to?: unknown;\n link?: boolean;\n exact?: boolean;\n}\n\nexport interface Props {\n color?: ContextColorsType;\n vertical?: boolean;\n disabled?: boolean;\n grow?: boolean;\n align?: TabAlignment;\n indicatorPosition?: TabIndicatorPosition;\n variant?: TabVariant;\n}\n\ndefineOptions({\n name: 'RuiTabs',\n});\n\n/**\n * The selected tab, defaulting to the first one. The default also narrows the\n * `update:modelValue` payload to `number | string`, so a consumer's handler\n * needs no undefined in its signature.\n */\nconst modelValue = defineModel<number | string>({ default: 0 });\n\nconst {\n color,\n vertical = false,\n disabled = false,\n grow = false,\n align = 'center',\n indicatorPosition = 'end',\n variant = TabVariant.underline,\n} = defineProps<Props>();\n\nconst internalModelValue = ref<string | number>();\nconst bar = useTemplateRef<HTMLDivElement>('bar');\nconst wrapper = useTemplateRef<HTMLDivElement>('wrapper');\nconst barTabindex = useKeyboardScroll(bar);\n\n/**\n * The bar. The underline variant draws its 1px track as a `before` line along\n * the whole root, so the arrows sit on it too, and the 2px indicator, a layer\n * above, covers it under the active tab.\n */\nconst tabs = tv({\n slots: {\n root: '',\n arrow: 'flex shrink-0 items-center justify-center',\n // a tab stop only when it scrolls with every tab disabled (useKeyboardScroll)\n bar: 'no-scrollbar relative max-h-full overflow-auto outline-hidden focus-visible:focus-ring focus-visible:-outline-offset-2',\n wrapper: 'inline-flex max-w-none',\n indicator: 'pointer-events-none absolute',\n },\n variants: {\n variant: {\n [TabVariant.underline]: {\n root: `relative before:pointer-events-none before:absolute before:bg-rui-divider before:content-['']`,\n indicator: 'z-1 bg-rui-primary',\n },\n [TabVariant.segmented]: {\n // neutral-200, not 100: on a near-white page (`#fafafa`) the lighter track all but disappeared\n root: 'rounded-rui-panel bg-rui-neutral-200 p-0.5 dark:bg-rui-neutral-800',\n wrapper: 'gap-0.5',\n indicator: 'rounded-rui-control bg-rui-surface shadow-rui-control dark:bg-rui-neutral-700',\n },\n },\n layout: {\n [TabLayout.horizontal]: { root: 'flex h-fit', arrow: 'w-8' },\n [TabLayout.vertical]: { root: 'inline-flex flex-col', arrow: 'h-8 w-full', wrapper: 'flex-col w-full' },\n },\n indicatorPosition: {\n start: {},\n end: {},\n },\n color: {\n primary: {},\n secondary: {},\n error: {},\n warning: {},\n info: {},\n success: {},\n },\n wide: {\n true: { bar: 'w-full', wrapper: 'min-w-full' },\n false: {},\n },\n animated: {\n true: { indicator: 'transition-[left,top,width,height] duration-200 ease-out motion-reduce:transition-none' },\n false: {},\n },\n },\n compoundVariants: [\n { variant: TabVariant.underline, layout: TabLayout.horizontal, indicatorPosition: 'end', class: { root: 'before:inset-x-0 before:bottom-0 before:h-px', indicator: 'bottom-0 h-0.5 rounded-t-full' } },\n { variant: TabVariant.underline, layout: TabLayout.horizontal, indicatorPosition: 'start', class: { root: 'before:inset-x-0 before:top-0 before:h-px', indicator: 'top-0 h-0.5 rounded-b-full' } },\n { variant: TabVariant.underline, layout: TabLayout.vertical, indicatorPosition: 'end', class: { root: 'before:inset-y-0 before:right-0 before:w-px', indicator: 'right-0 w-0.5 rounded-l-full' } },\n { variant: TabVariant.underline, layout: TabLayout.vertical, indicatorPosition: 'start', class: { root: 'before:inset-y-0 before:left-0 before:w-px', indicator: 'left-0 w-0.5 rounded-r-full' } },\n // the underline track spans its row, while a segmented control hugs its options unless it grows\n { variant: TabVariant.segmented, layout: TabLayout.horizontal, wide: false, class: { root: 'w-fit max-w-full' } },\n // `color` picks the underline's color; the segmented pill stays a neutral surface\n { variant: TabVariant.underline, color: 'secondary', class: { indicator: 'bg-rui-secondary' } },\n { variant: TabVariant.underline, color: 'error', class: { indicator: 'bg-rui-error' } },\n { variant: TabVariant.underline, color: 'warning', class: { indicator: 'bg-rui-warning' } },\n { variant: TabVariant.underline, color: 'info', class: { indicator: 'bg-rui-info' } },\n { variant: TabVariant.underline, color: 'success', class: { indicator: 'bg-rui-success' } },\n ],\n defaultVariants: { variant: TabVariant.underline, layout: TabLayout.horizontal, indicatorPosition: 'end' },\n});\n\nconst slots = useSlots();\n\nconst {\n showArrows,\n prevArrowDisabled,\n nextArrowDisabled,\n onPrevSliderClick,\n onNextSliderClick,\n keepActiveTabVisible,\n} = useTabScroll({ bar, wrapper, vertical: () => vertical });\n\nconst { resolveRoute, isPathMatch } = useTabRouting({\n onRouteChange: () => applyNewValue(true),\n});\n\nconst { onKeydown } = useTabKeyboard({ wrapper, vertical: () => vertical });\n\nconst { style: indicatorStyle, animated, update: updateIndicator } = useTabIndicator({\n bar,\n wrapper,\n vertical: () => vertical,\n variant: () => variant,\n});\n\nconst layout = computed<TabLayout>(() => vertical ? TabLayout.vertical : TabLayout.horizontal);\nconst ui = computed<ReturnType<typeof tabs>>(() => tabs({\n variant,\n layout: get(layout),\n indicatorPosition,\n color,\n wide: vertical || grow,\n animated: get(animated),\n}));\n\nconst children = computed<ChildNode[]>(() => {\n const slotContent = slots.default?.() ?? [];\n\n const tabs = getChildrenTabs(slotContent);\n\n const currentModelValue = get(internalModelValue);\n const inheritedProps = {\n color,\n grow,\n disabled,\n vertical,\n align,\n indicatorPosition,\n variant,\n };\n\n return tabs.map((tab, index) => {\n let tabValue = tab.props?.value ?? index;\n if (tab.props?.link !== false && tab.props?.to)\n tabValue = tab.props.to;\n\n const active = currentModelValue === tabValue;\n return {\n ...tab,\n props: {\n value: tabValue,\n active,\n ...inheritedProps,\n ...tab.props,\n },\n };\n });\n});\n\n/**\n * Unwraps the fragments a `v-for` in the slot produces, so only tabs come\n * back.\n *\n * @param children - the slot's vnodes\n * @returns the tabs among them\n */\nfunction getChildrenTabs(children: VNode[]): VNode[] {\n return children.flatMap((item) => {\n if (item.type === Fragment && Array.isArray(item.children) && item.children.length > 0)\n return getChildrenTabs(item.children.filter(isVNode));\n\n return [item];\n }).flat();\n}\n\nfunction updateModelValue(newModelValue: string | number): void {\n set(modelValue, newModelValue);\n set(internalModelValue, newModelValue);\n}\n\nfunction getTabRouteProps(props: Record<string, unknown>): ResolvedTabProps {\n return {\n value: typeof props.value === 'string' || typeof props.value === 'number' ? props.value : undefined,\n to: props.to ?? undefined,\n link: typeof props.link === 'boolean' ? props.link : undefined,\n exact: typeof props.exact === 'boolean' ? props.exact : undefined,\n };\n}\n\nfunction resolveActiveValue(onlyLink: boolean): string | number | undefined {\n const enabledChildren = get(children).filter(child => !child.props?.disabled);\n if (enabledChildren.length === 0)\n return undefined;\n\n let result: string | number = get(modelValue) || 0;\n enabledChildren.forEach((child, index) => {\n const tabProps = getTabRouteProps(child.props);\n if (!onlyLink && index === 0 && tabProps.value)\n result = tabProps.value;\n\n const fullPath = resolveRoute(tabProps.to);\n\n if (tabProps.link !== false && fullPath && isPathMatch(fullPath, tabProps))\n result = fullPath;\n });\n return result;\n}\n\nfunction applyNewValue(onlyLink = false): void {\n const value = resolveActiveValue(onlyLink);\n if (value !== undefined)\n updateModelValue(value);\n\n keepActiveTabVisible();\n}\n\nwatchImmediate(() => get(modelValue), (modelValue) => {\n set(internalModelValue, modelValue);\n});\n\nwatch(internalModelValue, () => {\n keepActiveTabVisible();\n});\n\nwatch(() => [vertical, variant, grow, align], () => nextTick(updateIndicator), { flush: 'post' });\n\nonMounted(() => {\n if (get(modelValue) !== undefined)\n return;\n\n applyNewValue();\n});\n</script>\n\n<template>\n <div\n :class=\"ui.root()\"\n :data-vertical=\"vertical || undefined\"\n >\n <div\n v-if=\"showArrows\"\n :class=\"ui.arrow()\"\n >\n <RuiButton\n variant=\"text\"\n icon\n size=\"sm\"\n tabindex=\"-1\"\n aria-label=\"Scroll tabs back\"\n :disabled=\"prevArrowDisabled\"\n @click=\"onPrevSliderClick()\"\n >\n <RuiIcon :name=\"vertical ? 'lu-chevron-up' : 'lu-chevron-left'\" />\n </RuiButton>\n </div>\n <div\n ref=\"bar\"\n :class=\"ui.bar()\"\n :tabindex=\"barTabindex\"\n >\n <span\n v-if=\"indicatorStyle\"\n aria-hidden=\"true\"\n data-id=\"tabs-indicator\"\n :class=\"ui.indicator()\"\n :style=\"indicatorStyle\"\n />\n <div\n ref=\"wrapper\"\n role=\"tablist\"\n data-id=\"tabs-wrapper\"\n :aria-orientation=\"vertical ? 'vertical' : undefined\"\n :class=\"ui.wrapper()\"\n @keydown=\"onKeydown($event)\"\n >\n <Component\n :is=\"child\"\n v-for=\"(child, i) in children\"\n :key=\"i\"\n @click=\"updateModelValue($event)\"\n />\n </div>\n </div>\n <div\n v-if=\"showArrows\"\n :class=\"ui.arrow()\"\n >\n <RuiButton\n variant=\"text\"\n icon\n size=\"sm\"\n tabindex=\"-1\"\n aria-label=\"Scroll tabs forward\"\n :disabled=\"nextArrowDisabled\"\n @click=\"onNextSliderClick()\"\n >\n <RuiIcon :name=\"vertical ? 'lu-chevron-down' : 'lu-chevron-right'\" />\n </RuiButton>\n </div>\n </div>\n</template>\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"RuiTabs.vue_vue_type_script_setup_true_lang.js","names":["_useModel","_openBlock","_createElementBlock","_normalizeClass","_unref","_createVNode","RuiButton","_withCtx","RuiIcon","_createCommentVNode","_createElementVNode","_normalizeStyle","_Fragment","_renderList","_createBlock","_resolveDynamicComponent"],"sources":["../../../../src/components/tabs/tabs/RuiTabs.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport type { ContextColorsType } from '@/consts/colors';\nimport { Fragment, isVNode, type VNode } from 'vue';\nimport RuiButton from '@/components/buttons/button/RuiButton.vue';\nimport RuiIcon from '@/components/icons/RuiIcon.vue';\nimport { type TabAlignment, type TabIndicatorPosition, TabLayout, TabVariant } from '@/components/tabs/tab-props';\nimport { useTabIndicator } from '@/components/tabs/tabs/use-tab-indicator';\nimport { useTabKeyboard } from '@/components/tabs/tabs/use-tab-keyboard';\nimport { useTabRouting } from '@/components/tabs/tabs/use-tab-routing';\nimport { useTabScroll } from '@/components/tabs/tabs/use-tab-scroll';\nimport { useKeyboardScroll } from '@/composables/keyboard-scroll';\nimport { tv } from '@/utils/tv';\n\ntype ChildNode = VNode & { props: Record<string, any> };\n\ninterface ResolvedTabProps {\n value?: string | number;\n to?: unknown;\n link?: boolean;\n exact?: boolean;\n}\n\nexport interface Props {\n color?: ContextColorsType;\n vertical?: boolean;\n disabled?: boolean;\n grow?: boolean;\n align?: TabAlignment;\n indicatorPosition?: TabIndicatorPosition;\n variant?: TabVariant;\n}\n\ndefineOptions({\n name: 'RuiTabs',\n});\n\n/**\n * The selected tab, defaulting to the first one. The default also narrows the\n * `update:modelValue` payload to `number | string`, so a consumer's handler\n * needs no undefined in its signature.\n */\nconst modelValue = defineModel<number | string>({ default: 0 });\n\nconst {\n color,\n vertical = false,\n disabled = false,\n grow = false,\n align = 'center',\n indicatorPosition = 'end',\n variant = TabVariant.underline,\n} = defineProps<Props>();\n\nconst internalModelValue = ref<string | number>();\nconst bar = useTemplateRef<HTMLDivElement>('bar');\nconst wrapper = useTemplateRef<HTMLDivElement>('wrapper');\nconst barTabindex = useKeyboardScroll(bar);\n\n/**\n * The bar. The underline variant draws its 1px track as a `before` line along\n * the whole root, so the arrows sit on it too, and the 2px indicator, a layer\n * above, covers it under the active tab.\n */\nconst tabs = tv({\n slots: {\n root: '',\n arrow: 'flex shrink-0 items-center justify-center',\n // a tab stop only when it scrolls with every tab disabled (useKeyboardScroll)\n bar: 'no-scrollbar relative max-h-full overflow-auto outline-hidden focus-visible:focus-ring focus-visible:-outline-offset-2',\n wrapper: 'inline-flex max-w-none',\n indicator: 'pointer-events-none absolute',\n },\n variants: {\n variant: {\n [TabVariant.underline]: {\n root: `relative before:pointer-events-none before:absolute before:bg-rui-divider before:content-['']`,\n indicator: 'z-1 bg-rui-primary',\n },\n [TabVariant.segmented]: {\n // neutral-200, not 100: on a near-white page (`#fafafa`) the lighter track all but disappeared\n root: 'rounded-rui-panel bg-rui-neutral-200 p-0.5 dark:bg-rui-neutral-800',\n wrapper: 'gap-0.5',\n indicator: 'rounded-rui-control bg-rui-surface shadow-rui-control dark:bg-rui-neutral-700',\n },\n },\n layout: {\n [TabLayout.horizontal]: { root: 'flex h-fit', arrow: 'w-8' },\n [TabLayout.vertical]: { root: 'inline-flex flex-col', arrow: 'h-8 w-full', wrapper: 'flex-col w-full' },\n },\n indicatorPosition: {\n start: {},\n end: {},\n },\n color: {\n primary: {},\n secondary: {},\n error: {},\n warning: {},\n info: {},\n success: {},\n },\n wide: {\n true: { bar: 'w-full', wrapper: 'min-w-full' },\n false: {},\n },\n animated: {\n true: { indicator: 'transition-[left,top,width,height] duration-200 ease-out motion-reduce:transition-none' },\n false: {},\n },\n },\n compoundVariants: [\n { variant: TabVariant.underline, layout: TabLayout.horizontal, indicatorPosition: 'end', class: { root: 'before:inset-x-0 before:bottom-0 before:h-px', indicator: 'bottom-0 h-0.5 rounded-t-full' } },\n { variant: TabVariant.underline, layout: TabLayout.horizontal, indicatorPosition: 'start', class: { root: 'before:inset-x-0 before:top-0 before:h-px', indicator: 'top-0 h-0.5 rounded-b-full' } },\n { variant: TabVariant.underline, layout: TabLayout.vertical, indicatorPosition: 'end', class: { root: 'before:inset-y-0 before:right-0 before:w-px', indicator: 'right-0 w-0.5 rounded-l-full' } },\n { variant: TabVariant.underline, layout: TabLayout.vertical, indicatorPosition: 'start', class: { root: 'before:inset-y-0 before:left-0 before:w-px', indicator: 'left-0 w-0.5 rounded-r-full' } },\n // the underline track spans its row, while a segmented control hugs its options unless it grows\n { variant: TabVariant.segmented, layout: TabLayout.horizontal, wide: false, class: { root: 'w-fit max-w-full' } },\n // `color` picks the underline's color; the segmented pill stays a neutral surface\n { variant: TabVariant.underline, color: 'secondary', class: { indicator: 'bg-rui-secondary' } },\n { variant: TabVariant.underline, color: 'error', class: { indicator: 'bg-rui-error' } },\n { variant: TabVariant.underline, color: 'warning', class: { indicator: 'bg-rui-warning' } },\n { variant: TabVariant.underline, color: 'info', class: { indicator: 'bg-rui-info' } },\n { variant: TabVariant.underline, color: 'success', class: { indicator: 'bg-rui-success' } },\n ],\n defaultVariants: { variant: TabVariant.underline, layout: TabLayout.horizontal, indicatorPosition: 'end' },\n});\n\nconst slots = useSlots();\n\nconst {\n showArrows,\n prevArrowDisabled,\n nextArrowDisabled,\n onPrevSliderClick,\n onNextSliderClick,\n keepActiveTabVisible,\n} = useTabScroll({ bar, wrapper, vertical: () => vertical });\n\nconst { resolveRoute, isPathMatch } = useTabRouting({\n onRouteChange: () => applyNewValue(true),\n});\n\nconst { onKeydown } = useTabKeyboard({ wrapper, vertical: () => vertical });\n\nconst { style: indicatorStyle, animated, update: updateIndicator } = useTabIndicator({\n bar,\n wrapper,\n vertical: () => vertical,\n variant: () => variant,\n});\n\nconst layout = computed<TabLayout>(() => vertical ? TabLayout.vertical : TabLayout.horizontal);\nconst ui = computed<ReturnType<typeof tabs>>(() => tabs({\n variant,\n layout: get(layout),\n indicatorPosition,\n color,\n wide: vertical || grow,\n animated: get(animated),\n}));\n\nconst children = computed<ChildNode[]>(() => {\n const slotContent = slots.default?.() ?? [];\n\n const tabs = getChildrenTabs(slotContent);\n\n const currentModelValue = get(internalModelValue);\n const inheritedProps = {\n color,\n grow,\n disabled,\n vertical,\n align,\n indicatorPosition,\n variant,\n };\n\n return tabs.map((tab, index) => {\n let tabValue = tab.props?.value ?? index;\n if (tab.props?.link !== false && tab.props?.to)\n tabValue = tab.props.to;\n\n const active = currentModelValue === tabValue;\n return {\n ...tab,\n props: {\n value: tabValue,\n active,\n ...inheritedProps,\n ...tab.props,\n },\n };\n });\n});\n\n/**\n * Unwraps the fragments a `v-for` in the slot produces, so only tabs come\n * back.\n *\n * @param children - the slot's vnodes\n * @returns the tabs among them\n */\nfunction getChildrenTabs(children: VNode[]): VNode[] {\n return children.flatMap((item) => {\n if (item.type === Fragment && Array.isArray(item.children) && item.children.length > 0)\n return getChildrenTabs(item.children.filter(isVNode));\n\n return [item];\n }).flat();\n}\n\nfunction updateModelValue(newModelValue: string | number): void {\n set(modelValue, newModelValue);\n set(internalModelValue, newModelValue);\n}\n\nfunction getTabRouteProps(props: Record<string, unknown>): ResolvedTabProps {\n return {\n value: typeof props.value === 'string' || typeof props.value === 'number' ? props.value : undefined,\n to: props.to ?? undefined,\n link: typeof props.link === 'boolean' ? props.link : undefined,\n exact: typeof props.exact === 'boolean' ? props.exact : undefined,\n };\n}\n\nfunction resolveActiveValue(onlyLink: boolean): string | number | undefined {\n const enabledChildren = get(children).filter(child => !child.props?.disabled);\n if (enabledChildren.length === 0)\n return undefined;\n\n let result: string | number = get(modelValue) || 0;\n enabledChildren.forEach((child, index) => {\n const tabProps = getTabRouteProps(child.props);\n if (!onlyLink && index === 0 && tabProps.value)\n result = tabProps.value;\n\n const fullPath = resolveRoute(tabProps.to);\n\n if (tabProps.link !== false && fullPath && isPathMatch(fullPath, tabProps))\n result = fullPath;\n });\n return result;\n}\n\nfunction applyNewValue(onlyLink = false): void {\n const value = resolveActiveValue(onlyLink);\n if (value !== undefined)\n updateModelValue(value);\n\n keepActiveTabVisible();\n}\n\nwatchImmediate(() => get(modelValue), (modelValue) => {\n set(internalModelValue, modelValue);\n});\n\nwatch(internalModelValue, () => {\n keepActiveTabVisible();\n});\n\nwatch(() => [vertical, variant, grow, align], () => nextTick(updateIndicator), { flush: 'post' });\n\nonMounted(() => {\n if (get(modelValue) !== undefined)\n return;\n\n applyNewValue();\n});\n</script>\n\n<template>\n <div\n :class=\"ui.root()\"\n :data-vertical=\"vertical || undefined\"\n >\n <div\n v-if=\"showArrows\"\n :class=\"ui.arrow()\"\n >\n <RuiButton\n variant=\"text\"\n icon\n size=\"sm\"\n tabindex=\"-1\"\n aria-label=\"Scroll tabs back\"\n :disabled=\"prevArrowDisabled\"\n @click=\"onPrevSliderClick()\"\n >\n <RuiIcon :name=\"vertical ? 'lu-chevron-up' : 'lu-chevron-left'\" />\n </RuiButton>\n </div>\n <div\n ref=\"bar\"\n :class=\"ui.bar()\"\n :tabindex=\"barTabindex\"\n >\n <span\n v-if=\"indicatorStyle\"\n aria-hidden=\"true\"\n data-id=\"tabs-indicator\"\n :class=\"ui.indicator()\"\n :style=\"indicatorStyle\"\n />\n <div\n ref=\"wrapper\"\n role=\"tablist\"\n data-id=\"tabs-wrapper\"\n :aria-orientation=\"vertical ? 'vertical' : undefined\"\n :class=\"ui.wrapper()\"\n @keydown=\"onKeydown($event)\"\n >\n <Component\n :is=\"child\"\n v-for=\"(child, i) in children\"\n :key=\"i\"\n @click=\"updateModelValue($event)\"\n />\n </div>\n </div>\n <div\n v-if=\"showArrows\"\n :class=\"ui.arrow()\"\n >\n <RuiButton\n variant=\"text\"\n icon\n size=\"sm\"\n tabindex=\"-1\"\n aria-label=\"Scroll tabs forward\"\n :disabled=\"nextArrowDisabled\"\n @click=\"onNextSliderClick()\"\n >\n <RuiIcon :name=\"vertical ? 'lu-chevron-down' : 'lu-chevron-right'\" />\n </RuiButton>\n </div>\n </div>\n</template>\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RuiTimePicker.js","names":[],"sources":["../../../src/components/time-picker/RuiTimePicker.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, onMounted, ref, type StyleValue, watch } from 'vue';\nimport { timePickerStyles } from '@/components/time-picker/time-picker-styles';\nimport { TimeAccuracy } from '@/consts/time-accuracy';\nimport { assert } from '@/utils/assert';\n\nexport type TimePickerSelection = 'hour' | 'minute' | 'second' | 'millisecond';\n\nexport interface RuiTimePickerProps {\n accuracy?: TimeAccuracy;\n borderless?: boolean;\n}\n\nconst modelValue = defineModel<Date | undefined>({ required: true });\n\nconst selectedHour = defineModel<number | undefined>('hour');\nconst selectedMinute = defineModel<number | undefined>('minute');\nconst selectedSecond = defineModel<number | undefined>('second');\nconst selectedMillisecond = defineModel<number | undefined>('millisecond');\nconst editMode = defineModel<TimePickerSelection>('selection', { default: 'hour' });\n\nconst { accuracy = TimeAccuracy.MINUTE, borderless = false } = defineProps<RuiTimePickerProps>();\n\nconst ui = timePickerStyles();\n\nconst FULL_CIRCLE = 360;\nconst TWELVE_HOURS = 12;\n\nconst totalItemsPerMode: Record<TimePickerSelection, number> = {\n hour: 12,\n minute: 60,\n second: 60,\n millisecond: 1000,\n};\n\nconst intervals: Record<TimePickerSelection, number> = {\n hour: 1,\n minute: 5,\n second: 5,\n millisecond: 100,\n};\n\nconst isDragging = ref<boolean>(false);\nconst clockFace = useTemplateRef<InstanceType<typeof HTMLDivElement>>('clockFace');\n\nconst showSecond = computed<boolean>(\n () => accuracy === TimeAccuracy.SECOND || accuracy === TimeAccuracy.MILLISECOND,\n);\nconst showMillisecond = computed<boolean>(() => accuracy === TimeAccuracy.MILLISECOND);\n\nconst period = computed<'PM' | 'AM'>(() =>\n isDefined(selectedHour) && get(selectedHour) >= TWELVE_HOURS ? 'PM' : 'AM',\n);\n\nconst displayHour = computed<number | undefined>(() => {\n if (!isDefined(selectedHour)) {\n return undefined;\n }\n const hourValue = get(selectedHour);\n const hour = hourValue % TWELVE_HOURS;\n return hour === 0 ? TWELVE_HOURS : hour;\n});\n\nconst editedValue = computed<number | undefined>(() => {\n const mode = get(editMode);\n if (mode === 'hour') {\n return get(displayHour);\n }\n else if (mode === 'minute') {\n return get(selectedMinute);\n }\n else if (mode === 'second') {\n return get(selectedSecond);\n }\n else {\n return get(selectedMillisecond);\n }\n});\n\nconst displayClockHandCircle = computed<boolean>(() => {\n const mode = get(editMode);\n if (mode === 'hour' || !isDefined(editedValue)) {\n return false;\n }\n else {\n const interval = intervals[mode];\n const value = get(editedValue);\n return value % interval !== 0;\n }\n});\n\nconst dotStyle = computed<StyleValue>(() => ({\n top: '50%',\n left: '50%',\n transform: 'translate(-50%, -50%)',\n}));\n\nconst clockHandStyle = computed<StyleValue>(() => {\n if (!isDefined(editedValue)) {\n return {};\n }\n const currentValue = get(editedValue);\n const totalItems = totalItemsPerMode[get(editMode)];\n const angle = currentValue * (FULL_CIRCLE / totalItems);\n\n return {\n height: '36%',\n top: '14%',\n left: '50%',\n transformOrigin: 'bottom center',\n transform: `translateX(-50%) rotate(${angle}deg)`,\n zIndex: 10,\n };\n});\n\nconst clockHandCircleStyle = computed<StyleValue>(() => {\n if (!isDefined(editedValue)) {\n return {};\n }\n const radius = '38%';\n const currentValue = get(editedValue);\n const totalItems = totalItemsPerMode[get(editMode)];\n const angle = currentValue * (FULL_CIRCLE / totalItems);\n\n const radians = (angle * Math.PI) / 180;\n\n const x = 50 + parseFloat(radius) * Math.cos(radians - Math.PI / 2);\n const y = 50 + parseFloat(radius) * Math.sin(radians - Math.PI / 2);\n\n return {\n position: 'absolute',\n top: `${y}%`,\n left: `${x}%`,\n width: '10px',\n height: '10px',\n borderRadius: '50%',\n transform: 'translate(-50%, -50%)',\n zIndex: 11,\n };\n});\n\nconst clockNumbers = computed<number[]>(() => {\n const mode = get(editMode);\n const interval = intervals[mode];\n const total = totalItemsPerMode[mode];\n const numbers = generateNumbers(total, interval);\n if (mode === 'hour') {\n numbers[0] = 12;\n }\n return numbers;\n});\n\nfunction getModelHours(): number | undefined {\n return isDefined(modelValue) ? new Date(get(modelValue)).getHours() : undefined;\n}\n\nfunction getModelMinutes(): number | undefined {\n return isDefined(modelValue) ? new Date(get(modelValue)).getMinutes() : undefined;\n}\n\nfunction getModelSeconds(): number | undefined {\n const acceptedAccuracy: TimeAccuracy[] = [TimeAccuracy.SECOND, TimeAccuracy.MILLISECOND];\n return acceptedAccuracy.includes(accuracy) && isDefined(modelValue)\n ? new Date(get(modelValue)).getSeconds()\n : undefined;\n}\n\nfunction getModelMilliseconds(): number | undefined {\n return accuracy === TimeAccuracy.MILLISECOND && isDefined(modelValue)\n ? new Date(get(modelValue)).getMilliseconds()\n : undefined;\n}\n\nfunction generateNumbers(total: number, interval: number): number[] {\n const numbers: number[] = [];\n for (let i = 0; i < total; i += interval) {\n numbers.push(i);\n }\n return numbers;\n}\n\nfunction formatValue(value?: number, padding = 2): string {\n return value !== undefined ? value.toString().padStart(padding, '0') : '-'.repeat(padding);\n}\n\nfunction numberStyle(num: number): StyleValue {\n const radius = '38%';\n const totalItems = totalItemsPerMode[get(editMode)];\n const angle = num * (FULL_CIRCLE / totalItems) - 90;\n\n const radians = (angle * Math.PI) / 180;\n const x = 50 + parseFloat(radius) * Math.cos(radians);\n const y = 50 + parseFloat(radius) * Math.sin(radians);\n\n return {\n top: `${y}%`,\n left: `${x}%`,\n transform: 'translate(-50%, -50%)',\n };\n}\n\nfunction isSelectedNumber(num: number): boolean {\n if (!isDefined(editedValue)) {\n return false;\n }\n const mode = get(editMode);\n if (mode === 'hour') {\n return get(displayHour) === num;\n }\n else {\n const value = get(editedValue);\n const interval = intervals[mode];\n return value === num || (value % interval === 0 && value === num);\n }\n}\n\nfunction toggleAmPm(): void {\n if (!isDefined(selectedHour)) {\n return;\n }\n if (get(selectedHour) < TWELVE_HOURS) {\n set(selectedHour, get(selectedHour) + TWELVE_HOURS);\n }\n else {\n set(selectedHour, get(selectedHour) - TWELVE_HOURS);\n }\n\n updateModelValue();\n}\n\nfunction startDrag(event: MouseEvent | TouchEvent): void {\n event.preventDefault();\n set(isDragging, true);\n\n if (!isDefined(clockFace))\n return;\n\n const rect = get(clockFace).getBoundingClientRect();\n const centerX = rect.left + rect.width / 2;\n const centerY = rect.top + rect.height / 2;\n let rafId: number | null = null;\n\n const applyMove = (clientX: number, clientY: number): void => {\n const x = clientX - centerX;\n const y = clientY - centerY;\n\n let angle = Math.atan2(y, x) * (180 / Math.PI) + 90;\n if (angle < 0)\n angle += FULL_CIRCLE;\n\n const mode = get(editMode);\n const unit =\n Math.round(angle / (FULL_CIRCLE / totalItemsPerMode[mode])) % totalItemsPerMode[mode];\n if (mode === 'hour') {\n let hour = unit;\n if (hour === 0)\n hour = TWELVE_HOURS;\n\n if (get(period) === 'PM' && hour < TWELVE_HOURS) {\n hour += TWELVE_HOURS;\n }\n else if (get(period) === 'AM' && hour === TWELVE_HOURS) {\n hour = 0;\n }\n\n set(selectedHour, hour);\n }\n else if (mode === 'minute') {\n set(selectedMinute, unit);\n }\n else if (mode === 'second') {\n set(selectedSecond, unit);\n }\n else {\n set(selectedMillisecond, unit);\n }\n\n updateModelValue();\n };\n\n const handleMove = (moveEvent: MouseEvent | TouchEvent): void => {\n if (!get(isDragging))\n return;\n\n if (rafId !== null)\n return;\n\n let clientX: number;\n let clientY: number;\n\n if ('touches' in moveEvent) {\n const touch = moveEvent.touches[0];\n assert(touch);\n clientX = touch.clientX;\n clientY = touch.clientY;\n }\n else {\n clientX = moveEvent.clientX;\n clientY = moveEvent.clientY;\n }\n\n rafId = requestAnimationFrame(() => {\n applyMove(clientX, clientY);\n rafId = null;\n });\n };\n\n const handleEnd = (): void => {\n if (rafId !== null) {\n cancelAnimationFrame(rafId);\n rafId = null;\n }\n set(isDragging, false);\n document.removeEventListener('mousemove', handleMove);\n document.removeEventListener('touchmove', handleMove);\n document.removeEventListener('mouseup', handleEnd);\n document.removeEventListener('touchend', handleEnd);\n\n if (get(editMode) === 'hour') {\n set(editMode, 'minute');\n }\n else if (get(showSecond) && get(editMode) === 'minute') {\n set(editMode, 'second');\n }\n else if (get(showMillisecond) && get(editMode) === 'second') {\n set(editMode, 'millisecond');\n }\n };\n\n document.addEventListener('mousemove', handleMove);\n document.addEventListener('touchmove', handleMove);\n document.addEventListener('mouseup', handleEnd);\n document.addEventListener('touchend', handleEnd);\n\n // Apply initial position synchronously for immediate feedback\n const initialEvent = event;\n let clientX: number;\n let clientY: number;\n if ('touches' in initialEvent) {\n const touch = initialEvent.touches[0];\n assert(touch);\n clientX = touch.clientX;\n clientY = touch.clientY;\n }\n else {\n clientX = initialEvent.clientX;\n clientY = initialEvent.clientY;\n }\n applyMove(clientX, clientY);\n}\n\nfunction selectByClick(num: number): void {\n const mode = get(editMode);\n if (mode === 'hour') {\n let newHour = num;\n\n if (get(period) === 'PM' && newHour < TWELVE_HOURS) {\n newHour += TWELVE_HOURS;\n }\n\n set(selectedHour, newHour);\n set(editMode, 'minute');\n }\n else if (mode === 'minute') {\n set(selectedMinute, num);\n if (get(showSecond))\n set(editMode, 'second');\n }\n else if (mode === 'second') {\n set(selectedSecond, num);\n if (get(showMillisecond)) {\n set(editMode, 'millisecond');\n }\n }\n else if (mode === 'millisecond') {\n set(selectedMillisecond, num);\n }\n\n updateModelValue();\n}\n\nfunction updateModelValue(): void {\n if (!(isDefined(selectedHour) && isDefined(selectedMinute))) {\n return;\n }\n nextTick(() => {\n const date = isDefined(modelValue) ? new Date(get(modelValue)) : new Date();\n date.setHours(get(selectedHour));\n date.setMinutes(get(selectedMinute));\n date.setSeconds(get(selectedSecond) ?? 0);\n date.setMilliseconds(get(selectedMillisecond) ?? 0);\n set(modelValue, date);\n });\n}\n\nwatch(\n modelValue,\n () => {\n set(selectedHour, getModelHours());\n set(selectedMinute, getModelMinutes());\n set(selectedSecond, getModelSeconds());\n set(selectedMillisecond, getModelMilliseconds());\n },\n);\n\nonMounted(() => {\n set(selectedHour, getModelHours());\n set(selectedMinute, getModelMinutes());\n set(selectedSecond, getModelSeconds());\n set(selectedMillisecond, getModelMilliseconds());\n});\n</script>\n\n<template>\n <div\n role=\"group\"\n aria-label=\"Time picker\"\n :class=\"ui.root({ bordered: !borderless })\"\n >\n <div :class=\"ui.digitalDisplay()\">\n <div :class=\"ui.time()\">\n <button\n type=\"button\"\n aria-label=\"Select hours\"\n :aria-pressed=\"editMode === 'hour'\"\n :class=\"ui.digit({ active: editMode === 'hour' })\"\n @click=\"editMode = 'hour'\"\n >\n {{ formatValue(displayHour) }}\n </button>\n <div :class=\"ui.separator()\">\n :\n </div>\n <button\n type=\"button\"\n aria-label=\"Select minutes\"\n :aria-pressed=\"editMode === 'minute'\"\n :class=\"ui.digit({ active: editMode === 'minute' })\"\n @click=\"editMode = 'minute'\"\n >\n {{ formatValue(selectedMinute) }}\n </button>\n <div\n v-if=\"showSecond\"\n :class=\"ui.separator()\"\n >\n :\n </div>\n <button\n v-if=\"showSecond\"\n type=\"button\"\n aria-label=\"Select seconds\"\n :aria-pressed=\"editMode === 'second'\"\n :class=\"ui.digit({ active: editMode === 'second' })\"\n @click=\"editMode = 'second'\"\n >\n {{ formatValue(selectedSecond) }}\n </button>\n\n <div\n v-if=\"showMillisecond\"\n :class=\"ui.separator({ class: 'text-lg' })\"\n >\n .\n </div>\n\n <button\n v-if=\"showMillisecond\"\n type=\"button\"\n aria-label=\"Select milliseconds\"\n :aria-pressed=\"editMode === 'millisecond'\"\n :class=\"ui.digit({ active: editMode === 'millisecond', class: 'text-lg' })\"\n @click=\"editMode = 'millisecond'\"\n >\n {{ formatValue(selectedMillisecond, 3) }}\n </button>\n </div>\n <button\n type=\"button\"\n aria-label=\"Toggle AM/PM\"\n :class=\"ui.period()\"\n @click=\"toggleAmPm()\"\n >\n {{ period }}\n </button>\n </div>\n\n <div\n ref=\"clockFace\"\n role=\"listbox\"\n :aria-label=\"`Select ${editMode}`\"\n :class=\"ui.clockFace()\"\n @mousedown=\"startDrag($event)\"\n @touchstart=\"startDrag($event)\"\n >\n <div\n :class=\"ui.centerDot()\"\n :style=\"dotStyle\"\n />\n\n <div\n :class=\"ui.clockHand()\"\n :style=\"clockHandStyle\"\n />\n\n <div\n v-if=\"displayClockHandCircle\"\n :class=\"ui.clockHandCircle()\"\n :style=\"clockHandCircleStyle\"\n />\n\n <div\n v-for=\"num in clockNumbers\"\n :key=\"`num-${num}`\"\n role=\"option\"\n :aria-selected=\"isSelectedNumber(num)\"\n :class=\"[\n ui.clockNumber({ selected: isSelectedNumber(num) }),\n `rui-${editMode}-${num.toString().padStart(2, '0')}`,\n ]\"\n :style=\"numberStyle(num)\"\n @click=\"selectByClick(num)\"\n >\n {{ num }}\n </div>\n </div>\n </div>\n</template>\n"],"mappings":""}
|
|
1
|
+
{"version":3,"file":"RuiTimePicker.js","names":["_sfc_main"],"sources":["../../../src/components/time-picker/RuiTimePicker.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, onMounted, ref, type StyleValue, watch } from 'vue';\nimport { timePickerStyles } from '@/components/time-picker/time-picker-styles';\nimport { TimeAccuracy } from '@/consts/time-accuracy';\nimport { assert } from '@/utils/assert';\n\nexport type TimePickerSelection = 'hour' | 'minute' | 'second' | 'millisecond';\n\nexport interface RuiTimePickerProps {\n accuracy?: TimeAccuracy;\n borderless?: boolean;\n}\n\nconst modelValue = defineModel<Date | undefined>({ required: true });\n\nconst selectedHour = defineModel<number | undefined>('hour');\nconst selectedMinute = defineModel<number | undefined>('minute');\nconst selectedSecond = defineModel<number | undefined>('second');\nconst selectedMillisecond = defineModel<number | undefined>('millisecond');\nconst editMode = defineModel<TimePickerSelection>('selection', { default: 'hour' });\n\nconst { accuracy = TimeAccuracy.MINUTE, borderless = false } = defineProps<RuiTimePickerProps>();\n\nconst ui = timePickerStyles();\n\nconst FULL_CIRCLE = 360;\nconst TWELVE_HOURS = 12;\n\nconst totalItemsPerMode: Record<TimePickerSelection, number> = {\n hour: 12,\n minute: 60,\n second: 60,\n millisecond: 1000,\n};\n\nconst intervals: Record<TimePickerSelection, number> = {\n hour: 1,\n minute: 5,\n second: 5,\n millisecond: 100,\n};\n\nconst isDragging = ref<boolean>(false);\nconst clockFace = useTemplateRef<InstanceType<typeof HTMLDivElement>>('clockFace');\n\nconst showSecond = computed<boolean>(\n () => accuracy === TimeAccuracy.SECOND || accuracy === TimeAccuracy.MILLISECOND,\n);\nconst showMillisecond = computed<boolean>(() => accuracy === TimeAccuracy.MILLISECOND);\n\nconst period = computed<'PM' | 'AM'>(() =>\n isDefined(selectedHour) && get(selectedHour) >= TWELVE_HOURS ? 'PM' : 'AM',\n);\n\nconst displayHour = computed<number | undefined>(() => {\n if (!isDefined(selectedHour)) {\n return undefined;\n }\n const hourValue = get(selectedHour);\n const hour = hourValue % TWELVE_HOURS;\n return hour === 0 ? TWELVE_HOURS : hour;\n});\n\nconst editedValue = computed<number | undefined>(() => {\n const mode = get(editMode);\n if (mode === 'hour') {\n return get(displayHour);\n }\n else if (mode === 'minute') {\n return get(selectedMinute);\n }\n else if (mode === 'second') {\n return get(selectedSecond);\n }\n else {\n return get(selectedMillisecond);\n }\n});\n\nconst displayClockHandCircle = computed<boolean>(() => {\n const mode = get(editMode);\n if (mode === 'hour' || !isDefined(editedValue)) {\n return false;\n }\n else {\n const interval = intervals[mode];\n const value = get(editedValue);\n return value % interval !== 0;\n }\n});\n\nconst dotStyle = computed<StyleValue>(() => ({\n top: '50%',\n left: '50%',\n transform: 'translate(-50%, -50%)',\n}));\n\nconst clockHandStyle = computed<StyleValue>(() => {\n if (!isDefined(editedValue)) {\n return {};\n }\n const currentValue = get(editedValue);\n const totalItems = totalItemsPerMode[get(editMode)];\n const angle = currentValue * (FULL_CIRCLE / totalItems);\n\n return {\n height: '36%',\n top: '14%',\n left: '50%',\n transformOrigin: 'bottom center',\n transform: `translateX(-50%) rotate(${angle}deg)`,\n zIndex: 10,\n };\n});\n\nconst clockHandCircleStyle = computed<StyleValue>(() => {\n if (!isDefined(editedValue)) {\n return {};\n }\n const radius = '38%';\n const currentValue = get(editedValue);\n const totalItems = totalItemsPerMode[get(editMode)];\n const angle = currentValue * (FULL_CIRCLE / totalItems);\n\n const radians = (angle * Math.PI) / 180;\n\n const x = 50 + parseFloat(radius) * Math.cos(radians - Math.PI / 2);\n const y = 50 + parseFloat(radius) * Math.sin(radians - Math.PI / 2);\n\n return {\n position: 'absolute',\n top: `${y}%`,\n left: `${x}%`,\n width: '10px',\n height: '10px',\n borderRadius: '50%',\n transform: 'translate(-50%, -50%)',\n zIndex: 11,\n };\n});\n\nconst clockNumbers = computed<number[]>(() => {\n const mode = get(editMode);\n const interval = intervals[mode];\n const total = totalItemsPerMode[mode];\n const numbers = generateNumbers(total, interval);\n if (mode === 'hour') {\n numbers[0] = 12;\n }\n return numbers;\n});\n\nfunction getModelHours(): number | undefined {\n return isDefined(modelValue) ? new Date(get(modelValue)).getHours() : undefined;\n}\n\nfunction getModelMinutes(): number | undefined {\n return isDefined(modelValue) ? new Date(get(modelValue)).getMinutes() : undefined;\n}\n\nfunction getModelSeconds(): number | undefined {\n const acceptedAccuracy: TimeAccuracy[] = [TimeAccuracy.SECOND, TimeAccuracy.MILLISECOND];\n return acceptedAccuracy.includes(accuracy) && isDefined(modelValue)\n ? new Date(get(modelValue)).getSeconds()\n : undefined;\n}\n\nfunction getModelMilliseconds(): number | undefined {\n return accuracy === TimeAccuracy.MILLISECOND && isDefined(modelValue)\n ? new Date(get(modelValue)).getMilliseconds()\n : undefined;\n}\n\nfunction generateNumbers(total: number, interval: number): number[] {\n const numbers: number[] = [];\n for (let i = 0; i < total; i += interval) {\n numbers.push(i);\n }\n return numbers;\n}\n\nfunction formatValue(value?: number, padding = 2): string {\n return value !== undefined ? value.toString().padStart(padding, '0') : '-'.repeat(padding);\n}\n\nfunction numberStyle(num: number): StyleValue {\n const radius = '38%';\n const totalItems = totalItemsPerMode[get(editMode)];\n const angle = num * (FULL_CIRCLE / totalItems) - 90;\n\n const radians = (angle * Math.PI) / 180;\n const x = 50 + parseFloat(radius) * Math.cos(radians);\n const y = 50 + parseFloat(radius) * Math.sin(radians);\n\n return {\n top: `${y}%`,\n left: `${x}%`,\n transform: 'translate(-50%, -50%)',\n };\n}\n\nfunction isSelectedNumber(num: number): boolean {\n if (!isDefined(editedValue)) {\n return false;\n }\n const mode = get(editMode);\n if (mode === 'hour') {\n return get(displayHour) === num;\n }\n else {\n const value = get(editedValue);\n const interval = intervals[mode];\n return value === num || (value % interval === 0 && value === num);\n }\n}\n\nfunction toggleAmPm(): void {\n if (!isDefined(selectedHour)) {\n return;\n }\n if (get(selectedHour) < TWELVE_HOURS) {\n set(selectedHour, get(selectedHour) + TWELVE_HOURS);\n }\n else {\n set(selectedHour, get(selectedHour) - TWELVE_HOURS);\n }\n\n updateModelValue();\n}\n\nfunction startDrag(event: MouseEvent | TouchEvent): void {\n event.preventDefault();\n set(isDragging, true);\n\n if (!isDefined(clockFace))\n return;\n\n const rect = get(clockFace).getBoundingClientRect();\n const centerX = rect.left + rect.width / 2;\n const centerY = rect.top + rect.height / 2;\n let rafId: number | null = null;\n\n const applyMove = (clientX: number, clientY: number): void => {\n const x = clientX - centerX;\n const y = clientY - centerY;\n\n let angle = Math.atan2(y, x) * (180 / Math.PI) + 90;\n if (angle < 0)\n angle += FULL_CIRCLE;\n\n const mode = get(editMode);\n const unit =\n Math.round(angle / (FULL_CIRCLE / totalItemsPerMode[mode])) % totalItemsPerMode[mode];\n if (mode === 'hour') {\n let hour = unit;\n if (hour === 0)\n hour = TWELVE_HOURS;\n\n if (get(period) === 'PM' && hour < TWELVE_HOURS) {\n hour += TWELVE_HOURS;\n }\n else if (get(period) === 'AM' && hour === TWELVE_HOURS) {\n hour = 0;\n }\n\n set(selectedHour, hour);\n }\n else if (mode === 'minute') {\n set(selectedMinute, unit);\n }\n else if (mode === 'second') {\n set(selectedSecond, unit);\n }\n else {\n set(selectedMillisecond, unit);\n }\n\n updateModelValue();\n };\n\n const handleMove = (moveEvent: MouseEvent | TouchEvent): void => {\n if (!get(isDragging))\n return;\n\n if (rafId !== null)\n return;\n\n let clientX: number;\n let clientY: number;\n\n if ('touches' in moveEvent) {\n const touch = moveEvent.touches[0];\n assert(touch);\n clientX = touch.clientX;\n clientY = touch.clientY;\n }\n else {\n clientX = moveEvent.clientX;\n clientY = moveEvent.clientY;\n }\n\n rafId = requestAnimationFrame(() => {\n applyMove(clientX, clientY);\n rafId = null;\n });\n };\n\n const handleEnd = (): void => {\n if (rafId !== null) {\n cancelAnimationFrame(rafId);\n rafId = null;\n }\n set(isDragging, false);\n document.removeEventListener('mousemove', handleMove);\n document.removeEventListener('touchmove', handleMove);\n document.removeEventListener('mouseup', handleEnd);\n document.removeEventListener('touchend', handleEnd);\n\n if (get(editMode) === 'hour') {\n set(editMode, 'minute');\n }\n else if (get(showSecond) && get(editMode) === 'minute') {\n set(editMode, 'second');\n }\n else if (get(showMillisecond) && get(editMode) === 'second') {\n set(editMode, 'millisecond');\n }\n };\n\n document.addEventListener('mousemove', handleMove);\n document.addEventListener('touchmove', handleMove);\n document.addEventListener('mouseup', handleEnd);\n document.addEventListener('touchend', handleEnd);\n\n // Apply initial position synchronously for immediate feedback\n const initialEvent = event;\n let clientX: number;\n let clientY: number;\n if ('touches' in initialEvent) {\n const touch = initialEvent.touches[0];\n assert(touch);\n clientX = touch.clientX;\n clientY = touch.clientY;\n }\n else {\n clientX = initialEvent.clientX;\n clientY = initialEvent.clientY;\n }\n applyMove(clientX, clientY);\n}\n\nfunction selectByClick(num: number): void {\n const mode = get(editMode);\n if (mode === 'hour') {\n let newHour = num;\n\n if (get(period) === 'PM' && newHour < TWELVE_HOURS) {\n newHour += TWELVE_HOURS;\n }\n\n set(selectedHour, newHour);\n set(editMode, 'minute');\n }\n else if (mode === 'minute') {\n set(selectedMinute, num);\n if (get(showSecond))\n set(editMode, 'second');\n }\n else if (mode === 'second') {\n set(selectedSecond, num);\n if (get(showMillisecond)) {\n set(editMode, 'millisecond');\n }\n }\n else if (mode === 'millisecond') {\n set(selectedMillisecond, num);\n }\n\n updateModelValue();\n}\n\nfunction updateModelValue(): void {\n if (!(isDefined(selectedHour) && isDefined(selectedMinute))) {\n return;\n }\n nextTick(() => {\n const date = isDefined(modelValue) ? new Date(get(modelValue)) : new Date();\n date.setHours(get(selectedHour));\n date.setMinutes(get(selectedMinute));\n date.setSeconds(get(selectedSecond) ?? 0);\n date.setMilliseconds(get(selectedMillisecond) ?? 0);\n set(modelValue, date);\n });\n}\n\nwatch(\n modelValue,\n () => {\n set(selectedHour, getModelHours());\n set(selectedMinute, getModelMinutes());\n set(selectedSecond, getModelSeconds());\n set(selectedMillisecond, getModelMilliseconds());\n },\n);\n\nonMounted(() => {\n set(selectedHour, getModelHours());\n set(selectedMinute, getModelMinutes());\n set(selectedSecond, getModelSeconds());\n set(selectedMillisecond, getModelMilliseconds());\n});\n</script>\n\n<template>\n <div\n role=\"group\"\n aria-label=\"Time picker\"\n :class=\"ui.root({ bordered: !borderless })\"\n >\n <div :class=\"ui.digitalDisplay()\">\n <div :class=\"ui.time()\">\n <button\n type=\"button\"\n data-id=\"hour\"\n :aria-label=\"`${formatValue(displayHour)} hours`\"\n :aria-pressed=\"editMode === 'hour'\"\n :class=\"ui.digit({ active: editMode === 'hour' })\"\n @click=\"editMode = 'hour'\"\n >\n {{ formatValue(displayHour) }}\n </button>\n <div :class=\"ui.separator()\">\n :\n </div>\n <button\n type=\"button\"\n data-id=\"minute\"\n :aria-label=\"`${formatValue(selectedMinute)} minutes`\"\n :aria-pressed=\"editMode === 'minute'\"\n :class=\"ui.digit({ active: editMode === 'minute' })\"\n @click=\"editMode = 'minute'\"\n >\n {{ formatValue(selectedMinute) }}\n </button>\n <div\n v-if=\"showSecond\"\n :class=\"ui.separator()\"\n >\n :\n </div>\n <button\n v-if=\"showSecond\"\n type=\"button\"\n data-id=\"second\"\n :aria-label=\"`${formatValue(selectedSecond)} seconds`\"\n :aria-pressed=\"editMode === 'second'\"\n :class=\"ui.digit({ active: editMode === 'second' })\"\n @click=\"editMode = 'second'\"\n >\n {{ formatValue(selectedSecond) }}\n </button>\n\n <div\n v-if=\"showMillisecond\"\n :class=\"ui.separator({ class: 'text-lg' })\"\n >\n .\n </div>\n\n <button\n v-if=\"showMillisecond\"\n type=\"button\"\n data-id=\"millisecond\"\n :aria-label=\"`${formatValue(selectedMillisecond, 3)} milliseconds`\"\n :aria-pressed=\"editMode === 'millisecond'\"\n :class=\"ui.digit({ active: editMode === 'millisecond', class: 'text-lg' })\"\n @click=\"editMode = 'millisecond'\"\n >\n {{ formatValue(selectedMillisecond, 3) }}\n </button>\n </div>\n <button\n type=\"button\"\n aria-label=\"Toggle AM/PM\"\n :class=\"ui.period()\"\n @click=\"toggleAmPm()\"\n >\n {{ period }}\n </button>\n </div>\n\n <div\n ref=\"clockFace\"\n role=\"listbox\"\n :aria-label=\"`Select ${editMode}`\"\n :class=\"ui.clockFace()\"\n @mousedown=\"startDrag($event)\"\n @touchstart=\"startDrag($event)\"\n >\n <div\n :class=\"ui.centerDot()\"\n :style=\"dotStyle\"\n />\n\n <div\n :class=\"ui.clockHand()\"\n :style=\"clockHandStyle\"\n />\n\n <div\n v-if=\"displayClockHandCircle\"\n :class=\"ui.clockHandCircle()\"\n :style=\"clockHandCircleStyle\"\n />\n\n <div\n v-for=\"num in clockNumbers\"\n :key=\"`num-${num}`\"\n role=\"option\"\n :aria-selected=\"isSelectedNumber(num)\"\n :class=\"[\n ui.clockNumber({ selected: isSelectedNumber(num) }),\n `rui-${editMode}-${num.toString().padStart(2, '0')}`,\n ]\"\n :style=\"numberStyle(num)\"\n @click=\"selectByClick(num)\"\n >\n {{ num }}\n </div>\n </div>\n </div>\n</template>\n"],"mappings":""}
|
|
@@ -4,10 +4,10 @@ import { timePickerStyles } from "./time-picker-styles.js";
|
|
|
4
4
|
import { TimeAccuracy } from "../../consts/time-accuracy.js";
|
|
5
5
|
import { Fragment, computed, createCommentVNode, createElementBlock, createElementVNode, defineComponent, mergeModels, nextTick, normalizeClass, normalizeStyle, onMounted, openBlock, ref, renderList, toDisplayString, unref, useModel, useTemplateRef, watch } from "vue";
|
|
6
6
|
//#region src/components/time-picker/RuiTimePicker.vue?vue&type=script&setup=true&lang.ts
|
|
7
|
-
var _hoisted_1 = ["aria-pressed"];
|
|
8
|
-
var _hoisted_2 = ["aria-pressed"];
|
|
9
|
-
var _hoisted_3 = ["aria-pressed"];
|
|
10
|
-
var _hoisted_4 = ["aria-pressed"];
|
|
7
|
+
var _hoisted_1 = ["aria-label", "aria-pressed"];
|
|
8
|
+
var _hoisted_2 = ["aria-label", "aria-pressed"];
|
|
9
|
+
var _hoisted_3 = ["aria-label", "aria-pressed"];
|
|
10
|
+
var _hoisted_4 = ["aria-label", "aria-pressed"];
|
|
11
11
|
var _hoisted_5 = ["aria-label"];
|
|
12
12
|
var _hoisted_6 = ["aria-selected", "onClick"];
|
|
13
13
|
var FULL_CIRCLE = 360;
|
|
@@ -297,7 +297,8 @@ var RuiTimePicker_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ de
|
|
|
297
297
|
}, [createElementVNode("div", { class: normalizeClass(unref(ui).digitalDisplay()) }, [createElementVNode("div", { class: normalizeClass(unref(ui).time()) }, [
|
|
298
298
|
createElementVNode("button", {
|
|
299
299
|
type: "button",
|
|
300
|
-
"
|
|
300
|
+
"data-id": "hour",
|
|
301
|
+
"aria-label": `${formatValue(displayHour.value)} hours`,
|
|
301
302
|
"aria-pressed": editMode.value === "hour",
|
|
302
303
|
class: normalizeClass(unref(ui).digit({ active: editMode.value === "hour" })),
|
|
303
304
|
onClick: _cache[0] || (_cache[0] = ($event) => editMode.value = "hour")
|
|
@@ -305,7 +306,8 @@ var RuiTimePicker_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ de
|
|
|
305
306
|
createElementVNode("div", { class: normalizeClass(unref(ui).separator()) }, " : ", 2),
|
|
306
307
|
createElementVNode("button", {
|
|
307
308
|
type: "button",
|
|
308
|
-
"
|
|
309
|
+
"data-id": "minute",
|
|
310
|
+
"aria-label": `${formatValue(selectedMinute.value)} minutes`,
|
|
309
311
|
"aria-pressed": editMode.value === "minute",
|
|
310
312
|
class: normalizeClass(unref(ui).digit({ active: editMode.value === "minute" })),
|
|
311
313
|
onClick: _cache[1] || (_cache[1] = ($event) => editMode.value = "minute")
|
|
@@ -317,7 +319,8 @@ var RuiTimePicker_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ de
|
|
|
317
319
|
showSecond.value ? (openBlock(), createElementBlock("button", {
|
|
318
320
|
key: 1,
|
|
319
321
|
type: "button",
|
|
320
|
-
"
|
|
322
|
+
"data-id": "second",
|
|
323
|
+
"aria-label": `${formatValue(selectedSecond.value)} seconds`,
|
|
321
324
|
"aria-pressed": editMode.value === "second",
|
|
322
325
|
class: normalizeClass(unref(ui).digit({ active: editMode.value === "second" })),
|
|
323
326
|
onClick: _cache[2] || (_cache[2] = ($event) => editMode.value = "second")
|
|
@@ -329,7 +332,8 @@ var RuiTimePicker_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ de
|
|
|
329
332
|
showMillisecond.value ? (openBlock(), createElementBlock("button", {
|
|
330
333
|
key: 3,
|
|
331
334
|
type: "button",
|
|
332
|
-
"
|
|
335
|
+
"data-id": "millisecond",
|
|
336
|
+
"aria-label": `${formatValue(selectedMillisecond.value, 3)} milliseconds`,
|
|
333
337
|
"aria-pressed": editMode.value === "millisecond",
|
|
334
338
|
class: normalizeClass(unref(ui).digit({
|
|
335
339
|
active: editMode.value === "millisecond",
|