@bagelink/vue 0.0.1141 → 0.0.1145

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.
Files changed (37) hide show
  1. package/dist/components/Carousel.vue.d.ts.map +1 -1
  2. package/dist/components/Modal.vue.d.ts.map +1 -1
  3. package/dist/components/Zoomer.vue.d.ts.map +1 -1
  4. package/dist/components/form/BagelForm.vue.d.ts.map +1 -1
  5. package/dist/components/form/index.d.ts +2 -3
  6. package/dist/components/form/index.d.ts.map +1 -1
  7. package/dist/components/form/inputs/FileUpload.vue.d.ts.map +1 -1
  8. package/dist/components/form/inputs/RichText/composables/useEditor.d.ts.map +1 -1
  9. package/dist/components/form/inputs/RichText/index.vue.d.ts +1 -0
  10. package/dist/components/form/inputs/RichText/index.vue.d.ts.map +1 -1
  11. package/dist/components/form/inputs/SelectInput.vue.d.ts +0 -1
  12. package/dist/components/form/inputs/SelectInput.vue.d.ts.map +1 -1
  13. package/dist/components/form/inputs/Upload/UploadInput.vue.d.ts.map +1 -1
  14. package/dist/components/lightbox/Lightbox.vue.d.ts.map +1 -1
  15. package/dist/index.cjs +594 -663
  16. package/dist/index.mjs +594 -663
  17. package/dist/plugins/modal.d.ts +5 -0
  18. package/dist/plugins/modal.d.ts.map +1 -1
  19. package/dist/style.css +143 -137
  20. package/dist/types/BagelForm.d.ts +3 -0
  21. package/dist/types/BagelForm.d.ts.map +1 -1
  22. package/package.json +1 -1
  23. package/src/components/Carousel.vue +1 -0
  24. package/src/components/Icon/Icon.vue +1 -1
  25. package/src/components/Modal.vue +0 -1
  26. package/src/components/ModalForm.vue +24 -19
  27. package/src/components/Zoomer.vue +24 -4
  28. package/src/components/form/BagelForm.vue +4 -3
  29. package/src/components/form/index.ts +2 -3
  30. package/src/components/form/inputs/FileUpload.vue +13 -1
  31. package/src/components/form/inputs/NumberInput.vue +6 -6
  32. package/src/components/form/inputs/RichText/index.vue +30 -27
  33. package/src/components/form/inputs/SelectInput.vue +1 -3
  34. package/src/components/form/inputs/Upload/UploadInput.vue +13 -6
  35. package/src/components/lightbox/Lightbox.vue +32 -33
  36. package/src/plugins/modal.ts +5 -0
  37. package/src/types/BagelForm.ts +1 -0
