@almadar/ui 4.50.21 → 4.51.0

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: useCallback128, useState: useState122 } = React93__namespace.default;
13700
+ const { useEffect: useEffect87, useRef: useRef87, useCallback: useCallback126, useState: useState120 } = 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] = useState122(null);
13746
- const handleMapClick = useCallback128((lat, lng) => {
13745
+ const [clickedPosition, setClickedPosition] = useState120(null);
13746
+ const handleMapClick = useCallback126((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 = useCallback128((marker) => {
13755
+ const handleMarkerClick = useCallback126((marker) => {
13756
13756
  onMarkerClick?.(marker);
13757
13757
  if (markerClickEvent) {
13758
13758
  eventBus.emit(`UI:${markerClickEvent}`, { ...marker });
@@ -24906,6 +24906,31 @@ var init_DashboardLayout = __esm({
24906
24906
  NavLink.displayName = "NavLink";
24907
24907
  }
24908
24908
  });
24909
+ function useAlmadarDndSensors(withSortableKeyboard = true) {
24910
+ return core$1.useSensors(
24911
+ core$1.useSensor(core$1.PointerSensor, {
24912
+ activationConstraint: { distance: ALMADAR_DND_ACTIVATION_DISTANCE }
24913
+ }),
24914
+ core$1.useSensor(
24915
+ core$1.KeyboardSensor,
24916
+ withSortableKeyboard ? { coordinateGetter: sortable.sortableKeyboardCoordinates } : void 0
24917
+ )
24918
+ );
24919
+ }
24920
+ var ALMADAR_DND_ACTIVATION_DISTANCE, almadarDndCollisionDetection;
24921
+ var init_useAlmadarDndCollision = __esm({
24922
+ "hooks/useAlmadarDndCollision.ts"() {
24923
+ "use client";
24924
+ ALMADAR_DND_ACTIVATION_DISTANCE = 5;
24925
+ almadarDndCollisionDetection = (args) => {
24926
+ const pw = core$1.pointerWithin(args);
24927
+ if (pw.length > 0) return pw;
24928
+ const ri = core$1.rectIntersection(args);
24929
+ if (ri.length > 0) return ri;
24930
+ return core$1.closestCorners(args);
24931
+ };
24932
+ }
24933
+ });
24909
24934
  function useDataDnd(args) {
24910
24935
  const {
24911
24936
  dragGroup,
@@ -25001,25 +25026,8 @@ function useDataDnd(args) {
25001
25026
  dndLog.debug("zone:unregister", { zoneId, group: meta.group });
25002
25027
  };
25003
25028
  }, [parentRoot, isRoot, zoneId, meta]);
25004
- const sensors = core$1.useSensors(
25005
- core$1.useSensor(core$1.PointerSensor, { activationConstraint: { distance: 5 } }),
25006
- core$1.useSensor(core$1.KeyboardSensor, { coordinateGetter: sortable.sortableKeyboardCoordinates })
25007
- );
25008
- const collisionDetection = React93__namespace.default.useCallback((args2) => {
25009
- const pointerCollisions = core$1.pointerWithin(args2);
25010
- if (pointerCollisions.length > 0) {
25011
- dndLog.debug("collision:pointerWithin", { count: pointerCollisions.length, ids: pointerCollisions.map((c) => c.id) });
25012
- return pointerCollisions;
25013
- }
25014
- const rectCollisions = core$1.rectIntersection(args2);
25015
- if (rectCollisions.length > 0) {
25016
- dndLog.debug("collision:rectIntersection", { count: rectCollisions.length, ids: rectCollisions.map((c) => c.id) });
25017
- return rectCollisions;
25018
- }
25019
- const cornerCollisions = core$1.closestCorners(args2);
25020
- dndLog.debug("collision:closestCorners", { count: cornerCollisions.length, ids: cornerCollisions.map((c) => c.id) });
25021
- return cornerCollisions;
25022
- }, []);
25029
+ const sensors = useAlmadarDndSensors(true);
25030
+ const collisionDetection = almadarDndCollisionDetection;
25023
25031
  const findZoneByItem = React93__namespace.default.useCallback(
25024
25032
  (id) => {
25025
25033
  for (const z of zonesRef.current.values()) {
@@ -25356,6 +25364,7 @@ var init_useDataDnd = __esm({
25356
25364
  "components/molecules/useDataDnd.tsx"() {
25357
25365
  "use client";
25358
25366
  init_useEventBus();
25367
+ init_useAlmadarDndCollision();
25359
25368
  init_Box();
25360
25369
  dndLog = logger.createLogger("almadar:ui:dnd");
25361
25370
  RootCtx = React93__namespace.default.createContext(null);
@@ -38135,6 +38144,7 @@ var init_Form = __esm({
38135
38144
  submitLabel,
38136
38145
  cancelLabel,
38137
38146
  showCancel,
38147
+ showSubmit = true,
38138
38148
  title,
38139
38149
  submitEvent = "SAVE",
38140
38150
  cancelEvent = "CANCEL",
@@ -38621,8 +38631,8 @@ var init_Form = __esm({
38621
38631
  sectionElements && sectionElements.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(VStack, { gap: gap === "sm" ? "sm" : gap === "lg" ? "lg" : "md", children: sectionElements }),
38622
38632
  schemaFields,
38623
38633
  children,
38624
- (schemaFields && schemaFields.length > 0 || sectionElements && sectionElements.length > 0) && /* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "sm", className: "pt-4", children: [
38625
- /* @__PURE__ */ jsxRuntime.jsx(
38634
+ (schemaFields && schemaFields.length > 0 || sectionElements && sectionElements.length > 0) && (showSubmit || shouldShowCancel) && /* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "sm", className: "pt-4", children: [
38635
+ showSubmit && /* @__PURE__ */ jsxRuntime.jsx(
38626
38636
  Button,
38627
38637
  {
38628
38638
  type: "submit",
@@ -42978,7 +42988,7 @@ function getAllEvents(traits2) {
42978
42988
  }
42979
42989
  function EventDispatcherTab({ traits: traits2, schema }) {
42980
42990
  const eventBus = useEventBus();
42981
- const [log19, setLog] = React93__namespace.useState([]);
42991
+ const [log20, setLog] = React93__namespace.useState([]);
42982
42992
  const prevStatesRef = React93__namespace.useRef(/* @__PURE__ */ new Map());
42983
42993
  React93__namespace.useEffect(() => {
42984
42994
  for (const trait of traits2) {
@@ -43042,9 +43052,9 @@ function EventDispatcherTab({ traits: traits2, schema }) {
43042
43052
  /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "small", weight: "medium", className: "text-gray-500 mb-1", children: "Other Events (not available from current state)" }),
43043
43053
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap gap-1", children: unavailableEvents.map((event) => /* @__PURE__ */ jsxRuntime.jsx(Badge, { variant: "default", size: "sm", className: "opacity-50", children: event }, event)) })
43044
43054
  ] }),
43045
- log19.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
43055
+ log20.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
43046
43056
  /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "small", weight: "medium", className: "text-gray-500 mb-1", children: "Recent Transitions" }),
43047
- /* @__PURE__ */ jsxRuntime.jsx(Stack, { gap: "xs", children: log19.map((entry, i) => /* @__PURE__ */ jsxRuntime.jsxs(Typography, { variant: "small", className: "font-mono text-xs", children: [
43057
+ /* @__PURE__ */ jsxRuntime.jsx(Stack, { gap: "xs", children: log20.map((entry, i) => /* @__PURE__ */ jsxRuntime.jsxs(Typography, { variant: "small", className: "font-mono text-xs", children: [
43048
43058
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-purple-400", children: entry.traitName }),
43049
43059
  " ",
43050
43060
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-gray-500", children: entry.from }),
@@ -57467,67 +57477,6 @@ function convertFnFormLambdasInProps(props) {
57467
57477
 
57468
57478
  // hooks/index.ts
57469
57479
  init_useEventBus();
57470
- var ALMADAR_DND_MIME = "application/x-almadar-dnd";
57471
-
57472
- // hooks/useDropZone.ts
57473
- init_useEventBus();
57474
- function parsePayload(e) {
57475
- try {
57476
- const raw = e.dataTransfer.getData(ALMADAR_DND_MIME);
57477
- if (!raw) return null;
57478
- const parsed = JSON.parse(raw);
57479
- if (typeof parsed.kind !== "string" || !parsed.data) return null;
57480
- return parsed;
57481
- } catch {
57482
- return null;
57483
- }
57484
- }
57485
- function hasAlmadarPayload(e) {
57486
- return e.dataTransfer.types.includes(ALMADAR_DND_MIME);
57487
- }
57488
- function useDropZone({ accepts, onDrop, disabled = false }) {
57489
- const [isOver, setIsOver] = React93.useState(false);
57490
- const eventBus = useEventBus();
57491
- const handleDragOver = React93.useCallback(
57492
- (e) => {
57493
- if (disabled) return;
57494
- if (!hasAlmadarPayload(e)) return;
57495
- e.preventDefault();
57496
- e.dataTransfer.dropEffect = "copy";
57497
- setIsOver(true);
57498
- },
57499
- [disabled]
57500
- );
57501
- const handleDragLeave = React93.useCallback(
57502
- (e) => {
57503
- setIsOver(false);
57504
- },
57505
- []
57506
- );
57507
- const handleDrop = React93.useCallback(
57508
- (e) => {
57509
- e.preventDefault();
57510
- setIsOver(false);
57511
- if (disabled) return;
57512
- const payload = parsePayload(e);
57513
- if (!payload) return;
57514
- if (!accepts.includes(payload.kind)) return;
57515
- const position = { x: e.clientX, y: e.clientY };
57516
- onDrop(payload, position);
57517
- eventBus.emit("UI:DROP", { kind: payload.kind, data: payload.data, ...position });
57518
- },
57519
- [disabled, accepts, onDrop, eventBus]
57520
- );
57521
- const dropProps = React93.useMemo(
57522
- () => ({
57523
- onDragOver: handleDragOver,
57524
- onDragLeave: handleDragLeave,
57525
- onDrop: handleDrop
57526
- }),
57527
- [handleDragOver, handleDragLeave, handleDrop]
57528
- );
57529
- return { dropProps, isOver };
57530
- }
57531
57480
  var log16 = logger.createLogger("almadar:ui:effects:client-handlers");
57532
57481
  function createClientEffectHandlers(options) {
57533
57482
  const { eventBus, slotSetter, navigate, notify, callService } = options;
@@ -59140,6 +59089,128 @@ function BrowserPlayground({
59140
59089
  // components/molecules/avl/OrbPreviewNode.tsx
59141
59090
  init_useEventBus();
59142
59091
 
59092
+ // components/molecules/avl/useCanvasDnd.tsx
59093
+ init_useEventBus();
59094
+ init_useAlmadarDndCollision();
59095
+ var log18 = logger.createLogger("almadar:ui:canvas-dnd");
59096
+ function useCanvasDraggable({
59097
+ id,
59098
+ payload,
59099
+ disabled
59100
+ }) {
59101
+ const { setNodeRef, attributes, listeners: listeners6, isDragging, transform } = core$1.useDraggable({
59102
+ id,
59103
+ data: { payload },
59104
+ disabled
59105
+ });
59106
+ const style = {
59107
+ transform: utilities.CSS.Translate.toString(transform),
59108
+ cursor: disabled ? "not-allowed" : isDragging ? "grabbing" : "grab",
59109
+ opacity: isDragging ? 0.5 : 1,
59110
+ touchAction: "none"
59111
+ };
59112
+ return { setNodeRef, attributes, listeners: listeners6, isDragging, style };
59113
+ }
59114
+ var DEFAULT_ACCEPTS = ["pattern", "behavior"];
59115
+ function useCanvasDroppable({
59116
+ id,
59117
+ target,
59118
+ accepts,
59119
+ disabled
59120
+ }) {
59121
+ const acceptsList = accepts ?? DEFAULT_ACCEPTS;
59122
+ const { setNodeRef, isOver } = core$1.useDroppable({
59123
+ id,
59124
+ data: { target, accepts: acceptsList },
59125
+ disabled
59126
+ });
59127
+ return { setNodeRef, isOver };
59128
+ }
59129
+ function defaultEmit(eventBus, drop) {
59130
+ const { payload, target, resolved } = drop;
59131
+ if (payload.kind === "pattern") {
59132
+ const patternType = payload.data.type;
59133
+ if (typeof patternType !== "string") {
59134
+ log18.warn("default-emit:pattern:missing-type");
59135
+ return;
59136
+ }
59137
+ const out = { patternType, containerNode: target.containerNode };
59138
+ if (resolved) {
59139
+ out.parentPath = resolved.parentPath;
59140
+ out.index = resolved.index;
59141
+ }
59142
+ eventBus.emit("UI:PATTERN_DROP", out);
59143
+ log18.info("default-emit:pattern", { patternType, level: target.level });
59144
+ return;
59145
+ }
59146
+ if (payload.kind === "behavior") {
59147
+ const behaviorName = payload.data.name;
59148
+ if (typeof behaviorName !== "string") {
59149
+ log18.warn("default-emit:behavior:missing-name");
59150
+ return;
59151
+ }
59152
+ eventBus.emit("UI:BEHAVIOR_DROP", {
59153
+ behaviorName,
59154
+ containerNode: target.containerNode
59155
+ });
59156
+ log18.info("default-emit:behavior", { behaviorName, level: target.level });
59157
+ return;
59158
+ }
59159
+ log18.debug("default-emit:unhandled-kind", { kind: payload.kind });
59160
+ }
59161
+ function CanvasDndProvider({ children, onDrop }) {
59162
+ const eventBus = useEventBus();
59163
+ const sensors = useAlmadarDndSensors(false);
59164
+ const handleDragStart = React93__namespace.default.useCallback((e) => {
59165
+ const data = e.active.data.current;
59166
+ const payload = data?.payload;
59167
+ if (payload) {
59168
+ eventBus.emit("UI:DRAG_START", { kind: payload.kind, data: payload.data });
59169
+ log18.info("dragStart", { id: e.active.id, kind: payload.kind });
59170
+ } else {
59171
+ log18.warn("dragStart:missing-payload", { id: e.active.id });
59172
+ }
59173
+ }, [eventBus]);
59174
+ const handleDragEnd = React93__namespace.default.useCallback((e) => {
59175
+ const activeData = e.active.data.current;
59176
+ const payload = activeData?.payload;
59177
+ const overData = e.over?.data.current;
59178
+ const target = overData?.target;
59179
+ const accepts = overData?.accepts;
59180
+ log18.info("dragEnd", {
59181
+ activeId: e.active.id,
59182
+ overId: e.over?.id,
59183
+ hasPayload: !!payload,
59184
+ hasTarget: !!target,
59185
+ targetLevel: target?.level
59186
+ });
59187
+ if (payload) {
59188
+ eventBus.emit("UI:DRAG_END", { kind: payload.kind, data: payload.data });
59189
+ }
59190
+ if (!payload || !target) return;
59191
+ if (accepts && !accepts.includes(payload.kind)) {
59192
+ log18.debug("dragEnd:rejected:kind", { kind: payload.kind, accepts: [...accepts] });
59193
+ return;
59194
+ }
59195
+ const activator = e.activatorEvent;
59196
+ const cursor = activator && typeof activator.clientX === "number" && typeof activator.clientY === "number" ? { x: activator.clientX + e.delta.x, y: activator.clientY + e.delta.y } : null;
59197
+ const resolved = target.resolvePath && cursor ? target.resolvePath(cursor) : null;
59198
+ const drop = { payload, target, cursor, resolved };
59199
+ const suppressed = onDrop ? onDrop(drop) === true : false;
59200
+ if (!suppressed) defaultEmit(eventBus, drop);
59201
+ }, [eventBus, onDrop]);
59202
+ return /* @__PURE__ */ jsxRuntime.jsx(
59203
+ core$1.DndContext,
59204
+ {
59205
+ sensors,
59206
+ collisionDetection: almadarDndCollisionDetection,
59207
+ onDragStart: handleDragStart,
59208
+ onDragEnd: handleDragEnd,
59209
+ children
59210
+ }
59211
+ );
59212
+ }
59213
+
59143
59214
  // components/molecules/avl/wire-validation.ts
59144
59215
  function validateWire(sourcePayload, targetPayload) {
59145
59216
  const warnings = [];
@@ -59488,105 +59559,74 @@ var OrbPreviewNodeInner = (props) => {
59488
59559
  unsub2();
59489
59560
  };
59490
59561
  }, [eventBus]);
59491
- const handlePreviewDrop = React93.useCallback((e) => {
59492
- e.preventDefault();
59493
- e.stopPropagation();
59494
- setDragActive(false);
59495
- contentRef.current?.querySelectorAll(".drag-hover, .drop-indicator").forEach((el2) => {
59496
- el2.classList.remove("drag-hover");
59497
- if (el2.classList.contains("drop-indicator")) el2.remove();
59498
- });
59499
- const raw = e.dataTransfer.getData(ALMADAR_DND_MIME);
59500
- if (!raw) return;
59501
- let payload;
59502
- try {
59503
- payload = JSON.parse(raw);
59504
- } catch {
59505
- return;
59506
- }
59507
- if (payload.kind !== "pattern") return;
59508
- let el = e.target;
59509
- while (el && el.dataset.acceptsChildren !== "true") {
59510
- el = el.parentElement;
59511
- if (!el || el === contentRef.current) break;
59512
- }
59513
- const containerNode = {
59514
- orbitalName: data.orbitalName,
59515
- traitName: data.traitName,
59516
- transitionEvent: data.transitionEvent
59517
- };
59518
- const containerPath = el?.dataset?.patternPath;
59519
- if (!containerPath) {
59520
- eventBus.emit("UI:PATTERN_DROP", {
59521
- parentPath: "root",
59522
- patternType: payload.data.type,
59523
- index: 0,
59524
- containerNode
59525
- });
59526
- return;
59527
- }
59528
- const pathChildren = el.querySelectorAll(":scope > [data-pattern-path]");
59529
- let insertIndex = pathChildren.length;
59530
- for (let i = 0; i < pathChildren.length; i++) {
59531
- const rect = pathChildren[i].getBoundingClientRect();
59562
+ const resolveL2Path = React93.useCallback(
59563
+ (cursor) => {
59564
+ const hit = document.elementFromPoint(cursor.x, cursor.y);
59565
+ if (!hit) return null;
59566
+ let el = hit;
59567
+ while (el && el.dataset.acceptsChildren !== "true") {
59568
+ if (el === contentRef.current) break;
59569
+ el = el.parentElement;
59570
+ }
59571
+ if (!el) return null;
59572
+ const containerPath = el.dataset?.patternPath;
59573
+ if (!containerPath) return { parentPath: "root", index: 0 };
59574
+ const pathChildren = el.querySelectorAll(":scope > [data-pattern-path]");
59575
+ let insertIndex = pathChildren.length;
59532
59576
  const style = el.firstElementChild ? getComputedStyle(el.firstElementChild) : null;
59533
59577
  const isVertical = style?.flexDirection !== "row";
59534
- const mid = isVertical ? rect.top + rect.height / 2 : rect.left + rect.width / 2;
59535
- const cursor = isVertical ? e.clientY : e.clientX;
59536
- if (cursor < mid) {
59537
- insertIndex = i;
59538
- break;
59578
+ for (let i = 0; i < pathChildren.length; i++) {
59579
+ const rect = pathChildren[i].getBoundingClientRect();
59580
+ const mid = isVertical ? rect.top + rect.height / 2 : rect.left + rect.width / 2;
59581
+ const pos = isVertical ? cursor.y : cursor.x;
59582
+ if (pos < mid) {
59583
+ insertIndex = i;
59584
+ break;
59585
+ }
59539
59586
  }
59540
- }
59541
- eventBus.emit("UI:PATTERN_DROP", {
59542
- parentPath: containerPath,
59543
- patternType: payload.data.type,
59544
- index: insertIndex,
59545
- containerNode
59546
- });
59547
- }, [eventBus, data.orbitalName, data.traitName, data.transitionEvent]);
59548
- const handlePreviewDragOver = React93.useCallback((e) => {
59549
- if (!e.dataTransfer.types.includes(ALMADAR_DND_MIME)) return;
59550
- e.preventDefault();
59551
- e.stopPropagation();
59552
- e.dataTransfer.dropEffect = "copy";
59553
- if (!dragActive) setDragActive(true);
59554
- let el = e.target;
59555
- while (el && el.dataset.acceptsChildren !== "true") {
59556
- el = el.parentElement;
59557
- if (!el || el === contentRef.current) break;
59558
- }
59559
- contentRef.current?.querySelectorAll(".drag-hover").forEach((c) => c.classList.remove("drag-hover"));
59560
- if (el?.dataset?.acceptsChildren === "true") {
59561
- el.classList.add("drag-hover");
59562
- }
59563
- }, [dragActive]);
59564
- const handlePreviewDragLeave = React93.useCallback((e) => {
59565
- contentRef.current?.querySelectorAll(".drag-hover").forEach((c) => c.classList.remove("drag-hover"));
59566
- }, []);
59587
+ return { parentPath: containerPath, index: insertIndex };
59588
+ },
59589
+ []
59590
+ );
59591
+ const l2Target = React93.useMemo(
59592
+ () => ({
59593
+ level: "l2",
59594
+ containerNode: {
59595
+ orbitalName: data.orbitalName,
59596
+ traitName: data.traitName,
59597
+ transitionEvent: data.transitionEvent
59598
+ },
59599
+ resolvePath: resolveL2Path
59600
+ }),
59601
+ [data.orbitalName, data.traitName, data.transitionEvent, resolveL2Path]
59602
+ );
59603
+ const { setNodeRef: l2SetNodeRef, isOver: l2IsOver } = useCanvasDroppable({
59604
+ id: `orb-l2-${data.orbitalName}-${data.traitName ?? ""}-${data.transitionEvent ?? ""}`,
59605
+ target: l2Target,
59606
+ accepts: ["pattern"],
59607
+ disabled: !isExpanded
59608
+ });
59609
+ const setContentRef = React93.useCallback((el) => {
59610
+ contentRef.current = el;
59611
+ l2SetNodeRef(el);
59612
+ }, [l2SetNodeRef]);
59567
59613
  const statusBorder = isRunning ? "var(--color-primary)" : isError ? "var(--color-danger)" : isSuccess ? "var(--color-success)" : null;
59568
59614
  const borderWidth = isRunning || isError || isSuccess ? "2px" : "1.5px";
59569
59615
  const borderColor = statusBorder ?? (hovered ? "var(--color-primary)" : colors.border);
59570
- const handleL1Drop = React93.useCallback(
59571
- (payload) => {
59572
- if (payload.kind !== "pattern") return;
59573
- if (typeof payload.data.type !== "string") return;
59574
- eventBus.emit("UI:PATTERN_DROP", {
59575
- patternType: payload.data.type,
59576
- containerNode: { orbitalName: data.orbitalName }
59577
- });
59578
- },
59579
- [eventBus, data.orbitalName]
59616
+ const l1Target = React93.useMemo(
59617
+ () => ({ level: "l1", containerNode: { orbitalName: data.orbitalName } }),
59618
+ [data.orbitalName]
59580
59619
  );
59581
- const { dropProps: l1DropProps, isOver: l1IsOver } = useDropZone({
59620
+ const { setNodeRef: l1SetNodeRef, isOver: l1IsOver } = useCanvasDroppable({
59621
+ id: `orb-l1-${data.orbitalName}`,
59622
+ target: l1Target,
59582
59623
  accepts: ["pattern"],
59583
- onDrop: handleL1Drop,
59584
59624
  disabled: isExpanded
59585
59625
  });
59586
59626
  return /* @__PURE__ */ jsxRuntime.jsxs(
59587
59627
  Box,
59588
59628
  {
59589
- ...isExpanded ? {} : l1DropProps,
59629
+ ref: isExpanded ? void 0 : l1SetNodeRef,
59590
59630
  className: `rounded-lg border shadow-sm bg-card transition-all duration-200 overflow-hidden relative${isRunning ? " orb-preview-running" : ""}`,
59591
59631
  style: {
59592
59632
  borderColor: l1IsOver ? "var(--color-primary)" : borderColor,
@@ -59728,12 +59768,9 @@ var OrbPreviewNodeInner = (props) => {
59728
59768
  /* @__PURE__ */ jsxRuntime.jsx(
59729
59769
  Box,
59730
59770
  {
59731
- ref: contentRef,
59732
- className: `orb-preview-live nodrag${dragActive ? " drag-active" : ""}`,
59771
+ ref: setContentRef,
59772
+ className: `orb-preview-live nodrag${dragActive || l2IsOver ? " drag-active" : ""}`,
59733
59773
  onClick: handleContentClick,
59734
- onDrop: handlePreviewDrop,
59735
- onDragOver: handlePreviewDragOver,
59736
- onDragLeave: handlePreviewDragLeave,
59737
59774
  children: orbitalSchema ? /* @__PURE__ */ jsxRuntime.jsx(Box, { style: { minHeight: preset.minHeight }, children: /* @__PURE__ */ jsxRuntime.jsx(
59738
59775
  BrowserPlayground,
59739
59776
  {
@@ -61229,7 +61266,7 @@ init_AvlTransitionLane();
61229
61266
  init_AvlSwimLane();
61230
61267
  init_types();
61231
61268
  init_avl_elk_layout();
61232
- var log18 = logger.createLogger("almadar:ui:avl:trait-scene");
61269
+ var log19 = logger.createLogger("almadar:ui:avl:trait-scene");
61233
61270
  var SWIM_GUTTER2 = 120;
61234
61271
  var CENTER_W2 = 360;
61235
61272
  var AvlTraitScene = ({
@@ -61241,7 +61278,7 @@ var AvlTraitScene = ({
61241
61278
  const dataKey = React93.useMemo(() => JSON.stringify(data), [data]);
61242
61279
  React93.useEffect(() => {
61243
61280
  computeTraitLayout(data).then(setLayout).catch((error) => {
61244
- log18.error("computeTraitLayout failed", { error: error instanceof Error ? error : String(error) });
61281
+ log19.error("computeTraitLayout failed", { error: error instanceof Error ? error : String(error) });
61245
61282
  });
61246
61283
  }, [dataKey]);
61247
61284
  if (!layout) {
@@ -62415,6 +62452,7 @@ exports.AvlTransition = AvlTransition;
62415
62452
  exports.AvlTransitionEdge = AvlTransitionEdge;
62416
62453
  exports.AvlTransitionScene = AvlTransitionScene;
62417
62454
  exports.BehaviorComposeNode = BehaviorComposeNode;
62455
+ exports.CanvasDndProvider = CanvasDndProvider;
62418
62456
  exports.DOMAIN_COLORS = DOMAIN_COLORS;
62419
62457
  exports.DetailView = DetailView;
62420
62458
  exports.EventFlowEdge = EventFlowEdge;
@@ -62444,5 +62482,7 @@ exports.registryEntryToCanvasEntry = registryEntryToCanvasEntry;
62444
62482
  exports.ringPositions = ringPositions;
62445
62483
  exports.schemaToFlowGraph = schemaToFlowGraph;
62446
62484
  exports.schemaToOverviewGraph = schemaToOverviewGraph;
62485
+ exports.useCanvasDraggable = useCanvasDraggable;
62486
+ exports.useCanvasDroppable = useCanvasDroppable;
62447
62487
  exports.useZoomBand = useZoomBand;
62448
62488
  exports.zoomProgress = zoomProgress;