vectis-ui 0.12.0 → 0.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/VAccordion/VAccordion.css +1 -1
- package/dist/components/VAccordion/VAccordion.d.ts +6 -5
- package/dist/components/VAccordion/VAccordion.js.map +1 -1
- package/dist/components/VAccordion/VAccordion.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VAccordion/VAccordionItem.css +1 -1
- package/dist/components/VAccordion/VAccordionItem.d.ts +1 -1
- package/dist/components/VAccordion/VAccordionItem.js.map +1 -1
- package/dist/components/VAccordion/VAccordionItem.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VAlert/VAlert.css +2 -0
- package/dist/components/VAlert/VAlert.d.ts +73 -0
- package/dist/components/VAlert/VAlert.js +9 -0
- package/dist/components/VAlert/VAlert.js.map +1 -0
- package/dist/components/VAlert/VAlert.vue_vue_type_script_setup_true_lang.js +96 -0
- package/dist/components/VAlert/VAlert.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VAvatar/VAvatar.d.ts +2 -2
- package/dist/components/VAvatar/VAvatarGroup.d.ts +1 -1
- package/dist/components/VAvatar/VAvatarGroup.vue_vue_type_script_setup_true_lang.js +8 -8
- package/dist/components/VBadge/VBadge.d.ts +3 -3
- package/dist/components/VBreadcrumb/VBreadcrumb.vue_vue_type_script_setup_true_lang.js +9 -9
- package/dist/components/VButton/VButton.d.ts +4 -4
- package/dist/components/VButton/VButtonGroup.css +1 -1
- package/dist/components/VButton/VButtonGroup.d.ts +2 -2
- package/dist/components/VButton/VButtonGroup.js.map +1 -1
- package/dist/components/VButton/VButtonGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VCalendar/VCalendar.css +1 -1
- package/dist/components/VCalendar/VCalendar.d.ts +7 -1
- package/dist/components/VCalendar/VCalendar.js.map +1 -1
- package/dist/components/VCalendar/VCalendar.vue_vue_type_script_setup_true_lang.js +20 -18
- package/dist/components/VCalendar/VCalendar.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VCalendar/VCalendarEvent.js.map +1 -1
- package/dist/components/VCalendar/VCalendarEvent.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VCalendar/VCalendarMonth.css +1 -1
- package/dist/components/VCalendar/VCalendarMonth.d.ts +2 -2
- package/dist/components/VCalendar/VCalendarMonth.js.map +1 -1
- package/dist/components/VCalendar/VCalendarMonth.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VCalendar/VCalendarTimeGrid.css +1 -1
- package/dist/components/VCalendar/VCalendarTimeGrid.d.ts +3 -3
- package/dist/components/VCalendar/VCalendarTimeGrid.js.map +1 -1
- package/dist/components/VCalendar/VCalendarTimeGrid.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VCalendar/VCalendarYear.css +1 -1
- package/dist/components/VCalendar/VCalendarYear.js.map +1 -1
- package/dist/components/VCalendar/VCalendarYear.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VCalendar/gesture.d.ts +1 -16
- package/dist/components/VCalendar/gesture.js +1 -1
- package/dist/components/VCalendar/gesture.js.map +1 -1
- package/dist/components/VCalendar/types.d.ts +2 -0
- package/dist/components/VCard/VCard.css +2 -0
- package/dist/components/VCard/VCard.d.ts +87 -0
- package/dist/components/VCard/VCard.js +9 -0
- package/dist/components/VCard/VCard.js.map +1 -0
- package/dist/components/VCard/VCard.vue_vue_type_script_setup_true_lang.js +103 -0
- package/dist/components/VCard/VCard.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VCarousel/VCarousel.d.ts +1 -1
- package/dist/components/VCarousel/VCarousel.js.map +1 -1
- package/dist/components/VCarousel/VCarousel.vue_vue_type_script_setup_true_lang.js +18 -18
- package/dist/components/VCarousel/VCarousel.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VCheckbox/VCheckMark.css +2 -0
- package/dist/components/VCheckbox/VCheckMark.js +9 -0
- package/dist/components/VCheckbox/VCheckMark.js.map +1 -0
- package/dist/components/VCheckbox/VCheckMark.vue_vue_type_script_setup_true_lang.js +33 -0
- package/dist/components/VCheckbox/VCheckMark.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VCheckbox/VCheckbox.css +1 -1
- package/dist/components/VCheckbox/VCheckbox.d.ts +8 -3
- package/dist/components/VCheckbox/VCheckbox.js.map +1 -1
- package/dist/components/VCheckbox/VCheckbox.vue_vue_type_script_setup_true_lang.js +54 -69
- package/dist/components/VCheckbox/VCheckbox.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VChip/VChip.d.ts +6 -6
- package/dist/components/VChip/VChip.js.map +1 -1
- package/dist/components/VChip/VChip.vue_vue_type_script_setup_true_lang.js +26 -26
- package/dist/components/VChip/VChip.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VColorInput/VColorInput.css +2 -0
- package/dist/components/VColorInput/VColorInput.d.ts +113 -0
- package/dist/components/VColorInput/VColorInput.js +9 -0
- package/dist/components/VColorInput/VColorInput.js.map +1 -0
- package/dist/components/VColorInput/VColorInput.vue_vue_type_script_setup_true_lang.js +230 -0
- package/dist/components/VColorInput/VColorInput.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VColorPicker/VColorPicker.css +2 -0
- package/dist/components/VColorPicker/VColorPicker.d.ts +67 -0
- package/dist/components/VColorPicker/VColorPicker.js +9 -0
- package/dist/components/VColorPicker/VColorPicker.js.map +1 -0
- package/dist/components/VColorPicker/VColorPicker.vue_vue_type_script_setup_true_lang.js +390 -0
- package/dist/components/VColorPicker/VColorPicker.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VColorPicker/color.d.ts +42 -0
- package/dist/components/VColorPicker/color.js +158 -0
- package/dist/components/VColorPicker/color.js.map +1 -0
- package/dist/components/VCombobox/VCombobox.css +1 -1
- package/dist/components/VCombobox/VCombobox.d.ts +46 -60
- package/dist/components/VCombobox/VCombobox.js.map +1 -1
- package/dist/components/VCombobox/VCombobox.vue_vue_type_script_setup_true_lang.js +271 -372
- package/dist/components/VCombobox/VCombobox.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VCommandPalette/VCommandPalette.css +2 -0
- package/dist/components/VCommandPalette/VCommandPalette.d.ts +163 -0
- package/dist/components/VCommandPalette/VCommandPalette.js +9 -0
- package/dist/components/VCommandPalette/VCommandPalette.js.map +1 -0
- package/dist/components/VCommandPalette/VCommandPalette.vue_vue_type_script_setup_true_lang.js +321 -0
- package/dist/components/VCommandPalette/VCommandPalette.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VCommandPalette/VCommandPaletteItem.css +2 -0
- package/dist/components/VCommandPalette/VCommandPaletteItem.d.ts +38 -0
- package/dist/components/VCommandPalette/VCommandPaletteItem.js +9 -0
- package/dist/components/VCommandPalette/VCommandPaletteItem.js.map +1 -0
- package/dist/components/VCommandPalette/VCommandPaletteItem.vue_vue_type_script_setup_true_lang.js +69 -0
- package/dist/components/VCommandPalette/VCommandPaletteItem.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VContextMenu/VContextMenu.css +2 -0
- package/dist/components/VContextMenu/VContextMenu.d.ts +66 -0
- package/dist/components/VContextMenu/VContextMenu.js +9 -0
- package/dist/components/VContextMenu/VContextMenu.js.map +1 -0
- package/dist/components/VContextMenu/VContextMenu.vue_vue_type_script_setup_true_lang.js +148 -0
- package/dist/components/VContextMenu/VContextMenu.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VDataTable/VDataTable.css +1 -1
- package/dist/components/VDataTable/VDataTable.d.ts +41 -16
- package/dist/components/VDataTable/VDataTable.js.map +1 -1
- package/dist/components/VDataTable/VDataTable.vue_vue_type_script_setup_true_lang.js +307 -195
- package/dist/components/VDataTable/VDataTable.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VDateInput/VDateInput.d.ts +27 -7
- package/dist/components/VDateInput/VDateInput.js.map +1 -1
- package/dist/components/VDateInput/VDateInput.vue_vue_type_script_setup_true_lang.js +170 -162
- package/dist/components/VDateInput/VDateInput.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VDatePicker/VDatePicker.d.ts +3 -3
- package/dist/components/VDatePicker/VDatePicker.js.map +1 -1
- package/dist/components/VDatePicker/VDatePicker.vue_vue_type_script_setup_true_lang.js +228 -227
- package/dist/components/VDatePicker/VDatePicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VDatePicker/keyboard.d.ts +7 -7
- package/dist/components/VDatePicker/keyboard.js +8 -6
- package/dist/components/VDatePicker/keyboard.js.map +1 -1
- package/dist/components/VDatePicker/names.js +16 -20
- package/dist/components/VDatePicker/names.js.map +1 -1
- package/dist/components/VDialog/VDialog.d.ts +2 -4
- package/dist/components/VDialog/VDialog.js.map +1 -1
- package/dist/components/VDialog/VDialog.vue_vue_type_script_setup_true_lang.js +46 -77
- package/dist/components/VDialog/VDialog.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VDrawer/VDrawer.css +2 -0
- package/dist/components/VDrawer/VDrawer.d.ts +102 -0
- package/dist/components/VDrawer/VDrawer.js +9 -0
- package/dist/components/VDrawer/VDrawer.js.map +1 -0
- package/dist/components/VDrawer/VDrawer.vue_vue_type_script_setup_true_lang.js +128 -0
- package/dist/components/VDrawer/VDrawer.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VEmptyState/VEmptyState.css +2 -0
- package/dist/components/VEmptyState/VEmptyState.d.ts +43 -0
- package/dist/components/VEmptyState/VEmptyState.js +9 -0
- package/dist/components/VEmptyState/VEmptyState.js.map +1 -0
- package/dist/components/VEmptyState/VEmptyState.vue_vue_type_script_setup_true_lang.js +48 -0
- package/dist/components/VEmptyState/VEmptyState.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VField/VField.css +2 -0
- package/dist/components/VField/VField.d.ts +84 -0
- package/dist/components/VField/VField.js +9 -0
- package/dist/components/VField/VField.js.map +1 -0
- package/dist/components/VField/VField.vue_vue_type_script_setup_true_lang.js +99 -0
- package/dist/components/VField/VField.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VField/VFieldAnnouncer.d.ts +7 -0
- package/dist/components/VField/VFieldAnnouncer.js +7 -0
- package/dist/components/VField/VFieldAnnouncer.js.map +1 -0
- package/dist/components/VField/VFieldAnnouncer.vue_vue_type_script_setup_true_lang.js +19 -0
- package/dist/components/VField/VFieldAnnouncer.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VField/VFieldMessage.d.ts +11 -0
- package/dist/components/VField/VFieldMessage.js +7 -0
- package/dist/components/VField/VFieldMessage.js.map +1 -0
- package/dist/components/VField/VFieldMessage.vue_vue_type_script_setup_true_lang.js +32 -0
- package/dist/components/VField/VFieldMessage.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VFieldset/VFieldset.css +2 -0
- package/dist/components/VFieldset/VFieldset.d.ts +52 -0
- package/dist/components/VFieldset/VFieldset.js +9 -0
- package/dist/components/VFieldset/VFieldset.js.map +1 -0
- package/dist/components/VFieldset/VFieldset.vue_vue_type_script_setup_true_lang.js +63 -0
- package/dist/components/VFieldset/VFieldset.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VFileInput/VFileInput.css +1 -1
- package/dist/components/VFileInput/VFileInput.d.ts +31 -7
- package/dist/components/VFileInput/VFileInput.js.map +1 -1
- package/dist/components/VFileInput/VFileInput.vue_vue_type_script_setup_true_lang.js +168 -161
- package/dist/components/VFileInput/VFileInput.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VFilePicker/VFilePicker.d.ts +4 -4
- package/dist/components/VHotkeys/VHotkeys.css +1 -1
- package/dist/components/VHotkeys/VHotkeys.js.map +1 -1
- package/dist/components/VHotkeys/VHotkeys.vue_vue_type_script_setup_true_lang.js +27 -30
- package/dist/components/VHotkeys/VHotkeys.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VHotkeys/platform.d.ts +2 -0
- package/dist/components/VHotkeys/platform.js +24 -5
- package/dist/components/VHotkeys/platform.js.map +1 -1
- package/dist/components/VHoverCard/VHoverCard.css +2 -0
- package/dist/components/VHoverCard/VHoverCard.d.ts +62 -0
- package/dist/components/VHoverCard/VHoverCard.js +9 -0
- package/dist/components/VHoverCard/VHoverCard.js.map +1 -0
- package/dist/components/VHoverCard/VHoverCard.vue_vue_type_script_setup_true_lang.js +97 -0
- package/dist/components/VHoverCard/VHoverCard.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VIcon/icons/add.d.ts +5 -0
- package/dist/components/VIcon/icons/add.js +9 -0
- package/dist/components/VIcon/icons/add.js.map +1 -0
- package/dist/components/VIcon/icons/colorize.d.ts +5 -0
- package/dist/components/VIcon/icons/colorize.js +9 -0
- package/dist/components/VIcon/icons/colorize.js.map +1 -0
- package/dist/components/VIcon/icons/inbox.d.ts +5 -0
- package/dist/components/VIcon/icons/inbox.js +9 -0
- package/dist/components/VIcon/icons/inbox.js.map +1 -0
- package/dist/components/VIcon/icons/index.d.ts +42 -2
- package/dist/components/VIcon/icons/index.js +88 -72
- package/dist/components/VIcon/icons/index.js.map +1 -1
- package/dist/components/VIcon/icons/names.d.ts +2 -2
- package/dist/components/VIcon/icons/names.js +1 -1
- package/dist/components/VIcon/icons/names.js.map +1 -1
- package/dist/components/VIcon/icons/open_in_new.d.ts +5 -0
- package/dist/components/VIcon/icons/open_in_new.js +9 -0
- package/dist/components/VIcon/icons/open_in_new.js.map +1 -0
- package/dist/components/VIcon/icons/priority_high.d.ts +5 -0
- package/dist/components/VIcon/icons/priority_high.js +9 -0
- package/dist/components/VIcon/icons/priority_high.js.map +1 -0
- package/dist/components/VIcon/icons/remove.d.ts +5 -0
- package/dist/components/VIcon/icons/remove.js +9 -0
- package/dist/components/VIcon/icons/remove.js.map +1 -0
- package/dist/components/VIcon/icons/search_off.d.ts +5 -0
- package/dist/components/VIcon/icons/search_off.js +9 -0
- package/dist/components/VIcon/icons/search_off.js.map +1 -0
- package/dist/components/VIcon/icons/star.d.ts +5 -0
- package/dist/components/VIcon/icons/star.js +9 -0
- package/dist/components/VIcon/icons/star.js.map +1 -0
- package/dist/components/VIconButton/VIconButton.d.ts +4 -4
- package/dist/components/VInput/VInput.css +1 -1
- package/dist/components/VInput/VInput.d.ts +51 -2
- package/dist/components/VInput/VInput.js.map +1 -1
- package/dist/components/VInput/VInput.vue_vue_type_script_setup_true_lang.js +129 -106
- package/dist/components/VInput/VInput.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VInput/VInputGroup.css +1 -1
- package/dist/components/VInput/VInputGroup.d.ts +20 -0
- package/dist/components/VInput/VInputGroup.js.map +1 -1
- package/dist/components/VInput/VInputGroup.vue_vue_type_script_setup_true_lang.js +50 -51
- package/dist/components/VInput/VInputGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VInputOTP/VInputOTP.css +1 -1
- package/dist/components/VInputOTP/VInputOTP.d.ts +27 -4
- package/dist/components/VInputOTP/VInputOTP.js.map +1 -1
- package/dist/components/VInputOTP/VInputOTP.vue_vue_type_script_setup_true_lang.js +131 -113
- package/dist/components/VInputOTP/VInputOTP.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VLink/VLink.css +2 -0
- package/dist/components/VLink/VLink.d.ts +53 -0
- package/dist/components/VLink/VLink.js +9 -0
- package/dist/components/VLink/VLink.js.map +1 -0
- package/dist/components/VLink/VLink.vue_vue_type_script_setup_true_lang.js +58 -0
- package/dist/components/VLink/VLink.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VListbox/VListboxChevron.css +2 -0
- package/dist/components/VListbox/VListboxChevron.d.ts +12 -0
- package/dist/components/VListbox/VListboxChevron.js +9 -0
- package/dist/components/VListbox/VListboxChevron.js.map +1 -0
- package/dist/components/VListbox/VListboxChevron.vue_vue_type_script_setup_true_lang.js +25 -0
- package/dist/components/VListbox/VListboxChevron.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VListbox/VListboxGroup.css +2 -0
- package/dist/components/VListbox/VListboxGroup.d.ts +27 -0
- package/dist/components/VListbox/VListboxGroup.js +9 -0
- package/dist/components/VListbox/VListboxGroup.js.map +1 -0
- package/dist/components/VListbox/VListboxGroup.vue_vue_type_script_setup_true_lang.js +21 -0
- package/dist/components/VListbox/VListboxGroup.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VListbox/VListboxOption.css +2 -0
- package/dist/components/{VCombobox/VComboboxOption.d.ts → VListbox/VListboxOption.d.ts} +4 -4
- package/dist/components/VListbox/VListboxOption.js +9 -0
- package/dist/components/VListbox/VListboxOption.js.map +1 -0
- package/dist/components/{VCombobox/VComboboxOption.vue_vue_type_script_setup_true_lang.js → VListbox/VListboxOption.vue_vue_type_script_setup_true_lang.js} +6 -6
- package/dist/components/VListbox/VListboxOption.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VListbox/VListboxPanel.css +2 -0
- package/dist/components/VListbox/VListboxPanel.d.ts +59 -0
- package/dist/components/VListbox/VListboxPanel.js +9 -0
- package/dist/components/VListbox/VListboxPanel.js.map +1 -0
- package/dist/components/VListbox/VListboxPanel.vue_vue_type_script_setup_true_lang.js +123 -0
- package/dist/components/VListbox/VListboxPanel.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VListbox/VListboxSeparator.css +2 -0
- package/dist/components/VListbox/VListboxSeparator.d.ts +3 -0
- package/dist/components/VListbox/VListboxSeparator.js +9 -0
- package/dist/components/VListbox/VListboxSeparator.js.map +1 -0
- package/dist/components/{VCombobox/VComboboxSeparator.vue_vue_type_script_setup_true_lang.js → VListbox/VListboxSeparator.vue_vue_type_script_setup_true_lang.js} +4 -4
- package/dist/components/VListbox/VListboxSeparator.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VListbox/VListboxValues.css +2 -0
- package/dist/components/VListbox/VListboxValues.d.ts +52 -0
- package/dist/components/VListbox/VListboxValues.js +9 -0
- package/dist/components/VListbox/VListboxValues.js.map +1 -0
- package/dist/components/VListbox/VListboxValues.vue_vue_type_script_setup_true_lang.js +103 -0
- package/dist/components/VListbox/VListboxValues.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VMenu/VMenu.d.ts +1 -1
- package/dist/components/VMenu/VMenu.vue_vue_type_script_setup_true_lang.js +9 -9
- package/dist/components/VMenu/VMenuItem.d.ts +1 -1
- package/dist/components/VMenu/VMenuItem.vue_vue_type_script_setup_true_lang.js +16 -16
- package/dist/components/VMenu/VMenuPanel.d.ts +2 -2
- package/dist/components/VMenu/VMenuPanel.js.map +1 -1
- package/dist/components/VMenu/VMenuPanel.vue_vue_type_script_setup_true_lang.js +7 -7
- package/dist/components/VMenu/VMenuPanel.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VMeter/VMeter.css +2 -0
- package/dist/components/VMeter/VMeter.d.ts +77 -0
- package/dist/components/VMeter/VMeter.js +9 -0
- package/dist/components/VMeter/VMeter.js.map +1 -0
- package/dist/components/VMeter/VMeter.vue_vue_type_script_setup_true_lang.js +113 -0
- package/dist/components/VMeter/VMeter.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VNumberInput/VNumberInput.css +2 -0
- package/dist/components/VNumberInput/VNumberInput.d.ts +114 -0
- package/dist/components/VNumberInput/VNumberInput.js +9 -0
- package/dist/components/VNumberInput/VNumberInput.js.map +1 -0
- package/dist/components/VNumberInput/VNumberInput.vue_vue_type_script_setup_true_lang.js +251 -0
- package/dist/components/VNumberInput/VNumberInput.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VNumberInput/number.d.ts +30 -0
- package/dist/components/VNumberInput/number.js +38 -0
- package/dist/components/VNumberInput/number.js.map +1 -0
- package/dist/components/VPagination/VPagination.d.ts +1 -1
- package/dist/components/VPagination/VPagination.vue_vue_type_script_setup_true_lang.js +76 -76
- package/dist/components/VProgressCircular/VProgressCircular.d.ts +2 -2
- package/dist/components/VProgressLinear/VProgressLinear.css +1 -1
- package/dist/components/VProgressLinear/VProgressLinear.d.ts +10 -7
- package/dist/components/VProgressLinear/VProgressLinear.js.map +1 -1
- package/dist/components/VProgressLinear/VProgressLinear.vue_vue_type_script_setup_true_lang.js +52 -34
- package/dist/components/VProgressLinear/VProgressLinear.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VRadio/VRadio.d.ts +8 -3
- package/dist/components/VRadio/VRadio.js.map +1 -1
- package/dist/components/VRadio/VRadio.vue_vue_type_script_setup_true_lang.js +52 -46
- package/dist/components/VRadio/VRadio.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VRating/VRating.css +2 -0
- package/dist/components/VRating/VRating.d.ts +92 -0
- package/dist/components/VRating/VRating.js +9 -0
- package/dist/components/VRating/VRating.js.map +1 -0
- package/dist/components/VRating/VRating.vue_vue_type_script_setup_true_lang.js +158 -0
- package/dist/components/VRating/VRating.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VResizable/VResizable.css +2 -0
- package/dist/components/VResizable/VResizable.d.ts +50 -0
- package/dist/components/VResizable/VResizable.js +9 -0
- package/dist/components/VResizable/VResizable.js.map +1 -0
- package/dist/components/VResizable/VResizable.vue_vue_type_script_setup_true_lang.js +225 -0
- package/dist/components/VResizable/VResizable.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VResizable/VResizablePanel.css +2 -0
- package/dist/components/VResizable/VResizablePanel.d.ts +60 -0
- package/dist/components/VResizable/VResizablePanel.js +9 -0
- package/dist/components/VResizable/VResizablePanel.js.map +1 -0
- package/dist/components/VResizable/VResizablePanel.vue_vue_type_script_setup_true_lang.js +83 -0
- package/dist/components/VResizable/VResizablePanel.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VResizable/context.d.ts +24 -0
- package/dist/components/VResizable/context.js +6 -0
- package/dist/components/VResizable/context.js.map +1 -0
- package/dist/components/VResizable/layout.d.ts +28 -0
- package/dist/components/VResizable/layout.js +41 -0
- package/dist/components/VResizable/layout.js.map +1 -0
- package/dist/components/VSelect/VSelect.css +2 -0
- package/dist/components/VSelect/VSelect.d.ts +193 -0
- package/dist/components/VSelect/VSelect.js +9 -0
- package/dist/components/VSelect/VSelect.js.map +1 -0
- package/dist/components/VSelect/VSelect.vue_vue_type_script_setup_true_lang.js +424 -0
- package/dist/components/VSelect/VSelect.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VSeparator/VSeparator.js.map +1 -1
- package/dist/components/VSeparator/VSeparator.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VSideNavigation/VSideNavigation.vue_vue_type_script_setup_true_lang.js +8 -8
- package/dist/components/VSideNavigation/VSideNavigationItem.d.ts +2 -2
- package/dist/components/VSideNavigation/VSideNavigationItem.js.map +1 -1
- package/dist/components/VSideNavigation/VSideNavigationItem.vue_vue_type_script_setup_true_lang.js +3 -3
- package/dist/components/VSideNavigation/VSideNavigationItem.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VSkeletonLoader/VSkeletonLoader.d.ts +3 -3
- package/dist/components/VSlider/VSlider.css +1 -1
- package/dist/components/VSlider/VSlider.d.ts +34 -8
- package/dist/components/VSlider/VSlider.js.map +1 -1
- package/dist/components/VSlider/VSlider.vue_vue_type_script_setup_true_lang.js +236 -215
- package/dist/components/VSlider/VSlider.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VSnackbar/VSnackbar.vue_vue_type_script_setup_true_lang.js +4 -4
- package/dist/components/VSnackbar/state.js.map +1 -1
- package/dist/components/VSplitButton/VSplitButton.css +2 -0
- package/dist/components/VSplitButton/VSplitButton.d.ts +114 -0
- package/dist/components/VSplitButton/VSplitButton.js +9 -0
- package/dist/components/VSplitButton/VSplitButton.js.map +1 -0
- package/dist/components/VSplitButton/VSplitButton.vue_vue_type_script_setup_true_lang.js +148 -0
- package/dist/components/VSplitButton/VSplitButton.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VStepper/VStepper.css +2 -0
- package/dist/components/VStepper/VStepper.d.ts +73 -0
- package/dist/components/VStepper/VStepper.js +9 -0
- package/dist/components/VStepper/VStepper.js.map +1 -0
- package/dist/components/VStepper/VStepper.vue_vue_type_script_setup_true_lang.js +96 -0
- package/dist/components/VStepper/VStepper.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VSwitch/VSwitch.d.ts +8 -3
- package/dist/components/VSwitch/VSwitch.js.map +1 -1
- package/dist/components/VSwitch/VSwitch.vue_vue_type_script_setup_true_lang.js +53 -47
- package/dist/components/VSwitch/VSwitch.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VTabs/VTab.css +1 -1
- package/dist/components/VTabs/VTab.d.ts +1 -1
- package/dist/components/VTabs/VTab.js.map +1 -1
- package/dist/components/VTabs/VTab.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VTabs/VTabs.css +1 -1
- package/dist/components/VTabs/VTabs.d.ts +13 -5
- package/dist/components/VTabs/VTabs.js.map +1 -1
- package/dist/components/VTabs/VTabs.vue_vue_type_script_setup_true_lang.js +20 -20
- package/dist/components/VTabs/VTabs.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VTextarea/VTextarea.css +1 -1
- package/dist/components/VTextarea/VTextarea.d.ts +22 -2
- package/dist/components/VTextarea/VTextarea.js.map +1 -1
- package/dist/components/VTextarea/VTextarea.vue_vue_type_script_setup_true_lang.js +108 -100
- package/dist/components/VTextarea/VTextarea.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VTimeInput/VTimeInput.d.ts +27 -7
- package/dist/components/VTimeInput/VTimeInput.js.map +1 -1
- package/dist/components/VTimeInput/VTimeInput.vue_vue_type_script_setup_true_lang.js +187 -171
- package/dist/components/VTimeInput/VTimeInput.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VTimePicker/VTimePicker.d.ts +2 -2
- package/dist/components/VTimePicker/VTimePicker.js.map +1 -1
- package/dist/components/VTimePicker/VTimePicker.vue_vue_type_script_setup_true_lang.js +15 -15
- package/dist/components/VTimePicker/VTimePicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VTimeline/VTimeline.css +2 -0
- package/dist/components/VTimeline/VTimeline.d.ts +59 -0
- package/dist/components/VTimeline/VTimeline.js +9 -0
- package/dist/components/VTimeline/VTimeline.js.map +1 -0
- package/dist/components/VTimeline/VTimeline.vue_vue_type_script_setup_true_lang.js +53 -0
- package/dist/components/VTimeline/VTimeline.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VTimeline/VTimelineItem.css +2 -0
- package/dist/components/VTimeline/VTimelineItem.d.ts +48 -0
- package/dist/components/VTimeline/VTimelineItem.js +9 -0
- package/dist/components/VTimeline/VTimelineItem.js.map +1 -0
- package/dist/components/VTimeline/VTimelineItem.vue_vue_type_script_setup_true_lang.js +70 -0
- package/dist/components/VTimeline/VTimelineItem.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VTimeline/context.d.ts +11 -0
- package/dist/components/VTimeline/context.js +6 -0
- package/dist/components/VTimeline/context.js.map +1 -0
- package/dist/components/VTimeline/datetime.d.ts +8 -0
- package/dist/components/VTimeline/datetime.js +36 -0
- package/dist/components/VTimeline/datetime.js.map +1 -0
- package/dist/components/VToast/VToast.vue_vue_type_script_setup_true_lang.js +8 -8
- package/dist/components/VToast/VToaster.vue_vue_type_script_setup_true_lang.js +12 -12
- package/dist/components/VToggle/VToggle.d.ts +4 -4
- package/dist/components/VToggle/VToggleItem.d.ts +1 -1
- package/dist/components/VTooltip/VTooltip.d.ts +8 -2
- package/dist/components/VTooltip/VTooltip.js.map +1 -1
- package/dist/components/VTooltip/VTooltip.vue_vue_type_script_setup_true_lang.js +45 -43
- package/dist/components/VTooltip/VTooltip.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/VTreeView/VTreeView.css +2 -0
- package/dist/components/VTreeView/VTreeView.d.ts +112 -0
- package/dist/components/VTreeView/VTreeView.js +9 -0
- package/dist/components/VTreeView/VTreeView.js.map +1 -0
- package/dist/components/VTreeView/VTreeView.vue_vue_type_script_setup_true_lang.js +321 -0
- package/dist/components/VTreeView/VTreeView.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/VTypography/VTypography.d.ts +1 -1
- package/dist/components/VVirtualList/VVirtualList.css +2 -0
- package/dist/components/VVirtualList/VVirtualList.d.ts +78 -0
- package/dist/components/VVirtualList/VVirtualList.js +9 -0
- package/dist/components/VVirtualList/VVirtualList.js.map +1 -0
- package/dist/components/VVirtualList/VVirtualList.vue_vue_type_script_setup_true_lang.js +114 -0
- package/dist/components/VVirtualList/VVirtualList.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/composables/useChoice.d.ts +28 -0
- package/dist/composables/useChoice.js +28 -0
- package/dist/composables/useChoice.js.map +1 -0
- package/dist/composables/useDebouncedSearch.d.ts +17 -0
- package/dist/composables/useDebouncedSearch.js +18 -0
- package/dist/composables/useDebouncedSearch.js.map +1 -0
- package/dist/composables/useEscapeDismiss.d.ts +8 -0
- package/dist/composables/useEscapeDismiss.js +16 -0
- package/dist/composables/useEscapeDismiss.js.map +1 -0
- package/dist/composables/useFieldIds.d.ts +2 -1
- package/dist/composables/useFieldIds.js +7 -6
- package/dist/composables/useFieldIds.js.map +1 -1
- package/dist/composables/useFieldPanel.d.ts +1 -0
- package/dist/composables/useFieldPanel.js +52 -42
- package/dist/composables/useFieldPanel.js.map +1 -1
- package/dist/composables/useFileField.d.ts +1 -3
- package/dist/composables/useFileField.js +48 -50
- package/dist/composables/useFileField.js.map +1 -1
- package/dist/composables/useHotkeyListener.d.ts +17 -0
- package/dist/composables/useHotkeyListener.js +26 -0
- package/dist/composables/useHotkeyListener.js.map +1 -0
- package/dist/composables/useIconClickHandlers.d.ts +2 -10
- package/dist/composables/useIconClickHandlers.js +1 -1
- package/dist/composables/useIconClickHandlers.js.map +1 -1
- package/dist/{components/VCombobox/infiniteScroll.d.ts → composables/useInfiniteScroll.d.ts} +6 -0
- package/dist/{components/VCombobox/infiniteScroll.js → composables/useInfiniteScroll.js} +7 -7
- package/dist/composables/useInfiniteScroll.js.map +1 -0
- package/dist/composables/useListbox.d.ts +132 -0
- package/dist/composables/useListbox.js +227 -0
- package/dist/composables/useListbox.js.map +1 -0
- package/dist/composables/useModalDialog.d.ts +28 -0
- package/dist/composables/useModalDialog.js +60 -0
- package/dist/composables/useModalDialog.js.map +1 -0
- package/dist/composables/useRootAttrs.d.ts +2 -3
- package/dist/composables/useRootAttrs.js.map +1 -1
- package/dist/composables/useVirtualList.d.ts +46 -0
- package/dist/composables/useVirtualList.js +145 -0
- package/dist/composables/useVirtualList.js.map +1 -0
- package/dist/i18n/en.js +50 -0
- package/dist/i18n/en.js.map +1 -1
- package/dist/i18n/fr.js +50 -0
- package/dist/i18n/fr.js.map +1 -1
- package/dist/i18n/types.d.ts +103 -2
- package/dist/icons.js +45 -37
- package/dist/index.d.ts +49 -3
- package/dist/index.js +80 -56
- package/dist/styles.css +1 -1
- package/dist/tokens/index.d.ts +43 -0
- package/dist/tokens/semantic.d.ts +42 -0
- package/dist/tokens/semantic.js +43 -1
- package/dist/tokens/semantic.js.map +1 -1
- package/dist/tokens/themes/dark.d.ts +1 -0
- package/dist/tokens/themes/dark.js +1 -0
- package/dist/tokens/themes/dark.js.map +1 -1
- package/dist/tokens.json +215 -1
- package/dist/types.d.ts +57 -4
- package/dist/utils/arrowNav.js.map +1 -1
- package/dist/utils/attrs.d.ts +9 -0
- package/dist/utils/attrs.js +14 -0
- package/dist/utils/attrs.js.map +1 -0
- package/dist/utils/date.d.ts +1 -0
- package/dist/utils/date.js +2 -2
- package/dist/utils/date.js.map +1 -1
- package/package.json +1 -1
- package/dist/components/VCombobox/VComboboxGroup.css +0 -2
- package/dist/components/VCombobox/VComboboxGroup.d.ts +0 -17
- package/dist/components/VCombobox/VComboboxGroup.js +0 -9
- package/dist/components/VCombobox/VComboboxGroup.js.map +0 -1
- package/dist/components/VCombobox/VComboboxGroup.vue_vue_type_script_setup_true_lang.js +0 -21
- package/dist/components/VCombobox/VComboboxGroup.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/components/VCombobox/VComboboxOption.css +0 -2
- package/dist/components/VCombobox/VComboboxOption.js +0 -9
- package/dist/components/VCombobox/VComboboxOption.js.map +0 -1
- package/dist/components/VCombobox/VComboboxOption.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/components/VCombobox/VComboboxSeparator.css +0 -2
- package/dist/components/VCombobox/VComboboxSeparator.js +0 -9
- package/dist/components/VCombobox/VComboboxSeparator.js.map +0 -1
- package/dist/components/VCombobox/VComboboxSeparator.vue_vue_type_script_setup_true_lang.js.map +0 -1
- package/dist/components/VCombobox/infiniteScroll.js.map +0 -1
- /package/dist/components/{VCombobox/VComboboxSeparator.d.ts → VCheckbox/VCheckMark.d.ts} +0 -0
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import e from "../VField/VFieldAnnouncer.js";
|
|
2
|
+
import t from "../VField/VFieldMessage.js";
|
|
3
|
+
import { useFieldIds as n } from "../../composables/useFieldIds.js";
|
|
4
|
+
import { createCommentVNode as r, createElementBlock as i, createElementVNode as a, createTextVNode as o, createVNode as s, defineComponent as c, mergeProps as l, normalizeClass as u, openBlock as d, ref as f, renderSlot as p, toDisplayString as m, unref as h, useAttrs as g } from "vue";
|
|
5
|
+
//#region src/components/VFieldset/VFieldset.vue?vue&type=script&setup=true&lang.ts
|
|
6
|
+
var _ = ["aria-describedby", "data-orientation"], v = {
|
|
7
|
+
key: 0,
|
|
8
|
+
class: "v-field-required",
|
|
9
|
+
"aria-hidden": "true"
|
|
10
|
+
}, y = { class: "v-fieldset-body" }, b = /*@__PURE__*/ c({
|
|
11
|
+
inheritAttrs: !1,
|
|
12
|
+
__name: "VFieldset",
|
|
13
|
+
props: {
|
|
14
|
+
legend: { default: void 0 },
|
|
15
|
+
hint: { default: void 0 },
|
|
16
|
+
error: { default: void 0 },
|
|
17
|
+
required: {
|
|
18
|
+
type: Boolean,
|
|
19
|
+
default: !1
|
|
20
|
+
},
|
|
21
|
+
hideLegend: {
|
|
22
|
+
type: Boolean,
|
|
23
|
+
default: !1
|
|
24
|
+
},
|
|
25
|
+
orientation: { default: "vertical" }
|
|
26
|
+
},
|
|
27
|
+
setup(c, { expose: b }) {
|
|
28
|
+
let x = c, S = g(), { hintId: C, errorId: w, describedBy: T } = n(S, () => !!x.hint && !x.error, void 0, () => !!x.error), E = f(null);
|
|
29
|
+
return b({ el: E }), (n, f) => (d(), i("fieldset", l({
|
|
30
|
+
ref_key: "rootEl",
|
|
31
|
+
ref: E
|
|
32
|
+
}, h(S), {
|
|
33
|
+
class: "v-fieldset",
|
|
34
|
+
"aria-describedby": h(T),
|
|
35
|
+
"data-orientation": c.orientation
|
|
36
|
+
}), [
|
|
37
|
+
c.legend ? (d(), i("legend", {
|
|
38
|
+
key: 0,
|
|
39
|
+
class: u(["v-fieldset-legend", { "v-visually-hidden": c.hideLegend }])
|
|
40
|
+
}, [o(m(c.legend), 1), c.required ? (d(), i("span", v, "*")) : r("", !0)], 2)) : r("", !0),
|
|
41
|
+
a("div", y, [p(n.$slots, "default", {
|
|
42
|
+
invalid: !!c.error,
|
|
43
|
+
required: c.required
|
|
44
|
+
})]),
|
|
45
|
+
s(t, {
|
|
46
|
+
hint: c.hint,
|
|
47
|
+
error: c.error,
|
|
48
|
+
"hint-id": h(C),
|
|
49
|
+
"error-id": h(w)
|
|
50
|
+
}, null, 8, [
|
|
51
|
+
"hint",
|
|
52
|
+
"error",
|
|
53
|
+
"hint-id",
|
|
54
|
+
"error-id"
|
|
55
|
+
]),
|
|
56
|
+
s(e, { text: c.error }, null, 8, ["text"])
|
|
57
|
+
], 16, _));
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
//#endregion
|
|
61
|
+
export { b as default };
|
|
62
|
+
|
|
63
|
+
//# sourceMappingURL=VFieldset.vue_vue_type_script_setup_true_lang.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"VFieldset.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../src/components/VFieldset/VFieldset.vue"],"sourcesContent":["<script setup lang=\"ts\">\n// @a11y\n/**\n * A native `<fieldset>`, named by its `<legend>`: a group of radios, checkboxes or related\n * fields announced as one. The hint and the error describe the group; `aria-invalid` is not\n * allowed on a group, so the invalid state reaches the controls through the slot.\n */\n\nimport { ref, useAttrs } from 'vue'\n\nimport VFieldAnnouncer from '../VField/VFieldAnnouncer.vue'\nimport VFieldMessage from '../VField/VFieldMessage.vue'\n\nimport { useFieldIds } from '../../composables/useFieldIds'\n\n/** How the controls of the group are laid out: in a column, or in a wrapping row. */\nexport type FieldsetOrientation = 'vertical' | 'horizontal'\n\ninterface FieldsetProps {\n /** The legend, which names the group for assistive technology. */\n legend?: string\n /** A line of help under the group, read along with its name. */\n hint?: string\n /**\n * A message saying what is wrong with the group, shown in place of the hint and read along\n * with its name. It is announced when it appears or changes, and the slot's `invalid` turns\n * true.\n */\n error?: string\n /**\n * Marks the group as required: an asterisk follows the legend, and the slot's `required`\n * turns true, to be set on the controls.\n */\n required?: boolean\n /** Hides the legend visually. It still names the group for assistive technology. */\n hideLegend?: boolean\n /** Lays the controls out in a column (`vertical`, the default) or in a wrapping row. */\n orientation?: FieldsetOrientation\n}\n\nconst props = withDefaults(defineProps<FieldsetProps>(), {\n legend: undefined,\n hint: undefined,\n error: undefined,\n required: false,\n hideLegend: false,\n orientation: 'vertical',\n})\n\ndefineSlots<{\n /**\n * The controls of the group. `invalid` is true while there is an error, and `required`\n * repeats the prop: bind them on the controls.\n */\n default(props: { invalid: boolean; required: boolean }): unknown\n}>()\n\n// The consumer's `aria-describedby` is merged with the hint and error references, and the\n// merged list is bound after the other attributes, which fallthrough would overwrite.\ndefineOptions({ inheritAttrs: false })\n\nconst attrs = useAttrs()\n\nconst { hintId, errorId, describedBy } = useFieldIds(\n attrs,\n () => !!props.hint && !props.error,\n undefined,\n () => !!props.error,\n)\n\nconst rootEl = ref<HTMLFieldSetElement | null>(null)\n\ndefineExpose({\n /** The `<fieldset>`. */\n el: rootEl,\n})\n</script>\n\n<template>\n <fieldset\n ref=\"rootEl\"\n v-bind=\"attrs\"\n class=\"v-fieldset\"\n :aria-describedby=\"describedBy\"\n :data-orientation=\"orientation\"\n >\n <legend v-if=\"legend\" class=\"v-fieldset-legend\" :class=\"{ 'v-visually-hidden': hideLegend }\">\n {{ legend }}<span v-if=\"required\" class=\"v-field-required\" aria-hidden=\"true\">*</span>\n </legend>\n <div class=\"v-fieldset-body\">\n <slot :invalid=\"!!error\" :required=\"required\" />\n </div>\n <VFieldMessage :hint=\"hint\" :error=\"error\" :hint-id=\"hintId\" :error-id=\"errorId\" />\n <VFieldAnnouncer :text=\"error\" />\n </fieldset>\n</template>\n\n<style>\n@layer vectis.components {\n .v-fieldset {\n display: flex;\n flex-direction: column;\n gap: var(--vectis-space-1);\n min-inline-size: 0;\n margin: 0;\n padding: 0;\n border: 0;\n font-family: var(--vectis-text-family);\n }\n\n /* A rendered legend is not a flex item of its fieldset, so the gap misses it: a margin. */\n .v-fieldset-legend {\n margin-block-end: var(--vectis-space-2);\n padding: 0;\n color: var(--vectis-color-text);\n font-size: var(--vectis-text-label-size);\n font-weight: var(--vectis-text-label-weight);\n line-height: var(--vectis-text-label-leading);\n }\n\n /* A native `disabled` disables every control of the group: its name and help grey out. */\n .v-fieldset:disabled > .v-fieldset-legend {\n color: var(--vectis-color-text-subtle);\n }\n\n .v-fieldset:disabled > .v-field-hint {\n --typography-color: var(--vectis-color-text-subtle);\n }\n\n .v-fieldset-body {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: var(--vectis-space-2);\n }\n\n .v-fieldset[data-orientation='horizontal'] > .v-fieldset-body {\n flex-flow: row wrap;\n column-gap: var(--vectis-space-4);\n }\n}\n</style>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;EAwCA,IAAM,IAAQ,GAqBR,IAAQ,EAAS,GAEjB,EAAE,WAAQ,YAAS,mBAAgB,EACvC,SACM,CAAC,CAAC,EAAM,QAAQ,CAAC,EAAM,OAC7B,KAAA,SACM,CAAC,CAAC,EAAM,KAChB,GAEM,IAAS,EAAgC,IAAI;SAEnD,EAAa,EAEX,IAAI,EACN,CAAC,mBAIC,EAeW,YAfX,EAeW;YAdL;GAAJ,KAAI;KACI,EAAA,CAAA,GAAK;GACb,OAAM;GACL,oBAAkB,EAAA,CAAA;GAClB,oBAAkB,EAAA;;GAEL,EAAA,UAAA,EAAA,GAAd,EAES,UAAA;;IAFa,OAAK,EAAA,CAAC,qBAAmB,EAAA,qBAAgC,EAAA,WAAU,CAAA,CAAA;WACpF,EAAA,MAAM,GAAA,CAAA,GAAe,EAAA,YAAA,EAAA,GAAZ,EAA0E,QAA1E,GAAkE,GAAC,KAAA,EAAA,IAAA,EAAA,CAAA,GAAA,CAAA,KAAA,EAAA,IAAA,EAAA;GAEjF,EAEM,OAFN,GAEM,CADJ,EAAgD,EAAA,QAAA,WAAA;IAAzC,SAAO,CAAA,CAAI,EAAA;IAAQ,UAAU,EAAA;;GAEtC,EAAmF,GAAA;IAAnE,MAAM,EAAA;IAAO,OAAO,EAAA;IAAQ,WAAS,EAAA,CAAA;IAAS,YAAU,EAAA,CAAA;;;;;;;GACxE,EAAiC,GAAA,EAAf,MAAM,EAAA,MAAK,GAAA,MAAA,GAAA,CAAA,MAAA,CAAA"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
@layer vectis.reset, vectis.tokens, vectis.components, vectis.utilities;
|
|
2
|
-
@layer vectis.components{.v-file-input{
|
|
2
|
+
@layer vectis.components{.v-file-input{width:100%;position:relative}.v-file-input:not([data-disabled]):not([data-readonly]) .v-file-input-control,.v-file-input:not([data-disabled]):not([data-readonly])[data-display=text] .v-input-control{cursor:pointer}.v-file-input[data-display=text] .v-input-control{text-overflow:ellipsis}.v-file-input[data-dragging] .v-input .v-input-field{--field-border-color:var(--vectis-color-accent);background:var(--vectis-color-accent-surface)}.v-file-input[data-disabled] .v-file-input-counter{color:var(--vectis-color-text-subtle)}}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ChipSize } from '../VChip/VChip.js';
|
|
2
|
+
import { FieldLabelPosition } from '../VField/VField.js';
|
|
2
3
|
import { IconSource } from '../VIcon/types.js';
|
|
3
4
|
import { FileRejection } from '../../utils/file.js';
|
|
4
5
|
/** How the chosen files are shown inside the field when several are allowed. */
|
|
@@ -67,13 +68,32 @@ interface FileInputProps {
|
|
|
67
68
|
* by the browser.
|
|
68
69
|
*/
|
|
69
70
|
invalid?: boolean;
|
|
70
|
-
/** The label
|
|
71
|
+
/** The label, tied to the field so that clicking it focuses the field. */
|
|
71
72
|
label?: string;
|
|
72
73
|
/**
|
|
73
74
|
* A line of help under the field, to the left of the counter. It is tied to the field
|
|
74
75
|
* for assistive technology.
|
|
75
76
|
*/
|
|
76
77
|
hint?: string;
|
|
78
|
+
/**
|
|
79
|
+
* A message saying what is wrong with the value, shown in place of the hint so that the field
|
|
80
|
+
* does not grow. It marks the field invalid, is read along with it, and is announced when it
|
|
81
|
+
* appears or changes.
|
|
82
|
+
*/
|
|
83
|
+
error?: string;
|
|
84
|
+
/**
|
|
85
|
+
* Marks the field as required: an asterisk follows the label, and the field is announced as
|
|
86
|
+
* required. The browser does not check it, its message would point at the hidden file input:
|
|
87
|
+
* validate the v-model and set `error`.
|
|
88
|
+
*/
|
|
89
|
+
required?: boolean;
|
|
90
|
+
/** Hides the label visually. It still names the field for assistive technology. */
|
|
91
|
+
hideLabel?: boolean;
|
|
92
|
+
/**
|
|
93
|
+
* Where the label sits: above the field (`top`, the default), or at its start, in a column of
|
|
94
|
+
* its own, moving back above when there is not room for both.
|
|
95
|
+
*/
|
|
96
|
+
labelPosition?: FieldLabelPosition;
|
|
77
97
|
/**
|
|
78
98
|
* What the field says while nothing is chosen. It falls back to the design system
|
|
79
99
|
* dictionary.
|
|
@@ -91,7 +111,7 @@ interface FileInputProps {
|
|
|
91
111
|
* What the button at the end of the field does, in words. It names the button
|
|
92
112
|
* `pickerIcon` renders, and falls back to the design system dictionary.
|
|
93
113
|
*/
|
|
94
|
-
|
|
114
|
+
pickerLabel?: string;
|
|
95
115
|
/**
|
|
96
116
|
* Shows a spinner at the end of the field, in place of the attach icon, while an upload is
|
|
97
117
|
* under way, typically.
|
|
@@ -163,24 +183,28 @@ declare const __VLS_base: import('vue').DefineComponent<__VLS_PublicProps, {
|
|
|
163
183
|
loading: boolean;
|
|
164
184
|
label: string;
|
|
165
185
|
placeholder: string;
|
|
186
|
+
pickerLabel: string;
|
|
187
|
+
error: string;
|
|
166
188
|
size: FileInputSize;
|
|
167
|
-
display: FileInputDisplay;
|
|
168
189
|
compact: boolean;
|
|
169
|
-
disabled: boolean;
|
|
170
190
|
iconStart: IconSource;
|
|
171
|
-
|
|
191
|
+
disabled: boolean;
|
|
192
|
+
required: boolean;
|
|
172
193
|
multiple: boolean;
|
|
194
|
+
display: FileInputDisplay;
|
|
195
|
+
maxSize: number;
|
|
196
|
+
invalid: boolean;
|
|
173
197
|
hint: string;
|
|
198
|
+
hideLabel: boolean;
|
|
199
|
+
labelPosition: FieldLabelPosition;
|
|
174
200
|
readonly: boolean;
|
|
175
201
|
iconStartLabel: string;
|
|
176
202
|
loadingText: string;
|
|
177
203
|
clearable: boolean;
|
|
178
204
|
clearLabel: string;
|
|
179
205
|
counter: boolean;
|
|
180
|
-
pickerIconLabel: string;
|
|
181
206
|
pickerIcon: IconSource;
|
|
182
207
|
accept: string;
|
|
183
|
-
maxSize: number;
|
|
184
208
|
maxTotalSize: number;
|
|
185
209
|
maxFiles: number;
|
|
186
210
|
noDrop: boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VFileInput.js","names":[],"sources":["../../../src/components/VFileInput/VFileInput.vue"],"sourcesContent":["<script setup lang=\"ts\">\n// @core\n/**\n * Compose a read-only VInput with a native file input. useFileField bridges File[] selection to\n * the browser dialog and form submission.\n */\nimport { computed, inject, ref, useId } from 'vue'\n\nimport VChip from '../VChip/VChip.vue'\nimport type { ChipSize } 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 { inputGroupKey } from '../VInput/context'\nimport VTypography from '../VTypography/VTypography.vue'\n\nimport { canClear } from '../../composables/useClearable'\nimport { useControlShape } from '../../composables/useControlShape'\nimport { useFileDrop } from '../../composables/useFileDrop'\nimport { useFileField } from '../../composables/useFileField'\nimport { iconStartListener } from '../../composables/useIconClickHandlers'\nimport { useRootAttrs } from '../../composables/useRootAttrs'\nimport { useLocale, useMessages } from '../../i18n/state'\nimport { chipScaleFor } from '../../utils/chip'\nimport { isDev } from '../../utils/env'\nimport { fileKey, formatBytes, type FileRejection } from '../../utils/file'\nimport { joinIds } from '../../utils/ids'\nimport { truncateMiddle } from './truncate'\n\n/** How the chosen files are shown inside the field when several are allowed. */\nexport type FileInputDisplay = 'chip' | 'text'\n\n/** What the `#chip` slot receives. */\nexport interface FileInputChipSlotProps {\n /** The file the chip stands for. */\n file: File\n /** Its position in the selection. */\n index: number\n /** Its name, already shortened in the middle so the extension survives. */\n label: string\n /** Takes the file out of the selection, the only way to. */\n remove: () => void\n /** The chip size worked out to sit inside the field, one step below it. */\n size: ChipSize\n /** Whether the chip takes its compact height, to catch up below the smallest step. */\n compact: boolean\n}\n\n/** What the `#counter` slot receives. */\nexport interface FileInputCounterSlotProps {\n /** How many files are selected. */\n count: number\n /** Their total size, in bytes. */\n bytes: number\n /** The sentence the counter shows by default, already translated. */\n text: string\n}\n\n/** The height of the field: 32, 40 or 48 pixels. */\nexport type FileInputSize = 'sm' | 'md' | 'lg'\n\ninterface FileInputProps {\n /** Allows several files to be chosen. With one only, every extra file is turned away. */\n multiple?: boolean\n /** Which kinds of file are accepted, in the browser's own syntax (`image/*,.pdf`). */\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 pickerIcon?: IconSource\n /** Refuses files dropped onto the component: only the dialog then adds any. */\n noDrop?: boolean\n /** The height of the field: 32, 40 or 48 pixels. */\n size?: FileInputSize\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 /**\n * An icon inside the field, at the start. Decorative by default, it becomes a real button as\n * soon as a `@click:icon-start` listener is attached, in which case it needs\n * `iconStartLabel`.\n */\n iconStart?: IconSource\n /** What the start icon does, in words, once it is clickable. */\n iconStartLabel?: string\n /**\n * What the button at the end of the field does, in words. It names the button\n * `pickerIcon` renders, and falls back to the design system dictionary.\n */\n pickerIconLabel?: string\n /**\n * Shows a spinner at the end of the field, in place of the attach icon, while an upload is\n * under way, typically.\n */\n loading?: boolean\n /**\n * What screen readers announce while the spinner turns. It falls back to the design\n * system dictionary.\n */\n loadingText?: string\n /** Offers a cross that empties the selection. */\n clearable?: boolean\n /** What that cross does, in words. It falls back to the design system dictionary. */\n clearLabel?: string\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 pickerIcon: () => attachFileIcon,\n noDrop: false,\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 iconStart: undefined,\n iconStartLabel: undefined,\n pickerIconLabel: undefined,\n loading: false,\n loadingText: undefined,\n clearable: false,\n clearLabel: undefined,\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: FileRejection]\n /**\n * ONE file was taken out through its chip, with the file and the position it held.\n * `change` follows it with the whole list, as it does after every other change.\n */\n remove: [file: File, index: number]\n /** The clear cross emptied the selection. */\n clear: []\n /** The start icon was clicked. Attaching this listener is what makes it a button. */\n 'click:icon-start': [event: MouseEvent]\n}>()\n\ndefineSlots<{\n /**\n * Content at the start of the field, rendered after the chips standing for the chosen\n * files rather than in their place.\n */\n start?(): unknown\n /**\n * Controls of your own inside the field, placed before the ones the field owns: the clear\n * cross and the icon that opens the file dialog.\n */\n 'value-end'?(): unknown\n /** Replaces the chip standing for one file. */\n chip?(props: FileInputChipSlotProps): unknown\n /**\n * Replaces the counter under the field. `text` is the sentence already built and\n * translated; the count and the total size in `bytes` are there for a wording of your own.\n */\n counter?(props: FileInputCounterSlotProps): unknown\n}>()\n\n// `get` reads an explicit `null` as the empty list: the default applies only to a model\n// that was never given, and `files = ref(null)` is a common start in untyped code.\n/** Always a LIST of files, whether or not several are allowed, and never a file on its own. */\nconst model = defineModel<File[]>({ default: () => [], get: (files) => files ?? [] })\n\nconst { attrs, rootClass, rootStyle, forwardedAttrs } = useRootAttrs()\n\n// Declared as this component's own event, `click:icon-start` is out of `$attrs`, so the\n// listener is relayed to the field by hand; and only when the consumer wrote one.\nconst iconStartClick = iconStartListener((event) => emit('click:icon-start', event))\n\nconst m = useMessages()\nconst locale = useLocale()\n\n// A VInputGroup joins several controls into one object, so the shape of this field is the\n// row's decision rather than its own (VInput/context.ts). The chips read the resolved pair\n// too, or they would come out one step off the field they sit in.\nconst group = inject(inputGroupKey, null)\nconst {\n size: resolvedSize,\n compact: resolvedCompact,\n disabled: resolvedDisabled,\n} = useControlShape(props, group)\n\n/*\n * Here, the bucket meant for \"the control the user deals with\" goes to the visible field: that\n * is what they see, focus and click, so a consumer's own `<label for>` has to point at it. The\n * description attribute is pulled out of that bucket, because this component re-assembles it\n * further down.\n */\nconst {\n fileEl,\n enabled,\n nativeInputAttrs,\n controlAttrs,\n acceptFiles,\n openPicker,\n removeAt,\n clear,\n} = useFileField({\n model,\n props,\n emit,\n forwardedAttrs,\n disabled: resolvedDisabled,\n excludeFromControl: ['aria-describedby'],\n onClear: () => emit('clear'),\n warnings: isDev\n ? () => [\n props.display === 'chip' &&\n !props.multiple &&\n 'display=\"chip\" ignored without `multiple`: a single file shows as text.',\n ]\n : undefined,\n})\n\n/** What reaches the visible field: the consumer's own attributes, plus that listener. */\nconst fieldAttrs = computed(() => ({ ...controlAttrs.value, ...iconStartClick }))\n\nconst inputRef = ref<InstanceType<typeof VInput> | null>(null)\nconst rootEl = ref<HTMLElement | null>(null)\n\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 * The visible field is read-only, and a read-only field hides its cross by default; rightly so,\n * since its 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 clearVisible = computed(() => canClear(props, resolvedDisabled.value, model.value.length > 0))\n\n// @a11y @devwarn\n/*\n * Its label stays defined always, even when no icon is rendered. The helper that detects a\n * click handler on an icon warns AT setup if one is attached without a label, and it has no way\n * of knowing whether an icon exists.\n */\nconst endIcon = computed<IconSource | undefined>(() =>\n props.readonly ? undefined : props.pickerIcon,\n)\nconst endIconLabel = computed(() => props.pickerIconLabel ?? m.value.fileInput.openPicker)\nconst resolvedClearLabel = computed(() => props.clearLabel ?? m.value.fileInput.clear)\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 it is\n * language; the SIZE is formatted by the platform, which knows the local conventions; and the\n * parentheses come from neither, being punctuation every language shares; the same boundary\n * VBadge's \"99+\" falls on. With nothing chosen it states the count alone: \"0 files ()\" would be\n * 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 rather\n * than by VInput: the hint belongs to OUR row under the field, VInput having no such row; its\n * own counter sits inside the field. The counter is deliberately part of that list, unlike in\n * VTextarea.\n */\nconst describedBy = computed(() =>\n joinIds(\n attrs['aria-describedby'] as string | undefined,\n !!props.hint && hintId,\n props.counter && counterId,\n ),\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(resolvedSize.value, resolvedCompact.value))\n\n/**\n * What each chip shows for its file, worked out once per change of the selection rather than on\n * every render, which reads it three times per chip.\n */\n// Computed lazily, so a text display, which never reads it, never pays for it.\nconst chipLabels = computed(() => model.value.map((file) => truncateMiddle(file.name)))\n\nfunction onControlClick(event: MouseEvent) {\n // Without this guard the attach icon would open the dialog TWICE, and the clear cross would\n // 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 removeFile(index: number) {\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 if (removeAt(index)) inputRef.value?.focus()\n}\n\n/*\n * Files may be dropped on the component itself; there is no separate drop area here; that is\n * what VFilePicker is for.\n */\nconst { dragging, onDragEnter, onDragOver, onDragLeave, onDrop } = useFileDrop(\n () => !props.noDrop && enabled.value,\n acceptFiles,\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 * The component's own box, for what neither of the two above covers. It is the wrapper\n * and not the hidden file input: that one is the FORM's element, this is the reader's.\n */\n el: rootEl,\n})\n</script>\n\n<template>\n <div\n ref=\"rootEl\"\n class=\"v-file-input\"\n :class=\"rootClass\"\n :style=\"[{ '--chip-height': chipScale.height }, rootStyle]\"\n :data-size=\"resolvedSize\"\n :data-compact=\"resolvedCompact ? '' : undefined\"\n :data-display=\"resolvedDisplay\"\n :data-disabled=\"resolvedDisabled ? '' : undefined\"\n :data-readonly=\"readonly ? '' : undefined\"\n :data-dragging=\"dragging ? '' : undefined\"\n @dragenter=\"onDragEnter\"\n @dragover=\"onDragOver\"\n @dragleave=\"onDragLeave\"\n @drop=\"onDrop\"\n >\n <input v-bind=\"nativeInputAttrs\" ref=\"fileEl\" class=\"v-file-input-native v-hidden-input\" />\n\n <div class=\"v-file-input-control\" @click=\"onControlClick\">\n <!-- Shown as chips, the field takes VInput's two arrangements for chips: its end\n controls lifted out of the flow, and the chips wrapping onto several rows. -->\n <VInput\n v-bind=\"fieldAttrs\"\n ref=\"inputRef\"\n :class=\"{ 'v-input-end-pinned v-input-chips': resolvedDisplay === 'chip' }\"\n :model-value=\"displayText\"\n no-typing\n :readonly=\"readonly\"\n :label=\"label\"\n :placeholder=\"placeholderText\"\n :size=\"resolvedSize\"\n :compact=\"resolvedCompact\"\n :disabled=\"resolvedDisabled\"\n :invalid=\"invalid\"\n :clearable=\"clearable\"\n :clear-visible=\"clearVisible\"\n :clear-label=\"resolvedClearLabel\"\n :icon-start=\"iconStart\"\n :icon-start-label=\"iconStartLabel\"\n :loading=\"loading\"\n :loading-text=\"loadingText\"\n :icon-end=\"endIcon\"\n :icon-end-label=\"endIconLabel\"\n :aria-describedby=\"describedBy\"\n @click:icon-end=\"openPicker\"\n @clear=\"clear\"\n @keydown=\"onFieldKeydown\"\n >\n <template v-if=\"resolvedDisplay === 'chip' || $slots.start\" #start>\n <template\n v-for=\"(file, index) in resolvedDisplay === 'chip' ? model : []\"\n :key=\"fileKey(file)\"\n >\n <slot\n name=\"chip\"\n :file=\"file\"\n :index=\"index\"\n :label=\"chipLabels[index]!\"\n :remove=\"() => removeFile(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=\"enabled\"\n :dismiss-label=\"m.common.remove(file.name)\"\n :disabled=\"resolvedDisabled\"\n :title=\"chipLabels[index] === file.name ? undefined : file.name\"\n @dismiss=\"removeFile(index)\"\n >{{ chipLabels[index] }}</VChip\n >\n </slot>\n </template>\n <slot name=\"start\" />\n </template>\n\n <template v-if=\"$slots['value-end']\" #value-end><slot name=\"value-end\" /></template>\n </VInput>\n </div>\n\n <div v-if=\"hint || counter\" class=\"v-file-input-meta v-field-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 v-field-counter\">\n <slot name=\"counter\" :count=\"model.length\" :bytes=\"totalSize\" :text=\"counterText\">\n {{ counterText }}\n </slot>\n </span>\n </div>\n </div>\n</template>\n\n<style>\n@layer vectis.components {\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 /*\n * The real file input is a source of files and not a control anyone deals with: it wears\n * `.v-hidden-input`, and taking it out of the tab order and hiding it from screen readers, in\n * `useFileField`, is what leaves the visible field as the single stop and the single\n * announcement.\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 /*\n * The selector weighs (0,4,0), one step above VInput's states, and it has to. The field\n * inside is always read-only, and VInput's read-only background weighs (0,3,0): at that\n * weight the winner would be whichever of the two sheets a bundler put last.\n */\n .v-file-input[data-dragging] .v-input .v-input-field {\n --field-border-color: var(--vectis-color-accent);\n\n background: var(--vectis-color-accent-surface);\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":""}
|
|
1
|
+
{"version":3,"file":"VFileInput.js","names":[],"sources":["../../../src/components/VFileInput/VFileInput.vue"],"sourcesContent":["<script setup lang=\"ts\">\n// @core\n/**\n * Compose a read-only VInput with a native file input. useFileField bridges File[] selection to\n * the browser dialog and form submission.\n */\nimport { computed, inject, ref } from 'vue'\n\nimport VChip from '../VChip/VChip.vue'\nimport type { ChipSize } from '../VChip/VChip.vue'\nimport type { FieldLabelPosition } from '../VField/VField.vue'\nimport { attach_file as attachFileIcon } from '../VIcon/icons/attach_file'\nimport type { IconSource } from '../VIcon/types'\nimport VInput from '../VInput/VInput.vue'\nimport { inputGroupKey } from '../VInput/context'\n\nimport { canClear } from '../../composables/useClearable'\nimport { useControlShape } from '../../composables/useControlShape'\nimport { useFileDrop } from '../../composables/useFileDrop'\nimport { useFileField } from '../../composables/useFileField'\nimport { iconStartListener } from '../../composables/useIconClickHandlers'\nimport { useRootAttrs } from '../../composables/useRootAttrs'\nimport { useLocale, useMessages } from '../../i18n/state'\nimport { chipScaleFor } from '../../utils/chip'\nimport { isDev } from '../../utils/env'\nimport { fileKey, formatBytes, type FileRejection } 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 = 'chip' | 'text'\n\n/** What the `#chip` slot receives. */\nexport interface FileInputChipSlotProps {\n /** The file the chip stands for. */\n file: File\n /** Its position in the selection. */\n index: number\n /** Its name, already shortened in the middle so the extension survives. */\n label: string\n /** Takes the file out of the selection, the only way to. */\n remove: () => void\n /** The chip size worked out to sit inside the field, one step below it. */\n size: ChipSize\n /** Whether the chip takes its compact height, to catch up below the smallest step. */\n compact: boolean\n}\n\n/** What the `#counter` slot receives. */\nexport interface FileInputCounterSlotProps {\n /** How many files are selected. */\n count: number\n /** Their total size, in bytes. */\n bytes: number\n /** The sentence the counter shows by default, already translated. */\n text: string\n}\n\n/** The height of the field: 32, 40 or 48 pixels. */\nexport type FileInputSize = 'sm' | 'md' | 'lg'\n\ninterface FileInputProps {\n /** Allows several files to be chosen. With one only, every extra file is turned away. */\n multiple?: boolean\n /** Which kinds of file are accepted, in the browser's own syntax (`image/*,.pdf`). */\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 pickerIcon?: IconSource\n /** Refuses files dropped onto the component: only the dialog then adds any. */\n noDrop?: boolean\n /** The height of the field: 32, 40 or 48 pixels. */\n size?: FileInputSize\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, tied to the field 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 * A message saying what is wrong with the value, shown in place of the hint so that the field\n * does not grow. It marks the field invalid, is read along with it, and is announced when it\n * appears or changes.\n */\n error?: string\n /**\n * Marks the field as required: an asterisk follows the label, and the field is announced as\n * required. The browser does not check it, its message would point at the hidden file input:\n * validate the v-model and set `error`.\n */\n required?: boolean\n /** Hides the label visually. It still names the field for assistive technology. */\n hideLabel?: boolean\n /**\n * Where the label sits: above the field (`top`, the default), or at its start, in a column of\n * its own, moving back above when there is not room for both.\n */\n labelPosition?: FieldLabelPosition\n /**\n * What the field says while nothing is chosen. It falls back to the design system\n * dictionary.\n */\n placeholder?: string\n /**\n * An icon inside the field, at the start. Decorative by default, it becomes a real button as\n * soon as a `@click:icon-start` listener is attached, in which case it needs\n * `iconStartLabel`.\n */\n iconStart?: IconSource\n /** What the start icon does, in words, once it is clickable. */\n iconStartLabel?: string\n /**\n * What the button at the end of the field does, in words. It names the button\n * `pickerIcon` renders, and falls back to the design system dictionary.\n */\n pickerLabel?: string\n /**\n * Shows a spinner at the end of the field, in place of the attach icon, while an upload is\n * under way, typically.\n */\n loading?: boolean\n /**\n * What screen readers announce while the spinner turns. It falls back to the design\n * system dictionary.\n */\n loadingText?: string\n /** Offers a cross that empties the selection. */\n clearable?: boolean\n /** What that cross does, in words. It falls back to the design system dictionary. */\n clearLabel?: string\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 pickerIcon: () => attachFileIcon,\n noDrop: false,\n size: 'md',\n compact: false,\n disabled: false,\n readonly: false,\n invalid: false,\n label: undefined,\n hint: undefined,\n error: undefined,\n required: false,\n hideLabel: false,\n labelPosition: 'top',\n placeholder: undefined,\n iconStart: undefined,\n iconStartLabel: undefined,\n pickerLabel: undefined,\n loading: false,\n loadingText: undefined,\n clearable: false,\n clearLabel: undefined,\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: FileRejection]\n /**\n * ONE file was taken out through its chip, with the file and the position it held.\n * `change` follows it with the whole list, as it does after every other change.\n */\n remove: [file: File, index: number]\n /** The clear cross emptied the selection. */\n clear: []\n /** The start icon was clicked. Attaching this listener is what makes it a button. */\n 'click:icon-start': [event: MouseEvent]\n}>()\n\ndefineSlots<{\n /**\n * Content at the start of the field, rendered after the chips standing for the chosen\n * files rather than in their place.\n */\n start?(): unknown\n /**\n * Controls of your own inside the field, placed before the ones the field owns: the clear\n * cross and the icon that opens the file dialog.\n */\n 'value-end'?(): unknown\n /** Replaces the chip standing for one file. */\n chip?(props: FileInputChipSlotProps): unknown\n /**\n * Replaces the counter under the field. `text` is the sentence already built and\n * translated; the count and the total size in `bytes` are there for a wording of your own.\n */\n counter?(props: FileInputCounterSlotProps): unknown\n}>()\n\n// `get` reads an explicit `null` as the empty list: the default applies only to a model\n// that was never given, and `files = ref(null)` is a common start in untyped code.\n/** Always a LIST of files, whether or not several are allowed, and never a file on its own. */\nconst model = defineModel<File[]>({ default: () => [], get: (files) => files ?? [] })\n\nconst { rootClass, rootStyle, forwardedAttrs } = useRootAttrs()\n\n// Declared as this component's own event, `click:icon-start` is out of `$attrs`, so the\n// listener is relayed to the field by hand; and only when the consumer wrote one.\nconst iconStartClick = iconStartListener((event) => emit('click:icon-start', event))\n\nconst m = useMessages()\nconst locale = useLocale()\n\n// A VInputGroup joins several controls into one object, so the shape of this field is the\n// row's decision rather than its own (VInput/context.ts). The chips read the resolved pair\n// too, or they would come out one step off the field they sit in.\nconst group = inject(inputGroupKey, null)\nconst {\n size: resolvedSize,\n compact: resolvedCompact,\n disabled: resolvedDisabled,\n} = useControlShape(props, group)\n\n/*\n * Here, the bucket meant for \"the control the user deals with\" goes to the visible field: that\n * is what they see, focus and click, so a consumer's own `<label for>` has to point at it.\n */\nconst {\n fileEl,\n enabled,\n nativeInputAttrs,\n controlAttrs,\n acceptFiles,\n openPicker,\n removeAt,\n clear,\n} = useFileField({\n model,\n props,\n emit,\n forwardedAttrs,\n disabled: resolvedDisabled,\n onClear: () => emit('clear'),\n warnings: isDev\n ? () => [\n props.display === 'chip' &&\n !props.multiple &&\n 'display=\"chip\" ignored without `multiple`: a single file shows as text.',\n ]\n : undefined,\n})\n\n/** What reaches the visible field: the consumer's own attributes, plus that listener. */\nconst fieldAttrs = computed(() => ({ ...controlAttrs.value, ...iconStartClick }))\n\nconst inputRef = ref<InstanceType<typeof VInput> | null>(null)\nconst rootEl = ref<HTMLElement | null>(null)\n\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 * The visible field is read-only, and a read-only field hides its cross by default; rightly so,\n * since its 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 clearVisible = computed(() => canClear(props, resolvedDisabled.value, model.value.length > 0))\n\n// @a11y @devwarn\n/*\n * Its label stays defined always, even when no icon is rendered. The helper that detects a\n * click handler on an icon warns AT setup if one is attached without a label, and it has no way\n * of knowing whether an icon exists.\n */\nconst endIcon = computed<IconSource | undefined>(() =>\n props.readonly ? undefined : props.pickerIcon,\n)\nconst endIconLabel = computed(() => props.pickerLabel ?? m.value.fileInput.openPicker)\nconst resolvedClearLabel = computed(() => props.clearLabel ?? m.value.fileInput.clear)\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 it is\n * language; the SIZE is formatted by the platform, which knows the local conventions; and the\n * parentheses come from neither, being punctuation every language shares; the same boundary\n * VBadge's \"99+\" falls on. With nothing chosen it states the count alone: \"0 files ()\" would be\n * 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\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(resolvedSize.value, resolvedCompact.value))\n\n/**\n * What each chip shows for its file, worked out once per change of the selection rather than on\n * every render, which reads it three times per chip.\n */\n// Computed lazily, so a text display, which never reads it, never pays for it.\nconst chipLabels = computed(() => model.value.map((file) => truncateMiddle(file.name)))\n\nfunction onControlClick(event: MouseEvent) {\n const target = event.target as HTMLElement\n // Only the field's box opens the dialog: a click on the label reaches it as the click the\n // label forwards to the input, and the hint and the counter do nothing. Without the button\n // guard the attach icon would open the dialog TWICE, and the clear cross would reopen it\n // immediately after emptying the selection.\n if (!target.closest('.v-input-field') || target.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 removeFile(index: number) {\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 if (removeAt(index)) inputRef.value?.focus()\n}\n\n/*\n * Files may be dropped on the component itself; there is no separate drop area here; that is\n * what VFilePicker is for.\n */\nconst { dragging, onDragEnter, onDragOver, onDragLeave, onDrop } = useFileDrop(\n () => !props.noDrop && enabled.value,\n acceptFiles,\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 * The component's own box, for what neither of the two above covers. It is the wrapper\n * and not the hidden file input: that one is the FORM's element, this is the reader's.\n */\n el: rootEl,\n})\n</script>\n\n<template>\n <div\n ref=\"rootEl\"\n class=\"v-file-input\"\n :class=\"rootClass\"\n :style=\"[{ '--chip-height': chipScale.height }, rootStyle]\"\n :data-size=\"resolvedSize\"\n :data-compact=\"resolvedCompact ? '' : undefined\"\n :data-display=\"resolvedDisplay\"\n :data-disabled=\"resolvedDisabled ? '' : undefined\"\n :data-readonly=\"readonly ? '' : undefined\"\n :data-dragging=\"dragging ? '' : undefined\"\n @dragenter=\"onDragEnter\"\n @dragover=\"onDragOver\"\n @dragleave=\"onDragLeave\"\n @drop=\"onDrop\"\n >\n <input v-bind=\"nativeInputAttrs\" ref=\"fileEl\" class=\"v-file-input-native v-hidden-input\" />\n\n <div class=\"v-file-input-control\" @click=\"onControlClick\">\n <!-- Shown as chips, the field takes VInput's two arrangements for chips: its end\n controls lifted out of the flow, and the chips wrapping onto several rows. -->\n <VInput\n v-bind=\"fieldAttrs\"\n ref=\"inputRef\"\n :class=\"{ 'v-input-end-pinned v-input-chips': resolvedDisplay === 'chip' }\"\n :model-value=\"displayText\"\n no-typing\n :readonly=\"readonly\"\n :label=\"label\"\n :hint=\"hint\"\n :error=\"error\"\n :required=\"required\"\n :hide-label=\"hideLabel\"\n :label-position=\"labelPosition\"\n :placeholder=\"placeholderText\"\n :size=\"resolvedSize\"\n :compact=\"resolvedCompact\"\n :disabled=\"resolvedDisabled\"\n :invalid=\"invalid\"\n :clearable=\"clearable\"\n :clear-visible=\"clearVisible\"\n :clear-label=\"resolvedClearLabel\"\n :icon-start=\"iconStart\"\n :icon-start-label=\"iconStartLabel\"\n :loading=\"loading\"\n :loading-text=\"loadingText\"\n :icon-end=\"endIcon\"\n :icon-end-label=\"endIconLabel\"\n @click:icon-end=\"openPicker\"\n @clear=\"clear\"\n @keydown=\"onFieldKeydown\"\n >\n <template v-if=\"resolvedDisplay === 'chip' || $slots.start\" #start>\n <template\n v-for=\"(file, index) in resolvedDisplay === 'chip' ? model : []\"\n :key=\"fileKey(file)\"\n >\n <slot\n name=\"chip\"\n :file=\"file\"\n :index=\"index\"\n :label=\"chipLabels[index]!\"\n :remove=\"() => removeFile(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=\"enabled\"\n :dismiss-label=\"m.common.remove(file.name)\"\n :disabled=\"resolvedDisabled\"\n :title=\"chipLabels[index] === file.name ? undefined : file.name\"\n @dismiss=\"removeFile(index)\"\n >{{ chipLabels[index] }}</VChip\n >\n </slot>\n </template>\n <slot name=\"start\" />\n </template>\n\n <template v-if=\"$slots['value-end']\" #value-end><slot name=\"value-end\" /></template>\n\n <template v-if=\"counter\" #meta=\"{ id }\">\n <span :id=\"id\" class=\"v-file-input-counter v-field-counter\">\n <slot name=\"counter\" :count=\"model.length\" :bytes=\"totalSize\" :text=\"counterText\">\n {{ counterText }}\n </slot>\n </span>\n </template>\n </VInput>\n </div>\n </div>\n</template>\n\n<style>\n@layer vectis.components {\n /* The label, the hint and the error are those of the VInput inside. */\n .v-file-input {\n position: relative;\n width: 100%;\n }\n\n /*\n * The real file input is a source of files and not a control anyone deals with: it wears\n * `.v-hidden-input`, and taking it out of the tab order and hiding it from screen readers, in\n * `useFileField`, is what leaves the visible field as the single stop and the single\n * announcement.\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 /*\n * The selector weighs (0,4,0), one step above VInput's states, and it has to. The field\n * inside is always read-only, and VInput's read-only background weighs (0,3,0): at that\n * weight the winner would be whichever of the two sheets a bundler put last.\n */\n .v-file-input[data-dragging] .v-input .v-input-field {\n --field-border-color: var(--vectis-color-accent);\n\n background: var(--vectis-color-accent-surface);\n }\n\n .v-file-input[data-disabled] .v-file-input-counter {\n color: var(--vectis-color-text-subtle);\n }\n}\n</style>\n"],"mappings":""}
|