Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

svelte-dnd-action

Package Overview
Dependencies
Maintainers
1
Versions
129
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

svelte-dnd-action

*An awesome drag and drop library for Svelte 3 (not using the browser's built-in dnd, thanks god): Rich animations, nested containers, touch support and more *

  • 0.5.0
  • Source
  • npm
  • Socket score

Version published
Weekly downloads
30K
increased by1.24%
Maintainers
1
Weekly downloads
 
Created
Source

SVELTE DND ACTION Dependencies Known Vulnerabilities

This is an implementation of Trello-like drag and drop for Svelte using a custom action. See features list below.

dnd_demo2

Play with this example in the REPL.

Current Status

The library is working well as far as I can tell, but I have not used it in production yet. It is being actively maintained.

Features

  • Awesome drag and drop with minimal fuss
  • Supports horizontal, vertical or any other type of container (it doesn't care much about the shape)
  • Supports nested dnd-zones (draggable containers with other draggable elements inside)
  • Rich animations (can be opted out of)
  • Touch support
  • Define what can be dropped where (dnd-zones optionally have a "type")
  • Scroll dnd-zones and/or the window horizontally or vertically by placing the dragged element next to the edge
  • Supports advanced use-cases such as various flavours of copy-on-drag and custom drag handles (see examples below)
  • Performant and small footprint (no external dependencies, no fluff code)

Installation

Pre-requisites: svelte-3

yarn add -D svelte-dnd-action

or

npm install --save-dev svelte-dnd-action

Usage

    <div use:dndzone="{{items: myItems, ...otherOptions}}" on:consider={handler} on:finalize={handler}>
         {#each myItems as item(item.id)}
            <div>this is now a draggable div that can be dropped in other dnd zones</div>
         {/each}   
    </div>
Basic Example:
<script>
	import { flip } from 'svelte/animate';
	import { dndzone } from 'svelte-dnd-action';
    let items = [
    		{id: 1, name: "item1"},
    		{id: 2, name: "item2"},
    		{id: 3, name: "item3"},
    		{id: 4, name: "item4"}
    ]; 
    const flipDurationMs = 300;
	function handleDndConsider(e) {
		items = e.detail.items;
	}
	function handleDndFinalize(e) {
		items = e.detail.items;
	}
</script>

<style>
	section {
		width: 50%;
		padding: 0.3em;
		border: 1px solid black;
        /* this will allow the dragged element to scroll the list */
		overflow: scroll;
		height: 200px;
	}
	div {
		width: 50%;
		padding: 0.2em;
		border: 1px solid blue;
		margin: 0.15em 0;
	}
</style>
<section use:dndzone={{items, flipDurationMs}} on:consider={handleDndConsider} on:finalize={handleDndFinalize}>
	{#each items as item(item.id)}
		<div animate:flip="{{duration: flipDurationMs}}">
			{item.name}	
		</div>
	{/each}
</section>
Input:

An options-object with the following attributes:

NameTypeRequired?Default ValueDescription
itemsArrayYes. Each object in the array has to have an id property (key name can be overridden globally) with a unique value (within all dnd-zones of the same type)N/AThe data array that is used to produce the list with the draggable items (the same thing you run your #each block on)
flipDurationMsNumberNo0The same value you give the flip animation on the items (to make them animated as they "make space" for the dragged item). Set to zero or leave out if you don't want animations
typeStringNoInternaldnd-zones that share the same type can have elements from one dragged into another. By default, all dnd-zones have the same type
dragDisabledBooleanNofalseSetting it to true will make it impossible to drag elements out of the dnd-zone. You can change it at any time, and the zone will adjust on the fly
dropFromOthersDisabledBooleanNofalseSetting it to true will make it impossible to drop elements from other dnd-zones of the same type. Can be useful if you want to limit the max number of items for example. You can change it at any time, and the zone will adjust on the fly
dropTargetStyleObjectNo{outline: 'rgba(255, 255, 102, 0.7) solid 2px'}An object of styles to apply to the dnd-zone when items can be dragged in to it. Note: the styles override any inline styles applied to the dnd-zone. When the styles are removed, any original inline styles will be lost
transformDraggedElementFunctionNo() => {}A function that is invoked when the draggable element enters the dnd-zone or hover overs a new index in the current dnd-zone.
Signature:
function(element, data, index) {}
element: The dragged element.
data: The data of the item from the items array.
index: The index the dragged element will become in the new dnd-zone.

This allows you to override properties on the dragged element, such as innerHTML to change how it displays.
Output:

The action dispatches two custom events:

  • consider - dispatched whenever the dragged element needs to make room for itself in a new position in the items list and when it leaves. The host (your component) is expected to update the items list (you can keep a copy of the original list if you need to)
  • finalize - dispatched on the target and origin dnd-zones when the dragged element is dropped into position.

The expectation is the same - update the list of items. In both cases the payload (within e.detail) is the same: an object with two attributes: items and info.

  • items: contains the updated items list.
  • info: This one can be used to achieve very advanced custom behaviours (ex: copy on drag). In most cases, don't worry about it. It is an object with the following properties:
    • trigger: will be one of the exported list of TRIGGERS (Please import if you plan to use): [DRAG_STARTED, DRAGGED_ENTERED, DRAGGED_OVER_INDEX, DRAGGED_LEFT, DROPPED_INTO_ZONE, DROPPED_INTO_ANOTHER, DROPPED_OUTSIDE_OF_ANY]
    • id: the item id of the dragged element

You have to listen for both events and update the list of items in order for this library to work correctly.

For advanced usecases you might also need to import SHADOW_ITEM_MARKER_PROPERTY_NAME, which marks the place holder element that is temporarily added to the list the dragged element hovers over. I haven't seen a usecase that required it yet, but you might be the first :)

Rules/ assumptions to keep in mind

  • Only one element can be dragged in any given time
  • The data that represents items within dnd-zones of the same type is expected to have the same shape (as in a data object that represents an item in one container can be added to another without conversion).
  • Item ids (#each keys) are unique in all dnd containers of the same type. EVERY DRAGGABLE ITEM (passed in through items) MUST HAVE AN ID PROPERTY CALLED id. You can override it globally if you'd like to use a different key (see below)
  • The items in the list that is passed-in are in the same order as the children of the container (i.e the items are rendered in an #each block).
  • The host component should refresh the items that are passed in to the custom-action when receiving consider and finalize events.
  • FYI, the library assumes it is okay to add a temporary item to the items list in any of the dnd-zones while an element is dragged around.
  • If you want dragged items to be able to scroll the container, make sure the scroll-container (the element with overflow:scroll) is the dnd-zone (the element decorated with this custom action)
  • Svelte's built-in transitions might not play nice with this library. Luckily, it is an easy issue to work around. There are examples below.

Overriding the item id key name

Sometimes it is useful to use a different key for your items instead of id, for example when working with PouchDB which expects _id. It can save some annoying conversions back and forth. In such cases you can import and call overrideItemIdKeyNameBeforeInitialisingDndZones. This function accepts one parameter of type string which is the new id key name. For example:

import {overrideItemIdKeyNameBeforeInitialisingDndZones} from 'svelte-dnd-action';
overrideItemIdKeyNameBeforeInitialisingDndZones('_id');

It applies globally (as in, all of your items everywhere are expected to have a unique identifier with this name). It can only be called when there are no rendered dndzones (I recommend calling it within the top-level

Examples

Contributing contributions welcome

There is still quite a lot to do. If you'd like to contribute please get in touch (raise an issue or comment on an existing one). Ideally, be specific about which area you'd like to help with. Thank you for reading :)

Keywords

FAQs

Package last updated on 15 Sep 2020

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

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc