@bagelink/vue 0.0.963 → 0.0.965

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@bagelink/vue",
3
3
  "type": "module",
4
- "version": "0.0.963",
4
+ "version": "0.0.965",
5
5
  "description": "Bagel core sdk packages",
6
6
  "author": {
7
7
  "name": "Neveh Allon",
@@ -196,7 +196,8 @@ async function registerLastItemObserver() {
196
196
 
197
197
  useIntersectionObserver(lastItem, ([entry]) => {
198
198
  if (entry.isIntersecting && computedData.value.length) {
199
- void onLastItemVisible?.()
199
+ // void onLastItemVisible?.()
200
+ emit('lastItemVisible')
200
201
  }
201
202
  }, { threshold: 0.5 }) }
202
203
 
@@ -1,12 +1,34 @@
1
1
  <script setup lang="ts">
2
- import { Btn, IMAGE_FORMATS_REGEXP, Icon, type StorageFile, useBagel, Card } from '@bagelink/vue'
2
+ import {
3
+ Btn,
4
+ IMAGE_FORMATS_REGEXP,
5
+ Icon,
6
+ type StorageFile,
7
+ useBagel,
8
+ Card,
9
+ } from '@bagelink/vue'
3
10
  import { onMounted, watch } from 'vue'
4
11
 
5
12
  type StrKey = keyof StorageFile
6
13
 
7
14
  type FSValue = string[] | string | number
8
15
 
9
- const props = defineProps<{
16
+ const {
17
+ label,
18
+ multiple,
19
+ files,
20
+ bindkey = 'id',
21
+ modelValue,
22
+ width,
23
+ height = '215px',
24
+ topic,
25
+ fill,
26
+ oval,
27
+ theme = 'dropzone',
28
+ accept = '*',
29
+ required,
30
+ disabled,
31
+ } = defineProps<{
10
32
  label?: string
11
33
  multiple?: boolean
12
34
  files?: StorageFile | StorageFile[]
@@ -20,11 +42,12 @@ const props = defineProps<{
20
42
  theme?: 'dropzone' | 'basic'
21
43
  accept?: string
22
44
  required?: boolean
45
+ disabled?: boolean
23
46
  }>()
24
47
 
25
48
  const emit = defineEmits(['update:modelValue', 'addFileStart'])
26
49
 
27
- const bindKey: StrKey = props.bindkey || 'id'
50
+ const bindKey: StrKey = bindkey
28
51
 
29
52
  const bagel = useBagel()
30
53
 
@@ -38,16 +61,21 @@ interface QueueFile {
38
61
 
39
62
  const isImage = (str: string) => IMAGE_FORMATS_REGEXP.test(str)
40
63
 
41
- const file_bindkeys = defineModel('modelValue', { default: () => [] as FSValue })
64
+ const file_bindkeys = defineModel('modelValue', {
65
+ default: () => [] as FSValue,
66
+ })
42
67
  const storageFiles = $ref<StorageFile[]>([])
43
68
 
44
69
  async function fetchTopicFiles() {
45
- const files = await bagel.get<StorageFile[]>(`/files?topic=${props.topic}`)
70
+ const files = await bagel.get<StorageFile[]>(`/files?topic=${topic}`)
46
71
  storageFiles.push(...files)
47
72
  }
48
73
 
49
74
  function loadFiles() {
50
- const ids = ([file_bindkeys.value].flat().filter(Boolean) as unknown) as (string | number)[]
75
+ const ids = [file_bindkeys.value].flat().filter(Boolean) as unknown as (
76
+ | string
77
+ | number
78
+ )[]
51
79
  if (!ids.length) {
52
80
  storageFiles.splice(0, storageFiles.length)
53
81
  return
@@ -55,7 +83,9 @@ function loadFiles() {
55
83
 
56
84
  const currentIds = storageFiles.map(file => file[bindKey])
57
85
  const idsToAdd = ids.filter(id => !currentIds.includes(id))
58
- const idsToRemove = currentIds.filter((id): id is string | number => (typeof id === 'string' || typeof id === 'number') && !ids.includes(id))
86
+ const idsToRemove = currentIds.filter(
87
+ (id): id is string | number => (typeof id === 'string' || typeof id === 'number') && !ids.includes(id)
88
+ )
59
89
 
60
90
  idsToRemove.forEach((id) => {
61
91
  const index = storageFiles.findIndex(file => file[bindKey] === id)
@@ -69,7 +99,7 @@ function loadFiles() {
69
99
  return
70
100
  }
71
101
 
72
- if (props.multiple) {
102
+ if (multiple) {
73
103
  idsToAdd.forEach((id) => {
74
104
  void bagel
75
105
  .get<StorageFile>(`/files/${id}`)
@@ -89,17 +119,17 @@ function loadFiles() {
89
119
  }
90
120
 
91
121
  onMounted(() => {
92
- if (props.topic) fetchTopicFiles()
93
- if (!props.files && [file_bindkeys.value].flat().length > 0) {
122
+ if (topic) fetchTopicFiles()
123
+ if (!files && [file_bindkeys.value].flat().length > 0) {
94
124
  loadFiles()
95
125
  }
96
126
  })
97
127
 
98
- watch(() => props.topic, fetchTopicFiles)
99
- watch(() => props.modelValue, loadFiles)
128
+ watch(() => topic, fetchTopicFiles)
129
+ watch(() => modelValue, loadFiles)
100
130
 
101
131
  watch(
102
- () => props.files,
132
+ () => files,
103
133
  (newFiles) => {
104
134
  if (newFiles) {
105
135
  const filesToAdd = [newFiles]
@@ -113,17 +143,16 @@ watch(
113
143
  { immediate: true }
114
144
  )
115
145
 
116
- const theme = props.theme || 'dropzone'
117
-
118
146
  function compareLists(a: any, b: any) {
119
- return [a]
120
- .flat()
121
- .every((id: any) => [b].flat().includes(id)) && [b].flat().every(id => [a].flat().includes(id))
147
+ return (
148
+ [a].flat().every((id: any) => [b].flat().includes(id))
149
+ && [b].flat().every(id => [a].flat().includes(id))
150
+ )
122
151
  }
123
152
 
124
153
  function updateModelValue() {
125
154
  let idValue: FSValue
126
- if (props.multiple) {
155
+ if (multiple) {
127
156
  idValue = storageFiles.map(f => f[bindKey]) as FSValue
128
157
  } else {
129
158
  idValue = (storageFiles[0][bindKey] as string) || ''
@@ -154,10 +183,10 @@ async function flushQueue() {
154
183
  emit('addFileStart')
155
184
  for (const file of fileQueue) {
156
185
  file.uploading = true
157
- if (!props.multiple) storageFiles.splice(0, 1)
186
+ if (!multiple) storageFiles.splice(0, 1)
158
187
  const serverFile = await bagel.uploadFile<StorageFile>(file.file, {
159
188
  onUploadProgress: (e: any) => (file.progress = e.progress * 100 - 1),
160
- topic: props.topic,
189
+ topic,
161
190
  })
162
191
  storageFiles.push(serverFile)
163
192
  }
@@ -166,10 +195,11 @@ async function flushQueue() {
166
195
  }
167
196
 
168
197
  function browse() {
198
+ if (disabled) return
169
199
  const input = document.createElement('input')
170
200
  input.type = 'file'
171
- input.multiple = props.multiple
172
- input.accept = props.accept || '*'
201
+ input.multiple = multiple
202
+ input.accept = accept
173
203
  input.onchange = (e: Event) => {
174
204
  const target = e.target as HTMLInputElement
175
205
  if (target.files) {
@@ -191,12 +221,14 @@ function dragleave(e: DragEvent) {
191
221
  }
192
222
 
193
223
  function dragover(e: DragEvent) {
224
+ if (disabled) return
194
225
  preventDefault(e)
195
226
  if (e.dataTransfer) isDragOver = true
196
227
  else isDragOver = false
197
228
  }
198
229
 
199
230
  function drop(e: DragEvent) {
231
+ if (disabled) return
200
232
  preventDefault(e)
201
233
  if (e.dataTransfer) {
202
234
  Array.from(e.dataTransfer.files).forEach((file: File) => fileQueue.push({ name: file.name, file, progress: 0 })
@@ -212,9 +244,18 @@ function drop(e: DragEvent) {
212
244
  <label>
213
245
  {{ label }}
214
246
  </label>
215
- <input v-if="required && !storageFiles.length" placeholder="required" type="text" required class="pixel">
247
+ <input
248
+ v-if="required && !storageFiles.length"
249
+ placeholder="required"
250
+ type="text"
251
+ required
252
+ class="pixel"
253
+ >
216
254
  <Card
217
- v-if="theme === 'basic'" outline class="flex p-05 gap-1" @dragover="dragover"
255
+ v-if="theme === 'basic'"
256
+ outline
257
+ class="flex p-05 gap-1"
258
+ @dragover="dragover"
218
259
  @drop="drop"
219
260
  >
220
261
  <Btn
@@ -227,21 +268,40 @@ function drop(e: DragEvent) {
227
268
  Upload
228
269
  </Btn>
229
270
 
230
- <div v-for="file in storageFiles" :key="file.id" class="txt-gray txt-12 flex">
271
+ <div
272
+ v-for="file in storageFiles"
273
+ :key="file.id"
274
+ class="txt-gray txt-12 flex"
275
+ >
231
276
  <div class="m-05 flex opacity-7 z-99">
232
- <Btn v-tooltip="'Delete'" color="gray" thin icon="delete" @click.stop="removeFile(file)" />
233
277
  <Btn
234
- v-tooltip="'Replace'" color="gray" thin icon="autorenew"
278
+ v-tooltip="'Delete'"
279
+ color="gray"
280
+ thin
281
+ icon="delete"
282
+ @click.stop="removeFile(file)"
283
+ />
284
+ <Btn
285
+ v-tooltip="'Replace'"
286
+ color="gray"
287
+ thin
288
+ icon="autorenew"
235
289
  @click="browse"
236
290
  />
237
291
  <Btn
238
292
  v-tooltip="'Download'"
239
- :href="file.url" :download="file.name"
240
- color="gray" thin icon="download"
293
+ :href="file.url"
294
+ :download="file.name"
295
+ color="gray"
296
+ thin
297
+ icon="download"
241
298
  target="_blank"
242
299
  @click.stop
243
300
  />
244
- <p v-lightbox="{ src: file.url, download: true }" class="ellipsis-1 word-break-all h-20 m-0">
301
+ <p
302
+ v-lightbox="{ src: file.url, download: true }"
303
+ class="ellipsis-1 word-break-all h-20 m-0"
304
+ >
245
305
  {{ file.name }}
246
306
  </p>
247
307
  <Btn
@@ -253,7 +313,10 @@ function drop(e: DragEvent) {
253
313
  />
254
314
  </div>
255
315
  </div>
256
- <span v-if="!storageFiles.length && !fileQueue.length" class="txt-gray txt-12">
316
+ <span
317
+ v-if="!storageFiles.length && !fileQueue.length"
318
+ class="txt-gray txt-12"
319
+ >
257
320
  No file selected
258
321
  </span>
259
322
  </Card>
@@ -265,7 +328,7 @@ function drop(e: DragEvent) {
265
328
  'dragover': isDragOver,
266
329
  'bgl_oval-upload': oval,
267
330
  }"
268
- :style="{ width: props.width, height: props.height || '215px' }"
331
+ :style="{ width, height }"
269
332
  @click="browse"
270
333
  @dragover="dragover"
271
334
  @drop="drop"
@@ -279,7 +342,12 @@ function drop(e: DragEvent) {
279
342
  v-lightbox="{ src: file.url, download: true }"
280
343
  class="multi-image-item-preview"
281
344
  >
282
- <img v-if="isImage(file.extension || file.url)" class="multi-preview" :src="file.url" alt="">
345
+ <img
346
+ v-if="isImage(file.extension || file.url)"
347
+ class="multi-preview"
348
+ :src="file.url"
349
+ alt=""
350
+ >
283
351
  <Icon v-else icon="draft" class="multi-preview" />
284
352
  <p class="m-0">
285
353
  {{ file.name }}
@@ -326,7 +394,10 @@ function drop(e: DragEvent) {
326
394
  </div>
327
395
  </div>
328
396
 
329
- <div v-if="!multiple && (storageFiles.length > 0 || fileQueue.length > 0)" class="bgl-single-preview">
397
+ <div
398
+ v-if="!multiple && (storageFiles.length > 0 || fileQueue.length > 0)"
399
+ class="bgl-single-preview"
400
+ >
330
401
  <div
331
402
  v-for="file in storageFiles"
332
403
  :key="file.id"
@@ -334,23 +405,47 @@ function drop(e: DragEvent) {
334
405
  :class="{ 'bgl_fill-image': fill }"
335
406
  >
336
407
  <div class="position-start m-05 flex opacity-7 z-99">
337
- <Btn v-tooltip="'Delete'" color="gray" thin icon="delete" @click.stop="removeFile(file)" />
338
408
  <Btn
339
- v-tooltip="'Replace'" color="gray" thin icon="autorenew"
409
+ v-tooltip="'Delete'"
410
+ color="gray"
411
+ thin
412
+ icon="delete"
413
+ @click.stop="removeFile(file)"
414
+ />
415
+ <Btn
416
+ v-tooltip="'Replace'"
417
+ color="gray"
418
+ thin
419
+ icon="autorenew"
340
420
  @click="browse"
341
421
  />
342
422
  <Btn
343
423
  v-tooltip="'Download'"
344
- :href="file.url" :download="file.name"
345
- color="gray" thin icon="download"
424
+ :href="file.url"
425
+ :download="file.name"
426
+ color="gray"
427
+ thin
428
+ icon="download"
346
429
  target="_blank"
347
430
  @click.stop
348
431
  />
349
432
  </div>
350
433
  <div v-if="isImage(file.extension || file.url)" class="h-100">
351
- <img v-lightbox="{ src: file.url, download: true }" class="single-preview" :src="file.url" alt="">
434
+ <img
435
+ v-lightbox="{ src: file.url, download: true }"
436
+ class="single-preview"
437
+ :src="file.url"
438
+ alt=""
439
+ >
352
440
  </div>
353
- <Icon v-else v-lightbox="{ src: file.url, download: true }" :size="4" weight="2" icon="draft" class="color-primary w-100" />
441
+ <Icon
442
+ v-else
443
+ v-lightbox="{ src: file.url, download: true }"
444
+ :size="4"
445
+ weight="2"
446
+ icon="draft"
447
+ class="color-primary w-100"
448
+ />
354
449
  </div>
355
450
 
356
451
  <div
@@ -370,7 +465,12 @@ function drop(e: DragEvent) {
370
465
  </span>
371
466
  <Icon class="success" icon="check" />
372
467
  </div>
373
- <img v-if="isImage(fileQ.file.type)" class="single-preview" :src="fileToUrl(fileQ.file)" alt="">
468
+ <img
469
+ v-if="isImage(fileQ.file.type)"
470
+ class="single-preview"
471
+ :src="fileToUrl(fileQ.file)"
472
+ alt=""
473
+ >
374
474
  <!-- <Icon v-else :size="8" weight="2" icon="draft" class="color-primary" /> -->
375
475
  </div>
376
476
  </div>
@@ -382,7 +482,9 @@ function drop(e: DragEvent) {
382
482
  :fileQueue
383
483
  :browse
384
484
  >
385
- <p class="p-1 flex column hover fileUploadPlaceHolder justify-content-center mb-05">
485
+ <p
486
+ class="p-1 flex column hover fileUploadPlaceHolder justify-content-center mb-05"
487
+ >
386
488
  <Icon icon="upload_2" />
387
489
  Drop files here or click to upload
388
490
  </p>
@@ -418,7 +520,7 @@ function drop(e: DragEvent) {
418
520
  box-shadow: inset 0 0 10px #00000012;
419
521
  }
420
522
 
421
- .fileUploadWrap[style*="height: auto;"] {
523
+ .fileUploadWrap[style*='height: auto;'] {
422
524
  min-height: 215px;
423
525
  }
424
526
 
@@ -441,7 +543,7 @@ function drop(e: DragEvent) {
441
543
  text-overflow: ellipsis;
442
544
  white-space: nowrap;
443
545
  }
444
- .multi-preview{
546
+ .multi-preview {
445
547
  width: 40px;
446
548
  height: 40px;
447
549
  border-radius: var(--input-border-radius);
@@ -452,11 +554,11 @@ function drop(e: DragEvent) {
452
554
  align-items: center;
453
555
  display: flex;
454
556
  }
455
- .bgl-single-preview{
557
+ .bgl-single-preview {
456
558
  height: 100%;
457
559
  position: relative;
458
560
  }
459
- .bgl-single-preview + .fileUploadPlaceHolder{
561
+ .bgl-single-preview + .fileUploadPlaceHolder {
460
562
  position: absolute;
461
563
  inset: 0;
462
564
  margin: auto;
@@ -470,15 +572,14 @@ function drop(e: DragEvent) {
470
572
  align-items: center;
471
573
  justify-content: center;
472
574
  }
473
- .fileUploadWrap[style*="height: auto"] .single-image-item-preview {
575
+ .fileUploadWrap[style*='height: auto'] .single-image-item-preview {
474
576
  min-height: 215px;
475
577
  }
476
578
 
477
- .fileUploadWrap[style*="height: auto"] .single-preview {
579
+ .fileUploadWrap[style*='height: auto'] .single-preview {
478
580
  margin: 0rem !important;
479
-
480
581
  }
481
- .single-preview{
582
+ .single-preview {
482
583
  border-radius: var(--input-border-radius);
483
584
  margin: 1rem;
484
585
  padding: 0px;
@@ -487,24 +588,24 @@ function drop(e: DragEvent) {
487
588
  object-fit: cover;
488
589
  background: var(--bgl-gray-light);
489
590
  }
490
- .single-image-item-preview:hover::after{
491
- content: "zoom_in";
591
+ .single-image-item-preview:hover::after {
592
+ content: 'zoom_in';
492
593
  font-size: 32px;
493
- font-family: "Material Symbols Outlined", serif;
594
+ font-family: 'Material Symbols Outlined', serif;
494
595
  position: absolute;
495
596
  border-radius: 100%;
496
597
  color: var(--bgl-white);
497
598
  z-index: 9;
498
599
  pointer-events: none;
499
600
  }
500
- .single-image-item-preview:hover img{
601
+ .single-image-item-preview:hover img {
501
602
  filter: brightness(70%);
502
603
  }
503
604
 
504
605
  .bgl_fill-image.single-image-item-preview {
505
606
  height: 100%;
506
607
  }
507
- .bgl_fill-image.single-image-item-preview .single-preview{
608
+ .bgl_fill-image.single-image-item-preview .single-preview {
508
609
  border-radius: unset;
509
610
  object-fit: cover;
510
611
  box-shadow: unset;
@@ -530,27 +631,27 @@ function drop(e: DragEvent) {
530
631
  .bgl_oval-upload {
531
632
  border-radius: 100% !important;
532
633
  overflow: hidden;
533
- }
634
+ }
534
635
  .bgl_oval-upload p {
535
- padding: 0.75rem !important;
536
- font-size: 12px
537
- }
538
- .bgl_oval-upload .fileUploadPlaceHolder{
539
- top: 0;
540
- }
541
- .bgl_oval-upload .pie {
542
- transform: scale(1);
543
- }
544
- .bgl_oval-upload span.bgl_icon-font.color-primary {
545
- transform: scale(0.4) !important;
546
- }
547
- .bgl_oval-upload .single-image-item-preview{
548
- height: 100%;
549
- }
550
- .bgl_oval-upload .single-preview {
551
- margin: 0;
552
- height: 100% !important;
553
- }
636
+ padding: 0.75rem !important;
637
+ font-size: 12px;
638
+ }
639
+ .bgl_oval-upload .fileUploadPlaceHolder {
640
+ top: 0;
641
+ }
642
+ .bgl_oval-upload .pie {
643
+ transform: scale(1);
644
+ }
645
+ .bgl_oval-upload span.bgl_icon-font.color-primary {
646
+ transform: scale(0.4) !important;
647
+ }
648
+ .bgl_oval-upload .single-image-item-preview {
649
+ height: 100%;
650
+ }
651
+ .bgl_oval-upload .single-preview {
652
+ margin: 0;
653
+ height: 100% !important;
654
+ }
554
655
 
555
656
  .pie {
556
657
  width: 30px;