@almadar/ui 4.50.4 → 4.50.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -21340,12 +21340,17 @@ function useDataDnd(args) {
21340
21340
  React81__namespace.default.useEffect(() => {
21341
21341
  setLocalOrder(null);
21342
21342
  }, [items]);
21343
+ const itemIdsSignature = orderedItems.map((it, idx) => {
21344
+ const raw = it[dndItemIdField];
21345
+ return String(raw ?? `__idx_${idx}`);
21346
+ }).join("|");
21343
21347
  const itemIds = React81__namespace.default.useMemo(
21344
21348
  () => orderedItems.map((it, idx) => {
21345
21349
  const raw = it[dndItemIdField];
21346
21350
  return raw ?? `__idx_${idx}`;
21347
21351
  }),
21348
- [orderedItems, dndItemIdField]
21352
+ // eslint-disable-next-line react-hooks/exhaustive-deps
21353
+ [itemIdsSignature]
21349
21354
  );
21350
21355
  const zonesRef = React81__namespace.default.useRef(/* @__PURE__ */ new Map());
21351
21356
  const registerZone = React81__namespace.default.useCallback((zoneId2, meta2) => {
@@ -21354,10 +21359,6 @@ function useDataDnd(args) {
21354
21359
  const unregisterZone = React81__namespace.default.useCallback((zoneId2) => {
21355
21360
  zonesRef.current.delete(zoneId2);
21356
21361
  }, []);
21357
- const [overlayNode, setOverlayNode] = React81__namespace.default.useState(null);
21358
- const setOverlay = React81__namespace.default.useCallback((node) => {
21359
- setOverlayNode(node);
21360
- }, []);
21361
21362
  const zoneId = React81__namespace.default.useId();
21362
21363
  const ownGroup = dragGroup ?? accepts ?? zoneId;
21363
21364
  const meta = React81__namespace.default.useMemo(
@@ -21368,10 +21369,18 @@ function useDataDnd(args) {
21368
21369
  const target = isRoot ? null : parentRoot;
21369
21370
  if (!target) {
21370
21371
  zonesRef.current.set(zoneId, meta);
21371
- return () => zonesRef.current.delete(zoneId);
21372
+ dndLog.debug("zone:register:self", { zoneId, group: meta.group, itemCount: meta.itemIds.length, isRoot });
21373
+ return () => {
21374
+ zonesRef.current.delete(zoneId);
21375
+ dndLog.debug("zone:unregister:self", { zoneId, group: meta.group });
21376
+ };
21372
21377
  }
21373
21378
  target.registerZone(zoneId, meta);
21374
- return () => target.unregisterZone(zoneId);
21379
+ dndLog.debug("zone:register", { zoneId, group: meta.group, itemCount: meta.itemIds.length, dropEvent: meta.dropEvent, reorderEvent: meta.reorderEvent });
21380
+ return () => {
21381
+ target.unregisterZone(zoneId);
21382
+ dndLog.debug("zone:unregister", { zoneId, group: meta.group });
21383
+ };
21375
21384
  }, [parentRoot, isRoot, zoneId, meta]);
21376
21385
  const sensors = core$1.useSensors(
21377
21386
  core$1.useSensor(core$1.PointerSensor, { activationConstraint: { distance: 5 } }),
@@ -21379,10 +21388,18 @@ function useDataDnd(args) {
21379
21388
  );
21380
21389
  const collisionDetection = React81__namespace.default.useCallback((args2) => {
21381
21390
  const pointerCollisions = core$1.pointerWithin(args2);
21382
- if (pointerCollisions.length > 0) return pointerCollisions;
21391
+ if (pointerCollisions.length > 0) {
21392
+ dndLog.debug("collision:pointerWithin", { count: pointerCollisions.length, ids: pointerCollisions.map((c) => c.id) });
21393
+ return pointerCollisions;
21394
+ }
21383
21395
  const rectCollisions = core$1.rectIntersection(args2);
21384
- if (rectCollisions.length > 0) return rectCollisions;
21385
- return core$1.closestCorners(args2);
21396
+ if (rectCollisions.length > 0) {
21397
+ dndLog.debug("collision:rectIntersection", { count: rectCollisions.length, ids: rectCollisions.map((c) => c.id) });
21398
+ return rectCollisions;
21399
+ }
21400
+ const cornerCollisions = core$1.closestCorners(args2);
21401
+ dndLog.debug("collision:closestCorners", { count: cornerCollisions.length, ids: cornerCollisions.map((c) => c.id) });
21402
+ return cornerCollisions;
21386
21403
  }, []);
21387
21404
  const findZoneByItem = React81__namespace.default.useCallback(
21388
21405
  (id) => {
@@ -21405,22 +21422,52 @@ function useDataDnd(args) {
21405
21422
  const handleDragEnd = React81__namespace.default.useCallback(
21406
21423
  (event) => {
21407
21424
  const { active, over } = event;
21408
- if (!over) return;
21425
+ const allZones = Array.from(zonesRef.current.entries()).map(([id, m]) => ({ id, group: m.group, items: m.itemIds.length }));
21426
+ dndLog.debug("dragEnd:received", {
21427
+ activeId: active.id,
21428
+ overId: over?.id,
21429
+ overData: over?.data?.current,
21430
+ zones: allZones
21431
+ });
21432
+ if (!over) {
21433
+ dndLog.warn("dragEnd:abort:no-over", { activeId: active.id, reason: "no droppable under pointer at drop time \u2192 item snaps back" });
21434
+ return;
21435
+ }
21409
21436
  const sourceZone = findZoneByItem(active.id);
21410
21437
  const overData = over.data?.current;
21411
21438
  const targetGroup = overData?.dndGroup;
21412
- if (!sourceZone || !targetGroup) return;
21439
+ dndLog.debug("dragEnd:resolved", { sourceGroup: sourceZone?.group, targetGroup, overDataKeys: overData ? Object.keys(overData) : null });
21440
+ if (!sourceZone) {
21441
+ dndLog.warn("dragEnd:abort:no-source-zone", { activeId: active.id });
21442
+ return;
21443
+ }
21444
+ if (!targetGroup) {
21445
+ dndLog.warn("dragEnd:abort:no-target-group", { overId: over.id, overData });
21446
+ return;
21447
+ }
21413
21448
  const targetZone = findZoneByGroup(targetGroup);
21414
- if (!targetZone) return;
21449
+ if (!targetZone) {
21450
+ dndLog.warn("dragEnd:abort:target-zone-not-registered", { targetGroup });
21451
+ return;
21452
+ }
21415
21453
  if (sourceZone.group !== targetZone.group) {
21416
21454
  if (targetZone.dropEvent) {
21417
21455
  const newIndex2 = targetZone.itemIds.indexOf(over.id);
21456
+ dndLog.info("dragEnd:cross-container:emit", {
21457
+ event: targetZone.dropEvent,
21458
+ id: String(active.id),
21459
+ sourceGroup: sourceZone.group,
21460
+ targetGroup: targetZone.group,
21461
+ newIndex: newIndex2 === -1 ? targetZone.itemIds.length : newIndex2
21462
+ });
21418
21463
  eventBus.emit(targetZone.dropEvent, {
21419
21464
  id: String(active.id),
21420
21465
  sourceGroup: sourceZone.group,
21421
21466
  targetGroup: targetZone.group,
21422
21467
  newIndex: newIndex2 === -1 ? targetZone.itemIds.length : newIndex2
21423
21468
  });
21469
+ } else {
21470
+ dndLog.warn("dragEnd:cross-container:no-dropEvent-on-target", { targetGroup: targetZone.group });
21424
21471
  }
21425
21472
  return;
21426
21473
  }
@@ -21432,16 +21479,24 @@ function useDataDnd(args) {
21432
21479
  setLocalOrder(reordered);
21433
21480
  }
21434
21481
  if (sourceZone.reorderEvent) {
21482
+ dndLog.info("dragEnd:reorder:emit", {
21483
+ event: sourceZone.reorderEvent,
21484
+ id: String(active.id),
21485
+ oldIndex,
21486
+ newIndex
21487
+ });
21435
21488
  eventBus.emit(sourceZone.reorderEvent, {
21436
21489
  id: String(active.id),
21437
21490
  oldIndex,
21438
21491
  newIndex
21439
21492
  });
21493
+ } else {
21494
+ dndLog.debug("dragEnd:reorder:no-reorderEvent", { sourceGroup: sourceZone.group });
21440
21495
  }
21441
21496
  },
21442
21497
  [orderedItems, ownGroup, findZoneByItem, findZoneByGroup, eventBus]
21443
21498
  );
21444
- const overlaySink = isRoot ? setOverlay : parentRoot?.setOverlay;
21499
+ const sortableData = React81__namespace.default.useMemo(() => ({ dndGroup: ownGroup }), [ownGroup]);
21445
21500
  const SortableItem = React81__namespace.default.useCallback(
21446
21501
  ({ id, children }) => {
21447
21502
  const {
@@ -21451,19 +21506,16 @@ function useDataDnd(args) {
21451
21506
  transform,
21452
21507
  transition,
21453
21508
  isDragging
21454
- } = sortable.useSortable({ id, data: { dndGroup: ownGroup } });
21455
- const childrenRef = React81__namespace.default.useRef(children);
21456
- childrenRef.current = children;
21457
- React81__namespace.default.useEffect(() => {
21458
- if (!isDragging || !overlaySink) return;
21459
- overlaySink(childrenRef.current);
21460
- return () => overlaySink(null);
21461
- }, [isDragging]);
21509
+ } = sortable.useSortable({ id, data: sortableData });
21462
21510
  const style = {
21463
21511
  transform: utilities.CSS.Transform.toString(transform),
21464
21512
  transition,
21465
21513
  opacity: isDragging ? 0.4 : 1,
21466
- cursor: enabled ? "grab" : void 0
21514
+ cursor: enabled ? "grab" : void 0,
21515
+ // Lift the dragged element above siblings so its visual movement
21516
+ // isn't hidden behind other cards / column boundaries.
21517
+ zIndex: isDragging ? 50 : void 0,
21518
+ position: isDragging ? "relative" : void 0
21467
21519
  };
21468
21520
  return /* @__PURE__ */ jsxRuntime.jsx(
21469
21521
  Box,
@@ -21477,73 +21529,91 @@ function useDataDnd(args) {
21477
21529
  }
21478
21530
  );
21479
21531
  },
21480
- [ownGroup, enabled, overlaySink]
21532
+ [sortableData, enabled]
21481
21533
  );
21482
21534
  const DropZoneShell = ({ children }) => {
21535
+ const droppableId = `dnd-zone-${zoneId}`;
21483
21536
  const { setNodeRef, isOver } = core$1.useDroppable({
21484
- id: `dnd-zone-${zoneId}`,
21485
- data: { dndGroup: ownGroup }
21537
+ id: droppableId,
21538
+ data: sortableData
21486
21539
  });
21540
+ React81__namespace.default.useEffect(() => {
21541
+ dndLog.debug("dropzone:isOver:change", { droppableId, group: ownGroup, isOver });
21542
+ }, [droppableId, isOver]);
21487
21543
  return /* @__PURE__ */ jsxRuntime.jsx(
21488
21544
  Box,
21489
21545
  {
21490
21546
  ref: setNodeRef,
21491
21547
  "data-dnd-zone": ownGroup,
21548
+ "data-dnd-is-over": isOver ? "true" : "false",
21492
21549
  className: isOver ? "ring-2 ring-primary ring-offset-2 rounded-lg transition-all min-h-[3rem]" : "min-h-[3rem] rounded-lg transition-all",
21493
21550
  children
21494
21551
  }
21495
21552
  );
21496
21553
  };
21497
21554
  const rootContextValue = React81__namespace.default.useMemo(
21498
- () => ({ registerZone, unregisterZone, setOverlay }),
21499
- [registerZone, unregisterZone, setOverlay]
21555
+ () => ({ registerZone, unregisterZone }),
21556
+ [registerZone, unregisterZone]
21500
21557
  );
21558
+ const handleDragStart = React81__namespace.default.useCallback((event) => {
21559
+ const sourceZone = findZoneByItem(event.active.id);
21560
+ dndLog.info("dragStart", {
21561
+ activeId: event.active.id,
21562
+ activeData: event.active.data?.current,
21563
+ sourceGroup: sourceZone?.group,
21564
+ zoneCount: zonesRef.current.size
21565
+ });
21566
+ }, [findZoneByItem]);
21567
+ const handleDragOver = React81__namespace.default.useCallback((event) => {
21568
+ dndLog.debug("dragOver", {
21569
+ activeId: event.active.id,
21570
+ overId: event.over?.id,
21571
+ overData: event.over?.data?.current
21572
+ });
21573
+ }, []);
21574
+ const handleDragCancel = React81__namespace.default.useCallback((event) => {
21575
+ dndLog.warn("dragCancel", {
21576
+ activeId: event.active.id,
21577
+ reason: "dnd-kit cancelled the drag (escape key, pointer interrupted, or external)"
21578
+ });
21579
+ }, []);
21501
21580
  const wrapContainer = React81__namespace.default.useCallback(
21502
21581
  (children) => {
21503
21582
  if (!enabled) return children;
21504
21583
  const strategy = layout === "grid" ? sortable.rectSortingStrategy : sortable.verticalListSortingStrategy;
21505
- const clearOverlay = () => setOverlay(null);
21506
21584
  if (!isZone) {
21507
21585
  if (!isRoot) return children;
21508
- return /* @__PURE__ */ jsxRuntime.jsx(RootCtx.Provider, { value: rootContextValue, children: /* @__PURE__ */ jsxRuntime.jsxs(
21586
+ return /* @__PURE__ */ jsxRuntime.jsx(RootCtx.Provider, { value: rootContextValue, children: /* @__PURE__ */ jsxRuntime.jsx(
21509
21587
  core$1.DndContext,
21510
21588
  {
21511
21589
  sensors,
21512
21590
  collisionDetection,
21513
- onDragEnd: (e) => {
21514
- handleDragEnd(e);
21515
- clearOverlay();
21516
- },
21517
- onDragCancel: clearOverlay,
21518
- children: [
21519
- children,
21520
- /* @__PURE__ */ jsxRuntime.jsx(core$1.DragOverlay, { children: overlayNode })
21521
- ]
21591
+ onDragStart: handleDragStart,
21592
+ onDragOver: handleDragOver,
21593
+ onDragEnd: handleDragEnd,
21594
+ onDragCancel: handleDragCancel,
21595
+ children
21522
21596
  }
21523
21597
  ) });
21524
21598
  }
21525
21599
  const inner = /* @__PURE__ */ jsxRuntime.jsx(DropZoneShell, { children: /* @__PURE__ */ jsxRuntime.jsx(sortable.SortableContext, { items: itemIds, strategy, children }) });
21526
21600
  if (isRoot) {
21527
- return /* @__PURE__ */ jsxRuntime.jsx(RootCtx.Provider, { value: rootContextValue, children: /* @__PURE__ */ jsxRuntime.jsxs(
21601
+ return /* @__PURE__ */ jsxRuntime.jsx(RootCtx.Provider, { value: rootContextValue, children: /* @__PURE__ */ jsxRuntime.jsx(
21528
21602
  core$1.DndContext,
21529
21603
  {
21530
21604
  sensors,
21531
21605
  collisionDetection,
21532
- onDragEnd: (e) => {
21533
- handleDragEnd(e);
21534
- clearOverlay();
21535
- },
21536
- onDragCancel: clearOverlay,
21537
- children: [
21538
- inner,
21539
- /* @__PURE__ */ jsxRuntime.jsx(core$1.DragOverlay, { children: overlayNode })
21540
- ]
21606
+ onDragStart: handleDragStart,
21607
+ onDragOver: handleDragOver,
21608
+ onDragEnd: handleDragEnd,
21609
+ onDragCancel: handleDragCancel,
21610
+ children: inner
21541
21611
  }
21542
21612
  ) });
21543
21613
  }
21544
21614
  return inner;
21545
21615
  },
21546
- [enabled, isZone, layout, sensors, collisionDetection, handleDragEnd, itemIds, isRoot, rootContextValue, overlayNode, setOverlay]
21616
+ [enabled, isZone, layout, sensors, collisionDetection, handleDragStart, handleDragOver, handleDragEnd, handleDragCancel, itemIds, isRoot, rootContextValue]
21547
21617
  );
21548
21618
  return {
21549
21619
  enabled,
@@ -21553,12 +21623,13 @@ function useDataDnd(args) {
21553
21623
  orderedItems
21554
21624
  };
21555
21625
  }
21556
- var RootCtx;
21626
+ var dndLog, RootCtx;
21557
21627
  var init_useDataDnd = __esm({
21558
21628
  "components/molecules/useDataDnd.tsx"() {
21559
21629
  "use client";
21560
21630
  init_useEventBus();
21561
21631
  init_Box();
21632
+ dndLog = logger.createLogger("almadar:ui:dnd");
21562
21633
  RootCtx = React81__namespace.default.createContext(null);
21563
21634
  }
21564
21635
  });
@@ -36,7 +36,7 @@ import langToml from 'react-syntax-highlighter/dist/esm/languages/prism/toml.js'
36
36
  import langGo from 'react-syntax-highlighter/dist/esm/languages/prism/go.js';
37
37
  import langGraphql from 'react-syntax-highlighter/dist/esm/languages/prism/graphql.js';
38
38
  import { isInlineTrait } from '@almadar/core';
39
- import { useSensors, useSensor, PointerSensor, KeyboardSensor, pointerWithin, rectIntersection, closestCorners, DndContext, DragOverlay, useDroppable } from '@dnd-kit/core';
39
+ import { useSensors, useSensor, PointerSensor, KeyboardSensor, pointerWithin, rectIntersection, closestCorners, DndContext, useDroppable } from '@dnd-kit/core';
40
40
  import { sortableKeyboardCoordinates, arrayMove, useSortable, SortableContext, rectSortingStrategy, verticalListSortingStrategy } from '@dnd-kit/sortable';
41
41
  import { CSS } from '@dnd-kit/utilities';
42
42
  import { Handle, Position } from '@xyflow/react';
@@ -21294,12 +21294,17 @@ function useDataDnd(args) {
21294
21294
  React81__default.useEffect(() => {
21295
21295
  setLocalOrder(null);
21296
21296
  }, [items]);
21297
+ const itemIdsSignature = orderedItems.map((it, idx) => {
21298
+ const raw = it[dndItemIdField];
21299
+ return String(raw ?? `__idx_${idx}`);
21300
+ }).join("|");
21297
21301
  const itemIds = React81__default.useMemo(
21298
21302
  () => orderedItems.map((it, idx) => {
21299
21303
  const raw = it[dndItemIdField];
21300
21304
  return raw ?? `__idx_${idx}`;
21301
21305
  }),
21302
- [orderedItems, dndItemIdField]
21306
+ // eslint-disable-next-line react-hooks/exhaustive-deps
21307
+ [itemIdsSignature]
21303
21308
  );
21304
21309
  const zonesRef = React81__default.useRef(/* @__PURE__ */ new Map());
21305
21310
  const registerZone = React81__default.useCallback((zoneId2, meta2) => {
@@ -21308,10 +21313,6 @@ function useDataDnd(args) {
21308
21313
  const unregisterZone = React81__default.useCallback((zoneId2) => {
21309
21314
  zonesRef.current.delete(zoneId2);
21310
21315
  }, []);
21311
- const [overlayNode, setOverlayNode] = React81__default.useState(null);
21312
- const setOverlay = React81__default.useCallback((node) => {
21313
- setOverlayNode(node);
21314
- }, []);
21315
21316
  const zoneId = React81__default.useId();
21316
21317
  const ownGroup = dragGroup ?? accepts ?? zoneId;
21317
21318
  const meta = React81__default.useMemo(
@@ -21322,10 +21323,18 @@ function useDataDnd(args) {
21322
21323
  const target = isRoot ? null : parentRoot;
21323
21324
  if (!target) {
21324
21325
  zonesRef.current.set(zoneId, meta);
21325
- return () => zonesRef.current.delete(zoneId);
21326
+ dndLog.debug("zone:register:self", { zoneId, group: meta.group, itemCount: meta.itemIds.length, isRoot });
21327
+ return () => {
21328
+ zonesRef.current.delete(zoneId);
21329
+ dndLog.debug("zone:unregister:self", { zoneId, group: meta.group });
21330
+ };
21326
21331
  }
21327
21332
  target.registerZone(zoneId, meta);
21328
- return () => target.unregisterZone(zoneId);
21333
+ dndLog.debug("zone:register", { zoneId, group: meta.group, itemCount: meta.itemIds.length, dropEvent: meta.dropEvent, reorderEvent: meta.reorderEvent });
21334
+ return () => {
21335
+ target.unregisterZone(zoneId);
21336
+ dndLog.debug("zone:unregister", { zoneId, group: meta.group });
21337
+ };
21329
21338
  }, [parentRoot, isRoot, zoneId, meta]);
21330
21339
  const sensors = useSensors(
21331
21340
  useSensor(PointerSensor, { activationConstraint: { distance: 5 } }),
@@ -21333,10 +21342,18 @@ function useDataDnd(args) {
21333
21342
  );
21334
21343
  const collisionDetection = React81__default.useCallback((args2) => {
21335
21344
  const pointerCollisions = pointerWithin(args2);
21336
- if (pointerCollisions.length > 0) return pointerCollisions;
21345
+ if (pointerCollisions.length > 0) {
21346
+ dndLog.debug("collision:pointerWithin", { count: pointerCollisions.length, ids: pointerCollisions.map((c) => c.id) });
21347
+ return pointerCollisions;
21348
+ }
21337
21349
  const rectCollisions = rectIntersection(args2);
21338
- if (rectCollisions.length > 0) return rectCollisions;
21339
- return closestCorners(args2);
21350
+ if (rectCollisions.length > 0) {
21351
+ dndLog.debug("collision:rectIntersection", { count: rectCollisions.length, ids: rectCollisions.map((c) => c.id) });
21352
+ return rectCollisions;
21353
+ }
21354
+ const cornerCollisions = closestCorners(args2);
21355
+ dndLog.debug("collision:closestCorners", { count: cornerCollisions.length, ids: cornerCollisions.map((c) => c.id) });
21356
+ return cornerCollisions;
21340
21357
  }, []);
21341
21358
  const findZoneByItem = React81__default.useCallback(
21342
21359
  (id) => {
@@ -21359,22 +21376,52 @@ function useDataDnd(args) {
21359
21376
  const handleDragEnd = React81__default.useCallback(
21360
21377
  (event) => {
21361
21378
  const { active, over } = event;
21362
- if (!over) return;
21379
+ const allZones = Array.from(zonesRef.current.entries()).map(([id, m]) => ({ id, group: m.group, items: m.itemIds.length }));
21380
+ dndLog.debug("dragEnd:received", {
21381
+ activeId: active.id,
21382
+ overId: over?.id,
21383
+ overData: over?.data?.current,
21384
+ zones: allZones
21385
+ });
21386
+ if (!over) {
21387
+ dndLog.warn("dragEnd:abort:no-over", { activeId: active.id, reason: "no droppable under pointer at drop time \u2192 item snaps back" });
21388
+ return;
21389
+ }
21363
21390
  const sourceZone = findZoneByItem(active.id);
21364
21391
  const overData = over.data?.current;
21365
21392
  const targetGroup = overData?.dndGroup;
21366
- if (!sourceZone || !targetGroup) return;
21393
+ dndLog.debug("dragEnd:resolved", { sourceGroup: sourceZone?.group, targetGroup, overDataKeys: overData ? Object.keys(overData) : null });
21394
+ if (!sourceZone) {
21395
+ dndLog.warn("dragEnd:abort:no-source-zone", { activeId: active.id });
21396
+ return;
21397
+ }
21398
+ if (!targetGroup) {
21399
+ dndLog.warn("dragEnd:abort:no-target-group", { overId: over.id, overData });
21400
+ return;
21401
+ }
21367
21402
  const targetZone = findZoneByGroup(targetGroup);
21368
- if (!targetZone) return;
21403
+ if (!targetZone) {
21404
+ dndLog.warn("dragEnd:abort:target-zone-not-registered", { targetGroup });
21405
+ return;
21406
+ }
21369
21407
  if (sourceZone.group !== targetZone.group) {
21370
21408
  if (targetZone.dropEvent) {
21371
21409
  const newIndex2 = targetZone.itemIds.indexOf(over.id);
21410
+ dndLog.info("dragEnd:cross-container:emit", {
21411
+ event: targetZone.dropEvent,
21412
+ id: String(active.id),
21413
+ sourceGroup: sourceZone.group,
21414
+ targetGroup: targetZone.group,
21415
+ newIndex: newIndex2 === -1 ? targetZone.itemIds.length : newIndex2
21416
+ });
21372
21417
  eventBus.emit(targetZone.dropEvent, {
21373
21418
  id: String(active.id),
21374
21419
  sourceGroup: sourceZone.group,
21375
21420
  targetGroup: targetZone.group,
21376
21421
  newIndex: newIndex2 === -1 ? targetZone.itemIds.length : newIndex2
21377
21422
  });
21423
+ } else {
21424
+ dndLog.warn("dragEnd:cross-container:no-dropEvent-on-target", { targetGroup: targetZone.group });
21378
21425
  }
21379
21426
  return;
21380
21427
  }
@@ -21386,16 +21433,24 @@ function useDataDnd(args) {
21386
21433
  setLocalOrder(reordered);
21387
21434
  }
21388
21435
  if (sourceZone.reorderEvent) {
21436
+ dndLog.info("dragEnd:reorder:emit", {
21437
+ event: sourceZone.reorderEvent,
21438
+ id: String(active.id),
21439
+ oldIndex,
21440
+ newIndex
21441
+ });
21389
21442
  eventBus.emit(sourceZone.reorderEvent, {
21390
21443
  id: String(active.id),
21391
21444
  oldIndex,
21392
21445
  newIndex
21393
21446
  });
21447
+ } else {
21448
+ dndLog.debug("dragEnd:reorder:no-reorderEvent", { sourceGroup: sourceZone.group });
21394
21449
  }
21395
21450
  },
21396
21451
  [orderedItems, ownGroup, findZoneByItem, findZoneByGroup, eventBus]
21397
21452
  );
21398
- const overlaySink = isRoot ? setOverlay : parentRoot?.setOverlay;
21453
+ const sortableData = React81__default.useMemo(() => ({ dndGroup: ownGroup }), [ownGroup]);
21399
21454
  const SortableItem = React81__default.useCallback(
21400
21455
  ({ id, children }) => {
21401
21456
  const {
@@ -21405,19 +21460,16 @@ function useDataDnd(args) {
21405
21460
  transform,
21406
21461
  transition,
21407
21462
  isDragging
21408
- } = useSortable({ id, data: { dndGroup: ownGroup } });
21409
- const childrenRef = React81__default.useRef(children);
21410
- childrenRef.current = children;
21411
- React81__default.useEffect(() => {
21412
- if (!isDragging || !overlaySink) return;
21413
- overlaySink(childrenRef.current);
21414
- return () => overlaySink(null);
21415
- }, [isDragging]);
21463
+ } = useSortable({ id, data: sortableData });
21416
21464
  const style = {
21417
21465
  transform: CSS.Transform.toString(transform),
21418
21466
  transition,
21419
21467
  opacity: isDragging ? 0.4 : 1,
21420
- cursor: enabled ? "grab" : void 0
21468
+ cursor: enabled ? "grab" : void 0,
21469
+ // Lift the dragged element above siblings so its visual movement
21470
+ // isn't hidden behind other cards / column boundaries.
21471
+ zIndex: isDragging ? 50 : void 0,
21472
+ position: isDragging ? "relative" : void 0
21421
21473
  };
21422
21474
  return /* @__PURE__ */ jsx(
21423
21475
  Box,
@@ -21431,73 +21483,91 @@ function useDataDnd(args) {
21431
21483
  }
21432
21484
  );
21433
21485
  },
21434
- [ownGroup, enabled, overlaySink]
21486
+ [sortableData, enabled]
21435
21487
  );
21436
21488
  const DropZoneShell = ({ children }) => {
21489
+ const droppableId = `dnd-zone-${zoneId}`;
21437
21490
  const { setNodeRef, isOver } = useDroppable({
21438
- id: `dnd-zone-${zoneId}`,
21439
- data: { dndGroup: ownGroup }
21491
+ id: droppableId,
21492
+ data: sortableData
21440
21493
  });
21494
+ React81__default.useEffect(() => {
21495
+ dndLog.debug("dropzone:isOver:change", { droppableId, group: ownGroup, isOver });
21496
+ }, [droppableId, isOver]);
21441
21497
  return /* @__PURE__ */ jsx(
21442
21498
  Box,
21443
21499
  {
21444
21500
  ref: setNodeRef,
21445
21501
  "data-dnd-zone": ownGroup,
21502
+ "data-dnd-is-over": isOver ? "true" : "false",
21446
21503
  className: isOver ? "ring-2 ring-primary ring-offset-2 rounded-lg transition-all min-h-[3rem]" : "min-h-[3rem] rounded-lg transition-all",
21447
21504
  children
21448
21505
  }
21449
21506
  );
21450
21507
  };
21451
21508
  const rootContextValue = React81__default.useMemo(
21452
- () => ({ registerZone, unregisterZone, setOverlay }),
21453
- [registerZone, unregisterZone, setOverlay]
21509
+ () => ({ registerZone, unregisterZone }),
21510
+ [registerZone, unregisterZone]
21454
21511
  );
21512
+ const handleDragStart = React81__default.useCallback((event) => {
21513
+ const sourceZone = findZoneByItem(event.active.id);
21514
+ dndLog.info("dragStart", {
21515
+ activeId: event.active.id,
21516
+ activeData: event.active.data?.current,
21517
+ sourceGroup: sourceZone?.group,
21518
+ zoneCount: zonesRef.current.size
21519
+ });
21520
+ }, [findZoneByItem]);
21521
+ const handleDragOver = React81__default.useCallback((event) => {
21522
+ dndLog.debug("dragOver", {
21523
+ activeId: event.active.id,
21524
+ overId: event.over?.id,
21525
+ overData: event.over?.data?.current
21526
+ });
21527
+ }, []);
21528
+ const handleDragCancel = React81__default.useCallback((event) => {
21529
+ dndLog.warn("dragCancel", {
21530
+ activeId: event.active.id,
21531
+ reason: "dnd-kit cancelled the drag (escape key, pointer interrupted, or external)"
21532
+ });
21533
+ }, []);
21455
21534
  const wrapContainer = React81__default.useCallback(
21456
21535
  (children) => {
21457
21536
  if (!enabled) return children;
21458
21537
  const strategy = layout === "grid" ? rectSortingStrategy : verticalListSortingStrategy;
21459
- const clearOverlay = () => setOverlay(null);
21460
21538
  if (!isZone) {
21461
21539
  if (!isRoot) return children;
21462
- return /* @__PURE__ */ jsx(RootCtx.Provider, { value: rootContextValue, children: /* @__PURE__ */ jsxs(
21540
+ return /* @__PURE__ */ jsx(RootCtx.Provider, { value: rootContextValue, children: /* @__PURE__ */ jsx(
21463
21541
  DndContext,
21464
21542
  {
21465
21543
  sensors,
21466
21544
  collisionDetection,
21467
- onDragEnd: (e) => {
21468
- handleDragEnd(e);
21469
- clearOverlay();
21470
- },
21471
- onDragCancel: clearOverlay,
21472
- children: [
21473
- children,
21474
- /* @__PURE__ */ jsx(DragOverlay, { children: overlayNode })
21475
- ]
21545
+ onDragStart: handleDragStart,
21546
+ onDragOver: handleDragOver,
21547
+ onDragEnd: handleDragEnd,
21548
+ onDragCancel: handleDragCancel,
21549
+ children
21476
21550
  }
21477
21551
  ) });
21478
21552
  }
21479
21553
  const inner = /* @__PURE__ */ jsx(DropZoneShell, { children: /* @__PURE__ */ jsx(SortableContext, { items: itemIds, strategy, children }) });
21480
21554
  if (isRoot) {
21481
- return /* @__PURE__ */ jsx(RootCtx.Provider, { value: rootContextValue, children: /* @__PURE__ */ jsxs(
21555
+ return /* @__PURE__ */ jsx(RootCtx.Provider, { value: rootContextValue, children: /* @__PURE__ */ jsx(
21482
21556
  DndContext,
21483
21557
  {
21484
21558
  sensors,
21485
21559
  collisionDetection,
21486
- onDragEnd: (e) => {
21487
- handleDragEnd(e);
21488
- clearOverlay();
21489
- },
21490
- onDragCancel: clearOverlay,
21491
- children: [
21492
- inner,
21493
- /* @__PURE__ */ jsx(DragOverlay, { children: overlayNode })
21494
- ]
21560
+ onDragStart: handleDragStart,
21561
+ onDragOver: handleDragOver,
21562
+ onDragEnd: handleDragEnd,
21563
+ onDragCancel: handleDragCancel,
21564
+ children: inner
21495
21565
  }
21496
21566
  ) });
21497
21567
  }
21498
21568
  return inner;
21499
21569
  },
21500
- [enabled, isZone, layout, sensors, collisionDetection, handleDragEnd, itemIds, isRoot, rootContextValue, overlayNode, setOverlay]
21570
+ [enabled, isZone, layout, sensors, collisionDetection, handleDragStart, handleDragOver, handleDragEnd, handleDragCancel, itemIds, isRoot, rootContextValue]
21501
21571
  );
21502
21572
  return {
21503
21573
  enabled,
@@ -21507,12 +21577,13 @@ function useDataDnd(args) {
21507
21577
  orderedItems
21508
21578
  };
21509
21579
  }
21510
- var RootCtx;
21580
+ var dndLog, RootCtx;
21511
21581
  var init_useDataDnd = __esm({
21512
21582
  "components/molecules/useDataDnd.tsx"() {
21513
21583
  "use client";
21514
21584
  init_useEventBus();
21515
21585
  init_Box();
21586
+ dndLog = createLogger("almadar:ui:dnd");
21516
21587
  RootCtx = React81__default.createContext(null);
21517
21588
  }
21518
21589
  });