From a611a3359be421396aa4edf93430bb06bbcc2e36 Mon Sep 17 00:00:00 2001 From: John Leider Date: Mon, 22 Apr 2024 15:53:03 -0500 Subject: [PATCH 01/16] feat(VFileUpload): add new component --- .../src/labs/VFileUpload/VFileUpload.tsx | 32 +++++++++++++++++++ packages/vuetify/src/labs/components.ts | 1 + 2 files changed, 33 insertions(+) create mode 100644 packages/vuetify/src/labs/VFileUpload/VFileUpload.tsx diff --git a/packages/vuetify/src/labs/VFileUpload/VFileUpload.tsx b/packages/vuetify/src/labs/VFileUpload/VFileUpload.tsx new file mode 100644 index 00000000000..844aea722b3 --- /dev/null +++ b/packages/vuetify/src/labs/VFileUpload/VFileUpload.tsx @@ -0,0 +1,32 @@ +// Components +import { VCard } from '@/components/VCard' +import { makeVCardProps } from '@/components/VCard/VCard' + +// Utilities +import { genericComponent, propsFactory, useRender } from '@/util' + +export const makeVFileUploadProps = propsFactory({ + ...makeVCardProps(), +}, 'VFileUpload') + +export const VFileUpload = genericComponent()({ + name: 'VFileUpload', + + props: makeVFileUploadProps(), + + setup (props) { + useRender(() => { + const cardProps = VCard.filterProps(props) + + return ( + + + + ) + }) + }, +}) + +export type VFileUpload = InstanceType diff --git a/packages/vuetify/src/labs/components.ts b/packages/vuetify/src/labs/components.ts index 6b753ff8790..341d9536360 100644 --- a/packages/vuetify/src/labs/components.ts +++ b/packages/vuetify/src/labs/components.ts @@ -1,5 +1,6 @@ export * from './VCalendar' export * from './VDateInput' +export * from './VFileUpload' export * from './VNumberInput' export * from './VPicker' export * from './VStepperVertical' From f4eab8e659b3005e7f98d663da03acccb00625ee Mon Sep 17 00:00:00 2001 From: John Leider Date: Mon, 22 Apr 2024 21:02:27 -0500 Subject: [PATCH 02/16] feat(VFileUpload): setup initial styling --- packages/vuetify/src/iconsets/mdi.ts | 1 + .../src/labs/VFileUpload/VFileUpload.sass | 33 +++++ .../src/labs/VFileUpload/VFileUpload.tsx | 115 ++++++++++++++++-- .../src/labs/VFileUpload/_variables.scss | 4 + .../vuetify/src/labs/VFileUpload/index.ts | 1 + packages/vuetify/src/locale/en.ts | 5 + 6 files changed, 151 insertions(+), 8 deletions(-) create mode 100644 packages/vuetify/src/labs/VFileUpload/VFileUpload.sass create mode 100644 packages/vuetify/src/labs/VFileUpload/_variables.scss create mode 100644 packages/vuetify/src/labs/VFileUpload/index.ts diff --git a/packages/vuetify/src/iconsets/mdi.ts b/packages/vuetify/src/iconsets/mdi.ts index d1a9e788062..059e3cf9f67 100644 --- a/packages/vuetify/src/iconsets/mdi.ts +++ b/packages/vuetify/src/iconsets/mdi.ts @@ -47,6 +47,7 @@ const aliases: IconAliases = { treeviewCollapse: 'mdi-menu-down', treeviewExpand: 'mdi-menu-right', eyeDropper: 'mdi-eyedropper', + upload: 'mdi-cloud-upload', } const mdi: IconSet = { diff --git a/packages/vuetify/src/labs/VFileUpload/VFileUpload.sass b/packages/vuetify/src/labs/VFileUpload/VFileUpload.sass new file mode 100644 index 00000000000..c791587866d --- /dev/null +++ b/packages/vuetify/src/labs/VFileUpload/VFileUpload.sass @@ -0,0 +1,33 @@ +@use '../../styles/tools' +@use '../../styles/settings' +@use './variables' as * + +@include tools.layer('components') + .v-file-upload + padding: 64px 0 + flex-direction: column + justify-content: center + align-items: center + + &.v-sheet + display: flex + border-radius: 4px + border-style: dashed + border-width: 2px + + &.v-file-upload--density-compact + padding: 32px 0 + flex-direction: row + gap: 1rem + + .v-file-upload-title + font-size: $file-upload-title-font-size + font-weight: 600 + + .v-file-upload-icon + font-size: 3rem + margin-bottom: 1rem + + .v-file-upload-divider + margin: 32px 0 + width: 100% diff --git a/packages/vuetify/src/labs/VFileUpload/VFileUpload.tsx b/packages/vuetify/src/labs/VFileUpload/VFileUpload.tsx index 844aea722b3..25a8d2b8c27 100644 --- a/packages/vuetify/src/labs/VFileUpload/VFileUpload.tsx +++ b/packages/vuetify/src/labs/VFileUpload/VFileUpload.tsx @@ -1,12 +1,46 @@ +// Styles +import './VFileUpload.sass' + // Components -import { VCard } from '@/components/VCard' -import { makeVCardProps } from '@/components/VCard/VCard' +import { VBtn } from '@/components/VBtn/VBtn' +import { VDefaultsProvider } from '@/components/VDefaultsProvider/VDefaultsProvider' +import { makeVDividerProps, VDivider } from '@/components/VDivider/VDivider' +import { VIcon } from '@/components/VIcon/VIcon' +import { makeVSheetProps, VSheet } from '@/components/VSheet/VSheet' + +// Composables +import { makeDensityProps, useDensity } from '@/composables/density' +import { IconValue } from '@/composables/icons' +import { useLocale } from '@/composables/locale' // Utilities -import { genericComponent, propsFactory, useRender } from '@/util' +import { computed } from 'vue' +import { genericComponent, only, propsFactory, useRender } from '@/util' export const makeVFileUploadProps = propsFactory({ - ...makeVCardProps(), + browseText: { + type: String, + default: '$vuetify.fileUpload.browse', + }, + dividerText: { + type: String, + default: '$vuetify.fileUpload.divider', + }, + title: { + type: String, + default: '$vuetify.fileUpload.title', + }, + subtitle: String, + icon: { + type: IconValue, + default: '$upload', + }, + + ...makeDensityProps(), + ...only(makeVDividerProps({ + length: 150, + }), ['length', 'thickness', 'opacity']), + ...makeVSheetProps(), }, 'VFileUpload') export const VFileUpload = genericComponent()({ @@ -14,16 +48,81 @@ export const VFileUpload = genericComponent()({ props: makeVFileUploadProps(), - setup (props) { + setup (props, { slots }) { + const { t } = useLocale() + const { densityClasses } = useDensity(props) + + const title = computed(() => { + return props.title.startsWith('$vuetify') + ? t(props.title) + : props.title + }) useRender(() => { - const cardProps = VCard.filterProps(props) + const hasTitle = !!(slots.title || title.value) + const hasIcon = !!(slots.icon || props.icon) + const cardProps = VSheet.filterProps(props) + const dividerProps = VDivider.filterProps(props) return ( - + { hasIcon && ( +
+ { !slots.icon ? ( + + ) : ( + + { slots.icon() } + + )} +
+ )} + + { hasTitle && ( +
+ { slots.title?.() ?? title.value } +
+ )} + + { props.density === 'default' && ( + <> +
+ { slots.divider?.() ?? ( + + { t(props.dividerText) } + + )} +
+ + -
+ { props.subtitle && ( +
+ { props.subtitle } +
+ )} + + )} + ) }) }, diff --git a/packages/vuetify/src/labs/VFileUpload/_variables.scss b/packages/vuetify/src/labs/VFileUpload/_variables.scss new file mode 100644 index 00000000000..87a4923e063 --- /dev/null +++ b/packages/vuetify/src/labs/VFileUpload/_variables.scss @@ -0,0 +1,4 @@ +@use '../../styles/tools'; +@use '../../styles/settings'; + +$file-upload-title-font-size: 1.5rem !default; diff --git a/packages/vuetify/src/labs/VFileUpload/index.ts b/packages/vuetify/src/labs/VFileUpload/index.ts new file mode 100644 index 00000000000..196726afe91 --- /dev/null +++ b/packages/vuetify/src/labs/VFileUpload/index.ts @@ -0,0 +1 @@ +export { VFileUpload } from './VFileUpload' diff --git a/packages/vuetify/src/locale/en.ts b/packages/vuetify/src/locale/en.ts index cf94f5e9786..0c59dac42d9 100644 --- a/packages/vuetify/src/locale/en.ts +++ b/packages/vuetify/src/locale/en.ts @@ -69,6 +69,11 @@ export default { counter: '{0} files', counterSize: '{0} files ({1} in total)', }, + fileUpload: { + title: 'Drag and drop files here', + divider: 'or', + browse: 'Browse Files', + }, timePicker: { am: 'AM', pm: 'PM', From 97388a7756eb88ae91639247c82f2e58591402b9 Mon Sep 17 00:00:00 2001 From: John Leider Date: Fri, 26 Apr 2024 23:26:21 -0500 Subject: [PATCH 03/16] feat(VFileUpload): add drag and drop highlighting --- .../src/labs/VFileUpload/VFileUpload.sass | 8 ++++ .../src/labs/VFileUpload/VFileUpload.tsx | 47 ++++++++++++++++++- 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/packages/vuetify/src/labs/VFileUpload/VFileUpload.sass b/packages/vuetify/src/labs/VFileUpload/VFileUpload.sass index c791587866d..72649443c43 100644 --- a/packages/vuetify/src/labs/VFileUpload/VFileUpload.sass +++ b/packages/vuetify/src/labs/VFileUpload/VFileUpload.sass @@ -8,6 +8,7 @@ flex-direction: column justify-content: center align-items: center + position: relative &.v-sheet display: flex @@ -20,6 +21,13 @@ flex-direction: row gap: 1rem + .v-overlay__scrim + pointer-events: none + + &--dragging + > * + pointer-events: none + .v-file-upload-title font-size: $file-upload-title-font-size font-weight: 600 diff --git a/packages/vuetify/src/labs/VFileUpload/VFileUpload.tsx b/packages/vuetify/src/labs/VFileUpload/VFileUpload.tsx index 25a8d2b8c27..4ce96de8d5b 100644 --- a/packages/vuetify/src/labs/VFileUpload/VFileUpload.tsx +++ b/packages/vuetify/src/labs/VFileUpload/VFileUpload.tsx @@ -6,15 +6,17 @@ import { VBtn } from '@/components/VBtn/VBtn' import { VDefaultsProvider } from '@/components/VDefaultsProvider/VDefaultsProvider' import { makeVDividerProps, VDivider } from '@/components/VDivider/VDivider' import { VIcon } from '@/components/VIcon/VIcon' +import { VOverlay } from '@/components/VOverlay/VOverlay' import { makeVSheetProps, VSheet } from '@/components/VSheet/VSheet' // Composables +import { makeDelayProps } from '@/composables/delay' import { makeDensityProps, useDensity } from '@/composables/density' import { IconValue } from '@/composables/icons' import { useLocale } from '@/composables/locale' // Utilities -import { computed } from 'vue' +import { computed, onMounted, onUnmounted, ref, shallowRef } from 'vue' import { genericComponent, only, propsFactory, useRender } from '@/util' export const makeVFileUploadProps = propsFactory({ @@ -35,7 +37,9 @@ export const makeVFileUploadProps = propsFactory({ type: IconValue, default: '$upload', }, + multiple: Boolean, + ...makeDelayProps(), ...makeDensityProps(), ...only(makeVDividerProps({ length: 150, @@ -52,11 +56,40 @@ export const VFileUpload = genericComponent()({ const { t } = useLocale() const { densityClasses } = useDensity(props) + const dragOver = shallowRef(false) + const vSheetRef = ref | null>(null) + const title = computed(() => { return props.title.startsWith('$vuetify') ? t(props.title) : props.title }) + + onMounted(() => { + vSheetRef.value?.$el.addEventListener('dragover', onDragOver) + vSheetRef.value?.$el.addEventListener('drop', onDrop) + }) + + onUnmounted(() => { + vSheetRef.value?.$el.removeEventListener('dragover', onDragOver) + vSheetRef.value?.$el.removeEventListener('drop', onDrop) + }) + + function onDragOver (e: DragEvent) { + e.preventDefault() + dragOver.value = true + } + + function onDragLeave (e: DragEvent) { + e.preventDefault() + dragOver.value = false + } + + function onDrop (e: DragEvent) { + e.preventDefault() + dragOver.value = false + } + useRender(() => { const hasTitle = !!(slots.title || title.value) const hasIcon = !!(slots.icon || props.icon) @@ -65,11 +98,18 @@ export const VFileUpload = genericComponent()({ return ( { hasIcon && (
@@ -122,6 +162,11 @@ export const VFileUpload = genericComponent()({ )} )} + + ) }) From 534347142129a0e97d595a418ef202189e570bfd Mon Sep 17 00:00:00 2001 From: John Leider Date: Sat, 27 Apr 2024 12:45:10 -0500 Subject: [PATCH 04/16] feat(VFileUpload): add visible items --- .../src/labs/VFileUpload/VFileUpload.sass | 7 + .../src/labs/VFileUpload/VFileUpload.tsx | 196 ++++++++++++------ .../src/labs/VFileUpload/VFileUploadItem.tsx | 64 ++++++ .../vuetify/src/labs/VFileUpload/index.ts | 1 + 4 files changed, 201 insertions(+), 67 deletions(-) create mode 100644 packages/vuetify/src/labs/VFileUpload/VFileUploadItem.tsx diff --git a/packages/vuetify/src/labs/VFileUpload/VFileUpload.sass b/packages/vuetify/src/labs/VFileUpload/VFileUpload.sass index 72649443c43..7d40bee5590 100644 --- a/packages/vuetify/src/labs/VFileUpload/VFileUpload.sass +++ b/packages/vuetify/src/labs/VFileUpload/VFileUpload.sass @@ -39,3 +39,10 @@ .v-file-upload-divider margin: 32px 0 width: 100% + + .v-file-upload-items + margin: 16px 0 + + .v-file-upload-item + &:not(:first-child) + margin-top: 8px diff --git a/packages/vuetify/src/labs/VFileUpload/VFileUpload.tsx b/packages/vuetify/src/labs/VFileUpload/VFileUpload.tsx index 4ce96de8d5b..c78841b834f 100644 --- a/packages/vuetify/src/labs/VFileUpload/VFileUpload.tsx +++ b/packages/vuetify/src/labs/VFileUpload/VFileUpload.tsx @@ -2,6 +2,7 @@ import './VFileUpload.sass' // Components +import { VFileUploadItem } from './VFileUploadItem' import { VBtn } from '@/components/VBtn/VBtn' import { VDefaultsProvider } from '@/components/VDefaultsProvider/VDefaultsProvider' import { makeVDividerProps, VDivider } from '@/components/VDivider/VDivider' @@ -14,10 +15,14 @@ import { makeDelayProps } from '@/composables/delay' import { makeDensityProps, useDensity } from '@/composables/density' import { IconValue } from '@/composables/icons' import { useLocale } from '@/composables/locale' +import { useProxiedModel } from '@/composables/proxiedModel' // Utilities import { computed, onMounted, onUnmounted, ref, shallowRef } from 'vue' -import { genericComponent, only, propsFactory, useRender } from '@/util' +import { genericComponent, humanReadableFileSize, only, propsFactory, useRender, wrapInArray } from '@/util' + +// Types +import type { PropType } from 'vue' export const makeVFileUploadProps = propsFactory({ browseText: { @@ -37,7 +42,15 @@ export const makeVFileUploadProps = propsFactory({ type: IconValue, default: '$upload', }, + modelValue: { + type: [Array, Object] as PropType, + default: null, + validator: (val: any) => { + return wrapInArray(val).every(v => v != null && typeof v === 'object') + }, + }, multiple: Boolean, + showSize: Boolean, ...makeDelayProps(), ...makeDensityProps(), @@ -52,13 +65,25 @@ export const VFileUpload = genericComponent()({ props: makeVFileUploadProps(), + emits: { + 'update:modelValue': (files: File[]) => true, + }, + setup (props, { slots }) { const { t } = useLocale() const { densityClasses } = useDensity(props) + const model = useProxiedModel( + props, + 'modelValue', + props.modelValue, + val => wrapInArray(val), + val => (props.multiple || Array.isArray(props.modelValue)) ? val : val[0], + ) const dragOver = shallowRef(false) const vSheetRef = ref | null>(null) + const base = computed(() => typeof props.showSize !== 'boolean' ? props.showSize : undefined) const title = computed(() => { return props.title.startsWith('$vuetify') ? t(props.title) @@ -77,6 +102,7 @@ export const VFileUpload = genericComponent()({ function onDragOver (e: DragEvent) { e.preventDefault() + e.stopImmediatePropagation() dragOver.value = true } @@ -87,7 +113,28 @@ export const VFileUpload = genericComponent()({ function onDrop (e: DragEvent) { e.preventDefault() + e.stopImmediatePropagation() dragOver.value = false + + const files = Array.from(e.dataTransfer?.files ?? []) + + if (!files.length) return + + if (!props.multiple) { + model.value = [files[0]] + + return + } + + for (const file of files) { + if (!model.value.some(f => f.name === file.name)) { + model.value.push(file) + } + } + } + + function onClickRemove (index: number) { + model.value = model.value.filter((_, i) => i !== index) } useRender(() => { @@ -97,77 +144,92 @@ export const VFileUpload = genericComponent()({ const dividerProps = VDivider.filterProps(props) return ( - - { hasIcon && ( -
- { !slots.icon ? ( - - ) : ( - - { slots.icon() } - - )} -
- )} - - { hasTitle && ( -
- { slots.title?.() ?? title.value } -
- )} - - { props.density === 'default' && ( - <> -
- { slots.divider?.() ?? ( - - { t(props.dividerText) } - + <> + + { hasIcon && ( +
+ { !slots.icon ? ( + + ) : ( + + { slots.icon() } + )}
+ )} - - - { props.subtitle && ( -
- { props.subtitle } + { hasTitle && ( +
+ { slots.title?.() ?? title.value } +
+ )} + + { props.density === 'default' && ( + <> +
+ { slots.divider?.() ?? ( + + { t(props.dividerText) } + + )}
- )} - - )} - - + + + { props.subtitle && ( +
+ { props.subtitle } +
+ )} + + )} + + + + + { model.value.length > 0 && ( +
+ { model.value.map((file, i) => ( + onClickRemove(i) } + /> + ))} +
+ )} + ) }) }, diff --git a/packages/vuetify/src/labs/VFileUpload/VFileUploadItem.tsx b/packages/vuetify/src/labs/VFileUpload/VFileUploadItem.tsx new file mode 100644 index 00000000000..ca55b769dd9 --- /dev/null +++ b/packages/vuetify/src/labs/VFileUpload/VFileUploadItem.tsx @@ -0,0 +1,64 @@ +// Components +import { VBtn } from '@/components/VBtn/VBtn' +import { VIcon } from '@/components/VIcon/VIcon' +import { makeVListItemProps, VListItem } from '@/components/VList/VListItem' + +// Utilities +import { genericComponent, propsFactory, useRender } from '@/util' + +// Types +import type { VListItemSlots } from '@/components/VList/VListItem' + +export const makeVFileUploadItemProps = propsFactory({ + + ...makeVListItemProps({ + border: true, + rounded: true, + lines: 'two' as const, + slim: true, + }), +}, 'VFileUploadItem') + +export const VFileUploadItem = genericComponent()({ + name: 'VFileUploadItem', + + props: makeVFileUploadItemProps(), + + emits: { + 'click:remove': () => true, + }, + + setup (props, { emit, slots }) { + function onClickRemove () { + emit('click:remove') + } + + useRender(() => { + const listItemProps = VListItem.filterProps(props) + + return ( + + {{ + ...slots, + prepend: slotProps => slots.prepend?.(slotProps) ?? ( + mdi-file-document + ), + append: slotProps => slots.append?.(slotProps) ?? ( + + ), + }} + + ) + }) + }, +}) + +export type VFileUploadItem = InstanceType diff --git a/packages/vuetify/src/labs/VFileUpload/index.ts b/packages/vuetify/src/labs/VFileUpload/index.ts index 196726afe91..3f85597a4d3 100644 --- a/packages/vuetify/src/labs/VFileUpload/index.ts +++ b/packages/vuetify/src/labs/VFileUpload/index.ts @@ -1 +1,2 @@ export { VFileUpload } from './VFileUpload' +export { VFileUploadItem } from './VFileUploadItem' From 363e69b602debac158934ec4f71d8a7e51cb5966 Mon Sep 17 00:00:00 2001 From: John Leider Date: Sat, 27 Apr 2024 12:46:34 -0500 Subject: [PATCH 05/16] fix(VFileUpload): remove startsWith check for locale --- packages/vuetify/src/labs/VFileUpload/VFileUpload.tsx | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/packages/vuetify/src/labs/VFileUpload/VFileUpload.tsx b/packages/vuetify/src/labs/VFileUpload/VFileUpload.tsx index c78841b834f..858430ddc65 100644 --- a/packages/vuetify/src/labs/VFileUpload/VFileUpload.tsx +++ b/packages/vuetify/src/labs/VFileUpload/VFileUpload.tsx @@ -84,11 +84,6 @@ export const VFileUpload = genericComponent()({ const vSheetRef = ref | null>(null) const base = computed(() => typeof props.showSize !== 'boolean' ? props.showSize : undefined) - const title = computed(() => { - return props.title.startsWith('$vuetify') - ? t(props.title) - : props.title - }) onMounted(() => { vSheetRef.value?.$el.addEventListener('dragover', onDragOver) @@ -138,7 +133,7 @@ export const VFileUpload = genericComponent()({ } useRender(() => { - const hasTitle = !!(slots.title || title.value) + const hasTitle = !!(slots.title || props.title) const hasIcon = !!(slots.icon || props.icon) const cardProps = VSheet.filterProps(props) const dividerProps = VDivider.filterProps(props) @@ -183,7 +178,7 @@ export const VFileUpload = genericComponent()({ { hasTitle && (
- { slots.title?.() ?? title.value } + { slots.title?.() ?? t(props.title) }
)} From 5c92c61035df93ea4d3e2df3588ba3cc053c39d2 Mon Sep 17 00:00:00 2001 From: John Leider Date: Sat, 27 Apr 2024 12:49:52 -0500 Subject: [PATCH 06/16] style(VFileUpload): fix typings --- .../vuetify/src/labs/VFileUpload/VFileUpload.tsx | 14 ++++++++++++-- .../src/labs/VFileUpload/VFileUploadItem.tsx | 2 +- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/packages/vuetify/src/labs/VFileUpload/VFileUpload.tsx b/packages/vuetify/src/labs/VFileUpload/VFileUpload.tsx index 858430ddc65..354395d6b78 100644 --- a/packages/vuetify/src/labs/VFileUpload/VFileUpload.tsx +++ b/packages/vuetify/src/labs/VFileUpload/VFileUpload.tsx @@ -24,6 +24,13 @@ import { genericComponent, humanReadableFileSize, only, propsFactory, useRender, // Types import type { PropType } from 'vue' +export type VFileUploadSlots = { + default: never + icon: never + title: never + divider: never +} + export const makeVFileUploadProps = propsFactory({ browseText: { type: String, @@ -60,7 +67,7 @@ export const makeVFileUploadProps = propsFactory({ ...makeVSheetProps(), }, 'VFileUpload') -export const VFileUpload = genericComponent()({ +export const VFileUpload = genericComponent()({ name: 'VFileUpload', props: makeVFileUploadProps(), @@ -123,7 +130,10 @@ export const VFileUpload = genericComponent()({ for (const file of files) { if (!model.value.some(f => f.name === file.name)) { - model.value.push(file) + model.value = [ + ...model.value, + file, + ] } } } diff --git a/packages/vuetify/src/labs/VFileUpload/VFileUploadItem.tsx b/packages/vuetify/src/labs/VFileUpload/VFileUploadItem.tsx index ca55b769dd9..5a81fc91ee3 100644 --- a/packages/vuetify/src/labs/VFileUpload/VFileUploadItem.tsx +++ b/packages/vuetify/src/labs/VFileUpload/VFileUploadItem.tsx @@ -10,7 +10,6 @@ import { genericComponent, propsFactory, useRender } from '@/util' import type { VListItemSlots } from '@/components/VList/VListItem' export const makeVFileUploadItemProps = propsFactory({ - ...makeVListItemProps({ border: true, rounded: true, @@ -26,6 +25,7 @@ export const VFileUploadItem = genericComponent()({ emits: { 'click:remove': () => true, + click: (e: MouseEvent | KeyboardEvent) => true, }, setup (props, { emit, slots }) { From 0e7491d43089d149a40b590e7fd2e69969f52b21 Mon Sep 17 00:00:00 2001 From: John Leider Date: Mon, 29 Apr 2024 16:32:11 -0500 Subject: [PATCH 07/16] feat(VFileUpload): add slots, inputNode, and other improvements --- .../src/labs/VFileUpload/VFileUpload.sass | 11 +++ .../src/labs/VFileUpload/VFileUpload.tsx | 95 +++++++++++++++---- .../src/labs/VFileUpload/VFileUploadItem.tsx | 30 +++++- 3 files changed, 114 insertions(+), 22 deletions(-) diff --git a/packages/vuetify/src/labs/VFileUpload/VFileUpload.sass b/packages/vuetify/src/labs/VFileUpload/VFileUpload.sass index 7d40bee5590..30875331cb0 100644 --- a/packages/vuetify/src/labs/VFileUpload/VFileUpload.sass +++ b/packages/vuetify/src/labs/VFileUpload/VFileUpload.sass @@ -28,6 +28,17 @@ > * pointer-events: none + &--clickable + cursor: pointer + + input[type="file"] + left: 0 + opacity: 0 + position: absolute + cursor: pointer + top: 0 + z-index: -1 + .v-file-upload-title font-size: $file-upload-title-font-size font-weight: 600 diff --git a/packages/vuetify/src/labs/VFileUpload/VFileUpload.tsx b/packages/vuetify/src/labs/VFileUpload/VFileUpload.tsx index 354395d6b78..685f30bb207 100644 --- a/packages/vuetify/src/labs/VFileUpload/VFileUpload.tsx +++ b/packages/vuetify/src/labs/VFileUpload/VFileUpload.tsx @@ -18,15 +18,21 @@ import { useLocale } from '@/composables/locale' import { useProxiedModel } from '@/composables/proxiedModel' // Utilities -import { computed, onMounted, onUnmounted, ref, shallowRef } from 'vue' -import { genericComponent, humanReadableFileSize, only, propsFactory, useRender, wrapInArray } from '@/util' +import { onMounted, onUnmounted, ref, shallowRef } from 'vue' +import { filterInputAttrs, genericComponent, only, propsFactory, useRender, wrapInArray } from '@/util' // Types -import type { PropType } from 'vue' +import type { PropType, VNode } from 'vue' export type VFileUploadSlots = { + browse: { + props: { onClick: (e: MouseEvent) => void } + } default: never icon: never + input: { + inputNode: VNode + } title: never divider: never } @@ -56,8 +62,11 @@ export const makeVFileUploadProps = propsFactory({ return wrapInArray(val).every(v => v != null && typeof v === 'object') }, }, + disabled: Boolean, + hideBrowse: Boolean, multiple: Boolean, showSize: Boolean, + name: String, ...makeDelayProps(), ...makeDensityProps(), @@ -70,13 +79,15 @@ export const makeVFileUploadProps = propsFactory({ export const VFileUpload = genericComponent()({ name: 'VFileUpload', + inheritAttrs: false, + props: makeVFileUploadProps(), emits: { 'update:modelValue': (files: File[]) => true, }, - setup (props, { slots }) { + setup (props, { attrs, slots }) { const { t } = useLocale() const { densityClasses } = useDensity(props) const model = useProxiedModel( @@ -89,8 +100,7 @@ export const VFileUpload = genericComponent()({ const dragOver = shallowRef(false) const vSheetRef = ref | null>(null) - - const base = computed(() => typeof props.showSize !== 'boolean' ? props.showSize : undefined) + const inputRef = ref(null) onMounted(() => { vSheetRef.value?.$el.addEventListener('dragover', onDragOver) @@ -128,14 +138,19 @@ export const VFileUpload = genericComponent()({ return } + const array = model.value.slice() + for (const file of files) { - if (!model.value.some(f => f.name === file.name)) { - model.value = [ - ...model.value, - file, - ] + if (!array.some(f => f.name === file.name)) { + array.push(file) } } + + model.value = array + } + + function onClick () { + inputRef.value?.click() } function onClickRemove (index: number) { @@ -145,8 +160,27 @@ export const VFileUpload = genericComponent()({ useRender(() => { const hasTitle = !!(slots.title || props.title) const hasIcon = !!(slots.icon || props.icon) + const hasBrowse = !!(!props.hideBrowse && (slots.browse || props.density === 'default')) const cardProps = VSheet.filterProps(props) const dividerProps = VDivider.filterProps(props) + const [rootAttrs, inputAttrs] = filterInputAttrs(attrs) + + const inputNode = ( + { + if (!e.target) return + + const target = e.target as HTMLInputElement + model.value = [...target.files ?? []] + }} + { ...inputAttrs } + /> + ) return ( <> @@ -156,6 +190,7 @@ export const VFileUpload = genericComponent()({ class={[ 'v-file-upload', { + 'v-file-upload--clickable': !hasBrowse, 'v-file-upload--dragging': dragOver.value, }, densityClasses.value, @@ -163,6 +198,8 @@ export const VFileUpload = genericComponent()({ onDragleave={ onDragLeave } onDragover={ onDragOver } onDrop={ onDrop } + onClick={ !hasBrowse ? onClick : undefined } + { ...rootAttrs } > { hasIcon && (
@@ -202,11 +239,32 @@ export const VFileUpload = genericComponent()({ )}
- + { hasBrowse && ( + <> + { !slots.browse ? ( + + ) : ( + + { slots.browse({ props: { onClick } }) } + + )} + + )} + + { slots.input?.({ inputNode }) ?? inputNode } { props.subtitle && (
@@ -220,6 +278,7 @@ export const VFileUpload = genericComponent()({ model-value={ dragOver.value } contained /> + { model.value.length > 0 && ( @@ -227,8 +286,8 @@ export const VFileUpload = genericComponent()({ { model.value.map((file, i) => ( onClickRemove(i) } /> ))} diff --git a/packages/vuetify/src/labs/VFileUpload/VFileUploadItem.tsx b/packages/vuetify/src/labs/VFileUpload/VFileUploadItem.tsx index 5a81fc91ee3..f738fa05e48 100644 --- a/packages/vuetify/src/labs/VFileUpload/VFileUploadItem.tsx +++ b/packages/vuetify/src/labs/VFileUpload/VFileUploadItem.tsx @@ -1,20 +1,32 @@ // Components +import { VAvatar } from '@/components/VAvatar/VAvatar' import { VBtn } from '@/components/VBtn/VBtn' -import { VIcon } from '@/components/VIcon/VIcon' import { makeVListItemProps, VListItem } from '@/components/VList/VListItem' // Utilities -import { genericComponent, propsFactory, useRender } from '@/util' +import { computed, ref, watchEffect } from 'vue' +import { genericComponent, humanReadableFileSize, propsFactory, useRender } from '@/util' // Types +import type { PropType } from 'vue' import type { VListItemSlots } from '@/components/VList/VListItem' export const makeVFileUploadItemProps = propsFactory({ + file: { + type: Object as PropType, + default: null, + }, + fileIcon: { + type: String, + // TODO: setup up a proper aliased icon + default: 'mdi-file-document', + }, + showSize: Boolean, + ...makeVListItemProps({ border: true, rounded: true, lines: 'two' as const, - slim: true, }), }, 'VFileUploadItem') @@ -29,22 +41,32 @@ export const VFileUploadItem = genericComponent()({ }, setup (props, { emit, slots }) { + const preview = ref() + const base = computed(() => typeof props.showSize !== 'boolean' ? props.showSize : undefined) + function onClickRemove () { emit('click:remove') } + watchEffect(() => { + preview.value = props.file?.type.startsWith('image') ? URL.createObjectURL(props.file) : undefined + }) + useRender(() => { const listItemProps = VListItem.filterProps(props) return ( {{ ...slots, prepend: slotProps => slots.prepend?.(slotProps) ?? ( - mdi-file-document + ), append: slotProps => slots.append?.(slotProps) ?? ( Date: Mon, 29 Apr 2024 18:56:03 -0500 Subject: [PATCH 08/16] refactor(VFileUpload): improve slot support --- .../src/labs/VFileUpload/VFileUpload.tsx | 40 ++++++++--- .../src/labs/VFileUpload/VFileUploadItem.tsx | 71 ++++++++++++++++--- 2 files changed, 92 insertions(+), 19 deletions(-) diff --git a/packages/vuetify/src/labs/VFileUpload/VFileUpload.tsx b/packages/vuetify/src/labs/VFileUpload/VFileUpload.tsx index 685f30bb207..d0cdf048008 100644 --- a/packages/vuetify/src/labs/VFileUpload/VFileUpload.tsx +++ b/packages/vuetify/src/labs/VFileUpload/VFileUpload.tsx @@ -33,6 +33,10 @@ export type VFileUploadSlots = { input: { inputNode: VNode } + item: { + file: File + props: { 'onClick:remove': () => void } + } title: never divider: never } @@ -283,14 +287,34 @@ export const VFileUpload = genericComponent()({ { model.value.length > 0 && (
- { model.value.map((file, i) => ( - onClickRemove(i) } - /> - ))} + { model.value.map((file, i) => { + const slotProps = { + file, + props: { + 'onClick:remove': () => onClickRemove(i), + }, + } + + return ( + + { slots.item?.(slotProps) ?? ( + onClickRemove(i) } + v-slots={ slots } + /> + )} + + ) + })}
)} diff --git a/packages/vuetify/src/labs/VFileUpload/VFileUploadItem.tsx b/packages/vuetify/src/labs/VFileUpload/VFileUploadItem.tsx index f738fa05e48..dfd3b3ef683 100644 --- a/packages/vuetify/src/labs/VFileUpload/VFileUploadItem.tsx +++ b/packages/vuetify/src/labs/VFileUpload/VFileUploadItem.tsx @@ -1,6 +1,7 @@ // Components import { VAvatar } from '@/components/VAvatar/VAvatar' import { VBtn } from '@/components/VBtn/VBtn' +import { VDefaultsProvider } from '@/components/VDefaultsProvider/VDefaultsProvider' import { makeVListItemProps, VListItem } from '@/components/VList/VListItem' // Utilities @@ -11,6 +12,12 @@ import { genericComponent, humanReadableFileSize, propsFactory, useRender } from import type { PropType } from 'vue' import type { VListItemSlots } from '@/components/VList/VListItem' +export type VFileUploadItemSlots = { + clear: { + props: { onClick: () => void } + } +} & VListItemSlots + export const makeVFileUploadItemProps = propsFactory({ file: { type: Object as PropType, @@ -30,7 +37,7 @@ export const makeVFileUploadItemProps = propsFactory({ }), }, 'VFileUploadItem') -export const VFileUploadItem = genericComponent()({ +export const VFileUploadItem = genericComponent()({ name: 'VFileUploadItem', props: makeVFileUploadItemProps(), @@ -61,20 +68,62 @@ export const VFileUploadItem = genericComponent()({ title={ props.title ?? props.file?.name } subtitle={ props.showSize ? humanReadableFileSize(props.file?.size, base.value) : props.file?.type } class="v-file-upload-item" - prependAvatar={ preview.value } > {{ ...slots, - prepend: slotProps => slots.prepend?.(slotProps) ?? ( - + prepend: slotProps => ( + <> + { !slots.prepend ? ( + + ) : ( + + { slots.prepend?.(slotProps) ?? ( + + )} + + )} + ), - append: slotProps => slots.append?.(slotProps) ?? ( - + append: slotProps => ( + <> + { !slots.clear ? ( + + ) : ( + + { slots.clear?.({ + ...slotProps, + props: { onClick: onClickRemove }, + }) ?? ()} + + )} + + { slots.append?.(slotProps) } + ), }}
From 04979d687cac2a388e9bcb9d411bda329c571abc Mon Sep 17 00:00:00 2001 From: John Leider Date: Mon, 29 Apr 2024 19:01:47 -0500 Subject: [PATCH 09/16] fix(VFileUpload): make sure to include inputNode in all densities --- packages/vuetify/src/labs/VFileUpload/VFileUpload.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/vuetify/src/labs/VFileUpload/VFileUpload.tsx b/packages/vuetify/src/labs/VFileUpload/VFileUpload.tsx index d0cdf048008..e2e8ff89e8f 100644 --- a/packages/vuetify/src/labs/VFileUpload/VFileUpload.tsx +++ b/packages/vuetify/src/labs/VFileUpload/VFileUpload.tsx @@ -268,8 +268,6 @@ export const VFileUpload = genericComponent()({ )} - { slots.input?.({ inputNode }) ?? inputNode } - { props.subtitle && (
{ props.subtitle } @@ -283,6 +281,7 @@ export const VFileUpload = genericComponent()({ contained /> + { slots.input?.({ inputNode }) ?? inputNode } { model.value.length > 0 && ( From 2cb5a3343117e46ec15b3c51c9fb569438e77f11 Mon Sep 17 00:00:00 2001 From: John Leider Date: Mon, 29 Apr 2024 19:09:25 -0500 Subject: [PATCH 10/16] fix(VFileUpload): clear when there are no more files --- packages/vuetify/src/labs/VFileUpload/VFileUpload.tsx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/vuetify/src/labs/VFileUpload/VFileUpload.tsx b/packages/vuetify/src/labs/VFileUpload/VFileUpload.tsx index e2e8ff89e8f..eb97b71edbb 100644 --- a/packages/vuetify/src/labs/VFileUpload/VFileUpload.tsx +++ b/packages/vuetify/src/labs/VFileUpload/VFileUpload.tsx @@ -159,6 +159,10 @@ export const VFileUpload = genericComponent()({ function onClickRemove (index: number) { model.value = model.value.filter((_, i) => i !== index) + + if (model.value.length > 0 || !inputRef.value) return + + inputRef.value.value = '' } useRender(() => { From 825825503335be382bcc4ba9113958e2c79be1a8 Mon Sep 17 00:00:00 2001 From: John Leider Date: Mon, 29 Apr 2024 19:33:25 -0500 Subject: [PATCH 11/16] feat(VFileUpload): add scrim color support --- packages/vuetify/src/labs/VFileUpload/VFileUpload.tsx | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/vuetify/src/labs/VFileUpload/VFileUpload.tsx b/packages/vuetify/src/labs/VFileUpload/VFileUpload.tsx index eb97b71edbb..1a932dca1c8 100644 --- a/packages/vuetify/src/labs/VFileUpload/VFileUpload.tsx +++ b/packages/vuetify/src/labs/VFileUpload/VFileUpload.tsx @@ -69,6 +69,10 @@ export const makeVFileUploadProps = propsFactory({ disabled: Boolean, hideBrowse: Boolean, multiple: Boolean, + scrim: { + type: [Boolean, String], + default: true, + }, showSize: Boolean, name: String, @@ -283,6 +287,7 @@ export const VFileUpload = genericComponent()({ { slots.input?.({ inputNode }) ?? inputNode } From 4eaad4919c7b8abc5b9888f94e9a584fec60202c Mon Sep 17 00:00:00 2001 From: John Leider Date: Mon, 29 Apr 2024 20:24:46 -0500 Subject: [PATCH 12/16] refactor(VFileUpload): create new sass variables --- .../src/labs/VFileUpload/VFileUpload.sass | 19 ++++++++++++++----- .../src/labs/VFileUpload/_variables.scss | 8 ++++++++ 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/packages/vuetify/src/labs/VFileUpload/VFileUpload.sass b/packages/vuetify/src/labs/VFileUpload/VFileUpload.sass index 30875331cb0..fda6057451d 100644 --- a/packages/vuetify/src/labs/VFileUpload/VFileUpload.sass +++ b/packages/vuetify/src/labs/VFileUpload/VFileUpload.sass @@ -4,7 +4,7 @@ @include tools.layer('components') .v-file-upload - padding: 64px 0 + padding: $file-upload-padding flex-direction: column justify-content: center align-items: center @@ -44,15 +44,24 @@ font-weight: 600 .v-file-upload-icon - font-size: 3rem - margin-bottom: 1rem + opacity: var(--v-medium-emphasis-opacity) + font-size: $file-upload-icon-font-size + margin-bottom: $file-upload-icon-margin-bottom + + .v-file-upload--density-comfortable & + font-size: $file-upload-icon-font-size - .5rem + margin-bottom: $file-upload-icon-margin-bottom - .5rem + + .v-file-upload--density-compact & + font-size: $file-upload-icon-font-size - 1rem + margin-bottom: $file-upload-icon-margin-bottom - 1rem .v-file-upload-divider - margin: 32px 0 + margin: $file-upload-divider-margin width: 100% .v-file-upload-items - margin: 16px 0 + margin: $file-upload-items-margin .v-file-upload-item &:not(:first-child) diff --git a/packages/vuetify/src/labs/VFileUpload/_variables.scss b/packages/vuetify/src/labs/VFileUpload/_variables.scss index 87a4923e063..38c3ba95aad 100644 --- a/packages/vuetify/src/labs/VFileUpload/_variables.scss +++ b/packages/vuetify/src/labs/VFileUpload/_variables.scss @@ -2,3 +2,11 @@ @use '../../styles/settings'; $file-upload-title-font-size: 1.5rem !default; +$file-upload-padding: 64px 0 !default; +$file-upload-border-radius: 4px !default; +$file-upload-border-width: 2px !default; +$file-upload-title-font-weight: 600 !default; +$file-upload-icon-font-size: 3rem !default; +$file-upload-icon-margin-bottom: 1rem !default; +$file-upload-divider-margin: 32px 0 !default; +$file-upload-items-margin: 16px 0 !default; From e6b041dd9def527e22683ee6636f6be66a583650 Mon Sep 17 00:00:00 2001 From: John Leider Date: Mon, 29 Apr 2024 21:01:38 -0500 Subject: [PATCH 13/16] feat(VFileUpload): hook up disabled and clearable functionality --- .../src/labs/VFileUpload/VFileUpload.sass | 4 ++ .../src/labs/VFileUpload/VFileUpload.tsx | 10 +++- .../src/labs/VFileUpload/VFileUploadItem.tsx | 49 ++++++++++--------- 3 files changed, 39 insertions(+), 24 deletions(-) diff --git a/packages/vuetify/src/labs/VFileUpload/VFileUpload.sass b/packages/vuetify/src/labs/VFileUpload/VFileUpload.sass index fda6057451d..1dec64f3ee4 100644 --- a/packages/vuetify/src/labs/VFileUpload/VFileUpload.sass +++ b/packages/vuetify/src/labs/VFileUpload/VFileUpload.sass @@ -24,6 +24,10 @@ .v-overlay__scrim pointer-events: none + &--disabled + pointer-events: none + opacity: var(--v-disabled-opacity) + &--dragging > * pointer-events: none diff --git a/packages/vuetify/src/labs/VFileUpload/VFileUpload.tsx b/packages/vuetify/src/labs/VFileUpload/VFileUpload.tsx index 1a932dca1c8..a48a79b21cc 100644 --- a/packages/vuetify/src/labs/VFileUpload/VFileUpload.tsx +++ b/packages/vuetify/src/labs/VFileUpload/VFileUpload.tsx @@ -66,6 +66,7 @@ export const makeVFileUploadProps = propsFactory({ return wrapInArray(val).every(v => v != null && typeof v === 'object') }, }, + clearable: Boolean, disabled: Boolean, hideBrowse: Boolean, multiple: Boolean, @@ -203,6 +204,7 @@ export const VFileUpload = genericComponent()({ 'v-file-upload', { 'v-file-upload--clickable': !hasBrowse, + 'v-file-upload--disabled': props.disabled, 'v-file-upload--dragging': dragOver.value, }, densityClasses.value, @@ -255,18 +257,20 @@ export const VFileUpload = genericComponent()({ <> { !slots.browse ? ( ) : ( @@ -309,6 +313,8 @@ export const VFileUpload = genericComponent()({ defaults={{ VFileUploadItem: { file, + clearable: props.clearable, + disabled: props.disabled, showSize: props.showSize, }, }} diff --git a/packages/vuetify/src/labs/VFileUpload/VFileUploadItem.tsx b/packages/vuetify/src/labs/VFileUpload/VFileUploadItem.tsx index dfd3b3ef683..24e5ea5ca30 100644 --- a/packages/vuetify/src/labs/VFileUpload/VFileUploadItem.tsx +++ b/packages/vuetify/src/labs/VFileUpload/VFileUploadItem.tsx @@ -19,6 +19,7 @@ export type VFileUploadItemSlots = { } & VListItemSlots export const makeVFileUploadItemProps = propsFactory({ + clearable: Boolean, file: { type: Object as PropType, default: null, @@ -98,28 +99,32 @@ export const VFileUploadItem = genericComponent()({ ), append: slotProps => ( <> - { !slots.clear ? ( - - ) : ( - - { slots.clear?.({ - ...slotProps, - props: { onClick: onClickRemove }, - }) ?? ()} - + { props.clearable && ( + <> + { !slots.clear ? ( + + ) : ( + + { slots.clear?.({ + ...slotProps, + props: { onClick: onClickRemove }, + }) ?? ()} + + )} + )} { slots.append?.(slotProps) } From b488234cb60c94f0d55926fb8c455ae66901ba76 Mon Sep 17 00:00:00 2001 From: John Leider Date: Mon, 29 Apr 2024 21:01:57 -0500 Subject: [PATCH 14/16] docs(VFileUpload): create docs page --- packages/docs/src/data/nav.json | 4 ++ .../docs/src/examples/v-file-upload/usage.vue | 44 ++++++++++++++ .../src/pages/en/components/file-upload.md | 60 +++++++++++++++++++ 3 files changed, 108 insertions(+) create mode 100644 packages/docs/src/examples/v-file-upload/usage.vue create mode 100644 packages/docs/src/pages/en/components/file-upload.md diff --git a/packages/docs/src/data/nav.json b/packages/docs/src/data/nav.json index 9d0a526bde2..d0f83422675 100644 --- a/packages/docs/src/data/nav.json +++ b/packages/docs/src/data/nav.json @@ -237,6 +237,10 @@ "title": "date-inputs", "subfolder": "components" }, + { + "title": "file-upload", + "subfolder": "components" + }, { "title": "number-inputs", "subfolder": "components" diff --git a/packages/docs/src/examples/v-file-upload/usage.vue b/packages/docs/src/examples/v-file-upload/usage.vue new file mode 100644 index 00000000000..bcc55d496b1 --- /dev/null +++ b/packages/docs/src/examples/v-file-upload/usage.vue @@ -0,0 +1,44 @@ + + + diff --git a/packages/docs/src/pages/en/components/file-upload.md b/packages/docs/src/pages/en/components/file-upload.md new file mode 100644 index 00000000000..cb06c39a5d1 --- /dev/null +++ b/packages/docs/src/pages/en/components/file-upload.md @@ -0,0 +1,60 @@ +--- +emphasized: true +meta: + title: File upload + description: The file upload component is a drag and drop area for uploading files. + keywords: file uploading, file upload, file drag and drop, file drop area, file dropzone, file upload component +related: + - /components/buttons/ + - /components/file-inputs/ + - /components/sheets/ +features: + report: true + label: 'C: VFileUpload' + github: '/labs/VFileUpload/' +--- + +# File upload + + + + + +::: warning + +This feature requires [v3.6.0](/getting-started/release-notes/?version=v3.6.0) + +::: + +## Installation + +Labs components require a manual import and installation of the component. + +```js { resource="src/plugins/vuetify.js" } +import { VFileUpload } from 'vuetify/labs/VFileUpload' + +export default createVuetify({ + components: { + VFileUpload, + }, +}) +``` + +## Usage + + + + + +## API + +| Component | Description | +| - | - | +| [v-file-upload](/api/v-file-upload/) | Primary Component | +| [v-file-input](/api/v-file-input/) | File input component | + + + +## Guide + +TODO From 43a7d69f90746aac6b1a6254e8bd63a7d4e3d1c2 Mon Sep 17 00:00:00 2001 From: John Leider Date: Thu, 10 Oct 2024 09:45:28 -0500 Subject: [PATCH 15/16] docs(VFileUpload): add documentation --- .../examples/v-file-upload/prop-content.vue | 8 ++++ .../examples/v-file-upload/prop-density.vue | 19 ++++++++ .../examples/v-file-upload/prop-disabled.vue | 3 ++ .../src/examples/v-file-upload/prop-scrim.vue | 3 ++ .../src/examples/v-file-upload/slot-item.vue | 26 ++++++++++ .../docs/src/examples/v-file-upload/usage.vue | 10 ++-- .../src/pages/en/components/file-upload.md | 47 +++++++++++++++++-- .../src/labs/VFileUpload/VFileUpload.sass | 3 ++ 8 files changed, 112 insertions(+), 7 deletions(-) create mode 100644 packages/docs/src/examples/v-file-upload/prop-content.vue create mode 100644 packages/docs/src/examples/v-file-upload/prop-density.vue create mode 100644 packages/docs/src/examples/v-file-upload/prop-disabled.vue create mode 100644 packages/docs/src/examples/v-file-upload/prop-scrim.vue create mode 100644 packages/docs/src/examples/v-file-upload/slot-item.vue diff --git a/packages/docs/src/examples/v-file-upload/prop-content.vue b/packages/docs/src/examples/v-file-upload/prop-content.vue new file mode 100644 index 00000000000..8d9a6070318 --- /dev/null +++ b/packages/docs/src/examples/v-file-upload/prop-content.vue @@ -0,0 +1,8 @@ + diff --git a/packages/docs/src/examples/v-file-upload/prop-density.vue b/packages/docs/src/examples/v-file-upload/prop-density.vue new file mode 100644 index 00000000000..12e8556663f --- /dev/null +++ b/packages/docs/src/examples/v-file-upload/prop-density.vue @@ -0,0 +1,19 @@ + + + diff --git a/packages/docs/src/examples/v-file-upload/prop-disabled.vue b/packages/docs/src/examples/v-file-upload/prop-disabled.vue new file mode 100644 index 00000000000..af636f7f41d --- /dev/null +++ b/packages/docs/src/examples/v-file-upload/prop-disabled.vue @@ -0,0 +1,3 @@ + diff --git a/packages/docs/src/examples/v-file-upload/prop-scrim.vue b/packages/docs/src/examples/v-file-upload/prop-scrim.vue new file mode 100644 index 00000000000..56d88c513ad --- /dev/null +++ b/packages/docs/src/examples/v-file-upload/prop-scrim.vue @@ -0,0 +1,3 @@ + diff --git a/packages/docs/src/examples/v-file-upload/slot-item.vue b/packages/docs/src/examples/v-file-upload/slot-item.vue new file mode 100644 index 00000000000..65f4772a483 --- /dev/null +++ b/packages/docs/src/examples/v-file-upload/slot-item.vue @@ -0,0 +1,26 @@ + + + diff --git a/packages/docs/src/examples/v-file-upload/usage.vue b/packages/docs/src/examples/v-file-upload/usage.vue index bcc55d496b1..417a9201e72 100644 --- a/packages/docs/src/examples/v-file-upload/usage.vue +++ b/packages/docs/src/examples/v-file-upload/usage.vue @@ -10,9 +10,11 @@
@@ -20,16 +22,18 @@