@medalsocial/meda
Version:
Shared Meda UI shell and runtime package.
67 lines (66 loc) • 3.39 kB
JavaScript
'use client';
import { jsx as _jsx } from "react/jsx-runtime";
import { useDndMonitor, useDroppable } from '@dnd-kit/core';
import { useState } from 'react';
import { cn } from '../lib/utils.js';
export function RailDropSlot({ id, accepts, disabled, children, render, className, ariaLabel, ref, }) {
const { isOver, active, setNodeRef } = useDroppable({
id,
disabled,
data: { type: 'rail-drop-slot' },
});
const [globalDragActive, setGlobalDragActive] = useState(false);
/* v8 ignore next — useDndMonitor: callbacks are never invoked in jsdom (no pointer events) */
useDndMonitor({
onDragStart: () => setGlobalDragActive(true),
onDragEnd: () => setGlobalDragActive(false),
onDragCancel: () => setGlobalDragActive(false),
});
/* v8 ignore next — active?.id: active is always null in jsdom (no pointer events) */
const wouldAccept = !disabled && (!accepts || (active?.id != null && accepts(String(active.id))));
let state;
/* v8 ignore next — isOver: always false in jsdom (no DnD pointer events) */
if (isOver && wouldAccept) {
state = 'over';
/* v8 ignore next — isOver: always false in jsdom */
}
else if (isOver && !wouldAccept) {
state = 'rejected';
/* v8 ignore next — globalDragActive: always false in jsdom */
}
else if (globalDragActive && disabled) {
state = 'rejected';
/* v8 ignore next — globalDragActive: always false in jsdom */
}
else if (globalDragActive && wouldAccept) {
state = 'active';
}
else {
state = 'idle';
}
// Legacy boolean aliases kept for backward-compat data attributes
const showHover = state === 'over';
const showRejected = state === 'rejected';
return (_jsx("section", { ref: (el) => {
setNodeRef(el);
if (typeof ref === 'function')
ref(el);
else if (ref)
ref.current = el;
}, "data-slot-id": id, "data-state": state, "aria-label": ariaLabel, "aria-disabled": disabled || undefined, className: cn('relative rounded-lg border border-border bg-card transition-all duration-150', state === 'idle' && '',
/* v8 ignore next — active state only reachable when drag is in progress (pointer events) */
state === 'active' && 'border-dashed border-primary/60 bg-primary/5',
/* v8 ignore next 2 — over state only reachable when dragging over this slot */
state === 'over' &&
'border-primary bg-primary/5 ring-2 ring-primary/30 shadow-[0_0_0_4px_hsl(var(--primary)/0.1)]',
/* v8 ignore next — rejected state only reachable when drag is active */
state === 'rejected' && 'border-destructive/40 opacity-60',
// Legacy classes — keep working for consumers using data-state selectors
/* v8 ignore next — showHover is always false in jsdom (no drag pointer events) */
showHover && '',
/* v8 ignore next — showRejected is always false in jsdom (no drag pointer events) */
showRejected && '',
/* v8 ignore next — disabled+idle combination: disabled prop not exercised with drag-active state */
disabled && state === 'idle' && 'opacity-60', className), children: render ? render(state) : children }));
}
RailDropSlot.displayName = 'RailDropSlot';