@almadar/ui 5.135.0 → 5.137.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.
@@ -1,8 +1,10 @@
1
- import * as React82 from 'react';
2
- import React82__default, { createContext, useContext, useMemo, useRef, useEffect, useCallback, Suspense, useState, useSyncExternalStore, useLayoutEffect, lazy, useId } from 'react';
3
- import { EventBusContext, useTraitScopeChain, useEntitySchemaOptional, useEntitySchema, getAllPages, matchPathAmong, OrbitalProvider, TraitScopeProvider, ServerBridgeProvider, useCurrentPagePath, useGameAudioContextOptional, VerificationProvider, EntitySchemaProvider, OrbitalThemeProvider, useServerBridge } from '@almadar/ui/providers';
1
+ import * as React83 from 'react';
2
+ import React83__default, { createContext, useContext, useMemo, useRef, useEffect, useCallback, Suspense, useState, useSyncExternalStore, useLayoutEffect, lazy, useId } from 'react';
3
+ import { EventBusContext, useTraitScopeChain, useEntitySchemaOptional, useEntityBindingSnapshot, useTraitScope, useEntitySchema, getAllPages, matchPathAmong, OrbitalProvider, TraitScopeProvider, ServerBridgeProvider, useCurrentPagePath, useGameAudioContextOptional, VerificationProvider, EntitySchemaProvider, OrbitalThemeProvider, useServerBridge, EntityBindingContext } from '@almadar/ui/providers';
4
4
  export { EntitySchemaProvider, ServerBridgeProvider, TraitContext, TraitProvider, useEntitySchema, useEntitySchemaOptional, useServerBridge, useTrait, useTraitContext } from '@almadar/ui/providers';
5
5
  import { createLogger, setNamespaceLevel, isLogLevelEnabled } from '@almadar/logger';
6
+ import { StateMachineManager, collectDeclaredConfigDefaults, resolveCallSitePayloadCaptures, createServerEffectHandlers, EffectExecutor, createContextFromBindings, createTickScheduler, isValidCronExpression, parseDurationString, InMemoryPersistence, normalizeCallSiteConfigToValues, interpolateValue } from '@almadar/runtime';
7
+ import { mergeEntityFrame, isCircuitEvent, applyListenPayloadMapping, schemaToIR, getPage, clearSchemaCache as clearSchemaCache$1, walkSExpr, buildResolvedTraitConfigs, isRenderBindingMarker, isInlineTrait, containsEntityBinding, isSExpr, isEventPayloadValue, RENDER_BINDING_MARKER } from '@almadar/core';
6
8
  import { clsx } from 'clsx';
7
9
  import { twMerge } from 'tailwind-merge';
8
10
  import * as LucideIcons2 from 'lucide-react';
@@ -69,14 +71,13 @@ import ReactMarkdown from 'react-markdown';
69
71
  import remarkGfm from 'remark-gfm';
70
72
  import remarkMath from 'remark-math';
71
73
  import rehypeKatex from 'rehype-katex';
72
- import { mergeEntityFrame, isCircuitEvent, applyListenPayloadMapping, schemaToIR, getPage, clearSchemaCache as clearSchemaCache$1, walkSExpr, buildResolvedTraitConfigs, isInlineTrait, isSExpr, isEventPayloadValue } from '@almadar/core';
73
74
  import { DndContext, pointerWithin, rectIntersection, closestCorners, useSensors, useSensor, PointerSensor, KeyboardSensor, useDroppable } from '@dnd-kit/core';
74
75
  import { useSortable, arrayMove, sortableKeyboardCoordinates, SortableContext, rectSortingStrategy, verticalListSortingStrategy } from '@dnd-kit/sortable';
75
76
  import { CSS } from '@dnd-kit/utilities';
77
+ import { ordered, lib } from 'emojilib';
76
78
  import { useNodeId, ReactFlowProvider, Handle, Position } from '@xyflow/react';
77
79
  import { forceSimulation, forceLink, forceManyBody, forceCollide, forceX, forceY } from 'd3-force';
78
80
  import { isDrawHostPattern, getPatternDefinition, getComponentForPattern as getComponentForPattern$1 } from '@almadar/core/patterns';
79
- import { StateMachineManager, collectDeclaredConfigDefaults, resolveCallSitePayloadCaptures, createServerEffectHandlers, EffectExecutor, createContextFromBindings, createTickScheduler, isValidCronExpression, parseDurationString, InMemoryPersistence, normalizeCallSiteConfigToValues } from '@almadar/runtime';
80
81
  import { isKnownStdOperator } from '@almadar/std/registry';
81
82
  import { OrbitalServerRuntime } from '@almadar/runtime/OrbitalServerRuntime';
82
83
 
@@ -812,6 +813,75 @@ var init_useTapReveal = __esm({
812
813
  "hooks/useTapReveal.ts"() {
813
814
  }
814
815
  });
816
+ function resolveMarkerExpression(expression, entity, config, state) {
817
+ const ctx = createContextFromBindings({
818
+ entity,
819
+ payload: {},
820
+ state,
821
+ ...config !== void 0 ? { config } : {}
822
+ });
823
+ return interpolateValue(expression, ctx);
824
+ }
825
+ function isPlainObject(value) {
826
+ if (value === null || value === void 0 || typeof value !== "object") return false;
827
+ if (Array.isArray(value)) return false;
828
+ if (React83__default.isValidElement(value)) return false;
829
+ if (value instanceof Date) return false;
830
+ if (typeof value === "function") return false;
831
+ return true;
832
+ }
833
+ function walkValue(value, scopeTrait, entity, config, state) {
834
+ if (isRenderBindingMarker(value)) {
835
+ return { resolved: resolveMarkerExpression(value.expression, entity, config, state), changed: true };
836
+ }
837
+ if (Array.isArray(value)) {
838
+ const out = [];
839
+ let changed = false;
840
+ for (const item of value) {
841
+ const element = item;
842
+ const wasMarker = isRenderBindingMarker(element);
843
+ const { resolved, changed: itemChanged } = walkValue(element, scopeTrait, entity, config, state);
844
+ if (wasMarker && Array.isArray(resolved)) {
845
+ out.push(...resolved);
846
+ changed = true;
847
+ continue;
848
+ }
849
+ out.push(resolved);
850
+ if (itemChanged) changed = true;
851
+ }
852
+ return changed ? { resolved: out, changed: true } : { resolved: value, changed: false };
853
+ }
854
+ if (isPlainObject(value)) {
855
+ const sourceTrait = value._sourceTrait;
856
+ if (typeof sourceTrait === "string" && sourceTrait !== scopeTrait) {
857
+ return { resolved: value, changed: false };
858
+ }
859
+ const out = {};
860
+ let changed = false;
861
+ for (const [key, item] of Object.entries(value)) {
862
+ const { resolved, changed: itemChanged } = walkValue(item, scopeTrait, entity, config, state);
863
+ out[key] = resolved;
864
+ if (itemChanged) changed = true;
865
+ }
866
+ return changed ? { resolved: out, changed: true } : { resolved: value, changed: false };
867
+ }
868
+ return { resolved: value, changed: false };
869
+ }
870
+ function resolveRenderBindingMarkers(props, scopeTrait, entity, config, state) {
871
+ const out = {};
872
+ let changed = false;
873
+ for (const [key, value] of Object.entries(props)) {
874
+ const { resolved, changed: propChanged } = walkValue(value, scopeTrait, entity, config, state);
875
+ out[key] = resolved;
876
+ if (propChanged) changed = true;
877
+ }
878
+ return changed ? out : props;
879
+ }
880
+ var init_resolve_render_bindings = __esm({
881
+ "lib/resolve-render-bindings.ts"() {
882
+ "use client";
883
+ }
884
+ });
815
885
  function cn(...inputs) {
816
886
  return twMerge(clsx(inputs));
817
887
  }
