diff --git a/packages/devui-theme/vite.config.theme-collection.ts b/packages/devui-theme/vite.config.theme.collection.ts similarity index 100% rename from packages/devui-theme/vite.config.theme-collection.ts rename to packages/devui-theme/vite.config.theme.collection.ts diff --git a/packages/devui-vue/devui/panel/src/body/panel-body.tsx b/packages/devui-vue/devui/panel/src/body/panel-body.tsx index 345b13baed..f59c1a7293 100644 --- a/packages/devui-vue/devui/panel/src/body/panel-body.tsx +++ b/packages/devui-vue/devui/panel/src/body/panel-body.tsx @@ -1,11 +1,11 @@ -import { defineComponent,ref,onMounted,Transition,inject,Ref } from 'vue'; +import { defineComponent, ref, onMounted, Transition, inject, Ref } from 'vue'; import { PanelProps } from '../panel.type'; import Store from '../store/store'; export default defineComponent({ name: 'DPanelBody', - props:PanelProps, - setup(props,ctx){ + props: PanelProps, + setup(props, ctx) { const animationName = inject('showAnimation') as Ref; const hasLeftPadding = inject('hasLeftPadding') as Ref; const keys = Object.keys(Store.state()); @@ -13,15 +13,16 @@ export default defineComponent({ const isCollapsed = Store.state(); const bodyEl = ref(); onMounted(() => { - if(bodyEl.value) { + if (bodyEl.value) { const dom = bodyEl.value; - if(isCollapsed[key]) - {dom.style.height = `${dom.offsetHeight}px`;} + if (isCollapsed[key as string]) { + dom.style.height = `${dom.offsetHeight}px`; + } } }); const enter = (element: Element) => { - const el = (element as HTMLElement); + const el = element as HTMLElement; el.style.height = ''; const height = el.offsetHeight; el.style.height = '0px'; @@ -30,19 +31,22 @@ export default defineComponent({ el.style.height = `${height}px`; }; const leave = (element: Element) => { - const el = (element as HTMLElement); + const el = element as HTMLElement; el.style.height = '0px'; }; return () => { return (
- - {isCollapsed[key] === undefined || isCollapsed[key] ? -
-
- {ctx.slots.default?.()} -
-
: null } + + {isCollapsed[key as string] === undefined || isCollapsed[key as string] ? ( +
+
{ctx.slots.default?.()}
+
+ ) : null}
); diff --git a/packages/devui-vue/devui/panel/src/foot/panel-footer.tsx b/packages/devui-vue/devui/panel/src/foot/panel-footer.tsx index 551dcd6a8f..be30e475b5 100644 --- a/packages/devui-vue/devui/panel/src/foot/panel-footer.tsx +++ b/packages/devui-vue/devui/panel/src/foot/panel-footer.tsx @@ -1,4 +1,4 @@ -import {ref,defineComponent} from 'vue'; +import {defineComponent} from 'vue'; export default defineComponent({ name: 'DPanelFooter', diff --git a/packages/devui-vue/devui/panel/src/header/panel-header.tsx b/packages/devui-vue/devui/panel/src/header/panel-header.tsx index 2262c09551..13eb8a4c0b 100644 --- a/packages/devui-vue/devui/panel/src/header/panel-header.tsx +++ b/packages/devui-vue/devui/panel/src/header/panel-header.tsx @@ -1,60 +1,73 @@ -import { defineComponent,ref,inject } from 'vue'; +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { defineComponent,ref,inject,Ref } from 'vue'; import {PanelProps} from '../panel.type'; import Store from '../store/store'; export default defineComponent({ name: 'DPanelHeader', props: PanelProps, + emits: ['toggle'], setup(props,ctx){ const beforeToggle = inject('beforeToggle'); const keys = Object.keys(Store.state()); const key = keys.pop(); - const isCollapsed = ref(Store.state()[key]); - // 当beforeToggle为fals时 - // 最好cursor是default 而不是 pointer; - // pointer一般用于可点击的 - // 用changeFlag + const isCollapsed = ref(Store.state()[key as string]) as Ref; const changeFlag = ref(); - let header = null; - - - const canToggle = (): Promise => { - let changeResult = Promise.resolve(true); - if(beforeToggle) { - const result = beforeToggle(isCollapsed); - if(typeof result !== undefined) { - if(result instanceof Promise) { - changeResult = result; + let header: JSX.Element | null = null; + const res = ref(isCollapsed.value) as Ref; + let changeResult = true; + const done = () => { + res.value = !res.value; + if (!changeFlag.value){ + // 禁止折叠不影响展开 + if (res.value){ + Store.setData(`${key}`, res.value); + isCollapsed.value = res.value; + ctx.emit('toggle', res.value); + } + return; + } + if (res.value !== undefined) { + Store.setData(`${key}`, res.value); + isCollapsed.value = res.value; + ctx.emit('toggle', res.value); + } + }; + const canToggle = async (): Promise => { + if (beforeToggle){ + const tmpRes = (beforeToggle as (value: Ref, + done?: () => void) => any)(isCollapsed, done); + if (typeof tmpRes !== 'undefined'){ + if (tmpRes instanceof Promise){ + changeResult = (await tmpRes); } else { - changeResult = Promise.resolve(result); + changeResult = tmpRes; } + } else { + changeResult = true; } } return changeResult; }; - - // 需要执行一次才能生效; - canToggle().then((val)=>changeFlag.value = val); - + canToggle().then(val => changeFlag.value = val); const toggleBody = (): void => { - canToggle().then((val) => { + canToggle().then((val)=>{ changeFlag.value = val; if (!val){ // 禁止折叠不影响展开 if (!isCollapsed.value){ Store.setData(`${key}`, !isCollapsed.value); isCollapsed.value = !isCollapsed.value; - props.toggle?.(isCollapsed.value); + ctx.emit('toggle', isCollapsed.value); } return; } if (isCollapsed.value !== undefined) { Store.setData(`${key}`, !isCollapsed.value); isCollapsed.value = !isCollapsed.value; - props.toggle?.(isCollapsed.value); + ctx.emit('toggle', isCollapsed.value); } }); - }; return () => { if (ctx.slots.default){ diff --git a/packages/devui-vue/devui/panel/src/panel.tsx b/packages/devui-vue/devui/panel/src/panel.tsx index 90c2b1733d..d11af1995e 100644 --- a/packages/devui-vue/devui/panel/src/panel.tsx +++ b/packages/devui-vue/devui/panel/src/panel.tsx @@ -6,6 +6,7 @@ import Store from './store/store'; export default defineComponent({ name: 'DPanel', props: PanelProps, + emits: ['toggle'], setup(props, ctx) { provide('beforeToggle', props.beforeToggle); provide('showAnimation', computed(()=>props.showAnimation)); @@ -13,10 +14,10 @@ export default defineComponent({ const isCollapsed = ref(props.isCollapsed); const type = computed(()=>props.type); const cssClass = computed(()=>props.cssClass); + const timeStamp = new Date().getTime().toString() + Math.random(); const onToggle = ()=> { - props.toggle?.(Store.getByKey(`isCollapsed[${timeStamp}]`)); + ctx.emit('toggle', Store.getByKey(`isCollapsed[${timeStamp}]`)); }; - const timeStamp = new Date().getTime().toString(); Store.setData(`isCollapsed[${timeStamp}]`, isCollapsed.value); return () => { return ( diff --git a/packages/devui-vue/devui/panel/src/panel.type.ts b/packages/devui-vue/devui/panel/src/panel.type.ts index 634550e232..f246cf55d5 100644 --- a/packages/devui-vue/devui/panel/src/panel.type.ts +++ b/packages/devui-vue/devui/panel/src/panel.type.ts @@ -16,11 +16,7 @@ export const PanelProps = { default: false }, beforeToggle: { - type: Function as unknown as () => (value: boolean) => boolean | Promise, - default: null - }, - toggle: { - type: Function as unknown as () => ((value: boolean) => void), + type: Function as unknown as () => (value: boolean, done?: () => void) => any, default: null }, showAnimation: { diff --git a/packages/devui-vue/devui/panel/src/store/store.ts b/packages/devui-vue/devui/panel/src/store/store.ts index a85617322d..fb40f51e7e 100644 --- a/packages/devui-vue/devui/panel/src/store/store.ts +++ b/packages/devui-vue/devui/panel/src/store/store.ts @@ -1,16 +1,16 @@ /* eslint-disable @typescript-eslint/explicit-module-boundary-types */ import {ref,reactive} from 'vue'; -export const option = reactive({}); +export const option = reactive({}) as Record; class Store { - public static getByKey(timeStamp){ + public static getByKey(timeStamp: string){ return option[timeStamp]; } public static state() { return option; } - public static setData(key,value){ + public static setData(key: string ,value: unknown){ option[key] = ref(value); } } diff --git a/packages/devui-vue/docs/components/panel/index.md b/packages/devui-vue/docs/components/panel/index.md index 30545ed2de..3d9b6b61d0 100644 --- a/packages/devui-vue/docs/components/panel/index.md +++ b/packages/devui-vue/docs/components/panel/index.md @@ -64,6 +64,8 @@ export default defineComponent({ Panel with info Type This is body +
+
Panel with Primary Type This is body @@ -104,7 +106,7 @@ export default defineComponent({ @@ -116,6 +118,7 @@ export default defineComponent({

+ 当前状态: {{nowState}}
{{ panelToggle ? '阻止折叠' : '允许折叠' }} @@ -131,11 +134,12 @@ export default defineComponent({ let showAnimation = ref(true); let state; let padding = ref(false); + let nowState = ref('收起'); const handleToggle = (e) => { toggle.value = e; + nowState.value = toggle.value === true ? '展开' : '收起'; }; const beforeToggle = (e) => { - console.log(e); return panelToggle.value; }; return { @@ -146,11 +150,67 @@ export default defineComponent({ isCollapsed, handleToggle, showAnimation, - padding + padding, + nowState + }; + } +}); + +``` + +::: + +在某些场景下,我们或许需要使用js来对Panel进行开合控制,尤其是异步时。我们可以使用beforeToggle中的```done```函数来对Panel进行开合处理。 + +案例中我们使用setTimeout来模拟异步任务控制Panel开合 + +:::demo + +```vue + + + + + ``` ::: @@ -200,8 +260,8 @@ export default defineComponent({ | is-collapsed | boolean | false | 可选,是否展开 | | has-left-padding | boolean | true | 可选,是否显示左侧填充 | | show-animation | boolean | true | 可选,是否展示动画 | -| before-toggle | Function\|Promise\|Observable | -- | 可选,面板折叠状态改变前的回调函数,返回 boolean 类型,返回 false 可以阻止面板改变折叠状态 根据条件阻止折叠 | -| toggle | Function | -- | 可选,面板当前状态的回调函数,返回 boolean 类型,返回 false 代表面板被收起,返回 true 代表面板展开 | +| before-toggle | () => (value: boolean, done?: () => void) => any | -- | 可选,面板折叠状态改变前的回调函数, 参数```value```代表当前状态,参数```done()```可以控制Panel开合 | +| @toggle | Function | -- | 可选,面板当前状态的回调函数,返回 boolean 类型,返回 false 代表面板被收起,返回 true 代表面板展开 | ### 接口&类型定义