@@ -18,14 +18,17 @@ export interface SplitPanelProps {
1818 /** Disable the manual resizing of the panels */
1919 disabled? : boolean ;
2020
21- /** The minimum allowed size of the primary panel. Accepts CSS like `"15px"` or `"5em"` */
22- minSize? : string ;
21+ /** The minimum allowed size of the primary panel */
22+ minSize? : number ;
2323
24- /** The maximum allowed size of the primary panel. Accepts CSS like `"15px"` or `"5em"` */
25- maxSize? : string ;
24+ /** The maximum allowed size of the primary panel */
25+ maxSize? : number ;
2626
2727 /** Whether to allow the primary panel to be collapsed on enter key on divider or when the collapse threshold is met */
2828 collapsible? : boolean ;
29+
30+ /** How far to drag beyond the minSize to collapse/expand the primary panel */
31+ collapseThreshold? : number ;
2932}
3033 </script >
3134
@@ -40,8 +43,8 @@ const props = withDefaults(defineProps<SplitPanelProps>(), {
4043 orientation: ' horizontal' ,
4144 disabled: false ,
4245 snapThreshold: 12 ,
43- minSize: ' 0px ' ,
44- maxSize: ' 100% ' ,
46+ minSize: 0 ,
47+ maxSize: 100 ,
4548 dividerHitArea: ' 12px' ,
4649 sizeUnit: ' %' ,
4750 direction: ' ltr' ,
@@ -57,62 +60,90 @@ const componentSize = computed(() => props.orientation === 'horizontal' ? compon
5760const { width : dividerWidth, height : dividerHeight } = useElementSize (dividerEl );
5861const dividerSize = computed (() => props .orientation === ' horizontal' ? dividerWidth .value : dividerHeight .value );
5962
60- const { x : dividerX, y : dividerY } = useDraggable (dividerEl , { containerElement: panelEl });
61-
62- /** Whether the primary column is collapsed or not */
63- const collapsed = defineModel <boolean >(' collapsed' , { default: false });
64-
6563/** Size of the primary panel in either percentages or pixels as defined by the sizeUnit property */
66- const primaryPanelSize = defineModel <number >(' size' , { default: 50 });
64+ const size = defineModel <number >(' size' , { default: 50 });
6765
68- const primaryPanelSizePercentage = computed ({
66+ const sizePercentage = computed ({
6967 get() {
70- if (props .sizeUnit === ' %' ) return primaryPanelSize .value ;
71- return pixelsToPercentage (componentSize .value , primaryPanelSize .value );
68+ if (props .sizeUnit === ' %' ) return size .value ;
69+ return pixelsToPercentage (componentSize .value , size .value );
7270 },
7371 set(newValue : number ) {
7472 if (props .sizeUnit === ' %' ) {
75- primaryPanelSize .value = newValue ;
73+ size .value = newValue ;
7674 }
7775 else {
78- primaryPanelSize .value = percentageToPixels (componentSize .value , newValue );
76+ size .value = percentageToPixels (componentSize .value , newValue );
7977 }
8078 },
8179});
8280
83- const primaryPanelSizePixels = computed ({
81+ const sizePixels = computed ({
8482 get() {
85- if (props .sizeUnit === ' px' ) return primaryPanelSize .value ;
86- return percentageToPixels (componentSize .value , primaryPanelSize .value );
83+ if (props .sizeUnit === ' px' ) return size .value ;
84+ return percentageToPixels (componentSize .value , size .value );
8785 },
8886 set(newValue : number ) {
8987 if (props .sizeUnit === ' px' ) {
90- primaryPanelSize .value = newValue ;
88+ size .value = newValue ;
9189 }
9290 else {
93- primaryPanelSize .value = pixelsToPercentage (componentSize .value , newValue );
91+ size .value = pixelsToPercentage (componentSize .value , newValue );
9492 }
9593 },
9694});
9795
98- let expandedPrimaryPanelSizePercentage = 0 ;
96+ const minSizePercentage = computed (() => {
97+ if (props .minSize === undefined ) return ;
98+
99+ if (props .sizeUnit === ' %' ) return props .minSize ;
100+ return pixelsToPercentage (componentSize .value , props .minSize );
101+ });
102+
103+ const minSizePixels = computed (() => {
104+ if (props .minSize === undefined ) return ;
105+
106+ if (props .sizeUnit === ' px' ) return props .minSize ;
107+ return percentageToPixels (componentSize .value , props .minSize );
108+ });
109+
110+ const maxSizePercentage = computed (() => {
111+ if (props .maxSize === undefined ) return ;
112+
113+ if (props .sizeUnit === ' %' ) return props .maxSize ;
114+ return pixelsToPercentage (componentSize .value , props .maxSize );
115+ });
116+
117+ const maxSizePixels = computed (() => {
118+ if (props .maxSize === undefined ) return ;
119+
120+ if (props .sizeUnit === ' px' ) return props .maxSize ;
121+ return percentageToPixels (componentSize .value , props .maxSize );
122+ });
123+
124+ let expandedSizePercentage = 0 ;
125+
126+ /** Whether the primary column is collapsed or not */
127+ const collapsed = defineModel <boolean >(' collapsed' , { default: false });
99128
100129watch (collapsed , (newCollapsed ) => {
101130 if (newCollapsed === true ) {
102- expandedPrimaryPanelSizePercentage = primaryPanelSizePercentage .value ;
103- primaryPanelSizePercentage .value = 0 ;
131+ expandedSizePercentage = sizePercentage .value ;
132+ sizePercentage .value = 0 ;
104133 }
105134 else {
106- primaryPanelSizePercentage .value = expandedPrimaryPanelSizePercentage ;
135+ sizePercentage .value = expandedSizePercentage ;
107136 }
108137});
109138
110- let cachedPrimaryPanelSizePixels = 0 ;
139+ let cachedSizePixels = 0 ;
111140
112141onMounted (() => {
113- cachedPrimaryPanelSizePixels = primaryPanelSizePixels .value ;
142+ cachedSizePixels = sizePixels .value ;
114143});
115144
145+ const { x : dividerX, y : dividerY } = useDraggable (dividerEl , { containerElement: panelEl });
146+
116147watch ([dividerX , dividerY ], ([newX , newY ]) => {
117148 if (props .disabled ) return ;
118149
@@ -122,12 +153,22 @@ watch([dividerX, dividerY], ([newX, newY]) => {
122153 newPositionInPixels = componentSize .value - newPositionInPixels ;
123154 }
124155
125- primaryPanelSizePercentage .value = clamp (pixelsToPercentage (componentSize .value , newPositionInPixels ), 0 , 100 );
156+ // if (props.collapsible && props.minSize !== undefined && props.collapseThreshold !== undefined) {
157+ // const threshold = props.minSize - (props.collapseThreshold ?? 0);
158+
159+ // console.log(threshold, newPositionInPixels);
160+
161+ // if (newPositionInPixels < threshold) {
162+ // collapsed.value = true;
163+ // }
164+ // }
165+
166+ sizePercentage .value = clamp (pixelsToPercentage (componentSize .value , newPositionInPixels ), 0 , 100 );
126167});
127168
128- watch (primaryPanelSizePixels , (newPixels , oldPixels ) => {
169+ watch (sizePixels , (newPixels , oldPixels ) => {
129170 if (newPixels === oldPixels ) return ;
130- cachedPrimaryPanelSizePixels = newPixels ;
171+ cachedSizePixels = newPixels ;
131172});
132173
133174useResizeObserver (panelEl , (entries ) => {
@@ -136,15 +177,15 @@ useResizeObserver(panelEl, (entries) => {
136177 const size = props .orientation === ' horizontal' ? width : height ;
137178
138179 if (props .primary ) {
139- primaryPanelSizePercentage .value = pixelsToPercentage (size , cachedPrimaryPanelSizePixels );
180+ sizePercentage .value = pixelsToPercentage (size , cachedSizePixels );
140181 }
141182});
142183
143184const handleKeydown = (event : KeyboardEvent ) => {
144185 if (props .disabled ) return ;
145186
146187 if ([' ArrowLeft' , ' ArrowRight' , ' ArrowUp' , ' ArrowDown' , ' Home' , ' End' , ' Enter' ].includes (event .key )) {
147- let newPosition = primaryPanelSizePercentage .value ;
188+ let newPosition = sizePercentage .value ;
148189
149190 const increment = (event .shiftKey ? 10 : 1 ) * (props .primary === ' end' ? - 1 : 1 );
150191
@@ -170,12 +211,12 @@ const handleKeydown = (event: KeyboardEvent) => {
170211 newPosition = props .primary === ' end' ? 0 : 100 ;
171212 }
172213
173- primaryPanelSizePercentage .value = clamp (newPosition , 0 , 100 );
214+ sizePercentage .value = clamp (newPosition , 0 , 100 );
174215 }
175216};
176217
177218const gridTemplate = computed (() => {
178- const primary = ` clamp(0%, clamp(${props . minSize } , ${primaryPanelSizePercentage .value }%, ${props . maxSize } ), calc(100% - ${dividerSize .value }px)) ` ;
219+ const primary = ` clamp(0%, clamp(${minSizePercentage . value }% , ${sizePercentage .value }%, ${maxSizePercentage . value }% ), calc(100% - ${dividerSize .value }px)) ` ;
179220 const secondary = ' auto' ;
180221
181222 if (! props .primary || props .primary === ' start' ) {
@@ -214,7 +255,7 @@ defineExpose({ collapse, expand, toggle });
214255 :class =" [{ disabled }, orientation]"
215256 :tabindex =" disabled ? undefined : 0"
216257 role =" separator"
217- :aria-valuenow =" primaryPanelSizePercentage "
258+ :aria-valuenow =" sizePercentage "
218259 aria-valuemin =" 0"
219260 aria-valuemax =" 100"
220261 aria-label =" Resize"
0 commit comments