@almadar/ui 4.50.12 → 4.50.14

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.
@@ -13697,7 +13697,7 @@ var init_MapView = __esm({
13697
13697
  shadowSize: [41, 41]
13698
13698
  });
13699
13699
  L.Marker.prototype.options.icon = defaultIcon;
13700
- const { useEffect: useEffect87, useRef: useRef87, useCallback: useCallback127, useState: useState121 } = React93__namespace.default;
13700
+ const { useEffect: useEffect87, useRef: useRef87, useCallback: useCallback128, useState: useState122 } = React93__namespace.default;
13701
13701
  const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
13702
13702
  const { useEventBus: useEventBus3 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
13703
13703
  function MapUpdater({ centerLat, centerLng, zoom }) {
@@ -13742,8 +13742,8 @@ var init_MapView = __esm({
13742
13742
  showAttribution = true
13743
13743
  }) {
13744
13744
  const eventBus = useEventBus3();
13745
- const [clickedPosition, setClickedPosition] = useState121(null);
13746
- const handleMapClick = useCallback127((lat, lng) => {
13745
+ const [clickedPosition, setClickedPosition] = useState122(null);
13746
+ const handleMapClick = useCallback128((lat, lng) => {
13747
13747
  if (showClickedPin) {
13748
13748
  setClickedPosition({ lat, lng });
13749
13749
  }
@@ -13752,7 +13752,7 @@ var init_MapView = __esm({
13752
13752
  eventBus.emit(`UI:${mapClickEvent}`, { latitude: lat, longitude: lng });
13753
13753
  }
13754
13754
  }, [onMapClick, mapClickEvent, eventBus, showClickedPin]);
13755
- const handleMarkerClick = useCallback127((marker) => {
13755
+ const handleMarkerClick = useCallback128((marker) => {
13756
13756
  onMarkerClick?.(marker);
13757
13757
  if (markerClickEvent) {
13758
13758
  eventBus.emit(`UI:${markerClickEvent}`, { ...marker });
@@ -24948,6 +24948,7 @@ function useDataDnd(args) {
24948
24948
  zonesRef.current.delete(zoneId2);
24949
24949
  }, []);
24950
24950
  const [activeDrag, setActiveDrag] = React93__namespace.default.useState(null);
24951
+ const [overZoneGroup, setOverZoneGroup] = React93__namespace.default.useState(null);
24951
24952
  const zoneId = React93__namespace.default.useId();
24952
24953
  const ownGroup = dragGroup ?? accepts ?? zoneId;
24953
24954
  const meta = React93__namespace.default.useMemo(
@@ -25130,25 +25131,29 @@ function useDataDnd(args) {
25130
25131
  });
25131
25132
  const ctx = React93__namespace.default.useContext(RootCtx);
25132
25133
  const activeDrag2 = ctx?.activeDrag ?? null;
25133
- const showForeignPlaceholder = isOver && activeDrag2 != null && activeDrag2.sourceGroup !== ownGroup;
25134
+ const overZoneGroup2 = ctx?.overZoneGroup ?? null;
25135
+ const isThisZoneOver = overZoneGroup2 === ownGroup;
25136
+ const showForeignPlaceholder = isThisZoneOver && activeDrag2 != null && activeDrag2.sourceGroup !== ownGroup;
25134
25137
  dndLog.debug("dropzone:render", {
25135
25138
  group: ownGroup,
25136
25139
  isOver,
25140
+ isThisZoneOver,
25141
+ overZoneGroup: overZoneGroup2,
25137
25142
  activeDragSourceGroup: activeDrag2?.sourceGroup ?? null,
25138
25143
  activeDragHeight: activeDrag2?.height ?? null,
25139
25144
  showForeignPlaceholder,
25140
25145
  ctxAvailable: ctx != null
25141
25146
  });
25142
25147
  React93__namespace.default.useEffect(() => {
25143
- dndLog.info("dropzone:isOver:change", { droppableId, group: ownGroup, isOver, showForeignPlaceholder, activeDragSourceGroup: activeDrag2?.sourceGroup ?? null });
25144
- }, [droppableId, isOver, showForeignPlaceholder]);
25148
+ dndLog.info("dropzone:isOver:change", { droppableId, group: ownGroup, isOver, isThisZoneOver, showForeignPlaceholder, activeDragSourceGroup: activeDrag2?.sourceGroup ?? null });
25149
+ }, [droppableId, isOver, isThisZoneOver, showForeignPlaceholder]);
25145
25150
  return /* @__PURE__ */ jsxRuntime.jsxs(
25146
25151
  Box,
25147
25152
  {
25148
25153
  ref: setNodeRef,
25149
25154
  "data-dnd-zone": ownGroup,
25150
- "data-dnd-is-over": isOver ? "true" : "false",
25151
- className: isOver ? "ring-2 ring-primary ring-offset-2 rounded-lg transition-all min-h-[3rem]" : "min-h-[3rem] rounded-lg transition-all",
25155
+ "data-dnd-is-over": isThisZoneOver ? "true" : "false",
25156
+ className: isThisZoneOver ? "ring-2 ring-primary ring-offset-2 rounded-lg transition-all min-h-[3rem]" : "min-h-[3rem] rounded-lg transition-all",
25152
25157
  children: [
25153
25158
  children,
25154
25159
  showForeignPlaceholder ? /* @__PURE__ */ jsxRuntime.jsx(
@@ -25164,8 +25169,8 @@ function useDataDnd(args) {
25164
25169
  );
25165
25170
  };
25166
25171
  const rootContextValue = React93__namespace.default.useMemo(
25167
- () => ({ registerZone, unregisterZone, activeDrag }),
25168
- [registerZone, unregisterZone, activeDrag]
25172
+ () => ({ registerZone, unregisterZone, activeDrag, overZoneGroup }),
25173
+ [registerZone, unregisterZone, activeDrag, overZoneGroup]
25169
25174
  );
25170
25175
  const handleDragStart = React93__namespace.default.useCallback((event) => {
25171
25176
  const sourceZone = findZoneByItem(event.active.id);
@@ -25187,14 +25192,18 @@ function useDataDnd(args) {
25187
25192
  });
25188
25193
  }, [findZoneByItem, isRoot, zoneId]);
25189
25194
  const handleDragOver = React93__namespace.default.useCallback((event) => {
25195
+ const overData = event.over?.data?.current;
25196
+ const group = overData?.dndGroup ?? null;
25197
+ setOverZoneGroup(group);
25190
25198
  dndLog.debug("dragOver", {
25191
25199
  activeId: event.active.id,
25192
25200
  overId: event.over?.id,
25193
- overData: event.over?.data?.current
25201
+ overGroup: group
25194
25202
  });
25195
25203
  }, []);
25196
25204
  const handleDragCancel = React93__namespace.default.useCallback((event) => {
25197
25205
  setActiveDrag(null);
25206
+ setOverZoneGroup(null);
25198
25207
  dndLog.warn("dragCancel", {
25199
25208
  activeId: event.active.id,
25200
25209
  reason: "dnd-kit cancelled the drag (escape key, pointer interrupted, or external)"
@@ -25203,6 +25212,7 @@ function useDataDnd(args) {
25203
25212
  const handleDragEndWithCleanup = React93__namespace.default.useCallback((event) => {
25204
25213
  handleDragEnd(event);
25205
25214
  setActiveDrag(null);
25215
+ setOverZoneGroup(null);
25206
25216
  }, [handleDragEnd]);
25207
25217
  const wrapContainer = React93__namespace.default.useCallback(
25208
25218
  (children) => {
@@ -57363,6 +57373,66 @@ function convertFnFormLambdasInProps(props) {
57363
57373
  // hooks/index.ts
57364
57374
  init_useEventBus();
57365
57375
  var ALMADAR_DND_MIME = "application/x-almadar-dnd";
57376
+
57377
+ // hooks/useDropZone.ts
57378
+ init_useEventBus();
57379
+ function parsePayload(e) {
57380
+ try {
57381
+ const raw = e.dataTransfer.getData(ALMADAR_DND_MIME);
57382
+ if (!raw) return null;
57383
+ const parsed = JSON.parse(raw);
57384
+ if (typeof parsed.kind !== "string" || !parsed.data) return null;
57385
+ return parsed;
57386
+ } catch {
57387
+ return null;
57388
+ }
57389
+ }
57390
+ function hasAlmadarPayload(e) {
57391
+ return e.dataTransfer.types.includes(ALMADAR_DND_MIME);
57392
+ }
57393
+ function useDropZone({ accepts, onDrop, disabled = false }) {
57394
+ const [isOver, setIsOver] = React93.useState(false);
57395
+ const eventBus = useEventBus();
57396
+ const handleDragOver = React93.useCallback(
57397
+ (e) => {
57398
+ if (disabled) return;
57399
+ if (!hasAlmadarPayload(e)) return;
57400
+ e.preventDefault();
57401
+ e.dataTransfer.dropEffect = "copy";
57402
+ setIsOver(true);
57403
+ },
57404
+ [disabled]
57405
+ );
57406
+ const handleDragLeave = React93.useCallback(
57407
+ (e) => {
57408
+ setIsOver(false);
57409
+ },
57410
+ []
57411
+ );
57412
+ const handleDrop = React93.useCallback(
57413
+ (e) => {
57414
+ e.preventDefault();
57415
+ setIsOver(false);
57416
+ if (disabled) return;
57417
+ const payload = parsePayload(e);
57418
+ if (!payload) return;
57419
+ if (!accepts.includes(payload.kind)) return;
57420
+ const position = { x: e.clientX, y: e.clientY };
57421
+ onDrop(payload, position);
57422
+ eventBus.emit("UI:DROP", { kind: payload.kind, data: payload.data, ...position });
57423
+ },
57424
+ [disabled, accepts, onDrop, eventBus]
57425
+ );
57426
+ const dropProps = React93.useMemo(
57427
+ () => ({
57428
+ onDragOver: handleDragOver,
57429
+ onDragLeave: handleDragLeave,
57430
+ onDrop: handleDrop
57431
+ }),
57432
+ [handleDragOver, handleDragLeave, handleDrop]
57433
+ );
57434
+ return { dropProps, isOver };
57435
+ }
57366
57436
  var log16 = logger.createLogger("almadar:ui:effects:client-handlers");
57367
57437
  function createClientEffectHandlers(options) {
57368
57438
  const { eventBus, slotSetter, navigate, notify, callService } = options;
@@ -59321,19 +59391,98 @@ var OrbPreviewNodeInner = (props) => {
59321
59391
  const statusBorder = isRunning ? "var(--color-primary)" : isError ? "var(--color-danger)" : isSuccess ? "var(--color-success)" : null;
59322
59392
  const borderWidth = isRunning || isError || isSuccess ? "2px" : "1.5px";
59323
59393
  const borderColor = statusBorder ?? (hovered ? "var(--color-primary)" : colors.border);
59394
+ const handleL1Drop = React93.useCallback(
59395
+ (payload) => {
59396
+ if (payload.kind !== "pattern") return;
59397
+ if (typeof payload.data.type !== "string") return;
59398
+ eventBus.emit("UI:PATTERN_DROP", {
59399
+ patternType: payload.data.type,
59400
+ containerNode: { orbitalName: data.orbitalName }
59401
+ });
59402
+ },
59403
+ [eventBus, data.orbitalName]
59404
+ );
59405
+ const { dropProps: l1DropProps, isOver: l1IsOver } = useDropZone({
59406
+ accepts: ["pattern"],
59407
+ onDrop: handleL1Drop,
59408
+ disabled: isExpanded
59409
+ });
59324
59410
  return /* @__PURE__ */ jsxRuntime.jsxs(
59325
59411
  Box,
59326
59412
  {
59413
+ ...isExpanded ? {} : l1DropProps,
59327
59414
  className: `rounded-lg border shadow-sm bg-card transition-all duration-200 overflow-hidden relative${isRunning ? " orb-preview-running" : ""}`,
59328
59415
  style: {
59329
- borderColor,
59330
- borderWidth,
59331
- width: preset.width
59416
+ borderColor: l1IsOver ? "var(--color-primary)" : borderColor,
59417
+ borderWidth: l1IsOver ? "2px" : borderWidth,
59418
+ width: preset.width,
59419
+ boxShadow: l1IsOver ? "0 0 0 3px var(--color-primary), 0 0 12px var(--color-primary)" : void 0
59332
59420
  },
59333
59421
  onMouseEnter: handleMouseEnter,
59334
59422
  onMouseLeave: handleMouseLeave,
59335
59423
  children: [
59336
59424
  /* @__PURE__ */ jsxRuntime.jsx("style", { children: SELECTION_STYLES }),
59425
+ !isExpanded && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
59426
+ /* @__PURE__ */ jsxRuntime.jsx(
59427
+ Box,
59428
+ {
59429
+ className: "absolute top-1.5 left-1.5 rounded px-1 py-[1px] text-[8px] font-mono uppercase tracking-wider pointer-events-none",
59430
+ style: {
59431
+ backgroundColor: "var(--color-muted)",
59432
+ color: "var(--color-muted-foreground)",
59433
+ zIndex: 3
59434
+ },
59435
+ children: "Preview"
59436
+ }
59437
+ ),
59438
+ hovered && !dragActive && !l1IsOver && /* @__PURE__ */ jsxRuntime.jsx(
59439
+ Box,
59440
+ {
59441
+ className: "absolute inset-0 flex items-center justify-center pointer-events-none",
59442
+ style: {
59443
+ backgroundColor: "rgba(0,0,0,0.04)",
59444
+ zIndex: 2
59445
+ },
59446
+ children: /* @__PURE__ */ jsxRuntime.jsxs(
59447
+ Box,
59448
+ {
59449
+ className: "rounded-md px-2 py-1 text-[11px] font-medium flex items-center gap-1",
59450
+ style: {
59451
+ backgroundColor: "var(--color-card)",
59452
+ color: "var(--color-foreground)",
59453
+ boxShadow: "var(--shadow-main)"
59454
+ },
59455
+ children: [
59456
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: 12 }, children: "\u279E" }),
59457
+ "Click to open"
59458
+ ]
59459
+ }
59460
+ )
59461
+ }
59462
+ ),
59463
+ (dragActive || l1IsOver) && /* @__PURE__ */ jsxRuntime.jsx(
59464
+ Box,
59465
+ {
59466
+ className: "absolute inset-0 flex items-center justify-center pointer-events-none",
59467
+ style: {
59468
+ backgroundColor: l1IsOver ? "rgba(20,184,166,0.15)" : "rgba(20,184,166,0.06)",
59469
+ zIndex: 2
59470
+ },
59471
+ children: /* @__PURE__ */ jsxRuntime.jsx(
59472
+ Box,
59473
+ {
59474
+ className: "rounded-md px-2 py-1 text-[11px] font-semibold",
59475
+ style: {
59476
+ backgroundColor: "var(--color-primary)",
59477
+ color: "var(--color-primary-foreground)",
59478
+ boxShadow: "var(--shadow-lg)"
59479
+ },
59480
+ children: "Drop to add and open"
59481
+ }
59482
+ )
59483
+ }
59484
+ )
59485
+ ] }),
59337
59486
  isRunning && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
59338
59487
  /* @__PURE__ */ jsxRuntime.jsx("style", { children: `
59339
59488
  @keyframes orb-preview-running-pulse {
@@ -60515,13 +60664,14 @@ function FlowCanvasInner({
60515
60664
  transition: nodeData.transitionEvent
60516
60665
  });
60517
60666
  } else {
60518
- onNodeClick?.({
60519
- level: "overview",
60520
- orbital: nodeData.orbitalName ?? node.id
60521
- });
60522
- onNodeSelect?.(nodeData.orbitalName ?? node.id);
60667
+ const orbitalName = nodeData.orbitalName ?? node.id;
60668
+ onNodeClick?.({ level: "overview", orbital: orbitalName });
60669
+ onNodeSelect?.(orbitalName);
60670
+ setExpandedOrbital(orbitalName);
60671
+ setLevel("expanded");
60672
+ onLevelChange?.("expanded", orbitalName);
60523
60673
  }
60524
- }, [level, expandedOrbital, onNodeClick]);
60674
+ }, [level, expandedOrbital, onNodeClick, onNodeSelect, onLevelChange]);
60525
60675
  const handleClosePanel = React93.useCallback(() => {
60526
60676
  setSelectedNode(null);
60527
60677
  }, []);
package/dist/avl/index.js CHANGED
@@ -13651,7 +13651,7 @@ var init_MapView = __esm({
13651
13651
  shadowSize: [41, 41]
13652
13652
  });
13653
13653
  L.Marker.prototype.options.icon = defaultIcon;
13654
- const { useEffect: useEffect87, useRef: useRef87, useCallback: useCallback127, useState: useState121 } = React93__default;
13654
+ const { useEffect: useEffect87, useRef: useRef87, useCallback: useCallback128, useState: useState122 } = React93__default;
13655
13655
  const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
13656
13656
  const { useEventBus: useEventBus3 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
13657
13657
  function MapUpdater({ centerLat, centerLng, zoom }) {
@@ -13696,8 +13696,8 @@ var init_MapView = __esm({
13696
13696
  showAttribution = true
13697
13697
  }) {
13698
13698
  const eventBus = useEventBus3();
13699
- const [clickedPosition, setClickedPosition] = useState121(null);
13700
- const handleMapClick = useCallback127((lat, lng) => {
13699
+ const [clickedPosition, setClickedPosition] = useState122(null);
13700
+ const handleMapClick = useCallback128((lat, lng) => {
13701
13701
  if (showClickedPin) {
13702
13702
  setClickedPosition({ lat, lng });
13703
13703
  }
@@ -13706,7 +13706,7 @@ var init_MapView = __esm({
13706
13706
  eventBus.emit(`UI:${mapClickEvent}`, { latitude: lat, longitude: lng });
13707
13707
  }
13708
13708
  }, [onMapClick, mapClickEvent, eventBus, showClickedPin]);
13709
- const handleMarkerClick = useCallback127((marker) => {
13709
+ const handleMarkerClick = useCallback128((marker) => {
13710
13710
  onMarkerClick?.(marker);
13711
13711
  if (markerClickEvent) {
13712
13712
  eventBus.emit(`UI:${markerClickEvent}`, { ...marker });
@@ -24902,6 +24902,7 @@ function useDataDnd(args) {
24902
24902
  zonesRef.current.delete(zoneId2);
24903
24903
  }, []);
24904
24904
  const [activeDrag, setActiveDrag] = React93__default.useState(null);
24905
+ const [overZoneGroup, setOverZoneGroup] = React93__default.useState(null);
24905
24906
  const zoneId = React93__default.useId();
24906
24907
  const ownGroup = dragGroup ?? accepts ?? zoneId;
24907
24908
  const meta = React93__default.useMemo(
@@ -25084,25 +25085,29 @@ function useDataDnd(args) {
25084
25085
  });
25085
25086
  const ctx = React93__default.useContext(RootCtx);
25086
25087
  const activeDrag2 = ctx?.activeDrag ?? null;
25087
- const showForeignPlaceholder = isOver && activeDrag2 != null && activeDrag2.sourceGroup !== ownGroup;
25088
+ const overZoneGroup2 = ctx?.overZoneGroup ?? null;
25089
+ const isThisZoneOver = overZoneGroup2 === ownGroup;
25090
+ const showForeignPlaceholder = isThisZoneOver && activeDrag2 != null && activeDrag2.sourceGroup !== ownGroup;
25088
25091
  dndLog.debug("dropzone:render", {
25089
25092
  group: ownGroup,
25090
25093
  isOver,
25094
+ isThisZoneOver,
25095
+ overZoneGroup: overZoneGroup2,
25091
25096
  activeDragSourceGroup: activeDrag2?.sourceGroup ?? null,
25092
25097
  activeDragHeight: activeDrag2?.height ?? null,
25093
25098
  showForeignPlaceholder,
25094
25099
  ctxAvailable: ctx != null
25095
25100
  });
25096
25101
  React93__default.useEffect(() => {
25097
- dndLog.info("dropzone:isOver:change", { droppableId, group: ownGroup, isOver, showForeignPlaceholder, activeDragSourceGroup: activeDrag2?.sourceGroup ?? null });
25098
- }, [droppableId, isOver, showForeignPlaceholder]);
25102
+ dndLog.info("dropzone:isOver:change", { droppableId, group: ownGroup, isOver, isThisZoneOver, showForeignPlaceholder, activeDragSourceGroup: activeDrag2?.sourceGroup ?? null });
25103
+ }, [droppableId, isOver, isThisZoneOver, showForeignPlaceholder]);
25099
25104
  return /* @__PURE__ */ jsxs(
25100
25105
  Box,
25101
25106
  {
25102
25107
  ref: setNodeRef,
25103
25108
  "data-dnd-zone": ownGroup,
25104
- "data-dnd-is-over": isOver ? "true" : "false",
25105
- className: isOver ? "ring-2 ring-primary ring-offset-2 rounded-lg transition-all min-h-[3rem]" : "min-h-[3rem] rounded-lg transition-all",
25109
+ "data-dnd-is-over": isThisZoneOver ? "true" : "false",
25110
+ className: isThisZoneOver ? "ring-2 ring-primary ring-offset-2 rounded-lg transition-all min-h-[3rem]" : "min-h-[3rem] rounded-lg transition-all",
25106
25111
  children: [
25107
25112
  children,
25108
25113
  showForeignPlaceholder ? /* @__PURE__ */ jsx(
@@ -25118,8 +25123,8 @@ function useDataDnd(args) {
25118
25123
  );
25119
25124
  };
25120
25125
  const rootContextValue = React93__default.useMemo(
25121
- () => ({ registerZone, unregisterZone, activeDrag }),
25122
- [registerZone, unregisterZone, activeDrag]
25126
+ () => ({ registerZone, unregisterZone, activeDrag, overZoneGroup }),
25127
+ [registerZone, unregisterZone, activeDrag, overZoneGroup]
25123
25128
  );
25124
25129
  const handleDragStart = React93__default.useCallback((event) => {
25125
25130
  const sourceZone = findZoneByItem(event.active.id);
@@ -25141,14 +25146,18 @@ function useDataDnd(args) {
25141
25146
  });
25142
25147
  }, [findZoneByItem, isRoot, zoneId]);
25143
25148
  const handleDragOver = React93__default.useCallback((event) => {
25149
+ const overData = event.over?.data?.current;
25150
+ const group = overData?.dndGroup ?? null;
25151
+ setOverZoneGroup(group);
25144
25152
  dndLog.debug("dragOver", {
25145
25153
  activeId: event.active.id,
25146
25154
  overId: event.over?.id,
25147
- overData: event.over?.data?.current
25155
+ overGroup: group
25148
25156
  });
25149
25157
  }, []);
25150
25158
  const handleDragCancel = React93__default.useCallback((event) => {
25151
25159
  setActiveDrag(null);
25160
+ setOverZoneGroup(null);
25152
25161
  dndLog.warn("dragCancel", {
25153
25162
  activeId: event.active.id,
25154
25163
  reason: "dnd-kit cancelled the drag (escape key, pointer interrupted, or external)"
@@ -25157,6 +25166,7 @@ function useDataDnd(args) {
25157
25166
  const handleDragEndWithCleanup = React93__default.useCallback((event) => {
25158
25167
  handleDragEnd(event);
25159
25168
  setActiveDrag(null);
25169
+ setOverZoneGroup(null);
25160
25170
  }, [handleDragEnd]);
25161
25171
  const wrapContainer = React93__default.useCallback(
25162
25172
  (children) => {
@@ -57317,6 +57327,66 @@ function convertFnFormLambdasInProps(props) {
57317
57327
  // hooks/index.ts
57318
57328
  init_useEventBus();
57319
57329
  var ALMADAR_DND_MIME = "application/x-almadar-dnd";
57330
+
57331
+ // hooks/useDropZone.ts
57332
+ init_useEventBus();
57333
+ function parsePayload(e) {
57334
+ try {
57335
+ const raw = e.dataTransfer.getData(ALMADAR_DND_MIME);
57336
+ if (!raw) return null;
57337
+ const parsed = JSON.parse(raw);
57338
+ if (typeof parsed.kind !== "string" || !parsed.data) return null;
57339
+ return parsed;
57340
+ } catch {
57341
+ return null;
57342
+ }
57343
+ }
57344
+ function hasAlmadarPayload(e) {
57345
+ return e.dataTransfer.types.includes(ALMADAR_DND_MIME);
57346
+ }
57347
+ function useDropZone({ accepts, onDrop, disabled = false }) {
57348
+ const [isOver, setIsOver] = useState(false);
57349
+ const eventBus = useEventBus();
57350
+ const handleDragOver = useCallback(
57351
+ (e) => {
57352
+ if (disabled) return;
57353
+ if (!hasAlmadarPayload(e)) return;
57354
+ e.preventDefault();
57355
+ e.dataTransfer.dropEffect = "copy";
57356
+ setIsOver(true);
57357
+ },
57358
+ [disabled]
57359
+ );
57360
+ const handleDragLeave = useCallback(
57361
+ (e) => {
57362
+ setIsOver(false);
57363
+ },
57364
+ []
57365
+ );
57366
+ const handleDrop = useCallback(
57367
+ (e) => {
57368
+ e.preventDefault();
57369
+ setIsOver(false);
57370
+ if (disabled) return;
57371
+ const payload = parsePayload(e);
57372
+ if (!payload) return;
57373
+ if (!accepts.includes(payload.kind)) return;
57374
+ const position = { x: e.clientX, y: e.clientY };
57375
+ onDrop(payload, position);
57376
+ eventBus.emit("UI:DROP", { kind: payload.kind, data: payload.data, ...position });
57377
+ },
57378
+ [disabled, accepts, onDrop, eventBus]
57379
+ );
57380
+ const dropProps = useMemo(
57381
+ () => ({
57382
+ onDragOver: handleDragOver,
57383
+ onDragLeave: handleDragLeave,
57384
+ onDrop: handleDrop
57385
+ }),
57386
+ [handleDragOver, handleDragLeave, handleDrop]
57387
+ );
57388
+ return { dropProps, isOver };
57389
+ }
57320
57390
  var log16 = createLogger("almadar:ui:effects:client-handlers");
57321
57391
  function createClientEffectHandlers(options) {
57322
57392
  const { eventBus, slotSetter, navigate, notify, callService } = options;
@@ -59275,19 +59345,98 @@ var OrbPreviewNodeInner = (props) => {
59275
59345
  const statusBorder = isRunning ? "var(--color-primary)" : isError ? "var(--color-danger)" : isSuccess ? "var(--color-success)" : null;
59276
59346
  const borderWidth = isRunning || isError || isSuccess ? "2px" : "1.5px";
59277
59347
  const borderColor = statusBorder ?? (hovered ? "var(--color-primary)" : colors.border);
59348
+ const handleL1Drop = useCallback(
59349
+ (payload) => {
59350
+ if (payload.kind !== "pattern") return;
59351
+ if (typeof payload.data.type !== "string") return;
59352
+ eventBus.emit("UI:PATTERN_DROP", {
59353
+ patternType: payload.data.type,
59354
+ containerNode: { orbitalName: data.orbitalName }
59355
+ });
59356
+ },
59357
+ [eventBus, data.orbitalName]
59358
+ );
59359
+ const { dropProps: l1DropProps, isOver: l1IsOver } = useDropZone({
59360
+ accepts: ["pattern"],
59361
+ onDrop: handleL1Drop,
59362
+ disabled: isExpanded
59363
+ });
59278
59364
  return /* @__PURE__ */ jsxs(
59279
59365
  Box,
59280
59366
  {
59367
+ ...isExpanded ? {} : l1DropProps,
59281
59368
  className: `rounded-lg border shadow-sm bg-card transition-all duration-200 overflow-hidden relative${isRunning ? " orb-preview-running" : ""}`,
59282
59369
  style: {
59283
- borderColor,
59284
- borderWidth,
59285
- width: preset.width
59370
+ borderColor: l1IsOver ? "var(--color-primary)" : borderColor,
59371
+ borderWidth: l1IsOver ? "2px" : borderWidth,
59372
+ width: preset.width,
59373
+ boxShadow: l1IsOver ? "0 0 0 3px var(--color-primary), 0 0 12px var(--color-primary)" : void 0
59286
59374
  },
59287
59375
  onMouseEnter: handleMouseEnter,
59288
59376
  onMouseLeave: handleMouseLeave,
59289
59377
  children: [
59290
59378
  /* @__PURE__ */ jsx("style", { children: SELECTION_STYLES }),
59379
+ !isExpanded && /* @__PURE__ */ jsxs(Fragment, { children: [
59380
+ /* @__PURE__ */ jsx(
59381
+ Box,
59382
+ {
59383
+ className: "absolute top-1.5 left-1.5 rounded px-1 py-[1px] text-[8px] font-mono uppercase tracking-wider pointer-events-none",
59384
+ style: {
59385
+ backgroundColor: "var(--color-muted)",
59386
+ color: "var(--color-muted-foreground)",
59387
+ zIndex: 3
59388
+ },
59389
+ children: "Preview"
59390
+ }
59391
+ ),
59392
+ hovered && !dragActive && !l1IsOver && /* @__PURE__ */ jsx(
59393
+ Box,
59394
+ {
59395
+ className: "absolute inset-0 flex items-center justify-center pointer-events-none",
59396
+ style: {
59397
+ backgroundColor: "rgba(0,0,0,0.04)",
59398
+ zIndex: 2
59399
+ },
59400
+ children: /* @__PURE__ */ jsxs(
59401
+ Box,
59402
+ {
59403
+ className: "rounded-md px-2 py-1 text-[11px] font-medium flex items-center gap-1",
59404
+ style: {
59405
+ backgroundColor: "var(--color-card)",
59406
+ color: "var(--color-foreground)",
59407
+ boxShadow: "var(--shadow-main)"
59408
+ },
59409
+ children: [
59410
+ /* @__PURE__ */ jsx("span", { style: { fontSize: 12 }, children: "\u279E" }),
59411
+ "Click to open"
59412
+ ]
59413
+ }
59414
+ )
59415
+ }
59416
+ ),
59417
+ (dragActive || l1IsOver) && /* @__PURE__ */ jsx(
59418
+ Box,
59419
+ {
59420
+ className: "absolute inset-0 flex items-center justify-center pointer-events-none",
59421
+ style: {
59422
+ backgroundColor: l1IsOver ? "rgba(20,184,166,0.15)" : "rgba(20,184,166,0.06)",
59423
+ zIndex: 2
59424
+ },
59425
+ children: /* @__PURE__ */ jsx(
59426
+ Box,
59427
+ {
59428
+ className: "rounded-md px-2 py-1 text-[11px] font-semibold",
59429
+ style: {
59430
+ backgroundColor: "var(--color-primary)",
59431
+ color: "var(--color-primary-foreground)",
59432
+ boxShadow: "var(--shadow-lg)"
59433
+ },
59434
+ children: "Drop to add and open"
59435
+ }
59436
+ )
59437
+ }
59438
+ )
59439
+ ] }),
59291
59440
  isRunning && /* @__PURE__ */ jsxs(Fragment, { children: [
59292
59441
  /* @__PURE__ */ jsx("style", { children: `
59293
59442
  @keyframes orb-preview-running-pulse {
@@ -60469,13 +60618,14 @@ function FlowCanvasInner({
60469
60618
  transition: nodeData.transitionEvent
60470
60619
  });
60471
60620
  } else {
60472
- onNodeClick?.({
60473
- level: "overview",
60474
- orbital: nodeData.orbitalName ?? node.id
60475
- });
60476
- onNodeSelect?.(nodeData.orbitalName ?? node.id);
60621
+ const orbitalName = nodeData.orbitalName ?? node.id;
60622
+ onNodeClick?.({ level: "overview", orbital: orbitalName });
60623
+ onNodeSelect?.(orbitalName);
60624
+ setExpandedOrbital(orbitalName);
60625
+ setLevel("expanded");
60626
+ onLevelChange?.("expanded", orbitalName);
60477
60627
  }
60478
- }, [level, expandedOrbital, onNodeClick]);
60628
+ }, [level, expandedOrbital, onNodeClick, onNodeSelect, onLevelChange]);
60479
60629
  const handleClosePanel = useCallback(() => {
60480
60630
  setSelectedNode(null);
60481
60631
  }, []);
@@ -20115,6 +20115,7 @@ function useDataDnd(args) {
20115
20115
  zonesRef.current.delete(zoneId2);
20116
20116
  }, []);
20117
20117
  const [activeDrag, setActiveDrag] = React75__namespace.default.useState(null);
20118
+ const [overZoneGroup, setOverZoneGroup] = React75__namespace.default.useState(null);
20118
20119
  const zoneId = React75__namespace.default.useId();
20119
20120
  const ownGroup = dragGroup ?? accepts ?? zoneId;
20120
20121
  const meta = React75__namespace.default.useMemo(
@@ -20297,25 +20298,29 @@ function useDataDnd(args) {
20297
20298
  });
20298
20299
  const ctx = React75__namespace.default.useContext(RootCtx);
20299
20300
  const activeDrag2 = ctx?.activeDrag ?? null;
20300
- const showForeignPlaceholder = isOver && activeDrag2 != null && activeDrag2.sourceGroup !== ownGroup;
20301
+ const overZoneGroup2 = ctx?.overZoneGroup ?? null;
20302
+ const isThisZoneOver = overZoneGroup2 === ownGroup;
20303
+ const showForeignPlaceholder = isThisZoneOver && activeDrag2 != null && activeDrag2.sourceGroup !== ownGroup;
20301
20304
  dndLog.debug("dropzone:render", {
20302
20305
  group: ownGroup,
20303
20306
  isOver,
20307
+ isThisZoneOver,
20308
+ overZoneGroup: overZoneGroup2,
20304
20309
  activeDragSourceGroup: activeDrag2?.sourceGroup ?? null,
20305
20310
  activeDragHeight: activeDrag2?.height ?? null,
20306
20311
  showForeignPlaceholder,
20307
20312
  ctxAvailable: ctx != null
20308
20313
  });
20309
20314
  React75__namespace.default.useEffect(() => {
20310
- dndLog.info("dropzone:isOver:change", { droppableId, group: ownGroup, isOver, showForeignPlaceholder, activeDragSourceGroup: activeDrag2?.sourceGroup ?? null });
20311
- }, [droppableId, isOver, showForeignPlaceholder]);
20315
+ dndLog.info("dropzone:isOver:change", { droppableId, group: ownGroup, isOver, isThisZoneOver, showForeignPlaceholder, activeDragSourceGroup: activeDrag2?.sourceGroup ?? null });
20316
+ }, [droppableId, isOver, isThisZoneOver, showForeignPlaceholder]);
20312
20317
  return /* @__PURE__ */ jsxRuntime.jsxs(
20313
20318
  exports.Box,
20314
20319
  {
20315
20320
  ref: setNodeRef,
20316
20321
  "data-dnd-zone": ownGroup,
20317
- "data-dnd-is-over": isOver ? "true" : "false",
20318
- className: isOver ? "ring-2 ring-primary ring-offset-2 rounded-lg transition-all min-h-[3rem]" : "min-h-[3rem] rounded-lg transition-all",
20322
+ "data-dnd-is-over": isThisZoneOver ? "true" : "false",
20323
+ className: isThisZoneOver ? "ring-2 ring-primary ring-offset-2 rounded-lg transition-all min-h-[3rem]" : "min-h-[3rem] rounded-lg transition-all",
20319
20324
  children: [
20320
20325
  children,
20321
20326
  showForeignPlaceholder ? /* @__PURE__ */ jsxRuntime.jsx(
@@ -20331,8 +20336,8 @@ function useDataDnd(args) {
20331
20336
  );
20332
20337
  };
20333
20338
  const rootContextValue = React75__namespace.default.useMemo(
20334
- () => ({ registerZone, unregisterZone, activeDrag }),
20335
- [registerZone, unregisterZone, activeDrag]
20339
+ () => ({ registerZone, unregisterZone, activeDrag, overZoneGroup }),
20340
+ [registerZone, unregisterZone, activeDrag, overZoneGroup]
20336
20341
  );
20337
20342
  const handleDragStart = React75__namespace.default.useCallback((event) => {
20338
20343
  const sourceZone = findZoneByItem(event.active.id);
@@ -20354,14 +20359,18 @@ function useDataDnd(args) {
20354
20359
  });
20355
20360
  }, [findZoneByItem, isRoot, zoneId]);
20356
20361
  const handleDragOver = React75__namespace.default.useCallback((event) => {
20362
+ const overData = event.over?.data?.current;
20363
+ const group = overData?.dndGroup ?? null;
20364
+ setOverZoneGroup(group);
20357
20365
  dndLog.debug("dragOver", {
20358
20366
  activeId: event.active.id,
20359
20367
  overId: event.over?.id,
20360
- overData: event.over?.data?.current
20368
+ overGroup: group
20361
20369
  });
20362
20370
  }, []);
20363
20371
  const handleDragCancel = React75__namespace.default.useCallback((event) => {
20364
20372
  setActiveDrag(null);
20373
+ setOverZoneGroup(null);
20365
20374
  dndLog.warn("dragCancel", {
20366
20375
  activeId: event.active.id,
20367
20376
  reason: "dnd-kit cancelled the drag (escape key, pointer interrupted, or external)"
@@ -20370,6 +20379,7 @@ function useDataDnd(args) {
20370
20379
  const handleDragEndWithCleanup = React75__namespace.default.useCallback((event) => {
20371
20380
  handleDragEnd(event);
20372
20381
  setActiveDrag(null);
20382
+ setOverZoneGroup(null);
20373
20383
  }, [handleDragEnd]);
20374
20384
  const wrapContainer = React75__namespace.default.useCallback(
20375
20385
  (children) => {
@@ -20069,6 +20069,7 @@ function useDataDnd(args) {
20069
20069
  zonesRef.current.delete(zoneId2);
20070
20070
  }, []);
20071
20071
  const [activeDrag, setActiveDrag] = React75__default.useState(null);
20072
+ const [overZoneGroup, setOverZoneGroup] = React75__default.useState(null);
20072
20073
  const zoneId = React75__default.useId();
20073
20074
  const ownGroup = dragGroup ?? accepts ?? zoneId;
20074
20075
  const meta = React75__default.useMemo(
@@ -20251,25 +20252,29 @@ function useDataDnd(args) {
20251
20252
  });
20252
20253
  const ctx = React75__default.useContext(RootCtx);
20253
20254
  const activeDrag2 = ctx?.activeDrag ?? null;
20254
- const showForeignPlaceholder = isOver && activeDrag2 != null && activeDrag2.sourceGroup !== ownGroup;
20255
+ const overZoneGroup2 = ctx?.overZoneGroup ?? null;
20256
+ const isThisZoneOver = overZoneGroup2 === ownGroup;
20257
+ const showForeignPlaceholder = isThisZoneOver && activeDrag2 != null && activeDrag2.sourceGroup !== ownGroup;
20255
20258
  dndLog.debug("dropzone:render", {
20256
20259
  group: ownGroup,
20257
20260
  isOver,
20261
+ isThisZoneOver,
20262
+ overZoneGroup: overZoneGroup2,
20258
20263
  activeDragSourceGroup: activeDrag2?.sourceGroup ?? null,
20259
20264
  activeDragHeight: activeDrag2?.height ?? null,
20260
20265
  showForeignPlaceholder,
20261
20266
  ctxAvailable: ctx != null
20262
20267
  });
20263
20268
  React75__default.useEffect(() => {
20264
- dndLog.info("dropzone:isOver:change", { droppableId, group: ownGroup, isOver, showForeignPlaceholder, activeDragSourceGroup: activeDrag2?.sourceGroup ?? null });
20265
- }, [droppableId, isOver, showForeignPlaceholder]);
20269
+ dndLog.info("dropzone:isOver:change", { droppableId, group: ownGroup, isOver, isThisZoneOver, showForeignPlaceholder, activeDragSourceGroup: activeDrag2?.sourceGroup ?? null });
20270
+ }, [droppableId, isOver, isThisZoneOver, showForeignPlaceholder]);
20266
20271
  return /* @__PURE__ */ jsxs(
20267
20272
  Box,
20268
20273
  {
20269
20274
  ref: setNodeRef,
20270
20275
  "data-dnd-zone": ownGroup,
20271
- "data-dnd-is-over": isOver ? "true" : "false",
20272
- className: isOver ? "ring-2 ring-primary ring-offset-2 rounded-lg transition-all min-h-[3rem]" : "min-h-[3rem] rounded-lg transition-all",
20276
+ "data-dnd-is-over": isThisZoneOver ? "true" : "false",
20277
+ className: isThisZoneOver ? "ring-2 ring-primary ring-offset-2 rounded-lg transition-all min-h-[3rem]" : "min-h-[3rem] rounded-lg transition-all",
20273
20278
  children: [
20274
20279
  children,
20275
20280
  showForeignPlaceholder ? /* @__PURE__ */ jsx(
@@ -20285,8 +20290,8 @@ function useDataDnd(args) {
20285
20290
  );
20286
20291
  };
20287
20292
  const rootContextValue = React75__default.useMemo(
20288
- () => ({ registerZone, unregisterZone, activeDrag }),
20289
- [registerZone, unregisterZone, activeDrag]
20293
+ () => ({ registerZone, unregisterZone, activeDrag, overZoneGroup }),
20294
+ [registerZone, unregisterZone, activeDrag, overZoneGroup]
20290
20295
  );
20291
20296
  const handleDragStart = React75__default.useCallback((event) => {
20292
20297
  const sourceZone = findZoneByItem(event.active.id);
@@ -20308,14 +20313,18 @@ function useDataDnd(args) {
20308
20313
  });
20309
20314
  }, [findZoneByItem, isRoot, zoneId]);
20310
20315
  const handleDragOver = React75__default.useCallback((event) => {
20316
+ const overData = event.over?.data?.current;
20317
+ const group = overData?.dndGroup ?? null;
20318
+ setOverZoneGroup(group);
20311
20319
  dndLog.debug("dragOver", {
20312
20320
  activeId: event.active.id,
20313
20321
  overId: event.over?.id,
20314
- overData: event.over?.data?.current
20322
+ overGroup: group
20315
20323
  });
20316
20324
  }, []);
20317
20325
  const handleDragCancel = React75__default.useCallback((event) => {
20318
20326
  setActiveDrag(null);
20327
+ setOverZoneGroup(null);
20319
20328
  dndLog.warn("dragCancel", {
20320
20329
  activeId: event.active.id,
20321
20330
  reason: "dnd-kit cancelled the drag (escape key, pointer interrupted, or external)"
@@ -20324,6 +20333,7 @@ function useDataDnd(args) {
20324
20333
  const handleDragEndWithCleanup = React75__default.useCallback((event) => {
20325
20334
  handleDragEnd(event);
20326
20335
  setActiveDrag(null);
20336
+ setOverZoneGroup(null);
20327
20337
  }, [handleDragEnd]);
20328
20338
  const wrapContainer = React75__default.useCallback(
20329
20339
  (children) => {
@@ -21360,6 +21360,7 @@ function useDataDnd(args) {
21360
21360
  zonesRef.current.delete(zoneId2);
21361
21361
  }, []);
21362
21362
  const [activeDrag, setActiveDrag] = React81__namespace.default.useState(null);
21363
+ const [overZoneGroup, setOverZoneGroup] = React81__namespace.default.useState(null);
21363
21364
  const zoneId = React81__namespace.default.useId();
21364
21365
  const ownGroup = dragGroup ?? accepts ?? zoneId;
21365
21366
  const meta = React81__namespace.default.useMemo(
@@ -21542,25 +21543,29 @@ function useDataDnd(args) {
21542
21543
  });
21543
21544
  const ctx = React81__namespace.default.useContext(RootCtx);
21544
21545
  const activeDrag2 = ctx?.activeDrag ?? null;
21545
- const showForeignPlaceholder = isOver && activeDrag2 != null && activeDrag2.sourceGroup !== ownGroup;
21546
+ const overZoneGroup2 = ctx?.overZoneGroup ?? null;
21547
+ const isThisZoneOver = overZoneGroup2 === ownGroup;
21548
+ const showForeignPlaceholder = isThisZoneOver && activeDrag2 != null && activeDrag2.sourceGroup !== ownGroup;
21546
21549
  dndLog.debug("dropzone:render", {
21547
21550
  group: ownGroup,
21548
21551
  isOver,
21552
+ isThisZoneOver,
21553
+ overZoneGroup: overZoneGroup2,
21549
21554
  activeDragSourceGroup: activeDrag2?.sourceGroup ?? null,
21550
21555
  activeDragHeight: activeDrag2?.height ?? null,
21551
21556
  showForeignPlaceholder,
21552
21557
  ctxAvailable: ctx != null
21553
21558
  });
21554
21559
  React81__namespace.default.useEffect(() => {
21555
- dndLog.info("dropzone:isOver:change", { droppableId, group: ownGroup, isOver, showForeignPlaceholder, activeDragSourceGroup: activeDrag2?.sourceGroup ?? null });
21556
- }, [droppableId, isOver, showForeignPlaceholder]);
21560
+ dndLog.info("dropzone:isOver:change", { droppableId, group: ownGroup, isOver, isThisZoneOver, showForeignPlaceholder, activeDragSourceGroup: activeDrag2?.sourceGroup ?? null });
21561
+ }, [droppableId, isOver, isThisZoneOver, showForeignPlaceholder]);
21557
21562
  return /* @__PURE__ */ jsxRuntime.jsxs(
21558
21563
  Box,
21559
21564
  {
21560
21565
  ref: setNodeRef,
21561
21566
  "data-dnd-zone": ownGroup,
21562
- "data-dnd-is-over": isOver ? "true" : "false",
21563
- className: isOver ? "ring-2 ring-primary ring-offset-2 rounded-lg transition-all min-h-[3rem]" : "min-h-[3rem] rounded-lg transition-all",
21567
+ "data-dnd-is-over": isThisZoneOver ? "true" : "false",
21568
+ className: isThisZoneOver ? "ring-2 ring-primary ring-offset-2 rounded-lg transition-all min-h-[3rem]" : "min-h-[3rem] rounded-lg transition-all",
21564
21569
  children: [
21565
21570
  children,
21566
21571
  showForeignPlaceholder ? /* @__PURE__ */ jsxRuntime.jsx(
@@ -21576,8 +21581,8 @@ function useDataDnd(args) {
21576
21581
  );
21577
21582
  };
21578
21583
  const rootContextValue = React81__namespace.default.useMemo(
21579
- () => ({ registerZone, unregisterZone, activeDrag }),
21580
- [registerZone, unregisterZone, activeDrag]
21584
+ () => ({ registerZone, unregisterZone, activeDrag, overZoneGroup }),
21585
+ [registerZone, unregisterZone, activeDrag, overZoneGroup]
21581
21586
  );
21582
21587
  const handleDragStart = React81__namespace.default.useCallback((event) => {
21583
21588
  const sourceZone = findZoneByItem(event.active.id);
@@ -21599,14 +21604,18 @@ function useDataDnd(args) {
21599
21604
  });
21600
21605
  }, [findZoneByItem, isRoot, zoneId]);
21601
21606
  const handleDragOver = React81__namespace.default.useCallback((event) => {
21607
+ const overData = event.over?.data?.current;
21608
+ const group = overData?.dndGroup ?? null;
21609
+ setOverZoneGroup(group);
21602
21610
  dndLog.debug("dragOver", {
21603
21611
  activeId: event.active.id,
21604
21612
  overId: event.over?.id,
21605
- overData: event.over?.data?.current
21613
+ overGroup: group
21606
21614
  });
21607
21615
  }, []);
21608
21616
  const handleDragCancel = React81__namespace.default.useCallback((event) => {
21609
21617
  setActiveDrag(null);
21618
+ setOverZoneGroup(null);
21610
21619
  dndLog.warn("dragCancel", {
21611
21620
  activeId: event.active.id,
21612
21621
  reason: "dnd-kit cancelled the drag (escape key, pointer interrupted, or external)"
@@ -21615,6 +21624,7 @@ function useDataDnd(args) {
21615
21624
  const handleDragEndWithCleanup = React81__namespace.default.useCallback((event) => {
21616
21625
  handleDragEnd(event);
21617
21626
  setActiveDrag(null);
21627
+ setOverZoneGroup(null);
21618
21628
  }, [handleDragEnd]);
21619
21629
  const wrapContainer = React81__namespace.default.useCallback(
21620
21630
  (children) => {
@@ -21314,6 +21314,7 @@ function useDataDnd(args) {
21314
21314
  zonesRef.current.delete(zoneId2);
21315
21315
  }, []);
21316
21316
  const [activeDrag, setActiveDrag] = React81__default.useState(null);
21317
+ const [overZoneGroup, setOverZoneGroup] = React81__default.useState(null);
21317
21318
  const zoneId = React81__default.useId();
21318
21319
  const ownGroup = dragGroup ?? accepts ?? zoneId;
21319
21320
  const meta = React81__default.useMemo(
@@ -21496,25 +21497,29 @@ function useDataDnd(args) {
21496
21497
  });
21497
21498
  const ctx = React81__default.useContext(RootCtx);
21498
21499
  const activeDrag2 = ctx?.activeDrag ?? null;
21499
- const showForeignPlaceholder = isOver && activeDrag2 != null && activeDrag2.sourceGroup !== ownGroup;
21500
+ const overZoneGroup2 = ctx?.overZoneGroup ?? null;
21501
+ const isThisZoneOver = overZoneGroup2 === ownGroup;
21502
+ const showForeignPlaceholder = isThisZoneOver && activeDrag2 != null && activeDrag2.sourceGroup !== ownGroup;
21500
21503
  dndLog.debug("dropzone:render", {
21501
21504
  group: ownGroup,
21502
21505
  isOver,
21506
+ isThisZoneOver,
21507
+ overZoneGroup: overZoneGroup2,
21503
21508
  activeDragSourceGroup: activeDrag2?.sourceGroup ?? null,
21504
21509
  activeDragHeight: activeDrag2?.height ?? null,
21505
21510
  showForeignPlaceholder,
21506
21511
  ctxAvailable: ctx != null
21507
21512
  });
21508
21513
  React81__default.useEffect(() => {
21509
- dndLog.info("dropzone:isOver:change", { droppableId, group: ownGroup, isOver, showForeignPlaceholder, activeDragSourceGroup: activeDrag2?.sourceGroup ?? null });
21510
- }, [droppableId, isOver, showForeignPlaceholder]);
21514
+ dndLog.info("dropzone:isOver:change", { droppableId, group: ownGroup, isOver, isThisZoneOver, showForeignPlaceholder, activeDragSourceGroup: activeDrag2?.sourceGroup ?? null });
21515
+ }, [droppableId, isOver, isThisZoneOver, showForeignPlaceholder]);
21511
21516
  return /* @__PURE__ */ jsxs(
21512
21517
  Box,
21513
21518
  {
21514
21519
  ref: setNodeRef,
21515
21520
  "data-dnd-zone": ownGroup,
21516
- "data-dnd-is-over": isOver ? "true" : "false",
21517
- className: isOver ? "ring-2 ring-primary ring-offset-2 rounded-lg transition-all min-h-[3rem]" : "min-h-[3rem] rounded-lg transition-all",
21521
+ "data-dnd-is-over": isThisZoneOver ? "true" : "false",
21522
+ className: isThisZoneOver ? "ring-2 ring-primary ring-offset-2 rounded-lg transition-all min-h-[3rem]" : "min-h-[3rem] rounded-lg transition-all",
21518
21523
  children: [
21519
21524
  children,
21520
21525
  showForeignPlaceholder ? /* @__PURE__ */ jsx(
@@ -21530,8 +21535,8 @@ function useDataDnd(args) {
21530
21535
  );
21531
21536
  };
21532
21537
  const rootContextValue = React81__default.useMemo(
21533
- () => ({ registerZone, unregisterZone, activeDrag }),
21534
- [registerZone, unregisterZone, activeDrag]
21538
+ () => ({ registerZone, unregisterZone, activeDrag, overZoneGroup }),
21539
+ [registerZone, unregisterZone, activeDrag, overZoneGroup]
21535
21540
  );
21536
21541
  const handleDragStart = React81__default.useCallback((event) => {
21537
21542
  const sourceZone = findZoneByItem(event.active.id);
@@ -21553,14 +21558,18 @@ function useDataDnd(args) {
21553
21558
  });
21554
21559
  }, [findZoneByItem, isRoot, zoneId]);
21555
21560
  const handleDragOver = React81__default.useCallback((event) => {
21561
+ const overData = event.over?.data?.current;
21562
+ const group = overData?.dndGroup ?? null;
21563
+ setOverZoneGroup(group);
21556
21564
  dndLog.debug("dragOver", {
21557
21565
  activeId: event.active.id,
21558
21566
  overId: event.over?.id,
21559
- overData: event.over?.data?.current
21567
+ overGroup: group
21560
21568
  });
21561
21569
  }, []);
21562
21570
  const handleDragCancel = React81__default.useCallback((event) => {
21563
21571
  setActiveDrag(null);
21572
+ setOverZoneGroup(null);
21564
21573
  dndLog.warn("dragCancel", {
21565
21574
  activeId: event.active.id,
21566
21575
  reason: "dnd-kit cancelled the drag (escape key, pointer interrupted, or external)"
@@ -21569,6 +21578,7 @@ function useDataDnd(args) {
21569
21578
  const handleDragEndWithCleanup = React81__default.useCallback((event) => {
21570
21579
  handleDragEnd(event);
21571
21580
  setActiveDrag(null);
21581
+ setOverZoneGroup(null);
21572
21582
  }, [handleDragEnd]);
21573
21583
  const wrapContainer = React81__default.useCallback(
21574
21584
  (children) => {
@@ -21129,6 +21129,7 @@ function useDataDnd(args) {
21129
21129
  zonesRef.current.delete(zoneId2);
21130
21130
  }, []);
21131
21131
  const [activeDrag, setActiveDrag] = React80__namespace.default.useState(null);
21132
+ const [overZoneGroup, setOverZoneGroup] = React80__namespace.default.useState(null);
21132
21133
  const zoneId = React80__namespace.default.useId();
21133
21134
  const ownGroup = dragGroup ?? accepts ?? zoneId;
21134
21135
  const meta = React80__namespace.default.useMemo(
@@ -21311,25 +21312,29 @@ function useDataDnd(args) {
21311
21312
  });
21312
21313
  const ctx = React80__namespace.default.useContext(RootCtx);
21313
21314
  const activeDrag2 = ctx?.activeDrag ?? null;
21314
- const showForeignPlaceholder = isOver && activeDrag2 != null && activeDrag2.sourceGroup !== ownGroup;
21315
+ const overZoneGroup2 = ctx?.overZoneGroup ?? null;
21316
+ const isThisZoneOver = overZoneGroup2 === ownGroup;
21317
+ const showForeignPlaceholder = isThisZoneOver && activeDrag2 != null && activeDrag2.sourceGroup !== ownGroup;
21315
21318
  dndLog.debug("dropzone:render", {
21316
21319
  group: ownGroup,
21317
21320
  isOver,
21321
+ isThisZoneOver,
21322
+ overZoneGroup: overZoneGroup2,
21318
21323
  activeDragSourceGroup: activeDrag2?.sourceGroup ?? null,
21319
21324
  activeDragHeight: activeDrag2?.height ?? null,
21320
21325
  showForeignPlaceholder,
21321
21326
  ctxAvailable: ctx != null
21322
21327
  });
21323
21328
  React80__namespace.default.useEffect(() => {
21324
- dndLog.info("dropzone:isOver:change", { droppableId, group: ownGroup, isOver, showForeignPlaceholder, activeDragSourceGroup: activeDrag2?.sourceGroup ?? null });
21325
- }, [droppableId, isOver, showForeignPlaceholder]);
21329
+ dndLog.info("dropzone:isOver:change", { droppableId, group: ownGroup, isOver, isThisZoneOver, showForeignPlaceholder, activeDragSourceGroup: activeDrag2?.sourceGroup ?? null });
21330
+ }, [droppableId, isOver, isThisZoneOver, showForeignPlaceholder]);
21326
21331
  return /* @__PURE__ */ jsxRuntime.jsxs(
21327
21332
  Box,
21328
21333
  {
21329
21334
  ref: setNodeRef,
21330
21335
  "data-dnd-zone": ownGroup,
21331
- "data-dnd-is-over": isOver ? "true" : "false",
21332
- className: isOver ? "ring-2 ring-primary ring-offset-2 rounded-lg transition-all min-h-[3rem]" : "min-h-[3rem] rounded-lg transition-all",
21336
+ "data-dnd-is-over": isThisZoneOver ? "true" : "false",
21337
+ className: isThisZoneOver ? "ring-2 ring-primary ring-offset-2 rounded-lg transition-all min-h-[3rem]" : "min-h-[3rem] rounded-lg transition-all",
21333
21338
  children: [
21334
21339
  children,
21335
21340
  showForeignPlaceholder ? /* @__PURE__ */ jsxRuntime.jsx(
@@ -21345,8 +21350,8 @@ function useDataDnd(args) {
21345
21350
  );
21346
21351
  };
21347
21352
  const rootContextValue = React80__namespace.default.useMemo(
21348
- () => ({ registerZone, unregisterZone, activeDrag }),
21349
- [registerZone, unregisterZone, activeDrag]
21353
+ () => ({ registerZone, unregisterZone, activeDrag, overZoneGroup }),
21354
+ [registerZone, unregisterZone, activeDrag, overZoneGroup]
21350
21355
  );
21351
21356
  const handleDragStart = React80__namespace.default.useCallback((event) => {
21352
21357
  const sourceZone = findZoneByItem(event.active.id);
@@ -21368,14 +21373,18 @@ function useDataDnd(args) {
21368
21373
  });
21369
21374
  }, [findZoneByItem, isRoot, zoneId]);
21370
21375
  const handleDragOver = React80__namespace.default.useCallback((event) => {
21376
+ const overData = event.over?.data?.current;
21377
+ const group = overData?.dndGroup ?? null;
21378
+ setOverZoneGroup(group);
21371
21379
  dndLog.debug("dragOver", {
21372
21380
  activeId: event.active.id,
21373
21381
  overId: event.over?.id,
21374
- overData: event.over?.data?.current
21382
+ overGroup: group
21375
21383
  });
21376
21384
  }, []);
21377
21385
  const handleDragCancel = React80__namespace.default.useCallback((event) => {
21378
21386
  setActiveDrag(null);
21387
+ setOverZoneGroup(null);
21379
21388
  dndLog.warn("dragCancel", {
21380
21389
  activeId: event.active.id,
21381
21390
  reason: "dnd-kit cancelled the drag (escape key, pointer interrupted, or external)"
@@ -21384,6 +21393,7 @@ function useDataDnd(args) {
21384
21393
  const handleDragEndWithCleanup = React80__namespace.default.useCallback((event) => {
21385
21394
  handleDragEnd(event);
21386
21395
  setActiveDrag(null);
21396
+ setOverZoneGroup(null);
21387
21397
  }, [handleDragEnd]);
21388
21398
  const wrapContainer = React80__namespace.default.useCallback(
21389
21399
  (children) => {
@@ -21083,6 +21083,7 @@ function useDataDnd(args) {
21083
21083
  zonesRef.current.delete(zoneId2);
21084
21084
  }, []);
21085
21085
  const [activeDrag, setActiveDrag] = React80__default.useState(null);
21086
+ const [overZoneGroup, setOverZoneGroup] = React80__default.useState(null);
21086
21087
  const zoneId = React80__default.useId();
21087
21088
  const ownGroup = dragGroup ?? accepts ?? zoneId;
21088
21089
  const meta = React80__default.useMemo(
@@ -21265,25 +21266,29 @@ function useDataDnd(args) {
21265
21266
  });
21266
21267
  const ctx = React80__default.useContext(RootCtx);
21267
21268
  const activeDrag2 = ctx?.activeDrag ?? null;
21268
- const showForeignPlaceholder = isOver && activeDrag2 != null && activeDrag2.sourceGroup !== ownGroup;
21269
+ const overZoneGroup2 = ctx?.overZoneGroup ?? null;
21270
+ const isThisZoneOver = overZoneGroup2 === ownGroup;
21271
+ const showForeignPlaceholder = isThisZoneOver && activeDrag2 != null && activeDrag2.sourceGroup !== ownGroup;
21269
21272
  dndLog.debug("dropzone:render", {
21270
21273
  group: ownGroup,
21271
21274
  isOver,
21275
+ isThisZoneOver,
21276
+ overZoneGroup: overZoneGroup2,
21272
21277
  activeDragSourceGroup: activeDrag2?.sourceGroup ?? null,
21273
21278
  activeDragHeight: activeDrag2?.height ?? null,
21274
21279
  showForeignPlaceholder,
21275
21280
  ctxAvailable: ctx != null
21276
21281
  });
21277
21282
  React80__default.useEffect(() => {
21278
- dndLog.info("dropzone:isOver:change", { droppableId, group: ownGroup, isOver, showForeignPlaceholder, activeDragSourceGroup: activeDrag2?.sourceGroup ?? null });
21279
- }, [droppableId, isOver, showForeignPlaceholder]);
21283
+ dndLog.info("dropzone:isOver:change", { droppableId, group: ownGroup, isOver, isThisZoneOver, showForeignPlaceholder, activeDragSourceGroup: activeDrag2?.sourceGroup ?? null });
21284
+ }, [droppableId, isOver, isThisZoneOver, showForeignPlaceholder]);
21280
21285
  return /* @__PURE__ */ jsxs(
21281
21286
  Box,
21282
21287
  {
21283
21288
  ref: setNodeRef,
21284
21289
  "data-dnd-zone": ownGroup,
21285
- "data-dnd-is-over": isOver ? "true" : "false",
21286
- className: isOver ? "ring-2 ring-primary ring-offset-2 rounded-lg transition-all min-h-[3rem]" : "min-h-[3rem] rounded-lg transition-all",
21290
+ "data-dnd-is-over": isThisZoneOver ? "true" : "false",
21291
+ className: isThisZoneOver ? "ring-2 ring-primary ring-offset-2 rounded-lg transition-all min-h-[3rem]" : "min-h-[3rem] rounded-lg transition-all",
21287
21292
  children: [
21288
21293
  children,
21289
21294
  showForeignPlaceholder ? /* @__PURE__ */ jsx(
@@ -21299,8 +21304,8 @@ function useDataDnd(args) {
21299
21304
  );
21300
21305
  };
21301
21306
  const rootContextValue = React80__default.useMemo(
21302
- () => ({ registerZone, unregisterZone, activeDrag }),
21303
- [registerZone, unregisterZone, activeDrag]
21307
+ () => ({ registerZone, unregisterZone, activeDrag, overZoneGroup }),
21308
+ [registerZone, unregisterZone, activeDrag, overZoneGroup]
21304
21309
  );
21305
21310
  const handleDragStart = React80__default.useCallback((event) => {
21306
21311
  const sourceZone = findZoneByItem(event.active.id);
@@ -21322,14 +21327,18 @@ function useDataDnd(args) {
21322
21327
  });
21323
21328
  }, [findZoneByItem, isRoot, zoneId]);
21324
21329
  const handleDragOver = React80__default.useCallback((event) => {
21330
+ const overData = event.over?.data?.current;
21331
+ const group = overData?.dndGroup ?? null;
21332
+ setOverZoneGroup(group);
21325
21333
  dndLog.debug("dragOver", {
21326
21334
  activeId: event.active.id,
21327
21335
  overId: event.over?.id,
21328
- overData: event.over?.data?.current
21336
+ overGroup: group
21329
21337
  });
21330
21338
  }, []);
21331
21339
  const handleDragCancel = React80__default.useCallback((event) => {
21332
21340
  setActiveDrag(null);
21341
+ setOverZoneGroup(null);
21333
21342
  dndLog.warn("dragCancel", {
21334
21343
  activeId: event.active.id,
21335
21344
  reason: "dnd-kit cancelled the drag (escape key, pointer interrupted, or external)"
@@ -21338,6 +21347,7 @@ function useDataDnd(args) {
21338
21347
  const handleDragEndWithCleanup = React80__default.useCallback((event) => {
21339
21348
  handleDragEnd(event);
21340
21349
  setActiveDrag(null);
21350
+ setOverZoneGroup(null);
21341
21351
  }, [handleDragEnd]);
21342
21352
  const wrapContainer = React80__default.useCallback(
21343
21353
  (children) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@almadar/ui",
3
- "version": "4.50.12",
3
+ "version": "4.50.14",
4
4
  "description": "React UI components, hooks, and providers for Almadar",
5
5
  "type": "module",
6
6
  "sideEffects": [