@react-querybuilder/dnd
Version:
Drag-and-drop-enabled version of react-querybuilder (DnD-library-agnostic)
1 lines • 36.7 kB
Source Map (JSON)
{"version":3,"file":"dnd-kit-c4Y2XzQh.mjs","names":[],"sources":["../src/adapters/dnd-kit.tsx"],"sourcesContent":["import type {\n DndContext as DndContextImport,\n KeyboardSensor as KeyboardSensorImport,\n PointerSensor as PointerSensorImport,\n useDraggable as useDraggableImport,\n useDroppable as useDroppableImport,\n useSensor as useSensorImport,\n useSensors as useSensorsImport,\n} from '@dnd-kit/core';\nimport * as React from 'react';\nimport {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport type {\n DndDropTargetType,\n DraggedItem,\n Path,\n RuleGroupTypeAny,\n RuleType,\n Schema,\n} from 'react-querybuilder';\nimport type {\n AdapterUseInlineCombinatorDnDResult,\n AdapterUseRuleDnDResult,\n AdapterUseRuleGroupDnDResult,\n DndAdapter,\n DndAdapterInlineCombinatorDnDParams,\n DndAdapterProviderProps,\n DndAdapterRuleDnDParams,\n DndAdapterRuleGroupDnDParams,\n} from '../adapter';\nimport {\n buildDropResult,\n canDropOnInlineCombinator,\n canDropOnRule,\n canDropOnRuleGroup,\n getDragItem,\n handleDrop,\n} from '../dndLogic';\nimport { DragPreviewContext } from '../DragPreviewContext';\nimport type { DragPreviewContextValue } from '../DragPreviewContext';\nimport { isHotkeyPressed } from '../isHotkeyPressed';\nimport { computeShadowQuery } from '../shadowQuery';\nimport type { DragPreviewState, OnDragMoveCallback } from '../types';\n\n/**\n * The `@dnd-kit/core` exports needed by the adapter.\n *\n * @group DnD\n */\nexport type DndKitExports = {\n DndContext: typeof DndContextImport;\n useDraggable: typeof useDraggableImport;\n useDroppable: typeof useDroppableImport;\n PointerSensor: typeof PointerSensorImport;\n KeyboardSensor: typeof KeyboardSensorImport;\n useSensor: typeof useSensorImport;\n useSensors: typeof useSensorsImport;\n};\n\n// #region Internal context\n\ninterface DndKitDragState {\n activeDragItem: DraggedItem | null;\n timerCopyMode: boolean;\n timerGroupMode: boolean;\n}\n\nconst defaultDragState: DndKitDragState = {\n activeDragItem: null,\n timerCopyMode: false,\n timerGroupMode: false,\n};\nconst DragStateContext = createContext(defaultDragState);\n\n// #endregion\n\n// #region Helpers\n\nconst getDragId = (type: DndDropTargetType, path: number[], qbId: string): string =>\n `drag-${type}-${qbId}-${path.join('_')}`;\n\nconst getDropId = (\n type: DndDropTargetType | 'inlineCombinator',\n path: number[],\n qbId: string\n): string => `drop-${type}-${qbId}-${path.join('_')}`;\n\n/**\n * Attaches dnd-kit's React synthetic event listeners (e.g. `onPointerDown`)\n * as native DOM event listeners on the given node. This bridges the gap\n * between the ref-based adapter interface and dnd-kit's listener-based API.\n */\nconst useNativeListeners = (\n nodeRef: React.RefObject<HTMLElement | null>,\n listeners: Record<string, Function> | undefined\n): void => {\n useEffect(() => {\n const node = nodeRef.current;\n if (!node || !listeners) return undefined;\n\n const nativeHandlers: [string, EventListener][] = [];\n\n for (const [reactEventName, handler] of Object.entries(listeners)) {\n const nativeEventName = reactEventName.slice(2).toLowerCase();\n const nativeHandler: EventListener = e => {\n // Need to make sure the instance type stays the same, so add property\n // instead of create new event with nativeEvent property\n (e as Event & { nativeEvent: Event }).nativeEvent = e;\n return handler(e);\n };\n node.addEventListener(nativeEventName, nativeHandler);\n nativeHandlers.push([nativeEventName, nativeHandler]);\n }\n\n return () => {\n for (const [name, handler] of nativeHandlers) {\n node.removeEventListener(name, handler);\n }\n };\n }, [nodeRef, listeners]);\n};\n\n// #endregion\n\n/**\n * Creates a {@link DndAdapter} backed by `@dnd-kit/core`.\n *\n * The adapter uses `setActivatorNodeRef` for drag handles, so sensor listeners\n * are automatically attached to the correct element without imperative DOM\n * manipulation.\n *\n * @example\n * ```tsx\n * import { QueryBuilderDnD } from '@react-querybuilder/dnd';\n * import { createDndKitAdapter } from '@react-querybuilder/dnd/dnd-kit';\n * import * as DndKit from '@dnd-kit/core';\n *\n * const adapter = createDndKitAdapter(DndKit);\n *\n * <QueryBuilderDnD dnd={adapter}>\n * <QueryBuilder />\n * </QueryBuilderDnD>\n * ```\n *\n * @group DnD\n */\nexport const createDndKitAdapter = (dndKitExports: DndKitExports): DndAdapter => {\n const {\n DndContext,\n useDraggable,\n useDroppable,\n PointerSensor,\n KeyboardSensor,\n useSensor,\n useSensors,\n } = dndKitExports;\n\n // #region DndProvider\n\n const DndProvider = ({\n children,\n updateWhileDragging,\n copyModeAfterHoverMs,\n groupModeAfterHoverMs,\n }: DndAdapterProviderProps): React.JSX.Element => {\n const [activeDragItem, setActiveDragItem] = useState<DraggedItem | null>(null);\n const activeDragItemRef = useRef<DraggedItem | null>(null);\n // oxlint-disable-next-line typescript/no-explicit-any\n const dragSchemaRef = useRef<Schema<any, any> | null>(null);\n\n // --- Hover timer state ---\n const [timerCopyMode, setTimerCopyMode] = useState(false);\n const [timerGroupMode, setTimerGroupMode] = useState(false);\n const timerCopyModeRef = useRef(false);\n const timerGroupModeRef = useRef(false);\n const copyTimerIdRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const groupTimerIdRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const lastHoverTargetIdRef = useRef<string | null>(null);\n\n const clearHoverTimers = useCallback(() => {\n if (copyTimerIdRef.current !== null) {\n clearTimeout(copyTimerIdRef.current);\n copyTimerIdRef.current = null;\n }\n if (groupTimerIdRef.current !== null) {\n clearTimeout(groupTimerIdRef.current);\n groupTimerIdRef.current = null;\n }\n timerCopyModeRef.current = false;\n timerGroupModeRef.current = false;\n setTimerCopyMode(false);\n setTimerGroupMode(false);\n lastHoverTargetIdRef.current = null;\n }, []);\n\n const startHoverTimers = useCallback(\n (targetId: string) => {\n if (lastHoverTargetIdRef.current === targetId) return;\n\n clearHoverTimers();\n lastHoverTargetIdRef.current = targetId;\n\n if (copyModeAfterHoverMs && copyModeAfterHoverMs > 0) {\n copyTimerIdRef.current = setTimeout(() => {\n timerCopyModeRef.current = true;\n setTimerCopyMode(true);\n copyTimerIdRef.current = null;\n }, copyModeAfterHoverMs);\n }\n if (groupModeAfterHoverMs && groupModeAfterHoverMs > 0) {\n groupTimerIdRef.current = setTimeout(() => {\n timerGroupModeRef.current = true;\n setTimerGroupMode(true);\n groupTimerIdRef.current = null;\n }, groupModeAfterHoverMs);\n }\n },\n [clearHoverTimers, copyModeAfterHoverMs, groupModeAfterHoverMs]\n );\n\n // --- Update-while-dragging state ---\n const [dragPreviewState, setDragPreviewState] = useState<DragPreviewState | null>(null);\n const dragPreviewStateRef = useRef<DragPreviewState | null>(null);\n const onDragMoveRef = useRef<OnDragMoveCallback | undefined>(undefined);\n const lastTargetRef = useRef<{\n targetPath: Path;\n targetType: DndDropTargetType;\n quadrant: 'upper' | 'lower';\n } | null>(null);\n\n const updatePreviewPosition = useCallback(\n (targetPath: Path, targetType: DndDropTargetType, quadrant: 'upper' | 'lower') => {\n const currentPreview = dragPreviewStateRef.current;\n // v8 ignore next\n if (!currentPreview || !updateWhileDragging) return;\n\n const last = lastTargetRef.current;\n if (\n last &&\n last.quadrant === quadrant &&\n last.targetType === targetType &&\n last.targetPath.length === targetPath.length &&\n last.targetPath.every((v, i) => v === targetPath[i])\n ) {\n return;\n }\n lastTargetRef.current = { targetPath, targetType, quadrant };\n\n // v8 ignore next -- hotkey branch tested in hotkey-specific tests\n const dropEffect =\n timerCopyModeRef.current ||\n isHotkeyPressed(currentPreview.dropEffect === 'copy' ? 'alt' : '')\n ? 'copy'\n : 'move';\n const groupItems = timerGroupModeRef.current || isHotkeyPressed('ctrl');\n\n const result = computeShadowQuery({\n originalQuery: currentPreview.originalQuery,\n draggedItem: activeDragItemRef.current!,\n draggedPath: currentPreview.draggedPath,\n targetPath,\n targetType,\n quadrant,\n dropEffect,\n groupItems,\n });\n\n if (result) {\n const newState: DragPreviewState = {\n ...currentPreview,\n shadowQuery: result.shadowQuery,\n previewPath: result.previewPath,\n dropEffect,\n groupItems,\n };\n dragPreviewStateRef.current = newState;\n setDragPreviewState(newState);\n\n onDragMoveRef.current?.({\n draggedItem: activeDragItemRef.current!,\n shadowQuery: result.shadowQuery,\n originalQuery: currentPreview.originalQuery,\n previewPath: result.previewPath,\n });\n }\n },\n [updateWhileDragging]\n );\n\n const commitDrag = useCallback(() => {\n const preview = dragPreviewStateRef.current;\n // v8 ignore next\n if (!preview) return;\n\n const schema = dragSchemaRef.current;\n if (schema && preview.shadowQuery !== preview.originalQuery) {\n schema.dispatchQuery(preview.shadowQuery);\n }\n\n dragSchemaRef.current = null;\n dragPreviewStateRef.current = null;\n lastTargetRef.current = null;\n setDragPreviewState(null);\n }, []);\n\n const cancelDrag = useCallback(() => {\n dragSchemaRef.current = null;\n dragPreviewStateRef.current = null;\n lastTargetRef.current = null;\n setDragPreviewState(null);\n }, []);\n\n const sensors = useSensors(\n useSensor(PointerSensor, { activationConstraint: { distance: 5 } }),\n useSensor(KeyboardSensor)\n );\n\n const handleDragStart = useCallback(\n // oxlint-disable-next-line typescript/no-explicit-any\n (event: any) => {\n const data = event.active?.data?.current;\n if (data?.path && data?.schema) {\n const item = getDragItem(data.path, data.schema);\n activeDragItemRef.current = item;\n setActiveDragItem(item);\n\n if (updateWhileDragging) {\n dragSchemaRef.current = data.schema;\n const originalQuery = data.schema.getQuery();\n const initialState: DragPreviewState = {\n shadowQuery: originalQuery,\n originalQuery,\n draggedPath: data.path as Path,\n previewPath: data.path as Path,\n dropEffect: 'move',\n groupItems: false,\n qbId: data.schema.qbId,\n };\n dragPreviewStateRef.current = initialState;\n setDragPreviewState(initialState);\n }\n }\n },\n [updateWhileDragging]\n );\n\n // Handle continuous drag movement for updateWhileDragging\n const handleDragOver = useCallback(\n // oxlint-disable-next-line typescript/no-explicit-any\n (event: any) => {\n const { over } = event;\n\n // Manage hover timers for copy/group mode\n if (over) {\n const targetData = over.data?.current;\n const targetType = targetData?.type as DndDropTargetType | undefined;\n const targetPath = targetData?.path as Path | undefined;\n if (targetType && targetPath) {\n const targetId = `${targetType}-${targetPath.join('_')}`;\n startHoverTimers(targetId);\n }\n } else {\n clearHoverTimers();\n }\n\n // v8 ignore next\n if (!updateWhileDragging || !dragPreviewStateRef.current) return;\n\n if (!over) return;\n\n const { activatorEvent, delta } = event;\n const targetData = over.data?.current;\n const targetType = targetData?.type as DndDropTargetType | undefined;\n const targetPath = targetData?.path as Path | undefined;\n\n if (!targetType || !targetPath) return;\n\n // Compute current clientY from activator event + delta\n // v8 ignore next -- activatorEvent and delta always provided by dnd-kit\n const initialY = (activatorEvent as PointerEvent | undefined)?.clientY ?? 0;\n // v8 ignore next\n const clientY = initialY + (delta?.y ?? 0);\n\n // For rule groups, always use 'upper' (insert as first child).\n // For rules, use quadrant detection on the droppable's rect.\n let quadrant: 'upper' | 'lower' | null;\n if (targetType === 'ruleGroup') {\n quadrant = 'upper';\n } else {\n // over.rect is the droppable container's bounding rect from dnd-kit\n const rect = over.rect;\n if (rect) {\n // v8 ignore next -- rect always has height from dnd-kit\n const height = rect.height ?? rect.bottom - rect.top;\n const quarterHeight = height / 4;\n // v8 ignore next -- rect always has top from dnd-kit\n const top = rect.top ?? rect.offsetTop ?? 0;\n const bottom = top + height;\n if (clientY < top + quarterHeight) {\n quadrant = 'upper';\n } else if (clientY > bottom - quarterHeight) {\n quadrant = 'lower';\n } else {\n quadrant = null;\n }\n } else {\n quadrant = null;\n }\n }\n\n if (!quadrant) return;\n\n const dragItem = activeDragItemRef.current;\n // v8 ignore next\n if (!dragItem) return;\n\n const validate = targetData?.validate as ((item: DraggedItem) => boolean) | undefined;\n if (validate && !validate(dragItem)) return;\n\n updatePreviewPosition(targetPath, targetType, quadrant);\n },\n [updateWhileDragging, updatePreviewPosition, startHoverTimers, clearHoverTimers]\n );\n\n const handleDragEnd = useCallback(\n // oxlint-disable-next-line typescript/no-explicit-any\n (event: any) => {\n const dragItem = activeDragItemRef.current;\n const { over, active } = event;\n\n // Capture timer overrides before clearing\n const copyOverride = timerCopyModeRef.current;\n const groupOverride = timerGroupModeRef.current;\n clearHoverTimers();\n\n if (updateWhileDragging && dragPreviewStateRef.current) {\n if (over) {\n commitDrag();\n } else {\n cancelDrag();\n }\n } else if (over && dragItem) {\n const sourceData = active?.data?.current;\n const targetData = over?.data?.current;\n\n if (sourceData && targetData?.validate?.(dragItem)) {\n const dropResult = targetData.getDropResult();\n handleDrop({\n item: dragItem,\n dropResult,\n schema: sourceData.schema,\n actions: sourceData.actions,\n copyModeModifierKey: sourceData.copyModeModifierKey,\n groupModeModifierKey: sourceData.groupModeModifierKey,\n copyModeOverride: copyOverride,\n groupModeOverride: groupOverride,\n onRuleDrop: sourceData.onRuleDrop,\n });\n }\n }\n\n activeDragItemRef.current = null;\n setActiveDragItem(null);\n },\n [updateWhileDragging, commitDrag, cancelDrag, clearHoverTimers]\n );\n\n const handleDragCancel = useCallback(() => {\n clearHoverTimers();\n if (updateWhileDragging && dragPreviewStateRef.current) {\n cancelDrag();\n }\n activeDragItemRef.current = null;\n setActiveDragItem(null);\n }, [updateWhileDragging, cancelDrag, clearHoverTimers]);\n\n const dragStateValue = useMemo<DndKitDragState>(\n () => ({ activeDragItem, timerCopyMode, timerGroupMode }),\n [activeDragItem, timerCopyMode, timerGroupMode]\n );\n\n const dragPreviewContextValue = useMemo<DragPreviewContextValue>(\n () => ({\n dragPreviewState,\n updatePreviewPosition,\n commitDrag,\n cancelDrag,\n }),\n [dragPreviewState, updatePreviewPosition, commitDrag, cancelDrag]\n );\n\n return (\n <DndContext\n sensors={sensors}\n onDragStart={handleDragStart}\n onDragEnd={handleDragEnd}\n onDragOver={handleDragOver}\n onDragCancel={handleDragCancel}>\n <DragStateContext.Provider value={dragStateValue}>\n <DragPreviewContext.Provider value={dragPreviewContextValue}>\n {children}\n </DragPreviewContext.Provider>\n </DragStateContext.Provider>\n </DndContext>\n );\n };\n\n // #endregion\n\n // #region useRuleDnD\n\n const useRuleDnD = (params: DndAdapterRuleDnDParams): AdapterUseRuleDnDResult => {\n const { activeDragItem, timerCopyMode, timerGroupMode } = useContext(DragStateContext);\n const activatorNodeRef = useRef<HTMLSpanElement>(null);\n const containerNodeRef = useRef<HTMLDivElement>(null);\n\n const dragId = getDragId('rule', params.path, params.schema.qbId);\n const dropId = getDropId('rule', params.path, params.schema.qbId);\n\n const {\n setNodeRef: setDragNodeRef,\n setActivatorNodeRef,\n isDragging,\n listeners,\n attributes,\n } = useDraggable({\n id: dragId,\n disabled: params.disabled,\n data: {\n path: params.path,\n schema: params.schema,\n actions: params.actions,\n copyModeModifierKey: params.copyModeModifierKey,\n groupModeModifierKey: params.groupModeModifierKey,\n onRuleDrop: params.onRuleDrop,\n },\n });\n\n const { setNodeRef: setDropNodeRef, isOver: rawIsOver } = useDroppable({\n id: dropId,\n data: {\n type: 'rule' as DndDropTargetType,\n path: params.path,\n schema: params.schema,\n validate: (dragging: DraggedItem) =>\n canDropOnRule({\n dragging,\n path: params.path,\n schema: params.schema,\n canDrop: params.canDrop,\n groupModeModifierKey: params.groupModeModifierKey,\n disabled: params.disabled,\n rule: params.rule,\n }),\n getDropResult: () =>\n buildDropResult({\n type: 'rule',\n path: params.path,\n schema: params.schema,\n copyModeModifierKey: params.copyModeModifierKey,\n groupModeModifierKey: params.groupModeModifierKey,\n }),\n },\n });\n\n // Compute validated isOver + dropNotAllowed\n const canDropHere =\n rawIsOver &&\n !!activeDragItem &&\n canDropOnRule({\n dragging: activeDragItem,\n path: params.path,\n schema: params.schema,\n canDrop: params.canDrop,\n groupModeModifierKey: params.groupModeModifierKey,\n disabled: params.disabled,\n rule: params.rule,\n });\n const isOver = rawIsOver && canDropHere;\n const dropNotAllowed = rawIsOver && !canDropHere;\n\n // Combined container ref: both draggable and droppable\n const dndRef: React.RefCallback<HTMLDivElement> = useCallback(\n (node: HTMLDivElement | null) => {\n containerNodeRef.current = node;\n setDragNodeRef(node);\n setDropNodeRef(node);\n },\n [setDragNodeRef, setDropNodeRef]\n );\n\n // Drag handle ref: activator node\n const dragRef: React.RefCallback<HTMLSpanElement> = useCallback(\n (node: HTMLSpanElement | null) => {\n activatorNodeRef.current = node;\n setActivatorNodeRef(node);\n },\n [setActivatorNodeRef]\n );\n\n // Set ARIA attributes on drag handle\n useEffect(() => {\n const node = activatorNodeRef.current;\n if (!node || !attributes) return;\n for (const [key, value] of Object.entries(attributes)) {\n if (value != null) {\n node.setAttribute(key === 'tabIndex' ? 'tabindex' : key, String(value));\n }\n }\n }, [attributes]);\n\n // Attach sensor listeners (e.g. onPointerDown) to the drag handle\n useNativeListeners(activatorNodeRef, listeners);\n\n return {\n isDragging,\n dragMonitorId: dragId,\n isOver,\n dropMonitorId: dropId,\n dndRef,\n dragRef,\n dropEffect: timerCopyMode || isHotkeyPressed(params.copyModeModifierKey) ? 'copy' : 'move',\n groupItems: timerGroupMode || isHotkeyPressed(params.groupModeModifierKey),\n dropNotAllowed,\n };\n };\n\n // #endregion\n\n // #region useRuleGroupDnD\n\n const useRuleGroupDnD = (params: DndAdapterRuleGroupDnDParams): AdapterUseRuleGroupDnDResult => {\n const { activeDragItem, timerCopyMode, timerGroupMode } = useContext(DragStateContext);\n const activatorNodeRef = useRef<HTMLSpanElement>(null);\n\n const dragId = getDragId('ruleGroup', params.path, params.schema.qbId);\n const dropId = getDropId('ruleGroup', params.path, params.schema.qbId);\n\n const isDragDisabled = params.disabled || params.path.length === 0;\n\n const {\n setNodeRef: setDragNodeRef,\n setActivatorNodeRef,\n isDragging,\n listeners,\n attributes,\n } = useDraggable({\n id: dragId,\n disabled: isDragDisabled,\n data: {\n path: params.path,\n schema: params.schema,\n actions: params.actions,\n copyModeModifierKey: params.copyModeModifierKey,\n groupModeModifierKey: params.groupModeModifierKey,\n onRuleDrop: params.onRuleDrop,\n },\n });\n\n const { setNodeRef: setDropNodeRef, isOver: rawIsOver } = useDroppable({\n id: dropId,\n data: {\n type: 'ruleGroup' as DndDropTargetType,\n path: params.path,\n schema: params.schema,\n validate: (dragging: DraggedItem) =>\n canDropOnRuleGroup({\n dragging,\n path: params.path,\n schema: params.schema,\n canDrop: params.canDrop,\n disabled: params.disabled,\n ruleGroup: params.ruleGroup,\n }),\n getDropResult: () =>\n buildDropResult({\n type: 'ruleGroup',\n path: params.path,\n schema: params.schema,\n copyModeModifierKey: params.copyModeModifierKey,\n groupModeModifierKey: params.groupModeModifierKey,\n }),\n },\n });\n\n // Compute validated isOver + dropNotAllowed\n const canDropHere =\n rawIsOver &&\n !!activeDragItem &&\n canDropOnRuleGroup({\n dragging: activeDragItem,\n path: params.path,\n schema: params.schema,\n canDrop: params.canDrop,\n disabled: params.disabled,\n ruleGroup: params.ruleGroup,\n });\n const isOver = rawIsOver && canDropHere;\n const dropNotAllowed = rawIsOver && !canDropHere;\n\n // Preview ref: draggable container (for visual measurement)\n const previewRef: React.RefCallback<HTMLDivElement> = useCallback(\n (node: HTMLDivElement | null) => {\n setDragNodeRef(node);\n },\n [setDragNodeRef]\n );\n\n // Drop ref: header element\n const dropRef: React.RefCallback<HTMLDivElement> = useCallback(\n (node: HTMLDivElement | null) => {\n setDropNodeRef(node);\n },\n [setDropNodeRef]\n );\n\n // Drag handle ref: activator node\n const dragRef: React.RefCallback<HTMLSpanElement> = useCallback(\n (node: HTMLSpanElement | null) => {\n activatorNodeRef.current = node;\n setActivatorNodeRef(node);\n },\n [setActivatorNodeRef]\n );\n\n // Set ARIA attributes on drag handle\n useEffect(() => {\n const node = activatorNodeRef.current;\n if (!node || !attributes || isDragDisabled) return;\n for (const [key, value] of Object.entries(attributes)) {\n if (value != null) {\n node.setAttribute(key === 'tabIndex' ? 'tabindex' : key, String(value));\n }\n }\n }, [attributes, isDragDisabled]);\n\n // Attach sensor listeners (e.g. onPointerDown) to the drag handle\n useNativeListeners(activatorNodeRef, listeners);\n\n return {\n isDragging,\n dragMonitorId: dragId,\n isOver,\n dropMonitorId: dropId,\n previewRef,\n dragRef,\n dropRef,\n dropEffect: timerCopyMode || isHotkeyPressed(params.copyModeModifierKey) ? 'copy' : 'move',\n groupItems: timerGroupMode || isHotkeyPressed(params.groupModeModifierKey),\n dropNotAllowed,\n };\n };\n\n // #endregion\n\n // #region useInlineCombinatorDnD\n\n const useInlineCombinatorDnD = (\n params: DndAdapterInlineCombinatorDnDParams\n ): AdapterUseInlineCombinatorDnDResult => {\n const { activeDragItem, timerCopyMode } = useContext(DragStateContext);\n\n const dropId = getDropId('inlineCombinator', params.path, params.schema.qbId);\n\n // The \"hovering\" item is the rule/group preceding this inline combinator.\n const hoveringItem = (params.rules ??\n /* v8 ignore start -- @preserve */ []) /* v8 ignore stop -- @preserve */[\n params.path.at(-1)! - 1\n ] as RuleType | RuleGroupTypeAny;\n\n const { setNodeRef: setDropNodeRef, isOver: rawIsOver } = useDroppable({\n id: dropId,\n data: {\n type: 'inlineCombinator' as DndDropTargetType,\n path: params.path,\n schema: params.schema,\n validate: (dragging: DraggedItem) =>\n canDropOnInlineCombinator({\n dragging,\n path: params.path,\n schema: params.schema,\n canDrop: params.canDrop,\n groupModeModifierKey: params.groupModeModifierKey,\n hoveringItem,\n }),\n getDropResult: () =>\n buildDropResult({\n type: 'inlineCombinator',\n path: params.path,\n schema: params.schema,\n copyModeModifierKey: params.copyModeModifierKey,\n groupModeModifierKey: params.groupModeModifierKey,\n }),\n },\n });\n\n // Compute validated isOver + dropNotAllowed\n const canDropHere =\n rawIsOver &&\n !!activeDragItem &&\n canDropOnInlineCombinator({\n dragging: activeDragItem,\n path: params.path,\n schema: params.schema,\n canDrop: params.canDrop,\n groupModeModifierKey: params.groupModeModifierKey,\n hoveringItem,\n });\n const isOver = rawIsOver && canDropHere;\n const dropNotAllowed = rawIsOver && !canDropHere;\n\n const dropRef: React.RefCallback<HTMLDivElement> = useCallback(\n (node: HTMLDivElement | null) => {\n setDropNodeRef(node);\n },\n [setDropNodeRef]\n );\n\n return {\n dropRef,\n dropMonitorId: dropId,\n isOver,\n dropEffect: timerCopyMode || isHotkeyPressed(params.copyModeModifierKey) ? 'copy' : 'move',\n dropNotAllowed,\n };\n };\n\n // #endregion\n\n return {\n DndProvider,\n useRuleDnD,\n useRuleGroupDnD,\n useInlineCombinatorDnD,\n };\n};\n"],"mappings":"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"}