@veltra/desktop 1.1.35 → 1.2.0
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/action/action-group.vue.d.ts +2 -2
- package/dist/components/action/action.vue.d.ts +1 -1
- package/dist/components/auto-complete/auto-complete.js +1 -0
- package/dist/components/auto-complete/auto-complete.js.map +1 -1
- package/dist/components/batch-edit/batch-edit-form.js +12 -5
- package/dist/components/batch-edit/batch-edit-form.js.map +1 -1
- package/dist/components/batch-edit/batch-edit.js +8 -3
- package/dist/components/batch-edit/batch-edit.js.map +1 -1
- package/dist/components/batch-edit/batch-edit.vue.d.ts +40 -35
- package/dist/components/batch-edit/di.js.map +1 -1
- package/dist/components/batch-edit/use-edit.js +41 -23
- package/dist/components/batch-edit/use-edit.js.map +1 -1
- package/dist/components/cascade/cascade.js +1 -0
- package/dist/components/cascade/cascade.js.map +1 -1
- package/dist/components/cascade/cascade.vue.d.ts +5 -5
- package/dist/components/checkbox/checkbox-button.js +1 -0
- package/dist/components/checkbox/checkbox-button.js.map +1 -1
- package/dist/components/checkbox/checkbox-button.vue.d.ts +1 -1
- package/dist/components/checkbox/checkbox.js +1 -0
- package/dist/components/checkbox/checkbox.js.map +1 -1
- package/dist/components/checkbox-group/checkbox-group.js +1 -0
- package/dist/components/checkbox-group/checkbox-group.js.map +1 -1
- package/dist/components/checkbox-group/checkbox-group.vue.d.ts +2 -2
- package/dist/components/code-editor/code-editor.js +1 -0
- package/dist/components/code-editor/code-editor.js.map +1 -1
- package/dist/components/condition-editor/core/evaluator.js +3 -3
- package/dist/components/condition-editor/core/evaluator.js.map +1 -1
- package/dist/components/date-panel/date-panel.vue.d.ts +1 -1
- package/dist/components/date-picker/date-picker.js +1 -0
- package/dist/components/date-picker/date-picker.js.map +1 -1
- package/dist/components/date-picker/date-picker.vue.d.ts +1 -1
- package/dist/components/date-range-picker/date-range-picker.js +2 -0
- package/dist/components/date-range-picker/date-range-picker.js.map +1 -1
- package/dist/components/date-range-picker/date-range-picker.vue.d.ts +1 -1
- package/dist/components/dialog/use-maximum.js +7 -1
- package/dist/components/dialog/use-maximum.js.map +1 -1
- package/dist/components/empty/empty.vue.d.ts +1 -1
- package/dist/components/expression-editor/expression-editor.js +1 -0
- package/dist/components/expression-editor/expression-editor.js.map +1 -1
- package/dist/components/file-picker/file-picker.js +1 -0
- package/dist/components/file-picker/file-picker.js.map +1 -1
- package/dist/components/form/form.js.map +1 -1
- package/dist/components/form/form.vue.d.ts +11 -19
- package/dist/components/form/form.vue_vue_type_script_setup_true_lang.js +24 -26
- package/dist/components/form/form.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/form/index.d.ts +0 -3
- package/dist/components/form/use-form-fields.js +88 -0
- package/dist/components/form/use-form-fields.js.map +1 -0
- package/dist/components/form/use-node-interceptor.js +19 -30
- package/dist/components/form/use-node-interceptor.js.map +1 -1
- package/dist/components/form-item/form-item.js.map +1 -1
- package/dist/components/form-item/form-item.vue_vue_type_script_setup_true_lang.js +44 -18
- package/dist/components/form-item/form-item.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/form-item/helper.js +4 -1
- package/dist/components/form-item/helper.js.map +1 -1
- package/dist/components/form-item/validate.d.ts +26 -0
- package/dist/components/form-item/validate.js +97 -0
- package/dist/components/form-item/validate.js.map +1 -0
- package/dist/components/group-input/group-input.js +1 -0
- package/dist/components/group-input/group-input.js.map +1 -1
- package/dist/components/index.d.ts +0 -3
- package/dist/components/index.js +0 -7
- package/dist/components/input/input.vue_vue_type_script_setup_true_lang.js +1 -0
- package/dist/components/input/input.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/loading/style2.css +90 -159
- package/dist/components/multi-select/multi-select.js +1 -0
- package/dist/components/multi-select/multi-select.js.map +1 -1
- package/dist/components/multi-select/multi-select.vue.d.ts +3 -3
- package/dist/components/multi-tree-select/multi-tree-select.js +1 -0
- package/dist/components/multi-tree-select/multi-tree-select.js.map +1 -1
- package/dist/components/multi-tree-select/multi-tree-select.vue.d.ts +4 -4
- package/dist/components/number-input/number-input.js +1 -0
- package/dist/components/number-input/number-input.js.map +1 -1
- package/dist/components/number-range-input/number-range-input.js +1 -0
- package/dist/components/number-range-input/number-range-input.js.map +1 -1
- package/dist/components/palette/palette.js +1 -0
- package/dist/components/palette/palette.js.map +1 -1
- package/dist/components/password-input/password-input.js +1 -0
- package/dist/components/password-input/password-input.js.map +1 -1
- package/dist/components/pop-confirm/pop-confirm.vue.d.ts +1 -1
- package/dist/components/radio/radio.js +1 -0
- package/dist/components/radio/radio.js.map +1 -1
- package/dist/components/radio-group/radio-group.js +1 -0
- package/dist/components/radio-group/radio-group.js.map +1 -1
- package/dist/components/radio-group/radio-group.vue.d.ts +2 -2
- package/dist/components/rich-text-editor/rich-text-editor.js +3 -2
- package/dist/components/rich-text-editor/rich-text-editor.js.map +1 -1
- package/dist/components/rich-text-editor/toolbar.js +10 -7
- package/dist/components/rich-text-editor/toolbar.js.map +1 -1
- package/dist/components/select/select.js +6 -3
- package/dist/components/select/select.js.map +1 -1
- package/dist/components/select/select.vue.d.ts +2 -2
- package/dist/components/slider/slider.js +15 -2
- package/dist/components/slider/slider.js.map +1 -1
- package/dist/components/steps/steps.vue.d.ts +1 -1
- package/dist/components/switch/switch.js +1 -0
- package/dist/components/switch/switch.js.map +1 -1
- package/dist/components/table/style2.css +4 -7
- package/dist/components/textarea/textarea.js +1 -0
- package/dist/components/textarea/textarea.js.map +1 -1
- package/dist/components/tip/tip.vue.d.ts +1 -1
- package/dist/components/tree-select/tree-select.js +1 -0
- package/dist/components/tree-select/tree-select.js.map +1 -1
- package/dist/components/tree-select/tree-select.vue.d.ts +4 -4
- package/dist/components/watermark/watermark.vue.d.ts +1 -1
- package/dist/index.d.ts +5 -6
- package/dist/index.js +1 -4
- package/dist/types/auto-complete.d.ts +3 -2
- package/dist/types/batch-edit.d.ts +4 -5
- package/dist/types/cascade.d.ts +3 -2
- package/dist/types/checkbox-group.d.ts +2 -2
- package/dist/types/checkbox.d.ts +4 -3
- package/dist/types/code-editor.d.ts +3 -2
- package/dist/types/date-picker.d.ts +3 -2
- package/dist/types/date-range-picker.d.ts +3 -2
- package/dist/types/expression-editor.d.ts +3 -2
- package/dist/types/file-picker.d.ts +3 -2
- package/dist/types/form-field.d.ts +12 -0
- package/dist/types/form-item.d.ts +2 -2
- package/dist/types/form.d.ts +9 -48
- package/dist/types/group-input.d.ts +3 -2
- package/dist/types/index.d.ts +4 -2
- package/dist/types/input.d.ts +3 -2
- package/dist/types/loading.d.ts +1 -1
- package/dist/types/multi-select.d.ts +3 -2
- package/dist/types/multi-tree-select.d.ts +3 -2
- package/dist/types/palette.d.ts +3 -2
- package/dist/types/radio-group.d.ts +3 -2
- package/dist/types/radio.d.ts +3 -2
- package/dist/types/rich-text-editor.d.ts +3 -2
- package/dist/types/select.d.ts +3 -2
- package/dist/types/slider.d.ts +3 -2
- package/dist/types/switch.d.ts +3 -2
- package/dist/types/text-editor.d.ts +3 -2
- package/dist/types/textarea.d.ts +3 -2
- package/dist/types/tree-select.d.ts +3 -2
- package/package.json +6 -6
- package/src/components/batch-edit/batch-edit-form.vue +20 -13
- package/src/components/batch-edit/batch-edit.vue +7 -8
- package/src/components/batch-edit/di.ts +1 -2
- package/src/components/batch-edit/use-edit.ts +58 -36
- package/src/components/date-range-picker/date-range-picker.vue +2 -0
- package/src/components/dialog/use-maximum.ts +8 -1
- package/src/components/form/form.vue +22 -38
- package/src/components/form/index.ts +0 -6
- package/src/components/form/use-form-fields.ts +126 -0
- package/src/components/form/use-node-interceptor.ts +27 -56
- package/src/components/form-item/form-item.vue +69 -18
- package/src/components/form-item/helper.ts +10 -4
- package/src/components/form-item/validate.ts +155 -0
- package/src/components/loading/style.scss +126 -355
- package/src/components/rich-text-editor/rich-text-editor.vue +28 -25
- package/src/components/rich-text-editor/toolbar.vue +23 -19
- package/src/components/select/select.vue +6 -4
- package/src/components/slider/slider.vue +12 -2
- package/src/components/table/style.scss +4 -14
- package/src/types/auto-complete.ts +4 -2
- package/src/types/batch-edit.ts +4 -5
- package/src/types/cascade.ts +4 -2
- package/src/types/checkbox-group.ts +2 -2
- package/src/types/checkbox.ts +5 -3
- package/src/types/code-editor.ts +4 -2
- package/src/types/date-picker.ts +4 -2
- package/src/types/date-range-picker.ts +4 -2
- package/src/types/expression-editor.ts +4 -2
- package/src/types/file-picker.ts +4 -2
- package/src/types/form-field.ts +11 -0
- package/src/types/form-item.ts +2 -2
- package/src/types/form.ts +9 -82
- package/src/types/group-input.ts +4 -2
- package/src/types/index.ts +1 -0
- package/src/types/input.ts +4 -2
- package/src/types/loading.ts +1 -1
- package/src/types/multi-select.ts +4 -2
- package/src/types/multi-tree-select.ts +5 -2
- package/src/types/palette.ts +4 -2
- package/src/types/radio-group.ts +4 -2
- package/src/types/radio.ts +4 -2
- package/src/types/rich-text-editor.ts +4 -2
- package/src/types/select.ts +4 -2
- package/src/types/slider.ts +4 -2
- package/src/types/switch.ts +4 -2
- package/src/types/text-editor.ts +4 -2
- package/src/types/textarea.ts +4 -2
- package/src/types/tree-select.ts +5 -2
- package/dist/components/form/dynamic-form-model.d.ts +0 -73
- package/dist/components/form/dynamic-form-model.js +0 -184
- package/dist/components/form/dynamic-form-model.js.map +0 -1
- package/dist/components/form/form-model.d.ts +0 -73
- package/dist/components/form/form-model.js +0 -179
- package/dist/components/form/form-model.js.map +0 -1
- package/dist/components/form/helper.d.ts +0 -16
- package/dist/components/form/helper.js +0 -20
- package/dist/components/form/helper.js.map +0 -1
- package/src/components/form/__test__/form-model.test.ts +0 -190
- package/src/components/form/dynamic-form-model.ts +0 -258
- package/src/components/form/form-model.ts +0 -255
- package/src/components/form/helper.ts +0 -23
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"expression-editor.js","names":[],"sources":["../../../src/components/expression-editor/expression-editor.vue"],"sourcesContent":["<template>\n <div :class=\"className\">\n <div\n ref=\"container\"\n :class=\"cls.e('container')\"\n :contenteditable=\"!readonly && !disabled\"\n :data-empty=\"isEmpty || undefined\"\n :data-placeholder=\"props.placeholder\"\n @keydown=\"onKeydown\"\n @blur=\"onBlur\"\n ></div>\n\n <div v-if=\"showPlaceholder\" :class=\"cls.e('placeholder')\">\n {{ props.placeholder }}\n </div>\n\n <VariablePicker\n ref=\"pickerRef\"\n :visible=\"pickerVisible\"\n :trigger-dom=\"pickerTriggerDom\"\n :variables=\"props.variables\"\n :filter=\"pickerFilter\"\n :selectable-levels=\"props.selectableLevels ?? 'leaf'\"\n @select=\"onPickerSelect\"\n @dismiss=\"onPickerDismiss\"\n @update:visible=\"onPickerVisibleChange\"\n />\n </div>\n</template>\n\n<script lang=\"ts\" setup>\nimport { useFormFallbackProps } from '@veltra/compositions'\nimport { bem } from '@veltra/utils'\nimport { injectFormContext } from '@veltra/utils'\nimport {\n computed,\n nextTick,\n onBeforeUnmount,\n onMounted,\n shallowRef,\n useTemplateRef,\n watch\n} from 'vue'\n\nimport type { ExpressionEditorProps, VariableItem } from '../../types'\nimport VariablePicker from './components/variable-picker.vue'\nimport { createEditor, type EditorAPI } from './core/editor'\nimport { createMention, type MentionAPI } from './core/mention'\nimport { parse, type Doc } from './core/model'\nimport { createVariableMap } from './di'\n\ndefineOptions({ name: 'ExpressionEditor' })\n\nconst props = withDefaults(defineProps<ExpressionEditorProps>(), {\n placeholder: '请输入表达式,输入 @ 可插入变量',\n selectableLevels: 'leaf'\n})\n\nconst emit = defineEmits<{ (e: 'update:modelValue', value: string): void }>()\n\nconst cls = bem('expression-editor')\nconst { formProps } = injectFormContext()\nconst { size, disabled, readonly } = useFormFallbackProps([formProps ?? {}, props])\n\nconst containerRef = useTemplateRef<HTMLDivElement>('container')\nconst pickerRef = useTemplateRef<{ handleKeydown: (e: KeyboardEvent) => boolean }>('pickerRef')\n\nconst className = computed(() => [\n cls.b,\n cls.m(size.value),\n bem.is('disabled', disabled.value),\n bem.is('readonly', readonly.value)\n])\n\nconst variableMap = computed(() => createVariableMap(props.variables))\n\nconst editorRef = shallowRef<EditorAPI | null>(null)\nconst mention: MentionAPI = createMention()\n\nconst currentDoc = shallowRef<Doc>([])\nconst isEmpty = computed(() => currentDoc.value.length === 0)\nconst showPlaceholder = computed(() => isEmpty.value && !disabled.value)\n\nconst pickerMode = shallowRef<'mention' | 'reselect' | null>(null)\nconst pickerTriggerDom = shallowRef<HTMLElement | undefined>(undefined)\nconst reselectingSegIdx = shallowRef<number | null>(null)\nconst pickerFilter = shallowRef('')\n\nconst pickerVisible = computed(() => pickerMode.value !== null)\n\nfunction syncMention() {\n const editor = editorRef.value\n if (!editor) return\n if (pickerMode.value === 'reselect') return\n const caret = editor.getCaretOffset()\n const state = mention.update(currentDoc.value, caret)\n if (state) {\n pickerMode.value = 'mention'\n pickerFilter.value = state.filter\n pickerTriggerDom.value = containerRef.value ?? undefined\n } else if (pickerMode.value === 'mention') {\n closePicker()\n }\n}\n\nfunction closePicker() {\n pickerMode.value = null\n reselectingSegIdx.value = null\n pickerFilter.value = ''\n}\n\nonMounted(() => {\n if (!containerRef.value) return\n const initialDoc = parse(props.modelValue ?? '', variableMap.value)\n currentDoc.value = initialDoc\n\n const editor = createEditor({\n container: containerRef.value,\n cls,\n initialDoc,\n getVariableMap: () => variableMap.value,\n onChange: (doc) => {\n currentDoc.value = doc\n const value = serializeFromDoc(doc)\n if (value !== (props.modelValue ?? '')) emit('update:modelValue', value)\n syncMention()\n },\n onSelectionChange: () => {\n syncMention()\n },\n onChipReselect: ({ chipEl, segIndex }) => {\n if (disabled.value || readonly.value) return\n mention.commit()\n pickerMode.value = 'reselect'\n pickerFilter.value = ''\n pickerTriggerDom.value = chipEl\n reselectingSegIdx.value = segIndex\n },\n onChipRemove: ({ segIndex }) => {\n if (disabled.value || readonly.value) return\n editor.removeVarAt(segIndex)\n }\n })\n editorRef.value = editor\n})\n\nonBeforeUnmount(() => {\n editorRef.value?.dispose()\n})\n\nfunction serializeFromDoc(doc: Doc): string {\n let s = ''\n for (const seg of doc) s += seg.kind === 'text' ? seg.value : `{${seg.value}}`\n return s\n}\n\nwatch(\n () => props.modelValue,\n (v) => {\n const editor = editorRef.value\n if (!editor) return\n if (v === editor.getValue()) return\n editor.setValue(v ?? '')\n }\n)\n\nwatch(variableMap, () => {\n // variables 变化:重渲染以刷新 chip label / type\n const editor = editorRef.value\n if (!editor) return\n editor.setValue(editor.getValue())\n})\n\nfunction onKeydown(e: KeyboardEvent) {\n if (disabled.value || readonly.value) return\n // mention / reselect 激活时,优先把箭头键 / Enter / Esc 转给 picker\n if (pickerMode.value !== null) {\n const handledByPicker = pickerRef.value?.handleKeydown(e)\n if (handledByPicker) {\n e.preventDefault()\n return\n }\n }\n\n if (pickerMode.value === 'mention') {\n // 这些键导致 mention 退出(保留 @filter 文本,光标继续移动)\n if (e.key === ' ' || e.key === 'ArrowLeft' || e.key === 'ArrowRight') {\n mention.dismiss()\n closePicker()\n }\n }\n}\n\nfunction onBlur() {\n if (pickerMode.value === 'mention') {\n mention.dismiss()\n // 下一帧再关闭,避免和 picker 内 click 冲突\n void nextTick(() => closePicker())\n }\n}\n\nfunction onPickerSelect(item: VariableItem) {\n const editor = editorRef.value\n if (!editor) return\n\n if (pickerMode.value === 'mention') {\n const state = mention.getState()\n if (!state) return\n const anchor = state.anchorOffset\n const caret = editor.getCaretOffset() ?? anchor + state.filter.length + 1\n editor.replaceRangeWithVar(anchor, caret, {\n value: item.value,\n label: item.label,\n ...(item.type ? { type: item.type } : {})\n })\n mention.commit()\n } else if (pickerMode.value === 'reselect') {\n const idx = reselectingSegIdx.value\n if (idx !== null) {\n editor.replaceVarAt(idx, {\n value: item.value,\n label: item.label,\n ...(item.type ? { type: item.type } : {})\n })\n }\n }\n closePicker()\n}\n\nfunction onPickerDismiss() {\n if (pickerMode.value === 'mention') mention.dismiss()\n closePicker()\n}\n\nfunction onPickerVisibleChange(v: boolean) {\n if (!v && pickerMode.value !== null) {\n if (pickerMode.value === 'mention') mention.dismiss()\n closePicker()\n }\n}\n</script>\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"expression-editor.js","names":[],"sources":["../../../src/components/expression-editor/expression-editor.vue"],"sourcesContent":["<template>\n <div :class=\"className\">\n <div\n ref=\"container\"\n :class=\"cls.e('container')\"\n :contenteditable=\"!readonly && !disabled\"\n :data-empty=\"isEmpty || undefined\"\n :data-placeholder=\"props.placeholder\"\n @keydown=\"onKeydown\"\n @blur=\"onBlur\"\n ></div>\n\n <div v-if=\"showPlaceholder\" :class=\"cls.e('placeholder')\">\n {{ props.placeholder }}\n </div>\n\n <VariablePicker\n ref=\"pickerRef\"\n :visible=\"pickerVisible\"\n :trigger-dom=\"pickerTriggerDom\"\n :variables=\"props.variables\"\n :filter=\"pickerFilter\"\n :selectable-levels=\"props.selectableLevels ?? 'leaf'\"\n @select=\"onPickerSelect\"\n @dismiss=\"onPickerDismiss\"\n @update:visible=\"onPickerVisibleChange\"\n />\n </div>\n</template>\n\n<script lang=\"ts\" setup>\nimport { useFormFallbackProps } from '@veltra/compositions'\nimport { bem } from '@veltra/utils'\nimport { injectFormContext } from '@veltra/utils'\nimport {\n computed,\n nextTick,\n onBeforeUnmount,\n onMounted,\n shallowRef,\n useTemplateRef,\n watch\n} from 'vue'\n\nimport type { ExpressionEditorProps, VariableItem } from '../../types'\nimport VariablePicker from './components/variable-picker.vue'\nimport { createEditor, type EditorAPI } from './core/editor'\nimport { createMention, type MentionAPI } from './core/mention'\nimport { parse, type Doc } from './core/model'\nimport { createVariableMap } from './di'\n\ndefineOptions({ name: 'ExpressionEditor' })\n\nconst props = withDefaults(defineProps<ExpressionEditorProps>(), {\n placeholder: '请输入表达式,输入 @ 可插入变量',\n selectableLevels: 'leaf'\n})\n\nconst emit = defineEmits<{ (e: 'update:modelValue', value: string): void }>()\n\nconst cls = bem('expression-editor')\nconst { formProps } = injectFormContext()\nconst { size, disabled, readonly } = useFormFallbackProps([formProps ?? {}, props])\n\nconst containerRef = useTemplateRef<HTMLDivElement>('container')\nconst pickerRef = useTemplateRef<{ handleKeydown: (e: KeyboardEvent) => boolean }>('pickerRef')\n\nconst className = computed(() => [\n cls.b,\n cls.m(size.value),\n bem.is('disabled', disabled.value),\n bem.is('readonly', readonly.value)\n])\n\nconst variableMap = computed(() => createVariableMap(props.variables))\n\nconst editorRef = shallowRef<EditorAPI | null>(null)\nconst mention: MentionAPI = createMention()\n\nconst currentDoc = shallowRef<Doc>([])\nconst isEmpty = computed(() => currentDoc.value.length === 0)\nconst showPlaceholder = computed(() => isEmpty.value && !disabled.value)\n\nconst pickerMode = shallowRef<'mention' | 'reselect' | null>(null)\nconst pickerTriggerDom = shallowRef<HTMLElement | undefined>(undefined)\nconst reselectingSegIdx = shallowRef<number | null>(null)\nconst pickerFilter = shallowRef('')\n\nconst pickerVisible = computed(() => pickerMode.value !== null)\n\nfunction syncMention() {\n const editor = editorRef.value\n if (!editor) return\n if (pickerMode.value === 'reselect') return\n const caret = editor.getCaretOffset()\n const state = mention.update(currentDoc.value, caret)\n if (state) {\n pickerMode.value = 'mention'\n pickerFilter.value = state.filter\n pickerTriggerDom.value = containerRef.value ?? undefined\n } else if (pickerMode.value === 'mention') {\n closePicker()\n }\n}\n\nfunction closePicker() {\n pickerMode.value = null\n reselectingSegIdx.value = null\n pickerFilter.value = ''\n}\n\nonMounted(() => {\n if (!containerRef.value) return\n const initialDoc = parse(props.modelValue ?? '', variableMap.value)\n currentDoc.value = initialDoc\n\n const editor = createEditor({\n container: containerRef.value,\n cls,\n initialDoc,\n getVariableMap: () => variableMap.value,\n onChange: (doc) => {\n currentDoc.value = doc\n const value = serializeFromDoc(doc)\n if (value !== (props.modelValue ?? '')) emit('update:modelValue', value)\n syncMention()\n },\n onSelectionChange: () => {\n syncMention()\n },\n onChipReselect: ({ chipEl, segIndex }) => {\n if (disabled.value || readonly.value) return\n mention.commit()\n pickerMode.value = 'reselect'\n pickerFilter.value = ''\n pickerTriggerDom.value = chipEl\n reselectingSegIdx.value = segIndex\n },\n onChipRemove: ({ segIndex }) => {\n if (disabled.value || readonly.value) return\n editor.removeVarAt(segIndex)\n }\n })\n editorRef.value = editor\n})\n\nonBeforeUnmount(() => {\n editorRef.value?.dispose()\n})\n\nfunction serializeFromDoc(doc: Doc): string {\n let s = ''\n for (const seg of doc) s += seg.kind === 'text' ? seg.value : `{${seg.value}}`\n return s\n}\n\nwatch(\n () => props.modelValue,\n (v) => {\n const editor = editorRef.value\n if (!editor) return\n if (v === editor.getValue()) return\n editor.setValue(v ?? '')\n }\n)\n\nwatch(variableMap, () => {\n // variables 变化:重渲染以刷新 chip label / type\n const editor = editorRef.value\n if (!editor) return\n editor.setValue(editor.getValue())\n})\n\nfunction onKeydown(e: KeyboardEvent) {\n if (disabled.value || readonly.value) return\n // mention / reselect 激活时,优先把箭头键 / Enter / Esc 转给 picker\n if (pickerMode.value !== null) {\n const handledByPicker = pickerRef.value?.handleKeydown(e)\n if (handledByPicker) {\n e.preventDefault()\n return\n }\n }\n\n if (pickerMode.value === 'mention') {\n // 这些键导致 mention 退出(保留 @filter 文本,光标继续移动)\n if (e.key === ' ' || e.key === 'ArrowLeft' || e.key === 'ArrowRight') {\n mention.dismiss()\n closePicker()\n }\n }\n}\n\nfunction onBlur() {\n if (pickerMode.value === 'mention') {\n mention.dismiss()\n // 下一帧再关闭,避免和 picker 内 click 冲突\n void nextTick(() => closePicker())\n }\n}\n\nfunction onPickerSelect(item: VariableItem) {\n const editor = editorRef.value\n if (!editor) return\n\n if (pickerMode.value === 'mention') {\n const state = mention.getState()\n if (!state) return\n const anchor = state.anchorOffset\n const caret = editor.getCaretOffset() ?? anchor + state.filter.length + 1\n editor.replaceRangeWithVar(anchor, caret, {\n value: item.value,\n label: item.label,\n ...(item.type ? { type: item.type } : {})\n })\n mention.commit()\n } else if (pickerMode.value === 'reselect') {\n const idx = reselectingSegIdx.value\n if (idx !== null) {\n editor.replaceVarAt(idx, {\n value: item.value,\n label: item.label,\n ...(item.type ? { type: item.type } : {})\n })\n }\n }\n closePicker()\n}\n\nfunction onPickerDismiss() {\n if (pickerMode.value === 'mention') mention.dismiss()\n closePicker()\n}\n\nfunction onPickerVisibleChange(v: boolean) {\n if (!v && pickerMode.value !== null) {\n if (pickerMode.value === 'mention') mention.dismiss()\n closePicker()\n }\n}\n</script>\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-picker.js","names":[],"sources":["../../../src/components/file-picker/file-picker.vue"],"sourcesContent":["<template>\n <component\n :is=\"tag\"\n :class=\"cls.b\"\n @click.stop=\"handleClickPicker\"\n @dragover.prevent=\"handleDragover\"\n @dragleave=\"handleDragLeave\"\n @drop.prevent=\"handleDrop\"\n >\n <input\n :multiple=\"multiple\"\n :class=\"cls.e('native')\"\n type=\"file\"\n :accept=\"accept\"\n hidden\n placeholder=\"选择文件\"\n ref=\"fileRef\"\n @change=\"handleChange\"\n capture=\"environment\"\n />\n <slot :is-dragover=\"isDragover\" />\n </component>\n</template>\n\n<script lang=\"ts\" setup>\nimport { bem } from '@veltra/utils'\nimport { shallowRef, ref } from 'vue'\n\nimport type { UploaderProps, UploaderEmits } from '../../types'\nimport { matchAccept } from './helper'\n\ndefineOptions({ name: 'FilePicker' })\n\nconst props = withDefaults(defineProps<UploaderProps>(), { tag: 'div', multiple: false })\n\nconst emit = defineEmits<UploaderEmits>()\n\nconst cls = bem('file-picker')\n\nconst fileRef = shallowRef<HTMLInputElement>()\nconst isDragover = ref(false)\n\nconst processFiles = (files: File[]) => {\n const filteredFiles = files.filter((file) => matchAccept(file, props.accept))\n emit('pick', filteredFiles)\n}\n\nconst handleChange = (e: Event) => {\n const target = e.target as HTMLInputElement\n const files = Array.from(target.files || [])\n processFiles(files)\n target.value = ''\n}\n\nconst handleDragover = (e: DragEvent) => {\n if (props.disabled) return\n isDragover.value = true\n}\n\nconst handleDragLeave = (e: DragEvent) => {\n if (props.disabled) return\n const currentTarget = e.currentTarget as HTMLElement\n const relatedTarget = e.relatedTarget as HTMLElement | null\n\n if (currentTarget.contains(relatedTarget)) return\n isDragover.value = false\n}\n\nconst handleDrop = (e: DragEvent) => {\n if (props.disabled) return\n isDragover.value = false\n const files = Array.from(e.dataTransfer?.files || [])\n processFiles(files)\n}\n\nfunction handleClickPicker() {\n if (props.disabled) return\n fileRef.value?.click()\n}\n</script>\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"file-picker.js","names":[],"sources":["../../../src/components/file-picker/file-picker.vue"],"sourcesContent":["<template>\n <component\n :is=\"tag\"\n :class=\"cls.b\"\n @click.stop=\"handleClickPicker\"\n @dragover.prevent=\"handleDragover\"\n @dragleave=\"handleDragLeave\"\n @drop.prevent=\"handleDrop\"\n >\n <input\n :multiple=\"multiple\"\n :class=\"cls.e('native')\"\n type=\"file\"\n :accept=\"accept\"\n hidden\n placeholder=\"选择文件\"\n ref=\"fileRef\"\n @change=\"handleChange\"\n capture=\"environment\"\n />\n <slot :is-dragover=\"isDragover\" />\n </component>\n</template>\n\n<script lang=\"ts\" setup>\nimport { bem } from '@veltra/utils'\nimport { shallowRef, ref } from 'vue'\n\nimport type { UploaderProps, UploaderEmits } from '../../types'\nimport { matchAccept } from './helper'\n\ndefineOptions({ name: 'FilePicker' })\n\nconst props = withDefaults(defineProps<UploaderProps>(), { tag: 'div', multiple: false })\n\nconst emit = defineEmits<UploaderEmits>()\n\nconst cls = bem('file-picker')\n\nconst fileRef = shallowRef<HTMLInputElement>()\nconst isDragover = ref(false)\n\nconst processFiles = (files: File[]) => {\n const filteredFiles = files.filter((file) => matchAccept(file, props.accept))\n emit('pick', filteredFiles)\n}\n\nconst handleChange = (e: Event) => {\n const target = e.target as HTMLInputElement\n const files = Array.from(target.files || [])\n processFiles(files)\n target.value = ''\n}\n\nconst handleDragover = (e: DragEvent) => {\n if (props.disabled) return\n isDragover.value = true\n}\n\nconst handleDragLeave = (e: DragEvent) => {\n if (props.disabled) return\n const currentTarget = e.currentTarget as HTMLElement\n const relatedTarget = e.relatedTarget as HTMLElement | null\n\n if (currentTarget.contains(relatedTarget)) return\n isDragover.value = false\n}\n\nconst handleDrop = (e: DragEvent) => {\n if (props.disabled) return\n isDragover.value = false\n const files = Array.from(e.dataTransfer?.files || [])\n processFiles(files)\n}\n\nfunction handleClickPicker() {\n if (props.disabled) return\n fileRef.value?.click()\n}\n</script>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;EAiCA,MAAM,QAAQ;EAEd,MAAM,OAAO;EAEb,MAAM,MAAM,IAAI,aAAa;EAE7B,MAAM,UAAU,WAA6B;EAC7C,MAAM,aAAa,IAAI,KAAK;EAE5B,MAAM,gBAAgB,UAAkB;GAEtC,KAAK,QADiB,MAAM,QAAQ,SAAS,YAAY,MAAM,MAAM,MAAM,CAC9D,CAAa;EAC5B;EAEA,MAAM,gBAAgB,MAAa;GACjC,MAAM,SAAS,EAAE;GAEjB,aADc,MAAM,KAAK,OAAO,SAAS,CAAC,CAC7B,CAAK;GAClB,OAAO,QAAQ;EACjB;EAEA,MAAM,kBAAkB,MAAiB;GACvC,IAAI,MAAM,UAAU;GACpB,WAAW,QAAQ;EACrB;EAEA,MAAM,mBAAmB,MAAiB;GACxC,IAAI,MAAM,UAAU;GACpB,MAAM,gBAAgB,EAAE;GACxB,MAAM,gBAAgB,EAAE;GAExB,IAAI,cAAc,SAAS,aAAa,GAAG;GAC3C,WAAW,QAAQ;EACrB;EAEA,MAAM,cAAc,MAAiB;GACnC,IAAI,MAAM,UAAU;GACpB,WAAW,QAAQ;GAEnB,aADc,MAAM,KAAK,EAAE,cAAc,SAAS,CAAC,CACtC,CAAK;EACpB;EAEA,SAAS,oBAAoB;GAC3B,IAAI,MAAM,UAAU;GACpB,QAAQ,OAAO,MAAM;EACvB;;uBA7EE,YAoBY,wBAnBL,QAAA,GAAG,GAAA;IACP,OAAK,eAAE,MAAA,GAAA,EAAI,CAAC;IACZ,SAAK,cAAO,mBAAiB,CAAA,MAAA,CAAA;IAC7B,YAAQ,cAAU,gBAAc,CAAA,SAAA,CAAA;IAChC,aAAW;IACX,QAAI,cAAU,YAAU,CAAA,SAAA,CAAA;;2BAYvB,CAVF,mBAUE,SAAA;KATC,UAAU,QAAA;KACV,OAAK,eAAE,MAAA,GAAA,EAAI,EAAC,QAAA,CAAA;KACb,MAAK;KACJ,QAAQ,QAAA;KACT,QAAA;KACA,aAAY;cACR;KAAJ,KAAI;KACH,UAAQ;KACT,SAAQ;8BAEV,WAAkC,KAAA,QAAA,WAAA,EAA3B,YAAa,WAAA,MAAU,CAAA,CAAA,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"form.js","names":[],"sources":["../../../src/components/form/form.vue"],"sourcesContent":["<template>\n <u-grid\n tag=\"form\"\n ref=\"gridRef\"\n @submit.prevent\n :cols=\"cols || breakpointCols\"\n :class=\"[cls.b, bem.is('readonly', readonly)]\"\n >\n <template\n v-for=\"{ node, isFormItem, formItemProps, field, modelValue } of getSlotsNodes()\"\n :key=\"node.key\"\n >\n <
|
|
1
|
+
{"version":3,"file":"form.js","names":[],"sources":["../../../src/components/form/form.vue"],"sourcesContent":["<template>\n <u-grid\n tag=\"form\"\n ref=\"gridRef\"\n @submit.prevent\n :cols=\"cols || breakpointCols\"\n :class=\"[cls.b, bem.is('readonly', readonly)]\"\n >\n <template\n v-for=\"{ node, isFormItem, formItemProps, field, modelValue } of getSlotsNodes()\"\n :key=\"node.key\"\n >\n <u-form-item v-if=\"!isFormItem && field\" v-bind=\"formItemProps\">\n <component\n :is=\"node\"\n :model-value=\"modelValue ?? o(model ?? {}).get(field)\"\n @update:model-value=\"handleUpdateValue(field, $event)\"\n />\n </u-form-item>\n\n <component v-else :is=\"node\" />\n </template>\n </u-grid>\n</template>\n\n<script lang=\"tsx\" setup>\nimport { o } from '@cat-kit/core'\nimport { bem } from '@veltra/utils'\nimport { provideFormContext } from '@veltra/utils'\nimport { shallowRef, toRef } from 'vue'\n\nimport type { BreakCols, GridExposed, FormProps, _FormExposed } from '../../types'\nimport { UFormItem } from '../form-item'\nimport { UGrid } from '../grid'\nimport { useFormFields } from './use-form-fields'\nimport { useNodeInterceptor } from './use-node-interceptor'\n\ndefineOptions({ name: 'Form' })\n\nconst props = defineProps<FormProps>()\n\ndefineSlots<{ default(props?: { data: Record<string, any> | undefined }): any }>()\n\nconst cls = bem('form')\n\nconst breakpointCols: BreakCols = { xs: 1, md: 2, lg: 3, xl: 4, default: 4 }\n\nconst { validate, clearValidate, reset, registerField, unregisterField, shouldValidate } =\n useFormFields({ props })\n\nprovideFormContext({\n formProps: props,\n registerField,\n unregisterField,\n validateFields: validate,\n shouldValidate\n})\n\nconst { getSlotsNodes } = useNodeInterceptor()\n\nfunction handleUpdateValue(field: string, value: any) {\n if (!props.model) return\n o(props.model).set(field, value)\n}\n\nconst gridRef = shallowRef<GridExposed>()\n\ndefineExpose<_FormExposed>({ el: toRef(() => gridRef.value?.el), validate, clearValidate, reset })\n</script>\n"],"mappings":""}
|
|
@@ -1,26 +1,18 @@
|
|
|
1
1
|
import { FormProps, _FormExposed } from "../../types/form.js";
|
|
2
|
-
import { DynamicFormModel } from "./dynamic-form-model.js";
|
|
3
|
-
import { FormModel } from "./form-model.js";
|
|
4
|
-
|
|
5
2
|
//#region src/components/form/form.vue.d.ts
|
|
6
|
-
|
|
7
|
-
props
|
|
8
|
-
|
|
9
|
-
}
|
|
10
|
-
expose: (exposed: import("vue").ShallowUnwrapRef<_FormExposed>) => void;
|
|
11
|
-
attrs: any;
|
|
12
|
-
slots: {
|
|
13
|
-
default(props: {
|
|
14
|
-
/** 表单数据 */data: Model["data"]; /** 表单模型 */
|
|
15
|
-
model: Model;
|
|
16
|
-
}): any;
|
|
17
|
-
};
|
|
18
|
-
emit: {};
|
|
19
|
-
}>) => import("vue").VNode & {
|
|
20
|
-
__ctx?: Awaited<typeof __VLS_setup>;
|
|
3
|
+
type __VLS_Slots = {
|
|
4
|
+
default(props?: {
|
|
5
|
+
data: Record<string, any> | undefined;
|
|
6
|
+
}): any;
|
|
21
7
|
};
|
|
8
|
+
declare const __VLS_base: import("vue").DefineComponent<FormProps, _FormExposed, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<FormProps> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
9
|
+
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
22
10
|
declare const _default: typeof __VLS_export;
|
|
23
|
-
type
|
|
11
|
+
type __VLS_WithSlots<T, S> = T & {
|
|
12
|
+
new (): {
|
|
13
|
+
$slots: S;
|
|
14
|
+
};
|
|
15
|
+
};
|
|
24
16
|
//#endregion
|
|
25
17
|
export { _default };
|
|
26
18
|
//# sourceMappingURL=form.vue.d.ts.map
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import _sfc_main from "../grid/grid.js";
|
|
2
2
|
import form_item_default from "../form-item/form-item.js";
|
|
3
|
+
import { useFormFields } from "./use-form-fields.js";
|
|
3
4
|
import { useNodeInterceptor } from "./use-node-interceptor.js";
|
|
4
|
-
import { Fragment, createBlock,
|
|
5
|
+
import { Fragment, createBlock, createElementBlock, defineComponent, mergeProps, normalizeClass, openBlock, renderList, resolveDynamicComponent, shallowRef, toRef, unref, withCtx, withModifiers } from "vue";
|
|
5
6
|
import { bem, provideFormContext } from "@veltra/utils";
|
|
6
7
|
import { o } from "@cat-kit/core";
|
|
7
8
|
//#region src/components/form/form.vue?vue&type=script&setup=true&lang.tsx
|
|
@@ -10,7 +11,6 @@ var form_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineCompo
|
|
|
10
11
|
__name: "form",
|
|
11
12
|
props: {
|
|
12
13
|
cols: {},
|
|
13
|
-
showInitialData: { type: Boolean },
|
|
14
14
|
model: {},
|
|
15
15
|
labelWidth: {},
|
|
16
16
|
noTips: { type: Boolean },
|
|
@@ -28,22 +28,26 @@ var form_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineCompo
|
|
|
28
28
|
xl: 4,
|
|
29
29
|
default: 4
|
|
30
30
|
};
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
const { validate, clearValidate, reset, registerField, unregisterField, shouldValidate } = useFormFields({ props });
|
|
32
|
+
provideFormContext({
|
|
33
|
+
formProps: props,
|
|
34
|
+
registerField,
|
|
35
|
+
unregisterField,
|
|
36
|
+
validateFields: validate,
|
|
37
|
+
shouldValidate
|
|
38
|
+
});
|
|
39
|
+
const { getSlotsNodes } = useNodeInterceptor();
|
|
33
40
|
function handleUpdateValue(field, value) {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
o(model.data).set(field, value);
|
|
37
|
-
}
|
|
38
|
-
function showInitialNode(field) {
|
|
39
|
-
const { data, initialData } = props.model || {};
|
|
40
|
-
const currentValue = o(data ?? {}).get(field);
|
|
41
|
-
const initialValue = o(initialData ?? {}).get(field);
|
|
42
|
-
const notEqual = !(initialValue === currentValue || !initialValue && !currentValue);
|
|
43
|
-
return props.showInitialData && notEqual;
|
|
41
|
+
if (!props.model) return;
|
|
42
|
+
o(props.model).set(field, value);
|
|
44
43
|
}
|
|
45
44
|
const gridRef = shallowRef();
|
|
46
|
-
__expose({
|
|
45
|
+
__expose({
|
|
46
|
+
el: toRef(() => gridRef.value?.el),
|
|
47
|
+
validate,
|
|
48
|
+
clearValidate,
|
|
49
|
+
reset
|
|
50
|
+
});
|
|
47
51
|
return (_ctx, _cache) => {
|
|
48
52
|
return openBlock(), createBlock(unref(_sfc_main), {
|
|
49
53
|
tag: "form",
|
|
@@ -54,22 +58,16 @@ var form_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineCompo
|
|
|
54
58
|
class: normalizeClass([unref(cls).b, unref(bem).is("readonly", __props.readonly)])
|
|
55
59
|
}, {
|
|
56
60
|
default: withCtx(() => [(openBlock(true), createElementBlock(Fragment, null, renderList(unref(getSlotsNodes)(), ({ node, isFormItem, formItemProps, field, modelValue }) => {
|
|
57
|
-
return openBlock(), createElementBlock(Fragment, { key: node.key }, [isFormItem
|
|
58
|
-
key:
|
|
61
|
+
return openBlock(), createElementBlock(Fragment, { key: node.key }, [!isFormItem && field ? (openBlock(), createBlock(unref(form_item_default), mergeProps({
|
|
62
|
+
key: 0,
|
|
59
63
|
ref_for: true
|
|
60
64
|
}, formItemProps), {
|
|
61
65
|
default: withCtx(() => [(openBlock(), createBlock(resolveDynamicComponent(node), {
|
|
62
|
-
"model-value": modelValue ?? unref(o)(__props.model
|
|
66
|
+
"model-value": modelValue ?? unref(o)(__props.model ?? {}).get(field),
|
|
63
67
|
"onUpdate:modelValue": ($event) => handleUpdateValue(field, $event)
|
|
64
|
-
}, null, 8, ["model-value", "onUpdate:modelValue"]))
|
|
65
|
-
key: 0,
|
|
66
|
-
class: normalizeClass(unref(cls).e("data-before"))
|
|
67
|
-
}, [createElementVNode("i", { class: normalizeClass(unref(cls).e("changed-tag")) }, "变更前:", 2), (openBlock(), createBlock(resolveDynamicComponent(node), {
|
|
68
|
-
readonly: "",
|
|
69
|
-
"model-value": unref(o)(__props.model?.initialData ?? {}).get(field)
|
|
70
|
-
}, null, 8, ["model-value"]))], 2)) : createCommentVNode("v-if", true)]),
|
|
68
|
+
}, null, 8, ["model-value", "onUpdate:modelValue"]))]),
|
|
71
69
|
_: 2
|
|
72
|
-
}, 1040))], 64);
|
|
70
|
+
}, 1040)) : (openBlock(), createBlock(resolveDynamicComponent(node), { key: 1 }))], 64);
|
|
73
71
|
}), 128))]),
|
|
74
72
|
_: 1
|
|
75
73
|
}, 8, ["cols", "class"]);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"form.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../src/components/form/form.vue"],"sourcesContent":["<template>\n <u-grid\n tag=\"form\"\n ref=\"gridRef\"\n @submit.prevent\n :cols=\"cols || breakpointCols\"\n :class=\"[cls.b, bem.is('readonly', readonly)]\"\n >\n <template\n v-for=\"{ node, isFormItem, formItemProps, field, modelValue } of getSlotsNodes()\"\n :key=\"node.key\"\n >\n <
|
|
1
|
+
{"version":3,"file":"form.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../src/components/form/form.vue"],"sourcesContent":["<template>\n <u-grid\n tag=\"form\"\n ref=\"gridRef\"\n @submit.prevent\n :cols=\"cols || breakpointCols\"\n :class=\"[cls.b, bem.is('readonly', readonly)]\"\n >\n <template\n v-for=\"{ node, isFormItem, formItemProps, field, modelValue } of getSlotsNodes()\"\n :key=\"node.key\"\n >\n <u-form-item v-if=\"!isFormItem && field\" v-bind=\"formItemProps\">\n <component\n :is=\"node\"\n :model-value=\"modelValue ?? o(model ?? {}).get(field)\"\n @update:model-value=\"handleUpdateValue(field, $event)\"\n />\n </u-form-item>\n\n <component v-else :is=\"node\" />\n </template>\n </u-grid>\n</template>\n\n<script lang=\"tsx\" setup>\nimport { o } from '@cat-kit/core'\nimport { bem } from '@veltra/utils'\nimport { provideFormContext } from '@veltra/utils'\nimport { shallowRef, toRef } from 'vue'\n\nimport type { BreakCols, GridExposed, FormProps, _FormExposed } from '../../types'\nimport { UFormItem } from '../form-item'\nimport { UGrid } from '../grid'\nimport { useFormFields } from './use-form-fields'\nimport { useNodeInterceptor } from './use-node-interceptor'\n\ndefineOptions({ name: 'Form' })\n\nconst props = defineProps<FormProps>()\n\ndefineSlots<{ default(props?: { data: Record<string, any> | undefined }): any }>()\n\nconst cls = bem('form')\n\nconst breakpointCols: BreakCols = { xs: 1, md: 2, lg: 3, xl: 4, default: 4 }\n\nconst { validate, clearValidate, reset, registerField, unregisterField, shouldValidate } =\n useFormFields({ props })\n\nprovideFormContext({\n formProps: props,\n registerField,\n unregisterField,\n validateFields: validate,\n shouldValidate\n})\n\nconst { getSlotsNodes } = useNodeInterceptor()\n\nfunction handleUpdateValue(field: string, value: any) {\n if (!props.model) return\n o(props.model).set(field, value)\n}\n\nconst gridRef = shallowRef<GridExposed>()\n\ndefineExpose<_FormExposed>({ el: toRef(() => gridRef.value?.el), validate, clearValidate, reset })\n</script>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;EAuCA,MAAM,QAAQ;EAId,MAAM,MAAM,IAAI,MAAM;EAEtB,MAAM,iBAA4B;GAAE,IAAI;GAAG,IAAI;GAAG,IAAI;GAAG,IAAI;GAAG,SAAS;EAAE;EAE3E,MAAM,EAAE,UAAU,eAAe,OAAO,eAAe,iBAAiB,mBACtE,cAAc,EAAE,MAAM,CAAC;EAEzB,mBAAmB;GACjB,WAAW;GACX;GACA;GACA,gBAAgB;GAChB;EACF,CAAC;EAED,MAAM,EAAE,kBAAkB,mBAAmB;EAE7C,SAAS,kBAAkB,OAAe,OAAY;GACpD,IAAI,CAAC,MAAM,OAAO;GAClB,EAAE,MAAM,KAAK,EAAE,IAAI,OAAO,KAAK;EACjC;EAEA,MAAM,UAAU,WAAwB;EAExC,SAA2B;GAAE,IAAI,YAAY,QAAQ,OAAO,EAAE;GAAG;GAAU;GAAe;EAAM,CAAC;;uBAlE/F,YAqBS,MAAA,SAAA,GAAA;IApBP,KAAI;aACA;IAAJ,KAAI;IACH,UAAM,OAAA,OAAA,OAAA,KAAA,oBAAP,CAAA,GAAe,CAAA,SAAA,CAAA;IACd,MAAM,QAAA,QAAQ;IACd,OAAK,eAAA,CAAG,MAAA,GAAA,EAAI,GAAG,MAAA,GAAA,EAAI,GAAE,YAAa,QAAA,QAAQ,CAAA,CAAA;;2BAGwC,EAAA,UAAA,IAAA,GADnF,mBAaW,UAAA,MAAA,WAZwD,MAAA,aAAA,EAAa,IAAA,EAArE,MAAM,YAAY,eAAe,OAAO,iBAAU;6DACrD,KAAK,IAAA,GAAA,CAAA,CAES,cAAc,SAAA,UAAA,GAAlC,YAMc,MAAA,iBAAA,GANd,WAMc;;;QANmC,aAAa,GAAA;6BAK1D,EAAA,UAAA,GAJF,YAIE,wBAHK,IAAI,GAAA;OACR,eAAa,cAAc,MAAA,CAAA,EAAE,QAAA,SAAK,CAAA,CAAA,EAAQ,IAAI,KAAK;OACnD,wBAAkB,WAAE,kBAAkB,OAAO,MAAM;;;+BAIxD,YAA+B,wBAAR,IAAI,GAAA,EAAA,KAAA,EAAA,CAAA,EAAA,GAAA,EAAA"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { nextTick, watch } from "vue";
|
|
2
|
+
import { o } from "@cat-kit/core";
|
|
3
|
+
//#region src/components/form/use-form-fields.ts
|
|
4
|
+
/** 深拷贝 model,保留 undefined 等 o().copy() 会丢弃的值 */
|
|
5
|
+
function snapshotModel(model) {
|
|
6
|
+
const result = {};
|
|
7
|
+
for (const key of Object.keys(model)) {
|
|
8
|
+
const value = model[key];
|
|
9
|
+
if (Array.isArray(value)) result[key] = value.map((item) => item !== null && typeof item === "object" ? snapshotModel(item) : item);
|
|
10
|
+
else if (value !== null && typeof value === "object") result[key] = snapshotModel(value);
|
|
11
|
+
else result[key] = value;
|
|
12
|
+
}
|
|
13
|
+
return result;
|
|
14
|
+
}
|
|
15
|
+
/** 按快照逐字段写回 model,支持 undefined 与嵌套对象 */
|
|
16
|
+
function applySnapshot(target, source) {
|
|
17
|
+
for (const key of Object.keys(source)) {
|
|
18
|
+
const sourceValue = source[key];
|
|
19
|
+
const targetValue = target[key];
|
|
20
|
+
if (sourceValue !== null && typeof sourceValue === "object" && !Array.isArray(sourceValue) && targetValue !== null && typeof targetValue === "object" && !Array.isArray(targetValue)) {
|
|
21
|
+
applySnapshot(targetValue, sourceValue);
|
|
22
|
+
continue;
|
|
23
|
+
}
|
|
24
|
+
if (Array.isArray(sourceValue)) {
|
|
25
|
+
o(target).set(key, sourceValue.map((item) => item !== null && typeof item === "object" ? snapshotModel(item) : item));
|
|
26
|
+
continue;
|
|
27
|
+
}
|
|
28
|
+
o(target).set(key, sourceValue);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
function useFormFields(options) {
|
|
32
|
+
const { props } = options;
|
|
33
|
+
const fields = {};
|
|
34
|
+
let willValidate = true;
|
|
35
|
+
/** model 初始快照,供 reset 恢复 */
|
|
36
|
+
let initialSnapshot;
|
|
37
|
+
function runWithoutChangeValidate(fn) {
|
|
38
|
+
willValidate = false;
|
|
39
|
+
fn();
|
|
40
|
+
nextTick(() => {
|
|
41
|
+
willValidate = true;
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
function shouldValidate() {
|
|
45
|
+
return willValidate;
|
|
46
|
+
}
|
|
47
|
+
watch(() => props.model, (model) => {
|
|
48
|
+
initialSnapshot = model ? snapshotModel(model) : void 0;
|
|
49
|
+
}, {
|
|
50
|
+
immediate: true,
|
|
51
|
+
deep: false
|
|
52
|
+
});
|
|
53
|
+
function registerField(field, item) {
|
|
54
|
+
fields[field] = item;
|
|
55
|
+
}
|
|
56
|
+
function unregisterField(field) {
|
|
57
|
+
delete fields[field];
|
|
58
|
+
}
|
|
59
|
+
function clearValidate() {
|
|
60
|
+
Object.values(fields).forEach((item) => item.clearValidate?.());
|
|
61
|
+
}
|
|
62
|
+
async function validate(keys) {
|
|
63
|
+
let validList;
|
|
64
|
+
if (keys) validList = await Promise.all(keys.map((key) => fields[key]?.validate() ?? Promise.resolve(true)));
|
|
65
|
+
else validList = await Promise.all(Object.values(fields).map((field) => field.validate()));
|
|
66
|
+
return validList.every((valid) => valid);
|
|
67
|
+
}
|
|
68
|
+
function reset() {
|
|
69
|
+
if (!props.model || !initialSnapshot) return;
|
|
70
|
+
runWithoutChangeValidate(() => {
|
|
71
|
+
applySnapshot(props.model, initialSnapshot);
|
|
72
|
+
Object.values(fields).forEach((item) => item.clearValidate?.());
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
return {
|
|
76
|
+
fields,
|
|
77
|
+
registerField,
|
|
78
|
+
validate,
|
|
79
|
+
unregisterField,
|
|
80
|
+
clearValidate,
|
|
81
|
+
reset,
|
|
82
|
+
shouldValidate
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
//#endregion
|
|
86
|
+
export { useFormFields };
|
|
87
|
+
|
|
88
|
+
//# sourceMappingURL=use-form-fields.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-form-fields.js","names":[],"sources":["../../../src/components/form/use-form-fields.ts"],"sourcesContent":["import { o } from '@cat-kit/core'\nimport type { FormFieldItem } from '@veltra/utils'\nimport { nextTick, watch } from 'vue'\n\nimport type { FormProps } from '../../types/form'\n\ninterface Options {\n props: FormProps\n}\n\n/** 深拷贝 model,保留 undefined 等 o().copy() 会丢弃的值 */\nfunction snapshotModel(model: Record<string, any>): Record<string, any> {\n const result: Record<string, any> = {}\n\n for (const key of Object.keys(model)) {\n const value = model[key]\n if (Array.isArray(value)) {\n result[key] = value.map((item) =>\n item !== null && typeof item === 'object' ? snapshotModel(item) : item\n )\n } else if (value !== null && typeof value === 'object') {\n result[key] = snapshotModel(value)\n } else {\n result[key] = value\n }\n }\n\n return result\n}\n\n/** 按快照逐字段写回 model,支持 undefined 与嵌套对象 */\nfunction applySnapshot(target: Record<string, any>, source: Record<string, any>) {\n for (const key of Object.keys(source)) {\n const sourceValue = source[key]\n const targetValue = target[key]\n\n if (\n sourceValue !== null &&\n typeof sourceValue === 'object' &&\n !Array.isArray(sourceValue) &&\n targetValue !== null &&\n typeof targetValue === 'object' &&\n !Array.isArray(targetValue)\n ) {\n applySnapshot(targetValue, sourceValue)\n continue\n }\n\n if (Array.isArray(sourceValue)) {\n o(target).set(\n key,\n sourceValue.map((item) =>\n item !== null && typeof item === 'object' ? snapshotModel(item) : item\n )\n )\n continue\n }\n\n o(target).set(key, sourceValue)\n }\n}\n\nexport function useFormFields(options: Options) {\n const { props } = options\n const fields: Record<string, FormFieldItem> = {}\n\n let willValidate = true\n\n /** model 初始快照,供 reset 恢复 */\n let initialSnapshot: Record<string, any> | undefined\n\n function runWithoutChangeValidate(fn: () => void) {\n willValidate = false\n fn()\n nextTick(() => {\n willValidate = true\n })\n }\n\n function shouldValidate() {\n return willValidate\n }\n\n watch(\n () => props.model,\n (model) => {\n initialSnapshot = model ? snapshotModel(model) : undefined\n },\n { immediate: true, deep: false }\n )\n\n function registerField(field: string, item: FormFieldItem) {\n fields[field] = item\n }\n\n function unregisterField(field: string) {\n delete fields[field]\n }\n\n function clearValidate() {\n Object.values(fields).forEach((item) => item.clearValidate?.())\n }\n\n async function validate(keys?: string[]) {\n let validList: boolean[]\n if (keys) {\n validList = await Promise.all(\n keys.map((key) => fields[key]?.validate() ?? Promise.resolve(true))\n )\n } else {\n validList = await Promise.all(Object.values(fields).map((field) => field.validate()))\n }\n return validList.every((valid) => valid)\n }\n\n function reset() {\n if (!props.model || !initialSnapshot) return\n\n runWithoutChangeValidate(() => {\n applySnapshot(props.model!, initialSnapshot!)\n Object.values(fields).forEach((item) => item.clearValidate?.())\n })\n }\n\n return { fields, registerField, validate, unregisterField, clearValidate, reset, shouldValidate }\n}\n"],"mappings":";;;;AAWA,SAAS,cAAc,OAAiD;CACtE,MAAM,SAA8B,CAAC;CAErC,KAAK,MAAM,OAAO,OAAO,KAAK,KAAK,GAAG;EACpC,MAAM,QAAQ,MAAM;EACpB,IAAI,MAAM,QAAQ,KAAK,GACrB,OAAO,OAAO,MAAM,KAAK,SACvB,SAAS,QAAQ,OAAO,SAAS,WAAW,cAAc,IAAI,IAAI,IACpE;OACK,IAAI,UAAU,QAAQ,OAAO,UAAU,UAC5C,OAAO,OAAO,cAAc,KAAK;OAEjC,OAAO,OAAO;CAElB;CAEA,OAAO;AACT;;AAGA,SAAS,cAAc,QAA6B,QAA6B;CAC/E,KAAK,MAAM,OAAO,OAAO,KAAK,MAAM,GAAG;EACrC,MAAM,cAAc,OAAO;EAC3B,MAAM,cAAc,OAAO;EAE3B,IACE,gBAAgB,QAChB,OAAO,gBAAgB,YACvB,CAAC,MAAM,QAAQ,WAAW,KAC1B,gBAAgB,QAChB,OAAO,gBAAgB,YACvB,CAAC,MAAM,QAAQ,WAAW,GAC1B;GACA,cAAc,aAAa,WAAW;GACtC;EACF;EAEA,IAAI,MAAM,QAAQ,WAAW,GAAG;GAC9B,EAAE,MAAM,EAAE,IACR,KACA,YAAY,KAAK,SACf,SAAS,QAAQ,OAAO,SAAS,WAAW,cAAc,IAAI,IAAI,IACpE,CACF;GACA;EACF;EAEA,EAAE,MAAM,EAAE,IAAI,KAAK,WAAW;CAChC;AACF;AAEA,SAAgB,cAAc,SAAkB;CAC9C,MAAM,EAAE,UAAU;CAClB,MAAM,SAAwC,CAAC;CAE/C,IAAI,eAAe;;CAGnB,IAAI;CAEJ,SAAS,yBAAyB,IAAgB;EAChD,eAAe;EACf,GAAG;EACH,eAAe;GACb,eAAe;EACjB,CAAC;CACH;CAEA,SAAS,iBAAiB;EACxB,OAAO;CACT;CAEA,YACQ,MAAM,QACX,UAAU;EACT,kBAAkB,QAAQ,cAAc,KAAK,IAAI,KAAA;CACnD,GACA;EAAE,WAAW;EAAM,MAAM;CAAM,CACjC;CAEA,SAAS,cAAc,OAAe,MAAqB;EACzD,OAAO,SAAS;CAClB;CAEA,SAAS,gBAAgB,OAAe;EACtC,OAAO,OAAO;CAChB;CAEA,SAAS,gBAAgB;EACvB,OAAO,OAAO,MAAM,EAAE,SAAS,SAAS,KAAK,gBAAgB,CAAC;CAChE;CAEA,eAAe,SAAS,MAAiB;EACvC,IAAI;EACJ,IAAI,MACF,YAAY,MAAM,QAAQ,IACxB,KAAK,KAAK,QAAQ,OAAO,MAAM,SAAS,KAAK,QAAQ,QAAQ,IAAI,CAAC,CACpE;OAEA,YAAY,MAAM,QAAQ,IAAI,OAAO,OAAO,MAAM,EAAE,KAAK,UAAU,MAAM,SAAS,CAAC,CAAC;EAEtF,OAAO,UAAU,OAAO,UAAU,KAAK;CACzC;CAEA,SAAS,QAAQ;EACf,IAAI,CAAC,MAAM,SAAS,CAAC,iBAAiB;EAEtC,+BAA+B;GAC7B,cAAc,MAAM,OAAQ,eAAgB;GAC5C,OAAO,OAAO,MAAM,EAAE,SAAS,SAAS,KAAK,gBAAgB,CAAC;EAChE,CAAC;CACH;CAEA,OAAO;EAAE;EAAQ;EAAe;EAAU;EAAiB;EAAe;EAAO;CAAe;AAClG"}
|
|
@@ -1,54 +1,43 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { useSlots } from "vue";
|
|
2
|
+
import { extractNormalVNodes } from "@veltra/utils";
|
|
3
3
|
import { o } from "@cat-kit/core";
|
|
4
4
|
//#region src/components/form/use-node-interceptor.ts
|
|
5
|
-
const id = createIncrease(1);
|
|
6
5
|
/**
|
|
7
6
|
* 虚拟node拦截
|
|
8
|
-
* @param options 选项
|
|
9
7
|
* @returns
|
|
10
8
|
*/
|
|
11
|
-
function useNodeInterceptor(
|
|
12
|
-
const { props } = options;
|
|
9
|
+
function useNodeInterceptor() {
|
|
13
10
|
const slots = useSlots();
|
|
14
|
-
const formId = id();
|
|
15
11
|
function getSlotsNodes() {
|
|
16
|
-
const
|
|
17
|
-
const nodes = slots.default?.({
|
|
18
|
-
model,
|
|
19
|
-
data: model?.data
|
|
20
|
-
});
|
|
12
|
+
const nodes = slots.default?.();
|
|
21
13
|
if (!nodes?.length) return null;
|
|
22
14
|
const flattedNodes = extractNormalVNodes(nodes);
|
|
23
15
|
const results = [];
|
|
24
|
-
const fields = [];
|
|
25
16
|
let i = 0;
|
|
26
17
|
while (i < flattedNodes.length) {
|
|
27
18
|
const node = flattedNodes[i];
|
|
28
19
|
i++;
|
|
29
20
|
const { props, type } = node;
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
21
|
+
const field = props?.field;
|
|
22
|
+
const isFormItem = type?.name === "FormItem";
|
|
23
|
+
const formItemProps = o(props ?? {}).pick([
|
|
24
|
+
"label",
|
|
25
|
+
"rules",
|
|
26
|
+
"span",
|
|
27
|
+
"tips",
|
|
28
|
+
"readonly",
|
|
29
|
+
"field"
|
|
30
|
+
]);
|
|
31
|
+
results.push({
|
|
32
|
+
isFormItem,
|
|
33
|
+
formItemProps,
|
|
39
34
|
node,
|
|
40
|
-
field
|
|
35
|
+
field,
|
|
41
36
|
modelValue: props?.["model-value"] ?? props?.modelValue
|
|
42
|
-
};
|
|
43
|
-
item.field && fields.push(item.field);
|
|
44
|
-
results.push(item);
|
|
37
|
+
});
|
|
45
38
|
}
|
|
46
|
-
model.formKeys.set(formId, fields);
|
|
47
39
|
return results;
|
|
48
40
|
}
|
|
49
|
-
onBeforeUnmount(() => {
|
|
50
|
-
props.model?.formKeys.delete(formId);
|
|
51
|
-
});
|
|
52
41
|
return { getSlotsNodes };
|
|
53
42
|
}
|
|
54
43
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-node-interceptor.js","names":[],"sources":["../../../src/components/form/use-node-interceptor.ts"],"sourcesContent":["import { o } from '@cat-kit/core'\nimport {
|
|
1
|
+
{"version":3,"file":"use-node-interceptor.js","names":[],"sources":["../../../src/components/form/use-node-interceptor.ts"],"sourcesContent":["import { o } from '@cat-kit/core'\nimport { extractNormalVNodes } from '@veltra/utils'\nimport { useSlots, type VNode } from 'vue'\n\nexport type SlotRenderItem = {\n isFormItem: boolean\n formItemProps?: Record<string, any>\n node: VNode\n field?: string\n modelValue?: any\n}\n\n/**\n * 虚拟node拦截\n * @returns\n */\nexport function useNodeInterceptor(): { getSlotsNodes: () => SlotRenderItem[] | null } {\n const slots = useSlots()\n\n function getSlotsNodes() {\n const nodes = slots.default?.()\n if (!nodes?.length) return null\n\n const flattedNodes = extractNormalVNodes(nodes)\n\n const results: SlotRenderItem[] = []\n\n let i = 0\n while (i < flattedNodes.length) {\n const node = flattedNodes[i]!\n i++\n\n const { props, type } = node\n const field = props?.field as string | undefined\n const isFormItem = (type as any)?.name === 'FormItem'\n const formItemProps = o((props ?? {}) as Record<string, any>).pick([\n 'label',\n 'rules',\n 'span',\n 'tips',\n 'readonly',\n 'field'\n ]) as Record<string, any>\n\n results.push({\n isFormItem,\n formItemProps,\n node,\n field,\n modelValue: props?.['model-value'] ?? props?.modelValue\n })\n }\n\n return results\n }\n\n return { getSlotsNodes }\n}\n"],"mappings":";;;;;;;;AAgBA,SAAgB,qBAAuE;CACrF,MAAM,QAAQ,SAAS;CAEvB,SAAS,gBAAgB;EACvB,MAAM,QAAQ,MAAM,UAAU;EAC9B,IAAI,CAAC,OAAO,QAAQ,OAAO;EAE3B,MAAM,eAAe,oBAAoB,KAAK;EAE9C,MAAM,UAA4B,CAAC;EAEnC,IAAI,IAAI;EACR,OAAO,IAAI,aAAa,QAAQ;GAC9B,MAAM,OAAO,aAAa;GAC1B;GAEA,MAAM,EAAE,OAAO,SAAS;GACxB,MAAM,QAAQ,OAAO;GACrB,MAAM,aAAc,MAAc,SAAS;GAC3C,MAAM,gBAAgB,EAAG,SAAS,CAAC,CAAyB,EAAE,KAAK;IACjE;IACA;IACA;IACA;IACA;IACA;GACF,CAAC;GAED,QAAQ,KAAK;IACX;IACA;IACA;IACA;IACA,YAAY,QAAQ,kBAAkB,OAAO;GAC/C,CAAC;EACH;EAEA,OAAO;CACT;CAEA,OAAO,EAAE,cAAc;AACzB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"form-item.js","names":[],"sources":["../../../src/components/form-item/form-item.vue"],"sourcesContent":["<template>\n <u-grid-item :span=\"span\" :class=\"className\">\n <label\n v-if=\"props.label || $slots.label\"\n :class=\"[cls.e('label'), bem.is('required',
|
|
1
|
+
{"version":3,"file":"form-item.js","names":[],"sources":["../../../src/components/form-item/form-item.vue"],"sourcesContent":["<template>\n <u-grid-item :span=\"span\" :class=\"className\">\n <label\n v-if=\"props.label || $slots.label\"\n :class=\"[cls.e('label'), bem.is('required', !!rules?.required)]\"\n :style=\"labelStyles\"\n >\n <u-tip v-if=\"tips\" :content=\"tips\" :class=\"cls.e('tips')\">\n <span :class=\"cls.e('tip-label')\">\n <slot name=\"label\">{{ label }}:</slot>\n </span>\n </u-tip>\n <template v-else>\n <slot name=\"label\">{{ label }}:</slot>\n </template>\n </label>\n\n <section :class=\"cls.e('wrapper')\">\n <div :class=\"cls.e('content')\">\n <slot></slot>\n </div>\n\n <!-- 只有表单控件处于非只读状态时,才显示错误提示 -->\n <section :class=\"cls.e('error')\" v-if=\"!readonly && !formProps?.noTips\">\n <transition name=\"form-item-tips\" mode=\"out-in\">\n <span :class=\"cls.e('error-text')\" v-if=\"!!errorTip\">\n {{ errorTip }}\n </span>\n </transition>\n </section>\n </section>\n </u-grid-item>\n</template>\n\n<script lang=\"tsx\" setup>\nimport { o } from '@cat-kit/core'\nimport { useConfig, useFallbackProps } from '@veltra/compositions'\nimport { bem, withUnit } from '@veltra/utils'\nimport { injectFormContext } from '@veltra/utils'\nimport { type CSSProperties, computed, onBeforeUnmount, shallowRef, watch } from 'vue'\n\nimport type { FormItemProps, ComponentSize } from '../../types'\nimport { UGridItem } from '../grid'\nimport { UTip } from '../tip'\nimport { formItemCls as cls, defineField } from './helper'\nimport { validateField } from './validate'\n\ndefineOptions({ name: 'FormItem' })\n\nconst props = withDefaults(defineProps<FormItemProps>(), { readonly: undefined })\n\ndefineSlots<{\n /** 标签插槽 */\n label?: () => any\n default?: () => any\n}>()\n\n/** 表单组件上下文 */\nconst { formProps, registerField, unregisterField, shouldValidate } = injectFormContext()\n\nconst { config } = useConfig()\n\nconst { size, readonly } = useFallbackProps([formProps ?? {}, props], {\n size: 'default' as ComponentSize,\n readonly: false\n})\n\nconst errorTip = shallowRef<string>()\n/** 递增序号,丢弃过期的异步校验结果 */\nlet validateSeq = 0\n/** 最近一次 validate 的 Promise,供过期调用等待最新结果 */\nlet latestValidatePromise: Promise<boolean> = Promise.resolve(true)\n\nconst className = computed(() => {\n return [cls.b, cls.m(size.value), bem.is('error', !!errorTip.value)].join(' ')\n})\n\n/** label样式 */\nconst labelStyles = computed<CSSProperties>(() => {\n return {\n width: withUnit(props.labelWidth ?? formProps?.labelWidth ?? config.form.labelWidth, 'px')\n }\n})\n\nconst fieldItem = defineField({\n clearValidate() {\n errorTip.value = ''\n },\n async validate() {\n if (!props.field || !formProps?.model || !props.rules || !shouldValidate?.()) return true\n\n const seq = ++validateSeq\n\n latestValidatePromise = validateField(formProps.model!, props.field!, props.rules!).then(\n (tip) => {\n if (seq !== validateSeq) return latestValidatePromise\n\n errorTip.value = tip\n return !errorTip.value\n }\n )\n return latestValidatePromise\n }\n})\n\nwatch(\n () => props.field,\n (field, oldField) => {\n if (oldField) {\n unregisterField?.(oldField)\n }\n if (field) {\n registerField?.(field, fieldItem)\n }\n },\n { immediate: true }\n)\n\nlet stopWatchFieldValue: (() => void) | undefined\n\nwatch(\n [() => formProps?.model, () => props.field],\n ([model, field]) => {\n stopWatchFieldValue?.()\n\n if (!field || !model) return\n\n stopWatchFieldValue = watch(\n () => o(model).get(field),\n () => {\n fieldItem.validate()\n }\n )\n },\n { immediate: true }\n)\n\nonBeforeUnmount(() => {\n props.field && unregisterField?.(props.field)\n})\n</script>\n"],"mappings":""}
|
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
import _sfc_main from "../tip/tip.js";
|
|
2
2
|
import _sfc_main$1 from "../grid/grid-item.js";
|
|
3
|
-
import { formItemCls } from "./helper.js";
|
|
4
|
-
import {
|
|
3
|
+
import { defineField, formItemCls } from "./helper.js";
|
|
4
|
+
import { validateField } from "./validate.js";
|
|
5
|
+
import { Transition, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, normalizeClass, normalizeStyle, onBeforeUnmount, openBlock, renderSlot, shallowRef, toDisplayString, unref, watch, withCtx } from "vue";
|
|
5
6
|
import { useConfig, useFallbackProps } from "@veltra/compositions";
|
|
6
7
|
import { bem, injectFormContext, withUnit } from "@veltra/utils";
|
|
8
|
+
import { o } from "@cat-kit/core";
|
|
7
9
|
//#region src/components/form-item/form-item.vue?vue&type=script&setup=true&lang.tsx
|
|
8
10
|
var form_item_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComponent({
|
|
9
11
|
name: "FormItem",
|
|
10
12
|
__name: "form-item",
|
|
11
13
|
props: {
|
|
12
14
|
labelWidth: {},
|
|
15
|
+
rules: {},
|
|
13
16
|
tips: {},
|
|
14
17
|
span: {},
|
|
15
18
|
label: {},
|
|
@@ -24,34 +27,57 @@ var form_item_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ define
|
|
|
24
27
|
setup(__props) {
|
|
25
28
|
const props = __props;
|
|
26
29
|
/** 表单组件上下文 */
|
|
27
|
-
const { formProps } = injectFormContext();
|
|
30
|
+
const { formProps, registerField, unregisterField, shouldValidate } = injectFormContext();
|
|
28
31
|
const { config } = useConfig();
|
|
29
32
|
const { size, readonly } = useFallbackProps([formProps ?? {}, props], {
|
|
30
33
|
size: "default",
|
|
31
34
|
readonly: false
|
|
32
35
|
});
|
|
36
|
+
const errorTip = shallowRef();
|
|
37
|
+
/** 递增序号,丢弃过期的异步校验结果 */
|
|
38
|
+
let validateSeq = 0;
|
|
39
|
+
/** 最近一次 validate 的 Promise,供过期调用等待最新结果 */
|
|
40
|
+
let latestValidatePromise = Promise.resolve(true);
|
|
33
41
|
const className = computed(() => {
|
|
34
42
|
return [
|
|
35
43
|
formItemCls.b,
|
|
36
44
|
formItemCls.m(size.value),
|
|
37
|
-
bem.is("error", !!
|
|
45
|
+
bem.is("error", !!errorTip.value)
|
|
38
46
|
].join(" ");
|
|
39
47
|
});
|
|
40
48
|
/** label样式 */
|
|
41
49
|
const labelStyles = computed(() => {
|
|
42
50
|
return { width: withUnit(props.labelWidth ?? formProps?.labelWidth ?? config.form.labelWidth, "px") };
|
|
43
51
|
});
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
52
|
+
const fieldItem = defineField({
|
|
53
|
+
clearValidate() {
|
|
54
|
+
errorTip.value = "";
|
|
55
|
+
},
|
|
56
|
+
async validate() {
|
|
57
|
+
if (!props.field || !formProps?.model || !props.rules || !shouldValidate?.()) return true;
|
|
58
|
+
const seq = ++validateSeq;
|
|
59
|
+
latestValidatePromise = validateField(formProps.model, props.field, props.rules).then((tip) => {
|
|
60
|
+
if (seq !== validateSeq) return latestValidatePromise;
|
|
61
|
+
errorTip.value = tip;
|
|
62
|
+
return !errorTip.value;
|
|
63
|
+
});
|
|
64
|
+
return latestValidatePromise;
|
|
65
|
+
}
|
|
48
66
|
});
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
67
|
+
watch(() => props.field, (field, oldField) => {
|
|
68
|
+
if (oldField) unregisterField?.(oldField);
|
|
69
|
+
if (field) registerField?.(field, fieldItem);
|
|
70
|
+
}, { immediate: true });
|
|
71
|
+
let stopWatchFieldValue;
|
|
72
|
+
watch([() => formProps?.model, () => props.field], ([model, field]) => {
|
|
73
|
+
stopWatchFieldValue?.();
|
|
74
|
+
if (!field || !model) return;
|
|
75
|
+
stopWatchFieldValue = watch(() => o(model).get(field), () => {
|
|
76
|
+
fieldItem.validate();
|
|
77
|
+
});
|
|
78
|
+
}, { immediate: true });
|
|
79
|
+
onBeforeUnmount(() => {
|
|
80
|
+
props.field && unregisterField?.(props.field);
|
|
55
81
|
});
|
|
56
82
|
return (_ctx, _cache) => {
|
|
57
83
|
return openBlock(), createBlock(unref(_sfc_main$1), {
|
|
@@ -60,7 +86,7 @@ var form_item_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ define
|
|
|
60
86
|
}, {
|
|
61
87
|
default: withCtx(() => [props.label || _ctx.$slots.label ? (openBlock(), createElementBlock("label", {
|
|
62
88
|
key: 0,
|
|
63
|
-
class: normalizeClass([unref(formItemCls).e("label"), unref(bem).is("required",
|
|
89
|
+
class: normalizeClass([unref(formItemCls).e("label"), unref(bem).is("required", !!__props.rules?.required)]),
|
|
64
90
|
style: normalizeStyle(labelStyles.value)
|
|
65
91
|
}, [__props.tips ? (openBlock(), createBlock(unref(_sfc_main), {
|
|
66
92
|
key: 0,
|
|
@@ -72,17 +98,17 @@ var form_item_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ define
|
|
|
72
98
|
}, 8, ["content", "class"])) : renderSlot(_ctx.$slots, "label", { key: 1 }, () => [createTextVNode(toDisplayString(__props.label) + ":", 1)])], 6)) : createCommentVNode("v-if", true), createElementVNode("section", { class: normalizeClass(unref(formItemCls).e("wrapper")) }, [
|
|
73
99
|
createElementVNode("div", { class: normalizeClass(unref(formItemCls).e("content")) }, [renderSlot(_ctx.$slots, "default")], 2),
|
|
74
100
|
createCommentVNode(" 只有表单控件处于非只读状态时,才显示错误提示 "),
|
|
75
|
-
!unref(
|
|
101
|
+
!unref(readonly) && !unref(formProps)?.noTips ? (openBlock(), createElementBlock("section", {
|
|
76
102
|
key: 0,
|
|
77
103
|
class: normalizeClass(unref(formItemCls).e("error"))
|
|
78
104
|
}, [createVNode(Transition, {
|
|
79
105
|
name: "form-item-tips",
|
|
80
106
|
mode: "out-in"
|
|
81
107
|
}, {
|
|
82
|
-
default: withCtx(() => [!!
|
|
108
|
+
default: withCtx(() => [!!errorTip.value ? (openBlock(), createElementBlock("span", {
|
|
83
109
|
key: 0,
|
|
84
110
|
class: normalizeClass(unref(formItemCls).e("error-text"))
|
|
85
|
-
}, toDisplayString(
|
|
111
|
+
}, toDisplayString(errorTip.value), 3)) : createCommentVNode("v-if", true)]),
|
|
86
112
|
_: 1
|
|
87
113
|
})], 2)) : createCommentVNode("v-if", true)
|
|
88
114
|
], 2)]),
|