@bagelink/vue 0.0.1035 → 0.0.1041

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 (47) hide show
  1. package/dist/components/BglComponent.vue.d.ts +24 -0
  2. package/dist/components/BglComponent.vue.d.ts.map +1 -0
  3. package/dist/components/FieldSetVue.vue.d.ts +22 -0
  4. package/dist/components/FieldSetVue.vue.d.ts.map +1 -0
  5. package/dist/components/Pill.vue.d.ts +1 -0
  6. package/dist/components/Pill.vue.d.ts.map +1 -1
  7. package/dist/components/TableSchema.vue.d.ts.map +1 -1
  8. package/dist/components/form/BglField.vue.d.ts +8 -6
  9. package/dist/components/form/BglField.vue.d.ts.map +1 -1
  10. package/dist/components/form/BglForm.vue.d.ts +5 -4
  11. package/dist/components/form/BglForm.vue.d.ts.map +1 -1
  12. package/dist/components/form/BglMultiStepForm.vue.d.ts +2 -2
  13. package/dist/components/form/FieldArray.vue.d.ts +1 -0
  14. package/dist/components/form/FieldArray.vue.d.ts.map +1 -1
  15. package/dist/components/form/inputs/NumberInput.vue.d.ts.map +1 -1
  16. package/dist/components/form/inputs/RadioGroup.vue.d.ts +1 -0
  17. package/dist/components/form/inputs/RadioGroup.vue.d.ts.map +1 -1
  18. package/dist/components/form/inputs/RangeInput.vue.d.ts +4 -3
  19. package/dist/components/form/inputs/RangeInput.vue.d.ts.map +1 -1
  20. package/dist/components/form/useBagelFormState.d.ts +11 -0
  21. package/dist/components/form/useBagelFormState.d.ts.map +1 -0
  22. package/dist/components/index.d.ts +2 -0
  23. package/dist/components/index.d.ts.map +1 -1
  24. package/dist/index.cjs +7085 -9121
  25. package/dist/index.d.ts +1 -0
  26. package/dist/index.d.ts.map +1 -1
  27. package/dist/index.mjs +7091 -9127
  28. package/dist/style.css +504 -495
  29. package/dist/utils/BagelFormUtils.d.ts +31 -17
  30. package/dist/utils/BagelFormUtils.d.ts.map +1 -1
  31. package/package.json +1 -1
  32. package/src/components/BglComponent.vue +174 -0
  33. package/src/components/FieldSetVue.vue +23 -0
  34. package/src/components/ModalForm.vue +1 -1
  35. package/src/components/Pill.vue +3 -2
  36. package/src/components/TableSchema.vue +3 -2
  37. package/src/components/form/BglField.vue +50 -77
  38. package/src/components/form/BglForm.vue +44 -31
  39. package/src/components/form/FieldArray.vue +25 -19
  40. package/src/components/form/inputs/NumberInput.vue +7 -8
  41. package/src/components/form/inputs/RadioGroup.vue +2 -0
  42. package/src/components/form/inputs/RangeInput.vue +75 -42
  43. package/src/components/form/useBagelFormState.ts +87 -0
  44. package/src/components/index.ts +5 -2
  45. package/src/index.ts +3 -1
  46. package/src/utils/BagelFormUtils.ts +12 -1
  47. package/src/components/FieldSet.vue +0 -15
@@ -1,6 +1,7 @@
1
1
  <script lang="ts" setup>
2
2
  import { BglField, type BglFormSchemaFnT, Title, useBglSchema, useModal } from '@bagelink/vue'
3
- import { useSlots, watch } from 'vue'
3
+ import { inject, useSlots, watch } from 'vue'
4
+ import { FORM_STATE_KEY, provideBagelFormState, type BagelFormState } from './useBagelFormState'
4
5
 
5
6
  export type FormStatus = 'idle' | 'loading' | 'success' | 'error'
6
7
 
