@almadar/ui 5.135.0 → 5.137.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,10 @@
1
- import * as React84 from 'react';
2
- import React84__default, { createContext, useContext, useMemo, useRef, useEffect, useCallback, Suspense, useState, useLayoutEffect, lazy, useId, useSyncExternalStore } from 'react';
3
- import { EventBusContext, useTraitScopeChain, useEntitySchemaOptional, TraitScopeProvider, useCurrentPagePath, useGameAudioContextOptional } from '@almadar/ui/providers';
1
+ import * as React85 from 'react';
2
+ import React85__default, { createContext, useContext, useMemo, useRef, useEffect, useCallback, Suspense, useState, useSyncExternalStore, useLayoutEffect, lazy, useId } from 'react';
3
+ import { EventBusContext, useTraitScopeChain, useEntitySchemaOptional, useEntityBindingSnapshot, useTraitScope, TraitScopeProvider, useCurrentPagePath, useGameAudioContextOptional } from '@almadar/ui/providers';
4
4
  import { createLogger, isLogLevelEnabled } from '@almadar/logger';
5
+ import { createContextFromBindings, interpolateValue } from '@almadar/runtime';
6
+ import { ANONYMOUS_USER, isRenderBindingMarker, isInlineTrait } from '@almadar/core';
7
+ export { ANONYMOUS_USER } from '@almadar/core';
5
8
  import { clsx } from 'clsx';
6
9
  import { twMerge } from 'tailwind-merge';
7
10
  import * as LucideIcons2 from 'lucide-react';
@@ -68,11 +71,10 @@ import ReactMarkdown from 'react-markdown';
68
71
  import remarkGfm from 'remark-gfm';
69
72
  import remarkMath from 'remark-math';
70
73
  import rehypeKatex from 'rehype-katex';
71
- import { ANONYMOUS_USER, isInlineTrait } from '@almadar/core';
72
- export { ANONYMOUS_USER } from '@almadar/core';
73
74
  import { DndContext, pointerWithin, rectIntersection, closestCorners, useSensors, useSensor, PointerSensor, KeyboardSensor, useDroppable } from '@dnd-kit/core';
74
75
  import { useSortable, arrayMove, sortableKeyboardCoordinates, SortableContext, rectSortingStrategy, verticalListSortingStrategy } from '@dnd-kit/sortable';
75
76
  import { CSS } from '@dnd-kit/utilities';
77
+ import { ordered, lib } from 'emojilib';
76
78
  import { useNodeId, ReactFlowProvider, Handle, Position } from '@xyflow/react';
77
79
  import { forceSimulation, forceLink, forceManyBody, forceCollide, forceX, forceY } from 'd3-force';
78
80
  import { isDrawHostPattern, getPatternDefinition, getComponentForPattern as getComponentForPattern$1 } from '@almadar/core/patterns';
@@ -267,6 +269,75 @@ var init_useEventBus = __esm({
267
269
  useEventBus_default = useEventBus;
268
270
  }
269
271
  });
272
+ function resolveMarkerExpression(expression, entity, config, state) {
273
+ const ctx = createContextFromBindings({
274
+ entity,
275
+ payload: {},
276
+ state,
277
+ ...config !== void 0 ? { config } : {}
278
+ });
279
+ return interpolateValue(expression, ctx);
280
+ }
281
+ function isPlainObject(value) {
282
+ if (value === null || value === void 0 || typeof value !== "object") return false;
283
+ if (Array.isArray(value)) return false;
284
+ if (React85__default.isValidElement(value)) return false;
285
+ if (value instanceof Date) return false;
286
+ if (typeof value === "function") return false;
287
+ return true;
288
+ }
289
+ function walkValue(value, scopeTrait, entity, config, state) {
290
+ if (isRenderBindingMarker(value)) {
291
+ return { resolved: resolveMarkerExpression(value.expression, entity, config, state), changed: true };
292
+ }
293
+ if (Array.isArray(value)) {
294
+ const out = [];
295
+ let changed = false;
296
+ for (const item of value) {
297
+ const element = item;
298
+ const wasMarker = isRenderBindingMarker(element);
299
+ const { resolved, changed: itemChanged } = walkValue(element, scopeTrait, entity, config, state);
300
+ if (wasMarker && Array.isArray(resolved)) {
301
+ out.push(...resolved);
302
+ changed = true;
303
+ continue;
304
+ }
305
+ out.push(resolved);
306
+ if (itemChanged) changed = true;
307
+ }
308
+ return changed ? { resolved: out, changed: true } : { resolved: value, changed: false };
309
+ }
310
+ if (isPlainObject(value)) {
311
+ const sourceTrait = value._sourceTrait;
312
+ if (typeof sourceTrait === "string" && sourceTrait !== scopeTrait) {
313
+ return { resolved: value, changed: false };
314
+ }
315
+ const out = {};
316
+ let changed = false;
317
+ for (const [key, item] of Object.entries(value)) {
318
+ const { resolved, changed: itemChanged } = walkValue(item, scopeTrait, entity, config, state);
319
+ out[key] = resolved;
320
+ if (itemChanged) changed = true;
321
+ }
322
+ return changed ? { resolved: out, changed: true } : { resolved: value, changed: false };
323
+ }
324
+ return { resolved: value, changed: false };
325
+ }
326
+ function resolveRenderBindingMarkers(props, scopeTrait, entity, config, state) {
327
+ const out = {};
328
+ let changed = false;
329
+ for (const [key, value] of Object.entries(props)) {
330
+ const { resolved, changed: propChanged } = walkValue(value, scopeTrait, entity, config, state);
331
+ out[key] = resolved;
332
+ if (propChanged) changed = true;
333
+ }
334
+ return changed ? out : props;
335
+ }
336
+ var init_resolve_render_bindings = __esm({
337
+ "lib/resolve-render-bindings.ts"() {
338
+ "use client";
339
+ }
340
+ });
270
341
  function cn(...inputs) {
271
342
  return twMerge(clsx(inputs));
272
343
  }
