@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.
package/dist/avl/index.js CHANGED
@@ -35,7 +35,7 @@ import langGo from 'react-syntax-highlighter/dist/esm/languages/prism/go.js';
35
35
  import langGraphql from 'react-syntax-highlighter/dist/esm/languages/prism/graphql.js';
36
36
  import { FieldTypeSchema, isInlineTrait, isEntityCall, schemaToIR, getPage, isCircuitEvent } from '@almadar/core';
37
37
  import { useSensors, useSensor, PointerSensor, KeyboardSensor, pointerWithin, rectIntersection, closestCorners, DndContext, useDroppable } from '@dnd-kit/core';
38
- import { sortableKeyboardCoordinates, arrayMove, useSortable, SortableContext, rectSortingStrategy, verticalListSortingStrategy } from '@dnd-kit/sortable';
38
+ import { sortableKeyboardCoordinates, useSortable, arrayMove, SortableContext, rectSortingStrategy, verticalListSortingStrategy } from '@dnd-kit/sortable';
39
39
  import { CSS } from '@dnd-kit/utilities';
40
40
  import { useThree, useFrame, Canvas } from '@react-three/fiber';
41
41
  import * as THREE6 from 'three';
@@ -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 });
@@ -24877,11 +24877,21 @@ function useDataDnd(args) {
24877
24877
  const eventBus = useEventBus();
24878
24878
  const parentRoot = React93__default.useContext(RootCtx);
24879
24879
  const isRoot = enabled && parentRoot === null;
24880
- const [localOrder, setLocalOrder] = React93__default.useState(null);
24881
- const orderedItems = localOrder ?? items;
24882
- React93__default.useEffect(() => {
24883
- setLocalOrder(null);
24884
- }, [items]);
24880
+ const zoneId = React93__default.useId();
24881
+ const ownGroup = dragGroup ?? accepts ?? zoneId;
24882
+ const [optimisticOrders, setOptimisticOrders] = React93__default.useState(() => /* @__PURE__ */ new Map());
24883
+ const optimisticOrdersRef = React93__default.useRef(optimisticOrders);
24884
+ optimisticOrdersRef.current = optimisticOrders;
24885
+ const clearOptimisticOrder = React93__default.useCallback((group) => {
24886
+ setOptimisticOrders((prev) => {
24887
+ if (!prev.has(group)) return prev;
24888
+ const next = new Map(prev);
24889
+ next.delete(group);
24890
+ return next;
24891
+ });
24892
+ }, []);
24893
+ const sharedOptimistic = isRoot ? optimisticOrders : parentRoot?.optimisticOrders ?? /* @__PURE__ */ new Map();
24894
+ const orderedItems = sharedOptimistic.get(ownGroup) ?? items;
24885
24895
  const itemIdsSignature = orderedItems.map((it, idx) => {
24886
24896
  const raw = it[dndItemIdField];
24887
24897
  return String(raw ?? `__idx_${idx}`);
@@ -24894,6 +24904,15 @@ function useDataDnd(args) {
24894
24904
  // eslint-disable-next-line react-hooks/exhaustive-deps
24895
24905
  [itemIdsSignature]
24896
24906
  );
24907
+ const itemsContentSig = items.map((it, idx) => String(it[dndItemIdField] ?? `__${idx}`)).join("|");
24908
+ React93__default.useEffect(() => {
24909
+ const root = isRoot ? null : parentRoot;
24910
+ if (root) {
24911
+ root.clearOptimisticOrder(ownGroup);
24912
+ } else {
24913
+ clearOptimisticOrder(ownGroup);
24914
+ }
24915
+ }, [itemsContentSig, ownGroup]);
24897
24916
  const zonesRef = React93__default.useRef(/* @__PURE__ */ new Map());
24898
24917
  const registerZone = React93__default.useCallback((zoneId2, meta2) => {
24899
24918
  zonesRef.current.set(zoneId2, meta2);
@@ -24903,11 +24922,9 @@ function useDataDnd(args) {
24903
24922
  }, []);
24904
24923
  const [activeDrag, setActiveDrag] = React93__default.useState(null);
24905
24924
  const [overZoneGroup, setOverZoneGroup] = React93__default.useState(null);
24906
- const zoneId = React93__default.useId();
24907
- const ownGroup = dragGroup ?? accepts ?? zoneId;
24908
24925
  const meta = React93__default.useMemo(
24909
- () => ({ group: ownGroup, dropEvent, reorderEvent, itemIds }),
24910
- [ownGroup, dropEvent, reorderEvent, itemIds]
24926
+ () => ({ group: ownGroup, dropEvent, reorderEvent, itemIds, rawItems: items, idField: dndItemIdField }),
24927
+ [ownGroup, dropEvent, reorderEvent, itemIds, items, dndItemIdField]
24911
24928
  );
24912
24929
  React93__default.useEffect(() => {
24913
24930
  const target = isRoot ? null : parentRoot;
@@ -24954,7 +24971,7 @@ function useDataDnd(args) {
24954
24971
  },
24955
24972
  []
24956
24973
  );
24957
- const findZoneByGroup = React93__default.useCallback(
24974
+ React93__default.useCallback(
24958
24975
  (group) => {
24959
24976
  for (const z of zonesRef.current.values()) {
24960
24977
  if (z.group === group) return z;
@@ -24966,81 +24983,76 @@ function useDataDnd(args) {
24966
24983
  const handleDragEnd = React93__default.useCallback(
24967
24984
  (event) => {
24968
24985
  const { active, over } = event;
24969
- const allZones = Array.from(zonesRef.current.entries()).map(([id, m]) => ({ id, group: m.group, items: m.itemIds.length }));
24986
+ const activeIdStr = String(active.id);
24970
24987
  dndLog.debug("dragEnd:received", {
24971
24988
  activeId: active.id,
24972
24989
  overId: over?.id,
24973
- overData: over?.data?.current,
24974
- zones: allZones
24990
+ overData: over?.data?.current
24975
24991
  });
24976
- if (!over) {
24977
- dndLog.warn("dragEnd:abort:no-over", { activeId: active.id, reason: "no droppable under pointer at drop time \u2192 item snaps back" });
24978
- return;
24979
- }
24980
- const sourceZone = findZoneByItem(active.id);
24981
- const overData = over.data?.current;
24982
- const targetGroup = overData?.dndGroup;
24983
- dndLog.debug("dragEnd:resolved", { sourceGroup: sourceZone?.group, targetGroup, overDataKeys: overData ? Object.keys(overData) : null });
24984
- if (!sourceZone) {
24985
- dndLog.warn("dragEnd:abort:no-source-zone", { activeId: active.id });
24986
- return;
24987
- }
24988
- if (!targetGroup) {
24989
- dndLog.warn("dragEnd:abort:no-target-group", { overId: over.id, overData });
24990
- return;
24991
- }
24992
- const targetZone = findZoneByGroup(targetGroup);
24993
- if (!targetZone) {
24994
- dndLog.warn("dragEnd:abort:target-zone-not-registered", { targetGroup });
24992
+ let sourceMeta;
24993
+ let oldIndex = -1;
24994
+ let targetMeta;
24995
+ let newIndex = -1;
24996
+ for (const m of zonesRef.current.values()) {
24997
+ const rawIdx = m.rawItems.findIndex((it) => String(it[m.idField]) === activeIdStr);
24998
+ if (rawIdx >= 0) {
24999
+ sourceMeta = m;
25000
+ oldIndex = rawIdx;
25001
+ }
25002
+ const currentItems = optimisticOrdersRef.current.get(m.group) ?? m.rawItems;
25003
+ const curIdx = currentItems.findIndex((it) => String(it[m.idField]) === activeIdStr);
25004
+ if (curIdx >= 0) {
25005
+ targetMeta = m;
25006
+ newIndex = curIdx;
25007
+ }
25008
+ }
25009
+ if (!sourceMeta || !targetMeta) {
25010
+ dndLog.warn("dragEnd:abort:no-zone-resolved", { activeId: active.id, hasSource: !!sourceMeta, hasTarget: !!targetMeta });
24995
25011
  return;
24996
25012
  }
24997
- if (sourceZone.group !== targetZone.group) {
24998
- if (targetZone.dropEvent) {
24999
- const newIndex2 = targetZone.itemIds.indexOf(over.id);
25000
- const evt = `UI:${targetZone.dropEvent}`;
25013
+ if (sourceMeta.group !== targetMeta.group) {
25014
+ if (targetMeta.dropEvent) {
25015
+ const evt = `UI:${targetMeta.dropEvent}`;
25001
25016
  dndLog.info("dragEnd:cross-container:emit", {
25002
25017
  event: evt,
25003
- id: String(active.id),
25004
- sourceGroup: sourceZone.group,
25005
- targetGroup: targetZone.group,
25006
- newIndex: newIndex2 === -1 ? targetZone.itemIds.length : newIndex2
25018
+ id: activeIdStr,
25019
+ sourceGroup: sourceMeta.group,
25020
+ targetGroup: targetMeta.group,
25021
+ newIndex
25007
25022
  });
25008
25023
  eventBus.emit(evt, {
25009
- id: String(active.id),
25010
- sourceGroup: sourceZone.group,
25011
- targetGroup: targetZone.group,
25012
- newIndex: newIndex2 === -1 ? targetZone.itemIds.length : newIndex2
25024
+ id: activeIdStr,
25025
+ sourceGroup: sourceMeta.group,
25026
+ targetGroup: targetMeta.group,
25027
+ newIndex
25013
25028
  });
25014
25029
  } else {
25015
- dndLog.warn("dragEnd:cross-container:no-dropEvent-on-target", { targetGroup: targetZone.group });
25030
+ dndLog.warn("dragEnd:cross-container:no-dropEvent-on-target", { targetGroup: targetMeta.group });
25016
25031
  }
25017
25032
  return;
25018
25033
  }
25019
- const oldIndex = sourceZone.itemIds.indexOf(active.id);
25020
- const newIndex = sourceZone.itemIds.indexOf(over.id);
25021
- if (oldIndex === -1 || newIndex === -1 || oldIndex === newIndex) return;
25022
- if (sourceZone.group === ownGroup) {
25023
- const reordered = arrayMove(orderedItems, oldIndex, newIndex);
25024
- setLocalOrder(reordered);
25034
+ if (oldIndex === newIndex) {
25035
+ dndLog.debug("dragEnd:reorder:no-op", { sourceGroup: sourceMeta.group, oldIndex });
25036
+ return;
25025
25037
  }
25026
- if (sourceZone.reorderEvent) {
25027
- const evt = `UI:${sourceZone.reorderEvent}`;
25038
+ if (sourceMeta.reorderEvent) {
25039
+ const evt = `UI:${sourceMeta.reorderEvent}`;
25028
25040
  dndLog.info("dragEnd:reorder:emit", {
25029
25041
  event: evt,
25030
- id: String(active.id),
25042
+ id: activeIdStr,
25031
25043
  oldIndex,
25032
25044
  newIndex
25033
25045
  });
25034
25046
  eventBus.emit(evt, {
25035
- id: String(active.id),
25047
+ id: activeIdStr,
25036
25048
  oldIndex,
25037
25049
  newIndex
25038
25050
  });
25039
25051
  } else {
25040
- dndLog.debug("dragEnd:reorder:no-reorderEvent", { sourceGroup: sourceZone.group });
25052
+ dndLog.debug("dragEnd:reorder:no-reorderEvent", { sourceGroup: sourceMeta.group });
25041
25053
  }
25042
25054
  },
25043
- [orderedItems, ownGroup, findZoneByItem, findZoneByGroup, eventBus]
25055
+ [eventBus]
25044
25056
  );
25045
25057
  const sortableData = React93__default.useMemo(() => ({ dndGroup: ownGroup }), [ownGroup]);
25046
25058
  const SortableItem = React93__default.useCallback(
@@ -25101,30 +25113,20 @@ function useDataDnd(args) {
25101
25113
  React93__default.useEffect(() => {
25102
25114
  dndLog.info("dropzone:isOver:change", { droppableId, group: ownGroup, isOver, isThisZoneOver, showForeignPlaceholder, activeDragSourceGroup: activeDrag2?.sourceGroup ?? null });
25103
25115
  }, [droppableId, isOver, isThisZoneOver, showForeignPlaceholder]);
25104
- return /* @__PURE__ */ jsxs(
25116
+ return /* @__PURE__ */ jsx(
25105
25117
  Box,
25106
25118
  {
25107
25119
  ref: setNodeRef,
25108
25120
  "data-dnd-zone": ownGroup,
25109
25121
  "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",
25111
- children: [
25112
- children,
25113
- showForeignPlaceholder ? /* @__PURE__ */ jsx(
25114
- Box,
25115
- {
25116
- "data-dnd-placeholder": true,
25117
- style: { height: activeDrag2.height },
25118
- className: "border-2 border-dashed border-primary/60 bg-primary/5 rounded-md my-1 transition-all"
25119
- }
25120
- ) : null
25121
- ]
25122
+ className: isThisZoneOver ? "ring-2 ring-primary/40 ring-offset-2 rounded-lg transition-all min-h-[3rem]" : "min-h-[3rem] rounded-lg transition-all",
25123
+ children
25122
25124
  }
25123
25125
  );
25124
25126
  };
25125
25127
  const rootContextValue = React93__default.useMemo(
25126
- () => ({ registerZone, unregisterZone, activeDrag, overZoneGroup }),
25127
- [registerZone, unregisterZone, activeDrag, overZoneGroup]
25128
+ () => ({ registerZone, unregisterZone, activeDrag, overZoneGroup, optimisticOrders, clearOptimisticOrder }),
25129
+ [registerZone, unregisterZone, activeDrag, overZoneGroup, optimisticOrders, clearOptimisticOrder]
25128
25130
  );
25129
25131
  const handleDragStart = React93__default.useCallback((event) => {
25130
25132
  const sourceZone = findZoneByItem(event.active.id);
@@ -25146,13 +25148,73 @@ function useDataDnd(args) {
25146
25148
  });
25147
25149
  }, [findZoneByItem, isRoot, zoneId]);
25148
25150
  const handleDragOver = React93__default.useCallback((event) => {
25149
- const overData = event.over?.data?.current;
25150
- const group = overData?.dndGroup ?? null;
25151
- setOverZoneGroup(group);
25152
- dndLog.debug("dragOver", {
25153
- activeId: event.active.id,
25154
- overId: event.over?.id,
25155
- overGroup: group
25151
+ const { active, over } = event;
25152
+ const overData = over?.data?.current;
25153
+ const overGroup = overData?.dndGroup ?? null;
25154
+ setOverZoneGroup(overGroup);
25155
+ if (!over || !overGroup) return;
25156
+ const activeIdStr = String(active.id);
25157
+ let sourceMeta;
25158
+ let sourceGroup;
25159
+ for (const m of zonesRef.current.values()) {
25160
+ const currentItems = optimisticOrdersRef.current.get(m.group) ?? m.rawItems;
25161
+ const found = currentItems.find((it) => String(it[m.idField]) === activeIdStr);
25162
+ if (found) {
25163
+ sourceMeta = m;
25164
+ sourceGroup = m.group;
25165
+ break;
25166
+ }
25167
+ }
25168
+ if (!sourceMeta || !sourceGroup) {
25169
+ dndLog.debug("dragOver:no-source-zone", { activeId: active.id });
25170
+ return;
25171
+ }
25172
+ let targetMeta;
25173
+ for (const m of zonesRef.current.values()) {
25174
+ if (m.group === overGroup) {
25175
+ targetMeta = m;
25176
+ break;
25177
+ }
25178
+ }
25179
+ if (!targetMeta) {
25180
+ dndLog.debug("dragOver:no-target-zone", { overGroup });
25181
+ return;
25182
+ }
25183
+ if (sourceGroup === overGroup) {
25184
+ setOptimisticOrders((prev) => {
25185
+ const currentItems = prev.get(sourceGroup) ?? sourceMeta.rawItems;
25186
+ const oldIndex = currentItems.findIndex((it) => String(it[sourceMeta.idField]) === activeIdStr);
25187
+ const newIndex = currentItems.findIndex((it) => String(it[sourceMeta.idField]) === String(over.id));
25188
+ if (oldIndex === -1 || newIndex === -1 || oldIndex === newIndex) return prev;
25189
+ const reordered = arrayMove([...currentItems], oldIndex, newIndex);
25190
+ const next = new Map(prev);
25191
+ next.set(sourceGroup, reordered);
25192
+ return next;
25193
+ });
25194
+ return;
25195
+ }
25196
+ setOptimisticOrders((prev) => {
25197
+ const currentSource = prev.get(sourceGroup) ?? sourceMeta.rawItems;
25198
+ const currentTarget = prev.get(overGroup) ?? targetMeta.rawItems;
25199
+ const activeItem = currentSource.find((it) => String(it[sourceMeta.idField]) === activeIdStr);
25200
+ if (!activeItem) return prev;
25201
+ if (currentTarget.some((it) => String(it[targetMeta.idField]) === activeIdStr)) {
25202
+ return prev;
25203
+ }
25204
+ const newSource = currentSource.filter((it) => String(it[sourceMeta.idField]) !== activeIdStr);
25205
+ const overIdStr = String(over.id);
25206
+ const overIndex = currentTarget.findIndex((it) => String(it[targetMeta.idField]) === overIdStr);
25207
+ const insertAt = overIndex >= 0 ? overIndex : currentTarget.length;
25208
+ const newTarget = [
25209
+ ...currentTarget.slice(0, insertAt),
25210
+ activeItem,
25211
+ ...currentTarget.slice(insertAt)
25212
+ ];
25213
+ const next = new Map(prev);
25214
+ next.set(sourceGroup, newSource);
25215
+ next.set(overGroup, newTarget);
25216
+ dndLog.debug("dragOver:cross-zone:splice", { sourceGroup, overGroup, sourceLen: newSource.length, targetLen: newTarget.length, insertAt });
25217
+ return next;
25156
25218
  });
25157
25219
  }, []);
25158
25220
  const handleDragCancel = React93__default.useCallback((event) => {
@@ -57327,6 +57389,66 @@ function convertFnFormLambdasInProps(props) {
57327
57389
  // hooks/index.ts
57328
57390
  init_useEventBus();
57329
57391
  var ALMADAR_DND_MIME = "application/x-almadar-dnd";
57392
+
57393
+ // hooks/useDropZone.ts
57394
+ init_useEventBus();
57395
+ function parsePayload(e) {
57396
+ try {
57397
+ const raw = e.dataTransfer.getData(ALMADAR_DND_MIME);
57398
+ if (!raw) return null;
57399
+ const parsed = JSON.parse(raw);
57400
+ if (typeof parsed.kind !== "string" || !parsed.data) return null;
57401
+ return parsed;
57402
+ } catch {
57403
+ return null;
57404
+ }
57405
+ }
57406
+ function hasAlmadarPayload(e) {
57407
+ return e.dataTransfer.types.includes(ALMADAR_DND_MIME);
57408
+ }
57409
+ function useDropZone({ accepts, onDrop, disabled = false }) {
57410
+ const [isOver, setIsOver] = useState(false);
57411
+ const eventBus = useEventBus();
57412
+ const handleDragOver = useCallback(
57413
+ (e) => {
57414
+ if (disabled) return;
57415
+ if (!hasAlmadarPayload(e)) return;
57416
+ e.preventDefault();
57417
+ e.dataTransfer.dropEffect = "copy";
57418
+ setIsOver(true);
57419
+ },
57420
+ [disabled]
57421
+ );
57422
+ const handleDragLeave = useCallback(
57423
+ (e) => {
57424
+ setIsOver(false);
57425
+ },
57426
+ []
57427
+ );
57428
+ const handleDrop = useCallback(
57429
+ (e) => {
57430
+ e.preventDefault();
57431
+ setIsOver(false);
57432
+ if (disabled) return;
57433
+ const payload = parsePayload(e);
57434
+ if (!payload) return;
57435
+ if (!accepts.includes(payload.kind)) return;
57436
+ const position = { x: e.clientX, y: e.clientY };
57437
+ onDrop(payload, position);
57438
+ eventBus.emit("UI:DROP", { kind: payload.kind, data: payload.data, ...position });
57439
+ },
57440
+ [disabled, accepts, onDrop, eventBus]
57441
+ );
57442
+ const dropProps = useMemo(
57443
+ () => ({
57444
+ onDragOver: handleDragOver,
57445
+ onDragLeave: handleDragLeave,
57446
+ onDrop: handleDrop
57447
+ }),
57448
+ [handleDragOver, handleDragLeave, handleDrop]
57449
+ );
57450
+ return { dropProps, isOver };
57451
+ }
57330
57452
  var log16 = createLogger("almadar:ui:effects:client-handlers");
57331
57453
  function createClientEffectHandlers(options) {
57332
57454
  const { eventBus, slotSetter, navigate, notify, callService } = options;
@@ -59285,19 +59407,98 @@ var OrbPreviewNodeInner = (props) => {
59285
59407
  const statusBorder = isRunning ? "var(--color-primary)" : isError ? "var(--color-danger)" : isSuccess ? "var(--color-success)" : null;
59286
59408
  const borderWidth = isRunning || isError || isSuccess ? "2px" : "1.5px";
59287
59409
  const borderColor = statusBorder ?? (hovered ? "var(--color-primary)" : colors.border);
59410
+ const handleL1Drop = useCallback(
59411
+ (payload) => {
59412
+ if (payload.kind !== "pattern") return;
59413
+ if (typeof payload.data.type !== "string") return;
59414
+ eventBus.emit("UI:PATTERN_DROP", {
59415
+ patternType: payload.data.type,
59416
+ containerNode: { orbitalName: data.orbitalName }
59417
+ });
59418
+ },
59419
+ [eventBus, data.orbitalName]
59420
+ );
59421
+ const { dropProps: l1DropProps, isOver: l1IsOver } = useDropZone({
59422
+ accepts: ["pattern"],
59423
+ onDrop: handleL1Drop,
59424
+ disabled: isExpanded
59425
+ });
59288
59426
  return /* @__PURE__ */ jsxs(
59289
59427
  Box,
59290
59428
  {
59429
+ ...isExpanded ? {} : l1DropProps,
59291
59430
  className: `rounded-lg border shadow-sm bg-card transition-all duration-200 overflow-hidden relative${isRunning ? " orb-preview-running" : ""}`,
59292
59431
  style: {
59293
- borderColor,
59294
- borderWidth,
59295
- width: preset.width
59432
+ borderColor: l1IsOver ? "var(--color-primary)" : borderColor,
59433
+ borderWidth: l1IsOver ? "2px" : borderWidth,
59434
+ width: preset.width,
59435
+ boxShadow: l1IsOver ? "0 0 0 3px var(--color-primary), 0 0 12px var(--color-primary)" : void 0
59296
59436
  },
59297
59437
  onMouseEnter: handleMouseEnter,
59298
59438
  onMouseLeave: handleMouseLeave,
59299
59439
  children: [
59300
59440
  /* @__PURE__ */ jsx("style", { children: SELECTION_STYLES }),
59441
+ !isExpanded && /* @__PURE__ */ jsxs(Fragment, { children: [
59442
+ /* @__PURE__ */ jsx(
59443
+ Box,
59444
+ {
59445
+ className: "absolute top-1.5 left-1.5 rounded px-1 py-[1px] text-[8px] font-mono uppercase tracking-wider pointer-events-none",
59446
+ style: {
59447
+ backgroundColor: "var(--color-muted)",
59448
+ color: "var(--color-muted-foreground)",
59449
+ zIndex: 3
59450
+ },
59451
+ children: "Preview"
59452
+ }
59453
+ ),
59454
+ hovered && !dragActive && !l1IsOver && /* @__PURE__ */ jsx(
59455
+ Box,
59456
+ {
59457
+ className: "absolute inset-0 flex items-center justify-center pointer-events-none",
59458
+ style: {
59459
+ backgroundColor: "rgba(0,0,0,0.04)",
59460
+ zIndex: 2
59461
+ },
59462
+ children: /* @__PURE__ */ jsxs(
59463
+ Box,
59464
+ {
59465
+ className: "rounded-md px-2 py-1 text-[11px] font-medium flex items-center gap-1",
59466
+ style: {
59467
+ backgroundColor: "var(--color-card)",
59468
+ color: "var(--color-foreground)",
59469
+ boxShadow: "var(--shadow-main)"
59470
+ },
59471
+ children: [
59472
+ /* @__PURE__ */ jsx("span", { style: { fontSize: 12 }, children: "\u279E" }),
59473
+ "Click to open"
59474
+ ]
59475
+ }
59476
+ )
59477
+ }
59478
+ ),
59479
+ (dragActive || l1IsOver) && /* @__PURE__ */ jsx(
59480
+ Box,
59481
+ {
59482
+ className: "absolute inset-0 flex items-center justify-center pointer-events-none",
59483
+ style: {
59484
+ backgroundColor: l1IsOver ? "rgba(20,184,166,0.15)" : "rgba(20,184,166,0.06)",
59485
+ zIndex: 2
59486
+ },
59487
+ children: /* @__PURE__ */ jsx(
59488
+ Box,
59489
+ {
59490
+ className: "rounded-md px-2 py-1 text-[11px] font-semibold",
59491
+ style: {
59492
+ backgroundColor: "var(--color-primary)",
59493
+ color: "var(--color-primary-foreground)",
59494
+ boxShadow: "var(--shadow-lg)"
59495
+ },
59496
+ children: "Drop to add and open"
59497
+ }
59498
+ )
59499
+ }
59500
+ )
59501
+ ] }),
59301
59502
  isRunning && /* @__PURE__ */ jsxs(Fragment, { children: [
59302
59503
  /* @__PURE__ */ jsx("style", { children: `
59303
59504
  @keyframes orb-preview-running-pulse {
@@ -60479,13 +60680,14 @@ function FlowCanvasInner({
60479
60680
  transition: nodeData.transitionEvent
60480
60681
  });
60481
60682
  } else {
60482
- onNodeClick?.({
60483
- level: "overview",
60484
- orbital: nodeData.orbitalName ?? node.id
60485
- });
60486
- onNodeSelect?.(nodeData.orbitalName ?? node.id);
60683
+ const orbitalName = nodeData.orbitalName ?? node.id;
60684
+ onNodeClick?.({ level: "overview", orbital: orbitalName });
60685
+ onNodeSelect?.(orbitalName);
60686
+ setExpandedOrbital(orbitalName);
60687
+ setLevel("expanded");
60688
+ onLevelChange?.("expanded", orbitalName);
60487
60689
  }
60488
- }, [level, expandedOrbital, onNodeClick]);
60690
+ }, [level, expandedOrbital, onNodeClick, onNodeSelect, onLevelChange]);
60489
60691
  const handleClosePanel = useCallback(() => {
60490
60692
  setSelectedNode(null);
60491
60693
  }, []);