@almadar/ui 5.135.0 → 5.137.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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]);
@@ -12970,18 +13131,45 @@ function Canvas2D({
12970
13131
  }
12971
13132
  return { width: maxX + 1, height: maxY + 1 };
12972
13133
  }, [scenePositions]);
13134
+ const defaultGridFocus = useMemo(() => {
13135
+ if (isFree || projection === "side") return void 0;
13136
+ if (gridExtent.width < 2 || gridExtent.height < 2) return void 0;
13137
+ return { x: (gridExtent.width - 1) / 2, y: (gridExtent.height - 1) / 2 };
13138
+ }, [isFree, projection, gridExtent]);
12973
13139
  const baseOffsetX = useMemo(() => {
12974
13140
  if (isFree || projection === "flat" || projection === "side") return 0;
12975
13141
  return (gridExtent.height - 1) * (scaledTileWidth / 2);
12976
13142
  }, [isFree, projection, gridExtent.height, scaledTileWidth]);
13143
+ const effectiveZoom = useMemo(() => {
13144
+ if (isFree || projection === "side") return scale;
13145
+ if (!fit) {
13146
+ const z2 = TILE_WIDTH * scale * scale / nativeTileW;
13147
+ return Number.isFinite(z2) && z2 > 0 ? z2 : scale;
13148
+ }
13149
+ if (!viewportSize.width || gridExtent.width < 2 || gridExtent.height < 2) return scale;
13150
+ let boardW;
13151
+ let boardH;
13152
+ if (projection === "flat") {
13153
+ boardW = gridExtent.width * nativeTileW;
13154
+ boardH = gridExtent.height * nativeTileW;
13155
+ } else if (projection === "hex") {
13156
+ boardW = (gridExtent.width + 0.5) * nativeTileW;
13157
+ boardH = gridExtent.height * (nativeTileW / 2) * 0.75 + nativeTileW / 2;
13158
+ } else {
13159
+ boardW = (gridExtent.width + gridExtent.height) * (nativeTileW / 2);
13160
+ boardH = (gridExtent.width + gridExtent.height) * (nativeTileW / 4);
13161
+ }
13162
+ const z = Math.min(viewportSize.width * 0.85 / boardW, viewportSize.height * 0.85 / boardH);
13163
+ return Number.isFinite(z) && z > 0 ? z : scale;
13164
+ }, [isFree, projection, fit, viewportSize, gridExtent, nativeTileW, scale]);
12977
13165
  const projector = useMemo(
12978
- () => create2DProjector({ scale, baseOffsetX, layout }),
12979
- [scale, baseOffsetX, layout]
13166
+ () => create2DProjector({ tileWidth: nativeTileW, baseOffsetX, layout }),
13167
+ [nativeTileW, baseOffsetX, layout]
12980
13168
  );
12981
13169
  const unproject = useCallback((screenX, screenY) => {
12982
13170
  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]);
13171
+ return screenToIso(screenX, screenY, nativeTileW, baseOffsetX, projection);
13172
+ }, [projection, nativeTileW, baseOffsetX]);
12985
13173
  const bgUrls = useMemo(() => backgroundImage ? [backgroundImage.url] : [], [backgroundImage]);
12986
13174
  const { getImage, pendingCount: _imagePendingCount } = useImageCache(bgUrls);
