Skip to content

Commit 28c51cb

Browse files
committed
Allow primary to be collapsed
1 parent 067dec3 commit 28c51cb

File tree

1 file changed

+36
-13
lines changed

1 file changed

+36
-13
lines changed

src/SplitPanel.vue

Lines changed: 36 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,23 @@ export interface SplitPanelProps {
99
/** If no primary panel is designated, both panels will resize proportionally when the host element is resized. If a primary panel is designated, it will maintain its size and the other panel will grow or shrink as needed when the panels component is resized */
1010
primary?: 'start' | 'end';
1111
12-
/** The minimum allowed size of the primary panel. Accepts CSS like `"15px"` or `"5em"` */
13-
min?: string;
14-
15-
/** The maximum allowed size of the primary panel. Accepts CSS like `"15px"` or `"5em"` */
16-
max?: string;
17-
18-
/** The invisible region around the divider where dragging can occur. This is usually wider than the divider to facilitate easier dragging. */
12+
/** The invisible region around the divider where dragging can occur. This is usually wider than the divider to facilitate easier dragging. CSS value */
1913
dividerHitArea?: string;
2014
2115
/** Whether the size v-model should be in relative percentages or absolute pixels */
2216
sizeUnit?: '%' | 'px';
2317
2418
/** Disable the manual resizing of the panels */
2519
disabled?: boolean;
20+
21+
/** The minimum allowed size of the primary panel. Accepts CSS like `"15px"` or `"5em"` */
22+
minSize?: string;
23+
24+
/** The maximum allowed size of the primary panel. Accepts CSS like `"15px"` or `"5em"` */
25+
maxSize?: string;
26+
27+
/** Whether to allow the primary panel to be collapsed on enter key on divider or when the collapse threshold is met */
28+
collapsible?: boolean;
2629
}
2730
</script>
2831

@@ -37,11 +40,12 @@ const props = withDefaults(defineProps<SplitPanelProps>(), {
3740
orientation: 'horizontal',
3841
disabled: false,
3942
snapThreshold: 12,
40-
min: '0px',
41-
max: '100%',
43+
minSize: '0px',
44+
maxSize: '100%',
4245
dividerHitArea: '12px',
4346
sizeUnit: '%',
4447
direction: 'ltr',
48+
collapsible: false,
4549
});
4650
4751
const panelEl = useTemplateRef('split-panel');
@@ -55,6 +59,9 @@ const dividerSize = computed(() => props.orientation === 'horizontal' ? dividerW
5559
5660
const { x: dividerX, y: dividerY } = useDraggable(dividerEl, { containerElement: panelEl });
5761
62+
/** Whether the primary column is collapsed or not */
63+
const collapsed = defineModel<boolean>('collapsed', { default: false });
64+
5865
/** Size of the primary panel in either percentages or pixels as defined by the sizeUnit property */
5966
const primaryPanelSize = defineModel<number>('size', { default: 50 });
6067
@@ -88,6 +95,18 @@ const primaryPanelSizePixels = computed({
8895
},
8996
});
9097
98+
let expandedPrimaryPanelSizePercentage = 0;
99+
100+
watch(collapsed, (newCollapsed) => {
101+
if (newCollapsed === true) {
102+
expandedPrimaryPanelSizePercentage = primaryPanelSizePercentage.value;
103+
primaryPanelSizePercentage.value = 0;
104+
}
105+
else {
106+
primaryPanelSizePercentage.value = expandedPrimaryPanelSizePercentage;
107+
}
108+
});
109+
91110
let cachedPrimaryPanelSizePixels = 0;
92111
93112
onMounted(() => {
@@ -153,12 +172,10 @@ const handleKeydown = (event: KeyboardEvent) => {
153172
154173
primaryPanelSizePercentage.value = clamp(newPosition, 0, 100);
155174
}
156-
157-
// TODO handle enter key collapsing / opening the primary panel
158175
};
159176
160177
const gridTemplate = computed(() => {
161-
const primary = `clamp(0%, clamp(${props.min}, ${primaryPanelSizePercentage.value}%, ${props.max}), calc(100% - ${dividerSize.value}px))`;
178+
const primary = `clamp(0%, clamp(${props.minSize}, ${primaryPanelSizePercentage.value}%, ${props.maxSize}), calc(100% - ${dividerSize.value}px))`;
162179
const secondary = 'auto';
163180
164181
if (!props.primary || props.primary === 'start') {
@@ -178,10 +195,16 @@ const gridTemplate = computed(() => {
178195
}
179196
}
180197
});
198+
199+
const collapse = () => collapsed.value = true;
200+
const expand = () => collapsed.value = false;
201+
const toggle = (val: boolean) => collapsed.value = val;
202+
203+
defineExpose({ collapse, expand, toggle });
181204
</script>
182205

183206
<template>
184-
<div ref="split-panel" class="split-panel" :class="orientation">
207+
<div ref="split-panel" class="split-panel" :class="[orientation, { collapsed }]">
185208
<div class="start">
186209
<slot name="start" />
187210
</div>

0 commit comments

Comments
 (0)