diff --git a/common/config/rush/pnpm-lock.yaml b/common/config/rush/pnpm-lock.yaml index db8c76bb9..cc3120d27 100644 --- a/common/config/rush/pnpm-lock.yaml +++ b/common/config/rush/pnpm-lock.yaml @@ -8,6 +8,7 @@ importers: ../../docs: specifiers: '@arco-design/web-react': 2.60.2 + '@arco-design/web-vue': ^2.11.0 '@internal/eslint-config': workspace:* '@internal/ts-config': workspace:* '@types/buble': ^0.20.5 @@ -47,6 +48,7 @@ importers: yargs: ^17.1.1 dependencies: '@arco-design/web-react': 2.60.2_52ux7kpa62vlx2is4pxiuz7b44 + '@arco-design/web-vue': 2.56.1_vue@3.5.0 '@visactor/openinula-vtable': link:../packages/openinula-vtable '@visactor/react-vtable': link:../packages/react-vtable '@visactor/vchart': 1.12.1 @@ -1130,7 +1132,6 @@ packages: resize-observer-polyfill: 1.5.1 scroll-into-view-if-needed: 2.2.31 vue: 3.5.0_typescript@4.9.5 - dev: true /@babel/code-frame/7.24.7: resolution: {integrity: sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==} @@ -12374,7 +12375,6 @@ packages: resolution: {integrity: sha512-dGCXy99wZQivjmjIqihaBQNjryrz5rueJY7eHfTdyWEiR4ttYpsajb14rn9s5d4DY4EcY6+4+U/maARBXJedkA==} dependencies: compute-scroll-into-view: 1.0.20 - dev: true /semver-compare/1.0.0: resolution: {integrity: sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==} diff --git a/docs/assets/demo-vue/en/edit-data/arco-select-editor.md b/docs/assets/demo-vue/en/edit-data/arco-select-editor.md index 51580888d..a42d60e31 100644 --- a/docs/assets/demo-vue/en/edit-data/arco-select-editor.md +++ b/docs/assets/demo-vue/en/edit-data/arco-select-editor.md @@ -1,21 +1,229 @@ --- category: examples group: functional-components -title: 自定义编辑器中使用arco列表选择器 +title: Using Arco Select in Custom Editor cover: link: '../guide/Developer_Ecology/vue' --- -# 自定义编辑器中使用 arco 列表选择器 +# Using Arco Select in Custom Editor -创建自定义编辑器类 ArcoListEditor, 并实现 onStart 方法,创建一个 arco-design 的 Select 组件,并将组件挂载到编辑器容器中。完善 isEditorElement 和 onEnd 方法。 +Create a custom editor class `ArcoListEditor` and implement the `onStart` method to create an Arco Design `Select` component and mount it to the editor container. Complete the `isEditorElement` and `onEnd` methods. -参考: +References: https://visactor.io/vtable/guide/edit/edit_cell https://arco.design/vue/components/select -## 代码演示 +## Code Demonstration -```javascript livedemo template=vtable-vue \ No newline at end of file +```javascript livedemo template=vtable-vue + +class ArcoListEditor { + root = null; + element = null; + container = null; + currentValue = null; + + onStart(editorContext) { + const { container, referencePosition, value } = editorContext; + this.container = container; + this.createElement(value); + if (value) this.setValue(value); + if (referencePosition?.rect) this.adjustPosition(referencePosition.rect); + } + + createElement(defaultValue) { + const div = document.createElement('div'); + div.style.position = 'absolute'; + div.style.width = '100%'; + div.style.padding = '1px'; + div.style.boxSizing = 'border-box'; + this.container?.appendChild(div); + + const app = this.createVueApp(defaultValue); + app.mount(div); + this.root = app; + this.element = div; + } + + createVueApp(defaultValue) { + const self = this; + return createApp({ + data() { + return { + currentValue: defaultValue, + options: ['Beijing', 'Shanghai', 'Guangzhou'], + }; + }, + render() { + return h('div', {}, [ + h(ArcoDesignVue.Select, { + style: { height: '32px' }, + placeholder: 'Select city', + modelValue: this.currentValue, + 'onUpdate:modelValue': (value) => { + this.currentValue = value; + self.setValue(value); + }, + }, { + default: () => + this.options.map((option) => + h(ArcoDesignVue.Option, { key: option, value: option }, { default: () => option }) + ), + }), + ]); + }, + }); + } + + getValue() { + return this.currentValue; + } + + setValue(value) { + this.currentValue = value; + } + + adjustPosition(rect) { + if (this.element) { + this.element.style.top = `${rect.top}px`; + this.element.style.left = `${rect.left}px`; + this.element.style.width = `${rect.width}px`; + this.element.style.height = `${rect.height}px`; + } + } + + onEnd() { + if (this.root) { + this.root.unmount(); + this.root = null; + } + if (this.element && this.container) { + this.container.removeChild(this.element); + this.element = null; + } + } + + isEditorElement(target) { + return this.element?.contains(target) || this.isClickPopUp(target); + } + + isClickPopUp(target) { + while (target) { + if (target.classList && target.classList.contains('arco-select')) { + return true; + } + target = target.parentNode; + } + return false; + } +} + +const input_editor = new VTable_editors.InputEditor(); +const date_input_editor = new VTable_editors.DateInputEditor(); +VTable.register.editor('input-editor', input_editor); +VTable.register.editor('date-input-editor', date_input_editor); +VTable.register.editor('arcoVue-editor', new ArcoListEditor()); + +function generateRandomString(length) { + let result = ''; + const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; + for (let i = 0; i < length; i++) { + result += characters.charAt(Math.floor(Math.random() * characters.length)); + } + return result; +} + +const generatePersons = (count) => { + return Array.from(new Array(count)).map((_, i) => { + const first = generateRandomString(10); + const last = generateRandomString(4); + return { + id: i + 1, + email1: `${first}_${last}@xxx.com`, + name: first, + lastName: last, + address: `No.${i + 100} ${generateRandomString(10)} ${generateRandomString(5)} ${generateRandomString(5)}`, + sex: i % 2 === 0 ? 'boy' : 'girl', + work: i % 2 === 0 ? 'back-end engineer' : 'front-end engineer', + city: 'beijing', + }; + }); +}; + +const records = generatePersons(10); +const columns = [ + { + field: 'id', + title: 'ID', + width: 80, + sort: true, + }, + { + field: 'full name', + title: 'Full name', + columns: [ + { + field: 'name', + title: 'First Name\n(input editor)', + width: 140, + editor: 'input-editor', + }, + { + field: 'lastName', + title: 'Last Name\n(input editor)', + width: 100, + editor: 'input-editor', + }, + ], + }, + { + field: 'address', + title: 'location\n(arcoVue-editor)', + width: 400, + editor: 'arcoVue-editor', + }, +]; + +const option = { + enableLineBreak: true, + autoWrapText: true, + limitMaxAutoWidth: 700, + heightMode: 'autoHeight', + editCellTrigger: 'click', + keyboardOptions: { + copySelected: true, + pasteValueToCell: true, + selectAllOnCtrlA: true, + }, +}; + +const app = createApp({ + template: ` + + + + `, + data() { + return { + records, + columns, + option, + }; + }, +}); + +app.component('ListTable', VueVTable.ListTable); +app.component('ListColumn', VueVTable.ListColumn); + +app.mount(`#${CONTAINER_ID}`); diff --git a/docs/assets/demo-vue/zh/edit-data/arco-select-editor.md b/docs/assets/demo-vue/zh/edit-data/arco-select-editor.md index 51580888d..49c445454 100644 --- a/docs/assets/demo-vue/zh/edit-data/arco-select-editor.md +++ b/docs/assets/demo-vue/zh/edit-data/arco-select-editor.md @@ -18,4 +18,214 @@ https://arco.design/vue/components/select ## 代码演示 -```javascript livedemo template=vtable-vue \ No newline at end of file +```javascript livedemo template=vtable-vue + + +class ArcoListEditor { + root = null; + element = null; + container = null; + currentValue = null; + + onStart(editorContext) { + const { container, referencePosition, value } = editorContext; + this.container = container; + this.createElement(value); + if (value) this.setValue(value); + if (referencePosition?.rect) this.adjustPosition(referencePosition.rect); + } + + createElement(defaultValue) { + const div = document.createElement('div'); + div.style.position = 'absolute'; + div.style.width = '100%'; + div.style.padding = '1px'; + div.style.boxSizing = 'border-box'; + this.container?.appendChild(div); + + const app = this.createVueApp(defaultValue); + app.mount(div); + this.root = app; + this.element = div; + } + + createVueApp(defaultValue) { + const self = this; + return createApp({ + data() { + return { + currentValue: defaultValue, + options: ['Beijing', 'Shanghai', 'Guangzhou'], + }; + }, + render() { + return h('div', {}, [ + h(ArcoDesignVue.Select, { + style: { height: '32px' }, + placeholder: 'Select city', + modelValue: this.currentValue, + 'onUpdate:modelValue': (value) => { + this.currentValue = value; + self.setValue(value); + }, + }, { + default: () => + this.options.map((option) => + h(ArcoDesignVue.Option, { key: option, value: option }, { default: () => option }) + ), + }), + ]); + }, + }); + } + + getValue() { + return this.currentValue; + } + + setValue(value) { + this.currentValue = value; + } + + adjustPosition(rect) { + if (this.element) { + this.element.style.top = `${rect.top}px`; + this.element.style.left = `${rect.left}px`; + this.element.style.width = `${rect.width}px`; + this.element.style.height = `${rect.height}px`; + } + } + + onEnd() { + if (this.root) { + this.root.unmount(); + this.root = null; + } + if (this.element && this.container) { + this.container.removeChild(this.element); + this.element = null; + } + } + + isEditorElement(target) { + return this.element?.contains(target) || this.isClickPopUp(target); + } + + isClickPopUp(target) { + while (target) { + if (target.classList && target.classList.contains('arco-select')) { + return true; + } + target = target.parentNode; + } + return false; + } +} + +const input_editor = new VTable_editors.InputEditor(); +const date_input_editor = new VTable_editors.DateInputEditor(); +VTable.register.editor('input-editor', input_editor); +VTable.register.editor('date-input-editor', date_input_editor); +VTable.register.editor('arcoVue-editor', new ArcoListEditor()); + +function generateRandomString(length) { + let result = ''; + const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; + for (let i = 0; i < length; i++) { + result += characters.charAt(Math.floor(Math.random() * characters.length)); + } + return result; +} + +const generatePersons = (count) => { + return Array.from(new Array(count)).map((_, i) => { + const first = generateRandomString(10); + const last = generateRandomString(4); + return { + id: i + 1, + email1: `${first}_${last}@xxx.com`, + name: first, + lastName: last, + address: `No.${i + 100} ${generateRandomString(10)} ${generateRandomString(5)} ${generateRandomString(5)}`, + sex: i % 2 === 0 ? 'boy' : 'girl', + work: i % 2 === 0 ? 'back-end engineer' : 'front-end engineer', + city: 'beijing', + }; + }); +}; + +const records = generatePersons(10); +const columns = [ + { + field: 'id', + title: 'ID', + width: 80, + sort: true, + }, + { + field: 'full name', + title: 'Full name', + columns: [ + { + field: 'name', + title: 'First Name\n(input editor)', + width: 140, + editor: 'input-editor', + }, + { + field: 'lastName', + title: 'Last Name\n(input editor)', + width: 100, + editor: 'input-editor', + }, + ], + }, + { + field: 'address', + title: 'location\n(arcoVue-editor)', + width: 400, + editor: 'arcoVue-editor', + }, +]; + +const option = { + enableLineBreak: true, + autoWrapText: true, + limitMaxAutoWidth: 700, + heightMode: 'autoHeight', + editCellTrigger: 'click', + keyboardOptions: { + copySelected: true, + pasteValueToCell: true, + selectAllOnCtrlA: true, + }, +}; + +const app = createApp({ + template: ` + + + + `, + data() { + return { + records, + columns, + option, + }; + }, +}); + + +app.component('ListTable', VueVTable.ListTable); +app.component('ListColumn', VueVTable.ListColumn); + +app.mount(`#${CONTAINER_ID}`); diff --git a/docs/package.json b/docs/package.json index ced94c107..d49cb5625 100644 --- a/docs/package.json +++ b/docs/package.json @@ -11,6 +11,7 @@ }, "dependencies": { "@arco-design/web-react": "2.60.2", + "@arco-design/web-vue": "^2.11.0", "@visactor/vtable": "workspace:*", "@visactor/react-vtable": "workspace:*", "@visactor/vue-vtable": "workspace:*", diff --git a/docs/src/main.tsx b/docs/src/main.tsx index 7f73a95e7..aaf774b94 100644 --- a/docs/src/main.tsx +++ b/docs/src/main.tsx @@ -13,11 +13,14 @@ import * as VueVTable from '@visactor/vue-vtable'; import * as InulaVTable from '@visactor/openinula-vtable'; import { App } from './app'; import * as ArcoDesign from '@arco-design/web-react'; +import * as ArcoDesignVue from '@arco-design/web-vue'; import * as ArcoDesignIcon from '@arco-design/web-react/icon'; import '@arco-design/web-react/dist/css/arco.css'; +import '@arco-design/web-vue/dist/arco.css'; import { createApp, ref, onMounted, h } from 'vue'; (window as any).ArcoDesign = ArcoDesign; +(window as any).ArcoDesignVue = ArcoDesignVue; (window as any).ArcoDesignIcon = ArcoDesignIcon; (window as any).VTable = VTable; (window as any).VRender = VRender;