@almadar/ui 5.135.0 → 5.136.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/avl/index.js CHANGED
@@ -1,11 +1,13 @@
1
1
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
- import * as React91 from 'react';
3
- import React91__default, { createContext, useState, useMemo, useRef, useEffect, useContext, useCallback, Suspense, useLayoutEffect, Profiler, useReducer, useSyncExternalStore, lazy, useId } from 'react';
4
- import { getAllPages, matchPathAmong, OrbitalProvider, EventBusContext, useTraitScopeChain, ServerBridgeProvider, VerificationProvider, EntitySchemaProvider, OrbitalThemeProvider, useServerBridge, useEntitySchema, useEntitySchemaOptional, TraitScopeProvider, useCurrentPagePath, useGameAudioContextOptional } from '@almadar/ui/providers';
2
+ import * as React92 from 'react';
3
+ import React92__default, { createContext, useState, useMemo, useRef, useEffect, useContext, useCallback, Suspense, useLayoutEffect, Profiler, useReducer, useSyncExternalStore, lazy, useId } from 'react';
4
+ import { getAllPages, matchPathAmong, OrbitalProvider, EventBusContext, useTraitScopeChain, ServerBridgeProvider, VerificationProvider, EntitySchemaProvider, OrbitalThemeProvider, useServerBridge, EntityBindingContext, useEntitySchema, useEntitySchemaOptional, useEntityBindingSnapshot, TraitScopeProvider, useTraitScope, useCurrentPagePath, useGameAudioContextOptional } from '@almadar/ui/providers';
5
5
  import { createLogger, setNamespaceLevel, isLogLevelEnabled } from '@almadar/logger';
6
6
  import ELK from 'elkjs/lib/elk.bundled.js';
7
7
  import { MarkerType, useReactFlow, Handle, Position, getBezierPath, EdgeLabelRenderer, useNodeId, ReactFlowProvider, BaseEdge, useNodesState, useEdgesState, ReactFlow, Controls, Background, BackgroundVariant } from '@xyflow/react';
8
8
  import { useTranslate } from '@almadar/ui/hooks';
9
+ import { InMemoryPersistence, StateMachineManager, collectDeclaredConfigDefaults, resolveCallSitePayloadCaptures, createServerEffectHandlers, EffectExecutor, createContextFromBindings, createTickScheduler, isValidCronExpression, parseDurationString, normalizeCallSiteConfigToValues, interpolateValue } from '@almadar/runtime';
10
+ import { FieldTypeSchema, isInlineTrait, isPageReference, buildResolvedTraitConfigs, schemaToIR, getPage, mergeEntityFrame, isCircuitEvent, applyListenPayloadMapping, walkSExpr, isRenderBindingMarker, containsEntityBinding, isSExpr, isEventPayloadValue, RENDER_BINDING_MARKER } from '@almadar/core';
9
11
  import * as LucideIcons2 from 'lucide-react';
10
12
  import { Loader2, X, Code, FileText, WrapText, Check, Copy, Lightbulb, CheckCircle, List, Printer, ChevronRight, ChevronLeft, GitBranch, Pencil, Eye, Plus, ArrowRight, Trash, RotateCcw, Play, Terminal, XCircle, AlertTriangle, Trash2, Link2, ZoomOut, ZoomIn, Download, ChevronDown, Menu as Menu$1, Package, Calendar, MoreHorizontal, Image as Image$1, Upload, ArrowLeft, HelpCircle, PauseCircle, Search, Type, Heading1, Heading2, Heading3, ListOrdered, Quote, Minus, Eraser, TrendingUp, TrendingDown, AlertCircle, Circle, Clock, CheckCircle2, ChevronUp, Tag, User, DollarSign } from 'lucide-react';
11
13
  import { createPortal } from 'react-dom';
@@ -66,15 +68,14 @@ import ReactMarkdown from 'react-markdown';
66
68
  import remarkGfm from 'remark-gfm';
67
69
  import remarkMath from 'remark-math';
68
70
  import rehypeKatex from 'rehype-katex';
69
- import { FieldTypeSchema, isInlineTrait, isPageReference, buildResolvedTraitConfigs, schemaToIR, getPage, mergeEntityFrame, isCircuitEvent, applyListenPayloadMapping, walkSExpr, isSExpr, isEventPayloadValue } from '@almadar/core';
70
71
  import { useDroppable, useDraggable, DndContext, DragOverlay, useSensors, useSensor, PointerSensor, KeyboardSensor, pointerWithin, rectIntersection, closestCorners } from '@dnd-kit/core';
71
72
  import { sortableKeyboardCoordinates, useSortable, arrayMove, SortableContext, rectSortingStrategy, verticalListSortingStrategy } from '@dnd-kit/sortable';
72
73
  import { CSS } from '@dnd-kit/utilities';
74
+ import { ordered, lib } from 'emojilib';
73
75
  import { forceSimulation, forceLink, forceManyBody, forceCollide, forceX, forceY } from 'd3-force';
74
76
  import { isDrawHostPattern, getPatternDefinition, getComponentForPattern as getComponentForPattern$1, isEntityAwarePattern } from '@almadar/core/patterns';
75
77
  import { OrbitalServerRuntime } from '@almadar/runtime/OrbitalServerRuntime';
76
78
  import { isKnownStdOperator } from '@almadar/std/registry';
77
- import { InMemoryPersistence, StateMachineManager, collectDeclaredConfigDefaults, resolveCallSitePayloadCaptures, createServerEffectHandlers, EffectExecutor, createContextFromBindings, createTickScheduler, isValidCronExpression, parseDurationString, normalizeCallSiteConfigToValues } from '@almadar/runtime';
78
79
 
79
80
  var __defProp = Object.defineProperty;
