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,156 @@
|
|
|
1
|
+
import { IconSource } from '../VIcon/types.js';
|
|
2
|
+
/** How the chosen files are shown inside the field when several are allowed. */
|
|
3
|
+
export type FileInputDisplay = 'text' | 'chip';
|
|
4
|
+
/** Why a file was turned away: its kind, its size, how many there already are, or the total. */
|
|
5
|
+
export type FileInputRejectReason = 'type' | 'size' | 'count' | 'total-size';
|
|
6
|
+
/** One file that was turned away, and the reason it was. */
|
|
7
|
+
export interface FileInputRejection {
|
|
8
|
+
/** The file itself, so a message can name it. */
|
|
9
|
+
file: File;
|
|
10
|
+
/** What it fell foul of. */
|
|
11
|
+
reason: FileInputRejectReason;
|
|
12
|
+
}
|
|
13
|
+
interface FileInputProps {
|
|
14
|
+
/** Allows several files to be chosen. With one only, every extra file is turned away. */
|
|
15
|
+
multiple?: boolean;
|
|
16
|
+
/**
|
|
17
|
+
* Which kinds of file are accepted, in the browser's own syntax (`image/*,.pdf`).
|
|
18
|
+
*
|
|
19
|
+
* It is applied TWICE, and it has to be: as an attribute, which is what filters the
|
|
20
|
+
* system's file dialog, and again in code, which is the only thing that can filter a
|
|
21
|
+
* file DROPPED on the component — the attribute has no say over a drop.
|
|
22
|
+
*/
|
|
23
|
+
accept?: string;
|
|
24
|
+
/**
|
|
25
|
+
* How the chosen files are shown: their names joined by commas, or one dismissible
|
|
26
|
+
* chip each. It only means something when several files are allowed; a single name is
|
|
27
|
+
* always text.
|
|
28
|
+
*/
|
|
29
|
+
display?: FileInputDisplay;
|
|
30
|
+
/** The largest ONE file may be, in bytes. */
|
|
31
|
+
maxSize?: number;
|
|
32
|
+
/** The largest the whole selection may be, in bytes. */
|
|
33
|
+
maxTotalSize?: number;
|
|
34
|
+
/** How many files may be chosen at most. */
|
|
35
|
+
maxFiles?: number;
|
|
36
|
+
/** Shows how much has been chosen under the field: "3 files (1.2 MB)". */
|
|
37
|
+
counter?: boolean;
|
|
38
|
+
/** The icon at the end of the field, which opens the file dialog. */
|
|
39
|
+
attachIcon?: IconSource;
|
|
40
|
+
/** Accepts files dropped onto the component, as well as chosen through the dialog. */
|
|
41
|
+
droppable?: boolean;
|
|
42
|
+
/** The height of the field: 32, 40 or 48 pixels. */
|
|
43
|
+
size?: 'sm' | 'md' | 'lg';
|
|
44
|
+
/** Takes 4px off the height, leaving the padding, the text and the icons as they are. */
|
|
45
|
+
compact?: boolean;
|
|
46
|
+
/** Makes the field unusable, greyed out through the colour tokens. */
|
|
47
|
+
disabled?: boolean;
|
|
48
|
+
/**
|
|
49
|
+
* Shows what was chosen without allowing it to change: no dialog, no drop, no removal.
|
|
50
|
+
*/
|
|
51
|
+
readonly?: boolean;
|
|
52
|
+
/**
|
|
53
|
+
* Marks the field as invalid — for a rule of your own, since nothing here is checked
|
|
54
|
+
* by the browser.
|
|
55
|
+
*/
|
|
56
|
+
invalid?: boolean;
|
|
57
|
+
/** The label above the field, tied to it so that clicking it focuses the field. */
|
|
58
|
+
label?: string;
|
|
59
|
+
/**
|
|
60
|
+
* A line of help under the field, to the left of the counter. It is tied to the field
|
|
61
|
+
* for assistive technology.
|
|
62
|
+
*/
|
|
63
|
+
hint?: string;
|
|
64
|
+
/**
|
|
65
|
+
* What the field says while nothing is chosen. It falls back to the design system
|
|
66
|
+
* dictionary.
|
|
67
|
+
*/
|
|
68
|
+
placeholder?: string;
|
|
69
|
+
/** Offers a cross that empties the selection. */
|
|
70
|
+
clearable?: boolean;
|
|
71
|
+
}
|
|
72
|
+
type __VLS_Props = FileInputProps;
|
|
73
|
+
type __VLS_Slots = {
|
|
74
|
+
/**
|
|
75
|
+
* Replaces the chip standing for one file.
|
|
76
|
+
*
|
|
77
|
+
* Three of the values it receives are what make it usable without regressions:
|
|
78
|
+
* `label` is the name already shortened in the MIDDLE so that its extension survives,
|
|
79
|
+
* `remove` is what takes the file out — without it the file could no longer be removed
|
|
80
|
+
* at all — and the size and density are the ones worked out to sit inside the field,
|
|
81
|
+
* which cannot be guessed from outside.
|
|
82
|
+
*/
|
|
83
|
+
chip?(props: {
|
|
84
|
+
file: File;
|
|
85
|
+
index: number;
|
|
86
|
+
label: string;
|
|
87
|
+
remove: () => void;
|
|
88
|
+
size: 'xs' | 'sm';
|
|
89
|
+
compact: boolean;
|
|
90
|
+
}): unknown;
|
|
91
|
+
/**
|
|
92
|
+
* Replaces the counter under the field. `text` is the sentence already built and
|
|
93
|
+
* translated; the count and the total size are there for a wording of your own.
|
|
94
|
+
*/
|
|
95
|
+
counter?(props: {
|
|
96
|
+
count: number;
|
|
97
|
+
size: number;
|
|
98
|
+
text: string;
|
|
99
|
+
}): unknown;
|
|
100
|
+
};
|
|
101
|
+
type __VLS_ModelProps = {
|
|
102
|
+
/**
|
|
103
|
+
* Always a LIST of files, whether or not several are allowed — never a file on its own.
|
|
104
|
+
* The shape of the value does not depend on a prop, so a consumer never has to narrow a
|
|
105
|
+
* union TypeScript has no way of discriminating. With a single file it is simply a list
|
|
106
|
+
* of at most one.
|
|
107
|
+
*/
|
|
108
|
+
modelValue?: File[];
|
|
109
|
+
};
|
|
110
|
+
type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
|
|
111
|
+
declare const __VLS_base: import('vue').DefineComponent<__VLS_PublicProps, {
|
|
112
|
+
/** Moves the focus to the visible field. */
|
|
113
|
+
focus: (options?: FocusOptions) => void | undefined;
|
|
114
|
+
/**
|
|
115
|
+
* Opens the file dialog. It only works when called from something the reader did — a
|
|
116
|
+
* click, a key press: browsers refuse to open a file dialog by themselves.
|
|
117
|
+
*/
|
|
118
|
+
open: () => void;
|
|
119
|
+
}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
|
|
120
|
+
clear: () => any;
|
|
121
|
+
"update:modelValue": (value: File[]) => any;
|
|
122
|
+
change: (files: File[]) => any;
|
|
123
|
+
reject: (rejection: FileInputRejection) => any;
|
|
124
|
+
}, string, import('vue').PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
|
|
125
|
+
onClear?: (() => any) | undefined;
|
|
126
|
+
"onUpdate:modelValue"?: ((value: File[]) => any) | undefined;
|
|
127
|
+
onChange?: ((files: File[]) => any) | undefined;
|
|
128
|
+
onReject?: ((rejection: FileInputRejection) => any) | undefined;
|
|
129
|
+
}>, {
|
|
130
|
+
label: string;
|
|
131
|
+
placeholder: string;
|
|
132
|
+
size: "sm" | "md" | "lg";
|
|
133
|
+
display: FileInputDisplay;
|
|
134
|
+
compact: boolean;
|
|
135
|
+
disabled: boolean;
|
|
136
|
+
multiple: boolean;
|
|
137
|
+
invalid: boolean;
|
|
138
|
+
readonly: boolean;
|
|
139
|
+
hint: string;
|
|
140
|
+
clearable: boolean;
|
|
141
|
+
counter: boolean;
|
|
142
|
+
accept: string;
|
|
143
|
+
maxSize: number;
|
|
144
|
+
maxTotalSize: number;
|
|
145
|
+
maxFiles: number;
|
|
146
|
+
attachIcon: IconSource;
|
|
147
|
+
droppable: boolean;
|
|
148
|
+
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
|
|
149
|
+
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
150
|
+
declare const _default: typeof __VLS_export;
|
|
151
|
+
export default _default;
|
|
152
|
+
type __VLS_WithSlots<T, S> = T & {
|
|
153
|
+
new (): {
|
|
154
|
+
$slots: S;
|
|
155
|
+
};
|
|
156
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import './VFileInput.css';
|
|
2
|
+
import e from "./VFileInput.vue_vue_type_script_setup_true_lang.js";
|
|
3
|
+
/* empty css */
|
|
4
|
+
//#region src/components/VFileInput/VFileInput.vue
|
|
5
|
+
var t = e;
|
|
6
|
+
//#endregion
|
|
7
|
+
export { t as default };
|
|
8
|
+
|
|
9
|
+
//# sourceMappingURL=VFileInput.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"VFileInput.js","names":[],"sources":["../../../src/components/VFileInput/VFileInput.vue"],"sourcesContent":["<script setup lang=\"ts\">\n// @core\n/**\n * Choosing files, presented as an ordinary form field: a read-only text field showing\n * what was picked, with the real file input hidden behind it. It is the shape of a\n * read-only date picker, without the panel.\n *\n * What was chosen is reported as a plain list of files, which is what lets a consumer\n * build whatever preview they like from it.\n *\n * The JavaScript here is imposed by the platform rather than chosen. A file dialog opens\n * ONLY from a real click on a real file input, and the list of files it holds cannot be\n * written from a template — so the visible field can never BE the native control, and\n * that control can only ever be a SOURCE of files, never a mirror of the value.\n *\n * Everything else follows from those two facts: the clicks and keys relayed to the\n * hidden input, the reset of that input after every change — without which the same file\n * cannot be picked twice in a row — and the screening of incoming files in code, since\n * the `accept` attribute has no say whatsoever over a drop.\n */\nimport { computed, ref, useId, watchEffect } from 'vue'\n\nimport VChip from '../VChip/VChip.vue'\nimport { attach_file as attachFileIcon } from '../VIcon/icons/attach_file'\nimport type { IconSource } from '../VIcon/types'\nimport VInput from '../VInput/VInput.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 { chipScaleFor } from '../../utils/chip'\nimport { isDev } from '../../utils/env'\nimport { formatBytes } from '../../utils/file'\nimport { truncateMiddle } from './truncate'\n\n/** How the chosen files are shown inside the field when several are allowed. */\nexport type FileInputDisplay = 'text' | 'chip'\n\n/** Why a file was turned away: its kind, its size, how many there already are, or the total. */\nexport type FileInputRejectReason = 'type' | 'size' | 'count' | 'total-size'\n\n/** One file that was turned away, and the reason it was. */\nexport interface FileInputRejection {\n /** The file itself, so a message can name it. */\n file: File\n /** What it fell foul of. */\n reason: FileInputRejectReason\n}\n\ninterface FileInputProps {\n /** Allows several files to be chosen. 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 * file DROPPED on the component — the attribute has no say over a drop.\n */\n accept?: string\n /**\n * How the chosen files are shown: their names joined by commas, or one dismissible\n * chip each. It only means something when several files are allowed; a single name is\n * always text.\n */\n display?: FileInputDisplay\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 chosen at most. */\n maxFiles?: number\n /** Shows how much has been chosen under the field: \"3 files (1.2 MB)\". */\n counter?: boolean\n /** The icon at the end of the field, which opens the file dialog. */\n attachIcon?: IconSource\n /** Accepts files dropped onto the component, as well as chosen through the dialog. */\n droppable?: boolean\n /** The height of the field: 32, 40 or 48 pixels. */\n size?: 'sm' | 'md' | 'lg'\n /** Takes 4px off the height, leaving the padding, the text and the icons as they are. */\n compact?: boolean\n /** Makes the field unusable, greyed out through the colour tokens. */\n disabled?: boolean\n /**\n * Shows what was chosen without allowing it to change: no dialog, no drop, no removal.\n */\n readonly?: boolean\n /**\n * Marks the field as invalid — for a rule of your own, since nothing here is checked\n * by the browser.\n */\n invalid?: boolean\n /** The label above the field, tied to it so that clicking it focuses the field. */\n label?: string\n /**\n * A line of help under the field, to the left of the counter. It is tied to the field\n * for assistive technology.\n */\n hint?: string\n /**\n * What the field says while nothing is chosen. It falls back to the design system\n * dictionary.\n */\n placeholder?: string\n /** Offers a cross that empties the selection. */\n clearable?: boolean\n}\n\ndefineOptions({ inheritAttrs: false })\n\nconst props = withDefaults(defineProps<FileInputProps>(), {\n multiple: false,\n accept: undefined,\n display: 'text',\n maxSize: undefined,\n maxTotalSize: undefined,\n maxFiles: undefined,\n counter: false,\n attachIcon: () => attachFileIcon,\n droppable: true,\n size: 'md',\n compact: false,\n disabled: false,\n readonly: false,\n invalid: false,\n label: undefined,\n hint: undefined,\n placeholder: undefined,\n // On by default, unlike an ordinary field: what is in a picker cannot be erased by\n // typing, so without the cross there would be no way to empty it — the same reasoning\n // as in a read-only date picker.\n clearable: true,\n})\n\nconst emit = defineEmits<{\n /** The reader changed the selection — added something, removed something, cleared it. */\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: FileInputRejection]\n /** The clear cross emptied the selection. */\n clear: []\n}>()\n\ndefineSlots<{\n /**\n * Replaces the chip standing for one file.\n *\n * Three of the values it receives are what make it usable without regressions:\n * `label` is the name already shortened in the MIDDLE so that its extension survives,\n * `remove` is what takes the file out — without it the file could no longer be removed\n * at all — and the size and density are the ones worked out to sit inside the field,\n * which cannot be guessed from outside.\n */\n chip?(props: {\n file: File\n index: number\n label: string\n remove: () => void\n size: 'xs' | 'sm'\n compact: boolean\n }): unknown\n /**\n * Replaces the counter under the field. `text` is the sentence already built and\n * translated; the count and the total size are there for a wording of your own.\n */\n counter?(props: { count: number; size: number; text: 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\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 VFilePicker.\n *\n * Here, the bucket meant for \"the control the user deals with\" goes to the visible\n * field: that is what they see, focus and click, so a consumer's own `<label for>` has\n * to point at it. The description attribute is pulled out of that bucket, because this\n * component re-assembles it further down.\n */\nconst {\n fileEl,\n nativeAttrs,\n controlAttrs: fieldAttrs,\n acceptFiles,\n onNativeChange,\n openPicker,\n resetNative,\n} = useFileField({\n model,\n forwardedAttrs,\n enabled: () => !props.disabled && !props.readonly,\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 excludeFromControl: ['aria-describedby'],\n})\n\nconst inputRef = ref<InstanceType<typeof VInput> | null>(null)\n\n// Chips only mean something for a list: a single file always shows as plain text.\nconst resolvedDisplay = computed<FileInputDisplay>(() => (props.multiple ? props.display : 'text'))\n\nconst displayText = computed(() =>\n resolvedDisplay.value === 'chip' ? '' : model.value.map((file) => file.name).join(', '),\n)\n\nconst placeholderText = computed(() =>\n model.value.length > 0 ? undefined : (props.placeholder ?? m.value.fileInput.placeholder),\n)\n\n/*\n * Whether the clear cross is shown has to be answered EXPLICITLY here. The visible field\n * is read-only, and a read-only field hides its cross by default — rightly so, since its\n * text cannot be edited. Here the value comes from the file dialog rather than from\n * typing, so there is something to clear all the same.\n */\nconst canClear = computed(\n () => props.clearable && !props.disabled && !props.readonly && model.value.length > 0,\n)\n\n// @a11y @devwarn\n/*\n * The icon disappears along with what it offers: a read-only field opens no dialog, so\n * an icon inviting one would be a lie — the same rule VDateInput follows for its\n * calendar.\n *\n * TRAP — its LABEL stays defined at all times, even when no icon is rendered. The helper\n * that detects a click handler on an icon warns AT SETUP if one is attached without a\n * label, and it has no way of knowing whether an icon exists.\n */\nconst endIcon = computed<IconSource | undefined>(() =>\n props.readonly ? undefined : props.attachIcon,\n)\n\nconst totalSize = computed(() => model.value.reduce((sum, file) => sum + file.size, 0))\n\n/*\n * The counter is assembled from three sources: the WORD comes from the dictionary, since\n * it is language; the SIZE is formatted by the platform, which knows the local\n * conventions; and the parentheses come from neither, being punctuation every language\n * shares — the same boundary VBadge's \"99+\" falls on.\n *\n * With nothing chosen it states the count alone: \"0 files ()\" would be noise.\n */\nconst counterText = computed(() => {\n const word = m.value.fileInput.files(model.value.length)\n return model.value.length === 0 ? word : `${word} (${formatBytes(totalSize.value, locale.value)})`\n})\n\nconst hintId = useId()\nconst counterId = useId()\n\n// @a11y\n/*\n * What describes the field for a screen reader is a LIST of references, assembled here\n * rather than by VInput: the hint belongs to OUR row under the field, VInput having no\n * such row — its own counter sits inside the field.\n *\n * The counter is deliberately part of that list, unlike in VTextarea. When the files are\n * shown as chips the field's own text is EMPTY, and the counter is then the only spoken\n * summary of what has been chosen.\n */\nconst describedBy = computed(\n () =>\n [\n attrs['aria-describedby'] as string | undefined,\n props.hint ? hintId : undefined,\n props.counter ? counterId : undefined,\n ]\n .filter(Boolean)\n .join(' ') || undefined,\n)\n\n// The size, the density and the HEIGHT of the chips sitting inside the field, worked out\n// once in `utils/chip.ts` and shared with VCombobox. The height is set inline rather than\n// restated as a table of CSS rules: it belongs to the chips' own subtree, out of the\n// field's reach, and the field has to force its input to that same height or it grows\n// when focused.\nconst chipScale = computed(() => chipScaleFor(props.size, props.compact))\n\n/**\n * What a chip shows for a file. The name is shortened in the MIDDLE rather than cut off\n * at the end, for two reasons.\n *\n * The chips WRAP, so there is no line for a long name to overflow: left whole it would\n * simply push the field onto two or three rows. And cutting the middle preserves the\n * extension, which is what tells the reader what kind of file it is — an ellipsis at the\n * end drops it first.\n *\n * The full name is never lost: the removal button is named with it, and the chip carries\n * it as a tooltip whenever the label was actually shortened.\n */\nconst chipLabel = (file: File) => truncateMiddle(file.name)\n\nfunction onControlClick(event: MouseEvent) {\n // The field's own buttons already handle their clicks, and the click also reaches the\n // field itself. Without this guard the attach icon would open the dialog TWICE, and\n // the clear cross would reopen it immediately after emptying the selection.\n if ((event.target as HTMLElement).closest('button')) return\n openPicker()\n}\n\nfunction onFieldKeydown(event: KeyboardEvent) {\n if (event.key !== 'Enter' && event.key !== ' ') return\n // Cancelling the default on Enter also stops the form from being submitted: a\n // read-only text field is still a field, and Enter in one submits the form around it.\n event.preventDefault()\n openPicker()\n}\n\nfunction removeAt(index: number) {\n model.value = model.value.filter((_, i) => i !== index)\n resetNative()\n emit('change', model.value)\n // The removal button disappears along with its chip, so the focus would fall back to\n // the page body. Unlike the date and time pickers, nothing here opens on focus, so\n // this needs no guard against re-entering.\n inputRef.value?.focus()\n}\n\n/**\n * Empties the selection, and the hidden input with it — without that reset the same file\n * could not be chosen again straight afterwards.\n */\nfunction clearValue() {\n model.value = []\n resetNative()\n emit('clear')\n emit('change', model.value)\n}\n\n/* Files may be dropped on the component itself; there is no separate drop area here —\n that is what VFilePicker is for. */\nconst { dragging, onDragEnter, onDragOver, onDragLeave, onDrop } = useFileDrop(\n () => props.droppable && !props.disabled && !props.readonly,\n acceptFiles,\n)\n\n// @devwarn\nif (isDev) {\n watchEffect(() => {\n if (props.display === 'chip' && !props.multiple)\n console.warn(\n '[VFileInput] display=\"chip\" ignored without `multiple`: a single file shows as text.',\n )\n if (props.maxFiles !== undefined && !props.multiple)\n console.warn(\n '[VFileInput] `maxFiles` ignored without `multiple`: single mode already caps at one file.',\n )\n if (attrs.required !== undefined)\n console.warn(\n '[VFileInput] `required` lands on the hidden file input, which is not focusable: the browser blocks submission with no visible message. Validate the v-model yourself and use the `invalid` prop.',\n )\n })\n}\n\ndefineExpose({\n /** Moves the focus to the visible field. */\n focus: (options?: FocusOptions) => inputRef.value?.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-input\"\n :class=\"rootClass\"\n :style=\"[{ '--chip-height': chipScale.height }, rootStyle]\"\n :data-size=\"size\"\n :data-compact=\"compact ? '' : undefined\"\n :data-display=\"resolvedDisplay\"\n :data-disabled=\"disabled ? '' : undefined\"\n :data-readonly=\"readonly ? '' : undefined\"\n :data-dragging=\"dragging ? '' : undefined\"\n :data-can-clear=\"canClear ? '' : 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-input-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 <div class=\"v-file-input-control\" @click=\"onControlClick\">\n <VInput\n v-bind=\"fieldAttrs\"\n ref=\"inputRef\"\n :model-value=\"displayText\"\n readonly\n :label=\"label\"\n :placeholder=\"placeholderText\"\n :size=\"size\"\n :compact=\"compact\"\n :disabled=\"disabled\"\n :invalid=\"invalid\"\n :clearable=\"clearable\"\n :clear-visible=\"canClear\"\n :clear-label=\"m.fileInput.clear\"\n :icon-end=\"endIcon\"\n :icon-end-label=\"m.fileInput.attach\"\n :aria-describedby=\"describedBy\"\n @click:icon-end=\"openPicker\"\n @clear=\"clearValue\"\n @keydown=\"onFieldKeydown\"\n >\n <template v-if=\"resolvedDisplay === 'chip'\" #start>\n <template v-for=\"(file, index) in model\" :key=\"`${index}-${file.name}`\">\n <slot\n name=\"chip\"\n :file=\"file\"\n :index=\"index\"\n :label=\"chipLabel(file)\"\n :remove=\"() => removeAt(index)\"\n :size=\"chipScale.size\"\n :compact=\"chipScale.compact\"\n >\n <VChip\n tone=\"accent\"\n :size=\"chipScale.size\"\n :compact=\"chipScale.compact\"\n :dismissible=\"!readonly && !disabled\"\n :dismiss-label=\"m.fileInput.remove(file.name)\"\n :disabled=\"disabled\"\n :title=\"chipLabel(file) === file.name ? undefined : file.name\"\n @dismiss=\"removeAt(index)\"\n >{{ chipLabel(file) }}</VChip\n >\n </slot>\n </template>\n </template>\n </VInput>\n </div>\n\n <div v-if=\"hint || counter\" class=\"v-file-input-meta\">\n <VTypography\n v-if=\"hint\"\n :id=\"hintId\"\n variant=\"caption\"\n tone=\"muted\"\n class=\"v-file-input-hint\"\n >\n {{ hint }}\n </VTypography>\n <span v-if=\"counter\" :id=\"counterId\" class=\"v-file-input-counter\">\n <slot name=\"counter\" :count=\"model.length\" :size=\"totalSize\" :text=\"counterText\">\n {{ counterText }}\n </slot>\n </span>\n </div>\n </div>\n</template>\n\n<style>\n@layer vectis.components {\n /* Positioned so the hidden file input, which has no size at all, has something to be\n placed against. */\n .v-file-input {\n position: relative;\n display: flex;\n flex-direction: column;\n gap: var(--vectis-space-1);\n width: 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 field. Taking it\n out of the tab order and hiding it from screen readers, in the template, is what\n leaves the visible field as the single stop and the single announcement. */\n .v-file-input-native {\n position: absolute;\n inline-size: 0;\n block-size: 0;\n opacity: 0;\n pointer-events: none;\n }\n\n .v-file-input:not([data-disabled]):not([data-readonly]) .v-file-input-control,\n .v-file-input:not([data-disabled]):not([data-readonly])[data-display='text'] .v-input-control {\n cursor: pointer;\n }\n\n /* An ellipsis DOES work on an input, and a read-only one never scrolls by itself, so a\n long list of names is simply cut short. No tooltip is added for the rest: it would be\n announced as a description repeating the value the field already shows, and the\n complete list is what the model is for. */\n .v-file-input[data-display='text'] .v-input-control {\n text-overflow: ellipsis;\n }\n\n /* While a file is being dragged over it, the field is highlighted by redefining the\n very variable VInput uses for its own border colour — so the two can never disagree.\n The selector is one step more specific than VInput's, which is what makes it win\n whatever order the two sheets end up in. */\n .v-file-input[data-dragging] .v-input-field {\n --field-border-color: var(--vectis-color-accent);\n\n background: var(--vectis-color-accent-surface);\n }\n\n /* Shown as chips, the field holds them and lets them WRAP onto several rows, so it\n grows instead of scrolling.\n\n Two things have to be forced for that to hold together. The input inside is given\n the chips' own height rather than the full height it inherits, or its natural height\n would stretch every row it shares. And the padding at the end reserves exactly the\n room the icons take, since those are lifted out of the wrapping flow just below.\n\n That reservation is written as what the flow itself produces when the files are\n shown as text and nothing is lifted out: one glyph's width per action from the\n field's padding, one gap between two of them. It reads from the same two variables\n as the insets further down, so the room reserved and the glyphs it protects cannot\n drift apart. */\n .v-file-input[data-display='chip'] .v-input-field {\n position: relative;\n flex-wrap: wrap;\n height: auto;\n min-height: var(--control-height);\n padding-block: var(--vectis-space-1);\n padding-inline-end: calc(\n var(--control-padding-inline-field) + var(--vectis-icon-size) + var(--control-gap)\n );\n }\n\n .v-file-input[data-display='chip'][data-can-clear] .v-input-field {\n padding-inline-end: calc(\n var(--control-padding-inline-field) + 2 * var(--vectis-icon-size) + 2 * var(--control-gap)\n );\n }\n\n .v-file-input[data-display='chip'] .v-input-control {\n height: var(--chip-height);\n }\n\n /* The two icons are lifted out of the wrapping flow — the same recipe VCombobox uses —\n so that they stay pinned to the end of the field and vertically centred whatever the\n chips do. VInput renders the clear cross FIRST and the end icon after it, which is\n why the icon has to be addressed by excluding the cross. */\n .v-file-input[data-display='chip'] .v-input-clear,\n .v-file-input[data-display='chip'] .v-input-action:not(.v-input-clear) {\n position: absolute;\n top: 50%;\n translate: 0 -50%;\n }\n\n .v-file-input[data-display='chip'] .v-input-action:not(.v-input-clear) {\n inset-inline-end: var(--control-padding-inline-field);\n }\n\n /* This is the ONE place where the spacing between the two icons has to be written by\n hand. Everywhere else the field's own flow produces it for free, and the two must\n agree, or the same component would show two different gaps depending on how the\n files are displayed.\n\n So it is written as exactly what that flow produces: the end icon occupies one\n glyph's width from the field's padding, then one gap separates the two.\n\n TRAP — this reads in GLYPHS and not in buttons. VInput gives its inner buttons a\n negative margin equal to half the difference between the two, which makes an inset\n land on the glyph's edge rather than on the button's. Measuring in button widths\n instead pushes the cross a whole gap too far, with nothing anywhere to signal it. */\n .v-file-input[data-display='chip'] .v-input-clear {\n inset-inline-end: calc(\n var(--control-padding-inline-field) + var(--vectis-icon-size) + var(--control-gap)\n );\n }\n\n .v-file-input-meta {\n display: flex;\n align-items: baseline;\n gap: var(--vectis-space-2);\n }\n\n /* The counter stays styled locally: tabular-nums is not a typographic role.\n No overflow state — an over-limit file never enters the model, so the\n counter cannot overflow. */\n .v-file-input-counter {\n margin-inline-start: auto;\n font-size: var(--vectis-text-caption-size);\n color: var(--vectis-color-text-muted);\n font-variant-numeric: tabular-nums;\n }\n\n .v-file-input[data-disabled] .v-file-input-hint,\n .v-file-input[data-disabled] .v-file-input-counter {\n color: var(--vectis-color-text-subtle);\n }\n}\n</style>\n"],"mappings":""}
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
import { useLocale as e, useMessages as t } from "../../i18n/state.js";
|
|
2
|
+
import n from "../VTypography/VTypography.js";
|
|
3
|
+
import { useRootAttrs as ee } from "../../composables/useRootAttrs.js";
|
|
4
|
+
import te from "../VInput/VInput.js";
|
|
5
|
+
import ne from "../VChip/VChip.js";
|
|
6
|
+
import { chipScaleFor as r } from "../../utils/chip.js";
|
|
7
|
+
import { attach_file as i } from "../VIcon/icons/attach_file.js";
|
|
8
|
+
import { useFileDrop as re } from "../../composables/useFileDrop.js";
|
|
9
|
+
import { formatBytes as ie } from "../../utils/file.js";
|
|
10
|
+
import { useFileField as ae } from "../../composables/useFileField.js";
|
|
11
|
+
import { truncateMiddle as oe } from "./truncate.js";
|
|
12
|
+
import { Fragment as se, computed as a, createBlock as ce, createCommentVNode as o, createElementBlock as s, createElementVNode as c, createSlots as le, createTextVNode as l, createVNode as u, defineComponent as d, mergeModels as f, mergeProps as p, normalizeClass as ue, normalizeStyle as m, openBlock as h, ref as g, renderList as _, renderSlot as v, toDisplayString as y, unref as b, useId as x, useModel as de, withCtx as S } from "vue";
|
|
13
|
+
//#region src/components/VFileInput/VFileInput.vue?vue&type=script&setup=true&lang.ts
|
|
14
|
+
var fe = [
|
|
15
|
+
"data-size",
|
|
16
|
+
"data-compact",
|
|
17
|
+
"data-display",
|
|
18
|
+
"data-disabled",
|
|
19
|
+
"data-readonly",
|
|
20
|
+
"data-dragging",
|
|
21
|
+
"data-can-clear"
|
|
22
|
+
], pe = [
|
|
23
|
+
"accept",
|
|
24
|
+
"multiple",
|
|
25
|
+
"disabled"
|
|
26
|
+
], me = {
|
|
27
|
+
key: 0,
|
|
28
|
+
class: "v-file-input-meta"
|
|
29
|
+
}, he = ["id"], C = /*@__PURE__*/ d({
|
|
30
|
+
inheritAttrs: !1,
|
|
31
|
+
__name: "VFileInput",
|
|
32
|
+
props: /*@__PURE__*/ f({
|
|
33
|
+
multiple: {
|
|
34
|
+
type: Boolean,
|
|
35
|
+
default: !1
|
|
36
|
+
},
|
|
37
|
+
accept: { default: void 0 },
|
|
38
|
+
display: { default: "text" },
|
|
39
|
+
maxSize: { default: void 0 },
|
|
40
|
+
maxTotalSize: { default: void 0 },
|
|
41
|
+
maxFiles: { default: void 0 },
|
|
42
|
+
counter: {
|
|
43
|
+
type: Boolean,
|
|
44
|
+
default: !1
|
|
45
|
+
},
|
|
46
|
+
attachIcon: { default: () => i },
|
|
47
|
+
droppable: {
|
|
48
|
+
type: Boolean,
|
|
49
|
+
default: !0
|
|
50
|
+
},
|
|
51
|
+
size: { default: "md" },
|
|
52
|
+
compact: {
|
|
53
|
+
type: Boolean,
|
|
54
|
+
default: !1
|
|
55
|
+
},
|
|
56
|
+
disabled: {
|
|
57
|
+
type: Boolean,
|
|
58
|
+
default: !1
|
|
59
|
+
},
|
|
60
|
+
readonly: {
|
|
61
|
+
type: Boolean,
|
|
62
|
+
default: !1
|
|
63
|
+
},
|
|
64
|
+
invalid: {
|
|
65
|
+
type: Boolean,
|
|
66
|
+
default: !1
|
|
67
|
+
},
|
|
68
|
+
label: { default: void 0 },
|
|
69
|
+
hint: { default: void 0 },
|
|
70
|
+
placeholder: { default: void 0 },
|
|
71
|
+
clearable: {
|
|
72
|
+
type: Boolean,
|
|
73
|
+
default: !0
|
|
74
|
+
}
|
|
75
|
+
}, {
|
|
76
|
+
modelValue: { default: () => [] },
|
|
77
|
+
modelModifiers: {}
|
|
78
|
+
}),
|
|
79
|
+
emits: /*@__PURE__*/ f([
|
|
80
|
+
"change",
|
|
81
|
+
"reject",
|
|
82
|
+
"clear"
|
|
83
|
+
], ["update:modelValue"]),
|
|
84
|
+
setup(i, { expose: d, emit: f }) {
|
|
85
|
+
let C = i, w = f, T = de(i, "modelValue"), { attrs: E, rootClass: D, rootStyle: O, forwardedAttrs: k } = ee(), A = t(), j = e(), { fileEl: M, nativeAttrs: N, controlAttrs: P, acceptFiles: F, onNativeChange: I, openPicker: L, resetNative: R } = ae({
|
|
86
|
+
model: T,
|
|
87
|
+
forwardedAttrs: k,
|
|
88
|
+
enabled: () => !C.disabled && !C.readonly,
|
|
89
|
+
multiple: () => C.multiple,
|
|
90
|
+
limits: () => ({
|
|
91
|
+
accept: C.accept,
|
|
92
|
+
maxSize: C.maxSize,
|
|
93
|
+
maxFiles: C.maxFiles,
|
|
94
|
+
maxTotalSize: C.maxTotalSize
|
|
95
|
+
}),
|
|
96
|
+
onReject: (e) => w("reject", e),
|
|
97
|
+
onChange: (e) => w("change", e),
|
|
98
|
+
excludeFromControl: ["aria-describedby"]
|
|
99
|
+
}), z = g(null), B = a(() => C.multiple ? C.display : "text"), ge = a(() => B.value === "chip" ? "" : T.value.map((e) => e.name).join(", ")), _e = a(() => T.value.length > 0 ? void 0 : C.placeholder ?? A.value.fileInput.placeholder), V = a(() => C.clearable && !C.disabled && !C.readonly && T.value.length > 0), ve = a(() => C.readonly ? void 0 : C.attachIcon), H = a(() => T.value.reduce((e, t) => e + t.size, 0)), U = a(() => {
|
|
100
|
+
let e = A.value.fileInput.files(T.value.length);
|
|
101
|
+
return T.value.length === 0 ? e : `${e} (${ie(H.value, j.value)})`;
|
|
102
|
+
}), W = x(), G = x(), K = a(() => [
|
|
103
|
+
E["aria-describedby"],
|
|
104
|
+
C.hint ? W : void 0,
|
|
105
|
+
C.counter ? G : void 0
|
|
106
|
+
].filter(Boolean).join(" ") || void 0), q = a(() => r(C.size, C.compact)), J = (e) => oe(e.name);
|
|
107
|
+
function ye(e) {
|
|
108
|
+
e.target.closest("button") || L();
|
|
109
|
+
}
|
|
110
|
+
function be(e) {
|
|
111
|
+
e.key !== "Enter" && e.key !== " " || (e.preventDefault(), L());
|
|
112
|
+
}
|
|
113
|
+
function Y(e) {
|
|
114
|
+
T.value = T.value.filter((t, n) => n !== e), R(), w("change", T.value), z.value?.focus();
|
|
115
|
+
}
|
|
116
|
+
function xe() {
|
|
117
|
+
T.value = [], R(), w("clear"), w("change", T.value);
|
|
118
|
+
}
|
|
119
|
+
let { dragging: Se, onDragEnter: X, onDragOver: Z, onDragLeave: Q, onDrop: $ } = re(() => C.droppable && !C.disabled && !C.readonly, F);
|
|
120
|
+
return d({
|
|
121
|
+
focus: (e) => z.value?.focus(e),
|
|
122
|
+
open: L
|
|
123
|
+
}), (e, t) => (h(), s("div", {
|
|
124
|
+
class: ue(["v-file-input", b(D)]),
|
|
125
|
+
style: m([{ "--chip-height": q.value.height }, b(O)]),
|
|
126
|
+
"data-size": i.size,
|
|
127
|
+
"data-compact": i.compact ? "" : void 0,
|
|
128
|
+
"data-display": B.value,
|
|
129
|
+
"data-disabled": i.disabled ? "" : void 0,
|
|
130
|
+
"data-readonly": i.readonly ? "" : void 0,
|
|
131
|
+
"data-dragging": b(Se) ? "" : void 0,
|
|
132
|
+
"data-can-clear": V.value ? "" : void 0,
|
|
133
|
+
onDragenter: t[1] ||= (...e) => b(X) && b(X)(...e),
|
|
134
|
+
onDragover: t[2] ||= (...e) => b(Z) && b(Z)(...e),
|
|
135
|
+
onDragleave: t[3] ||= (...e) => b(Q) && b(Q)(...e),
|
|
136
|
+
onDrop: t[4] ||= (...e) => b($) && b($)(...e)
|
|
137
|
+
}, [
|
|
138
|
+
c("input", p(b(N), {
|
|
139
|
+
ref_key: "fileEl",
|
|
140
|
+
ref: M,
|
|
141
|
+
type: "file",
|
|
142
|
+
class: "v-file-input-native",
|
|
143
|
+
tabindex: "-1",
|
|
144
|
+
"aria-hidden": "true",
|
|
145
|
+
accept: i.accept,
|
|
146
|
+
multiple: i.multiple || void 0,
|
|
147
|
+
disabled: i.disabled || void 0,
|
|
148
|
+
onChange: t[0] ||= (...e) => b(I) && b(I)(...e)
|
|
149
|
+
}), null, 16, pe),
|
|
150
|
+
c("div", {
|
|
151
|
+
class: "v-file-input-control",
|
|
152
|
+
onClick: ye
|
|
153
|
+
}, [u(te, p(b(P), {
|
|
154
|
+
ref_key: "inputRef",
|
|
155
|
+
ref: z,
|
|
156
|
+
"model-value": ge.value,
|
|
157
|
+
readonly: "",
|
|
158
|
+
label: i.label,
|
|
159
|
+
placeholder: _e.value,
|
|
160
|
+
size: i.size,
|
|
161
|
+
compact: i.compact,
|
|
162
|
+
disabled: i.disabled,
|
|
163
|
+
invalid: i.invalid,
|
|
164
|
+
clearable: i.clearable,
|
|
165
|
+
"clear-visible": V.value,
|
|
166
|
+
"clear-label": b(A).fileInput.clear,
|
|
167
|
+
"icon-end": ve.value,
|
|
168
|
+
"icon-end-label": b(A).fileInput.attach,
|
|
169
|
+
"aria-describedby": K.value,
|
|
170
|
+
"onClick:iconEnd": b(L),
|
|
171
|
+
onClear: xe,
|
|
172
|
+
onKeydown: be
|
|
173
|
+
}), le({ _: 2 }, [B.value === "chip" ? {
|
|
174
|
+
name: "start",
|
|
175
|
+
fn: S(() => [(h(!0), s(se, null, _(T.value, (t, n) => v(e.$slots, "chip", {
|
|
176
|
+
file: t,
|
|
177
|
+
index: n,
|
|
178
|
+
label: J(t),
|
|
179
|
+
remove: () => Y(n),
|
|
180
|
+
size: q.value.size,
|
|
181
|
+
compact: q.value.compact
|
|
182
|
+
}, () => [u(ne, {
|
|
183
|
+
tone: "accent",
|
|
184
|
+
size: q.value.size,
|
|
185
|
+
compact: q.value.compact,
|
|
186
|
+
dismissible: !i.readonly && !i.disabled,
|
|
187
|
+
"dismiss-label": b(A).fileInput.remove(t.name),
|
|
188
|
+
disabled: i.disabled,
|
|
189
|
+
title: J(t) === t.name ? void 0 : t.name,
|
|
190
|
+
onDismiss: (e) => Y(n)
|
|
191
|
+
}, {
|
|
192
|
+
default: S(() => [l(y(J(t)), 1)]),
|
|
193
|
+
_: 2
|
|
194
|
+
}, 1032, [
|
|
195
|
+
"size",
|
|
196
|
+
"compact",
|
|
197
|
+
"dismissible",
|
|
198
|
+
"dismiss-label",
|
|
199
|
+
"disabled",
|
|
200
|
+
"title",
|
|
201
|
+
"onDismiss"
|
|
202
|
+
])], void 0, `${n}-${t.name}`)), 128))]),
|
|
203
|
+
key: "0"
|
|
204
|
+
} : void 0]), 1040, [
|
|
205
|
+
"model-value",
|
|
206
|
+
"label",
|
|
207
|
+
"placeholder",
|
|
208
|
+
"size",
|
|
209
|
+
"compact",
|
|
210
|
+
"disabled",
|
|
211
|
+
"invalid",
|
|
212
|
+
"clearable",
|
|
213
|
+
"clear-visible",
|
|
214
|
+
"clear-label",
|
|
215
|
+
"icon-end",
|
|
216
|
+
"icon-end-label",
|
|
217
|
+
"aria-describedby",
|
|
218
|
+
"onClick:iconEnd"
|
|
219
|
+
])]),
|
|
220
|
+
i.hint || i.counter ? (h(), s("div", me, [i.hint ? (h(), ce(n, {
|
|
221
|
+
key: 0,
|
|
222
|
+
id: b(W),
|
|
223
|
+
variant: "caption",
|
|
224
|
+
tone: "muted",
|
|
225
|
+
class: "v-file-input-hint"
|
|
226
|
+
}, {
|
|
227
|
+
default: S(() => [l(y(i.hint), 1)]),
|
|
228
|
+
_: 1
|
|
229
|
+
}, 8, ["id"])) : o("", !0), i.counter ? (h(), s("span", {
|
|
230
|
+
key: 1,
|
|
231
|
+
id: b(G),
|
|
232
|
+
class: "v-file-input-counter"
|
|
233
|
+
}, [v(e.$slots, "counter", {
|
|
234
|
+
count: T.value.length,
|
|
235
|
+
size: H.value,
|
|
236
|
+
text: U.value
|
|
237
|
+
}, () => [l(y(U.value), 1)])], 8, he)) : o("", !0)])) : o("", !0)
|
|
238
|
+
], 46, fe));
|
|
239
|
+
}
|
|
240
|
+
});
|
|
241
|
+
//#endregion
|
|
242
|
+
export { C as default };
|
|
243
|
+
|
|
244
|
+
//# sourceMappingURL=VFileInput.vue_vue_type_script_setup_true_lang.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"VFileInput.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../src/components/VFileInput/VFileInput.vue"],"sourcesContent":["<script setup lang=\"ts\">\n// @core\n/**\n * Choosing files, presented as an ordinary form field: a read-only text field showing\n * what was picked, with the real file input hidden behind it. It is the shape of a\n * read-only date picker, without the panel.\n *\n * What was chosen is reported as a plain list of files, which is what lets a consumer\n * build whatever preview they like from it.\n *\n * The JavaScript here is imposed by the platform rather than chosen. A file dialog opens\n * ONLY from a real click on a real file input, and the list of files it holds cannot be\n * written from a template — so the visible field can never BE the native control, and\n * that control can only ever be a SOURCE of files, never a mirror of the value.\n *\n * Everything else follows from those two facts: the clicks and keys relayed to the\n * hidden input, the reset of that input after every change — without which the same file\n * cannot be picked twice in a row — and the screening of incoming files in code, since\n * the `accept` attribute has no say whatsoever over a drop.\n */\nimport { computed, ref, useId, watchEffect } from 'vue'\n\nimport VChip from '../VChip/VChip.vue'\nimport { attach_file as attachFileIcon } from '../VIcon/icons/attach_file'\nimport type { IconSource } from '../VIcon/types'\nimport VInput from '../VInput/VInput.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 { chipScaleFor } from '../../utils/chip'\nimport { isDev } from '../../utils/env'\nimport { formatBytes } from '../../utils/file'\nimport { truncateMiddle } from './truncate'\n\n/** How the chosen files are shown inside the field when several are allowed. */\nexport type FileInputDisplay = 'text' | 'chip'\n\n/** Why a file was turned away: its kind, its size, how many there already are, or the total. */\nexport type FileInputRejectReason = 'type' | 'size' | 'count' | 'total-size'\n\n/** One file that was turned away, and the reason it was. */\nexport interface FileInputRejection {\n /** The file itself, so a message can name it. */\n file: File\n /** What it fell foul of. */\n reason: FileInputRejectReason\n}\n\ninterface FileInputProps {\n /** Allows several files to be chosen. 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 * file DROPPED on the component — the attribute has no say over a drop.\n */\n accept?: string\n /**\n * How the chosen files are shown: their names joined by commas, or one dismissible\n * chip each. It only means something when several files are allowed; a single name is\n * always text.\n */\n display?: FileInputDisplay\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 chosen at most. */\n maxFiles?: number\n /** Shows how much has been chosen under the field: \"3 files (1.2 MB)\". */\n counter?: boolean\n /** The icon at the end of the field, which opens the file dialog. */\n attachIcon?: IconSource\n /** Accepts files dropped onto the component, as well as chosen through the dialog. */\n droppable?: boolean\n /** The height of the field: 32, 40 or 48 pixels. */\n size?: 'sm' | 'md' | 'lg'\n /** Takes 4px off the height, leaving the padding, the text and the icons as they are. */\n compact?: boolean\n /** Makes the field unusable, greyed out through the colour tokens. */\n disabled?: boolean\n /**\n * Shows what was chosen without allowing it to change: no dialog, no drop, no removal.\n */\n readonly?: boolean\n /**\n * Marks the field as invalid — for a rule of your own, since nothing here is checked\n * by the browser.\n */\n invalid?: boolean\n /** The label above the field, tied to it so that clicking it focuses the field. */\n label?: string\n /**\n * A line of help under the field, to the left of the counter. It is tied to the field\n * for assistive technology.\n */\n hint?: string\n /**\n * What the field says while nothing is chosen. It falls back to the design system\n * dictionary.\n */\n placeholder?: string\n /** Offers a cross that empties the selection. */\n clearable?: boolean\n}\n\ndefineOptions({ inheritAttrs: false })\n\nconst props = withDefaults(defineProps<FileInputProps>(), {\n multiple: false,\n accept: undefined,\n display: 'text',\n maxSize: undefined,\n maxTotalSize: undefined,\n maxFiles: undefined,\n counter: false,\n attachIcon: () => attachFileIcon,\n droppable: true,\n size: 'md',\n compact: false,\n disabled: false,\n readonly: false,\n invalid: false,\n label: undefined,\n hint: undefined,\n placeholder: undefined,\n // On by default, unlike an ordinary field: what is in a picker cannot be erased by\n // typing, so without the cross there would be no way to empty it — the same reasoning\n // as in a read-only date picker.\n clearable: true,\n})\n\nconst emit = defineEmits<{\n /** The reader changed the selection — added something, removed something, cleared it. */\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: FileInputRejection]\n /** The clear cross emptied the selection. */\n clear: []\n}>()\n\ndefineSlots<{\n /**\n * Replaces the chip standing for one file.\n *\n * Three of the values it receives are what make it usable without regressions:\n * `label` is the name already shortened in the MIDDLE so that its extension survives,\n * `remove` is what takes the file out — without it the file could no longer be removed\n * at all — and the size and density are the ones worked out to sit inside the field,\n * which cannot be guessed from outside.\n */\n chip?(props: {\n file: File\n index: number\n label: string\n remove: () => void\n size: 'xs' | 'sm'\n compact: boolean\n }): unknown\n /**\n * Replaces the counter under the field. `text` is the sentence already built and\n * translated; the count and the total size are there for a wording of your own.\n */\n counter?(props: { count: number; size: number; text: 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\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 VFilePicker.\n *\n * Here, the bucket meant for \"the control the user deals with\" goes to the visible\n * field: that is what they see, focus and click, so a consumer's own `<label for>` has\n * to point at it. The description attribute is pulled out of that bucket, because this\n * component re-assembles it further down.\n */\nconst {\n fileEl,\n nativeAttrs,\n controlAttrs: fieldAttrs,\n acceptFiles,\n onNativeChange,\n openPicker,\n resetNative,\n} = useFileField({\n model,\n forwardedAttrs,\n enabled: () => !props.disabled && !props.readonly,\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 excludeFromControl: ['aria-describedby'],\n})\n\nconst inputRef = ref<InstanceType<typeof VInput> | null>(null)\n\n// Chips only mean something for a list: a single file always shows as plain text.\nconst resolvedDisplay = computed<FileInputDisplay>(() => (props.multiple ? props.display : 'text'))\n\nconst displayText = computed(() =>\n resolvedDisplay.value === 'chip' ? '' : model.value.map((file) => file.name).join(', '),\n)\n\nconst placeholderText = computed(() =>\n model.value.length > 0 ? undefined : (props.placeholder ?? m.value.fileInput.placeholder),\n)\n\n/*\n * Whether the clear cross is shown has to be answered EXPLICITLY here. The visible field\n * is read-only, and a read-only field hides its cross by default — rightly so, since its\n * text cannot be edited. Here the value comes from the file dialog rather than from\n * typing, so there is something to clear all the same.\n */\nconst canClear = computed(\n () => props.clearable && !props.disabled && !props.readonly && model.value.length > 0,\n)\n\n// @a11y @devwarn\n/*\n * The icon disappears along with what it offers: a read-only field opens no dialog, so\n * an icon inviting one would be a lie — the same rule VDateInput follows for its\n * calendar.\n *\n * TRAP — its LABEL stays defined at all times, even when no icon is rendered. The helper\n * that detects a click handler on an icon warns AT SETUP if one is attached without a\n * label, and it has no way of knowing whether an icon exists.\n */\nconst endIcon = computed<IconSource | undefined>(() =>\n props.readonly ? undefined : props.attachIcon,\n)\n\nconst totalSize = computed(() => model.value.reduce((sum, file) => sum + file.size, 0))\n\n/*\n * The counter is assembled from three sources: the WORD comes from the dictionary, since\n * it is language; the SIZE is formatted by the platform, which knows the local\n * conventions; and the parentheses come from neither, being punctuation every language\n * shares — the same boundary VBadge's \"99+\" falls on.\n *\n * With nothing chosen it states the count alone: \"0 files ()\" would be noise.\n */\nconst counterText = computed(() => {\n const word = m.value.fileInput.files(model.value.length)\n return model.value.length === 0 ? word : `${word} (${formatBytes(totalSize.value, locale.value)})`\n})\n\nconst hintId = useId()\nconst counterId = useId()\n\n// @a11y\n/*\n * What describes the field for a screen reader is a LIST of references, assembled here\n * rather than by VInput: the hint belongs to OUR row under the field, VInput having no\n * such row — its own counter sits inside the field.\n *\n * The counter is deliberately part of that list, unlike in VTextarea. When the files are\n * shown as chips the field's own text is EMPTY, and the counter is then the only spoken\n * summary of what has been chosen.\n */\nconst describedBy = computed(\n () =>\n [\n attrs['aria-describedby'] as string | undefined,\n props.hint ? hintId : undefined,\n props.counter ? counterId : undefined,\n ]\n .filter(Boolean)\n .join(' ') || undefined,\n)\n\n// The size, the density and the HEIGHT of the chips sitting inside the field, worked out\n// once in `utils/chip.ts` and shared with VCombobox. The height is set inline rather than\n// restated as a table of CSS rules: it belongs to the chips' own subtree, out of the\n// field's reach, and the field has to force its input to that same height or it grows\n// when focused.\nconst chipScale = computed(() => chipScaleFor(props.size, props.compact))\n\n/**\n * What a chip shows for a file. The name is shortened in the MIDDLE rather than cut off\n * at the end, for two reasons.\n *\n * The chips WRAP, so there is no line for a long name to overflow: left whole it would\n * simply push the field onto two or three rows. And cutting the middle preserves the\n * extension, which is what tells the reader what kind of file it is — an ellipsis at the\n * end drops it first.\n *\n * The full name is never lost: the removal button is named with it, and the chip carries\n * it as a tooltip whenever the label was actually shortened.\n */\nconst chipLabel = (file: File) => truncateMiddle(file.name)\n\nfunction onControlClick(event: MouseEvent) {\n // The field's own buttons already handle their clicks, and the click also reaches the\n // field itself. Without this guard the attach icon would open the dialog TWICE, and\n // the clear cross would reopen it immediately after emptying the selection.\n if ((event.target as HTMLElement).closest('button')) return\n openPicker()\n}\n\nfunction onFieldKeydown(event: KeyboardEvent) {\n if (event.key !== 'Enter' && event.key !== ' ') return\n // Cancelling the default on Enter also stops the form from being submitted: a\n // read-only text field is still a field, and Enter in one submits the form around it.\n event.preventDefault()\n openPicker()\n}\n\nfunction removeAt(index: number) {\n model.value = model.value.filter((_, i) => i !== index)\n resetNative()\n emit('change', model.value)\n // The removal button disappears along with its chip, so the focus would fall back to\n // the page body. Unlike the date and time pickers, nothing here opens on focus, so\n // this needs no guard against re-entering.\n inputRef.value?.focus()\n}\n\n/**\n * Empties the selection, and the hidden input with it — without that reset the same file\n * could not be chosen again straight afterwards.\n */\nfunction clearValue() {\n model.value = []\n resetNative()\n emit('clear')\n emit('change', model.value)\n}\n\n/* Files may be dropped on the component itself; there is no separate drop area here —\n that is what VFilePicker is for. */\nconst { dragging, onDragEnter, onDragOver, onDragLeave, onDrop } = useFileDrop(\n () => props.droppable && !props.disabled && !props.readonly,\n acceptFiles,\n)\n\n// @devwarn\nif (isDev) {\n watchEffect(() => {\n if (props.display === 'chip' && !props.multiple)\n console.warn(\n '[VFileInput] display=\"chip\" ignored without `multiple`: a single file shows as text.',\n )\n if (props.maxFiles !== undefined && !props.multiple)\n console.warn(\n '[VFileInput] `maxFiles` ignored without `multiple`: single mode already caps at one file.',\n )\n if (attrs.required !== undefined)\n console.warn(\n '[VFileInput] `required` lands on the hidden file input, which is not focusable: the browser blocks submission with no visible message. Validate the v-model yourself and use the `invalid` prop.',\n )\n })\n}\n\ndefineExpose({\n /** Moves the focus to the visible field. */\n focus: (options?: FocusOptions) => inputRef.value?.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-input\"\n :class=\"rootClass\"\n :style=\"[{ '--chip-height': chipScale.height }, rootStyle]\"\n :data-size=\"size\"\n :data-compact=\"compact ? '' : undefined\"\n :data-display=\"resolvedDisplay\"\n :data-disabled=\"disabled ? '' : undefined\"\n :data-readonly=\"readonly ? '' : undefined\"\n :data-dragging=\"dragging ? '' : undefined\"\n :data-can-clear=\"canClear ? '' : 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-input-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 <div class=\"v-file-input-control\" @click=\"onControlClick\">\n <VInput\n v-bind=\"fieldAttrs\"\n ref=\"inputRef\"\n :model-value=\"displayText\"\n readonly\n :label=\"label\"\n :placeholder=\"placeholderText\"\n :size=\"size\"\n :compact=\"compact\"\n :disabled=\"disabled\"\n :invalid=\"invalid\"\n :clearable=\"clearable\"\n :clear-visible=\"canClear\"\n :clear-label=\"m.fileInput.clear\"\n :icon-end=\"endIcon\"\n :icon-end-label=\"m.fileInput.attach\"\n :aria-describedby=\"describedBy\"\n @click:icon-end=\"openPicker\"\n @clear=\"clearValue\"\n @keydown=\"onFieldKeydown\"\n >\n <template v-if=\"resolvedDisplay === 'chip'\" #start>\n <template v-for=\"(file, index) in model\" :key=\"`${index}-${file.name}`\">\n <slot\n name=\"chip\"\n :file=\"file\"\n :index=\"index\"\n :label=\"chipLabel(file)\"\n :remove=\"() => removeAt(index)\"\n :size=\"chipScale.size\"\n :compact=\"chipScale.compact\"\n >\n <VChip\n tone=\"accent\"\n :size=\"chipScale.size\"\n :compact=\"chipScale.compact\"\n :dismissible=\"!readonly && !disabled\"\n :dismiss-label=\"m.fileInput.remove(file.name)\"\n :disabled=\"disabled\"\n :title=\"chipLabel(file) === file.name ? undefined : file.name\"\n @dismiss=\"removeAt(index)\"\n >{{ chipLabel(file) }}</VChip\n >\n </slot>\n </template>\n </template>\n </VInput>\n </div>\n\n <div v-if=\"hint || counter\" class=\"v-file-input-meta\">\n <VTypography\n v-if=\"hint\"\n :id=\"hintId\"\n variant=\"caption\"\n tone=\"muted\"\n class=\"v-file-input-hint\"\n >\n {{ hint }}\n </VTypography>\n <span v-if=\"counter\" :id=\"counterId\" class=\"v-file-input-counter\">\n <slot name=\"counter\" :count=\"model.length\" :size=\"totalSize\" :text=\"counterText\">\n {{ counterText }}\n </slot>\n </span>\n </div>\n </div>\n</template>\n\n<style>\n@layer vectis.components {\n /* Positioned so the hidden file input, which has no size at all, has something to be\n placed against. */\n .v-file-input {\n position: relative;\n display: flex;\n flex-direction: column;\n gap: var(--vectis-space-1);\n width: 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 field. Taking it\n out of the tab order and hiding it from screen readers, in the template, is what\n leaves the visible field as the single stop and the single announcement. */\n .v-file-input-native {\n position: absolute;\n inline-size: 0;\n block-size: 0;\n opacity: 0;\n pointer-events: none;\n }\n\n .v-file-input:not([data-disabled]):not([data-readonly]) .v-file-input-control,\n .v-file-input:not([data-disabled]):not([data-readonly])[data-display='text'] .v-input-control {\n cursor: pointer;\n }\n\n /* An ellipsis DOES work on an input, and a read-only one never scrolls by itself, so a\n long list of names is simply cut short. No tooltip is added for the rest: it would be\n announced as a description repeating the value the field already shows, and the\n complete list is what the model is for. */\n .v-file-input[data-display='text'] .v-input-control {\n text-overflow: ellipsis;\n }\n\n /* While a file is being dragged over it, the field is highlighted by redefining the\n very variable VInput uses for its own border colour — so the two can never disagree.\n The selector is one step more specific than VInput's, which is what makes it win\n whatever order the two sheets end up in. */\n .v-file-input[data-dragging] .v-input-field {\n --field-border-color: var(--vectis-color-accent);\n\n background: var(--vectis-color-accent-surface);\n }\n\n /* Shown as chips, the field holds them and lets them WRAP onto several rows, so it\n grows instead of scrolling.\n\n Two things have to be forced for that to hold together. The input inside is given\n the chips' own height rather than the full height it inherits, or its natural height\n would stretch every row it shares. And the padding at the end reserves exactly the\n room the icons take, since those are lifted out of the wrapping flow just below.\n\n That reservation is written as what the flow itself produces when the files are\n shown as text and nothing is lifted out: one glyph's width per action from the\n field's padding, one gap between two of them. It reads from the same two variables\n as the insets further down, so the room reserved and the glyphs it protects cannot\n drift apart. */\n .v-file-input[data-display='chip'] .v-input-field {\n position: relative;\n flex-wrap: wrap;\n height: auto;\n min-height: var(--control-height);\n padding-block: var(--vectis-space-1);\n padding-inline-end: calc(\n var(--control-padding-inline-field) + var(--vectis-icon-size) + var(--control-gap)\n );\n }\n\n .v-file-input[data-display='chip'][data-can-clear] .v-input-field {\n padding-inline-end: calc(\n var(--control-padding-inline-field) + 2 * var(--vectis-icon-size) + 2 * var(--control-gap)\n );\n }\n\n .v-file-input[data-display='chip'] .v-input-control {\n height: var(--chip-height);\n }\n\n /* The two icons are lifted out of the wrapping flow — the same recipe VCombobox uses —\n so that they stay pinned to the end of the field and vertically centred whatever the\n chips do. VInput renders the clear cross FIRST and the end icon after it, which is\n why the icon has to be addressed by excluding the cross. */\n .v-file-input[data-display='chip'] .v-input-clear,\n .v-file-input[data-display='chip'] .v-input-action:not(.v-input-clear) {\n position: absolute;\n top: 50%;\n translate: 0 -50%;\n }\n\n .v-file-input[data-display='chip'] .v-input-action:not(.v-input-clear) {\n inset-inline-end: var(--control-padding-inline-field);\n }\n\n /* This is the ONE place where the spacing between the two icons has to be written by\n hand. Everywhere else the field's own flow produces it for free, and the two must\n agree, or the same component would show two different gaps depending on how the\n files are displayed.\n\n So it is written as exactly what that flow produces: the end icon occupies one\n glyph's width from the field's padding, then one gap separates the two.\n\n TRAP — this reads in GLYPHS and not in buttons. VInput gives its inner buttons a\n negative margin equal to half the difference between the two, which makes an inset\n land on the glyph's edge rather than on the button's. Measuring in button widths\n instead pushes the cross a whole gap too far, with nothing anywhere to signal it. */\n .v-file-input[data-display='chip'] .v-input-clear {\n inset-inline-end: calc(\n var(--control-padding-inline-field) + var(--vectis-icon-size) + var(--control-gap)\n );\n }\n\n .v-file-input-meta {\n display: flex;\n align-items: baseline;\n gap: var(--vectis-space-2);\n }\n\n /* The counter stays styled locally: tabular-nums is not a typographic role.\n No overflow state — an over-limit file never enters the model, so the\n counter cannot overflow. */\n .v-file-input-counter {\n margin-inline-start: auto;\n font-size: var(--vectis-text-caption-size);\n color: var(--vectis-color-text-muted);\n font-variant-numeric: tabular-nums;\n }\n\n .v-file-input[data-disabled] .v-file-input-hint,\n .v-file-input[data-disabled] .v-file-input-counter {\n color: var(--vectis-color-text-subtle);\n }\n}\n</style>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAiHA,IAAM,IAAQ,GAwBR,IAAO,GA2CP,IAAQ,GAAmB,GAAA,YAAsB,GAEjD,EAAE,UAAO,cAAW,cAAW,sBAAmB,GAAa,GAE/D,IAAI,EAAY,GAChB,IAAS,EAAU,GAWnB,EACJ,WACA,gBACA,cAAc,GACd,gBACA,mBACA,eACA,mBACE,GAAa;GACf;GACA;GACA,eAAe,CAAC,EAAM,YAAY,CAAC,EAAM;GACzC,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;GACzC,oBAAoB,CAAC,kBAAkB;EACzC,CAAC,GAEK,IAAW,EAAwC,IAAI,GAGvD,IAAkB,QAAkC,EAAM,WAAW,EAAM,UAAU,MAAO,GAE5F,KAAc,QAClB,EAAgB,UAAU,SAAS,KAAK,EAAM,MAAM,KAAK,MAAS,EAAK,IAAI,CAAC,CAAC,KAAK,IAAI,CACxF,GAEM,KAAkB,QACtB,EAAM,MAAM,SAAS,IAAI,KAAA,IAAa,EAAM,eAAe,EAAE,MAAM,UAAU,WAC/E,GAQM,IAAW,QACT,EAAM,aAAa,CAAC,EAAM,YAAY,CAAC,EAAM,YAAY,EAAM,MAAM,SAAS,CACtF,GAYM,KAAU,QACd,EAAM,WAAW,KAAA,IAAY,EAAM,UACrC,GAEM,IAAY,QAAe,EAAM,MAAM,QAAQ,GAAK,MAAS,IAAM,EAAK,MAAM,CAAC,CAAC,GAUhF,IAAc,QAAe;GACjC,IAAM,IAAO,EAAE,MAAM,UAAU,MAAM,EAAM,MAAM,MAAM;GACvD,OAAO,EAAM,MAAM,WAAW,IAAI,IAAO,GAAG,EAAK,IAAI,GAAY,EAAU,OAAO,EAAO,KAAK,EAAE;EAClG,CAAC,GAEK,IAAS,EAAM,GACf,IAAY,EAAM,GAYlB,IAAc,QAEhB;GACE,EAAM;GACN,EAAM,OAAO,IAAS,KAAA;GACtB,EAAM,UAAU,IAAY,KAAA;EAC9B,CAAA,CACG,OAAO,OAAO,CAAA,CACd,KAAK,GAAG,KAAK,KAAA,CACpB,GAOM,IAAY,QAAe,EAAa,EAAM,MAAM,EAAM,OAAO,CAAC,GAclE,KAAa,MAAe,GAAe,EAAK,IAAI;EAE1D,SAAS,GAAe,GAAmB;GAIpC,EAAM,OAAuB,QAAQ,QAAQ,KAClD,EAAW;EACb;EAEA,SAAS,GAAe,GAAsB;GACxC,EAAM,QAAQ,WAAW,EAAM,QAAQ,QAG3C,EAAM,eAAe,GACrB,EAAW;EACb;EAEA,SAAS,EAAS,GAAe;GAO/B,AANA,EAAM,QAAQ,EAAM,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAK,GACtD,EAAY,GACZ,EAAK,UAAU,EAAM,KAAK,GAI1B,EAAS,OAAO,MAAM;EACxB;EAMA,SAAS,KAAa;GAIpB,AAHA,EAAM,QAAQ,CAAC,GACf,EAAY,GACZ,EAAK,OAAO,GACZ,EAAK,UAAU,EAAM,KAAK;EAC5B;EAIA,IAAM,EAAE,cAAU,gBAAa,eAAY,gBAAa,cAAW,SAC3D,EAAM,aAAa,CAAC,EAAM,YAAY,CAAC,EAAM,UACnD,CACF;SAoBA,EAAa;GAEX,QAAQ,MAA2B,EAAS,OAAO,MAAM,CAAO;GAKhE,MAAM;EACR,CAAC,mBAIC,EA+FM,OAAA;GA9FJ,OAAK,GAAA,CAAC,gBACE,EAAA,CAAA,CAAS,CAAA;GAChB,OAAK,EAAA,CAAA,EAAA,iBAAsB,EAAA,MAAU,OAAM,GAAI,EAAA,CAAA,CAAS,CAAA;GACxD,aAAW,EAAA;GACX,gBAAc,EAAA,UAAO,KAAQ,KAAA;GAC7B,gBAAc,EAAA;GACd,iBAAe,EAAA,WAAQ,KAAQ,KAAA;GAC/B,iBAAe,EAAA,WAAQ,KAAQ,KAAA;GAC/B,iBAAe,EAAA,EAAA,IAAQ,KAAQ,KAAA;GAC/B,kBAAgB,EAAA,QAAQ,KAAQ,KAAA;GAChC,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;;GAEP,EAWE,SAXF,EACU,EAUR,CAAA,GAVmB;aACf;IAAJ,KAAI;IACJ,MAAK;IACL,OAAM;IACN,UAAS;IACT,eAAY;IACX,QAAQ,EAAA;IACR,UAAU,EAAA,YAAY,KAAA;IACtB,UAAU,EAAA,YAAY,KAAA;IACtB,UAAM,AAAA,EAAA,QAAA,GAAA,MAAE,EAAA,CAAA,KAAA,EAAA,CAAA,CAAA,CAAA,GAAA,CAAA;;GAGX,EAgDM,OAAA;IAhDD,OAAM;IAAwB,SAAO;OACxC,EA8CS,IA9CT,EACU,EA6CD,CAAA,GA7CW;aACd;IAAJ,KAAI;IACH,eAAa,GAAA;IACd,UAAA;IACC,OAAO,EAAA;IACP,aAAa,GAAA;IACb,MAAM,EAAA;IACN,SAAS,EAAA;IACT,UAAU,EAAA;IACV,SAAS,EAAA;IACT,WAAW,EAAA;IACX,iBAAe,EAAA;IACf,eAAa,EAAA,CAAA,CAAC,CAAC,UAAU;IACzB,YAAU,GAAA;IACV,kBAAgB,EAAA,CAAA,CAAC,CAAC,UAAU;IAC5B,oBAAkB,EAAA;IAClB,mBAAgB,EAAA,CAAA;IAChB,SAAO;IACP,WAAS;qBAEM,EAAA,UAAe,SAAA;UAAc;gBACH,EAAA,EAAA,EAAA,GAAxC,EAsBW,IAAA,MAAA,EAtBuB,EAAA,QAAhB,GAAM,MACtB,EAoBO,EAAA,QAAA,QAAA;KAlBE;KACC;KACP,OAAO,EAAU,CAAI;KACrB,cAAc,EAAS,CAAK;KAC5B,MAAM,EAAA,MAAU;KAChB,SAAS,EAAA,MAAU;aAaf,CAXL,EAUC,IAAA;KATC,MAAK;KACJ,MAAM,EAAA,MAAU;KAChB,SAAS,EAAA,MAAU;KACnB,aAAW,CAAG,EAAA,YAAQ,CAAK,EAAA;KAC3B,iBAAe,EAAA,CAAA,CAAC,CAAC,UAAU,OAAO,EAAK,IAAI;KAC3C,UAAU,EAAA;KACV,OAAO,EAAU,CAAI,MAAM,EAAK,OAAO,KAAA,IAAY,EAAK;KACxD,YAAO,MAAE,EAAS,CAAK;;sBACF,CAAA,EAAA,EAAlB,EAAU,CAAI,CAAA,GAAA,CAAA,CAAA,CAAA;;;;;;;;;;oBAnB0B,EAAK,GAAI,EAAK,MAAI;;;;;;;;;;;;;;;;;;GA2B/D,EAAA,QAAQ,EAAA,WAAA,EAAA,GAAnB,EAeM,OAfN,IAeM,CAbI,EAAA,QAAA,EAAA,GADR,GAQc,GAAA;;IANX,IAAI,EAAA,CAAA;IACL,SAAQ;IACR,MAAK;IACL,OAAM;;qBAEI,CAAA,EAAA,EAAP,EAAA,IAAI,GAAA,CAAA,CAAA,CAAA;;+BAEG,EAAA,WAAA,EAAA,GAAZ,EAIO,QAAA;;IAJe,IAAI,EAAA,CAAA;IAAW,OAAM;OACzC,EAEO,EAAA,QAAA,WAAA;IAFe,OAAO,EAAA,MAAM;IAAS,MAAM,EAAA;IAAY,MAAM,EAAA;YAE7D,CAAA,EAAA,EADF,EAAA,KAAW,GAAA,CAAA,CAAA,CAAA,CAAA,GAAA,GAAA,EAAA,KAAA,EAAA,IAAA,EAAA,CAAA,CAAA,KAAA,EAAA,IAAA,EAAA"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Middle truncation, for text whose END carries as much meaning as its start.
|
|
3
|
+
* A file name is the canonical case: `text-overflow: ellipsis` would drop the
|
|
4
|
+
* extension, which is often the only thing distinguishing two entries
|
|
5
|
+
* (`invoice.pdf` and `invoice.png`), and the tail is also where the version or
|
|
6
|
+
* date suffixes live.
|
|
7
|
+
*
|
|
8
|
+
* Pure, no Vue — the `VHotkeys/platform.ts` precedent: a single consumer, so it
|
|
9
|
+
* stays in the component's folder. Deliberately NOT promoted alongside the file
|
|
10
|
+
* helpers of `utils/file.ts`: cutting a string is a lexical operation, not
|
|
11
|
+
* something the FILE domain decides — `utils/text.ts` is where it would go the
|
|
12
|
+
* day a second consumer appears.
|
|
13
|
+
*/
|
|
14
|
+
/** Ceiling of a chip's label, ellipsis included. Chips wrap, so the point is not
|
|
15
|
+
the field's width but keeping a row readable at a glance. */
|
|
16
|
+
export declare const CHIP_NAME_MAX = 20;
|
|
17
|
+
/**
|
|
18
|
+
* `truncateMiddle('annual_report_2026_final.pdf')` → `annual_rep…_final.pdf`.
|
|
19
|
+
*
|
|
20
|
+
* The result is EXACTLY `max` characters long: the ellipsis takes one of them,
|
|
21
|
+
* and the odd one goes to the head — the start of a name is what makes it
|
|
22
|
+
* recognizable, the end is what disambiguates it.
|
|
23
|
+
*
|
|
24
|
+
* Counted in CODE POINTS (`[...text]`) and not in UTF-16 units: an emoji in a
|
|
25
|
+
* name would otherwise be cut between its two halves and render as a
|
|
26
|
+
* replacement character. Combining marks stay out of scope — a grapheme
|
|
27
|
+
* segmenter for a chip label would be a lot of machinery for a rounding error.
|
|
28
|
+
*/
|
|
29
|
+
export declare function truncateMiddle(text: string, max?: number): string;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
function e(e, t = 20) {
|
|
2
|
+
let n = [...e];
|
|
3
|
+
if (n.length <= t) return e;
|
|
4
|
+
let r = Math.max(0, t - 1), i = Math.ceil(r / 2), a = r - i;
|
|
5
|
+
return `${n.slice(0, i).join("")}…${n.slice(n.length - a).join("")}`;
|
|
6
|
+
}
|
|
7
|
+
//#endregion
|
|
8
|
+
export { e as truncateMiddle };
|
|
9
|
+
|
|
10
|
+
//# sourceMappingURL=truncate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"truncate.js","names":[],"sources":["../../../src/components/VFileInput/truncate.ts"],"sourcesContent":["/**\n * Middle truncation, for text whose END carries as much meaning as its start.\n * A file name is the canonical case: `text-overflow: ellipsis` would drop the\n * extension, which is often the only thing distinguishing two entries\n * (`invoice.pdf` and `invoice.png`), and the tail is also where the version or\n * date suffixes live.\n *\n * Pure, no Vue — the `VHotkeys/platform.ts` precedent: a single consumer, so it\n * stays in the component's folder. Deliberately NOT promoted alongside the file\n * helpers of `utils/file.ts`: cutting a string is a lexical operation, not\n * something the FILE domain decides — `utils/text.ts` is where it would go the\n * day a second consumer appears.\n */\n\n/** Ceiling of a chip's label, ellipsis included. Chips wrap, so the point is not\n the field's width but keeping a row readable at a glance. */\nexport const CHIP_NAME_MAX = 20\n\n/**\n * `truncateMiddle('annual_report_2026_final.pdf')` → `annual_rep…_final.pdf`.\n *\n * The result is EXACTLY `max` characters long: the ellipsis takes one of them,\n * and the odd one goes to the head — the start of a name is what makes it\n * recognizable, the end is what disambiguates it.\n *\n * Counted in CODE POINTS (`[...text]`) and not in UTF-16 units: an emoji in a\n * name would otherwise be cut between its two halves and render as a\n * replacement character. Combining marks stay out of scope — a grapheme\n * segmenter for a chip label would be a lot of machinery for a rounding error.\n */\nexport function truncateMiddle(text: string, max: number = CHIP_NAME_MAX): string {\n const chars = [...text]\n if (chars.length <= max) return text\n\n const budget = Math.max(0, max - 1)\n const head = Math.ceil(budget / 2)\n const tail = budget - head\n\n return `${chars.slice(0, head).join('')}…${chars.slice(chars.length - tail).join('')}`\n}\n"],"mappings":"AA8BA,SAAgB,EAAe,GAAc,IAAA,IAAqC;CAChF,IAAM,IAAQ,CAAC,GAAG,CAAI;CACtB,IAAI,EAAM,UAAU,GAAK,OAAO;CAEhC,IAAM,IAAS,KAAK,IAAI,GAAG,IAAM,CAAC,GAC5B,IAAO,KAAK,KAAK,IAAS,CAAC,GAC3B,IAAO,IAAS;CAEtB,OAAO,GAAG,EAAM,MAAM,GAAG,CAAI,CAAC,CAAC,KAAK,EAAE,EAAE,GAAG,EAAM,MAAM,EAAM,SAAS,CAAI,CAAC,CAAC,KAAK,EAAE;AACrF"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
@layer vectis.reset, vectis.tokens, vectis.components, vectis.utilities;
|
|
2
|
+
@layer vectis.components{.v-file-picker{--file-picker-border-color:var(--vectis-color-border-strong);--file-picker-bg:var(--vectis-color-surface-sunken);--file-picker-text:var(--vectis-color-text);--file-picker-text-muted:var(--vectis-color-text-muted);--file-picker-row-bg:var(--vectis-color-surface-raised);--file-picker-thumb-bg:var(--vectis-color-surface-muted);inline-size:100%;font-family:var(--vectis-text-family);display:block;position:relative}.v-file-picker-native{opacity:0;pointer-events:none;block-size:0;inline-size:0;position:absolute}.v-file-picker-body{gap:var(--vectis-space-4);flex-direction:column;display:flex}.v-file-picker-zone{justify-content:center;align-items:center;gap:var(--vectis-space-2);inline-size:100%;min-block-size:var(--vectis-control-size-file-picker-min-block);padding:var(--vectis-space-6) var(--vectis-space-4);appearance:none;border:1px dashed var(--file-picker-border-color);border-radius:var(--vectis-radius-surface);background:var(--file-picker-bg);color:var(--file-picker-text);font:inherit;text-align:center;transition:border-color var(--vectis-duration-fast) var(--vectis-ease-default), background-color var(--vectis-duration-fast) var(--vectis-ease-default);flex-direction:column;margin:0;display:flex}.v-file-picker:not([data-disabled]):not([data-readonly]) .v-file-picker-zone{cursor:pointer}.v-file-picker:not([data-disabled]):not([data-readonly]) .v-file-picker-zone:hover{--file-picker-border-color:var(--vectis-color-accent)}.v-file-picker-zone:focus-visible{outline:var(--vectis-focus-ring-width) solid var(--vectis-focus-ring-color);outline-offset:var(--vectis-focus-ring-offset)}.v-file-picker[data-dragging]{--file-picker-border-color:var(--vectis-color-accent);--file-picker-bg:var(--vectis-color-accent-surface)}.v-file-picker-icon{--vectis-icon-size:var(--vectis-control-size-file-picker-icon);color:var(--file-picker-text-muted);display:inline-flex}.v-file-picker-subtitle{--typography-color:var(--file-picker-text-muted)}.v-file-picker-separator{align-items:center;gap:var(--vectis-space-3);inline-size:100%;color:var(--file-picker-text-muted);font-size:var(--vectis-text-caption-size);margin-block-start:var(--vectis-space-2);display:flex}.v-file-picker-separator:before,.v-file-picker-separator:after{content:"";border-block-start:1px solid var(--vectis-color-border);flex:1 1 0}.v-file-picker-list{gap:var(--vectis-space-2);flex-direction:column;margin:0;padding:0;list-style:none;display:flex}.v-file-picker-item{align-items:center;gap:var(--vectis-space-3);padding:var(--vectis-space-2);border:1px solid var(--vectis-color-border);border-radius:var(--vectis-radius-interactive);background:var(--file-picker-row-bg);display:flex}.v-file-picker-thumb{inline-size:var(--vectis-control-size-file-picker-thumb);block-size:var(--vectis-control-size-file-picker-thumb);border-radius:var(--vectis-radius-interactive);background:var(--file-picker-thumb-bg);color:var(--file-picker-text-muted);flex:none;justify-content:center;align-items:center;display:inline-flex;overflow:hidden}.v-file-picker-image{object-fit:cover;block-size:100%;inline-size:100%;display:block}.v-file-picker-info{min-inline-size:0;color:var(--file-picker-text);flex-direction:column;flex:auto;display:flex}.v-file-picker-name{font-size:var(--vectis-text-body-sm-size);white-space:nowrap;text-overflow:ellipsis;overflow:hidden}.v-file-picker-size{color:var(--file-picker-text-muted);font-size:var(--vectis-text-caption-size);font-variant-numeric:tabular-nums}.v-file-picker[data-preview=end]{container:v-file-picker/inline-size}.v-file-picker[data-preview=end] .v-file-picker-body{flex-direction:row;align-items:flex-start}.v-file-picker[data-preview=end] .v-file-picker-zone,.v-file-picker[data-preview=end] .v-file-picker-list{flex:1 1 0;min-inline-size:0}@container v-file-picker (width<=34rem){.v-file-picker[data-preview=end] .v-file-picker-body{flex-direction:column}}.v-file-picker[data-disabled]{--file-picker-border-color:var(--vectis-color-border);--file-picker-bg:var(--vectis-color-surface-muted);--file-picker-text:var(--vectis-color-text-muted);--file-picker-text-muted:var(--vectis-color-text-muted);--file-picker-row-bg:var(--vectis-color-surface-muted)}.v-file-picker[data-readonly]{--file-picker-border-color:var(--vectis-color-border)}@media (prefers-reduced-motion:reduce){.v-file-picker-zone{transition:none}}@media (forced-colors:active){.v-file-picker[data-dragging] .v-file-picker-zone{border-style:solid}.v-file-picker-thumb{border:1px solid}}}
|