@bagelink/vue 0.0.1035 → 0.0.1037
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/Accordion.d.ts +12 -0
- package/dist/components/Accordion.d.ts.map +1 -0
- package/dist/components/AccordionItem.d.ts +34 -0
- package/dist/components/AccordionItem.d.ts.map +1 -0
- package/dist/components/Alert.d.ts +34 -0
- package/dist/components/Alert.d.ts.map +1 -0
- package/dist/components/Avatar.d.ts +36 -0
- package/dist/components/Avatar.d.ts.map +1 -0
- package/dist/components/Badge.d.ts +22 -0
- package/dist/components/Badge.d.ts.map +1 -0
- package/dist/components/BglComponent.vue.d.ts +24 -0
- package/dist/components/BglComponent.vue.d.ts.map +1 -0
- package/dist/components/BglVideo.d.ts +20 -0
- package/dist/components/BglVideo.d.ts.map +1 -0
- package/dist/components/Btn.d.ts +99 -0
- package/dist/components/Btn.d.ts.map +1 -0
- package/dist/components/Card.d.ts +39 -0
- package/dist/components/Card.d.ts.map +1 -0
- package/dist/components/Carousel.d.ts +74 -0
- package/dist/components/Carousel.d.ts.map +1 -0
- package/dist/components/ComboBox.vue.d.ts +3 -3
- package/dist/components/Comments.vue.d.ts +2 -2
- package/dist/components/ContactSubmissions.vue.d.ts +2 -2
- package/dist/components/DataPreview.d.ts +42 -0
- package/dist/components/DataPreview.d.ts.map +1 -0
- package/dist/components/Drop.vue.d.ts +34 -0
- package/dist/components/Drop.vue.d.ts.map +1 -0
- package/dist/components/FieldSetVue.vue.d.ts +22 -0
- package/dist/components/FieldSetVue.vue.d.ts.map +1 -0
- package/dist/components/FileUploader.vue.d.ts +60 -0
- package/dist/components/FileUploader.vue.d.ts.map +1 -0
- package/dist/components/Flag.d.ts +20 -0
- package/dist/components/Flag.d.ts.map +1 -0
- package/dist/components/FormSchema.vue.d.ts +5 -4
- package/dist/components/LangText.vue.d.ts +2 -2
- package/dist/components/ListItem.d.ts +34 -0
- package/dist/components/ListItem.d.ts.map +1 -0
- package/dist/components/ListView.d.ts +13 -0
- package/dist/components/ListView.d.ts.map +1 -0
- package/dist/components/MapEmbed.d.ts +3 -0
- package/dist/components/MapEmbed.d.ts.map +1 -0
- package/dist/components/MaterialIcon.d.ts +26 -0
- package/dist/components/MaterialIcon.d.ts.map +1 -0
- package/dist/components/Modal.d.ts +46 -0
- package/dist/components/Modal.d.ts.map +1 -0
- package/dist/components/ModalBglForm.vue.d.ts +21 -20
- package/dist/components/ModalConfirm.d.ts +24 -0
- package/dist/components/ModalConfirm.d.ts.map +1 -0
- package/dist/components/ModalForm.d.ts +78 -0
- package/dist/components/ModalForm.d.ts.map +1 -0
- package/dist/components/NavBar.d.ts +64 -0
- package/dist/components/NavBar.d.ts.map +1 -0
- package/dist/components/PageTitle.d.ts +24 -0
- package/dist/components/PageTitle.d.ts.map +1 -0
- package/dist/components/PersonPreview.vue.d.ts +5 -4
- package/dist/components/PersonPreviewFormkit.vue.d.ts +4 -3
- package/dist/components/Pill.vue.d.ts +1 -0
- package/dist/components/Pill.vue.d.ts.map +1 -1
- package/dist/components/RTXEditor.vue.d.ts +3 -3
- package/dist/components/RouterWrapper.d.ts +3 -0
- package/dist/components/RouterWrapper.d.ts.map +1 -0
- package/dist/components/TabbedLayout.vue.d.ts +5 -4
- package/dist/components/TableSchema.d.ts +35 -0
- package/dist/components/TableSchema.d.ts.map +1 -0
- package/dist/components/TableSchema.vue.d.ts.map +1 -1
- package/dist/components/Title.d.ts +42 -0
- package/dist/components/Title.d.ts.map +1 -0
- package/dist/components/TopBar.d.ts +12 -0
- package/dist/components/TopBar.d.ts.map +1 -0
- package/dist/components/charts/BarChart.vue.d.ts +2 -2
- package/dist/components/dashboard/Lineart.d.ts +20 -0
- package/dist/components/dashboard/Lineart.d.ts.map +1 -0
- package/dist/components/form/BglField.d.ts +25 -0
- package/dist/components/form/BglField.d.ts.map +1 -0
- package/dist/components/form/BglField.vue.d.ts +8 -6
- package/dist/components/form/BglField.vue.d.ts.map +1 -1
- package/dist/components/form/BglForm.d.ts +75 -0
- package/dist/components/form/BglForm.d.ts.map +1 -0
- package/dist/components/form/BglForm.vue.d.ts +5 -4
- package/dist/components/form/BglForm.vue.d.ts.map +1 -1
- package/dist/components/form/BglMultiStepForm.vue.d.ts +2 -2
- package/dist/components/form/FieldArray.vue.d.ts +1 -0
- package/dist/components/form/FieldArray.vue.d.ts.map +1 -1
- package/dist/components/form/ItemRef.vue.d.ts +5 -3
- package/dist/components/form/ItemRef.vue.d.ts.map +1 -1
- package/dist/components/form/MaterialIcon.vue.d.ts +4 -3
- package/dist/components/form/PlainInputField.vue.d.ts +3 -3
- package/dist/components/form/inputs/CheckInput.d.ts +56 -0
- package/dist/components/form/inputs/CheckInput.d.ts.map +1 -0
- package/dist/components/form/inputs/Checkbox.d.ts +16 -0
- package/dist/components/form/inputs/Checkbox.d.ts.map +1 -0
- package/dist/components/form/inputs/ColorPicker.d.ts +48 -0
- package/dist/components/form/inputs/ColorPicker.d.ts.map +1 -0
- package/dist/components/form/inputs/CurrencyInput.vue.d.ts +3 -3
- package/dist/components/form/inputs/DateInput.d.ts +64 -0
- package/dist/components/form/inputs/DateInput.d.ts.map +1 -0
- package/dist/components/form/inputs/DatePicker.d.ts +33 -0
- package/dist/components/form/inputs/DatePicker.d.ts.map +1 -0
- package/dist/components/form/inputs/DatetimeInput.vue.d.ts +3 -3
- package/dist/components/form/inputs/DurationInput.vue.d.ts +3 -3
- package/dist/components/form/inputs/DynamicLinkField.vue.d.ts +3 -3
- package/dist/components/form/inputs/EmailInput.vue.d.ts +3 -3
- package/dist/components/form/inputs/FileUpload.d.ts +108 -0
- package/dist/components/form/inputs/FileUpload.d.ts.map +1 -0
- package/dist/components/form/inputs/FloatInput.vue.d.ts +3 -3
- package/dist/components/form/inputs/IntInput.vue.d.ts +3 -3
- package/dist/components/form/inputs/JSONInput.d.ts +53 -0
- package/dist/components/form/inputs/JSONInput.d.ts.map +1 -0
- package/dist/components/form/inputs/LinkField.vue.d.ts +3 -3
- package/dist/components/form/inputs/NumberInput.vue.d.ts.map +1 -1
- package/dist/components/form/inputs/Password.vue.d.ts +3 -3
- package/dist/components/form/inputs/PlainText.vue.d.ts +3 -3
- package/dist/components/form/inputs/RadioGroup.d.ts +42 -0
- package/dist/components/form/inputs/RadioGroup.d.ts.map +1 -0
- package/dist/components/form/inputs/RadioPillsInput.d.ts +48 -0
- package/dist/components/form/inputs/RadioPillsInput.d.ts.map +1 -0
- package/dist/components/form/inputs/RangeInput.vue.d.ts.map +1 -1
- package/dist/components/form/inputs/ReadOnlyInput.vue.d.ts +2 -2
- package/dist/components/form/inputs/RichText.d.ts +20 -0
- package/dist/components/form/inputs/RichText.d.ts.map +1 -0
- package/dist/components/form/inputs/RichText2/Toolbar.d.ts +22 -0
- package/dist/components/form/inputs/RichText2/Toolbar.d.ts.map +1 -0
- package/dist/components/form/inputs/RichText2/Toolbar.vue.d.ts.map +1 -1
- package/dist/components/form/inputs/RichText2/index.d.ts +24 -0
- package/dist/components/form/inputs/RichText2/index.d.ts.map +1 -0
- package/dist/components/form/inputs/RichText2/index.vue.d.ts +1 -0
- package/dist/components/form/inputs/RichText2/index.vue.d.ts.map +1 -1
- package/dist/components/form/inputs/RichTextEditor.vue.d.ts +3 -3
- package/dist/components/form/inputs/SelectField.vue.d.ts +6 -8
- package/dist/components/form/inputs/SelectField.vue.d.ts.map +1 -1
- package/dist/components/form/inputs/SelectInput.d.ts +55 -0
- package/dist/components/form/inputs/SelectInput.d.ts.map +1 -0
- package/dist/components/form/inputs/SignaturePad.d.ts +72 -0
- package/dist/components/form/inputs/SignaturePad.d.ts.map +1 -0
- package/dist/components/form/inputs/TableField.d.ts +45 -0
- package/dist/components/form/inputs/TableField.d.ts.map +1 -0
- package/dist/components/form/inputs/TelInput.d.ts +241 -0
- package/dist/components/form/inputs/TelInput.d.ts.map +1 -0
- package/dist/components/form/inputs/TextArea.vue.d.ts +3 -3
- package/dist/components/form/inputs/TextInput.d.ts +90 -0
- package/dist/components/form/inputs/TextInput.d.ts.map +1 -0
- package/dist/components/form/inputs/ToggleInput.d.ts +58 -0
- package/dist/components/form/inputs/ToggleInput.d.ts.map +1 -0
- package/dist/components/form/useBagelFormState.d.ts +11 -0
- package/dist/components/form/useBagelFormState.d.ts.map +1 -0
- package/dist/components/formkit/AddressArray.vue.d.ts +2 -2
- package/dist/components/formkit/BankDetailsArray.vue.d.ts +2 -2
- package/dist/components/formkit/ContactArrayFormKit.vue.d.ts +2 -2
- package/dist/components/formkit/FileUploader.vue.d.ts +2 -2
- package/dist/components/formkit/MiscFields.vue.d.ts +2 -2
- package/dist/components/formkit/Toggle.vue.d.ts +2 -2
- package/dist/components/index.d.ts +2 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/layout/BottomMenu.d.ts +27 -0
- package/dist/components/layout/BottomMenu.d.ts.map +1 -0
- package/dist/components/layout/Layout.d.ts +58 -0
- package/dist/components/layout/Layout.d.ts.map +1 -0
- package/dist/components/layout/SidebarMenu.d.ts +38 -0
- package/dist/components/layout/SidebarMenu.d.ts.map +1 -0
- package/dist/components/layout/TabbedLayout.d.ts +42 -0
- package/dist/components/layout/TabbedLayout.d.ts.map +1 -0
- package/dist/components/layout/Tabs.d.ts +31 -0
- package/dist/components/layout/Tabs.d.ts.map +1 -0
- package/dist/components/layout/TabsBody.d.ts +23 -0
- package/dist/components/layout/TabsBody.d.ts.map +1 -0
- package/dist/components/layout/TabsNav.d.ts +35 -0
- package/dist/components/layout/TabsNav.d.ts.map +1 -0
- package/dist/components/whatsapp/form/MsgTemplate.vue.d.ts +4 -3
- package/dist/components/whatsapp/form/TextVariableExamples.vue.d.ts +2 -2
- package/dist/index.cjs +7045 -9110
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +7051 -9116
- package/dist/style.css +500 -494
- package/dist/styles.css +14073 -0
- package/dist/utils/BagelFormUtils.d.ts +31 -17
- package/dist/utils/BagelFormUtils.d.ts.map +1 -1
- package/dist/utils/objects.d.ts +1 -0
- package/dist/vue.css +14073 -0
- package/package.json +1 -1
- package/src/components/BglComponent.vue +174 -0
- package/src/components/FieldSetVue.vue +23 -0
- package/src/components/ModalForm.vue +1 -1
- package/src/components/Pill.vue +3 -2
- package/src/components/TableSchema.vue +3 -2
- package/src/components/form/BglField.vue +50 -77
- package/src/components/form/BglForm.vue +44 -31
- package/src/components/form/FieldArray.vue +25 -19
- package/src/components/form/inputs/NumberInput.vue +7 -8
- package/src/components/form/inputs/RangeInput.vue +9 -0
- package/src/components/form/useBagelFormState.ts +87 -0
- package/src/components/index.ts +5 -2
- package/src/index.ts +3 -1
- package/src/utils/BagelFormUtils.ts +12 -1
- package/dist/common-C_IH8b5S.cjs +0 -12580
- package/dist/common-DoeNgx31.js +0 -12579
- package/dist/components/AddressSaerch.vue.d.ts +0 -7
- package/dist/components/AddressSaerch.vue.d.ts.map +0 -1
- package/dist/components/Popover.vue.d.ts +0 -10
- package/dist/components/Popover.vue.d.ts.map +0 -1
- package/dist/components/form/inputs/RichText/Toolbar.vue.d.ts +0 -14
- package/dist/components/form/inputs/RichText/Toolbar.vue.d.ts.map +0 -1
- package/dist/components/form/inputs/RichText/formatting.d.ts +0 -11
- package/dist/components/form/inputs/RichText/formatting.d.ts.map +0 -1
- package/dist/components/form/inputs/RichText/richtext-types.d.ts +0 -3
- package/dist/components/form/inputs/RichText/richtext-types.d.ts.map +0 -1
- package/dist/components/form/inputs/Upload/UploadFile.vue.d.ts +0 -86
- package/dist/components/form/inputs/Upload/UploadFile.vue.d.ts.map +0 -1
- package/dist/components/sortable/Animation.d.ts +0 -43
- package/dist/components/sortable/Animation.d.ts.map +0 -1
- package/dist/components/sortable/BrowserInfo.d.ts +0 -7
- package/dist/components/sortable/BrowserInfo.d.ts.map +0 -1
- package/dist/components/sortable/EventDispatcher.d.ts +0 -13
- package/dist/components/sortable/EventDispatcher.d.ts.map +0 -1
- package/dist/components/sortable/PluginManager.d.ts +0 -27
- package/dist/components/sortable/PluginManager.d.ts.map +0 -1
- package/dist/components/sortable/Sortable.d.ts +0 -81
- package/dist/components/sortable/Sortable.d.ts.map +0 -1
- package/dist/components/sortable/index.d.ts +0 -5
- package/dist/components/sortable/index.d.ts.map +0 -1
- package/dist/components/sortable/utils.d.ts +0 -49
- package/dist/components/sortable/utils.d.ts.map +0 -1
- package/dist/composables/drag-n-drop/useDraggable.d.ts +0 -2
- package/dist/composables/drag-n-drop/useDraggable.d.ts.map +0 -1
- package/dist/editor-CUDRLdmS.js +0 -4
- package/dist/editor-Cu374vEW.cjs +0 -4
- package/dist/editor-a8DSbb6P.js +0 -4
- package/dist/editor-xBt_vIha.cjs +0 -4
- package/dist/heic2any-8wMqMfB_.js +0 -933
- package/dist/heic2any-BrqcNzfV.js +0 -935
- package/dist/heic2any-C8KwH72N.cjs +0 -934
- package/dist/heic2any-k9wDCKka.cjs +0 -932
- package/dist/index-DiG-xM9T.cjs +0 -35016
- package/dist/index-nGuSAiY2.js +0 -35017
- package/dist/plugins/drag-n-drop/draggable.d.ts +0 -4
- package/dist/plugins/drag-n-drop/draggable.d.ts.map +0 -1
- package/dist/plugins/drag-n-drop/droppable.d.ts +0 -4
- package/dist/plugins/drag-n-drop/droppable.d.ts.map +0 -1
- package/dist/plugins/drag-n-drop/index.d.ts +0 -5
- package/dist/plugins/drag-n-drop/index.d.ts.map +0 -1
- package/dist/plugins/drag-n-drop/useDraggable.d.ts +0 -8
- package/dist/plugins/drag-n-drop/useDraggable.d.ts.map +0 -1
- package/dist/plugins/drag-n-drop/useDroppable.d.ts +0 -7
- package/dist/plugins/drag-n-drop/useDroppable.d.ts.map +0 -1
- package/dist/types/materialIcon.d.ts +0 -2
- package/dist/types/materialIcon.d.ts.map +0 -1
- package/src/components/FieldSet.vue +0 -15
package/package.json
CHANGED
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
<script setup lang="ts" generic="T extends Record<string, any>">
|
|
2
|
+
import {
|
|
3
|
+
CheckInput,
|
|
4
|
+
DateInput,
|
|
5
|
+
FieldArray,
|
|
6
|
+
type Field,
|
|
7
|
+
FileUpload,
|
|
8
|
+
RichText,
|
|
9
|
+
SelectInput,
|
|
10
|
+
TextInput,
|
|
11
|
+
ToggleInput,
|
|
12
|
+
bindAttrs,
|
|
13
|
+
classify,
|
|
14
|
+
NumberInput,
|
|
15
|
+
UploadInput,
|
|
16
|
+
BglForm,
|
|
17
|
+
TabsNav,
|
|
18
|
+
} from '@bagelink/vue'
|
|
19
|
+
|
|
20
|
+
const props = defineProps<{
|
|
21
|
+
field: Field<T>
|
|
22
|
+
id?: string
|
|
23
|
+
modelValue?: any
|
|
24
|
+
parentPath?: string
|
|
25
|
+
}>()
|
|
26
|
+
|
|
27
|
+
const emit = defineEmits<{
|
|
28
|
+
'update:modelValue': [value: any]
|
|
29
|
+
}>()
|
|
30
|
+
|
|
31
|
+
const customAttrs = $ref<{ [key: string]: any }>({})
|
|
32
|
+
|
|
33
|
+
const is = $computed(() => {
|
|
34
|
+
if (props.field.$el === 'text') return TextInput
|
|
35
|
+
if (props.field.$el === 'textarea') {
|
|
36
|
+
customAttrs.multiline = true
|
|
37
|
+
return TextInput
|
|
38
|
+
}
|
|
39
|
+
if (props.field.$el === 'number') return NumberInput
|
|
40
|
+
if (props.field.$el === 'array') return FieldArray
|
|
41
|
+
if (props.field.$el === 'select') return SelectInput
|
|
42
|
+
if (props.field.$el === 'toggle') return ToggleInput
|
|
43
|
+
if (props.field.$el === 'check') return CheckInput
|
|
44
|
+
if (props.field.$el === 'richtext') return RichText
|
|
45
|
+
if (props.field.$el === 'upload') return UploadInput
|
|
46
|
+
if (props.field.$el === 'file') return FileUpload
|
|
47
|
+
if (props.field.$el === 'date') return DateInput
|
|
48
|
+
if (props.field.$el === 'tabs') return TabsNav
|
|
49
|
+
if (props.field.$el === 'form') return BglForm
|
|
50
|
+
return props.field.$el ?? 'div'
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
function getFieldData(path?: string) {
|
|
54
|
+
if (!path) return ''
|
|
55
|
+
const keys = path.split(/[.[]/)
|
|
56
|
+
let current = props.modelValue as any
|
|
57
|
+
|
|
58
|
+
for (let i = 0; i < keys.length; i++) {
|
|
59
|
+
const key = keys[i]
|
|
60
|
+
if (!current || typeof current !== 'object' || !(key in current)) {
|
|
61
|
+
return ''
|
|
62
|
+
}
|
|
63
|
+
current = current[key]
|
|
64
|
+
}
|
|
65
|
+
return current ?? ''
|
|
66
|
+
}
|
|
67
|
+
function safeClone(obj: any): any {
|
|
68
|
+
if (obj === null || typeof obj !== 'object') return obj
|
|
69
|
+
|
|
70
|
+
const seen = new WeakSet()
|
|
71
|
+
return JSON.parse(JSON.stringify(obj, (key, value) => {
|
|
72
|
+
if (typeof value === 'object' && value !== null) {
|
|
73
|
+
if (seen.has(value)) {
|
|
74
|
+
return undefined // Remove circular reference
|
|
75
|
+
}
|
|
76
|
+
seen.add(value)
|
|
77
|
+
}
|
|
78
|
+
return value
|
|
79
|
+
}))
|
|
80
|
+
}
|
|
81
|
+
function updateField(path: string, value: any) {
|
|
82
|
+
const keys = path.split(/[.[]/)
|
|
83
|
+
|
|
84
|
+
let current = props.modelValue ?? {} as any
|
|
85
|
+
|
|
86
|
+
// Build the path, ensuring each level is an object
|
|
87
|
+
for (let i = 0; i < keys.length - 1; i++) {
|
|
88
|
+
const key = keys[i]
|
|
89
|
+
if (!(key in current) || typeof current[key] !== 'object' || current[key] === null) {
|
|
90
|
+
current[key] = {}
|
|
91
|
+
}
|
|
92
|
+
current = current[key]
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Safely clone the value to remove circular references
|
|
96
|
+
const safeValue = safeClone(value)
|
|
97
|
+
current[keys[keys.length - 1]] = safeValue
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const fieldData = $computed({
|
|
101
|
+
get: () => {
|
|
102
|
+
if (!props.id) return props.modelValue ?? props.field.defaultValue ?? (props.field.$el === 'form' ? {} : '')
|
|
103
|
+
const value = getFieldData(props.id)
|
|
104
|
+
if (props.field.$el === 'form' && !value) return {}
|
|
105
|
+
return value ?? ''
|
|
106
|
+
},
|
|
107
|
+
set: (val: any) => {
|
|
108
|
+
if (!props.id) return
|
|
109
|
+
const currentValue = getFieldData(props.id)
|
|
110
|
+
if (JSON.stringify(val) === JSON.stringify(currentValue)) return
|
|
111
|
+
|
|
112
|
+
emit('update:modelValue', val)
|
|
113
|
+
if (props.field.onUpdate) {
|
|
114
|
+
props.field.onUpdate(val, currentValue)
|
|
115
|
+
}
|
|
116
|
+
updateField(props.id, val)
|
|
117
|
+
}
|
|
118
|
+
})
|
|
119
|
+
|
|
120
|
+
const vIf = $computed(() => {
|
|
121
|
+
if (props.field['v-if'] === undefined && props.field.vIf === undefined) return true
|
|
122
|
+
if (typeof props.field['v-if'] === 'boolean' || typeof props.field.vIf === 'boolean') return props.field['v-if']
|
|
123
|
+
if (typeof props.field['v-if'] === 'string' || typeof props.field.vIf === 'string') return true
|
|
124
|
+
if (typeof props.field['v-if'] === 'function') return props.field['v-if'](fieldData, props.modelValue as T)
|
|
125
|
+
if (typeof props.field.vIf === 'function') return props.field.vIf(fieldData, props.modelValue as T)
|
|
126
|
+
return true
|
|
127
|
+
})
|
|
128
|
+
|
|
129
|
+
const computedOptions = $computed(
|
|
130
|
+
() => bindAttrs({ options: props.field.options }, fieldData, props.modelValue).options
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
const computedAttrs = $computed(() => {
|
|
134
|
+
const attrs = { ...customAttrs, ...props.field.attrs }
|
|
135
|
+
return bindAttrs(attrs, fieldData, props.modelValue)
|
|
136
|
+
})
|
|
137
|
+
|
|
138
|
+
const computedClass = $computed(
|
|
139
|
+
() => classify(fieldData, props.modelValue, props.field.class, props.field.attrs?.class)
|
|
140
|
+
)
|
|
141
|
+
</script>
|
|
142
|
+
|
|
143
|
+
<template>
|
|
144
|
+
<component
|
|
145
|
+
v-bind="computedAttrs"
|
|
146
|
+
:is="is"
|
|
147
|
+
v-if="vIf"
|
|
148
|
+
:id="props.id"
|
|
149
|
+
v-model="fieldData"
|
|
150
|
+
:required="field.required"
|
|
151
|
+
:class="computedClass"
|
|
152
|
+
:label="field.label"
|
|
153
|
+
:placeholder="field.placeholder || field.label"
|
|
154
|
+
:defaultValue="field.defaultValue"
|
|
155
|
+
:disabled="field.disabled"
|
|
156
|
+
:options="computedOptions"
|
|
157
|
+
:helptext="field.helptext"
|
|
158
|
+
:schema="field.attrs?.schema ?? undefined"
|
|
159
|
+
>
|
|
160
|
+
<template v-if="field.$el === 'form'">
|
|
161
|
+
<slot />
|
|
162
|
+
</template>
|
|
163
|
+
<template v-else>
|
|
164
|
+
{{ fieldData }}
|
|
165
|
+
<BglComponent
|
|
166
|
+
v-for="(child, ii) in field.children"
|
|
167
|
+
:id="[props.id, child.id].filter(Boolean).join('.')"
|
|
168
|
+
:key="child.id || ii"
|
|
169
|
+
:field="child"
|
|
170
|
+
:parent-path="props.id"
|
|
171
|
+
/>
|
|
172
|
+
</template>
|
|
173
|
+
</component>
|
|
174
|
+
</template>
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
<script lang="ts" setup>
|
|
2
|
+
defineProps<{
|
|
3
|
+
label?: string
|
|
4
|
+
legend?: string
|
|
5
|
+
}>()
|
|
6
|
+
</script>
|
|
7
|
+
|
|
8
|
+
<template>
|
|
9
|
+
<fieldset class="px-1 pt-025 pb-1">
|
|
10
|
+
<legend class="ms-1">
|
|
11
|
+
{{ legend || label }}
|
|
12
|
+
</legend>
|
|
13
|
+
<slot />
|
|
14
|
+
</fieldset>
|
|
15
|
+
</template>
|
|
16
|
+
|
|
17
|
+
<style scoped>
|
|
18
|
+
fieldset {
|
|
19
|
+
border: 1px solid var(--border-color);
|
|
20
|
+
border-radius: var(--card-border-radius);
|
|
21
|
+
padding: var(--space-md);
|
|
22
|
+
}
|
|
23
|
+
</style>
|
package/src/components/Pill.vue
CHANGED
|
@@ -20,6 +20,7 @@ const props = defineProps<{
|
|
|
20
20
|
outline?: boolean
|
|
21
21
|
loading?: boolean
|
|
22
22
|
value?: string
|
|
23
|
+
modelValue?: string
|
|
23
24
|
round?: boolean
|
|
24
25
|
btn?: BtnProp
|
|
25
26
|
btnEnd?: BtnProp
|
|
@@ -91,8 +92,8 @@ const computedBackgroundColor = $computed(
|
|
|
91
92
|
</div>
|
|
92
93
|
<MaterialIcon v-if="icon" :icon="icon" />
|
|
93
94
|
<slot />
|
|
94
|
-
<template v-if="!slots.default && value">
|
|
95
|
-
{{ value }}
|
|
95
|
+
<template v-if="!slots.default && (value)">
|
|
96
|
+
{{ value || modelValue }}
|
|
96
97
|
</template>
|
|
97
98
|
<MaterialIcon v-if="iconEnd" :icon="iconEnd" />
|
|
98
99
|
<div v-if="loading" class="loading" />
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<script setup lang="ts" generic="T extends Record<string, any>">
|
|
2
2
|
import {
|
|
3
|
-
|
|
3
|
+
BglComponent,
|
|
4
4
|
type BglFormSchemaT,
|
|
5
5
|
MaterialIcon,
|
|
6
6
|
isDate,
|
|
@@ -272,7 +272,8 @@ watch(
|
|
|
272
272
|
:field
|
|
273
273
|
/>
|
|
274
274
|
<div v-else>
|
|
275
|
-
<
|
|
275
|
+
<BglComponent
|
|
276
|
+
:id="field.id"
|
|
276
277
|
class="embedded-field"
|
|
277
278
|
:field
|
|
278
279
|
:modelValue="row"
|
|
@@ -11,23 +11,27 @@ import {
|
|
|
11
11
|
ToggleInput,
|
|
12
12
|
bindAttrs,
|
|
13
13
|
classify,
|
|
14
|
-
BagelForm,
|
|
15
14
|
NumberInput,
|
|
16
15
|
UploadInput,
|
|
16
|
+
type BagelFormState,
|
|
17
|
+
BglForm
|
|
17
18
|
} from '@bagelink/vue'
|
|
19
|
+
import { inject } from 'vue'
|
|
18
20
|
import TabsNav from '../layout/TabsNav.vue'
|
|
21
|
+
import { FORM_STATE_KEY } from './useBagelFormState'
|
|
19
22
|
|
|
20
|
-
const props =
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
23
|
+
const props = defineProps<{
|
|
24
|
+
field: Field<T>
|
|
25
|
+
id?: string
|
|
26
|
+
modelValue?: any
|
|
27
|
+
parentPath?: string
|
|
28
|
+
}>()
|
|
29
|
+
|
|
30
|
+
const emit = defineEmits<{
|
|
31
|
+
'update:modelValue': [value: any]
|
|
32
|
+
}>()
|
|
29
33
|
|
|
30
|
-
const
|
|
34
|
+
const formState = inject<BagelFormState<T>>(FORM_STATE_KEY)
|
|
31
35
|
|
|
32
36
|
const customAttrs = $ref<{ [key: string]: any }>({})
|
|
33
37
|
|
|
@@ -47,90 +51,54 @@ const is = $computed(() => {
|
|
|
47
51
|
if (props.field.$el === 'file') return FileUpload
|
|
48
52
|
if (props.field.$el === 'date') return DateInput
|
|
49
53
|
if (props.field.$el === 'tabs') return TabsNav
|
|
50
|
-
if (props.field.$el === 'form') return
|
|
54
|
+
if (props.field.$el === 'form') return BglForm
|
|
51
55
|
return props.field.$el ?? 'div'
|
|
52
56
|
})
|
|
53
57
|
|
|
54
|
-
const
|
|
55
|
-
get: () =>
|
|
56
|
-
|
|
57
|
-
|
|
58
|
+
const fieldData = $computed({
|
|
59
|
+
get: () => {
|
|
60
|
+
if (!props.id) return props.field.defaultValue ?? (props.field.$el === 'form' ? {} : '')
|
|
61
|
+
const value = formState?.getFieldData(props.id)
|
|
62
|
+
if (props.field.$el === 'form' && !value) return {}
|
|
63
|
+
return value ?? ''
|
|
58
64
|
},
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
const
|
|
62
|
-
|
|
63
|
-
function setFieldData(key: string, val: any) {
|
|
64
|
-
const data = { ...props.modelValue }
|
|
65
|
-
const keys = key.split(objPathRegex)
|
|
66
|
-
let temp = data
|
|
67
|
-
for (let i = 0; i < keys.length - 1; i++) {
|
|
68
|
-
if (!temp[keys[i]]) {
|
|
69
|
-
temp[keys[i]] = {}
|
|
70
|
-
}
|
|
71
|
-
temp = temp[keys[i]]
|
|
72
|
-
}
|
|
73
|
-
temp[keys[keys.length - 1]] = val
|
|
74
|
-
return data
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
const isForm = $computed(() => props.field.$el === 'form' || props.field.$el === BagelForm)
|
|
65
|
+
set: (val: any) => {
|
|
66
|
+
if (!props.id) return
|
|
67
|
+
const currentValue = formState?.getFieldData(props.id)
|
|
68
|
+
if (JSON.stringify(val) === JSON.stringify(currentValue)) return
|
|
78
69
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
let result = obj
|
|
83
|
-
for (const k of keys) {
|
|
84
|
-
if (result && k in result) {
|
|
85
|
-
result = result[k]
|
|
86
|
-
} else {
|
|
87
|
-
return undefined
|
|
70
|
+
emit('update:modelValue', val)
|
|
71
|
+
if (props.field.onUpdate) {
|
|
72
|
+
props.field.onUpdate(val, currentValue)
|
|
88
73
|
}
|
|
74
|
+
formState?.updateField(props.id, val)
|
|
89
75
|
}
|
|
90
|
-
return result
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
const fieldData = $computed({
|
|
94
|
-
set: (val: any) => {
|
|
95
|
-
if (isForm) {
|
|
96
|
-
emit('update:modelValue', val)
|
|
97
|
-
return
|
|
98
|
-
}
|
|
99
|
-
if (!props.field.id) return
|
|
100
|
-
const data = setFieldData(props.field.id, val)
|
|
101
|
-
emit('update:modelValue', data)
|
|
102
|
-
},
|
|
103
|
-
get: () => {
|
|
104
|
-
if (props.field.id) return getFieldData(props.modelValue, props.field.id)
|
|
105
|
-
if (isForm) return props.modelValue
|
|
106
|
-
return props.field.defaultValue ?? ''
|
|
107
|
-
},
|
|
108
76
|
})
|
|
109
77
|
|
|
110
78
|
const vIf = $computed(() => {
|
|
111
79
|
if (props.field['v-if'] === undefined && props.field.vIf === undefined) return true
|
|
112
80
|
if (typeof props.field['v-if'] === 'boolean' || typeof props.field.vIf === 'boolean') return props.field['v-if']
|
|
113
81
|
if (typeof props.field['v-if'] === 'string' || typeof props.field.vIf === 'string') return true
|
|
114
|
-
if (typeof props.field['v-if'] === 'function') return props.field['v-if'](fieldData,
|
|
115
|
-
if (typeof props.field.vIf === 'function') return props.field.vIf(fieldData,
|
|
82
|
+
if (typeof props.field['v-if'] === 'function') return props.field['v-if'](fieldData, formState?.data.value as T)
|
|
83
|
+
if (typeof props.field.vIf === 'function') return props.field.vIf(fieldData, formState?.data.value as T)
|
|
116
84
|
return true
|
|
117
85
|
})
|
|
118
86
|
|
|
119
87
|
const computedFieldData = $computed(
|
|
120
|
-
() => props.field.transform?.(fieldData,
|
|
88
|
+
() => props.field.transform?.(fieldData, formState?.data.value as T) ?? fieldData
|
|
121
89
|
)
|
|
122
90
|
|
|
123
91
|
const computedOptions = $computed(
|
|
124
|
-
() => bindAttrs({ options: props.field.options }, fieldData,
|
|
92
|
+
() => bindAttrs({ options: props.field.options }, fieldData, formState?.data.value).options
|
|
125
93
|
)
|
|
126
94
|
|
|
127
95
|
const computedAttrs = $computed(() => {
|
|
128
96
|
const attrs = { ...customAttrs, ...props.field.attrs }
|
|
129
|
-
return bindAttrs(attrs, fieldData,
|
|
97
|
+
return bindAttrs(attrs, fieldData, formState?.data.value)
|
|
130
98
|
})
|
|
131
99
|
|
|
132
100
|
const computedClass = $computed(
|
|
133
|
-
() => classify(fieldData,
|
|
101
|
+
() => classify(fieldData, formState?.data.value, props.field.class, props.field.attrs?.class)
|
|
134
102
|
)
|
|
135
103
|
</script>
|
|
136
104
|
|
|
@@ -139,7 +107,7 @@ const computedClass = $computed(
|
|
|
139
107
|
v-bind="computedAttrs"
|
|
140
108
|
:is="is"
|
|
141
109
|
v-if="vIf"
|
|
142
|
-
:id="
|
|
110
|
+
:id="props.id"
|
|
143
111
|
v-model="fieldData"
|
|
144
112
|
:required="field.required"
|
|
145
113
|
:class="computedClass"
|
|
@@ -149,14 +117,19 @@ const computedClass = $computed(
|
|
|
149
117
|
:disabled="field.disabled"
|
|
150
118
|
:options="computedOptions"
|
|
151
119
|
:helptext="field.helptext"
|
|
152
|
-
|
|
120
|
+
:schema="field.attrs?.schema ?? undefined"
|
|
153
121
|
>
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
122
|
+
<template v-if="field.$el === 'form'">
|
|
123
|
+
<slot />
|
|
124
|
+
</template>
|
|
125
|
+
<template v-else>
|
|
126
|
+
<BglField
|
|
127
|
+
v-for="(child, ii) in field.children"
|
|
128
|
+
:id="[props.id, child.id].filter(Boolean).join('.')"
|
|
129
|
+
:key="child.id || ii"
|
|
130
|
+
:field="child"
|
|
131
|
+
:parent-path="props.id"
|
|
132
|
+
/>
|
|
133
|
+
</template>
|
|
161
134
|
</component>
|
|
162
135
|
</template>
|
|
@@ -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
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
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
|
-
|
|
51
|
+
emit('update:modelValue', newVal)
|
|
37
52
|
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
get: () => formData,
|
|
42
|
-
})
|
|
53
|
+
}, { deep: true })
|
|
54
|
+
}
|
|
55
|
+
|
|
43
56
|
const form = $ref<HTMLFormElement>()
|
|
44
57
|
|
|
45
58
|
function validateForm() {
|
|
46
|
-
|
|
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
|
-
|
|
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
|
-
|
|
70
|
-
|
|
71
|
-
|
|
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
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
//
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
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
|
-
|
|
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-
|
|
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 (
|
|
51
|
-
|
|
52
|
-
|
|
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
|
-
|
|
58
|
-
|
|
59
|
-
|
|
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) {
|