vectis-ui 0.14.0 → 0.15.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/dist/components/VAccordion/VAccordion.js.map +1 -1
- package/dist/components/VAccordion/VAccordion.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VAccordion/VAccordionItem.js.map +1 -1
- package/dist/components/VAccordion/VAccordionItem.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VAccordion/context.js.map +1 -1
- package/dist/components/VAlert/VAlert.js.map +1 -1
- package/dist/components/VAlert/VAlert.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VAvatar/VAvatar.js.map +1 -1
- package/dist/components/VAvatar/VAvatar.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VAvatar/VAvatarGroup.js.map +1 -1
- package/dist/components/VAvatar/VAvatarGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VAvatar/context.js.map +1 -1
- package/dist/components/VBadge/VBadge.js.map +1 -1
- package/dist/components/VBadge/VBadge.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/components/VBadge/VBadge.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VBreadcrumb/VBreadcrumb.js.map +1 -1
- package/dist/components/VBreadcrumb/VBreadcrumb.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VButton/VButton.js.map +1 -1
- package/dist/components/VButton/VButton.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VButton/VButtonGroup.js.map +1 -1
- package/dist/components/VButton/VButtonGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VButton/context.js.map +1 -1
- package/dist/components/VCalendar/VCalendar.js.map +1 -1
- package/dist/components/VCalendar/VCalendar.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VCalendar/VCalendarEvent.js.map +1 -1
- package/dist/components/VCalendar/VCalendarEvent.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VCalendar/VCalendarMonth.js.map +1 -1
- package/dist/components/VCalendar/VCalendarMonth.vue_vue_type_script_setup_true_lang.js +5 -17
- package/dist/components/VCalendar/VCalendarMonth.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VCalendar/VCalendarTimeGrid.js.map +1 -1
- package/dist/components/VCalendar/VCalendarTimeGrid.vue_vue_type_script_setup_true_lang.js +19 -31
- package/dist/components/VCalendar/VCalendarTimeGrid.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VCalendar/VCalendarYear.js.map +1 -1
- package/dist/components/VCalendar/VCalendarYear.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VCalendar/color.js.map +1 -1
- package/dist/components/VCalendar/edgeStep.js +1 -5
- package/dist/components/VCalendar/edgeStep.js.map +1 -1
- package/dist/components/VCalendar/gesture.js +4 -12
- package/dist/components/VCalendar/gesture.js.map +1 -1
- package/dist/components/VCalendar/keyboard.js.map +1 -1
- package/dist/components/VCalendar/layout.js +8 -12
- package/dist/components/VCalendar/layout.js.map +1 -1
- package/dist/components/VCalendar/timeGrid.js +5 -5
- package/dist/components/VCalendar/timeGrid.js.map +1 -1
- package/dist/components/VCard/VCard.js.map +1 -1
- package/dist/components/VCard/VCard.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VCarousel/VCarousel.js.map +1 -1
- package/dist/components/VCarousel/VCarousel.vue_vue_type_script_setup_true_lang.js.map +1 -1
- 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.js.map +1 -1
- package/dist/components/VCheckbox/VCheckMark.js.map +1 -1
- package/dist/components/VCheckbox/VCheckMark.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VCheckbox/VCheckbox.js.map +1 -1
- package/dist/components/VCheckbox/VCheckbox.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VChip/VChip.js.map +1 -1
- package/dist/components/VChip/VChip.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VColorInput/VColorInput.js.map +1 -1
- package/dist/components/VColorInput/VColorInput.vue_vue_type_script_setup_true_lang.js +62 -62
- package/dist/components/VColorInput/VColorInput.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VColorPicker/VColorPicker.js.map +1 -1
- package/dist/components/VColorPicker/VColorPicker.vue_vue_type_script_setup_true_lang.js +1 -5
- package/dist/components/VColorPicker/VColorPicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VColorPicker/color.js.map +1 -1
- package/dist/components/VCombobox/VCombobox.js.map +1 -1
- package/dist/components/VCombobox/VCombobox.vue_vue_type_script_setup_true_lang.js +114 -122
- package/dist/components/VCombobox/VCombobox.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VCommandPalette/VCommandPalette.js.map +1 -1
- package/dist/components/VCommandPalette/VCommandPalette.vue_vue_type_script_setup_true_lang.js +0 -1
- package/dist/components/VCommandPalette/VCommandPalette.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VCommandPalette/VCommandPaletteItem.js.map +1 -1
- package/dist/components/VCommandPalette/VCommandPaletteItem.vue_vue_type_script_setup_true_lang.js +1 -5
- package/dist/components/VCommandPalette/VCommandPaletteItem.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VContextMenu/VContextMenu.js.map +1 -1
- package/dist/components/VContextMenu/VContextMenu.vue_vue_type_script_setup_true_lang.js +3 -5
- package/dist/components/VContextMenu/VContextMenu.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VDataTable/VDataTable.js.map +1 -1
- package/dist/components/VDataTable/VDataTable.vue_vue_type_script_setup_true_lang.js +1 -5
- package/dist/components/VDataTable/VDataTable.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VDateInput/VDateInput.js.map +1 -1
- package/dist/components/VDateInput/VDateInput.vue_vue_type_script_setup_true_lang.js +35 -35
- package/dist/components/VDateInput/VDateInput.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VDateInput/mask.js.map +1 -1
- package/dist/components/VDatePicker/VDatePicker.js.map +1 -1
- package/dist/components/VDatePicker/VDatePicker.vue_vue_type_script_setup_true_lang.js +2 -1
- package/dist/components/VDatePicker/VDatePicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VDatePicker/keyboard.js.map +1 -1
- package/dist/components/VDatePicker/names.js.map +1 -1
- package/dist/components/VDialog/VDialog.js.map +1 -1
- package/dist/components/VDialog/VDialog.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VDialog/VDialogAlert.js.map +1 -1
- package/dist/components/VDialog/VDialogAlert.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VDrawer/VDrawer.js.map +1 -1
- package/dist/components/VDrawer/VDrawer.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VEmptyState/VEmptyState.js.map +1 -1
- package/dist/components/VEmptyState/VEmptyState.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VField/VField.js.map +1 -1
- package/dist/components/VField/VField.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VField/VFieldAnnouncer.js.map +1 -1
- package/dist/components/VField/VFieldAnnouncer.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VField/VFieldMessage.js.map +1 -1
- package/dist/components/VField/VFieldMessage.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VFieldset/VFieldset.js.map +1 -1
- package/dist/components/VFieldset/VFieldset.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VFileInput/VFileInput.js.map +1 -1
- package/dist/components/VFileInput/VFileInput.vue_vue_type_script_setup_true_lang.js +85 -85
- package/dist/components/VFileInput/VFileInput.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VFileInput/truncate.js.map +1 -1
- package/dist/components/VFilePicker/VFilePicker.js.map +1 -1
- package/dist/components/VFilePicker/VFilePicker.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/components/VFilePicker/VFilePicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VFilePicker/fileKind.js.map +1 -1
- package/dist/components/VHotkeys/VHotkeys.js.map +1 -1
- package/dist/components/VHotkeys/VHotkeys.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VHotkeys/platform.js +1 -1
- package/dist/components/VHotkeys/platform.js.map +1 -1
- package/dist/components/VHoverCard/VHoverCard.js.map +1 -1
- package/dist/components/VHoverCard/VHoverCard.vue_vue_type_script_setup_true_lang.js +2 -12
- package/dist/components/VHoverCard/VHoverCard.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VIcon/VIcon.js.map +1 -1
- 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/add.js.map +1 -1
- package/dist/components/VIcon/icons/arrow_downward.js.map +1 -1
- package/dist/components/VIcon/icons/arrow_downward_alt.js.map +1 -1
- package/dist/components/VIcon/icons/arrow_drop_down.js.map +1 -1
- package/dist/components/VIcon/icons/arrow_drop_up.js.map +1 -1
- package/dist/components/VIcon/icons/arrow_left_alt.js.map +1 -1
- package/dist/components/VIcon/icons/arrow_right_alt.js.map +1 -1
- package/dist/components/VIcon/icons/arrow_upward.js.map +1 -1
- package/dist/components/VIcon/icons/arrow_upward_alt.js.map +1 -1
- package/dist/components/VIcon/icons/attach_file.js.map +1 -1
- package/dist/components/VIcon/icons/audio_file.js.map +1 -1
- package/dist/components/VIcon/icons/calendar_today.js.map +1 -1
- package/dist/components/VIcon/icons/check.js.map +1 -1
- package/dist/components/VIcon/icons/check_circle.js.map +1 -1
- package/dist/components/VIcon/icons/chevron_left.js.map +1 -1
- package/dist/components/VIcon/icons/chevron_right.js.map +1 -1
- package/dist/components/VIcon/icons/close.js.map +1 -1
- package/dist/components/VIcon/icons/cloud_upload.js.map +1 -1
- package/dist/components/VIcon/icons/code.js.map +1 -1
- package/dist/components/VIcon/icons/colorize.js.map +1 -1
- package/dist/components/VIcon/icons/description.js.map +1 -1
- package/dist/components/VIcon/icons/error.js.map +1 -1
- package/dist/components/VIcon/icons/expand_less.js.map +1 -1
- package/dist/components/VIcon/icons/expand_more.js.map +1 -1
- package/dist/components/VIcon/icons/first_page.js.map +1 -1
- package/dist/components/VIcon/icons/folder_zip.js.map +1 -1
- package/dist/components/VIcon/icons/image.js.map +1 -1
- package/dist/components/VIcon/icons/inbox.js.map +1 -1
- package/dist/components/VIcon/icons/index.js.map +1 -1
- package/dist/components/VIcon/icons/info.js.map +1 -1
- package/dist/components/VIcon/icons/last_page.js.map +1 -1
- package/dist/components/VIcon/icons/more_horiz.js.map +1 -1
- package/dist/components/VIcon/icons/names.js.map +1 -1
- package/dist/components/VIcon/icons/notifications.js.map +1 -1
- package/dist/components/VIcon/icons/open_in_new.js.map +1 -1
- package/dist/components/VIcon/icons/picture_as_pdf.js.map +1 -1
- package/dist/components/VIcon/icons/priority_high.js.map +1 -1
- package/dist/components/VIcon/icons/remove.js.map +1 -1
- package/dist/components/VIcon/icons/schedule.js.map +1 -1
- package/dist/components/VIcon/icons/search.js.map +1 -1
- package/dist/components/VIcon/icons/search_off.js.map +1 -1
- package/dist/components/VIcon/icons/star.js.map +1 -1
- package/dist/components/VIcon/icons/swap_vert.js.map +1 -1
- package/dist/components/VIcon/icons/table_chart.js.map +1 -1
- package/dist/components/VIcon/icons/video_file.js.map +1 -1
- package/dist/components/VIcon/icons/viewBox.js.map +1 -1
- package/dist/components/VIcon/icons/warning.js.map +1 -1
- package/dist/components/VIcon/resolver.js.map +1 -1
- package/dist/components/VIconButton/VIconButton.js.map +1 -1
- package/dist/components/VIconButton/VIconButton.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VInput/VInput.js.map +1 -1
- package/dist/components/VInput/VInput.vue_vue_type_script_setup_true_lang.js +20 -20
- package/dist/components/VInput/VInput.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VInput/VInputGroup.js.map +1 -1
- package/dist/components/VInput/VInputGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VInput/context.js.map +1 -1
- package/dist/components/VInputOTP/VInputOTP.js.map +1 -1
- package/dist/components/VInputOTP/VInputOTP.vue_vue_type_script_setup_true_lang.js +2 -8
- package/dist/components/VInputOTP/VInputOTP.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VLink/VLink.js.map +1 -1
- package/dist/components/VLink/VLink.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VListbox/VListboxChevron.js.map +1 -1
- package/dist/components/VListbox/VListboxChevron.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VListbox/VListboxGroup.js.map +1 -1
- package/dist/components/VListbox/VListboxGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VListbox/VListboxOption.js.map +1 -1
- package/dist/components/VListbox/VListboxOption.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VListbox/VListboxPanel.js.map +1 -1
- package/dist/components/VListbox/VListboxPanel.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VListbox/VListboxSeparator.js.map +1 -1
- package/dist/components/VListbox/VListboxSeparator.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VListbox/VListboxValues.js.map +1 -1
- package/dist/components/VListbox/VListboxValues.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VMenu/VMenu.js.map +1 -1
- package/dist/components/VMenu/VMenu.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VMenu/VMenuGroup.js.map +1 -1
- package/dist/components/VMenu/VMenuGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VMenu/VMenuItem.js.map +1 -1
- package/dist/components/VMenu/VMenuItem.vue_vue_type_script_setup_true_lang.js +6 -12
- package/dist/components/VMenu/VMenuItem.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VMenu/VMenuPanel.js.map +1 -1
- package/dist/components/VMenu/VMenuPanel.vue_vue_type_script_setup_true_lang.js +9 -10
- package/dist/components/VMenu/VMenuPanel.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VMenu/VMenuSeparator.js.map +1 -1
- package/dist/components/VMenu/VMenuSeparator.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VMenu/context.js.map +1 -1
- package/dist/components/VMeter/VMeter.js.map +1 -1
- package/dist/components/VMeter/VMeter.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VNumberInput/VNumberInput.js.map +1 -1
- package/dist/components/VNumberInput/VNumberInput.vue_vue_type_script_setup_true_lang.js +86 -85
- package/dist/components/VNumberInput/VNumberInput.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VNumberInput/number.js.map +1 -1
- package/dist/components/VPagination/VPagination.js.map +1 -1
- package/dist/components/VPagination/VPagination.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VPopover/VPopover.js.map +1 -1
- package/dist/components/VPopover/VPopover.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VProgressCircular/VProgressCircular.js.map +1 -1
- package/dist/components/VProgressCircular/VProgressCircular.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VProgressLinear/VProgressLinear.js.map +1 -1
- package/dist/components/VProgressLinear/VProgressLinear.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VRadio/VRadio.js.map +1 -1
- package/dist/components/VRadio/VRadio.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VRating/VRating.js.map +1 -1
- package/dist/components/VRating/VRating.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VResizable/VResizable.js.map +1 -1
- package/dist/components/VResizable/VResizable.vue_vue_type_script_setup_true_lang.js +8 -6
- package/dist/components/VResizable/VResizable.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VResizable/VResizablePanel.js.map +1 -1
- package/dist/components/VResizable/VResizablePanel.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VResizable/context.js.map +1 -1
- package/dist/components/VResizable/layout.js.map +1 -1
- package/dist/components/VSelect/VSelect.js.map +1 -1
- package/dist/components/VSelect/VSelect.vue_vue_type_script_setup_true_lang.js +124 -125
- package/dist/components/VSelect/VSelect.vue_vue_type_script_setup_true_lang.js.map +1 -1
- 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.js.map +1 -1
- package/dist/components/VSideNavigation/VSideNavigation.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/components/VSideNavigation/VSideNavigation.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VSideNavigation/VSideNavigationGroup.js.map +1 -1
- package/dist/components/VSideNavigation/VSideNavigationGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VSideNavigation/VSideNavigationItem.js.map +1 -1
- package/dist/components/VSideNavigation/VSideNavigationItem.vue_vue_type_script_setup_true_lang.js +1 -5
- package/dist/components/VSideNavigation/VSideNavigationItem.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VSideNavigation/VSideNavigationSeparator.js.map +1 -1
- package/dist/components/VSideNavigation/context.js.map +1 -1
- 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.js.map +1 -1
- package/dist/components/VSlider/VSlider.vue_vue_type_script_setup_true_lang.js +22 -22
- package/dist/components/VSlider/VSlider.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VSnackbar/VSnackbar.js.map +1 -1
- package/dist/components/VSnackbar/VSnackbar.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VSnackbar/state.js.map +1 -1
- package/dist/components/VSpinner/VSpinner.js.map +1 -1
- package/dist/components/VSpinner/VSpinner.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VSplitButton/VSplitButton.js.map +1 -1
- package/dist/components/VSplitButton/VSplitButton.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VStepper/VStepper.js.map +1 -1
- package/dist/components/VStepper/VStepper.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VSwitch/VSwitch.js.map +1 -1
- package/dist/components/VSwitch/VSwitch.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VTabs/VTab.js.map +1 -1
- package/dist/components/VTabs/VTab.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VTabs/VTabPanel.js.map +1 -1
- package/dist/components/VTabs/VTabPanel.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VTabs/VTabs.js.map +1 -1
- package/dist/components/VTabs/VTabs.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VTabs/context.js.map +1 -1
- package/dist/components/VTextarea/VTextarea.js.map +1 -1
- package/dist/components/VTextarea/VTextarea.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VTimeInput/VTimeInput.js.map +1 -1
- package/dist/components/VTimeInput/VTimeInput.vue_vue_type_script_setup_true_lang.js +45 -45
- package/dist/components/VTimeInput/VTimeInput.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VTimeInput/search.js.map +1 -1
- package/dist/components/VTimePicker/VTimePicker.js.map +1 -1
- package/dist/components/VTimePicker/VTimePicker.vue_vue_type_script_setup_true_lang.js +9 -9
- package/dist/components/VTimePicker/VTimePicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VTimePicker/limits.js.map +1 -1
- package/dist/components/VTimeline/VTimeline.js.map +1 -1
- package/dist/components/VTimeline/VTimeline.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VTimeline/VTimelineItem.js.map +1 -1
- package/dist/components/VTimeline/VTimelineItem.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VTimeline/context.js.map +1 -1
- package/dist/components/VTimeline/datetime.js.map +1 -1
- package/dist/components/VToast/VToast.js.map +1 -1
- package/dist/components/VToast/VToast.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VToast/VToaster.js.map +1 -1
- package/dist/components/VToast/VToaster.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/components/VToast/VToaster.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VToast/state.js.map +1 -1
- package/dist/components/VToggle/VToggle.js.map +1 -1
- package/dist/components/VToggle/VToggle.vue_vue_type_script_setup_true_lang.js +1 -7
- package/dist/components/VToggle/VToggle.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VToggle/VToggleItem.js.map +1 -1
- package/dist/components/VToggle/VToggleItem.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VToggle/context.js.map +1 -1
- package/dist/components/VTooltip/VTooltip.js.map +1 -1
- package/dist/components/VTooltip/VTooltip.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VTreeView/VTreeView.js.map +1 -1
- package/dist/components/VTreeView/VTreeView.vue_vue_type_script_setup_true_lang.js +1 -5
- package/dist/components/VTreeView/VTreeView.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/components/VVirtualList/VVirtualList.js.map +1 -1
- package/dist/components/VVirtualList/VVirtualList.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/composables/useAriaLabel.js.map +1 -1
- package/dist/composables/useChoice.js.map +1 -1
- package/dist/composables/useClearable.js.map +1 -1
- package/dist/composables/useControlShape.js.map +1 -1
- package/dist/composables/useDebouncedSearch.js.map +1 -1
- package/dist/composables/useDetailsOpen.js.map +1 -1
- package/dist/composables/useEscapeDismiss.js.map +1 -1
- package/dist/composables/useFieldIds.js.map +1 -1
- package/dist/composables/useFieldPanel.js +3 -7
- package/dist/composables/useFieldPanel.js.map +1 -1
- package/dist/composables/useFileDrop.js.map +1 -1
- package/dist/composables/useFileField.js +2 -2
- package/dist/composables/useFileField.js.map +1 -1
- package/dist/composables/useFocusoutDismiss.js.map +1 -1
- package/dist/composables/useHotkeyListener.js.map +1 -1
- package/dist/composables/useIconClickHandlers.js.map +1 -1
- package/dist/composables/useInertLink.js.map +1 -1
- package/dist/composables/useInfiniteScroll.js +2 -2
- package/dist/composables/useInfiniteScroll.js.map +1 -1
- package/dist/composables/useListbox.js +3 -9
- package/dist/composables/useListbox.js.map +1 -1
- package/dist/composables/useLiveAnnouncer.js.map +1 -1
- package/dist/composables/useMaskedField.js +28 -48
- package/dist/composables/useMaskedField.js.map +1 -1
- package/dist/composables/useModalDialog.js +1 -1
- package/dist/composables/useModalDialog.js.map +1 -1
- package/dist/composables/usePopover.js +1 -1
- package/dist/composables/usePopover.js.map +1 -1
- package/dist/composables/useProgressValue.js.map +1 -1
- package/dist/composables/useRootAttrs.js.map +1 -1
- package/dist/composables/useSlotNodes.js.map +1 -1
- package/dist/composables/useTextLimit.js.map +1 -1
- package/dist/composables/useTimer.js.map +1 -1
- package/dist/composables/useTypeahead.js.map +1 -1
- package/dist/composables/useVirtualList.js.map +1 -1
- package/dist/i18n/en.js.map +1 -1
- package/dist/i18n/fr.js.map +1 -1
- package/dist/i18n/state.js.map +1 -1
- package/dist/tokens/css.js.map +1 -1
- package/dist/tokens/index.js.map +1 -1
- package/dist/tokens/primitives.js.map +1 -1
- package/dist/tokens/semantic.js.map +1 -1
- package/dist/tokens/themes/dark.js.map +1 -1
- package/dist/tokens/types.js.map +1 -1
- package/dist/utils/array.js.map +1 -1
- package/dist/utils/arrowNav.js.map +1 -1
- package/dist/utils/attrs.js.map +1 -1
- package/dist/utils/chip.js.map +1 -1
- package/dist/utils/clock.js +3 -1
- package/dist/utils/clock.js.map +1 -1
- package/dist/utils/css.js +1 -1
- package/dist/utils/css.js.map +1 -1
- package/dist/utils/date.js.map +1 -1
- package/dist/utils/direction.js.map +1 -1
- package/dist/utils/env.js.map +1 -1
- package/dist/utils/file.js +13 -31
- package/dist/utils/file.js.map +1 -1
- package/dist/utils/focus.js.map +1 -1
- package/dist/utils/hostWarns.js.map +1 -1
- package/dist/utils/ids.js.map +1 -1
- package/dist/utils/matcher.js.map +1 -1
- package/dist/utils/memo.js.map +1 -1
- package/dist/utils/number.js.map +1 -1
- package/dist/utils/text.js.map +1 -1
- package/dist/utils/time.js.map +1 -1
- package/dist/utils/vnode.js.map +1 -1
- package/package.json +19 -19
|
@@ -2,73 +2,55 @@ import { digitsOf as e } from "../utils/text.js";
|
|
|
2
2
|
import { computed as t, ref as n, watch as r } from "vue";
|
|
3
3
|
//#region src/composables/useMaskedField.ts
|
|
4
4
|
function i(i) {
|
|
5
|
-
let a = n(""), o = i.acceptable ?? (() => !0);
|
|
6
|
-
r(
|
|
5
|
+
let a = n(""), o = i.acceptable ?? (() => !0), s = t(() => i.toMask(i.readValue()));
|
|
6
|
+
r(s, (e) => {
|
|
7
7
|
e !== a.value && (a.value = e);
|
|
8
8
|
}, { immediate: !0 });
|
|
9
|
-
let
|
|
9
|
+
let c = t({
|
|
10
10
|
get: () => i.typing() ? a.value : i.displayText(),
|
|
11
11
|
set: (e) => {
|
|
12
12
|
i.typing() && (a.value = String(e ?? ""));
|
|
13
13
|
}
|
|
14
14
|
});
|
|
15
|
-
function
|
|
15
|
+
function l(e, t) {
|
|
16
16
|
a.value = e;
|
|
17
17
|
let n = i.fieldEl.value;
|
|
18
18
|
n && (n.value !== e && (n.value = e), t !== void 0 && n.setSelectionRange(t, t));
|
|
19
19
|
}
|
|
20
|
-
function
|
|
20
|
+
function u() {
|
|
21
21
|
let e = i.parse(a.value, !1);
|
|
22
22
|
e && o(e) && e !== i.readValue() && i.writeValue(e);
|
|
23
23
|
}
|
|
24
|
-
function
|
|
24
|
+
function d() {
|
|
25
25
|
if (!i.typing()) return;
|
|
26
26
|
if (!e(a.value)) {
|
|
27
|
-
i.readValue() !== null && i.writeValue(null),
|
|
27
|
+
i.readValue() !== null && i.writeValue(null), l("");
|
|
28
28
|
return;
|
|
29
29
|
}
|
|
30
30
|
let t = i.parse(a.value, !0);
|
|
31
|
-
|
|
32
|
-
t !== i.readValue() && i.writeValue(t), c(i.toMask(t));
|
|
33
|
-
return;
|
|
34
|
-
}
|
|
35
|
-
c(i.toMask(i.readValue()));
|
|
31
|
+
t && o(t) ? (t !== i.readValue() && i.writeValue(t), l(i.toMask(t))) : l(i.toMask(i.readValue()));
|
|
36
32
|
}
|
|
37
|
-
function
|
|
33
|
+
function f(t) {
|
|
38
34
|
if (!i.typing()) return;
|
|
39
|
-
let n = t.target, r = n.value, a = n.selectionStart ?? r.length, o = e(r.slice(0, a)).length, s = e(r).slice(0, i.maxDigits()),
|
|
40
|
-
|
|
35
|
+
let n = t.target, r = n.value, a = n.selectionStart ?? r.length, o = e(r.slice(0, a)).length, s = e(r).slice(0, i.maxDigits()), c = !String(t.inputType ?? "").startsWith("delete"), d = i.format(s);
|
|
36
|
+
l(d, i.caret(d, Math.min(o, s.length), c)), u();
|
|
41
37
|
}
|
|
42
|
-
function
|
|
38
|
+
function p(t) {
|
|
43
39
|
let n = t.selectionStart;
|
|
44
40
|
if (n === null || n !== t.selectionEnd || n === 0 || /\d/.test(t.value[n - 1] ?? "")) return !1;
|
|
45
41
|
let r = e(t.value.slice(0, n)).length, a = e(t.value), o = i.format(a.slice(0, r - 1) + a.slice(r));
|
|
46
|
-
return
|
|
42
|
+
return l(o, i.caret(o, r - 1, !1)), u(), !0;
|
|
47
43
|
}
|
|
48
|
-
function
|
|
49
|
-
let r = t.selectionStart ?? t.value.length, a = t.selectionEnd ?? r, o = e(t.value), s = e(t.value.slice(0, r)).length,
|
|
50
|
-
|
|
44
|
+
function m(t, n) {
|
|
45
|
+
let r = t.selectionStart ?? t.value.length, a = t.selectionEnd ?? r, o = e(t.value), s = e(t.value.slice(0, r)).length, c = e(t.value.slice(0, a)).length, d = e(n), f = (o.slice(0, s) + d + o.slice(c)).slice(0, i.maxDigits()), p = i.format(f);
|
|
46
|
+
l(p, i.caret(p, Math.min(s + d.length, f.length), !0)), u();
|
|
51
47
|
}
|
|
52
|
-
function
|
|
48
|
+
function h(e, t) {
|
|
53
49
|
if (!i.typing()) return;
|
|
54
50
|
let n = i.fieldEl.value;
|
|
55
|
-
|
|
56
|
-
if (e.key === "Enter") {
|
|
57
|
-
e.preventDefault(), u(), t.onEnter?.();
|
|
58
|
-
return;
|
|
59
|
-
}
|
|
60
|
-
if (e.key === "ArrowDown") {
|
|
61
|
-
t.onArrowDown?.() && e.preventDefault();
|
|
62
|
-
return;
|
|
63
|
-
}
|
|
64
|
-
if (e.key === "Backspace") {
|
|
65
|
-
f(n) && e.preventDefault();
|
|
66
|
-
return;
|
|
67
|
-
}
|
|
68
|
-
e.key.length === 1 && !e.ctrlKey && !e.metaKey && !e.altKey && !/\d/.test(e.key) && (e.preventDefault(), t.onSeparator(n));
|
|
69
|
-
}
|
|
51
|
+
n && (e.key === "Enter" ? (e.preventDefault(), d(), t.onEnter?.()) : e.key === "ArrowDown" ? t.onArrowDown?.() && e.preventDefault() : e.key === "Backspace" ? p(n) && e.preventDefault() : e.key.length === 1 && !e.ctrlKey && !e.metaKey && !e.altKey && !/\d/.test(e.key) && (e.preventDefault(), t.onSeparator(n)));
|
|
70
52
|
}
|
|
71
|
-
function
|
|
53
|
+
function g(e, t) {
|
|
72
54
|
if (!i.typing()) return;
|
|
73
55
|
let n = i.fieldEl.value;
|
|
74
56
|
if (!n) return;
|
|
@@ -76,20 +58,18 @@ function i(i) {
|
|
|
76
58
|
let r = (e.clipboardData?.getData("text") ?? "").trim(), a = t(r);
|
|
77
59
|
if (a) {
|
|
78
60
|
let e = i.toMask(a);
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
}
|
|
82
|
-
p(n, r);
|
|
61
|
+
l(e, e.length), o(a) && a !== i.readValue() && i.writeValue(a);
|
|
62
|
+
} else m(n, r);
|
|
83
63
|
}
|
|
84
64
|
return {
|
|
85
65
|
draft: a,
|
|
86
|
-
fieldModel:
|
|
87
|
-
writeField:
|
|
88
|
-
commitLive:
|
|
89
|
-
commitOrRevert:
|
|
90
|
-
onFieldInput:
|
|
91
|
-
onKeydown:
|
|
92
|
-
onPaste:
|
|
66
|
+
fieldModel: c,
|
|
67
|
+
writeField: l,
|
|
68
|
+
commitLive: u,
|
|
69
|
+
commitOrRevert: d,
|
|
70
|
+
onFieldInput: f,
|
|
71
|
+
onKeydown: h,
|
|
72
|
+
onPaste: g
|
|
93
73
|
};
|
|
94
74
|
}
|
|
95
75
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useMaskedField.js","names":[],"sources":["../../src/composables/useMaskedField.ts"],"sourcesContent":["// @core\n/**\n * Share digit masking, caret preservation and commit logic between date and time fields; each\n * component supplies its format and parser.\n */\nimport { computed, ref, watch, type Ref, type WritableComputedRef } from 'vue'\n\nimport { digitsOf } from '../utils/text'\n\nexport interface MaskedFieldOptions<T extends string> {\n /** The real input, which is written to directly: see below. */\n fieldEl: Ref<HTMLInputElement | null>\n /** Whether the field can be typed into at all. Everything here is inert when it cannot. */\n typing: () => boolean\n /** What the field shows when it is not being typed into: the value, written out in full. */\n displayText: () => string\n /** The current value, or nothing. */\n readValue: () => T | null\n /** Writes a new value. */\n writeValue: (value: T | null) => void\n /** How many digits the mask holds: eight for a date, four for a time. */\n maxDigits: () => number\n /** Lays a run of digits out as masked text. */\n format: (digits: string) => string\n /**\n * Where the caret goes so as to sit after a given number of digits. The flag says whether\n * something was INSERTED rather than deleted, and it matters: on a deletion the caret must\n * stay in FRONT of the separator, or the next press of the key would step over it instead of\n * erasing, and the key would appear to do nothing.\n */\n caret: (text: string, digitsBefore: number, inserting: boolean) => number\n /** Reads masked text back into a value, or nothing when it is not one yet. */\n parse: (text: string, final: boolean) => T | null\n /** Writes a value as masked text, and nothing at all for no value. */\n toMask: (value: T | null) => string\n /**\n * Whether a value the reader has finished typing may be taken: within the bounds, not\n * one of the excluded days. Everything is acceptable by default.\n */\n acceptable?: (value: T) => boolean\n}\n\n/** What a component adds to the mask's own keys. */\nexport interface MaskedKeyHooks {\n /** A key that is not a digit was typed: a separator, most often. */\n onSeparator: (el: HTMLInputElement) => void\n /**\n * The down arrow, which a component with a panel turns into the way into it. It answers\n * whether it handled the press: only then is the default cancelled, and a press left\n * alone travels on to whatever opens the panel.\n */\n onArrowDown?: () => boolean\n /** Runs once Enter has committed or reverted what was typed: closing a panel, say. */\n onEnter?: () => void\n}\n\nexport interface MaskedField<T extends string> {\n /** The text currently in the field while it is being typed into. */\n draft: Ref<string>\n /**\n * Bind with `v-model` and never `:model-value`. Without an `onUpdate:modelValue` listener,\n * `useModel` keeps an internal copy of the RAW typed text and rewrites it on the next patch,\n * erasing the mask exactly when the masked text did not change: a rejected character, or a\n * digit past the last.\n */\n fieldModel: WritableComputedRef<string | number>\n /**\n * Writes into both the draft and the input. Both are needed: Vue does not patch an element\n * whose value it believes unchanged, and after a reformat it often is.\n */\n writeField: (text: string, caret?: number) => void\n /** Takes the value as soon as what has been typed is complete and acceptable. */\n commitLive: () => void\n /** Called as the reader leaves the field. It is safe to call twice. */\n commitOrRevert: () => void\n /** The handler to bind to the field's input event. */\n onFieldInput: (event: Event) => void\n /** The handler for the field's keydown event, with what the component adds to it. */\n onKeydown: (event: KeyboardEvent, hooks: MaskedKeyHooks) => void\n /** The handler for the field's paste event. */\n onPaste: (event: ClipboardEvent, recognize: (pasted: string) => T | null) => void\n}\n\nexport function useMaskedField<T extends string>(options: MaskedFieldOptions<T>): MaskedField<T> {\n const draft = ref('')\n const acceptable = options.acceptable ?? (() => true)\n\n /*\n * The value as masked text. Being a computed it also tracks what the conversion reads; the\n * locale's mask, the hour cycle; so neither component lists those dependencies.\n */\n const maskedValue = computed(() => options.toMask(options.readValue()))\n\n watch(\n maskedValue,\n (next) => {\n // The anti-loop guard. A commit made while typing writes the value, which comes straight\n // back here; without the test, the text being typed and its caret would be overwritten by\n // text identical to what is already there.\n if (next !== draft.value) draft.value = next\n },\n { immediate: true },\n )\n\n const fieldModel = computed<string | number>({\n get: () => (options.typing() ? draft.value : options.displayText()),\n set: (value) => {\n if (options.typing()) draft.value = String(value ?? '')\n },\n })\n\n function writeField(text: string, caret?: number) {\n draft.value = text\n const el = options.fieldEl.value\n if (!el) return\n if (el.value !== text) el.value = text\n if (caret !== undefined) el.setSelectionRange(caret, caret)\n }\n\n function commitLive() {\n const value = options.parse(draft.value, false)\n if (value && acceptable(value) && value !== options.readValue()) options.writeValue(value)\n }\n\n /** Commits what was typed, or SILENTLY reverts to the current value. */\n function commitOrRevert() {\n if (!options.typing()) return\n if (!digitsOf(draft.value)) {\n if (options.readValue() !== null) options.writeValue(null)\n writeField('')\n return\n }\n const value = options.parse(draft.value, true)\n if (value && acceptable(value)) {\n if (value !== options.readValue()) options.writeValue(value)\n writeField(options.toMask(value))\n return\n }\n writeField(options.toMask(options.readValue()))\n }\n\n /**\n * Reformats the field on every keystroke. Restoring an absolute position instead would\n * misplace the caret on exactly the keystrokes that matter: a position jumps by one the\n * moment a separator appears or disappears.\n */\n function onFieldInput(event: Event) {\n if (!options.typing()) return\n const el = event.target as HTMLInputElement\n const raw = el.value\n const caret = el.selectionStart ?? raw.length\n const before = digitsOf(raw.slice(0, caret)).length\n const digits = digitsOf(raw).slice(0, options.maxDigits())\n const inserting = !String((event as InputEvent).inputType ?? '').startsWith('delete')\n const text = options.format(digits)\n writeField(text, options.caret(text, Math.min(before, digits.length), inserting))\n commitLive()\n }\n\n /*\n * A separator is placed by the mask and never typed, so erasing one has to erase the DIGIT\n * before it, which the reader believes they are erasing. Left alone, the mask writes the\n * separator straight back and the key looks dead.\n */\n function backspaceOverSeparator(el: HTMLInputElement) {\n const start = el.selectionStart\n if (\n start === null ||\n start !== el.selectionEnd ||\n start === 0 ||\n /\\d/.test(el.value[start - 1] ?? '')\n ) {\n return false\n }\n const before = digitsOf(el.value.slice(0, start)).length\n const digits = digitsOf(el.value)\n const text = options.format(digits.slice(0, before - 1) + digits.slice(before))\n writeField(text, options.caret(text, before - 1, false))\n commitLive()\n return true\n }\n\n /**\n * Splices a pasted run of digits into the one already in the field, at the selection, and\n * puts the caret after what was inserted.\n */\n function pasteDigits(el: HTMLInputElement, pasted: string) {\n const start = el.selectionStart ?? el.value.length\n const end = el.selectionEnd ?? start\n const digits = digitsOf(el.value)\n const from = digitsOf(el.value.slice(0, start)).length\n const to = digitsOf(el.value.slice(0, end)).length\n const inserted = digitsOf(pasted)\n const next = (digits.slice(0, from) + inserted + digits.slice(to)).slice(0, options.maxDigits())\n const text = options.format(next)\n writeField(text, options.caret(text, Math.min(from + inserted.length, next.length), true))\n commitLive()\n }\n\n // @keyboard\n function onKeydown(event: KeyboardEvent, hooks: MaskedKeyHooks) {\n if (!options.typing()) return\n const el = options.fieldEl.value\n if (!el) return\n\n if (event.key === 'Enter') {\n // Cancelling the default does two things at once: it stops the surrounding form from\n // being submitted, and it stops a panel this keystroke closes from being reopened as\n // the event travels up to the component's root.\n event.preventDefault()\n commitOrRevert()\n hooks.onEnter?.()\n return\n }\n if (event.key === 'ArrowDown') {\n if (hooks.onArrowDown?.()) event.preventDefault()\n return\n }\n if (event.key === 'Backspace') {\n if (backspaceOverSeparator(el)) event.preventDefault()\n return\n }\n if (\n event.key.length === 1 &&\n !event.ctrlKey &&\n !event.metaKey &&\n !event.altKey &&\n !/\\d/.test(event.key)\n ) {\n event.preventDefault()\n hooks.onSeparator(el)\n }\n }\n\n /**\n * Pasting. Without the whole-value path, pasting \"2026-06-10\" into a field expecting day,\n * month, year would produce \"20/26/0610\": the digits would be taken in order and the\n * separators ignored.\n */\n function onPaste(event: ClipboardEvent, recognize: (pasted: string) => T | null) {\n if (!options.typing()) return\n const el = options.fieldEl.value\n if (!el) return\n event.preventDefault()\n const pasted = (event.clipboardData?.getData('text') ?? '').trim()\n const whole = recognize(pasted)\n if (whole) {\n const text = options.toMask(whole)\n writeField(text, text.length)\n if (acceptable(whole) && whole !== options.readValue()) options.writeValue(whole)\n return\n }\n pasteDigits(el, pasted)\n }\n\n return {\n draft,\n fieldModel,\n writeField,\n commitLive,\n commitOrRevert,\n onFieldInput,\n onKeydown,\n onPaste,\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"useMaskedField.js","names":["useMaskedField","draft","ref","acceptable","options","maskedValue","computed","next","fieldModel","value","writeField","text","el","caret","commitLive","commitOrRevert","digitsOf","onFieldInput","event","raw","before","digits","inserting","backspaceOverSeparator","start","pasteDigits","end","from","to","inserted","pasted","onKeydown","hooks","onPaste","whole","recognize"],"sources":["../../src/composables/useMaskedField.ts"],"sourcesContent":["// @core\n/**\n * Share digit masking, caret preservation and commit logic between date and time fields; each\n * component supplies its format and parser.\n */\nimport { computed, ref, watch, type Ref, type WritableComputedRef } from 'vue'\n\nimport { digitsOf } from '../utils/text'\n\nexport interface MaskedFieldOptions<T extends string> {\n /** The real input, which is written to directly: see below. */\n fieldEl: Ref<HTMLInputElement | null>\n /** Whether the field can be typed into at all. Everything here is inert when it cannot. */\n typing: () => boolean\n /** What the field shows when it is not being typed into: the value, written out in full. */\n displayText: () => string\n /** The current value, or nothing. */\n readValue: () => T | null\n /** Writes a new value. */\n writeValue: (value: T | null) => void\n /** How many digits the mask holds: eight for a date, four for a time. */\n maxDigits: () => number\n /** Lays a run of digits out as masked text. */\n format: (digits: string) => string\n /**\n * Where the caret goes so as to sit after a given number of digits. The flag says whether\n * something was INSERTED rather than deleted, and it matters: on a deletion the caret must\n * stay in FRONT of the separator, or the next press of the key would step over it instead of\n * erasing, and the key would appear to do nothing.\n */\n caret: (text: string, digitsBefore: number, inserting: boolean) => number\n /** Reads masked text back into a value, or nothing when it is not one yet. */\n parse: (text: string, final: boolean) => T | null\n /** Writes a value as masked text, and nothing at all for no value. */\n toMask: (value: T | null) => string\n /**\n * Whether a value the reader has finished typing may be taken: within the bounds, not\n * one of the excluded days. Everything is acceptable by default.\n */\n acceptable?: (value: T) => boolean\n}\n\n/** What a component adds to the mask's own keys. */\nexport interface MaskedKeyHooks {\n /** A key that is not a digit was typed: a separator, most often. */\n onSeparator: (el: HTMLInputElement) => void\n /**\n * The down arrow, which a component with a panel turns into the way into it. It answers\n * whether it handled the press: only then is the default cancelled, and a press left\n * alone travels on to whatever opens the panel.\n */\n onArrowDown?: () => boolean\n /** Runs once Enter has committed or reverted what was typed: closing a panel, say. */\n onEnter?: () => void\n}\n\nexport interface MaskedField<T extends string> {\n /** The text currently in the field while it is being typed into. */\n draft: Ref<string>\n /**\n * Bind with `v-model` and never `:model-value`. Without an `onUpdate:modelValue` listener,\n * `useModel` keeps an internal copy of the RAW typed text and rewrites it on the next patch,\n * erasing the mask exactly when the masked text did not change: a rejected character, or a\n * digit past the last.\n */\n fieldModel: WritableComputedRef<string | number>\n /**\n * Writes into both the draft and the input. Both are needed: Vue does not patch an element\n * whose value it believes unchanged, and after a reformat it often is.\n */\n writeField: (text: string, caret?: number) => void\n /** Takes the value as soon as what has been typed is complete and acceptable. */\n commitLive: () => void\n /** Called as the reader leaves the field. It is safe to call twice. */\n commitOrRevert: () => void\n /** The handler to bind to the field's input event. */\n onFieldInput: (event: Event) => void\n /** The handler for the field's keydown event, with what the component adds to it. */\n onKeydown: (event: KeyboardEvent, hooks: MaskedKeyHooks) => void\n /** The handler for the field's paste event. */\n onPaste: (event: ClipboardEvent, recognize: (pasted: string) => T | null) => void\n}\n\nexport function useMaskedField<T extends string>(options: MaskedFieldOptions<T>): MaskedField<T> {\n const draft = ref('')\n const acceptable = options.acceptable ?? (() => true)\n\n /*\n * The value as masked text. Being a computed it also tracks what the conversion reads; the\n * locale's mask, the hour cycle; so neither component lists those dependencies.\n */\n const maskedValue = computed(() => options.toMask(options.readValue()))\n\n watch(\n maskedValue,\n (next) => {\n // The anti-loop guard. A commit made while typing writes the value, which comes straight\n // back here; without the test, the text being typed and its caret would be overwritten by\n // text identical to what is already there.\n if (next !== draft.value) draft.value = next\n },\n { immediate: true },\n )\n\n const fieldModel = computed<string | number>({\n get: () => (options.typing() ? draft.value : options.displayText()),\n set: (value) => {\n if (options.typing()) draft.value = String(value ?? '')\n },\n })\n\n function writeField(text: string, caret?: number) {\n draft.value = text\n const el = options.fieldEl.value\n if (!el) return\n if (el.value !== text) el.value = text\n if (caret !== undefined) el.setSelectionRange(caret, caret)\n }\n\n function commitLive() {\n const value = options.parse(draft.value, false)\n if (value && acceptable(value) && value !== options.readValue()) options.writeValue(value)\n }\n\n /** Commits what was typed, or SILENTLY reverts to the current value. */\n function commitOrRevert() {\n if (!options.typing()) return\n if (!digitsOf(draft.value)) {\n if (options.readValue() !== null) options.writeValue(null)\n writeField('')\n return\n }\n const value = options.parse(draft.value, true)\n if (value && acceptable(value)) {\n if (value !== options.readValue()) options.writeValue(value)\n writeField(options.toMask(value))\n return\n }\n writeField(options.toMask(options.readValue()))\n }\n\n /**\n * Reformats the field on every keystroke. Restoring an absolute position instead would\n * misplace the caret on exactly the keystrokes that matter: a position jumps by one the\n * moment a separator appears or disappears.\n */\n function onFieldInput(event: Event) {\n if (!options.typing()) return\n const el = event.target as HTMLInputElement\n const raw = el.value\n const caret = el.selectionStart ?? raw.length\n const before = digitsOf(raw.slice(0, caret)).length\n const digits = digitsOf(raw).slice(0, options.maxDigits())\n const inserting = !String((event as InputEvent).inputType ?? '').startsWith('delete')\n const text = options.format(digits)\n writeField(text, options.caret(text, Math.min(before, digits.length), inserting))\n commitLive()\n }\n\n /*\n * A separator is placed by the mask and never typed, so erasing one has to erase the DIGIT\n * before it, which the reader believes they are erasing. Left alone, the mask writes the\n * separator straight back and the key looks dead.\n */\n function backspaceOverSeparator(el: HTMLInputElement) {\n const start = el.selectionStart\n if (\n start === null ||\n start !== el.selectionEnd ||\n start === 0 ||\n /\\d/.test(el.value[start - 1] ?? '')\n ) {\n return false\n }\n const before = digitsOf(el.value.slice(0, start)).length\n const digits = digitsOf(el.value)\n const text = options.format(digits.slice(0, before - 1) + digits.slice(before))\n writeField(text, options.caret(text, before - 1, false))\n commitLive()\n return true\n }\n\n /**\n * Splices a pasted run of digits into the one already in the field, at the selection, and\n * puts the caret after what was inserted.\n */\n function pasteDigits(el: HTMLInputElement, pasted: string) {\n const start = el.selectionStart ?? el.value.length\n const end = el.selectionEnd ?? start\n const digits = digitsOf(el.value)\n const from = digitsOf(el.value.slice(0, start)).length\n const to = digitsOf(el.value.slice(0, end)).length\n const inserted = digitsOf(pasted)\n const next = (digits.slice(0, from) + inserted + digits.slice(to)).slice(0, options.maxDigits())\n const text = options.format(next)\n writeField(text, options.caret(text, Math.min(from + inserted.length, next.length), true))\n commitLive()\n }\n\n // @keyboard\n function onKeydown(event: KeyboardEvent, hooks: MaskedKeyHooks) {\n if (!options.typing()) return\n const el = options.fieldEl.value\n if (!el) return\n\n if (event.key === 'Enter') {\n // Cancelling the default does two things at once: it stops the surrounding form from\n // being submitted, and it stops a panel this keystroke closes from being reopened as\n // the event travels up to the component's root.\n event.preventDefault()\n commitOrRevert()\n hooks.onEnter?.()\n return\n }\n if (event.key === 'ArrowDown') {\n if (hooks.onArrowDown?.()) event.preventDefault()\n return\n }\n if (event.key === 'Backspace') {\n if (backspaceOverSeparator(el)) event.preventDefault()\n return\n }\n if (\n event.key.length === 1 &&\n !event.ctrlKey &&\n !event.metaKey &&\n !event.altKey &&\n !/\\d/.test(event.key)\n ) {\n event.preventDefault()\n hooks.onSeparator(el)\n }\n }\n\n /**\n * Pasting. Without the whole-value path, pasting \"2026-06-10\" into a field expecting day,\n * month, year would produce \"20/26/0610\": the digits would be taken in order and the\n * separators ignored.\n */\n function onPaste(event: ClipboardEvent, recognize: (pasted: string) => T | null) {\n if (!options.typing()) return\n const el = options.fieldEl.value\n if (!el) return\n event.preventDefault()\n const pasted = (event.clipboardData?.getData('text') ?? '').trim()\n const whole = recognize(pasted)\n if (whole) {\n const text = options.toMask(whole)\n writeField(text, text.length)\n if (acceptable(whole) && whole !== options.readValue()) options.writeValue(whole)\n return\n }\n pasteDigits(el, pasted)\n }\n\n return {\n draft,\n fieldModel,\n writeField,\n commitLive,\n commitOrRevert,\n onFieldInput,\n onKeydown,\n onPaste,\n }\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useModalDialog.js","names":[],"sources":["../../src/composables/useModalDialog.ts"],"sourcesContent":["import { computed, nextTick, onBeforeUnmount, ref, useAttrs, watch } from 'vue'\nimport type { Ref } from 'vue'\n\n// @core\n/**\n * The bridge between a `v-model:open` and a native modal `<dialog>`, shared by VDialog and\n * VDrawer. Native showModal supplies top-layer placement and modal focus; this bridges the model\n * to the imperative open and close, and provides guarded dismissal where closedBy is absent.\n *\n * The element is rendered only while it is needed. With `exitTransition`, it outlives its\n * closing until the transitions it runs on the way out have finished.\n */\nexport function useModalDialog(\n open: Ref<boolean>,\n options: {\n persistentBackdrop: () => boolean\n persistentEscape: () => boolean\n exitTransition?: boolean\n },\n) {\n const attrs = useAttrs()\n const dialogEl = ref<HTMLDialogElement | null>(null)\n\n /** Whether the `<dialog>` is in the page: while open, and through its exit if it has one. */\n const leaving = ref(false)\n const rendered = computed(() => open.value || leaving.value)\n\n /**\n * Which dismissals the browser itself accepts, declared as an attribute rather than handled in\n * code: everything, Escape alone, or nothing. One combination cannot be expressed that way; a\n * click outside allowed while Escape is not; and it falls back to allowing both.\n */\n const closedby = computed(() =>\n options.persistentBackdrop() ? (options.persistentEscape() ? 'none' : 'closerequest') : 'any',\n )\n\n // @fallback\n // The `closedby` attribute is newer than the type definitions shipped with TypeScript, so\n // writing it directly in the template would be reported as an unknown attribute. Passing it\n // inside a bound object goes through the same path as any forwarded attribute, which is not\n // checked element by element.\n const rootAttrs = computed(() => ({ ...attrs, closedby: closedby.value }))\n\n function show(): Promise<void> {\n open.value = true\n return nextTick()\n }\n\n function close() {\n // Closing the element is enough: the browser then fires its own close event, which puts the\n // model back in step below.\n dialogEl.value?.close()\n }\n\n // Close before v-if removes the element so the browser restores the invoker's focus.\n watch(open, (value) => {\n if (!value) dialogEl.value?.close()\n // Reopened during its exit, the same element is shown again and its transitions reverse.\n else if (dialogEl.value && !dialogEl.value.open) dialogEl.value.showModal()\n })\n\n // @ssr\n // Template refs become available after mounting, including when hydrating an open dialog.\n watch(dialogEl, (dialog) => dialog?.showModal(), { flush: 'post' })\n\n /*\n * Each closing is counted, so that the end of an exit interrupted by a reopening, then\n * followed by a second closing, does not remove the element in the middle of the second exit.\n */\n let closings = 0\n async function leave(dialog: HTMLDialogElement) {\n const closing = ++closings\n leaving.value = true\n // Reading the animations flushes the style change the closing made, so the exit\n // transitions have already started. A reversed or cancelled one rejects: either way it is\n // over.\n await Promise.allSettled(dialog.getAnimations().map((animation) => animation.finished))\n if (closing === closings && !open.value) leaving.value = false\n }\n\n // Ignore close events from replaced elements: the queued event from a quick close-and-reopen\n // must not close the new dialog.\n function onClose(event: Event) {\n const dialog = dialogEl.value\n if (!dialog || event.target !== dialog) return\n open.value = false\n if (options.exitTransition) void leave(dialog)\n }\n\n // @core\n // An open dialog removed with its parent (a `v-if`, a route change) runs no close steps,\n // so no close event would come: the model is handed back closed here, or it stayed `true`\n // and the dialog reopened by itself the next time its parent was shown.\n onBeforeUnmount(() => {\n if (open.value) open.value = false\n })\n\n // @fallback\n /*\n * `closedby` is what applies `persistentBackdrop` and `persistentEscape`, and Safari does not\n * implement it: there Escape always closes and the backdrop never does. The two halves are\n * rebuilt below, and only where the attribute is unknown, so a browser that has it is never\n * second-guessed.\n */\n const closedbyUnsupported = () => !('closedBy' in HTMLDialogElement.prototype)\n\n function onCancel(event: Event) {\n if (closedbyUnsupported() && closedby.value === 'none') event.preventDefault()\n }\n\n /**\n * Whether a point lies outside the dialog's box, which is where the backdrop is: a click on\n * the `::backdrop` is dispatched to the dialog element itself.\n */\n function outsideBox(event: MouseEvent) {\n const box = dialogEl.value?.getBoundingClientRect()\n if (!box) return false\n return (\n event.clientX < box.left ||\n event.clientX > box.right ||\n event.clientY < box.top ||\n event.clientY > box.bottom\n )\n }\n\n // A press that STARTED inside and ended on the backdrop (a text selection dragged past the\n // edge) is not a click on the backdrop, so the press is remembered, not only the release.\n let pressedOnBackdrop = false\n function onPointerdown(event: PointerEvent) {\n pressedOnBackdrop =\n closedbyUnsupported() && event.target === dialogEl.value && outsideBox(event)\n }\n function onBackdropClick(event: MouseEvent) {\n const onBackdrop = pressedOnBackdrop && event.target === dialogEl.value && outsideBox(event)\n pressedOnBackdrop = false\n if (onBackdrop && closedbyUnsupported() && closedby.value === 'any') close()\n }\n\n return {\n dialogEl,\n rendered,\n rootAttrs,\n show,\n close,\n onClose,\n onCancel,\n onPointerdown,\n onBackdropClick,\n }\n}\n"],"mappings":";;AAYA,
|
|
1
|
+
{"version":3,"file":"useModalDialog.js","names":["useModalDialog","attrs","useAttrs","dialogEl","ref","leaving","rendered","computed","open","closedby","options","rootAttrs","show","nextTick","close","watch","value","dialog","closings","leave","closing","animation","onClose","event","closedbyUnsupported","onCancel","outsideBox","box","pressedOnBackdrop","onPointerdown","onBackdropClick","onBackdrop"],"sources":["../../src/composables/useModalDialog.ts"],"sourcesContent":["import { computed, nextTick, onBeforeUnmount, ref, useAttrs, watch } from 'vue'\nimport type { Ref } from 'vue'\n\n// @core\n/**\n * The bridge between a `v-model:open` and a native modal `<dialog>`, shared by VDialog and\n * VDrawer. Native showModal supplies top-layer placement and modal focus; this bridges the model\n * to the imperative open and close, and provides guarded dismissal where closedBy is absent.\n *\n * The element is rendered only while it is needed. With `exitTransition`, it outlives its\n * closing until the transitions it runs on the way out have finished.\n */\nexport function useModalDialog(\n open: Ref<boolean>,\n options: {\n persistentBackdrop: () => boolean\n persistentEscape: () => boolean\n exitTransition?: boolean\n },\n) {\n const attrs = useAttrs()\n const dialogEl = ref<HTMLDialogElement | null>(null)\n\n /** Whether the `<dialog>` is in the page: while open, and through its exit if it has one. */\n const leaving = ref(false)\n const rendered = computed(() => open.value || leaving.value)\n\n /**\n * Which dismissals the browser itself accepts, declared as an attribute rather than handled in\n * code: everything, Escape alone, or nothing. One combination cannot be expressed that way; a\n * click outside allowed while Escape is not; and it falls back to allowing both.\n */\n const closedby = computed(() =>\n options.persistentBackdrop() ? (options.persistentEscape() ? 'none' : 'closerequest') : 'any',\n )\n\n // @fallback\n // The `closedby` attribute is newer than the type definitions shipped with TypeScript, so\n // writing it directly in the template would be reported as an unknown attribute. Passing it\n // inside a bound object goes through the same path as any forwarded attribute, which is not\n // checked element by element.\n const rootAttrs = computed(() => ({ ...attrs, closedby: closedby.value }))\n\n function show(): Promise<void> {\n open.value = true\n return nextTick()\n }\n\n function close() {\n // Closing the element is enough: the browser then fires its own close event, which puts the\n // model back in step below.\n dialogEl.value?.close()\n }\n\n // Close before v-if removes the element so the browser restores the invoker's focus.\n watch(open, (value) => {\n if (!value) dialogEl.value?.close()\n // Reopened during its exit, the same element is shown again and its transitions reverse.\n else if (dialogEl.value && !dialogEl.value.open) dialogEl.value.showModal()\n })\n\n // @ssr\n // Template refs become available after mounting, including when hydrating an open dialog.\n watch(dialogEl, (dialog) => dialog?.showModal(), { flush: 'post' })\n\n /*\n * Each closing is counted, so that the end of an exit interrupted by a reopening, then\n * followed by a second closing, does not remove the element in the middle of the second exit.\n */\n let closings = 0\n async function leave(dialog: HTMLDialogElement) {\n const closing = ++closings\n leaving.value = true\n // Reading the animations flushes the style change the closing made, so the exit\n // transitions have already started. A reversed or cancelled one rejects: either way it is\n // over.\n await Promise.allSettled(dialog.getAnimations().map((animation) => animation.finished))\n if (closing === closings && !open.value) leaving.value = false\n }\n\n // Ignore close events from replaced elements: the queued event from a quick close-and-reopen\n // must not close the new dialog.\n function onClose(event: Event) {\n const dialog = dialogEl.value\n if (!dialog || event.target !== dialog) return\n open.value = false\n if (options.exitTransition) void leave(dialog)\n }\n\n // @core\n // An open dialog removed with its parent (a `v-if`, a route change) runs no close steps,\n // so no close event would come: the model is handed back closed here, or it stayed `true`\n // and the dialog reopened by itself the next time its parent was shown.\n onBeforeUnmount(() => {\n if (open.value) open.value = false\n })\n\n // @fallback\n /*\n * `closedby` is what applies `persistentBackdrop` and `persistentEscape`, and Safari does not\n * implement it: there Escape always closes and the backdrop never does. The two halves are\n * rebuilt below, and only where the attribute is unknown, so a browser that has it is never\n * second-guessed.\n */\n const closedbyUnsupported = () => !('closedBy' in HTMLDialogElement.prototype)\n\n function onCancel(event: Event) {\n if (closedbyUnsupported() && closedby.value === 'none') event.preventDefault()\n }\n\n /**\n * Whether a point lies outside the dialog's box, which is where the backdrop is: a click on\n * the `::backdrop` is dispatched to the dialog element itself.\n */\n function outsideBox(event: MouseEvent) {\n const box = dialogEl.value?.getBoundingClientRect()\n if (!box) return false\n return (\n event.clientX < box.left ||\n event.clientX > box.right ||\n event.clientY < box.top ||\n event.clientY > box.bottom\n )\n }\n\n // A press that STARTED inside and ended on the backdrop (a text selection dragged past the\n // edge) is not a click on the backdrop, so the press is remembered, not only the release.\n let pressedOnBackdrop = false\n function onPointerdown(event: PointerEvent) {\n pressedOnBackdrop =\n closedbyUnsupported() && event.target === dialogEl.value && outsideBox(event)\n }\n function onBackdropClick(event: MouseEvent) {\n const onBackdrop = pressedOnBackdrop && event.target === dialogEl.value && outsideBox(event)\n pressedOnBackdrop = false\n if (onBackdrop && closedbyUnsupported() && closedby.value === 'any') close()\n }\n\n return {\n dialogEl,\n rendered,\n rootAttrs,\n show,\n close,\n onClose,\n onCancel,\n onPointerdown,\n onBackdropClick,\n }\n}\n"],"mappings":";;AAYA,SAAgBA,EACd,GACA,GAKA;CACA,IAAMC,IAAQC,EAAS,GACjBC,IAAWC,EAA8B,IAAI,GAG7CC,IAAUD,EAAI,EAAK,GACnBE,IAAWC,QAAeC,EAAK,SAASH,EAAQ,KAAK,GAOrDI,IAAWF,QACfG,EAAQ,mBAAmB,IAAKA,EAAQ,iBAAiB,IAAI,SAAS,iBAAkB,KAC1F,GAOMC,IAAYJ,SAAgB;EAAE,GAAGN;EAAO,UAAUQ,EAAS;CAAM,EAAE;CAEzE,SAASG,IAAsB;EAE7B,OADA,EAAK,QAAQ,IACNC,EAAS;CAClB;CAEA,SAASC,IAAQ;EAGf,EAAS,OAAO,MAAM;CACxB;CAWA,AARAC,EAAMP,IAAO,MAAU;EACrB,AAAKQ,IAEIb,EAAS,SAAS,CAACA,EAAS,MAAM,QAAMA,EAAS,MAAM,UAAU,IAF9DA,EAAS,OAAO,MAAM;CAGpC,CAAC,GAIDY,EAAMZ,IAAW,MAAWc,GAAQ,UAAU,GAAG,EAAE,OAAO,OAAO,CAAC;CAMlE,IAAIC,IAAW;CACf,eAAeC,EAAM,GAA2B;EAC9C,IAAMC,IAAU,EAAEF;EAMlB,AALA,EAAQ,QAAQ,IAIhB,MAAM,QAAQ,WAAWD,EAAO,cAAc,CAAC,CAAC,KAAK,MAAcI,EAAU,QAAQ,CAAC,GAClFD,MAAYF,KAAY,CAACV,EAAK,UAAO,EAAQ,QAAQ;CAC3D;CAIA,SAASc,EAAQ,GAAc;EAC7B,IAAML,IAASd,EAAS;EACxB,AAAKc,KAAUM,EAAM,WAAWN,MAChC,EAAK,QAAQ,IACTP,EAAQ,kBAAgBS,EAAWF,CAAM;CAC/C;CAMA,QAAsB;EACpB,AAAgBT,EAAK,UAAQ;CAC/B,CAAC;CASD,IAAMgB,UAA4B,EAAE,cAAc,kBAAkB;CAEpE,SAASC,EAAS,GAAc;EAC9B,AAAID,EAAoB,KAAKf,EAAS,UAAU,UAAQc,EAAM,eAAe;CAC/E;CAMA,SAASG,EAAW,GAAmB;EACrC,IAAMC,IAAMxB,EAAS,OAAO,sBAAsB;EAElD,OADKwB,IAEHJ,EAAM,UAAUI,EAAI,QACpBJ,EAAM,UAAUI,EAAI,SACpBJ,EAAM,UAAUI,EAAI,OACpBJ,EAAM,UAAUI,EAAI,SALL;CAOnB;CAIA,IAAIC,IAAoB;CACxB,SAASC,EAAc,GAAqB;EAC1C,IACEL,EAAoB,KAAKD,EAAM,WAAWpB,EAAS,SAASuB,EAAWH,CAAK;CAChF;CACA,SAASO,EAAgB,GAAmB;EAC1C,IAAMC,IAAaH,KAAqBL,EAAM,WAAWpB,EAAS,SAASuB,EAAWH,CAAK;EAE3F,AADA,IAAoB,IAChBQ,KAAcP,EAAoB,KAAKf,EAAS,UAAU,SAAOK,EAAM;CAC7E;CAEA,OAAO;EACL;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF;AACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"usePopover.js","names":[],"sources":["../../src/composables/usePopover.ts"],"sourcesContent":["// @core\n/**\n * Read open state from the element and update the model from native toggle events. Assigning a\n * separate shown flag would miss browser dismissal.\n */\n\nimport { onMounted, ref, watch, type Ref } from 'vue'\n\n// @fallback\n// The option below is newer than the type definitions shipped with TypeScript, so the\n// element is described locally rather than being cast about at each call site.\ntype PopoverWithSource = HTMLElement & { showPopover(options?: { source?: HTMLElement }): void }\n\nexport function usePopover(el: Readonly<Ref<HTMLElement | null>>) {\n const shown = ref(false)\n\n /**\n * Reads the state back off the panel. Bind it to both `@beforetoggle` and `@toggle`, and\n * on the popover element itself: ToggleEvents do not bubble.\n */\n function syncShown(event: Event) {\n shown.value = (event as ToggleEvent).newState === 'open'\n }\n\n /**\n * Opening from code rather than from a click must name the invoker as `source`. That is what\n * recreates the relationship a click would have: the implicit anchor and the panel's place in\n * the popover stack.\n */\n function show(source?: HTMLElement) {\n attempt(source, true)\n }\n\n /*\n * Retry after the current popover operation: synchronous focus restoration can request\n * another popover while the browser is still hiding the first.\n */\n function attempt(source: HTMLElement | undefined, retry: boolean) {\n const panel = el.value as PopoverWithSource | null\n if (!panel || shown.value) return\n try {\n panel.showPopover(source ? { source } : undefined)\n } catch {\n // A close asked for before the microtask runs must win: the retry checks that no `hide`\n // came in between, or it would reopen a panel just closed.\n const asked = generation\n if (retry) queueMicrotask(() => asked === generation && attempt(source, false))\n }\n }\n\n /** Bumped by every close, so a retry queued before it knows it was overtaken. */\n let generation = 0\n\n /** Closes the panel. */\n function hide() {\n generation += 1\n if (shown.value) el.value?.hidePopover()\n }\n\n return { shown, syncShown, show, hide }\n}\n\n// @core\n/**\n * The `value === shown()` guard is what keeps the two directions from chasing each other. A\n * panel the browser has just dismissed writes `false` into the model; without the guard that\n * write would come back here as a request to close a panel already closed.\n */\nexport function usePopoverModel(\n open: Ref<boolean>,\n shown: () => boolean,\n show: () => void,\n hide: () => void,\n) {\n watch(open, (value) => {\n if (value === shown()) return\n if (value) show()\n else hide()\n })\n\n // @ssr\n // A watcher does not run during the server render, so a panel asked to be open\n // from the start would never be told to open. Replaying the initial state on mount is\n // what covers that case.\n onMounted(() => {\n if (open.value) show()\n })\n}\n"],"mappings":";;AAaA,
|
|
1
|
+
{"version":3,"file":"usePopover.js","names":["usePopover","shown","ref","syncShown","event","show","source","attempt","panel","el","asked","generation","retry","hide","usePopoverModel","watch","open","value","onMounted"],"sources":["../../src/composables/usePopover.ts"],"sourcesContent":["// @core\n/**\n * Read open state from the element and update the model from native toggle events. Assigning a\n * separate shown flag would miss browser dismissal.\n */\n\nimport { onMounted, ref, watch, type Ref } from 'vue'\n\n// @fallback\n// The option below is newer than the type definitions shipped with TypeScript, so the\n// element is described locally rather than being cast about at each call site.\ntype PopoverWithSource = HTMLElement & { showPopover(options?: { source?: HTMLElement }): void }\n\nexport function usePopover(el: Readonly<Ref<HTMLElement | null>>) {\n const shown = ref(false)\n\n /**\n * Reads the state back off the panel. Bind it to both `@beforetoggle` and `@toggle`, and\n * on the popover element itself: ToggleEvents do not bubble.\n */\n function syncShown(event: Event) {\n shown.value = (event as ToggleEvent).newState === 'open'\n }\n\n /**\n * Opening from code rather than from a click must name the invoker as `source`. That is what\n * recreates the relationship a click would have: the implicit anchor and the panel's place in\n * the popover stack.\n */\n function show(source?: HTMLElement) {\n attempt(source, true)\n }\n\n /*\n * Retry after the current popover operation: synchronous focus restoration can request\n * another popover while the browser is still hiding the first.\n */\n function attempt(source: HTMLElement | undefined, retry: boolean) {\n const panel = el.value as PopoverWithSource | null\n if (!panel || shown.value) return\n try {\n panel.showPopover(source ? { source } : undefined)\n } catch {\n // A close asked for before the microtask runs must win: the retry checks that no `hide`\n // came in between, or it would reopen a panel just closed.\n const asked = generation\n if (retry) queueMicrotask(() => asked === generation && attempt(source, false))\n }\n }\n\n /** Bumped by every close, so a retry queued before it knows it was overtaken. */\n let generation = 0\n\n /** Closes the panel. */\n function hide() {\n generation += 1\n if (shown.value) el.value?.hidePopover()\n }\n\n return { shown, syncShown, show, hide }\n}\n\n// @core\n/**\n * The `value === shown()` guard is what keeps the two directions from chasing each other. A\n * panel the browser has just dismissed writes `false` into the model; without the guard that\n * write would come back here as a request to close a panel already closed.\n */\nexport function usePopoverModel(\n open: Ref<boolean>,\n shown: () => boolean,\n show: () => void,\n hide: () => void,\n) {\n watch(open, (value) => {\n if (value === shown()) return\n if (value) show()\n else hide()\n })\n\n // @ssr\n // A watcher does not run during the server render, so a panel asked to be open\n // from the start would never be told to open. Replaying the initial state on mount is\n // what covers that case.\n onMounted(() => {\n if (open.value) show()\n })\n}\n"],"mappings":";;AAaA,SAAgBA,EAAW,GAAuC;CAChE,IAAMC,IAAQC,EAAI,EAAK;CAMvB,SAASC,EAAU,GAAc;EAC/B,EAAM,QAASC,EAAsB,aAAa;CACpD;CAOA,SAASC,EAAK,GAAsB;EAClC,EAAQC,GAAQ,EAAI;CACtB;CAMA,SAASC,EAAQ,GAAiC,GAAgB;EAChE,IAAMC,IAAQC,EAAG;EACjB,IAAKD,KAAS,GAAM,OACpB,IAAI;GACF,EAAM,YAAYF,IAAS,EAAE,UAAO,IAAI,KAAA,CAAS;EACnD,QAAQ;GAGN,IAAMI,IAAQC;GACd,AAAIC,KAAO,qBAAqBF,MAAUC,KAAcJ,EAAQD,GAAQ,EAAK,CAAC;EAChF;CACF;CAGA,IAAIK,IAAa;CAGjB,SAASE,IAAO;EAEd,AADA,KAAc,GACVZ,EAAM,SAAOQ,EAAG,OAAO,YAAY;CACzC;CAEA,OAAO;EAAE;EAAO;EAAW;EAAM;CAAK;AACxC;AAQA,SAAgBK,EACd,GACA,GACA,GACA,GACA;CAWA,AAVAC,EAAMC,IAAO,MAAU;EACrB,AAAIC,MAAUhB,EAAM,MAChBgB,IAAOZ,EAAK,IACXQ,EAAK;CACZ,CAAC,GAMDK,QAAgB;EACd,AAAIF,EAAK,SAAOX,EAAK;CACvB,CAAC;AACH"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useProgressValue.js","names":[],"sources":["../../src/composables/useProgressValue.ts"],"sourcesContent":["// @core\n/**\n * Normalize finite bounds and values once so CSS, slot text and progressbar ARIA all describe\n * the same range.\n */\n\nimport { computed, type ComputedRef } from 'vue'\nimport { clamp } from '../utils/number'\n\nexport function useProgressValue(\n value: () => number,\n max: () => number,\n): {\n max: ComputedRef<number>\n clamped: ComputedRef<number>\n fraction: ComputedRef<number>\n /** The fraction as a percentage, unrounded: what the default slot receives. */\n percent: ComputedRef<number>\n /** The percentage rounded to a whole number: what the component writes by default. */\n roundedPercent: ComputedRef<number>\n} {\n /* A value computed by the consumer (`loaded / total * 100` before `total` is known) can\n be NaN, which `clamp` and `Math.max` both hand back unchanged: it would reach\n `aria-valuenow` and the text as the word \"NaN\". A value that is not a number is read as\n no progress, and a bound that is not a finite number as the default of 100. */\n const normalizedMax = computed(() => {\n const bound = max()\n return Number.isFinite(bound) ? Math.max(bound, 0) : 100\n })\n const clamped = computed(() => {\n const current = value()\n return Number.isNaN(current) ? 0 : clamp(current, 0, normalizedMax.value)\n })\n\n const fraction = computed(() => clamped.value / (normalizedMax.value || 1))\n const percent = computed(() => fraction.value * 100)\n /* Rounded to the nearest whole number, except at the two ends: \"100%\" is written only\n once the work is complete and \"0%\" only while nothing has been done, so 99.6 reads 99%\n and 0.4 reads 1%. A plain round would announce a finished task that is still running. */\n const roundedPercent = computed(() => {\n const p = percent.value\n return p <= 0 || p >= 100 ? Math.round(p) : clamp(Math.round(p), 1, 99)\n })\n\n return { max: normalizedMax, clamped, fraction, percent, roundedPercent }\n}\n"],"mappings":";;;AASA,
|
|
1
|
+
{"version":3,"file":"useProgressValue.js","names":["useProgressValue","normalizedMax","computed","bound","max","clamped","current","value","clamp","fraction","percent","p"],"sources":["../../src/composables/useProgressValue.ts"],"sourcesContent":["// @core\n/**\n * Normalize finite bounds and values once so CSS, slot text and progressbar ARIA all describe\n * the same range.\n */\n\nimport { computed, type ComputedRef } from 'vue'\nimport { clamp } from '../utils/number'\n\nexport function useProgressValue(\n value: () => number,\n max: () => number,\n): {\n max: ComputedRef<number>\n clamped: ComputedRef<number>\n fraction: ComputedRef<number>\n /** The fraction as a percentage, unrounded: what the default slot receives. */\n percent: ComputedRef<number>\n /** The percentage rounded to a whole number: what the component writes by default. */\n roundedPercent: ComputedRef<number>\n} {\n /* A value computed by the consumer (`loaded / total * 100` before `total` is known) can\n be NaN, which `clamp` and `Math.max` both hand back unchanged: it would reach\n `aria-valuenow` and the text as the word \"NaN\". A value that is not a number is read as\n no progress, and a bound that is not a finite number as the default of 100. */\n const normalizedMax = computed(() => {\n const bound = max()\n return Number.isFinite(bound) ? Math.max(bound, 0) : 100\n })\n const clamped = computed(() => {\n const current = value()\n return Number.isNaN(current) ? 0 : clamp(current, 0, normalizedMax.value)\n })\n\n const fraction = computed(() => clamped.value / (normalizedMax.value || 1))\n const percent = computed(() => fraction.value * 100)\n /* Rounded to the nearest whole number, except at the two ends: \"100%\" is written only\n once the work is complete and \"0%\" only while nothing has been done, so 99.6 reads 99%\n and 0.4 reads 1%. A plain round would announce a finished task that is still running. */\n const roundedPercent = computed(() => {\n const p = percent.value\n return p <= 0 || p >= 100 ? Math.round(p) : clamp(Math.round(p), 1, 99)\n })\n\n return { max: normalizedMax, clamped, fraction, percent, roundedPercent }\n}\n"],"mappings":";;;AASA,SAAgBA,EACd,GACA,GASA;CAKA,IAAMC,IAAgBC,QAAe;EACnC,IAAMC,IAAQC,EAAI;EAClB,OAAO,OAAO,SAASD,CAAK,IAAI,KAAK,IAAIA,GAAO,CAAC,IAAI;CACvD,CAAC,GACKE,IAAUH,QAAe;EAC7B,IAAMI,IAAUC,EAAM;EACtB,OAAO,OAAO,MAAMD,CAAO,IAAI,IAAIE,EAAMF,GAAS,GAAGL,EAAc,KAAK;CAC1E,CAAC,GAEKQ,IAAWP,QAAeG,EAAQ,SAASJ,EAAc,SAAS,EAAE,GACpES,IAAUR,QAAeO,EAAS,QAAQ,GAAG;CASnD,OAAO;EAAE,KAAKR;EAAe;EAAS;EAAU;EAAS,gBALlCC,QAAe;GACpC,IAAMS,IAAID,EAAQ;GAClB,OAAOC,KAAK,KAAKA,KAAK,MAAM,KAAK,MAAMA,CAAC,IAAIH,EAAM,KAAK,MAAMG,CAAC,GAAG,GAAG,EAAE;EACxE,CAEyD;CAAe;AAC1E"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useRootAttrs.js","names":[],"sources":["../../src/composables/useRootAttrs.ts"],"sourcesContent":["import { computed, useAttrs, type ComputedRef, type StyleValue } from 'vue'\n\n/**\n * Redeclared locally: `@vue/runtime-dom` exports this as `ClassValue` and the `vue` package\n * does not re-export it. Typed `unknown` instead, a template refuses to bind it.\n */\ntype ClassBinding = false | null | undefined | string | Record<string, unknown> | ClassBinding[]\n\n// @a11y\n/**\n * The attribute split of the wrapper-root pattern: `class` and `style` stay on a root that is\n * only a container, and every other attribute goes to the functional element.\n */\nexport function useRootAttrs(): {\n attrs: Record<string, unknown>\n rootClass: ComputedRef<ClassBinding>\n rootStyle: ComputedRef<StyleValue>\n forwardedAttrs: ComputedRef<Record<string, unknown>>\n} {\n const attrs = useAttrs()\n // Read the styling keys even when absent: enumerating an empty attrs object tracks no reads.\n const split = computed(() => {\n const { class: rootClass, style: rootStyle, ...forwardedAttrs } = attrs\n return { rootClass, rootStyle, forwardedAttrs }\n })\n\n return {\n attrs,\n rootClass: computed(() => split.value.rootClass as ClassBinding),\n rootStyle: computed(() => split.value.rootStyle as StyleValue),\n forwardedAttrs: computed(() => split.value.forwardedAttrs),\n }\n}\n"],"mappings":";;AAaA,
|
|
1
|
+
{"version":3,"file":"useRootAttrs.js","names":["useRootAttrs","attrs","useAttrs","split","computed","rootClass","rootStyle","forwardedAttrs"],"sources":["../../src/composables/useRootAttrs.ts"],"sourcesContent":["import { computed, useAttrs, type ComputedRef, type StyleValue } from 'vue'\n\n/**\n * Redeclared locally: `@vue/runtime-dom` exports this as `ClassValue` and the `vue` package\n * does not re-export it. Typed `unknown` instead, a template refuses to bind it.\n */\ntype ClassBinding = false | null | undefined | string | Record<string, unknown> | ClassBinding[]\n\n// @a11y\n/**\n * The attribute split of the wrapper-root pattern: `class` and `style` stay on a root that is\n * only a container, and every other attribute goes to the functional element.\n */\nexport function useRootAttrs(): {\n attrs: Record<string, unknown>\n rootClass: ComputedRef<ClassBinding>\n rootStyle: ComputedRef<StyleValue>\n forwardedAttrs: ComputedRef<Record<string, unknown>>\n} {\n const attrs = useAttrs()\n // Read the styling keys even when absent: enumerating an empty attrs object tracks no reads.\n const split = computed(() => {\n const { class: rootClass, style: rootStyle, ...forwardedAttrs } = attrs\n return { rootClass, rootStyle, forwardedAttrs }\n })\n\n return {\n attrs,\n rootClass: computed(() => split.value.rootClass as ClassBinding),\n rootStyle: computed(() => split.value.rootStyle as StyleValue),\n forwardedAttrs: computed(() => split.value.forwardedAttrs),\n }\n}\n"],"mappings":";;AAaA,SAAgBA,IAKd;CACA,IAAMC,IAAQC,EAAS,GAEjBC,IAAQC,QAAe;EAC3B,IAAM,EAAE,OAAOC,GAAW,OAAOC,GAAW,GAAGC,MAAmBN;EAClE,OAAO;GAAE;GAAW;GAAW;EAAe;CAChD,CAAC;CAED,OAAO;EACL;EACA,WAAWG,QAAeD,EAAM,MAAM,SAAyB;EAC/D,WAAWC,QAAeD,EAAM,MAAM,SAAuB;EAC7D,gBAAgBC,QAAeD,EAAM,MAAM,cAAc;CAC3D;AACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useSlotNodes.js","names":[],"sources":["../../src/composables/useSlotNodes.ts"],"sourcesContent":["import { computed, onBeforeUpdate, ref, useSlots, type ComputedRef, type VNode } from 'vue'\n\nimport { flattenSlot } from '../utils/vnode'\n\n// @ssr @core\n/**\n * A bare `computed(() => flattenSlot(slots.default?.()))` goes stale. `slots` is not reactive:\n * the computed only tracks what the slot READS while it runs, so a parent handing down a NEW\n * slot function leaves it cached.\n */\nexport function useSlotNodes(name = 'default'): ComputedRef<VNode[]> {\n const slots = useSlots()\n const tick = ref(0)\n onBeforeUpdate(() => {\n tick.value++\n })\n return computed(() => {\n void tick.value\n return flattenSlot(slots[name]?.())\n })\n}\n"],"mappings":";;;AAUA,
|
|
1
|
+
{"version":3,"file":"useSlotNodes.js","names":["useSlotNodes","slots","useSlots","tick","ref","onBeforeUpdate","computed","flattenSlot","name"],"sources":["../../src/composables/useSlotNodes.ts"],"sourcesContent":["import { computed, onBeforeUpdate, ref, useSlots, type ComputedRef, type VNode } from 'vue'\n\nimport { flattenSlot } from '../utils/vnode'\n\n// @ssr @core\n/**\n * A bare `computed(() => flattenSlot(slots.default?.()))` goes stale. `slots` is not reactive:\n * the computed only tracks what the slot READS while it runs, so a parent handing down a NEW\n * slot function leaves it cached.\n */\nexport function useSlotNodes(name = 'default'): ComputedRef<VNode[]> {\n const slots = useSlots()\n const tick = ref(0)\n onBeforeUpdate(() => {\n tick.value++\n })\n return computed(() => {\n void tick.value\n return flattenSlot(slots[name]?.())\n })\n}\n"],"mappings":";;;AAUA,SAAgBA,EAAa,IAAO,WAAiC;CACnE,IAAMC,IAAQC,EAAS,GACjBC,IAAOC,EAAI,CAAC;CAIlB,OAHAC,QAAqB;EACnB,EAAK;CACP,CAAC,GACMC,SACLH,EAAU,OACHI,EAAYN,EAAMO,EAAK,GAAG,CAAC,EACnC;AACH"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useTextLimit.js","names":[],"sources":["../../src/composables/useTextLimit.ts"],"sourcesContent":["import { computed, watchEffect, type ComputedRef, type Ref } from 'vue'\n\nimport { useMessages } from '../i18n/state'\n\n/** The least this needs of the real control; the two kinds of field both offer it. */\ninterface ValidatableControl {\n setCustomValidity: (message: string) => void\n}\n\n// @core\n/**\n * How much has been typed against how much is allowed: the \"12/80\" counter under a field,\n * whether the allowance has been passed, and the SOFT limit. A soft limit lets the reader keep\n * typing past the allowance and puts the field in error instead of cutting them off mid-word.\n */\nexport function useTextLimit(options: {\n el: Ref<ValidatableControl | null>\n text: () => string\n maxlength: () => number | undefined\n softLimit: () => boolean\n}): { counterText: ComputedRef<string>; over: ComputedRef<boolean> } {\n const length = computed(() => options.text().length)\n const max = computed(() => options.maxlength())\n const m = useMessages()\n\n // Without it the effect would clear the validity on every re-run, erasing a consumer's own\n // `setCustomValidity` the moment an unrelated prop such as `maxlength` changed, and letting\n // the form submit.\n let owned = false\n\n // The dictionary is read INSIDE the effect, which makes the error message rewrite itself when\n // the language is changed after the component is on screen. The branches are spelled out\n // rather than written as a ternary so that TypeScript can narrow the limit to a number.\n watchEffect(\n () => {\n const el = options.el.value\n if (!el) return\n const limit = max.value\n if (options.softLimit() && limit != null && length.value > limit) {\n el.setCustomValidity(m.value.field.limitExceeded(limit))\n owned = true\n } else if (owned) {\n el.setCustomValidity('')\n owned = false\n }\n },\n { flush: 'post' },\n )\n\n return {\n counterText: computed(() =>\n max.value != null ? `${length.value}/${max.value}` : `${length.value}`,\n ),\n over: computed(() => max.value != null && length.value > max.value),\n }\n}\n"],"mappings":";;;AAeA,
|
|
1
|
+
{"version":3,"file":"useTextLimit.js","names":["useTextLimit","length","computed","options","max","m","useMessages","owned","watchEffect","el","limit"],"sources":["../../src/composables/useTextLimit.ts"],"sourcesContent":["import { computed, watchEffect, type ComputedRef, type Ref } from 'vue'\n\nimport { useMessages } from '../i18n/state'\n\n/** The least this needs of the real control; the two kinds of field both offer it. */\ninterface ValidatableControl {\n setCustomValidity: (message: string) => void\n}\n\n// @core\n/**\n * How much has been typed against how much is allowed: the \"12/80\" counter under a field,\n * whether the allowance has been passed, and the SOFT limit. A soft limit lets the reader keep\n * typing past the allowance and puts the field in error instead of cutting them off mid-word.\n */\nexport function useTextLimit(options: {\n el: Ref<ValidatableControl | null>\n text: () => string\n maxlength: () => number | undefined\n softLimit: () => boolean\n}): { counterText: ComputedRef<string>; over: ComputedRef<boolean> } {\n const length = computed(() => options.text().length)\n const max = computed(() => options.maxlength())\n const m = useMessages()\n\n // Without it the effect would clear the validity on every re-run, erasing a consumer's own\n // `setCustomValidity` the moment an unrelated prop such as `maxlength` changed, and letting\n // the form submit.\n let owned = false\n\n // The dictionary is read INSIDE the effect, which makes the error message rewrite itself when\n // the language is changed after the component is on screen. The branches are spelled out\n // rather than written as a ternary so that TypeScript can narrow the limit to a number.\n watchEffect(\n () => {\n const el = options.el.value\n if (!el) return\n const limit = max.value\n if (options.softLimit() && limit != null && length.value > limit) {\n el.setCustomValidity(m.value.field.limitExceeded(limit))\n owned = true\n } else if (owned) {\n el.setCustomValidity('')\n owned = false\n }\n },\n { flush: 'post' },\n )\n\n return {\n counterText: computed(() =>\n max.value != null ? `${length.value}/${max.value}` : `${length.value}`,\n ),\n over: computed(() => max.value != null && length.value > max.value),\n }\n}\n"],"mappings":";;;AAeA,SAAgBA,EAAa,GAKwC;CACnE,IAAMC,IAASC,QAAeC,EAAQ,KAAK,CAAC,CAAC,MAAM,GAC7CC,IAAMF,QAAeC,EAAQ,UAAU,CAAC,GACxCE,IAAIC,EAAY,GAKlBC,IAAQ;CAqBZ,OAhBAC,QACQ;EACJ,IAAMC,IAAKN,EAAQ,GAAG;EACtB,IAAI,CAACM,GAAI;EACT,IAAMC,IAAQN,EAAI;EAClB,AAAID,EAAQ,UAAU,KAAKO,KAAS,QAAQT,EAAO,QAAQS,KACzDD,EAAG,kBAAkBJ,EAAE,MAAM,MAAM,cAAcK,CAAK,CAAC,GACvD,IAAQ,MACH,AAELH,OADAE,EAAG,kBAAkB,EAAE,GACf;CAEZ,GACA,EAAE,OAAO,OAAO,CAClB,GAEO;EACL,aAAaP,QACXE,EAAI,SAAS,OAAwC,GAAGH,EAAO,UAA3C,GAAGA,EAAO,MAAM,GAAGG,EAAI,OAC7C;EACA,MAAMF,QAAeE,EAAI,SAAS,QAAQH,EAAO,QAAQG,EAAI,KAAK;CACpE;AACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useTimer.js","names":[],"sources":["../../src/composables/useTimer.ts"],"sourcesContent":["// @core\n/**\n * One cancellable timeout. Nonpositive delays invoke the callback synchronously, so\n * self-rearming consumers must guard against zero-delay recursion.\n */\n\nimport { onActivated, onBeforeUnmount, onDeactivated } from 'vue'\n\nexport function useTimer(): { start: (fn: () => void, delay: number) => void; cancel: () => void } {\n let timer: ReturnType<typeof setTimeout> | undefined\n let armed: { fn: () => void; delay: number } | undefined\n let held: typeof armed\n\n function cancel() {\n clearTimeout(timer)\n timer = undefined\n armed = undefined\n held = undefined\n }\n\n function start(fn: () => void, delay: number) {\n cancel()\n if (delay <= 0) return fn()\n armed = { fn, delay }\n timer = setTimeout(() => {\n timer = undefined\n armed = undefined\n fn()\n }, delay)\n }\n\n onBeforeUnmount(cancel)\n onDeactivated(() => {\n const pending = armed\n cancel()\n held = pending\n })\n onActivated(() => {\n if (held) start(held.fn, held.delay)\n })\n\n return { start, cancel }\n}\n"],"mappings":";;AAQA,
|
|
1
|
+
{"version":3,"file":"useTimer.js","names":["useTimer","timer","armed","held","cancel","start","delay","fn","onBeforeUnmount","onDeactivated","pending","onActivated"],"sources":["../../src/composables/useTimer.ts"],"sourcesContent":["// @core\n/**\n * One cancellable timeout. Nonpositive delays invoke the callback synchronously, so\n * self-rearming consumers must guard against zero-delay recursion.\n */\n\nimport { onActivated, onBeforeUnmount, onDeactivated } from 'vue'\n\nexport function useTimer(): { start: (fn: () => void, delay: number) => void; cancel: () => void } {\n let timer: ReturnType<typeof setTimeout> | undefined\n let armed: { fn: () => void; delay: number } | undefined\n let held: typeof armed\n\n function cancel() {\n clearTimeout(timer)\n timer = undefined\n armed = undefined\n held = undefined\n }\n\n function start(fn: () => void, delay: number) {\n cancel()\n if (delay <= 0) return fn()\n armed = { fn, delay }\n timer = setTimeout(() => {\n timer = undefined\n armed = undefined\n fn()\n }, delay)\n }\n\n onBeforeUnmount(cancel)\n onDeactivated(() => {\n const pending = armed\n cancel()\n held = pending\n })\n onActivated(() => {\n if (held) start(held.fn, held.delay)\n })\n\n return { start, cancel }\n}\n"],"mappings":";;AAQA,SAAgBA,IAAmF;CACjG,IAAIC,GACAC,GACAC;CAEJ,SAASC,IAAS;EAIhB,AAHA,aAAaH,CAAK,GAClB,IAAQ,KAAA,GACR,IAAQ,KAAA,GACR,IAAO,KAAA;CACT;CAEA,SAASI,EAAM,GAAgB,GAAe;EAE5C,IADAD,EAAO,GACHE,KAAS,GAAG,OAAOC,EAAG;EAE1B,AADA,IAAQ;GAAE;GAAI;EAAM,GACpB,IAAQ,iBAAiB;GAGvB,AAFA,IAAQ,KAAA,GACR,IAAQ,KAAA,GACRA,EAAG;EACL,GAAGD,CAAK;CACV;CAYA,OAVAE,EAAgBJ,CAAM,GACtBK,QAAoB;EAClB,IAAMC,IAAUR;EAEhB,AADAE,EAAO,GACP,IAAOM;CACT,CAAC,GACDC,QAAkB;EAChB,AAAIR,KAAME,EAAMF,EAAK,IAAIA,EAAK,KAAK;CACrC,CAAC,GAEM;EAAE;EAAO;CAAO;AACzB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useTypeahead.js","names":[],"sources":["../../src/composables/useTypeahead.ts"],"sourcesContent":["import { normalizeText } from '../utils/text'\n\nimport { useTimer } from './useTimer'\n\n// @keyboard\n/**\n * Type-to-find, as a native list does, for VSelect and VTreeView: the letters typed within half a\n * second add up to a prefix, and the same letter repeated cycles through the items it starts.\n */\nexport function useTypeahead(): {\n /**\n * Adds a key to the prefix and returns the index it leads to, searching from `from`, or -1.\n * `labelAt` gives an item's label already normalized, or nothing for one to skip.\n */\n find: (\n key: string,\n count: number,\n from: number,\n labelAt: (index: number) => string | undefined,\n ) => number\n /** Whether a prefix is being typed, so that a space belongs to it: \"New York\". */\n typing: () => boolean\n} {\n const timer = useTimer()\n let typed = ''\n\n function find(\n key: string,\n count: number,\n from: number,\n labelAt: (index: number) => string | undefined,\n ): number {\n typed += normalizeText(key)\n timer.start(() => (typed = ''), 500)\n if (!typed) return -1\n const cycling = [...typed].every((char) => char === typed[0])\n const needle = cycling ? typed[0]! : typed\n // A new prefix may match the current item itself; a cycle moves on from it.\n const start = Math.max(from + (cycling ? 1 : 0), 0)\n for (let step = 0; step < count; step++) {\n const index = (start + step) % count\n if (labelAt(index)?.startsWith(needle)) return index\n }\n return -1\n }\n\n return { find, typing: () => typed !== '' }\n}\n"],"mappings":";;;AASA,
|
|
1
|
+
{"version":3,"file":"useTypeahead.js","names":["useTypeahead","timer","useTimer","typed","find","normalizeText","key","cycling","char","needle","start","from","step","count","index","labelAt"],"sources":["../../src/composables/useTypeahead.ts"],"sourcesContent":["import { normalizeText } from '../utils/text'\n\nimport { useTimer } from './useTimer'\n\n// @keyboard\n/**\n * Type-to-find, as a native list does, for VSelect and VTreeView: the letters typed within half a\n * second add up to a prefix, and the same letter repeated cycles through the items it starts.\n */\nexport function useTypeahead(): {\n /**\n * Adds a key to the prefix and returns the index it leads to, searching from `from`, or -1.\n * `labelAt` gives an item's label already normalized, or nothing for one to skip.\n */\n find: (\n key: string,\n count: number,\n from: number,\n labelAt: (index: number) => string | undefined,\n ) => number\n /** Whether a prefix is being typed, so that a space belongs to it: \"New York\". */\n typing: () => boolean\n} {\n const timer = useTimer()\n let typed = ''\n\n function find(\n key: string,\n count: number,\n from: number,\n labelAt: (index: number) => string | undefined,\n ): number {\n typed += normalizeText(key)\n timer.start(() => (typed = ''), 500)\n if (!typed) return -1\n const cycling = [...typed].every((char) => char === typed[0])\n const needle = cycling ? typed[0]! : typed\n // A new prefix may match the current item itself; a cycle moves on from it.\n const start = Math.max(from + (cycling ? 1 : 0), 0)\n for (let step = 0; step < count; step++) {\n const index = (start + step) % count\n if (labelAt(index)?.startsWith(needle)) return index\n }\n return -1\n }\n\n return { find, typing: () => typed !== '' }\n}\n"],"mappings":";;;AASA,SAAgBA,IAad;CACA,IAAMC,IAAQC,EAAS,GACnBC,IAAQ;CAEZ,SAASC,EACP,GACA,GACA,GACA,GACQ;EAGR,IAFA,KAASC,EAAcC,CAAG,GAC1BL,EAAM,YAAa,IAAQ,IAAK,GAAG,GAC/B,CAACE,GAAO,OAAO;EACnB,IAAMI,IAAU,CAAC,GAAGJ,CAAK,CAAC,CAAC,OAAO,MAASK,MAASL,EAAM,EAAE,GACtDM,IAASF,IAAUJ,EAAM,KAAMA,GAE/BO,IAAQ,KAAK,IAAIC,IAAQ,MAAkB,CAAC;EAClD,KAAK,IAAIC,IAAO,GAAGA,IAAOC,GAAO,KAAQ;GACvC,IAAMC,KAASJ,IAAQE,KAAQC;GAC/B,IAAIE,EAAQD,CAAK,CAAC,EAAE,WAAWL,CAAM,GAAG,OAAOK;EACjD;EACA,OAAO;CACT;CAEA,OAAO;EAAE;EAAM,cAAcX,MAAU;CAAG;AAC5C"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useVirtualList.js","names":[],"sources":["../../src/composables/useVirtualList.ts"],"sourcesContent":["// @core\n/**\n * Render only the rows near the viewport of a scroll container, for VVirtualList and the virtual\n * mode of VCombobox. A row's size starts as an estimate and becomes its measured height once it\n * renders, remembered under its key, so rows may differ in height. The consumer renders\n * `segments`: the rows to draw, and spacers standing for the runs of rows left out.\n */\nimport {\n computed,\n nextTick,\n onBeforeUnmount,\n ref,\n watch,\n type ComponentPublicInstance,\n type ComputedRef,\n type Ref,\n} from 'vue'\n\nexport interface VirtualListOptions {\n /** The element that scrolls. Null disables the windowing: every row up to `initialCount`. */\n scrollEl: Readonly<Ref<HTMLElement | null>>\n /** How many rows there are. */\n count: () => number\n /** A stable identity for a row, under which its measured size is remembered. */\n key: (index: number) => unknown\n /** The height assumed for a row not measured yet, in pixels. */\n itemSize: () => number\n /** How many rows to render beyond each edge of the viewport. */\n overscan: () => number\n /** How many rows to render before the container is measured: on the server and at hydration. */\n initialCount: () => number\n /** Rows kept rendered wherever the scroll is: the active option, the row holding the focus. */\n pinned?: () => readonly number[]\n /**\n * The element the rows sit in, when content comes before it inside the scroll container: a\n * table's caption and heading. Its distance from the top of the scrolled content replaces the\n * container's top padding.\n */\n listEl?: Readonly<Ref<HTMLElement | null>>\n /**\n * The height a sticky element covers at the top of the viewport, a table's frozen heading:\n * an alignment keeps rows out from under it. The container's top padding otherwise.\n */\n insetStart?: () => number\n}\n\n/** A row to render, or a block of empty space standing for the rows left out. */\nexport type VirtualSegment =\n { type: 'row'; index: number } | { type: 'spacer'; key: string; size: number }\n\nexport interface VirtualList {\n /** What to render, in order. */\n segments: ComputedRef<VirtualSegment[]>\n /** The template ref of a rendered row: `:ref=\"(el) => measure(el, index)\"`. */\n measure: (target: Element | ComponentPublicInstance | null, index: number) => void\n /** Scrolls the container until the row is in view, rendering it first if it is not. */\n scrollToIndex: (index: number, align?: ScrollLogicalPosition) => Promise<void>\n}\n\nexport function useVirtualList(options: VirtualListOptions): VirtualList {\n // Sizes are kept outside reactivity, a row measured once per render would otherwise trigger\n // one recomputation of the offsets each; `version` publishes a batch of them at once.\n const sizes = new Map<unknown, number>()\n const version = ref(0)\n const scrollTop = ref(0)\n const viewport = ref(0)\n const padStart = ref(0)\n // The space a flex or grid container puts between two rows. A spacer is a sibling too and\n // gets one, so it is taken off the spacer. A group nested in the container is expected to\n // space its own rows the same way, as VCombobox's groups do.\n const gap = ref(0)\n const measuring = ref(false)\n\n // Each row's pitch is its height plus the gap after it: the offset of row `i` is the sum of\n // the pitches before it, and the last offset is the height of the whole list plus one gap.\n const offsets = computed(() => {\n void version.value\n const n = options.count()\n const pitch = options.itemSize() + gap.value\n const out = new Float64Array(n + 1)\n for (let i = 0; i < n; i++) {\n const size = sizes.size > 0 ? sizes.get(options.key(i)) : undefined\n out[i + 1] = out[i]! + (size ?? pitch)\n }\n return out\n })\n\n /** The row under a position in the list, clamped to the rows that exist. */\n function indexAt(position: number) {\n const o = offsets.value\n let low = 0\n let high = o.length - 2\n while (low < high) {\n const mid = (low + high + 1) >> 1\n if (o[mid]! <= position) low = mid\n else high = mid - 1\n }\n return Math.max(0, low)\n }\n\n // Two numbers rather than one object: a computed object is new on every scroll event, and\n // the segments would then be rebuilt even when the window has not moved by a row.\n const start = computed(() => {\n if (!measuring.value) return 0\n return Math.max(0, indexAt(scrollTop.value - padStart.value) - options.overscan())\n })\n const end = computed(() => {\n const n = options.count()\n if (!measuring.value) return Math.min(n, options.initialCount())\n const last = indexAt(scrollTop.value - padStart.value + viewport.value)\n return Math.min(n, last + 1 + options.overscan())\n })\n\n const segments = computed<VirtualSegment[]>(() => {\n const n = options.count()\n const o = offsets.value\n const from = start.value\n const to = end.value\n const pinned = [...new Set(options.pinned?.() ?? [])]\n .filter((i) => i >= 0 && i < n && (i < from || i >= to))\n .sort((a, b) => a - b)\n const indexes = pinned.filter((i) => i < from)\n for (let i = from; i < to; i++) indexes.push(i)\n indexes.push(...pinned.filter((i) => i >= to))\n\n const out: VirtualSegment[] = []\n let next = 0\n for (const i of indexes) {\n if (i > next) out.push(spacer(next, o[i]! - o[next]!))\n out.push({ type: 'row', index: i })\n next = i + 1\n }\n if (next < n) out.push(spacer(next, o[n]! - o[next]!))\n return out\n })\n\n function spacer(from: number, span: number): VirtualSegment {\n return { type: 'spacer', key: `spacer:${from}`, size: Math.max(0, span - gap.value) }\n }\n\n const observed = new Set<HTMLElement>()\n const indexOf = new WeakMap<Element, number>()\n let observer: ResizeObserver | undefined\n\n function measure(target: Element | ComponentPublicInstance | null, index: number) {\n const el = target && '$el' in target ? target.$el : target\n if (!(el instanceof HTMLElement)) return\n indexOf.set(el, index)\n if (observed.has(el)) return\n observed.add(el)\n observer?.observe(el)\n }\n\n /** Records a row's height. Returns how much it moved the rows below it. */\n function record(el: Element, height: number) {\n const index = indexOf.get(el)\n if (index === undefined || index >= options.count()) return 0\n const key = options.key(index)\n const pitch = height + gap.value\n const previous = sizes.get(key) ?? options.itemSize() + gap.value\n // Sub-pixel rounding differs from one reading to the next and would never settle.\n if (Math.abs(pitch - previous) < 0.5) return 0\n sizes.set(key, pitch)\n return pitch - previous\n }\n\n function readContainer(el: HTMLElement) {\n const style = getComputedStyle(el)\n const list = options.listEl?.value\n viewport.value = el.clientHeight\n padStart.value = list ? positionIn(el, list) : parseFloat(style.paddingTop) || 0\n gap.value = parseFloat(style.rowGap) || 0\n }\n\n /** Where an element starts in the scrolled content of the container, scroll included. */\n function positionIn(el: HTMLElement, target: Element) {\n const top = target.getBoundingClientRect().top - el.getBoundingClientRect().top\n return top / scaleOf(el) - el.clientTop + el.scrollTop\n }\n\n // @core\n // What the observer learns reaches the reactive state on the next frame, not from inside its\n // callback. Rendered there, the rows entering the window and the new height of the list would\n // be resizes the browser cannot deliver in the same pass, and it reports each such pass to the\n // page as a \"ResizeObserver loop\" error. Deferred, they are ordinary first observations.\n let commitFrame = 0\n let containerChanged = false\n let rowsChanged = false\n\n function scheduleCommit() {\n if (!commitFrame) commitFrame = requestAnimationFrame(commit)\n }\n\n function cancelCommit() {\n if (commitFrame) cancelAnimationFrame(commitFrame)\n commitFrame = 0\n containerChanged = rowsChanged = false\n }\n\n function commit() {\n commitFrame = 0\n const el = options.scrollEl.value\n if (el) {\n if (containerChanged) readContainer(el)\n // Also covers a container shown again after `display: none`, which has lost its scroll\n // position without a scroll event.\n scrollTop.value = el.scrollTop\n }\n if (rowsChanged) version.value++\n containerChanged = rowsChanged = false\n }\n\n // @core\n // A row above the viewport that turns out taller or shorter than assumed pushes everything\n // in view by the difference. The scroll position follows it at once, before the frame is\n // painted, so what the reader is looking at stays put; the browser's own scroll anchoring is\n // turned off by the consumer's stylesheet (`overflow-anchor: none`), or both corrections\n // would apply.\n function onResize(entries: ResizeObserverEntry[]) {\n const el = options.scrollEl.value\n if (!el) return\n // A container taken out of the layout, by `display: none` or a closed `<details>`, reports\n // itself and every row at zero. Recorded, those zeros would pull the next rows into the\n // window, which would report zero in turn, one frame after another for as long as the list\n // stays hidden. The sizes measured last are kept instead.\n if (el.getClientRects().length === 0) return\n const o = offsets.value\n const top = el.scrollTop - padStart.value\n let shift = 0\n for (const entry of entries) {\n if (entry.target === el || entry.target === options.listEl?.value) {\n containerChanged = true\n continue\n }\n if (!entry.target.isConnected) continue\n const index = indexOf.get(entry.target)\n const delta = record(entry.target, entry.borderBoxSize[0]?.blockSize ?? 0)\n if (delta === 0) continue\n rowsChanged = true\n if (index !== undefined && o[index]! < top) shift += delta\n }\n if (shift !== 0) el.scrollTop += shift\n if (containerChanged || rowsChanged || shift !== 0) scheduleCommit()\n }\n\n /**\n * Reads every rendered row at once, without moving the scroll: used before an explicit\n * alignment, which already places the rows by their real boxes. The observer reports the same\n * heights afterwards and finds nothing left to correct.\n */\n function measureNow(container: HTMLElement) {\n const scale = scaleOf(container)\n let changed = false\n for (const el of observed) {\n if (el.isConnected && record(el, el.getBoundingClientRect().height / scale) !== 0) {\n changed = true\n }\n }\n if (changed) version.value++\n }\n\n /**\n * How much a transform scales the container, as a panel's entry animation does: boxes read\n * from the page are scaled, scroll positions and the observer's sizes are not.\n */\n function scaleOf(container: HTMLElement) {\n const height = container.offsetHeight\n return height > 0 ? container.getBoundingClientRect().height / height || 1 : 1\n }\n\n function elementAt(index: number) {\n for (const el of observed) if (el.isConnected && indexOf.get(el) === index) return el\n return undefined\n }\n\n const onScroll = (event: Event) => {\n scrollTop.value = (event.currentTarget as HTMLElement).scrollTop\n }\n\n watch(\n options.scrollEl,\n (el, _previous, onCleanup) => {\n measuring.value = !!el\n if (!el) return\n readContainer(el)\n scrollTop.value = el.scrollTop\n el.addEventListener('scroll', onScroll, { passive: true })\n // @fallback\n // jsdom has no ResizeObserver: the rows keep their estimated size there, and the\n // measuring is checked in a real browser.\n if (typeof ResizeObserver !== 'undefined') {\n observer = new ResizeObserver(onResize)\n observer.observe(el)\n if (options.listEl?.value) observer.observe(options.listEl.value)\n for (const row of observed) observer.observe(row)\n }\n onCleanup(() => {\n el.removeEventListener('scroll', onScroll)\n observer?.disconnect()\n observer = undefined\n cancelCommit()\n })\n },\n { flush: 'post', immediate: true },\n )\n\n // A row that leaves the window is dropped from the observer: the observer would otherwise keep\n // every row ever rendered alive, detached, for as long as the list lives.\n watch(\n segments,\n () => {\n for (const el of observed) {\n if (el.isConnected) continue\n observer?.unobserve(el)\n observed.delete(el)\n }\n },\n { flush: 'post' },\n )\n\n onBeforeUnmount(() => {\n observed.clear()\n cancelCommit()\n })\n\n async function scrollToIndex(index: number, align: ScrollLogicalPosition = 'nearest') {\n const el = options.scrollEl.value\n if (!el || index < 0 || index >= options.count()) return\n if (!elementAt(index)) {\n // Placed by the offsets known so far, which renders the row; the real boxes then settle\n // the exact position below.\n const atStart = offsets.value[index]!\n const atEnd = offsets.value[index + 1]! - el.clientHeight\n let target = atStart\n if (align === 'end') target = atEnd\n else if (align === 'center') target = (atStart + atEnd) / 2\n else if (align === 'nearest' && atStart >= el.scrollTop - padStart.value) target = atEnd\n el.scrollTop = padStart.value + target\n scrollTop.value = el.scrollTop\n await nextTick()\n }\n const row = elementAt(index)\n if (!row) return\n measureNow(el)\n alignTo(el, row, align)\n }\n\n function alignTo(el: HTMLElement, row: HTMLElement, align: ScrollLogicalPosition) {\n const style = getComputedStyle(el)\n const padTop = options.insetStart?.() ?? (parseFloat(style.paddingTop) || 0)\n const padBottom = parseFloat(style.paddingBottom) || 0\n const top = positionIn(el, row)\n const height = row.getBoundingClientRect().height / scaleOf(el)\n const bottom = top + height\n const view = el.clientHeight\n let next = el.scrollTop\n if (align === 'start') next = top - padTop\n else if (align === 'end') next = bottom - view + padBottom\n else if (align === 'center') next = top + height / 2 - view / 2\n else if (top - padTop < el.scrollTop) next = top - padTop\n else if (bottom + padBottom > el.scrollTop + view) next = bottom - view + padBottom\n el.scrollTop = next\n scrollTop.value = el.scrollTop\n }\n\n return { segments, measure, scrollToIndex }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"useVirtualList.js","names":["useVirtualList","sizes","version","ref","scrollTop","viewport","padStart","gap","measuring","offsets","computed","n","options","pitch","out","i","size","indexAt","o","low","high","mid","position","start","end","last","segments","from","to","pinned","a","b","indexes","next","spacer","span","observed","indexOf","observer","measure","el","target","index","record","key","height","previous","readContainer","style","list","positionIn","scaleOf","commitFrame","containerChanged","rowsChanged","scheduleCommit","commit","cancelCommit","onResize","top","shift","entry","entries","delta","measureNow","scale","container","changed","elementAt","onScroll","event","watch","row","onBeforeUnmount","scrollToIndex","atStart","atEnd","align","nextTick","alignTo","padTop","padBottom","bottom","view"],"sources":["../../src/composables/useVirtualList.ts"],"sourcesContent":["// @core\n/**\n * Render only the rows near the viewport of a scroll container, for VVirtualList and the virtual\n * mode of VCombobox. A row's size starts as an estimate and becomes its measured height once it\n * renders, remembered under its key, so rows may differ in height. The consumer renders\n * `segments`: the rows to draw, and spacers standing for the runs of rows left out.\n */\nimport {\n computed,\n nextTick,\n onBeforeUnmount,\n ref,\n watch,\n type ComponentPublicInstance,\n type ComputedRef,\n type Ref,\n} from 'vue'\n\nexport interface VirtualListOptions {\n /** The element that scrolls. Null disables the windowing: every row up to `initialCount`. */\n scrollEl: Readonly<Ref<HTMLElement | null>>\n /** How many rows there are. */\n count: () => number\n /** A stable identity for a row, under which its measured size is remembered. */\n key: (index: number) => unknown\n /** The height assumed for a row not measured yet, in pixels. */\n itemSize: () => number\n /** How many rows to render beyond each edge of the viewport. */\n overscan: () => number\n /** How many rows to render before the container is measured: on the server and at hydration. */\n initialCount: () => number\n /** Rows kept rendered wherever the scroll is: the active option, the row holding the focus. */\n pinned?: () => readonly number[]\n /**\n * The element the rows sit in, when content comes before it inside the scroll container: a\n * table's caption and heading. Its distance from the top of the scrolled content replaces the\n * container's top padding.\n */\n listEl?: Readonly<Ref<HTMLElement | null>>\n /**\n * The height a sticky element covers at the top of the viewport, a table's frozen heading:\n * an alignment keeps rows out from under it. The container's top padding otherwise.\n */\n insetStart?: () => number\n}\n\n/** A row to render, or a block of empty space standing for the rows left out. */\nexport type VirtualSegment =\n | { type: 'row'; index: number }\n | { type: 'spacer'; key: string; size: number }\n\nexport interface VirtualList {\n /** What to render, in order. */\n segments: ComputedRef<VirtualSegment[]>\n /** The template ref of a rendered row: `:ref=\"(el) => measure(el, index)\"`. */\n measure: (target: Element | ComponentPublicInstance | null, index: number) => void\n /** Scrolls the container until the row is in view, rendering it first if it is not. */\n scrollToIndex: (index: number, align?: ScrollLogicalPosition) => Promise<void>\n}\n\nexport function useVirtualList(options: VirtualListOptions): VirtualList {\n // Sizes are kept outside reactivity, a row measured once per render would otherwise trigger\n // one recomputation of the offsets each; `version` publishes a batch of them at once.\n const sizes = new Map<unknown, number>()\n const version = ref(0)\n const scrollTop = ref(0)\n const viewport = ref(0)\n const padStart = ref(0)\n // The space a flex or grid container puts between two rows. A spacer is a sibling too and\n // gets one, so it is taken off the spacer. A group nested in the container is expected to\n // space its own rows the same way, as VCombobox's groups do.\n const gap = ref(0)\n const measuring = ref(false)\n\n // Each row's pitch is its height plus the gap after it: the offset of row `i` is the sum of\n // the pitches before it, and the last offset is the height of the whole list plus one gap.\n const offsets = computed(() => {\n void version.value\n const n = options.count()\n const pitch = options.itemSize() + gap.value\n const out = new Float64Array(n + 1)\n for (let i = 0; i < n; i++) {\n const size = sizes.size > 0 ? sizes.get(options.key(i)) : undefined\n out[i + 1] = out[i]! + (size ?? pitch)\n }\n return out\n })\n\n /** The row under a position in the list, clamped to the rows that exist. */\n function indexAt(position: number) {\n const o = offsets.value\n let low = 0\n let high = o.length - 2\n while (low < high) {\n const mid = (low + high + 1) >> 1\n if (o[mid]! <= position) low = mid\n else high = mid - 1\n }\n return Math.max(0, low)\n }\n\n // Two numbers rather than one object: a computed object is new on every scroll event, and\n // the segments would then be rebuilt even when the window has not moved by a row.\n const start = computed(() => {\n if (!measuring.value) return 0\n return Math.max(0, indexAt(scrollTop.value - padStart.value) - options.overscan())\n })\n const end = computed(() => {\n const n = options.count()\n if (!measuring.value) return Math.min(n, options.initialCount())\n const last = indexAt(scrollTop.value - padStart.value + viewport.value)\n return Math.min(n, last + 1 + options.overscan())\n })\n\n const segments = computed<VirtualSegment[]>(() => {\n const n = options.count()\n const o = offsets.value\n const from = start.value\n const to = end.value\n const pinned = [...new Set(options.pinned?.() ?? [])]\n .filter((i) => i >= 0 && i < n && (i < from || i >= to))\n .sort((a, b) => a - b)\n const indexes = pinned.filter((i) => i < from)\n for (let i = from; i < to; i++) indexes.push(i)\n indexes.push(...pinned.filter((i) => i >= to))\n\n const out: VirtualSegment[] = []\n let next = 0\n for (const i of indexes) {\n if (i > next) out.push(spacer(next, o[i]! - o[next]!))\n out.push({ type: 'row', index: i })\n next = i + 1\n }\n if (next < n) out.push(spacer(next, o[n]! - o[next]!))\n return out\n })\n\n function spacer(from: number, span: number): VirtualSegment {\n return { type: 'spacer', key: `spacer:${from}`, size: Math.max(0, span - gap.value) }\n }\n\n const observed = new Set<HTMLElement>()\n const indexOf = new WeakMap<Element, number>()\n let observer: ResizeObserver | undefined\n\n function measure(target: Element | ComponentPublicInstance | null, index: number) {\n const el = target && '$el' in target ? target.$el : target\n if (!(el instanceof HTMLElement)) return\n indexOf.set(el, index)\n if (observed.has(el)) return\n observed.add(el)\n observer?.observe(el)\n }\n\n /** Records a row's height. Returns how much it moved the rows below it. */\n function record(el: Element, height: number) {\n const index = indexOf.get(el)\n if (index === undefined || index >= options.count()) return 0\n const key = options.key(index)\n const pitch = height + gap.value\n const previous = sizes.get(key) ?? options.itemSize() + gap.value\n // Sub-pixel rounding differs from one reading to the next and would never settle.\n if (Math.abs(pitch - previous) < 0.5) return 0\n sizes.set(key, pitch)\n return pitch - previous\n }\n\n function readContainer(el: HTMLElement) {\n const style = getComputedStyle(el)\n const list = options.listEl?.value\n viewport.value = el.clientHeight\n padStart.value = list ? positionIn(el, list) : parseFloat(style.paddingTop) || 0\n gap.value = parseFloat(style.rowGap) || 0\n }\n\n /** Where an element starts in the scrolled content of the container, scroll included. */\n function positionIn(el: HTMLElement, target: Element) {\n const top = target.getBoundingClientRect().top - el.getBoundingClientRect().top\n return top / scaleOf(el) - el.clientTop + el.scrollTop\n }\n\n // @core\n // What the observer learns reaches the reactive state on the next frame, not from inside its\n // callback. Rendered there, the rows entering the window and the new height of the list would\n // be resizes the browser cannot deliver in the same pass, and it reports each such pass to the\n // page as a \"ResizeObserver loop\" error. Deferred, they are ordinary first observations.\n let commitFrame = 0\n let containerChanged = false\n let rowsChanged = false\n\n function scheduleCommit() {\n if (!commitFrame) commitFrame = requestAnimationFrame(commit)\n }\n\n function cancelCommit() {\n if (commitFrame) cancelAnimationFrame(commitFrame)\n commitFrame = 0\n containerChanged = rowsChanged = false\n }\n\n function commit() {\n commitFrame = 0\n const el = options.scrollEl.value\n if (el) {\n if (containerChanged) readContainer(el)\n // Also covers a container shown again after `display: none`, which has lost its scroll\n // position without a scroll event.\n scrollTop.value = el.scrollTop\n }\n if (rowsChanged) version.value++\n containerChanged = rowsChanged = false\n }\n\n // @core\n // A row above the viewport that turns out taller or shorter than assumed pushes everything\n // in view by the difference. The scroll position follows it at once, before the frame is\n // painted, so what the reader is looking at stays put; the browser's own scroll anchoring is\n // turned off by the consumer's stylesheet (`overflow-anchor: none`), or both corrections\n // would apply.\n function onResize(entries: ResizeObserverEntry[]) {\n const el = options.scrollEl.value\n if (!el) return\n // A container taken out of the layout, by `display: none` or a closed `<details>`, reports\n // itself and every row at zero. Recorded, those zeros would pull the next rows into the\n // window, which would report zero in turn, one frame after another for as long as the list\n // stays hidden. The sizes measured last are kept instead.\n if (el.getClientRects().length === 0) return\n const o = offsets.value\n const top = el.scrollTop - padStart.value\n let shift = 0\n for (const entry of entries) {\n if (entry.target === el || entry.target === options.listEl?.value) {\n containerChanged = true\n continue\n }\n if (!entry.target.isConnected) continue\n const index = indexOf.get(entry.target)\n const delta = record(entry.target, entry.borderBoxSize[0]?.blockSize ?? 0)\n if (delta === 0) continue\n rowsChanged = true\n if (index !== undefined && o[index]! < top) shift += delta\n }\n if (shift !== 0) el.scrollTop += shift\n if (containerChanged || rowsChanged || shift !== 0) scheduleCommit()\n }\n\n /**\n * Reads every rendered row at once, without moving the scroll: used before an explicit\n * alignment, which already places the rows by their real boxes. The observer reports the same\n * heights afterwards and finds nothing left to correct.\n */\n function measureNow(container: HTMLElement) {\n const scale = scaleOf(container)\n let changed = false\n for (const el of observed) {\n if (el.isConnected && record(el, el.getBoundingClientRect().height / scale) !== 0) {\n changed = true\n }\n }\n if (changed) version.value++\n }\n\n /**\n * How much a transform scales the container, as a panel's entry animation does: boxes read\n * from the page are scaled, scroll positions and the observer's sizes are not.\n */\n function scaleOf(container: HTMLElement) {\n const height = container.offsetHeight\n return height > 0 ? container.getBoundingClientRect().height / height || 1 : 1\n }\n\n function elementAt(index: number) {\n for (const el of observed) if (el.isConnected && indexOf.get(el) === index) return el\n return undefined\n }\n\n const onScroll = (event: Event) => {\n scrollTop.value = (event.currentTarget as HTMLElement).scrollTop\n }\n\n watch(\n options.scrollEl,\n (el, _previous, onCleanup) => {\n measuring.value = !!el\n if (!el) return\n readContainer(el)\n scrollTop.value = el.scrollTop\n el.addEventListener('scroll', onScroll, { passive: true })\n // @fallback\n // jsdom has no ResizeObserver: the rows keep their estimated size there, and the\n // measuring is checked in a real browser.\n if (typeof ResizeObserver !== 'undefined') {\n observer = new ResizeObserver(onResize)\n observer.observe(el)\n if (options.listEl?.value) observer.observe(options.listEl.value)\n for (const row of observed) observer.observe(row)\n }\n onCleanup(() => {\n el.removeEventListener('scroll', onScroll)\n observer?.disconnect()\n observer = undefined\n cancelCommit()\n })\n },\n { flush: 'post', immediate: true },\n )\n\n // A row that leaves the window is dropped from the observer: the observer would otherwise keep\n // every row ever rendered alive, detached, for as long as the list lives.\n watch(\n segments,\n () => {\n for (const el of observed) {\n if (el.isConnected) continue\n observer?.unobserve(el)\n observed.delete(el)\n }\n },\n { flush: 'post' },\n )\n\n onBeforeUnmount(() => {\n observed.clear()\n cancelCommit()\n })\n\n async function scrollToIndex(index: number, align: ScrollLogicalPosition = 'nearest') {\n const el = options.scrollEl.value\n if (!el || index < 0 || index >= options.count()) return\n if (!elementAt(index)) {\n // Placed by the offsets known so far, which renders the row; the real boxes then settle\n // the exact position below.\n const atStart = offsets.value[index]!\n const atEnd = offsets.value[index + 1]! - el.clientHeight\n let target = atStart\n if (align === 'end') target = atEnd\n else if (align === 'center') target = (atStart + atEnd) / 2\n else if (align === 'nearest' && atStart >= el.scrollTop - padStart.value) target = atEnd\n el.scrollTop = padStart.value + target\n scrollTop.value = el.scrollTop\n await nextTick()\n }\n const row = elementAt(index)\n if (!row) return\n measureNow(el)\n alignTo(el, row, align)\n }\n\n function alignTo(el: HTMLElement, row: HTMLElement, align: ScrollLogicalPosition) {\n const style = getComputedStyle(el)\n const padTop = options.insetStart?.() ?? (parseFloat(style.paddingTop) || 0)\n const padBottom = parseFloat(style.paddingBottom) || 0\n const top = positionIn(el, row)\n const height = row.getBoundingClientRect().height / scaleOf(el)\n const bottom = top + height\n const view = el.clientHeight\n let next = el.scrollTop\n if (align === 'start') next = top - padTop\n else if (align === 'end') next = bottom - view + padBottom\n else if (align === 'center') next = top + height / 2 - view / 2\n else if (top - padTop < el.scrollTop) next = top - padTop\n else if (bottom + padBottom > el.scrollTop + view) next = bottom - view + padBottom\n el.scrollTop = next\n scrollTop.value = el.scrollTop\n }\n\n return { segments, measure, scrollToIndex }\n}\n"],"mappings":"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"}
|
package/dist/i18n/en.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"en.js","names":[],"sources":["../../src/i18n/en.ts"],"sourcesContent":["/**\n * English is the bundled fallback. Labels are also used by tests and play-function queries;\n * update those contracts when changing wording.\n */\n\nimport type { Messages } from './types'\n\nexport const en: Messages = {\n common: {\n loading: 'Loading…',\n clear: 'Clear',\n close: 'Close',\n dismiss: 'Remove',\n remove: (name) => `Remove ${name}`,\n cancel: 'Cancel',\n confirm: 'OK',\n },\n pagination: {\n label: 'Pagination',\n first: 'First page',\n previous: 'Previous page',\n next: 'Next page',\n last: 'Last page',\n page: (page) => `Page ${page}`,\n },\n tabs: {\n label: 'Tabs',\n previous: 'Previous tabs',\n next: 'Next tabs',\n },\n breadcrumb: {\n label: 'Breadcrumb',\n ellipsis: 'Show intermediate pages',\n },\n sideNavigation: { label: 'Navigation' },\n link: { newTab: ', opens in a new tab' },\n combobox: {\n empty: 'No results',\n clear: 'Clear selection',\n },\n select: { clear: 'Clear selection' },\n commandPalette: {\n label: 'Command palette',\n searchLabel: 'Search commands',\n placeholder: 'Type a command or search…',\n empty: 'No results',\n navigate: 'Navigate',\n choose: 'Select',\n },\n dataTable: {\n empty: 'No data',\n noResults: 'No results',\n loading: 'Loading data…',\n searchLabel: 'Search the table',\n searchPlaceholder: 'Search…',\n perPage: 'Rows per page',\n perPageValue: (label, value) => `${label}: ${value}`,\n selectAll: 'Select all',\n selectRow: (index) => `Select row ${index}`,\n // The plural is chosen right here, in the message itself. That one line is the whole\n // of the design system's handling of plurals, and it is meant to be.\n selection: (count) => `${count} item${count === 1 ? '' : 's'} selected`,\n range: ({ start, end, total }) => `${start}–${end} of ${total}`,\n pagination: 'Table pagination',\n },\n toaster: { label: 'Notifications' },\n snackbar: { label: 'Confirmation', action: 'Undo' },\n inputOTP: {\n label: 'Verification code',\n slot: (index, total) => `Character ${index} of ${total}`,\n },\n slider: {\n value: 'Value',\n start: 'Start',\n end: 'End',\n rangeStart: (label) => `${label} (start)`,\n rangeEnd: (label) => `${label} (end)`,\n },\n field: {\n limitExceeded: (max) => `Exceeds the limit of ${max} characters`,\n },\n progress: { percent: (percent) => `${percent}%`, label: 'Progress' },\n meter: { label: 'Meter' },\n hotkeys: {\n command: 'Command',\n ctrl: 'Ctrl',\n alt: 'Alt',\n shift: 'Shift',\n windows: 'Win',\n super: 'Super',\n enter: 'Enter',\n escape: 'Esc',\n space: 'Space',\n backspace: 'Backspace',\n delete: 'Del',\n tab: 'Tab',\n up: 'Up arrow',\n down: 'Down arrow',\n left: 'Left arrow',\n right: 'Right arrow',\n label: (keys) => `Keyboard shortcut: ${keys}`,\n },\n colorPicker: {\n label: 'Colour picker',\n saturation: 'Saturation',\n brightness: 'Brightness',\n areaValue: (saturation, brightness) => `Saturation ${saturation}, brightness ${brightness}`,\n hue: 'Hue',\n alpha: 'Opacity',\n value: 'Colour value',\n format: 'Colour format',\n eyeDropper: 'Pick a colour from the screen',\n swatches: 'Preset colours',\n },\n colorInput: {\n clear: 'Clear colour',\n openPicker: 'Open colour picker',\n pickerLabel: 'Choose a colour',\n },\n datePicker: {\n label: 'Date picker',\n previousMonth: 'Previous month',\n nextMonth: 'Next month',\n previousYear: 'Previous year',\n nextYear: 'Next year',\n monthPicker: 'Choose month',\n yearPicker: 'Choose year',\n },\n dateInput: {\n clear: 'Clear date',\n openPicker: 'Open calendar',\n pickerLabel: 'Choose a date',\n },\n numberInput: {\n increment: 'Increase',\n decrement: 'Decrease',\n },\n splitButton: { menu: 'More options' },\n rating: {\n label: 'Rating',\n empty: 'No rating',\n value: (value, max) => `${value} out of ${max}`,\n },\n resizable: {\n panel: (position) => `Panel ${position}`,\n },\n stepper: {\n label: 'Progress',\n completed: 'Completed',\n error: 'Error',\n },\n treeView: {\n label: 'Tree',\n loadFailed: 'Could not load',\n loadError: (label) => `Could not load the contents of ${label}`,\n },\n timePicker: {\n label: 'Time picker',\n meridiem: 'AM or PM',\n am: 'AM',\n pm: 'PM',\n selectHour: 'Select hour',\n selectMinutes: 'Select minutes',\n choosingHour: 'Selecting the hour',\n choosingMinutes: 'Selecting the minutes',\n hour: 'Hour',\n minutes: 'Minutes',\n hourValue: (hour) => `${hour} o'clock`,\n minutesValue: (minute) => (minute === 1 ? '1 minute' : `${minute} minutes`),\n },\n timeInput: {\n clear: 'Clear time',\n openPicker: 'Open time picker',\n pickerLabel: 'Choose a time',\n meridiemValue: (value) => `AM or PM: ${value}`,\n maskPlaceholder: 'hh:mm',\n unavailable: 'This time is not available.',\n },\n fileInput: {\n openPicker: 'Choose files',\n clear: 'Clear files',\n files: (count) => `${count} file${count === 1 ? '' : 's'}`,\n placeholder: 'No file selected',\n },\n filePicker: {\n browse: 'Browse files',\n or: 'or',\n list: 'Selected files',\n },\n carousel: {\n label: 'Carousel',\n roleDescription: 'carousel',\n slideRoleDescription: 'slide',\n slides: 'Slides',\n slide: (index, total) => `${index} of ${total}`,\n previous: 'Previous slide',\n next: 'Next slide',\n indicators: 'Choose slide to display',\n },\n calendar: {\n label: 'Calendar',\n roleDescription: 'calendar',\n today: 'Today',\n view: 'View',\n viewDay: 'Day',\n view4Days: '4 days',\n viewWeek: 'Week',\n viewMonth: 'Month',\n viewYear: 'Year',\n viewCustom: (days) => `${days} days`,\n previousDay: 'Previous day',\n nextDay: 'Next day',\n previousWeek: 'Previous week',\n nextWeek: 'Next week',\n previousMonth: 'Previous month',\n nextMonth: 'Next month',\n previousYear: 'Previous year',\n nextYear: 'Next year',\n previousPeriod: 'Previous period',\n nextPeriod: 'Next period',\n allDay: 'All day',\n moreEvents: (count) => `+${count} more`,\n openDay: (day) => `Open ${day}`,\n untitled: '(No title)',\n eventRoleDescription: 'event',\n eventHint:\n 'Press Enter to open this event. Press Space to take hold of it, then the arrow keys to move it and Shift with the arrow keys to change when it ends.',\n grabbed:\n 'Event held. Use the arrow keys to move it, Enter or Space to place it, Escape to cancel.',\n dropped: 'Event placed.',\n reverted: 'Move cancelled. The event is back where it was.',\n movedTo: (title, when) => `${title} moved to ${when}.`,\n },\n}\n"],"mappings":";AAOA,
|
|
1
|
+
{"version":3,"file":"en.js","names":["en","name","page","label","value","index","count","start","end","total","max","percent","keys","saturation","brightness","position","hour","minute","days","day","title","when"],"sources":["../../src/i18n/en.ts"],"sourcesContent":["/**\n * English is the bundled fallback. Labels are also used by tests and play-function queries;\n * update those contracts when changing wording.\n */\n\nimport type { Messages } from './types'\n\nexport const en: Messages = {\n common: {\n loading: 'Loading…',\n clear: 'Clear',\n close: 'Close',\n dismiss: 'Remove',\n remove: (name) => `Remove ${name}`,\n cancel: 'Cancel',\n confirm: 'OK',\n },\n pagination: {\n label: 'Pagination',\n first: 'First page',\n previous: 'Previous page',\n next: 'Next page',\n last: 'Last page',\n page: (page) => `Page ${page}`,\n },\n tabs: {\n label: 'Tabs',\n previous: 'Previous tabs',\n next: 'Next tabs',\n },\n breadcrumb: {\n label: 'Breadcrumb',\n ellipsis: 'Show intermediate pages',\n },\n sideNavigation: { label: 'Navigation' },\n link: { newTab: ', opens in a new tab' },\n combobox: {\n empty: 'No results',\n clear: 'Clear selection',\n },\n select: { clear: 'Clear selection' },\n commandPalette: {\n label: 'Command palette',\n searchLabel: 'Search commands',\n placeholder: 'Type a command or search…',\n empty: 'No results',\n navigate: 'Navigate',\n choose: 'Select',\n },\n dataTable: {\n empty: 'No data',\n noResults: 'No results',\n loading: 'Loading data…',\n searchLabel: 'Search the table',\n searchPlaceholder: 'Search…',\n perPage: 'Rows per page',\n perPageValue: (label, value) => `${label}: ${value}`,\n selectAll: 'Select all',\n selectRow: (index) => `Select row ${index}`,\n // The plural is chosen right here, in the message itself. That one line is the whole\n // of the design system's handling of plurals, and it is meant to be.\n selection: (count) => `${count} item${count === 1 ? '' : 's'} selected`,\n range: ({ start, end, total }) => `${start}–${end} of ${total}`,\n pagination: 'Table pagination',\n },\n toaster: { label: 'Notifications' },\n snackbar: { label: 'Confirmation', action: 'Undo' },\n inputOTP: {\n label: 'Verification code',\n slot: (index, total) => `Character ${index} of ${total}`,\n },\n slider: {\n value: 'Value',\n start: 'Start',\n end: 'End',\n rangeStart: (label) => `${label} (start)`,\n rangeEnd: (label) => `${label} (end)`,\n },\n field: {\n limitExceeded: (max) => `Exceeds the limit of ${max} characters`,\n },\n progress: { percent: (percent) => `${percent}%`, label: 'Progress' },\n meter: { label: 'Meter' },\n hotkeys: {\n command: 'Command',\n ctrl: 'Ctrl',\n alt: 'Alt',\n shift: 'Shift',\n windows: 'Win',\n super: 'Super',\n enter: 'Enter',\n escape: 'Esc',\n space: 'Space',\n backspace: 'Backspace',\n delete: 'Del',\n tab: 'Tab',\n up: 'Up arrow',\n down: 'Down arrow',\n left: 'Left arrow',\n right: 'Right arrow',\n label: (keys) => `Keyboard shortcut: ${keys}`,\n },\n colorPicker: {\n label: 'Colour picker',\n saturation: 'Saturation',\n brightness: 'Brightness',\n areaValue: (saturation, brightness) => `Saturation ${saturation}, brightness ${brightness}`,\n hue: 'Hue',\n alpha: 'Opacity',\n value: 'Colour value',\n format: 'Colour format',\n eyeDropper: 'Pick a colour from the screen',\n swatches: 'Preset colours',\n },\n colorInput: {\n clear: 'Clear colour',\n openPicker: 'Open colour picker',\n pickerLabel: 'Choose a colour',\n },\n datePicker: {\n label: 'Date picker',\n previousMonth: 'Previous month',\n nextMonth: 'Next month',\n previousYear: 'Previous year',\n nextYear: 'Next year',\n monthPicker: 'Choose month',\n yearPicker: 'Choose year',\n },\n dateInput: {\n clear: 'Clear date',\n openPicker: 'Open calendar',\n pickerLabel: 'Choose a date',\n },\n numberInput: {\n increment: 'Increase',\n decrement: 'Decrease',\n },\n splitButton: { menu: 'More options' },\n rating: {\n label: 'Rating',\n empty: 'No rating',\n value: (value, max) => `${value} out of ${max}`,\n },\n resizable: {\n panel: (position) => `Panel ${position}`,\n },\n stepper: {\n label: 'Progress',\n completed: 'Completed',\n error: 'Error',\n },\n treeView: {\n label: 'Tree',\n loadFailed: 'Could not load',\n loadError: (label) => `Could not load the contents of ${label}`,\n },\n timePicker: {\n label: 'Time picker',\n meridiem: 'AM or PM',\n am: 'AM',\n pm: 'PM',\n selectHour: 'Select hour',\n selectMinutes: 'Select minutes',\n choosingHour: 'Selecting the hour',\n choosingMinutes: 'Selecting the minutes',\n hour: 'Hour',\n minutes: 'Minutes',\n hourValue: (hour) => `${hour} o'clock`,\n minutesValue: (minute) => (minute === 1 ? '1 minute' : `${minute} minutes`),\n },\n timeInput: {\n clear: 'Clear time',\n openPicker: 'Open time picker',\n pickerLabel: 'Choose a time',\n meridiemValue: (value) => `AM or PM: ${value}`,\n maskPlaceholder: 'hh:mm',\n unavailable: 'This time is not available.',\n },\n fileInput: {\n openPicker: 'Choose files',\n clear: 'Clear files',\n files: (count) => `${count} file${count === 1 ? '' : 's'}`,\n placeholder: 'No file selected',\n },\n filePicker: {\n browse: 'Browse files',\n or: 'or',\n list: 'Selected files',\n },\n carousel: {\n label: 'Carousel',\n roleDescription: 'carousel',\n slideRoleDescription: 'slide',\n slides: 'Slides',\n slide: (index, total) => `${index} of ${total}`,\n previous: 'Previous slide',\n next: 'Next slide',\n indicators: 'Choose slide to display',\n },\n calendar: {\n label: 'Calendar',\n roleDescription: 'calendar',\n today: 'Today',\n view: 'View',\n viewDay: 'Day',\n view4Days: '4 days',\n viewWeek: 'Week',\n viewMonth: 'Month',\n viewYear: 'Year',\n viewCustom: (days) => `${days} days`,\n previousDay: 'Previous day',\n nextDay: 'Next day',\n previousWeek: 'Previous week',\n nextWeek: 'Next week',\n previousMonth: 'Previous month',\n nextMonth: 'Next month',\n previousYear: 'Previous year',\n nextYear: 'Next year',\n previousPeriod: 'Previous period',\n nextPeriod: 'Next period',\n allDay: 'All day',\n moreEvents: (count) => `+${count} more`,\n openDay: (day) => `Open ${day}`,\n untitled: '(No title)',\n eventRoleDescription: 'event',\n eventHint:\n 'Press Enter to open this event. Press Space to take hold of it, then the arrow keys to move it and Shift with the arrow keys to change when it ends.',\n grabbed:\n 'Event held. Use the arrow keys to move it, Enter or Space to place it, Escape to cancel.',\n dropped: 'Event placed.',\n reverted: 'Move cancelled. The event is back where it was.',\n movedTo: (title, when) => `${title} moved to ${when}.`,\n },\n}\n"],"mappings":"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"}
|