From e245c9adccab92c5b1e11257bab5887da3ff054c Mon Sep 17 00:00:00 2001 From: lejunyang Date: Fri, 1 Nov 2024 22:52:26 +0800 Subject: [PATCH] docs: add useForm and update other docs; bump vitepress; fix workflow issue --- .changeset/curvy-brooms-kiss.md | 13 +++- .github/workflows/build.yml | 6 ++ package.json | 2 +- pnpm-lock.yaml | 74 +++++++++---------- src/components/Layout.vue | 6 +- src/docs/.vitepress/config.ts | 2 + src/docs/.vitepress/locales.ts | 2 + src/docs/components/form/index.md | 12 ++- src/docs/components/use-form/index.md | 102 ++++++++++++++++++++++++++ src/docs/index.md | 2 +- src/utils/data.ts | 28 +++++++ 11 files changed, 204 insertions(+), 45 deletions(-) create mode 100644 src/docs/components/use-form/index.md diff --git a/.changeset/curvy-brooms-kiss.md b/.changeset/curvy-brooms-kiss.md index 8214d11c..89d5906f 100644 --- a/.changeset/curvy-brooms-kiss.md +++ b/.changeset/curvy-brooms-kiss.md @@ -9,6 +9,13 @@ ## Features -- `config`: add `transitionRegistry` and `componentTransitions` global context config; add `useTransition` hook and `registerTransition` util -- `dialog`: add custom renderer for header, remove `title` prop -- `switch`: add `beforeUpdate` to asynchronously determine whether to update checked status +- `components/config`: add `transitionRegistry` and `componentTransitions` global context config; add `useTransition` hook and `registerTransition` util +- `components/dialog`: add custom renderer for header, remove `title` prop +- `components/switch`: add `beforeUpdate` to asynchronously determine whether to update checked status + +## Bug Fixes + +- `components/tree`: fix check methods are not working +- `components/tree`: fix wrong expose type; fix items processing issue +- `core/createCollector`: parent element can be undefined when adding item; invode getParentEl if collectOnSetup is true +- `theme/form-item`: fix vertical align issue of checkbox-group and radio-group in form-item \ No newline at end of file diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2c3fb9b0..e6a22869 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -6,6 +6,12 @@ on: # Allows you to run this workflow manually from the Actions tab workflow_dispatch: +# must have permissons same as call_docs +permissions: + contents: read + pages: write + id-token: write + jobs: build_packages: if: ${{ !contains(github.event.head_commit.message, '[all skip]') && !contains(github.event.head_commit.message, '[build skip]') }} diff --git a/package.json b/package.json index 39a7c6b2..1706c94b 100644 --- a/package.json +++ b/package.json @@ -64,7 +64,7 @@ "v-lazy-show": "^0.2.4", "vite": "catalog:", "vite-plugin-dts": "catalog:", - "vitepress": "1.4.1", + "vitepress": "1.4.3", "vitest": "catalog:", "vitest-browser-vue": "^0.0.1", "vue-tsc": "catalog:" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ebb316ba..33e8bba5 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -178,8 +178,8 @@ importers: specifier: 'catalog:' version: 4.3.0(@types/node@22.2.0)(rollup@4.22.2)(typescript@5.6.3)(vite@5.4.10(@types/node@22.2.0)(sass-embedded@1.80.4)(sass@1.77.6)(terser@5.36.0)) vitepress: - specifier: 1.4.1 - version: 1.4.1(@algolia/client-search@4.24.0)(@types/node@22.2.0)(postcss@8.4.39)(react-dom@19.0.0-rc-cae764ce-20241025(react@19.0.0-rc-cae764ce-20241025))(react@19.0.0-rc-cae764ce-20241025)(sass-embedded@1.80.4)(sass@1.77.6)(search-insights@2.14.0)(terser@5.36.0)(types-react@19.0.0-rc.1)(typescript@5.6.3) + specifier: 1.4.3 + version: 1.4.3(@algolia/client-search@4.24.0)(@types/node@22.2.0)(postcss@8.4.39)(react-dom@19.0.0-rc-cae764ce-20241025(react@19.0.0-rc-cae764ce-20241025))(react@19.0.0-rc-cae764ce-20241025)(sass-embedded@1.80.4)(sass@1.77.6)(search-insights@2.14.0)(terser@5.36.0)(types-react@19.0.0-rc.1)(typescript@5.6.3) vitest: specifier: 'catalog:' version: 2.1.3(@types/node@22.2.0)(@vitest/browser@2.1.3)(happy-dom@15.7.4)(msw@2.5.1(@types/node@22.2.0)(typescript@5.6.3))(sass-embedded@1.80.4)(sass@1.77.6)(terser@5.36.0) @@ -1183,20 +1183,20 @@ packages: '@rushstack/ts-command-line@4.23.0': resolution: {integrity: sha512-jYREBtsxduPV6ptNq8jOKp9+yx0ld1Tb/Tkdnlj8gTjazl1sF3DwX2VbluyYrNd0meWIL0bNeer7WDf5tKFjaQ==} - '@shikijs/core@1.22.1': - resolution: {integrity: sha512-bqAhT/Ri5ixV4oYsvJNH8UJjpjbINWlWyXY6tBTsP4OmD6XnFv43nRJ+lTdxd2rmG5pgam/x+zGR6kLRXrpEKA==} + '@shikijs/core@1.22.2': + resolution: {integrity: sha512-bvIQcd8BEeR1yFvOYv6HDiyta2FFVePbzeowf5pPS1avczrPK+cjmaxxh0nx5QzbON7+Sv0sQfQVciO7bN72sg==} - '@shikijs/engine-javascript@1.22.1': - resolution: {integrity: sha512-540pyoy0LWe4jj2BVbgELwOFu1uFvRI7lg4hdsExrSXA9x7gqfzZ/Nnh4RfX86aDAgJ647gx4TCmRwACbnQSvw==} + '@shikijs/engine-javascript@1.22.2': + resolution: {integrity: sha512-iOvql09ql6m+3d1vtvP8fLCVCK7BQD1pJFmHIECsujB0V32BJ0Ab6hxk1ewVSMFA58FI0pR2Had9BKZdyQrxTw==} - '@shikijs/engine-oniguruma@1.22.1': - resolution: {integrity: sha512-L+1Vmd+a2kk8HtogUFymQS6BjUfJnzcWoUp1BUgxoDiklbKSMvrsMuLZGevTOP1m0rEjgnC5MsDmsr8lX1lC+Q==} + '@shikijs/engine-oniguruma@1.22.2': + resolution: {integrity: sha512-GIZPAGzQOy56mGvWMoZRPggn0dTlBf1gutV5TdceLCZlFNqWmuc7u+CzD0Gd9vQUTgLbrt0KLzz6FNprqYAxlA==} - '@shikijs/transformers@1.22.1': - resolution: {integrity: sha512-KvG49YFV6gV116sC4L3Sn1Rp6HXsioMKBBG373j088rw849440hm8s2r+/dgjsGLvT4p+QB7newev+5a3ARM6w==} + '@shikijs/transformers@1.22.2': + resolution: {integrity: sha512-8f78OiBa6pZDoZ53lYTmuvpFPlWtevn23bzG+azpPVvZg7ITax57o/K3TC91eYL3OMJOO0onPbgnQyZjRos8XQ==} - '@shikijs/types@1.22.1': - resolution: {integrity: sha512-+45f8mu/Hxqs6Kyhfm98Nld5n7Q7lwhjU8UtdQwrOPs7BnM4VAb929O3IQ2ce+4D7SlNFlZGd8CnKRSnwbQreQ==} + '@shikijs/types@1.22.2': + resolution: {integrity: sha512-NCWDa6LGZqTuzjsGfXOBWfjS/fDIbDdmVDug+7ykVe1IKT4c1gakrvlfFYp5NhAXH/lyqLM8wsAPo5wNy73Feg==} '@shikijs/vscode-textmate@9.3.0': resolution: {integrity: sha512-jn7/7ky30idSkd/O5yDBfAnVt+JJpepofP/POZ1iMOxK59cOfqIgg/Dj0eFsjOTMw+4ycJN0uhZH/Eb0bs/EUA==} @@ -2718,8 +2718,8 @@ packages: resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} engines: {node: '>=8'} - shiki@1.22.1: - resolution: {integrity: sha512-PbJ6XxrWLMwB2rm3qdjIHNm3zq4SfFnOx0B3rEoi4AN8AUngsdyZ1tRe5slMPtn6jQkbUURLNZPpLR7Do3k78g==} + shiki@1.22.2: + resolution: {integrity: sha512-3IZau0NdGKXhH2bBlUk4w1IHNxPh6A5B2sUpyY+8utLu2j/h1QpFkAaUA1bAMxOWWGtTWcAh531vnS4NJKS/lA==} siginfo@2.0.0: resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} @@ -3010,8 +3010,8 @@ packages: terser: optional: true - vitepress@1.4.1: - resolution: {integrity: sha512-C2rQ7PMlDVqgsaHOa0uJtgGGWaGv74QMaGL62lxKbtFkYtosJB5HAfZ8+pEbfzzvLemYaYwaiQdFLBlexK2sFw==} + vitepress@1.4.3: + resolution: {integrity: sha512-956c2K2Mr0ubY9bTc2lCJD3g0mgo0mARB1iJC/BqUt4s0AM8Wl60wSU4zbFnzV7X2miFK1XJDKzGZnuEN90umw==} hasBin: true peerDependencies: markdown-it-mathjax3: ^4 @@ -4084,31 +4084,31 @@ snapshots: transitivePeerDependencies: - '@types/node' - '@shikijs/core@1.22.1': + '@shikijs/core@1.22.2': dependencies: - '@shikijs/engine-javascript': 1.22.1 - '@shikijs/engine-oniguruma': 1.22.1 - '@shikijs/types': 1.22.1 + '@shikijs/engine-javascript': 1.22.2 + '@shikijs/engine-oniguruma': 1.22.2 + '@shikijs/types': 1.22.2 '@shikijs/vscode-textmate': 9.3.0 '@types/hast': 3.0.4 hast-util-to-html: 9.0.3 - '@shikijs/engine-javascript@1.22.1': + '@shikijs/engine-javascript@1.22.2': dependencies: - '@shikijs/types': 1.22.1 + '@shikijs/types': 1.22.2 '@shikijs/vscode-textmate': 9.3.0 oniguruma-to-js: 0.4.3 - '@shikijs/engine-oniguruma@1.22.1': + '@shikijs/engine-oniguruma@1.22.2': dependencies: - '@shikijs/types': 1.22.1 + '@shikijs/types': 1.22.2 '@shikijs/vscode-textmate': 9.3.0 - '@shikijs/transformers@1.22.1': + '@shikijs/transformers@1.22.2': dependencies: - shiki: 1.22.1 + shiki: 1.22.2 - '@shikijs/types@1.22.1': + '@shikijs/types@1.22.2': dependencies: '@shikijs/vscode-textmate': 9.3.0 '@types/hast': 3.0.4 @@ -5664,12 +5664,12 @@ snapshots: shebang-regex@3.0.0: {} - shiki@1.22.1: + shiki@1.22.2: dependencies: - '@shikijs/core': 1.22.1 - '@shikijs/engine-javascript': 1.22.1 - '@shikijs/engine-oniguruma': 1.22.1 - '@shikijs/types': 1.22.1 + '@shikijs/core': 1.22.2 + '@shikijs/engine-javascript': 1.22.2 + '@shikijs/engine-oniguruma': 1.22.2 + '@shikijs/types': 1.22.2 '@shikijs/vscode-textmate': 9.3.0 '@types/hast': 3.0.4 @@ -5942,13 +5942,13 @@ snapshots: sass-embedded: 1.80.4 terser: 5.36.0 - vitepress@1.4.1(@algolia/client-search@4.24.0)(@types/node@22.2.0)(postcss@8.4.39)(react-dom@19.0.0-rc-cae764ce-20241025(react@19.0.0-rc-cae764ce-20241025))(react@19.0.0-rc-cae764ce-20241025)(sass-embedded@1.80.4)(sass@1.77.6)(search-insights@2.14.0)(terser@5.36.0)(types-react@19.0.0-rc.1)(typescript@5.6.3): + vitepress@1.4.3(@algolia/client-search@4.24.0)(@types/node@22.2.0)(postcss@8.4.39)(react-dom@19.0.0-rc-cae764ce-20241025(react@19.0.0-rc-cae764ce-20241025))(react@19.0.0-rc-cae764ce-20241025)(sass-embedded@1.80.4)(sass@1.77.6)(search-insights@2.14.0)(terser@5.36.0)(types-react@19.0.0-rc.1)(typescript@5.6.3): dependencies: '@docsearch/css': 3.6.2 '@docsearch/js': 3.6.2(@algolia/client-search@4.24.0)(react-dom@19.0.0-rc-cae764ce-20241025(react@19.0.0-rc-cae764ce-20241025))(react@19.0.0-rc-cae764ce-20241025)(search-insights@2.14.0)(types-react@19.0.0-rc.1) - '@shikijs/core': 1.22.1 - '@shikijs/transformers': 1.22.1 - '@shikijs/types': 1.22.1 + '@shikijs/core': 1.22.2 + '@shikijs/transformers': 1.22.2 + '@shikijs/types': 1.22.2 '@types/markdown-it': 14.1.2 '@vitejs/plugin-vue': 5.1.4(vite@5.4.10(@types/node@22.2.0)(sass-embedded@1.80.4)(sass@1.77.6)(terser@5.36.0))(vue@3.5.12(typescript@5.6.3)) '@vue/devtools-api': 7.5.4 @@ -5958,7 +5958,7 @@ snapshots: focus-trap: 7.6.0 mark.js: 8.11.1 minisearch: 7.1.0 - shiki: 1.22.1 + shiki: 1.22.2 vite: 5.4.10(@types/node@22.2.0)(sass-embedded@1.80.4)(sass@1.77.6)(terser@5.36.0) vue: 3.5.12(typescript@5.6.3) optionalDependencies: diff --git a/src/components/Layout.vue b/src/components/Layout.vue index 7bf865e3..3ce0db95 100644 --- a/src/components/Layout.vue +++ b/src/components/Layout.vue @@ -47,8 +47,10 @@ 2 3 - Get Started - View + + Get Started + + View
设置全局组件缩放系数
选择全局组件大小
diff --git a/src/docs/.vitepress/config.ts b/src/docs/.vitepress/config.ts index f640d466..5ebba66d 100644 --- a/src/docs/.vitepress/config.ts +++ b/src/docs/.vitepress/config.ts @@ -129,6 +129,7 @@ const getThemeConfig = (lang: keyof typeof locales = 'zh-CN') => { link: wrapLink('/components/form/', lang), collapsed: true, items: [ + { text: locales[lang].sidebar.dataDisplay.useForm, link: wrapLink('/components/use-form/', lang) }, { text: locales[lang].sidebar.dataDisplay.formItem, link: wrapLink('/components/form-item/', lang) }, ], }, @@ -214,6 +215,7 @@ export default defineConfig({ }; }, }, + appearance: 'dark', vite: viteConfig, head: [], lastUpdated: true, diff --git a/src/docs/.vitepress/locales.ts b/src/docs/.vitepress/locales.ts index 7a8f517b..cc86a1cb 100644 --- a/src/docs/.vitepress/locales.ts +++ b/src/docs/.vitepress/locales.ts @@ -32,6 +32,7 @@ export default { menu: '复杂数据', calendar: 'Calendar 日历', form: 'Form 表单', + useForm: 'useForm', formItem: 'FormItem 表单项', table: 'Table 表格', tree: 'Tree 树', @@ -150,6 +151,7 @@ export default { menu: 'Complex Data', calendar: 'Calendar', form: 'Form', + useForm: 'useForm', formItem: 'FormItem', table: 'Table', tree: 'Tree', diff --git a/src/docs/components/form/index.md b/src/docs/components/form/index.md index a4360289..be55a0f7 100644 --- a/src/docs/components/form/index.md +++ b/src/docs/components/form/index.md @@ -3,6 +3,16 @@ title: Form 表单 lang: zh-CN --- +- 自动接管输入组件的值更新,可随意响应式更新 +- 支持嵌套深层字段,支持数组字段 +- 支持字段自动触发其他字段,如清除、禁用、必输、校验 +- 支持校验规则设置为其他字段的值,自动更新规则与校验 +- 校验信息多样,支持错误、警告、成功多种类型的校验信息展示 +- 支持多表单处理,支持字段统一属性设置 +- 灵活布局,对齐简易 + +使用示例有待更新 + ## 基本使用 表单由若干表单项(`l-form-item`)和表单项下的输入组件构成,每一个表单项代表一个字段,由`name`属性指定字段名称,支持链式路径(如`a.b.c`, `d[0]`)和数组(`['a', 'b', 'c']`) @@ -11,7 +21,7 @@ lang: zh-CN 表单由`useForm`产生的实例进行管控,该实例可被多个表单共享,其用于方便管理表单的数据、状态、方法以及事件。如果不指定`instance`,那么内部会创建一个 -实例的属性和方法都会暴露到组件 DOM 节点本身,ts 类型过长暂不列出,你可以在控制台选中节点,通过`dir($0)`查看有哪些属性和方法 +实例的属性和方法都会暴露到组件 DOM 节点本身,你前往下一小节查看其具体类型 diff --git a/src/docs/components/use-form/index.md b/src/docs/components/use-form/index.md new file mode 100644 index 00000000..d0436228 --- /dev/null +++ b/src/docs/components/use-form/index.md @@ -0,0 +1,102 @@ +--- +title: useForm +lang: zh-CN +--- + +`useForm`用于生成表单实例,管理表单数据和表单状态,并提供一系列方法和钩子函数,帮助开发者更方便地处理表单相关的逻辑。 + +## 参数 + +```ts +export type UseFormOptions = { + config?: Record; // 暂未使用 + defaultData?: Partial; + defaultFormState?: Partial; + hooks?: FormHooksOptions; +}; +``` + +## 钩子函数 + +有待以后完善文档 + +```ts +const hooks = { + // form lifecycle + onFormConnected: createSyncHook<(formInstance: ComponentInternalInstance) => void>(), + onFormDisconnected: createSyncHook<(formInstance: ComponentInternalInstance) => void>(), + // form-item lifecycle + onFormItemConnected: + createSyncHook<(vms: { item: ComponentInternalInstance; form: ComponentInternalInstance }) => void>(), + onFormItemDisconnected: + createSyncHook<(vms: { item: ComponentInternalInstance; form: ComponentInternalInstance }) => void>(), + // value updated + /** trigger when value of one field updates */ + onUpdateValue: createSyncHook<(param: UpdateValueParam) => UpdateValueParam | undefined>(), + onFormReset: createSyncHook<() => void>(), + // validate + onValidate: + createAsyncHook< + (param: Omit & Pick) => void + >(), +} +``` + +使用示例: + +```ts +const form = useForm({ + hooks: { + // add hooks on created + onFormConnected(formInstance) { + console.log('form connected', formInstance.props) + } + } +}) +// or +const onUpdateValue = ({ value, path }) => { + console.log('value updated', value, path) +} +form.hooks.onValidate.use(onUpdateValue) +// remove listener +form.hooks.onValidate.eject(onUpdateValue) +// use once +form.hooks.onValidate.use(onUpdateValue, { once: true }); +``` + +## 返回值 + +```ts +export type MaybeFormItemPath = string | string[] | null | undefined; +export type FormMethods = { + isPlainName(name?: string): boolean; + getValue(path: MaybeFormItemPath, raw?: boolean): any; + setValue(path: MaybeFormItemPath, value: any, rawValue?: any): void; + deletePath(path: MaybeFormItemPath): void; + resetFormData(): void; + resetFormState(): void; + validate(): Promise>>; + clearStatusMessages(): void; + setStatusMessages(path: MaybeFormItemPath, statusMsg: MaybeFormItemStatusMessages): void; + getStatusMessages( + path: MaybeFormItemPath, + status?: Status, + ): Status extends string ? string[] : Record; +}; +export type FormState = { + /** + * { field1: { error: ['msg'], warning: ['msg'] } } + */ + statusMessages: Record>; + isDirty: boolean; // 暂未实现 + dirtyFields: Set; // 暂未实现 +} & LocalEditState; + +// 返回的data、rawData、formState均为响应式,可直接修改 +export type UseFormReturn = { + data: Data; + rawData: unknown; + formState: FormState; + hooks: FormHooks; +} & FormMethods; +``` \ No newline at end of file diff --git a/src/docs/index.md b/src/docs/index.md index d8e5bcab..200db066 100644 --- a/src/docs/index.md +++ b/src/docs/index.md @@ -4,7 +4,7 @@ layout: home hero: name: Lun text: 基于Vue3的跨框架Web组件库 - tagline: 个人学习,勿用于生产环境 + tagline: 个人学习,暂勿用于生产环境 actions: - theme: brand text: 开始 diff --git a/src/utils/data.ts b/src/utils/data.ts index 0ed33ec3..2699041a 100644 --- a/src/utils/data.ts +++ b/src/utils/data.ts @@ -79,3 +79,31 @@ export const filesRenderer = (files) => ensureArray(files) .map((file) => file.name) .join(', '); + +export const treeItems = [ + { + label: 'Item 1', + value: '1', + children: [ + { + label: 'Item 1.1', + value: '1.1', + children: [ + { label: 'Item 1.1.1', value: '1.1.1' }, + { label: 'Item 1.1.2', value: '1.1.2' }, + { label: 'Item 1.1.3', value: '1.1.3', disabled: true }, + ], + }, + { label: 'Item 1.2', value: '1.2' }, + { + label: 'Item 1.3', + value: '1.3', + children: [{ label: 'Item 1.3.1', value: '1.3.1' }], + }, + ], + }, + { + label: 'Item 2', + value: '2', + }, +];