80
81
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -3300,7 +3301,7 @@ var init_Typography = __esm({
3300
3301
  if (format !== void 0 && format !== "none" && (typeof body === "string" || typeof body === "number" || body instanceof Date)) {
3301
3302
  body = formatValue(body, format);
3302
3303
  }
3303
- return React91__default.createElement(
3304
+ return React92__default.createElement(
3304
3305
  Component,
3305
3306
  {
3306
3307
  id,
@@ -3646,7 +3647,7 @@ var init_Box = __esm({
3646
3647
  fixed: "fixed",
3647
3648
  sticky: "sticky"
3648
3649
  };
3649
- Box = React91__default.forwardRef(
3650
+ Box = React92__default.forwardRef(
3650
3651
  ({
3651
3652
  padding,
3652
3653
  paddingX,
@@ -3711,7 +3712,7 @@ var init_Box = __esm({
3711
3712
  onPointerDown?.(e);
3712
3713
  }, [hoverEvent, tapReveal, triggerProps, onPointerDown]);
3713
3714
  const isClickable = action || onClick;
3714
- return React91__default.createElement(
3715
+ return React92__default.createElement(
3715
3716
  Component,
3716
3717
  {
3717
3718
  ref,
@@ -3807,7 +3808,7 @@ var init_Stack = __esm({
3807
3808
  };
3808
3809
  const isHorizontal = direction === "horizontal";
3809
3810
  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";
3810
- return React91__default.createElement(
3811
+ return React92__default.createElement(
3811
3812
  Component,
3812
3813
  {
3813
3814
  className: cn(
@@ -4299,7 +4300,7 @@ var init_MiniStateMachine = __esm({
4299
4300
  const x = 2 + i * (NODE_W + GAP + ARROW_W + GAP);
4300
4301
  const tc = transitionCounts[s.name] ?? 0;
4301
4302
  const role = getStateRole(s.name, s.isInitial ?? void 0, s.isTerminal ?? void 0, tc, maxTC);
4302
- return /* @__PURE__ */ jsxs(React91__default.Fragment, { children: [
4303
+ return /* @__PURE__ */ jsxs(React92__default.Fragment, { children: [
4303
4304
  /* @__PURE__ */ jsx(
4304
4305
  AvlState,
4305
4306
  {
@@ -4570,6 +4571,75 @@ var init_BehaviorView = __esm({
4570
4571
  BehaviorView.displayName = "BehaviorView";
4571
4572
  }
4572
4573
  });
4574
+ function resolveMarkerExpression(expression, entity, config, state) {
4575
+ const ctx = createContextFromBindings({
4576
+ entity,
4577
+ payload: {},
4578
+ state,
4579
+ ...config !== void 0 ? { config } : {}
4580
+ });
4581
+ return interpolateValue(expression, ctx);
4582
+ }
4583
+ function isPlainObject(value) {
4584
+ if (value === null || value === void 0 || typeof value !== "object") return false;
4585
+ if (Array.isArray(value)) return false;
4586
+ if (React92__default.isValidElement(value)) return false;
4587
+ if (value instanceof Date) return false;
4588
+ if (typeof value === "function") return false;
4589
+ return true;
4590
+ }
4591
+ function walkValue(value, scopeTrait, entity, config, state) {
4592
+ if (isRenderBindingMarker(value)) {
4593
+ return { resolved: resolveMarkerExpression(value.expression, entity, config, state), changed: true };
4594
+ }
4595
+ if (Array.isArray(value)) {
4596
+ const out = [];
4597
+ let changed = false;
4598
+ for (const item of value) {
4599
+ const element = item;
4600
+ const wasMarker = isRenderBindingMarker(element);
4601
+ const { resolved, changed: itemChanged } = walkValue(element, scopeTrait, entity, config, state);
4602
+ if (wasMarker && Array.isArray(resolved)) {
4603
+ out.push(...resolved);
4604
+ changed = true;
4605
+ continue;
4606
+ }
4607
+ out.push(resolved);
4608
+ if (itemChanged) changed = true;
4609
+ }
4610
+ return changed ? { resolved: out, changed: true } : { resolved: value, changed: false };
4611
+ }
4612
+ if (isPlainObject(value)) {
4613
+ const sourceTrait = value._sourceTrait;
4614
+ if (typeof sourceTrait === "string" && sourceTrait !== scopeTrait) {
4615
+ return { resolved: value, changed: false };
4616
+ }
4617
+ const out = {};
4618
+ let changed = false;
4619
+ for (const [key, item] of Object.entries(value)) {
4620
+ const { resolved, changed: itemChanged } = walkValue(item, scopeTrait, entity, config, state);
4621
+ out[key] = resolved;
4622
+ if (itemChanged) changed = true;
4623
+ }
4624
+ return changed ? { resolved: out, changed: true } : { resolved: value, changed: false };
4625
+ }
4626
+ return { resolved: value, changed: false };
4627
+ }
4628
+ function resolveRenderBindingMarkers(props, scopeTrait, entity, config, state) {
4629
+ const out = {};
4630
+ let changed = false;
4631
+ for (const [key, value] of Object.entries(props)) {
4632
+ const { resolved, changed: propChanged } = walkValue(value, scopeTrait, entity, config, state);
4633
+ out[key] = resolved;
4634
+ if (propChanged) changed = true;
4635
+ }
4636
+ return changed ? out : props;
4637
+ }
4638
+ var init_resolve_render_bindings = __esm({
4639
+ "lib/resolve-render-bindings.ts"() {
4640
+ "use client";
4641
+ }
4642
+ });
4573
4643
  function getCurrentIconFamily() {
4574
4644
  if (typeof window === "undefined" || typeof document === "undefined") {
4575
4645
  return DEFAULT_FAMILY;
@@ -4750,7 +4820,7 @@ var init_Icon = __esm({
4750
4820
  const effectiveName = typeof icon === "string" && icon !== "" ? icon : name;
4751
4821
  const effectiveStrokeWidth = strokeWidth != null && strokeWidth > 0 ? strokeWidth : void 0;
4752
4822
  const family = useIconFamily();
4753
- const RenderedComponent = React91__default.useMemo(() => {
4823
+ const RenderedComponent = React92__default.useMemo(() => {
4754
4824
  if (directIcon) return null;
4755
4825
  return effectiveName ? resolveIconForFamily(effectiveName) : null;
4756
4826
  }, [directIcon, effectiveName, family]);
@@ -4812,9 +4882,13 @@ function getAtlas(url, onReady) {
4812
4882
  onReady();
4813
4883
  }).catch(() => {
4814
4884
  atlasCache.set(url, null);
4885
+ onReady();
4815
4886
  });
4816
4887
  return void 0;
4817
4888
  }
4889
+ function atlasFailed(url) {
4890
+ return atlasCache.get(url) === null;
4891
+ }
4818
4892
  function subRectFor(atlas, sprite) {
4819
4893
  if (isTilesheet(atlas)) {
4820
4894
  let col;
@@ -4870,7 +4944,7 @@ var init_atlasSlice = __esm({
4870
4944
  }
4871
4945
  });
4872
4946
  function useAtlasSliceDataUrl(asset) {
4873
- const [, bump] = React91.useReducer((x) => x + 1, 0);
4947
+ const [, bump] = React92.useReducer((x) => x + 1, 0);
4874
4948
  if (!isAtlasAsset(asset)) return void 0;
4875
4949
  const key = `${asset.atlas}#${asset.sprite}`;
4876
4950
  const cached = sliceDataUrlCache.get(key);
@@ -4933,13 +5007,13 @@ function AtlasImage({
4933
5007
  style,
4934
5008
  "aria-hidden": ariaHidden
4935
5009
  }) {
4936
- const [, bump] = React91.useReducer((x) => x + 1, 0);
4937
- const canvasRef = React91.useRef(null);
5010
+ const [, bump] = React92.useReducer((x) => x + 1, 0);
5011
+ const canvasRef = React92.useRef(null);
4938
5012
  const sliced = isAtlasAsset(asset);
4939
5013
  const atlas = sliced ? getAtlas(asset.atlas, bump) : void 0;
4940
5014
  const img = sliced && asset?.url ? getSheetImage(asset.url, bump) : null;
4941
5015
  const rect = sliced && atlas ? subRectFor(atlas, asset.sprite) : null;
4942
- React91.useEffect(() => {
5016
+ React92.useEffect(() => {
4943
5017
  const canvas = canvasRef.current;
4944
5018
  if (!canvas || !img || !rect) return;
4945
5019
  canvas.width = rect.sw;
@@ -5015,7 +5089,7 @@ function resolveIconProp(value, sizeClass) {
5015
5089
  const IconComp = value;
5016
5090
  return /* @__PURE__ */ jsx(IconComp, { className: sizeClass });
5017
5091
  }
5018
- if (React91__default.isValidElement(value)) {
5092
+ if (React92__default.isValidElement(value)) {
5019
5093
  return value;
5020
5094
  }
5021
5095
  if (typeof value === "object" && value !== null && isIconLike(value)) {
@@ -5092,7 +5166,7 @@ var init_Button = __esm({
5092
5166
  md: "h-icon-default w-icon-default",
5093
5167
  lg: "h-icon-default w-icon-default"
5094
5168
  };
5095
- Button = React91__default.forwardRef(
5169
+ Button = React92__default.forwardRef(
5096
5170
  ({
5097
5171
  className,
5098
5172
  variant = "primary",
@@ -5162,7 +5236,7 @@ var Dialog;
5162
5236
  var init_Dialog = __esm({
5163
5237
  "components/core/atoms/Dialog.tsx"() {
5164
5238
  init_cn();
5165
- Dialog = React91__default.forwardRef(
5239
+ Dialog = React92__default.forwardRef(
5166
5240
  ({
5167
5241
  role = "dialog",
5168
5242
  "aria-modal": ariaModal = true,
@@ -5725,7 +5799,7 @@ var init_Badge = __esm({
5725
5799
  md: "px-2.5 py-1 text-sm",
5726
5800
  lg: "px-3 py-1.5 text-base"
5727
5801
  };
5728
- Badge = React91__default.forwardRef(
5802
+ Badge = React92__default.forwardRef(
5729
5803
  ({ className, variant = "default", size = "sm", amount, label, icon, iconAsset, children, onRemove, removeLabel, ...props }, ref) => {
5730
5804
  const iconSizes3 = {
5731
5805
  sm: "h-icon-default w-icon-default",
@@ -6075,7 +6149,7 @@ var init_SvgFlow = __esm({
6075
6149
  width = 100,
6076
6150
  height = 100
6077
6151
  }) => {
6078
- const markerId = React91__default.useMemo(() => {
6152
+ const markerId = React92__default.useMemo(() => {
6079
6153
  flowIdCounter += 1;
6080
6154
  return `almadar-flow-arrow-${flowIdCounter}`;
6081
6155
  }, []);
@@ -6668,7 +6742,7 @@ var init_SvgRing = __esm({
6668
6742
  width = 100,
6669
6743
  height = 100
6670
6744
  }) => {
6671
- const gradientId = React91__default.useMemo(() => {
6745
+ const gradientId = React92__default.useMemo(() => {
6672
6746
  ringIdCounter += 1;
6673
6747
  return `almadar-ring-glow-${ringIdCounter}`;
6674
6748
  }, []);
@@ -6849,7 +6923,7 @@ var init_Input = __esm({
6849
6923
  init_cn();
6850
6924
  init_Icon();
6851
6925
  init_useEventBus();
6852
- Input = React91__default.forwardRef(
6926
+ Input = React92__default.forwardRef(
6853
6927
  ({
6854
6928
  className,
6855
6929
  inputType,
@@ -6872,6 +6946,20 @@ var init_Input = __esm({
6872
6946
  const { t } = useTranslate();
6873
6947
  const eventBus = useEventBus();
6874
6948
  const type = inputType || htmlType || "text";
6949
+ const isDeclarative = typeof onChange === "string";
6950
+ const [localValue, setLocalValue] = React92__default.useState(value);
6951
+ const pendingEchoRef = React92__default.useRef(/* @__PURE__ */ new Set());
6952
+ React92__default.useEffect(() => {
6953
+ if (!isDeclarative) return;
6954
+ const incoming = value == null ? "" : String(value);
6955
+ if (pendingEchoRef.current.has(incoming)) {
6956
+ pendingEchoRef.current.delete(incoming);
6957
+ return;
6958
+ }
6959
+ pendingEchoRef.current.clear();
6960
+ setLocalValue(value);
6961
+ }, [value, isDeclarative]);
6962
+ const displayValue = isDeclarative ? localValue : value;
6875
6963
  const resolveIconNode = (i, cls) => {
6876
6964
  if (!i) return null;
6877
6965
  if (typeof i === "string") return /* @__PURE__ */ jsx(Icon, { name: i, className: cls });
@@ -6881,7 +6969,7 @@ var init_Input = __esm({
6881
6969
  const iconCls = "h-icon-default w-icon-default";
6882
6970
  const IconComponent = typeof iconProp === "string" ? resolveIcon(iconProp) : iconProp;
6883
6971
  const resolvedLeftIcon = (leftIcon ? resolveIconNode(leftIcon, iconCls) : null) || IconComponent && /* @__PURE__ */ jsx(IconComponent, { className: iconCls });
6884
- const showClearButton = clearable && value && String(value).length > 0;
6972
+ const showClearButton = clearable && displayValue && String(displayValue).length > 0;
6885
6973
  const isMultiline = type === "textarea";
6886
6974
  const baseClassName = cn(
6887
6975
  "block w-full rounded-sm transition-all duration-fast",
@@ -6900,6 +6988,10 @@ var init_Input = __esm({
6900
6988
  if (typeof onChange === "string") {
6901
6989
  const target = e.target;
6902
6990
  const payload = type === "checkbox" ? { checked: target.checked } : { value: target.value };
6991
+ if (type !== "checkbox") {
6992
+ pendingEchoRef.current.add(target.value);
6993
+ setLocalValue(target.value);
6994
+ }
6903
6995
  eventBus.emit(`UI:${onChange}`, payload);
6904
6996
  } else {
6905
6997
  onChange?.(e);
@@ -6930,7 +7022,7 @@ var init_Input = __esm({
6930
7022
  "select",
6931
7023
  {
6932
7024
  ref,
6933
- value,
7025
+ value: displayValue,
6934
7026
  onChange: handleChange,
6935
7027
  className: cn(baseClassName, "appearance-none pr-10", className),
6936
7028
  ...props,
@@ -6950,7 +7042,7 @@ var init_Input = __esm({
6950
7042
  "textarea",
6951
7043
  {
6952
7044
  ref,
6953
- value,
7045
+ value: displayValue,
6954
7046
  onChange: handleChange,
6955
7047
  rows,
6956
7048
  className: baseClassName,
@@ -6989,7 +7081,7 @@ var init_Input = __esm({
6989
7081
  {
6990
7082
  ref,
6991
7083
  type,
6992
- value,
7084
+ value: displayValue,
6993
7085
  onChange: handleChange,
6994
7086
  onKeyDown: handleKeyDown,
6995
7087
  className: baseClassName,
@@ -7017,7 +7109,7 @@ var Label;
7017
7109
  var init_Label = __esm({
7018
7110
  "components/core/atoms/Label.tsx"() {
7019
7111
  init_cn();
7020
- Label = React91__default.forwardRef(
7112
+ Label = React92__default.forwardRef(
7021
7113
  ({ className, required, children, ...props }, ref) => {
7022
7114
  return /* @__PURE__ */ jsxs(
7023
7115
  "label",
@@ -7044,7 +7136,7 @@ var init_Textarea = __esm({
7044
7136
  "components/core/atoms/Textarea.tsx"() {
7045
7137
  init_cn();
7046
7138
  init_useEventBus();
7047
- Textarea = React91__default.forwardRef(
7139
+ Textarea = React92__default.forwardRef(
7048
7140
  ({ className, error, onChange, ...props }, ref) => {
7049
7141
  const eventBus = useEventBus();
7050
7142
  const handleChange = (e) => {
@@ -7283,7 +7375,7 @@ var init_Select = __esm({
7283
7375
  init_cn();
7284
7376
  init_Icon();
7285
7377
  init_useEventBus();
7286
- Select = React91__default.forwardRef(
7378
+ Select = React92__default.forwardRef(
7287
7379
  (props, _ref) => {
7288
7380
  const { multiple, searchable, clearable } = props;
7289
7381
  if (multiple || searchable || clearable) {
@@ -7300,7 +7392,7 @@ var init_Checkbox = __esm({
7300
7392
  "components/core/atoms/Checkbox.tsx"() {
7301
7393
  init_cn();
7302
7394
  init_useEventBus();
7303
- Checkbox = React91__default.forwardRef(
7395
+ Checkbox = React92__default.forwardRef(
7304
7396
  ({ className, label, id, onChange, ...props }, ref) => {
7305
7397
  const inputId = id || `checkbox-${Math.random().toString(36).substr(2, 9)}`;
7306
7398
  const eventBus = useEventBus();
@@ -7354,7 +7446,7 @@ var init_Spinner = __esm({
7354
7446
  md: "h-6 w-6",
7355
7447
  lg: "h-8 w-8"
7356
7448
  };
7357
- Spinner = React91__default.forwardRef(
7449
+ Spinner = React92__default.forwardRef(
7358
7450
  ({ className, size = "md", overlay, ...props }, ref) => {
7359
7451
  if (overlay) {
7360
7452
  return /* @__PURE__ */ jsx(
@@ -7444,7 +7536,7 @@ var init_Card = __esm({
7444
7536
  chip: "shadow-none rounded-pill border-[length:var(--border-width)] border-border",
7445
7537
  "tile-image-first": "p-0 overflow-hidden"
7446
7538
  };
7447
- Card = React91__default.forwardRef(
7539
+ Card = React92__default.forwardRef(
7448
7540
  ({
7449
7541
  className,
7450
7542
  variant = "bordered",
@@ -7493,9 +7585,9 @@ var init_Card = __esm({
7493
7585
  }
7494
7586
  );
7495
7587
  Card.displayName = "Card";
7496
- CardHeader = React91__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("mb-4", className), ...props }));
7588
+ CardHeader = React92__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("mb-4", className), ...props }));
7497
7589
  CardHeader.displayName = "CardHeader";
7498
- CardTitle = React91__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
7590
+ CardTitle = React92__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
7499
7591
  "h3",
7500
7592
  {
7501
7593
  ref,
@@ -7508,11 +7600,11 @@ var init_Card = __esm({
7508
7600
  }
7509
7601
  ));
7510
7602
  CardTitle.displayName = "CardTitle";
7511
- CardContent = React91__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("", className), ...props }));
7603
+ CardContent = React92__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("", className), ...props }));
7512
7604
  CardContent.displayName = "CardContent";
7513
7605
  CardBody = CardContent;
7514
7606
  CardBody.displayName = "CardBody";
7515
- CardFooter = React91__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
7607
+ CardFooter = React92__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
7516
7608
  "div",
7517
7609
  {
7518
7610
  ref,
@@ -7599,7 +7691,7 @@ var init_FilterPill = __esm({
7599
7691
  md: "w-3.5 h-3.5",
7600
7692
  lg: "w-4 h-4"
7601
7693
  };
7602
- FilterPill = React91__default.forwardRef(
7694
+ FilterPill = React92__default.forwardRef(
7603
7695
  ({
7604
7696
  className,
7605
7697
  variant = "default",
@@ -7728,8 +7820,8 @@ var init_Avatar = __esm({
7728
7820
  actionPayload
7729
7821
  }) => {
7730
7822
  const eventBus = useEventBus();
7731
- const [imgFailed, setImgFailed] = React91__default.useState(false);
7732
- React91__default.useEffect(() => {
7823
+ const [imgFailed, setImgFailed] = React92__default.useState(false);
7824
+ React92__default.useEffect(() => {
7733
7825
  setImgFailed(false);
7734
7826
  }, [src]);
7735
7827
  const initials = providedInitials ?? (name ? generateInitials(name) : void 0);
@@ -7842,7 +7934,7 @@ var init_Center = __esm({
7842
7934
  as: Component = "div"
7843
7935
  }) => {
7844
7936
  const mergedStyle = minHeight ? { minHeight, ...style } : style;
7845
- return React91__default.createElement(Component, {
7937
+ return React92__default.createElement(Component, {
7846
7938
  className: cn(
7847
7939
  inline ? "inline-flex" : "flex",
7848
7940
  horizontal && "justify-center",
@@ -8110,7 +8202,7 @@ var init_Radio = __esm({
8110
8202
  md: "w-2.5 h-2.5",
8111
8203
  lg: "w-3 h-3"
8112
8204
  };
8113
- Radio = React91__default.forwardRef(
8205
+ Radio = React92__default.forwardRef(
8114
8206
  ({
8115
8207
  label,
8116
8208
  helperText,
@@ -8127,12 +8219,12 @@ var init_Radio = __esm({
8127
8219
  onChange,
8128
8220
  ...props
8129
8221
  }, ref) => {
8130
- const reactId = React91__default.useId();
8222
+ const reactId = React92__default.useId();
8131
8223
  const baseId = id || `radio-${reactId}`;
8132
8224
  const hasError = !!error;
8133
8225
  const eventBus = useEventBus();
8134
- const [selected, setSelected] = React91__default.useState(value);
8135
- React91__default.useEffect(() => {
8226
+ const [selected, setSelected] = React92__default.useState(value);
8227
+ React92__default.useEffect(() => {
8136
8228
  if (value !== void 0) setSelected(value);
8137
8229
  }, [value]);
8138
8230
  const pick = (next, e) => {
@@ -8314,7 +8406,7 @@ var init_Switch = __esm({
8314
8406
  "components/core/atoms/Switch.tsx"() {
8315
8407
  "use client";
8316
8408
  init_cn();
8317
- Switch = React91.forwardRef(
8409
+ Switch = React92.forwardRef(
8318
8410
  ({
8319
8411
  checked,
8320
8412
  defaultChecked = false,
@@ -8325,10 +8417,10 @@ var init_Switch = __esm({
8325
8417
  name,
8326
8418
  className
8327
8419
  }, ref) => {
8328
- const [isChecked, setIsChecked] = React91.useState(
8420
+ const [isChecked, setIsChecked] = React92.useState(
8329
8421
  checked !== void 0 ? checked : defaultChecked
8330
8422
  );
8331
- React91.useEffect(() => {
8423
+ React92.useEffect(() => {
8332
8424
  if (checked !== void 0) {
8333
8425
  setIsChecked(checked);
8334
8426
  }
@@ -8606,7 +8698,7 @@ var Aside;
8606
8698
  var init_Aside = __esm({
8607
8699
  "components/core/atoms/Aside.tsx"() {
8608
8700
  init_cn();
8609
- Aside = React91__default.forwardRef(
8701
+ Aside = React92__default.forwardRef(
8610
8702
  ({ className, children, ...rest }, ref) => /* @__PURE__ */ jsx("aside", { ref, className: cn(className), ...rest, children })
8611
8703
  );
8612
8704
  Aside.displayName = "Aside";
@@ -8685,9 +8777,9 @@ var init_LawReferenceTooltip = __esm({
8685
8777
  className
8686
8778
  }) => {
8687
8779
  const { t } = useTranslate();
8688
- const [isVisible, setIsVisible] = React91__default.useState(false);
8689
- const timeoutRef = React91__default.useRef(null);
8690
- const triggerRef = React91__default.useRef(null);
8780
+ const [isVisible, setIsVisible] = React92__default.useState(false);
8781
+ const timeoutRef = React92__default.useRef(null);
8782
+ const triggerRef = React92__default.useRef(null);
8691
8783
  const handleMouseEnter = () => {
8692
8784
  if (timeoutRef.current) clearTimeout(timeoutRef.current);
8693
8785
  timeoutRef.current = setTimeout(() => setIsVisible(true), 200);
@@ -8698,7 +8790,7 @@ var init_LawReferenceTooltip = __esm({
8698
8790
  };
8699
8791
  const { revealed, triggerProps } = useTapReveal({ refs: [triggerRef] });
8700
8792
  const open = isVisible || revealed;
8701
- React91__default.useEffect(() => {
8793
+ React92__default.useEffect(() => {
8702
8794
  return () => {
8703
8795
  if (timeoutRef.current) clearTimeout(timeoutRef.current);
8704
8796
  };
@@ -8908,7 +9000,7 @@ var init_StatusDot = __esm({
8908
9000
  md: "w-2.5 h-2.5",
8909
9001
  lg: "w-3 h-3"
8910
9002
  };
8911
- StatusDot = React91__default.forwardRef(
9003
+ StatusDot = React92__default.forwardRef(
8912
9004
  ({ className, status = "offline", pulse = false, size = "md", label, ...props }, ref) => {
8913
9005
  return /* @__PURE__ */ jsx(
8914
9006
  "span",
@@ -8962,7 +9054,7 @@ var init_TrendIndicator = __esm({
8962
9054
  down: "trending-down",
8963
9055
  flat: "arrow-right"
8964
9056
  };
8965
- TrendIndicator = React91__default.forwardRef(
9057
+ TrendIndicator = React92__default.forwardRef(
8966
9058
  ({
8967
9059
  className,
8968
9060
  value,
@@ -9031,7 +9123,7 @@ var init_RangeSlider = __esm({
9031
9123
  md: "w-4 h-4",
9032
9124
  lg: "w-5 h-5"
9033
9125
  };
9034
- RangeSlider = React91__default.forwardRef(
9126
+ RangeSlider = React92__default.forwardRef(
9035
9127
  ({
9036
9128
  className,
9037
9129
  min = 0,
@@ -9642,7 +9734,7 @@ var init_ContentSection = __esm({
9642
9734
  md: "py-16",
9643
9735
  lg: "py-24"
9644
9736
  };
9645
- ContentSection = React91__default.forwardRef(
9737
+ ContentSection = React92__default.forwardRef(
9646
9738
  ({ children, background = "default", padding = "lg", id, className }, ref) => {
9647
9739
  return /* @__PURE__ */ jsx(
9648
9740
  Box,
@@ -10176,7 +10268,7 @@ var init_AnimatedReveal = __esm({
10176
10268
  "scale-up": { opacity: 1, transform: "scale(1) translateY(0)" },
10177
10269
  "none": {}
10178
10270
  };
10179
- AnimatedReveal = React91__default.forwardRef(
10271
+ AnimatedReveal = React92__default.forwardRef(
10180
10272
  ({
10181
10273
  trigger = "scroll",
10182
10274
  animation = "fade-up",
@@ -10336,7 +10428,7 @@ var init_AnimatedGraphic = __esm({
10336
10428
  "components/marketing/atoms/AnimatedGraphic.tsx"() {
10337
10429
  "use client";
10338
10430
  init_cn();
10339
- AnimatedGraphic = React91__default.forwardRef(
10431
+ AnimatedGraphic = React92__default.forwardRef(
10340
10432
  ({
10341
10433
  src,
10342
10434
  svgContent,
@@ -10359,7 +10451,7 @@ var init_AnimatedGraphic = __esm({
10359
10451
  const fetchedSvg = useFetchedSvg(svgContent ? void 0 : src);
10360
10452
  const resolvedSvg = svgContent ?? fetchedSvg;
10361
10453
  const prevAnimateRef = useRef(animate);
10362
- const setRef = React91__default.useCallback(
10454
+ const setRef = React92__default.useCallback(
10363
10455
  (node) => {
10364
10456
  containerRef.current = node;
10365
10457
  if (typeof ref === "function") ref(node);
@@ -10826,46 +10918,45 @@ var init_useImageCache = __esm({
10826
10918
  });
10827
10919
 
10828
10920
  // lib/isometric.ts
10829
- function isoToScreen(tileX, tileY, scale, baseOffsetX, layout = "isometric") {
10830
- const scaledTileWidth = TILE_WIDTH * scale;
10831
- const scaledFloorHeight = FLOOR_HEIGHT * scale;
10921
+ function isoToScreen(tileX, tileY, cellWidth, baseOffsetX, layout = "isometric") {
10922
+ const w = cellWidth;
10923
+ const fh = cellWidth / 2;
10832
10924
  if (layout === "hex") {
10833
- const screenX2 = tileX * scaledTileWidth + (tileY & 1) * (scaledTileWidth / 2) + baseOffsetX;
10834
- const screenY2 = tileY * (scaledFloorHeight * 0.75);
10925
+ const screenX2 = tileX * w + (tileY & 1) * (w / 2) + baseOffsetX;
10926
+ const screenY2 = tileY * (fh * 0.75);
10835
10927
  return { x: screenX2, y: screenY2 };
10836
10928
  }
10837
10929
  if (layout === "flat") {
10838
- const screenX2 = tileX * scaledTileWidth + baseOffsetX;
10839
- const screenY2 = tileY * scaledTileWidth;
10930
+ const screenX2 = tileX * w + baseOffsetX;
10931
+ const screenY2 = tileY * w;
10840
10932
  return { x: screenX2, y: screenY2 };
10841
10933
  }
10842
- const screenX = (tileX - tileY) * (scaledTileWidth / 2) + baseOffsetX;
10843
- const screenY = (tileX + tileY) * (scaledFloorHeight / 2);
10934
+ const screenX = (tileX - tileY) * (w / 2) + baseOffsetX;
10935
+ const screenY = (tileX + tileY) * (fh / 2);
10844
10936
  return { x: screenX, y: screenY };
10845
10937
  }
10846
- function screenToIso(screenX, screenY, scale, baseOffsetX, layout = "isometric") {
10847
- const scaledTileWidth = TILE_WIDTH * scale;
10848
- const scaledFloorHeight = FLOOR_HEIGHT * scale;
10938
+ function screenToIso(screenX, screenY, cellWidth, baseOffsetX, layout = "isometric") {
10939
+ const w = cellWidth;
10940
+ const fh = cellWidth / 2;
10849
10941
  if (layout === "hex") {
10850
- const row = Math.round(screenY / (scaledFloorHeight * 0.75));
10851
- const col = Math.round((screenX - (row & 1) * (scaledTileWidth / 2) - baseOffsetX) / scaledTileWidth);
10942
+ const row = Math.round(screenY / (fh * 0.75));
10943
+ const col = Math.round((screenX - (row & 1) * (w / 2) - baseOffsetX) / w);
10852
10944
  return { x: col, y: row };
10853
10945
  }
10854
10946
  if (layout === "flat") {
10855
- const col = Math.round((screenX - baseOffsetX) / scaledTileWidth);
10856
- const row = Math.round(screenY / scaledTileWidth);
10947
+ const col = Math.round((screenX - baseOffsetX) / w);
10948
+ const row = Math.round(screenY / w);
10857
10949
  return { x: col, y: row };
10858
10950
  }
10859
10951
  const adjustedX = screenX - baseOffsetX;
10860
- const tileX = (adjustedX / (scaledTileWidth / 2) + screenY / (scaledFloorHeight / 2)) / 2;
10861
- const tileY = (screenY / (scaledFloorHeight / 2) - adjustedX / (scaledTileWidth / 2)) / 2;
10952
+ const tileX = (adjustedX / (w / 2) + screenY / (fh / 2)) / 2;
10953
+ const tileY = (screenY / (fh / 2) - adjustedX / (w / 2)) / 2;
10862
10954
  return { x: Math.round(tileX), y: Math.round(tileY) };
10863
10955
  }
10864
- var TILE_WIDTH, FLOOR_HEIGHT, DIAMOND_TOP_Y, BACKGROUND_FALLBACK_COLOR, MINIMAP_TERRAIN_COLORS;
10956
+ var TILE_WIDTH, DIAMOND_TOP_Y, BACKGROUND_FALLBACK_COLOR, MINIMAP_TERRAIN_COLORS;
10865
10957
  var init_isometric = __esm({
10866
10958
  "lib/isometric.ts"() {
10867
10959
  TILE_WIDTH = 256;
10868
- FLOOR_HEIGHT = 128;
10869
10960
  DIAMOND_TOP_Y = 374;
10870
10961
  BACKGROUND_FALLBACK_COLOR = "#1a1a2e";
10871
10962
  MINIMAP_TERRAIN_COLORS = {
@@ -11087,9 +11178,9 @@ function ControlButton({
11087
11178
  className
11088
11179
  }) {
11089
11180
  const eventBus = useEventBus();
11090
- const [isPressed, setIsPressed] = React91.useState(false);
11181
+ const [isPressed, setIsPressed] = React92.useState(false);
11091
11182
  const actualPressed = pressed ?? isPressed;
11092
- const handlePointerDown = React91.useCallback(
11183
+ const handlePointerDown = React92.useCallback(
11093
11184
  (e) => {
11094
11185
  e.preventDefault();
11095
11186
  if (disabled) return;
@@ -11099,7 +11190,7 @@ function ControlButton({
11099
11190
  },
11100
11191
  [disabled, pressEvent, eventBus, onPress]
11101
11192
  );
11102
- const handlePointerUp = React91.useCallback(
11193
+ const handlePointerUp = React92.useCallback(
11103
11194
  (e) => {
11104
11195
  e.preventDefault();
11105
11196
  if (disabled) return;
@@ -11109,7 +11200,7 @@ function ControlButton({
11109
11200
  },
11110
11201
  [disabled, releaseEvent, eventBus, onRelease]
11111
11202
  );
11112
- const handlePointerLeave = React91.useCallback(
11203
+ const handlePointerLeave = React92.useCallback(
11113
11204
  (e) => {
11114
11205
  if (isPressed) {
11115
11206
  setIsPressed(false);
@@ -11367,8 +11458,8 @@ function ControlGrid({
11367
11458
  className
11368
11459
  }) {
11369
11460
  const eventBus = useEventBus();
11370
- const [active, setActive] = React91.useState(/* @__PURE__ */ new Set());
11371
- const handlePress = React91.useCallback(
11461
+ const [active, setActive] = React92.useState(/* @__PURE__ */ new Set());
11462
+ const handlePress = React92.useCallback(
11372
11463
  (id) => {
11373
11464
  setActive((prev) => new Set(prev).add(id));
11374
11465
  if (actionEvent) eventBus.emit(`UI:${actionEvent}`, { id, pressed: true });
@@ -11382,7 +11473,7 @@ function ControlGrid({
11382
11473
  },
11383
11474
  [kind, actionEvent, directionEvent, directionEvents, eventBus, onAction, onDirection]
11384
11475
  );
11385
- const handleRelease = React91.useCallback(
11476
+ const handleRelease = React92.useCallback(
11386
11477
  (id) => {
11387
11478
  setActive((prev) => {
11388
11479
  const next = new Set(prev);
@@ -11740,7 +11831,7 @@ function GameMenu({
11740
11831
  }) {
11741
11832
  const resolvedOptions = (options?.length ? options : void 0) ?? (menuItems?.length ? menuItems : void 0) ?? DEFAULT_MENU_OPTIONS;
11742
11833
  const eventBus = useEventBus();
11743
- const handleOptionClick = React91.useCallback(
11834
+ const handleOptionClick = React92.useCallback(
11744
11835
  (option) => {
11745
11836
  if (option.event) {
11746
11837
  eventBus.emit(`UI:${option.event}`, { option });
@@ -11976,7 +12067,7 @@ function StateGraph({
11976
12067
  }) {
11977
12068
  const eventBus = useEventBus();
11978
12069
  const nodes = states ?? [];
11979
- const positions = React91.useMemo(() => layoutStates(nodes, width, height), [nodes, width, height]);
12070
+ const positions = React92.useMemo(() => layoutStates(nodes, width, height), [nodes, width, height]);
11980
12071
  return /* @__PURE__ */ jsxs(
11981
12072
  Box,
11982
12073
  {
@@ -12047,12 +12138,13 @@ function MiniMap({
12047
12138
  tileAssets,
12048
12139
  unitAssets
12049
12140
  }) {
12050
- const canvasRef = React91.useRef(null);
12051
- const imgCacheRef = React91.useRef(/* @__PURE__ */ new Map());
12141
+ const canvasRef = React92.useRef(null);
12142
+ const imgCacheRef = React92.useRef(/* @__PURE__ */ new Map());
12052
12143
  function loadImg(url) {
12053
12144
  const cached = imgCacheRef.current.get(url);
12054
12145
  if (cached) return cached.complete ? cached : null;
12055
12146
  const img = new Image();
12147
+ img.crossOrigin = "anonymous";
12056
12148
  img.src = url;
12057
12149
  img.onload = () => {
12058
12150
  const canvas = canvasRef.current;
@@ -12063,7 +12155,7 @@ function MiniMap({
12063
12155
  imgCacheRef.current.set(url, img);
12064
12156
  return null;
12065
12157
  }
12066
- React91.useEffect(() => {
12158
+ React92.useEffect(() => {
12067
12159
  const canvas = canvasRef.current;
12068
12160
  if (!canvas) return;
12069
12161
  const ctx = canvas.getContext("2d");
@@ -12220,7 +12312,7 @@ function useCamera(initial) {
12220
12312
  const handleWheel = useCallback((e, drawFn) => {
12221
12313
  e.preventDefault();
12222
12314
  const zoomDelta = e.deltaY > 0 ? 0.9 : 1.1;
12223
- cameraRef.current.zoom = Math.max(0.5, Math.min(3, cameraRef.current.zoom * zoomDelta));
12315
+ cameraRef.current.zoom = Math.max(MIN_ZOOM, Math.min(MAX_ZOOM, cameraRef.current.zoom * zoomDelta));
12224
12316
  drawFn?.();
12225
12317
  }, []);
12226
12318
  const handlePointerDown = useCallback((e) => {
@@ -12241,7 +12333,7 @@ function useCamera(initial) {
12241
12333
  const zoomAtPoint = useCallback((factor, centerX, centerY, viewportSize, drawFn) => {
12242
12334
  const cam = cameraRef.current;
12243
12335
  const oldZoom = cam.zoom;
12244
- const newZoom = Math.max(0.5, Math.min(3, oldZoom * factor));
12336
+ const newZoom = Math.max(MIN_ZOOM, Math.min(MAX_ZOOM, oldZoom * factor));
12245
12337
  if (newZoom === oldZoom) {
12246
12338
  drawFn?.();
12247
12339
  return;
@@ -12293,9 +12385,12 @@ function useCamera(initial) {
12293
12385
  lerpToTarget
12294
12386
  };
12295
12387
  }
12388
+ var MIN_ZOOM, MAX_ZOOM;
12296
12389
  var init_useCamera = __esm({
12297
12390
  "hooks/useCamera.ts"() {
12298
12391
  "use client";
12392
+ MIN_ZOOM = 0.05;
12393
+ MAX_ZOOM = 10;
12299
12394
  }
12300
12395
  });
12301
12396
  function localPoint(canvas, clientX, clientY) {
@@ -12416,6 +12511,7 @@ function getOrLoadImage(url, onReady) {
12416
12511
  return null;
12417
12512
  }
12418
12513
  const img = new Image();
12514
+ img.crossOrigin = "anonymous";
12419
12515
  const entry = { img, status: "pending", onReady };
12420
12516
  cache.set(url, entry);
12421
12517
  updateAssetStatus(url, "pending");
@@ -12427,10 +12523,14 @@ function getOrLoadImage(url, onReady) {
12427
12523
  img.onerror = () => {
12428
12524
  entry.status = "failed";
12429
12525
  updateAssetStatus(url, "failed");
12526
+ entry.onReady?.();
12430
12527
  };
12431
12528
  img.src = url;
12432
12529
  return null;
12433
12530
  }
12531
+ function getImageStatus(url) {
12532
+ return cache.get(url)?.status;
12533
+ }
12434
12534
  var cache;
12435
12535
  var init_imageCache = __esm({
12436
12536
  "lib/imageCache.ts"() {
@@ -12569,12 +12669,13 @@ var init_webPainter2d = __esm({
12569
12669
 
12570
12670
  // lib/drawable/projector.ts
12571
12671
  function create2DProjector(opts) {
12572
- const { scale, baseOffsetX, layout } = opts;
12573
- const tileWidth = layout === "free" ? 1 : TILE_WIDTH * scale;
12574
- const floorHeight = layout === "free" ? 1 : FLOOR_HEIGHT * scale;
12575
- const diamondTopY = layout === "free" ? 0 : (opts.diamondTopY ?? DIAMOND_TOP_Y) * scale;
12672
+ const { baseOffsetX, layout } = opts;
12673
+ const tw = opts.tileWidth ?? TILE_WIDTH;
12674
+ const tileWidth = layout === "free" ? 1 : tw;
12675
+ const floorHeight = layout === "free" ? 1 : tw / 2;
12676
+ const diamondTopY = layout === "free" ? 0 : opts.diamondTopY ?? tw * (DIAMOND_TOP_Y / TILE_WIDTH);
12576
12677
  const squareGrid = layout === "flat" || layout === "free";
12577
- const project = (pos) => layout === "free" ? { x: pos.x, y: pos.y } : isoToScreen(pos.x, pos.y, scale, baseOffsetX, layout);
12678
+ const project = (pos) => layout === "free" ? { x: pos.x, y: pos.y } : isoToScreen(pos.x, pos.y, tw, baseOffsetX, layout);
12578
12679
  const anchorPoint = (pos, anchor) => {
12579
12680
  const base = project(pos);
12580
12681
  if (anchor === "top-left") return base;
@@ -12605,7 +12706,7 @@ function create2DProjector(opts) {
12605
12706
  { x: base.x, y: topY + floorHeight / 2 }
12606
12707
  ];
12607
12708
  };
12608
- return { project, anchorPoint, cellPath, tileWidth, floorHeight, diamondTopY, scale, squareGrid };
12709
+ return { project, anchorPoint, cellPath, tileWidth, floorHeight, diamondTopY, squareGrid, worldPixelDirect: layout === "free" };
12609
12710
  }
12610
12711
  var init_projector = __esm({
12611
12712
  "lib/drawable/projector.ts"() {
@@ -12621,32 +12722,67 @@ var init_contract = __esm({
12621
12722
  "lib/drawable/contract.ts"() {
12622
12723
  }
12623
12724
  });
12624
-
12625
- // components/game/atoms/DrawSprite.tsx
12725
+ function warnMissingOnce(reason, node) {
12726
+ const key = `${reason}:${node.asset.url}:${String(node.asset.atlas)}:${String(node.asset.sprite)}`;
12727
+ if (loggedMissing.has(key)) return;
12728
+ loggedMissing.add(key);
12729
+ spriteLog.warn("draw-sprite asset unresolvable \u2014 painting fallback square", { reason, url: node.asset.url, atlas: node.asset.atlas, sprite: node.asset.sprite });
12730
+ }
12731
+ function paintFallbackSquare(painter, node, dctx, reason) {
12732
+ warnMissingOnce(reason, node);
12733
+ const tw = dctx.projector.tileWidth;
12734
+ const natural = dctx.projector.worldPixelDirect ? FALLBACK_WORLD_PX : tw;
12735
+ const w = node.width !== void 0 ? node.width * tw : natural;
12736
+ const h = node.height !== void 0 ? node.height * tw : natural;
12737
+ const anchor = node.anchor ?? "top-left";
12738
+ const p = dctx.projector.anchorPoint(node.position, anchor);
12739
+ const dx = anchor === "top-left" ? p.x : p.x - w / 2;
12740
+ const dy = anchor === "ground" ? p.y - h : anchor === "center" ? p.y - h / 2 : p.y;
12741
+ painter.save();
12742
+ if (node.opacity !== void 0 && node.opacity !== 1) painter.setAlpha(node.opacity);
12743
+ painter.fillRect(dx, dy, w, h, "#9b8f7f");
12744
+ painter.strokeRect(dx, dy, w, h, "#5e564b", Math.max(1, tw / 32));
12745
+ painter.restore();
12746
+ }
12626
12747
  function DrawSprite(_props) {
12627
12748
  return null;
12628
12749
  }
12629
- var paintSprite;
12750
+ var spriteLog, loggedMissing, FALLBACK_WORLD_PX, paintSprite;
12630
12751
  var init_DrawSprite = __esm({
12631
12752
  "components/game/atoms/DrawSprite.tsx"() {
12632
12753
  "use client";
12633
12754
  init_atlasSlice();
12755
+ init_imageCache();
12634
12756
  init_contract();
12757
+ spriteLog = createLogger("almadar:ui:draw-sprite");
12758
+ loggedMissing = /* @__PURE__ */ new Set();
12759
+ FALLBACK_WORLD_PX = 32;
12635
12760
  paintSprite = (painter, node, dctx) => {
12636
12761
  if (!node.asset?.url || !isValidScenePos(node.position)) return;
12637
12762
  const tex = painter.resolveTexture(node.asset.url);
12638
- if (!tex) return;
12763
+ if (!tex) {
12764
+ if (getImageStatus(node.asset.url) === "failed") paintFallbackSquare(painter, node, dctx, "texture-failed");
12765
+ return;
12766
+ }
12639
12767
  let src = typeof node.frame === "object" ? node.frame : void 0;
12640
12768
  if (!src && isAtlasAsset(node.asset)) {
12641
12769
  const atlas = getAtlas(node.asset.atlas, dctx.invalidate);
12642
- if (!atlas) return;
12770
+ if (!atlas) {
12771
+ if (atlasFailed(node.asset.atlas)) paintFallbackSquare(painter, node, dctx, "atlas-failed");
12772
+ return;
12773
+ }
12643
12774
  const r2 = subRectFor(atlas, node.asset.sprite);
12644
- if (!r2) return;
12775
+ if (!r2) {
12776
+ paintFallbackSquare(painter, node, dctx, "sprite-missing");
12777
+ return;
12778
+ }
12645
12779
  src = { x: r2.sx, y: r2.sy, w: r2.sw, h: r2.sh };
12646
12780
  }
12647
12781
  const tw = dctx.projector.tileWidth;
12648
- const w = node.width !== void 0 ? node.width * tw : src ? src.w : tex.width;
12649
- const h = node.height !== void 0 ? node.height * tw : src ? src.h : tex.height;
12782
+ const fallbackW = dctx.projector.worldPixelDirect ? src ? src.w : tex.width : tw;
12783
+ const fallbackH = dctx.projector.worldPixelDirect ? src ? src.h : tex.height : tw;
12784
+ const w = node.width !== void 0 ? node.width * tw : fallbackW;
12785
+ const h = node.height !== void 0 ? node.height * tw : fallbackH;
12650
12786
  const anchor = node.anchor ?? "top-left";
12651
12787
  const p = dctx.projector.anchorPoint(node.position, anchor);
12652
12788
  const dx = anchor === "top-left" ? p.x : p.x - w / 2;
@@ -12912,6 +13048,8 @@ function Canvas2D({
12912
13048
  keyUpMap,
12913
13049
  camera = "pan-zoom",
12914
13050
  scale = 0.4,
13051
+ tileWidth,
13052
+ fit = false,
12915
13053
  showMinimap = true,
12916
13054
  followTarget,
12917
13055
  cameraPos,
@@ -12954,9 +13092,32 @@ function Canvas2D({
12954
13092
  observer2.observe(el);
12955
13093
  return () => observer2.disconnect();
12956
13094
  }, []);
12957
- const scaledTileWidth = TILE_WIDTH * scale;
12958
- const scaledFloorHeight = FLOOR_HEIGHT * scale;
12959
- const scaledDiamondTopY = DIAMOND_TOP_Y * scale;
13095
+ const [atlasVersion, setAtlasVersion] = useState(0);
13096
+ const bumpAtlas = useCallback(() => setAtlasVersion((v) => v + 1), []);
13097
+ const detectedTileWidth = useMemo(() => {
13098
+ for (const n of drawables ?? []) {
13099
+ const refs = [];
13100
+ if (n.type === "draw-sprite") refs.push(n.asset);
13101
+ else if (n.type === "draw-sprite-layer") for (const it of n.items) refs.push(it.asset);
13102
+ for (const a of refs) {
13103
+ if (a && isAtlasAsset(a) && a.atlas) {
13104
+ const atlas = getAtlas(a.atlas, bumpAtlas);
13105
+ if (atlas) {
13106
+ if ("tileWidth" in atlas) return atlas.tileWidth;
13107
+ if ("subTextures" in atlas) {
13108
+ const first = Object.values(atlas.subTextures)[0];
13109
+ if (first && typeof first.width === "number") return first.width;
13110
+ }
13111
+ }
13112
+ }
13113
+ }
13114
+ }
13115
+ return void 0;
13116
+ }, [drawables, atlasVersion]);
13117
+ const nativeTileW = tileWidth ?? detectedTileWidth ?? TILE_WIDTH;
13118
+ const scaledTileWidth = nativeTileW;
13119
+ const scaledFloorHeight = nativeTileW / 2;
13120
+ const scaledDiamondTopY = nativeTileW * (DIAMOND_TOP_Y / TILE_WIDTH);
12960
13121
  const drawnItems = useMemo(() => collectDrawnItems(drawables ?? []), [drawables]);
12961
13122
  const scenePositions = useMemo(() => drawnItems.map((i) => i.pos), [drawnItems]);
12962
13123
  const hitIndex = useMemo(() => buildHitIndex(drawnItems), [drawnItems]);
@@ -12974,14 +13135,36 @@ function Canvas2D({
12974
13135
  if (isFree || projection === "flat" || projection === "side") return 0;
12975
13136
  return (gridExtent.height - 1) * (scaledTileWidth / 2);
12976
13137
  }, [isFree, projection, gridExtent.height, scaledTileWidth]);
13138
+ const effectiveZoom = useMemo(() => {
13139
+ if (isFree || projection === "side") return scale;
13140
+ if (!fit) {
13141
+ const z2 = TILE_WIDTH * scale * scale / nativeTileW;
13142
+ return Number.isFinite(z2) && z2 > 0 ? z2 : scale;
13143
+ }
13144
+ if (!viewportSize.width || gridExtent.width < 2 || gridExtent.height < 2) return scale;
13145
+ let boardW;
13146
+ let boardH;
13147
+ if (projection === "flat") {
13148
+ boardW = gridExtent.width * nativeTileW;
13149
+ boardH = gridExtent.height * nativeTileW;
13150
+ } else if (projection === "hex") {
13151
+ boardW = (gridExtent.width + 0.5) * nativeTileW;
13152
+ boardH = gridExtent.height * (nativeTileW / 2) * 0.75 + nativeTileW / 2;
13153
+ } else {
13154
+ boardW = (gridExtent.width + gridExtent.height) * (nativeTileW / 2);
13155
+ boardH = (gridExtent.width + gridExtent.height) * (nativeTileW / 4);
13156
+ }
13157
+ const z = Math.min(viewportSize.width * 0.85 / boardW, viewportSize.height * 0.85 / boardH);
13158
+ return Number.isFinite(z) && z > 0 ? z : scale;
13159
+ }, [isFree, projection, fit, viewportSize, gridExtent, nativeTileW, scale]);
12977
13160
  const projector = useMemo(
12978
- () => create2DProjector({ scale, baseOffsetX, layout }),
12979
- [scale, baseOffsetX, layout]
13161
+ () => create2DProjector({ tileWidth: nativeTileW, baseOffsetX, layout }),
13162
+ [nativeTileW, baseOffsetX, layout]
12980
13163
  );
12981
13164
  const unproject = useCallback((screenX, screenY) => {
12982
13165
  if (projection === "free" || projection === "side") return { x: Math.round(screenX), y: Math.round(screenY) };
12983
- return screenToIso(screenX, screenY, scale, baseOffsetX, projection);
12984
- }, [projection, scale, baseOffsetX]);
13166
+ return screenToIso(screenX, screenY, nativeTileW, baseOffsetX, projection);
13167
+ }, [projection, nativeTileW, baseOffsetX]);
12985
13168
  const bgUrls = useMemo(() => backgroundImage ? [backgroundImage.url] : [], [backgroundImage]);
12986
13169
  const { getImage, pendingCount: _imagePendingCount } = useImageCache(bgUrls);
12987
13170
  useEffect(() => {
@@ -13008,9 +13191,7 @@ function Canvas2D({
13008
13191
  zoomAtPoint,
13009
13192
  screenToWorld,
13010
13193
  lerpToTarget
13011
- } = useCamera({ zoom: scale });
13012
- const [atlasVersion, setAtlasVersion] = useState(0);
13013
- const bumpAtlas = useCallback(() => setAtlasVersion((v) => v + 1), []);
13194
+ } = useCamera({ zoom: effectiveZoom });
13014
13195
  const miniMapTiles = useMemo(() => {
13015
13196
  if (!showMinimap) return [];
13016
13197
  const color = MINIMAP_TERRAIN_COLORS.default;
@@ -13085,6 +13266,13 @@ function Canvas2D({
13085
13266
  useEffect(() => {
13086
13267
  draw();
13087
13268
  }, [_imagePendingCount, draw]);
13269
+ const userZoomedRef = useRef(false);
13270
+ useEffect(() => {
13271
+ if (userZoomedRef.current) return;
13272
+ if (cameraRef.current.zoom === effectiveZoom) return;
13273
+ cameraRef.current.zoom = effectiveZoom;
13274
+ draw();
13275
+ }, [effectiveZoom, cameraRef, draw]);
13088
13276
  useEffect(() => {
13089
13277
  draw();
13090
13278
  }, [atlasVersion, draw]);
@@ -13141,7 +13329,9 @@ function Canvas2D({
13141
13329
  if (tileLeaveEvent) eventBus.emit(`UI:${tileLeaveEvent}`, {});
13142
13330
  }, [handleMouseLeave, tileLeaveEvent, eventBus]);
13143
13331
  const applyZoom = useCallback((factor, centerX, centerY) => {
13144
- if (enableCamera) zoomAtPoint(factor, centerX, centerY, viewportSize, () => draw());
13332
+ if (!enableCamera) return;
13333
+ userZoomedRef.current = true;
13334
+ zoomAtPoint(factor, centerX, centerY, viewportSize, () => draw());
13145
13335
  }, [enableCamera, zoomAtPoint, viewportSize, draw]);
13146
13336
  const applyPanDelta = useCallback((dx, dy) => {
13147
13337
  if (enableCamera) panBy(dx, dy, () => draw());
@@ -13326,6 +13516,8 @@ function Canvas({
13326
13516
  isLoading,
13327
13517
  unitScale,
13328
13518
  showMinimap,
13519
+ fit,
13520
+ tileWidth,
13329
13521
  backgroundImage,
13330
13522
  backgroundColor,
13331
13523
  worldWidth,
@@ -13383,6 +13575,8 @@ function Canvas({
13383
13575
  projection,
13384
13576
  camera: to2DCamera(camera?.mode),
13385
13577
  ...zoom !== void 0 ? { scale: zoom } : {},
13578
+ ...fit !== void 0 ? { fit } : {},
13579
+ ...tileWidth !== void 0 ? { tileWidth } : {},
13386
13580
  ...camera?.target !== void 0 ? { followTarget: camera.target } : {},
13387
13581
  ...camera?.pos !== void 0 ? { cameraPos: camera.pos } : {},
13388
13582
  showMinimap,
@@ -13525,7 +13719,7 @@ function LinearView({
13525
13719
  /* @__PURE__ */ jsx(HStack, { className: "flex-wrap items-center", gap: "xs", children: trait.states.map((state, i) => {
13526
13720
  const isDone = i < currentIdx;
13527
13721
  const isCurrent = i === currentIdx;
13528
- return /* @__PURE__ */ jsxs(React91__default.Fragment, { children: [
13722
+ return /* @__PURE__ */ jsxs(React92__default.Fragment, { children: [
13529
13723
  i > 0 && /* @__PURE__ */ jsx(
13530
13724
  Typography,
13531
13725
  {
@@ -14060,7 +14254,7 @@ function SequenceBar({
14060
14254
  else onSlotRemove?.(index);
14061
14255
  }, [emit, slotRemoveEvent, onSlotRemove, playing]);
14062
14256
  const paddedSlots = Array.from({ length: maxSlots }, (_, i) => slots[i]);
14063
- return /* @__PURE__ */ jsx(HStack, { className: cn("items-center", className), gap: "sm", children: paddedSlots.map((slot, i) => /* @__PURE__ */ jsxs(React91__default.Fragment, { children: [
14257
+ return /* @__PURE__ */ jsx(HStack, { className: cn("items-center", className), gap: "sm", children: paddedSlots.map((slot, i) => /* @__PURE__ */ jsxs(React92__default.Fragment, { children: [
14064
14258
  i > 0 && /* @__PURE__ */ jsx(
14065
14259
  Typography,
14066
14260
  {
@@ -14709,7 +14903,7 @@ var init_ErrorBoundary = __esm({
14709
14903
  }
14710
14904
  );
14711
14905
  };
14712
- ErrorBoundary = class extends React91__default.Component {
14906
+ ErrorBoundary = class extends React92__default.Component {
14713
14907
  constructor(props) {
14714
14908
  super(props);
14715
14909
  __publicField(this, "reset", () => {
@@ -14978,7 +15172,7 @@ var init_Container = __esm({
14978
15172
  as: Component = "div"
14979
15173
  }) => {
14980
15174
  const resolvedSize = maxWidth ?? size ?? "lg";
14981
- return React91__default.createElement(
15175
+ return React92__default.createElement(
14982
15176
  Component,
14983
15177
  {
14984
15178
  className: cn(
@@ -17116,7 +17310,7 @@ var init_CodeBlock = __esm({
17116
17310
  DIFF_STYLE_FALLBACK = { bg: "", prefix: " ", text: "text-foreground" };
17117
17311
  LINE_PROPS_FN = (n) => ({ "data-line": String(n - 1) });
17118
17312
  HIDDEN_LINE_NUMBERS = { display: "none" };
17119
- CodeBlock = React91__default.memo(
17313
+ CodeBlock = React92__default.memo(
17120
17314
  ({
17121
17315
  code: rawCode,
17122
17316
  language = "text",
@@ -17704,7 +17898,7 @@ var init_MarkdownContent = __esm({
17704
17898
  init_Box();
17705
17899
  init_CodeBlock();
17706
17900
  init_cn();
17707
- MarkdownContent = React91__default.memo(
17901
+ MarkdownContent = React92__default.memo(
17708
17902
  ({ content, direction = "ltr", className }) => {
17709
17903
  const { t: _t } = useTranslate();
17710
17904
  const safeContent = typeof content === "string" ? content : String(content ?? "");
@@ -19031,7 +19225,7 @@ var init_StateMachineView = __esm({
19031
19225
  style: { top: title ? 30 : 0 },
19032
19226
  children: [
19033
19227
  entity && /* @__PURE__ */ jsx(EntityBox, { entity, config }),
19034
- states.map((state) => renderStateNode ? /* @__PURE__ */ jsx(React91__default.Fragment, { children: renderStateNode(state, config) }, state.id) : /* @__PURE__ */ jsx(
19228
+ states.map((state) => renderStateNode ? /* @__PURE__ */ jsx(React92__default.Fragment, { children: renderStateNode(state, config) }, state.id) : /* @__PURE__ */ jsx(
19035
19229
  StateNode2,
19036
19230
  {
19037
19231
  state,
@@ -24853,8 +25047,8 @@ var init_Menu = __esm({
24853
25047
  "bottom-end": "bottom-start"
24854
25048
  };
24855
25049
  const effectivePosition = direction === "rtl" ? rtlMirror[position] ?? position : position;
24856
- const triggerChild = React91__default.isValidElement(trigger) ? trigger : /* @__PURE__ */ jsx(Typography, { variant: "small", as: "span", children: trigger });
24857
- const triggerElement = React91__default.cloneElement(
25050
+ const triggerChild = React92__default.isValidElement(trigger) ? trigger : /* @__PURE__ */ jsx(Typography, { variant: "small", as: "span", children: trigger });
25051
+ const triggerElement = React92__default.cloneElement(
24858
25052
  triggerChild,
24859
25053
  {
24860
25054
  ref: triggerRef,
@@ -24949,14 +25143,14 @@ function useDataDnd(args) {
24949
25143
  const isZone = Boolean(dragGroup || accepts || sortable);
24950
25144
  const enabled = isZone || Boolean(dndRoot);
24951
25145
  const eventBus = useEventBus();
24952
- const parentRoot = React91__default.useContext(RootCtx);
25146
+ const parentRoot = React92__default.useContext(RootCtx);
24953
25147
  const isRoot = enabled && parentRoot === null;
24954
- const zoneId = React91__default.useId();
25148
+ const zoneId = React92__default.useId();
24955
25149
  const ownGroup = dragGroup ?? accepts ?? zoneId;
24956
- const [optimisticOrders, setOptimisticOrders] = React91__default.useState(() => /* @__PURE__ */ new Map());
24957
- const optimisticOrdersRef = React91__default.useRef(optimisticOrders);
25150
+ const [optimisticOrders, setOptimisticOrders] = React92__default.useState(() => /* @__PURE__ */ new Map());
25151
+ const optimisticOrdersRef = React92__default.useRef(optimisticOrders);
24958
25152
  optimisticOrdersRef.current = optimisticOrders;
24959
- const clearOptimisticOrder = React91__default.useCallback((group) => {
25153
+ const clearOptimisticOrder = React92__default.useCallback((group) => {
24960
25154
  setOptimisticOrders((prev) => {
24961
25155
  if (!prev.has(group)) return prev;
24962
25156
  const next = new Map(prev);
@@ -24981,7 +25175,7 @@ function useDataDnd(args) {
24981
25175
  const raw = it[dndItemIdField];
24982
25176
  return raw != null ? String(raw) : `__idx_${idx}`;
24983
25177
  }).join("|");
24984
- const itemIds = React91__default.useMemo(
25178
+ const itemIds = React92__default.useMemo(
24985
25179
  () => orderedItems.map((it, idx) => {
24986
25180
  const raw = it[dndItemIdField];
24987
25181
  return raw != null ? String(raw) : `__idx_${idx}`;
@@ -24992,7 +25186,7 @@ function useDataDnd(args) {
24992
25186
  const raw = it[dndItemIdField];
24993
25187
  return raw != null ? String(raw) : `__${idx}`;
24994
25188
  }).join("|");
24995
- React91__default.useEffect(() => {
25189
+ React92__default.useEffect(() => {
24996
25190
  const root = isRoot ? null : parentRoot;
24997
25191
  if (root) {
24998
25192
  root.clearOptimisticOrder(ownGroup);
@@ -25000,20 +25194,20 @@ function useDataDnd(args) {
25000
25194
  clearOptimisticOrder(ownGroup);
25001
25195
  }
25002
25196
  }, [itemsContentSig, ownGroup]);
25003
- const zonesRef = React91__default.useRef(/* @__PURE__ */ new Map());
25004
- const registerZone = React91__default.useCallback((zoneId2, meta2) => {
25197
+ const zonesRef = React92__default.useRef(/* @__PURE__ */ new Map());
25198
+ const registerZone = React92__default.useCallback((zoneId2, meta2) => {
25005
25199
  zonesRef.current.set(zoneId2, meta2);
25006
25200
  }, []);
25007
- const unregisterZone = React91__default.useCallback((zoneId2) => {
25201
+ const unregisterZone = React92__default.useCallback((zoneId2) => {
25008
25202
  zonesRef.current.delete(zoneId2);
25009
25203
  }, []);
25010
- const [activeDrag, setActiveDrag] = React91__default.useState(null);
25011
- const [overZoneGroup, setOverZoneGroup] = React91__default.useState(null);
25012
- const meta = React91__default.useMemo(
25204
+ const [activeDrag, setActiveDrag] = React92__default.useState(null);
25205
+ const [overZoneGroup, setOverZoneGroup] = React92__default.useState(null);
25206
+ const meta = React92__default.useMemo(
25013
25207
  () => ({ group: ownGroup, dropEvent, reorderEvent, positionEvent, itemIds, rawItems: items, idField: dndItemIdField }),
25014
25208
  [ownGroup, dropEvent, reorderEvent, positionEvent, itemIds, items, dndItemIdField]
25015
25209
  );
25016
- React91__default.useEffect(() => {
25210
+ React92__default.useEffect(() => {
25017
25211
  const target = isRoot ? null : parentRoot;
25018
25212
  if (!target) {
25019
25213
  zonesRef.current.set(zoneId, meta);
@@ -25032,7 +25226,7 @@ function useDataDnd(args) {
25032
25226
  }, [parentRoot, isRoot, zoneId, meta]);
25033
25227
  const sensors = useAlmadarDndSensors(true);
25034
25228
  const collisionDetection = almadarDndCollisionDetection;
25035
- const findZoneByItem = React91__default.useCallback(
25229
+ const findZoneByItem = React92__default.useCallback(
25036
25230
  (id) => {
25037
25231
  for (const z of zonesRef.current.values()) {
25038
25232
  if (z.itemIds.includes(id)) return z;
@@ -25041,7 +25235,7 @@ function useDataDnd(args) {
25041
25235
  },
25042
25236
  []
25043
25237
  );
25044
- React91__default.useCallback(
25238
+ React92__default.useCallback(
25045
25239
  (group) => {
25046
25240
  for (const z of zonesRef.current.values()) {
25047
25241
  if (z.group === group) return z;
@@ -25050,7 +25244,7 @@ function useDataDnd(args) {
25050
25244
  },
25051
25245
  []
25052
25246
  );
25053
- const handleDragEnd = React91__default.useCallback(
25247
+ const handleDragEnd = React92__default.useCallback(
25054
25248
  (event) => {
25055
25249
  const { active, over } = event;
25056
25250
  const activeIdStr = String(active.id);
@@ -25141,8 +25335,8 @@ function useDataDnd(args) {
25141
25335
  },
25142
25336
  [eventBus]
25143
25337
  );
25144
- const sortableData = React91__default.useMemo(() => ({ dndGroup: ownGroup }), [ownGroup]);
25145
- const SortableItem = React91__default.useCallback(
25338
+ const sortableData = React92__default.useMemo(() => ({ dndGroup: ownGroup }), [ownGroup]);
25339
+ const SortableItem = React92__default.useCallback(
25146
25340
  ({ id, children }) => {
25147
25341
  const {
25148
25342
  attributes,
@@ -25182,7 +25376,7 @@ function useDataDnd(args) {
25182
25376
  id: droppableId,
25183
25377
  data: sortableData
25184
25378
  });
25185
- const ctx = React91__default.useContext(RootCtx);
25379
+ const ctx = React92__default.useContext(RootCtx);
25186
25380
  const activeDrag2 = ctx?.activeDrag ?? null;
25187
25381
  const overZoneGroup2 = ctx?.overZoneGroup ?? null;
25188
25382
  const isThisZoneOver = overZoneGroup2 === ownGroup;
@@ -25197,7 +25391,7 @@ function useDataDnd(args) {
25197
25391
  showForeignPlaceholder,
25198
25392
  ctxAvailable: ctx != null
25199
25393
  });
25200
- React91__default.useEffect(() => {
25394
+ React92__default.useEffect(() => {
25201
25395
  dndLog.info("dropzone:isOver:change", { droppableId, group: ownGroup, isOver, isThisZoneOver, showForeignPlaceholder, activeDragSourceGroup: activeDrag2?.sourceGroup ?? null });
25202
25396
  }, [droppableId, isOver, isThisZoneOver, showForeignPlaceholder]);
25203
25397
  return /* @__PURE__ */ jsx(
@@ -25211,11 +25405,11 @@ function useDataDnd(args) {
25211
25405
  }
25212
25406
  );
25213
25407
  };
25214
- const rootContextValue = React91__default.useMemo(
25408
+ const rootContextValue = React92__default.useMemo(
25215
25409
  () => ({ registerZone, unregisterZone, activeDrag, overZoneGroup, optimisticOrders, clearOptimisticOrder }),
25216
25410
  [registerZone, unregisterZone, activeDrag, overZoneGroup, optimisticOrders, clearOptimisticOrder]
25217
25411
  );
25218
- const handleDragStart = React91__default.useCallback((event) => {
25412
+ const handleDragStart = React92__default.useCallback((event) => {
25219
25413
  const sourceZone = findZoneByItem(event.active.id);
25220
25414
  const rect = event.active.rect.current.initial;
25221
25415
  const height = rect?.height && rect.height > 0 ? rect.height : 64;
@@ -25234,7 +25428,7 @@ function useDataDnd(args) {
25234
25428
  isRoot
25235
25429
  });
25236
25430
  }, [findZoneByItem, isRoot, zoneId]);
25237
- const handleDragOver = React91__default.useCallback((event) => {
25431
+ const handleDragOver = React92__default.useCallback((event) => {
25238
25432
  const { active, over } = event;
25239
25433
  const overData = over?.data?.current;
25240
25434
  const overGroup = overData?.dndGroup ?? null;
@@ -25304,7 +25498,7 @@ function useDataDnd(args) {
25304
25498
  return next;
25305
25499
  });
25306
25500
  }, []);
25307
- const handleDragCancel = React91__default.useCallback((event) => {
25501
+ const handleDragCancel = React92__default.useCallback((event) => {
25308
25502
  setActiveDrag(null);
25309
25503
  setOverZoneGroup(null);
25310
25504
  dndLog.warn("dragCancel", {
@@ -25312,12 +25506,12 @@ function useDataDnd(args) {
25312
25506
  reason: "dnd-kit cancelled the drag (escape key, pointer interrupted, or external)"
25313
25507
  });
25314
25508
  }, []);
25315
- const handleDragEndWithCleanup = React91__default.useCallback((event) => {
25509
+ const handleDragEndWithCleanup = React92__default.useCallback((event) => {
25316
25510
  handleDragEnd(event);
25317
25511
  setActiveDrag(null);
25318
25512
  setOverZoneGroup(null);
25319
25513
  }, [handleDragEnd]);
25320
- const wrapContainer = React91__default.useCallback(
25514
+ const wrapContainer = React92__default.useCallback(
25321
25515
  (children) => {
25322
25516
  if (!enabled) return children;
25323
25517
  const strategy = layout === "grid" ? rectSortingStrategy : verticalListSortingStrategy;
@@ -25371,7 +25565,7 @@ var init_useDataDnd = __esm({
25371
25565
  init_useAlmadarDndCollision();
25372
25566
  init_Box();
25373
25567
  dndLog = createLogger("almadar:ui:dnd");
25374
- RootCtx = React91__default.createContext(null);
25568
+ RootCtx = React92__default.createContext(null);
25375
25569
  }
25376
25570
  });
25377
25571
  function renderIconInput(icon, props) {
@@ -25913,7 +26107,7 @@ function DataList({
25913
26107
  }) {
25914
26108
  const eventBus = useEventBus();
25915
26109
  const { t } = useTranslate();
25916
- const [visibleCount, setVisibleCount] = React91__default.useState(pageSize || Infinity);
26110
+ const [visibleCount, setVisibleCount] = React92__default.useState(pageSize || Infinity);
25917
26111
  const fieldDefs = fields ?? columns ?? [];
25918
26112
  const allDataRaw = Array.isArray(entity) ? entity : entity ? [entity] : [];
25919
26113
  const dnd = useDataDnd({
@@ -25929,14 +26123,14 @@ function DataList({
25929
26123
  dndRoot
25930
26124
  });
25931
26125
  const orderedData = dnd.orderedItems;
25932
- const allData = React91__default.useMemo(
26126
+ const allData = React92__default.useMemo(
25933
26127
  () => sortRows(orderedData, sortBy, sortDirection),
25934
26128
  [orderedData, sortBy, sortDirection]
25935
26129
  );
25936
26130
  const data = pageSize > 0 ? allData.slice(0, visibleCount) : allData;
25937
26131
  const hasMoreLocal = pageSize > 0 && visibleCount < allData.length;
25938
26132
  const hasRenderProp = typeof children === "function";
25939
- React91__default.useEffect(() => {
26133
+ React92__default.useEffect(() => {
25940
26134
  const renderItemTypeOf = typeof schemaRenderItem;
25941
26135
  const childrenTypeOf = typeof children;
25942
26136
  if (data.length > 0 && !hasRenderProp) {
@@ -26051,7 +26245,7 @@ function DataList({
26051
26245
  return v === void 0 || v === null || v === "" ? raw : String(v);
26052
26246
  };
26053
26247
  return /* @__PURE__ */ jsxs(VStack, { gap: "sm", className: cn("py-2", className), children: [
26054
- groups2.map((group, gi) => /* @__PURE__ */ jsxs(React91__default.Fragment, { children: [
26248
+ groups2.map((group, gi) => /* @__PURE__ */ jsxs(React92__default.Fragment, { children: [
26055
26249
  group.label && /* @__PURE__ */ jsx(Divider, { label: group.label, className: "my-2" }),
26056
26250
  group.items.map((itemData, index) => {
26057
26251
  const id = itemData.id || `${gi}-${index}`;
@@ -26087,7 +26281,11 @@ function DataList({
26087
26281
  metaFields.length > 0 && /* @__PURE__ */ jsx(HStack, { gap: "xs", className: "mt-1 flex-wrap", children: metaFields.map((f3) => {
26088
26282
  const v = getNestedValue(itemData, f3.name);
26089
26283
  if (v === void 0 || v === null || v === "") return null;
26090
- return f3.variant === "badge" ? /* @__PURE__ */ jsx(Badge, { variant: statusVariant3(String(v)), children: String(v) }, f3.name) : /* @__PURE__ */ jsx(
26284
+ return f3.variant === "badge" ? (
26285
+ // `format` applies here too — a boolean field badged
26286
+ // without it renders the raw "false" instead of "No".
26287
+ /* @__PURE__ */ jsx(Badge, { variant: statusVariant3(String(v)), children: formatValue2(v, f3.format) }, f3.name)
26288
+ ) : /* @__PURE__ */ jsx(
26091
26289
  Typography,
26092
26290
  {
26093
26291
  variant: "caption",
@@ -26199,7 +26397,7 @@ function DataList({
26199
26397
  if (val === void 0 || val === null) return null;
26200
26398
  return /* @__PURE__ */ jsxs(HStack, { gap: "xs", className: "items-center flex-shrink-0", children: [
26201
26399
  field.icon && renderIconInput2(field.icon, { size: "xs" }),
26202
- /* @__PURE__ */ jsx(Badge, { variant: statusVariant3(String(val)), children: String(val) })
26400
+ /* @__PURE__ */ jsx(Badge, { variant: statusVariant3(String(val)), children: formatValue2(val, field.format) })
26203
26401
  ] }, field.name);
26204
26402
  })
26205
26403
  ] }),
@@ -26246,7 +26444,7 @@ function DataList({
26246
26444
  className
26247
26445
  ),
26248
26446
  children: [
26249
- groups.map((group, gi) => /* @__PURE__ */ jsxs(React91__default.Fragment, { children: [
26447
+ groups.map((group, gi) => /* @__PURE__ */ jsxs(React92__default.Fragment, { children: [
26250
26448
  group.label && /* @__PURE__ */ jsx(Divider, { label: group.label, className: gi > 0 ? "mt-4" : "mt-0" }),
26251
26449
  group.items.map(
26252
26450
  (itemData, index) => renderItem(itemData, index, gi === groups.length - 1 && index === group.items.length - 1)
@@ -26333,7 +26531,7 @@ var init_FormSection = __esm({
26333
26531
  columns = 1,
26334
26532
  className
26335
26533
  }) => {
26336
- const [collapsed, setCollapsed] = React91__default.useState(defaultCollapsed);
26534
+ const [collapsed, setCollapsed] = React92__default.useState(defaultCollapsed);
26337
26535
  const { t } = useTranslate();
26338
26536
  const eventBus = useEventBus();
26339
26537
  const gridClass = {
@@ -26341,7 +26539,7 @@ var init_FormSection = __esm({
26341
26539
  2: "grid-cols-1 md:grid-cols-2",
26342
26540
  3: "grid-cols-1 md:grid-cols-2 lg:grid-cols-3"
26343
26541
  }[columns];
26344
- React91__default.useCallback(() => {
26542
+ React92__default.useCallback(() => {
26345
26543
  if (collapsible) {
26346
26544
  setCollapsed((prev) => !prev);
26347
26545
  eventBus.emit("UI:TOGGLE_COLLAPSE", { collapsed: !collapsed });
@@ -26438,6 +26636,182 @@ var init_FormSection = __esm({
26438
26636
  FormActions.displayName = "FormActions";
26439
26637
  }
26440
26638
  });
26639
+ var ALL_CATEGORY, MAX_RENDERED, GridPicker;
26640
+ var init_GridPicker = __esm({
26641
+ "components/core/molecules/GridPicker.tsx"() {
26642
+ "use client";
26643
+ init_cn();
26644
+ init_Input();
26645
+ init_Badge();
26646
+ init_Stack();
26647
+ ALL_CATEGORY = "__all__";
26648
+ MAX_RENDERED = 300;
26649
+ GridPicker = ({
26650
+ items,
26651
+ value,
26652
+ onChange,
26653
+ categories,
26654
+ searchPlaceholder,
26655
+ renderThumbnail,
26656
+ cellSize = 32,
26657
+ className
26658
+ }) => {
26659
+ const [search, setSearch] = useState("");
26660
+ const [activeCategory, setActiveCategory] = useState(ALL_CATEGORY);
26661
+ const gridRef = useRef(null);
26662
+ const categoryChips = useMemo(() => {
26663
+ if (categories !== void 0) return categories;
26664
+ const seen = [];
26665
+ for (const item of items) {
26666
+ if (!seen.includes(item.category)) seen.push(item.category);
26667
+ }
26668
+ return seen;
26669
+ }, [categories, items]);
26670
+ const filtered = useMemo(() => {
26671
+ const needle = search.trim().toLowerCase();
26672
+ return items.filter((item) => {
26673
+ const matchesCategory = activeCategory === ALL_CATEGORY || item.category === activeCategory;
26674
+ const matchesSearch = needle === "" || item.label.toLowerCase().includes(needle) || item.keywords !== void 0 && item.keywords.some((k) => k.toLowerCase().includes(needle));
26675
+ return matchesCategory && matchesSearch;
26676
+ });
26677
+ }, [items, search, activeCategory]);
26678
+ const visible = useMemo(() => filtered.slice(0, MAX_RENDERED), [filtered]);
26679
+ const truncated = filtered.length - visible.length;
26680
+ const select = useCallback(
26681
+ (item) => {
26682
+ onChange(item.id);
26683
+ },
26684
+ [onChange]
26685
+ );
26686
+ const handleKeyDown = useCallback(
26687
+ (e, index) => {
26688
+ const cells = gridRef.current?.querySelectorAll(
26689
+ "[data-gridpicker-cell]"
26690
+ );
26691
+ if (cells === void 0 || cells.length === 0) return;
26692
+ const columns = (() => {
26693
+ const grid = gridRef.current;
26694
+ if (grid === null) return 1;
26695
+ const style = window.getComputedStyle(grid);
26696
+ const cols = style.gridTemplateColumns.split(" ").filter(Boolean).length;
26697
+ return cols > 0 ? cols : 1;
26698
+ })();
26699
+ let next = -1;
26700
+ if (e.key === "ArrowRight") next = index + 1;
26701
+ else if (e.key === "ArrowLeft") next = index - 1;
26702
+ else if (e.key === "ArrowDown") next = index + columns;
26703
+ else if (e.key === "ArrowUp") next = index - columns;
26704
+ else if (e.key === "Enter" || e.key === " ") {
26705
+ e.preventDefault();
26706
+ select(filtered[index]);
26707
+ return;
26708
+ } else {
26709
+ return;
26710
+ }
26711
+ e.preventDefault();
26712
+ if (next >= 0 && next < cells.length) {
26713
+ cells[next].focus();
26714
+ }
26715
+ },
26716
+ [filtered, select]
26717
+ );
26718
+ return /* @__PURE__ */ jsxs(VStack, { gap: "sm", className: cn("w-full", className), children: [
26719
+ /* @__PURE__ */ jsx(
26720
+ Input,
26721
+ {
26722
+ type: "search",
26723
+ icon: "search",
26724
+ value: search,
26725
+ placeholder: searchPlaceholder,
26726
+ clearable: true,
26727
+ onClear: () => setSearch(""),
26728
+ onChange: (e) => setSearch(e.target.value)
26729
+ }
26730
+ ),
26731
+ categoryChips.length > 0 && /* @__PURE__ */ jsxs(HStack, { gap: "xs", wrap: true, children: [
26732
+ /* @__PURE__ */ jsx(
26733
+ Badge,
26734
+ {
26735
+ variant: activeCategory === ALL_CATEGORY ? "primary" : "neutral",
26736
+ size: "sm",
26737
+ role: "button",
26738
+ tabIndex: 0,
26739
+ "aria-pressed": activeCategory === ALL_CATEGORY,
26740
+ className: "cursor-pointer",
26741
+ onClick: () => setActiveCategory(ALL_CATEGORY),
26742
+ onKeyDown: (e) => {
26743
+ if (e.key === "Enter" || e.key === " ") {
26744
+ e.preventDefault();
26745
+ setActiveCategory(ALL_CATEGORY);
26746
+ }
26747
+ },
26748
+ children: "All"
26749
+ }
26750
+ ),
26751
+ categoryChips.map((category) => /* @__PURE__ */ jsx(
26752
+ Badge,
26753
+ {
26754
+ variant: activeCategory === category ? "primary" : "neutral",
26755
+ size: "sm",
26756
+ role: "button",
26757
+ tabIndex: 0,
26758
+ "aria-pressed": activeCategory === category,
26759
+ className: "cursor-pointer",
26760
+ onClick: () => setActiveCategory(category),
26761
+ onKeyDown: (e) => {
26762
+ if (e.key === "Enter" || e.key === " ") {
26763
+ e.preventDefault();
26764
+ setActiveCategory(category);
26765
+ }
26766
+ },
26767
+ children: category
26768
+ },
26769
+ category
26770
+ ))
26771
+ ] }),
26772
+ /* @__PURE__ */ jsx(
26773
+ "div",
26774
+ {
26775
+ ref: gridRef,
26776
+ role: "listbox",
26777
+ className: "grid gap-1 overflow-y-auto max-h-64 p-1",
26778
+ style: {
26779
+ gridTemplateColumns: `repeat(auto-fill, minmax(${cellSize}px, 1fr))`
26780
+ },
26781
+ children: visible.map((item, index) => {
26782
+ const selected = item.id === value;
26783
+ return /* @__PURE__ */ jsx(
26784
+ "button",
26785
+ {
26786
+ type: "button",
26787
+ role: "option",
26788
+ "aria-selected": selected,
26789
+ "aria-label": item.label,
26790
+ title: item.label,
26791
+ "data-gridpicker-cell": true,
26792
+ tabIndex: selected || value === void 0 && index === 0 ? 0 : -1,
26793
+ onClick: () => select(item),
26794
+ onKeyDown: (e) => handleKeyDown(e, index),
26795
+ className: cn(
26796
+ "flex items-center justify-center rounded-sm",
26797
+ "transition-colors hover:bg-muted",
26798
+ "focus:outline-none focus:ring-1 focus:ring-ring",
26799
+ selected && "bg-primary/10 ring-1 ring-primary"
26800
+ ),
26801
+ style: { width: cellSize, height: cellSize },
26802
+ children: renderThumbnail(item)
26803
+ },
26804
+ item.id
26805
+ );
26806
+ })
26807
+ }
26808
+ ),
26809
+ truncated > 0 && /* @__PURE__ */ jsx("div", { className: "px-1 text-xs text-muted-foreground", children: `+${truncated} more \u2014 refine your search` })
26810
+ ] });
26811
+ };
26812
+ GridPicker.displayName = "GridPicker";
26813
+ }
26814
+ });
26441
26815
  function fileIcon(name) {
26442
26816
  const ext = name.split(".").pop()?.toLowerCase() ?? "";
26443
26817
  switch (ext) {
@@ -27210,7 +27584,7 @@ var init_Flex = __esm({
27210
27584
  flexStyle.flexBasis = typeof basis === "number" ? `${basis}px` : basis;
27211
27585
  }
27212
27586
  }
27213
- return React91__default.createElement(Component, {
27587
+ return React92__default.createElement(Component, {
27214
27588
  className: cn(
27215
27589
  inline ? "inline-flex" : "flex",
27216
27590
  directionStyles[direction],
@@ -27329,7 +27703,7 @@ var init_Grid = __esm({
27329
27703
  as: Component = "div"
27330
27704
  }) => {
27331
27705
  const mergedStyle = rows ? { gridTemplateRows: `repeat(${rows}, minmax(0, 1fr))`, ...style } : style;
27332
- return React91__default.createElement(
27706
+ return React92__default.createElement(
27333
27707
  Component,
27334
27708
  {
27335
27709
  className: cn(
@@ -27466,9 +27840,16 @@ var init_Popover = __esm({
27466
27840
  position = "bottom",
27467
27841
  trigger = "click",
27468
27842
  showArrow = true,
27843
+ open,
27844
+ onOpenChange,
27469
27845
  className
27470
27846
  }) => {
27471
- const [isOpen, setIsOpen] = useState(false);
27847
+ const [uncontrolledOpen, setUncontrolledOpen] = useState(false);
27848
+ const isOpen = open !== void 0 ? open : uncontrolledOpen;
27849
+ const setIsOpen = (next) => {
27850
+ if (open === void 0) setUncontrolledOpen(next);
27851
+ onOpenChange?.(next);
27852
+ };
27472
27853
  const [triggerRect, setTriggerRect] = useState(null);
27473
27854
  const [popoverWidth, setPopoverWidth] = useState(0);
27474
27855
  const triggerRef = useRef(null);
@@ -27501,6 +27882,23 @@ var init_Popover = __esm({
27501
27882
  updatePosition();
27502
27883
  }
27503
27884
  }, [isOpen]);
27885
+ useEffect(() => {
27886
+ if (!isOpen) return;
27887
+ let raf = 0;
27888
+ let lastTop = Number.NaN;
27889
+ let lastLeft = Number.NaN;
27890
+ const track = () => {
27891
+ const rect = triggerRef.current?.getBoundingClientRect();
27892
+ if (rect && (rect.top !== lastTop || rect.left !== lastLeft)) {
27893
+ lastTop = rect.top;
27894
+ lastLeft = rect.left;
27895
+ updatePosition();
27896
+ }
27897
+ raf = requestAnimationFrame(track);
27898
+ };
27899
+ raf = requestAnimationFrame(track);
27900
+ return () => cancelAnimationFrame(raf);
27901
+ }, [isOpen]);
27504
27902
  useEffect(() => {
27505
27903
  if (!mounted) setPopoverWidth(0);
27506
27904
  }, [mounted]);
@@ -27537,9 +27935,9 @@ var init_Popover = __esm({
27537
27935
  onMouseLeave: handleClose,
27538
27936
  onPointerDown: tapTriggerProps.onPointerDown
27539
27937
  };
27540
- const childElement = React91__default.isValidElement(children) ? children : /* @__PURE__ */ jsx("span", { children });
27938
+ const childElement = React92__default.isValidElement(children) ? children : /* @__PURE__ */ jsx("span", { children });
27541
27939
  const childPointerDown = childElement.props.onPointerDown;
27542
- const triggerElement = React91__default.cloneElement(
27940
+ const triggerElement = React92__default.cloneElement(
27543
27941
  childElement,
27544
27942
  {
27545
27943
  ref: triggerRef,
@@ -28148,9 +28546,9 @@ var init_Tooltip = __esm({
28148
28546
  if (hideTimeoutRef.current) clearTimeout(hideTimeoutRef.current);
28149
28547
  };
28150
28548
  }, []);
28151
- const triggerElement = React91__default.isValidElement(children) ? children : /* @__PURE__ */ jsx("span", { children });
28549
+ const triggerElement = React92__default.isValidElement(children) ? children : /* @__PURE__ */ jsx("span", { children });
28152
28550
  const childPointerDown = triggerElement.props.onPointerDown;
28153
- const trigger = React91__default.cloneElement(triggerElement, {
28551
+ const trigger = React92__default.cloneElement(triggerElement, {
28154
28552
  ref: triggerRef,
28155
28553
  onMouseEnter: handleMouseEnter,
28156
28554
  onMouseLeave: handleMouseLeave,
@@ -28240,7 +28638,7 @@ var init_WizardProgress = __esm({
28240
28638
  children: /* @__PURE__ */ jsx("div", { className: "flex items-center gap-2", children: normalizedSteps.map((step, index) => {
28241
28639
  const isActive = index === currentStep;
28242
28640
  const isCompleted = index < currentStep;
28243
- return /* @__PURE__ */ jsxs(React91__default.Fragment, { children: [
28641
+ return /* @__PURE__ */ jsxs(React92__default.Fragment, { children: [
28244
28642
  /* @__PURE__ */ jsx(
28245
28643
  "button",
28246
28644
  {
@@ -28849,6 +29247,80 @@ var init_FlipCard = __esm({
28849
29247
  FlipCard.displayName = "FlipCard";
28850
29248
  }
28851
29249
  });
29250
+ var EMOJI_ITEMS, EmojiPicker;
29251
+ var init_EmojiPicker = __esm({
29252
+ "components/core/molecules/EmojiPicker.tsx"() {
29253
+ "use client";
29254
+ init_useEventBus();
29255
+ init_Button();
29256
+ init_GridPicker();
29257
+ init_Popover();
29258
+ EMOJI_ITEMS = (() => {
29259
+ const items = [];
29260
+ for (const name of ordered) {
29261
+ const entry = lib[name];
29262
+ if (entry === void 0 || entry.char === null || entry.char === "") continue;
29263
+ items.push({
29264
+ id: entry.char,
29265
+ label: name.replace(/_/g, " "),
29266
+ category: entry.category.replace(/_/g, " "),
29267
+ keywords: entry.keywords
29268
+ });
29269
+ }
29270
+ return items;
29271
+ })();
29272
+ EmojiPicker = ({
29273
+ pickEvent,
29274
+ position = "top",
29275
+ triggerIcon = "smile",
29276
+ triggerLabel = "Add emoji",
29277
+ className
29278
+ }) => {
29279
+ const eventBus = useEventBus();
29280
+ const [open, setOpen] = useState(false);
29281
+ const handlePick = (glyph) => {
29282
+ if (pickEvent !== void 0) {
29283
+ const payload = { emoji: glyph };
29284
+ eventBus.emit(`UI:${pickEvent}`, payload);
29285
+ }
29286
+ setOpen(false);
29287
+ };
29288
+ return /* @__PURE__ */ jsx(
29289
+ Popover,
29290
+ {
29291
+ position,
29292
+ trigger: "click",
29293
+ showArrow: false,
29294
+ open,
29295
+ onOpenChange: setOpen,
29296
+ content: /* @__PURE__ */ jsx(
29297
+ GridPicker,
29298
+ {
29299
+ items: EMOJI_ITEMS,
29300
+ onChange: handlePick,
29301
+ searchPlaceholder: "Search emoji\u2026",
29302
+ renderThumbnail: (item) => /* @__PURE__ */ jsx("span", { className: "text-xl leading-none", "aria-hidden": "true", children: item.id }),
29303
+ cellSize: 32,
29304
+ className: "w-80"
29305
+ }
29306
+ ),
29307
+ children: /* @__PURE__ */ jsx(
29308
+ Button,
29309
+ {
29310
+ variant: "ghost",
29311
+ icon: triggerIcon,
29312
+ "aria-label": triggerLabel,
29313
+ title: triggerLabel,
29314
+ className,
29315
+ "data-testid": "emoji-picker-trigger"
29316
+ }
29317
+ )
29318
+ }
29319
+ );
29320
+ };
29321
+ EmojiPicker.displayName = "EmojiPicker";
29322
+ }
29323
+ });
28852
29324
  function toISODate(d) {
28853
29325
  return d.toISOString().slice(0, 10);
28854
29326
  }
@@ -29801,12 +30273,12 @@ var init_MapView = __esm({
29801
30273
  shadowSize: [41, 41]
29802
30274
  });
29803
30275
  L.Marker.prototype.options.icon = defaultIcon;
29804
- const { useEffect: useEffect63, useRef: useRef62, useCallback: useCallback94, useState: useState97 } = React91__default;
30276
+ const { useEffect: useEffect63, useRef: useRef63, useCallback: useCallback95, useState: useState99 } = React92__default;
29805
30277
  const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
29806
30278
  const { useEventBus: useEventBus2 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
29807
30279
  function MapUpdater({ centerLat, centerLng, zoom }) {
29808
30280
  const map = useMap();
29809
- const prevRef = useRef62({ centerLat, centerLng, zoom });
30281
+ const prevRef = useRef63({ centerLat, centerLng, zoom });
29810
30282
  useEffect63(() => {
29811
30283
  const prev = prevRef.current;
29812
30284
  if (prev.centerLat !== centerLat || prev.centerLng !== centerLng || prev.zoom !== zoom) {
@@ -29846,8 +30318,8 @@ var init_MapView = __esm({
29846
30318
  showAttribution = true
29847
30319
  }) {
29848
30320
  const eventBus = useEventBus2();
29849
- const [clickedPosition, setClickedPosition] = useState97(null);
29850
- const handleMapClick = useCallback94((lat, lng) => {
30321
+ const [clickedPosition, setClickedPosition] = useState99(null);
30322
+ const handleMapClick = useCallback95((lat, lng) => {
29851
30323
  if (showClickedPin) {
29852
30324
  setClickedPosition({ lat, lng });
29853
30325
  }
@@ -29856,7 +30328,7 @@ var init_MapView = __esm({
29856
30328
  eventBus.emit(`UI:${mapClickEvent}`, { latitude: lat, longitude: lng });
29857
30329
  }
29858
30330
  }, [onMapClick, mapClickEvent, eventBus, showClickedPin]);
29859
- const handleMarkerClick = useCallback94((marker) => {
30331
+ const handleMarkerClick = useCallback95((marker) => {
29860
30332
  onMarkerClick?.(marker);
29861
30333
  if (markerClickEvent) {
29862
30334
  eventBus.emit(`UI:${markerClickEvent}`, { ...marker });
@@ -30691,6 +31163,7 @@ function TableView({
30691
31163
  fields,
30692
31164
  itemActions,
30693
31165
  maxInlineActions,
31166
+ itemClickEvent,
30694
31167
  selectable = false,
30695
31168
  selectEvent,
30696
31169
  selectedIds,
@@ -30718,8 +31191,8 @@ function TableView({
30718
31191
  }) {
30719
31192
  const eventBus = useEventBus();
30720
31193
  const { t } = useTranslate();
30721
- const [visibleCount, setVisibleCount] = React91__default.useState(pageSize > 0 ? pageSize : Infinity);
30722
- const [localSelected, setLocalSelected] = React91__default.useState(/* @__PURE__ */ new Set());
31194
+ const [visibleCount, setVisibleCount] = React92__default.useState(pageSize > 0 ? pageSize : Infinity);
31195
+ const [localSelected, setLocalSelected] = React92__default.useState(/* @__PURE__ */ new Set());
30723
31196
  const colDefs = (Array.isArray(columns) ? columns : void 0) ?? (Array.isArray(fields) ? fields : void 0) ?? [];
30724
31197
  const actionDefs = Array.isArray(itemActions) ? itemActions : [];
30725
31198
  const allDataRaw = Array.isArray(entity) ? entity : entity ? [entity] : [];
@@ -30735,13 +31208,13 @@ function TableView({
30735
31208
  dndItemIdField,
30736
31209
  dndRoot
30737
31210
  });
30738
- const ordered = dnd.orderedItems;
30739
- const data = pageSize > 0 ? ordered.slice(0, visibleCount) : ordered;
30740
- const hasMore = pageSize > 0 && visibleCount < ordered.length;
31211
+ const ordered2 = dnd.orderedItems;
31212
+ const data = pageSize > 0 ? ordered2.slice(0, visibleCount) : ordered2;
31213
+ const hasMore = pageSize > 0 && visibleCount < ordered2.length;
30741
31214
  const hasRenderProp = typeof children === "function";
30742
31215
  const idField = dndItemIdField ?? "id";
30743
31216
  const isCoarsePointer = useMediaQuery("(pointer: coarse)");
30744
- React91__default.useEffect(() => {
31217
+ React92__default.useEffect(() => {
30745
31218
  tableViewLog.debug("render", {
30746
31219
  rowCount: data.length,
30747
31220
  colCount: colDefs.length,
@@ -30790,7 +31263,15 @@ function TableView({
30790
31263
  };
30791
31264
  eventBus.emit(`UI:${action.event}`, payload);
30792
31265
  };
30793
- const colFloors = React91__default.useMemo(
31266
+ const handleRowClick = (row) => () => {
31267
+ if (!itemClickEvent) return;
31268
+ const payload = {
31269
+ id: row.id,
31270
+ row
31271
+ };
31272
+ eventBus.emit(`UI:${itemClickEvent}`, payload);
31273
+ };
31274
+ const colFloors = React92__default.useMemo(
30794
31275
  () => colDefs.map((col) => {
30795
31276
  const longest = data.reduce((widest, row) => {
30796
31277
  const cell = formatCell(asFieldValue(getNestedValue(row, col.field ?? col.key)), col.format);
@@ -30866,10 +31347,12 @@ function TableView({
30866
31347
  role: "row",
30867
31348
  "data-entity-row": true,
30868
31349
  "data-entity-id": id,
31350
+ onClick: itemClickEvent ? handleRowClick(row) : void 0,
30869
31351
  style: !hasRenderProp ? { gridTemplateColumns } : void 0,
30870
31352
  className: cn(
30871
31353
  "group items-center gap-3 transition-colors duration-fast",
30872
31354
  hasRenderProp ? "flex" : "grid",
31355
+ itemClickEvent && "cursor-pointer",
30873
31356
  lk.rowPad,
30874
31357
  lk.divider && "border-b border-[var(--color-border)]",
30875
31358
  lk.striped && index % 2 === 1 && "bg-[var(--color-surface-subtle)]",
@@ -30877,7 +31360,7 @@ function TableView({
30877
31360
  look === "bordered" && "[&>*]:border-r [&>*]:border-[var(--color-border)] [&>*:last-child]:border-r-0"
30878
31361
  ),
30879
31362
  children: [
30880
- selectable && /* @__PURE__ */ jsx(Box, { className: "flex items-center", children: /* @__PURE__ */ jsx(
31363
+ selectable && /* @__PURE__ */ jsx(Box, { className: "flex items-center", onClick: itemClickEvent ? (e) => e.stopPropagation() : void 0, children: /* @__PURE__ */ jsx(
30881
31364
  Checkbox,
30882
31365
  {
30883
31366
  checked: selected.has(id),
@@ -30902,6 +31385,7 @@ function TableView({
30902
31385
  HStack,
30903
31386
  {
30904
31387
  gap: "xs",
31388
+ onClick: itemClickEvent ? (e) => e.stopPropagation() : void 0,
30905
31389
  className: cn(
30906
31390
  // Pinned: the fixed column tracks routinely overflow the caller's
30907
31391
  // scroll container, which used to leave the actions off-screen.
@@ -30949,12 +31433,12 @@ function TableView({
30949
31433
  ]
30950
31434
  }
30951
31435
  );
30952
- return dnd.isZone ? /* @__PURE__ */ jsx(dnd.SortableItem, { id: row[idField] ?? id, children: rowInner }, id) : /* @__PURE__ */ jsx(React91__default.Fragment, { children: rowInner }, id);
31436
+ return dnd.isZone ? /* @__PURE__ */ jsx(dnd.SortableItem, { id: row[idField] ?? id, children: rowInner }, id) : /* @__PURE__ */ jsx(React92__default.Fragment, { children: rowInner }, id);
30953
31437
  };
30954
31438
  const items = Array.from(data);
30955
31439
  const groups = groupBy ? groupData2(items, groupBy) : [{ label: "", items }];
30956
31440
  let runningIndex = 0;
30957
- const body = /* @__PURE__ */ jsx(Box, { role: "rowgroup", children: groups.map((group, gi) => /* @__PURE__ */ jsxs(React91__default.Fragment, { children: [
31441
+ const body = /* @__PURE__ */ jsx(Box, { role: "rowgroup", children: groups.map((group, gi) => /* @__PURE__ */ jsxs(React92__default.Fragment, { children: [
30958
31442
  group.label && /* @__PURE__ */ jsx(Divider, { label: group.label, className: gi > 0 ? "mt-3" : "mt-0" }),
30959
31443
  group.items.map((row) => renderRow(row, runningIndex++))
30960
31444
  ] }, gi)) });
@@ -30971,7 +31455,7 @@ function TableView({
30971
31455
  /* @__PURE__ */ jsx(Icon, { name: "chevron-down", size: "xs", className: "mr-1" }),
30972
31456
  t("common.showMore"),
30973
31457
  " (",
30974
- t("common.remaining", { count: ordered.length - visibleCount }),
31458
+ t("common.remaining", { count: ordered2.length - visibleCount }),
30975
31459
  ")"
30976
31460
  ] }) })
30977
31461
  ]
@@ -32317,7 +32801,7 @@ var init_StepFlow = __esm({
32317
32801
  className
32318
32802
  }) => {
32319
32803
  if (orientation === "vertical") {
32320
- return /* @__PURE__ */ jsx(VStack, { gap: "none", className: cn("w-full", className), children: steps.map((step, index) => /* @__PURE__ */ jsx(React91__default.Fragment, { children: /* @__PURE__ */ jsxs(HStack, { gap: "md", align: "start", className: "w-full", children: [
32804
+ return /* @__PURE__ */ jsx(VStack, { gap: "none", className: cn("w-full", className), children: steps.map((step, index) => /* @__PURE__ */ jsx(React92__default.Fragment, { children: /* @__PURE__ */ jsxs(HStack, { gap: "md", align: "start", className: "w-full", children: [
32321
32805
  /* @__PURE__ */ jsxs(VStack, { gap: "none", align: "center", children: [
32322
32806
  /* @__PURE__ */ jsx(StepCircle, { step, index }),
32323
32807
  showConnectors && index < steps.length - 1 && /* @__PURE__ */ jsx(Box, { className: "w-px h-8 bg-border" })
@@ -32328,7 +32812,7 @@ var init_StepFlow = __esm({
32328
32812
  ] })
32329
32813
  ] }) }, index)) });
32330
32814
  }
32331
- 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(React91__default.Fragment, { children: [
32815
+ 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(React92__default.Fragment, { children: [
32332
32816
  /* @__PURE__ */ jsxs(VStack, { gap: "sm", align: "center", className: "flex-1 w-full md:w-auto", children: [
32333
32817
  /* @__PURE__ */ jsx(StepCircle, { step, index }),
32334
32818
  /* @__PURE__ */ jsx(Typography, { variant: "h4", className: "text-center", children: step.title }),
@@ -33318,7 +33802,7 @@ var init_LikertScale = __esm({
33318
33802
  md: "text-base",
33319
33803
  lg: "text-lg"
33320
33804
  };
33321
- LikertScale = React91__default.forwardRef(
33805
+ LikertScale = React92__default.forwardRef(
33322
33806
  ({
33323
33807
  question,
33324
33808
  options = DEFAULT_LIKERT_OPTIONS,
@@ -33330,7 +33814,7 @@ var init_LikertScale = __esm({
33330
33814
  variant = "radios",
33331
33815
  className
33332
33816
  }, ref) => {
33333
- const groupId = React91__default.useId();
33817
+ const groupId = React92__default.useId();
33334
33818
  const eventBus = useEventBus();
33335
33819
  const handleSelect = useCallback(
33336
33820
  (next) => {
@@ -35619,7 +36103,7 @@ var init_DocBreadcrumb = __esm({
35619
36103
  "aria-label": t("aria.breadcrumb"),
35620
36104
  children: /* @__PURE__ */ jsx(HStack, { gap: "xs", align: "center", wrap: true, children: items.map((item, idx) => {
35621
36105
  const isLast = idx === items.length - 1;
35622
- return /* @__PURE__ */ jsxs(React91__default.Fragment, { children: [
36106
+ return /* @__PURE__ */ jsxs(React92__default.Fragment, { children: [
35623
36107
  idx > 0 && /* @__PURE__ */ jsx(
35624
36108
  Icon,
35625
36109
  {
@@ -36283,7 +36767,7 @@ var init_PageHeader = __esm({
36283
36767
  info: "bg-info/10 text-info"
36284
36768
  };
36285
36769
  return /* @__PURE__ */ jsxs(Box, { className: cn("mb-6", className), children: [
36286
- 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(React91__default.Fragment, { children: [
36770
+ 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(React92__default.Fragment, { children: [
36287
36771
  idx > 0 && /* @__PURE__ */ jsx(Typography, { variant: "small", color: "muted", children: "/" }),
36288
36772
  crumb.href ? /* @__PURE__ */ jsx(
36289
36773
  "a",
@@ -36641,7 +37125,7 @@ var init_Section = __esm({
36641
37125
  as: Component = "section"
36642
37126
  }) => {
36643
37127
  const hasHeader = title || description || action;
36644
- return React91__default.createElement(
37128
+ return React92__default.createElement(
36645
37129
  Component,
36646
37130
  {
36647
37131
  className: cn(
@@ -37015,7 +37499,7 @@ var init_WizardContainer = __esm({
37015
37499
  const isCompleted = index < currentStep;
37016
37500
  const stepKey = step.id ?? step.tabId ?? `step-${index}`;
37017
37501
  const stepTitle = step.title ?? step.name ?? `Step ${index + 1}`;
37018
- return /* @__PURE__ */ jsxs(React91__default.Fragment, { children: [
37502
+ return /* @__PURE__ */ jsxs(React92__default.Fragment, { children: [
37019
37503
  /* @__PURE__ */ jsx(
37020
37504
  Button,
37021
37505
  {
@@ -38802,7 +39286,7 @@ var init_ImportPreviewTree = __esm({
38802
39286
  const renderUnit = (unit, childrenByParent, depth) => {
38803
39287
  const summary = fieldSummary(unit);
38804
39288
  const children = childrenByParent.get(unit.ref) ?? [];
38805
- return /* @__PURE__ */ jsxs(React91__default.Fragment, { children: [
39289
+ return /* @__PURE__ */ jsxs(React92__default.Fragment, { children: [
38806
39290
  /* @__PURE__ */ jsxs(
38807
39291
  Box,
38808
39292
  {
@@ -38899,7 +39383,7 @@ var init_ImportProgress = __esm({
38899
39383
  PIPELINE.map((key, index) => {
38900
39384
  const isComplete = index < currentIndex;
38901
39385
  const isActive = index === currentIndex;
38902
- return /* @__PURE__ */ jsxs(React91__default.Fragment, { children: [
39386
+ return /* @__PURE__ */ jsxs(React92__default.Fragment, { children: [
38903
39387
  index > 0 ? /* @__PURE__ */ jsx(Box, { className: "h-px w-4 bg-border" }) : null,
38904
39388
  /* @__PURE__ */ jsxs(Box, { className: "flex items-center gap-1", "data-testid": `import-progress-step-${key}`, children: [
38905
39389
  /* @__PURE__ */ jsx(
@@ -40012,7 +40496,7 @@ var init_DrawGroup = __esm({
40012
40496
  }
40013
40497
  });
40014
40498
  function extractTitle(children) {
40015
- if (!React91__default.isValidElement(children)) return void 0;
40499
+ if (!React92__default.isValidElement(children)) return void 0;
40016
40500
  const props = children.props;
40017
40501
  if (typeof props.title === "string") {
40018
40502
  return props.title;
@@ -40362,12 +40846,12 @@ var init_Form = __esm({
40362
40846
  const isSchemaEntity = isOrbitalEntitySchema(entity);
40363
40847
  const resolvedEntity = isSchemaEntity ? entity : void 0;
40364
40848
  const entityName = typeof entity === "string" ? entity : resolvedEntity?.name;
40365
- const normalizedInitialData = React91__default.useMemo(() => {
40849
+ const normalizedInitialData = React92__default.useMemo(() => {
40366
40850
  const entityRowAsInitial = isPlainEntityRow(entity) ? entity : void 0;
40367
40851
  const callerInitial = initialData !== null && typeof initialData === "object" && !Array.isArray(initialData) ? initialData : {};
40368
40852
  return entityRowAsInitial !== void 0 ? { ...entityRowAsInitial, ...callerInitial } : callerInitial;
40369
40853
  }, [entity, initialData]);
40370
- const entityDerivedFields = React91__default.useMemo(() => {
40854
+ const entityDerivedFields = React92__default.useMemo(() => {
40371
40855
  if (fields && fields.length > 0) return void 0;
40372
40856
  if (!resolvedEntity) return void 0;
40373
40857
  return resolvedEntity.fields.map(
@@ -40388,16 +40872,16 @@ var init_Form = __esm({
40388
40872
  const conditionalFields = typeof conditionalFieldsRaw === "boolean" ? {} : conditionalFieldsRaw;
40389
40873
  const hiddenCalculations = typeof hiddenCalculationsRaw === "boolean" ? [] : hiddenCalculationsRaw;
40390
40874
  const violationTriggers = typeof violationTriggersRaw === "boolean" ? [] : violationTriggersRaw;
40391
- const [formData, setFormData] = React91__default.useState(
40875
+ const [formData, setFormData] = React92__default.useState(
40392
40876
  normalizedInitialData
40393
40877
  );
40394
- const [collapsedSections, setCollapsedSections] = React91__default.useState(
40878
+ const [collapsedSections, setCollapsedSections] = React92__default.useState(
40395
40879
  /* @__PURE__ */ new Set()
40396
40880
  );
40397
- const [submitError, setSubmitError] = React91__default.useState(null);
40398
- const formRef = React91__default.useRef(null);
40881
+ const [submitError, setSubmitError] = React92__default.useState(null);
40882
+ const formRef = React92__default.useRef(null);
40399
40883
  const formMode = props.mode;
40400
- const mountedRef = React91__default.useRef(false);
40884
+ const mountedRef = React92__default.useRef(false);
40401
40885
  if (!mountedRef.current) {
40402
40886
  mountedRef.current = true;
40403
40887
  debug("forms", "mount", {
@@ -40410,7 +40894,7 @@ var init_Form = __esm({
40410
40894
  });
40411
40895
  }
40412
40896
  const shouldShowCancel = showCancel ?? (fields && fields.length > 0);
40413
- const evalContext = React91__default.useMemo(
40897
+ const evalContext = React92__default.useMemo(
40414
40898
  () => ({
40415
40899
  formValues: formData,
40416
40900
  globalVariables: externalContext?.globalVariables ?? {},
@@ -40419,7 +40903,7 @@ var init_Form = __esm({
40419
40903
  }),
40420
40904
  [formData, externalContext]
40421
40905
  );
40422
- React91__default.useEffect(() => {
40906
+ React92__default.useEffect(() => {
40423
40907
  debug("forms", "initialData-sync", {
40424
40908
  mode: formMode,
40425
40909
  normalizedInitialData,
@@ -40430,7 +40914,7 @@ var init_Form = __esm({
40430
40914
  setFormData(normalizedInitialData);
40431
40915
  }
40432
40916
  }, [normalizedInitialData]);
40433
- const processCalculations = React91__default.useCallback(
40917
+ const processCalculations = React92__default.useCallback(
40434
40918
  (changedFieldId, newFormData) => {
40435
40919
  if (!hiddenCalculations.length) return;
40436
40920
  const context = {
@@ -40455,7 +40939,7 @@ var init_Form = __esm({
40455
40939
  },
40456
40940
  [hiddenCalculations, externalContext, eventBus]
40457
40941
  );
40458
- const checkViolations = React91__default.useCallback(
40942
+ const checkViolations = React92__default.useCallback(
40459
40943
  (changedFieldId, newFormData) => {
40460
40944
  if (!violationTriggers.length) return;
40461
40945
  const context = {
@@ -40493,7 +40977,7 @@ var init_Form = __esm({
40493
40977
  processCalculations(name, newFormData);
40494
40978
  checkViolations(name, newFormData);
40495
40979
  };
40496
- const isFieldVisible = React91__default.useCallback(
40980
+ const isFieldVisible = React92__default.useCallback(
40497
40981
  (fieldName) => {
40498
40982
  const condition = conditionalFields[fieldName];
40499
40983
  if (!condition) return true;
@@ -40501,7 +40985,7 @@ var init_Form = __esm({
40501
40985
  },
40502
40986
  [conditionalFields, evalContext]
40503
40987
  );
40504
- const isSectionVisible = React91__default.useCallback(
40988
+ const isSectionVisible = React92__default.useCallback(
40505
40989
  (section) => {
40506
40990
  if (!section.condition) return true;
40507
40991
  return Boolean(evaluateFormExpression(section.condition, evalContext));
@@ -40577,7 +41061,7 @@ var init_Form = __esm({
40577
41061
  eventBus.emit(`UI:${onCancel}`);
40578
41062
  }
40579
41063
  };
40580
- const renderField = React91__default.useCallback(
41064
+ const renderField = React92__default.useCallback(
40581
41065
  (field) => {
40582
41066
  const fieldName = field.name || field.field;
40583
41067
  if (!fieldName) return null;
@@ -40598,7 +41082,7 @@ var init_Form = __esm({
40598
41082
  [formData, isFieldVisible, relationsData, relationsLoading, isLoading]
40599
41083
  );
40600
41084
  const effectiveFields = entityDerivedFields ?? fields;
40601
- const normalizedFields = React91__default.useMemo(() => {
41085
+ const normalizedFields = React92__default.useMemo(() => {
40602
41086
  if (!effectiveFields || effectiveFields.length === 0) return [];
40603
41087
  return effectiveFields.map((field) => {
40604
41088
  if (typeof field === "string") {
@@ -40622,7 +41106,7 @@ var init_Form = __esm({
40622
41106
  return field;
40623
41107
  });
40624
41108
  }, [effectiveFields, resolvedEntity]);
40625
- const schemaFields = React91__default.useMemo(() => {
41109
+ const schemaFields = React92__default.useMemo(() => {
40626
41110
  if (normalizedFields.length === 0) return null;
40627
41111
  if (isDebugEnabled()) {
40628
41112
  debugGroup(`Form: ${entityName || "unknown"}`);
@@ -40632,7 +41116,7 @@ var init_Form = __esm({
40632
41116
  }
40633
41117
  return normalizedFields.map(renderField).filter(Boolean);
40634
41118
  }, [normalizedFields, renderField, entityName, conditionalFields]);
40635
- const sectionElements = React91__default.useMemo(() => {
41119
+ const sectionElements = React92__default.useMemo(() => {
40636
41120
  if (!sections || sections.length === 0) return null;
40637
41121
  return sections.map((section) => {
40638
41122
  if (!isSectionVisible(section)) {
@@ -41358,7 +41842,7 @@ var init_List = __esm({
41358
41842
  if (entity && typeof entity === "object" && "id" in entity) return [entity];
41359
41843
  return [];
41360
41844
  }, [entity]);
41361
- const getItemActions = React91__default.useCallback(
41845
+ const getItemActions = React92__default.useCallback(
41362
41846
  (item) => {
41363
41847
  if (!itemActions) return [];
41364
41848
  if (typeof itemActions === "function") {
@@ -41839,7 +42323,7 @@ var init_MediaGallery = __esm({
41839
42323
  [selectable, selectedItems, selectionEvent, eventBus]
41840
42324
  );
41841
42325
  const entityData = Array.isArray(entity) ? entity : [];
41842
- const items = React91__default.useMemo(() => {
42326
+ const items = React92__default.useMemo(() => {
41843
42327
  if (propItems && propItems.length > 0) return propItems;
41844
42328
  if (entityData.length === 0) return [];
41845
42329
  return entityData.map((record, idx) => {
@@ -42004,7 +42488,7 @@ var init_MediaGallery = __esm({
42004
42488
  }
42005
42489
  });
42006
42490
  function extractTitle2(children) {
42007
- if (!React91__default.isValidElement(children)) return void 0;
42491
+ if (!React92__default.isValidElement(children)) return void 0;
42008
42492
  const props = children.props;
42009
42493
  if (typeof props.title === "string") {
42010
42494
  return props.title;
@@ -42278,7 +42762,7 @@ var init_debugRegistry = __esm({
42278
42762
  }
42279
42763
  });
42280
42764
  function useDebugData() {
42281
- const [data, setData] = React91.useState(() => ({
42765
+ const [data, setData] = React92.useState(() => ({
42282
42766
  traits: [],
42283
42767
  ticks: [],
42284
42768
  guards: [],
@@ -42292,7 +42776,7 @@ function useDebugData() {
42292
42776
  },
42293
42777
  lastUpdate: Date.now()
42294
42778
  }));
42295
- React91.useEffect(() => {
42779
+ React92.useEffect(() => {
42296
42780
  const updateData = () => {
42297
42781
  setData({
42298
42782
  traits: getAllTraits(),
@@ -42401,12 +42885,12 @@ function layoutGraph(states, transitions, initialState, width, height) {
42401
42885
  return positions;
42402
42886
  }
42403
42887
  function WalkMinimap() {
42404
- const [walkStep, setWalkStep] = React91.useState(null);
42405
- const [traits2, setTraits] = React91.useState([]);
42406
- const [coveredEdges, setCoveredEdges] = React91.useState([]);
42407
- const [completedTraits, setCompletedTraits] = React91.useState(/* @__PURE__ */ new Set());
42408
- const prevTraitRef = React91.useRef(null);
42409
- React91.useEffect(() => {
42888
+ const [walkStep, setWalkStep] = React92.useState(null);
42889
+ const [traits2, setTraits] = React92.useState([]);
42890
+ const [coveredEdges, setCoveredEdges] = React92.useState([]);
42891
+ const [completedTraits, setCompletedTraits] = React92.useState(/* @__PURE__ */ new Set());
42892
+ const prevTraitRef = React92.useRef(null);
42893
+ React92.useEffect(() => {
42410
42894
  const interval = setInterval(() => {
42411
42895
  const w = window;
42412
42896
  const step = w.__orbitalWalkStep;
@@ -42842,15 +43326,15 @@ var init_EntitiesTab = __esm({
42842
43326
  });
42843
43327
  function EventFlowTab({ events: events2 }) {
42844
43328
  const { t } = useTranslate();
42845
- const [filter, setFilter] = React91.useState("all");
42846
- const containerRef = React91.useRef(null);
42847
- const [autoScroll, setAutoScroll] = React91.useState(true);
42848
- React91.useEffect(() => {
43329
+ const [filter, setFilter] = React92.useState("all");
43330
+ const containerRef = React92.useRef(null);
43331
+ const [autoScroll, setAutoScroll] = React92.useState(true);
43332
+ React92.useEffect(() => {
42849
43333
  if (autoScroll && containerRef.current) {
42850
43334
  containerRef.current.scrollTop = containerRef.current.scrollHeight;
42851
43335
  }
42852
43336
  }, [events2.length, autoScroll]);
42853
- const filteredEvents = React91.useMemo(() => {
43337
+ const filteredEvents = React92.useMemo(() => {
42854
43338
  if (filter === "all") return events2;
42855
43339
  return events2.filter((e) => e.type === filter);
42856
43340
  }, [events2, filter]);
@@ -42966,7 +43450,7 @@ var init_EventFlowTab = __esm({
42966
43450
  });
42967
43451
  function GuardsPanel({ guards }) {
42968
43452
  const { t } = useTranslate();
42969
- const [filter, setFilter] = React91.useState("all");
43453
+ const [filter, setFilter] = React92.useState("all");
42970
43454
  if (guards.length === 0) {
42971
43455
  return /* @__PURE__ */ jsx(
42972
43456
  EmptyState,
@@ -42979,7 +43463,7 @@ function GuardsPanel({ guards }) {
42979
43463
  }
42980
43464
  const passedCount = guards.filter((g) => g.result).length;
42981
43465
  const failedCount = guards.length - passedCount;
42982
- const filteredGuards = React91.useMemo(() => {
43466
+ const filteredGuards = React92.useMemo(() => {
42983
43467
  if (filter === "all") return guards;
42984
43468
  if (filter === "passed") return guards.filter((g) => g.result);
42985
43469
  return guards.filter((g) => !g.result);
@@ -43142,10 +43626,10 @@ function EffectBadge({ effect }) {
43142
43626
  }
43143
43627
  function TransitionTimeline({ transitions }) {
43144
43628
  const { t } = useTranslate();
43145
- const containerRef = React91.useRef(null);
43146
- const [autoScroll, setAutoScroll] = React91.useState(true);
43147
- const [expandedId, setExpandedId] = React91.useState(null);
43148
- React91.useEffect(() => {
43629
+ const containerRef = React92.useRef(null);
43630
+ const [autoScroll, setAutoScroll] = React92.useState(true);
43631
+ const [expandedId, setExpandedId] = React92.useState(null);
43632
+ React92.useEffect(() => {
43149
43633
  if (autoScroll && containerRef.current) {
43150
43634
  containerRef.current.scrollTop = containerRef.current.scrollHeight;
43151
43635
  }
@@ -43425,9 +43909,9 @@ function getAllEvents(traits2) {
43425
43909
  function EventDispatcherTab({ traits: traits2, schema }) {
43426
43910
  const eventBus = useEventBus();
43427
43911
  const { t } = useTranslate();
43428
- const [log11, setLog] = React91.useState([]);
43429
- const prevStatesRef = React91.useRef(/* @__PURE__ */ new Map());
43430
- React91.useEffect(() => {
43912
+ const [log11, setLog] = React92.useState([]);
43913
+ const prevStatesRef = React92.useRef(/* @__PURE__ */ new Map());
43914
+ React92.useEffect(() => {
43431
43915
  for (const trait of traits2) {
43432
43916
  const prev = prevStatesRef.current.get(trait.id);
43433
43917
  if (prev && prev !== trait.currentState) {
@@ -43596,10 +44080,10 @@ function VerifyModePanel({
43596
44080
  localCount
43597
44081
  }) {
43598
44082
  const { t } = useTranslate();
43599
- const [expanded, setExpanded] = React91.useState(true);
43600
- const scrollRef = React91.useRef(null);
43601
- const prevCountRef = React91.useRef(0);
43602
- React91.useEffect(() => {
44083
+ const [expanded, setExpanded] = React92.useState(true);
44084
+ const scrollRef = React92.useRef(null);
44085
+ const prevCountRef = React92.useRef(0);
44086
+ React92.useEffect(() => {
43603
44087
  if (expanded && transitions.length > prevCountRef.current && scrollRef.current) {
43604
44088
  scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
43605
44089
  }
@@ -43656,10 +44140,10 @@ function RuntimeDebugger({
43656
44140
  schema
43657
44141
  }) {
43658
44142
  const { t } = useTranslate();
43659
- const [isCollapsed, setIsCollapsed] = React91.useState(mode === "verify" ? true : defaultCollapsed);
43660
- const [isVisible, setIsVisible] = React91.useState(mode === "inline" || mode === "verify" || isDebugEnabled2());
44143
+ const [isCollapsed, setIsCollapsed] = React92.useState(mode === "verify" ? true : defaultCollapsed);
44144
+ const [isVisible, setIsVisible] = React92.useState(mode === "inline" || mode === "verify" || isDebugEnabled2());
43661
44145
  const debugData = useDebugData();
43662
- React91.useEffect(() => {
44146
+ React92.useEffect(() => {
43663
44147
  if (mode === "inline") return;
43664
44148
  return onDebugToggle((enabled) => {
43665
44149
  setIsVisible(enabled);
@@ -43668,7 +44152,7 @@ function RuntimeDebugger({
43668
44152
  }
43669
44153
  });
43670
44154
  }, [mode]);
43671
- React91.useEffect(() => {
44155
+ React92.useEffect(() => {
43672
44156
  if (mode === "inline") return;
43673
44157
  const handleKeyDown = (e) => {
43674
44158
  if (e.key === "`" && isVisible) {
@@ -44188,7 +44672,7 @@ var init_StatCard = __esm({
44188
44672
  const labelToUse = propLabel ?? propTitle;
44189
44673
  const eventBus = useEventBus();
44190
44674
  const { t } = useTranslate();
44191
- const handleActionClick = React91__default.useCallback(() => {
44675
+ const handleActionClick = React92__default.useCallback(() => {
44192
44676
  if (action?.event) {
44193
44677
  eventBus.emit(`UI:${action.event}`, {});
44194
44678
  }
@@ -44199,7 +44683,7 @@ var init_StatCard = __esm({
44199
44683
  const data = Array.isArray(entity) ? entity : entity ? [entity] : [];
44200
44684
  const isLoading = externalLoading ?? false;
44201
44685
  const error = externalError;
44202
- const computeMetricValue = React91__default.useCallback(
44686
+ const computeMetricValue = React92__default.useCallback(
44203
44687
  (metric, items) => {
44204
44688
  if (metric.value !== void 0) {
44205
44689
  return metric.value;
@@ -44238,7 +44722,7 @@ var init_StatCard = __esm({
44238
44722
  },
44239
44723
  []
44240
44724
  );
44241
- const schemaStats = React91__default.useMemo(() => {
44725
+ const schemaStats = React92__default.useMemo(() => {
44242
44726
  if (!metrics || metrics.length === 0) return null;
44243
44727
  return metrics.map((metric) => ({
44244
44728
  label: metric.label,
@@ -44246,7 +44730,7 @@ var init_StatCard = __esm({
44246
44730
  format: metric.format
44247
44731
  }));
44248
44732
  }, [metrics, data, computeMetricValue]);
44249
- const calculatedTrend = React91__default.useMemo(() => {
44733
+ const calculatedTrend = React92__default.useMemo(() => {
44250
44734
  if (manualTrend !== void 0) return manualTrend;
44251
44735
  if (previousValue === void 0 || currentValue === void 0)
44252
44736
  return void 0;
@@ -44886,8 +45370,8 @@ var init_SubagentTracePanel = __esm({
44886
45370
  ] });
44887
45371
  };
44888
45372
  InlineActivityStream = ({ activities, autoScroll = true, className }) => {
44889
- const endRef = React91__default.useRef(null);
44890
- React91__default.useEffect(() => {
45373
+ const endRef = React92__default.useRef(null);
45374
+ React92__default.useEffect(() => {
44891
45375
  if (!autoScroll) return;
44892
45376
  endRef.current?.scrollIntoView({ behavior: "smooth", block: "end" });
44893
45377
  }, [activities.length, autoScroll]);
@@ -44981,7 +45465,7 @@ var init_SubagentTracePanel = __esm({
44981
45465
  };
44982
45466
  SubagentRichCard = ({ subagent }) => {
44983
45467
  const { t } = useTranslate();
44984
- const activities = React91__default.useMemo(
45468
+ const activities = React92__default.useMemo(
44985
45469
  () => subagentMessagesToActivities(subagent.messages),
44986
45470
  [subagent.messages]
44987
45471
  );
@@ -45058,8 +45542,8 @@ var init_SubagentTracePanel = __esm({
45058
45542
  ] });
45059
45543
  };
45060
45544
  CoordinatorConversation = ({ messages, autoScroll = true, className }) => {
45061
- const endRef = React91__default.useRef(null);
45062
- React91__default.useEffect(() => {
45545
+ const endRef = React92__default.useRef(null);
45546
+ React92__default.useEffect(() => {
45063
45547
  if (!autoScroll) return;
45064
45548
  endRef.current?.scrollIntoView({ behavior: "smooth", block: "end" });
45065
45549
  }, [messages.length, autoScroll]);
@@ -45494,7 +45978,7 @@ var init_Timeline = __esm({
45494
45978
  }) => {
45495
45979
  const { t } = useTranslate();
45496
45980
  const entityData = entity ?? [];
45497
- const items = React91__default.useMemo(() => {
45981
+ const items = React92__default.useMemo(() => {
45498
45982
  if (propItems) return propItems;
45499
45983
  if (entityData.length === 0) return [];
45500
45984
  return entityData.map((record, idx) => {
@@ -45596,7 +46080,7 @@ var init_Timeline = __esm({
45596
46080
  }
45597
46081
  });
45598
46082
  function extractToastProps(children) {
45599
- if (!React91__default.isValidElement(children)) {
46083
+ if (!React92__default.isValidElement(children)) {
45600
46084
  if (typeof children === "string") {
45601
46085
  return { message: children };
45602
46086
  }
@@ -45638,7 +46122,7 @@ var init_ToastSlot = __esm({
45638
46122
  eventBus.emit(`${prefix}CLOSE`);
45639
46123
  };
45640
46124
  if (!isVisible) return null;
45641
- const isCustomContent = React91__default.isValidElement(children) && !message;
46125
+ const isCustomContent = React92__default.isValidElement(children) && !message;
45642
46126
  return /* @__PURE__ */ jsx(Box, { className: "fixed bottom-4 right-4 z-50", children: isCustomContent ? children : /* @__PURE__ */ jsx(
45643
46127
  Toast,
45644
46128
  {
@@ -45743,6 +46227,7 @@ var init_component_registry_generated = __esm({
45743
46227
  init_Drawer();
45744
46228
  init_DrawerSlot();
45745
46229
  init_EdgeDecoration();
46230
+ init_EmojiPicker();
45746
46231
  init_EmptyState();
45747
46232
  init_ErrorBoundary();
45748
46233
  init_ErrorState();
@@ -46010,6 +46495,7 @@ var init_component_registry_generated = __esm({
46010
46495
  "Drawer": Drawer,
46011
46496
  "DrawerSlot": DrawerSlot,
46012
46497
  "EdgeDecoration": EdgeDecoration,
46498
+ "EmojiPicker": EmojiPicker,
46013
46499
  "EmptyState": EmptyState,
46014
46500
  "ErrorBoundary": ErrorBoundary,
46015
46501
  "ErrorState": ErrorState,
@@ -46209,7 +46695,7 @@ function SuspenseConfigProvider({
46209
46695
  config,
46210
46696
  children
46211
46697
  }) {
46212
- return React91__default.createElement(
46698
+ return React92__default.createElement(
46213
46699
  SuspenseConfigContext.Provider,
46214
46700
  { value: config },
46215
46701
  children
@@ -46251,7 +46737,7 @@ function enrichFormFields(fields, entityDef) {
46251
46737
  }
46252
46738
  return { name: field, label: humanizeFieldName(field) };
46253
46739
  }
46254
- if (field && typeof field === "object" && !Array.isArray(field) && !React91__default.isValidElement(field) && !(field instanceof Date)) {
46740
+ if (field && typeof field === "object" && !Array.isArray(field) && !React92__default.isValidElement(field) && !(field instanceof Date)) {
46255
46741
  const obj = field;
46256
46742
  const fieldName = typeof obj.name === "string" ? obj.name : typeof obj.field === "string" ? obj.field : void 0;
46257
46743
  if (!fieldName) return field;
@@ -46437,7 +46923,19 @@ function UISlotComponent({
46437
46923
  const suspenseConfig = useContext(SuspenseConfigContext);
46438
46924
  const contained = useContext(SlotContainedContext);
46439
46925
  const schemaCtx = useEntitySchemaOptional();
46440
- const content = slots[slot];
46926
+ const rawContent = slots[slot];
46927
+ const binding = useEntityBindingSnapshot(rawContent?.sourceTrait);
46928
+ const content = useMemo(() => {
46929
+ if (!rawContent) return rawContent;
46930
+ const resolvedProps = resolveRenderBindingMarkers(
46931
+ rawContent.props,
46932
+ rawContent.sourceTrait,
46933
+ binding.entity,
46934
+ binding.config,
46935
+ binding.state
46936
+ );
46937
+ return resolvedProps === rawContent.props ? rawContent : { ...rawContent, props: resolvedProps };
46938
+ }, [rawContent, binding.entity, binding.config, binding.state]);
46441
46939
  if (children !== void 0) {
46442
46940
  if (pattern === "clear") {
46443
46941
  return null;
@@ -46711,7 +47209,7 @@ function renderPatternChildren(children, onDismiss, parentId = "root", parentPat
46711
47209
  const key = `${parentId}-${index}-trait:${traitName}`;
46712
47210
  return /* @__PURE__ */ jsx(TraitFrame, { traitName }, key);
46713
47211
  }
46714
- return /* @__PURE__ */ jsx(React91__default.Fragment, { children: child }, `${parentId}-${index}`);
47212
+ return /* @__PURE__ */ jsx(React92__default.Fragment, { children: child }, `${parentId}-${index}`);
46715
47213
  }
46716
47214
  if (!child || typeof child !== "object") return null;
46717
47215
  const childId = `${parentId}-${index}`;
@@ -46768,19 +47266,20 @@ function isPatternConfig(value) {
46768
47266
  if (value === null || value === void 0) return false;
46769
47267
  if (typeof value !== "object") return false;
46770
47268
  if (Array.isArray(value)) return false;
46771
- if (React91__default.isValidElement(value)) return false;
47269
+ if (React92__default.isValidElement(value)) return false;
46772
47270
  if (value instanceof Date) return false;
46773
47271
  if (typeof value === "function") return false;
46774
47272
  const record = value;
46775
47273
  return "type" in record && typeof record.type === "string" && getComponentForPattern$1(record.type) !== null;
46776
47274
  }
46777
47275
  function isPlainConfigObject(value) {
46778
- if (React91__default.isValidElement(value)) return false;
47276
+ if (React92__default.isValidElement(value)) return false;
46779
47277
  if (value instanceof Date) return false;
46780
47278
  const proto = Object.getPrototypeOf(value);
46781
47279
  return proto === Object.prototype || proto === null;
46782
47280
  }
46783
47281
  function substituteTraitRefsDeep(value, pathKey) {
47282
+ if (isRenderBindingMarker(value)) return value;
46784
47283
  if (typeof value === "string") {
46785
47284
  const match = TRAIT_BINDING_RE.exec(value);
46786
47285
  if (match) {
@@ -46853,7 +47352,14 @@ function SlotContentRenderer({
46853
47352
  onDismiss,
46854
47353
  patternPath
46855
47354
  }) {
46856
- const entityProp = content.props.entity;
47355
+ const ambientScope = useTraitScope();
47356
+ const bindingTrait = content.sourceTrait ?? ambientScope?.trait;
47357
+ const binding = useEntityBindingSnapshot(bindingTrait);
47358
+ const liveProps = useMemo(
47359
+ () => resolveRenderBindingMarkers(content.props, bindingTrait, binding.entity, binding.config, binding.state),
47360
+ [content.props, bindingTrait, binding.entity, binding.config, binding.state]
47361
+ );
47362
+ const entityProp = liveProps.entity;
46857
47363
  if (content.pattern === "form-section") {
46858
47364
  slotLog.debug("SlotContentRenderer:form-section-render", {
46859
47365
  contentId: content.id,
@@ -46884,7 +47390,7 @@ function SlotContentRenderer({
46884
47390
  const orbitalName = schemaCtx && content.sourceTrait !== void 0 ? schemaCtx.orbitalsByTrait.get(content.sourceTrait) : void 0;
46885
47391
  const PatternComponent = getComponentForPattern(content.pattern);
46886
47392
  if (PatternComponent) {
46887
- const childrenConfig = content.props.children;
47393
+ const childrenConfig = liveProps.children;
46888
47394
  const isSingleChild = typeof childrenConfig === "string" || typeof childrenConfig === "object" && childrenConfig !== null && !Array.isArray(childrenConfig) && "type" in childrenConfig;
46889
47395
  const hasChildren = PATTERNS_WITH_CHILDREN.has(content.pattern) || Array.isArray(childrenConfig) && childrenConfig.length > 0 || isSingleChild;
46890
47396
  const isDrawHost = isDrawHostPattern(content.pattern);
@@ -46895,15 +47401,15 @@ function SlotContentRenderer({
46895
47401
  fromState: content.fromState,
46896
47402
  entity: content.entity
46897
47403
  }) : void 0;
46898
- const incomingChildren = content.props.children;
47404
+ const incomingChildren = liveProps.children;
46899
47405
  const childrenIsRenderFn = typeof incomingChildren === "function";
46900
- const { children: _childrenConfig, ...restPropsNoChildren } = content.props;
47406
+ const { children: _childrenConfig, ...restPropsNoChildren } = liveProps;
46901
47407
  const restProps = childrenIsRenderFn ? { ...restPropsNoChildren, children: incomingChildren } : restPropsNoChildren;
46902
47408
  const nodeSlotOverrides = {};
46903
47409
  for (const slotKey of CONTENT_NODE_SLOTS) {
46904
47410
  const slotVal = restProps[slotKey];
46905
47411
  if (slotVal === void 0 || slotVal === null) continue;
46906
- if (React91__default.isValidElement(slotVal) || typeof slotVal === "string" || typeof slotVal === "number" || typeof slotVal === "boolean") continue;
47412
+ if (React92__default.isValidElement(slotVal) || typeof slotVal === "string" || typeof slotVal === "number" || typeof slotVal === "boolean") continue;
46907
47413
  const typelessChildren = !Array.isArray(slotVal) && typeof slotVal === "object" && !("type" in slotVal) && Array.isArray(slotVal.children) ? slotVal.children : void 0;
46908
47414
  if (typelessChildren !== void 0 || Array.isArray(slotVal) || typeof slotVal === "object" && "type" in slotVal) {
46909
47415
  nodeSlotOverrides[slotKey] = renderPatternChildren(
@@ -46957,7 +47463,7 @@ function SlotContentRenderer({
46957
47463
  const resolvedItems = Array.isArray(entityVal) && entityVal[0] !== "fn" ? entityVal : null;
46958
47464
  if (resolvedItems && resolvedItems.length > 0 && !finalProps.fields && !finalProps.columns) {
46959
47465
  const sample = resolvedItems[0];
46960
- if (sample && typeof sample === "object" && !Array.isArray(sample) && !React91__default.isValidElement(sample) && !(sample instanceof Date)) {
47466
+ if (sample && typeof sample === "object" && !Array.isArray(sample) && !React92__default.isValidElement(sample) && !(sample instanceof Date)) {
46961
47467
  const keys = Object.keys(sample).filter((k) => k !== "id" && k !== "_id");
46962
47468
  finalProps.fields = keys.map((k, i) => ({ name: k, variant: i === 0 ? "h4" : "body" }));
46963
47469
  }
@@ -47006,7 +47512,7 @@ function SlotContentRenderer({
47006
47512
  "data-orb-path": patternPath ?? "root",
47007
47513
  "data-orb-pattern": content.pattern,
47008
47514
  "data-orb-orbital": orbitalName,
47009
- children: content.props.children ?? /* @__PURE__ */ jsxs(Box, { className: "p-4 text-sm text-muted-foreground border border-dashed border-border rounded", children: [
47515
+ children: liveProps.children ?? /* @__PURE__ */ jsxs(Box, { className: "p-4 text-sm text-muted-foreground border border-dashed border-border rounded", children: [
47010
47516
  "Unknown pattern: ",
47011
47517
  content.pattern,
47012
47518
  content.sourceTrait && /* @__PURE__ */ jsxs(Typography, { variant: "small", className: "ml-2", children: [
@@ -47078,6 +47584,7 @@ var scopeWrapLog, TRAIT_BINDING_RE, SuspenseConfigContext, SlotContainedContext,
47078
47584
  var init_UISlotRenderer = __esm({
47079
47585
  "components/core/organisms/UISlotRenderer.tsx"() {
47080
47586
  "use client";
47587
+ init_resolve_render_bindings();
47081
47588
  init_Modal();
47082
47589
  init_Drawer();
47083
47590
  init_Toast();
@@ -47323,7 +47830,7 @@ var AvlTransition = ({
47323
47830
  opacity = 1,
47324
47831
  className
47325
47832
  }) => {
47326
- const ids = React91__default.useMemo(() => {
47833
+ const ids = React92__default.useMemo(() => {
47327
47834
  avlTransitionId += 1;
47328
47835
  return { arrow: `avl-tr-${avlTransitionId}-arrow` };
47329
47836
  }, []);
@@ -47884,7 +48391,7 @@ var AvlStateMachine = ({
47884
48391
  color = "var(--color-primary)",
47885
48392
  animated = false
47886
48393
  }) => {
47887
- const ids = React91__default.useMemo(() => {
48394
+ const ids = React92__default.useMemo(() => {
47888
48395
  avlSmId += 1;
47889
48396
  const base = `avl-sm-${avlSmId}`;
47890
48397
  return { glow: `${base}-glow`, grad: `${base}-grad` };
@@ -48083,7 +48590,7 @@ var AvlOrbitalUnit = ({
48083
48590
  color = "var(--color-primary)",
48084
48591
  animated = false
48085
48592
  }) => {
48086
- const ids = React91__default.useMemo(() => {
48593
+ const ids = React92__default.useMemo(() => {
48087
48594
  avlOuId += 1;
48088
48595
  const base = `avl-ou-${avlOuId}`;
48089
48596
  return { glow: `${base}-glow`, grad: `${base}-grad` };
@@ -48179,7 +48686,7 @@ var AvlClosedCircuit = ({
48179
48686
  color = "var(--color-primary)",
48180
48687
  animated = false
48181
48688
  }) => {
48182
- const ids = React91__default.useMemo(() => {
48689
+ const ids = React92__default.useMemo(() => {
48183
48690
  avlCcId += 1;
48184
48691
  const base = `avl-cc-${avlCcId}`;
48185
48692
  return { glow: `${base}-glow`, grad: `${base}-grad`, arrow: `${base}-arrow` };
@@ -48334,7 +48841,7 @@ var AvlEmitListen = ({
48334
48841
  color = "var(--color-primary)",
48335
48842
  animated = false
48336
48843
  }) => {
48337
- const ids = React91__default.useMemo(() => {
48844
+ const ids = React92__default.useMemo(() => {
48338
48845
  avlElId += 1;
48339
48846
  const base = `avl-el-${avlElId}`;
48340
48847
  return { arrow: `${base}-arrow`, grad: `${base}-grad` };
@@ -48608,7 +49115,7 @@ function renderNode(node, color, glowId) {
48608
49115
  const baseR = node.type === "operator" ? 20 : 16;
48609
49116
  const r2 = Math.max(baseR, labelLen * 3.5 + 6);
48610
49117
  const nc = nodeColor(node.type, color);
48611
- return /* @__PURE__ */ jsxs(React91__default.Fragment, { children: [
49118
+ return /* @__PURE__ */ jsxs(React92__default.Fragment, { children: [
48612
49119
  node.children.map((child, i) => {
48613
49120
  const childR = Math.max(
48614
49121
  child.type === "operator" ? 20 : 16,
@@ -48665,7 +49172,7 @@ var AvlExprTree = ({
48665
49172
  className,
48666
49173
  color = "var(--color-primary)"
48667
49174
  }) => {
48668
- const ids = React91__default.useMemo(() => {
49175
+ const ids = React92__default.useMemo(() => {
48669
49176
  avlEtId += 1;
48670
49177
  return { glow: `avl-et-${avlEtId}-glow` };
48671
49178
  }, []);
@@ -49500,7 +50007,7 @@ var SystemNode = ({ data }) => {
49500
50007
  stateChain.length > 0 && /* @__PURE__ */ jsx("svg", { width: stateChain.length * 14 + 2, height: 10, viewBox: `0 0 ${stateChain.length * 14 + 2} 10`, children: stateChain.map((s, i) => {
49501
50008
  const tc = transitionCounts[s.name] ?? 0;
49502
50009
  const role = getStateRole(s.name, s.isInitial ?? void 0, s.isTerminal ?? void 0, tc, maxTC);
49503
- return /* @__PURE__ */ jsxs(React91__default.Fragment, { children: [
50010
+ return /* @__PURE__ */ jsxs(React92__default.Fragment, { children: [
49504
50011
  /* @__PURE__ */ jsx(AvlState, { x: i * 14 + 1, y: 1, width: 10, height: 8, name: "", role, isInitial: s.isInitial ?? void 0, isTerminal: s.isTerminal ?? void 0 }),
49505
50012
  i < stateChain.length - 1 && /* @__PURE__ */ jsx("line", { x1: i * 14 + 12, y1: 5, x2: i * 14 + 15, y2: 5, stroke: "var(--color-border)", strokeWidth: 0.5 })
49506
50013
  ] }, s.name);
@@ -50579,12 +51086,15 @@ function resolveLambdaBindings(body, params, item, index) {
50579
51086
  const arr = body;
50580
51087
  const substituted = arr.map((b) => recur(b));
50581
51088
  if (isOperatorCall(substituted) && isSExpr(substituted)) {
51089
+ if (containsEntityBinding(substituted)) {
51090
+ return substituted;
51091
+ }
50582
51092
  const evaluated = evaluate(substituted, createMinimalContext());
50583
51093
  return isEventPayloadValue(evaluated) ? evaluated : String(evaluated);
50584
51094
  }
50585
51095
  return substituted;
50586
51096
  }
50587
- if (body !== null && typeof body === "object" && !React91__default.isValidElement(body) && !(body instanceof Date) && typeof body !== "function") {
51097
+ if (body !== null && typeof body === "object" && !React92__default.isValidElement(body) && !(body instanceof Date) && typeof body !== "function") {
50588
51098
  const out = {};
50589
51099
  for (const [k, v] of Object.entries(body)) {
50590
51100
  out[k] = recur(v);
@@ -50600,10 +51110,38 @@ function getSlotContentRenderer2() {
50600
51110
  _slotContentRenderer2 = mod.SlotContentRenderer;
50601
51111
  return _slotContentRenderer2;
50602
51112
  }
51113
+ function deferLambdaEntityExprs(value) {
51114
+ if (typeof value === "string") {
51115
+ if (containsEntityBinding(value)) {
51116
+ const marker = { [RENDER_BINDING_MARKER]: true, expression: value };
51117
+ return marker;
51118
+ }
51119
+ return value;
51120
+ }
51121
+ if (Array.isArray(value)) {
51122
+ if (isFnFormLambda(value)) return value;
51123
+ const arr = value;
51124
+ if (isOperatorCall(arr) && isSExpr(arr) && containsEntityBinding(arr)) {
51125
+ const marker = { [RENDER_BINDING_MARKER]: true, expression: arr };
51126
+ return marker;
51127
+ }
51128
+ return arr.map((v) => deferLambdaEntityExprs(v));
51129
+ }
51130
+ if (value !== null && typeof value === "object" && !React92__default.isValidElement(value) && !(value instanceof Date) && typeof value !== "function" && !isRenderBindingMarker(value)) {
51131
+ const out = {};
51132
+ for (const [k, v] of Object.entries(value)) {
51133
+ out[k] = deferLambdaEntityExprs(v);
51134
+ }
51135
+ return out;
51136
+ }
51137
+ return value;
51138
+ }
50603
51139
  function makeLambdaFn(params, lambdaBody, callerKey) {
50604
51140
  return (item, index) => {
50605
- const resolvedBody = resolveLambdaBindings(lambdaBody, params, item, index);
50606
- if (resolvedBody === null || typeof resolvedBody !== "object" || Array.isArray(resolvedBody) || typeof resolvedBody === "function" || React91__default.isValidElement(resolvedBody) || resolvedBody instanceof Date) {
51141
+ const resolvedBody = deferLambdaEntityExprs(
51142
+ resolveLambdaBindings(lambdaBody, params, item, index)
51143
+ );
51144
+ if (resolvedBody === null || typeof resolvedBody !== "object" || Array.isArray(resolvedBody) || typeof resolvedBody === "function" || React92__default.isValidElement(resolvedBody) || resolvedBody instanceof Date) {
50607
51145
  return null;
50608
51146
  }
50609
51147
  const record = resolvedBody;
@@ -50622,11 +51160,12 @@ function makeLambdaFn(params, lambdaBody, callerKey) {
50622
51160
  props: childProps,
50623
51161
  priority: 0
50624
51162
  };
50625
- return React91__default.createElement(SlotContentRenderer2, { content: childContent });
51163
+ return React92__default.createElement(SlotContentRenderer2, { content: childContent });
50626
51164
  };
50627
51165
  }
50628
51166
  function convertNode(node, callerKey) {
50629
51167
  if (node === null || node === void 0) return node;
51168
+ if (isRenderBindingMarker(node)) return node;
50630
51169
  if (Array.isArray(node)) {
50631
51170
  if (isFnFormLambda(node)) {
50632
51171
  const arr2 = node;
@@ -50641,7 +51180,7 @@ function convertNode(node, callerKey) {
50641
51180
  });
50642
51181
  return anyChanged ? mapped : node;
50643
51182
  }
50644
- if (typeof node === "object" && !React91__default.isValidElement(node) && !(node instanceof Date)) {
51183
+ if (typeof node === "object" && !React92__default.isValidElement(node) && !(node instanceof Date)) {
50645
51184
  return convertObjectProps(node);
50646
51185
  }
50647
51186
  return node;
@@ -50800,6 +51339,7 @@ var tickLog = createLogger("almadar:ui:tick-effects");
50800
51339
  setNamespaceLevel("almadar:ui:tick-effects", "WARN");
50801
51340
  var sharedEntityLog = createLogger("almadar:ui:shared-entity");
50802
51341
  setNamespaceLevel("almadar:ui:shared-entity", "WARN");
51342
+ var EMPTY_BINDING_SNAPSHOT = {};
50803
51343
  var SYNC_TICK_OPERATORS = /* @__PURE__ */ new Set([
50804
51344
  "set",
50805
51345
  "emit",
@@ -50820,11 +51360,6 @@ var SYNC_TICK_OPERATORS = /* @__PURE__ */ new Set([
50820
51360
  "do",
50821
51361
  "when"
50822
51362
  ]);
50823
- var REACTIVE_REPAINT_PATTERN_TYPES = /* @__PURE__ */ new Set([
50824
- "canvas",
50825
- "game-hud",
50826
- "game-shell"
50827
- ]);
50828
51363
  var LIFECYCLE_EVENTS = ["INIT", "LOAD", "$MOUNT"];
50829
51364
  function toTraitDefinition(binding) {
50830
51365
  return {
@@ -50865,6 +51400,27 @@ function classifySharedTick(tick) {
50865
51400
  if (renders) return "renderer";
50866
51401
  return "neither";
50867
51402
  }
51403
+ function buildTraitRenderConfig(binding, traitConfigsByName, payload) {
51404
+ const declaredDefaults = collectDeclaredConfigDefaults(binding.trait);
51405
+ const resolvedDefaults = traitConfigsByName?.[binding.trait.name];
51406
+ const callSiteConfig = getBindingConfig(binding);
51407
+ const callSiteOverrides = callSiteConfig ? resolveCallSitePayloadCaptures(
51408
+ Object.fromEntries(
51409
+ Object.entries(callSiteConfig).filter(
51410
+ ([, v]) => !containsConfigForward(v)
51411
+ )
51412
+ ),
51413
+ payload
51414
+ ) : void 0;
51415
+ if (declaredDefaults || resolvedDefaults || callSiteOverrides) {
51416
+ return {
51417
+ ...declaredDefaults ?? {},
51418
+ ...resolvedDefaults ?? {},
51419
+ ...callSiteOverrides ?? {}
51420
+ };
51421
+ }
51422
+ return void 0;
51423
+ }
50868
51424
  function createSharedEntityWriter(binding, tick, traitStatesRef, emit) {
50869
51425
  return (scratch) => {
50870
51426
  const traitName = binding.trait.name;
@@ -51085,8 +51641,24 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
51085
51641
  }, [traitStates]);
51086
51642
  const traitSnapshotDataRef = useRef(/* @__PURE__ */ new Map());
51087
51643
  const traitFieldStatesRef = useRef(/* @__PURE__ */ new Map());
51088
- const lastCanvasRenderUiRef = useRef(/* @__PURE__ */ new Map());
51089
- const executeTransitionEffectsRef = useRef(null);
51644
+ const bridgeEchoPendingRef = useRef(/* @__PURE__ */ new Map());
51645
+ const bindingSnapshotsRef = useRef(/* @__PURE__ */ new Map());
51646
+ const bindingListenersRef = useRef(/* @__PURE__ */ new Map());
51647
+ const publishBindingSnapshot = useCallback((traitName, row) => {
51648
+ bindingSnapshotsRef.current.set(traitName, { ...row });
51649
+ const listeners7 = bindingListenersRef.current.get(traitName);
51650
+ if (!listeners7) return;
51651
+ listeners7.forEach((callback) => {
51652
+ try {
51653
+ callback();
51654
+ } catch (error) {
51655
+ stateLog.error("binding-snapshot listener error", {
51656
+ traitName,
51657
+ error: error instanceof Error ? error.message : String(error)
51658
+ });
51659
+ }
51660
+ });
51661
+ }, []);
51090
51662
  useEffect(() => {
51091
51663
  const mgr = managerRef.current;
51092
51664
  const bindings = traitBindingsRef.current;
@@ -51214,15 +51786,6 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
51214
51786
  const existing = pendingSlots.get(slot) || [];
51215
51787
  existing.push({ pattern, props: props || {} });
51216
51788
  pendingSlots.set(slot, existing);
51217
- const patternType = pattern?.type;
51218
- if (patternType !== void 0 && REACTIVE_REPAINT_PATTERN_TYPES.has(patternType)) {
51219
- const rawForSlot = effects.filter(
51220
- (e) => Array.isArray(e) && (e[0] === "render-ui" || e[0] === "render") && e[1] === slot
51221
- );
51222
- if (rawForSlot.length > 0) {
51223
- lastCanvasRenderUiRef.current.set(traitName, rawForSlot);
51224
- }
51225
- }
51226
51789
  },
51227
51790
  clearSlot: (slot) => {
51228
51791
  pendingSlots.set(slot, []);
@@ -51294,11 +51857,13 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
51294
51857
  };
51295
51858
  }
51296
51859
  const sharedWrites = [];
51860
+ let didWrite = false;
51297
51861
  const baseSet = handlers.set;
51298
51862
  handlers = {
51299
51863
  ...handlers,
51300
51864
  set: async (targetId, field, value) => {
51301
51865
  if (baseSet) await baseSet(targetId, field, value);
51866
+ didWrite = true;
51302
51867
  if (sharedKey !== void 0) {
51303
51868
  sharedWrites.push({ field, value });
51304
51869
  }
@@ -51315,23 +51880,9 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
51315
51880
  payload: payload || {},
51316
51881
  state: previousState
51317
51882
  };
51318
- const declaredDefaults = collectDeclaredConfigDefaults(binding.trait);
51319
- const resolvedDefaults = traitConfigsByName?.[traitName];
51320
- const callSiteConfig = getBindingConfig(binding);
51321
- const callSiteOverrides = callSiteConfig ? resolveCallSitePayloadCaptures(
51322
- Object.fromEntries(
51323
- Object.entries(callSiteConfig).filter(
51324
- ([, v]) => !containsConfigForward(v)
51325
- )
51326
- ),
51327
- payload || {}
51328
- ) : void 0;
51329
- if (declaredDefaults || resolvedDefaults || callSiteOverrides) {
51330
- bindingCtx.config = {
51331
- ...declaredDefaults ?? {},
51332
- ...resolvedDefaults ?? {},
51333
- ...callSiteOverrides ?? {}
51334
- };
51883
+ const renderConfig = buildTraitRenderConfig(binding, traitConfigsByName, payload || {});
51884
+ if (renderConfig !== void 0) {
51885
+ bindingCtx.config = renderConfig;
51335
51886
  }
51336
51887
  if (traitName === "Authority" || traitName === "Hero") {
51337
51888
  sharedEntityLog.debug("executeTransitionEffects config tiles", {
@@ -51365,7 +51916,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
51365
51916
  effectHeads: effects.map((e) => Array.isArray(e) ? String(e[0]) : "??")
51366
51917
  });
51367
51918
  }
51368
- const executor = new EffectExecutor({ handlers: trackingHandlers, bindings: bindingCtx, context: effectContext });
51919
+ const executor = new EffectExecutor({ handlers: trackingHandlers, bindings: bindingCtx, context: effectContext, deferRenderBindings: true });
51369
51920
  try {
51370
51921
  await executor.executeAll(effects);
51371
51922
  if (traitName === "Authority" || traitName === "Hero") {
@@ -51406,37 +51957,8 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
51406
51957
  entity: binding.linkedEntity
51407
51958
  });
51408
51959
  }
51409
- if (pendingSlots.size === 0 && effectsCallOp(effects, SHARED_ENTITY_WRITE_OPS)) {
51410
- const stashed = lastCanvasRenderUiRef.current.get(traitName);
51411
- if (stashed !== void 0 && stashed.length > 0) {
51412
- await executor.executeAll(stashed);
51413
- for (const [slot, patterns] of pendingSlots) {
51414
- flushSlot(traitName, slot, patterns, {
51415
- event: flushEvent,
51416
- state: previousState,
51417
- entity: binding.linkedEntity
51418
- });
51419
- }
51420
- }
51421
- if (sharedKey !== void 0 && executeTransitionEffectsRef.current !== null) {
51422
- for (const sibling of traitBindingsRef.current) {
51423
- const siblingName = sibling.trait.name;
51424
- if (siblingName === traitName) continue;
51425
- if (sharedKeyByTraitNameRef.current.get(siblingName) !== sharedKey) continue;
51426
- const siblingStash = lastCanvasRenderUiRef.current.get(siblingName);
51427
- if (siblingStash === void 0 || siblingStash.length === 0) continue;
51428
- const siblingState = traitStatesRef.current.get(siblingName)?.currentState ?? "";
51429
- await executeTransitionEffectsRef.current({
51430
- binding: sibling,
51431
- effects: siblingStash,
51432
- previousState: siblingState,
51433
- newState: siblingState,
51434
- flushEvent: `${flushEvent}:repaint`,
51435
- syncOnly,
51436
- log: log11
51437
- });
51438
- }
51439
- }
51960
+ if (didWrite && sharedKey === void 0) {
51961
+ publishBindingSnapshot(traitName, liveEntity);
51440
51962
  }
51441
51963
  } catch (error) {
51442
51964
  log11.error("effects:error", {
@@ -51448,10 +51970,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
51448
51970
  });
51449
51971
  }
51450
51972
  return emittedDuringExec;
51451
- }, [eventBus, flushSlot, sharedEntityStore]);
51452
- useEffect(() => {
51453
- executeTransitionEffectsRef.current = executeTransitionEffects;
51454
- }, [executeTransitionEffects]);
51973
+ }, [eventBus, flushSlot, sharedEntityStore, publishBindingSnapshot]);
51455
51974
  const runTickEffects = useCallback((tick, binding) => {
51456
51975
  const traitName = binding.trait.name;
51457
51976
  const currentState = traitStatesRef.current.get(traitName)?.currentState ?? "";
@@ -51514,24 +52033,6 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
51514
52033
  ({ binding, tick }) => createSharedEntityWriter(binding, tick, traitStatesRef, emitFromSharedWriter)
51515
52034
  );
51516
52035
  runTickFrame(group.storeKey, writers, sharedEntityStore);
51517
- const repaint = executeTransitionEffectsRef.current;
51518
- if (repaint !== null) {
51519
- for (const renderBinding of group.renderBindings) {
51520
- const renderTraitName = renderBinding.trait.name;
51521
- const stash = lastCanvasRenderUiRef.current.get(renderTraitName);
51522
- if (stash === void 0 || stash.length === 0) continue;
51523
- const renderState = traitStatesRef.current.get(renderTraitName)?.currentState ?? "";
51524
- void repaint({
51525
- binding: renderBinding,
51526
- effects: stash,
51527
- previousState: renderState,
51528
- newState: renderState,
51529
- flushEvent: "tick:repaint",
51530
- syncOnly: true,
51531
- log: sharedEntityLog
51532
- });
51533
- }
51534
- }
51535
52036
  };
51536
52037
  if (interval === "frame") {
51537
52038
  scheduler.add(0, onDue);
@@ -51602,6 +52103,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
51602
52103
  executedTraits: results.map((r2) => r2.traitName).join(",")
51603
52104
  });
51604
52105
  const emittedByTrait = /* @__PURE__ */ new Map();
52106
+ bridgeEchoPendingRef.current.clear();
51605
52107
  for (const { traitName, result } of results) {
51606
52108
  const binding = bindingMap.get(traitName);
51607
52109
  const traitState = currentManager.getState(traitName);
@@ -51656,6 +52158,12 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
51656
52158
  log: stateLog
51657
52159
  });
51658
52160
  emittedByTrait.set(traitName, emittedDuringExec);
52161
+ for (const emittedKey of emittedDuringExec) {
52162
+ bridgeEchoPendingRef.current.set(
52163
+ emittedKey,
52164
+ (bridgeEchoPendingRef.current.get(emittedKey) ?? 0) + 1
52165
+ );
52166
+ }
51659
52167
  } else if (!result.executed) {
51660
52168
  if (result.guardResult === false) {
51661
52169
  stateLog.debug("guard-blocked-transition", {
@@ -51805,8 +52313,13 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
51805
52313
  crossTraitLog.debug("self:subscribe", { traitName, busKey: selfBusKey, eventKey });
51806
52314
  const unsub = eventBus.on(selfBusKey, (event) => {
51807
52315
  if (event.source && event.source.dispatched) {
51808
- crossTraitLog.debug("self:fire-skipped-bridge-echo", { traitName, busKey: selfBusKey, eventKey });
51809
- return;
52316
+ const pendingEchoes = bridgeEchoPendingRef.current.get(eventKey) ?? 0;
52317
+ if (pendingEchoes > 0) {
52318
+ bridgeEchoPendingRef.current.set(eventKey, pendingEchoes - 1);
52319
+ crossTraitLog.debug("self:fire-skipped-bridge-echo", { traitName, busKey: selfBusKey, eventKey });
52320
+ return;
52321
+ }
52322
+ crossTraitLog.debug("self:fire-server-cascade", { traitName, busKey: selfBusKey, eventKey });
51810
52323
  }
51811
52324
  crossTraitLog.debug("self:fire", { traitName, busKey: selfBusKey, eventKey });
51812
52325
  enqueueAndDrain(eventKey, event.payload, traitName);
@@ -51898,11 +52411,47 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
51898
52411
  initedTraitsRef.current = /* @__PURE__ */ new Set();
51899
52412
  };
51900
52413
  }, [traitBindings, enqueueAndDrain]);
52414
+ const entityBindingSource = useMemo(() => ({
52415
+ getEntitySnapshot: (traitName) => {
52416
+ const sharedKey = sharedKeyByTraitNameRef.current.get(traitName);
52417
+ if (sharedKey !== void 0) {
52418
+ return sharedEntityStore.getSnapshot(sharedKey);
52419
+ }
52420
+ return bindingSnapshotsRef.current.get(traitName) ?? EMPTY_BINDING_SNAPSHOT;
52421
+ },
52422
+ getConfig: (traitName) => {
52423
+ const binding = traitBindingsRef.current.find((b) => b.trait.name === traitName);
52424
+ if (binding === void 0) return void 0;
52425
+ return buildTraitRenderConfig(binding, traitConfigsByName, {});
52426
+ },
52427
+ getState: (traitName) => traitStatesRef.current.get(traitName)?.currentState ?? "",
52428
+ subscribe: (traitName, callback) => {
52429
+ const sharedKey = sharedKeyByTraitNameRef.current.get(traitName);
52430
+ if (sharedKey !== void 0) {
52431
+ return sharedEntityStore.subscribe(sharedKey, callback);
52432
+ }
52433
+ let listeners7 = bindingListenersRef.current.get(traitName);
52434
+ if (!listeners7) {
52435
+ listeners7 = /* @__PURE__ */ new Set();
52436
+ bindingListenersRef.current.set(traitName, listeners7);
52437
+ }
52438
+ listeners7.add(callback);
52439
+ return () => {
52440
+ const current = bindingListenersRef.current.get(traitName);
52441
+ if (!current) return;
52442
+ current.delete(callback);
52443
+ if (current.size === 0) {
52444
+ bindingListenersRef.current.delete(traitName);
52445
+ }
52446
+ };
52447
+ }
52448
+ }), [sharedEntityStore, traitConfigsByName]);
51901
52449
  return {
51902
52450
  traitStates,
51903
52451
  sendEvent,
51904
52452
  getTraitState,
51905
- canHandleEvent
52453
+ canHandleEvent,
52454
+ entityBindingSource
51906
52455
  };
51907
52456
  }
51908
52457
 
@@ -51991,7 +52540,7 @@ function collectServerActiveTraits(ir, allTraits, mountedTraitNames) {
51991
52540
  }
51992
52541
  return active;
51993
52542
  }
51994
- function TraitInitializer({ traits: traits2, routeParams, orbitalNames, onNavigate, onLocalFallback, persistence, traitConfigsByName, orbitalsByTrait, embeddedTraits, serverActiveTraits }) {
52543
+ function TraitInitializer({ traits: traits2, routeParams, orbitalNames, onNavigate, onLocalFallback, persistence, traitConfigsByName, orbitalsByTrait, embeddedTraits, serverActiveTraits, children }) {
51995
52544
  const bridge = useServerBridge();
51996
52545
  const activeTraitNames = useMemo(
51997
52546
  () => new Set(traits2.map((b) => b.trait.name).filter((n) => !!n)),
@@ -52021,7 +52570,7 @@ function TraitInitializer({ traits: traits2, routeParams, orbitalNames, onNaviga
52021
52570
  }
52022
52571
  }, [bridge.connected, bridge.sendEvent, orbitalNames, uiSlots, onNavigate, embeddedTraits, activeTraitNames, withActiveTraits]);
52023
52572
  const opts = orbitalNames ? { onEventProcessed, navigate: onNavigate, traitConfigsByName, orbitalsByTrait, embeddedTraits, initPayload: routeParams } : { navigate: onNavigate, persistence, traitConfigsByName, orbitalsByTrait, embeddedTraits, initPayload: routeParams };
52024
- const { sendEvent } = useTraitStateMachine(traits2, uiSlots, opts);
52573
+ const { sendEvent, entityBindingSource } = useTraitStateMachine(traits2, uiSlots, opts);
52025
52574
  const initSentRef = useRef(false);
52026
52575
  const prevTraitsRef = useRef(void 0);
52027
52576
  const paramsKey = JSON.stringify(routeParams ?? {});
@@ -52067,7 +52616,7 @@ function TraitInitializer({ traits: traits2, routeParams, orbitalNames, onNaviga
52067
52616
  { type: "fetch", args: [], status: "executed" },
52068
52617
  ...effects.map((eff) => ({
52069
52618
  type: eff.type,
52070
- args: eff.type === "render-ui" ? [eff.slot] : [],
52619
+ args: eff.type === "render-ui" && eff.slot !== void 0 ? [eff.slot] : [],
52071
52620
  status: "executed"
52072
52621
  }))
52073
52622
  ];
@@ -52083,7 +52632,7 @@ function TraitInitializer({ traits: traits2, routeParams, orbitalNames, onNaviga
52083
52632
  }
52084
52633
  })();
52085
52634
  }, [bridge.connected, orbitalNames, bridge.sendEvent, uiSlots, onNavigate, embeddedTraits, activeTraitNames, withActiveTraits, routeParams]);
52086
- return null;
52635
+ return /* @__PURE__ */ jsx(EntityBindingContext.Provider, { value: entityBindingSource, children });
52087
52636
  }
52088
52637
  function SchemaRunner({ schema, serverUrl, transport, mockData, pageName, routeParams, onNavigate, onLocalFallback, persistence }) {
52089
52638
  const { traits: traits2, allEntities, allTraits, ir } = useResolvedSchema(schema, pageName);
@@ -52216,30 +52765,28 @@ function SchemaRunner({ schema, serverUrl, transport, mockData, pageName, routeP
52216
52765
  }
52217
52766
  return schema.orbitals[0]?.theme;
52218
52767
  }, [schema, pageName]);
52219
- const inner = /* @__PURE__ */ jsx(VerificationProvider, { enabled: true, children: /* @__PURE__ */ jsxs(
52768
+ const inner = /* @__PURE__ */ jsx(VerificationProvider, { enabled: true, children: /* @__PURE__ */ jsx(
52220
52769
  EntitySchemaProvider,
52221
52770
  {
52222
52771
  entities: entitiesArray,
52223
52772
  traitLinkedEntities: traitLinkedEntitiesMap,
52224
52773
  orbitalsByTrait: orbitalsByTraitMap,
52225
- children: [
52226
- /* @__PURE__ */ jsx(
52227
- TraitInitializer,
52228
- {
52229
- traits: allPageTraits,
52230
- routeParams,
52231
- orbitalNames: serverUrl || transport ? pageOrbitalNames : void 0,
52232
- traitConfigsByName,
52233
- orbitalsByTrait,
52234
- embeddedTraits,
52235
- serverActiveTraits,
52236
- onNavigate,
52237
- onLocalFallback,
52238
- persistence
52239
- }
52240
- ),
52241
- /* @__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 }) }) })
52242
- ]
52774
+ children: /* @__PURE__ */ jsx(
52775
+ TraitInitializer,
52776
+ {
52777
+ traits: allPageTraits,
52778
+ routeParams,
52779
+ orbitalNames: serverUrl || transport ? pageOrbitalNames : void 0,
52780
+ traitConfigsByName,
52781
+ orbitalsByTrait,
52782
+ embeddedTraits,
52783
+ serverActiveTraits,
52784
+ onNavigate,
52785
+ onLocalFallback,
52786
+ persistence,
52787
+ 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 }) }) })
52788
+ }
52789
+ )
52243
52790
  }
52244
52791
  ) });
52245
52792
  if (serverUrl || transport) {
@@ -52556,8 +53103,8 @@ function CanvasDndProvider({
52556
53103
  }) {
52557
53104
  const eventBus = useEventBus();
52558
53105
  const sensors = useAlmadarDndSensors(false);
52559
- const [activePayload, setActivePayload] = React91__default.useState(null);
52560
- const handleDragStart = React91__default.useCallback((e) => {
53106
+ const [activePayload, setActivePayload] = React92__default.useState(null);
53107
+ const handleDragStart = React92__default.useCallback((e) => {
52561
53108
  const data = e.active.data.current;
52562
53109
  const payload = data?.payload;
52563
53110
  if (payload) {
@@ -52568,7 +53115,7 @@ function CanvasDndProvider({
52568
53115
  log9.warn("dragStart:missing-payload", { id: e.active.id });
52569
53116
  }
52570
53117
  }, [eventBus]);
52571
- const handleDragEnd = React91__default.useCallback((e) => {
53118
+ const handleDragEnd = React92__default.useCallback((e) => {
52572
53119
  setActivePayload(null);
52573
53120
  const activeData = e.active.data.current;
52574
53121
  const payload = activeData?.payload;
@@ -52597,7 +53144,7 @@ function CanvasDndProvider({
52597
53144
  const suppressed = onDrop ? onDrop(drop) === true : false;
52598
53145
  if (!suppressed) defaultEmit(eventBus, drop);
52599
53146
  }, [eventBus, onDrop]);
52600
- const handleDragCancel = React91__default.useCallback(() => {
53147
+ const handleDragCancel = React92__default.useCallback(() => {
52601
53148
  setActivePayload(null);
52602
53149
  log9.info("dragCancel");
52603
53150
  }, []);
@@ -53355,7 +53902,7 @@ var OrbPreviewNodeInner = (props) => {
53355
53902
  }
53356
53903
  );
53357
53904
  };
53358
- var OrbPreviewNode = React91__default.memo(OrbPreviewNodeInner);
53905
+ var OrbPreviewNode = React92__default.memo(OrbPreviewNodeInner);
53359
53906
  OrbPreviewNode.displayName = "OrbPreviewNode";
53360
53907
  orbPreviewLog.debug("export-resolved", () => ({
53361
53908
  type: typeof OrbPreviewNode,
@@ -53460,7 +54007,7 @@ var EventFlowEdgeInner = (props) => {
53460
54007
  ) })
53461
54008
  ] });
53462
54009
  };
53463
- var EventFlowEdge = React91__default.memo(EventFlowEdgeInner);
54010
+ var EventFlowEdge = React92__default.memo(EventFlowEdgeInner);
53464
54011
  EventFlowEdge.displayName = "EventFlowEdge";
53465
54012
 
53466
54013
  // components/avl/molecules/BehaviorComposeNode.tsx
@@ -53607,7 +54154,7 @@ var BehaviorComposeNodeInner = (props) => {
53607
54154
  }
53608
54155
  );
53609
54156
  };
53610
- var BehaviorComposeNode = React91__default.memo(BehaviorComposeNodeInner);
54157
+ var BehaviorComposeNode = React92__default.memo(BehaviorComposeNodeInner);
53611
54158
  BehaviorComposeNode.displayName = "BehaviorComposeNode";
53612
54159
 
53613
54160
  // components/avl/lib/avl-behavior-compose-converter.ts
@@ -54633,7 +55180,7 @@ var TraitCardNodeInner = (props) => {
54633
55180
  }
54634
55181
  );
54635
55182
  };
54636
- var TraitCardNode = React91__default.memo(TraitCardNodeInner);
55183
+ var TraitCardNode = React92__default.memo(TraitCardNodeInner);
54637
55184
  TraitCardNode.displayName = "TraitCardNode";
54638
55185
 
54639
55186
  // components/avl/organisms/FlowCanvas.tsx
@@ -54714,7 +55261,7 @@ function FlowCanvasInner({
54714
55261
  initialOrbital
54715
55262
  );
54716
55263
  const [expandedBehaviorAlias, setExpandedBehaviorAlias] = useState(void 0);
54717
- const screenSizeUserOverrideRef = React91__default.useRef(false);
55264
+ const screenSizeUserOverrideRef = React92__default.useRef(false);
54718
55265
  const [screenSize, setScreenSize] = useState(
54719
55266
  () => typeof window === "undefined" ? "laptop" : detectScreenSize(window.innerWidth)
54720
55267
  );
@@ -55098,7 +55645,7 @@ var ZoomBreadcrumb = ({
55098
55645
  if (eventName && band === "detail") {
55099
55646
  segments.push({ icon: "\u26A1", label: eventName });
55100
55647
  }
55101
- return /* @__PURE__ */ jsx("div", { className: "absolute top-2 left-2 z-10 flex items-center gap-1 px-2 py-1 rounded-md bg-card/90 border border-border text-xs text-muted-foreground backdrop-blur-sm", children: segments.map((seg, i) => /* @__PURE__ */ jsxs(React91__default.Fragment, { children: [
55648
+ return /* @__PURE__ */ jsx("div", { className: "absolute top-2 left-2 z-10 flex items-center gap-1 px-2 py-1 rounded-md bg-card/90 border border-border text-xs text-muted-foreground backdrop-blur-sm", children: segments.map((seg, i) => /* @__PURE__ */ jsxs(React92__default.Fragment, { children: [
55102
55649
  i > 0 && /* @__PURE__ */ jsx("span", { className: "opacity-40", children: ">" }),
55103
55650
  /* @__PURE__ */ jsx("span", { className: "opacity-60", children: seg.icon }),
55104
55651
  /* @__PURE__ */ jsx("span", { children: seg.label })
@@ -55439,7 +55986,7 @@ var EventWireOverlay = ({
55439
55986
  containerW,
55440
55987
  containerH
55441
55988
  }) => {
55442
- const ids = React91__default.useMemo(() => {
55989
+ const ids = React92__default.useMemo(() => {
55443
55990
  avlOczWireId += 1;
55444
55991
  return { arrow: `avl-ocz-wire-${avlOczWireId}-arrow` };
55445
55992
  }, []);
@@ -55806,7 +56353,7 @@ var AvlOrbitalsCosmicZoom = ({
55806
56353
  borderRadius: 6,
55807
56354
  border: `1px solid ${color}`
55808
56355
  },
55809
- children: /* @__PURE__ */ jsx(HStack, { gap: "xs", align: "center", children: breadcrumbs.map((crumb, i) => /* @__PURE__ */ jsxs(React91__default.Fragment, { children: [
56356
+ children: /* @__PURE__ */ jsx(HStack, { gap: "xs", align: "center", children: breadcrumbs.map((crumb, i) => /* @__PURE__ */ jsxs(React92__default.Fragment, { children: [
55810
56357
  i > 0 && /* @__PURE__ */ jsx(Typography, { variant: "small", style: { opacity: 0.5, color }, children: "/" }),
55811
56358
  i < breadcrumbs.length - 1 ? /* @__PURE__ */ jsx(
55812
56359
  Box,