@@ -22,41 +23,55 @@ const props = withDefaults(
22
23
  const emit = defineEmits(['update:modelValue', 'submit', 'dirty'])
23
24
 
24
25
  const slots = useSlots()
25
-
26
26
  const { showModal } = useModal()
27
-
28
27
  const instAt = new Date()
29
28
  const timeSinceInst = () => Date.now() - instAt.getTime()
30
- let formData = $ref(props.modelValue || {})
31
- let isDirty = $ref(false)
32
- let data = $computed({
33
- set: (val: any) => {
34
- if (timeSinceInst() > 100) {
29
+
30
+ // Check if we're a nested form
31
+ const existingFormState = inject<BagelFormState | undefined>(FORM_STATE_KEY)
32
+ const isNested = Boolean(existingFormState && props.id)
33
+
34
+ // Only provide new form state if we're not nested
35
+ const { data, isDirty } = isNested
36
+ ? existingFormState!
37
+ : provideBagelFormState(props.modelValue)
38
+
39
+ // Only watch for external updates if we're not nested
40
+ if (!isNested) {
41
+ watch(() => props.modelValue, (newVal) => {
42
+ if (JSON.stringify(newVal) !== JSON.stringify(data.value)) {
43
+ data.value = newVal
44
+ }
45
+ }, { deep: true, immediate: true })
46
+
47
+ // Emit updates when internal state changes
48
+ watch(data, (newVal) => {
49
+ if (timeSinceInst() > 100 && JSON.stringify(newVal) !== JSON.stringify(props.modelValue)) {
35
50
  emit('dirty')
36
- isDirty = true
51
+ emit('update:modelValue', newVal)
37
52
  }
38
- formData = val
39
- emit('update:modelValue', val)
40
- },
41
- get: () => formData,
42
- })
53
+ }, { deep: true })
54
+ }
55
+
43
56
  const form = $ref<HTMLFormElement>()
44
57
 
45
58
  function validateForm() {
46
- // ? Ensures that scrolling does not dismiss validation-tooltip in safari
47
- setTimeout(() => form?.reportValidity(), 300) // TODO: check if browser is safari
48
-
59
+ setTimeout(() => form?.reportValidity(), 300)
49
60
  if (!form) return false
50
61
  return form.reportValidity()
51
62
  }
52
63
 
53
- const clearForm = () => (data = {})
64
+ function clearForm() {
65
+ if (!isNested) {
66
+ data.value = {}
67
+ }
68
+ }
54
69
 
55
70
  watch(
56
71
  () => props.status,
57
72
  (status) => {
58
- if (status === 'success') {
59
- isDirty = false
73
+ if (status === 'success' && !isNested) {
74
+ isDirty.value = false
60
75
  clearForm()
61
76
  }
62
77
  },
@@ -66,9 +81,10 @@ watch(
66
81
  function runSubmit() {
67
82
  const isValid = validateForm()
68
83
  if (!isValid) return
69
- // props.onSubmit?.(data);
70
- emit('submit', { ...formData })
71
- isDirty = false
84
+ emit('submit', { ...data.value })
85
+ if (!isNested) {
86
+ isDirty.value = false
87
+ }
72
88
  }
73
89
 
74
90
  const i18nT = (val: string) => val
@@ -91,9 +107,7 @@ function deleteItem() {
91
107
  )
92
108
  }
93
109
 
94
- const computedSchema = $computed(
95
- () => useBglSchema({ schema: props.schema })
96
- )
110
+ const computedSchema = $computed(() => useBglSchema({ schema: props.schema }))
97
111
 
98
112
  defineExpose({
99
113
  submit: runSubmit,
@@ -106,14 +120,13 @@ defineExpose({
106
120
 
107
121
  <template>
108
122
  <template v-if="id">
109
- <Title v-if="label" tag="h4" :label="label" />
110
123
  <BglField
111
124
  v-for="(field, i) in computedSchema"
125
+ :id="[id, field.id].filter(Boolean).join('.')"
112
126
  :key="field.id || `${i}p`"
113
- v-model="data"
114
127
  :field="field"
115
128
  />
116
- <slot name="submit" :submit="runSubmit" :isDirty :validateForm />
129
+ <slot name="submit" :submit="runSubmit" :isDirty="isDirty" :validateForm="validateForm" />
117
130
  </template>
118
131
  <form
119
132
  v-else-if="!slots.success || status !== 'success'"
@@ -123,11 +136,11 @@ defineExpose({
123
136
  <Title v-if="label" tag="h4" :label="label" />
124
137
  <BglField
125
138
  v-for="(field, i) in computedSchema"
139
+ :id="field.id"
126
140
  :key="field.id || `${i}p`"
127
- v-model="data"
128
141
  :field="field"
129
142
  />
130
- <slot name="submit" :submit="runSubmit" :isDirty :validateForm />
143
+ <slot name="submit" :submit="runSubmit" :isDirty="isDirty" :validateForm="validateForm" />
131
144
  </form>
132
145
  <slot v-if="status === 'success'" name="success" />
133
146
  <slot v-if="status === 'error'" name="error" />
@@ -7,7 +7,7 @@ import type {
7
7
  BglFormSchemaFnT,
8
8
  Field,
9
9
  } from '@bagelink/vue'
10
- import { BglForm, Btn } from '@bagelink/vue'
10
+ import { BglForm, BglField, Btn } from '@bagelink/vue'
11
11
 
12
12
  const props = withDefaults(
13
13
  defineProps<{
@@ -25,6 +25,7 @@ const props = withDefaults(
25
25
  defaultValue?: any
26
26
  add?: boolean
27
27
  delete?: boolean
28
+ transform?: (value: T) => T
28
29
  schema: BglFormSchemaFnT
29
30
  modelValue: T[]
30
31
  }>(),
@@ -53,31 +54,33 @@ function addItem() {
53
54
  emitValue()
54
55
  }
55
56
 
56
- // const computedField = $computed(
57
- // () => ({
58
- // label: props.label,
59
- // placeholder: props.placeholder,
60
- // children: props.children,
61
- // class: props.class,
62
- // attrs: props.attrs,
63
- // required: props.required,
64
- // disabled: props.disabled,
65
- // helptext: props.helptext,
66
- // options: props.options,
67
- // defaultValue: props.defaultValue,
68
- // $el: props.el,
69
- // }) as Field<T>
70
- // ) as Field<Record<string, any>>
57
+ const computedField = $computed(
58
+ () => ({
59
+ label: props.label,
60
+ placeholder: props.placeholder,
61
+ children: props.children,
62
+ // class: props.class,
63
+ attrs: props.attrs,
64
+ required: props.required,
65
+ disabled: props.disabled,
66
+ helptext: props.helptext,
67
+ options: props.options,
68
+ defaultValue: props.defaultValue,
69
+ transform: props.transform,
70
+ $el: props.el,
71
+ }) as Field<T>
72
+ ) as Field<Record<string, any>>
71
73
  </script>
72
74
 
73
75
  <template>
74
- <div>
76
+ <div :class="props.class">
75
77
  <p class="label mb-05">
76
78
  {{ label }}
77
79
  </p>
78
- <div class="-ms-05 ps-05 border-start">
80
+
81
+ <div v-if="schema" class="-ms-05 ps-05 border-start">
79
82
  <div v-for="(_, i) in data" :key="i" outline thin class="mb-05 itemBox transition p-05">
80
- <BglForm v-if="schema" v-model="data[i]" :schema="schema" @update:model-value="emitValue" />
83
+ <BglForm v-model="data[i]" :schema="schema" @update:model-value="emitValue" />
81
84
  <Btn
82
85
  v-if="props.delete"
83
86
  icon="delete"
@@ -92,6 +95,9 @@ function addItem() {
92
95
  <p>Add {{ label }}</p>
93
96
  </Btn>
94
97
  </div>
98
+ <template v-else>
99
+ <BglField v-for="(_, i) in data" :key="i" v-model="data[i]" :field="computedField" @update:model-value="emitValue" />
100
+ </template>
95
101
  </div>
96
102
  </template>
97
103
 
@@ -47,17 +47,16 @@ const btnLayouts: NumberLayout[] = ['horizontal', 'vertical']
47
47
 
48
48
  // Methods
49
49
  function increment() {
50
- if (!max || numberValue + step <= max) {
51
- numberValue = (numberValue || 0) + step
52
- emit('update:modelValue', numberValue)
53
- }
50
+ if (max !== undefined && (numberValue + step) > max) return
51
+ numberValue = (numberValue || 0) + step
52
+ emit('update:modelValue', numberValue)
54
53
  }
55
54
 
56
55
  function decrement() {
57
- if (!min || numberValue - step >= min) {
58
- numberValue = (numberValue || 0) - step
59
- emit('update:modelValue', numberValue)
60
- }
56
+ numberValue = numberValue || 0
57
+ if (min !== undefined && (numberValue - step) < min) return
58
+ numberValue = numberValue - step
59
+ emit('update:modelValue', numberValue)
61
60
  }
62
61
 
63
62
  function formatNumber(num: number) {
@@ -15,6 +15,7 @@ defineProps<{
15
15
  groupName: string
16
16
  options: RadioOption<ContextObjType>[]
17
17
  deletable?: boolean
18
+ required?: boolean
18
19
  }>()
19
20
  defineEmits(['delete'])
20
21
 
@@ -36,6 +37,7 @@ const selectedOption = defineModel('modelValue')
36
37
  type="radio"
37
38
  :name="groupName"
38
39
  :value="opt.value"
40
+ :required="required"
39
41
  >
40
42
  <div class="flex w-100 gap-1 flex-wrap m_gap-05 m_gap-row-025">
41
43
  <img
@@ -1,7 +1,7 @@
1
1
  <script setup lang="ts">
2
2
  import { watch } from 'vue'
3
3
 
4
- interface props {
4
+ export interface RangeInputProps {
5
5
  modelValue: number | [number, number]
6
6
  min?: number
7
7
  max?: number
@@ -11,45 +11,81 @@ interface props {
11
11
  disabled?: boolean
12
12
  id?: string
13
13
  rtl?: boolean
14
+ multiRange?: boolean
14
15
  }
15
16
 
16
- const { min = 0, max = 100, step = 1, modelValue, label, disabled, id, rtl } = defineProps<props>()
17
-
17
+ const props = defineProps<RangeInputProps>()
18
18
  const emit = defineEmits(['update:modelValue'])
19
19
 
20
- const isRange = $computed(() => Array.isArray(modelValue))
20
+ const {
21
+ min = 0,
22
+ max = 100,
23
+ step = 1,
24
+ label,
25
+ disabled,
26
+ id,
27
+ rtl,
28
+ multiRange
29
+ } = props
21
30
 
22
31
  let from = $ref<number>(min)
23
32
  let to = $ref<number>(max)
24
33
 
25
- const validFrom = $computed(() => Math.min(Math.max(from, min), to)) as number
26
- const validTo = $computed(() => Math.max(Math.min(to, max), from)) as number
34
+ let isExternalUpdate = $ref(true)
35
+
36
+ const validFrom = $computed(() => Math.min(Math.max(from, min), multiRange ? to : max))
37
+ const validTo = $computed(() => Math.max(Math.min(to, max), from))
38
+
39
+ watch(() => props.modelValue, (newVal) => {
40
+ isExternalUpdate = true
41
+ if (multiRange && Array.isArray(newVal)) {
42
+ from = newVal[0]
43
+ to = newVal[1]
44
+ } else if (!multiRange && !Array.isArray(newVal)) {
45
+ from = newVal ?? min
46
+ to = max
47
+ }
48
+ }, { immediate: true })
49
+
50
+ watch([() => validFrom, () => validTo], () => {
51
+ if (!isExternalUpdate) {
52
+ if (multiRange) {
53
+ emit('update:modelValue', [validFrom, validTo])
54
+ } else {
55
+ emit('update:modelValue', validFrom)
56
+ }
57
+ }
58
+ isExternalUpdate = false
59
+ })
27
60
 
28
- function emitValue() {
29
- emit('update:modelValue', isRange ? [validFrom, validTo] : validFrom)
61
+ function handleInput(value: number, isFromInput: boolean) {
62
+ isExternalUpdate = false
63
+ if (isFromInput) {
64
+ from = value
65
+ } else {
66
+ to = value
67
+ }
30
68
  }
31
69
 
32
- watch(() => validFrom, (newVal) => {
33
- if (from !== newVal) from = newVal
34
- })
35
- watch(() => validTo, (newVal) => {
36
- if (to !== newVal) to = newVal
37
- })
38
-
39
70
  const fromPercentage = $computed(() => ((validFrom - min) / (max - min)) * 100)
40
71
  const toPercentage = $computed(() => ((validTo - min) / (max - min)) * 100)
41
72
 
42
73
  const rangeStyle = $computed(() => {
43
- const width = ((validTo - validFrom) / (max - min)) * 100
44
- if (isRange) return { left: `${fromPercentage}%`, width: `${width}%` }
45
- if (rtl) return { left: `${width}%`, width: `${fromPercentage}%` }
46
- return { right: `${width}%`, width: `${fromPercentage}%` }
74
+ if (multiRange) {
75
+ return {
76
+ left: `${fromPercentage}%`,
77
+ width: `${toPercentage - fromPercentage}%`
78
+ }
79
+ }
80
+ return rtl
81
+ ? { left: `${100 - fromPercentage}%`, width: `${fromPercentage}%` }
82
+ : { left: '0', width: `${fromPercentage}%` }
47
83
  })
48
84
  </script>
49
85
 
50
86
  <template>
51
87
  <div>
52
- <label class="label">{{ label }}</label>
88
+ <label v-if="label" class="label">{{ label }}</label>
53
89
  <div class="range-slider relative w-100" :dir="rtl ? 'rtl' : 'ltr'">
54
90
  <input
55
91
  :id="id"
@@ -57,25 +93,25 @@ const rangeStyle = $computed(() => {
57
93
  class="from"
58
94
  type="range"
59
95
  :min="min"
60
- :max="max"
96
+ :max="multiRange ? to : max"
61
97
  :step="step"
62
98
  :required="required"
63
99
  :disabled="disabled"
64
- aria-label="Minimum value"
65
- @change="emitValue"
100
+ :aria-label="multiRange ? 'Minimum value' : 'Value'"
101
+ @input="(e) => handleInput(+(e.target as HTMLInputElement).value, true)"
66
102
  >
67
103
  <input
68
- v-if="isRange"
104
+ v-if="multiRange"
69
105
  v-model="to"
70
106
  class="to"
71
107
  type="range"
72
- :min="min"
108
+ :min="from"
73
109
  :max="max"
74
110
  :step="step"
75
111
  :required="required"
76
112
  :disabled="disabled"
77
113
  aria-label="Maximum value"
78
- @change="emitValue"
114
+ @input="(e) => handleInput(+(e.target as HTMLInputElement).value, false)"
79
115
  >
80
116
  <div class="track absolute pointer-events-none overflow-hidden round">
81
117
  <div
@@ -84,31 +120,23 @@ const rangeStyle = $computed(() => {
84
120
  />
85
121
  </div>
86
122
  <p
87
- v-if="from !== min"
123
+ v-if="validFrom !== min"
88
124
  class="txt-center txt-12 range-slider-position-txt absolute line-height-1 opacity-0"
89
125
  :style="{ '--progress': `${fromPercentage}` }"
90
126
  >
91
- <span>
92
- {{ from }}
93
- </span>
127
+ {{ validFrom }}
94
128
  </p>
95
129
  <p
96
- v-if="isRange && to !== max"
130
+ v-if="multiRange && validTo !== max"
97
131
  class="txt-center txt-12 range-slider-position-txt opacity-0 line-height-1 absolute"
98
132
  :style="{ '--progress': `${toPercentage}` }"
99
133
  >
100
- <span>
101
- {{ to }}
102
- </span>
134
+ {{ validTo }}
103
135
  </p>
104
136
  </div>
105
137
  <p class="txt-center txt-14 range-slider-txt flex space-between opacity-4 mx-05">
106
- <span>
107
- {{ min }}
108
- </span>
109
- <span>
110
- {{ max }}
111
- </span>
138
+ <span>{{ min }}</span>
139
+ <span>{{ max }}</span>
112
140
  </p>
113
141
  </div>
114
142
  </template>
@@ -125,8 +153,8 @@ const rangeStyle = $computed(() => {
125
153
  opacity: 1;
126
154
  transform: scale(1);
127
155
  top: calc(var(--bgl-range-thumb-size) / 1) ;
128
-
129
156
  }
157
+
130
158
  .range-slider {
131
159
  height: var(--bgl-range-track-size);
132
160
  display: flex;
@@ -158,9 +186,10 @@ input[type="range"]::-webkit-slider-thumb {
158
186
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
159
187
  position: relative;
160
188
  z-index: 2;
161
- cursor: pointer;
189
+ cursor: grab;
162
190
  transition: var(--bgl-transition);
163
191
  }
192
+
164
193
  input[type="range"]::-webkit-slider-thumb:hover {
165
194
  box-shadow: 0 0 0 calc(var(--bgl-range-thumb-size) / 2) var(--bgl-primary-tint);
166
195
  filter: brightness(90%);
@@ -171,6 +200,10 @@ input[type="range"]:focus::-webkit-slider-thumb {
171
200
  box-shadow: 0 0 0 calc(var(--bgl-range-thumb-size) / 2.2) var(--bgl-primary-tint);
172
201
  }
173
202
 
203
+ input[type="range"]:active::-webkit-slider-thumb {
204
+ cursor: grabbing;
205
+ }
206
+
174
207
  .track {
175
208
  height: var(--bgl-range-track-height);
176
209
  background: var(--bgl-bg);
@@ -0,0 +1,87 @@
1
+ import { inject, provide, ref, type Ref } from 'vue'
2
+
3
+ export const FORM_STATE_KEY = Symbol('bagelFormState')
4
+
5
+ export interface BagelFormState<T = any> {
6
+ data: Ref<T>
7
+ getFieldData: (path?: string) => any
8
+ updateField: (path: string, value: any) => void
9
+ isDirty: Ref<boolean>
10
+ }
11
+
12
+ // Helper function to safely clone objects without circular references
13
+ function safeClone(obj: any): any {
14
+ if (obj === null || typeof obj !== 'object') return obj
15
+
16
+ const seen = new WeakSet()
17
+ return JSON.parse(JSON.stringify(obj, (key, value) => {
18
+ if (typeof value === 'object' && value !== null) {
19
+ if (seen.has(value)) {
20
+ return undefined // Remove circular reference
21
+ }
22
+ seen.add(value)
23
+ }
24
+ return value
25
+ }))
26
+ }
27
+
28
+ export function provideBagelFormState<T>(initialData: T) {
29
+ const data = ref(initialData) as Ref<T>
30
+ const isDirty = ref(false)
31
+
32
+ const getFieldData = (path?: string) => {
33
+ if (!path) return ''
34
+ const keys = path.split(/[.[]/)
35
+ let current = data.value as any
36
+
37
+ for (let i = 0; i < keys.length; i++) {
38
+ const key = keys[i]
39
+ if (!current || typeof current !== 'object' || !(key in current)) {
40
+ return ''
41
+ }
42
+ current = current[key]
43
+ }
44
+ return current ?? ''
45
+ }
46
+
47
+ const updateField = (path: string, value: any) => {
48
+ const keys = path.split(/[.[]/)
49
+
50
+ // Initialize the root if it's not an object
51
+ if (typeof data.value !== 'object' || data.value === null) {
52
+ data.value = {} as T
53
+ }
54
+
55
+ let current = data.value as any
56
+
57
+ // Build the path, ensuring each level is an object
58
+ for (let i = 0; i < keys.length - 1; i++) {
59
+ const key = keys[i]
60
+ if (!(key in current) || typeof current[key] !== 'object' || current[key] === null) {
61
+ current[key] = {}
62
+ }
63
+ current = current[key]
64
+ }
65
+
66
+ // Safely clone the value to remove circular references
67
+ const safeValue = safeClone(value)
68
+ current[keys[keys.length - 1]] = safeValue
69
+ isDirty.value = true
70
+ }
71
+
72
+ const state: BagelFormState<T> = {
73
+ data,
74
+ getFieldData,
75
+ updateField,
76
+ isDirty
77
+ }
78
+
79
+ provide(FORM_STATE_KEY, state)
80
+ return state
81
+ }
82
+
83
+ export function useBagelFormState<T>() {
84
+ const state = inject<BagelFormState<T>>(FORM_STATE_KEY)
85
+ if (!state) throw new Error('BagelFormState must be provided')
86
+ return state
87
+ }
@@ -4,6 +4,7 @@ export { default as AddressSearch } from './AddressSearch.vue'
4
4
  export { default as Alert } from './Alert.vue'
5
5
  export { default as Avatar } from './Avatar.vue'
6
6
  export { default as Badge } from './Badge.vue'
7
+ export { default as BglComponent } from './BglComponent.vue'
7
8
  export { default as BglVideo } from './BglVideo.vue'
8
9
  export { default as Btn } from './Btn.vue'
9
10
  export { default as Card } from './Card.vue'
@@ -11,6 +12,7 @@ export { default as Carousel } from './Carousel.vue'
11
12
  export * from './dashboard'
12
13
  export { default as DataPreview } from './DataPreview.vue'
13
14
  export { default as Dropdown } from './Dropdown.vue'
15
+ export { default as FieldSetVue } from './FieldSetVue.vue'
14
16
  export { default as Flag } from './Flag.vue'
15
17
  export * from './form'
16
18
  export { default as IframeVue } from './IframeVue.vue'
@@ -22,17 +24,18 @@ export { default as Loading } from './Loading.vue'
22
24
  export { default as MapEmbed } from './MapEmbed.vue'
23
25
  export { default as MaterialIcon } from './MaterialIcon.vue'
24
26
  export { default as Icon } from './MaterialIcon.vue'
27
+
25
28
  export { default as Modal } from './Modal.vue'
26
29
  export { default as ModalConfirm } from './ModalConfirm.vue'
27
30
  export { default as ModalForm } from './ModalForm.vue'
28
-
29
31
  export { default as NavBar } from './NavBar.vue'
30
32
  export { default as PageTitle } from './PageTitle.vue'
31
33
  export { default as Pill } from './Pill.vue'
32
34
  export { default as RouterWrapper } from './RouterWrapper.vue'
33
35
  export { default as TableSchema } from './TableSchema.vue'
36
+
34
37
  export { default as Title } from './Title.vue'
35
38
  export { default as ToolBar } from './ToolBar.vue'
36
- export { default as TopBar } from './TopBar.vue'
37
39
 
40
+ export { default as TopBar } from './TopBar.vue'
38
41
  export { default as Zoomer } from './Zoomer.vue'
package/src/index.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  export * from './components'
2
+ export * from './components/form/useBagelFormState'
2
3
  export * from './composables'
3
4
  export {
4
5
  bagelInjectionKey,
@@ -13,5 +14,6 @@ export * from './types'
13
14
  export * from './utils'
14
15
  export * from './utils/allCountries'
15
16
  export * from './utils/constants'
16
- export * from './utils/timeAgo'
17
17
  import './styles/bagel.css'
18
+
19
+ export * from './utils/timeAgo'
@@ -8,6 +8,7 @@ interface InputOptions {
8
8
  defaultValue?: string
9
9
  disabled?: boolean
10
10
  helptext?: string
11
+ vIf?: boolean | ((item: any, row: any) => boolean)
11
12
  }
12
13
 
13
14
  type DateOptions = InputOptions
@@ -50,6 +51,7 @@ export function richText(
50
51
  required: options?.required,
51
52
  id,
52
53
  label,
54
+ vIf: options?.vIf,
53
55
  placeholder: options?.placeholder,
54
56
  attrs: {},
55
57
  }
@@ -66,6 +68,7 @@ export function txtField(
66
68
  required: options?.required,
67
69
  id,
68
70
  label,
71
+ vIf: options?.vIf,
69
72
  disabled: options?.disabled,
70
73
  placeholder: options?.placeholder,
71
74
  defaultValue: options?.defaultValue,
@@ -93,6 +96,7 @@ export function slctField(
93
96
  required: config?.required,
94
97
  label,
95
98
  defaultValue: config?.defaultValue,
99
+ vIf: config?.vIf,
96
100
  attrs: {
97
101
  disabled: config?.disabled,
98
102
  searchable: config?.searchable,
@@ -130,6 +134,7 @@ export function dateField(
130
134
  disabled: options?.disabled,
131
135
  label,
132
136
  defaultValue: options?.defaultValue,
137
+ vIf: options?.vIf,
133
138
  attrs: {
134
139
  disabled: options?.disabled,
135
140
  },
@@ -151,6 +156,7 @@ export function numField(
151
156
  disabled: options?.disabled,
152
157
  placeholder: options?.placeholder,
153
158
  helptext: options?.helptext,
159
+ vIf: options?.vIf,
154
160
  attrs: {
155
161
  step: options?.step,
156
162
  min: options?.min,
@@ -176,7 +182,10 @@ export function uploadField(id: string, label?: string, options?: UploadOptions)
176
182
  $el: 'upload',
177
183
  id,
178
184
  label,
179
- attrs: options,
185
+ vIf: options?.vIf,
186
+ attrs: {
187
+ ...options,
188
+ },
180
189
  }
181
190
  }
182
191
 
@@ -203,6 +212,7 @@ export function telField(id: string, label?: string, options?: { [key: string]:
203
212
  $el: markRaw(TelInput),
204
213
  id,
205
214
  label,
215
+ vIf: options?.vIf,
206
216
  attrs: options,
207
217
  }
208
218
  }
@@ -228,6 +238,7 @@ export function arrField(id: string, label: string, schema: BglFormSchemaT, opti
228
238
  label,
229
239
  id,
230
240
  $el: 'array',
241
+ vIf: options?.vIf,
231
242
  attrs: { schema, delete: true, add: true, ...options },
232
243
  }
233
244
  }