From 6b3bcee5822043e1aace5c46a4b2f9f45732cb88 Mon Sep 17 00:00:00 2001 From: xingyu4j Date: Sat, 14 Mar 2026 21:34:48 +0800 Subject: [PATCH] docs(@vben/docs): sync component docs with current APIs --- docs/.vitepress/config/en.mts | 81 ++++++- docs/src/_env/adapter/form.ts | 2 + docs/src/components/common-ui/vben-alert.md | 87 ++------ .../common-ui/vben-api-component.md | 2 +- .../common-ui/vben-count-to-animator.md | 60 +++--- docs/src/components/common-ui/vben-drawer.md | 6 +- .../common-ui/vben-ellipsis-text.md | 50 ++--- docs/src/components/common-ui/vben-form.md | 80 +++---- docs/src/components/common-ui/vben-modal.md | 2 +- .../components/common-ui/vben-vxe-table.md | 127 +++++------ docs/src/components/layout-ui/page.md | 39 ++-- .../src/en/components/common-ui/vben-alert.md | 76 +++++++ .../common-ui/vben-api-component.md | 69 ++++++ .../common-ui/vben-count-to-animator.md | 51 +++++ .../en/components/common-ui/vben-drawer.md | 56 +++++ .../common-ui/vben-ellipsis-text.md | 42 ++++ docs/src/en/components/common-ui/vben-form.md | 203 ++++++++++++++++++ .../src/en/components/common-ui/vben-modal.md | 56 +++++ .../en/components/common-ui/vben-vxe-table.md | 87 ++++++++ docs/src/en/components/introduction.md | 15 ++ docs/src/en/components/layout-ui/page.md | 29 +++ 21 files changed, 937 insertions(+), 283 deletions(-) create mode 100644 docs/src/en/components/common-ui/vben-alert.md create mode 100644 docs/src/en/components/common-ui/vben-api-component.md create mode 100644 docs/src/en/components/common-ui/vben-count-to-animator.md create mode 100644 docs/src/en/components/common-ui/vben-drawer.md create mode 100644 docs/src/en/components/common-ui/vben-ellipsis-text.md create mode 100644 docs/src/en/components/common-ui/vben-form.md create mode 100644 docs/src/en/components/common-ui/vben-modal.md create mode 100644 docs/src/en/components/common-ui/vben-vxe-table.md create mode 100644 docs/src/en/components/introduction.md create mode 100644 docs/src/en/components/layout-ui/page.md diff --git a/docs/.vitepress/config/en.mts b/docs/.vitepress/config/en.mts index a74a7e5fb..8bac04ceb 100644 --- a/docs/.vitepress/config/en.mts +++ b/docs/.vitepress/config/en.mts @@ -42,6 +42,10 @@ export const en = defineConfig({ base: '/en/commercial/', items: sidebarCommercial(), }, + '/en/components/': { + base: '/en/components/', + items: sidebarComponents(), + }, '/en/guide/': { base: '/en/guide/', items: sidebarGuide() }, }, }, @@ -63,6 +67,11 @@ function sidebarGuide(): DefaultTheme.SidebarItem[] { }, { link: 'introduction/quick-start', text: 'Quick Start' }, { link: 'introduction/thin', text: 'Lite Version' }, + { + base: '/', + link: 'components/introduction', + text: 'Components', + }, ], }, { @@ -132,6 +141,68 @@ function sidebarCommercial(): DefaultTheme.SidebarItem[] { ]; } +function sidebarComponents(): DefaultTheme.SidebarItem[] { + return [ + { + text: 'Components', + items: [ + { + link: 'introduction', + text: 'Introduction', + }, + ], + }, + { + collapsed: false, + text: 'Layout UI', + items: [ + { + link: 'layout-ui/page', + text: 'Page', + }, + ], + }, + { + collapsed: false, + text: 'Common UI', + items: [ + { + link: 'common-ui/vben-api-component', + text: 'ApiComponent', + }, + { + link: 'common-ui/vben-alert', + text: 'Alert', + }, + { + link: 'common-ui/vben-modal', + text: 'Modal', + }, + { + link: 'common-ui/vben-drawer', + text: 'Drawer', + }, + { + link: 'common-ui/vben-form', + text: 'Form', + }, + { + link: 'common-ui/vben-vxe-table', + text: 'Vxe Table', + }, + { + link: 'common-ui/vben-count-to-animator', + text: 'CountToAnimator', + }, + { + link: 'common-ui/vben-ellipsis-text', + text: 'EllipsisText', + }, + ], + }, + ]; +} + function nav(): DefaultTheme.NavItem[] { return [ { @@ -143,11 +214,11 @@ function nav(): DefaultTheme.NavItem[] { link: '/en/guide/introduction/vben', text: 'Guide', }, - // { - // activeMatch: '^/en/components/', - // link: '/en/components/introduction', - // text: 'Components', - // }, + { + activeMatch: '^/en/components/', + link: '/en/components/introduction', + text: 'Components', + }, { text: 'Historical Versions', items: [ diff --git a/docs/src/_env/adapter/form.ts b/docs/src/_env/adapter/form.ts index d8b51c254..30ced04e8 100644 --- a/docs/src/_env/adapter/form.ts +++ b/docs/src/_env/adapter/form.ts @@ -10,7 +10,9 @@ import { $t } from '@vben/locales'; import { initComponentAdapter } from './component'; +// oxlint-disable-next-line typescript/no-floating-promises initComponentAdapter(); + setupVbenForm({ config: { baseModelPropName: 'value', diff --git a/docs/src/components/common-ui/vben-alert.md b/docs/src/components/common-ui/vben-alert.md index 6541b665d..eebd1f857 100644 --- a/docs/src/components/common-ui/vben-alert.md +++ b/docs/src/components/common-ui/vben-alert.md @@ -4,132 +4,90 @@ outline: deep # Vben Alert 轻量提示框 -框架提供的一些用于轻量提示的弹窗,仅使用js代码即可快速动态创建提示而不需要在template写任何代码。 +`Alert` 提供了一组纯 JavaScript 调用的轻量提示框能力,适合快速创建 `alert`、`confirm`、`prompt` 这类简单交互。 -::: info 应用场景 +::: info 适用场景 -Alert提供的功能与Modal类似,但只适用于简单应用场景。例如临时性、动态地弹出模态确认框、输入框等。如果对弹窗有更复杂的需求,请使用VbenModal - -::: +`Alert` 与 `Modal` 的能力有部分重叠,但更适合临时确认、简单提示和轻量输入场景。复杂弹窗仍然建议使用 `Vben Modal`。::: ::: tip 注意 -Alert提供的快捷方法alert、confirm、prompt动态创建的弹窗在已打开的情况下,不支持HMR(热更新),代码变更后需要关闭这些弹窗后重新打开。 - -::: - -::: tip README - -下方示例代码中的,存在一些主题色未适配、样式缺失的问题,这些问题只在文档内会出现,实际使用并不会有这些问题,可忽略,不必纠结。 - -::: +通过 `alert`、`confirm`、`prompt` 动态创建的弹窗,在已经打开的情况下不支持 HMR 热更新。修改相关代码后,需要关闭后重新打开。::: ## 基础用法 -使用 `alert` 创建只有一个确认按钮的提示框。 +使用 `alert` 创建只有确认按钮的提示框。 -使用 `confirm` 创建有确认和取消按钮的提示框。 +使用 `confirm` 创建带确认和取消按钮的提示框。 -使用 `prompt` 创建有确认和取消按钮、接受用户输入的提示框。 +使用 `prompt` 创建可接收用户输入的提示框。 ## useAlertContext -当弹窗的content、footer、icon使用自定义组件时,在这些组件中可以使用 `useAlertContext` 获取当前弹窗的上下文对象,用来主动控制弹窗。 +当 `content`、`footer` 或 `icon` 使用的是自定义组件时,可以在这些组件内部通过 `useAlertContext()` 获取当前弹窗上下文,并主动触发确认或取消。 ::: tip 注意 -`useAlertContext`只能用在setup或者函数式组件中。 - -::: +`useAlertContext` 只能在 `setup` 或函数式组件中使用。::: ### Methods -| 方法 | 描述 | 类型 | 版本要求 | -| --------- | ------------------ | -------- | -------- | -| doConfirm | 调用弹窗的确认操作 | ()=>void | >5.5.4 | -| doCancel | 调用弹窗的取消操作 | ()=>void | >5.5.4 | +| 方法 | 描述 | 类型 | 版本要求 | +| --------- | ---------------------- | ------------ | -------- | +| doConfirm | 触发当前弹窗的确认操作 | `() => void` | `>5.5.4` | +| doCancel | 触发当前弹窗的取消操作 | `() => void` | `>5.5.4` | ## 类型说明 ```ts -/** 预置的图标类型 */ export type IconType = 'error' | 'info' | 'question' | 'success' | 'warning'; export type BeforeCloseScope = { - /** 是否为点击确认按钮触发的关闭 */ isConfirm: boolean; }; -/** - * alert 属性 - */ export type AlertProps = { - /** 关闭前的回调,如果返回false,则终止关闭 */ beforeClose?: ( scope: BeforeCloseScope, ) => boolean | Promise | undefined; - /** 边框 */ bordered?: boolean; - /** 按钮对齐方式 */ buttonAlign?: 'center' | 'end' | 'start'; - /** 取消按钮的标题 */ cancelText?: string; - /** 是否居中显示 */ centered?: boolean; - /** 确认按钮的标题 */ confirmText?: string; - /** 弹窗容器的额外样式 */ containerClass?: string; - /** 弹窗提示内容 */ content: Component | string; - /** 弹窗内容的额外样式 */ contentClass?: string; - /** 执行beforeClose回调期间,在内容区域显示一个loading遮罩*/ contentMasking?: boolean; - /** 弹窗底部内容(与按钮在同一个容器中) */ footer?: Component | string; - /** 弹窗的图标(在标题的前面) */ icon?: Component | IconType; - /** - * 弹窗遮罩模糊效果 - */ overlayBlur?: number; - /** 是否显示取消按钮 */ showCancel?: boolean; - /** 弹窗标题 */ title?: string; }; -/** prompt 属性 */ export type PromptProps = { - /** 关闭前的回调,如果返回false,则终止关闭 */ beforeClose?: (scope: { isConfirm: boolean; value: T | undefined; }) => boolean | Promise | undefined; - /** 用于接受用户输入的组件 */ component?: Component; - /** 输入组件的属性 */ componentProps?: Recordable; - /** 输入组件的插槽 */ - componentSlots?: Recordable; - /** 默认值 */ + componentSlots?: + | (() => any) + | Recordable + | VNode + | VNodeArrayChildren; defaultValue?: T; - /** 输入组件的值属性名 */ modelPropName?: string; } & Omit; -/** - * 函数签名 - * alert和confirm的函数签名相同。 - * confirm默认会显示取消按钮,而alert默认只有一个按钮 - * */ export function alert(options: AlertProps): Promise; export function alert( message: string, @@ -141,19 +99,10 @@ export function alert( options?: Partial, ): Promise; -/** - * 弹出输入框的函数签名。 - * beforeClose的参数会传入用户当前输入的值 - * component指定接受用户输入的组件,默认为Input - * componentProps 为输入组件设置的属性数据 - * defaultValue 默认的值 - * modelPropName 输入组件的值属性名称。默认为modelValue - */ export async function prompt( options: Omit & { beforeClose?: ( scope: BeforeCloseScope & { - /** 输入组件的当前值 */ value: T; }, ) => boolean | Promise | undefined; diff --git a/docs/src/components/common-ui/vben-api-component.md b/docs/src/components/common-ui/vben-api-component.md index 2c84e56b5..5465f1516 100644 --- a/docs/src/components/common-ui/vben-api-component.md +++ b/docs/src/components/common-ui/vben-api-component.md @@ -14,7 +14,7 @@ outline: deep ## 基础用法 -通过 `component` 传入其它组件的定义,并配置相关的其它属性(主要是一些名称映射)。包装组件将通过`api`获取数据(`beforerFetch`、`afterFetch`将分别在`api`运行前、运行后被调用),使用`resultField`从中提取数组,使用`valueField`、`labelField`等来从数据中提取value和label(如果提供了`childrenField`,会将其作为树形结构递归处理每一级数据),之后将处理好的数据通过`optionsPropName`指定的属性传递给目标组件。 +通过 `component` 传入其它组件的定义,并配置相关的其它属性(主要是一些名称映射)。包装组件将通过 `api` 获取数据(`beforeFetch`、`afterFetch` 将分别在 `api` 运行前、运行后被调用),使用 `resultField` 从中提取数组,使用 `valueField`、`labelField` 等来从数据中提取 value 和 label(如果提供了 `childrenField`,会将其作为树形结构递归处理每一级数据),之后将处理好的数据通过 `optionsPropName` 指定的属性传递给目标组件。 ::: details 包装级联选择器,点击下拉时开始加载远程数据 diff --git a/docs/src/components/common-ui/vben-count-to-animator.md b/docs/src/components/common-ui/vben-count-to-animator.md index 5f3ec1881..1a15401a3 100644 --- a/docs/src/components/common-ui/vben-count-to-animator.md +++ b/docs/src/components/common-ui/vben-count-to-animator.md @@ -4,56 +4,54 @@ outline: deep # Vben CountToAnimator 数字动画 -框架提供的数字动画组件,支持数字动画效果。 +`CountToAnimator` 用于展示数字滚动动画效果。 -> 如果文档内没有参数说明,可以尝试在在线示例内寻找 +> 如果文档内没有覆盖到你需要的细节,可以结合在线示例一起查看。 ::: info 写在前面 -如果你觉得现有组件的封装不够理想,或者不完全符合你的需求,大可以直接使用原生组件,亦或亲手封装一个适合的组件。框架提供的组件并非束缚,使用与否,完全取决于你的需求与自由。 - -::: +这是一个轻量数字动画组件。如果你需要完全不同的过渡控制方式,也可以直接使用原生动画方案或自行封装。::: ## 基础用法 -通过 `start-val` 和 `end-val`设置数字动画的开始值和结束值, 持续时间`3000`ms。 +通过 `start-val` 和 `end-val` 设置数字动画的起始值和结束值,配合 `duration` 控制动画时长。 -## 自定义前缀及分隔符 +## 自定义前缀与分隔符 -通过 `prefix` 和 `separator` 设置数字动画的前缀和分隔符。 +通过 `prefix`、`suffix`、`separator` 和 `decimal` 可以控制展示格式。 ### Props -| 属性名 | 描述 | 类型 | 默认值 | -| ---------- | -------------- | --------- | -------- | -| startVal | 起始值 | `number` | `0` | -| endVal | 结束值 | `number` | `2021` | -| duration | 动画持续时间 | `number` | `1500` | -| autoplay | 自动执行 | `boolean` | `true` | -| prefix | 前缀 | `string` | - | -| suffix | 后缀 | `string` | - | -| separator | 分隔符 | `string` | `,` | -| color | 字体颜色 | `string` | - | -| useEasing | 是否开启动画 | `boolean` | `true` | -| transition | 动画效果 | `string` | `linear` | -| decimals | 保留小数点位数 | `number` | `0` | +| 属性名 | 描述 | 类型 | 默认值 | +| --- | --- | --- | --- | +| startVal | 起始值 | `number` | `0` | +| endVal | 结束值 | `number` | `2021` | +| duration | 动画持续时间 | `number` | `1500` | +| autoplay | 是否自动播放 | `boolean` | `true` | +| prefix | 前缀 | `string` | `''` | +| suffix | 后缀 | `string` | `''` | +| separator | 千分位分隔符 | `string` | `','` | +| decimal | 小数点分隔符 | `string` | `'.'` | +| color | 文本颜色 | `string` | `''` | +| useEasing | 是否启用过渡预设 | `boolean` | `true` | +| transition | 过渡预设名称 | `keyof typeof TransitionPresets` | `'linear'` | +| decimals | 保留小数位数 | `number` | `0` | ### Events -| 事件名 | 描述 | 类型 | -| -------------- | -------------- | -------------- | -| started | 动画已开始 | `()=>void` | -| finished | 动画已结束 | `()=>void` | -| ~~onStarted~~ | ~~动画已开始~~ | ~~`()=>void`~~ | -| ~~onFinished~~ | ~~动画已结束~~ | ~~`()=>void`~~ | +| 事件名 | 描述 | 类型 | +| -------------- | ----------------------------- | ---------------- | +| started | 动画开始时触发 | `() => void` | +| finished | 动画结束时触发 | `() => void` | +| ~~onStarted~~ | ~~已废弃,请改用 `started`~~ | ~~`() => void`~~ | +| ~~onFinished~~ | ~~已废弃,请改用 `finished`~~ | ~~`() => void`~~ | ### Methods -| 方法名 | 描述 | 类型 | -| ------ | ------------ | ---------- | -| start | 开始执行动画 | `()=>void` | -| reset | 重置 | `()=>void` | +| 方法名 | 描述 | 类型 | +| ------ | -------------------------------- | ------------ | +| reset | 重置为 `startVal` 并重新执行动画 | `() => void` | diff --git a/docs/src/components/common-ui/vben-drawer.md b/docs/src/components/common-ui/vben-drawer.md index 3a28cce79..8214b8554 100644 --- a/docs/src/components/common-ui/vben-drawer.md +++ b/docs/src/components/common-ui/vben-drawer.md @@ -55,7 +55,7 @@ Drawer 内的内容一般业务中,会比较复杂,所以我们可以将 dra - `VbenDrawer` 组件对于参数的处理优先级是 `slot` > `props` > `state`(通过api更新的状态以及useVbenDrawer参数)。如果你已经传入了 `slot` 或者 `props`,那么 `setState` 将不会生效,这种情况下你可以通过 `slot` 或者 `props` 来更新状态。 - 如果你使用到了 `connectedComponent` 参数,那么会存在 2 个`useVbenDrawer`, 此时,如果同时设置了相同的参数,那么以内部为准(也就是没有设置 connectedComponent 的代码)。比如 同时设置了 `onConfirm`,那么以内部的 `onConfirm` 为准。`onOpenChange`事件除外,内外都会触发。 - 使用了`connectedComponent`参数时,可以配置`destroyOnClose`属性来决定当关闭弹窗时,是否要销毁`connectedComponent`组件(重新创建`connectedComponent`组件,这将会把其内部所有的变量、状态、数据等恢复到初始状态。)。 -- 如果抽屉的默认行为不符合你的预期,可以在`src\bootstrap.ts`中修改`setDefaultDrawerProps`的参数来设置默认的属性,如默认隐藏全屏按钮,修改默认ZIndex等。 +- 如果抽屉的默认行为不符合你的预期,可以在对应应用的 `apps//src/bootstrap.ts` 中修改 `setDefaultDrawerProps` 的参数来设置默认属性,例如修改默认 `zIndex` 等。 ::: @@ -116,7 +116,7 @@ const [Drawer, drawerApi] = useVbenDrawer({ | 事件名 | 描述 | 类型 | 版本限制 | | --- | --- | --- | --- | -| onBeforeClose | 关闭前触发,返回 `false`则禁止关闭 | `()=>boolean` | --- | +| onBeforeClose | 关闭前触发,返回 `false` 或 Promise reject 则禁止关闭 | `()=>Promise\|boolean\|undefined` | >5.5.2 支持 Promise | | onCancel | 点击取消按钮触发 | `()=>void` | --- | | onClosed | 关闭动画播放完毕时触发 | `()=>void` | >5.5.2 | | onConfirm | 点击确认按钮触发 | `()=>void` | --- | @@ -140,7 +140,7 @@ const [Drawer, drawerApi] = useVbenDrawer({ | 方法 | 描述 | 类型 | 版本限制 | | --- | --- | --- | --- | -| setState | 动态设置弹窗状态属性 | `(((prev: ModalState) => Partial)\| Partial)=>drawerApi` | +| setState | 动态设置抽屉状态属性 | `(((prev: DrawerState) => Partial)\| Partial)=>drawerApi` | | open | 打开弹窗 | `()=>void` | --- | | close | 关闭弹窗 | `()=>void` | --- | | setData | 设置共享数据 | `(data:T)=>drawerApi` | --- | diff --git a/docs/src/components/common-ui/vben-ellipsis-text.md b/docs/src/components/common-ui/vben-ellipsis-text.md index ce6c0334a..32a8fa58e 100644 --- a/docs/src/components/common-ui/vben-ellipsis-text.md +++ b/docs/src/components/common-ui/vben-ellipsis-text.md @@ -4,31 +4,31 @@ outline: deep # Vben EllipsisText 省略文本 -框架提供的文本展示组件,可配置超长省略、tooltip提示、展开收起等功能。 +`EllipsisText` 用于展示超长文本,支持省略、Tooltip 提示以及点击展开收起。 -> 如果文档内没有参数说明,可以尝试在在线示例内寻找 +> 如果文档内没有覆盖到你需要的细节,可以结合在线示例一起查看。 ## 基础用法 -通过默认插槽设置文本内容,`maxWidth`属性设置最大宽度。 +通过默认插槽提供文本内容,`maxWidth` 用于限制文本区域宽度。 -## 可折叠的文本块 +## 可折叠文本 -通过`line`设置折叠后的行数,`expand`属性设置是否支持展开收起。 +通过 `line` 设置折叠后的最大行数,通过 `expand` 开启点击展开与收起。 ## 自定义提示浮层 -通过名为`tooltip`的插槽定制提示信息。 +通过 `tooltip` 插槽自定义提示内容。 -## 自动显示 tooltip +## 仅在省略时显示 Tooltip -通过`tooltip-when-ellipsis`设置,仅在文本长度超出导致省略号出现时才触发 tooltip。 +通过 `tooltip-when-ellipsis` 控制仅在文本被截断时显示 Tooltip。 @@ -38,27 +38,27 @@ outline: deep | 属性名 | 描述 | 类型 | 默认值 | | --- | --- | --- | --- | -| expand | 支持点击展开或收起 | `boolean` | `false` | -| line | 文本最大行数 | `number` | `1` | +| expand | 是否支持点击展开或收起 | `boolean` | `false` | +| line | 文本最大显示行数 | `number` | `1` | | maxWidth | 文本区域最大宽度 | `number \| string` | `'100%'` | -| placement | 提示浮层的位置 | `'bottom'\|'left'\|'right'\|'top'` | `'top'` | -| tooltip | 启用文本提示 | `boolean` | `true` | -| tooltipWhenEllipsis | 内容超出,自动启用文本提示 | `boolean` | `false` | -| ellipsisThreshold | 设置 tooltipWhenEllipsis 后才生效,文本截断检测的像素差异阈值,越大则判断越严格,如果碰见异常情况可以自己设置阈值 | `number` | `3` | -| tooltipBackgroundColor | 提示文本的背景颜色 | `string` | - | -| tooltipColor | 提示文本的颜色 | `string` | - | -| tooltipFontSize | 提示文本的大小 | `string` | - | -| tooltipMaxWidth | 提示浮层的最大宽度。如不设置则保持与文本宽度一致 | `number` | - | -| tooltipOverlayStyle | 提示框内容区域样式 | `CSSProperties` | `{ textAlign: 'justify' }` | +| placement | 提示浮层位置 | `'bottom' \| 'left' \| 'right' \| 'top'` | `'top'` | +| tooltip | 是否启用文本提示 | `boolean` | `true` | +| tooltipWhenEllipsis | 是否仅在文本被截断时显示提示 | `boolean` | `false` | +| ellipsisThreshold | 文本截断检测阈值,值越大判定越严格 | `number` | `3` | +| tooltipBackgroundColor | 提示背景色 | `string` | `''` | +| tooltipColor | 提示文字颜色 | `string` | `''` | +| tooltipFontSize | 提示文字大小,单位 `px` | `number` | `14` | +| tooltipMaxWidth | 提示内容最大宽度,单位 `px` | `number` | - | +| tooltipOverlayStyle | 提示内容区域样式 | `CSSProperties` | `{ textAlign: 'justify' }` | ### Events -| 事件名 | 描述 | 类型 | -| ------------ | ------------ | -------------------------- | -| expandChange | 展开状态改变 | `(isExpand:boolean)=>void` | +| 事件名 | 描述 | 类型 | +| ------------ | ------------------ | ----------------------------- | +| expandChange | 展开状态变化时触发 | `(isExpand: boolean) => void` | ### Slots -| 插槽名 | 描述 | -| ------- | -------------------------------- | -| tooltip | 启用文本提示时,用来定制提示内容 | +| 插槽名 | 描述 | +| ------- | ---------------------------------- | +| tooltip | 开启文本提示时,用于自定义提示内容 | diff --git a/docs/src/components/common-ui/vben-form.md b/docs/src/components/common-ui/vben-form.md index 30cbec448..0a5f2edce 100644 --- a/docs/src/components/common-ui/vben-form.md +++ b/docs/src/components/common-ui/vben-form.md @@ -35,10 +35,15 @@ import type { ComponentType } from './component'; import { setupVbenForm, useVbenForm as useForm, z } from '@vben/common-ui'; import { $t } from '@vben/locales'; +import { initComponentAdapter } from './component'; + +initComponentAdapter(); setupVbenForm({ config: { // ant design vue组件库默认都是 v-model:value baseModelPropName: 'value', + // 一些组件库空值为 null,重置表单时需要和实际组件行为保持一致 + emptyStateValue: null, // 一些组件是 v-model:checked 或者 v-model:fileList modelPropNameMap: { Checkbox: 'checked', @@ -87,55 +92,32 @@ import type { BaseFormComponentType } from '@vben/common-ui'; import type { Component, SetupContext } from 'vue'; import { h } from 'vue'; -import { globalShareState, IconPicker } from '@vben/common-ui'; +import { globalShareState } from '@vben/common-ui'; import { $t } from '@vben/locales'; - -const AutoComplete = defineAsyncComponent( - () => import('ant-design-vue/es/auto-complete'), -); -const Button = defineAsyncComponent(() => import('ant-design-vue/es/button')); -const Checkbox = defineAsyncComponent( - () => import('ant-design-vue/es/checkbox'), -); -const CheckboxGroup = defineAsyncComponent(() => - import('ant-design-vue/es/checkbox').then((res) => res.CheckboxGroup), -); -const DatePicker = defineAsyncComponent( - () => import('ant-design-vue/es/date-picker'), -); -const Divider = defineAsyncComponent(() => import('ant-design-vue/es/divider')); -const Input = defineAsyncComponent(() => import('ant-design-vue/es/input')); -const InputNumber = defineAsyncComponent( - () => import('ant-design-vue/es/input-number'), -); -const InputPassword = defineAsyncComponent(() => - import('ant-design-vue/es/input').then((res) => res.InputPassword), -); -const Mentions = defineAsyncComponent( - () => import('ant-design-vue/es/mentions'), -); -const Radio = defineAsyncComponent(() => import('ant-design-vue/es/radio')); -const RadioGroup = defineAsyncComponent(() => - import('ant-design-vue/es/radio').then((res) => res.RadioGroup), -); -const RangePicker = defineAsyncComponent(() => - import('ant-design-vue/es/date-picker').then((res) => res.RangePicker), -); -const Rate = defineAsyncComponent(() => import('ant-design-vue/es/rate')); -const Select = defineAsyncComponent(() => import('ant-design-vue/es/select')); -const Space = defineAsyncComponent(() => import('ant-design-vue/es/space')); -const Switch = defineAsyncComponent(() => import('ant-design-vue/es/switch')); -const Textarea = defineAsyncComponent(() => - import('ant-design-vue/es/input').then((res) => res.Textarea), -); -const TimePicker = defineAsyncComponent( - () => import('ant-design-vue/es/time-picker'), -); -const TreeSelect = defineAsyncComponent( - () => import('ant-design-vue/es/tree-select'), -); -const Upload = defineAsyncComponent(() => import('ant-design-vue/es/upload')); - +import { + AutoComplete, + Button, + Checkbox, + CheckboxGroup, + DatePicker, + Divider, + Input, + InputNumber, + InputPassword, + Mentions, + notification, + Radio, + RadioGroup, + RangePicker, + Rate, + Select, + Space, + Switch, + Textarea, + TimePicker, + TreeSelect, + Upload, +} from 'ant-design-vue'; const withDefaultPlaceholder = ( component: T, @@ -171,7 +153,6 @@ export type ComponentType = | 'TimePicker' | 'TreeSelect' | 'Upload' - | 'IconPicker'; | BaseFormComponentType; async function initComponentAdapter() { @@ -189,7 +170,6 @@ async function initComponentAdapter() { return h(Button, { ...props, attrs, type: 'default' }, slots); }, Divider, - IconPicker, Input: withDefaultPlaceholder(Input, 'input'), InputNumber: withDefaultPlaceholder(InputNumber, 'input'), InputPassword: withDefaultPlaceholder(InputPassword, 'input'), diff --git a/docs/src/components/common-ui/vben-modal.md b/docs/src/components/common-ui/vben-modal.md index fc714e279..4d99f59f4 100644 --- a/docs/src/components/common-ui/vben-modal.md +++ b/docs/src/components/common-ui/vben-modal.md @@ -69,7 +69,7 @@ Modal 内的内容一般业务中,会比较复杂,所以我们可以将 moda - `VbenModal` 组件对与参数的处理优先级是 `slot` > `props` > `state`(通过api更新的状态以及useVbenModal参数)。如果你已经传入了 `slot` 或者 `props`,那么 `setState` 将不会生效,这种情况下你可以通过 `slot` 或者 `props` 来更新状态。 - 如果你使用到了 `connectedComponent` 参数,那么会存在 2 个`useVbenModal`, 此时,如果同时设置了相同的参数,那么以内部为准(也就是没有设置 connectedComponent 的代码)。比如 同时设置了 `onConfirm`,那么以内部的 `onConfirm` 为准。`onOpenChange`事件除外,内外都会触发。另外,如果设置了`destroyOnClose`,内部Modal及其子组件会在被关闭后完全销毁。 -- 如果弹窗的默认行为不符合你的预期,可以在`src\bootstrap.ts`中修改`setDefaultModalProps`的参数来设置默认的属性,如默认隐藏全屏按钮,修改默认ZIndex等。 +- 如果弹窗的默认行为不符合你的预期,可以在对应应用的 `apps//src/bootstrap.ts` 中修改 `setDefaultModalProps` 的参数来设置默认属性,例如默认隐藏全屏按钮、修改默认 `zIndex` 等。 ::: diff --git a/docs/src/components/common-ui/vben-vxe-table.md b/docs/src/components/common-ui/vben-vxe-table.md index 344ecae11..8e3088a05 100644 --- a/docs/src/components/common-ui/vben-vxe-table.md +++ b/docs/src/components/common-ui/vben-vxe-table.md @@ -4,25 +4,19 @@ outline: deep # Vben Vxe Table 表格 -框架提供的Table 列表组件基于 [vxe-table](https://vxetable.cn/v4/#/grid/api?apiKey=grid),结合`Vben Form 表单`进行了二次封装。 +`Vben Vxe Table` 基于 [vxe-table](https://vxetable.cn/v4/#/grid/api?apiKey=grid) 和 `Vben Form` 做了二次封装,用于构建带搜索表单的列表页面。 -其中,表头的 **表单搜索** 部分采用了`Vben Form表单`,表格主体部分使用了`vxe-grid`组件,支持表格的分页、排序、筛选等功能。 - -> 如果文档内没有参数说明,可以尝试在在线示例或者在 [vxe-grid 官方API 文档](https://vxetable.cn/v4/#/grid/api?apiKey=grid) 内寻找 +> 如果文档内没有覆盖到你需要的细节,可以结合在线示例和 [vxe-grid 官方 API](https://vxetable.cn/v4/#/grid/api?apiKey=grid) 一起查看。 ::: info 写在前面 -如果你觉得现有组件的封装不够理想,或者不完全符合你的需求,大可以直接使用原生组件,亦或亲手封装一个适合的组件。框架提供的组件并非束缚,使用与否,完全取决于你的需求与自由。 - -::: +如果现有封装不满足你的场景,可以直接使用原生 `vxe-table` 能力,或者在适配层中继续扩展。::: ## 适配器 -表格底层使用 [vxe-table](https://vxetable.cn/#/start/install) 进行实现,所以你可以使用 `vxe-table` 的所有功能。对于不同的 UI 框架,我们提供了适配器,以便更好的适配不同的 UI 框架。 +底层表格基于 `vxe-table`,每个应用都可以在自己的适配层中配置默认行为、自定义渲染器以及与 UI 组件库的集成。 -### 适配器说明 - -每个应用都可以自己配置`vxe-table`的适配器,你可以根据自己的需求。下面是一个简单的配置示例: +### 适配器示例 ::: details vxe-table 表格适配器 @@ -46,7 +40,6 @@ setupVbenVxeTable({ }, minHeight: 180, formConfig: { - // 全局禁用vxe-table的表单配置,使用formOptions enabled: false, }, proxyConfig: { @@ -65,7 +58,6 @@ setupVbenVxeTable({ }, }); - // 表格配置项可以用 cellRender: { name: 'CellImage' }, vxeUI.renderer.add('CellImage', { renderTableDefault(_renderOpts, params) { const { column, row } = params; @@ -73,7 +65,6 @@ setupVbenVxeTable({ }, }); - // 表格配置项可以用 cellRender: { name: 'CellLink' }, vxeUI.renderer.add('CellLink', { renderTableDefault(renderOpts) { const { props } = renderOpts; @@ -84,9 +75,6 @@ setupVbenVxeTable({ ); }, }); - - // 这里可以自行扩展 vxe-table 的全局配置,比如自定义格式化 - // vxeUI.formats.add }, useVbenForm, }); @@ -100,55 +88,50 @@ export type * from '@vben/plugins/vxe-table'; ## 基础表格 -使用 `useVbenVxeGrid` 创建最基础的表格。 +通过 `useVbenVxeGrid` 创建一个基础表格。 ## 远程加载 -通过指定 `proxyConfig.ajax` 的 `query` 方法,可以实现远程加载数据。 +通过配置 `proxyConfig.ajax.query` 实现远程数据加载。 ## 树形表格 -树形表格的数据源为扁平结构,可以指定`treeConfig`配置项,实现树形表格。 +树形表格的数据源通常是扁平结构,可以通过 `treeConfig` 转换为树形展示。 -```typescript +```ts treeConfig: { - transform: true, // 指定表格为树形表格 - parentField: 'parentId', // 父节点字段名 - rowField: 'id', // 行数据字段名 + transform: true, + parentField: 'parentId', + rowField: 'id', }, ``` -## 固定表头/列 +## 固定列 -列固定可选参数: `'left' | 'right' | '' | null` +固定列可选值为 `'left' | 'right' | '' | null`。 ## 自定义单元格 -自定义单元格有两种实现方式 +可以通过插槽或自定义渲染器实现单元格定制。 -- 通过 `slots` 插槽 -- 通过 `customCell` 自定义单元格,但是要先添加渲染器 - -```typescript -// 表格配置项可以用 cellRender: { name: 'CellImage' }, +```ts vxeUI.renderer.add('CellImage', { - renderDefault(_renderOpts, params) { + renderTableDefault(_renderOpts, params) { const { column, row } = params; - return h(Image, { src: row[column.field] } as any); // 注意此处的Image 组件,来源于Antd,需要自行引入,否则会使用js的Image类 + return h(Image, { src: row[column.field] } as any); }, }); -// 表格配置项可以用 cellRender: { name: 'CellLink' }, vxeUI.renderer.add('CellLink', { - renderDefault(renderOpts) { + renderTableDefault(renderOpts) { const { props } = renderOpts; return h( Button, @@ -163,23 +146,20 @@ vxeUI.renderer.add('CellLink', { ## 搜索表单 -**表单搜索** 部分采用了`Vben Form 表单`,参考 [Vben Form 表单文档](/components/common-ui/vben-form)。 +搜索区域底层使用的是 `Vben Form`。启用搜索表单后,可以通过 `gridOptions.toolbarConfig.search = true` 在工具栏中显示搜索面板开关按钮。 -当启用了表单搜索时,可以在toolbarConfig中配置`search`为`true`来让表格在工具栏区域显示一个搜索表单控制按钮。表格的所有以`form-`开头的命名插槽都会被传递给搜索表单。 +所有以 `form-` 开头的具名插槽都会自动转发到搜索表单。 -### 定制分隔条 +### 自定义分隔条 -当你启用表单搜索时,在表单和表格之间会显示一个分隔条。这个分隔条使用了默认的组件背景色,并且横向贯穿整个Vben Vxe Table在视觉上融入了页面的默认背景中。如果你在Vben Vxe Table的外层包裹了一个不同背景色的容器(如将其放在一个Card内),默认的表单和表格之间的分隔条可能就显得格格不入了,下面的代码演示了如何定制这个分隔条。 +启用搜索表单时,表单和表格主体之间默认会显示一个分隔条。可以通过 `separator` 调整或关闭它。 ```ts const [Grid] = useVbenVxeGrid({ formOptions: {}, gridOptions: {}, - // 完全移除分隔条 separator: false, - // 你也可以使用下面的代码来移除分隔条 // separator: { show: false }, - // 或者使用下面的代码来改变分隔条的颜色 // separator: { backgroundColor: 'rgba(100,100,0,0.5)' }, }); ``` @@ -188,40 +168,36 @@ const [Grid] = useVbenVxeGrid({ ## 单元格编辑 -通过指定`editConfig.mode`为`cell`,可以实现单元格编辑。 +通过设置 `editConfig.mode = 'cell'` 开启单元格编辑。 ## 行编辑 -通过指定`editConfig.mode`为`row`,可以实现行编辑。 +通过设置 `editConfig.mode = 'row'` 开启整行编辑。 ## 虚拟滚动 -通过 scroll-y.enabled 与 scroll-y.gt 组合开启,其中 enabled 为总开关,gt 是指当总行数大于指定行数时自动开启。 +通过 `scroll-y.enabled` 和 `scroll-y.gt` 组合开启纵向虚拟滚动。 -> 参考 [vxe-table 官方文档 - 虚拟滚动](https://vxetable.cn/v4/#/component/grid/scroll/vertical)。 +> 参考 [vxe-table 官方文档 - 虚拟滚动](https://vxetable.cn/v4/#/component/grid/scroll/vertical) ## API -`useVbenVxeGrid` 返回一个数组,第一个元素是表格组件,第二个元素是表格的方法。 +`useVbenVxeGrid` 返回一个数组,第一个元素是表格组件,第二个元素是表格 API。 ```vue @@ -232,45 +208,42 @@ const [Grid, gridApi] = useVbenVxeGrid({ ### GridApi -useVbenVxeGrid 返回的第二个参数,是一个对象,包含了一些表单的方法。 - | 方法名 | 描述 | 类型 | 说明 | | --- | --- | --- | --- | -| setLoading | 设置loading状态 | `(loading)=>void` | - | -| setGridOptions | 设置vxe-table grid组件参数 | `(options: Partialvoid` | - | -| reload | 重载表格,会进行初始化 | `(params:any)=>void` | - | -| query | 重载表格,会保留当前分页 | `(params:any)=>void` | - | -| grid | vxe-table grid实例 | `VxeGridInstance` | - | -| formApi | vbenForm api实例 | `FormApi` | - | -| toggleSearchForm | 设置搜索表单显示状态 | `(show?: boolean)=>boolean` | 当省略参数时,则将表单在显示和隐藏两种状态之间切换 | +| setLoading | 设置 loading 状态 | `(loading: boolean) => void` | - | +| setGridOptions | 更新 `gridOptions` | `(options: Partial) => void` | - | +| reload | 重新加载表格,并重置到初始分页 | `(params?: Record) => void` | - | +| query | 重新查询表格,保留当前分页 | `(params?: Record) => void` | - | +| grid | `vxe-grid` 实例 | `VxeGridInstance` | - | +| formApi | 搜索表单 API 实例 | `FormApi` | - | +| toggleSearchForm | 切换或指定搜索表单显示状态 | `(show?: boolean) => boolean` | 传入参数时强制设置;不传参数时在显示和隐藏之间切换,并返回当前状态 | ## Props -所有属性都可以传入 `useVbenVxeGrid` 的第一个参数中。 +所有属性都通过 `useVbenVxeGrid` 的第一个参数传入。 | 属性名 | 描述 | 类型 | 版本要求 | | --- | --- | --- | --- | | tableTitle | 表格标题 | `string` | - | | tableTitleHelp | 表格标题帮助信息 | `string` | - | -| gridClass | grid组件的class | `string` | - | -| gridOptions | grid组件的参数 | `VxeTableGridProps` | - | -| gridEvents | grid组件的触发的事件 | `VxeGridListeners` | - | -| formOptions | 表单参数 | `VbenFormProps` | - | +| class | 外层容器的 class | `string` | - | +| gridClass | `vxe-grid` 的 class | `string` | - | +| gridOptions | `vxe-grid` 配置 | `DeepPartial` | - | +| gridEvents | `vxe-grid` 事件 | `DeepPartial` | - | +| formOptions | 搜索表单配置 | `VbenFormProps` | - | | showSearchForm | 是否显示搜索表单 | `boolean` | - | -| separator | 搜索表单与表格主体之间的分隔条 | `boolean\|SeparatorOptions` | >5.5.4 | +| separator | 搜索表单与表格主体之间的分隔条 | `boolean \| SeparatorOptions` | `>5.5.4` | ## Slots -大部分插槽的说明请参考 [vxe-table 官方文档](https://vxetable.cn/v4/#/grid/api),但工具栏部分由于做了一些定制封装,需使用以下插槽定制表格的工具栏: +大部分插槽说明可参考 [vxe-table 官方文档](https://vxetable.cn/v4/#/grid/api),这里列出封装层新增或约定的部分。 -| 插槽名 | 描述 | -| --------------- | -------------------------------------------- | -| toolbar-actions | 工具栏左侧部分(表格标题附近) | -| toolbar-tools | 工具栏右侧部分(vxeTable原生工具按钮的左侧) | -| table-title | 表格标题插槽 | +| 插槽名 | 描述 | +| --------------- | ------------------------------------ | +| toolbar-actions | 工具栏左侧区域,位于标题附近 | +| toolbar-tools | 工具栏右侧区域,位于内置工具按钮左侧 | +| table-title | 自定义表格标题 | -::: info 搜索表单的插槽 +::: info 搜索表单插槽 -对于使用了搜索表单的表格来说,所有以`form-`开头的命名插槽都会传递给表单。 - -::: +当启用了搜索表单时,所有以 `form-` 开头的具名插槽都会被转发给表单。::: diff --git a/docs/src/components/layout-ui/page.md b/docs/src/components/layout-ui/page.md index 29fbdd40f..8f21fae19 100644 --- a/docs/src/components/layout-ui/page.md +++ b/docs/src/components/layout-ui/page.md @@ -4,41 +4,38 @@ outline: deep # Page 常规页面组件 -提供一个常规页面布局的组件,包括头部、内容区域、底部三个部分。 +`Page` 是页面内容区最常用的顶层布局容器,内置了标题区、内容区和底部区三部分结构。 ::: info 写在前面 -本组件是一个基本布局组件。如果有更多的通用页面布局需求(比如双列布局等),可以根据实际需求自行封装。 - -::: +这是一个基础页面容器。如果你的业务页面需要更复杂的布局,例如双列、侧边操作区或自定义滚动区域,建议在 `Page` 之上继续封装。::: ## 基础用法 -将`Page`作为你的业务页面的根组件即可。 +直接将 `Page` 作为业务页面的根组件使用即可。 ### Props | 属性名 | 描述 | 类型 | 默认值 | 说明 | | --- | --- | --- | --- | --- | -| title | 页面标题 | `string\|slot` | - | - | -| description | 页面描述(标题下的内容) | `string\|slot` | - | - | -| contentClass | 内容区域的class | `string` | - | - | -| headerClass | 头部区域的class | `string` | - | - | -| footerClass | 底部区域的class | `string` | - | - | -| autoContentHeight | 自动调整内容区域的高度 | `boolean` | `false` | - | +| title | 页面标题 | `string \| slot` | - | - | +| description | 页面描述 | `string \| slot` | - | - | +| contentClass | 内容区域的 class | `string` | - | - | +| headerClass | 头部区域的 class | `string` | - | - | +| footerClass | 底部区域的 class | `string` | - | - | +| autoContentHeight | 根据可视内容高度自动计算内容区高度 | `boolean` | `false` | 开启后内容区会根据布局可视高度自动扣减头部和底部高度 | +| heightOffset | 额外扣减的内容区高度偏移量 | `number` | `0` | 仅在 `autoContentHeight` 开启时生效,单位为 `px` | ::: tip 注意 -如果`title`、`description`、`extra`三者均未提供有效内容(通过`props`或者`slots`均可),则页面头部区域不会渲染。 - -::: +如果 `title`、`description`、`extra` 三者都没有提供有效内容,无论是通过 `props` 还是 `slots`,头部区域都不会渲染。::: ### Slots -| 插槽名称 | 描述 | -| ----------- | ------------ | -| default | 页面内容 | -| title | 页面标题 | -| description | 页面描述 | -| extra | 页面头部右侧 | -| footer | 页面底部 | +| 插槽名称 | 描述 | +| ----------- | ---------------- | +| default | 页面内容 | +| title | 页面标题 | +| description | 页面描述 | +| extra | 页面头部右侧内容 | +| footer | 页面底部内容 | diff --git a/docs/src/en/components/common-ui/vben-alert.md b/docs/src/en/components/common-ui/vben-alert.md new file mode 100644 index 000000000..fe2a13749 --- /dev/null +++ b/docs/src/en/components/common-ui/vben-alert.md @@ -0,0 +1,76 @@ +--- +outline: deep +--- + +# Vben Alert + +`Alert` provides lightweight JavaScript-driven dialogs for simple `alert`, `confirm`, and `prompt` style interactions. + +## Basic Usage + +Use `alert` for a single confirm button dialog: + + + +Use `confirm` for confirm/cancel interactions: + + + +Use `prompt` when you need simple user input: + + + +## useAlertContext + +If `content`, `footer`, or `icon` is rendered through a custom component, you can call `useAlertContext()` inside that component to access the current dialog actions. + +| Method | Description | Type | +| ----------- | -------------------------- | ------------ | +| `doConfirm` | trigger the confirm action | `() => void` | +| `doCancel` | trigger the cancel action | `() => void` | + +## Core Types + +```ts +export type IconType = 'error' | 'info' | 'question' | 'success' | 'warning'; + +export type BeforeCloseScope = { + isConfirm: boolean; +}; + +export type AlertProps = { + beforeClose?: ( + scope: BeforeCloseScope, + ) => boolean | Promise | undefined; + bordered?: boolean; + buttonAlign?: 'center' | 'end' | 'start'; + cancelText?: string; + centered?: boolean; + confirmText?: string; + containerClass?: string; + content: Component | string; + contentClass?: string; + contentMasking?: boolean; + footer?: Component | string; + icon?: Component | IconType; + overlayBlur?: number; + showCancel?: boolean; + title?: string; +}; + +export type PromptProps = { + beforeClose?: (scope: { + isConfirm: boolean; + value: T | undefined; + }) => boolean | Promise | undefined; + component?: Component; + componentProps?: Recordable; + componentSlots?: + | (() => any) + | Recordable + | VNode + | VNodeArrayChildren; + defaultValue?: T; + modelPropName?: string; +} & Omit; +``` diff --git a/docs/src/en/components/common-ui/vben-api-component.md b/docs/src/en/components/common-ui/vben-api-component.md new file mode 100644 index 000000000..f260a3791 --- /dev/null +++ b/docs/src/en/components/common-ui/vben-api-component.md @@ -0,0 +1,69 @@ +--- +outline: deep +--- + +# Vben ApiComponent + +`ApiComponent` is a wrapper used to attach remote-option loading behavior to an existing component while preserving the original component usage pattern. + +## Common Usage + +The current wrapper flow is: + +- pass the target component through `component` +- fetch remote data through `api` +- transform data through `beforeFetch` and `afterFetch` +- map remote fields through `resultField`, `valueField`, `labelField`, and `childrenField` +- pass normalized options to the target component through `optionsPropName` + +```vue + + + +``` + +## Current Props + +| Prop | Description | Type | +| --- | --- | --- | +| `component` | wrapped target component | `Component` | +| `api` | remote request function | `(arg?: any) => Promise` | +| `params` | extra request params | `Record` | +| `beforeFetch` | hook before request | `AnyPromiseFunction` | +| `afterFetch` | hook after request | `AnyPromiseFunction` | +| `visibleEvent` | event name used to lazy-load data | `string` | +| `loadingSlot` | slot name used to render the loading icon | `string` | +| `modelPropName` | model prop name of the wrapped component | `string` | +| `autoSelect` | auto-pick the first / last / only option, or use a custom function | `'first' \| 'last' \| 'one' \| ((items) => item) \| false` | + +## Exposed Methods + +| Method | Description | +| ------------------------ | -------------------------------------- | +| `getComponentRef()` | returns the wrapped component instance | +| `updateParam(newParams)` | merges and updates request params | +| `getOptions()` | returns loaded options | +| `getValue()` | returns the current bound value | diff --git a/docs/src/en/components/common-ui/vben-count-to-animator.md b/docs/src/en/components/common-ui/vben-count-to-animator.md new file mode 100644 index 000000000..615a417b4 --- /dev/null +++ b/docs/src/en/components/common-ui/vben-count-to-animator.md @@ -0,0 +1,51 @@ +--- +outline: deep +--- + +# Vben CountToAnimator + +`CountToAnimator` renders animated number transitions. + +## Basic Usage + +Use `start-val`, `end-val`, and `duration` to control the animation range and timing. + + + +## Formatting + +Use `prefix`, `suffix`, `separator`, and `decimal` to control how the number is displayed. + + + +## Props + +| Prop | Description | Type | Default | +| --- | --- | --- | --- | +| `startVal` | starting value | `number` | `0` | +| `endVal` | ending value | `number` | `2021` | +| `duration` | animation duration in ms | `number` | `1500` | +| `autoplay` | start automatically | `boolean` | `true` | +| `prefix` | value prefix | `string` | `''` | +| `suffix` | value suffix | `string` | `''` | +| `separator` | thousands separator | `string` | `','` | +| `decimal` | decimal separator | `string` | `'.'` | +| `color` | text color | `string` | `''` | +| `useEasing` | enable transition preset easing | `boolean` | `true` | +| `transition` | transition preset name | `keyof typeof TransitionPresets` | `'linear'` | +| `decimals` | decimal places to keep | `number` | `0` | + +## Events + +| Event | Description | Type | +| ------------ | ------------------------------- | ------------ | +| `started` | fired when the animation starts | `() => void` | +| `finished` | fired when the animation ends | `() => void` | +| `onStarted` | deprecated alias of `started` | `() => void` | +| `onFinished` | deprecated alias of `finished` | `() => void` | + +## Exposed Methods + +| Method | Description | Type | +| ------- | --------------------------------- | ------------ | +| `reset` | reset to `startVal` and run again | `() => void` | diff --git a/docs/src/en/components/common-ui/vben-drawer.md b/docs/src/en/components/common-ui/vben-drawer.md new file mode 100644 index 000000000..20b1d7ddf --- /dev/null +++ b/docs/src/en/components/common-ui/vben-drawer.md @@ -0,0 +1,56 @@ +--- +outline: deep +--- + +# Vben Drawer + +`Vben Drawer` is the shared drawer wrapper used by the framework. It supports auto-height layout, loading state, connected components, and an imperative API similar to the modal API. + +## Basic Usage + +```ts +const [Drawer, drawerApi] = useVbenDrawer({ + // props + // events +}); +``` + + + +## Current Usage Notes + +- If you use `connectedComponent`, the inner and outer components share data through `drawerApi.setData()` and `drawerApi.getData()`. +- Default drawer behavior can be adjusted in `apps//src/bootstrap.ts` through `setDefaultDrawerProps(...)`. +- `setState(...)` works on `DrawerState`, not `ModalState`. + +## Key Props + +| Prop | Description | Type | +| --- | --- | --- | +| `appendToMain` | mount inside the main content area instead of `body` | `boolean` | +| `connectedComponent` | connect an inner component to the drawer wrapper | `Component` | +| `closeIconPlacement` | position of the close icon | `'left' \| 'right'` | +| `placement` | drawer side | `'left' \| 'right' \| 'top' \| 'bottom'` | +| `overlayBlur` | blur amount for the overlay | `number` | +| `submitting` | lock drawer interactions while submitting | `boolean` | + +## Events + +| Event | Description | Type | +| --- | --- | --- | +| `onBeforeClose` | called before close; returning `false` or rejecting prevents close | `() => Promise \| boolean \| undefined` | +| `onOpenChange` | called when open state changes | `(isOpen: boolean) => void` | +| `onOpened` | called after open animation completes | `() => void` | +| `onClosed` | called after close animation completes | `() => void` | + +## drawerApi + +| Method | Description | +| ----------------------- | -------------------------------------- | +| `setState(...)` | updates drawer state | +| `open()` | opens the drawer | +| `close()` | closes the drawer | +| `setData(data)` | stores shared data | +| `getData()` | reads shared data | +| `lock(isLocked = true)` | locks the drawer into submitting state | +| `unlock()` | alias for `lock(false)` | diff --git a/docs/src/en/components/common-ui/vben-ellipsis-text.md b/docs/src/en/components/common-ui/vben-ellipsis-text.md new file mode 100644 index 000000000..602812a07 --- /dev/null +++ b/docs/src/en/components/common-ui/vben-ellipsis-text.md @@ -0,0 +1,42 @@ +--- +outline: deep +--- + +# Vben EllipsisText + +`EllipsisText` displays long text with truncation, tooltip support, and optional expand/collapse behavior. + +## Basic Usage + +Pass the text through the default slot and limit the visual width with `maxWidth`. + + + +## Current Props + +| Prop | Description | Type | Default | +| --- | --- | --- | --- | +| `expand` | allow click-to-expand behavior | `boolean` | `false` | +| `line` | max visible line count | `number` | `1` | +| `maxWidth` | max width of the text area | `number \| string` | `'100%'` | +| `placement` | tooltip placement | `'bottom' \| 'left' \| 'right' \| 'top'` | `'top'` | +| `tooltip` | enable tooltip | `boolean` | `true` | +| `tooltipWhenEllipsis` | only show tooltip when text is actually truncated | `boolean` | `false` | +| `ellipsisThreshold` | pixel threshold used when checking truncation | `number` | `3` | +| `tooltipBackgroundColor` | tooltip background color | `string` | `''` | +| `tooltipColor` | tooltip text color | `string` | `''` | +| `tooltipFontSize` | tooltip font size in px | `number` | `14` | +| `tooltipMaxWidth` | tooltip max width in px | `number` | - | +| `tooltipOverlayStyle` | tooltip content style | `CSSProperties` | `{ textAlign: 'justify' }` | + +## Events + +| Event | Description | Type | +| --- | --- | --- | +| `expandChange` | fired when expand state changes | `(isExpand: boolean) => void` | + +## Slots + +| Slot | Description | +| --------- | ---------------------- | +| `tooltip` | custom tooltip content | diff --git a/docs/src/en/components/common-ui/vben-form.md b/docs/src/en/components/common-ui/vben-form.md new file mode 100644 index 000000000..d23e869bc --- /dev/null +++ b/docs/src/en/components/common-ui/vben-form.md @@ -0,0 +1,203 @@ +--- +outline: deep +--- + +# Vben Form + +`Vben Form` is the shared form abstraction used across different UI-library variants such as `Ant Design Vue`, `Element Plus`, `Naive UI`, and other adapters added inside this repository. + +> If some details are not obvious from the docs, check the live demos as well. + +## Adapter Setup + +Each app keeps its own adapter layer under `src/adapter/form.ts` and `src/adapter/component/index.ts`. + +The current adapter pattern is: + +- initialize the shared component adapter first +- call `setupVbenForm(...)` +- map special `v-model:*` prop names through `modelPropNameMap` +- keep the form empty state aligned with the actual UI library behavior + +### Form Adapter Example + +```ts +import type { + VbenFormSchema as FormSchema, + VbenFormProps, +} from '@vben/common-ui'; + +import type { ComponentType } from './component'; + +import { setupVbenForm, useVbenForm as useForm, z } from '@vben/common-ui'; +import { $t } from '@vben/locales'; + +import { initComponentAdapter } from './component'; + +initComponentAdapter(); +setupVbenForm({ + config: { + baseModelPropName: 'value', + emptyStateValue: null, + modelPropNameMap: { + Checkbox: 'checked', + Radio: 'checked', + Switch: 'checked', + Upload: 'fileList', + }, + }, + defineRules: { + required: (value, _params, ctx) => { + if (value === undefined || value === null || value.length === 0) { + return $t('ui.formRules.required', [ctx.label]); + } + return true; + }, + selectRequired: (value, _params, ctx) => { + if (value === undefined || value === null) { + return $t('ui.formRules.selectRequired', [ctx.label]); + } + return true; + }, + }, +}); + +const useVbenForm = useForm; + +export { useVbenForm, z }; +export type VbenFormSchema = FormSchema; +export type { VbenFormProps }; +``` + +### Component Adapter Example + +```ts +import type { Component, SetupContext } from 'vue'; + +import type { BaseFormComponentType } from '@vben/common-ui'; + +import { h } from 'vue'; + +import { globalShareState } from '@vben/common-ui'; +import { $t } from '@vben/locales'; +import { + AutoComplete, + Button, + Checkbox, + CheckboxGroup, + DatePicker, + Divider, + Input, + InputNumber, + InputPassword, + Mentions, + notification, + Radio, + RadioGroup, + RangePicker, + Rate, + Select, + Space, + Switch, + Textarea, + TimePicker, + TreeSelect, + Upload, +} from 'ant-design-vue'; + +const withDefaultPlaceholder = ( + component: T, + type: 'input' | 'select', +) => { + return (props: any, { attrs, slots }: Omit) => { + const placeholder = props?.placeholder || $t(`ui.placeholder.${type}`); + return h(component, { ...props, ...attrs, placeholder }, slots); + }; +}; + +export type ComponentType = + | 'AutoComplete' + | 'Checkbox' + | 'CheckboxGroup' + | 'DatePicker' + | 'DefaultButton' + | 'Divider' + | 'Input' + | 'InputNumber' + | 'InputPassword' + | 'Mentions' + | 'PrimaryButton' + | 'Radio' + | 'RadioGroup' + | 'RangePicker' + | 'Rate' + | 'Select' + | 'Space' + | 'Switch' + | 'Textarea' + | 'TimePicker' + | 'TreeSelect' + | 'Upload' + | BaseFormComponentType; + +async function initComponentAdapter() { + const components: Partial> = { + AutoComplete, + Checkbox, + CheckboxGroup, + DatePicker, + DefaultButton: (props, { attrs, slots }) => { + return h(Button, { ...props, attrs, type: 'default' }, slots); + }, + Divider, + Input: withDefaultPlaceholder(Input, 'input'), + InputNumber: withDefaultPlaceholder(InputNumber, 'input'), + InputPassword: withDefaultPlaceholder(InputPassword, 'input'), + Mentions: withDefaultPlaceholder(Mentions, 'input'), + PrimaryButton: (props, { attrs, slots }) => { + return h(Button, { ...props, attrs, type: 'primary' }, slots); + }, + Radio, + RadioGroup, + RangePicker, + Rate, + Select: withDefaultPlaceholder(Select, 'select'), + Space, + Switch, + Textarea: withDefaultPlaceholder(Textarea, 'input'), + TimePicker, + TreeSelect: withDefaultPlaceholder(TreeSelect, 'select'), + Upload, + }; + + globalShareState.setComponents(components); + globalShareState.defineMessage({ + copyPreferencesSuccess: (title, content) => { + notification.success({ + description: content, + message: title, + placement: 'bottomRight', + }); + }, + }); +} + +export { initComponentAdapter }; +``` + +## Basic Usage + +Create the form through `useVbenForm`: + + + +## Key API Notes + +- `useVbenForm` returns `[Form, formApi]` +- `formApi.getFieldComponentRef()` and `formApi.getFocusedField()` are available in current versions +- `handleValuesChange(values, fieldsChanged)` includes the second parameter in newer versions +- `fieldMappingTime` and `scrollToFirstError` are part of the current form props + +## Reference + +For the complete Chinese API tables and more examples, see the Chinese component page if you need the full parameter matrix. diff --git a/docs/src/en/components/common-ui/vben-modal.md b/docs/src/en/components/common-ui/vben-modal.md new file mode 100644 index 000000000..0971c4413 --- /dev/null +++ b/docs/src/en/components/common-ui/vben-modal.md @@ -0,0 +1,56 @@ +--- +outline: deep +--- + +# Vben Modal + +`Vben Modal` is the shared modal wrapper used by the framework. It supports draggable behavior, fullscreen mode, auto-height handling, loading state, connected components, and an imperative API. + +## Basic Usage + +```ts +const [Modal, modalApi] = useVbenModal({ + // props + // events +}); +``` + + + +## Current Usage Notes + +- If you use `connectedComponent`, the inner and outer components share data through `modalApi.setData()` and `modalApi.getData()`. +- When `connectedComponent` is present, avoid pushing extra modal props through the connected side. Prefer `useVbenModal(...)` or `modalApi.setState(...)`. +- Default modal behavior can be adjusted in `apps//src/bootstrap.ts` through `setDefaultModalProps(...)`. + +## Key Props + +| Prop | Description | Type | +| --- | --- | --- | +| `appendToMain` | mount inside the main content area instead of `body` | `boolean` | +| `connectedComponent` | connect an inner component to the modal wrapper | `Component` | +| `animationType` | modal enter/leave animation | `'slide' \| 'scale'` | +| `fullscreenButton` | show or hide the fullscreen toggle | `boolean` | +| `overlayBlur` | blur amount for the overlay | `number` | +| `submitting` | lock modal interactions while submitting | `boolean` | + +## Events + +| Event | Description | Type | +| --- | --- | --- | +| `onBeforeClose` | called before close; returning `false` or rejecting prevents close | `() => Promise \| boolean \| undefined` | +| `onOpenChange` | called when open state changes | `(isOpen: boolean) => void` | +| `onOpened` | called after open animation completes | `() => void` | +| `onClosed` | called after close animation completes | `() => void` | + +## modalApi + +| Method | Description | +| ----------------------- | ------------------------------------- | +| `setState(...)` | updates modal state | +| `open()` | opens the modal | +| `close()` | closes the modal | +| `setData(data)` | stores shared data | +| `getData()` | reads shared data | +| `lock(isLocked = true)` | locks the modal into submitting state | +| `unlock()` | alias for `lock(false)` | diff --git a/docs/src/en/components/common-ui/vben-vxe-table.md b/docs/src/en/components/common-ui/vben-vxe-table.md new file mode 100644 index 000000000..2fba1dc0c --- /dev/null +++ b/docs/src/en/components/common-ui/vben-vxe-table.md @@ -0,0 +1,87 @@ +--- +outline: deep +--- + +# Vben Vxe Table + +`Vben Vxe Table` wraps `vxe-table` together with `Vben Form` so you can build searchable data grids with a shared API. + +## Adapter Example + +The current renderer adapter uses `renderTableDefault(...)` for table cell rendering: + +```ts +vxeUI.renderer.add('CellImage', { + renderTableDefault(_renderOpts, params) { + const { column, row } = params; + return h(Image, { src: row[column.field] }); + }, +}); + +vxeUI.renderer.add('CellLink', { + renderTableDefault(renderOpts) { + const { props } = renderOpts; + return h( + Button, + { size: 'small', type: 'link' }, + { default: () => props?.text }, + ); + }, +}); +``` + +## Basic Usage + +```vue + + + +``` + + + +## GridApi + +| Method | Description | Type | +| --- | --- | --- | +| `setLoading` | update loading state | `(loading: boolean) => void` | +| `setGridOptions` | merge new grid options | `(options: Partial) => void` | +| `reload` | reload data and reset pagination | `(params?: Record) => void` | +| `query` | query data while keeping the current page | `(params?: Record) => void` | +| `grid` | `vxe-grid` instance | `VxeGridInstance` | +| `formApi` | search form API | `FormApi` | +| `toggleSearchForm` | toggle or force the search form visible state | `(show?: boolean) => boolean` | + +## Props + +| Prop | Description | Type | +| --- | --- | --- | +| `tableTitle` | table title | `string` | +| `tableTitleHelp` | help text for the table title | `string` | +| `class` | class for the outer container | `string` | +| `gridClass` | class for the `vxe-grid` node | `string` | +| `gridOptions` | `vxe-grid` options | `DeepPartial` | +| `gridEvents` | `vxe-grid` event handlers | `DeepPartial` | +| `formOptions` | search form options | `VbenFormProps` | +| `showSearchForm` | whether the search form is visible | `boolean` | +| `separator` | separator between the search form and table body | `boolean \| SeparatorOptions` | + +## Slots + +| Slot | Description | +| ----------------- | ------------------------------------------------------- | +| `toolbar-actions` | left side of the toolbar, near the title | +| `toolbar-tools` | right side of the toolbar, before built-in tool buttons | +| `table-title` | custom table title | + +All named slots starting with `form-` are forwarded to the search form. diff --git a/docs/src/en/components/introduction.md b/docs/src/en/components/introduction.md new file mode 100644 index 000000000..806ef09ff --- /dev/null +++ b/docs/src/en/components/introduction.md @@ -0,0 +1,15 @@ +# Introduction + +::: info README + +This section documents the framework components, including their usage patterns, configuration points, and major APIs. If the built-in wrappers do not fit your needs, you can always use native components directly or build your own abstractions. + +::: + +## Layout Components + +Layout components are usually used as top-level containers inside the page content area. They provide shared layout styles and some baseline behavior. + +## Common Components + +Common components include frequently used UI building blocks such as modals, drawers, forms, and API-backed selectors. Most of them are implemented on top of shared Tailwind CSS and shadcn-vue based primitives, while still allowing each app to adapt them to its own UI library. diff --git a/docs/src/en/components/layout-ui/page.md b/docs/src/en/components/layout-ui/page.md new file mode 100644 index 000000000..467d30c4c --- /dev/null +++ b/docs/src/en/components/layout-ui/page.md @@ -0,0 +1,29 @@ +--- +outline: deep +--- + +# Page + +`Page` is the standard top-level layout container for business pages. It provides a header area, a content area, and an optional footer area. + +## Props + +| Prop | Description | Type | Default | +| --- | --- | --- | --- | +| `title` | page title | `string \| slot` | - | +| `description` | page description | `string \| slot` | - | +| `contentClass` | class for the content area | `string` | - | +| `headerClass` | class for the header area | `string` | - | +| `footerClass` | class for the footer area | `string` | - | +| `autoContentHeight` | auto-calculate the content area height from the visible layout height | `boolean` | `false` | +| `heightOffset` | extra height offset subtracted from the content area when auto height is enabled | `number` | `0` | + +## Slots + +| Slot | Description | +| ------------- | ------------------------- | +| `default` | page content | +| `title` | custom title | +| `description` | custom description | +| `extra` | right-side header content | +| `footer` | footer content |