@@ -430,7 +501,7 @@ var init_Box = __esm({
430
501
  fixed: "fixed",
431
502
  sticky: "sticky"
432
503
  };
433
- Box = React84__default.forwardRef(
504
+ Box = React85__default.forwardRef(
434
505
  ({
435
506
  padding,
436
507
  paddingX,
@@ -495,7 +566,7 @@ var init_Box = __esm({
495
566
  onPointerDown?.(e);
496
567
  }, [hoverEvent, tapReveal, triggerProps, onPointerDown]);
497
568
  const isClickable = action || onClick;
498
- return React84__default.createElement(
569
+ return React85__default.createElement(
499
570
  Component,
500
571
  {
501
572
  ref,
@@ -712,7 +783,7 @@ var init_Icon = __esm({
712
783
  const effectiveName = typeof icon === "string" && icon !== "" ? icon : name;
713
784
  const effectiveStrokeWidth = strokeWidth != null && strokeWidth > 0 ? strokeWidth : void 0;
714
785
  const family = useIconFamily();
715
- const RenderedComponent = React84__default.useMemo(() => {
786
+ const RenderedComponent = React85__default.useMemo(() => {
716
787
  if (directIcon) return null;
717
788
  return effectiveName ? resolveIconForFamily(effectiveName) : null;
718
789
  }, [directIcon, effectiveName, family]);
@@ -774,9 +845,13 @@ function getAtlas(url, onReady) {
774
845
  onReady();
775
846
  }).catch(() => {
776
847
  atlasCache.set(url, null);
848
+ onReady();
777
849
  });
778
850
  return void 0;
779
851
  }
852
+ function atlasFailed(url) {
853
+ return atlasCache.get(url) === null;
854
+ }
780
855
  function subRectFor(atlas, sprite) {
781
856
  if (isTilesheet(atlas)) {
782
857
  let col;
@@ -832,7 +907,7 @@ var init_atlasSlice = __esm({
832
907
  }
833
908
  });
834
909
  function useAtlasSliceDataUrl(asset) {
835
- const [, bump] = React84.useReducer((x) => x + 1, 0);
910
+ const [, bump] = React85.useReducer((x) => x + 1, 0);
836
911
  if (!isAtlasAsset(asset)) return void 0;
837
912
  const key = `${asset.atlas}#${asset.sprite}`;
838
913
  const cached = sliceDataUrlCache.get(key);
@@ -895,13 +970,13 @@ function AtlasImage({
895
970
  style,
896
971
  "aria-hidden": ariaHidden
897
972
  }) {
898
- const [, bump] = React84.useReducer((x) => x + 1, 0);
899
- const canvasRef = React84.useRef(null);
973
+ const [, bump] = React85.useReducer((x) => x + 1, 0);
974
+ const canvasRef = React85.useRef(null);
900
975
  const sliced = isAtlasAsset(asset);
901
976
  const atlas = sliced ? getAtlas(asset.atlas, bump) : void 0;
902
977
  const img = sliced && asset?.url ? getSheetImage(asset.url, bump) : null;
903
978
  const rect = sliced && atlas ? subRectFor(atlas, asset.sprite) : null;
904
- React84.useEffect(() => {
979
+ React85.useEffect(() => {
905
980
  const canvas = canvasRef.current;
906
981
  if (!canvas || !img || !rect) return;
907
982
  canvas.width = rect.sw;
@@ -977,7 +1052,7 @@ function resolveIconProp(value, sizeClass) {
977
1052
  const IconComp = value;
978
1053
  return /* @__PURE__ */ jsx(IconComp, { className: sizeClass });
979
1054
  }
980
- if (React84__default.isValidElement(value)) {
1055
+ if (React85__default.isValidElement(value)) {
981
1056
  return value;
982
1057
  }
983
1058
  if (typeof value === "object" && value !== null && isIconLike(value)) {
@@ -1054,7 +1129,7 @@ var init_Button = __esm({
1054
1129
  md: "h-icon-default w-icon-default",
1055
1130
  lg: "h-icon-default w-icon-default"
1056
1131
  };
1057
- Button = React84__default.forwardRef(
1132
+ Button = React85__default.forwardRef(
1058
1133
  ({
1059
1134
  className,
1060
1135
  variant = "primary",
@@ -1124,7 +1199,7 @@ var Dialog;
1124
1199
  var init_Dialog = __esm({
1125
1200
  "components/core/atoms/Dialog.tsx"() {
1126
1201
  init_cn();
1127
- Dialog = React84__default.forwardRef(
1202
+ Dialog = React85__default.forwardRef(
1128
1203
  ({
1129
1204
  role = "dialog",
1130
1205
  "aria-modal": ariaModal = true,
@@ -1335,7 +1410,7 @@ var init_Typography = __esm({
1335
1410
  if (format !== void 0 && format !== "none" && (typeof body === "string" || typeof body === "number" || body instanceof Date)) {
1336
1411
  body = formatValue(body, format);
1337
1412
  }
1338
- return React84__default.createElement(
1413
+ return React85__default.createElement(
1339
1414
  Component,
1340
1415
  {
1341
1416
  id,
@@ -1898,7 +1973,7 @@ var init_Badge = __esm({
1898
1973
  md: "px-2.5 py-1 text-sm",
1899
1974
  lg: "px-3 py-1.5 text-base"
1900
1975
  };
1901
- Badge = React84__default.forwardRef(
1976
+ Badge = React85__default.forwardRef(
1902
1977
  ({ className, variant = "default", size = "sm", amount, label, icon, iconAsset, children, onRemove, removeLabel, ...props }, ref) => {
1903
1978
  const iconSizes3 = {
1904
1979
  sm: "h-icon-default w-icon-default",
@@ -2248,7 +2323,7 @@ var init_SvgFlow = __esm({
2248
2323
  width = 100,
2249
2324
  height = 100
2250
2325
  }) => {
2251
- const markerId = React84__default.useMemo(() => {
2326
+ const markerId = React85__default.useMemo(() => {
2252
2327
  flowIdCounter += 1;
2253
2328
  return `almadar-flow-arrow-${flowIdCounter}`;
2254
2329
  }, []);
@@ -2841,7 +2916,7 @@ var init_SvgRing = __esm({
2841
2916
  width = 100,
2842
2917
  height = 100
2843
2918
  }) => {
2844
- const gradientId = React84__default.useMemo(() => {
2919
+ const gradientId = React85__default.useMemo(() => {
2845
2920
  ringIdCounter += 1;
2846
2921
  return `almadar-ring-glow-${ringIdCounter}`;
2847
2922
  }, []);
@@ -3022,7 +3097,7 @@ var init_Input = __esm({
3022
3097
  init_cn();
3023
3098
  init_Icon();
3024
3099
  init_useEventBus();
3025
- Input = React84__default.forwardRef(
3100
+ Input = React85__default.forwardRef(
3026
3101
  ({
3027
3102
  className,
3028
3103
  inputType,
@@ -3045,6 +3120,20 @@ var init_Input = __esm({
3045
3120
  const { t } = useTranslate();
3046
3121
  const eventBus = useEventBus();
3047
3122
  const type = inputType || htmlType || "text";
3123
+ const isDeclarative = typeof onChange === "string";
3124
+ const [localValue, setLocalValue] = React85__default.useState(value);
3125
+ const pendingEchoRef = React85__default.useRef(/* @__PURE__ */ new Set());
3126
+ React85__default.useEffect(() => {
3127
+ if (!isDeclarative) return;
3128
+ const incoming = value == null ? "" : String(value);
3129
+ if (pendingEchoRef.current.has(incoming)) {
3130
+ pendingEchoRef.current.delete(incoming);
3131
+ return;
3132
+ }
3133
+ pendingEchoRef.current.clear();
3134
+ setLocalValue(value);
3135
+ }, [value, isDeclarative]);
3136
+ const displayValue = isDeclarative ? localValue : value;
3048
3137
  const resolveIconNode = (i, cls) => {
3049
3138
  if (!i) return null;
3050
3139
  if (typeof i === "string") return /* @__PURE__ */ jsx(Icon, { name: i, className: cls });
@@ -3054,7 +3143,7 @@ var init_Input = __esm({
3054
3143
  const iconCls = "h-icon-default w-icon-default";
3055
3144
  const IconComponent = typeof iconProp === "string" ? resolveIcon(iconProp) : iconProp;
3056
3145
  const resolvedLeftIcon = (leftIcon ? resolveIconNode(leftIcon, iconCls) : null) || IconComponent && /* @__PURE__ */ jsx(IconComponent, { className: iconCls });
3057
- const showClearButton = clearable && value && String(value).length > 0;
3146
+ const showClearButton = clearable && displayValue && String(displayValue).length > 0;
3058
3147
  const isMultiline = type === "textarea";
3059
3148
  const baseClassName = cn(
3060
3149
  "block w-full rounded-sm transition-all duration-fast",
@@ -3073,6 +3162,10 @@ var init_Input = __esm({
3073
3162
  if (typeof onChange === "string") {
3074
3163
  const target = e.target;
3075
3164
  const payload = type === "checkbox" ? { checked: target.checked } : { value: target.value };
3165
+ if (type !== "checkbox") {
3166
+ pendingEchoRef.current.add(target.value);
3167
+ setLocalValue(target.value);
3168
+ }
3076
3169
  eventBus.emit(`UI:${onChange}`, payload);
3077
3170
  } else {
3078
3171
  onChange?.(e);
@@ -3103,7 +3196,7 @@ var init_Input = __esm({
3103
3196
  "select",
3104
3197
  {
3105
3198
  ref,
3106
- value,
3199
+ value: displayValue,
3107
3200
  onChange: handleChange,
3108
3201
  className: cn(baseClassName, "appearance-none pr-10", className),
3109
3202
  ...props,
@@ -3123,7 +3216,7 @@ var init_Input = __esm({
3123
3216
  "textarea",
3124
3217
  {
3125
3218
  ref,
3126
- value,
3219
+ value: displayValue,
3127
3220
  onChange: handleChange,
3128
3221
  rows,
3129
3222
  className: baseClassName,
@@ -3162,7 +3255,7 @@ var init_Input = __esm({
3162
3255
  {
3163
3256
  ref,
3164
3257
  type,
3165
- value,
3258
+ value: displayValue,
3166
3259
  onChange: handleChange,
3167
3260
  onKeyDown: handleKeyDown,
3168
3261
  className: baseClassName,
@@ -3190,7 +3283,7 @@ var Label;
3190
3283
  var init_Label = __esm({
3191
3284
  "components/core/atoms/Label.tsx"() {
3192
3285
  init_cn();
3193
- Label = React84__default.forwardRef(
3286
+ Label = React85__default.forwardRef(
3194
3287
  ({ className, required, children, ...props }, ref) => {
3195
3288
  return /* @__PURE__ */ jsxs(
3196
3289
  "label",
@@ -3217,7 +3310,7 @@ var init_Textarea = __esm({
3217
3310
  "components/core/atoms/Textarea.tsx"() {
3218
3311
  init_cn();
3219
3312
  init_useEventBus();
3220
- Textarea = React84__default.forwardRef(
3313
+ Textarea = React85__default.forwardRef(
3221
3314
  ({ className, error, onChange, ...props }, ref) => {
3222
3315
  const eventBus = useEventBus();
3223
3316
  const handleChange = (e) => {
@@ -3456,7 +3549,7 @@ var init_Select = __esm({
3456
3549
  init_cn();
3457
3550
  init_Icon();
3458
3551
  init_useEventBus();
3459
- Select = React84__default.forwardRef(
3552
+ Select = React85__default.forwardRef(
3460
3553
  (props, _ref) => {
3461
3554
  const { multiple, searchable, clearable } = props;
3462
3555
  if (multiple || searchable || clearable) {
@@ -3473,7 +3566,7 @@ var init_Checkbox = __esm({
3473
3566
  "components/core/atoms/Checkbox.tsx"() {
3474
3567
  init_cn();
3475
3568
  init_useEventBus();
3476
- Checkbox = React84__default.forwardRef(
3569
+ Checkbox = React85__default.forwardRef(
3477
3570
  ({ className, label, id, onChange, ...props }, ref) => {
3478
3571
  const inputId = id || `checkbox-${Math.random().toString(36).substr(2, 9)}`;
3479
3572
  const eventBus = useEventBus();
@@ -3527,7 +3620,7 @@ var init_Spinner = __esm({
3527
3620
  md: "h-6 w-6",
3528
3621
  lg: "h-8 w-8"
3529
3622
  };
3530
- Spinner = React84__default.forwardRef(
3623
+ Spinner = React85__default.forwardRef(
3531
3624
  ({ className, size = "md", overlay, ...props }, ref) => {
3532
3625
  if (overlay) {
3533
3626
  return /* @__PURE__ */ jsx(
@@ -3617,7 +3710,7 @@ var init_Card = __esm({
3617
3710
  chip: "shadow-none rounded-pill border-[length:var(--border-width)] border-border",
3618
3711
  "tile-image-first": "p-0 overflow-hidden"
3619
3712
  };
3620
- Card = React84__default.forwardRef(
3713
+ Card = React85__default.forwardRef(
3621
3714
  ({
3622
3715
  className,
3623
3716
  variant = "bordered",
@@ -3666,9 +3759,9 @@ var init_Card = __esm({
3666
3759
  }
3667
3760
  );
3668
3761
  Card.displayName = "Card";
3669
- CardHeader = React84__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("mb-4", className), ...props }));
3762
+ CardHeader = React85__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("mb-4", className), ...props }));
3670
3763
  CardHeader.displayName = "CardHeader";
3671
- CardTitle = React84__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
3764
+ CardTitle = React85__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
3672
3765
  "h3",
3673
3766
  {
3674
3767
  ref,
@@ -3681,11 +3774,11 @@ var init_Card = __esm({
3681
3774
  }
3682
3775
  ));
3683
3776
  CardTitle.displayName = "CardTitle";
3684
- CardContent = React84__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("", className), ...props }));
3777
+ CardContent = React85__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("", className), ...props }));
3685
3778
  CardContent.displayName = "CardContent";
3686
3779
  CardBody = CardContent;
3687
3780
  CardBody.displayName = "CardBody";
3688
- CardFooter = React84__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
3781
+ CardFooter = React85__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
3689
3782
  "div",
3690
3783
  {
3691
3784
  ref,
@@ -3772,7 +3865,7 @@ var init_FilterPill = __esm({
3772
3865
  md: "w-3.5 h-3.5",
3773
3866
  lg: "w-4 h-4"
3774
3867
  };
3775
- FilterPill = React84__default.forwardRef(
3868
+ FilterPill = React85__default.forwardRef(
3776
3869
  ({
3777
3870
  className,
3778
3871
  variant = "default",
@@ -3901,8 +3994,8 @@ var init_Avatar = __esm({
3901
3994
  actionPayload
3902
3995
  }) => {
3903
3996
  const eventBus = useEventBus();
3904
- const [imgFailed, setImgFailed] = React84__default.useState(false);
3905
- React84__default.useEffect(() => {
3997
+ const [imgFailed, setImgFailed] = React85__default.useState(false);
3998
+ React85__default.useEffect(() => {
3906
3999
  setImgFailed(false);
3907
4000
  }, [src]);
3908
4001
  const initials = providedInitials ?? (name ? generateInitials(name) : void 0);
@@ -4015,7 +4108,7 @@ var init_Center = __esm({
4015
4108
  as: Component = "div"
4016
4109
  }) => {
4017
4110
  const mergedStyle = minHeight ? { minHeight, ...style } : style;
4018
- return React84__default.createElement(Component, {
4111
+ return React85__default.createElement(Component, {
4019
4112
  className: cn(
4020
4113
  inline ? "inline-flex" : "flex",
4021
4114
  horizontal && "justify-center",
@@ -4283,7 +4376,7 @@ var init_Radio = __esm({
4283
4376
  md: "w-2.5 h-2.5",
4284
4377
  lg: "w-3 h-3"
4285
4378
  };
4286
- Radio = React84__default.forwardRef(
4379
+ Radio = React85__default.forwardRef(
4287
4380
  ({
4288
4381
  label,
4289
4382
  helperText,
@@ -4300,12 +4393,12 @@ var init_Radio = __esm({
4300
4393
  onChange,
4301
4394
  ...props
4302
4395
  }, ref) => {
4303
- const reactId = React84__default.useId();
4396
+ const reactId = React85__default.useId();
4304
4397
  const baseId = id || `radio-${reactId}`;
4305
4398
  const hasError = !!error;
4306
4399
  const eventBus = useEventBus();
4307
- const [selected, setSelected] = React84__default.useState(value);
4308
- React84__default.useEffect(() => {
4400
+ const [selected, setSelected] = React85__default.useState(value);
4401
+ React85__default.useEffect(() => {
4309
4402
  if (value !== void 0) setSelected(value);
4310
4403
  }, [value]);
4311
4404
  const pick = (next, e) => {
@@ -4487,7 +4580,7 @@ var init_Switch = __esm({
4487
4580
  "components/core/atoms/Switch.tsx"() {
4488
4581
  "use client";
4489
4582
  init_cn();
4490
- Switch = React84.forwardRef(
4583
+ Switch = React85.forwardRef(
4491
4584
  ({
4492
4585
  checked,
4493
4586
  defaultChecked = false,
@@ -4498,10 +4591,10 @@ var init_Switch = __esm({
4498
4591
  name,
4499
4592
  className
4500
4593
  }, ref) => {
4501
- const [isChecked, setIsChecked] = React84.useState(
4594
+ const [isChecked, setIsChecked] = React85.useState(
4502
4595
  checked !== void 0 ? checked : defaultChecked
4503
4596
  );
4504
- React84.useEffect(() => {
4597
+ React85.useEffect(() => {
4505
4598
  if (checked !== void 0) {
4506
4599
  setIsChecked(checked);
4507
4600
  }
@@ -4664,7 +4757,7 @@ var init_Stack = __esm({
4664
4757
  };
4665
4758
  const isHorizontal = direction === "horizontal";
4666
4759
  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";
4667
- return React84__default.createElement(
4760
+ return React85__default.createElement(
4668
4761
  Component,
4669
4762
  {
4670
4763
  className: cn(
@@ -4864,7 +4957,7 @@ var Aside;
4864
4957
  var init_Aside = __esm({
4865
4958
  "components/core/atoms/Aside.tsx"() {
4866
4959
  init_cn();
4867
- Aside = React84__default.forwardRef(
4960
+ Aside = React85__default.forwardRef(
4868
4961
  ({ className, children, ...rest }, ref) => /* @__PURE__ */ jsx("aside", { ref, className: cn(className), ...rest, children })
4869
4962
  );
4870
4963
  Aside.displayName = "Aside";
@@ -4943,9 +5036,9 @@ var init_LawReferenceTooltip = __esm({
4943
5036
  className
4944
5037
  }) => {
4945
5038
  const { t } = useTranslate();
4946
- const [isVisible, setIsVisible] = React84__default.useState(false);
4947
- const timeoutRef = React84__default.useRef(null);
4948
- const triggerRef = React84__default.useRef(null);
5039
+ const [isVisible, setIsVisible] = React85__default.useState(false);
5040
+ const timeoutRef = React85__default.useRef(null);
5041
+ const triggerRef = React85__default.useRef(null);
4949
5042
  const handleMouseEnter = () => {
4950
5043
  if (timeoutRef.current) clearTimeout(timeoutRef.current);
4951
5044
  timeoutRef.current = setTimeout(() => setIsVisible(true), 200);
@@ -4956,7 +5049,7 @@ var init_LawReferenceTooltip = __esm({
4956
5049
  };
4957
5050
  const { revealed, triggerProps } = useTapReveal({ refs: [triggerRef] });
4958
5051
  const open = isVisible || revealed;
4959
- React84__default.useEffect(() => {
5052
+ React85__default.useEffect(() => {
4960
5053
  return () => {
4961
5054
  if (timeoutRef.current) clearTimeout(timeoutRef.current);
4962
5055
  };
@@ -5166,7 +5259,7 @@ var init_StatusDot = __esm({
5166
5259
  md: "w-2.5 h-2.5",
5167
5260
  lg: "w-3 h-3"
5168
5261
  };
5169
- StatusDot = React84__default.forwardRef(
5262
+ StatusDot = React85__default.forwardRef(
5170
5263
  ({ className, status = "offline", pulse = false, size = "md", label, ...props }, ref) => {
5171
5264
  return /* @__PURE__ */ jsx(
5172
5265
  "span",
@@ -5220,7 +5313,7 @@ var init_TrendIndicator = __esm({
5220
5313
  down: "trending-down",
5221
5314
  flat: "arrow-right"
5222
5315
  };
5223
- TrendIndicator = React84__default.forwardRef(
5316
+ TrendIndicator = React85__default.forwardRef(
5224
5317
  ({
5225
5318
  className,
5226
5319
  value,
@@ -5289,7 +5382,7 @@ var init_RangeSlider = __esm({
5289
5382
  md: "w-4 h-4",
5290
5383
  lg: "w-5 h-5"
5291
5384
  };
5292
- RangeSlider = React84__default.forwardRef(
5385
+ RangeSlider = React85__default.forwardRef(
5293
5386
  ({
5294
5387
  className,
5295
5388
  min = 0,
@@ -5900,7 +5993,7 @@ var init_ContentSection = __esm({
5900
5993
  md: "py-16",
5901
5994
  lg: "py-24"
5902
5995
  };
5903
- ContentSection = React84__default.forwardRef(
5996
+ ContentSection = React85__default.forwardRef(
5904
5997
  ({ children, background = "default", padding = "lg", id, className }, ref) => {
5905
5998
  return /* @__PURE__ */ jsx(
5906
5999
  Box,
@@ -6434,7 +6527,7 @@ var init_AnimatedReveal = __esm({
6434
6527
  "scale-up": { opacity: 1, transform: "scale(1) translateY(0)" },
6435
6528
  "none": {}
6436
6529
  };
6437
- AnimatedReveal = React84__default.forwardRef(
6530
+ AnimatedReveal = React85__default.forwardRef(
6438
6531
  ({
6439
6532
  trigger = "scroll",
6440
6533
  animation = "fade-up",
@@ -6594,7 +6687,7 @@ var init_AnimatedGraphic = __esm({
6594
6687
  "components/marketing/atoms/AnimatedGraphic.tsx"() {
6595
6688
  "use client";
6596
6689
  init_cn();
6597
- AnimatedGraphic = React84__default.forwardRef(
6690
+ AnimatedGraphic = React85__default.forwardRef(
6598
6691
  ({
6599
6692
  src,
6600
6693
  svgContent,
@@ -6617,7 +6710,7 @@ var init_AnimatedGraphic = __esm({
6617
6710
  const fetchedSvg = useFetchedSvg(svgContent ? void 0 : src);
6618
6711
  const resolvedSvg = svgContent ?? fetchedSvg;
6619
6712
  const prevAnimateRef = useRef(animate);
6620
- const setRef = React84__default.useCallback(
6713
+ const setRef = React85__default.useCallback(
6621
6714
  (node) => {
6622
6715
  containerRef.current = node;
6623
6716
  if (typeof ref === "function") ref(node);
@@ -7085,46 +7178,45 @@ var init_useImageCache = __esm({
7085
7178
  });
7086
7179
 
7087
7180
  // lib/isometric.ts
7088
- function isoToScreen(tileX, tileY, scale, baseOffsetX, layout = "isometric") {
7089
- const scaledTileWidth = TILE_WIDTH * scale;
7090
- const scaledFloorHeight = FLOOR_HEIGHT * scale;
7181
+ function isoToScreen(tileX, tileY, cellWidth, baseOffsetX, layout = "isometric") {
7182
+ const w = cellWidth;
7183
+ const fh = cellWidth / 2;
7091
7184
  if (layout === "hex") {
7092
- const screenX2 = tileX * scaledTileWidth + (tileY & 1) * (scaledTileWidth / 2) + baseOffsetX;
7093
- const screenY2 = tileY * (scaledFloorHeight * 0.75);
7185
+ const screenX2 = tileX * w + (tileY & 1) * (w / 2) + baseOffsetX;
7186
+ const screenY2 = tileY * (fh * 0.75);
7094
7187
  return { x: screenX2, y: screenY2 };
7095
7188
  }
7096
7189
  if (layout === "flat") {
7097
- const screenX2 = tileX * scaledTileWidth + baseOffsetX;
7098
- const screenY2 = tileY * scaledTileWidth;
7190
+ const screenX2 = tileX * w + baseOffsetX;
7191
+ const screenY2 = tileY * w;
7099
7192
  return { x: screenX2, y: screenY2 };
7100
7193
  }
7101
- const screenX = (tileX - tileY) * (scaledTileWidth / 2) + baseOffsetX;
7102
- const screenY = (tileX + tileY) * (scaledFloorHeight / 2);
7194
+ const screenX = (tileX - tileY) * (w / 2) + baseOffsetX;
7195
+ const screenY = (tileX + tileY) * (fh / 2);
7103
7196
  return { x: screenX, y: screenY };
7104
7197
  }
7105
- function screenToIso(screenX, screenY, scale, baseOffsetX, layout = "isometric") {
7106
- const scaledTileWidth = TILE_WIDTH * scale;
7107
- const scaledFloorHeight = FLOOR_HEIGHT * scale;
7198
+ function screenToIso(screenX, screenY, cellWidth, baseOffsetX, layout = "isometric") {
7199
+ const w = cellWidth;
7200
+ const fh = cellWidth / 2;
7108
7201
  if (layout === "hex") {
7109
- const row = Math.round(screenY / (scaledFloorHeight * 0.75));
7110
- const col = Math.round((screenX - (row & 1) * (scaledTileWidth / 2) - baseOffsetX) / scaledTileWidth);
7202
+ const row = Math.round(screenY / (fh * 0.75));
7203
+ const col = Math.round((screenX - (row & 1) * (w / 2) - baseOffsetX) / w);
7111
7204
  return { x: col, y: row };
7112
7205
  }
7113
7206
  if (layout === "flat") {
7114
- const col = Math.round((screenX - baseOffsetX) / scaledTileWidth);
7115
- const row = Math.round(screenY / scaledTileWidth);
7207
+ const col = Math.round((screenX - baseOffsetX) / w);
7208
+ const row = Math.round(screenY / w);
7116
7209
  return { x: col, y: row };
7117
7210
  }
7118
7211
  const adjustedX = screenX - baseOffsetX;
7119
- const tileX = (adjustedX / (scaledTileWidth / 2) + screenY / (scaledFloorHeight / 2)) / 2;
7120
- const tileY = (screenY / (scaledFloorHeight / 2) - adjustedX / (scaledTileWidth / 2)) / 2;
7212
+ const tileX = (adjustedX / (w / 2) + screenY / (fh / 2)) / 2;
7213
+ const tileY = (screenY / (fh / 2) - adjustedX / (w / 2)) / 2;
7121
7214
  return { x: Math.round(tileX), y: Math.round(tileY) };
7122
7215
  }
7123
- var TILE_WIDTH, FLOOR_HEIGHT, DIAMOND_TOP_Y, BACKGROUND_FALLBACK_COLOR, MINIMAP_TERRAIN_COLORS;
7216
+ var TILE_WIDTH, DIAMOND_TOP_Y, BACKGROUND_FALLBACK_COLOR, MINIMAP_TERRAIN_COLORS;
7124
7217
  var init_isometric = __esm({
7125
7218
  "lib/isometric.ts"() {
7126
7219
  TILE_WIDTH = 256;
7127
- FLOOR_HEIGHT = 128;
7128
7220
  DIAMOND_TOP_Y = 374;
7129
7221
  BACKGROUND_FALLBACK_COLOR = "#1a1a2e";
7130
7222
  MINIMAP_TERRAIN_COLORS = {
@@ -7346,9 +7438,9 @@ function ControlButton({
7346
7438
  className
7347
7439
  }) {
7348
7440
  const eventBus = useEventBus();
7349
- const [isPressed, setIsPressed] = React84.useState(false);
7441
+ const [isPressed, setIsPressed] = React85.useState(false);
7350
7442
  const actualPressed = pressed ?? isPressed;
7351
- const handlePointerDown = React84.useCallback(
7443
+ const handlePointerDown = React85.useCallback(
7352
7444
  (e) => {
7353
7445
  e.preventDefault();
7354
7446
  if (disabled) return;
@@ -7358,7 +7450,7 @@ function ControlButton({
7358
7450
  },
7359
7451
  [disabled, pressEvent, eventBus, onPress]
7360
7452
  );
7361
- const handlePointerUp = React84.useCallback(
7453
+ const handlePointerUp = React85.useCallback(
7362
7454
  (e) => {
7363
7455
  e.preventDefault();
7364
7456
  if (disabled) return;
@@ -7368,7 +7460,7 @@ function ControlButton({
7368
7460
  },
7369
7461
  [disabled, releaseEvent, eventBus, onRelease]
7370
7462
  );
7371
- const handlePointerLeave = React84.useCallback(
7463
+ const handlePointerLeave = React85.useCallback(
7372
7464
  (e) => {
7373
7465
  if (isPressed) {
7374
7466
  setIsPressed(false);
@@ -7626,8 +7718,8 @@ function ControlGrid({
7626
7718
  className
7627
7719
  }) {
7628
7720
  const eventBus = useEventBus();
7629
- const [active, setActive] = React84.useState(/* @__PURE__ */ new Set());
7630
- const handlePress = React84.useCallback(
7721
+ const [active, setActive] = React85.useState(/* @__PURE__ */ new Set());
7722
+ const handlePress = React85.useCallback(
7631
7723
  (id) => {
7632
7724
  setActive((prev) => new Set(prev).add(id));
7633
7725
  if (actionEvent) eventBus.emit(`UI:${actionEvent}`, { id, pressed: true });
@@ -7641,7 +7733,7 @@ function ControlGrid({
7641
7733
  },
7642
7734
  [kind, actionEvent, directionEvent, directionEvents, eventBus, onAction, onDirection]
7643
7735
  );
7644
- const handleRelease = React84.useCallback(
7736
+ const handleRelease = React85.useCallback(
7645
7737
  (id) => {
7646
7738
  setActive((prev) => {
7647
7739
  const next = new Set(prev);
@@ -7999,7 +8091,7 @@ function GameMenu({
7999
8091
  }) {
8000
8092
  const resolvedOptions = (options?.length ? options : void 0) ?? (menuItems?.length ? menuItems : void 0) ?? DEFAULT_MENU_OPTIONS;
8001
8093
  const eventBus = useEventBus();
8002
- const handleOptionClick = React84.useCallback(
8094
+ const handleOptionClick = React85.useCallback(
8003
8095
  (option) => {
8004
8096
  if (option.event) {
8005
8097
  eventBus.emit(`UI:${option.event}`, { option });
@@ -8235,7 +8327,7 @@ function StateGraph({
8235
8327
  }) {
8236
8328
  const eventBus = useEventBus();
8237
8329
  const nodes = states ?? [];
8238
- const positions = React84.useMemo(() => layoutStates(nodes, width, height), [nodes, width, height]);
8330
+ const positions = React85.useMemo(() => layoutStates(nodes, width, height), [nodes, width, height]);
8239
8331
  return /* @__PURE__ */ jsxs(
8240
8332
  Box,
8241
8333
  {
@@ -8306,12 +8398,13 @@ function MiniMap({
8306
8398
  tileAssets,
8307
8399
  unitAssets
8308
8400
  }) {
8309
- const canvasRef = React84.useRef(null);
8310
- const imgCacheRef = React84.useRef(/* @__PURE__ */ new Map());
8401
+ const canvasRef = React85.useRef(null);
8402
+ const imgCacheRef = React85.useRef(/* @__PURE__ */ new Map());
8311
8403
  function loadImg(url) {
8312
8404
  const cached = imgCacheRef.current.get(url);
8313
8405
  if (cached) return cached.complete ? cached : null;
8314
8406
  const img = new Image();
8407
+ img.crossOrigin = "anonymous";
8315
8408
  img.src = url;
8316
8409
  img.onload = () => {
8317
8410
  const canvas = canvasRef.current;
@@ -8322,7 +8415,7 @@ function MiniMap({
8322
8415
  imgCacheRef.current.set(url, img);
8323
8416
  return null;
8324
8417
  }
8325
- React84.useEffect(() => {
8418
+ React85.useEffect(() => {
8326
8419
  const canvas = canvasRef.current;
8327
8420
  if (!canvas) return;
8328
8421
  const ctx = canvas.getContext("2d");
@@ -8479,7 +8572,7 @@ function useCamera(initial) {
8479
8572
  const handleWheel = useCallback((e, drawFn) => {
8480
8573
  e.preventDefault();
8481
8574
  const zoomDelta = e.deltaY > 0 ? 0.9 : 1.1;
8482
- cameraRef.current.zoom = Math.max(0.5, Math.min(3, cameraRef.current.zoom * zoomDelta));
8575
+ cameraRef.current.zoom = Math.max(MIN_ZOOM, Math.min(MAX_ZOOM, cameraRef.current.zoom * zoomDelta));
8483
8576
  drawFn?.();
8484
8577
  }, []);
8485
8578
  const handlePointerDown = useCallback((e) => {
@@ -8500,7 +8593,7 @@ function useCamera(initial) {
8500
8593
  const zoomAtPoint = useCallback((factor, centerX, centerY, viewportSize, drawFn) => {
8501
8594
  const cam = cameraRef.current;
8502
8595
  const oldZoom = cam.zoom;
8503
- const newZoom = Math.max(0.5, Math.min(3, oldZoom * factor));
8596
+ const newZoom = Math.max(MIN_ZOOM, Math.min(MAX_ZOOM, oldZoom * factor));
8504
8597
  if (newZoom === oldZoom) {
8505
8598
  drawFn?.();
8506
8599
  return;
@@ -8552,9 +8645,12 @@ function useCamera(initial) {
8552
8645
  lerpToTarget
8553
8646
  };
8554
8647
  }
8648
+ var MIN_ZOOM, MAX_ZOOM;
8555
8649
  var init_useCamera = __esm({
8556
8650
  "hooks/useCamera.ts"() {
8557
8651
  "use client";
8652
+ MIN_ZOOM = 0.05;
8653
+ MAX_ZOOM = 10;
8558
8654
  }
8559
8655
  });
8560
8656
  function localPoint(canvas, clientX, clientY) {
@@ -8675,6 +8771,7 @@ function getOrLoadImage(url, onReady) {
8675
8771
  return null;
8676
8772
  }
8677
8773
  const img = new Image();
8774
+ img.crossOrigin = "anonymous";
8678
8775
  const entry = { img, status: "pending", onReady };
8679
8776
  cache.set(url, entry);
8680
8777
  updateAssetStatus(url, "pending");
@@ -8686,10 +8783,14 @@ function getOrLoadImage(url, onReady) {
8686
8783
  img.onerror = () => {
8687
8784
  entry.status = "failed";
8688
8785
  updateAssetStatus(url, "failed");
8786
+ entry.onReady?.();
8689
8787
  };
8690
8788
  img.src = url;
8691
8789
  return null;
8692
8790
  }
8791
+ function getImageStatus(url) {
8792
+ return cache.get(url)?.status;
8793
+ }
8693
8794
  var cache;
8694
8795
  var init_imageCache = __esm({
8695
8796
  "lib/imageCache.ts"() {
@@ -8828,12 +8929,13 @@ var init_webPainter2d = __esm({
8828
8929
 
8829
8930
  // lib/drawable/projector.ts
8830
8931
  function create2DProjector(opts) {
8831
- const { scale, baseOffsetX, layout } = opts;
8832
- const tileWidth = layout === "free" ? 1 : TILE_WIDTH * scale;
8833
- const floorHeight = layout === "free" ? 1 : FLOOR_HEIGHT * scale;
8834
- const diamondTopY = layout === "free" ? 0 : (opts.diamondTopY ?? DIAMOND_TOP_Y) * scale;
8932
+ const { baseOffsetX, layout } = opts;
8933
+ const tw = opts.tileWidth ?? TILE_WIDTH;
8934
+ const tileWidth = layout === "free" ? 1 : tw;
8935
+ const floorHeight = layout === "free" ? 1 : tw / 2;
8936
+ const diamondTopY = layout === "free" ? 0 : opts.diamondTopY ?? tw * (DIAMOND_TOP_Y / TILE_WIDTH);
8835
8937
  const squareGrid = layout === "flat" || layout === "free";
8836
- const project = (pos) => layout === "free" ? { x: pos.x, y: pos.y } : isoToScreen(pos.x, pos.y, scale, baseOffsetX, layout);
8938
+ const project = (pos) => layout === "free" ? { x: pos.x, y: pos.y } : isoToScreen(pos.x, pos.y, tw, baseOffsetX, layout);
8837
8939
  const anchorPoint = (pos, anchor) => {
8838
8940
  const base = project(pos);
8839
8941
  if (anchor === "top-left") return base;
@@ -8864,7 +8966,7 @@ function create2DProjector(opts) {
8864
8966
  { x: base.x, y: topY + floorHeight / 2 }
8865
8967
  ];
8866
8968
  };
8867
- return { project, anchorPoint, cellPath, tileWidth, floorHeight, diamondTopY, scale, squareGrid };
8969
+ return { project, anchorPoint, cellPath, tileWidth, floorHeight, diamondTopY, squareGrid, worldPixelDirect: layout === "free" };
8868
8970
  }
8869
8971
  var init_projector = __esm({
8870
8972
  "lib/drawable/projector.ts"() {
@@ -8880,32 +8982,67 @@ var init_contract = __esm({
8880
8982
  "lib/drawable/contract.ts"() {
8881
8983
  }
8882
8984
  });
8883
-
8884
- // components/game/atoms/DrawSprite.tsx
8985
+ function warnMissingOnce(reason, node) {
8986
+ const key = `${reason}:${node.asset.url}:${String(node.asset.atlas)}:${String(node.asset.sprite)}`;
8987
+ if (loggedMissing.has(key)) return;
8988
+ loggedMissing.add(key);
8989
+ spriteLog.warn("draw-sprite asset unresolvable \u2014 painting fallback square", { reason, url: node.asset.url, atlas: node.asset.atlas, sprite: node.asset.sprite });
8990
+ }
8991
+ function paintFallbackSquare(painter, node, dctx, reason) {
8992
+ warnMissingOnce(reason, node);
8993
+ const tw = dctx.projector.tileWidth;
8994
+ const natural = dctx.projector.worldPixelDirect ? FALLBACK_WORLD_PX : tw;
8995
+ const w = node.width !== void 0 ? node.width * tw : natural;
8996
+ const h = node.height !== void 0 ? node.height * tw : natural;
8997
+ const anchor = node.anchor ?? "top-left";
8998
+ const p = dctx.projector.anchorPoint(node.position, anchor);
8999
+ const dx = anchor === "top-left" ? p.x : p.x - w / 2;
9000
+ const dy = anchor === "ground" ? p.y - h : anchor === "center" ? p.y - h / 2 : p.y;
9001
+ painter.save();
9002
+ if (node.opacity !== void 0 && node.opacity !== 1) painter.setAlpha(node.opacity);
9003
+ painter.fillRect(dx, dy, w, h, "#9b8f7f");
9004
+ painter.strokeRect(dx, dy, w, h, "#5e564b", Math.max(1, tw / 32));
9005
+ painter.restore();
9006
+ }
8885
9007
  function DrawSprite(_props) {
8886
9008
  return null;
8887
9009
  }
8888
- var paintSprite;
9010
+ var spriteLog, loggedMissing, FALLBACK_WORLD_PX, paintSprite;
8889
9011
  var init_DrawSprite = __esm({
8890
9012
  "components/game/atoms/DrawSprite.tsx"() {
8891
9013
  "use client";
8892
9014
  init_atlasSlice();
9015
+ init_imageCache();
8893
9016
  init_contract();
9017
+ spriteLog = createLogger("almadar:ui:draw-sprite");
9018
+ loggedMissing = /* @__PURE__ */ new Set();
9019
+ FALLBACK_WORLD_PX = 32;
8894
9020
  paintSprite = (painter, node, dctx) => {
8895
9021
  if (!node.asset?.url || !isValidScenePos(node.position)) return;
8896
9022
  const tex = painter.resolveTexture(node.asset.url);
8897
- if (!tex) return;
9023
+ if (!tex) {
9024
+ if (getImageStatus(node.asset.url) === "failed") paintFallbackSquare(painter, node, dctx, "texture-failed");
9025
+ return;
9026
+ }
8898
9027
  let src = typeof node.frame === "object" ? node.frame : void 0;
8899
9028
  if (!src && isAtlasAsset(node.asset)) {
8900
9029
  const atlas = getAtlas(node.asset.atlas, dctx.invalidate);
8901
- if (!atlas) return;
9030
+ if (!atlas) {
9031
+ if (atlasFailed(node.asset.atlas)) paintFallbackSquare(painter, node, dctx, "atlas-failed");
9032
+ return;
9033
+ }
8902
9034
  const r = subRectFor(atlas, node.asset.sprite);
8903
- if (!r) return;
9035
+ if (!r) {
9036
+ paintFallbackSquare(painter, node, dctx, "sprite-missing");
9037
+ return;
9038
+ }
8904
9039
  src = { x: r.sx, y: r.sy, w: r.sw, h: r.sh };
8905
9040
  }
8906
9041
  const tw = dctx.projector.tileWidth;
8907
- const w = node.width !== void 0 ? node.width * tw : src ? src.w : tex.width;
8908
- const h = node.height !== void 0 ? node.height * tw : src ? src.h : tex.height;
9042
+ const fallbackW = dctx.projector.worldPixelDirect ? src ? src.w : tex.width : tw;
9043
+ const fallbackH = dctx.projector.worldPixelDirect ? src ? src.h : tex.height : tw;
9044
+ const w = node.width !== void 0 ? node.width * tw : fallbackW;
9045
+ const h = node.height !== void 0 ? node.height * tw : fallbackH;
8909
9046
  const anchor = node.anchor ?? "top-left";
8910
9047
  const p = dctx.projector.anchorPoint(node.position, anchor);
8911
9048
  const dx = anchor === "top-left" ? p.x : p.x - w / 2;
@@ -9171,6 +9308,8 @@ function Canvas2D({
9171
9308
  keyUpMap,
9172
9309
  camera = "pan-zoom",
9173
9310
  scale = 0.4,
9311
+ tileWidth,
9312
+ fit = false,
9174
9313
  showMinimap = true,
9175
9314
  followTarget,
9176
9315
  cameraPos,
@@ -9213,9 +9352,32 @@ function Canvas2D({
9213
9352
  observer2.observe(el);
9214
9353
  return () => observer2.disconnect();
9215
9354
  }, []);
9216
- const scaledTileWidth = TILE_WIDTH * scale;
9217
- const scaledFloorHeight = FLOOR_HEIGHT * scale;
9218
- const scaledDiamondTopY = DIAMOND_TOP_Y * scale;
9355
+ const [atlasVersion, setAtlasVersion] = useState(0);
9356
+ const bumpAtlas = useCallback(() => setAtlasVersion((v) => v + 1), []);
9357
+ const detectedTileWidth = useMemo(() => {
9358
+ for (const n of drawables ?? []) {
9359
+ const refs = [];
9360
+ if (n.type === "draw-sprite") refs.push(n.asset);
9361
+ else if (n.type === "draw-sprite-layer") for (const it of n.items) refs.push(it.asset);
9362
+ for (const a of refs) {
9363
+ if (a && isAtlasAsset(a) && a.atlas) {
9364
+ const atlas = getAtlas(a.atlas, bumpAtlas);
9365
+ if (atlas) {
9366
+ if ("tileWidth" in atlas) return atlas.tileWidth;
9367
+ if ("subTextures" in atlas) {
9368
+ const first = Object.values(atlas.subTextures)[0];
9369
+ if (first && typeof first.width === "number") return first.width;
9370
+ }
9371
+ }
9372
+ }
9373
+ }
9374
+ }
9375
+ return void 0;
9376
+ }, [drawables, atlasVersion]);
9377
+ const nativeTileW = tileWidth ?? detectedTileWidth ?? TILE_WIDTH;
9378
+ const scaledTileWidth = nativeTileW;
9379
+ const scaledFloorHeight = nativeTileW / 2;
9380
+ const scaledDiamondTopY = nativeTileW * (DIAMOND_TOP_Y / TILE_WIDTH);
9219
9381
  const drawnItems = useMemo(() => collectDrawnItems(drawables ?? []), [drawables]);
9220
9382
  const scenePositions = useMemo(() => drawnItems.map((i) => i.pos), [drawnItems]);
9221
9383
  const hitIndex = useMemo(() => buildHitIndex(drawnItems), [drawnItems]);
@@ -9229,18 +9391,45 @@ function Canvas2D({
9229
9391
  }
9230
9392
  return { width: maxX + 1, height: maxY + 1 };
9231
9393
  }, [scenePositions]);
9394
+ const defaultGridFocus = useMemo(() => {
9395
+ if (isFree || projection === "side") return void 0;
9396
+ if (gridExtent.width < 2 || gridExtent.height < 2) return void 0;
9397
+ return { x: (gridExtent.width - 1) / 2, y: (gridExtent.height - 1) / 2 };
9398
+ }, [isFree, projection, gridExtent]);
9232
9399
  const baseOffsetX = useMemo(() => {
9233
9400
  if (isFree || projection === "flat" || projection === "side") return 0;
9234
9401
  return (gridExtent.height - 1) * (scaledTileWidth / 2);
9235
9402
  }, [isFree, projection, gridExtent.height, scaledTileWidth]);
9403
+ const effectiveZoom = useMemo(() => {
9404
+ if (isFree || projection === "side") return scale;
9405
+ if (!fit) {
9406
+ const z2 = TILE_WIDTH * scale * scale / nativeTileW;
9407
+ return Number.isFinite(z2) && z2 > 0 ? z2 : scale;
9408
+ }
9409
+ if (!viewportSize.width || gridExtent.width < 2 || gridExtent.height < 2) return scale;
9410
+ let boardW;
9411
+ let boardH;
9412
+ if (projection === "flat") {
9413
+ boardW = gridExtent.width * nativeTileW;
9414
+ boardH = gridExtent.height * nativeTileW;
9415
+ } else if (projection === "hex") {
9416
+ boardW = (gridExtent.width + 0.5) * nativeTileW;
9417
+ boardH = gridExtent.height * (nativeTileW / 2) * 0.75 + nativeTileW / 2;
9418
+ } else {
9419
+ boardW = (gridExtent.width + gridExtent.height) * (nativeTileW / 2);
9420
+ boardH = (gridExtent.width + gridExtent.height) * (nativeTileW / 4);
9421
+ }
9422
+ const z = Math.min(viewportSize.width * 0.85 / boardW, viewportSize.height * 0.85 / boardH);
9423
+ return Number.isFinite(z) && z > 0 ? z : scale;
9424
+ }, [isFree, projection, fit, viewportSize, gridExtent, nativeTileW, scale]);
9236
9425
  const projector = useMemo(
9237
- () => create2DProjector({ scale, baseOffsetX, layout }),
9238
- [scale, baseOffsetX, layout]
9426
+ () => create2DProjector({ tileWidth: nativeTileW, baseOffsetX, layout }),
9427
+ [nativeTileW, baseOffsetX, layout]
9239
9428
  );
9240
9429
  const unproject = useCallback((screenX, screenY) => {
9241
9430
  if (projection === "free" || projection === "side") return { x: Math.round(screenX), y: Math.round(screenY) };
9242
- return screenToIso(screenX, screenY, scale, baseOffsetX, projection);
9243
- }, [projection, scale, baseOffsetX]);
9431
+ return screenToIso(screenX, screenY, nativeTileW, baseOffsetX, projection);
9432
+ }, [projection, nativeTileW, baseOffsetX]);
9244
9433
  const bgUrls = useMemo(() => backgroundImage ? [backgroundImage.url] : [], [backgroundImage]);
9245
9434
  const { getImage, pendingCount: _imagePendingCount } = useImageCache(bgUrls);
9246
9435
  useEffect(() => {
@@ -9267,9 +9456,7 @@ function Canvas2D({
9267
9456
  zoomAtPoint,
9268
9457
  screenToWorld,
9269
9458
  lerpToTarget
9270
- } = useCamera({ zoom: scale });
9271
- const [atlasVersion, setAtlasVersion] = useState(0);
9272
- const bumpAtlas = useCallback(() => setAtlasVersion((v) => v + 1), []);
9459
+ } = useCamera({ zoom: effectiveZoom });
9273
9460
  const miniMapTiles = useMemo(() => {
9274
9461
  if (!showMinimap) return [];
9275
9462
  const color = MINIMAP_TERRAIN_COLORS.default;
@@ -9313,10 +9500,13 @@ function Canvas2D({
9313
9500
  }
9314
9501
  if (!drawables || drawables.length === 0) return;
9315
9502
  const cam = cameraRef.current;
9316
- if (cameraPos && dragDistance() === 0) {
9317
- const p = projector.anchorPoint(cameraPos, "center");
9318
- cam.x = p.x - viewportSize.width / 2;
9319
- cam.y = p.y - viewportSize.height / 2;
9503
+ if (camera !== "follow" && dragDistance() === 0) {
9504
+ const focus = cameraPos ?? defaultGridFocus;
9505
+ if (focus) {
9506
+ const p = projector.anchorPoint(focus, "center");
9507
+ cam.x = p.x - viewportSize.width / 2;
9508
+ cam.y = p.y - viewportSize.height / 2;
9509
+ }
9320
9510
  }
9321
9511
  const containerRect = containerRef.current?.getBoundingClientRect();
9322
9512
  const canvasRect = canvas.getBoundingClientRect();
@@ -9329,7 +9519,7 @@ function Canvas2D({
9329
9519
  const dctx = { projector, time: 0, invalidate: bumpAtlas };
9330
9520
  for (const node of drawables) paintDrawable(painter, node, dctx);
9331
9521
  painter.restore();
9332
- }, [viewportSize, backgroundImage, bgColor, drawables, projector, cameraRef, bumpAtlas, getImage]);
9522
+ }, [viewportSize, backgroundImage, bgColor, drawables, projector, cameraRef, bumpAtlas, getImage, cameraPos, defaultGridFocus, camera, dragDistance]);
9333
9523
  useEffect(() => {
9334
9524
  if (camera !== "follow" || !followTarget) return;
9335
9525
  const p = projector.anchorPoint(followTarget, "center");
@@ -9344,6 +9534,13 @@ function Canvas2D({
9344
9534
  useEffect(() => {
9345
9535
  draw();
9346
9536
  }, [_imagePendingCount, draw]);
9537
+ const userZoomedRef = useRef(false);
9538
+ useEffect(() => {
9539
+ if (userZoomedRef.current) return;
9540
+ if (cameraRef.current.zoom === effectiveZoom) return;
9541
+ cameraRef.current.zoom = effectiveZoom;
9542
+ draw();
9543
+ }, [effectiveZoom, cameraRef, draw]);
9347
9544
  useEffect(() => {
9348
9545
  draw();
9349
9546
  }, [atlasVersion, draw]);
@@ -9400,7 +9597,9 @@ function Canvas2D({
9400
9597
  if (tileLeaveEvent) eventBus.emit(`UI:${tileLeaveEvent}`, {});
9401
9598
  }, [handleMouseLeave, tileLeaveEvent, eventBus]);
9402
9599
  const applyZoom = useCallback((factor, centerX, centerY) => {
9403
- if (enableCamera) zoomAtPoint(factor, centerX, centerY, viewportSize, () => draw());
9600
+ if (!enableCamera) return;
9601
+ userZoomedRef.current = true;
9602
+ zoomAtPoint(factor, centerX, centerY, viewportSize, () => draw());
9404
9603
  }, [enableCamera, zoomAtPoint, viewportSize, draw]);
9405
9604
  const applyPanDelta = useCallback((dx, dy) => {
9406
9605
  if (enableCamera) panBy(dx, dy, () => draw());
@@ -9585,6 +9784,8 @@ function Canvas({
9585
9784
  isLoading,
9586
9785
  unitScale,
9587
9786
  showMinimap,
9787
+ fit,
9788
+ tileWidth,
9588
9789
  backgroundImage,
9589
9790
  backgroundColor,
9590
9791
  worldWidth,
@@ -9642,6 +9843,8 @@ function Canvas({
9642
9843
  projection,
9643
9844
  camera: to2DCamera(camera?.mode),
9644
9845
  ...zoom !== void 0 ? { scale: zoom } : {},
9846
+ ...fit !== void 0 ? { fit } : {},
9847
+ ...tileWidth !== void 0 ? { tileWidth } : {},
9645
9848
  ...camera?.target !== void 0 ? { followTarget: camera.target } : {},
9646
9849
  ...camera?.pos !== void 0 ? { cameraPos: camera.pos } : {},
9647
9850
  showMinimap,
@@ -10051,7 +10254,7 @@ function LinearView({
10051
10254
  /* @__PURE__ */ jsx(HStack, { className: "flex-wrap items-center", gap: "xs", children: trait.states.map((state, i) => {
10052
10255
  const isDone = i < currentIdx;
10053
10256
  const isCurrent = i === currentIdx;
10054
- return /* @__PURE__ */ jsxs(React84__default.Fragment, { children: [
10257
+ return /* @__PURE__ */ jsxs(React85__default.Fragment, { children: [
10055
10258
  i > 0 && /* @__PURE__ */ jsx(
10056
10259
  Typography,
10057
10260
  {
@@ -10586,7 +10789,7 @@ function SequenceBar({
10586
10789
  else onSlotRemove?.(index);
10587
10790
  }, [emit, slotRemoveEvent, onSlotRemove, playing]);
10588
10791
  const paddedSlots = Array.from({ length: maxSlots }, (_, i) => slots[i]);
10589
- return /* @__PURE__ */ jsx(HStack, { className: cn("items-center", className), gap: "sm", children: paddedSlots.map((slot, i) => /* @__PURE__ */ jsxs(React84__default.Fragment, { children: [
10792
+ return /* @__PURE__ */ jsx(HStack, { className: cn("items-center", className), gap: "sm", children: paddedSlots.map((slot, i) => /* @__PURE__ */ jsxs(React85__default.Fragment, { children: [
10590
10793
  i > 0 && /* @__PURE__ */ jsx(
10591
10794
  Typography,
10592
10795
  {
@@ -11235,7 +11438,7 @@ var init_ErrorBoundary = __esm({
11235
11438
  }
11236
11439
  );
11237
11440
  };
11238
- ErrorBoundary = class extends React84__default.Component {
11441
+ ErrorBoundary = class extends React85__default.Component {
11239
11442
  constructor(props) {
11240
11443
  super(props);
11241
11444
  __publicField(this, "reset", () => {
@@ -11887,7 +12090,7 @@ var init_Container = __esm({
11887
12090
  as: Component = "div"
11888
12091
  }) => {
11889
12092
  const resolvedSize = maxWidth ?? size ?? "lg";
11890
- return React84__default.createElement(
12093
+ return React85__default.createElement(
11891
12094
  Component,
11892
12095
  {
11893
12096
  className: cn(
@@ -14852,7 +15055,7 @@ var init_CodeBlock = __esm({
14852
15055
  DIFF_STYLE_FALLBACK = { bg: "", prefix: " ", text: "text-foreground" };
14853
15056
  LINE_PROPS_FN = (n) => ({ "data-line": String(n - 1) });
14854
15057
  HIDDEN_LINE_NUMBERS = { display: "none" };
14855
- CodeBlock = React84__default.memo(
15058
+ CodeBlock = React85__default.memo(
14856
15059
  ({
14857
15060
  code: rawCode,
14858
15061
  language = "text",
@@ -15440,7 +15643,7 @@ var init_MarkdownContent = __esm({
15440
15643
  init_Box();
15441
15644
  init_CodeBlock();
15442
15645
  init_cn();
15443
- MarkdownContent = React84__default.memo(
15646
+ MarkdownContent = React85__default.memo(
15444
15647
  ({ content, direction = "ltr", className }) => {
15445
15648
  const { t: _t } = useTranslate();
15446
15649
  const safeContent = typeof content === "string" ? content : String(content ?? "");
@@ -16767,7 +16970,7 @@ var init_StateMachineView = __esm({
16767
16970
  style: { top: title ? 30 : 0 },
16768
16971
  children: [
16769
16972
  entity && /* @__PURE__ */ jsx(EntityBox, { entity, config }),
16770
- states.map((state) => renderStateNode ? /* @__PURE__ */ jsx(React84__default.Fragment, { children: renderStateNode(state, config) }, state.id) : /* @__PURE__ */ jsx(
16973
+ states.map((state) => renderStateNode ? /* @__PURE__ */ jsx(React85__default.Fragment, { children: renderStateNode(state, config) }, state.id) : /* @__PURE__ */ jsx(
16771
16974
  StateNode2,
16772
16975
  {
16773
16976
  state,
@@ -22589,8 +22792,8 @@ var init_Menu = __esm({
22589
22792
  "bottom-end": "bottom-start"
22590
22793
  };
22591
22794
  const effectivePosition = direction === "rtl" ? rtlMirror[position] ?? position : position;
22592
- const triggerChild = React84__default.isValidElement(trigger) ? trigger : /* @__PURE__ */ jsx(Typography, { variant: "small", as: "span", children: trigger });
22593
- const triggerElement = React84__default.cloneElement(
22795
+ const triggerChild = React85__default.isValidElement(trigger) ? trigger : /* @__PURE__ */ jsx(Typography, { variant: "small", as: "span", children: trigger });
22796
+ const triggerElement = React85__default.cloneElement(
22594
22797
  triggerChild,
22595
22798
  {
22596
22799
  ref: triggerRef,
@@ -22685,14 +22888,14 @@ function useDataDnd(args) {
22685
22888
  const isZone = Boolean(dragGroup || accepts || sortable);
22686
22889
  const enabled = isZone || Boolean(dndRoot);
22687
22890
  const eventBus = useEventBus();
22688
- const parentRoot = React84__default.useContext(RootCtx);
22891
+ const parentRoot = React85__default.useContext(RootCtx);
22689
22892
  const isRoot = enabled && parentRoot === null;
22690
- const zoneId = React84__default.useId();
22893
+ const zoneId = React85__default.useId();
22691
22894
  const ownGroup = dragGroup ?? accepts ?? zoneId;
22692
- const [optimisticOrders, setOptimisticOrders] = React84__default.useState(() => /* @__PURE__ */ new Map());
22693
- const optimisticOrdersRef = React84__default.useRef(optimisticOrders);
22895
+ const [optimisticOrders, setOptimisticOrders] = React85__default.useState(() => /* @__PURE__ */ new Map());
22896
+ const optimisticOrdersRef = React85__default.useRef(optimisticOrders);
22694
22897
  optimisticOrdersRef.current = optimisticOrders;
22695
- const clearOptimisticOrder = React84__default.useCallback((group) => {
22898
+ const clearOptimisticOrder = React85__default.useCallback((group) => {
22696
22899
  setOptimisticOrders((prev) => {
22697
22900
  if (!prev.has(group)) return prev;
22698
22901
  const next = new Map(prev);
@@ -22717,7 +22920,7 @@ function useDataDnd(args) {
22717
22920
  const raw = it[dndItemIdField];
22718
22921
  return raw != null ? String(raw) : `__idx_${idx}`;
22719
22922
  }).join("|");
22720
- const itemIds = React84__default.useMemo(
22923
+ const itemIds = React85__default.useMemo(
22721
22924
  () => orderedItems.map((it, idx) => {
22722
22925
  const raw = it[dndItemIdField];
22723
22926
  return raw != null ? String(raw) : `__idx_${idx}`;
@@ -22728,7 +22931,7 @@ function useDataDnd(args) {
22728
22931
  const raw = it[dndItemIdField];
22729
22932
  return raw != null ? String(raw) : `__${idx}`;
22730
22933
  }).join("|");
22731
- React84__default.useEffect(() => {
22934
+ React85__default.useEffect(() => {
22732
22935
  const root = isRoot ? null : parentRoot;
22733
22936
  if (root) {
22734
22937
  root.clearOptimisticOrder(ownGroup);
@@ -22736,20 +22939,20 @@ function useDataDnd(args) {
22736
22939
  clearOptimisticOrder(ownGroup);
22737
22940
  }
22738
22941
  }, [itemsContentSig, ownGroup]);
22739
- const zonesRef = React84__default.useRef(/* @__PURE__ */ new Map());
22740
- const registerZone = React84__default.useCallback((zoneId2, meta2) => {
22942
+ const zonesRef = React85__default.useRef(/* @__PURE__ */ new Map());
22943
+ const registerZone = React85__default.useCallback((zoneId2, meta2) => {
22741
22944
  zonesRef.current.set(zoneId2, meta2);
22742
22945
  }, []);
22743
- const unregisterZone = React84__default.useCallback((zoneId2) => {
22946
+ const unregisterZone = React85__default.useCallback((zoneId2) => {
22744
22947
  zonesRef.current.delete(zoneId2);
22745
22948
  }, []);
22746
- const [activeDrag, setActiveDrag] = React84__default.useState(null);
22747
- const [overZoneGroup, setOverZoneGroup] = React84__default.useState(null);
22748
- const meta = React84__default.useMemo(
22949
+ const [activeDrag, setActiveDrag] = React85__default.useState(null);
22950
+ const [overZoneGroup, setOverZoneGroup] = React85__default.useState(null);
22951
+ const meta = React85__default.useMemo(
22749
22952
  () => ({ group: ownGroup, dropEvent, reorderEvent, positionEvent, itemIds, rawItems: items, idField: dndItemIdField }),
22750
22953
  [ownGroup, dropEvent, reorderEvent, positionEvent, itemIds, items, dndItemIdField]
22751
22954
  );
22752
- React84__default.useEffect(() => {
22955
+ React85__default.useEffect(() => {
22753
22956
  const target = isRoot ? null : parentRoot;
22754
22957
  if (!target) {
22755
22958
  zonesRef.current.set(zoneId, meta);
@@ -22768,7 +22971,7 @@ function useDataDnd(args) {
22768
22971
  }, [parentRoot, isRoot, zoneId, meta]);
22769
22972
  const sensors = useAlmadarDndSensors(true);
22770
22973
  const collisionDetection = almadarDndCollisionDetection;
22771
- const findZoneByItem = React84__default.useCallback(
22974
+ const findZoneByItem = React85__default.useCallback(
22772
22975
  (id) => {
22773
22976
  for (const z of zonesRef.current.values()) {
22774
22977
  if (z.itemIds.includes(id)) return z;
@@ -22777,7 +22980,7 @@ function useDataDnd(args) {
22777
22980
  },
22778
22981
  []
22779
22982
  );
22780
- React84__default.useCallback(
22983
+ React85__default.useCallback(
22781
22984
  (group) => {
22782
22985
  for (const z of zonesRef.current.values()) {
22783
22986
  if (z.group === group) return z;
@@ -22786,7 +22989,7 @@ function useDataDnd(args) {
22786
22989
  },
22787
22990
  []
22788
22991
  );
22789
- const handleDragEnd = React84__default.useCallback(
22992
+ const handleDragEnd = React85__default.useCallback(
22790
22993
  (event) => {
22791
22994
  const { active, over } = event;
22792
22995
  const activeIdStr = String(active.id);
@@ -22877,8 +23080,8 @@ function useDataDnd(args) {
22877
23080
  },
22878
23081
  [eventBus]
22879
23082
  );
22880
- const sortableData = React84__default.useMemo(() => ({ dndGroup: ownGroup }), [ownGroup]);
22881
- const SortableItem = React84__default.useCallback(
23083
+ const sortableData = React85__default.useMemo(() => ({ dndGroup: ownGroup }), [ownGroup]);
23084
+ const SortableItem = React85__default.useCallback(
22882
23085
  ({ id, children }) => {
22883
23086
  const {
22884
23087
  attributes,
@@ -22918,7 +23121,7 @@ function useDataDnd(args) {
22918
23121
  id: droppableId,
22919
23122
  data: sortableData
22920
23123
  });
22921
- const ctx = React84__default.useContext(RootCtx);
23124
+ const ctx = React85__default.useContext(RootCtx);
22922
23125
  const activeDrag2 = ctx?.activeDrag ?? null;
22923
23126
  const overZoneGroup2 = ctx?.overZoneGroup ?? null;
22924
23127
  const isThisZoneOver = overZoneGroup2 === ownGroup;
@@ -22933,7 +23136,7 @@ function useDataDnd(args) {
22933
23136
  showForeignPlaceholder,
22934
23137
  ctxAvailable: ctx != null
22935
23138
  });
22936
- React84__default.useEffect(() => {
23139
+ React85__default.useEffect(() => {
22937
23140
  dndLog.info("dropzone:isOver:change", { droppableId, group: ownGroup, isOver, isThisZoneOver, showForeignPlaceholder, activeDragSourceGroup: activeDrag2?.sourceGroup ?? null });
22938
23141
  }, [droppableId, isOver, isThisZoneOver, showForeignPlaceholder]);
22939
23142
  return /* @__PURE__ */ jsx(
@@ -22947,11 +23150,11 @@ function useDataDnd(args) {
22947
23150
  }
22948
23151
  );
22949
23152
  };
22950
- const rootContextValue = React84__default.useMemo(
23153
+ const rootContextValue = React85__default.useMemo(
22951
23154
  () => ({ registerZone, unregisterZone, activeDrag, overZoneGroup, optimisticOrders, clearOptimisticOrder }),
22952
23155
  [registerZone, unregisterZone, activeDrag, overZoneGroup, optimisticOrders, clearOptimisticOrder]
22953
23156
  );
22954
- const handleDragStart = React84__default.useCallback((event) => {
23157
+ const handleDragStart = React85__default.useCallback((event) => {
22955
23158
  const sourceZone = findZoneByItem(event.active.id);
22956
23159
  const rect = event.active.rect.current.initial;
22957
23160
  const height = rect?.height && rect.height > 0 ? rect.height : 64;
@@ -22970,7 +23173,7 @@ function useDataDnd(args) {
22970
23173
  isRoot
22971
23174
  });
22972
23175
  }, [findZoneByItem, isRoot, zoneId]);
22973
- const handleDragOver = React84__default.useCallback((event) => {
23176
+ const handleDragOver = React85__default.useCallback((event) => {
22974
23177
  const { active, over } = event;
22975
23178
  const overData = over?.data?.current;
22976
23179
  const overGroup = overData?.dndGroup ?? null;
@@ -23040,7 +23243,7 @@ function useDataDnd(args) {
23040
23243
  return next;
23041
23244
  });
23042
23245
  }, []);
23043
- const handleDragCancel = React84__default.useCallback((event) => {
23246
+ const handleDragCancel = React85__default.useCallback((event) => {
23044
23247
  setActiveDrag(null);
23045
23248
  setOverZoneGroup(null);
23046
23249
  dndLog.warn("dragCancel", {
@@ -23048,12 +23251,12 @@ function useDataDnd(args) {
23048
23251
  reason: "dnd-kit cancelled the drag (escape key, pointer interrupted, or external)"
23049
23252
  });
23050
23253
  }, []);
23051
- const handleDragEndWithCleanup = React84__default.useCallback((event) => {
23254
+ const handleDragEndWithCleanup = React85__default.useCallback((event) => {
23052
23255
  handleDragEnd(event);
23053
23256
  setActiveDrag(null);
23054
23257
  setOverZoneGroup(null);
23055
23258
  }, [handleDragEnd]);
23056
- const wrapContainer = React84__default.useCallback(
23259
+ const wrapContainer = React85__default.useCallback(
23057
23260
  (children) => {
23058
23261
  if (!enabled) return children;
23059
23262
  const strategy = layout === "grid" ? rectSortingStrategy : verticalListSortingStrategy;
@@ -23107,7 +23310,7 @@ var init_useDataDnd = __esm({
23107
23310
  init_useAlmadarDndCollision();
23108
23311
  init_Box();
23109
23312
  dndLog = createLogger("almadar:ui:dnd");
23110
- RootCtx = React84__default.createContext(null);
23313
+ RootCtx = React85__default.createContext(null);
23111
23314
  }
23112
23315
  });
23113
23316
  function renderIconInput(icon, props) {
@@ -23649,7 +23852,7 @@ function DataList({
23649
23852
  }) {
23650
23853
  const eventBus = useEventBus();
23651
23854
  const { t } = useTranslate();
23652
- const [visibleCount, setVisibleCount] = React84__default.useState(pageSize || Infinity);
23855
+ const [visibleCount, setVisibleCount] = React85__default.useState(pageSize || Infinity);
23653
23856
  const fieldDefs = fields ?? columns ?? [];
23654
23857
  const allDataRaw = Array.isArray(entity) ? entity : entity ? [entity] : [];
23655
23858
  const dnd = useDataDnd({
@@ -23665,14 +23868,14 @@ function DataList({
23665
23868
  dndRoot
23666
23869
  });
23667
23870
  const orderedData = dnd.orderedItems;
23668
- const allData = React84__default.useMemo(
23871
+ const allData = React85__default.useMemo(
23669
23872
  () => sortRows(orderedData, sortBy, sortDirection),
23670
23873
  [orderedData, sortBy, sortDirection]
23671
23874
  );
23672
23875
  const data = pageSize > 0 ? allData.slice(0, visibleCount) : allData;
23673
23876
  const hasMoreLocal = pageSize > 0 && visibleCount < allData.length;
23674
23877
  const hasRenderProp = typeof children === "function";
23675
- React84__default.useEffect(() => {
23878
+ React85__default.useEffect(() => {
23676
23879
  const renderItemTypeOf = typeof schemaRenderItem;
23677
23880
  const childrenTypeOf = typeof children;
23678
23881
  if (data.length > 0 && !hasRenderProp) {
@@ -23787,7 +23990,7 @@ function DataList({
23787
23990
  return v === void 0 || v === null || v === "" ? raw : String(v);
23788
23991
  };
23789
23992
  return /* @__PURE__ */ jsxs(VStack, { gap: "sm", className: cn("py-2", className), children: [
23790
- groups2.map((group, gi) => /* @__PURE__ */ jsxs(React84__default.Fragment, { children: [
23993
+ groups2.map((group, gi) => /* @__PURE__ */ jsxs(React85__default.Fragment, { children: [
23791
23994
  group.label && /* @__PURE__ */ jsx(Divider, { label: group.label, className: "my-2" }),
23792
23995
  group.items.map((itemData, index) => {
23793
23996
  const id = itemData.id || `${gi}-${index}`;
@@ -23823,7 +24026,11 @@ function DataList({
23823
24026
  metaFields.length > 0 && /* @__PURE__ */ jsx(HStack, { gap: "xs", className: "mt-1 flex-wrap", children: metaFields.map((f3) => {
23824
24027
  const v = getNestedValue(itemData, f3.name);
23825
24028
  if (v === void 0 || v === null || v === "") return null;
23826
- return f3.variant === "badge" ? /* @__PURE__ */ jsx(Badge, { variant: statusVariant3(String(v)), children: String(v) }, f3.name) : /* @__PURE__ */ jsx(
24029
+ return f3.variant === "badge" ? (
24030
+ // `format` applies here too — a boolean field badged
24031
+ // without it renders the raw "false" instead of "No".
24032
+ /* @__PURE__ */ jsx(Badge, { variant: statusVariant3(String(v)), children: formatValue2(v, f3.format) }, f3.name)
24033
+ ) : /* @__PURE__ */ jsx(
23827
24034
  Typography,
23828
24035
  {
23829
24036
  variant: "caption",
@@ -23935,7 +24142,7 @@ function DataList({
23935
24142
  if (val === void 0 || val === null) return null;
23936
24143
  return /* @__PURE__ */ jsxs(HStack, { gap: "xs", className: "items-center flex-shrink-0", children: [
23937
24144
  field.icon && renderIconInput2(field.icon, { size: "xs" }),
23938
- /* @__PURE__ */ jsx(Badge, { variant: statusVariant3(String(val)), children: String(val) })
24145
+ /* @__PURE__ */ jsx(Badge, { variant: statusVariant3(String(val)), children: formatValue2(val, field.format) })
23939
24146
  ] }, field.name);
23940
24147
  })
23941
24148
  ] }),
@@ -23982,7 +24189,7 @@ function DataList({
23982
24189
  className
23983
24190
  ),
23984
24191
  children: [
23985
- groups.map((group, gi) => /* @__PURE__ */ jsxs(React84__default.Fragment, { children: [
24192
+ groups.map((group, gi) => /* @__PURE__ */ jsxs(React85__default.Fragment, { children: [
23986
24193
  group.label && /* @__PURE__ */ jsx(Divider, { label: group.label, className: gi > 0 ? "mt-4" : "mt-0" }),
23987
24194
  group.items.map(
23988
24195
  (itemData, index) => renderItem(itemData, index, gi === groups.length - 1 && index === group.items.length - 1)
@@ -24069,7 +24276,7 @@ var init_FormSection = __esm({
24069
24276
  columns = 1,
24070
24277
  className
24071
24278
  }) => {
24072
- const [collapsed, setCollapsed] = React84__default.useState(defaultCollapsed);
24279
+ const [collapsed, setCollapsed] = React85__default.useState(defaultCollapsed);
24073
24280
  const { t } = useTranslate();
24074
24281
  const eventBus = useEventBus();
24075
24282
  const gridClass = {
@@ -24077,7 +24284,7 @@ var init_FormSection = __esm({
24077
24284
  2: "grid-cols-1 md:grid-cols-2",
24078
24285
  3: "grid-cols-1 md:grid-cols-2 lg:grid-cols-3"
24079
24286
  }[columns];
24080
- React84__default.useCallback(() => {
24287
+ React85__default.useCallback(() => {
24081
24288
  if (collapsible) {
24082
24289
  setCollapsed((prev) => !prev);
24083
24290
  eventBus.emit("UI:TOGGLE_COLLAPSE", { collapsed: !collapsed });
@@ -24174,6 +24381,182 @@ var init_FormSection = __esm({
24174
24381
  FormActions.displayName = "FormActions";
24175
24382
  }
24176
24383
  });
24384
+ var ALL_CATEGORY, MAX_RENDERED, GridPicker;
24385
+ var init_GridPicker = __esm({
24386
+ "components/core/molecules/GridPicker.tsx"() {
24387
+ "use client";
24388
+ init_cn();
24389
+ init_Input();
24390
+ init_Badge();
24391
+ init_Stack();
24392
+ ALL_CATEGORY = "__all__";
24393
+ MAX_RENDERED = 300;
24394
+ GridPicker = ({
24395
+ items,
24396
+ value,
24397
+ onChange,
24398
+ categories,
24399
+ searchPlaceholder,
24400
+ renderThumbnail,
24401
+ cellSize = 32,
24402
+ className
24403
+ }) => {
24404
+ const [search, setSearch] = useState("");
24405
+ const [activeCategory, setActiveCategory] = useState(ALL_CATEGORY);
24406
+ const gridRef = useRef(null);
24407
+ const categoryChips = useMemo(() => {
24408
+ if (categories !== void 0) return categories;
24409
+ const seen = [];
24410
+ for (const item of items) {
24411
+ if (!seen.includes(item.category)) seen.push(item.category);
24412
+ }
24413
+ return seen;
24414
+ }, [categories, items]);
24415
+ const filtered = useMemo(() => {
24416
+ const needle = search.trim().toLowerCase();
24417
+ return items.filter((item) => {
24418
+ const matchesCategory = activeCategory === ALL_CATEGORY || item.category === activeCategory;
24419
+ const matchesSearch = needle === "" || item.label.toLowerCase().includes(needle) || item.keywords !== void 0 && item.keywords.some((k) => k.toLowerCase().includes(needle));
24420
+ return matchesCategory && matchesSearch;
24421
+ });
24422
+ }, [items, search, activeCategory]);
24423
+ const visible = useMemo(() => filtered.slice(0, MAX_RENDERED), [filtered]);
24424
+ const truncated = filtered.length - visible.length;
24425
+ const select = useCallback(
24426
+ (item) => {
24427
+ onChange(item.id);
24428
+ },
24429
+ [onChange]
24430
+ );
24431
+ const handleKeyDown = useCallback(
24432
+ (e, index) => {
24433
+ const cells = gridRef.current?.querySelectorAll(
24434
+ "[data-gridpicker-cell]"
24435
+ );
24436
+ if (cells === void 0 || cells.length === 0) return;
24437
+ const columns = (() => {
24438
+ const grid = gridRef.current;
24439
+ if (grid === null) return 1;
24440
+ const style = window.getComputedStyle(grid);
24441
+ const cols = style.gridTemplateColumns.split(" ").filter(Boolean).length;
24442
+ return cols > 0 ? cols : 1;
24443
+ })();
24444
+ let next = -1;
24445
+ if (e.key === "ArrowRight") next = index + 1;
24446
+ else if (e.key === "ArrowLeft") next = index - 1;
24447
+ else if (e.key === "ArrowDown") next = index + columns;
24448
+ else if (e.key === "ArrowUp") next = index - columns;
24449
+ else if (e.key === "Enter" || e.key === " ") {
24450
+ e.preventDefault();
24451
+ select(filtered[index]);
24452
+ return;
24453
+ } else {
24454
+ return;
24455
+ }
24456
+ e.preventDefault();
24457
+ if (next >= 0 && next < cells.length) {
24458
+ cells[next].focus();
24459
+ }
24460
+ },
24461
+ [filtered, select]
24462
+ );
24463
+ return /* @__PURE__ */ jsxs(VStack, { gap: "sm", className: cn("w-full", className), children: [
24464
+ /* @__PURE__ */ jsx(
24465
+ Input,
24466
+ {
24467
+ type: "search",
24468
+ icon: "search",
24469
+ value: search,
24470
+ placeholder: searchPlaceholder,
24471
+ clearable: true,
24472
+ onClear: () => setSearch(""),
24473
+ onChange: (e) => setSearch(e.target.value)
24474
+ }
24475
+ ),
24476
+ categoryChips.length > 0 && /* @__PURE__ */ jsxs(HStack, { gap: "xs", wrap: true, children: [
24477
+ /* @__PURE__ */ jsx(
24478
+ Badge,
24479
+ {
24480
+ variant: activeCategory === ALL_CATEGORY ? "primary" : "neutral",
24481
+ size: "sm",
24482
+ role: "button",
24483
+ tabIndex: 0,
24484
+ "aria-pressed": activeCategory === ALL_CATEGORY,
24485
+ className: "cursor-pointer",
24486
+ onClick: () => setActiveCategory(ALL_CATEGORY),
24487
+ onKeyDown: (e) => {
24488
+ if (e.key === "Enter" || e.key === " ") {
24489
+ e.preventDefault();
24490
+ setActiveCategory(ALL_CATEGORY);
24491
+ }
24492
+ },
24493
+ children: "All"
24494
+ }
24495
+ ),
24496
+ categoryChips.map((category) => /* @__PURE__ */ jsx(
24497
+ Badge,
24498
+ {
24499
+ variant: activeCategory === category ? "primary" : "neutral",
24500
+ size: "sm",
24501
+ role: "button",
24502
+ tabIndex: 0,
24503
+ "aria-pressed": activeCategory === category,
24504
+ className: "cursor-pointer",
24505
+ onClick: () => setActiveCategory(category),
24506
+ onKeyDown: (e) => {
24507
+ if (e.key === "Enter" || e.key === " ") {
24508
+ e.preventDefault();
24509
+ setActiveCategory(category);
24510
+ }
24511
+ },
24512
+ children: category
24513
+ },
24514
+ category
24515
+ ))
24516
+ ] }),
24517
+ /* @__PURE__ */ jsx(
24518
+ "div",
24519
+ {
24520
+ ref: gridRef,
24521
+ role: "listbox",
24522
+ className: "grid gap-1 overflow-y-auto max-h-64 p-1",
24523
+ style: {
24524
+ gridTemplateColumns: `repeat(auto-fill, minmax(${cellSize}px, 1fr))`
24525
+ },
24526
+ children: visible.map((item, index) => {
24527
+ const selected = item.id === value;
24528
+ return /* @__PURE__ */ jsx(
24529
+ "button",
24530
+ {
24531
+ type: "button",
24532
+ role: "option",
24533
+ "aria-selected": selected,
24534
+ "aria-label": item.label,
24535
+ title: item.label,
24536
+ "data-gridpicker-cell": true,
24537
+ tabIndex: selected || value === void 0 && index === 0 ? 0 : -1,
24538
+ onClick: () => select(item),
24539
+ onKeyDown: (e) => handleKeyDown(e, index),
24540
+ className: cn(
24541
+ "flex items-center justify-center rounded-sm",
24542
+ "transition-colors hover:bg-muted",
24543
+ "focus:outline-none focus:ring-1 focus:ring-ring",
24544
+ selected && "bg-primary/10 ring-1 ring-primary"
24545
+ ),
24546
+ style: { width: cellSize, height: cellSize },
24547
+ children: renderThumbnail(item)
24548
+ },
24549
+ item.id
24550
+ );
24551
+ })
24552
+ }
24553
+ ),
24554
+ truncated > 0 && /* @__PURE__ */ jsx("div", { className: "px-1 text-xs text-muted-foreground", children: `+${truncated} more \u2014 refine your search` })
24555
+ ] });
24556
+ };
24557
+ GridPicker.displayName = "GridPicker";
24558
+ }
24559
+ });
24177
24560
  function fileIcon(name) {
24178
24561
  const ext = name.split(".").pop()?.toLowerCase() ?? "";
24179
24562
  switch (ext) {
@@ -24946,7 +25329,7 @@ var init_Flex = __esm({
24946
25329
  flexStyle.flexBasis = typeof basis === "number" ? `${basis}px` : basis;
24947
25330
  }
24948
25331
  }
24949
- return React84__default.createElement(Component, {
25332
+ return React85__default.createElement(Component, {
24950
25333
  className: cn(
24951
25334
  inline ? "inline-flex" : "flex",
24952
25335
  directionStyles[direction],
@@ -25065,7 +25448,7 @@ var init_Grid = __esm({
25065
25448
  as: Component = "div"
25066
25449
  }) => {
25067
25450
  const mergedStyle = rows ? { gridTemplateRows: `repeat(${rows}, minmax(0, 1fr))`, ...style } : style;
25068
- return React84__default.createElement(
25451
+ return React85__default.createElement(
25069
25452
  Component,
25070
25453
  {
25071
25454
  className: cn(
@@ -25202,9 +25585,16 @@ var init_Popover = __esm({
25202
25585
  position = "bottom",
25203
25586
  trigger = "click",
25204
25587
  showArrow = true,
25588
+ open,
25589
+ onOpenChange,
25205
25590
  className
25206
25591
  }) => {
25207
- const [isOpen, setIsOpen] = useState(false);
25592
+ const [uncontrolledOpen, setUncontrolledOpen] = useState(false);
25593
+ const isOpen = open !== void 0 ? open : uncontrolledOpen;
25594
+ const setIsOpen = (next) => {
25595
+ if (open === void 0) setUncontrolledOpen(next);
25596
+ onOpenChange?.(next);
25597
+ };
25208
25598
  const [triggerRect, setTriggerRect] = useState(null);
25209
25599
  const [popoverWidth, setPopoverWidth] = useState(0);
25210
25600
  const triggerRef = useRef(null);
@@ -25237,6 +25627,23 @@ var init_Popover = __esm({
25237
25627
  updatePosition();
25238
25628
  }
25239
25629
  }, [isOpen]);
25630
+ useEffect(() => {
25631
+ if (!isOpen) return;
25632
+ let raf = 0;
25633
+ let lastTop = Number.NaN;
25634
+ let lastLeft = Number.NaN;
25635
+ const track = () => {
25636
+ const rect = triggerRef.current?.getBoundingClientRect();
25637
+ if (rect && (rect.top !== lastTop || rect.left !== lastLeft)) {
25638
+ lastTop = rect.top;
25639
+ lastLeft = rect.left;
25640
+ updatePosition();
25641
+ }
25642
+ raf = requestAnimationFrame(track);
25643
+ };
25644
+ raf = requestAnimationFrame(track);
25645
+ return () => cancelAnimationFrame(raf);
25646
+ }, [isOpen]);
25240
25647
  useEffect(() => {
25241
25648
  if (!mounted) setPopoverWidth(0);
25242
25649
  }, [mounted]);
@@ -25273,9 +25680,9 @@ var init_Popover = __esm({
25273
25680
  onMouseLeave: handleClose,
25274
25681
  onPointerDown: tapTriggerProps.onPointerDown
25275
25682
  };
25276
- const childElement = React84__default.isValidElement(children) ? children : /* @__PURE__ */ jsx("span", { children });
25683
+ const childElement = React85__default.isValidElement(children) ? children : /* @__PURE__ */ jsx("span", { children });
25277
25684
  const childPointerDown = childElement.props.onPointerDown;
25278
- const triggerElement = React84__default.cloneElement(
25685
+ const triggerElement = React85__default.cloneElement(
25279
25686
  childElement,
25280
25687
  {
25281
25688
  ref: triggerRef,
@@ -25884,9 +26291,9 @@ var init_Tooltip = __esm({
25884
26291
  if (hideTimeoutRef.current) clearTimeout(hideTimeoutRef.current);
25885
26292
  };
25886
26293
  }, []);
25887
- const triggerElement = React84__default.isValidElement(children) ? children : /* @__PURE__ */ jsx("span", { children });
26294
+ const triggerElement = React85__default.isValidElement(children) ? children : /* @__PURE__ */ jsx("span", { children });
25888
26295
  const childPointerDown = triggerElement.props.onPointerDown;
25889
- const trigger = React84__default.cloneElement(triggerElement, {
26296
+ const trigger = React85__default.cloneElement(triggerElement, {
25890
26297
  ref: triggerRef,
25891
26298
  onMouseEnter: handleMouseEnter,
25892
26299
  onMouseLeave: handleMouseLeave,
@@ -25976,7 +26383,7 @@ var init_WizardProgress = __esm({
25976
26383
  children: /* @__PURE__ */ jsx("div", { className: "flex items-center gap-2", children: normalizedSteps.map((step, index) => {
25977
26384
  const isActive = index === currentStep;
25978
26385
  const isCompleted = index < currentStep;
25979
- return /* @__PURE__ */ jsxs(React84__default.Fragment, { children: [
26386
+ return /* @__PURE__ */ jsxs(React85__default.Fragment, { children: [
25980
26387
  /* @__PURE__ */ jsx(
25981
26388
  "button",
25982
26389
  {
@@ -26585,6 +26992,80 @@ var init_FlipCard = __esm({
26585
26992
  FlipCard.displayName = "FlipCard";
26586
26993
  }
26587
26994
  });
26995
+ var EMOJI_ITEMS, EmojiPicker;
26996
+ var init_EmojiPicker = __esm({
26997
+ "components/core/molecules/EmojiPicker.tsx"() {
26998
+ "use client";
26999
+ init_useEventBus();
27000
+ init_Button();
27001
+ init_GridPicker();
27002
+ init_Popover();
27003
+ EMOJI_ITEMS = (() => {
27004
+ const items = [];
27005
+ for (const name of ordered) {
27006
+ const entry = lib[name];
27007
+ if (entry === void 0 || entry.char === null || entry.char === "") continue;
27008
+ items.push({
27009
+ id: entry.char,
27010
+ label: name.replace(/_/g, " "),
27011
+ category: entry.category.replace(/_/g, " "),
27012
+ keywords: entry.keywords
27013
+ });
27014
+ }
27015
+ return items;
27016
+ })();
27017
+ EmojiPicker = ({
27018
+ pickEvent,
27019
+ position = "top",
27020
+ triggerIcon = "smile",
27021
+ triggerLabel = "Add emoji",
27022
+ className
27023
+ }) => {
27024
+ const eventBus = useEventBus();
27025
+ const [open, setOpen] = useState(false);
27026
+ const handlePick = (glyph) => {
27027
+ if (pickEvent !== void 0) {
27028
+ const payload = { emoji: glyph };
27029
+ eventBus.emit(`UI:${pickEvent}`, payload);
27030
+ }
27031
+ setOpen(false);
27032
+ };
27033
+ return /* @__PURE__ */ jsx(
27034
+ Popover,
27035
+ {
27036
+ position,
27037
+ trigger: "click",
27038
+ showArrow: false,
27039
+ open,
27040
+ onOpenChange: setOpen,
27041
+ content: /* @__PURE__ */ jsx(
27042
+ GridPicker,
27043
+ {
27044
+ items: EMOJI_ITEMS,
27045
+ onChange: handlePick,
27046
+ searchPlaceholder: "Search emoji\u2026",
27047
+ renderThumbnail: (item) => /* @__PURE__ */ jsx("span", { className: "text-xl leading-none", "aria-hidden": "true", children: item.id }),
27048
+ cellSize: 32,
27049
+ className: "w-80"
27050
+ }
27051
+ ),
27052
+ children: /* @__PURE__ */ jsx(
27053
+ Button,
27054
+ {
27055
+ variant: "ghost",
27056
+ icon: triggerIcon,
27057
+ "aria-label": triggerLabel,
27058
+ title: triggerLabel,
27059
+ className,
27060
+ "data-testid": "emoji-picker-trigger"
27061
+ }
27062
+ )
27063
+ }
27064
+ );
27065
+ };
27066
+ EmojiPicker.displayName = "EmojiPicker";
27067
+ }
27068
+ });
26588
27069
  function toISODate(d) {
26589
27070
  return d.toISOString().slice(0, 10);
26590
27071
  }
@@ -27537,12 +28018,12 @@ var init_MapView = __esm({
27537
28018
  shadowSize: [41, 41]
27538
28019
  });
27539
28020
  L.Marker.prototype.options.icon = defaultIcon;
27540
- const { useEffect: useEffect62, useRef: useRef60, useCallback: useCallback94, useState: useState91 } = React84__default;
28021
+ const { useEffect: useEffect62, useRef: useRef61, useCallback: useCallback95, useState: useState93 } = React85__default;
27541
28022
  const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
27542
28023
  const { useEventBus: useEventBus2 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
27543
28024
  function MapUpdater({ centerLat, centerLng, zoom }) {
27544
28025
  const map = useMap();
27545
- const prevRef = useRef60({ centerLat, centerLng, zoom });
28026
+ const prevRef = useRef61({ centerLat, centerLng, zoom });
27546
28027
  useEffect62(() => {
27547
28028
  const prev = prevRef.current;
27548
28029
  if (prev.centerLat !== centerLat || prev.centerLng !== centerLng || prev.zoom !== zoom) {
@@ -27582,8 +28063,8 @@ var init_MapView = __esm({
27582
28063
  showAttribution = true
27583
28064
  }) {
27584
28065
  const eventBus = useEventBus2();
27585
- const [clickedPosition, setClickedPosition] = useState91(null);
27586
- const handleMapClick = useCallback94((lat, lng) => {
28066
+ const [clickedPosition, setClickedPosition] = useState93(null);
28067
+ const handleMapClick = useCallback95((lat, lng) => {
27587
28068
  if (showClickedPin) {
27588
28069
  setClickedPosition({ lat, lng });
27589
28070
  }
@@ -27592,7 +28073,7 @@ var init_MapView = __esm({
27592
28073
  eventBus.emit(`UI:${mapClickEvent}`, { latitude: lat, longitude: lng });
27593
28074
  }
27594
28075
  }, [onMapClick, mapClickEvent, eventBus, showClickedPin]);
27595
- const handleMarkerClick = useCallback94((marker) => {
28076
+ const handleMarkerClick = useCallback95((marker) => {
27596
28077
  onMarkerClick?.(marker);
27597
28078
  if (markerClickEvent) {
27598
28079
  eventBus.emit(`UI:${markerClickEvent}`, { ...marker });
@@ -28427,6 +28908,7 @@ function TableView({
28427
28908
  fields,
28428
28909
  itemActions,
28429
28910
  maxInlineActions,
28911
+ itemClickEvent,
28430
28912
  selectable = false,
28431
28913
  selectEvent,
28432
28914
  selectedIds,
@@ -28454,8 +28936,8 @@ function TableView({
28454
28936
  }) {
28455
28937
  const eventBus = useEventBus();
28456
28938
  const { t } = useTranslate();
28457
- const [visibleCount, setVisibleCount] = React84__default.useState(pageSize > 0 ? pageSize : Infinity);
28458
- const [localSelected, setLocalSelected] = React84__default.useState(/* @__PURE__ */ new Set());
28939
+ const [visibleCount, setVisibleCount] = React85__default.useState(pageSize > 0 ? pageSize : Infinity);
28940
+ const [localSelected, setLocalSelected] = React85__default.useState(/* @__PURE__ */ new Set());
28459
28941
  const colDefs = (Array.isArray(columns) ? columns : void 0) ?? (Array.isArray(fields) ? fields : void 0) ?? [];
28460
28942
  const actionDefs = Array.isArray(itemActions) ? itemActions : [];
28461
28943
  const allDataRaw = Array.isArray(entity) ? entity : entity ? [entity] : [];
@@ -28471,13 +28953,13 @@ function TableView({
28471
28953
  dndItemIdField,
28472
28954
  dndRoot
28473
28955
  });
28474
- const ordered = dnd.orderedItems;
28475
- const data = pageSize > 0 ? ordered.slice(0, visibleCount) : ordered;
28476
- const hasMore = pageSize > 0 && visibleCount < ordered.length;
28956
+ const ordered2 = dnd.orderedItems;
28957
+ const data = pageSize > 0 ? ordered2.slice(0, visibleCount) : ordered2;
28958
+ const hasMore = pageSize > 0 && visibleCount < ordered2.length;
28477
28959
  const hasRenderProp = typeof children === "function";
28478
28960
  const idField = dndItemIdField ?? "id";
28479
28961
  const isCoarsePointer = useMediaQuery("(pointer: coarse)");
28480
- React84__default.useEffect(() => {
28962
+ React85__default.useEffect(() => {
28481
28963
  tableViewLog.debug("render", {
28482
28964
  rowCount: data.length,
28483
28965
  colCount: colDefs.length,
@@ -28526,7 +29008,15 @@ function TableView({
28526
29008
  };
28527
29009
  eventBus.emit(`UI:${action.event}`, payload);
28528
29010
  };
28529
- const colFloors = React84__default.useMemo(
29011
+ const handleRowClick = (row) => () => {
29012
+ if (!itemClickEvent) return;
29013
+ const payload = {
29014
+ id: row.id,
29015
+ row
29016
+ };
29017
+ eventBus.emit(`UI:${itemClickEvent}`, payload);
29018
+ };
29019
+ const colFloors = React85__default.useMemo(
28530
29020
  () => colDefs.map((col) => {
28531
29021
  const longest = data.reduce((widest, row) => {
28532
29022
  const cell = formatCell(asFieldValue(getNestedValue(row, col.field ?? col.key)), col.format);
@@ -28602,10 +29092,12 @@ function TableView({
28602
29092
  role: "row",
28603
29093
  "data-entity-row": true,
28604
29094
  "data-entity-id": id,
29095
+ onClick: itemClickEvent ? handleRowClick(row) : void 0,
28605
29096
  style: !hasRenderProp ? { gridTemplateColumns } : void 0,
28606
29097
  className: cn(
28607
29098
  "group items-center gap-3 transition-colors duration-fast",
28608
29099
  hasRenderProp ? "flex" : "grid",
29100
+ itemClickEvent && "cursor-pointer",
28609
29101
  lk.rowPad,
28610
29102
  lk.divider && "border-b border-[var(--color-border)]",
28611
29103
  lk.striped && index % 2 === 1 && "bg-[var(--color-surface-subtle)]",
@@ -28613,7 +29105,7 @@ function TableView({
28613
29105
  look === "bordered" && "[&>*]:border-r [&>*]:border-[var(--color-border)] [&>*:last-child]:border-r-0"
28614
29106
  ),
28615
29107
  children: [
28616
- selectable && /* @__PURE__ */ jsx(Box, { className: "flex items-center", children: /* @__PURE__ */ jsx(
29108
+ selectable && /* @__PURE__ */ jsx(Box, { className: "flex items-center", onClick: itemClickEvent ? (e) => e.stopPropagation() : void 0, children: /* @__PURE__ */ jsx(
28617
29109
  Checkbox,
28618
29110
  {
28619
29111
  checked: selected.has(id),
@@ -28638,6 +29130,7 @@ function TableView({
28638
29130
  HStack,
28639
29131
  {
28640
29132
  gap: "xs",
29133
+ onClick: itemClickEvent ? (e) => e.stopPropagation() : void 0,
28641
29134
  className: cn(
28642
29135
  // Pinned: the fixed column tracks routinely overflow the caller's
28643
29136
  // scroll container, which used to leave the actions off-screen.
@@ -28685,12 +29178,12 @@ function TableView({
28685
29178
  ]
28686
29179
  }
28687
29180
  );
28688
- return dnd.isZone ? /* @__PURE__ */ jsx(dnd.SortableItem, { id: row[idField] ?? id, children: rowInner }, id) : /* @__PURE__ */ jsx(React84__default.Fragment, { children: rowInner }, id);
29181
+ return dnd.isZone ? /* @__PURE__ */ jsx(dnd.SortableItem, { id: row[idField] ?? id, children: rowInner }, id) : /* @__PURE__ */ jsx(React85__default.Fragment, { children: rowInner }, id);
28689
29182
  };
28690
29183
  const items = Array.from(data);
28691
29184
  const groups = groupBy ? groupData2(items, groupBy) : [{ label: "", items }];
28692
29185
  let runningIndex = 0;
28693
- const body = /* @__PURE__ */ jsx(Box, { role: "rowgroup", children: groups.map((group, gi) => /* @__PURE__ */ jsxs(React84__default.Fragment, { children: [
29186
+ const body = /* @__PURE__ */ jsx(Box, { role: "rowgroup", children: groups.map((group, gi) => /* @__PURE__ */ jsxs(React85__default.Fragment, { children: [
28694
29187
  group.label && /* @__PURE__ */ jsx(Divider, { label: group.label, className: gi > 0 ? "mt-3" : "mt-0" }),
28695
29188
  group.items.map((row) => renderRow(row, runningIndex++))
28696
29189
  ] }, gi)) });
@@ -28707,7 +29200,7 @@ function TableView({
28707
29200
  /* @__PURE__ */ jsx(Icon, { name: "chevron-down", size: "xs", className: "mr-1" }),
28708
29201
  t("common.showMore"),
28709
29202
  " (",
28710
- t("common.remaining", { count: ordered.length - visibleCount }),
29203
+ t("common.remaining", { count: ordered2.length - visibleCount }),
28711
29204
  ")"
28712
29205
  ] }) })
28713
29206
  ]
@@ -30053,7 +30546,7 @@ var init_StepFlow = __esm({
30053
30546
  className
30054
30547
  }) => {
30055
30548
  if (orientation === "vertical") {
30056
- return /* @__PURE__ */ jsx(VStack, { gap: "none", className: cn("w-full", className), children: steps.map((step, index) => /* @__PURE__ */ jsx(React84__default.Fragment, { children: /* @__PURE__ */ jsxs(HStack, { gap: "md", align: "start", className: "w-full", children: [
30549
+ return /* @__PURE__ */ jsx(VStack, { gap: "none", className: cn("w-full", className), children: steps.map((step, index) => /* @__PURE__ */ jsx(React85__default.Fragment, { children: /* @__PURE__ */ jsxs(HStack, { gap: "md", align: "start", className: "w-full", children: [
30057
30550
  /* @__PURE__ */ jsxs(VStack, { gap: "none", align: "center", children: [
30058
30551
  /* @__PURE__ */ jsx(StepCircle, { step, index }),
30059
30552
  showConnectors && index < steps.length - 1 && /* @__PURE__ */ jsx(Box, { className: "w-px h-8 bg-border" })
@@ -30064,7 +30557,7 @@ var init_StepFlow = __esm({
30064
30557
  ] })
30065
30558
  ] }) }, index)) });
30066
30559
  }
30067
- 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(React84__default.Fragment, { children: [
30560
+ 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(React85__default.Fragment, { children: [
30068
30561
  /* @__PURE__ */ jsxs(VStack, { gap: "sm", align: "center", className: "flex-1 w-full md:w-auto", children: [
30069
30562
  /* @__PURE__ */ jsx(StepCircle, { step, index }),
30070
30563
  /* @__PURE__ */ jsx(Typography, { variant: "h4", className: "text-center", children: step.title }),
@@ -31054,7 +31547,7 @@ var init_LikertScale = __esm({
31054
31547
  md: "text-base",
31055
31548
  lg: "text-lg"
31056
31549
  };
31057
- LikertScale = React84__default.forwardRef(
31550
+ LikertScale = React85__default.forwardRef(
31058
31551
  ({
31059
31552
  question,
31060
31553
  options = DEFAULT_LIKERT_OPTIONS,
@@ -31066,7 +31559,7 @@ var init_LikertScale = __esm({
31066
31559
  variant = "radios",
31067
31560
  className
31068
31561
  }, ref) => {
31069
- const groupId = React84__default.useId();
31562
+ const groupId = React85__default.useId();
31070
31563
  const eventBus = useEventBus();
31071
31564
  const handleSelect = useCallback(
31072
31565
  (next) => {
@@ -33355,7 +33848,7 @@ var init_DocBreadcrumb = __esm({
33355
33848
  "aria-label": t("aria.breadcrumb"),
33356
33849
  children: /* @__PURE__ */ jsx(HStack, { gap: "xs", align: "center", wrap: true, children: items.map((item, idx) => {
33357
33850
  const isLast = idx === items.length - 1;
33358
- return /* @__PURE__ */ jsxs(React84__default.Fragment, { children: [
33851
+ return /* @__PURE__ */ jsxs(React85__default.Fragment, { children: [
33359
33852
  idx > 0 && /* @__PURE__ */ jsx(
33360
33853
  Icon,
33361
33854
  {
@@ -34224,7 +34717,7 @@ var init_MiniStateMachine = __esm({
34224
34717
  const x = 2 + i * (NODE_W + GAP + ARROW_W + GAP);
34225
34718
  const tc = transitionCounts[s.name] ?? 0;
34226
34719
  const role = getStateRole(s.name, s.isInitial ?? void 0, s.isTerminal ?? void 0, tc, maxTC);
34227
- return /* @__PURE__ */ jsxs(React84__default.Fragment, { children: [
34720
+ return /* @__PURE__ */ jsxs(React85__default.Fragment, { children: [
34228
34721
  /* @__PURE__ */ jsx(
34229
34722
  AvlState,
34230
34723
  {
@@ -34428,7 +34921,7 @@ var init_PageHeader = __esm({
34428
34921
  info: "bg-info/10 text-info"
34429
34922
  };
34430
34923
  return /* @__PURE__ */ jsxs(Box, { className: cn("mb-6", className), children: [
34431
- 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(React84__default.Fragment, { children: [
34924
+ 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(React85__default.Fragment, { children: [
34432
34925
  idx > 0 && /* @__PURE__ */ jsx(Typography, { variant: "small", color: "muted", children: "/" }),
34433
34926
  crumb.href ? /* @__PURE__ */ jsx(
34434
34927
  "a",
@@ -34786,7 +35279,7 @@ var init_Section = __esm({
34786
35279
  as: Component = "section"
34787
35280
  }) => {
34788
35281
  const hasHeader = title || description || action;
34789
- return React84__default.createElement(
35282
+ return React85__default.createElement(
34790
35283
  Component,
34791
35284
  {
34792
35285
  className: cn(
@@ -35160,7 +35653,7 @@ var init_WizardContainer = __esm({
35160
35653
  const isCompleted = index < currentStep;
35161
35654
  const stepKey = step.id ?? step.tabId ?? `step-${index}`;
35162
35655
  const stepTitle = step.title ?? step.name ?? `Step ${index + 1}`;
35163
- return /* @__PURE__ */ jsxs(React84__default.Fragment, { children: [
35656
+ return /* @__PURE__ */ jsxs(React85__default.Fragment, { children: [
35164
35657
  /* @__PURE__ */ jsx(
35165
35658
  Button,
35166
35659
  {
@@ -36947,7 +37440,7 @@ var init_ImportPreviewTree = __esm({
36947
37440
  const renderUnit = (unit, childrenByParent, depth) => {
36948
37441
  const summary = fieldSummary(unit);
36949
37442
  const children = childrenByParent.get(unit.ref) ?? [];
36950
- return /* @__PURE__ */ jsxs(React84__default.Fragment, { children: [
37443
+ return /* @__PURE__ */ jsxs(React85__default.Fragment, { children: [
36951
37444
  /* @__PURE__ */ jsxs(
36952
37445
  Box,
36953
37446
  {
@@ -37044,7 +37537,7 @@ var init_ImportProgress = __esm({
37044
37537
  PIPELINE.map((key, index) => {
37045
37538
  const isComplete = index < currentIndex;
37046
37539
  const isActive = index === currentIndex;
37047
- return /* @__PURE__ */ jsxs(React84__default.Fragment, { children: [
37540
+ return /* @__PURE__ */ jsxs(React85__default.Fragment, { children: [
37048
37541
  index > 0 ? /* @__PURE__ */ jsx(Box, { className: "h-px w-4 bg-border" }) : null,
37049
37542
  /* @__PURE__ */ jsxs(Box, { className: "flex items-center gap-1", "data-testid": `import-progress-step-${key}`, children: [
37050
37543
  /* @__PURE__ */ jsx(
@@ -38157,7 +38650,7 @@ var init_DrawGroup = __esm({
38157
38650
  }
38158
38651
  });
38159
38652
  function extractTitle(children) {
38160
- if (!React84__default.isValidElement(children)) return void 0;
38653
+ if (!React85__default.isValidElement(children)) return void 0;
38161
38654
  const props = children.props;
38162
38655
  if (typeof props.title === "string") {
38163
38656
  return props.title;
@@ -38507,12 +39000,12 @@ var init_Form = __esm({
38507
39000
  const isSchemaEntity = isOrbitalEntitySchema(entity);
38508
39001
  const resolvedEntity = isSchemaEntity ? entity : void 0;
38509
39002
  const entityName = typeof entity === "string" ? entity : resolvedEntity?.name;
38510
- const normalizedInitialData = React84__default.useMemo(() => {
39003
+ const normalizedInitialData = React85__default.useMemo(() => {
38511
39004
  const entityRowAsInitial = isPlainEntityRow(entity) ? entity : void 0;
38512
39005
  const callerInitial = initialData !== null && typeof initialData === "object" && !Array.isArray(initialData) ? initialData : {};
38513
39006
  return entityRowAsInitial !== void 0 ? { ...entityRowAsInitial, ...callerInitial } : callerInitial;
38514
39007
  }, [entity, initialData]);
38515
- const entityDerivedFields = React84__default.useMemo(() => {
39008
+ const entityDerivedFields = React85__default.useMemo(() => {
38516
39009
  if (fields && fields.length > 0) return void 0;
38517
39010
  if (!resolvedEntity) return void 0;
38518
39011
  return resolvedEntity.fields.map(
@@ -38533,16 +39026,16 @@ var init_Form = __esm({
38533
39026
  const conditionalFields = typeof conditionalFieldsRaw === "boolean" ? {} : conditionalFieldsRaw;
38534
39027
  const hiddenCalculations = typeof hiddenCalculationsRaw === "boolean" ? [] : hiddenCalculationsRaw;
38535
39028
  const violationTriggers = typeof violationTriggersRaw === "boolean" ? [] : violationTriggersRaw;
38536
- const [formData, setFormData] = React84__default.useState(
39029
+ const [formData, setFormData] = React85__default.useState(
38537
39030
  normalizedInitialData
38538
39031
  );
38539
- const [collapsedSections, setCollapsedSections] = React84__default.useState(
39032
+ const [collapsedSections, setCollapsedSections] = React85__default.useState(
38540
39033
  /* @__PURE__ */ new Set()
38541
39034
  );
38542
- const [submitError, setSubmitError] = React84__default.useState(null);
38543
- const formRef = React84__default.useRef(null);
39035
+ const [submitError, setSubmitError] = React85__default.useState(null);
39036
+ const formRef = React85__default.useRef(null);
38544
39037
  const formMode = props.mode;
38545
- const mountedRef = React84__default.useRef(false);
39038
+ const mountedRef = React85__default.useRef(false);
38546
39039
  if (!mountedRef.current) {
38547
39040
  mountedRef.current = true;
38548
39041
  debug("forms", "mount", {
@@ -38555,7 +39048,7 @@ var init_Form = __esm({
38555
39048
  });
38556
39049
  }
38557
39050
  const shouldShowCancel = showCancel ?? (fields && fields.length > 0);
38558
- const evalContext = React84__default.useMemo(
39051
+ const evalContext = React85__default.useMemo(
38559
39052
  () => ({
38560
39053
  formValues: formData,
38561
39054
  globalVariables: externalContext?.globalVariables ?? {},
@@ -38564,7 +39057,7 @@ var init_Form = __esm({
38564
39057
  }),
38565
39058
  [formData, externalContext]
38566
39059
  );
38567
- React84__default.useEffect(() => {
39060
+ React85__default.useEffect(() => {
38568
39061
  debug("forms", "initialData-sync", {
38569
39062
  mode: formMode,
38570
39063
  normalizedInitialData,
@@ -38575,7 +39068,7 @@ var init_Form = __esm({
38575
39068
  setFormData(normalizedInitialData);
38576
39069
  }
38577
39070
  }, [normalizedInitialData]);
38578
- const processCalculations = React84__default.useCallback(
39071
+ const processCalculations = React85__default.useCallback(
38579
39072
  (changedFieldId, newFormData) => {
38580
39073
  if (!hiddenCalculations.length) return;
38581
39074
  const context = {
@@ -38600,7 +39093,7 @@ var init_Form = __esm({
38600
39093
  },
38601
39094
  [hiddenCalculations, externalContext, eventBus]
38602
39095
  );
38603
- const checkViolations = React84__default.useCallback(
39096
+ const checkViolations = React85__default.useCallback(
38604
39097
  (changedFieldId, newFormData) => {
38605
39098
  if (!violationTriggers.length) return;
38606
39099
  const context = {
@@ -38638,7 +39131,7 @@ var init_Form = __esm({
38638
39131
  processCalculations(name, newFormData);
38639
39132
  checkViolations(name, newFormData);
38640
39133
  };
38641
- const isFieldVisible = React84__default.useCallback(
39134
+ const isFieldVisible = React85__default.useCallback(
38642
39135
  (fieldName) => {
38643
39136
  const condition = conditionalFields[fieldName];
38644
39137
  if (!condition) return true;
@@ -38646,7 +39139,7 @@ var init_Form = __esm({
38646
39139
  },
38647
39140
  [conditionalFields, evalContext]
38648
39141
  );
38649
- const isSectionVisible = React84__default.useCallback(
39142
+ const isSectionVisible = React85__default.useCallback(
38650
39143
  (section) => {
38651
39144
  if (!section.condition) return true;
38652
39145
  return Boolean(evaluateFormExpression(section.condition, evalContext));
@@ -38722,7 +39215,7 @@ var init_Form = __esm({
38722
39215
  eventBus.emit(`UI:${onCancel}`);
38723
39216
  }
38724
39217
  };
38725
- const renderField = React84__default.useCallback(
39218
+ const renderField = React85__default.useCallback(
38726
39219
  (field) => {
38727
39220
  const fieldName = field.name || field.field;
38728
39221
  if (!fieldName) return null;
@@ -38743,7 +39236,7 @@ var init_Form = __esm({
38743
39236
  [formData, isFieldVisible, relationsData, relationsLoading, isLoading]
38744
39237
  );
38745
39238
  const effectiveFields = entityDerivedFields ?? fields;
38746
- const normalizedFields = React84__default.useMemo(() => {
39239
+ const normalizedFields = React85__default.useMemo(() => {
38747
39240
  if (!effectiveFields || effectiveFields.length === 0) return [];
38748
39241
  return effectiveFields.map((field) => {
38749
39242
  if (typeof field === "string") {
@@ -38767,7 +39260,7 @@ var init_Form = __esm({
38767
39260
  return field;
38768
39261
  });
38769
39262
  }, [effectiveFields, resolvedEntity]);
38770
- const schemaFields = React84__default.useMemo(() => {
39263
+ const schemaFields = React85__default.useMemo(() => {
38771
39264
  if (normalizedFields.length === 0) return null;
38772
39265
  if (isDebugEnabled()) {
38773
39266
  debugGroup(`Form: ${entityName || "unknown"}`);
@@ -38777,7 +39270,7 @@ var init_Form = __esm({
38777
39270
  }
38778
39271
  return normalizedFields.map(renderField).filter(Boolean);
38779
39272
  }, [normalizedFields, renderField, entityName, conditionalFields]);
38780
- const sectionElements = React84__default.useMemo(() => {
39273
+ const sectionElements = React85__default.useMemo(() => {
38781
39274
  if (!sections || sections.length === 0) return null;
38782
39275
  return sections.map((section) => {
38783
39276
  if (!isSectionVisible(section)) {
@@ -39503,7 +39996,7 @@ var init_List = __esm({
39503
39996
  if (entity && typeof entity === "object" && "id" in entity) return [entity];
39504
39997
  return [];
39505
39998
  }, [entity]);
39506
- const getItemActions = React84__default.useCallback(
39999
+ const getItemActions = React85__default.useCallback(
39507
40000
  (item) => {
39508
40001
  if (!itemActions) return [];
39509
40002
  if (typeof itemActions === "function") {
@@ -39984,7 +40477,7 @@ var init_MediaGallery = __esm({
39984
40477
  [selectable, selectedItems, selectionEvent, eventBus]
39985
40478
  );
39986
40479
  const entityData = Array.isArray(entity) ? entity : [];
39987
- const items = React84__default.useMemo(() => {
40480
+ const items = React85__default.useMemo(() => {
39988
40481
  if (propItems && propItems.length > 0) return propItems;
39989
40482
  if (entityData.length === 0) return [];
39990
40483
  return entityData.map((record, idx) => {
@@ -40149,7 +40642,7 @@ var init_MediaGallery = __esm({
40149
40642
  }
40150
40643
  });
40151
40644
  function extractTitle2(children) {
40152
- if (!React84__default.isValidElement(children)) return void 0;
40645
+ if (!React85__default.isValidElement(children)) return void 0;
40153
40646
  const props = children.props;
40154
40647
  if (typeof props.title === "string") {
40155
40648
  return props.title;
@@ -40404,7 +40897,7 @@ var init_debugRegistry = __esm({
40404
40897
  }
40405
40898
  });
40406
40899
  function useDebugData() {
40407
- const [data, setData] = React84.useState(() => ({
40900
+ const [data, setData] = React85.useState(() => ({
40408
40901
  traits: [],
40409
40902
  ticks: [],
40410
40903
  guards: [],
@@ -40418,7 +40911,7 @@ function useDebugData() {
40418
40911
  },
40419
40912
  lastUpdate: Date.now()
40420
40913
  }));
40421
- React84.useEffect(() => {
40914
+ React85.useEffect(() => {
40422
40915
  const updateData = () => {
40423
40916
  setData({
40424
40917
  traits: getAllTraits(),
@@ -40527,12 +41020,12 @@ function layoutGraph(states, transitions, initialState, width, height) {
40527
41020
  return positions;
40528
41021
  }
40529
41022
  function WalkMinimap() {
40530
- const [walkStep, setWalkStep] = React84.useState(null);
40531
- const [traits2, setTraits] = React84.useState([]);
40532
- const [coveredEdges, setCoveredEdges] = React84.useState([]);
40533
- const [completedTraits, setCompletedTraits] = React84.useState(/* @__PURE__ */ new Set());
40534
- const prevTraitRef = React84.useRef(null);
40535
- React84.useEffect(() => {
41023
+ const [walkStep, setWalkStep] = React85.useState(null);
41024
+ const [traits2, setTraits] = React85.useState([]);
41025
+ const [coveredEdges, setCoveredEdges] = React85.useState([]);
41026
+ const [completedTraits, setCompletedTraits] = React85.useState(/* @__PURE__ */ new Set());
41027
+ const prevTraitRef = React85.useRef(null);
41028
+ React85.useEffect(() => {
40536
41029
  const interval = setInterval(() => {
40537
41030
  const w = window;
40538
41031
  const step = w.__orbitalWalkStep;
@@ -40968,15 +41461,15 @@ var init_EntitiesTab = __esm({
40968
41461
  });
40969
41462
  function EventFlowTab({ events: events2 }) {
40970
41463
  const { t } = useTranslate();
40971
- const [filter, setFilter] = React84.useState("all");
40972
- const containerRef = React84.useRef(null);
40973
- const [autoScroll, setAutoScroll] = React84.useState(true);
40974
- React84.useEffect(() => {
41464
+ const [filter, setFilter] = React85.useState("all");
41465
+ const containerRef = React85.useRef(null);
41466
+ const [autoScroll, setAutoScroll] = React85.useState(true);
41467
+ React85.useEffect(() => {
40975
41468
  if (autoScroll && containerRef.current) {
40976
41469
  containerRef.current.scrollTop = containerRef.current.scrollHeight;
40977
41470
  }
40978
41471
  }, [events2.length, autoScroll]);
40979
- const filteredEvents = React84.useMemo(() => {
41472
+ const filteredEvents = React85.useMemo(() => {
40980
41473
  if (filter === "all") return events2;
40981
41474
  return events2.filter((e) => e.type === filter);
40982
41475
  }, [events2, filter]);
@@ -41092,7 +41585,7 @@ var init_EventFlowTab = __esm({
41092
41585
  });
41093
41586
  function GuardsPanel({ guards }) {
41094
41587
  const { t } = useTranslate();
41095
- const [filter, setFilter] = React84.useState("all");
41588
+ const [filter, setFilter] = React85.useState("all");
41096
41589
  if (guards.length === 0) {
41097
41590
  return /* @__PURE__ */ jsx(
41098
41591
  EmptyState,
@@ -41105,7 +41598,7 @@ function GuardsPanel({ guards }) {
41105
41598
  }
41106
41599
  const passedCount = guards.filter((g) => g.result).length;
41107
41600
  const failedCount = guards.length - passedCount;
41108
- const filteredGuards = React84.useMemo(() => {
41601
+ const filteredGuards = React85.useMemo(() => {
41109
41602
  if (filter === "all") return guards;
41110
41603
  if (filter === "passed") return guards.filter((g) => g.result);
41111
41604
  return guards.filter((g) => !g.result);
@@ -41268,10 +41761,10 @@ function EffectBadge({ effect }) {
41268
41761
  }
41269
41762
  function TransitionTimeline({ transitions }) {
41270
41763
  const { t } = useTranslate();
41271
- const containerRef = React84.useRef(null);
41272
- const [autoScroll, setAutoScroll] = React84.useState(true);
41273
- const [expandedId, setExpandedId] = React84.useState(null);
41274
- React84.useEffect(() => {
41764
+ const containerRef = React85.useRef(null);
41765
+ const [autoScroll, setAutoScroll] = React85.useState(true);
41766
+ const [expandedId, setExpandedId] = React85.useState(null);
41767
+ React85.useEffect(() => {
41275
41768
  if (autoScroll && containerRef.current) {
41276
41769
  containerRef.current.scrollTop = containerRef.current.scrollHeight;
41277
41770
  }
@@ -41551,9 +42044,9 @@ function getAllEvents(traits2) {
41551
42044
  function EventDispatcherTab({ traits: traits2, schema }) {
41552
42045
  const eventBus = useEventBus();
41553
42046
  const { t } = useTranslate();
41554
- const [log13, setLog] = React84.useState([]);
41555
- const prevStatesRef = React84.useRef(/* @__PURE__ */ new Map());
41556
- React84.useEffect(() => {
42047
+ const [log13, setLog] = React85.useState([]);
42048
+ const prevStatesRef = React85.useRef(/* @__PURE__ */ new Map());
42049
+ React85.useEffect(() => {
41557
42050
  for (const trait of traits2) {
41558
42051
  const prev = prevStatesRef.current.get(trait.id);
41559
42052
  if (prev && prev !== trait.currentState) {
@@ -41722,10 +42215,10 @@ function VerifyModePanel({
41722
42215
  localCount
41723
42216
  }) {
41724
42217
  const { t } = useTranslate();
41725
- const [expanded, setExpanded] = React84.useState(true);
41726
- const scrollRef = React84.useRef(null);
41727
- const prevCountRef = React84.useRef(0);
41728
- React84.useEffect(() => {
42218
+ const [expanded, setExpanded] = React85.useState(true);
42219
+ const scrollRef = React85.useRef(null);
42220
+ const prevCountRef = React85.useRef(0);
42221
+ React85.useEffect(() => {
41729
42222
  if (expanded && transitions.length > prevCountRef.current && scrollRef.current) {
41730
42223
  scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
41731
42224
  }
@@ -41782,10 +42275,10 @@ function RuntimeDebugger({
41782
42275
  schema
41783
42276
  }) {
41784
42277
  const { t } = useTranslate();
41785
- const [isCollapsed, setIsCollapsed] = React84.useState(mode === "verify" ? true : defaultCollapsed);
41786
- const [isVisible, setIsVisible] = React84.useState(mode === "inline" || mode === "verify" || isDebugEnabled2());
42278
+ const [isCollapsed, setIsCollapsed] = React85.useState(mode === "verify" ? true : defaultCollapsed);
42279
+ const [isVisible, setIsVisible] = React85.useState(mode === "inline" || mode === "verify" || isDebugEnabled2());
41787
42280
  const debugData = useDebugData();
41788
- React84.useEffect(() => {
42281
+ React85.useEffect(() => {
41789
42282
  if (mode === "inline") return;
41790
42283
  return onDebugToggle((enabled) => {
41791
42284
  setIsVisible(enabled);
@@ -41794,7 +42287,7 @@ function RuntimeDebugger({
41794
42287
  }
41795
42288
  });
41796
42289
  }, [mode]);
41797
- React84.useEffect(() => {
42290
+ React85.useEffect(() => {
41798
42291
  if (mode === "inline") return;
41799
42292
  const handleKeyDown = (e) => {
41800
42293
  if (e.key === "`" && isVisible) {
@@ -42314,7 +42807,7 @@ var init_StatCard = __esm({
42314
42807
  const labelToUse = propLabel ?? propTitle;
42315
42808
  const eventBus = useEventBus();
42316
42809
  const { t } = useTranslate();
42317
- const handleActionClick = React84__default.useCallback(() => {
42810
+ const handleActionClick = React85__default.useCallback(() => {
42318
42811
  if (action?.event) {
42319
42812
  eventBus.emit(`UI:${action.event}`, {});
42320
42813
  }
@@ -42325,7 +42818,7 @@ var init_StatCard = __esm({
42325
42818
  const data = Array.isArray(entity) ? entity : entity ? [entity] : [];
42326
42819
  const isLoading = externalLoading ?? false;
42327
42820
  const error = externalError;
42328
- const computeMetricValue = React84__default.useCallback(
42821
+ const computeMetricValue = React85__default.useCallback(
42329
42822
  (metric, items) => {
42330
42823
  if (metric.value !== void 0) {
42331
42824
  return metric.value;
@@ -42364,7 +42857,7 @@ var init_StatCard = __esm({
42364
42857
  },
42365
42858
  []
42366
42859
  );
42367
- const schemaStats = React84__default.useMemo(() => {
42860
+ const schemaStats = React85__default.useMemo(() => {
42368
42861
  if (!metrics || metrics.length === 0) return null;
42369
42862
  return metrics.map((metric) => ({
42370
42863
  label: metric.label,
@@ -42372,7 +42865,7 @@ var init_StatCard = __esm({
42372
42865
  format: metric.format
42373
42866
  }));
42374
42867
  }, [metrics, data, computeMetricValue]);
42375
- const calculatedTrend = React84__default.useMemo(() => {
42868
+ const calculatedTrend = React85__default.useMemo(() => {
42376
42869
  if (manualTrend !== void 0) return manualTrend;
42377
42870
  if (previousValue === void 0 || currentValue === void 0)
42378
42871
  return void 0;
@@ -43012,8 +43505,8 @@ var init_SubagentTracePanel = __esm({
43012
43505
  ] });
43013
43506
  };
43014
43507
  InlineActivityStream = ({ activities, autoScroll = true, className }) => {
43015
- const endRef = React84__default.useRef(null);
43016
- React84__default.useEffect(() => {
43508
+ const endRef = React85__default.useRef(null);
43509
+ React85__default.useEffect(() => {
43017
43510
  if (!autoScroll) return;
43018
43511
  endRef.current?.scrollIntoView({ behavior: "smooth", block: "end" });
43019
43512
  }, [activities.length, autoScroll]);
@@ -43107,7 +43600,7 @@ var init_SubagentTracePanel = __esm({
43107
43600
  };
43108
43601
  SubagentRichCard = ({ subagent }) => {
43109
43602
  const { t } = useTranslate();
43110
- const activities = React84__default.useMemo(
43603
+ const activities = React85__default.useMemo(
43111
43604
  () => subagentMessagesToActivities(subagent.messages),
43112
43605
  [subagent.messages]
43113
43606
  );
@@ -43184,8 +43677,8 @@ var init_SubagentTracePanel = __esm({
43184
43677
  ] });
43185
43678
  };
43186
43679
  CoordinatorConversation = ({ messages, autoScroll = true, className }) => {
43187
- const endRef = React84__default.useRef(null);
43188
- React84__default.useEffect(() => {
43680
+ const endRef = React85__default.useRef(null);
43681
+ React85__default.useEffect(() => {
43189
43682
  if (!autoScroll) return;
43190
43683
  endRef.current?.scrollIntoView({ behavior: "smooth", block: "end" });
43191
43684
  }, [messages.length, autoScroll]);
@@ -43620,7 +44113,7 @@ var init_Timeline = __esm({
43620
44113
  }) => {
43621
44114
  const { t } = useTranslate();
43622
44115
  const entityData = entity ?? [];
43623
- const items = React84__default.useMemo(() => {
44116
+ const items = React85__default.useMemo(() => {
43624
44117
  if (propItems) return propItems;
43625
44118
  if (entityData.length === 0) return [];
43626
44119
  return entityData.map((record, idx) => {
@@ -43722,7 +44215,7 @@ var init_Timeline = __esm({
43722
44215
  }
43723
44216
  });
43724
44217
  function extractToastProps(children) {
43725
- if (!React84__default.isValidElement(children)) {
44218
+ if (!React85__default.isValidElement(children)) {
43726
44219
  if (typeof children === "string") {
43727
44220
  return { message: children };
43728
44221
  }
@@ -43764,7 +44257,7 @@ var init_ToastSlot = __esm({
43764
44257
  eventBus.emit(`${prefix}CLOSE`);
43765
44258
  };
43766
44259
  if (!isVisible) return null;
43767
- const isCustomContent = React84__default.isValidElement(children) && !message;
44260
+ const isCustomContent = React85__default.isValidElement(children) && !message;
43768
44261
  return /* @__PURE__ */ jsx(Box, { className: "fixed bottom-4 right-4 z-50", children: isCustomContent ? children : /* @__PURE__ */ jsx(
43769
44262
  Toast,
43770
44263
  {
@@ -43869,6 +44362,7 @@ var init_component_registry_generated = __esm({
43869
44362
  init_Drawer();
43870
44363
  init_DrawerSlot();
43871
44364
  init_EdgeDecoration();
44365
+ init_EmojiPicker();
43872
44366
  init_EmptyState();
43873
44367
  init_ErrorBoundary();
43874
44368
  init_ErrorState();
@@ -44136,6 +44630,7 @@ var init_component_registry_generated = __esm({
44136
44630
  "Drawer": Drawer,
44137
44631
  "DrawerSlot": DrawerSlot,
44138
44632
  "EdgeDecoration": EdgeDecoration,
44633
+ "EmojiPicker": EmojiPicker,
44139
44634
  "EmptyState": EmptyState,
44140
44635
  "ErrorBoundary": ErrorBoundary,
44141
44636
  "ErrorState": ErrorState,
@@ -44335,7 +44830,7 @@ function SuspenseConfigProvider({
44335
44830
  config,
44336
44831
  children
44337
44832
  }) {
44338
- return React84__default.createElement(
44833
+ return React85__default.createElement(
44339
44834
  SuspenseConfigContext.Provider,
44340
44835
  { value: config },
44341
44836
  children
@@ -44377,7 +44872,7 @@ function enrichFormFields(fields, entityDef) {
44377
44872
  }
44378
44873
  return { name: field, label: humanizeFieldName(field) };
44379
44874
  }
44380
- if (field && typeof field === "object" && !Array.isArray(field) && !React84__default.isValidElement(field) && !(field instanceof Date)) {
44875
+ if (field && typeof field === "object" && !Array.isArray(field) && !React85__default.isValidElement(field) && !(field instanceof Date)) {
44381
44876
  const obj = field;
44382
44877
  const fieldName = typeof obj.name === "string" ? obj.name : typeof obj.field === "string" ? obj.field : void 0;
44383
44878
  if (!fieldName) return field;
@@ -44563,7 +45058,19 @@ function UISlotComponent({
44563
45058
  const suspenseConfig = useContext(SuspenseConfigContext);
44564
45059
  const contained = useContext(SlotContainedContext);
44565
45060
  const schemaCtx = useEntitySchemaOptional();
44566
- const content = slots[slot];
45061
+ const rawContent = slots[slot];
45062
+ const binding = useEntityBindingSnapshot(rawContent?.sourceTrait);
45063
+ const content = useMemo(() => {
45064
+ if (!rawContent) return rawContent;
45065
+ const resolvedProps = resolveRenderBindingMarkers(
45066
+ rawContent.props,
45067
+ rawContent.sourceTrait,
45068
+ binding.entity,
45069
+ binding.config,
45070
+ binding.state
45071
+ );
45072
+ return resolvedProps === rawContent.props ? rawContent : { ...rawContent, props: resolvedProps };
45073
+ }, [rawContent, binding.entity, binding.config, binding.state]);
44567
45074
  if (children !== void 0) {
44568
45075
  if (pattern === "clear") {
44569
45076
  return null;
@@ -44837,7 +45344,7 @@ function renderPatternChildren(children, onDismiss, parentId = "root", parentPat
44837
45344
  const key = `${parentId}-${index}-trait:${traitName}`;
44838
45345
  return /* @__PURE__ */ jsx(TraitFrame, { traitName }, key);
44839
45346
  }
44840
- return /* @__PURE__ */ jsx(React84__default.Fragment, { children: child }, `${parentId}-${index}`);
45347
+ return /* @__PURE__ */ jsx(React85__default.Fragment, { children: child }, `${parentId}-${index}`);
44841
45348
  }
44842
45349
  if (!child || typeof child !== "object") return null;
44843
45350
  const childId = `${parentId}-${index}`;
@@ -44894,19 +45401,20 @@ function isPatternConfig(value) {
44894
45401
  if (value === null || value === void 0) return false;
44895
45402
  if (typeof value !== "object") return false;
44896
45403
  if (Array.isArray(value)) return false;
44897
- if (React84__default.isValidElement(value)) return false;
45404
+ if (React85__default.isValidElement(value)) return false;
44898
45405
  if (value instanceof Date) return false;
44899
45406
  if (typeof value === "function") return false;
44900
45407
  const record = value;
44901
45408
  return "type" in record && typeof record.type === "string" && getComponentForPattern$1(record.type) !== null;
44902
45409
  }
44903
45410
  function isPlainConfigObject(value) {
44904
- if (React84__default.isValidElement(value)) return false;
45411
+ if (React85__default.isValidElement(value)) return false;
44905
45412
  if (value instanceof Date) return false;
44906
45413
  const proto = Object.getPrototypeOf(value);
44907
45414
  return proto === Object.prototype || proto === null;
44908
45415
  }
44909
45416
  function substituteTraitRefsDeep(value, pathKey) {
45417
+ if (isRenderBindingMarker(value)) return value;
44910
45418
  if (typeof value === "string") {
44911
45419
  const match = TRAIT_BINDING_RE.exec(value);
44912
45420
  if (match) {
@@ -44979,7 +45487,14 @@ function SlotContentRenderer({
44979
45487
  onDismiss,
44980
45488
  patternPath
44981
45489
  }) {
44982
- const entityProp = content.props.entity;
45490
+ const ambientScope = useTraitScope();
45491
+ const bindingTrait = content.sourceTrait ?? ambientScope?.trait;
45492
+ const binding = useEntityBindingSnapshot(bindingTrait);
45493
+ const liveProps = useMemo(
45494
+ () => resolveRenderBindingMarkers(content.props, bindingTrait, binding.entity, binding.config, binding.state),
45495
+ [content.props, bindingTrait, binding.entity, binding.config, binding.state]
45496
+ );
45497
+ const entityProp = liveProps.entity;
44983
45498
  if (content.pattern === "form-section") {
44984
45499
  slotLog.debug("SlotContentRenderer:form-section-render", {
44985
45500
  contentId: content.id,
@@ -45010,7 +45525,7 @@ function SlotContentRenderer({
45010
45525
  const orbitalName = schemaCtx && content.sourceTrait !== void 0 ? schemaCtx.orbitalsByTrait.get(content.sourceTrait) : void 0;
45011
45526
  const PatternComponent = getComponentForPattern(content.pattern);
45012
45527
  if (PatternComponent) {
45013
- const childrenConfig = content.props.children;
45528
+ const childrenConfig = liveProps.children;
45014
45529
  const isSingleChild = typeof childrenConfig === "string" || typeof childrenConfig === "object" && childrenConfig !== null && !Array.isArray(childrenConfig) && "type" in childrenConfig;
45015
45530
  const hasChildren = PATTERNS_WITH_CHILDREN.has(content.pattern) || Array.isArray(childrenConfig) && childrenConfig.length > 0 || isSingleChild;
45016
45531
  const isDrawHost = isDrawHostPattern(content.pattern);
@@ -45021,15 +45536,15 @@ function SlotContentRenderer({
45021
45536
  fromState: content.fromState,
45022
45537
  entity: content.entity
45023
45538
  }) : void 0;
45024
- const incomingChildren = content.props.children;
45539
+ const incomingChildren = liveProps.children;
45025
45540
  const childrenIsRenderFn = typeof incomingChildren === "function";
45026
- const { children: _childrenConfig, ...restPropsNoChildren } = content.props;
45541
+ const { children: _childrenConfig, ...restPropsNoChildren } = liveProps;
45027
45542
  const restProps = childrenIsRenderFn ? { ...restPropsNoChildren, children: incomingChildren } : restPropsNoChildren;
45028
45543
  const nodeSlotOverrides = {};
45029
45544
  for (const slotKey of CONTENT_NODE_SLOTS) {
45030
45545
  const slotVal = restProps[slotKey];
45031
45546
  if (slotVal === void 0 || slotVal === null) continue;
45032
- if (React84__default.isValidElement(slotVal) || typeof slotVal === "string" || typeof slotVal === "number" || typeof slotVal === "boolean") continue;
45547
+ if (React85__default.isValidElement(slotVal) || typeof slotVal === "string" || typeof slotVal === "number" || typeof slotVal === "boolean") continue;
45033
45548
  const typelessChildren = !Array.isArray(slotVal) && typeof slotVal === "object" && !("type" in slotVal) && Array.isArray(slotVal.children) ? slotVal.children : void 0;
45034
45549
  if (typelessChildren !== void 0 || Array.isArray(slotVal) || typeof slotVal === "object" && "type" in slotVal) {
45035
45550
  nodeSlotOverrides[slotKey] = renderPatternChildren(
@@ -45083,7 +45598,7 @@ function SlotContentRenderer({
45083
45598
  const resolvedItems = Array.isArray(entityVal) && entityVal[0] !== "fn" ? entityVal : null;
45084
45599
  if (resolvedItems && resolvedItems.length > 0 && !finalProps.fields && !finalProps.columns) {
45085
45600
  const sample = resolvedItems[0];
45086
- if (sample && typeof sample === "object" && !Array.isArray(sample) && !React84__default.isValidElement(sample) && !(sample instanceof Date)) {
45601
+ if (sample && typeof sample === "object" && !Array.isArray(sample) && !React85__default.isValidElement(sample) && !(sample instanceof Date)) {
45087
45602
  const keys = Object.keys(sample).filter((k) => k !== "id" && k !== "_id");
45088
45603
  finalProps.fields = keys.map((k, i) => ({ name: k, variant: i === 0 ? "h4" : "body" }));
45089
45604
  }
@@ -45132,7 +45647,7 @@ function SlotContentRenderer({
45132
45647
  "data-orb-path": patternPath ?? "root",
45133
45648
  "data-orb-pattern": content.pattern,
45134
45649
  "data-orb-orbital": orbitalName,
45135
- children: content.props.children ?? /* @__PURE__ */ jsxs(Box, { className: "p-4 text-sm text-muted-foreground border border-dashed border-border rounded", children: [
45650
+ children: liveProps.children ?? /* @__PURE__ */ jsxs(Box, { className: "p-4 text-sm text-muted-foreground border border-dashed border-border rounded", children: [
45136
45651
  "Unknown pattern: ",
45137
45652
  content.pattern,
45138
45653
  content.sourceTrait && /* @__PURE__ */ jsxs(Typography, { variant: "small", className: "ml-2", children: [
@@ -45204,6 +45719,7 @@ var scopeWrapLog, TRAIT_BINDING_RE, SuspenseConfigContext, SlotContainedContext,
45204
45719
  var init_UISlotRenderer = __esm({
45205
45720
  "components/core/organisms/UISlotRenderer.tsx"() {
45206
45721
  "use client";
45722
+ init_resolve_render_bindings();
45207
45723
  init_Modal();
45208
45724
  init_Drawer();
45209
45725
  init_Toast();
@@ -45598,9 +46114,10 @@ function VerificationProvider({
45598
46114
  }));
45599
46115
  const effectResults = Array.isArray(payload["effectResults"]) ? payload["effectResults"] : [];
45600
46116
  for (const er of effectResults) {
46117
+ const target = er["entity"] ?? er["service"];
45601
46118
  effects.push({
45602
46119
  type: String(er["type"] ?? er["effect"] ?? "server-effect"),
45603
- args: [er["entity"] ?? er["service"] ?? ""].filter(Boolean),
46120
+ args: typeof target === "string" && target !== "" ? [target] : [],
45604
46121
  status: er["error"] ? "failed" : "executed",
45605
46122
  error: er["error"]
45606
46123
  });
@@ -46389,7 +46906,7 @@ function reEmitServerEvent(eventBus, emitted, origin) {
46389
46906
  sourceTrait: evTrait,
46390
46907
  origin
46391
46908
  });
46392
- eventBus.emit(key, emitted.payload);
46909
+ eventBus.emit(key, emitted.payload, emitted.source);
46393
46910
  }
46394
46911
  function isBusPushEnvelope(value) {
46395
46912
  return value.type === "bus" && typeof value.event === "string";
@@ -46557,7 +47074,12 @@ function ServerBridgeProvider({
46557
47074
  }
46558
47075
  if (result.emittedEvents) {
46559
47076
  for (const emitted of result.emittedEvents) {
46560
- reEmitServerEvent(eventBus, emitted, orbitalName);
47077
+ if (emitted.event === event) continue;
47078
+ reEmitServerEvent(
47079
+ eventBus,
47080
+ { ...emitted, source: { ...emitted.source, dispatched: true } },
47081
+ orbitalName
47082
+ );
46561
47083
  }
46562
47084
  }
46563
47085
  } else if (result.error) {
@@ -46695,10 +47217,29 @@ function useTraitScopeChain2() {
46695
47217
  const chain = useContext(TraitScopeContext);
46696
47218
  return chain ?? EMPTY_CHAIN;
46697
47219
  }
46698
- function useTraitScope() {
47220
+ function useTraitScope2() {
46699
47221
  const chain = useContext(TraitScopeContext);
46700
47222
  return chain && chain.length > 0 ? chain[0] : null;
46701
47223
  }
47224
+ var EntityBindingContext = createContext(null);
47225
+ var EMPTY_ENTITY = {};
47226
+ var NOOP_SUBSCRIBE = () => () => void 0;
47227
+ function useEntityBindingSnapshot2(traitName) {
47228
+ const source = useContext(EntityBindingContext);
47229
+ const entity = useSyncExternalStore(
47230
+ source !== null && traitName !== void 0 ? (onStoreChange) => source.subscribe(traitName, onStoreChange) : NOOP_SUBSCRIBE,
47231
+ () => source !== null && traitName !== void 0 ? source.getEntitySnapshot(traitName) : EMPTY_ENTITY
47232
+ );
47233
+ const config = useMemo(
47234
+ () => source !== null && traitName !== void 0 ? source.getConfig(traitName) : void 0,
47235
+ [source, traitName]
47236
+ );
47237
+ return {
47238
+ entity,
47239
+ config,
47240
+ state: source !== null && traitName !== void 0 ? source.getState(traitName) : ""
47241
+ };
47242
+ }
46702
47243
 
46703
47244
  // providers/OfflineModeProvider.tsx
46704
47245
  init_offline_executor();
@@ -46791,4 +47332,4 @@ function GameAudioProvider2({
46791
47332
  }
46792
47333
  GameAudioProvider2.displayName = "GameAudioProvider";
46793
47334
 
46794
- export { CurrentPagePathContext, CurrentPagePathProvider, EntitySchemaProvider, EventBusContext2 as EventBusContext, EventBusProvider, GameAudioContext2 as GameAudioContext, GameAudioProvider2 as GameAudioProvider, NavigationProvider2 as NavigationProvider, OfflineModeProvider, OrbitalProvider, OrbitalThemeProvider, SelectionContext, SelectionProvider, ServerBridgeProvider, TraitContext, TraitProvider, TraitScopeProvider3 as TraitScopeProvider, UserContext, UserProvider, VerificationProvider, comparePathSpecificity2 as comparePathSpecificity, extractRouteParams2 as extractRouteParams, findPageByName2 as findPageByName, findPageByPath2 as findPageByPath, getAllPages2 as getAllPages, getDefaultPage2 as getDefaultPage, matchPath2 as matchPath, matchPathAmong2 as matchPathAmong, pathMatches2 as pathMatches, useActivePage2 as useActivePage, useCurrentPagePath2 as useCurrentPagePath, useEntitySchema, useEntitySchemaOptional6 as useEntitySchemaOptional, useGameAudioContext2 as useGameAudioContext, useGameAudioContextOptional2 as useGameAudioContextOptional, useHasPermission, useHasRole, useInitPayload2 as useInitPayload, useNavigateTo2 as useNavigateTo, useNavigation2 as useNavigation, useNavigationId2 as useNavigationId, useNavigationState2 as useNavigationState, useOfflineMode, useOptionalOfflineMode, useSelection, useSelectionOptional, useServerBridge, useTrait, useTraitContext, useTraitScope, useTraitScopeChain2 as useTraitScopeChain, useUser, useUserForEvaluation };
47335
+ export { CurrentPagePathContext, CurrentPagePathProvider, EntityBindingContext, EntitySchemaProvider, EventBusContext2 as EventBusContext, EventBusProvider, GameAudioContext2 as GameAudioContext, GameAudioProvider2 as GameAudioProvider, NavigationProvider2 as NavigationProvider, OfflineModeProvider, OrbitalProvider, OrbitalThemeProvider, SelectionContext, SelectionProvider, ServerBridgeProvider, TraitContext, TraitProvider, TraitScopeProvider3 as TraitScopeProvider, UserContext, UserProvider, VerificationProvider, comparePathSpecificity2 as comparePathSpecificity, extractRouteParams2 as extractRouteParams, findPageByName2 as findPageByName, findPageByPath2 as findPageByPath, getAllPages2 as getAllPages, getDefaultPage2 as getDefaultPage, matchPath2 as matchPath, matchPathAmong2 as matchPathAmong, pathMatches2 as pathMatches, useActivePage2 as useActivePage, useCurrentPagePath2 as useCurrentPagePath, useEntityBindingSnapshot2 as useEntityBindingSnapshot, useEntitySchema, useEntitySchemaOptional6 as useEntitySchemaOptional, useGameAudioContext2 as useGameAudioContext, useGameAudioContextOptional2 as useGameAudioContextOptional, useHasPermission, useHasRole, useInitPayload2 as useInitPayload, useNavigateTo2 as useNavigateTo, useNavigation2 as useNavigation, useNavigationId2 as useNavigationId, useNavigationState2 as useNavigationState, useOfflineMode, useOptionalOfflineMode, useSelection, useSelectionOptional, useServerBridge, useTrait, useTraitContext, useTraitScope2 as useTraitScope, useTraitScopeChain2 as useTraitScopeChain, useUser, useUserForEvaluation };