Skip to content

はじめに(バージョン1)

インストール

ターミナルに以下を入力してください:

sh
# npm
npm i effdnd

# pnpm
pnpm add effdnd

# yarn
yarn add effdnd

クイックスタート

簡単に言うと、effdnd はデータ属性を使って、通常の HTML 要素の役割を設定します。

  • ドラッグする要素 item
  • ドラッグする対象 target
  • ドラッグ範囲 scope

カスタム要素 effdnd-trigger は、最も近い item に対してドラッグ&ドロップを開始します。属性を使って設定できます(詳細は ITriggerAttrs インターフェースを参照)。effdnd-trigger 自体も item の役割を持つことができ、つまり、独自のドラッグを開始できます。

useDnD 関数を呼び出して effdnd-trigger を定義し、その結果を使って特別なデータ属性を作成するだけです。

jsx
import { useDnD } from 'effdnd';

// useDnDにスタイルパラメータを渡すことで、DnD要素のグローバルCSSを上書きできます(詳細は`TUseDnD`型を参照してください)。
const { scope, item, target, css, observe } = useDnD();
// `scope`属性を作成します
const scopeAttrs = scope('local');
// `target`属性を作成します
const fisrtTargetAttrs = target('first');
// ターゲットはグループ化できます
const secondTargetAttrs = target('second', 'group');
// `item`属性を作成します
const fisrtItemAttrs = item('first');
const secondItemAttrs = item('second');
// さまざまなD&D要素ごとに個別のスタイルを設定することもできます。
const separateStyleAttrs = css({
    passiveTarget: 'border: 4px solid grey',
});

export const Component = () => {
    const ref = useRef();
    useEffect(() => {
      // DnDイベントを観察できます
      const unobserve = observe((e) => {
        // DnDイベントの反応
      }, ref.current);
      // そして、あなたは観察を中止することができます
      return () => unobserve();
    })
    // 準備完了の属性を適用するだけで、魔法のように動作します。
    // アイテム内で `effdnd-trigger` を使用することを忘れないでください
    return <div ref={ref} {...scopeAttrs}>
        <div className="targets-wrapper">
            <div {...fisrtTargetAttrs}>...</div>
            <div {...secondTargetAttrs} {...separateStyleAttrs}>...</div>
        </div>
        <div id="items-wrapper">
            <div {...fisrtItemAttrs}>
                <effdnd-trigger>Trigger #1</effdnd-trigger>
            </div>
            <div {...secondItemAttrs}>
                <effdnd-trigger>Trigger #2</effdnd-trigger>
            </div>
        </div>
    </div>;
}

アクティブ要素とパッシブ要素

ドラッグ中、effdnd は要素の状態を示す動的な属性を設定します。要素は、

  • 状態なし、
  • パッシブ状態、
  • アクティブ状態のいずれかになります。

item はドラッグ中はアクティブ状態です。

scope は、ドラッグ中の item がスコープ内にあり、かつ以下の条件のうち少なくとも 1 つが真である場合にパッシブ状態になります。

  • effdnd-triggerscope のキーと等しい値の scope 属性が含まれている場合、
  • effdnd-triggerscope 属性が含まれておらず、かつ scope が最も近い scope である場合。

scope 要素がパッシブ状態であり、item がその範囲を超えようとすると、scope 要素はアクティブ状態になります。この状態は、ユーザーにドラッグ可能な範囲を示すのに役立ちます。

target要素は、scope内にあり、active状態またはpassive状態のいずれかで、かつ以下のいずれかの条件を満たす場合にpassive状態となります。

  • effdnd-triggerに、target要素のグループと同じ値が設定されたtarget属性が含まれている場合。
  • effdnd-triggertarget属性が含まれていない場合(すべてのtarget要素が該当します)。

target要素は、passive状態にあるときにitemがその上にドラッグされるとactive状態になります。

useDnD

この関数は、最初の引数としてトランジション設定を、2番目の引数としてカスタムスタイルを受け取ります。そして、属性リゾルバーとイベントハンドラーを返します。

ts
type TEventDetail = {
    type: TEventType;
    refs: TRefs;
    keys: TKeys;
    event: MouseEvent | TouchEvent;
};

interface TDnDEvent extends CustomEvent {
    detail: TEventDetail;
}

type TDnDCallback = (event: TDnDEvent) => void;

type TDynamicAttrs = Partial<{
    /**
     * Active DnD item styles
     */
    activeItem: string;
    /**
     * Passive DnD target styles
     */
    passiveTarget: string;
    /**
     * Active DnD target styles
     */
    activeTarget: string;
    /**
     * Passive DnD scope styles
     */
    passiveScope: string;
    /**
     * Active DnD scope styles
     */
    activeScope: string;
}>;

type TUseDnD = {
    (transition?: Partial<{
        /**
         * Duration
         */
        dur: string | number;
        /**
         * Delay
         */
        del: string | number;
        /**
         * Transition-timing-function
         */
        tf: string;
    }>, css?: TDynamicAttrs): {
        /**
         * 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;
        /**
         * Use DnD item
         * @param key - item key
         */
        item: (key: string) => object;
        /**
         * Use DnD target
         * @param key - target key
         */
        target: (key: string, group?: string) => object;
        /**
         * Use DnD scope
         * @param key - scope key
         */
        scope: (key?: string) => object;
        /**
         * Use different CSS for DnD elements
         */
        css: (params: TDynamicAttrs) => object;
    };
    customCount?: number;
    stylesheet?: CSSStyleSheet;
}

effdnd-trigger

要素は属性によって設定できます。

ts
interface ITriggerAttrs {
    /**
     * Bounding scope key
     */
    scope?: string;
    /**
     * Targets group
     */
    target?: string;
    /**
     * Triggering distance
     */
    dist?: string;
    /**
     * Triggering event
     * @description
     * Both 'touch' and 'mouse' by default
     */
    event?: 'touch' | 'mouse';
}

Apache License 2.0に基づいて公開されています。