12987
13175
  useEffect(() => {
@@ -13008,9 +13196,7 @@ function Canvas2D({
13008
13196
  zoomAtPoint,
13009
13197
  screenToWorld,
13010
13198
  lerpToTarget
13011
- } = useCamera({ zoom: scale });
13012
- const [atlasVersion, setAtlasVersion] = useState(0);
13013
- const bumpAtlas = useCallback(() => setAtlasVersion((v) => v + 1), []);
13199
+ } = useCamera({ zoom: effectiveZoom });
13014
13200
  const miniMapTiles = useMemo(() => {
13015
13201
  if (!showMinimap) return [];
13016
13202
  const color = MINIMAP_TERRAIN_COLORS.default;
@@ -13054,10 +13240,13 @@ function Canvas2D({
13054
13240
  }
13055
13241
  if (!drawables || drawables.length === 0) return;
13056
13242
  const cam = cameraRef.current;
13057
- if (cameraPos && dragDistance() === 0) {
13058
- const p = projector.anchorPoint(cameraPos, "center");
13059
- cam.x = p.x - viewportSize.width / 2;
13060
- cam.y = p.y - viewportSize.height / 2;
13243
+ if (camera !== "follow" && dragDistance() === 0) {
13244
+ const focus = cameraPos ?? defaultGridFocus;
13245
+ if (focus) {
13246
+ const p = projector.anchorPoint(focus, "center");
13247
+ cam.x = p.x - viewportSize.width / 2;
13248
+ cam.y = p.y - viewportSize.height / 2;
13249
+ }
13061
13250
  }
13062
13251
  const containerRect = containerRef.current?.getBoundingClientRect();
13063
13252
  const canvasRect = canvas.getBoundingClientRect();
@@ -13070,7 +13259,7 @@ function Canvas2D({
13070
13259
  const dctx = { projector, time: 0, invalidate: bumpAtlas };
13071
13260
  for (const node of drawables) paintDrawable(painter, node, dctx);
13072
13261
  painter.restore();
13073
- }, [viewportSize, backgroundImage, bgColor, drawables, projector, cameraRef, bumpAtlas, getImage]);
13262
+ }, [viewportSize, backgroundImage, bgColor, drawables, projector, cameraRef, bumpAtlas, getImage, cameraPos, defaultGridFocus, camera, dragDistance]);
13074
13263
  useEffect(() => {
13075
13264
  if (camera !== "follow" || !followTarget) return;
13076
13265
  const p = projector.anchorPoint(followTarget, "center");
@@ -13085,6 +13274,13 @@ function Canvas2D({
13085
13274
  useEffect(() => {
13086
13275
  draw();
13087
13276
  }, [_imagePendingCount, draw]);
13277
+ const userZoomedRef = useRef(false);
13278
+ useEffect(() => {
13279
+ if (userZoomedRef.current) return;
13280
+ if (cameraRef.current.zoom === effectiveZoom) return;
13281
+ cameraRef.current.zoom = effectiveZoom;
13282
+ draw();
13283
+ }, [effectiveZoom, cameraRef, draw]);
13088
13284
  useEffect(() => {
13089
13285
  draw();
13090
13286
  }, [atlasVersion, draw]);
@@ -13141,7 +13337,9 @@ function Canvas2D({
13141
13337
  if (tileLeaveEvent) eventBus.emit(`UI:${tileLeaveEvent}`, {});
13142
13338
  }, [handleMouseLeave, tileLeaveEvent, eventBus]);
13143
13339
  const applyZoom = useCallback((factor, centerX, centerY) => {
13144
- if (enableCamera) zoomAtPoint(factor, centerX, centerY, viewportSize, () => draw());
13340
+ if (!enableCamera) return;
13341
+ userZoomedRef.current = true;
13342
+ zoomAtPoint(factor, centerX, centerY, viewportSize, () => draw());
13145
13343
  }, [enableCamera, zoomAtPoint, viewportSize, draw]);
13146
13344
  const applyPanDelta = useCallback((dx, dy) => {
13147
13345
  if (enableCamera) panBy(dx, dy, () => draw());
@@ -13326,6 +13524,8 @@ function Canvas({
13326
13524
  isLoading,
13327
13525
  unitScale,
13328
13526
  showMinimap,
13527
+ fit,
13528
+ tileWidth,
13329
13529
  backgroundImage,
13330
13530
  backgroundColor,
13331
13531
  worldWidth,
@@ -13383,6 +13583,8 @@ function Canvas({
13383
13583
  projection,
13384
13584
  camera: to2DCamera(camera?.mode),
13385
13585
  ...zoom !== void 0 ? { scale: zoom } : {},
13586
+ ...fit !== void 0 ? { fit } : {},
13587
+ ...tileWidth !== void 0 ? { tileWidth } : {},
13386
13588
  ...camera?.target !== void 0 ? { followTarget: camera.target } : {},
13387
13589
  ...camera?.pos !== void 0 ? { cameraPos: camera.pos } : {},
13388
13590
  showMinimap,
@@ -13525,7 +13727,7 @@ function LinearView({
13525
13727
  /* @__PURE__ */ jsx(HStack, { className: "flex-wrap items-center", gap: "xs", children: trait.states.map((state, i) => {
13526
13728
  const isDone = i < currentIdx;
13527
13729
  const isCurrent = i === currentIdx;
13528
- return /* @__PURE__ */ jsxs(React91__default.Fragment, { children: [
13730
+ return /* @__PURE__ */ jsxs(React92__default.Fragment, { children: [
13529
13731
  i > 0 && /* @__PURE__ */ jsx(
13530
13732
  Typography,
13531
13733
  {
@@ -14060,7 +14262,7 @@ function SequenceBar({
14060
14262
  else onSlotRemove?.(index);
14061
14263
  }, [emit, slotRemoveEvent, onSlotRemove, playing]);
14062
14264
  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: [
14265
+ return /* @__PURE__ */ jsx(HStack, { className: cn("items-center", className), gap: "sm", children: paddedSlots.map((slot, i) => /* @__PURE__ */ jsxs(React92__default.Fragment, { children: [
14064
14266
  i > 0 && /* @__PURE__ */ jsx(
14065
14267
  Typography,
14066
14268
  {
@@ -14709,7 +14911,7 @@ var init_ErrorBoundary = __esm({
14709
14911
  }
14710
14912
  );
14711
14913
  };
14712
- ErrorBoundary = class extends React91__default.Component {
14914
+ ErrorBoundary = class extends React92__default.Component {
14713
14915
  constructor(props) {
14714
14916
  super(props);
14715
14917
  __publicField(this, "reset", () => {
@@ -14978,7 +15180,7 @@ var init_Container = __esm({
14978
15180
  as: Component = "div"
14979
15181
  }) => {
14980
15182
  const resolvedSize = maxWidth ?? size ?? "lg";
14981
- return React91__default.createElement(
15183
+ return React92__default.createElement(
14982
15184
  Component,
14983
15185
  {
14984
15186
  className: cn(
@@ -17116,7 +17318,7 @@ var init_CodeBlock = __esm({
17116
17318
  DIFF_STYLE_FALLBACK = { bg: "", prefix: " ", text: "text-foreground" };
17117
17319
  LINE_PROPS_FN = (n) => ({ "data-line": String(n - 1) });
17118
17320
  HIDDEN_LINE_NUMBERS = { display: "none" };
17119
- CodeBlock = React91__default.memo(
17321
+ CodeBlock = React92__default.memo(
17120
17322
  ({
17121
17323
  code: rawCode,
17122
17324
  language = "text",
@@ -17704,7 +17906,7 @@ var init_MarkdownContent = __esm({
17704
17906
  init_Box();
17705
17907
  init_CodeBlock();
17706
17908
  init_cn();
17707
- MarkdownContent = React91__default.memo(
17909
+ MarkdownContent = React92__default.memo(
17708
17910
  ({ content, direction = "ltr", className }) => {
17709
17911
  const { t: _t } = useTranslate();
17710
17912
  const safeContent = typeof content === "string" ? content : String(content ?? "");
@@ -19031,7 +19233,7 @@ var init_StateMachineView = __esm({
19031
19233
  style: { top: title ? 30 : 0 },
19032
19234
  children: [
19033
19235
  entity && /* @__PURE__ */ jsx(EntityBox, { entity, config }),
19034
- states.map((state) => renderStateNode ? /* @__PURE__ */ jsx(React91__default.Fragment, { children: renderStateNode(state, config) }, state.id) : /* @__PURE__ */ jsx(
19236
+ states.map((state) => renderStateNode ? /* @__PURE__ */ jsx(React92__default.Fragment, { children: renderStateNode(state, config) }, state.id) : /* @__PURE__ */ jsx(
19035
19237
  StateNode2,
19036
19238
  {
19037
19239
  state,
@@ -24853,8 +25055,8 @@ var init_Menu = __esm({
24853
25055
  "bottom-end": "bottom-start"
24854
25056
  };
24855
25057
  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(
25058
+ const triggerChild = React92__default.isValidElement(trigger) ? trigger : /* @__PURE__ */ jsx(Typography, { variant: "small", as: "span", children: trigger });
25059
+ const triggerElement = React92__default.cloneElement(
24858
25060
  triggerChild,
24859
25061
  {
24860
25062
  ref: triggerRef,
@@ -24949,14 +25151,14 @@ function useDataDnd(args) {
24949
25151
  const isZone = Boolean(dragGroup || accepts || sortable);
24950
25152
  const enabled = isZone || Boolean(dndRoot);
24951
25153
  const eventBus = useEventBus();
24952
- const parentRoot = React91__default.useContext(RootCtx);
25154
+ const parentRoot = React92__default.useContext(RootCtx);
24953
25155
  const isRoot = enabled && parentRoot === null;
24954
- const zoneId = React91__default.useId();
25156
+ const zoneId = React92__default.useId();
24955
25157
  const ownGroup = dragGroup ?? accepts ?? zoneId;
24956
- const [optimisticOrders, setOptimisticOrders] = React91__default.useState(() => /* @__PURE__ */ new Map());
24957
- const optimisticOrdersRef = React91__default.useRef(optimisticOrders);
25158
+ const [optimisticOrders, setOptimisticOrders] = React92__default.useState(() => /* @__PURE__ */ new Map());
25159
+ const optimisticOrdersRef = React92__default.useRef(optimisticOrders);
24958
25160
  optimisticOrdersRef.current = optimisticOrders;
24959
- const clearOptimisticOrder = React91__default.useCallback((group) => {
25161
+ const clearOptimisticOrder = React92__default.useCallback((group) => {
24960
25162
  setOptimisticOrders((prev) => {
24961
25163
  if (!prev.has(group)) return prev;
24962
25164
  const next = new Map(prev);
@@ -24981,7 +25183,7 @@ function useDataDnd(args) {
24981
25183
  const raw = it[dndItemIdField];
24982
25184
  return raw != null ? String(raw) : `__idx_${idx}`;
24983
25185
  }).join("|");
24984
- const itemIds = React91__default.useMemo(
25186
+ const itemIds = React92__default.useMemo(
24985
25187
  () => orderedItems.map((it, idx) => {
24986
25188
  const raw = it[dndItemIdField];
24987
25189
  return raw != null ? String(raw) : `__idx_${idx}`;
@@ -24992,7 +25194,7 @@ function useDataDnd(args) {
24992
25194
  const raw = it[dndItemIdField];
24993
25195
  return raw != null ? String(raw) : `__${idx}`;
24994
25196
  }).join("|");
24995
- React91__default.useEffect(() => {
25197
+ React92__default.useEffect(() => {
24996
25198
  const root = isRoot ? null : parentRoot;
24997
25199
  if (root) {
24998
25200
  root.clearOptimisticOrder(ownGroup);
@@ -25000,20 +25202,20 @@ function useDataDnd(args) {
25000
25202
  clearOptimisticOrder(ownGroup);
25001
25203
  }
25002
25204
  }, [itemsContentSig, ownGroup]);
25003
- const zonesRef = React91__default.useRef(/* @__PURE__ */ new Map());
25004
- const registerZone = React91__default.useCallback((zoneId2, meta2) => {
25205
+ const zonesRef = React92__default.useRef(/* @__PURE__ */ new Map());
25206
+ const registerZone = React92__default.useCallback((zoneId2, meta2) => {
25005
25207
  zonesRef.current.set(zoneId2, meta2);
25006
25208
  }, []);
25007
- const unregisterZone = React91__default.useCallback((zoneId2) => {
25209
+ const unregisterZone = React92__default.useCallback((zoneId2) => {
25008
25210
  zonesRef.current.delete(zoneId2);
25009
25211
  }, []);
25010
- const [activeDrag, setActiveDrag] = React91__default.useState(null);
25011
- const [overZoneGroup, setOverZoneGroup] = React91__default.useState(null);
25012
- const meta = React91__default.useMemo(
25212
+ const [activeDrag, setActiveDrag] = React92__default.useState(null);
25213
+ const [overZoneGroup, setOverZoneGroup] = React92__default.useState(null);
25214
+ const meta = React92__default.useMemo(
25013
25215
  () => ({ group: ownGroup, dropEvent, reorderEvent, positionEvent, itemIds, rawItems: items, idField: dndItemIdField }),
25014
25216
  [ownGroup, dropEvent, reorderEvent, positionEvent, itemIds, items, dndItemIdField]
25015
25217
  );
25016
- React91__default.useEffect(() => {
25218
+ React92__default.useEffect(() => {
25017
25219
  const target = isRoot ? null : parentRoot;
25018
25220
  if (!target) {
25019
25221
  zonesRef.current.set(zoneId, meta);
@@ -25032,7 +25234,7 @@ function useDataDnd(args) {
25032
25234
  }, [parentRoot, isRoot, zoneId, meta]);
25033
25235
  const sensors = useAlmadarDndSensors(true);
25034
25236
  const collisionDetection = almadarDndCollisionDetection;
25035
- const findZoneByItem = React91__default.useCallback(
25237
+ const findZoneByItem = React92__default.useCallback(
25036
25238
  (id) => {
25037
25239
  for (const z of zonesRef.current.values()) {
25038
25240
  if (z.itemIds.includes(id)) return z;
@@ -25041,7 +25243,7 @@ function useDataDnd(args) {
25041
25243
  },
25042
25244
  []
25043
25245
  );
25044
- React91__default.useCallback(
25246
+ React92__default.useCallback(
25045
25247
  (group) => {
25046
25248
  for (const z of zonesRef.current.values()) {
25047
25249
  if (z.group === group) return z;
@@ -25050,7 +25252,7 @@ function useDataDnd(args) {
25050
25252
  },
25051
25253
  []
25052
25254
  );
25053
- const handleDragEnd = React91__default.useCallback(
25255
+ const handleDragEnd = React92__default.useCallback(
25054
25256
  (event) => {
25055
25257
  const { active, over } = event;
25056
25258
  const activeIdStr = String(active.id);
@@ -25141,8 +25343,8 @@ function useDataDnd(args) {
25141
25343
  },
25142
25344
  [eventBus]
25143
25345
  );
25144
- const sortableData = React91__default.useMemo(() => ({ dndGroup: ownGroup }), [ownGroup]);
25145
- const SortableItem = React91__default.useCallback(
25346
+ const sortableData = React92__default.useMemo(() => ({ dndGroup: ownGroup }), [ownGroup]);
25347
+ const SortableItem = React92__default.useCallback(
25146
25348
  ({ id, children }) => {
25147
25349
  const {
25148
25350
  attributes,
@@ -25182,7 +25384,7 @@ function useDataDnd(args) {
25182
25384
  id: droppableId,
25183
25385
  data: sortableData
25184
25386
  });
25185
- const ctx = React91__default.useContext(RootCtx);
25387
+ const ctx = React92__default.useContext(RootCtx);
25186
25388
  const activeDrag2 = ctx?.activeDrag ?? null;
25187
25389
  const overZoneGroup2 = ctx?.overZoneGroup ?? null;
25188
25390
  const isThisZoneOver = overZoneGroup2 === ownGroup;
@@ -25197,7 +25399,7 @@ function useDataDnd(args) {
25197
25399
  showForeignPlaceholder,
25198
25400
  ctxAvailable: ctx != null
25199
25401
  });
25200
- React91__default.useEffect(() => {
25402
+ React92__default.useEffect(() => {
25201
25403
  dndLog.info("dropzone:isOver:change", { droppableId, group: ownGroup, isOver, isThisZoneOver, showForeignPlaceholder, activeDragSourceGroup: activeDrag2?.sourceGroup ?? null });
25202
25404
  }, [droppableId, isOver, isThisZoneOver, showForeignPlaceholder]);
25203
25405
  return /* @__PURE__ */ jsx(
@@ -25211,11 +25413,11 @@ function useDataDnd(args) {
25211
25413
  }
25212
25414
  );
25213
25415
  };
25214
- const rootContextValue = React91__default.useMemo(
25416
+ const rootContextValue = React92__default.useMemo(
25215
25417
  () => ({ registerZone, unregisterZone, activeDrag, overZoneGroup, optimisticOrders, clearOptimisticOrder }),
25216
25418
  [registerZone, unregisterZone, activeDrag, overZoneGroup, optimisticOrders, clearOptimisticOrder]
25217
25419
  );
25218
- const handleDragStart = React91__default.useCallback((event) => {
25420
+ const handleDragStart = React92__default.useCallback((event) => {
25219
25421
  const sourceZone = findZoneByItem(event.active.id);
25220
25422
  const rect = event.active.rect.current.initial;
25221
25423
  const height = rect?.height && rect.height > 0 ? rect.height : 64;
@@ -25234,7 +25436,7 @@ function useDataDnd(args) {
25234
25436
  isRoot
25235
25437
  });
25236
25438
  }, [findZoneByItem, isRoot, zoneId]);
25237
- const handleDragOver = React91__default.useCallback((event) => {
25439
+ const handleDragOver = React92__default.useCallback((event) => {
25238
25440
  const { active, over } = event;
25239
25441
  const overData = over?.data?.current;
25240
25442
  const overGroup = overData?.dndGroup ?? null;
@@ -25304,7 +25506,7 @@ function useDataDnd(args) {
25304
25506
  return next;
25305
25507
  });
25306
25508
  }, []);
25307
- const handleDragCancel = React91__default.useCallback((event) => {
25509
+ const handleDragCancel = React92__default.useCallback((event) => {
25308
25510
  setActiveDrag(null);
25309
25511
  setOverZoneGroup(null);
25310
25512
  dndLog.warn("dragCancel", {
@@ -25312,12 +25514,12 @@ function useDataDnd(args) {
25312
25514
  reason: "dnd-kit cancelled the drag (escape key, pointer interrupted, or external)"
25313
25515
  });
25314
25516
  }, []);
25315
- const handleDragEndWithCleanup = React91__default.useCallback((event) => {
25517
+ const handleDragEndWithCleanup = React92__default.useCallback((event) => {
25316
25518
  handleDragEnd(event);
25317
25519
  setActiveDrag(null);
25318
25520
  setOverZoneGroup(null);
25319
25521
  }, [handleDragEnd]);
25320
- const wrapContainer = React91__default.useCallback(
25522
+ const wrapContainer = React92__default.useCallback(
25321
25523
  (children) => {
25322
25524
  if (!enabled) return children;
25323
25525
  const strategy = layout === "grid" ? rectSortingStrategy : verticalListSortingStrategy;
@@ -25371,7 +25573,7 @@ var init_useDataDnd = __esm({
25371
25573
  init_useAlmadarDndCollision();
25372
25574
  init_Box();
25373
25575
  dndLog = createLogger("almadar:ui:dnd");
25374
- RootCtx = React91__default.createContext(null);
25576
+ RootCtx = React92__default.createContext(null);
25375
25577
  }
25376
25578
  });
25377
25579
  function renderIconInput(icon, props) {
@@ -25913,7 +26115,7 @@ function DataList({
25913
26115
  }) {
25914
26116
  const eventBus = useEventBus();
25915
26117
  const { t } = useTranslate();
25916
- const [visibleCount, setVisibleCount] = React91__default.useState(pageSize || Infinity);
26118
+ const [visibleCount, setVisibleCount] = React92__default.useState(pageSize || Infinity);
25917
26119
  const fieldDefs = fields ?? columns ?? [];
25918
26120
  const allDataRaw = Array.isArray(entity) ? entity : entity ? [entity] : [];
25919
26121
  const dnd = useDataDnd({
@@ -25929,14 +26131,14 @@ function DataList({
25929
26131
  dndRoot
25930
26132
  });
25931
26133
  const orderedData = dnd.orderedItems;
25932
- const allData = React91__default.useMemo(
26134
+ const allData = React92__default.useMemo(
25933
26135
  () => sortRows(orderedData, sortBy, sortDirection),
25934
26136
  [orderedData, sortBy, sortDirection]
25935
26137
  );
25936
26138
  const data = pageSize > 0 ? allData.slice(0, visibleCount) : allData;
25937
26139
  const hasMoreLocal = pageSize > 0 && visibleCount < allData.length;
25938
26140
  const hasRenderProp = typeof children === "function";
25939
- React91__default.useEffect(() => {
26141
+ React92__default.useEffect(() => {
25940
26142
  const renderItemTypeOf = typeof schemaRenderItem;
25941
26143
  const childrenTypeOf = typeof children;
25942
26144
  if (data.length > 0 && !hasRenderProp) {
@@ -26051,7 +26253,7 @@ function DataList({
26051
26253
  return v === void 0 || v === null || v === "" ? raw : String(v);
26052
26254
  };
26053
26255
  return /* @__PURE__ */ jsxs(VStack, { gap: "sm", className: cn("py-2", className), children: [
26054
- groups2.map((group, gi) => /* @__PURE__ */ jsxs(React91__default.Fragment, { children: [
26256
+ groups2.map((group, gi) => /* @__PURE__ */ jsxs(React92__default.Fragment, { children: [
26055
26257
  group.label && /* @__PURE__ */ jsx(Divider, { label: group.label, className: "my-2" }),
26056
26258
  group.items.map((itemData, index) => {
26057
26259
  const id = itemData.id || `${gi}-${index}`;
@@ -26087,7 +26289,11 @@ function DataList({
26087
26289
  metaFields.length > 0 && /* @__PURE__ */ jsx(HStack, { gap: "xs", className: "mt-1 flex-wrap", children: metaFields.map((f3) => {
26088
26290
  const v = getNestedValue(itemData, f3.name);
26089
26291
  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(
26292
+ return f3.variant === "badge" ? (
26293
+ // `format` applies here too — a boolean field badged
26294
+ // without it renders the raw "false" instead of "No".
26295
+ /* @__PURE__ */ jsx(Badge, { variant: statusVariant3(String(v)), children: formatValue2(v, f3.format) }, f3.name)
26296
+ ) : /* @__PURE__ */ jsx(
26091
26297
  Typography,
26092
26298
  {
26093
26299
  variant: "caption",
@@ -26199,7 +26405,7 @@ function DataList({
26199
26405
  if (val === void 0 || val === null) return null;
26200
26406
  return /* @__PURE__ */ jsxs(HStack, { gap: "xs", className: "items-center flex-shrink-0", children: [
26201
26407
  field.icon && renderIconInput2(field.icon, { size: "xs" }),
26202
- /* @__PURE__ */ jsx(Badge, { variant: statusVariant3(String(val)), children: String(val) })
26408
+ /* @__PURE__ */ jsx(Badge, { variant: statusVariant3(String(val)), children: formatValue2(val, field.format) })
26203
26409
  ] }, field.name);
26204
26410
  })
26205
26411
  ] }),
@@ -26246,7 +26452,7 @@ function DataList({
26246
26452
  className
26247
26453
  ),
26248
26454
  children: [
26249
- groups.map((group, gi) => /* @__PURE__ */ jsxs(React91__default.Fragment, { children: [
26455
+ groups.map((group, gi) => /* @__PURE__ */ jsxs(React92__default.Fragment, { children: [
26250
26456
  group.label && /* @__PURE__ */ jsx(Divider, { label: group.label, className: gi > 0 ? "mt-4" : "mt-0" }),
26251
26457
  group.items.map(
26252
26458
  (itemData, index) => renderItem(itemData, index, gi === groups.length - 1 && index === group.items.length - 1)
@@ -26333,7 +26539,7 @@ var init_FormSection = __esm({
26333
26539
  columns = 1,
26334
26540
  className
26335
26541
  }) => {
26336
- const [collapsed, setCollapsed] = React91__default.useState(defaultCollapsed);
26542
+ const [collapsed, setCollapsed] = React92__default.useState(defaultCollapsed);
26337
26543
  const { t } = useTranslate();
26338
26544
  const eventBus = useEventBus();
26339
26545
  const gridClass = {
@@ -26341,7 +26547,7 @@ var init_FormSection = __esm({
26341
26547
  2: "grid-cols-1 md:grid-cols-2",
26342
26548
  3: "grid-cols-1 md:grid-cols-2 lg:grid-cols-3"
26343
26549
  }[columns];
26344
- React91__default.useCallback(() => {
26550
+ React92__default.useCallback(() => {
26345
26551
  if (collapsible) {
26346
26552
  setCollapsed((prev) => !prev);
26347
26553
  eventBus.emit("UI:TOGGLE_COLLAPSE", { collapsed: !collapsed });
@@ -26438,6 +26644,182 @@ var init_FormSection = __esm({
26438
26644
  FormActions.displayName = "FormActions";
26439
26645
  }
26440
26646
  });
26647
+ var ALL_CATEGORY, MAX_RENDERED, GridPicker;
26648
+ var init_GridPicker = __esm({
26649
+ "components/core/molecules/GridPicker.tsx"() {
26650
+ "use client";
26651
+ init_cn();
26652
+ init_Input();
26653
+ init_Badge();
26654
+ init_Stack();
26655
+ ALL_CATEGORY = "__all__";
26656
+ MAX_RENDERED = 300;
26657
+ GridPicker = ({
26658
+ items,
26659
+ value,
26660
+ onChange,
26661
+ categories,
26662
+ searchPlaceholder,
26663
+ renderThumbnail,
26664
+ cellSize = 32,
26665
+ className
26666
+ }) => {
26667
+ const [search, setSearch] = useState("");
26668
+ const [activeCategory, setActiveCategory] = useState(ALL_CATEGORY);
26669
+ const gridRef = useRef(null);
26670
+ const categoryChips = useMemo(() => {
26671
+ if (categories !== void 0) return categories;
26672
+ const seen = [];
26673
+ for (const item of items) {
26674
+ if (!seen.includes(item.category)) seen.push(item.category);
26675
+ }
26676
+ return seen;
26677
+ }, [categories, items]);
26678
+ const filtered = useMemo(() => {
26679
+ const needle = search.trim().toLowerCase();
26680
+ return items.filter((item) => {
26681
+ const matchesCategory = activeCategory === ALL_CATEGORY || item.category === activeCategory;
26682
+ const matchesSearch = needle === "" || item.label.toLowerCase().includes(needle) || item.keywords !== void 0 && item.keywords.some((k) => k.toLowerCase().includes(needle));
26683
+ return matchesCategory && matchesSearch;
26684
+ });
26685
+ }, [items, search, activeCategory]);
26686
+ const visible = useMemo(() => filtered.slice(0, MAX_RENDERED), [filtered]);
26687
+ const truncated = filtered.length - visible.length;
26688
+ const select = useCallback(
26689
+ (item) => {
26690
+ onChange(item.id);
26691
+ },
26692
+ [onChange]
26693
+ );
26694
+ const handleKeyDown = useCallback(
26695
+ (e, index) => {
26696
+ const cells = gridRef.current?.querySelectorAll(
26697
+ "[data-gridpicker-cell]"
26698
+ );
26699
+ if (cells === void 0 || cells.length === 0) return;
26700
+ const columns = (() => {
26701
+ const grid = gridRef.current;
26702
+ if (grid === null) return 1;
26703
+ const style = window.getComputedStyle(grid);
26704
+ const cols = style.gridTemplateColumns.split(" ").filter(Boolean).length;
26705
+ return cols > 0 ? cols : 1;
26706
+ })();
26707
+ let next = -1;
26708
+ if (e.key === "ArrowRight") next = index + 1;
26709
+ else if (e.key === "ArrowLeft") next = index - 1;
26710
+ else if (e.key === "ArrowDown") next = index + columns;
26711
+ else if (e.key === "ArrowUp") next = index - columns;
26712
+ else if (e.key === "Enter" || e.key === " ") {
26713
+ e.preventDefault();
26714
+ select(filtered[index]);
26715
+ return;
26716
+ } else {
26717
+ return;
26718
+ }
26719
+ e.preventDefault();
26720
+ if (next >= 0 && next < cells.length) {
26721
+ cells[next].focus();
26722
+ }
26723
+ },
26724
+ [filtered, select]
26725
+ );
26726
+ return /* @__PURE__ */ jsxs(VStack, { gap: "sm", className: cn("w-full", className), children: [
26727
+ /* @__PURE__ */ jsx(
26728
+ Input,
26729
+ {
26730
+ type: "search",
26731
+ icon: "search",
26732
+ value: search,
26733
+ placeholder: searchPlaceholder,
26734
+ clearable: true,
26735
+ onClear: () => setSearch(""),
26736
+ onChange: (e) => setSearch(e.target.value)
26737
+ }
26738
+ ),
26739
+ categoryChips.length > 0 && /* @__PURE__ */ jsxs(HStack, { gap: "xs", wrap: true, children: [
26740
+ /* @__PURE__ */ jsx(
26741
+ Badge,
26742
+ {
26743
+ variant: activeCategory === ALL_CATEGORY ? "primary" : "neutral",
26744
+ size: "sm",
26745
+ role: "button",
26746
+ tabIndex: 0,
26747
+ "aria-pressed": activeCategory === ALL_CATEGORY,
26748
+ className: "cursor-pointer",
26749
+ onClick: () => setActiveCategory(ALL_CATEGORY),
26750
+ onKeyDown: (e) => {
26751
+ if (e.key === "Enter" || e.key === " ") {
26752
+ e.preventDefault();
26753
+ setActiveCategory(ALL_CATEGORY);
26754
+ }
26755
+ },
26756
+ children: "All"
26757
+ }
26758
+ ),
26759
+ categoryChips.map((category) => /* @__PURE__ */ jsx(
26760
+ Badge,
26761
+ {
26762
+ variant: activeCategory === category ? "primary" : "neutral",
26763
+ size: "sm",
26764
+ role: "button",
26765
+ tabIndex: 0,
26766
+ "aria-pressed": activeCategory === category,
26767
+ className: "cursor-pointer",
26768
+ onClick: () => setActiveCategory(category),
26769
+ onKeyDown: (e) => {
26770
+ if (e.key === "Enter" || e.key === " ") {
26771
+ e.preventDefault();
26772
+ setActiveCategory(category);
26773
+ }
26774
+ },
26775
+ children: category
26776
+ },
26777
+ category
26778
+ ))
26779
+ ] }),
26780
+ /* @__PURE__ */ jsx(
26781
+ "div",
26782
+ {
26783
+ ref: gridRef,
26784
+ role: "listbox",
26785
+ className: "grid gap-1 overflow-y-auto max-h-64 p-1",
26786
+ style: {
26787
+ gridTemplateColumns: `repeat(auto-fill, minmax(${cellSize}px, 1fr))`
26788
+ },
26789
+ children: visible.map((item, index) => {
26790
+ const selected = item.id === value;
26791
+ return /* @__PURE__ */ jsx(
26792
+ "button",
26793
+ {
26794
+ type: "button",
26795
+ role: "option",
26796
+ "aria-selected": selected,
26797
+ "aria-label": item.label,
26798
+ title: item.label,
26799
+ "data-gridpicker-cell": true,
26800
+ tabIndex: selected || value === void 0 && index === 0 ? 0 : -1,
26801
+ onClick: () => select(item),
26802
+ onKeyDown: (e) => handleKeyDown(e, index),
26803
+ className: cn(
26804
+ "flex items-center justify-center rounded-sm",
26805
+ "transition-colors hover:bg-muted",
26806
+ "focus:outline-none focus:ring-1 focus:ring-ring",
26807
+ selected && "bg-primary/10 ring-1 ring-primary"
26808
+ ),
26809
+ style: { width: cellSize, height: cellSize },
26810
+ children: renderThumbnail(item)
26811
+ },
26812
+ item.id
26813
+ );
26814
+ })
26815
+ }
26816
+ ),
26817
+ truncated > 0 && /* @__PURE__ */ jsx("div", { className: "px-1 text-xs text-muted-foreground", children: `+${truncated} more \u2014 refine your search` })
26818
+ ] });
26819
+ };
26820
+ GridPicker.displayName = "GridPicker";
26821
+ }
26822
+ });
26441
26823
  function fileIcon(name) {
26442
26824
  const ext = name.split(".").pop()?.toLowerCase() ?? "";
26443
26825
  switch (ext) {
@@ -27210,7 +27592,7 @@ var init_Flex = __esm({
27210
27592
  flexStyle.flexBasis = typeof basis === "number" ? `${basis}px` : basis;
27211
27593
  }
27212
27594
  }
27213
- return React91__default.createElement(Component, {
27595
+ return React92__default.createElement(Component, {
27214
27596
  className: cn(
27215
27597
  inline ? "inline-flex" : "flex",
27216
27598
  directionStyles[direction],
@@ -27329,7 +27711,7 @@ var init_Grid = __esm({
27329
27711
  as: Component = "div"
27330
27712
  }) => {
27331
27713
  const mergedStyle = rows ? { gridTemplateRows: `repeat(${rows}, minmax(0, 1fr))`, ...style } : style;
27332
- return React91__default.createElement(
27714
+ return React92__default.createElement(
27333
27715
  Component,
27334
27716
  {
27335
27717
  className: cn(
@@ -27466,9 +27848,16 @@ var init_Popover = __esm({
27466
27848
  position = "bottom",
27467
27849
  trigger = "click",
27468
27850
  showArrow = true,
27851
+ open,
27852
+ onOpenChange,
27469
27853
  className
27470
27854
  }) => {
27471
- const [isOpen, setIsOpen] = useState(false);
27855
+ const [uncontrolledOpen, setUncontrolledOpen] = useState(false);
27856
+ const isOpen = open !== void 0 ? open : uncontrolledOpen;
27857
+ const setIsOpen = (next) => {
27858
+ if (open === void 0) setUncontrolledOpen(next);
27859
+ onOpenChange?.(next);
27860
+ };
27472
27861
  const [triggerRect, setTriggerRect] = useState(null);
27473
27862
  const [popoverWidth, setPopoverWidth] = useState(0);
27474
27863
  const triggerRef = useRef(null);
@@ -27501,6 +27890,23 @@ var init_Popover = __esm({
27501
27890
  updatePosition();
27502
27891
  }
27503
27892
  }, [isOpen]);
27893
+ useEffect(() => {
27894
+ if (!isOpen) return;
27895
+ let raf = 0;
27896
+ let lastTop = Number.NaN;
27897
+ let lastLeft = Number.NaN;
27898
+ const track = () => {
27899
+ const rect = triggerRef.current?.getBoundingClientRect();
27900
+ if (rect && (rect.top !== lastTop || rect.left !== lastLeft)) {
27901
+ lastTop = rect.top;
27902
+ lastLeft = rect.left;
27903
+ updatePosition();
27904
+ }
27905
+ raf = requestAnimationFrame(track);
27906
+ };
27907
+ raf = requestAnimationFrame(track);
27908
+ return () => cancelAnimationFrame(raf);
27909
+ }, [isOpen]);
27504
27910
  useEffect(() => {
27505
27911
  if (!mounted) setPopoverWidth(0);
27506
27912
  }, [mounted]);
@@ -27537,9 +27943,9 @@ var init_Popover = __esm({
27537
27943
  onMouseLeave: handleClose,
27538
27944
  onPointerDown: tapTriggerProps.onPointerDown
27539
27945
  };
27540
- const childElement = React91__default.isValidElement(children) ? children : /* @__PURE__ */ jsx("span", { children });
27946
+ const childElement = React92__default.isValidElement(children) ? children : /* @__PURE__ */ jsx("span", { children });
27541
27947
  const childPointerDown = childElement.props.onPointerDown;
27542
- const triggerElement = React91__default.cloneElement(
27948
+ const triggerElement = React92__default.cloneElement(
27543
27949
  childElement,
27544
27950
  {
27545
27951
  ref: triggerRef,
@@ -28148,9 +28554,9 @@ var init_Tooltip = __esm({
28148
28554
  if (hideTimeoutRef.current) clearTimeout(hideTimeoutRef.current);
28149
28555
  };
28150
28556
  }, []);
28151
- const triggerElement = React91__default.isValidElement(children) ? children : /* @__PURE__ */ jsx("span", { children });
28557
+ const triggerElement = React92__default.isValidElement(children) ? children : /* @__PURE__ */ jsx("span", { children });
28152
28558
  const childPointerDown = triggerElement.props.onPointerDown;
28153
- const trigger = React91__default.cloneElement(triggerElement, {
28559
+ const trigger = React92__default.cloneElement(triggerElement, {
28154
28560
  ref: triggerRef,
28155
28561
  onMouseEnter: handleMouseEnter,
28156
28562
  onMouseLeave: handleMouseLeave,
@@ -28240,7 +28646,7 @@ var init_WizardProgress = __esm({
28240
28646
  children: /* @__PURE__ */ jsx("div", { className: "flex items-center gap-2", children: normalizedSteps.map((step, index) => {
28241
28647
  const isActive = index === currentStep;
28242
28648
  const isCompleted = index < currentStep;
28243
- return /* @__PURE__ */ jsxs(React91__default.Fragment, { children: [
28649
+ return /* @__PURE__ */ jsxs(React92__default.Fragment, { children: [
28244
28650
  /* @__PURE__ */ jsx(
28245
28651
  "button",
28246
28652
  {
@@ -28849,6 +29255,80 @@ var init_FlipCard = __esm({
28849
29255
  FlipCard.displayName = "FlipCard";
28850
29256
  }
28851
29257
  });
29258
+ var EMOJI_ITEMS, EmojiPicker;
29259
+ var init_EmojiPicker = __esm({
29260
+ "components/core/molecules/EmojiPicker.tsx"() {
29261
+ "use client";
29262
+ init_useEventBus();
29263
+ init_Button();
29264
+ init_GridPicker();
29265
+ init_Popover();
29266
+ EMOJI_ITEMS = (() => {
29267
+ const items = [];
29268
+ for (const name of ordered) {
29269
+ const entry = lib[name];
29270
+ if (entry === void 0 || entry.char === null || entry.char === "") continue;
29271
+ items.push({
29272
+ id: entry.char,
29273
+ label: name.replace(/_/g, " "),
29274
+ category: entry.category.replace(/_/g, " "),
29275
+ keywords: entry.keywords
29276
+ });
29277
+ }
29278
+ return items;
29279
+ })();
29280
+ EmojiPicker = ({
29281
+ pickEvent,
29282
+ position = "top",
29283
+ triggerIcon = "smile",
29284
+ triggerLabel = "Add emoji",
29285
+ className
29286
+ }) => {
29287
+ const eventBus = useEventBus();
29288
+ const [open, setOpen] = useState(false);
29289
+ const handlePick = (glyph) => {
29290
+ if (pickEvent !== void 0) {
29291
+ const payload = { emoji: glyph };
29292
+ eventBus.emit(`UI:${pickEvent}`, payload);
29293
+ }
29294
+ setOpen(false);
29295
+ };
29296
+ return /* @__PURE__ */ jsx(
29297
+ Popover,
29298
+ {
29299
+ position,
29300
+ trigger: "click",
29301
+ showArrow: false,
29302
+ open,
29303
+ onOpenChange: setOpen,
29304
+ content: /* @__PURE__ */ jsx(
29305
+ GridPicker,
29306
+ {
29307
+ items: EMOJI_ITEMS,
29308
+ onChange: handlePick,
29309
+ searchPlaceholder: "Search emoji\u2026",
29310
+ renderThumbnail: (item) => /* @__PURE__ */ jsx("span", { className: "text-xl leading-none", "aria-hidden": "true", children: item.id }),
29311
+ cellSize: 32,
29312
+ className: "w-80"
29313
+ }
29314
+ ),
29315
+ children: /* @__PURE__ */ jsx(
29316
+ Button,
29317
+ {
29318
+ variant: "ghost",
29319
+ icon: triggerIcon,
29320
+ "aria-label": triggerLabel,
29321
+ title: triggerLabel,
29322
+ className,
29323
+ "data-testid": "emoji-picker-trigger"
29324
+ }
29325
+ )
29326
+ }
29327
+ );
29328
+ };
29329
+ EmojiPicker.displayName = "EmojiPicker";
29330
+ }
29331
+ });
28852
29332
  function toISODate(d) {
28853
29333
  return d.toISOString().slice(0, 10);
28854
29334
  }
@@ -29801,12 +30281,12 @@ var init_MapView = __esm({
29801
30281
  shadowSize: [41, 41]
29802
30282
  });
29803
30283
  L.Marker.prototype.options.icon = defaultIcon;
29804
- const { useEffect: useEffect63, useRef: useRef62, useCallback: useCallback94, useState: useState97 } = React91__default;
30284
+ const { useEffect: useEffect63, useRef: useRef63, useCallback: useCallback95, useState: useState99 } = React92__default;
29805
30285
  const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
29806
30286
  const { useEventBus: useEventBus2 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
29807
30287
  function MapUpdater({ centerLat, centerLng, zoom }) {
29808
30288
  const map = useMap();
29809
- const prevRef = useRef62({ centerLat, centerLng, zoom });
30289
+ const prevRef = useRef63({ centerLat, centerLng, zoom });
29810
30290
  useEffect63(() => {
29811
30291
  const prev = prevRef.current;
29812
30292
  if (prev.centerLat !== centerLat || prev.centerLng !== centerLng || prev.zoom !== zoom) {
@@ -29846,8 +30326,8 @@ var init_MapView = __esm({
29846
30326
  showAttribution = true
29847
30327
  }) {
29848
30328
  const eventBus = useEventBus2();
29849
- const [clickedPosition, setClickedPosition] = useState97(null);
29850
- const handleMapClick = useCallback94((lat, lng) => {
30329
+ const [clickedPosition, setClickedPosition] = useState99(null);
30330
+ const handleMapClick = useCallback95((lat, lng) => {
29851
30331
  if (showClickedPin) {
29852
30332
  setClickedPosition({ lat, lng });
29853
30333
  }
@@ -29856,7 +30336,7 @@ var init_MapView = __esm({
29856
30336
  eventBus.emit(`UI:${mapClickEvent}`, { latitude: lat, longitude: lng });
29857
30337
  }
29858
30338
  }, [onMapClick, mapClickEvent, eventBus, showClickedPin]);
29859
- const handleMarkerClick = useCallback94((marker) => {
30339
+ const handleMarkerClick = useCallback95((marker) => {
29860
30340
  onMarkerClick?.(marker);
29861
30341
  if (markerClickEvent) {
29862
30342
  eventBus.emit(`UI:${markerClickEvent}`, { ...marker });
@@ -30691,6 +31171,7 @@ function TableView({
30691
31171
  fields,
30692
31172
  itemActions,
30693
31173
  maxInlineActions,
31174
+ itemClickEvent,
30694
31175
  selectable = false,
30695
31176
  selectEvent,
30696
31177
  selectedIds,
@@ -30718,8 +31199,8 @@ function TableView({
30718
31199
  }) {
30719
31200
  const eventBus = useEventBus();
30720
31201
  const { t } = useTranslate();
30721
- const [visibleCount, setVisibleCount] = React91__default.useState(pageSize > 0 ? pageSize : Infinity);
30722
- const [localSelected, setLocalSelected] = React91__default.useState(/* @__PURE__ */ new Set());
31202
+ const [visibleCount, setVisibleCount] = React92__default.useState(pageSize > 0 ? pageSize : Infinity);
31203
+ const [localSelected, setLocalSelected] = React92__default.useState(/* @__PURE__ */ new Set());
30723
31204
  const colDefs = (Array.isArray(columns) ? columns : void 0) ?? (Array.isArray(fields) ? fields : void 0) ?? [];
30724
31205
  const actionDefs = Array.isArray(itemActions) ? itemActions : [];
30725
31206
  const allDataRaw = Array.isArray(entity) ? entity : entity ? [entity] : [];
@@ -30735,13 +31216,13 @@ function TableView({
30735
31216
  dndItemIdField,
30736
31217
  dndRoot
30737
31218
  });
30738
- const ordered = dnd.orderedItems;
30739
- const data = pageSize > 0 ? ordered.slice(0, visibleCount) : ordered;
30740
- const hasMore = pageSize > 0 && visibleCount < ordered.length;
31219
+ const ordered2 = dnd.orderedItems;
31220
+ const data = pageSize > 0 ? ordered2.slice(0, visibleCount) : ordered2;
31221
+ const hasMore = pageSize > 0 && visibleCount < ordered2.length;
30741
31222
  const hasRenderProp = typeof children === "function";
30742
31223
  const idField = dndItemIdField ?? "id";
30743
31224
  const isCoarsePointer = useMediaQuery("(pointer: coarse)");
30744
- React91__default.useEffect(() => {
31225
+ React92__default.useEffect(() => {
30745
31226
  tableViewLog.debug("render", {
30746
31227
  rowCount: data.length,
30747
31228
  colCount: colDefs.length,
@@ -30790,7 +31271,15 @@ function TableView({
30790
31271
  };
30791
31272
  eventBus.emit(`UI:${action.event}`, payload);
30792
31273
  };
30793
- const colFloors = React91__default.useMemo(
31274
+ const handleRowClick = (row) => () => {
31275
+ if (!itemClickEvent) return;
31276
+ const payload = {
31277
+ id: row.id,
31278
+ row
31279
+ };
31280
+ eventBus.emit(`UI:${itemClickEvent}`, payload);
31281
+ };
31282
+ const colFloors = React92__default.useMemo(
30794
31283
  () => colDefs.map((col) => {
30795
31284
  const longest = data.reduce((widest, row) => {
30796
31285
  const cell = formatCell(asFieldValue(getNestedValue(row, col.field ?? col.key)), col.format);
@@ -30866,10 +31355,12 @@ function TableView({
30866
31355
  role: "row",
30867
31356
  "data-entity-row": true,
30868
31357
  "data-entity-id": id,
31358
+ onClick: itemClickEvent ? handleRowClick(row) : void 0,
30869
31359
  style: !hasRenderProp ? { gridTemplateColumns } : void 0,
30870
31360
  className: cn(
30871
31361
  "group items-center gap-3 transition-colors duration-fast",
30872
31362
  hasRenderProp ? "flex" : "grid",
31363
+ itemClickEvent && "cursor-pointer",
30873
31364
  lk.rowPad,
30874
31365
  lk.divider && "border-b border-[var(--color-border)]",
30875
31366
  lk.striped && index % 2 === 1 && "bg-[var(--color-surface-subtle)]",
@@ -30877,7 +31368,7 @@ function TableView({
30877
31368
  look === "bordered" && "[&>*]:border-r [&>*]:border-[var(--color-border)] [&>*:last-child]:border-r-0"
30878
31369
  ),
30879
31370
  children: [
30880
- selectable && /* @__PURE__ */ jsx(Box, { className: "flex items-center", children: /* @__PURE__ */ jsx(
31371
+ selectable && /* @__PURE__ */ jsx(Box, { className: "flex items-center", onClick: itemClickEvent ? (e) => e.stopPropagation() : void 0, children: /* @__PURE__ */ jsx(
30881
31372
  Checkbox,
30882
31373
  {
30883
31374
  checked: selected.has(id),
@@ -30902,6 +31393,7 @@ function TableView({
30902
31393
  HStack,
30903
31394
  {
30904
31395
  gap: "xs",
31396
+ onClick: itemClickEvent ? (e) => e.stopPropagation() : void 0,
30905
31397
  className: cn(
30906
31398
  // Pinned: the fixed column tracks routinely overflow the caller's
30907
31399
  // scroll container, which used to leave the actions off-screen.
@@ -30949,12 +31441,12 @@ function TableView({
30949
31441
  ]
30950
31442
  }
30951
31443
  );
30952
- return dnd.isZone ? /* @__PURE__ */ jsx(dnd.SortableItem, { id: row[idField] ?? id, children: rowInner }, id) : /* @__PURE__ */ jsx(React91__default.Fragment, { children: rowInner }, id);
31444
+ return dnd.isZone ? /* @__PURE__ */ jsx(dnd.SortableItem, { id: row[idField] ?? id, children: rowInner }, id) : /* @__PURE__ */ jsx(React92__default.Fragment, { children: rowInner }, id);
30953
31445
  };
30954
31446
  const items = Array.from(data);
30955
31447
  const groups = groupBy ? groupData2(items, groupBy) : [{ label: "", items }];
30956
31448
  let runningIndex = 0;
30957
- const body = /* @__PURE__ */ jsx(Box, { role: "rowgroup", children: groups.map((group, gi) => /* @__PURE__ */ jsxs(React91__default.Fragment, { children: [
31449
+ const body = /* @__PURE__ */ jsx(Box, { role: "rowgroup", children: groups.map((group, gi) => /* @__PURE__ */ jsxs(React92__default.Fragment, { children: [
30958
31450
  group.label && /* @__PURE__ */ jsx(Divider, { label: group.label, className: gi > 0 ? "mt-3" : "mt-0" }),
30959
31451
  group.items.map((row) => renderRow(row, runningIndex++))
30960
31452
  ] }, gi)) });
@@ -30971,7 +31463,7 @@ function TableView({
30971
31463
  /* @__PURE__ */ jsx(Icon, { name: "chevron-down", size: "xs", className: "mr-1" }),
30972
31464
  t("common.showMore"),
30973
31465
  " (",
30974
- t("common.remaining", { count: ordered.length - visibleCount }),
31466
+ t("common.remaining", { count: ordered2.length - visibleCount }),
30975
31467
  ")"
30976
31468
  ] }) })
30977
31469
  ]
@@ -32317,7 +32809,7 @@ var init_StepFlow = __esm({
32317
32809
  className
32318
32810
  }) => {
32319
32811
  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: [
32812
+ 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
32813
  /* @__PURE__ */ jsxs(VStack, { gap: "none", align: "center", children: [
32322
32814
  /* @__PURE__ */ jsx(StepCircle, { step, index }),
32323
32815
  showConnectors && index < steps.length - 1 && /* @__PURE__ */ jsx(Box, { className: "w-px h-8 bg-border" })
@@ -32328,7 +32820,7 @@ var init_StepFlow = __esm({
32328
32820
  ] })
32329
32821
  ] }) }, index)) });
32330
32822
  }
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: [
32823
+ 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
32824
  /* @__PURE__ */ jsxs(VStack, { gap: "sm", align: "center", className: "flex-1 w-full md:w-auto", children: [
32333
32825
  /* @__PURE__ */ jsx(StepCircle, { step, index }),
32334
32826
  /* @__PURE__ */ jsx(Typography, { variant: "h4", className: "text-center", children: step.title }),
@@ -33318,7 +33810,7 @@ var init_LikertScale = __esm({
33318
33810
  md: "text-base",
33319
33811
  lg: "text-lg"
33320
33812
  };
33321
- LikertScale = React91__default.forwardRef(
33813
+ LikertScale = React92__default.forwardRef(
33322
33814
  ({
33323
33815
  question,
33324
33816
  options = DEFAULT_LIKERT_OPTIONS,
@@ -33330,7 +33822,7 @@ var init_LikertScale = __esm({
33330
33822
  variant = "radios",
33331
33823
  className
33332
33824
  }, ref) => {
33333
- const groupId = React91__default.useId();
33825
+ const groupId = React92__default.useId();
33334
33826
  const eventBus = useEventBus();
33335
33827
  const handleSelect = useCallback(
33336
33828
  (next) => {
@@ -35619,7 +36111,7 @@ var init_DocBreadcrumb = __esm({
35619
36111
  "aria-label": t("aria.breadcrumb"),
35620
36112
  children: /* @__PURE__ */ jsx(HStack, { gap: "xs", align: "center", wrap: true, children: items.map((item, idx) => {
35621
36113
  const isLast = idx === items.length - 1;
35622
- return /* @__PURE__ */ jsxs(React91__default.Fragment, { children: [
36114
+ return /* @__PURE__ */ jsxs(React92__default.Fragment, { children: [
35623
36115
  idx > 0 && /* @__PURE__ */ jsx(
35624
36116
  Icon,
35625
36117
  {
@@ -36283,7 +36775,7 @@ var init_PageHeader = __esm({
36283
36775
  info: "bg-info/10 text-info"
36284
36776
  };
36285
36777
  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: [
36778
+ 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
36779
  idx > 0 && /* @__PURE__ */ jsx(Typography, { variant: "small", color: "muted", children: "/" }),
36288
36780
  crumb.href ? /* @__PURE__ */ jsx(
36289
36781
  "a",
@@ -36641,7 +37133,7 @@ var init_Section = __esm({
36641
37133
  as: Component = "section"
36642
37134
  }) => {
36643
37135
  const hasHeader = title || description || action;
36644
- return React91__default.createElement(
37136
+ return React92__default.createElement(
36645
37137
  Component,
36646
37138
  {
36647
37139
  className: cn(
@@ -37015,7 +37507,7 @@ var init_WizardContainer = __esm({
37015
37507
  const isCompleted = index < currentStep;
37016
37508
  const stepKey = step.id ?? step.tabId ?? `step-${index}`;
37017
37509
  const stepTitle = step.title ?? step.name ?? `Step ${index + 1}`;
37018
- return /* @__PURE__ */ jsxs(React91__default.Fragment, { children: [
37510
+ return /* @__PURE__ */ jsxs(React92__default.Fragment, { children: [
37019
37511
  /* @__PURE__ */ jsx(
37020
37512
  Button,
37021
37513
  {
@@ -38802,7 +39294,7 @@ var init_ImportPreviewTree = __esm({
38802
39294
  const renderUnit = (unit, childrenByParent, depth) => {
38803
39295
  const summary = fieldSummary(unit);
38804
39296
  const children = childrenByParent.get(unit.ref) ?? [];
38805
- return /* @__PURE__ */ jsxs(React91__default.Fragment, { children: [
39297
+ return /* @__PURE__ */ jsxs(React92__default.Fragment, { children: [
38806
39298
  /* @__PURE__ */ jsxs(
38807
39299
  Box,
38808
39300
  {
@@ -38899,7 +39391,7 @@ var init_ImportProgress = __esm({
38899
39391
  PIPELINE.map((key, index) => {
38900
39392
  const isComplete = index < currentIndex;
38901
39393
  const isActive = index === currentIndex;
38902
- return /* @__PURE__ */ jsxs(React91__default.Fragment, { children: [
39394
+ return /* @__PURE__ */ jsxs(React92__default.Fragment, { children: [
38903
39395
  index > 0 ? /* @__PURE__ */ jsx(Box, { className: "h-px w-4 bg-border" }) : null,
38904
39396
  /* @__PURE__ */ jsxs(Box, { className: "flex items-center gap-1", "data-testid": `import-progress-step-${key}`, children: [
38905
39397
  /* @__PURE__ */ jsx(
@@ -40012,7 +40504,7 @@ var init_DrawGroup = __esm({
40012
40504
  }
40013
40505
  });
40014
40506
  function extractTitle(children) {
40015
- if (!React91__default.isValidElement(children)) return void 0;
40507
+ if (!React92__default.isValidElement(children)) return void 0;
40016
40508
  const props = children.props;
40017
40509
  if (typeof props.title === "string") {
40018
40510
  return props.title;
@@ -40362,12 +40854,12 @@ var init_Form = __esm({
40362
40854
  const isSchemaEntity = isOrbitalEntitySchema(entity);
40363
40855
  const resolvedEntity = isSchemaEntity ? entity : void 0;
40364
40856
  const entityName = typeof entity === "string" ? entity : resolvedEntity?.name;
40365
- const normalizedInitialData = React91__default.useMemo(() => {
40857
+ const normalizedInitialData = React92__default.useMemo(() => {
40366
40858
  const entityRowAsInitial = isPlainEntityRow(entity) ? entity : void 0;
40367
40859
  const callerInitial = initialData !== null && typeof initialData === "object" && !Array.isArray(initialData) ? initialData : {};
40368
40860
  return entityRowAsInitial !== void 0 ? { ...entityRowAsInitial, ...callerInitial } : callerInitial;
40369
40861
  }, [entity, initialData]);
40370
- const entityDerivedFields = React91__default.useMemo(() => {
40862
+ const entityDerivedFields = React92__default.useMemo(() => {
40371
40863
  if (fields && fields.length > 0) return void 0;
40372
40864
  if (!resolvedEntity) return void 0;
40373
40865
  return resolvedEntity.fields.map(
@@ -40388,16 +40880,16 @@ var init_Form = __esm({
40388
40880
  const conditionalFields = typeof conditionalFieldsRaw === "boolean" ? {} : conditionalFieldsRaw;
40389
40881
  const hiddenCalculations = typeof hiddenCalculationsRaw === "boolean" ? [] : hiddenCalculationsRaw;
40390
40882
  const violationTriggers = typeof violationTriggersRaw === "boolean" ? [] : violationTriggersRaw;
40391
- const [formData, setFormData] = React91__default.useState(
40883
+ const [formData, setFormData] = React92__default.useState(
40392
40884
  normalizedInitialData
40393
40885
  );
40394
- const [collapsedSections, setCollapsedSections] = React91__default.useState(
40886
+ const [collapsedSections, setCollapsedSections] = React92__default.useState(
40395
40887
  /* @__PURE__ */ new Set()
40396
40888
  );
40397
- const [submitError, setSubmitError] = React91__default.useState(null);
40398
- const formRef = React91__default.useRef(null);
40889
+ const [submitError, setSubmitError] = React92__default.useState(null);
40890
+ const formRef = React92__default.useRef(null);
40399
40891
  const formMode = props.mode;
40400
- const mountedRef = React91__default.useRef(false);
40892
+ const mountedRef = React92__default.useRef(false);
40401
40893
  if (!mountedRef.current) {
40402
40894
  mountedRef.current = true;
40403
40895
  debug("forms", "mount", {
@@ -40410,7 +40902,7 @@ var init_Form = __esm({
40410
40902
  });
40411
40903
  }
40412
40904
  const shouldShowCancel = showCancel ?? (fields && fields.length > 0);
40413
- const evalContext = React91__default.useMemo(
40905
+ const evalContext = React92__default.useMemo(
40414
40906
  () => ({
40415
40907
  formValues: formData,
40416
40908
  globalVariables: externalContext?.globalVariables ?? {},
@@ -40419,7 +40911,7 @@ var init_Form = __esm({
40419
40911
  }),
40420
40912
  [formData, externalContext]
40421
40913
  );
40422
- React91__default.useEffect(() => {
40914
+ React92__default.useEffect(() => {
40423
40915
  debug("forms", "initialData-sync", {
40424
40916
  mode: formMode,
40425
40917
  normalizedInitialData,
@@ -40430,7 +40922,7 @@ var init_Form = __esm({
40430
40922
  setFormData(normalizedInitialData);
40431
40923
  }
40432
40924
  }, [normalizedInitialData]);
40433
- const processCalculations = React91__default.useCallback(
40925
+ const processCalculations = React92__default.useCallback(
40434
40926
  (changedFieldId, newFormData) => {
40435
40927
  if (!hiddenCalculations.length) return;
40436
40928
  const context = {
@@ -40455,7 +40947,7 @@ var init_Form = __esm({
40455
40947
  },
40456
40948
  [hiddenCalculations, externalContext, eventBus]
40457
40949
  );
40458
- const checkViolations = React91__default.useCallback(
40950
+ const checkViolations = React92__default.useCallback(
40459
40951
  (changedFieldId, newFormData) => {
40460
40952
  if (!violationTriggers.length) return;
40461
40953
  const context = {
@@ -40493,7 +40985,7 @@ var init_Form = __esm({
40493
40985
  processCalculations(name, newFormData);
40494
40986
  checkViolations(name, newFormData);
40495
40987
  };
40496
- const isFieldVisible = React91__default.useCallback(
40988
+ const isFieldVisible = React92__default.useCallback(
40497
40989
  (fieldName) => {
40498
40990
  const condition = conditionalFields[fieldName];
40499
40991
  if (!condition) return true;
@@ -40501,7 +40993,7 @@ var init_Form = __esm({
40501
40993
  },
40502
40994
  [conditionalFields, evalContext]
40503
40995
  );
40504
- const isSectionVisible = React91__default.useCallback(
40996
+ const isSectionVisible = React92__default.useCallback(
40505
40997
  (section) => {
40506
40998
  if (!section.condition) return true;
40507
40999
  return Boolean(evaluateFormExpression(section.condition, evalContext));
@@ -40577,7 +41069,7 @@ var init_Form = __esm({
40577
41069
  eventBus.emit(`UI:${onCancel}`);
40578
41070
  }
40579
41071
  };
40580
- const renderField = React91__default.useCallback(
41072
+ const renderField = React92__default.useCallback(
40581
41073
  (field) => {
40582
41074
  const fieldName = field.name || field.field;
40583
41075
  if (!fieldName) return null;
@@ -40598,7 +41090,7 @@ var init_Form = __esm({
40598
41090
  [formData, isFieldVisible, relationsData, relationsLoading, isLoading]
40599
41091
  );
40600
41092
  const effectiveFields = entityDerivedFields ?? fields;
40601
- const normalizedFields = React91__default.useMemo(() => {
41093
+ const normalizedFields = React92__default.useMemo(() => {
40602
41094
  if (!effectiveFields || effectiveFields.length === 0) return [];
40603
41095
  return effectiveFields.map((field) => {
40604
41096
  if (typeof field === "string") {
@@ -40622,7 +41114,7 @@ var init_Form = __esm({
40622
41114
  return field;
40623
41115
  });
40624
41116
  }, [effectiveFields, resolvedEntity]);
40625
- const schemaFields = React91__default.useMemo(() => {
41117
+ const schemaFields = React92__default.useMemo(() => {
40626
41118
  if (normalizedFields.length === 0) return null;
40627
41119
  if (isDebugEnabled()) {
40628
41120
  debugGroup(`Form: ${entityName || "unknown"}`);
@@ -40632,7 +41124,7 @@ var init_Form = __esm({
40632
41124
  }
40633
41125
  return normalizedFields.map(renderField).filter(Boolean);
40634
41126
  }, [normalizedFields, renderField, entityName, conditionalFields]);
40635
- const sectionElements = React91__default.useMemo(() => {
41127
+ const sectionElements = React92__default.useMemo(() => {
40636
41128
  if (!sections || sections.length === 0) return null;
40637
41129
  return sections.map((section) => {
40638
41130
  if (!isSectionVisible(section)) {
@@ -41358,7 +41850,7 @@ var init_List = __esm({
41358
41850
  if (entity && typeof entity === "object" && "id" in entity) return [entity];
41359
41851
  return [];
41360
41852
  }, [entity]);
41361
- const getItemActions = React91__default.useCallback(
41853
+ const getItemActions = React92__default.useCallback(
41362
41854
  (item) => {
41363
41855
  if (!itemActions) return [];
41364
41856
  if (typeof itemActions === "function") {
@@ -41839,7 +42331,7 @@ var init_MediaGallery = __esm({
41839
42331
  [selectable, selectedItems, selectionEvent, eventBus]
41840
42332
  );
41841
42333
  const entityData = Array.isArray(entity) ? entity : [];
41842
- const items = React91__default.useMemo(() => {
42334
+ const items = React92__default.useMemo(() => {
41843
42335
  if (propItems && propItems.length > 0) return propItems;
41844
42336
  if (entityData.length === 0) return [];
41845
42337
  return entityData.map((record, idx) => {
@@ -42004,7 +42496,7 @@ var init_MediaGallery = __esm({
42004
42496
  }
42005
42497
  });
42006
42498
  function extractTitle2(children) {
42007
- if (!React91__default.isValidElement(children)) return void 0;
42499
+ if (!React92__default.isValidElement(children)) return void 0;
42008
42500
  const props = children.props;
42009
42501
  if (typeof props.title === "string") {
42010
42502
  return props.title;
@@ -42278,7 +42770,7 @@ var init_debugRegistry = __esm({
42278
42770
  }
42279
42771
  });
42280
42772
  function useDebugData() {
42281
- const [data, setData] = React91.useState(() => ({
42773
+ const [data, setData] = React92.useState(() => ({
42282
42774
  traits: [],
42283
42775
  ticks: [],
42284
42776
  guards: [],
@@ -42292,7 +42784,7 @@ function useDebugData() {
42292
42784
  },
42293
42785
  lastUpdate: Date.now()
42294
42786
  }));
42295
- React91.useEffect(() => {
42787
+ React92.useEffect(() => {
42296
42788
  const updateData = () => {
42297
42789
  setData({
42298
42790
  traits: getAllTraits(),
@@ -42401,12 +42893,12 @@ function layoutGraph(states, transitions, initialState, width, height) {
42401
42893
  return positions;
42402
42894
  }
42403
42895
  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(() => {
42896
+ const [walkStep, setWalkStep] = React92.useState(null);
42897
+ const [traits2, setTraits] = React92.useState([]);
42898
+ const [coveredEdges, setCoveredEdges] = React92.useState([]);
42899
+ const [completedTraits, setCompletedTraits] = React92.useState(/* @__PURE__ */ new Set());
42900
+ const prevTraitRef = React92.useRef(null);
42901
+ React92.useEffect(() => {
42410
42902
  const interval = setInterval(() => {
42411
42903
  const w = window;
42412
42904
  const step = w.__orbitalWalkStep;
@@ -42842,15 +43334,15 @@ var init_EntitiesTab = __esm({
42842
43334
  });
42843
43335
  function EventFlowTab({ events: events2 }) {
42844
43336
  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(() => {
43337
+ const [filter, setFilter] = React92.useState("all");
43338
+ const containerRef = React92.useRef(null);
43339
+ const [autoScroll, setAutoScroll] = React92.useState(true);
43340
+ React92.useEffect(() => {
42849
43341
  if (autoScroll && containerRef.current) {
42850
43342
  containerRef.current.scrollTop = containerRef.current.scrollHeight;
42851
43343
  }
42852
43344
  }, [events2.length, autoScroll]);
42853
- const filteredEvents = React91.useMemo(() => {
43345
+ const filteredEvents = React92.useMemo(() => {
42854
43346
  if (filter === "all") return events2;
42855
43347
  return events2.filter((e) => e.type === filter);
42856
43348
  }, [events2, filter]);
@@ -42966,7 +43458,7 @@ var init_EventFlowTab = __esm({
42966
43458
  });
42967
43459
  function GuardsPanel({ guards }) {
42968
43460
  const { t } = useTranslate();
42969
- const [filter, setFilter] = React91.useState("all");
43461
+ const [filter, setFilter] = React92.useState("all");
42970
43462
  if (guards.length === 0) {
42971
43463
  return /* @__PURE__ */ jsx(
42972
43464
  EmptyState,
@@ -42979,7 +43471,7 @@ function GuardsPanel({ guards }) {
42979
43471
  }
42980
43472
  const passedCount = guards.filter((g) => g.result).length;
42981
43473
  const failedCount = guards.length - passedCount;
42982
- const filteredGuards = React91.useMemo(() => {
43474
+ const filteredGuards = React92.useMemo(() => {
42983
43475
  if (filter === "all") return guards;
42984
43476
  if (filter === "passed") return guards.filter((g) => g.result);
42985
43477
  return guards.filter((g) => !g.result);
@@ -43142,10 +43634,10 @@ function EffectBadge({ effect }) {
43142
43634
  }
43143
43635
  function TransitionTimeline({ transitions }) {
43144
43636
  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(() => {
43637
+ const containerRef = React92.useRef(null);
43638
+ const [autoScroll, setAutoScroll] = React92.useState(true);
43639
+ const [expandedId, setExpandedId] = React92.useState(null);
43640
+ React92.useEffect(() => {
43149
43641
  if (autoScroll && containerRef.current) {
43150
43642
  containerRef.current.scrollTop = containerRef.current.scrollHeight;
43151
43643
  }
@@ -43425,9 +43917,9 @@ function getAllEvents(traits2) {
43425
43917
  function EventDispatcherTab({ traits: traits2, schema }) {
43426
43918
  const eventBus = useEventBus();
43427
43919
  const { t } = useTranslate();
43428
- const [log11, setLog] = React91.useState([]);
43429
- const prevStatesRef = React91.useRef(/* @__PURE__ */ new Map());
43430
- React91.useEffect(() => {
43920
+ const [log11, setLog] = React92.useState([]);
43921
+ const prevStatesRef = React92.useRef(/* @__PURE__ */ new Map());
43922
+ React92.useEffect(() => {
43431
43923
  for (const trait of traits2) {
43432
43924
  const prev = prevStatesRef.current.get(trait.id);
43433
43925
  if (prev && prev !== trait.currentState) {
@@ -43596,10 +44088,10 @@ function VerifyModePanel({
43596
44088
  localCount
43597
44089
  }) {
43598
44090
  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(() => {
44091
+ const [expanded, setExpanded] = React92.useState(true);
44092
+ const scrollRef = React92.useRef(null);
44093
+ const prevCountRef = React92.useRef(0);
44094
+ React92.useEffect(() => {
43603
44095
  if (expanded && transitions.length > prevCountRef.current && scrollRef.current) {
43604
44096
  scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
43605
44097
  }
@@ -43656,10 +44148,10 @@ function RuntimeDebugger({
43656
44148
  schema
43657
44149
  }) {
43658
44150
  const { t } = useTranslate();
43659
- const [isCollapsed, setIsCollapsed] = React91.useState(mode === "verify" ? true : defaultCollapsed);
43660
- const [isVisible, setIsVisible] = React91.useState(mode === "inline" || mode === "verify" || isDebugEnabled2());
44151
+ const [isCollapsed, setIsCollapsed] = React92.useState(mode === "verify" ? true : defaultCollapsed);
44152
+ const [isVisible, setIsVisible] = React92.useState(mode === "inline" || mode === "verify" || isDebugEnabled2());
43661
44153
  const debugData = useDebugData();
43662
- React91.useEffect(() => {
44154
+ React92.useEffect(() => {
43663
44155
  if (mode === "inline") return;
43664
44156
  return onDebugToggle((enabled) => {
43665
44157
  setIsVisible(enabled);
@@ -43668,7 +44160,7 @@ function RuntimeDebugger({
43668
44160
  }
43669
44161
  });
43670
44162
  }, [mode]);
43671
- React91.useEffect(() => {
44163
+ React92.useEffect(() => {
43672
44164
  if (mode === "inline") return;
43673
44165
  const handleKeyDown = (e) => {
43674
44166
  if (e.key === "`" && isVisible) {
@@ -44188,7 +44680,7 @@ var init_StatCard = __esm({
44188
44680
  const labelToUse = propLabel ?? propTitle;
44189
44681
  const eventBus = useEventBus();
44190
44682
  const { t } = useTranslate();
44191
- const handleActionClick = React91__default.useCallback(() => {
44683
+ const handleActionClick = React92__default.useCallback(() => {
44192
44684
  if (action?.event) {
44193
44685
  eventBus.emit(`UI:${action.event}`, {});
44194
44686
  }
@@ -44199,7 +44691,7 @@ var init_StatCard = __esm({
44199
44691
  const data = Array.isArray(entity) ? entity : entity ? [entity] : [];
44200
44692
  const isLoading = externalLoading ?? false;
44201
44693
  const error = externalError;
44202
- const computeMetricValue = React91__default.useCallback(
44694
+ const computeMetricValue = React92__default.useCallback(
44203
44695
  (metric, items) => {
44204
44696
  if (metric.value !== void 0) {
44205
44697
  return metric.value;
@@ -44238,7 +44730,7 @@ var init_StatCard = __esm({
44238
44730
  },
44239
44731
  []
44240
44732
  );
44241
- const schemaStats = React91__default.useMemo(() => {
44733
+ const schemaStats = React92__default.useMemo(() => {
44242
44734
  if (!metrics || metrics.length === 0) return null;
44243
44735
  return metrics.map((metric) => ({
44244
44736
  label: metric.label,
@@ -44246,7 +44738,7 @@ var init_StatCard = __esm({
44246
44738
  format: metric.format
44247
44739
  }));
44248
44740
  }, [metrics, data, computeMetricValue]);
44249
- const calculatedTrend = React91__default.useMemo(() => {
44741
+ const calculatedTrend = React92__default.useMemo(() => {
44250
44742
  if (manualTrend !== void 0) return manualTrend;
44251
44743
  if (previousValue === void 0 || currentValue === void 0)
44252
44744
  return void 0;
@@ -44886,8 +45378,8 @@ var init_SubagentTracePanel = __esm({
44886
45378
  ] });
44887
45379
  };
44888
45380
  InlineActivityStream = ({ activities, autoScroll = true, className }) => {
44889
- const endRef = React91__default.useRef(null);
44890
- React91__default.useEffect(() => {
45381
+ const endRef = React92__default.useRef(null);
45382
+ React92__default.useEffect(() => {
44891
45383
  if (!autoScroll) return;
44892
45384
  endRef.current?.scrollIntoView({ behavior: "smooth", block: "end" });
44893
45385
  }, [activities.length, autoScroll]);
@@ -44981,7 +45473,7 @@ var init_SubagentTracePanel = __esm({
44981
45473
  };
44982
45474
  SubagentRichCard = ({ subagent }) => {
44983
45475
  const { t } = useTranslate();
44984
- const activities = React91__default.useMemo(
45476
+ const activities = React92__default.useMemo(
44985
45477
  () => subagentMessagesToActivities(subagent.messages),
44986
45478
  [subagent.messages]
44987
45479
  );
@@ -45058,8 +45550,8 @@ var init_SubagentTracePanel = __esm({
45058
45550
  ] });
45059
45551
  };
45060
45552
  CoordinatorConversation = ({ messages, autoScroll = true, className }) => {
45061
- const endRef = React91__default.useRef(null);
45062
- React91__default.useEffect(() => {
45553
+ const endRef = React92__default.useRef(null);
45554
+ React92__default.useEffect(() => {
45063
45555
  if (!autoScroll) return;
45064
45556
  endRef.current?.scrollIntoView({ behavior: "smooth", block: "end" });
45065
45557
  }, [messages.length, autoScroll]);
@@ -45494,7 +45986,7 @@ var init_Timeline = __esm({
45494
45986
  }) => {
45495
45987
  const { t } = useTranslate();
45496
45988
  const entityData = entity ?? [];
45497
- const items = React91__default.useMemo(() => {
45989
+ const items = React92__default.useMemo(() => {
45498
45990
  if (propItems) return propItems;
45499
45991
  if (entityData.length === 0) return [];
45500
45992
  return entityData.map((record, idx) => {
@@ -45596,7 +46088,7 @@ var init_Timeline = __esm({
45596
46088
  }
45597
46089
  });
45598
46090
  function extractToastProps(children) {
45599
- if (!React91__default.isValidElement(children)) {
46091
+ if (!React92__default.isValidElement(children)) {
45600
46092
  if (typeof children === "string") {
45601
46093
  return { message: children };
45602
46094
  }
@@ -45638,7 +46130,7 @@ var init_ToastSlot = __esm({
45638
46130
  eventBus.emit(`${prefix}CLOSE`);
45639
46131
  };
45640
46132
  if (!isVisible) return null;
45641
- const isCustomContent = React91__default.isValidElement(children) && !message;
46133
+ const isCustomContent = React92__default.isValidElement(children) && !message;
45642
46134
  return /* @__PURE__ */ jsx(Box, { className: "fixed bottom-4 right-4 z-50", children: isCustomContent ? children : /* @__PURE__ */ jsx(
45643
46135
  Toast,
45644
46136
  {
@@ -45743,6 +46235,7 @@ var init_component_registry_generated = __esm({
45743
46235
  init_Drawer();
45744
46236
  init_DrawerSlot();
45745
46237
  init_EdgeDecoration();
46238
+ init_EmojiPicker();
45746
46239
  init_EmptyState();
45747
46240
  init_ErrorBoundary();
45748
46241
  init_ErrorState();
@@ -46010,6 +46503,7 @@ var init_component_registry_generated = __esm({
46010
46503
  "Drawer": Drawer,
46011
46504
  "DrawerSlot": DrawerSlot,
46012
46505
  "EdgeDecoration": EdgeDecoration,
46506
+ "EmojiPicker": EmojiPicker,
46013
46507
  "EmptyState": EmptyState,
46014
46508
  "ErrorBoundary": ErrorBoundary,
46015
46509
  "ErrorState": ErrorState,
@@ -46209,7 +46703,7 @@ function SuspenseConfigProvider({
46209
46703
  config,
46210
46704
  children
46211
46705
  }) {
46212
- return React91__default.createElement(
46706
+ return React92__default.createElement(
46213
46707
  SuspenseConfigContext.Provider,
46214
46708
  { value: config },
46215
46709
  children
@@ -46251,7 +46745,7 @@ function enrichFormFields(fields, entityDef) {
46251
46745
  }
46252
46746
  return { name: field, label: humanizeFieldName(field) };
46253
46747
  }
46254
- if (field && typeof field === "object" && !Array.isArray(field) && !React91__default.isValidElement(field) && !(field instanceof Date)) {
46748
+ if (field && typeof field === "object" && !Array.isArray(field) && !React92__default.isValidElement(field) && !(field instanceof Date)) {
46255
46749
  const obj = field;
46256
46750
  const fieldName = typeof obj.name === "string" ? obj.name : typeof obj.field === "string" ? obj.field : void 0;
46257
46751
  if (!fieldName) return field;
@@ -46437,7 +46931,19 @@ function UISlotComponent({
46437
46931
  const suspenseConfig = useContext(SuspenseConfigContext);
46438
46932
  const contained = useContext(SlotContainedContext);
46439
46933
  const schemaCtx = useEntitySchemaOptional();
46440
- const content = slots[slot];
46934
+ const rawContent = slots[slot];
46935
+ const binding = useEntityBindingSnapshot(rawContent?.sourceTrait);
46936
+ const content = useMemo(() => {
46937
+ if (!rawContent) return rawContent;
46938
+ const resolvedProps = resolveRenderBindingMarkers(
46939
+ rawContent.props,
46940
+ rawContent.sourceTrait,
46941
+ binding.entity,
46942
+ binding.config,
46943
+ binding.state
46944
+ );
46945
+ return resolvedProps === rawContent.props ? rawContent : { ...rawContent, props: resolvedProps };
46946
+ }, [rawContent, binding.entity, binding.config, binding.state]);
46441
46947
  if (children !== void 0) {
46442
46948
  if (pattern === "clear") {
46443
46949
  return null;
@@ -46711,7 +47217,7 @@ function renderPatternChildren(children, onDismiss, parentId = "root", parentPat
46711
47217
  const key = `${parentId}-${index}-trait:${traitName}`;
46712
47218
  return /* @__PURE__ */ jsx(TraitFrame, { traitName }, key);
46713
47219
  }
46714
- return /* @__PURE__ */ jsx(React91__default.Fragment, { children: child }, `${parentId}-${index}`);
47220
+ return /* @__PURE__ */ jsx(React92__default.Fragment, { children: child }, `${parentId}-${index}`);
46715
47221
  }
46716
47222
  if (!child || typeof child !== "object") return null;
46717
47223
  const childId = `${parentId}-${index}`;
@@ -46768,19 +47274,20 @@ function isPatternConfig(value) {
46768
47274
  if (value === null || value === void 0) return false;
46769
47275
  if (typeof value !== "object") return false;
46770
47276
  if (Array.isArray(value)) return false;
46771
- if (React91__default.isValidElement(value)) return false;
47277
+ if (React92__default.isValidElement(value)) return false;
46772
47278
  if (value instanceof Date) return false;
46773
47279
  if (typeof value === "function") return false;
46774
47280
  const record = value;
46775
47281
  return "type" in record && typeof record.type === "string" && getComponentForPattern$1(record.type) !== null;
46776
47282
  }
46777
47283
  function isPlainConfigObject(value) {
46778
- if (React91__default.isValidElement(value)) return false;
47284
+ if (React92__default.isValidElement(value)) return false;
46779
47285
  if (value instanceof Date) return false;
46780
47286
  const proto = Object.getPrototypeOf(value);
46781
47287
  return proto === Object.prototype || proto === null;
46782
47288
  }
46783
47289
  function substituteTraitRefsDeep(value, pathKey) {
47290
+ if (isRenderBindingMarker(value)) return value;
46784
47291
  if (typeof value === "string") {
46785
47292
  const match = TRAIT_BINDING_RE.exec(value);
46786
47293
  if (match) {
@@ -46853,7 +47360,14 @@ function SlotContentRenderer({
46853
47360
  onDismiss,
46854
47361
  patternPath
46855
47362
  }) {
46856
- const entityProp = content.props.entity;
47363
+ const ambientScope = useTraitScope();
47364
+ const bindingTrait = content.sourceTrait ?? ambientScope?.trait;
47365
+ const binding = useEntityBindingSnapshot(bindingTrait);
47366
+ const liveProps = useMemo(
47367
+ () => resolveRenderBindingMarkers(content.props, bindingTrait, binding.entity, binding.config, binding.state),
47368
+ [content.props, bindingTrait, binding.entity, binding.config, binding.state]
47369
+ );
47370
+ const entityProp = liveProps.entity;
46857
47371
  if (content.pattern === "form-section") {
46858
47372
  slotLog.debug("SlotContentRenderer:form-section-render", {
46859
47373
  contentId: content.id,
@@ -46884,7 +47398,7 @@ function SlotContentRenderer({
46884
47398
  const orbitalName = schemaCtx && content.sourceTrait !== void 0 ? schemaCtx.orbitalsByTrait.get(content.sourceTrait) : void 0;
46885
47399
  const PatternComponent = getComponentForPattern(content.pattern);
46886
47400
  if (PatternComponent) {
46887
- const childrenConfig = content.props.children;
47401
+ const childrenConfig = liveProps.children;
46888
47402
  const isSingleChild = typeof childrenConfig === "string" || typeof childrenConfig === "object" && childrenConfig !== null && !Array.isArray(childrenConfig) && "type" in childrenConfig;
46889
47403
  const hasChildren = PATTERNS_WITH_CHILDREN.has(content.pattern) || Array.isArray(childrenConfig) && childrenConfig.length > 0 || isSingleChild;
46890
47404
  const isDrawHost = isDrawHostPattern(content.pattern);
@@ -46895,15 +47409,15 @@ function SlotContentRenderer({
46895
47409
  fromState: content.fromState,
46896
47410
  entity: content.entity
46897
47411
  }) : void 0;
46898
- const incomingChildren = content.props.children;
47412
+ const incomingChildren = liveProps.children;
46899
47413
  const childrenIsRenderFn = typeof incomingChildren === "function";
46900
- const { children: _childrenConfig, ...restPropsNoChildren } = content.props;
47414
+ const { children: _childrenConfig, ...restPropsNoChildren } = liveProps;
46901
47415
  const restProps = childrenIsRenderFn ? { ...restPropsNoChildren, children: incomingChildren } : restPropsNoChildren;
46902
47416
  const nodeSlotOverrides = {};
46903
47417
  for (const slotKey of CONTENT_NODE_SLOTS) {
46904
47418
  const slotVal = restProps[slotKey];
46905
47419
  if (slotVal === void 0 || slotVal === null) continue;
46906
- if (React91__default.isValidElement(slotVal) || typeof slotVal === "string" || typeof slotVal === "number" || typeof slotVal === "boolean") continue;
47420
+ if (React92__default.isValidElement(slotVal) || typeof slotVal === "string" || typeof slotVal === "number" || typeof slotVal === "boolean") continue;
46907
47421
  const typelessChildren = !Array.isArray(slotVal) && typeof slotVal === "object" && !("type" in slotVal) && Array.isArray(slotVal.children) ? slotVal.children : void 0;
46908
47422
  if (typelessChildren !== void 0 || Array.isArray(slotVal) || typeof slotVal === "object" && "type" in slotVal) {
46909
47423
  nodeSlotOverrides[slotKey] = renderPatternChildren(
@@ -46957,7 +47471,7 @@ function SlotContentRenderer({
46957
47471
  const resolvedItems = Array.isArray(entityVal) && entityVal[0] !== "fn" ? entityVal : null;
46958
47472
  if (resolvedItems && resolvedItems.length > 0 && !finalProps.fields && !finalProps.columns) {
46959
47473
  const sample = resolvedItems[0];
46960
- if (sample && typeof sample === "object" && !Array.isArray(sample) && !React91__default.isValidElement(sample) && !(sample instanceof Date)) {
47474
+ if (sample && typeof sample === "object" && !Array.isArray(sample) && !React92__default.isValidElement(sample) && !(sample instanceof Date)) {
46961
47475
  const keys = Object.keys(sample).filter((k) => k !== "id" && k !== "_id");
46962
47476
  finalProps.fields = keys.map((k, i) => ({ name: k, variant: i === 0 ? "h4" : "body" }));
46963
47477
  }
@@ -47006,7 +47520,7 @@ function SlotContentRenderer({
47006
47520
  "data-orb-path": patternPath ?? "root",
47007
47521
  "data-orb-pattern": content.pattern,
47008
47522
  "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: [
47523
+ children: liveProps.children ?? /* @__PURE__ */ jsxs(Box, { className: "p-4 text-sm text-muted-foreground border border-dashed border-border rounded", children: [
47010
47524
  "Unknown pattern: ",
47011
47525
  content.pattern,
47012
47526
  content.sourceTrait && /* @__PURE__ */ jsxs(Typography, { variant: "small", className: "ml-2", children: [
@@ -47078,6 +47592,7 @@ var scopeWrapLog, TRAIT_BINDING_RE, SuspenseConfigContext, SlotContainedContext,
47078
47592
  var init_UISlotRenderer = __esm({
47079
47593
  "components/core/organisms/UISlotRenderer.tsx"() {
47080
47594
  "use client";
47595
+ init_resolve_render_bindings();
47081
47596
  init_Modal();
47082
47597
  init_Drawer();
47083
47598
  init_Toast();
@@ -47323,7 +47838,7 @@ var AvlTransition = ({
47323
47838
  opacity = 1,
47324
47839
  className
47325
47840
  }) => {
47326
- const ids = React91__default.useMemo(() => {
47841
+ const ids = React92__default.useMemo(() => {
47327
47842
  avlTransitionId += 1;
47328
47843
  return { arrow: `avl-tr-${avlTransitionId}-arrow` };
47329
47844
  }, []);
@@ -47884,7 +48399,7 @@ var AvlStateMachine = ({
47884
48399
  color = "var(--color-primary)",
47885
48400
  animated = false
47886
48401
  }) => {
47887
- const ids = React91__default.useMemo(() => {
48402
+ const ids = React92__default.useMemo(() => {
47888
48403
  avlSmId += 1;
47889
48404
  const base = `avl-sm-${avlSmId}`;
47890
48405
  return { glow: `${base}-glow`, grad: `${base}-grad` };
@@ -48083,7 +48598,7 @@ var AvlOrbitalUnit = ({
48083
48598
  color = "var(--color-primary)",
48084
48599
  animated = false
48085
48600
  }) => {
48086
- const ids = React91__default.useMemo(() => {
48601
+ const ids = React92__default.useMemo(() => {
48087
48602
  avlOuId += 1;
48088
48603
  const base = `avl-ou-${avlOuId}`;
48089
48604
  return { glow: `${base}-glow`, grad: `${base}-grad` };
@@ -48179,7 +48694,7 @@ var AvlClosedCircuit = ({
48179
48694
  color = "var(--color-primary)",
48180
48695
  animated = false
48181
48696
  }) => {
48182
- const ids = React91__default.useMemo(() => {
48697
+ const ids = React92__default.useMemo(() => {
48183
48698
  avlCcId += 1;
48184
48699
  const base = `avl-cc-${avlCcId}`;
48185
48700
  return { glow: `${base}-glow`, grad: `${base}-grad`, arrow: `${base}-arrow` };
@@ -48334,7 +48849,7 @@ var AvlEmitListen = ({
48334
48849
  color = "var(--color-primary)",
48335
48850
  animated = false
48336
48851
  }) => {
48337
- const ids = React91__default.useMemo(() => {
48852
+ const ids = React92__default.useMemo(() => {
48338
48853
  avlElId += 1;
48339
48854
  const base = `avl-el-${avlElId}`;
48340
48855
  return { arrow: `${base}-arrow`, grad: `${base}-grad` };
@@ -48608,7 +49123,7 @@ function renderNode(node, color, glowId) {
48608
49123
  const baseR = node.type === "operator" ? 20 : 16;
48609
49124
  const r2 = Math.max(baseR, labelLen * 3.5 + 6);
48610
49125
  const nc = nodeColor(node.type, color);
48611
- return /* @__PURE__ */ jsxs(React91__default.Fragment, { children: [
49126
+ return /* @__PURE__ */ jsxs(React92__default.Fragment, { children: [
48612
49127
  node.children.map((child, i) => {
48613
49128
  const childR = Math.max(
48614
49129
  child.type === "operator" ? 20 : 16,
@@ -48665,7 +49180,7 @@ var AvlExprTree = ({
48665
49180
  className,
48666
49181
  color = "var(--color-primary)"
48667
49182
  }) => {
48668
- const ids = React91__default.useMemo(() => {
49183
+ const ids = React92__default.useMemo(() => {
48669
49184
  avlEtId += 1;
48670
49185
  return { glow: `avl-et-${avlEtId}-glow` };
48671
49186
  }, []);
@@ -49500,7 +50015,7 @@ var SystemNode = ({ data }) => {
49500
50015
  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
50016
  const tc = transitionCounts[s.name] ?? 0;
49502
50017
  const role = getStateRole(s.name, s.isInitial ?? void 0, s.isTerminal ?? void 0, tc, maxTC);
49503
- return /* @__PURE__ */ jsxs(React91__default.Fragment, { children: [
50018
+ return /* @__PURE__ */ jsxs(React92__default.Fragment, { children: [
49504
50019
  /* @__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
50020
  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
50021
  ] }, s.name);
@@ -50579,12 +51094,15 @@ function resolveLambdaBindings(body, params, item, index) {
50579
51094
  const arr = body;
50580
51095
  const substituted = arr.map((b) => recur(b));
50581
51096
  if (isOperatorCall(substituted) && isSExpr(substituted)) {
51097
+ if (containsEntityBinding(substituted)) {
51098
+ return substituted;
51099
+ }
50582
51100
  const evaluated = evaluate(substituted, createMinimalContext());
50583
51101
  return isEventPayloadValue(evaluated) ? evaluated : String(evaluated);
50584
51102
  }
50585
51103
  return substituted;
50586
51104
  }
50587
- if (body !== null && typeof body === "object" && !React91__default.isValidElement(body) && !(body instanceof Date) && typeof body !== "function") {
51105
+ if (body !== null && typeof body === "object" && !React92__default.isValidElement(body) && !(body instanceof Date) && typeof body !== "function") {
50588
51106
  const out = {};
50589
51107
  for (const [k, v] of Object.entries(body)) {
50590
51108
  out[k] = recur(v);
@@ -50600,10 +51118,38 @@ function getSlotContentRenderer2() {
50600
51118
  _slotContentRenderer2 = mod.SlotContentRenderer;
50601
51119
  return _slotContentRenderer2;
50602
51120
  }
51121
+ function deferLambdaEntityExprs(value) {
51122
+ if (typeof value === "string") {
51123
+ if (containsEntityBinding(value)) {
51124
+ const marker = { [RENDER_BINDING_MARKER]: true, expression: value };
51125
+ return marker;
51126
+ }
51127
+ return value;
51128
+ }
51129
+ if (Array.isArray(value)) {
51130
+ if (isFnFormLambda(value)) return value;
51131
+ const arr = value;
51132
+ if (isOperatorCall(arr) && isSExpr(arr) && containsEntityBinding(arr)) {
51133
+ const marker = { [RENDER_BINDING_MARKER]: true, expression: arr };
51134
+ return marker;
51135
+ }
51136
+ return arr.map((v) => deferLambdaEntityExprs(v));
51137
+ }
51138
+ if (value !== null && typeof value === "object" && !React92__default.isValidElement(value) && !(value instanceof Date) && typeof value !== "function" && !isRenderBindingMarker(value)) {
51139
+ const out = {};
51140
+ for (const [k, v] of Object.entries(value)) {
51141
+ out[k] = deferLambdaEntityExprs(v);
51142
+ }
51143
+ return out;
51144
+ }
51145
+ return value;
51146
+ }
50603
51147
  function makeLambdaFn(params, lambdaBody, callerKey) {
50604
51148
  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) {
51149
+ const resolvedBody = deferLambdaEntityExprs(
51150
+ resolveLambdaBindings(lambdaBody, params, item, index)
51151
+ );
51152
+ if (resolvedBody === null || typeof resolvedBody !== "object" || Array.isArray(resolvedBody) || typeof resolvedBody === "function" || React92__default.isValidElement(resolvedBody) || resolvedBody instanceof Date) {
50607
51153
  return null;
50608
51154
  }
50609
51155
  const record = resolvedBody;
@@ -50622,11 +51168,12 @@ function makeLambdaFn(params, lambdaBody, callerKey) {
50622
51168
  props: childProps,
50623
51169
  priority: 0
50624
51170
  };
50625
- return React91__default.createElement(SlotContentRenderer2, { content: childContent });
51171
+ return React92__default.createElement(SlotContentRenderer2, { content: childContent });
50626
51172
  };
50627
51173
  }
50628
51174
  function convertNode(node, callerKey) {
50629
51175
  if (node === null || node === void 0) return node;
51176
+ if (isRenderBindingMarker(node)) return node;
50630
51177
  if (Array.isArray(node)) {
50631
51178
  if (isFnFormLambda(node)) {
50632
51179
  const arr2 = node;
@@ -50641,7 +51188,7 @@ function convertNode(node, callerKey) {
50641
51188
  });
50642
51189
  return anyChanged ? mapped : node;
50643
51190
  }
50644
- if (typeof node === "object" && !React91__default.isValidElement(node) && !(node instanceof Date)) {
51191
+ if (typeof node === "object" && !React92__default.isValidElement(node) && !(node instanceof Date)) {
50645
51192
  return convertObjectProps(node);
50646
51193
  }
50647
51194
  return node;
@@ -50800,6 +51347,7 @@ var tickLog = createLogger("almadar:ui:tick-effects");
50800
51347
  setNamespaceLevel("almadar:ui:tick-effects", "WARN");
50801
51348
  var sharedEntityLog = createLogger("almadar:ui:shared-entity");
50802
51349
  setNamespaceLevel("almadar:ui:shared-entity", "WARN");
51350
+ var EMPTY_BINDING_SNAPSHOT = {};
50803
51351
  var SYNC_TICK_OPERATORS = /* @__PURE__ */ new Set([
50804
51352
  "set",
50805
51353
  "emit",
@@ -50820,11 +51368,6 @@ var SYNC_TICK_OPERATORS = /* @__PURE__ */ new Set([
50820
51368
  "do",
50821
51369
  "when"
50822
51370
  ]);
50823
- var REACTIVE_REPAINT_PATTERN_TYPES = /* @__PURE__ */ new Set([
50824
- "canvas",
50825
- "game-hud",
50826
- "game-shell"
50827
- ]);
50828
51371
  var LIFECYCLE_EVENTS = ["INIT", "LOAD", "$MOUNT"];
50829
51372
  function toTraitDefinition(binding) {
50830
51373
  return {
@@ -50865,6 +51408,27 @@ function classifySharedTick(tick) {
50865
51408
  if (renders) return "renderer";
50866
51409
  return "neither";
50867
51410
  }
51411
+ function buildTraitRenderConfig(binding, traitConfigsByName, payload) {
51412
+ const declaredDefaults = collectDeclaredConfigDefaults(binding.trait);
51413
+ const resolvedDefaults = traitConfigsByName?.[binding.trait.name];
51414
+ const callSiteConfig = getBindingConfig(binding);
51415
+ const callSiteOverrides = callSiteConfig ? resolveCallSitePayloadCaptures(
51416
+ Object.fromEntries(
51417
+ Object.entries(callSiteConfig).filter(
51418
+ ([, v]) => !containsConfigForward(v)
51419
+ )
51420
+ ),
51421
+ payload
51422
+ ) : void 0;
51423
+ if (declaredDefaults || resolvedDefaults || callSiteOverrides) {
51424
+ return {
51425
+ ...declaredDefaults ?? {},
51426
+ ...resolvedDefaults ?? {},
51427
+ ...callSiteOverrides ?? {}
51428
+ };
51429
+ }
51430
+ return void 0;
51431
+ }
50868
51432
  function createSharedEntityWriter(binding, tick, traitStatesRef, emit) {
50869
51433
  return (scratch) => {
50870
51434
  const traitName = binding.trait.name;
@@ -51085,8 +51649,24 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
51085
51649
  }, [traitStates]);
51086
51650
  const traitSnapshotDataRef = useRef(/* @__PURE__ */ new Map());
51087
51651
  const traitFieldStatesRef = useRef(/* @__PURE__ */ new Map());
51088
- const lastCanvasRenderUiRef = useRef(/* @__PURE__ */ new Map());
51089
- const executeTransitionEffectsRef = useRef(null);
51652
+ const bridgeEchoPendingRef = useRef(/* @__PURE__ */ new Map());
51653
+ const bindingSnapshotsRef = useRef(/* @__PURE__ */ new Map());
51654
+ const bindingListenersRef = useRef(/* @__PURE__ */ new Map());
51655
+ const publishBindingSnapshot = useCallback((traitName, row) => {
51656
+ bindingSnapshotsRef.current.set(traitName, { ...row });
51657
+ const listeners7 = bindingListenersRef.current.get(traitName);
51658
+ if (!listeners7) return;
51659
+ listeners7.forEach((callback) => {
51660
+ try {
51661
+ callback();
51662
+ } catch (error) {
51663
+ stateLog.error("binding-snapshot listener error", {
51664
+ traitName,
51665
+ error: error instanceof Error ? error.message : String(error)
51666
+ });
51667
+ }
51668
+ });
51669
+ }, []);
51090
51670
  useEffect(() => {
51091
51671
  const mgr = managerRef.current;
51092
51672
  const bindings = traitBindingsRef.current;
@@ -51214,15 +51794,6 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
51214
51794
  const existing = pendingSlots.get(slot) || [];
51215
51795
  existing.push({ pattern, props: props || {} });
51216
51796
  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
51797
  },
51227
51798
  clearSlot: (slot) => {
51228
51799
  pendingSlots.set(slot, []);
@@ -51294,11 +51865,13 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
51294
51865
  };
51295
51866
  }
51296
51867
  const sharedWrites = [];
51868
+ let didWrite = false;
51297
51869
  const baseSet = handlers.set;
51298
51870
  handlers = {
51299
51871
  ...handlers,
51300
51872
  set: async (targetId, field, value) => {
51301
51873
  if (baseSet) await baseSet(targetId, field, value);
51874
+ didWrite = true;
51302
51875
  if (sharedKey !== void 0) {
51303
51876
  sharedWrites.push({ field, value });
51304
51877
  }
@@ -51315,23 +51888,9 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
51315
51888
  payload: payload || {},
51316
51889
  state: previousState
51317
51890
  };
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
- };
51891
+ const renderConfig = buildTraitRenderConfig(binding, traitConfigsByName, payload || {});
51892
+ if (renderConfig !== void 0) {
51893
+ bindingCtx.config = renderConfig;
51335
51894
  }
51336
51895
  if (traitName === "Authority" || traitName === "Hero") {
51337
51896
  sharedEntityLog.debug("executeTransitionEffects config tiles", {
@@ -51365,7 +51924,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
51365
51924
  effectHeads: effects.map((e) => Array.isArray(e) ? String(e[0]) : "??")
51366
51925
  });
51367
51926
  }
51368
- const executor = new EffectExecutor({ handlers: trackingHandlers, bindings: bindingCtx, context: effectContext });
51927
+ const executor = new EffectExecutor({ handlers: trackingHandlers, bindings: bindingCtx, context: effectContext, deferRenderBindings: true });
51369
51928
  try {
51370
51929
  await executor.executeAll(effects);
51371
51930
  if (traitName === "Authority" || traitName === "Hero") {
@@ -51406,37 +51965,8 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
51406
51965
  entity: binding.linkedEntity
51407
51966
  });
51408
51967
  }
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
- }
51968
+ if (didWrite && sharedKey === void 0) {
51969
+ publishBindingSnapshot(traitName, liveEntity);
51440
51970
  }
51441
51971
  } catch (error) {
51442
51972
  log11.error("effects:error", {
@@ -51448,10 +51978,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
51448
51978
  });
51449
51979
  }
51450
51980
  return emittedDuringExec;
51451
- }, [eventBus, flushSlot, sharedEntityStore]);
51452
- useEffect(() => {
51453
- executeTransitionEffectsRef.current = executeTransitionEffects;
51454
- }, [executeTransitionEffects]);
51981
+ }, [eventBus, flushSlot, sharedEntityStore, publishBindingSnapshot]);
51455
51982
  const runTickEffects = useCallback((tick, binding) => {
51456
51983
  const traitName = binding.trait.name;
51457
51984
  const currentState = traitStatesRef.current.get(traitName)?.currentState ?? "";
@@ -51514,24 +52041,6 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
51514
52041
  ({ binding, tick }) => createSharedEntityWriter(binding, tick, traitStatesRef, emitFromSharedWriter)
51515
52042
  );
51516
52043
  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
52044
  };
51536
52045
  if (interval === "frame") {
51537
52046
  scheduler.add(0, onDue);
@@ -51602,6 +52111,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
51602
52111
  executedTraits: results.map((r2) => r2.traitName).join(",")
51603
52112
  });
51604
52113
  const emittedByTrait = /* @__PURE__ */ new Map();
52114
+ bridgeEchoPendingRef.current.clear();
51605
52115
  for (const { traitName, result } of results) {
51606
52116
  const binding = bindingMap.get(traitName);
51607
52117
  const traitState = currentManager.getState(traitName);
@@ -51656,6 +52166,12 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
51656
52166
  log: stateLog
51657
52167
  });
51658
52168
  emittedByTrait.set(traitName, emittedDuringExec);
52169
+ for (const emittedKey of emittedDuringExec) {
52170
+ bridgeEchoPendingRef.current.set(
52171
+ emittedKey,
52172
+ (bridgeEchoPendingRef.current.get(emittedKey) ?? 0) + 1
52173
+ );
52174
+ }
51659
52175
  } else if (!result.executed) {
51660
52176
  if (result.guardResult === false) {
51661
52177
  stateLog.debug("guard-blocked-transition", {
@@ -51805,8 +52321,13 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
51805
52321
  crossTraitLog.debug("self:subscribe", { traitName, busKey: selfBusKey, eventKey });
51806
52322
  const unsub = eventBus.on(selfBusKey, (event) => {
51807
52323
  if (event.source && event.source.dispatched) {
51808
- crossTraitLog.debug("self:fire-skipped-bridge-echo", { traitName, busKey: selfBusKey, eventKey });
51809
- return;
52324
+ const pendingEchoes = bridgeEchoPendingRef.current.get(eventKey) ?? 0;
52325
+ if (pendingEchoes > 0) {
52326
+ bridgeEchoPendingRef.current.set(eventKey, pendingEchoes - 1);
52327
+ crossTraitLog.debug("self:fire-skipped-bridge-echo", { traitName, busKey: selfBusKey, eventKey });
52328
+ return;
52329
+ }
52330
+ crossTraitLog.debug("self:fire-server-cascade", { traitName, busKey: selfBusKey, eventKey });
51810
52331
  }
51811
52332
  crossTraitLog.debug("self:fire", { traitName, busKey: selfBusKey, eventKey });
51812
52333
  enqueueAndDrain(eventKey, event.payload, traitName);
@@ -51898,11 +52419,47 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
51898
52419
  initedTraitsRef.current = /* @__PURE__ */ new Set();
51899
52420
  };
51900
52421
  }, [traitBindings, enqueueAndDrain]);
52422
+ const entityBindingSource = useMemo(() => ({
52423
+ getEntitySnapshot: (traitName) => {
52424
+ const sharedKey = sharedKeyByTraitNameRef.current.get(traitName);
52425
+ if (sharedKey !== void 0) {
52426
+ return sharedEntityStore.getSnapshot(sharedKey);
52427
+ }
52428
+ return bindingSnapshotsRef.current.get(traitName) ?? EMPTY_BINDING_SNAPSHOT;
52429
+ },
52430
+ getConfig: (traitName) => {
52431
+ const binding = traitBindingsRef.current.find((b) => b.trait.name === traitName);
52432
+ if (binding === void 0) return void 0;
52433
+ return buildTraitRenderConfig(binding, traitConfigsByName, {});
52434
+ },
52435
+ getState: (traitName) => traitStatesRef.current.get(traitName)?.currentState ?? "",
52436
+ subscribe: (traitName, callback) => {
52437
+ const sharedKey = sharedKeyByTraitNameRef.current.get(traitName);
52438
+ if (sharedKey !== void 0) {
52439
+ return sharedEntityStore.subscribe(sharedKey, callback);
52440
+ }
52441
+ let listeners7 = bindingListenersRef.current.get(traitName);
52442
+ if (!listeners7) {
52443
+ listeners7 = /* @__PURE__ */ new Set();
52444
+ bindingListenersRef.current.set(traitName, listeners7);
52445
+ }
52446
+ listeners7.add(callback);
52447
+ return () => {
52448
+ const current = bindingListenersRef.current.get(traitName);
52449
+ if (!current) return;
52450
+ current.delete(callback);
52451
+ if (current.size === 0) {
52452
+ bindingListenersRef.current.delete(traitName);
52453
+ }
52454
+ };
52455
+ }
52456
+ }), [sharedEntityStore, traitConfigsByName]);
51901
52457
  return {
51902
52458
  traitStates,
51903
52459
  sendEvent,
51904
52460
  getTraitState,
51905
- canHandleEvent
52461
+ canHandleEvent,
52462
+ entityBindingSource
51906
52463
  };
51907
52464
  }
51908
52465
 
@@ -51991,7 +52548,7 @@ function collectServerActiveTraits(ir, allTraits, mountedTraitNames) {
51991
52548
  }
51992
52549
  return active;
51993
52550
  }
51994
- function TraitInitializer({ traits: traits2, routeParams, orbitalNames, onNavigate, onLocalFallback, persistence, traitConfigsByName, orbitalsByTrait, embeddedTraits, serverActiveTraits }) {
52551
+ function TraitInitializer({ traits: traits2, routeParams, orbitalNames, onNavigate, onLocalFallback, persistence, traitConfigsByName, orbitalsByTrait, embeddedTraits, serverActiveTraits, children }) {
51995
52552
  const bridge = useServerBridge();
51996
52553
  const activeTraitNames = useMemo(
51997
52554
  () => new Set(traits2.map((b) => b.trait.name).filter((n) => !!n)),
@@ -52021,7 +52578,7 @@ function TraitInitializer({ traits: traits2, routeParams, orbitalNames, onNaviga
52021
52578
  }
52022
52579
  }, [bridge.connected, bridge.sendEvent, orbitalNames, uiSlots, onNavigate, embeddedTraits, activeTraitNames, withActiveTraits]);
52023
52580
  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);
52581
+ const { sendEvent, entityBindingSource } = useTraitStateMachine(traits2, uiSlots, opts);
52025
52582
  const initSentRef = useRef(false);
52026
52583
  const prevTraitsRef = useRef(void 0);
52027
52584
  const paramsKey = JSON.stringify(routeParams ?? {});
@@ -52067,7 +52624,7 @@ function TraitInitializer({ traits: traits2, routeParams, orbitalNames, onNaviga
52067
52624
  { type: "fetch", args: [], status: "executed" },
52068
52625
  ...effects.map((eff) => ({
52069
52626
  type: eff.type,
52070
- args: eff.type === "render-ui" ? [eff.slot] : [],
52627
+ args: eff.type === "render-ui" && eff.slot !== void 0 ? [eff.slot] : [],
52071
52628
  status: "executed"
52072
52629
  }))
52073
52630
  ];
@@ -52083,7 +52640,7 @@ function TraitInitializer({ traits: traits2, routeParams, orbitalNames, onNaviga
52083
52640
  }
52084
52641
  })();
52085
52642
  }, [bridge.connected, orbitalNames, bridge.sendEvent, uiSlots, onNavigate, embeddedTraits, activeTraitNames, withActiveTraits, routeParams]);
52086
- return null;
52643
+ return /* @__PURE__ */ jsx(EntityBindingContext.Provider, { value: entityBindingSource, children });
52087
52644
  }
52088
52645
  function SchemaRunner({ schema, serverUrl, transport, mockData, pageName, routeParams, onNavigate, onLocalFallback, persistence }) {
52089
52646
  const { traits: traits2, allEntities, allTraits, ir } = useResolvedSchema(schema, pageName);
@@ -52216,30 +52773,28 @@ function SchemaRunner({ schema, serverUrl, transport, mockData, pageName, routeP
52216
52773
  }
52217
52774
  return schema.orbitals[0]?.theme;
52218
52775
  }, [schema, pageName]);
52219
- const inner = /* @__PURE__ */ jsx(VerificationProvider, { enabled: true, children: /* @__PURE__ */ jsxs(
52776
+ const inner = /* @__PURE__ */ jsx(VerificationProvider, { enabled: true, children: /* @__PURE__ */ jsx(
52220
52777
  EntitySchemaProvider,
52221
52778
  {
52222
52779
  entities: entitiesArray,
52223
52780
  traitLinkedEntities: traitLinkedEntitiesMap,
52224
52781
  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
- ]
52782
+ children: /* @__PURE__ */ jsx(
52783
+ TraitInitializer,
52784
+ {
52785
+ traits: allPageTraits,
52786
+ routeParams,
52787
+ orbitalNames: serverUrl || transport ? pageOrbitalNames : void 0,
52788
+ traitConfigsByName,
52789
+ orbitalsByTrait,
52790
+ embeddedTraits,
52791
+ serverActiveTraits,
52792
+ onNavigate,
52793
+ onLocalFallback,
52794
+ persistence,
52795
+ 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 }) }) })
52796
+ }
52797
+ )
52243
52798
  }
52244
52799
  ) });
52245
52800
  if (serverUrl || transport) {
@@ -52556,8 +53111,8 @@ function CanvasDndProvider({
52556
53111
  }) {
52557
53112
  const eventBus = useEventBus();
52558
53113
  const sensors = useAlmadarDndSensors(false);
52559
- const [activePayload, setActivePayload] = React91__default.useState(null);
52560
- const handleDragStart = React91__default.useCallback((e) => {
53114
+ const [activePayload, setActivePayload] = React92__default.useState(null);
53115
+ const handleDragStart = React92__default.useCallback((e) => {
52561
53116
  const data = e.active.data.current;
52562
53117
  const payload = data?.payload;
52563
53118
  if (payload) {
@@ -52568,7 +53123,7 @@ function CanvasDndProvider({
52568
53123
  log9.warn("dragStart:missing-payload", { id: e.active.id });
52569
53124
  }
52570
53125
  }, [eventBus]);
52571
- const handleDragEnd = React91__default.useCallback((e) => {
53126
+ const handleDragEnd = React92__default.useCallback((e) => {
52572
53127
  setActivePayload(null);
52573
53128
  const activeData = e.active.data.current;
52574
53129
  const payload = activeData?.payload;
@@ -52597,7 +53152,7 @@ function CanvasDndProvider({
52597
53152
  const suppressed = onDrop ? onDrop(drop) === true : false;
52598
53153
  if (!suppressed) defaultEmit(eventBus, drop);
52599
53154
  }, [eventBus, onDrop]);
52600
- const handleDragCancel = React91__default.useCallback(() => {
53155
+ const handleDragCancel = React92__default.useCallback(() => {
52601
53156
  setActivePayload(null);
52602
53157
  log9.info("dragCancel");
52603
53158
  }, []);
@@ -53355,7 +53910,7 @@ var OrbPreviewNodeInner = (props) => {
53355
53910
  }
53356
53911
  );
53357
53912
  };
53358
- var OrbPreviewNode = React91__default.memo(OrbPreviewNodeInner);
53913
+ var OrbPreviewNode = React92__default.memo(OrbPreviewNodeInner);
53359
53914
  OrbPreviewNode.displayName = "OrbPreviewNode";
53360
53915
  orbPreviewLog.debug("export-resolved", () => ({
53361
53916
  type: typeof OrbPreviewNode,
@@ -53460,7 +54015,7 @@ var EventFlowEdgeInner = (props) => {
53460
54015
  ) })
53461
54016
  ] });
53462
54017
  };
53463
- var EventFlowEdge = React91__default.memo(EventFlowEdgeInner);
54018
+ var EventFlowEdge = React92__default.memo(EventFlowEdgeInner);
53464
54019
  EventFlowEdge.displayName = "EventFlowEdge";
53465
54020
 
53466
54021
  // components/avl/molecules/BehaviorComposeNode.tsx
@@ -53607,7 +54162,7 @@ var BehaviorComposeNodeInner = (props) => {
53607
54162
  }
53608
54163
  );
53609
54164
  };
53610
- var BehaviorComposeNode = React91__default.memo(BehaviorComposeNodeInner);
54165
+ var BehaviorComposeNode = React92__default.memo(BehaviorComposeNodeInner);
53611
54166
  BehaviorComposeNode.displayName = "BehaviorComposeNode";
53612
54167
 
53613
54168
  // components/avl/lib/avl-behavior-compose-converter.ts
@@ -54633,7 +55188,7 @@ var TraitCardNodeInner = (props) => {
54633
55188
  }
54634
55189
  );
54635
55190
  };
54636
- var TraitCardNode = React91__default.memo(TraitCardNodeInner);
55191
+ var TraitCardNode = React92__default.memo(TraitCardNodeInner);
54637
55192
  TraitCardNode.displayName = "TraitCardNode";
54638
55193
 
54639
55194
  // components/avl/organisms/FlowCanvas.tsx
@@ -54714,7 +55269,7 @@ function FlowCanvasInner({
54714
55269
  initialOrbital
54715
55270
  );
54716
55271
  const [expandedBehaviorAlias, setExpandedBehaviorAlias] = useState(void 0);
54717
- const screenSizeUserOverrideRef = React91__default.useRef(false);
55272
+ const screenSizeUserOverrideRef = React92__default.useRef(false);
54718
55273
  const [screenSize, setScreenSize] = useState(
54719
55274
  () => typeof window === "undefined" ? "laptop" : detectScreenSize(window.innerWidth)
54720
55275
  );
@@ -55098,7 +55653,7 @@ var ZoomBreadcrumb = ({
55098
55653
  if (eventName && band === "detail") {
55099
55654
  segments.push({ icon: "\u26A1", label: eventName });
55100
55655
  }
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: [
55656
+ 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
55657
  i > 0 && /* @__PURE__ */ jsx("span", { className: "opacity-40", children: ">" }),
55103
55658
  /* @__PURE__ */ jsx("span", { className: "opacity-60", children: seg.icon }),
55104
55659
  /* @__PURE__ */ jsx("span", { children: seg.label })
@@ -55439,7 +55994,7 @@ var EventWireOverlay = ({
55439
55994
  containerW,
55440
55995
  containerH
55441
55996
  }) => {
55442
- const ids = React91__default.useMemo(() => {
55997
+ const ids = React92__default.useMemo(() => {
55443
55998
  avlOczWireId += 1;
55444
55999
  return { arrow: `avl-ocz-wire-${avlOczWireId}-arrow` };
55445
56000
  }, []);
@@ -55806,7 +56361,7 @@ var AvlOrbitalsCosmicZoom = ({
55806
56361
  borderRadius: 6,
55807
56362
  border: `1px solid ${color}`
55808
56363
  },
55809
- children: /* @__PURE__ */ jsx(HStack, { gap: "xs", align: "center", children: breadcrumbs.map((crumb, i) => /* @__PURE__ */ jsxs(React91__default.Fragment, { children: [
56364
+ children: /* @__PURE__ */ jsx(HStack, { gap: "xs", align: "center", children: breadcrumbs.map((crumb, i) => /* @__PURE__ */ jsxs(React92__default.Fragment, { children: [
55810
56365
  i > 0 && /* @__PURE__ */ jsx(Typography, { variant: "small", style: { opacity: 0.5, color }, children: "/" }),
55811
56366
  i < breadcrumbs.length - 1 ? /* @__PURE__ */ jsx(
55812
56367
  Box,