vectis-ui 0.1.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/LICENSE +21 -0
- package/NOTICE +27 -0
- package/README.md +354 -0
- package/dist/_virtual/_plugin-vue_export-helper.js +8 -0
- package/dist/components/VAccordion/VAccordion.css +2 -0
- package/dist/components/VAccordion/VAccordion.d.ts +59 -0
- package/dist/components/VAccordion/VAccordion.js +9 -0
- package/dist/components/VAccordion/VAccordion.js.map +1 -0
- package/dist/components/VAccordion/VAccordion.vue_vue_type_script_setup_true_lang.js +42 -0
- package/dist/components/VAccordion/VAccordion.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VAccordion/VAccordionItem.css +2 -0
- package/dist/components/VAccordion/VAccordionItem.d.ts +64 -0
- package/dist/components/VAccordion/VAccordionItem.js +9 -0
- package/dist/components/VAccordion/VAccordionItem.js.map +1 -0
- package/dist/components/VAccordion/VAccordionItem.vue_vue_type_script_setup_true_lang.js +70 -0
- package/dist/components/VAccordion/VAccordionItem.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VAccordion/context.d.ts +18 -0
- package/dist/components/VAccordion/context.js +6 -0
- package/dist/components/VAccordion/context.js.map +1 -0
- package/dist/components/VAvatar/VAvatar.css +2 -0
- package/dist/components/VAvatar/VAvatar.d.ts +68 -0
- package/dist/components/VAvatar/VAvatar.js +9 -0
- package/dist/components/VAvatar/VAvatar.js.map +1 -0
- package/dist/components/VAvatar/VAvatar.vue_vue_type_script_setup_true_lang.js +87 -0
- package/dist/components/VAvatar/VAvatar.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VAvatar/VAvatarGroup.css +2 -0
- package/dist/components/VAvatar/VAvatarGroup.d.ts +59 -0
- package/dist/components/VAvatar/VAvatarGroup.js +9 -0
- package/dist/components/VAvatar/VAvatarGroup.js.map +1 -0
- package/dist/components/VAvatar/VAvatarGroup.vue_vue_type_script_setup_true_lang.js +43 -0
- package/dist/components/VAvatar/VAvatarGroup.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VAvatar/context.d.ts +17 -0
- package/dist/components/VAvatar/context.js +6 -0
- package/dist/components/VAvatar/context.js.map +1 -0
- package/dist/components/VBadge/VBadge.css +2 -0
- package/dist/components/VBadge/VBadge.d.ts +74 -0
- package/dist/components/VBadge/VBadge.js +9 -0
- package/dist/components/VBadge/VBadge.js.map +1 -0
- package/dist/components/VBadge/VBadge.vue_vue_type_script_setup_true_lang.js +40 -0
- package/dist/components/VBadge/VBadge.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VBreadcrumb/VBreadcrumb.css +2 -0
- package/dist/components/VBreadcrumb/VBreadcrumb.d.ts +68 -0
- package/dist/components/VBreadcrumb/VBreadcrumb.js +9 -0
- package/dist/components/VBreadcrumb/VBreadcrumb.js.map +1 -0
- package/dist/components/VBreadcrumb/VBreadcrumb.vue_vue_type_script_setup_true_lang.js +70 -0
- package/dist/components/VBreadcrumb/VBreadcrumb.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VButton/VButton.css +2 -0
- package/dist/components/VButton/VButton.d.ts +88 -0
- package/dist/components/VButton/VButton.js +9 -0
- package/dist/components/VButton/VButton.js.map +1 -0
- package/dist/components/VButton/VButton.vue_vue_type_script_setup_true_lang.js +86 -0
- package/dist/components/VButton/VButton.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VButton/VButtonGroup.css +2 -0
- package/dist/components/VButton/VButtonGroup.d.ts +32 -0
- package/dist/components/VButton/VButtonGroup.js +9 -0
- package/dist/components/VButton/VButtonGroup.js.map +1 -0
- package/dist/components/VButton/VButtonGroup.vue_vue_type_script_setup_true_lang.js +17 -0
- package/dist/components/VButton/VButtonGroup.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VCalendar/VCalendar.css +2 -0
- package/dist/components/VCalendar/VCalendar.d.ts +129 -0
- package/dist/components/VCalendar/VCalendar.js +9 -0
- package/dist/components/VCalendar/VCalendar.js.map +1 -0
- package/dist/components/VCalendar/VCalendar.vue_vue_type_script_setup_true_lang.js +374 -0
- package/dist/components/VCalendar/VCalendar.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VCalendar/VCalendarEvent.css +2 -0
- package/dist/components/VCalendar/VCalendarEvent.d.ts +71 -0
- package/dist/components/VCalendar/VCalendarEvent.js +9 -0
- package/dist/components/VCalendar/VCalendarEvent.js.map +1 -0
- package/dist/components/VCalendar/VCalendarEvent.vue_vue_type_script_setup_true_lang.js +106 -0
- package/dist/components/VCalendar/VCalendarEvent.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VCalendar/VCalendarMonth.css +2 -0
- package/dist/components/VCalendar/VCalendarMonth.d.ts +60 -0
- package/dist/components/VCalendar/VCalendarMonth.js +9 -0
- package/dist/components/VCalendar/VCalendarMonth.js.map +1 -0
- package/dist/components/VCalendar/VCalendarMonth.vue_vue_type_script_setup_true_lang.js +342 -0
- package/dist/components/VCalendar/VCalendarMonth.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VCalendar/VCalendarTimeGrid.css +2 -0
- package/dist/components/VCalendar/VCalendarTimeGrid.d.ts +85 -0
- package/dist/components/VCalendar/VCalendarTimeGrid.js +9 -0
- package/dist/components/VCalendar/VCalendarTimeGrid.js.map +1 -0
- package/dist/components/VCalendar/VCalendarTimeGrid.vue_vue_type_script_setup_true_lang.js +621 -0
- package/dist/components/VCalendar/VCalendarTimeGrid.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VCalendar/VCalendarYear.css +2 -0
- package/dist/components/VCalendar/VCalendarYear.d.ts +31 -0
- package/dist/components/VCalendar/VCalendarYear.js +9 -0
- package/dist/components/VCalendar/VCalendarYear.js.map +1 -0
- package/dist/components/VCalendar/VCalendarYear.vue_vue_type_script_setup_true_lang.js +76 -0
- package/dist/components/VCalendar/VCalendarYear.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VCalendar/color.d.ts +9 -0
- package/dist/components/VCalendar/color.js +9 -0
- package/dist/components/VCalendar/color.js.map +1 -0
- package/dist/components/VCalendar/edgeStep.d.ts +38 -0
- package/dist/components/VCalendar/edgeStep.js +28 -0
- package/dist/components/VCalendar/edgeStep.js.map +1 -0
- package/dist/components/VCalendar/keyboard.d.ts +78 -0
- package/dist/components/VCalendar/keyboard.js +86 -0
- package/dist/components/VCalendar/keyboard.js.map +1 -0
- package/dist/components/VCalendar/layout.d.ts +355 -0
- package/dist/components/VCalendar/layout.js +292 -0
- package/dist/components/VCalendar/layout.js.map +1 -0
- package/dist/components/VCalendar/types.d.ts +78 -0
- package/dist/components/VCarousel/VCarousel.css +2 -0
- package/dist/components/VCarousel/VCarousel.d.ts +241 -0
- package/dist/components/VCarousel/VCarousel.js +9 -0
- package/dist/components/VCarousel/VCarousel.js.map +1 -0
- package/dist/components/VCarousel/VCarousel.vue_vue_type_script_setup_true_lang.js +262 -0
- package/dist/components/VCarousel/VCarousel.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VCarousel/VCarouselItem.d.ts +41 -0
- package/dist/components/VCarousel/VCarouselItem.js +7 -0
- package/dist/components/VCarousel/VCarouselItem.js.map +1 -0
- package/dist/components/VCarousel/VCarouselItem.vue_vue_type_script_setup_true_lang.js +25 -0
- package/dist/components/VCarousel/VCarouselItem.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VCarousel/context.d.ts +23 -0
- package/dist/components/VCarousel/context.js +6 -0
- package/dist/components/VCarousel/context.js.map +1 -0
- package/dist/components/VCheckbox/VCheckbox.css +2 -0
- package/dist/components/VCheckbox/VCheckbox.d.ts +63 -0
- package/dist/components/VCheckbox/VCheckbox.js +9 -0
- package/dist/components/VCheckbox/VCheckbox.js.map +1 -0
- package/dist/components/VCheckbox/VCheckbox.vue_vue_type_script_setup_true_lang.js +83 -0
- package/dist/components/VCheckbox/VCheckbox.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VChip/VChip.css +2 -0
- package/dist/components/VChip/VChip.d.ts +120 -0
- package/dist/components/VChip/VChip.js +9 -0
- package/dist/components/VChip/VChip.js.map +1 -0
- package/dist/components/VChip/VChip.vue_vue_type_script_setup_true_lang.js +118 -0
- package/dist/components/VChip/VChip.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VCombobox/VCombobox.css +2 -0
- package/dist/components/VCombobox/VCombobox.d.ts +183 -0
- package/dist/components/VCombobox/VCombobox.js +9 -0
- package/dist/components/VCombobox/VCombobox.js.map +1 -0
- package/dist/components/VCombobox/VCombobox.vue_vue_type_script_setup_true_lang.js +428 -0
- package/dist/components/VCombobox/VCombobox.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VCombobox/VComboboxGroup.css +2 -0
- package/dist/components/VCombobox/VComboboxGroup.d.ts +26 -0
- package/dist/components/VCombobox/VComboboxGroup.js +9 -0
- package/dist/components/VCombobox/VComboboxGroup.js.map +1 -0
- package/dist/components/VCombobox/VComboboxGroup.vue_vue_type_script_setup_true_lang.js +21 -0
- package/dist/components/VCombobox/VComboboxGroup.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VCombobox/VComboboxOption.css +2 -0
- package/dist/components/VCombobox/VComboboxOption.d.ts +48 -0
- package/dist/components/VCombobox/VComboboxOption.js +9 -0
- package/dist/components/VCombobox/VComboboxOption.js.map +1 -0
- package/dist/components/VCombobox/VComboboxOption.vue_vue_type_script_setup_true_lang.js +56 -0
- package/dist/components/VCombobox/VComboboxOption.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VCombobox/VComboboxSeparator.css +2 -0
- package/dist/components/VCombobox/VComboboxSeparator.d.ts +3 -0
- package/dist/components/VCombobox/VComboboxSeparator.js +9 -0
- package/dist/components/VCombobox/VComboboxSeparator.js.map +1 -0
- package/dist/components/VCombobox/VComboboxSeparator.vue_vue_type_script_setup_true_lang.js +16 -0
- package/dist/components/VCombobox/VComboboxSeparator.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VCombobox/infiniteScroll.d.ts +22 -0
- package/dist/components/VCombobox/infiniteScroll.js +28 -0
- package/dist/components/VCombobox/infiniteScroll.js.map +1 -0
- package/dist/components/VDataTable/VDataTable.css +2 -0
- package/dist/components/VDataTable/VDataTable.d.ts +214 -0
- package/dist/components/VDataTable/VDataTable.js +9 -0
- package/dist/components/VDataTable/VDataTable.js.map +1 -0
- package/dist/components/VDataTable/VDataTable.vue_vue_type_script_setup_true_lang.js +396 -0
- package/dist/components/VDataTable/VDataTable.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VDateInput/VDateInput.css +2 -0
- package/dist/components/VDateInput/VDateInput.d.ts +152 -0
- package/dist/components/VDateInput/VDateInput.js +9 -0
- package/dist/components/VDateInput/VDateInput.js.map +1 -0
- package/dist/components/VDateInput/VDateInput.vue_vue_type_script_setup_true_lang.js +324 -0
- package/dist/components/VDateInput/VDateInput.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VDatePicker/VDatePicker.css +2 -0
- package/dist/components/VDatePicker/VDatePicker.d.ts +143 -0
- package/dist/components/VDatePicker/VDatePicker.js +9 -0
- package/dist/components/VDatePicker/VDatePicker.js.map +1 -0
- package/dist/components/VDatePicker/VDatePicker.vue_vue_type_script_setup_true_lang.js +454 -0
- package/dist/components/VDatePicker/VDatePicker.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VDatePicker/keyboard.d.ts +56 -0
- package/dist/components/VDatePicker/keyboard.js +26 -0
- package/dist/components/VDatePicker/keyboard.js.map +1 -0
- package/dist/components/VDialog/VDialog.css +2 -0
- package/dist/components/VDialog/VDialog.d.ts +96 -0
- package/dist/components/VDialog/VDialog.js +9 -0
- package/dist/components/VDialog/VDialog.js.map +1 -0
- package/dist/components/VDialog/VDialog.vue_vue_type_script_setup_true_lang.js +134 -0
- package/dist/components/VDialog/VDialog.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VDialog/VDialogAlert.d.ts +67 -0
- package/dist/components/VDialog/VDialogAlert.js +7 -0
- package/dist/components/VDialog/VDialogAlert.js.map +1 -0
- package/dist/components/VDialog/VDialogAlert.vue_vue_type_script_setup_true_lang.js +60 -0
- package/dist/components/VDialog/VDialogAlert.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VFileInput/VFileInput.css +2 -0
- package/dist/components/VFileInput/VFileInput.d.ts +156 -0
- package/dist/components/VFileInput/VFileInput.js +9 -0
- package/dist/components/VFileInput/VFileInput.js.map +1 -0
- package/dist/components/VFileInput/VFileInput.vue_vue_type_script_setup_true_lang.js +244 -0
- package/dist/components/VFileInput/VFileInput.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VFileInput/truncate.d.ts +29 -0
- package/dist/components/VFileInput/truncate.js +10 -0
- package/dist/components/VFileInput/truncate.js.map +1 -0
- package/dist/components/VFilePicker/VFilePicker.css +2 -0
- package/dist/components/VFilePicker/VFilePicker.d.ts +203 -0
- package/dist/components/VFilePicker/VFilePicker.js +9 -0
- package/dist/components/VFilePicker/VFilePicker.js.map +1 -0
- package/dist/components/VFilePicker/VFilePicker.vue_vue_type_script_setup_true_lang.js +266 -0
- package/dist/components/VFilePicker/VFilePicker.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VFilePicker/fileKind.d.ts +29 -0
- package/dist/components/VFilePicker/fileKind.js +91 -0
- package/dist/components/VFilePicker/fileKind.js.map +1 -0
- package/dist/components/VHotkeys/VHotkeys.css +2 -0
- package/dist/components/VHotkeys/VHotkeys.d.ts +100 -0
- package/dist/components/VHotkeys/VHotkeys.js +9 -0
- package/dist/components/VHotkeys/VHotkeys.js.map +1 -0
- package/dist/components/VHotkeys/VHotkeys.vue_vue_type_script_setup_true_lang.js +76 -0
- package/dist/components/VHotkeys/VHotkeys.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VHotkeys/platform.d.ts +82 -0
- package/dist/components/VHotkeys/platform.js +115 -0
- package/dist/components/VHotkeys/platform.js.map +1 -0
- package/dist/components/VIcon/VIcon.css +2 -0
- package/dist/components/VIcon/VIcon.d.ts +57 -0
- package/dist/components/VIcon/VIcon.js +9 -0
- package/dist/components/VIcon/VIcon.js.map +1 -0
- package/dist/components/VIcon/VIcon.vue_vue_type_script_setup_true_lang.js +99 -0
- package/dist/components/VIcon/VIcon.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VIcon/iconProps.d.ts +30 -0
- package/dist/components/VIcon/iconProps.js +6 -0
- package/dist/components/VIcon/iconProps.js.map +1 -0
- package/dist/components/VIcon/icons/arrow_downward.d.ts +5 -0
- package/dist/components/VIcon/icons/arrow_downward.js +9 -0
- package/dist/components/VIcon/icons/arrow_downward.js.map +1 -0
- package/dist/components/VIcon/icons/arrow_downward_alt.d.ts +5 -0
- package/dist/components/VIcon/icons/arrow_downward_alt.js +9 -0
- package/dist/components/VIcon/icons/arrow_downward_alt.js.map +1 -0
- package/dist/components/VIcon/icons/arrow_drop_down.d.ts +5 -0
- package/dist/components/VIcon/icons/arrow_drop_down.js +9 -0
- package/dist/components/VIcon/icons/arrow_drop_down.js.map +1 -0
- package/dist/components/VIcon/icons/arrow_drop_up.d.ts +5 -0
- package/dist/components/VIcon/icons/arrow_drop_up.js +9 -0
- package/dist/components/VIcon/icons/arrow_drop_up.js.map +1 -0
- package/dist/components/VIcon/icons/arrow_left_alt.d.ts +5 -0
- package/dist/components/VIcon/icons/arrow_left_alt.js +9 -0
- package/dist/components/VIcon/icons/arrow_left_alt.js.map +1 -0
- package/dist/components/VIcon/icons/arrow_right_alt.d.ts +5 -0
- package/dist/components/VIcon/icons/arrow_right_alt.js +9 -0
- package/dist/components/VIcon/icons/arrow_right_alt.js.map +1 -0
- package/dist/components/VIcon/icons/arrow_upward.d.ts +5 -0
- package/dist/components/VIcon/icons/arrow_upward.js +9 -0
- package/dist/components/VIcon/icons/arrow_upward.js.map +1 -0
- package/dist/components/VIcon/icons/arrow_upward_alt.d.ts +5 -0
- package/dist/components/VIcon/icons/arrow_upward_alt.js +9 -0
- package/dist/components/VIcon/icons/arrow_upward_alt.js.map +1 -0
- package/dist/components/VIcon/icons/attach_file.d.ts +5 -0
- package/dist/components/VIcon/icons/attach_file.js +9 -0
- package/dist/components/VIcon/icons/attach_file.js.map +1 -0
- package/dist/components/VIcon/icons/audio_file.d.ts +5 -0
- package/dist/components/VIcon/icons/audio_file.js +9 -0
- package/dist/components/VIcon/icons/audio_file.js.map +1 -0
- package/dist/components/VIcon/icons/calendar_today.d.ts +5 -0
- package/dist/components/VIcon/icons/calendar_today.js +9 -0
- package/dist/components/VIcon/icons/calendar_today.js.map +1 -0
- package/dist/components/VIcon/icons/check.d.ts +5 -0
- package/dist/components/VIcon/icons/check.js +9 -0
- package/dist/components/VIcon/icons/check.js.map +1 -0
- package/dist/components/VIcon/icons/check_circle.d.ts +5 -0
- package/dist/components/VIcon/icons/check_circle.js +9 -0
- package/dist/components/VIcon/icons/check_circle.js.map +1 -0
- package/dist/components/VIcon/icons/chevron_left.d.ts +5 -0
- package/dist/components/VIcon/icons/chevron_left.js +9 -0
- package/dist/components/VIcon/icons/chevron_left.js.map +1 -0
- package/dist/components/VIcon/icons/chevron_right.d.ts +5 -0
- package/dist/components/VIcon/icons/chevron_right.js +9 -0
- package/dist/components/VIcon/icons/chevron_right.js.map +1 -0
- package/dist/components/VIcon/icons/close.d.ts +5 -0
- package/dist/components/VIcon/icons/close.js +9 -0
- package/dist/components/VIcon/icons/close.js.map +1 -0
- package/dist/components/VIcon/icons/cloud_upload.d.ts +5 -0
- package/dist/components/VIcon/icons/cloud_upload.js +9 -0
- package/dist/components/VIcon/icons/cloud_upload.js.map +1 -0
- package/dist/components/VIcon/icons/code.d.ts +5 -0
- package/dist/components/VIcon/icons/code.js +9 -0
- package/dist/components/VIcon/icons/code.js.map +1 -0
- package/dist/components/VIcon/icons/description.d.ts +5 -0
- package/dist/components/VIcon/icons/description.js +9 -0
- package/dist/components/VIcon/icons/description.js.map +1 -0
- package/dist/components/VIcon/icons/error.d.ts +5 -0
- package/dist/components/VIcon/icons/error.js +9 -0
- package/dist/components/VIcon/icons/error.js.map +1 -0
- package/dist/components/VIcon/icons/expand_less.d.ts +5 -0
- package/dist/components/VIcon/icons/expand_less.js +9 -0
- package/dist/components/VIcon/icons/expand_less.js.map +1 -0
- package/dist/components/VIcon/icons/expand_more.d.ts +5 -0
- package/dist/components/VIcon/icons/expand_more.js +9 -0
- package/dist/components/VIcon/icons/expand_more.js.map +1 -0
- package/dist/components/VIcon/icons/folder_zip.d.ts +5 -0
- package/dist/components/VIcon/icons/folder_zip.js +9 -0
- package/dist/components/VIcon/icons/folder_zip.js.map +1 -0
- package/dist/components/VIcon/icons/image.d.ts +5 -0
- package/dist/components/VIcon/icons/image.js +9 -0
- package/dist/components/VIcon/icons/image.js.map +1 -0
- package/dist/components/VIcon/icons/index.d.ts +183 -0
- package/dist/components/VIcon/icons/index.js +77 -0
- package/dist/components/VIcon/icons/index.js.map +1 -0
- package/dist/components/VIcon/icons/info.d.ts +5 -0
- package/dist/components/VIcon/icons/info.js +9 -0
- package/dist/components/VIcon/icons/info.js.map +1 -0
- package/dist/components/VIcon/icons/more_horiz.d.ts +5 -0
- package/dist/components/VIcon/icons/more_horiz.js +9 -0
- package/dist/components/VIcon/icons/more_horiz.js.map +1 -0
- package/dist/components/VIcon/icons/names.d.ts +11 -0
- package/dist/components/VIcon/icons/names.js +5 -0
- package/dist/components/VIcon/icons/names.js.map +1 -0
- package/dist/components/VIcon/icons/notifications.d.ts +5 -0
- package/dist/components/VIcon/icons/notifications.js +9 -0
- package/dist/components/VIcon/icons/notifications.js.map +1 -0
- package/dist/components/VIcon/icons/picture_as_pdf.d.ts +5 -0
- package/dist/components/VIcon/icons/picture_as_pdf.js +9 -0
- package/dist/components/VIcon/icons/picture_as_pdf.js.map +1 -0
- package/dist/components/VIcon/icons/schedule.d.ts +5 -0
- package/dist/components/VIcon/icons/schedule.js +9 -0
- package/dist/components/VIcon/icons/schedule.js.map +1 -0
- package/dist/components/VIcon/icons/search.d.ts +5 -0
- package/dist/components/VIcon/icons/search.js +9 -0
- package/dist/components/VIcon/icons/search.js.map +1 -0
- package/dist/components/VIcon/icons/swap_vert.d.ts +5 -0
- package/dist/components/VIcon/icons/swap_vert.js +9 -0
- package/dist/components/VIcon/icons/swap_vert.js.map +1 -0
- package/dist/components/VIcon/icons/table_chart.d.ts +5 -0
- package/dist/components/VIcon/icons/table_chart.js +9 -0
- package/dist/components/VIcon/icons/table_chart.js.map +1 -0
- package/dist/components/VIcon/icons/video_file.d.ts +5 -0
- package/dist/components/VIcon/icons/video_file.js +9 -0
- package/dist/components/VIcon/icons/video_file.js.map +1 -0
- package/dist/components/VIcon/icons/viewBox.d.ts +6 -0
- package/dist/components/VIcon/icons/viewBox.js +6 -0
- package/dist/components/VIcon/icons/viewBox.js.map +1 -0
- package/dist/components/VIcon/icons/warning.d.ts +5 -0
- package/dist/components/VIcon/icons/warning.js +9 -0
- package/dist/components/VIcon/icons/warning.js.map +1 -0
- package/dist/components/VIcon/resolver.d.ts +76 -0
- package/dist/components/VIcon/resolver.js +35 -0
- package/dist/components/VIcon/resolver.js.map +1 -0
- package/dist/components/VIcon/types.d.ts +77 -0
- package/dist/components/VIconButton/VIconButton.css +2 -0
- package/dist/components/VIconButton/VIconButton.d.ts +66 -0
- package/dist/components/VIconButton/VIconButton.js +9 -0
- package/dist/components/VIconButton/VIconButton.js.map +1 -0
- package/dist/components/VIconButton/VIconButton.vue_vue_type_script_setup_true_lang.js +70 -0
- package/dist/components/VIconButton/VIconButton.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VInput/VInput.css +2 -0
- package/dist/components/VInput/VInput.d.ts +152 -0
- package/dist/components/VInput/VInput.js +9 -0
- package/dist/components/VInput/VInput.js.map +1 -0
- package/dist/components/VInput/VInput.vue_vue_type_script_setup_true_lang.js +185 -0
- package/dist/components/VInput/VInput.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VInputOTP/VInputOTP.css +2 -0
- package/dist/components/VInputOTP/VInputOTP.d.ts +76 -0
- package/dist/components/VInputOTP/VInputOTP.js +9 -0
- package/dist/components/VInputOTP/VInputOTP.js.map +1 -0
- package/dist/components/VInputOTP/VInputOTP.vue_vue_type_script_setup_true_lang.js +149 -0
- package/dist/components/VInputOTP/VInputOTP.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VMenu/VMenu.d.ts +91 -0
- package/dist/components/VMenu/VMenu.js +7 -0
- package/dist/components/VMenu/VMenu.js.map +1 -0
- package/dist/components/VMenu/VMenu.vue_vue_type_script_setup_true_lang.js +73 -0
- package/dist/components/VMenu/VMenu.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VMenu/VMenuGroup.css +2 -0
- package/dist/components/VMenu/VMenuGroup.d.ts +22 -0
- package/dist/components/VMenu/VMenuGroup.js +9 -0
- package/dist/components/VMenu/VMenuGroup.js.map +1 -0
- package/dist/components/VMenu/VMenuGroup.vue_vue_type_script_setup_true_lang.js +21 -0
- package/dist/components/VMenu/VMenuGroup.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VMenu/VMenuItem.css +2 -0
- package/dist/components/VMenu/VMenuItem.d.ts +85 -0
- package/dist/components/VMenu/VMenuItem.js +9 -0
- package/dist/components/VMenu/VMenuItem.js.map +1 -0
- package/dist/components/VMenu/VMenuItem.vue_vue_type_script_setup_true_lang.js +121 -0
- package/dist/components/VMenu/VMenuItem.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VMenu/VMenuPanel.css +2 -0
- package/dist/components/VMenu/VMenuPanel.d.ts +91 -0
- package/dist/components/VMenu/VMenuPanel.js +9 -0
- package/dist/components/VMenu/VMenuPanel.js.map +1 -0
- package/dist/components/VMenu/VMenuPanel.vue_vue_type_script_setup_true_lang.js +103 -0
- package/dist/components/VMenu/VMenuPanel.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VMenu/VMenuSeparator.css +2 -0
- package/dist/components/VMenu/VMenuSeparator.d.ts +3 -0
- package/dist/components/VMenu/VMenuSeparator.js +9 -0
- package/dist/components/VMenu/VMenuSeparator.js.map +1 -0
- package/dist/components/VMenu/VMenuSeparator.vue_vue_type_script_setup_true_lang.js +13 -0
- package/dist/components/VMenu/VMenuSeparator.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VMenu/context.d.ts +33 -0
- package/dist/components/VMenu/context.js +9 -0
- package/dist/components/VMenu/context.js.map +1 -0
- package/dist/components/VPagination/VPagination.css +2 -0
- package/dist/components/VPagination/VPagination.d.ts +103 -0
- package/dist/components/VPagination/VPagination.js +9 -0
- package/dist/components/VPagination/VPagination.js.map +1 -0
- package/dist/components/VPagination/VPagination.vue_vue_type_script_setup_true_lang.js +270 -0
- package/dist/components/VPagination/VPagination.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VPopover/VPopover.css +2 -0
- package/dist/components/VPopover/VPopover.d.ts +82 -0
- package/dist/components/VPopover/VPopover.js +9 -0
- package/dist/components/VPopover/VPopover.js.map +1 -0
- package/dist/components/VPopover/VPopover.vue_vue_type_script_setup_true_lang.js +65 -0
- package/dist/components/VPopover/VPopover.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VProgressCircular/VProgressCircular.css +2 -0
- package/dist/components/VProgressCircular/VProgressCircular.d.ts +60 -0
- package/dist/components/VProgressCircular/VProgressCircular.js +9 -0
- package/dist/components/VProgressCircular/VProgressCircular.js.map +1 -0
- package/dist/components/VProgressCircular/VProgressCircular.vue_vue_type_script_setup_true_lang.js +74 -0
- package/dist/components/VProgressCircular/VProgressCircular.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VProgressLinear/VProgressLinear.css +2 -0
- package/dist/components/VProgressLinear/VProgressLinear.d.ts +74 -0
- package/dist/components/VProgressLinear/VProgressLinear.js +9 -0
- package/dist/components/VProgressLinear/VProgressLinear.js.map +1 -0
- package/dist/components/VProgressLinear/VProgressLinear.vue_vue_type_script_setup_true_lang.js +74 -0
- package/dist/components/VProgressLinear/VProgressLinear.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VRadio/VRadio.css +2 -0
- package/dist/components/VRadio/VRadio.d.ts +58 -0
- package/dist/components/VRadio/VRadio.js +9 -0
- package/dist/components/VRadio/VRadio.js.map +1 -0
- package/dist/components/VRadio/VRadio.vue_vue_type_script_setup_true_lang.js +60 -0
- package/dist/components/VRadio/VRadio.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VSeparator/VSeparator.css +2 -0
- package/dist/components/VSeparator/VSeparator.d.ts +23 -0
- package/dist/components/VSeparator/VSeparator.js +9 -0
- package/dist/components/VSeparator/VSeparator.js.map +1 -0
- package/dist/components/VSeparator/VSeparator.vue_vue_type_script_setup_true_lang.js +17 -0
- package/dist/components/VSeparator/VSeparator.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VSideNavigation/VSideNavigation.css +2 -0
- package/dist/components/VSideNavigation/VSideNavigation.d.ts +64 -0
- package/dist/components/VSideNavigation/VSideNavigation.js +9 -0
- package/dist/components/VSideNavigation/VSideNavigation.js.map +1 -0
- package/dist/components/VSideNavigation/VSideNavigation.vue_vue_type_script_setup_true_lang.js +67 -0
- package/dist/components/VSideNavigation/VSideNavigation.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VSideNavigation/VSideNavigationGroup.css +2 -0
- package/dist/components/VSideNavigation/VSideNavigationGroup.d.ts +33 -0
- package/dist/components/VSideNavigation/VSideNavigationGroup.js +9 -0
- package/dist/components/VSideNavigation/VSideNavigationGroup.js.map +1 -0
- package/dist/components/VSideNavigation/VSideNavigationGroup.vue_vue_type_script_setup_true_lang.js +20 -0
- package/dist/components/VSideNavigation/VSideNavigationGroup.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VSideNavigation/VSideNavigationItem.css +2 -0
- package/dist/components/VSideNavigation/VSideNavigationItem.d.ts +103 -0
- package/dist/components/VSideNavigation/VSideNavigationItem.js +9 -0
- package/dist/components/VSideNavigation/VSideNavigationItem.js.map +1 -0
- package/dist/components/VSideNavigation/VSideNavigationItem.vue_vue_type_script_setup_true_lang.js +154 -0
- package/dist/components/VSideNavigation/VSideNavigationItem.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VSideNavigation/VSideNavigationSeparator.css +2 -0
- package/dist/components/VSideNavigation/VSideNavigationSeparator.d.ts +3 -0
- package/dist/components/VSideNavigation/VSideNavigationSeparator.js +17 -0
- package/dist/components/VSideNavigation/VSideNavigationSeparator.js.map +1 -0
- package/dist/components/VSideNavigation/context.d.ts +37 -0
- package/dist/components/VSideNavigation/context.js +6 -0
- package/dist/components/VSideNavigation/context.js.map +1 -0
- package/dist/components/VSkeletonLoader/VSkeletonLoader.css +2 -0
- package/dist/components/VSkeletonLoader/VSkeletonLoader.d.ts +75 -0
- package/dist/components/VSkeletonLoader/VSkeletonLoader.js +9 -0
- package/dist/components/VSkeletonLoader/VSkeletonLoader.js.map +1 -0
- package/dist/components/VSkeletonLoader/VSkeletonLoader.vue_vue_type_script_setup_true_lang.js +61 -0
- package/dist/components/VSkeletonLoader/VSkeletonLoader.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VSlider/VSlider.css +2 -0
- package/dist/components/VSlider/VSlider.d.ts +82 -0
- package/dist/components/VSlider/VSlider.js +9 -0
- package/dist/components/VSlider/VSlider.js.map +1 -0
- package/dist/components/VSlider/VSlider.vue_vue_type_script_setup_true_lang.js +220 -0
- package/dist/components/VSlider/VSlider.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VSnackbar/VSnackbar.css +2 -0
- package/dist/components/VSnackbar/VSnackbar.d.ts +51 -0
- package/dist/components/VSnackbar/VSnackbar.js +9 -0
- package/dist/components/VSnackbar/VSnackbar.js.map +1 -0
- package/dist/components/VSnackbar/VSnackbar.vue_vue_type_script_setup_true_lang.js +83 -0
- package/dist/components/VSnackbar/VSnackbar.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VSnackbar/state.d.ts +92 -0
- package/dist/components/VSnackbar/state.js +18 -0
- package/dist/components/VSnackbar/state.js.map +1 -0
- package/dist/components/VSpinner/VSpinner.css +2 -0
- package/dist/components/VSpinner/VSpinner.d.ts +21 -0
- package/dist/components/VSpinner/VSpinner.js +9 -0
- package/dist/components/VSpinner/VSpinner.js.map +1 -0
- package/dist/components/VSpinner/VSpinner.vue_vue_type_script_setup_true_lang.js +25 -0
- package/dist/components/VSpinner/VSpinner.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VSwitch/VSwitch.css +2 -0
- package/dist/components/VSwitch/VSwitch.d.ts +46 -0
- package/dist/components/VSwitch/VSwitch.js +9 -0
- package/dist/components/VSwitch/VSwitch.js.map +1 -0
- package/dist/components/VSwitch/VSwitch.vue_vue_type_script_setup_true_lang.js +51 -0
- package/dist/components/VSwitch/VSwitch.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VTabs/VTab.css +2 -0
- package/dist/components/VTabs/VTab.d.ts +42 -0
- package/dist/components/VTabs/VTab.js +9 -0
- package/dist/components/VTabs/VTab.js.map +1 -0
- package/dist/components/VTabs/VTab.vue_vue_type_script_setup_true_lang.js +66 -0
- package/dist/components/VTabs/VTab.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VTabs/VTabPanel.css +2 -0
- package/dist/components/VTabs/VTabPanel.d.ts +34 -0
- package/dist/components/VTabs/VTabPanel.js +9 -0
- package/dist/components/VTabs/VTabPanel.js.map +1 -0
- package/dist/components/VTabs/VTabPanel.vue_vue_type_script_setup_true_lang.js +34 -0
- package/dist/components/VTabs/VTabPanel.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VTabs/VTabs.css +2 -0
- package/dist/components/VTabs/VTabs.d.ts +107 -0
- package/dist/components/VTabs/VTabs.js +9 -0
- package/dist/components/VTabs/VTabs.js.map +1 -0
- package/dist/components/VTabs/VTabs.vue_vue_type_script_setup_true_lang.js +199 -0
- package/dist/components/VTabs/VTabs.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VTabs/context.d.ts +43 -0
- package/dist/components/VTabs/context.js +6 -0
- package/dist/components/VTabs/context.js.map +1 -0
- package/dist/components/VTextarea/VTextarea.css +2 -0
- package/dist/components/VTextarea/VTextarea.d.ts +140 -0
- package/dist/components/VTextarea/VTextarea.js +9 -0
- package/dist/components/VTextarea/VTextarea.js.map +1 -0
- package/dist/components/VTextarea/VTextarea.vue_vue_type_script_setup_true_lang.js +187 -0
- package/dist/components/VTextarea/VTextarea.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VTimeInput/VTimeInput.css +2 -0
- package/dist/components/VTimeInput/VTimeInput.d.ts +112 -0
- package/dist/components/VTimeInput/VTimeInput.js +9 -0
- package/dist/components/VTimeInput/VTimeInput.js.map +1 -0
- package/dist/components/VTimeInput/VTimeInput.vue_vue_type_script_setup_true_lang.js +385 -0
- package/dist/components/VTimeInput/VTimeInput.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VTimePicker/VTimePicker.css +2 -0
- package/dist/components/VTimePicker/VTimePicker.d.ts +89 -0
- package/dist/components/VTimePicker/VTimePicker.js +9 -0
- package/dist/components/VTimePicker/VTimePicker.js.map +1 -0
- package/dist/components/VTimePicker/VTimePicker.vue_vue_type_script_setup_true_lang.js +257 -0
- package/dist/components/VTimePicker/VTimePicker.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VToast/VToast.css +2 -0
- package/dist/components/VToast/VToast.d.ts +24 -0
- package/dist/components/VToast/VToast.js +9 -0
- package/dist/components/VToast/VToast.js.map +1 -0
- package/dist/components/VToast/VToast.vue_vue_type_script_setup_true_lang.js +62 -0
- package/dist/components/VToast/VToast.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VToast/VToaster.css +2 -0
- package/dist/components/VToast/VToaster.d.ts +42 -0
- package/dist/components/VToast/VToaster.js +9 -0
- package/dist/components/VToast/VToaster.js.map +1 -0
- package/dist/components/VToast/VToaster.vue_vue_type_script_setup_true_lang.js +112 -0
- package/dist/components/VToast/VToaster.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VToast/state.d.ts +74 -0
- package/dist/components/VToast/state.js +25 -0
- package/dist/components/VToast/state.js.map +1 -0
- package/dist/components/VToggle/VToggle.css +2 -0
- package/dist/components/VToggle/VToggle.d.ts +84 -0
- package/dist/components/VToggle/VToggle.js +9 -0
- package/dist/components/VToggle/VToggle.js.map +1 -0
- package/dist/components/VToggle/VToggle.vue_vue_type_script_setup_true_lang.js +103 -0
- package/dist/components/VToggle/VToggle.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VToggle/VToggleItem.css +2 -0
- package/dist/components/VToggle/VToggleItem.d.ts +35 -0
- package/dist/components/VToggle/VToggleItem.js +9 -0
- package/dist/components/VToggle/VToggleItem.js.map +1 -0
- package/dist/components/VToggle/VToggleItem.vue_vue_type_script_setup_true_lang.js +51 -0
- package/dist/components/VToggle/VToggleItem.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VToggle/context.d.ts +37 -0
- package/dist/components/VToggle/context.js +6 -0
- package/dist/components/VToggle/context.js.map +1 -0
- package/dist/components/VTooltip/VTooltip.css +2 -0
- package/dist/components/VTooltip/VTooltip.d.ts +76 -0
- package/dist/components/VTooltip/VTooltip.js +9 -0
- package/dist/components/VTooltip/VTooltip.js.map +1 -0
- package/dist/components/VTooltip/VTooltip.vue_vue_type_script_setup_true_lang.js +50 -0
- package/dist/components/VTooltip/VTooltip.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VTypography/VTypography.css +2 -0
- package/dist/components/VTypography/VTypography.d.ts +46 -0
- package/dist/components/VTypography/VTypography.js +9 -0
- package/dist/components/VTypography/VTypography.js.map +1 -0
- package/dist/components/VTypography/VTypography.vue_vue_type_script_setup_true_lang.js +49 -0
- package/dist/components/VTypography/VTypography.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/composables/useAriaLabel.d.ts +19 -0
- package/dist/composables/useAriaLabel.js +10 -0
- package/dist/composables/useAriaLabel.js.map +1 -0
- package/dist/composables/useFieldIds.d.ts +21 -0
- package/dist/composables/useFieldIds.js +14 -0
- package/dist/composables/useFieldIds.js.map +1 -0
- package/dist/composables/useFieldPanel.d.ts +61 -0
- package/dist/composables/useFieldPanel.js +39 -0
- package/dist/composables/useFieldPanel.js.map +1 -0
- package/dist/composables/useFileDrop.d.ts +30 -0
- package/dist/composables/useFileDrop.js +28 -0
- package/dist/composables/useFileDrop.js.map +1 -0
- package/dist/composables/useFileField.d.ts +36 -0
- package/dist/composables/useFileField.js +45 -0
- package/dist/composables/useFileField.js.map +1 -0
- package/dist/composables/useFocusoutDismiss.d.ts +17 -0
- package/dist/composables/useFocusoutDismiss.js +11 -0
- package/dist/composables/useFocusoutDismiss.js.map +1 -0
- package/dist/composables/useIconClickHandlers.d.ts +27 -0
- package/dist/composables/useIconClickHandlers.js +13 -0
- package/dist/composables/useIconClickHandlers.js.map +1 -0
- package/dist/composables/useMaskedField.d.ts +65 -0
- package/dist/composables/useMaskedField.js +54 -0
- package/dist/composables/useMaskedField.js.map +1 -0
- package/dist/composables/usePopover.d.ts +7 -0
- package/dist/composables/usePopover.js +24 -0
- package/dist/composables/usePopover.js.map +1 -0
- package/dist/composables/useProgressValue.d.ts +13 -0
- package/dist/composables/useProgressValue.js +14 -0
- package/dist/composables/useProgressValue.js.map +1 -0
- package/dist/composables/useRootAttrs.d.ts +34 -0
- package/dist/composables/useRootAttrs.js +15 -0
- package/dist/composables/useRootAttrs.js.map +1 -0
- package/dist/composables/useTextLimit.d.ts +31 -0
- package/dist/composables/useTextLimit.js +19 -0
- package/dist/composables/useTextLimit.js.map +1 -0
- package/dist/composables/useTimer.d.ts +18 -0
- package/dist/composables/useTimer.js +19 -0
- package/dist/composables/useTimer.js.map +1 -0
- package/dist/i18n/en.d.ts +10 -0
- package/dist/i18n/en.js +179 -0
- package/dist/i18n/en.js.map +1 -0
- package/dist/i18n/fr.d.ts +18 -0
- package/dist/i18n/fr.js +179 -0
- package/dist/i18n/fr.js.map +1 -0
- package/dist/i18n/state.d.ts +64 -0
- package/dist/i18n/state.js +40 -0
- package/dist/i18n/state.js.map +1 -0
- package/dist/i18n/types.d.ts +345 -0
- package/dist/icons.d.ts +16 -0
- package/dist/icons.js +38 -0
- package/dist/index.d.ts +90 -0
- package/dist/index.js +64 -0
- package/dist/styles.css +1 -0
- package/dist/tokens/css.d.ts +25 -0
- package/dist/tokens/css.js +29 -0
- package/dist/tokens/css.js.map +1 -0
- package/dist/tokens/index.d.ts +370 -0
- package/dist/tokens/index.js +15 -0
- package/dist/tokens/index.js.map +1 -0
- package/dist/tokens/primitives.d.ts +101 -0
- package/dist/tokens/primitives.js +166 -0
- package/dist/tokens/primitives.js.map +1 -0
- package/dist/tokens/semantic.d.ts +236 -0
- package/dist/tokens/semantic.js +219 -0
- package/dist/tokens/semantic.js.map +1 -0
- package/dist/tokens/themes/dark.d.ts +49 -0
- package/dist/tokens/themes/dark.js +53 -0
- package/dist/tokens/themes/dark.js.map +1 -0
- package/dist/tokens/types.d.ts +38 -0
- package/dist/tokens/types.js +16 -0
- package/dist/tokens/types.js.map +1 -0
- package/dist/tokens.json +1516 -0
- package/dist/utils/array.d.ts +10 -0
- package/dist/utils/array.js +8 -0
- package/dist/utils/array.js.map +1 -0
- package/dist/utils/arrowNav.d.ts +27 -0
- package/dist/utils/arrowNav.js +26 -0
- package/dist/utils/arrowNav.js.map +1 -0
- package/dist/utils/chip.d.ts +26 -0
- package/dist/utils/chip.js +13 -0
- package/dist/utils/chip.js.map +1 -0
- package/dist/utils/css.d.ts +19 -0
- package/dist/utils/css.js +13 -0
- package/dist/utils/css.js.map +1 -0
- package/dist/utils/date.d.ts +199 -0
- package/dist/utils/date.js +225 -0
- package/dist/utils/date.js.map +1 -0
- package/dist/utils/direction.d.ts +18 -0
- package/dist/utils/direction.js +8 -0
- package/dist/utils/direction.js.map +1 -0
- package/dist/utils/env.d.ts +10 -0
- package/dist/utils/file.d.ts +95 -0
- package/dist/utils/file.js +70 -0
- package/dist/utils/file.js.map +1 -0
- package/dist/utils/focus.d.ts +24 -0
- package/dist/utils/focus.js +13 -0
- package/dist/utils/focus.js.map +1 -0
- package/dist/utils/matcher.d.ts +13 -0
- package/dist/utils/matcher.js +11 -0
- package/dist/utils/matcher.js.map +1 -0
- package/dist/utils/number.d.ts +9 -0
- package/dist/utils/number.js +8 -0
- package/dist/utils/number.js.map +1 -0
- package/dist/utils/text.d.ts +19 -0
- package/dist/utils/text.js +12 -0
- package/dist/utils/text.js.map +1 -0
- package/dist/utils/time.d.ts +138 -0
- package/dist/utils/time.js +123 -0
- package/dist/utils/time.js.map +1 -0
- package/dist/utils/vnode.d.ts +21 -0
- package/dist/utils/vnode.js +14 -0
- package/dist/utils/vnode.js.map +1 -0
- package/package.json +114 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"VFilePicker.vue_vue_type_script_setup_true_lang.js","names":["$slots"],"sources":["../../../src/components/VFilePicker/VFilePicker.vue"],"sourcesContent":["<script setup lang=\"ts\">\n// @core\n/**\n * A drop zone: a dashed rectangle that accepts files dragged onto it or chosen through\n * a dialog, with an optional list of what has been taken.\n *\n * The value is a plain list of files, and the division of labour matters: this component\n * SHOWS and SCREENS, while sending anything anywhere is the parent's business.\n *\n * Four pieces of behaviour need JavaScript, each because the platform leaves no choice.\n * A file dialog opens ONLY from a real click on a real file input, and the list of files\n * it holds cannot be written from a template — hence the relayed click, and the hidden\n * input being a source of files rather than a mirror of the value. The `accept`\n * attribute has no say over a DROP, the browser handing the dropped files over\n * untouched, so the screening has to happen in code. That input has to be reset after\n * every change, or the same file cannot be chosen twice in a row. And a thumbnail has no\n * HTML-only form: an image needs an address, a file only yields one through a temporary\n * URL, and that URL then has to be released.\n *\n * What deliberately is NOT JavaScript is the keyboard. With the browse button hidden,\n * the zone becomes a real button, so Enter, Space, the focus, the role and the complete\n * inertness of a disabled control all come from the browser. The other incarnation, a\n * plain container, exists for one reason only: a button inside a button is invalid\n * markup and unusable by keyboard. Nor is any of the drag highlighting, the \"or\"\n * separator, or the side-by-side layout — all three are CSS.\n */\nimport {\n computed,\n nextTick,\n onBeforeUnmount,\n onMounted,\n reactive,\n ref,\n watch,\n watchEffect,\n} from 'vue'\n\nimport VButton from '../VButton/VButton.vue'\nimport VIcon from '../VIcon/VIcon.vue'\nimport { iconProps } from '../VIcon/iconProps'\nimport { audio_file as audioFileIcon } from '../VIcon/icons/audio_file'\nimport { close as closeIcon } from '../VIcon/icons/close'\nimport { cloud_upload as cloudUploadIcon } from '../VIcon/icons/cloud_upload'\nimport { code as codeIcon } from '../VIcon/icons/code'\nimport { description as descriptionIcon } from '../VIcon/icons/description'\nimport { folder_zip as folderZipIcon } from '../VIcon/icons/folder_zip'\nimport { image as imageIcon } from '../VIcon/icons/image'\nimport { picture_as_pdf as pictureAsPdfIcon } from '../VIcon/icons/picture_as_pdf'\nimport { table_chart as tableChartIcon } from '../VIcon/icons/table_chart'\nimport { video_file as videoFileIcon } from '../VIcon/icons/video_file'\nimport type { IconSource } from '../VIcon/types'\nimport VIconButton from '../VIconButton/VIconButton.vue'\nimport VTypography from '../VTypography/VTypography.vue'\n\nimport { useFileDrop } from '../../composables/useFileDrop'\nimport { useFileField } from '../../composables/useFileField'\nimport { useRootAttrs } from '../../composables/useRootAttrs'\nimport { useLocale, useMessages } from '../../i18n/state'\nimport { isDev } from '../../utils/env'\nimport { formatBytes } from '../../utils/file'\nimport { fileKind, type FileKind } from './fileKind'\n\n/** Where the files taken are listed — under the zone, beside it, or nowhere. */\nexport type FilePickerPreview = false | 'bottom' | 'end'\n\n/** Why a file was turned away: its kind, its size, how many there already are, or the total. */\nexport type FilePickerRejectReason = 'type' | 'size' | 'count' | 'total-size'\n\n/** One file that was turned away, and the reason it was. */\nexport interface FilePickerRejection {\n /** The file itself, so a message can name it. */\n file: File\n /** What it fell foul of. */\n reason: FilePickerRejectReason\n}\n\n/**\n * Everything known about one row of the list. The same object is handed to both slots\n * that can replace part of a row, so the two can never be given different information.\n */\nexport interface FilePickerRow {\n /** The file itself. */\n file: File\n /** Its position in the list. */\n index: number\n /** What kind of file it is, as worked out from its type or its extension. */\n kind: FileKind\n /**\n * The address of its image thumbnail, when there is one.\n *\n * It is absent on the server AND on the browser's first render — those addresses only\n * exist in a browser, and creating them during the first render would make the two\n * markups differ — and absent as well for anything the browser fails to decode. Fall\n * back to the icon in that case.\n */\n thumbnail: string | undefined\n /** The icon standing for that kind of file, a consumer's override included. */\n icon: IconSource\n /** Its size, already written out in the reader's conventions. */\n sizeText: string\n /** Takes this file out of the list. */\n remove: () => void\n}\n\ninterface FilePickerProps {\n /**\n * What the reader is being asked to drop, in one line. It is REQUIRED: a drop zone\n * with no instruction is just a rectangle.\n *\n * Note that this prop shadows the HTML attribute of the same name on the component\n * itself, an accepted trade-off — a tooltip on a drop zone would be redundant anyway.\n */\n title: string\n /** A second line under it, for the constraints in plain words: kinds, sizes, how many. */\n subtitle?: string\n /** The large icon at the top of the zone. */\n icon?: IconSource\n /**\n * Shows the separator and the browse button under the instruction. Hiding them\n * changes the zone's nature: it then becomes the control ITSELF, a real button, so\n * Enter, Space and the focus come from the platform rather than from a container that\n * merely reacts to clicks.\n */\n showBrowse?: boolean\n /** The wording of the browse button. It falls back to the design system dictionary. */\n browseLabel?: string\n /**\n * Where the files taken are listed: under the zone, or beside it — beside folds back\n * underneath when the COMPONENT is narrow, following the width it was given rather\n * than the width of the window.\n *\n * By default nothing is listed at all: the value is there for a parent that wants to\n * present it its own way.\n */\n preview?: FilePickerPreview\n /**\n * Shows a thumbnail for each image in that list. Every image is given a temporary\n * address, created in the browser only and released as soon as the file leaves the\n * list or the component goes away.\n *\n * Turning it off shows the kind icon for every file instead — the way out when a list\n * holds many images, or very large ones.\n */\n thumbnails?: boolean\n /** Replaces the icon of one or more kinds of file. */\n typeIcons?: Partial<Record<FileKind, IconSource>>\n /** The icon of the button removing a file from the list. */\n removeIcon?: IconSource\n /** Allows several files to be taken. With one only, every extra file is turned away. */\n multiple?: boolean\n /**\n * Which kinds of file are accepted, in the browser's own syntax (`image/*,.pdf`).\n *\n * It is applied TWICE, and it has to be: as an attribute, which is what filters the\n * system's file dialog, and again in code, which is the only thing that can filter a\n * DROPPED file — the attribute has no say over a drop.\n */\n accept?: string\n /** The largest ONE file may be, in bytes. */\n maxSize?: number\n /** The largest the whole selection may be, in bytes. */\n maxTotalSize?: number\n /** How many files may be taken at most. */\n maxFiles?: number\n /** Makes the zone unusable, greyed out through the colour tokens. */\n disabled?: boolean\n /** Shows what was taken without allowing it to change: no dialog, no drop, no removal. */\n readonly?: boolean\n}\n\ndefineOptions({ inheritAttrs: false })\n\nconst props = withDefaults(defineProps<FilePickerProps>(), {\n subtitle: undefined,\n icon: () => cloudUploadIcon,\n showBrowse: true,\n browseLabel: undefined,\n preview: false,\n thumbnails: true,\n typeIcons: undefined,\n removeIcon: () => closeIcon,\n multiple: false,\n accept: undefined,\n maxSize: undefined,\n maxTotalSize: undefined,\n maxFiles: undefined,\n disabled: false,\n readonly: false,\n})\n\nconst emit = defineEmits<{\n /** The reader changed the selection, by adding or removing something. */\n change: [files: File[]]\n /**\n * A file was turned away and never joined the selection. It is emitted once PER file,\n * so a batch drop can be reported precisely.\n */\n reject: [rejection: FilePickerRejection]\n /**\n * One file was taken out, and which one. It exists alongside `change`, which only says\n * what is LEFT: an upload already in flight is aborted from here, without having to\n * compare two lists to find out what went.\n */\n remove: [file: File, index: number]\n}>()\n\ndefineSlots<{\n /**\n * The large icon, for an illustration the icon props cannot express.\n *\n * It must stay non-interactive, and so must the two below: with the browse button\n * hidden, the zone IS a button, and nothing interactive may sit inside one.\n */\n icon?(): unknown\n /** The instruction. Text and inline elements only, for the same reason. */\n title?(): unknown\n /** The second line. Same contract as the instruction. */\n subtitle?(): unknown\n /**\n * The browse button. Call the `open` it receives: without it a button of your own\n * could no longer open the file dialog at all.\n */\n browse?(props: { open: () => void; disabled: boolean }): unknown\n /**\n * A WHOLE row of the list — the way out for a row showing its own upload progress. It\n * receives everything the standard row was given, so nothing has to be worked out\n * again.\n */\n item?(props: FilePickerRow): unknown\n /**\n * The square at the start of a row alone: for a thumbnail produced by your server, a\n * video's poster frame, or a format the browser cannot decode.\n */\n thumbnail?(props: FilePickerRow): unknown\n /**\n * The control that removes a row. Two of the values it receives are not optional in\n * practice: `remove` is the only thing that can take the file out, and `label` is the\n * ready-made name — including the file's own — without which the button would be\n * announced as nothing at all.\n */\n remove?(props: { file: File; index: number; remove: () => void; label: string }): unknown\n}>()\n\n/**\n * Always a LIST of files, whether or not several are allowed — never a file on its own.\n * The shape of the value does not depend on a prop, so a consumer never has to narrow a\n * union TypeScript has no way of discriminating. With a single file it is simply a list\n * of at most one.\n */\nconst model = defineModel<File[]>({ default: () => [] })\n\nconst { attrs, rootClass, rootStyle, forwardedAttrs } = useRootAttrs()\n\nconst m = useMessages()\nconst locale = useLocale()\n\nconst interactive = computed(() => !props.disabled && !props.readonly)\n\n/*\n * The hidden input, the sorting of the consumer's attributes and the single entry point\n * into the value all live in `useFileField`, shared with VFileInput.\n *\n * Here, the bucket meant for \"the control the user deals with\" goes to the ZONE: that is\n * what they see, and what takes the focus once the browse button is hidden. Nothing is\n * pulled out of it, unlike in VFileInput — this component assembles no description of\n * its own.\n */\nconst {\n fileEl,\n nativeAttrs,\n controlAttrs: zoneAttrs,\n acceptFiles,\n onNativeChange,\n openPicker,\n resetNative,\n} = useFileField({\n model,\n forwardedAttrs,\n enabled: () => interactive.value,\n multiple: () => props.multiple,\n limits: () => ({\n accept: props.accept,\n maxSize: props.maxSize,\n maxFiles: props.maxFiles,\n maxTotalSize: props.maxTotalSize,\n }),\n onReject: (rejection) => emit('reject', rejection),\n onChange: (files) => emit('change', files),\n})\n\nconst zoneEl = ref<HTMLElement | null>(null)\nconst listEl = ref<HTMLUListElement | null>(null)\n/** The zone becomes the control exactly when there is no button inside to be one. */\nconst zoneIsControl = computed(() => !props.showBrowse)\nconst showList = computed(() => props.preview !== false && model.value.length > 0)\n\n/**\n * Which icon stands for which kind of file. A consumer overrides it entry by entry, so\n * replacing one icon does not mean restating the other seven.\n */\nconst KIND_ICONS: Record<FileKind, IconSource> = {\n image: imageIcon,\n pdf: pictureAsPdfIcon,\n audio: audioFileIcon,\n video: videoFileIcon,\n archive: folderZipIcon,\n spreadsheet: tableChartIcon,\n code: codeIcon,\n file: descriptionIcon,\n}\n\nconst iconForKind = (kind: FileKind): IconSource => props.typeIcons?.[kind] ?? KIND_ICONS[kind]\n\nfunction onZoneClick(event: MouseEvent) {\n // The browse button already handles its own click, and that click also reaches the\n // zone: without this guard it would open the dialog twice. The test is inert when the\n // zone IS the button, there being nothing inside it to match.\n if (!zoneIsControl.value && (event.target as HTMLElement).closest('button')) return\n openPicker()\n}\n\nconst { dragging, onDragEnter, onDragOver, onDragLeave, onDrop } = useFileDrop(\n () => interactive.value,\n acceptFiles,\n)\n\n// @a11y\n/**\n * What can be focused in the zone, whichever shape it has taken: the zone itself when it\n * is the button, and otherwise the first button inside it.\n *\n * It is found by searching the DOM rather than kept as a reference, because a consumer\n * may have replaced the browse button entirely — theirs is not ours to hold a reference\n * to, and it still has to be reachable.\n */\nfunction focusTarget(): HTMLElement | null {\n const zone = zoneEl.value\n if (!zone) return null\n return zone.matches('button') ? zone : zone.querySelector('button')\n}\n\n// @a11y @core\n/**\n * Takes a file out of the list, and catches the focus that was on its remove button.\n *\n * That button disappears with its row, so the focus would fall back to the page body.\n * It is moved instead to the row that takes its place, or to the browse control once\n * the list is empty. Waiting for the next tick is what makes the new row findable: the\n * page still shows the old one at the moment the value is written.\n */\nasync function removeAt(index: number) {\n const file = model.value[index]\n if (!file || !interactive.value) return\n\n model.value = model.value.filter((_, i) => i !== index)\n resetNative()\n emit('remove', file, index)\n emit('change', model.value)\n\n await nextTick()\n const items = listEl.value?.querySelectorAll<HTMLElement>('.v-file-picker-item') ?? []\n const next = items[Math.min(index, items.length - 1)]?.querySelector('button')\n ;(next ?? focusTarget())?.focus()\n}\n\n/**\n * One temporary address per image, kept against THE FILE OBJECT ITSELF.\n *\n * Using the file as the key is safe, and that is worth knowing: Vue's reactivity only\n * wraps plain objects, arrays and collections, so a File travelling through the value\n * comes back with its identity intact — the exact opposite of VCombobox's option cache,\n * where comparing identities IS the bug. Keying by name would be wrong here: two files\n * picked from different folders can share one.\n *\n * The map is made reactive rather than held in a plain reference, which is what lets a\n * single row re-render when its address is ready, instead of replacing the whole map.\n *\n * TRAP — it is called `thumbUrls` and NOT `thumbnails`. Every top-level binding of a\n * `<script setup>` is exposed to the template, where it would SHADOW the prop of the\n * same name — the same trap VHotkeys' `listening` flag avoids.\n */\nconst thumbUrls = reactive(new Map<File, string>())\n\n/**\n * Whether a thumbnail can be drawn at all, decided on the type the BROWSER reports and\n * not on the kind derived from the extension. A `.heic` file counts as an image and\n * deserves the image icon, but no engine will decode it.\n */\nconst isThumbable = (file: File) => file.type.startsWith('image/')\n\n// @ssr @core\n/**\n * Brings the map into line with the list: releases the addresses of files that have\n * gone, and creates them for files that have arrived.\n *\n * TRAP — it is never called from setup, from a derived value or during rendering, only\n * once mounted, from a watcher and from handlers. That is what keeps the component\n * renderable on a server: the server draws the kind icon, and so does the browser's\n * first render, the map being empty until then — the same reasoning as today's date in\n * VDatePicker.\n */\nfunction syncThumbnails() {\n // With no list rendered there is nothing to draw a thumbnail in, so no address is\n // created at all. This gate — and not a warning — is what makes the default\n // configuration cost strictly nothing.\n const wanted = new Set(\n props.thumbnails && props.preview !== false ? model.value.filter(isThumbable) : [],\n )\n\n for (const [file, url] of thumbUrls) {\n if (wanted.has(file)) continue\n URL.revokeObjectURL(url)\n thumbUrls.delete(file)\n }\n for (const file of wanted) {\n if (!thumbUrls.has(file)) thumbUrls.set(file, URL.createObjectURL(file))\n }\n}\n\n// @fallback\n/**\n * The image failed to decode — a format the browser does not read, a corrupt file, a\n * type that lied about itself. The address is released and the kind icon takes over: a\n * failure to draw must never leave an empty square in the list.\n */\nfunction dropThumbnail(file: File) {\n const url = thumbUrls.get(file)\n if (!url) return\n URL.revokeObjectURL(url)\n thumbUrls.delete(file)\n}\n\n// @ssr — the addresses are created in the browser only; the server and the browser's\n// first render both show the kind icon, so the two markups agree.\nonMounted(syncThumbnails)\n/*\n * Watching deeply costs nothing here and covers a consumer who ADDS to the list rather\n * than replacing it: the walk stops at a File, which is neither a plain object nor a\n * collection, so it never descends past the array itself.\n */\nwatch([model, () => props.thumbnails, () => props.preview], syncThumbnails, { deep: true })\n// Released BEFORE the component is torn down and never after — the same rule `useTimer`\n// and VHotkeys follow.\nonBeforeUnmount(() => {\n for (const url of thumbUrls.values()) URL.revokeObjectURL(url)\n thumbUrls.clear()\n})\n\n/**\n * Everything one row of the list needs, assembled in one place. A Vue template has no\n * way of declaring a reusable fragment, so this is what keeps the two slots that can\n * replace part of a row fed from a single source.\n */\nfunction rowProps(file: File, index: number): FilePickerRow {\n const kind = fileKind(file)\n return {\n file,\n index,\n kind,\n thumbnail: thumbUrls.get(file),\n icon: iconForKind(kind),\n sizeText: formatBytes(file.size, locale.value),\n remove: () => removeAt(index),\n }\n}\n\n// @devwarn — the last two are accessibility guards, and both describe things that fail\n// SILENTLY at runtime: a required control nobody can focus, and a name given to a plain\n// container, which assistive technology ignores.\nif (isDev) {\n watchEffect(() => {\n if (props.maxFiles !== undefined && !props.multiple)\n console.warn(\n '[VFilePicker] `maxFiles` ignored without `multiple`: single mode already caps at one file.',\n )\n if (attrs.required !== undefined)\n console.warn(\n '[VFilePicker] `required` lands on the hidden file input, which is not focusable: the browser blocks submission with no visible message. Validate the v-model yourself.',\n )\n if (\n props.showBrowse &&\n (attrs['aria-label'] !== undefined || attrs['aria-labelledby'] !== undefined)\n )\n console.warn(\n '[VFilePicker] an aria-label on the zone is inert while the browse button is shown: the zone is a plain container then, and axe reports aria-prohibited-attr. Name the zone through `title`, or set `showBrowse: false` to make the zone itself the control.',\n )\n })\n}\n\ndefineExpose({\n /** Moves the focus to the browse control — the button, or the zone when it is one. */\n focus: (options?: FocusOptions) => focusTarget()?.focus(options),\n /**\n * Opens the file dialog. It only works when called from something the reader did — a\n * click, a key press: browsers refuse to open a file dialog by themselves.\n */\n open: openPicker,\n})\n</script>\n\n<template>\n <div\n class=\"v-file-picker\"\n :class=\"rootClass\"\n :style=\"rootStyle\"\n :data-preview=\"preview || undefined\"\n :data-disabled=\"disabled ? '' : undefined\"\n :data-readonly=\"readonly ? '' : undefined\"\n :data-dragging=\"dragging ? '' : undefined\"\n @dragenter=\"onDragEnter\"\n @dragover=\"onDragOver\"\n @dragleave=\"onDragLeave\"\n @drop=\"onDrop\"\n >\n <input\n v-bind=\"nativeAttrs\"\n ref=\"fileEl\"\n type=\"file\"\n class=\"v-file-picker-native\"\n tabindex=\"-1\"\n aria-hidden=\"true\"\n :accept=\"accept\"\n :multiple=\"multiple || undefined\"\n :disabled=\"disabled || undefined\"\n @change=\"onNativeChange\"\n />\n\n <!-- TRAP — this wrapper is not decoration. The root is what the layout asks about\n its own width, and an element cannot ask about ITSELF: whatever flips has to be\n a descendant of it. Deleting this element makes the side-by-side layout\n silently stop folding, with no error anywhere. -->\n <div class=\"v-file-picker-body\">\n <!-- A real button as soon as the zone IS the control: the role, Enter, Space, the\n focus and the complete inertness of a disabled control then come from the\n platform. A plain container otherwise — a button inside a button is invalid\n markup, and unreachable by keyboard. -->\n <component\n :is=\"zoneIsControl ? 'button' : 'div'\"\n v-bind=\"zoneAttrs\"\n ref=\"zoneEl\"\n class=\"v-file-picker-zone\"\n :type=\"zoneIsControl ? 'button' : undefined\"\n :disabled=\"zoneIsControl && !interactive ? true : undefined\"\n @click=\"onZoneClick\"\n >\n <span class=\"v-file-picker-icon\">\n <slot name=\"icon\"><VIcon v-bind=\"iconProps(icon)\" /></slot>\n </span>\n\n <!-- Rendered as a span in BOTH shapes: a paragraph is not allowed inside a\n button, and the markup must not change form between the two — one shape\n means one set of CSS rules. -->\n <VTypography as=\"span\" variant=\"subtitle\" class=\"v-file-picker-title\">\n <slot name=\"title\">{{ title }}</slot>\n </VTypography>\n\n <VTypography\n v-if=\"subtitle || $slots.subtitle\"\n as=\"span\"\n variant=\"body-sm\"\n class=\"v-file-picker-subtitle\"\n >\n <slot name=\"subtitle\">{{ subtitle }}</slot>\n </VTypography>\n\n <template v-if=\"showBrowse\">\n <!-- Deliberately not hidden from screen readers: \"or\" is real text, and it\n reads naturally between the instruction and the button. The two rules on\n either side of it are pseudo-elements, and therefore decorative by\n construction. -->\n <span class=\"v-file-picker-separator\">{{ m.filePicker.or }}</span>\n\n <slot name=\"browse\" :open=\"openPicker\" :disabled=\"!interactive\">\n <VButton\n class=\"v-file-picker-browse\"\n variant=\"outline\"\n tone=\"neutral\"\n :disabled=\"!interactive\"\n @click=\"openPicker\"\n >\n {{ browseLabel ?? m.filePicker.browse }}\n </VButton>\n </slot>\n </template>\n </component>\n\n <ul v-if=\"showList\" ref=\"listEl\" class=\"v-file-picker-list\" :aria-label=\"m.filePicker.list\">\n <li\n v-for=\"(file, index) in model\"\n :key=\"`${index}-${file.name}`\"\n class=\"v-file-picker-item\"\n >\n <slot name=\"item\" v-bind=\"rowProps(file, index)\">\n <span class=\"v-file-picker-thumb\">\n <slot name=\"thumbnail\" v-bind=\"rowProps(file, index)\">\n <img\n v-if=\"thumbUrls.get(file)\"\n class=\"v-file-picker-image\"\n :src=\"thumbUrls.get(file)\"\n alt=\"\"\n loading=\"lazy\"\n decoding=\"async\"\n @error=\"dropThumbnail(file)\"\n />\n <VIcon v-else v-bind=\"iconProps(iconForKind(fileKind(file)))\" />\n </slot>\n </span>\n\n <span class=\"v-file-picker-info\">\n <span class=\"v-file-picker-name\" :title=\"file.name\">{{ file.name }}</span>\n <span class=\"v-file-picker-size\">{{ formatBytes(file.size, locale) }}</span>\n </span>\n\n <slot\n name=\"remove\"\n :file=\"file\"\n :index=\"index\"\n :remove=\"() => removeAt(index)\"\n :label=\"m.filePicker.remove(file.name)\"\n >\n <VIconButton\n class=\"v-file-picker-remove\"\n size=\"sm\"\n :icon=\"removeIcon\"\n :label=\"m.filePicker.remove(file.name)\"\n :disabled=\"!interactive\"\n @click=\"removeAt(index)\"\n />\n </slot>\n </slot>\n </li>\n </ul>\n </div>\n </div>\n</template>\n\n<style>\n@layer vectis.components {\n /* These variables carry the component's name for a reason: they INHERIT, so a bare\n `--bg` or `--border-color` set by the host application on any ancestor would be\n picked up here instead — and nothing would catch it, since the unit tests evaluate\n no styles at all.\n\n They are declared on the ROOT so that the drag, disabled and read-only states each\n redefine them in ONE place, which is what makes those states structurally incapable\n of disagreeing with hover or focus. */\n .v-file-picker {\n --file-picker-border-color: var(--vectis-color-border-strong);\n --file-picker-bg: var(--vectis-color-surface-sunken);\n --file-picker-text: var(--vectis-color-text);\n --file-picker-text-muted: var(--vectis-color-text-muted);\n --file-picker-row-bg: var(--vectis-color-surface-raised);\n --file-picker-thumb-bg: var(--vectis-color-surface-muted);\n\n /* Positioned so the hidden file input, which has no size at all, has something to be\n placed against. */\n position: relative;\n display: block;\n inline-size: 100%;\n font-family: var(--vectis-text-family);\n }\n\n /* The real file input is a SOURCE of files and not a control anyone deals with. It is\n hidden with `opacity` and never with `display: none`, the design system's rule for a\n hidden form control, which has to stay submittable; it is given no size and made\n deaf to the pointer, so it can never swallow a click meant for the zone. */\n .v-file-picker-native {\n position: absolute;\n inline-size: 0;\n block-size: 0;\n opacity: 0;\n pointer-events: none;\n }\n\n .v-file-picker-body {\n display: flex;\n flex-direction: column;\n gap: var(--vectis-space-4);\n }\n\n /* One set of rules serves both shapes the zone can take. All that has to be undone is\n what the browser gives a button — its own appearance, font and margin — since\n everything else is declared here regardless. The full width is part of that: a\n button shrinks to fit its content, where a container does not. */\n .v-file-picker-zone {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: var(--vectis-space-2);\n inline-size: 100%;\n min-block-size: var(--vectis-control-size-file-picker-min-block);\n margin: 0;\n padding: var(--vectis-space-6) var(--vectis-space-4);\n appearance: none;\n border: 1px dashed var(--file-picker-border-color);\n border-radius: var(--vectis-radius-surface);\n background: var(--file-picker-bg);\n color: var(--file-picker-text);\n font: inherit;\n text-align: center;\n transition:\n border-color var(--vectis-duration-fast) var(--vectis-ease-default),\n background-color var(--vectis-duration-fast) var(--vectis-ease-default);\n }\n\n .v-file-picker:not([data-disabled]):not([data-readonly]) .v-file-picker-zone {\n cursor: pointer;\n }\n\n .v-file-picker:not([data-disabled]):not([data-readonly]) .v-file-picker-zone:hover {\n --file-picker-border-color: var(--vectis-color-accent);\n }\n\n .v-file-picker-zone:focus-visible {\n outline: var(--vectis-focus-ring-width) solid var(--vectis-focus-ring-color);\n outline-offset: var(--vectis-focus-ring-offset);\n }\n\n /* While a file is being dragged over it, the zone is highlighted by redefining the\n very variables it paints itself with — so the highlight cannot disagree with the\n hover and focus states. */\n .v-file-picker[data-dragging] {\n --file-picker-border-color: var(--vectis-color-accent);\n --file-picker-bg: var(--vectis-color-accent-surface);\n }\n\n /* The large icon's size is set HERE, on its own wrapper, and never on the zone: set\n there it would inherit down and enlarge the browse button's icons as well. */\n .v-file-picker-icon {\n --vectis-icon-size: var(--vectis-control-size-file-picker-icon);\n\n display: inline-flex;\n color: var(--file-picker-text-muted);\n }\n\n .v-file-picker-subtitle {\n /* Set through VTypography's own colour variable rather than with a plain colour:\n there is then a single source, and the disabled state below overrides that same\n one instead of introducing a second. */\n --typography-color: var(--file-picker-text-muted);\n }\n\n /* The word set between two rules, entirely in CSS: the two lines are pseudo-elements\n sharing the row with the text between them. No extra element is added to the markup,\n and nothing decorative reaches the accessibility tree. */\n .v-file-picker-separator {\n display: flex;\n align-items: center;\n gap: var(--vectis-space-3);\n inline-size: 100%;\n margin-block-start: var(--vectis-space-2);\n color: var(--file-picker-text-muted);\n font-size: var(--vectis-text-caption-size);\n }\n\n .v-file-picker-separator::before,\n .v-file-picker-separator::after {\n content: '';\n flex: 1 1 0;\n border-block-start: 1px solid var(--vectis-color-border);\n }\n\n .v-file-picker-list {\n display: flex;\n flex-direction: column;\n gap: var(--vectis-space-2);\n margin: 0;\n padding: 0;\n list-style: none;\n }\n\n .v-file-picker-item {\n display: flex;\n align-items: center;\n gap: var(--vectis-space-3);\n padding: var(--vectis-space-2);\n border: 1px solid var(--vectis-color-border);\n border-radius: var(--vectis-radius-interactive);\n background: var(--file-picker-row-bg);\n }\n\n .v-file-picker-thumb {\n display: inline-flex;\n flex: none;\n align-items: center;\n justify-content: center;\n inline-size: var(--vectis-control-size-file-picker-thumb);\n block-size: var(--vectis-control-size-file-picker-thumb);\n overflow: hidden;\n border-radius: var(--vectis-radius-interactive);\n background: var(--file-picker-thumb-bg);\n color: var(--file-picker-text-muted);\n }\n\n .v-file-picker-image {\n display: block;\n inline-size: 100%;\n block-size: 100%;\n object-fit: cover;\n }\n\n /* The zero minimum is what makes the ellipsis below possible at all: a flex item\n refuses by default to shrink below its own content, so without it a long file name\n would widen the row instead of being cut short. */\n .v-file-picker-info {\n display: flex;\n flex: 1 1 auto;\n flex-direction: column;\n min-inline-size: 0;\n color: var(--file-picker-text);\n }\n\n .v-file-picker-name {\n overflow: hidden;\n font-size: var(--vectis-text-body-sm-size);\n white-space: nowrap;\n text-overflow: ellipsis;\n }\n\n /* Figures of equal width, so the sizes line up down the column instead of wobbling.\n That is not a typographic role, so it stays a local rule — the same reasoning as\n VFileInput's counter. */\n .v-file-picker-size {\n color: var(--file-picker-text-muted);\n font-size: var(--vectis-text-caption-size);\n font-variant-numeric: tabular-nums;\n }\n\n /*\n * Making the component a query container is reserved for the side-by-side layout,\n * since only its rule below depends on it — and it is not free.\n *\n * A container of this kind computes its width WITHOUT looking at its content, so the\n * component would lose its natural width inside an automatically sized grid column or\n * an inline box. In the two other layouts it keeps it.\n */\n .v-file-picker[data-preview='end'] {\n container-type: inline-size;\n container-name: v-file-picker;\n }\n\n .v-file-picker[data-preview='end'] .v-file-picker-body {\n flex-direction: row;\n align-items: flex-start;\n }\n\n .v-file-picker[data-preview='end'] .v-file-picker-zone,\n .v-file-picker[data-preview='end'] .v-file-picker-list {\n flex: 1 1 0;\n min-inline-size: 0;\n }\n\n /*\n * The threshold is written as a literal length, a container query accepting no\n * variables. It is the width NEEDED to hold the two columns side by side, and not what\n * is left once they fold: the zone stops being readable below about 18rem — its\n * instruction wraps onto two lines and the button follows — a row needs about 15rem to\n * show a thumbnail, a name worth reading and its remove button, and there is a gutter\n * between them.\n */\n @container v-file-picker (max-width: 34rem) {\n .v-file-picker[data-preview='end'] .v-file-picker-body {\n flex-direction: column;\n }\n }\n\n /* A disabled zone greys out through the colour tokens and never through opacity.\n\n The pairing used is the design system's own for a disabled surface, exactly as\n VInput sets it: a lighter text would look more convincingly disabled, and would fall\n below the required contrast against that background — which the accessibility checks\n refuse.\n\n Both text variables take the SAME value here, so that the secondary line does not\n sink below the title on a surface that is already dimmed. */\n .v-file-picker[data-disabled] {\n --file-picker-border-color: var(--vectis-color-border);\n --file-picker-bg: var(--vectis-color-surface-muted);\n --file-picker-text: var(--vectis-color-text-muted);\n --file-picker-text-muted: var(--vectis-color-text-muted);\n --file-picker-row-bg: var(--vectis-color-surface-muted);\n }\n\n .v-file-picker[data-readonly] {\n --file-picker-border-color: var(--vectis-color-border);\n }\n\n @media (prefers-reduced-motion: reduce) {\n .v-file-picker-zone {\n transition: none;\n }\n }\n\n /*\n * Under Windows forced colours the backgrounds are dropped and every border colour is\n * replaced, so the drag highlight — which is nothing but colour — would disappear\n * entirely. A change of border STYLE survives that: the dashed outline becomes solid\n * for as long as a file hovers over the zone.\n */\n @media (forced-colors: active) {\n .v-file-picker[data-dragging] .v-file-picker-zone {\n border-style: solid;\n }\n\n .v-file-picker-thumb {\n border: 1px solid;\n }\n }\n}\n</style>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA4KA,IAAM,IAAQ,GAkBR,IAAO,GA2DP,IAAQ,EAAmB,GAAA,YAAsB,GAEjD,EAAE,WAAO,eAAW,eAAW,uBAAmB,GAAa,GAE/D,IAAI,EAAY,GAChB,IAAS,EAAU,GAEnB,IAAc,QAAe,CAAC,EAAM,YAAY,CAAC,EAAM,QAAQ,GAW/D,EACJ,YACA,iBACA,cAAc,IACd,iBACA,mBACA,eACA,oBACE,GAAa;GACf;GACA;GACA,eAAe,EAAY;GAC3B,gBAAgB,EAAM;GACtB,eAAe;IACb,QAAQ,EAAM;IACd,SAAS,EAAM;IACf,UAAU,EAAM;IAChB,cAAc,EAAM;GACtB;GACA,WAAW,MAAc,EAAK,UAAU,CAAS;GACjD,WAAW,MAAU,EAAK,UAAU,CAAK;EAC3C,CAAC,GAEK,IAAS,EAAwB,IAAI,GACrC,IAAS,EAA6B,IAAI,GAE1C,IAAgB,QAAe,CAAC,EAAM,UAAU,GAChD,KAAW,QAAe,EAAM,YAAY,MAAS,EAAM,MAAM,SAAS,CAAC,GAM3E,KAA2C;GACxC;GACP,KAAK;GACL,OAAO;GACP,OAAO;GACP,SAAS;GACT,aAAa;GACP;GACN,MAAM;EACR,GAEM,KAAe,MAA+B,EAAM,YAAY,MAAS,GAAW;EAE1F,SAAS,GAAY,GAAmB;GAIlC,CAAC,EAAc,SAAU,EAAM,OAAuB,QAAQ,QAAQ,KAC1E,EAAW;EACb;EAEA,IAAM,EAAE,cAAU,gBAAa,eAAY,gBAAa,cAAW,SAC3D,EAAY,OAClB,EACF;EAWA,SAAS,IAAkC;GACzC,IAAM,IAAO,EAAO;GAEpB,OADK,IACE,EAAK,QAAQ,QAAQ,IAAI,IAAO,EAAK,cAAc,QAAQ,IADhD;EAEpB;EAWA,eAAe,EAAS,GAAe;GACrC,IAAM,IAAO,EAAM,MAAM;GACzB,IAAI,CAAC,KAAQ,CAAC,EAAY,OAAO;GAOjC,AALA,EAAM,QAAQ,EAAM,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAK,GACtD,GAAY,GACZ,EAAK,UAAU,GAAM,CAAK,GAC1B,EAAK,UAAU,EAAM,KAAK,GAE1B,MAAM,GAAS;GACf,IAAM,IAAQ,EAAO,OAAO,iBAA8B,qBAAqB,KAAK,CAAC;GAEpF,CADY,EAAM,KAAK,IAAI,GAAO,EAAM,SAAS,CAAC,EAAE,EAAE,cAAc,QAAQ,KACnE,EAAY,EAAA,EAAI,MAAM;EAClC;EAkBA,IAAM,IAAY,mBAAS,IAAI,IAAkB,CAAC,GAO5C,MAAe,MAAe,EAAK,KAAK,WAAW,QAAQ;EAajE,SAAS,IAAiB;GAIxB,IAAM,IAAS,IAAI,IACjB,EAAM,cAAc,EAAM,YAAY,KAAQ,EAAM,MAAM,OAAO,EAAW,IAAI,CAAC,CACnF;GAEA,KAAK,IAAM,CAAC,GAAM,MAAQ,GACpB,EAAO,IAAI,CAAI,MACnB,IAAI,gBAAgB,CAAG,GACvB,EAAU,OAAO,CAAI;GAEvB,KAAK,IAAM,KAAQ,GACjB,AAAK,EAAU,IAAI,CAAI,KAAG,EAAU,IAAI,GAAM,IAAI,gBAAgB,CAAI,CAAC;EAE3E;EAQA,SAAS,GAAc,GAAY;GACjC,IAAM,IAAM,EAAU,IAAI,CAAI;GACzB,MACL,IAAI,gBAAgB,CAAG,GACvB,EAAU,OAAO,CAAI;EACvB;EAaA,AATA,GAAU,CAAc,GAMxB,EAAM;GAAC;SAAa,EAAM;SAAkB,EAAM;EAAO,GAAG,GAAgB,EAAE,MAAM,GAAK,CAAC,GAG1F,SAAsB;GACpB,KAAK,IAAM,KAAO,EAAU,OAAO,GAAG,IAAI,gBAAgB,CAAG;GAC7D,EAAU,MAAM;EAClB,CAAC;EAOD,SAAS,EAAS,GAAY,GAA8B;GAC1D,IAAM,IAAO,EAAS,CAAI;GAC1B,OAAO;IACL;IACA;IACA;IACA,WAAW,EAAU,IAAI,CAAI;IAC7B,MAAM,EAAY,CAAI;IACtB,UAAU,EAAY,EAAK,MAAM,EAAO,KAAK;IAC7C,cAAc,EAAS,CAAK;GAC9B;EACF;SAyBA,EAAa;GAEX,QAAQ,MAA2B,EAAY,CAAC,EAAE,MAAM,CAAO;GAK/D,MAAM;EACR,CAAC,mBAIC,EAoIM,OAAA;GAnIJ,OAAK,GAAA,CAAC,iBACE,EAAA,EAAA,CAAS,CAAA;GAChB,OAAK,GAAE,EAAA,EAAA,CAAS;GAChB,gBAAc,EAAA,WAAW,KAAA;GACzB,iBAAe,EAAA,WAAQ,KAAQ,KAAA;GAC/B,iBAAe,EAAA,WAAQ,KAAQ,KAAA;GAC/B,iBAAe,EAAA,EAAA,IAAQ,KAAQ,KAAA;GAC/B,aAAS,AAAA,EAAA,QAAA,GAAA,MAAE,EAAA,CAAA,KAAA,EAAA,CAAA,CAAA,CAAA,GAAA,CAAA;GACX,YAAQ,AAAA,EAAA,QAAA,GAAA,MAAE,EAAA,CAAA,KAAA,EAAA,CAAA,CAAA,CAAA,GAAA,CAAA;GACV,aAAS,AAAA,EAAA,QAAA,GAAA,MAAE,EAAA,CAAA,KAAA,EAAA,CAAA,CAAA,CAAA,GAAA,CAAA;GACX,QAAI,AAAA,EAAA,QAAA,GAAA,MAAE,EAAA,CAAA,KAAA,EAAA,CAAA,CAAA,CAAA,GAAA,CAAA;MAEP,EAWE,SAXF,EACU,EAUR,EAAA,GAVmB;YACf;GAAJ,KAAI;GACJ,MAAK;GACL,OAAM;GACN,UAAS;GACT,eAAY;GACX,QAAQ,EAAA;GACR,UAAU,EAAA,YAAY,KAAA;GACtB,UAAU,EAAA,YAAY,KAAA;GACtB,UAAM,AAAA,EAAA,QAAA,GAAA,MAAE,EAAA,CAAA,KAAA,EAAA,CAAA,CAAA,CAAA,GAAA,CAAA;oBAOX,EAqGM,OArGN,GAqGM,EAAA,EAAA,GAhGJ,EAgDY,GA/CL,EAAA,QAAa,WAAA,KAAA,GADpB,EAEU,EA8CE,EAAA,GA9CO;YACb;GAAJ,KAAI;GACJ,OAAM;GACL,MAAM,EAAA,QAAa,WAAc,KAAA;GACjC,UAAU,EAAA,SAAa,CAAK,EAAA,QAAW,KAAU,KAAA;GACjD,SAAO;;oBAID;IAFP,EAEO,QAFP,GAEO,CADL,EAA2D,EAAA,QAAA,QAAA,CAAA,SAAA,CAAzC,EAAkC,GAAA,GAAA,GAAnB,EAAA,CAAA,CAAS,CAAC,EAAA,IAAI,CAAA,CAAA,GAAA,MAAA,EAAA,CAAA,CAAA,CAAA,CAAA;IAMjD,EAEc,GAAA;KAFD,IAAG;KAAO,SAAQ;KAAW,OAAM;;sBACT,CAArC,EAAqC,EAAA,QAAA,SAAA,CAAA,SAAA,CAAA,EAAA,EAAf,EAAA,KAAK,GAAA,CAAA,CAAA,CAAA,CAAA,CAAA;;;IAIrB,EAAA,YAAYA,EAAAA,OAAO,YAAA,EAAA,GAD3B,EAOc,GAAA;;KALZ,IAAG;KACH,SAAQ;KACR,OAAM;;sBAEqC,CAA3C,EAA2C,EAAA,QAAA,YAAA,CAAA,SAAA,CAAA,EAAA,EAAlB,EAAA,QAAQ,GAAA,CAAA,CAAA,CAAA,CAAA,CAAA;;;IAGnB,EAAA,cAAA,EAAA,GAAhB,EAkBW,GAAA,EAAA,KAAA,EAAA,GAAA,CAbT,EAAkE,QAAlE,IAAkE,EAAzB,EAAA,CAAA,CAAC,CAAC,WAAW,EAAE,GAAA,CAAA,GAExD,EAUO,EAAA,QAAA,UAAA;KAVc,MAAM,EAAA,CAAA;KAAa,UAAQ,CAAG,EAAA;aAU5C,CATL,EAQU,IAAA;KAPR,OAAM;KACN,SAAQ;KACR,MAAK;KACJ,UAAQ,CAAG,EAAA;KACX,SAAO,EAAA,CAAA;;sBAEgC,CAAA,EAAA,EAArC,EAAA,eAAe,EAAA,CAAA,CAAC,CAAC,WAAW,MAAM,GAAA,CAAA,CAAA,CAAA;;;;;iCAMnC,GAAA,SAAA,EAAA,GAAV,EA6CK,MAAA;;YA7CmB;GAAJ,KAAI;GAAS,OAAM;GAAsB,cAAY,EAAA,CAAA,CAAC,CAAC,WAAW;cACpF,EA2CK,GAAA,MAAA,GA1CqB,EAAA,QAAhB,GAAM,YADhB,EA2CK,MAAA;GAzCF,KAAG,GAAK,EAAK,GAAI,EAAK;GACvB,OAAM;MAEN,EAqCO,EAAA,QAAA,QArCP,EAqCO,EAAA,SAAA,GAAA,GArCmB,EAAS,GAAM,CAAK,CAAA,SAqCvC;GApCL,EAaO,QAbP,IAaO,CAZL,EAWO,EAAA,QAAA,aAXP,EAWO,EAAA,SAAA,GAAA,GAXwB,EAAS,GAAM,CAAK,CAAA,SAW5C,CATG,EAAU,IAAI,CAAI,KAAA,EAAA,GAD1B,EAQE,OAAA;;IANA,OAAM;IACL,KAAK,EAAU,IAAI,CAAI;IACxB,KAAI;IACJ,SAAQ;IACR,UAAS;IACR,UAAK,MAAE,GAAc,CAAI;6BAE5B,EAAgE,GAAhE,EAAgE;;;MAA1C,EAAA,CAAA,CAAS,CAAC,EAAY,EAAA,CAAA,CAAQ,CAAC,CAAI,CAAA,CAAA,CAAA,GAAA,MAAA,EAAA,EAAA,CAAA,CAAA,CAAA;GAI7D,EAGO,QAHP,IAGO,CAFL,EAA0E,QAAA;IAApE,OAAM;IAAsB,OAAO,EAAK;QAAS,EAAK,IAAI,GAAA,GAAA,CAAA,GAChE,EAA4E,QAA5E,IAA4E,EAAxC,EAAA,CAAA,CAAW,CAAC,EAAK,MAAM,EAAA,CAAA,CAAM,CAAA,GAAA,CAAA,CAAA,CAAA;GAGnE,EAeO,EAAA,QAAA,UAAA;IAbE;IACC;IACP,cAAc,EAAS,CAAK;IAC5B,OAAO,EAAA,CAAA,CAAC,CAAC,WAAW,OAAO,EAAK,IAAI;YAUhC,CARL,EAOE,IAAA;IANA,OAAM;IACN,MAAK;IACJ,MAAM,EAAA;IACN,OAAO,EAAA,CAAA,CAAC,CAAC,WAAW,OAAO,EAAK,IAAI;IACpC,UAAQ,CAAG,EAAA;IACX,UAAK,MAAE,EAAS,CAAK"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What KIND of thing a file is, for the sole purpose of choosing an icon. It is
|
|
3
|
+
* deliberately coarse: the question is which of eight pictures to show, not how to
|
|
4
|
+
* classify every type in existence.
|
|
5
|
+
*
|
|
6
|
+
* The answer comes from the type the browser reports FIRST, and from the extension
|
|
7
|
+
* afterwards. That order is the contract: the reported type is authoritative when there
|
|
8
|
+
* IS one, but it is empty far more often than one expects — an extension the operating
|
|
9
|
+
* system does not know, certain Linux setups — which is why the extension has to be
|
|
10
|
+
* there as a fallback rather than as a first resort.
|
|
11
|
+
*
|
|
12
|
+
* The module is pure and knows nothing of Vue. It lives in the component's folder for
|
|
13
|
+
* the usual reason: a single consumer, so it does not qualify as shared code — promote
|
|
14
|
+
* it the day a second one appears.
|
|
15
|
+
*
|
|
16
|
+
* What is NOT here is which icon each kind takes. That belongs to VFilePicker, which
|
|
17
|
+
* exposes it as a prop a consumer can override.
|
|
18
|
+
*/
|
|
19
|
+
export type FileKind = 'image' | 'pdf' | 'audio' | 'video' | 'archive' | 'spreadsheet' | 'code' | 'file';
|
|
20
|
+
/**
|
|
21
|
+
* The only two things this module needs of a file. Taking that rather than a File is
|
|
22
|
+
* what lets the tests describe a case in two lines instead of forging one.
|
|
23
|
+
*/
|
|
24
|
+
export interface FileKindCandidate {
|
|
25
|
+
name: string;
|
|
26
|
+
type: string;
|
|
27
|
+
}
|
|
28
|
+
/** Works out which kind a file belongs to. */
|
|
29
|
+
export declare function fileKind(file: FileKindCandidate): FileKind;
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
//#region src/components/VFilePicker/fileKind.ts
|
|
2
|
+
var e = {
|
|
3
|
+
"application/pdf": "pdf",
|
|
4
|
+
"application/zip": "archive",
|
|
5
|
+
"application/x-zip-compressed": "archive",
|
|
6
|
+
"application/vnd.rar": "archive",
|
|
7
|
+
"application/x-7z-compressed": "archive",
|
|
8
|
+
"application/x-tar": "archive",
|
|
9
|
+
"application/gzip": "archive",
|
|
10
|
+
"text/csv": "spreadsheet",
|
|
11
|
+
"application/vnd.ms-excel": "spreadsheet",
|
|
12
|
+
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": "spreadsheet",
|
|
13
|
+
"application/vnd.oasis.opendocument.spreadsheet": "spreadsheet",
|
|
14
|
+
"application/json": "code",
|
|
15
|
+
"application/xml": "code",
|
|
16
|
+
"text/xml": "code",
|
|
17
|
+
"text/html": "code",
|
|
18
|
+
"text/css": "code",
|
|
19
|
+
"text/javascript": "code",
|
|
20
|
+
"application/javascript": "code"
|
|
21
|
+
}, t = {
|
|
22
|
+
avif: "image",
|
|
23
|
+
bmp: "image",
|
|
24
|
+
gif: "image",
|
|
25
|
+
heic: "image",
|
|
26
|
+
heif: "image",
|
|
27
|
+
ico: "image",
|
|
28
|
+
jpeg: "image",
|
|
29
|
+
jpg: "image",
|
|
30
|
+
png: "image",
|
|
31
|
+
svg: "image",
|
|
32
|
+
tif: "image",
|
|
33
|
+
tiff: "image",
|
|
34
|
+
webp: "image",
|
|
35
|
+
pdf: "pdf",
|
|
36
|
+
aac: "audio",
|
|
37
|
+
flac: "audio",
|
|
38
|
+
m4a: "audio",
|
|
39
|
+
mp3: "audio",
|
|
40
|
+
ogg: "audio",
|
|
41
|
+
wav: "audio",
|
|
42
|
+
avi: "video",
|
|
43
|
+
mkv: "video",
|
|
44
|
+
mov: "video",
|
|
45
|
+
mp4: "video",
|
|
46
|
+
webm: "video",
|
|
47
|
+
"7z": "archive",
|
|
48
|
+
bz2: "archive",
|
|
49
|
+
gz: "archive",
|
|
50
|
+
iso: "archive",
|
|
51
|
+
rar: "archive",
|
|
52
|
+
tar: "archive",
|
|
53
|
+
xz: "archive",
|
|
54
|
+
zip: "archive",
|
|
55
|
+
csv: "spreadsheet",
|
|
56
|
+
ods: "spreadsheet",
|
|
57
|
+
tsv: "spreadsheet",
|
|
58
|
+
xls: "spreadsheet",
|
|
59
|
+
xlsx: "spreadsheet",
|
|
60
|
+
css: "code",
|
|
61
|
+
go: "code",
|
|
62
|
+
html: "code",
|
|
63
|
+
java: "code",
|
|
64
|
+
js: "code",
|
|
65
|
+
json: "code",
|
|
66
|
+
jsx: "code",
|
|
67
|
+
py: "code",
|
|
68
|
+
rb: "code",
|
|
69
|
+
rs: "code",
|
|
70
|
+
scss: "code",
|
|
71
|
+
sh: "code",
|
|
72
|
+
ts: "code",
|
|
73
|
+
tsx: "code",
|
|
74
|
+
xml: "code",
|
|
75
|
+
yaml: "code",
|
|
76
|
+
yml: "code"
|
|
77
|
+
};
|
|
78
|
+
function n(n) {
|
|
79
|
+
let r = n.type.toLowerCase();
|
|
80
|
+
if (r.startsWith("image/")) return "image";
|
|
81
|
+
if (r.startsWith("audio/")) return "audio";
|
|
82
|
+
if (r.startsWith("video/")) return "video";
|
|
83
|
+
let i = e[r];
|
|
84
|
+
if (i) return i;
|
|
85
|
+
let a = n.name.lastIndexOf(".");
|
|
86
|
+
return t[a > 0 ? n.name.slice(a + 1).toLowerCase() : ""] ?? "file";
|
|
87
|
+
}
|
|
88
|
+
//#endregion
|
|
89
|
+
export { n as fileKind };
|
|
90
|
+
|
|
91
|
+
//# sourceMappingURL=fileKind.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fileKind.js","names":[],"sources":["../../../src/components/VFilePicker/fileKind.ts"],"sourcesContent":["/**\n * What KIND of thing a file is, for the sole purpose of choosing an icon. It is\n * deliberately coarse: the question is which of eight pictures to show, not how to\n * classify every type in existence.\n *\n * The answer comes from the type the browser reports FIRST, and from the extension\n * afterwards. That order is the contract: the reported type is authoritative when there\n * IS one, but it is empty far more often than one expects — an extension the operating\n * system does not know, certain Linux setups — which is why the extension has to be\n * there as a fallback rather than as a first resort.\n *\n * The module is pure and knows nothing of Vue. It lives in the component's folder for\n * the usual reason: a single consumer, so it does not qualify as shared code — promote\n * it the day a second one appears.\n *\n * What is NOT here is which icon each kind takes. That belongs to VFilePicker, which\n * exposes it as a prop a consumer can override.\n */\n\nexport type FileKind =\n 'image' | 'pdf' | 'audio' | 'video' | 'archive' | 'spreadsheet' | 'code' | 'file'\n\n/**\n * The only two things this module needs of a file. Taking that rather than a File is\n * what lets the tests describe a case in two lines instead of forging one.\n */\nexport interface FileKindCandidate {\n name: string\n type: string\n}\n\nconst MIME_KINDS: Record<string, FileKind> = {\n 'application/pdf': 'pdf',\n 'application/zip': 'archive',\n 'application/x-zip-compressed': 'archive',\n 'application/vnd.rar': 'archive',\n 'application/x-7z-compressed': 'archive',\n 'application/x-tar': 'archive',\n 'application/gzip': 'archive',\n 'text/csv': 'spreadsheet',\n 'application/vnd.ms-excel': 'spreadsheet',\n 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': 'spreadsheet',\n 'application/vnd.oasis.opendocument.spreadsheet': 'spreadsheet',\n 'application/json': 'code',\n 'application/xml': 'code',\n 'text/xml': 'code',\n 'text/html': 'code',\n 'text/css': 'code',\n 'text/javascript': 'code',\n 'application/javascript': 'code',\n}\n\nconst EXTENSION_KINDS: Record<string, FileKind> = {\n avif: 'image',\n bmp: 'image',\n gif: 'image',\n heic: 'image',\n heif: 'image',\n ico: 'image',\n jpeg: 'image',\n jpg: 'image',\n png: 'image',\n svg: 'image',\n tif: 'image',\n tiff: 'image',\n webp: 'image',\n\n pdf: 'pdf',\n\n aac: 'audio',\n flac: 'audio',\n m4a: 'audio',\n mp3: 'audio',\n ogg: 'audio',\n wav: 'audio',\n\n avi: 'video',\n mkv: 'video',\n mov: 'video',\n mp4: 'video',\n webm: 'video',\n\n '7z': 'archive',\n bz2: 'archive',\n gz: 'archive',\n iso: 'archive',\n rar: 'archive',\n tar: 'archive',\n xz: 'archive',\n zip: 'archive',\n\n csv: 'spreadsheet',\n ods: 'spreadsheet',\n tsv: 'spreadsheet',\n xls: 'spreadsheet',\n xlsx: 'spreadsheet',\n\n css: 'code',\n go: 'code',\n html: 'code',\n java: 'code',\n js: 'code',\n json: 'code',\n jsx: 'code',\n py: 'code',\n rb: 'code',\n rs: 'code',\n scss: 'code',\n sh: 'code',\n ts: 'code',\n tsx: 'code',\n xml: 'code',\n yaml: 'code',\n yml: 'code',\n}\n\n/** Works out which kind a file belongs to. */\nexport function fileKind(file: FileKindCandidate): FileKind {\n const type = file.type.toLowerCase()\n\n // The whole families first: matching on the family covers every image, audio and\n // video format, including the ones no table will ever list.\n if (type.startsWith('image/')) return 'image'\n if (type.startsWith('audio/')) return 'audio'\n if (type.startsWith('video/')) return 'video'\n\n const byMime = MIME_KINDS[type]\n if (byMime) return byMime\n\n // TRAP — the dot must be found PAST the first character and not at it: a file named\n // `.gitignore` has no extension at all, it has a name beginning with a dot.\n const dot = file.name.lastIndexOf('.')\n const extension = dot > 0 ? file.name.slice(dot + 1).toLowerCase() : ''\n return EXTENSION_KINDS[extension] ?? 'file'\n}\n"],"mappings":";AA+BA,IAAM,IAAuC;CAC3C,mBAAmB;CACnB,mBAAmB;CACnB,gCAAgC;CAChC,uBAAuB;CACvB,+BAA+B;CAC/B,qBAAqB;CACrB,oBAAoB;CACpB,YAAY;CACZ,4BAA4B;CAC5B,qEAAqE;CACrE,kDAAkD;CAClD,oBAAoB;CACpB,mBAAmB;CACnB,YAAY;CACZ,aAAa;CACb,YAAY;CACZ,mBAAmB;CACnB,0BAA0B;AAC5B,GAEM,IAA4C;CAChD,MAAM;CACN,KAAK;CACL,KAAK;CACL,MAAM;CACN,MAAM;CACN,KAAK;CACL,MAAM;CACN,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,MAAM;CACN,MAAM;CAEN,KAAK;CAEL,KAAK;CACL,MAAM;CACN,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CAEL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,MAAM;CAEN,MAAM;CACN,KAAK;CACL,IAAI;CACJ,KAAK;CACL,KAAK;CACL,KAAK;CACL,IAAI;CACJ,KAAK;CAEL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,MAAM;CAEN,KAAK;CACL,IAAI;CACJ,MAAM;CACN,MAAM;CACN,IAAI;CACJ,MAAM;CACN,KAAK;CACL,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,MAAM;CACN,IAAI;CACJ,IAAI;CACJ,KAAK;CACL,KAAK;CACL,MAAM;CACN,KAAK;AACP;AAGA,SAAgB,EAAS,GAAmC;CAC1D,IAAM,IAAO,EAAK,KAAK,YAAY;CAInC,IAAI,EAAK,WAAW,QAAQ,GAAG,OAAO;CACtC,IAAI,EAAK,WAAW,QAAQ,GAAG,OAAO;CACtC,IAAI,EAAK,WAAW,QAAQ,GAAG,OAAO;CAEtC,IAAM,IAAS,EAAW;CAC1B,IAAI,GAAQ,OAAO;CAInB,IAAM,IAAM,EAAK,KAAK,YAAY,GAAG;CAErC,OAAO,EADW,IAAM,IAAI,EAAK,KAAK,MAAM,IAAM,CAAC,CAAC,CAAC,YAAY,IAAI,OAChC;AACvC"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
@layer vectis.reset, vectis.tokens, vectis.components, vectis.utilities;
|
|
2
|
+
@layer vectis.components{.v-hotkeys{vertical-align:middle;font-family:var(--vectis-text-family);font-size:var(--control-font-size);--hotkeys-pad:var(--control-padding-inline);justify-content:center;align-items:center;display:inline-flex}.v-hotkeys-keys{align-items:center;gap:var(--control-gap);color:var(--vectis-color-text);display:inline-flex}.v-hotkeys-key{font-family:inherit;font-size:inherit;font-weight:var(--vectis-text-control-weight);line-height:var(--vectis-text-control-leading);justify-content:center;align-items:center;display:inline-flex}.v-hotkeys[data-variant=flat]{--hotkeys-bg:var(--vectis-color-surface-muted);--hotkeys-border:transparent;--hotkeys-shadow:none}.v-hotkeys[data-variant=outlined]{--hotkeys-bg:transparent;--hotkeys-border:var(--vectis-color-border-strong);--hotkeys-shadow:none}.v-hotkeys[data-variant=elevated]{--hotkeys-bg:var(--vectis-color-surface-raised);--hotkeys-border:transparent;--hotkeys-shadow:var(--vectis-shadow-sm)}.v-hotkeys[data-attached]{--hotkeys-pad:var(--control-gap)}.v-hotkeys[data-attached],.v-hotkeys:not([data-attached]) .v-hotkeys-key{height:var(--control-height);min-inline-size:var(--control-height);padding-inline:var(--hotkeys-pad);border:1px solid var(--hotkeys-border);border-radius:var(--vectis-radius-interactive);background:var(--hotkeys-bg);box-shadow:var(--hotkeys-shadow)}.v-hotkeys-separator{color:color-mix(in oklab, currentcolor, transparent 40%)}}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { HotkeysPlatform } from './platform.js';
|
|
2
|
+
/**
|
|
3
|
+
* A keyboard shortcut, shown as the keys one presses. It is written as a plain string
|
|
4
|
+
* — `mod+k` — and rendered with the symbols of the system the reader is actually on:
|
|
5
|
+
* ⌘K on a Mac, Ctrl+K on Windows and Linux.
|
|
6
|
+
*
|
|
7
|
+
* Two pieces of behaviour here are unique in the whole library, and both are worth
|
|
8
|
+
* knowing about.
|
|
9
|
+
*
|
|
10
|
+
* The first is reading which operating system this is, the only place the library asks
|
|
11
|
+
* that question. It happens once the component is mounted and nowhere else, because a
|
|
12
|
+
* server cannot know the answer and the browser's first render has to match what the
|
|
13
|
+
* server sent — the same reasoning as today's date in VDatePicker. A Mac visitor
|
|
14
|
+
* therefore sees "Ctrl" for a single frame; the `platform` prop is the way out for a
|
|
15
|
+
* host that already knows better.
|
|
16
|
+
*
|
|
17
|
+
* The second is `listen`, which attaches a key listener to the whole document — the
|
|
18
|
+
* only one in the library, and therefore something one has to ASK for: a component
|
|
19
|
+
* whose job is to display a shortcut must not silently capture the page's keyboard.
|
|
20
|
+
*
|
|
21
|
+
* The component is not interactive and cannot be focused, so it carries no hover, no
|
|
22
|
+
* active and no focus rule, and consequently no transition and no reduced-motion
|
|
23
|
+
* block. That absence is deliberate: do not copy VButton's state rules into it.
|
|
24
|
+
*/
|
|
25
|
+
export type HotkeysVariant = 'flat' | 'outlined' | 'elevated';
|
|
26
|
+
export type HotkeysSize = 'xs' | 'sm';
|
|
27
|
+
interface HotkeysProps {
|
|
28
|
+
/**
|
|
29
|
+
* The combination, `+`-separated: `mod+k`, `ctrl+shift+p`, `alt+enter`, `esc`.
|
|
30
|
+
* Case- and space-insensitive. `mod` is the CROSS-PLATFORM modifier — ⌘ on
|
|
31
|
+
* macOS, Ctrl everywhere else; `meta` is the literal Command/Windows/Super key.
|
|
32
|
+
* Aliases: cmd/command/win/super → meta, control → ctrl, option/opt → alt,
|
|
33
|
+
* return → enter, escape → esc, del → delete, arrowup… → up…. An unknown token
|
|
34
|
+
* is displayed as declared (`k` → K, `f5` → F5). The `+` key is `plus`.
|
|
35
|
+
*/
|
|
36
|
+
keys: string;
|
|
37
|
+
/** How a key cap is drawn: tinted, outlined, or raised off the page. */
|
|
38
|
+
variant?: HotkeysVariant;
|
|
39
|
+
/**
|
|
40
|
+
* Draws the whole combination as a SINGLE key rather than as several: the decoration
|
|
41
|
+
* moves from each cap to the shortcut as a whole, so the separator ends up inside
|
|
42
|
+
* the key instead of between two of them. It is purely visual — the markup and the
|
|
43
|
+
* announced name are identical either way.
|
|
44
|
+
*/
|
|
45
|
+
attached?: boolean;
|
|
46
|
+
/** The size of the caps. */
|
|
47
|
+
size?: HotkeysSize;
|
|
48
|
+
/** Takes 4px off the height, leaving the padding and the text as they are. */
|
|
49
|
+
compact?: boolean;
|
|
50
|
+
/**
|
|
51
|
+
* Forces the keyboard's OS instead of detecting it — for a deterministic
|
|
52
|
+
* rendering (stories, tests, a table showing all three) or a host that already
|
|
53
|
+
* knows (Electron, Tauri, a server reading the User-Agent).
|
|
54
|
+
*/
|
|
55
|
+
platform?: HotkeysPlatform;
|
|
56
|
+
/**
|
|
57
|
+
* What is written between two caps. An empty string gives the macOS convention,
|
|
58
|
+
* where the symbols simply follow one another: ⇧⌘K.
|
|
59
|
+
*/
|
|
60
|
+
separator?: string;
|
|
61
|
+
/**
|
|
62
|
+
* Actually listens for the combination and reports it. It is off by default: a
|
|
63
|
+
* component whose job is to display a shortcut must not capture the page's keyboard
|
|
64
|
+
* without being asked.
|
|
65
|
+
*/
|
|
66
|
+
listen?: boolean;
|
|
67
|
+
/**
|
|
68
|
+
* While listening, stops the browser from doing whatever the combination normally
|
|
69
|
+
* does — which is the entire point of taking over something like ⌘K.
|
|
70
|
+
*/
|
|
71
|
+
preventDefault?: boolean;
|
|
72
|
+
/**
|
|
73
|
+
* While listening, fires even when the reader is typing in a field. It is off by
|
|
74
|
+
* default, so a shortcut cannot fire in the middle of a sentence.
|
|
75
|
+
*/
|
|
76
|
+
allowInInput?: boolean;
|
|
77
|
+
/**
|
|
78
|
+
* What screen readers announce, "Keyboard shortcut: Ctrl + K" by default, from the
|
|
79
|
+
* design system dictionary.
|
|
80
|
+
*/
|
|
81
|
+
label?: string;
|
|
82
|
+
}
|
|
83
|
+
declare const __VLS_export: import('vue').DefineComponent<HotkeysProps, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
|
|
84
|
+
trigger: (event: KeyboardEvent) => any;
|
|
85
|
+
}, string, import('vue').PublicProps, Readonly<HotkeysProps> & Readonly<{
|
|
86
|
+
onTrigger?: ((event: KeyboardEvent) => any) | undefined;
|
|
87
|
+
}>, {
|
|
88
|
+
label: string;
|
|
89
|
+
size: HotkeysSize;
|
|
90
|
+
variant: HotkeysVariant;
|
|
91
|
+
compact: boolean;
|
|
92
|
+
attached: boolean;
|
|
93
|
+
separator: string;
|
|
94
|
+
platform: HotkeysPlatform;
|
|
95
|
+
listen: boolean;
|
|
96
|
+
preventDefault: boolean;
|
|
97
|
+
allowInInput: boolean;
|
|
98
|
+
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
|
|
99
|
+
declare const _default: typeof __VLS_export;
|
|
100
|
+
export default _default;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"VHotkeys.js","names":[],"sources":["../../../src/components/VHotkeys/VHotkeys.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, onBeforeUnmount, onMounted, ref, watch } from 'vue'\n\nimport {\n DEFAULT_PLATFORM,\n capLabel,\n detectPlatform,\n isEditableTarget,\n matchesEvent,\n parseHotkeys,\n resolveKeys,\n} from './platform'\nimport type { HotkeysPlatform } from './platform'\nimport { useMessages } from '../../i18n/state'\n\n/**\n * A keyboard shortcut, shown as the keys one presses. It is written as a plain string\n * — `mod+k` — and rendered with the symbols of the system the reader is actually on:\n * ⌘K on a Mac, Ctrl+K on Windows and Linux.\n *\n * Two pieces of behaviour here are unique in the whole library, and both are worth\n * knowing about.\n *\n * The first is reading which operating system this is, the only place the library asks\n * that question. It happens once the component is mounted and nowhere else, because a\n * server cannot know the answer and the browser's first render has to match what the\n * server sent — the same reasoning as today's date in VDatePicker. A Mac visitor\n * therefore sees \"Ctrl\" for a single frame; the `platform` prop is the way out for a\n * host that already knows better.\n *\n * The second is `listen`, which attaches a key listener to the whole document — the\n * only one in the library, and therefore something one has to ASK for: a component\n * whose job is to display a shortcut must not silently capture the page's keyboard.\n *\n * The component is not interactive and cannot be focused, so it carries no hover, no\n * active and no focus rule, and consequently no transition and no reduced-motion\n * block. That absence is deliberate: do not copy VButton's state rules into it.\n */\nexport type HotkeysVariant = 'flat' | 'outlined' | 'elevated'\nexport type HotkeysSize = 'xs' | 'sm'\n\ninterface HotkeysProps {\n /**\n * The combination, `+`-separated: `mod+k`, `ctrl+shift+p`, `alt+enter`, `esc`.\n * Case- and space-insensitive. `mod` is the CROSS-PLATFORM modifier — ⌘ on\n * macOS, Ctrl everywhere else; `meta` is the literal Command/Windows/Super key.\n * Aliases: cmd/command/win/super → meta, control → ctrl, option/opt → alt,\n * return → enter, escape → esc, del → delete, arrowup… → up…. An unknown token\n * is displayed as declared (`k` → K, `f5` → F5). The `+` key is `plus`.\n */\n keys: string\n /** How a key cap is drawn: tinted, outlined, or raised off the page. */\n variant?: HotkeysVariant\n /**\n * Draws the whole combination as a SINGLE key rather than as several: the decoration\n * moves from each cap to the shortcut as a whole, so the separator ends up inside\n * the key instead of between two of them. It is purely visual — the markup and the\n * announced name are identical either way.\n */\n attached?: boolean\n /** The size of the caps. */\n size?: HotkeysSize\n /** Takes 4px off the height, leaving the padding and the text as they are. */\n compact?: boolean\n /**\n * Forces the keyboard's OS instead of detecting it — for a deterministic\n * rendering (stories, tests, a table showing all three) or a host that already\n * knows (Electron, Tauri, a server reading the User-Agent).\n */\n platform?: HotkeysPlatform\n /**\n * What is written between two caps. An empty string gives the macOS convention,\n * where the symbols simply follow one another: ⇧⌘K.\n */\n separator?: string\n /**\n * Actually listens for the combination and reports it. It is off by default: a\n * component whose job is to display a shortcut must not capture the page's keyboard\n * without being asked.\n */\n listen?: boolean\n /**\n * While listening, stops the browser from doing whatever the combination normally\n * does — which is the entire point of taking over something like ⌘K.\n */\n preventDefault?: boolean\n /**\n * While listening, fires even when the reader is typing in a field. It is off by\n * default, so a shortcut cannot fire in the middle of a sentence.\n */\n allowInInput?: boolean\n /**\n * What screen readers announce, \"Keyboard shortcut: Ctrl + K\" by default, from the\n * design system dictionary.\n */\n label?: string\n}\n\nconst props = withDefaults(defineProps<HotkeysProps>(), {\n variant: 'flat',\n attached: false,\n size: 'xs',\n compact: false,\n platform: undefined,\n separator: '+',\n listen: false,\n preventDefault: true,\n allowInInput: false,\n label: undefined,\n})\n\nconst emit = defineEmits<{\n /** The combination was pressed. It is only ever emitted while `listen` is on. */\n trigger: [event: KeyboardEvent]\n}>()\n\nconst m = useMessages()\n\n// @ssr — the library's ONLY reading of the visitor's platform, and the reason it\n// happens after mounting.\n/* The operating system is read once the component is in the page and never during\n setup: a server has nothing to read it from, so rendering the detected value\n directly would make the two markups differ.\n\n TRAP — the value is held PER INSTANCE and not at module level. A shared one, having\n already resolved to macOS, would make a component hydrated later — a Nuxt island, a\n route loaded on demand — render ⌘ on its very first client pass where the server had\n written Ctrl. */\nconst detected = ref<HotkeysPlatform>(DEFAULT_PLATFORM)\nonMounted(() => {\n detected.value = detectPlatform()\n if (props.listen) attach()\n})\n\nconst platform = computed(() => props.platform ?? detected.value)\nconst tokens = computed(() => parseHotkeys(props.keys))\nconst resolved = computed(() => resolveKeys(tokens.value, platform.value))\n\n// @a11y\n/* The same table is read twice, in opposite directions. On SCREEN the symbol wins, ⌘\n being what is engraved on the key; in the ANNOUNCED NAME the word does, because that\n symbol is either passed over in silence or read out as \"place of interest sign\",\n depending on the screen reader. Inverting the preference is what lets one table\n serve both. */\nconst caps = computed(() =>\n resolved.value.map(\n (key) => key.glyph ?? (key.word ? m.value.hotkeys[key.word] : capLabel(key.token)),\n ),\n)\nconst spoken = computed(() =>\n resolved.value\n .map((key) => (key.word ? m.value.hotkeys[key.word] : (key.glyph ?? capLabel(key.token))))\n .join(' + '),\n)\nconst resolvedLabel = computed(() => props.label ?? m.value.hotkeys.label(spoken.value))\n\n/* A plain variable and not a reactive one: nothing renders it, and making it reactive\n would cause renders for no reason — the same reasoning as in `useTimer`.\n\n TRAP — it is called `listening` and NOT `attached`. Every top-level binding of a\n `<script setup>` is exposed to the template, where it SHADOWS the prop of the same\n name: called `attached`, this flag would silently be what the template read instead\n of the prop, and the joined rendering would follow whether a listener happened to be\n installed. */\nlet listening = false\n\nfunction attach() {\n if (listening || typeof document === 'undefined') return\n document.addEventListener('keydown', onKeydown)\n listening = true\n}\n\nfunction detach() {\n if (!listening) return\n document.removeEventListener('keydown', onKeydown)\n listening = false\n}\n\n// @keyboard @core — the listening half. Deciding whether a key event IS the\n// combination is pure and lives in `platform.ts`.\nfunction onKeydown(event: KeyboardEvent) {\n /* A held-down combination repeats at the system's auto-repeat rate, which would\n reopen the consumer's palette a dozen times a second; only the first press\n counts. */\n if (!props.listen || event.repeat) return\n if (!props.allowInInput && isEditableTarget(event.target)) return\n if (!matchesEvent(event, tokens.value, platform.value)) return\n if (props.preventDefault) event.preventDefault()\n emit('trigger', event)\n}\n\n/* Attaching the listener once and simply returning early inside it would be shorter to\n write, but a documentation page listing fifty shortcuts would then install fifty\n document listeners that do nothing. Following the prop is what keeps that at zero. */\nwatch(\n () => props.listen,\n (on) => (on ? attach() : detach()),\n)\nonBeforeUnmount(detach)\n</script>\n\n<template>\n <kbd\n class=\"v-hotkeys v-control\"\n :data-variant=\"variant\"\n :data-attached=\"attached ? '' : undefined\"\n :data-size=\"size\"\n :data-compact=\"compact ? '' : undefined\"\n :data-platform=\"platform\"\n >\n <span class=\"v-hotkeys-keys\" aria-hidden=\"true\">\n <template v-for=\"(cap, index) in caps\" :key=\"index\">\n <span v-if=\"index > 0 && separator\" class=\"v-hotkeys-separator\">{{ separator }}</span>\n <kbd class=\"v-hotkeys-key\">{{ cap }}</kbd>\n </template>\n </span>\n <span class=\"v-visually-hidden\">{{ resolvedLabel }}</span>\n </kbd>\n</template>\n\n<style>\n@layer vectis.components {\n /* TRAP — the browser gives a `<kbd>` a monospaced family AND a smaller size, and\n that reduction COMPOUNDS when one `<kbd>` sits inside another, as it does here:\n the caps would come out at roughly 69% of the surrounding text. Both are reset\n here and again on the caps themselves, and deleting either line silently\n miniaturizes the whole component.\n\n The vertical alignment is the second correction: a box laid out this way sits on\n the baseline of its FIRST item, which drops the caps below the line of prose\n around them. */\n .v-hotkeys {\n display: inline-flex;\n align-items: center;\n /* Centres the content in the cases where the minimum width wins over it: a\n single-character combination drawn as one key. */\n justify-content: center;\n vertical-align: middle;\n font-family: var(--vectis-text-family);\n font-size: var(--control-font-size);\n --hotkeys-pad: var(--control-padding-inline);\n }\n\n /* The size comes from the shared class set on the ROOT: its variables inherit down,\n and it is the CAPS that read the height from them. The scale itself holds five\n steps; the component's type restricts it to the two smallest, a key cap being\n smaller than a control. */\n .v-hotkeys-keys {\n display: inline-flex;\n align-items: center;\n gap: var(--control-gap);\n color: var(--vectis-color-text);\n }\n\n .v-hotkeys-key {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n font-family: inherit;\n font-size: inherit;\n font-weight: var(--vectis-text-control-weight);\n line-height: var(--vectis-text-control-leading);\n }\n\n /* The three variants mirror VButton's NEUTRAL tone declaration for declaration —\n tinted, outlined, and raised — minus everything that reacts to a pointer, since\n nothing here is interactive. There is a single set of colours and therefore no\n tone table at all: a shortcut is chrome, never data of the reader's.\n\n They set VARIABLES rather than declaring the look straight away, because that look\n has two possible carriers (see below). The names are qualified on purpose: these\n variables inherit, so a bare `--bg` would be captured by any ancestor in the host\n application that happened to define one. */\n .v-hotkeys[data-variant='flat'] {\n --hotkeys-bg: var(--vectis-color-surface-muted);\n --hotkeys-border: transparent;\n --hotkeys-shadow: none;\n }\n\n .v-hotkeys[data-variant='outlined'] {\n --hotkeys-bg: transparent;\n --hotkeys-border: var(--vectis-color-border-strong);\n --hotkeys-shadow: none;\n }\n\n .v-hotkeys[data-variant='elevated'] {\n --hotkeys-bg: var(--vectis-color-surface-raised);\n --hotkeys-border: transparent;\n --hotkeys-shadow: var(--vectis-shadow-sm);\n }\n\n /* When one key holds the WHOLE combination, its ends take the same breathing room as\n the gaps inside it, which gives the key a single rhythm. The usual control padding\n is sized to wrap ONE short label; around three runs of text already spaced from\n one another, it reads as slack at the edges. */\n .v-hotkeys[data-attached] {\n --hotkeys-pad: var(--control-gap);\n }\n\n /* THE key recipe, written once for its two possible carriers: every cap by default,\n and the whole shortcut alone when it is drawn as a single key — which is exactly\n what puts the separator inside the key rather than between two of them. Written\n out twice, the two renderings would drift apart at the first token change. */\n .v-hotkeys[data-attached],\n .v-hotkeys:not([data-attached]) .v-hotkeys-key {\n height: var(--control-height);\n /* A minimum equal to the height makes a single-character key read as a square\n rather than as a sliver. */\n min-inline-size: var(--control-height);\n padding-inline: var(--hotkeys-pad);\n border: 1px solid var(--hotkeys-border);\n border-radius: var(--vectis-radius-interactive);\n background: var(--hotkeys-bg);\n box-shadow: var(--hotkeys-shadow);\n }\n\n /* The separator is the surrounding text colour softened, and not a fixed grey: a\n shortcut may sit in prose of any colour, and a grey chosen against the page would\n be wrong in half of them. */\n .v-hotkeys-separator {\n color: color-mix(in oklab, currentcolor, transparent 40%);\n }\n}\n</style>\n"],"mappings":""}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { useMessages as e } from "../../i18n/state.js";
|
|
2
|
+
import { DEFAULT_PLATFORM as t, capLabel as n, detectPlatform as r, isEditableTarget as i, matchesEvent as a, parseHotkeys as o, resolveKeys as s } from "./platform.js";
|
|
3
|
+
import { Fragment as c, computed as l, createCommentVNode as u, createElementBlock as d, createElementVNode as f, defineComponent as p, onBeforeUnmount as m, onMounted as h, openBlock as g, ref as _, renderList as v, toDisplayString as y, watch as b } from "vue";
|
|
4
|
+
//#region src/components/VHotkeys/VHotkeys.vue?vue&type=script&setup=true&lang.ts
|
|
5
|
+
var x = [
|
|
6
|
+
"data-variant",
|
|
7
|
+
"data-attached",
|
|
8
|
+
"data-size",
|
|
9
|
+
"data-compact",
|
|
10
|
+
"data-platform"
|
|
11
|
+
], S = {
|
|
12
|
+
class: "v-hotkeys-keys",
|
|
13
|
+
"aria-hidden": "true"
|
|
14
|
+
}, C = {
|
|
15
|
+
key: 0,
|
|
16
|
+
class: "v-hotkeys-separator"
|
|
17
|
+
}, w = { class: "v-hotkeys-key" }, T = { class: "v-visually-hidden" }, E = /*@__PURE__*/ p({
|
|
18
|
+
__name: "VHotkeys",
|
|
19
|
+
props: {
|
|
20
|
+
keys: {},
|
|
21
|
+
variant: { default: "flat" },
|
|
22
|
+
attached: {
|
|
23
|
+
type: Boolean,
|
|
24
|
+
default: !1
|
|
25
|
+
},
|
|
26
|
+
size: { default: "xs" },
|
|
27
|
+
compact: {
|
|
28
|
+
type: Boolean,
|
|
29
|
+
default: !1
|
|
30
|
+
},
|
|
31
|
+
platform: { default: void 0 },
|
|
32
|
+
separator: { default: "+" },
|
|
33
|
+
listen: {
|
|
34
|
+
type: Boolean,
|
|
35
|
+
default: !1
|
|
36
|
+
},
|
|
37
|
+
preventDefault: {
|
|
38
|
+
type: Boolean,
|
|
39
|
+
default: !0
|
|
40
|
+
},
|
|
41
|
+
allowInInput: {
|
|
42
|
+
type: Boolean,
|
|
43
|
+
default: !1
|
|
44
|
+
},
|
|
45
|
+
label: { default: void 0 }
|
|
46
|
+
},
|
|
47
|
+
emits: ["trigger"],
|
|
48
|
+
setup(p, { emit: E }) {
|
|
49
|
+
let D = p, O = E, k = e(), A = _(t);
|
|
50
|
+
h(() => {
|
|
51
|
+
A.value = r(), D.listen && R();
|
|
52
|
+
});
|
|
53
|
+
let j = l(() => D.platform ?? A.value), M = l(() => o(D.keys)), N = l(() => s(M.value, j.value)), P = l(() => N.value.map((e) => e.glyph ?? (e.word ? k.value.hotkeys[e.word] : n(e.token)))), F = l(() => N.value.map((e) => e.word ? k.value.hotkeys[e.word] : e.glyph ?? n(e.token)).join(" + ")), I = l(() => D.label ?? k.value.hotkeys.label(F.value)), L = !1;
|
|
54
|
+
function R() {
|
|
55
|
+
L || typeof document > "u" || (document.addEventListener("keydown", B), L = !0);
|
|
56
|
+
}
|
|
57
|
+
function z() {
|
|
58
|
+
L &&= (document.removeEventListener("keydown", B), !1);
|
|
59
|
+
}
|
|
60
|
+
function B(e) {
|
|
61
|
+
!D.listen || e.repeat || !D.allowInInput && i(e.target) || a(e, M.value, j.value) && (D.preventDefault && e.preventDefault(), O("trigger", e));
|
|
62
|
+
}
|
|
63
|
+
return b(() => D.listen, (e) => e ? R() : z()), m(z), (e, t) => (g(), d("kbd", {
|
|
64
|
+
class: "v-hotkeys v-control",
|
|
65
|
+
"data-variant": p.variant,
|
|
66
|
+
"data-attached": p.attached ? "" : void 0,
|
|
67
|
+
"data-size": p.size,
|
|
68
|
+
"data-compact": p.compact ? "" : void 0,
|
|
69
|
+
"data-platform": j.value
|
|
70
|
+
}, [f("span", S, [(g(!0), d(c, null, v(P.value, (e, t) => (g(), d(c, { key: t }, [t > 0 && p.separator ? (g(), d("span", C, y(p.separator), 1)) : u("", !0), f("kbd", w, y(e), 1)], 64))), 128))]), f("span", T, y(I.value), 1)], 8, x));
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
//#endregion
|
|
74
|
+
export { E as default };
|
|
75
|
+
|
|
76
|
+
//# sourceMappingURL=VHotkeys.vue_vue_type_script_setup_true_lang.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"VHotkeys.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../src/components/VHotkeys/VHotkeys.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, onBeforeUnmount, onMounted, ref, watch } from 'vue'\n\nimport {\n DEFAULT_PLATFORM,\n capLabel,\n detectPlatform,\n isEditableTarget,\n matchesEvent,\n parseHotkeys,\n resolveKeys,\n} from './platform'\nimport type { HotkeysPlatform } from './platform'\nimport { useMessages } from '../../i18n/state'\n\n/**\n * A keyboard shortcut, shown as the keys one presses. It is written as a plain string\n * — `mod+k` — and rendered with the symbols of the system the reader is actually on:\n * ⌘K on a Mac, Ctrl+K on Windows and Linux.\n *\n * Two pieces of behaviour here are unique in the whole library, and both are worth\n * knowing about.\n *\n * The first is reading which operating system this is, the only place the library asks\n * that question. It happens once the component is mounted and nowhere else, because a\n * server cannot know the answer and the browser's first render has to match what the\n * server sent — the same reasoning as today's date in VDatePicker. A Mac visitor\n * therefore sees \"Ctrl\" for a single frame; the `platform` prop is the way out for a\n * host that already knows better.\n *\n * The second is `listen`, which attaches a key listener to the whole document — the\n * only one in the library, and therefore something one has to ASK for: a component\n * whose job is to display a shortcut must not silently capture the page's keyboard.\n *\n * The component is not interactive and cannot be focused, so it carries no hover, no\n * active and no focus rule, and consequently no transition and no reduced-motion\n * block. That absence is deliberate: do not copy VButton's state rules into it.\n */\nexport type HotkeysVariant = 'flat' | 'outlined' | 'elevated'\nexport type HotkeysSize = 'xs' | 'sm'\n\ninterface HotkeysProps {\n /**\n * The combination, `+`-separated: `mod+k`, `ctrl+shift+p`, `alt+enter`, `esc`.\n * Case- and space-insensitive. `mod` is the CROSS-PLATFORM modifier — ⌘ on\n * macOS, Ctrl everywhere else; `meta` is the literal Command/Windows/Super key.\n * Aliases: cmd/command/win/super → meta, control → ctrl, option/opt → alt,\n * return → enter, escape → esc, del → delete, arrowup… → up…. An unknown token\n * is displayed as declared (`k` → K, `f5` → F5). The `+` key is `plus`.\n */\n keys: string\n /** How a key cap is drawn: tinted, outlined, or raised off the page. */\n variant?: HotkeysVariant\n /**\n * Draws the whole combination as a SINGLE key rather than as several: the decoration\n * moves from each cap to the shortcut as a whole, so the separator ends up inside\n * the key instead of between two of them. It is purely visual — the markup and the\n * announced name are identical either way.\n */\n attached?: boolean\n /** The size of the caps. */\n size?: HotkeysSize\n /** Takes 4px off the height, leaving the padding and the text as they are. */\n compact?: boolean\n /**\n * Forces the keyboard's OS instead of detecting it — for a deterministic\n * rendering (stories, tests, a table showing all three) or a host that already\n * knows (Electron, Tauri, a server reading the User-Agent).\n */\n platform?: HotkeysPlatform\n /**\n * What is written between two caps. An empty string gives the macOS convention,\n * where the symbols simply follow one another: ⇧⌘K.\n */\n separator?: string\n /**\n * Actually listens for the combination and reports it. It is off by default: a\n * component whose job is to display a shortcut must not capture the page's keyboard\n * without being asked.\n */\n listen?: boolean\n /**\n * While listening, stops the browser from doing whatever the combination normally\n * does — which is the entire point of taking over something like ⌘K.\n */\n preventDefault?: boolean\n /**\n * While listening, fires even when the reader is typing in a field. It is off by\n * default, so a shortcut cannot fire in the middle of a sentence.\n */\n allowInInput?: boolean\n /**\n * What screen readers announce, \"Keyboard shortcut: Ctrl + K\" by default, from the\n * design system dictionary.\n */\n label?: string\n}\n\nconst props = withDefaults(defineProps<HotkeysProps>(), {\n variant: 'flat',\n attached: false,\n size: 'xs',\n compact: false,\n platform: undefined,\n separator: '+',\n listen: false,\n preventDefault: true,\n allowInInput: false,\n label: undefined,\n})\n\nconst emit = defineEmits<{\n /** The combination was pressed. It is only ever emitted while `listen` is on. */\n trigger: [event: KeyboardEvent]\n}>()\n\nconst m = useMessages()\n\n// @ssr — the library's ONLY reading of the visitor's platform, and the reason it\n// happens after mounting.\n/* The operating system is read once the component is in the page and never during\n setup: a server has nothing to read it from, so rendering the detected value\n directly would make the two markups differ.\n\n TRAP — the value is held PER INSTANCE and not at module level. A shared one, having\n already resolved to macOS, would make a component hydrated later — a Nuxt island, a\n route loaded on demand — render ⌘ on its very first client pass where the server had\n written Ctrl. */\nconst detected = ref<HotkeysPlatform>(DEFAULT_PLATFORM)\nonMounted(() => {\n detected.value = detectPlatform()\n if (props.listen) attach()\n})\n\nconst platform = computed(() => props.platform ?? detected.value)\nconst tokens = computed(() => parseHotkeys(props.keys))\nconst resolved = computed(() => resolveKeys(tokens.value, platform.value))\n\n// @a11y\n/* The same table is read twice, in opposite directions. On SCREEN the symbol wins, ⌘\n being what is engraved on the key; in the ANNOUNCED NAME the word does, because that\n symbol is either passed over in silence or read out as \"place of interest sign\",\n depending on the screen reader. Inverting the preference is what lets one table\n serve both. */\nconst caps = computed(() =>\n resolved.value.map(\n (key) => key.glyph ?? (key.word ? m.value.hotkeys[key.word] : capLabel(key.token)),\n ),\n)\nconst spoken = computed(() =>\n resolved.value\n .map((key) => (key.word ? m.value.hotkeys[key.word] : (key.glyph ?? capLabel(key.token))))\n .join(' + '),\n)\nconst resolvedLabel = computed(() => props.label ?? m.value.hotkeys.label(spoken.value))\n\n/* A plain variable and not a reactive one: nothing renders it, and making it reactive\n would cause renders for no reason — the same reasoning as in `useTimer`.\n\n TRAP — it is called `listening` and NOT `attached`. Every top-level binding of a\n `<script setup>` is exposed to the template, where it SHADOWS the prop of the same\n name: called `attached`, this flag would silently be what the template read instead\n of the prop, and the joined rendering would follow whether a listener happened to be\n installed. */\nlet listening = false\n\nfunction attach() {\n if (listening || typeof document === 'undefined') return\n document.addEventListener('keydown', onKeydown)\n listening = true\n}\n\nfunction detach() {\n if (!listening) return\n document.removeEventListener('keydown', onKeydown)\n listening = false\n}\n\n// @keyboard @core — the listening half. Deciding whether a key event IS the\n// combination is pure and lives in `platform.ts`.\nfunction onKeydown(event: KeyboardEvent) {\n /* A held-down combination repeats at the system's auto-repeat rate, which would\n reopen the consumer's palette a dozen times a second; only the first press\n counts. */\n if (!props.listen || event.repeat) return\n if (!props.allowInInput && isEditableTarget(event.target)) return\n if (!matchesEvent(event, tokens.value, platform.value)) return\n if (props.preventDefault) event.preventDefault()\n emit('trigger', event)\n}\n\n/* Attaching the listener once and simply returning early inside it would be shorter to\n write, but a documentation page listing fifty shortcuts would then install fifty\n document listeners that do nothing. Following the prop is what keeps that at zero. */\nwatch(\n () => props.listen,\n (on) => (on ? attach() : detach()),\n)\nonBeforeUnmount(detach)\n</script>\n\n<template>\n <kbd\n class=\"v-hotkeys v-control\"\n :data-variant=\"variant\"\n :data-attached=\"attached ? '' : undefined\"\n :data-size=\"size\"\n :data-compact=\"compact ? '' : undefined\"\n :data-platform=\"platform\"\n >\n <span class=\"v-hotkeys-keys\" aria-hidden=\"true\">\n <template v-for=\"(cap, index) in caps\" :key=\"index\">\n <span v-if=\"index > 0 && separator\" class=\"v-hotkeys-separator\">{{ separator }}</span>\n <kbd class=\"v-hotkeys-key\">{{ cap }}</kbd>\n </template>\n </span>\n <span class=\"v-visually-hidden\">{{ resolvedLabel }}</span>\n </kbd>\n</template>\n\n<style>\n@layer vectis.components {\n /* TRAP — the browser gives a `<kbd>` a monospaced family AND a smaller size, and\n that reduction COMPOUNDS when one `<kbd>` sits inside another, as it does here:\n the caps would come out at roughly 69% of the surrounding text. Both are reset\n here and again on the caps themselves, and deleting either line silently\n miniaturizes the whole component.\n\n The vertical alignment is the second correction: a box laid out this way sits on\n the baseline of its FIRST item, which drops the caps below the line of prose\n around them. */\n .v-hotkeys {\n display: inline-flex;\n align-items: center;\n /* Centres the content in the cases where the minimum width wins over it: a\n single-character combination drawn as one key. */\n justify-content: center;\n vertical-align: middle;\n font-family: var(--vectis-text-family);\n font-size: var(--control-font-size);\n --hotkeys-pad: var(--control-padding-inline);\n }\n\n /* The size comes from the shared class set on the ROOT: its variables inherit down,\n and it is the CAPS that read the height from them. The scale itself holds five\n steps; the component's type restricts it to the two smallest, a key cap being\n smaller than a control. */\n .v-hotkeys-keys {\n display: inline-flex;\n align-items: center;\n gap: var(--control-gap);\n color: var(--vectis-color-text);\n }\n\n .v-hotkeys-key {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n font-family: inherit;\n font-size: inherit;\n font-weight: var(--vectis-text-control-weight);\n line-height: var(--vectis-text-control-leading);\n }\n\n /* The three variants mirror VButton's NEUTRAL tone declaration for declaration —\n tinted, outlined, and raised — minus everything that reacts to a pointer, since\n nothing here is interactive. There is a single set of colours and therefore no\n tone table at all: a shortcut is chrome, never data of the reader's.\n\n They set VARIABLES rather than declaring the look straight away, because that look\n has two possible carriers (see below). The names are qualified on purpose: these\n variables inherit, so a bare `--bg` would be captured by any ancestor in the host\n application that happened to define one. */\n .v-hotkeys[data-variant='flat'] {\n --hotkeys-bg: var(--vectis-color-surface-muted);\n --hotkeys-border: transparent;\n --hotkeys-shadow: none;\n }\n\n .v-hotkeys[data-variant='outlined'] {\n --hotkeys-bg: transparent;\n --hotkeys-border: var(--vectis-color-border-strong);\n --hotkeys-shadow: none;\n }\n\n .v-hotkeys[data-variant='elevated'] {\n --hotkeys-bg: var(--vectis-color-surface-raised);\n --hotkeys-border: transparent;\n --hotkeys-shadow: var(--vectis-shadow-sm);\n }\n\n /* When one key holds the WHOLE combination, its ends take the same breathing room as\n the gaps inside it, which gives the key a single rhythm. The usual control padding\n is sized to wrap ONE short label; around three runs of text already spaced from\n one another, it reads as slack at the edges. */\n .v-hotkeys[data-attached] {\n --hotkeys-pad: var(--control-gap);\n }\n\n /* THE key recipe, written once for its two possible carriers: every cap by default,\n and the whole shortcut alone when it is drawn as a single key — which is exactly\n what puts the separator inside the key rather than between two of them. Written\n out twice, the two renderings would drift apart at the first token change. */\n .v-hotkeys[data-attached],\n .v-hotkeys:not([data-attached]) .v-hotkeys-key {\n height: var(--control-height);\n /* A minimum equal to the height makes a single-character key read as a square\n rather than as a sliver. */\n min-inline-size: var(--control-height);\n padding-inline: var(--hotkeys-pad);\n border: 1px solid var(--hotkeys-border);\n border-radius: var(--vectis-radius-interactive);\n background: var(--hotkeys-bg);\n box-shadow: var(--hotkeys-shadow);\n }\n\n /* The separator is the surrounding text colour softened, and not a fixed grey: a\n shortcut may sit in prose of any colour, and a grey chosen against the page would\n be wrong in half of them. */\n .v-hotkeys-separator {\n color: color-mix(in oklab, currentcolor, transparent 40%);\n }\n}\n</style>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAkGA,IAAM,IAAQ,GAaR,IAAO,GAKP,IAAI,EAAY,GAYhB,IAAW,EAAqB,CAAgB;EACtD,QAAgB;GAEd,AADA,EAAS,QAAQ,EAAe,GAC5B,EAAM,UAAQ,EAAO;EAC3B,CAAC;EAED,IAAM,IAAW,QAAe,EAAM,YAAY,EAAS,KAAK,GAC1D,IAAS,QAAe,EAAa,EAAM,IAAI,CAAC,GAChD,IAAW,QAAe,EAAY,EAAO,OAAO,EAAS,KAAK,CAAC,GAQnE,IAAO,QACX,EAAS,MAAM,KACZ,MAAQ,EAAI,UAAU,EAAI,OAAO,EAAE,MAAM,QAAQ,EAAI,QAAQ,EAAS,EAAI,KAAK,EAClF,CACF,GACM,IAAS,QACb,EAAS,MACN,KAAK,MAAS,EAAI,OAAO,EAAE,MAAM,QAAQ,EAAI,QAAS,EAAI,SAAS,EAAS,EAAI,KAAK,CAAG,CAAA,CACxF,KAAK,KAAK,CACf,GACM,IAAgB,QAAe,EAAM,SAAS,EAAE,MAAM,QAAQ,MAAM,EAAO,KAAK,CAAC,GAUnF,IAAY;EAEhB,SAAS,IAAS;GACZ,KAAa,OAAO,WAAa,QACrC,SAAS,iBAAiB,WAAW,CAAS,GAC9C,IAAY;EACd;EAEA,SAAS,IAAS;GACX,AAEL,OADA,SAAS,oBAAoB,WAAW,CAAS,GACrC;EACd;EAIA,SAAS,EAAU,GAAsB;GAInC,CAAC,EAAM,UAAU,EAAM,UACvB,CAAC,EAAM,gBAAgB,EAAiB,EAAM,MAAM,KACnD,EAAa,GAAO,EAAO,OAAO,EAAS,KAAK,MACjD,EAAM,kBAAgB,EAAM,eAAe,GAC/C,EAAK,WAAW,CAAK;EACvB;SAKA,QACQ,EAAM,SACX,MAAQ,IAAK,EAAO,IAAI,EAAO,CAClC,GACA,EAAgB,CAAM,mBAIpB,EAeM,OAAA;GAdJ,OAAM;GACL,gBAAc,EAAA;GACd,iBAAe,EAAA,WAAQ,KAAQ,KAAA;GAC/B,aAAW,EAAA;GACX,gBAAc,EAAA,UAAO,KAAQ,KAAA;GAC7B,iBAAe,EAAA;MAEhB,EAKO,QALP,GAKO,EAAA,EAAA,EAAA,GAJL,EAGW,GAAA,MAAA,EAHsB,EAAA,QAAf,GAAK,wBAAsB,EAAK,GAAA,CACpC,IAAK,KAAQ,EAAA,aAAA,EAAA,GAAzB,EAAsF,QAAtF,GAAsF,EAAnB,EAAA,SAAS,GAAA,CAAA,KAAA,EAAA,IAAA,EAAA,GAC5E,EAA0C,OAA1C,GAA0C,EAAZ,CAAG,GAAA,CAAA,CAAA,GAAA,EAAA,cAGrC,EAA0D,QAA1D,GAA0D,EAAvB,EAAA,KAAa,GAAA,CAAA,CAAA,GAAA,GAAA,CAAA"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Everything VHotkeys needs to know about keyboards: which system this one belongs to,
|
|
3
|
+
* and how a written token relates to the symbol engraved on the key, to the word for
|
|
4
|
+
* it, and to what the browser reports when it is pressed.
|
|
5
|
+
*
|
|
6
|
+
* An operating system is not a language, and the distinction matters here. Whether a
|
|
7
|
+
* key shows ⌘ or Ctrl is a fact about the hardware, so it does NOT depend on the
|
|
8
|
+
* reader's language. Only the WORDS do — Shift becomes Maj in French — and those live
|
|
9
|
+
* in the dictionary: this module hands back the dictionary KEY and never the text
|
|
10
|
+
* itself.
|
|
11
|
+
*
|
|
12
|
+
* What earns the module its existence is the alias table. The SAME table normalizes
|
|
13
|
+
* the tokens a consumer writes in `keys` and the key names the browser reports, so a
|
|
14
|
+
* shortcut cannot be declared in a spelling the matcher would fail to recognize.
|
|
15
|
+
*
|
|
16
|
+
* TRAP — detecting the platform must only ever be done once a component is mounted.
|
|
17
|
+
* There is nothing to read it from on a server, and sniffing a request header is not
|
|
18
|
+
* this library's business.
|
|
19
|
+
*/
|
|
20
|
+
export type HotkeysPlatform = 'mac' | 'windows' | 'linux' | 'other';
|
|
21
|
+
/**
|
|
22
|
+
* The dictionary entries naming a key, and only those — the sentence framing the
|
|
23
|
+
* shortcut is not one of them.
|
|
24
|
+
*
|
|
25
|
+
* The list is written out here rather than derived from the dictionary's own type,
|
|
26
|
+
* which would tie this module to the dictionary's shape. Nothing is lost: reading an
|
|
27
|
+
* entry by one of these names is checked just as strictly at the point of use.
|
|
28
|
+
*/
|
|
29
|
+
export type HotkeysWord = 'command' | 'ctrl' | 'alt' | 'shift' | 'windows' | 'super' | 'enter' | 'escape' | 'space' | 'backspace' | 'delete' | 'tab' | 'up' | 'down' | 'left' | 'right';
|
|
30
|
+
/** One key of a shortcut, once resolved for a given platform. */
|
|
31
|
+
export interface ResolvedKey {
|
|
32
|
+
/** Its canonical name, which is what the matcher compares a key press against. */
|
|
33
|
+
token: string;
|
|
34
|
+
/** The symbol engraved on that key, where the system engraves one. */
|
|
35
|
+
glyph?: string;
|
|
36
|
+
/**
|
|
37
|
+
* Which dictionary entry names it. Nothing here means the design system does not
|
|
38
|
+
* know this key, and it is printed as it was written.
|
|
39
|
+
*/
|
|
40
|
+
word?: HotkeysWord;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* What a SERVER renders, and therefore what the browser's FIRST render must be as
|
|
44
|
+
* well. It shares its words with Windows and Linux — Ctrl, Alt, Shift — so only a Mac
|
|
45
|
+
* visitor pays a single frame of "Ctrl" before it is corrected to ⌘.
|
|
46
|
+
*/
|
|
47
|
+
export declare const DEFAULT_PLATFORM: HotkeysPlatform;
|
|
48
|
+
/**
|
|
49
|
+
* Works out which system the keyboard belongs to, from two sources in order. The
|
|
50
|
+
* modern one is the more reliable; the older one is deprecated and frozen, but it is
|
|
51
|
+
* still the only one Firefox and Safari provide.
|
|
52
|
+
*
|
|
53
|
+
* The modern one is missing from TypeScript's own definitions, so it is described by a
|
|
54
|
+
* type declared LOCALLY rather than added to the global ones — the latter would leak
|
|
55
|
+
* out into every consumer's compilation.
|
|
56
|
+
*/
|
|
57
|
+
export declare function detectPlatform(): HotkeysPlatform;
|
|
58
|
+
/**
|
|
59
|
+
* Reads a combination as it was written and returns its keys in canonical form:
|
|
60
|
+
* `'mod+k'` and `' Mod + K '` both give the same two. Empty segments are dropped, so a
|
|
61
|
+
* trailing separator is harmless — and the `+` KEY itself is written `plus`.
|
|
62
|
+
*/
|
|
63
|
+
export declare function parseHotkeys(keys: string): string[];
|
|
64
|
+
/**
|
|
65
|
+
* How a key nobody has a word or a symbol for is printed: as it was written, merely
|
|
66
|
+
* capitalized — `k` becomes K, `f5` becomes F5, and a slash stays a slash.
|
|
67
|
+
*/
|
|
68
|
+
export declare function capLabel(token: string): string;
|
|
69
|
+
/**
|
|
70
|
+
* Resolves each key of a combination for a given system, attaching the symbol engraved
|
|
71
|
+
* on it and the dictionary entry naming it, where either exists.
|
|
72
|
+
*/
|
|
73
|
+
export declare function resolveKeys(tokens: string[], platform: HotkeysPlatform): ResolvedKey[];
|
|
74
|
+
/**
|
|
75
|
+
* Whether a key press IS this combination.
|
|
76
|
+
*
|
|
77
|
+
* The modifiers are compared EXACTLY, and never as "at least these ones". Without
|
|
78
|
+
* that, `mod+k` and `mod+shift+k` could not coexist in one application: the first
|
|
79
|
+
* would swallow every press meant for the second.
|
|
80
|
+
*/
|
|
81
|
+
export declare function matchesEvent(event: KeyboardEvent, tokens: string[], platform: HotkeysPlatform): boolean;
|
|
82
|
+
export declare function isEditableTarget(target: EventTarget | null): boolean;
|