@almadar/ui 6.51.2 → 6.53.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.
Files changed (127) hide show
  1. package/dist/{EntityBindingContext-BbxrwSb9.d.ts → AwaitingSkeletonContext-Bh399p1x.d.ts} +17 -2
  2. package/dist/{Canvas3DHost-CLC_jXh_.d.ts → Canvas3DHost-B-y2TNij.d.ts} +1 -1
  3. package/dist/{FileTree-RKQqRhIM.d.ts → FileTree-DUi7e7Z8.d.ts} +5 -5
  4. package/dist/{GameAudioProvider-BgWLggIy.d.ts → GameAudioProvider-DyBvYP2c.d.ts} +1 -1
  5. package/dist/{NavStackContext-B-XLULCO.d.ts → NavStackContext-04NLdXsY.d.ts} +8 -0
  6. package/dist/Typography-JGSDH4JP.js +5 -0
  7. package/dist/{UISlotContext-DNM8iXna.d.ts → UISlotContext-CS487Uoc.d.ts} +1 -1
  8. package/dist/{UISlotRenderer-7UYHFW4S.js → UISlotRenderer-JT34I3O7.js} +9 -9
  9. package/dist/avl/index.cjs +39958 -38525
  10. package/dist/avl/index.d.ts +8 -5
  11. package/dist/avl/index.js +37 -26
  12. package/dist/{chunk-JXUYEO7U.js → chunk-2LFBQ4IS.js} +7 -1
  13. package/dist/{chunk-GIPZSCND.js → chunk-3EF5SDIJ.js} +31157 -31206
  14. package/dist/{chunk-GHXWGQTX.js → chunk-4OZDHCZV.js} +1 -1
  15. package/dist/{chunk-HQDKHLFG.js → chunk-64WACXM7.js} +15 -1
  16. package/dist/{chunk-FGHRVJCI.js → chunk-6O37FCX4.js} +13 -2
  17. package/dist/{chunk-BUEIZY54.js → chunk-7LM6I3NA.js} +8 -7
  18. package/dist/chunk-CBIJP5PL.js +284 -0
  19. package/dist/{chunk-MWPX2O4M.js → chunk-GMDMOYXD.js} +3 -16
  20. package/dist/{chunk-YKHNK5JH.js → chunk-GODZKHAL.js} +11 -4
  21. package/dist/{chunk-T7IH5ABO.js → chunk-IKULQIDX.js} +199 -88
  22. package/dist/{chunk-NTO555KF.js → chunk-JRW33U35.js} +183 -62
  23. package/dist/{chunk-OLZ3EEML.js → chunk-KQXXO42S.js} +106 -90
  24. package/dist/chunk-OKWD7LPO.js +80 -0
  25. package/dist/{chunk-YHY5K2Y7.js → chunk-PEST66PN.js} +6 -0
  26. package/dist/{chunk-L55SAFKL.js → chunk-UGHAADU5.js} +77 -1
  27. package/dist/{chunk-6CFYRP4S.js → chunk-VHTJRS2N.js} +4 -8
  28. package/dist/{chunk-R4V7IZQP.js → chunk-WPNM2KC6.js} +2 -2
  29. package/dist/{cn-CO-0rolG.d.ts → cn-ClXGlIOY.d.ts} +2 -2
  30. package/dist/components/index.cjs +46084 -44766
  31. package/dist/components/index.d.ts +645 -699
  32. package/dist/components/index.js +621 -13
  33. package/dist/context/index.cjs +20 -7
  34. package/dist/context/index.d.ts +3 -3
  35. package/dist/context/index.js +3 -3
  36. package/dist/hooks/index.cjs +126 -9
  37. package/dist/hooks/index.d.ts +32 -7
  38. package/dist/hooks/index.js +7 -7
  39. package/dist/lib/drawable/three/index.cjs +79 -2
  40. package/dist/lib/drawable/three/index.d.ts +3 -3
  41. package/dist/lib/drawable/three/index.js +7 -7
  42. package/dist/lib/index.cjs +116 -2
  43. package/dist/lib/index.d.ts +29 -6
  44. package/dist/lib/index.js +6 -5
  45. package/dist/locales/index.cjs +231 -3
  46. package/dist/locales/index.js +155 -3
  47. package/dist/{paintDispatch-CMgOyVjS.d.ts → paintDispatch-_6EhJCiL.d.ts} +6 -6
  48. package/dist/providers/index.cjs +36404 -35028
  49. package/dist/providers/index.d.ts +34 -9
  50. package/dist/providers/index.js +82 -19
  51. package/dist/renderer/index.cjs +6 -0
  52. package/dist/renderer/index.d.ts +1 -1
  53. package/dist/renderer/index.js +1 -1
  54. package/dist/runtime/index.cjs +37861 -36437
  55. package/dist/runtime/index.d.ts +6 -4
  56. package/dist/runtime/index.js +11 -11
  57. package/dist/ssr/index.cjs +584 -181
  58. package/dist/ssr/index.d.cts +36 -44
  59. package/dist/ssr/index.d.ts +36 -44
  60. package/dist/ssr/index.js +527 -124
  61. package/dist/{themeTokens-CN9WCXQc.d.ts → themeTokens-Ccu7EmGY.d.ts} +4 -2
  62. package/dist/{useUISlots-CwUWM1ra.d.ts → useUISlots-1dk2TR4j.d.ts} +1 -9
  63. package/dist/{verificationRegistry-DBHfOR9y.d.ts → verificationRegistry-CD7Xb40L.d.ts} +1 -1
  64. package/locales/ar.json +77 -1
  65. package/locales/en.json +77 -1
  66. package/locales/sl.json +77 -1
  67. package/package.json +13 -10
  68. package/tailwind-preset.cjs +37 -1
  69. package/themes/_base.css +114 -8
  70. package/themes/_contract.md +6 -0
  71. package/themes/almadar-website.css +2 -0
  72. package/themes/almadar.css +2 -0
  73. package/themes/aqua.css +5 -3
  74. package/themes/arabesque.css +9 -7
  75. package/themes/art-deco.css +5 -3
  76. package/themes/art-nouveau.css +4 -0
  77. package/themes/atelier.css +10 -8
  78. package/themes/bauhaus.css +2 -0
  79. package/themes/bloomberg-dense.css +13 -11
  80. package/themes/blueprint.css +2 -0
  81. package/themes/clay.css +2 -0
  82. package/themes/comic.css +12 -10
  83. package/themes/constructivist.css +2 -0
  84. package/themes/corporate.css +4 -2
  85. package/themes/cyberpunk.css +2 -0
  86. package/themes/frutiger-aero.css +2 -0
  87. package/themes/game-adventure.css +1 -0
  88. package/themes/game-rpg.css +1 -0
  89. package/themes/game-sci-fi.css +1 -0
  90. package/themes/game-ui-pack.css +1 -0
  91. package/themes/gazette.css +10 -8
  92. package/themes/glass.css +17 -15
  93. package/themes/gothic.css +2 -0
  94. package/themes/ink-wash.css +2 -0
  95. package/themes/kawaii.css +2 -0
  96. package/themes/kiosk.css +17 -15
  97. package/themes/linear-clean.css +12 -10
  98. package/themes/luxury.css +2 -0
  99. package/themes/mac-classic.css +2 -0
  100. package/themes/material.css +2 -0
  101. package/themes/memphis.css +2 -0
  102. package/themes/mid-century.css +2 -0
  103. package/themes/minimalist.css +2 -0
  104. package/themes/mudcloth.css +2 -0
  105. package/themes/neon.css +2 -0
  106. package/themes/neumorphic.css +2 -0
  107. package/themes/newsprint.css +2 -0
  108. package/themes/notion-editorial.css +12 -10
  109. package/themes/pixel.css +2 -0
  110. package/themes/prism.css +20 -18
  111. package/themes/retro.css +2 -0
  112. package/themes/risograph.css +2 -0
  113. package/themes/scandi.css +2 -0
  114. package/themes/sketch.css +2 -0
  115. package/themes/solarpunk.css +2 -0
  116. package/themes/steampunk.css +2 -0
  117. package/themes/swiss.css +2 -0
  118. package/themes/terminal.css +8 -6
  119. package/themes/trait-wars.css +2 -0
  120. package/themes/ukiyo-e.css +2 -0
  121. package/themes/vaporwave.css +2 -0
  122. package/themes/victorian.css +2 -0
  123. package/themes/wabi-sabi.css +2 -0
  124. package/themes/win95.css +2 -0
  125. package/themes/wireframe.css +2 -0
  126. package/themes/zine.css +2 -0
  127. package/dist/Typography-2Z3JKWHN.js +0 -5
