@bagelink/vue 1.4.111 → 1.4.115

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 (44) hide show
  1. package/bin/generateFormSchema.ts +12 -12
  2. package/dist/components/Card.vue.d.ts.map +1 -1
  3. package/dist/components/ImportData.vue.d.ts.map +1 -1
  4. package/dist/components/analytics/PieChart.vue.d.ts.map +1 -1
  5. package/dist/components/calendar/Index.vue.d.ts.map +1 -1
  6. package/dist/components/calendar/index.d.ts +2 -0
  7. package/dist/components/calendar/index.d.ts.map +1 -0
  8. package/dist/components/calendar/views/MonthView.vue.d.ts.map +1 -1
  9. package/dist/components/calendar/views/WeekView.vue.d.ts.map +1 -1
  10. package/dist/components/dataTable/DataTable.vue.d.ts.map +1 -1
  11. package/dist/components/form/BagelForm.vue.d.ts.map +1 -1
  12. package/dist/components/form/inputs/DatePicker.vue.d.ts +1 -0
  13. package/dist/components/form/inputs/DatePicker.vue.d.ts.map +1 -1
  14. package/dist/components/form/inputs/RichText/utils/media.d.ts.map +1 -1
  15. package/dist/components/layout/AppContent.vue.d.ts.map +1 -1
  16. package/dist/composables/useSchemaField.d.ts +2 -2
  17. package/dist/composables/useSchemaField.d.ts.map +1 -1
  18. package/dist/index.cjs +5 -5
  19. package/dist/index.mjs +5 -5
  20. package/dist/style.css +1 -1
  21. package/dist/types/BagelForm.d.ts +24 -12
  22. package/dist/types/BagelForm.d.ts.map +1 -1
  23. package/dist/utils/BagelFormUtils.d.ts +11 -7
  24. package/dist/utils/BagelFormUtils.d.ts.map +1 -1
  25. package/dist/utils/elementUtils.d.ts.map +1 -1
  26. package/package.json +1 -1
  27. package/src/components/Card.vue +1 -2
  28. package/src/components/DataPreview.vue +1 -1
  29. package/src/components/ImportData.vue +94 -88
  30. package/src/components/analytics/PieChart.vue +21 -34
  31. package/src/components/calendar/Index.vue +15 -35
  32. package/src/components/calendar/views/MonthView.vue +84 -88
  33. package/src/components/calendar/views/WeekView.vue +143 -89
  34. package/src/components/dataTable/DataTable.vue +2 -3
  35. package/src/components/form/BagelForm.vue +3 -6
  36. package/src/components/form/inputs/DateInput.vue +2 -2
  37. package/src/components/form/inputs/DatePicker.vue +40 -47
  38. package/src/components/form/inputs/RichText/utils/media.ts +1 -2
  39. package/src/components/layout/AppContent.vue +21 -1
  40. package/src/composables/useSchemaField.ts +7 -7
  41. package/src/types/BagelForm.ts +67 -13
  42. package/src/utils/BagelFormUtils.ts +49 -50
  43. package/src/utils/elementUtils.ts +1 -4
  44. /package/src/components/{dialog → calendar}/index.ts +0 -0
@@ -114,12 +114,9 @@ async function handleSubmit() {
114
114
  }
115
115
 
116
116
  // Field renderingks
