grab cursor

A tinydata-first library
for modern apps

  • Data-first

    No direct DOM manipulations.

  • Lightweight

    ~4kb min-gzip. No dependencies.

  • Modern

    Leverages modern web APIs.

  • Plugins

    Multi-drag, animations, and more.

  • TypeScript

    First-class TypeScript support.

  • Production-ready

    Used on FormKit Pro inputs.

AI-Generated forms in seconds.

KickStart your next FormKit form in seconds. Generate from a prompt, image, or text attachment. Copy & paste as Vue components or FormKit schema.

Introduction

FormKit’s Drag and Drop is a small library for adding drag and drop functionality to your app. It’s simple, flexible, framework agnostic, and clocks in at only ~5kb gzipped. Drag and Drop works with React, Solid, Vue, Svelte, or any JavaScript framework. This library differs from others in the way the drag and drop operations are performed. Rather than moving elements around the DOM manually, Drag and Drop updates the reactive data model used by the provided render function.

Getting Started

Install

Drag and Drop is published as @formkit/drag-and-drop on npm. Click to copy the install command for your package manager of choice:

Usage

Drag and drop ships two main functions: dragAndDrop and useDragAndDrop. These can be imported for your framework of choice by using the subpath import @formkit/drag-and-drop/{react/vue/solid}. A native JavaScript version of the dragAndDrop function is also available at @formkit/drag-and-drop.

Whichever method you choose, the core concept remains the same: FormKit's Drag and Drop accepts two main arguments — the parent element containing the draggable items and the data that those items represent.

useDragAndDrop

The useDragAndDrop hook is the most convenient way to add Drag and Drop to your app and is available for React, Vue, and Solid. Call this function with an initial array of values and the configuration options. It returns an array of values containing a a template ref, a reactive set of values (and a setter in the case of React), as well as a function to update the parent's config. The template ref should be assigned to the parent DOM element of the items you wish to make draggable. The reactive array of values should be used in your template to render the draggable elements.

// Example parent configuration object:
const config = { sortable: false }

// React:
const [parentRef, values, setValues, updateConfig] = useDragAndDrop(
['Item 1', 'Item2', 'Item3'],
config
)

// Vue:
const [parentRef, values, updateConfig] = useDragAndDrop(
['Item 1', 'Item2', 'Item3'],
config
)

dragAndDrop

The dragAndDrop hook allows you to define your own ref and list state. This is useful if you need to integrate with a pre-existing app without changing your component structure.

// Example parent configuration object:
const config = { sortable: false }

// React:
dragAndDrop({
parent: parentRef,
state: [values, setValues],
config
})

// Vue:
dragAndDrop({
parent: parentRef,
values: valueRef,
config
})

// Vanilla JS: (import from core, not subpath)
dragAndDrop({
parent: HTMLElement,
getValues: () => {

// Return array of values
},
setValues: (newValues) =>
// Do something with updated values

},
config
})

Core Features

Sortability

Using useDragAndDrop or dragAndDrop automatically makes a lists sortable. Dragging items within your list will automatically change your list’s state to reflect the new order (which in turn allows the framework to re-render to the correct order):

  • React
  • Vue
  • Solid
  • Native
import React from "react";
import { function useDragAndDrop<E extends HTMLElement, T = unknown>(list: T[], options?: Partial<ParentConfig<T>>): [React.RefObject<E>, T[], React.Dispatch<React.SetStateAction<T[]>>, (config: Partial<ParentConfig<...>>) => void]
Hook for adding drag and drop/sortable support to a list of items.
@paramlist - Initial list of data.@paramoptions - The drag and drop configuration.@returns
useDragAndDrop
} from "@formkit/drag-and-drop/react";
export function function myComponent(): React.JSX.ElementmyComponent() { const [const parent: React.RefObject<HTMLUListElement>parent, const tapes: string[]tapes] = useDragAndDrop<HTMLUListElement, string>(list: string[], options?: Partial<ParentConfig<string>> | undefined): [React.RefObject<HTMLUListElement>, string[], React.Dispatch<...>, (config: Partial<...>) => void]
Hook for adding drag and drop/sortable support to a list of items.
@paramlist - Initial list of data.@paramoptions - The drag and drop configuration.@returns
useDragAndDrop
<HTMLUListElement, string>([
"Depeche Mode", "Duran Duran", "Pet Shop Boys", "Kraftwerk", "Tears for Fears", "Spandau Ballet", ]); return ( <JSX.IntrinsicElements.ul: React.DetailedHTMLProps<React.HTMLAttributes<HTMLUListElement>, HTMLUListElement>ul React.RefAttributes<HTMLUListElement>.ref?: React.LegacyRef<HTMLUListElement> | undefined
Allows getting a ref to the component instance. Once the component unmounts, React will set `ref.current` to `null` (or call the ref with `null` if you passed a callback ref).
@see{@link https://react.dev/learn/referencing-values-with-refs#refs-and-the-dom React Docs}
ref
={const parent: React.RefObject<HTMLUListElement>parent}>
{const tapes: string[]tapes.Array<string>.map<React.JSX.Element>(callbackfn: (value: string, index: number, array: string[]) => React.JSX.Element, thisArg?: any): React.JSX.Element[]
Calls a defined callback function on each element of an array, and returns an array that contains the results.
@paramcallbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.@paramthisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
map
((tape: stringtape) => (
<JSX.IntrinsicElements.li: React.DetailedHTMLProps<React.LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>li React.HTMLAttributes<HTMLLIElement>.className?: string | undefinedclassName="cassette" data-label: stringdata-label={tape: stringtape} React.Attributes.key?: React.Key | null | undefinedkey={tape: stringtape}> {tape: stringtape} </JSX.IntrinsicElements.li: React.DetailedHTMLProps<React.LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>li> ))} </JSX.IntrinsicElements.ul: React.DetailedHTMLProps<React.HTMLAttributes<HTMLUListElement>, HTMLUListElement>ul> ); }
<script setup lang="ts">
import { function useDragAndDrop<T>(initialValues: T[], options?: Partial<VueParentConfig<T>>): [Ref<HTMLElement | undefined>, Ref<T[]>, (config: Partial<VueParentConfig<T>>) => void]
Creates a new instance of drag and drop and returns the parent element and a ref of the values to use in your template.
@paraminitialValues - The initial values of the parent element.@returnsThe parent element and values for drag and drop.
useDragAndDrop
} from "@formkit/drag-and-drop/vue";
const [const parent: Ref<HTMLElement | undefined, HTMLElement | undefined>parent, const tapes: Ref<string[], string[]>tapes] = useDragAndDrop<string>(initialValues: string[], options?: Partial<Partial<ParentConfig<string>>> | undefined): [Ref<HTMLElement | undefined, HTMLElement | undefined>, Ref<...>, (config: Partial<...>) => void]
Creates a new instance of drag and drop and returns the parent element and a ref of the values to use in your template.
@paraminitialValues - The initial values of the parent element.@returnsThe parent element and values for drag and drop.
useDragAndDrop
([
"Depeche Mode", "Duran Duran", "Pet Shop Boys", "Kraftwerk", "Tears for Fears", "Spandau Ballet", ]); </script> <template> <ul: HTMLAttributes & ReservedPropsul ref?: VNodeRef | undefinedref="parent: HTMLElement | undefinedparent"> <li: LiHTMLAttributes & ReservedPropsli v-for="const tape: stringtape in tapes: string[]tapes" key?: PropertyKey | undefined:key?: PropertyKey | undefinedkey="const tape: stringtape" HTMLAttributes.class?: anyclass="cassette"> {{ const tape: stringtape }} </li: LiHTMLAttributes & ReservedPropsli> </ul: HTMLAttributes & ReservedPropsul> </template>
/** @jsxImportSource solid-js */
import { 
function For<T extends readonly any[], U extends JSX.Element>(props: {
    each: T | undefined | null | false;
    fallback?: JSX.Element;
    children: (item: T[number], index: Accessor<number>) => U;
}): JSX.Element
Creates a list elements from a list it receives a map function as its child that receives a list element and an accessor with the index and returns a JSX-Element; if the list is empty, an optional fallback is returned: ```typescript <For each={items} fallback={<div>No items</div>}> {(item, index) => <div data-index={index()}>{item}</div>} </For> ``` If you have a list with fixed indices and changing values, consider using `<Index>` instead.
@descriptionhttps://docs.solidjs.com/reference/components/for
For
, type JSX } from "solid-js";
import { function useDragAndDrop<E extends HTMLElement, T = unknown>(initValues: T[], options?: Partial<ParentConfig<T>>): [Setter<E | null>, Accessor<Store<T[]>>, ReturnType<typeof createStore>[1], (config?: Partial<ParentConfig<T>>) => void]
Hook for adding drag and drop/sortable support to a list of items.
@paraminitValues - Initial list of data.@paramoptions - The drag and drop configuration.@returns
useDragAndDrop
} from "@formkit/drag-and-drop/solid";
export const const MyComponent: () => JSX.ElementMyComponent = (): JSX.type JSX.Element = number | boolean | Node | JSX.ArrayElement | (string & {}) | null | undefinedElement => { const [const parent: Setter<HTMLUListElement | null>parent, const tapes: Accessor<string[]>tapes] = useDragAndDrop<HTMLUListElement, string>(initValues: string[], options?: Partial<ParentConfig<string>> | undefined): [Setter<HTMLUListElement | null>, Accessor<...>, SetStoreFunction<...>, (config?: Partial<...> | undefined) => void]
Hook for adding drag and drop/sortable support to a list of items.
@paraminitValues - Initial list of data.@paramoptions - The drag and drop configuration.@returns
useDragAndDrop
<HTMLUListElement, string>([
"Depeche Mode", "Duran Duran", "Pet Shop Boys", "Kraftwerk", "Tears for Fears", "Spandau Ballet", ]); return ( <JSX.HTMLElementTags.ul: JSX.HTMLAttributes<HTMLUListElement>ul ref?: HTMLUListElement | ((el: HTMLUListElement) => void) | undefinedref={const parent: Setter<HTMLUListElement | null>parent}> <
function For<T extends readonly any[], U extends JSX.Element>(props: {
    each: T | undefined | null | false;
    fallback?: JSX.Element;
    children: (item: T[number], index: Accessor<number>) => U;
}): JSX.Element
Creates a list elements from a list it receives a map function as its child that receives a list element and an accessor with the index and returns a JSX-Element; if the list is empty, an optional fallback is returned: ```typescript <For each={items} fallback={<div>No items</div>}> {(item, index) => <div data-index={index()}>{item}</div>} </For> ``` If you have a list with fixed indices and changing values, consider using `<Index>` instead.
@descriptionhttps://docs.solidjs.com/reference/components/for
For
each: false | string[] | null | undefinedeach={const tapes: () => string[]tapes()}>
{(tape: stringtape) => ( <JSX.HTMLElementTags.li: JSX.LiHTMLAttributes<HTMLLIElement>li JSX.HTMLAttributes<HTMLLIElement>.class?: string | undefinedclass="cassette" data-label: stringdata-label={tape: stringtape}> {tape: stringtape} </JSX.HTMLElementTags.li: JSX.LiHTMLAttributes<HTMLLIElement>li> )} </
function For<T extends readonly any[], U extends JSX.Element>(props: {
    each: T | undefined | null | false;
    fallback?: JSX.Element;
    children: (item: T[number], index: Accessor<number>) => U;
}): JSX.Element
Creates a list elements from a list it receives a map function as its child that receives a list element and an accessor with the index and returns a JSX-Element; if the list is empty, an optional fallback is returned: ```typescript <For each={items} fallback={<div>No items</div>}> {(item, index) => <div data-index={index()}>{item}</div>} </For> ``` If you have a list with fixed indices and changing values, consider using `<Index>` instead.
@descriptionhttps://docs.solidjs.com/reference/components/for
For
>
</JSX.HTMLElementTags.ul: JSX.HTMLAttributes<HTMLUListElement>ul> ); };
import { const reactive: <T extends DataSource>(data: T, state?: ReactiveProxyState) => ReactiveProxy<T>
reactive is an alias for r
reactive
, const html: (strings: TemplateStringsArray, ...expSlots: any[]) => ArrowTemplate
html is an alias for t
html
} from "@arrow-js/core";
import { function dragAndDrop<T>({ parent, getValues, setValues, config, }: DragAndDrop<T>): void
Initializes the drag and drop functionality for a given parent.
@paramdragAndDrop - The drag and drop configuration.@returnsvoid
dragAndDrop
} from "@formkit/drag-and-drop";
const
const state: ReactiveProxy<{
    tapes: string[];
}>
state
=
reactive<{
    tapes: string[];
}>(data: {
    tapes: string[];
}, state?: ReactiveProxyState): ReactiveProxy<{
    tapes: string[];
}>
Given a data object, often an object literal, return a proxy of that object with mutation observers for each property.
@paramdata@returnsReactiveProxy
reactive
({
tapes: string[]tapes: [ "Depeche Mode", "Duran Duran", "Pet Shop Boys", "Kraftwerk", "Tears for Fears", "Spandau Ballet", ], }); const html: (strings: TemplateStringsArray, ...expSlots: any[]) => ArrowTemplate
html is an alias for t
html
`
<ul id="cassettes"> ${() =>
const state: ReactiveProxy<{
    tapes: string[];
}>
state
.tapes: ReactiveProxy<string[]>tapes.Array<string>.map<void>(callbackfn: (value: string, index: number, array: string[]) => void, thisArg?: any): void[]
Calls a defined callback function on each element of an array, and returns an array that contains the results.
@paramcallbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.@paramthisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
map
((tape: stringtape) =>
const html: (strings: TemplateStringsArray, ...expSlots: any[]) => ArrowTemplate
html is an alias for t
html
`<li class="cassette" data-label="${tape: stringtape}">${tape: stringtape}</li>`.ArrowTemplate.key: (key: ArrowTemplateKey) => void
Adds a key to this template to identify it as a unique instance.
@paramkey - A unique key that identifies this template instance (not index).@returns
key
(tape: stringtape)
)} </ul> `(var document: Document
[MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/document)
document
.Document.getElementById(elementId: string): HTMLElement | null
Returns a reference to the first object with the specified value of the ID attribute.
@paramelementId String that specifies the ID value.
getElementById
("app")!);
dragAndDrop<string>({ parent, getValues, setValues, config, }: DragAndDrop<string>): void
Initializes the drag and drop functionality for a given parent.
@paramdragAndDrop - The drag and drop configuration.@returnsvoid
dragAndDrop
<string>({
DragAndDrop<string>.parent: HTMLElement
The parent element that will contain the draggable nodes.
parent
: var document: Document
[MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/document)
document
.Document.getElementById(elementId: string): HTMLElement | null
Returns a reference to the first object with the specified value of the ID attribute.
@paramelementId String that specifies the ID value.
getElementById
("cassettes")!,
DragAndDrop<string>.getValues: (parent: HTMLElement) => string[]
A function that returns the values assigned to the parent.
getValues
: () =>
const state: ReactiveProxy<{
    tapes: string[];
}>
state
.tapes: ReactiveProxy<string[]>tapes,
DragAndDrop<string>.setValues: (values: string[], parent: HTMLElement) => void
A function that sets the values assigned to the parent.
setValues
: (newValues: string[]newValues) => {
const state: ReactiveProxy<{
    tapes: string[];
}>
state
.tapes: ReactiveProxy<string[]>tapes = reactive<string[]>(data: string[], state?: ReactiveProxyState): ReactiveProxy<string[]>
Given a data object, often an object literal, return a proxy of that object with mutation observers for each property.
@paramdata@returnsReactiveProxy
reactive
(newValues: string[]newValues);
}, });
FormKit Office Jams
  • Depeche Mode
    Cassette Tape
  • Duran Duran
    Cassette Tape
  • Pet Shop Boys
    Cassette Tape
  • Kraftwerk
    Cassette Tape
  • Tears for Fears
    Cassette Tape
  • Spandau Ballet
    Cassette Tape
["Depeche Mode","Duran Duran","Pet Shop Boys","Kraftwerk","Tears for Fears","Spandau Ballet"]

Draggable

For drag-and-drop to function correctly, the length of array of values provided must be equivalent to the number of immediate children to the parent element. If they are not, a console warning will appear: The number of draggable items in the parent does not match the number of values, which may lead to unexpected behavior." The most common cause of this is when the parent element has an immediate child that is not meant to be draggable. In this case, the configuration property draggable can be set to a callback function that lets you determine whether or not a given element should be draggable:

  • React
  • Vue
  • Solid
  • Native
import React from "react";
import { function useDragAndDrop<E extends HTMLElement, T = unknown>(list: T[], options?: Partial<ParentConfig<T>>): [React.RefObject<E>, T[], React.Dispatch<React.SetStateAction<T[]>>, (config: Partial<ParentConfig<...>>) => void]
Hook for adding drag and drop/sortable support to a list of items.
@paramlist - Initial list of data.@paramoptions - The drag and drop configuration.@returns
useDragAndDrop
} from "@formkit/drag-and-drop/react";
export function function myComponent(): React.JSX.ElementmyComponent() { const [const parent: React.RefObject<HTMLUListElement>parent, const tapes: string[]tapes] = useDragAndDrop<HTMLUListElement, string>(list: string[], options?: Partial<ParentConfig<string>> | undefined): [React.RefObject<HTMLUListElement>, string[], React.Dispatch<...>, (config: Partial<...>) => void]
Hook for adding drag and drop/sortable support to a list of items.
@paramlist - Initial list of data.@paramoptions - The drag and drop configuration.@returns
useDragAndDrop
<HTMLUListElement, string>(
[ "Depeche Mode", "Duran Duran", "Pet Shop Boys", "Kraftwerk", "Tears for Fears", "Spandau Ballet", ], { draggable?: ((child: HTMLElement) => boolean) | undefined
A function that returns whether a given node is draggable.
draggable
: (el: HTMLElementel) => {
return el: HTMLElementel.Element.id: string
Returns the value of element's id content attribute. Can be set to change it. [MDN Reference](https://developer.mozilla.org/docs/Web/API/Element/id)
id
!== "no-drag";
}, } ); return ( <JSX.IntrinsicElements.ul: React.DetailedHTMLProps<React.HTMLAttributes<HTMLUListElement>, HTMLUListElement>ul React.RefAttributes<HTMLUListElement>.ref?: React.LegacyRef<HTMLUListElement> | undefined
Allows getting a ref to the component instance. Once the component unmounts, React will set `ref.current` to `null` (or call the ref with `null` if you passed a callback ref).
@see{@link https://react.dev/learn/referencing-values-with-refs#refs-and-the-dom React Docs}
ref
={const parent: React.RefObject<HTMLUListElement>parent}>
{const tapes: string[]tapes.Array<string>.map<React.JSX.Element>(callbackfn: (value: string, index: number, array: string[]) => React.JSX.Element, thisArg?: any): React.JSX.Element[]
Calls a defined callback function on each element of an array, and returns an array that contains the results.
@paramcallbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.@paramthisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
map
((tape: stringtape) => (
<JSX.IntrinsicElements.li: React.DetailedHTMLProps<React.LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>li React.HTMLAttributes<HTMLLIElement>.className?: string | undefinedclassName="cassette" data-label: stringdata-label={tape: stringtape} React.Attributes.key?: React.Key | null | undefinedkey={tape: stringtape}> {tape: stringtape} </JSX.IntrinsicElements.li: React.DetailedHTMLProps<React.LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>li> ))} <JSX.IntrinsicElements.div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>div React.HTMLAttributes<HTMLDivElement>.id?: string | undefinedid="no-drag">I am NOT draggable</JSX.IntrinsicElements.div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>div> </JSX.IntrinsicElements.ul: React.DetailedHTMLProps<React.HTMLAttributes<HTMLUListElement>, HTMLUListElement>ul> ); }
<script setup lang="ts">
import { function useDragAndDrop<T>(initialValues: T[], options?: Partial<VueParentConfig<T>>): [Ref<HTMLElement | undefined>, Ref<T[]>, (config: Partial<VueParentConfig<T>>) => void]
Creates a new instance of drag and drop and returns the parent element and a ref of the values to use in your template.
@paraminitialValues - The initial values of the parent element.@returnsThe parent element and values for drag and drop.
useDragAndDrop
} from "@formkit/drag-and-drop/vue";
const [const parent: Ref<HTMLElement | undefined, HTMLElement | undefined>parent, const tapes: Ref<string[], string[]>tapes] = useDragAndDrop<string>(initialValues: string[], options?: Partial<Partial<ParentConfig<string>>> | undefined): [Ref<HTMLElement | undefined, HTMLElement | undefined>, Ref<...>, (config: Partial<...>) => void]
Creates a new instance of drag and drop and returns the parent element and a ref of the values to use in your template.
@paraminitialValues - The initial values of the parent element.@returnsThe parent element and values for drag and drop.
useDragAndDrop
(
[ "Depeche Mode", "Duran Duran", "Pet Shop Boys", "Kraftwerk", "Tears for Fears", "Spandau Ballet", ], { draggable?: ((child: HTMLElement) => boolean) | undefined
A function that returns whether a given node is draggable.
draggable
: (el: HTMLElementel) => {
return el: HTMLElementel.Element.id: string
Returns the value of element's id content attribute. Can be set to change it. [MDN Reference](https://developer.mozilla.org/docs/Web/API/Element/id)
id
!== "no-drag";
}, } ); </script> <template> <ul: HTMLAttributes & ReservedPropsul ref?: VNodeRef | undefinedref="parent: HTMLElement | undefinedparent"> <li: LiHTMLAttributes & ReservedPropsli v-for="const tape: stringtape in tapes: string[]tapes" key?: PropertyKey | undefined:key?: PropertyKey | undefinedkey="const tape: stringtape" HTMLAttributes.class?: anyclass="cassette"> {{ const tape: stringtape }} </li: LiHTMLAttributes & ReservedPropsli> <li: LiHTMLAttributes & ReservedPropsli HTMLAttributes.id?: string | undefinedid="no-drag">I am NOT draggable</li: LiHTMLAttributes & ReservedPropsli> </ul: HTMLAttributes & ReservedPropsul> </template>
/** @jsxImportSource solid-js */
import { 
function For<T extends readonly any[], U extends JSX.Element>(props: {
    each: T | undefined | null | false;
    fallback?: JSX.Element;
    children: (item: T[number], index: Accessor<number>) => U;
}): JSX.Element
Creates a list elements from a list it receives a map function as its child that receives a list element and an accessor with the index and returns a JSX-Element; if the list is empty, an optional fallback is returned: ```typescript <For each={items} fallback={<div>No items</div>}> {(item, index) => <div data-index={index()}>{item}</div>} </For> ``` If you have a list with fixed indices and changing values, consider using `<Index>` instead.
@descriptionhttps://docs.solidjs.com/reference/components/for
For
} from "solid-js";
import { function useDragAndDrop<E extends HTMLElement, T = unknown>(initValues: T[], options?: Partial<ParentConfig<T>>): [Setter<E | null>, Accessor<Store<T[]>>, ReturnType<typeof createStore>[1], (config?: Partial<ParentConfig<T>>) => void]
Hook for adding drag and drop/sortable support to a list of items.
@paraminitValues - Initial list of data.@paramoptions - The drag and drop configuration.@returns
useDragAndDrop
} from "@formkit/drag-and-drop/solid";
export function function MyComponent(): JSX.ElementMyComponent() { const [const parent: Setter<HTMLUListElement | null>parent, const tapes: Accessor<string[]>tapes] = useDragAndDrop<HTMLUListElement, string>(initValues: string[], options?: Partial<ParentConfig<string>> | undefined): [Setter<HTMLUListElement | null>, Accessor<...>, SetStoreFunction<...>, (config?: Partial<...> | undefined) => void]
Hook for adding drag and drop/sortable support to a list of items.
@paraminitValues - Initial list of data.@paramoptions - The drag and drop configuration.@returns
useDragAndDrop
<HTMLUListElement, string>(
[ "Depeche Mode", "Duran Duran", "Pet Shop Boys", "Kraftwerk", "Tears for Fears", "Spandau Ballet", ], { draggable?: ((child: HTMLElement) => boolean) | undefined
A function that returns whether a given node is draggable.
draggable
: (el: HTMLElementel) => {
return el: HTMLElementel.Element.id: string
Returns the value of element's id content attribute. Can be set to change it. [MDN Reference](https://developer.mozilla.org/docs/Web/API/Element/id)
id
!== "no-drag";
}, } ); return ( <JSX.HTMLElementTags.ul: JSX.HTMLAttributes<HTMLUListElement>ul ref?: HTMLUListElement | ((el: HTMLUListElement) => void) | undefinedref={const parent: Setter<HTMLUListElement | null>parent}> <
function For<T extends readonly any[], U extends JSX.Element>(props: {
    each: T | undefined | null | false;
    fallback?: JSX.Element;
    children: (item: T[number], index: Accessor<number>) => U;
}): JSX.Element
Creates a list elements from a list it receives a map function as its child that receives a list element and an accessor with the index and returns a JSX-Element; if the list is empty, an optional fallback is returned: ```typescript <For each={items} fallback={<div>No items</div>}> {(item, index) => <div data-index={index()}>{item}</div>} </For> ``` If you have a list with fixed indices and changing values, consider using `<Index>` instead.
@descriptionhttps://docs.solidjs.com/reference/components/for
For
each: false | string[] | null | undefinedeach={const tapes: () => string[]tapes()}>
{(tape: stringtape) => ( <JSX.HTMLElementTags.li: JSX.LiHTMLAttributes<HTMLLIElement>li JSX.HTMLAttributes<HTMLLIElement>.class?: string | undefinedclass="cassette" data-label: stringdata-label={tape: stringtape}> {tape: stringtape} </JSX.HTMLElementTags.li: JSX.LiHTMLAttributes<HTMLLIElement>li> )} </
function For<T extends readonly any[], U extends JSX.Element>(props: {
    each: T | undefined | null | false;
    fallback?: JSX.Element;
    children: (item: T[number], index: Accessor<number>) => U;
}): JSX.Element
Creates a list elements from a list it receives a map function as its child that receives a list element and an accessor with the index and returns a JSX-Element; if the list is empty, an optional fallback is returned: ```typescript <For each={items} fallback={<div>No items</div>}> {(item, index) => <div data-index={index()}>{item}</div>} </For> ``` If you have a list with fixed indices and changing values, consider using `<Index>` instead.
@descriptionhttps://docs.solidjs.com/reference/components/for
For
>
<JSX.HTMLElementTags.div: JSX.HTMLAttributes<HTMLDivElement>div JSX.HTMLAttributes<HTMLDivElement>.id?: string | undefinedid="no-drag">I am NOT draggable</JSX.HTMLElementTags.div: JSX.HTMLAttributes<HTMLDivElement>div> </JSX.HTMLElementTags.ul: JSX.HTMLAttributes<HTMLUListElement>ul> ); }
import { const reactive: <T extends DataSource>(data: T, state?: ReactiveProxyState) => ReactiveProxy<T>
reactive is an alias for r
reactive
, const html: (strings: TemplateStringsArray, ...expSlots: any[]) => ArrowTemplate
html is an alias for t
html
} from "@arrow-js/core";
import { function dragAndDrop<T>({ parent, getValues, setValues, config, }: DragAndDrop<T>): void
Initializes the drag and drop functionality for a given parent.
@paramdragAndDrop - The drag and drop configuration.@returnsvoid
dragAndDrop
} from "@formkit/drag-and-drop";
const
const state: ReactiveProxy<{
    tapes: string[];
}>
state
=
reactive<{
    tapes: string[];
}>(data: {
    tapes: string[];
}, state?: ReactiveProxyState): ReactiveProxy<{
    tapes: string[];
}>
Given a data object, often an object literal, return a proxy of that object with mutation observers for each property.
@paramdata@returnsReactiveProxy
reactive
({
tapes: string[]tapes: [ "Depeche Mode", "Duran Duran", "Pet Shop Boys", "Kraftwerk", "Tears for Fears", "Spandau Ballet", ], }); const html: (strings: TemplateStringsArray, ...expSlots: any[]) => ArrowTemplate
html is an alias for t
html
`
<ul id="cassettes"> ${() =>
const state: ReactiveProxy<{
    tapes: string[];
}>
state
.tapes: ReactiveProxy<string[]>tapes.Array<string>.map<void>(callbackfn: (value: string, index: number, array: string[]) => void, thisArg?: any): void[]
Calls a defined callback function on each element of an array, and returns an array that contains the results.
@paramcallbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.@paramthisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
map
((tape: stringtape) =>
const html: (strings: TemplateStringsArray, ...expSlots: any[]) => ArrowTemplate
html is an alias for t
html
`<li class="cassette" data-label="${tape: stringtape}">${tape: stringtape}</li>`.ArrowTemplate.key: (key: ArrowTemplateKey) => void
Adds a key to this template to identify it as a unique instance.
@paramkey - A unique key that identifies this template instance (not index).@returns
key
(tape: stringtape)
)} <div id="no-drag">I am NOT draggable</div> </ul> `(var document: Document
[MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/document)
document
.Document.getElementById(elementId: string): HTMLElement | null
Returns a reference to the first object with the specified value of the ID attribute.
@paramelementId String that specifies the ID value.
getElementById
("app")!);
dragAndDrop<string>({ parent, getValues, setValues, config, }: DragAndDrop<string>): void
Initializes the drag and drop functionality for a given parent.
@paramdragAndDrop - The drag and drop configuration.@returnsvoid
dragAndDrop
<string>({
DragAndDrop<string>.parent: HTMLElement
The parent element that will contain the draggable nodes.
parent
: var document: Document
[MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/document)
document
.Document.getElementById(elementId: string): HTMLElement | null
Returns a reference to the first object with the specified value of the ID attribute.
@paramelementId String that specifies the ID value.
getElementById
("cassettes")!,
DragAndDrop<string>.getValues: (parent: HTMLElement) => string[]
A function that returns the values assigned to the parent.
getValues
: () =>
const state: ReactiveProxy<{
    tapes: string[];
}>
state
.tapes: ReactiveProxy<string[]>tapes,
DragAndDrop<string>.setValues: (values: string[], parent: HTMLElement) => void
A function that sets the values assigned to the parent.
setValues
: (newValues: string[]newValues) => {
const state: ReactiveProxy<{
    tapes: string[];
}>
state
.tapes: ReactiveProxy<string[]>tapes = reactive<string[]>(data: string[], state?: ReactiveProxyState): ReactiveProxy<string[]>
Given a data object, often an object literal, return a proxy of that object with mutation observers for each property.
@paramdata@returnsReactiveProxy
reactive
(newValues: string[]newValues);
}, DragAndDrop<string>.config?: Partial<ParentConfig<string>> | undefined
An optional configuration object.
config
: {
draggable?: ((child: HTMLElement) => boolean) | undefined
A function that returns whether a given node is draggable.
draggable
: (el: HTMLElementel) => {
return el: HTMLElementel.Element.id: string
Returns the value of element's id content attribute. Can be set to change it. [MDN Reference](https://developer.mozilla.org/docs/Web/API/Element/id)
id
!== "no-drag";
}, }, });
FormKit Office Jams
  • Depeche Mode
    Cassette Tape
  • Duran Duran
    Cassette Tape
  • Pet Shop Boys
    Cassette Tape
  • Kraftwerk
    Cassette Tape
  • Tears for Fears
    Cassette Tape
  • Spandau Ballet
    Cassette Tape
  • I am NOT draggable
["Depeche Mode","Duran Duran","Pet Shop Boys","Kraftwerk","Tears for Fears","Spandau Ballet"]

Transferability

In addition to sorting, drag-and-drop allows transferring values between parents (lists). To enable this, set the configuration property group to the same value for each list that should allow value transfers. Notice in the example below that items can be appended to the end of the list by hovering over the list itself, or inserted into the list by hovering over the target parent's draggable items.

  • React
  • Vue
  • Solid
  • Native
import React from "react";
import { function useDragAndDrop<E extends HTMLElement, T = unknown>(list: T[], options?: Partial<ParentConfig<T>>): [React.RefObject<E>, T[], React.Dispatch<React.SetStateAction<T[]>>, (config: Partial<ParentConfig<...>>) => void]
Hook for adding drag and drop/sortable support to a list of items.
@paramlist - Initial list of data.@paramoptions - The drag and drop configuration.@returns
useDragAndDrop
} from "@formkit/drag-and-drop/react";
export function function myComponent(): React.JSX.ElementmyComponent() { const const todoItems: string[]todoItems = [ "Schedule perm", "Rewind VHS tapes", "Make change for the arcade", "Get disposable camera developed", "Learn C++", "Return Nintendo Power Glove", ]; const const doneItems: string[]doneItems = ["Pickup new mix-tape from Beth"]; const [const todoList: React.RefObject<HTMLUListElement>todoList, const todos: string[]todos] = useDragAndDrop<HTMLUListElement, string>(list: string[], options?: Partial<ParentConfig<string>> | undefined): [React.RefObject<HTMLUListElement>, string[], React.Dispatch<...>, (config: Partial<...>) => void]
Hook for adding drag and drop/sortable support to a list of items.
@paramlist - Initial list of data.@paramoptions - The drag and drop configuration.@returns
useDragAndDrop
<HTMLUListElement, string>(
const todoItems: string[]todoItems, { group?: string | undefined
The group that the parent belongs to. This is used for allowing multiple parents to transfer nodes between each other.
group
: "todoList" }
); const [const doneList: React.RefObject<HTMLUListElement>doneList, const dones: string[]dones] = useDragAndDrop<HTMLUListElement, string>(list: string[], options?: Partial<ParentConfig<string>> | undefined): [React.RefObject<HTMLUListElement>, string[], React.Dispatch<...>, (config: Partial<...>) => void]
Hook for adding drag and drop/sortable support to a list of items.
@paramlist - Initial list of data.@paramoptions - The drag and drop configuration.@returns
useDragAndDrop
<HTMLUListElement, string>(
const doneItems: string[]doneItems, { group?: string | undefined
The group that the parent belongs to. This is used for allowing multiple parents to transfer nodes between each other.
group
: "todoList" }
); return ( <JSX.IntrinsicElements.div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>div React.HTMLAttributes<HTMLDivElement>.className?: string | undefinedclassName="kanban-board"> <JSX.IntrinsicElements.ul: React.DetailedHTMLProps<React.HTMLAttributes<HTMLUListElement>, HTMLUListElement>ul React.RefAttributes<HTMLUListElement>.ref?: React.LegacyRef<HTMLUListElement> | undefined
Allows getting a ref to the component instance. Once the component unmounts, React will set `ref.current` to `null` (or call the ref with `null` if you passed a callback ref).
@see{@link https://react.dev/learn/referencing-values-with-refs#refs-and-the-dom React Docs}
ref
={const todoList: React.RefObject<HTMLUListElement>todoList}>
{const todos: string[]todos.Array<string>.map<React.JSX.Element>(callbackfn: (value: string, index: number, array: string[]) => React.JSX.Element, thisArg?: any): React.JSX.Element[]
Calls a defined callback function on each element of an array, and returns an array that contains the results.
@paramcallbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.@paramthisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
map
((todo: stringtodo) => (
<JSX.IntrinsicElements.li: React.DetailedHTMLProps<React.LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>li React.HTMLAttributes<T>.className?: string | undefinedclassName="kanban-item" React.Attributes.key?: React.Key | null | undefinedkey={todo: stringtodo}> {todo: stringtodo} </JSX.IntrinsicElements.li: React.DetailedHTMLProps<React.LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>li> ))} </JSX.IntrinsicElements.ul: React.DetailedHTMLProps<React.HTMLAttributes<HTMLUListElement>, HTMLUListElement>ul> <JSX.IntrinsicElements.ul: React.DetailedHTMLProps<React.HTMLAttributes<HTMLUListElement>, HTMLUListElement>ul React.RefAttributes<HTMLUListElement>.ref?: React.LegacyRef<HTMLUListElement> | undefined
Allows getting a ref to the component instance. Once the component unmounts, React will set `ref.current` to `null` (or call the ref with `null` if you passed a callback ref).
@see{@link https://react.dev/learn/referencing-values-with-refs#refs-and-the-dom React Docs}
ref
={const doneList: React.RefObject<HTMLUListElement>doneList}>
{const dones: string[]dones.Array<string>.map<React.JSX.Element>(callbackfn: (value: string, index: number, array: string[]) => React.JSX.Element, thisArg?: any): React.JSX.Element[]
Calls a defined callback function on each element of an array, and returns an array that contains the results.
@paramcallbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.@paramthisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
map
((done: stringdone) => (
<JSX.IntrinsicElements.li: React.DetailedHTMLProps<React.LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>li React.HTMLAttributes<T>.className?: string | undefinedclassName="kanban-item" React.Attributes.key?: React.Key | null | undefinedkey={done: stringdone}> {done: stringdone} </JSX.IntrinsicElements.li: React.DetailedHTMLProps<React.LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>li> ))} </JSX.IntrinsicElements.ul: React.DetailedHTMLProps<React.HTMLAttributes<HTMLUListElement>, HTMLUListElement>ul> </JSX.IntrinsicElements.div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>div> ); }
<script setup lang="ts">
import { function useDragAndDrop<T>(initialValues: T[], options?: Partial<VueParentConfig<T>>): [Ref<HTMLElement | undefined>, Ref<T[]>, (config: Partial<VueParentConfig<T>>) => void]
Creates a new instance of drag and drop and returns the parent element and a ref of the values to use in your template.
@paraminitialValues - The initial values of the parent element.@returnsThe parent element and values for drag and drop.
useDragAndDrop
} from "@formkit/drag-and-drop/vue";
const const todoItems: string[]todoItems = ["Schedule perm", "Rewind VHS tapes", "Make change for the arcade", "Get disposable camera developed", "Learn C++", "Return Nintendo Power Glove"]; const const doneItems: string[]doneItems = ["Pickup new mix-tape from Beth"]; const [const todoList: Ref<HTMLElement | undefined, HTMLElement | undefined>todoList, const todos: Ref<string[], string[]>todos] = useDragAndDrop<string>(initialValues: string[], options?: Partial<Partial<ParentConfig<string>>> | undefined): [Ref<HTMLElement | undefined, HTMLElement | undefined>, Ref<...>, (config: Partial<...>) => void]
Creates a new instance of drag and drop and returns the parent element and a ref of the values to use in your template.
@paraminitialValues - The initial values of the parent element.@returnsThe parent element and values for drag and drop.
useDragAndDrop
(const todoItems: string[]todoItems, { group?: string | undefined
The group that the parent belongs to. This is used for allowing multiple parents to transfer nodes between each other.
group
: "todoList" });
const [const doneList: Ref<HTMLElement | undefined, HTMLElement | undefined>doneList, const dones: Ref<string[], string[]>dones] = useDragAndDrop<string>(initialValues: string[], options?: Partial<Partial<ParentConfig<string>>> | undefined): [Ref<HTMLElement | undefined, HTMLElement | undefined>, Ref<...>, (config: Partial<...>) => void]
Creates a new instance of drag and drop and returns the parent element and a ref of the values to use in your template.
@paraminitialValues - The initial values of the parent element.@returnsThe parent element and values for drag and drop.
useDragAndDrop
(const doneItems: string[]doneItems, { group?: string | undefined
The group that the parent belongs to. This is used for allowing multiple parents to transfer nodes between each other.
group
: "todoList" });
</script> <template> <div: HTMLAttributes & ReservedPropsdiv HTMLAttributes.class?: anyclass="kanban-board"> <ul: HTMLAttributes & ReservedPropsul ref?: VNodeRef | undefinedref="const todoList: Ref<HTMLElement | undefined, HTMLElement | undefined>todoList" HTMLAttributes.class?: anyclass="kanban-column"> <li: LiHTMLAttributes & ReservedPropsli v-for="const todo: stringtodo in const todos: Ref<string[], string[]>todos" key?: PropertyKey | undefined:key?: PropertyKey | undefinedkey="const todo: stringtodo" HTMLAttributes.class?: anyclass="kanban-item"> {{ const todo: stringtodo }} </li: LiHTMLAttributes & ReservedPropsli> </ul: HTMLAttributes & ReservedPropsul> <ul: HTMLAttributes & ReservedPropsul ref?: VNodeRef | undefinedref="const doneList: Ref<HTMLElement | undefined, HTMLElement | undefined>doneList" HTMLAttributes.class?: anyclass="kanban-column"> <li: LiHTMLAttributes & ReservedPropsli v-for="const done: stringdone in const dones: Ref<string[], string[]>dones" key?: PropertyKey | undefined:key?: PropertyKey | undefinedkey="const done: stringdone" HTMLAttributes.class?: anyclass="kanban-item"> {{ const done: stringdone }} </li: LiHTMLAttributes & ReservedPropsli> </ul: HTMLAttributes & ReservedPropsul> </div: HTMLAttributes & ReservedPropsdiv> </template>
/** @jsxImportSource solid-js */
import { 
function For<T extends readonly any[], U extends JSX.Element>(props: {
    each: T | undefined | null | false;
    fallback?: JSX.Element;
    children: (item: T[number], index: Accessor<number>) => U;
}): JSX.Element
Creates a list elements from a list it receives a map function as its child that receives a list element and an accessor with the index and returns a JSX-Element; if the list is empty, an optional fallback is returned: ```typescript <For each={items} fallback={<div>No items</div>}> {(item, index) => <div data-index={index()}>{item}</div>} </For> ``` If you have a list with fixed indices and changing values, consider using `<Index>` instead.
@descriptionhttps://docs.solidjs.com/reference/components/for
For
} from "solid-js";
import { function useDragAndDrop<E extends HTMLElement, T = unknown>(initValues: T[], options?: Partial<ParentConfig<T>>): [Setter<E | null>, Accessor<Store<T[]>>, ReturnType<typeof createStore>[1], (config?: Partial<ParentConfig<T>>) => void]
Hook for adding drag and drop/sortable support to a list of items.
@paraminitValues - Initial list of data.@paramoptions - The drag and drop configuration.@returns
useDragAndDrop
} from "@formkit/drag-and-drop/solid";
export function function MyComponent(): JSX.ElementMyComponent() { const const todoItems: string[]todoItems = [ "Schedule perm", "Rewind VHS tapes", "Make change for the arcade", "Get disposable camera developed", "Learn C++", "Return Nintendo Power Glove", ]; const const doneItems: string[]doneItems = ["Pickup new mix-tape from Beth"]; const [const todoList: Setter<HTMLUListElement | null>todoList, const todos: Accessor<string[]>todos] = useDragAndDrop<HTMLUListElement, string>(initValues: string[], options?: Partial<ParentConfig<string>> | undefined): [Setter<HTMLUListElement | null>, Accessor<...>, SetStoreFunction<...>, (config?: Partial<...> | undefined) => void]
Hook for adding drag and drop/sortable support to a list of items.
@paraminitValues - Initial list of data.@paramoptions - The drag and drop configuration.@returns
useDragAndDrop
<HTMLUListElement, string>(
const todoItems: string[]todoItems, { group?: string | undefined
The group that the parent belongs to. This is used for allowing multiple parents to transfer nodes between each other.
group
: "todoList" }
); const [const doneList: Setter<HTMLUListElement | null>doneList, const dones: Accessor<string[]>dones] = useDragAndDrop<HTMLUListElement, string>(initValues: string[], options?: Partial<ParentConfig<string>> | undefined): [Setter<HTMLUListElement | null>, Accessor<...>, SetStoreFunction<...>, (config?: Partial<...> | undefined) => void]
Hook for adding drag and drop/sortable support to a list of items.
@paraminitValues - Initial list of data.@paramoptions - The drag and drop configuration.@returns
useDragAndDrop
<HTMLUListElement, string>(
const doneItems: string[]doneItems, { group?: string | undefined
The group that the parent belongs to. This is used for allowing multiple parents to transfer nodes between each other.
group
: "todoList" }
); return ( <JSX.HTMLElementTags.div: JSX.HTMLAttributes<HTMLDivElement>div JSX.HTMLAttributes<HTMLDivElement>.class?: string | undefinedclass="kanban-board"> <JSX.HTMLElementTags.ul: JSX.HTMLAttributes<HTMLUListElement>ul ref?: HTMLUListElement | ((el: HTMLUListElement) => void) | undefinedref={const todoList: Setter<HTMLUListElement | null>todoList}> <
function For<T extends readonly any[], U extends JSX.Element>(props: {
    each: T | undefined | null | false;
    fallback?: JSX.Element;
    children: (item: T[number], index: Accessor<number>) => U;
}): JSX.Element
Creates a list elements from a list it receives a map function as its child that receives a list element and an accessor with the index and returns a JSX-Element; if the list is empty, an optional fallback is returned: ```typescript <For each={items} fallback={<div>No items</div>}> {(item, index) => <div data-index={index()}>{item}</div>} </For> ``` If you have a list with fixed indices and changing values, consider using `<Index>` instead.
@descriptionhttps://docs.solidjs.com/reference/components/for
For
each: false | string[] | null | undefinedeach={const todos: () => string[]todos()}>
{(todo: stringtodo) => <JSX.HTMLElementTags.li: JSX.LiHTMLAttributes<HTMLLIElement>li JSX.HTMLAttributes<T>.class?: string | undefinedclass="kanban-item">{todo: stringtodo}</JSX.HTMLElementTags.li: JSX.LiHTMLAttributes<HTMLLIElement>li>} </
function For<T extends readonly any[], U extends JSX.Element>(props: {
    each: T | undefined | null | false;
    fallback?: JSX.Element;
    children: (item: T[number], index: Accessor<number>) => U;
}): JSX.Element
Creates a list elements from a list it receives a map function as its child that receives a list element and an accessor with the index and returns a JSX-Element; if the list is empty, an optional fallback is returned: ```typescript <For each={items} fallback={<div>No items</div>}> {(item, index) => <div data-index={index()}>{item}</div>} </For> ``` If you have a list with fixed indices and changing values, consider using `<Index>` instead.
@descriptionhttps://docs.solidjs.com/reference/components/for
For
>
</JSX.HTMLElementTags.ul: JSX.HTMLAttributes<HTMLUListElement>ul> <JSX.HTMLElementTags.ul: JSX.HTMLAttributes<HTMLUListElement>ul ref?: HTMLUListElement | ((el: HTMLUListElement) => void) | undefinedref={const doneList: Setter<HTMLUListElement | null>doneList}> <
function For<T extends readonly any[], U extends JSX.Element>(props: {
    each: T | undefined | null | false;
    fallback?: JSX.Element;
    children: (item: T[number], index: Accessor<number>) => U;
}): JSX.Element
Creates a list elements from a list it receives a map function as its child that receives a list element and an accessor with the index and returns a JSX-Element; if the list is empty, an optional fallback is returned: ```typescript <For each={items} fallback={<div>No items</div>}> {(item, index) => <div data-index={index()}>{item}</div>} </For> ``` If you have a list with fixed indices and changing values, consider using `<Index>` instead.
@descriptionhttps://docs.solidjs.com/reference/components/for
For
each: false | string[] | null | undefinedeach={const dones: () => string[]dones()}>
{(done: stringdone) => <JSX.HTMLElementTags.li: JSX.LiHTMLAttributes<HTMLLIElement>li JSX.HTMLAttributes<T>.class?: string | undefinedclass="kanban-item">{done: stringdone}</JSX.HTMLElementTags.li: JSX.LiHTMLAttributes<HTMLLIElement>li>} </
function For<T extends readonly any[], U extends JSX.Element>(props: {
    each: T | undefined | null | false;
    fallback?: JSX.Element;
    children: (item: T[number], index: Accessor<number>) => U;
}): JSX.Element
Creates a list elements from a list it receives a map function as its child that receives a list element and an accessor with the index and returns a JSX-Element; if the list is empty, an optional fallback is returned: ```typescript <For each={items} fallback={<div>No items</div>}> {(item, index) => <div data-index={index()}>{item}</div>} </For> ``` If you have a list with fixed indices and changing values, consider using `<Index>` instead.
@descriptionhttps://docs.solidjs.com/reference/components/for
For
>
</JSX.HTMLElementTags.ul: JSX.HTMLAttributes<HTMLUListElement>ul> </JSX.HTMLElementTags.div: JSX.HTMLAttributes<HTMLDivElement>div> ); }
import { const reactive: <T extends DataSource>(data: T, state?: ReactiveProxyState) => ReactiveProxy<T>
reactive is an alias for r
reactive
, const html: (strings: TemplateStringsArray, ...expSlots: any[]) => ArrowTemplate
html is an alias for t
html
} from "@arrow-js/core";
import { function dragAndDrop<T>({ parent, getValues, setValues, config, }: DragAndDrop<T>): void
Initializes the drag and drop functionality for a given parent.
@paramdragAndDrop - The drag and drop configuration.@returnsvoid
dragAndDrop
} from "@formkit/drag-and-drop";
const
const state: ReactiveProxy<{
    todos: string[];
    dones: string[];
}>
state
=
reactive<{
    todos: string[];
    dones: string[];
}>(data: {
    todos: string[];
    dones: string[];
}, state?: ReactiveProxyState): ReactiveProxy<{
    todos: string[];
    dones: string[];
}>
Given a data object, often an object literal, return a proxy of that object with mutation observers for each property.
@paramdata@returnsReactiveProxy
reactive
({
todos: string[]todos: [ "Schedule perm", "Rewind VHS tapes", "Make change for the arcade", "Get disposable camera developed", "Learn C++", "Return Nintendo Power Glove", ], dones: string[]dones: ["Pickup new mix-tape from Beth"], }); dragAndDrop<string>({ parent, getValues, setValues, config, }: DragAndDrop<string>): void
Initializes the drag and drop functionality for a given parent.
@paramdragAndDrop - The drag and drop configuration.@returnsvoid
dragAndDrop
<string>({
DragAndDrop<string>.parent: HTMLElement
The parent element that will contain the draggable nodes.
parent
: var document: Document
[MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/document)
document
.Document.getElementById(elementId: string): HTMLElement | null
Returns a reference to the first object with the specified value of the ID attribute.
@paramelementId String that specifies the ID value.
getElementById
("todo-list")!,
DragAndDrop<string>.getValues: (parent: HTMLElement) => string[]
A function that returns the values assigned to the parent.
getValues
: () =>
const state: ReactiveProxy<{
    todos: string[];
    dones: string[];
}>
state
.todos: ReactiveProxy<string[]>todos,
DragAndDrop<string>.setValues: (values: string[], parent: HTMLElement) => void
A function that sets the values assigned to the parent.
setValues
: (newValues: string[]newValues) => {
const state: ReactiveProxy<{
    todos: string[];
    dones: string[];
}>
state
.todos: ReactiveProxy<string[]>todos = reactive<string[]>(data: string[], state?: ReactiveProxyState): ReactiveProxy<string[]>
Given a data object, often an object literal, return a proxy of that object with mutation observers for each property.
@paramdata@returnsReactiveProxy
reactive
(newValues: string[]newValues);
}, DragAndDrop<string>.config?: Partial<ParentConfig<string>> | undefined
An optional configuration object.
config
: {
group?: string | undefined
The group that the parent belongs to. This is used for allowing multiple parents to transfer nodes between each other.
group
: "todoList",
}, }); dragAndDrop<string>({ parent, getValues, setValues, config, }: DragAndDrop<string>): void
Initializes the drag and drop functionality for a given parent.
@paramdragAndDrop - The drag and drop configuration.@returnsvoid
dragAndDrop
<string>({
DragAndDrop<string>.parent: HTMLElement
The parent element that will contain the draggable nodes.
parent
: var document: Document
[MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/document)
document
.Document.getElementById(elementId: string): HTMLElement | null
Returns a reference to the first object with the specified value of the ID attribute.
@paramelementId String that specifies the ID value.
getElementById
("done-list")!,
DragAndDrop<string>.getValues: (parent: HTMLElement) => string[]
A function that returns the values assigned to the parent.
getValues
: () =>
const state: ReactiveProxy<{
    todos: string[];
    dones: string[];
}>
state
.dones: ReactiveProxy<string[]>dones,
DragAndDrop<string>.setValues: (values: string[], parent: HTMLElement) => void
A function that sets the values assigned to the parent.
setValues
: (newValues: string[]newValues) => {
const state: ReactiveProxy<{
    todos: string[];
    dones: string[];
}>
state
.dones: ReactiveProxy<string[]>dones = reactive<string[]>(data: string[], state?: ReactiveProxyState): ReactiveProxy<string[]>
Given a data object, often an object literal, return a proxy of that object with mutation observers for each property.
@paramdata@returnsReactiveProxy
reactive
(newValues: string[]newValues);
}, DragAndDrop<string>.config?: Partial<ParentConfig<string>> | undefined
An optional configuration object.
config
: {
group?: string | undefined
The group that the parent belongs to. This is used for allowing multiple parents to transfer nodes between each other.
group
: "todoList",
}, }); const html: (strings: TemplateStringsArray, ...expSlots: any[]) => ArrowTemplate
html is an alias for t
html
`
<div class="kanban-board"> <ul class="kanban-list" id="todo-list"> ${() =>
const state: ReactiveProxy<{
    todos: string[];
    dones: string[];
}>
state
.todos: ReactiveProxy<string[]>todos.Array<string>.map<void>(callbackfn: (value: string, index: number, array: string[]) => void, thisArg?: any): void[]
Calls a defined callback function on each element of an array, and returns an array that contains the results.
@paramcallbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.@paramthisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
map
((todo: stringtodo) =>
const html: (strings: TemplateStringsArray, ...expSlots: any[]) => ArrowTemplate
html is an alias for t
html
`<li class="kanban-item">${todo: stringtodo}</li>`.ArrowTemplate.key: (key: ArrowTemplateKey) => void
Adds a key to this template to identify it as a unique instance.
@paramkey - A unique key that identifies this template instance (not index).@returns
key
(todo: stringtodo)
)} </ul> <ul class="kanban-list" id="done-list"> ${
const state: ReactiveProxy<{
    todos: string[];
    dones: string[];
}>
state
.dones: ReactiveProxy<string[]>dones.Array<string>.map<void>(callbackfn: (value: string, index: number, array: string[]) => void, thisArg?: any): void[]
Calls a defined callback function on each element of an array, and returns an array that contains the results.
@paramcallbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.@paramthisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
map
((done: stringdone) =>
const html: (strings: TemplateStringsArray, ...expSlots: any[]) => ArrowTemplate
html is an alias for t
html
`<li class="kanban-item">${done: stringdone}</li>`.ArrowTemplate.key: (key: ArrowTemplateKey) => void
Adds a key to this template to identify it as a unique instance.
@paramkey - A unique key that identifies this template instance (not index).@returns
key
(done: stringdone)
)} </ul> </div> `(var document: Document
[MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/document)
document
.Document.getElementById(elementId: string): HTMLElement | null
Returns a reference to the first object with the specified value of the ID attribute.
@paramelementId String that specifies the ID value.
getElementById
("app")!);

ToDos

  • Schedule perm
  • Rewind VHS tapes
  • Make change for the arcade
  • Get disposable camera developed
  • Learn C++
  • Return Nintendo Power Glove
["Schedule perm","Rewind VHS tapes","Make change for the arcade","Get disposable camera developed","Learn C++","Return Nintendo Power Glove"]

Complete

  • Pickup new mix-tape from Beth
["Pickup new mix-tape from Beth"]

Disable sort

Sortability within a given parent can be toggled on and off by setting the sortable property to in the configuration.

  • React
  • Vue
  • Solid
  • Native
import React from "react";
import { function useDragAndDrop<E extends HTMLElement, T = unknown>(list: T[], options?: Partial<ParentConfig<T>>): [React.RefObject<E>, T[], React.Dispatch<React.SetStateAction<T[]>>, (config: Partial<ParentConfig<...>>) => void]
Hook for adding drag and drop/sortable support to a list of items.
@paramlist - Initial list of data.@paramoptions - The drag and drop configuration.@returns
useDragAndDrop
} from "@formkit/drag-and-drop/react";
export function function myComponent(): React.JSX.ElementmyComponent() { const const todoItems: string[]todoItems = ["Schedule perm", "Rewind VHS tapes", "Make change for the arcade", "Get disposable camera developed", "Learn C++", "Return Nintendo Power Glove"]; const const doneItems: string[]doneItems = ["Pickup new mix-tape from Beth"]; const [const todoList: React.RefObject<HTMLUListElement>todoList, const todos: string[]todos] = useDragAndDrop<HTMLUListElement, string>(list: string[], options?: Partial<ParentConfig<string>> | undefined): [React.RefObject<HTMLUListElement>, string[], React.Dispatch<...>, (config: Partial<...>) => void]
Hook for adding drag and drop/sortable support to a list of items.
@paramlist - Initial list of data.@paramoptions - The drag and drop configuration.@returns
useDragAndDrop
<HTMLUListElement, string>(
const todoItems: string[]todoItems, { group?: string | undefined
The group that the parent belongs to. This is used for allowing multiple parents to transfer nodes between each other.
group
: "todoList",
sortable?: boolean | undefined
Flag for whether or not to allow sorting within a given parent.
sortable
: false
} ); const [const doneList: React.RefObject<HTMLUListElement>doneList, const dones: string[]dones] = useDragAndDrop<HTMLUListElement, string>(list: string[], options?: Partial<ParentConfig<string>> | undefined): [React.RefObject<HTMLUListElement>, string[], React.Dispatch<...>, (config: Partial<...>) => void]
Hook for adding drag and drop/sortable support to a list of items.
@paramlist - Initial list of data.@paramoptions - The drag and drop configuration.@returns
useDragAndDrop
<HTMLUListElement, string>(
const doneItems: string[]doneItems, { group?: string | undefined
The group that the parent belongs to. This is used for allowing multiple parents to transfer nodes between each other.
group
: "todoList",
sortable?: boolean | undefined
Flag for whether or not to allow sorting within a given parent.
sortable
: false
} ); return ( <JSX.IntrinsicElements.div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>div React.HTMLAttributes<HTMLDivElement>.className?: string | undefinedclassName="kanban-board"> <JSX.IntrinsicElements.ul: React.DetailedHTMLProps<React.HTMLAttributes<HTMLUListElement>, HTMLUListElement>ul React.RefAttributes<HTMLUListElement>.ref?: React.LegacyRef<HTMLUListElement> | undefined
Allows getting a ref to the component instance. Once the component unmounts, React will set `ref.current` to `null` (or call the ref with `null` if you passed a callback ref).
@see{@link https://react.dev/learn/referencing-values-with-refs#refs-and-the-dom React Docs}
ref
={const todoList: React.RefObject<HTMLUListElement>todoList}>
{const todos: string[]todos.Array<string>.map<React.JSX.Element>(callbackfn: (value: string, index: number, array: string[]) => React.JSX.Element, thisArg?: any): React.JSX.Element[]
Calls a defined callback function on each element of an array, and returns an array that contains the results.
@paramcallbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.@paramthisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
map
((todo: stringtodo) => (
<JSX.IntrinsicElements.li: React.DetailedHTMLProps<React.LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>li React.HTMLAttributes<T>.className?: string | undefinedclassName="kanban-item" React.Attributes.key?: React.Key | null | undefinedkey={todo: stringtodo}> {todo: stringtodo} </JSX.IntrinsicElements.li: React.DetailedHTMLProps<React.LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>li> ))} </JSX.IntrinsicElements.ul: React.DetailedHTMLProps<React.HTMLAttributes<HTMLUListElement>, HTMLUListElement>ul> <JSX.IntrinsicElements.ul: React.DetailedHTMLProps<React.HTMLAttributes<HTMLUListElement>, HTMLUListElement>ul React.RefAttributes<HTMLUListElement>.ref?: React.LegacyRef<HTMLUListElement> | undefined
Allows getting a ref to the component instance. Once the component unmounts, React will set `ref.current` to `null` (or call the ref with `null` if you passed a callback ref).
@see{@link https://react.dev/learn/referencing-values-with-refs#refs-and-the-dom React Docs}
ref
={const doneList: React.RefObject<HTMLUListElement>doneList}>
{const dones: string[]dones.Array<string>.map<React.JSX.Element>(callbackfn: (value: string, index: number, array: string[]) => React.JSX.Element, thisArg?: any): React.JSX.Element[]
Calls a defined callback function on each element of an array, and returns an array that contains the results.
@paramcallbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.@paramthisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
map
((done: stringdone) => (
<JSX.IntrinsicElements.li: React.DetailedHTMLProps<React.LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>li React.HTMLAttributes<T>.className?: string | undefinedclassName="kanban-item" React.Attributes.key?: React.Key | null | undefinedkey={done: stringdone}> {done: stringdone} </JSX.IntrinsicElements.li: React.DetailedHTMLProps<React.LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>li> ))} </JSX.IntrinsicElements.ul: React.DetailedHTMLProps<React.HTMLAttributes<HTMLUListElement>, HTMLUListElement>ul> </JSX.IntrinsicElements.div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>div> ); }
<script setup lang="ts">
import { function useDragAndDrop<T>(initialValues: T[], options?: Partial<VueParentConfig<T>>): [Ref<HTMLElement | undefined>, Ref<T[]>, (config: Partial<VueParentConfig<T>>) => void]
Creates a new instance of drag and drop and returns the parent element and a ref of the values to use in your template.
@paraminitialValues - The initial values of the parent element.@returnsThe parent element and values for drag and drop.
useDragAndDrop
} from "@formkit/drag-and-drop/vue";
const const todoItems: string[]todoItems = [ "Schedule perm", "Rewind VHS tapes", "Make change for the arcade", "Get disposable camera developed", "Learn C++", "Return Nintendo Power Glove", ]; const const doneItems: string[]doneItems = ["Pickup new mix-tape from Beth"]; const [const todoList: Ref<HTMLElement | undefined, HTMLElement | undefined>todoList, const todos: Ref<string[], string[]>todos] = useDragAndDrop<string>(initialValues: string[], options?: Partial<Partial<ParentConfig<string>>> | undefined): [Ref<HTMLElement | undefined, HTMLElement | undefined>, Ref<...>, (config: Partial<...>) => void]
Creates a new instance of drag and drop and returns the parent element and a ref of the values to use in your template.
@paraminitialValues - The initial values of the parent element.@returnsThe parent element and values for drag and drop.
useDragAndDrop
(const todoItems: string[]todoItems, {
group?: string | undefined
The group that the parent belongs to. This is used for allowing multiple parents to transfer nodes between each other.
group
: "todoList",
sortable?: boolean | undefined
Flag for whether or not to allow sorting within a given parent.
sortable
: false,
}); const [const doneList: Ref<HTMLElement | undefined, HTMLElement | undefined>doneList, const dones: Ref<string[], string[]>dones] = useDragAndDrop<string>(initialValues: string[], options?: Partial<Partial<ParentConfig<string>>> | undefined): [Ref<HTMLElement | undefined, HTMLElement | undefined>, Ref<...>, (config: Partial<...>) => void]
Creates a new instance of drag and drop and returns the parent element and a ref of the values to use in your template.
@paraminitialValues - The initial values of the parent element.@returnsThe parent element and values for drag and drop.
useDragAndDrop
(const doneItems: string[]doneItems, {
group?: string | undefined
The group that the parent belongs to. This is used for allowing multiple parents to transfer nodes between each other.
group
: "todoList",
sortable?: boolean | undefined
Flag for whether or not to allow sorting within a given parent.
sortable
: false,
}); </script> <template> <div: HTMLAttributes & ReservedPropsdiv HTMLAttributes.class?: anyclass="kanban-board"> <ul: HTMLAttributes & ReservedPropsul ref?: VNodeRef | undefinedref="const todoList: Ref<HTMLElement | undefined, HTMLElement | undefined>todoList" HTMLAttributes.class?: anyclass="kanban-column"> <li: LiHTMLAttributes & ReservedPropsli v-for="const todo: stringtodo in const todos: Ref<string[], string[]>todos" key?: PropertyKey | undefined:key?: PropertyKey | undefinedkey="const todo: stringtodo" HTMLAttributes.class?: anyclass="kanban-item"> {{ const todo: stringtodo }} </li: LiHTMLAttributes & ReservedPropsli> </ul: HTMLAttributes & ReservedPropsul> <ul: HTMLAttributes & ReservedPropsul ref?: VNodeRef | undefinedref="const doneList: Ref<HTMLElement | undefined, HTMLElement | undefined>doneList" HTMLAttributes.class?: anyclass="kanban-column"> <li: LiHTMLAttributes & ReservedPropsli v-for="const done: stringdone in const dones: Ref<string[], string[]>dones" key?: PropertyKey | undefined:key?: PropertyKey | undefinedkey="const done: stringdone" HTMLAttributes.class?: anyclass="kanban-item"> {{ const done: stringdone }} </li: LiHTMLAttributes & ReservedPropsli> </ul: HTMLAttributes & ReservedPropsul> </div: HTMLAttributes & ReservedPropsdiv> </template>
/** @jsxImportSource solid-js */
import { 
function For<T extends readonly any[], U extends JSX.Element>(props: {
    each: T | undefined | null | false;
    fallback?: JSX.Element;
    children: (item: T[number], index: Accessor<number>) => U;
}): JSX.Element
Creates a list elements from a list it receives a map function as its child that receives a list element and an accessor with the index and returns a JSX-Element; if the list is empty, an optional fallback is returned: ```typescript <For each={items} fallback={<div>No items</div>}> {(item, index) => <div data-index={index()}>{item}</div>} </For> ``` If you have a list with fixed indices and changing values, consider using `<Index>` instead.
@descriptionhttps://docs.solidjs.com/reference/components/for
For
} from "solid-js";
import { function useDragAndDrop<E extends HTMLElement, T = unknown>(initValues: T[], options?: Partial<ParentConfig<T>>): [Setter<E | null>, Accessor<Store<T[]>>, ReturnType<typeof createStore>[1], (config?: Partial<ParentConfig<T>>) => void]
Hook for adding drag and drop/sortable support to a list of items.
@paraminitValues - Initial list of data.@paramoptions - The drag and drop configuration.@returns
useDragAndDrop
} from "@formkit/drag-and-drop/solid";
export function function MyComponent(): JSX.ElementMyComponent() { const const todoItems: string[]todoItems = [ "Schedule perm", "Rewind VHS tapes", "Make change for the arcade", "Get disposable camera developed", "Learn C++", "Return Nintendo Power Glove", ]; const const doneItems: string[]doneItems = ["Pickup new mix-tape from Beth"]; const [const todoList: Setter<HTMLUListElement | null>todoList, const todos: Accessor<string[]>todos] = useDragAndDrop<HTMLUListElement, string>(initValues: string[], options?: Partial<ParentConfig<string>> | undefined): [Setter<HTMLUListElement | null>, Accessor<...>, SetStoreFunction<...>, (config?: Partial<...> | undefined) => void]
Hook for adding drag and drop/sortable support to a list of items.
@paraminitValues - Initial list of data.@paramoptions - The drag and drop configuration.@returns
useDragAndDrop
<HTMLUListElement, string>(
const todoItems: string[]todoItems, { group?: string | undefined
The group that the parent belongs to. This is used for allowing multiple parents to transfer nodes between each other.
group
: "todoList",
sortable?: boolean | undefined
Flag for whether or not to allow sorting within a given parent.
sortable
: false,
} ); const [const doneList: Setter<HTMLUListElement | null>doneList, const dones: Accessor<string[]>dones] = useDragAndDrop<HTMLUListElement, string>(initValues: string[], options?: Partial<ParentConfig<string>> | undefined): [Setter<HTMLUListElement | null>, Accessor<...>, SetStoreFunction<...>, (config?: Partial<...> | undefined) => void]
Hook for adding drag and drop/sortable support to a list of items.
@paraminitValues - Initial list of data.@paramoptions - The drag and drop configuration.@returns
useDragAndDrop
<HTMLUListElement, string>(
const doneItems: string[]doneItems, { group?: string | undefined
The group that the parent belongs to. This is used for allowing multiple parents to transfer nodes between each other.
group
: "todoList",
sortable?: boolean | undefined
Flag for whether or not to allow sorting within a given parent.
sortable
: false,
} ); return ( <JSX.HTMLElementTags.div: JSX.HTMLAttributes<HTMLDivElement>div JSX.HTMLAttributes<HTMLDivElement>.class?: string | undefinedclass="kanban-board"> <JSX.HTMLElementTags.ul: JSX.HTMLAttributes<HTMLUListElement>ul ref?: HTMLUListElement | ((el: HTMLUListElement) => void) | undefinedref={const todoList: Setter<HTMLUListElement | null>todoList}> <
function For<T extends readonly any[], U extends JSX.Element>(props: {
    each: T | undefined | null | false;
    fallback?: JSX.Element;
    children: (item: T[number], index: Accessor<number>) => U;
}): JSX.Element
Creates a list elements from a list it receives a map function as its child that receives a list element and an accessor with the index and returns a JSX-Element; if the list is empty, an optional fallback is returned: ```typescript <For each={items} fallback={<div>No items</div>}> {(item, index) => <div data-index={index()}>{item}</div>} </For> ``` If you have a list with fixed indices and changing values, consider using `<Index>` instead.
@descriptionhttps://docs.solidjs.com/reference/components/for
For
each: false | string[] | null | undefinedeach={const todos: () => string[]todos()}>
{(todo: stringtodo) => <JSX.HTMLElementTags.li: JSX.LiHTMLAttributes<HTMLLIElement>li JSX.HTMLAttributes<T>.class?: string | undefinedclass="kanban-item">{todo: stringtodo}</JSX.HTMLElementTags.li: JSX.LiHTMLAttributes<HTMLLIElement>li>} </
function For<T extends readonly any[], U extends JSX.Element>(props: {
    each: T | undefined | null | false;
    fallback?: JSX.Element;
    children: (item: T[number], index: Accessor<number>) => U;
}): JSX.Element
Creates a list elements from a list it receives a map function as its child that receives a list element and an accessor with the index and returns a JSX-Element; if the list is empty, an optional fallback is returned: ```typescript <For each={items} fallback={<div>No items</div>}> {(item, index) => <div data-index={index()}>{item}</div>} </For> ``` If you have a list with fixed indices and changing values, consider using `<Index>` instead.
@descriptionhttps://docs.solidjs.com/reference/components/for
For
>
</JSX.HTMLElementTags.ul: JSX.HTMLAttributes<HTMLUListElement>ul> <JSX.HTMLElementTags.ul: JSX.HTMLAttributes<HTMLUListElement>ul ref?: HTMLUListElement | ((el: HTMLUListElement) => void) | undefinedref={const doneList: Setter<HTMLUListElement | null>doneList}> <
function For<T extends readonly any[], U extends JSX.Element>(props: {
    each: T | undefined | null | false;
    fallback?: JSX.Element;
    children: (item: T[number], index: Accessor<number>) => U;
}): JSX.Element
Creates a list elements from a list it receives a map function as its child that receives a list element and an accessor with the index and returns a JSX-Element; if the list is empty, an optional fallback is returned: ```typescript <For each={items} fallback={<div>No items</div>}> {(item, index) => <div data-index={index()}>{item}</div>} </For> ``` If you have a list with fixed indices and changing values, consider using `<Index>` instead.
@descriptionhttps://docs.solidjs.com/reference/components/for
For
each: false | string[] | null | undefinedeach={const dones: () => string[]dones()}>
{(done: stringdone) => <JSX.HTMLElementTags.li: JSX.LiHTMLAttributes<HTMLLIElement>li JSX.HTMLAttributes<T>.class?: string | undefinedclass="kanban-item">{done: stringdone}</JSX.HTMLElementTags.li: JSX.LiHTMLAttributes<HTMLLIElement>li>} </
function For<T extends readonly any[], U extends JSX.Element>(props: {
    each: T | undefined | null | false;
    fallback?: JSX.Element;
    children: (item: T[number], index: Accessor<number>) => U;
}): JSX.Element
Creates a list elements from a list it receives a map function as its child that receives a list element and an accessor with the index and returns a JSX-Element; if the list is empty, an optional fallback is returned: ```typescript <For each={items} fallback={<div>No items</div>}> {(item, index) => <div data-index={index()}>{item}</div>} </For> ``` If you have a list with fixed indices and changing values, consider using `<Index>` instead.
@descriptionhttps://docs.solidjs.com/reference/components/for
For
>
</JSX.HTMLElementTags.ul: JSX.HTMLAttributes<HTMLUListElement>ul> </JSX.HTMLElementTags.div: JSX.HTMLAttributes<HTMLDivElement>div> ); }
import { const reactive: <T extends DataSource>(data: T, state?: ReactiveProxyState) => ReactiveProxy<T>
reactive is an alias for r
reactive
, const html: (strings: TemplateStringsArray, ...expSlots: any[]) => ArrowTemplate
html is an alias for t
html
} from "@arrow-js/core";
import { function dragAndDrop<T>({ parent, getValues, setValues, config, }: DragAndDrop<T>): void
Initializes the drag and drop functionality for a given parent.
@paramdragAndDrop - The drag and drop configuration.@returnsvoid
dragAndDrop
} from "@formkit/drag-and-drop";
const
const state: ReactiveProxy<{
    todos: string[];
    dones: string[];
}>
state
=
reactive<{
    todos: string[];
    dones: string[];
}>(data: {
    todos: string[];
    dones: string[];
}, state?: ReactiveProxyState): ReactiveProxy<{
    todos: string[];
    dones: string[];
}>
Given a data object, often an object literal, return a proxy of that object with mutation observers for each property.
@paramdata@returnsReactiveProxy
reactive
({
todos: string[]todos: [ "Schedule perm", "Rewind VHS tapes", "Make change for the arcade", "Get disposable camera developed", "Learn C++", "Return Nintendo Power Glove", ], dones: string[]dones: ["Pickup new mix-tape from Beth"], }); dragAndDrop<string>({ parent, getValues, setValues, config, }: DragAndDrop<string>): void
Initializes the drag and drop functionality for a given parent.
@paramdragAndDrop - The drag and drop configuration.@returnsvoid
dragAndDrop
<string>({
DragAndDrop<string>.parent: HTMLElement
The parent element that will contain the draggable nodes.
parent
: var document: Document
[MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/document)
document
.Document.getElementById(elementId: string): HTMLElement | null
Returns a reference to the first object with the specified value of the ID attribute.
@paramelementId String that specifies the ID value.
getElementById
("todo-list")!,
DragAndDrop<string>.getValues: (parent: HTMLElement) => string[]
A function that returns the values assigned to the parent.
getValues
: () =>
const state: ReactiveProxy<{
    todos: string[];
    dones: string[];
}>
state
.todos: ReactiveProxy<string[]>todos,
DragAndDrop<string>.setValues: (values: string[], parent: HTMLElement) => void
A function that sets the values assigned to the parent.
setValues
: (newValues: string[]newValues) => {
const state: ReactiveProxy<{
    todos: string[];
    dones: string[];
}>
state
.todos: ReactiveProxy<string[]>todos = reactive<string[]>(data: string[], state?: ReactiveProxyState): ReactiveProxy<string[]>
Given a data object, often an object literal, return a proxy of that object with mutation observers for each property.
@paramdata@returnsReactiveProxy
reactive
(newValues: string[]newValues);
}, DragAndDrop<string>.config?: Partial<ParentConfig<string>> | undefined
An optional configuration object.
config
: {
group?: string | undefined
The group that the parent belongs to. This is used for allowing multiple parents to transfer nodes between each other.
group
: "todoList",
sortable?: boolean | undefined
Flag for whether or not to allow sorting within a given parent.
sortable
: false,
}, }); dragAndDrop<string>({ parent, getValues, setValues, config, }: DragAndDrop<string>): void
Initializes the drag and drop functionality for a given parent.
@paramdragAndDrop - The drag and drop configuration.@returnsvoid
dragAndDrop
<string>({
DragAndDrop<string>.parent: HTMLElement
The parent element that will contain the draggable nodes.
parent
: var document: Document
[MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/document)
document
.Document.getElementById(elementId: string): HTMLElement | null
Returns a reference to the first object with the specified value of the ID attribute.
@paramelementId String that specifies the ID value.
getElementById
("done-list")!,
DragAndDrop<string>.getValues: (parent: HTMLElement) => string[]
A function that returns the values assigned to the parent.
getValues
: () =>
const state: ReactiveProxy<{
    todos: string[];
    dones: string[];
}>
state
.dones: ReactiveProxy<string[]>dones,
DragAndDrop<string>.setValues: (values: string[], parent: HTMLElement) => void
A function that sets the values assigned to the parent.
setValues
: (newValues: string[]newValues) => {
const state: ReactiveProxy<{
    todos: string[];
    dones: string[];
}>
state
.dones: ReactiveProxy<string[]>dones = reactive<string[]>(data: string[], state?: ReactiveProxyState): ReactiveProxy<string[]>
Given a data object, often an object literal, return a proxy of that object with mutation observers for each property.
@paramdata@returnsReactiveProxy
reactive
(newValues: string[]newValues);
}, DragAndDrop<string>.config?: Partial<ParentConfig<string>> | undefined
An optional configuration object.
config
: {
group?: string | undefined
The group that the parent belongs to. This is used for allowing multiple parents to transfer nodes between each other.
group
: "todoList",
sortable?: boolean | undefined
Flag for whether or not to allow sorting within a given parent.
sortable
: false,
}, }); const html: (strings: TemplateStringsArray, ...expSlots: any[]) => ArrowTemplate
html is an alias for t
html
`
<div class="kanban-board"> <ul class="kanban-list" id="todo-list"> ${() =>
const state: ReactiveProxy<{
    todos: string[];
    dones: string[];
}>
state
.todos: ReactiveProxy<string[]>todos.Array<string>.map<void>(callbackfn: (value: string, index: number, array: string[]) => void, thisArg?: any): void[]
Calls a defined callback function on each element of an array, and returns an array that contains the results.
@paramcallbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.@paramthisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
map
((todo: stringtodo) =>
const html: (strings: TemplateStringsArray, ...expSlots: any[]) => ArrowTemplate
html is an alias for t
html
`<li class="kanban-item">${todo: stringtodo}</li>`.ArrowTemplate.key: (key: ArrowTemplateKey) => void
Adds a key to this template to identify it as a unique instance.
@paramkey - A unique key that identifies this template instance (not index).@returns
key
(todo: stringtodo)
)} </ul> <ul class="kanban-list" id="done-list"> ${
const state: ReactiveProxy<{
    todos: string[];
    dones: string[];
}>
state
.dones: ReactiveProxy<string[]>dones.Array<string>.map<void>(callbackfn: (value: string, index: number, array: string[]) => void, thisArg?: any): void[]
Calls a defined callback function on each element of an array, and returns an array that contains the results.
@paramcallbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.@paramthisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
map
((done: stringdone) =>
const html: (strings: TemplateStringsArray, ...expSlots: any[]) => ArrowTemplate
html is an alias for t
html
`<li class="kanban-item">${done: stringdone}</li>`.ArrowTemplate.key: (key: ArrowTemplateKey) => void
Adds a key to this template to identify it as a unique instance.
@paramkey - A unique key that identifies this template instance (not index).@returns
key
(done: stringdone)
)} </ul> </div> `(var document: Document
[MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/document)
document
.Document.getElementById(elementId: string): HTMLElement | null
Returns a reference to the first object with the specified value of the ID attribute.
@paramelementId String that specifies the ID value.
getElementById
("app")!);

ToDos

  • Schedule perm
  • Rewind VHS tapes
  • Make change for the arcade
  • Get disposable camera developed
  • Learn C++
  • Return Nintendo Power Glove
["Schedule perm","Rewind VHS tapes","Make change for the arcade","Get disposable camera developed","Learn C++","Return Nintendo Power Glove"]

Complete

  • Pickup new mix-tape from Beth
["Pickup new mix-tape from Beth"]

Accepts

For a more nuanced transfer experience, define the accepts property in the configuration. This property is a callback function that lets you determine whether or not a given element can be transferred into the given list.

  • React
  • Vue
  • Solid
  • Native
import React from "react";
import type { interface ParentConfig<T>
The configuration object for a given parent.
ParentConfig
} from "@formkit/drag-and-drop";
import { function useDragAndDrop<E extends HTMLElement, T = unknown>(list: T[], options?: Partial<ParentConfig<T>>): [React.RefObject<E>, T[], React.Dispatch<React.SetStateAction<T[]>>, (config: Partial<ParentConfig<...>>) => void]
Hook for adding drag and drop/sortable support to a list of items.
@paramlist - Initial list of data.@paramoptions - The drag and drop configuration.@returns
useDragAndDrop
} from "@formkit/drag-and-drop/react";
export default function function myComponent(): React.JSX.ElementmyComponent() { const [const source: React.RefObject<HTMLUListElement>source, const items1: string[]items1] = useDragAndDrop<HTMLUListElement, string>(list: string[], options?: Partial<ParentConfig<string>> | undefined): [React.RefObject<HTMLUListElement>, string[], React.Dispatch<...>, (config: Partial<...>) => void]
Hook for adding drag and drop/sortable support to a list of items.
@paramlist - Initial list of data.@paramoptions - The drag and drop configuration.@returns
useDragAndDrop
<HTMLUListElement, string>(
["dungeon_master.exe", "map_1.dat", "map_2.dat", "character1.txt", "character2.txt", "shell32.dll", "README.txt",], { draggable?: ((child: HTMLElement) => boolean) | undefined
A function that returns whether a given node is draggable.
draggable
: (el: HTMLElementel) => {
return el: HTMLElementel.Element.id: string
Returns the value of element's id content attribute. Can be set to change it. [MDN Reference](https://developer.mozilla.org/docs/Web/API/Element/id)
id
!== "no-drag";
}, } ); const const config1: Partial<ParentConfig<string>>config1: type Partial<T> = { [P in keyof T]?: T[P] | undefined; }
Make all properties in T optional
Partial
<interface ParentConfig<T>
The configuration object for a given parent.
ParentConfig
<string>> = {};
const config1: Partial<ParentConfig<string>>config1.accepts?: ((targetParentData: ParentRecord<string>, initialParentData: ParentRecord<string>, currentParentData: ParentRecord<string>, state: BaseDragState<...>) => boolean) | undefined
A function that returns whether a given parent accepts a given node.
accepts
= (_parent: ParentRecord<string>_parent, lastParent: ParentRecord<string>lastParent) => {
if (lastParent: ParentRecord<string>lastParent.ParentRecord<string>.el: HTMLElementel === const target2: React.RefObject<HTMLElement>target2.React.RefObject<HTMLElement>.current: HTMLElement | null
The current value of the ref.
current
) {
return false; } return const items2: string[]items2.Array<string>.length: number
Gets or sets the length of the array. This is a number one higher than the highest index in the array.
length
< 3;
}; const const config2: Partial<ParentConfig<string>>config2: type Partial<T> = { [P in keyof T]?: T[P] | undefined; }
Make all properties in T optional
Partial
<interface ParentConfig<T>
The configuration object for a given parent.
ParentConfig
<string>> = {};
const config2: Partial<ParentConfig<string>>config2.accepts?: ((targetParentData: ParentRecord<string>, initialParentData: ParentRecord<string>, currentParentData: ParentRecord<string>, state: BaseDragState<...>) => boolean) | undefined
A function that returns whether a given parent accepts a given node.
accepts
= (_parent: ParentRecord<string>_parent, lastParent: ParentRecord<string>lastParent) => {
if (lastParent: ParentRecord<string>lastParent.ParentRecord<string>.el: HTMLElementel === const target1: React.RefObject<HTMLElement>target1.React.RefObject<HTMLElement>.current: HTMLElement | null
The current value of the ref.
current
) {
return false; } return const items3: string[]items3.Array<string>.length: number
Gets or sets the length of the array. This is a number one higher than the highest index in the array.
length
< 5;
}; const [const target1: React.RefObject<HTMLElement>target1, const items2: string[]items2] = useDragAndDrop<HTMLElement, string>(list: string[], options?: Partial<ParentConfig<string>> | undefined): [React.RefObject<HTMLElement>, string[], React.Dispatch<...>, (config: Partial<...>) => void]
Hook for adding drag and drop/sortable support to a list of items.
@paramlist - Initial list of data.@paramoptions - The drag and drop configuration.@returns
useDragAndDrop
(["knight.bmp", "dragon.bmp"], const config1: Partial<ParentConfig<string>>config1);
const [const target2: React.RefObject<HTMLElement>target2, const items3: string[]items3] = useDragAndDrop<HTMLElement, string>(list: string[], options?: Partial<ParentConfig<string>> | undefined): [React.RefObject<HTMLElement>, string[], React.Dispatch<...>, (config: Partial<...>) => void]
Hook for adding drag and drop/sortable support to a list of items.
@paramlist - Initial list of data.@paramoptions - The drag and drop configuration.@returns
useDragAndDrop
(["brick.bmp", "moss.bmp"], const config2: Partial<ParentConfig<string>>config2);
return ( <JSX.IntrinsicElements.div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>div> <JSX.IntrinsicElements.ul: React.DetailedHTMLProps<React.HTMLAttributes<HTMLUListElement>, HTMLUListElement>ul React.RefAttributes<HTMLUListElement>.ref?: React.LegacyRef<HTMLUListElement> | undefined
Allows getting a ref to the component instance. Once the component unmounts, React will set `ref.current` to `null` (or call the ref with `null` if you passed a callback ref).
@see{@link https://react.dev/learn/referencing-values-with-refs#refs-and-the-dom React Docs}
ref
={const source: React.RefObject<HTMLUListElement>source}>
{const items1: string[]items1.Array<string>.map<React.JSX.Element>(callbackfn: (value: string, index: number, array: string[]) => React.JSX.Element, thisArg?: any): React.JSX.Element[]
Calls a defined callback function on each element of an array, and returns an array that contains the results.
@paramcallbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.@paramthisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
map
((item: stringitem) => (
<JSX.IntrinsicElements.li: React.DetailedHTMLProps<React.LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>li React.Attributes.key?: React.Key | null | undefinedkey={item: stringitem}>{item: stringitem}</JSX.IntrinsicElements.li: React.DetailedHTMLProps<React.LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>li> ))} </JSX.IntrinsicElements.ul: React.DetailedHTMLProps<React.HTMLAttributes<HTMLUListElement>, HTMLUListElement>ul> <JSX.IntrinsicElements.ul: React.DetailedHTMLProps<React.HTMLAttributes<HTMLUListElement>, HTMLUListElement>ul React.RefAttributes<HTMLUListElement>.ref?: React.LegacyRef<HTMLUListElement> | undefined
Allows getting a ref to the component instance. Once the component unmounts, React will set `ref.current` to `null` (or call the ref with `null` if you passed a callback ref).
@see{@link https://react.dev/learn/referencing-values-with-refs#refs-and-the-dom React Docs}
ref
="target1">
{const items2: string[]items2.Array<string>.map<React.JSX.Element>(callbackfn: (value: string, index: number, array: string[]) => React.JSX.Element, thisArg?: any): React.JSX.Element[]
Calls a defined callback function on each element of an array, and returns an array that contains the results.
@paramcallbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.@paramthisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
map
((item: stringitem) => (
<JSX.IntrinsicElements.li: React.DetailedHTMLProps<React.LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>li React.Attributes.key?: React.Key | null | undefinedkey={item: stringitem}>{item: stringitem}</JSX.IntrinsicElements.li: React.DetailedHTMLProps<React.LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>li> ))} </JSX.IntrinsicElements.ul: React.DetailedHTMLProps<React.HTMLAttributes<HTMLUListElement>, HTMLUListElement>ul> <JSX.IntrinsicElements.ul: React.DetailedHTMLProps<React.HTMLAttributes<HTMLUListElement>, HTMLUListElement>ul React.RefAttributes<HTMLUListElement>.ref?: React.LegacyRef<HTMLUListElement> | undefined
Allows getting a ref to the component instance. Once the component unmounts, React will set `ref.current` to `null` (or call the ref with `null` if you passed a callback ref).
@see{@link https://react.dev/learn/referencing-values-with-refs#refs-and-the-dom React Docs}
ref
="target2">
{const items3: string[]items3.Array<string>.map<React.JSX.Element>(callbackfn: (value: string, index: number, array: string[]) => React.JSX.Element, thisArg?: any): React.JSX.Element[]
Calls a defined callback function on each element of an array, and returns an array that contains the results.
@paramcallbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.@paramthisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
map
((item: stringitem) => (
<JSX.IntrinsicElements.li: React.DetailedHTMLProps<React.LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>li React.Attributes.key?: React.Key | null | undefinedkey={item: stringitem}>{item: stringitem}</JSX.IntrinsicElements.li: React.DetailedHTMLProps<React.LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>li> ))} </JSX.IntrinsicElements.ul: React.DetailedHTMLProps<React.HTMLAttributes<HTMLUListElement>, HTMLUListElement>ul> </JSX.IntrinsicElements.div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>div> ); }
<script setup lang="ts">
import type { interface ParentConfig<T>
The configuration object for a given parent.
ParentConfig
} from "@formkit/drag-and-drop";
import { function useDragAndDrop<T>(initialValues: T[], options?: Partial<VueParentConfig<T>>): [Ref<HTMLElement | undefined>, Ref<T[]>, (config: Partial<VueParentConfig<T>>) => void]
Creates a new instance of drag and drop and returns the parent element and a ref of the values to use in your template.
@paraminitialValues - The initial values of the parent element.@returnsThe parent element and values for drag and drop.
useDragAndDrop
} from "@formkit/drag-and-drop/vue";
const [const source: Ref<HTMLElement | undefined, HTMLElement | undefined>source, const items1: Ref<string[], string[]>items1] = useDragAndDrop<string>(initialValues: string[], options?: Partial<Partial<ParentConfig<string>>> | undefined): [Ref<HTMLElement | undefined, HTMLElement | undefined>, Ref<...>, (config: Partial<...>) => void]
Creates a new instance of drag and drop and returns the parent element and a ref of the values to use in your template.
@paraminitialValues - The initial values of the parent element.@returnsThe parent element and values for drag and drop.
useDragAndDrop
(
["dungeon_master.exe", "map_1.dat", "map_2.dat", "character1.txt", "character2.txt", "shell32.dll", "README.txt"], { accepts?: ((targetParentData: ParentRecord<string>, initialParentData: ParentRecord<string>, currentParentData: ParentRecord<string>, state: BaseDragState<...>) => boolean) | undefined
A function that returns whether a given parent accepts a given node.
accepts
: () => {
return true; }, } ); const const config1: Partial<ParentConfig<string>>config1: type Partial<T> = { [P in keyof T]?: T[P] | undefined; }
Make all properties in T optional
Partial
<interface ParentConfig<T>
The configuration object for a given parent.
ParentConfig
<string>> = {};
const config1: Partial<ParentConfig<string>>config1.accepts?: ((targetParentData: ParentRecord<string>, initialParentData: ParentRecord<string>, currentParentData: ParentRecord<string>, state: BaseDragState<...>) => boolean) | undefined
A function that returns whether a given parent accepts a given node.
accepts
= (_parent: ParentRecord<string>_parent, lastParent: ParentRecord<string>lastParent) => {
if (lastParent: ParentRecord<string>lastParent.ParentRecord<string>.el: HTMLElementel === const target2: Ref<HTMLElement | undefined, HTMLElement | undefined>target2.Ref<HTMLElement | undefined, HTMLElement | undefined>.value: HTMLElement | undefinedvalue) { return false; } return const items2: Ref<string[], string[]>items2.Ref<string[], string[]>.value: string[]value.Array<T>.length: number
Gets or sets the length of the array. This is a number one higher than the highest index in the array.
length
< 3;
}; const const config2: Partial<ParentConfig<string>>config2: type Partial<T> = { [P in keyof T]?: T[P] | undefined; }
Make all properties in T optional
Partial
<interface ParentConfig<T>
The configuration object for a given parent.
ParentConfig
<string>> = {};
const config2: Partial<ParentConfig<string>>config2.accepts?: ((targetParentData: ParentRecord<string>, initialParentData: ParentRecord<string>, currentParentData: ParentRecord<string>, state: BaseDragState<...>) => boolean) | undefined
A function that returns whether a given parent accepts a given node.
accepts
= (_parent: ParentRecord<string>_parent, lastParent: ParentRecord<string>lastParent) => {
if (lastParent: ParentRecord<string>lastParent.ParentRecord<string>.el: HTMLElementel === const target1: Ref<HTMLElement | undefined, HTMLElement | undefined>target1.Ref<HTMLElement | undefined, HTMLElement | undefined>.value: HTMLElement | undefinedvalue) { return false; } return const items3: Ref<string[], string[]>items3.Ref<string[], string[]>.value: string[]value.Array<T>.length: number
Gets or sets the length of the array. This is a number one higher than the highest index in the array.
length
< 5;
}; const [const target1: Ref<HTMLElement | undefined, HTMLElement | undefined>target1, const items2: Ref<string[], string[]>items2] = useDragAndDrop<string>(initialValues: string[], options?: Partial<Partial<ParentConfig<string>>> | undefined): [Ref<HTMLElement | undefined, HTMLElement | undefined>, Ref<...>, (config: Partial<...>) => void]
Creates a new instance of drag and drop and returns the parent element and a ref of the values to use in your template.
@paraminitialValues - The initial values of the parent element.@returnsThe parent element and values for drag and drop.
useDragAndDrop
(["knight.bmp", "dragon.bmp"], const config1: Partial<ParentConfig<string>>config1);
const [const target2: Ref<HTMLElement | undefined, HTMLElement | undefined>target2, const items3: Ref<string[], string[]>items3] = useDragAndDrop<string>(initialValues: string[], options?: Partial<Partial<ParentConfig<string>>> | undefined): [Ref<HTMLElement | undefined, HTMLElement | undefined>, Ref<...>, (config: Partial<...>) => void]
Creates a new instance of drag and drop and returns the parent element and a ref of the values to use in your template.
@paraminitialValues - The initial values of the parent element.@returnsThe parent element and values for drag and drop.
useDragAndDrop
(["brick.bmp", "moss.bmp"], const config2: Partial<ParentConfig<string>>config2);
</script> <template> <div: HTMLAttributes & ReservedPropsdiv name: stringname="accepts"> <div: HTMLAttributes & ReservedPropsdiv HTMLAttributes.class?: anyclass="flex justify-between"> <div: HTMLAttributes & ReservedPropsdiv> <ul: HTMLAttributes & ReservedPropsul ref?: VNodeRef | undefinedref="const source: Ref<HTMLElement | undefined, HTMLElement | undefined>source"> <li: LiHTMLAttributes & ReservedPropsli v-for="const item: stringitem in const items1: Ref<string[], string[]>items1" key?: PropertyKey | undefined:key?: PropertyKey | undefinedkey="const item: stringitem">{{ const item: stringitem }}</li: LiHTMLAttributes & ReservedPropsli> </ul: HTMLAttributes & ReservedPropsul> </div: HTMLAttributes & ReservedPropsdiv> <div: HTMLAttributes & ReservedPropsdiv HTMLAttributes.class?: anyclass="flex flex-col"> <div: HTMLAttributes & ReservedPropsdiv> <h5: HTMLAttributes & ReservedPropsh5>I can accept up to three items</h5: HTMLAttributes & ReservedPropsh5> <ul: HTMLAttributes & ReservedPropsul ref?: VNodeRef | undefinedref="const target1: Ref<HTMLElement | undefined, HTMLElement | undefined>target1" HTMLAttributes.class?: anyclass="border-solid border-2 border-indigo-600"> <li: LiHTMLAttributes & ReservedPropsli v-for="const item: stringitem in const items2: Ref<string[], string[]>items2" key?: PropertyKey | undefined:key?: PropertyKey | undefinedkey="const item: stringitem">{{ const item: stringitem }}</li: LiHTMLAttributes & ReservedPropsli> </ul: HTMLAttributes & ReservedPropsul> </div: HTMLAttributes & ReservedPropsdiv> <div: HTMLAttributes & ReservedPropsdiv> I can accept up to five items. <ul: HTMLAttributes & ReservedPropsul ref?: VNodeRef | undefinedref="const target2: Ref<HTMLElement | undefined, HTMLElement | undefined>target2" HTMLAttributes.class?: anyclass="border-solid border-2 border-indigo-600"> <li: LiHTMLAttributes & ReservedPropsli v-for="const item: stringitem in const items3: Ref<string[], string[]>items3" key?: PropertyKey | undefined:key?: PropertyKey | undefinedkey="const item: stringitem">{{ const item: stringitem }}</li: LiHTMLAttributes & ReservedPropsli> </ul: HTMLAttributes & ReservedPropsul> </div: HTMLAttributes & ReservedPropsdiv> </div: HTMLAttributes & ReservedPropsdiv> </div: HTMLAttributes & ReservedPropsdiv> </div: HTMLAttributes & ReservedPropsdiv> </template>
/** @jsxImportSource solid-js */
import type { interface ParentConfig<T>
The configuration object for a given parent.
ParentConfig
} from "@formkit/drag-and-drop";
import {
function For<T extends readonly any[], U extends JSX.Element>(props: {
    each: T | undefined | null | false;
    fallback?: JSX.Element;
    children: (item: T[number], index: Accessor<number>) => U;
}): JSX.Element
Creates a list elements from a list it receives a map function as its child that receives a list element and an accessor with the index and returns a JSX-Element; if the list is empty, an optional fallback is returned: ```typescript <For each={items} fallback={<div>No items</div>}> {(item, index) => <div data-index={index()}>{item}</div>} </For> ``` If you have a list with fixed indices and changing values, consider using `<Index>` instead.
@descriptionhttps://docs.solidjs.com/reference/components/for
For
} from "solid-js";
import { function useDragAndDrop<E extends HTMLElement, T = unknown>(initValues: T[], options?: Partial<ParentConfig<T>>): [Setter<E | null>, Accessor<Store<T[]>>, ReturnType<typeof createStore>[1], (config?: Partial<ParentConfig<T>>) => void]
Hook for adding drag and drop/sortable support to a list of items.
@paraminitValues - Initial list of data.@paramoptions - The drag and drop configuration.@returns
useDragAndDrop
} from "@formkit/drag-and-drop/solid";
export default function function MyComponent(): JSX.ElementMyComponent() { const [const source: Setter<HTMLUListElement | null>source, const items1: Accessor<string[]>items1] = useDragAndDrop<HTMLUListElement, string>(initValues: string[], options?: Partial<ParentConfig<string>> | undefined): [Setter<HTMLUListElement | null>, Accessor<...>, SetStoreFunction<...>, (config?: Partial<...> | undefined) => void]
Hook for adding drag and drop/sortable support to a list of items.
@paraminitValues - Initial list of data.@paramoptions - The drag and drop configuration.@returns
useDragAndDrop
<HTMLUListElement, string>(
[ "dungeon_master.exe", "map_1.dat", "map_2.dat", "character1.txt", "character2.txt", "shell32.dll", "README.txt", ], { draggable?: ((child: HTMLElement) => boolean) | undefined
A function that returns whether a given node is draggable.
draggable
: (el: HTMLElementel) => {
return el: HTMLElementel.Element.id: string
Returns the value of element's id content attribute. Can be set to change it. [MDN Reference](https://developer.mozilla.org/docs/Web/API/Element/id)
id
!== "no-drag";
}, } ); const const config1: Partial<ParentConfig<string>>config1: type Partial<T> = { [P in keyof T]?: T[P] | undefined; }
Make all properties in T optional
Partial
<interface ParentConfig<T>
The configuration object for a given parent.
ParentConfig
<string>> = {};
const config1: Partial<ParentConfig<string>>config1.accepts?: ((targetParentData: ParentRecord<string>, initialParentData: ParentRecord<string>, currentParentData: ParentRecord<string>, state: BaseDragState<...>) => boolean) | undefined
A function that returns whether a given parent accepts a given node.
accepts
= (_parent: ParentRecord<string>_parent, lastParent: ParentRecord<string>lastParent) => {
if ( const target2: Setter<HTMLElement | null>target2 && const target2: Setter<HTMLElement | null>target2 instanceof
var HTMLElement: {
    new (): HTMLElement;
    prototype: HTMLElement;
}
Any HTML element. Some elements directly implement this interface, while others implement it via an interface that inherits it. [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLElement)
HTMLElement
&&
lastParent: ParentRecord<string>lastParent.ParentRecord<string>.el: HTMLElementel === const target2: Setter<HTMLElement | null> & HTMLElementtarget2 ) { return false; } return const items2: () => string[]items2().Array<string>.length: number
Gets or sets the length of the array. This is a number one higher than the highest index in the array.
length
< 3;
}; const const config2: Partial<ParentConfig<string>>config2: type Partial<T> = { [P in keyof T]?: T[P] | undefined; }
Make all properties in T optional
Partial
<interface ParentConfig<T>
The configuration object for a given parent.
ParentConfig
<string>> = {};
const config2: Partial<ParentConfig<string>>config2.accepts?: ((targetParentData: ParentRecord<string>, initialParentData: ParentRecord<string>, currentParentData: ParentRecord<string>, state: BaseDragState<...>) => boolean) | undefined
A function that returns whether a given parent accepts a given node.
accepts
= (_parent: ParentRecord<string>_parent, lastParent: ParentRecord<string>lastParent) => {
if ( const target1: Setter<HTMLElement | null>target1 && const target1: Setter<HTMLElement | null>target1 instanceof
var HTMLElement: {
    new (): HTMLElement;
    prototype: HTMLElement;
}
Any HTML element. Some elements directly implement this interface, while others implement it via an interface that inherits it. [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLElement)
HTMLElement
&&
lastParent: ParentRecord<string>lastParent.ParentRecord<string>.el: HTMLElementel === const target1: Setter<HTMLElement | null> & HTMLElementtarget1 ) { return false; } return const items3: () => string[]items3().Array<string>.length: number
Gets or sets the length of the array. This is a number one higher than the highest index in the array.
length
< 5;
}; const [const target1: Setter<HTMLElement | null>target1, const items2: Accessor<string[]>items2] = useDragAndDrop<HTMLElement, string>(initValues: string[], options?: Partial<ParentConfig<string>> | undefined): [Setter<HTMLElement | null>, Accessor<...>, SetStoreFunction<...>, (config?: Partial<...> | undefined) => void]
Hook for adding drag and drop/sortable support to a list of items.
@paraminitValues - Initial list of data.@paramoptions - The drag and drop configuration.@returns
useDragAndDrop
(
["knight.bmp", "dragon.bmp"], const config1: Partial<ParentConfig<string>>config1 ); const [const target2: Setter<HTMLElement | null>target2, const items3: Accessor<string[]>items3] = useDragAndDrop<HTMLElement, string>(initValues: string[], options?: Partial<ParentConfig<string>> | undefined): [Setter<HTMLElement | null>, Accessor<...>, SetStoreFunction<...>, (config?: Partial<...> | undefined) => void]
Hook for adding drag and drop/sortable support to a list of items.
@paraminitValues - Initial list of data.@paramoptions - The drag and drop configuration.@returns
useDragAndDrop
(["brick.bmp", "moss.bmp"], const config2: Partial<ParentConfig<string>>config2);
return ( <JSX.HTMLElementTags.div: JSX.HTMLAttributes<HTMLDivElement>div> <JSX.HTMLElementTags.ul: JSX.HTMLAttributes<HTMLUListElement>ul ref?: HTMLUListElement | ((el: HTMLUListElement) => void) | undefinedref={const source: Setter<HTMLUListElement | null>source}> <
function For<T extends readonly any[], U extends JSX.Element>(props: {
    each: T | undefined | null | false;
    fallback?: JSX.Element;
    children: (item: T[number], index: Accessor<number>) => U;
}): JSX.Element
Creates a list elements from a list it receives a map function as its child that receives a list element and an accessor with the index and returns a JSX-Element; if the list is empty, an optional fallback is returned: ```typescript <For each={items} fallback={<div>No items</div>}> {(item, index) => <div data-index={index()}>{item}</div>} </For> ``` If you have a list with fixed indices and changing values, consider using `<Index>` instead.
@descriptionhttps://docs.solidjs.com/reference/components/for
For
each: false | string[] | null | undefinedeach={const items1: () => string[]items1()}>{(item: stringitem) => <JSX.HTMLElementTags.li: JSX.LiHTMLAttributes<HTMLLIElement>li>{item: stringitem}</JSX.HTMLElementTags.li: JSX.LiHTMLAttributes<HTMLLIElement>li>}</
function For<T extends readonly any[], U extends JSX.Element>(props: {
    each: T | undefined | null | false;
    fallback?: JSX.Element;
    children: (item: T[number], index: Accessor<number>) => U;
}): JSX.Element
Creates a list elements from a list it receives a map function as its child that receives a list element and an accessor with the index and returns a JSX-Element; if the list is empty, an optional fallback is returned: ```typescript <For each={items} fallback={<div>No items</div>}> {(item, index) => <div data-index={index()}>{item}</div>} </For> ``` If you have a list with fixed indices and changing values, consider using `<Index>` instead.
@descriptionhttps://docs.solidjs.com/reference/components/for
For
>
</JSX.HTMLElementTags.ul: JSX.HTMLAttributes<HTMLUListElement>ul> <JSX.HTMLElementTags.ul: JSX.HTMLAttributes<HTMLUListElement>ul ref?: HTMLUListElement | ((el: HTMLUListElement) => void) | undefinedref={const target1: Setter<HTMLElement | null>target1}> <
function For<T extends readonly any[], U extends JSX.Element>(props: {
    each: T | undefined | null | false;
    fallback?: JSX.Element;
    children: (item: T[number], index: Accessor<number>) => U;
}): JSX.Element
Creates a list elements from a list it receives a map function as its child that receives a list element and an accessor with the index and returns a JSX-Element; if the list is empty, an optional fallback is returned: ```typescript <For each={items} fallback={<div>No items</div>}> {(item, index) => <div data-index={index()}>{item}</div>} </For> ``` If you have a list with fixed indices and changing values, consider using `<Index>` instead.
@descriptionhttps://docs.solidjs.com/reference/components/for
For
each: false | string[] | null | undefinedeach={const items2: () => string[]items2()}>{(item: stringitem) => <JSX.HTMLElementTags.li: JSX.LiHTMLAttributes<HTMLLIElement>li>{item: stringitem}</JSX.HTMLElementTags.li: JSX.LiHTMLAttributes<HTMLLIElement>li>}</
function For<T extends readonly any[], U extends JSX.Element>(props: {
    each: T | undefined | null | false;
    fallback?: JSX.Element;
    children: (item: T[number], index: Accessor<number>) => U;
}): JSX.Element
Creates a list elements from a list it receives a map function as its child that receives a list element and an accessor with the index and returns a JSX-Element; if the list is empty, an optional fallback is returned: ```typescript <For each={items} fallback={<div>No items</div>}> {(item, index) => <div data-index={index()}>{item}</div>} </For> ``` If you have a list with fixed indices and changing values, consider using `<Index>` instead.
@descriptionhttps://docs.solidjs.com/reference/components/for
For
>
</JSX.HTMLElementTags.ul: JSX.HTMLAttributes<HTMLUListElement>ul> <JSX.HTMLElementTags.ul: JSX.HTMLAttributes<HTMLUListElement>ul ref?: HTMLUListElement | ((el: HTMLUListElement) => void) | undefinedref={const target2: Setter<HTMLElement | null>target2}> <
function For<T extends readonly any[], U extends JSX.Element>(props: {
    each: T | undefined | null | false;
    fallback?: JSX.Element;
    children: (item: T[number], index: Accessor<number>) => U;
}): JSX.Element
Creates a list elements from a list it receives a map function as its child that receives a list element and an accessor with the index and returns a JSX-Element; if the list is empty, an optional fallback is returned: ```typescript <For each={items} fallback={<div>No items</div>}> {(item, index) => <div data-index={index()}>{item}</div>} </For> ``` If you have a list with fixed indices and changing values, consider using `<Index>` instead.
@descriptionhttps://docs.solidjs.com/reference/components/for
For
each: false | string[] | null | undefinedeach={const items3: () => string[]items3()}>{(item: stringitem) => <JSX.HTMLElementTags.li: JSX.LiHTMLAttributes<HTMLLIElement>li>{item: stringitem}</JSX.HTMLElementTags.li: JSX.LiHTMLAttributes<HTMLLIElement>li>}</
function For<T extends readonly any[], U extends JSX.Element>(props: {
    each: T | undefined | null | false;
    fallback?: JSX.Element;
    children: (item: T[number], index: Accessor<number>) => U;
}): JSX.Element
Creates a list elements from a list it receives a map function as its child that receives a list element and an accessor with the index and returns a JSX-Element; if the list is empty, an optional fallback is returned: ```typescript <For each={items} fallback={<div>No items</div>}> {(item, index) => <div data-index={index()}>{item}</div>} </For> ``` If you have a list with fixed indices and changing values, consider using `<Index>` instead.
@descriptionhttps://docs.solidjs.com/reference/components/for
For
>
</JSX.HTMLElementTags.ul: JSX.HTMLAttributes<HTMLUListElement>ul> </JSX.HTMLElementTags.div: JSX.HTMLAttributes<HTMLDivElement>div> ); }
import { const reactive: <T extends DataSource>(data: T, state?: ReactiveProxyState) => ReactiveProxy<T>
reactive is an alias for r
reactive
, const html: (strings: TemplateStringsArray, ...expSlots: any[]) => ArrowTemplate
html is an alias for t
html
} from "@arrow-js/core";
import { function dragAndDrop<T>({ parent, getValues, setValues, config, }: DragAndDrop<T>): void
Initializes the drag and drop functionality for a given parent.
@paramdragAndDrop - The drag and drop configuration.@returnsvoid
dragAndDrop
} from "@formkit/drag-and-drop";
const
const state: ReactiveProxy<{
    items1: string[];
    items2: string[];
    items3: string[];
}>
state
=
reactive<{
    items1: string[];
    items2: string[];
    items3: string[];
}>(data: {
    items1: string[];
    items2: string[];
    items3: string[];
}, state?: ReactiveProxyState): ReactiveProxy<{
    items1: string[];
    items2: string[];
    items3: string[];
}>
Given a data object, often an object literal, return a proxy of that object with mutation observers for each property.
@paramdata@returnsReactiveProxy
reactive
({
items1: string[]items1: ["dungeon_master.exe", "map_1.dat", "map_2.dat", "character1.txt", "character2.txt", "shell32.dll", "README.txt"], items2: string[]items2: ["knight.bmp", "dragon.bmp"], items3: string[]items3: ["brick.bmp", "moss.bmp"], }); dragAndDrop<string>({ parent, getValues, setValues, config, }: DragAndDrop<string>): void
Initializes the drag and drop functionality for a given parent.
@paramdragAndDrop - The drag and drop configuration.@returnsvoid
dragAndDrop
<string>({
DragAndDrop<string>.parent: HTMLElement
The parent element that will contain the draggable nodes.
parent
: var document: Document
[MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/document)
document
.Document.getElementById(elementId: string): HTMLElement | null
Returns a reference to the first object with the specified value of the ID attribute.
@paramelementId String that specifies the ID value.
getElementById
("source")!,
DragAndDrop<string>.getValues: (parent: HTMLElement) => string[]
A function that returns the values assigned to the parent.
getValues
: () =>
const state: ReactiveProxy<{
    items1: string[];
    items2: string[];
    items3: string[];
}>
state
.items1: ReactiveProxy<string[]>items1,
DragAndDrop<string>.setValues: (values: string[], parent: HTMLElement) => void
A function that sets the values assigned to the parent.
setValues
: (newValues: string[]newValues) => {
const state: ReactiveProxy<{
    items1: string[];
    items2: string[];
    items3: string[];
}>
state
.items1: ReactiveProxy<string[]>items1 = reactive<string[]>(data: string[], state?: ReactiveProxyState): ReactiveProxy<string[]>
Given a data object, often an object literal, return a proxy of that object with mutation observers for each property.
@paramdata@returnsReactiveProxy
reactive
(newValues: string[]newValues);
}, DragAndDrop<string>.config?: Partial<ParentConfig<string>> | undefined
An optional configuration object.
config
: {
accepts?: ((targetParentData: ParentRecord<string>, initialParentData: ParentRecord<string>, currentParentData: ParentRecord<string>, state: BaseDragState<...>) => boolean) | undefined
A function that returns whether a given parent accepts a given node.
accepts
: () => {
return true; }, }, }); dragAndDrop<string>({ parent, getValues, setValues, config, }: DragAndDrop<string>): void
Initializes the drag and drop functionality for a given parent.
@paramdragAndDrop - The drag and drop configuration.@returnsvoid
dragAndDrop
<string>({
DragAndDrop<string>.parent: HTMLElement
The parent element that will contain the draggable nodes.
parent
: var document: Document
[MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/document)
document
.Document.getElementById(elementId: string): HTMLElement | null
Returns a reference to the first object with the specified value of the ID attribute.
@paramelementId String that specifies the ID value.
getElementById
("target1")!,
DragAndDrop<string>.getValues: (parent: HTMLElement) => string[]
A function that returns the values assigned to the parent.
getValues
: () =>
const state: ReactiveProxy<{
    items1: string[];
    items2: string[];
    items3: string[];
}>
state
.items2: ReactiveProxy<string[]>items2,
DragAndDrop<string>.setValues: (values: string[], parent: HTMLElement) => void
A function that sets the values assigned to the parent.
setValues
: (newValues: string[]newValues) => {
const state: ReactiveProxy<{
    items1: string[];
    items2: string[];
    items3: string[];
}>
state
.items2: ReactiveProxy<string[]>items2 = reactive<string[]>(data: string[], state?: ReactiveProxyState): ReactiveProxy<string[]>
Given a data object, often an object literal, return a proxy of that object with mutation observers for each property.
@paramdata@returnsReactiveProxy
reactive
(newValues: string[]newValues);
}, DragAndDrop<string>.config?: Partial<ParentConfig<string>> | undefined
An optional configuration object.
config
: {
accepts?: ((targetParentData: ParentRecord<string>, initialParentData: ParentRecord<string>, currentParentData: ParentRecord<string>, state: BaseDragState<...>) => boolean) | undefined
A function that returns whether a given parent accepts a given node.
accepts
: () => {
return
const state: ReactiveProxy<{
    items1: string[];
    items2: string[];
    items3: string[];
}>
state
.items1: ReactiveProxy<string[]>items1.Array<T>.length: number
Gets or sets the length of the array. This is a number one higher than the highest index in the array.
length
< 3;
}, }, }); dragAndDrop<string>({ parent, getValues, setValues, config, }: DragAndDrop<string>): void
Initializes the drag and drop functionality for a given parent.
@paramdragAndDrop - The drag and drop configuration.@returnsvoid
dragAndDrop
<string>({
DragAndDrop<string>.parent: HTMLElement
The parent element that will contain the draggable nodes.
parent
: var document: Document
[MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/document)
document
.Document.getElementById(elementId: string): HTMLElement | null
Returns a reference to the first object with the specified value of the ID attribute.
@paramelementId String that specifies the ID value.
getElementById
("target2")!,
DragAndDrop<string>.getValues: (parent: HTMLElement) => string[]
A function that returns the values assigned to the parent.
getValues
: () =>
const state: ReactiveProxy<{
    items1: string[];
    items2: string[];
    items3: string[];
}>
state
.items3: ReactiveProxy<string[]>items3,
DragAndDrop<string>.setValues: (values: string[], parent: HTMLElement) => void
A function that sets the values assigned to the parent.
setValues
: (newValues: string[]newValues) => {
const state: ReactiveProxy<{
    items1: string[];
    items2: string[];
    items3: string[];
}>
state
.items3: ReactiveProxy<string[]>items3 = reactive<string[]>(data: string[], state?: ReactiveProxyState): ReactiveProxy<string[]>
Given a data object, often an object literal, return a proxy of that object with mutation observers for each property.
@paramdata@returnsReactiveProxy
reactive
(newValues: string[]newValues);
}, DragAndDrop<string>.config?: Partial<ParentConfig<string>> | undefined
An optional configuration object.
config
: {
accepts?: ((targetParentData: ParentRecord<string>, initialParentData: ParentRecord<string>, currentParentData: ParentRecord<string>, state: BaseDragState<...>) => boolean) | undefined
A function that returns whether a given parent accepts a given node.
accepts
: () => {
return
const state: ReactiveProxy<{
    items1: string[];
    items2: string[];
    items3: string[];
}>
state
.items1: ReactiveProxy<string[]>items1.Array<T>.length: number
Gets or sets the length of the array. This is a number one higher than the highest index in the array.
length
< 3;
}, }, }); const html: (strings: TemplateStringsArray, ...expSlots: any[]) => ArrowTemplate
html is an alias for t
html
`
<div> <ul id="source"> ${
const state: ReactiveProxy<{
    items1: string[];
    items2: string[];
    items3: string[];
}>
state
.items1: ReactiveProxy<string[]>items1.Array<string>.map<ArrowTemplate>(callbackfn: (value: string, index: number, array: string[]) => ArrowTemplate, thisArg?: any): ArrowTemplate[]
Calls a defined callback function on each element of an array, and returns an array that contains the results.
@paramcallbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.@paramthisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
map
((item: stringitem) => const html: (strings: TemplateStringsArray, ...expSlots: any[]) => ArrowTemplate
html is an alias for t
html
`<li>${item: stringitem}</li>`)}
</ul> <div> <h5>I can accept up to three items</h5> <ul id="target1"> ${
const state: ReactiveProxy<{
    items1: string[];
    items2: string[];
    items3: string[];
}>
state
.items2: ReactiveProxy<string[]>items2.Array<string>.map<ArrowTemplate>(callbackfn: (value: string, index: number, array: string[]) => ArrowTemplate, thisArg?: any): ArrowTemplate[]
Calls a defined callback function on each element of an array, and returns an array that contains the results.
@paramcallbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.@paramthisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
map
((item: stringitem) => const html: (strings: TemplateStringsArray, ...expSlots: any[]) => ArrowTemplate
html is an alias for t
html
`<li>${item: stringitem}</li>`)}
</ul> <h5>I can accept up to five items</h5> <ul id="target2"> ${
const state: ReactiveProxy<{
    items1: string[];
    items2: string[];
    items3: string[];
}>
state
.items2: ReactiveProxy<string[]>items2.Array<string>.map<ArrowTemplate>(callbackfn: (value: string, index: number, array: string[]) => ArrowTemplate, thisArg?: any): ArrowTemplate[]
Calls a defined callback function on each element of an array, and returns an array that contains the results.
@paramcallbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.@paramthisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
map
((item: stringitem) => const html: (strings: TemplateStringsArray, ...expSlots: any[]) => ArrowTemplate
html is an alias for t
html
`<li>${item: stringitem}</li>`)}
</ul> </div> </div> `(var document: Document
[MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/document)
document
.Document.getElementById(elementId: string): HTMLElement | null
Returns a reference to the first object with the specified value of the ID attribute.
@paramelementId String that specifies the ID value.
getElementById
("app")!);
  • dungeon_master.exe
  • map_1.dat
  • map_2.dat
  • character1.txt
  • character2.txt
  • shell32.dll
  • README.txt
I can accept 3 items
  • knight.bmp
  • dragon.bmp
I can accept 5 items.
  • brick.bmp
  • moss.bmp

Drag Handles

Drag handles are a common way to allow users to drag items without accidentally dragging them when they don't intend to. To implement drag handles, set the dragHandle property to a selector that will be used to find the handle.

  • React
  • Vue
  • Solid
  • Native
import React from "react";
import { function useDragAndDrop<E extends HTMLElement, T = unknown>(list: T[], options?: Partial<ParentConfig<T>>): [React.RefObject<E>, T[], React.Dispatch<React.SetStateAction<T[]>>, (config: Partial<ParentConfig<...>>) => void]
Hook for adding drag and drop/sortable support to a list of items.
@paramlist - Initial list of data.@paramoptions - The drag and drop configuration.@returns
useDragAndDrop
} from "@formkit/drag-and-drop/react";
export function function myComponent(): React.JSX.ElementmyComponent() { const const todoItems: string[]todoItems = ["Schedule perm", "Rewind VHS tapes", "Make change for the arcade", "Get disposable camera developed", "Learn C++", "Return Nintendo Power Glove"]; const const doneItems: string[]doneItems = ["Pickup new mix-tape from Beth", "Implement drag handles"]; const [const todoList: React.RefObject<HTMLUListElement>todoList, const todos: string[]todos] = useDragAndDrop<HTMLUListElement, string>(list: string[], options?: Partial<ParentConfig<string>> | undefined): [React.RefObject<HTMLUListElement>, string[], React.Dispatch<...>, (config: Partial<...>) => void]
Hook for adding drag and drop/sortable support to a list of items.
@paramlist - Initial list of data.@paramoptions - The drag and drop configuration.@returns
useDragAndDrop
<HTMLUListElement, string>(
const todoItems: string[]todoItems, { group?: string | undefined
The group that the parent belongs to. This is used for allowing multiple parents to transfer nodes between each other.
group
: "todoList",
dragHandle?: string | undefined
A selector for the drag handle. Will search at any depth within the draggable element.
dragHandle
: ".kanban-handle"
} ); const [const doneList: React.RefObject<HTMLUListElement>doneList, const dones: string[]dones] = useDragAndDrop<HTMLUListElement, string>(list: string[], options?: Partial<ParentConfig<string>> | undefined): [React.RefObject<HTMLUListElement>, string[], React.Dispatch<...>, (config: Partial<...>) => void]
Hook for adding drag and drop/sortable support to a list of items.
@paramlist - Initial list of data.@paramoptions - The drag and drop configuration.@returns
useDragAndDrop
<HTMLUListElement, string>(
const doneItems: string[]doneItems, { group?: string | undefined
The group that the parent belongs to. This is used for allowing multiple parents to transfer nodes between each other.
group
: "todoList",
dragHandle?: string | undefined
A selector for the drag handle. Will search at any depth within the draggable element.
dragHandle
: ".kanban-handle"
} ); return ( <JSX.IntrinsicElements.div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>div React.HTMLAttributes<HTMLDivElement>.className?: string | undefinedclassName="kanban-board"> <JSX.IntrinsicElements.ul: React.DetailedHTMLProps<React.HTMLAttributes<HTMLUListElement>, HTMLUListElement>ul React.RefAttributes<HTMLUListElement>.ref?: React.LegacyRef<HTMLUListElement> | undefined
Allows getting a ref to the component instance. Once the component unmounts, React will set `ref.current` to `null` (or call the ref with `null` if you passed a callback ref).
@see{@link https://react.dev/learn/referencing-values-with-refs#refs-and-the-dom React Docs}
ref
={const todoList: React.RefObject<HTMLUListElement>todoList} React.HTMLAttributes<T>.className?: string | undefinedclassName="kanban-column">
{const todos: string[]todos.Array<string>.map<React.JSX.Element>(callbackfn: (value: string, index: number, array: string[]) => React.JSX.Element, thisArg?: any): React.JSX.Element[]
Calls a defined callback function on each element of an array, and returns an array that contains the results.
@paramcallbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.@paramthisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
map
((todo: stringtodo) => (
<JSX.IntrinsicElements.li: React.DetailedHTMLProps<React.LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>li React.HTMLAttributes<T>.className?: string | undefinedclassName="kanban-item" React.Attributes.key?: React.Key | null | undefinedkey={todo: stringtodo}> <JSX.IntrinsicElements.span: React.DetailedHTMLProps<React.HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>span React.HTMLAttributes<T>.className?: string | undefinedclassName="kanban-handle"></JSX.IntrinsicElements.span: React.DetailedHTMLProps<React.HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>span> {todo: stringtodo} </JSX.IntrinsicElements.li: React.DetailedHTMLProps<React.LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>li> ))} </JSX.IntrinsicElements.ul: React.DetailedHTMLProps<React.HTMLAttributes<HTMLUListElement>, HTMLUListElement>ul> <JSX.IntrinsicElements.ul: React.DetailedHTMLProps<React.HTMLAttributes<HTMLUListElement>, HTMLUListElement>ul React.RefAttributes<HTMLUListElement>.ref?: React.LegacyRef<HTMLUListElement> | undefined
Allows getting a ref to the component instance. Once the component unmounts, React will set `ref.current` to `null` (or call the ref with `null` if you passed a callback ref).
@see{@link https://react.dev/learn/referencing-values-with-refs#refs-and-the-dom React Docs}
ref
={const doneList: React.RefObject<HTMLUListElement>doneList} React.HTMLAttributes<T>.className?: string | undefinedclassName="kanban-column">
{const dones: string[]dones.Array<string>.map<React.JSX.Element>(callbackfn: (value: string, index: number, array: string[]) => React.JSX.Element, thisArg?: any): React.JSX.Element[]
Calls a defined callback function on each element of an array, and returns an array that contains the results.
@paramcallbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.@paramthisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
map
((done: stringdone) => (
<JSX.IntrinsicElements.li: React.DetailedHTMLProps<React.LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>li React.HTMLAttributes<T>.className?: string | undefinedclassName="kanban-item" React.Attributes.key?: React.Key | null | undefinedkey={done: stringdone}> <JSX.IntrinsicElements.span: React.DetailedHTMLProps<React.HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>span React.HTMLAttributes<T>.className?: string | undefinedclassName="kanban-handle"></JSX.IntrinsicElements.span: React.DetailedHTMLProps<React.HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>span> {done: stringdone} </JSX.IntrinsicElements.li: React.DetailedHTMLProps<React.LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>li> ))} </JSX.IntrinsicElements.ul: React.DetailedHTMLProps<React.HTMLAttributes<HTMLUListElement>, HTMLUListElement>ul> </JSX.IntrinsicElements.div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>div> ); }
<script setup lang="ts">
import { function useDragAndDrop<T>(initialValues: T[], options?: Partial<VueParentConfig<T>>): [Ref<HTMLElement | undefined>, Ref<T[]>, (config: Partial<VueParentConfig<T>>) => void]
Creates a new instance of drag and drop and returns the parent element and a ref of the values to use in your template.
@paraminitialValues - The initial values of the parent element.@returnsThe parent element and values for drag and drop.
useDragAndDrop
} from "@formkit/drag-and-drop/vue";
const const todoItems: string[]todoItems = ["Schedule perm", "Rewind VHS tapes", "Make change for the arcade", "Get disposable camera developed", "Learn C++", "Return Nintendo Power Glove"]; const const doneItems: string[]doneItems = ["Pickup new mix-tape from Beth", "Implement drag handles"]; const [const todoList: Ref<HTMLElement | undefined, HTMLElement | undefined>todoList, const todos: Ref<string[], string[]>todos] = useDragAndDrop<string>(initialValues: string[], options?: Partial<Partial<ParentConfig<string>>> | undefined): [Ref<HTMLElement | undefined, HTMLElement | undefined>, Ref<...>, (config: Partial<...>) => void]
Creates a new instance of drag and drop and returns the parent element and a ref of the values to use in your template.
@paraminitialValues - The initial values of the parent element.@returnsThe parent element and values for drag and drop.
useDragAndDrop
(const todoItems: string[]todoItems, {
group?: string | undefined
The group that the parent belongs to. This is used for allowing multiple parents to transfer nodes between each other.
group
: "todoList",
dragHandle?: string | undefined
A selector for the drag handle. Will search at any depth within the draggable element.
dragHandle
: ".kanban-handle",
}); const [const doneList: Ref<HTMLElement | undefined, HTMLElement | undefined>doneList, const dones: Ref<string[], string[]>dones] = useDragAndDrop<string>(initialValues: string[], options?: Partial<Partial<ParentConfig<string>>> | undefined): [Ref<HTMLElement | undefined, HTMLElement | undefined>, Ref<...>, (config: Partial<...>) => void]
Creates a new instance of drag and drop and returns the parent element and a ref of the values to use in your template.
@paraminitialValues - The initial values of the parent element.@returnsThe parent element and values for drag and drop.
useDragAndDrop
(const doneItems: string[]doneItems, {
group?: string | undefined
The group that the parent belongs to. This is used for allowing multiple parents to transfer nodes between each other.
group
: "todoList",
dragHandle?: string | undefined
A selector for the drag handle. Will search at any depth within the draggable element.
dragHandle
: ".kanban-handle",
}); </script> <template> <div: HTMLAttributes & ReservedPropsdiv HTMLAttributes.class?: anyclass="kanban-board"> <ul: HTMLAttributes & ReservedPropsul ref?: VNodeRef | undefinedref="const todoList: Ref<HTMLElement | undefined, HTMLElement | undefined>todoList" HTMLAttributes.class?: anyclass="kanban-column"> <li: LiHTMLAttributes & ReservedPropsli v-for="const todo: stringtodo in const todos: Ref<string[], string[]>todos" key?: PropertyKey | undefined:key?: PropertyKey | undefinedkey="const todo: stringtodo" HTMLAttributes.class?: anyclass="kanban-item"> <span: HTMLAttributes & ReservedPropsspan HTMLAttributes.class?: anyclass="kanban-handle"></span: HTMLAttributes & ReservedPropsspan> {{ const todo: stringtodo }} </li: LiHTMLAttributes & ReservedPropsli> </ul: HTMLAttributes & ReservedPropsul> <ul: HTMLAttributes & ReservedPropsul ref?: VNodeRef | undefinedref="const doneList: Ref<HTMLElement | undefined, HTMLElement | undefined>doneList" HTMLAttributes.class?: anyclass="kanban-column"> <li: LiHTMLAttributes & ReservedPropsli v-for="const done: stringdone in const dones: Ref<string[], string[]>dones" key?: PropertyKey | undefined:key?: PropertyKey | undefinedkey="const done: stringdone" HTMLAttributes.class?: anyclass="kanban-item"> <span: HTMLAttributes & ReservedPropsspan HTMLAttributes.class?: anyclass="kanban-handle"></span: HTMLAttributes & ReservedPropsspan> {{ const done: stringdone }} </li: LiHTMLAttributes & ReservedPropsli> </ul: HTMLAttributes & ReservedPropsul> </div: HTMLAttributes & ReservedPropsdiv> </template>
/** @jsxImportSource solid-js */
import { 
function For<T extends readonly any[], U extends JSX.Element>(props: {
    each: T | undefined | null | false;
    fallback?: JSX.Element;
    children: (item: T[number], index: Accessor<number>) => U;
}): JSX.Element
Creates a list elements from a list it receives a map function as its child that receives a list element and an accessor with the index and returns a JSX-Element; if the list is empty, an optional fallback is returned: ```typescript <For each={items} fallback={<div>No items</div>}> {(item, index) => <div data-index={index()}>{item}</div>} </For> ``` If you have a list with fixed indices and changing values, consider using `<Index>` instead.
@descriptionhttps://docs.solidjs.com/reference/components/for
For
} from "solid-js";
import { function useDragAndDrop<E extends HTMLElement, T = unknown>(initValues: T[], options?: Partial<ParentConfig<T>>): [Setter<E | null>, Accessor<Store<T[]>>, ReturnType<typeof createStore>[1], (config?: Partial<ParentConfig<T>>) => void]
Hook for adding drag and drop/sortable support to a list of items.
@paraminitValues - Initial list of data.@paramoptions - The drag and drop configuration.@returns
useDragAndDrop
} from "@formkit/drag-and-drop/solid";
export function function MyComponent(): JSX.ElementMyComponent() { const const todoItems: string[]todoItems = [ "Schedule perm", "Rewind VHS tapes", "Make change for the arcade", "Get disposable camera developed", "Learn C++", "Return Nintendo Power Glove", ]; const const doneItems: string[]doneItems = ["Pickup new mix-tape from Beth", "Implement drag handles"]; const [const todoList: Setter<HTMLUListElement | null>todoList, const todos: Accessor<string[]>todos] = useDragAndDrop<HTMLUListElement, string>(initValues: string[], options?: Partial<ParentConfig<string>> | undefined): [Setter<HTMLUListElement | null>, Accessor<...>, SetStoreFunction<...>, (config?: Partial<...> | undefined) => void]
Hook for adding drag and drop/sortable support to a list of items.
@paraminitValues - Initial list of data.@paramoptions - The drag and drop configuration.@returns
useDragAndDrop
<HTMLUListElement, string>(
const todoItems: string[]todoItems, { group?: string | undefined
The group that the parent belongs to. This is used for allowing multiple parents to transfer nodes between each other.
group
: "todoList",
dragHandle?: string | undefined
A selector for the drag handle. Will search at any depth within the draggable element.
dragHandle
: ".kanban-handle",
} ); const [const doneList: Setter<HTMLUListElement | null>doneList, const dones: Accessor<string[]>dones] = useDragAndDrop<HTMLUListElement, string>(initValues: string[], options?: Partial<ParentConfig<string>> | undefined): [Setter<HTMLUListElement | null>, Accessor<...>, SetStoreFunction<...>, (config?: Partial<...> | undefined) => void]
Hook for adding drag and drop/sortable support to a list of items.
@paraminitValues - Initial list of data.@paramoptions - The drag and drop configuration.@returns
useDragAndDrop
<HTMLUListElement, string>(
const doneItems: string[]doneItems, { group?: string | undefined
The group that the parent belongs to. This is used for allowing multiple parents to transfer nodes between each other.
group
: "todoList",
dragHandle?: string | undefined
A selector for the drag handle. Will search at any depth within the draggable element.
dragHandle
: ".kanban-handle",
} ); return ( <JSX.HTMLElementTags.div: JSX.HTMLAttributes<HTMLDivElement>div JSX.HTMLAttributes<HTMLDivElement>.class?: string | undefinedclass="kanban-board"> <JSX.HTMLElementTags.ul: JSX.HTMLAttributes<HTMLUListElement>ul ref?: HTMLUListElement | ((el: HTMLUListElement) => void) | undefinedref={const todoList: Setter<HTMLUListElement | null>todoList} JSX.HTMLAttributes<T>.class?: string | undefinedclass="kanban-column"> <
function For<T extends readonly any[], U extends JSX.Element>(props: {
    each: T | undefined | null | false;
    fallback?: JSX.Element;
    children: (item: T[number], index: Accessor<number>) => U;
}): JSX.Element
Creates a list elements from a list it receives a map function as its child that receives a list element and an accessor with the index and returns a JSX-Element; if the list is empty, an optional fallback is returned: ```typescript <For each={items} fallback={<div>No items</div>}> {(item, index) => <div data-index={index()}>{item}</div>} </For> ``` If you have a list with fixed indices and changing values, consider using `<Index>` instead.
@descriptionhttps://docs.solidjs.com/reference/components/for
For
each: false | string[] | null | undefinedeach={const todos: () => string[]todos()}>
{(todo: stringtodo) => ( <JSX.HTMLElementTags.li: JSX.LiHTMLAttributes<HTMLLIElement>li JSX.HTMLAttributes<T>.class?: string | undefinedclass="kanban-item"> <JSX.HTMLElementTags.span: JSX.HTMLAttributes<HTMLSpanElement>span JSX.HTMLAttributes<T>.class?: string | undefinedclass="kanban-handle"></JSX.HTMLElementTags.span: JSX.HTMLAttributes<HTMLSpanElement>span> {todo: stringtodo} </JSX.HTMLElementTags.li: JSX.LiHTMLAttributes<HTMLLIElement>li> )} </
function For<T extends readonly any[], U extends JSX.Element>(props: {
    each: T | undefined | null | false;
    fallback?: JSX.Element;
    children: (item: T[number], index: Accessor<number>) => U;
}): JSX.Element
Creates a list elements from a list it receives a map function as its child that receives a list element and an accessor with the index and returns a JSX-Element; if the list is empty, an optional fallback is returned: ```typescript <For each={items} fallback={<div>No items</div>}> {(item, index) => <div data-index={index()}>{item}</div>} </For> ``` If you have a list with fixed indices and changing values, consider using `<Index>` instead.
@descriptionhttps://docs.solidjs.com/reference/components/for
For
>
</JSX.HTMLElementTags.ul: JSX.HTMLAttributes<HTMLUListElement>ul> <JSX.HTMLElementTags.ul: JSX.HTMLAttributes<HTMLUListElement>ul ref?: HTMLUListElement | ((el: HTMLUListElement) => void) | undefinedref={const doneList: Setter<HTMLUListElement | null>doneList} JSX.HTMLAttributes<T>.class?: string | undefinedclass="kanban-column"> <
function For<T extends readonly any[], U extends JSX.Element>(props: {
    each: T | undefined | null | false;
    fallback?: JSX.Element;
    children: (item: T[number], index: Accessor<number>) => U;
}): JSX.Element
Creates a list elements from a list it receives a map function as its child that receives a list element and an accessor with the index and returns a JSX-Element; if the list is empty, an optional fallback is returned: ```typescript <For each={items} fallback={<div>No items</div>}> {(item, index) => <div data-index={index()}>{item}</div>} </For> ``` If you have a list with fixed indices and changing values, consider using `<Index>` instead.
@descriptionhttps://docs.solidjs.com/reference/components/for
For
each: false | string[] | null | undefinedeach={const dones: () => string[]dones()}>
{(done: stringdone) => ( <JSX.HTMLElementTags.li: JSX.LiHTMLAttributes<HTMLLIElement>li JSX.HTMLAttributes<T>.class?: string | undefinedclass="kanban-item"> <JSX.HTMLElementTags.span: JSX.HTMLAttributes<HTMLSpanElement>span JSX.HTMLAttributes<T>.class?: string | undefinedclass="kanban-handle"></JSX.HTMLElementTags.span: JSX.HTMLAttributes<HTMLSpanElement>span> {done: stringdone} </JSX.HTMLElementTags.li: JSX.LiHTMLAttributes<HTMLLIElement>li> )} </
function For<T extends readonly any[], U extends JSX.Element>(props: {
    each: T | undefined | null | false;
    fallback?: JSX.Element;
    children: (item: T[number], index: Accessor<number>) => U;
}): JSX.Element
Creates a list elements from a list it receives a map function as its child that receives a list element and an accessor with the index and returns a JSX-Element; if the list is empty, an optional fallback is returned: ```typescript <For each={items} fallback={<div>No items</div>}> {(item, index) => <div data-index={index()}>{item}</div>} </For> ``` If you have a list with fixed indices and changing values, consider using `<Index>` instead.
@descriptionhttps://docs.solidjs.com/reference/components/for
For
>
</JSX.HTMLElementTags.ul: JSX.HTMLAttributes<HTMLUListElement>ul> </JSX.HTMLElementTags.div: JSX.HTMLAttributes<HTMLDivElement>div> ); }
import { const reactive: <T extends DataSource>(data: T, state?: ReactiveProxyState) => ReactiveProxy<T>
reactive is an alias for r
reactive
, const html: (strings: TemplateStringsArray, ...expSlots: any[]) => ArrowTemplate
html is an alias for t
html
} from "@arrow-js/core";
import { function dragAndDrop<T>({ parent, getValues, setValues, config, }: DragAndDrop<T>): void
Initializes the drag and drop functionality for a given parent.
@paramdragAndDrop - The drag and drop configuration.@returnsvoid
dragAndDrop
} from "@formkit/drag-and-drop";
const
const state: ReactiveProxy<{
    todos: string[];
    dones: string[];
}>
state
=
reactive<{
    todos: string[];
    dones: string[];
}>(data: {
    todos: string[];
    dones: string[];
}, state?: ReactiveProxyState): ReactiveProxy<{
    todos: string[];
    dones: string[];
}>
Given a data object, often an object literal, return a proxy of that object with mutation observers for each property.
@paramdata@returnsReactiveProxy
reactive
({
todos: string[]todos: [ "Schedule perm", "Rewind VHS tapes", "Make change for the arcade", "Get disposable camera developed", "Learn C++", "Return Nintendo Power Glove", ], dones: string[]dones: ["Pickup new mix-tape from Beth", "Implement drag handles"], }); dragAndDrop<string>({ parent, getValues, setValues, config, }: DragAndDrop<string>): void
Initializes the drag and drop functionality for a given parent.
@paramdragAndDrop - The drag and drop configuration.@returnsvoid
dragAndDrop
<string>({
DragAndDrop<string>.parent: HTMLElement
The parent element that will contain the draggable nodes.
parent
: var document: Document
[MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/document)
document
.Document.getElementById(elementId: string): HTMLElement | null
Returns a reference to the first object with the specified value of the ID attribute.
@paramelementId String that specifies the ID value.
getElementById
("todo-list")!,
DragAndDrop<string>.getValues: (parent: HTMLElement) => string[]
A function that returns the values assigned to the parent.
getValues
: () =>
const state: ReactiveProxy<{
    todos: string[];
    dones: string[];
}>
state
.todos: ReactiveProxy<string[]>todos,
DragAndDrop<string>.setValues: (values: string[], parent: HTMLElement) => void
A function that sets the values assigned to the parent.
setValues
: (newValues: string[]newValues) => {
const state: ReactiveProxy<{
    todos: string[];
    dones: string[];
}>
state
.todos: ReactiveProxy<string[]>todos = reactive<string[]>(data: string[], state?: ReactiveProxyState): ReactiveProxy<string[]>
Given a data object, often an object literal, return a proxy of that object with mutation observers for each property.
@paramdata@returnsReactiveProxy
reactive
(newValues: string[]newValues);
}, DragAndDrop<string>.config?: Partial<ParentConfig<string>> | undefined
An optional configuration object.
config
: {
group?: string | undefined
The group that the parent belongs to. This is used for allowing multiple parents to transfer nodes between each other.
group
: "todoList",
dragHandle?: string | undefined
A selector for the drag handle. Will search at any depth within the draggable element.
dragHandle
: ".kanban-handle",
}, }); dragAndDrop<string>({ parent, getValues, setValues, config, }: DragAndDrop<string>): void
Initializes the drag and drop functionality for a given parent.
@paramdragAndDrop - The drag and drop configuration.@returnsvoid
dragAndDrop
<string>({
DragAndDrop<string>.parent: HTMLElement
The parent element that will contain the draggable nodes.
parent
: var document: Document
[MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/document)
document
.Document.getElementById(elementId: string): HTMLElement | null
Returns a reference to the first object with the specified value of the ID attribute.
@paramelementId String that specifies the ID value.
getElementById
("done-list")!,
DragAndDrop<string>.getValues: (parent: HTMLElement) => string[]
A function that returns the values assigned to the parent.
getValues
: () =>
const state: ReactiveProxy<{
    todos: string[];
    dones: string[];
}>
state
.dones: ReactiveProxy<string[]>dones,
DragAndDrop<string>.setValues: (values: string[], parent: HTMLElement) => void
A function that sets the values assigned to the parent.
setValues
: (newValues: string[]newValues) => {
const state: ReactiveProxy<{
    todos: string[];
    dones: string[];
}>
state
.dones: ReactiveProxy<string[]>dones = reactive<string[]>(data: string[], state?: ReactiveProxyState): ReactiveProxy<string[]>
Given a data object, often an object literal, return a proxy of that object with mutation observers for each property.
@paramdata@returnsReactiveProxy
reactive
(newValues: string[]newValues);
}, DragAndDrop<string>.config?: Partial<ParentConfig<string>> | undefined
An optional configuration object.
config
: {
group?: string | undefined
The group that the parent belongs to. This is used for allowing multiple parents to transfer nodes between each other.
group
: "todoList",
dragHandle?: string | undefined
A selector for the drag handle. Will search at any depth within the draggable element.
dragHandle
: ".kanban-handle",
}, }); const html: (strings: TemplateStringsArray, ...expSlots: any[]) => ArrowTemplate
html is an alias for t
html
`
<div class="kanban-board"> <ul class="kanban-column" id="todo-list"> ${() =>
const state: ReactiveProxy<{
    todos: string[];
    dones: string[];
}>
state
.todos: ReactiveProxy<string[]>todos.Array<string>.map<void>(callbackfn: (value: string, index: number, array: string[]) => void, thisArg?: any): void[]
Calls a defined callback function on each element of an array, and returns an array that contains the results.
@paramcallbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.@paramthisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
map
((todo: stringtodo) =>
const html: (strings: TemplateStringsArray, ...expSlots: any[]) => ArrowTemplate
html is an alias for t
html
`
<li class="kanban-item"> <span class="kanban-handle"></span> ${todo: stringtodo} </li> `.ArrowTemplate.key: (key: ArrowTemplateKey) => void
Adds a key to this template to identify it as a unique instance.
@paramkey - A unique key that identifies this template instance (not index).@returns
key
(todo: stringtodo)
)} </ul> <ul class="kanban-column" id="done-list"> ${
const state: ReactiveProxy<{
    todos: string[];
    dones: string[];
}>
state
.dones: ReactiveProxy<string[]>dones.Array<string>.map<void>(callbackfn: (value: string, index: number, array: string[]) => void, thisArg?: any): void[]
Calls a defined callback function on each element of an array, and returns an array that contains the results.
@paramcallbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.@paramthisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
map
((done: stringdone) =>
const html: (strings: TemplateStringsArray, ...expSlots: any[]) => ArrowTemplate
html is an alias for t
html
`
<li class="kanban-item"> <span class="kanban-handle"></span> ${done: stringdone} </li> `.ArrowTemplate.key: (key: ArrowTemplateKey) => void
Adds a key to this template to identify it as a unique instance.
@paramkey - A unique key that identifies this template instance (not index).@returns
key
(done: stringdone)
)} </ul> </div> `(var document: Document
[MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/document)
document
.Document.getElementById(elementId: string): HTMLElement | null
Returns a reference to the first object with the specified value of the ID attribute.
@paramelementId String that specifies the ID value.
getElementById
("app")!);

ToDos

  • Schedule perm
  • Rewind VHS tapes
  • Make change for the arcade
  • Get disposable camera developed
  • Learn C++
  • Return Nintendo Power Glove
["Schedule perm","Rewind VHS tapes","Make change for the arcade","Get disposable camera developed","Learn C++","Return Nintendo Power Glove"]

Complete

  • Pickup new mix-tape from Beth
  • Implement drag handles
["Pickup new mix-tape from Beth","Implement drag handles"]

Updating Config

The parent's configuration can be updated idempotently during runtime by using the updateConfig method. In the example below, clicking the button will toggle whether drag and drop is enabled for the parent.

  • React
  • Vue
  • Solid
  • Native
import React from "react";
import { function useState<S>(initialState: S | (() => S)): [S, React.Dispatch<React.SetStateAction<S>>] (+1 overload)
Returns a stateful value, and a function to update it.
@version16.8.0@see{@link https://react.dev/reference/react/useState}
useState
} from "react";
import { function useDragAndDrop<E extends HTMLElement, T = unknown>(list: T[], options?: Partial<ParentConfig<T>>): [React.RefObject<E>, T[], React.Dispatch<React.SetStateAction<T[]>>, (config: Partial<ParentConfig<...>>) => void]
Hook for adding drag and drop/sortable support to a list of items.
@paramlist - Initial list of data.@paramoptions - The drag and drop configuration.@returns
useDragAndDrop
} from "@formkit/drag-and-drop/react";
export function function myComponent(): React.JSX.ElementmyComponent() { const [const parent: React.RefObject<HTMLUListElement>parent, const values: string[]values, const _setValues: React.Dispatch<React.SetStateAction<string[]>>_setValues, const updateConfig: (config: Partial<ParentConfig<string>>) => voidupdateConfig] = useDragAndDrop<HTMLUListElement, string>(list: string[], options?: Partial<ParentConfig<string>> | undefined): [React.RefObject<HTMLUListElement>, string[], React.Dispatch<...>, (config: Partial<...>) => void]
Hook for adding drag and drop/sortable support to a list of items.
@paramlist - Initial list of data.@paramoptions - The drag and drop configuration.@returns
useDragAndDrop
<
HTMLUListElement, string >([ "Depeche Mode", "Duran Duran", "Pet Shop Boys", "Kraftwerk", "Tears for Fears", "Spandau Ballet", ]); const [const disabled: booleandisabled, const setDisabled: React.Dispatch<React.SetStateAction<boolean>>setDisabled] = useState<boolean>(initialState: boolean | (() => boolean)): [boolean, React.Dispatch<React.SetStateAction<boolean>>] (+1 overload)
Returns a stateful value, and a function to update it.
@version16.8.0@see{@link https://react.dev/reference/react/useState}
useState
(false);
const const toggleDisabled: () => voidtoggleDisabled = () => { const setDisabled: (value: React.SetStateAction<boolean>) => voidsetDisabled(!const disabled: booleandisabled); const updateConfig: (config: Partial<ParentConfig<string>>) => voidupdateConfig({ disabled?: boolean | undefined
A flag to disable dragability of all nodes in the parent.
disabled
: !const disabled: booleandisabled });
}; return ( <JSX.IntrinsicElements.div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>div> <JSX.IntrinsicElements.ul: React.DetailedHTMLProps<React.HTMLAttributes<HTMLUListElement>, HTMLUListElement>ul React.RefAttributes<HTMLUListElement>.ref?: React.LegacyRef<HTMLUListElement> | undefined
Allows getting a ref to the component instance. Once the component unmounts, React will set `ref.current` to `null` (or call the ref with `null` if you passed a callback ref).
@see{@link https://react.dev/learn/referencing-values-with-refs#refs-and-the-dom React Docs}
ref
={const parent: React.RefObject<HTMLUListElement>parent}>
{const values: string[]values.Array<string>.map<React.JSX.Element>(callbackfn: (value: string, index: number, array: string[]) => React.JSX.Element, thisArg?: any): React.JSX.Element[]
Calls a defined callback function on each element of an array, and returns an array that contains the results.
@paramcallbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.@paramthisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
map
((tape: stringtape) => (
<JSX.IntrinsicElements.li: React.DetailedHTMLProps<React.LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>li React.HTMLAttributes<HTMLLIElement>.className?: string | undefinedclassName="cassette" data-label: stringdata-label={tape: stringtape} React.Attributes.key?: React.Key | null | undefinedkey={tape: stringtape}> {tape: stringtape} </JSX.IntrinsicElements.li: React.DetailedHTMLProps<React.LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>li> ))} </JSX.IntrinsicElements.ul: React.DetailedHTMLProps<React.HTMLAttributes<HTMLUListElement>, HTMLUListElement>ul> <JSX.IntrinsicElements.button: React.DetailedHTMLProps<React.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>button React.DOMAttributes<HTMLButtonElement>.onClick?: React.MouseEventHandler<HTMLButtonElement> | undefinedonClick={const toggleDisabled: () => voidtoggleDisabled}> {const disabled: booleandisabled ? "Enable" : "Disable"} drag and drop </JSX.IntrinsicElements.button: React.DetailedHTMLProps<React.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>button> </JSX.IntrinsicElements.div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>div> ); }
<script setup lang="ts">
import { function useDragAndDrop<T>(initialValues: T[], options?: Partial<VueParentConfig<T>>): [Ref<HTMLElement | undefined>, Ref<T[]>, (config: Partial<VueParentConfig<T>>) => void]
Creates a new instance of drag and drop and returns the parent element and a ref of the values to use in your template.
@paraminitialValues - The initial values of the parent element.@returnsThe parent element and values for drag and drop.
useDragAndDrop
} from "@formkit/drag-and-drop/vue";
import { function ref<T>(value: T): [T] extends [Ref] ? IfAny<T, Ref<T>, T> : Ref<UnwrapRef<T>, UnwrapRef<T> | T> (+1 overload)
Takes an inner value and returns a reactive and mutable ref object, which has a single property `.value` that points to the inner value.
@paramvalue - The object to wrap in the ref.@see{@link https://vuejs.org/api/reactivity-core.html#ref}
ref
} from "vue";
const const disabled: Ref<boolean, boolean>disabled = ref<boolean>(value: boolean): Ref<boolean, boolean> (+1 overload)
Takes an inner value and returns a reactive and mutable ref object, which has a single property `.value` that points to the inner value.
@paramvalue - The object to wrap in the ref.@see{@link https://vuejs.org/api/reactivity-core.html#ref}
ref
(false);
const [const parentRef: Ref<HTMLElement | undefined, HTMLElement | undefined>parentRef, const values: Ref<string[], string[]>values, const updateConfig: (config: Partial<Partial<ParentConfig<string>>>) => voidupdateConfig] = useDragAndDrop<string>(initialValues: string[], options?: Partial<Partial<ParentConfig<string>>> | undefined): [Ref<HTMLElement | undefined, HTMLElement | undefined>, Ref<...>, (config: Partial<...>) => void]
Creates a new instance of drag and drop and returns the parent element and a ref of the values to use in your template.
@paraminitialValues - The initial values of the parent element.@returnsThe parent element and values for drag and drop.
useDragAndDrop
([
"Depeche Mode", "Duran Duran", "Pet", "Kraftwerk", "Tears for Fears", "Spandau Ballet", ]); function function toggleDisabled(): voidtoggleDisabled() { const disabled: Ref<boolean, boolean>disabled.Ref<boolean, boolean>.value: booleanvalue = !const disabled: Ref<boolean, boolean>disabled.Ref<boolean, boolean>.value: booleanvalue; const updateConfig: (config: Partial<Partial<ParentConfig<string>>>) => voidupdateConfig({ disabled?: boolean | undefined
A flag to disable dragability of all nodes in the parent.
disabled
: const disabled: Ref<boolean, boolean>disabled.Ref<boolean, boolean>.value: booleanvalue });
} </script> <template> <ul: HTMLAttributes & ReservedPropsul ref?: VNodeRef | undefinedref="const parentRef: Ref<HTMLElement | undefined, HTMLElement | undefined>parentRef"> <li: LiHTMLAttributes & ReservedPropsli v-for="const tape: stringtape in const values: Ref<string[], string[]>values" key?: PropertyKey | undefined:key?: PropertyKey | undefinedkey="const tape: stringtape" HTMLAttributes.class?: anyclass="cassette"> {{ const tape: stringtape }} </li: LiHTMLAttributes & ReservedPropsli> </ul: HTMLAttributes & ReservedPropsul> <button: ButtonHTMLAttributes & ReservedPropsbutton HTMLAttributes.id?: string | undefinedid="no-drag" @onClick?: ((payload: MouseEvent) => void) | undefinedclick="function toggleDisabled(): voidtoggleDisabled"> {{ const disabled: Ref<boolean, boolean>disabled ? "Enable" : "Disable" }} drag and drop </button: ButtonHTMLAttributes & ReservedPropsbutton> </template>
/** @jsxImportSource solid-js */
import { function createSignal<T>(): Signal<T | undefined> (+1 overload)
Creates a simple reactive state with a getter and setter ```typescript const [state: Accessor<T>, setState: Setter<T>] = createSignal<T>( value: T, options?: { name?: string, equals?: false | ((prev: T, next: T) => boolean) } ) ```
@paramvalue initial value of the state; if empty, the state's type will automatically extended with undefined; otherwise you need to extend the type manually if you want setting to undefined not be an error@paramoptions optional object with a name for debugging purposes and equals, a comparator function for the previous and next value to allow fine-grained control over the reactivity@returns```typescript [state: Accessor<T>, setState: Setter<T>] ``` * the Accessor is merely a function that returns the current value and registers each call to the reactive root * the Setter is a function that allows directly setting or mutating the value: ```typescript const [count, setCount] = createSignal(0); setCount(count => count + 1); ```@descriptionhttps://docs.solidjs.com/reference/basic-reactivity/create-signal
createSignal
} from "solid-js";
import {
function For<T extends readonly any[], U extends JSX.Element>(props: {
    each: T | undefined | null | false;
    fallback?: JSX.Element;
    children: (item: T[number], index: Accessor<number>) => U;
}): JSX.Element
Creates a list elements from a list it receives a map function as its child that receives a list element and an accessor with the index and returns a JSX-Element; if the list is empty, an optional fallback is returned: ```typescript <For each={items} fallback={<div>No items</div>}> {(item, index) => <div data-index={index()}>{item}</div>} </For> ``` If you have a list with fixed indices and changing values, consider using `<Index>` instead.
@descriptionhttps://docs.solidjs.com/reference/components/for
For
} from "solid-js";
import { function useDragAndDrop<E extends HTMLElement, T = unknown>(initValues: T[], options?: Partial<ParentConfig<T>>): [Setter<E | null>, Accessor<Store<T[]>>, ReturnType<typeof createStore>[1], (config?: Partial<ParentConfig<T>>) => void]
Hook for adding drag and drop/sortable support to a list of items.
@paraminitValues - Initial list of data.@paramoptions - The drag and drop configuration.@returns
useDragAndDrop
} from "@formkit/drag-and-drop/solid";
export function function MyComponent(): JSX.ElementMyComponent() { const [const parent: Setter<HTMLUListElement | null>parent, const values: Accessor<string[]>values, , const updateConfig: (config?: Partial<ParentConfig<string>> | undefined) => voidupdateConfig] = useDragAndDrop<HTMLUListElement, string>(initValues: string[], options?: Partial<ParentConfig<string>> | undefined): [Setter<HTMLUListElement | null>, Accessor<...>, SetStoreFunction<...>, (config?: Partial<...> | undefined) => void]
Hook for adding drag and drop/sortable support to a list of items.
@paraminitValues - Initial list of data.@paramoptions - The drag and drop configuration.@returns
useDragAndDrop
<
HTMLUListElement, string >([ "Depeche Mode", "Duran Duran", "Pet Shop Boys", "Kraftwerk", "Tears for Fears", "Spandau Ballet", ]); const [const disabled: Accessor<boolean>disabled, const setDisabled: Setter<boolean>setDisabled] = createSignal<boolean>(value: boolean, options?: SignalOptions<boolean> | undefined): Signal<boolean> (+1 overload)
Creates a simple reactive state with a getter and setter ```typescript const [state: Accessor<T>, setState: Setter<T>] = createSignal<T>( value: T, options?: { name?: string, equals?: false | ((prev: T, next: T) => boolean) } ) ```
@paramvalue initial value of the state; if empty, the state's type will automatically extended with undefined; otherwise you need to extend the type manually if you want setting to undefined not be an error@paramoptions optional object with a name for debugging purposes and equals, a comparator function for the previous and next value to allow fine-grained control over the reactivity@returns```typescript [state: Accessor<T>, setState: Setter<T>] ``` * the Accessor is merely a function that returns the current value and registers each call to the reactive root * the Setter is a function that allows directly setting or mutating the value: ```typescript const [count, setCount] = createSignal(0); setCount(count => count + 1); ```@descriptionhttps://docs.solidjs.com/reference/basic-reactivity/create-signal
createSignal
(false);
const const toggleDisabled: () => voidtoggleDisabled = () => { const setDisabled: <boolean>(value: boolean | ((prev: boolean) => boolean)) => boolean (+3 overloads)setDisabled(!const disabled: () => booleandisabled()); const updateConfig: (config?: Partial<ParentConfig<string>> | undefined) => voidupdateConfig({ disabled?: boolean | undefined
A flag to disable dragability of all nodes in the parent.
disabled
: !const disabled: () => booleandisabled() });
}; return ( <JSX.HTMLElementTags.div: JSX.HTMLAttributes<HTMLDivElement>div> <JSX.HTMLElementTags.ul: JSX.HTMLAttributes<HTMLUListElement>ul ref?: HTMLUListElement | ((el: HTMLUListElement) => void) | undefinedref={const parent: Setter<HTMLUListElement | null>parent}> <
function For<T extends readonly any[], U extends JSX.Element>(props: {
    each: T | undefined | null | false;
    fallback?: JSX.Element;
    children: (item: T[number], index: Accessor<number>) => U;
}): JSX.Element
Creates a list elements from a list it receives a map function as its child that receives a list element and an accessor with the index and returns a JSX-Element; if the list is empty, an optional fallback is returned: ```typescript <For each={items} fallback={<div>No items</div>}> {(item, index) => <div data-index={index()}>{item}</div>} </For> ``` If you have a list with fixed indices and changing values, consider using `<Index>` instead.
@descriptionhttps://docs.solidjs.com/reference/components/for
For
each: false | string[] | null | undefinedeach={const values: () => string[]values()}>
{(tape: stringtape) => ( <JSX.HTMLElementTags.li: JSX.LiHTMLAttributes<HTMLLIElement>li JSX.HTMLAttributes<HTMLLIElement>.class?: string | undefinedclass="cassette" data-label: stringdata-label={tape: stringtape}> {tape: stringtape} </JSX.HTMLElementTags.li: JSX.LiHTMLAttributes<HTMLLIElement>li> )} </
function For<T extends readonly any[], U extends JSX.Element>(props: {
    each: T | undefined | null | false;
    fallback?: JSX.Element;
    children: (item: T[number], index: Accessor<number>) => U;
}): JSX.Element
Creates a list elements from a list it receives a map function as its child that receives a list element and an accessor with the index and returns a JSX-Element; if the list is empty, an optional fallback is returned: ```typescript <For each={items} fallback={<div>No items</div>}> {(item, index) => <div data-index={index()}>{item}</div>} </For> ``` If you have a list with fixed indices and changing values, consider using `<Index>` instead.
@descriptionhttps://docs.solidjs.com/reference/components/for
For
>
</JSX.HTMLElementTags.ul: JSX.HTMLAttributes<HTMLUListElement>ul> <JSX.HTMLElementTags.button: JSX.ButtonHTMLAttributes<HTMLButtonElement>button JSX.CustomEventHandlersCamelCase<HTMLButtonElement>.onClick?: JSX.EventHandlerUnion<HTMLButtonElement, MouseEvent, JSX.EventHandler<HTMLButtonElement, MouseEvent>> | undefinedonClick={const toggleDisabled: () => voidtoggleDisabled}> {const disabled: () => booleandisabled() ? "Enable" : "Disable"} drag and drop </JSX.HTMLElementTags.button: JSX.ButtonHTMLAttributes<HTMLButtonElement>button> </JSX.HTMLElementTags.div: JSX.HTMLAttributes<HTMLDivElement>div> ); }
import { const reactive: <T extends DataSource>(data: T, state?: ReactiveProxyState) => ReactiveProxy<T>
reactive is an alias for r
reactive
, const html: (strings: TemplateStringsArray, ...expSlots: any[]) => ArrowTemplate
html is an alias for t
html
} from "@arrow-js/core";
import { function dragAndDrop<T>({ parent, getValues, setValues, config, }: DragAndDrop<T>): void
Initializes the drag and drop functionality for a given parent.
@paramdragAndDrop - The drag and drop configuration.@returnsvoid
dragAndDrop
, function updateConfig<T>(parent: HTMLElement, config: Partial<ParentConfig<T>>): void
Utility function to update parent config.
@paramparent - The parent element.@paramconfig - The config to update.@returnsvoid
updateConfig
} from "@formkit/drag-and-drop";
const
const state: ReactiveProxy<{
    tapes: string[];
    disabled: boolean;
}>
state
=
reactive<{
    tapes: string[];
    disabled: boolean;
}>(data: {
    tapes: string[];
    disabled: boolean;
}, state?: ReactiveProxyState): ReactiveProxy<{
    tapes: string[];
    disabled: boolean;
}>
Given a data object, often an object literal, return a proxy of that object with mutation observers for each property.
@paramdata@returnsReactiveProxy
reactive
({
tapes: string[]tapes: [ "Depeche Mode", "Duran Duran", "Pet Shop Boys", "Kraftwerk", "Tears for Fears", "Spandau Ballet", ], disabled: booleandisabled: false, }); function function toggleDisabled(): voidtoggleDisabled() {
const state: ReactiveProxy<{
    tapes: string[];
    disabled: boolean;
}>
state
.disabled: booleandisabled = !
const state: ReactiveProxy<{
    tapes: string[];
    disabled: boolean;
}>
state
.disabled: booleandisabled;
updateConfig<unknown>(parent: HTMLElement, config: Partial<ParentConfig<unknown>>): void
Utility function to update parent config.
@paramparent - The parent element.@paramconfig - The config to update.@returnsvoid
updateConfig
(var document: Document
[MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/document)
document
.Document.getElementById(elementId: string): HTMLElement | null
Returns a reference to the first object with the specified value of the ID attribute.
@paramelementId String that specifies the ID value.
getElementById
("cassettes")!, {
disabled?: boolean | undefined
A flag to disable dragability of all nodes in the parent.
disabled
: !
const state: ReactiveProxy<{
    tapes: string[];
    disabled: boolean;
}>
state
.disabled: booleandisabled,
}); } const html: (strings: TemplateStringsArray, ...expSlots: any[]) => ArrowTemplate
html is an alias for t
html
`
<ul id="cassettes"> ${
const state: ReactiveProxy<{
    tapes: string[];
    disabled: boolean;
}>
state
.tapes: ReactiveProxy<string[]>tapes.Array<string>.map<void>(callbackfn: (value: string, index: number, array: string[]) => void, thisArg?: any): void[]
Calls a defined callback function on each element of an array, and returns an array that contains the results.
@paramcallbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.@paramthisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
map
((tape: stringtape) =>
const html: (strings: TemplateStringsArray, ...expSlots: any[]) => ArrowTemplate
html is an alias for t
html
`<li class="cassette" data-label="${tape: stringtape}">${tape: stringtape}</li>`.ArrowTemplate.key: (key: ArrowTemplateKey) => void
Adds a key to this template to identify it as a unique instance.
@paramkey - A unique key that identifies this template instance (not index).@returns
key
(tape: stringtape)
)} </ul> <button onclick=${function toggleDisabled(): voidtoggleDisabled}>Toggle Disabled</button> `(var document: Document
[MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/document)
document
.Document.getElementById(elementId: string): HTMLElement | null
Returns a reference to the first object with the specified value of the ID attribute.
@paramelementId String that specifies the ID value.
getElementById
("app")!);
dragAndDrop<string>({ parent, getValues, setValues, config, }: DragAndDrop<string>): void
Initializes the drag and drop functionality for a given parent.
@paramdragAndDrop - The drag and drop configuration.@returnsvoid
dragAndDrop
<string>({
DragAndDrop<string>.parent: HTMLElement
The parent element that will contain the draggable nodes.
parent
: var document: Document
[MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/document)
document
.Document.getElementById(elementId: string): HTMLElement | null
Returns a reference to the first object with the specified value of the ID attribute.
@paramelementId String that specifies the ID value.
getElementById
("cassettes")!,
DragAndDrop<string>.getValues: (parent: HTMLElement) => string[]
A function that returns the values assigned to the parent.
getValues
: () =>
const state: ReactiveProxy<{
    tapes: string[];
    disabled: boolean;
}>
state
.tapes: ReactiveProxy<string[]>tapes,
DragAndDrop<string>.setValues: (values: string[], parent: HTMLElement) => void
A function that sets the values assigned to the parent.
setValues
: (newValues: string[]newValues) => {
const state: ReactiveProxy<{
    tapes: string[];
    disabled: boolean;
}>
state
.tapes: ReactiveProxy<string[]>tapes = reactive<string[]>(data: string[], state?: ReactiveProxyState): ReactiveProxy<string[]>
Given a data object, often an object literal, return a proxy of that object with mutation observers for each property.
@paramdata@returnsReactiveProxy
reactive
(newValues: string[]newValues);
}, });
FormKit Office Jams
  • Depeche Mode
    Cassette Tape
  • Duran Duran
    Cassette Tape
  • Pet
    Cassette Tape
  • Kraftwerk
    Cassette Tape
  • Tears for Fears
    Cassette Tape
  • Spandau Ballet
    Cassette Tape

Multi Drag

Multi drag allows users to select multiple items and drag them all at once. To enable multi drag, set the multiDrag property to true in the configuration.

  • React
  • Vue
  • Solid
  • Native
import React from "react";
import { function useDragAndDrop<E extends HTMLElement, T = unknown>(list: T[], options?: Partial<ParentConfig<T>>): [React.RefObject<E>, T[], React.Dispatch<React.SetStateAction<T[]>>, (config: Partial<ParentConfig<...>>) => void]
Hook for adding drag and drop/sortable support to a list of items.
@paramlist - Initial list of data.@paramoptions - The drag and drop configuration.@returns
useDragAndDrop
} from "@formkit/drag-and-drop/react";
export function function myComponent(): React.JSX.ElementmyComponent() { const const mockFileNames: string[]mockFileNames = [ "dungeon_master.exe", "map_1.dat", "map_2.dat", "character1.txt", "character2.txt", "shell32.dll", "README.txt", ]; const [const parent1: React.RefObject<HTMLUListElement>parent1, const files1: string[]files1] = useDragAndDrop<HTMLUListElement, string>(list: string[], options?: Partial<ParentConfig<string>> | undefined): [React.RefObject<HTMLUListElement>, string[], React.Dispatch<...>, (config: Partial<...>) => void]
Hook for adding drag and drop/sortable support to a list of items.
@paramlist - Initial list of data.@paramoptions - The drag and drop configuration.@returns
useDragAndDrop
<HTMLUListElement, string>(
const mockFileNames: string[]mockFileNames, { group?: string | undefined
The group that the parent belongs to. This is used for allowing multiple parents to transfer nodes between each other.
group
: "A",
multiDrag?: boolean | undefinedmultiDrag: true, selectedClass?: string | undefined
The class to add to a node when it is selected (clicked or pressed).
selectedClass
: "bg-blue-500 text-white",
} ); const [const parent2: React.RefObject<HTMLUListElement>parent2, const files2: string[]files2] = useDragAndDrop<HTMLUListElement, string>(list: string[], options?: Partial<ParentConfig<string>> | undefined): [React.RefObject<HTMLUListElement>, string[], React.Dispatch<...>, (config: Partial<...>) => void]
Hook for adding drag and drop/sortable support to a list of items.
@paramlist - Initial list of data.@paramoptions - The drag and drop configuration.@returns
useDragAndDrop
<HTMLUListElement, string>([], {
group?: string | undefined
The group that the parent belongs to. This is used for allowing multiple parents to transfer nodes between each other.
group
: "A",
multiDrag?: boolean | undefinedmultiDrag: true, selectedClass?: string | undefined
The class to add to a node when it is selected (clicked or pressed).
selectedClass
: "bg-blue-500 text-white",
}); return ( <JSX.IntrinsicElements.div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>div React.HTMLAttributes<HTMLDivElement>.className?: string | undefinedclassName="file-manager"> <JSX.IntrinsicElements.ul: React.DetailedHTMLProps<React.HTMLAttributes<HTMLUListElement>, HTMLUListElement>ul React.RefAttributes<HTMLUListElement>.ref?: React.LegacyRef<HTMLUListElement> | undefined
Allows getting a ref to the component instance. Once the component unmounts, React will set `ref.current` to `null` (or call the ref with `null` if you passed a callback ref).
@see{@link https://react.dev/learn/referencing-values-with-refs#refs-and-the-dom React Docs}
ref
={const parent1: React.RefObject<HTMLUListElement>parent1} React.HTMLAttributes<T>.className?: string | undefinedclassName="file-list">
{const files1: string[]files1.Array<string>.map<React.JSX.Element>(callbackfn: (value: string, index: number, array: string[]) => React.JSX.Element, thisArg?: any): React.JSX.Element[]
Calls a defined callback function on each element of an array, and returns an array that contains the results.
@paramcallbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.@paramthisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
map
((file: stringfile) => (
<JSX.IntrinsicElements.li: React.DetailedHTMLProps<React.LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>li React.Attributes.key?: React.Key | null | undefinedkey={file: stringfile} React.HTMLAttributes<T>.className?: string | undefinedclassName="file"> {file: stringfile} </JSX.IntrinsicElements.li: React.DetailedHTMLProps<React.LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>li> ))} </JSX.IntrinsicElements.ul: React.DetailedHTMLProps<React.HTMLAttributes<HTMLUListElement>, HTMLUListElement>ul> <JSX.IntrinsicElements.ul: React.DetailedHTMLProps<React.HTMLAttributes<HTMLUListElement>, HTMLUListElement>ul React.RefAttributes<HTMLUListElement>.ref?: React.LegacyRef<HTMLUListElement> | undefined
Allows getting a ref to the component instance. Once the component unmounts, React will set `ref.current` to `null` (or call the ref with `null` if you passed a callback ref).
@see{@link https://react.dev/learn/referencing-values-with-refs#refs-and-the-dom React Docs}
ref
={const parent2: React.RefObject<HTMLUListElement>parent2} React.HTMLAttributes<T>.className?: string | undefinedclassName="file-list">
{const files2: string[]files2.Array<string>.map<React.JSX.Element>(callbackfn: (value: string, index: number, array: string[]) => React.JSX.Element, thisArg?: any): React.JSX.Element[]
Calls a defined callback function on each element of an array, and returns an array that contains the results.
@paramcallbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.@paramthisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
map
((file: stringfile) => (
<JSX.IntrinsicElements.li: React.DetailedHTMLProps<React.LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>li React.Attributes.key?: React.Key | null | undefinedkey={file: stringfile} React.HTMLAttributes<T>.className?: string | undefinedclassName="file"> {file: stringfile} </JSX.IntrinsicElements.li: React.DetailedHTMLProps<React.LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>li> ))} </JSX.IntrinsicElements.ul: React.DetailedHTMLProps<React.HTMLAttributes<HTMLUListElement>, HTMLUListElement>ul> </JSX.IntrinsicElements.div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>div> ); }
<script setup lang="ts">
import { function useDragAndDrop<T>(initialValues: T[], options?: Partial<VueParentConfig<T>>): [Ref<HTMLElement | undefined>, Ref<T[]>, (config: Partial<VueParentConfig<T>>) => void]
Creates a new instance of drag and drop and returns the parent element and a ref of the values to use in your template.
@paraminitialValues - The initial values of the parent element.@returnsThe parent element and values for drag and drop.
useDragAndDrop
} from "@formkit/drag-and-drop/vue";
const const mockFileNames: string[]mockFileNames = [ "dungeon_master.exe", "map_1.dat", "map_2.dat", "character1.txt", "character2.txt", "shell32.dll", "README.txt", ]; const [const parent1: Ref<HTMLElement | undefined, HTMLElement | undefined>parent1, const files1: Ref<string[], string[]>files1] = useDragAndDrop<string>(initialValues: string[], options?: Partial<Partial<ParentConfig<string>>> | undefined): [Ref<HTMLElement | undefined, HTMLElement | undefined>, Ref<...>, (config: Partial<...>) => void]
Creates a new instance of drag and drop and returns the parent element and a ref of the values to use in your template.
@paraminitialValues - The initial values of the parent element.@returnsThe parent element and values for drag and drop.
useDragAndDrop
(const mockFileNames: string[]mockFileNames, {
group?: string | undefined
The group that the parent belongs to. This is used for allowing multiple parents to transfer nodes between each other.
group
: "A",
multiDrag?: boolean | undefinedmultiDrag: true, selectedClass?: string | undefined
The class to add to a node when it is selected (clicked or pressed).
selectedClass
: "bg-blue-500 text-white",
}); const [const parent2: Ref<HTMLElement | undefined, HTMLElement | undefined>parent2, const files2: Ref<never[], never[]>files2] = useDragAndDrop<never>(initialValues: never[], options?: Partial<Partial<ParentConfig<never>>> | undefined): [Ref<HTMLElement | undefined, HTMLElement | undefined>, Ref<...>, (config: Partial<...>) => void]
Creates a new instance of drag and drop and returns the parent element and a ref of the values to use in your template.
@paraminitialValues - The initial values of the parent element.@returnsThe parent element and values for drag and drop.
useDragAndDrop
([], {
group?: string | undefined
The group that the parent belongs to. This is used for allowing multiple parents to transfer nodes between each other.
group
: "A",
multiDrag?: boolean | undefinedmultiDrag: true, selectedClass?: string | undefined
The class to add to a node when it is selected (clicked or pressed).
selectedClass
: "bg-blue-500 text-white",
}); </script> <template> <div: HTMLAttributes & ReservedPropsdiv HTMLAttributes.class?: anyclass="file-manager"> <ul: HTMLAttributes & ReservedPropsul ref?: VNodeRef | undefinedref="const parent1: Ref<HTMLElement | undefined, HTMLElement | undefined>parent1" HTMLAttributes.class?: anyclass="file-list"> <li: LiHTMLAttributes & ReservedPropsli v-for="const item: stringitem in const files1: Ref<string[], string[]>files1" key?: PropertyKey | undefined:key?: PropertyKey | undefinedkey="const item: stringitem" HTMLAttributes.class?: anyclass="file"> {{ const item: stringitem }} </li: LiHTMLAttributes & ReservedPropsli> </ul: HTMLAttributes & ReservedPropsul> <ul: HTMLAttributes & ReservedPropsul ref?: VNodeRef | undefinedref="const parent2: Ref<HTMLElement | undefined, HTMLElement | undefined>parent2" HTMLAttributes.class?: anyclass="file-list"> <li: LiHTMLAttributes & ReservedPropsli v-for="const item: neveritem in const files2: Ref<never[], never[]>files2" key?: PropertyKey | undefined:key?: PropertyKey | undefinedkey="const item: neveritem" HTMLAttributes.class?: anyclass="file"> {{ const item: neveritem }} </li: LiHTMLAttributes & ReservedPropsli> </ul: HTMLAttributes & ReservedPropsul> </div: HTMLAttributes & ReservedPropsdiv> </template>
/** @jsxImportSource solid-js */
import { 
function For<T extends readonly any[], U extends JSX.Element>(props: {
    each: T | undefined | null | false;
    fallback?: JSX.Element;
    children: (item: T[number], index: Accessor<number>) => U;
}): JSX.Element
Creates a list elements from a list it receives a map function as its child that receives a list element and an accessor with the index and returns a JSX-Element; if the list is empty, an optional fallback is returned: ```typescript <For each={items} fallback={<div>No items</div>}> {(item, index) => <div data-index={index()}>{item}</div>} </For> ``` If you have a list with fixed indices and changing values, consider using `<Index>` instead.
@descriptionhttps://docs.solidjs.com/reference/components/for
For
} from "solid-js";
import { function useDragAndDrop<E extends HTMLElement, T = unknown>(initValues: T[], options?: Partial<ParentConfig<T>>): [Setter<E | null>, Accessor<Store<T[]>>, ReturnType<typeof createStore>[1], (config?: Partial<ParentConfig<T>>) => void]
Hook for adding drag and drop/sortable support to a list of items.
@paraminitValues - Initial list of data.@paramoptions - The drag and drop configuration.@returns
useDragAndDrop
} from "@formkit/drag-and-drop/solid";
export function function MyComponent(): JSX.ElementMyComponent() { const const mockFileNames: string[]mockFileNames = [ "dungeon_master.exe", "map_1.dat", "map_2.dat", "character1.txt", "character2.txt", "shell32.dll", "README.txt", ]; const [const parent1: Setter<HTMLUListElement | null>parent1, const files1: Accessor<string[]>files1] = useDragAndDrop<HTMLUListElement, string>(initValues: string[], options?: Partial<ParentConfig<string>> | undefined): [Setter<HTMLUListElement | null>, Accessor<...>, SetStoreFunction<...>, (config?: Partial<...> | undefined) => void]
Hook for adding drag and drop/sortable support to a list of items.
@paraminitValues - Initial list of data.@paramoptions - The drag and drop configuration.@returns
useDragAndDrop
<HTMLUListElement, string>(
const mockFileNames: string[]mockFileNames, { group?: string | undefined
The group that the parent belongs to. This is used for allowing multiple parents to transfer nodes between each other.
group
: "A",
multiDrag?: boolean | undefinedmultiDrag: true, selectedClass?: string | undefined
The class to add to a node when it is selected (clicked or pressed).
selectedClass
: "bg-blue-500 text-white",
} ); const [const parent2: Setter<HTMLUListElement | null>parent2, const files2: Accessor<string[]>files2] = useDragAndDrop<HTMLUListElement, string>(initValues: string[], options?: Partial<ParentConfig<string>> | undefined): [Setter<HTMLUListElement | null>, Accessor<...>, SetStoreFunction<...>, (config?: Partial<...> | undefined) => void]
Hook for adding drag and drop/sortable support to a list of items.
@paraminitValues - Initial list of data.@paramoptions - The drag and drop configuration.@returns
useDragAndDrop
<HTMLUListElement, string>([], {
group?: string | undefined
The group that the parent belongs to. This is used for allowing multiple parents to transfer nodes between each other.
group
: "A",
multiDrag?: boolean | undefinedmultiDrag: true, selectedClass?: string | undefined
The class to add to a node when it is selected (clicked or pressed).
selectedClass
: "bg-blue-500 text-white",
}); return ( <JSX.HTMLElementTags.div: JSX.HTMLAttributes<HTMLDivElement>div JSX.HTMLAttributes<HTMLDivElement>.class?: string | undefinedclass="file-manager"> <JSX.HTMLElementTags.ul: JSX.HTMLAttributes<HTMLUListElement>ul ref?: HTMLUListElement | ((el: HTMLUListElement) => void) | undefinedref={const parent1: Setter<HTMLUListElement | null>parent1} JSX.HTMLAttributes<T>.class?: string | undefinedclass="file-list"> <
function For<T extends readonly any[], U extends JSX.Element>(props: {
    each: T | undefined | null | false;
    fallback?: JSX.Element;
    children: (item: T[number], index: Accessor<number>) => U;
}): JSX.Element
Creates a list elements from a list it receives a map function as its child that receives a list element and an accessor with the index and returns a JSX-Element; if the list is empty, an optional fallback is returned: ```typescript <For each={items} fallback={<div>No items</div>}> {(item, index) => <div data-index={index()}>{item}</div>} </For> ``` If you have a list with fixed indices and changing values, consider using `<Index>` instead.
@descriptionhttps://docs.solidjs.com/reference/components/for
For
each: false | string[] | null | undefinedeach={const files1: () => string[]files1()}>{(file: stringfile) => <JSX.HTMLElementTags.li: JSX.LiHTMLAttributes<HTMLLIElement>li JSX.HTMLAttributes<T>.class?: string | undefinedclass="file">{file: stringfile}</JSX.HTMLElementTags.li: JSX.LiHTMLAttributes<HTMLLIElement>li>}</
function For<T extends readonly any[], U extends JSX.Element>(props: {
    each: T | undefined | null | false;
    fallback?: JSX.Element;
    children: (item: T[number], index: Accessor<number>) => U;
}): JSX.Element
Creates a list elements from a list it receives a map function as its child that receives a list element and an accessor with the index and returns a JSX-Element; if the list is empty, an optional fallback is returned: ```typescript <For each={items} fallback={<div>No items</div>}> {(item, index) => <div data-index={index()}>{item}</div>} </For> ``` If you have a list with fixed indices and changing values, consider using `<Index>` instead.
@descriptionhttps://docs.solidjs.com/reference/components/for
For
>
</JSX.HTMLElementTags.ul: JSX.HTMLAttributes<HTMLUListElement>ul> <JSX.HTMLElementTags.ul: JSX.HTMLAttributes<HTMLUListElement>ul ref?: HTMLUListElement | ((el: HTMLUListElement) => void) | undefinedref={const parent2: Setter<HTMLUListElement | null>parent2} JSX.HTMLAttributes<T>.class?: string | undefinedclass="file-list"> <
function For<T extends readonly any[], U extends JSX.Element>(props: {
    each: T | undefined | null | false;
    fallback?: JSX.Element;
    children: (item: T[number], index: Accessor<number>) => U;
}): JSX.Element
Creates a list elements from a list it receives a map function as its child that receives a list element and an accessor with the index and returns a JSX-Element; if the list is empty, an optional fallback is returned: ```typescript <For each={items} fallback={<div>No items</div>}> {(item, index) => <div data-index={index()}>{item}</div>} </For> ``` If you have a list with fixed indices and changing values, consider using `<Index>` instead.
@descriptionhttps://docs.solidjs.com/reference/components/for
For
each: false | string[] | null | undefinedeach={const files2: () => string[]files2()}>{(file: stringfile) => <JSX.HTMLElementTags.li: JSX.LiHTMLAttributes<HTMLLIElement>li JSX.HTMLAttributes<T>.class?: string | undefinedclass="file">{file: stringfile}</JSX.HTMLElementTags.li: JSX.LiHTMLAttributes<HTMLLIElement>li>}</
function For<T extends readonly any[], U extends JSX.Element>(props: {
    each: T | undefined | null | false;
    fallback?: JSX.Element;
    children: (item: T[number], index: Accessor<number>) => U;
}): JSX.Element
Creates a list elements from a list it receives a map function as its child that receives a list element and an accessor with the index and returns a JSX-Element; if the list is empty, an optional fallback is returned: ```typescript <For each={items} fallback={<div>No items</div>}> {(item, index) => <div data-index={index()}>{item}</div>} </For> ``` If you have a list with fixed indices and changing values, consider using `<Index>` instead.
@descriptionhttps://docs.solidjs.com/reference/components/for
For
>
</JSX.HTMLElementTags.ul: JSX.HTMLAttributes<HTMLUListElement>ul> </JSX.HTMLElementTags.div: JSX.HTMLAttributes<HTMLDivElement>div> ); }
import { const reactive: <T extends DataSource>(data: T, state?: ReactiveProxyState) => ReactiveProxy<T>
reactive is an alias for r
reactive
, const html: (strings: TemplateStringsArray, ...expSlots: any[]) => ArrowTemplate
html is an alias for t
html
} from "@arrow-js/core";
import { function dragAndDrop<T>({ parent, getValues, setValues, config, }: DragAndDrop<T>): void
Initializes the drag and drop functionality for a given parent.
@paramdragAndDrop - The drag and drop configuration.@returnsvoid
dragAndDrop
} from "@formkit/drag-and-drop";
const
const state: ReactiveProxy<{
    files1: string[];
    files2: string[];
}>
state
=
reactive<{
    files1: string[];
    files2: string[];
}>(data: {
    files1: string[];
    files2: string[];
}, state?: ReactiveProxyState): ReactiveProxy<{
    files1: string[];
    files2: string[];
}>
Given a data object, often an object literal, return a proxy of that object with mutation observers for each property.
@paramdata@returnsReactiveProxy
reactive
({
files1: string[]files1: [ "dungeon_master.exe", "map_1.dat", "map_2.dat", "character1.txt", "character2.txt", "shell32.dll", "README.txt", ], files2: string[]files2: [] as string[], }); dragAndDrop<string>({ parent, getValues, setValues, config, }: DragAndDrop<string>): void
Initializes the drag and drop functionality for a given parent.
@paramdragAndDrop - The drag and drop configuration.@returnsvoid
dragAndDrop
<string>({
DragAndDrop<string>.parent: HTMLElement
The parent element that will contain the draggable nodes.
parent
: var document: Document
[MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/document)
document
.Document.getElementById(elementId: string): HTMLElement | null
Returns a reference to the first object with the specified value of the ID attribute.
@paramelementId String that specifies the ID value.
getElementById
("parent1")!,
DragAndDrop<string>.getValues: (parent: HTMLElement) => string[]
A function that returns the values assigned to the parent.
getValues
: () =>
const state: ReactiveProxy<{
    files1: string[];
    files2: string[];
}>
state
.files1: ReactiveProxy<string[]>files1,
DragAndDrop<string>.setValues: (values: string[], parent: HTMLElement) => void
A function that sets the values assigned to the parent.
setValues
: (newValues: string[]newValues) => {
const state: ReactiveProxy<{
    files1: string[];
    files2: string[];
}>
state
.files1: ReactiveProxy<string[]>files1 = reactive<string[]>(data: string[], state?: ReactiveProxyState): ReactiveProxy<string[]>
Given a data object, often an object literal, return a proxy of that object with mutation observers for each property.
@paramdata@returnsReactiveProxy
reactive
(newValues: string[]newValues);
}, DragAndDrop<string>.config?: Partial<ParentConfig<string>> | undefined
An optional configuration object.
config
: {
group?: string | undefined
The group that the parent belongs to. This is used for allowing multiple parents to transfer nodes between each other.
group
: "A",
multiDrag?: boolean | undefinedmultiDrag: true, selectedClass?: string | undefined
The class to add to a node when it is selected (clicked or pressed).
selectedClass
: "bg-blue-500 text-white",
}, }); dragAndDrop<string>({ parent, getValues, setValues, config, }: DragAndDrop<string>): void
Initializes the drag and drop functionality for a given parent.
@paramdragAndDrop - The drag and drop configuration.@returnsvoid
dragAndDrop
<string>({
DragAndDrop<string>.parent: HTMLElement
The parent element that will contain the draggable nodes.
parent
: var document: Document
[MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/document)
document
.Document.getElementById(elementId: string): HTMLElement | null
Returns a reference to the first object with the specified value of the ID attribute.
@paramelementId String that specifies the ID value.
getElementById
("parent2")!,
DragAndDrop<string>.getValues: (parent: HTMLElement) => string[]
A function that returns the values assigned to the parent.
getValues
: () =>
const state: ReactiveProxy<{
    files1: string[];
    files2: string[];
}>
state
.files2: ReactiveProxy<string[]>files2,
DragAndDrop<string>.setValues: (values: string[], parent: HTMLElement) => void
A function that sets the values assigned to the parent.
setValues
: (newValues: string[]newValues) => {
const state: ReactiveProxy<{
    files1: string[];
    files2: string[];
}>
state
.files2: ReactiveProxy<string[]>files2 = reactive<string[]>(data: string[], state?: ReactiveProxyState): ReactiveProxy<string[]>
Given a data object, often an object literal, return a proxy of that object with mutation observers for each property.
@paramdata@returnsReactiveProxy
reactive
(newValues: string[]newValues);
}, DragAndDrop<string>.config?: Partial<ParentConfig<string>> | undefined
An optional configuration object.
config
: {
group?: string | undefined
The group that the parent belongs to. This is used for allowing multiple parents to transfer nodes between each other.
group
: "A",
multiDrag?: boolean | undefinedmultiDrag: true, selectedClass?: string | undefined
The class to add to a node when it is selected (clicked or pressed).
selectedClass
: "bg-blue-500 text-white",
}, }); const html: (strings: TemplateStringsArray, ...expSlots: any[]) => ArrowTemplate
html is an alias for t
html
`
<div class="file-manager"> <ul class="file-list" id="parent1"> ${() =>
const state: ReactiveProxy<{
    files1: string[];
    files2: string[];
}>
state
.files1: ReactiveProxy<string[]>files1.Array<string>.map<void>(callbackfn: (value: string, index: number, array: string[]) => void, thisArg?: any): void[]
Calls a defined callback function on each element of an array, and returns an array that contains the results.
@paramcallbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.@paramthisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
map
((file: stringfile) =>
const html: (strings: TemplateStringsArray, ...expSlots: any[]) => ArrowTemplate
html is an alias for t
html
` <li class="file">${file: stringfile}</li> `.ArrowTemplate.key: (key: ArrowTemplateKey) => void
Adds a key to this template to identify it as a unique instance.
@paramkey - A unique key that identifies this template instance (not index).@returns
key
(file: stringfile)
)} </ul> <ul class="file-list" id="parent2"> ${
const state: ReactiveProxy<{
    files1: string[];
    files2: string[];
}>
state
.files2: ReactiveProxy<string[]>files2.Array<string>.map<void>(callbackfn: (value: string, index: number, array: string[]) => void, thisArg?: any): void[]
Calls a defined callback function on each element of an array, and returns an array that contains the results.
@paramcallbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.@paramthisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
map
((file: stringfile) =>
const html: (strings: TemplateStringsArray, ...expSlots: any[]) => ArrowTemplate
html is an alias for t
html
` <li class="file">${file: stringfile}</li> `.ArrowTemplate.key: (key: ArrowTemplateKey) => void
Adds a key to this template to identify it as a unique instance.
@paramkey - A unique key that identifies this template instance (not index).@returns
key
(file: stringfile)
)} </ul> </div> `(var document: Document
[MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/document)
document
.Document.getElementById(elementId: string): HTMLElement | null
Returns a reference to the first object with the specified value of the ID attribute.
@paramelementId String that specifies the ID value.
getElementById
("app")!);
  • dungeon_master.exe
  • map_1.dat
  • map_2.dat
  • character1.txt
  • character2.txt
  • shell32.dll
  • README.txt

Plugins

Plugins are a powerful way to extend the functionality of the library. They can be used to add new features, modify existing ones, or even create entirely new experiences.

Drop or Swap

The examples seen so far have shown the values of a given list being updated as the end-user drags over the list and its children. To enable behavior where the values of the list are only updated when the user drops the item, use the dropOrSwap plugin.

  • React
  • Vue
  • Solid
  • Native
import React from "react";
import { 
function dropOrSwap<T>(dropSwapConfig?: DropSwapConfig<T>): (parent: HTMLElement) => {
    setup(): void;
} | undefined
dropOrSwap
} from "@formkit/drag-and-drop";
import { function useDragAndDrop<E extends HTMLElement, T = unknown>(list: T[], options?: Partial<ParentConfig<T>>): [React.RefObject<E>, T[], React.Dispatch<React.SetStateAction<T[]>>, (config: Partial<ParentConfig<...>>) => void]
Hook for adding drag and drop/sortable support to a list of items.
@paramlist - Initial list of data.@paramoptions - The drag and drop configuration.@returns
useDragAndDrop
} from "@formkit/drag-and-drop/react";
export function function myComponent(): React.JSX.ElementmyComponent() { const const todoItems: string[]todoItems = [ "Schedule perm", "Rewind VHS tapes", "Make change for the arcade", "Get disposable camera developed", "Learn C++", "Return Nintendo Power Glove", ]; const [const todoSwap: booleantodoSwap, const setTodoSwap: React.Dispatch<React.SetStateAction<boolean>>setTodoSwap] = React.function React.useState<boolean>(initialState: boolean | (() => boolean)): [boolean, React.Dispatch<React.SetStateAction<boolean>>] (+1 overload)
Returns a stateful value, and a function to update it.
@version16.8.0@see{@link https://react.dev/reference/react/useState}
useState
(false);
const [const doneSwap: booleandoneSwap, const setDoneSwap: React.Dispatch<React.SetStateAction<boolean>>setDoneSwap] = React.function React.useState<boolean>(initialState: boolean | (() => boolean)): [boolean, React.Dispatch<React.SetStateAction<boolean>>] (+1 overload)
Returns a stateful value, and a function to update it.
@version16.8.0@see{@link https://react.dev/reference/react/useState}
useState
(false);
const const doneItems: string[]doneItems = ["Pickup new mix-tape from Beth"]; const [const todoList: React.RefObject<HTMLUListElement>todoList, const todos: string[]todos] = useDragAndDrop<HTMLUListElement, string>(list: string[], options?: Partial<ParentConfig<string>> | undefined): [React.RefObject<HTMLUListElement>, string[], React.Dispatch<...>, (config: Partial<...>) => void]
Hook for adding drag and drop/sortable support to a list of items.
@paramlist - Initial list of data.@paramoptions - The drag and drop configuration.@returns
useDragAndDrop
<HTMLUListElement, string>(
const todoItems: string[]todoItems, { group?: string | undefined
The group that the parent belongs to. This is used for allowing multiple parents to transfer nodes between each other.
group
: "todoList",
plugins?: DNDPlugin[] | undefined
An array of functions to use for a given parent.
plugins
: [
dropOrSwap<unknown>(dropSwapConfig?: DropSwapConfig<unknown> | undefined): (parent: HTMLElement) => {
    setup(): void;
} | undefined
dropOrSwap
({
DropSwapConfig<unknown>.shouldSwap?: ((data: ShouldSwapData<unknown>) => boolean) | undefinedshouldSwap: () => { return const todoSwap: booleantodoSwap; }, }), ], } ); const [const doneList: React.RefObject<HTMLUListElement>doneList, const dones: string[]dones] = useDragAndDrop<HTMLUListElement, string>(list: string[], options?: Partial<ParentConfig<string>> | undefined): [React.RefObject<HTMLUListElement>, string[], React.Dispatch<...>, (config: Partial<...>) => void]
Hook for adding drag and drop/sortable support to a list of items.
@paramlist - Initial list of data.@paramoptions - The drag and drop configuration.@returns
useDragAndDrop
<HTMLUListElement, string>(
const doneItems: string[]doneItems, { group?: string | undefined
The group that the parent belongs to. This is used for allowing multiple parents to transfer nodes between each other.
group
: "todoList",
plugins?: DNDPlugin[] | undefined
An array of functions to use for a given parent.
plugins
: [
dropOrSwap<unknown>(dropSwapConfig?: DropSwapConfig<unknown> | undefined): (parent: HTMLElement) => {
    setup(): void;
} | undefined
dropOrSwap
({
DropSwapConfig<unknown>.shouldSwap?: ((data: ShouldSwapData<unknown>) => boolean) | undefinedshouldSwap: () => { return const doneSwap: booleandoneSwap; }, }), ], } ); function function (local function) toggleTodoSwap(): voidtoggleTodoSwap() { const setTodoSwap: (value: React.SetStateAction<boolean>) => voidsetTodoSwap(!const todoSwap: booleantodoSwap); } function function (local function) toggleDoneSwap(): voidtoggleDoneSwap() { const setDoneSwap: (value: React.SetStateAction<boolean>) => voidsetDoneSwap(!const doneSwap: booleandoneSwap); } return ( <JSX.IntrinsicElements.div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>div React.HTMLAttributes<HTMLDivElement>.className?: string | undefinedclassName="kanban-board"> <JSX.IntrinsicElements.ul: React.DetailedHTMLProps<React.HTMLAttributes<HTMLUListElement>, HTMLUListElement>ul React.RefAttributes<HTMLUListElement>.ref?: React.LegacyRef<HTMLUListElement> | undefined
Allows getting a ref to the component instance. Once the component unmounts, React will set `ref.current` to `null` (or call the ref with `null` if you passed a callback ref).
@see{@link https://react.dev/learn/referencing-values-with-refs#refs-and-the-dom React Docs}
ref
={const todoList: React.RefObject<HTMLUListElement>todoList}>
{const todos: string[]todos.Array<string>.map<React.JSX.Element>(callbackfn: (value: string, index: number, array: string[]) => React.JSX.Element, thisArg?: any): React.JSX.Element[]
Calls a defined callback function on each element of an array, and returns an array that contains the results.
@paramcallbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.@paramthisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
map
((todo: stringtodo) => (
<JSX.IntrinsicElements.li: React.DetailedHTMLProps<React.LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>li React.HTMLAttributes<T>.className?: string | undefinedclassName="kanban-item" React.Attributes.key?: React.Key | null | undefinedkey={todo: stringtodo}> {todo: stringtodo} </JSX.IntrinsicElements.li: React.DetailedHTMLProps<React.LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>li> ))} </JSX.IntrinsicElements.ul: React.DetailedHTMLProps<React.HTMLAttributes<HTMLUListElement>, HTMLUListElement>ul> <JSX.IntrinsicElements.button: React.DetailedHTMLProps<React.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>button React.DOMAttributes<HTMLButtonElement>.onClick?: React.MouseEventHandler<HTMLButtonElement> | undefinedonClick={function (local function) toggleTodoSwap(): voidtoggleTodoSwap}> {" "} Toggle {const todoSwap: booleantodoSwap ? "Drop" : "Swap"} </JSX.IntrinsicElements.button: React.DetailedHTMLProps<React.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>button> <JSX.IntrinsicElements.ul: React.DetailedHTMLProps<React.HTMLAttributes<HTMLUListElement>, HTMLUListElement>ul React.RefAttributes<HTMLUListElement>.ref?: React.LegacyRef<HTMLUListElement> | undefined
Allows getting a ref to the component instance. Once the component unmounts, React will set `ref.current` to `null` (or call the ref with `null` if you passed a callback ref).
@see{@link https://react.dev/learn/referencing-values-with-refs#refs-and-the-dom React Docs}
ref
={const doneList: React.RefObject<HTMLUListElement>doneList}>
{const dones: string[]dones.Array<string>.map<React.JSX.Element>(callbackfn: (value: string, index: number, array: string[]) => React.JSX.Element, thisArg?: any): React.JSX.Element[]
Calls a defined callback function on each element of an array, and returns an array that contains the results.
@paramcallbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.@paramthisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
map
((done: stringdone) => (
<JSX.IntrinsicElements.li: React.DetailedHTMLProps<React.LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>li React.HTMLAttributes<T>.className?: string | undefinedclassName="kanban-item" React.Attributes.key?: React.Key | null | undefinedkey={done: stringdone}> {done: stringdone} </JSX.IntrinsicElements.li: React.DetailedHTMLProps<React.LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>li> ))} </JSX.IntrinsicElements.ul: React.DetailedHTMLProps<React.HTMLAttributes<HTMLUListElement>, HTMLUListElement>ul> <JSX.IntrinsicElements.button: React.DetailedHTMLProps<React.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>button React.DOMAttributes<HTMLButtonElement>.onClick?: React.MouseEventHandler<HTMLButtonElement> | undefinedonClick={function (local function) toggleDoneSwap(): voidtoggleDoneSwap}> Toggle {const doneSwap: booleandoneSwap ? "Drop" : "Swap"} </JSX.IntrinsicElements.button: React.DetailedHTMLProps<React.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>button> </JSX.IntrinsicElements.div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>div> ); }
<script setup lang="ts">
import { function ref<T>(value: T): [T] extends [Ref] ? IfAny<T, Ref<T>, T> : Ref<UnwrapRef<T>, UnwrapRef<T> | T> (+1 overload)
Takes an inner value and returns a reactive and mutable ref object, which has a single property `.value` that points to the inner value.
@paramvalue - The object to wrap in the ref.@see{@link https://vuejs.org/api/reactivity-core.html#ref}
ref
} from "vue";
import {
function dropOrSwap<T>(dropSwapConfig?: DropSwapConfig<T>): (parent: HTMLElement) => {
    setup(): void;
} | undefined
dropOrSwap
} from "@formkit/drag-and-drop";
import { function useDragAndDrop<T>(initialValues: T[], options?: Partial<VueParentConfig<T>>): [Ref<HTMLElement | undefined>, Ref<T[]>, (config: Partial<VueParentConfig<T>>) => void]
Creates a new instance of drag and drop and returns the parent element and a ref of the values to use in your template.
@paraminitialValues - The initial values of the parent element.@returnsThe parent element and values for drag and drop.
useDragAndDrop
} from "@formkit/drag-and-drop/vue";
const const todoItems: string[]todoItems = [ "Schedule perm", "Rewind VHS tapes", "Make change for the arcade", "Get disposable camera developed", "Learn C++", "Return Nintendo Power Glove", ]; const const doneItems: string[]doneItems = ["Pickup new mix-tape from Beth"]; const const todoShouldSwap: Ref<boolean, boolean>todoShouldSwap = ref<boolean>(value: boolean): Ref<boolean, boolean> (+1 overload)
Takes an inner value and returns a reactive and mutable ref object, which has a single property `.value` that points to the inner value.
@paramvalue - The object to wrap in the ref.@see{@link https://vuejs.org/api/reactivity-core.html#ref}
ref
(false);
const const doneShouldSwap: Ref<boolean, boolean>doneShouldSwap = ref<boolean>(value: boolean): Ref<boolean, boolean> (+1 overload)
Takes an inner value and returns a reactive and mutable ref object, which has a single property `.value` that points to the inner value.
@paramvalue - The object to wrap in the ref.@see{@link https://vuejs.org/api/reactivity-core.html#ref}
ref
(false);
const [const todoList: Ref<HTMLElement | undefined, HTMLElement | undefined>todoList, const todos: Ref<string[], string[]>todos] = useDragAndDrop<string>(initialValues: string[], options?: Partial<Partial<ParentConfig<string>>> | undefined): [Ref<HTMLElement | undefined, HTMLElement | undefined>, Ref<...>, (config: Partial<...>) => void]
Creates a new instance of drag and drop and returns the parent element and a ref of the values to use in your template.
@paraminitialValues - The initial values of the parent element.@returnsThe parent element and values for drag and drop.
useDragAndDrop
(const todoItems: string[]todoItems, {
group?: string | undefined
The group that the parent belongs to. This is used for allowing multiple parents to transfer nodes between each other.
group
: "todoList",
plugins?: DNDPlugin[] | undefined
An array of functions to use for a given parent.
plugins
: [
dropOrSwap<unknown>(dropSwapConfig?: DropSwapConfig<unknown> | undefined): (parent: HTMLElement) => {
    setup(): void;
} | undefined
dropOrSwap
({
DropSwapConfig<unknown>.shouldSwap?: ((data: ShouldSwapData<unknown>) => boolean) | undefinedshouldSwap: () => const todoShouldSwap: Ref<boolean, boolean>todoShouldSwap.Ref<boolean, boolean>.value: booleanvalue, }), ], }); const [const doneList: Ref<HTMLElement | undefined, HTMLElement | undefined>doneList, const dones: Ref<string[], string[]>dones] = useDragAndDrop<string>(initialValues: string[], options?: Partial<Partial<ParentConfig<string>>> | undefined): [Ref<HTMLElement | undefined, HTMLElement | undefined>, Ref<...>, (config: Partial<...>) => void]
Creates a new instance of drag and drop and returns the parent element and a ref of the values to use in your template.
@paraminitialValues - The initial values of the parent element.@returnsThe parent element and values for drag and drop.
useDragAndDrop
(const doneItems: string[]doneItems, {
group?: string | undefined
The group that the parent belongs to. This is used for allowing multiple parents to transfer nodes between each other.
group
: "todoList",
plugins?: DNDPlugin[] | undefined
An array of functions to use for a given parent.
plugins
: [
dropOrSwap<unknown>(dropSwapConfig?: DropSwapConfig<unknown> | undefined): (parent: HTMLElement) => {
    setup(): void;
} | undefined
dropOrSwap
({
DropSwapConfig<unknown>.shouldSwap?: ((data: ShouldSwapData<unknown>) => boolean) | undefinedshouldSwap: () => const doneShouldSwap: Ref<boolean, boolean>doneShouldSwap.Ref<boolean, boolean>.value: booleanvalue, }), ], }); function function toggleTodoSwap(): voidtoggleTodoSwap() { const todoShouldSwap: Ref<boolean, boolean>todoShouldSwap.Ref<boolean, boolean>.value: booleanvalue = !const todoShouldSwap: Ref<boolean, boolean>todoShouldSwap.Ref<boolean, boolean>.value: booleanvalue; } function function toggleDoneSwap(): voidtoggleDoneSwap() { const doneShouldSwap: Ref<boolean, boolean>doneShouldSwap.Ref<boolean, boolean>.value: booleanvalue = !const doneShouldSwap: Ref<boolean, boolean>doneShouldSwap.Ref<boolean, boolean>.value: booleanvalue; } </script> <template> <div: HTMLAttributes & ReservedPropsdiv HTMLAttributes.class?: anyclass="kanban-board"> <ul: HTMLAttributes & ReservedPropsul ref?: VNodeRef | undefinedref="const todoList: Ref<HTMLElement | undefined, HTMLElement | undefined>todoList" HTMLAttributes.class?: anyclass="kanban-column"> <li: LiHTMLAttributes & ReservedPropsli v-for="const todo: stringtodo in const todos: Ref<string[], string[]>todos" key?: PropertyKey | undefined:key?: PropertyKey | undefinedkey="const todo: stringtodo" HTMLAttributes.class?: anyclass="kanban-item"> {{ const todo: stringtodo }} </li: LiHTMLAttributes & ReservedPropsli> </ul: HTMLAttributes & ReservedPropsul> <div: HTMLAttributes & ReservedPropsdiv> <button: ButtonHTMLAttributes & ReservedPropsbutton @onClick?: ((payload: MouseEvent) => void) | undefinedclick="function toggleTodoSwap(): voidtoggleTodoSwap()" HTMLAttributes.class?: anyclass="bg-indigo-500 text-white font-bold py-2 px-4 rounded-lg mt-4" > Toggle {{ const todoShouldSwap: Ref<boolean, boolean>todoShouldSwap ? "Drop" : "Swap" }} </button: ButtonHTMLAttributes & ReservedPropsbutton> </div: HTMLAttributes & ReservedPropsdiv> <ul: HTMLAttributes & ReservedPropsul ref?: VNodeRef | undefinedref="const doneList: Ref<HTMLElement | undefined, HTMLElement | undefined>doneList" HTMLAttributes.class?: anyclass="kanban-column"> <li: LiHTMLAttributes & ReservedPropsli v-for="const done: stringdone in const dones: Ref<string[], string[]>dones" key?: PropertyKey | undefined:key?: PropertyKey | undefinedkey="const done: stringdone" HTMLAttributes.class?: anyclass="kanban-item"> {{ const done: stringdone }} </li: LiHTMLAttributes & ReservedPropsli> </ul: HTMLAttributes & ReservedPropsul> <div: HTMLAttributes & ReservedPropsdiv> <button: ButtonHTMLAttributes & ReservedPropsbutton @onClick?: ((payload: MouseEvent) => void) | undefinedclick="function toggleDoneSwap(): voidtoggleDoneSwap()" HTMLAttributes.class?: anyclass="bg-indigo-500 text-white font-bold py-2 px-4 rounded-lg mt-4" > Toggle {{ const doneShouldSwap: Ref<boolean, boolean>doneShouldSwap ? "Drop" : "Swap" }} </button: ButtonHTMLAttributes & ReservedPropsbutton> </div: HTMLAttributes & ReservedPropsdiv> </div: HTMLAttributes & ReservedPropsdiv> </template>
/** @jsxImportSource solid-js */
import { function createSignal<T>(): Signal<T | undefined> (+1 overload)
Creates a simple reactive state with a getter and setter ```typescript const [state: Accessor<T>, setState: Setter<T>] = createSignal<T>( value: T, options?: { name?: string, equals?: false | ((prev: T, next: T) => boolean) } ) ```
@paramvalue initial value of the state; if empty, the state's type will automatically extended with undefined; otherwise you need to extend the type manually if you want setting to undefined not be an error@paramoptions optional object with a name for debugging purposes and equals, a comparator function for the previous and next value to allow fine-grained control over the reactivity@returns```typescript [state: Accessor<T>, setState: Setter<T>] ``` * the Accessor is merely a function that returns the current value and registers each call to the reactive root * the Setter is a function that allows directly setting or mutating the value: ```typescript const [count, setCount] = createSignal(0); setCount(count => count + 1); ```@descriptionhttps://docs.solidjs.com/reference/basic-reactivity/create-signal
createSignal
} from "solid-js";
import {
function For<T extends readonly any[], U extends JSX.Element>(props: {
    each: T | undefined | null | false;
    fallback?: JSX.Element;
    children: (item: T[number], index: Accessor<number>) => U;
}): JSX.Element
Creates a list elements from a list it receives a map function as its child that receives a list element and an accessor with the index and returns a JSX-Element; if the list is empty, an optional fallback is returned: ```typescript <For each={items} fallback={<div>No items</div>}> {(item, index) => <div data-index={index()}>{item}</div>} </For> ``` If you have a list with fixed indices and changing values, consider using `<Index>` instead.
@descriptionhttps://docs.solidjs.com/reference/components/for
For
} from "solid-js";
import {
function dropOrSwap<T>(dropSwapConfig?: DropSwapConfig<T>): (parent: HTMLElement) => {
    setup(): void;
} | undefined
dropOrSwap
} from "@formkit/drag-and-drop";
import { function useDragAndDrop<E extends HTMLElement, T = unknown>(initValues: T[], options?: Partial<ParentConfig<T>>): [Setter<E | null>, Accessor<Store<T[]>>, ReturnType<typeof createStore>[1], (config?: Partial<ParentConfig<T>>) => void]
Hook for adding drag and drop/sortable support to a list of items.
@paraminitValues - Initial list of data.@paramoptions - The drag and drop configuration.@returns
useDragAndDrop
} from "@formkit/drag-and-drop/solid";
export function function MyComponent(): JSX.ElementMyComponent() { const const todoItems: string[]todoItems = [ "Schedule perm", "Rewind VHS tapes", "Make change for the arcade", "Get disposable camera developed", "Learn C++", "Return Nintendo Power Glove", ]; const [const todoSwap: Accessor<boolean>todoSwap, const setTodoSwap: Setter<boolean>setTodoSwap] = createSignal<boolean>(value: boolean, options?: SignalOptions<boolean> | undefined): Signal<boolean> (+1 overload)
Creates a simple reactive state with a getter and setter ```typescript const [state: Accessor<T>, setState: Setter<T>] = createSignal<T>( value: T, options?: { name?: string, equals?: false | ((prev: T, next: T) => boolean) } ) ```
@paramvalue initial value of the state; if empty, the state's type will automatically extended with undefined; otherwise you need to extend the type manually if you want setting to undefined not be an error@paramoptions optional object with a name for debugging purposes and equals, a comparator function for the previous and next value to allow fine-grained control over the reactivity@returns```typescript [state: Accessor<T>, setState: Setter<T>] ``` * the Accessor is merely a function that returns the current value and registers each call to the reactive root * the Setter is a function that allows directly setting or mutating the value: ```typescript const [count, setCount] = createSignal(0); setCount(count => count + 1); ```@descriptionhttps://docs.solidjs.com/reference/basic-reactivity/create-signal
createSignal
(false);
const [const doneSwap: Accessor<boolean>doneSwap, const setDoneSwap: Setter<boolean>setDoneSwap] = createSignal<boolean>(value: boolean, options?: SignalOptions<boolean> | undefined): Signal<boolean> (+1 overload)
Creates a simple reactive state with a getter and setter ```typescript const [state: Accessor<T>, setState: Setter<T>] = createSignal<T>( value: T, options?: { name?: string, equals?: false | ((prev: T, next: T) => boolean) } ) ```
@paramvalue initial value of the state; if empty, the state's type will automatically extended with undefined; otherwise you need to extend the type manually if you want setting to undefined not be an error@paramoptions optional object with a name for debugging purposes and equals, a comparator function for the previous and next value to allow fine-grained control over the reactivity@returns```typescript [state: Accessor<T>, setState: Setter<T>] ``` * the Accessor is merely a function that returns the current value and registers each call to the reactive root * the Setter is a function that allows directly setting or mutating the value: ```typescript const [count, setCount] = createSignal(0); setCount(count => count + 1); ```@descriptionhttps://docs.solidjs.com/reference/basic-reactivity/create-signal
createSignal
(false);
const const doneItems: string[]doneItems = ["Pickup new mix-tape from Beth"]; const [const todoList: Setter<HTMLUListElement | null>todoList, const todos: Accessor<string[]>todos] = useDragAndDrop<HTMLUListElement, string>(initValues: string[], options?: Partial<ParentConfig<string>> | undefined): [Setter<HTMLUListElement | null>, Accessor<...>, SetStoreFunction<...>, (config?: Partial<...> | undefined) => void]
Hook for adding drag and drop/sortable support to a list of items.
@paraminitValues - Initial list of data.@paramoptions - The drag and drop configuration.@returns
useDragAndDrop
<HTMLUListElement, string>(
const todoItems: string[]todoItems, { group?: string | undefined
The group that the parent belongs to. This is used for allowing multiple parents to transfer nodes between each other.
group
: "todoList",
plugins?: DNDPlugin[] | undefined
An array of functions to use for a given parent.
plugins
: [
dropOrSwap<unknown>(dropSwapConfig?: DropSwapConfig<unknown> | undefined): (parent: HTMLElement) => {
    setup(): void;
} | undefined
dropOrSwap
({
DropSwapConfig<unknown>.shouldSwap?: ((data: ShouldSwapData<unknown>) => boolean) | undefinedshouldSwap: () => { return const todoSwap: () => booleantodoSwap(); }, }), ], } ); const [const doneList: Setter<HTMLUListElement | null>doneList, const dones: Accessor<string[]>dones] = useDragAndDrop<HTMLUListElement, string>(initValues: string[], options?: Partial<ParentConfig<string>> | undefined): [Setter<HTMLUListElement | null>, Accessor<...>, SetStoreFunction<...>, (config?: Partial<...> | undefined) => void]
Hook for adding drag and drop/sortable support to a list of items.
@paraminitValues - Initial list of data.@paramoptions - The drag and drop configuration.@returns
useDragAndDrop
<HTMLUListElement, string>(
const doneItems: string[]doneItems, { group?: string | undefined
The group that the parent belongs to. This is used for allowing multiple parents to transfer nodes between each other.
group
: "todoList",
plugins?: DNDPlugin[] | undefined
An array of functions to use for a given parent.
plugins
: [
dropOrSwap<unknown>(dropSwapConfig?: DropSwapConfig<unknown> | undefined): (parent: HTMLElement) => {
    setup(): void;
} | undefined
dropOrSwap
({
DropSwapConfig<unknown>.shouldSwap?: ((data: ShouldSwapData<unknown>) => boolean) | undefinedshouldSwap: () => { return const doneSwap: () => booleandoneSwap(); }, }), ], } ); function function (local function) toggleTodoSwap(): voidtoggleTodoSwap() { const setTodoSwap: <boolean>(value: boolean | ((prev: boolean) => boolean)) => boolean (+3 overloads)setTodoSwap(!const todoSwap: () => booleantodoSwap()); } function function (local function) toggleDoneSwap(): voidtoggleDoneSwap() { const setDoneSwap: <boolean>(value: boolean | ((prev: boolean) => boolean)) => boolean (+3 overloads)setDoneSwap(!const doneSwap: () => booleandoneSwap()); } return ( <JSX.HTMLElementTags.div: JSX.HTMLAttributes<HTMLDivElement>div JSX.HTMLAttributes<HTMLDivElement>.class?: string | undefinedclass="kanban-board"> <JSX.HTMLElementTags.ul: JSX.HTMLAttributes<HTMLUListElement>ul ref?: HTMLUListElement | ((el: HTMLUListElement) => void) | undefinedref={const todoList: Setter<HTMLUListElement | null>todoList}> <
function For<T extends readonly any[], U extends JSX.Element>(props: {
    each: T | undefined | null | false;
    fallback?: JSX.Element;
    children: (item: T[number], index: Accessor<number>) => U;
}): JSX.Element
Creates a list elements from a list it receives a map function as its child that receives a list element and an accessor with the index and returns a JSX-Element; if the list is empty, an optional fallback is returned: ```typescript <For each={items} fallback={<div>No items</div>}> {(item, index) => <div data-index={index()}>{item}</div>} </For> ``` If you have a list with fixed indices and changing values, consider using `<Index>` instead.
@descriptionhttps://docs.solidjs.com/reference/components/for
For
each: false | string[] | null | undefinedeach={const todos: () => string[]todos()}>
{(todo: stringtodo) => ( <JSX.HTMLElementTags.li: JSX.LiHTMLAttributes<HTMLLIElement>li JSX.HTMLAttributes<T>.class?: string | undefinedclass="kanban-item" data-key: stringdata-key={todo: stringtodo}> {todo: stringtodo} </JSX.HTMLElementTags.li: JSX.LiHTMLAttributes<HTMLLIElement>li> )} </
function For<T extends readonly any[], U extends JSX.Element>(props: {
    each: T | undefined | null | false;
    fallback?: JSX.Element;
    children: (item: T[number], index: Accessor<number>) => U;
}): JSX.Element
Creates a list elements from a list it receives a map function as its child that receives a list element and an accessor with the index and returns a JSX-Element; if the list is empty, an optional fallback is returned: ```typescript <For each={items} fallback={<div>No items</div>}> {(item, index) => <div data-index={index()}>{item}</div>} </For> ``` If you have a list with fixed indices and changing values, consider using `<Index>` instead.
@descriptionhttps://docs.solidjs.com/reference/components/for
For
>
</JSX.HTMLElementTags.ul: JSX.HTMLAttributes<HTMLUListElement>ul> <JSX.HTMLElementTags.button: JSX.ButtonHTMLAttributes<HTMLButtonElement>button JSX.CustomEventHandlersCamelCase<HTMLButtonElement>.onClick?: JSX.EventHandlerUnion<HTMLButtonElement, MouseEvent, JSX.EventHandler<HTMLButtonElement, MouseEvent>> | undefinedonClick={function (local function) toggleTodoSwap(): voidtoggleTodoSwap}> Toggle {const todoSwap: () => booleantodoSwap() ? "Drop" : "Swap"} </JSX.HTMLElementTags.button: JSX.ButtonHTMLAttributes<HTMLButtonElement>button> <JSX.HTMLElementTags.ul: JSX.HTMLAttributes<HTMLUListElement>ul ref?: HTMLUListElement | ((el: HTMLUListElement) => void) | undefinedref={const doneList: Setter<HTMLUListElement | null>doneList}> <
function For<T extends readonly any[], U extends JSX.Element>(props: {
    each: T | undefined | null | false;
    fallback?: JSX.Element;
    children: (item: T[number], index: Accessor<number>) => U;
}): JSX.Element
Creates a list elements from a list it receives a map function as its child that receives a list element and an accessor with the index and returns a JSX-Element; if the list is empty, an optional fallback is returned: ```typescript <For each={items} fallback={<div>No items</div>}> {(item, index) => <div data-index={index()}>{item}</div>} </For> ``` If you have a list with fixed indices and changing values, consider using `<Index>` instead.
@descriptionhttps://docs.solidjs.com/reference/components/for
For
each: false | string[] | null | undefinedeach={const dones: () => string[]dones()}>
{(done: stringdone) => ( <JSX.HTMLElementTags.li: JSX.LiHTMLAttributes<HTMLLIElement>li JSX.HTMLAttributes<T>.class?: string | undefinedclass="kanban-item" data-key: stringdata-key={done: stringdone}> {done: stringdone} </JSX.HTMLElementTags.li: JSX.LiHTMLAttributes<HTMLLIElement>li> )} </
function For<T extends readonly any[], U extends JSX.Element>(props: {
    each: T | undefined | null | false;
    fallback?: JSX.Element;
    children: (item: T[number], index: Accessor<number>) => U;
}): JSX.Element
Creates a list elements from a list it receives a map function as its child that receives a list element and an accessor with the index and returns a JSX-Element; if the list is empty, an optional fallback is returned: ```typescript <For each={items} fallback={<div>No items</div>}> {(item, index) => <div data-index={index()}>{item}</div>} </For> ``` If you have a list with fixed indices and changing values, consider using `<Index>` instead.
@descriptionhttps://docs.solidjs.com/reference/components/for
For
>
</JSX.HTMLElementTags.ul: JSX.HTMLAttributes<HTMLUListElement>ul> <JSX.HTMLElementTags.button: JSX.ButtonHTMLAttributes<HTMLButtonElement>button JSX.CustomEventHandlersCamelCase<HTMLButtonElement>.onClick?: JSX.EventHandlerUnion<HTMLButtonElement, MouseEvent, JSX.EventHandler<HTMLButtonElement, MouseEvent>> | undefinedonClick={function (local function) toggleDoneSwap(): voidtoggleDoneSwap}> Toggle {const doneSwap: () => booleandoneSwap() ? "Drop" : "Swap"} </JSX.HTMLElementTags.button: JSX.ButtonHTMLAttributes<HTMLButtonElement>button> </JSX.HTMLElementTags.div: JSX.HTMLAttributes<HTMLDivElement>div> ); }
import { const reactive: <T extends DataSource>(data: T, state?: ReactiveProxyState) => ReactiveProxy<T>
reactive is an alias for r
reactive
, const html: (strings: TemplateStringsArray, ...expSlots: any[]) => ArrowTemplate
html is an alias for t
html
} from "@arrow-js/core";
import { function dragAndDrop<T>({ parent, getValues, setValues, config, }: DragAndDrop<T>): void
Initializes the drag and drop functionality for a given parent.
@paramdragAndDrop - The drag and drop configuration.@returnsvoid
dragAndDrop
,
function dropOrSwap<T>(dropSwapConfig?: DropSwapConfig<T>): (parent: HTMLElement) => {
    setup(): void;
} | undefined
dropOrSwap
} from "@formkit/drag-and-drop";
const
const state: ReactiveProxy<{
    todos: string[];
    dones: string[];
    todoSwap: boolean;
    doneSwap: boolean;
}>
state
=
reactive<{
    todos: string[];
    dones: string[];
    todoSwap: boolean;
    doneSwap: boolean;
}>(data: {
    todos: string[];
    dones: string[];
    todoSwap: boolean;
    doneSwap: boolean;
}, state?: ReactiveProxyState): ReactiveProxy<...>
Given a data object, often an object literal, return a proxy of that object with mutation observers for each property.
@paramdata@returnsReactiveProxy
reactive
({
todos: string[]todos: [ "Schedule perm", "Rewind VHS tapes", "Make change for the arcade", "Get disposable camera developed", "Learn C++", "Return Nintendo Power Glove", ], dones: string[]dones: ["Pickup new mix-tape from Beth"], todoSwap: booleantodoSwap: false, doneSwap: booleandoneSwap: false, }); dragAndDrop<string>({ parent, getValues, setValues, config, }: DragAndDrop<string>): void
Initializes the drag and drop functionality for a given parent.
@paramdragAndDrop - The drag and drop configuration.@returnsvoid
dragAndDrop
<string>({
DragAndDrop<string>.parent: HTMLElement
The parent element that will contain the draggable nodes.
parent
: var document: Document
[MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/document)
document
.Document.getElementById(elementId: string): HTMLElement | null
Returns a reference to the first object with the specified value of the ID attribute.
@paramelementId String that specifies the ID value.
getElementById
("todo-list")!,
DragAndDrop<string>.getValues: (parent: HTMLElement) => string[]
A function that returns the values assigned to the parent.
getValues
: () =>
const state: ReactiveProxy<{
    todos: string[];
    dones: string[];
    todoSwap: boolean;
    doneSwap: boolean;
}>
state
.todos: ReactiveProxy<string[]>todos,
DragAndDrop<string>.setValues: (values: string[], parent: HTMLElement) => void
A function that sets the values assigned to the parent.
setValues
: (newValues: string[]newValues) => {
const state: ReactiveProxy<{
    todos: string[];
    dones: string[];
    todoSwap: boolean;
    doneSwap: boolean;
}>
state
.todos: ReactiveProxy<string[]>todos = reactive<string[]>(data: string[], state?: ReactiveProxyState): ReactiveProxy<string[]>
Given a data object, often an object literal, return a proxy of that object with mutation observers for each property.
@paramdata@returnsReactiveProxy
reactive
(newValues: string[]newValues);
}, DragAndDrop<string>.config?: Partial<ParentConfig<string>> | undefined
An optional configuration object.
config
: {
group?: string | undefined
The group that the parent belongs to. This is used for allowing multiple parents to transfer nodes between each other.
group
: "todoList",
plugins?: DNDPlugin[] | undefined
An array of functions to use for a given parent.
plugins
: [
dropOrSwap<unknown>(dropSwapConfig?: DropSwapConfig<unknown> | undefined): (parent: HTMLElement) => {
    setup(): void;
} | undefined
dropOrSwap
({
DropSwapConfig<unknown>.shouldSwap?: ((data: ShouldSwapData<unknown>) => boolean) | undefinedshouldSwap: () =>
const state: ReactiveProxy<{
    todos: string[];
    dones: string[];
    todoSwap: boolean;
    doneSwap: boolean;
}>
state
.todoSwap: booleantodoSwap,
}), ], }, }); dragAndDrop<string>({ parent, getValues, setValues, config, }: DragAndDrop<string>): void
Initializes the drag and drop functionality for a given parent.
@paramdragAndDrop - The drag and drop configuration.@returnsvoid
dragAndDrop
<string>({
DragAndDrop<string>.parent: HTMLElement
The parent element that will contain the draggable nodes.
parent
: var document: Document
[MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/document)
document
.Document.getElementById(elementId: string): HTMLElement | null
Returns a reference to the first object with the specified value of the ID attribute.
@paramelementId String that specifies the ID value.
getElementById
("done-list")!,
DragAndDrop<string>.getValues: (parent: HTMLElement) => string[]
A function that returns the values assigned to the parent.
getValues
: () =>
const state: ReactiveProxy<{
    todos: string[];
    dones: string[];
    todoSwap: boolean;
    doneSwap: boolean;
}>
state
.dones: ReactiveProxy<string[]>dones,
DragAndDrop<string>.setValues: (values: string[], parent: HTMLElement) => void
A function that sets the values assigned to the parent.
setValues
: (newValues: string[]newValues) => {
const state: ReactiveProxy<{
    todos: string[];
    dones: string[];
    todoSwap: boolean;
    doneSwap: boolean;
}>
state
.dones: ReactiveProxy<string[]>dones = reactive<string[]>(data: string[], state?: ReactiveProxyState): ReactiveProxy<string[]>
Given a data object, often an object literal, return a proxy of that object with mutation observers for each property.
@paramdata@returnsReactiveProxy
reactive
(newValues: string[]newValues);
}, DragAndDrop<string>.config?: Partial<ParentConfig<string>> | undefined
An optional configuration object.
config
: {
group?: string | undefined
The group that the parent belongs to. This is used for allowing multiple parents to transfer nodes between each other.
group
: "todoList",
plugins?: DNDPlugin[] | undefined
An array of functions to use for a given parent.
plugins
: [
dropOrSwap<unknown>(dropSwapConfig?: DropSwapConfig<unknown> | undefined): (parent: HTMLElement) => {
    setup(): void;
} | undefined
dropOrSwap
({
DropSwapConfig<unknown>.shouldSwap?: ((data: ShouldSwapData<unknown>) => boolean) | undefinedshouldSwap: () =>
const state: ReactiveProxy<{
    todos: string[];
    dones: string[];
    todoSwap: boolean;
    doneSwap: boolean;
}>
state
.doneSwap: booleandoneSwap,
}), ], }, }); const html: (strings: TemplateStringsArray, ...expSlots: any[]) => ArrowTemplate
html is an alias for t
html
`
<div class="kanban-board"> <ul class="kanban-list" id="todo-list"> ${() =>
const state: ReactiveProxy<{
    todos: string[];
    dones: string[];
    todoSwap: boolean;
    doneSwap: boolean;
}>
state
.todos: ReactiveProxy<string[]>todos.Array<string>.map<void>(callbackfn: (value: string, index: number, array: string[]) => void, thisArg?: any): void[]
Calls a defined callback function on each element of an array, and returns an array that contains the results.
@paramcallbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.@paramthisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
map
((todo: stringtodo) =>
const html: (strings: TemplateStringsArray, ...expSlots: any[]) => ArrowTemplate
html is an alias for t
html
`<li class="kanban-item">${todo: stringtodo}</li>`.ArrowTemplate.key: (key: ArrowTemplateKey) => void
Adds a key to this template to identify it as a unique instance.
@paramkey - A unique key that identifies this template instance (not index).@returns
key
(todo: stringtodo)
)} </ul> <button onclick=${() => (
const state: ReactiveProxy<{
    todos: string[];
    dones: string[];
    todoSwap: boolean;
    doneSwap: boolean;
}>
state
.todoSwap: booleantodoSwap = !
const state: ReactiveProxy<{
    todos: string[];
    dones: string[];
    todoSwap: boolean;
    doneSwap: boolean;
}>
state
.todoSwap: booleantodoSwap)}>
${() => (
const state: ReactiveProxy<{
    todos: string[];
    dones: string[];
    todoSwap: boolean;
    doneSwap: boolean;
}>
state
.todoSwap: booleantodoSwap ? "Disable" : "Enable")} swap
</button> <ul class="kanban-list" id="done-list"> ${
const state: ReactiveProxy<{
    todos: string[];
    dones: string[];
    todoSwap: boolean;
    doneSwap: boolean;
}>
state
.dones: ReactiveProxy<string[]>dones.Array<string>.map<void>(callbackfn: (value: string, index: number, array: string[]) => void, thisArg?: any): void[]
Calls a defined callback function on each element of an array, and returns an array that contains the results.
@paramcallbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.@paramthisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
map
((done: stringdone) =>
const html: (strings: TemplateStringsArray, ...expSlots: any[]) => ArrowTemplate
html is an alias for t
html
`<li class="kanban-item">${done: stringdone}</li>`.ArrowTemplate.key: (key: ArrowTemplateKey) => void
Adds a key to this template to identify it as a unique instance.
@paramkey - A unique key that identifies this template instance (not index).@returns
key
(done: stringdone)
)} </ul> <button onclick=${() => (
const state: ReactiveProxy<{
    todos: string[];
    dones: string[];
    todoSwap: boolean;
    doneSwap: boolean;
}>
state
.doneSwap: booleandoneSwap = !
const state: ReactiveProxy<{
    todos: string[];
    dones: string[];
    todoSwap: boolean;
    doneSwap: boolean;
}>
state
.doneSwap: booleandoneSwap)}>
${() => (
const state: ReactiveProxy<{
    todos: string[];
    dones: string[];
    todoSwap: boolean;
    doneSwap: boolean;
}>
state
.doneSwap: booleandoneSwap ? "Disable" : "Enable")} swap
</button> </div> `(var document: Document
[MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/document)
document
.Document.getElementById(elementId: string): HTMLElement | null
Returns a reference to the first object with the specified value of the ID attribute.
@paramelementId String that specifies the ID value.
getElementById
("app")!);

ToDos

  • Schedule perm
  • Rewind VHS tapes
  • Make change for the arcade
  • Get disposable camera developed
  • Learn C++
  • Return Nintendo Power Glove
["Schedule perm","Rewind VHS tapes","Make change for the arcade","Get disposable camera developed","Learn C++","Return Nintendo Power Glove"]

Complete

  • Pickup new mix-tape from Beth
["Pickup new mix-tape from Beth"]

Insert (Experimental)

Similar to the dropOrSwap plugin, the insert plugin does not update values until the user drops the item. In addition, the insert plugin will render an insert point between the items to indicate where the item will be placed.

  • React
  • Vue
  • Solid
  • Native
import React from "react";
import { 
function insert<T>(insertConfig: InsertConfig<T>): (parent: HTMLElement) => {
    teardown(): void;
    setup(): void;
} | undefined
insert
} from "@formkit/drag-and-drop";
import { function useDragAndDrop<E extends HTMLElement, T = unknown>(list: T[], options?: Partial<ParentConfig<T>>): [React.RefObject<E>, T[], React.Dispatch<React.SetStateAction<T[]>>, (config: Partial<ParentConfig<...>>) => void]
Hook for adding drag and drop/sortable support to a list of items.
@paramlist - Initial list of data.@paramoptions - The drag and drop configuration.@returns
useDragAndDrop
} from "@formkit/drag-and-drop/react";
const const insertPointClasses: string[]insertPointClasses = [ "absolute", "bg-blue-500", "z-[1000]", "rounded-full", "duration-[5ms]", "before:block", 'before:content-["Insert"]', "before:whitespace-nowrap", "before:block", "before:bg-blue-500", "before:py-1", "before:px-2", "before:rounded-full", "before:text-xs", "before:absolute", "before:top-1/2", "before:left-1/2", "before:-translate-y-1/2", "before:-translate-x-1/2", "before:text-white", "before:text-xs", ]; export function function myComponent(): React.JSX.ElementmyComponent() { const const todoItems: string[]todoItems = [ "Schedule perm", "Rewind VHS tapes", "Make change for the arcade", "Get disposable camera developed", "Learn C++", "Return Nintendo Power Glove", ]; const [const todoSwap: booleantodoSwap, const setTodoSwap: React.Dispatch<React.SetStateAction<boolean>>setTodoSwap] = React.function React.useState<boolean>(initialState: boolean | (() => boolean)): [boolean, React.Dispatch<React.SetStateAction<boolean>>] (+1 overload)
Returns a stateful value, and a function to update it.
@version16.8.0@see{@link https://react.dev/reference/react/useState}
useState
(false);
const [const doneSwap: booleandoneSwap, const setDoneSwap: React.Dispatch<React.SetStateAction<boolean>>setDoneSwap] = React.function React.useState<boolean>(initialState: boolean | (() => boolean)): [boolean, React.Dispatch<React.SetStateAction<boolean>>] (+1 overload)
Returns a stateful value, and a function to update it.
@version16.8.0@see{@link https://react.dev/reference/react/useState}
useState
(false);
const const doneItems: string[]doneItems = ["Pickup new mix-tape from Beth"]; const [const todoList: React.RefObject<HTMLUListElement>todoList, const todos: string[]todos] = useDragAndDrop<HTMLUListElement, string>(list: string[], options?: Partial<ParentConfig<string>> | undefined): [React.RefObject<HTMLUListElement>, string[], React.Dispatch<...>, (config: Partial<...>) => void]
Hook for adding drag and drop/sortable support to a list of items.
@paramlist - Initial list of data.@paramoptions - The drag and drop configuration.@returns
useDragAndDrop
<HTMLUListElement, string>(
const todoItems: string[]todoItems, { group?: string | undefined
The group that the parent belongs to. This is used for allowing multiple parents to transfer nodes between each other.
group
: "todoList",
plugins?: DNDPlugin[] | undefined
An array of functions to use for a given parent.
plugins
: [
insert<unknown>(insertConfig: InsertConfig<unknown>): (parent: HTMLElement) => {
    teardown(): void;
    setup(): void;
} | undefined
insert
({
InsertConfig<unknown>.insertPoint: (parent: ParentRecord<unknown>) => HTMLElementinsertPoint: (parent: ParentRecord<unknown>parent) => { const const div: HTMLDivElementdiv = var document: Document
[MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/document)
document
.Document.createElement<"div">(tagName: "div", options?: ElementCreationOptions): HTMLDivElement (+2 overloads)
Creates an instance of the element for the specified tag.
@paramtagName The name of an element. [MDN Reference](https://developer.mozilla.org/docs/Web/API/Document/createElement)
createElement
("div");
for (const const cls: stringcls of const insertPointClasses: string[]insertPointClasses) const div: HTMLDivElementdiv.Element.classList: DOMTokenList
Allows for manipulation of element's class content attribute as a set of whitespace-separated tokens through a DOMTokenList object. [MDN Reference](https://developer.mozilla.org/docs/Web/API/Element/classList)
classList
.DOMTokenList.add(...tokens: string[]): void
Adds all arguments passed, except those already present. Throws a "SyntaxError" DOMException if one of the arguments is the empty string. Throws an "InvalidCharacterError" DOMException if one of the arguments contains any ASCII whitespace. [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMTokenList/add)
add
(const cls: stringcls);
return const div: HTMLDivElementdiv; }, }), ], } ); const [const doneList: React.RefObject<HTMLUListElement>doneList, const dones: string[]dones] = useDragAndDrop<HTMLUListElement, string>(list: string[], options?: Partial<ParentConfig<string>> | undefined): [React.RefObject<HTMLUListElement>, string[], React.Dispatch<...>, (config: Partial<...>) => void]
Hook for adding drag and drop/sortable support to a list of items.
@paramlist - Initial list of data.@paramoptions - The drag and drop configuration.@returns
useDragAndDrop
<HTMLUListElement, string>(
const doneItems: string[]doneItems, { group?: string | undefined
The group that the parent belongs to. This is used for allowing multiple parents to transfer nodes between each other.
group
: "todoList",
plugins?: DNDPlugin[] | undefined
An array of functions to use for a given parent.
plugins
: [
insert<unknown>(insertConfig: InsertConfig<unknown>): (parent: HTMLElement) => {
    teardown(): void;
    setup(): void;
} | undefined
insert
({
InsertConfig<unknown>.insertPoint: (parent: ParentRecord<unknown>) => HTMLElementinsertPoint: (parent: ParentRecord<unknown>parent) => { const const div: HTMLDivElementdiv = var document: Document
[MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/document)
document
.Document.createElement<"div">(tagName: "div", options?: ElementCreationOptions): HTMLDivElement (+2 overloads)
Creates an instance of the element for the specified tag.
@paramtagName The name of an element. [MDN Reference](https://developer.mozilla.org/docs/Web/API/Document/createElement)
createElement
("div");
for (const const cls: stringcls of const insertPointClasses: string[]insertPointClasses) const div: HTMLDivElementdiv.Element.classList: DOMTokenList
Allows for manipulation of element's class content attribute as a set of whitespace-separated tokens through a DOMTokenList object. [MDN Reference](https://developer.mozilla.org/docs/Web/API/Element/classList)
classList
.DOMTokenList.add(...tokens: string[]): void
Adds all arguments passed, except those already present. Throws a "SyntaxError" DOMException if one of the arguments is the empty string. Throws an "InvalidCharacterError" DOMException if one of the arguments contains any ASCII whitespace. [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMTokenList/add)
add
(const cls: stringcls);
return const div: HTMLDivElementdiv; }, }), ], } ); return ( <JSX.IntrinsicElements.div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>div React.HTMLAttributes<HTMLDivElement>.className?: string | undefinedclassName="kanban-board"> <JSX.IntrinsicElements.ul: React.DetailedHTMLProps<React.HTMLAttributes<HTMLUListElement>, HTMLUListElement>ul React.RefAttributes<HTMLUListElement>.ref?: React.LegacyRef<HTMLUListElement> | undefined
Allows getting a ref to the component instance. Once the component unmounts, React will set `ref.current` to `null` (or call the ref with `null` if you passed a callback ref).
@see{@link https://react.dev/learn/referencing-values-with-refs#refs-and-the-dom React Docs}
ref
={const todoList: React.RefObject<HTMLUListElement>todoList}>
{const todos: string[]todos.Array<string>.map<React.JSX.Element>(callbackfn: (value: string, index: number, array: string[]) => React.JSX.Element, thisArg?: any): React.JSX.Element[]
Calls a defined callback function on each element of an array, and returns an array that contains the results.
@paramcallbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.@paramthisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
map
((todo: stringtodo) => (
<JSX.IntrinsicElements.li: React.DetailedHTMLProps<React.LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>li React.HTMLAttributes<T>.className?: string | undefinedclassName="kanban-item" React.Attributes.key?: React.Key | null | undefinedkey={todo: stringtodo}> {todo: stringtodo} </JSX.IntrinsicElements.li: React.DetailedHTMLProps<React.LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>li> ))} </JSX.IntrinsicElements.ul: React.DetailedHTMLProps<React.HTMLAttributes<HTMLUListElement>, HTMLUListElement>ul> <JSX.IntrinsicElements.ul: React.DetailedHTMLProps<React.HTMLAttributes<HTMLUListElement>, HTMLUListElement>ul React.RefAttributes<HTMLUListElement>.ref?: React.LegacyRef<HTMLUListElement> | undefined
Allows getting a ref to the component instance. Once the component unmounts, React will set `ref.current` to `null` (or call the ref with `null` if you passed a callback ref).
@see{@link https://react.dev/learn/referencing-values-with-refs#refs-and-the-dom React Docs}
ref
={const doneList: React.RefObject<HTMLUListElement>doneList}>
{const dones: string[]dones.Array<string>.map<React.JSX.Element>(callbackfn: (value: string, index: number, array: string[]) => React.JSX.Element, thisArg?: any): React.JSX.Element[]
Calls a defined callback function on each element of an array, and returns an array that contains the results.
@paramcallbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.@paramthisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
map
((done: stringdone) => (
<JSX.IntrinsicElements.li: React.DetailedHTMLProps<React.LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>li React.HTMLAttributes<T>.className?: string | undefinedclassName="kanban-item" React.Attributes.key?: React.Key | null | undefinedkey={done: stringdone}> {done: stringdone} </JSX.IntrinsicElements.li: React.DetailedHTMLProps<React.LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>li> ))} </JSX.IntrinsicElements.ul: React.DetailedHTMLProps<React.HTMLAttributes<HTMLUListElement>, HTMLUListElement>ul> </JSX.IntrinsicElements.div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>div> ); }
<script setup lang="ts">
import { function ref<T>(value: T): [T] extends [Ref] ? IfAny<T, Ref<T>, T> : Ref<UnwrapRef<T>, UnwrapRef<T> | T> (+1 overload)
Takes an inner value and returns a reactive and mutable ref object, which has a single property `.value` that points to the inner value.
@paramvalue - The object to wrap in the ref.@see{@link https://vuejs.org/api/reactivity-core.html#ref}
ref
} from "vue";
import {
function insert<T>(insertConfig: InsertConfig<T>): (parent: HTMLElement) => {
    teardown(): void;
    setup(): void;
} | undefined
insert
} from "@formkit/drag-and-drop";
import { function useDragAndDrop<T>(initialValues: T[], options?: Partial<VueParentConfig<T>>): [Ref<HTMLElement | undefined>, Ref<T[]>, (config: Partial<VueParentConfig<T>>) => void]
Creates a new instance of drag and drop and returns the parent element and a ref of the values to use in your template.
@paraminitialValues - The initial values of the parent element.@returnsThe parent element and values for drag and drop.
useDragAndDrop
} from "@formkit/drag-and-drop/vue";
const const insertPointClasses: string[]insertPointClasses = [ "absolute", "bg-blue-500", "z-[1000]", "rounded-full", "duration-[5ms]", "before:block", 'before:content-["Insert"]', "before:whitespace-nowrap", "before:block", "before:bg-blue-500", "before:py-1", "before:px-2", "before:rounded-full", "before:text-xs", "before:absolute", "before:top-1/2", "before:left-1/2", "before:-translate-y-1/2", "before:-translate-x-1/2", "before:text-white", "before:text-xs", ]; const const todoItems: string[]todoItems = [ "Schedule perm", "Rewind VHS tapes", "Make change for the arcade", "Get disposable camera developed", "Learn C++", "Return Nintendo Power Glove", ]; const const doneItems: string[]doneItems = ["Pickup new mix-tape from Beth"]; const const todoShouldSwap: Ref<boolean, boolean>todoShouldSwap = ref<boolean>(value: boolean): Ref<boolean, boolean> (+1 overload)
Takes an inner value and returns a reactive and mutable ref object, which has a single property `.value` that points to the inner value.
@paramvalue - The object to wrap in the ref.@see{@link https://vuejs.org/api/reactivity-core.html#ref}
ref
(false);
const const doneShouldSwap: Ref<boolean, boolean>doneShouldSwap = ref<boolean>(value: boolean): Ref<boolean, boolean> (+1 overload)
Takes an inner value and returns a reactive and mutable ref object, which has a single property `.value` that points to the inner value.
@paramvalue - The object to wrap in the ref.@see{@link https://vuejs.org/api/reactivity-core.html#ref}
ref
(false);
const [const todoList: Ref<HTMLElement | undefined, HTMLElement | undefined>todoList, const todos: Ref<string[], string[]>todos] = useDragAndDrop<string>(initialValues: string[], options?: Partial<Partial<ParentConfig<string>>> | undefined): [Ref<HTMLElement | undefined, HTMLElement | undefined>, Ref<...>, (config: Partial<...>) => void]
Creates a new instance of drag and drop and returns the parent element and a ref of the values to use in your template.
@paraminitialValues - The initial values of the parent element.@returnsThe parent element and values for drag and drop.
useDragAndDrop
(const todoItems: string[]todoItems, {
group?: string | undefined
The group that the parent belongs to. This is used for allowing multiple parents to transfer nodes between each other.
group
: "todoList",
plugins?: DNDPlugin[] | undefined
An array of functions to use for a given parent.
plugins
: [
insert<unknown>(insertConfig: InsertConfig<unknown>): (parent: HTMLElement) => {
    teardown(): void;
    setup(): void;
} | undefined
insert
({
InsertConfig<unknown>.insertPoint: (parent: ParentRecord<unknown>) => HTMLElementinsertPoint: (parent: ParentRecord<unknown>parent) => { const const div: HTMLDivElementdiv = var document: Document
[MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/document)
document
.Document.createElement<"div">(tagName: "div", options?: ElementCreationOptions): HTMLDivElement (+2 overloads)
Creates an instance of the element for the specified tag.
@paramtagName The name of an element. [MDN Reference](https://developer.mozilla.org/docs/Web/API/Document/createElement)
createElement
("div");
for (const const cls: stringcls of const insertPointClasses: string[]insertPointClasses) const div: HTMLDivElementdiv.Element.classList: DOMTokenList
Allows for manipulation of element's class content attribute as a set of whitespace-separated tokens through a DOMTokenList object. [MDN Reference](https://developer.mozilla.org/docs/Web/API/Element/classList)
classList
.DOMTokenList.add(...tokens: string[]): void
Adds all arguments passed, except those already present. Throws a "SyntaxError" DOMException if one of the arguments is the empty string. Throws an "InvalidCharacterError" DOMException if one of the arguments contains any ASCII whitespace. [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMTokenList/add)
add
(const cls: stringcls);
return const div: HTMLDivElementdiv; }, }), ], }); const [const doneList: Ref<HTMLElement | undefined, HTMLElement | undefined>doneList, const dones: Ref<string[], string[]>dones] = useDragAndDrop<string>(initialValues: string[], options?: Partial<Partial<ParentConfig<string>>> | undefined): [Ref<HTMLElement | undefined, HTMLElement | undefined>, Ref<...>, (config: Partial<...>) => void]
Creates a new instance of drag and drop and returns the parent element and a ref of the values to use in your template.
@paraminitialValues - The initial values of the parent element.@returnsThe parent element and values for drag and drop.
useDragAndDrop
(const doneItems: string[]doneItems, {
group?: string | undefined
The group that the parent belongs to. This is used for allowing multiple parents to transfer nodes between each other.
group
: "todoList",
plugins?: DNDPlugin[] | undefined
An array of functions to use for a given parent.
plugins
: [
insert<unknown>(insertConfig: InsertConfig<unknown>): (parent: HTMLElement) => {
    teardown(): void;
    setup(): void;
} | undefined
insert
({
InsertConfig<unknown>.insertPoint: (parent: ParentRecord<unknown>) => HTMLElementinsertPoint: (parent: ParentRecord<unknown>parent) => { const const div: HTMLDivElementdiv = var document: Document
[MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/document)
document
.Document.createElement<"div">(tagName: "div", options?: ElementCreationOptions): HTMLDivElement (+2 overloads)
Creates an instance of the element for the specified tag.
@paramtagName The name of an element. [MDN Reference](https://developer.mozilla.org/docs/Web/API/Document/createElement)
createElement
("div");
for (const const cls: stringcls of const insertPointClasses: string[]insertPointClasses) const div: HTMLDivElementdiv.Element.classList: DOMTokenList
Allows for manipulation of element's class content attribute as a set of whitespace-separated tokens through a DOMTokenList object. [MDN Reference](https://developer.mozilla.org/docs/Web/API/Element/classList)
classList
.DOMTokenList.add(...tokens: string[]): void
Adds all arguments passed, except those already present. Throws a "SyntaxError" DOMException if one of the arguments is the empty string. Throws an "InvalidCharacterError" DOMException if one of the arguments contains any ASCII whitespace. [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMTokenList/add)
add
(const cls: stringcls);
return const div: HTMLDivElementdiv; }, }), ], }); function function toggleTodoSwap(): voidtoggleTodoSwap() { const todoShouldSwap: Ref<boolean, boolean>todoShouldSwap.Ref<boolean, boolean>.value: booleanvalue = !const todoShouldSwap: Ref<boolean, boolean>todoShouldSwap.Ref<boolean, boolean>.value: booleanvalue; } function function toggleDoneSwap(): voidtoggleDoneSwap() { const doneShouldSwap: Ref<boolean, boolean>doneShouldSwap.Ref<boolean, boolean>.value: booleanvalue = !const doneShouldSwap: Ref<boolean, boolean>doneShouldSwap.Ref<boolean, boolean>.value: booleanvalue; } </script> <template> <div: HTMLAttributes & ReservedPropsdiv HTMLAttributes.class?: anyclass="kanban-board"> <ul: HTMLAttributes & ReservedPropsul ref?: VNodeRef | undefinedref="const todoList: Ref<HTMLElement | undefined, HTMLElement | undefined>todoList" HTMLAttributes.class?: anyclass="kanban-column"> <li: LiHTMLAttributes & ReservedPropsli v-for="const todo: stringtodo in const todos: Ref<string[], string[]>todos" key?: PropertyKey | undefined:key?: PropertyKey | undefinedkey="const todo: stringtodo" HTMLAttributes.class?: anyclass="kanban-item"> {{ const todo: stringtodo }} </li: LiHTMLAttributes & ReservedPropsli> </ul: HTMLAttributes & ReservedPropsul> <div: HTMLAttributes & ReservedPropsdiv> <button: ButtonHTMLAttributes & ReservedPropsbutton @onClick?: ((payload: MouseEvent) => void) | undefinedclick="function toggleTodoSwap(): voidtoggleTodoSwap()" HTMLAttributes.class?: anyclass="bg-indigo-500 text-white font-bold py-2 px-4 rounded-lg mt-4" > Toggle {{ const todoShouldSwap: Ref<boolean, boolean>todoShouldSwap ? "Drop" : "Swap" }} </button: ButtonHTMLAttributes & ReservedPropsbutton> </div: HTMLAttributes & ReservedPropsdiv> <ul: HTMLAttributes & ReservedPropsul ref?: VNodeRef | undefinedref="const doneList: Ref<HTMLElement | undefined, HTMLElement | undefined>doneList" HTMLAttributes.class?: anyclass="kanban-column"> <li: LiHTMLAttributes & ReservedPropsli v-for="const done: stringdone in const dones: Ref<string[], string[]>dones" key?: PropertyKey | undefined:key?: PropertyKey | undefinedkey="const done: stringdone" HTMLAttributes.class?: anyclass="kanban-item"> {{ const done: stringdone }} </li: LiHTMLAttributes & ReservedPropsli> </ul: HTMLAttributes & ReservedPropsul> <div: HTMLAttributes & ReservedPropsdiv> <button: ButtonHTMLAttributes & ReservedPropsbutton @onClick?: ((payload: MouseEvent) => void) | undefinedclick="function toggleDoneSwap(): voidtoggleDoneSwap()" HTMLAttributes.class?: anyclass="bg-indigo-500 text-white font-bold py-2 px-4 rounded-lg mt-4" > Toggle {{ const doneShouldSwap: Ref<boolean, boolean>doneShouldSwap ? "Drop" : "Swap" }} </button: ButtonHTMLAttributes & ReservedPropsbutton> </div: HTMLAttributes & ReservedPropsdiv> </div: HTMLAttributes & ReservedPropsdiv> </template>
/** @jsxImportSource solid-js */
import { function createSignal<T>(): Signal<T | undefined> (+1 overload)
Creates a simple reactive state with a getter and setter ```typescript const [state: Accessor<T>, setState: Setter<T>] = createSignal<T>( value: T, options?: { name?: string, equals?: false | ((prev: T, next: T) => boolean) } ) ```
@paramvalue initial value of the state; if empty, the state's type will automatically extended with undefined; otherwise you need to extend the type manually if you want setting to undefined not be an error@paramoptions optional object with a name for debugging purposes and equals, a comparator function for the previous and next value to allow fine-grained control over the reactivity@returns```typescript [state: Accessor<T>, setState: Setter<T>] ``` * the Accessor is merely a function that returns the current value and registers each call to the reactive root * the Setter is a function that allows directly setting or mutating the value: ```typescript const [count, setCount] = createSignal(0); setCount(count => count + 1); ```@descriptionhttps://docs.solidjs.com/reference/basic-reactivity/create-signal
createSignal
} from "solid-js";
import {
function For<T extends readonly any[], U extends JSX.Element>(props: {
    each: T | undefined | null | false;
    fallback?: JSX.Element;
    children: (item: T[number], index: Accessor<number>) => U;
}): JSX.Element
Creates a list elements from a list it receives a map function as its child that receives a list element and an accessor with the index and returns a JSX-Element; if the list is empty, an optional fallback is returned: ```typescript <For each={items} fallback={<div>No items</div>}> {(item, index) => <div data-index={index()}>{item}</div>} </For> ``` If you have a list with fixed indices and changing values, consider using `<Index>` instead.
@descriptionhttps://docs.solidjs.com/reference/components/for
For
} from "solid-js";
import {
function insert<T>(insertConfig: InsertConfig<T>): (parent: HTMLElement) => {
    teardown(): void;
    setup(): void;
} | undefined
insert
} from "@formkit/drag-and-drop";
import { function useDragAndDrop<E extends HTMLElement, T = unknown>(initValues: T[], options?: Partial<ParentConfig<T>>): [Setter<E | null>, Accessor<Store<T[]>>, ReturnType<typeof createStore>[1], (config?: Partial<ParentConfig<T>>) => void]
Hook for adding drag and drop/sortable support to a list of items.
@paraminitValues - Initial list of data.@paramoptions - The drag and drop configuration.@returns
useDragAndDrop
} from "@formkit/drag-and-drop/solid";
const const insertPointClasses: string[]insertPointClasses = [ "absolute", "bg-blue-500", "z-[1000]", "rounded-full", "duration-[5ms]", "before:block", 'before:content-["Insert"]', "before:whitespace-nowrap", "before:block", "before:bg-blue-500", "before:py-1", "before:px-2", "before:rounded-full", "before:text-xs", "before:absolute", "before:top-1/2", "before:left-1/2", "before:-translate-y-1/2", "before:-translate-x-1/2", "before:text-white", "before:text-xs", ]; export function function MyComponent(): JSX.ElementMyComponent() { const const todoItems: string[]todoItems = [ "Schedule perm", "Rewind VHS tapes", "Make change for the arcade", "Get disposable camera developed", "Learn C++", "Return Nintendo Power Glove", ]; const [const todoSwap: Accessor<boolean>todoSwap, const setTodoSwap: Setter<boolean>setTodoSwap] = createSignal<boolean>(value: boolean, options?: SignalOptions<boolean> | undefined): Signal<boolean> (+1 overload)
Creates a simple reactive state with a getter and setter ```typescript const [state: Accessor<T>, setState: Setter<T>] = createSignal<T>( value: T, options?: { name?: string, equals?: false | ((prev: T, next: T) => boolean) } ) ```
@paramvalue initial value of the state; if empty, the state's type will automatically extended with undefined; otherwise you need to extend the type manually if you want setting to undefined not be an error@paramoptions optional object with a name for debugging purposes and equals, a comparator function for the previous and next value to allow fine-grained control over the reactivity@returns```typescript [state: Accessor<T>, setState: Setter<T>] ``` * the Accessor is merely a function that returns the current value and registers each call to the reactive root * the Setter is a function that allows directly setting or mutating the value: ```typescript const [count, setCount] = createSignal(0); setCount(count => count + 1); ```@descriptionhttps://docs.solidjs.com/reference/basic-reactivity/create-signal
createSignal
(false);
const [const doneSwap: Accessor<boolean>doneSwap, const setDoneSwap: Setter<boolean>setDoneSwap] = createSignal<boolean>(value: boolean, options?: SignalOptions<boolean> | undefined): Signal<boolean> (+1 overload)
Creates a simple reactive state with a getter and setter ```typescript const [state: Accessor<T>, setState: Setter<T>] = createSignal<T>( value: T, options?: { name?: string, equals?: false | ((prev: T, next: T) => boolean) } ) ```
@paramvalue initial value of the state; if empty, the state's type will automatically extended with undefined; otherwise you need to extend the type manually if you want setting to undefined not be an error@paramoptions optional object with a name for debugging purposes and equals, a comparator function for the previous and next value to allow fine-grained control over the reactivity@returns```typescript [state: Accessor<T>, setState: Setter<T>] ``` * the Accessor is merely a function that returns the current value and registers each call to the reactive root * the Setter is a function that allows directly setting or mutating the value: ```typescript const [count, setCount] = createSignal(0); setCount(count => count + 1); ```@descriptionhttps://docs.solidjs.com/reference/basic-reactivity/create-signal
createSignal
(false);
const const doneItems: string[]doneItems = ["Pickup new mix-tape from Beth"]; const [const todoList: Setter<HTMLUListElement | null>todoList, const todos: Accessor<string[]>todos] = useDragAndDrop<HTMLUListElement, string>(initValues: string[], options?: Partial<ParentConfig<string>> | undefined): [Setter<HTMLUListElement | null>, Accessor<...>, SetStoreFunction<...>, (config?: Partial<...> | undefined) => void]
Hook for adding drag and drop/sortable support to a list of items.
@paraminitValues - Initial list of data.@paramoptions - The drag and drop configuration.@returns
useDragAndDrop
<HTMLUListElement, string>(
const todoItems: string[]todoItems, { group?: string | undefined
The group that the parent belongs to. This is used for allowing multiple parents to transfer nodes between each other.
group
: "todoList",
plugins?: DNDPlugin[] | undefined
An array of functions to use for a given parent.
plugins
: [
insert<unknown>(insertConfig: InsertConfig<unknown>): (parent: HTMLElement) => {
    teardown(): void;
    setup(): void;
} | undefined
insert
({
InsertConfig<unknown>.insertPoint: (parent: ParentRecord<unknown>) => HTMLElementinsertPoint: (parent: ParentRecord<unknown>parent) => { const const div: HTMLDivElementdiv = var document: Document
[MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/document)
document
.Document.createElement<"div">(tagName: "div", options?: ElementCreationOptions): HTMLDivElement (+2 overloads)
Creates an instance of the element for the specified tag.
@paramtagName The name of an element. [MDN Reference](https://developer.mozilla.org/docs/Web/API/Document/createElement)
createElement
("div");
for (const const cls: stringcls of const insertPointClasses: string[]insertPointClasses) const div: HTMLDivElementdiv.Element.classList: DOMTokenList
Allows for manipulation of element's class content attribute as a set of whitespace-separated tokens through a DOMTokenList object. [MDN Reference](https://developer.mozilla.org/docs/Web/API/Element/classList)
classList
.DOMTokenList.add(...tokens: string[]): void
Adds all arguments passed, except those already present. Throws a "SyntaxError" DOMException if one of the arguments is the empty string. Throws an "InvalidCharacterError" DOMException if one of the arguments contains any ASCII whitespace. [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMTokenList/add)
add
(const cls: stringcls);
return const div: HTMLDivElementdiv; }, }), ], } ); const [const doneList: Setter<HTMLUListElement | null>doneList, const dones: Accessor<string[]>dones] = useDragAndDrop<HTMLUListElement, string>(initValues: string[], options?: Partial<ParentConfig<string>> | undefined): [Setter<HTMLUListElement | null>, Accessor<...>, SetStoreFunction<...>, (config?: Partial<...> | undefined) => void]
Hook for adding drag and drop/sortable support to a list of items.
@paraminitValues - Initial list of data.@paramoptions - The drag and drop configuration.@returns
useDragAndDrop
<HTMLUListElement, string>(
const doneItems: string[]doneItems, { group?: string | undefined
The group that the parent belongs to. This is used for allowing multiple parents to transfer nodes between each other.
group
: "todoList",
plugins?: DNDPlugin[] | undefined
An array of functions to use for a given parent.
plugins
: [
insert<unknown>(insertConfig: InsertConfig<unknown>): (parent: HTMLElement) => {
    teardown(): void;
    setup(): void;
} | undefined
insert
({
InsertConfig<unknown>.insertPoint: (parent: ParentRecord<unknown>) => HTMLElementinsertPoint: (parent: ParentRecord<unknown>parent) => { const const div: HTMLDivElementdiv = var document: Document
[MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/document)
document
.Document.createElement<"div">(tagName: "div", options?: ElementCreationOptions): HTMLDivElement (+2 overloads)
Creates an instance of the element for the specified tag.
@paramtagName The name of an element. [MDN Reference](https://developer.mozilla.org/docs/Web/API/Document/createElement)
createElement
("div");
for (const const cls: stringcls of const insertPointClasses: string[]insertPointClasses) const div: HTMLDivElementdiv.Element.classList: DOMTokenList
Allows for manipulation of element's class content attribute as a set of whitespace-separated tokens through a DOMTokenList object. [MDN Reference](https://developer.mozilla.org/docs/Web/API/Element/classList)
classList
.DOMTokenList.add(...tokens: string[]): void
Adds all arguments passed, except those already present. Throws a "SyntaxError" DOMException if one of the arguments is the empty string. Throws an "InvalidCharacterError" DOMException if one of the arguments contains any ASCII whitespace. [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMTokenList/add)
add
(const cls: stringcls);
return const div: HTMLDivElementdiv; }, }), ], } ); function function (local function) toggleTodoSwap(): voidtoggleTodoSwap() { const setTodoSwap: <boolean>(value: boolean | ((prev: boolean) => boolean)) => boolean (+3 overloads)setTodoSwap(!const todoSwap: () => booleantodoSwap()); } function function (local function) toggleDoneSwap(): voidtoggleDoneSwap() { const setDoneSwap: <boolean>(value: boolean | ((prev: boolean) => boolean)) => boolean (+3 overloads)setDoneSwap(!const doneSwap: () => booleandoneSwap()); } return ( <JSX.HTMLElementTags.div: JSX.HTMLAttributes<HTMLDivElement>div JSX.HTMLAttributes<HTMLDivElement>.class?: string | undefinedclass="kanban-board"> <JSX.HTMLElementTags.ul: JSX.HTMLAttributes<HTMLUListElement>ul ref?: HTMLUListElement | ((el: HTMLUListElement) => void) | undefinedref={const todoList: Setter<HTMLUListElement | null>todoList}> <
function For<T extends readonly any[], U extends JSX.Element>(props: {
    each: T | undefined | null | false;
    fallback?: JSX.Element;
    children: (item: T[number], index: Accessor<number>) => U;
}): JSX.Element
Creates a list elements from a list it receives a map function as its child that receives a list element and an accessor with the index and returns a JSX-Element; if the list is empty, an optional fallback is returned: ```typescript <For each={items} fallback={<div>No items</div>}> {(item, index) => <div data-index={index()}>{item}</div>} </For> ``` If you have a list with fixed indices and changing values, consider using `<Index>` instead.
@descriptionhttps://docs.solidjs.com/reference/components/for
For
each: false | string[] | null | undefinedeach={const todos: () => string[]todos()}>
{(todo: stringtodo) => <JSX.HTMLElementTags.li: JSX.LiHTMLAttributes<HTMLLIElement>li JSX.HTMLAttributes<T>.class?: string | undefinedclass="kanban-item">{todo: stringtodo}</JSX.HTMLElementTags.li: JSX.LiHTMLAttributes<HTMLLIElement>li>} </
function For<T extends readonly any[], U extends JSX.Element>(props: {
    each: T | undefined | null | false;
    fallback?: JSX.Element;
    children: (item: T[number], index: Accessor<number>) => U;
}): JSX.Element
Creates a list elements from a list it receives a map function as its child that receives a list element and an accessor with the index and returns a JSX-Element; if the list is empty, an optional fallback is returned: ```typescript <For each={items} fallback={<div>No items</div>}> {(item, index) => <div data-index={index()}>{item}</div>} </For> ``` If you have a list with fixed indices and changing values, consider using `<Index>` instead.
@descriptionhttps://docs.solidjs.com/reference/components/for
For
>
</JSX.HTMLElementTags.ul: JSX.HTMLAttributes<HTMLUListElement>ul> <JSX.HTMLElementTags.ul: JSX.HTMLAttributes<HTMLUListElement>ul ref?: HTMLUListElement | ((el: HTMLUListElement) => void) | undefinedref={const doneList: Setter<HTMLUListElement | null>doneList}> <
function For<T extends readonly any[], U extends JSX.Element>(props: {
    each: T | undefined | null | false;
    fallback?: JSX.Element;
    children: (item: T[number], index: Accessor<number>) => U;
}): JSX.Element
Creates a list elements from a list it receives a map function as its child that receives a list element and an accessor with the index and returns a JSX-Element; if the list is empty, an optional fallback is returned: ```typescript <For each={items} fallback={<div>No items</div>}> {(item, index) => <div data-index={index()}>{item}</div>} </For> ``` If you have a list with fixed indices and changing values, consider using `<Index>` instead.
@descriptionhttps://docs.solidjs.com/reference/components/for
For
each: false | string[] | null | undefinedeach={const dones: () => string[]dones()}>
{(done: stringdone) => <JSX.HTMLElementTags.li: JSX.LiHTMLAttributes<HTMLLIElement>li JSX.HTMLAttributes<T>.class?: string | undefinedclass="kanban-item">{done: stringdone}</JSX.HTMLElementTags.li: JSX.LiHTMLAttributes<HTMLLIElement>li>} </
function For<T extends readonly any[], U extends JSX.Element>(props: {
    each: T | undefined | null | false;
    fallback?: JSX.Element;
    children: (item: T[number], index: Accessor<number>) => U;
}): JSX.Element
Creates a list elements from a list it receives a map function as its child that receives a list element and an accessor with the index and returns a JSX-Element; if the list is empty, an optional fallback is returned: ```typescript <For each={items} fallback={<div>No items</div>}> {(item, index) => <div data-index={index()}>{item}</div>} </For> ``` If you have a list with fixed indices and changing values, consider using `<Index>` instead.
@descriptionhttps://docs.solidjs.com/reference/components/for
For
>
</JSX.HTMLElementTags.ul: JSX.HTMLAttributes<HTMLUListElement>ul> </JSX.HTMLElementTags.div: JSX.HTMLAttributes<HTMLDivElement>div> ); }
import { const reactive: <T extends DataSource>(data: T, state?: ReactiveProxyState) => ReactiveProxy<T>
reactive is an alias for r
reactive
, const html: (strings: TemplateStringsArray, ...expSlots: any[]) => ArrowTemplate
html is an alias for t
html
} from "@arrow-js/core";
import { function dragAndDrop<T>({ parent, getValues, setValues, config, }: DragAndDrop<T>): void
Initializes the drag and drop functionality for a given parent.
@paramdragAndDrop - The drag and drop configuration.@returnsvoid
dragAndDrop
,
function insert<T>(insertConfig: InsertConfig<T>): (parent: HTMLElement) => {
    teardown(): void;
    setup(): void;
} | undefined
insert
} from "@formkit/drag-and-drop";
const const insertPointClasses: string[]insertPointClasses = [ "absolute", "bg-blue-500", "z-[1000]", "rounded-full", "duration-[5ms]", "before:block", 'before:content-["Insert"]', "before:whitespace-nowrap", "before:block", "before:bg-blue-500", "before:py-1", "before:px-2", "before:rounded-full", "before:text-xs", "before:absolute", "before:top-1/2", "before:left-1/2", "before:-translate-y-1/2", "before:-translate-x-1/2", "before:text-white", "before:text-xs", ]; const
const state: ReactiveProxy<{
    todos: string[];
    dones: string[];
    todoSwap: boolean;
    doneSwap: boolean;
}>
state
=
reactive<{
    todos: string[];
    dones: string[];
    todoSwap: boolean;
    doneSwap: boolean;
}>(data: {
    todos: string[];
    dones: string[];
    todoSwap: boolean;
    doneSwap: boolean;
}, state?: ReactiveProxyState): ReactiveProxy<...>
Given a data object, often an object literal, return a proxy of that object with mutation observers for each property.
@paramdata@returnsReactiveProxy
reactive
({
todos: string[]todos: [ "Schedule perm", "Rewind VHS tapes", "Make change for the arcade", "Get disposable camera developed", "Learn C++", "Return Nintendo Power Glove", ], dones: string[]dones: ["Pickup new mix-tape from Beth"], todoSwap: booleantodoSwap: false, doneSwap: booleandoneSwap: false, }); dragAndDrop<string>({ parent, getValues, setValues, config, }: DragAndDrop<string>): void
Initializes the drag and drop functionality for a given parent.
@paramdragAndDrop - The drag and drop configuration.@returnsvoid
dragAndDrop
<string>({
DragAndDrop<string>.parent: HTMLElement
The parent element that will contain the draggable nodes.
parent
: var document: Document
[MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/document)
document
.Document.getElementById(elementId: string): HTMLElement | null
Returns a reference to the first object with the specified value of the ID attribute.
@paramelementId String that specifies the ID value.
getElementById
("todo-list")!,
DragAndDrop<string>.getValues: (parent: HTMLElement) => string[]
A function that returns the values assigned to the parent.
getValues
: () =>
const state: ReactiveProxy<{
    todos: string[];
    dones: string[];
    todoSwap: boolean;
    doneSwap: boolean;
}>
state
.todos: ReactiveProxy<string[]>todos,
DragAndDrop<string>.setValues: (values: string[], parent: HTMLElement) => void
A function that sets the values assigned to the parent.
setValues
: (newValues: string[]newValues) => {
const state: ReactiveProxy<{
    todos: string[];
    dones: string[];
    todoSwap: boolean;
    doneSwap: boolean;
}>
state
.todos: ReactiveProxy<string[]>todos = reactive<string[]>(data: string[], state?: ReactiveProxyState): ReactiveProxy<string[]>
Given a data object, often an object literal, return a proxy of that object with mutation observers for each property.
@paramdata@returnsReactiveProxy
reactive
(newValues: string[]newValues);
}, DragAndDrop<string>.config?: Partial<ParentConfig<string>> | undefined
An optional configuration object.
config
: {
group?: string | undefined
The group that the parent belongs to. This is used for allowing multiple parents to transfer nodes between each other.
group
: "todoList",
plugins?: DNDPlugin[] | undefined
An array of functions to use for a given parent.
plugins
: [
insert<unknown>(insertConfig: InsertConfig<unknown>): (parent: HTMLElement) => {
    teardown(): void;
    setup(): void;
} | undefined
insert
({
InsertConfig<unknown>.insertPoint: (parent: ParentRecord<unknown>) => HTMLElementinsertPoint: (parent: ParentRecord<unknown>parent) => { const const div: HTMLDivElementdiv = var document: Document
[MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/document)
document
.Document.createElement<"div">(tagName: "div", options?: ElementCreationOptions): HTMLDivElement (+2 overloads)
Creates an instance of the element for the specified tag.
@paramtagName The name of an element. [MDN Reference](https://developer.mozilla.org/docs/Web/API/Document/createElement)
createElement
("div");
for (const const cls: stringcls of const insertPointClasses: string[]insertPointClasses) const div: HTMLDivElementdiv.Element.classList: DOMTokenList
Allows for manipulation of element's class content attribute as a set of whitespace-separated tokens through a DOMTokenList object. [MDN Reference](https://developer.mozilla.org/docs/Web/API/Element/classList)
classList
.DOMTokenList.add(...tokens: string[]): void
Adds all arguments passed, except those already present. Throws a "SyntaxError" DOMException if one of the arguments is the empty string. Throws an "InvalidCharacterError" DOMException if one of the arguments contains any ASCII whitespace. [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMTokenList/add)
add
(const cls: stringcls);
return const div: HTMLDivElementdiv; }, }), ], }, }); dragAndDrop<string>({ parent, getValues, setValues, config, }: DragAndDrop<string>): void
Initializes the drag and drop functionality for a given parent.
@paramdragAndDrop - The drag and drop configuration.@returnsvoid
dragAndDrop
<string>({
DragAndDrop<string>.parent: HTMLElement
The parent element that will contain the draggable nodes.
parent
: var document: Document
[MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/document)
document
.Document.getElementById(elementId: string): HTMLElement | null
Returns a reference to the first object with the specified value of the ID attribute.
@paramelementId String that specifies the ID value.
getElementById
("done-list")!,
DragAndDrop<string>.getValues: (parent: HTMLElement) => string[]
A function that returns the values assigned to the parent.
getValues
: () =>
const state: ReactiveProxy<{
    todos: string[];
    dones: string[];
    todoSwap: boolean;
    doneSwap: boolean;
}>
state
.dones: ReactiveProxy<string[]>dones,
DragAndDrop<string>.setValues: (values: string[], parent: HTMLElement) => void
A function that sets the values assigned to the parent.
setValues
: (newValues: string[]newValues) => {
const state: ReactiveProxy<{
    todos: string[];
    dones: string[];
    todoSwap: boolean;
    doneSwap: boolean;
}>
state
.dones: ReactiveProxy<string[]>dones = reactive<string[]>(data: string[], state?: ReactiveProxyState): ReactiveProxy<string[]>
Given a data object, often an object literal, return a proxy of that object with mutation observers for each property.
@paramdata@returnsReactiveProxy
reactive
(newValues: string[]newValues);
}, DragAndDrop<string>.config?: Partial<ParentConfig<string>> | undefined
An optional configuration object.
config
: {
group?: string | undefined
The group that the parent belongs to. This is used for allowing multiple parents to transfer nodes between each other.
group
: "todoList",
plugins?: DNDPlugin[] | undefined
An array of functions to use for a given parent.
plugins
: [
insert<unknown>(insertConfig: InsertConfig<unknown>): (parent: HTMLElement) => {
    teardown(): void;
    setup(): void;
} | undefined
insert
({
InsertConfig<unknown>.insertPoint: (parent: ParentRecord<unknown>) => HTMLElementinsertPoint: () => var document: Document
[MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/document)
document
.Document.createElement<"div">(tagName: "div", options?: ElementCreationOptions): HTMLDivElement (+2 overloads)
Creates an instance of the element for the specified tag.
@paramtagName The name of an element. [MDN Reference](https://developer.mozilla.org/docs/Web/API/Document/createElement)
createElement
("div"),
}), ], }, }); const html: (strings: TemplateStringsArray, ...expSlots: any[]) => ArrowTemplate
html is an alias for t
html
`
<div class="kanban-board"> <ul class="kanban-list" id="todo-list"> ${() =>
const state: ReactiveProxy<{
    todos: string[];
    dones: string[];
    todoSwap: boolean;
    doneSwap: boolean;
}>
state
.todos: ReactiveProxy<string[]>todos.Array<string>.map<void>(callbackfn: (value: string, index: number, array: string[]) => void, thisArg?: any): void[]
Calls a defined callback function on each element of an array, and returns an array that contains the results.
@paramcallbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.@paramthisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
map
((todo: stringtodo) =>
const html: (strings: TemplateStringsArray, ...expSlots: any[]) => ArrowTemplate
html is an alias for t
html
`<li class="kanban-item">${todo: stringtodo}</li>`.ArrowTemplate.key: (key: ArrowTemplateKey) => void
Adds a key to this template to identify it as a unique instance.
@paramkey - A unique key that identifies this template instance (not index).@returns
key
(todo: stringtodo)
)} </ul> <ul class="kanban-list" id="done-list"> ${
const state: ReactiveProxy<{
    todos: string[];
    dones: string[];
    todoSwap: boolean;
    doneSwap: boolean;
}>
state
.dones: ReactiveProxy<string[]>dones.Array<string>.map<void>(callbackfn: (value: string, index: number, array: string[]) => void, thisArg?: any): void[]
Calls a defined callback function on each element of an array, and returns an array that contains the results.
@paramcallbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.@paramthisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
map
((done: stringdone) =>
const html: (strings: TemplateStringsArray, ...expSlots: any[]) => ArrowTemplate
html is an alias for t
html
`<li class="kanban-item">${done: stringdone}</li>`.ArrowTemplate.key: (key: ArrowTemplateKey) => void
Adds a key to this template to identify it as a unique instance.
@paramkey - A unique key that identifies this template instance (not index).@returns
key
(done: stringdone)
)} </ul> </div> `(var document: Document
[MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/document)
document
.Document.getElementById(elementId: string): HTMLElement | null
Returns a reference to the first object with the specified value of the ID attribute.
@paramelementId String that specifies the ID value.
getElementById
("app")!);

ToDos

  • Schedule perm
  • Rewind VHS tapes
  • Make change for the arcade
  • Get disposable camera developed
  • Learn C++
  • Return Nintendo Power Glove
["Schedule perm","Rewind VHS tapes","Make change for the arcade","Get disposable camera developed","Learn C++","Return Nintendo Power Glove"]

Complete

  • Pickup new mix-tape from Beth
["Pickup new mix-tape from Beth"]

Animations (Experimenal)

To add animations to your drag and drop experience, you can use the animations plugin.

  • React
  • Vue
  • Solid
  • Native
import React from "react";
import { 
function animations(animationsConfig?: Partial<AnimationsConfig>): (parent: HTMLElement) => {
    setup(): void;
    setupNodeRemap<T>(data: SetupNodeData<T>): void;
} | undefined
animations
} from "@formkit/drag-and-drop";
import { function useDragAndDrop<E extends HTMLElement, T = unknown>(list: T[], options?: Partial<ParentConfig<T>>): [React.RefObject<E>, T[], React.Dispatch<React.SetStateAction<T[]>>, (config: Partial<ParentConfig<...>>) => void]
Hook for adding drag and drop/sortable support to a list of items.
@paramlist - Initial list of data.@paramoptions - The drag and drop configuration.@returns
useDragAndDrop
} from "@formkit/drag-and-drop/react";
export function function myComponent(): React.JSX.ElementmyComponent() { const [const parent: React.RefObject<HTMLUListElement>parent, const tapes: string[]tapes] = useDragAndDrop<HTMLUListElement, string>(list: string[], options?: Partial<ParentConfig<string>> | undefined): [React.RefObject<HTMLUListElement>, string[], React.Dispatch<...>, (config: Partial<...>) => void]
Hook for adding drag and drop/sortable support to a list of items.
@paramlist - Initial list of data.@paramoptions - The drag and drop configuration.@returns
useDragAndDrop
<HTMLUListElement, string>(
[ "Depeche Mode", "Duran Duran", "Pet Shop Boys", "Kraftwerk", "Tears for Fears", "Spandau Ballet", ], { plugins?: DNDPlugin[] | undefined
An array of functions to use for a given parent.
plugins
: [
function animations(animationsConfig?: Partial<AnimationsConfig>): (parent: HTMLElement) => {
    setup(): void;
    setupNodeRemap<T>(data: SetupNodeData<T>): void;
} | undefined
animations
()] }
); return ( <JSX.IntrinsicElements.ul: React.DetailedHTMLProps<React.HTMLAttributes<HTMLUListElement>, HTMLUListElement>ul React.RefAttributes<HTMLUListElement>.ref?: React.LegacyRef<HTMLUListElement> | undefined
Allows getting a ref to the component instance. Once the component unmounts, React will set `ref.current` to `null` (or call the ref with `null` if you passed a callback ref).
@see{@link https://react.dev/learn/referencing-values-with-refs#refs-and-the-dom React Docs}
ref
={const parent: React.RefObject<HTMLUListElement>parent}>
{const tapes: string[]tapes.Array<string>.map<React.JSX.Element>(callbackfn: (value: string, index: number, array: string[]) => React.JSX.Element, thisArg?: any): React.JSX.Element[]
Calls a defined callback function on each element of an array, and returns an array that contains the results.
@paramcallbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.@paramthisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
map
((tape: stringtape) => (
<JSX.IntrinsicElements.li: React.DetailedHTMLProps<React.LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>li React.HTMLAttributes<HTMLLIElement>.className?: string | undefinedclassName="cassette" data-label: stringdata-label={tape: stringtape} React.Attributes.key?: React.Key | null | undefinedkey={tape: stringtape}> {tape: stringtape} </JSX.IntrinsicElements.li: React.DetailedHTMLProps<React.LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>li> ))} </JSX.IntrinsicElements.ul: React.DetailedHTMLProps<React.HTMLAttributes<HTMLUListElement>, HTMLUListElement>ul> ); }
<script setup lang="ts">
import { 
function animations(animationsConfig?: Partial<AnimationsConfig>): (parent: HTMLElement) => {
    setup(): void;
    setupNodeRemap<T>(data: SetupNodeData<T>): void;
} | undefined
animations
} from "@formkit/drag-and-drop";
import { function useDragAndDrop<T>(initialValues: T[], options?: Partial<VueParentConfig<T>>): [Ref<HTMLElement | undefined>, Ref<T[]>, (config: Partial<VueParentConfig<T>>) => void]
Creates a new instance of drag and drop and returns the parent element and a ref of the values to use in your template.
@paraminitialValues - The initial values of the parent element.@returnsThe parent element and values for drag and drop.
useDragAndDrop
} from "@formkit/drag-and-drop/vue";
const [const parent: Ref<HTMLElement | undefined, HTMLElement | undefined>parent, const tapes: Ref<string[], string[]>tapes] = useDragAndDrop<string>(initialValues: string[], options?: Partial<Partial<ParentConfig<string>>> | undefined): [Ref<HTMLElement | undefined, HTMLElement | undefined>, Ref<...>, (config: Partial<...>) => void]
Creates a new instance of drag and drop and returns the parent element and a ref of the values to use in your template.
@paraminitialValues - The initial values of the parent element.@returnsThe parent element and values for drag and drop.
useDragAndDrop
(
[ "Depeche Mode", "Duran Duran", "Pet Shop Boys", "Kraftwerk", "Tears for Fears", "Spandau Ballet", ], { plugins?: DNDPlugin[] | undefined
An array of functions to use for a given parent.
plugins
: [
function animations(animationsConfig?: Partial<AnimationsConfig>): (parent: HTMLElement) => {
    setup(): void;
    setupNodeRemap<T>(data: SetupNodeData<T>): void;
} | undefined
animations
()] }
); </script> <template> <ul: HTMLAttributes & ReservedPropsul ref?: VNodeRef | undefinedref="const parent: Ref<HTMLElement | undefined, HTMLElement | undefined>parent"> <li: LiHTMLAttributes & ReservedPropsli v-for="const tape: stringtape in const tapes: Ref<string[], string[]>tapes" key?: PropertyKey | undefined:key?: PropertyKey | undefinedkey="const tape: stringtape" HTMLAttributes.class?: anyclass="cassette"> {{ const tape: stringtape }} </li: LiHTMLAttributes & ReservedPropsli> </ul: HTMLAttributes & ReservedPropsul> </template>
/** @jsxImportSource solid-js */
import { 
function For<T extends readonly any[], U extends JSX.Element>(props: {
    each: T | undefined | null | false;
    fallback?: JSX.Element;
    children: (item: T[number], index: Accessor<number>) => U;
}): JSX.Element
Creates a list elements from a list it receives a map function as its child that receives a list element and an accessor with the index and returns a JSX-Element; if the list is empty, an optional fallback is returned: ```typescript <For each={items} fallback={<div>No items</div>}> {(item, index) => <div data-index={index()}>{item}</div>} </For> ``` If you have a list with fixed indices and changing values, consider using `<Index>` instead.
@descriptionhttps://docs.solidjs.com/reference/components/for
For
} from "solid-js";
import {
function animations(animationsConfig?: Partial<AnimationsConfig>): (parent: HTMLElement) => {
    setup(): void;
    setupNodeRemap<T>(data: SetupNodeData<T>): void;
} | undefined
animations
} from "@formkit/drag-and-drop";
import { function useDragAndDrop<E extends HTMLElement, T = unknown>(initValues: T[], options?: Partial<ParentConfig<T>>): [Setter<E | null>, Accessor<Store<T[]>>, ReturnType<typeof createStore>[1], (config?: Partial<ParentConfig<T>>) => void]
Hook for adding drag and drop/sortable support to a list of items.
@paraminitValues - Initial list of data.@paramoptions - The drag and drop configuration.@returns
useDragAndDrop
} from "@formkit/drag-and-drop/solid";
export function function MyComponent(): JSX.ElementMyComponent() { const [const parent: Setter<HTMLUListElement | null>parent, const tapes: Accessor<string[]>tapes] = useDragAndDrop<HTMLUListElement, string>(initValues: string[], options?: Partial<ParentConfig<string>> | undefined): [Setter<HTMLUListElement | null>, Accessor<...>, SetStoreFunction<...>, (config?: Partial<...> | undefined) => void]
Hook for adding drag and drop/sortable support to a list of items.
@paraminitValues - Initial list of data.@paramoptions - The drag and drop configuration.@returns
useDragAndDrop
<HTMLUListElement, string>(
[ "Depeche Mode", "Duran Duran", "Pet Shop Boys", "Kraftwerk", "Tears for Fears", "Spandau Ballet", ], { plugins?: DNDPlugin[] | undefined
An array of functions to use for a given parent.
plugins
: [
function animations(animationsConfig?: Partial<AnimationsConfig>): (parent: HTMLElement) => {
    setup(): void;
    setupNodeRemap<T>(data: SetupNodeData<T>): void;
} | undefined
animations
()] }
); return ( <JSX.HTMLElementTags.ul: JSX.HTMLAttributes<HTMLUListElement>ul ref?: HTMLUListElement | ((el: HTMLUListElement) => void) | undefinedref={const parent: Setter<HTMLUListElement | null>parent}> <
function For<T extends readonly any[], U extends JSX.Element>(props: {
    each: T | undefined | null | false;
    fallback?: JSX.Element;
    children: (item: T[number], index: Accessor<number>) => U;
}): JSX.Element
Creates a list elements from a list it receives a map function as its child that receives a list element and an accessor with the index and returns a JSX-Element; if the list is empty, an optional fallback is returned: ```typescript <For each={items} fallback={<div>No items</div>}> {(item, index) => <div data-index={index()}>{item}</div>} </For> ``` If you have a list with fixed indices and changing values, consider using `<Index>` instead.
@descriptionhttps://docs.solidjs.com/reference/components/for
For
each: false | string[] | null | undefinedeach={const tapes: () => string[]tapes()}>
{(tape: stringtape) => ( <JSX.HTMLElementTags.li: JSX.LiHTMLAttributes<HTMLLIElement>li JSX.HTMLAttributes<HTMLLIElement>.class?: string | undefinedclass="cassette" data-label: stringdata-label={tape: stringtape}> {tape: stringtape} </JSX.HTMLElementTags.li: JSX.LiHTMLAttributes<HTMLLIElement>li> )} </
function For<T extends readonly any[], U extends JSX.Element>(props: {
    each: T | undefined | null | false;
    fallback?: JSX.Element;
    children: (item: T[number], index: Accessor<number>) => U;
}): JSX.Element
Creates a list elements from a list it receives a map function as its child that receives a list element and an accessor with the index and returns a JSX-Element; if the list is empty, an optional fallback is returned: ```typescript <For each={items} fallback={<div>No items</div>}> {(item, index) => <div data-index={index()}>{item}</div>} </For> ``` If you have a list with fixed indices and changing values, consider using `<Index>` instead.
@descriptionhttps://docs.solidjs.com/reference/components/for
For
>
</JSX.HTMLElementTags.ul: JSX.HTMLAttributes<HTMLUListElement>ul> ); }
import { const reactive: <T extends DataSource>(data: T, state?: ReactiveProxyState) => ReactiveProxy<T>
reactive is an alias for r
reactive
, const html: (strings: TemplateStringsArray, ...expSlots: any[]) => ArrowTemplate
html is an alias for t
html
} from "@arrow-js/core";
import { function dragAndDrop<T>({ parent, getValues, setValues, config, }: DragAndDrop<T>): void
Initializes the drag and drop functionality for a given parent.
@paramdragAndDrop - The drag and drop configuration.@returnsvoid
dragAndDrop
,
function animations(animationsConfig?: Partial<AnimationsConfig>): (parent: HTMLElement) => {
    setup(): void;
    setupNodeRemap<T>(data: SetupNodeData<T>): void;
} | undefined
animations
} from "@formkit/drag-and-drop";
const
const state: ReactiveProxy<{
    tapes: string[];
}>
state
=
reactive<{
    tapes: string[];
}>(data: {
    tapes: string[];
}, state?: ReactiveProxyState): ReactiveProxy<{
    tapes: string[];
}>
Given a data object, often an object literal, return a proxy of that object with mutation observers for each property.
@paramdata@returnsReactiveProxy
reactive
({
tapes: string[]tapes: [ "Depeche Mode", "Duran Duran", "Pet Shop Boys", "Kraftwerk", "Tears for Fears", "Spandau Ballet", ], }); const html: (strings: TemplateStringsArray, ...expSlots: any[]) => ArrowTemplate
html is an alias for t
html
`
<ul id="cassettes"> ${() =>
const state: ReactiveProxy<{
    tapes: string[];
}>
state
.tapes: ReactiveProxy<string[]>tapes.Array<string>.map<void>(callbackfn: (value: string, index: number, array: string[]) => void, thisArg?: any): void[]
Calls a defined callback function on each element of an array, and returns an array that contains the results.
@paramcallbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.@paramthisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
map
((tape: stringtape) =>
const html: (strings: TemplateStringsArray, ...expSlots: any[]) => ArrowTemplate
html is an alias for t
html
`<li class="cassette" data-label="${tape: stringtape}">${tape: stringtape}</li>`.ArrowTemplate.key: (key: ArrowTemplateKey) => void
Adds a key to this template to identify it as a unique instance.
@paramkey - A unique key that identifies this template instance (not index).@returns
key
(tape: stringtape)
)} </ul> `(var document: Document
[MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/document)
document
.Document.getElementById(elementId: string): HTMLElement | null
Returns a reference to the first object with the specified value of the ID attribute.
@paramelementId String that specifies the ID value.
getElementById
("app")!);
dragAndDrop<string>({ parent, getValues, setValues, config, }: DragAndDrop<string>): void
Initializes the drag and drop functionality for a given parent.
@paramdragAndDrop - The drag and drop configuration.@returnsvoid
dragAndDrop
<string>({
DragAndDrop<string>.parent: HTMLElement
The parent element that will contain the draggable nodes.
parent
: var document: Document
[MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/document)
document
.Document.getElementById(elementId: string): HTMLElement | null
Returns a reference to the first object with the specified value of the ID attribute.
@paramelementId String that specifies the ID value.
getElementById
("cassettes")!,
DragAndDrop<string>.getValues: (parent: HTMLElement) => string[]
A function that returns the values assigned to the parent.
getValues
: () =>
const state: ReactiveProxy<{
    tapes: string[];
}>
state
.tapes: ReactiveProxy<string[]>tapes,
DragAndDrop<string>.setValues: (values: string[], parent: HTMLElement) => void
A function that sets the values assigned to the parent.
setValues
: (newValues: string[]newValues) => {
const state: ReactiveProxy<{
    tapes: string[];
}>
state
.tapes: ReactiveProxy<string[]>tapes = reactive<string[]>(data: string[], state?: ReactiveProxyState): ReactiveProxy<string[]>
Given a data object, often an object literal, return a proxy of that object with mutation observers for each property.
@paramdata@returnsReactiveProxy
reactive
(newValues: string[]newValues);
}, DragAndDrop<string>.config?: Partial<ParentConfig<string>> | undefined
An optional configuration object.
config
: {
plugins?: DNDPlugin[] | undefined
An array of functions to use for a given parent.
plugins
: [
function animations(animationsConfig?: Partial<AnimationsConfig>): (parent: HTMLElement) => {
    setup(): void;
    setupNodeRemap<T>(data: SetupNodeData<T>): void;
} | undefined
animations
()],
}, });
FormKit Office Jams
  • Depeche Mode
    Cassette Tape
  • Duran Duran
    Cassette Tape
  • Pet Shop Boys
    Cassette Tape
  • Kraftwerk
    Cassette Tape
  • Tears for Fears
    Cassette Tape
  • Spandau Ballet
    Cassette Tape

Events

When using a drag and drop library, often it is useful to be able to listen to particular events, such as when a drag starts or ends. Event listeners can be set at either a global level or at the parent level.

Global

Two global events are available, `dragStarted` and `dragEnded`. In order to listen to global events, import the state object from @formkit/drag-and-drop and register your event listener using the on method.

  • React
  • Vue
  • Solid
  • Native
import React from "react";
import { function useState<S>(initialState: S | (() => S)): [S, React.Dispatch<React.SetStateAction<S>>] (+1 overload)
Returns a stateful value, and a function to update it.
@version16.8.0@see{@link https://react.dev/reference/react/useState}
useState
} from "react";
import { let state: BaseDragState<unknown>
The state of the drag and drop.
@type{BaseDragState<unknown>}
state
} from "@formkit/drag-and-drop";
import { function useDragAndDrop<E extends HTMLElement, T = unknown>(list: T[], options?: Partial<ParentConfig<T>>): [React.RefObject<E>, T[], React.Dispatch<React.SetStateAction<T[]>>, (config: Partial<ParentConfig<...>>) => void]
Hook for adding drag and drop/sortable support to a list of items.
@paramlist - Initial list of data.@paramoptions - The drag and drop configuration.@returns
useDragAndDrop
} from "@formkit/drag-and-drop/react";
export function function App(): React.JSX.ElementApp() { const [const dragStatus: stringdragStatus, const setDragStatus: React.Dispatch<React.SetStateAction<string>>setDragStatus] = useState<string>(initialState: string | (() => string)): [string, React.Dispatch<React.SetStateAction<string>>] (+1 overload)
Returns a stateful value, and a function to update it.
@version16.8.0@see{@link https://react.dev/reference/react/useState}
useState
("Not dragging");
const [const parent: React.RefObject<HTMLUListElement>parent, const items: string[]items] = useDragAndDrop<HTMLUListElement, string>(list: string[], options?: Partial<ParentConfig<string>> | undefined): [React.RefObject<HTMLUListElement>, string[], React.Dispatch<...>, (config: Partial<...>) => void]
Hook for adding drag and drop/sortable support to a list of items.
@paramlist - Initial list of data.@paramoptions - The drag and drop configuration.@returns
useDragAndDrop
<HTMLUListElement, string>([
"🍦 vanilla", "🍫 chocolate", "🍓 strawberry", ]); let state: BaseDragState<unknown>
The state of the drag and drop.
@type{BaseDragState<unknown>}
state
.on: (event: string, callback: (data: unknown) => void) => voidon("dragStarted", () => const setDragStatus: (value: React.SetStateAction<string>) => voidsetDragStatus("Dragging"));
let state: BaseDragState<unknown>
The state of the drag and drop.
@type{BaseDragState<unknown>}
state
.on: (event: string, callback: (data: unknown) => void) => voidon("dragEnded", () => const setDragStatus: (value: React.SetStateAction<string>) => voidsetDragStatus("Not dragging"));
return ( <JSX.IntrinsicElements.div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>div> <JSX.IntrinsicElements.strong: React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement>, HTMLElement>strong>Rank your favorite flavors</JSX.IntrinsicElements.strong: React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement>, HTMLElement>strong> <JSX.IntrinsicElements.br: React.DetailedHTMLProps<React.HTMLAttributes<HTMLBRElement>, HTMLBRElement>br /> <JSX.IntrinsicElements.span: React.DetailedHTMLProps<React.HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>span>{const dragStatus: stringdragStatus}</JSX.IntrinsicElements.span: React.DetailedHTMLProps<React.HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>span> <JSX.IntrinsicElements.br: React.DetailedHTMLProps<React.HTMLAttributes<HTMLBRElement>, HTMLBRElement>br /> <JSX.IntrinsicElements.ul: React.DetailedHTMLProps<React.HTMLAttributes<HTMLUListElement>, HTMLUListElement>ul React.RefAttributes<HTMLUListElement>.ref?: React.LegacyRef<HTMLUListElement> | undefined
Allows getting a ref to the component instance. Once the component unmounts, React will set `ref.current` to `null` (or call the ref with `null` if you passed a callback ref).
@see{@link https://react.dev/learn/referencing-values-with-refs#refs-and-the-dom React Docs}
ref
={const parent: React.RefObject<HTMLUListElement>parent}>
{const items: string[]items.Array<string>.map<React.JSX.Element>(callbackfn: (value: string, index: number, array: string[]) => React.JSX.Element, thisArg?: any): React.JSX.Element[]
Calls a defined callback function on each element of an array, and returns an array that contains the results.
@paramcallbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.@paramthisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
map
((item: stringitem) => {
return <JSX.IntrinsicElements.li: React.DetailedHTMLProps<React.LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>li React.Attributes.key?: React.Key | null | undefinedkey={item: stringitem}>{item: stringitem}</JSX.IntrinsicElements.li: React.DetailedHTMLProps<React.LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>li>; })} </JSX.IntrinsicElements.ul: React.DetailedHTMLProps<React.HTMLAttributes<HTMLUListElement>, HTMLUListElement>ul> </JSX.IntrinsicElements.div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>div> ); }
<script setup lang="ts">
import { function ref<T>(value: T): [T] extends [Ref] ? IfAny<T, Ref<T>, T> : Ref<UnwrapRef<T>, UnwrapRef<T> | T> (+1 overload)
Takes an inner value and returns a reactive and mutable ref object, which has a single property `.value` that points to the inner value.
@paramvalue - The object to wrap in the ref.@see{@link https://vuejs.org/api/reactivity-core.html#ref}
ref
} from "vue";
import { let state: BaseDragState<unknown>
The state of the drag and drop.
@type{BaseDragState<unknown>}
state
} from "@formkit/drag-and-drop";
import { function useDragAndDrop<T>(initialValues: T[], options?: Partial<VueParentConfig<T>>): [Ref<HTMLElement | undefined>, Ref<T[]>, (config: Partial<VueParentConfig<T>>) => void]
Creates a new instance of drag and drop and returns the parent element and a ref of the values to use in your template.
@paraminitialValues - The initial values of the parent element.@returnsThe parent element and values for drag and drop.
useDragAndDrop
} from "@formkit/drag-and-drop/vue";
const const dragStatus: Ref<string, string>dragStatus = ref<string>(value: string): Ref<string, string> (+1 overload)
Takes an inner value and returns a reactive and mutable ref object, which has a single property `.value` that points to the inner value.
@paramvalue - The object to wrap in the ref.@see{@link https://vuejs.org/api/reactivity-core.html#ref}
ref
("Not dragging");
const [const parent: Ref<HTMLElement | undefined, HTMLElement | undefined>parent, const flavors: Ref<string[], string[]>flavors] = useDragAndDrop<string>(initialValues: string[], options?: Partial<Partial<ParentConfig<string>>> | undefined): [Ref<HTMLElement | undefined, HTMLElement | undefined>, Ref<...>, (config: Partial<...>) => void]
Creates a new instance of drag and drop and returns the parent element and a ref of the values to use in your template.
@paraminitialValues - The initial values of the parent element.@returnsThe parent element and values for drag and drop.
useDragAndDrop
([
"🍦 vanilla", "🍫 chocolate", "🍓 strawberry", ]); let state: BaseDragState<unknown>
The state of the drag and drop.
@type{BaseDragState<unknown>}
state
.on: (event: string, callback: (data: unknown) => void) => voidon("dragStarted", () => {
const dragStatus: Ref<string, string>dragStatus.Ref<string, string>.value: stringvalue = "Dragging"; }); let state: BaseDragState<unknown>
The state of the drag and drop.
@type{BaseDragState<unknown>}
state
.on: (event: string, callback: (data: unknown) => void) => voidon("dragEnded", () => {
const dragStatus: Ref<string, string>dragStatus.Ref<string, string>.value: stringvalue = "Not dragging"; }); </script> <template> <div: HTMLAttributes & ReservedPropsdiv HTMLAttributes.class?: anyclass="border-4 p-4 border-indigo-300 dark:bg-slate-800 antialiased"> <div: HTMLAttributes & ReservedPropsdiv HTMLAttributes.class?: anyclass="font-oldschool mb-4 text-lg md:text-xl lg:text-2xl"> <span: HTMLAttributes & ReservedPropsspan HTMLAttributes.class?: anyclass="antialiased">=== Rank your favorite flavors ===</span: HTMLAttributes & ReservedPropsspan> <div: HTMLAttributes & ReservedPropsdiv>Drag status: {{ const dragStatus: Ref<string, string>dragStatus }}</div: HTMLAttributes & ReservedPropsdiv> </div: HTMLAttributes & ReservedPropsdiv> <div: HTMLAttributes & ReservedPropsdiv ref?: VNodeRef | undefinedref="const parent: Ref<HTMLElement | undefined, HTMLElement | undefined>parent" HTMLAttributes.class?: anyclass="border-2 border-indigo-300 font-oldschool text-lg md:text-xl lg:text-2xl antialiased" > <div: HTMLAttributes & ReservedPropsdiv v-for="const flavor: stringflavor in const flavors: Ref<string[], string[]>flavors" key?: PropertyKey | undefined:key?: PropertyKey | undefinedkey="const flavor: stringflavor" HTMLAttributes.class?: anyclass="border-2 border-indigo-300 p-2" > {{ const flavor: stringflavor }} </div: HTMLAttributes & ReservedPropsdiv> </div: HTMLAttributes & ReservedPropsdiv> </div: HTMLAttributes & ReservedPropsdiv> </template>
/** @jsxImportSource solid-js */
import { function createSignal<T>(): Signal<T | undefined> (+1 overload)
Creates a simple reactive state with a getter and setter ```typescript const [state: Accessor<T>, setState: Setter<T>] = createSignal<T>( value: T, options?: { name?: string, equals?: false | ((prev: T, next: T) => boolean) } ) ```
@paramvalue initial value of the state; if empty, the state's type will automatically extended with undefined; otherwise you need to extend the type manually if you want setting to undefined not be an error@paramoptions optional object with a name for debugging purposes and equals, a comparator function for the previous and next value to allow fine-grained control over the reactivity@returns```typescript [state: Accessor<T>, setState: Setter<T>] ``` * the Accessor is merely a function that returns the current value and registers each call to the reactive root * the Setter is a function that allows directly setting or mutating the value: ```typescript const [count, setCount] = createSignal(0); setCount(count => count + 1); ```@descriptionhttps://docs.solidjs.com/reference/basic-reactivity/create-signal
createSignal
} from "solid-js";
import {
function For<T extends readonly any[], U extends JSX.Element>(props: {
    each: T | undefined | null | false;
    fallback?: JSX.Element;
    children: (item: T[number], index: Accessor<number>) => U;
}): JSX.Element
Creates a list elements from a list it receives a map function as its child that receives a list element and an accessor with the index and returns a JSX-Element; if the list is empty, an optional fallback is returned: ```typescript <For each={items} fallback={<div>No items</div>}> {(item, index) => <div data-index={index()}>{item}</div>} </For> ``` If you have a list with fixed indices and changing values, consider using `<Index>` instead.
@descriptionhttps://docs.solidjs.com/reference/components/for
For
} from "solid-js";
import { let state: BaseDragState<unknown>
The state of the drag and drop.
@type{BaseDragState<unknown>}
state
} from "@formkit/drag-and-drop";
import { function useDragAndDrop<E extends HTMLElement, T = unknown>(initValues: T[], options?: Partial<ParentConfig<T>>): [Setter<E | null>, Accessor<Store<T[]>>, ReturnType<typeof createStore>[1], (config?: Partial<ParentConfig<T>>) => void]
Hook for adding drag and drop/sortable support to a list of items.
@paraminitValues - Initial list of data.@paramoptions - The drag and drop configuration.@returns
useDragAndDrop
} from "@formkit/drag-and-drop/solid";
export function function App(): JSX.ElementApp() { const [const dragStatus: Accessor<string>dragStatus, const setDragStatus: Setter<string>setDragStatus] = createSignal<string>(value: string, options?: SignalOptions<string> | undefined): Signal<string> (+1 overload)
Creates a simple reactive state with a getter and setter ```typescript const [state: Accessor<T>, setState: Setter<T>] = createSignal<T>( value: T, options?: { name?: string, equals?: false | ((prev: T, next: T) => boolean) } ) ```
@paramvalue initial value of the state; if empty, the state's type will automatically extended with undefined; otherwise you need to extend the type manually if you want setting to undefined not be an error@paramoptions optional object with a name for debugging purposes and equals, a comparator function for the previous and next value to allow fine-grained control over the reactivity@returns```typescript [state: Accessor<T>, setState: Setter<T>] ``` * the Accessor is merely a function that returns the current value and registers each call to the reactive root * the Setter is a function that allows directly setting or mutating the value: ```typescript const [count, setCount] = createSignal(0); setCount(count => count + 1); ```@descriptionhttps://docs.solidjs.com/reference/basic-reactivity/create-signal
createSignal
("Not dragging");
const [const parent: Setter<HTMLUListElement | null>parent, const items: Accessor<string[]>items] = useDragAndDrop<HTMLUListElement, string>(initValues: string[], options?: Partial<ParentConfig<string>> | undefined): [Setter<HTMLUListElement | null>, Accessor<...>, SetStoreFunction<...>, (config?: Partial<...> | undefined) => void]
Hook for adding drag and drop/sortable support to a list of items.
@paraminitValues - Initial list of data.@paramoptions - The drag and drop configuration.@returns
useDragAndDrop
<HTMLUListElement, string>([
"🍦 vanilla", "🍫 chocolate", "🍓 strawberry", ]); const const onDragStarted: () => "Dragging"onDragStarted = () => const setDragStatus: <"Dragging">(value: "Dragging" | ((prev: string) => "Dragging")) => "Dragging" (+3 overloads)setDragStatus("Dragging"); const const onDragEnded: () => "Not dragging"onDragEnded = () => const setDragStatus: <"Not dragging">(value: "Not dragging" | ((prev: string) => "Not dragging")) => "Not dragging" (+3 overloads)setDragStatus("Not dragging"); let state: BaseDragState<unknown>
The state of the drag and drop.
@type{BaseDragState<unknown>}
state
.on: (event: string, callback: (data: unknown) => void) => voidon("dragStarted", const onDragStarted: () => "Dragging"onDragStarted);
let state: BaseDragState<unknown>
The state of the drag and drop.
@type{BaseDragState<unknown>}
state
.on: (event: string, callback: (data: unknown) => void) => voidon("dragEnded", const onDragEnded: () => "Not dragging"onDragEnded);
return ( <JSX.HTMLElementTags.div: JSX.HTMLAttributes<HTMLDivElement>div> <JSX.HTMLElementTags.strong: JSX.HTMLAttributes<HTMLElement>strong>Rank your favorite flavors</JSX.HTMLElementTags.strong: JSX.HTMLAttributes<HTMLElement>strong> <JSX.HTMLElementTags.br: JSX.HTMLAttributes<HTMLBRElement>br /> <JSX.HTMLElementTags.span: JSX.HTMLAttributes<HTMLSpanElement>span>{const dragStatus: () => stringdragStatus()}</JSX.HTMLElementTags.span: JSX.HTMLAttributes<HTMLSpanElement>span> <JSX.HTMLElementTags.br: JSX.HTMLAttributes<HTMLBRElement>br /> <JSX.HTMLElementTags.ul: JSX.HTMLAttributes<HTMLUListElement>ul ref?: HTMLUListElement | ((el: HTMLUListElement) => void) | undefinedref={const parent: Setter<HTMLUListElement | null>parent}> <
function For<T extends readonly any[], U extends JSX.Element>(props: {
    each: T | undefined | null | false;
    fallback?: JSX.Element;
    children: (item: T[number], index: Accessor<number>) => U;
}): JSX.Element
Creates a list elements from a list it receives a map function as its child that receives a list element and an accessor with the index and returns a JSX-Element; if the list is empty, an optional fallback is returned: ```typescript <For each={items} fallback={<div>No items</div>}> {(item, index) => <div data-index={index()}>{item}</div>} </For> ``` If you have a list with fixed indices and changing values, consider using `<Index>` instead.
@descriptionhttps://docs.solidjs.com/reference/components/for
For
each: false | string[] | null | undefinedeach={const items: () => string[]items()}>{(item: stringitem) => <JSX.HTMLElementTags.li: JSX.LiHTMLAttributes<HTMLLIElement>li>{item: stringitem}</JSX.HTMLElementTags.li: JSX.LiHTMLAttributes<HTMLLIElement>li>}</
function For<T extends readonly any[], U extends JSX.Element>(props: {
    each: T | undefined | null | false;
    fallback?: JSX.Element;
    children: (item: T[number], index: Accessor<number>) => U;
}): JSX.Element
Creates a list elements from a list it receives a map function as its child that receives a list element and an accessor with the index and returns a JSX-Element; if the list is empty, an optional fallback is returned: ```typescript <For each={items} fallback={<div>No items</div>}> {(item, index) => <div data-index={index()}>{item}</div>} </For> ``` If you have a list with fixed indices and changing values, consider using `<Index>` instead.
@descriptionhttps://docs.solidjs.com/reference/components/for
For
>
</JSX.HTMLElementTags.ul: JSX.HTMLAttributes<HTMLUListElement>ul> </JSX.HTMLElementTags.div: JSX.HTMLAttributes<HTMLDivElement>div> ); }
import { const reactive: <T extends DataSource>(data: T, state?: ReactiveProxyState) => ReactiveProxy<T>
reactive is an alias for r
reactive
, const html: (strings: TemplateStringsArray, ...expSlots: any[]) => ArrowTemplate
html is an alias for t
html
} from "@arrow-js/core";
import { function dragAndDrop<T>({ parent, getValues, setValues, config, }: DragAndDrop<T>): void
Initializes the drag and drop functionality for a given parent.
@paramdragAndDrop - The drag and drop configuration.@returnsvoid
dragAndDrop
,
let state: BaseDragState<unknown>
export state
The state of the drag and drop.
@type{BaseDragState<unknown>}
state
as let DNDState: BaseDragState<unknown>
The state of the drag and drop.
@type{BaseDragState<unknown>}
DNDState
} from "@formkit/drag-and-drop";
const
const state: ReactiveProxy<{
    items: string[];
    dragStatus: string;
}>
state
=
reactive<{
    items: string[];
    dragStatus: string;
}>(data: {
    items: string[];
    dragStatus: string;
}, state?: ReactiveProxyState): ReactiveProxy<{
    items: string[];
    dragStatus: string;
}>
Given a data object, often an object literal, return a proxy of that object with mutation observers for each property.
@paramdata@returnsReactiveProxy
reactive
({
items: string[]items: ["🍦 vanilla", "🍫 chocolate", "🍓 strawberry"], dragStatus: stringdragStatus: "Not dragging", }); const html: (strings: TemplateStringsArray, ...expSlots: any[]) => ArrowTemplate
html is an alias for t
html
`
<div> <strong>Rank your favorite flavors</strong> <span>${
const state: ReactiveProxy<{
    items: string[];
    dragStatus: string;
}>
state
.dragStatus: stringdragStatus}</span>
<ul id="list"> ${() =>
const state: ReactiveProxy<{
    items: string[];
    dragStatus: string;
}>
state
.items: ReactiveProxy<string[]>items.Array<string>.map<void>(callbackfn: (value: string, index: number, array: string[]) => void, thisArg?: any): void[]
Calls a defined callback function on each element of an array, and returns an array that contains the results.
@paramcallbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.@paramthisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
map
((item: stringitem) => const html: (strings: TemplateStringsArray, ...expSlots: any[]) => ArrowTemplate
html is an alias for t
html
`<li>${item: stringitem}</li>`.ArrowTemplate.key: (key: ArrowTemplateKey) => void
Adds a key to this template to identify it as a unique instance.
@paramkey - A unique key that identifies this template instance (not index).@returns
key
(item: stringitem))}
</ul> </div> `(var document: Document
[MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/document)
document
.Document.getElementById(elementId: string): HTMLElement | null
Returns a reference to the first object with the specified value of the ID attribute.
@paramelementId String that specifies the ID value.
getElementById
("app")!);
dragAndDrop<string>({ parent, getValues, setValues, config, }: DragAndDrop<string>): void
Initializes the drag and drop functionality for a given parent.
@paramdragAndDrop - The drag and drop configuration.@returnsvoid
dragAndDrop
<string>({
DragAndDrop<string>.parent: HTMLElement
The parent element that will contain the draggable nodes.
parent
: var document: Document
[MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/document)
document
.Document.getElementById(elementId: string): HTMLElement | null
Returns a reference to the first object with the specified value of the ID attribute.
@paramelementId String that specifies the ID value.
getElementById
("list")!,
DragAndDrop<string>.getValues: (parent: HTMLElement) => string[]
A function that returns the values assigned to the parent.
getValues
: () =>
const state: ReactiveProxy<{
    items: string[];
    dragStatus: string;
}>
state
.items: ReactiveProxy<string[]>items,
DragAndDrop<string>.setValues: (values: string[], parent: HTMLElement) => void
A function that sets the values assigned to the parent.
setValues
: (newValues: string[]newValues) => {
const state: ReactiveProxy<{
    items: string[];
    dragStatus: string;
}>
state
.items: ReactiveProxy<string[]>items = reactive<string[]>(data: string[], state?: ReactiveProxyState): ReactiveProxy<string[]>
Given a data object, often an object literal, return a proxy of that object with mutation observers for each property.
@paramdata@returnsReactiveProxy
reactive
(newValues: string[]newValues);
}, }); let DNDState: BaseDragState<unknown>
The state of the drag and drop.
@type{BaseDragState<unknown>}
DNDState
.on: (event: string, callback: (data: unknown) => void) => voidon("dragStarted", () => {
const state: ReactiveProxy<{
    items: string[];
    dragStatus: string;
}>
state
.dragStatus: stringdragStatus = "Dragging";
}); let DNDState: BaseDragState<unknown>
The state of the drag and drop.
@type{BaseDragState<unknown>}
DNDState
.on: (event: string, callback: (data: unknown) => void) => voidon("dragEnded", () => {
const state: ReactiveProxy<{
    items: string[];
    dragStatus: string;
}>
state
.dragStatus: stringdragStatus = "Not dragging";
});
=== Rank your favorite flavors ===
Drag status: Not dragging
🍦 vanilla
🍫 chocolate
🍓 strawberry

Parent

Parents themselves have their own set of events that can be listened to. These events include: `onDragstart`, `onDragend`, `onSort`, `onTransfer`. To listen to parent events, assign a callback function to the event in the parent's configuration object.

  • React
  • Vue
  • Solid
  • Native
import React from "react";
import { function useState<S>(initialState: S | (() => S)): [S, React.Dispatch<React.SetStateAction<S>>] (+1 overload)
Returns a stateful value, and a function to update it.
@version16.8.0@see{@link https://react.dev/reference/react/useState}
useState
} from "react";
import { function useDragAndDrop<E extends HTMLElement, T = unknown>(list: T[], options?: Partial<ParentConfig<T>>): [React.RefObject<E>, T[], React.Dispatch<React.SetStateAction<T[]>>, (config: Partial<ParentConfig<...>>) => void]
Hook for adding drag and drop/sortable support to a list of items.
@paramlist - Initial list of data.@paramoptions - The drag and drop configuration.@returns
useDragAndDrop
} from "@formkit/drag-and-drop/react";
export function function App(): React.JSX.ElementApp() { const [const dragStatus: stringdragStatus, const setDragStatus: React.Dispatch<React.SetStateAction<string>>setDragStatus] = useState<string>(initialState: string | (() => string)): [string, React.Dispatch<React.SetStateAction<string>>] (+1 overload)
Returns a stateful value, and a function to update it.
@version16.8.0@see{@link https://react.dev/reference/react/useState}
useState
("Not dragging");
const [const valuesChanged: stringvaluesChanged, const setValuesChanged: React.Dispatch<React.SetStateAction<string>>setValuesChanged] = useState<string>(initialState: string | (() => string)): [string, React.Dispatch<React.SetStateAction<string>>] (+1 overload)
Returns a stateful value, and a function to update it.
@version16.8.0@see{@link https://react.dev/reference/react/useState}
useState
("Not sorting");
const [const parent: React.RefObject<HTMLUListElement>parent, const items: string[]items] = useDragAndDrop<HTMLUListElement, string>(list: string[], options?: Partial<ParentConfig<string>> | undefined): [React.RefObject<HTMLUListElement>, string[], React.Dispatch<...>, (config: Partial<...>) => void]
Hook for adding drag and drop/sortable support to a list of items.
@paramlist - Initial list of data.@paramoptions - The drag and drop configuration.@returns
useDragAndDrop
<HTMLUListElement, string>(
["🍦 vanilla", "🍫 chocolate", "🍓 strawberry"], { onDragstart?: DragstartEvent | undefined
Fired when a drag is started, whether native drag or synthetic
onDragstart
: () => {
const setDragStatus: (value: React.SetStateAction<string>) => voidsetDragStatus("Dragging"); }, onDragend?: DragendEvent | undefined
Fired when a drag is ended, whether native drag or synthetic
onDragend
: () => {
const setDragStatus: (value: React.SetStateAction<string>) => voidsetDragStatus("Not dragging"); const setValuesChanged: (value: React.SetStateAction<string>) => voidsetValuesChanged("Not sorting"); }, onSort?: SortEvent | undefined
Callback function for when a sort operation is performed.
onSort
: (event: SortEventData<T>event) => {
const setValuesChanged: (value: React.SetStateAction<string>) => voidsetValuesChanged(`${event: SortEventData<T>event.SortEventData<T>.previousValues: T[]previousValues} -> ${event: SortEventData<T>event.SortEventData<T>.values: T[]values}`); }, } ); return ( <JSX.IntrinsicElements.div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>div> <JSX.IntrinsicElements.strong: React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement>, HTMLElement>strong>Rank your favorite flavors</JSX.IntrinsicElements.strong: React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement>, HTMLElement>strong> <JSX.IntrinsicElements.br: React.DetailedHTMLProps<React.HTMLAttributes<HTMLBRElement>, HTMLBRElement>br /> <JSX.IntrinsicElements.span: React.DetailedHTMLProps<React.HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>span>{const dragStatus: stringdragStatus}</JSX.IntrinsicElements.span: React.DetailedHTMLProps<React.HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>span> <JSX.IntrinsicElements.span: React.DetailedHTMLProps<React.HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>span>{const valuesChanged: stringvaluesChanged}</JSX.IntrinsicElements.span: React.DetailedHTMLProps<React.HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>span> <JSX.IntrinsicElements.br: React.DetailedHTMLProps<React.HTMLAttributes<HTMLBRElement>, HTMLBRElement>br /> <JSX.IntrinsicElements.ul: React.DetailedHTMLProps<React.HTMLAttributes<HTMLUListElement>, HTMLUListElement>ul React.RefAttributes<HTMLUListElement>.ref?: React.LegacyRef<HTMLUListElement> | undefined
Allows getting a ref to the component instance. Once the component unmounts, React will set `ref.current` to `null` (or call the ref with `null` if you passed a callback ref).
@see{@link https://react.dev/learn/referencing-values-with-refs#refs-and-the-dom React Docs}
ref
={const parent: React.RefObject<HTMLUListElement>parent}>
{const items: string[]items.Array<string>.map<React.JSX.Element>(callbackfn: (value: string, index: number, array: string[]) => React.JSX.Element, thisArg?: any): React.JSX.Element[]
Calls a defined callback function on each element of an array, and returns an array that contains the results.
@paramcallbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.@paramthisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
map
((item: stringitem) => {
return <JSX.IntrinsicElements.li: React.DetailedHTMLProps<React.LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>li React.Attributes.key?: React.Key | null | undefinedkey={item: stringitem}>{item: stringitem}</JSX.IntrinsicElements.li: React.DetailedHTMLProps<React.LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>li>; })} </JSX.IntrinsicElements.ul: React.DetailedHTMLProps<React.HTMLAttributes<HTMLUListElement>, HTMLUListElement>ul> </JSX.IntrinsicElements.div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>div> ); }
<script setup lang="ts">
import { function ref<T>(value: T): [T] extends [Ref] ? IfAny<T, Ref<T>, T> : Ref<UnwrapRef<T>, UnwrapRef<T> | T> (+1 overload)
Takes an inner value and returns a reactive and mutable ref object, which has a single property `.value` that points to the inner value.
@paramvalue - The object to wrap in the ref.@see{@link https://vuejs.org/api/reactivity-core.html#ref}
ref
} from "vue";
import { function useDragAndDrop<T>(initialValues: T[], options?: Partial<VueParentConfig<T>>): [Ref<HTMLElement | undefined>, Ref<T[]>, (config: Partial<VueParentConfig<T>>) => void]
Creates a new instance of drag and drop and returns the parent element and a ref of the values to use in your template.
@paraminitialValues - The initial values of the parent element.@returnsThe parent element and values for drag and drop.
useDragAndDrop
} from "@formkit/drag-and-drop/vue";
const const dragStatus: Ref<string, string>dragStatus = ref<string>(value: string): Ref<string, string> (+1 overload)
Takes an inner value and returns a reactive and mutable ref object, which has a single property `.value` that points to the inner value.
@paramvalue - The object to wrap in the ref.@see{@link https://vuejs.org/api/reactivity-core.html#ref}
ref
("Not dragging");
const const valuesChanged: Ref<string, string>valuesChanged = ref<string>(value: string): Ref<string, string> (+1 overload)
Takes an inner value and returns a reactive and mutable ref object, which has a single property `.value` that points to the inner value.
@paramvalue - The object to wrap in the ref.@see{@link https://vuejs.org/api/reactivity-core.html#ref}
ref
("Not sorting");
const [const parent: Ref<HTMLElement | undefined, HTMLElement | undefined>parent, const flavors: Ref<string[], string[]>flavors] = useDragAndDrop<string>(initialValues: string[], options?: Partial<Partial<ParentConfig<string>>> | undefined): [Ref<HTMLElement | undefined, HTMLElement | undefined>, Ref<...>, (config: Partial<...>) => void]
Creates a new instance of drag and drop and returns the parent element and a ref of the values to use in your template.
@paraminitialValues - The initial values of the parent element.@returnsThe parent element and values for drag and drop.
useDragAndDrop
(
["🍦 vanilla", "🍫 chocolate", "🍓 strawberry"], { onDragstart?: DragstartEvent | undefined
Fired when a drag is started, whether native drag or synthetic
onDragstart
: () => {
const dragStatus: Ref<string, string>dragStatus.Ref<string, string>.value: stringvalue = "Dragging"; }, onDragend?: DragendEvent | undefined
Fired when a drag is ended, whether native drag or synthetic
onDragend
: () => {
const dragStatus: Ref<string, string>dragStatus.Ref<string, string>.value: stringvalue = "Not dragging"; const valuesChanged: Ref<string, string>valuesChanged.Ref<string, string>.value: stringvalue = "Not sorting"; }, onSort?: SortEvent | undefined
Callback function for when a sort operation is performed.
onSort
: (event: SortEventData<T>event) => {
const valuesChanged: Ref<string, string>valuesChanged.Ref<string, string>.value: stringvalue = `${event: SortEventData<T>event.SortEventData<T>.previousValues: T[]previousValues} -> ${event: SortEventData<T>event.SortEventData<T>.values: T[]values}`; }, } ); </script> <template> <div: HTMLAttributes & ReservedPropsdiv HTMLAttributes.class?: anyclass="border-4 p-4 border-indigo-300 dark:bg-slate-800 antialiased"> <div: HTMLAttributes & ReservedPropsdiv HTMLAttributes.class?: anyclass="font-oldschool mb-4 text-lg md:text-xl lg:text-2xl"> <span: HTMLAttributes & ReservedPropsspan HTMLAttributes.class?: anyclass="antialiased">=== Rank your favorite flavors ===</span: HTMLAttributes & ReservedPropsspan> <div: HTMLAttributes & ReservedPropsdiv>Drag status: {{ const dragStatus: Ref<string, string>dragStatus }}</div: HTMLAttributes & ReservedPropsdiv> <div: HTMLAttributes & ReservedPropsdiv>Values changed: {{ const valuesChanged: Ref<string, string>valuesChanged }}</div: HTMLAttributes & ReservedPropsdiv> </div: HTMLAttributes & ReservedPropsdiv> <div: HTMLAttributes & ReservedPropsdiv ref?: VNodeRef | undefinedref="const parent: Ref<HTMLElement | undefined, HTMLElement | undefined>parent" HTMLAttributes.class?: anyclass="border-2 border-indigo-300 font-oldschool text-lg md:text-xl lg:text-2xl antialiased" > <div: HTMLAttributes & ReservedPropsdiv v-for="const flavor: stringflavor in const flavors: Ref<string[], string[]>flavors" key?: PropertyKey | undefined:key?: PropertyKey | undefinedkey="const flavor: stringflavor" HTMLAttributes.class?: anyclass="border-2 border-indigo-300 p-2" > {{ const flavor: stringflavor }} </div: HTMLAttributes & ReservedPropsdiv> </div: HTMLAttributes & ReservedPropsdiv> </div: HTMLAttributes & ReservedPropsdiv> </template>
/** @jsxImportSource solid-js */
// Start of Selection
import { function createSignal<T>(): Signal<T | undefined> (+1 overload)
Creates a simple reactive state with a getter and setter ```typescript const [state: Accessor<T>, setState: Setter<T>] = createSignal<T>( value: T, options?: { name?: string, equals?: false | ((prev: T, next: T) => boolean) } ) ```
@paramvalue initial value of the state; if empty, the state's type will automatically extended with undefined; otherwise you need to extend the type manually if you want setting to undefined not be an error@paramoptions optional object with a name for debugging purposes and equals, a comparator function for the previous and next value to allow fine-grained control over the reactivity@returns```typescript [state: Accessor<T>, setState: Setter<T>] ``` * the Accessor is merely a function that returns the current value and registers each call to the reactive root * the Setter is a function that allows directly setting or mutating the value: ```typescript const [count, setCount] = createSignal(0); setCount(count => count + 1); ```@descriptionhttps://docs.solidjs.com/reference/basic-reactivity/create-signal
createSignal
} from "solid-js";
import {
function For<T extends readonly any[], U extends JSX.Element>(props: {
    each: T | undefined | null | false;
    fallback?: JSX.Element;
    children: (item: T[number], index: Accessor<number>) => U;
}): JSX.Element
Creates a list elements from a list it receives a map function as its child that receives a list element and an accessor with the index and returns a JSX-Element; if the list is empty, an optional fallback is returned: ```typescript <For each={items} fallback={<div>No items</div>}> {(item, index) => <div data-index={index()}>{item}</div>} </For> ``` If you have a list with fixed indices and changing values, consider using `<Index>` instead.
@descriptionhttps://docs.solidjs.com/reference/components/for
For
} from "solid-js";
import { function useDragAndDrop<E extends HTMLElement, T = unknown>(initValues: T[], options?: Partial<ParentConfig<T>>): [Setter<E | null>, Accessor<Store<T[]>>, ReturnType<typeof createStore>[1], (config?: Partial<ParentConfig<T>>) => void]
Hook for adding drag and drop/sortable support to a list of items.
@paraminitValues - Initial list of data.@paramoptions - The drag and drop configuration.@returns
useDragAndDrop
} from "@formkit/drag-and-drop/solid";
export function function App(): JSX.ElementApp() { const [const dragStatus: Accessor<string>dragStatus, const setDragStatus: Setter<string>setDragStatus] = createSignal<string>(value: string, options?: SignalOptions<string> | undefined): Signal<string> (+1 overload)
Creates a simple reactive state with a getter and setter ```typescript const [state: Accessor<T>, setState: Setter<T>] = createSignal<T>( value: T, options?: { name?: string, equals?: false | ((prev: T, next: T) => boolean) } ) ```
@paramvalue initial value of the state; if empty, the state's type will automatically extended with undefined; otherwise you need to extend the type manually if you want setting to undefined not be an error@paramoptions optional object with a name for debugging purposes and equals, a comparator function for the previous and next value to allow fine-grained control over the reactivity@returns```typescript [state: Accessor<T>, setState: Setter<T>] ``` * the Accessor is merely a function that returns the current value and registers each call to the reactive root * the Setter is a function that allows directly setting or mutating the value: ```typescript const [count, setCount] = createSignal(0); setCount(count => count + 1); ```@descriptionhttps://docs.solidjs.com/reference/basic-reactivity/create-signal
createSignal
("Not dragging");
const [const valuesChanged: Accessor<string>valuesChanged, const setValuesChanged: Setter<string>setValuesChanged] = createSignal<string>(value: string, options?: SignalOptions<string> | undefined): Signal<string> (+1 overload)
Creates a simple reactive state with a getter and setter ```typescript const [state: Accessor<T>, setState: Setter<T>] = createSignal<T>( value: T, options?: { name?: string, equals?: false | ((prev: T, next: T) => boolean) } ) ```
@paramvalue initial value of the state; if empty, the state's type will automatically extended with undefined; otherwise you need to extend the type manually if you want setting to undefined not be an error@paramoptions optional object with a name for debugging purposes and equals, a comparator function for the previous and next value to allow fine-grained control over the reactivity@returns```typescript [state: Accessor<T>, setState: Setter<T>] ``` * the Accessor is merely a function that returns the current value and registers each call to the reactive root * the Setter is a function that allows directly setting or mutating the value: ```typescript const [count, setCount] = createSignal(0); setCount(count => count + 1); ```@descriptionhttps://docs.solidjs.com/reference/basic-reactivity/create-signal
createSignal
("Not sorting");
const [const parent: Setter<HTMLUListElement | null>parent, const items: Accessor<string[]>items] = useDragAndDrop<HTMLUListElement, string>(initValues: string[], options?: Partial<ParentConfig<string>> | undefined): [Setter<HTMLUListElement | null>, Accessor<...>, SetStoreFunction<...>, (config?: Partial<...> | undefined) => void]
Hook for adding drag and drop/sortable support to a list of items.
@paraminitValues - Initial list of data.@paramoptions - The drag and drop configuration.@returns
useDragAndDrop
<HTMLUListElement, string>(
["🍦 vanilla", "🍫 chocolate", "🍓 strawberry"], { onDragstart?: DragstartEvent | undefined
Fired when a drag is started, whether native drag or synthetic
onDragstart
: () => {
const setDragStatus: <"Dragging">(value: "Dragging" | ((prev: string) => "Dragging")) => "Dragging" (+3 overloads)setDragStatus("Dragging"); }, onDragend?: DragendEvent | undefined
Fired when a drag is ended, whether native drag or synthetic
onDragend
: () => {
const setDragStatus: <"Not dragging">(value: "Not dragging" | ((prev: string) => "Not dragging")) => "Not dragging" (+3 overloads)setDragStatus("Not dragging"); const setValuesChanged: <"Not sorting">(value: "Not sorting" | ((prev: string) => "Not sorting")) => "Not sorting" (+3 overloads)setValuesChanged("Not sorting"); }, onSort?: SortEvent | undefined
Callback function for when a sort operation is performed.
onSort
: (event: SortEventData<T>event) => {
const setValuesChanged: <`${string} -> ${string}`>(value: `${string} -> ${string}` | ((prev: string) => `${string} -> ${string}`)) => `${string} -> ${string}` (+3 overloads)setValuesChanged(`${event: SortEventData<T>event.SortEventData<T>.previousValues: T[]previousValues} -> ${event: SortEventData<T>event.SortEventData<T>.values: T[]values}`); }, } ); return ( <JSX.HTMLElementTags.div: JSX.HTMLAttributes<HTMLDivElement>div> <JSX.HTMLElementTags.strong: JSX.HTMLAttributes<HTMLElement>strong>Rank your favorite flavors</JSX.HTMLElementTags.strong: JSX.HTMLAttributes<HTMLElement>strong> <JSX.HTMLElementTags.br: JSX.HTMLAttributes<HTMLBRElement>br /> <JSX.HTMLElementTags.span: JSX.HTMLAttributes<HTMLSpanElement>span>{const dragStatus: () => stringdragStatus()}</JSX.HTMLElementTags.span: JSX.HTMLAttributes<HTMLSpanElement>span> <JSX.HTMLElementTags.span: JSX.HTMLAttributes<HTMLSpanElement>span>{const valuesChanged: () => stringvaluesChanged()}</JSX.HTMLElementTags.span: JSX.HTMLAttributes<HTMLSpanElement>span> <JSX.HTMLElementTags.br: JSX.HTMLAttributes<HTMLBRElement>br /> <JSX.HTMLElementTags.ul: JSX.HTMLAttributes<HTMLUListElement>ul ref?: HTMLUListElement | ((el: HTMLUListElement) => void) | undefinedref={const parent: Setter<HTMLUListElement | null>parent}> <
function For<T extends readonly any[], U extends JSX.Element>(props: {
    each: T | undefined | null | false;
    fallback?: JSX.Element;
    children: (item: T[number], index: Accessor<number>) => U;
}): JSX.Element
Creates a list elements from a list it receives a map function as its child that receives a list element and an accessor with the index and returns a JSX-Element; if the list is empty, an optional fallback is returned: ```typescript <For each={items} fallback={<div>No items</div>}> {(item, index) => <div data-index={index()}>{item}</div>} </For> ``` If you have a list with fixed indices and changing values, consider using `<Index>` instead.
@descriptionhttps://docs.solidjs.com/reference/components/for
For
each: false | string[] | null | undefinedeach={const items: () => string[]items()}>{(item: stringitem) => <JSX.HTMLElementTags.li: JSX.LiHTMLAttributes<HTMLLIElement>li>{item: stringitem}</JSX.HTMLElementTags.li: JSX.LiHTMLAttributes<HTMLLIElement>li>}</
function For<T extends readonly any[], U extends JSX.Element>(props: {
    each: T | undefined | null | false;
    fallback?: JSX.Element;
    children: (item: T[number], index: Accessor<number>) => U;
}): JSX.Element
Creates a list elements from a list it receives a map function as its child that receives a list element and an accessor with the index and returns a JSX-Element; if the list is empty, an optional fallback is returned: ```typescript <For each={items} fallback={<div>No items</div>}> {(item, index) => <div data-index={index()}>{item}</div>} </For> ``` If you have a list with fixed indices and changing values, consider using `<Index>` instead.
@descriptionhttps://docs.solidjs.com/reference/components/for
For
>
</JSX.HTMLElementTags.ul: JSX.HTMLAttributes<HTMLUListElement>ul> </JSX.HTMLElementTags.div: JSX.HTMLAttributes<HTMLDivElement>div> ); }
import { const reactive: <T extends DataSource>(data: T, state?: ReactiveProxyState) => ReactiveProxy<T>
reactive is an alias for r
reactive
, const html: (strings: TemplateStringsArray, ...expSlots: any[]) => ArrowTemplate
html is an alias for t
html
} from "@arrow-js/core";
import { function dragAndDrop<T>({ parent, getValues, setValues, config, }: DragAndDrop<T>): void
Initializes the drag and drop functionality for a given parent.
@paramdragAndDrop - The drag and drop configuration.@returnsvoid
dragAndDrop
} from "@formkit/drag-and-drop";
const
const state: ReactiveProxy<{
    items: string[];
    dragStatus: string;
    valuesChanged: string;
}>
state
=
reactive<{
    items: string[];
    dragStatus: string;
    valuesChanged: string;
}>(data: {
    items: string[];
    dragStatus: string;
    valuesChanged: string;
}, state?: ReactiveProxyState): ReactiveProxy<...>
Given a data object, often an object literal, return a proxy of that object with mutation observers for each property.
@paramdata@returnsReactiveProxy
reactive
({
items: string[]items: ["🍦 vanilla", "🍫 chocolate", "🍓 strawberry"], dragStatus: stringdragStatus: "Not dragging", valuesChanged: stringvaluesChanged: "Not sorting", }); const html: (strings: TemplateStringsArray, ...expSlots: any[]) => ArrowTemplate
html is an alias for t
html
`
<div> <strong>Rank your favorite flavors</strong> <span>${
const state: ReactiveProxy<{
    items: string[];
    dragStatus: string;
    valuesChanged: string;
}>
state
.dragStatus: stringdragStatus}</span>
<ul id="list"> ${() =>
const state: ReactiveProxy<{
    items: string[];
    dragStatus: string;
    valuesChanged: string;
}>
state
.items: ReactiveProxy<string[]>items.Array<string>.map<void>(callbackfn: (value: string, index: number, array: string[]) => void, thisArg?: any): void[]
Calls a defined callback function on each element of an array, and returns an array that contains the results.
@paramcallbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.@paramthisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
map
((item: stringitem) => const html: (strings: TemplateStringsArray, ...expSlots: any[]) => ArrowTemplate
html is an alias for t
html
`<li>${item: stringitem}</li>`.ArrowTemplate.key: (key: ArrowTemplateKey) => void
Adds a key to this template to identify it as a unique instance.
@paramkey - A unique key that identifies this template instance (not index).@returns
key
(item: stringitem))}
</ul> </div> `(var document: Document
[MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/document)
document
.Document.getElementById(elementId: string): HTMLElement | null
Returns a reference to the first object with the specified value of the ID attribute.
@paramelementId String that specifies the ID value.
getElementById
("app")!);
dragAndDrop<string>({ parent, getValues, setValues, config, }: DragAndDrop<string>): void
Initializes the drag and drop functionality for a given parent.
@paramdragAndDrop - The drag and drop configuration.@returnsvoid
dragAndDrop
<string>({
DragAndDrop<string>.parent: HTMLElement
The parent element that will contain the draggable nodes.
parent
: var document: Document
[MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/document)
document
.Document.getElementById(elementId: string): HTMLElement | null
Returns a reference to the first object with the specified value of the ID attribute.
@paramelementId String that specifies the ID value.
getElementById
("list")!,
DragAndDrop<string>.getValues: (parent: HTMLElement) => string[]
A function that returns the values assigned to the parent.
getValues
: () =>
const state: ReactiveProxy<{
    items: string[];
    dragStatus: string;
    valuesChanged: string;
}>
state
.items: ReactiveProxy<string[]>items,
DragAndDrop<string>.setValues: (values: string[], parent: HTMLElement) => void
A function that sets the values assigned to the parent.
setValues
: (newValues: string[]newValues) => {
const state: ReactiveProxy<{
    items: string[];
    dragStatus: string;
    valuesChanged: string;
}>
state
.items: ReactiveProxy<string[]>items = reactive<string[]>(data: string[], state?: ReactiveProxyState): ReactiveProxy<string[]>
Given a data object, often an object literal, return a proxy of that object with mutation observers for each property.
@paramdata@returnsReactiveProxy
reactive
(newValues: string[]newValues);
}, DragAndDrop<string>.config?: Partial<ParentConfig<string>> | undefined
An optional configuration object.
config
: {
onDragstart?: DragstartEvent | undefined
Fired when a drag is started, whether native drag or synthetic
onDragstart
: () => {
const state: ReactiveProxy<{
    items: string[];
    dragStatus: string;
    valuesChanged: string;
}>
state
.dragStatus: stringdragStatus = "Dragging";
}, onDragend?: DragendEvent | undefined
Fired when a drag is ended, whether native drag or synthetic
onDragend
: () => {
const state: ReactiveProxy<{
    items: string[];
    dragStatus: string;
    valuesChanged: string;
}>
state
.dragStatus: stringdragStatus = "Not dragging";
const state: ReactiveProxy<{
    items: string[];
    dragStatus: string;
    valuesChanged: string;
}>
state
.valuesChanged: stringvaluesChanged = "Not sorting";
}, onSort?: SortEvent | undefined
Callback function for when a sort operation is performed.
onSort
: (event: SortEventData<T>event) => {
const state: ReactiveProxy<{
    items: string[];
    dragStatus: string;
    valuesChanged: string;
}>
state
.valuesChanged: stringvaluesChanged = `${event: SortEventData<T>event.SortEventData<T>.previousValues: T[]previousValues} -> ${event: SortEventData<T>event.SortEventData<T>.values: T[]values}`;
}, }, });
=== Rank your favorite flavors ===
Drag status: Not dragging
Values changed: Not sorting
🍦 vanilla
🍫 chocolate
🍓 strawberry

Configuration

Each parent can be passed a configuration object. This object can be used to set options like group, drag handles, and or more dynamic options such as determining which direct descendants of a list are draggable. Invocation of useDragAndDrop or dragAndDrop can be used idempotently to update the configuration for a given list.

import type {
  interface ParentRecord<T>
The parent record, contains the el and the data in the `parents` weakmap.
ParentRecord
,
type DragState<T> = DragStateProps<T> & BaseDragState<T>DragState, interface NodeDragEventData<T>
The data passed to the node event listener when the event is a drag event.
NodeDragEventData
,
interface NodePointerEventData<T>
The data passed to the node event listener when the event is a pointer event (not a native drag event).
NodePointerEventData
,
interface NodeEventData<T>
The data passed to the node event listener.
NodeEventData
,
type DNDPlugin = (parent: HTMLElement) => DNDPluginData | undefinedDNDPlugin, interface PointeroverNodeEvent<T>
The payload of the custom event dispatched when a node is "touched" over a node.
PointeroverNodeEvent
,
type SetupNode = <T>(data: SetupNodeData<T>) => voidSetupNode, interface ParentEventData<T>
The data passed to the parent event listener.
@parame - The event that was triggered.@paramtargetData - The data of the target parent.
ParentEventData
,
type TearDownNode = <T>(data: TearDownNodeData<T>) => voidTearDownNode, interface PointeroverParentEvent<T>
The payload of the custom event dispatched when a node is "touched" over a parent.
PointeroverParentEvent
,
type SortEvent = <T>(data: SortEventData<T>) => voidSortEvent, type TransferEvent = <T>(data: TransferEventData<T>) => voidTransferEvent, type DragstartEvent = <T>(data: DragstartEventData<T>) => voidDragstartEvent, type DragendEvent = <T>(data: DragendEventData<T>) => voidDragendEvent, interface ParentDragEventData<T>ParentDragEventData,
type BaseDragState<T> = {
    activeState?: {
        node: NodeRecord<T>;
        parent: ParentRecord<T>;
    };
    affectedNodes: Array<NodeRecord<T>>;
    currentTargetValue: T | undefined;
    emit: (event: string, data: unknown) => void;
    ... 23 more ...;
    frameIdY?: number;
}
BaseDragState
,
type NativeDragEffects = "link" | "none" | "copy" | "move"NativeDragEffects, interface NodeRecord<T>
The node record, contains the el and the data in the `nodes` weakmap.
NodeRecord
,
interface DropSwapConfig<T>DropSwapConfig, interface InsertConfig<T>InsertConfig, interface ParentData<T>
The data assigned to a given parent in the `parents` weakmap.
ParentData
,
interface ParentKeydownEventData<T>ParentKeydownEventData, type SynthDragState<T> = SynthDragStateProps & DragStateProps<T> & BaseDragState<T>
The state of the current drag. State is only created when a drag start event is triggered.
@paramactiveNode - The node that was most recently clicked (used optionally).@paramaffectedNodes - The nodes that will be updated by a drag action (sorted).@paramascendingDirection - Indicates whetehr the dragged node is moving to a node with a higher index or not.@paramclonedDraggedEls - The cloned elements of the dragged node. This is used primarily for TouchEvents or multi-drag purposes.@paramdraggedNode - The node that is being dragged.@paramdraggedNodes - The nodes that are being dragged.@paramincomingDirection - The direction that the dragged node is moving into a dragover node.@paraminitialParent - The parent that the dragged node was initially in.@paramcurrentParent - The parent that the dragged node was most recently in.@paramlastValue - The last value of the dragged node.@paramoriginalZIndex - The original z-index of the dragged node.@parampreventEnter - A flag to prevent a sort operation from firing until the mutation observer has had a chance to update the data of the remapped nodes.@paramswappedNodeValue - The value of the node that was swapped with the dragged node.@paramtargetIndex - The index of the node that the dragged node is moving into.
SynthDragState
,
} from "@formkit/drag-and-drop"; /** * The configuration object for a given parent. */ export interface interface ParentConfig<T>
The configuration object for a given parent.
ParentConfig
<function (type parameter) T in ParentConfig<T>T> {
/** * A function that returns whether a given parent accepts a given node. */ ParentConfig<T>.accepts?: ((targetParentData: ParentRecord<T>, initialParentData: ParentRecord<T>, currentParentData: ParentRecord<T>, state: BaseDragState<T>) => boolean) | undefined
A function that returns whether a given parent accepts a given node.
accepts
?: (
targetParentData: ParentRecord<T>targetParentData: interface ParentRecord<T>
The parent record, contains the el and the data in the `parents` weakmap.
ParentRecord
<function (type parameter) T in ParentConfig<T>T>,
initialParentData: ParentRecord<T>initialParentData: interface ParentRecord<T>
The parent record, contains the el and the data in the `parents` weakmap.
ParentRecord
<function (type parameter) T in ParentConfig<T>T>,
currentParentData: ParentRecord<T>currentParentData: interface ParentRecord<T>
The parent record, contains the el and the data in the `parents` weakmap.
ParentRecord
<function (type parameter) T in ParentConfig<T>T>,
state: BaseDragState<T>state:
type BaseDragState<T> = {
    activeState?: {
        node: NodeRecord<T>;
        parent: ParentRecord<T>;
    };
    affectedNodes: Array<NodeRecord<T>>;
    currentTargetValue: T | undefined;
    emit: (event: string, data: unknown) => void;
    ... 23 more ...;
    frameIdY?: number;
}
BaseDragState
<function (type parameter) T in ParentConfig<T>T>
) => boolean; /** * The data transfer effect to use for the drag operation. */ ParentConfig<T>.dragEffectAllowed: NativeDragEffects
The data transfer effect to use for the drag operation.
dragEffectAllowed
: type NativeDragEffects = "link" | "none" | "copy" | "move"NativeDragEffects;
/** * The data transfer effect to use for the drag operation. */ ParentConfig<T>.dragDropEffect: NativeDragEffects
The data transfer effect to use for the drag operation.
dragDropEffect
: type NativeDragEffects = "link" | "none" | "copy" | "move"NativeDragEffects;
/** * A function that returns the image to use for the drag operation. This is * invoked for native operations. The clonedNode is what will be set as the drag * image, but this can be updated. */ ParentConfig<T>.dragImage?: ((data: NodeDragEventData<T>, draggedNodes: Array<NodeRecord<T>>) => HTMLElement) | undefined
A function that returns the image to use for the drag operation. This is invoked for native operations. The clonedNode is what will be set as the drag image, but this can be updated.
dragImage
?: (
data: NodeDragEventData<T>data: interface NodeDragEventData<T>
The data passed to the node event listener when the event is a drag event.
NodeDragEventData
<function (type parameter) T in ParentConfig<T>T>,
draggedNodes: NodeRecord<T>[]draggedNodes: interface Array<T>Array<interface NodeRecord<T>
The node record, contains the el and the data in the `nodes` weakmap.
NodeRecord
<function (type parameter) T in ParentConfig<T>T>>
) => HTMLElement; /** * A flag to disable dragability of all nodes in the parent. */ ParentConfig<T>.disabled?: boolean | undefined
A flag to disable dragability of all nodes in the parent.
disabled
?: boolean;
/** * A selector for the drag handle. Will search at any depth within the * draggable element. */ ParentConfig<T>.dragHandle?: string | undefined
A selector for the drag handle. Will search at any depth within the draggable element.
dragHandle
?: string;
/** * External drag handle */
ParentConfig<T>.externalDragHandle?: {
    el: HTMLElement;
    callback: () => HTMLElement;
} | undefined
External drag handle
externalDragHandle
?: {
el: HTMLElementel: HTMLElement; callback: () => HTMLElementcallback: () => HTMLElement; }; /** * A function that returns whether a given node is draggable. */ ParentConfig<T>.draggable?: ((child: HTMLElement) => boolean) | undefined
A function that returns whether a given node is draggable.
draggable
?: (child: HTMLElementchild: HTMLElement) => boolean;
/** * A function that returns whether a given value is draggable */ ParentConfig<T>.draggableValue?: ((values: T) => boolean) | undefined
A function that returns whether a given value is draggable
draggableValue
?: (values: Tvalues: function (type parameter) T in ParentConfig<T>T) => boolean;
ParentConfig<T>.draggedNodes: (pointerDown: {
    parent: ParentRecord<T>;
    node: NodeRecord<T>;
}) => Array<NodeRecord<T>>
draggedNodes
: (
pointerDown: {
    parent: ParentRecord<T>;
    node: NodeRecord<T>;
}
pointerDown
: {
parent: ParentRecord<T>parent: interface ParentRecord<T>
The parent record, contains the el and the data in the `parents` weakmap.
ParentRecord
<function (type parameter) T in ParentConfig<T>T>;
node: NodeRecord<T>node: interface NodeRecord<T>
The node record, contains the el and the data in the `nodes` weakmap.
NodeRecord
<function (type parameter) T in ParentConfig<T>T>;
}) => interface Array<T>Array<interface NodeRecord<T>
The node record, contains the el and the data in the `nodes` weakmap.
NodeRecord
<function (type parameter) T in ParentConfig<T>T>>;
/** * The class to add to a node when it is being dragged. */ ParentConfig<T>.draggingClass?: string | undefined
The class to add to a node when it is being dragged.
draggingClass
?: string;
/** * Accepts array of "dragged nodes" and applies dragstart classes to them. */ ParentConfig<T>.dragstartClasses: (node: NodeRecord<T>, nodes: Array<NodeRecord<T>>, config: ParentConfig<T>, isSynthDrag?: boolean) => void
Accepts array of "dragged nodes" and applies dragstart classes to them.
dragstartClasses
: (
node: NodeRecord<T>node: interface NodeRecord<T>
The node record, contains the el and the data in the `nodes` weakmap.
NodeRecord
<function (type parameter) T in ParentConfig<T>T>,
nodes: NodeRecord<T>[]nodes: interface Array<T>Array<interface NodeRecord<T>
The node record, contains the el and the data in the `nodes` weakmap.
NodeRecord
<function (type parameter) T in ParentConfig<T>T>>,
config: ParentConfig<T>config: interface ParentConfig<T>
The configuration object for a given parent.
ParentConfig
<function (type parameter) T in ParentConfig<T>T>,
isSynthDrag: boolean | undefinedisSynthDrag?: boolean ) => void; // When drag starts, this will be applied to the dragged node(s) (not their // representations being dragged) on dragstart. This will remain on the nodes // until the drag ends. ParentConfig<T>.dragPlaceholderClass?: string | undefineddragPlaceholderClass?: string; /** * The configuration object for the drop and swap plugin. */ ParentConfig<T>.dropSwapConfig?: DropSwapConfig<T> | undefined
The configuration object for the drop and swap plugin.
dropSwapConfig
?: interface DropSwapConfig<T>DropSwapConfig<function (type parameter) T in ParentConfig<T>T>;
/** * The class to add to a node when the node is dragged over it. */ ParentConfig<T>.dropZoneClass?: string | undefined
The class to add to a node when the node is dragged over it.
dropZoneClass
?: string;
/** * The class to add to a parent when it is dragged over. */ ParentConfig<T>.dropZoneParentClass?: string | undefined
The class to add to a parent when it is dragged over.
dropZoneParentClass
?: string;
/** * A flag to indicate whether the parent itself is a dropZone. */ ParentConfig<T>.dropZone?: boolean | undefined
A flag to indicate whether the parent itself is a dropZone.
dropZone
?: boolean;
/** * The group that the parent belongs to. This is used for allowing multiple * parents to transfer nodes between each other. */ ParentConfig<T>.group?: string | undefined
The group that the parent belongs to. This is used for allowing multiple parents to transfer nodes between each other.
group
?: string;
ParentConfig<T>.handleParentFocus: (data: ParentEventData<T>, state: BaseDragState<T>) => voidhandleParentFocus: ( data: ParentEventData<T>data: interface ParentEventData<T>
The data passed to the parent event listener.
@parame - The event that was triggered.@paramtargetData - The data of the target parent.
ParentEventData
<function (type parameter) T in ParentConfig<T>T>,
state: BaseDragState<T>state:
type BaseDragState<T> = {
    activeState?: {
        node: NodeRecord<T>;
        parent: ParentRecord<T>;
    };
    affectedNodes: Array<NodeRecord<T>>;
    currentTargetValue: T | undefined;
    emit: (event: string, data: unknown) => void;
    ... 23 more ...;
    frameIdY?: number;
}
BaseDragState
<function (type parameter) T in ParentConfig<T>T>
) => void; ParentConfig<T>.handleNodeKeydown: (data: NodeEventData<T>, state: DragState<T>) => voidhandleNodeKeydown: (data: NodeEventData<T>data: interface NodeEventData<T>
The data passed to the node event listener.
NodeEventData
<function (type parameter) T in ParentConfig<T>T>, state: DragState<T>state: type DragState<T> = DragStateProps<T> & BaseDragState<T>DragState<function (type parameter) T in ParentConfig<T>T>) => void;
/** * Function that is called when dragend or touchend event occurs. */ ParentConfig<T>.handleDragend: (data: NodeDragEventData<T>, state: DragState<T>) => void
Function that is called when dragend or touchend event occurs.
handleDragend
: (data: NodeDragEventData<T>data: interface NodeDragEventData<T>
The data passed to the node event listener when the event is a drag event.
NodeDragEventData
<function (type parameter) T in ParentConfig<T>T>, state: DragState<T>state: type DragState<T> = DragStateProps<T> & BaseDragState<T>DragState<function (type parameter) T in ParentConfig<T>T>) => void;
/** * Function that is called when dragstart event occurs. */ ParentConfig<T>.handleDragstart: (data: NodeDragEventData<T>, state: DragState<T>) => void
Function that is called when dragstart event occurs.
handleDragstart
: (data: NodeDragEventData<T>data: interface NodeDragEventData<T>
The data passed to the node event listener when the event is a drag event.
NodeDragEventData
<function (type parameter) T in ParentConfig<T>T>, state: DragState<T>state: type DragState<T> = DragStateProps<T> & BaseDragState<T>DragState<function (type parameter) T in ParentConfig<T>T>) => void;
ParentConfig<T>.handleEnd: (state: DragState<T> | SynthDragState<T>) => voidhandleEnd: (state: DragState<T> | SynthDragState<T>state: type DragState<T> = DragStateProps<T> & BaseDragState<T>DragState<function (type parameter) T in ParentConfig<T>T> | type SynthDragState<T> = SynthDragStateProps & DragStateProps<T> & BaseDragState<T>
The state of the current drag. State is only created when a drag start event is triggered.
@paramactiveNode - The node that was most recently clicked (used optionally).@paramaffectedNodes - The nodes that will be updated by a drag action (sorted).@paramascendingDirection - Indicates whetehr the dragged node is moving to a node with a higher index or not.@paramclonedDraggedEls - The cloned elements of the dragged node. This is used primarily for TouchEvents or multi-drag purposes.@paramdraggedNode - The node that is being dragged.@paramdraggedNodes - The nodes that are being dragged.@paramincomingDirection - The direction that the dragged node is moving into a dragover node.@paraminitialParent - The parent that the dragged node was initially in.@paramcurrentParent - The parent that the dragged node was most recently in.@paramlastValue - The last value of the dragged node.@paramoriginalZIndex - The original z-index of the dragged node.@parampreventEnter - A flag to prevent a sort operation from firing until the mutation observer has had a chance to update the data of the remapped nodes.@paramswappedNodeValue - The value of the node that was swapped with the dragged node.@paramtargetIndex - The index of the node that the dragged node is moving into.
SynthDragState
<function (type parameter) T in ParentConfig<T>T>) => void;
ParentConfig<T>.handleNodeDrop: (data: NodeDragEventData<T>, state: DragState<T>) => voidhandleNodeDrop: (data: NodeDragEventData<T>data: interface NodeDragEventData<T>
The data passed to the node event listener when the event is a drag event.
NodeDragEventData
<function (type parameter) T in ParentConfig<T>T>, state: DragState<T>state: type DragState<T> = DragStateProps<T> & BaseDragState<T>DragState<function (type parameter) T in ParentConfig<T>T>) => void;
ParentConfig<T>.handleNodePointerup: (data: NodePointerEventData<T>, state: DragState<T>) => voidhandleNodePointerup: ( data: NodePointerEventData<T>data: interface NodePointerEventData<T>
The data passed to the node event listener when the event is a pointer event (not a native drag event).
NodePointerEventData
<function (type parameter) T in ParentConfig<T>T>,
state: DragState<T>state: type DragState<T> = DragStateProps<T> & BaseDragState<T>DragState<function (type parameter) T in ParentConfig<T>T> ) => void; ParentConfig<T>.handleParentScroll: (data: ParentEventData<T>, state: DragState<T> | BaseDragState<T> | SynthDragState<T>) => voidhandleParentScroll: ( data: ParentEventData<T>data: interface ParentEventData<T>
The data passed to the parent event listener.
@parame - The event that was triggered.@paramtargetData - The data of the target parent.
ParentEventData
<function (type parameter) T in ParentConfig<T>T>,
state: BaseDragState<T> | DragState<T> | SynthDragState<T>state: type DragState<T> = DragStateProps<T> & BaseDragState<T>DragState<function (type parameter) T in ParentConfig<T>T> |
type BaseDragState<T> = {
    activeState?: {
        node: NodeRecord<T>;
        parent: ParentRecord<T>;
    };
    affectedNodes: Array<NodeRecord<T>>;
    currentTargetValue: T | undefined;
    emit: (event: string, data: unknown) => void;
    ... 23 more ...;
    frameIdY?: number;
}
BaseDragState
<function (type parameter) T in ParentConfig<T>T> | type SynthDragState<T> = SynthDragStateProps & DragStateProps<T> & BaseDragState<T>
The state of the current drag. State is only created when a drag start event is triggered.
@paramactiveNode - The node that was most recently clicked (used optionally).@paramaffectedNodes - The nodes that will be updated by a drag action (sorted).@paramascendingDirection - Indicates whetehr the dragged node is moving to a node with a higher index or not.@paramclonedDraggedEls - The cloned elements of the dragged node. This is used primarily for TouchEvents or multi-drag purposes.@paramdraggedNode - The node that is being dragged.@paramdraggedNodes - The nodes that are being dragged.@paramincomingDirection - The direction that the dragged node is moving into a dragover node.@paraminitialParent - The parent that the dragged node was initially in.@paramcurrentParent - The parent that the dragged node was most recently in.@paramlastValue - The last value of the dragged node.@paramoriginalZIndex - The original z-index of the dragged node.@parampreventEnter - A flag to prevent a sort operation from firing until the mutation observer has had a chance to update the data of the remapped nodes.@paramswappedNodeValue - The value of the node that was swapped with the dragged node.@paramtargetIndex - The index of the node that the dragged node is moving into.
SynthDragState
<function (type parameter) T in ParentConfig<T>T>
) => void; /** * Function that is called when a dragenter event is triggered on the node. */ ParentConfig<T>.handleNodeDragenter: (data: NodeDragEventData<T>, state: DragState<T>) => void
Function that is called when a dragenter event is triggered on the node.
handleNodeDragenter
: (
data: NodeDragEventData<T>data: interface NodeDragEventData<T>
The data passed to the node event listener when the event is a drag event.
NodeDragEventData
<function (type parameter) T in ParentConfig<T>T>,
state: DragState<T>state: type DragState<T> = DragStateProps<T> & BaseDragState<T>DragState<function (type parameter) T in ParentConfig<T>T> ) => void; ParentConfig<T>.handleNodeBlur: (data: NodeEventData<T>, state: DragState<T>) => voidhandleNodeBlur: (data: NodeEventData<T>data: interface NodeEventData<T>
The data passed to the node event listener.
NodeEventData
<function (type parameter) T in ParentConfig<T>T>, state: DragState<T>state: type DragState<T> = DragStateProps<T> & BaseDragState<T>DragState<function (type parameter) T in ParentConfig<T>T>) => void;
ParentConfig<T>.handleNodeFocus: (data: NodeEventData<T>, state: DragState<T>) => voidhandleNodeFocus: (data: NodeEventData<T>data: interface NodeEventData<T>
The data passed to the node event listener.
NodeEventData
<function (type parameter) T in ParentConfig<T>T>, state: DragState<T>state: type DragState<T> = DragStateProps<T> & BaseDragState<T>DragState<function (type parameter) T in ParentConfig<T>T>) => void;
/** * Dragleave event on node */ ParentConfig<T>.handleNodeDragleave: (data: NodeDragEventData<T>, state: DragState<T>) => void
Dragleave event on node
handleNodeDragleave
: (
data: NodeDragEventData<T>data: interface NodeDragEventData<T>
The data passed to the node event listener when the event is a drag event.
NodeDragEventData
<function (type parameter) T in ParentConfig<T>T>,
state: DragState<T>state: type DragState<T> = DragStateProps<T> & BaseDragState<T>DragState<function (type parameter) T in ParentConfig<T>T> ) => void; /** * Function that is called when a dragover event is triggered on the parent. */ ParentConfig<T>.handleParentDragover: (data: ParentDragEventData<T>, state: DragState<T>) => void
Function that is called when a dragover event is triggered on the parent.
handleParentDragover
: (
data: ParentDragEventData<T>data: interface ParentDragEventData<T>ParentDragEventData<function (type parameter) T in ParentConfig<T>T>, state: DragState<T>state: type DragState<T> = DragStateProps<T> & BaseDragState<T>DragState<function (type parameter) T in ParentConfig<T>T> ) => void; /** * Drop event on parent */ ParentConfig<T>.handleParentDrop: (data: ParentDragEventData<T>, state: DragState<T>) => void
Drop event on parent
handleParentDrop
: (data: ParentDragEventData<T>data: interface ParentDragEventData<T>ParentDragEventData<function (type parameter) T in ParentConfig<T>T>, state: DragState<T>state: type DragState<T> = DragStateProps<T> & BaseDragState<T>DragState<function (type parameter) T in ParentConfig<T>T>) => void;
/** * Function that is called when a dragover event is triggered on a node. */ ParentConfig<T>.handleNodeDragover: (data: NodeDragEventData<T>, state: DragState<T>) => void
Function that is called when a dragover event is triggered on a node.
handleNodeDragover
: (data: NodeDragEventData<T>data: interface NodeDragEventData<T>
The data passed to the node event listener when the event is a drag event.
NodeDragEventData
<function (type parameter) T in ParentConfig<T>T>, state: DragState<T>state: type DragState<T> = DragStateProps<T> & BaseDragState<T>DragState<function (type parameter) T in ParentConfig<T>T>) => void;
ParentConfig<T>.handlePointercancel: (data: NodeDragEventData<T> | NodePointerEventData<T>, state: DragState<T> | SynthDragState<T> | BaseDragState<T>) => voidhandlePointercancel: ( data: NodeDragEventData<T> | NodePointerEventData<T>data: interface NodeDragEventData<T>
The data passed to the node event listener when the event is a drag event.
NodeDragEventData
<function (type parameter) T in ParentConfig<T>T> | interface NodePointerEventData<T>
The data passed to the node event listener when the event is a pointer event (not a native drag event).
NodePointerEventData
<function (type parameter) T in ParentConfig<T>T>,
state: BaseDragState<T> | DragState<T> | SynthDragState<T>state: type DragState<T> = DragStateProps<T> & BaseDragState<T>DragState<function (type parameter) T in ParentConfig<T>T> | type SynthDragState<T> = SynthDragStateProps & DragStateProps<T> & BaseDragState<T>
The state of the current drag. State is only created when a drag start event is triggered.
@paramactiveNode - The node that was most recently clicked (used optionally).@paramaffectedNodes - The nodes that will be updated by a drag action (sorted).@paramascendingDirection - Indicates whetehr the dragged node is moving to a node with a higher index or not.@paramclonedDraggedEls - The cloned elements of the dragged node. This is used primarily for TouchEvents or multi-drag purposes.@paramdraggedNode - The node that is being dragged.@paramdraggedNodes - The nodes that are being dragged.@paramincomingDirection - The direction that the dragged node is moving into a dragover node.@paraminitialParent - The parent that the dragged node was initially in.@paramcurrentParent - The parent that the dragged node was most recently in.@paramlastValue - The last value of the dragged node.@paramoriginalZIndex - The original z-index of the dragged node.@parampreventEnter - A flag to prevent a sort operation from firing until the mutation observer has had a chance to update the data of the remapped nodes.@paramswappedNodeValue - The value of the node that was swapped with the dragged node.@paramtargetIndex - The index of the node that the dragged node is moving into.
SynthDragState
<function (type parameter) T in ParentConfig<T>T> |
type BaseDragState<T> = {
    activeState?: {
        node: NodeRecord<T>;
        parent: ParentRecord<T>;
    };
    affectedNodes: Array<NodeRecord<T>>;
    currentTargetValue: T | undefined;
    emit: (event: string, data: unknown) => void;
    ... 23 more ...;
    frameIdY?: number;
}
BaseDragState
<function (type parameter) T in ParentConfig<T>T>
) => void; /* * Function that is called when a pointerdown is triggered on node. */ ParentConfig<T>.handleNodePointerdown: (data: NodePointerEventData<T>, state: DragState<T>) => voidhandleNodePointerdown: ( data: NodePointerEventData<T>data: interface NodePointerEventData<T>
The data passed to the node event listener when the event is a pointer event (not a native drag event).
NodePointerEventData
<function (type parameter) T in ParentConfig<T>T>,
state: DragState<T>state: type DragState<T> = DragStateProps<T> & BaseDragState<T>DragState<function (type parameter) T in ParentConfig<T>T> ) => void; /** * Function that is called when a node that is being moved by touchmove event * is over a given node (similar to dragover). */ ParentConfig<T>.handleNodePointerover: (data: PointeroverNodeEvent<T>, state: SynthDragState<T>) => void
Function that is called when a node that is being moved by touchmove event is over a given node (similar to dragover).
handleNodePointerover
: (
data: PointeroverNodeEvent<T>data: interface PointeroverNodeEvent<T>
The payload of the custom event dispatched when a node is "touched" over a node.
PointeroverNodeEvent
<function (type parameter) T in ParentConfig<T>T>,
state: SynthDragState<T>state: type SynthDragState<T> = SynthDragStateProps & DragStateProps<T> & BaseDragState<T>
The state of the current drag. State is only created when a drag start event is triggered.
@paramactiveNode - The node that was most recently clicked (used optionally).@paramaffectedNodes - The nodes that will be updated by a drag action (sorted).@paramascendingDirection - Indicates whetehr the dragged node is moving to a node with a higher index or not.@paramclonedDraggedEls - The cloned elements of the dragged node. This is used primarily for TouchEvents or multi-drag purposes.@paramdraggedNode - The node that is being dragged.@paramdraggedNodes - The nodes that are being dragged.@paramincomingDirection - The direction that the dragged node is moving into a dragover node.@paraminitialParent - The parent that the dragged node was initially in.@paramcurrentParent - The parent that the dragged node was most recently in.@paramlastValue - The last value of the dragged node.@paramoriginalZIndex - The original z-index of the dragged node.@parampreventEnter - A flag to prevent a sort operation from firing until the mutation observer has had a chance to update the data of the remapped nodes.@paramswappedNodeValue - The value of the node that was swapped with the dragged node.@paramtargetIndex - The index of the node that the dragged node is moving into.
SynthDragState
<function (type parameter) T in ParentConfig<T>T>
) => void; /** * Function that is called when a node that is being moved by touchmove event * is over the parent (similar to dragover). */ ParentConfig<T>.handleParentPointerover: (e: PointeroverParentEvent<T>, state: SynthDragState<T>) => void
Function that is called when a node that is being moved by touchmove event is over the parent (similar to dragover).
handleParentPointerover
: (
e: PointeroverParentEvent<T>e: interface PointeroverParentEvent<T>
The payload of the custom event dispatched when a node is "touched" over a parent.
PointeroverParentEvent
<function (type parameter) T in ParentConfig<T>T>,
state: SynthDragState<T>state: type SynthDragState<T> = SynthDragStateProps & DragStateProps<T> & BaseDragState<T>
The state of the current drag. State is only created when a drag start event is triggered.
@paramactiveNode - The node that was most recently clicked (used optionally).@paramaffectedNodes - The nodes that will be updated by a drag action (sorted).@paramascendingDirection - Indicates whetehr the dragged node is moving to a node with a higher index or not.@paramclonedDraggedEls - The cloned elements of the dragged node. This is used primarily for TouchEvents or multi-drag purposes.@paramdraggedNode - The node that is being dragged.@paramdraggedNodes - The nodes that are being dragged.@paramincomingDirection - The direction that the dragged node is moving into a dragover node.@paraminitialParent - The parent that the dragged node was initially in.@paramcurrentParent - The parent that the dragged node was most recently in.@paramlastValue - The last value of the dragged node.@paramoriginalZIndex - The original z-index of the dragged node.@parampreventEnter - A flag to prevent a sort operation from firing until the mutation observer has had a chance to update the data of the remapped nodes.@paramswappedNodeValue - The value of the node that was swapped with the dragged node.@paramtargetIndex - The index of the node that the dragged node is moving into.
SynthDragState
<function (type parameter) T in ParentConfig<T>T>
) => void; /** * Config option for insert plugin. */ ParentConfig<T>.insertConfig?: InsertConfig<T> | undefined
Config option for insert plugin.
insertConfig
?: interface InsertConfig<T>InsertConfig<function (type parameter) T in ParentConfig<T>T>;
/** * A flag to indicate whether long touch is enabled. */ ParentConfig<T>.longPress?: boolean | undefined
A flag to indicate whether long touch is enabled.
longPress
?: boolean;
/** * The class to add to a node when a long touch action is performed. */ ParentConfig<T>.longPressClass?: string | undefined
The class to add to a node when a long touch action is performed.
longPressClass
?: string;
/** * The time in milliseconds to wait before a long touch is performed. */ ParentConfig<T>.longPressDuration?: number | undefined
The time in milliseconds to wait before a long touch is performed.
longPressDuration
?: number;
/** * The name of the parent (used for accepts function for increased specificity). */ ParentConfig<T>.name?: string | undefined
The name of the parent (used for accepts function for increased specificity).
name
?: string;
ParentConfig<T>.multiDrag?: boolean | undefinedmultiDrag?: boolean; /** * If set to false, the library will not use the native drag and drop API. */ ParentConfig<T>.nativeDrag?: boolean | undefined
If set to false, the library will not use the native drag and drop API.
nativeDrag
?: boolean;
/** * Function that is called when a sort operation is to be performed. */
ParentConfig<T>.performSort: ({ parent, draggedNodes, targetNodes, }: {
    parent: ParentRecord<T>;
    draggedNodes: Array<NodeRecord<T>>;
    targetNodes: Array<NodeRecord<T>>;
}) => void
Function that is called when a sort operation is to be performed.
performSort
: ({
parent: ParentRecord<T>parent, draggedNodes: NodeRecord<T>[]draggedNodes, targetNodes: NodeRecord<T>[]targetNodes, }: { parent: ParentRecord<T>parent: interface ParentRecord<T>
The parent record, contains the el and the data in the `parents` weakmap.
ParentRecord
<function (type parameter) T in ParentConfig<T>T>;
draggedNodes: NodeRecord<T>[]draggedNodes: interface Array<T>Array<interface NodeRecord<T>
The node record, contains the el and the data in the `nodes` weakmap.
NodeRecord
<function (type parameter) T in ParentConfig<T>T>>;
targetNodes: NodeRecord<T>[]targetNodes: interface Array<T>Array<interface NodeRecord<T>
The node record, contains the el and the data in the `nodes` weakmap.
NodeRecord
<function (type parameter) T in ParentConfig<T>T>>;
}) => void; /** * Function that is called when a transfer operation is to be performed. */
ParentConfig<T>.performTransfer: ({ currentParent, targetParent, initialParent, draggedNodes, initialIndex, state, targetNodes, }: {
    currentParent: ParentRecord<T>;
    targetParent: ParentRecord<T>;
    initialParent: ParentRecord<T>;
    draggedNodes: Array<NodeRecord<T>>;
    initialIndex: number;
    state: BaseDragState<T> | DragState<T> | SynthDragState<T>;
    targetNodes: Array<NodeRecord<T>>;
}) => void
Function that is called when a transfer operation is to be performed.
performTransfer
: ({
currentParent: ParentRecord<T>currentParent, targetParent: ParentRecord<T>targetParent, initialParent: ParentRecord<T>initialParent, draggedNodes: NodeRecord<T>[]draggedNodes, initialIndex: numberinitialIndex, state: BaseDragState<T> | DragState<T> | SynthDragState<T>state, targetNodes: NodeRecord<T>[]targetNodes, }: { currentParent: ParentRecord<T>currentParent: interface ParentRecord<T>
The parent record, contains the el and the data in the `parents` weakmap.
ParentRecord
<function (type parameter) T in ParentConfig<T>T>;
targetParent: ParentRecord<T>targetParent: interface ParentRecord<T>
The parent record, contains the el and the data in the `parents` weakmap.
ParentRecord
<function (type parameter) T in ParentConfig<T>T>;
initialParent: ParentRecord<T>initialParent: interface ParentRecord<T>
The parent record, contains the el and the data in the `parents` weakmap.
ParentRecord
<function (type parameter) T in ParentConfig<T>T>;
draggedNodes: NodeRecord<T>[]draggedNodes: interface Array<T>Array<interface NodeRecord<T>
The node record, contains the el and the data in the `nodes` weakmap.
NodeRecord
<function (type parameter) T in ParentConfig<T>T>>;
initialIndex: numberinitialIndex: number; state: BaseDragState<T> | DragState<T> | SynthDragState<T>state:
type BaseDragState<T> = {
    activeState?: {
        node: NodeRecord<T>;
        parent: ParentRecord<T>;
    };
    affectedNodes: Array<NodeRecord<T>>;
    currentTargetValue: T | undefined;
    emit: (event: string, data: unknown) => void;
    ... 23 more ...;
    frameIdY?: number;
}
BaseDragState
<function (type parameter) T in ParentConfig<T>T> | type DragState<T> = DragStateProps<T> & BaseDragState<T>DragState<function (type parameter) T in ParentConfig<T>T> | type SynthDragState<T> = SynthDragStateProps & DragStateProps<T> & BaseDragState<T>
The state of the current drag. State is only created when a drag start event is triggered.
@paramactiveNode - The node that was most recently clicked (used optionally).@paramaffectedNodes - The nodes that will be updated by a drag action (sorted).@paramascendingDirection - Indicates whetehr the dragged node is moving to a node with a higher index or not.@paramclonedDraggedEls - The cloned elements of the dragged node. This is used primarily for TouchEvents or multi-drag purposes.@paramdraggedNode - The node that is being dragged.@paramdraggedNodes - The nodes that are being dragged.@paramincomingDirection - The direction that the dragged node is moving into a dragover node.@paraminitialParent - The parent that the dragged node was initially in.@paramcurrentParent - The parent that the dragged node was most recently in.@paramlastValue - The last value of the dragged node.@paramoriginalZIndex - The original z-index of the dragged node.@parampreventEnter - A flag to prevent a sort operation from firing until the mutation observer has had a chance to update the data of the remapped nodes.@paramswappedNodeValue - The value of the node that was swapped with the dragged node.@paramtargetIndex - The index of the node that the dragged node is moving into.
SynthDragState
<function (type parameter) T in ParentConfig<T>T>;
targetNodes: NodeRecord<T>[]targetNodes: interface Array<T>Array<interface NodeRecord<T>
The node record, contains the el and the data in the `nodes` weakmap.
NodeRecord
<function (type parameter) T in ParentConfig<T>T>>;
}) => void; /** * An array of functions to use for a given parent. */ ParentConfig<T>.plugins?: DNDPlugin[] | undefined
An array of functions to use for a given parent.
plugins
?: interface Array<T>Array<type DNDPlugin = (parent: HTMLElement) => DNDPluginData | undefinedDNDPlugin>;
/** * Takes a given node and reapplies the drag classes. */ ParentConfig<T>.reapplyDragClasses: (node: Node, parentData: ParentData<T>) => void
Takes a given node and reapplies the drag classes.
reapplyDragClasses
: (node: Nodenode: Node, parentData: ParentData<T>parentData: interface ParentData<T>
The data assigned to a given parent in the `parents` weakmap.
ParentData
<function (type parameter) T in ParentConfig<T>T>) => void;
/** * Invoked when the remapping of a given parent's nodes is finished. */ ParentConfig<T>.remapFinished: (data: ParentData<T>) => void
Invoked when the remapping of a given parent's nodes is finished.
remapFinished
: (data: ParentData<T>data: interface ParentData<T>
The data assigned to a given parent in the `parents` weakmap.
ParentData
<function (type parameter) T in ParentConfig<T>T>) => void;
/** * The root element to use for the parent. */ ParentConfig<T>.root: Document | ShadowRoot
The root element to use for the parent.
root
: Document | ShadowRoot;
/** * The class to add to a node when it is selected (clicked or pressed). */ ParentConfig<T>.selectedClass?: string | undefined
The class to add to a node when it is selected (clicked or pressed).
selectedClass
?: string;
/** * Function that is called when a node is set up. */ ParentConfig<T>.setupNode: SetupNode
Function that is called when a node is set up.
setupNode
: type SetupNode = <T>(data: SetupNodeData<T>) => voidSetupNode;
/** * Called when the value of the parent is changed and the nodes are remapped. */ ParentConfig<T>.setupNodeRemap: SetupNode
Called when the value of the parent is changed and the nodes are remapped.
setupNodeRemap
: type SetupNode = <T>(data: SetupNodeData<T>) => voidSetupNode;
/** * Flag for whether or not to allow sorting within a given parent. */ ParentConfig<T>.sortable?: boolean | undefined
Flag for whether or not to allow sorting within a given parent.
sortable
?: boolean;
/** * The class to add to a parent when it is dragged over. */ ParentConfig<T>.synthDropZoneParentClass?: string | undefined
The class to add to a parent when it is dragged over.
synthDropZoneParentClass
?: string;
/** * A function that returns the image to use for the drag operation. This is * invoked for synth drag operations operations. The clonedNode is what will * be set as the drag image, but this can be updated. */
ParentConfig<T>.synthDragImage?: ((node: NodeRecord<T>, parent: ParentRecord<T>, e: PointerEvent, draggedNodes: Array<NodeRecord<T>>) => {
    dragImage: HTMLElement;
    offsetX?: number;
    offsetY?: number;
}) | undefined
A function that returns the image to use for the drag operation. This is invoked for synth drag operations operations. The clonedNode is what will be set as the drag image, but this can be updated.
synthDragImage
?: (
node: NodeRecord<T>node: interface NodeRecord<T>
The node record, contains the el and the data in the `nodes` weakmap.
NodeRecord
<function (type parameter) T in ParentConfig<T>T>,
parent: ParentRecord<T>parent: interface ParentRecord<T>
The parent record, contains the el and the data in the `parents` weakmap.
ParentRecord
<function (type parameter) T in ParentConfig<T>T>,
e: PointerEvente: PointerEvent, draggedNodes: NodeRecord<T>[]draggedNodes: interface Array<T>Array<interface NodeRecord<T>
The node record, contains the el and the data in the `nodes` weakmap.
NodeRecord
<function (type parameter) T in ParentConfig<T>T>>
) => { dragImage: HTMLElementdragImage: HTMLElement; offsetX?: number | undefinedoffsetX?: number; offsetY?: number | undefinedoffsetY?: number; }; /** * Function that is called when a node is torn down. */ ParentConfig<T>.tearDownNode: TearDownNode
Function that is called when a node is torn down.
tearDownNode
: type TearDownNode = <T>(data: TearDownNodeData<T>) => voidTearDownNode;
/** * Called when the value of the parent is changed and the nodes are remapped. */ ParentConfig<T>.tearDownNodeRemap: TearDownNode
Called when the value of the parent is changed and the nodes are remapped.
tearDownNodeRemap
: type TearDownNode = <T>(data: TearDownNodeData<T>) => voidTearDownNode;
/** * Property to identify which group of tree descendants the current parent belongs to. */ /** * The threshold for a drag to be considered a valid sort * operation. */
ParentConfig<T>.threshold: {
    horizontal: number;
    vertical: number;
}
The threshold for a drag to be considered a valid sort operation.
threshold
: {
horizontal: numberhorizontal: number; vertical: numbervertical: number; }; /** * The class to add to a node when it is being synthetically dragged. */ ParentConfig<T>.synthDraggingClass?: string | undefined
The class to add to a node when it is being synthetically dragged.
synthDraggingClass
?: string;
/** * On synth drag start, this is applied to the dragged node(s) (not their * representations being dragged). */ ParentConfig<T>.synthDragPlaceholderClass?: string | undefined
On synth drag start, this is applied to the dragged node(s) (not their representations being dragged).
synthDragPlaceholderClass
?: string;
/** * When hovering over a node, this class is applied to the node. */ ParentConfig<T>.synthDropZoneClass?: string | undefined
When hovering over a node, this class is applied to the node.
synthDropZoneClass
?: string;
/** * Callback function for when a sort operation is performed. */ ParentConfig<T>.onSort?: SortEvent | undefined
Callback function for when a sort operation is performed.
onSort
?: type SortEvent = <T>(data: SortEventData<T>) => voidSortEvent;
/** * Callback function for when a transfer operation is performed. */ ParentConfig<T>.onTransfer?: TransferEvent | undefined
Callback function for when a transfer operation is performed.
onTransfer
?: type TransferEvent = <T>(data: TransferEventData<T>) => voidTransferEvent;
/** * Fired when a drag is started, whether native drag or synthetic */ ParentConfig<T>.onDragstart?: DragstartEvent | undefined
Fired when a drag is started, whether native drag or synthetic
onDragstart
?: type DragstartEvent = <T>(data: DragstartEventData<T>) => voidDragstartEvent;
/** * Fired when a drag is ended, whether native drag or synthetic */ ParentConfig<T>.onDragend?: DragendEvent | undefined
Fired when a drag is ended, whether native drag or synthetic
onDragend
?: type DragendEvent = <T>(data: DragendEventData<T>) => voidDragendEvent;
}

Accessibility

Below is an example of how to implement drag and drop lists with accessibility in mind.

  • React
  • Vue
  • Solid
  • Native
import React, { function useState<S>(initialState: S | (() => S)): [S, React.Dispatch<React.SetStateAction<S>>] (+1 overload)
Returns a stateful value, and a function to update it.
@version16.8.0@see{@link https://react.dev/reference/react/useState}
useState
, function useRef<T>(initialValue: T): React.MutableRefObject<T> (+2 overloads)
`useRef` returns a mutable ref object whose `.current` property is initialized to the passed argument (`initialValue`). The returned object will persist for the full lifetime of the component. Note that `useRef()` is useful for more than the `ref` attribute. It’s handy for keeping any mutable value around similar to how you’d use instance fields in classes.
@version16.8.0@see{@link https://react.dev/reference/react/useRef}
useRef
, function useCallback<T extends Function>(callback: T, deps: React.DependencyList): T
`useCallback` will return a memoized version of the callback that only changes if one of the `inputs` has changed.
@version16.8.0@see{@link https://react.dev/reference/react/useCallback}
useCallback
, function useMemo<T>(factory: () => T, deps: React.DependencyList): T
`useMemo` will only recompute the memoized value when one of the `deps` has changed.
@version16.8.0@see{@link https://react.dev/reference/react/useMemo}
useMemo
} from "react";
import { function useDragAndDrop<E extends HTMLElement, T = unknown>(list: T[], options?: Partial<ParentConfig<T>>): [React.RefObject<E>, T[], React.Dispatch<React.SetStateAction<T[]>>, (config: Partial<ParentConfig<...>>) => void]
Hook for adding drag and drop/sortable support to a list of items.
@paramlist - Initial list of data.@paramoptions - The drag and drop configuration.@returns
useDragAndDrop
} from "@formkit/drag-and-drop/react";
// Initial data for the lists const const initialItems1: string[]initialItems1 = ["Apples", "Bananas", "Oranges", "Grapes"]; const const initialItems2: string[]initialItems2 = ["Milk", "Cheese", "Yogurt"]; interface SelectedItem { SelectedItem.listIndex: 0 | 1listIndex: 0 | 1; SelectedItem.itemIndex: numberitemIndex: number; SelectedItem.value: stringvalue: string; } export default function function AccessibilityDemoReact(): React.JSX.ElementAccessibilityDemoReact() { // Refs for ARIA Live region const [const liveMessage: stringliveMessage, const setLiveMessage: React.Dispatch<React.SetStateAction<string>>setLiveMessage] = useState<string>(initialState: string | (() => string)): [string, React.Dispatch<React.SetStateAction<string>>] (+1 overload)
Returns a stateful value, and a function to update it.
@version16.8.0@see{@link https://react.dev/reference/react/useState}
useState
("");
const const liveRegionRef: React.RefObject<HTMLDivElement>liveRegionRef = useRef<HTMLDivElement>(initialValue: HTMLDivElement | null): React.RefObject<HTMLDivElement> (+2 overloads)
`useRef` returns a mutable ref object whose `.current` property is initialized to the passed argument (`initialValue`). The returned object will persist for the full lifetime of the component. Note that `useRef()` is useful for more than the `ref` attribute. It’s handy for keeping any mutable value around similar to how you’d use instance fields in classes. Usage note: if you need the result of useRef to be directly mutable, include `| null` in the type of the generic argument.
@version16.8.0@see{@link https://react.dev/reference/react/useRef}
useRef
<HTMLDivElement>(null);
// Function to update the live region const const announce: (message: string) => voidannounce = useCallback<(message: string) => void>(callback: (message: string) => void, deps: React.DependencyList): (message: string) => void
`useCallback` will return a memoized version of the callback that only changes if one of the `inputs` has changed.
@version16.8.0@see{@link https://react.dev/reference/react/useCallback}
useCallback
((message: stringmessage: string) => {
const setLiveMessage: (value: React.SetStateAction<string>) => voidsetLiveMessage(message: stringmessage); // Optional: Clear the message after a delay // const timer = setTimeout(() => setLiveMessage(''), 5000); // return () => clearTimeout(timer); }, []); // Setup drag and drop for List 1 const [const list1Ref: React.RefObject<HTMLUListElement>list1Ref, const items1: string[]items1, const setItems1: React.Dispatch<React.SetStateAction<string[]>>setItems1] = useDragAndDrop<HTMLUListElement, string>(list: string[], options?: Partial<ParentConfig<string>> | undefined): [React.RefObject<HTMLUListElement>, string[], React.Dispatch<...>, (config: Partial<...>) => void]
Hook for adding drag and drop/sortable support to a list of items.
@paramlist - Initial list of data.@paramoptions - The drag and drop configuration.@returns
useDragAndDrop
<
HTMLUListElement, string >(const initialItems1: string[]initialItems1, { group?: string | undefined
The group that the parent belongs to. This is used for allowing multiple parents to transfer nodes between each other.
group
: "accessibleList",
// Let types be inferred onDragstart?: DragstartEvent | undefined
Fired when a drag is started, whether native drag or synthetic
onDragstart
: (state: DragstartEventData<T>state) =>
const announce: (message: string) => voidannounce(`Drag started for ${state: DragstartEventData<T>state.DragstartEventData<T>.draggedNode: NodeRecord<T>draggedNode.NodeRecord<T>.data: NodeData<T>data.NodeData<T>.value: T
The value of the node.
value
}.`),
onSort?: SortEvent | undefined
Callback function for when a sort operation is performed.
onSort
: (event: SortEventData<T>event) =>
const announce: (message: string) => voidannounce( `Sorted ${event: SortEventData<T>event.SortEventData<T>.draggedNodes: NodeRecord<T>[]draggedNodes[0].NodeRecord<T>.data: NodeData<T>data.NodeData<T>.value: T
The value of the node.
value
} in List 1 to position ${
event: SortEventData<T>event.SortEventData<T>.position: numberposition + 1 }.` ), onTransfer?: TransferEvent | undefined
Callback function for when a transfer operation is performed.
onTransfer
: (event: TransferEventData<T>event) => {
const announce: (message: string) => voidannounce( `Transferred ${event: TransferEventData<T>event.TransferEventData<T>.draggedNodes: NodeRecord<T>[]draggedNodes[0].NodeRecord<T>.data: NodeData<T>data.NodeData<T>.value: T
The value of the node.
value
} from List ${
event: TransferEventData<T>event.TransferEventData<T>.sourceParent: ParentRecord<T>sourceParent.ParentRecord<T>.el: HTMLElementel === const list1Ref: React.RefObject<HTMLUListElement>list1Ref.React.RefObject<HTMLUListElement>.current: HTMLUListElement | null
The current value of the ref.
current
? 1 : 2
} to List 1 at position ${event: TransferEventData<T>event.TransferEventData<T>.targetIndex: numbertargetIndex + 1}.` ); }, onDragend?: DragendEvent | undefined
Fired when a drag is ended, whether native drag or synthetic
onDragend
: (state: DragendEventData<T>state) =>
const announce: (message: string) => voidannounce(`Drag ended for ${state: DragendEventData<T>state.DragendEventData<T>.draggedNode: NodeRecord<T>draggedNode.NodeRecord<T>.data: NodeData<T>data.NodeData<T>.value: T
The value of the node.
value
}.`),
}); // Setup drag and drop for List 2 const [const list2Ref: React.RefObject<HTMLUListElement>list2Ref, const items2: string[]items2, const setItems2: React.Dispatch<React.SetStateAction<string[]>>setItems2] = useDragAndDrop<HTMLUListElement, string>(list: string[], options?: Partial<ParentConfig<string>> | undefined): [React.RefObject<HTMLUListElement>, string[], React.Dispatch<...>, (config: Partial<...>) => void]
Hook for adding drag and drop/sortable support to a list of items.
@paramlist - Initial list of data.@paramoptions - The drag and drop configuration.@returns
useDragAndDrop
<
HTMLUListElement, string >(const initialItems2: string[]initialItems2, { group?: string | undefined
The group that the parent belongs to. This is used for allowing multiple parents to transfer nodes between each other.
group
: "accessibleList",
onDragstart?: DragstartEvent | undefined
Fired when a drag is started, whether native drag or synthetic
onDragstart
: (state: DragstartEventData<T>state) =>
const announce: (message: string) => voidannounce(`Drag started for ${state: DragstartEventData<T>state.DragstartEventData<T>.draggedNode: NodeRecord<T>draggedNode.NodeRecord<T>.data: NodeData<T>data.NodeData<T>.value: T
The value of the node.
value
}.`),
onSort?: SortEvent | undefined
Callback function for when a sort operation is performed.
onSort
: (event: SortEventData<T>event) =>
const announce: (message: string) => voidannounce( `Sorted ${event: SortEventData<T>event.SortEventData<T>.draggedNodes: NodeRecord<T>[]draggedNodes[0].NodeRecord<T>.data: NodeData<T>data.NodeData<T>.value: T
The value of the node.
value
} in List 2 to position ${
event: SortEventData<T>event.SortEventData<T>.position: numberposition + 1 }.` ), onTransfer?: TransferEvent | undefined
Callback function for when a transfer operation is performed.
onTransfer
: (event: TransferEventData<T>event) => {
// Compare against element refs const announce: (message: string) => voidannounce( `Transferred ${event: TransferEventData<T>event.TransferEventData<T>.draggedNodes: NodeRecord<T>[]draggedNodes[0].NodeRecord<T>.data: NodeData<T>data.NodeData<T>.value: T
The value of the node.
value
} from List ${
event: TransferEventData<T>event.TransferEventData<T>.sourceParent: ParentRecord<T>sourceParent.ParentRecord<T>.el: HTMLElementel === const list1Ref: React.RefObject<HTMLUListElement>list1Ref.React.RefObject<HTMLUListElement>.current: HTMLUListElement | null
The current value of the ref.
current
? 1 : 2
} to List 2 at position ${event: TransferEventData<T>event.TransferEventData<T>.targetIndex: numbertargetIndex + 1}.` ); }, onDragend?: DragendEvent | undefined
Fired when a drag is ended, whether native drag or synthetic
onDragend
: (state: DragendEventData<T>state) =>
const announce: (message: string) => voidannounce(`Drag ended for ${state: DragendEventData<T>state.DragendEventData<T>.draggedNode: NodeRecord<T>draggedNode.NodeRecord<T>.data: NodeData<T>data.NodeData<T>.value: T
The value of the node.
value
}.`),
}); // State for keyboard navigation const [const focusedListIndex: 0 | 1 | nullfocusedListIndex, const setFocusedListIndex: React.Dispatch<React.SetStateAction<0 | 1 | null>>setFocusedListIndex] = useState<0 | 1 | null>(initialState: 0 | 1 | (() => 0 | 1 | null) | null): [0 | 1 | null, React.Dispatch<React.SetStateAction<0 | 1 | null>>] (+1 overload)
Returns a stateful value, and a function to update it.
@version16.8.0@see{@link https://react.dev/reference/react/useState}
useState
<0 | 1 | null>(null);
const [const focusedItemIndex: number | nullfocusedItemIndex, const setFocusedItemIndex: React.Dispatch<React.SetStateAction<number | null>>setFocusedItemIndex] = useState<number | null>(initialState: number | (() => number | null) | null): [number | null, React.Dispatch<React.SetStateAction<number | null>>] (+1 overload)
Returns a stateful value, and a function to update it.
@version16.8.0@see{@link https://react.dev/reference/react/useState}
useState
<number | null>(null);
const [const selectedItem: SelectedItem | nullselectedItem, const setSelectedItem: React.Dispatch<React.SetStateAction<SelectedItem | null>>setSelectedItem] = useState<SelectedItem | null>(initialState: SelectedItem | (() => SelectedItem | null) | null): [SelectedItem | null, React.Dispatch<...>] (+1 overload)
Returns a stateful value, and a function to update it.
@version16.8.0@see{@link https://react.dev/reference/react/useState}
useState
<SelectedItem | null>(null);
// Calculate focusedItemId directly const const focusedItemId: string | undefinedfocusedItemId = useMemo<string | undefined>(factory: () => string | undefined, deps: React.DependencyList): string | undefined
`useMemo` will only recompute the memoized value when one of the `deps` has changed.
@version16.8.0@see{@link https://react.dev/reference/react/useMemo}
useMemo
(() => {
if ( const focusedListIndex: 0 | 1 | nullfocusedListIndex === 0 && const focusedItemIndex: number | nullfocusedItemIndex !== null && const focusedItemIndex: numberfocusedItemIndex < const items1: string[]items1.Array<string>.length: number
Gets or sets the length of the array. This is a number one higher than the highest index in the array.
length
) { return `list1-item-${const items1: string[]items1[const focusedItemIndex: numberfocusedItemIndex]}`; } if ( const focusedListIndex: 0 | 1 | nullfocusedListIndex === 1 && const focusedItemIndex: number | nullfocusedItemIndex !== null && const focusedItemIndex: numberfocusedItemIndex < const items2: string[]items2.Array<string>.length: number
Gets or sets the length of the array. This is a number one higher than the highest index in the array.
length
) { return `list2-item-${const items2: string[]items2[const focusedItemIndex: numberfocusedItemIndex]}`; } return var undefinedundefined; }, [const focusedListIndex: 0 | 1 | nullfocusedListIndex, const focusedItemIndex: number | nullfocusedItemIndex, const items1: string[]items1, const items2: string[]items2]); const const handleListFocus: (listIndex: 0 | 1) => voidhandleListFocus = useCallback<(listIndex: 0 | 1) => void>(callback: (listIndex: 0 | 1) => void, deps: React.DependencyList): (listIndex: 0 | 1) => void
`useCallback` will return a memoized version of the callback that only changes if one of the `inputs` has changed.
@version16.8.0@see{@link https://react.dev/reference/react/useCallback}
useCallback
(
(listIndex: 0 | 1listIndex: 0 | 1) => { const setFocusedListIndex: (value: React.SetStateAction<0 | 1 | null>) => voidsetFocusedListIndex(listIndex: 0 | 1listIndex); const const currentItems: string[]currentItems = listIndex: 0 | 1listIndex === 0 ? const items1: string[]items1 : const items2: string[]items2; if (const focusedItemIndex: number | nullfocusedItemIndex === null && const currentItems: string[]currentItems.Array<string>.length: number
Gets or sets the length of the array. This is a number one higher than the highest index in the array.
length
> 0) {
const setFocusedItemIndex: (value: React.SetStateAction<number | null>) => voidsetFocusedItemIndex(0); } const announce: (message: string) => voidannounce( `List ${ listIndex: 0 | 1listIndex + 1 } focused. Use up and down arrows to navigate items.` ); }, [const items1: string[]items1, const items2: string[]items2, const announce: (message: string) => voidannounce, const focusedItemIndex: number | nullfocusedItemIndex] ); const const handleListBlur: () => voidhandleListBlur = useCallback<() => void>(callback: () => void, deps: React.DependencyList): () => void
`useCallback` will return a memoized version of the callback that only changes if one of the `inputs` has changed.
@version16.8.0@see{@link https://react.dev/reference/react/useCallback}
useCallback
(() => {
// Minimal blur handler - prevents immediate focus loss when clicking between elements // More complex logic might be needed for specific focus management scenarios }, []); const const handleListKeydown: (event: React.KeyboardEvent<HTMLUListElement>, listIndex: 0 | 1) => voidhandleListKeydown = useCallback<(event: React.KeyboardEvent<HTMLUListElement>, listIndex: 0 | 1) => void>(callback: (event: React.KeyboardEvent<HTMLUListElement>, listIndex: 0 | 1) => void, deps: React.DependencyList): (event: React.KeyboardEvent<HTMLUListElement>, listIndex: 0 | 1) => void
`useCallback` will return a memoized version of the callback that only changes if one of the `inputs` has changed.
@version16.8.0@see{@link https://react.dev/reference/react/useCallback}
useCallback
(
(event: React.KeyboardEvent<HTMLUListElement>event: React.interface React.KeyboardEvent<T = Element>KeyboardEvent<HTMLUListElement>, listIndex: 0 | 1listIndex: 0 | 1) => { if (const focusedListIndex: 0 | 1 | nullfocusedListIndex !== listIndex: 0 | 1listIndex) return; const const currentItems: string[]currentItems = listIndex: 0 | 1listIndex === 0 ? const items1: string[]items1 : const items2: string[]items2; const const setItems: React.Dispatch<React.SetStateAction<string[]>>setItems = listIndex: 0 | 1listIndex === 0 ? const setItems1: React.Dispatch<React.SetStateAction<string[]>>setItems1 : const setItems2: React.Dispatch<React.SetStateAction<string[]>>setItems2; const const currentItemIndex: number | nullcurrentItemIndex = const focusedItemIndex: number | nullfocusedItemIndex; switch (event: React.KeyboardEvent<HTMLUListElement>event.React.KeyboardEvent<HTMLUListElement>.key: string
See the [DOM Level 3 Events spec](https://www.w3.org/TR/uievents-key/#named-key-attribute-values). for possible values
key
) {
case "ArrowDown": event: React.KeyboardEvent<HTMLUListElement>event.React.BaseSyntheticEvent<KeyboardEvent, EventTarget & HTMLUListElement, EventTarget>.preventDefault(): voidpreventDefault(); if (const currentItems: string[]currentItems.Array<string>.length: number
Gets or sets the length of the array. This is a number one higher than the highest index in the array.
length
> 0) {
const const nextIndex: numbernextIndex = const currentItemIndex: number | nullcurrentItemIndex === null ? 0 : (const currentItemIndex: numbercurrentItemIndex + 1) % const currentItems: string[]currentItems.Array<string>.length: number
Gets or sets the length of the array. This is a number one higher than the highest index in the array.
length
;
const setFocusedItemIndex: (value: React.SetStateAction<number | null>) => voidsetFocusedItemIndex(const nextIndex: numbernextIndex); const announce: (message: string) => voidannounce(const currentItems: string[]currentItems[const nextIndex: numbernextIndex]); } break; case "ArrowUp": event: React.KeyboardEvent<HTMLUListElement>event.React.BaseSyntheticEvent<KeyboardEvent, EventTarget & HTMLUListElement, EventTarget>.preventDefault(): voidpreventDefault(); if (const currentItems: string[]currentItems.Array<string>.length: number
Gets or sets the length of the array. This is a number one higher than the highest index in the array.
length
> 0) {
const const prevIndex: numberprevIndex = const currentItemIndex: number | nullcurrentItemIndex === null ? const currentItems: string[]currentItems.Array<string>.length: number
Gets or sets the length of the array. This is a number one higher than the highest index in the array.
length
- 1
: (const currentItemIndex: numbercurrentItemIndex - 1 + const currentItems: string[]currentItems.Array<string>.length: number
Gets or sets the length of the array. This is a number one higher than the highest index in the array.
length
) %
const currentItems: string[]currentItems.Array<string>.length: number
Gets or sets the length of the array. This is a number one higher than the highest index in the array.
length
;
const setFocusedItemIndex: (value: React.SetStateAction<number | null>) => voidsetFocusedItemIndex(const prevIndex: numberprevIndex); const announce: (message: string) => voidannounce(const currentItems: string[]currentItems[const prevIndex: numberprevIndex]); } break; case " ": // Spacebar event: React.KeyboardEvent<HTMLUListElement>event.React.BaseSyntheticEvent<KeyboardEvent, EventTarget & HTMLUListElement, EventTarget>.preventDefault(): voidpreventDefault(); if ( const currentItemIndex: number | nullcurrentItemIndex !== null && const currentItemIndex: numbercurrentItemIndex >= 0 && const currentItemIndex: numbercurrentItemIndex < const currentItems: string[]currentItems.Array<string>.length: number
Gets or sets the length of the array. This is a number one higher than the highest index in the array.
length
) { const const currentItemValue: stringcurrentItemValue = const currentItems: string[]currentItems[const currentItemIndex: numbercurrentItemIndex]; if ( const selectedItem: SelectedItem | nullselectedItem?.SelectedItem.listIndex: 0 | 1 | undefinedlistIndex === listIndex: 0 | 1listIndex && const selectedItem: SelectedItemselectedItem?.SelectedItem.itemIndex: numberitemIndex === const currentItemIndex: numbercurrentItemIndex ) { const setSelectedItem: (value: React.SetStateAction<SelectedItem | null>) => voidsetSelectedItem(null); const announce: (message: string) => voidannounce(`${const currentItemValue: stringcurrentItemValue} deselected.`); } else { const setSelectedItem: (value: React.SetStateAction<SelectedItem | null>) => voidsetSelectedItem({ SelectedItem.listIndex: 0 | 1listIndex, SelectedItem.itemIndex: numberitemIndex: const currentItemIndex: numbercurrentItemIndex, SelectedItem.value: stringvalue: const currentItemValue: stringcurrentItemValue, }); const announce: (message: string) => voidannounce( `${const currentItemValue: stringcurrentItemValue} selected. Use arrow keys to choose drop position, then press Enter.` ); } } break; case "Enter": event: React.KeyboardEvent<HTMLUListElement>event.React.BaseSyntheticEvent<KeyboardEvent, EventTarget & HTMLUListElement, EventTarget>.preventDefault(): voidpreventDefault(); if ( const selectedItem: SelectedItem | nullselectedItem && const currentItemIndex: number | nullcurrentItemIndex !== null && const currentItemIndex: numbercurrentItemIndex >= 0 && const currentItemIndex: numbercurrentItemIndex < const currentItems: string[]currentItems.Array<string>.length: number
Gets or sets the length of the array. This is a number one higher than the highest index in the array.
length
) { const { SelectedItem.listIndex: 0 | 1listIndex: const sourceListIndex: 0 | 1sourceListIndex, SelectedItem.itemIndex: numberitemIndex: const sourceItemIndex: numbersourceItemIndex, SelectedItem.value: stringvalue: const itemValue: stringitemValue, } = const selectedItem: SelectedItemselectedItem; const const targetListIndex: 0 | 1targetListIndex = listIndex: 0 | 1listIndex; const const targetItemIndex: numbertargetItemIndex = const currentItemIndex: numbercurrentItemIndex; if ( const sourceListIndex: 0 | 1sourceListIndex === const targetListIndex: 0 | 1targetListIndex && const sourceItemIndex: numbersourceItemIndex === const targetItemIndex: numbertargetItemIndex ) { const announce: (message: string) => voidannounce(`Keyboard: Cannot drop ${const itemValue: stringitemValue} onto itself.`); const setSelectedItem: (value: React.SetStateAction<SelectedItem | null>) => voidsetSelectedItem(null); break; } const const sourceItemsArray: string[]sourceItemsArray = const sourceListIndex: 0 | 1sourceListIndex === 0 ? const items1: string[]items1 : const items2: string[]items2; const const setSourceItems: React.Dispatch<React.SetStateAction<string[]>>setSourceItems = const sourceListIndex: 0 | 1sourceListIndex === 0 ? const setItems1: React.Dispatch<React.SetStateAction<string[]>>setItems1 : const setItems2: React.Dispatch<React.SetStateAction<string[]>>setItems2; const const targetItemsArray: string[]targetItemsArray = const targetListIndex: 0 | 1targetListIndex === 0 ? const items1: string[]items1 : const items2: string[]items2; const const setTargetItems: React.Dispatch<React.SetStateAction<string[]>>setTargetItems = const targetListIndex: 0 | 1targetListIndex === 0 ? const setItems1: React.Dispatch<React.SetStateAction<string[]>>setItems1 : const setItems2: React.Dispatch<React.SetStateAction<string[]>>setItems2; const const newSourceItems: string[]newSourceItems = [...const sourceItemsArray: string[]sourceItemsArray]; const newSourceItems: string[]newSourceItems.Array<string>.splice(start: number, deleteCount?: number): string[] (+1 overload)
Removes elements from an array and, if necessary, inserts new elements in their place, returning the deleted elements.
@paramstart The zero-based location in the array from which to start removing elements.@paramdeleteCount The number of elements to remove.@returnsAn array containing the elements that were deleted.
splice
(const sourceItemIndex: numbersourceItemIndex, 1);
const const newTargetItems: string[]newTargetItems = const sourceListIndex: 0 | 1sourceListIndex === const targetListIndex: 0 | 1targetListIndex ? const newSourceItems: string[]newSourceItems : [...const targetItemsArray: string[]targetItemsArray]; let let effectiveTargetIndex: numbereffectiveTargetIndex = const targetItemIndex: numbertargetItemIndex; if (const sourceListIndex: 0 | 1sourceListIndex === const targetListIndex: 0 | 1targetListIndex) { if (const sourceItemIndex: numbersourceItemIndex < const targetItemIndex: numbertargetItemIndex) { let effectiveTargetIndex: numbereffectiveTargetIndex = const targetItemIndex: numbertargetItemIndex - 1; } else { let effectiveTargetIndex: numbereffectiveTargetIndex = const targetItemIndex: numbertargetItemIndex; } } else { let effectiveTargetIndex: numbereffectiveTargetIndex = const targetItemIndex: numbertargetItemIndex; } let effectiveTargetIndex: numbereffectiveTargetIndex = var Math: Math
An intrinsic object that provides basic mathematics functionality and constants.
Math
.Math.max(...values: number[]): number
Returns the larger of a set of supplied numeric expressions.
@paramvalues Numeric expressions to be evaluated.
max
(
0, var Math: Math
An intrinsic object that provides basic mathematics functionality and constants.
Math
.Math.min(...values: number[]): number
Returns the smaller of a set of supplied numeric expressions.
@paramvalues Numeric expressions to be evaluated.
min
(let effectiveTargetIndex: numbereffectiveTargetIndex, const newTargetItems: string[]newTargetItems.Array<string>.length: number
Gets or sets the length of the array. This is a number one higher than the highest index in the array.
length
)
); const newTargetItems: string[]newTargetItems.Array<string>.splice(start: number, deleteCount: number, ...items: string[]): string[] (+1 overload)
Removes elements from an array and, if necessary, inserts new elements in their place, returning the deleted elements.
@paramstart The zero-based location in the array from which to start removing elements.@paramdeleteCount The number of elements to remove.@paramitems Elements to insert into the array in place of the deleted elements.@returnsAn array containing the elements that were deleted.
splice
(let effectiveTargetIndex: numbereffectiveTargetIndex, 0, const itemValue: stringitemValue);
// Update state using the hook's setters const setSourceItems: (value: React.SetStateAction<string[]>) => voidsetSourceItems(const newSourceItems: string[]newSourceItems); if (const sourceListIndex: 0 | 1sourceListIndex !== const targetListIndex: 0 | 1targetListIndex) { const setTargetItems: (value: React.SetStateAction<string[]>) => voidsetTargetItems(const newTargetItems: string[]newTargetItems); } // If same list, setSourceItems has updated the array const announce: (message: string) => voidannounce( `Keyboard: Moved ${const itemValue: stringitemValue} to position ${ let effectiveTargetIndex: numbereffectiveTargetIndex + 1 } in List ${const targetListIndex: 0 | 1targetListIndex + 1}.` ); const setSelectedItem: (value: React.SetStateAction<SelectedItem | null>) => voidsetSelectedItem(null); const setFocusedItemIndex: (value: React.SetStateAction<number | null>) => voidsetFocusedItemIndex(let effectiveTargetIndex: numbereffectiveTargetIndex); const setFocusedListIndex: (value: React.SetStateAction<0 | 1 | null>) => voidsetFocusedListIndex(const targetListIndex: 0 | 1targetListIndex); } break; case "Escape": event: React.KeyboardEvent<HTMLUListElement>event.React.BaseSyntheticEvent<KeyboardEvent, EventTarget & HTMLUListElement, EventTarget>.preventDefault(): voidpreventDefault(); if (const selectedItem: SelectedItem | nullselectedItem) { const announce: (message: string) => voidannounce(`Selection cancelled for ${const selectedItem: SelectedItemselectedItem.SelectedItem.value: stringvalue}.`); const setSelectedItem: (value: React.SetStateAction<SelectedItem | null>) => voidsetSelectedItem(null); } else { const announce: (message: string) => voidannounce("Escape pressed. No item selected."); (event: React.KeyboardEvent<HTMLUListElement>event.React.BaseSyntheticEvent<KeyboardEvent, EventTarget & HTMLUListElement, EventTarget>.target: EventTargettarget as HTMLElement).HTMLOrSVGElement.blur(): void
[MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLElement/blur)
blur
();
const setFocusedListIndex: (value: React.SetStateAction<0 | 1 | null>) => voidsetFocusedListIndex(null); const setFocusedItemIndex: (value: React.SetStateAction<number | null>) => voidsetFocusedItemIndex(null); } break; default: return; } }, [ const focusedListIndex: 0 | 1 | nullfocusedListIndex, const focusedItemIndex: number | nullfocusedItemIndex, const selectedItem: SelectedItem | nullselectedItem, const items1: string[]items1, const items2: string[]items2, const setItems1: React.Dispatch<React.SetStateAction<string[]>>setItems1, const setItems2: React.Dispatch<React.SetStateAction<string[]>>setItems2, const announce: (message: string) => voidannounce, ] ); return ( // Using a standard div wrapper instead of DemoContainer <JSX.IntrinsicElements.div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>div React.HTMLAttributes<HTMLDivElement>.className?: string | undefinedclassName="container p-4 border-4 border-blue-300"> <JSX.IntrinsicElements.h1: React.DetailedHTMLProps<React.HTMLAttributes<HTMLHeadingElement>, HTMLHeadingElement>h1 React.HTMLAttributes<T>.className?: string | undefinedclassName="text-xl font-bold mb-4">React Accessibility Demo</JSX.IntrinsicElements.h1: React.DetailedHTMLProps<React.HTMLAttributes<HTMLHeadingElement>, HTMLHeadingElement>h1> <JSX.IntrinsicElements.div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>div React.HTMLAttributes<HTMLDivElement>.className?: string | undefinedclassName="accessibility-demo"> <JSX.IntrinsicElements.div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>div React.RefAttributes<HTMLDivElement>.ref?: React.LegacyRef<HTMLDivElement> | undefined
Allows getting a ref to the component instance. Once the component unmounts, React will set `ref.current` to `null` (or call the ref with `null` if you passed a callback ref).
@see{@link https://react.dev/learn/referencing-values-with-refs#refs-and-the-dom React Docs}
ref
={const liveRegionRef: React.RefObject<HTMLDivElement>liveRegionRef} React.AriaAttributes["aria-live"]?: "polite" | "off" | "assertive" | undefined
Indicates that an element will be updated, and describes the types of updates the user agents, assistive technologies, and user can expect from the live region.
aria-live
="polite" React.HTMLAttributes<HTMLDivElement>.className?: string | undefinedclassName="sr-only">
{const liveMessage: stringliveMessage} </JSX.IntrinsicElements.div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>div> <JSX.IntrinsicElements.div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>div React.HTMLAttributes<HTMLDivElement>.className?: string | undefinedclassName="lists-container"> {/* List 1 */} <JSX.IntrinsicElements.div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>div React.HTMLAttributes<HTMLDivElement>.className?: string | undefinedclassName="list-wrapper"> <JSX.IntrinsicElements.h2: React.DetailedHTMLProps<React.HTMLAttributes<HTMLHeadingElement>, HTMLHeadingElement>h2 React.HTMLAttributes<HTMLHeadingElement>.id?: string | undefinedid="list1-item-heading">List 1</JSX.IntrinsicElements.h2: React.DetailedHTMLProps<React.HTMLAttributes<HTMLHeadingElement>, HTMLHeadingElement>h2> <JSX.IntrinsicElements.ul: React.DetailedHTMLProps<React.HTMLAttributes<HTMLUListElement>, HTMLUListElement>ul React.RefAttributes<HTMLUListElement>.ref?: React.LegacyRef<HTMLUListElement> | undefined
Allows getting a ref to the component instance. Once the component unmounts, React will set `ref.current` to `null` (or call the ref with `null` if you passed a callback ref).
@see{@link https://react.dev/learn/referencing-values-with-refs#refs-and-the-dom React Docs}
ref
={const list1Ref: React.RefObject<HTMLUListElement>list1Ref} // Assign ref from hook
React.HTMLAttributes<T>.className?: string | undefinedclassName="list" React.HTMLAttributes<HTMLUListElement>.tabIndex?: number | undefinedtabIndex={0} React.HTMLAttributes<HTMLUListElement>.role?: React.AriaRole | undefinedrole="listbox" React.AriaAttributes["aria-labelledby"]?: string | undefined
Identifies the element (or elements) that labels the current element.
@seearia-describedby.
aria-labelledby
="list1-item-heading"
React.AriaAttributes["aria-activedescendant"]?: string | undefined
Identifies the currently active element when DOM focus is on a composite widget, textbox, group, or application.
aria-activedescendant
={
const focusedListIndex: 0 | 1 | nullfocusedListIndex === 0 ? const focusedItemId: string | undefinedfocusedItemId : var undefinedundefined } React.DOMAttributes<HTMLUListElement>.onFocus?: React.FocusEventHandler<HTMLUListElement> | undefinedonFocus={() => const handleListFocus: (listIndex: 0 | 1) => voidhandleListFocus(0)} React.DOMAttributes<HTMLUListElement>.onBlur?: React.FocusEventHandler<HTMLUListElement> | undefinedonBlur={const handleListBlur: () => voidhandleListBlur} React.DOMAttributes<HTMLUListElement>.onKeyDown?: React.KeyboardEventHandler<HTMLUListElement> | undefinedonKeyDown={(e: React.KeyboardEvent<HTMLUListElement>e) => const handleListKeydown: (event: React.KeyboardEvent<HTMLUListElement>, listIndex: 0 | 1) => voidhandleListKeydown(e: React.KeyboardEvent<HTMLUListElement>e, 0)} > {const items1: string[]items1.Array<string>.length: number
Gets or sets the length of the array. This is a number one higher than the highest index in the array.
length
> 0 ? (
const items1: string[]items1.Array<string>.map<React.JSX.Element>(callbackfn: (value: string, index: number, array: string[]) => React.JSX.Element, thisArg?: any): React.JSX.Element[]
Calls a defined callback function on each element of an array, and returns an array that contains the results.
@paramcallbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.@paramthisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
map
((item: stringitem, index: numberindex) => {
const const isFocused: booleanisFocused = const focusedListIndex: 0 | 1 | nullfocusedListIndex === 0 && const focusedItemIndex: number | nullfocusedItemIndex === index: numberindex; const const isSelected: booleanisSelected = const selectedItem: SelectedItem | nullselectedItem?.SelectedItem.listIndex: 0 | 1 | undefinedlistIndex === 0 && const selectedItem: SelectedItemselectedItem?.SelectedItem.itemIndex: numberitemIndex === index: numberindex; const const itemId: stringitemId = `list1-item-${item: stringitem}`; return ( <JSX.IntrinsicElements.li: React.DetailedHTMLProps<React.LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>li React.Attributes.key?: React.Key | null | undefinedkey={const itemId: stringitemId} React.HTMLAttributes<T>.id?: string | undefinedid={const itemId: stringitemId} React.HTMLAttributes<T>.className?: string | undefinedclassName={`item ${const isFocused: booleanisFocused ? "item-focused" : ""} ${ const isSelected: booleanisSelected ? "item-selected" : "" }`} React.HTMLAttributes<T>.role?: React.AriaRole | undefinedrole="option" React.AriaAttributes["aria-selected"]?: Booleanish | undefined
Indicates the current "selected" state of various widgets.
@seearia-checked@seearia-pressed.
aria-selected
={const isFocused: booleanisFocused}
React.HTMLAttributes<T>.tabIndex?: number | undefinedtabIndex={-1} > {item: stringitem} </JSX.IntrinsicElements.li: React.DetailedHTMLProps<React.LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>li> ); }) ) : ( <JSX.IntrinsicElements.li: React.DetailedHTMLProps<React.LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>li React.HTMLAttributes<T>.className?: string | undefinedclassName="empty-list-message">Empty</JSX.IntrinsicElements.li: React.DetailedHTMLProps<React.LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>li> )} </JSX.IntrinsicElements.ul: React.DetailedHTMLProps<React.HTMLAttributes<HTMLUListElement>, HTMLUListElement>ul> </JSX.IntrinsicElements.div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>div> {/* List 2 */} <JSX.IntrinsicElements.div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>div React.HTMLAttributes<HTMLDivElement>.className?: string | undefinedclassName="list-wrapper"> <JSX.IntrinsicElements.h2: React.DetailedHTMLProps<React.HTMLAttributes<HTMLHeadingElement>, HTMLHeadingElement>h2 React.HTMLAttributes<HTMLHeadingElement>.id?: string | undefinedid="list2-item-heading">List 2</JSX.IntrinsicElements.h2: React.DetailedHTMLProps<React.HTMLAttributes<HTMLHeadingElement>, HTMLHeadingElement>h2> <JSX.IntrinsicElements.ul: React.DetailedHTMLProps<React.HTMLAttributes<HTMLUListElement>, HTMLUListElement>ul React.RefAttributes<HTMLUListElement>.ref?: React.LegacyRef<HTMLUListElement> | undefined
Allows getting a ref to the component instance. Once the component unmounts, React will set `ref.current` to `null` (or call the ref with `null` if you passed a callback ref).
@see{@link https://react.dev/learn/referencing-values-with-refs#refs-and-the-dom React Docs}
ref
={const list2Ref: React.RefObject<HTMLUListElement>list2Ref} // Assign ref from hook
React.HTMLAttributes<T>.className?: string | undefinedclassName="list" React.HTMLAttributes<HTMLUListElement>.tabIndex?: number | undefinedtabIndex={0} React.HTMLAttributes<HTMLUListElement>.role?: React.AriaRole | undefinedrole="listbox" React.AriaAttributes["aria-labelledby"]?: string | undefined
Identifies the element (or elements) that labels the current element.
@seearia-describedby.
aria-labelledby
="list2-item-heading"
React.AriaAttributes["aria-activedescendant"]?: string | undefined
Identifies the currently active element when DOM focus is on a composite widget, textbox, group, or application.
aria-activedescendant
={
const focusedListIndex: 0 | 1 | nullfocusedListIndex === 1 ? const focusedItemId: string | undefinedfocusedItemId : var undefinedundefined } React.DOMAttributes<HTMLUListElement>.onFocus?: React.FocusEventHandler<HTMLUListElement> | undefinedonFocus={() => const handleListFocus: (listIndex: 0 | 1) => voidhandleListFocus(1)} React.DOMAttributes<HTMLUListElement>.onBlur?: React.FocusEventHandler<HTMLUListElement> | undefinedonBlur={const handleListBlur: () => voidhandleListBlur} React.DOMAttributes<HTMLUListElement>.onKeyDown?: React.KeyboardEventHandler<HTMLUListElement> | undefinedonKeyDown={(e: React.KeyboardEvent<HTMLUListElement>e) => const handleListKeydown: (event: React.KeyboardEvent<HTMLUListElement>, listIndex: 0 | 1) => voidhandleListKeydown(e: React.KeyboardEvent<HTMLUListElement>e, 1)} > {const items2: string[]items2.Array<string>.length: number
Gets or sets the length of the array. This is a number one higher than the highest index in the array.
length
> 0 ? (
const items2: string[]items2.Array<string>.map<React.JSX.Element>(callbackfn: (value: string, index: number, array: string[]) => React.JSX.Element, thisArg?: any): React.JSX.Element[]
Calls a defined callback function on each element of an array, and returns an array that contains the results.
@paramcallbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.@paramthisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
map
((item: stringitem, index: numberindex) => {
const const isFocused: booleanisFocused = const focusedListIndex: 0 | 1 | nullfocusedListIndex === 1 && const focusedItemIndex: number | nullfocusedItemIndex === index: numberindex; const const isSelected: booleanisSelected = const selectedItem: SelectedItem | nullselectedItem?.SelectedItem.listIndex: 0 | 1 | undefinedlistIndex === 1 && const selectedItem: SelectedItemselectedItem?.SelectedItem.itemIndex: numberitemIndex === index: numberindex; const const itemId: stringitemId = `list2-item-${item: stringitem}`; return ( <JSX.IntrinsicElements.li: React.DetailedHTMLProps<React.LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>li React.Attributes.key?: React.Key | null | undefinedkey={const itemId: stringitemId} React.HTMLAttributes<T>.id?: string | undefinedid={const itemId: stringitemId} React.HTMLAttributes<T>.className?: string | undefinedclassName={`item ${const isFocused: booleanisFocused ? "item-focused" : ""} ${ const isSelected: booleanisSelected ? "item-selected" : "" }`} React.HTMLAttributes<T>.role?: React.AriaRole | undefinedrole="option" React.AriaAttributes["aria-selected"]?: Booleanish | undefined
Indicates the current "selected" state of various widgets.
@seearia-checked@seearia-pressed.
aria-selected
={const isFocused: booleanisFocused}
React.HTMLAttributes<T>.tabIndex?: number | undefinedtabIndex={-1} > {item: stringitem} </JSX.IntrinsicElements.li: React.DetailedHTMLProps<React.LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>li> ); }) ) : ( <JSX.IntrinsicElements.li: React.DetailedHTMLProps<React.LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>li React.HTMLAttributes<T>.className?: string | undefinedclassName="empty-list-message">Empty</JSX.IntrinsicElements.li: React.DetailedHTMLProps<React.LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>li> )} </JSX.IntrinsicElements.ul: React.DetailedHTMLProps<React.HTMLAttributes<HTMLUListElement>, HTMLUListElement>ul> </JSX.IntrinsicElements.div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>div> </JSX.IntrinsicElements.div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>div> <JSX.IntrinsicElements.div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>div React.HTMLAttributes<HTMLDivElement>.className?: string | undefinedclassName="instructions"> <JSX.IntrinsicElements.h3: React.DetailedHTMLProps<React.HTMLAttributes<HTMLHeadingElement>, HTMLHeadingElement>h3>Keyboard Instructions</JSX.IntrinsicElements.h3: React.DetailedHTMLProps<React.HTMLAttributes<HTMLHeadingElement>, HTMLHeadingElement>h3> <JSX.IntrinsicElements.ul: React.DetailedHTMLProps<React.HTMLAttributes<HTMLUListElement>, HTMLUListElement>ul> <JSX.IntrinsicElements.li: React.DetailedHTMLProps<React.LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>li> Use <JSX.IntrinsicElements.kbd: React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement>, HTMLElement>kbd>Tab</JSX.IntrinsicElements.kbd: React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement>, HTMLElement>kbd> or <JSX.IntrinsicElements.kbd: React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement>, HTMLElement>kbd>Shift+Tab</JSX.IntrinsicElements.kbd: React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement>, HTMLElement>kbd> to focus a list. </JSX.IntrinsicElements.li: React.DetailedHTMLProps<React.LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>li> <JSX.IntrinsicElements.li: React.DetailedHTMLProps<React.LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>li> Use <JSX.IntrinsicElements.kbd: React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement>, HTMLElement>kbd>↑</JSX.IntrinsicElements.kbd: React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement>, HTMLElement>kbd> / <JSX.IntrinsicElements.kbd: React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement>, HTMLElement>kbd>↓</JSX.IntrinsicElements.kbd: React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement>, HTMLElement>kbd> arrows to navigate items within the focused list. </JSX.IntrinsicElements.li: React.DetailedHTMLProps<React.LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>li> <JSX.IntrinsicElements.li: React.DetailedHTMLProps<React.LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>li> Press <JSX.IntrinsicElements.kbd: React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement>, HTMLElement>kbd>Spacebar</JSX.IntrinsicElements.kbd: React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement>, HTMLElement>kbd> to select/deselect the highlighted item for moving. </JSX.IntrinsicElements.li: React.DetailedHTMLProps<React.LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>li> <JSX.IntrinsicElements.li: React.DetailedHTMLProps<React.LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>li> With an item selected, use <JSX.IntrinsicElements.kbd: React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement>, HTMLElement>kbd>↑</JSX.IntrinsicElements.kbd: React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement>, HTMLElement>kbd> / <JSX.IntrinsicElements.kbd: React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement>, HTMLElement>kbd>↓</JSX.IntrinsicElements.kbd: React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement>, HTMLElement>kbd> (within the same or another focused list) to choose the drop position. </JSX.IntrinsicElements.li: React.DetailedHTMLProps<React.LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>li> <JSX.IntrinsicElements.li: React.DetailedHTMLProps<React.LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>li> Press <JSX.IntrinsicElements.kbd: React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement>, HTMLElement>kbd>Enter</JSX.IntrinsicElements.kbd: React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement>, HTMLElement>kbd> to drop the selected item at the highlighted position. </JSX.IntrinsicElements.li: React.DetailedHTMLProps<React.LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>li> <JSX.IntrinsicElements.li: React.DetailedHTMLProps<React.LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>li> Press <JSX.IntrinsicElements.kbd: React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement>, HTMLElement>kbd>Escape</JSX.IntrinsicElements.kbd: React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement>, HTMLElement>kbd> to cancel a selection or leave the list. </JSX.IntrinsicElements.li: React.DetailedHTMLProps<React.LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>li> </JSX.IntrinsicElements.ul: React.DetailedHTMLProps<React.HTMLAttributes<HTMLUListElement>, HTMLUListElement>ul> </JSX.IntrinsicElements.div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>div> </JSX.IntrinsicElements.div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>div> {/* Styles assumed to be global or handled via CSS Modules/Tailwind etc. */} </JSX.IntrinsicElements.div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>div> ); }
<script setup lang="ts">
import { function ref<T>(value: T): [T] extends [Ref] ? IfAny<T, Ref<T>, T> : Ref<UnwrapRef<T>, UnwrapRef<T> | T> (+1 overload)
Takes an inner value and returns a reactive and mutable ref object, which has a single property `.value` that points to the inner value.
@paramvalue - The object to wrap in the ref.@see{@link https://vuejs.org/api/reactivity-core.html#ref}
ref
,
const computed: {
    <T>(getter: ComputedGetter<T>, debugOptions?: DebuggerOptions): ComputedRef<T>;
    <T, S = T>(options: WritableComputedOptions<T, S>, debugOptions?: DebuggerOptions): WritableComputedRef<T, S>;
}
computed
, function nextTick<T = void, R = void>(this: T, fn?: (this: T) => R): Promise<Awaited<R>>nextTick } from "vue";
import { function useDragAndDrop<T>(initialValues: T[], options?: Partial<VueParentConfig<T>>): [Ref<HTMLElement | undefined>, Ref<T[]>, (config: Partial<VueParentConfig<T>>) => void]
Creates a new instance of drag and drop and returns the parent element and a ref of the values to use in your template.
@paraminitialValues - The initial values of the parent element.@returnsThe parent element and values for drag and drop.
useDragAndDrop
} from "@formkit/drag-and-drop/vue";
// Refs for ARIA Live region const const liveMessage: Ref<string, string>liveMessage = ref<string>(value: string): Ref<string, string> (+1 overload)
Takes an inner value and returns a reactive and mutable ref object, which has a single property `.value` that points to the inner value.
@paramvalue - The object to wrap in the ref.@see{@link https://vuejs.org/api/reactivity-core.html#ref}
ref
("");
const const liveRegion: Ref<HTMLDivElement | null, HTMLDivElement | null>liveRegion = ref<HTMLDivElement | null>(value: HTMLDivElement | null): Ref<HTMLDivElement | null, HTMLDivElement | null> (+1 overload)
Takes an inner value and returns a reactive and mutable ref object, which has a single property `.value` that points to the inner value.
@paramvalue - The object to wrap in the ref.@see{@link https://vuejs.org/api/reactivity-core.html#ref}
ref
<HTMLDivElement | null>(null);
// Function to update the live region function function announce(message: string): voidannounce(message: stringmessage: string) { const liveMessage: Ref<string, string>liveMessage.Ref<string, string>.value: stringvalue = message: stringmessage; // Optional: Clear the message after a delay if needed // setTimeout(() => { liveMessage.value = ''; }, 5000); } // Initial data for the lists const const initialItems1: string[]initialItems1 = ["Apples", "Bananas", "Oranges", "Grapes"]; const const initialItems2: string[]initialItems2 = ["Milk", "Cheese", "Yogurt"]; // Setup drag and drop for List 1 const [const list1Node: Ref<HTMLElement | undefined, HTMLElement | undefined>list1Node, const items1: Ref<string[], string[]>items1] = useDragAndDrop<string>(initialValues: string[], options?: Partial<Partial<ParentConfig<string>>> | undefined): [Ref<HTMLElement | undefined, HTMLElement | undefined>, Ref<...>, (config: Partial<...>) => void]
Creates a new instance of drag and drop and returns the parent element and a ref of the values to use in your template.
@paraminitialValues - The initial values of the parent element.@returnsThe parent element and values for drag and drop.
useDragAndDrop
(const initialItems1: string[]initialItems1, {
group?: string | undefined
The group that the parent belongs to. This is used for allowing multiple parents to transfer nodes between each other.
group
: "accessibleList",
onDragstart?: DragstartEvent | undefined
Fired when a drag is started, whether native drag or synthetic
onDragstart
: (state: DragstartEventData<T>state) => {
function announce(message: string): voidannounce(`Drag started for ${state: DragstartEventData<T>state.DragstartEventData<T>.draggedNode: NodeRecord<T>draggedNode.NodeRecord<T>.data: NodeData<T>data.NodeData<T>.value: T
The value of the node.
value
}.`);
}, onSort?: SortEvent | undefined
Callback function for when a sort operation is performed.
onSort
: (event: SortEventData<T>event) => {
function announce(message: string): voidannounce( `Sorted ${event: SortEventData<T>event.SortEventData<T>.draggedNodes: NodeRecord<T>[]draggedNodes[0].NodeRecord<T>.data: NodeData<T>data.NodeData<T>.value: T
The value of the node.
value
} in List 1 to position ${
event: SortEventData<T>event.SortEventData<T>.position: numberposition + 1 }.` ); }, onTransfer?: TransferEvent | undefined
Callback function for when a transfer operation is performed.
onTransfer
: (event: TransferEventData<T>event) => {
function announce(message: string): voidannounce( `Transferred ${event: TransferEventData<T>event.TransferEventData<T>.draggedNodes: NodeRecord<T>[]draggedNodes[0].NodeRecord<T>.data: NodeData<T>data.NodeData<T>.value: T
The value of the node.
value
} from List ${
event: TransferEventData<T>event.TransferEventData<T>.sourceParent: ParentRecord<T>sourceParent.ParentRecord<T>.el: HTMLElementel === const list1Node: Ref<HTMLElement | undefined, HTMLElement | undefined>list1Node.Ref<HTMLElement | undefined, HTMLElement | undefined>.value: HTMLElement | undefinedvalue ? 1 : 2 } to List 1 at position ${event: TransferEventData<T>event.TransferEventData<T>.targetIndex: numbertargetIndex + 1}.` ); }, onDragend?: DragendEvent | undefined
Fired when a drag is ended, whether native drag or synthetic
onDragend
: (state: DragendEventData<T>state) => {
function announce(message: string): voidannounce(`Drag ended for ${state: DragendEventData<T>state.DragendEventData<T>.draggedNode: NodeRecord<T>draggedNode.NodeRecord<T>.data: NodeData<T>data.NodeData<T>.value: T
The value of the node.
value
}.`);
}, }); // Setup drag and drop for List 2 const [const list2Node: Ref<HTMLElement | undefined, HTMLElement | undefined>list2Node, const items2: Ref<string[], string[]>items2] = useDragAndDrop<string>(initialValues: string[], options?: Partial<Partial<ParentConfig<string>>> | undefined): [Ref<HTMLElement | undefined, HTMLElement | undefined>, Ref<...>, (config: Partial<...>) => void]
Creates a new instance of drag and drop and returns the parent element and a ref of the values to use in your template.
@paraminitialValues - The initial values of the parent element.@returnsThe parent element and values for drag and drop.
useDragAndDrop
(const initialItems2: string[]initialItems2, {
group?: string | undefined
The group that the parent belongs to. This is used for allowing multiple parents to transfer nodes between each other.
group
: "accessibleList",
onDragstart?: DragstartEvent | undefined
Fired when a drag is started, whether native drag or synthetic
onDragstart
: (state: DragstartEventData<T>state) => {
function announce(message: string): voidannounce(`Drag started for ${state: DragstartEventData<T>state.DragstartEventData<T>.draggedNode: NodeRecord<T>draggedNode.NodeRecord<T>.data: NodeData<T>data.NodeData<T>.value: T
The value of the node.
value
}.`);
}, onSort?: SortEvent | undefined
Callback function for when a sort operation is performed.
onSort
: (event: SortEventData<T>event) => {
function announce(message: string): voidannounce( `Sorted ${event: SortEventData<T>event.SortEventData<T>.draggedNodes: NodeRecord<T>[]draggedNodes[0].NodeRecord<T>.data: NodeData<T>data.NodeData<T>.value: T
The value of the node.
value
} in List 2 to position ${
event: SortEventData<T>event.SortEventData<T>.position: numberposition + 1 }.` ); }, onTransfer?: TransferEvent | undefined
Callback function for when a transfer operation is performed.
onTransfer
: (event: TransferEventData<T>event) => {
function announce(message: string): voidannounce( `Transferred ${event: TransferEventData<T>event.TransferEventData<T>.draggedNodes: NodeRecord<T>[]draggedNodes[0].NodeRecord<T>.data: NodeData<T>data.NodeData<T>.value: T
The value of the node.
value
} from List ${
event: TransferEventData<T>event.TransferEventData<T>.sourceParent: ParentRecord<T>sourceParent.ParentRecord<T>.el: HTMLElementel === const list1Node: Ref<HTMLElement | undefined, HTMLElement | undefined>list1Node.Ref<HTMLElement | undefined, HTMLElement | undefined>.value: HTMLElement | undefinedvalue ? 1 : 2 } to List 2 at position ${event: TransferEventData<T>event.TransferEventData<T>.targetIndex: numbertargetIndex + 1}.` ); }, onDragend?: DragendEvent | undefined
Fired when a drag is ended, whether native drag or synthetic
onDragend
: (state: DragendEventData<T>state) => {
function announce(message: string): voidannounce(`Drag ended for ${state: DragendEventData<T>state.DragendEventData<T>.draggedNode: NodeRecord<T>draggedNode.NodeRecord<T>.data: NodeData<T>data.NodeData<T>.value: T
The value of the node.
value
}.`);
}, }); // State for keyboard navigation const const focusedListIndex: Ref<0 | 1 | null, 0 | 1 | null>focusedListIndex = ref<0 | 1 | null>(value: 0 | 1 | null): Ref<0 | 1 | null, 0 | 1 | null> (+1 overload)
Takes an inner value and returns a reactive and mutable ref object, which has a single property `.value` that points to the inner value.
@paramvalue - The object to wrap in the ref.@see{@link https://vuejs.org/api/reactivity-core.html#ref}
ref
<0 | 1 | null>(null);
const const focusedItemIndex: Ref<number | null, number | null>focusedItemIndex = ref<number | null>(value: number | null): Ref<number | null, number | null> (+1 overload)
Takes an inner value and returns a reactive and mutable ref object, which has a single property `.value` that points to the inner value.
@paramvalue - The object to wrap in the ref.@see{@link https://vuejs.org/api/reactivity-core.html#ref}
ref
<number | null>(null); // Index within the focused list
const
const selectedItem: Ref<{
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
} | null, {
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
} | {
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
} | null>
selectedItem
=
ref<{
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
} | null>(value: {
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
} | null): Ref<{
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
} | null, {
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
} | ... 1 more ... | null> (+1 overload)
Takes an inner value and returns a reactive and mutable ref object, which has a single property `.value` that points to the inner value.
@paramvalue - The object to wrap in the ref.@see{@link https://vuejs.org/api/reactivity-core.html#ref}
ref
<{
listIndex: 0 | 1listIndex: 0 | 1; itemIndex: numberitemIndex: number; value: stringvalue: string; } | null>(null); const
const lists: ComputedRef<{
    node: Ref<HTMLElement | undefined, HTMLElement | undefined>;
    items: Ref<string[], string[]>;
    idPrefix: string;
}[]>
lists
=
computed<{
    node: Ref<HTMLElement | undefined, HTMLElement | undefined>;
    items: Ref<string[], string[]>;
    idPrefix: string;
}[]>(getter: ComputedGetter<{
    node: Ref<HTMLElement | undefined, HTMLElement | undefined>;
    items: Ref<string[], string[]>;
    idPrefix: string;
}[]>, debugOptions?: DebuggerOptions): ComputedRef<...> (+1 overload)
Takes a getter function and returns a readonly reactive ref object for the returned value from the getter. It can also take an object with get and set functions to create a writable ref object.
@example```js // Creating a readonly computed ref: const count = ref(1) const plusOne = computed(() => count.value + 1) console.log(plusOne.value) // 2 plusOne.value++ // error ``` ```js // Creating a writable computed ref: const count = ref(1) const plusOne = computed({ get: () => count.value + 1, set: (val) => { count.value = val - 1 } }) plusOne.value = 1 console.log(count.value) // 0 ```@paramgetter - Function that produces the next value.@paramdebugOptions - For debugging. See {@link https://vuejs.org/guide/extras/reactivity-in-depth.html#computed-debugging}.@see{@link https://vuejs.org/api/reactivity-core.html#computed}
computed
(() => [
{ node: Ref<HTMLElement | undefined, HTMLElement | undefined>node: const list1Node: Ref<HTMLElement | undefined, HTMLElement | undefined>list1Node, items: Ref<string[], string[]>items: const items1: Ref<string[], string[]>items1, idPrefix: stringidPrefix: "list1-item" }, { node: Ref<HTMLElement | undefined, HTMLElement | undefined>node: const list2Node: Ref<HTMLElement | undefined, HTMLElement | undefined>list2Node, items: Ref<string[], string[]>items: const items2: Ref<string[], string[]>items2, idPrefix: stringidPrefix: "list2-item" }, ]); const const focusedItemId: ComputedRef<string | undefined>focusedItemId = computed<string | undefined>(getter: ComputedGetter<string | undefined>, debugOptions?: DebuggerOptions): ComputedRef<string | undefined> (+1 overload)
Takes a getter function and returns a readonly reactive ref object for the returned value from the getter. It can also take an object with get and set functions to create a writable ref object.
@example```js // Creating a readonly computed ref: const count = ref(1) const plusOne = computed(() => count.value + 1) console.log(plusOne.value) // 2 plusOne.value++ // error ``` ```js // Creating a writable computed ref: const count = ref(1) const plusOne = computed({ get: () => count.value + 1, set: (val) => { count.value = val - 1 } }) plusOne.value = 1 console.log(count.value) // 0 ```@paramgetter - Function that produces the next value.@paramdebugOptions - For debugging. See {@link https://vuejs.org/guide/extras/reactivity-in-depth.html#computed-debugging}.@see{@link https://vuejs.org/api/reactivity-core.html#computed}
computed
(() => {
if (const focusedListIndex: Ref<0 | 1 | null, 0 | 1 | null>focusedListIndex.Ref<0 | 1 | null, 0 | 1 | null>.value: 0 | 1 | nullvalue !== null && const focusedItemIndex: Ref<number | null, number | null>focusedItemIndex.Ref<number | null, number | null>.value: number | nullvalue !== null) { const
const list: {
    node: Ref<HTMLElement | undefined, HTMLElement | undefined>;
    items: Ref<string[], string[]>;
    idPrefix: string;
}
list
=
const lists: ComputedRef<{
    node: Ref<HTMLElement | undefined, HTMLElement | undefined>;
    items: Ref<string[], string[]>;
    idPrefix: string;
}[]>
lists
.
ComputedRef<{ node: Ref<HTMLElement | undefined, HTMLElement | undefined>; items: Ref<string[], string[]>; idPrefix: string; }[]>.value: {
    node: Ref<HTMLElement | undefined, HTMLElement | undefined>;
    items: Ref<string[], string[]>;
    idPrefix: string;
}[]
value
[const focusedListIndex: Ref<0 | 1 | null, 0 | 1 | null>focusedListIndex.Ref<0 | 1 | null, 0 | 1 | null>.value: 0 | 1value];
if (
const list: {
    node: Ref<HTMLElement | undefined, HTMLElement | undefined>;
    items: Ref<string[], string[]>;
    idPrefix: string;
}
list
&& const focusedItemIndex: Ref<number | null, number | null>focusedItemIndex.Ref<number | null, number | null>.value: numbervalue <
const list: {
    node: Ref<HTMLElement | undefined, HTMLElement | undefined>;
    items: Ref<string[], string[]>;
    idPrefix: string;
}
list
.items: Ref<string[], string[]>items.Ref<string[], string[]>.value: string[]value.Array<string>.length: number
Gets or sets the length of the array. This is a number one higher than the highest index in the array.
length
) {
return `${
const list: {
    node: Ref<HTMLElement | undefined, HTMLElement | undefined>;
    items: Ref<string[], string[]>;
    idPrefix: string;
}
list
.idPrefix: stringidPrefix}-${
const list: {
    node: Ref<HTMLElement | undefined, HTMLElement | undefined>;
    items: Ref<string[], string[]>;
    idPrefix: string;
}
list
.items: Ref<string[], string[]>items.Ref<string[], string[]>.value: string[]value[const focusedItemIndex: Ref<number | null, number | null>focusedItemIndex.Ref<number | null, number | null>.value: numbervalue]}`;
} } return var undefinedundefined; }); // Function to handle focus moving to a list function function handleListFocus(listIndex: 0 | 1): voidhandleListFocus(listIndex: 0 | 1listIndex: 0 | 1) { const focusedListIndex: Ref<0 | 1 | null, 0 | 1 | null>focusedListIndex.Ref<0 | 1 | null, 0 | 1 | null>.value: 0 | 1 | nullvalue = listIndex: 0 | 1listIndex; // Optionally focus the first item if none is focused if ( const focusedItemIndex: Ref<number | null, number | null>focusedItemIndex.Ref<number | null, number | null>.value: number | nullvalue === null &&
const lists: ComputedRef<{
    node: Ref<HTMLElement | undefined, HTMLElement | undefined>;
    items: Ref<string[], string[]>;
    idPrefix: string;
}[]>
lists
.
ComputedRef<{ node: Ref<HTMLElement | undefined, HTMLElement | undefined>; items: Ref<string[], string[]>; idPrefix: string; }[]>.value: {
    node: Ref<HTMLElement | undefined, HTMLElement | undefined>;
    items: Ref<string[], string[]>;
    idPrefix: string;
}[]
value
[listIndex: 0 | 1listIndex].items: Ref<string[], string[]>items.Ref<string[], string[]>.value: string[]value.Array<string>.length: number
Gets or sets the length of the array. This is a number one higher than the highest index in the array.
length
> 0
) { const focusedItemIndex: Ref<number | null, number | null>focusedItemIndex.Ref<number | null, number | null>.value: number | nullvalue = 0; } function announce(message: string): voidannounce( `List ${listIndex: 0 | 1listIndex + 1} focused. Use up and down arrows to navigate items.` ); } // Function to handle blur from a list function function handleListBlur(): voidhandleListBlur() { // Keep focus state if moving between related elements or temporarily losing focus // For simplicity now, we clear it. More robust logic might be needed. // focusedListIndex.value = null; // focusedItemIndex.value = null; } // Function to handle keydown events on lists async function function handleListKeydown(event: KeyboardEvent, listIndex: 0 | 1): Promise<void>handleListKeydown(event: KeyboardEventevent: KeyboardEvent, listIndex: 0 | 1listIndex: 0 | 1) { if (const focusedListIndex: Ref<0 | 1 | null, 0 | 1 | null>focusedListIndex.Ref<0 | 1 | null, 0 | 1 | null>.value: 0 | 1 | nullvalue !== listIndex: 0 | 1listIndex) return; // Ignore if not the focused list const
const list: {
    node: Ref<HTMLElement | undefined, HTMLElement | undefined>;
    items: Ref<string[], string[]>;
    idPrefix: string;
}
list
=
const lists: ComputedRef<{
    node: Ref<HTMLElement | undefined, HTMLElement | undefined>;
    items: Ref<string[], string[]>;
    idPrefix: string;
}[]>
lists
.
ComputedRef<{ node: Ref<HTMLElement | undefined, HTMLElement | undefined>; items: Ref<string[], string[]>; idPrefix: string; }[]>.value: {
    node: Ref<HTMLElement | undefined, HTMLElement | undefined>;
    items: Ref<string[], string[]>;
    idPrefix: string;
}[]
value
[listIndex: 0 | 1listIndex];
const const items: string[]items =
const list: {
    node: Ref<HTMLElement | undefined, HTMLElement | undefined>;
    items: Ref<string[], string[]>;
    idPrefix: string;
}
list
.items: Ref<string[], string[]>items.Ref<string[], string[]>.value: string[]value;
const const currentItemIndex: number | nullcurrentItemIndex = const focusedItemIndex: Ref<number | null, number | null>focusedItemIndex.Ref<number | null, number | null>.value: number | nullvalue; switch (event: KeyboardEventevent.KeyboardEvent.key: string
[MDN Reference](https://developer.mozilla.org/docs/Web/API/KeyboardEvent/key)
key
) {
case "ArrowDown": event: KeyboardEventevent.Event.preventDefault(): void
If invoked when the cancelable attribute value is true, and while executing a listener for the event with passive set to false, signals to the operation that caused event to be dispatched that it needs to be canceled. [MDN Reference](https://developer.mozilla.org/docs/Web/API/Event/preventDefault)
preventDefault
();
if (const items: string[]items.Array<string>.length: number
Gets or sets the length of the array. This is a number one higher than the highest index in the array.
length
> 0) {
const const nextIndex: numbernextIndex = const currentItemIndex: number | nullcurrentItemIndex === null ? 0 : (const currentItemIndex: numbercurrentItemIndex + 1) % const items: string[]items.Array<string>.length: number
Gets or sets the length of the array. This is a number one higher than the highest index in the array.
length
;
const focusedItemIndex: Ref<number | null, number | null>focusedItemIndex.Ref<number | null, number | null>.value: number | nullvalue = const nextIndex: numbernextIndex; function announce(message: string): voidannounce(const items: string[]items[const nextIndex: numbernextIndex]); await nextTick<void, void>(this: void, fn?: ((this: void) => void) | undefined): Promise<void>nextTick(); // Ensure DOM updates before focusing // Optionally focus the element itself if not purely virtual // const el = document.getElementById(focusedItemId.value!); // el?.focus(); } break; case "ArrowUp": event: KeyboardEventevent.Event.preventDefault(): void
If invoked when the cancelable attribute value is true, and while executing a listener for the event with passive set to false, signals to the operation that caused event to be dispatched that it needs to be canceled. [MDN Reference](https://developer.mozilla.org/docs/Web/API/Event/preventDefault)
preventDefault
();
if (const items: string[]items.Array<string>.length: number
Gets or sets the length of the array. This is a number one higher than the highest index in the array.
length
> 0) {
const const prevIndex: numberprevIndex = const currentItemIndex: number | nullcurrentItemIndex === null ? const items: string[]items.Array<string>.length: number
Gets or sets the length of the array. This is a number one higher than the highest index in the array.
length
- 1
: (const currentItemIndex: numbercurrentItemIndex - 1 + const items: string[]items.Array<string>.length: number
Gets or sets the length of the array. This is a number one higher than the highest index in the array.
length
) % const items: string[]items.Array<string>.length: number
Gets or sets the length of the array. This is a number one higher than the highest index in the array.
length
;
const focusedItemIndex: Ref<number | null, number | null>focusedItemIndex.Ref<number | null, number | null>.value: number | nullvalue = const prevIndex: numberprevIndex; function announce(message: string): voidannounce(const items: string[]items[const prevIndex: numberprevIndex]); await nextTick<void, void>(this: void, fn?: ((this: void) => void) | undefined): Promise<void>nextTick(); // const el = document.getElementById(focusedItemId.value!); // el?.focus(); } break; case " ": // Spacebar event: KeyboardEventevent.Event.preventDefault(): void
If invoked when the cancelable attribute value is true, and while executing a listener for the event with passive set to false, signals to the operation that caused event to be dispatched that it needs to be canceled. [MDN Reference](https://developer.mozilla.org/docs/Web/API/Event/preventDefault)
preventDefault
();
if (const currentItemIndex: number | nullcurrentItemIndex !== null) { if (
const selectedItem: Ref<{
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
} | null, {
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
} | {
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
} | null>
selectedItem
.
Ref<{ listIndex: 0 | 1; itemIndex: number; value: string; } | null, { listIndex: 0 | 1; itemIndex: number; value: string; } | { listIndex: 0 | 1; itemIndex: number; value: string; } | null>.value: {
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
} | null
value
?.listIndex: 0 | 1 | undefinedlistIndex === listIndex: 0 | 1listIndex &&
const selectedItem: Ref<{
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
} | null, {
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
} | {
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
} | null>
selectedItem
.
Ref<{ listIndex: 0 | 1; itemIndex: number; value: string; } | null, { listIndex: 0 | 1; itemIndex: number; value: string; } | { listIndex: 0 | 1; itemIndex: number; value: string; } | null>.value: {
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
}
value
?.itemIndex: numberitemIndex === const currentItemIndex: numbercurrentItemIndex
) { // Deselect if selecting the same item again
const selectedItem: Ref<{
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
} | null, {
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
} | {
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
} | null>
selectedItem
.
Ref<{ listIndex: 0 | 1; itemIndex: number; value: string; } | null, { listIndex: 0 | 1; itemIndex: number; value: string; } | { listIndex: 0 | 1; itemIndex: number; value: string; } | null>.value: {
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
} | {
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
} | null
value
= null;
function announce(message: string): voidannounce(`${const items: string[]items[const currentItemIndex: numbercurrentItemIndex]} deselected.`); } else { // Select the currently focused item
const selectedItem: Ref<{
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
} | null, {
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
} | {
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
} | null>
selectedItem
.
Ref<{ listIndex: 0 | 1; itemIndex: number; value: string; } | null, { listIndex: 0 | 1; itemIndex: number; value: string; } | { listIndex: 0 | 1; itemIndex: number; value: string; } | null>.value: {
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
} | {
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
} | null
value
= {
listIndex: 0 | 1listIndex, itemIndex: numberitemIndex: const currentItemIndex: numbercurrentItemIndex, value: stringvalue: const items: string[]items[const currentItemIndex: numbercurrentItemIndex], }; function announce(message: string): voidannounce( `${const items: string[]items[const currentItemIndex: numbercurrentItemIndex]} selected. Use arrow keys to choose drop position, then press Enter.` ); } } break; case "Enter": event: KeyboardEventevent.Event.preventDefault(): void
If invoked when the cancelable attribute value is true, and while executing a listener for the event with passive set to false, signals to the operation that caused event to be dispatched that it needs to be canceled. [MDN Reference](https://developer.mozilla.org/docs/Web/API/Event/preventDefault)
preventDefault
();
if (
const selectedItem: Ref<{
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
} | null, {
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
} | {
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
} | null>
selectedItem
.
Ref<{ listIndex: 0 | 1; itemIndex: number; value: string; } | null, { listIndex: 0 | 1; itemIndex: number; value: string; } | { listIndex: 0 | 1; itemIndex: number; value: string; } | null>.value: {
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
} | null
value
&& const currentItemIndex: number | nullcurrentItemIndex !== null) {
const const sourceListIndex: 0 | 1sourceListIndex =
const selectedItem: Ref<{
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
} | null, {
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
} | {
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
} | null>
selectedItem
.
Ref<{ listIndex: 0 | 1; itemIndex: number; value: string; } | null, { listIndex: 0 | 1; itemIndex: number; value: string; } | { listIndex: 0 | 1; itemIndex: number; value: string; } | null>.value: {
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
}
value
.listIndex: 0 | 1listIndex;
const const sourceItemIndex: numbersourceItemIndex =
const selectedItem: Ref<{
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
} | null, {
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
} | {
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
} | null>
selectedItem
.
Ref<{ listIndex: 0 | 1; itemIndex: number; value: string; } | null, { listIndex: 0 | 1; itemIndex: number; value: string; } | { listIndex: 0 | 1; itemIndex: number; value: string; } | null>.value: {
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
}
value
.itemIndex: numberitemIndex;
const const targetListIndex: 0 | 1targetListIndex = listIndex: 0 | 1listIndex; const const targetItemIndex: numbertargetItemIndex = const currentItemIndex: numbercurrentItemIndex; const const itemValue: stringitemValue =
const selectedItem: Ref<{
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
} | null, {
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
} | {
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
} | null>
selectedItem
.
Ref<{ listIndex: 0 | 1; itemIndex: number; value: string; } | null, { listIndex: 0 | 1; itemIndex: number; value: string; } | { listIndex: 0 | 1; itemIndex: number; value: string; } | null>.value: {
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
}
value
.value: stringvalue;
// Prevent dropping onto itself without moving if ( const sourceListIndex: 0 | 1sourceListIndex === const targetListIndex: 0 | 1targetListIndex && const sourceItemIndex: numbersourceItemIndex === const targetItemIndex: numbertargetItemIndex ) { // Announce slightly different message for keyboard attempt function announce(message: string): voidannounce(`Keyboard: Cannot drop ${const itemValue: stringitemValue} onto itself.`);
const selectedItem: Ref<{
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
} | null, {
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
} | {
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
} | null>
selectedItem
.
Ref<{ listIndex: 0 | 1; itemIndex: number; value: string; } | null, { listIndex: 0 | 1; itemIndex: number; value: string; } | { listIndex: 0 | 1; itemIndex: number; value: string; } | null>.value: {
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
} | {
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
} | null
value
= null; // Clear selection
break; } // Perform the move by directly modifying the reactive refs const const sourceItems: Ref<string[], string[]>sourceItems =
const lists: ComputedRef<{
    node: Ref<HTMLElement | undefined, HTMLElement | undefined>;
    items: Ref<string[], string[]>;
    idPrefix: string;
}[]>
lists
.
ComputedRef<{ node: Ref<HTMLElement | undefined, HTMLElement | undefined>; items: Ref<string[], string[]>; idPrefix: string; }[]>.value: {
    node: Ref<HTMLElement | undefined, HTMLElement | undefined>;
    items: Ref<string[], string[]>;
    idPrefix: string;
}[]
value
[const sourceListIndex: 0 | 1sourceListIndex].items: Ref<string[], string[]>items;
const const targetItems: Ref<string[], string[]>targetItems =
const lists: ComputedRef<{
    node: Ref<HTMLElement | undefined, HTMLElement | undefined>;
    items: Ref<string[], string[]>;
    idPrefix: string;
}[]>
lists
.
ComputedRef<{ node: Ref<HTMLElement | undefined, HTMLElement | undefined>; items: Ref<string[], string[]>; idPrefix: string; }[]>.value: {
    node: Ref<HTMLElement | undefined, HTMLElement | undefined>;
    items: Ref<string[], string[]>;
    idPrefix: string;
}[]
value
[const targetListIndex: 0 | 1targetListIndex].items: Ref<string[], string[]>items;
// 1. Remove from source const sourceItems: Ref<string[], string[]>sourceItems.Ref<string[], string[]>.value: string[]value.Array<string>.splice(start: number, deleteCount?: number): string[] (+1 overload)
Removes elements from an array and, if necessary, inserts new elements in their place, returning the deleted elements.
@paramstart The zero-based location in the array from which to start removing elements.@paramdeleteCount The number of elements to remove.@returnsAn array containing the elements that were deleted.
splice
(const sourceItemIndex: numbersourceItemIndex, 1);
// 2. Insert into target // Adjust target index if moving within the same list downwards let let effectiveTargetIndex: numbereffectiveTargetIndex = const targetItemIndex: numbertargetItemIndex; // If dropping onto the same list if (const sourceListIndex: 0 | 1sourceListIndex === const targetListIndex: 0 | 1targetListIndex) { // If dropping after the original position if (const sourceItemIndex: numbersourceItemIndex < const targetItemIndex: numbertargetItemIndex) { // No adjustment needed because the targetItemIndex already accounts // for the removal of the item before it. // However, if the target *was* the placeholder *after* the last item, // we might need to adjust. Let's refine this slightly. // The targetItemIndex is the index *before* insertion. let effectiveTargetIndex: numbereffectiveTargetIndex = const targetItemIndex: numbertargetItemIndex; // This seems correct for splice insertion point } else { // If dropping before the original position, the targetItemIndex is correct. let effectiveTargetIndex: numbereffectiveTargetIndex = const targetItemIndex: numbertargetItemIndex; } } else { // If dropping onto a different list, the targetItemIndex is correct. let effectiveTargetIndex: numbereffectiveTargetIndex = const targetItemIndex: numbertargetItemIndex; } // Ensure the index is valid for splice (handles dropping at the end) let effectiveTargetIndex: numbereffectiveTargetIndex = var Math: Math
An intrinsic object that provides basic mathematics functionality and constants.
Math
.Math.max(...values: number[]): number
Returns the larger of a set of supplied numeric expressions.
@paramvalues Numeric expressions to be evaluated.
max
(
0, var Math: Math
An intrinsic object that provides basic mathematics functionality and constants.
Math
.Math.min(...values: number[]): number
Returns the smaller of a set of supplied numeric expressions.
@paramvalues Numeric expressions to be evaluated.
min
(let effectiveTargetIndex: numbereffectiveTargetIndex, const targetItems: Ref<string[], string[]>targetItems.Ref<string[], string[]>.value: string[]value.Array<string>.length: number
Gets or sets the length of the array. This is a number one higher than the highest index in the array.
length
)
); const targetItems: Ref<string[], string[]>targetItems.Ref<string[], string[]>.value: string[]value.Array<string>.splice(start: number, deleteCount: number, ...items: string[]): string[] (+1 overload)
Removes elements from an array and, if necessary, inserts new elements in their place, returning the deleted elements.
@paramstart The zero-based location in the array from which to start removing elements.@paramdeleteCount The number of elements to remove.@paramitems Elements to insert into the array in place of the deleted elements.@returnsAn array containing the elements that were deleted.
splice
(let effectiveTargetIndex: numbereffectiveTargetIndex, 0, const itemValue: stringitemValue);
// Announce the keyboard-driven move function announce(message: string): voidannounce( `Keyboard: Moved ${const itemValue: stringitemValue} to position ${ let effectiveTargetIndex: numbereffectiveTargetIndex + 1 } in List ${const targetListIndex: 0 | 1targetListIndex + 1}.` ); // Reset state
const selectedItem: Ref<{
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
} | null, {
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
} | {
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
} | null>
selectedItem
.
Ref<{ listIndex: 0 | 1; itemIndex: number; value: string; } | null, { listIndex: 0 | 1; itemIndex: number; value: string; } | { listIndex: 0 | 1; itemIndex: number; value: string; } | null>.value: {
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
} | {
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
} | null
value
= null;
// Keep focus on the item in its new position if possible const focusedItemIndex: Ref<number | null, number | null>focusedItemIndex.Ref<number | null, number | null>.value: number | nullvalue = let effectiveTargetIndex: numbereffectiveTargetIndex; const focusedListIndex: Ref<0 | 1 | null, 0 | 1 | null>focusedListIndex.Ref<0 | 1 | null, 0 | 1 | null>.value: 0 | 1 | nullvalue = const targetListIndex: 0 | 1targetListIndex; // Ensure focus stays on target list } break; case "Escape": event: KeyboardEventevent.Event.preventDefault(): void
If invoked when the cancelable attribute value is true, and while executing a listener for the event with passive set to false, signals to the operation that caused event to be dispatched that it needs to be canceled. [MDN Reference](https://developer.mozilla.org/docs/Web/API/Event/preventDefault)
preventDefault
();
if (
const selectedItem: Ref<{
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
} | null, {
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
} | {
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
} | null>
selectedItem
.
Ref<{ listIndex: 0 | 1; itemIndex: number; value: string; } | null, { listIndex: 0 | 1; itemIndex: number; value: string; } | { listIndex: 0 | 1; itemIndex: number; value: string; } | null>.value: {
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
} | null
value
) {
function announce(message: string): voidannounce(`Selection cancelled for ${
const selectedItem: Ref<{
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
} | null, {
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
} | {
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
} | null>
selectedItem
.
Ref<{ listIndex: 0 | 1; itemIndex: number; value: string; } | null, { listIndex: 0 | 1; itemIndex: number; value: string; } | { listIndex: 0 | 1; itemIndex: number; value: string; } | null>.value: {
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
}
value
.value: stringvalue}.`);
const selectedItem: Ref<{
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
} | null, {
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
} | {
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
} | null>
selectedItem
.
Ref<{ listIndex: 0 | 1; itemIndex: number; value: string; } | null, { listIndex: 0 | 1; itemIndex: number; value: string; } | { listIndex: 0 | 1; itemIndex: number; value: string; } | null>.value: {
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
} | {
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
} | null
value
= null;
} else { // Optionally blur the list or reset focus function announce(message: string): voidannounce("Escape pressed. No item selected."); (event: KeyboardEventevent.Event.target: EventTarget | null
Returns the object to which event is dispatched (its target). [MDN Reference](https://developer.mozilla.org/docs/Web/API/Event/target)
target
as HTMLElement).HTMLOrSVGElement.blur(): void
[MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLElement/blur)
blur
(); // Example: blur the list
const focusedListIndex: Ref<0 | 1 | null, 0 | 1 | null>focusedListIndex.Ref<0 | 1 | null, 0 | 1 | null>.value: 0 | 1 | nullvalue = null; const focusedItemIndex: Ref<number | null, number | null>focusedItemIndex.Ref<number | null, number | null>.value: number | nullvalue = null; } break; // Add Home/End key support if desired // case "Home": ... // case "End": ... default: // Allow other keys like Tab to function normally return; } } </script> <template> <div: HTMLAttributes & ReservedPropsdiv HTMLAttributes.class?: anyclass="accessibility-demo"> <div: HTMLAttributes & ReservedPropsdiv ref?: VNodeRef | undefinedref="const liveRegion: Ref<HTMLDivElement | null, HTMLDivElement | null>liveRegion" aria-live="polite" HTMLAttributes.class?: anyclass="sr-only"> {{ const liveMessage: Ref<string, string>liveMessage }} </div: HTMLAttributes & ReservedPropsdiv> <div: HTMLAttributes & ReservedPropsdiv HTMLAttributes.class?: anyclass="lists-container"> <div: HTMLAttributes & ReservedPropsdiv HTMLAttributes.class?: anyclass="list-wrapper"> <h2: HTMLAttributes & ReservedPropsh2 HTMLAttributes.id?: string | undefinedid="list1-heading">List 1</h2: HTMLAttributes & ReservedPropsh2> <ul: HTMLAttributes & ReservedPropsul ref?: VNodeRef | undefinedref="const list1Node: Ref<HTMLElement | undefined, HTMLElement | undefined>list1Node" HTMLAttributes.class?: anyclass="list" HTMLAttributes.tabindex?: Numberish | undefinedtabindex="0" HTMLAttributes.role?: string | undefinedrole="listbox" aria-labelledby="list1-heading" :aria-activedescendant=" const focusedListIndex: Ref<0 | 1 | null, 0 | 1 | null>focusedListIndex === 0 ? const focusedItemId: ComputedRef<string | undefined>focusedItemId : var undefinedundefined " @onFocus?: ((payload: FocusEvent) => void) | undefinedfocus="function handleListFocus(listIndex: 0 | 1): voidhandleListFocus(0)" @onBlur?: ((payload: FocusEvent) => void) | undefinedblur="function handleListBlur(): voidhandleListBlur" @onKeydown?: ((payload: KeyboardEvent) => void) | undefinedkeydown="function handleListKeydown(event: KeyboardEvent, listIndex: 0 | 1): Promise<void>handleListKeydown($event: KeyboardEvent$event, 0)" > <li: LiHTMLAttributes & ReservedPropsli v-for="(const item: stringitem, const index: numberindex) in const items1: Ref<string[], string[]>items1" key?: PropertyKey | undefined:key?: PropertyKey | undefinedkey="const item: stringitem" HTMLAttributes.id?: string | undefined:HTMLAttributes.id?: string | undefinedid="`list1-item-${const item: stringitem}`" HTMLAttributes.class?: anyclass="item" HTMLAttributes.role?: string | undefinedrole="option" :aria-selected=" const focusedListIndex: Ref<0 | 1 | null, 0 | 1 | null>focusedListIndex === 0 && const focusedItemIndex: Ref<number | null, number | null>focusedItemIndex === const index: numberindex " HTMLAttributes.class?: any:HTMLAttributes.class?: anyclass="{ 'item-focused': const focusedListIndex: Ref<0 | 1 | null, 0 | 1 | null>focusedListIndex === 0 && const focusedItemIndex: Ref<number | null, number | null>focusedItemIndex === const index: numberindex, 'item-selected':
const selectedItem: Ref<{
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
} | null, {
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
} | {
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
} | null>
selectedItem
?.listIndex: 0 | 1 | undefinedlistIndex === 0 &&
const selectedItem: Ref<{
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
} | null, {
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
} | {
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
} | null>
selectedItem
?.itemIndex: numberitemIndex === const index: numberindex,
}" HTMLAttributes.tabindex?: Numberish | undefinedtabindex="-1" > {{ const item: stringitem }} </li: LiHTMLAttributes & ReservedPropsli> <li: LiHTMLAttributes & ReservedPropsli v-if="const items1: Ref<string[], string[]>items1.Array<string>.length: number
Gets or sets the length of the array. This is a number one higher than the highest index in the array.
length
=== 0" HTMLAttributes.class?: anyclass="empty-list-message">Empty</li: LiHTMLAttributes & ReservedPropsli>
</ul: HTMLAttributes & ReservedPropsul> </div: HTMLAttributes & ReservedPropsdiv> <div: HTMLAttributes & ReservedPropsdiv HTMLAttributes.class?: anyclass="list-wrapper"> <h2: HTMLAttributes & ReservedPropsh2 HTMLAttributes.id?: string | undefinedid="list2-heading">List 2</h2: HTMLAttributes & ReservedPropsh2> <ul: HTMLAttributes & ReservedPropsul ref?: VNodeRef | undefinedref="const list2Node: Ref<HTMLElement | undefined, HTMLElement | undefined>list2Node" HTMLAttributes.class?: anyclass="list" HTMLAttributes.tabindex?: Numberish | undefinedtabindex="0" HTMLAttributes.role?: string | undefinedrole="listbox" aria-labelledby="list2-heading" :aria-activedescendant=" const focusedListIndex: Ref<0 | 1 | null, 0 | 1 | null>focusedListIndex === 1 ? const focusedItemId: ComputedRef<string | undefined>focusedItemId : var undefinedundefined " @onFocus?: ((payload: FocusEvent) => void) | undefinedfocus="function handleListFocus(listIndex: 0 | 1): voidhandleListFocus(1)" @onBlur?: ((payload: FocusEvent) => void) | undefinedblur="function handleListBlur(): voidhandleListBlur" @onKeydown?: ((payload: KeyboardEvent) => void) | undefinedkeydown="function handleListKeydown(event: KeyboardEvent, listIndex: 0 | 1): Promise<void>handleListKeydown($event: KeyboardEvent$event, 1)" > <li: LiHTMLAttributes & ReservedPropsli v-for="(const item: stringitem, const index: numberindex) in const items2: Ref<string[], string[]>items2" key?: PropertyKey | undefined:key?: PropertyKey | undefinedkey="const item: stringitem" HTMLAttributes.id?: string | undefined:HTMLAttributes.id?: string | undefinedid="`list2-item-${const item: stringitem}`" HTMLAttributes.class?: anyclass="item" HTMLAttributes.role?: string | undefinedrole="option" :aria-selected=" const focusedListIndex: Ref<0 | 1 | null, 0 | 1 | null>focusedListIndex === 1 && const focusedItemIndex: Ref<number | null, number | null>focusedItemIndex === const index: numberindex " HTMLAttributes.class?: any:HTMLAttributes.class?: anyclass="{ 'item-focused': const focusedListIndex: Ref<0 | 1 | null, 0 | 1 | null>focusedListIndex === 1 && const focusedItemIndex: Ref<number | null, number | null>focusedItemIndex === const index: numberindex, 'item-selected':
const selectedItem: Ref<{
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
} | null, {
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
} | {
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
} | null>
selectedItem
?.listIndex: 0 | 1 | undefinedlistIndex === 1 &&
const selectedItem: Ref<{
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
} | null, {
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
} | {
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
} | null>
selectedItem
?.itemIndex: numberitemIndex === const index: numberindex,
}" HTMLAttributes.tabindex?: Numberish | undefinedtabindex="-1" > {{ const item: stringitem }} </li: LiHTMLAttributes & ReservedPropsli> <li: LiHTMLAttributes & ReservedPropsli v-if="const items2: Ref<string[], string[]>items2.Array<string>.length: number
Gets or sets the length of the array. This is a number one higher than the highest index in the array.
length
=== 0" HTMLAttributes.class?: anyclass="empty-list-message">Empty</li: LiHTMLAttributes & ReservedPropsli>
</ul: HTMLAttributes & ReservedPropsul> </div: HTMLAttributes & ReservedPropsdiv> </div: HTMLAttributes & ReservedPropsdiv> <div: HTMLAttributes & ReservedPropsdiv HTMLAttributes.class?: anyclass="instructions"> <h3: HTMLAttributes & ReservedPropsh3>Keyboard Instructions</h3: HTMLAttributes & ReservedPropsh3> <ul: HTMLAttributes & ReservedPropsul> <li: LiHTMLAttributes & ReservedPropsli>Use <kbd: HTMLAttributes & ReservedPropskbd>Tab</kbd: HTMLAttributes & ReservedPropskbd> or <kbd: HTMLAttributes & ReservedPropskbd>Shift+Tab</kbd: HTMLAttributes & ReservedPropskbd> to focus a list.</li: LiHTMLAttributes & ReservedPropsli> <li: LiHTMLAttributes & ReservedPropsli> Use <kbd: HTMLAttributes & ReservedPropskbd>↑</kbd: HTMLAttributes & ReservedPropskbd> / <kbd: HTMLAttributes & ReservedPropskbd>↓</kbd: HTMLAttributes & ReservedPropskbd> arrows to navigate items within the focused list. </li: LiHTMLAttributes & ReservedPropsli> <li: LiHTMLAttributes & ReservedPropsli> Press <kbd: HTMLAttributes & ReservedPropskbd>Spacebar</kbd: HTMLAttributes & ReservedPropskbd> to select/deselect the highlighted item for moving. </li: LiHTMLAttributes & ReservedPropsli> <li: LiHTMLAttributes & ReservedPropsli> With an item selected, use <kbd: HTMLAttributes & ReservedPropskbd>↑</kbd: HTMLAttributes & ReservedPropskbd> / <kbd: HTMLAttributes & ReservedPropskbd>↓</kbd: HTMLAttributes & ReservedPropskbd> (within the same or another focused list) to choose the drop position. </li: LiHTMLAttributes & ReservedPropsli> <li: LiHTMLAttributes & ReservedPropsli> Press <kbd: HTMLAttributes & ReservedPropskbd>Enter</kbd: HTMLAttributes & ReservedPropskbd> to drop the selected item at the highlighted position. </li: LiHTMLAttributes & ReservedPropsli> <li: LiHTMLAttributes & ReservedPropsli> Press <kbd: HTMLAttributes & ReservedPropskbd>Escape</kbd: HTMLAttributes & ReservedPropskbd> to cancel a selection or leave the list. </li: LiHTMLAttributes & ReservedPropsli> </ul: HTMLAttributes & ReservedPropsul> </div: HTMLAttributes & ReservedPropsdiv> </div: HTMLAttributes & ReservedPropsdiv> </template>
/** @jsxImportSource solid-js */
import { function createSignal<T>(): Signal<T | undefined> (+1 overload)
Creates a simple reactive state with a getter and setter ```typescript const [state: Accessor<T>, setState: Setter<T>] = createSignal<T>( value: T, options?: { name?: string, equals?: false | ((prev: T, next: T) => boolean) } ) ```
@paramvalue initial value of the state; if empty, the state's type will automatically extended with undefined; otherwise you need to extend the type manually if you want setting to undefined not be an error@paramoptions optional object with a name for debugging purposes and equals, a comparator function for the previous and next value to allow fine-grained control over the reactivity@returns```typescript [state: Accessor<T>, setState: Setter<T>] ``` * the Accessor is merely a function that returns the current value and registers each call to the reactive root * the Setter is a function that allows directly setting or mutating the value: ```typescript const [count, setCount] = createSignal(0); setCount(count => count + 1); ```@descriptionhttps://docs.solidjs.com/reference/basic-reactivity/create-signal
createSignal
, function createMemo<Next extends Prev, Prev = Next>(fn: EffectFunction<undefined | NoInfer<Prev>, Next>): Accessor<Next> (+1 overload)
Creates a readonly derived reactive memoized signal ```typescript export function createMemo<T>( fn: (v: T) => T, value?: T, options?: { name?: string, equals?: false | ((prev: T, next: T) => boolean) } ): () => T; ```
@paramfn a function that receives its previous or the initial value, if set, and returns a new value used to react on a computation@paramvalue an optional initial value for the computation; if set, fn will never receive undefined as first argument@paramoptions allows to set a name in dev mode for debugging purposes and use a custom comparison function in equals@descriptionhttps://docs.solidjs.com/reference/basic-reactivity/create-memo
createMemo
,
function For<T extends readonly any[], U extends JSX.Element>(props: {
    each: T | undefined | null | false;
    fallback?: JSX.Element;
    children: (item: T[number], index: Accessor<number>) => U;
}): JSX.Element
Creates a list elements from a list it receives a map function as its child that receives a list element and an accessor with the index and returns a JSX-Element; if the list is empty, an optional fallback is returned: ```typescript <For each={items} fallback={<div>No items</div>}> {(item, index) => <div data-index={index()}>{item}</div>} </For> ``` If you have a list with fixed indices and changing values, consider using `<Index>` instead.
@descriptionhttps://docs.solidjs.com/reference/components/for
For
} from "solid-js";
import { function useDragAndDrop<E extends HTMLElement, T = unknown>(initValues: T[], options?: Partial<ParentConfig<T>>): [Setter<E | null>, Accessor<Store<T[]>>, ReturnType<typeof createStore>[1], (config?: Partial<ParentConfig<T>>) => void]
Hook for adding drag and drop/sortable support to a list of items.
@paraminitValues - Initial list of data.@paramoptions - The drag and drop configuration.@returns
useDragAndDrop
} from "@formkit/drag-and-drop/solid";
// Initial data for the lists const const initialItems1: string[]initialItems1 = ["Apples", "Bananas", "Oranges", "Grapes"]; const const initialItems2: string[]initialItems2 = ["Milk", "Cheese", "Yogurt"]; interface SelectedItem { SelectedItem.listIndex: 0 | 1listIndex: 0 | 1; SelectedItem.itemIndex: numberitemIndex: number; SelectedItem.value: stringvalue: string; } export default function function AccessibilityDemoSolid(): JSX.ElementAccessibilityDemoSolid() { // --- Refs and Signals --- const [const liveMessage: Accessor<string>liveMessage, const setLiveMessage: Setter<string>setLiveMessage] = createSignal<string>(value: string, options?: SignalOptions<string> | undefined): Signal<string> (+1 overload)
Creates a simple reactive state with a getter and setter ```typescript const [state: Accessor<T>, setState: Setter<T>] = createSignal<T>( value: T, options?: { name?: string, equals?: false | ((prev: T, next: T) => boolean) } ) ```
@paramvalue initial value of the state; if empty, the state's type will automatically extended with undefined; otherwise you need to extend the type manually if you want setting to undefined not be an error@paramoptions optional object with a name for debugging purposes and equals, a comparator function for the previous and next value to allow fine-grained control over the reactivity@returns```typescript [state: Accessor<T>, setState: Setter<T>] ``` * the Accessor is merely a function that returns the current value and registers each call to the reactive root * the Setter is a function that allows directly setting or mutating the value: ```typescript const [count, setCount] = createSignal(0); setCount(count => count + 1); ```@descriptionhttps://docs.solidjs.com/reference/basic-reactivity/create-signal
createSignal
("");
let let liveRegionRef: HTMLDivElement | undefinedliveRegionRef: HTMLDivElement | undefined; // Variables to hold the actual DOM elements for comparison let let list1RefEl: HTMLUListElement | undefinedlist1RefEl: HTMLUListElement | undefined; let let list2RefEl: HTMLUListElement | undefinedlist2RefEl: HTMLUListElement | undefined; // --- Announcer Function --- const const announce: (message: string) => voidannounce = (message: stringmessage: string) => { const setLiveMessage: <string>(value: string | ((prev: string) => string)) => string (+3 overloads)setLiveMessage(message: stringmessage); // Optional: Clear message after delay // setTimeout(() => setLiveMessage(''), 5000); }; // --- Drag and Drop Setup --- // useDragAndDrop returns [setRef, itemsSignal, setItemsSignal] in Solid const [const setList1Ref: Setter<HTMLUListElement | null>setList1Ref, const items1: Accessor<string[]>items1, const setItems1: SetStoreFunction<string[]>setItems1] = useDragAndDrop<HTMLUListElement, string>(initValues: string[], options?: Partial<ParentConfig<string>> | undefined): [Setter<HTMLUListElement | null>, Accessor<...>, SetStoreFunction<...>, (config?: Partial<...> | undefined) => void]
Hook for adding drag and drop/sortable support to a list of items.
@paraminitValues - Initial list of data.@paramoptions - The drag and drop configuration.@returns
useDragAndDrop
<
HTMLUListElement, string >(const initialItems1: string[]initialItems1, { group?: string | undefined
The group that the parent belongs to. This is used for allowing multiple parents to transfer nodes between each other.
group
: "accessibleList",
// Let types be inferred onDragstart?: DragstartEvent | undefined
Fired when a drag is started, whether native drag or synthetic
onDragstart
: (state: DragstartEventData<T>state) =>
const announce: (message: string) => voidannounce(`Drag started for ${state: DragstartEventData<T>state.DragstartEventData<T>.draggedNode: NodeRecord<T>draggedNode.NodeRecord<T>.data: NodeData<T>data.NodeData<T>.value: T
The value of the node.
value
}.`),
onSort?: SortEvent | undefined
Callback function for when a sort operation is performed.
onSort
: (event: SortEventData<T>event) =>
const announce: (message: string) => voidannounce( `Sorted ${event: SortEventData<T>event.SortEventData<T>.draggedNodes: NodeRecord<T>[]draggedNodes[0].NodeRecord<T>.data: NodeData<T>data.NodeData<T>.value: T
The value of the node.
value
} in List 1 to position ${
event: SortEventData<T>event.SortEventData<T>.position: numberposition + 1 }.` ), onTransfer?: TransferEvent | undefined
Callback function for when a transfer operation is performed.
onTransfer
: (event: TransferEventData<T>event) => {
// Compare event source element with the element stored in list1RefEl const announce: (message: string) => voidannounce( `Transferred ${event: TransferEventData<T>event.TransferEventData<T>.draggedNodes: NodeRecord<T>[]draggedNodes[0].NodeRecord<T>.data: NodeData<T>data.NodeData<T>.value: T
The value of the node.
value
} from List ${
event: TransferEventData<T>event.TransferEventData<T>.sourceParent: ParentRecord<T>sourceParent.ParentRecord<T>.el: HTMLElementel === let list1RefEl: HTMLUListElement | undefinedlist1RefEl ? 1 : 2 } to List 1 at position ${event: TransferEventData<T>event.TransferEventData<T>.targetIndex: numbertargetIndex + 1}.` ); }, onDragend?: DragendEvent | undefined
Fired when a drag is ended, whether native drag or synthetic
onDragend
: (state: DragendEventData<T>state) =>
const announce: (message: string) => voidannounce(`Drag ended for ${state: DragendEventData<T>state.DragendEventData<T>.draggedNode: NodeRecord<T>draggedNode.NodeRecord<T>.data: NodeData<T>data.NodeData<T>.value: T
The value of the node.
value
}.`),
}); const [const setList2Ref: Setter<HTMLUListElement | null>setList2Ref, const items2: Accessor<string[]>items2, const setItems2: SetStoreFunction<string[]>setItems2] = useDragAndDrop<HTMLUListElement, string>(initValues: string[], options?: Partial<ParentConfig<string>> | undefined): [Setter<HTMLUListElement | null>, Accessor<...>, SetStoreFunction<...>, (config?: Partial<...> | undefined) => void]
Hook for adding drag and drop/sortable support to a list of items.
@paraminitValues - Initial list of data.@paramoptions - The drag and drop configuration.@returns
useDragAndDrop
<
HTMLUListElement, string >(const initialItems2: string[]initialItems2, { group?: string | undefined
The group that the parent belongs to. This is used for allowing multiple parents to transfer nodes between each other.
group
: "accessibleList",
onDragstart?: DragstartEvent | undefined
Fired when a drag is started, whether native drag or synthetic
onDragstart
: (state: DragstartEventData<T>state) =>
const announce: (message: string) => voidannounce(`Drag started for ${state: DragstartEventData<T>state.DragstartEventData<T>.draggedNode: NodeRecord<T>draggedNode.NodeRecord<T>.data: NodeData<T>data.NodeData<T>.value: T
The value of the node.
value
}.`),
onSort?: SortEvent | undefined
Callback function for when a sort operation is performed.
onSort
: (event: SortEventData<T>event) =>
const announce: (message: string) => voidannounce( `Sorted ${event: SortEventData<T>event.SortEventData<T>.draggedNodes: NodeRecord<T>[]draggedNodes[0].NodeRecord<T>.data: NodeData<T>data.NodeData<T>.value: T
The value of the node.
value
} in List 2 to position ${
event: SortEventData<T>event.SortEventData<T>.position: numberposition + 1 }.` ), onTransfer?: TransferEvent | undefined
Callback function for when a transfer operation is performed.
onTransfer
: (event: TransferEventData<T>event) => {
// Compare event source element with the element stored in list1RefEl const announce: (message: string) => voidannounce( `Transferred ${event: TransferEventData<T>event.TransferEventData<T>.draggedNodes: NodeRecord<T>[]draggedNodes[0].NodeRecord<T>.data: NodeData<T>data.NodeData<T>.value: T
The value of the node.
value
} from List ${
event: TransferEventData<T>event.TransferEventData<T>.sourceParent: ParentRecord<T>sourceParent.ParentRecord<T>.el: HTMLElementel === let list1RefEl: HTMLUListElement | undefinedlist1RefEl ? 1 : 2 } to List 2 at position ${event: TransferEventData<T>event.TransferEventData<T>.targetIndex: numbertargetIndex + 1}.` ); }, onDragend?: DragendEvent | undefined
Fired when a drag is ended, whether native drag or synthetic
onDragend
: (state: DragendEventData<T>state) =>
const announce: (message: string) => voidannounce(`Drag ended for ${state: DragendEventData<T>state.DragendEventData<T>.draggedNode: NodeRecord<T>draggedNode.NodeRecord<T>.data: NodeData<T>data.NodeData<T>.value: T
The value of the node.
value
}.`),
}); // --- Keyboard Navigation State --- const [const focusedListIndex: Accessor<0 | 1 | null>focusedListIndex, const setFocusedListIndex: Setter<0 | 1 | null>setFocusedListIndex] = createSignal<0 | 1 | null>(value: 0 | 1 | null, options?: SignalOptions<0 | 1 | null> | undefined): Signal<0 | 1 | null> (+1 overload)
Creates a simple reactive state with a getter and setter ```typescript const [state: Accessor<T>, setState: Setter<T>] = createSignal<T>( value: T, options?: { name?: string, equals?: false | ((prev: T, next: T) => boolean) } ) ```
@paramvalue initial value of the state; if empty, the state's type will automatically extended with undefined; otherwise you need to extend the type manually if you want setting to undefined not be an error@paramoptions optional object with a name for debugging purposes and equals, a comparator function for the previous and next value to allow fine-grained control over the reactivity@returns```typescript [state: Accessor<T>, setState: Setter<T>] ``` * the Accessor is merely a function that returns the current value and registers each call to the reactive root * the Setter is a function that allows directly setting or mutating the value: ```typescript const [count, setCount] = createSignal(0); setCount(count => count + 1); ```@descriptionhttps://docs.solidjs.com/reference/basic-reactivity/create-signal
createSignal
<0 | 1 | null>(
null ); const [const focusedItemIndex: Accessor<number | null>focusedItemIndex, const setFocusedItemIndex: Setter<number | null>setFocusedItemIndex] = createSignal<number | null>(value: number | null, options?: SignalOptions<number | null> | undefined): Signal<number | null> (+1 overload)
Creates a simple reactive state with a getter and setter ```typescript const [state: Accessor<T>, setState: Setter<T>] = createSignal<T>( value: T, options?: { name?: string, equals?: false | ((prev: T, next: T) => boolean) } ) ```
@paramvalue initial value of the state; if empty, the state's type will automatically extended with undefined; otherwise you need to extend the type manually if you want setting to undefined not be an error@paramoptions optional object with a name for debugging purposes and equals, a comparator function for the previous and next value to allow fine-grained control over the reactivity@returns```typescript [state: Accessor<T>, setState: Setter<T>] ``` * the Accessor is merely a function that returns the current value and registers each call to the reactive root * the Setter is a function that allows directly setting or mutating the value: ```typescript const [count, setCount] = createSignal(0); setCount(count => count + 1); ```@descriptionhttps://docs.solidjs.com/reference/basic-reactivity/create-signal
createSignal
<number | null>(
null ); const [const selectedItem: Accessor<SelectedItem | null>selectedItem, const setSelectedItem: Setter<SelectedItem | null>setSelectedItem] = createSignal<SelectedItem | null>(value: SelectedItem | null, options?: SignalOptions<SelectedItem | null> | undefined): Signal<...> (+1 overload)
Creates a simple reactive state with a getter and setter ```typescript const [state: Accessor<T>, setState: Setter<T>] = createSignal<T>( value: T, options?: { name?: string, equals?: false | ((prev: T, next: T) => boolean) } ) ```
@paramvalue initial value of the state; if empty, the state's type will automatically extended with undefined; otherwise you need to extend the type manually if you want setting to undefined not be an error@paramoptions optional object with a name for debugging purposes and equals, a comparator function for the previous and next value to allow fine-grained control over the reactivity@returns```typescript [state: Accessor<T>, setState: Setter<T>] ``` * the Accessor is merely a function that returns the current value and registers each call to the reactive root * the Setter is a function that allows directly setting or mutating the value: ```typescript const [count, setCount] = createSignal(0); setCount(count => count + 1); ```@descriptionhttps://docs.solidjs.com/reference/basic-reactivity/create-signal
createSignal
<SelectedItem | null>(
null ); // --- Computed Values --- const const focusedItemId: Accessor<string | undefined>focusedItemId = createMemo<string | undefined, string | undefined>(fn: EffectFunction<string | undefined, string | undefined>): Accessor<string | undefined> (+1 overload)
Creates a readonly derived reactive memoized signal ```typescript export function createMemo<T>( fn: (v: T) => T, value?: T, options?: { name?: string, equals?: false | ((prev: T, next: T) => boolean) } ): () => T; ```
@paramfn a function that receives its previous or the initial value, if set, and returns a new value used to react on a computation@paramvalue an optional initial value for the computation; if set, fn will never receive undefined as first argument@paramoptions allows to set a name in dev mode for debugging purposes and use a custom comparison function in equals@descriptionhttps://docs.solidjs.com/reference/basic-reactivity/create-memo
createMemo
(() => {
const const listIndex: 0 | 1 | nulllistIndex = const focusedListIndex: () => 0 | 1 | nullfocusedListIndex(); const const itemIndex: number | nullitemIndex = const focusedItemIndex: () => number | nullfocusedItemIndex(); const const currentItems: string[]currentItems = const listIndex: 0 | 1 | nulllistIndex === 0 ? const items1: () => string[]items1() : const items2: () => string[]items2(); // Access signal value const const prefix: "list1-item" | "list2-item"prefix = const listIndex: 0 | 1 | nulllistIndex === 0 ? "list1-item" : "list2-item"; if ( const itemIndex: number | nullitemIndex !== null && const itemIndex: numberitemIndex >= 0 && const itemIndex: numberitemIndex < const currentItems: string[]currentItems.Array<string>.length: number
Gets or sets the length of the array. This is a number one higher than the highest index in the array.
length
) { return `${const prefix: "list1-item" | "list2-item"prefix}-${const currentItems: string[]currentItems[const itemIndex: numberitemIndex]}`; } return var undefinedundefined; }); // --- Event Handlers --- const const handleListFocus: (listIndex: 0 | 1) => voidhandleListFocus = (listIndex: 0 | 1listIndex: 0 | 1) => { const setFocusedListIndex: <0 | 1>(value: 0 | 1 | ((prev: 0 | 1 | null) => 0 | 1)) => 0 | 1 (+3 overloads)setFocusedListIndex(listIndex: 0 | 1listIndex); const const currentItems: string[]currentItems = listIndex: 0 | 1listIndex === 0 ? const items1: () => string[]items1() : const items2: () => string[]items2(); if (const focusedItemIndex: () => number | nullfocusedItemIndex() === null && const currentItems: string[]currentItems.Array<string>.length: number
Gets or sets the length of the array. This is a number one higher than the highest index in the array.
length
> 0) {
const setFocusedItemIndex: <0>(value: 0 | ((prev: number | null) => 0)) => 0 (+3 overloads)setFocusedItemIndex(0); } const announce: (message: string) => voidannounce( `List ${listIndex: 0 | 1listIndex + 1} focused. Use up and down arrows to navigate items.` ); }; const const handleListBlur: () => voidhandleListBlur = () => { // Basic blur handling }; const const handleListKeydown: (event: KeyboardEvent, listIndex: 0 | 1) => voidhandleListKeydown = (event: KeyboardEventevent: KeyboardEvent, listIndex: 0 | 1listIndex: 0 | 1) => { if (const focusedListIndex: () => 0 | 1 | nullfocusedListIndex() !== listIndex: 0 | 1listIndex) return; const const currentItems: string[]currentItems = listIndex: 0 | 1listIndex === 0 ? const items1: () => string[]items1() : const items2: () => string[]items2(); const const setItems: SetStoreFunction<string[]>setItems = listIndex: 0 | 1listIndex === 0 ? const setItems1: SetStoreFunction<string[]>setItems1 : const setItems2: SetStoreFunction<string[]>setItems2; const const currentItemIndex: number | nullcurrentItemIndex = const focusedItemIndex: () => number | nullfocusedItemIndex(); // Access signal value switch (event: KeyboardEventevent.KeyboardEvent.key: string
[MDN Reference](https://developer.mozilla.org/docs/Web/API/KeyboardEvent/key)
key
) {
case "ArrowDown": event: KeyboardEventevent.Event.preventDefault(): void
If invoked when the cancelable attribute value is true, and while executing a listener for the event with passive set to false, signals to the operation that caused event to be dispatched that it needs to be canceled. [MDN Reference](https://developer.mozilla.org/docs/Web/API/Event/preventDefault)
preventDefault
();
if (const currentItems: string[]currentItems.Array<string>.length: number
Gets or sets the length of the array. This is a number one higher than the highest index in the array.
length
> 0) {
const const nextIndex: numbernextIndex = const currentItemIndex: number | nullcurrentItemIndex === null ? 0 : (const currentItemIndex: numbercurrentItemIndex + 1) % const currentItems: string[]currentItems.Array<string>.length: number
Gets or sets the length of the array. This is a number one higher than the highest index in the array.
length
;
const setFocusedItemIndex: <number>(value: number | ((prev: number | null) => number)) => number (+3 overloads)setFocusedItemIndex(const nextIndex: numbernextIndex); const announce: (message: string) => voidannounce(const currentItems: string[]currentItems[const nextIndex: numbernextIndex]); } break; case "ArrowUp": event: KeyboardEventevent.Event.preventDefault(): void
If invoked when the cancelable attribute value is true, and while executing a listener for the event with passive set to false, signals to the operation that caused event to be dispatched that it needs to be canceled. [MDN Reference](https://developer.mozilla.org/docs/Web/API/Event/preventDefault)
preventDefault
();
if (const currentItems: string[]currentItems.Array<string>.length: number
Gets or sets the length of the array. This is a number one higher than the highest index in the array.
length
> 0) {
const const prevIndex: numberprevIndex = const currentItemIndex: number | nullcurrentItemIndex === null ? const currentItems: string[]currentItems.Array<string>.length: number
Gets or sets the length of the array. This is a number one higher than the highest index in the array.
length
- 1
: (const currentItemIndex: numbercurrentItemIndex - 1 + const currentItems: string[]currentItems.Array<string>.length: number
Gets or sets the length of the array. This is a number one higher than the highest index in the array.
length
) %
const currentItems: string[]currentItems.Array<string>.length: number
Gets or sets the length of the array. This is a number one higher than the highest index in the array.
length
;
const setFocusedItemIndex: <number>(value: number | ((prev: number | null) => number)) => number (+3 overloads)setFocusedItemIndex(const prevIndex: numberprevIndex); const announce: (message: string) => voidannounce(const currentItems: string[]currentItems[const prevIndex: numberprevIndex]); } break; case " ": // Spacebar event: KeyboardEventevent.Event.preventDefault(): void
If invoked when the cancelable attribute value is true, and while executing a listener for the event with passive set to false, signals to the operation that caused event to be dispatched that it needs to be canceled. [MDN Reference](https://developer.mozilla.org/docs/Web/API/Event/preventDefault)
preventDefault
();
if ( const currentItemIndex: number | nullcurrentItemIndex !== null && const currentItemIndex: numbercurrentItemIndex >= 0 && const currentItemIndex: numbercurrentItemIndex < const currentItems: string[]currentItems.Array<string>.length: number
Gets or sets the length of the array. This is a number one higher than the highest index in the array.
length
) { const const currentItemValue: stringcurrentItemValue = const currentItems: string[]currentItems[const currentItemIndex: numbercurrentItemIndex]; const const currentSelection: SelectedItem | nullcurrentSelection = const selectedItem: () => SelectedItem | nullselectedItem(); // Access signal value if ( const currentSelection: SelectedItem | nullcurrentSelection?.SelectedItem.listIndex: 0 | 1 | undefinedlistIndex === listIndex: 0 | 1listIndex && const currentSelection: SelectedItemcurrentSelection?.SelectedItem.itemIndex: numberitemIndex === const currentItemIndex: numbercurrentItemIndex ) { const setSelectedItem: <null>(value: ((prev: SelectedItem | null) => null) | null) => null (+3 overloads)setSelectedItem(null); const announce: (message: string) => voidannounce(`${const currentItemValue: stringcurrentItemValue} deselected.`); } else {
const setSelectedItem: <{
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
}>(value: {
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
} | ((prev: SelectedItem | null) => {
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
})) => {
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
} (+3 overloads)
setSelectedItem
({
listIndex: 0 | 1listIndex, itemIndex: numberitemIndex: const currentItemIndex: numbercurrentItemIndex, value: stringvalue: const currentItemValue: stringcurrentItemValue, }); const announce: (message: string) => voidannounce( `${const currentItemValue: stringcurrentItemValue} selected. Use arrow keys to choose drop position, then press Enter.` ); } } break; case "Enter": event: KeyboardEventevent.Event.preventDefault(): void
If invoked when the cancelable attribute value is true, and while executing a listener for the event with passive set to false, signals to the operation that caused event to be dispatched that it needs to be canceled. [MDN Reference](https://developer.mozilla.org/docs/Web/API/Event/preventDefault)
preventDefault
();
const const currentSelection: SelectedItem | nullcurrentSelection = const selectedItem: () => SelectedItem | nullselectedItem(); // Access signal value if ( const currentSelection: SelectedItem | nullcurrentSelection && const currentItemIndex: number | nullcurrentItemIndex !== null && const currentItemIndex: numbercurrentItemIndex >= 0 && const currentItemIndex: numbercurrentItemIndex < const currentItems: string[]currentItems.Array<string>.length: number
Gets or sets the length of the array. This is a number one higher than the highest index in the array.
length
) { const { SelectedItem.listIndex: 0 | 1listIndex: const sourceListIndex: 0 | 1sourceListIndex, SelectedItem.itemIndex: numberitemIndex: const sourceItemIndex: numbersourceItemIndex, SelectedItem.value: stringvalue: const itemValue: stringitemValue, } = const currentSelection: SelectedItemcurrentSelection; const const targetListIndex: 0 | 1targetListIndex = listIndex: 0 | 1listIndex; const const targetItemIndex: numbertargetItemIndex = const currentItemIndex: numbercurrentItemIndex; if ( const sourceListIndex: 0 | 1sourceListIndex === const targetListIndex: 0 | 1targetListIndex && const sourceItemIndex: numbersourceItemIndex === const targetItemIndex: numbertargetItemIndex ) { const announce: (message: string) => voidannounce(`Keyboard: Cannot drop ${const itemValue: stringitemValue} onto itself.`); const setSelectedItem: <null>(value: ((prev: SelectedItem | null) => null) | null) => null (+3 overloads)setSelectedItem(null); break; } const const sourceItemsArray: string[]sourceItemsArray = const sourceListIndex: 0 | 1sourceListIndex === 0 ? const items1: () => string[]items1() : const items2: () => string[]items2(); const const setSourceItems: SetStoreFunction<string[]>setSourceItems = const sourceListIndex: 0 | 1sourceListIndex === 0 ? const setItems1: SetStoreFunction<string[]>setItems1 : const setItems2: SetStoreFunction<string[]>setItems2; const const targetItemsArray: string[]targetItemsArray = const targetListIndex: 0 | 1targetListIndex === 0 ? const items1: () => string[]items1() : const items2: () => string[]items2(); const const setTargetItems: SetStoreFunction<string[]>setTargetItems = const targetListIndex: 0 | 1targetListIndex === 0 ? const setItems1: SetStoreFunction<string[]>setItems1 : const setItems2: SetStoreFunction<string[]>setItems2; const const newSourceItems: string[]newSourceItems = [...const sourceItemsArray: string[]sourceItemsArray]; const newSourceItems: string[]newSourceItems.Array<string>.splice(start: number, deleteCount?: number): string[] (+1 overload)
Removes elements from an array and, if necessary, inserts new elements in their place, returning the deleted elements.
@paramstart The zero-based location in the array from which to start removing elements.@paramdeleteCount The number of elements to remove.@returnsAn array containing the elements that were deleted.
splice
(const sourceItemIndex: numbersourceItemIndex, 1);
const const newTargetItems: string[]newTargetItems = const sourceListIndex: 0 | 1sourceListIndex === const targetListIndex: 0 | 1targetListIndex ? const newSourceItems: string[]newSourceItems : [...const targetItemsArray: string[]targetItemsArray]; let let effectiveTargetIndex: numbereffectiveTargetIndex = const targetItemIndex: numbertargetItemIndex; if (const sourceListIndex: 0 | 1sourceListIndex === const targetListIndex: 0 | 1targetListIndex) { if (const sourceItemIndex: numbersourceItemIndex < const targetItemIndex: numbertargetItemIndex) { let effectiveTargetIndex: numbereffectiveTargetIndex = const targetItemIndex: numbertargetItemIndex - 1; } else { let effectiveTargetIndex: numbereffectiveTargetIndex = const targetItemIndex: numbertargetItemIndex; } } else { let effectiveTargetIndex: numbereffectiveTargetIndex = const targetItemIndex: numbertargetItemIndex; } let effectiveTargetIndex: numbereffectiveTargetIndex = var Math: Math
An intrinsic object that provides basic mathematics functionality and constants.
Math
.Math.max(...values: number[]): number
Returns the larger of a set of supplied numeric expressions.
@paramvalues Numeric expressions to be evaluated.
max
(
0, var Math: Math
An intrinsic object that provides basic mathematics functionality and constants.
Math
.Math.min(...values: number[]): number
Returns the smaller of a set of supplied numeric expressions.
@paramvalues Numeric expressions to be evaluated.
min
(let effectiveTargetIndex: numbereffectiveTargetIndex, const newTargetItems: string[]newTargetItems.Array<string>.length: number
Gets or sets the length of the array. This is a number one higher than the highest index in the array.
length
)
); const newTargetItems: string[]newTargetItems.Array<string>.splice(start: number, deleteCount: number, ...items: string[]): string[] (+1 overload)
Removes elements from an array and, if necessary, inserts new elements in their place, returning the deleted elements.
@paramstart The zero-based location in the array from which to start removing elements.@paramdeleteCount The number of elements to remove.@paramitems Elements to insert into the array in place of the deleted elements.@returnsAn array containing the elements that were deleted.
splice
(let effectiveTargetIndex: numbereffectiveTargetIndex, 0, const itemValue: stringitemValue);
// Use signal setters to update state
const setSourceItems: SetStoreFunction
(setter: StoreSetter<string[], []>) => void (+8 overloads)
setSourceItems
(const newSourceItems: string[]newSourceItems);
if (const sourceListIndex: 0 | 1sourceListIndex !== const targetListIndex: 0 | 1targetListIndex) {
const setTargetItems: SetStoreFunction
(setter: StoreSetter<string[], []>) => void (+8 overloads)
setTargetItems
(const newTargetItems: string[]newTargetItems);
} // If same list, setSourceItems updated the array const announce: (message: string) => voidannounce( `Keyboard: Moved ${const itemValue: stringitemValue} to position ${ let effectiveTargetIndex: numbereffectiveTargetIndex + 1 } in List ${const targetListIndex: 0 | 1targetListIndex + 1}.` ); const setSelectedItem: <null>(value: ((prev: SelectedItem | null) => null) | null) => null (+3 overloads)setSelectedItem(null); const setFocusedItemIndex: <number>(value: number | ((prev: number | null) => number)) => number (+3 overloads)setFocusedItemIndex(let effectiveTargetIndex: numbereffectiveTargetIndex); const setFocusedListIndex: <0 | 1>(value: 0 | 1 | ((prev: 0 | 1 | null) => 0 | 1)) => 0 | 1 (+3 overloads)setFocusedListIndex(const targetListIndex: 0 | 1targetListIndex); } break; case "Escape": event: KeyboardEventevent.Event.preventDefault(): void
If invoked when the cancelable attribute value is true, and while executing a listener for the event with passive set to false, signals to the operation that caused event to be dispatched that it needs to be canceled. [MDN Reference](https://developer.mozilla.org/docs/Web/API/Event/preventDefault)
preventDefault
();
if (const selectedItem: () => SelectedItem | nullselectedItem()) { // Access signal value const announce: (message: string) => voidannounce(`Selection cancelled for ${const selectedItem: () => SelectedItem | nullselectedItem()!.SelectedItem.value: stringvalue}.`); const setSelectedItem: <null>(value: ((prev: SelectedItem | null) => null) | null) => null (+3 overloads)setSelectedItem(null); } else { const announce: (message: string) => voidannounce("Escape pressed. No item selected."); (event: KeyboardEventevent.Event.target: EventTarget | null
Returns the object to which event is dispatched (its target). [MDN Reference](https://developer.mozilla.org/docs/Web/API/Event/target)
target
as HTMLElement).HTMLOrSVGElement.blur(): void
[MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLElement/blur)
blur
();
const setFocusedListIndex: <null>(value: ((prev: 0 | 1 | null) => null) | null) => null (+3 overloads)setFocusedListIndex(null); const setFocusedItemIndex: <null>(value: ((prev: number | null) => null) | null) => null (+3 overloads)setFocusedItemIndex(null); } break; default: return; } }; // --- JSX --- return ( // Using a standard div wrapper <JSX.HTMLElementTags.div: JSX.HTMLAttributes<HTMLDivElement>div JSX.HTMLAttributes<HTMLDivElement>.class?: string | undefinedclass="container p-4 border-4 border-blue-300"> <JSX.HTMLElementTags.h1: JSX.HTMLAttributes<HTMLHeadingElement>h1 JSX.HTMLAttributes<T>.class?: string | undefinedclass="text-xl font-bold mb-4">SolidJS Accessibility Demo</JSX.HTMLElementTags.h1: JSX.HTMLAttributes<HTMLHeadingElement>h1> <JSX.HTMLElementTags.div: JSX.HTMLAttributes<HTMLDivElement>div JSX.HTMLAttributes<HTMLDivElement>.class?: string | undefinedclass="accessibility-demo"> {/* ARIA Live Region */} <JSX.HTMLElementTags.div: JSX.HTMLAttributes<HTMLDivElement>div ref?: HTMLDivElement | ((el: HTMLDivElement) => void) | undefinedref={let liveRegionRef: HTMLDivElement | undefinedliveRegionRef} JSX.AriaAttributes["aria-live"]?: "polite" | "off" | "assertive" | undefined
Indicates that an element will be updated, and describes the types of updates the user agents, assistive technologies, and user can expect from the live region.
aria-live
="polite" JSX.HTMLAttributes<HTMLDivElement>.class?: string | undefinedclass="sr-only">
{const liveMessage: () => stringliveMessage()} {/* Access signal value */} </JSX.HTMLElementTags.div: JSX.HTMLAttributes<HTMLDivElement>div> <JSX.HTMLElementTags.div: JSX.HTMLAttributes<HTMLDivElement>div JSX.HTMLAttributes<HTMLDivElement>.class?: string | undefinedclass="lists-container"> {/* List 1 */} <JSX.HTMLElementTags.div: JSX.HTMLAttributes<HTMLDivElement>div JSX.HTMLAttributes<HTMLDivElement>.class?: string | undefinedclass="list-wrapper"> <JSX.HTMLElementTags.h2: JSX.HTMLAttributes<HTMLHeadingElement>h2 JSX.HTMLAttributes<HTMLHeadingElement>.id?: string | undefinedid="list1-item-heading">List 1</JSX.HTMLElementTags.h2: JSX.HTMLAttributes<HTMLHeadingElement>h2> <JSX.HTMLElementTags.ul: JSX.HTMLAttributes<HTMLUListElement>ul // Assign element to variable via ref callback ref?: HTMLUListElement | ((el: HTMLUListElement) => void) | undefinedref={let list1RefEl: HTMLUListElement | undefinedlist1RefEl} // Assign element directly JSX.HTMLAttributes<T>.class?: string | undefinedclass="list" JSX.HTMLAttributes<HTMLUListElement>.tabindex?: string | number | undefinedtabindex="0" JSX.AriaAttributes.role?: "group" | "list" | "listbox" | "alert" | "alertdialog" | "application" | "article" | "banner" | "button" | "cell" | "checkbox" | "columnheader" | "combobox" | "complementary" | ... 56 more ... | undefinedrole="listbox" JSX.AriaAttributes["aria-labelledby"]?: string | undefined
Identifies the element (or elements) that labels the current element.
@seearia-describedby.
aria-labelledby
="list1-item-heading"
JSX.AriaAttributes["aria-activedescendant"]?: string | undefined
Identifies the currently active element when DOM focus is on a composite widget, textbox, group, or application.
aria-activedescendant
={
const focusedListIndex: () => 0 | 1 | nullfocusedListIndex() === 0 ? const focusedItemId: () => string | undefinedfocusedItemId() : var undefinedundefined } JSX.CustomEventHandlersCamelCase<HTMLUListElement>.onFocus?: JSX.FocusEventHandlerUnion<HTMLUListElement, FocusEvent> | undefinedonFocus={() => const handleListFocus: (listIndex: 0 | 1) => voidhandleListFocus(0)} JSX.CustomEventHandlersCamelCase<HTMLUListElement>.onBlur?: JSX.FocusEventHandlerUnion<HTMLUListElement, FocusEvent> | undefinedonBlur={const handleListBlur: () => voidhandleListBlur} JSX.CustomEventHandlersCamelCase<HTMLUListElement>.onKeyDown?: JSX.EventHandlerUnion<HTMLUListElement, KeyboardEvent, JSX.EventHandler<HTMLUListElement, KeyboardEvent>> | undefinedonKeyDown={(
e: KeyboardEvent & {
    currentTarget: HTMLUListElement;
    target: DOMElement;
}
e
) => const handleListKeydown: (event: KeyboardEvent, listIndex: 0 | 1) => voidhandleListKeydown(
e: KeyboardEvent & {
    currentTarget: HTMLUListElement;
    target: DOMElement;
}
e
, 0)}
> <
function For<T extends readonly any[], U extends JSX.Element>(props: {
    each: T | undefined | null | false;
    fallback?: JSX.Element;
    children: (item: T[number], index: Accessor<number>) => U;
}): JSX.Element
Creates a list elements from a list it receives a map function as its child that receives a list element and an accessor with the index and returns a JSX-Element; if the list is empty, an optional fallback is returned: ```typescript <For each={items} fallback={<div>No items</div>}> {(item, index) => <div data-index={index()}>{item}</div>} </For> ``` If you have a list with fixed indices and changing values, consider using `<Index>` instead.
@descriptionhttps://docs.solidjs.com/reference/components/for
For
each: false | string[] | null | undefinedeach={const items1: () => string[]items1()} fallback?: JSX.Elementfallback={<JSX.HTMLElementTags.li: JSX.LiHTMLAttributes<HTMLLIElement>li JSX.HTMLAttributes<T>.class?: string | undefinedclass="empty-list-message">Empty</JSX.HTMLElementTags.li: JSX.LiHTMLAttributes<HTMLLIElement>li>} > {(item: stringitem, index: Accessor<number>index) => { // Use memos or functions for computed values inside For if needed const const isFocused: () => booleanisFocused = () => const focusedListIndex: () => 0 | 1 | nullfocusedListIndex() === 0 && const focusedItemIndex: () => number | nullfocusedItemIndex() === index: () => numberindex(); const const isSelected: () => booleanisSelected = () => const selectedItem: () => SelectedItem | nullselectedItem()?.SelectedItem.listIndex: 0 | 1 | undefinedlistIndex === 0 && const selectedItem: () => SelectedItem | nullselectedItem()?.SelectedItem.itemIndex: number | undefineditemIndex === index: () => numberindex(); const const itemId: () => stringitemId = () => `list1-item-${item: stringitem}`; return ( <JSX.HTMLElementTags.li: JSX.LiHTMLAttributes<HTMLLIElement>li JSX.HTMLAttributes<T>.id?: string | undefinedid={const itemId: () => stringitemId()} // Use classList directive for dynamic classes
JSX.CustomAttributes<HTMLLIElement>.classList?: {
    [k: string]: boolean | undefined;
} | undefined
classList
={{
item: trueitem: true, "item-focused": const isFocused: () => booleanisFocused(), "item-selected": const isSelected: () => booleanisSelected(), }} JSX.AriaAttributes.role?: "group" | "list" | "listbox" | "alert" | "alertdialog" | "application" | "article" | "banner" | "button" | "cell" | "checkbox" | "columnheader" | "combobox" | "complementary" | ... 56 more ... | undefinedrole="option" JSX.AriaAttributes["aria-selected"]?: boolean | "false" | "true" | undefined
Indicates the current "selected" state of various widgets.
@seearia-checked@seearia-pressed.
aria-selected
={const isFocused: () => booleanisFocused()}
JSX.HTMLAttributes<T>.tabindex?: string | number | undefinedtabindex="-1" > {item: stringitem} </JSX.HTMLElementTags.li: JSX.LiHTMLAttributes<HTMLLIElement>li> ); }} </
function For<T extends readonly any[], U extends JSX.Element>(props: {
    each: T | undefined | null | false;
    fallback?: JSX.Element;
    children: (item: T[number], index: Accessor<number>) => U;
}): JSX.Element
Creates a list elements from a list it receives a map function as its child that receives a list element and an accessor with the index and returns a JSX-Element; if the list is empty, an optional fallback is returned: ```typescript <For each={items} fallback={<div>No items</div>}> {(item, index) => <div data-index={index()}>{item}</div>} </For> ``` If you have a list with fixed indices and changing values, consider using `<Index>` instead.
@descriptionhttps://docs.solidjs.com/reference/components/for
For
>
</JSX.HTMLElementTags.ul: JSX.HTMLAttributes<HTMLUListElement>ul> </JSX.HTMLElementTags.div: JSX.HTMLAttributes<HTMLDivElement>div> {/* List 2 */} <JSX.HTMLElementTags.div: JSX.HTMLAttributes<HTMLDivElement>div JSX.HTMLAttributes<HTMLDivElement>.class?: string | undefinedclass="list-wrapper"> <JSX.HTMLElementTags.h2: JSX.HTMLAttributes<HTMLHeadingElement>h2 JSX.HTMLAttributes<HTMLHeadingElement>.id?: string | undefinedid="list2-item-heading">List 2</JSX.HTMLElementTags.h2: JSX.HTMLAttributes<HTMLHeadingElement>h2> <JSX.HTMLElementTags.ul: JSX.HTMLAttributes<HTMLUListElement>ul ref?: HTMLUListElement | ((el: HTMLUListElement) => void) | undefinedref={let list2RefEl: HTMLUListElement | undefinedlist2RefEl} // Assign element directly JSX.HTMLAttributes<T>.class?: string | undefinedclass="list" JSX.HTMLAttributes<HTMLUListElement>.tabindex?: string | number | undefinedtabindex="0" JSX.AriaAttributes.role?: "group" | "list" | "listbox" | "alert" | "alertdialog" | "application" | "article" | "banner" | "button" | "cell" | "checkbox" | "columnheader" | "combobox" | "complementary" | ... 56 more ... | undefinedrole="listbox" JSX.AriaAttributes["aria-labelledby"]?: string | undefined
Identifies the element (or elements) that labels the current element.
@seearia-describedby.
aria-labelledby
="list2-item-heading"
JSX.AriaAttributes["aria-activedescendant"]?: string | undefined
Identifies the currently active element when DOM focus is on a composite widget, textbox, group, or application.
aria-activedescendant
={
const focusedListIndex: () => 0 | 1 | nullfocusedListIndex() === 1 ? const focusedItemId: () => string | undefinedfocusedItemId() : var undefinedundefined } JSX.CustomEventHandlersCamelCase<HTMLUListElement>.onFocus?: JSX.FocusEventHandlerUnion<HTMLUListElement, FocusEvent> | undefinedonFocus={() => const handleListFocus: (listIndex: 0 | 1) => voidhandleListFocus(1)} JSX.CustomEventHandlersCamelCase<HTMLUListElement>.onBlur?: JSX.FocusEventHandlerUnion<HTMLUListElement, FocusEvent> | undefinedonBlur={const handleListBlur: () => voidhandleListBlur} JSX.CustomEventHandlersCamelCase<HTMLUListElement>.onKeyDown?: JSX.EventHandlerUnion<HTMLUListElement, KeyboardEvent, JSX.EventHandler<HTMLUListElement, KeyboardEvent>> | undefinedonKeyDown={(
e: KeyboardEvent & {
    currentTarget: HTMLUListElement;
    target: DOMElement;
}
e
) => const handleListKeydown: (event: KeyboardEvent, listIndex: 0 | 1) => voidhandleListKeydown(
e: KeyboardEvent & {
    currentTarget: HTMLUListElement;
    target: DOMElement;
}
e
, 1)}
> <
function For<T extends readonly any[], U extends JSX.Element>(props: {
    each: T | undefined | null | false;
    fallback?: JSX.Element;
    children: (item: T[number], index: Accessor<number>) => U;
}): JSX.Element
Creates a list elements from a list it receives a map function as its child that receives a list element and an accessor with the index and returns a JSX-Element; if the list is empty, an optional fallback is returned: ```typescript <For each={items} fallback={<div>No items</div>}> {(item, index) => <div data-index={index()}>{item}</div>} </For> ``` If you have a list with fixed indices and changing values, consider using `<Index>` instead.
@descriptionhttps://docs.solidjs.com/reference/components/for
For
each: false | string[] | null | undefinedeach={const items2: () => string[]items2()} fallback?: JSX.Elementfallback={<JSX.HTMLElementTags.li: JSX.LiHTMLAttributes<HTMLLIElement>li JSX.HTMLAttributes<T>.class?: string | undefinedclass="empty-list-message">Empty</JSX.HTMLElementTags.li: JSX.LiHTMLAttributes<HTMLLIElement>li>} > {(item: stringitem, index: Accessor<number>index) => { const const isFocused: () => booleanisFocused = () => const focusedListIndex: () => 0 | 1 | nullfocusedListIndex() === 1 && const focusedItemIndex: () => number | nullfocusedItemIndex() === index: () => numberindex(); const const isSelected: () => booleanisSelected = () => const selectedItem: () => SelectedItem | nullselectedItem()?.SelectedItem.listIndex: 0 | 1 | undefinedlistIndex === 1 && const selectedItem: () => SelectedItem | nullselectedItem()?.SelectedItem.itemIndex: number | undefineditemIndex === index: () => numberindex(); const const itemId: () => stringitemId = () => `list2-item-${item: stringitem}`; return ( <JSX.HTMLElementTags.li: JSX.LiHTMLAttributes<HTMLLIElement>li JSX.HTMLAttributes<T>.id?: string | undefinedid={const itemId: () => stringitemId()}
JSX.CustomAttributes<HTMLLIElement>.classList?: {
    [k: string]: boolean | undefined;
} | undefined
classList
={{
item: trueitem: true, "item-focused": const isFocused: () => booleanisFocused(), "item-selected": const isSelected: () => booleanisSelected(), }} JSX.AriaAttributes.role?: "group" | "list" | "listbox" | "alert" | "alertdialog" | "application" | "article" | "banner" | "button" | "cell" | "checkbox" | "columnheader" | "combobox" | "complementary" | ... 56 more ... | undefinedrole="option" JSX.AriaAttributes["aria-selected"]?: boolean | "false" | "true" | undefined
Indicates the current "selected" state of various widgets.
@seearia-checked@seearia-pressed.
aria-selected
={const isFocused: () => booleanisFocused()}
JSX.HTMLAttributes<T>.tabindex?: string | number | undefinedtabindex="-1" > {item: stringitem} </JSX.HTMLElementTags.li: JSX.LiHTMLAttributes<HTMLLIElement>li> ); }} </
function For<T extends readonly any[], U extends JSX.Element>(props: {
    each: T | undefined | null | false;
    fallback?: JSX.Element;
    children: (item: T[number], index: Accessor<number>) => U;
}): JSX.Element
Creates a list elements from a list it receives a map function as its child that receives a list element and an accessor with the index and returns a JSX-Element; if the list is empty, an optional fallback is returned: ```typescript <For each={items} fallback={<div>No items</div>}> {(item, index) => <div data-index={index()}>{item}</div>} </For> ``` If you have a list with fixed indices and changing values, consider using `<Index>` instead.
@descriptionhttps://docs.solidjs.com/reference/components/for
For
>
</JSX.HTMLElementTags.ul: JSX.HTMLAttributes<HTMLUListElement>ul> </JSX.HTMLElementTags.div: JSX.HTMLAttributes<HTMLDivElement>div> </JSX.HTMLElementTags.div: JSX.HTMLAttributes<HTMLDivElement>div> {/* Instructions */} <JSX.HTMLElementTags.div: JSX.HTMLAttributes<HTMLDivElement>div JSX.HTMLAttributes<HTMLDivElement>.class?: string | undefinedclass="instructions"> <JSX.HTMLElementTags.h3: JSX.HTMLAttributes<HTMLHeadingElement>h3>Keyboard Instructions</JSX.HTMLElementTags.h3: JSX.HTMLAttributes<HTMLHeadingElement>h3> <JSX.HTMLElementTags.ul: JSX.HTMLAttributes<HTMLUListElement>ul> <JSX.HTMLElementTags.li: JSX.LiHTMLAttributes<HTMLLIElement>li> Use <JSX.HTMLElementTags.kbd: JSX.HTMLAttributes<HTMLElement>kbd>Tab</JSX.HTMLElementTags.kbd: JSX.HTMLAttributes<HTMLElement>kbd> or <JSX.HTMLElementTags.kbd: JSX.HTMLAttributes<HTMLElement>kbd>Shift+Tab</JSX.HTMLElementTags.kbd: JSX.HTMLAttributes<HTMLElement>kbd> to focus a list. </JSX.HTMLElementTags.li: JSX.LiHTMLAttributes<HTMLLIElement>li> <JSX.HTMLElementTags.li: JSX.LiHTMLAttributes<HTMLLIElement>li> Use <JSX.HTMLElementTags.kbd: JSX.HTMLAttributes<HTMLElement>kbd>↑</JSX.HTMLElementTags.kbd: JSX.HTMLAttributes<HTMLElement>kbd> / <JSX.HTMLElementTags.kbd: JSX.HTMLAttributes<HTMLElement>kbd>↓</JSX.HTMLElementTags.kbd: JSX.HTMLAttributes<HTMLElement>kbd> arrows to navigate items within the focused list. </JSX.HTMLElementTags.li: JSX.LiHTMLAttributes<HTMLLIElement>li> <JSX.HTMLElementTags.li: JSX.LiHTMLAttributes<HTMLLIElement>li> Press <JSX.HTMLElementTags.kbd: JSX.HTMLAttributes<HTMLElement>kbd>Spacebar</JSX.HTMLElementTags.kbd: JSX.HTMLAttributes<HTMLElement>kbd> to select/deselect the highlighted item for moving. </JSX.HTMLElementTags.li: JSX.LiHTMLAttributes<HTMLLIElement>li> <JSX.HTMLElementTags.li: JSX.LiHTMLAttributes<HTMLLIElement>li> With an item selected, use <JSX.HTMLElementTags.kbd: JSX.HTMLAttributes<HTMLElement>kbd>↑</JSX.HTMLElementTags.kbd: JSX.HTMLAttributes<HTMLElement>kbd> / <JSX.HTMLElementTags.kbd: JSX.HTMLAttributes<HTMLElement>kbd>↓</JSX.HTMLElementTags.kbd: JSX.HTMLAttributes<HTMLElement>kbd> (within the same or another focused list) to choose the drop position. </JSX.HTMLElementTags.li: JSX.LiHTMLAttributes<HTMLLIElement>li> <JSX.HTMLElementTags.li: JSX.LiHTMLAttributes<HTMLLIElement>li> Press <JSX.HTMLElementTags.kbd: JSX.HTMLAttributes<HTMLElement>kbd>Enter</JSX.HTMLElementTags.kbd: JSX.HTMLAttributes<HTMLElement>kbd> to drop the selected item at the highlighted position. </JSX.HTMLElementTags.li: JSX.LiHTMLAttributes<HTMLLIElement>li> <JSX.HTMLElementTags.li: JSX.LiHTMLAttributes<HTMLLIElement>li> Press <JSX.HTMLElementTags.kbd: JSX.HTMLAttributes<HTMLElement>kbd>Escape</JSX.HTMLElementTags.kbd: JSX.HTMLAttributes<HTMLElement>kbd> to cancel a selection or leave the list. </JSX.HTMLElementTags.li: JSX.LiHTMLAttributes<HTMLLIElement>li> </JSX.HTMLElementTags.ul: JSX.HTMLAttributes<HTMLUListElement>ul> </JSX.HTMLElementTags.div: JSX.HTMLAttributes<HTMLDivElement>div> </JSX.HTMLElementTags.div: JSX.HTMLAttributes<HTMLDivElement>div> {/* Styles needed externally */} </JSX.HTMLElementTags.div: JSX.HTMLAttributes<HTMLDivElement>div> ); }
import { function dragAndDrop<T>({ parent, getValues, setValues, config, }: DragAndDrop<T>): void
Initializes the drag and drop functionality for a given parent.
@paramdragAndDrop - The drag and drop configuration.@returnsvoid
dragAndDrop
} from "@formkit/drag-and-drop";
import type { interface DragstartEventData<T>DragstartEventData, interface SortEventData<T>SortEventData, interface TransferEventData<T>TransferEventData, interface DragendEventData<T>DragendEventData, } from "@formkit/drag-and-drop"; // --- State Management --- let let items1: string[]items1 = ["Apples", "Bananas", "Oranges", "Grapes"]; let let items2: string[]items2 = ["Milk", "Cheese", "Yogurt"]; let let focusedListIndex: 0 | 1 | nullfocusedListIndex: 0 | 1 | null = null; let let focusedItemIndex: number | nullfocusedItemIndex: number | null = null; let
let selectedItem: {
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
} | null
selectedItem
: {
listIndex: 0 | 1listIndex: 0 | 1; itemIndex: numberitemIndex: number; value: stringvalue: string; } | null = null; let let liveMessage: stringliveMessage = ""; // --- DOM References (Assume these elements exist in the HTML) --- const const list1Element: HTMLUListElementlist1Element = var document: Document
[MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/document)
document
.Document.getElementById(elementId: string): HTMLElement | null
Returns a reference to the first object with the specified value of the ID attribute.
@paramelementId String that specifies the ID value.
getElementById
("list1") as HTMLUListElement;
const const list2Element: HTMLUListElementlist2Element = var document: Document
[MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/document)
document
.Document.getElementById(elementId: string): HTMLElement | null
Returns a reference to the first object with the specified value of the ID attribute.
@paramelementId String that specifies the ID value.
getElementById
("list2") as HTMLUListElement;
const const liveRegionElement: HTMLDivElementliveRegionElement = var document: Document
[MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/document)
document
.Document.getElementById(elementId: string): HTMLElement | null
Returns a reference to the first object with the specified value of the ID attribute.
@paramelementId String that specifies the ID value.
getElementById
(
"live-region" ) as HTMLDivElement; if (!const list1Element: HTMLUListElementlist1Element || !const list2Element: HTMLUListElementlist2Element || !const liveRegionElement: HTMLDivElementliveRegionElement) { var console: Console
The `console` module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers. The module exports two specific components: * A `Console` class with methods such as `console.log()`, `console.error()` and `console.warn()` that can be used to write to any Node.js stream. * A global `console` instance configured to write to [`process.stdout`](https://nodejs.org/docs/latest-v18.x/api/process.html#processstdout) and [`process.stderr`](https://nodejs.org/docs/latest-v18.x/api/process.html#processstderr). The global `console` can be used without importing the `node:console` module. _**Warning**_: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the [`note on process I/O`](https://nodejs.org/docs/latest-v18.x/api/process.html#a-note-on-process-io) for more information. Example using the global `console`: ```js console.log('hello world'); // Prints: hello world, to stdout console.log('hello %s', 'world'); // Prints: hello world, to stdout console.error(new Error('Whoops, something bad happened')); // Prints error message and stack trace to stderr: // Error: Whoops, something bad happened // at [eval]:5:15 // at Script.runInThisContext (node:vm:132:18) // at Object.runInThisContext (node:vm:309:38) // at node:internal/process/execution:77:19 // at [eval]-wrapper:6:22 // at evalScript (node:internal/process/execution:76:60) // at node:internal/main/eval_string:23:3 const name = 'Will Robinson'; console.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to stderr ``` Example using the `Console` class: ```js const out = getStreamSomehow(); const err = getStreamSomehow(); const myConsole = new console.Console(out, err); myConsole.log('hello world'); // Prints: hello world, to out myConsole.log('hello %s', 'world'); // Prints: hello world, to out myConsole.error(new Error('Whoops, something bad happened')); // Prints: [Error: Whoops, something bad happened], to err const name = 'Will Robinson'; myConsole.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to err ```
@see[source](https://github.com/nodejs/node/blob/v18.19.1/lib/console.js)
console
.Console.error(message?: any, ...optionalParams: any[]): void (+1 overload)
Prints to `stderr` with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to [`printf(3)`](http://man7.org/linux/man-pages/man3/printf.3.html) (the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v18.x/api/util.html#utilformatformat-args)). ```js const code = 5; console.error('error #%d', code); // Prints: error #5, to stderr console.error('error', code); // Prints: error 5, to stderr ``` If formatting elements (e.g. `%d`) are not found in the first string then [`util.inspect()`](https://nodejs.org/docs/latest-v18.x/api/util.html#utilinspectobject-options) is called on each argument and the resulting string values are concatenated. See [`util.format()`](https://nodejs.org/docs/latest-v18.x/api/util.html#utilformatformat-args) for more information.
@sincev0.1.100
error
("Required DOM elements not found for accessibility demo.");
// Handle the error appropriately, maybe return or throw } const
const lists: {
    el: HTMLUListElement;
    items: () => string[];
    setItems: (newItems: string[]) => void;
    idPrefix: string;
    name: string;
}[]
lists
= [
{ el: HTMLUListElementel: const list1Element: HTMLUListElementlist1Element, items: () => string[]items: () => let items1: string[]items1, setItems: (newItems: string[]) => voidsetItems: (newItems: string[]newItems: string[]) => { let items1: string[]items1 = newItems: string[]newItems; }, idPrefix: stringidPrefix: "list1-item", name: stringname: "List 1", }, { el: HTMLUListElementel: const list2Element: HTMLUListElementlist2Element, items: () => string[]items: () => let items2: string[]items2, setItems: (newItems: string[]) => voidsetItems: (newItems: string[]newItems: string[]) => { let items2: string[]items2 = newItems: string[]newItems; }, idPrefix: stringidPrefix: "list2-item", name: stringname: "List 2", }, ]; // --- ARIA Live Region --- function function announce(message: string): voidannounce(message: stringmessage: string) { let liveMessage: stringliveMessage = message: stringmessage; if (const liveRegionElement: HTMLDivElementliveRegionElement) { const liveRegionElement: HTMLDivElementliveRegionElement.Node.textContent: string | null
[MDN Reference](https://developer.mozilla.org/docs/Web/API/Node/textContent)
textContent
= let liveMessage: stringliveMessage;
} // Optional: Clear message after delay // setTimeout(() => { if (liveRegionElement) liveRegionElement.textContent = ''; }, 5000); } // --- Rendering --- function function renderList(listIndex: 0 | 1): voidrenderList(listIndex: 0 | 1listIndex: 0 | 1) { const
const listData: {
    el: HTMLUListElement;
    items: () => string[];
    setItems: (newItems: string[]) => void;
    idPrefix: string;
    name: string;
}
listData
=
const lists: {
    el: HTMLUListElement;
    items: () => string[];
    setItems: (newItems: string[]) => void;
    idPrefix: string;
    name: string;
}[]
lists
[listIndex: 0 | 1listIndex];
if (!
const listData: {
    el: HTMLUListElement;
    items: () => string[];
    setItems: (newItems: string[]) => void;
    idPrefix: string;
    name: string;
}
listData
|| !
const listData: {
    el: HTMLUListElement;
    items: () => string[];
    setItems: (newItems: string[]) => void;
    idPrefix: string;
    name: string;
}
listData
.el: HTMLUListElementel) return;
const const currentItems: string[]currentItems =
const listData: {
    el: HTMLUListElement;
    items: () => string[];
    setItems: (newItems: string[]) => void;
    idPrefix: string;
    name: string;
}
listData
.items: () => string[]items();
const listData: {
    el: HTMLUListElement;
    items: () => string[];
    setItems: (newItems: string[]) => void;
    idPrefix: string;
    name: string;
}
listData
.el: HTMLUListElementel.Element.innerHTML: string
[MDN Reference](https://developer.mozilla.org/docs/Web/API/Element/innerHTML)
innerHTML
= ""; // Clear existing items
if (const currentItems: string[]currentItems.Array<string>.length: number
Gets or sets the length of the array. This is a number one higher than the highest index in the array.
length
=== 0) {
const const li: HTMLLIElementli = var document: Document
[MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/document)
document
.Document.createElement<"li">(tagName: "li", options?: ElementCreationOptions): HTMLLIElement (+2 overloads)
Creates an instance of the element for the specified tag.
@paramtagName The name of an element. [MDN Reference](https://developer.mozilla.org/docs/Web/API/Document/createElement)
createElement
("li");
const li: HTMLLIElementli.Element.className: string
Returns the value of element's class content attribute. Can be set to change it. [MDN Reference](https://developer.mozilla.org/docs/Web/API/Element/className)
className
= "empty-list-message";
const li: HTMLLIElementli.Node.textContent: string | null
[MDN Reference](https://developer.mozilla.org/docs/Web/API/Node/textContent)
textContent
= "Empty";
const listData: {
    el: HTMLUListElement;
    items: () => string[];
    setItems: (newItems: string[]) => void;
    idPrefix: string;
    name: string;
}
listData
.el: HTMLUListElementel.Node.appendChild<HTMLLIElement>(node: HTMLLIElement): HTMLLIElement
[MDN Reference](https://developer.mozilla.org/docs/Web/API/Node/appendChild)
appendChild
(const li: HTMLLIElementli);
// Clear active descendant when list is empty
const listData: {
    el: HTMLUListElement;
    items: () => string[];
    setItems: (newItems: string[]) => void;
    idPrefix: string;
    name: string;
}
listData
.el: HTMLUListElementel.Element.removeAttribute(qualifiedName: string): void
Removes element's first attribute whose qualified name is qualifiedName. [MDN Reference](https://developer.mozilla.org/docs/Web/API/Element/removeAttribute)
removeAttribute
("aria-activedescendant");
return; } const currentItems: string[]currentItems.Array<string>.forEach(callbackfn: (value: string, index: number, array: string[]) => void, thisArg?: any): void
Performs the specified action for each element in an array.
@paramcallbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array.@paramthisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
forEach
((item: stringitem, index: numberindex) => {
const const li: HTMLLIElementli = var document: Document
[MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/document)
document
.Document.createElement<"li">(tagName: "li", options?: ElementCreationOptions): HTMLLIElement (+2 overloads)
Creates an instance of the element for the specified tag.
@paramtagName The name of an element. [MDN Reference](https://developer.mozilla.org/docs/Web/API/Document/createElement)
createElement
("li");
const const itemId: stringitemId = `${
const listData: {
    el: HTMLUListElement;
    items: () => string[];
    setItems: (newItems: string[]) => void;
    idPrefix: string;
    name: string;
}
listData
.idPrefix: stringidPrefix}-${item: stringitem}`; // Consider making IDs more robust if items can have same name
const li: HTMLLIElementli.Element.id: string
Returns the value of element's id content attribute. Can be set to change it. [MDN Reference](https://developer.mozilla.org/docs/Web/API/Element/id)
id
= const itemId: stringitemId;
const li: HTMLLIElementli.Element.className: string
Returns the value of element's class content attribute. Can be set to change it. [MDN Reference](https://developer.mozilla.org/docs/Web/API/Element/className)
className
= "item";
const li: HTMLLIElementli.Element.setAttribute(qualifiedName: string, value: string): void
Sets the value of element's first attribute whose qualified name is qualifiedName to value. [MDN Reference](https://developer.mozilla.org/docs/Web/API/Element/setAttribute)
setAttribute
("role", "option");
const li: HTMLLIElementli.Element.setAttribute(qualifiedName: string, value: string): void
Sets the value of element's first attribute whose qualified name is qualifiedName to value. [MDN Reference](https://developer.mozilla.org/docs/Web/API/Element/setAttribute)
setAttribute
("tabindex", "-1"); // Items are not directly tabbable
const li: HTMLLIElementli.Node.textContent: string | null
[MDN Reference](https://developer.mozilla.org/docs/Web/API/Node/textContent)
textContent
= item: stringitem;
const const isFocused: booleanisFocused = let focusedListIndex: 0 | 1 | nullfocusedListIndex === listIndex: 0 | 1listIndex && let focusedItemIndex: number | nullfocusedItemIndex === index: numberindex; const const isSelected: booleanisSelected =
let selectedItem: {
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
} | null
selectedItem
?.listIndex: 0 | 1 | undefinedlistIndex === listIndex: 0 | 1listIndex &&
let selectedItem: {
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
}
selectedItem
?.itemIndex: numberitemIndex === index: numberindex;
const li: HTMLLIElementli.Element.setAttribute(qualifiedName: string, value: string): void
Sets the value of element's first attribute whose qualified name is qualifiedName to value. [MDN Reference](https://developer.mozilla.org/docs/Web/API/Element/setAttribute)
setAttribute
("aria-selected",
var String: StringConstructor
(value?: any) => string
Allows manipulation and formatting of text strings and determination and location of substrings within strings.
String
(const isFocused: booleanisFocused)); // Reflect focus state
if (const isFocused: booleanisFocused) { const li: HTMLLIElementli.Element.classList: DOMTokenList
Allows for manipulation of element's class content attribute as a set of whitespace-separated tokens through a DOMTokenList object. [MDN Reference](https://developer.mozilla.org/docs/Web/API/Element/classList)
classList
.DOMTokenList.add(...tokens: string[]): void
Adds all arguments passed, except those already present. Throws a "SyntaxError" DOMException if one of the arguments is the empty string. Throws an "InvalidCharacterError" DOMException if one of the arguments contains any ASCII whitespace. [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMTokenList/add)
add
("item-focused");
} else { const li: HTMLLIElementli.Element.classList: DOMTokenList
Allows for manipulation of element's class content attribute as a set of whitespace-separated tokens through a DOMTokenList object. [MDN Reference](https://developer.mozilla.org/docs/Web/API/Element/classList)
classList
.DOMTokenList.remove(...tokens: string[]): void
Removes arguments passed, if they are present. Throws a "SyntaxError" DOMException if one of the arguments is the empty string. Throws an "InvalidCharacterError" DOMException if one of the arguments contains any ASCII whitespace. [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMTokenList/remove)
remove
("item-focused");
} if (const isSelected: booleanisSelected) { const li: HTMLLIElementli.Element.classList: DOMTokenList
Allows for manipulation of element's class content attribute as a set of whitespace-separated tokens through a DOMTokenList object. [MDN Reference](https://developer.mozilla.org/docs/Web/API/Element/classList)
classList
.DOMTokenList.add(...tokens: string[]): void
Adds all arguments passed, except those already present. Throws a "SyntaxError" DOMException if one of the arguments is the empty string. Throws an "InvalidCharacterError" DOMException if one of the arguments contains any ASCII whitespace. [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMTokenList/add)
add
("item-selected");
} else { const li: HTMLLIElementli.Element.classList: DOMTokenList
Allows for manipulation of element's class content attribute as a set of whitespace-separated tokens through a DOMTokenList object. [MDN Reference](https://developer.mozilla.org/docs/Web/API/Element/classList)
classList
.DOMTokenList.remove(...tokens: string[]): void
Removes arguments passed, if they are present. Throws a "SyntaxError" DOMException if one of the arguments is the empty string. Throws an "InvalidCharacterError" DOMException if one of the arguments contains any ASCII whitespace. [MDN Reference](https://developer.mozilla.org/docs/Web/API/DOMTokenList/remove)
remove
("item-selected");
}
const listData: {
    el: HTMLUListElement;
    items: () => string[];
    setItems: (newItems: string[]) => void;
    idPrefix: string;
    name: string;
}
listData
.el: HTMLUListElementel.Node.appendChild<HTMLLIElement>(node: HTMLLIElement): HTMLLIElement
[MDN Reference](https://developer.mozilla.org/docs/Web/API/Node/appendChild)
appendChild
(const li: HTMLLIElementli);
}); // Update aria-activedescendant on the list itself if ( let focusedListIndex: 0 | 1 | nullfocusedListIndex === listIndex: 0 | 1listIndex && let focusedItemIndex: number | nullfocusedItemIndex !== null && let focusedItemIndex: numberfocusedItemIndex < const currentItems: string[]currentItems.Array<string>.length: number
Gets or sets the length of the array. This is a number one higher than the highest index in the array.
length
) { const const activeDescendantId: stringactiveDescendantId = `${
const listData: {
    el: HTMLUListElement;
    items: () => string[];
    setItems: (newItems: string[]) => void;
    idPrefix: string;
    name: string;
}
listData
.idPrefix: stringidPrefix}-${const currentItems: string[]currentItems[let focusedItemIndex: numberfocusedItemIndex]}`;
const listData: {
    el: HTMLUListElement;
    items: () => string[];
    setItems: (newItems: string[]) => void;
    idPrefix: string;
    name: string;
}
listData
.el: HTMLUListElementel.Element.setAttribute(qualifiedName: string, value: string): void
Sets the value of element's first attribute whose qualified name is qualifiedName to value. [MDN Reference](https://developer.mozilla.org/docs/Web/API/Element/setAttribute)
setAttribute
("aria-activedescendant", const activeDescendantId: stringactiveDescendantId);
} else {
const listData: {
    el: HTMLUListElement;
    items: () => string[];
    setItems: (newItems: string[]) => void;
    idPrefix: string;
    name: string;
}
listData
.el: HTMLUListElementel.Element.removeAttribute(qualifiedName: string): void
Removes element's first attribute whose qualified name is qualifiedName. [MDN Reference](https://developer.mozilla.org/docs/Web/API/Element/removeAttribute)
removeAttribute
("aria-activedescendant");
} } // --- Drag and Drop Initialization --- dragAndDrop<string>({ parent, getValues, setValues, config, }: DragAndDrop<string>): void
Initializes the drag and drop functionality for a given parent.
@paramdragAndDrop - The drag and drop configuration.@returnsvoid
dragAndDrop
<string>({
// List 1 DragAndDrop<string>.parent: HTMLElement
The parent element that will contain the draggable nodes.
parent
: const list1Element: HTMLUListElementlist1Element,
DragAndDrop<string>.getValues: (parent: HTMLElement) => string[]
A function that returns the values assigned to the parent.
getValues
: () => let items1: string[]items1,
DragAndDrop<string>.setValues: (values: string[], parent: HTMLElement) => void
A function that sets the values assigned to the parent.
setValues
: (newValues: string[]newValues) => {
let items1: string[]items1 = newValues: string[]newValues; function renderList(listIndex: 0 | 1): voidrenderList(0); // If items were potentially transferred from list 2, ensure it's re-rendered // Note: The library should ideally handle calling setValues on the source list too. // If it doesn't reliably, we might need a flag or check here. // For simplicity, we assume the library calls setValues on both lists involved in a transfer. }, DragAndDrop<string>.config?: Partial<ParentConfig<string>> | undefined
An optional configuration object.
config
: {
group?: string | undefined
The group that the parent belongs to. This is used for allowing multiple parents to transfer nodes between each other.
group
: "accessibleList",
onDragstart?: DragstartEvent | undefined
Fired when a drag is started, whether native drag or synthetic
onDragstart
: (state: DragstartEventData<T>state) =>
function announce(message: string): voidannounce(`Drag started for ${state: DragstartEventData<T>state.DragstartEventData<T>.draggedNode: NodeRecord<T>draggedNode.NodeRecord<T>.data: NodeData<T>data.NodeData<T>.value: T
The value of the node.
value
}.`),
onSort?: SortEvent | undefined
Callback function for when a sort operation is performed.
onSort
: (event: SortEventData<T>event) =>
function announce(message: string): voidannounce( `Sorted ${event: SortEventData<T>event.SortEventData<T>.draggedNodes: NodeRecord<T>[]draggedNodes[0].NodeRecord<T>.data: NodeData<T>data.NodeData<T>.value: T
The value of the node.
value
} in List 1 to position ${
event: SortEventData<T>event.SortEventData<T>.position: numberposition + 1 }.` ), onTransfer?: TransferEvent | undefined
Callback function for when a transfer operation is performed.
onTransfer
: (event: TransferEventData<T>event) => {
function announce(message: string): voidannounce( `Transferred ${event: TransferEventData<T>event.TransferEventData<T>.draggedNodes: NodeRecord<T>[]draggedNodes[0].NodeRecord<T>.data: NodeData<T>data.NodeData<T>.value: T
The value of the node.
value
} from List ${
event: TransferEventData<T>event.TransferEventData<T>.sourceParent: ParentRecord<T>sourceParent.ParentRecord<T>.el: HTMLElementel === const list1Element: HTMLUListElementlist1Element ? 1 : 2 } to List 1 at position ${event: TransferEventData<T>event.TransferEventData<T>.targetIndex: numbertargetIndex + 1}.` ); // Since setValues in the target (list 1) already re-renders list 1, // and we assume the lib calls setValues on source (list 2), list 2 should also re-render. }, onDragend?: DragendEvent | undefined
Fired when a drag is ended, whether native drag or synthetic
onDragend
: (state: DragendEventData<T>state) =>
function announce(message: string): voidannounce(`Drag ended for ${state: DragendEventData<T>state.DragendEventData<T>.draggedNode: NodeRecord<T>draggedNode.NodeRecord<T>.data: NodeData<T>data.NodeData<T>.value: T
The value of the node.
value
}.`),
}, }); dragAndDrop<string>({ parent, getValues, setValues, config, }: DragAndDrop<string>): void
Initializes the drag and drop functionality for a given parent.
@paramdragAndDrop - The drag and drop configuration.@returnsvoid
dragAndDrop
<string>({
// List 2 DragAndDrop<string>.parent: HTMLElement
The parent element that will contain the draggable nodes.
parent
: const list2Element: HTMLUListElementlist2Element,
DragAndDrop<string>.getValues: (parent: HTMLElement) => string[]
A function that returns the values assigned to the parent.
getValues
: () => let items2: string[]items2,
DragAndDrop<string>.setValues: (values: string[], parent: HTMLElement) => void
A function that sets the values assigned to the parent.
setValues
: (newValues: string[]newValues) => {
let items2: string[]items2 = newValues: string[]newValues; function renderList(listIndex: 0 | 1): voidrenderList(1); }, DragAndDrop<string>.config?: Partial<ParentConfig<string>> | undefined
An optional configuration object.
config
: {
group?: string | undefined
The group that the parent belongs to. This is used for allowing multiple parents to transfer nodes between each other.
group
: "accessibleList",
onDragstart?: DragstartEvent | undefined
Fired when a drag is started, whether native drag or synthetic
onDragstart
: (state: DragstartEventData<T>state) =>
function announce(message: string): voidannounce(`Drag started for ${state: DragstartEventData<T>state.DragstartEventData<T>.draggedNode: NodeRecord<T>draggedNode.NodeRecord<T>.data: NodeData<T>data.NodeData<T>.value: T
The value of the node.
value
}.`),
onSort?: SortEvent | undefined
Callback function for when a sort operation is performed.
onSort
: (event: SortEventData<T>event) =>
function announce(message: string): voidannounce( `Sorted ${event: SortEventData<T>event.SortEventData<T>.draggedNodes: NodeRecord<T>[]draggedNodes[0].NodeRecord<T>.data: NodeData<T>data.NodeData<T>.value: T
The value of the node.
value
} in List 2 to position ${
event: SortEventData<T>event.SortEventData<T>.position: numberposition + 1 }.` ), onTransfer?: TransferEvent | undefined
Callback function for when a transfer operation is performed.
onTransfer
: (event: TransferEventData<T>event) => {
function announce(message: string): voidannounce( `Transferred ${event: TransferEventData<T>event.TransferEventData<T>.draggedNodes: NodeRecord<T>[]draggedNodes[0].NodeRecord<T>.data: NodeData<T>data.NodeData<T>.value: T
The value of the node.
value
} from List ${
event: TransferEventData<T>event.TransferEventData<T>.sourceParent: ParentRecord<T>sourceParent.ParentRecord<T>.el: HTMLElementel === const list1Element: HTMLUListElementlist1Element ? 1 : 2 } to List 2 at position ${event: TransferEventData<T>event.TransferEventData<T>.targetIndex: numbertargetIndex + 1}.` ); // Assume setValues on source (list 1) handles its re-render. }, onDragend?: DragendEvent | undefined
Fired when a drag is ended, whether native drag or synthetic
onDragend
: (state: DragendEventData<T>state) =>
function announce(message: string): voidannounce(`Drag ended for ${state: DragendEventData<T>state.DragendEventData<T>.draggedNode: NodeRecord<T>draggedNode.NodeRecord<T>.data: NodeData<T>data.NodeData<T>.value: T
The value of the node.
value
}.`),
}, }); // --- Event Handlers --- function function handleFocus(listIndex: 0 | 1): voidhandleFocus(listIndex: 0 | 1listIndex: 0 | 1) { let focusedListIndex: 0 | 1 | nullfocusedListIndex = listIndex: 0 | 1listIndex; const const currentItems: string[]currentItems =
const lists: {
    el: HTMLUListElement;
    items: () => string[];
    setItems: (newItems: string[]) => void;
    idPrefix: string;
    name: string;
}[]
lists
[listIndex: 0 | 1listIndex].items: () => string[]items();
if (let focusedItemIndex: number | nullfocusedItemIndex === null && const currentItems: string[]currentItems.Array<string>.length: number
Gets or sets the length of the array. This is a number one higher than the highest index in the array.
length
> 0) {
let focusedItemIndex: number | nullfocusedItemIndex = 0; // Default to first item on focus } function announce(message: string): voidannounce( `List ${listIndex: 0 | 1listIndex + 1} focused. Use up and down arrows to navigate items.` ); function renderList(listIndex: 0 | 1): voidrenderList(listIndex: 0 | 1listIndex); // Update focused list visuals // Render the other list to remove potential old focus styles function renderList(listIndex: 0 | 1): voidrenderList(listIndex: 0 | 1listIndex === 0 ? 1 : 0); } function function handleBlur(event: FocusEvent, listIndex: 0 | 1): voidhandleBlur(event: FocusEventevent: FocusEvent, listIndex: 0 | 1listIndex: 0 | 1) { // Simple blur handling: Reset focus only if focus moves outside the component entirely. // A more robust solution might involve checking relatedTarget against a container element. // For this example, we'll reset if focus leaves the list element itself. const const listElement: HTMLUListElementlistElement =
const lists: {
    el: HTMLUListElement;
    items: () => string[];
    setItems: (newItems: string[]) => void;
    idPrefix: string;
    name: string;
}[]
lists
[listIndex: 0 | 1listIndex].el: HTMLUListElementel;
// Check if relatedTarget is null or outside the current list element if ( !event: FocusEventevent.FocusEvent.relatedTarget: EventTarget | null
[MDN Reference](https://developer.mozilla.org/docs/Web/API/FocusEvent/relatedTarget)
relatedTarget
||
(event: FocusEventevent.FocusEvent.relatedTarget: EventTarget
[MDN Reference](https://developer.mozilla.org/docs/Web/API/FocusEvent/relatedTarget)
relatedTarget
instanceof
var Node: {
    new (): Node;
    prototype: Node;
    readonly ELEMENT_NODE: 1;
    readonly ATTRIBUTE_NODE: 2;
    readonly TEXT_NODE: 3;
    readonly CDATA_SECTION_NODE: 4;
    readonly ENTITY_REFERENCE_NODE: 5;
    readonly ENTITY_NODE: 6;
    ... 11 more ...;
    readonly DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC: 32;
}
Node is an interface from which a number of DOM API object types inherit. It allows those types to be treated similarly; for example, inheriting the same set of methods, or being tested in the same way. [MDN Reference](https://developer.mozilla.org/docs/Web/API/Node)
Node
&&
!const listElement: HTMLUListElementlistElement.Node.contains(other: Node | null): boolean
Returns true if other is an inclusive descendant of node, and false otherwise. [MDN Reference](https://developer.mozilla.org/docs/Web/API/Node/contains)
contains
(event: FocusEventevent.FocusEvent.relatedTarget: Node
[MDN Reference](https://developer.mozilla.org/docs/Web/API/FocusEvent/relatedTarget)
relatedTarget
))
) { // Check if focus moved to the *other* list, if so, handleFocus will manage it. const const otherListIndex: 0 | 1otherListIndex = listIndex: 0 | 1listIndex === 0 ? 1 : 0; const const otherListElement: HTMLUListElementotherListElement =
const lists: {
    el: HTMLUListElement;
    items: () => string[];
    setItems: (newItems: string[]) => void;
    idPrefix: string;
    name: string;
}[]
lists
[const otherListIndex: 0 | 1otherListIndex].el: HTMLUListElementel;
if (event: FocusEventevent.FocusEvent.relatedTarget: Node | null
[MDN Reference](https://developer.mozilla.org/docs/Web/API/FocusEvent/relatedTarget)
relatedTarget
!== const otherListElement: HTMLUListElementotherListElement) {
let focusedListIndex: 0 | 1 | nullfocusedListIndex = null; let focusedItemIndex: number | nullfocusedItemIndex = null; // Don't announce blur unless necessary, can be noisy // announce("List blurred."); function renderList(listIndex: 0 | 1): voidrenderList(listIndex: 0 | 1listIndex); // Re-render to remove focus styles } } } function function handleKeydown(event: KeyboardEvent, listIndex: 0 | 1): voidhandleKeydown(event: KeyboardEventevent: KeyboardEvent, listIndex: 0 | 1listIndex: 0 | 1) { if (let focusedListIndex: 0 | 1 | nullfocusedListIndex !== listIndex: 0 | 1listIndex) return; const const currentItems: string[]currentItems =
const lists: {
    el: HTMLUListElement;
    items: () => string[];
    setItems: (newItems: string[]) => void;
    idPrefix: string;
    name: string;
}[]
lists
[listIndex: 0 | 1listIndex].items: () => string[]items();
let let currentItemIndex: number | nullcurrentItemIndex = let focusedItemIndex: number | nullfocusedItemIndex; // Use local var for modifications switch (event: KeyboardEventevent.KeyboardEvent.key: string
[MDN Reference](https://developer.mozilla.org/docs/Web/API/KeyboardEvent/key)
key
) {
case "ArrowDown": case "ArrowUp": event: KeyboardEventevent.Event.preventDefault(): void
If invoked when the cancelable attribute value is true, and while executing a listener for the event with passive set to false, signals to the operation that caused event to be dispatched that it needs to be canceled. [MDN Reference](https://developer.mozilla.org/docs/Web/API/Event/preventDefault)
preventDefault
();
if (const currentItems: string[]currentItems.Array<string>.length: number
Gets or sets the length of the array. This is a number one higher than the highest index in the array.
length
> 0) {
let let nextIndex: anynextIndex; if (event: KeyboardEventevent.KeyboardEvent.key: "ArrowDown" | "ArrowUp"
[MDN Reference](https://developer.mozilla.org/docs/Web/API/KeyboardEvent/key)
key
=== "ArrowDown") {
let nextIndex: anynextIndex = let currentItemIndex: number | nullcurrentItemIndex === null ? 0 : (let currentItemIndex: numbercurrentItemIndex + 1) % const currentItems: string[]currentItems.Array<string>.length: number
Gets or sets the length of the array. This is a number one higher than the highest index in the array.
length
;
} else { // ArrowUp let nextIndex: anynextIndex = let currentItemIndex: number | nullcurrentItemIndex === null ? const currentItems: string[]currentItems.Array<string>.length: number
Gets or sets the length of the array. This is a number one higher than the highest index in the array.
length
- 1
: (let currentItemIndex: numbercurrentItemIndex - 1 + const currentItems: string[]currentItems.Array<string>.length: number
Gets or sets the length of the array. This is a number one higher than the highest index in the array.
length
) %
const currentItems: string[]currentItems.Array<string>.length: number
Gets or sets the length of the array. This is a number one higher than the highest index in the array.
length
;
} let focusedItemIndex: number | nullfocusedItemIndex = let nextIndex: numbernextIndex; // Update state function announce(message: string): voidannounce(const currentItems: string[]currentItems[let nextIndex: numbernextIndex]); function renderList(listIndex: 0 | 1): voidrenderList(listIndex: 0 | 1listIndex); // Re-render to update focus style and aria-activedescendant } break; case " ": // Spacebar event: KeyboardEventevent.Event.preventDefault(): void
If invoked when the cancelable attribute value is true, and while executing a listener for the event with passive set to false, signals to the operation that caused event to be dispatched that it needs to be canceled. [MDN Reference](https://developer.mozilla.org/docs/Web/API/Event/preventDefault)
preventDefault
();
if ( let currentItemIndex: number | nullcurrentItemIndex !== null && let currentItemIndex: numbercurrentItemIndex >= 0 && let currentItemIndex: numbercurrentItemIndex < const currentItems: string[]currentItems.Array<string>.length: number
Gets or sets the length of the array. This is a number one higher than the highest index in the array.
length
) { const const currentItemValue: stringcurrentItemValue = const currentItems: string[]currentItems[let currentItemIndex: numbercurrentItemIndex]; if (
let selectedItem: {
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
} | null
selectedItem
?.listIndex: 0 | 1 | undefinedlistIndex === listIndex: 0 | 1listIndex &&
let selectedItem: {
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
}
selectedItem
?.itemIndex: numberitemIndex === let currentItemIndex: numbercurrentItemIndex
) {
let selectedItem: {
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
} | null
selectedItem
= null; // Deselect
function announce(message: string): voidannounce(`${const currentItemValue: stringcurrentItemValue} deselected.`); } else {
let selectedItem: {
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
} | null
selectedItem
= {
listIndex: 0 | 1listIndex, itemIndex: numberitemIndex: let currentItemIndex: numbercurrentItemIndex, value: stringvalue: const currentItemValue: stringcurrentItemValue, }; // Select function announce(message: string): voidannounce( `${const currentItemValue: stringcurrentItemValue} selected. Use arrow keys to choose drop position, then press Enter.` ); } function renderList(listIndex: 0 | 1): voidrenderList(listIndex: 0 | 1listIndex); // Re-render to update selection style } break; case "Enter": event: KeyboardEventevent.Event.preventDefault(): void
If invoked when the cancelable attribute value is true, and while executing a listener for the event with passive set to false, signals to the operation that caused event to be dispatched that it needs to be canceled. [MDN Reference](https://developer.mozilla.org/docs/Web/API/Event/preventDefault)
preventDefault
();
if (
let selectedItem: {
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
} | null
selectedItem
&&
let currentItemIndex: number | nullcurrentItemIndex !== null && let currentItemIndex: numbercurrentItemIndex >= 0 && let currentItemIndex: numbercurrentItemIndex < const currentItems: string[]currentItems.Array<string>.length: number
Gets or sets the length of the array. This is a number one higher than the highest index in the array.
length
) { const { listIndex: 0 | 1listIndex: const sourceListIndex: 0 | 1sourceListIndex, itemIndex: numberitemIndex: const sourceItemIndex: numbersourceItemIndex, value: stringvalue: const itemValue: stringitemValue, } =
let selectedItem: {
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
}
selectedItem
;
const const targetListIndex: 0 | 1targetListIndex = listIndex: 0 | 1listIndex; const const targetItemIndex: numbertargetItemIndex = let currentItemIndex: numbercurrentItemIndex; if ( const sourceListIndex: 0 | 1sourceListIndex === const targetListIndex: 0 | 1targetListIndex && const sourceItemIndex: numbersourceItemIndex === const targetItemIndex: numbertargetItemIndex ) { function announce(message: string): voidannounce(`Keyboard: Cannot drop ${const itemValue: stringitemValue} onto itself.`);
let selectedItem: {
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
} | null
selectedItem
= null;
function renderList(listIndex: 0 | 1): voidrenderList(listIndex: 0 | 1listIndex); // Update style break; } // Perform move in data arrays const const sourceItemsArray: string[]sourceItemsArray =
const lists: {
    el: HTMLUListElement;
    items: () => string[];
    setItems: (newItems: string[]) => void;
    idPrefix: string;
    name: string;
}[]
lists
[const sourceListIndex: 0 | 1sourceListIndex].items: () => string[]items();
const const targetItemsArray: string[]targetItemsArray =
const lists: {
    el: HTMLUListElement;
    items: () => string[];
    setItems: (newItems: string[]) => void;
    idPrefix: string;
    name: string;
}[]
lists
[const targetListIndex: 0 | 1targetListIndex].items: () => string[]items();
const const newSourceItems: string[]newSourceItems = [...const sourceItemsArray: string[]sourceItemsArray]; const newSourceItems: string[]newSourceItems.Array<string>.splice(start: number, deleteCount?: number): string[] (+1 overload)
Removes elements from an array and, if necessary, inserts new elements in their place, returning the deleted elements.
@paramstart The zero-based location in the array from which to start removing elements.@paramdeleteCount The number of elements to remove.@returnsAn array containing the elements that were deleted.
splice
(const sourceItemIndex: numbersourceItemIndex, 1);
const const newTargetItems: string[]newTargetItems = const sourceListIndex: 0 | 1sourceListIndex === const targetListIndex: 0 | 1targetListIndex ? const newSourceItems: string[]newSourceItems : [...const targetItemsArray: string[]targetItemsArray]; let let effectiveTargetIndex: numbereffectiveTargetIndex = const targetItemIndex: numbertargetItemIndex; if (const sourceListIndex: 0 | 1sourceListIndex === const targetListIndex: 0 | 1targetListIndex) { if (const sourceItemIndex: numbersourceItemIndex < const targetItemIndex: numbertargetItemIndex) { let effectiveTargetIndex: numbereffectiveTargetIndex = const targetItemIndex: numbertargetItemIndex - 1; } else { let effectiveTargetIndex: numbereffectiveTargetIndex = const targetItemIndex: numbertargetItemIndex; } } else { let effectiveTargetIndex: numbereffectiveTargetIndex = const targetItemIndex: numbertargetItemIndex; } let effectiveTargetIndex: numbereffectiveTargetIndex = var Math: Math
An intrinsic object that provides basic mathematics functionality and constants.
Math
.Math.max(...values: number[]): number
Returns the larger of a set of supplied numeric expressions.
@paramvalues Numeric expressions to be evaluated.
max
(
0, var Math: Math
An intrinsic object that provides basic mathematics functionality and constants.
Math
.Math.min(...values: number[]): number
Returns the smaller of a set of supplied numeric expressions.
@paramvalues Numeric expressions to be evaluated.
min
(let effectiveTargetIndex: numbereffectiveTargetIndex, const newTargetItems: string[]newTargetItems.Array<string>.length: number
Gets or sets the length of the array. This is a number one higher than the highest index in the array.
length
)
); const newTargetItems: string[]newTargetItems.Array<string>.splice(start: number, deleteCount: number, ...items: string[]): string[] (+1 overload)
Removes elements from an array and, if necessary, inserts new elements in their place, returning the deleted elements.
@paramstart The zero-based location in the array from which to start removing elements.@paramdeleteCount The number of elements to remove.@paramitems Elements to insert into the array in place of the deleted elements.@returnsAn array containing the elements that were deleted.
splice
(let effectiveTargetIndex: numbereffectiveTargetIndex, 0, const itemValue: stringitemValue);
// Update state arrays *before* calling render
const lists: {
    el: HTMLUListElement;
    items: () => string[];
    setItems: (newItems: string[]) => void;
    idPrefix: string;
    name: string;
}[]
lists
[const sourceListIndex: 0 | 1sourceListIndex].setItems: (newItems: string[]) => voidsetItems(const newSourceItems: string[]newSourceItems);
if (const sourceListIndex: 0 | 1sourceListIndex !== const targetListIndex: 0 | 1targetListIndex) {
const lists: {
    el: HTMLUListElement;
    items: () => string[];
    setItems: (newItems: string[]) => void;
    idPrefix: string;
    name: string;
}[]
lists
[const targetListIndex: 0 | 1targetListIndex].setItems: (newItems: string[]) => voidsetItems(const newTargetItems: string[]newTargetItems);
} // If same list, the source setter already updated the correct underlying array function announce(message: string): voidannounce( `Keyboard: Moved ${const itemValue: stringitemValue} to position ${ let effectiveTargetIndex: numbereffectiveTargetIndex + 1 } in List ${const targetListIndex: 0 | 1targetListIndex + 1}.` ); // Reset selection and update focus state
let selectedItem: {
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
} | null
selectedItem
= null;
let focusedItemIndex: number | nullfocusedItemIndex = let effectiveTargetIndex: numbereffectiveTargetIndex; let focusedListIndex: 0 | 1 | nullfocusedListIndex = const targetListIndex: 0 | 1targetListIndex; // Focus stays on the target list // Re-render both lists with updated data and focus function renderList(listIndex: 0 | 1): voidrenderList(0); function renderList(listIndex: 0 | 1): voidrenderList(1); } break; case "Escape": event: KeyboardEventevent.Event.preventDefault(): void
If invoked when the cancelable attribute value is true, and while executing a listener for the event with passive set to false, signals to the operation that caused event to be dispatched that it needs to be canceled. [MDN Reference](https://developer.mozilla.org/docs/Web/API/Event/preventDefault)
preventDefault
();
if (
let selectedItem: {
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
} | null
selectedItem
) {
function announce(message: string): voidannounce(`Selection cancelled for ${
let selectedItem: {
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
}
selectedItem
.value: stringvalue}.`);
let selectedItem: {
    listIndex: 0 | 1;
    itemIndex: number;
    value: string;
} | null
selectedItem
= null;
function renderList(listIndex: 0 | 1): voidrenderList(listIndex: 0 | 1listIndex); // Update style } else { function announce(message: string): voidannounce("Escape pressed. No item selected."); (event: KeyboardEventevent.Event.target: EventTarget | null
Returns the object to which event is dispatched (its target). [MDN Reference](https://developer.mozilla.org/docs/Web/API/Event/target)
target
as HTMLElement).HTMLOrSVGElement.blur(): void
[MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLElement/blur)
blur
(); // Blur the list
// Blur handler should take care of resetting state and rendering } break; default: return; // Allow other keys } } // --- Initial Setup --- if (const list1Element: HTMLUListElementlist1Element && const list2Element: HTMLUListElementlist2Element) { // Make lists tabbable const list1Element: HTMLUListElementlist1Element.Element.setAttribute(qualifiedName: string, value: string): void
Sets the value of element's first attribute whose qualified name is qualifiedName to value. [MDN Reference](https://developer.mozilla.org/docs/Web/API/Element/setAttribute)
setAttribute
("tabindex", "0");
const list2Element: HTMLUListElementlist2Element.Element.setAttribute(qualifiedName: string, value: string): void
Sets the value of element's first attribute whose qualified name is qualifiedName to value. [MDN Reference](https://developer.mozilla.org/docs/Web/API/Element/setAttribute)
setAttribute
("tabindex", "0");
// Add ARIA roles const list1Element: HTMLUListElementlist1Element.Element.setAttribute(qualifiedName: string, value: string): void
Sets the value of element's first attribute whose qualified name is qualifiedName to value. [MDN Reference](https://developer.mozilla.org/docs/Web/API/Element/setAttribute)
setAttribute
("role", "listbox");
const list1Element: HTMLUListElementlist1Element.Element.setAttribute(qualifiedName: string, value: string): void
Sets the value of element's first attribute whose qualified name is qualifiedName to value. [MDN Reference](https://developer.mozilla.org/docs/Web/API/Element/setAttribute)
setAttribute
("aria-labelledby", "list1-heading"); // Assume h2 has id='list1-heading'
const list2Element: HTMLUListElementlist2Element.Element.setAttribute(qualifiedName: string, value: string): void
Sets the value of element's first attribute whose qualified name is qualifiedName to value. [MDN Reference](https://developer.mozilla.org/docs/Web/API/Element/setAttribute)
setAttribute
("role", "listbox");
const list2Element: HTMLUListElementlist2Element.Element.setAttribute(qualifiedName: string, value: string): void
Sets the value of element's first attribute whose qualified name is qualifiedName to value. [MDN Reference](https://developer.mozilla.org/docs/Web/API/Element/setAttribute)
setAttribute
("aria-labelledby", "list2-heading"); // Assume h2 has id='list2-heading'
const list1Element: HTMLUListElementlist1Element.HTMLUListElement.addEventListener<"focus">(type: "focus", listener: (this: HTMLUListElement, ev: FocusEvent) => any, options?: boolean | AddEventListenerOptions): void (+1 overload)
Appends an event listener for events whose type attribute value is type. The callback argument sets the callback that will be invoked when the event is dispatched. The options argument sets listener-specific options. For compatibility this can be a boolean, in which case the method behaves exactly as if the value was specified as options's capture. When set to true, options's capture prevents callback from being invoked when the event's eventPhase attribute value is BUBBLING_PHASE. When false (or not present), callback will not be invoked when event's eventPhase attribute value is CAPTURING_PHASE. Either way, callback will be invoked if event's eventPhase attribute value is AT_TARGET. When set to true, options's passive indicates that the callback will not cancel the event by invoking preventDefault(). This is used to enable performance optimizations described in § 2.8 Observing event listeners. When set to true, options's once indicates that the callback will only be invoked once after which the event listener will be removed. If an AbortSignal is passed for options's signal, then the event listener will be removed when signal is aborted. The event listener is appended to target's event listener list and is not appended if it has the same type, callback, and capture. [MDN Reference](https://developer.mozilla.org/docs/Web/API/EventTarget/addEventListener) Appends an event listener for events whose type attribute value is type. The callback argument sets the callback that will be invoked when the event is dispatched. The options argument sets listener-specific options. For compatibility this can be a boolean, in which case the method behaves exactly as if the value was specified as options's capture. When set to true, options's capture prevents callback from being invoked when the event's eventPhase attribute value is BUBBLING_PHASE. When false (or not present), callback will not be invoked when event's eventPhase attribute value is CAPTURING_PHASE. Either way, callback will be invoked if event's eventPhase attribute value is AT_TARGET. When set to true, options's passive indicates that the callback will not cancel the event by invoking preventDefault(). This is used to enable performance optimizations described in § 2.8 Observing event listeners. When set to true, options's once indicates that the callback will only be invoked once after which the event listener will be removed. If an AbortSignal is passed for options's signal, then the event listener will be removed when signal is aborted. The event listener is appended to target's event listener list and is not appended if it has the same type, callback, and capture. [MDN Reference](https://developer.mozilla.org/docs/Web/API/EventTarget/addEventListener)
addEventListener
("focus", () => function handleFocus(listIndex: 0 | 1): voidhandleFocus(0));
const list1Element: HTMLUListElementlist1Element.HTMLUListElement.addEventListener<"blur">(type: "blur", listener: (this: HTMLUListElement, ev: FocusEvent) => any, options?: boolean | AddEventListenerOptions): void (+1 overload)
Appends an event listener for events whose type attribute value is type. The callback argument sets the callback that will be invoked when the event is dispatched. The options argument sets listener-specific options. For compatibility this can be a boolean, in which case the method behaves exactly as if the value was specified as options's capture. When set to true, options's capture prevents callback from being invoked when the event's eventPhase attribute value is BUBBLING_PHASE. When false (or not present), callback will not be invoked when event's eventPhase attribute value is CAPTURING_PHASE. Either way, callback will be invoked if event's eventPhase attribute value is AT_TARGET. When set to true, options's passive indicates that the callback will not cancel the event by invoking preventDefault(). This is used to enable performance optimizations described in § 2.8 Observing event listeners. When set to true, options's once indicates that the callback will only be invoked once after which the event listener will be removed. If an AbortSignal is passed for options's signal, then the event listener will be removed when signal is aborted. The event listener is appended to target's event listener list and is not appended if it has the same type, callback, and capture. [MDN Reference](https://developer.mozilla.org/docs/Web/API/EventTarget/addEventListener) Appends an event listener for events whose type attribute value is type. The callback argument sets the callback that will be invoked when the event is dispatched. The options argument sets listener-specific options. For compatibility this can be a boolean, in which case the method behaves exactly as if the value was specified as options's capture. When set to true, options's capture prevents callback from being invoked when the event's eventPhase attribute value is BUBBLING_PHASE. When false (or not present), callback will not be invoked when event's eventPhase attribute value is CAPTURING_PHASE. Either way, callback will be invoked if event's eventPhase attribute value is AT_TARGET. When set to true, options's passive indicates that the callback will not cancel the event by invoking preventDefault(). This is used to enable performance optimizations described in § 2.8 Observing event listeners. When set to true, options's once indicates that the callback will only be invoked once after which the event listener will be removed. If an AbortSignal is passed for options's signal, then the event listener will be removed when signal is aborted. The event listener is appended to target's event listener list and is not appended if it has the same type, callback, and capture. [MDN Reference](https://developer.mozilla.org/docs/Web/API/EventTarget/addEventListener)
addEventListener
("blur", (e: FocusEvente) => function handleBlur(event: FocusEvent, listIndex: 0 | 1): voidhandleBlur(e: FocusEvente, 0));
const list1Element: HTMLUListElementlist1Element.HTMLUListElement.addEventListener<"keydown">(type: "keydown", listener: (this: HTMLUListElement, ev: KeyboardEvent) => any, options?: boolean | AddEventListenerOptions): void (+1 overload)
Appends an event listener for events whose type attribute value is type. The callback argument sets the callback that will be invoked when the event is dispatched. The options argument sets listener-specific options. For compatibility this can be a boolean, in which case the method behaves exactly as if the value was specified as options's capture. When set to true, options's capture prevents callback from being invoked when the event's eventPhase attribute value is BUBBLING_PHASE. When false (or not present), callback will not be invoked when event's eventPhase attribute value is CAPTURING_PHASE. Either way, callback will be invoked if event's eventPhase attribute value is AT_TARGET. When set to true, options's passive indicates that the callback will not cancel the event by invoking preventDefault(). This is used to enable performance optimizations described in § 2.8 Observing event listeners. When set to true, options's once indicates that the callback will only be invoked once after which the event listener will be removed. If an AbortSignal is passed for options's signal, then the event listener will be removed when signal is aborted. The event listener is appended to target's event listener list and is not appended if it has the same type, callback, and capture. [MDN Reference](https://developer.mozilla.org/docs/Web/API/EventTarget/addEventListener) Appends an event listener for events whose type attribute value is type. The callback argument sets the callback that will be invoked when the event is dispatched. The options argument sets listener-specific options. For compatibility this can be a boolean, in which case the method behaves exactly as if the value was specified as options's capture. When set to true, options's capture prevents callback from being invoked when the event's eventPhase attribute value is BUBBLING_PHASE. When false (or not present), callback will not be invoked when event's eventPhase attribute value is CAPTURING_PHASE. Either way, callback will be invoked if event's eventPhase attribute value is AT_TARGET. When set to true, options's passive indicates that the callback will not cancel the event by invoking preventDefault(). This is used to enable performance optimizations described in § 2.8 Observing event listeners. When set to true, options's once indicates that the callback will only be invoked once after which the event listener will be removed. If an AbortSignal is passed for options's signal, then the event listener will be removed when signal is aborted. The event listener is appended to target's event listener list and is not appended if it has the same type, callback, and capture. [MDN Reference](https://developer.mozilla.org/docs/Web/API/EventTarget/addEventListener)
addEventListener
("keydown", (e: KeyboardEvente) => function handleKeydown(event: KeyboardEvent, listIndex: 0 | 1): voidhandleKeydown(e: KeyboardEvente, 0));
const list2Element: HTMLUListElementlist2Element.HTMLUListElement.addEventListener<"focus">(type: "focus", listener: (this: HTMLUListElement, ev: FocusEvent) => any, options?: boolean | AddEventListenerOptions): void (+1 overload)
Appends an event listener for events whose type attribute value is type. The callback argument sets the callback that will be invoked when the event is dispatched. The options argument sets listener-specific options. For compatibility this can be a boolean, in which case the method behaves exactly as if the value was specified as options's capture. When set to true, options's capture prevents callback from being invoked when the event's eventPhase attribute value is BUBBLING_PHASE. When false (or not present), callback will not be invoked when event's eventPhase attribute value is CAPTURING_PHASE. Either way, callback will be invoked if event's eventPhase attribute value is AT_TARGET. When set to true, options's passive indicates that the callback will not cancel the event by invoking preventDefault(). This is used to enable performance optimizations described in § 2.8 Observing event listeners. When set to true, options's once indicates that the callback will only be invoked once after which the event listener will be removed. If an AbortSignal is passed for options's signal, then the event listener will be removed when signal is aborted. The event listener is appended to target's event listener list and is not appended if it has the same type, callback, and capture. [MDN Reference](https://developer.mozilla.org/docs/Web/API/EventTarget/addEventListener) Appends an event listener for events whose type attribute value is type. The callback argument sets the callback that will be invoked when the event is dispatched. The options argument sets listener-specific options. For compatibility this can be a boolean, in which case the method behaves exactly as if the value was specified as options's capture. When set to true, options's capture prevents callback from being invoked when the event's eventPhase attribute value is BUBBLING_PHASE. When false (or not present), callback will not be invoked when event's eventPhase attribute value is CAPTURING_PHASE. Either way, callback will be invoked if event's eventPhase attribute value is AT_TARGET. When set to true, options's passive indicates that the callback will not cancel the event by invoking preventDefault(). This is used to enable performance optimizations described in § 2.8 Observing event listeners. When set to true, options's once indicates that the callback will only be invoked once after which the event listener will be removed. If an AbortSignal is passed for options's signal, then the event listener will be removed when signal is aborted. The event listener is appended to target's event listener list and is not appended if it has the same type, callback, and capture. [MDN Reference](https://developer.mozilla.org/docs/Web/API/EventTarget/addEventListener)
addEventListener
("focus", () => function handleFocus(listIndex: 0 | 1): voidhandleFocus(1));
const list2Element: HTMLUListElementlist2Element.HTMLUListElement.addEventListener<"blur">(type: "blur", listener: (this: HTMLUListElement, ev: FocusEvent) => any, options?: boolean | AddEventListenerOptions): void (+1 overload)
Appends an event listener for events whose type attribute value is type. The callback argument sets the callback that will be invoked when the event is dispatched. The options argument sets listener-specific options. For compatibility this can be a boolean, in which case the method behaves exactly as if the value was specified as options's capture. When set to true, options's capture prevents callback from being invoked when the event's eventPhase attribute value is BUBBLING_PHASE. When false (or not present), callback will not be invoked when event's eventPhase attribute value is CAPTURING_PHASE. Either way, callback will be invoked if event's eventPhase attribute value is AT_TARGET. When set to true, options's passive indicates that the callback will not cancel the event by invoking preventDefault(). This is used to enable performance optimizations described in § 2.8 Observing event listeners. When set to true, options's once indicates that the callback will only be invoked once after which the event listener will be removed. If an AbortSignal is passed for options's signal, then the event listener will be removed when signal is aborted. The event listener is appended to target's event listener list and is not appended if it has the same type, callback, and capture. [MDN Reference](https://developer.mozilla.org/docs/Web/API/EventTarget/addEventListener) Appends an event listener for events whose type attribute value is type. The callback argument sets the callback that will be invoked when the event is dispatched. The options argument sets listener-specific options. For compatibility this can be a boolean, in which case the method behaves exactly as if the value was specified as options's capture. When set to true, options's capture prevents callback from being invoked when the event's eventPhase attribute value is BUBBLING_PHASE. When false (or not present), callback will not be invoked when event's eventPhase attribute value is CAPTURING_PHASE. Either way, callback will be invoked if event's eventPhase attribute value is AT_TARGET. When set to true, options's passive indicates that the callback will not cancel the event by invoking preventDefault(). This is used to enable performance optimizations described in § 2.8 Observing event listeners. When set to true, options's once indicates that the callback will only be invoked once after which the event listener will be removed. If an AbortSignal is passed for options's signal, then the event listener will be removed when signal is aborted. The event listener is appended to target's event listener list and is not appended if it has the same type, callback, and capture. [MDN Reference](https://developer.mozilla.org/docs/Web/API/EventTarget/addEventListener)
addEventListener
("blur", (e: FocusEvente) => function handleBlur(event: FocusEvent, listIndex: 0 | 1): voidhandleBlur(e: FocusEvente, 1));
const list2Element: HTMLUListElementlist2Element.HTMLUListElement.addEventListener<"keydown">(type: "keydown", listener: (this: HTMLUListElement, ev: KeyboardEvent) => any, options?: boolean | AddEventListenerOptions): void (+1 overload)
Appends an event listener for events whose type attribute value is type. The callback argument sets the callback that will be invoked when the event is dispatched. The options argument sets listener-specific options. For compatibility this can be a boolean, in which case the method behaves exactly as if the value was specified as options's capture. When set to true, options's capture prevents callback from being invoked when the event's eventPhase attribute value is BUBBLING_PHASE. When false (or not present), callback will not be invoked when event's eventPhase attribute value is CAPTURING_PHASE. Either way, callback will be invoked if event's eventPhase attribute value is AT_TARGET. When set to true, options's passive indicates that the callback will not cancel the event by invoking preventDefault(). This is used to enable performance optimizations described in § 2.8 Observing event listeners. When set to true, options's once indicates that the callback will only be invoked once after which the event listener will be removed. If an AbortSignal is passed for options's signal, then the event listener will be removed when signal is aborted. The event listener is appended to target's event listener list and is not appended if it has the same type, callback, and capture. [MDN Reference](https://developer.mozilla.org/docs/Web/API/EventTarget/addEventListener) Appends an event listener for events whose type attribute value is type. The callback argument sets the callback that will be invoked when the event is dispatched. The options argument sets listener-specific options. For compatibility this can be a boolean, in which case the method behaves exactly as if the value was specified as options's capture. When set to true, options's capture prevents callback from being invoked when the event's eventPhase attribute value is BUBBLING_PHASE. When false (or not present), callback will not be invoked when event's eventPhase attribute value is CAPTURING_PHASE. Either way, callback will be invoked if event's eventPhase attribute value is AT_TARGET. When set to true, options's passive indicates that the callback will not cancel the event by invoking preventDefault(). This is used to enable performance optimizations described in § 2.8 Observing event listeners. When set to true, options's once indicates that the callback will only be invoked once after which the event listener will be removed. If an AbortSignal is passed for options's signal, then the event listener will be removed when signal is aborted. The event listener is appended to target's event listener list and is not appended if it has the same type, callback, and capture. [MDN Reference](https://developer.mozilla.org/docs/Web/API/EventTarget/addEventListener)
addEventListener
("keydown", (e: KeyboardEvente) => function handleKeydown(event: KeyboardEvent, listIndex: 0 | 1): voidhandleKeydown(e: KeyboardEvente, 1));
// Initial render function renderList(listIndex: 0 | 1): voidrenderList(0); function renderList(listIndex: 0 | 1): voidrenderList(1); }

List 1

  • Apples
  • Bananas
  • Oranges
  • Grapes

List 2

  • Milk
  • Cheese
  • Yogurt

Keyboard Instructions

  • Use Tab or Shift+Tab to focus a list.
  • Use / arrows to navigate items within the focused list.
  • Press Spacebar to select/deselect the highlighted item for moving.
  • With an item selected, use / (within the same or another focused list) to choose the drop position.
  • Press Enter to drop the selected item at the highlighted position.
  • Press Escape to cancel a selection or leave the list.

Support Us

FormKit Drag and Drop is made with love by the FormKit team — the creators of open-source projects such as:

  • FormKit - The open-source form framework for Vue.
  • AutoAnimate - Add motion to your apps with a single line of code.
  • Tempo - The easiest way to work with dates in JavaScript.
  • ArrowJS - Reactivity without the Framework.

If you find our projects useful and would like to support their ongoing development, please consider sponsoring us on GitHub!