@bagelink/vue 1.8.9 → 1.8.14

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,25 +1,18 @@
1
1
  <script setup lang="ts" generic="T extends Record<string, any>">
2
2
  import type { Option } from '@bagelink/vue'
3
- import type { ComparisonOperator } from '../utils/queryFilter'
3
+ import type { ComparisonOperator, LogicalOperator, QueryConditions } from './queryFilter'
4
4
  import { Btn, DateInput, Dropdown, Icon, SelectInput, TextInput } from '@bagelink/vue'
5
5
  import { computed } from 'vue'
6
6
 
7
7
  type OptionsSource = Option[] | ((query: string) => Promise<Option[]>)
8
8
  type Language = 'he' | 'en'
9
9
 
10
- // Define missing types locally
11
- type QueryObject<T = Record<string, any>> = Record<string, any> & T
12
- interface Condition {
13
- pr?: boolean
14
- [operator: string]: any
15
- }
16
-
17
- interface FilterCondition {
10
+ interface UICondition {
18
11
  id: string
19
12
  field: string
20
13
  operator: ComparisonOperator
21
14
  value: string
22
- connector: 'and' | 'or' | ''
15
+ connector: LogicalOperator | ''
23
16
  }
24
17
 
25
18
  const props = defineProps<{
@@ -33,10 +26,15 @@ const props = defineProps<{
33
26
  }>()
34
27
 
35
28
  const emit = defineEmits<{
36
- change: [value: QueryObject<T>]
29
+ change: [value: QueryConditions<T>]
37
30
  }>()
38
31
 
39
- const model = defineModel<QueryObject<T>>({ default: () => ({}) })
32
+ const model = defineModel<QueryConditions<T>>({ default: () => [] })
33
+
34
+ let conditionIdCounter = 0
35
+ function generateId() {
36
+ return `cond_${++conditionIdCounter}_${Date.now()}`
37
+ }
40
38
 
41
39
  // Localization data
42
40
  const texts = {
@@ -113,45 +111,27 @@ const texts = {
113
111
  // Get current language texts
114
112
  const currentTexts = computed(() => texts[props.language || 'en'])
115
113
 
116
- // Derive conditions directly from model (read-only view)
117
- const conditions = computed(() => {
118
- const obj = model.value
119
- if (Object.keys(obj).filter(k => !k.startsWith('_')).length === 0) {
120
- return [] as FilterCondition[]
121
- }
122
-
123
- const result: FilterCondition[] = []
124
- const useOr = (obj as any)._or === true
125
-
126
- for (const [field, value] of Object.entries(obj)) {
127
- if (field.startsWith('_')) continue
114
+ // Map model conditions to UI conditions with stable IDs
115
+ const conditionIds = new Map<number, string>()
128
116
 
129
- const condition: FilterCondition = {
130
- id: field, // use field as id for stability
131
- field,
132
- operator: 'eq',
133
- value: '',
134
- connector: result.length > 0 ? (useOr ? 'or' : 'and') : '',
117
+ const conditions = computed(() => {
118
+ const arr = model.value || []
119
+ return arr.map((cond, index) => {
120
+ // Get or create stable ID for this index
121
+ if (!conditionIds.has(index)) {
122
+ conditionIds.set(index, generateId())
135
123
  }
136
-
137
- if (value !== null && value !== undefined && typeof value === 'object' && !Array.isArray(value)) {
138
- const cond = value as Condition
139
- if (cond.pr === true) {
140
- condition.operator = 'pr'
141
- } else {
142
- const op = Object.keys(cond)[0] as ComparisonOperator
143
- condition.operator = op
144
- const val = (cond as any)[op]
145
- condition.value = val === null ? 'null' : String(val)
146
- }
147
- } else if (value !== undefined) {
148
- condition.value = value === null ? 'null' : String(value)
124
+ const id = conditionIds.get(index)!
125
+
126
+ const uiCond: UICondition = {
127
+ id,
128
+ field: cond.field as string,
129
+ operator: cond.op,
130
+ value: cond.value === null ? 'null' : cond.value === undefined ? '' : String(cond.value),
131
+ connector: index > 0 ? (cond.connector || 'and') : '',
149
132
  }
150
-
151
- result.push(condition)
152
- }
153
-
154
- return result
133
+ return uiCond
134
+ })
155
135
  })
156
136
 
157
137
  const allOperatorOptions = computed(() => [
@@ -191,43 +171,60 @@ const booleanOptions = computed(() => [
191
171
  { label: currentTexts.value.boolean.false, value: 'false' },
192
172
  ])
193
173
 
194
- // Update a single field in model
195
- function updateCondition(field: string, operator: ComparisonOperator, value: string) {
196
- const newModel = { ...model.value }
197
-
198
- let parsedValue: any = value
199
- if (value === 'true') parsedValue = true
200
- else if (value === 'false') parsedValue = false
201
- else if (value === 'null') parsedValue = null
202
- else if (!Number.isNaN(Number(value)) && value.trim() !== '') parsedValue = Number(value)
203
-
204
- if (operator === 'eq') {
205
- (newModel as any)[field] = parsedValue
206
- } else if (operator === 'pr') {
207
- (newModel as any)[field] = { pr: true }
208
- } else {
209
- (newModel as any)[field] = { [operator]: parsedValue }
210
- }
174
+ function parseValue(value: string): string | number | boolean | null {
175
+ if (value === 'true') return true
176
+ if (value === 'false') return false
177
+ if (value === 'null') return null
178
+ if (!Number.isNaN(Number(value)) && value.trim() !== '') return Number(value)
179
+ return value
180
+ }
181
+
182
+ function updateConditionAtIndex(index: number, updates: Partial<{ field: string, op: ComparisonOperator, value: string, connector: LogicalOperator }>) {
183
+ const newModel = [...model.value]
184
+ const existing = newModel[index]
185
+ if (!existing) return
211
186
 
187
+ const updated = { ...existing }
188
+ if (updates.field !== undefined) updated.field = updates.field
189
+ if (updates.op !== undefined) updated.op = updates.op
190
+ if (updates.value !== undefined) updated.value = parseValue(updates.value)
191
+ if (updates.connector !== undefined) updated.connector = updates.connector
192
+
193
+ newModel[index] = updated
212
194
  model.value = newModel
213
195
  emit('change', newModel)
214
196
  }
215
197
 
216
198
  function addCondition() {
217
- const field = props.fields[0]?.value || 'new_field'
218
- updateCondition(field, 'eq', '')
199
+ const field = props.fields[0]?.value || 'field'
200
+ const newCondition = {
201
+ field,
202
+ op: 'eq' as ComparisonOperator,
203
+ value: '' as any,
204
+ connector: model.value.length > 0 ? 'and' as LogicalOperator : undefined,
205
+ }
206
+ const newModel = [...model.value, newCondition]
207
+ model.value = newModel
208
+ emit('change', newModel)
219
209
  }
220
210
 
221
- function removeCondition(field: string) {
222
- const newModel = { ...model.value }
223
- Reflect.deleteProperty(newModel, field)
211
+ function removeCondition(index: number) {
212
+ const newModel = [...model.value]
213
+ newModel.splice(index, 1)
214
+ // Clear connector on new first item
215
+ if (newModel.length > 0 && newModel[0].connector) {
216
+ newModel[0] = { ...newModel[0], connector: undefined }
217
+ }
218
+ // Clean up ID mapping
219
+ conditionIds.delete(index)
224
220
  model.value = newModel
225
221
  emit('change', newModel)
226
222
  }
227
223
 
228
224
  function clearAll() {
229
- model.value = {} as QueryObject<T>
230
- emit('change', {} as QueryObject<T>)
225
+ conditionIds.clear()
226
+ model.value = []
227
+ emit('change', [])
231
228
  }
232
229
 
233
230
  function getFieldType(fieldValue: string): string {
@@ -242,35 +239,28 @@ const activeFiltersCount = computed(() => {
242
239
  return conditions.value.filter(c => Boolean(c.field) && (c.operator === 'pr' || Boolean(c.value))).length
243
240
  })
244
241
 
245
- // Handle field change - need to rename the key in model
246
- function onFieldChange(oldField: string, newField: string, condition: FilterCondition) {
247
- const newModel = { ...model.value }
248
- Reflect.deleteProperty(newModel, oldField)
249
-
250
- let parsedValue: any = condition.value
251
- if (condition.value === 'true') parsedValue = true
252
- else if (condition.value === 'false') parsedValue = false
253
- else if (condition.value === 'null') parsedValue = null
254
- else if (!Number.isNaN(Number(condition.value)) && condition.value.trim() !== '') parsedValue = Number(condition.value)
255
-
256
- if (condition.operator === 'eq') {
257
- (newModel as any)[newField] = parsedValue
258
- } else if (condition.operator === 'pr') {
259
- (newModel as any)[newField] = { pr: true }
260
- } else {
261
- (newModel as any)[newField] = { [condition.operator]: parsedValue }
262
- }
242
+ function getConditionIndex(id: string): number {
243
+ return conditions.value.findIndex(c => c.id === id)
244
+ }
263
245
 
264
- model.value = newModel
265
- emit('change', newModel)
246
+ function onFieldChange(id: string, newField: string) {
247
+ const index = getConditionIndex(id)
248
+ if (index >= 0) updateConditionAtIndex(index, { field: newField })
249
+ }
250
+
251
+ function onOperatorChange(id: string, operator: ComparisonOperator) {
252
+ const index = getConditionIndex(id)
253
+ if (index >= 0) updateConditionAtIndex(index, { op: operator })
266
254
  }
267
255
 
268
- function onOperatorChange(field: string, operator: ComparisonOperator, value: string) {
269
- updateCondition(field, operator, value)
256
+ function onValueChange(id: string, value: string) {
257
+ const index = getConditionIndex(id)
258
+ if (index >= 0) updateConditionAtIndex(index, { value })
270
259
  }
271
260
 
272
- function onValueChange(field: string, operator: ComparisonOperator, value: string) {
273
- updateCondition(field, operator, value)
261
+ function onConnectorChange(id: string, connector: LogicalOperator) {
262
+ const index = getConditionIndex(id)
263
+ if (index >= 0) updateConditionAtIndex(index, { connector })
274
264
  }
275
265
  </script>
276
266
 
@@ -293,21 +283,31 @@ function onValueChange(field: string, operator: ComparisonOperator, value: strin
293
283
  <TransitionGroup name="condition">
294
284
  <div
295
285
  v-for="(condition, index) in conditions" :key="condition.id"
296
- class="grid filter-row gap-025 align-items-center p-025"
286
+ class="grid filter-row gap-025 align-items-center pt-025"
287
+ :class="{
288
+ 'mt-025': index > 0 && condition.connector === 'or',
289
+ 'pt-075 border-top-or': index > 0 && condition.connector === 'or',
290
+ }"
297
291
  >
298
- <!-- Connector (AND/OR) - display only for now -->
299
- <div v-if="index > 0" class="min-w-20px">
300
- <span v-if="condition.connector === 'or'" class="txt12 opacity-6">{{
301
- currentTexts.connectors.or }}</span>
302
- <span v-else class="txt12 opacity-6">{{ currentTexts.connectors.and }}</span>
292
+ <!-- Connector (AND/OR) -->
293
+ <div v-if="index > 0" class="min-w-60px">
294
+ <SelectInput
295
+ :model-value="condition.connector || 'and'"
296
+ :options="[
297
+ { label: currentTexts.connectors.and, value: 'and' },
298
+ { label: currentTexts.connectors.or, value: 'or' },
299
+ ]"
300
+ class="m-0 and-or-select txt-12"
301
+ @update:model-value="(v: LogicalOperator) => onConnectorChange(condition.id, v)"
302
+ />
303
303
  </div>
304
- <div v-else class="min-w-20px" />
304
+ <div v-else class="" />
305
305
 
306
306
  <!-- Field selector -->
307
307
  <SelectInput
308
308
  :model-value="condition.field" :options="fields"
309
309
  :placeholder="currentTexts.placeholders.selectField" class="m-0 light-input borderHover"
310
- @update:model-value="(v: string) => onFieldChange(condition.field, v, condition)"
310
+ @update:model-value="(v: string) => onFieldChange(condition.id, v)"
311
311
  />
312
312
 
313
313
  <!-- Operator selector -->
@@ -315,7 +315,7 @@ function onValueChange(field: string, operator: ComparisonOperator, value: strin
315
315
  :model-value="condition.operator"
316
316
  :options="getOperatorsForType(getFieldType(condition.field), !!getFieldOptions(condition.field))"
317
317
  class="m-0 light-input borderHover"
318
- @update:model-value="(v: ComparisonOperator) => onOperatorChange(condition.field, v, condition.value)"
318
+ @update:model-value="(v: ComparisonOperator) => onOperatorChange(condition.id, v)"
319
319
  />
320
320
 
321
321
  <!-- Value input - type-specific -->
@@ -325,31 +325,31 @@ function onValueChange(field: string, operator: ComparisonOperator, value: strin
325
325
  :options="getFieldOptions(condition.field)!"
326
326
  :placeholder="currentTexts.placeholders.selectOption"
327
327
  class="m-0 light-input borderHover" searchable
328
- @update:model-value="(v: string) => onValueChange(condition.field, condition.operator, v)"
328
+ @update:model-value="(v: string) => onValueChange(condition.id, v)"
329
329
  />
330
330
  <SelectInput
331
331
  v-else-if="getFieldType(condition.field) === 'boolean'"
332
332
  :model-value="condition.value" :options="booleanOptions"
333
333
  :placeholder="currentTexts.placeholders.selectOption"
334
334
  class="m-0 light-input borderHover"
335
- @update:model-value="(v: string) => onValueChange(condition.field, condition.operator, v)"
335
+ @update:model-value="(v: string) => onValueChange(condition.id, v)"
336
336
  />
337
337
  <DateInput
338
338
  v-else-if="getFieldType(condition.field) === 'date'"
339
339
  :model-value="condition.value" :placeholder="currentTexts.placeholders.selectDate"
340
340
  class="m-0 light-input borderHover"
341
- @update:model-value="(v: any) => onValueChange(condition.field, condition.operator, String(v))"
341
+ @update:model-value="(v: any) => onValueChange(condition.id, String(v))"
342
342
  />
343
343
  <TextInput
344
344
  v-else-if="getFieldType(condition.field) === 'number'"
345
345
  :model-value="condition.value" placeholder="0" type="number"
346
346
  class="m-0 light-input borderHover"
347
- @update:model-value="(v: string) => onValueChange(condition.field, condition.operator, v)"
347
+ @update:model-value="(v: string) => onValueChange(condition.id, v)"
348
348
  />
349
349
  <TextInput
350
350
  v-else :model-value="condition.value"
351
351
  :placeholder="currentTexts.placeholders.enterValue" class="m-0 light-input borderHover"
352
- @update:model-value="(v: string) => onValueChange(condition.field, condition.operator, v)"
352
+ @update:model-value="(v: string) => onValueChange(condition.id, v)"
353
353
  />
354
354
  </template>
355
355
  <div v-else />
@@ -357,7 +357,7 @@ function onValueChange(field: string, operator: ComparisonOperator, value: strin
357
357
  <!-- Remove button -->
358
358
  <Btn
359
359
  icon="close" thin flat size="small" class="m_bg-gray-40 m_px-3 m_mx-auto"
360
- @click="removeCondition(condition.field)"
360
+ @click="removeCondition(index)"
361
361
  />
362
362
  </div>
363
363
  </TransitionGroup>
@@ -375,8 +375,20 @@ function onValueChange(field: string, operator: ComparisonOperator, value: strin
375
375
  </template>
376
376
 
377
377
  <style scoped>
378
+ .and-or-select {
379
+ --input-font-size: 12px !important;
380
+ --input-background-color: transparent !important;
381
+ }
382
+ .and-or-select .selectinput-btn {
383
+ border: none;
384
+ width: 100%;
385
+ box-shadow: none;
386
+ padding: 0.25rem !important;
387
+ font-size: 12px !important;
388
+ }
389
+
378
390
  .filter-row {
379
- grid-template-columns: auto minmax(90px, 0.5fr) minmax(170px, 0.75fr) minmax(120px, 0.5fr) auto;
391
+ grid-template-columns: 50px minmax(90px, 0.5fr) minmax(170px, 0.75fr) minmax(120px, 0.5fr) auto;
380
392
  }
381
393
 
382
394
  /* Transition animations */
@@ -124,27 +124,17 @@ function fileName(pathKey: string) {
124
124
  >
125
125
  <slot name="files" :files="pathKeys" :fileQueue>
126
126
  <div v-if="multiple" class="bgl-multi-preview">
127
- <!-- Show uploaded files only if showFileList is true (default) -->
128
- <template v-if="showFileList !== false">
129
- <div
130
- v-for="path_key in pathKeys" :key="path_key"
131
- v-lightbox="{ src: pathKeyToURL(path_key), download: true }"
132
- class="multi-image-item-preview" :class="{ 'bgl_fill-image': fill }"
133
- >
134
- <Image v-if="isImage(path_key)" :pathKey="path_key" class="multi-preview" />
135
- <Icon v-else icon="description" class="multi-preview" />
136
- <p class="m-0">
137
- {{ fileName(path_key) }}
138
- </p>
139
- <Btn thin flat icon="delete" color="red" @click="removeFile(path_key)" />
140
- </div>
141
- </template>
142
- <!-- File count indicator when showFileList is false and multiple files -->
143
- <div v-if="showFileList === false && pathKeys.length > 0" class="flex column gap-05 pt-1">
144
- <p class="color-primary">
145
- {{ pathKeys.length }} file{{ pathKeys.length > 1 ? 's' : '' }} uploaded
127
+ <div
128
+ v-for="path_key in pathKeys" :key="path_key"
129
+ v-lightbox="{ src: pathKeyToURL(path_key), download: true }"
130
+ class="multi-image-item-preview" :class="{ 'bgl_fill-image': fill }"
131
+ >
132
+ <Image v-if="isImage(path_key)" :pathKey="path_key" class="multi-preview" />
133
+ <Icon v-else icon="description" class="multi-preview" />
134
+ <p class="m-0">
135
+ {{ fileName(path_key) }}
146
136
  </p>
147
- <Btn color="primary" thin icon="autorenew" value="Replace files" @click="browse()" />
137
+ <Btn thin flat icon="delete" color="red" @click="removeFile(path_key)" />
148
138
  </div>
149
139
  <div
150
140
  v-for="file in fileQueue" :key="file.name" class="multi-image-item-preview"
package/src/index.ts CHANGED
@@ -1,3 +1,5 @@
1
+ import './styles/bagel.css'
2
+
1
3
  export * from './components'
2
4
  export * from './components/form/useBagelFormState'
3
5
  export * from './composables'
@@ -14,7 +16,6 @@ export * from './types'
14
16
  export * from './utils'
15
17
  export * from './utils/allCountries'
16
18
  export * from './utils/BagelFormUtils'
17
- import './styles/bagel.css'
18
19
 
19
20
  export * from './utils/calendar/dateUtils'
20
21
  export * from './utils/constants'
@@ -1,18 +1,19 @@
1
1
  // Local type definitions for internal use only
2
- type ArrayAttrs = any
3
- interface Option { label: string, value: any }
4
2
  import type { Paths, Get, IterableElement, OmitIndexSignature } from 'type-fest'
5
3
  import type { ToString } from 'type-fest/source/internal'
6
4
  import type { LiteralStringUnion } from 'type-fest/source/literal-union'
7
5
  import type { PathsOptions, DefaultPathsOptions } from 'type-fest/source/paths'
8
6
  import type { VNode } from 'vue'
9
7
 
10
- export type AttributeValue =
11
- | string
12
- | number
13
- | boolean
14
- | undefined
15
- | { [key: string]: any }
8
+ type ArrayAttrs = any
9
+ interface Option { label: string, value: any }
10
+
11
+ export type AttributeValue
12
+ = | string
13
+ | number
14
+ | boolean
15
+ | undefined
16
+ | { [key: string]: any }
16
17
 
17
18
  export type AttributeFn<T, P extends Path<T>> = (
18
19
  field: SmartFieldVal<T, P>,
@@ -23,25 +24,25 @@ export interface Attributes<T, P extends Path<T>> {
23
24
  [key: string]: AttributeValue | AttributeFn<T, P>
24
25
  }
25
26
 
26
- export type BagelFieldOptions<T, P extends Path<T>> =
27
- | string
28
- | (
29
- | {
30
- label?: string
31
- value: string | number
32
- }
33
- | string
34
- | number
27
+ export type BagelFieldOptions<T, P extends Path<T>>
28
+ = | string
29
+ | (
30
+ | {
31
+ label?: string
32
+ value: string | number
33
+ }
34
+ | string
35
+ | number
36
+ | boolean
37
+ | { [key: string]: any }
38
+ )[]
39
+ | ((val?: SmartFieldVal<T, P>, rowData?: T) => Option[] | ((query: string) => Promise<Option[]>))
40
+ | ((query: string, val?: SmartFieldVal<T, P>, rowData?: T) => Promise<Option[]>)
41
+
42
+ export type VIfType<T, P extends Path<T>>
43
+ = | string
35
44
  | boolean
36
- | { [key: string]: any }
37
- )[]
38
- | ((val?: SmartFieldVal<T, P>, rowData?: T) => Option[] | ((query: string) => Promise<Option[]>))
39
- | ((query: string, val?: SmartFieldVal<T, P>, rowData?: T) => Promise<Option[]>)
40
-
41
- export type VIfType<T, P extends Path<T>> =
42
- | string
43
- | boolean
44
- | ((val?: SmartFieldVal<T, P>, rowData?: T) => boolean)
45
+ | ((val?: SmartFieldVal<T, P>, rowData?: T) => boolean)
45
46
 
46
47
  export type ValidationFn<T, P extends Path<T>> = (
47
48
  val?: SmartFieldVal<T, P>,
@@ -58,14 +59,14 @@ export type _Path<
58
59
  > = ToString<Paths<OmitIndexSignature<T>, PO>>
59
60
 
60
61
  // Utility type for open-ended object paths
61
- export type OpenEndedPath<T> =
62
- keyof T extends infer K ?
63
- K extends keyof T ?
64
- T[K] extends { [key: string]: any } ?
65
- `${K & string}.${string}`
66
- : never
67
- : never
68
- : never
62
+ export type OpenEndedPath<T>
63
+ = keyof T extends infer K
64
+ ? K extends keyof T
65
+ ? T[K] extends { [key: string]: any }
66
+ ? `${K & string}.${string}`
67
+ : never
68
+ : never
69
+ : never
69
70
 
70
71
  // Helper type to get paths for index signature properties
71
72
  type IndexSignaturePaths<T> = {
@@ -77,40 +78,40 @@ type IndexSignaturePaths<T> = {
77
78
  }[keyof T]
78
79
 
79
80
  // Enhanced Path type that allows flexibility for nested open-ended objects
80
- export type Path<T, PO extends PathsOptions = DefaultPathsOptions> =
81
- FieldVal<T, _Path<T, PO>> extends Array<any>
82
- ? LiteralStringUnion<_Path<T, PO>>
83
- : _Path<T, PO> | IndexSignaturePaths<T> | `${keyof T & string}.more_info.${string}`
81
+ export type Path<T, PO extends PathsOptions = DefaultPathsOptions>
82
+ = FieldVal<T, _Path<T, PO>> extends Array<any>
83
+ ? LiteralStringUnion<_Path<T, PO>>
84
+ : _Path<T, PO> | IndexSignaturePaths<T> | `${keyof T & string}.more_info.${string}`
84
85
 
85
86
  // Smart field value type that preserves type information when possible
86
- export type SmartFieldVal<T, P extends Path<T>> =
87
- P extends string
87
+ export type SmartFieldVal<T, P extends Path<T>>
88
+ = P extends string
88
89
  ? P extends keyof T
89
90
  ? T[P]
90
91
  : any
91
92
  : FieldVal<T, P>
92
93
 
93
94
  // Smart bagel field options that preserve type information
94
- export type SmartBagelFieldOptions<T, P extends Path<T>> =
95
- | string
96
- | (
97
- | {
98
- label?: string
99
- value: string | number
100
- }
101
- | string
102
- | number
103
- | boolean
104
- | { [key: string]: any }
105
- )[]
106
- | ((val?: SmartFieldVal<T, P>, rowData?: T) => Option[] | ((query: string) => Promise<Option[]>))
107
- | ((query: string, val?: SmartFieldVal<T, P>, rowData?: T) => Promise<Option[]>)
95
+ export type SmartBagelFieldOptions<T, P extends Path<T>>
96
+ = | string
97
+ | (
98
+ | {
99
+ label?: string
100
+ value: string | number
101
+ }
102
+ | string
103
+ | number
104
+ | boolean
105
+ | { [key: string]: any }
106
+ )[]
107
+ | ((val?: SmartFieldVal<T, P>, rowData?: T) => Option[] | ((query: string) => Promise<Option[]>))
108
+ | ((query: string, val?: SmartFieldVal<T, P>, rowData?: T) => Promise<Option[]>)
108
109
 
109
110
  // Smart VIf type that preserves type information
110
- export type SmartVIfType<T, P extends Path<T>> =
111
- | string
112
- | boolean
113
- | ((val?: SmartFieldVal<T, P>, rowData?: T) => boolean)
111
+ export type SmartVIfType<T, P extends Path<T>>
112
+ = | string
113
+ | boolean
114
+ | ((val?: SmartFieldVal<T, P>, rowData?: T) => boolean)
114
115
 
115
116
  // Smart validation function that preserves type information
116
117
  export type SmartValidationFn<T, P extends Path<T>> = (
@@ -138,8 +139,8 @@ export type SmartUpdateFn<T, P extends Path<T>> = (
138
139
 
139
140
  /** The value type at path P in object T. */
140
141
  // Fall back to unknown if type resolution fails
141
- export type FieldVal<T, P extends Path<T>> =
142
- unknown extends Get<T, P> ? unknown : Get<T, P>
142
+ export type FieldVal<T, P extends Path<T>>
143
+ = unknown extends Get<T, P> ? unknown : Get<T, P>
143
144
 
144
145
  /** If path P in T is an array, this gives the array's element type. */
145
146
  export type ArrayFieldVal<T, P extends Path<T>> = IterableElement<Get<T, P>>
@@ -297,5 +298,4 @@ export interface UploadInputProps {
297
298
  dropPlaceholder?: string
298
299
  noFilePlaceholder?: string
299
300
  btnPlaceholder?: string
300
- showFileList?: boolean
301
301
  }