
Security News
npm ‘is’ Package Hijacked in Expanding Supply Chain Attack
The ongoing npm phishing campaign escalates as attackers hijack the popular 'is' package, embedding malware in multiple versions.
@rafaelgm/vue-split-layout
Advanced tools
Vue 3 component for creating draggable and resizable split layouts (forked and updated)
Vue 3 component for creating draggable and resizable split layouts. Forked and updated from vue-hxs/vue-split-layout.
div
elements as panes.Pane
component for convenient header/content structure.npm install @rafaelgm/vue-split-layout
# or
yarn add @rafaelgm/vue-split-layout
1. Import Components and Styles:
// main.js or your component
import { createApp } from 'vue'
import App from './App.vue'
// Import library styles
import '@rafaelgm/vue-split-layout/style.css';
createApp(App).mount('#app')
2. Use in your Component:
<template>
<div class="app-container">
<header>
<button @click="editMode = !editMode">Toggle Edit ({{ editMode }})</button>
<button @click="resizeMode = !resizeMode">Toggle Resize ({{ resizeMode }})</button>
<button @click="saveLayout">Save Layout</button>
</header>
<Layout
class="main-layout"
:splits="layoutConfig"
:edit="editMode"
:resize="resizeMode"
@layout:update="handleLayoutUpdate"
@splitResize="handleSplitResize"
>
<!-- Child elements MUST have unique keys matching the IDs in layoutConfig -->
<!-- View/Pane 0 -->
<Pane title="Pane A (Key 0)" :key="0">
<div>Content for Pane A</div>
<input type="text" placeholder="Input A"/>
</Pane>
<!-- View/Pane 1 -->
<div :key="1" style="padding: 10px; background-color: #e0f0ff;">
<h2>Pane B (Key 1)</h2>
<p>This is a simple div acting as a pane.</p>
<textarea placeholder="Text Area B"></textarea>
<!-- Custom Drag Handle Example -->
<div style="padding: 5px; background: #ccc; cursor: grab; display: inline-block;" pane-drag-handle>
DRAG ME HERE
</div>
</div>
<!-- View/Pane 2 -->
<Pane title="Pane C (Key 2)" :key="2">
<p>Content for Pane C.</p>
<input type="text" placeholder="Input C"/>
</Pane>
</Layout>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue';
import { Layout, Pane } from '@rafaelgm/vue-split-layout';
const editMode = ref(true);
const resizeMode = ref(true);
// Define the layout structure
const layoutConfig = ref({
dir: 'horizontal', split: '30%', first: 0,
second: { dir: 'vertical', split: '50%', first: 1, second: 2 }
});
// Handler for layout updates
const handleLayoutUpdate = (newLayoutConfig) => {
console.log('Layout updated:', newLayoutConfig);
layoutConfig.value = newLayoutConfig; // Update local state to persist change
// localStorage.setItem('myLayout', JSON.stringify(newLayoutConfig));
};
// Handler for split resizing
const handleSplitResize = (event, nodeId, newSplitValue) => {
console.log(`Split ${nodeId} resized to ${newSplitValue}`);
// If saving layout on resize, might need debounce or save on mouseup
};
const saveLayout = () => {
console.log('Saving layout:', layoutConfig.value);
localStorage.setItem('myLayout', JSON.stringify(layoutConfig.value));
};
// Example: Load layout on mount
// onMounted(() => {
// const savedLayout = localStorage.getItem('myLayout');
// if (savedLayout) {
// layoutConfig.value = JSON.parse(savedLayout);
// }
// });
</script>
<style scoped>
/* ... (styles remain the same) ... */
.app-container { display: flex; flex-direction: column; height: 100vh; width: 100vw; overflow: hidden; }
header { padding: 10px; border-bottom: 1px solid #ccc; flex-shrink: 0; }
.main-layout { flex-grow: 1; position: relative; overflow: hidden; }
:deep(.pane .content div), :deep(.pane .content p), :deep(h2), :deep(p) { margin-bottom: 10px; }
:deep(input[type="text"]), :deep(textarea) { width: 90%; padding: 8px; margin-top: 5px; border: 1px solid #ccc; border-radius: 4px; box-sizing: border-box; }
:deep([pane-drag-handle]) { cursor: grab; }
:deep([pane-drag-handle]:active) { cursor: grabbing; }
</style>
3. Layout Configuration (splits
prop):
The splits
prop defines the layout structure. It's a recursive object where:
dir
('horizontal' or 'vertical'), first
, and second
defines a split.
split
: (Optional) A string percentage (e.g., '30%'
) defining the size of the first
child. Defaults to '50%'
.first
: The key
of the component/element for the first pane (left/top). Can be another split object for nesting.second
: The key
of the component/element for the second pane (right/bottom). Can be another split object for nesting.key
of a view/pane component/element.Important: The values used for first
and second
(when they are not nested split objects) must match the key
prop on the direct children passed into the <Layout>
component's default slot.
<Layout>
The main container component.
Props:
splits
: (Object, Default: {}
) The layout configuration object (see above). Required for defining the layout.edit
: (Boolean, Default: true
) Enables/disables dragging panes to rearrange the layout. When enabled, the entire pane area is draggable unless a pane-drag-handle
is specified within the pane.resize
: (Boolean, Default: true
) Enables/disables dragging splitters to resize panes.Events:
layout:complete
: Emitted after the layout has finished rendering or updating its structure (e.g., on mount, after prop changes, after drag completion).splitResize
: Emitted during a splitter handle drag and also on release.
(event: MouseEvent, nodeId: Number, newSplitValue: String)
- nodeId
is an internal ID of the split node, newSplitValue
is the new percentage string (e.g., '42.5%'
). Note: The layout's internal state is updated automatically. This event is informational.layout:update
: Emitted after a drag-and-drop operation successfully rearranges the layout.
(newLayoutConfig: Object)
- The new layout configuration object, reflecting the structure after the drop. You should use this payload to update your splits
prop if you want the change to persist.Slots:
default
: Place your view components or elements here. Each direct child must have a unique key
prop corresponding to the keys used in the splits
configuration.<Pane>
A helper component for structuring content within a layout pane. Provides a distinct header and content area.
Props:
title
: (String, Default: ''
) Text to display in the pane's header.Slots:
default
: Content to display below the header within the pane.To restrict dragging of a pane (when edit
mode is enabled) to a specific handle element inside that pane, add the pane-drag-handle
attribute to the desired handle element. If this attribute is not present on any element within a pane, the entire pane content area becomes the drag target.
<Layout :splits="{ first: 0, second: 1 }" :edit="true">
<div :key="0">Cannot drag me (no handle and not a default draggable area)</div>
<Pane title="Pane 1" :key="1">
Content...
<button pane-drag-handle>Drag Pane 1 ONLY from here</button>
More content...
</Pane>
</Layout>
The library requires its base styles. Import them once in your application:
import '@rafaelgm/vue-split-layout/style.css';
You can override styles using standard CSS techniques by targeting the generated classes (e.g., .layout-container
, .split
, .splitter
, .pane
, .header
, .content
). Use your browser's developer tools to inspect the structure.
touchstart
, touchmove
, touchend
) for mobile/tablet usability.splits
config instead of numeric keys (would require internal mapping).layout:update
after Resize: Currently, only drag operations emit layout:update
. Consider if resizing should also trigger this event (perhaps debounced on mouseup) to allow saving percentage changes easily.This project is a fork and update to Vue 3 of the original vue-split-layout
library created by Luis Figueiredo.
MIT License. See the LICENSE file for details.
FAQs
Vue 3 component for creating draggable and resizable split layouts (forked and updated)
We found that @rafaelgm/vue-split-layout demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
The ongoing npm phishing campaign escalates as attackers hijack the popular 'is' package, embedding malware in multiple versions.
Security News
A critical flaw in the popular npm form-data package could allow HTTP parameter pollution, affecting millions of projects until patched versions are adopted.
Security News
Bun 1.2.19 introduces isolated installs for smoother monorepo workflows, along with performance boosts, new tooling, and key compatibility fixes.