@bagelink/vue 0.0.568 → 0.0.575
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/form/inputs/FileUpload.vue.d.ts +2 -2
- package/dist/components/form/inputs/FileUpload.vue.d.ts.map +1 -1
- package/dist/components/form/inputs/SelectInput.vue.d.ts +2 -0
- package/dist/components/form/inputs/SelectInput.vue.d.ts.map +1 -1
- package/dist/index.cjs +655 -318
- package/dist/index.mjs +655 -318
- package/dist/style.css +22 -22
- package/package.json +10 -10
- package/src/components/MaterialIcon.vue +2 -3
- package/src/components/form/inputs/FileUpload.vue +20 -21
- package/src/components/form/inputs/SelectInput.vue +42 -25
package/dist/style.css
CHANGED
|
@@ -1909,10 +1909,10 @@ svg.leaflet-image-layer.leaflet-interactive path {
|
|
|
1909
1909
|
}
|
|
1910
1910
|
.resize-observer[data-v-b329ee4c]{position:absolute;top:0;left:0;z-index:-1;width:100%;height:100%;border:none;background-color:transparent;pointer-events:none;display:block;overflow:hidden;opacity:0}.resize-observer[data-v-b329ee4c] object{display:block;position:absolute;top:0;left:0;height:100%;width:100%;overflow:hidden;pointer-events:none;z-index:-1}.v-popper__popper{z-index:10000;top:0;left:0;outline:none}.v-popper__popper.v-popper__popper--hidden{visibility:hidden;opacity:0;transition:opacity .15s,visibility .15s;pointer-events:none}.v-popper__popper.v-popper__popper--shown{visibility:visible;opacity:1;transition:opacity .15s}.v-popper__popper.v-popper__popper--skip-transition,.v-popper__popper.v-popper__popper--skip-transition>.v-popper__wrapper{transition:none!important}.v-popper__backdrop{position:absolute;top:0;left:0;width:100%;height:100%;display:none}.v-popper__inner{position:relative;box-sizing:border-box;overflow-y:auto}.v-popper__inner>div{position:relative;z-index:1;max-width:inherit;max-height:inherit}.v-popper__arrow-container{position:absolute;width:10px;height:10px}.v-popper__popper--arrow-overflow .v-popper__arrow-container,.v-popper__popper--no-positioning .v-popper__arrow-container{display:none}.v-popper__arrow-inner,.v-popper__arrow-outer{border-style:solid;position:absolute;top:0;left:0;width:0;height:0}.v-popper__arrow-inner{visibility:hidden;border-width:7px}.v-popper__arrow-outer{border-width:6px}.v-popper__popper[data-popper-placement^=top] .v-popper__arrow-inner,.v-popper__popper[data-popper-placement^=bottom] .v-popper__arrow-inner{left:-2px}.v-popper__popper[data-popper-placement^=top] .v-popper__arrow-outer,.v-popper__popper[data-popper-placement^=bottom] .v-popper__arrow-outer{left:-1px}.v-popper__popper[data-popper-placement^=top] .v-popper__arrow-inner,.v-popper__popper[data-popper-placement^=top] .v-popper__arrow-outer{border-bottom-width:0;border-left-color:transparent!important;border-right-color:transparent!important;border-bottom-color:transparent!important}.v-popper__popper[data-popper-placement^=top] .v-popper__arrow-inner{top:-2px}.v-popper__popper[data-popper-placement^=bottom] .v-popper__arrow-container{top:0}.v-popper__popper[data-popper-placement^=bottom] .v-popper__arrow-inner,.v-popper__popper[data-popper-placement^=bottom] .v-popper__arrow-outer{border-top-width:0;border-left-color:transparent!important;border-right-color:transparent!important;border-top-color:transparent!important}.v-popper__popper[data-popper-placement^=bottom] .v-popper__arrow-inner{top:-4px}.v-popper__popper[data-popper-placement^=bottom] .v-popper__arrow-outer{top:-6px}.v-popper__popper[data-popper-placement^=left] .v-popper__arrow-inner,.v-popper__popper[data-popper-placement^=right] .v-popper__arrow-inner{top:-2px}.v-popper__popper[data-popper-placement^=left] .v-popper__arrow-outer,.v-popper__popper[data-popper-placement^=right] .v-popper__arrow-outer{top:-1px}.v-popper__popper[data-popper-placement^=right] .v-popper__arrow-inner,.v-popper__popper[data-popper-placement^=right] .v-popper__arrow-outer{border-left-width:0;border-left-color:transparent!important;border-top-color:transparent!important;border-bottom-color:transparent!important}.v-popper__popper[data-popper-placement^=right] .v-popper__arrow-inner{left:-4px}.v-popper__popper[data-popper-placement^=right] .v-popper__arrow-outer{left:-6px}.v-popper__popper[data-popper-placement^=left] .v-popper__arrow-container{right:-10px}.v-popper__popper[data-popper-placement^=left] .v-popper__arrow-inner,.v-popper__popper[data-popper-placement^=left] .v-popper__arrow-outer{border-right-width:0;border-top-color:transparent!important;border-right-color:transparent!important;border-bottom-color:transparent!important}.v-popper__popper[data-popper-placement^=left] .v-popper__arrow-inner{left:-2px}.v-popper--theme-tooltip .v-popper__inner{background:rgba(0,0,0,.8);color:#fff;border-radius:6px;padding:7px 12px 6px}.v-popper--theme-tooltip .v-popper__arrow-outer{border-color:#000c}.v-popper--theme-dropdown .v-popper__inner{background:#fff;color:#000;border-radius:6px;border:1px solid #ddd;box-shadow:0 6px 30px #0000001a}.v-popper--theme-dropdown .v-popper__arrow-inner{visibility:visible;border-color:#fff}.v-popper--theme-dropdown .v-popper__arrow-outer{border-color:#ddd}
|
|
1911
1911
|
|
|
1912
|
-
.selectinput[data-v-
|
|
1912
|
+
.selectinput[data-v-c5344871] {
|
|
1913
1913
|
width: 100%;
|
|
1914
1914
|
}
|
|
1915
|
-
.selectinput-option[data-v-
|
|
1915
|
+
.selectinput-option[data-v-c5344871] {
|
|
1916
1916
|
padding: 6px 12px;
|
|
1917
1917
|
cursor: pointer;
|
|
1918
1918
|
border-radius: 5px;
|
|
@@ -1923,14 +1923,14 @@ svg.leaflet-image-layer.leaflet-interactive path {
|
|
|
1923
1923
|
width: 100%;
|
|
1924
1924
|
font-size: var(--input-font-size);
|
|
1925
1925
|
}
|
|
1926
|
-
.selectinput-options[data-v-
|
|
1926
|
+
.selectinput-options[data-v-c5344871] {
|
|
1927
1927
|
max-height: 300px;
|
|
1928
1928
|
overflow-y: auto;
|
|
1929
1929
|
}
|
|
1930
|
-
.selectinput-option[data-v-
|
|
1930
|
+
.selectinput-option[data-v-c5344871]:hover {
|
|
1931
1931
|
background: var(--bgl-gray-20);
|
|
1932
1932
|
}
|
|
1933
|
-
.isEmpty p[data-v-
|
|
1933
|
+
.isEmpty p[data-v-c5344871] {
|
|
1934
1934
|
opacity: 0.3;
|
|
1935
1935
|
}
|
|
1936
1936
|
|
|
@@ -2337,7 +2337,7 @@ svg.leaflet-image-layer.leaflet-interactive path {
|
|
|
2337
2337
|
color: var(--bgl-white);
|
|
2338
2338
|
}
|
|
2339
2339
|
|
|
2340
|
-
.bagel-input .fileUploadWrap[data-v-
|
|
2340
|
+
.bagel-input .fileUploadWrap[data-v-853e75be] {
|
|
2341
2341
|
--width: 320px;
|
|
2342
2342
|
outline: 1px solid var(--border-color);
|
|
2343
2343
|
border-radius: var(--input-border-radius);
|
|
@@ -2350,7 +2350,7 @@ svg.leaflet-image-layer.leaflet-interactive path {
|
|
|
2350
2350
|
overflow-y: auto;
|
|
2351
2351
|
background: var(--input-bg);
|
|
2352
2352
|
}
|
|
2353
|
-
.previewName[data-v-
|
|
2353
|
+
.previewName[data-v-853e75be] {
|
|
2354
2354
|
padding: 0.5rem;
|
|
2355
2355
|
text-align: start;
|
|
2356
2356
|
color: var(--input-color);
|
|
@@ -2360,18 +2360,18 @@ svg.leaflet-image-layer.leaflet-interactive path {
|
|
|
2360
2360
|
align-items: center;
|
|
2361
2361
|
padding-inline: 14px;
|
|
2362
2362
|
}
|
|
2363
|
-
.previewName p[data-v-
|
|
2363
|
+
.previewName p[data-v-853e75be] {
|
|
2364
2364
|
overflow: hidden;
|
|
2365
2365
|
text-overflow: ellipsis;
|
|
2366
2366
|
white-space: nowrap;
|
|
2367
2367
|
}
|
|
2368
|
-
.imagePreviewWrap[data-v-
|
|
2368
|
+
.imagePreviewWrap[data-v-853e75be] {
|
|
2369
2369
|
background: var(--input-bg);
|
|
2370
2370
|
border-radius: var(--input-border-radius);
|
|
2371
2371
|
padding: 5px;
|
|
2372
2372
|
min-height: 90px;
|
|
2373
2373
|
}
|
|
2374
|
-
img.preview[data-v-
|
|
2374
|
+
img.preview[data-v-853e75be] {
|
|
2375
2375
|
/* max-height: calc(var(--width) / 2); */
|
|
2376
2376
|
/* max-width: calc(var(--width) * 2); */
|
|
2377
2377
|
width: 40px;
|
|
@@ -2381,7 +2381,7 @@ img.preview[data-v-1ce244aa] {
|
|
|
2381
2381
|
background: var(--bgl-gray-light);
|
|
2382
2382
|
box-shadow: 0 0 10px #00000012;
|
|
2383
2383
|
}
|
|
2384
|
-
img.preview.single[data-v-
|
|
2384
|
+
img.preview.single[data-v-853e75be] {
|
|
2385
2385
|
max-width: var(--width);
|
|
2386
2386
|
width: auto;
|
|
2387
2387
|
object-fit: contain;
|
|
@@ -2389,18 +2389,18 @@ img.preview.single[data-v-1ce244aa] {
|
|
|
2389
2389
|
max-height: calc(var(--width) / 2);
|
|
2390
2390
|
margin: 1rem;
|
|
2391
2391
|
}
|
|
2392
|
-
.fileUploadWrap.dragover[data-v-
|
|
2393
|
-
.fileUploadWrap[data-v-
|
|
2392
|
+
.fileUploadWrap.dragover[data-v-853e75be],
|
|
2393
|
+
.fileUploadWrap[data-v-853e75be]:hover {
|
|
2394
2394
|
box-shadow: inset 0 0 10px #00000012;
|
|
2395
2395
|
}
|
|
2396
|
-
.bagel-input .fileUploadWrap.fileDropZone[data-v-
|
|
2396
|
+
.bagel-input .fileUploadWrap.fileDropZone[data-v-853e75be] {
|
|
2397
2397
|
background: var(--input-bg);
|
|
2398
2398
|
display: flex;
|
|
2399
2399
|
align-items: center;
|
|
2400
2400
|
justify-content: center;
|
|
2401
2401
|
color: var(--bgl-gray);
|
|
2402
2402
|
}
|
|
2403
|
-
.pie[data-v-
|
|
2403
|
+
.pie[data-v-853e75be] {
|
|
2404
2404
|
width: 30px;
|
|
2405
2405
|
height: 30px;
|
|
2406
2406
|
position: relative;
|
|
@@ -2408,7 +2408,7 @@ img.preview.single[data-v-1ce244aa] {
|
|
|
2408
2408
|
align-items: center;
|
|
2409
2409
|
justify-content: center;
|
|
2410
2410
|
}
|
|
2411
|
-
.pie[data-v-
|
|
2411
|
+
.pie[data-v-853e75be]:before {
|
|
2412
2412
|
content: '';
|
|
2413
2413
|
position: absolute;
|
|
2414
2414
|
border-radius: 50%;
|
|
@@ -2426,26 +2426,26 @@ img.preview.single[data-v-1ce244aa] {
|
|
|
2426
2426
|
#000 calc(100% - var(--b))
|
|
2427
2427
|
);
|
|
2428
2428
|
}
|
|
2429
|
-
.pie .success[data-v-
|
|
2429
|
+
.pie .success[data-v-853e75be] {
|
|
2430
2430
|
transform: scale(0);
|
|
2431
2431
|
opacity: 0;
|
|
2432
2432
|
transition: all 0.3s ease-in-out;
|
|
2433
2433
|
}
|
|
2434
|
-
.pie .progress[data-v-
|
|
2434
|
+
.pie .progress[data-v-853e75be] {
|
|
2435
2435
|
position: absolute;
|
|
2436
2436
|
font-size: 10px;
|
|
2437
2437
|
}
|
|
2438
|
-
.pie.complete .progress[data-v-
|
|
2438
|
+
.pie.complete .progress[data-v-853e75be] {
|
|
2439
2439
|
display: none;
|
|
2440
2440
|
}
|
|
2441
|
-
.pie.complete .success[data-v-
|
|
2441
|
+
.pie.complete .success[data-v-853e75be] {
|
|
2442
2442
|
transform: scale(1.3);
|
|
2443
2443
|
opacity: 1;
|
|
2444
2444
|
}
|
|
2445
|
-
.pie.complete[data-v-
|
|
2445
|
+
.pie.complete[data-v-853e75be]:before {
|
|
2446
2446
|
background: conic-gradient(var(--bgl-green) calc(var(--p) * 1%), #0000 0);
|
|
2447
2447
|
}
|
|
2448
|
-
.pie.complete[data-v-
|
|
2448
|
+
.pie.complete[data-v-853e75be] {
|
|
2449
2449
|
color: var(--bgl-green);
|
|
2450
2450
|
}
|
|
2451
2451
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bagelink/vue",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.575",
|
|
5
5
|
"description": "Bagel core sdk packages",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "Neveh Allon",
|
|
@@ -105,15 +105,15 @@
|
|
|
105
105
|
"access": "public"
|
|
106
106
|
},
|
|
107
107
|
"dependencies": {
|
|
108
|
-
"@tiptap/extension-image": "^2.
|
|
109
|
-
"@tiptap/extension-table": "^2.
|
|
110
|
-
"@tiptap/extension-table-cell": "^2.
|
|
111
|
-
"@tiptap/extension-table-header": "^2.
|
|
112
|
-
"@tiptap/extension-table-row": "^2.
|
|
113
|
-
"@tiptap/extension-youtube": "^2.
|
|
114
|
-
"@tiptap/pm": "^2.
|
|
115
|
-
"@tiptap/starter-kit": "^2.
|
|
116
|
-
"@tiptap/vue-3": "^2.
|
|
108
|
+
"@tiptap/extension-image": "^2.5.1",
|
|
109
|
+
"@tiptap/extension-table": "^2.5.1",
|
|
110
|
+
"@tiptap/extension-table-cell": "^2.5.1",
|
|
111
|
+
"@tiptap/extension-table-header": "^2.5.1",
|
|
112
|
+
"@tiptap/extension-table-row": "^2.5.1",
|
|
113
|
+
"@tiptap/extension-youtube": "^2.5.1",
|
|
114
|
+
"@tiptap/pm": "^2.5.1",
|
|
115
|
+
"@tiptap/starter-kit": "^2.5.1",
|
|
116
|
+
"@tiptap/vue-3": "^2.5.1",
|
|
117
117
|
"@vuepic/vue-datepicker": "^8.8.1",
|
|
118
118
|
"@vueuse/core": "^10.11.0",
|
|
119
119
|
"axios": "^1.7.2",
|
|
@@ -6,17 +6,16 @@ defineProps<{
|
|
|
6
6
|
name?: MaterialIcons
|
|
7
7
|
size?: number | string
|
|
8
8
|
color?: string
|
|
9
|
-
weight?: number | string
|
|
9
|
+
weight?: number | string
|
|
10
10
|
}>()
|
|
11
11
|
</script>
|
|
12
12
|
|
|
13
13
|
<template>
|
|
14
|
-
<span class="bgl_icon-font" :style="{ fontSize: `${size}rem`, color,
|
|
14
|
+
<span class="bgl_icon-font" :style="{ 'fontSize': `${size}rem`, color, 'font-variation-settings': `'wght' ${weight || 400}` }">
|
|
15
15
|
{{ icon || name }}
|
|
16
16
|
</span>
|
|
17
17
|
</template>
|
|
18
18
|
|
|
19
|
-
|
|
20
19
|
<style scoped>
|
|
21
20
|
|
|
22
21
|
</style>
|
|
@@ -6,12 +6,14 @@ const props = defineProps<{
|
|
|
6
6
|
label?: string
|
|
7
7
|
multiple?: boolean
|
|
8
8
|
files?: StorageFile | StorageFile[]
|
|
9
|
-
deleteEndpoint?: string
|
|
10
9
|
bindkey?: StrKey
|
|
11
10
|
modelValue?: FSValue
|
|
12
11
|
width?: string
|
|
12
|
+
topic?: string
|
|
13
13
|
}>()
|
|
14
14
|
|
|
15
|
+
const emit = defineEmits(['update:modelValue'])
|
|
16
|
+
|
|
15
17
|
const bagel = useBagel()
|
|
16
18
|
|
|
17
19
|
interface QueueFile {
|
|
@@ -28,23 +30,24 @@ type FSValue = string[] | string | number
|
|
|
28
30
|
|
|
29
31
|
const bindKey: StrKey = props.bindkey || 'id'
|
|
30
32
|
|
|
31
|
-
const emit = defineEmits(['update:modelValue'])
|
|
32
|
-
|
|
33
33
|
let file_bindkeys = $ref<FSValue>(props.modelValue || [])
|
|
34
34
|
const storageFiles = $ref<StorageFile[]>([])
|
|
35
35
|
|
|
36
|
-
|
|
37
|
-
|
|
36
|
+
async function fetchFiles() {
|
|
37
|
+
const files = await bagel.get<StorageFile[]>(`/files?topic=${props.topic}`)
|
|
38
|
+
storageFiles.push(...files)
|
|
39
|
+
}
|
|
38
40
|
|
|
39
41
|
onMounted(() => {
|
|
42
|
+
if (props.topic) fetchFiles()
|
|
40
43
|
if (!props.files && [file_bindkeys].flat().length) {
|
|
41
44
|
const ids = [file_bindkeys].flat().filter(Boolean)
|
|
42
45
|
if (!ids.length) return
|
|
43
46
|
if (props.multiple) {
|
|
44
|
-
ids.forEach(id => {
|
|
47
|
+
ids.forEach((id) => {
|
|
45
48
|
void bagel
|
|
46
49
|
.get<StorageFile>(`/files/${id}`)
|
|
47
|
-
.then(file => {
|
|
50
|
+
.then((file) => {
|
|
48
51
|
storageFiles.push(file)
|
|
49
52
|
})
|
|
50
53
|
.catch(console.error)
|
|
@@ -52,7 +55,7 @@ onMounted(() => {
|
|
|
52
55
|
} else {
|
|
53
56
|
void bagel
|
|
54
57
|
.get<StorageFile>(`/files/${ids[0]}`)
|
|
55
|
-
.then(file => {
|
|
58
|
+
.then((file) => {
|
|
56
59
|
storageFiles.push(file)
|
|
57
60
|
})
|
|
58
61
|
.catch(console.error)
|
|
@@ -62,7 +65,7 @@ onMounted(() => {
|
|
|
62
65
|
|
|
63
66
|
watch(
|
|
64
67
|
() => props.files,
|
|
65
|
-
newFiles => {
|
|
68
|
+
(newFiles) => {
|
|
66
69
|
if (newFiles) {
|
|
67
70
|
const filesToAdd = [newFiles]
|
|
68
71
|
.flat()
|
|
@@ -103,10 +106,7 @@ const fileToUrl = (file: File) => URL.createObjectURL(file)
|
|
|
103
106
|
function removeFile(file: StorageFile) {
|
|
104
107
|
const index = storageFiles.indexOf(file)
|
|
105
108
|
storageFiles.splice(index, 1)
|
|
106
|
-
|
|
107
|
-
if (props.deleteEndpoint) {
|
|
108
|
-
void bagel.delete(`${props.deleteEndpoint}/${file.id}`)
|
|
109
|
-
}
|
|
109
|
+
void bagel.delete(`/static_files/${file.id}`)
|
|
110
110
|
updateModelValue()
|
|
111
111
|
}
|
|
112
112
|
|
|
@@ -116,6 +116,7 @@ async function flushQueue() {
|
|
|
116
116
|
if (!props.multiple) storageFiles.splice(0, 1)
|
|
117
117
|
const serverFile = await bagel.uploadFile<StorageFile>(file.file, {
|
|
118
118
|
onUploadProgress: (e: any) => (file.progress = e.progress * 100 - 1),
|
|
119
|
+
topic: props.topic,
|
|
119
120
|
})
|
|
120
121
|
storageFiles.push(serverFile)
|
|
121
122
|
const i = fileQueue.indexOf(file)
|
|
@@ -131,8 +132,7 @@ function browse() {
|
|
|
131
132
|
input.onchange = (e: Event) => {
|
|
132
133
|
const target = e.target as HTMLInputElement
|
|
133
134
|
if (target.files) {
|
|
134
|
-
Array.from(target.files).forEach((file: File) =>
|
|
135
|
-
fileQueue.push({ name: file.name, file, progress: 0 })
|
|
135
|
+
Array.from(target.files).forEach((file: File) => fileQueue.push({ name: file.name, file, progress: 0 })
|
|
136
136
|
)
|
|
137
137
|
}
|
|
138
138
|
flushQueue()
|
|
@@ -155,8 +155,7 @@ function dragover(e: DragEvent) {
|
|
|
155
155
|
function drop(e: DragEvent) {
|
|
156
156
|
preventDefault(e)
|
|
157
157
|
if (e.dataTransfer) {
|
|
158
|
-
Array.from(e.dataTransfer.files).forEach((file: File) =>
|
|
159
|
-
fileQueue.push({ name: file.name, file, progress: 0 })
|
|
158
|
+
Array.from(e.dataTransfer.files).forEach((file: File) => fileQueue.push({ name: file.name, file, progress: 0 })
|
|
160
159
|
)
|
|
161
160
|
}
|
|
162
161
|
isDragOver = false
|
|
@@ -183,13 +182,13 @@ function drop(e: DragEvent) {
|
|
|
183
182
|
<slot name="files" :files="storageFiles" :fileQueue>
|
|
184
183
|
<template v-for="file in storageFiles" :key="file.id">
|
|
185
184
|
<div v-if="!multiple" class="single-image">
|
|
186
|
-
<img class="single preview" :src="file.url" alt=""
|
|
185
|
+
<img class="single preview" :src="file.url" alt="">
|
|
187
186
|
<!-- <p class="no-margin">
|
|
188
187
|
{{ file.name }}
|
|
189
188
|
</p> -->
|
|
190
189
|
</div>
|
|
191
190
|
<div v-if="multiple" class="multi-image-item previewName">
|
|
192
|
-
<img class="preview" :src="file.url" alt=""
|
|
191
|
+
<img class="preview" :src="file.url" alt="">
|
|
193
192
|
<p class="no-margin">
|
|
194
193
|
{{ file.name }}
|
|
195
194
|
</p>
|
|
@@ -204,7 +203,7 @@ function drop(e: DragEvent) {
|
|
|
204
203
|
</template>
|
|
205
204
|
<template v-for="fileQ in fileQueue" :key="fileQ.file">
|
|
206
205
|
<div v-if="!multiple" class="imagePreviewWrap">
|
|
207
|
-
<img class="preview" :src="fileToUrl(fileQ.file)" alt=""
|
|
206
|
+
<img class="preview" :src="fileToUrl(fileQ.file)" alt="">
|
|
208
207
|
</div>
|
|
209
208
|
<div class="previewName">
|
|
210
209
|
<img
|
|
@@ -213,7 +212,7 @@ function drop(e: DragEvent) {
|
|
|
213
212
|
class="preview"
|
|
214
213
|
:src="fileToUrl(fileQ.file)"
|
|
215
214
|
alt=""
|
|
216
|
-
|
|
215
|
+
>
|
|
217
216
|
<p class="no-margin">
|
|
218
217
|
{{ fileQ.name }}
|
|
219
218
|
</p>
|
|
@@ -3,6 +3,7 @@ import { onMounted, watch } from 'vue'
|
|
|
3
3
|
import { Dropdown } from 'floating-vue'
|
|
4
4
|
import 'floating-vue/style.css'
|
|
5
5
|
import {
|
|
6
|
+
Btn,
|
|
6
7
|
Card,
|
|
7
8
|
Icon,
|
|
8
9
|
type MaterialIcons,
|
|
@@ -28,6 +29,7 @@ const props = defineProps<{
|
|
|
28
29
|
icon?: MaterialIcons
|
|
29
30
|
hideLabel?: boolean
|
|
30
31
|
defaultValue?: Option
|
|
32
|
+
clearable?: boolean
|
|
31
33
|
}>()
|
|
32
34
|
|
|
33
35
|
const emit = defineEmits(['update:modelValue'])
|
|
@@ -35,6 +37,8 @@ const emit = defineEmits(['update:modelValue'])
|
|
|
35
37
|
const searchInput = $ref<HTMLInputElement | null>(null)
|
|
36
38
|
|
|
37
39
|
let selectedItems = $ref<Option[]>([])
|
|
40
|
+
|
|
41
|
+
const selectedItemCount = $computed(() => selectedItems.length ?? 0)
|
|
38
42
|
let search = $ref('')
|
|
39
43
|
|
|
40
44
|
const dropdown = $ref<InstanceType<typeof Dropdown> | null>(null)
|
|
@@ -58,13 +62,13 @@ function updateOpen(visible: boolean) {
|
|
|
58
62
|
}
|
|
59
63
|
|
|
60
64
|
const selectedLabel = $computed(() => {
|
|
61
|
-
if (
|
|
62
|
-
if (
|
|
65
|
+
if (selectedItemCount === 0) return props.placeholder || 'Select'
|
|
66
|
+
if (selectedItemCount > 4) {
|
|
63
67
|
const str = selectedItems
|
|
64
68
|
.slice(0, 4)
|
|
65
69
|
.map(item => getLabel(item))
|
|
66
70
|
.join(', ')
|
|
67
|
-
return `${str}... +${
|
|
71
|
+
return `${str}... +${selectedItemCount - 4}`
|
|
68
72
|
}
|
|
69
73
|
return selectedItems.map(item => getLabel(item)).join(', ')
|
|
70
74
|
})
|
|
@@ -108,7 +112,7 @@ function select(option: Option) {
|
|
|
108
112
|
current.push(option)
|
|
109
113
|
|
|
110
114
|
selectedItems = current
|
|
111
|
-
} else { selectedItems.splice(0,
|
|
115
|
+
} else { selectedItems.splice(0, selectedItemCount, option)
|
|
112
116
|
}
|
|
113
117
|
|
|
114
118
|
if (!props.multiselect) dropdown?.hide()
|
|
@@ -119,7 +123,7 @@ function emitUpdate() {
|
|
|
119
123
|
if (props.multiselect) {
|
|
120
124
|
emit('update:modelValue', selectedItems.map(getValue).filter(Boolean))
|
|
121
125
|
} else {
|
|
122
|
-
// selectedItems.splice(1,
|
|
126
|
+
// selectedItems.splice(1, selectedItemCount - 1);
|
|
123
127
|
const [item] = selectedItems
|
|
124
128
|
emit('update:modelValue', getValue(item))
|
|
125
129
|
}
|
|
@@ -141,7 +145,7 @@ watch(
|
|
|
141
145
|
} else {
|
|
142
146
|
const isSame = compareArrays([newVal].flat(), selectedItems)
|
|
143
147
|
if (!isSame) {
|
|
144
|
-
selectedItems.splice(0,
|
|
148
|
+
selectedItems.splice(0, selectedItemCount, ...[newVal].flat())
|
|
145
149
|
}
|
|
146
150
|
}
|
|
147
151
|
},
|
|
@@ -170,6 +174,7 @@ onMounted(() => {
|
|
|
170
174
|
const defaultOption = props.options.find(
|
|
171
175
|
o => getValue(o) === getValue(props.defaultValue),
|
|
172
176
|
)
|
|
177
|
+
|
|
173
178
|
if (defaultOption === undefined) return
|
|
174
179
|
|
|
175
180
|
selectedItems = [defaultOption]
|
|
@@ -185,13 +190,13 @@ onMounted(() => {
|
|
|
185
190
|
@click.stop
|
|
186
191
|
@hide="updateOpen(false)"
|
|
187
192
|
>
|
|
188
|
-
<label>
|
|
193
|
+
<label class="flex gap-05">
|
|
189
194
|
{{ label }}
|
|
190
195
|
<button
|
|
191
196
|
:disabled="disabled"
|
|
192
197
|
type="button"
|
|
193
198
|
class="selectinput-btn"
|
|
194
|
-
:class="{ isEmpty:
|
|
199
|
+
:class="{ isEmpty: selectedItemCount === 0 }"
|
|
195
200
|
@keydown="openOptions"
|
|
196
201
|
@click="updateOpen(true)"
|
|
197
202
|
>
|
|
@@ -199,6 +204,15 @@ onMounted(() => {
|
|
|
199
204
|
<p v-if="!hideLabel">
|
|
200
205
|
{{ selectedLabel }}
|
|
201
206
|
</p>
|
|
207
|
+
|
|
208
|
+
<div v-if="clearable" class="ms-auto ps-05 me-05">
|
|
209
|
+
<Btn
|
|
210
|
+
thin
|
|
211
|
+
icon="clear"
|
|
212
|
+
class="color-black bg-gray-light"
|
|
213
|
+
@click="selectedItems = []"
|
|
214
|
+
/>
|
|
215
|
+
</div>
|
|
202
216
|
<Icon
|
|
203
217
|
v-if="!disabled"
|
|
204
218
|
thin
|
|
@@ -213,10 +227,11 @@ onMounted(() => {
|
|
|
213
227
|
required
|
|
214
228
|
@input="updateOpen(true)"
|
|
215
229
|
>
|
|
230
|
+
|
|
216
231
|
</label>
|
|
217
232
|
<template #popper>
|
|
218
233
|
<Card
|
|
219
|
-
class="
|
|
234
|
+
class="p-05"
|
|
220
235
|
:style="{ width: fullWidth ? '100%' : 'auto' }"
|
|
221
236
|
>
|
|
222
237
|
<TextInput
|
|
@@ -227,22 +242,24 @@ onMounted(() => {
|
|
|
227
242
|
placeholder="Search"
|
|
228
243
|
icon="search"
|
|
229
244
|
/>
|
|
230
|
-
<div
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
245
|
+
<div class="selectinput-options">
|
|
246
|
+
<div
|
|
247
|
+
v-for="(option, i) in filteredOptions"
|
|
248
|
+
:key="`${option}${i}`"
|
|
249
|
+
class="selectinput-option hover gap-1"
|
|
250
|
+
:class="{ selected: isSelected(option) }"
|
|
251
|
+
@click="select(option)"
|
|
252
|
+
>
|
|
253
|
+
<Icon v-if="isSelected(option)" icon="check" />
|
|
254
|
+
<Icon
|
|
255
|
+
v-if="!isSelected(option)"
|
|
256
|
+
class="opacity-3"
|
|
257
|
+
icon="fiber_manual_record"
|
|
258
|
+
/>
|
|
259
|
+
<span>
|
|
260
|
+
{{ getLabel(option) }}
|
|
261
|
+
</span>
|
|
262
|
+
</div>
|
|
246
263
|
</div>
|
|
247
264
|
<slot name="last" />
|
|
248
265
|
</Card>
|