Vue3 highly customizable component for resizing nested content
npm install vue3-resize-bounding!Version 
Vue3 Resize Bounding is a simple, highly customizable Vue3 component that allows you to intuitively resize nested content using draggable border panels.
| Demo | Documentation | Example (Interactive Grid) | Repository |
---
Installation
``bash`
npm i vue3-resize-boundingor
yarn add vue3-resize-bounding
Usage
`html
:height="container.height"
:min-width="240"
:max-width="480"
:min-height="120"
:directions="'hv'"
:options="{
knob: {
show: true
}
}"
:style="{ border: '1px solid gray' }"
@update:width="(width) => (container.width = width)"
@update:height="(height) => (container.height = height)"
>
My Container
`
Register the component globally:
`ts
// @filename: main.ts
import App from "@/App";
import { createApp } from "vue";
import ResizeBounding from "vue3-resize-bounding";
const app = createApp(App);
app.use(ResizeBounding, { name: "resize-bounding" });
app.mount("#app");
`
| property | type | default value | description | |
|---|---|---|---|---|
directions | PaneDirections | '' | ||
The literal 'hv' specifies which boundaries should beenabled for resizing. The order of the characters is not significant. 'hv' is equivalent to 'tblr' | value | description | ||
| 't' | top | |||
| 'r' | right | |||
| 'b' | bottom | |||
| 'l' | left | |||
| 'h' | horizontal alias, equivalent to 'lr' | |||
| 'v' | vertical alias, equivalent to 'tb' | |||
disabled | boolean | false | Disable border selection | |
width | number | undefined | undefined | Set current container width | |
minWidth | number | undefined | 0 | Minimum value of the width resizing range | |
maxWidth | number | undefined | undefined | Maximum resizing range value. undefiendEquivalent to Number.POSITIVE_INFINITY | |
height | number | undefined | undefined | Set current container height | |
minHeight | number | undefined | 0 | Minimum height resizing range value | |
maxHeight | number | undefined | undefined | The maximum value of the height resizing range. Equivalent to Number.POSITIVE_INFINITY | |
| additional options | ||||
| property | type | value | ||
options | Partial <Options> | |||
options.prefix | ||||
| description | Overrides the default class names prefix | |||
| type | string | |||
| default value | 'resize-bounding-' | |||
options.width | ||||
| description | !Legacy. Set width of splitter (both splitterWidthNormal and splitterWidthActive props) in pixels | |||
| type | number | |||
| default value | 4 | |||
options.splitterWidthNormal | ||||
| description | Set width of splitter in normal state in pixels (splitterWidthActive will be equal to splitterWidthNormal if splitterWidthActive prop is not set) | |||
| type | number | |||
| default value | undefined | |||
options.splitterWidthActive | ||||
| description | Set width of splitter in active state. If splitterWidthNormal and splitterWidthActive are different then the splitter width will be animated by default. To change the animation parameters or disable the animation use :styles props | |||
| type | number | |||
| default value | undefined | |||
options.activeAreaWidth | ||||
| description | Sets the width of the active space within which the border (splitter) selection will be activated | |||
| type | number | undefined | |||
| default value | undefined | |||
options.position | ||||
| description | Determines the positioning of the splitter relative to the container boundaries | |||
| type | SplitterPosition | |||
| default value | 'central' | |||
| values: | ||||
'central' | ||||
'internal' | ||||
'external' | ||||
options.touchActions | ||||
| description | Enable touch actions | |||
| type | boolean | |||
| default value | true | |||
options.addStateClasses | ||||
| description | Adds state classes to a pane element (.normal, .selected, .pressed) | |||
| type | boolean | |||
| default value | false | |||
options.knob.show | ||||
| description | Render the knob | |||
| type | boolean | |||
| default value | false | |||
options.knob.normalHidden | ||||
| description | Render the knob only when focusing or pressing on the splitter | |||
| type | boolean | |||
| default value | false | |||
options.cursor.vertical | ||||
| description | Cursor style for horizontal bounding during Focus and Resize | |||
| type | CSSStyleDeclaration["cursor"] | |||
| default value | 'row-resize' | |||
options.cursor.horizontal | ||||
| description | Cursor style for vertical bounding during Focus and Resize | |||
| type | CSSStyleDeclaration["cursor"] | |||
| default value | 'col-resize' | |||
styles | IStyles | |||
styles.container | ||||
| description | Describes custom styles the container element. container is theelement directly in which the user content is located, forwarded through <slot/>. | |||
| type | IStyle | |||
styles.pane | ||||
| description | Describes custom styles the pane element. The pane element is acontainer responsible for positioning the splitter. Therefore, treat this component as an empty container, since you may only need to style it in very rare cases. >Pane receives normal, focused andpressed classes | |||
| type | IStyle | |||
styles.splitter | ||||
| description | Describes custom styles the splitter element. splitter is an elementthat displays a selected border line | |||
| type | IStyle | |||
styles.splitterContainer | ||||
| description | Describes custom styles the splitterContainer element. splitterContainer is empty element used to rotating the knob | |||
| type | IStyle | |||
styles.knob | ||||
| description | Describes custom styles the knob element. Knobis a decorative elementlocated on top of the splitter. Convenient to use with touch actions, as it increases the touch area of the splitter by its own size and has a positive effect on user experience | |||
| type | IStyle | |||
| property | type | description | |
|---|---|---|---|
@update:width | (width: number) => void | Emitted every time a container width is updated | |
@update:height | (height: number) => void | Emitted every time a container height is updated | |
@drag:start | (direction: PaneDirections) => void | Emitted when resizing starts. The callback function accepts an argument of current direction | |
@drag:move | (direction: PaneDirections) => void | Emitted when resizing. The callback function accepts an argument of current direction | |
@drag:end | (direction: PaneDirections) => void | Emitted when resizing ends. The callback function accepts an argument of current direction | |
@focus | ({state: boolean, direction: PaneDirections}) => void | Emitted when focusing on a specific boundary pane | |
| name | description |
|---|---|
default | Content |
knob | Knob inner content (icon) |
---
Overriding:
`html
knob: {
show: true,
},
}}>
`
> Touch Area
> To increase the touch area, set the value to options.activeAreaWidth or use increased height of the knob
> Default value is undefined
States styling:
By default, to style the active state (both .focused or .pressed), the .actvie class is used;
So the style definition looks like this:
`ts.${globalClassNames(prefix).pane}.active &
const styles = {
// Active (focused/pressed) state:
splitter: {
[]: {.${globalClassNames(prefix).pane}.active &
background: "cornflowerblue",
},
},
knob: {
[]: {`
background: "cornflowerblue",
},
},
};
To separately configure the focused state or the pressed state of a splitter/knob, use the included :options="{ addStateClasses: true }" flag and the generated state classes:
`ts.${prefix}-pane.focused &
const styles = {
splitter: {
// Focused state:
[]: {.${prefix}-pane.pressed &
backgroundColor: "blue",
},
// Pressed state:
[]: {
backgroundColor: "red",
},
},
knob: {
// Focused state:
[.${prefix}-pane.focused &]: {.${prefix}-pane.pressed &
backgroundColor: "blue",
},
// Pressed state:
[]: {`
backgroundColor: "red",
},
},
};
---
Using css (preprocessors)
Use the included :options="{ addStateClasses: true }" flag to style the .selected and .pressed states separately.
`html
:height="container.height"
:min-width="240"
:max-width="480"
:min-height="120"
:directions="'hv'"
:options="{ addStateClasses: true, knob: { show: true } }"
:style="{ border: '1px solid gray' }"
@update:width="(width) => (container.width = width)"
@update:height="(height) => (container.height = height)"
>
My Container
`
---
`html
``
---
Licensing is in accordance with the original.
Mikhail Grebennikov - yamogoo