@almadar/ui 4.50.13 → 4.50.15

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 });
@@ -24923,11 +24923,21 @@ function useDataDnd(args) {
24923
24923
  const eventBus = useEventBus();
24924
24924
  const parentRoot = React93__namespace.default.useContext(RootCtx);
24925
24925
  const isRoot = enabled && parentRoot === null;
24926
- const [localOrder, setLocalOrder] = React93__namespace.default.useState(null);
24927
- const orderedItems = localOrder ?? items;
24928
- React93__namespace.default.useEffect(() => {
24929
- setLocalOrder(null);
24930
- }, [items]);
24926
+ const zoneId = React93__namespace.default.useId();
24927
+ const ownGroup = dragGroup ?? accepts ?? zoneId;
24928
+ const [optimisticOrders, setOptimisticOrders] = React93__namespace.default.useState(() => /* @__PURE__ */ new Map());
24929
+ const optimisticOrdersRef = React93__namespace.default.useRef(optimisticOrders);
24930
+ optimisticOrdersRef.current = optimisticOrders;
24931
+ const clearOptimisticOrder = React93__namespace.default.useCallback((group) => {
24932
+ setOptimisticOrders((prev) => {
24933
+ if (!prev.has(group)) return prev;
24934
+ const next = new Map(prev);
24935
+ next.delete(group);
24936
+ return next;
24937
+ });
24938
+ }, []);
24939
+ const sharedOptimistic = isRoot ? optimisticOrders : parentRoot?.optimisticOrders ?? /* @__PURE__ */ new Map();
24940
+ const orderedItems = sharedOptimistic.get(ownGroup) ?? items;
24931
24941
  const itemIdsSignature = orderedItems.map((it, idx) => {
24932
24942
  const raw = it[dndItemIdField];
24933
24943
  return String(raw ?? `__idx_${idx}`);
@@ -24940,6 +24950,15 @@ function useDataDnd(args) {
24940
24950
  // eslint-disable-next-line react-hooks/exhaustive-deps
24941
24951
  [itemIdsSignature]
24942
24952
  );
24953
+ const itemsContentSig = items.map((it, idx) => String(it[dndItemIdField] ?? `__${idx}`)).join("|");
24954
+ React93__namespace.default.useEffect(() => {
24955
+ const root = isRoot ? null : parentRoot;
24956
+ if (root) {
24957
+ root.clearOptimisticOrder(ownGroup);
24958
+ } else {
24959
+ clearOptimisticOrder(ownGroup);
24960
+ }
24961
+ }, [itemsContentSig, ownGroup]);
24943
24962
  const zonesRef = React93__namespace.default.useRef(/* @__PURE__ */ new Map());
24944
24963
  const registerZone = React93__namespace.default.useCallback((zoneId2, meta2) => {
24945
24964
  zonesRef.current.set(zoneId2, meta2);
@@ -24949,11 +24968,9 @@ function useDataDnd(args) {
24949
24968
  }, []);
24950
24969
  const [activeDrag, setActiveDrag] = React93__namespace.default.useState(null);
24951
24970
  const [overZoneGroup, setOverZoneGroup] = React93__namespace.default.useState(null);
24952
- const zoneId = React93__namespace.default.useId();
24953
- const ownGroup = dragGroup ?? accepts ?? zoneId;
24954
24971
  const meta = React93__namespace.default.useMemo(
24955
- () => ({ group: ownGroup, dropEvent, reorderEvent, itemIds }),
24956
- [ownGroup, dropEvent, reorderEvent, itemIds]
24972
+ () => ({ group: ownGroup, dropEvent, reorderEvent, itemIds, rawItems: items, idField: dndItemIdField }),
24973
+ [ownGroup, dropEvent, reorderEvent, itemIds, items, dndItemIdField]
24957
24974
  );
24958
24975
  React93__namespace.default.useEffect(() => {
24959
24976
  const target = isRoot ? null : parentRoot;
@@ -25000,7 +25017,7 @@ function useDataDnd(args) {
25000
25017
  },
25001
25018
  []
25002
25019
  );
25003
- const findZoneByGroup = React93__namespace.default.useCallback(
25020
+ React93__namespace.default.useCallback(
25004
25021
  (group) => {
25005
25022
  for (const z of zonesRef.current.values()) {
25006
25023
  if (z.group === group) return z;
@@ -25012,81 +25029,76 @@ function useDataDnd(args) {
25012
25029
  const handleDragEnd = React93__namespace.default.useCallback(
25013
25030
  (event) => {
25014
25031
  const { active, over } = event;
25015
- const allZones = Array.from(zonesRef.current.entries()).map(([id, m]) => ({ id, group: m.group, items: m.itemIds.length }));
25032
+ const activeIdStr = String(active.id);
25016
25033
  dndLog.debug("dragEnd:received", {
25017
25034
  activeId: active.id,
25018
25035
  overId: over?.id,
25019
- overData: over?.data?.current,
25020
- zones: allZones
25036
+ overData: over?.data?.current
25021
25037
  });
25022
- if (!over) {
25023
- dndLog.warn("dragEnd:abort:no-over", { activeId: active.id, reason: "no droppable under pointer at drop time \u2192 item snaps back" });
25024
- return;
25025
- }
25026
- const sourceZone = findZoneByItem(active.id);
25027
- const overData = over.data?.current;
25028
- const targetGroup = overData?.dndGroup;
25029
- dndLog.debug("dragEnd:resolved", { sourceGroup: sourceZone?.group, targetGroup, overDataKeys: overData ? Object.keys(overData) : null });
25030
- if (!sourceZone) {
25031
- dndLog.warn("dragEnd:abort:no-source-zone", { activeId: active.id });
25032
- return;
25033
- }
25034
- if (!targetGroup) {
25035
- dndLog.warn("dragEnd:abort:no-target-group", { overId: over.id, overData });
25036
- return;
25037
- }
25038
- const targetZone = findZoneByGroup(targetGroup);
25039
- if (!targetZone) {
25040
- dndLog.warn("dragEnd:abort:target-zone-not-registered", { targetGroup });
25038
+ let sourceMeta;
25039
+ let oldIndex = -1;
25040
+ let targetMeta;
25041
+ let newIndex = -1;
25042
+ for (const m of zonesRef.current.values()) {
25043
+ const rawIdx = m.rawItems.findIndex((it) => String(it[m.idField]) === activeIdStr);
25044
+ if (rawIdx >= 0) {
25045
+ sourceMeta = m;
25046
+ oldIndex = rawIdx;
25047
+ }
25048
+ const currentItems = optimisticOrdersRef.current.get(m.group) ?? m.rawItems;
25049
+ const curIdx = currentItems.findIndex((it) => String(it[m.idField]) === activeIdStr);
25050
+ if (curIdx >= 0) {
25051
+ targetMeta = m;
25052
+ newIndex = curIdx;
25053
+ }
25054
+ }
25055
+ if (!sourceMeta || !targetMeta) {
25056
+ dndLog.warn("dragEnd:abort:no-zone-resolved", { activeId: active.id, hasSource: !!sourceMeta, hasTarget: !!targetMeta });
25041
25057
  return;
25042
25058
  }
25043
- if (sourceZone.group !== targetZone.group) {
25044
- if (targetZone.dropEvent) {
25045
- const newIndex2 = targetZone.itemIds.indexOf(over.id);
25046
- const evt = `UI:${targetZone.dropEvent}`;
25059
+ if (sourceMeta.group !== targetMeta.group) {
25060
+ if (targetMeta.dropEvent) {
25061
+ const evt = `UI:${targetMeta.dropEvent}`;
25047
25062
  dndLog.info("dragEnd:cross-container:emit", {
25048
25063
  event: evt,
25049
- id: String(active.id),
25050
- sourceGroup: sourceZone.group,
25051
- targetGroup: targetZone.group,
25052
- newIndex: newIndex2 === -1 ? targetZone.itemIds.length : newIndex2
25064
+ id: activeIdStr,
25065
+ sourceGroup: sourceMeta.group,
25066
+ targetGroup: targetMeta.group,
25067
+ newIndex
25053
25068
  });
25054
25069
  eventBus.emit(evt, {
25055
- id: String(active.id),
25056
- sourceGroup: sourceZone.group,
25057
- targetGroup: targetZone.group,
25058
- newIndex: newIndex2 === -1 ? targetZone.itemIds.length : newIndex2
25070
+ id: activeIdStr,
25071
+ sourceGroup: sourceMeta.group,
25072
+ targetGroup: targetMeta.group,
25073
+ newIndex
25059
25074
  });
25060
25075
  } else {
25061
- dndLog.warn("dragEnd:cross-container:no-dropEvent-on-target", { targetGroup: targetZone.group });
25076
+ dndLog.warn("dragEnd:cross-container:no-dropEvent-on-target", { targetGroup: targetMeta.group });
25062
25077
  }
25063
25078
  return;
25064
25079
  }
25065
- const oldIndex = sourceZone.itemIds.indexOf(active.id);
25066
- const newIndex = sourceZone.itemIds.indexOf(over.id);
25067
- if (oldIndex === -1 || newIndex === -1 || oldIndex === newIndex) return;
25068
- if (sourceZone.group === ownGroup) {
25069
- const reordered = sortable.arrayMove(orderedItems, oldIndex, newIndex);
25070
- setLocalOrder(reordered);
25080
+ if (oldIndex === newIndex) {
25081
+ dndLog.debug("dragEnd:reorder:no-op", { sourceGroup: sourceMeta.group, oldIndex });
25082
+ return;
25071
25083
  }
25072
- if (sourceZone.reorderEvent) {
25073
- const evt = `UI:${sourceZone.reorderEvent}`;
25084
+ if (sourceMeta.reorderEvent) {
25085
+ const evt = `UI:${sourceMeta.reorderEvent}`;
25074
25086
  dndLog.info("dragEnd:reorder:emit", {
25075
25087
  event: evt,
25076
- id: String(active.id),
25088
+ id: activeIdStr,
25077
25089
  oldIndex,
25078
25090
  newIndex
25079
25091
  });
25080
25092
  eventBus.emit(evt, {
25081
- id: String(active.id),
25093
+ id: activeIdStr,
25082
25094
  oldIndex,
25083
25095
  newIndex
25084
25096
  });
25085
25097
  } else {
25086
- dndLog.debug("dragEnd:reorder:no-reorderEvent", { sourceGroup: sourceZone.group });
25098
+ dndLog.debug("dragEnd:reorder:no-reorderEvent", { sourceGroup: sourceMeta.group });
25087
25099
  }
25088
25100
  },
25089
- [orderedItems, ownGroup, findZoneByItem, findZoneByGroup, eventBus]
25101
+ [eventBus]
25090
25102
  );
25091
25103
  const sortableData = React93__namespace.default.useMemo(() => ({ dndGroup: ownGroup }), [ownGroup]);
25092
25104
  const SortableItem = React93__namespace.default.useCallback(
@@ -25147,30 +25159,20 @@ function useDataDnd(args) {
25147
25159
  React93__namespace.default.useEffect(() => {
25148
25160
  dndLog.info("dropzone:isOver:change", { droppableId, group: ownGroup, isOver, isThisZoneOver, showForeignPlaceholder, activeDragSourceGroup: activeDrag2?.sourceGroup ?? null });
25149
25161
  }, [droppableId, isOver, isThisZoneOver, showForeignPlaceholder]);
25150
- return /* @__PURE__ */ jsxRuntime.jsxs(
25162
+ return /* @__PURE__ */ jsxRuntime.jsx(
25151
25163
  Box,
25152
25164
  {
25153
25165
  ref: setNodeRef,
25154
25166
  "data-dnd-zone": ownGroup,
25155
25167
  "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",
25157
- children: [
25158
- children,
25159
- showForeignPlaceholder ? /* @__PURE__ */ jsxRuntime.jsx(
25160
- Box,
25161
- {
25162
- "data-dnd-placeholder": true,
25163
- style: { height: activeDrag2.height },
25164
- className: "border-2 border-dashed border-primary/60 bg-primary/5 rounded-md my-1 transition-all"
25165
- }
25166
- ) : null
25167
- ]
25168
+ className: isThisZoneOver ? "ring-2 ring-primary/40 ring-offset-2 rounded-lg transition-all min-h-[3rem]" : "min-h-[3rem] rounded-lg transition-all",
25169
+ children
25168
25170
  }
25169
25171
  );
25170
25172
  };
25171
25173
  const rootContextValue = React93__namespace.default.useMemo(
25172
- () => ({ registerZone, unregisterZone, activeDrag, overZoneGroup }),
25173
- [registerZone, unregisterZone, activeDrag, overZoneGroup]
25174
+ () => ({ registerZone, unregisterZone, activeDrag, overZoneGroup, optimisticOrders, clearOptimisticOrder }),
25175
+ [registerZone, unregisterZone, activeDrag, overZoneGroup, optimisticOrders, clearOptimisticOrder]
25174
25176
  );
25175
25177
  const handleDragStart = React93__namespace.default.useCallback((event) => {
25176
25178
  const sourceZone = findZoneByItem(event.active.id);
@@ -25192,13 +25194,73 @@ function useDataDnd(args) {
25192
25194
  });
25193
25195
  }, [findZoneByItem, isRoot, zoneId]);
25194
25196
  const handleDragOver = React93__namespace.default.useCallback((event) => {
25195
- const overData = event.over?.data?.current;
25196
- const group = overData?.dndGroup ?? null;
25197
- setOverZoneGroup(group);
25198
- dndLog.debug("dragOver", {
25199
- activeId: event.active.id,
25200
- overId: event.over?.id,
25201
- overGroup: group
25197
+ const { active, over } = event;
25198
+ const overData = over?.data?.current;
25199
+ const overGroup = overData?.dndGroup ?? null;
25200
+ setOverZoneGroup(overGroup);
25201
+ if (!over || !overGroup) return;
25202
+ const activeIdStr = String(active.id);
25203
+ let sourceMeta;
25204
+ let sourceGroup;
25205
+ for (const m of zonesRef.current.values()) {
25206
+ const currentItems = optimisticOrdersRef.current.get(m.group) ?? m.rawItems;
25207
+ const found = currentItems.find((it) => String(it[m.idField]) === activeIdStr);
25208
+ if (found) {
25209
+ sourceMeta = m;
25210
+ sourceGroup = m.group;
25211
+ break;
25212
+ }
25213
+ }
25214
+ if (!sourceMeta || !sourceGroup) {
25215
+ dndLog.debug("dragOver:no-source-zone", { activeId: active.id });
25216
+ return;
25217
+ }
25218
+ let targetMeta;
25219
+ for (const m of zonesRef.current.values()) {
25220
+ if (m.group === overGroup) {
25221
+ targetMeta = m;
25222
+ break;
25223
+ }
25224
+ }
25225
+ if (!targetMeta) {
25226
+ dndLog.debug("dragOver:no-target-zone", { overGroup });
25227
+ return;
25228
+ }
25229
+ if (sourceGroup === overGroup) {
25230
+ setOptimisticOrders((prev) => {
25231
+ const currentItems = prev.get(sourceGroup) ?? sourceMeta.rawItems;
25232
+ const oldIndex = currentItems.findIndex((it) => String(it[sourceMeta.idField]) === activeIdStr);
25233
+ const newIndex = currentItems.findIndex((it) => String(it[sourceMeta.idField]) === String(over.id));
25234
+ if (oldIndex === -1 || newIndex === -1 || oldIndex === newIndex) return prev;
25235
+ const reordered = sortable.arrayMove([...currentItems], oldIndex, newIndex);
25236
+ const next = new Map(prev);
25237
+ next.set(sourceGroup, reordered);
25238
+ return next;
25239
+ });
25240
+ return;
25241
+ }
25242
+ setOptimisticOrders((prev) => {
25243
+ const currentSource = prev.get(sourceGroup) ?? sourceMeta.rawItems;
25244
+ const currentTarget = prev.get(overGroup) ?? targetMeta.rawItems;
25245
+ const activeItem = currentSource.find((it) => String(it[sourceMeta.idField]) === activeIdStr);
25246
+ if (!activeItem) return prev;
25247
+ if (currentTarget.some((it) => String(it[targetMeta.idField]) === activeIdStr)) {
25248
+ return prev;
25249
+ }
25250
+ const newSource = currentSource.filter((it) => String(it[sourceMeta.idField]) !== activeIdStr);
25251
+ const overIdStr = String(over.id);
25252
+ const overIndex = currentTarget.findIndex((it) => String(it[targetMeta.idField]) === overIdStr);
25253
+ const insertAt = overIndex >= 0 ? overIndex : currentTarget.length;
25254
+ const newTarget = [
25255
+ ...currentTarget.slice(0, insertAt),
25256
+ activeItem,
25257
+ ...currentTarget.slice(insertAt)
25258
+ ];
25259
+ const next = new Map(prev);
25260
+ next.set(sourceGroup, newSource);
25261
+ next.set(overGroup, newTarget);
25262
+ dndLog.debug("dragOver:cross-zone:splice", { sourceGroup, overGroup, sourceLen: newSource.length, targetLen: newTarget.length, insertAt });
25263
+ return next;
25202
25264
  });
25203
25265
  }, []);
25204
25266
  const handleDragCancel = React93__namespace.default.useCallback((event) => {
@@ -57373,6 +57435,66 @@ function convertFnFormLambdasInProps(props) {
57373
57435
  // hooks/index.ts
57374
57436
  init_useEventBus();
57375
57437
  var ALMADAR_DND_MIME = "application/x-almadar-dnd";
57438
+
57439
+ // hooks/useDropZone.ts
57440
+ init_useEventBus();
57441
+ function parsePayload(e) {
57442
+ try {
57443
+ const raw = e.dataTransfer.getData(ALMADAR_DND_MIME);
57444
+ if (!raw) return null;
57445
+ const parsed = JSON.parse(raw);
57446
+ if (typeof parsed.kind !== "string" || !parsed.data) return null;
57447
+ return parsed;
57448
+ } catch {
57449
+ return null;
57450
+ }
57451
+ }
57452
+ function hasAlmadarPayload(e) {
57453
+ return e.dataTransfer.types.includes(ALMADAR_DND_MIME);
57454
+ }
57455
+ function useDropZone({ accepts, onDrop, disabled = false }) {
57456
+ const [isOver, setIsOver] = React93.useState(false);
57457
+ const eventBus = useEventBus();
57458
+ const handleDragOver = React93.useCallback(
57459
+ (e) => {
57460
+ if (disabled) return;
57461
+ if (!hasAlmadarPayload(e)) return;
57462
+ e.preventDefault();
57463
+ e.dataTransfer.dropEffect = "copy";
57464
+ setIsOver(true);
57465
+ },
57466
+ [disabled]
57467
+ );
57468
+ const handleDragLeave = React93.useCallback(
57469
+ (e) => {
57470
+ setIsOver(false);
57471
+ },
57472
+ []
57473
+ );
57474
+ const handleDrop = React93.useCallback(
57475
+ (e) => {
57476
+ e.preventDefault();
57477
+ setIsOver(false);
57478
+ if (disabled) return;
57479
+ const payload = parsePayload(e);
57480
+ if (!payload) return;
57481
+ if (!accepts.includes(payload.kind)) return;
57482
+ const position = { x: e.clientX, y: e.clientY };
57483
+ onDrop(payload, position);
57484
+ eventBus.emit("UI:DROP", { kind: payload.kind, data: payload.data, ...position });
57485
+ },
57486
+ [disabled, accepts, onDrop, eventBus]
57487
+ );
57488
+ const dropProps = React93.useMemo(
57489
+ () => ({
57490
+ onDragOver: handleDragOver,
57491
+ onDragLeave: handleDragLeave,
57492
+ onDrop: handleDrop
57493
+ }),
57494
+ [handleDragOver, handleDragLeave, handleDrop]
57495
+ );
57496
+ return { dropProps, isOver };
57497
+ }
57376
57498
  var log16 = logger.createLogger("almadar:ui:effects:client-handlers");
57377
57499
  function createClientEffectHandlers(options) {
57378
57500
  const { eventBus, slotSetter, navigate, notify, callService } = options;
@@ -59331,19 +59453,98 @@ var OrbPreviewNodeInner = (props) => {
59331
59453
  const statusBorder = isRunning ? "var(--color-primary)" : isError ? "var(--color-danger)" : isSuccess ? "var(--color-success)" : null;
59332
59454
  const borderWidth = isRunning || isError || isSuccess ? "2px" : "1.5px";
59333
59455
  const borderColor = statusBorder ?? (hovered ? "var(--color-primary)" : colors.border);
59456
+ const handleL1Drop = React93.useCallback(
59457
+ (payload) => {
59458
+ if (payload.kind !== "pattern") return;
59459
+ if (typeof payload.data.type !== "string") return;
59460
+ eventBus.emit("UI:PATTERN_DROP", {
59461
+ patternType: payload.data.type,
59462
+ containerNode: { orbitalName: data.orbitalName }
59463
+ });
59464
+ },
59465
+ [eventBus, data.orbitalName]
59466
+ );
59467
+ const { dropProps: l1DropProps, isOver: l1IsOver } = useDropZone({
59468
+ accepts: ["pattern"],
59469
+ onDrop: handleL1Drop,
59470
+ disabled: isExpanded
59471
+ });
59334
59472
  return /* @__PURE__ */ jsxRuntime.jsxs(
59335
59473
  Box,
59336
59474
  {
59475
+ ...isExpanded ? {} : l1DropProps,
59337
59476
  className: `rounded-lg border shadow-sm bg-card transition-all duration-200 overflow-hidden relative${isRunning ? " orb-preview-running" : ""}`,
59338
59477
  style: {
59339
- borderColor,
59340
- borderWidth,
59341
- width: preset.width
59478
+ borderColor: l1IsOver ? "var(--color-primary)" : borderColor,
59479
+ borderWidth: l1IsOver ? "2px" : borderWidth,
59480
+ width: preset.width,
59481
+ boxShadow: l1IsOver ? "0 0 0 3px var(--color-primary), 0 0 12px var(--color-primary)" : void 0
59342
59482
  },
59343
59483
  onMouseEnter: handleMouseEnter,
59344
59484
  onMouseLeave: handleMouseLeave,
59345
59485
  children: [
59346
59486
  /* @__PURE__ */ jsxRuntime.jsx("style", { children: SELECTION_STYLES }),
59487
+ !isExpanded && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
59488
+ /* @__PURE__ */ jsxRuntime.jsx(
59489
+ Box,
59490
+ {
59491
+ className: "absolute top-1.5 left-1.5 rounded px-1 py-[1px] text-[8px] font-mono uppercase tracking-wider pointer-events-none",
59492
+ style: {
59493
+ backgroundColor: "var(--color-muted)",
59494
+ color: "var(--color-muted-foreground)",
59495
+ zIndex: 3
59496
+ },
59497
+ children: "Preview"
59498
+ }
59499
+ ),
59500
+ hovered && !dragActive && !l1IsOver && /* @__PURE__ */ jsxRuntime.jsx(
59501
+ Box,
59502
+ {
59503
+ className: "absolute inset-0 flex items-center justify-center pointer-events-none",
59504
+ style: {
59505
+ backgroundColor: "rgba(0,0,0,0.04)",
59506
+ zIndex: 2
59507
+ },
59508
+ children: /* @__PURE__ */ jsxRuntime.jsxs(
59509
+ Box,
59510
+ {
59511
+ className: "rounded-md px-2 py-1 text-[11px] font-medium flex items-center gap-1",
59512
+ style: {
59513
+ backgroundColor: "var(--color-card)",
59514
+ color: "var(--color-foreground)",
59515
+ boxShadow: "var(--shadow-main)"
59516
+ },
59517
+ children: [
59518
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: 12 }, children: "\u279E" }),
59519
+ "Click to open"
59520
+ ]
59521
+ }
59522
+ )
59523
+ }
59524
+ ),
59525
+ (dragActive || l1IsOver) && /* @__PURE__ */ jsxRuntime.jsx(
59526
+ Box,
59527
+ {
59528
+ className: "absolute inset-0 flex items-center justify-center pointer-events-none",
59529
+ style: {
59530
+ backgroundColor: l1IsOver ? "rgba(20,184,166,0.15)" : "rgba(20,184,166,0.06)",
59531
+ zIndex: 2
59532
+ },
59533
+ children: /* @__PURE__ */ jsxRuntime.jsx(
59534
+ Box,
59535
+ {
59536
+ className: "rounded-md px-2 py-1 text-[11px] font-semibold",
59537
+ style: {
59538
+ backgroundColor: "var(--color-primary)",
59539
+ color: "var(--color-primary-foreground)",
59540
+ boxShadow: "var(--shadow-lg)"
59541
+ },
59542
+ children: "Drop to add and open"
59543
+ }
59544
+ )
59545
+ }
59546
+ )
59547
+ ] }),
59347
59548
  isRunning && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
59348
59549
  /* @__PURE__ */ jsxRuntime.jsx("style", { children: `
59349
59550
  @keyframes orb-preview-running-pulse {
@@ -60525,13 +60726,14 @@ function FlowCanvasInner({
60525
60726
  transition: nodeData.transitionEvent
60526
60727
  });
60527
60728
  } else {
60528
- onNodeClick?.({
60529
- level: "overview",
60530
- orbital: nodeData.orbitalName ?? node.id
60531
- });
60532
- onNodeSelect?.(nodeData.orbitalName ?? node.id);
60729
+ const orbitalName = nodeData.orbitalName ?? node.id;
60730
+ onNodeClick?.({ level: "overview", orbital: orbitalName });
60731
+ onNodeSelect?.(orbitalName);
60732
+ setExpandedOrbital(orbitalName);
60733
+ setLevel("expanded");
60734
+ onLevelChange?.("expanded", orbitalName);
60533
60735
  }
60534
- }, [level, expandedOrbital, onNodeClick]);
60736
+ }, [level, expandedOrbital, onNodeClick, onNodeSelect, onLevelChange]);
60535
60737
  const handleClosePanel = React93.useCallback(() => {
60536
60738
  setSelectedNode(null);
60537
60739
  }, []);