@bagelink/vue 1.0.38 → 1.0.41

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.
@@ -5,10 +5,10 @@ import type {
5
5
  Attributes,
6
6
  BagelFieldOptions,
7
7
  BglFormSchemaFnT,
8
- BglFormSchemaT,
9
8
  Field,
10
9
  } from '@bagelink/vue'
11
- import { BagelForm, Btn } from '@bagelink/vue'
10
+ import { BagelForm, Btn, Loading } from '@bagelink/vue'
11
+ import { ref, onMounted } from 'vue'
12
12
  import { useSchemaField } from '../../composables/useSchemaField'
13
13
 
14
14
  const props = withDefaults(
@@ -40,61 +40,82 @@ const props = withDefaults(
40
40
 
41
41
  const emit = defineEmits(['update:modelValue'])
42
42
 
43
- const minimizedItems = $ref<boolean[]>([])
43
+ // State
44
+ const minimizedItems = ref<boolean[]>([])
45
+ const internalData = ref<any[]>(props.modelValue || [])
46
+ const schemaState = ref<'loading' | 'loaded' | 'error'>('loaded')
47
+ const resolvedSchemaData = ref<any[]>([])
48
+
49
+ // Resolve schema (handles sync, async, function, and direct values)
50
+ async function resolveSchema() {
51
+ if (!props.schema) {
52
+ resolvedSchemaData.value = []
53
+ schemaState.value = 'loaded'
54
+ return
55
+ }
44
56
 
45
- const data = $ref<T[]>(props.modelValue || [])
57
+ try {
58
+ schemaState.value = 'loading'
59
+ const isPromise = (obj: any) => obj && typeof obj.then === 'function'
60
+
61
+ let result: any
62
+ if (typeof props.schema === 'function') {
63
+ result = props.schema()
64
+ result = isPromise(result) ? await result : result
65
+ } else {
66
+ result = isPromise(props.schema) ? await props.schema : props.schema
67
+ }
68
+
69
+ resolvedSchemaData.value = result
70
+ schemaState.value = 'loaded'
71
+ } catch (error) {
72
+ console.error('Schema error:', error)
73
+ schemaState.value = 'error'
74
+ resolvedSchemaData.value = []
75
+ }
76
+ }
77
+
78
+ // Initialize schema on mount
79
+ onMounted(() => {
80
+ resolveSchema()
81
+ })
46
82
 
83
+ // Event handlers
47
84
  function emitValue() {
48
- emit('update:modelValue', data)
85
+ emit('update:modelValue', internalData.value)
49
86
  }
50
87
 
51
88
  function deleteItem(i: number) {
52
- data.splice(i, 1)
89
+ internalData.value.splice(i, 1)
53
90
  emitValue()
54
91
  }
55
92
 
56
93
  function addItem() {
57
- data.push({} as any)
94
+ internalData.value.push({})
58
95
  emitValue()
59
96
  }
60
97
 
61
98
  function toggleMinimized(index: number) {
62
- minimizedItems[index] = !minimizedItems[index]
99
+ minimizedItems.value[index] = !minimizedItems.value[index]
63
100
  }
64
101
 
65
- const computedField = $computed(
66
- () => ({
67
- label: props.label,
68
- placeholder: props.placeholder,
69
- children: props.children,
70
- // class: props.class,
71
- attrs: props.attrs,
72
- required: props.required,
73
- disabled: props.disabled,
74
- helptext: props.helptext,
75
- options: props.options,
76
- defaultValue: props.defaultValue,
77
- transform: props.transform,
78
- $el: props.el,
79
- }) as Field<T>
80
- ) as Field<Record<string, any>>
81
-
82
- const resolvedSchema = $computed<BglFormSchemaT<T>>(() => {
83
- if (!props.schema) return [] as BglFormSchemaT<T>
84
- return typeof props.schema === 'function' ? props.schema() : props.schema
85
- })
102
+ function updateItem(index: number, value: any) {
103
+ internalData.value[index] = value
104
+ emitValue()
105
+ }
86
106
 
87
- const { renderField } = useSchemaField<Record<string, any>>({
88
- mode: 'form',
89
- getRowData: () => data,
90
- onUpdate: (field, value) => {
91
- if (!field.id) return
92
- const index = Number.parseInt(field.id)
93
- if (Number.isNaN(index)) return
94
- data[index] = value
95
- emitValue()
96
- }
97
- })
107
+ // // Field rendering
108
+ // const { renderField } = useSchemaField<any>({
109
+ // mode: 'form',
110
+ // getRowData: () => internalData.value,
111
+ // onUpdate: (field, value) => {
112
+ // if (!field.id) return
113
+ // const index = Number.parseInt(field.id)
114
+ // if (Number.isNaN(index)) return
115
+ // internalData.value[index] = value
116
+ // emitValue()
117
+ // }
118
+ // })
98
119
  </script>
99
120
 
100
121
  <template>
@@ -102,45 +123,60 @@ const { renderField } = useSchemaField<Record<string, any>>({
102
123
  <p class="label mb-05">
103
124
  {{ label }}
104
125
  </p>
105
- <div v-if="resolvedSchema" class="ps-025 border-start mb-05">
106
- <div
107
- v-for="(_, i) in data" :key="i" outline thin
108
- class="mb-05 itemBox transition ps-05 pb-025 pt-025 radius-05 gap-05 overflow-hidden"
109
- :class="{ minimized: minimizedItems[i] }"
110
- >
111
- <p v-if="minimizedItems[i]" class="minimizedText txt14 p-025 opacity-7">
112
- {{ label }} {{ i + 1 }}
113
- </p>
114
- <BagelForm v-else v-model="data[i]" :schema="resolvedSchema" @update:model-value="emitValue" />
115
- <div class="bg-gray-80 -my-05 px-025 pt-065 pb-05 txt-center space-between flex column">
116
- <Btn
117
- v-if="resolvedSchema.length > 4"
118
- class="block rotate-180 txt10 opacity-7 p-025"
119
- flat thin icon="keyboard_arrow_down"
120
- @click="toggleMinimized(i)"
121
- />
122
- <Btn
123
- v-if="props.delete"
124
- icon="delete"
125
- class="txt10 opacity-7"
126
- thin
127
- flat
128
- @click="deleteItem(i)"
126
+ <div v-if="resolvedSchemaData.length > 0" class="ps-025 border-start mb-05">
127
+ <!-- Loading state -->
128
+ <div v-if="schemaState === 'loading'" class="flex-center h-300px">
129
+ <Loading />
130
+ </div>
131
+
132
+ <!-- Error state -->
133
+ <div v-else-if="schemaState === 'error'" class="flex-center h-300px txt-red">
134
+ Error
135
+ </div>
136
+
137
+ <!-- Render items -->
138
+ <template v-else>
139
+ <div
140
+ v-for="(item, i) in internalData" :key="i" outline thin
141
+ class="mb-05 itemBox transition ps-05 pb-025 pt-025 radius-05 gap-05 overflow-hidden"
142
+ :class="{ minimized: minimizedItems[i] }"
143
+ >
144
+ <p v-if="minimizedItems[i]" class="minimizedText txt14 p-025 opacity-7">
145
+ {{ label }} {{ i + 1 }}
146
+ </p>
147
+ <BagelForm
148
+ v-else
149
+ :model-value="item"
150
+ :schema="resolvedSchemaData"
151
+ @update:model-value="val => updateItem(i, val)"
129
152
  />
153
+ <div class="bg-gray-80 -my-05 px-025 pt-065 pb-05 txt-center space-between flex column">
154
+ <Btn
155
+ v-if="resolvedSchemaData.length > 4"
156
+ class="block rotate-180 txt10 opacity-7 p-025"
157
+ flat thin icon="keyboard_arrow_down"
158
+ @click="toggleMinimized(i)"
159
+ />
160
+ <Btn
161
+ v-if="props.delete"
162
+ icon="delete"
163
+ class="txt10 opacity-7"
164
+ thin
165
+ flat
166
+ @click="deleteItem(i)"
167
+ />
168
+ </div>
130
169
  </div>
131
- </div>
132
- <Btn v-if="add" thin icon="add" color="gray" class="txt12" @click="addItem">
133
- <p>{{ label }}</p>
134
- </Btn>
170
+ <Btn v-if="add" thin icon="add" color="gray" class="txt12" @click="addItem">
171
+ <p>{{ label }}</p>
172
+ </Btn>
173
+ </template>
135
174
  </div>
136
175
 
137
176
  <template v-else>
138
- <component
139
- :is="renderField({ ...computedField, id: String(i) })"
140
- v-for="(_, i) in data"
141
- :key="i"
142
- @update:model-value="emitValue"
143
- />
177
+ <div v-for="(_, i) in internalData" :key="i">
178
+ <p>No schema available</p>
179
+ </div>
144
180
  </template>
145
181
  </div>
146
182
  </template>
@@ -10,13 +10,23 @@ interface useBglSchemaParamsT<T> {
10
10
  data?: any[]
11
11
  }
12
12
 
13
- export function useBglSchema<T = { [key: string]: unknown }>(
13
+ export async function useBglSchema<T = { [key: string]: unknown }>(
14
14
  { schema, columns, data }: useBglSchemaParamsT<T> = {}
15
- ): BglFormSchemaT<T> {
15
+ ): Promise<BglFormSchemaT<T>> {
16
16
  let _schema = schema
17
+
18
+ // Handle async schema functions
17
19
  if (typeof _schema === 'function') {
18
- _schema = _schema()
20
+ const result = _schema()
21
+ if (result instanceof Promise) {
22
+ _schema = await result
23
+ } else {
24
+ _schema = result
25
+ }
26
+ } else if (_schema instanceof Promise) {
27
+ _schema = await _schema
19
28
  }
29
+
20
30
  if (_schema) {
21
31
  return (
22
32
  columns && columns.length > 0
@@ -41,7 +51,7 @@ export function localRef<T>(
41
51
  localStorage.setItem(key, JSON.stringify(val))
42
52
  }, { immediate: true, deep: true })
43
53
 
44
- return value
54
+ return value as any
45
55
  }
46
56
 
47
57
  export const useLocalStorage = localRef
@@ -73,4 +73,4 @@ export type BglFieldT<T = { [key: string]: any }> = Field<T>
73
73
 
74
74
  export type BglFormSchemaT<T = { [key: string]: any }> = Field<T>[]
75
75
 
76
- export type BglFormSchemaFnT<T = { [key: string]: any }> = (() => BglFormSchemaT<T>) | BglFormSchemaT<T>
76
+ export type BglFormSchemaFnT<T = { [key: string]: any }> = (() => BglFormSchemaT<T>) | BglFormSchemaT<T> | (() => Promise<BglFormSchemaT<T>>) | Promise<BglFormSchemaT<T>>