@bagelink/vue 0.0.1033 → 0.0.1035

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.
@@ -1,5 +1,5 @@
1
1
  <script setup lang="ts">
2
- import { Skeleton, normalizeDimension, appendScript } from '@bagelink/vue'
2
+ import { Skeleton, normalizeDimension, appendScript, useBagel } from '@bagelink/vue'
3
3
  import { watch } from 'vue'
4
4
 
5
5
  declare global {
@@ -8,8 +8,9 @@ declare global {
8
8
  }
9
9
  }
10
10
 
11
- const { height, width, alt = '', src } = defineProps<{
12
- src: string
11
+ const { height, width, alt = '', src, pathKey } = defineProps<{
12
+ src?: string
13
+ pathKey?: string
13
14
  alt?: string
14
15
  width?: string | number
15
16
  height?: string | number
@@ -18,12 +19,18 @@ const { height, width, alt = '', src } = defineProps<{
18
19
 
19
20
  let imageSrc = $ref<string | null>(null)
20
21
 
21
- async function loadImage(src: string) {
22
- if (!src) {
22
+ const bagel = useBagel()
23
+ const fileBaseUrl = $computed(() => (bagel.fileBaseUrl || 'https://files.bagel.design').replace(/\/$/, ''))
24
+ const pathToUrl = () => `${fileBaseUrl}/${pathKey}`
25
+
26
+ async function loadImage() {
27
+ const url = src || pathToUrl()
28
+ console.log(url)
29
+ if (!url) {
23
30
  imageSrc = null
24
31
  return
25
32
  }
26
- const ext = src.split('.').pop()?.toLowerCase().split('?').shift()
33
+ const ext = url.split('.').pop()?.toLowerCase().split('?').shift()
27
34
 
28
35
  if (ext === 'heic') {
29
36
  if (!('caches' in window)) {
@@ -31,7 +38,7 @@ async function loadImage(src: string) {
31
38
  } else {
32
39
  try {
33
40
  const imgCache = await window.caches.open('img-cache')
34
- const cachedResponse = await imgCache.match(src)
41
+ const cachedResponse = await imgCache.match(url)
35
42
  if (cachedResponse) {
36
43
  imageSrc = URL.createObjectURL(await cachedResponse.blob())
37
44
  return
@@ -42,7 +49,7 @@ async function loadImage(src: string) {
42
49
  }
43
50
  try {
44
51
  await appendScript('https://cdnjs.cloudflare.com/ajax/libs/heic2any/0.0.1/index.min.js')
45
- const response = await fetch(src)
52
+ const response = await fetch(url)
46
53
  const blob = await response.blob()
47
54
  const convertedBlob = await window.heic2any({ blob }) as Blob
48
55
  imageSrc = URL.createObjectURL(convertedBlob)
@@ -50,7 +57,7 @@ async function loadImage(src: string) {
50
57
  if ('caches' in window) {
51
58
  try {
52
59
  const imgCache = await window.caches.open('img-cache')
53
- imgCache.put(src, new Response(convertedBlob))
60
+ imgCache.put(url, new Response(convertedBlob))
54
61
  } catch (cacheError) {
55
62
  console.warn('Failed to cache the image:', cacheError)
56
63
  }
@@ -59,10 +66,10 @@ async function loadImage(src: string) {
59
66
  console.error('Error converting HEIC file:', error)
60
67
  }
61
68
  } else {
62
- imageSrc = src
69
+ imageSrc = url
63
70
  }
64
71
  }
65
- watch(() => src, loadImage, { immediate: true })
72
+ watch(() => [src, pathKey], loadImage, { immediate: true })
66
73
  </script>
67
74
 
68
75
  <template>
@@ -11,7 +11,9 @@ import {
11
11
  ToggleInput,
12
12
  bindAttrs,
13
13
  classify,
14
- BagelForm
14
+ BagelForm,
15
+ NumberInput,
16
+ UploadInput,
15
17
  } from '@bagelink/vue'
16
18
  import TabsNav from '../layout/TabsNav.vue'
17
19
 
@@ -35,11 +37,13 @@ const is = $computed(() => {
35
37
  customAttrs.multiline = true
36
38
  return TextInput
37
39
  }
40
+ if (props.field.$el === 'number') return NumberInput
38
41
  if (props.field.$el === 'array') return FieldArray
39
42
  if (props.field.$el === 'select') return SelectInput
40
43
  if (props.field.$el === 'toggle') return ToggleInput
41
44
  if (props.field.$el === 'check') return CheckInput
42
45
  if (props.field.$el === 'richtext') return RichText
46
+ if (props.field.$el === 'upload') return UploadInput
43
47
  if (props.field.$el === 'file') return FileUpload
44
48
  if (props.field.$el === 'date') return DateInput
45
49
  if (props.field.$el === 'tabs') return TabsNav
@@ -14,7 +14,7 @@ interface NumberInputProps {
14
14
  icon?: MaterialIcons
15
15
  label?: string
16
16
  placeholder?: string
17
- disabled: boolean
17
+ disabled?: boolean
18
18
  required?: boolean
19
19
  id?: string
20
20
  helptext?: string
@@ -97,7 +97,7 @@ watch(() => modelValue, (newVal) => {
97
97
  <label :for="id">
98
98
  {{ label }}
99
99
  <div class="gap-025" :class="{ 'column flex': layout === 'vertical', 'flex': layout === 'horizontal' }">
100
- <Btn v-if="layout && btnLayouts.includes(layout)" icon="add" class="radius" :class="[{ 'bgl-big-ctrl-num-btn': layout === 'vertical' }]" @click="increment" />
100
+ <Btn v-if="layout && btnLayouts.includes(layout)" flat icon="add" class="radius" :class="[{ 'bgl-big-ctrl-num-btn': layout === 'vertical' }]" @click="increment" />
101
101
 
102
102
  <input
103
103
  :id
@@ -131,7 +131,7 @@ watch(() => modelValue, (newVal) => {
131
131
  v-if="icon"
132
132
  :icon
133
133
  />
134
- <Btn v-if="layout && btnLayouts.includes(layout)" icon="remove" class="radius" :class="[{ 'bgl-big-ctrl-num-btn': layout === 'vertical' }]" @click="decrement" />
134
+ <Btn v-if="layout && btnLayouts.includes(layout)" flat icon="remove" class="radius" :class="[{ 'bgl-big-ctrl-num-btn': layout === 'vertical' }]" @click="decrement" />
135
135
 
136
136
  <div v-if="spinner && (!layout || !btnLayouts.includes(layout))" class="flex column spinner">
137
137
  <Btn icon="add" flat thin class="bgl-ctrl-num-btn" @click="increment" />
@@ -1,5 +1,4 @@
1
1
  <script setup lang="ts">
2
- import type { MaterialIcons } from '@bagelink/vue'
3
2
  import type { BglFile, QueueFile } from './upload.types'
4
3
  import { Btn, IMAGE_FORMATS_REGEXP, Icon, useBagel, Card, Image } from '@bagelink/vue'
5
4
  import { watch } from 'vue'
@@ -27,10 +26,11 @@ const props = withDefaults(defineProps<{
27
26
 
28
27
  const emit = defineEmits(['update:modelValue', 'addFileStart'])
29
28
  const bagel = useBagel()
30
- const fileBaseUrl = $computed(() => (props.baseURL || bagel.fileBaseUrl || 'https://files.bagel.design').replace(/\/$/, ''))
31
29
 
32
30
  files.setBaseUrl(bagel.host)
33
31
 
32
+ const fileBaseUrl = $computed(() => (props.baseURL || bagel.fileBaseUrl || 'https://files.bagel.design').replace(/\/$/, ''))
33
+ const pathToUrl = (path_key: string) => `${fileBaseUrl}/${path_key}`
34
34
  const fileQueue = $ref<QueueFile[]>([])
35
35
  let storageFiles = $ref<BglFile[]>([])
36
36
  const pk = $ref<string[]>([props.modelValue].flat().filter(Boolean) as string[])
@@ -46,7 +46,6 @@ watch(() => pk, (value) => {
46
46
  }, { deep: true })
47
47
 
48
48
  const isImage = (str: string) => IMAGE_FORMATS_REGEXP.test(str)
49
- const pathToUrl = (path_key: string) => `${fileBaseUrl}/${path_key}`
50
49
  const fileToUrl = (file: File) => URL.createObjectURL(file)
51
50
 
52
51
  let isDragOver = $ref(false)
@@ -165,18 +164,25 @@ watch(() => props.dirPath, () => {
165
164
  <div class="txt-gray txt-12 flex">
166
165
  <div class="m-05 flex opacity-7 z-99">
167
166
  <Btn
168
- v-for="action in [
169
- { tooltip: 'Delete', icon: 'delete' as MaterialIcons, onClick: () => removeFile(path_key) },
170
- { tooltip: 'Replace', icon: 'autorenew' as MaterialIcons, onClick: browse },
171
- { tooltip: 'Download', icon: 'download' as MaterialIcons, href: pathToUrl(path_key), download: path_key.split('/').pop() },
172
- ]"
173
- :key="action.tooltip"
174
- v-tooltip="action.tooltip"
167
+ v-tooltip="'Delete'"
168
+ color="gray"
169
+ thin
170
+ icon="delete"
171
+ @click="removeFile(path_key)"
172
+ />
173
+ <Btn
174
+ v-tooltip="'Replace'"
175
175
  color="gray"
176
176
  thin
177
- :icon="action.icon"
178
- v-bind="action.href ? { href: action.href, download: action.download, target: '_blank' } : {}"
179
- @click.stop="action.onClick"
177
+ icon="autorenew"
178
+ @click="browse"
179
+ />
180
+ <Btn
181
+ icon="download"
182
+ flat
183
+ thin
184
+ :href="pathToUrl(path_key)"
185
+ :download="path_key.split('/').pop()"
180
186
  />
181
187
  <p
182
188
  v-lightbox="{ src: pathToUrl(path_key), download: true }"
@@ -219,12 +225,11 @@ watch(() => props.dirPath, () => {
219
225
  class="multi-image-item-preview"
220
226
  :class="{ 'bgl_fill-image': fill }"
221
227
  >
222
- <img
228
+ <Image
223
229
  v-if="isImage(path_key)"
230
+ :pathKey="path_key"
224
231
  class="multi-preview"
225
- :src="pathToUrl(path_key)"
226
- alt=""
227
- >
232
+ />
228
233
  <Icon v-else icon="description" class="multi-preview" />
229
234
  <p class="m-0">
230
235
  {{ path_key.split('/').pop() }}
@@ -234,7 +239,7 @@ watch(() => props.dirPath, () => {
234
239
  flat
235
240
  icon="delete"
236
241
  color="red"
237
- @click.stop="removeFile(path_key)"
242
+ @click="removeFile(path_key)"
238
243
  />
239
244
  </div>
240
245
  <div
@@ -304,7 +309,7 @@ watch(() => props.dirPath, () => {
304
309
  <div v-if="isImage(path_key)" class="h-100">
305
310
  <Image
306
311
  class="single-preview"
307
- :src="pathToUrl(path_key)"
312
+ :pathKey="path_key"
308
313
  alt=""
309
314
  />
310
315
  </div>
@@ -19,4 +19,4 @@ export { default as TableField } from './TableField.vue'
19
19
  export { default as TelInput } from './TelInput.vue'
20
20
  export { default as TextInput } from './TextInput.vue'
21
21
  export { default as ToggleInput } from './ToggleInput.vue'
22
- export { default as Upload } from './Upload/UploadFile.vue'
22
+ export { default as UploadInput } from './Upload/UploadInput.vue'
@@ -142,7 +142,7 @@ export function numField(
142
142
  options?: NumFieldOptions,
143
143
  ): Field {
144
144
  return {
145
- $el: 'text',
145
+ $el: 'number',
146
146
  class: options?.class,
147
147
  required: options?.required,
148
148
  defaultValue: options?.defaultValue,
@@ -152,12 +152,9 @@ export function numField(
152
152
  placeholder: options?.placeholder,
153
153
  helptext: options?.helptext,
154
154
  attrs: {
155
- type: 'number',
156
- nativeInputAttrs: {
157
- step: options?.step,
158
- min: options?.min,
159
- max: options?.max,
160
- },
155
+ step: options?.step,
156
+ min: options?.min,
157
+ max: options?.max,
161
158
  },
162
159
  }
163
160
  }
@@ -170,6 +167,19 @@ export function frmRow(...children: Field[]) {
170
167
  }
171
168
  }
172
169
 
170
+ interface UploadOptions extends InputOptions {
171
+ multiple?: boolean
172
+ }
173
+
174
+ export function uploadField(id: string, label?: string, options?: UploadOptions) {
175
+ return {
176
+ $el: 'upload',
177
+ id,
178
+ label,
179
+ attrs: options,
180
+ }
181
+ }
182
+
173
183
  export function bglForm(idOrField?: string | Field, ...schema: Field[]) {
174
184
  if (typeof idOrField === 'string') {
175
185
  return {