117
- const { renderField } = useSchemaField<T, P>({
117
+ const { renderField } = useSchemaField<T>({
118
118
  mode: 'form',
119
- getFormData: () => ({
120
- ...formData.value,
121
- get: (path: string) => getNestedValue(formData.value, path, '')
122
- }),
119
+ getFormData: () => formData.value,
123
120
  onUpdateModelValue: (field, value) => {
124
121
  if (!field.id) return
125
122
 
@@ -128,7 +125,7 @@ const { renderField } = useSchemaField<T, P>({
128
125
  }
129
126
  })
130
127
 
131
- const renderSchemaField = (field: any) => renderField(field as BaseBagelField<T, P>)
128
+ const renderSchemaField = (field: any) => renderField(field as BaseBagelField<T, Path<T>>)
132
129
 
133
130
  // Add new method to handle slot input changes
134
131
  function handleSlotInputChange(event: Event) {
@@ -1,6 +1,6 @@
1
1
  <script setup lang="ts">
2
2
  import type { ModeType } from '../../../utils/calendar/typings'
3
- import { TextInput, Dropdown, fmtDate } from '@bagelink/vue'
3
+ import { TextInput, Dropdown, formatDate } from '@bagelink/vue'
4
4
  import { onClickOutside } from '@vueuse/core'
5
5
  import { ref, onMounted } from 'vue'
6
6
  import { WEEK_START_DAY } from '../../../utils/calendar/time'
@@ -47,7 +47,7 @@ const isOpen = ref(false)
47
47
  function useFormatting() {
48
48
  const formatDisplayDate = (date: Date | string | undefined): string => {
49
49
  if (!date) return ''
50
- return fmtDate(date, { fmt: props.enableTime ? 'DD.MM.YY HH:mm' : 'DD.MM.YY' })
50
+ return formatDate(date, { fmt: props.enableTime ? 'DD.MM.YY HH:mm' : 'DD.MM.YY' })
51
51
  }
52
52
 
53
53
  const parseUserInput = (input: string): Date | null => {
@@ -15,6 +15,7 @@ const props = withDefaults(
15
15
  locale?: string
16
16
  enableTime?: boolean
17
17
  highlightedDates?: MaybeRefOrGetter<(string | Date)[]>
18
+ disabledDates?: MaybeRefOrGetter<(string | Date)[]>
18
19
  autoSize?: boolean
19
20
  }>(),
20
21
  {
@@ -28,6 +29,7 @@ const props = withDefaults(
28
29
  const emit = defineEmits(['update:modelValue'])
29
30
 
30
31
  const computedHighlightedDates = $computed(() => toValue(props.highlightedDates))
32
+ const computedDisabledDates = $computed(() => toValue(props.disabledDates))
31
33
 
32
34
  // State
33
35
  const currentMonth = ref(new Date())
@@ -50,8 +52,24 @@ function useDateValidation() {
50
52
  const minDate = parseDate(props.min)
51
53
  const maxDate = parseDate(props.max)
52
54
 
55
+ // Check if date is in min/max range
53
56
  if (minDate && date < minDate) return true
54
57
  if (maxDate && date > maxDate) return true
58
+
59
+ // Check if date is in the disabled dates array
60
+ if (Array.isArray(computedDisabledDates) && computedDisabledDates.length > 0) {
61
+ const isInDisabledDates = computedDisabledDates.some((disabledDate) => {
62
+ const parsedDisabledDate = parseDate(disabledDate)
63
+ if (!parsedDisabledDate) return false
64
+
65
+ // Compare year, month, and day
66
+ return date.getFullYear() === parsedDisabledDate.getFullYear()
67
+ && date.getMonth() === parsedDisabledDate.getMonth()
68
+ && date.getDate() === parsedDisabledDate.getDate()
69
+ })
70
+ if (isInDisabledDates) return true
71
+ }
72
+
55
73
  return false
56
74
  }
57
75
 
@@ -310,7 +328,7 @@ function selectDate(date: Date | null) {
310
328
  </script>
311
329
 
312
330
  <template>
313
- <div class="ltr gap-075 m_flex-wrap calendar-container justify-content-center h-100p" :class="{ 'flex': !autoSize }">
331
+ <div class="ltr gap-075 m_flex-wrap calendar-container justify-content-center h-100p" :class="{ flex: !autoSize }">
314
332
  <div class="calendar-section m_border-none px-05 m_p-0">
315
333
  <div class="flex space-between pb-1">
316
334
  <template v-if="currentView === 'days'">
@@ -333,18 +351,12 @@ function selectDate(date: Date | null) {
333
351
  </div>
334
352
 
335
353
  <div v-if="currentView === 'days'" class="calendar-grid grid gap-025">
336
- <div
337
- v-for="day in weekDays"
338
- :key="day"
339
- class="txt-center txt-12 opacity-6"
340
- >
354
+ <div v-for="day in weekDays" :key="day" class="txt-center txt-12 opacity-6">
341
355
  {{ day }}
342
356
  </div>
343
357
 
344
358
  <button
345
- v-for="date in currentMonthDays"
346
- :key="date?.toISOString()"
347
- type="button"
359
+ v-for="date in currentMonthDays" :key="date?.toISOString()" type="button"
348
360
  class="day aspect-ratio-1 flex align-items-center justify-content-center pointer round txt14 p-0"
349
361
  :class="{
350
362
  'selected': isSelected(date),
@@ -352,9 +364,7 @@ function selectDate(date: Date | null) {
352
364
  'disabled': isDateDisabled(date),
353
365
  'not-in-month': isNotInMonth(date),
354
366
  'highlighted': isHighlighted(date),
355
- }"
356
- :disabled="isDateDisabled(date)"
357
- @click="selectDate(date)"
367
+ }" :disabled="isDateDisabled(date)" @click="selectDate(date)"
358
368
  >
359
369
  {{ date?.getDate() }}
360
370
  </button>
@@ -362,52 +372,34 @@ function selectDate(date: Date | null) {
362
372
 
363
373
  <div v-else-if="currentView === 'months'" class="month-grid grid gap-05 p-05">
364
374
  <Btn
365
- v-for="month in months"
366
- :key="month.value"
367
- thin
368
- :flat="month.value !== currentMonthValue.month"
369
- :disabled="month.disabled"
370
- :value="month.name"
371
- @click="selectMonth(month.value)"
375
+ v-for="month in months" :key="month.value" thin :flat="month.value !== currentMonthValue.month"
376
+ :disabled="month.disabled" :value="month.name" @click="selectMonth(month.value)"
372
377
  />
373
378
  </div>
374
379
 
375
380
  <div v-else class="year-grid grid gap-05 p-0">
376
381
  <Btn
377
- v-for="year in years"
378
- :key="year.value" thin
379
- :flat="year.value !== currentMonthValue.year"
380
- :disabled="year.disabled"
381
- :value="year.value.toString()"
382
- @click="selectYear(year.value)"
382
+ v-for="year in years" :key="year.value" thin :flat="year.value !== currentMonthValue.year"
383
+ :disabled="year.disabled" :value="year.value.toString()" @click="selectYear(year.value)"
383
384
  />
384
385
  </div>
385
386
  </div>
386
387
 
387
- <div v-if="enableTime && currentView === 'days'" class="time-picker border-start flex column gap-1 w-120px px-025">
388
+ <div
389
+ v-if="enableTime && currentView === 'days'"
390
+ class="time-picker border-start flex column gap-1 w-120px px-025"
391
+ >
388
392
  <div class="flex gap-025">
389
393
  <NumberInput
390
- center
391
- :modelValue="hours"
392
- :disabled="!selectedDate"
393
- :min="0"
394
- :max="23"
395
- layout="vertical"
396
- :padZero="2"
397
- @update:modelValue="handleHourInput"
394
+ center :modelValue="hours" :disabled="!selectedDate" :min="0" :max="23" layout="vertical"
395
+ :padZero="2" @update:modelValue="handleHourInput"
398
396
  />
399
397
  <p class="pb-075">
400
398
  :
401
399
  </p>
402
400
  <NumberInput
403
- center
404
- :modelValue="minutes"
405
- :disabled="!selectedDate"
406
- :min="0"
407
- :max="59"
408
- :padZero="2"
409
- layout="vertical"
410
- @update:modelValue="handleMinuteInput"
401
+ center :modelValue="minutes" :disabled="!selectedDate" :min="0" :max="59" :padZero="2"
402
+ layout="vertical" @update:modelValue="handleMinuteInput"
411
403
  />
412
404
  </div>
413
405
  </div>
@@ -478,6 +470,7 @@ function selectDate(date: Date | null) {
478
470
  color: var(--bgl-text-color);
479
471
  outline: 1px solid var(--border-color);
480
472
  }
473
+
481
474
  .day:hover:not(.disabled).selected {
482
475
  filter: var(--bgl-hover-filter);
483
476
  background-color: var(--bgl-primary);
@@ -504,16 +497,16 @@ function selectDate(date: Date | null) {
504
497
  }
505
498
 
506
499
  .day.highlighted:not(.selected) {
507
- background-color: var(--bgl-secondary-light, rgba(var(--bgl-primary-rgb, 0, 123, 255), 0.15));
508
- font-weight: 500;
500
+ background-color: var(--bgl-secondary-light, rgba(var(--bgl-primary-rgb, 0, 123, 255), 0.15));
501
+ font-weight: 500;
509
502
  }
510
503
 
511
504
  .day.highlighted.selected {
512
- /* Add a subtle ring effect for dates that are both selected and highlighted */
513
- box-shadow: 0 0 0 2px var(--bgl-secondary, rgba(var(--bgl-primary-rgb, 0, 123, 255), 0.5));
505
+ /* Add a subtle ring effect for dates that are both selected and highlighted */
506
+ box-shadow: 0 0 0 2px var(--bgl-secondary, rgba(var(--bgl-primary-rgb, 0, 123, 255), 0.5));
514
507
  }
515
508
 
516
509
  .day.highlighted:not(.selected):hover {
517
- background-color: var(--bgl-secondary-light-hover, rgba(var(--bgl-primary-rgb, 0, 123, 255), 0.25));
510
+ background-color: var(--bgl-secondary-light-hover, rgba(var(--bgl-primary-rgb, 0, 123, 255), 0.25));
518
511
  }
519
512
  </style>
@@ -1,4 +1,3 @@
1
- import type { BaseBagelField } from '@bagelink/vue'
2
1
  import type { ModalApi } from '../../../../../plugins/useModal'
3
2
 
4
3
  import type { EditorState } from '../richTextTypes'
@@ -90,7 +89,7 @@ export function insertEmbed(modal: ModalApi, state: EditorState) {
90
89
  bglFrmUtil.numField('width', 'Width', { min: 200, placeholder: '560' }),
91
90
  bglFrmUtil.numField('height', 'Height', { min: 200, placeholder: '315' })
92
91
  ),
93
- { id: 'allowFullscreen', $el: 'check', label: 'Allow Fullscreen', value: true } as BaseBagelField<InsertImbedModalData, 'allowFullscreen'>,
92
+ { id: 'allowFullscreen', $el: 'check', label: 'Allow Fullscreen', attrs: { value: true } },
94
93
  ],
95
94
  onSubmit: (data: { url: string, width?: number, height?: number, allowFullscreen?: boolean }) => {
96
95
  if (!data.url) return
@@ -66,7 +66,7 @@ const sidebarCardStyle = inject('sidebarCardStyle', { value: true })
66
66
  </header>
67
67
 
68
68
  <!-- Page Content -->
69
- <main class="flex-grow overflow py-1 w-100p m_p-05 m_scrollbar-gutter-stable-both m_vw100" :class="{
69
+ <main class="pageContent flex-grow overflow py-1 w-100p m_p-05 m_scrollbar-gutter-stable-both m_vw100" :class="{
70
70
  'px-1': !sidebarCardStyle?.value,
71
71
  }">
72
72
  <slot name="content">
@@ -77,6 +77,26 @@ const sidebarCardStyle = inject('sidebarCardStyle', { value: true })
77
77
  </div>
78
78
  </template>
79
79
 
80
+ <style>
81
+ .slide-fade-enter-from:has(.app-header),
82
+ .slide-fade-leave-to:has(.app-header) {
83
+ transform: translateX(0) !important;
84
+ opacity: 1 !important;
85
+ }
86
+
87
+ .slide-fade-enter-from:has(.app-header) .pageContent,
88
+ .slide-fade-leave-to:has(.app-header) .pageContent {
89
+ transform: translateX(-20px) !important;
90
+ opacity: 0 !important;
91
+ }
92
+
93
+ .slide-fade-enter-active:has(.app-header) .pageContent,
94
+ .slide-fade-leave-active:has(.app-header) .pageContent {
95
+ transition: all 0.15s ease-in;
96
+ overflow: hidden;
97
+ }
98
+ </style>
99
+
80
100
  <style scoped>
81
101
  .paddingAppContent {
82
102
  padding-inline-start: 0.5rem;
@@ -34,7 +34,7 @@ export interface UseSchemaFieldOptions<T, SFP extends Path<T>> {
34
34
  includeUnset?: boolean
35
35
  }
36
36
 
37
- export function useSchemaField<T extends { [key: string]: any }, SP extends Path<T>>(optns: UseSchemaFieldOptions<T, SP>) {
37
+ export function useSchemaField<T extends { [key: string]: any }>(optns: UseSchemaFieldOptions<T, Path<T>>) {
38
38
  const { mode = 'form', getFormData, onUpdateModelValue, includeUnset = false } = optns
39
39
 
40
40
  // Helper function to render objects recursively
@@ -96,18 +96,18 @@ export function useSchemaField<T extends { [key: string]: any }, SP extends Path
96
96
  return typeof field.$el === 'object' ? field.$el : componentMap[field.$el as keyof typeof componentMap] ?? field.$el ?? 'div'
97
97
  }
98
98
 
99
- function renderChild(child: SchemaChild<T, SP>, slots?: BaseBagelField<T, SP>['slots']) {
99
+ function renderChild(child: SchemaChild<T, Path<T>>, slots?: BaseBagelField<T, Path<T>>['slots']) {
100
100
  if (typeof child === 'string') return child
101
101
  if (isVNode(child)) return child
102
102
  return renderField(
103
- child as BaseBagelField<T, SP>,
103
+ child as BaseBagelField<T, Path<T>>,
104
104
  slots
105
105
  )
106
106
  }
107
107
 
108
108
  function renderField(
109
- field: BaseBagelField<T, SP>,
110
- slots?: BaseBagelField<T, SP>['slots']
109
+ field: BaseBagelField<T, Path<T>>,
110
+ slots?: BaseBagelField<T, Path<T>>['slots']
111
111
  ): VNode | undefined {
112
112
  const Component = getComponent(field as Field<T>)
113
113
  if (!Component) return
@@ -320,7 +320,7 @@ export function useSchemaField<T extends { [key: string]: any }, SP extends Path
320
320
  return schemaField
321
321
  }
322
322
 
323
- return renderField(schemaField as BaseBagelField<T, SP>, slots)
323
+ return renderField(schemaField as BaseBagelField<T, Path<T>>, slots)
324
324
  })
325
325
  }
326
326
  }
@@ -329,7 +329,7 @@ export function useSchemaField<T extends { [key: string]: any }, SP extends Path
329
329
 
330
330
  // Handle custom slot content from parent
331
331
 
332
- const slotContent = field.id ? (slots?.[field.id] as VNodeFn<T, SP> | undefined)?.({ row: rowData, field }) : undefined
332
+ const slotContent = field.id ? (slots?.[field.id] as VNodeFn<T, Path<T>> | undefined)?.({ row: rowData, field }) : undefined
333
333
  // field.id && slots?.[field.id] && typeof slots[field.id] === 'function' && !Array.isArray(slots?.[field.id])
334
334
  // ? (slots[field.id])({ row: rowData, field })
335
335
  // : undefined
@@ -14,7 +14,7 @@ export type AttributeValue =
14
14
  | { [key: string]: any }
15
15
 
16
16
  export type AttributeFn<T, P extends Path<T>> = (
17
- field: FieldVal<T, P>,
17
+ field: SmartFieldVal<T, P>,
18
18
  row?: T
19
19
  ) => AttributeValue
20
20
 
@@ -34,16 +34,16 @@ export type BagelFieldOptions<T, P extends Path<T>> =
34
34
  | boolean
35
35
  | { [key: string]: any }
36
36
  )[]
37
- | ((val?: FieldVal<T, P>, rowData?: T) => Option[] | ((query: string) => Promise<Option[]>))
38
- | ((query: string, val?: FieldVal<T, P>, rowData?: T) => Promise<Option[]>)
37
+ | ((val?: SmartFieldVal<T, P>, rowData?: T) => Option[] | ((query: string) => Promise<Option[]>))
38
+ | ((query: string, val?: SmartFieldVal<T, P>, rowData?: T) => Promise<Option[]>)
39
39
 
40
40
  export type VIfType<T, P extends Path<T>> =
41
41
  | string
42
42
  | boolean
43
- | ((val?: FieldVal<T, P>, rowData?: T) => boolean)
43
+ | ((val?: SmartFieldVal<T, P>, rowData?: T) => boolean)
44
44
 
45
45
  export type ValidationFn<T, P extends Path<T>> = (
46
- val?: FieldVal<T, P>,
46
+ val?: SmartFieldVal<T, P>,
47
47
  rowData?: T
48
48
  ) => string | undefined
49
49
 
@@ -59,7 +59,61 @@ export type _Path<
59
59
  export type Path<T, PO extends PathsOptions = DefaultPathsOptions> =
60
60
  FieldVal<T, _Path<T, PO>> extends Array<any>
61
61
  ? LiteralStringUnion<_Path<T, PO>>
62
- : _Path<T, PO>
62
+ : _Path<T, PO> | string
63
+
64
+ // Smart field value type that preserves type information when possible
65
+ export type SmartFieldVal<T, P extends Path<T>> =
66
+ P extends string
67
+ ? P extends keyof T
68
+ ? T[P]
69
+ : any
70
+ : FieldVal<T, P>
71
+
72
+ // Smart bagel field options that preserve type information
73
+ export type SmartBagelFieldOptions<T, P extends Path<T>> =
74
+ | string
75
+ | (
76
+ | {
77
+ label?: string
78
+ value: string | number
79
+ }
80
+ | string
81
+ | number
82
+ | boolean
83
+ | { [key: string]: any }
84
+ )[]
85
+ | ((val?: SmartFieldVal<T, P>, rowData?: T) => Option[] | ((query: string) => Promise<Option[]>))
86
+ | ((query: string, val?: SmartFieldVal<T, P>, rowData?: T) => Promise<Option[]>)
87
+
88
+ // Smart VIf type that preserves type information
89
+ export type SmartVIfType<T, P extends Path<T>> =
90
+ | string
91
+ | boolean
92
+ | ((val?: SmartFieldVal<T, P>, rowData?: T) => boolean)
93
+
94
+ // Smart validation function that preserves type information
95
+ export type SmartValidationFn<T, P extends Path<T>> = (
96
+ val?: SmartFieldVal<T, P>,
97
+ rowData?: T
98
+ ) => string | undefined
99
+
100
+ // Smart attribute function that preserves type information
101
+ export type SmartAttributeFn<T, P extends Path<T>> = (
102
+ field: SmartFieldVal<T, P>,
103
+ row?: T
104
+ ) => AttributeValue
105
+
106
+ // Smart transform function that preserves type information
107
+ export type SmartTransformFn<T, P extends Path<T>> = (
108
+ val?: SmartFieldVal<T, P>,
109
+ rowData?: T
110
+ ) => any
111
+
112
+ // Smart update function that preserves type information
113
+ export type SmartUpdateFn<T, P extends Path<T>> = (
114
+ val?: SmartFieldVal<T, P>,
115
+ rowData?: T
116
+ ) => unknown
63
117
 
64
118
  /** The value type at path P in object T. */
65
119
  // Fall back to unknown if type resolution fails
@@ -104,20 +158,20 @@ export interface BaseBagelField<
104
158
  'id'?: P
105
159
  'label'?: string
106
160
  'placeholder'?: string
107
- 'class'?: AttributeValue | AttributeFn<T, P>
161
+ 'class'?: AttributeValue | SmartAttributeFn<T, P>
108
162
  'attrs'?: Attributes<T, P>
109
163
  'required'?: boolean
110
164
  'disabled'?: boolean
111
165
  'helptext'?: string
112
- 'options'?: BagelFieldOptions<T, P>
166
+ 'options'?: SmartBagelFieldOptions<T, P>
113
167
  'children'?: SchemaChild<T, Path<T, PO>, PO>[]
114
168
  'slots'?: { [key: string]: SchemaChild<T, Path<T, PO>, PO>[] }
115
169
  'defaultValue'?: any
116
- 'vIf'?: VIfType<T, P>
117
- 'v-if'?: VIfType<T, P>
118
- 'transform'?: (val?: FieldVal<T, P>, rowData?: T) => any
119
- 'onUpdate'?: (val?: FieldVal<T, P>, rowData?: T) => unknown
120
- 'validate'?: ValidationFn<T, P>
170
+ 'vIf'?: SmartVIfType<T, P>
171
+ 'v-if'?: SmartVIfType<T, P>
172
+ 'transform'?: SmartTransformFn<T, P>
173
+ 'onUpdate'?: SmartUpdateFn<T, P>
174
+ 'validate'?: SmartValidationFn<T, P>
121
175
  }
122
176
 
123
177
  export type _MappedBaseBagelField<
@@ -1,4 +1,4 @@
1
- import type { ArrayBagelField, ArrayFieldVal, Attributes, BaseBagelField, BglFormSchemaT, FieldByP, IconType, InputBagelField, Option, Path, SchemaChild, SelectBagelField, ShallowBglFormSchemaT, UploadInputProps } from '@bagelink/vue'
1
+ import type { ArrayBagelField, ArrayFieldVal, Attributes, BaseBagelField, BglFormSchemaT, FieldByP, IconType, InputBagelField, Path, SchemaChild, SelectBagelField, ShallowBglFormSchemaT, UploadInputProps } from '@bagelink/vue'
2
2
  import type { DefaultPathsOptions, PathsOptions } from 'type-fest/source/paths'
3
3
  import type { InputTypeHTMLAttribute, MaybeRefOrGetter } from 'vue'
4
4
 
@@ -85,70 +85,64 @@ export function richText<
85
85
 
86
86
  export function txtField<
87
87
  T,
88
- P extends Path<T, PO>,
89
88
  PO extends PathsOptions = DefaultPathsOptions,
90
89
  >(
91
- id?: P,
90
+ id?: Path<T, PO>,
92
91
  label?: string,
93
- options?: TextInputOptions<T, P>,
94
- ): InputBagelField<T, P, PO> {
92
+ options?: TextInputOptions<T, Path<T, PO>>,
93
+ ): InputBagelField<T, Path<T, PO>, PO> {
95
94
  return {
96
95
  $el: 'text',
97
96
  id,
98
97
  label,
99
98
  class: options?.class,
100
99
  required: options?.required,
101
- vIf: options?.vIf,
102
- disabled: options?.disabled,
103
100
  placeholder: options?.placeholder,
104
- defaultValue: options?.defaultValue,
105
- validate: options?.validate,
106
- onUpdate: options?.onUpdate,
107
101
  helptext: options?.helptext,
102
+ disabled: options?.disabled,
103
+ defaultValue: options?.defaultValue,
104
+ vIf: options?.vIf,
108
105
  transform: options?.transform,
109
106
  attrs: {
110
- type: options?.type,
107
+ autocomplete: options?.autocomplete,
111
108
  pattern: options?.pattern,
112
109
  multiline: options?.multiline,
113
- autocomplete: options?.autocomplete,
114
- rows: options?.rows,
115
- code: options?.code,
116
110
  autoheight: options?.autoheight,
111
+ code: options?.code,
112
+ rows: options?.rows,
117
113
  icon: options?.icon,
118
114
  iconStart: options?.iconStart,
115
+ type: options?.type,
119
116
  },
120
117
  }
121
118
  }
122
119
 
123
120
  export function selectField<
124
121
  T,
125
- P extends Path<T, PO>,
126
122
  PO extends PathsOptions = DefaultPathsOptions,
127
123
  >(
128
- id?: P,
124
+ id?: Path<T, PO>,
129
125
  label?: string,
130
- options?: Option[] | ((query: string) => Promise<Option[]>) | ((val?: any, row?: T) => Option[] | ((query: string) => Promise<Option[]>)) | ((query: string, val?: any, row?: T) => Promise<Option[]>),
131
- config?: SlctInputOptions<T, P>,
132
- ): SelectBagelField<T, P, PO> {
126
+ options?: any[],
127
+ fieldOptions?: SlctInputOptions<T, Path<T, PO>>,
128
+ ): SelectBagelField<T, Path<T, PO>, PO> {
133
129
  return {
134
130
  $el: 'select',
135
131
  id,
136
- options,
137
- class: config?.class,
138
- placeholder: config?.placeholder,
139
- required: config?.required,
140
132
  label,
141
- defaultValue: config?.defaultValue,
142
- vIf: config?.vIf,
143
- validate: config?.validate,
144
- onUpdate: config?.onUpdate,
145
- transform: config?.transform,
133
+ class: fieldOptions?.class,
134
+ required: fieldOptions?.required,
135
+ helptext: fieldOptions?.helptext,
136
+ disabled: fieldOptions?.disabled,
137
+ defaultValue: fieldOptions?.defaultValue,
138
+ vIf: fieldOptions?.vIf,
139
+ transform: fieldOptions?.transform,
140
+ options,
146
141
  attrs: {
147
- disabled: config?.disabled,
148
- searchable: config?.searchable,
149
- multiselect: config?.multiselect,
150
- clearable: config?.clearable,
151
- autocomplete: config?.autocomplete,
142
+ ...fieldOptions?.attrs,
143
+ searchable: fieldOptions?.searchable,
144
+ multiselect: fieldOptions?.multiselect,
145
+ clearable: fieldOptions?.clearable,
152
146
  },
153
147
  }
154
148
  }
@@ -162,22 +156,25 @@ interface CheckInputOptions<T, K extends Path<T>> extends Omit<InputOptions<T, K
162
156
 
163
157
  export function checkField<
164
158
  T,
165
- P extends Path<T, PO>,
166
159
  PO extends PathsOptions = DefaultPathsOptions,
167
160
  >(
168
- id?: P,
161
+ id?: Path<T, PO>,
169
162
  label?: string,
170
- options?: CheckInputOptions<T, P>,
171
- ): BaseBagelField<T, P, PO> {
163
+ options?: CheckInputOptions<T, Path<T, PO>>,
164
+ ): BaseBagelField<T, Path<T, PO>, PO> {
172
165
  return {
173
166
  $el: 'check',
167
+ id,
168
+ label,
174
169
  class: options?.class,
175
170
  required: options?.required,
171
+ helptext: options?.helptext,
172
+ disabled: options?.disabled,
176
173
  defaultValue: options?.defaultValue,
177
- id,
178
- label,
174
+ vIf: options?.vIf,
179
175
  transform: options?.transform,
180
176
  attrs: {
177
+ ...options?.attrs,
181
178
  value: options?.value,
182
179
  },
183
180
  }
@@ -247,13 +244,12 @@ export function dateField<
247
244
 
248
245
  export function numField<
249
246
  T,
250
- P extends Path<T, PO>,
251
247
  PO extends PathsOptions = DefaultPathsOptions,
252
248
  >(
253
- id?: P,
249
+ id?: Path<T, PO>,
254
250
  label?: string,
255
- options?: NumFieldOptions<T, P>,
256
- ): BaseBagelField<T, P, PO> {
251
+ options?: NumFieldOptions<T, Path<T, PO>>,
252
+ ): BaseBagelField<T, Path<T, PO>, PO> {
257
253
  return {
258
254
  $el: 'number',
259
255
  class: options?.class,
@@ -281,11 +277,10 @@ export function numField<
281
277
 
282
278
  export function frmRow<
283
279
  T,
284
- P extends Path<T, PO>,
285
280
  PO extends PathsOptions = DefaultPathsOptions,
286
281
  >(
287
- ...children: SchemaChild<T, P, PO>[]
288
- ): FieldByP<T, P, PO> {
282
+ ...children: SchemaChild<T, Path<T, PO>, PO>[]
283
+ ): { $el: string, class: string, children: SchemaChild<T, Path<T, PO>, PO>[] } {
289
284
  return {
290
285
  $el: 'div',
291
286
  class: 'flex gap-1 m_block align-items-end',
@@ -297,17 +292,21 @@ export interface UploadOptions<T, K extends Path<T>> extends Omit<UploadInputPro
297
292
 
298
293
  export function uploadField<
299
294
  T,
300
- P extends Path<T, PO>,
301
295
  PO extends PathsOptions = DefaultPathsOptions,
302
296
  >(
303
- id?: P,
297
+ id?: Path<T, PO>,
304
298
  label?: string,
305
- options?: UploadOptions<T, P>
306
- ): BaseBagelField<T, P, PO> {
299
+ options?: UploadOptions<T, Path<T, PO>>,
300
+ ): BaseBagelField<T, Path<T, PO>, PO> {
307
301
  return {
308
302
  $el: 'upload',
309
303
  id,
310
304
  label,
305
+ class: options?.class,
306
+ required: options?.required,
307
+ helptext: options?.helptext,
308
+ disabled: options?.disabled,
309
+ defaultValue: options?.defaultValue,
311
310
  vIf: options?.vIf,
312
311
  transform: options?.transform,
313
312
  attrs: {
@@ -353,20 +353,17 @@ export function img<
353
353
  ): BaseElementField<T, PO> {
354
354
  // Handle different overload patterns
355
355
  let id: Path<T, PO> | undefined
356
- let finalSrc: string = ''
357
356
  let finalOptions: ImgElementOptions<T, PO> = {}
358
357
 
359
358
  if (typeof idOrOptions === 'object' && idOrOptions !== null) {
360
359
  // img(options)
361
360
  finalOptions = idOrOptions
362
- const { id: optionId, src: optionSrc } = finalOptions
361
+ const { id: optionId } = finalOptions
363
362
  id = optionId as Path<T, PO> | undefined
364
- finalSrc = optionSrc ?? ''
365
363
  } else {
366
364
  // img(id, ...) patterns
367
365
  id = idOrOptions
368
366
  if (src != null) {
369
- finalSrc = src
370
367
  if (typeof altOrOptions === 'string') {
371
368
  // img(id, src, alt)
372
369
  finalOptions = { alt: altOrOptions }
File without changes