@@ -1,9 +1,9 @@
1
1
  import { OperatorCategory } from '@almadar/std';
2
2
  import * as React$1 from 'react';
3
3
  import React__default from 'react';
4
- import { FieldType, EntityPersistence, SExpr, EvalTrace, EventEmit, Expression, UISlot, OrbitalSchema, EntityData, EditFocus, EventPayload, DomainQuestion, DomainQuestionAnswer, ThemeDefinition, CircuitStepResult, GuardEvaluation, EffectTrace } from '@almadar/core';
5
- import { A as AvlNodeData, F as FileTreeItem } from '../FileTree-RKQqRhIM.js';
6
- export { a as AvlEdgeData, b as AvlStateMachine, c as AvlStateMachineProps, B as BehaviorView, M as ModuleCard, s as schemaToFlowGraph } from '../FileTree-RKQqRhIM.js';
4
+ import { FieldType, EntityPersistence, SExpr, EvalTrace, A11yProps, EventEmit, Expression, UISlot, OrbitalSchema, EntityData, EditFocus, EventPayload, AriaRole, DomainQuestion, DomainQuestionAnswer, ThemeDefinition, CircuitStepResult, GuardEvaluation, EffectTrace } from '@almadar/core';
5
+ import { A as AvlNodeData, F as FileTreeItem } from '../FileTree-DUi7e7Z8.js';
6
+ export { a as AvlEdgeData, b as AvlStateMachine, c as AvlStateMachineProps, B as BehaviorView, M as ModuleCard, s as schemaToFlowGraph } from '../FileTree-DUi7e7Z8.js';
7
7
  import { T as TraitLevelData, d as TraitTransitionInfo, c as TransitionLevelData } from '../avl-schema-parser-C0wnAp5x.js';
