@vuetify/nightly 3.7.5-master.2024-12-03 → 3.7.5-master.2024-12-12
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/_component-variables-labs.sass +1 -0
- package/dist/json/attributes.json +3129 -2833
- package/dist/json/importMap-labs.json +22 -14
- package/dist/json/importMap.json +152 -152
- package/dist/json/tags.json +84 -0
- package/dist/json/web-types.json +6118 -5177
- package/dist/vuetify-labs.css +4145 -4074
- package/dist/vuetify-labs.d.ts +1314 -1
- package/dist/vuetify-labs.esm.js +331 -6
- package/dist/vuetify-labs.esm.js.map +1 -1
- package/dist/vuetify-labs.js +331 -6
- package/dist/vuetify-labs.min.css +2 -2
- package/dist/vuetify.css +3508 -3510
- package/dist/vuetify.d.ts +50 -48
- package/dist/vuetify.esm.js +16 -6
- package/dist/vuetify.esm.js.map +1 -1
- package/dist/vuetify.js +16 -6
- package/dist/vuetify.js.map +1 -1
- package/dist/vuetify.min.css +2 -2
- package/dist/vuetify.min.js +14 -13
- package/dist/vuetify.min.js.map +1 -1
- package/lib/components/VRangeSlider/VRangeSlider.mjs +2 -2
- package/lib/components/VRangeSlider/VRangeSlider.mjs.map +1 -1
- package/lib/components/VSelectionControl/VSelectionControl.css +1 -3
- package/lib/components/VSelectionControl/VSelectionControl.sass +1 -5
- package/lib/composables/virtual.mjs +4 -0
- package/lib/composables/virtual.mjs.map +1 -1
- package/lib/entry-bundler.mjs +1 -1
- package/lib/framework.mjs +1 -1
- package/lib/iconsets/mdi.mjs +2 -1
- package/lib/iconsets/mdi.mjs.map +1 -1
- package/lib/index.d.mts +50 -48
- package/lib/labs/VFileUpload/VFileUpload.css +74 -0
- package/lib/labs/VFileUpload/VFileUpload.mjs +241 -0
- package/lib/labs/VFileUpload/VFileUpload.mjs.map +1 -0
- package/lib/labs/VFileUpload/VFileUpload.sass +75 -0
- package/lib/labs/VFileUpload/VFileUploadItem.mjs +95 -0
- package/lib/labs/VFileUpload/VFileUploadItem.mjs.map +1 -0
- package/lib/labs/VFileUpload/_variables.scss +12 -0
- package/lib/labs/VFileUpload/index.d.mts +1365 -0
- package/lib/labs/VFileUpload/index.mjs +3 -0
- package/lib/labs/VFileUpload/index.mjs.map +1 -0
- package/lib/labs/components.d.mts +1348 -37
- package/lib/labs/components.mjs +1 -0
- package/lib/labs/components.mjs.map +1 -1
- package/lib/locale/af.mjs +5 -0
- package/lib/locale/af.mjs.map +1 -1
- package/lib/locale/ar.mjs +5 -0
- package/lib/locale/ar.mjs.map +1 -1
- package/lib/locale/az.mjs +5 -0
- package/lib/locale/az.mjs.map +1 -1
- package/lib/locale/bg.mjs +5 -0
- package/lib/locale/bg.mjs.map +1 -1
- package/lib/locale/ca.mjs +5 -0
- package/lib/locale/ca.mjs.map +1 -1
- package/lib/locale/ckb.mjs +5 -0
- package/lib/locale/ckb.mjs.map +1 -1
- package/lib/locale/cs.mjs +5 -0
- package/lib/locale/cs.mjs.map +1 -1
- package/lib/locale/da.mjs +5 -0
- package/lib/locale/da.mjs.map +1 -1
- package/lib/locale/de.mjs +5 -0
- package/lib/locale/de.mjs.map +1 -1
- package/lib/locale/el.mjs +5 -0
- package/lib/locale/el.mjs.map +1 -1
- package/lib/locale/en.mjs +5 -0
- package/lib/locale/en.mjs.map +1 -1
- package/lib/locale/es.mjs +5 -0
- package/lib/locale/es.mjs.map +1 -1
- package/lib/locale/et.mjs +5 -0
- package/lib/locale/et.mjs.map +1 -1
- package/lib/locale/fa.mjs +5 -0
- package/lib/locale/fa.mjs.map +1 -1
- package/lib/locale/fi.mjs +5 -0
- package/lib/locale/fi.mjs.map +1 -1
- package/lib/locale/fr.mjs +5 -0
- package/lib/locale/fr.mjs.map +1 -1
- package/lib/locale/he.mjs +5 -0
- package/lib/locale/he.mjs.map +1 -1
- package/lib/locale/hr.mjs +5 -0
- package/lib/locale/hr.mjs.map +1 -1
- package/lib/locale/hu.mjs +5 -0
- package/lib/locale/hu.mjs.map +1 -1
- package/lib/locale/id.mjs +5 -0
- package/lib/locale/id.mjs.map +1 -1
- package/lib/locale/index.d.mts +215 -0
- package/lib/locale/it.mjs +5 -0
- package/lib/locale/it.mjs.map +1 -1
- package/lib/locale/ja.mjs +5 -0
- package/lib/locale/ja.mjs.map +1 -1
- package/lib/locale/km.mjs +5 -0
- package/lib/locale/km.mjs.map +1 -1
- package/lib/locale/ko.mjs +5 -0
- package/lib/locale/ko.mjs.map +1 -1
- package/lib/locale/lt.mjs +5 -0
- package/lib/locale/lt.mjs.map +1 -1
- package/lib/locale/lv.mjs +5 -0
- package/lib/locale/lv.mjs.map +1 -1
- package/lib/locale/nl.mjs +5 -0
- package/lib/locale/nl.mjs.map +1 -1
- package/lib/locale/no.mjs +5 -0
- package/lib/locale/no.mjs.map +1 -1
- package/lib/locale/pl.mjs +5 -0
- package/lib/locale/pl.mjs.map +1 -1
- package/lib/locale/pt.mjs +5 -0
- package/lib/locale/pt.mjs.map +1 -1
- package/lib/locale/ro.mjs +5 -0
- package/lib/locale/ro.mjs.map +1 -1
- package/lib/locale/ru.mjs +5 -0
- package/lib/locale/ru.mjs.map +1 -1
- package/lib/locale/sk.mjs +5 -0
- package/lib/locale/sk.mjs.map +1 -1
- package/lib/locale/sl.mjs +5 -0
- package/lib/locale/sl.mjs.map +1 -1
- package/lib/locale/sr-Cyrl.mjs +5 -0
- package/lib/locale/sr-Cyrl.mjs.map +1 -1
- package/lib/locale/sr-Latn.mjs +5 -0
- package/lib/locale/sr-Latn.mjs.map +1 -1
- package/lib/locale/sv.mjs +5 -0
- package/lib/locale/sv.mjs.map +1 -1
- package/lib/locale/th.mjs +5 -0
- package/lib/locale/th.mjs.map +1 -1
- package/lib/locale/tr.mjs +5 -0
- package/lib/locale/tr.mjs.map +1 -1
- package/lib/locale/uk.mjs +5 -0
- package/lib/locale/uk.mjs.map +1 -1
- package/lib/locale/vi.mjs +5 -0
- package/lib/locale/vi.mjs.map +1 -1
- package/lib/locale/zh-Hans.mjs +5 -0
- package/lib/locale/zh-Hans.mjs.map +1 -1
- package/lib/locale/zh-Hant.mjs +5 -0
- package/lib/locale/zh-Hant.mjs.map +1 -1
- package/package.json +1 -1
@@ -0,0 +1,74 @@
|
|
1
|
+
.v-file-upload {
|
2
|
+
padding: 64px 0;
|
3
|
+
flex-direction: column;
|
4
|
+
justify-content: center;
|
5
|
+
align-items: center;
|
6
|
+
position: relative;
|
7
|
+
}
|
8
|
+
.v-file-upload.v-sheet {
|
9
|
+
display: flex;
|
10
|
+
border-radius: 4px;
|
11
|
+
border-style: dashed;
|
12
|
+
border-width: 2px;
|
13
|
+
}
|
14
|
+
.v-file-upload.v-file-upload--density-compact {
|
15
|
+
padding: 32px 0;
|
16
|
+
flex-direction: row;
|
17
|
+
gap: 1rem;
|
18
|
+
}
|
19
|
+
.v-file-upload .v-overlay__scrim {
|
20
|
+
pointer-events: none;
|
21
|
+
}
|
22
|
+
.v-file-upload--disabled {
|
23
|
+
pointer-events: none;
|
24
|
+
opacity: var(--v-disabled-opacity);
|
25
|
+
}
|
26
|
+
.v-file-upload--dragging > * {
|
27
|
+
pointer-events: none;
|
28
|
+
}
|
29
|
+
.v-file-upload--clickable {
|
30
|
+
cursor: pointer;
|
31
|
+
}
|
32
|
+
.v-file-upload input[type=file] {
|
33
|
+
left: 0;
|
34
|
+
opacity: 0;
|
35
|
+
position: absolute;
|
36
|
+
cursor: pointer;
|
37
|
+
top: 0;
|
38
|
+
z-index: -1;
|
39
|
+
}
|
40
|
+
|
41
|
+
.v-file-upload-title {
|
42
|
+
font-size: 1.5rem;
|
43
|
+
font-weight: 600;
|
44
|
+
}
|
45
|
+
|
46
|
+
.v-file-upload-icon {
|
47
|
+
opacity: var(--v-medium-emphasis-opacity);
|
48
|
+
font-size: 3rem;
|
49
|
+
margin-bottom: 1rem;
|
50
|
+
}
|
51
|
+
.v-file-upload--density-comfortable .v-file-upload-icon {
|
52
|
+
font-size: 2.5rem;
|
53
|
+
margin-bottom: 0.5rem;
|
54
|
+
}
|
55
|
+
.v-file-upload--density-compact .v-file-upload-icon {
|
56
|
+
font-size: 2rem;
|
57
|
+
margin-bottom: 0rem;
|
58
|
+
}
|
59
|
+
|
60
|
+
.v-file-upload-divider {
|
61
|
+
align-items: center;
|
62
|
+
display: flex;
|
63
|
+
margin: 32px 0;
|
64
|
+
justify-content: center;
|
65
|
+
width: 100%;
|
66
|
+
}
|
67
|
+
|
68
|
+
.v-file-upload-items {
|
69
|
+
margin: 16px 0;
|
70
|
+
}
|
71
|
+
|
72
|
+
.v-file-upload-item:not(:first-child) {
|
73
|
+
margin-top: 8px;
|
74
|
+
}
|
@@ -0,0 +1,241 @@
|
|
1
|
+
import { resolveDirective as _resolveDirective, Fragment as _Fragment, createVNode as _createVNode, mergeProps as _mergeProps } from "vue";
|
2
|
+
// Styles
|
3
|
+
import "./VFileUpload.css";
|
4
|
+
|
5
|
+
// Components
|
6
|
+
import { VFileUploadItem } from "./VFileUploadItem.mjs";
|
7
|
+
import { VBtn } from "../../components/VBtn/VBtn.mjs";
|
8
|
+
import { VDefaultsProvider } from "../../components/VDefaultsProvider/VDefaultsProvider.mjs";
|
9
|
+
import { makeVDividerProps, VDivider } from "../../components/VDivider/VDivider.mjs";
|
10
|
+
import { VIcon } from "../../components/VIcon/VIcon.mjs";
|
11
|
+
import { VOverlay } from "../../components/VOverlay/VOverlay.mjs";
|
12
|
+
import { makeVSheetProps, VSheet } from "../../components/VSheet/VSheet.mjs"; // Composables
|
13
|
+
import { makeDelayProps } from "../../composables/delay.mjs";
|
14
|
+
import { makeDensityProps, useDensity } from "../../composables/density.mjs";
|
15
|
+
import { IconValue } from "../../composables/icons.mjs";
|
16
|
+
import { useLocale } from "../../composables/locale.mjs";
|
17
|
+
import { useProxiedModel } from "../../composables/proxiedModel.mjs"; // Utilities
|
18
|
+
import { onMounted, onUnmounted, ref, shallowRef } from 'vue';
|
19
|
+
import { filterInputAttrs, genericComponent, only, propsFactory, useRender, wrapInArray } from "../../util/index.mjs"; // Types
|
20
|
+
export const makeVFileUploadProps = propsFactory({
|
21
|
+
browseText: {
|
22
|
+
type: String,
|
23
|
+
default: '$vuetify.fileUpload.browse'
|
24
|
+
},
|
25
|
+
dividerText: {
|
26
|
+
type: String,
|
27
|
+
default: '$vuetify.fileUpload.divider'
|
28
|
+
},
|
29
|
+
title: {
|
30
|
+
type: String,
|
31
|
+
default: '$vuetify.fileUpload.title'
|
32
|
+
},
|
33
|
+
subtitle: String,
|
34
|
+
icon: {
|
35
|
+
type: IconValue,
|
36
|
+
default: '$upload'
|
37
|
+
},
|
38
|
+
modelValue: {
|
39
|
+
type: [Array, Object],
|
40
|
+
default: null,
|
41
|
+
validator: val => {
|
42
|
+
return wrapInArray(val).every(v => v != null && typeof v === 'object');
|
43
|
+
}
|
44
|
+
},
|
45
|
+
clearable: Boolean,
|
46
|
+
disabled: Boolean,
|
47
|
+
hideBrowse: Boolean,
|
48
|
+
multiple: Boolean,
|
49
|
+
scrim: {
|
50
|
+
type: [Boolean, String],
|
51
|
+
default: true
|
52
|
+
},
|
53
|
+
showSize: Boolean,
|
54
|
+
name: String,
|
55
|
+
...makeDelayProps(),
|
56
|
+
...makeDensityProps(),
|
57
|
+
...only(makeVDividerProps({
|
58
|
+
length: 150
|
59
|
+
}), ['length', 'thickness', 'opacity']),
|
60
|
+
...makeVSheetProps()
|
61
|
+
}, 'VFileUpload');
|
62
|
+
export const VFileUpload = genericComponent()({
|
63
|
+
name: 'VFileUpload',
|
64
|
+
inheritAttrs: false,
|
65
|
+
props: makeVFileUploadProps(),
|
66
|
+
emits: {
|
67
|
+
'update:modelValue': files => true
|
68
|
+
},
|
69
|
+
setup(props, _ref) {
|
70
|
+
let {
|
71
|
+
attrs,
|
72
|
+
slots
|
73
|
+
} = _ref;
|
74
|
+
const {
|
75
|
+
t
|
76
|
+
} = useLocale();
|
77
|
+
const {
|
78
|
+
densityClasses
|
79
|
+
} = useDensity(props);
|
80
|
+
const model = useProxiedModel(props, 'modelValue', props.modelValue, val => wrapInArray(val), val => props.multiple || Array.isArray(props.modelValue) ? val : val[0]);
|
81
|
+
const dragOver = shallowRef(false);
|
82
|
+
const vSheetRef = ref(null);
|
83
|
+
const inputRef = ref(null);
|
84
|
+
onMounted(() => {
|
85
|
+
vSheetRef.value?.$el.addEventListener('dragover', onDragOver);
|
86
|
+
vSheetRef.value?.$el.addEventListener('drop', onDrop);
|
87
|
+
});
|
88
|
+
onUnmounted(() => {
|
89
|
+
vSheetRef.value?.$el.removeEventListener('dragover', onDragOver);
|
90
|
+
vSheetRef.value?.$el.removeEventListener('drop', onDrop);
|
91
|
+
});
|
92
|
+
function onDragOver(e) {
|
93
|
+
e.preventDefault();
|
94
|
+
e.stopImmediatePropagation();
|
95
|
+
dragOver.value = true;
|
96
|
+
}
|
97
|
+
function onDragLeave(e) {
|
98
|
+
e.preventDefault();
|
99
|
+
dragOver.value = false;
|
100
|
+
}
|
101
|
+
function onDrop(e) {
|
102
|
+
e.preventDefault();
|
103
|
+
e.stopImmediatePropagation();
|
104
|
+
dragOver.value = false;
|
105
|
+
const files = Array.from(e.dataTransfer?.files ?? []);
|
106
|
+
if (!files.length) return;
|
107
|
+
if (!props.multiple) {
|
108
|
+
model.value = [files[0]];
|
109
|
+
return;
|
110
|
+
}
|
111
|
+
const array = model.value.slice();
|
112
|
+
for (const file of files) {
|
113
|
+
if (!array.some(f => f.name === file.name)) {
|
114
|
+
array.push(file);
|
115
|
+
}
|
116
|
+
}
|
117
|
+
model.value = array;
|
118
|
+
}
|
119
|
+
function onClick() {
|
120
|
+
inputRef.value?.click();
|
121
|
+
}
|
122
|
+
function onClickRemove(index) {
|
123
|
+
model.value = model.value.filter((_, i) => i !== index);
|
124
|
+
if (model.value.length > 0 || !inputRef.value) return;
|
125
|
+
inputRef.value.value = '';
|
126
|
+
}
|
127
|
+
useRender(() => {
|
128
|
+
const hasTitle = !!(slots.title || props.title);
|
129
|
+
const hasIcon = !!(slots.icon || props.icon);
|
130
|
+
const hasBrowse = !!(!props.hideBrowse && (slots.browse || props.density === 'default'));
|
131
|
+
const cardProps = VSheet.filterProps(props);
|
132
|
+
const dividerProps = VDivider.filterProps(props);
|
133
|
+
const [rootAttrs, inputAttrs] = filterInputAttrs(attrs);
|
134
|
+
const inputNode = _createVNode("input", _mergeProps({
|
135
|
+
"ref": inputRef,
|
136
|
+
"type": "file",
|
137
|
+
"disabled": props.disabled,
|
138
|
+
"multiple": props.multiple,
|
139
|
+
"name": props.name,
|
140
|
+
"onChange": e => {
|
141
|
+
if (!e.target) return;
|
142
|
+
const target = e.target;
|
143
|
+
model.value = [...(target.files ?? [])];
|
144
|
+
}
|
145
|
+
}, inputAttrs), null);
|
146
|
+
return _createVNode(_Fragment, null, [_createVNode(VSheet, _mergeProps({
|
147
|
+
"ref": vSheetRef
|
148
|
+
}, cardProps, {
|
149
|
+
"class": ['v-file-upload', {
|
150
|
+
'v-file-upload--clickable': !hasBrowse,
|
151
|
+
'v-file-upload--disabled': props.disabled,
|
152
|
+
'v-file-upload--dragging': dragOver.value
|
153
|
+
}, densityClasses.value],
|
154
|
+
"onDragleave": onDragLeave,
|
155
|
+
"onDragover": onDragOver,
|
156
|
+
"onDrop": onDrop,
|
157
|
+
"onClick": !hasBrowse ? onClick : undefined
|
158
|
+
}, rootAttrs), {
|
159
|
+
default: () => [hasIcon && _createVNode("div", {
|
160
|
+
"key": "icon",
|
161
|
+
"class": "v-file-upload-icon"
|
162
|
+
}, [!slots.icon ? _createVNode(VIcon, {
|
163
|
+
"key": "icon-icon",
|
164
|
+
"icon": props.icon
|
165
|
+
}, null) : _createVNode(VDefaultsProvider, {
|
166
|
+
"key": "icon-defaults",
|
167
|
+
"defaults": {
|
168
|
+
VIcon: {
|
169
|
+
icon: props.icon
|
170
|
+
}
|
171
|
+
}
|
172
|
+
}, {
|
173
|
+
default: () => [slots.icon()]
|
174
|
+
})]), hasTitle && _createVNode("div", {
|
175
|
+
"key": "title",
|
176
|
+
"class": "v-file-upload-title"
|
177
|
+
}, [slots.title?.() ?? t(props.title)]), props.density === 'default' && _createVNode(_Fragment, null, [_createVNode("div", {
|
178
|
+
"key": "upload-divider",
|
179
|
+
"class": "v-file-upload-divider"
|
180
|
+
}, [slots.divider?.() ?? _createVNode(VDivider, dividerProps, {
|
181
|
+
default: () => [t(props.dividerText)]
|
182
|
+
})]), hasBrowse && _createVNode(_Fragment, null, [!slots.browse ? _createVNode(VBtn, {
|
183
|
+
"readonly": props.disabled,
|
184
|
+
"size": "large",
|
185
|
+
"text": t(props.browseText),
|
186
|
+
"variant": "tonal",
|
187
|
+
"onClick": onClick
|
188
|
+
}, null) : _createVNode(VDefaultsProvider, {
|
189
|
+
"defaults": {
|
190
|
+
VBtn: {
|
191
|
+
readonly: props.disabled,
|
192
|
+
size: 'large',
|
193
|
+
text: t(props.browseText),
|
194
|
+
variant: 'tonal'
|
195
|
+
}
|
196
|
+
}
|
197
|
+
}, {
|
198
|
+
default: () => [slots.browse({
|
199
|
+
props: {
|
200
|
+
onClick
|
201
|
+
}
|
202
|
+
})]
|
203
|
+
})]), props.subtitle && _createVNode("div", {
|
204
|
+
"class": "v-file-upload-subtitle"
|
205
|
+
}, [props.subtitle])]), _createVNode(VOverlay, {
|
206
|
+
"model-value": dragOver.value,
|
207
|
+
"contained": true,
|
208
|
+
"scrim": props.scrim
|
209
|
+
}, null), slots.input?.({
|
210
|
+
inputNode
|
211
|
+
}) ?? inputNode]
|
212
|
+
}), model.value.length > 0 && _createVNode("div", {
|
213
|
+
"class": "v-file-upload-items"
|
214
|
+
}, [model.value.map((file, i) => {
|
215
|
+
const slotProps = {
|
216
|
+
file,
|
217
|
+
props: {
|
218
|
+
'onClick:remove': () => onClickRemove(i)
|
219
|
+
}
|
220
|
+
};
|
221
|
+
return _createVNode(VDefaultsProvider, {
|
222
|
+
"key": i,
|
223
|
+
"defaults": {
|
224
|
+
VFileUploadItem: {
|
225
|
+
file,
|
226
|
+
clearable: props.clearable,
|
227
|
+
disabled: props.disabled,
|
228
|
+
showSize: props.showSize
|
229
|
+
}
|
230
|
+
}
|
231
|
+
}, {
|
232
|
+
default: () => [slots.item?.(slotProps) ?? _createVNode(VFileUploadItem, {
|
233
|
+
"key": i,
|
234
|
+
"onClick:remove": () => onClickRemove(i)
|
235
|
+
}, slots)]
|
236
|
+
});
|
237
|
+
})])]);
|
238
|
+
});
|
239
|
+
}
|
240
|
+
});
|
241
|
+
//# sourceMappingURL=VFileUpload.mjs.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"VFileUpload.mjs","names":["VFileUploadItem","VBtn","VDefaultsProvider","makeVDividerProps","VDivider","VIcon","VOverlay","makeVSheetProps","VSheet","makeDelayProps","makeDensityProps","useDensity","IconValue","useLocale","useProxiedModel","onMounted","onUnmounted","ref","shallowRef","filterInputAttrs","genericComponent","only","propsFactory","useRender","wrapInArray","makeVFileUploadProps","browseText","type","String","default","dividerText","title","subtitle","icon","modelValue","Array","Object","validator","val","every","v","clearable","Boolean","disabled","hideBrowse","multiple","scrim","showSize","name","length","VFileUpload","inheritAttrs","props","emits","files","setup","_ref","attrs","slots","t","densityClasses","model","isArray","dragOver","vSheetRef","inputRef","value","$el","addEventListener","onDragOver","onDrop","removeEventListener","e","preventDefault","stopImmediatePropagation","onDragLeave","from","dataTransfer","array","slice","file","some","f","push","onClick","click","onClickRemove","index","filter","_","i","hasTitle","hasIcon","hasBrowse","browse","density","cardProps","filterProps","dividerProps","rootAttrs","inputAttrs","inputNode","_createVNode","_mergeProps","target","_Fragment","undefined","divider","readonly","size","text","variant","input","map","slotProps","onClick:remove","item"],"sources":["../../../src/labs/VFileUpload/VFileUpload.tsx"],"sourcesContent":["// Styles\nimport './VFileUpload.sass'\n\n// Components\nimport { VFileUploadItem } from './VFileUploadItem'\nimport { VBtn } from '@/components/VBtn/VBtn'\nimport { VDefaultsProvider } from '@/components/VDefaultsProvider/VDefaultsProvider'\nimport { makeVDividerProps, VDivider } from '@/components/VDivider/VDivider'\nimport { VIcon } from '@/components/VIcon/VIcon'\nimport { VOverlay } from '@/components/VOverlay/VOverlay'\nimport { makeVSheetProps, VSheet } from '@/components/VSheet/VSheet'\n\n// Composables\nimport { makeDelayProps } from '@/composables/delay'\nimport { makeDensityProps, useDensity } from '@/composables/density'\nimport { IconValue } from '@/composables/icons'\nimport { useLocale } from '@/composables/locale'\nimport { useProxiedModel } from '@/composables/proxiedModel'\n\n// Utilities\nimport { onMounted, onUnmounted, ref, shallowRef } from 'vue'\nimport { filterInputAttrs, genericComponent, only, propsFactory, useRender, wrapInArray } from '@/util'\n\n// Types\nimport type { PropType, VNode } from 'vue'\n\nexport type VFileUploadSlots = {\n browse: {\n props: { onClick: (e: MouseEvent) => void }\n }\n default: never\n icon: never\n input: {\n inputNode: VNode\n }\n item: {\n file: File\n props: { 'onClick:remove': () => void }\n }\n title: never\n divider: never\n}\n\nexport const makeVFileUploadProps = propsFactory({\n browseText: {\n type: String,\n default: '$vuetify.fileUpload.browse',\n },\n dividerText: {\n type: String,\n default: '$vuetify.fileUpload.divider',\n },\n title: {\n type: String,\n default: '$vuetify.fileUpload.title',\n },\n subtitle: String,\n icon: {\n type: IconValue,\n default: '$upload',\n },\n modelValue: {\n type: [Array, Object] as PropType<File[] | File>,\n default: null,\n validator: (val: any) => {\n return wrapInArray(val).every(v => v != null && typeof v === 'object')\n },\n },\n clearable: Boolean,\n disabled: Boolean,\n hideBrowse: Boolean,\n multiple: Boolean,\n scrim: {\n type: [Boolean, String],\n default: true,\n },\n showSize: Boolean,\n name: String,\n\n ...makeDelayProps(),\n ...makeDensityProps(),\n ...only(makeVDividerProps({\n length: 150,\n }), ['length', 'thickness', 'opacity']),\n ...makeVSheetProps(),\n}, 'VFileUpload')\n\nexport const VFileUpload = genericComponent<VFileUploadSlots>()({\n name: 'VFileUpload',\n\n inheritAttrs: false,\n\n props: makeVFileUploadProps(),\n\n emits: {\n 'update:modelValue': (files: File[]) => true,\n },\n\n setup (props, { attrs, slots }) {\n const { t } = useLocale()\n const { densityClasses } = useDensity(props)\n const model = useProxiedModel(\n props,\n 'modelValue',\n props.modelValue,\n val => wrapInArray(val),\n val => (props.multiple || Array.isArray(props.modelValue)) ? val : val[0],\n )\n\n const dragOver = shallowRef(false)\n const vSheetRef = ref<InstanceType<typeof VSheet> | null>(null)\n const inputRef = ref<HTMLInputElement | null>(null)\n\n onMounted(() => {\n vSheetRef.value?.$el.addEventListener('dragover', onDragOver)\n vSheetRef.value?.$el.addEventListener('drop', onDrop)\n })\n\n onUnmounted(() => {\n vSheetRef.value?.$el.removeEventListener('dragover', onDragOver)\n vSheetRef.value?.$el.removeEventListener('drop', onDrop)\n })\n\n function onDragOver (e: DragEvent) {\n e.preventDefault()\n e.stopImmediatePropagation()\n dragOver.value = true\n }\n\n function onDragLeave (e: DragEvent) {\n e.preventDefault()\n dragOver.value = false\n }\n\n function onDrop (e: DragEvent) {\n e.preventDefault()\n e.stopImmediatePropagation()\n dragOver.value = false\n\n const files = Array.from(e.dataTransfer?.files ?? [])\n\n if (!files.length) return\n\n if (!props.multiple) {\n model.value = [files[0]]\n\n return\n }\n\n const array = model.value.slice()\n\n for (const file of files) {\n if (!array.some(f => f.name === file.name)) {\n array.push(file)\n }\n }\n\n model.value = array\n }\n\n function onClick () {\n inputRef.value?.click()\n }\n\n function onClickRemove (index: number) {\n model.value = model.value.filter((_, i) => i !== index)\n\n if (model.value.length > 0 || !inputRef.value) return\n\n inputRef.value.value = ''\n }\n\n useRender(() => {\n const hasTitle = !!(slots.title || props.title)\n const hasIcon = !!(slots.icon || props.icon)\n const hasBrowse = !!(!props.hideBrowse && (slots.browse || props.density === 'default'))\n const cardProps = VSheet.filterProps(props)\n const dividerProps = VDivider.filterProps(props)\n const [rootAttrs, inputAttrs] = filterInputAttrs(attrs)\n\n const inputNode = (\n <input\n ref={ inputRef }\n type=\"file\"\n disabled={ props.disabled }\n multiple={ props.multiple }\n name={ props.name }\n onChange={ e => {\n if (!e.target) return\n\n const target = e.target as HTMLInputElement\n model.value = [...target.files ?? []]\n }}\n { ...inputAttrs }\n />\n )\n\n return (\n <>\n <VSheet\n ref={ vSheetRef }\n { ...cardProps }\n class={[\n 'v-file-upload',\n {\n 'v-file-upload--clickable': !hasBrowse,\n 'v-file-upload--disabled': props.disabled,\n 'v-file-upload--dragging': dragOver.value,\n },\n densityClasses.value,\n ]}\n onDragleave={ onDragLeave }\n onDragover={ onDragOver }\n onDrop={ onDrop }\n onClick={ !hasBrowse ? onClick : undefined }\n { ...rootAttrs }\n >\n { hasIcon && (\n <div key=\"icon\" class=\"v-file-upload-icon\">\n { !slots.icon ? (\n <VIcon\n key=\"icon-icon\"\n icon={ props.icon }\n />\n ) : (\n <VDefaultsProvider\n key=\"icon-defaults\"\n defaults={{\n VIcon: {\n icon: props.icon,\n },\n }}\n >\n { slots.icon() }\n </VDefaultsProvider>\n )}\n </div>\n )}\n\n { hasTitle && (\n <div key=\"title\" class=\"v-file-upload-title\">\n { slots.title?.() ?? t(props.title) }\n </div>\n )}\n\n { props.density === 'default' && (\n <>\n <div key=\"upload-divider\" class=\"v-file-upload-divider\">\n { slots.divider?.() ?? (\n <VDivider { ...dividerProps }>\n { t(props.dividerText) }\n </VDivider>\n )}\n </div>\n\n { hasBrowse && (\n <>\n { !slots.browse ? (\n <VBtn\n readonly={ props.disabled }\n size=\"large\"\n text={ t(props.browseText) }\n variant=\"tonal\"\n onClick={ onClick }\n />\n ) : (\n <VDefaultsProvider\n defaults={{\n VBtn: {\n readonly: props.disabled,\n size: 'large',\n text: t(props.browseText),\n variant: 'tonal',\n },\n }}\n >\n { slots.browse({ props: { onClick } }) }\n </VDefaultsProvider>\n )}\n </>\n )}\n\n { props.subtitle && (\n <div class=\"v-file-upload-subtitle\">\n { props.subtitle }\n </div>\n )}\n </>\n )}\n\n <VOverlay\n model-value={ dragOver.value }\n contained\n scrim={ props.scrim }\n />\n\n { slots.input?.({ inputNode }) ?? inputNode }\n </VSheet>\n\n { model.value.length > 0 && (\n <div class=\"v-file-upload-items\">\n { model.value.map((file, i) => {\n const slotProps = {\n file,\n props: {\n 'onClick:remove': () => onClickRemove(i),\n },\n }\n\n return (\n <VDefaultsProvider\n key={ i }\n defaults={{\n VFileUploadItem: {\n file,\n clearable: props.clearable,\n disabled: props.disabled,\n showSize: props.showSize,\n },\n }}\n >\n { slots.item?.(slotProps) ?? (\n <VFileUploadItem\n key={ i }\n onClick:remove={ () => onClickRemove(i) }\n v-slots={ slots }\n />\n )}\n </VDefaultsProvider>\n )\n })}\n </div>\n )}\n </>\n )\n })\n },\n})\n\nexport type VFileUpload = InstanceType<typeof VFileUpload>\n"],"mappings":"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","ignoreList":[]}
|
@@ -0,0 +1,75 @@
|
|
1
|
+
@use '../../styles/tools'
|
2
|
+
@use '../../styles/settings'
|
3
|
+
@use './variables' as *
|
4
|
+
|
5
|
+
@include tools.layer('components')
|
6
|
+
.v-file-upload
|
7
|
+
padding: $file-upload-padding
|
8
|
+
flex-direction: column
|
9
|
+
justify-content: center
|
10
|
+
align-items: center
|
11
|
+
position: relative
|
12
|
+
|
13
|
+
&.v-sheet
|
14
|
+
display: flex
|
15
|
+
border-radius: 4px
|
16
|
+
border-style: dashed
|
17
|
+
border-width: 2px
|
18
|
+
|
19
|
+
&.v-file-upload--density-compact
|
20
|
+
padding: 32px 0
|
21
|
+
flex-direction: row
|
22
|
+
gap: 1rem
|
23
|
+
|
24
|
+
.v-overlay__scrim
|
25
|
+
pointer-events: none
|
26
|
+
|
27
|
+
&--disabled
|
28
|
+
pointer-events: none
|
29
|
+
opacity: var(--v-disabled-opacity)
|
30
|
+
|
31
|
+
&--dragging
|
32
|
+
> *
|
33
|
+
pointer-events: none
|
34
|
+
|
35
|
+
&--clickable
|
36
|
+
cursor: pointer
|
37
|
+
|
38
|
+
input[type="file"]
|
39
|
+
left: 0
|
40
|
+
opacity: 0
|
41
|
+
position: absolute
|
42
|
+
cursor: pointer
|
43
|
+
top: 0
|
44
|
+
z-index: -1
|
45
|
+
|
46
|
+
.v-file-upload-title
|
47
|
+
font-size: $file-upload-title-font-size
|
48
|
+
font-weight: 600
|
49
|
+
|
50
|
+
.v-file-upload-icon
|
51
|
+
opacity: var(--v-medium-emphasis-opacity)
|
52
|
+
font-size: $file-upload-icon-font-size
|
53
|
+
margin-bottom: $file-upload-icon-margin-bottom
|
54
|
+
|
55
|
+
.v-file-upload--density-comfortable &
|
56
|
+
font-size: $file-upload-icon-font-size - .5rem
|
57
|
+
margin-bottom: $file-upload-icon-margin-bottom - .5rem
|
58
|
+
|
59
|
+
.v-file-upload--density-compact &
|
60
|
+
font-size: $file-upload-icon-font-size - 1rem
|
61
|
+
margin-bottom: $file-upload-icon-margin-bottom - 1rem
|
62
|
+
|
63
|
+
.v-file-upload-divider
|
64
|
+
align-items: center
|
65
|
+
display: flex
|
66
|
+
margin: $file-upload-divider-margin
|
67
|
+
justify-content: center
|
68
|
+
width: 100%
|
69
|
+
|
70
|
+
.v-file-upload-items
|
71
|
+
margin: $file-upload-items-margin
|
72
|
+
|
73
|
+
.v-file-upload-item
|
74
|
+
&:not(:first-child)
|
75
|
+
margin-top: 8px
|
@@ -0,0 +1,95 @@
|
|
1
|
+
import { mergeProps as _mergeProps, createVNode as _createVNode, Fragment as _Fragment } from "vue";
|
2
|
+
// Components
|
3
|
+
import { VAvatar } from "../../components/VAvatar/VAvatar.mjs";
|
4
|
+
import { VBtn } from "../../components/VBtn/VBtn.mjs";
|
5
|
+
import { VDefaultsProvider } from "../../components/VDefaultsProvider/VDefaultsProvider.mjs";
|
6
|
+
import { makeVListItemProps, VListItem } from "../../components/VList/VListItem.mjs"; // Utilities
|
7
|
+
import { computed, ref, watchEffect } from 'vue';
|
8
|
+
import { genericComponent, humanReadableFileSize, propsFactory, useRender } from "../../util/index.mjs"; // Types
|
9
|
+
export const makeVFileUploadItemProps = propsFactory({
|
10
|
+
clearable: Boolean,
|
11
|
+
file: {
|
12
|
+
type: Object,
|
13
|
+
default: null
|
14
|
+
},
|
15
|
+
fileIcon: {
|
16
|
+
type: String,
|
17
|
+
// TODO: setup up a proper aliased icon
|
18
|
+
default: 'mdi-file-document'
|
19
|
+
},
|
20
|
+
showSize: Boolean,
|
21
|
+
...makeVListItemProps({
|
22
|
+
border: true,
|
23
|
+
rounded: true,
|
24
|
+
lines: 'two'
|
25
|
+
})
|
26
|
+
}, 'VFileUploadItem');
|
27
|
+
export const VFileUploadItem = genericComponent()({
|
28
|
+
name: 'VFileUploadItem',
|
29
|
+
props: makeVFileUploadItemProps(),
|
30
|
+
emits: {
|
31
|
+
'click:remove': () => true,
|
32
|
+
click: e => true
|
33
|
+
},
|
34
|
+
setup(props, _ref) {
|
35
|
+
let {
|
36
|
+
emit,
|
37
|
+
slots
|
38
|
+
} = _ref;
|
39
|
+
const preview = ref();
|
40
|
+
const base = computed(() => typeof props.showSize !== 'boolean' ? props.showSize : undefined);
|
41
|
+
function onClickRemove() {
|
42
|
+
emit('click:remove');
|
43
|
+
}
|
44
|
+
watchEffect(() => {
|
45
|
+
preview.value = props.file?.type.startsWith('image') ? URL.createObjectURL(props.file) : undefined;
|
46
|
+
});
|
47
|
+
useRender(() => {
|
48
|
+
const listItemProps = VListItem.filterProps(props);
|
49
|
+
return _createVNode(VListItem, _mergeProps(listItemProps, {
|
50
|
+
"title": props.title ?? props.file?.name,
|
51
|
+
"subtitle": props.showSize ? humanReadableFileSize(props.file?.size, base.value) : props.file?.type,
|
52
|
+
"class": "v-file-upload-item"
|
53
|
+
}), {
|
54
|
+
...slots,
|
55
|
+
prepend: slotProps => _createVNode(_Fragment, null, [!slots.prepend ? _createVNode(VAvatar, {
|
56
|
+
"icon": props.fileIcon,
|
57
|
+
"image": preview.value,
|
58
|
+
"rounded": true
|
59
|
+
}, null) : _createVNode(VDefaultsProvider, {
|
60
|
+
"defaults": {
|
61
|
+
VAvatar: {
|
62
|
+
image: preview.value,
|
63
|
+
icon: !preview.value ? props.fileIcon : undefined,
|
64
|
+
rounded: true
|
65
|
+
}
|
66
|
+
}
|
67
|
+
}, {
|
68
|
+
default: () => [slots.prepend?.(slotProps) ?? _createVNode(VAvatar, null, null)]
|
69
|
+
})]),
|
70
|
+
append: slotProps => _createVNode(_Fragment, null, [props.clearable && _createVNode(_Fragment, null, [!slots.clear ? _createVNode(VBtn, {
|
71
|
+
"icon": "$clear",
|
72
|
+
"density": "comfortable",
|
73
|
+
"variant": "text",
|
74
|
+
"onClick": onClickRemove
|
75
|
+
}, null) : _createVNode(VDefaultsProvider, {
|
76
|
+
"defaults": {
|
77
|
+
VBtn: {
|
78
|
+
icon: '$clear',
|
79
|
+
density: 'comfortable',
|
80
|
+
variant: 'text'
|
81
|
+
}
|
82
|
+
}
|
83
|
+
}, {
|
84
|
+
default: () => [slots.clear?.({
|
85
|
+
...slotProps,
|
86
|
+
props: {
|
87
|
+
onClick: onClickRemove
|
88
|
+
}
|
89
|
+
}) ?? _createVNode(VBtn, null, null)]
|
90
|
+
})]), slots.append?.(slotProps)])
|
91
|
+
});
|
92
|
+
});
|
93
|
+
}
|
94
|
+
});
|
95
|
+
//# sourceMappingURL=VFileUploadItem.mjs.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"VFileUploadItem.mjs","names":["VAvatar","VBtn","VDefaultsProvider","makeVListItemProps","VListItem","computed","ref","watchEffect","genericComponent","humanReadableFileSize","propsFactory","useRender","makeVFileUploadItemProps","clearable","Boolean","file","type","Object","default","fileIcon","String","showSize","border","rounded","lines","VFileUploadItem","name","props","emits","click:remove","click","e","setup","_ref","emit","slots","preview","base","undefined","onClickRemove","value","startsWith","URL","createObjectURL","listItemProps","filterProps","_createVNode","_mergeProps","title","size","prepend","slotProps","_Fragment","image","icon","append","clear","density","variant","onClick"],"sources":["../../../src/labs/VFileUpload/VFileUploadItem.tsx"],"sourcesContent":["// Components\nimport { VAvatar } from '@/components/VAvatar/VAvatar'\nimport { VBtn } from '@/components/VBtn/VBtn'\nimport { VDefaultsProvider } from '@/components/VDefaultsProvider/VDefaultsProvider'\nimport { makeVListItemProps, VListItem } from '@/components/VList/VListItem'\n\n// Utilities\nimport { computed, ref, watchEffect } from 'vue'\nimport { genericComponent, humanReadableFileSize, propsFactory, useRender } from '@/util'\n\n// Types\nimport type { PropType } from 'vue'\nimport type { VListItemSlots } from '@/components/VList/VListItem'\n\nexport type VFileUploadItemSlots = {\n clear: {\n props: { onClick: () => void }\n }\n} & VListItemSlots\n\nexport const makeVFileUploadItemProps = propsFactory({\n clearable: Boolean,\n file: {\n type: Object as PropType<File>,\n default: null,\n },\n fileIcon: {\n type: String,\n // TODO: setup up a proper aliased icon\n default: 'mdi-file-document',\n },\n showSize: Boolean,\n\n ...makeVListItemProps({\n border: true,\n rounded: true,\n lines: 'two' as const,\n }),\n}, 'VFileUploadItem')\n\nexport const VFileUploadItem = genericComponent<VFileUploadItemSlots>()({\n name: 'VFileUploadItem',\n\n props: makeVFileUploadItemProps(),\n\n emits: {\n 'click:remove': () => true,\n click: (e: MouseEvent | KeyboardEvent) => true,\n },\n\n setup (props, { emit, slots }) {\n const preview = ref()\n const base = computed(() => typeof props.showSize !== 'boolean' ? props.showSize : undefined)\n\n function onClickRemove () {\n emit('click:remove')\n }\n\n watchEffect(() => {\n preview.value = props.file?.type.startsWith('image') ? URL.createObjectURL(props.file) : undefined\n })\n\n useRender(() => {\n const listItemProps = VListItem.filterProps(props)\n\n return (\n <VListItem\n { ...listItemProps }\n title={ props.title ?? props.file?.name }\n subtitle={ props.showSize ? humanReadableFileSize(props.file?.size, base.value) : props.file?.type }\n class=\"v-file-upload-item\"\n >\n {{\n ...slots,\n prepend: slotProps => (\n <>\n { !slots.prepend ? (\n <VAvatar\n icon={ props.fileIcon }\n image={ preview.value }\n rounded\n />\n ) : (\n <VDefaultsProvider\n defaults={{\n VAvatar: {\n image: preview.value,\n icon: !preview.value ? props.fileIcon : undefined,\n rounded: true,\n },\n }}\n >\n { slots.prepend?.(slotProps) ?? (\n <VAvatar />\n )}\n </VDefaultsProvider>\n )}\n </>\n ),\n append: slotProps => (\n <>\n { props.clearable && (\n <>\n { !slots.clear ? (\n <VBtn\n icon=\"$clear\"\n density=\"comfortable\"\n variant=\"text\"\n onClick={ onClickRemove }\n />\n ) : (\n <VDefaultsProvider\n defaults={{\n VBtn: {\n icon: '$clear',\n density: 'comfortable',\n variant: 'text',\n },\n }}\n >\n { slots.clear?.({\n ...slotProps,\n props: { onClick: onClickRemove },\n }) ?? (<VBtn />)}\n </VDefaultsProvider>\n )}\n </>\n )}\n\n { slots.append?.(slotProps) }\n </>\n ),\n }}\n </VListItem>\n )\n })\n },\n})\n\nexport type VFileUploadItem = InstanceType<typeof VFileUploadItem>\n"],"mappings":"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","ignoreList":[]}
|
@@ -0,0 +1,12 @@
|
|
1
|
+
@use '../../styles/tools';
|
2
|
+
@use '../../styles/settings';
|
3
|
+
|
4
|
+
$file-upload-title-font-size: 1.5rem !default;
|
5
|
+
$file-upload-padding: 64px 0 !default;
|
6
|
+
$file-upload-border-radius: 4px !default;
|
7
|
+
$file-upload-border-width: 2px !default;
|
8
|
+
$file-upload-title-font-weight: 600 !default;
|
9
|
+
$file-upload-icon-font-size: 3rem !default;
|
10
|
+
$file-upload-icon-margin-bottom: 1rem !default;
|
11
|
+
$file-upload-divider-margin: 32px 0 !default;
|
12
|
+
$file-upload-items-margin: 16px 0 !default;
|