@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.
@@ -20095,12 +20095,17 @@ function useDataDnd(args) {
20095
20095
  React75__namespace.default.useEffect(() => {
20096
20096
  setLocalOrder(null);
20097
20097
  }, [items]);
20098
+ const itemIdsSignature = orderedItems.map((it, idx) => {
20099
+ const raw = it[dndItemIdField];
20100
+ return String(raw ?? `__idx_${idx}`);
20101
+ }).join("|");
20098
20102
  const itemIds = React75__namespace.default.useMemo(
20099
20103
  () => orderedItems.map((it, idx) => {
20100
20104
  const raw = it[dndItemIdField];
20101
20105
  return raw ?? `__idx_${idx}`;
20102
20106
  }),
20103
- [orderedItems, dndItemIdField]
20107
+ // eslint-disable-next-line react-hooks/exhaustive-deps
20108
+ [itemIdsSignature]
20104
20109
  );
20105
20110
  const zonesRef = React75__namespace.default.useRef(/* @__PURE__ */ new Map());
20106
20111
  const registerZone = React75__namespace.default.useCallback((zoneId2, meta2) => {
@@ -20109,10 +20114,6 @@ function useDataDnd(args) {
20109
20114
  const unregisterZone = React75__namespace.default.useCallback((zoneId2) => {
20110
20115
  zonesRef.current.delete(zoneId2);
20111
20116
  }, []);
20112
- const [overlayNode, setOverlayNode] = React75__namespace.default.useState(null);
20113
- const setOverlay = React75__namespace.default.useCallback((node) => {
20114
- setOverlayNode(node);
20115
- }, []);
20116
20117
  const zoneId = React75__namespace.default.useId();
20117
20118
  const ownGroup = dragGroup ?? accepts ?? zoneId;
20118
20119
  const meta = React75__namespace.default.useMemo(
@@ -20123,10 +20124,18 @@ function useDataDnd(args) {
20123
20124
  const target = isRoot ? null : parentRoot;
20124
20125
  if (!target) {
20125
20126
  zonesRef.current.set(zoneId, meta);
20126
- return () => zonesRef.current.delete(zoneId);
20127
+ dndLog.debug("zone:register:self", { zoneId, group: meta.group, itemCount: meta.itemIds.length, isRoot });
20128
+ return () => {
20129
+ zonesRef.current.delete(zoneId);
20130
+ dndLog.debug("zone:unregister:self", { zoneId, group: meta.group });
20131
+ };
20127
20132
  }
20128
20133
  target.registerZone(zoneId, meta);
20129
- return () => target.unregisterZone(zoneId);
20134
+ dndLog.debug("zone:register", { zoneId, group: meta.group, itemCount: meta.itemIds.length, dropEvent: meta.dropEvent, reorderEvent: meta.reorderEvent });
20135
+ return () => {
20136
+ target.unregisterZone(zoneId);
20137
+ dndLog.debug("zone:unregister", { zoneId, group: meta.group });
20138
+ };
20130
20139
  }, [parentRoot, isRoot, zoneId, meta]);
20131
20140
  const sensors = core$1.useSensors(
20132
20141
  core$1.useSensor(core$1.PointerSensor, { activationConstraint: { distance: 5 } }),
@@ -20134,10 +20143,18 @@ function useDataDnd(args) {
20134
20143
  );
20135
20144
  const collisionDetection = React75__namespace.default.useCallback((args2) => {
20136
20145
  const pointerCollisions = core$1.pointerWithin(args2);
20137
- if (pointerCollisions.length > 0) return pointerCollisions;
20146
+ if (pointerCollisions.length > 0) {
20147
+ dndLog.debug("collision:pointerWithin", { count: pointerCollisions.length, ids: pointerCollisions.map((c) => c.id) });
20148
+ return pointerCollisions;
20149
+ }
20138
20150
  const rectCollisions = core$1.rectIntersection(args2);
20139
- if (rectCollisions.length > 0) return rectCollisions;
20140
- return core$1.closestCorners(args2);
20151
+ if (rectCollisions.length > 0) {
20152
+ dndLog.debug("collision:rectIntersection", { count: rectCollisions.length, ids: rectCollisions.map((c) => c.id) });
20153
+ return rectCollisions;
20154
+ }
20155
+ const cornerCollisions = core$1.closestCorners(args2);
20156
+ dndLog.debug("collision:closestCorners", { count: cornerCollisions.length, ids: cornerCollisions.map((c) => c.id) });
20157
+ return cornerCollisions;
20141
20158
  }, []);
20142
20159
  const findZoneByItem = React75__namespace.default.useCallback(
20143
20160
  (id) => {
@@ -20160,22 +20177,52 @@ function useDataDnd(args) {
20160
20177
  const handleDragEnd = React75__namespace.default.useCallback(
20161
20178
  (event) => {
20162
20179
  const { active, over } = event;
20163
- if (!over) return;
20180
+ const allZones = Array.from(zonesRef.current.entries()).map(([id, m]) => ({ id, group: m.group, items: m.itemIds.length }));
20181
+ dndLog.debug("dragEnd:received", {
20182
+ activeId: active.id,
20183
+ overId: over?.id,
20184
+ overData: over?.data?.current,
20185
+ zones: allZones
20186
+ });
20187
+ if (!over) {
20188
+ dndLog.warn("dragEnd:abort:no-over", { activeId: active.id, reason: "no droppable under pointer at drop time \u2192 item snaps back" });
20189
+ return;
20190
+ }
20164
20191
  const sourceZone = findZoneByItem(active.id);
20165
20192
  const overData = over.data?.current;
20166
20193
  const targetGroup = overData?.dndGroup;
20167
- if (!sourceZone || !targetGroup) return;
20194
+ dndLog.debug("dragEnd:resolved", { sourceGroup: sourceZone?.group, targetGroup, overDataKeys: overData ? Object.keys(overData) : null });
20195
+ if (!sourceZone) {
20196
+ dndLog.warn("dragEnd:abort:no-source-zone", { activeId: active.id });
20197
+ return;
20198
+ }
20199
+ if (!targetGroup) {
20200
+ dndLog.warn("dragEnd:abort:no-target-group", { overId: over.id, overData });
20201
+ return;
20202
+ }
20168
20203
  const targetZone = findZoneByGroup(targetGroup);
20169
- if (!targetZone) return;
20204
+ if (!targetZone) {
20205
+ dndLog.warn("dragEnd:abort:target-zone-not-registered", { targetGroup });
20206
+ return;
20207
+ }
20170
20208
  if (sourceZone.group !== targetZone.group) {
20171
20209
  if (targetZone.dropEvent) {
20172
20210
  const newIndex2 = targetZone.itemIds.indexOf(over.id);
20211
+ dndLog.info("dragEnd:cross-container:emit", {
20212
+ event: targetZone.dropEvent,
20213
+ id: String(active.id),
20214
+ sourceGroup: sourceZone.group,
20215
+ targetGroup: targetZone.group,
20216
+ newIndex: newIndex2 === -1 ? targetZone.itemIds.length : newIndex2
20217
+ });
20173
20218
  eventBus.emit(targetZone.dropEvent, {
20174
20219
  id: String(active.id),
20175
20220
  sourceGroup: sourceZone.group,
20176
20221
  targetGroup: targetZone.group,
20177
20222
  newIndex: newIndex2 === -1 ? targetZone.itemIds.length : newIndex2
20178
20223
  });
20224
+ } else {
20225
+ dndLog.warn("dragEnd:cross-container:no-dropEvent-on-target", { targetGroup: targetZone.group });
20179
20226
  }
20180
20227
  return;
20181
20228
  }
@@ -20187,16 +20234,24 @@ function useDataDnd(args) {
20187
20234
  setLocalOrder(reordered);
20188
20235
  }
20189
20236
  if (sourceZone.reorderEvent) {
20237
+ dndLog.info("dragEnd:reorder:emit", {
20238
+ event: sourceZone.reorderEvent,
20239
+ id: String(active.id),
20240
+ oldIndex,
20241
+ newIndex
20242
+ });
20190
20243
  eventBus.emit(sourceZone.reorderEvent, {
20191
20244
  id: String(active.id),
20192
20245
  oldIndex,
20193
20246
  newIndex
20194
20247
  });
20248
+ } else {
20249
+ dndLog.debug("dragEnd:reorder:no-reorderEvent", { sourceGroup: sourceZone.group });
20195
20250
  }
20196
20251
  },
20197
20252
  [orderedItems, ownGroup, findZoneByItem, findZoneByGroup, eventBus]
20198
20253
  );
20199
- const overlaySink = isRoot ? setOverlay : parentRoot?.setOverlay;
20254
+ const sortableData = React75__namespace.default.useMemo(() => ({ dndGroup: ownGroup }), [ownGroup]);
20200
20255
  const SortableItem = React75__namespace.default.useCallback(
20201
20256
  ({ id, children }) => {
20202
20257
  const {
@@ -20206,19 +20261,16 @@ function useDataDnd(args) {
20206
20261
  transform,
20207
20262
  transition,
20208
20263
  isDragging
20209
- } = sortable.useSortable({ id, data: { dndGroup: ownGroup } });
20210
- const childrenRef = React75__namespace.default.useRef(children);
20211
- childrenRef.current = children;
20212
- React75__namespace.default.useEffect(() => {
20213
- if (!isDragging || !overlaySink) return;
20214
- overlaySink(childrenRef.current);
20215
- return () => overlaySink(null);
20216
- }, [isDragging]);
20264
+ } = sortable.useSortable({ id, data: sortableData });
20217
20265
  const style = {
20218
20266
  transform: utilities.CSS.Transform.toString(transform),
20219
20267
  transition,
20220
20268
  opacity: isDragging ? 0.4 : 1,
20221
- cursor: enabled ? "grab" : void 0
20269
+ cursor: enabled ? "grab" : void 0,
20270
+ // Lift the dragged element above siblings so its visual movement
20271
+ // isn't hidden behind other cards / column boundaries.
20272
+ zIndex: isDragging ? 50 : void 0,
20273
+ position: isDragging ? "relative" : void 0
20222
20274
  };
20223
20275
  return /* @__PURE__ */ jsxRuntime.jsx(
20224
20276
  exports.Box,
@@ -20232,73 +20284,91 @@ function useDataDnd(args) {
20232
20284
  }
20233
20285
  );
20234
20286
  },
20235
- [ownGroup, enabled, overlaySink]
20287
+ [sortableData, enabled]
20236
20288
  );
20237
20289
  const DropZoneShell = ({ children }) => {
20290
+ const droppableId = `dnd-zone-${zoneId}`;
20238
20291
  const { setNodeRef, isOver } = core$1.useDroppable({
20239
- id: `dnd-zone-${zoneId}`,
20240
- data: { dndGroup: ownGroup }
20292
+ id: droppableId,
20293
+ data: sortableData
20241
20294
  });
20295
+ React75__namespace.default.useEffect(() => {
20296
+ dndLog.debug("dropzone:isOver:change", { droppableId, group: ownGroup, isOver });
20297
+ }, [droppableId, isOver]);
20242
20298
  return /* @__PURE__ */ jsxRuntime.jsx(
20243
20299
  exports.Box,
20244
20300
  {
20245
20301
  ref: setNodeRef,
20246
20302
  "data-dnd-zone": ownGroup,
20303
+ "data-dnd-is-over": isOver ? "true" : "false",
20247
20304
  className: isOver ? "ring-2 ring-primary ring-offset-2 rounded-lg transition-all min-h-[3rem]" : "min-h-[3rem] rounded-lg transition-all",
20248
20305
  children
20249
20306
  }
20250
20307
  );
20251
20308
  };
20252
20309
  const rootContextValue = React75__namespace.default.useMemo(
20253
- () => ({ registerZone, unregisterZone, setOverlay }),
20254
- [registerZone, unregisterZone, setOverlay]
20310
+ () => ({ registerZone, unregisterZone }),
20311
+ [registerZone, unregisterZone]
20255
20312
  );
20313
+ const handleDragStart = React75__namespace.default.useCallback((event) => {
20314
+ const sourceZone = findZoneByItem(event.active.id);
20315
+ dndLog.info("dragStart", {
20316
+ activeId: event.active.id,
20317
+ activeData: event.active.data?.current,
20318
+ sourceGroup: sourceZone?.group,
20319
+ zoneCount: zonesRef.current.size
20320
+ });
20321
+ }, [findZoneByItem]);
20322
+ const handleDragOver = React75__namespace.default.useCallback((event) => {
20323
+ dndLog.debug("dragOver", {
20324
+ activeId: event.active.id,
20325
+ overId: event.over?.id,
20326
+ overData: event.over?.data?.current
20327
+ });
20328
+ }, []);
20329
+ const handleDragCancel = React75__namespace.default.useCallback((event) => {
20330
+ dndLog.warn("dragCancel", {
20331
+ activeId: event.active.id,
20332
+ reason: "dnd-kit cancelled the drag (escape key, pointer interrupted, or external)"
20333
+ });
20334
+ }, []);
20256
20335
  const wrapContainer = React75__namespace.default.useCallback(
20257
20336
  (children) => {
20258
20337
  if (!enabled) return children;
20259
20338
  const strategy = layout === "grid" ? sortable.rectSortingStrategy : sortable.verticalListSortingStrategy;
20260
- const clearOverlay = () => setOverlay(null);
20261
20339
  if (!isZone) {
20262
20340
  if (!isRoot) return children;
20263
- return /* @__PURE__ */ jsxRuntime.jsx(RootCtx.Provider, { value: rootContextValue, children: /* @__PURE__ */ jsxRuntime.jsxs(
20341
+ return /* @__PURE__ */ jsxRuntime.jsx(RootCtx.Provider, { value: rootContextValue, children: /* @__PURE__ */ jsxRuntime.jsx(
20264
20342
  core$1.DndContext,
20265
20343
  {
20266
20344
  sensors,
20267
20345
  collisionDetection,
20268
- onDragEnd: (e) => {
20269
- handleDragEnd(e);
20270
- clearOverlay();
20271
- },
20272
- onDragCancel: clearOverlay,
20273
- children: [
20274
- children,
20275
- /* @__PURE__ */ jsxRuntime.jsx(core$1.DragOverlay, { children: overlayNode })
20276
- ]
20346
+ onDragStart: handleDragStart,
20347
+ onDragOver: handleDragOver,
20348
+ onDragEnd: handleDragEnd,
20349
+ onDragCancel: handleDragCancel,
20350
+ children
20277
20351
  }
20278
20352
  ) });
20279
20353
  }
20280
20354
  const inner = /* @__PURE__ */ jsxRuntime.jsx(DropZoneShell, { children: /* @__PURE__ */ jsxRuntime.jsx(sortable.SortableContext, { items: itemIds, strategy, children }) });
20281
20355
  if (isRoot) {
20282
- return /* @__PURE__ */ jsxRuntime.jsx(RootCtx.Provider, { value: rootContextValue, children: /* @__PURE__ */ jsxRuntime.jsxs(
20356
+ return /* @__PURE__ */ jsxRuntime.jsx(RootCtx.Provider, { value: rootContextValue, children: /* @__PURE__ */ jsxRuntime.jsx(
20283
20357
  core$1.DndContext,
20284
20358
  {
20285
20359
  sensors,
20286
20360
  collisionDetection,
20287
- onDragEnd: (e) => {
20288
- handleDragEnd(e);
20289
- clearOverlay();
20290
- },
20291
- onDragCancel: clearOverlay,
20292
- children: [
20293
- inner,
20294
- /* @__PURE__ */ jsxRuntime.jsx(core$1.DragOverlay, { children: overlayNode })
20295
- ]
20361
+ onDragStart: handleDragStart,
20362
+ onDragOver: handleDragOver,
20363
+ onDragEnd: handleDragEnd,
20364
+ onDragCancel: handleDragCancel,
20365
+ children: inner
20296
20366
  }
20297
20367
  ) });
20298
20368
  }
20299
20369
  return inner;
20300
20370
  },
20301
- [enabled, isZone, layout, sensors, collisionDetection, handleDragEnd, itemIds, isRoot, rootContextValue, overlayNode, setOverlay]
20371
+ [enabled, isZone, layout, sensors, collisionDetection, handleDragStart, handleDragOver, handleDragEnd, handleDragCancel, itemIds, isRoot, rootContextValue]
20302
20372
  );
20303
20373
  return {
20304
20374
  enabled,
@@ -20308,12 +20378,13 @@ function useDataDnd(args) {
20308
20378
  orderedItems
20309
20379
  };
20310
20380
  }
20311
- var RootCtx;
20381
+ var dndLog, RootCtx;
20312
20382
  var init_useDataDnd = __esm({
20313
20383
  "components/molecules/useDataDnd.tsx"() {
20314
20384
  "use client";
20315
20385
  init_useEventBus();
20316
20386
  init_Box();
20387
+ dndLog = logger.createLogger("almadar:ui:dnd");
20317
20388
  RootCtx = React75__namespace.default.createContext(null);
20318
20389
  }
20319
20390
  });
@@ -35,7 +35,7 @@ import langToml from 'react-syntax-highlighter/dist/esm/languages/prism/toml.js'
35
35
  import langGo from 'react-syntax-highlighter/dist/esm/languages/prism/go.js';
36
36
  import langGraphql from 'react-syntax-highlighter/dist/esm/languages/prism/graphql.js';
37
37
  import { isInlineTrait } from '@almadar/core';
38
- import { useSensors, useSensor, PointerSensor, KeyboardSensor, pointerWithin, rectIntersection, closestCorners, DndContext, DragOverlay, useDroppable } from '@dnd-kit/core';
38
+ import { useSensors, useSensor, PointerSensor, KeyboardSensor, pointerWithin, rectIntersection, closestCorners, DndContext, useDroppable } from '@dnd-kit/core';
39
39
  import { sortableKeyboardCoordinates, arrayMove, useSortable, SortableContext, rectSortingStrategy, verticalListSortingStrategy } from '@dnd-kit/sortable';
40
40
  import { CSS } from '@dnd-kit/utilities';
41
41
  import { Handle, Position } from '@xyflow/react';
@@ -20049,12 +20049,17 @@ function useDataDnd(args) {
20049
20049
  React75__default.useEffect(() => {
20050
20050
  setLocalOrder(null);
20051
20051
  }, [items]);
20052
+ const itemIdsSignature = orderedItems.map((it, idx) => {
20053
+ const raw = it[dndItemIdField];
20054
+ return String(raw ?? `__idx_${idx}`);
20055
+ }).join("|");
20052
20056
  const itemIds = React75__default.useMemo(
20053
20057
  () => orderedItems.map((it, idx) => {
20054
20058
  const raw = it[dndItemIdField];
20055
20059
  return raw ?? `__idx_${idx}`;
20056
20060
  }),
20057
- [orderedItems, dndItemIdField]
20061
+ // eslint-disable-next-line react-hooks/exhaustive-deps
20062
+ [itemIdsSignature]
20058
20063
  );
20059
20064
  const zonesRef = React75__default.useRef(/* @__PURE__ */ new Map());
20060
20065
  const registerZone = React75__default.useCallback((zoneId2, meta2) => {
@@ -20063,10 +20068,6 @@ function useDataDnd(args) {
20063
20068
  const unregisterZone = React75__default.useCallback((zoneId2) => {
20064
20069
  zonesRef.current.delete(zoneId2);
20065
20070
  }, []);
20066
- const [overlayNode, setOverlayNode] = React75__default.useState(null);
20067
- const setOverlay = React75__default.useCallback((node) => {
20068
- setOverlayNode(node);
20069
- }, []);
20070
20071
  const zoneId = React75__default.useId();
20071
20072
  const ownGroup = dragGroup ?? accepts ?? zoneId;
20072
20073
  const meta = React75__default.useMemo(
@@ -20077,10 +20078,18 @@ function useDataDnd(args) {
20077
20078
  const target = isRoot ? null : parentRoot;
20078
20079
  if (!target) {
20079
20080
  zonesRef.current.set(zoneId, meta);
20080
- return () => zonesRef.current.delete(zoneId);
20081
+ dndLog.debug("zone:register:self", { zoneId, group: meta.group, itemCount: meta.itemIds.length, isRoot });
20082
+ return () => {
20083
+ zonesRef.current.delete(zoneId);
20084
+ dndLog.debug("zone:unregister:self", { zoneId, group: meta.group });
20085
+ };
20081
20086
  }
20082
20087
  target.registerZone(zoneId, meta);
20083
- return () => target.unregisterZone(zoneId);
20088
+ dndLog.debug("zone:register", { zoneId, group: meta.group, itemCount: meta.itemIds.length, dropEvent: meta.dropEvent, reorderEvent: meta.reorderEvent });
20089
+ return () => {
20090
+ target.unregisterZone(zoneId);
20091
+ dndLog.debug("zone:unregister", { zoneId, group: meta.group });
20092
+ };
20084
20093
  }, [parentRoot, isRoot, zoneId, meta]);
20085
20094
  const sensors = useSensors(
20086
20095
  useSensor(PointerSensor, { activationConstraint: { distance: 5 } }),
@@ -20088,10 +20097,18 @@ function useDataDnd(args) {
20088
20097
  );
20089
20098
  const collisionDetection = React75__default.useCallback((args2) => {
20090
20099
  const pointerCollisions = pointerWithin(args2);
20091
- if (pointerCollisions.length > 0) return pointerCollisions;
20100
+ if (pointerCollisions.length > 0) {
20101
+ dndLog.debug("collision:pointerWithin", { count: pointerCollisions.length, ids: pointerCollisions.map((c) => c.id) });
20102
+ return pointerCollisions;
20103
+ }
20092
20104
  const rectCollisions = rectIntersection(args2);
20093
- if (rectCollisions.length > 0) return rectCollisions;
20094
- return closestCorners(args2);
20105
+ if (rectCollisions.length > 0) {
20106
+ dndLog.debug("collision:rectIntersection", { count: rectCollisions.length, ids: rectCollisions.map((c) => c.id) });
20107
+ return rectCollisions;
20108
+ }
20109
+ const cornerCollisions = closestCorners(args2);
20110
+ dndLog.debug("collision:closestCorners", { count: cornerCollisions.length, ids: cornerCollisions.map((c) => c.id) });
20111
+ return cornerCollisions;
20095
20112
  }, []);
20096
20113
  const findZoneByItem = React75__default.useCallback(
20097
20114
  (id) => {
@@ -20114,22 +20131,52 @@ function useDataDnd(args) {
20114
20131
  const handleDragEnd = React75__default.useCallback(
20115
20132
  (event) => {
20116
20133
  const { active, over } = event;
20117
- if (!over) return;
20134
+ const allZones = Array.from(zonesRef.current.entries()).map(([id, m]) => ({ id, group: m.group, items: m.itemIds.length }));
20135
+ dndLog.debug("dragEnd:received", {
20136
+ activeId: active.id,
20137
+ overId: over?.id,
20138
+ overData: over?.data?.current,
20139
+ zones: allZones
20140
+ });
20141
+ if (!over) {
20142
+ dndLog.warn("dragEnd:abort:no-over", { activeId: active.id, reason: "no droppable under pointer at drop time \u2192 item snaps back" });
20143
+ return;
20144
+ }
20118
20145
  const sourceZone = findZoneByItem(active.id);
20119
20146
  const overData = over.data?.current;
20120
20147
  const targetGroup = overData?.dndGroup;
20121
- if (!sourceZone || !targetGroup) return;
20148
+ dndLog.debug("dragEnd:resolved", { sourceGroup: sourceZone?.group, targetGroup, overDataKeys: overData ? Object.keys(overData) : null });
20149
+ if (!sourceZone) {
20150
+ dndLog.warn("dragEnd:abort:no-source-zone", { activeId: active.id });
20151
+ return;
20152
+ }
20153
+ if (!targetGroup) {
20154
+ dndLog.warn("dragEnd:abort:no-target-group", { overId: over.id, overData });
20155
+ return;
20156
+ }
20122
20157
  const targetZone = findZoneByGroup(targetGroup);
20123
- if (!targetZone) return;
20158
+ if (!targetZone) {
20159
+ dndLog.warn("dragEnd:abort:target-zone-not-registered", { targetGroup });
20160
+ return;
20161
+ }
20124
20162
  if (sourceZone.group !== targetZone.group) {
20125
20163
  if (targetZone.dropEvent) {
20126
20164
  const newIndex2 = targetZone.itemIds.indexOf(over.id);
20165
+ dndLog.info("dragEnd:cross-container:emit", {
20166
+ event: targetZone.dropEvent,
20167
+ id: String(active.id),
20168
+ sourceGroup: sourceZone.group,
20169
+ targetGroup: targetZone.group,
20170
+ newIndex: newIndex2 === -1 ? targetZone.itemIds.length : newIndex2
20171
+ });
20127
20172
  eventBus.emit(targetZone.dropEvent, {
20128
20173
  id: String(active.id),
20129
20174
  sourceGroup: sourceZone.group,
20130
20175
  targetGroup: targetZone.group,
20131
20176
  newIndex: newIndex2 === -1 ? targetZone.itemIds.length : newIndex2
20132
20177
  });
20178
+ } else {
20179
+ dndLog.warn("dragEnd:cross-container:no-dropEvent-on-target", { targetGroup: targetZone.group });
20133
20180
  }
20134
20181
  return;
20135
20182
  }
@@ -20141,16 +20188,24 @@ function useDataDnd(args) {
20141
20188
  setLocalOrder(reordered);
20142
20189
  }
20143
20190
  if (sourceZone.reorderEvent) {
20191
+ dndLog.info("dragEnd:reorder:emit", {
20192
+ event: sourceZone.reorderEvent,
20193
+ id: String(active.id),
20194
+ oldIndex,
20195
+ newIndex
20196
+ });
20144
20197
  eventBus.emit(sourceZone.reorderEvent, {
20145
20198
  id: String(active.id),
20146
20199
  oldIndex,
20147
20200
  newIndex
20148
20201
  });
20202
+ } else {
20203
+ dndLog.debug("dragEnd:reorder:no-reorderEvent", { sourceGroup: sourceZone.group });
20149
20204
  }
20150
20205
  },
20151
20206
  [orderedItems, ownGroup, findZoneByItem, findZoneByGroup, eventBus]
20152
20207
  );
20153
- const overlaySink = isRoot ? setOverlay : parentRoot?.setOverlay;
20208
+ const sortableData = React75__default.useMemo(() => ({ dndGroup: ownGroup }), [ownGroup]);
20154
20209
  const SortableItem = React75__default.useCallback(
20155
20210
  ({ id, children }) => {
20156
20211
  const {
@@ -20160,19 +20215,16 @@ function useDataDnd(args) {
20160
20215
  transform,
20161
20216
  transition,
20162
20217
  isDragging
20163
- } = useSortable({ id, data: { dndGroup: ownGroup } });
20164
- const childrenRef = React75__default.useRef(children);
20165
- childrenRef.current = children;
20166
- React75__default.useEffect(() => {
20167
- if (!isDragging || !overlaySink) return;
20168
- overlaySink(childrenRef.current);
20169
- return () => overlaySink(null);
20170
- }, [isDragging]);
20218
+ } = useSortable({ id, data: sortableData });
20171
20219
  const style = {
20172
20220
  transform: CSS.Transform.toString(transform),
20173
20221
  transition,
20174
20222
  opacity: isDragging ? 0.4 : 1,
20175
- cursor: enabled ? "grab" : void 0
20223
+ cursor: enabled ? "grab" : void 0,
20224
+ // Lift the dragged element above siblings so its visual movement
20225
+ // isn't hidden behind other cards / column boundaries.
20226
+ zIndex: isDragging ? 50 : void 0,
20227
+ position: isDragging ? "relative" : void 0
20176
20228
  };
20177
20229
  return /* @__PURE__ */ jsx(
20178
20230
  Box,
@@ -20186,73 +20238,91 @@ function useDataDnd(args) {
20186
20238
  }
20187
20239
  );
20188
20240
  },
20189
- [ownGroup, enabled, overlaySink]
20241
+ [sortableData, enabled]
20190
20242
  );
20191
20243
  const DropZoneShell = ({ children }) => {
20244
+ const droppableId = `dnd-zone-${zoneId}`;
20192
20245
  const { setNodeRef, isOver } = useDroppable({
20193
- id: `dnd-zone-${zoneId}`,
20194
- data: { dndGroup: ownGroup }
20246
+ id: droppableId,
20247
+ data: sortableData
20195
20248
  });
20249
+ React75__default.useEffect(() => {
20250
+ dndLog.debug("dropzone:isOver:change", { droppableId, group: ownGroup, isOver });
20251
+ }, [droppableId, isOver]);
20196
20252
  return /* @__PURE__ */ jsx(
20197
20253
  Box,
20198
20254
  {
20199
20255
  ref: setNodeRef,
20200
20256
  "data-dnd-zone": ownGroup,
20257
+ "data-dnd-is-over": isOver ? "true" : "false",
20201
20258
  className: isOver ? "ring-2 ring-primary ring-offset-2 rounded-lg transition-all min-h-[3rem]" : "min-h-[3rem] rounded-lg transition-all",
20202
20259
  children
20203
20260
  }
20204
20261
  );
20205
20262
  };
20206
20263
  const rootContextValue = React75__default.useMemo(
20207
- () => ({ registerZone, unregisterZone, setOverlay }),
20208
- [registerZone, unregisterZone, setOverlay]
20264
+ () => ({ registerZone, unregisterZone }),
20265
+ [registerZone, unregisterZone]
20209
20266
  );
20267
+ const handleDragStart = React75__default.useCallback((event) => {
20268
+ const sourceZone = findZoneByItem(event.active.id);
20269
+ dndLog.info("dragStart", {
20270
+ activeId: event.active.id,
20271
+ activeData: event.active.data?.current,
20272
+ sourceGroup: sourceZone?.group,
20273
+ zoneCount: zonesRef.current.size
20274
+ });
20275
+ }, [findZoneByItem]);
20276
+ const handleDragOver = React75__default.useCallback((event) => {
20277
+ dndLog.debug("dragOver", {
20278
+ activeId: event.active.id,
20279
+ overId: event.over?.id,
20280
+ overData: event.over?.data?.current
20281
+ });
20282
+ }, []);
20283
+ const handleDragCancel = React75__default.useCallback((event) => {
20284
+ dndLog.warn("dragCancel", {
20285
+ activeId: event.active.id,
20286
+ reason: "dnd-kit cancelled the drag (escape key, pointer interrupted, or external)"
20287
+ });
20288
+ }, []);
20210
20289
  const wrapContainer = React75__default.useCallback(
20211
20290
  (children) => {
20212
20291
  if (!enabled) return children;
20213
20292
  const strategy = layout === "grid" ? rectSortingStrategy : verticalListSortingStrategy;
20214
- const clearOverlay = () => setOverlay(null);
20215
20293
  if (!isZone) {
20216
20294
  if (!isRoot) return children;
20217
- return /* @__PURE__ */ jsx(RootCtx.Provider, { value: rootContextValue, children: /* @__PURE__ */ jsxs(
20295
+ return /* @__PURE__ */ jsx(RootCtx.Provider, { value: rootContextValue, children: /* @__PURE__ */ jsx(
20218
20296
  DndContext,
20219
20297
  {
20220
20298
  sensors,
20221
20299
  collisionDetection,
20222
- onDragEnd: (e) => {
20223
- handleDragEnd(e);
20224
- clearOverlay();
20225
- },
20226
- onDragCancel: clearOverlay,
20227
- children: [
20228
- children,
20229
- /* @__PURE__ */ jsx(DragOverlay, { children: overlayNode })
20230
- ]
20300
+ onDragStart: handleDragStart,
20301
+ onDragOver: handleDragOver,
20302
+ onDragEnd: handleDragEnd,
20303
+ onDragCancel: handleDragCancel,
20304
+ children
20231
20305
  }
20232
20306
  ) });
20233
20307
  }
20234
20308
  const inner = /* @__PURE__ */ jsx(DropZoneShell, { children: /* @__PURE__ */ jsx(SortableContext, { items: itemIds, strategy, children }) });
20235
20309
  if (isRoot) {
20236
- return /* @__PURE__ */ jsx(RootCtx.Provider, { value: rootContextValue, children: /* @__PURE__ */ jsxs(
20310
+ return /* @__PURE__ */ jsx(RootCtx.Provider, { value: rootContextValue, children: /* @__PURE__ */ jsx(
20237
20311
  DndContext,
20238
20312
  {
20239
20313
  sensors,
20240
20314
  collisionDetection,
20241
- onDragEnd: (e) => {
20242
- handleDragEnd(e);
20243
- clearOverlay();
20244
- },
20245
- onDragCancel: clearOverlay,
20246
- children: [
20247
- inner,
20248
- /* @__PURE__ */ jsx(DragOverlay, { children: overlayNode })
20249
- ]
20315
+ onDragStart: handleDragStart,
20316
+ onDragOver: handleDragOver,
20317
+ onDragEnd: handleDragEnd,
20318
+ onDragCancel: handleDragCancel,
20319
+ children: inner
20250
20320
  }
20251
20321
  ) });
20252
20322
  }
20253
20323
  return inner;
20254
20324
  },
20255
- [enabled, isZone, layout, sensors, collisionDetection, handleDragEnd, itemIds, isRoot, rootContextValue, overlayNode, setOverlay]
20325
+ [enabled, isZone, layout, sensors, collisionDetection, handleDragStart, handleDragOver, handleDragEnd, handleDragCancel, itemIds, isRoot, rootContextValue]
20256
20326
  );
20257
20327
  return {
20258
20328
  enabled,
@@ -20262,12 +20332,13 @@ function useDataDnd(args) {
20262
20332
  orderedItems
20263
20333
  };
20264
20334
  }
20265
- var RootCtx;
20335
+ var dndLog, RootCtx;
20266
20336
  var init_useDataDnd = __esm({
20267
20337
  "components/molecules/useDataDnd.tsx"() {
20268
20338
  "use client";
20269
20339
  init_useEventBus();
20270
20340
  init_Box();
20341
+ dndLog = createLogger("almadar:ui:dnd");
20271
20342
  RootCtx = React75__default.createContext(null);
20272
20343
  }
20273
20344
  });