col-page.vue
2.38 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
<script lang="ts" setup>
import type { ColPageProps } from './types';
import { computed, ref, useSlots } from 'vue';
import {
ResizableHandle,
ResizablePanel,
ResizablePanelGroup,
} from '@vben-core/shadcn-ui';
import Page from '../page/page.vue';
defineOptions({
name: 'ColPage',
inheritAttrs: false,
});
const props = withDefaults(defineProps<ColPageProps>(), {
leftWidth: 30,
rightWidth: 70,
resizable: true,
});
const delegatedProps = computed(() => {
const { leftWidth: _, ...delegated } = props;
return delegated;
});
const slots = useSlots();
const delegatedSlots = computed(() => {
const resultSlots: string[] = [];
for (const key of Object.keys(slots)) {
if (!['default', 'left'].includes(key)) {
resultSlots.push(key);
}
}
return resultSlots;
});
const leftPanelRef = ref<InstanceType<typeof ResizablePanel>>();
function expandLeft() {
leftPanelRef.value?.expand();
}
function collapseLeft() {
leftPanelRef.value?.collapse();
}
defineExpose({
expandLeft,
collapseLeft,
});
</script>
<template>
<Page v-bind="delegatedProps">
<!-- 继承默认的slot -->
<template
v-for="slotName in delegatedSlots"
:key="slotName"
#[slotName]="slotProps"
>
<slot :name="slotName" v-bind="slotProps"></slot>
</template>
<ResizablePanelGroup class="w-full" direction="horizontal">
<ResizablePanel
ref="leftPanelRef"
:collapsed-size="leftCollapsedWidth"
:collapsible="leftCollapsible"
:default-size="leftWidth"
:max-size="leftMaxWidth"
:min-size="leftMinWidth"
>
<template #default="slotProps">
<slot
name="left"
v-bind="{
...slotProps,
expand: expandLeft,
collapse: collapseLeft,
}"
></slot>
</template>
</ResizablePanel>
<ResizableHandle
v-if="resizable"
:style="{ backgroundColor: splitLine ? undefined : 'transparent' }"
:with-handle="splitHandle"
/>
<ResizablePanel
:collapsed-size="rightCollapsedWidth"
:collapsible="rightCollapsible"
:default-size="rightWidth"
:max-size="rightMaxWidth"
:min-size="rightMinWidth"
>
<template #default>
<slot></slot>
</template>
</ResizablePanel>
</ResizablePanelGroup>
</Page>
</template>