vue-vben-admin/src/components/Container/src/collapse/CollapseContainer.vue

119 lines
3.2 KiB
Vue

<script lang="tsx">
import { CollapseTransition } from '@/components/Transition';
import { useDesign } from '@/hooks/web/useDesign';
import { triggerWindowResize } from '@/utils/event';
import { useTimeoutFn } from '@vben/hooks';
import { Skeleton } from 'ant-design-vue';
import { isNil } from 'lodash-es';
import { defineComponent, ref, unref, type ExtractPropTypes, type PropType } from 'vue';
import CollapseHeader from './CollapseHeader.vue';
const collapseContainerProps = {
title: { type: String, default: '' },
loading: { type: Boolean },
/**
* Can it be expanded
*/
canExpand: { type: Boolean, default: true },
/**
* Warm reminder on the right side of the title
*/
helpMessage: {
type: [Array, String] as PropType<string[] | string>,
default: '',
},
/**
* Whether to trigger window.resize when expanding and contracting,
* Can adapt to tables and forms, when the form shrinks, the form triggers resize to adapt to the height
*/
triggerWindowResize: { type: Boolean },
/**
* Delayed loading time
*/
lazyTime: { type: Number, default: 0 },
};
export type CollapseContainerProps = ExtractPropTypes<typeof collapseContainerProps>;
export default defineComponent({
name: 'CollapseContainer',
props: collapseContainerProps,
setup(props, { expose, slots }) {
const { prefixCls } = useDesign('collapse-container');
const show = ref(true);
const handleExpand = (val: boolean) => {
show.value = isNil(val) ? !show.value : val;
if (props.triggerWindowResize) {
// 200 milliseconds here is because the expansion has animation,
useTimeoutFn(triggerWindowResize, 200);
}
};
expose({ handleExpand });
return () => (
<div class={unref(prefixCls)}>
<CollapseHeader
{...props}
prefixCls={unref(prefixCls)}
onExpand={handleExpand}
show={show.value}
v-slots={{
title: slots.title,
action: slots.action,
}}
/>
<div class="p-2">
<CollapseTransition enable={props.canExpand}>
{props.loading ? (
<Skeleton active={props.loading} />
) : (
<div class={`${prefixCls}__body`} v-show={show.value}>
{slots.default?.()}
</div>
)}
</CollapseTransition>
</div>
{slots.footer && <div class={`${prefixCls}__footer`}>{slots.footer()}</div>}
</div>
);
},
});
</script>
<style lang="less">
@prefix-cls: ~'@{namespace}-collapse-container';
.@{prefix-cls} {
transition: all 0.3s ease-in-out;
border-radius: 2px;
background-color: @component-background;
&__header {
display: flex;
align-items: center;
justify-content: space-between;
height: 32px;
border-bottom: 1px solid @border-color-light;
}
&__footer {
border-top: 1px solid @border-color-light;
}
&__action {
display: flex;
flex: 1;
align-items: center;
justify-content: flex-end;
text-align: right;
}
}
</style>