feat: 重构表单输入组件,添加文本输入类型,优化配置和样式
Some checks failed
/ test (push) Failing after 31s
/ surge (push) Successful in 45s

This commit is contained in:
严浩
2024-11-24 17:47:02 +08:00
parent 798954d6f3
commit 2aa80123b8
11 changed files with 257 additions and 40 deletions

View File

@ -6,6 +6,4 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: yanhao98/composite-actions/setup-node-environment@main - uses: yanhao98/composite-actions/setup-node-environment@main
- name: deploy - run: npx vue-tsc -b
run: |
npx vue-tsc -b

View File

@ -15,12 +15,13 @@ export function addAsteriskPlugin(node: FormKitNode) {
// } // }
console.debug(`legendOrLabel :>> `, legendOrLabel); console.debug(`legendOrLabel :>> `, legendOrLabel);
console.groupEnd() console.groupEnd()
if (!node.props.definition) return;
if (node.props.definition?.schemaMemoKey) { if (node.props.definition.schemaMemoKey) {
node.props.definition.schemaMemoKey += `${node.props.options ? '_multi' : ''}_add_asterisk`; node.props.definition.schemaMemoKey += `${node.props.options ? '_multi' : ''}_add_asterisk`;
}; };
const schemaFn = node.props.definition!.schema!; const schemaFn = node.props.definition.schema!;
node.props.definition!.schema = (sectionsSchema = {}) => { node.props.definition!.schema = (sectionsSchema = {}) => {
sectionsSchema[legendOrLabel] = { sectionsSchema[legendOrLabel] = {
children: ['$label', { children: ['$label', {

View File

@ -1,8 +1,8 @@
import { createAutoAnimatePlugin, createAutoHeightTextareaPlugin } from '@formkit/addons' import { createAutoAnimatePlugin, createAutoHeightTextareaPlugin } from '@formkit/addons'
import type { FormKitOptions } from '@formkit/core' import type { FormKitNode, FormKitOptions } from '@formkit/core'
import { createI18nPlugin, zh } from '@formkit/i18n' import { createI18nPlugin, zh } from '@formkit/i18n'
import { genesisIcons } from '@formkit/icons' import { genesisIcons } from '@formkit/icons'
import { createLibraryPlugin, submit } from '@formkit/inputs' import { createLibraryPlugin, submit, text } from '@formkit/inputs'
import { createProPlugin, toggle } from '@formkit/pro' import { createProPlugin, toggle } from '@formkit/pro'
import * as defaultRules from '@formkit/rules' import * as defaultRules from '@formkit/rules'
import { createThemePlugin } from '@formkit/themes' import { createThemePlugin } from '@formkit/themes'
@ -10,7 +10,7 @@ import { createValidationPlugin } from '@formkit/validation'
import { /* defaultConfig, */ bindings, createInput } from '@formkit/vue' import { /* defaultConfig, */ bindings, createInput } from '@formkit/vue'
import { addAsteriskPlugin } from './formkit.addAsteriskPlugin' import { addAsteriskPlugin } from './formkit.addAsteriskPlugin'
// import { fkLibrary } from './formkit.config.fkLibrary' // import { fkLibrary } from './formkit.config.fkLibrary'
import { rootClasses } from "./formkit.config.theme" // import { rootClasses } from "./formkit.config.theme"
import HeadlessuiToggle from "./src/headlessui-switch.vue" import HeadlessuiToggle from "./src/headlessui-switch.vue"
import { register as decodeErrors } from '@formkit/dev' import { register as decodeErrors } from '@formkit/dev'
@ -21,14 +21,20 @@ const validation = createValidationPlugin(defaultRules)
const theme = undefined; const theme = undefined;
const icons = genesisIcons; const icons = genesisIcons;
const apiKey = 'fk-6cdd5192223' // const apiKey = 'fk-6cdd5192223'
export default { export default {
plugins: [ plugins: [
createProPlugin(apiKey, { toggle }), // createProPlugin(apiKey, { toggle }),
// createLibraryPlugin(fkLibrary), // createLibraryPlugin(fkLibrary),
createLibraryPlugin({ createLibraryPlugin({
text,
submit, submit,
}), }),
// createLibraryPlugin(
// {
// 'headlessuiSwitch': createInput(HeadlessuiToggle),
// }
// ),
createThemePlugin(theme, icons/* , iconLoaderUrl, iconLoader */), createThemePlugin(theme, icons/* , iconLoaderUrl, iconLoader */),
bindings, bindings,
createI18nPlugin({ zh }), createI18nPlugin({ zh }),
@ -56,6 +62,10 @@ export default {
) )
], ],
config: { config: {
// rootClasses: false,
// rootClasses, // rootClasses,
// rootClasses: (sectionName: string, node: FormKitNode) => {
// console.debug(`sectionName :>> `, sectionName);
// }
}, },
} satisfies FormKitOptions } satisfies FormKitOptions

View File

@ -0,0 +1,14 @@
<template>
<div>
input-text.vue
</div>
</template>
<script setup lang="ts">
import { FormKitFrameworkContext } from '@formkit/core';
const props = defineProps<{
context: FormKitFrameworkContext & { 'some': string };
}>();
console.debug(`props.context.some :>> `, props.context.some);
</script>

View File

@ -1,6 +1,5 @@
import { FormKitTypeDefinition } from '@formkit/core' import { FormKitTypeDefinition } from '@formkit/core'
import { import {
formInput,
messages, messages,
message, message,
actions, actions,
@ -8,6 +7,7 @@ import {
forms, forms,
disablesChildren, disablesChildren,
} from '@formkit/inputs' } from '@formkit/inputs'
import { formInput } from '../sections/formInput'
/** /**
* Input definition for a form. * Input definition for a form.
@ -44,5 +44,5 @@ export const form: FormKitTypeDefinition = {
/** /**
* The key used to memoize the schema. * The key used to memoize the schema.
*/ */
schemaMemoKey: 'rorzq1rsrf', // schemaMemoKey: 'rorzq1rsrf',
} }

View File

@ -0,0 +1,68 @@
import { FormKitTypeDefinition } from '@formkit/core'
import {
outer,
inner,
wrapper,
label,
help,
messages,
message,
icon,
prefix,
suffix,
textInput,
casts,
createSection,
} from '@formkit/inputs'
/**
* Input definition for a text.
* @public
*/
export const text: FormKitTypeDefinition = {
/**
* The actual schema of the input, or a function that returns the schema.
*/
schema: outer(
wrapper(
label('$label'),
inner(
icon('prefix', 'label'),
prefix(),
textInput(),
suffix(),
icon('suffix')
)
),
help('$help'),
messages(message('$message.value'))
),
/**
* The type of node, can be a list, group, or input.
*/
type: 'input',
/**
* The family of inputs this one belongs too. For example "text" and "email"
* are both part of the "text" family. This is primary used for styling.
*/
family: 'text',
/**
* An array of extra props to accept for this input.
*/
props: [
// 'label2',
],
/**
* Forces node.props.type to be this explicit value.
*/
forceTypeProp: 'text',
/**
* Additional features that should be added to your input
*/
features: [casts],
/**
* The key used to memoize the schema.
*/
// schemaMemoKey: 'g2f31c24kjh',
}

View File

@ -0,0 +1,20 @@
import { createSection } from '@formkit/inputs'
/**
* Form section
*
* @public
*/
export const formInput = createSection('form', () => ({
$el: 'form',
bind: '$attrs',
meta: {
autoAnimate: true,
},
attrs: {
id: '$id',
name: '$node.name',
onSubmit: '$handlers.submit',
'data-loading': '$state.loading || undefined',
},
}))

View File

@ -1,10 +1,15 @@
<script setup lang="ts"> <script setup lang="ts">
import Swal from 'sweetalert2'; import Swal from 'sweetalert2';
import { form } from '../inputs/form' import { createInput, FormKitSummary } from '@formkit/vue'
import { FormKitSummary } from '@formkit/vue' import { form } from '__fk-inputs__/inputs/inputs/form';
import { text } from '@/__fk-inputs__/inputs/inputs/text';
import InputText from '@/__fk-inputs__/components/input-text.vue'
import { createSection, outer } from '@formkit/inputs'
import { FormKitTypeDefinition } from '@formkit/core';
import { markRaw } from 'vue';
async function submit() { async function submit() {
await new Promise(r => setTimeout(r, 300)) await new Promise(r => setTimeout(r, 500))
Swal.fire({ Swal.fire({
title: 'Submitted! 🎉', title: 'Submitted! 🎉',
icon: 'success', icon: 'success',
@ -12,20 +17,94 @@ async function submit() {
timer: 1500 timer: 1500
}) })
} }
/* const fooInput = createInput(
'hello11',
{
schemaMemoKey: '',
},
{
label: null,
}
)
console.debug(`fooInput :>> `, fooInput); */
const fooInput: FormKitTypeDefinition = {
type: 'input',
props: ['some'],
schema: outer(
createSection('input', () => ({
$cmp: 'cmpName',
props: {
context: '$node.context',
},
}))(),
),
library: {
'cmpName': markRaw(InputText),
},
// schema: createSection('input', () => ({
// $cmp: InputText,
// props: {
// context: '$node.context',
// },
// }))
}
</script> </script>
<template> <template>
<Fieldset
<!-- https://formkit.com/inputs/form#props-attributes --> legend="Form 1"
<FormKit pt:content:class="flex justify-center"
:type="form"
@submit="submit"
submit-label="提交 "
:submit-attrs="{ class: 'btn btn-primary' }"
:errors="['Our server is not working.', 'But we dont like you anyway!']"
incomplete-message="Please fill out all fields."
> >
<FormKitSummary /> <!-- https://formkit.com/inputs/form#props-attributes -->
<div>content</div> <FormKit
</FormKit> :config="{
classes: {
form: 'flex flex-col gap-4 w-full',
}
}"
:type="form"
@submit="submit"
submit-label="提交 "
:submit-attrs="{ class: 'btn btn-primary' }"
:errors="['our server is not working.', 'But we dont like you anyway!']"
incomplete-message="Please fill out all fields."
>
<FormKit
:type="fooInput"
label="fooInput"
some="prop"
validation="required"
validation-visibility="live"
>
</FormKit>
<FormKit
:type="text"
label="customType"
validation="required"
validation-visibility="live"
>
<!-- <template #label>
<div>labelll</div>
</template> -->
</FormKit>
<FormKit
type="text"
label="默认text"
validation="required"
validation-visibility="live"
>
</FormKit>
<FormKitSummary />
<div>content</div>
</FormKit>
</Fieldset>
</template> </template>

View File

@ -24,3 +24,9 @@ body {
background-color: #1f2937; background-color: #1f2937;
} }
} }
/* DEV: */
.formkit-outer {
border: 1px solid #e5e7eb;
}

View File

@ -1,12 +1,16 @@
{ {
"compilerOptions": { "compilerOptions": {
"baseUrl": ".",
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
"target": "ES2020", "target": "ES2020",
"useDefineForClassFields": true, "useDefineForClassFields": true,
"module": "ESNext", "module": "ESNext",
"lib": ["ES2020", "DOM", "DOM.Iterable"], "lib": [
"ES2020",
"DOM",
"DOM.Iterable"
],
"skipLibCheck": true, "skipLibCheck": true,
/* Bundler mode */ /* Bundler mode */
"moduleResolution": "Bundler", "moduleResolution": "Bundler",
"allowImportingTsExtensions": true, "allowImportingTsExtensions": true,
@ -14,13 +18,24 @@
"moduleDetection": "force", "moduleDetection": "force",
"noEmit": true, "noEmit": true,
"jsx": "preserve", "jsx": "preserve",
/* Linting */ /* Linting */
"strict": true, "strict": true,
"noUnusedLocals": true, "noUnusedLocals": true,
"noUnusedParameters": true, "noUnusedParameters": true,
"noFallthroughCasesInSwitch": true, "noFallthroughCasesInSwitch": true,
"noUncheckedSideEffectImports": true "noUncheckedSideEffectImports": true,
"paths": {
"@/*": [
"src/*"
],
"__fk-inputs__/*": [
"src/__fk-inputs__/*"
]
}
}, },
"include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"] "include": [
} "src/**/*.ts",
"src/**/*.tsx",
"src/**/*.vue"
]
}

View File

@ -6,14 +6,20 @@ import { PrimeVueResolver } from '@primevue/auto-import-resolver';
// https://vite.dev/config/ // https://vite.dev/config/
export default defineConfig({ export default defineConfig({
plugins: [vue(), UnoCSS(), plugins: [
Components({ vue(), UnoCSS(),
resolvers: [ Components({
PrimeVueResolver() resolvers: [
] PrimeVueResolver()
}) ]
})
], ],
resolve: {
alias: {
'__fk-inputs__': '/src/__fk-inputs__',
'@': '/src',
}
},
build: { build: {
sourcemap: true sourcemap: true
} }