@@ -928,7 +998,7 @@ var init_Box = __esm({
928
998
  fixed: "fixed",
929
999
  sticky: "sticky"
930
1000
  };
931
- Box = React82__default.forwardRef(
1001
+ Box = React83__default.forwardRef(
932
1002
  ({
933
1003
  padding,
934
1004
  paddingX,
@@ -993,7 +1063,7 @@ var init_Box = __esm({
993
1063
  onPointerDown?.(e);
994
1064
  }, [hoverEvent, tapReveal, triggerProps, onPointerDown]);
995
1065
  const isClickable = action || onClick;
996
- return React82__default.createElement(
1066
+ return React83__default.createElement(
997
1067
  Component,
998
1068
  {
999
1069
  ref,
@@ -1210,7 +1280,7 @@ var init_Icon = __esm({
1210
1280
  const effectiveName = typeof icon === "string" && icon !== "" ? icon : name;
1211
1281
  const effectiveStrokeWidth = strokeWidth != null && strokeWidth > 0 ? strokeWidth : void 0;
1212
1282
  const family = useIconFamily();
1213
- const RenderedComponent = React82__default.useMemo(() => {
1283
+ const RenderedComponent = React83__default.useMemo(() => {
1214
1284
  if (directIcon) return null;
1215
1285
  return effectiveName ? resolveIconForFamily(effectiveName) : null;
1216
1286
  }, [directIcon, effectiveName, family]);
@@ -1272,9 +1342,13 @@ function getAtlas(url, onReady) {
1272
1342
  onReady();
1273
1343
  }).catch(() => {
1274
1344
  atlasCache.set(url, null);
1345
+ onReady();
1275
1346
  });
1276
1347
  return void 0;
1277
1348
  }
1349
+ function atlasFailed(url) {
1350
+ return atlasCache.get(url) === null;
1351
+ }
1278
1352
  function subRectFor(atlas, sprite) {
1279
1353
  if (isTilesheet(atlas)) {
1280
1354
  let col;
@@ -1330,7 +1404,7 @@ var init_atlasSlice = __esm({
1330
1404
  }
1331
1405
  });
1332
1406
  function useAtlasSliceDataUrl(asset) {
1333
- const [, bump] = React82.useReducer((x) => x + 1, 0);
1407
+ const [, bump] = React83.useReducer((x) => x + 1, 0);
1334
1408
  if (!isAtlasAsset(asset)) return void 0;
1335
1409
  const key = `${asset.atlas}#${asset.sprite}`;
1336
1410
  const cached = sliceDataUrlCache.get(key);
@@ -1393,13 +1467,13 @@ function AtlasImage({
1393
1467
  style,
1394
1468
  "aria-hidden": ariaHidden
1395
1469
  }) {
1396
- const [, bump] = React82.useReducer((x) => x + 1, 0);
1397
- const canvasRef = React82.useRef(null);
1470
+ const [, bump] = React83.useReducer((x) => x + 1, 0);
1471
+ const canvasRef = React83.useRef(null);
1398
1472
  const sliced = isAtlasAsset(asset);
1399
1473
  const atlas = sliced ? getAtlas(asset.atlas, bump) : void 0;
1400
1474
  const img = sliced && asset?.url ? getSheetImage(asset.url, bump) : null;
1401
1475
  const rect = sliced && atlas ? subRectFor(atlas, asset.sprite) : null;
1402
- React82.useEffect(() => {
1476
+ React83.useEffect(() => {
1403
1477
  const canvas = canvasRef.current;
1404
1478
  if (!canvas || !img || !rect) return;
1405
1479
  canvas.width = rect.sw;
@@ -1475,7 +1549,7 @@ function resolveIconProp(value, sizeClass) {
1475
1549
  const IconComp = value;
1476
1550
  return /* @__PURE__ */ jsx(IconComp, { className: sizeClass });
1477
1551
  }
1478
- if (React82__default.isValidElement(value)) {
1552
+ if (React83__default.isValidElement(value)) {
1479
1553
  return value;
1480
1554
  }
1481
1555
  if (typeof value === "object" && value !== null && isIconLike(value)) {
@@ -1552,7 +1626,7 @@ var init_Button = __esm({
1552
1626
  md: "h-icon-default w-icon-default",
1553
1627
  lg: "h-icon-default w-icon-default"
1554
1628
  };
1555
- Button = React82__default.forwardRef(
1629
+ Button = React83__default.forwardRef(
1556
1630
  ({
1557
1631
  className,
1558
1632
  variant = "primary",
@@ -1622,7 +1696,7 @@ var Dialog;
1622
1696
  var init_Dialog = __esm({
1623
1697
  "components/core/atoms/Dialog.tsx"() {
1624
1698
  init_cn();
1625
- Dialog = React82__default.forwardRef(
1699
+ Dialog = React83__default.forwardRef(
1626
1700
  ({
1627
1701
  role = "dialog",
1628
1702
  "aria-modal": ariaModal = true,
@@ -1833,7 +1907,7 @@ var init_Typography = __esm({
1833
1907
  if (format !== void 0 && format !== "none" && (typeof body === "string" || typeof body === "number" || body instanceof Date)) {
1834
1908
  body = formatValue(body, format);
1835
1909
  }
1836
- return React82__default.createElement(
1910
+ return React83__default.createElement(
1837
1911
  Component,
1838
1912
  {
1839
1913
  id,
@@ -2396,7 +2470,7 @@ var init_Badge = __esm({
2396
2470
  md: "px-2.5 py-1 text-sm",
2397
2471
  lg: "px-3 py-1.5 text-base"
2398
2472
  };
2399
- Badge = React82__default.forwardRef(
2473
+ Badge = React83__default.forwardRef(
2400
2474
  ({ className, variant = "default", size = "sm", amount, label, icon, iconAsset, children, onRemove, removeLabel, ...props }, ref) => {
2401
2475
  const iconSizes3 = {
2402
2476
  sm: "h-icon-default w-icon-default",
@@ -2746,7 +2820,7 @@ var init_SvgFlow = __esm({
2746
2820
  width = 100,
2747
2821
  height = 100
2748
2822
  }) => {
2749
- const markerId = React82__default.useMemo(() => {
2823
+ const markerId = React83__default.useMemo(() => {
2750
2824
  flowIdCounter += 1;
2751
2825
  return `almadar-flow-arrow-${flowIdCounter}`;
2752
2826
  }, []);
@@ -3339,7 +3413,7 @@ var init_SvgRing = __esm({
3339
3413
  width = 100,
3340
3414
  height = 100
3341
3415
  }) => {
3342
- const gradientId = React82__default.useMemo(() => {
3416
+ const gradientId = React83__default.useMemo(() => {
3343
3417
  ringIdCounter += 1;
3344
3418
  return `almadar-ring-glow-${ringIdCounter}`;
3345
3419
  }, []);
@@ -3520,7 +3594,7 @@ var init_Input = __esm({
3520
3594
  init_cn();
3521
3595
  init_Icon();
3522
3596
  init_useEventBus();
3523
- Input = React82__default.forwardRef(
3597
+ Input = React83__default.forwardRef(
3524
3598
  ({
3525
3599
  className,
3526
3600
  inputType,
@@ -3543,6 +3617,20 @@ var init_Input = __esm({
3543
3617
  const { t } = useTranslate();
3544
3618
  const eventBus = useEventBus();
3545
3619
  const type = inputType || htmlType || "text";
3620
+ const isDeclarative = typeof onChange === "string";
3621
+ const [localValue, setLocalValue] = React83__default.useState(value);
3622
+ const pendingEchoRef = React83__default.useRef(/* @__PURE__ */ new Set());
3623
+ React83__default.useEffect(() => {
3624
+ if (!isDeclarative) return;
3625
+ const incoming = value == null ? "" : String(value);
3626
+ if (pendingEchoRef.current.has(incoming)) {
3627
+ pendingEchoRef.current.delete(incoming);
3628
+ return;
3629
+ }
3630
+ pendingEchoRef.current.clear();
3631
+ setLocalValue(value);
3632
+ }, [value, isDeclarative]);
3633
+ const displayValue = isDeclarative ? localValue : value;
3546
3634
  const resolveIconNode = (i, cls) => {
3547
3635
  if (!i) return null;
3548
3636
  if (typeof i === "string") return /* @__PURE__ */ jsx(Icon, { name: i, className: cls });
@@ -3552,7 +3640,7 @@ var init_Input = __esm({
3552
3640
  const iconCls = "h-icon-default w-icon-default";
3553
3641
  const IconComponent = typeof iconProp === "string" ? resolveIcon(iconProp) : iconProp;
3554
3642
  const resolvedLeftIcon = (leftIcon ? resolveIconNode(leftIcon, iconCls) : null) || IconComponent && /* @__PURE__ */ jsx(IconComponent, { className: iconCls });
3555
- const showClearButton = clearable && value && String(value).length > 0;
3643
+ const showClearButton = clearable && displayValue && String(displayValue).length > 0;
3556
3644
  const isMultiline = type === "textarea";
3557
3645
  const baseClassName = cn(
3558
3646
  "block w-full rounded-sm transition-all duration-fast",
@@ -3571,6 +3659,10 @@ var init_Input = __esm({
3571
3659
  if (typeof onChange === "string") {
3572
3660
  const target = e.target;
3573
3661
  const payload = type === "checkbox" ? { checked: target.checked } : { value: target.value };
3662
+ if (type !== "checkbox") {
3663
+ pendingEchoRef.current.add(target.value);
3664
+ setLocalValue(target.value);
3665
+ }
3574
3666
  eventBus.emit(`UI:${onChange}`, payload);
3575
3667
  } else {
3576
3668
  onChange?.(e);
@@ -3601,7 +3693,7 @@ var init_Input = __esm({
3601
3693
  "select",
3602
3694
  {
3603
3695
  ref,
3604
- value,
3696
+ value: displayValue,
3605
3697
  onChange: handleChange,
3606
3698
  className: cn(baseClassName, "appearance-none pr-10", className),
3607
3699
  ...props,
@@ -3621,7 +3713,7 @@ var init_Input = __esm({
3621
3713
  "textarea",
3622
3714
  {
3623
3715
  ref,
3624
- value,
3716
+ value: displayValue,
3625
3717
  onChange: handleChange,
3626
3718
  rows,
3627
3719
  className: baseClassName,
@@ -3660,7 +3752,7 @@ var init_Input = __esm({
3660
3752
  {
3661
3753
  ref,
3662
3754
  type,
3663
- value,
3755
+ value: displayValue,
3664
3756
  onChange: handleChange,
3665
3757
  onKeyDown: handleKeyDown,
3666
3758
  className: baseClassName,
@@ -3688,7 +3780,7 @@ var Label;
3688
3780
  var init_Label = __esm({
3689
3781
  "components/core/atoms/Label.tsx"() {
3690
3782
  init_cn();
3691
- Label = React82__default.forwardRef(
3783
+ Label = React83__default.forwardRef(
3692
3784
  ({ className, required, children, ...props }, ref) => {
3693
3785
  return /* @__PURE__ */ jsxs(
3694
3786
  "label",
@@ -3715,7 +3807,7 @@ var init_Textarea = __esm({
3715
3807
  "components/core/atoms/Textarea.tsx"() {
3716
3808
  init_cn();
3717
3809
  init_useEventBus();
3718
- Textarea = React82__default.forwardRef(
3810
+ Textarea = React83__default.forwardRef(
3719
3811
  ({ className, error, onChange, ...props }, ref) => {
3720
3812
  const eventBus = useEventBus();
3721
3813
  const handleChange = (e) => {
@@ -3954,7 +4046,7 @@ var init_Select = __esm({
3954
4046
  init_cn();
3955
4047
  init_Icon();
3956
4048
  init_useEventBus();
3957
- Select = React82__default.forwardRef(
4049
+ Select = React83__default.forwardRef(
3958
4050
  (props, _ref) => {
3959
4051
  const { multiple, searchable, clearable } = props;
3960
4052
  if (multiple || searchable || clearable) {
@@ -3971,7 +4063,7 @@ var init_Checkbox = __esm({
3971
4063
  "components/core/atoms/Checkbox.tsx"() {
3972
4064
  init_cn();
3973
4065
  init_useEventBus();
3974
- Checkbox = React82__default.forwardRef(
4066
+ Checkbox = React83__default.forwardRef(
3975
4067
  ({ className, label, id, onChange, ...props }, ref) => {
3976
4068
  const inputId = id || `checkbox-${Math.random().toString(36).substr(2, 9)}`;
3977
4069
  const eventBus = useEventBus();
@@ -4025,7 +4117,7 @@ var init_Spinner = __esm({
4025
4117
  md: "h-6 w-6",
4026
4118
  lg: "h-8 w-8"
4027
4119
  };
4028
- Spinner = React82__default.forwardRef(
4120
+ Spinner = React83__default.forwardRef(
4029
4121
  ({ className, size = "md", overlay, ...props }, ref) => {
4030
4122
  if (overlay) {
4031
4123
  return /* @__PURE__ */ jsx(
@@ -4115,7 +4207,7 @@ var init_Card = __esm({
4115
4207
  chip: "shadow-none rounded-pill border-[length:var(--border-width)] border-border",
4116
4208
  "tile-image-first": "p-0 overflow-hidden"
4117
4209
  };
4118
- Card = React82__default.forwardRef(
4210
+ Card = React83__default.forwardRef(
4119
4211
  ({
4120
4212
  className,
4121
4213
  variant = "bordered",
@@ -4164,9 +4256,9 @@ var init_Card = __esm({
4164
4256
  }
4165
4257
  );
4166
4258
  Card.displayName = "Card";
4167
- CardHeader = React82__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("mb-4", className), ...props }));
4259
+ CardHeader = React83__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("mb-4", className), ...props }));
4168
4260
  CardHeader.displayName = "CardHeader";
4169
- CardTitle = React82__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
4261
+ CardTitle = React83__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
4170
4262
  "h3",
4171
4263
  {
4172
4264
  ref,
@@ -4179,11 +4271,11 @@ var init_Card = __esm({
4179
4271
  }
4180
4272
  ));
4181
4273
  CardTitle.displayName = "CardTitle";
4182
- CardContent = React82__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("", className), ...props }));
4274
+ CardContent = React83__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("", className), ...props }));
4183
4275
  CardContent.displayName = "CardContent";
4184
4276
  CardBody = CardContent;
4185
4277
  CardBody.displayName = "CardBody";
4186
- CardFooter = React82__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
4278
+ CardFooter = React83__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
4187
4279
  "div",
4188
4280
  {
4189
4281
  ref,
@@ -4270,7 +4362,7 @@ var init_FilterPill = __esm({
4270
4362
  md: "w-3.5 h-3.5",
4271
4363
  lg: "w-4 h-4"
4272
4364
  };
4273
- FilterPill = React82__default.forwardRef(
4365
+ FilterPill = React83__default.forwardRef(
4274
4366
  ({
4275
4367
  className,
4276
4368
  variant = "default",
@@ -4399,8 +4491,8 @@ var init_Avatar = __esm({
4399
4491
  actionPayload
4400
4492
  }) => {
4401
4493
  const eventBus = useEventBus();
4402
- const [imgFailed, setImgFailed] = React82__default.useState(false);
4403
- React82__default.useEffect(() => {
4494
+ const [imgFailed, setImgFailed] = React83__default.useState(false);
4495
+ React83__default.useEffect(() => {
4404
4496
  setImgFailed(false);
4405
4497
  }, [src]);
4406
4498
  const initials = providedInitials ?? (name ? generateInitials(name) : void 0);
@@ -4513,7 +4605,7 @@ var init_Center = __esm({
4513
4605
  as: Component = "div"
4514
4606
  }) => {
4515
4607
  const mergedStyle = minHeight ? { minHeight, ...style } : style;
4516
- return React82__default.createElement(Component, {
4608
+ return React83__default.createElement(Component, {
4517
4609
  className: cn(
4518
4610
  inline ? "inline-flex" : "flex",
4519
4611
  horizontal && "justify-center",
@@ -4781,7 +4873,7 @@ var init_Radio = __esm({
4781
4873
  md: "w-2.5 h-2.5",
4782
4874
  lg: "w-3 h-3"
4783
4875
  };
4784
- Radio = React82__default.forwardRef(
4876
+ Radio = React83__default.forwardRef(
4785
4877
  ({
4786
4878
  label,
4787
4879
  helperText,
@@ -4798,12 +4890,12 @@ var init_Radio = __esm({
4798
4890
  onChange,
4799
4891
  ...props
4800
4892
  }, ref) => {
4801
- const reactId = React82__default.useId();
4893
+ const reactId = React83__default.useId();
4802
4894
  const baseId = id || `radio-${reactId}`;
4803
4895
  const hasError = !!error;
4804
4896
  const eventBus = useEventBus();
4805
- const [selected, setSelected] = React82__default.useState(value);
4806
- React82__default.useEffect(() => {
4897
+ const [selected, setSelected] = React83__default.useState(value);
4898
+ React83__default.useEffect(() => {
4807
4899
  if (value !== void 0) setSelected(value);
4808
4900
  }, [value]);
4809
4901
  const pick = (next, e) => {
@@ -4985,7 +5077,7 @@ var init_Switch = __esm({
4985
5077
  "components/core/atoms/Switch.tsx"() {
4986
5078
  "use client";
4987
5079
  init_cn();
4988
- Switch = React82.forwardRef(
5080
+ Switch = React83.forwardRef(
4989
5081
  ({
4990
5082
  checked,
4991
5083
  defaultChecked = false,
@@ -4996,10 +5088,10 @@ var init_Switch = __esm({
4996
5088
  name,
4997
5089
  className
4998
5090
  }, ref) => {
4999
- const [isChecked, setIsChecked] = React82.useState(
5091
+ const [isChecked, setIsChecked] = React83.useState(
5000
5092
  checked !== void 0 ? checked : defaultChecked
5001
5093
  );
5002
- React82.useEffect(() => {
5094
+ React83.useEffect(() => {
5003
5095
  if (checked !== void 0) {
5004
5096
  setIsChecked(checked);
5005
5097
  }
@@ -5162,7 +5254,7 @@ var init_Stack = __esm({
5162
5254
  };
5163
5255
  const isHorizontal = direction === "horizontal";
5164
5256
  const directionClass = responsive && isHorizontal ? reverse ? "flex-col-reverse md:flex-row-reverse" : "flex-col md:flex-row" : isHorizontal ? reverse ? "flex-row-reverse" : "flex-row" : reverse ? "flex-col-reverse" : "flex-col";
5165
- return React82__default.createElement(
5257
+ return React83__default.createElement(
5166
5258
  Component,
5167
5259
  {
5168
5260
  className: cn(
@@ -5362,7 +5454,7 @@ var Aside;
5362
5454
  var init_Aside = __esm({
5363
5455
  "components/core/atoms/Aside.tsx"() {
5364
5456
  init_cn();
5365
- Aside = React82__default.forwardRef(
5457
+ Aside = React83__default.forwardRef(
5366
5458
  ({ className, children, ...rest }, ref) => /* @__PURE__ */ jsx("aside", { ref, className: cn(className), ...rest, children })
5367
5459
  );
5368
5460
  Aside.displayName = "Aside";
@@ -5441,9 +5533,9 @@ var init_LawReferenceTooltip = __esm({
5441
5533
  className
5442
5534
  }) => {
5443
5535
  const { t } = useTranslate();
5444
- const [isVisible, setIsVisible] = React82__default.useState(false);
5445
- const timeoutRef = React82__default.useRef(null);
5446
- const triggerRef = React82__default.useRef(null);
5536
+ const [isVisible, setIsVisible] = React83__default.useState(false);
5537
+ const timeoutRef = React83__default.useRef(null);
5538
+ const triggerRef = React83__default.useRef(null);
5447
5539
  const handleMouseEnter = () => {
5448
5540
  if (timeoutRef.current) clearTimeout(timeoutRef.current);
5449
5541
  timeoutRef.current = setTimeout(() => setIsVisible(true), 200);
@@ -5454,7 +5546,7 @@ var init_LawReferenceTooltip = __esm({
5454
5546
  };
5455
5547
  const { revealed, triggerProps } = useTapReveal({ refs: [triggerRef] });
5456
5548
  const open = isVisible || revealed;
5457
- React82__default.useEffect(() => {
5549
+ React83__default.useEffect(() => {
5458
5550
  return () => {
5459
5551
  if (timeoutRef.current) clearTimeout(timeoutRef.current);
5460
5552
  };
@@ -5664,7 +5756,7 @@ var init_StatusDot = __esm({
5664
5756
  md: "w-2.5 h-2.5",
5665
5757
  lg: "w-3 h-3"
5666
5758
  };
5667
- StatusDot = React82__default.forwardRef(
5759
+ StatusDot = React83__default.forwardRef(
5668
5760
  ({ className, status = "offline", pulse = false, size = "md", label, ...props }, ref) => {
5669
5761
  return /* @__PURE__ */ jsx(
5670
5762
  "span",
@@ -5718,7 +5810,7 @@ var init_TrendIndicator = __esm({
5718
5810
  down: "trending-down",
5719
5811
  flat: "arrow-right"
5720
5812
  };
5721
- TrendIndicator = React82__default.forwardRef(
5813
+ TrendIndicator = React83__default.forwardRef(
5722
5814
  ({
5723
5815
  className,
5724
5816
  value,
@@ -5787,7 +5879,7 @@ var init_RangeSlider = __esm({
5787
5879
  md: "w-4 h-4",
5788
5880
  lg: "w-5 h-5"
5789
5881
  };
5790
- RangeSlider = React82__default.forwardRef(
5882
+ RangeSlider = React83__default.forwardRef(
5791
5883
  ({
5792
5884
  className,
5793
5885
  min = 0,
@@ -6363,7 +6455,7 @@ var init_ContentSection = __esm({
6363
6455
  md: "py-16",
6364
6456
  lg: "py-24"
6365
6457
  };
6366
- ContentSection = React82__default.forwardRef(
6458
+ ContentSection = React83__default.forwardRef(
6367
6459
  ({ children, background = "default", padding = "lg", id, className }, ref) => {
6368
6460
  return /* @__PURE__ */ jsx(
6369
6461
  Box,
@@ -6897,7 +6989,7 @@ var init_AnimatedReveal = __esm({
6897
6989
  "scale-up": { opacity: 1, transform: "scale(1) translateY(0)" },
6898
6990
  "none": {}
6899
6991
  };
6900
- AnimatedReveal = React82__default.forwardRef(
6992
+ AnimatedReveal = React83__default.forwardRef(
6901
6993
  ({
6902
6994
  trigger = "scroll",
6903
6995
  animation = "fade-up",
@@ -7057,7 +7149,7 @@ var init_AnimatedGraphic = __esm({
7057
7149
  "components/marketing/atoms/AnimatedGraphic.tsx"() {
7058
7150
  "use client";
7059
7151
  init_cn();
7060
- AnimatedGraphic = React82__default.forwardRef(
7152
+ AnimatedGraphic = React83__default.forwardRef(
7061
7153
  ({
7062
7154
  src,
7063
7155
  svgContent,
@@ -7080,7 +7172,7 @@ var init_AnimatedGraphic = __esm({
7080
7172
  const fetchedSvg = useFetchedSvg(svgContent ? void 0 : src);
7081
7173
  const resolvedSvg = svgContent ?? fetchedSvg;
7082
7174
  const prevAnimateRef = useRef(animate);
7083
- const setRef = React82__default.useCallback(
7175
+ const setRef = React83__default.useCallback(
7084
7176
  (node) => {
7085
7177
  containerRef.current = node;
7086
7178
  if (typeof ref === "function") ref(node);
@@ -7547,46 +7639,45 @@ var init_useImageCache = __esm({
7547
7639
  });
7548
7640
 
7549
7641
  // lib/isometric.ts
7550
- function isoToScreen(tileX, tileY, scale, baseOffsetX, layout = "isometric") {
7551
- const scaledTileWidth = TILE_WIDTH * scale;
7552
- const scaledFloorHeight = FLOOR_HEIGHT * scale;
7642
+ function isoToScreen(tileX, tileY, cellWidth, baseOffsetX, layout = "isometric") {
7643
+ const w = cellWidth;
7644
+ const fh = cellWidth / 2;
7553
7645
  if (layout === "hex") {
7554
- const screenX2 = tileX * scaledTileWidth + (tileY & 1) * (scaledTileWidth / 2) + baseOffsetX;
7555
- const screenY2 = tileY * (scaledFloorHeight * 0.75);
7646
+ const screenX2 = tileX * w + (tileY & 1) * (w / 2) + baseOffsetX;
7647
+ const screenY2 = tileY * (fh * 0.75);
7556
7648
  return { x: screenX2, y: screenY2 };
7557
7649
  }
7558
7650
  if (layout === "flat") {
7559
- const screenX2 = tileX * scaledTileWidth + baseOffsetX;
7560
- const screenY2 = tileY * scaledTileWidth;
7651
+ const screenX2 = tileX * w + baseOffsetX;
7652
+ const screenY2 = tileY * w;
7561
7653
  return { x: screenX2, y: screenY2 };
7562
7654
  }
7563
- const screenX = (tileX - tileY) * (scaledTileWidth / 2) + baseOffsetX;
7564
- const screenY = (tileX + tileY) * (scaledFloorHeight / 2);
7655
+ const screenX = (tileX - tileY) * (w / 2) + baseOffsetX;
7656
+ const screenY = (tileX + tileY) * (fh / 2);
7565
7657
  return { x: screenX, y: screenY };
7566
7658
  }
7567
- function screenToIso(screenX, screenY, scale, baseOffsetX, layout = "isometric") {
7568
- const scaledTileWidth = TILE_WIDTH * scale;
7569
- const scaledFloorHeight = FLOOR_HEIGHT * scale;
7659
+ function screenToIso(screenX, screenY, cellWidth, baseOffsetX, layout = "isometric") {
7660
+ const w = cellWidth;
7661
+ const fh = cellWidth / 2;
7570
7662
  if (layout === "hex") {
7571
- const row = Math.round(screenY / (scaledFloorHeight * 0.75));
7572
- const col = Math.round((screenX - (row & 1) * (scaledTileWidth / 2) - baseOffsetX) / scaledTileWidth);
7663
+ const row = Math.round(screenY / (fh * 0.75));
7664
+ const col = Math.round((screenX - (row & 1) * (w / 2) - baseOffsetX) / w);
7573
7665
  return { x: col, y: row };
7574
7666
  }
7575
7667
  if (layout === "flat") {
7576
- const col = Math.round((screenX - baseOffsetX) / scaledTileWidth);
7577
- const row = Math.round(screenY / scaledTileWidth);
7668
+ const col = Math.round((screenX - baseOffsetX) / w);
7669
+ const row = Math.round(screenY / w);
7578
7670
  return { x: col, y: row };
7579
7671
  }
7580
7672
  const adjustedX = screenX - baseOffsetX;
7581
- const tileX = (adjustedX / (scaledTileWidth / 2) + screenY / (scaledFloorHeight / 2)) / 2;
7582
- const tileY = (screenY / (scaledFloorHeight / 2) - adjustedX / (scaledTileWidth / 2)) / 2;
7673
+ const tileX = (adjustedX / (w / 2) + screenY / (fh / 2)) / 2;
7674
+ const tileY = (screenY / (fh / 2) - adjustedX / (w / 2)) / 2;
7583
7675
  return { x: Math.round(tileX), y: Math.round(tileY) };
7584
7676
  }
7585
- var TILE_WIDTH, FLOOR_HEIGHT, DIAMOND_TOP_Y, BACKGROUND_FALLBACK_COLOR, MINIMAP_TERRAIN_COLORS;
7677
+ var TILE_WIDTH, DIAMOND_TOP_Y, BACKGROUND_FALLBACK_COLOR, MINIMAP_TERRAIN_COLORS;
7586
7678
  var init_isometric = __esm({
7587
7679
  "lib/isometric.ts"() {
7588
7680
  TILE_WIDTH = 256;
7589
- FLOOR_HEIGHT = 128;
7590
7681
  DIAMOND_TOP_Y = 374;
7591
7682
  BACKGROUND_FALLBACK_COLOR = "#1a1a2e";
7592
7683
  MINIMAP_TERRAIN_COLORS = {
@@ -7808,9 +7899,9 @@ function ControlButton({
7808
7899
  className
7809
7900
  }) {
7810
7901
  const eventBus = useEventBus();
7811
- const [isPressed, setIsPressed] = React82.useState(false);
7902
+ const [isPressed, setIsPressed] = React83.useState(false);
7812
7903
  const actualPressed = pressed ?? isPressed;
7813
- const handlePointerDown = React82.useCallback(
7904
+ const handlePointerDown = React83.useCallback(
7814
7905
  (e) => {
7815
7906
  e.preventDefault();
7816
7907
  if (disabled) return;
@@ -7820,7 +7911,7 @@ function ControlButton({
7820
7911
  },
7821
7912
  [disabled, pressEvent, eventBus, onPress]
7822
7913
  );
7823
- const handlePointerUp = React82.useCallback(
7914
+ const handlePointerUp = React83.useCallback(
7824
7915
  (e) => {
7825
7916
  e.preventDefault();
7826
7917
  if (disabled) return;
@@ -7830,7 +7921,7 @@ function ControlButton({
7830
7921
  },
7831
7922
  [disabled, releaseEvent, eventBus, onRelease]
7832
7923
  );
7833
- const handlePointerLeave = React82.useCallback(
7924
+ const handlePointerLeave = React83.useCallback(
7834
7925
  (e) => {
7835
7926
  if (isPressed) {
7836
7927
  setIsPressed(false);
@@ -8088,8 +8179,8 @@ function ControlGrid({
8088
8179
  className
8089
8180
  }) {
8090
8181
  const eventBus = useEventBus();
8091
- const [active, setActive] = React82.useState(/* @__PURE__ */ new Set());
8092
- const handlePress = React82.useCallback(
8182
+ const [active, setActive] = React83.useState(/* @__PURE__ */ new Set());
8183
+ const handlePress = React83.useCallback(
8093
8184
  (id) => {
8094
8185
  setActive((prev) => new Set(prev).add(id));
8095
8186
  if (actionEvent) eventBus.emit(`UI:${actionEvent}`, { id, pressed: true });
@@ -8103,7 +8194,7 @@ function ControlGrid({
8103
8194
  },
8104
8195
  [kind, actionEvent, directionEvent, directionEvents, eventBus, onAction, onDirection]
8105
8196
  );
8106
- const handleRelease = React82.useCallback(
8197
+ const handleRelease = React83.useCallback(
8107
8198
  (id) => {
8108
8199
  setActive((prev) => {
8109
8200
  const next = new Set(prev);
@@ -8461,7 +8552,7 @@ function GameMenu({
8461
8552
  }) {
8462
8553
  const resolvedOptions = (options?.length ? options : void 0) ?? (menuItems?.length ? menuItems : void 0) ?? DEFAULT_MENU_OPTIONS;
8463
8554
  const eventBus = useEventBus();
8464
- const handleOptionClick = React82.useCallback(
8555
+ const handleOptionClick = React83.useCallback(
8465
8556
  (option) => {
8466
8557
  if (option.event) {
8467
8558
  eventBus.emit(`UI:${option.event}`, { option });
@@ -8697,7 +8788,7 @@ function StateGraph({
8697
8788
  }) {
8698
8789
  const eventBus = useEventBus();
8699
8790
  const nodes = states ?? [];
8700
- const positions = React82.useMemo(() => layoutStates(nodes, width, height), [nodes, width, height]);
8791
+ const positions = React83.useMemo(() => layoutStates(nodes, width, height), [nodes, width, height]);
8701
8792
  return /* @__PURE__ */ jsxs(
8702
8793
  Box,
8703
8794
  {
@@ -8768,12 +8859,13 @@ function MiniMap({
8768
8859
  tileAssets,
8769
8860
  unitAssets
8770
8861
  }) {
8771
- const canvasRef = React82.useRef(null);
8772
- const imgCacheRef = React82.useRef(/* @__PURE__ */ new Map());
8862
+ const canvasRef = React83.useRef(null);
8863
+ const imgCacheRef = React83.useRef(/* @__PURE__ */ new Map());
8773
8864
  function loadImg(url) {
8774
8865
  const cached = imgCacheRef.current.get(url);
8775
8866
  if (cached) return cached.complete ? cached : null;
8776
8867
  const img = new Image();
8868
+ img.crossOrigin = "anonymous";
8777
8869
  img.src = url;
8778
8870
  img.onload = () => {
8779
8871
  const canvas = canvasRef.current;
@@ -8784,7 +8876,7 @@ function MiniMap({
8784
8876
  imgCacheRef.current.set(url, img);
8785
8877
  return null;
8786
8878
  }
8787
- React82.useEffect(() => {
8879
+ React83.useEffect(() => {
8788
8880
  const canvas = canvasRef.current;
8789
8881
  if (!canvas) return;
8790
8882
  const ctx = canvas.getContext("2d");
@@ -8941,7 +9033,7 @@ function useCamera(initial) {
8941
9033
  const handleWheel = useCallback((e, drawFn) => {
8942
9034
  e.preventDefault();
8943
9035
  const zoomDelta = e.deltaY > 0 ? 0.9 : 1.1;
8944
- cameraRef.current.zoom = Math.max(0.5, Math.min(3, cameraRef.current.zoom * zoomDelta));
9036
+ cameraRef.current.zoom = Math.max(MIN_ZOOM, Math.min(MAX_ZOOM, cameraRef.current.zoom * zoomDelta));
8945
9037
  drawFn?.();
8946
9038
  }, []);
8947
9039
  const handlePointerDown = useCallback((e) => {
@@ -8962,7 +9054,7 @@ function useCamera(initial) {
8962
9054
  const zoomAtPoint = useCallback((factor, centerX, centerY, viewportSize, drawFn) => {
8963
9055
  const cam = cameraRef.current;
8964
9056
  const oldZoom = cam.zoom;
8965
- const newZoom = Math.max(0.5, Math.min(3, oldZoom * factor));
9057
+ const newZoom = Math.max(MIN_ZOOM, Math.min(MAX_ZOOM, oldZoom * factor));
8966
9058
  if (newZoom === oldZoom) {
8967
9059
  drawFn?.();
8968
9060
  return;
@@ -9014,9 +9106,12 @@ function useCamera(initial) {
9014
9106
  lerpToTarget
9015
9107
  };
9016
9108
  }
9109
+ var MIN_ZOOM, MAX_ZOOM;
9017
9110
  var init_useCamera = __esm({
9018
9111
  "hooks/useCamera.ts"() {
9019
9112
  "use client";
9113
+ MIN_ZOOM = 0.05;
9114
+ MAX_ZOOM = 10;
9020
9115
  }
9021
9116
  });
9022
9117
 
@@ -9030,6 +9125,7 @@ function getOrLoadImage(url, onReady) {
9030
9125
  return null;
9031
9126
  }
9032
9127
  const img = new Image();
9128
+ img.crossOrigin = "anonymous";
9033
9129
  const entry = { img, status: "pending", onReady };
9034
9130
  cache.set(url, entry);
9035
9131
  updateAssetStatus(url, "pending");
@@ -9041,10 +9137,14 @@ function getOrLoadImage(url, onReady) {
9041
9137
  img.onerror = () => {
9042
9138
  entry.status = "failed";
9043
9139
  updateAssetStatus(url, "failed");
9140
+ entry.onReady?.();
9044
9141
  };
9045
9142
  img.src = url;
9046
9143
  return null;
9047
9144
  }
9145
+ function getImageStatus(url) {
9146
+ return cache.get(url)?.status;
9147
+ }
9048
9148
  var cache;
9049
9149
  var init_imageCache = __esm({
9050
9150
  "lib/imageCache.ts"() {
@@ -9183,12 +9283,13 @@ var init_webPainter2d = __esm({
9183
9283
 
9184
9284
  // lib/drawable/projector.ts
9185
9285
  function create2DProjector(opts) {
9186
- const { scale, baseOffsetX, layout } = opts;
9187
- const tileWidth = layout === "free" ? 1 : TILE_WIDTH * scale;
9188
- const floorHeight = layout === "free" ? 1 : FLOOR_HEIGHT * scale;
9189
- const diamondTopY = layout === "free" ? 0 : (opts.diamondTopY ?? DIAMOND_TOP_Y) * scale;
9286
+ const { baseOffsetX, layout } = opts;
9287
+ const tw = opts.tileWidth ?? TILE_WIDTH;
9288
+ const tileWidth = layout === "free" ? 1 : tw;
9289
+ const floorHeight = layout === "free" ? 1 : tw / 2;
9290
+ const diamondTopY = layout === "free" ? 0 : opts.diamondTopY ?? tw * (DIAMOND_TOP_Y / TILE_WIDTH);
9190
9291
  const squareGrid = layout === "flat" || layout === "free";
9191
- const project = (pos) => layout === "free" ? { x: pos.x, y: pos.y } : isoToScreen(pos.x, pos.y, scale, baseOffsetX, layout);
9292
+ const project = (pos) => layout === "free" ? { x: pos.x, y: pos.y } : isoToScreen(pos.x, pos.y, tw, baseOffsetX, layout);
9192
9293
  const anchorPoint = (pos, anchor) => {
9193
9294
  const base = project(pos);
9194
9295
  if (anchor === "top-left") return base;
@@ -9219,7 +9320,7 @@ function create2DProjector(opts) {
9219
9320
  { x: base.x, y: topY + floorHeight / 2 }
9220
9321
  ];
9221
9322
  };
9222
- return { project, anchorPoint, cellPath, tileWidth, floorHeight, diamondTopY, scale, squareGrid };
9323
+ return { project, anchorPoint, cellPath, tileWidth, floorHeight, diamondTopY, squareGrid, worldPixelDirect: layout === "free" };
9223
9324
  }
9224
9325
  var init_projector = __esm({
9225
9326
  "lib/drawable/projector.ts"() {
@@ -9235,32 +9336,67 @@ var init_contract = __esm({
9235
9336
  "lib/drawable/contract.ts"() {
9236
9337
  }
9237
9338
  });
9238
-
9239
- // components/game/atoms/DrawSprite.tsx
9339
+ function warnMissingOnce(reason, node) {
9340
+ const key = `${reason}:${node.asset.url}:${String(node.asset.atlas)}:${String(node.asset.sprite)}`;
9341
+ if (loggedMissing.has(key)) return;
9342
+ loggedMissing.add(key);
9343
+ spriteLog.warn("draw-sprite asset unresolvable \u2014 painting fallback square", { reason, url: node.asset.url, atlas: node.asset.atlas, sprite: node.asset.sprite });
9344
+ }
9345
+ function paintFallbackSquare(painter, node, dctx, reason) {
9346
+ warnMissingOnce(reason, node);
9347
+ const tw = dctx.projector.tileWidth;
9348
+ const natural = dctx.projector.worldPixelDirect ? FALLBACK_WORLD_PX : tw;
9349
+ const w = node.width !== void 0 ? node.width * tw : natural;
9350
+ const h = node.height !== void 0 ? node.height * tw : natural;
9351
+ const anchor = node.anchor ?? "top-left";
9352
+ const p = dctx.projector.anchorPoint(node.position, anchor);
9353
+ const dx = anchor === "top-left" ? p.x : p.x - w / 2;
9354
+ const dy = anchor === "ground" ? p.y - h : anchor === "center" ? p.y - h / 2 : p.y;
9355
+ painter.save();
9356
+ if (node.opacity !== void 0 && node.opacity !== 1) painter.setAlpha(node.opacity);
9357
+ painter.fillRect(dx, dy, w, h, "#9b8f7f");
9358
+ painter.strokeRect(dx, dy, w, h, "#5e564b", Math.max(1, tw / 32));
9359
+ painter.restore();
9360
+ }
9240
9361
  function DrawSprite(_props) {
9241
9362
  return null;
9242
9363
  }
9243
- var paintSprite;
9364
+ var spriteLog, loggedMissing, FALLBACK_WORLD_PX, paintSprite;
9244
9365
  var init_DrawSprite = __esm({
9245
9366
  "components/game/atoms/DrawSprite.tsx"() {
9246
9367
  "use client";
9247
9368
  init_atlasSlice();
9369
+ init_imageCache();
9248
9370
  init_contract();
9371
+ spriteLog = createLogger("almadar:ui:draw-sprite");
9372
+ loggedMissing = /* @__PURE__ */ new Set();
9373
+ FALLBACK_WORLD_PX = 32;
9249
9374
  paintSprite = (painter, node, dctx) => {
9250
9375
  if (!node.asset?.url || !isValidScenePos(node.position)) return;
9251
9376
  const tex = painter.resolveTexture(node.asset.url);
9252
- if (!tex) return;
9377
+ if (!tex) {
9378
+ if (getImageStatus(node.asset.url) === "failed") paintFallbackSquare(painter, node, dctx, "texture-failed");
9379
+ return;
9380
+ }
9253
9381
  let src = typeof node.frame === "object" ? node.frame : void 0;
9254
9382
  if (!src && isAtlasAsset(node.asset)) {
9255
9383
  const atlas = getAtlas(node.asset.atlas, dctx.invalidate);
9256
- if (!atlas) return;
9384
+ if (!atlas) {
9385
+ if (atlasFailed(node.asset.atlas)) paintFallbackSquare(painter, node, dctx, "atlas-failed");
9386
+ return;
9387
+ }
9257
9388
  const r = subRectFor(atlas, node.asset.sprite);
9258
- if (!r) return;
9389
+ if (!r) {
9390
+ paintFallbackSquare(painter, node, dctx, "sprite-missing");
9391
+ return;
9392
+ }
9259
9393
  src = { x: r.sx, y: r.sy, w: r.sw, h: r.sh };
9260
9394
  }
9261
9395
  const tw = dctx.projector.tileWidth;
9262
- const w = node.width !== void 0 ? node.width * tw : src ? src.w : tex.width;
9263
- const h = node.height !== void 0 ? node.height * tw : src ? src.h : tex.height;
9396
+ const fallbackW = dctx.projector.worldPixelDirect ? src ? src.w : tex.width : tw;
9397
+ const fallbackH = dctx.projector.worldPixelDirect ? src ? src.h : tex.height : tw;
9398
+ const w = node.width !== void 0 ? node.width * tw : fallbackW;
9399
+ const h = node.height !== void 0 ? node.height * tw : fallbackH;
9264
9400
  const anchor = node.anchor ?? "top-left";
9265
9401
  const p = dctx.projector.anchorPoint(node.position, anchor);
9266
9402
  const dx = anchor === "top-left" ? p.x : p.x - w / 2;
@@ -9526,6 +9662,8 @@ function Canvas2D({
9526
9662
  keyUpMap,
9527
9663
  camera = "pan-zoom",
9528
9664
  scale = 0.4,
9665
+ tileWidth,
9666
+ fit = false,
9529
9667
  showMinimap = true,
9530
9668
  followTarget,
9531
9669
  cameraPos,
@@ -9568,9 +9706,32 @@ function Canvas2D({
9568
9706
  observer2.observe(el);
9569
9707
  return () => observer2.disconnect();
9570
9708
  }, []);
9571
- const scaledTileWidth = TILE_WIDTH * scale;
9572
- const scaledFloorHeight = FLOOR_HEIGHT * scale;
9573
- const scaledDiamondTopY = DIAMOND_TOP_Y * scale;
9709
+ const [atlasVersion, setAtlasVersion] = useState(0);
9710
+ const bumpAtlas = useCallback(() => setAtlasVersion((v) => v + 1), []);
9711
+ const detectedTileWidth = useMemo(() => {
9712
+ for (const n of drawables ?? []) {
9713
+ const refs = [];
9714
+ if (n.type === "draw-sprite") refs.push(n.asset);
9715
+ else if (n.type === "draw-sprite-layer") for (const it of n.items) refs.push(it.asset);
9716
+ for (const a of refs) {
9717
+ if (a && isAtlasAsset(a) && a.atlas) {
9718
+ const atlas = getAtlas(a.atlas, bumpAtlas);
9719
+ if (atlas) {
9720
+ if ("tileWidth" in atlas) return atlas.tileWidth;
9721
+ if ("subTextures" in atlas) {
9722
+ const first = Object.values(atlas.subTextures)[0];
9723
+ if (first && typeof first.width === "number") return first.width;
9724
+ }
9725
+ }
9726
+ }
9727
+ }
9728
+ }
9729
+ return void 0;
9730
+ }, [drawables, atlasVersion]);
9731
+ const nativeTileW = tileWidth ?? detectedTileWidth ?? TILE_WIDTH;
9732
+ const scaledTileWidth = nativeTileW;
9733
+ const scaledFloorHeight = nativeTileW / 2;
9734
+ const scaledDiamondTopY = nativeTileW * (DIAMOND_TOP_Y / TILE_WIDTH);
9574
9735
  const drawnItems = useMemo(() => collectDrawnItems(drawables ?? []), [drawables]);
9575
9736
  const scenePositions = useMemo(() => drawnItems.map((i) => i.pos), [drawnItems]);
9576
9737
  const hitIndex = useMemo(() => buildHitIndex(drawnItems), [drawnItems]);
@@ -9584,18 +9745,45 @@ function Canvas2D({
9584
9745
  }
9585
9746
  return { width: maxX + 1, height: maxY + 1 };
9586
9747
  }, [scenePositions]);
9748
+ const defaultGridFocus = useMemo(() => {
9749
+ if (isFree || projection === "side") return void 0;
9750
+ if (gridExtent.width < 2 || gridExtent.height < 2) return void 0;
9751
+ return { x: (gridExtent.width - 1) / 2, y: (gridExtent.height - 1) / 2 };
9752
+ }, [isFree, projection, gridExtent]);
9587
9753
  const baseOffsetX = useMemo(() => {
9588
9754
  if (isFree || projection === "flat" || projection === "side") return 0;
9589
9755
  return (gridExtent.height - 1) * (scaledTileWidth / 2);
9590
9756
  }, [isFree, projection, gridExtent.height, scaledTileWidth]);
9757
+ const effectiveZoom = useMemo(() => {
9758
+ if (isFree || projection === "side") return scale;
9759
+ if (!fit) {
9760
+ const z2 = TILE_WIDTH * scale * scale / nativeTileW;
9761
+ return Number.isFinite(z2) && z2 > 0 ? z2 : scale;
9762
+ }
9763
+ if (!viewportSize.width || gridExtent.width < 2 || gridExtent.height < 2) return scale;
9764
+ let boardW;
9765
+ let boardH;
9766
+ if (projection === "flat") {
9767
+ boardW = gridExtent.width * nativeTileW;
9768
+ boardH = gridExtent.height * nativeTileW;
9769
+ } else if (projection === "hex") {
9770
+ boardW = (gridExtent.width + 0.5) * nativeTileW;
9771
+ boardH = gridExtent.height * (nativeTileW / 2) * 0.75 + nativeTileW / 2;
9772
+ } else {
9773
+ boardW = (gridExtent.width + gridExtent.height) * (nativeTileW / 2);
9774
+ boardH = (gridExtent.width + gridExtent.height) * (nativeTileW / 4);
9775
+ }
9776
+ const z = Math.min(viewportSize.width * 0.85 / boardW, viewportSize.height * 0.85 / boardH);
9777
+ return Number.isFinite(z) && z > 0 ? z : scale;
9778
+ }, [isFree, projection, fit, viewportSize, gridExtent, nativeTileW, scale]);
9591
9779
  const projector = useMemo(
9592
- () => create2DProjector({ scale, baseOffsetX, layout }),
9593
- [scale, baseOffsetX, layout]
9780
+ () => create2DProjector({ tileWidth: nativeTileW, baseOffsetX, layout }),
9781
+ [nativeTileW, baseOffsetX, layout]
9594
9782
  );
9595
9783
  const unproject = useCallback((screenX, screenY) => {
9596
9784
  if (projection === "free" || projection === "side") return { x: Math.round(screenX), y: Math.round(screenY) };
9597
- return screenToIso(screenX, screenY, scale, baseOffsetX, projection);
9598
- }, [projection, scale, baseOffsetX]);
9785
+ return screenToIso(screenX, screenY, nativeTileW, baseOffsetX, projection);
9786
+ }, [projection, nativeTileW, baseOffsetX]);
9599
9787
  const bgUrls = useMemo(() => backgroundImage ? [backgroundImage.url] : [], [backgroundImage]);
9600
9788
  const { getImage, pendingCount: _imagePendingCount } = useImageCache(bgUrls);
9601
9789
  useEffect(() => {
@@ -9622,9 +9810,7 @@ function Canvas2D({
9622
9810
  zoomAtPoint,
9623
9811
  screenToWorld,
9624
9812
  lerpToTarget
9625
- } = useCamera({ zoom: scale });
9626
- const [atlasVersion, setAtlasVersion] = useState(0);
9627
- const bumpAtlas = useCallback(() => setAtlasVersion((v) => v + 1), []);
9813
+ } = useCamera({ zoom: effectiveZoom });
9628
9814
  const miniMapTiles = useMemo(() => {
9629
9815
  if (!showMinimap) return [];
9630
9816
  const color = MINIMAP_TERRAIN_COLORS.default;
@@ -9668,10 +9854,13 @@ function Canvas2D({
9668
9854
  }
9669
9855
  if (!drawables || drawables.length === 0) return;
9670
9856
  const cam = cameraRef.current;
9671
- if (cameraPos && dragDistance() === 0) {
9672
- const p = projector.anchorPoint(cameraPos, "center");
9673
- cam.x = p.x - viewportSize.width / 2;
9674
- cam.y = p.y - viewportSize.height / 2;
9857
+ if (camera !== "follow" && dragDistance() === 0) {
9858
+ const focus = cameraPos ?? defaultGridFocus;
9859
+ if (focus) {
9860
+ const p = projector.anchorPoint(focus, "center");
9861
+ cam.x = p.x - viewportSize.width / 2;
9862
+ cam.y = p.y - viewportSize.height / 2;
9863
+ }
9675
9864
  }
9676
9865
  const containerRect = containerRef.current?.getBoundingClientRect();
9677
9866
  const canvasRect = canvas.getBoundingClientRect();
@@ -9684,7 +9873,7 @@ function Canvas2D({
9684
9873
  const dctx = { projector, time: 0, invalidate: bumpAtlas };
9685
9874
  for (const node of drawables) paintDrawable(painter, node, dctx);
9686
9875
  painter.restore();
9687
- }, [viewportSize, backgroundImage, bgColor, drawables, projector, cameraRef, bumpAtlas, getImage]);
9876
+ }, [viewportSize, backgroundImage, bgColor, drawables, projector, cameraRef, bumpAtlas, getImage, cameraPos, defaultGridFocus, camera, dragDistance]);
9688
9877
  useEffect(() => {
9689
9878
  if (camera !== "follow" || !followTarget) return;
9690
9879
  const p = projector.anchorPoint(followTarget, "center");
@@ -9699,6 +9888,13 @@ function Canvas2D({
9699
9888
  useEffect(() => {
9700
9889
  draw();
9701
9890
  }, [_imagePendingCount, draw]);
9891
+ const userZoomedRef = useRef(false);
9892
+ useEffect(() => {
9893
+ if (userZoomedRef.current) return;
9894
+ if (cameraRef.current.zoom === effectiveZoom) return;
9895
+ cameraRef.current.zoom = effectiveZoom;
9896
+ draw();
9897
+ }, [effectiveZoom, cameraRef, draw]);
9702
9898
  useEffect(() => {
9703
9899
  draw();
9704
9900
  }, [atlasVersion, draw]);
@@ -9755,7 +9951,9 @@ function Canvas2D({
9755
9951
  if (tileLeaveEvent) eventBus.emit(`UI:${tileLeaveEvent}`, {});
9756
9952
  }, [handleMouseLeave, tileLeaveEvent, eventBus]);
9757
9953
  const applyZoom = useCallback((factor, centerX, centerY) => {
9758
- if (enableCamera) zoomAtPoint(factor, centerX, centerY, viewportSize, () => draw());
9954
+ if (!enableCamera) return;
9955
+ userZoomedRef.current = true;
9956
+ zoomAtPoint(factor, centerX, centerY, viewportSize, () => draw());
9759
9957
  }, [enableCamera, zoomAtPoint, viewportSize, draw]);
9760
9958
  const applyPanDelta = useCallback((dx, dy) => {
9761
9959
  if (enableCamera) panBy(dx, dy, () => draw());
@@ -9940,6 +10138,8 @@ function Canvas({
9940
10138
  isLoading,
9941
10139
  unitScale,
9942
10140
  showMinimap,
10141
+ fit,
10142
+ tileWidth,
9943
10143
  backgroundImage,
9944
10144
  backgroundColor,
9945
10145
  worldWidth,
@@ -9997,6 +10197,8 @@ function Canvas({
9997
10197
  projection,
9998
10198
  camera: to2DCamera(camera?.mode),
9999
10199
  ...zoom !== void 0 ? { scale: zoom } : {},
10200
+ ...fit !== void 0 ? { fit } : {},
10201
+ ...tileWidth !== void 0 ? { tileWidth } : {},
10000
10202
  ...camera?.target !== void 0 ? { followTarget: camera.target } : {},
10001
10203
  ...camera?.pos !== void 0 ? { cameraPos: camera.pos } : {},
10002
10204
  showMinimap,
@@ -10139,7 +10341,7 @@ function LinearView({
10139
10341
  /* @__PURE__ */ jsx(HStack, { className: "flex-wrap items-center", gap: "xs", children: trait.states.map((state, i) => {
10140
10342
  const isDone = i < currentIdx;
10141
10343
  const isCurrent = i === currentIdx;
10142
- return /* @__PURE__ */ jsxs(React82__default.Fragment, { children: [
10344
+ return /* @__PURE__ */ jsxs(React83__default.Fragment, { children: [
10143
10345
  i > 0 && /* @__PURE__ */ jsx(
10144
10346
  Typography,
10145
10347
  {
@@ -10674,7 +10876,7 @@ function SequenceBar({
10674
10876
  else onSlotRemove?.(index);
10675
10877
  }, [emit, slotRemoveEvent, onSlotRemove, playing]);
10676
10878
  const paddedSlots = Array.from({ length: maxSlots }, (_, i) => slots[i]);
10677
- return /* @__PURE__ */ jsx(HStack, { className: cn("items-center", className), gap: "sm", children: paddedSlots.map((slot, i) => /* @__PURE__ */ jsxs(React82__default.Fragment, { children: [
10879
+ return /* @__PURE__ */ jsx(HStack, { className: cn("items-center", className), gap: "sm", children: paddedSlots.map((slot, i) => /* @__PURE__ */ jsxs(React83__default.Fragment, { children: [
10678
10880
  i > 0 && /* @__PURE__ */ jsx(
10679
10881
  Typography,
10680
10882
  {
@@ -11323,7 +11525,7 @@ var init_ErrorBoundary = __esm({
11323
11525
  }
11324
11526
  );
11325
11527
  };
11326
- ErrorBoundary = class extends React82__default.Component {
11528
+ ErrorBoundary = class extends React83__default.Component {
11327
11529
  constructor(props) {
11328
11530
  super(props);
11329
11531
  __publicField(this, "reset", () => {
@@ -11592,7 +11794,7 @@ var init_Container = __esm({
11592
11794
  as: Component = "div"
11593
11795
  }) => {
11594
11796
  const resolvedSize = maxWidth ?? size ?? "lg";
11595
- return React82__default.createElement(
11797
+ return React83__default.createElement(
11596
11798
  Component,
11597
11799
  {
11598
11800
  className: cn(
@@ -14557,7 +14759,7 @@ var init_CodeBlock = __esm({
14557
14759
  DIFF_STYLE_FALLBACK = { bg: "", prefix: " ", text: "text-foreground" };
14558
14760
  LINE_PROPS_FN = (n) => ({ "data-line": String(n - 1) });
14559
14761
  HIDDEN_LINE_NUMBERS = { display: "none" };
14560
- CodeBlock = React82__default.memo(
14762
+ CodeBlock = React83__default.memo(
14561
14763
  ({
14562
14764
  code: rawCode,
14563
14765
  language = "text",
@@ -15145,7 +15347,7 @@ var init_MarkdownContent = __esm({
15145
15347
  init_Box();
15146
15348
  init_CodeBlock();
15147
15349
  init_cn();
15148
- MarkdownContent = React82__default.memo(
15350
+ MarkdownContent = React83__default.memo(
15149
15351
  ({ content, direction = "ltr", className }) => {
15150
15352
  const { t: _t } = useTranslate();
15151
15353
  const safeContent = typeof content === "string" ? content : String(content ?? "");
@@ -16422,7 +16624,7 @@ var init_StateMachineView = __esm({
16422
16624
  style: { top: title ? 30 : 0 },
16423
16625
  children: [
16424
16626
  entity && /* @__PURE__ */ jsx(EntityBox, { entity, config }),
16425
- states.map((state) => renderStateNode ? /* @__PURE__ */ jsx(React82__default.Fragment, { children: renderStateNode(state, config) }, state.id) : /* @__PURE__ */ jsx(
16627
+ states.map((state) => renderStateNode ? /* @__PURE__ */ jsx(React83__default.Fragment, { children: renderStateNode(state, config) }, state.id) : /* @__PURE__ */ jsx(
16426
16628
  StateNode2,
16427
16629
  {
16428
16630
  state,
@@ -22163,8 +22365,8 @@ var init_Menu = __esm({
22163
22365
  "bottom-end": "bottom-start"
22164
22366
  };
22165
22367
  const effectivePosition = direction === "rtl" ? rtlMirror[position] ?? position : position;
22166
- const triggerChild = React82__default.isValidElement(trigger) ? trigger : /* @__PURE__ */ jsx(Typography, { variant: "small", as: "span", children: trigger });
22167
- const triggerElement = React82__default.cloneElement(
22368
+ const triggerChild = React83__default.isValidElement(trigger) ? trigger : /* @__PURE__ */ jsx(Typography, { variant: "small", as: "span", children: trigger });
22369
+ const triggerElement = React83__default.cloneElement(
22168
22370
  triggerChild,
22169
22371
  {
22170
22372
  ref: triggerRef,
@@ -22259,14 +22461,14 @@ function useDataDnd(args) {
22259
22461
  const isZone = Boolean(dragGroup || accepts || sortable);
22260
22462
  const enabled = isZone || Boolean(dndRoot);
22261
22463
  const eventBus = useEventBus();
22262
- const parentRoot = React82__default.useContext(RootCtx);
22464
+ const parentRoot = React83__default.useContext(RootCtx);
22263
22465
  const isRoot = enabled && parentRoot === null;
22264
- const zoneId = React82__default.useId();
22466
+ const zoneId = React83__default.useId();
22265
22467
  const ownGroup = dragGroup ?? accepts ?? zoneId;
22266
- const [optimisticOrders, setOptimisticOrders] = React82__default.useState(() => /* @__PURE__ */ new Map());
22267
- const optimisticOrdersRef = React82__default.useRef(optimisticOrders);
22468
+ const [optimisticOrders, setOptimisticOrders] = React83__default.useState(() => /* @__PURE__ */ new Map());
22469
+ const optimisticOrdersRef = React83__default.useRef(optimisticOrders);
22268
22470
  optimisticOrdersRef.current = optimisticOrders;
22269
- const clearOptimisticOrder = React82__default.useCallback((group) => {
22471
+ const clearOptimisticOrder = React83__default.useCallback((group) => {
22270
22472
  setOptimisticOrders((prev) => {
22271
22473
  if (!prev.has(group)) return prev;
22272
22474
  const next = new Map(prev);
@@ -22291,7 +22493,7 @@ function useDataDnd(args) {
22291
22493
  const raw = it[dndItemIdField];
22292
22494
  return raw != null ? String(raw) : `__idx_${idx}`;
22293
22495
  }).join("|");
22294
- const itemIds = React82__default.useMemo(
22496
+ const itemIds = React83__default.useMemo(
22295
22497
  () => orderedItems.map((it, idx) => {
22296
22498
  const raw = it[dndItemIdField];
22297
22499
  return raw != null ? String(raw) : `__idx_${idx}`;
@@ -22302,7 +22504,7 @@ function useDataDnd(args) {
22302
22504
  const raw = it[dndItemIdField];
22303
22505
  return raw != null ? String(raw) : `__${idx}`;
22304
22506
  }).join("|");
22305
- React82__default.useEffect(() => {
22507
+ React83__default.useEffect(() => {
22306
22508
  const root = isRoot ? null : parentRoot;
22307
22509
  if (root) {
22308
22510
  root.clearOptimisticOrder(ownGroup);
@@ -22310,20 +22512,20 @@ function useDataDnd(args) {
22310
22512
  clearOptimisticOrder(ownGroup);
22311
22513
  }
22312
22514
  }, [itemsContentSig, ownGroup]);
22313
- const zonesRef = React82__default.useRef(/* @__PURE__ */ new Map());
22314
- const registerZone = React82__default.useCallback((zoneId2, meta2) => {
22515
+ const zonesRef = React83__default.useRef(/* @__PURE__ */ new Map());
22516
+ const registerZone = React83__default.useCallback((zoneId2, meta2) => {
22315
22517
  zonesRef.current.set(zoneId2, meta2);
22316
22518
  }, []);
22317
- const unregisterZone = React82__default.useCallback((zoneId2) => {
22519
+ const unregisterZone = React83__default.useCallback((zoneId2) => {
22318
22520
  zonesRef.current.delete(zoneId2);
22319
22521
  }, []);
22320
- const [activeDrag, setActiveDrag] = React82__default.useState(null);
22321
- const [overZoneGroup, setOverZoneGroup] = React82__default.useState(null);
22322
- const meta = React82__default.useMemo(
22522
+ const [activeDrag, setActiveDrag] = React83__default.useState(null);
22523
+ const [overZoneGroup, setOverZoneGroup] = React83__default.useState(null);
22524
+ const meta = React83__default.useMemo(
22323
22525
  () => ({ group: ownGroup, dropEvent, reorderEvent, positionEvent, itemIds, rawItems: items, idField: dndItemIdField }),
22324
22526
  [ownGroup, dropEvent, reorderEvent, positionEvent, itemIds, items, dndItemIdField]
22325
22527
  );
22326
- React82__default.useEffect(() => {
22528
+ React83__default.useEffect(() => {
22327
22529
  const target = isRoot ? null : parentRoot;
22328
22530
  if (!target) {
22329
22531
  zonesRef.current.set(zoneId, meta);
@@ -22342,7 +22544,7 @@ function useDataDnd(args) {
22342
22544
  }, [parentRoot, isRoot, zoneId, meta]);
22343
22545
  const sensors = useAlmadarDndSensors(true);
22344
22546
  const collisionDetection = almadarDndCollisionDetection;
22345
- const findZoneByItem = React82__default.useCallback(
22547
+ const findZoneByItem = React83__default.useCallback(
22346
22548
  (id) => {
22347
22549
  for (const z of zonesRef.current.values()) {
22348
22550
  if (z.itemIds.includes(id)) return z;
@@ -22351,7 +22553,7 @@ function useDataDnd(args) {
22351
22553
  },
22352
22554
  []
22353
22555
  );
22354
- React82__default.useCallback(
22556
+ React83__default.useCallback(
22355
22557
  (group) => {
22356
22558
  for (const z of zonesRef.current.values()) {
22357
22559
  if (z.group === group) return z;
@@ -22360,7 +22562,7 @@ function useDataDnd(args) {
22360
22562
  },
22361
22563
  []
22362
22564
  );
22363
- const handleDragEnd = React82__default.useCallback(
22565
+ const handleDragEnd = React83__default.useCallback(
22364
22566
  (event) => {
22365
22567
  const { active, over } = event;
22366
22568
  const activeIdStr = String(active.id);
@@ -22451,8 +22653,8 @@ function useDataDnd(args) {
22451
22653
  },
22452
22654
  [eventBus]
22453
22655
  );
22454
- const sortableData = React82__default.useMemo(() => ({ dndGroup: ownGroup }), [ownGroup]);
22455
- const SortableItem = React82__default.useCallback(
22656
+ const sortableData = React83__default.useMemo(() => ({ dndGroup: ownGroup }), [ownGroup]);
22657
+ const SortableItem = React83__default.useCallback(
22456
22658
  ({ id, children }) => {
22457
22659
  const {
22458
22660
  attributes,
@@ -22492,7 +22694,7 @@ function useDataDnd(args) {
22492
22694
  id: droppableId,
22493
22695
  data: sortableData
22494
22696
  });
22495
- const ctx = React82__default.useContext(RootCtx);
22697
+ const ctx = React83__default.useContext(RootCtx);
22496
22698
  const activeDrag2 = ctx?.activeDrag ?? null;
22497
22699
  const overZoneGroup2 = ctx?.overZoneGroup ?? null;
22498
22700
  const isThisZoneOver = overZoneGroup2 === ownGroup;
@@ -22507,7 +22709,7 @@ function useDataDnd(args) {
22507
22709
  showForeignPlaceholder,
22508
22710
  ctxAvailable: ctx != null
22509
22711
  });
22510
- React82__default.useEffect(() => {
22712
+ React83__default.useEffect(() => {
22511
22713
  dndLog.info("dropzone:isOver:change", { droppableId, group: ownGroup, isOver, isThisZoneOver, showForeignPlaceholder, activeDragSourceGroup: activeDrag2?.sourceGroup ?? null });
22512
22714
  }, [droppableId, isOver, isThisZoneOver, showForeignPlaceholder]);
22513
22715
  return /* @__PURE__ */ jsx(
@@ -22521,11 +22723,11 @@ function useDataDnd(args) {
22521
22723
  }
22522
22724
  );
22523
22725
  };
22524
- const rootContextValue = React82__default.useMemo(
22726
+ const rootContextValue = React83__default.useMemo(
22525
22727
  () => ({ registerZone, unregisterZone, activeDrag, overZoneGroup, optimisticOrders, clearOptimisticOrder }),
22526
22728
  [registerZone, unregisterZone, activeDrag, overZoneGroup, optimisticOrders, clearOptimisticOrder]
22527
22729
  );
22528
- const handleDragStart = React82__default.useCallback((event) => {
22730
+ const handleDragStart = React83__default.useCallback((event) => {
22529
22731
  const sourceZone = findZoneByItem(event.active.id);
22530
22732
  const rect = event.active.rect.current.initial;
22531
22733
  const height = rect?.height && rect.height > 0 ? rect.height : 64;
@@ -22544,7 +22746,7 @@ function useDataDnd(args) {
22544
22746
  isRoot
22545
22747
  });
22546
22748
  }, [findZoneByItem, isRoot, zoneId]);
22547
- const handleDragOver = React82__default.useCallback((event) => {
22749
+ const handleDragOver = React83__default.useCallback((event) => {
22548
22750
  const { active, over } = event;
22549
22751
  const overData = over?.data?.current;
22550
22752
  const overGroup = overData?.dndGroup ?? null;
@@ -22614,7 +22816,7 @@ function useDataDnd(args) {
22614
22816
  return next;
22615
22817
  });
22616
22818
  }, []);
22617
- const handleDragCancel = React82__default.useCallback((event) => {
22819
+ const handleDragCancel = React83__default.useCallback((event) => {
22618
22820
  setActiveDrag(null);
22619
22821
  setOverZoneGroup(null);
22620
22822
  dndLog.warn("dragCancel", {
@@ -22622,12 +22824,12 @@ function useDataDnd(args) {
22622
22824
  reason: "dnd-kit cancelled the drag (escape key, pointer interrupted, or external)"
22623
22825
  });
22624
22826
  }, []);
22625
- const handleDragEndWithCleanup = React82__default.useCallback((event) => {
22827
+ const handleDragEndWithCleanup = React83__default.useCallback((event) => {
22626
22828
  handleDragEnd(event);
22627
22829
  setActiveDrag(null);
22628
22830
  setOverZoneGroup(null);
22629
22831
  }, [handleDragEnd]);
22630
- const wrapContainer = React82__default.useCallback(
22832
+ const wrapContainer = React83__default.useCallback(
22631
22833
  (children) => {
22632
22834
  if (!enabled) return children;
22633
22835
  const strategy = layout === "grid" ? rectSortingStrategy : verticalListSortingStrategy;
@@ -22681,7 +22883,7 @@ var init_useDataDnd = __esm({
22681
22883
  init_useAlmadarDndCollision();
22682
22884
  init_Box();
22683
22885
  dndLog = createLogger("almadar:ui:dnd");
22684
- RootCtx = React82__default.createContext(null);
22886
+ RootCtx = React83__default.createContext(null);
22685
22887
  }
22686
22888
  });
22687
22889
  function renderIconInput(icon, props) {
@@ -23223,7 +23425,7 @@ function DataList({
23223
23425
  }) {
23224
23426
  const eventBus = useEventBus();
23225
23427
  const { t } = useTranslate();
23226
- const [visibleCount, setVisibleCount] = React82__default.useState(pageSize || Infinity);
23428
+ const [visibleCount, setVisibleCount] = React83__default.useState(pageSize || Infinity);
23227
23429
  const fieldDefs = fields ?? columns ?? [];
23228
23430
  const allDataRaw = Array.isArray(entity) ? entity : entity ? [entity] : [];
23229
23431
  const dnd = useDataDnd({
@@ -23239,14 +23441,14 @@ function DataList({
23239
23441
  dndRoot
23240
23442
  });
23241
23443
  const orderedData = dnd.orderedItems;
23242
- const allData = React82__default.useMemo(
23444
+ const allData = React83__default.useMemo(
23243
23445
  () => sortRows(orderedData, sortBy, sortDirection),
23244
23446
  [orderedData, sortBy, sortDirection]
23245
23447
  );
23246
23448
  const data = pageSize > 0 ? allData.slice(0, visibleCount) : allData;
23247
23449
  const hasMoreLocal = pageSize > 0 && visibleCount < allData.length;
23248
23450
  const hasRenderProp = typeof children === "function";
23249
- React82__default.useEffect(() => {
23451
+ React83__default.useEffect(() => {
23250
23452
  const renderItemTypeOf = typeof schemaRenderItem;
23251
23453
  const childrenTypeOf = typeof children;
23252
23454
  if (data.length > 0 && !hasRenderProp) {
@@ -23361,7 +23563,7 @@ function DataList({
23361
23563
  return v === void 0 || v === null || v === "" ? raw : String(v);
23362
23564
  };
23363
23565
  return /* @__PURE__ */ jsxs(VStack, { gap: "sm", className: cn("py-2", className), children: [
23364
- groups2.map((group, gi) => /* @__PURE__ */ jsxs(React82__default.Fragment, { children: [
23566
+ groups2.map((group, gi) => /* @__PURE__ */ jsxs(React83__default.Fragment, { children: [
23365
23567
  group.label && /* @__PURE__ */ jsx(Divider, { label: group.label, className: "my-2" }),
23366
23568
  group.items.map((itemData, index) => {
23367
23569
  const id = itemData.id || `${gi}-${index}`;
@@ -23397,7 +23599,11 @@ function DataList({
23397
23599
  metaFields.length > 0 && /* @__PURE__ */ jsx(HStack, { gap: "xs", className: "mt-1 flex-wrap", children: metaFields.map((f3) => {
23398
23600
  const v = getNestedValue(itemData, f3.name);
23399
23601
  if (v === void 0 || v === null || v === "") return null;
23400
- return f3.variant === "badge" ? /* @__PURE__ */ jsx(Badge, { variant: statusVariant3(String(v)), children: String(v) }, f3.name) : /* @__PURE__ */ jsx(
23602
+ return f3.variant === "badge" ? (
23603
+ // `format` applies here too — a boolean field badged
23604
+ // without it renders the raw "false" instead of "No".
23605
+ /* @__PURE__ */ jsx(Badge, { variant: statusVariant3(String(v)), children: formatValue2(v, f3.format) }, f3.name)
23606
+ ) : /* @__PURE__ */ jsx(
23401
23607
  Typography,
23402
23608
  {
23403
23609
  variant: "caption",
@@ -23509,7 +23715,7 @@ function DataList({
23509
23715
  if (val === void 0 || val === null) return null;
23510
23716
  return /* @__PURE__ */ jsxs(HStack, { gap: "xs", className: "items-center flex-shrink-0", children: [
23511
23717
  field.icon && renderIconInput2(field.icon, { size: "xs" }),
23512
- /* @__PURE__ */ jsx(Badge, { variant: statusVariant3(String(val)), children: String(val) })
23718
+ /* @__PURE__ */ jsx(Badge, { variant: statusVariant3(String(val)), children: formatValue2(val, field.format) })
23513
23719
  ] }, field.name);
23514
23720
  })
23515
23721
  ] }),
@@ -23556,7 +23762,7 @@ function DataList({
23556
23762
  className
23557
23763
  ),
23558
23764
  children: [
23559
- groups.map((group, gi) => /* @__PURE__ */ jsxs(React82__default.Fragment, { children: [
23765
+ groups.map((group, gi) => /* @__PURE__ */ jsxs(React83__default.Fragment, { children: [
23560
23766
  group.label && /* @__PURE__ */ jsx(Divider, { label: group.label, className: gi > 0 ? "mt-4" : "mt-0" }),
23561
23767
  group.items.map(
23562
23768
  (itemData, index) => renderItem(itemData, index, gi === groups.length - 1 && index === group.items.length - 1)
@@ -23643,7 +23849,7 @@ var init_FormSection = __esm({
23643
23849
  columns = 1,
23644
23850
  className
23645
23851
  }) => {
23646
- const [collapsed, setCollapsed] = React82__default.useState(defaultCollapsed);
23852
+ const [collapsed, setCollapsed] = React83__default.useState(defaultCollapsed);
23647
23853
  const { t } = useTranslate();
23648
23854
  const eventBus = useEventBus();
23649
23855
  const gridClass = {
@@ -23651,7 +23857,7 @@ var init_FormSection = __esm({
23651
23857
  2: "grid-cols-1 md:grid-cols-2",
23652
23858
  3: "grid-cols-1 md:grid-cols-2 lg:grid-cols-3"
23653
23859
  }[columns];
23654
- React82__default.useCallback(() => {
23860
+ React83__default.useCallback(() => {
23655
23861
  if (collapsible) {
23656
23862
  setCollapsed((prev) => !prev);
23657
23863
  eventBus.emit("UI:TOGGLE_COLLAPSE", { collapsed: !collapsed });
@@ -23748,6 +23954,182 @@ var init_FormSection = __esm({
23748
23954
  FormActions.displayName = "FormActions";
23749
23955
  }
23750
23956
  });
23957
+ var ALL_CATEGORY, MAX_RENDERED, GridPicker;
23958
+ var init_GridPicker = __esm({
23959
+ "components/core/molecules/GridPicker.tsx"() {
23960
+ "use client";
23961
+ init_cn();
23962
+ init_Input();
23963
+ init_Badge();
23964
+ init_Stack();
23965
+ ALL_CATEGORY = "__all__";
23966
+ MAX_RENDERED = 300;
23967
+ GridPicker = ({
23968
+ items,
23969
+ value,
23970
+ onChange,
23971
+ categories,
23972
+ searchPlaceholder,
23973
+ renderThumbnail,
23974
+ cellSize = 32,
23975
+ className
23976
+ }) => {
23977
+ const [search, setSearch] = useState("");
23978
+ const [activeCategory, setActiveCategory] = useState(ALL_CATEGORY);
23979
+ const gridRef = useRef(null);
23980
+ const categoryChips = useMemo(() => {
23981
+ if (categories !== void 0) return categories;
23982
+ const seen = [];
23983
+ for (const item of items) {
23984
+ if (!seen.includes(item.category)) seen.push(item.category);
23985
+ }
23986
+ return seen;
23987
+ }, [categories, items]);
23988
+ const filtered = useMemo(() => {
23989
+ const needle = search.trim().toLowerCase();
23990
+ return items.filter((item) => {
23991
+ const matchesCategory = activeCategory === ALL_CATEGORY || item.category === activeCategory;
23992
+ const matchesSearch = needle === "" || item.label.toLowerCase().includes(needle) || item.keywords !== void 0 && item.keywords.some((k) => k.toLowerCase().includes(needle));
23993
+ return matchesCategory && matchesSearch;
23994
+ });
23995
+ }, [items, search, activeCategory]);
23996
+ const visible = useMemo(() => filtered.slice(0, MAX_RENDERED), [filtered]);
23997
+ const truncated = filtered.length - visible.length;
23998
+ const select = useCallback(
23999
+ (item) => {
24000
+ onChange(item.id);
24001
+ },
24002
+ [onChange]
24003
+ );
24004
+ const handleKeyDown = useCallback(
24005
+ (e, index) => {
24006
+ const cells = gridRef.current?.querySelectorAll(
24007
+ "[data-gridpicker-cell]"
24008
+ );
24009
+ if (cells === void 0 || cells.length === 0) return;
24010
+ const columns = (() => {
24011
+ const grid = gridRef.current;
24012
+ if (grid === null) return 1;
24013
+ const style = window.getComputedStyle(grid);
24014
+ const cols = style.gridTemplateColumns.split(" ").filter(Boolean).length;
24015
+ return cols > 0 ? cols : 1;
24016
+ })();
24017
+ let next = -1;
24018
+ if (e.key === "ArrowRight") next = index + 1;
24019
+ else if (e.key === "ArrowLeft") next = index - 1;
24020
+ else if (e.key === "ArrowDown") next = index + columns;
24021
+ else if (e.key === "ArrowUp") next = index - columns;
24022
+ else if (e.key === "Enter" || e.key === " ") {
24023
+ e.preventDefault();
24024
+ select(filtered[index]);
24025
+ return;
24026
+ } else {
24027
+ return;
24028
+ }
24029
+ e.preventDefault();
24030
+ if (next >= 0 && next < cells.length) {
24031
+ cells[next].focus();
24032
+ }
24033
+ },
24034
+ [filtered, select]
24035
+ );
24036
+ return /* @__PURE__ */ jsxs(VStack, { gap: "sm", className: cn("w-full", className), children: [
24037
+ /* @__PURE__ */ jsx(
24038
+ Input,
24039
+ {
24040
+ type: "search",
24041
+ icon: "search",
24042
+ value: search,
24043
+ placeholder: searchPlaceholder,
24044
+ clearable: true,
24045
+ onClear: () => setSearch(""),
24046
+ onChange: (e) => setSearch(e.target.value)
24047
+ }
24048
+ ),
24049
+ categoryChips.length > 0 && /* @__PURE__ */ jsxs(HStack, { gap: "xs", wrap: true, children: [
24050
+ /* @__PURE__ */ jsx(
24051
+ Badge,
24052
+ {
24053
+ variant: activeCategory === ALL_CATEGORY ? "primary" : "neutral",
24054
+ size: "sm",
24055
+ role: "button",
24056
+ tabIndex: 0,
24057
+ "aria-pressed": activeCategory === ALL_CATEGORY,
24058
+ className: "cursor-pointer",
24059
+ onClick: () => setActiveCategory(ALL_CATEGORY),
24060
+ onKeyDown: (e) => {
24061
+ if (e.key === "Enter" || e.key === " ") {
24062
+ e.preventDefault();
24063
+ setActiveCategory(ALL_CATEGORY);
24064
+ }
24065
+ },
24066
+ children: "All"
24067
+ }
24068
+ ),
24069
+ categoryChips.map((category) => /* @__PURE__ */ jsx(
24070
+ Badge,
24071
+ {
24072
+ variant: activeCategory === category ? "primary" : "neutral",
24073
+ size: "sm",
24074
+ role: "button",
24075
+ tabIndex: 0,
24076
+ "aria-pressed": activeCategory === category,
24077
+ className: "cursor-pointer",
24078
+ onClick: () => setActiveCategory(category),
24079
+ onKeyDown: (e) => {
24080
+ if (e.key === "Enter" || e.key === " ") {
24081
+ e.preventDefault();
24082
+ setActiveCategory(category);
24083
+ }
24084
+ },
24085
+ children: category
24086
+ },
24087
+ category
24088
+ ))
24089
+ ] }),
24090
+ /* @__PURE__ */ jsx(
24091
+ "div",
24092
+ {
24093
+ ref: gridRef,
24094
+ role: "listbox",
24095
+ className: "grid gap-1 overflow-y-auto max-h-64 p-1",
24096
+ style: {
24097
+ gridTemplateColumns: `repeat(auto-fill, minmax(${cellSize}px, 1fr))`
24098
+ },
24099
+ children: visible.map((item, index) => {
24100
+ const selected = item.id === value;
24101
+ return /* @__PURE__ */ jsx(
24102
+ "button",
24103
+ {
24104
+ type: "button",
24105
+ role: "option",
24106
+ "aria-selected": selected,
24107
+ "aria-label": item.label,
24108
+ title: item.label,
24109
+ "data-gridpicker-cell": true,
24110
+ tabIndex: selected || value === void 0 && index === 0 ? 0 : -1,
24111
+ onClick: () => select(item),
24112
+ onKeyDown: (e) => handleKeyDown(e, index),
24113
+ className: cn(
24114
+ "flex items-center justify-center rounded-sm",
24115
+ "transition-colors hover:bg-muted",
24116
+ "focus:outline-none focus:ring-1 focus:ring-ring",
24117
+ selected && "bg-primary/10 ring-1 ring-primary"
24118
+ ),
24119
+ style: { width: cellSize, height: cellSize },
24120
+ children: renderThumbnail(item)
24121
+ },
24122
+ item.id
24123
+ );
24124
+ })
24125
+ }
24126
+ ),
24127
+ truncated > 0 && /* @__PURE__ */ jsx("div", { className: "px-1 text-xs text-muted-foreground", children: `+${truncated} more \u2014 refine your search` })
24128
+ ] });
24129
+ };
24130
+ GridPicker.displayName = "GridPicker";
24131
+ }
24132
+ });
23751
24133
  function fileIcon(name) {
23752
24134
  const ext = name.split(".").pop()?.toLowerCase() ?? "";
23753
24135
  switch (ext) {
@@ -24456,7 +24838,7 @@ var init_Flex = __esm({
24456
24838
  flexStyle.flexBasis = typeof basis === "number" ? `${basis}px` : basis;
24457
24839
  }
24458
24840
  }
24459
- return React82__default.createElement(Component, {
24841
+ return React83__default.createElement(Component, {
24460
24842
  className: cn(
24461
24843
  inline ? "inline-flex" : "flex",
24462
24844
  directionStyles[direction],
@@ -24575,7 +24957,7 @@ var init_Grid = __esm({
24575
24957
  as: Component = "div"
24576
24958
  }) => {
24577
24959
  const mergedStyle = rows ? { gridTemplateRows: `repeat(${rows}, minmax(0, 1fr))`, ...style } : style;
24578
- return React82__default.createElement(
24960
+ return React83__default.createElement(
24579
24961
  Component,
24580
24962
  {
24581
24963
  className: cn(
@@ -24712,9 +25094,16 @@ var init_Popover = __esm({
24712
25094
  position = "bottom",
24713
25095
  trigger = "click",
24714
25096
  showArrow = true,
25097
+ open,
25098
+ onOpenChange,
24715
25099
  className
24716
25100
  }) => {
24717
- const [isOpen, setIsOpen] = useState(false);
25101
+ const [uncontrolledOpen, setUncontrolledOpen] = useState(false);
25102
+ const isOpen = open !== void 0 ? open : uncontrolledOpen;
25103
+ const setIsOpen = (next) => {
25104
+ if (open === void 0) setUncontrolledOpen(next);
25105
+ onOpenChange?.(next);
25106
+ };
24718
25107
  const [triggerRect, setTriggerRect] = useState(null);
24719
25108
  const [popoverWidth, setPopoverWidth] = useState(0);
24720
25109
  const triggerRef = useRef(null);
@@ -24747,6 +25136,23 @@ var init_Popover = __esm({
24747
25136
  updatePosition();
24748
25137
  }
24749
25138
  }, [isOpen]);
25139
+ useEffect(() => {
25140
+ if (!isOpen) return;
25141
+ let raf = 0;
25142
+ let lastTop = Number.NaN;
25143
+ let lastLeft = Number.NaN;
25144
+ const track = () => {
25145
+ const rect = triggerRef.current?.getBoundingClientRect();
25146
+ if (rect && (rect.top !== lastTop || rect.left !== lastLeft)) {
25147
+ lastTop = rect.top;
25148
+ lastLeft = rect.left;
25149
+ updatePosition();
25150
+ }
25151
+ raf = requestAnimationFrame(track);
25152
+ };
25153
+ raf = requestAnimationFrame(track);
25154
+ return () => cancelAnimationFrame(raf);
25155
+ }, [isOpen]);
24750
25156
  useEffect(() => {
24751
25157
  if (!mounted) setPopoverWidth(0);
24752
25158
  }, [mounted]);
@@ -24783,9 +25189,9 @@ var init_Popover = __esm({
24783
25189
  onMouseLeave: handleClose,
24784
25190
  onPointerDown: tapTriggerProps.onPointerDown
24785
25191
  };
24786
- const childElement = React82__default.isValidElement(children) ? children : /* @__PURE__ */ jsx("span", { children });
25192
+ const childElement = React83__default.isValidElement(children) ? children : /* @__PURE__ */ jsx("span", { children });
24787
25193
  const childPointerDown = childElement.props.onPointerDown;
24788
- const triggerElement = React82__default.cloneElement(
25194
+ const triggerElement = React83__default.cloneElement(
24789
25195
  childElement,
24790
25196
  {
24791
25197
  ref: triggerRef,
@@ -25394,9 +25800,9 @@ var init_Tooltip = __esm({
25394
25800
  if (hideTimeoutRef.current) clearTimeout(hideTimeoutRef.current);
25395
25801
  };
25396
25802
  }, []);
25397
- const triggerElement = React82__default.isValidElement(children) ? children : /* @__PURE__ */ jsx("span", { children });
25803
+ const triggerElement = React83__default.isValidElement(children) ? children : /* @__PURE__ */ jsx("span", { children });
25398
25804
  const childPointerDown = triggerElement.props.onPointerDown;
25399
- const trigger = React82__default.cloneElement(triggerElement, {
25805
+ const trigger = React83__default.cloneElement(triggerElement, {
25400
25806
  ref: triggerRef,
25401
25807
  onMouseEnter: handleMouseEnter,
25402
25808
  onMouseLeave: handleMouseLeave,
@@ -25486,7 +25892,7 @@ var init_WizardProgress = __esm({
25486
25892
  children: /* @__PURE__ */ jsx("div", { className: "flex items-center gap-2", children: normalizedSteps.map((step, index) => {
25487
25893
  const isActive = index === currentStep;
25488
25894
  const isCompleted = index < currentStep;
25489
- return /* @__PURE__ */ jsxs(React82__default.Fragment, { children: [
25895
+ return /* @__PURE__ */ jsxs(React83__default.Fragment, { children: [
25490
25896
  /* @__PURE__ */ jsx(
25491
25897
  "button",
25492
25898
  {
@@ -26095,6 +26501,80 @@ var init_FlipCard = __esm({
26095
26501
  FlipCard.displayName = "FlipCard";
26096
26502
  }
26097
26503
  });
26504
+ var EMOJI_ITEMS, EmojiPicker;
26505
+ var init_EmojiPicker = __esm({
26506
+ "components/core/molecules/EmojiPicker.tsx"() {
26507
+ "use client";
26508
+ init_useEventBus();
26509
+ init_Button();
26510
+ init_GridPicker();
26511
+ init_Popover();
26512
+ EMOJI_ITEMS = (() => {
26513
+ const items = [];
26514
+ for (const name of ordered) {
26515
+ const entry = lib[name];
26516
+ if (entry === void 0 || entry.char === null || entry.char === "") continue;
26517
+ items.push({
26518
+ id: entry.char,
26519
+ label: name.replace(/_/g, " "),
26520
+ category: entry.category.replace(/_/g, " "),
26521
+ keywords: entry.keywords
26522
+ });
26523
+ }
26524
+ return items;
26525
+ })();
26526
+ EmojiPicker = ({
26527
+ pickEvent,
26528
+ position = "top",
26529
+ triggerIcon = "smile",
26530
+ triggerLabel = "Add emoji",
26531
+ className
26532
+ }) => {
26533
+ const eventBus = useEventBus();
26534
+ const [open, setOpen] = useState(false);
26535
+ const handlePick = (glyph) => {
26536
+ if (pickEvent !== void 0) {
26537
+ const payload = { emoji: glyph };
26538
+ eventBus.emit(`UI:${pickEvent}`, payload);
26539
+ }
26540
+ setOpen(false);
26541
+ };
26542
+ return /* @__PURE__ */ jsx(
26543
+ Popover,
26544
+ {
26545
+ position,
26546
+ trigger: "click",
26547
+ showArrow: false,
26548
+ open,
26549
+ onOpenChange: setOpen,
26550
+ content: /* @__PURE__ */ jsx(
26551
+ GridPicker,
26552
+ {
26553
+ items: EMOJI_ITEMS,
26554
+ onChange: handlePick,
26555
+ searchPlaceholder: "Search emoji\u2026",
26556
+ renderThumbnail: (item) => /* @__PURE__ */ jsx("span", { className: "text-xl leading-none", "aria-hidden": "true", children: item.id }),
26557
+ cellSize: 32,
26558
+ className: "w-80"
26559
+ }
26560
+ ),
26561
+ children: /* @__PURE__ */ jsx(
26562
+ Button,
26563
+ {
26564
+ variant: "ghost",
26565
+ icon: triggerIcon,
26566
+ "aria-label": triggerLabel,
26567
+ title: triggerLabel,
26568
+ className,
26569
+ "data-testid": "emoji-picker-trigger"
26570
+ }
26571
+ )
26572
+ }
26573
+ );
26574
+ };
26575
+ EmojiPicker.displayName = "EmojiPicker";
26576
+ }
26577
+ });
26098
26578
  function toISODate(d) {
26099
26579
  return d.toISOString().slice(0, 10);
26100
26580
  }
@@ -27047,12 +27527,12 @@ var init_MapView = __esm({
27047
27527
  shadowSize: [41, 41]
27048
27528
  });
27049
27529
  L.Marker.prototype.options.icon = defaultIcon;
27050
- const { useEffect: useEffect59, useRef: useRef60, useCallback: useCallback88, useState: useState89 } = React82__default;
27530
+ const { useEffect: useEffect59, useRef: useRef61, useCallback: useCallback89, useState: useState91 } = React83__default;
27051
27531
  const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
27052
27532
  const { useEventBus: useEventBus2 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
27053
27533
  function MapUpdater({ centerLat, centerLng, zoom }) {
27054
27534
  const map = useMap();
27055
- const prevRef = useRef60({ centerLat, centerLng, zoom });
27535
+ const prevRef = useRef61({ centerLat, centerLng, zoom });
27056
27536
  useEffect59(() => {
27057
27537
  const prev = prevRef.current;
27058
27538
  if (prev.centerLat !== centerLat || prev.centerLng !== centerLng || prev.zoom !== zoom) {
@@ -27092,8 +27572,8 @@ var init_MapView = __esm({
27092
27572
  showAttribution = true
27093
27573
  }) {
27094
27574
  const eventBus = useEventBus2();
27095
- const [clickedPosition, setClickedPosition] = useState89(null);
27096
- const handleMapClick = useCallback88((lat, lng) => {
27575
+ const [clickedPosition, setClickedPosition] = useState91(null);
27576
+ const handleMapClick = useCallback89((lat, lng) => {
27097
27577
  if (showClickedPin) {
27098
27578
  setClickedPosition({ lat, lng });
27099
27579
  }
@@ -27102,7 +27582,7 @@ var init_MapView = __esm({
27102
27582
  eventBus.emit(`UI:${mapClickEvent}`, { latitude: lat, longitude: lng });
27103
27583
  }
27104
27584
  }, [onMapClick, mapClickEvent, eventBus, showClickedPin]);
27105
- const handleMarkerClick = useCallback88((marker) => {
27585
+ const handleMarkerClick = useCallback89((marker) => {
27106
27586
  onMarkerClick?.(marker);
27107
27587
  if (markerClickEvent) {
27108
27588
  eventBus.emit(`UI:${markerClickEvent}`, { ...marker });
@@ -27917,6 +28397,7 @@ function TableView({
27917
28397
  fields,
27918
28398
  itemActions,
27919
28399
  maxInlineActions,
28400
+ itemClickEvent,
27920
28401
  selectable = false,
27921
28402
  selectEvent,
27922
28403
  selectedIds,
@@ -27944,8 +28425,8 @@ function TableView({
27944
28425
  }) {
27945
28426
  const eventBus = useEventBus();
27946
28427
  const { t } = useTranslate();
27947
- const [visibleCount, setVisibleCount] = React82__default.useState(pageSize > 0 ? pageSize : Infinity);
27948
- const [localSelected, setLocalSelected] = React82__default.useState(/* @__PURE__ */ new Set());
28428
+ const [visibleCount, setVisibleCount] = React83__default.useState(pageSize > 0 ? pageSize : Infinity);
28429
+ const [localSelected, setLocalSelected] = React83__default.useState(/* @__PURE__ */ new Set());
27949
28430
  const colDefs = (Array.isArray(columns) ? columns : void 0) ?? (Array.isArray(fields) ? fields : void 0) ?? [];
27950
28431
  const actionDefs = Array.isArray(itemActions) ? itemActions : [];
27951
28432
  const allDataRaw = Array.isArray(entity) ? entity : entity ? [entity] : [];
@@ -27961,13 +28442,13 @@ function TableView({
27961
28442
  dndItemIdField,
27962
28443
  dndRoot
27963
28444
  });
27964
- const ordered = dnd.orderedItems;
27965
- const data = pageSize > 0 ? ordered.slice(0, visibleCount) : ordered;
27966
- const hasMore = pageSize > 0 && visibleCount < ordered.length;
28445
+ const ordered2 = dnd.orderedItems;
28446
+ const data = pageSize > 0 ? ordered2.slice(0, visibleCount) : ordered2;
28447
+ const hasMore = pageSize > 0 && visibleCount < ordered2.length;
27967
28448
  const hasRenderProp = typeof children === "function";
27968
28449
  const idField = dndItemIdField ?? "id";
27969
28450
  const isCoarsePointer = useMediaQuery("(pointer: coarse)");
27970
- React82__default.useEffect(() => {
28451
+ React83__default.useEffect(() => {
27971
28452
  tableViewLog.debug("render", {
27972
28453
  rowCount: data.length,
27973
28454
  colCount: colDefs.length,
@@ -28016,7 +28497,15 @@ function TableView({
28016
28497
  };
28017
28498
  eventBus.emit(`UI:${action.event}`, payload);
28018
28499
  };
28019
- const colFloors = React82__default.useMemo(
28500
+ const handleRowClick = (row) => () => {
28501
+ if (!itemClickEvent) return;
28502
+ const payload = {
28503
+ id: row.id,
28504
+ row
28505
+ };
28506
+ eventBus.emit(`UI:${itemClickEvent}`, payload);
28507
+ };
28508
+ const colFloors = React83__default.useMemo(
28020
28509
  () => colDefs.map((col) => {
28021
28510
  const longest = data.reduce((widest, row) => {
28022
28511
  const cell = formatCell(asFieldValue(getNestedValue(row, col.field ?? col.key)), col.format);
@@ -28092,10 +28581,12 @@ function TableView({
28092
28581
  role: "row",
28093
28582
  "data-entity-row": true,
28094
28583
  "data-entity-id": id,
28584
+ onClick: itemClickEvent ? handleRowClick(row) : void 0,
28095
28585
  style: !hasRenderProp ? { gridTemplateColumns } : void 0,
28096
28586
  className: cn(
28097
28587
  "group items-center gap-3 transition-colors duration-fast",
28098
28588
  hasRenderProp ? "flex" : "grid",
28589
+ itemClickEvent && "cursor-pointer",
28099
28590
  lk.rowPad,
28100
28591
  lk.divider && "border-b border-[var(--color-border)]",
28101
28592
  lk.striped && index % 2 === 1 && "bg-[var(--color-surface-subtle)]",
@@ -28103,7 +28594,7 @@ function TableView({
28103
28594
  look === "bordered" && "[&>*]:border-r [&>*]:border-[var(--color-border)] [&>*:last-child]:border-r-0"
28104
28595
  ),
28105
28596
  children: [
28106
- selectable && /* @__PURE__ */ jsx(Box, { className: "flex items-center", children: /* @__PURE__ */ jsx(
28597
+ selectable && /* @__PURE__ */ jsx(Box, { className: "flex items-center", onClick: itemClickEvent ? (e) => e.stopPropagation() : void 0, children: /* @__PURE__ */ jsx(
28107
28598
  Checkbox,
28108
28599
  {
28109
28600
  checked: selected.has(id),
@@ -28128,6 +28619,7 @@ function TableView({
28128
28619
  HStack,
28129
28620
  {
28130
28621
  gap: "xs",
28622
+ onClick: itemClickEvent ? (e) => e.stopPropagation() : void 0,
28131
28623
  className: cn(
28132
28624
  // Pinned: the fixed column tracks routinely overflow the caller's
28133
28625
  // scroll container, which used to leave the actions off-screen.
@@ -28175,12 +28667,12 @@ function TableView({
28175
28667
  ]
28176
28668
  }
28177
28669
  );
28178
- return dnd.isZone ? /* @__PURE__ */ jsx(dnd.SortableItem, { id: row[idField] ?? id, children: rowInner }, id) : /* @__PURE__ */ jsx(React82__default.Fragment, { children: rowInner }, id);
28670
+ return dnd.isZone ? /* @__PURE__ */ jsx(dnd.SortableItem, { id: row[idField] ?? id, children: rowInner }, id) : /* @__PURE__ */ jsx(React83__default.Fragment, { children: rowInner }, id);
28179
28671
  };
28180
28672
  const items = Array.from(data);
28181
28673
  const groups = groupBy ? groupData2(items, groupBy) : [{ label: "", items }];
28182
28674
  let runningIndex = 0;
28183
- const body = /* @__PURE__ */ jsx(Box, { role: "rowgroup", children: groups.map((group, gi) => /* @__PURE__ */ jsxs(React82__default.Fragment, { children: [
28675
+ const body = /* @__PURE__ */ jsx(Box, { role: "rowgroup", children: groups.map((group, gi) => /* @__PURE__ */ jsxs(React83__default.Fragment, { children: [
28184
28676
  group.label && /* @__PURE__ */ jsx(Divider, { label: group.label, className: gi > 0 ? "mt-3" : "mt-0" }),
28185
28677
  group.items.map((row) => renderRow(row, runningIndex++))
28186
28678
  ] }, gi)) });
@@ -28197,7 +28689,7 @@ function TableView({
28197
28689
  /* @__PURE__ */ jsx(Icon, { name: "chevron-down", size: "xs", className: "mr-1" }),
28198
28690
  t("common.showMore"),
28199
28691
  " (",
28200
- t("common.remaining", { count: ordered.length - visibleCount }),
28692
+ t("common.remaining", { count: ordered2.length - visibleCount }),
28201
28693
  ")"
28202
28694
  ] }) })
28203
28695
  ]
@@ -29405,7 +29897,7 @@ var init_StepFlow = __esm({
29405
29897
  className
29406
29898
  }) => {
29407
29899
  if (orientation === "vertical") {
29408
- return /* @__PURE__ */ jsx(VStack, { gap: "none", className: cn("w-full", className), children: steps.map((step, index) => /* @__PURE__ */ jsx(React82__default.Fragment, { children: /* @__PURE__ */ jsxs(HStack, { gap: "md", align: "start", className: "w-full", children: [
29900
+ return /* @__PURE__ */ jsx(VStack, { gap: "none", className: cn("w-full", className), children: steps.map((step, index) => /* @__PURE__ */ jsx(React83__default.Fragment, { children: /* @__PURE__ */ jsxs(HStack, { gap: "md", align: "start", className: "w-full", children: [
29409
29901
  /* @__PURE__ */ jsxs(VStack, { gap: "none", align: "center", children: [
29410
29902
  /* @__PURE__ */ jsx(StepCircle, { step, index }),
29411
29903
  showConnectors && index < steps.length - 1 && /* @__PURE__ */ jsx(Box, { className: "w-px h-8 bg-border" })
@@ -29416,7 +29908,7 @@ var init_StepFlow = __esm({
29416
29908
  ] })
29417
29909
  ] }) }, index)) });
29418
29910
  }
29419
- return /* @__PURE__ */ jsx(Box, { className: cn("w-full flex flex-col md:flex-row items-start gap-0", className), children: steps.map((step, index) => /* @__PURE__ */ jsxs(React82__default.Fragment, { children: [
29911
+ return /* @__PURE__ */ jsx(Box, { className: cn("w-full flex flex-col md:flex-row items-start gap-0", className), children: steps.map((step, index) => /* @__PURE__ */ jsxs(React83__default.Fragment, { children: [
29420
29912
  /* @__PURE__ */ jsxs(VStack, { gap: "sm", align: "center", className: "flex-1 w-full md:w-auto", children: [
29421
29913
  /* @__PURE__ */ jsx(StepCircle, { step, index }),
29422
29914
  /* @__PURE__ */ jsx(Typography, { variant: "h4", className: "text-center", children: step.title }),
@@ -30406,7 +30898,7 @@ var init_LikertScale = __esm({
30406
30898
  md: "text-base",
30407
30899
  lg: "text-lg"
30408
30900
  };
30409
- LikertScale = React82__default.forwardRef(
30901
+ LikertScale = React83__default.forwardRef(
30410
30902
  ({
30411
30903
  question,
30412
30904
  options = DEFAULT_LIKERT_OPTIONS,
@@ -30418,7 +30910,7 @@ var init_LikertScale = __esm({
30418
30910
  variant = "radios",
30419
30911
  className
30420
30912
  }, ref) => {
30421
- const groupId = React82__default.useId();
30913
+ const groupId = React83__default.useId();
30422
30914
  const eventBus = useEventBus();
30423
30915
  const handleSelect = useCallback(
30424
30916
  (next) => {
@@ -32707,7 +33199,7 @@ var init_DocBreadcrumb = __esm({
32707
33199
  "aria-label": t("aria.breadcrumb"),
32708
33200
  children: /* @__PURE__ */ jsx(HStack, { gap: "xs", align: "center", wrap: true, children: items.map((item, idx) => {
32709
33201
  const isLast = idx === items.length - 1;
32710
- return /* @__PURE__ */ jsxs(React82__default.Fragment, { children: [
33202
+ return /* @__PURE__ */ jsxs(React83__default.Fragment, { children: [
32711
33203
  idx > 0 && /* @__PURE__ */ jsx(
32712
33204
  Icon,
32713
33205
  {
@@ -33576,7 +34068,7 @@ var init_MiniStateMachine = __esm({
33576
34068
  const x = 2 + i * (NODE_W + GAP + ARROW_W + GAP);
33577
34069
  const tc = transitionCounts[s.name] ?? 0;
33578
34070
  const role = getStateRole(s.name, s.isInitial ?? void 0, s.isTerminal ?? void 0, tc, maxTC);
33579
- return /* @__PURE__ */ jsxs(React82__default.Fragment, { children: [
34071
+ return /* @__PURE__ */ jsxs(React83__default.Fragment, { children: [
33580
34072
  /* @__PURE__ */ jsx(
33581
34073
  AvlState,
33582
34074
  {
@@ -33780,7 +34272,7 @@ var init_PageHeader = __esm({
33780
34272
  info: "bg-info/10 text-info"
33781
34273
  };
33782
34274
  return /* @__PURE__ */ jsxs(Box, { className: cn("mb-6", className), children: [
33783
- breadcrumbs && breadcrumbs.length > 0 && /* @__PURE__ */ jsx(Box, { as: "nav", className: "mb-4", children: /* @__PURE__ */ jsx(Box, { as: "ol", className: "flex items-center gap-2 text-sm", children: breadcrumbs.map((crumb, idx) => /* @__PURE__ */ jsxs(React82__default.Fragment, { children: [
34275
+ breadcrumbs && breadcrumbs.length > 0 && /* @__PURE__ */ jsx(Box, { as: "nav", className: "mb-4", children: /* @__PURE__ */ jsx(Box, { as: "ol", className: "flex items-center gap-2 text-sm", children: breadcrumbs.map((crumb, idx) => /* @__PURE__ */ jsxs(React83__default.Fragment, { children: [
33784
34276
  idx > 0 && /* @__PURE__ */ jsx(Typography, { variant: "small", color: "muted", children: "/" }),
33785
34277
  crumb.href ? /* @__PURE__ */ jsx(
33786
34278
  "a",
@@ -34138,7 +34630,7 @@ var init_Section = __esm({
34138
34630
  as: Component = "section"
34139
34631
  }) => {
34140
34632
  const hasHeader = title || description || action;
34141
- return React82__default.createElement(
34633
+ return React83__default.createElement(
34142
34634
  Component,
34143
34635
  {
34144
34636
  className: cn(
@@ -34512,7 +35004,7 @@ var init_WizardContainer = __esm({
34512
35004
  const isCompleted = index < currentStep;
34513
35005
  const stepKey = step.id ?? step.tabId ?? `step-${index}`;
34514
35006
  const stepTitle = step.title ?? step.name ?? `Step ${index + 1}`;
34515
- return /* @__PURE__ */ jsxs(React82__default.Fragment, { children: [
35007
+ return /* @__PURE__ */ jsxs(React83__default.Fragment, { children: [
34516
35008
  /* @__PURE__ */ jsx(
34517
35009
  Button,
34518
35010
  {
@@ -36299,7 +36791,7 @@ var init_ImportPreviewTree = __esm({
36299
36791
  const renderUnit = (unit, childrenByParent, depth) => {
36300
36792
  const summary = fieldSummary(unit);
36301
36793
  const children = childrenByParent.get(unit.ref) ?? [];
36302
- return /* @__PURE__ */ jsxs(React82__default.Fragment, { children: [
36794
+ return /* @__PURE__ */ jsxs(React83__default.Fragment, { children: [
36303
36795
  /* @__PURE__ */ jsxs(
36304
36796
  Box,
36305
36797
  {
@@ -36396,7 +36888,7 @@ var init_ImportProgress = __esm({
36396
36888
  PIPELINE.map((key, index) => {
36397
36889
  const isComplete = index < currentIndex;
36398
36890
  const isActive = index === currentIndex;
36399
- return /* @__PURE__ */ jsxs(React82__default.Fragment, { children: [
36891
+ return /* @__PURE__ */ jsxs(React83__default.Fragment, { children: [
36400
36892
  index > 0 ? /* @__PURE__ */ jsx(Box, { className: "h-px w-4 bg-border" }) : null,
36401
36893
  /* @__PURE__ */ jsxs(Box, { className: "flex items-center gap-1", "data-testid": `import-progress-step-${key}`, children: [
36402
36894
  /* @__PURE__ */ jsx(
@@ -37509,7 +38001,7 @@ var init_DrawGroup = __esm({
37509
38001
  }
37510
38002
  });
37511
38003
  function extractTitle(children) {
37512
- if (!React82__default.isValidElement(children)) return void 0;
38004
+ if (!React83__default.isValidElement(children)) return void 0;
37513
38005
  const props = children.props;
37514
38006
  if (typeof props.title === "string") {
37515
38007
  return props.title;
@@ -37859,12 +38351,12 @@ var init_Form = __esm({
37859
38351
  const isSchemaEntity = isOrbitalEntitySchema(entity);
37860
38352
  const resolvedEntity = isSchemaEntity ? entity : void 0;
37861
38353
  const entityName = typeof entity === "string" ? entity : resolvedEntity?.name;
37862
- const normalizedInitialData = React82__default.useMemo(() => {
38354
+ const normalizedInitialData = React83__default.useMemo(() => {
37863
38355
  const entityRowAsInitial = isPlainEntityRow(entity) ? entity : void 0;
37864
38356
  const callerInitial = initialData !== null && typeof initialData === "object" && !Array.isArray(initialData) ? initialData : {};
37865
38357
  return entityRowAsInitial !== void 0 ? { ...entityRowAsInitial, ...callerInitial } : callerInitial;
37866
38358
  }, [entity, initialData]);
37867
- const entityDerivedFields = React82__default.useMemo(() => {
38359
+ const entityDerivedFields = React83__default.useMemo(() => {
37868
38360
  if (fields && fields.length > 0) return void 0;
37869
38361
  if (!resolvedEntity) return void 0;
37870
38362
  return resolvedEntity.fields.map(
@@ -37885,16 +38377,16 @@ var init_Form = __esm({
37885
38377
  const conditionalFields = typeof conditionalFieldsRaw === "boolean" ? {} : conditionalFieldsRaw;
37886
38378
  const hiddenCalculations = typeof hiddenCalculationsRaw === "boolean" ? [] : hiddenCalculationsRaw;
37887
38379
  const violationTriggers = typeof violationTriggersRaw === "boolean" ? [] : violationTriggersRaw;
37888
- const [formData, setFormData] = React82__default.useState(
38380
+ const [formData, setFormData] = React83__default.useState(
37889
38381
  normalizedInitialData
37890
38382
  );
37891
- const [collapsedSections, setCollapsedSections] = React82__default.useState(
38383
+ const [collapsedSections, setCollapsedSections] = React83__default.useState(
37892
38384
  /* @__PURE__ */ new Set()
37893
38385
  );
37894
- const [submitError, setSubmitError] = React82__default.useState(null);
37895
- const formRef = React82__default.useRef(null);
38386
+ const [submitError, setSubmitError] = React83__default.useState(null);
38387
+ const formRef = React83__default.useRef(null);
37896
38388
  const formMode = props.mode;
37897
- const mountedRef = React82__default.useRef(false);
38389
+ const mountedRef = React83__default.useRef(false);
37898
38390
  if (!mountedRef.current) {
37899
38391
  mountedRef.current = true;
37900
38392
  debug("forms", "mount", {
@@ -37907,7 +38399,7 @@ var init_Form = __esm({
37907
38399
  });
37908
38400
  }
37909
38401
  const shouldShowCancel = showCancel ?? (fields && fields.length > 0);
37910
- const evalContext = React82__default.useMemo(
38402
+ const evalContext = React83__default.useMemo(
37911
38403
  () => ({
37912
38404
  formValues: formData,
37913
38405
  globalVariables: externalContext?.globalVariables ?? {},
@@ -37916,7 +38408,7 @@ var init_Form = __esm({
37916
38408
  }),
37917
38409
  [formData, externalContext]
37918
38410
  );
37919
- React82__default.useEffect(() => {
38411
+ React83__default.useEffect(() => {
37920
38412
  debug("forms", "initialData-sync", {
37921
38413
  mode: formMode,
37922
38414
  normalizedInitialData,
@@ -37927,7 +38419,7 @@ var init_Form = __esm({
37927
38419
  setFormData(normalizedInitialData);
37928
38420
  }
37929
38421
  }, [normalizedInitialData]);
37930
- const processCalculations = React82__default.useCallback(
38422
+ const processCalculations = React83__default.useCallback(
37931
38423
  (changedFieldId, newFormData) => {
37932
38424
  if (!hiddenCalculations.length) return;
37933
38425
  const context = {
@@ -37952,7 +38444,7 @@ var init_Form = __esm({
37952
38444
  },
37953
38445
  [hiddenCalculations, externalContext, eventBus]
37954
38446
  );
37955
- const checkViolations = React82__default.useCallback(
38447
+ const checkViolations = React83__default.useCallback(
37956
38448
  (changedFieldId, newFormData) => {
37957
38449
  if (!violationTriggers.length) return;
37958
38450
  const context = {
@@ -37990,7 +38482,7 @@ var init_Form = __esm({
37990
38482
  processCalculations(name, newFormData);
37991
38483
  checkViolations(name, newFormData);
37992
38484
  };
37993
- const isFieldVisible = React82__default.useCallback(
38485
+ const isFieldVisible = React83__default.useCallback(
37994
38486
  (fieldName) => {
37995
38487
  const condition = conditionalFields[fieldName];
37996
38488
  if (!condition) return true;
@@ -37998,7 +38490,7 @@ var init_Form = __esm({
37998
38490
  },
37999
38491
  [conditionalFields, evalContext]
38000
38492
  );
38001
- const isSectionVisible = React82__default.useCallback(
38493
+ const isSectionVisible = React83__default.useCallback(
38002
38494
  (section) => {
38003
38495
  if (!section.condition) return true;
38004
38496
  return Boolean(evaluateFormExpression(section.condition, evalContext));
@@ -38074,7 +38566,7 @@ var init_Form = __esm({
38074
38566
  eventBus.emit(`UI:${onCancel}`);
38075
38567
  }
38076
38568
  };
38077
- const renderField = React82__default.useCallback(
38569
+ const renderField = React83__default.useCallback(
38078
38570
  (field) => {
38079
38571
  const fieldName = field.name || field.field;
38080
38572
  if (!fieldName) return null;
@@ -38095,7 +38587,7 @@ var init_Form = __esm({
38095
38587
  [formData, isFieldVisible, relationsData, relationsLoading, isLoading]
38096
38588
  );
38097
38589
  const effectiveFields = entityDerivedFields ?? fields;
38098
- const normalizedFields = React82__default.useMemo(() => {
38590
+ const normalizedFields = React83__default.useMemo(() => {
38099
38591
  if (!effectiveFields || effectiveFields.length === 0) return [];
38100
38592
  return effectiveFields.map((field) => {
38101
38593
  if (typeof field === "string") {
@@ -38119,7 +38611,7 @@ var init_Form = __esm({
38119
38611
  return field;
38120
38612
  });
38121
38613
  }, [effectiveFields, resolvedEntity]);
38122
- const schemaFields = React82__default.useMemo(() => {
38614
+ const schemaFields = React83__default.useMemo(() => {
38123
38615
  if (normalizedFields.length === 0) return null;
38124
38616
  if (isDebugEnabled()) {
38125
38617
  debugGroup(`Form: ${entityName || "unknown"}`);
@@ -38129,7 +38621,7 @@ var init_Form = __esm({
38129
38621
  }
38130
38622
  return normalizedFields.map(renderField).filter(Boolean);
38131
38623
  }, [normalizedFields, renderField, entityName, conditionalFields]);
38132
- const sectionElements = React82__default.useMemo(() => {
38624
+ const sectionElements = React83__default.useMemo(() => {
38133
38625
  if (!sections || sections.length === 0) return null;
38134
38626
  return sections.map((section) => {
38135
38627
  if (!isSectionVisible(section)) {
@@ -38855,7 +39347,7 @@ var init_List = __esm({
38855
39347
  if (entity && typeof entity === "object" && "id" in entity) return [entity];
38856
39348
  return [];
38857
39349
  }, [entity]);
38858
- const getItemActions = React82__default.useCallback(
39350
+ const getItemActions = React83__default.useCallback(
38859
39351
  (item) => {
38860
39352
  if (!itemActions) return [];
38861
39353
  if (typeof itemActions === "function") {
@@ -39336,7 +39828,7 @@ var init_MediaGallery = __esm({
39336
39828
  [selectable, selectedItems, selectionEvent, eventBus]
39337
39829
  );
39338
39830
  const entityData = Array.isArray(entity) ? entity : [];
39339
- const items = React82__default.useMemo(() => {
39831
+ const items = React83__default.useMemo(() => {
39340
39832
  if (propItems && propItems.length > 0) return propItems;
39341
39833
  if (entityData.length === 0) return [];
39342
39834
  return entityData.map((record, idx) => {
@@ -39501,7 +39993,7 @@ var init_MediaGallery = __esm({
39501
39993
  }
39502
39994
  });
39503
39995
  function extractTitle2(children) {
39504
- if (!React82__default.isValidElement(children)) return void 0;
39996
+ if (!React83__default.isValidElement(children)) return void 0;
39505
39997
  const props = children.props;
39506
39998
  if (typeof props.title === "string") {
39507
39999
  return props.title;
@@ -39775,7 +40267,7 @@ var init_debugRegistry = __esm({
39775
40267
  }
39776
40268
  });
39777
40269
  function useDebugData() {
39778
- const [data, setData] = React82.useState(() => ({
40270
+ const [data, setData] = React83.useState(() => ({
39779
40271
  traits: [],
39780
40272
  ticks: [],
39781
40273
  guards: [],
@@ -39789,7 +40281,7 @@ function useDebugData() {
39789
40281
  },
39790
40282
  lastUpdate: Date.now()
39791
40283
  }));
39792
- React82.useEffect(() => {
40284
+ React83.useEffect(() => {
39793
40285
  const updateData = () => {
39794
40286
  setData({
39795
40287
  traits: getAllTraits(),
@@ -39898,12 +40390,12 @@ function layoutGraph(states, transitions, initialState, width, height) {
39898
40390
  return positions;
39899
40391
  }
39900
40392
  function WalkMinimap() {
39901
- const [walkStep, setWalkStep] = React82.useState(null);
39902
- const [traits2, setTraits] = React82.useState([]);
39903
- const [coveredEdges, setCoveredEdges] = React82.useState([]);
39904
- const [completedTraits, setCompletedTraits] = React82.useState(/* @__PURE__ */ new Set());
39905
- const prevTraitRef = React82.useRef(null);
39906
- React82.useEffect(() => {
40393
+ const [walkStep, setWalkStep] = React83.useState(null);
40394
+ const [traits2, setTraits] = React83.useState([]);
40395
+ const [coveredEdges, setCoveredEdges] = React83.useState([]);
40396
+ const [completedTraits, setCompletedTraits] = React83.useState(/* @__PURE__ */ new Set());
40397
+ const prevTraitRef = React83.useRef(null);
40398
+ React83.useEffect(() => {
39907
40399
  const interval = setInterval(() => {
39908
40400
  const w = window;
39909
40401
  const step = w.__orbitalWalkStep;
@@ -40339,15 +40831,15 @@ var init_EntitiesTab = __esm({
40339
40831
  });
40340
40832
  function EventFlowTab({ events: events2 }) {
40341
40833
  const { t } = useTranslate();
40342
- const [filter, setFilter] = React82.useState("all");
40343
- const containerRef = React82.useRef(null);
40344
- const [autoScroll, setAutoScroll] = React82.useState(true);
40345
- React82.useEffect(() => {
40834
+ const [filter, setFilter] = React83.useState("all");
40835
+ const containerRef = React83.useRef(null);
40836
+ const [autoScroll, setAutoScroll] = React83.useState(true);
40837
+ React83.useEffect(() => {
40346
40838
  if (autoScroll && containerRef.current) {
40347
40839
  containerRef.current.scrollTop = containerRef.current.scrollHeight;
40348
40840
  }
40349
40841
  }, [events2.length, autoScroll]);
40350
- const filteredEvents = React82.useMemo(() => {
40842
+ const filteredEvents = React83.useMemo(() => {
40351
40843
  if (filter === "all") return events2;
40352
40844
  return events2.filter((e) => e.type === filter);
40353
40845
  }, [events2, filter]);
@@ -40463,7 +40955,7 @@ var init_EventFlowTab = __esm({
40463
40955
  });
40464
40956
  function GuardsPanel({ guards }) {
40465
40957
  const { t } = useTranslate();
40466
- const [filter, setFilter] = React82.useState("all");
40958
+ const [filter, setFilter] = React83.useState("all");
40467
40959
  if (guards.length === 0) {
40468
40960
  return /* @__PURE__ */ jsx(
40469
40961
  EmptyState,
@@ -40476,7 +40968,7 @@ function GuardsPanel({ guards }) {
40476
40968
  }
40477
40969
  const passedCount = guards.filter((g) => g.result).length;
40478
40970
  const failedCount = guards.length - passedCount;
40479
- const filteredGuards = React82.useMemo(() => {
40971
+ const filteredGuards = React83.useMemo(() => {
40480
40972
  if (filter === "all") return guards;
40481
40973
  if (filter === "passed") return guards.filter((g) => g.result);
40482
40974
  return guards.filter((g) => !g.result);
@@ -40639,10 +41131,10 @@ function EffectBadge({ effect }) {
40639
41131
  }
40640
41132
  function TransitionTimeline({ transitions }) {
40641
41133
  const { t } = useTranslate();
40642
- const containerRef = React82.useRef(null);
40643
- const [autoScroll, setAutoScroll] = React82.useState(true);
40644
- const [expandedId, setExpandedId] = React82.useState(null);
40645
- React82.useEffect(() => {
41134
+ const containerRef = React83.useRef(null);
41135
+ const [autoScroll, setAutoScroll] = React83.useState(true);
41136
+ const [expandedId, setExpandedId] = React83.useState(null);
41137
+ React83.useEffect(() => {
40646
41138
  if (autoScroll && containerRef.current) {
40647
41139
  containerRef.current.scrollTop = containerRef.current.scrollHeight;
40648
41140
  }
@@ -40922,9 +41414,9 @@ function getAllEvents(traits2) {
40922
41414
  function EventDispatcherTab({ traits: traits2, schema }) {
40923
41415
  const eventBus = useEventBus();
40924
41416
  const { t } = useTranslate();
40925
- const [log9, setLog] = React82.useState([]);
40926
- const prevStatesRef = React82.useRef(/* @__PURE__ */ new Map());
40927
- React82.useEffect(() => {
41417
+ const [log9, setLog] = React83.useState([]);
41418
+ const prevStatesRef = React83.useRef(/* @__PURE__ */ new Map());
41419
+ React83.useEffect(() => {
40928
41420
  for (const trait of traits2) {
40929
41421
  const prev = prevStatesRef.current.get(trait.id);
40930
41422
  if (prev && prev !== trait.currentState) {
@@ -41093,10 +41585,10 @@ function VerifyModePanel({
41093
41585
  localCount
41094
41586
  }) {
41095
41587
  const { t } = useTranslate();
41096
- const [expanded, setExpanded] = React82.useState(true);
41097
- const scrollRef = React82.useRef(null);
41098
- const prevCountRef = React82.useRef(0);
41099
- React82.useEffect(() => {
41588
+ const [expanded, setExpanded] = React83.useState(true);
41589
+ const scrollRef = React83.useRef(null);
41590
+ const prevCountRef = React83.useRef(0);
41591
+ React83.useEffect(() => {
41100
41592
  if (expanded && transitions.length > prevCountRef.current && scrollRef.current) {
41101
41593
  scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
41102
41594
  }
@@ -41153,10 +41645,10 @@ function RuntimeDebugger({
41153
41645
  schema
41154
41646
  }) {
41155
41647
  const { t } = useTranslate();
41156
- const [isCollapsed, setIsCollapsed] = React82.useState(mode === "verify" ? true : defaultCollapsed);
41157
- const [isVisible, setIsVisible] = React82.useState(mode === "inline" || mode === "verify" || isDebugEnabled2());
41648
+ const [isCollapsed, setIsCollapsed] = React83.useState(mode === "verify" ? true : defaultCollapsed);
41649
+ const [isVisible, setIsVisible] = React83.useState(mode === "inline" || mode === "verify" || isDebugEnabled2());
41158
41650
  const debugData = useDebugData();
41159
- React82.useEffect(() => {
41651
+ React83.useEffect(() => {
41160
41652
  if (mode === "inline") return;
41161
41653
  return onDebugToggle((enabled) => {
41162
41654
  setIsVisible(enabled);
@@ -41165,7 +41657,7 @@ function RuntimeDebugger({
41165
41657
  }
41166
41658
  });
41167
41659
  }, [mode]);
41168
- React82.useEffect(() => {
41660
+ React83.useEffect(() => {
41169
41661
  if (mode === "inline") return;
41170
41662
  const handleKeyDown = (e) => {
41171
41663
  if (e.key === "`" && isVisible) {
@@ -41685,7 +42177,7 @@ var init_StatCard = __esm({
41685
42177
  const labelToUse = propLabel ?? propTitle;
41686
42178
  const eventBus = useEventBus();
41687
42179
  const { t } = useTranslate();
41688
- const handleActionClick = React82__default.useCallback(() => {
42180
+ const handleActionClick = React83__default.useCallback(() => {
41689
42181
  if (action?.event) {
41690
42182
  eventBus.emit(`UI:${action.event}`, {});
41691
42183
  }
@@ -41696,7 +42188,7 @@ var init_StatCard = __esm({
41696
42188
  const data = Array.isArray(entity) ? entity : entity ? [entity] : [];
41697
42189
  const isLoading = externalLoading ?? false;
41698
42190
  const error = externalError;
41699
- const computeMetricValue = React82__default.useCallback(
42191
+ const computeMetricValue = React83__default.useCallback(
41700
42192
  (metric, items) => {
41701
42193
  if (metric.value !== void 0) {
41702
42194
  return metric.value;
@@ -41735,7 +42227,7 @@ var init_StatCard = __esm({
41735
42227
  },
41736
42228
  []
41737
42229
  );
41738
- const schemaStats = React82__default.useMemo(() => {
42230
+ const schemaStats = React83__default.useMemo(() => {
41739
42231
  if (!metrics || metrics.length === 0) return null;
41740
42232
  return metrics.map((metric) => ({
41741
42233
  label: metric.label,
@@ -41743,7 +42235,7 @@ var init_StatCard = __esm({
41743
42235
  format: metric.format
41744
42236
  }));
41745
42237
  }, [metrics, data, computeMetricValue]);
41746
- const calculatedTrend = React82__default.useMemo(() => {
42238
+ const calculatedTrend = React83__default.useMemo(() => {
41747
42239
  if (manualTrend !== void 0) return manualTrend;
41748
42240
  if (previousValue === void 0 || currentValue === void 0)
41749
42241
  return void 0;
@@ -42383,8 +42875,8 @@ var init_SubagentTracePanel = __esm({
42383
42875
  ] });
42384
42876
  };
42385
42877
  InlineActivityStream = ({ activities, autoScroll = true, className }) => {
42386
- const endRef = React82__default.useRef(null);
42387
- React82__default.useEffect(() => {
42878
+ const endRef = React83__default.useRef(null);
42879
+ React83__default.useEffect(() => {
42388
42880
  if (!autoScroll) return;
42389
42881
  endRef.current?.scrollIntoView({ behavior: "smooth", block: "end" });
42390
42882
  }, [activities.length, autoScroll]);
@@ -42478,7 +42970,7 @@ var init_SubagentTracePanel = __esm({
42478
42970
  };
42479
42971
  SubagentRichCard = ({ subagent }) => {
42480
42972
  const { t } = useTranslate();
42481
- const activities = React82__default.useMemo(
42973
+ const activities = React83__default.useMemo(
42482
42974
  () => subagentMessagesToActivities(subagent.messages),
42483
42975
  [subagent.messages]
42484
42976
  );
@@ -42555,8 +43047,8 @@ var init_SubagentTracePanel = __esm({
42555
43047
  ] });
42556
43048
  };
42557
43049
  CoordinatorConversation = ({ messages, autoScroll = true, className }) => {
42558
- const endRef = React82__default.useRef(null);
42559
- React82__default.useEffect(() => {
43050
+ const endRef = React83__default.useRef(null);
43051
+ React83__default.useEffect(() => {
42560
43052
  if (!autoScroll) return;
42561
43053
  endRef.current?.scrollIntoView({ behavior: "smooth", block: "end" });
42562
43054
  }, [messages.length, autoScroll]);
@@ -42991,7 +43483,7 @@ var init_Timeline = __esm({
42991
43483
  }) => {
42992
43484
  const { t } = useTranslate();
42993
43485
  const entityData = entity ?? [];
42994
- const items = React82__default.useMemo(() => {
43486
+ const items = React83__default.useMemo(() => {
42995
43487
  if (propItems) return propItems;
42996
43488
  if (entityData.length === 0) return [];
42997
43489
  return entityData.map((record, idx) => {
@@ -43093,7 +43585,7 @@ var init_Timeline = __esm({
43093
43585
  }
43094
43586
  });
43095
43587
  function extractToastProps(children) {
43096
- if (!React82__default.isValidElement(children)) {
43588
+ if (!React83__default.isValidElement(children)) {
43097
43589
  if (typeof children === "string") {
43098
43590
  return { message: children };
43099
43591
  }
@@ -43135,7 +43627,7 @@ var init_ToastSlot = __esm({
43135
43627
  eventBus.emit(`${prefix}CLOSE`);
43136
43628
  };
43137
43629
  if (!isVisible) return null;
43138
- const isCustomContent = React82__default.isValidElement(children) && !message;
43630
+ const isCustomContent = React83__default.isValidElement(children) && !message;
43139
43631
  return /* @__PURE__ */ jsx(Box, { className: "fixed bottom-4 right-4 z-50", children: isCustomContent ? children : /* @__PURE__ */ jsx(
43140
43632
  Toast,
43141
43633
  {
@@ -43240,6 +43732,7 @@ var init_component_registry_generated = __esm({
43240
43732
  init_Drawer();
43241
43733
  init_DrawerSlot();
43242
43734
  init_EdgeDecoration();
43735
+ init_EmojiPicker();
43243
43736
  init_EmptyState();
43244
43737
  init_ErrorBoundary();
43245
43738
  init_ErrorState();
@@ -43507,6 +44000,7 @@ var init_component_registry_generated = __esm({
43507
44000
  "Drawer": Drawer,
43508
44001
  "DrawerSlot": DrawerSlot,
43509
44002
  "EdgeDecoration": EdgeDecoration,
44003
+ "EmojiPicker": EmojiPicker,
43510
44004
  "EmptyState": EmptyState,
43511
44005
  "ErrorBoundary": ErrorBoundary,
43512
44006
  "ErrorState": ErrorState,
@@ -43706,7 +44200,7 @@ function SuspenseConfigProvider({
43706
44200
  config,
43707
44201
  children
43708
44202
  }) {
43709
- return React82__default.createElement(
44203
+ return React83__default.createElement(
43710
44204
  SuspenseConfigContext.Provider,
43711
44205
  { value: config },
43712
44206
  children
@@ -43748,7 +44242,7 @@ function enrichFormFields(fields, entityDef) {
43748
44242
  }
43749
44243
  return { name: field, label: humanizeFieldName(field) };
43750
44244
  }
43751
- if (field && typeof field === "object" && !Array.isArray(field) && !React82__default.isValidElement(field) && !(field instanceof Date)) {
44245
+ if (field && typeof field === "object" && !Array.isArray(field) && !React83__default.isValidElement(field) && !(field instanceof Date)) {
43752
44246
  const obj = field;
43753
44247
  const fieldName = typeof obj.name === "string" ? obj.name : typeof obj.field === "string" ? obj.field : void 0;
43754
44248
  if (!fieldName) return field;
@@ -43934,7 +44428,19 @@ function UISlotComponent({
43934
44428
  const suspenseConfig = useContext(SuspenseConfigContext);
43935
44429
  const contained = useContext(SlotContainedContext);
43936
44430
  const schemaCtx = useEntitySchemaOptional();
43937
- const content = slots[slot];
44431
+ const rawContent = slots[slot];
44432
+ const binding = useEntityBindingSnapshot(rawContent?.sourceTrait);
44433
+ const content = useMemo(() => {
44434
+ if (!rawContent) return rawContent;
44435
+ const resolvedProps = resolveRenderBindingMarkers(
44436
+ rawContent.props,
44437
+ rawContent.sourceTrait,
44438
+ binding.entity,
44439
+ binding.config,
44440
+ binding.state
44441
+ );
44442
+ return resolvedProps === rawContent.props ? rawContent : { ...rawContent, props: resolvedProps };
44443
+ }, [rawContent, binding.entity, binding.config, binding.state]);
43938
44444
  if (children !== void 0) {
43939
44445
  if (pattern === "clear") {
43940
44446
  return null;
@@ -44208,7 +44714,7 @@ function renderPatternChildren(children, onDismiss, parentId = "root", parentPat
44208
44714
  const key = `${parentId}-${index}-trait:${traitName}`;
44209
44715
  return /* @__PURE__ */ jsx(TraitFrame, { traitName }, key);
44210
44716
  }
44211
- return /* @__PURE__ */ jsx(React82__default.Fragment, { children: child }, `${parentId}-${index}`);
44717
+ return /* @__PURE__ */ jsx(React83__default.Fragment, { children: child }, `${parentId}-${index}`);
44212
44718
  }
44213
44719
  if (!child || typeof child !== "object") return null;
44214
44720
  const childId = `${parentId}-${index}`;
@@ -44265,19 +44771,20 @@ function isPatternConfig(value) {
44265
44771
  if (value === null || value === void 0) return false;
44266
44772
  if (typeof value !== "object") return false;
44267
44773
  if (Array.isArray(value)) return false;
44268
- if (React82__default.isValidElement(value)) return false;
44774
+ if (React83__default.isValidElement(value)) return false;
44269
44775
  if (value instanceof Date) return false;
44270
44776
  if (typeof value === "function") return false;
44271
44777
  const record = value;
44272
44778
  return "type" in record && typeof record.type === "string" && getComponentForPattern$1(record.type) !== null;
44273
44779
  }
44274
44780
  function isPlainConfigObject(value) {
44275
- if (React82__default.isValidElement(value)) return false;
44781
+ if (React83__default.isValidElement(value)) return false;
44276
44782
  if (value instanceof Date) return false;
44277
44783
  const proto = Object.getPrototypeOf(value);
44278
44784
  return proto === Object.prototype || proto === null;
44279
44785
  }
44280
44786
  function substituteTraitRefsDeep(value, pathKey) {
44787
+ if (isRenderBindingMarker(value)) return value;
44281
44788
  if (typeof value === "string") {
44282
44789
  const match = TRAIT_BINDING_RE.exec(value);
44283
44790
  if (match) {
@@ -44350,7 +44857,14 @@ function SlotContentRenderer({
44350
44857
  onDismiss,
44351
44858
  patternPath
44352
44859
  }) {
44353
- const entityProp = content.props.entity;
44860
+ const ambientScope = useTraitScope();
44861
+ const bindingTrait = content.sourceTrait ?? ambientScope?.trait;
44862
+ const binding = useEntityBindingSnapshot(bindingTrait);
44863
+ const liveProps = useMemo(
44864
+ () => resolveRenderBindingMarkers(content.props, bindingTrait, binding.entity, binding.config, binding.state),
44865
+ [content.props, bindingTrait, binding.entity, binding.config, binding.state]
44866
+ );
44867
+ const entityProp = liveProps.entity;
44354
44868
  if (content.pattern === "form-section") {
44355
44869
  slotLog.debug("SlotContentRenderer:form-section-render", {
44356
44870
  contentId: content.id,
@@ -44381,7 +44895,7 @@ function SlotContentRenderer({
44381
44895
  const orbitalName = schemaCtx && content.sourceTrait !== void 0 ? schemaCtx.orbitalsByTrait.get(content.sourceTrait) : void 0;
44382
44896
  const PatternComponent = getComponentForPattern(content.pattern);
44383
44897
  if (PatternComponent) {
44384
- const childrenConfig = content.props.children;
44898
+ const childrenConfig = liveProps.children;
44385
44899
  const isSingleChild = typeof childrenConfig === "string" || typeof childrenConfig === "object" && childrenConfig !== null && !Array.isArray(childrenConfig) && "type" in childrenConfig;
44386
44900
  const hasChildren = PATTERNS_WITH_CHILDREN.has(content.pattern) || Array.isArray(childrenConfig) && childrenConfig.length > 0 || isSingleChild;
44387
44901
  const isDrawHost = isDrawHostPattern(content.pattern);
@@ -44392,15 +44906,15 @@ function SlotContentRenderer({
44392
44906
  fromState: content.fromState,
44393
44907
  entity: content.entity
44394
44908
  }) : void 0;
44395
- const incomingChildren = content.props.children;
44909
+ const incomingChildren = liveProps.children;
44396
44910
  const childrenIsRenderFn = typeof incomingChildren === "function";
44397
- const { children: _childrenConfig, ...restPropsNoChildren } = content.props;
44911
+ const { children: _childrenConfig, ...restPropsNoChildren } = liveProps;
44398
44912
  const restProps = childrenIsRenderFn ? { ...restPropsNoChildren, children: incomingChildren } : restPropsNoChildren;
44399
44913
  const nodeSlotOverrides = {};
44400
44914
  for (const slotKey of CONTENT_NODE_SLOTS) {
44401
44915
  const slotVal = restProps[slotKey];
44402
44916
  if (slotVal === void 0 || slotVal === null) continue;
44403
- if (React82__default.isValidElement(slotVal) || typeof slotVal === "string" || typeof slotVal === "number" || typeof slotVal === "boolean") continue;
44917
+ if (React83__default.isValidElement(slotVal) || typeof slotVal === "string" || typeof slotVal === "number" || typeof slotVal === "boolean") continue;
44404
44918
  const typelessChildren = !Array.isArray(slotVal) && typeof slotVal === "object" && !("type" in slotVal) && Array.isArray(slotVal.children) ? slotVal.children : void 0;
44405
44919
  if (typelessChildren !== void 0 || Array.isArray(slotVal) || typeof slotVal === "object" && "type" in slotVal) {
44406
44920
  nodeSlotOverrides[slotKey] = renderPatternChildren(
@@ -44454,7 +44968,7 @@ function SlotContentRenderer({
44454
44968
  const resolvedItems = Array.isArray(entityVal) && entityVal[0] !== "fn" ? entityVal : null;
44455
44969
  if (resolvedItems && resolvedItems.length > 0 && !finalProps.fields && !finalProps.columns) {
44456
44970
  const sample = resolvedItems[0];
44457
- if (sample && typeof sample === "object" && !Array.isArray(sample) && !React82__default.isValidElement(sample) && !(sample instanceof Date)) {
44971
+ if (sample && typeof sample === "object" && !Array.isArray(sample) && !React83__default.isValidElement(sample) && !(sample instanceof Date)) {
44458
44972
  const keys = Object.keys(sample).filter((k) => k !== "id" && k !== "_id");
44459
44973
  finalProps.fields = keys.map((k, i) => ({ name: k, variant: i === 0 ? "h4" : "body" }));
44460
44974
  }
@@ -44503,7 +45017,7 @@ function SlotContentRenderer({
44503
45017
  "data-orb-path": patternPath ?? "root",
44504
45018
  "data-orb-pattern": content.pattern,
44505
45019
  "data-orb-orbital": orbitalName,
44506
- children: content.props.children ?? /* @__PURE__ */ jsxs(Box, { className: "p-4 text-sm text-muted-foreground border border-dashed border-border rounded", children: [
45020
+ children: liveProps.children ?? /* @__PURE__ */ jsxs(Box, { className: "p-4 text-sm text-muted-foreground border border-dashed border-border rounded", children: [
44507
45021
  "Unknown pattern: ",
44508
45022
  content.pattern,
44509
45023
  content.sourceTrait && /* @__PURE__ */ jsxs(Typography, { variant: "small", className: "ml-2", children: [
@@ -44575,6 +45089,7 @@ var scopeWrapLog, TRAIT_BINDING_RE, SuspenseConfigContext, SlotContainedContext,
44575
45089
  var init_UISlotRenderer = __esm({
44576
45090
  "components/core/organisms/UISlotRenderer.tsx"() {
44577
45091
  "use client";
45092
+ init_resolve_render_bindings();
44578
45093
  init_Modal();
44579
45094
  init_Drawer();
44580
45095
  init_Toast();
@@ -44821,12 +45336,15 @@ function resolveLambdaBindings(body, params, item, index) {
44821
45336
  const arr = body;
44822
45337
  const substituted = arr.map((b) => recur(b));
44823
45338
  if (isOperatorCall(substituted) && isSExpr(substituted)) {
45339
+ if (containsEntityBinding(substituted)) {
45340
+ return substituted;
45341
+ }
44824
45342
  const evaluated = evaluate(substituted, createMinimalContext());
44825
45343
  return isEventPayloadValue(evaluated) ? evaluated : String(evaluated);
44826
45344
  }
44827
45345
  return substituted;
44828
45346
  }
44829
- if (body !== null && typeof body === "object" && !React82__default.isValidElement(body) && !(body instanceof Date) && typeof body !== "function") {
45347
+ if (body !== null && typeof body === "object" && !React83__default.isValidElement(body) && !(body instanceof Date) && typeof body !== "function") {
44830
45348
  const out = {};
44831
45349
  for (const [k, v] of Object.entries(body)) {
44832
45350
  out[k] = recur(v);
@@ -44842,10 +45360,38 @@ function getSlotContentRenderer2() {
44842
45360
  _slotContentRenderer2 = mod.SlotContentRenderer;
44843
45361
  return _slotContentRenderer2;
44844
45362
  }
45363
+ function deferLambdaEntityExprs(value) {
45364
+ if (typeof value === "string") {
45365
+ if (containsEntityBinding(value)) {
45366
+ const marker = { [RENDER_BINDING_MARKER]: true, expression: value };
45367
+ return marker;
45368
+ }
45369
+ return value;
45370
+ }
45371
+ if (Array.isArray(value)) {
45372
+ if (isFnFormLambda(value)) return value;
45373
+ const arr = value;
45374
+ if (isOperatorCall(arr) && isSExpr(arr) && containsEntityBinding(arr)) {
45375
+ const marker = { [RENDER_BINDING_MARKER]: true, expression: arr };
45376
+ return marker;
45377
+ }
45378
+ return arr.map((v) => deferLambdaEntityExprs(v));
45379
+ }
45380
+ if (value !== null && typeof value === "object" && !React83__default.isValidElement(value) && !(value instanceof Date) && typeof value !== "function" && !isRenderBindingMarker(value)) {
45381
+ const out = {};
45382
+ for (const [k, v] of Object.entries(value)) {
45383
+ out[k] = deferLambdaEntityExprs(v);
45384
+ }
45385
+ return out;
45386
+ }
45387
+ return value;
45388
+ }
44845
45389
  function makeLambdaFn(params, lambdaBody, callerKey) {
44846
45390
  return (item, index) => {
44847
- const resolvedBody = resolveLambdaBindings(lambdaBody, params, item, index);
44848
- if (resolvedBody === null || typeof resolvedBody !== "object" || Array.isArray(resolvedBody) || typeof resolvedBody === "function" || React82__default.isValidElement(resolvedBody) || resolvedBody instanceof Date) {
45391
+ const resolvedBody = deferLambdaEntityExprs(
45392
+ resolveLambdaBindings(lambdaBody, params, item, index)
45393
+ );
45394
+ if (resolvedBody === null || typeof resolvedBody !== "object" || Array.isArray(resolvedBody) || typeof resolvedBody === "function" || React83__default.isValidElement(resolvedBody) || resolvedBody instanceof Date) {
44849
45395
  return null;
44850
45396
  }
44851
45397
  const record = resolvedBody;
@@ -44864,11 +45410,12 @@ function makeLambdaFn(params, lambdaBody, callerKey) {
44864
45410
  props: childProps,
44865
45411
  priority: 0
44866
45412
  };
44867
- return React82__default.createElement(SlotContentRenderer2, { content: childContent });
45413
+ return React83__default.createElement(SlotContentRenderer2, { content: childContent });
44868
45414
  };
44869
45415
  }
44870
45416
  function convertNode(node, callerKey) {
44871
45417
  if (node === null || node === void 0) return node;
45418
+ if (isRenderBindingMarker(node)) return node;
44872
45419
  if (Array.isArray(node)) {
44873
45420
  if (isFnFormLambda(node)) {
44874
45421
  const arr2 = node;
@@ -44883,7 +45430,7 @@ function convertNode(node, callerKey) {
44883
45430
  });
44884
45431
  return anyChanged ? mapped : node;
44885
45432
  }
44886
- if (typeof node === "object" && !React82__default.isValidElement(node) && !(node instanceof Date)) {
45433
+ if (typeof node === "object" && !React83__default.isValidElement(node) && !(node instanceof Date)) {
44887
45434
  return convertObjectProps(node);
44888
45435
  }
44889
45436
  return node;
@@ -44921,6 +45468,7 @@ var tickLog = createLogger("almadar:ui:tick-effects");
44921
45468
  setNamespaceLevel("almadar:ui:tick-effects", "WARN");
44922
45469
  var sharedEntityLog = createLogger("almadar:ui:shared-entity");
44923
45470
  setNamespaceLevel("almadar:ui:shared-entity", "WARN");
45471
+ var EMPTY_BINDING_SNAPSHOT = {};
44924
45472
  var SYNC_TICK_OPERATORS = /* @__PURE__ */ new Set([
44925
45473
  "set",
44926
45474
  "emit",
@@ -44941,11 +45489,6 @@ var SYNC_TICK_OPERATORS = /* @__PURE__ */ new Set([
44941
45489
  "do",
44942
45490
  "when"
44943
45491
  ]);
44944
- var REACTIVE_REPAINT_PATTERN_TYPES = /* @__PURE__ */ new Set([
44945
- "canvas",
44946
- "game-hud",
44947
- "game-shell"
44948
- ]);
44949
45492
  var LIFECYCLE_EVENTS = ["INIT", "LOAD", "$MOUNT"];
44950
45493
  function toTraitDefinition(binding) {
44951
45494
  return {
@@ -44986,6 +45529,27 @@ function classifySharedTick(tick) {
44986
45529
  if (renders) return "renderer";
44987
45530
  return "neither";
44988
45531
  }
45532
+ function buildTraitRenderConfig(binding, traitConfigsByName, payload) {
45533
+ const declaredDefaults = collectDeclaredConfigDefaults(binding.trait);
45534
+ const resolvedDefaults = traitConfigsByName?.[binding.trait.name];
45535
+ const callSiteConfig = getBindingConfig(binding);
45536
+ const callSiteOverrides = callSiteConfig ? resolveCallSitePayloadCaptures(
45537
+ Object.fromEntries(
45538
+ Object.entries(callSiteConfig).filter(
45539
+ ([, v]) => !containsConfigForward(v)
45540
+ )
45541
+ ),
45542
+ payload
45543
+ ) : void 0;
45544
+ if (declaredDefaults || resolvedDefaults || callSiteOverrides) {
45545
+ return {
45546
+ ...declaredDefaults ?? {},
45547
+ ...resolvedDefaults ?? {},
45548
+ ...callSiteOverrides ?? {}
45549
+ };
45550
+ }
45551
+ return void 0;
45552
+ }
44989
45553
  function createSharedEntityWriter(binding, tick, traitStatesRef, emit) {
44990
45554
  return (scratch) => {
44991
45555
  const traitName = binding.trait.name;
@@ -45206,8 +45770,24 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
45206
45770
  }, [traitStates]);
45207
45771
  const traitSnapshotDataRef = useRef(/* @__PURE__ */ new Map());
45208
45772
  const traitFieldStatesRef = useRef(/* @__PURE__ */ new Map());
45209
- const lastCanvasRenderUiRef = useRef(/* @__PURE__ */ new Map());
45210
- const executeTransitionEffectsRef = useRef(null);
45773
+ const bridgeEchoPendingRef = useRef(/* @__PURE__ */ new Map());
45774
+ const bindingSnapshotsRef = useRef(/* @__PURE__ */ new Map());
45775
+ const bindingListenersRef = useRef(/* @__PURE__ */ new Map());
45776
+ const publishBindingSnapshot = useCallback((traitName, row) => {
45777
+ bindingSnapshotsRef.current.set(traitName, { ...row });
45778
+ const listeners7 = bindingListenersRef.current.get(traitName);
45779
+ if (!listeners7) return;
45780
+ listeners7.forEach((callback) => {
45781
+ try {
45782
+ callback();
45783
+ } catch (error) {
45784
+ stateLog.error("binding-snapshot listener error", {
45785
+ traitName,
45786
+ error: error instanceof Error ? error.message : String(error)
45787
+ });
45788
+ }
45789
+ });
45790
+ }, []);
45211
45791
  useEffect(() => {
45212
45792
  const mgr = managerRef.current;
45213
45793
  const bindings = traitBindingsRef.current;
@@ -45335,15 +45915,6 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
45335
45915
  const existing = pendingSlots.get(slot) || [];
45336
45916
  existing.push({ pattern, props: props || {} });
45337
45917
  pendingSlots.set(slot, existing);
45338
- const patternType = pattern?.type;
45339
- if (patternType !== void 0 && REACTIVE_REPAINT_PATTERN_TYPES.has(patternType)) {
45340
- const rawForSlot = effects.filter(
45341
- (e) => Array.isArray(e) && (e[0] === "render-ui" || e[0] === "render") && e[1] === slot
45342
- );
45343
- if (rawForSlot.length > 0) {
45344
- lastCanvasRenderUiRef.current.set(traitName, rawForSlot);
45345
- }
45346
- }
45347
45918
  },
45348
45919
  clearSlot: (slot) => {
45349
45920
  pendingSlots.set(slot, []);
@@ -45415,11 +45986,13 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
45415
45986
  };
45416
45987
  }
45417
45988
  const sharedWrites = [];
45989
+ let didWrite = false;
45418
45990
  const baseSet = handlers.set;
45419
45991
  handlers = {
45420
45992
  ...handlers,
45421
45993
  set: async (targetId, field, value) => {
45422
45994
  if (baseSet) await baseSet(targetId, field, value);
45995
+ didWrite = true;
45423
45996
  if (sharedKey !== void 0) {
45424
45997
  sharedWrites.push({ field, value });
45425
45998
  }
@@ -45436,23 +46009,9 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
45436
46009
  payload: payload || {},
45437
46010
  state: previousState
45438
46011
  };
45439
- const declaredDefaults = collectDeclaredConfigDefaults(binding.trait);
45440
- const resolvedDefaults = traitConfigsByName?.[traitName];
45441
- const callSiteConfig = getBindingConfig(binding);
45442
- const callSiteOverrides = callSiteConfig ? resolveCallSitePayloadCaptures(
45443
- Object.fromEntries(
45444
- Object.entries(callSiteConfig).filter(
45445
- ([, v]) => !containsConfigForward(v)
45446
- )
45447
- ),
45448
- payload || {}
45449
- ) : void 0;
45450
- if (declaredDefaults || resolvedDefaults || callSiteOverrides) {
45451
- bindingCtx.config = {
45452
- ...declaredDefaults ?? {},
45453
- ...resolvedDefaults ?? {},
45454
- ...callSiteOverrides ?? {}
45455
- };
46012
+ const renderConfig = buildTraitRenderConfig(binding, traitConfigsByName, payload || {});
46013
+ if (renderConfig !== void 0) {
46014
+ bindingCtx.config = renderConfig;
45456
46015
  }
45457
46016
  if (traitName === "Authority" || traitName === "Hero") {
45458
46017
  sharedEntityLog.debug("executeTransitionEffects config tiles", {
@@ -45486,7 +46045,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
45486
46045
  effectHeads: effects.map((e) => Array.isArray(e) ? String(e[0]) : "??")
45487
46046
  });
45488
46047
  }
45489
- const executor = new EffectExecutor({ handlers: trackingHandlers, bindings: bindingCtx, context: effectContext });
46048
+ const executor = new EffectExecutor({ handlers: trackingHandlers, bindings: bindingCtx, context: effectContext, deferRenderBindings: true });
45490
46049
  try {
45491
46050
  await executor.executeAll(effects);
45492
46051
  if (traitName === "Authority" || traitName === "Hero") {
@@ -45527,37 +46086,8 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
45527
46086
  entity: binding.linkedEntity
45528
46087
  });
45529
46088
  }
45530
- if (pendingSlots.size === 0 && effectsCallOp(effects, SHARED_ENTITY_WRITE_OPS)) {
45531
- const stashed = lastCanvasRenderUiRef.current.get(traitName);
45532
- if (stashed !== void 0 && stashed.length > 0) {
45533
- await executor.executeAll(stashed);
45534
- for (const [slot, patterns] of pendingSlots) {
45535
- flushSlot(traitName, slot, patterns, {
45536
- event: flushEvent,
45537
- state: previousState,
45538
- entity: binding.linkedEntity
45539
- });
45540
- }
45541
- }
45542
- if (sharedKey !== void 0 && executeTransitionEffectsRef.current !== null) {
45543
- for (const sibling of traitBindingsRef.current) {
45544
- const siblingName = sibling.trait.name;
45545
- if (siblingName === traitName) continue;
45546
- if (sharedKeyByTraitNameRef.current.get(siblingName) !== sharedKey) continue;
45547
- const siblingStash = lastCanvasRenderUiRef.current.get(siblingName);
45548
- if (siblingStash === void 0 || siblingStash.length === 0) continue;
45549
- const siblingState = traitStatesRef.current.get(siblingName)?.currentState ?? "";
45550
- await executeTransitionEffectsRef.current({
45551
- binding: sibling,
45552
- effects: siblingStash,
45553
- previousState: siblingState,
45554
- newState: siblingState,
45555
- flushEvent: `${flushEvent}:repaint`,
45556
- syncOnly,
45557
- log: log9
45558
- });
45559
- }
45560
- }
46089
+ if (didWrite && sharedKey === void 0) {
46090
+ publishBindingSnapshot(traitName, liveEntity);
45561
46091
  }
45562
46092
  } catch (error) {
45563
46093
  log9.error("effects:error", {
@@ -45569,10 +46099,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
45569
46099
  });
45570
46100
  }
45571
46101
  return emittedDuringExec;
45572
- }, [eventBus, flushSlot, sharedEntityStore]);
45573
- useEffect(() => {
45574
- executeTransitionEffectsRef.current = executeTransitionEffects;
45575
- }, [executeTransitionEffects]);
46102
+ }, [eventBus, flushSlot, sharedEntityStore, publishBindingSnapshot]);
45576
46103
  const runTickEffects = useCallback((tick, binding) => {
45577
46104
  const traitName = binding.trait.name;
45578
46105
  const currentState = traitStatesRef.current.get(traitName)?.currentState ?? "";
@@ -45635,24 +46162,6 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
45635
46162
  ({ binding, tick }) => createSharedEntityWriter(binding, tick, traitStatesRef, emitFromSharedWriter)
45636
46163
  );
45637
46164
  runTickFrame(group.storeKey, writers, sharedEntityStore);
45638
- const repaint = executeTransitionEffectsRef.current;
45639
- if (repaint !== null) {
45640
- for (const renderBinding of group.renderBindings) {
45641
- const renderTraitName = renderBinding.trait.name;
45642
- const stash = lastCanvasRenderUiRef.current.get(renderTraitName);
45643
- if (stash === void 0 || stash.length === 0) continue;
45644
- const renderState = traitStatesRef.current.get(renderTraitName)?.currentState ?? "";
45645
- void repaint({
45646
- binding: renderBinding,
45647
- effects: stash,
45648
- previousState: renderState,
45649
- newState: renderState,
45650
- flushEvent: "tick:repaint",
45651
- syncOnly: true,
45652
- log: sharedEntityLog
45653
- });
45654
- }
45655
- }
45656
46165
  };
45657
46166
  if (interval === "frame") {
45658
46167
  scheduler.add(0, onDue);
@@ -45723,6 +46232,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
45723
46232
  executedTraits: results.map((r) => r.traitName).join(",")
45724
46233
  });
45725
46234
  const emittedByTrait = /* @__PURE__ */ new Map();
46235
+ bridgeEchoPendingRef.current.clear();
45726
46236
  for (const { traitName, result } of results) {
45727
46237
  const binding = bindingMap.get(traitName);
45728
46238
  const traitState = currentManager.getState(traitName);
@@ -45777,6 +46287,12 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
45777
46287
  log: stateLog
45778
46288
  });
45779
46289
  emittedByTrait.set(traitName, emittedDuringExec);
46290
+ for (const emittedKey of emittedDuringExec) {
46291
+ bridgeEchoPendingRef.current.set(
46292
+ emittedKey,
46293
+ (bridgeEchoPendingRef.current.get(emittedKey) ?? 0) + 1
46294
+ );
46295
+ }
45780
46296
  } else if (!result.executed) {
45781
46297
  if (result.guardResult === false) {
45782
46298
  stateLog.debug("guard-blocked-transition", {
@@ -45926,8 +46442,13 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
45926
46442
  crossTraitLog.debug("self:subscribe", { traitName, busKey: selfBusKey, eventKey });
45927
46443
  const unsub = eventBus.on(selfBusKey, (event) => {
45928
46444
  if (event.source && event.source.dispatched) {
45929
- crossTraitLog.debug("self:fire-skipped-bridge-echo", { traitName, busKey: selfBusKey, eventKey });
45930
- return;
46445
+ const pendingEchoes = bridgeEchoPendingRef.current.get(eventKey) ?? 0;
46446
+ if (pendingEchoes > 0) {
46447
+ bridgeEchoPendingRef.current.set(eventKey, pendingEchoes - 1);
46448
+ crossTraitLog.debug("self:fire-skipped-bridge-echo", { traitName, busKey: selfBusKey, eventKey });
46449
+ return;
46450
+ }
46451
+ crossTraitLog.debug("self:fire-server-cascade", { traitName, busKey: selfBusKey, eventKey });
45931
46452
  }
45932
46453
  crossTraitLog.debug("self:fire", { traitName, busKey: selfBusKey, eventKey });
45933
46454
  enqueueAndDrain(eventKey, event.payload, traitName);
@@ -46019,11 +46540,47 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
46019
46540
  initedTraitsRef.current = /* @__PURE__ */ new Set();
46020
46541
  };
46021
46542
  }, [traitBindings, enqueueAndDrain]);
46543
+ const entityBindingSource = useMemo(() => ({
46544
+ getEntitySnapshot: (traitName) => {
46545
+ const sharedKey = sharedKeyByTraitNameRef.current.get(traitName);
46546
+ if (sharedKey !== void 0) {
46547
+ return sharedEntityStore.getSnapshot(sharedKey);
46548
+ }
46549
+ return bindingSnapshotsRef.current.get(traitName) ?? EMPTY_BINDING_SNAPSHOT;
46550
+ },
46551
+ getConfig: (traitName) => {
46552
+ const binding = traitBindingsRef.current.find((b) => b.trait.name === traitName);
46553
+ if (binding === void 0) return void 0;
46554
+ return buildTraitRenderConfig(binding, traitConfigsByName, {});
46555
+ },
46556
+ getState: (traitName) => traitStatesRef.current.get(traitName)?.currentState ?? "",
46557
+ subscribe: (traitName, callback) => {
46558
+ const sharedKey = sharedKeyByTraitNameRef.current.get(traitName);
46559
+ if (sharedKey !== void 0) {
46560
+ return sharedEntityStore.subscribe(sharedKey, callback);
46561
+ }
46562
+ let listeners7 = bindingListenersRef.current.get(traitName);
46563
+ if (!listeners7) {
46564
+ listeners7 = /* @__PURE__ */ new Set();
46565
+ bindingListenersRef.current.set(traitName, listeners7);
46566
+ }
46567
+ listeners7.add(callback);
46568
+ return () => {
46569
+ const current = bindingListenersRef.current.get(traitName);
46570
+ if (!current) return;
46571
+ current.delete(callback);
46572
+ if (current.size === 0) {
46573
+ bindingListenersRef.current.delete(traitName);
46574
+ }
46575
+ };
46576
+ }
46577
+ }), [sharedEntityStore, traitConfigsByName]);
46022
46578
  return {
46023
46579
  traitStates,
46024
46580
  sendEvent,
46025
46581
  getTraitState,
46026
- canHandleEvent
46582
+ canHandleEvent,
46583
+ entityBindingSource
46027
46584
  };
46028
46585
  }
46029
46586
  var resolvedSchemaLog = createLogger("almadar:ui:resolved-schema");
@@ -46215,7 +46772,7 @@ function collectServerActiveTraits(ir, allTraits, mountedTraitNames) {
46215
46772
  }
46216
46773
  return active;
46217
46774
  }
46218
- function TraitInitializer({ traits: traits2, routeParams, orbitalNames, onNavigate, onLocalFallback, persistence, traitConfigsByName, orbitalsByTrait, embeddedTraits, serverActiveTraits }) {
46775
+ function TraitInitializer({ traits: traits2, routeParams, orbitalNames, onNavigate, onLocalFallback, persistence, traitConfigsByName, orbitalsByTrait, embeddedTraits, serverActiveTraits, children }) {
46219
46776
  const bridge = useServerBridge();
46220
46777
  const activeTraitNames = useMemo(
46221
46778
  () => new Set(traits2.map((b) => b.trait.name).filter((n) => !!n)),
@@ -46245,7 +46802,7 @@ function TraitInitializer({ traits: traits2, routeParams, orbitalNames, onNaviga
46245
46802
  }
46246
46803
  }, [bridge.connected, bridge.sendEvent, orbitalNames, uiSlots, onNavigate, embeddedTraits, activeTraitNames, withActiveTraits]);
46247
46804
  const opts = orbitalNames ? { onEventProcessed, navigate: onNavigate, traitConfigsByName, orbitalsByTrait, embeddedTraits, initPayload: routeParams } : { navigate: onNavigate, persistence, traitConfigsByName, orbitalsByTrait, embeddedTraits, initPayload: routeParams };
46248
- const { sendEvent } = useTraitStateMachine(traits2, uiSlots, opts);
46805
+ const { sendEvent, entityBindingSource } = useTraitStateMachine(traits2, uiSlots, opts);
46249
46806
  const initSentRef = useRef(false);
46250
46807
  const prevTraitsRef = useRef(void 0);
46251
46808
  const paramsKey = JSON.stringify(routeParams ?? {});
@@ -46291,7 +46848,7 @@ function TraitInitializer({ traits: traits2, routeParams, orbitalNames, onNaviga
46291
46848
  { type: "fetch", args: [], status: "executed" },
46292
46849
  ...effects.map((eff) => ({
46293
46850
  type: eff.type,
46294
- args: eff.type === "render-ui" ? [eff.slot] : [],
46851
+ args: eff.type === "render-ui" && eff.slot !== void 0 ? [eff.slot] : [],
46295
46852
  status: "executed"
46296
46853
  }))
46297
46854
  ];
@@ -46307,7 +46864,7 @@ function TraitInitializer({ traits: traits2, routeParams, orbitalNames, onNaviga
46307
46864
  }
46308
46865
  })();
46309
46866
  }, [bridge.connected, orbitalNames, bridge.sendEvent, uiSlots, onNavigate, embeddedTraits, activeTraitNames, withActiveTraits, routeParams]);
46310
- return null;
46867
+ return /* @__PURE__ */ jsx(EntityBindingContext.Provider, { value: entityBindingSource, children });
46311
46868
  }
46312
46869
  function SchemaRunner({ schema, serverUrl, transport, mockData, pageName, routeParams, onNavigate, onLocalFallback, persistence }) {
46313
46870
  const { traits: traits2, allEntities, allTraits, ir } = useResolvedSchema(schema, pageName);
@@ -46440,30 +46997,28 @@ function SchemaRunner({ schema, serverUrl, transport, mockData, pageName, routeP
46440
46997
  }
46441
46998
  return schema.orbitals[0]?.theme;
46442
46999
  }, [schema, pageName]);
46443
- const inner = /* @__PURE__ */ jsx(VerificationProvider, { enabled: true, children: /* @__PURE__ */ jsxs(
47000
+ const inner = /* @__PURE__ */ jsx(VerificationProvider, { enabled: true, children: /* @__PURE__ */ jsx(
46444
47001
  EntitySchemaProvider,
46445
47002
  {
46446
47003
  entities: entitiesArray,
46447
47004
  traitLinkedEntities: traitLinkedEntitiesMap,
46448
47005
  orbitalsByTrait: orbitalsByTraitMap,
46449
- children: [
46450
- /* @__PURE__ */ jsx(
46451
- TraitInitializer,
46452
- {
46453
- traits: allPageTraits,
46454
- routeParams,
46455
- orbitalNames: serverUrl || transport ? pageOrbitalNames : void 0,
46456
- traitConfigsByName,
46457
- orbitalsByTrait,
46458
- embeddedTraits,
46459
- serverActiveTraits,
46460
- onNavigate,
46461
- onLocalFallback,
46462
- persistence
46463
- }
46464
- ),
46465
- /* @__PURE__ */ jsx(OrbitalThemeProvider, { theme: activeOrbitalTheme, children: /* @__PURE__ */ jsx(Box, { className: "h-full min-h-full overflow-auto p-4", children: /* @__PURE__ */ jsx(UISlotRenderer, { includeHud: true, hudMode: "inline", includeFloating: true }) }) })
46466
- ]
47006
+ children: /* @__PURE__ */ jsx(
47007
+ TraitInitializer,
47008
+ {
47009
+ traits: allPageTraits,
47010
+ routeParams,
47011
+ orbitalNames: serverUrl || transport ? pageOrbitalNames : void 0,
47012
+ traitConfigsByName,
47013
+ orbitalsByTrait,
47014
+ embeddedTraits,
47015
+ serverActiveTraits,
47016
+ onNavigate,
47017
+ onLocalFallback,
47018
+ persistence,
47019
+ children: /* @__PURE__ */ jsx(OrbitalThemeProvider, { theme: activeOrbitalTheme, children: /* @__PURE__ */ jsx(Box, { className: "h-full min-h-full overflow-auto p-4", children: /* @__PURE__ */ jsx(UISlotRenderer, { includeHud: true, hudMode: "inline", includeFloating: true }) }) })
47020
+ }
47021
+ )
46467
47022
  }
46468
47023
  ) });
46469
47024
  if (serverUrl || transport) {