@bagelink/vue 0.0.564 → 0.0.568
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/DataPreview.vue.d.ts.map +1 -1
- package/dist/components/MaterialIcon.vue.d.ts +2 -0
- package/dist/components/MaterialIcon.vue.d.ts.map +1 -1
- package/dist/components/TableSchema.vue.d.ts +34 -21
- package/dist/components/TableSchema.vue.d.ts.map +1 -1
- package/dist/components/form/BglForm.vue.d.ts.map +1 -1
- package/dist/components/form/inputs/CheckInput.vue.d.ts +21 -11
- package/dist/components/form/inputs/CheckInput.vue.d.ts.map +1 -1
- package/dist/components/form/inputs/DateInput.vue.d.ts +2 -0
- package/dist/components/form/inputs/DateInput.vue.d.ts.map +1 -1
- package/dist/components/form/inputs/FileUpload.vue.d.ts +31 -41
- package/dist/components/form/inputs/FileUpload.vue.d.ts.map +1 -1
- package/dist/components/form/inputs/RadioPillsInput.vue.d.ts +1 -1
- package/dist/components/form/inputs/RadioPillsInput.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/components/form/inputs/TelInput.vue.d.ts +11 -11
- package/dist/components/form/inputs/TelInput.vue.d.ts.map +1 -1
- package/dist/components/form/inputs/ToggleInput.vue.d.ts +18 -3
- package/dist/components/form/inputs/ToggleInput.vue.d.ts.map +1 -1
- package/dist/components/layout/TabbedLayout.vue.d.ts.map +1 -1
- package/dist/composables/index.d.ts +10 -0
- package/dist/composables/index.d.ts.map +1 -0
- package/dist/index.cjs +623 -200
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +624 -201
- package/dist/style.css +267 -124
- package/dist/types/BagelForm.d.ts +1 -0
- package/dist/types/BagelForm.d.ts.map +1 -1
- package/dist/utils/index.d.ts +3 -2
- package/dist/utils/index.d.ts.map +1 -1
- package/package.json +15 -14
- package/src/components/Btn.vue +1 -1
- package/src/components/DataPreview.vue +12 -13
- package/src/components/MapEmbed.vue +2 -2
- package/src/components/MaterialIcon.vue +7 -3
- package/src/components/TableSchema.vue +283 -104
- package/src/components/form/BglFieldSet.vue +0 -2
- package/src/components/form/BglForm.vue +2 -4
- package/src/components/form/inputs/CheckInput.vue +13 -6
- package/src/components/form/inputs/DateInput.vue +2 -0
- package/src/components/form/inputs/FileUpload.vue +63 -47
- package/src/components/form/inputs/SelectInput.vue +17 -7
- package/src/components/form/inputs/ToggleInput.vue +22 -5
- package/src/components/layout/TabbedLayout.vue +1 -1
- package/src/composables/index.ts +24 -0
- package/src/index.ts +1 -0
- package/src/styles/layout.css +24 -0
- package/src/styles/mobilLayout.css +23 -0
- package/src/styles/text.css +0 -2
- package/src/styles/theme.css +2 -1
- package/src/types/BagelForm.ts +2 -0
- package/src/utils/index.ts +22 -2
|
@@ -1,11 +1,6 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { onMounted, watch } from 'vue'
|
|
3
|
-
import {
|
|
4
|
-
Btn,
|
|
5
|
-
MaterialIcon,
|
|
6
|
-
type StorageFile,
|
|
7
|
-
useBagel,
|
|
8
|
-
} from '@bagelink/vue'
|
|
3
|
+
import { Btn, MaterialIcon, type StorageFile, useBagel } from '@bagelink/vue'
|
|
9
4
|
|
|
10
5
|
const props = defineProps<{
|
|
11
6
|
label?: string
|
|
@@ -13,6 +8,7 @@ const props = defineProps<{
|
|
|
13
8
|
files?: StorageFile | StorageFile[]
|
|
14
9
|
deleteEndpoint?: string
|
|
15
10
|
bindkey?: StrKey
|
|
11
|
+
modelValue?: FSValue
|
|
16
12
|
width?: string
|
|
17
13
|
}>()
|
|
18
14
|
|
|
@@ -32,32 +28,41 @@ type FSValue = string[] | string | number
|
|
|
32
28
|
|
|
33
29
|
const bindKey: StrKey = props.bindkey || 'id'
|
|
34
30
|
|
|
35
|
-
const
|
|
31
|
+
const emit = defineEmits(['update:modelValue'])
|
|
32
|
+
|
|
33
|
+
let file_bindkeys = $ref<FSValue>(props.modelValue || [])
|
|
36
34
|
const storageFiles = $ref<StorageFile[]>([])
|
|
37
35
|
|
|
38
|
-
const compareIds = (v1?: FSValue, v2?: FSValue) =>
|
|
36
|
+
const compareIds = (v1?: FSValue, v2?: FSValue) =>
|
|
37
|
+
[v1].flat().join(',') === [v2].flat().join(',')
|
|
39
38
|
|
|
40
39
|
onMounted(() => {
|
|
41
|
-
if (!props.files && [file_bindkeys
|
|
42
|
-
const ids = [file_bindkeys
|
|
40
|
+
if (!props.files && [file_bindkeys].flat().length) {
|
|
41
|
+
const ids = [file_bindkeys].flat().filter(Boolean)
|
|
43
42
|
if (!ids.length) return
|
|
44
43
|
if (props.multiple) {
|
|
45
|
-
ids.forEach(
|
|
46
|
-
void bagel
|
|
47
|
-
|
|
48
|
-
|
|
44
|
+
ids.forEach(id => {
|
|
45
|
+
void bagel
|
|
46
|
+
.get<StorageFile>(`/files/${id}`)
|
|
47
|
+
.then(file => {
|
|
48
|
+
storageFiles.push(file)
|
|
49
|
+
})
|
|
50
|
+
.catch(console.error)
|
|
49
51
|
})
|
|
50
52
|
} else {
|
|
51
|
-
void bagel
|
|
52
|
-
|
|
53
|
-
|
|
53
|
+
void bagel
|
|
54
|
+
.get<StorageFile>(`/files/${ids[0]}`)
|
|
55
|
+
.then(file => {
|
|
56
|
+
storageFiles.push(file)
|
|
57
|
+
})
|
|
58
|
+
.catch(console.error)
|
|
54
59
|
}
|
|
55
60
|
}
|
|
56
61
|
})
|
|
57
62
|
|
|
58
63
|
watch(
|
|
59
64
|
() => props.files,
|
|
60
|
-
|
|
65
|
+
newFiles => {
|
|
61
66
|
if (newFiles) {
|
|
62
67
|
const filesToAdd = [newFiles]
|
|
63
68
|
.flat()
|
|
@@ -67,24 +72,24 @@ watch(
|
|
|
67
72
|
}
|
|
68
73
|
}
|
|
69
74
|
},
|
|
70
|
-
{ immediate: true }
|
|
75
|
+
{ immediate: true }
|
|
71
76
|
)
|
|
72
77
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
(
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
78
|
+
function updateModelValue() {
|
|
79
|
+
let idValue: FSValue
|
|
80
|
+
if (props.multiple) {
|
|
81
|
+
idValue = storageFiles.map(f => f[bindKey]) as FSValue
|
|
82
|
+
} else {
|
|
83
|
+
idValue = (storageFiles[0][bindKey] as string) || ''
|
|
84
|
+
}
|
|
85
|
+
const isSame = [idValue]
|
|
86
|
+
.flat()
|
|
87
|
+
.every(id => [file_bindkeys].flat().includes(id))
|
|
88
|
+
if (!isSame) {
|
|
89
|
+
file_bindkeys = idValue
|
|
90
|
+
emit('update:modelValue', file_bindkeys)
|
|
91
|
+
}
|
|
92
|
+
}
|
|
88
93
|
|
|
89
94
|
const fileQueue = $ref<QueueFile[]>([])
|
|
90
95
|
let isDragOver = $ref(false)
|
|
@@ -102,17 +107,21 @@ function removeFile(file: StorageFile) {
|
|
|
102
107
|
if (props.deleteEndpoint) {
|
|
103
108
|
void bagel.delete(`${props.deleteEndpoint}/${file.id}`)
|
|
104
109
|
}
|
|
110
|
+
updateModelValue()
|
|
105
111
|
}
|
|
106
112
|
|
|
107
|
-
function flushQueue() {
|
|
108
|
-
|
|
113
|
+
async function flushQueue() {
|
|
114
|
+
for (const file of fileQueue) {
|
|
115
|
+
file.uploading = true
|
|
109
116
|
if (!props.multiple) storageFiles.splice(0, 1)
|
|
110
117
|
const serverFile = await bagel.uploadFile<StorageFile>(file.file, {
|
|
111
118
|
onUploadProgress: (e: any) => (file.progress = e.progress * 100 - 1),
|
|
112
119
|
})
|
|
113
120
|
storageFiles.push(serverFile)
|
|
121
|
+
const i = fileQueue.indexOf(file)
|
|
114
122
|
fileQueue.splice(i, 1)
|
|
115
|
-
}
|
|
123
|
+
}
|
|
124
|
+
updateModelValue()
|
|
116
125
|
}
|
|
117
126
|
|
|
118
127
|
function browse() {
|
|
@@ -122,7 +131,9 @@ function browse() {
|
|
|
122
131
|
input.onchange = (e: Event) => {
|
|
123
132
|
const target = e.target as HTMLInputElement
|
|
124
133
|
if (target.files) {
|
|
125
|
-
Array.from(target.files).forEach((file: File) =>
|
|
134
|
+
Array.from(target.files).forEach((file: File) =>
|
|
135
|
+
fileQueue.push({ name: file.name, file, progress: 0 })
|
|
136
|
+
)
|
|
126
137
|
}
|
|
127
138
|
flushQueue()
|
|
128
139
|
}
|
|
@@ -144,7 +155,9 @@ function dragover(e: DragEvent) {
|
|
|
144
155
|
function drop(e: DragEvent) {
|
|
145
156
|
preventDefault(e)
|
|
146
157
|
if (e.dataTransfer) {
|
|
147
|
-
Array.from(e.dataTransfer.files).forEach((file: File) =>
|
|
158
|
+
Array.from(e.dataTransfer.files).forEach((file: File) =>
|
|
159
|
+
fileQueue.push({ name: file.name, file, progress: 0 })
|
|
160
|
+
)
|
|
148
161
|
}
|
|
149
162
|
isDragOver = false
|
|
150
163
|
flushQueue()
|
|
@@ -170,13 +183,13 @@ function drop(e: DragEvent) {
|
|
|
170
183
|
<slot name="files" :files="storageFiles" :fileQueue>
|
|
171
184
|
<template v-for="file in storageFiles" :key="file.id">
|
|
172
185
|
<div v-if="!multiple" class="single-image">
|
|
173
|
-
<img class="single preview" :src="file.url" alt=""
|
|
174
|
-
|
|
186
|
+
<img class="single preview" :src="file.url" alt="" />
|
|
187
|
+
<!-- <p class="no-margin">
|
|
175
188
|
{{ file.name }}
|
|
176
189
|
</p> -->
|
|
177
190
|
</div>
|
|
178
191
|
<div v-if="multiple" class="multi-image-item previewName">
|
|
179
|
-
<img class="preview" :src="file.url" alt=""
|
|
192
|
+
<img class="preview" :src="file.url" alt="" />
|
|
180
193
|
<p class="no-margin">
|
|
181
194
|
{{ file.name }}
|
|
182
195
|
</p>
|
|
@@ -191,7 +204,7 @@ function drop(e: DragEvent) {
|
|
|
191
204
|
</template>
|
|
192
205
|
<template v-for="fileQ in fileQueue" :key="fileQ.file">
|
|
193
206
|
<div v-if="!multiple" class="imagePreviewWrap">
|
|
194
|
-
<img class="preview" :src="fileToUrl(fileQ.file)" alt=""
|
|
207
|
+
<img class="preview" :src="fileToUrl(fileQ.file)" alt="" />
|
|
195
208
|
</div>
|
|
196
209
|
<div class="previewName">
|
|
197
210
|
<img
|
|
@@ -200,7 +213,7 @@ function drop(e: DragEvent) {
|
|
|
200
213
|
class="preview"
|
|
201
214
|
:src="fileToUrl(fileQ.file)"
|
|
202
215
|
alt=""
|
|
203
|
-
|
|
216
|
+
/>
|
|
204
217
|
<p class="no-margin">
|
|
205
218
|
{{ fileQ.name }}
|
|
206
219
|
</p>
|
|
@@ -218,7 +231,11 @@ function drop(e: DragEvent) {
|
|
|
218
231
|
</div>
|
|
219
232
|
</template>
|
|
220
233
|
</slot>
|
|
221
|
-
<slot
|
|
234
|
+
<slot
|
|
235
|
+
v-if="(!storageFiles.length && !fileQueue.length) || multiple"
|
|
236
|
+
name="placeholder"
|
|
237
|
+
:browse
|
|
238
|
+
>
|
|
222
239
|
<p>Drop files here or click to upload</p>
|
|
223
240
|
</slot>
|
|
224
241
|
</div>
|
|
@@ -273,10 +290,9 @@ img.preview {
|
|
|
273
290
|
object-fit: cover;
|
|
274
291
|
background: var(--bgl-gray-light);
|
|
275
292
|
box-shadow: 0 0 10px #00000012;
|
|
276
|
-
|
|
277
293
|
}
|
|
278
294
|
|
|
279
|
-
img.preview.single{
|
|
295
|
+
img.preview.single {
|
|
280
296
|
max-width: var(--width);
|
|
281
297
|
width: auto;
|
|
282
298
|
object-fit: contain;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<script lang="ts" setup>
|
|
2
|
-
import { watch } from 'vue'
|
|
2
|
+
import { onMounted, watch } from 'vue'
|
|
3
3
|
import { Dropdown } from 'floating-vue'
|
|
4
4
|
import 'floating-vue/style.css'
|
|
5
5
|
import {
|
|
@@ -27,6 +27,7 @@ const props = defineProps<{
|
|
|
27
27
|
multiselect?: boolean
|
|
28
28
|
icon?: MaterialIcons
|
|
29
29
|
hideLabel?: boolean
|
|
30
|
+
defaultValue?: Option
|
|
30
31
|
}>()
|
|
31
32
|
|
|
32
33
|
const emit = defineEmits(['update:modelValue'])
|
|
@@ -47,8 +48,7 @@ function openOptions() {
|
|
|
47
48
|
|
|
48
49
|
function updateOpen(visible: boolean) {
|
|
49
50
|
open = visible
|
|
50
|
-
if (!open) { search = ''
|
|
51
|
-
}
|
|
51
|
+
if (!open) { search = '' }
|
|
52
52
|
else {
|
|
53
53
|
setTimeout(
|
|
54
54
|
() => (searchInput as any)?.$el?.querySelector('input')?.focus(),
|
|
@@ -83,7 +83,7 @@ function getValue(option?: Option) {
|
|
|
83
83
|
return option.value
|
|
84
84
|
}
|
|
85
85
|
|
|
86
|
-
const isSelected = (option: Option) =>
|
|
86
|
+
const isSelected = (option: Option) => selectedItems.find(item => getValue(option) === getValue(item)) !== undefined
|
|
87
87
|
|
|
88
88
|
const filteredOptions = $computed(() => props.options.filter((option) => {
|
|
89
89
|
const searchTerm = search
|
|
@@ -136,8 +136,7 @@ watch(
|
|
|
136
136
|
() => props.modelValue,
|
|
137
137
|
(newVal: Option | Option[]) => {
|
|
138
138
|
if (!props.multiselect) {
|
|
139
|
-
const newOption
|
|
140
|
-
= props.options.find(o => getValue(o) === newVal) || newVal
|
|
139
|
+
const newOption = props.options.find(o => getValue(o) === newVal) ?? newVal
|
|
141
140
|
if (newOption && !isSelected(newOption)) selectedItems = [newOption]
|
|
142
141
|
} else {
|
|
143
142
|
const isSame = compareArrays([newVal].flat(), selectedItems)
|
|
@@ -156,7 +155,7 @@ watch(
|
|
|
156
155
|
const exists = props.options.find(
|
|
157
156
|
o => getValue(o) === getValue(option),
|
|
158
157
|
)
|
|
159
|
-
if (
|
|
158
|
+
if (exists === undefined) selectedItems.splice(i, 1)
|
|
160
159
|
else selectedItems.splice(i, 1, exists)
|
|
161
160
|
})
|
|
162
161
|
// const original = JSON.stringify(props.options.map(getValue));
|
|
@@ -165,6 +164,17 @@ watch(
|
|
|
165
164
|
},
|
|
166
165
|
{ deep: true, immediate: true },
|
|
167
166
|
)
|
|
167
|
+
|
|
168
|
+
onMounted(() => {
|
|
169
|
+
if (props.defaultValue !== undefined) {
|
|
170
|
+
const defaultOption = props.options.find(
|
|
171
|
+
o => getValue(o) === getValue(props.defaultValue),
|
|
172
|
+
)
|
|
173
|
+
if (defaultOption === undefined) return
|
|
174
|
+
|
|
175
|
+
selectedItems = [defaultOption]
|
|
176
|
+
}
|
|
177
|
+
})
|
|
168
178
|
</script>
|
|
169
179
|
|
|
170
180
|
<template>
|
|
@@ -6,10 +6,13 @@ const props = withDefaults(defineProps<{
|
|
|
6
6
|
id?: string
|
|
7
7
|
title?: string
|
|
8
8
|
small?: boolean
|
|
9
|
+
required?: boolean
|
|
9
10
|
defaultValue?: boolean
|
|
10
11
|
}>(), { defaultValue: false })
|
|
11
12
|
|
|
12
|
-
const
|
|
13
|
+
const inputId = $ref(props.id || Math.random().toString(36).substring(7))
|
|
14
|
+
|
|
15
|
+
const checked = defineModel<boolean | undefined>('modelValue', { default: undefined })
|
|
13
16
|
|
|
14
17
|
onMounted(() => {
|
|
15
18
|
if (checked.value === undefined) checked.value = props.defaultValue
|
|
@@ -17,13 +20,27 @@ onMounted(() => {
|
|
|
17
20
|
</script>
|
|
18
21
|
|
|
19
22
|
<template>
|
|
20
|
-
<div
|
|
23
|
+
<div
|
|
24
|
+
class="bagel-input bgl-checkbox justify-content-center gap-1"
|
|
25
|
+
:title
|
|
26
|
+
:class="{ small }"
|
|
27
|
+
@click.prevent="checked = !checked"
|
|
28
|
+
>
|
|
21
29
|
<div class="switch" :class="{ checked }">
|
|
22
30
|
<span class="slider round" />
|
|
23
31
|
</div>
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
32
|
+
|
|
33
|
+
<input
|
|
34
|
+
:id="inputId"
|
|
35
|
+
v-model="checked"
|
|
36
|
+
type="checkbox"
|
|
37
|
+
:required
|
|
38
|
+
>
|
|
39
|
+
|
|
40
|
+
<label :for="inputId">
|
|
41
|
+
<slot name="label">
|
|
42
|
+
{{ label }}
|
|
43
|
+
</slot>
|
|
27
44
|
</label>
|
|
28
45
|
</div>
|
|
29
46
|
</template>
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { type BglFormSchemaFnT, type BglFormSchemaT, getFallbackSchema } from '@bagelink/vue'
|
|
2
|
+
|
|
3
|
+
interface useBglSchemaParamsT {
|
|
4
|
+
schema?: BglFormSchemaFnT
|
|
5
|
+
showFields?: string[]
|
|
6
|
+
data?: any[]
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function useBglSchema(
|
|
10
|
+
{ schema, showFields, data }: useBglSchemaParamsT = {}
|
|
11
|
+
): BglFormSchemaT {
|
|
12
|
+
let _schema = schema
|
|
13
|
+
if (typeof _schema === 'function') {
|
|
14
|
+
_schema = _schema()
|
|
15
|
+
}
|
|
16
|
+
if (_schema) {
|
|
17
|
+
return (
|
|
18
|
+
showFields && showFields.length
|
|
19
|
+
? _schema.filter(f => showFields.includes(f.id as string))
|
|
20
|
+
: _schema
|
|
21
|
+
) as BglFormSchemaT
|
|
22
|
+
}
|
|
23
|
+
return getFallbackSchema(data, showFields)
|
|
24
|
+
}
|
package/src/index.ts
CHANGED
package/src/styles/layout.css
CHANGED
|
@@ -2185,6 +2185,30 @@
|
|
|
2185
2185
|
.direction-rtl {
|
|
2186
2186
|
direction: rtl;
|
|
2187
2187
|
}
|
|
2188
|
+
.inset-0, .inset{
|
|
2189
|
+
inset: 0;
|
|
2190
|
+
}
|
|
2191
|
+
.inset-1{
|
|
2192
|
+
inset: 1rem;
|
|
2193
|
+
}
|
|
2194
|
+
.inset-2{
|
|
2195
|
+
inset: 2rem;
|
|
2196
|
+
}
|
|
2197
|
+
|
|
2198
|
+
.inset-3{
|
|
2199
|
+
inset: 3rem;
|
|
2200
|
+
}
|
|
2201
|
+
|
|
2202
|
+
.inset-4{
|
|
2203
|
+
inset: 4rem;
|
|
2204
|
+
}
|
|
2205
|
+
|
|
2206
|
+
.inset-5{
|
|
2207
|
+
inset: 5rem;
|
|
2208
|
+
}
|
|
2209
|
+
.inset-6{
|
|
2210
|
+
inset: 6rem;
|
|
2211
|
+
}
|
|
2188
2212
|
|
|
2189
2213
|
|
|
2190
2214
|
@media screen and (max-width: 910px) {
|
|
@@ -2085,5 +2085,28 @@
|
|
|
2085
2085
|
.m_-bottom-8{
|
|
2086
2086
|
bottom: -8rem !important;
|
|
2087
2087
|
}
|
|
2088
|
+
.m_inset-0, .m_inset{
|
|
2089
|
+
inset: 0;
|
|
2090
|
+
}
|
|
2091
|
+
.m_inset-1{
|
|
2092
|
+
inset: 1rem;
|
|
2093
|
+
}
|
|
2094
|
+
.m_inset-2{
|
|
2095
|
+
inset: 2rem;
|
|
2096
|
+
}
|
|
2097
|
+
|
|
2098
|
+
.m_inset-3{
|
|
2099
|
+
inset: 3rem;
|
|
2100
|
+
}
|
|
2088
2101
|
|
|
2102
|
+
.m_inset-4{
|
|
2103
|
+
inset: 4rem;
|
|
2104
|
+
}
|
|
2105
|
+
|
|
2106
|
+
.m_inset-5{
|
|
2107
|
+
inset: 5rem;
|
|
2108
|
+
}
|
|
2109
|
+
.m_inset-6{
|
|
2110
|
+
inset: 6rem;
|
|
2111
|
+
}
|
|
2089
2112
|
}
|
package/src/styles/text.css
CHANGED
package/src/styles/theme.css
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/* @import url("https://fonts.googleapis.com/css2?family=Noto+Sans+Hebrew:wght@300;400;500;600;700&display=swap"); */
|
|
2
2
|
/*noinspection CssUnknownTarget*/
|
|
3
|
-
@import url("https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined&display=swap");
|
|
3
|
+
/* @import url("https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined&display=swap"); */
|
|
4
|
+
@import url("https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200");
|
|
4
5
|
@import url("https://fonts.googleapis.com/css2?family=Lexend:wght@100;200;300;400;500;600;700;800;900&display=swap");
|
|
5
6
|
|
|
6
7
|
:root {
|
package/src/types/BagelForm.ts
CHANGED
|
@@ -54,3 +54,5 @@ export interface SelectBagelField<T> extends BaseBagelField<T> {
|
|
|
54
54
|
export type Field<T = Record<string, any>> = BaseBagelField<T> | InputBagelField<T> | SelectBagelField<T>
|
|
55
55
|
|
|
56
56
|
export type BglFormSchemaT<T = Record<string, any>> = Field<T>[]
|
|
57
|
+
|
|
58
|
+
export type BglFormSchemaFnT<T = Record<string, any>> = (() => BglFormSchemaT<T>) | BglFormSchemaT<T>
|
package/src/utils/index.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Attributes } from '
|
|
1
|
+
import type { Attributes, BglFormSchemaT } from '@bagelink/vue'
|
|
2
2
|
|
|
3
3
|
let timeout: any
|
|
4
4
|
export function debounce(fn: () => void, delay = 500) {
|
|
@@ -55,7 +55,10 @@ export function iffer(field: any, itemData: any) {
|
|
|
55
55
|
return true
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
-
export
|
|
58
|
+
export function denullify(itemData?: Record<string, any>, fieldID?: string) {
|
|
59
|
+
if (!fieldID) return null
|
|
60
|
+
return itemData ? itemData[fieldID] : null
|
|
61
|
+
}
|
|
59
62
|
|
|
60
63
|
export const isDate = (dateToTest: any) => !Number.isNaN(Date.parse(dateToTest))
|
|
61
64
|
|
|
@@ -64,3 +67,20 @@ export { formatString } from './strings'
|
|
|
64
67
|
export * as bagelFormUtils from './BagelFormUtils'
|
|
65
68
|
|
|
66
69
|
export { useLang } from './lang'
|
|
70
|
+
|
|
71
|
+
export function getFallbackSchema(data?: any[], showFields?: string[]): BglFormSchemaT {
|
|
72
|
+
const keys = [
|
|
73
|
+
...new Set((data ?? []).map(Object.keys).flat()),
|
|
74
|
+
] as string[]
|
|
75
|
+
|
|
76
|
+
const schema: BglFormSchemaT = keys.map(
|
|
77
|
+
id => ({
|
|
78
|
+
id,
|
|
79
|
+
label: keyToLabel(id),
|
|
80
|
+
})
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
return showFields
|
|
84
|
+
? schema.filter(f => showFields.includes(f.id as string) || !f.id)
|
|
85
|
+
: schema
|
|
86
|
+
}
|