@@ -31,6 +31,9 @@ export interface BaseBagelField<T = {
31
31
  'disabled'?: boolean;
32
32
  'helptext'?: string;
33
33
  'options'?: BagelFieldOptions<T>;
34
+ 'slots'?: {
35
+ [key: string]: any;
36
+ };
34
37
  'defaultValue'?: any;
35
38
  'transform'?: (val?: any, rowData?: T) => any;
36
39
  'onUpdate'?: (val: any, rowData?: T) => void;
@@ -1 +1 @@
1
- {"version":3,"file":"BagelForm.d.ts","sourceRoot":"","sources":["../../src/types/BagelForm.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"BagelForm.d.ts","sourceRoot":"","sources":["../../src/types/BagelForm.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@bagelink/vue",
3
3
  "type": "module",
4
- "version": "0.0.1141",
4
+ "version": "0.0.1145",
5
5
  "description": "Bagel core sdk packages",
6
6
  "author": {
7
7
  "name": "Neveh Allon",
@@ -238,6 +238,7 @@ async function disableDrag() {
238
238
  }
239
239
 
240
240
  function startDrag(e: MouseEvent) {
241
+ e.stopPropagation()
241
242
  if (e.button !== 0 || !props.freeDrag || !isSliderAvailable) return
242
243
 
243
244
  clearAutoplay()
@@ -31,7 +31,7 @@ const isFaBrand = $computed(() => FONT_AWESOME_BRANDS_ICONS.includes(iconRender)
31
31
  </span>
32
32
  <i
33
33
  v-else-if="iconRenderType === 'font-awesome'"
34
- class="fa" :class="[`fa-${iconRender}`, { 'fa-brands': isFaBrand }]"
34
+ class="fa far" :class="[`fa-${iconRender}`, { 'fa-brands': isFaBrand }]"
35
35
  :style="{ 'fontSize': `${size}rem`, color, 'font-variation-settings': `'wght' ${weight || 400}` }"
36
36
  />
37
37
  </template>
@@ -147,7 +147,6 @@ onUnmounted(() => {
147
147
  display: flex;
148
148
  justify-content: space-between;
149
149
  align-items: center;
150
- gap: 0;
151
150
  }
152
151
  .modal-no-title{
153
152
  width: calc(100% + 2rem);
@@ -1,6 +1,6 @@
1
1
  <script lang="ts" setup>
2
- import type { BglFormSchemaFnT, BtnOptions, BagelForm } from '@bagelink/vue'
3
- import { Btn, Modal, useBagel, BagelForm2 } from '@bagelink/vue'
2
+ import type { BglFormSchemaFnT, BtnOptions } from '@bagelink/vue'
3
+ import { Btn, Modal, useBagel, BagelForm } from '@bagelink/vue'
4
4
 
5
5
  const props = defineProps<{
6
6
  side?: boolean
@@ -11,13 +11,14 @@ const props = defineProps<{
11
11
  schema: BglFormSchemaFnT<any>
12
12
 
13
13
  onSubmit?: (formData: any) => Promise<void>
14
-
14
+ onDuplicate?: (formData: any) => Promise<void>
15
+ submitText?: string
16
+ cancelText?: string
17
+ deleteText?: string
18
+ duplicateText?: string
15
19
  onDelete?: (id: string) => void
16
-
17
20
  visible?: boolean
18
-
19
21
  onError?: (err: any) => void
20
-
21
22
  modelValue?: { [key: string]: any }
22
23
  }>()
23
24
 
@@ -76,34 +77,38 @@ defineExpose({ setFormValues })
76
77
  :title
77
78
  @update:visible="($event: boolean) => emit('update:visible', $event)"
78
79
  >
79
- <BagelForm2
80
+ <BagelForm
80
81
  v-if="visible"
81
82
  ref="form"
82
83
  v-model="formData"
83
84
  :schema="computedFormSchema"
84
85
  @submit="runSubmit"
85
86
  />
86
- <!-- <BagelForm
87
- v-if="visible"
88
- ref="form"
89
- v-model="formData"
90
- :schema="computedFormSchema"
91
- @submit="runSubmit"
92
- /> -->
93
87
  <template v-if="onDelete || onSubmit" #footer>
94
- <div>
95
- <Btn thin flat value="Cancel" @click="closeModal" />
88
+ <div class="flex gap-0">
89
+ <Btn thin flat :value="cancelText || 'Cancel'" @click="closeModal" />
96
90
  <Btn
97
- v-if="onDelete"
91
+ v-if="onDelete && formData.id"
98
92
  thin
99
93
  icon="delete"
100
94
  flat
101
- value="Delete"
95
+ :value="deleteText || 'Delete'"
102
96
  color="red"
103
97
  @click="runDelete"
104
98
  />
105
99
  </div>
106
- <Btn value="Submit" @click="runSubmit" />
100
+ <div class="flex gap-05">
101
+ <Btn
102
+ v-if="onDuplicate"
103
+ outline
104
+ class="px-1"
105
+ icon="copy_all"
106
+ flat
107
+ :value="duplicateText || 'Duplicate'"
108
+ @click="onDuplicate"
109
+ />
110
+ <Btn v-if="onSubmit" :value="submitText || 'Submit'" @click="runSubmit" />
111
+ </div>
107
112
  </template>
108
113
  </Modal>
109
114
  </template>
@@ -65,9 +65,12 @@ let panLocked = $ref(true)
65
65
  let raf = $ref<number | undefined>()
66
66
  let tapDetector = $ref<TapDetector | undefined>()
67
67
 
68
+ let translateXValue = $ref(0)
69
+ let translateYValue = $ref(0)
70
+
68
71
  const wrapperStyle = $computed(() => {
69
- const translateXValue = containerWidth * animTranslateX
70
- const translateYValue = containerHeight * animTranslateY
72
+ translateXValue = containerWidth * animTranslateX
73
+ translateYValue = containerHeight * animTranslateY
71
74
  return {
72
75
  transform: [
73
76
  `translate(${translateXValue}px, ${translateYValue}px)`,
@@ -169,12 +172,18 @@ function calcTranslateLimit() {
169
172
  const imageToContainerRatio = containerWidth / aspectRatio / containerHeight
170
173
  let translateLimitY = (scale * imageToContainerRatio - 1) / 2
171
174
  if (translateLimitY < 0) translateLimitY = 0
172
- return { x: (scale - 1) / 2, y: translateLimitY }
175
+ return {
176
+ x: scale - 1, // Allow full movement to edges horizontally
177
+ y: translateLimitY * 2 // Allow full movement to edges vertically
178
+ }
173
179
  }
174
180
  const imageToContainerRatio = containerHeight * aspectRatio / containerWidth
175
181
  let translateLimitX = (scale * imageToContainerRatio - 1) / 2
176
182
  if (translateLimitX < 0) translateLimitX = 0
177
- return { x: translateLimitX, y: (scale - 1) / 2 }
183
+ return {
184
+ x: translateLimitX * 2, // Allow full movement to edges horizontally
185
+ y: scale - 1 // Allow full movement to edges vertically
186
+ }
178
187
  }
179
188
 
180
189
  function getMarginDirection() {
@@ -353,6 +362,15 @@ function onWindowResize() {
353
362
  </template>
354
363
 
355
364
  <style scoped>
365
+ .zoomer-debug {
366
+ position: fixed;
367
+ top: 0;
368
+ right: 0;
369
+ background-color: rgba(0, 0, 0, 0.5);
370
+ color: white;
371
+ z-index: 1000;
372
+ height: 100px
373
+ }
356
374
  .vue-zoomer {
357
375
  overflow: hidden;
358
376
  }
@@ -360,6 +378,8 @@ function onWindowResize() {
360
378
  transform-origin: 50% 50%;
361
379
  width: 100%;
362
380
  height: 100%;
381
+ max-width: 100vw;
382
+ max-height: 100vh;
363
383
  }
364
384
  .zoomer > img {
365
385
  vertical-align: top;
@@ -144,9 +144,10 @@ function renderSchemaField(field: Field): VNode | null {
144
144
  ? {
145
145
  default: () => field.children!
146
146
  .map(child => typeof child === 'string' ? child : renderSchemaField(child))
147
- .filter(Boolean)
147
+ .filter(Boolean),
148
+ ...field.slots
148
149
  }
149
- : undefined
150
+ : field.slots
150
151
 
151
152
  return h(Component as any, props, slots)
152
153
  }
@@ -170,7 +171,7 @@ defineExpose({ form, isDirty, validateForm })
170
171
  <template>
171
172
  <form ref="form" @submit.prevent="handleSubmit">
172
173
  <template v-if="resolvedSchema">
173
- <template v-for="(field, index) in resolvedSchema" :key="field.id || index">
174
+ <template v-for="(field) in resolvedSchema" :key="field.id">
174
175
  <component :is="renderSchemaField(field)" />
175
176
  </template>
176
177
  </template>
@@ -1,6 +1,5 @@
1
- export { default as BagelForm2 } from './BagelForm.vue'
1
+ export { default as BglForm } from './BagelForm.vue'
2
+ export { default as BagelForm } from './BagelForm.vue'
2
3
  export { default as BglField } from './BglField.vue'
3
- export { default as BglForm } from './BglForm.vue'
4
- export { default as BagelForm } from './BglForm.vue'
5
4
  export { default as FieldArray } from './FieldArray.vue'
6
5
  export * from './inputs'
@@ -295,10 +295,21 @@ function drop(e: DragEvent) {
295
295
  />
296
296
  <p
297
297
  v-lightbox="{ src: file.url, download: true }"
298
- class="ellipsis-1 word-break-all h-20 m-0"
298
+ class="ellipsis-1 word-break-all h-20 m-0 color-black"
299
299
  >
300
300
  {{ file.name }}
301
301
  </p>
302
+
303
+ <div class="flex gap-025 rounded pe-1 ps-05 py-025 bg-gray-80 -my-1 ">
304
+ <Icon icon="draft" :size="1.5" />
305
+ <p
306
+ v-lightbox="{ src: file.url, download: true }"
307
+ class="ellipsis-1 word-break-all h-20 m-0 color-black txt18"
308
+ >
309
+ {{ file.name }}
310
+ </p>
311
+ </div>
312
+
302
313
  <Btn
303
314
  thin
304
315
  flat
@@ -462,6 +473,7 @@ function drop(e: DragEvent) {
462
473
  </div>
463
474
  <Image
464
475
  v-if="isImage(fileQ.file.type)"
476
+ v-lightbox="{ src: fileToUrl(fileQ.file), download: true }"
465
477
  class="single-preview"
466
478
  :src="fileToUrl(fileQ.file)"
467
479
  alt=""
@@ -44,23 +44,23 @@ const {
44
44
 
45
45
  const emit = defineEmits(['update:modelValue'])
46
46
 
47
- let numberValue = $ref(Number.parseFloat(`${modelValue}`) || 0)
47
+ let numberValue = $ref(Number.parseFloat(`${modelValue}`) || undefined)
48
48
 
49
49
  const btnLayouts: NumberLayout[] = ['horizontal', 'vertical']
50
50
 
51
- const canAdd = $computed(() => !(max !== undefined && (numberValue + step) > max))
52
- const canDecrement = $computed(() => !(min !== undefined && (numberValue - step) < min))
51
+ const canAdd = $computed(() => !(max !== undefined && (numberValue || 0 + step) > max))
52
+ const canDecrement = $computed(() => !(min !== undefined && (numberValue || 0 - step) < min))
53
53
 
54
54
  // Methods
55
55
  function increment() {
56
56
  if (!canAdd) return
57
- numberValue += step
57
+ numberValue = (numberValue || 0) + step
58
58
  emit('update:modelValue', numberValue)
59
59
  }
60
60
 
61
61
  function decrement() {
62
62
  if (!canDecrement) return
63
- numberValue -= step
63
+ numberValue = (numberValue || 0) - step
64
64
  emit('update:modelValue', numberValue)
65
65
  }
66
66
 
@@ -84,7 +84,7 @@ function inputHandler() {
84
84
  }
85
85
 
86
86
  watch(() => numberValue, () => {
87
- formattedValue = formatNumber(numberValue)
87
+ formattedValue = numberValue !== undefined ? formatNumber(numberValue) : ''
88
88
  }, { immediate: true })
89
89
 
90
90
  watch(() => modelValue, (newVal) => {
@@ -7,7 +7,7 @@ import { useCommands } from './composables/useCommands'
7
7
  import { useEditor } from './composables/useEditor'
8
8
  import { useEditorKeyboard } from './composables/useEditorKeyboard'
9
9
 
10
- const props = defineProps<{ modelValue: string, toolbarConfig?: ToolbarConfig, debug?: boolean }>()
10
+ const props = defineProps<{ modelValue: string, toolbarConfig?: ToolbarConfig, debug?: boolean, label?: string }>()
11
11
  const emit = defineEmits(['update:modelValue'])
12
12
 
13
13
  const iframe = $ref<HTMLIFrameElement>()
@@ -86,33 +86,36 @@ watch(() => editor.state.content, (newValue) => {
86
86
  </script>
87
87
 
88
88
  <template>
89
- <div class="rich-text-editor rounded pt-05 px-05 pb-075 mb-05" :class="{ 'fullscreen-mode': editor.state.isFullscreen }">
90
- <EditorToolbar
91
- v-if="editor.state.hasInit" :config="toolbarConfig" :selectedStyles="editor.state.selectedStyles"
92
- @action="commands.execute"
93
- />
94
- <div class="editor-container" :class="{ 'split-view': editor.state.isSplitView }">
95
- <div class="content-area radius-05">
96
- <iframe id="rich-text-iframe" ref="iframe" class="editableContent" title="Editor" @load="initEditor" />
97
- </div>
98
- <CodeEditor
99
- v-if="editor.state.isSplitView" v-model="editor.state.content" language="html"
100
- @update:modelValue="editor.updateContent('html')"
89
+ <div class="bagel-input">
90
+ <label>{{ label }}</label>
91
+ <div class="rich-text-editor rounded pt-05 px-05 pb-075 mb-05" :class="{ 'fullscreen-mode': editor.state.isFullscreen }">
92
+ <EditorToolbar
93
+ v-if="editor.state.hasInit" :config="toolbarConfig" :selectedStyles="editor.state.selectedStyles"
94
+ @action="commands.execute"
101
95
  />
102
- </div>
103
- <div v-if="debug" class="flex">
104
- <p class="text12 txt-gray mb-0 p-0">
105
- Debug
106
- </p>
107
- <Btn thin color="gray" icon="delete" @click="debugMethods?.clearSession">
108
- Clear Session
109
- </Btn>
110
- <Btn thin color="gray" icon="download" @click="debugMethods?.downloadSession">
111
- Download Log
112
- </Btn>
113
- <Btn thin color="gray" icon="content_copy" @click="copyText(debugMethods?.exportDebugWithPrompt() || '')">
114
- Copy Log
115
- </Btn>
96
+ <div class="editor-container" :class="{ 'split-view': editor.state.isSplitView }">
97
+ <div class="content-area radius-05">
98
+ <iframe id="rich-text-iframe" ref="iframe" class="editableContent" title="Editor" @load="initEditor" />
99
+ </div>
100
+ <CodeEditor
101
+ v-if="editor.state.isSplitView" v-model="editor.state.content" language="html"
102
+ @update:modelValue="editor.updateContent('html')"
103
+ />
104
+ </div>
105
+ <div v-if="debug" class="flex">
106
+ <p class="text12 txt-gray mb-0 p-0">
107
+ Debug
108
+ </p>
109
+ <Btn thin color="gray" icon="delete" @click="debugMethods?.clearSession">
110
+ Clear Session
111
+ </Btn>
112
+ <Btn thin color="gray" icon="download" @click="debugMethods?.downloadSession">
113
+ Download Log
114
+ </Btn>
115
+ <Btn thin color="gray" icon="content_copy" @click="copyText(debugMethods?.exportDebugWithPrompt() || '')">
116
+ Copy Log
117
+ </Btn>
118
+ </div>
116
119
  </div>
117
120
  </div>
118
121
  </template>
@@ -31,14 +31,11 @@ interface PropTypes {
31
31
  }
32
32
 
33
33
  const props = withDefaults(defineProps<PropTypes>(), {
34
- searchPlaceholder: 'Search',
35
34
  placeholder: 'Select',
36
35
  })
37
36
 
38
37
  const emit = defineEmits(['update:modelValue']) // Add 'search' event
39
38
 
40
- const searchPlaceholder = $computed(() => props.searchPlaceholder)
41
-
42
39
  const searchInput = $ref<HTMLElement | undefined>()
43
40
 
44
41
  let selectedItems = $ref<Option[]>([])
@@ -61,6 +58,7 @@ const selectedLabel = $computed((): string => {
61
58
  }
62
59
  return selectedItems.map(item => getLabel(item)).join(', ')
63
60
  })
61
+ const searchPlaceholder = $computed(() => props.searchPlaceholder ?? selectedLabel ?? 'Search')
64
62
 
65
63
  let serverOptions: Option[] = $ref([])
66
64
  let isSearching = $ref(false)
@@ -184,12 +184,15 @@ watch(() => props.dirPath, () => {
184
184
  :href="pathToUrl(path_key)"
185
185
  :download="path_key.split('/').pop()"
186
186
  />
187
- <p
188
- v-lightbox="{ src: pathToUrl(path_key), download: true }"
189
- class="ellipsis-1 word-break-all h-20 m-0"
190
- >
191
- {{ path_key.split('/').pop() }}
192
- </p>
187
+ <div class="flex gap-025 rounded pe-1 ps-05 py-025 bg-gray-80 -my-1 ">
188
+ <Icon icon="draft" :size="1.5" />
189
+ <p
190
+ v-lightbox="{ src: pathToUrl(path_key), download: true }"
191
+ class="ellipsis-1 word-break-all h-20 m-0 color-black txt18"
192
+ >
193
+ {{ path_key.split('/').pop() }}
194
+ </p>
195
+ </div>
193
196
  </div>
194
197
  </div>
195
198
  </template>
@@ -308,6 +311,8 @@ watch(() => props.dirPath, () => {
308
311
  </div>
309
312
  <div v-if="isImage(path_key)" class="h-100">
310
313
  <Image
314
+ v-lightbox="{ src: pathToUrl(path_key), download: true }"
315
+
311
316
  class="single-preview"
312
317
  :pathKey="path_key"
313
318
  alt=""
@@ -341,7 +346,9 @@ watch(() => props.dirPath, () => {
341
346
  </div>
342
347
  <Image
343
348
  v-if="isImage(file.file.type)"
349
+ v-lightbox="{ src: fileToUrl(file.file), download: true }"
344
350
  class="single-preview"
351
+
345
352
  :src="fileToUrl(file.file)"
346
353
  alt=""
347
354
  />
@@ -1,20 +1,18 @@
1
1
  <script setup lang="ts">
2
2
  import type { LightboxItem } from './lightbox.types'
3
3
 
4
- import { BglVideo, Btn, Icon, Zoomer, Image, normalizeURL } from '@bagelink/vue'
4
+ import { BglVideo, Btn, Icon, Zoomer, Image, normalizeURL, Carousel } from '@bagelink/vue'
5
5
  import { watch } from 'vue'
6
6
 
7
7
  let isOpen = $ref(false)
8
- let currentItem = $ref<LightboxItem>()
9
8
  let group = $ref<LightboxItem[]>([])
10
9
  let currentIndex = $ref(0)
10
+ let currentItem = $computed<LightboxItem>(() => group[currentIndex])
11
11
 
12
12
  function open(item: LightboxItem, groupItems?: LightboxItem[]) {
13
13
  isOpen = true
14
- currentItem = item
15
- if (groupItems === undefined) return
16
- group = groupItems
17
- currentIndex = groupItems.findIndex(({ src }) => item.src === src)
14
+ group = groupItems || [item]
15
+ currentIndex = group.findIndex(({ src }) => item.src === src)
18
16
  document.addEventListener('keydown', handleKeydown)
19
17
  }
20
18
 
@@ -78,16 +76,18 @@ defineExpose({ open, close })
78
76
  @keydown.right="next"
79
77
  @click="clickOutside"
80
78
  >
81
- <div v-if="group && group.length > 1" class="navigation flex space-between px-3 w-100 absolute m_px-1">
79
+ <div v-if="group && group.length > 1" class="navigation flex space-between px-3 w-100 absolute m_px-1 m_none z-9">
82
80
  <Btn
83
- class="navigation-btn oval"
81
+ class="oval opacity-8"
84
82
  icon="arrow_back"
83
+ color="black"
85
84
  @click="prev"
86
85
  />
87
86
 
88
87
  <Btn
89
- class="navigation-btn oval"
88
+ class="oval opacity-8"
90
89
  icon="arrow_forward"
90
+ color="black"
91
91
  @click="next"
92
92
  />
93
93
  </div>
@@ -113,32 +113,31 @@ defineExpose({ open, close })
113
113
  />
114
114
  <div v-if="!currentItem?.openFile && !currentItem?.download" />
115
115
  </div>
116
- <div class="bgl-lightbox-item">
117
- <template v-if="currentItem?.type === 'image'">
118
- <Zoomer v-model:zoom="zoom" :disabled="!currentItem?.enableZoom" :mouse-wheel-to-zoom="false">
119
- <Image :draggable="false" :src="currentItem?.src" alt="Preview" class="vw90 lightbox-image" />
116
+
117
+ <Carousel v-model:index="currentIndex" :items="1" class="bgl-lightbox-item" :class="{ zoomed: zoom > 1 }" :freeDrag="zoom === 1">
118
+ <template v-for="item in group" :key="item.src">
119
+ <Zoomer v-if="item.type === 'image'" v-model:zoom="zoom" :disabled="!item?.enableZoom" :mouse-wheel-to-zoom="false">
120
+ <Image :draggable="false" :src="item?.src" alt="Preview" class="vw90 lightbox-image" />
120
121
  </Zoomer>
121
- </template>
122
- <template v-else-if="currentItem?.type === 'video'">
122
+
123
123
  <BglVideo
124
- :src="currentItem?.src"
124
+ v-else-if="item?.type === 'video'"
125
+ :src="item?.src"
125
126
  autoplay
126
127
  controls
127
128
  class="vw90"
128
129
  />
129
- </template>
130
- <template v-else-if="currentItem?.type === 'pdf'">
130
+
131
131
  <embed
132
- :src="normalizeURL(currentItem?.src)"
132
+ v-else-if="item?.type === 'pdf'"
133
+ :src="normalizeURL(item?.src)"
133
134
  type="application/pdf"
134
135
  width="100%"
135
136
  height="1080"
136
- :title="currentItem?.name"
137
+ :title="item?.name"
137
138
  class="vw90"
138
139
  >
139
- </template>
140
- <template v-else>
141
- <div class="file-info txt-white flex m_block align-items-start gap-025">
140
+ <div v-else class="file-info txt-white flex m_block align-items-start gap-025">
142
141
  <Icon class="m-0 m_none" icon="draft" :size="10" weight="12" />
143
142
  <Icon class="m-0 none m_block m_-mb-1" icon="draft" :size="4" weight="2" />
144
143
 
@@ -146,21 +145,21 @@ defineExpose({ open, close })
146
145
  <p class="mx-0 light">
147
146
  File:
148
147
  <span class="semi word-break-all ">
149
- {{ currentItem?.name }}
148
+ {{ item?.name }}
150
149
  </span>
151
150
  </p>
152
151
  <p class="mx-0 ">
153
152
  Type:
154
153
  <span class="semi">
155
- {{ currentItem?.type }}
154
+ {{ item?.type }}
156
155
  </span>
157
156
  </p>
158
- <Btn :href="currentItem?.src" target="_blank" round thin class="mt-1" value="Open file" />
157
+ <Btn :href="item?.src" target="_blank" round thin class="mt-1" value="Open file" />
159
158
  <!-- <a :href="currentItem?.src" target="_blank">Open file</a> -->
160
159
  </div>
161
160
  </div>
162
161
  </template>
163
- </div>
162
+ </Carousel>
164
163
  <div
165
164
  v-if="group && group.length > 1"
166
165
  class="flex justify-content-center mt-2 overflow
@@ -222,11 +221,16 @@ defineExpose({ open, close })
222
221
  }
223
222
 
224
223
  .bgl-lightbox-item * {
225
- max-width: 90%;
226
224
  max-height: calc(80vh - 90px);
227
225
  border-radius: 3px;
228
226
  margin: auto;
229
227
  animation: 200ms ease bgl-lightbox-load;
228
+ transition: max-height 200ms ease;
229
+ }
230
+
231
+ .bgl-lightbox-item.zoomed * {
232
+ max-height: calc(100vh - 90px);
233
+ height: calc(100vh - 90px);
230
234
  }
231
235
 
232
236
  .navigation {
@@ -234,11 +238,6 @@ defineExpose({ open, close })
234
238
  transform: translateY(-50%);
235
239
  }
236
240
 
237
- .navigation-btn {
238
- width: var(--input-height);
239
- height: var(--input-height);
240
- }
241
-
242
241
  .thumbnail {
243
242
  height: 50px;
244
243
  width: 50px;
@@ -17,7 +17,12 @@ export interface ModalOptions {
17
17
  export interface ModalFormOptions extends ModalOptions {
18
18
  'schema': BglFormSchemaFnT<any>
19
19
  'onSubmit'?: (formData: any) => any
20
+ 'submitText'?: string
21
+ 'cancelText'?: string
22
+ 'deleteText'?: string
23
+ 'duplicateText'?: string
20
24
  'onDelete'?: (id: string) => Promise<void>
25
+ 'onDuplicate'?: (formData: any) => Promise<void>
21
26
  'onError'?: (err: any) => void
22
27
  'modelValue'?: { [key: string]: any }
23
28
  'onUpdate:modelValue'?: (val: any) => void
@@ -36,6 +36,7 @@ export interface BaseBagelField<T = { [key: string]: any }> {
36
36
  'disabled'?: boolean
37
37
  'helptext'?: string
38
38
  'options'?: BagelFieldOptions<T>
39
+ 'slots'?: { [key: string]: any }
39
40
  'defaultValue'?: any
40
41
  'transform'?: (val?: any, rowData?: T) => any
41
42
  'onUpdate'?: (val: any, rowData?: T) => void