Skip to content

Primeros pasos (V2)

Instalación

Ingrese en su terminal:

sh
# npm
npm i effdnd

# pnpm
pnpm add effdnd

# yarn
yarn add effdnd

Inicio rápido

En resumen, effdnd utiliza dos componentes web personalizados:

  • effdnd trigger activa la función de arrastrar y soltar,
  • effdnd-actor indica 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 destino del movimiento,
  • scope: los límites del movimiento.

Para definir una función, debe establecer el atributo del mismo nombre en el elemento effdnd-actor. Se pueden definir varias funciones para un mismo elemento. Los valores de los atributos se utilizarán para identificar los participantes de la función de arrastrar y soltar mediante el componente effdnd-trigger.

Al inicio de la función de arrastrar y soltar, el componente web effdnd-trigger utiliza sus atributos para seleccionar los participantes del proceso (actores): - El atributo item permite seleccionar el elemento que se va a mover. Si no se especifica, se utilizará el elemento <effdnd-actor item='...'> más cercano en el árbol DOM con el atributo item especificado. 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. Si el activador tiene el atributo clone, se creará un clon del elemento HTML para el movimiento.

  • El atributo scope permite seleccionar el área de movimiento disponible. Si no se especifica, se utilizará el elemento <effdnd-actor scope='...'> más cercano en el árbol DOM con el atributo scope especificado. Si se establece un atributo con el valor # (<effdnd-trigger scope='#'>) o no existe <effdnd-actor scope='...'> en el árbol DOM anterior, el área de ámbito será document.body.

El atributo target permite seleccionar los objetivos de movimiento disponibles. Estos objetivos generan eventos especiales cuando finaliza la acción de arrastrar y soltar sobre ellos. Todos los elementos <effdnd-actor target='...'> ubicados dentro del área de ámbito 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 elementos <effdnd-actor target='...'> estarán disponibles dentro del área de ámbito.

Para definir ambos componentes web, simplemente llame a la función useDnD y utilice los resultados de la llamada para crear detectores de eventos.

jsx
import { useRef } from 'react';
import { useDnD } from 'effdnd';

// Puedes pasar parámetros de estilo a useDnD para anular los parámetros de movimiento.
// (Para más información, consulta el tipo `TUseDnD`).
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 elementos effdnd-actor seleccionados. Es decir, al inicio, el trigger determina qué se mueve (item), cómo se limita su movimiento (scope) y adó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.

El elemento con el rol scope está pasivo cuando el item se mueve dentro de él.

El elemento con el rol scope se activa si se encuentra en estado pasivo y el elemento intenta sobrepasarlo. Este estado muestra al usuario los límites de movimiento disponibles.

El elemento con el rol target permanece pasivo cuando se encuentra dentro de un scope con estado activo o pasivo.

El elemento con el rol target se activa si se encuentra en estado pasivo y el elemento se mueve sobre él.

Estilos de componentes

La apariencia de <effdnd-actor item='...'> se define mediante el activador utilizando atributos durante el movimiento. También se pueden usar atributos para configurar los parámetros de animación, el eje de movimiento y la distancia mínima de activación.

ts
/**
 * DnD trigger attributes
 */
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;
    /**
     * 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;
    /**
     * Item z-index in active state
     */
    zi?: string;
    /**
     * Item opacity in active state
     */
    opacity?: string;
    /**
     * Use item clone while dragging
     */
    clone?: boolean;
}

El componente web effdnd-actor ya contiene los estilos iniciales para los estados pasivo y activo de target y scope, pero también permite cancelarlos mediante el atributo unstyled. Al mismo tiempo, <effdnd-actor unstyled="target"> cancela solo los estilos integrados de target, <effdnd-actor unstyled="scope"> cancela solo los estilos integrados de scope, y <effdnd-actor unstyled> cancela todos los estilos integrados.

ts
/**
 * 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;
}

El atributo contents permite establecer el estilo display:contents;. Si se añade el atributo unstyled, se pueden definir estilos CSS personalizados para diferentes estados.

css
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;
}

useDnD

La función acepta configuraciones de transición como primer argumento y estilos personalizados como segundo. Devuelve funciones para escuchar eventos personalizados:

ts
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 = (defs?: Partial<{
    /**
     * Duration
     */
    dur: number;
    /**
     * Delay
     */
    del: number;
    /**
     * Transition-timing-function
     */
    tf: string;
    /**
     * Active DnD item z-index
     */
    zi: number;
    /**
     * Active DnD item opacity
     */
    opacity: number;
}>) => {
    /**
     * Observe DnD events
     * @param callback - event handler
     * @param element - HTML element
     */
    observe: (callback: TDnDCallback, element?: HTMLElement) => () => void;
    /**
     * Unobserve DnD events
     * @param callback - event handler
     * @param element - HTML element
     */
    unobserve: (callback: TDnDCallback, element?: HTMLElement) => void;
};

effdnd trigger

El componente web de activación contiene varios métodos y propiedades útiles.

ts
/**
 * DnD trigger element 
 */
export interface ITriggerElement extends HTMLElement {
    /**
     * DnD item y-offset
     */
    dndY: number;
    /**
     * DnD item x-offset
     */
    dndX: number;
    /**
     * DnD item
     */
    dndItem: HTMLElement;
    /**
     * DnD scope
     */
    dndScope: HTMLElement;
    /**
     * DnD targets
     */
    dndTargets: Set<HTMLElement>;
    /**
     * Reset DnD transforms
     */
    resetDnD(options?: KeyframeAnimationOptions): Promise<void>;
}

Publicado bajo la Licencia Apache 2.0