8
8
  export { A as ApplicationLevelData, C as CrossLink, b as OrbitalLevelData, p as parseApplicationLevel, e as parseOrbitalLevel, f as parseTraitLevel, g as parseTransitionLevel, t as traitLevelFromTrait } from '../avl-schema-parser-C0wnAp5x.js';
9
9
  import { NodeProps, EdgeProps, Edge, Node, NodeTypes, ReactFlowProps } from '@xyflow/react';
@@ -254,7 +254,7 @@ declare const AvlCircuit: React__default.FC<AvlCircuitProps>;
254
254
 
255
255
  declare const AVL_GLYPH_KINDS: readonly ["application", "orbital", "entity", "trait", "page", "state", "transition", "event", "guard", "effect", "field", "fieldType", "binding", "bindingRef", "persistence", "operator", "sexpr", "literal"];
256
256
  type AvlGlyphKind = (typeof AVL_GLYPH_KINDS)[number];
257
- interface AvlGlyphProps {
257
+ interface AvlGlyphProps extends Omit<React__default.AriaAttributes, keyof A11yProps>, A11yProps {
258
258
  /** Which notation symbol to draw.
259
259
  * @example "state"
260
260
  */
@@ -1213,7 +1213,10 @@ interface UseCanvasDraggableArgs {
1213
1213
  }
1214
1214
  interface UseCanvasDraggableResult {
1215
1215
  setNodeRef: (node: HTMLElement | null) => void;
1216
- attributes: ReturnType<typeof useDraggable>['attributes'];
1216
+ /** dnd-kit's attributes, with `role` narrowed to a declared ARIA role so they spread onto a core `Box`. */
1217
+ attributes: Omit<ReturnType<typeof useDraggable>['attributes'], 'role'> & {
1218
+ role?: AriaRole;
1219
+ };
1217
1220
  listeners: ReturnType<typeof useDraggable>['listeners'];
1218
1221
  isDragging: boolean;
1219
1222
  /** Spread on the tile — live transform + grab cursor + touch-action. */
package/dist/avl/index.js CHANGED
@@ -1,28 +1,29 @@
1
- import { BrowserPlayground, collectEmbeddedTraits } from '../chunk-T7IH5ABO.js';
2
- import { zoomReducer, initialZoomState, getBreadcrumbs } from '../chunk-R4V7IZQP.js';
3
- import { useTranslate as useTranslate$1 } from '../chunk-YKHNK5JH.js';
1
+ import { BrowserPlayground, collectEmbeddedTraits } from '../chunk-IKULQIDX.js';
2
+ import { zoomReducer, initialZoomState, getBreadcrumbs } from '../chunk-WPNM2KC6.js';
3
+ import { JsonTreeEditor } from '../chunk-CBIJP5PL.js';
4
+ import { useTranslate as useTranslate$1 } from '../chunk-GODZKHAL.js';
4
5
  import '../chunk-DQTV6QVS.js';
5
- import '../chunk-6CFYRP4S.js';
6
+ import '../chunk-VHTJRS2N.js';
6
7
  import { spacingTokenOf, positionOf, withPosition, snapToSpacingStep, defaultSpacingStepPx, spacingOf, withSizing, withSpacing, layoutOf, withLayout, sizingOf, DESIGN_COLOR_TOKENS, DESIGN_RADIUS_TOKENS, DESIGN_SPACING_SCALE, sizeLimitOf, withSizeLimit, isArbitraryClass, tokenOfDesignClass } from '../chunk-ERXIHZW3.js';
7
- import { Popover, Button, Icon, Select, Badge, IconButton, AvlStateMachine, Input, AvlFieldType, AvlEffect, AvlState, AvlPage, AvlEntity, useContainerWidth, useAlmadarDndSensors, almadarDndCollisionDetection, TagInput, Checkbox, Switch, CodeBlock, FileTree, Card, JsonTreeEditor, Accordion, RangeSlider, computeTraitLayout, edgePath, FormField, Radio, useCompactLayout, ButtonGroup, roundedEdgePath } from '../chunk-GIPZSCND.js';
8
- export { AvlEffect, AvlEntity, AvlFieldType, AvlPage, AvlState, AvlStateMachine, BehaviorView, FIELD_TYPE_SHAPES, MiniStateMachine, ModuleCard, computeTraitLayout, edgePath } from '../chunk-GIPZSCND.js';
9
- import { avlSeries, STATE_COLORS, Box, HStack, VStack, avlTint, CONNECTION_COLORS, parseTraitLevel, OPERATOR_CATEGORY_COLORS, AVL_INK, AVL_FONT, parseApplicationLevel, parseOrbitalLevel, getStateRole, effectCategoryOf, EFFECT_CATEGORY_COLORS, pressableProps, traitTransitionRenderUi, traitEventWires, effectZoneOf, avlBlend } from '../chunk-BUEIZY54.js';
10
- export { CONNECTION_COLORS, EFFECT_CATEGORY_COLORS, OPERATOR_CATEGORY_COLORS, STATE_COLORS, effectCategoryOf, getStateRole, parseApplicationLevel, parseOrbitalLevel, parseTraitLevel, parseTransitionLevel, traitLevelFromTrait } from '../chunk-BUEIZY54.js';
11
- import { Typography, INLINE_TEXT_ATTR } from '../chunk-MWPX2O4M.js';
12
- import { useMediaQuery } from '../chunk-NTO555KF.js';
8
+ import { Popover, Button, Icon, Select, Badge, IconButton, AvlStateMachine, Input, AvlFieldType, AvlEffect, AvlState, AvlPage, AvlEntity, useContainerWidth, useAlmadarDndSensors, almadarDndCollisionDetection, TagInput, Checkbox, Switch, CodeBlock, FileTree, Card, Accordion, RangeSlider, computeTraitLayout, edgePath, FormField, Radio, useCompactLayout, ButtonGroup, roundedEdgePath } from '../chunk-3EF5SDIJ.js';
9
+ export { AvlEffect, AvlEntity, AvlFieldType, AvlPage, AvlState, AvlStateMachine, BehaviorView, FIELD_TYPE_SHAPES, MiniStateMachine, ModuleCard, computeTraitLayout, edgePath } from '../chunk-3EF5SDIJ.js';
10
+ import { avlSeries, STATE_COLORS, Box, HStack, VStack, avlTint, CONNECTION_COLORS, parseTraitLevel, OPERATOR_CATEGORY_COLORS, AVL_INK, AVL_FONT, parseApplicationLevel, parseOrbitalLevel, getStateRole, effectCategoryOf, EFFECT_CATEGORY_COLORS, pressableProps, traitTransitionRenderUi, traitEventWires, effectZoneOf, avlBlend } from '../chunk-7LM6I3NA.js';
11
+ export { CONNECTION_COLORS, EFFECT_CATEGORY_COLORS, OPERATOR_CATEGORY_COLORS, STATE_COLORS, effectCategoryOf, getStateRole, parseApplicationLevel, parseOrbitalLevel, parseTraitLevel, parseTransitionLevel, traitLevelFromTrait } from '../chunk-7LM6I3NA.js';
12
+ import { Typography, INLINE_TEXT_ATTR } from '../chunk-GMDMOYXD.js';
13
+ import { usePrefersReducedMotion, useMediaQuery } from '../chunk-JRW33U35.js';
13
14
  import '../chunk-XJTHMW4G.js';
14
15
  import { useEventBus } from '../chunk-6EV3OEBQ.js';
15
- import { profilerOnRender, perfStart, perfEnd } from '../chunk-OLZ3EEML.js';
16
+ import { profilerOnRender, perfStart, perfEnd } from '../chunk-KQXXO42S.js';
16
17
  import { isEditableTarget } from '../chunk-O7OLVVBR.js';
17
- import { cn } from '../chunk-HQDKHLFG.js';
18
- import '../chunk-GHXWGQTX.js';
19
- import '../chunk-L55SAFKL.js';
18
+ import { domPassthrough, cn } from '../chunk-64WACXM7.js';
19
+ import '../chunk-4OZDHCZV.js';
20
+ import '../chunk-UGHAADU5.js';
20
21
  import '../chunk-PQKU62LK.js';
21
- import '../chunk-YHY5K2Y7.js';
22
+ import '../chunk-PEST66PN.js';
22
23
  import '../chunk-QPXIAUJD.js';
23
24
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
24
25
  import React19, { createContext, useContext, useState, useRef, useCallback, useMemo, useEffect, useLayoutEffect, Profiler, useReducer } from 'react';
25
- import { FieldTypeSchema, EFFECT_OPERATORS, isInlineTrait, isPageReference, navigatePatternPath, formatSExpr, answerToMutations, isBinding } from '@almadar/core';
26
+ import { FieldTypeSchema, EFFECT_OPERATORS, isInlineTrait, isPageReference, navigatePatternPath, isAriaRole, formatSExpr, answerToMutations, isBinding } from '@almadar/core';
26
27
  import { operatorVisualForm, getStdOperatorMeta } from '@almadar/std/registry';
27
28
  import { useTranslate } from '@almadar/ui/hooks';
28
29
  import { MarkerType, Handle, Position, useReactFlow, NodeResizeControl, ResizeControlVariant, getBezierPath, EdgeLabelRenderer, BaseEdge, ReactFlow, Controls, Background, BackgroundVariant, ReactFlowProvider, useNodesState, useEdgesState, useNodesInitialized } from '@xyflow/react';
@@ -1286,7 +1287,8 @@ function Symbol({ kind, label, effectType, fieldType, persistence, namespace })
1286
1287
  return /* @__PURE__ */ jsx(AvlLiteral, { value: label ?? "42", size: 14 });
1287
1288
  }
1288
1289
  }
1289
- var AvlGlyph = ({ kind, label, size: size2 = "md", showCaption = true, className, ...variant }) => {
1290
+ var AvlGlyph = ({ kind, label, size: size2 = "md", showCaption = true, className, effectType, fieldType, persistence, namespace, ...rest }) => {
1291
+ const variant = { effectType, fieldType, persistence, namespace };
1290
1292
  const { t } = useTranslate();
1291
1293
  const groupRef = useRef(null);
1292
1294
  const [box, setBox] = useState({ x: -50, y: -50, w: 100, h: 100 });
@@ -1297,7 +1299,7 @@ var AvlGlyph = ({ kind, label, size: size2 = "md", showCaption = true, className
1297
1299
  if (b.width > 0 && b.height > 0) setBox({ x: b.x - PAD2, y: b.y - PAD2, w: b.width + 2 * PAD2, h: b.height + 2 * PAD2 });
1298
1300
  }, [kind, label, variant.effectType, variant.fieldType, variant.persistence, variant.namespace]);
1299
1301
  const height = HEIGHT[size2];
1300
- return /* @__PURE__ */ jsxs(Box, { "data-testid": "avl-glyph", "data-kind": kind, className: `inline-flex flex-col items-center gap-1 ${className ?? ""}`, children: [
1302
+ return /* @__PURE__ */ jsxs(Box, { ...domPassthrough(rest), "data-testid": "avl-glyph", "data-kind": kind, className: `inline-flex flex-col items-center gap-1 ${className ?? ""}`, children: [
1301
1303
  /* @__PURE__ */ jsx("svg", { height, width: height * box.w / box.h, viewBox: `${box.x} ${box.y} ${box.w} ${box.h}`, role: "img", "aria-label": label ?? t(`avl.glyph.${kind}`), children: /* @__PURE__ */ jsx("g", { ref: groupRef, children: /* @__PURE__ */ jsx(Symbol, { kind, label, ...variant }) }) }),
1302
1304
  showCaption ? /* @__PURE__ */ jsx(Box, { "data-testid": "avl-glyph-caption", children: /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "muted", children: label ?? t(`avl.glyph.${kind}`) }) }) : null
1303
1305
  ] });
@@ -4515,7 +4517,14 @@ function useCanvasDraggable({
4515
4517
  opacity: isDragging ? 0.5 : 1,
4516
4518
  touchAction: "none"
4517
4519
  };
4518
- return { setNodeRef, attributes, listeners, isDragging, style };
4520
+ const { role, ...ariaAttributes } = attributes;
4521
+ return {
4522
+ setNodeRef,
4523
+ attributes: { ...ariaAttributes, ...isAriaRole(role) ? { role } : {} },
4524
+ listeners,
4525
+ isDragging,
4526
+ style
4527
+ };
4519
4528
  }
4520
4529
  var DEFAULT_ACCEPTS = ["pattern", "behavior"];
4521
4530
  function useCanvasDroppable({
@@ -5126,6 +5135,7 @@ var OrbPreviewNodeInner = (props) => {
5126
5135
  const { t } = useTranslate();
5127
5136
  const eventBus = useEventBus();
5128
5137
  const reactFlow = useReactFlow();
5138
+ const cameraMs = usePrefersReducedMotion() ? 0 : 200;
5129
5139
  const contentRef = useRef(null);
5130
5140
  const [hovered, setHovered] = useState(false);
5131
5141
  const [playing, setPlaying] = useState(false);
@@ -5328,7 +5338,7 @@ var OrbPreviewNodeInner = (props) => {
5328
5338
  if (e.shiftKey && (e.code === "Digit1" || e.code === "Digit2") && hasCanvasTool(tools, "zoomToSelection")) {
5329
5339
  handled();
5330
5340
  if (e.code === "Digit1") {
5331
- void reactFlow.fitView({ padding: 0.1, duration: 200 });
5341
+ void reactFlow.fitView({ padding: 0.1, duration: cameraMs });
5332
5342
  return;
5333
5343
  }
5334
5344
  const container = contentRef.current;
@@ -5345,7 +5355,7 @@ var OrbPreviewNodeInner = (props) => {
5345
5355
  orbPreviewLog.info("zoom-to-selection", { paths, boxes, topLeft, bottomRight });
5346
5356
  void reactFlow.fitBounds(
5347
5357
  { x: topLeft.x, y: topLeft.y, width: bottomRight.x - topLeft.x, height: bottomRight.y - topLeft.y },
5348
- { padding: 0.2, duration: 200 }
5358
+ { padding: 0.2, duration: cameraMs }
5349
5359
  );
5350
5360
  return;
5351
5361
  }
@@ -6035,7 +6045,7 @@ var OrbPreviewNodeInner = (props) => {
6035
6045
  Box,
6036
6046
  {
6037
6047
  ref: setContentRef,
6038
- className: `orb-preview-live nodrag nopan relative outline-none${dragActive || reorderDragActive || l2IsOver ? " drag-active" : ""}`,
6048
+ className: `orb-preview-live nodrag nopan relative outline-none focus-visible:ring-[length:var(--focus-ring-width)] focus-visible:ring-ring focus-visible:ring-inset${dragActive || reorderDragActive || l2IsOver ? " drag-active" : ""}`,
6039
6049
  "data-playing": playing,
6040
6050
  onClick: playing ? handleContentClick : void 0,
6041
6051
  onClickCapture: playing ? void 0 : handlePausedClickCapture,
@@ -8500,6 +8510,7 @@ function FlowCanvasInner({
8500
8510
  const [nodes, setNodes, onNodesChange] = useNodesState(activeNodes);
8501
8511
  const [edges, setEdges, onEdgesChange] = useEdgesState(activeEdges);
8502
8512
  const reactFlow = useReactFlow();
8513
+ const cameraMs = usePrefersReducedMotion() ? 0 : 300;
8503
8514
  const savedPositionsRef = React19.useRef(nodePositions);
8504
8515
  savedPositionsRef.current = nodePositions;
8505
8516
  const nodesRef = React19.useRef(nodes);
@@ -8527,8 +8538,8 @@ function FlowCanvasInner({
8527
8538
  const pending = pendingFitRef.current;
8528
8539
  if (!nodesInitialized || !pending) return;
8529
8540
  pendingFitRef.current = null;
8530
- void reactFlow.fitView({ duration: 300, padding: fitPadding, ...pending.centreOn ? { nodes: [{ id: pending.centreOn }] } : {} });
8531
- }, [nodesInitialized, nodes, reactFlow, fitPadding]);
8541
+ void reactFlow.fitView({ duration: cameraMs, padding: fitPadding, ...pending.centreOn ? { nodes: [{ id: pending.centreOn }] } : {} });
8542
+ }, [nodesInitialized, nodes, reactFlow, fitPadding, cameraMs]);
8532
8543
  const visibleEdges = useMemo(() => {
8533
8544
  const nodeIds = new Set(nodes.map((n) => n.id));
8534
8545
  return edges.filter((e) => nodeIds.has(e.source) && nodeIds.has(e.target));
@@ -8686,7 +8697,7 @@ function FlowCanvasInner({
8686
8697
  const applyScreenSize = (size2) => {
8687
8698
  pickScreenSize(size2);
8688
8699
  requestAnimationFrame(() => {
8689
- reactFlow.fitView({ duration: 300, padding: 0.25 });
8700
+ reactFlow.fitView({ duration: cameraMs, padding: 0.25 });
8690
8701
  });
8691
8702
  };
8692
8703
  const traitCardSelectionValue = useMemo(() => ({
@@ -8914,7 +8925,7 @@ function FlowCanvasInner({
8914
8925
  /* @__PURE__ */ jsx(
8915
8926
  Box,
8916
8927
  {
8917
- className: "relative flex-1 min-w-0 h-full outline-none flex flex-col",
8928
+ className: "relative flex-1 min-w-0 h-full outline-none focus-visible:ring-[length:var(--focus-ring-width)] focus-visible:ring-ring focus-visible:ring-inset flex flex-col",
8918
8929
  tabIndex: 0,
8919
8930
  onKeyDown: handleCanvasKeyDown,
8920
8931
  "data-testid": "flow-canvas",
@@ -1,3 +1,4 @@
1
+ import { beginPending, endPending } from './chunk-JRW33U35.js';
1
2
  import { useEventBus } from './chunk-6EV3OEBQ.js';
2
3
  import { useState, useCallback, useEffect, useMemo, useRef } from 'react';
3
4
  import { createLogger } from '@almadar/logger';
@@ -856,7 +857,12 @@ function useUIEvents(dispatch, traitName, validEvents, eventBusInstance) {
856
857
  if (event.source && event.source.dispatched) {
857
858
  return;
858
859
  }
859
- dispatch(smEvent, event.payload);
860
+ const pendingKey = event.source?.pendingKey;
861
+ const settled = dispatch(smEvent, event.payload);
862
+ if (pendingKey !== void 0 && settled instanceof Promise) {
863
+ beginPending(pendingKey);
864
+ void settled.finally(() => endPending(pendingKey));
865
+ }
860
866
  };
861
867
  unsubscribes.push(
862
868
  eventBus.on(`${UI_PREFIX}${traitName}.${smEvent}`, handler)