@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.
package/dist/avl/index.js CHANGED
@@ -34,7 +34,7 @@ import langToml from 'react-syntax-highlighter/dist/esm/languages/prism/toml.js'
34
34
  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
- import { useSensors, useSensor, PointerSensor, KeyboardSensor, pointerWithin, rectIntersection, closestCorners, DndContext, useDroppable } from '@dnd-kit/core';
37
+ import { useDroppable, useDraggable, DndContext, useSensors, useSensor, PointerSensor, KeyboardSensor, pointerWithin, rectIntersection, closestCorners } from '@dnd-kit/core';
38
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';
@@ -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: useCallback128, useState: useState122 } = React93__default;
13654
+ const { useEffect: useEffect87, useRef: useRef87, useCallback: useCallback126, useState: useState120 } = 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] = useState122(null);
13700
- const handleMapClick = useCallback128((lat, lng) => {
13699
+ const [clickedPosition, setClickedPosition] = useState120(null);
13700
+ const handleMapClick = useCallback126((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 = useCallback128((marker) => {
13709
+ const handleMarkerClick = useCallback126((marker) => {
13710
13710
  onMarkerClick?.(marker);
13711
13711
  if (markerClickEvent) {
13712
13712
  eventBus.emit(`UI:${markerClickEvent}`, { ...marker });
@@ -24860,6 +24860,31 @@ var init_DashboardLayout = __esm({
24860
24860
  NavLink.displayName = "NavLink";
24861
24861
  }
24862
24862
  });
24863
+ function useAlmadarDndSensors(withSortableKeyboard = true) {
24864
+ return useSensors(
24865
+ useSensor(PointerSensor, {
24866
+ activationConstraint: { distance: ALMADAR_DND_ACTIVATION_DISTANCE }
24867
+ }),
24868
+ useSensor(
24869
+ KeyboardSensor,
24870
+ withSortableKeyboard ? { coordinateGetter: sortableKeyboardCoordinates } : void 0
24871
+ )
24872
+ );
24873
+ }
24874
+ var ALMADAR_DND_ACTIVATION_DISTANCE, almadarDndCollisionDetection;
24875
+ var init_useAlmadarDndCollision = __esm({
24876
+ "hooks/useAlmadarDndCollision.ts"() {
24877
+ "use client";
24878
+ ALMADAR_DND_ACTIVATION_DISTANCE = 5;
24879
+ almadarDndCollisionDetection = (args) => {
24880
+ const pw = pointerWithin(args);
24881
+ if (pw.length > 0) return pw;
24882
+ const ri = rectIntersection(args);
24883
+ if (ri.length > 0) return ri;
24884
+ return closestCorners(args);
24885
+ };
24886
+ }
24887
+ });
24863
24888
  function useDataDnd(args) {
24864
24889
  const {
24865
24890
  dragGroup,
@@ -24955,25 +24980,8 @@ function useDataDnd(args) {
24955
24980
  dndLog.debug("zone:unregister", { zoneId, group: meta.group });
24956
24981
  };
24957
24982
  }, [parentRoot, isRoot, zoneId, meta]);
24958
- const sensors = useSensors(
24959
- useSensor(PointerSensor, { activationConstraint: { distance: 5 } }),
24960
- useSensor(KeyboardSensor, { coordinateGetter: sortableKeyboardCoordinates })
24961
- );
24962
- const collisionDetection = React93__default.useCallback((args2) => {
24963
- const pointerCollisions = pointerWithin(args2);
24964
- if (pointerCollisions.length > 0) {
24965
- dndLog.debug("collision:pointerWithin", { count: pointerCollisions.length, ids: pointerCollisions.map((c) => c.id) });
24966
- return pointerCollisions;
24967
- }
24968
- const rectCollisions = rectIntersection(args2);
24969
- if (rectCollisions.length > 0) {
24970
- dndLog.debug("collision:rectIntersection", { count: rectCollisions.length, ids: rectCollisions.map((c) => c.id) });
24971
- return rectCollisions;
24972
- }
24973
- const cornerCollisions = closestCorners(args2);
24974
- dndLog.debug("collision:closestCorners", { count: cornerCollisions.length, ids: cornerCollisions.map((c) => c.id) });
24975
- return cornerCollisions;
24976
- }, []);
24983
+ const sensors = useAlmadarDndSensors(true);
24984
+ const collisionDetection = almadarDndCollisionDetection;
24977
24985
  const findZoneByItem = React93__default.useCallback(
24978
24986
  (id) => {
24979
24987
  for (const z of zonesRef.current.values()) {
@@ -25310,6 +25318,7 @@ var init_useDataDnd = __esm({
25310
25318
  "components/molecules/useDataDnd.tsx"() {
25311
25319
  "use client";
25312
25320
  init_useEventBus();
25321
+ init_useAlmadarDndCollision();
25313
25322
  init_Box();
25314
25323
  dndLog = createLogger("almadar:ui:dnd");
25315
25324
  RootCtx = React93__default.createContext(null);
@@ -38089,6 +38098,7 @@ var init_Form = __esm({
38089
38098
  submitLabel,
38090
38099
  cancelLabel,
38091
38100
  showCancel,
38101
+ showSubmit = true,
38092
38102
  title,
38093
38103
  submitEvent = "SAVE",
38094
38104
  cancelEvent = "CANCEL",
@@ -38575,8 +38585,8 @@ var init_Form = __esm({
38575
38585
  sectionElements && sectionElements.length > 0 && /* @__PURE__ */ jsx(VStack, { gap: gap === "sm" ? "sm" : gap === "lg" ? "lg" : "md", children: sectionElements }),
38576
38586
  schemaFields,
38577
38587
  children,
38578
- (schemaFields && schemaFields.length > 0 || sectionElements && sectionElements.length > 0) && /* @__PURE__ */ jsxs(HStack, { gap: "sm", className: "pt-4", children: [
38579
- /* @__PURE__ */ jsx(
38588
+ (schemaFields && schemaFields.length > 0 || sectionElements && sectionElements.length > 0) && (showSubmit || shouldShowCancel) && /* @__PURE__ */ jsxs(HStack, { gap: "sm", className: "pt-4", children: [
38589
+ showSubmit && /* @__PURE__ */ jsx(
38580
38590
  Button,
38581
38591
  {
38582
38592
  type: "submit",
@@ -42932,7 +42942,7 @@ function getAllEvents(traits2) {
42932
42942
  }
42933
42943
  function EventDispatcherTab({ traits: traits2, schema }) {
42934
42944
  const eventBus = useEventBus();
42935
- const [log19, setLog] = React93.useState([]);
42945
+ const [log20, setLog] = React93.useState([]);
42936
42946
  const prevStatesRef = React93.useRef(/* @__PURE__ */ new Map());
42937
42947
  React93.useEffect(() => {
42938
42948
  for (const trait of traits2) {
@@ -42996,9 +43006,9 @@ function EventDispatcherTab({ traits: traits2, schema }) {
42996
43006
  /* @__PURE__ */ jsx(Typography, { variant: "small", weight: "medium", className: "text-gray-500 mb-1", children: "Other Events (not available from current state)" }),
42997
43007
  /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-1", children: unavailableEvents.map((event) => /* @__PURE__ */ jsx(Badge, { variant: "default", size: "sm", className: "opacity-50", children: event }, event)) })
42998
43008
  ] }),
42999
- log19.length > 0 && /* @__PURE__ */ jsxs("div", { children: [
43009
+ log20.length > 0 && /* @__PURE__ */ jsxs("div", { children: [
43000
43010
  /* @__PURE__ */ jsx(Typography, { variant: "small", weight: "medium", className: "text-gray-500 mb-1", children: "Recent Transitions" }),
43001
- /* @__PURE__ */ jsx(Stack, { gap: "xs", children: log19.map((entry, i) => /* @__PURE__ */ jsxs(Typography, { variant: "small", className: "font-mono text-xs", children: [
43011
+ /* @__PURE__ */ jsx(Stack, { gap: "xs", children: log20.map((entry, i) => /* @__PURE__ */ jsxs(Typography, { variant: "small", className: "font-mono text-xs", children: [
43002
43012
  /* @__PURE__ */ jsx("span", { className: "text-purple-400", children: entry.traitName }),
43003
43013
  " ",
43004
43014
  /* @__PURE__ */ jsx("span", { className: "text-gray-500", children: entry.from }),
@@ -57421,67 +57431,6 @@ function convertFnFormLambdasInProps(props) {
57421
57431
 
57422
57432
  // hooks/index.ts
57423
57433
  init_useEventBus();
57424
- var ALMADAR_DND_MIME = "application/x-almadar-dnd";
57425
-
57426
- // hooks/useDropZone.ts
57427
- init_useEventBus();
57428
- function parsePayload(e) {
57429
- try {
57430
- const raw = e.dataTransfer.getData(ALMADAR_DND_MIME);
57431
- if (!raw) return null;
57432
- const parsed = JSON.parse(raw);
57433
- if (typeof parsed.kind !== "string" || !parsed.data) return null;
57434
- return parsed;
57435
- } catch {
57436
- return null;
57437
- }
57438
- }
57439
- function hasAlmadarPayload(e) {
57440
- return e.dataTransfer.types.includes(ALMADAR_DND_MIME);
57441
- }
57442
- function useDropZone({ accepts, onDrop, disabled = false }) {
57443
- const [isOver, setIsOver] = useState(false);
57444
- const eventBus = useEventBus();
57445
- const handleDragOver = useCallback(
57446
- (e) => {
57447
- if (disabled) return;
57448
- if (!hasAlmadarPayload(e)) return;
57449
- e.preventDefault();
57450
- e.dataTransfer.dropEffect = "copy";
57451
- setIsOver(true);
57452
- },
57453
- [disabled]
57454
- );
57455
- const handleDragLeave = useCallback(
57456
- (e) => {
57457
- setIsOver(false);
57458
- },
57459
- []
57460
- );
57461
- const handleDrop = useCallback(
57462
- (e) => {
57463
- e.preventDefault();
57464
- setIsOver(false);
57465
- if (disabled) return;
57466
- const payload = parsePayload(e);
57467
- if (!payload) return;
57468
- if (!accepts.includes(payload.kind)) return;
57469
- const position = { x: e.clientX, y: e.clientY };
57470
- onDrop(payload, position);
57471
- eventBus.emit("UI:DROP", { kind: payload.kind, data: payload.data, ...position });
57472
- },
57473
- [disabled, accepts, onDrop, eventBus]
57474
- );
57475
- const dropProps = useMemo(
57476
- () => ({
57477
- onDragOver: handleDragOver,
57478
- onDragLeave: handleDragLeave,
57479
- onDrop: handleDrop
57480
- }),
57481
- [handleDragOver, handleDragLeave, handleDrop]
57482
- );
57483
- return { dropProps, isOver };
57484
- }
57485
57434
  var log16 = createLogger("almadar:ui:effects:client-handlers");
57486
57435
  function createClientEffectHandlers(options) {
57487
57436
  const { eventBus, slotSetter, navigate, notify, callService } = options;
@@ -59094,6 +59043,128 @@ function BrowserPlayground({
59094
59043
  // components/molecules/avl/OrbPreviewNode.tsx
59095
59044
  init_useEventBus();
59096
59045
 
59046
+ // components/molecules/avl/useCanvasDnd.tsx
59047
+ init_useEventBus();
59048
+ init_useAlmadarDndCollision();
59049
+ var log18 = createLogger("almadar:ui:canvas-dnd");
59050
+ function useCanvasDraggable({
59051
+ id,
59052
+ payload,
59053
+ disabled
59054
+ }) {
59055
+ const { setNodeRef, attributes, listeners: listeners6, isDragging, transform } = useDraggable({
59056
+ id,
59057
+ data: { payload },
59058
+ disabled
59059
+ });
59060
+ const style = {
59061
+ transform: CSS.Translate.toString(transform),
59062
+ cursor: disabled ? "not-allowed" : isDragging ? "grabbing" : "grab",
59063
+ opacity: isDragging ? 0.5 : 1,
59064
+ touchAction: "none"
59065
+ };
59066
+ return { setNodeRef, attributes, listeners: listeners6, isDragging, style };
59067
+ }
59068
+ var DEFAULT_ACCEPTS = ["pattern", "behavior"];
59069
+ function useCanvasDroppable({
59070
+ id,
59071
+ target,
59072
+ accepts,
59073
+ disabled
59074
+ }) {
59075
+ const acceptsList = accepts ?? DEFAULT_ACCEPTS;
59076
+ const { setNodeRef, isOver } = useDroppable({
59077
+ id,
59078
+ data: { target, accepts: acceptsList },
59079
+ disabled
59080
+ });
59081
+ return { setNodeRef, isOver };
59082
+ }
59083
+ function defaultEmit(eventBus, drop) {
59084
+ const { payload, target, resolved } = drop;
59085
+ if (payload.kind === "pattern") {
59086
+ const patternType = payload.data.type;
59087
+ if (typeof patternType !== "string") {
59088
+ log18.warn("default-emit:pattern:missing-type");
59089
+ return;
59090
+ }
59091
+ const out = { patternType, containerNode: target.containerNode };
59092
+ if (resolved) {
59093
+ out.parentPath = resolved.parentPath;
59094
+ out.index = resolved.index;
59095
+ }
59096
+ eventBus.emit("UI:PATTERN_DROP", out);
59097
+ log18.info("default-emit:pattern", { patternType, level: target.level });
59098
+ return;
59099
+ }
59100
+ if (payload.kind === "behavior") {
59101
+ const behaviorName = payload.data.name;
59102
+ if (typeof behaviorName !== "string") {
59103
+ log18.warn("default-emit:behavior:missing-name");
59104
+ return;
59105
+ }
59106
+ eventBus.emit("UI:BEHAVIOR_DROP", {
59107
+ behaviorName,
59108
+ containerNode: target.containerNode
59109
+ });
59110
+ log18.info("default-emit:behavior", { behaviorName, level: target.level });
59111
+ return;
59112
+ }
59113
+ log18.debug("default-emit:unhandled-kind", { kind: payload.kind });
59114
+ }
59115
+ function CanvasDndProvider({ children, onDrop }) {
59116
+ const eventBus = useEventBus();
59117
+ const sensors = useAlmadarDndSensors(false);
59118
+ const handleDragStart = React93__default.useCallback((e) => {
59119
+ const data = e.active.data.current;
59120
+ const payload = data?.payload;
59121
+ if (payload) {
59122
+ eventBus.emit("UI:DRAG_START", { kind: payload.kind, data: payload.data });
59123
+ log18.info("dragStart", { id: e.active.id, kind: payload.kind });
59124
+ } else {
59125
+ log18.warn("dragStart:missing-payload", { id: e.active.id });
59126
+ }
59127
+ }, [eventBus]);
59128
+ const handleDragEnd = React93__default.useCallback((e) => {
59129
+ const activeData = e.active.data.current;
59130
+ const payload = activeData?.payload;
59131
+ const overData = e.over?.data.current;
59132
+ const target = overData?.target;
59133
+ const accepts = overData?.accepts;
59134
+ log18.info("dragEnd", {
59135
+ activeId: e.active.id,
59136
+ overId: e.over?.id,
59137
+ hasPayload: !!payload,
59138
+ hasTarget: !!target,
59139
+ targetLevel: target?.level
59140
+ });
59141
+ if (payload) {
59142
+ eventBus.emit("UI:DRAG_END", { kind: payload.kind, data: payload.data });
59143
+ }
59144
+ if (!payload || !target) return;
59145
+ if (accepts && !accepts.includes(payload.kind)) {
59146
+ log18.debug("dragEnd:rejected:kind", { kind: payload.kind, accepts: [...accepts] });
59147
+ return;
59148
+ }
59149
+ const activator = e.activatorEvent;
59150
+ const cursor = activator && typeof activator.clientX === "number" && typeof activator.clientY === "number" ? { x: activator.clientX + e.delta.x, y: activator.clientY + e.delta.y } : null;
59151
+ const resolved = target.resolvePath && cursor ? target.resolvePath(cursor) : null;
59152
+ const drop = { payload, target, cursor, resolved };
59153
+ const suppressed = onDrop ? onDrop(drop) === true : false;
59154
+ if (!suppressed) defaultEmit(eventBus, drop);
59155
+ }, [eventBus, onDrop]);
59156
+ return /* @__PURE__ */ jsx(
59157
+ DndContext,
59158
+ {
59159
+ sensors,
59160
+ collisionDetection: almadarDndCollisionDetection,
59161
+ onDragStart: handleDragStart,
59162
+ onDragEnd: handleDragEnd,
59163
+ children
59164
+ }
59165
+ );
59166
+ }
59167
+
59097
59168
  // components/molecules/avl/wire-validation.ts
59098
59169
  function validateWire(sourcePayload, targetPayload) {
59099
59170
  const warnings = [];
@@ -59442,105 +59513,74 @@ var OrbPreviewNodeInner = (props) => {
59442
59513
  unsub2();
59443
59514
  };
59444
59515
  }, [eventBus]);
59445
- const handlePreviewDrop = useCallback((e) => {
59446
- e.preventDefault();
59447
- e.stopPropagation();
59448
- setDragActive(false);
59449
- contentRef.current?.querySelectorAll(".drag-hover, .drop-indicator").forEach((el2) => {
59450
- el2.classList.remove("drag-hover");
59451
- if (el2.classList.contains("drop-indicator")) el2.remove();
59452
- });
59453
- const raw = e.dataTransfer.getData(ALMADAR_DND_MIME);
59454
- if (!raw) return;
59455
- let payload;
59456
- try {
59457
- payload = JSON.parse(raw);
59458
- } catch {
59459
- return;
59460
- }
59461
- if (payload.kind !== "pattern") return;
59462
- let el = e.target;
59463
- while (el && el.dataset.acceptsChildren !== "true") {
59464
- el = el.parentElement;
59465
- if (!el || el === contentRef.current) break;
59466
- }
59467
- const containerNode = {
59468
- orbitalName: data.orbitalName,
59469
- traitName: data.traitName,
59470
- transitionEvent: data.transitionEvent
59471
- };
59472
- const containerPath = el?.dataset?.patternPath;
59473
- if (!containerPath) {
59474
- eventBus.emit("UI:PATTERN_DROP", {
59475
- parentPath: "root",
59476
- patternType: payload.data.type,
59477
- index: 0,
59478
- containerNode
59479
- });
59480
- return;
59481
- }
59482
- const pathChildren = el.querySelectorAll(":scope > [data-pattern-path]");
59483
- let insertIndex = pathChildren.length;
59484
- for (let i = 0; i < pathChildren.length; i++) {
59485
- const rect = pathChildren[i].getBoundingClientRect();
59516
+ const resolveL2Path = useCallback(
59517
+ (cursor) => {
59518
+ const hit = document.elementFromPoint(cursor.x, cursor.y);
59519
+ if (!hit) return null;
59520
+ let el = hit;
59521
+ while (el && el.dataset.acceptsChildren !== "true") {
59522
+ if (el === contentRef.current) break;
59523
+ el = el.parentElement;
59524
+ }
59525
+ if (!el) return null;
59526
+ const containerPath = el.dataset?.patternPath;
59527
+ if (!containerPath) return { parentPath: "root", index: 0 };
59528
+ const pathChildren = el.querySelectorAll(":scope > [data-pattern-path]");
59529
+ let insertIndex = pathChildren.length;
59486
59530
  const style = el.firstElementChild ? getComputedStyle(el.firstElementChild) : null;
59487
59531
  const isVertical = style?.flexDirection !== "row";
59488
- const mid = isVertical ? rect.top + rect.height / 2 : rect.left + rect.width / 2;
59489
- const cursor = isVertical ? e.clientY : e.clientX;
59490
- if (cursor < mid) {
59491
- insertIndex = i;
59492
- break;
59532
+ for (let i = 0; i < pathChildren.length; i++) {
59533
+ const rect = pathChildren[i].getBoundingClientRect();
59534
+ const mid = isVertical ? rect.top + rect.height / 2 : rect.left + rect.width / 2;
59535
+ const pos = isVertical ? cursor.y : cursor.x;
59536
+ if (pos < mid) {
59537
+ insertIndex = i;
59538
+ break;
59539
+ }
59493
59540
  }
59494
- }
59495
- eventBus.emit("UI:PATTERN_DROP", {
59496
- parentPath: containerPath,
59497
- patternType: payload.data.type,
59498
- index: insertIndex,
59499
- containerNode
59500
- });
59501
- }, [eventBus, data.orbitalName, data.traitName, data.transitionEvent]);
59502
- const handlePreviewDragOver = useCallback((e) => {
59503
- if (!e.dataTransfer.types.includes(ALMADAR_DND_MIME)) return;
59504
- e.preventDefault();
59505
- e.stopPropagation();
59506
- e.dataTransfer.dropEffect = "copy";
59507
- if (!dragActive) setDragActive(true);
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
- contentRef.current?.querySelectorAll(".drag-hover").forEach((c) => c.classList.remove("drag-hover"));
59514
- if (el?.dataset?.acceptsChildren === "true") {
59515
- el.classList.add("drag-hover");
59516
- }
59517
- }, [dragActive]);
59518
- const handlePreviewDragLeave = useCallback((e) => {
59519
- contentRef.current?.querySelectorAll(".drag-hover").forEach((c) => c.classList.remove("drag-hover"));
59520
- }, []);
59541
+ return { parentPath: containerPath, index: insertIndex };
59542
+ },
59543
+ []
59544
+ );
59545
+ const l2Target = useMemo(
59546
+ () => ({
59547
+ level: "l2",
59548
+ containerNode: {
59549
+ orbitalName: data.orbitalName,
59550
+ traitName: data.traitName,
59551
+ transitionEvent: data.transitionEvent
59552
+ },
59553
+ resolvePath: resolveL2Path
59554
+ }),
59555
+ [data.orbitalName, data.traitName, data.transitionEvent, resolveL2Path]
59556
+ );
59557
+ const { setNodeRef: l2SetNodeRef, isOver: l2IsOver } = useCanvasDroppable({
59558
+ id: `orb-l2-${data.orbitalName}-${data.traitName ?? ""}-${data.transitionEvent ?? ""}`,
59559
+ target: l2Target,
59560
+ accepts: ["pattern"],
59561
+ disabled: !isExpanded
59562
+ });
59563
+ const setContentRef = useCallback((el) => {
59564
+ contentRef.current = el;
59565
+ l2SetNodeRef(el);
59566
+ }, [l2SetNodeRef]);
59521
59567
  const statusBorder = isRunning ? "var(--color-primary)" : isError ? "var(--color-danger)" : isSuccess ? "var(--color-success)" : null;
59522
59568
  const borderWidth = isRunning || isError || isSuccess ? "2px" : "1.5px";
59523
59569
  const borderColor = statusBorder ?? (hovered ? "var(--color-primary)" : colors.border);
59524
- const handleL1Drop = useCallback(
59525
- (payload) => {
59526
- if (payload.kind !== "pattern") return;
59527
- if (typeof payload.data.type !== "string") return;
59528
- eventBus.emit("UI:PATTERN_DROP", {
59529
- patternType: payload.data.type,
59530
- containerNode: { orbitalName: data.orbitalName }
59531
- });
59532
- },
59533
- [eventBus, data.orbitalName]
59570
+ const l1Target = useMemo(
59571
+ () => ({ level: "l1", containerNode: { orbitalName: data.orbitalName } }),
59572
+ [data.orbitalName]
59534
59573
  );
59535
- const { dropProps: l1DropProps, isOver: l1IsOver } = useDropZone({
59574
+ const { setNodeRef: l1SetNodeRef, isOver: l1IsOver } = useCanvasDroppable({
59575
+ id: `orb-l1-${data.orbitalName}`,
59576
+ target: l1Target,
59536
59577
  accepts: ["pattern"],
59537
- onDrop: handleL1Drop,
59538
59578
  disabled: isExpanded
59539
59579
  });
59540
59580
  return /* @__PURE__ */ jsxs(
59541
59581
  Box,
59542
59582
  {
59543
- ...isExpanded ? {} : l1DropProps,
59583
+ ref: isExpanded ? void 0 : l1SetNodeRef,
59544
59584
  className: `rounded-lg border shadow-sm bg-card transition-all duration-200 overflow-hidden relative${isRunning ? " orb-preview-running" : ""}`,
59545
59585
  style: {
59546
59586
  borderColor: l1IsOver ? "var(--color-primary)" : borderColor,
@@ -59682,12 +59722,9 @@ var OrbPreviewNodeInner = (props) => {
59682
59722
  /* @__PURE__ */ jsx(
59683
59723
  Box,
59684
59724
  {
59685
- ref: contentRef,
59686
- className: `orb-preview-live nodrag${dragActive ? " drag-active" : ""}`,
59725
+ ref: setContentRef,
59726
+ className: `orb-preview-live nodrag${dragActive || l2IsOver ? " drag-active" : ""}`,
59687
59727
  onClick: handleContentClick,
59688
- onDrop: handlePreviewDrop,
59689
- onDragOver: handlePreviewDragOver,
59690
- onDragLeave: handlePreviewDragLeave,
59691
59728
  children: orbitalSchema ? /* @__PURE__ */ jsx(Box, { style: { minHeight: preset.minHeight }, children: /* @__PURE__ */ jsx(
59692
59729
  BrowserPlayground,
59693
59730
  {
@@ -61183,7 +61220,7 @@ init_AvlTransitionLane();
61183
61220
  init_AvlSwimLane();
61184
61221
  init_types();
61185
61222
  init_avl_elk_layout();
61186
- var log18 = createLogger("almadar:ui:avl:trait-scene");
61223
+ var log19 = createLogger("almadar:ui:avl:trait-scene");
61187
61224
  var SWIM_GUTTER2 = 120;
61188
61225
  var CENTER_W2 = 360;
61189
61226
  var AvlTraitScene = ({
@@ -61195,7 +61232,7 @@ var AvlTraitScene = ({
61195
61232
  const dataKey = useMemo(() => JSON.stringify(data), [data]);
61196
61233
  useEffect(() => {
61197
61234
  computeTraitLayout(data).then(setLayout).catch((error) => {
61198
- log18.error("computeTraitLayout failed", { error: error instanceof Error ? error : String(error) });
61235
+ log19.error("computeTraitLayout failed", { error: error instanceof Error ? error : String(error) });
61199
61236
  });
61200
61237
  }, [dataKey]);
61201
61238
  if (!layout) {
@@ -62337,4 +62374,4 @@ AvlClickTarget.displayName = "AvlClickTarget";
62337
62374
  // components/organisms/avl/index.ts
62338
62375
  init_avl_schema_parser();
62339
62376
 
62340
- export { AVL_FIELD_TYPE_SHAPES, AVL_OPERATOR_COLORS, AvlApplication, AvlBackwardEdge, AvlBehaviorGlyph, AvlBinding, AvlBindingEdge, AvlBindingRef, AvlClickTarget, AvlClosedCircuit, AvlCosmicZoom, AvlEffect, AvlEmitListen, AvlEntity, AvlEvent, AvlEventWireEdge, AvlExprTree, AvlField, AvlFieldType, AvlGuard, AvlLiteral, AvlOperator, AvlOrbital, AvlOrbitalNode, AvlOrbitalUnit, AvlOrbitalsCosmicZoom, AvlPage, AvlPageEdge, AvlPersistence, AvlSExpr, AvlSlotMap, AvlState, AvlStateMachine, AvlSwimLane, AvlTrait, AvlTraitScene, AvlTransition, AvlTransitionEdge, AvlTransitionLane, AvlTransitionScene, BehaviorComposeNode, BehaviorView, CONNECTION_COLORS, DOMAIN_COLORS, DetailView, EFFECT_CATEGORY_COLORS, EFFECT_TYPE_TO_CATEGORY, EventFlowEdge, FlowCanvas, MiniStateMachine, ModuleCard, OrbInspector, OrbPreviewNode, STATE_COLORS, SystemNode, ZOOM_BAND_THRESHOLDS, ZoomBandContext, ZoomBreadcrumb, ZoomLegend, arcPath, behaviorsToComposeGraph, computeTraitLayout, computeZoomBand, curveControlPoint, edgePath, getStateRole, gridPositions, orbitalToExpandedGraph, parseApplicationLevel, parseOrbitalLevel, parseTraitLevel, parseTransitionLevel, radialPositions, registryEntryToCanvasEntry, ringPositions, schemaToFlowGraph, schemaToOverviewGraph, useZoomBand, zoomProgress };
62377
+ export { AVL_FIELD_TYPE_SHAPES, AVL_OPERATOR_COLORS, AvlApplication, AvlBackwardEdge, AvlBehaviorGlyph, AvlBinding, AvlBindingEdge, AvlBindingRef, AvlClickTarget, AvlClosedCircuit, AvlCosmicZoom, AvlEffect, AvlEmitListen, AvlEntity, AvlEvent, AvlEventWireEdge, AvlExprTree, AvlField, AvlFieldType, AvlGuard, AvlLiteral, AvlOperator, AvlOrbital, AvlOrbitalNode, AvlOrbitalUnit, AvlOrbitalsCosmicZoom, AvlPage, AvlPageEdge, AvlPersistence, AvlSExpr, AvlSlotMap, AvlState, AvlStateMachine, AvlSwimLane, AvlTrait, AvlTraitScene, AvlTransition, AvlTransitionEdge, AvlTransitionLane, AvlTransitionScene, BehaviorComposeNode, BehaviorView, CONNECTION_COLORS, CanvasDndProvider, DOMAIN_COLORS, DetailView, EFFECT_CATEGORY_COLORS, EFFECT_TYPE_TO_CATEGORY, EventFlowEdge, FlowCanvas, MiniStateMachine, ModuleCard, OrbInspector, OrbPreviewNode, STATE_COLORS, SystemNode, ZOOM_BAND_THRESHOLDS, ZoomBandContext, ZoomBreadcrumb, ZoomLegend, arcPath, behaviorsToComposeGraph, computeTraitLayout, computeZoomBand, curveControlPoint, edgePath, getStateRole, gridPositions, orbitalToExpandedGraph, parseApplicationLevel, parseOrbitalLevel, parseTraitLevel, parseTransitionLevel, radialPositions, registryEntryToCanvasEntry, ringPositions, schemaToFlowGraph, schemaToOverviewGraph, useCanvasDraggable, useCanvasDroppable, useZoomBand, zoomProgress };
@@ -20073,6 +20073,31 @@ var init_DashboardLayout = __esm({
20073
20073
  NavLink.displayName = "NavLink";
20074
20074
  }
20075
20075
  });
20076
+ function useAlmadarDndSensors(withSortableKeyboard = true) {
20077
+ return core$1.useSensors(
20078
+ core$1.useSensor(core$1.PointerSensor, {
20079
+ activationConstraint: { distance: ALMADAR_DND_ACTIVATION_DISTANCE }
20080
+ }),
20081
+ core$1.useSensor(
20082
+ core$1.KeyboardSensor,
20083
+ withSortableKeyboard ? { coordinateGetter: sortable.sortableKeyboardCoordinates } : void 0
20084
+ )
20085
+ );
20086
+ }
20087
+ var ALMADAR_DND_ACTIVATION_DISTANCE, almadarDndCollisionDetection;
20088
+ var init_useAlmadarDndCollision = __esm({
20089
+ "hooks/useAlmadarDndCollision.ts"() {
20090
+ "use client";
20091
+ ALMADAR_DND_ACTIVATION_DISTANCE = 5;
20092
+ almadarDndCollisionDetection = (args) => {
20093
+ const pw = core$1.pointerWithin(args);
20094
+ if (pw.length > 0) return pw;
20095
+ const ri = core$1.rectIntersection(args);
20096
+ if (ri.length > 0) return ri;
20097
+ return core$1.closestCorners(args);
20098
+ };
20099
+ }
20100
+ });
20076
20101
  function useDataDnd(args) {
20077
20102
  const {
20078
20103
  dragGroup,
@@ -20168,25 +20193,8 @@ function useDataDnd(args) {
20168
20193
  dndLog.debug("zone:unregister", { zoneId, group: meta.group });
20169
20194
  };
20170
20195
  }, [parentRoot, isRoot, zoneId, meta]);
20171
- const sensors = core$1.useSensors(
20172
- core$1.useSensor(core$1.PointerSensor, { activationConstraint: { distance: 5 } }),
20173
- core$1.useSensor(core$1.KeyboardSensor, { coordinateGetter: sortable.sortableKeyboardCoordinates })
20174
- );
20175
- const collisionDetection = React75__namespace.default.useCallback((args2) => {
20176
- const pointerCollisions = core$1.pointerWithin(args2);
20177
- if (pointerCollisions.length > 0) {
20178
- dndLog.debug("collision:pointerWithin", { count: pointerCollisions.length, ids: pointerCollisions.map((c) => c.id) });
20179
- return pointerCollisions;
20180
- }
20181
- const rectCollisions = core$1.rectIntersection(args2);
20182
- if (rectCollisions.length > 0) {
20183
- dndLog.debug("collision:rectIntersection", { count: rectCollisions.length, ids: rectCollisions.map((c) => c.id) });
20184
- return rectCollisions;
20185
- }
20186
- const cornerCollisions = core$1.closestCorners(args2);
20187
- dndLog.debug("collision:closestCorners", { count: cornerCollisions.length, ids: cornerCollisions.map((c) => c.id) });
20188
- return cornerCollisions;
20189
- }, []);
20196
+ const sensors = useAlmadarDndSensors(true);
20197
+ const collisionDetection = almadarDndCollisionDetection;
20190
20198
  const findZoneByItem = React75__namespace.default.useCallback(
20191
20199
  (id) => {
20192
20200
  for (const z of zonesRef.current.values()) {
@@ -20523,6 +20531,7 @@ var init_useDataDnd = __esm({
20523
20531
  "components/molecules/useDataDnd.tsx"() {
20524
20532
  "use client";
20525
20533
  init_useEventBus();
20534
+ init_useAlmadarDndCollision();
20526
20535
  init_Box();
20527
20536
  dndLog = logger.createLogger("almadar:ui:dnd");
20528
20537
  RootCtx = React75__namespace.default.createContext(null);
@@ -34190,6 +34199,7 @@ var init_Form = __esm({
34190
34199
  submitLabel,
34191
34200
  cancelLabel,
34192
34201
  showCancel,
34202
+ showSubmit = true,
34193
34203
  title,
34194
34204
  submitEvent = "SAVE",
34195
34205
  cancelEvent = "CANCEL",
@@ -34676,8 +34686,8 @@ var init_Form = __esm({
34676
34686
  sectionElements && sectionElements.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(exports.VStack, { gap: gap === "sm" ? "sm" : gap === "lg" ? "lg" : "md", children: sectionElements }),
34677
34687
  schemaFields,
34678
34688
  children,
34679
- (schemaFields && schemaFields.length > 0 || sectionElements && sectionElements.length > 0) && /* @__PURE__ */ jsxRuntime.jsxs(exports.HStack, { gap: "sm", className: "pt-4", children: [
34680
- /* @__PURE__ */ jsxRuntime.jsx(
34689
+ (schemaFields && schemaFields.length > 0 || sectionElements && sectionElements.length > 0) && (showSubmit || shouldShowCancel) && /* @__PURE__ */ jsxRuntime.jsxs(exports.HStack, { gap: "sm", className: "pt-4", children: [
34690
+ showSubmit && /* @__PURE__ */ jsxRuntime.jsx(
34681
34691
  exports.Button,
34682
34692
  {
34683
34693
  type: "submit",