Primeros pasos
Instalación
Ingresa en tu terminal:
# npm
npm i effdnd
# pnpm
pnpm add effdnd
# yarn
yarn add effdndInicio rápido
En resumen, effdnd utiliza dos componentes web personalizados:
effdnd triggeractiva la función de arrastrar y soltar,effdnd-actorindica las áreas del diseño que participarán en el proceso de arrastrar y soltar (desempeñarán sus funciones).
El componente web effdnd-actor puede desempeñar varias funciones:
item: el elemento que se mueve,target: el objetivo del movimiento,scope: los límites del movimiento.
Para definir una función, debes establecer el atributo del mismo nombre en el elemento effdnd-actor. Se pueden asignar múltiples roles a un mismo elemento.
Al iniciar la función de arrastrar y soltar, el componente web effdnd-trigger utiliza sus atributos para seleccionar los participantes del proceso (actores):
- El atributo
itempermite seleccionar el elemento que se va a mover. Si no se especifica, se utilizará el elemento más cercano en el árbol<effdnd-actor item='...'>con el atributoitemespecificado. Si se establece un atributo con el valor#(<effdnd-trigger item='#'>) o no existe ningún<effdnd-actor item='...'>en el árbol DOM superior, se moverá el propio activador. - El atributo
scopepermite seleccionar el área de movimiento disponible. Si no se especifica, se utilizará el elemento más cercano en el árbol<effdnd-actor scope='...'>con el atributoscopeespecificado. Si se establece un atributo con el valor#(<effdnd-trigger scope='#'>) o no existe un<effdnd-actor scope='...'>en el árbol DOM superior, el área de desplazamiento se considerarádocument.body.
El atributo target permite seleccionar los objetivos de movimiento disponibles. Estos objetivos generan eventos especiales cuando finaliza la operación de arrastrar y soltar sobre ellos. Todos los elementos <effdnd-actor target='...'> ubicados dentro del área scope se considerarán objetivos de movimiento, cuyos nombres comiencen con el valor del atributo target del activador. Esto significa que, si no se especifica el atributo, todos los <effdnd-actor target='...'> estarán disponibles dentro del <effdnd-actor scope='...'> actual.
Para definir ambos componentes web, simplemente llame a la función useDnD y utilice la escucha de eventos para detectar los resultados de la llamada:
import { useRef } from 'react';
import { useDnD } from 'effdnd';
const { observe } = useDnD();
export const Component = () => {
const ref = useRef();
useEffect(() => {
// puedes suscribirte a eventos de arrastrar y soltar
const unobserve = observe((e) => {
// el evento se está procesando aquí
}, ref.current);
// y puedes darte de baja
return () => unobserve();
});
return <effdnd-actor scope='top' ref={ref} >
<div className="targets-wrapper">
<effdnd-actor target='target-1'>...</effdnd-actor>
<effdnd-actor target='target-2'>...</effdnd-actor>
</div>
<div id="items-wrapper">
<effdnd-actor item='item-1'>
<effdnd-trigger>Trigger #1</effdnd-trigger>
</effdnd-actor>
<effdnd-actor item='item-2'>
<effdnd-trigger>Trigger #2</effdnd-trigger>
</effdnd-actor>
</div>
</effdnd-actor>;
}Elementos activos y pasivos
Durante la operación de arrastrar y soltar, el effdnd-trigger establece el atributo dinámico state en los actores effdnd-actor seleccionados. Es decir, al inicio, el trigger determina qué se mueve (item), dónde puede moverse (scope) y dónde debe moverse (target). Los elementos pueden estar:
- sin estado,
- en estado pasivo (
state="passive"), - en estado activo (
state="active").
El elemento con el rol item está activo mientras se mueve. Además, un elemento con el rol item puede estar en estado clonado (state="cloned") si su clon está activo. Para clonar un elemento, active el modo item-mode="cloned".
Un elemento con el rol scope está pasivo cuando el item se mueve dentro de él. Este estado delimita el área de desplazamiento.
Un elemento con el rol de ámbito se activa si se encuentra en estado pasivo y el elemento intenta sobrepasarlo. Este estado indica al usuario que el cursor se ha movido más allá de los límites permitidos.
Un elemento con el rol de destino se encuentra en estado pasivo cuando está dentro de un ámbito con estado activo o pasivo. Este estado muestra dónde se puede mover el elemento.
Un elemento con el rol de destino se activa si se encuentra en estado pasivo y el cursor con el elemento está sobre él. Este estado indica que el destino se está preparando para aceptar el elemento.
Modos de rol
El comportamiento básico de la biblioteca es de bajo nivel, por lo que es posible refinar el caso de uso mediante el modo de cada rol:
item-modedefine el modo deitemy permite establecer los siguientes valores:item-mode="keep": el elementoitemconservará sus nuevas coordenadas tras moverse;item-mode="clone": se creará un clon del elementoitem, que se moverá;
target-modedefine el modo detargettras seleccionarlo y permite establecer los siguientes valores:target-mode="prepend": el elementoitemse añadirá altargetcomo primer elemento hijo;target-mode="append": el elementoitemse añadirá altargetcomo último elemento hijo; -target-mode="remove": el elementoitemse eliminará del árbol DOM;
scope-modedefine el modo descopedurante la operación de arrastrar y soltar, y puede establecer los siguientes valores:scope-mode="order-x": el elementoscopepermite reorganizar los elementositema lo largo del ejex;scope-mode="order-y": el elementoscopepermite reorganizar los elementositema lo largo del ejey.
Estilos
La apariencia de <effdnd-actor item='...'> se define mediante el activador utilizando atributos durante el movimiento. También puedes usar atributos para configurar los parámetros de animación, el eje de movimiento y la distancia mínima de disparo.
/export interface ITriggerAttrs {
/**
* Item name
* @description
* If the value is "#" then it will use `effnd-trigger` as item
*/
item?: string;
/**
* Bounding scope name
* @description
* If the value is "#" then it will use `document.body` as scope
*/
scope?: string;
/**
* Target name or its prefix
*/
target?: string;
/**
* Triggering distance
*/
dist?: string;
/**
* Triggering mouse button
* @description
* Any mouse button if not specified
*/
btn?: '0' | '1' | '2';
/**
* DnD axis
*/
axis?: string;
/**
* Triggering event
* @description
* Both 'touch' and 'mouse' by default
*/
event?: 'touch' | 'mouse';
/**
* Transition duration
*/
dur?: string;
/**
* Transition delay
*/
del?: string;
/**
* Transition timing-function
*/
tf?: string;
}Por defecto, se utilizará un icono de movimiento SVG dentro del activador vacío, cuya apariencia depende del atributo axis. Para ocultar el icono, utilice su propio contenido dentro del effdnd-trigger.
El componente web effdnd-actor ya incluye los estilos iniciales para los estados pasivo y activo de los roles, pero también permite eliminarlos mediante el atributo unstyled. <effdnd-actor unstyled="target"> elimina únicamente los estilos integrados de target, <effdnd-actor unstyled="scope"> elimina únicamente los estilos integrados de scope, y <effdnd-actor unstyled> elimina todos los estilos integrados.
/**
* DnD actor attributes
*/
export interface IActorAttrs {
/**
* Item name
*/
item?: string;
/**
* Scope name
*/
scope?: string;
/**
* Target name
*/
target?: string;
/**
* Actor state
*/
state?: 'active' | 'passive';
/**
* Reset target state styles
*/
unstyled?: boolean | 'target' | 'scope';
/**
* Display contents
*/
contents?: boolean;
/**
* Item mode
*/
'item-mode'?: 'keep' | 'clone';
/**
* Target mode
*/
'target-mode'?: 'append' | 'prepend' | 'remove';
/**
* Scope mode
*/
'scope-mode'?: 'order-x' | 'order-y';
/**
* Scope transition duration
*/
'scope-dur'?: number;
/**
* Scope transition delay
*/
'scope-del'?: number;
/**
* Scope transition timing-function
*/
'scope-tf'?: string;
}Los atributos scope-dur, scope-del y scope-del para un elemento con el rol scope establecen los valores predeterminados de la propiedad CSS transition.
El atributo contents permite establecer el estilo display:contents;.
También puedes definir tus propios estilos CSS para diferentes estados:
effdnd-actor[target][state=passive] .custom-dnd-target {
outline: 4px solid #646cffaa;
}
effdnd-actor[target][state=active] .custom-dnd-target {
outline: 4px solid #646cffaa;
background: #646cffaa;
}Renderizado del lado del servidor
Si utilizas el renderizado del lado del servidor, simplemente añade un script con la declaración effdnd a la cabecera de tu HTML para mantener el diseño:
<head>
<script src="https://cdn.jsdelivr.net/npm/effdnd@3.1.0/dist/use.js"></script>
</head>Este script también te permitirá usar effdnd como variable global:
import { TUseDnD } from 'effdnd';
declare global {
interface Window {
effdnd: ReturnType<TUseDnD>;
}
};
const unobserve = window.effdnd.observe(() => console.log('effdnd'));useDnD
La función declara los componentes web effdnd-trigger y effdnd-actor, y también devuelve manejadores para suscribirse a eventos personalizados:
export type TEventDetail = {
type: TEventType;
refs: TRefs;
keys: TKeys;
event: MouseEvent | TouchEvent;
};
interface TDnDEvent extends CustomEvent {
detail: TEventDetail;
}
export type TDnDCallback = (event: TDnDEvent) => void;
export type TUseDnD = () => {
/**
* Observar eventos DnD
* @param callback - controlador de eventos
* @param element - elemento HTML
*/
observe: (callback: TDnDCallback, element?: HTMLElement) => () => void;
/**
* No observar eventos DnD
* @param callback - controlador de eventos
* @param element - elemento HTML
*/
unobserve: (callback: TDnDCallback, element?: HTMLElement) => void;
};effdnd-trigger
El componente web de activación contiene varios métodos y propiedades útiles:
/**
* Elemento disparador DnD
*/
export interface ITriggerElement extends HTMLElement {
/**
* Está activo el disparador
*/
isActive: boolean;
/**
* Artículo y-desplazamiento
*/
dndY: number;
/**
* Artículo x-desplazamiento
*/
dndX: number;
/**
* Artículo DnD
*/
dndItem: HTMLElement;
/**
* Alcance DnD
*/
dndScope: HTMLElement;
/**
* Objetivos DnD
*/
dndTargets: Set<HTMLElement>;
/**
* Restablecer DnD traducir
*/
resetDnD(): void;
}