diff --git a/packages/docs/plugins/injectDemoAndApi.ts b/packages/docs/plugins/injectDemoAndApi.ts index a34acb0fb5dfa76d4e576a9759896af72e2d3e90..5b3a2840e3685b8d01f844c06f5c8bd0363d9e7f 100644 --- a/packages/docs/plugins/injectDemoAndApi.ts +++ b/packages/docs/plugins/injectDemoAndApi.ts @@ -82,15 +82,18 @@ const transformMdEntry = async (code: string, id: string, usageFiles: Set 注释替换成 // 将 注释替换成 let newCode = await asyncReplace(code, //g, async (match) => { - const [, directive, fileName] = match; + const [, directive, filePath] = match; + const paths = filePath.split('/'); + const dirs = paths.slice(0, -1); + const fileName = paths[paths.length - 1]; if (directive === 'api') { // 拼接 api 文件 - const apiFile = join(dirname(id), `${fileName}-api.${lang.lang}.md`); + const apiFile = join(dirname(id), ...dirs, `${fileName}-api.${lang.lang}.md`); if (await fsp.stat(apiFile).catch(() => false)) { return fsp.readFile(apiFile, 'utf-8'); } } - const demoFile = join(dirname(id), `./__case__/${fileName}.vue`); + const demoFile = join(dirname(id), ...dirs, `./__case__/${fileName}.vue`); if (await fsp.stat(demoFile).catch(() => false)) { if (directive === 'case') { imported.push({ diff --git a/packages/docs/scripts/generateApi.ts b/packages/docs/scripts/generateApi.ts index ca1ea2d6bc6c094458654e7938c8ae79605948be..cfb8894afaf01f3b2b541268da68f5b042a3c67e 100644 --- a/packages/docs/scripts/generateApi.ts +++ b/packages/docs/scripts/generateApi.ts @@ -30,7 +30,7 @@ function replaceCellChar(ch: string) { return CELL_REPLACEMENTS[ch]; } function escapeTableValue(value?: string) { - const CELL_ESCAPE_REPLACE_RE = /[<>"'\|]/g; + const CELL_ESCAPE_REPLACE_RE = /[<>"'|]/g; return value ? value.replace(CELL_ESCAPE_REPLACE_RE, replaceCellChar) : ''; } function cleanTableData(table: any[][]) { @@ -61,11 +61,11 @@ function cleanTableData(table: any[][]) { function markdownTable(table: string[][]) { let code = ''; // head - code += '| ' + table[0].join(' | ') + ' |\n'; - code += '| ' + table[0].map(() => '---').join(' | ') + ' |\n'; + code += `| ${table[0].join(' | ')} |\n`; + code += `| ${table[0].map(() => '---').join(' | ')} |\n`; // body for (let i = 1; i < table.length; i++) { - code += '| ' + table[i].join(' | ') + ' |\n'; + code += `| ${table[i].join(' | ')} |\n`; } return code; } @@ -85,7 +85,7 @@ async function applyTempFixForEventDescriptions(filename: string, componentMeta: try { const parsedComponentDocs = await parseMulti(filename, { modules: [srcDir], nameFilter: ['default'] }); componentMeta.events = componentMeta.events.map((event) => { - const parsedEvent = parsedComponentDocs[0].events.find((parsedEvent) => parsedEvent.name === event.name); + const parsedEvent = parsedComponentDocs[0].events.find((item) => item.name === event.name); if (parsedEvent) { event.description = parsedEvent.description; @@ -105,7 +105,6 @@ async function applyTempFixForEventDescriptions(filename: string, componentMeta: * @returns 新的组件元数据 */ async function applyTempFixForSlot(filename: string, componentMeta: ComponentMeta) { - debugger; const slotReg = /defineSlots<{[^}]+}>\(\)/; const slotMatch = slotReg.exec(await fsp.readFile(filename, 'utf-8')); if (!slotMatch) { @@ -129,8 +128,8 @@ const terminalWidth = process.stdout.columns || 80; const progressBarLength = Math.min(Math.floor(terminalWidth / 4), 30); const pathReg = /\/(O.*)\.vue/; const tagTypes = { - deprecated: '(warning)' -} + deprecated: '(warning)', +}; glob('*/O*.vue', { cwd: srcDir, posix: true }).then((files) => { files.forEach(async (file, index) => { const fullPath = join(srcDir, file); @@ -209,6 +208,20 @@ glob('*/O*.vue', { cwd: srcDir, posix: true }).then((files) => { slotsData = cleanTableData(slotsData); mdContent = `${mdContent}\n\n#### slots\n\n${markdownTable(slotsData)}`; } + // expose + const selfExposed = meta.exposed.filter((expose) => expose.description); + if (selfExposed.length) { + const tableHeader = { + 'zh-CN': ['名称', '类型', '说明'], + 'en-US': ['Name', 'Type', 'Description'], + }; + let exposeData =selfExposed.map((expose) => { + return [expose.name, expose.type, expose.description]; + }); + exposeData.unshift(tableHeader[lang]); + exposeData = cleanTableData(exposeData); + mdContent = `${mdContent}\n\n#### expose\n\n${markdownTable(exposeData)}`; + } await fsp.mkdir(dirname(apiMdPath), { recursive: true }).then(() => fsp.writeFile(apiMdPath, mdContent, { encoding: 'utf-8' })); } }); diff --git a/packages/opendesign/src/checkbox-group/types.ts b/packages/opendesign/src/checkbox-group/types.ts index ebd6e041cb63804f4b23767b200c1bc98990bd6b..8577b3a0a74a2fb6ac4a0129b41618483010894c 100644 --- a/packages/opendesign/src/checkbox-group/types.ts +++ b/packages/opendesign/src/checkbox-group/types.ts @@ -3,42 +3,47 @@ import type { ExtractPropTypes, PropType } from 'vue'; export const checkboxGroupProps = { /** - * 多选框组双向绑定值 + * @zh-CN 多选框组双向绑定值 + * @en-US checkbox group two-way binding value */ modelValue: { type: Array as PropType>, }, /** - * 非受控状态时,多选框组默认值 + * @zh-CN 非受控状态时,多选框组默认值 + * @en-US Default value when not controlled */ defaultValue: { type: Array as PropType>, default: () => [], }, /** - * 多选框组是否禁用 + * @zh-CN 是否禁用多选框组 + * @en-US Whether to disable the checkbox group */ disabled: { type: Boolean, default: false, }, /** - * 多选框组方向 - * 'h' | 'v' + * @zh-CN 多选框组布局方向 + * @en-US Layout direction of checkbox group */ direction: { type: String as PropType, default: 'h', }, /** - * 多选框组支持选中的最小多选框数量 + * @zh-CN 最少选择数量 + * @en-US Minimum number of selections */ min: { type: Number, default: undefined, }, /** - * 多选框组支持选中的最大多选框数量 + * @zh-CN 最多选择数量 + * @en-US Maximum number of selections */ max: { type: Number, diff --git a/packages/opendesign/src/checkbox/OCheckbox.vue b/packages/opendesign/src/checkbox/OCheckbox.vue index 70bfb0c096bd60fc00ef868d466717e935a109bd..2c249be364cf216569c0b06684e3934cd7bc20e5 100644 --- a/packages/opendesign/src/checkbox/OCheckbox.vue +++ b/packages/opendesign/src/checkbox/OCheckbox.vue @@ -90,6 +90,7 @@ const onChange = (ev: Event) => { }; defineExpose({ + /** is checked */ checked: isChecked, }); diff --git a/packages/opendesign/src/checkbox/__docs__/__case__/CheckboxGroup.vue b/packages/opendesign/src/checkbox/__docs__/__case__/CheckboxGroup.vue new file mode 100644 index 0000000000000000000000000000000000000000..2990fbe90df8053c4630b072795222e96f60596d --- /dev/null +++ b/packages/opendesign/src/checkbox/__docs__/__case__/CheckboxGroup.vue @@ -0,0 +1,56 @@ + + + +### 多选框组 + +由于 `OCheckbox` 是通过判断 `modelValue` 数组中是否含有 `value` 值来判断是否被选中。因此多个多选框公用同一个响应式变量即可实现多选框组功能。 + +也可以配合 `OCheckGroup` 实现多选框组以及其它更丰富的功能: + +1. `OCheckboxGroup` 的 `disabled` 属性禁用整个多选框组(`OCheckbox` 的 `disabled` 禁用自身) +2. `max` 属性限制多选框组可选数量 +3. `min` 属性限制多选框组至少可选数量 +4. `direction` 属性控制多选框组内多选框的排列方向 + + +### Checkbox Group + +Since `OCheckbox` determines whether it's selected by checking if its `value` exists in the `modelValue` array, multiple checkboxes sharing the same reactive variable can implement a checkbox group. + +It can also be used in conjunction with `OCheckboxGroup` to implement checkbox group functionality along with other enhanced features: + +1. The `disabled` property of `OCheckboxGroup` disables the entire checkbox group (whereas `OCheckbox`'s `disabled` property disables only itself) +2. The `max` property sets the maximum number of selectable options in the checkbox group +3. The `min` property sets the minimum number of options that must be selected in the checkbox group +4. The `direction` property controls the alignment direction of checkboxes within the group + + + + + diff --git a/packages/opendesign/src/checkbox/__docs__/__case__/CheckboxIndeterminate.vue b/packages/opendesign/src/checkbox/__docs__/__case__/CheckboxIndeterminate.vue new file mode 100644 index 0000000000000000000000000000000000000000..53efae180047ef616e674a139e456bcd9d32fa5a --- /dev/null +++ b/packages/opendesign/src/checkbox/__docs__/__case__/CheckboxIndeterminate.vue @@ -0,0 +1,62 @@ + + + +### 全选及半选 + +通过 `indeterminate` 属性设置半选状态,结合 `change` 事件实现全/半选功能 + + + +### Select All and Indeterminate State + +Set the indeterminate state using the `indeterminate` attribute, and implement the select all/indeterminate functionality by combining with the `change` event. + + + + diff --git a/packages/opendesign/src/checkbox/__docs__/__case__/CheckboxUsage.vue b/packages/opendesign/src/checkbox/__docs__/__case__/CheckboxUsage.vue new file mode 100644 index 0000000000000000000000000000000000000000..914d893e3c968f1a99d9cfdc7b3e06096092f4e7 --- /dev/null +++ b/packages/opendesign/src/checkbox/__docs__/__case__/CheckboxUsage.vue @@ -0,0 +1,68 @@ + + +### 使用 + +多选框传值: + +1. `value` 用于设置选中后 `modelValue` 的中包含的值 +2. `modelValue` 的类型是 `Array`,当选中后数组中会添加 `value`,否则会移除 `value` + +半选:当 `indeterminate` 为 true 时,多选框将处于半选状态(无论 `modelValue` 是何值)。 + +多选框组:由于 `modelValue` 是一个数组,因此多选框组可以单独使用 `OCheckbox` 组件,也可以嵌套在 `OCheckboxGroup` 组件中。 + + +### Usage + +Checkbox Value Binding: + +1. `value` sets the value to be included in `modelValue` when the checkbox is checked. +2. `modelValue` has a type of `Array`. When checked, the `value` is added to the array; when unchecked, the `value` is removed. + +Indeterminate State: When `indeterminate` is set to true, the checkbox will appear partially checked (regardless of the modelValue state). + +Checkbox Groups: Since `modelValue` is an array, checkbox groups can be implemented either by using individual `OCheckbox` components directly or by nesting them within an `OCheckboxGroup` component. + + + diff --git a/packages/opendesign/src/checkbox/__docs__/index.en-US.md b/packages/opendesign/src/checkbox/__docs__/index.en-US.md new file mode 100644 index 0000000000000000000000000000000000000000..c83f9f852d414dca94726adc3c74c80a7d66700d --- /dev/null +++ b/packages/opendesign/src/checkbox/__docs__/index.en-US.md @@ -0,0 +1,16 @@ +--- +sidebar: OCheckbox +--- + +# OCheckbox + +## Demo + + + + + +## API + + + diff --git a/packages/opendesign/src/checkbox/__docs__/index.zh-CN.md b/packages/opendesign/src/checkbox/__docs__/index.zh-CN.md new file mode 100644 index 0000000000000000000000000000000000000000..8ccb1f0d7577bf38bf9c6268d1c4d0cfe4301b91 --- /dev/null +++ b/packages/opendesign/src/checkbox/__docs__/index.zh-CN.md @@ -0,0 +1,16 @@ +--- +sidebar: OCheckbox 多选框 +--- + +# OCheckbox 多选框 + +## 示例 + + + + + +## API + + + diff --git a/packages/opendesign/src/checkbox/types.ts b/packages/opendesign/src/checkbox/types.ts index fb212802be315dadb42b91e89654a385616bc8fe..2c38173fe4b0882417ca874e298b68ee204c1f21 100644 --- a/packages/opendesign/src/checkbox/types.ts +++ b/packages/opendesign/src/checkbox/types.ts @@ -2,41 +2,47 @@ import { ExtractPropTypes, PropType } from 'vue'; export const checkboxProps = { /** - * 多选框value + * @zh-CN 多选框value,会作为 modelValue 的值 + * @en-US Checkbox value, which will be the value of modelValue */ value: { type: [String, Number], - required: true, + required: true as const, }, /** - * 多选框双向绑定值 + * @zh-CN 多选框双向绑定值 + * @en-US Checkbox two-way binding value */ modelValue: { type: Array as PropType>, }, /** - * 非受控状态时,默认是否选中 + * @zh-CN 非受控状态时,默认是否选中 + * @en-US Default checked when uncontrolled */ defaultChecked: { type: Boolean, default: false, }, /** - * 是否禁用 + * @zh-CN 是否禁用 + * @en-US Whether to disable */ disabled: { type: Boolean, default: false, }, /** - * 是否为半选状态 + * @zh-CN 是否半选 + * @en-US Whether to select half */ indeterminate: { type: Boolean, default: false, }, /** - * input id + * @zh-CN 输入框的 id + * @en-US The id of the input box */ inputId: { type: String,