You're Invited:Meet the Socket Team at BlackHat and DEF CON in Las Vegas, Aug 4-6.RSVP
Socket
Book a DemoInstallSign in
Socket

@rafaelgm/vue-split-layout

Package Overview
Dependencies
Maintainers
1
Versions
1
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@rafaelgm/vue-split-layout

Vue 3 component for creating draggable and resizable split layouts (forked and updated)

1.0.0
latest
Source
npmnpm
Version published
Maintainers
1
Created
Source

@rafaelgm/vue-split-layout (Vue 3)

Vue 3 component for creating draggable and resizable split layouts. Forked and updated from vue-hxs/vue-split-layout.

Demo npm GitHub repo

Features

  • Create horizontal or vertical splits.
  • Nest splits for complex layouts.
  • Drag panes to rearrange the layout (edit mode).
  • Drag splitters to resize panes (resize mode).
  • Preserves component state within panes during layout changes.
  • Supports standard components or simple div elements as panes.
  • Optional Pane component for convenient header/content structure.
  • Custom drag handles within panes.
  • Built with Vue 3 Composition API.

Installation

npm install @rafaelgm/vue-split-layout
# or
yarn add @rafaelgm/vue-split-layout

Usage

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:

  • An object with 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.
  • A primitive value (Number or String) represents the 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.

Components

<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.
    • Payload: (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.
    • Payload: (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.

Custom Drag Handle

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>

Styling

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.

TODO / Future Ideas

  • Touch Support: Add touch event listeners (touchstart, touchmove, touchend) for mobile/tablet usability.
  • Accessibility: Improve WAI-ARIA attributes for draggable/resizable elements.
  • Named Views: Potentially allow using string aliases in the splits config instead of numeric keys (would require internal mapping).
  • Draggable Views Menu: Allow adding/removing views from a separate menu (feature enhancement).
  • Emit 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.

Acknowledgements

This project is a fork and update to Vue 3 of the original vue-split-layout library created by Luis Figueiredo.

License

MIT License. See the LICENSE file for details.

Keywords

vue

FAQs

Package last updated on 28 Apr 2025

Did you know?

Socket

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.

Install

Related posts