vectis-ui 0.1.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +40 -6
- package/dist/components/VAccordion/VAccordion.css +1 -1
- package/dist/components/VAccordion/VAccordion.d.ts +9 -16
- package/dist/components/VAccordion/VAccordion.js.map +1 -1
- package/dist/components/VAccordion/VAccordion.vue_vue_type_script_setup_true_lang.js +3 -3
- package/dist/components/VAccordion/VAccordion.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VAccordion/VAccordionItem.css +1 -1
- package/dist/components/VAccordion/VAccordionItem.d.ts +33 -19
- package/dist/components/VAccordion/VAccordionItem.js.map +1 -1
- package/dist/components/VAccordion/VAccordionItem.vue_vue_type_script_setup_true_lang.js +50 -38
- package/dist/components/VAccordion/VAccordionItem.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VAccordion/context.d.ts +1 -8
- package/dist/components/VAccordion/context.js.map +1 -1
- package/dist/components/VAvatar/VAvatar.css +1 -1
- package/dist/components/VAvatar/VAvatar.d.ts +44 -29
- package/dist/components/VAvatar/VAvatar.js.map +1 -1
- package/dist/components/VAvatar/VAvatar.vue_vue_type_script_setup_true_lang.js +38 -35
- package/dist/components/VAvatar/VAvatar.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VAvatar/VAvatarGroup.d.ts +5 -16
- package/dist/components/VAvatar/VAvatarGroup.js.map +1 -1
- package/dist/components/VAvatar/VAvatarGroup.vue_vue_type_script_setup_true_lang.js +7 -7
- package/dist/components/VAvatar/VAvatarGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VAvatar/context.d.ts +6 -10
- package/dist/components/VAvatar/context.js.map +1 -1
- package/dist/components/VBadge/VBadge.css +1 -1
- package/dist/components/VBadge/VBadge.d.ts +31 -10
- package/dist/components/VBadge/VBadge.js.map +1 -1
- package/dist/components/VBadge/VBadge.vue_vue_type_script_setup_true_lang.js +39 -24
- package/dist/components/VBadge/VBadge.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VBreadcrumb/VBreadcrumb.css +1 -1
- package/dist/components/VBreadcrumb/VBreadcrumb.d.ts +4 -17
- package/dist/components/VBreadcrumb/VBreadcrumb.js.map +1 -1
- package/dist/components/VBreadcrumb/VBreadcrumb.vue_vue_type_script_setup_true_lang.js +23 -25
- package/dist/components/VBreadcrumb/VBreadcrumb.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VButton/VButton.css +1 -1
- package/dist/components/VButton/VButton.d.ts +30 -10
- package/dist/components/VButton/VButton.js.map +1 -1
- package/dist/components/VButton/VButton.vue_vue_type_script_setup_true_lang.js +39 -30
- package/dist/components/VButton/VButton.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VButton/VButtonGroup.css +1 -1
- package/dist/components/VButton/VButtonGroup.d.ts +76 -13
- package/dist/components/VButton/VButtonGroup.js.map +1 -1
- package/dist/components/VButton/VButtonGroup.vue_vue_type_script_setup_true_lang.js +74 -8
- package/dist/components/VButton/VButtonGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VButton/context.d.ts +30 -0
- package/dist/components/VButton/context.js +6 -0
- package/dist/components/VButton/context.js.map +1 -0
- package/dist/components/VCalendar/VCalendar.css +1 -1
- package/dist/components/VCalendar/VCalendar.d.ts +50 -36
- package/dist/components/VCalendar/VCalendar.js.map +1 -1
- package/dist/components/VCalendar/VCalendar.vue_vue_type_script_setup_true_lang.js +99 -85
- package/dist/components/VCalendar/VCalendar.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VCalendar/VCalendarEvent.css +1 -1
- package/dist/components/VCalendar/VCalendarEvent.d.ts +5 -11
- package/dist/components/VCalendar/VCalendarEvent.js.map +1 -1
- package/dist/components/VCalendar/VCalendarEvent.vue_vue_type_script_setup_true_lang.js +7 -1
- package/dist/components/VCalendar/VCalendarEvent.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VCalendar/VCalendarMonth.css +1 -1
- package/dist/components/VCalendar/VCalendarMonth.d.ts +10 -13
- package/dist/components/VCalendar/VCalendarMonth.js.map +1 -1
- package/dist/components/VCalendar/VCalendarMonth.vue_vue_type_script_setup_true_lang.js +183 -244
- package/dist/components/VCalendar/VCalendarMonth.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VCalendar/VCalendarTimeGrid.css +1 -1
- package/dist/components/VCalendar/VCalendarTimeGrid.d.ts +15 -20
- package/dist/components/VCalendar/VCalendarTimeGrid.js.map +1 -1
- package/dist/components/VCalendar/VCalendarTimeGrid.vue_vue_type_script_setup_true_lang.js +385 -448
- package/dist/components/VCalendar/VCalendarTimeGrid.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VCalendar/VCalendarYear.css +1 -1
- package/dist/components/VCalendar/VCalendarYear.js.map +1 -1
- package/dist/components/VCalendar/VCalendarYear.vue_vue_type_script_setup_true_lang.js +53 -49
- package/dist/components/VCalendar/VCalendarYear.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VCalendar/gesture.d.ts +158 -0
- package/dist/components/VCalendar/gesture.js +170 -0
- package/dist/components/VCalendar/gesture.js.map +1 -0
- package/dist/components/VCalendar/keyboard.d.ts +9 -3
- package/dist/components/VCalendar/keyboard.js +2 -6
- package/dist/components/VCalendar/keyboard.js.map +1 -1
- package/dist/components/VCalendar/layout.d.ts +67 -54
- package/dist/components/VCalendar/layout.js +77 -69
- package/dist/components/VCalendar/layout.js.map +1 -1
- package/dist/components/VCalendar/timeGrid.d.ts +55 -0
- package/dist/components/VCalendar/timeGrid.js +71 -0
- package/dist/components/VCalendar/timeGrid.js.map +1 -0
- package/dist/components/VCalendar/types.d.ts +41 -16
- package/dist/components/VCarousel/VCarousel.css +1 -1
- package/dist/components/VCarousel/VCarousel.d.ts +21 -41
- package/dist/components/VCarousel/VCarousel.js.map +1 -1
- package/dist/components/VCarousel/VCarousel.vue_vue_type_script_setup_true_lang.js +157 -129
- package/dist/components/VCarousel/VCarousel.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VCarousel/VCarouselItem.d.ts +0 -17
- package/dist/components/VCarousel/VCarouselItem.js.map +1 -1
- package/dist/components/VCarousel/VCarouselItem.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VCarousel/context.d.ts +0 -12
- package/dist/components/VCarousel/context.js.map +1 -1
- package/dist/components/VCheckbox/VCheckbox.css +1 -1
- package/dist/components/VCheckbox/VCheckbox.d.ts +31 -16
- package/dist/components/VCheckbox/VCheckbox.js.map +1 -1
- package/dist/components/VCheckbox/VCheckbox.vue_vue_type_script_setup_true_lang.js +62 -29
- package/dist/components/VCheckbox/VCheckbox.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VChip/VChip.css +1 -1
- package/dist/components/VChip/VChip.d.ts +36 -26
- package/dist/components/VChip/VChip.js.map +1 -1
- package/dist/components/VChip/VChip.vue_vue_type_script_setup_true_lang.js +57 -48
- package/dist/components/VChip/VChip.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VCombobox/VCombobox.css +1 -1
- package/dist/components/VCombobox/VCombobox.d.ts +127 -31
- package/dist/components/VCombobox/VCombobox.js.map +1 -1
- package/dist/components/VCombobox/VCombobox.vue_vue_type_script_setup_true_lang.js +336 -247
- package/dist/components/VCombobox/VCombobox.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VCombobox/VComboboxGroup.css +1 -1
- package/dist/components/VCombobox/VComboboxGroup.d.ts +0 -9
- package/dist/components/VCombobox/VComboboxGroup.js.map +1 -1
- package/dist/components/VCombobox/VComboboxGroup.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/components/VCombobox/VComboboxGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VCombobox/VComboboxOption.css +1 -1
- package/dist/components/VCombobox/VComboboxOption.d.ts +0 -15
- package/dist/components/VCombobox/VComboboxOption.js.map +1 -1
- package/dist/components/VCombobox/VComboboxOption.vue_vue_type_script_setup_true_lang.js +4 -4
- package/dist/components/VCombobox/VComboboxOption.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VCombobox/VComboboxSeparator.js.map +1 -1
- package/dist/components/VCombobox/VComboboxSeparator.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VCombobox/infiniteScroll.js.map +1 -1
- package/dist/components/VDataTable/VDataTable.css +1 -1
- package/dist/components/VDataTable/VDataTable.d.ts +50 -28
- package/dist/components/VDataTable/VDataTable.js.map +1 -1
- package/dist/components/VDataTable/VDataTable.vue_vue_type_script_setup_true_lang.js +183 -194
- package/dist/components/VDataTable/VDataTable.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VDateInput/VDateInput.css +1 -1
- package/dist/components/VDateInput/VDateInput.d.ts +90 -42
- package/dist/components/VDateInput/VDateInput.js.map +1 -1
- package/dist/components/VDateInput/VDateInput.vue_vue_type_script_setup_true_lang.js +159 -191
- package/dist/components/VDateInput/VDateInput.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VDatePicker/VDatePicker.css +1 -1
- package/dist/components/VDatePicker/VDatePicker.d.ts +61 -30
- package/dist/components/VDatePicker/VDatePicker.js.map +1 -1
- package/dist/components/VDatePicker/VDatePicker.vue_vue_type_script_setup_true_lang.js +243 -221
- package/dist/components/VDatePicker/VDatePicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VDialog/VDialog.css +1 -1
- package/dist/components/VDialog/VDialog.d.ts +45 -33
- package/dist/components/VDialog/VDialog.js.map +1 -1
- package/dist/components/VDialog/VDialog.vue_vue_type_script_setup_true_lang.js +65 -64
- package/dist/components/VDialog/VDialog.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VDialog/VDialogAlert.d.ts +24 -20
- package/dist/components/VDialog/VDialogAlert.js.map +1 -1
- package/dist/components/VDialog/VDialogAlert.vue_vue_type_script_setup_true_lang.js +36 -25
- package/dist/components/VDialog/VDialogAlert.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VFileInput/VFileInput.css +1 -1
- package/dist/components/VFileInput/VFileInput.d.ts +78 -26
- package/dist/components/VFileInput/VFileInput.js.map +1 -1
- package/dist/components/VFileInput/VFileInput.vue_vue_type_script_setup_true_lang.js +144 -132
- package/dist/components/VFileInput/VFileInput.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VFilePicker/VFilePicker.css +1 -1
- package/dist/components/VFilePicker/VFilePicker.d.ts +47 -30
- package/dist/components/VFilePicker/VFilePicker.js.map +1 -1
- package/dist/components/VFilePicker/VFilePicker.vue_vue_type_script_setup_true_lang.js +166 -163
- package/dist/components/VFilePicker/VFilePicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VFilePicker/fileKind.d.ts +2 -27
- package/dist/components/VFilePicker/fileKind.js +9 -8
- package/dist/components/VFilePicker/fileKind.js.map +1 -1
- package/dist/components/VHotkeys/VHotkeys.css +1 -1
- package/dist/components/VHotkeys/VHotkeys.d.ts +8 -30
- package/dist/components/VHotkeys/VHotkeys.js.map +1 -1
- package/dist/components/VHotkeys/VHotkeys.vue_vue_type_script_setup_true_lang.js +4 -4
- package/dist/components/VHotkeys/VHotkeys.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VHotkeys/platform.js.map +1 -1
- package/dist/components/VIcon/VIcon.css +1 -1
- package/dist/components/VIcon/VIcon.d.ts +15 -6
- package/dist/components/VIcon/VIcon.js.map +1 -1
- package/dist/components/VIcon/VIcon.vue_vue_type_script_setup_true_lang.js +45 -37
- package/dist/components/VIcon/VIcon.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VIcon/iconProps.js.map +1 -1
- package/dist/components/VIcon/icons/index.d.ts +1 -1
- package/dist/components/VIcon/icons/index.js.map +1 -1
- package/dist/components/VIcon/icons/names.d.ts +1 -1
- package/dist/components/VIcon/icons/names.js.map +1 -1
- package/dist/components/VIcon/resolver.d.ts +3 -3
- package/dist/components/VIcon/resolver.js.map +1 -1
- package/dist/components/VIcon/types.d.ts +12 -12
- package/dist/components/VIconButton/VIconButton.css +1 -1
- package/dist/components/VIconButton/VIconButton.d.ts +28 -11
- package/dist/components/VIconButton/VIconButton.js.map +1 -1
- package/dist/components/VIconButton/VIconButton.vue_vue_type_script_setup_true_lang.js +26 -20
- package/dist/components/VIconButton/VIconButton.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VInput/VInput.css +1 -1
- package/dist/components/VInput/VInput.d.ts +26 -7
- package/dist/components/VInput/VInput.js.map +1 -1
- package/dist/components/VInput/VInput.vue_vue_type_script_setup_true_lang.js +86 -75
- package/dist/components/VInput/VInput.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VInput/VInputGroup.css +2 -0
- package/dist/components/VInput/VInputGroup.d.ts +47 -0
- package/dist/components/VInput/VInputGroup.js +9 -0
- package/dist/components/VInput/VInputGroup.js.map +1 -0
- package/dist/components/VInput/VInputGroup.vue_vue_type_script_setup_true_lang.js +80 -0
- package/dist/components/VInput/VInputGroup.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VInput/context.d.ts +11 -0
- package/dist/components/VInput/context.js +6 -0
- package/dist/components/VInput/context.js.map +1 -0
- package/dist/components/VInputOTP/VInputOTP.css +1 -1
- package/dist/components/VInputOTP/VInputOTP.d.ts +37 -22
- package/dist/components/VInputOTP/VInputOTP.js.map +1 -1
- package/dist/components/VInputOTP/VInputOTP.vue_vue_type_script_setup_true_lang.js +98 -61
- package/dist/components/VInputOTP/VInputOTP.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VMenu/VMenu.d.ts +23 -30
- package/dist/components/VMenu/VMenu.js.map +1 -1
- package/dist/components/VMenu/VMenu.vue_vue_type_script_setup_true_lang.js +31 -27
- package/dist/components/VMenu/VMenu.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VMenu/VMenuGroup.css +1 -1
- package/dist/components/VMenu/VMenuGroup.d.ts +12 -8
- package/dist/components/VMenu/VMenuGroup.js.map +1 -1
- package/dist/components/VMenu/VMenuGroup.vue_vue_type_script_setup_true_lang.js +11 -11
- package/dist/components/VMenu/VMenuGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VMenu/VMenuItem.css +1 -1
- package/dist/components/VMenu/VMenuItem.d.ts +11 -19
- package/dist/components/VMenu/VMenuItem.js.map +1 -1
- package/dist/components/VMenu/VMenuItem.vue_vue_type_script_setup_true_lang.js +65 -57
- package/dist/components/VMenu/VMenuItem.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VMenu/VMenuPanel.d.ts +14 -30
- package/dist/components/VMenu/VMenuPanel.js.map +1 -1
- package/dist/components/VMenu/VMenuPanel.vue_vue_type_script_setup_true_lang.js +43 -44
- package/dist/components/VMenu/VMenuPanel.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VMenu/context.d.ts +2 -6
- package/dist/components/VMenu/context.js.map +1 -1
- package/dist/components/VPagination/VPagination.css +1 -1
- package/dist/components/VPagination/VPagination.d.ts +60 -22
- package/dist/components/VPagination/VPagination.js.map +1 -1
- package/dist/components/VPagination/VPagination.vue_vue_type_script_setup_true_lang.js +113 -161
- package/dist/components/VPagination/VPagination.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VPopover/VPopover.css +1 -1
- package/dist/components/VPopover/VPopover.d.ts +26 -7
- package/dist/components/VPopover/VPopover.js.map +1 -1
- package/dist/components/VPopover/VPopover.vue_vue_type_script_setup_true_lang.js +43 -37
- package/dist/components/VPopover/VPopover.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VProgressCircular/VProgressCircular.css +1 -1
- package/dist/components/VProgressCircular/VProgressCircular.d.ts +15 -4
- package/dist/components/VProgressCircular/VProgressCircular.js.map +1 -1
- package/dist/components/VProgressCircular/VProgressCircular.vue_vue_type_script_setup_true_lang.js +32 -30
- package/dist/components/VProgressCircular/VProgressCircular.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VProgressLinear/VProgressLinear.css +1 -1
- package/dist/components/VProgressLinear/VProgressLinear.d.ts +23 -8
- package/dist/components/VProgressLinear/VProgressLinear.js.map +1 -1
- package/dist/components/VProgressLinear/VProgressLinear.vue_vue_type_script_setup_true_lang.js +34 -32
- package/dist/components/VProgressLinear/VProgressLinear.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VRadio/VRadio.css +1 -1
- package/dist/components/VRadio/VRadio.d.ts +36 -18
- package/dist/components/VRadio/VRadio.js.map +1 -1
- package/dist/components/VRadio/VRadio.vue_vue_type_script_setup_true_lang.js +55 -26
- package/dist/components/VRadio/VRadio.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VSeparator/VSeparator.d.ts +4 -2
- package/dist/components/VSeparator/VSeparator.js.map +1 -1
- package/dist/components/VSeparator/VSeparator.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VSideNavigation/VSideNavigation.css +1 -1
- package/dist/components/VSideNavigation/VSideNavigation.d.ts +5 -19
- package/dist/components/VSideNavigation/VSideNavigation.js.map +1 -1
- package/dist/components/VSideNavigation/VSideNavigation.vue_vue_type_script_setup_true_lang.js +5 -5
- package/dist/components/VSideNavigation/VSideNavigation.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VSideNavigation/VSideNavigationGroup.css +1 -1
- package/dist/components/VSideNavigation/VSideNavigationGroup.d.ts +9 -17
- package/dist/components/VSideNavigation/VSideNavigationGroup.js.map +1 -1
- package/dist/components/VSideNavigation/VSideNavigationGroup.vue_vue_type_script_setup_true_lang.js +2 -2
- package/dist/components/VSideNavigation/VSideNavigationGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VSideNavigation/VSideNavigationItem.css +1 -1
- package/dist/components/VSideNavigation/VSideNavigationItem.d.ts +22 -30
- package/dist/components/VSideNavigation/VSideNavigationItem.js.map +1 -1
- package/dist/components/VSideNavigation/VSideNavigationItem.vue_vue_type_script_setup_true_lang.js +77 -87
- package/dist/components/VSideNavigation/VSideNavigationItem.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VSideNavigation/context.d.ts +0 -14
- package/dist/components/VSideNavigation/context.js.map +1 -1
- package/dist/components/VSkeletonLoader/VSkeletonLoader.css +1 -1
- package/dist/components/VSkeletonLoader/VSkeletonLoader.d.ts +9 -9
- package/dist/components/VSkeletonLoader/VSkeletonLoader.js.map +1 -1
- package/dist/components/VSkeletonLoader/VSkeletonLoader.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VSlider/VSlider.css +1 -1
- package/dist/components/VSlider/VSlider.d.ts +52 -27
- package/dist/components/VSlider/VSlider.js.map +1 -1
- package/dist/components/VSlider/VSlider.vue_vue_type_script_setup_true_lang.js +202 -118
- package/dist/components/VSlider/VSlider.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VSnackbar/VSnackbar.css +1 -1
- package/dist/components/VSnackbar/VSnackbar.d.ts +0 -23
- package/dist/components/VSnackbar/VSnackbar.js.map +1 -1
- package/dist/components/VSnackbar/VSnackbar.vue_vue_type_script_setup_true_lang.js +38 -38
- package/dist/components/VSnackbar/VSnackbar.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VSnackbar/state.d.ts +0 -27
- package/dist/components/VSnackbar/state.js.map +1 -1
- package/dist/components/VSpinner/VSpinner.css +1 -1
- package/dist/components/VSpinner/VSpinner.d.ts +6 -6
- package/dist/components/VSpinner/VSpinner.js.map +1 -1
- package/dist/components/VSpinner/VSpinner.vue_vue_type_script_setup_true_lang.js +10 -9
- package/dist/components/VSpinner/VSpinner.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VSwitch/VSwitch.css +1 -1
- package/dist/components/VSwitch/VSwitch.d.ts +35 -13
- package/dist/components/VSwitch/VSwitch.js.map +1 -1
- package/dist/components/VSwitch/VSwitch.vue_vue_type_script_setup_true_lang.js +62 -21
- package/dist/components/VSwitch/VSwitch.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VTabs/VTab.css +1 -1
- package/dist/components/VTabs/VTab.d.ts +12 -12
- package/dist/components/VTabs/VTab.js.map +1 -1
- package/dist/components/VTabs/VTab.vue_vue_type_script_setup_true_lang.js +36 -24
- package/dist/components/VTabs/VTab.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VTabs/VTabPanel.d.ts +2 -10
- package/dist/components/VTabs/VTabPanel.js.map +1 -1
- package/dist/components/VTabs/VTabPanel.vue_vue_type_script_setup_true_lang.js +4 -4
- package/dist/components/VTabs/VTabPanel.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VTabs/VTabs.css +1 -1
- package/dist/components/VTabs/VTabs.d.ts +27 -18
- package/dist/components/VTabs/VTabs.js.map +1 -1
- package/dist/components/VTabs/VTabs.vue_vue_type_script_setup_true_lang.js +92 -81
- package/dist/components/VTabs/VTabs.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VTabs/context.d.ts +9 -19
- package/dist/components/VTabs/context.js +1 -1
- package/dist/components/VTabs/context.js.map +1 -1
- package/dist/components/VTextarea/VTextarea.css +1 -1
- package/dist/components/VTextarea/VTextarea.d.ts +34 -6
- package/dist/components/VTextarea/VTextarea.js.map +1 -1
- package/dist/components/VTextarea/VTextarea.vue_vue_type_script_setup_true_lang.js +91 -74
- package/dist/components/VTextarea/VTextarea.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VTimeInput/VTimeInput.css +1 -1
- package/dist/components/VTimeInput/VTimeInput.d.ts +123 -33
- package/dist/components/VTimeInput/VTimeInput.js.map +1 -1
- package/dist/components/VTimeInput/VTimeInput.vue_vue_type_script_setup_true_lang.js +294 -291
- package/dist/components/VTimeInput/VTimeInput.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VTimeInput/search.d.ts +24 -0
- package/dist/components/VTimeInput/search.js +22 -0
- package/dist/components/VTimeInput/search.js.map +1 -0
- package/dist/components/VTimePicker/VTimePicker.css +1 -1
- package/dist/components/VTimePicker/VTimePicker.d.ts +51 -30
- package/dist/components/VTimePicker/VTimePicker.js.map +1 -1
- package/dist/components/VTimePicker/VTimePicker.vue_vue_type_script_setup_true_lang.js +216 -151
- package/dist/components/VTimePicker/VTimePicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VTimePicker/limits.d.ts +88 -0
- package/dist/components/VTimePicker/limits.js +70 -0
- package/dist/components/VTimePicker/limits.js.map +1 -0
- package/dist/components/VToast/VToast.css +1 -1
- package/dist/components/VToast/VToast.d.ts +0 -10
- package/dist/components/VToast/VToast.js.map +1 -1
- package/dist/components/VToast/VToast.vue_vue_type_script_setup_true_lang.js +10 -10
- package/dist/components/VToast/VToast.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VToast/VToaster.css +1 -1
- package/dist/components/VToast/VToaster.d.ts +0 -17
- package/dist/components/VToast/VToaster.js.map +1 -1
- package/dist/components/VToast/VToaster.vue_vue_type_script_setup_true_lang.js +29 -28
- package/dist/components/VToast/VToaster.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VToast/state.d.ts +10 -19
- package/dist/components/VToast/state.js +1 -1
- package/dist/components/VToast/state.js.map +1 -1
- package/dist/components/VToggle/VToggle.css +1 -1
- package/dist/components/VToggle/VToggle.d.ts +56 -11
- package/dist/components/VToggle/VToggle.js.map +1 -1
- package/dist/components/VToggle/VToggle.vue_vue_type_script_setup_true_lang.js +80 -46
- package/dist/components/VToggle/VToggle.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VToggle/VToggleItem.d.ts +16 -2
- package/dist/components/VToggle/VToggleItem.js +0 -2
- package/dist/components/VToggle/VToggleItem.js.map +1 -1
- package/dist/components/VToggle/VToggleItem.vue_vue_type_script_setup_true_lang.js +23 -15
- package/dist/components/VToggle/VToggleItem.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VToggle/context.d.ts +4 -24
- package/dist/components/VToggle/context.js.map +1 -1
- package/dist/components/VTooltip/VTooltip.css +1 -1
- package/dist/components/VTooltip/VTooltip.d.ts +9 -33
- package/dist/components/VTooltip/VTooltip.js.map +1 -1
- package/dist/components/VTooltip/VTooltip.vue_vue_type_script_setup_true_lang.js +28 -24
- package/dist/components/VTooltip/VTooltip.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VTypography/VTypography.js.map +1 -1
- package/dist/components/VTypography/VTypography.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/composables/useAriaLabel.d.ts +0 -17
- package/dist/composables/useAriaLabel.js.map +1 -1
- package/dist/composables/useClearable.d.ts +42 -0
- package/dist/composables/useClearable.js +19 -0
- package/dist/composables/useClearable.js.map +1 -0
- package/dist/composables/useControlShape.d.ts +22 -0
- package/dist/composables/useControlShape.js +13 -0
- package/dist/composables/useControlShape.js.map +1 -0
- package/dist/composables/useDetailsOpen.d.ts +22 -0
- package/dist/composables/useDetailsOpen.js +21 -0
- package/dist/composables/useDetailsOpen.js.map +1 -0
- package/dist/composables/useFieldIds.d.ts +0 -15
- package/dist/composables/useFieldIds.js +8 -7
- package/dist/composables/useFieldIds.js.map +1 -1
- package/dist/composables/useFieldPanel.d.ts +21 -18
- package/dist/composables/useFieldPanel.js +43 -23
- package/dist/composables/useFieldPanel.js.map +1 -1
- package/dist/composables/useFileDrop.d.ts +0 -22
- package/dist/composables/useFileDrop.js.map +1 -1
- package/dist/composables/useFileField.d.ts +45 -17
- package/dist/composables/useFileField.js +40 -20
- package/dist/composables/useFileField.js.map +1 -1
- package/dist/composables/useFocusoutDismiss.d.ts +0 -15
- package/dist/composables/useFocusoutDismiss.js.map +1 -1
- package/dist/composables/useIconClickHandlers.d.ts +29 -14
- package/dist/composables/useIconClickHandlers.js +15 -5
- package/dist/composables/useIconClickHandlers.js.map +1 -1
- package/dist/composables/useInertLink.d.ts +20 -0
- package/dist/composables/useInertLink.js +23 -0
- package/dist/composables/useInertLink.js.map +1 -0
- package/dist/composables/useMaskedField.d.ts +33 -10
- package/dist/composables/useMaskedField.js +45 -1
- package/dist/composables/useMaskedField.js.map +1 -1
- package/dist/composables/usePopover.d.ts +15 -1
- package/dist/composables/usePopover.js +23 -8
- package/dist/composables/usePopover.js.map +1 -1
- package/dist/composables/useProgressValue.d.ts +5 -8
- package/dist/composables/useProgressValue.js +6 -3
- package/dist/composables/useProgressValue.js.map +1 -1
- package/dist/composables/useRootAttrs.d.ts +12 -19
- package/dist/composables/useRootAttrs.js.map +1 -1
- package/dist/composables/useTimer.d.ts +8 -10
- package/dist/composables/useTimer.js.map +1 -1
- package/dist/i18n/en.d.ts +2 -10
- package/dist/i18n/en.js +18 -19
- package/dist/i18n/en.js.map +1 -1
- package/dist/i18n/fr.d.ts +2 -18
- package/dist/i18n/fr.js +18 -19
- package/dist/i18n/fr.js.map +1 -1
- package/dist/i18n/state.d.ts +44 -47
- package/dist/i18n/state.js +20 -17
- package/dist/i18n/state.js.map +1 -1
- package/dist/i18n/types.d.ts +53 -44
- package/dist/icons.d.ts +3 -3
- package/dist/index.d.ts +43 -17
- package/dist/index.js +45 -44
- package/dist/styles.css +1 -1
- package/dist/tokens/css.js.map +1 -1
- package/dist/tokens/index.d.ts +5 -1
- package/dist/tokens/primitives.js.map +1 -1
- package/dist/tokens/semantic.d.ts +5 -1
- package/dist/tokens/semantic.js +6 -2
- package/dist/tokens/semantic.js.map +1 -1
- package/dist/tokens/themes/dark.js.map +1 -1
- package/dist/tokens/types.d.ts +7 -15
- package/dist/tokens/types.js.map +1 -1
- package/dist/tokens.json +25 -5
- package/dist/types.d.ts +24 -0
- package/dist/utils/array.d.ts +3 -6
- package/dist/utils/array.js.map +1 -1
- package/dist/utils/arrowNav.d.ts +17 -17
- package/dist/utils/arrowNav.js +5 -3
- package/dist/utils/arrowNav.js.map +1 -1
- package/dist/utils/chip.d.ts +11 -15
- package/dist/utils/chip.js.map +1 -1
- package/dist/utils/css.d.ts +22 -11
- package/dist/utils/css.js +5 -2
- package/dist/utils/css.js.map +1 -1
- package/dist/utils/date.d.ts +42 -19
- package/dist/utils/date.js +97 -98
- package/dist/utils/date.js.map +1 -1
- package/dist/utils/direction.d.ts +6 -12
- package/dist/utils/direction.js.map +1 -1
- package/dist/utils/env.d.ts +5 -6
- package/dist/utils/file.d.ts +46 -58
- package/dist/utils/file.js +43 -36
- package/dist/utils/file.js.map +1 -1
- package/dist/utils/focus.d.ts +8 -17
- package/dist/utils/focus.js.map +1 -1
- package/dist/utils/hostWarns.d.ts +12 -0
- package/dist/utils/hostWarns.js +6 -0
- package/dist/utils/hostWarns.js.map +1 -0
- package/dist/utils/ids.d.ts +10 -0
- package/dist/utils/ids.js +8 -0
- package/dist/utils/ids.js.map +1 -0
- package/dist/utils/matcher.d.ts +5 -9
- package/dist/utils/matcher.js.map +1 -1
- package/dist/utils/memo.d.ts +12 -0
- package/dist/utils/memo.js +9 -0
- package/dist/utils/memo.js.map +1 -0
- package/dist/utils/number.d.ts +3 -4
- package/dist/utils/number.js.map +1 -1
- package/dist/utils/text.d.ts +20 -9
- package/dist/utils/text.js +17 -3
- package/dist/utils/text.js.map +1 -1
- package/dist/utils/time.d.ts +53 -61
- package/dist/utils/time.js +49 -45
- package/dist/utils/time.js.map +1 -1
- package/dist/utils/vnode.d.ts +8 -15
- package/dist/utils/vnode.js.map +1 -1
- package/package.json +6 -6
- package/dist/components/VToggle/VToggleItem.css +0 -2
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
@layer vectis.reset, vectis.tokens, vectis.components, vectis.utilities;
|
|
2
|
-
@layer vectis.components{.v-slider{--slider-thumb:var(--vectis-control-size-slider-thumb);--slider-track:var(--vectis-control-size-slider-track);align-items:center;column-gap:var(--vectis-space-2);row-gap:var(--vectis-space-1);width:100%;font-family:var(--vectis-text-family);grid-template-columns:minmax(0,1fr);grid-template-areas:"rail";display:grid}.v-slider:has(.v-slider-labels){grid-template-areas:"rail""labels"}.v-slider:has(.v-slider-field-end){grid-template-columns:minmax(0,1fr) auto;grid-template-areas:"rail field-end"}.v-slider:has(.v-slider-field-end):has(.v-slider-labels){grid-template-areas:"rail field-end""labels."}.v-slider:has(.v-slider-field-start){grid-template-columns:auto minmax(0,1fr) auto;grid-template-areas:"field-start rail field-end"}.v-slider:has(.v-slider-field-start):has(.v-slider-labels){grid-template-areas:"field-start rail field-end"".labels."}.v-slider-rail{block-size:var(--slider-thumb);grid-area:rail;position:relative}.v-slider-control{position:absolute;inset:0}.v-slider-track{block-size:var(--slider-track);border-radius:var(--vectis-radius-
|
|
2
|
+
@layer vectis.components{.v-slider{--slider-thumb:var(--vectis-control-size-slider-thumb);--slider-track:var(--vectis-control-size-slider-track);align-items:center;column-gap:var(--vectis-space-2);row-gap:var(--vectis-space-1);width:100%;font-family:var(--vectis-text-family);grid-template-columns:minmax(0,1fr);grid-template-areas:"rail";display:grid}.v-slider:has(.v-slider-labels){grid-template-areas:"rail""labels"}.v-slider:has(.v-slider-field-end){grid-template-columns:minmax(0,1fr) auto;grid-template-areas:"rail field-end"}.v-slider:has(.v-slider-field-end):has(.v-slider-labels){grid-template-areas:"rail field-end""labels."}.v-slider:has(.v-slider-field-start){grid-template-columns:auto minmax(0,1fr) auto;grid-template-areas:"field-start rail field-end"}.v-slider:has(.v-slider-field-start):has(.v-slider-labels){grid-template-areas:"field-start rail field-end"".labels."}.v-slider-rail{block-size:var(--slider-thumb);grid-area:rail;position:relative}.v-slider-control{position:absolute;inset:0}.v-slider-track{block-size:var(--slider-track);border-radius:var(--vectis-radius-pill);background:var(--vectis-color-border);margin-block:auto;position:absolute;inset-block:0;inset-inline:0;overflow:hidden}.v-slider-fill,.v-slider-tick,.v-slider-tooltip,.v-slider-label{--slider-at:calc(var(--slider-thumb) / 2 + (100% - var(--slider-thumb)) * var(--fill-fraction))}.v-slider-fill{--fill-fraction:var(--end-fraction);inline-size:var(--slider-at);background:var(--vectis-color-accent);position:absolute;inset-block:0;inset-inline-start:0}.v-slider[data-range] .v-slider-fill{--fill-fraction:var(--start-fraction);inline-size:calc((100% - var(--slider-thumb)) * (var(--end-fraction) - var(--start-fraction)));inset-inline-start:var(--slider-at)}.v-slider-tick{--slider-tick:calc(var(--slider-track) / 3 * 2);inline-size:var(--slider-tick);block-size:var(--slider-tick);border-radius:var(--vectis-radius-pill);background:var(--vectis-color-border-strong);margin-block:auto;position:absolute;inset-block:0;inset-inline-start:calc(var(--slider-at) - var(--slider-tick) / 2)}.v-slider-tick[data-filled]{background:var(--vectis-color-text-on-accent)}.v-slider-input{--slider-thumb-bg:var(--vectis-color-text-on-accent);--slider-thumb-border:var(--vectis-color-accent);--slider-thumb-shadow:var(--vectis-shadow-xs);--slider-thumb-outline:none;--slider-thumb-cursor:pointer;--slider-thumb-transition:background-color var(--vectis-duration-fast) var(--vectis-ease-default);appearance:none;pointer-events:none;background:0 0;width:100%;height:100%;margin:0;position:absolute;inset:0}.v-slider:not([data-range]) .v-slider-input{pointer-events:auto;cursor:pointer}.v-slider-input::-webkit-slider-thumb{appearance:none;pointer-events:auto;width:var(--slider-thumb);height:var(--slider-thumb);border-radius:var(--vectis-radius-pill);background:var(--slider-thumb-bg);border:var(--vectis-control-border-width) solid var(--slider-thumb-border);box-shadow:var(--slider-thumb-shadow);outline:var(--slider-thumb-outline);outline-offset:var(--vectis-focus-ring-offset);cursor:var(--slider-thumb-cursor);transition:var(--slider-thumb-transition)}.v-slider-input::-moz-range-thumb{pointer-events:auto;width:var(--slider-thumb);height:var(--slider-thumb);border-radius:var(--vectis-radius-pill);background:var(--slider-thumb-bg);border:var(--vectis-control-border-width) solid var(--slider-thumb-border);box-shadow:var(--slider-thumb-shadow);outline:var(--slider-thumb-outline);outline-offset:var(--vectis-focus-ring-offset);cursor:var(--slider-thumb-cursor);transition:var(--slider-thumb-transition)}.v-slider-input:is(:hover,:active):not(:disabled){--slider-thumb-bg:color-mix(in oklab, var(--vectis-color-text-on-accent), var(--vectis-color-accent) 10%)}.v-slider-input:focus-visible{--slider-thumb-outline:var(--vectis-focus-ring-width) solid var(--vectis-focus-ring-color);outline:none}.v-slider[data-readonly] .v-slider-input{--slider-thumb-bg:var(--vectis-color-surface);--slider-thumb-border:var(--vectis-color-text-muted);--slider-thumb-cursor:default;cursor:default}.v-slider[data-readonly] .v-slider-fill{background:var(--vectis-color-text-muted)}.v-slider[data-readonly] .v-slider-tick[data-filled]{background:var(--vectis-color-surface)}.v-slider[data-invalid] .v-slider-input{--slider-thumb-border:var(--vectis-color-danger)}.v-slider-tooltip{opacity:0;visibility:hidden;inline-size:0;transition:opacity var(--vectis-duration-fast) var(--vectis-ease-default), visibility var(--vectis-duration-fast) var(--vectis-ease-default);justify-content:center;display:flex;position:absolute;inset-block-end:calc(100% + var(--vectis-space-2));inset-inline-start:var(--slider-at)}.v-slider-tooltip-start{--fill-fraction:var(--start-fraction)}.v-slider-tooltip-end{--fill-fraction:var(--end-fraction)}.v-slider:has(.v-slider-input-start:active) .v-slider-tooltip-start,.v-slider:has(.v-slider-input-start:focus-visible) .v-slider-tooltip-start,.v-slider:has(.v-slider-input-end:active) .v-slider-tooltip-end,.v-slider:has(.v-slider-input-end:focus-visible) .v-slider-tooltip-end{opacity:1;visibility:visible}.v-slider-tooltip-bubble{padding:var(--vectis-space-1) var(--vectis-space-2);background:var(--vectis-color-surface-inverse);color:var(--vectis-color-text-on-inverse);font-size:var(--vectis-text-caption-size);line-height:var(--vectis-text-caption-leading);border-radius:min(var(--vectis-radius-interactive), calc(.5lh + var(--vectis-space-1)));box-shadow:var(--vectis-shadow-sm);white-space:nowrap}.v-slider-labels{min-block-size:var(--vectis-icon-size-md);--vectis-icon-size:var(--vectis-icon-size-md);font-size:var(--vectis-text-caption-size);color:var(--vectis-color-text-muted);grid-area:labels;position:relative}.v-slider-label{white-space:nowrap;justify-content:center;inline-size:0;display:flex;position:absolute;inset-block-start:0;inset-inline-start:var(--slider-at)}.v-slider-field.v-input{inline-size:var(--vectis-control-size-slider-field)}.v-slider-field-start{grid-area:field-start}.v-slider-field-end{grid-area:field-end}.v-slider[data-orientation=vertical]{grid-template-columns:none;grid-template-areas:"rail";justify-items:center;inline-size:fit-content}.v-slider[data-orientation=vertical]:has(.v-slider-labels){grid-template-columns:auto auto;grid-template-areas:"rail labels"}.v-slider[data-orientation=vertical]:has(.v-slider-field-end){grid-template-columns:none;grid-template-areas:"field-end""rail"}.v-slider[data-orientation=vertical]:has(.v-slider-field-end):has(.v-slider-labels){grid-template-columns:auto auto;grid-template-areas:"field-end.""rail labels"}.v-slider[data-orientation=vertical]:has(.v-slider-field-start){grid-template-columns:none;grid-template-areas:"field-end""rail""field-start"}.v-slider[data-orientation=vertical]:has(.v-slider-field-start):has(.v-slider-labels){grid-template-columns:auto auto;grid-template-areas:"field-end.""rail labels""field-start."}.v-slider[data-orientation=vertical] .v-slider-rail{inline-size:var(--slider-thumb);block-size:var(--vectis-control-size-slider-length)}.v-slider[data-orientation=vertical] .v-slider-control{writing-mode:vertical-lr;direction:rtl}.v-slider[data-orientation=vertical] .v-slider-tooltip{justify-content:flex-end;align-items:center;block-size:0;inline-size:auto;inset-block-end:var(--slider-at);inset-inline-start:auto;inset-inline-end:calc(100% + var(--vectis-space-2))}.v-slider[data-orientation=vertical] .v-slider-labels{align-self:stretch;min-block-size:auto}.v-slider[data-orientation=vertical] .v-slider-label{justify-content:flex-start;align-items:center;block-size:0;inline-size:auto;inset-block-start:auto;inset-block-end:var(--slider-at);inset-inline-start:0}.v-slider[data-disabled]{cursor:not-allowed}.v-slider[data-disabled] .v-slider-track{background:var(--vectis-color-surface-muted)}.v-slider[data-disabled] .v-slider-fill,.v-slider[data-disabled] .v-slider-tick{background:var(--vectis-color-text-subtle)}.v-slider[data-disabled] .v-slider-tick[data-filled]{background:var(--vectis-color-surface-muted)}.v-slider[data-disabled] .v-slider-labels{color:var(--vectis-color-text-subtle)}.v-slider[data-disabled] .v-slider-input{--slider-thumb-bg:var(--vectis-color-surface-muted);--slider-thumb-border:var(--vectis-color-text-subtle);--slider-thumb-shadow:none;--slider-thumb-cursor:not-allowed;cursor:not-allowed}@media (prefers-reduced-motion:reduce){.v-slider-input{--slider-thumb-transition:none}.v-slider-tooltip{transition:none}}}
|
|
@@ -1,42 +1,52 @@
|
|
|
1
1
|
import { IconSource } from '../VIcon/types.js';
|
|
2
|
-
/**
|
|
3
|
-
* A value chosen by sliding a thumb along a track, and optionally a range between two
|
|
4
|
-
* of them.
|
|
5
|
-
*
|
|
6
|
-
* Underneath is the browser's own range control, which brings the keyboard, the correct
|
|
7
|
-
* announcement to screen readers and the form behaviour with it. The JavaScript covers
|
|
8
|
-
* only what it cannot: stopping the two values from crossing over each other — there is
|
|
9
|
-
* no native control with two thumbs, so a range is two of them superimposed — feeding
|
|
10
|
-
* the optional number fields, which the native element does not validate, and computing
|
|
11
|
-
* the positions of the ticks, the labels and the tooltip.
|
|
12
|
-
*
|
|
13
|
-
* Those positions are handed to the stylesheet as plain fractions written inline, and
|
|
14
|
-
* that is the only binding between the two. They matter because a thumb's centre does
|
|
15
|
-
* NOT travel the full width of the track: it runs from half a thumb in to half a thumb
|
|
16
|
-
* from the end, and everything meant to line up with it has to follow that same run.
|
|
17
|
-
*/
|
|
18
2
|
export type SliderLabel = string | {
|
|
19
3
|
icon: IconSource;
|
|
20
4
|
label: string;
|
|
21
5
|
};
|
|
6
|
+
/** The value of a slider: one number, or an ordered pair of them in range mode. */
|
|
7
|
+
export type SliderValue = number | [number, number];
|
|
8
|
+
/** Which way the track runs. */
|
|
9
|
+
export type SliderOrientation = 'horizontal' | 'vertical';
|
|
10
|
+
/** The height of the number fields: 32, 40 or 48 pixels. */
|
|
11
|
+
export type SliderSize = 'sm' | 'md' | 'lg';
|
|
22
12
|
interface SliderProps {
|
|
23
|
-
/** The lowest value the thumb can reach. */
|
|
13
|
+
/** The lowest value the thumb can reach. It is 0 by default. */
|
|
24
14
|
min?: number;
|
|
25
|
-
/** The highest value the thumb can reach. */
|
|
15
|
+
/** The highest value the thumb can reach. It is 100 by default. */
|
|
26
16
|
max?: number;
|
|
27
|
-
/**
|
|
17
|
+
/**
|
|
18
|
+
* The gap between two values the thumb can stop on, 1 by default. It is also what the
|
|
19
|
+
* arrow keys move by, and what a value typed into the companion field is snapped to.
|
|
20
|
+
*/
|
|
28
21
|
step?: number;
|
|
29
22
|
/** Offers two thumbs to pick a range, which makes the v-model a pair of values. */
|
|
30
23
|
range?: boolean;
|
|
31
24
|
/** Makes the slider unusable. */
|
|
32
25
|
disabled?: boolean;
|
|
33
26
|
/**
|
|
34
|
-
*
|
|
35
|
-
* announced as the
|
|
27
|
+
* Shows the value without allowing it to be changed. The thumbs can still be focused and
|
|
28
|
+
* are announced as read-only, but neither the pointer nor the keyboard moves them, and the
|
|
29
|
+
* number fields turn read-only with them.
|
|
30
|
+
*/
|
|
31
|
+
readonly?: boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Marks the value as invalid, which colours the thumbs and tells assistive technology
|
|
34
|
+
* so. It is for a rule the browser cannot check by itself.
|
|
35
|
+
*/
|
|
36
|
+
invalid?: boolean;
|
|
37
|
+
/**
|
|
38
|
+
* The height of the number fields `inputs` adds. Inside a VInputGroup the group's size
|
|
39
|
+
* wins, as it does for every field of the row.
|
|
40
|
+
*/
|
|
41
|
+
size?: SliderSize;
|
|
42
|
+
/**
|
|
43
|
+
* What screen readers announce for the slider. It is an accessible name and draws
|
|
44
|
+
* nothing on screen. In range mode the two thumbs are announced as the start and the
|
|
45
|
+
* end of it.
|
|
36
46
|
*/
|
|
37
47
|
label?: string;
|
|
38
48
|
/** Turns the slider upright, with the lowest value at the bottom. */
|
|
39
|
-
orientation?:
|
|
49
|
+
orientation?: SliderOrientation;
|
|
40
50
|
/**
|
|
41
51
|
* Adds a number field beside the slider for setting the value exactly — one, or one
|
|
42
52
|
* per end in range mode. Sliding is quick but imprecise; this is the way out.
|
|
@@ -58,18 +68,33 @@ interface SliderProps {
|
|
|
58
68
|
}
|
|
59
69
|
type __VLS_Props = SliderProps;
|
|
60
70
|
type __VLS_ModelProps = {
|
|
61
|
-
|
|
71
|
+
/**
|
|
72
|
+
* The value, and its SHAPE is what puts the slider in range mode: a single number — 0 to
|
|
73
|
+
* begin with — gives one thumb, a pair of them gives two. The pair is always ordered, the
|
|
74
|
+
* thumbs being stopped from crossing.
|
|
75
|
+
*/
|
|
76
|
+
modelValue?: SliderValue;
|
|
62
77
|
};
|
|
63
78
|
type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
|
|
64
|
-
declare const __VLS_export: import('vue').DefineComponent<__VLS_PublicProps, {
|
|
65
|
-
|
|
79
|
+
declare const __VLS_export: import('vue').DefineComponent<__VLS_PublicProps, {
|
|
80
|
+
/** Moves the focus to the end thumb, the only thumb outside range mode. */
|
|
81
|
+
focus: (options?: FocusOptions) => void | undefined;
|
|
82
|
+
/** The end thumb's real `<input type="range">`, for what `focus` does not cover. */
|
|
83
|
+
el: import('vue').Ref<HTMLInputElement | null, HTMLInputElement | null>;
|
|
84
|
+
}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
|
|
85
|
+
change: (value: SliderValue) => any;
|
|
86
|
+
"update:modelValue": (value: SliderValue) => any;
|
|
66
87
|
}, string, import('vue').PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
|
|
67
|
-
|
|
88
|
+
onChange?: ((value: SliderValue) => any) | undefined;
|
|
89
|
+
"onUpdate:modelValue"?: ((value: SliderValue) => any) | undefined;
|
|
68
90
|
}>, {
|
|
69
91
|
label: string;
|
|
70
92
|
range: boolean;
|
|
71
|
-
|
|
93
|
+
size: SliderSize;
|
|
94
|
+
orientation: SliderOrientation;
|
|
72
95
|
disabled: boolean;
|
|
96
|
+
invalid: boolean;
|
|
97
|
+
readonly: boolean;
|
|
73
98
|
tooltip: boolean;
|
|
74
99
|
max: number;
|
|
75
100
|
step: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VSlider.js","names":[],"sources":["../../../src/components/VSlider/VSlider.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, ref, watch } from 'vue'\nimport VIcon from '../VIcon/VIcon.vue'\nimport { iconProps } from '../VIcon/iconProps'\nimport type { IconSource } from '../VIcon/types'\nimport VInput from '../VInput/VInput.vue'\n\nimport { isDev } from '../../utils/env'\nimport { useMessages } from '../../i18n/state'\n\n// @core\n/**\n * A value chosen by sliding a thumb along a track, and optionally a range between two\n * of them.\n *\n * Underneath is the browser's own range control, which brings the keyboard, the correct\n * announcement to screen readers and the form behaviour with it. The JavaScript covers\n * only what it cannot: stopping the two values from crossing over each other — there is\n * no native control with two thumbs, so a range is two of them superimposed — feeding\n * the optional number fields, which the native element does not validate, and computing\n * the positions of the ticks, the labels and the tooltip.\n *\n * Those positions are handed to the stylesheet as plain fractions written inline, and\n * that is the only binding between the two. They matter because a thumb's centre does\n * NOT travel the full width of the track: it runs from half a thumb in to half a thumb\n * from the end, and everything meant to line up with it has to follow that same run.\n */\nexport type SliderLabel = string | { icon: IconSource; label: string }\n\ninterface SliderProps {\n /** The lowest value the thumb can reach. */\n min?: number\n /** The highest value the thumb can reach. */\n max?: number\n /** The gap between two values it can stop on. */\n step?: number\n /** Offers two thumbs to pick a range, which makes the v-model a pair of values. */\n range?: boolean\n /** Makes the slider unusable. */\n disabled?: boolean\n /**\n * What screen readers announce for the slider. In range mode the two thumbs are\n * announced as the start and the end of it.\n */\n label?: string\n /** Turns the slider upright, with the lowest value at the bottom. */\n orientation?: 'horizontal' | 'vertical'\n /**\n * Adds a number field beside the slider for setting the value exactly — one, or one\n * per end in range mode. Sliding is quick but imprecise; this is the way out.\n */\n inputs?: boolean\n /**\n * Marks each step on the track. Providing labels implies it. Past fifty steps the\n * marks would be an unreadable comb and are not drawn at all.\n */\n ticks?: boolean\n /**\n * A label for every step, in order — a piece of text, or an icon with the words that\n * name it for screen readers. They also become what a screen reader announces in\n * place of the raw number.\n */\n labels?: SliderLabel[]\n /** Shows the value in a bubble above the thumb while it is being moved or focused. */\n tooltip?: boolean\n}\n\nconst props = withDefaults(defineProps<SliderProps>(), {\n min: 0,\n max: 100,\n step: 1,\n range: false,\n disabled: false,\n label: undefined,\n orientation: 'horizontal',\n inputs: false,\n ticks: false,\n labels: undefined,\n tooltip: false,\n})\n\nconst model = defineModel<number | [number, number]>({ default: 0 })\n\nconst startValue = computed(() => (Array.isArray(model.value) ? model.value[0] : props.min))\nconst endValue = computed(() =>\n Array.isArray(model.value) ? model.value[1] : (model.value as number),\n)\n\n/**\n * Where a value sits along the run, as a fraction between 0 and 1. The guard covers a\n * slider whose two bounds are equal, which would otherwise divide by zero.\n */\nconst frac = (v: number) => Math.min(1, Math.max(0, (v - props.min) / (props.max - props.min || 1)))\n\n// @core — what stops the two values from crossing. A range is two native controls laid\n// over one another, and there is no dual-thumb control to inherit this behaviour from.\nfunction onStartInput(event: Event) {\n const el = event.target as HTMLInputElement\n const clamped = Math.min(Number(el.value), endValue.value)\n el.value = String(clamped)\n model.value = [clamped, endValue.value]\n}\n\nfunction onEndInput(event: Event) {\n const el = event.target as HTMLInputElement\n if (!props.range) {\n model.value = Number(el.value)\n return\n }\n const clamped = Math.max(Number(el.value), startValue.value)\n el.value = String(clamped)\n model.value = [startValue.value, clamped]\n}\n\n/**\n * How many whole steps the thumb can actually stop on. It matters when the range does\n * not divide evenly by the step: the native control stops at the last step that fits,\n * short of the maximum, and the ticks have to agree with it.\n */\nconst stepCount = computed(() => Math.floor((props.max - props.min) / props.step + 1e-9))\n\nconst showTicks = computed(\n () =>\n (props.ticks || props.labels !== undefined) && stepCount.value >= 1 && stepCount.value <= 50,\n)\n\nconst tickItems = computed(() => {\n if (!showTicks.value) return []\n return Array.from({ length: stepCount.value + 1 }, (_, i) => {\n const value = props.min + i * props.step\n const filled = props.range\n ? value >= startValue.value && value <= endValue.value\n : value <= endValue.value\n return { f: frac(value), filled }\n })\n})\n\nconst labelFraction = (index: number) => frac(props.min + index * props.step)\n\n/** What a value is called, if the consumer named its step; failing that, the number itself. */\nfunction labelTextAt(value: number): string {\n const item = props.labels?.[Math.round((value - props.min) / props.step)]\n if (item === undefined) return String(value)\n return typeof item === 'string' ? item : item.label\n}\n\n// @a11y\n/* What each thumb is announced as. There is no prop for the two halves: the wording\n comes from the dictionary, which is also where it is changed.\n\n With a single thumb there is nothing to distinguish: that thumb IS the value, so it\n simply takes the consumer's label, and is left unnamed when none was given. The\n generic fallback applies to the NUMBER FIELD alone, which cannot go unnamed — a bare\n field in a form has to say what it holds. */\nconst m = useMessages()\nconst startLabel = computed(() =>\n props.label ? m.value.slider.rangeStart(props.label) : m.value.slider.start,\n)\nconst endLabel = computed(() =>\n props.label ? m.value.slider.rangeEnd(props.label) : m.value.slider.end,\n)\nconst rangeEndLabel = computed(() => (props.range ? endLabel.value : props.label))\nconst fieldEndLabel = computed(() =>\n props.range ? endLabel.value : (props.label ?? m.value.slider.value),\n)\n\nconst startValueText = computed(() => (props.labels ? labelTextAt(startValue.value) : undefined))\nconst endValueText = computed(() => (props.labels ? labelTextAt(endValue.value) : undefined))\n\n// @devwarn\nif (isDev) {\n if ((props.ticks || props.labels) && stepCount.value > 50)\n console.warn(`[VSlider] ${stepCount.value} steps — ticks/labels not rendered past 50.`)\n if (props.labels && props.labels.length !== stepCount.value + 1)\n console.warn(\n `[VSlider] ${props.labels.length} labels for ${stepCount.value + 1} steps — one label per step expected.`,\n )\n}\n\n// The text held by the number fields, kept apart from the slider's own value.\n//\n// It is typed as text OR a number because these are number fields, whose value Vue\n// converts to a number as soon as it can be read as one — while an empty field, or one\n// holding a half-typed \"1-\", stays text. That is why the value is turned back into text\n// when it is committed.\nconst startFieldText = ref<string | number>(String(startValue.value))\nconst endFieldText = ref<string | number>(String(endValue.value))\n\n// Sliding the thumb keeps the fields in step, continuously.\nwatch(startValue, (v) => (startFieldText.value = String(v)))\nwatch(endValue, (v) => (endFieldText.value = String(v)))\n\n/**\n * Takes what was typed in a field and makes it the value — but only once the reader has\n * finished, on leaving the field or on Enter. Reading it as they type would clamp the\n * \"1\" of \"15\" to the minimum before the 5 was ever pressed.\n *\n * Anything unreadable, an empty field included, silently puts the previous value back.\n */\nfunction commitField(which: 'start' | 'end') {\n const raw = which === 'start' ? startFieldText.value : endFieldText.value\n // TRAP — parsed rather than converted: an empty string parses to nothing, which is\n // what triggers the revert below, where converting it would give ZERO and quietly\n // overwrite the value with it.\n const parsed = Number.parseFloat(String(raw))\n if (Number.isNaN(parsed)) {\n resyncFields()\n return\n }\n const clamped = Math.min(props.max, Math.max(props.min, parsed))\n // Brought onto the nearest step. The rounding that follows removes the noise decimal\n // steps leave behind — a tenth cannot be represented exactly, so 0.1 × 3 comes out as\n // 0.30000000000000004.\n let value = props.min + Math.round((clamped - props.min) / props.step) * props.step\n value = Math.min(props.max, Math.round(value * 1e10) / 1e10)\n if (!props.range) {\n model.value = value\n } else if (which === 'start') {\n model.value = [Math.min(value, endValue.value), endValue.value]\n } else {\n model.value = [startValue.value, Math.max(value, startValue.value)]\n }\n // Put back explicitly, because a commit that does not change the value — typing 200\n // where the maximum is 100 — changes nothing for the watchers to react to, and the\n // field would go on showing what was typed.\n resyncFields()\n}\n\nfunction resyncFields() {\n startFieldText.value = String(startValue.value)\n endFieldText.value = String(endValue.value)\n}\n</script>\n\n<template>\n <div\n class=\"v-slider\"\n :data-range=\"range ? '' : undefined\"\n :data-disabled=\"disabled ? '' : undefined\"\n :data-orientation=\"orientation === 'vertical' ? 'vertical' : undefined\"\n :style=\"{\n '--start-fraction': String(frac(startValue)),\n '--end-fraction': String(frac(endValue)),\n }\"\n >\n <VInput\n v-if=\"inputs && range\"\n v-model=\"startFieldText\"\n class=\"v-slider-field v-slider-field-start\"\n type=\"number\"\n size=\"sm\"\n :min=\"min\"\n :max=\"max\"\n :step=\"step\"\n :disabled=\"disabled\"\n :aria-label=\"startLabel\"\n @change=\"commitField('start')\"\n />\n <div class=\"v-slider-rail\">\n <span class=\"v-slider-control\">\n <span class=\"v-slider-track\" aria-hidden=\"true\">\n <span class=\"v-slider-fill\" />\n <span\n v-for=\"(tick, i) in tickItems\"\n :key=\"i\"\n class=\"v-slider-tick\"\n :data-filled=\"tick.filled ? '' : undefined\"\n :style=\"{ '--fill-fraction': String(tick.f) }\"\n />\n </span>\n <input\n v-if=\"range\"\n type=\"range\"\n class=\"v-slider-input v-slider-input-start\"\n :min=\"min\"\n :max=\"max\"\n :step=\"step\"\n :disabled=\"disabled\"\n :value=\"startValue\"\n :aria-label=\"startLabel\"\n :aria-valuetext=\"startValueText\"\n @input=\"onStartInput\"\n />\n <input\n type=\"range\"\n class=\"v-slider-input v-slider-input-end\"\n :min=\"min\"\n :max=\"max\"\n :step=\"step\"\n :disabled=\"disabled\"\n :value=\"endValue\"\n :aria-label=\"rangeEndLabel\"\n :aria-valuetext=\"endValueText\"\n @input=\"onEndInput\"\n />\n </span>\n <span\n v-if=\"tooltip && range\"\n class=\"v-slider-tooltip v-slider-tooltip-start\"\n aria-hidden=\"true\"\n :style=\"{ '--fill-fraction': String(frac(startValue)) }\"\n >\n <span class=\"v-slider-tooltip-bubble\">{{ startValueText ?? startValue }}</span>\n </span>\n <span\n v-if=\"tooltip\"\n class=\"v-slider-tooltip v-slider-tooltip-end\"\n aria-hidden=\"true\"\n :style=\"{ '--fill-fraction': String(frac(endValue)) }\"\n >\n <span class=\"v-slider-tooltip-bubble\">{{ endValueText ?? endValue }}</span>\n </span>\n </div>\n <div v-if=\"labels\" class=\"v-slider-labels\">\n <span\n v-for=\"(item, i) in labels\"\n :key=\"i\"\n class=\"v-slider-label\"\n :style=\"{ '--fill-fraction': String(labelFraction(i)) }\"\n >\n <template v-if=\"typeof item === 'string'\">{{ item }}</template>\n <VIcon v-else v-bind=\"iconProps(item.icon)\" :label=\"item.label\" />\n </span>\n </div>\n <VInput\n v-if=\"inputs\"\n v-model=\"endFieldText\"\n class=\"v-slider-field v-slider-field-end\"\n type=\"number\"\n size=\"sm\"\n :min=\"min\"\n :max=\"max\"\n :step=\"step\"\n :disabled=\"disabled\"\n :aria-label=\"fieldEndLabel\"\n @change=\"commitField('end')\"\n />\n </div>\n</template>\n\n<style>\n@layer vectis.components {\n .v-slider {\n --slider-thumb: var(--vectis-control-size-slider-thumb);\n --slider-track: var(--vectis-control-size-slider-track);\n display: grid;\n grid-template-areas: 'rail';\n grid-template-columns: minmax(0, 1fr);\n align-items: center;\n column-gap: var(--vectis-space-2);\n row-gap: var(--vectis-space-1);\n width: 100%;\n font-family: var(--vectis-text-family);\n }\n\n .v-slider:has(.v-slider-labels) {\n grid-template-areas: 'rail' 'labels';\n }\n\n .v-slider:has(.v-slider-field-end) {\n grid-template-areas: 'rail field-end';\n grid-template-columns: minmax(0, 1fr) auto;\n }\n\n .v-slider:has(.v-slider-field-end):has(.v-slider-labels) {\n grid-template-areas: 'rail field-end' 'labels .';\n }\n\n .v-slider:has(.v-slider-field-start) {\n grid-template-areas: 'field-start rail field-end';\n grid-template-columns: auto minmax(0, 1fr) auto;\n }\n\n .v-slider:has(.v-slider-field-start):has(.v-slider-labels) {\n grid-template-areas: 'field-start rail field-end' '. labels .';\n }\n\n .v-slider-rail {\n grid-area: rail;\n position: relative;\n block-size: var(--slider-thumb);\n }\n\n .v-slider-control {\n position: absolute;\n inset: 0;\n }\n\n .v-slider-track {\n position: absolute;\n inset-inline: 0;\n inset-block: 0;\n margin-block: auto;\n block-size: var(--slider-track);\n border-radius: var(--vectis-radius-full);\n background: var(--vectis-color-border);\n overflow: hidden;\n }\n\n .v-slider-fill {\n position: absolute;\n inset-block: 0;\n inset-inline-start: 0;\n inline-size: calc(var(--slider-thumb) / 2 + (100% - var(--slider-thumb)) * var(--end-fraction));\n background: var(--vectis-color-accent);\n }\n\n .v-slider[data-range] .v-slider-fill {\n inset-inline-start: calc(\n var(--slider-thumb) / 2 + (100% - var(--slider-thumb)) * var(--start-fraction)\n );\n inline-size: calc((100% - var(--slider-thumb)) * (var(--end-fraction) - var(--start-fraction)));\n }\n\n .v-slider-tick {\n --slider-tick: calc(var(--slider-track) / 3 * 2);\n position: absolute;\n inset-block: 0;\n margin-block: auto;\n inset-inline-start: calc(\n var(--slider-thumb) / 2 + (100% - var(--slider-thumb)) * var(--fill-fraction) -\n var(--slider-tick) / 2\n );\n inline-size: var(--slider-tick);\n block-size: var(--slider-tick);\n border-radius: var(--vectis-radius-full);\n background: var(--vectis-color-border-strong);\n }\n\n .v-slider-tick[data-filled] {\n background: var(--vectis-color-text-on-accent);\n }\n\n /* The two controls lie exactly on top of one another, so only their thumbs are allowed\n to receive the pointer. Without that, the one on top would swallow every click and\n the other thumb could never be grabbed. */\n .v-slider-input {\n position: absolute;\n inset: 0;\n width: 100%;\n height: 100%;\n margin: 0;\n appearance: none;\n background: transparent;\n pointer-events: none;\n }\n\n /* With a single thumb there is nothing underneath to protect, so the whole control\n takes the pointer again — which is what makes clicking the track jump the value\n there and start dragging at once, natively and with no code at all. The accepted\n side effect is that the thumb lights up when the pointer is anywhere over the\n track. */\n .v-slider:not([data-range]) .v-slider-input {\n pointer-events: auto;\n cursor: pointer;\n }\n\n .v-slider-input::-webkit-slider-thumb {\n appearance: none;\n pointer-events: auto;\n width: var(--slider-thumb);\n height: var(--slider-thumb);\n border-radius: var(--vectis-radius-full);\n background: var(--vectis-color-surface);\n border: var(--vectis-control-border-width) solid var(--vectis-color-accent);\n box-shadow: var(--vectis-shadow-xs);\n cursor: pointer;\n transition: background-color var(--vectis-duration-fast) var(--vectis-ease-default);\n }\n\n .v-slider-input::-moz-range-thumb {\n pointer-events: auto;\n width: var(--slider-thumb);\n height: var(--slider-thumb);\n border-radius: var(--vectis-radius-full);\n background: var(--vectis-color-surface);\n border: var(--vectis-control-border-width) solid var(--vectis-color-accent);\n box-shadow: var(--vectis-shadow-xs);\n cursor: pointer;\n transition: background-color var(--vectis-duration-fast) var(--vectis-ease-default);\n }\n\n /* The thumb tints as the pointer rests on it or drags it. TRAP — the state is read on\n the control and the thumb is then addressed, never the reverse: a state pseudo-class\n written after the thumb's own pseudo-element is unreliable across browsers. */\n .v-slider-input:hover:not(:disabled)::-webkit-slider-thumb,\n .v-slider-input:active:not(:disabled)::-webkit-slider-thumb {\n background: var(--vectis-color-accent-surface);\n }\n\n .v-slider-input:hover:not(:disabled)::-moz-range-thumb,\n .v-slider-input:active:not(:disabled)::-moz-range-thumb {\n background: var(--vectis-color-accent-surface);\n }\n\n .v-slider-input:focus-visible {\n outline: none;\n }\n\n .v-slider-input:focus-visible::-webkit-slider-thumb {\n outline: var(--vectis-focus-ring-width) solid var(--vectis-focus-ring-color);\n outline-offset: var(--vectis-focus-ring-offset);\n }\n\n .v-slider-input:focus-visible::-moz-range-thumb {\n outline: var(--vectis-focus-ring-width) solid var(--vectis-focus-ring-color);\n outline-offset: var(--vectis-focus-ring-offset);\n }\n\n /* The bubble showing the value. It looks like a VTooltip but is placed by arithmetic\n rather than anchored to the thumb: a native thumb is a pseudo-element, and the\n browser's anchoring cannot attach anything to one. */\n .v-slider-tooltip {\n position: absolute;\n inset-block-end: calc(100% + var(--vectis-space-2));\n inset-inline-start: calc(\n var(--slider-thumb) / 2 + (100% - var(--slider-thumb)) * var(--fill-fraction)\n );\n inline-size: 0;\n display: flex;\n justify-content: center;\n opacity: 0;\n visibility: hidden;\n transition:\n opacity var(--vectis-duration-fast) var(--vectis-ease-default),\n visibility var(--vectis-duration-fast) var(--vectis-ease-default);\n }\n\n .v-slider:has(.v-slider-input-start:active) .v-slider-tooltip-start,\n .v-slider:has(.v-slider-input-start:focus-visible) .v-slider-tooltip-start,\n .v-slider:has(.v-slider-input-end:active) .v-slider-tooltip-end,\n .v-slider:has(.v-slider-input-end:focus-visible) .v-slider-tooltip-end {\n opacity: 1;\n visibility: visible;\n }\n\n .v-slider-tooltip-bubble {\n padding: var(--vectis-space-1) var(--vectis-space-2);\n background: var(--vectis-color-surface-inverse);\n color: var(--vectis-color-text-on-inverse);\n font-size: var(--vectis-text-caption-size);\n line-height: var(--vectis-text-caption-leading);\n border-radius: var(--vectis-radius-sm);\n box-shadow: var(--vectis-shadow-sm);\n white-space: nowrap;\n }\n\n .v-slider-labels {\n grid-area: labels;\n position: relative;\n /* The labels are positioned individually and therefore contribute no height of\n their own; this reserves enough room for either kind, a small line of text or an\n icon. */\n min-block-size: var(--vectis-icon-size-md);\n --vectis-icon-size: var(--vectis-icon-size-md);\n font-size: var(--vectis-text-caption-size);\n color: var(--vectis-color-text-muted);\n }\n\n /* A box of zero width placed exactly on the step: its content then overflows equally\n on both sides, which centres it there. Centring it with a transform would be the\n usual trick, but a transform is physical and would have to be undone for the\n vertical orientation and again for a right-to-left page. */\n .v-slider-label {\n position: absolute;\n inset-block-start: 0;\n inset-inline-start: calc(\n var(--slider-thumb) / 2 + (100% - var(--slider-thumb)) * var(--fill-fraction)\n );\n inline-size: 0;\n display: flex;\n justify-content: center;\n white-space: nowrap;\n }\n\n .v-slider-field.v-input {\n inline-size: var(--vectis-control-size-slider-field);\n }\n\n .v-slider-field-start {\n grid-area: field-start;\n }\n\n .v-slider-field-end {\n grid-area: field-end;\n }\n\n .v-slider[data-orientation='vertical'] {\n grid-template-areas: 'rail';\n grid-template-columns: none;\n inline-size: fit-content;\n justify-items: center;\n }\n\n .v-slider[data-orientation='vertical']:has(.v-slider-labels) {\n grid-template-areas: 'rail labels';\n grid-template-columns: auto auto;\n }\n\n .v-slider[data-orientation='vertical']:has(.v-slider-field-end) {\n grid-template-areas: 'field-end' 'rail';\n grid-template-columns: none;\n }\n\n .v-slider[data-orientation='vertical']:has(.v-slider-field-end):has(.v-slider-labels) {\n grid-template-areas: 'field-end .' 'rail labels';\n grid-template-columns: auto auto;\n }\n\n .v-slider[data-orientation='vertical']:has(.v-slider-field-start) {\n grid-template-areas: 'field-end' 'rail' 'field-start';\n grid-template-columns: none;\n }\n\n .v-slider[data-orientation='vertical']:has(.v-slider-field-start):has(.v-slider-labels) {\n grid-template-areas: 'field-end .' 'rail labels' 'field-start .';\n grid-template-columns: auto auto;\n }\n\n .v-slider[data-orientation='vertical'] .v-slider-rail {\n inline-size: var(--slider-thumb);\n block-size: var(--vectis-control-size-slider-length);\n }\n\n /* Only this inner box is turned upright, and that is the whole trick: the track, the\n fill and the ticks are all placed with logical properties, so they follow the change\n of axis with no rule written a second time — while the bubbles and the labels stay\n outside that box, and therefore keep their text horizontal.\n\n The direction is reversed with it so that the lowest value ends up at the bottom. */\n .v-slider[data-orientation='vertical'] .v-slider-control {\n writing-mode: vertical-lr;\n direction: rtl;\n }\n\n .v-slider[data-orientation='vertical'] .v-slider-tooltip {\n inset-block-end: calc(\n var(--slider-thumb) / 2 + (100% - var(--slider-thumb)) * var(--fill-fraction)\n );\n inset-inline-start: auto;\n inset-inline-end: calc(100% + var(--vectis-space-2));\n inline-size: auto;\n block-size: 0;\n align-items: center;\n justify-content: flex-end;\n }\n\n .v-slider[data-orientation='vertical'] .v-slider-labels {\n align-self: stretch;\n min-block-size: auto;\n }\n\n .v-slider[data-orientation='vertical'] .v-slider-label {\n inset-block-start: auto;\n inset-block-end: calc(\n var(--slider-thumb) / 2 + (100% - var(--slider-thumb)) * var(--fill-fraction)\n );\n inset-inline-start: 0;\n inline-size: auto;\n block-size: 0;\n align-items: center;\n justify-content: flex-start;\n }\n\n /* A disabled slider greys out through the colour tokens, the same ones VCheckbox and\n VSwitch use, and never through opacity. */\n .v-slider[data-disabled] {\n cursor: not-allowed;\n }\n\n .v-slider[data-disabled] .v-slider-track {\n background: var(--vectis-color-surface-muted);\n }\n\n .v-slider[data-disabled] .v-slider-fill {\n background: var(--vectis-color-text-subtle);\n }\n\n .v-slider[data-disabled] .v-slider-tick {\n background: var(--vectis-color-text-subtle);\n }\n\n /* A tick sitting on the greyed fill takes the light colour back, so that it stays\n visible against it — the same inversion VCheckbox applies to its disabled tick. */\n .v-slider[data-disabled] .v-slider-tick[data-filled] {\n background: var(--vectis-color-surface-muted);\n }\n\n .v-slider[data-disabled] .v-slider-labels {\n color: var(--vectis-color-text-subtle);\n }\n\n .v-slider[data-disabled] .v-slider-input {\n cursor: not-allowed;\n }\n\n .v-slider[data-disabled] .v-slider-input::-webkit-slider-thumb {\n background: var(--vectis-color-surface-muted);\n border-color: var(--vectis-color-text-subtle);\n box-shadow: none;\n cursor: not-allowed;\n }\n\n .v-slider[data-disabled] .v-slider-input::-moz-range-thumb {\n background: var(--vectis-color-surface-muted);\n border-color: var(--vectis-color-text-subtle);\n box-shadow: none;\n cursor: not-allowed;\n }\n\n @media (prefers-reduced-motion: reduce) {\n .v-slider-input::-webkit-slider-thumb {\n transition: none;\n }\n\n .v-slider-input::-moz-range-thumb {\n transition: none;\n }\n\n .v-slider-tooltip {\n transition: none;\n }\n }\n}\n</style>\n"],"mappings":""}
|
|
1
|
+
{"version":3,"file":"VSlider.js","names":[],"sources":["../../../src/components/VSlider/VSlider.vue"],"sourcesContent":["<script setup lang=\"ts\">\n// @core\n/**\n * A value chosen by sliding a thumb along a track, optionally a range between two.\n *\n * Underneath is a native `<input type=\"range\">`, which brings the keyboard, the ARIA and the\n * form behaviour. The JS covers only what it cannot: stopping the two values crossing —\n * there is no native two-thumb control, so a range is two superimposed — refusing a change\n * when `readonly`, which a range input has no native form of, feeding the optional number\n * fields, and computing the positions of the ticks and labels.\n *\n * Those positions reach the stylesheet as unitless inline fractions, and that is the whole\n * binding between the two. They matter because a thumb's CENTRE does not travel the full\n * width of the track: it runs from half a thumb in to half a thumb from the end, and\n * everything meant to line up with it has to follow that same run.\n */\n\nimport { computed, inject, ref, watch } from 'vue'\nimport VIcon from '../VIcon/VIcon.vue'\nimport { iconProps } from '../VIcon/iconProps'\nimport type { IconSource } from '../VIcon/types'\nimport VInput from '../VInput/VInput.vue'\nimport { inputGroupKey } from '../VInput/context'\n\nimport { useControlShape } from '../../composables/useControlShape'\nimport { useRootAttrs } from '../../composables/useRootAttrs'\nimport { isDev } from '../../utils/env'\nimport { clamp } from '../../utils/number'\nimport { useMessages } from '../../i18n/state'\n\nexport type SliderLabel = string | { icon: IconSource; label: string }\n\n/** The value of a slider: one number, or an ordered pair of them in range mode. */\nexport type SliderValue = number | [number, number]\n\n/** Which way the track runs. */\nexport type SliderOrientation = 'horizontal' | 'vertical'\n\n/** The height of the number fields: 32, 40 or 48 pixels. */\nexport type SliderSize = 'sm' | 'md' | 'lg'\n\ninterface SliderProps {\n /** The lowest value the thumb can reach. It is 0 by default. */\n min?: number\n /** The highest value the thumb can reach. It is 100 by default. */\n max?: number\n /**\n * The gap between two values the thumb can stop on, 1 by default. It is also what the\n * arrow keys move by, and what a value typed into the companion field is snapped to.\n */\n step?: number\n /** Offers two thumbs to pick a range, which makes the v-model a pair of values. */\n range?: boolean\n /** Makes the slider unusable. */\n disabled?: boolean\n /**\n * Shows the value without allowing it to be changed. The thumbs can still be focused and\n * are announced as read-only, but neither the pointer nor the keyboard moves them, and the\n * number fields turn read-only with them.\n */\n readonly?: boolean\n /**\n * Marks the value as invalid, which colours the thumbs and tells assistive technology\n * so. It is for a rule the browser cannot check by itself.\n */\n invalid?: boolean\n /**\n * The height of the number fields `inputs` adds. Inside a VInputGroup the group's size\n * wins, as it does for every field of the row.\n */\n size?: SliderSize\n /**\n * What screen readers announce for the slider. It is an accessible name and draws\n * nothing on screen. In range mode the two thumbs are announced as the start and the\n * end of it.\n */\n label?: string\n /** Turns the slider upright, with the lowest value at the bottom. */\n orientation?: SliderOrientation\n /**\n * Adds a number field beside the slider for setting the value exactly — one, or one\n * per end in range mode. Sliding is quick but imprecise; this is the way out.\n */\n inputs?: boolean\n /**\n * Marks each step on the track. Providing labels implies it. Past fifty steps the\n * marks would be an unreadable comb and are not drawn at all.\n */\n ticks?: boolean\n /**\n * A label for every step, in order — a piece of text, or an icon with the words that\n * name it for screen readers. They also become what a screen reader announces in\n * place of the raw number.\n */\n labels?: SliderLabel[]\n /** Shows the value in a bubble above the thumb while it is being moved or focused. */\n tooltip?: boolean\n}\n\nconst props = withDefaults(defineProps<SliderProps>(), {\n min: 0,\n max: 100,\n step: 1,\n range: false,\n disabled: false,\n readonly: false,\n invalid: false,\n size: 'md',\n label: undefined,\n orientation: 'horizontal',\n inputs: false,\n ticks: false,\n labels: undefined,\n tooltip: false,\n})\n\n/**\n * The value, and its SHAPE is what puts the slider in range mode: a single number — 0 to\n * begin with — gives one thumb, a pair of them gives two. The pair is always ordered, the\n * thumbs being stopped from crossing.\n */\nconst model = defineModel<SliderValue>({ default: 0 })\n\nconst emit = defineEmits<{\n /**\n * The reader has SETTLED on a value: a thumb was released or moved by a key, or a number\n * field was committed. It carries the whole value, a pair in range mode, and fires for\n * either thumb, where the v-model follows every step of a drag.\n */\n change: [value: SliderValue]\n}>()\n\n// The number fields are fields of a VInputGroup row like any other, so the row's size and\n// its disabled state reach them through the same arbitration. A slider has no `compact` of\n// its own: only the row's can apply.\nconst group = inject(inputGroupKey, null)\nconst {\n size: resolvedSize,\n compact: resolvedCompact,\n disabled: resolvedDisabled,\n} = useControlShape(\n {\n get size() {\n return props.size\n },\n compact: false,\n get disabled() {\n return props.disabled\n },\n },\n group,\n)\n\ntype Thumb = 'start' | 'end'\n\nconst startValue = computed(() => (Array.isArray(model.value) ? model.value[0] : props.min))\nconst endValue = computed(() =>\n Array.isArray(model.value) ? model.value[1] : (model.value as number),\n)\n\nconst thumbValue = (which: Thumb) => (which === 'start' ? startValue.value : endValue.value)\n\n/**\n * Where a value sits along the run, as a fraction between 0 and 1. The guard covers a\n * slider whose two bounds are equal, which would otherwise divide by zero.\n */\nconst frac = (v: number) => clamp((v - props.min) / (props.max - props.min || 1), 0, 1)\n\n// @core — the ONE place a thumb is written, so what stops the two values crossing exists\n// once for the thumbs and the number fields alike. A range is two native controls laid over\n// one another, and there is no dual-thumb control to inherit this behaviour from. It returns\n// what was written, which is what each caller reads back: a model that lags a parent\n// `v-model` would still hold the value from before.\nfunction writeThumb(which: Thumb, n: number): SliderValue {\n const next: SliderValue = !props.range\n ? n\n : which === 'start'\n ? [Math.min(n, endValue.value), endValue.value]\n : [startValue.value, Math.max(n, startValue.value)]\n model.value = next\n return next\n}\n\nconst writtenFor = (value: SliderValue, which: Thumb) =>\n Array.isArray(value) ? value[which === 'start' ? 0 : 1] : value\n\nfunction onThumbInput(which: Thumb, event: Event) {\n const el = event.target as HTMLInputElement\n // @core\n // A drag or a click on the track has ALREADY moved the native thumb when `input` fires,\n // and the event cannot be cancelled: putting the value back is the only refusal there is.\n // It lands before the browser paints, so the thumb never visibly leaves its place, and\n // since the value at release is the one it started from, no `change` follows either.\n if (props.readonly) {\n el.value = String(thumbValue(which))\n return\n }\n // Written back to the DOM as well: a thumb dragged past its sibling stops against it.\n el.value = String(writtenFor(writeThumb(which, Number(el.value)), which))\n}\n\n// @keyboard @core\n// The keys that move a range input, cancelled before the browser applies them when the\n// slider is read-only. Tab and every other key pass, so the thumbs stay reachable.\nconst VALUE_KEYS = new Set([\n 'ArrowUp',\n 'ArrowDown',\n 'ArrowLeft',\n 'ArrowRight',\n 'Home',\n 'End',\n 'PageUp',\n 'PageDown',\n])\n\nfunction onThumbKeydown(event: KeyboardEvent) {\n if (props.readonly && VALUE_KEYS.has(event.key)) event.preventDefault()\n}\n\n// @core\n/*\n * A range is two native controls, and a consumer's `@change` could only ever reach ONE of\n * them through the forwarded attributes: moving the start thumb told nobody. So `change` is\n * declared and fed by both.\n *\n * TRAP — the settled value is read off the THUMB, never off the model. A key press fires\n * `input` and `change` back to back in one task, and under a parent `v-model` the model's\n * local copy only catches up when the parent re-renders, so it would still hold the value\n * from before the key.\n */\nfunction onThumbChange(which: Thumb, event: Event) {\n if (props.readonly) return\n const value = Number((event.target as HTMLInputElement).value)\n if (!props.range) emit('change', value)\n else emit('change', which === 'start' ? [value, endValue.value] : [startValue.value, value])\n}\n\n/**\n * How many whole steps the thumb can actually stop on. It matters when the range does\n * not divide evenly by the step: the native control stops at the last step that fits,\n * short of the maximum, and the ticks have to agree with it.\n */\nconst stepCount = computed(() => Math.floor((props.max - props.min) / props.step + 1e-9))\n\nconst showTicks = computed(\n () =>\n (props.ticks || props.labels !== undefined) && stepCount.value >= 1 && stepCount.value <= 50,\n)\n\n/**\n * Each step's value and the style that places it, shared by the ticks and the labels. Only\n * the bounds and the step move them, so dragging a thumb rebuilds none of it: each style\n * object keeps its identity from one render to the next, and Vue skips a binding whose\n * object has not changed. Which ticks are FILLED does follow the value, and is asked\n * separately, in `isFilled`.\n */\nconst stepPlaces = computed(() => {\n const length = Math.max(showTicks.value ? stepCount.value + 1 : 0, props.labels?.length ?? 0)\n return Array.from({ length }, (_, i) => {\n const value = props.min + i * props.step\n return { value, style: { '--fill-fraction': String(frac(value)) } }\n })\n})\n\nconst tickPlaces = computed(() =>\n showTicks.value ? stepPlaces.value.slice(0, stepCount.value + 1) : [],\n)\n\nconst isFilled = (value: number) =>\n props.range ? value >= startValue.value && value <= endValue.value : value <= endValue.value\n\n/** What a value is called, if the consumer named its step; failing that, the number itself. */\nfunction labelTextAt(value: number): string {\n const item = props.labels?.[Math.round((value - props.min) / props.step)]\n if (item === undefined) return String(value)\n return typeof item === 'string' ? item : item.label\n}\n\n// @a11y\n/* What each thumb is announced as. There is no prop for the two halves: the wording\n comes from the dictionary, which is also where it is changed.\n\n With a single thumb there is nothing to distinguish: that thumb IS the value, so it\n simply takes the consumer's label, and is left unnamed when none was given. The\n generic fallback applies to the NUMBER FIELD alone, which cannot go unnamed — a bare\n field in a form has to say what it holds. */\nconst m = useMessages()\nconst startLabel = computed(() =>\n props.label ? m.value.slider.rangeStart(props.label) : m.value.slider.start,\n)\nconst endLabel = computed(() =>\n props.label ? m.value.slider.rangeEnd(props.label) : m.value.slider.end,\n)\nconst thumbEndLabel = computed(() => (props.range ? endLabel.value : props.label))\nconst fieldEndLabel = computed(() =>\n props.range ? endLabel.value : (props.label ?? m.value.slider.value),\n)\n\nconst startValueText = computed(() =>\n props.range && props.labels ? labelTextAt(startValue.value) : undefined,\n)\nconst endValueText = computed(() => (props.labels ? labelTextAt(endValue.value) : undefined))\n\n// @a11y\n/*\n * The wrapper-root split. The root here is a layout box holding the labels, the track and\n * the optional number fields, so a consumer's `name`, `id`, `required` and `aria-*` have\n * to be redirected onto the real `<input type=\"range\">` — left on the wrapper, a `name`\n * submits nothing and a `<label for>` points at a div.\n *\n * They go to the END thumb, which is the one always rendered. A RANGE has two thumbs and\n * therefore no single value to submit, which the warning below says out loud rather than\n * letting a form come back with half the answer.\n */\ndefineOptions({ inheritAttrs: false })\nconst { attrs, rootClass, rootStyle, forwardedAttrs } = useRootAttrs()\n\n// @devwarn\nif (isDev) {\n if ((props.ticks || props.labels) && stepCount.value > 50)\n console.warn(`[VSlider] ${stepCount.value} steps — ticks/labels not rendered past 50.`)\n if (props.labels && props.labels.length !== stepCount.value + 1)\n console.warn(\n `[VSlider] ${props.labels.length} labels for ${stepCount.value + 1} steps — one label per step expected.`,\n )\n if (props.range && attrs.name !== undefined)\n console.warn(\n `[VSlider] name=\"${String(attrs.name)}\" on a range: only the end thumb carries it, so the form receives one value of the two. Bind the model to two inputs of your own instead.`,\n )\n}\n\n// The text held by the number fields, kept apart from the slider's own value.\n//\n// It is typed as text OR a number because these are number fields, whose value Vue\n// converts to a number as soon as it can be read as one — while an empty field, or one\n// holding a half-typed \"1-\", stays text. That is why the value is turned back into text\n// when it is committed. The start field exists in range mode only, and so does its sync.\nconst startFieldText = ref<string | number>(String(startValue.value))\nconst endFieldText = ref<string | number>(String(endValue.value))\n\n// Sliding the thumb keeps the fields in step, continuously.\nwatch(startValue, (v) => {\n if (props.range) startFieldText.value = String(v)\n})\nwatch(endValue, (v) => (endFieldText.value = String(v)))\n\n/**\n * Takes what was typed in a field and makes it the value — but only once the reader has\n * finished, on leaving the field or on Enter. Reading it as they type would clamp the\n * \"1\" of \"15\" to the minimum before the 5 was ever pressed.\n *\n * Anything unreadable, an empty field included, silently puts the previous value back.\n */\nfunction commitField(which: Thumb) {\n const raw = which === 'start' ? startFieldText.value : endFieldText.value\n // TRAP — parsed rather than converted: an empty string parses to nothing, which is\n // what triggers the revert below, where converting it would give ZERO and quietly\n // overwrite the value with it.\n const parsed = Number.parseFloat(String(raw))\n if (Number.isNaN(parsed)) {\n resyncFields()\n return\n }\n // Brought onto the nearest step. The rounding that follows removes the noise decimal\n // steps leave behind — a tenth cannot be represented exactly, so 0.1 × 3 comes out as\n // 0.30000000000000004.\n const clamped = clamp(parsed, props.min, props.max)\n let value = props.min + Math.round((clamped - props.min) / props.step) * props.step\n value = Math.min(props.max, Math.round(value * 1e10) / 1e10)\n const previous = thumbValue(which)\n const next = writeThumb(which, value)\n // Emitted only when the value MOVED, as a native range emits nothing for a key that\n // cannot move its thumb — and the payload is `next`, the model's local copy lagging a\n // parent `v-model` (see `onThumbChange`).\n if (writtenFor(next, which) !== previous) emit('change', next)\n // Put back explicitly, because a commit that does not change the value — typing 200\n // where the maximum is 100 — changes nothing for the watchers to react to, and the\n // field would go on showing what was typed.\n resyncFields()\n}\n\nfunction resyncFields() {\n if (props.range) startFieldText.value = String(startValue.value)\n endFieldText.value = String(endValue.value)\n}\n\nconst endThumbEl = ref<HTMLInputElement | null>(null)\n\n// The root is a layout box, so a template ref on the component reaches the wrapper and not\n// the control. Both members point at the END thumb: it is the one always rendered, and the\n// one the consumer's `id` lands on, so `focus()` goes where a `<label for>` would send it.\ndefineExpose({\n /** Moves the focus to the end thumb, the only thumb outside range mode. */\n focus: (options?: FocusOptions) => endThumbEl.value?.focus(options),\n /** The end thumb's real `<input type=\"range\">`, for what `focus` does not cover. */\n el: endThumbEl,\n})\n</script>\n\n<template>\n <div\n class=\"v-slider\"\n :class=\"rootClass\"\n :data-range=\"range ? '' : undefined\"\n :data-disabled=\"resolvedDisabled ? '' : undefined\"\n :data-readonly=\"readonly ? '' : undefined\"\n :data-invalid=\"invalid ? '' : undefined\"\n :data-size=\"resolvedSize\"\n :data-orientation=\"orientation\"\n :style=\"[\n rootStyle,\n {\n '--start-fraction': range ? String(frac(startValue)) : undefined,\n '--end-fraction': String(frac(endValue)),\n },\n ]\"\n >\n <VInput\n v-if=\"inputs && range\"\n v-model=\"startFieldText\"\n class=\"v-slider-field v-slider-field-start\"\n type=\"number\"\n :size=\"resolvedSize\"\n :compact=\"resolvedCompact\"\n :min=\"min\"\n :max=\"max\"\n :step=\"step\"\n :disabled=\"resolvedDisabled\"\n :readonly=\"readonly\"\n :invalid=\"invalid\"\n :aria-label=\"startLabel\"\n @change=\"commitField('start')\"\n />\n <div class=\"v-slider-rail\">\n <span class=\"v-slider-control\">\n <span class=\"v-slider-track\" aria-hidden=\"true\">\n <span class=\"v-slider-fill\" />\n <span\n v-for=\"(tick, i) in tickPlaces\"\n :key=\"i\"\n class=\"v-slider-tick\"\n :data-filled=\"isFilled(tick.value) ? '' : undefined\"\n :style=\"tick.style\"\n />\n </span>\n <input\n v-if=\"range\"\n type=\"range\"\n class=\"v-slider-input v-slider-input-start\"\n :min=\"min\"\n :max=\"max\"\n :step=\"step\"\n :disabled=\"resolvedDisabled\"\n :value=\"startValue\"\n :aria-label=\"startLabel\"\n :aria-valuetext=\"startValueText\"\n :aria-invalid=\"invalid || undefined\"\n :aria-readonly=\"readonly || undefined\"\n @keydown=\"onThumbKeydown\"\n @input=\"onThumbInput('start', $event)\"\n @change=\"onThumbChange('start', $event)\"\n />\n <!-- The consumer's attributes come FIRST, so what the component decides for\n itself — the bounds, the value, the disabled state and the thumb's own\n accessible name — cannot be overwritten by one of them. Naming a slider\n goes through the `label` prop, which is what gives each thumb of a range a\n name of its own. -->\n <input\n ref=\"endThumbEl\"\n v-bind=\"forwardedAttrs\"\n type=\"range\"\n class=\"v-slider-input v-slider-input-end\"\n :min=\"min\"\n :max=\"max\"\n :step=\"step\"\n :disabled=\"resolvedDisabled\"\n :value=\"endValue\"\n :aria-label=\"thumbEndLabel\"\n :aria-valuetext=\"endValueText\"\n :aria-invalid=\"invalid || undefined\"\n :aria-readonly=\"readonly || undefined\"\n @keydown=\"onThumbKeydown\"\n @input=\"onThumbInput('end', $event)\"\n @change=\"onThumbChange('end', $event)\"\n />\n </span>\n <span\n v-if=\"tooltip && range\"\n class=\"v-slider-tooltip v-slider-tooltip-start\"\n aria-hidden=\"true\"\n >\n <span class=\"v-slider-tooltip-bubble\">{{ startValueText ?? startValue }}</span>\n </span>\n <span v-if=\"tooltip\" class=\"v-slider-tooltip v-slider-tooltip-end\" aria-hidden=\"true\">\n <span class=\"v-slider-tooltip-bubble\">{{ endValueText ?? endValue }}</span>\n </span>\n </div>\n <div v-if=\"labels\" class=\"v-slider-labels\">\n <span\n v-for=\"(item, i) in labels\"\n :key=\"i\"\n class=\"v-slider-label\"\n :style=\"stepPlaces[i]?.style\"\n >\n <template v-if=\"typeof item === 'string'\">{{ item }}</template>\n <VIcon v-else v-bind=\"iconProps(item.icon)\" :label=\"item.label\" />\n </span>\n </div>\n <VInput\n v-if=\"inputs\"\n v-model=\"endFieldText\"\n class=\"v-slider-field v-slider-field-end\"\n type=\"number\"\n :size=\"resolvedSize\"\n :compact=\"resolvedCompact\"\n :min=\"min\"\n :max=\"max\"\n :step=\"step\"\n :disabled=\"resolvedDisabled\"\n :readonly=\"readonly\"\n :invalid=\"invalid\"\n :aria-label=\"fieldEndLabel\"\n @change=\"commitField('end')\"\n />\n </div>\n</template>\n\n<style>\n@layer vectis.components {\n .v-slider {\n --slider-thumb: var(--vectis-control-size-slider-thumb);\n --slider-track: var(--vectis-control-size-slider-track);\n display: grid;\n grid-template-areas: 'rail';\n grid-template-columns: minmax(0, 1fr);\n align-items: center;\n column-gap: var(--vectis-space-2);\n row-gap: var(--vectis-space-1);\n width: 100%;\n font-family: var(--vectis-text-family);\n }\n\n /*\n The zones the root lays out, from least to most furnished. `:has()` takes the\n specificity of its argument, so the single-condition rules are all (0,2,0) and the\n two-condition ones (0,3,0) — which means the five below are arbitrated by SOURCE\n ORDER as much as by weight, and a range slider with inputs matches three of them at\n once. They must stay in this order, each configuration overwriting the poorer one it\n builds on. Alphabetize them, or move `field-start` above `field-end`, and the start\n field lands outside the grid: no error, just a control sitting where nothing put it. */\n .v-slider:has(.v-slider-labels) {\n grid-template-areas: 'rail' 'labels';\n }\n\n .v-slider:has(.v-slider-field-end) {\n grid-template-areas: 'rail field-end';\n grid-template-columns: minmax(0, 1fr) auto;\n }\n\n .v-slider:has(.v-slider-field-end):has(.v-slider-labels) {\n grid-template-areas: 'rail field-end' 'labels .';\n }\n\n .v-slider:has(.v-slider-field-start) {\n grid-template-areas: 'field-start rail field-end';\n grid-template-columns: auto minmax(0, 1fr) auto;\n }\n\n .v-slider:has(.v-slider-field-start):has(.v-slider-labels) {\n grid-template-areas: 'field-start rail field-end' '. labels .';\n }\n\n .v-slider-rail {\n grid-area: rail;\n position: relative;\n block-size: var(--slider-thumb);\n }\n\n .v-slider-control {\n position: absolute;\n inset: 0;\n }\n\n .v-slider-track {\n position: absolute;\n inset-inline: 0;\n inset-block: 0;\n margin-block: auto;\n block-size: var(--slider-track);\n border-radius: var(--vectis-radius-pill);\n background: var(--vectis-color-border);\n overflow: hidden;\n }\n\n /*\n Where a thumb's CENTRE sits for the fraction `--fill-fraction`, written once for every\n element lined up with it: half a thumb in, then the fraction of the run that is left.\n\n TRAP — it must be declared on the element that CARRIES the fraction, never on an\n ancestor. A custom property's `var()` is resolved where the property is declared, so\n set on the root it would read a `--fill-fraction` the root does not have and turn\n invalid, and every tick, label and bubble would drop to its static position at the\n start of the track, with no error. The `100%`, on the other hand, stays a percentage\n until it is used, and resolves against the box of the property that reads it — the\n inline size of the track for an inset, the block size in the vertical rules. */\n .v-slider-fill,\n .v-slider-tick,\n .v-slider-tooltip,\n .v-slider-label {\n --slider-at: calc(\n var(--slider-thumb) / 2 + (100% - var(--slider-thumb)) * var(--fill-fraction)\n );\n }\n\n .v-slider-fill {\n --fill-fraction: var(--end-fraction);\n position: absolute;\n inset-block: 0;\n inset-inline-start: 0;\n inline-size: var(--slider-at);\n background: var(--vectis-color-accent);\n }\n\n .v-slider[data-range] .v-slider-fill {\n --fill-fraction: var(--start-fraction);\n inset-inline-start: var(--slider-at);\n inline-size: calc((100% - var(--slider-thumb)) * (var(--end-fraction) - var(--start-fraction)));\n }\n\n .v-slider-tick {\n --slider-tick: calc(var(--slider-track) / 3 * 2);\n position: absolute;\n inset-block: 0;\n margin-block: auto;\n inset-inline-start: calc(var(--slider-at) - var(--slider-tick) / 2);\n inline-size: var(--slider-tick);\n block-size: var(--slider-tick);\n border-radius: var(--vectis-radius-pill);\n background: var(--vectis-color-border-strong);\n }\n\n .v-slider-tick[data-filled] {\n background: var(--vectis-color-text-on-accent);\n }\n\n /* The two controls lie exactly on top of one another, so only their thumbs are allowed\n to receive the pointer. Without that, the one on top would swallow every click and\n the other thumb could never be grabbed.\n\n The thumb's paint lives in variables set HERE, on the control, and read once by each\n vendor pseudo-element below. That is what lets every state be written a single time:\n a state pseudo-class written after the thumb's own pseudo-element is unreliable across\n browsers, so a state has to be read on the control either way, and the thumb inherits\n the variables from it.\n\n The thumb is white in BOTH themes, the VSwitch thumb's colour: on a dark page a thumb\n painted in `surface` sinks into the track instead of standing out as the handle. */\n .v-slider-input {\n --slider-thumb-bg: var(--vectis-color-text-on-accent);\n --slider-thumb-border: var(--vectis-color-accent);\n --slider-thumb-shadow: var(--vectis-shadow-xs);\n --slider-thumb-outline: none;\n --slider-thumb-cursor: pointer;\n --slider-thumb-transition: background-color var(--vectis-duration-fast)\n var(--vectis-ease-default);\n position: absolute;\n inset: 0;\n width: 100%;\n height: 100%;\n margin: 0;\n appearance: none;\n background: transparent;\n pointer-events: none;\n }\n\n /* With a single thumb there is nothing underneath to protect, so the whole control\n takes the pointer again — which is what makes clicking the track jump the value\n there and start dragging at once, natively and with no code at all. The accepted\n side effect is that the thumb lights up when the pointer is anywhere over the\n track. */\n .v-slider:not([data-range]) .v-slider-input {\n pointer-events: auto;\n cursor: pointer;\n }\n\n /* TRAP — the two vendor pseudo-elements stay in two separate rules. A selector list\n holding one a browser does not know is dropped WHOLE, so merged, each engine would\n throw away the other's thumb and draw its native one. */\n .v-slider-input::-webkit-slider-thumb {\n appearance: none;\n pointer-events: auto;\n width: var(--slider-thumb);\n height: var(--slider-thumb);\n border-radius: var(--vectis-radius-pill);\n background: var(--slider-thumb-bg);\n border: var(--vectis-control-border-width) solid var(--slider-thumb-border);\n box-shadow: var(--slider-thumb-shadow);\n outline: var(--slider-thumb-outline);\n outline-offset: var(--vectis-focus-ring-offset);\n cursor: var(--slider-thumb-cursor);\n transition: var(--slider-thumb-transition);\n }\n\n .v-slider-input::-moz-range-thumb {\n pointer-events: auto;\n width: var(--slider-thumb);\n height: var(--slider-thumb);\n border-radius: var(--vectis-radius-pill);\n background: var(--slider-thumb-bg);\n border: var(--vectis-control-border-width) solid var(--slider-thumb-border);\n box-shadow: var(--slider-thumb-shadow);\n outline: var(--slider-thumb-outline);\n outline-offset: var(--vectis-focus-ring-offset);\n cursor: var(--slider-thumb-cursor);\n transition: var(--slider-thumb-transition);\n }\n\n /* The states, all at (0,3,0) but the base, so their ORDER arbitrates them: hover, then\n read-only, invalid and disabled, each overriding what came before on a thumb that is\n several at once.\n\n The hover tint is mixed from the thumb's own white rather than read from\n `accent-surface`: that token turns dark in the dark theme, and a white thumb would\n flash nearly black under the pointer. */\n .v-slider-input:is(:hover, :active):not(:disabled) {\n --slider-thumb-bg: color-mix(\n in oklab,\n var(--vectis-color-text-on-accent),\n var(--vectis-color-accent) 10%\n );\n }\n\n .v-slider-input:focus-visible {\n --slider-thumb-outline: var(--vectis-focus-ring-width) solid var(--vectis-focus-ring-color);\n outline: none;\n }\n\n /* The muted text colour a read-only VCheckbox takes, on the fill and the thumb's ring:\n the value stays plainly readable, the accent no longer invites a drag. */\n .v-slider[data-readonly] .v-slider-input {\n --slider-thumb-bg: var(--vectis-color-surface);\n --slider-thumb-border: var(--vectis-color-text-muted);\n --slider-thumb-cursor: default;\n cursor: default;\n }\n\n .v-slider[data-readonly] .v-slider-fill {\n background: var(--vectis-color-text-muted);\n }\n\n .v-slider[data-readonly] .v-slider-tick[data-filled] {\n background: var(--vectis-color-surface);\n }\n\n /* The border colour VCheckbox and VRadio take when invalid, on the thumb's ring. */\n .v-slider[data-invalid] .v-slider-input {\n --slider-thumb-border: var(--vectis-color-danger);\n }\n\n /* The bubble showing the value. It looks like a VTooltip but is placed by arithmetic\n rather than anchored to the thumb: a native thumb is a pseudo-element, and the\n browser's anchoring cannot attach anything to one. The fraction it follows is the one\n the root already carries for the fill. */\n .v-slider-tooltip {\n position: absolute;\n inset-block-end: calc(100% + var(--vectis-space-2));\n inset-inline-start: var(--slider-at);\n inline-size: 0;\n display: flex;\n justify-content: center;\n opacity: 0;\n visibility: hidden;\n transition:\n opacity var(--vectis-duration-fast) var(--vectis-ease-default),\n visibility var(--vectis-duration-fast) var(--vectis-ease-default);\n }\n\n .v-slider-tooltip-start {\n --fill-fraction: var(--start-fraction);\n }\n\n .v-slider-tooltip-end {\n --fill-fraction: var(--end-fraction);\n }\n\n .v-slider:has(.v-slider-input-start:active) .v-slider-tooltip-start,\n .v-slider:has(.v-slider-input-start:focus-visible) .v-slider-tooltip-start,\n .v-slider:has(.v-slider-input-end:active) .v-slider-tooltip-end,\n .v-slider:has(.v-slider-input-end:focus-visible) .v-slider-tooltip-end {\n opacity: 1;\n visibility: visible;\n }\n\n .v-slider-tooltip-bubble {\n padding: var(--vectis-space-1) var(--vectis-space-2);\n background: var(--vectis-color-surface-inverse);\n color: var(--vectis-color-text-on-inverse);\n font-size: var(--vectis-text-caption-size);\n line-height: var(--vectis-text-caption-leading);\n /* VTooltip's bubble corner, so the two tooltips of the design system stay one shape. */\n border-radius: min(var(--vectis-radius-interactive), calc(0.5lh + var(--vectis-space-1)));\n box-shadow: var(--vectis-shadow-sm);\n white-space: nowrap;\n }\n\n .v-slider-labels {\n grid-area: labels;\n position: relative;\n /* The labels are positioned individually and therefore contribute no height of\n their own; this reserves enough room for either kind, a small line of text or an\n icon. */\n min-block-size: var(--vectis-icon-size-md);\n --vectis-icon-size: var(--vectis-icon-size-md);\n font-size: var(--vectis-text-caption-size);\n color: var(--vectis-color-text-muted);\n }\n\n /* A box of zero width placed exactly on the step: its content then overflows equally\n on both sides, which centres it there. Centring it with a transform would be the\n usual trick, but a transform is physical and would have to be undone for the\n vertical orientation and again for a right-to-left page. */\n .v-slider-label {\n position: absolute;\n inset-block-start: 0;\n inset-inline-start: var(--slider-at);\n inline-size: 0;\n display: flex;\n justify-content: center;\n white-space: nowrap;\n }\n\n .v-slider-field.v-input {\n inline-size: var(--vectis-control-size-slider-field);\n }\n\n .v-slider-field-start {\n grid-area: field-start;\n }\n\n .v-slider-field-end {\n grid-area: field-end;\n }\n\n .v-slider[data-orientation='vertical'] {\n grid-template-areas: 'rail';\n grid-template-columns: none;\n inline-size: fit-content;\n justify-items: center;\n }\n\n .v-slider[data-orientation='vertical']:has(.v-slider-labels) {\n grid-template-areas: 'rail labels';\n grid-template-columns: auto auto;\n }\n\n .v-slider[data-orientation='vertical']:has(.v-slider-field-end) {\n grid-template-areas: 'field-end' 'rail';\n grid-template-columns: none;\n }\n\n .v-slider[data-orientation='vertical']:has(.v-slider-field-end):has(.v-slider-labels) {\n grid-template-areas: 'field-end .' 'rail labels';\n grid-template-columns: auto auto;\n }\n\n .v-slider[data-orientation='vertical']:has(.v-slider-field-start) {\n grid-template-areas: 'field-end' 'rail' 'field-start';\n grid-template-columns: none;\n }\n\n .v-slider[data-orientation='vertical']:has(.v-slider-field-start):has(.v-slider-labels) {\n grid-template-areas: 'field-end .' 'rail labels' 'field-start .';\n grid-template-columns: auto auto;\n }\n\n .v-slider[data-orientation='vertical'] .v-slider-rail {\n inline-size: var(--slider-thumb);\n block-size: var(--vectis-control-size-slider-length);\n }\n\n /* Only this inner box is turned upright, and that is the whole trick: the track, the\n fill and the ticks are all placed with logical properties, so they follow the change\n of axis with no rule written a second time — while the bubbles and the labels stay\n outside that box, and therefore keep their text horizontal.\n\n The direction is reversed with it so that the lowest value ends up at the bottom. */\n .v-slider[data-orientation='vertical'] .v-slider-control {\n writing-mode: vertical-lr;\n direction: rtl;\n }\n\n .v-slider[data-orientation='vertical'] .v-slider-tooltip {\n inset-block-end: var(--slider-at);\n inset-inline-start: auto;\n inset-inline-end: calc(100% + var(--vectis-space-2));\n inline-size: auto;\n block-size: 0;\n align-items: center;\n justify-content: flex-end;\n }\n\n .v-slider[data-orientation='vertical'] .v-slider-labels {\n align-self: stretch;\n min-block-size: auto;\n }\n\n .v-slider[data-orientation='vertical'] .v-slider-label {\n inset-block-start: auto;\n inset-block-end: var(--slider-at);\n inset-inline-start: 0;\n inline-size: auto;\n block-size: 0;\n align-items: center;\n justify-content: flex-start;\n }\n\n /* A disabled slider greys out through the colour tokens, the same ones VCheckbox and\n VSwitch use, and never through opacity. It comes LAST among the states, so a slider\n both disabled and read-only or invalid is drawn disabled. */\n .v-slider[data-disabled] {\n cursor: not-allowed;\n }\n\n .v-slider[data-disabled] .v-slider-track {\n background: var(--vectis-color-surface-muted);\n }\n\n .v-slider[data-disabled] .v-slider-fill {\n background: var(--vectis-color-text-subtle);\n }\n\n .v-slider[data-disabled] .v-slider-tick {\n background: var(--vectis-color-text-subtle);\n }\n\n /* A tick sitting on the greyed fill takes the light colour back, so that it stays\n visible against it — the same inversion VCheckbox applies to its disabled tick. */\n .v-slider[data-disabled] .v-slider-tick[data-filled] {\n background: var(--vectis-color-surface-muted);\n }\n\n .v-slider[data-disabled] .v-slider-labels {\n color: var(--vectis-color-text-subtle);\n }\n\n .v-slider[data-disabled] .v-slider-input {\n --slider-thumb-bg: var(--vectis-color-surface-muted);\n --slider-thumb-border: var(--vectis-color-text-subtle);\n --slider-thumb-shadow: none;\n --slider-thumb-cursor: not-allowed;\n cursor: not-allowed;\n }\n\n @media (prefers-reduced-motion: reduce) {\n .v-slider-input {\n --slider-thumb-transition: none;\n }\n\n .v-slider-tooltip {\n transition: none;\n }\n }\n}\n</style>\n"],"mappings":""}
|