@almadar/ui 6.4.0 → 6.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/dist/{EntityBindingContext-0Evn_LcT.d.cts → EntityBindingContext-Bn3ePJQC.d.cts} +1 -1
  2. package/dist/{EntityBindingContext-0Evn_LcT.d.ts → EntityBindingContext-Bn3ePJQC.d.ts} +1 -1
  3. package/dist/{GameAudioProvider-B48iXwz3.d.ts → GameAudioProvider-Ctceau1s.d.ts} +6 -18
  4. package/dist/{GameAudioProvider-CQAdPreB.d.cts → GameAudioProvider-Dk_Y3LN3.d.cts} +6 -18
  5. package/dist/avl/index.cjs +2755 -1532
  6. package/dist/avl/index.js +1710 -487
  7. package/dist/{avl-schema-parser-dvJKXn-o.d.ts → avl-schema-parser-DncJLEn9.d.ts} +18 -0
  8. package/dist/{avl-schema-parser-Bt4NzAam.d.cts → avl-schema-parser-FQ1474v8.d.cts} +18 -0
  9. package/dist/{cn-DJSBBm5W.d.cts → cn-CCjFspAo.d.cts} +25 -1
  10. package/dist/{cn-BbhJq_nr.d.ts → cn-sgpqpN0U.d.ts} +25 -1
  11. package/dist/components/index.cjs +2518 -1692
  12. package/dist/components/index.d.cts +178 -25
  13. package/dist/components/index.d.ts +178 -25
  14. package/dist/components/index.js +1500 -677
  15. package/dist/context/index.cjs +10 -13
  16. package/dist/context/index.js +10 -13
  17. package/dist/hooks/index.cjs +63 -13
  18. package/dist/hooks/index.d.cts +2 -2
  19. package/dist/hooks/index.d.ts +2 -2
  20. package/dist/hooks/index.js +64 -15
  21. package/dist/lib/drawable/three/index.cjs +126 -13
  22. package/dist/lib/drawable/three/index.d.cts +2 -2
  23. package/dist/lib/drawable/three/index.d.ts +2 -2
  24. package/dist/lib/drawable/three/index.js +127 -14
  25. package/dist/lib/index.cjs +180 -0
  26. package/dist/lib/index.d.cts +1 -1
  27. package/dist/lib/index.d.ts +1 -1
  28. package/dist/lib/index.js +178 -1
  29. package/dist/locales/index.cjs +6 -3
  30. package/dist/locales/index.js +6 -3
  31. package/dist/providers/index.cjs +2346 -1399
  32. package/dist/providers/index.d.cts +2 -2
  33. package/dist/providers/index.d.ts +2 -2
  34. package/dist/providers/index.js +1389 -442
  35. package/dist/runtime/index.cjs +2892 -1356
  36. package/dist/runtime/index.d.cts +78 -6
  37. package/dist/runtime/index.d.ts +78 -6
  38. package/dist/runtime/index.js +1974 -441
  39. package/dist/{useEventBus-CQWyAWpK.d.ts → useKeyboardRouter-D84cNWmA.d.ts} +31 -1
  40. package/dist/{useEventBus-Ckr4wqW3.d.cts → useKeyboardRouter-DQEE_9mq.d.cts} +31 -1
  41. package/locales/ar.json +2 -1
  42. package/locales/en.json +2 -1
  43. package/locales/sl.json +2 -1
  44. package/package.json +4 -4
  45. package/themes/comic.css +437 -0
  46. package/themes/index.css +1 -0
@@ -1,12 +1,12 @@
1
- import * as React86 from 'react';
2
- import React86__default, { createContext, useContext, useMemo, useRef, useEffect, useCallback, useSyncExternalStore, Suspense, useState, useLayoutEffect, lazy, useId } from 'react';
1
+ import * as React87 from 'react';
2
+ import React87__default, { createContext, useContext, useMemo, useRef, useEffect, useCallback, useSyncExternalStore, Suspense, useState, useLayoutEffect, lazy, useId } from 'react';
3
3
  import { EventBusContext, useTraitScopeChain, RenderSlotProvider, useEntitySchemaOptional, useEntityBindingSnapshot, useTraitScope, useEntitySchema, getAllPages, matchPathAmong, CurrentPagePathProvider, NavStackProvider, OrbitalProvider, TraitScopeProvider, useNavStack, ServerBridgeProvider, useCurrentPagePath, useRenderSlot, useGameAudioContextOptional, VerificationProvider, EntitySchemaProvider, OrbitalThemeProvider, useServerBridge, EntityBindingContext } from '@almadar/ui/providers';
4
4
  export { EntitySchemaProvider, ServerBridgeProvider, TraitContext, TraitProvider, useEntitySchema, useEntitySchemaOptional, useServerBridge, useTrait, useTraitContext } from '@almadar/ui/providers';
5
5
  import { createLogger, setNamespaceLevel, isLogLevelEnabled } from '@almadar/logger';
6
6
  import { perfStore, pushPerfEntry, wrapCallbackForEvent, perfStart, perfEnd, perfGauge, prepareSchemaForPreview, perfTimeAsync, collectTraitRefsFromResolvedTrait, buildOrbitalsByTrait, collectEmbeddedTraits } from '@almadar/runtime/ui';
7
7
  export { PERF_NAMESPACE, adjustSchemaForMockData, buildMockData, clearPerf, perfEnd, perfStart, perfTime, prepareSchemaForPreview, wrapCallbackForEvent } from '@almadar/runtime/ui';
8
8
  import { StateMachineManager, collectDeclaredConfigDefaults, resolveCallSitePayloadCaptures, createServerEffectHandlers, EffectExecutor, createContextFromBindings, createTickScheduler, isValidCronExpression, parseDurationString, InMemoryPersistence, normalizeCallSiteConfigToValues, interpolateValue } from '@almadar/runtime';
9
- import { mergeEntityFrame, isCircuitEvent, applyListenPayloadMapping, schemaToIR, getPage, clearSchemaCache as clearSchemaCache$1, walkSExpr, buildResolvedTraitConfigs, isRenderBindingMarker, isFileValue, isInlineTrait, containsEntityBinding, isSExpr, isEventPayloadValue, RENDER_BINDING_MARKER } from '@almadar/core';
9
+ import { UI_SLOTS, mergeEntityFrame, isCircuitEvent, applyListenPayloadMapping, schemaToIR, getPage, clearSchemaCache as clearSchemaCache$1, walkSExpr, buildResolvedTraitConfigs, isRenderBindingMarker, isFileValue, isInlineTrait, containsEntityBinding, isSExpr, isEventPayloadValue, RENDER_BINDING_MARKER } from '@almadar/core';
10
10
  import { clsx } from 'clsx';
11
11
  import { twMerge } from 'tailwind-merge';
12
12
  import * as LucideIcons2 from 'lucide-react';
@@ -927,7 +927,7 @@ function resolveMarkerExpression(expression, entity, config, state) {
927
927
  function isPlainObject(value) {
928
928
  if (value === null || value === void 0 || typeof value !== "object") return false;
929
929
  if (Array.isArray(value)) return false;
930
- if (React86__default.isValidElement(value)) return false;
930
+ if (React87__default.isValidElement(value)) return false;
931
931
  if (value instanceof Date) return false;
932
932
  if (typeof value === "function") return false;
933
933
  return true;
@@ -936,7 +936,7 @@ function isEvaluatorResolvedData(value) {
936
936
  return evaluatorResolvedData.has(value);
937
937
  }
938
938
  function brandResolved(value) {
939
- if (value !== null && typeof value === "object" && !React86__default.isValidElement(value) && !(value instanceof Date)) {
939
+ if (value !== null && typeof value === "object" && !React87__default.isValidElement(value) && !(value instanceof Date)) {
940
940
  resolvedMarkerFree.add(value);
941
941
  }
942
942
  }
@@ -969,7 +969,7 @@ function walkValue(value, scopeTrait, entity, config, state) {
969
969
  }
970
970
  const resolved = resolveMarkerExpression(value.expression, entity, config, state);
971
971
  markerResolutionCache.set(value, { entity, config, state, resolved });
972
- if (resolved !== null && typeof resolved === "object" && !React86__default.isValidElement(resolved) && !(resolved instanceof Date)) {
972
+ if (resolved !== null && typeof resolved === "object" && !React87__default.isValidElement(resolved) && !(resolved instanceof Date)) {
973
973
  resolvedMarkerFree.add(resolved);
974
974
  evaluatorResolvedData.add(resolved);
975
975
  }
@@ -1156,7 +1156,7 @@ var init_Box = __esm({
1156
1156
  fixed: "fixed",
1157
1157
  sticky: "sticky"
1158
1158
  };
1159
- Box = React86__default.forwardRef(
1159
+ Box = React87__default.forwardRef(
1160
1160
  ({
1161
1161
  padding,
1162
1162
  paddingX,
@@ -1221,7 +1221,7 @@ var init_Box = __esm({
1221
1221
  onPointerDown?.(e);
1222
1222
  }, [hoverEvent, tapReveal, triggerProps, onPointerDown]);
1223
1223
  const isClickable = action || onClick;
1224
- return React86__default.createElement(
1224
+ return React87__default.createElement(
1225
1225
  Component,
1226
1226
  {
1227
1227
  ref,
@@ -1438,7 +1438,7 @@ var init_Icon = __esm({
1438
1438
  const effectiveName = typeof icon === "string" && icon !== "" ? icon : name;
1439
1439
  const effectiveStrokeWidth = strokeWidth != null && strokeWidth > 0 ? strokeWidth : void 0;
1440
1440
  const family = useIconFamily();
1441
- const RenderedComponent = React86__default.useMemo(() => {
1441
+ const RenderedComponent = React87__default.useMemo(() => {
1442
1442
  if (directIcon) return null;
1443
1443
  return effectiveName ? resolveIconForFamily(effectiveName) : null;
1444
1444
  }, [directIcon, effectiveName, family]);
@@ -1567,7 +1567,7 @@ var init_atlasSlice = __esm({
1567
1567
  }
1568
1568
  });
1569
1569
  function useAtlasSliceDataUrl(asset) {
1570
- const [, bump] = React86.useReducer((x) => x + 1, 0);
1570
+ const [, bump] = React87.useReducer((x) => x + 1, 0);
1571
1571
  if (!isAtlasAsset(asset)) return void 0;
1572
1572
  const key = `${asset.atlas}#${asset.sprite}`;
1573
1573
  const cached = sliceDataUrlCache.get(key);
@@ -1630,13 +1630,13 @@ function AtlasImage({
1630
1630
  style,
1631
1631
  "aria-hidden": ariaHidden
1632
1632
  }) {
1633
- const [, bump] = React86.useReducer((x) => x + 1, 0);
1634
- const canvasRef = React86.useRef(null);
1633
+ const [, bump] = React87.useReducer((x) => x + 1, 0);
1634
+ const canvasRef = React87.useRef(null);
1635
1635
  const sliced = isAtlasAsset(asset);
1636
1636
  const atlas = sliced ? getAtlas(asset.atlas, bump) : void 0;
1637
1637
  const img = sliced && asset?.url ? getSheetImage(asset.url, bump) : null;
1638
1638
  const rect = sliced && atlas ? subRectFor(atlas, asset.sprite) : null;
1639
- React86.useEffect(() => {
1639
+ React87.useEffect(() => {
1640
1640
  const canvas = canvasRef.current;
1641
1641
  if (!canvas || !img || !rect) return;
1642
1642
  canvas.width = rect.sw;
@@ -1712,7 +1712,7 @@ function resolveIconProp(value, sizeClass) {
1712
1712
  const IconComp = value;
1713
1713
  return /* @__PURE__ */ jsx(IconComp, { className: sizeClass });
1714
1714
  }
1715
- if (React86__default.isValidElement(value)) {
1715
+ if (React87__default.isValidElement(value)) {
1716
1716
  return value;
1717
1717
  }
1718
1718
  if (typeof value === "object" && value !== null && isIconLike(value)) {
@@ -1789,7 +1789,7 @@ var init_Button = __esm({
1789
1789
  md: "h-icon-default w-icon-default",
1790
1790
  lg: "h-icon-default w-icon-default"
1791
1791
  };
1792
- Button = React86__default.forwardRef(
1792
+ Button = React87__default.forwardRef(
1793
1793
  ({
1794
1794
  className,
1795
1795
  variant = "primary",
@@ -1859,7 +1859,7 @@ var Dialog;
1859
1859
  var init_Dialog = __esm({
1860
1860
  "components/core/atoms/Dialog.tsx"() {
1861
1861
  init_cn();
1862
- Dialog = React86__default.forwardRef(
1862
+ Dialog = React87__default.forwardRef(
1863
1863
  ({
1864
1864
  role = "dialog",
1865
1865
  "aria-modal": ariaModal = true,
@@ -2070,7 +2070,7 @@ var init_Typography = __esm({
2070
2070
  if (format !== void 0 && format !== "none" && (typeof body === "string" || typeof body === "number" || body instanceof Date)) {
2071
2071
  body = formatValue(body, format);
2072
2072
  }
2073
- return React86__default.createElement(
2073
+ return React87__default.createElement(
2074
2074
  Component,
2075
2075
  {
2076
2076
  id,
@@ -2632,7 +2632,7 @@ var init_Badge = __esm({
2632
2632
  md: "px-2.5 py-1 text-sm",
2633
2633
  lg: "px-3 py-1.5 text-base"
2634
2634
  };
2635
- Badge = React86__default.forwardRef(
2635
+ Badge = React87__default.forwardRef(
2636
2636
  ({ className, variant = "default", size = "sm", amount, label, icon, iconAsset, children, onRemove, removeLabel, ...props }, ref) => {
2637
2637
  const iconSizes3 = {
2638
2638
  sm: "h-icon-default w-icon-default",
@@ -2982,7 +2982,7 @@ var init_SvgFlow = __esm({
2982
2982
  width = 100,
2983
2983
  height = 100
2984
2984
  }) => {
2985
- const markerId = React86__default.useMemo(() => {
2985
+ const markerId = React87__default.useMemo(() => {
2986
2986
  flowIdCounter += 1;
2987
2987
  return `almadar-flow-arrow-${flowIdCounter}`;
2988
2988
  }, []);
@@ -3575,7 +3575,7 @@ var init_SvgRing = __esm({
3575
3575
  width = 100,
3576
3576
  height = 100
3577
3577
  }) => {
3578
- const gradientId = React86__default.useMemo(() => {
3578
+ const gradientId = React87__default.useMemo(() => {
3579
3579
  ringIdCounter += 1;
3580
3580
  return `almadar-ring-glow-${ringIdCounter}`;
3581
3581
  }, []);
@@ -3756,7 +3756,7 @@ var init_Input = __esm({
3756
3756
  init_cn();
3757
3757
  init_Icon();
3758
3758
  init_useEventBus();
3759
- Input = React86__default.forwardRef(
3759
+ Input = React87__default.forwardRef(
3760
3760
  ({
3761
3761
  className,
3762
3762
  inputType,
@@ -3780,9 +3780,9 @@ var init_Input = __esm({
3780
3780
  const eventBus = useEventBus();
3781
3781
  const type = inputType || htmlType || "text";
3782
3782
  const isDeclarative = typeof onChange === "string";
3783
- const [localValue, setLocalValue] = React86__default.useState(value);
3784
- const pendingEchoRef = React86__default.useRef(/* @__PURE__ */ new Set());
3785
- React86__default.useEffect(() => {
3783
+ const [localValue, setLocalValue] = React87__default.useState(value);
3784
+ const pendingEchoRef = React87__default.useRef(/* @__PURE__ */ new Set());
3785
+ React87__default.useEffect(() => {
3786
3786
  if (!isDeclarative) return;
3787
3787
  const incoming = value == null ? "" : String(value);
3788
3788
  if (pendingEchoRef.current.has(incoming)) {
@@ -3949,7 +3949,7 @@ var Label;
3949
3949
  var init_Label = __esm({
3950
3950
  "components/core/atoms/Label.tsx"() {
3951
3951
  init_cn();
3952
- Label = React86__default.forwardRef(
3952
+ Label = React87__default.forwardRef(
3953
3953
  ({ className, required, children, ...props }, ref) => {
3954
3954
  return /* @__PURE__ */ jsxs(
3955
3955
  "label",
@@ -3976,7 +3976,7 @@ var init_Textarea = __esm({
3976
3976
  "components/core/atoms/Textarea.tsx"() {
3977
3977
  init_cn();
3978
3978
  init_useEventBus();
3979
- Textarea = React86__default.forwardRef(
3979
+ Textarea = React87__default.forwardRef(
3980
3980
  ({ className, error, onChange, ...props }, ref) => {
3981
3981
  const eventBus = useEventBus();
3982
3982
  const handleChange = (e) => {
@@ -4226,7 +4226,7 @@ var init_Select = __esm({
4226
4226
  init_cn();
4227
4227
  init_Icon();
4228
4228
  init_useEventBus();
4229
- Select = React86__default.forwardRef(
4229
+ Select = React87__default.forwardRef(
4230
4230
  (props, _ref) => {
4231
4231
  const { multiple, searchable, clearable } = props;
4232
4232
  if (multiple || searchable || clearable) {
@@ -4243,7 +4243,7 @@ var init_Checkbox = __esm({
4243
4243
  "components/core/atoms/Checkbox.tsx"() {
4244
4244
  init_cn();
4245
4245
  init_useEventBus();
4246
- Checkbox = React86__default.forwardRef(
4246
+ Checkbox = React87__default.forwardRef(
4247
4247
  ({ className, label, id, onChange, ...props }, ref) => {
4248
4248
  const inputId = id || `checkbox-${Math.random().toString(36).substr(2, 9)}`;
4249
4249
  const eventBus = useEventBus();
@@ -4297,7 +4297,7 @@ var init_Spinner = __esm({
4297
4297
  md: "h-6 w-6",
4298
4298
  lg: "h-8 w-8"
4299
4299
  };
4300
- Spinner = React86__default.forwardRef(
4300
+ Spinner = React87__default.forwardRef(
4301
4301
  ({ className, size = "md", overlay, ...props }, ref) => {
4302
4302
  if (overlay) {
4303
4303
  return /* @__PURE__ */ jsx(
@@ -4387,7 +4387,7 @@ var init_Card = __esm({
4387
4387
  chip: "shadow-none rounded-pill border-[length:var(--border-width)] border-border",
4388
4388
  "tile-image-first": "p-0 overflow-hidden"
4389
4389
  };
4390
- Card = React86__default.forwardRef(
4390
+ Card = React87__default.forwardRef(
4391
4391
  ({
4392
4392
  className,
4393
4393
  variant = "bordered",
@@ -4436,9 +4436,9 @@ var init_Card = __esm({
4436
4436
  }
4437
4437
  );
4438
4438
  Card.displayName = "Card";
4439
- CardHeader = React86__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("mb-4", className), ...props }));
4439
+ CardHeader = React87__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("mb-4", className), ...props }));
4440
4440
  CardHeader.displayName = "CardHeader";
4441
- CardTitle = React86__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
4441
+ CardTitle = React87__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
4442
4442
  "h3",
4443
4443
  {
4444
4444
  ref,
@@ -4451,11 +4451,11 @@ var init_Card = __esm({
4451
4451
  }
4452
4452
  ));
4453
4453
  CardTitle.displayName = "CardTitle";
4454
- CardContent = React86__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("", className), ...props }));
4454
+ CardContent = React87__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("", className), ...props }));
4455
4455
  CardContent.displayName = "CardContent";
4456
4456
  CardBody = CardContent;
4457
4457
  CardBody.displayName = "CardBody";
4458
- CardFooter = React86__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
4458
+ CardFooter = React87__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
4459
4459
  "div",
4460
4460
  {
4461
4461
  ref,
@@ -4542,7 +4542,7 @@ var init_FilterPill = __esm({
4542
4542
  md: "w-3.5 h-3.5",
4543
4543
  lg: "w-4 h-4"
4544
4544
  };
4545
- FilterPill = React86__default.forwardRef(
4545
+ FilterPill = React87__default.forwardRef(
4546
4546
  ({
4547
4547
  className,
4548
4548
  variant = "default",
@@ -4671,8 +4671,8 @@ var init_Avatar = __esm({
4671
4671
  actionPayload
4672
4672
  }) => {
4673
4673
  const eventBus = useEventBus();
4674
- const [imgFailed, setImgFailed] = React86__default.useState(false);
4675
- React86__default.useEffect(() => {
4674
+ const [imgFailed, setImgFailed] = React87__default.useState(false);
4675
+ React87__default.useEffect(() => {
4676
4676
  setImgFailed(false);
4677
4677
  }, [src]);
4678
4678
  const initials = providedInitials ?? (name ? generateInitials(name) : void 0);
@@ -4785,7 +4785,7 @@ var init_Center = __esm({
4785
4785
  as: Component = "div"
4786
4786
  }) => {
4787
4787
  const mergedStyle = minHeight ? { minHeight, ...style } : style;
4788
- return React86__default.createElement(Component, {
4788
+ return React87__default.createElement(Component, {
4789
4789
  className: cn(
4790
4790
  inline ? "inline-flex" : "flex",
4791
4791
  horizontal && "justify-center",
@@ -5053,7 +5053,7 @@ var init_Radio = __esm({
5053
5053
  md: "w-2.5 h-2.5",
5054
5054
  lg: "w-3 h-3"
5055
5055
  };
5056
- Radio = React86__default.forwardRef(
5056
+ Radio = React87__default.forwardRef(
5057
5057
  ({
5058
5058
  label,
5059
5059
  helperText,
@@ -5070,12 +5070,12 @@ var init_Radio = __esm({
5070
5070
  onChange,
5071
5071
  ...props
5072
5072
  }, ref) => {
5073
- const reactId = React86__default.useId();
5073
+ const reactId = React87__default.useId();
5074
5074
  const baseId = id || `radio-${reactId}`;
5075
5075
  const hasError = !!error;
5076
5076
  const eventBus = useEventBus();
5077
- const [selected, setSelected] = React86__default.useState(value);
5078
- React86__default.useEffect(() => {
5077
+ const [selected, setSelected] = React87__default.useState(value);
5078
+ React87__default.useEffect(() => {
5079
5079
  if (value !== void 0) setSelected(value);
5080
5080
  }, [value]);
5081
5081
  const pick = (next, e) => {
@@ -5257,7 +5257,7 @@ var init_Switch = __esm({
5257
5257
  "components/core/atoms/Switch.tsx"() {
5258
5258
  "use client";
5259
5259
  init_cn();
5260
- Switch = React86.forwardRef(
5260
+ Switch = React87.forwardRef(
5261
5261
  ({
5262
5262
  checked,
5263
5263
  defaultChecked = false,
@@ -5268,10 +5268,10 @@ var init_Switch = __esm({
5268
5268
  name,
5269
5269
  className
5270
5270
  }, ref) => {
5271
- const [isChecked, setIsChecked] = React86.useState(
5271
+ const [isChecked, setIsChecked] = React87.useState(
5272
5272
  checked !== void 0 ? checked : defaultChecked
5273
5273
  );
5274
- React86.useEffect(() => {
5274
+ React87.useEffect(() => {
5275
5275
  if (checked !== void 0) {
5276
5276
  setIsChecked(checked);
5277
5277
  }
@@ -5434,7 +5434,7 @@ var init_Stack = __esm({
5434
5434
  };
5435
5435
  const isHorizontal = direction === "horizontal";
5436
5436
  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";
5437
- return React86__default.createElement(
5437
+ return React87__default.createElement(
5438
5438
  Component,
5439
5439
  {
5440
5440
  className: cn(
@@ -5634,7 +5634,7 @@ var Aside;
5634
5634
  var init_Aside = __esm({
5635
5635
  "components/core/atoms/Aside.tsx"() {
5636
5636
  init_cn();
5637
- Aside = React86__default.forwardRef(
5637
+ Aside = React87__default.forwardRef(
5638
5638
  ({ className, children, ...rest }, ref) => /* @__PURE__ */ jsx("aside", { ref, className: cn(className), ...rest, children })
5639
5639
  );
5640
5640
  Aside.displayName = "Aside";
@@ -5713,9 +5713,9 @@ var init_LawReferenceTooltip = __esm({
5713
5713
  className
5714
5714
  }) => {
5715
5715
  const { t } = useTranslate();
5716
- const [isVisible, setIsVisible] = React86__default.useState(false);
5717
- const timeoutRef = React86__default.useRef(null);
5718
- const triggerRef = React86__default.useRef(null);
5716
+ const [isVisible, setIsVisible] = React87__default.useState(false);
5717
+ const timeoutRef = React87__default.useRef(null);
5718
+ const triggerRef = React87__default.useRef(null);
5719
5719
  const handleMouseEnter = () => {
5720
5720
  if (timeoutRef.current) clearTimeout(timeoutRef.current);
5721
5721
  timeoutRef.current = setTimeout(() => setIsVisible(true), 200);
@@ -5726,7 +5726,7 @@ var init_LawReferenceTooltip = __esm({
5726
5726
  };
5727
5727
  const { revealed, triggerProps } = useTapReveal({ refs: [triggerRef] });
5728
5728
  const open = isVisible || revealed;
5729
- React86__default.useEffect(() => {
5729
+ React87__default.useEffect(() => {
5730
5730
  return () => {
5731
5731
  if (timeoutRef.current) clearTimeout(timeoutRef.current);
5732
5732
  };
@@ -5936,7 +5936,7 @@ var init_StatusDot = __esm({
5936
5936
  md: "w-2.5 h-2.5",
5937
5937
  lg: "w-3 h-3"
5938
5938
  };
5939
- StatusDot = React86__default.forwardRef(
5939
+ StatusDot = React87__default.forwardRef(
5940
5940
  ({ className, status = "offline", pulse = false, size = "md", label, ...props }, ref) => {
5941
5941
  return /* @__PURE__ */ jsx(
5942
5942
  "span",
@@ -5990,7 +5990,7 @@ var init_TrendIndicator = __esm({
5990
5990
  down: "trending-down",
5991
5991
  flat: "arrow-right"
5992
5992
  };
5993
- TrendIndicator = React86__default.forwardRef(
5993
+ TrendIndicator = React87__default.forwardRef(
5994
5994
  ({
5995
5995
  className,
5996
5996
  value,
@@ -6059,7 +6059,7 @@ var init_RangeSlider = __esm({
6059
6059
  md: "w-4 h-4",
6060
6060
  lg: "w-5 h-5"
6061
6061
  };
6062
- RangeSlider = React86__default.forwardRef(
6062
+ RangeSlider = React87__default.forwardRef(
6063
6063
  ({
6064
6064
  className,
6065
6065
  min = 0,
@@ -6681,7 +6681,7 @@ var init_ContentSection = __esm({
6681
6681
  md: "py-16",
6682
6682
  lg: "py-24"
6683
6683
  };
6684
- ContentSection = React86__default.forwardRef(
6684
+ ContentSection = React87__default.forwardRef(
6685
6685
  ({ children, background = "default", padding = "lg", id, className }, ref) => {
6686
6686
  return /* @__PURE__ */ jsx(
6687
6687
  Box,
@@ -7215,7 +7215,7 @@ var init_AnimatedReveal = __esm({
7215
7215
  "scale-up": { opacity: 1, transform: "scale(1) translateY(0)" },
7216
7216
  "none": {}
7217
7217
  };
7218
- AnimatedReveal = React86__default.forwardRef(
7218
+ AnimatedReveal = React87__default.forwardRef(
7219
7219
  ({
7220
7220
  trigger = "scroll",
7221
7221
  animation = "fade-up",
@@ -7375,7 +7375,7 @@ var init_AnimatedGraphic = __esm({
7375
7375
  "components/marketing/atoms/AnimatedGraphic.tsx"() {
7376
7376
  "use client";
7377
7377
  init_cn();
7378
- AnimatedGraphic = React86__default.forwardRef(
7378
+ AnimatedGraphic = React87__default.forwardRef(
7379
7379
  ({
7380
7380
  src,
7381
7381
  svgContent,
@@ -7398,7 +7398,7 @@ var init_AnimatedGraphic = __esm({
7398
7398
  const fetchedSvg = useFetchedSvg(svgContent ? void 0 : src);
7399
7399
  const resolvedSvg = svgContent ?? fetchedSvg;
7400
7400
  const prevAnimateRef = useRef(animate);
7401
- const setRef = React86__default.useCallback(
7401
+ const setRef = React87__default.useCallback(
7402
7402
  (node) => {
7403
7403
  containerRef.current = node;
7404
7404
  if (typeof ref === "function") ref(node);
@@ -8150,9 +8150,9 @@ function ControlButton({
8150
8150
  className
8151
8151
  }) {
8152
8152
  const eventBus = useEventBus();
8153
- const [isPressed, setIsPressed] = React86.useState(false);
8153
+ const [isPressed, setIsPressed] = React87.useState(false);
8154
8154
  const actualPressed = pressed ?? isPressed;
8155
- const handlePointerDown = React86.useCallback(
8155
+ const handlePointerDown = React87.useCallback(
8156
8156
  (e) => {
8157
8157
  e.preventDefault();
8158
8158
  if (disabled) return;
@@ -8162,7 +8162,7 @@ function ControlButton({
8162
8162
  },
8163
8163
  [disabled, pressEvent, eventBus, onPress]
8164
8164
  );
8165
- const handlePointerUp = React86.useCallback(
8165
+ const handlePointerUp = React87.useCallback(
8166
8166
  (e) => {
8167
8167
  e.preventDefault();
8168
8168
  if (disabled) return;
@@ -8172,7 +8172,7 @@ function ControlButton({
8172
8172
  },
8173
8173
  [disabled, releaseEvent, eventBus, onRelease]
8174
8174
  );
8175
- const handlePointerLeave = React86.useCallback(
8175
+ const handlePointerLeave = React87.useCallback(
8176
8176
  (e) => {
8177
8177
  if (isPressed) {
8178
8178
  setIsPressed(false);
@@ -8431,18 +8431,18 @@ function ControlGrid({
8431
8431
  className
8432
8432
  }) {
8433
8433
  const eventBus = useEventBus();
8434
- const [active, setActive] = React86.useState(/* @__PURE__ */ new Set());
8435
- const [coarse, setCoarse] = React86.useState(
8434
+ const [active, setActive] = React87.useState(/* @__PURE__ */ new Set());
8435
+ const [coarse, setCoarse] = React87.useState(
8436
8436
  () => typeof window !== "undefined" && window.matchMedia("(pointer: coarse)").matches
8437
8437
  );
8438
- React86.useEffect(() => {
8438
+ React87.useEffect(() => {
8439
8439
  if (visibility !== "auto" || typeof window === "undefined") return;
8440
8440
  const mq = window.matchMedia("(pointer: coarse)");
8441
8441
  const onChange = (e) => setCoarse(e.matches);
8442
8442
  mq.addEventListener("change", onChange);
8443
8443
  return () => mq.removeEventListener("change", onChange);
8444
8444
  }, [visibility]);
8445
- const handlePress = React86.useCallback(
8445
+ const handlePress = React87.useCallback(
8446
8446
  (id) => {
8447
8447
  setActive((prev) => new Set(prev).add(id));
8448
8448
  if (actionEvent) eventBus.emit(`UI:${actionEvent}`, { id, pressed: true });
@@ -8456,7 +8456,7 @@ function ControlGrid({
8456
8456
  },
8457
8457
  [kind, actionEvent, directionEvent, directionEvents, eventBus, onAction, onDirection]
8458
8458
  );
8459
- const handleRelease = React86.useCallback(
8459
+ const handleRelease = React87.useCallback(
8460
8460
  (id) => {
8461
8461
  setActive((prev) => {
8462
8462
  const next = new Set(prev);
@@ -8819,7 +8819,7 @@ function GameMenu({
8819
8819
  }) {
8820
8820
  const resolvedOptions = (options?.length ? options : void 0) ?? (menuItems?.length ? menuItems : void 0) ?? DEFAULT_MENU_OPTIONS;
8821
8821
  const eventBus = useEventBus();
8822
- const handleOptionClick = React86.useCallback(
8822
+ const handleOptionClick = React87.useCallback(
8823
8823
  (option) => {
8824
8824
  if (option.event) {
8825
8825
  eventBus.emit(`UI:${option.event}`, { option });
@@ -9055,7 +9055,7 @@ function StateGraph({
9055
9055
  }) {
9056
9056
  const eventBus = useEventBus();
9057
9057
  const nodes = states ?? [];
9058
- const positions = React86.useMemo(() => layoutStates(nodes, width, height), [nodes, width, height]);
9058
+ const positions = React87.useMemo(() => layoutStates(nodes, width, height), [nodes, width, height]);
9059
9059
  return /* @__PURE__ */ jsxs(
9060
9060
  Box,
9061
9061
  {
@@ -9126,8 +9126,8 @@ function MiniMap({
9126
9126
  tileAssets,
9127
9127
  unitAssets
9128
9128
  }) {
9129
- const canvasRef = React86.useRef(null);
9130
- const imgCacheRef = React86.useRef(/* @__PURE__ */ new Map());
9129
+ const canvasRef = React87.useRef(null);
9130
+ const imgCacheRef = React87.useRef(/* @__PURE__ */ new Map());
9131
9131
  function loadImg(url) {
9132
9132
  const cached = imgCacheRef.current.get(url);
9133
9133
  if (cached) return cached.complete ? cached : null;
@@ -9143,7 +9143,7 @@ function MiniMap({
9143
9143
  imgCacheRef.current.set(url, img);
9144
9144
  return null;
9145
9145
  }
9146
- React86.useEffect(() => {
9146
+ React87.useEffect(() => {
9147
9147
  const canvas = canvasRef.current;
9148
9148
  if (!canvas) return;
9149
9149
  const ctx = canvas.getContext("2d");
@@ -10427,7 +10427,7 @@ function collectDrawnItems(nodes) {
10427
10427
  for (const n of nodes) {
10428
10428
  switch (n.type) {
10429
10429
  case "draw-sprite":
10430
- if (isValidScenePos(n.position)) out.push({ pos: n.position, id: n.id, anchor: n.anchor, width: n.width, height: n.height });
10430
+ if (isValidScenePos(n.position)) out.push({ pos: n.position, id: n.id, anchor: n.anchor, width: n.width, height: n.height, rotation: n.rotation });
10431
10431
  break;
10432
10432
  case "draw-shape":
10433
10433
  case "draw-text":
@@ -10437,7 +10437,7 @@ function collectDrawnItems(nodes) {
10437
10437
  break;
10438
10438
  case "draw-sprite-layer":
10439
10439
  for (const it of n.items) {
10440
- if (isValidScenePos(it.position)) out.push({ pos: it.position, id: it.id, anchor: it.anchor, width: it.width, height: it.height });
10440
+ if (isValidScenePos(it.position)) out.push({ pos: it.position, id: it.id, anchor: it.anchor, width: it.width, height: it.height, rotation: it.rotation });
10441
10441
  }
10442
10442
  break;
10443
10443
  case "draw-shape-layer":
@@ -10457,15 +10457,39 @@ function buildHitIndex(items) {
10457
10457
  }
10458
10458
  return m;
10459
10459
  }
10460
+ function withPreviewPosition(nodes, id, pos) {
10461
+ return nodes.map((n) => {
10462
+ if (n.type === "draw-sprite-layer" || n.type === "draw-shape-layer" || n.type === "draw-text-layer") {
10463
+ if (!n.items.some((it) => it.id === id)) return n;
10464
+ return { ...n, items: n.items.map((it) => it.id === id ? { ...it, position: pos } : it) };
10465
+ }
10466
+ if (n.type === "draw-group") {
10467
+ if (!Array.isArray(n.items)) return n;
10468
+ return { ...n, items: withPreviewPosition(n.items, id, pos) };
10469
+ }
10470
+ if (n.id === id && "position" in n) {
10471
+ return { ...n, position: pos };
10472
+ }
10473
+ return n;
10474
+ });
10475
+ }
10460
10476
  function hitTestSprites(items, projector, point) {
10461
10477
  for (let i = items.length - 1; i >= 0; i--) {
10462
10478
  const it = items[i];
10463
10479
  if (it.id === void 0) continue;
10464
10480
  const r = spriteRect(projector, { position: it.pos, anchor: it.anchor, width: it.width, height: it.height });
10465
- if (point.x >= r.x && point.x <= r.x + r.w && point.y >= r.y && point.y <= r.y + r.h) return it.id;
10481
+ const test = it.rotation ? rotatePoint(point, { x: r.x + r.w / 2, y: r.y + r.h / 2 }, -it.rotation) : point;
10482
+ if (test.x >= r.x && test.x <= r.x + r.w && test.y >= r.y && test.y <= r.y + r.h) return it.id;
10466
10483
  }
10467
10484
  return void 0;
10468
10485
  }
10486
+ function rotatePoint(p, center, radians) {
10487
+ const cos = Math.cos(radians);
10488
+ const sin = Math.sin(radians);
10489
+ const dx = p.x - center.x;
10490
+ const dy = p.y - center.y;
10491
+ return { x: center.x + dx * cos - dy * sin, y: center.y + dx * sin + dy * cos };
10492
+ }
10469
10493
  var init_hitTest = __esm({
10470
10494
  "lib/drawable/hitTest.ts"() {
10471
10495
  init_contract();
@@ -10474,6 +10498,41 @@ var init_hitTest = __esm({
10474
10498
  function normalizeBackdrop(bg) {
10475
10499
  return typeof bg === "string" ? { url: bg, role: "decoration", category: "background" } : bg;
10476
10500
  }
10501
+ function selectionOverlayNodes(projector, item) {
10502
+ const r = spriteRect(projector, { position: item.pos, anchor: item.anchor, width: item.width, height: item.height });
10503
+ const tw = projector.tileWidth;
10504
+ const cellTopLeft = projector.anchorPoint(item.pos, "top-left");
10505
+ const offsetX = (r.x - cellTopLeft.x) / tw;
10506
+ const offsetY = (r.y - cellTopLeft.y) / tw;
10507
+ const width = r.w / tw;
10508
+ const height = r.h / tw;
10509
+ const handle = EDIT_HANDLE_SIZE_PX / tw;
10510
+ const ring = {
10511
+ type: "draw-shape",
10512
+ shape: "rect",
10513
+ position: item.pos,
10514
+ anchor: "top-left",
10515
+ offsetX,
10516
+ offsetY,
10517
+ width,
10518
+ height,
10519
+ stroke: EDIT_SELECTION_COLOR,
10520
+ strokeWidth: 2,
10521
+ fill: "none"
10522
+ };
10523
+ const handles = EDIT_SELECTION_CORNERS.map(([cx, cy]) => ({
10524
+ type: "draw-shape",
10525
+ shape: "rect",
10526
+ position: item.pos,
10527
+ anchor: "top-left",
10528
+ offsetX: offsetX + cx * width - handle / 2,
10529
+ offsetY: offsetY + cy * height - handle / 2,
10530
+ width: handle,
10531
+ height: handle,
10532
+ fill: EDIT_SELECTION_COLOR
10533
+ }));
10534
+ return [ring, ...handles];
10535
+ }
10477
10536
  function Canvas2D({
10478
10537
  className,
10479
10538
  isLoading = false,
@@ -10487,6 +10546,12 @@ function Canvas2D({
10487
10546
  tileLeaveEvent,
10488
10547
  keyMap,
10489
10548
  keyUpMap,
10549
+ editable = false,
10550
+ selectedId = null,
10551
+ onSelect,
10552
+ onMove,
10553
+ selectEvent,
10554
+ moveEvent,
10490
10555
  camera = "pan-zoom",
10491
10556
  scale = 0.4,
10492
10557
  tileWidth,
@@ -10503,7 +10568,7 @@ function Canvas2D({
10503
10568
  const registerChildDrawable = useCallback((node) => {
10504
10569
  childDrawablesRef.current.push(node);
10505
10570
  }, []);
10506
- const hasJsxChildren = React86.Children.count(children) > 0;
10571
+ const hasJsxChildren = React87.Children.count(children) > 0;
10507
10572
  function isDrawableLayer(node) {
10508
10573
  return node.type === "draw-sprite-layer" || node.type === "draw-shape-layer" || node.type === "draw-text-layer";
10509
10574
  }
@@ -10744,10 +10809,22 @@ function Canvas2D({
10744
10809
  painter.scale(cam.zoom, cam.zoom);
10745
10810
  painter.translate(-viewportSize.width / 2 - cam.x, -viewportSize.height / 2 - cam.y);
10746
10811
  const dctx = { projector, time: timeMs, invalidate: bumpAtlas };
10747
- for (const node of drawables) paintDrawable(painter, node, dctx);
10812
+ let paintNodes = drawables;
10813
+ if (editable) {
10814
+ const drag = editDragRef.current;
10815
+ if (drag && drag.moved) {
10816
+ paintNodes = withPreviewPosition(paintNodes, drag.id, { x: drag.previewX, y: drag.previewY });
10817
+ }
10818
+ const selectedItem = selectedId != null ? drawnItems.find((it) => it.id === selectedId) : void 0;
10819
+ if (selectedItem) {
10820
+ const overlaySource = drag && drag.moved && drag.id === selectedId ? { ...selectedItem, pos: { x: drag.previewX, y: drag.previewY } } : selectedItem;
10821
+ paintNodes = [...paintNodes, ...selectionOverlayNodes(projector, overlaySource)];
10822
+ }
10823
+ }
10824
+ for (const node of paintNodes) paintDrawable(painter, node, dctx);
10748
10825
  painter.restore();
10749
- scheduleAnimation(drawables);
10750
- }, [viewportSize, backgroundImage, bgColor, drawables, projector, cameraRef, bumpAtlas, getImage, cameraPos, defaultGridFocus, camera, dragDistance]);
10826
+ scheduleAnimation(paintNodes);
10827
+ }, [viewportSize, backgroundImage, bgColor, drawables, projector, cameraRef, bumpAtlas, getImage, cameraPos, defaultGridFocus, camera, dragDistance, editable, selectedId, drawnItems]);
10751
10828
  useEffect(() => {
10752
10829
  drawTimeRef.current = draw;
10753
10830
  }, [draw]);
@@ -10792,23 +10869,83 @@ function Canvas2D({
10792
10869
  };
10793
10870
  }, [camera, followTarget, lerpToTarget, draw]);
10794
10871
  const singlePointerActiveRef = useRef(false);
10872
+ const editDragRef = useRef(null);
10873
+ const pointerToScene = useCallback((clientX, clientY) => {
10874
+ const canvas = canvasRef.current;
10875
+ if (!canvas) return { x: 0, y: 0 };
10876
+ const world = screenToWorld(clientX, clientY, canvas, viewportSize);
10877
+ const adjustedX = world.x - scaledTileWidth / 2;
10878
+ const adjustedY = squareGrid ? world.y - scaledTileWidth / 2 : world.y - scaledDiamondTopY - scaledFloorHeight / 2;
10879
+ return unproject(adjustedX, adjustedY);
10880
+ }, [screenToWorld, viewportSize, scaledTileWidth, squareGrid, scaledDiamondTopY, scaledFloorHeight, unproject]);
10795
10881
  const handleCanvasPointerDown = useCallback((e) => {
10796
10882
  singlePointerActiveRef.current = true;
10883
+ if (editable) {
10884
+ if (!canvasRef.current) return;
10885
+ const world = screenToWorld(e.clientX, e.clientY, canvasRef.current, viewportSize);
10886
+ const hitId = hitTestSprites(drawnItems, projector, world);
10887
+ if (hitId === void 0) return;
10888
+ const item = [...drawnItems].reverse().find((it) => it.id === hitId);
10889
+ if (!item) return;
10890
+ editDragRef.current = {
10891
+ id: hitId,
10892
+ pointerId: e.pointerId,
10893
+ startClientX: e.clientX,
10894
+ startClientY: e.clientY,
10895
+ startSceneX: item.pos.x,
10896
+ startSceneY: item.pos.y,
10897
+ moved: false,
10898
+ previewX: item.pos.x,
10899
+ previewY: item.pos.y
10900
+ };
10901
+ return;
10902
+ }
10797
10903
  if (enableCamera) handlePointerDown(e);
10798
- }, [enableCamera, handlePointerDown]);
10904
+ }, [editable, screenToWorld, viewportSize, drawnItems, projector, enableCamera, handlePointerDown]);
10799
10905
  const handleCanvasPointerMove = useCallback((e) => {
10906
+ if (editable) {
10907
+ const drag = editDragRef.current;
10908
+ if (!drag || drag.pointerId !== e.pointerId) return;
10909
+ const dxPx = e.clientX - drag.startClientX;
10910
+ const dyPx = e.clientY - drag.startClientY;
10911
+ if (!drag.moved && Math.abs(dxPx) + Math.abs(dyPx) <= 5) return;
10912
+ drag.moved = true;
10913
+ const nowScene = pointerToScene(e.clientX, e.clientY);
10914
+ const startScene = pointerToScene(drag.startClientX, drag.startClientY);
10915
+ drag.previewX = drag.startSceneX + (nowScene.x - startScene.x);
10916
+ drag.previewY = drag.startSceneY + (nowScene.y - startScene.y);
10917
+ draw();
10918
+ return;
10919
+ }
10800
10920
  if (enableCamera) handlePointerMove(e, () => draw());
10801
- }, [enableCamera, handlePointerMove, draw]);
10921
+ }, [editable, pointerToScene, draw, enableCamera, handlePointerMove]);
10802
10922
  const handleCanvasHover = useCallback((e) => {
10803
10923
  if (singlePointerActiveRef.current) return;
10804
10924
  if (!tileHoverEvent || !canvasRef.current) return;
10805
- const world = screenToWorld(e.clientX, e.clientY, canvasRef.current, viewportSize);
10806
- const adjustedX = world.x - scaledTileWidth / 2;
10807
- const adjustedY = squareGrid ? world.y - scaledTileWidth / 2 : world.y - scaledDiamondTopY - scaledFloorHeight / 2;
10808
- const isoPos = unproject(adjustedX, adjustedY);
10925
+ const isoPos = pointerToScene(e.clientX, e.clientY);
10809
10926
  eventBus.emit(`UI:${tileHoverEvent}`, { x: isoPos.x, y: isoPos.y });
10810
- }, [screenToWorld, viewportSize, scaledTileWidth, squareGrid, scaledDiamondTopY, scaledFloorHeight, unproject, tileHoverEvent, eventBus]);
10927
+ }, [pointerToScene, tileHoverEvent, eventBus]);
10811
10928
  const handleCanvasPointerUp = useCallback((e) => {
10929
+ if (editable) {
10930
+ singlePointerActiveRef.current = false;
10931
+ const drag = editDragRef.current;
10932
+ if (drag && drag.pointerId === e.pointerId) {
10933
+ editDragRef.current = null;
10934
+ if (drag.moved) {
10935
+ onMove?.(drag.id, drag.previewX, drag.previewY);
10936
+ if (moveEvent) eventBus.emit(`UI:${moveEvent}`, { id: drag.id, x: drag.previewX, y: drag.previewY });
10937
+ draw();
10938
+ return;
10939
+ }
10940
+ const next = selectedId === drag.id ? null : drag.id;
10941
+ onSelect?.(next);
10942
+ if (selectEvent) eventBus.emit(`UI:${selectEvent}`, { id: next });
10943
+ return;
10944
+ }
10945
+ onSelect?.(null);
10946
+ if (selectEvent) eventBus.emit(`UI:${selectEvent}`, { id: null });
10947
+ return;
10948
+ }
10812
10949
  singlePointerActiveRef.current = false;
10813
10950
  if (enableCamera) handlePointerUp();
10814
10951
  if (dragDistance() > 5) return;
@@ -10819,16 +10956,14 @@ function Canvas2D({
10819
10956
  eventBus.emit(`UI:${unitClickEvent}`, { unitId: spriteHit });
10820
10957
  return;
10821
10958
  }
10822
- const adjustedX = world.x - scaledTileWidth / 2;
10823
- const adjustedY = squareGrid ? world.y - scaledTileWidth / 2 : world.y - scaledDiamondTopY - scaledFloorHeight / 2;
10824
- const isoPos = unproject(adjustedX, adjustedY);
10959
+ const isoPos = pointerToScene(e.clientX, e.clientY);
10825
10960
  const hitId = hitIndex.get(`${isoPos.x},${isoPos.y}`);
10826
10961
  if (hitId !== void 0 && unitClickEvent) {
10827
10962
  eventBus.emit(`UI:${unitClickEvent}`, { unitId: hitId });
10828
10963
  } else if (tileClickEvent) {
10829
10964
  eventBus.emit(`UI:${tileClickEvent}`, { x: isoPos.x, y: isoPos.y });
10830
10965
  }
10831
- }, [enableCamera, handlePointerUp, dragDistance, screenToWorld, viewportSize, scaledTileWidth, squareGrid, scaledDiamondTopY, scaledFloorHeight, unproject, hitIndex, drawnItems, projector, tileClickEvent, unitClickEvent, eventBus]);
10966
+ }, [editable, selectedId, onMove, moveEvent, onSelect, selectEvent, eventBus, draw, enableCamera, handlePointerUp, dragDistance, screenToWorld, viewportSize, drawnItems, projector, tileClickEvent, unitClickEvent, hitIndex, pointerToScene]);
10832
10967
  const handleCanvasPointerLeave = useCallback(() => {
10833
10968
  handleMouseLeave();
10834
10969
  if (tileLeaveEvent) eventBus.emit(`UI:${tileLeaveEvent}`, {});
@@ -10847,7 +10982,7 @@ function Canvas2D({
10847
10982
  }, [enableCamera, handlePointerUp]);
10848
10983
  const gestureHandlers = useCanvasGestures({
10849
10984
  canvasRef,
10850
- enabled: enableCamera || !!tileHoverEvent || !!tileClickEvent || !!unitClickEvent,
10985
+ enabled: enableCamera || !!tileHoverEvent || !!tileClickEvent || !!unitClickEvent || editable,
10851
10986
  onPointerDown: handleCanvasPointerDown,
10852
10987
  onPointerMove: handleCanvasPointerMove,
10853
10988
  onPointerUp: handleCanvasPointerUp,
@@ -10979,7 +11114,7 @@ function Canvas2D({
10979
11114
  }
10980
11115
  ) });
10981
11116
  }
10982
- var canvas2DLog;
11117
+ var canvas2DLog, EDIT_SELECTION_COLOR, EDIT_HANDLE_SIZE_PX, EDIT_SELECTION_CORNERS;
10983
11118
  var init_Canvas2D = __esm({
10984
11119
  "components/game/molecules/Canvas2D.tsx"() {
10985
11120
  "use client";
@@ -11004,8 +11139,12 @@ var init_Canvas2D = __esm({
11004
11139
  init_DrawGroup();
11005
11140
  init_registry();
11006
11141
  init_hitTest();
11142
+ init_contract();
11007
11143
  init_isometric();
11008
11144
  canvas2DLog = createLogger("almadar:ui:game-canvas");
11145
+ EDIT_SELECTION_COLOR = "#3b82f6";
11146
+ EDIT_HANDLE_SIZE_PX = 8;
11147
+ EDIT_SELECTION_CORNERS = [[0, 0], [1, 0], [0, 1], [1, 1]];
11009
11148
  Canvas2D.displayName = "Canvas2D";
11010
11149
  }
11011
11150
  });
@@ -11047,6 +11186,12 @@ function Canvas({
11047
11186
  featureClickEvent,
11048
11187
  keyMap,
11049
11188
  keyUpMap,
11189
+ editable,
11190
+ selectedId,
11191
+ onSelect,
11192
+ onMove,
11193
+ selectEvent,
11194
+ moveEvent,
11050
11195
  children
11051
11196
  }) {
11052
11197
  canvasLog.debug("Canvas render", { mode, drawablesCount: drawables?.length, projection, camera: camera ? JSON.stringify(camera) : void 0 });
@@ -11061,7 +11206,7 @@ function Canvas({
11061
11206
  if (mode !== "3d") return;
11062
11207
  const next = childDrawablesRef.current;
11063
11208
  canvasLog.debug("children:adopt", { registered: next.length, adopted: childDrawables.length });
11064
- if (next.length === 0 && React86.Children.count(children) > 0) return;
11209
+ if (next.length === 0 && React87.Children.count(children) > 0) return;
11065
11210
  setChildDrawables(
11066
11211
  (prev) => prev.length === next.length && JSON.stringify(prev) === JSON.stringify(next) ? prev : [...next]
11067
11212
  );
@@ -11099,7 +11244,7 @@ function Canvas({
11099
11244
  };
11100
11245
  return /* @__PURE__ */ jsxs(Fragment, { children: [
11101
11246
  /* @__PURE__ */ jsx(Suspense, { fallback: null, children: /* @__PURE__ */ jsx(Canvas3DHost, { ...props3d }) }),
11102
- React86.Children.count(children) > 0 && /* @__PURE__ */ jsx(DrawableRegistryContext.Provider, { value: registerChildDrawable, children: /* @__PURE__ */ jsx("div", { "aria-hidden": "true", style: { position: "absolute", width: 0, height: 0, overflow: "hidden" }, children }) })
11247
+ React87.Children.count(children) > 0 && /* @__PURE__ */ jsx(DrawableRegistryContext.Provider, { value: registerChildDrawable, children: /* @__PURE__ */ jsx("div", { "aria-hidden": "true", style: { position: "absolute", width: 0, height: 0, overflow: "hidden" }, children }) })
11103
11248
  ] });
11104
11249
  }
11105
11250
  return /* @__PURE__ */ jsx(
@@ -11124,6 +11269,12 @@ function Canvas({
11124
11269
  tileLeaveEvent,
11125
11270
  keyMap,
11126
11271
  keyUpMap,
11272
+ editable,
11273
+ selectedId,
11274
+ onSelect,
11275
+ onMove,
11276
+ selectEvent,
11277
+ moveEvent,
11127
11278
  ...children !== void 0 ? { children } : {}
11128
11279
  }
11129
11280
  );
@@ -11145,15 +11296,19 @@ function GameAudioToggle({
11145
11296
  size = "sm",
11146
11297
  className,
11147
11298
  onAsset,
11148
- offAsset
11299
+ offAsset,
11300
+ toggleEvent
11149
11301
  }) {
11150
11302
  const ctx = useGameAudioContextOptional();
11151
11303
  const [localMuted, setLocalMuted] = useState(false);
11152
11304
  const muted = ctx ? ctx.muted : localMuted;
11153
11305
  const setMuted = ctx ? ctx.setMuted : setLocalMuted;
11306
+ const eventBus = useEventBus();
11154
11307
  const handleToggle = useCallback(() => {
11155
- setMuted(!muted);
11156
- }, [muted, setMuted]);
11308
+ const next = !muted;
11309
+ setMuted(next);
11310
+ if (toggleEvent) eventBus.emit(`UI:${toggleEvent}`, { muted: next });
11311
+ }, [muted, setMuted, toggleEvent, eventBus]);
11157
11312
  const activeAsset = muted ? offAsset : onAsset;
11158
11313
  return /* @__PURE__ */ jsx(
11159
11314
  Button,
@@ -11172,10 +11327,319 @@ var init_GameAudioToggle = __esm({
11172
11327
  "use client";
11173
11328
  init_atoms();
11174
11329
  init_cn();
11330
+ init_useEventBus();
11175
11331
  init_GameIcon();
11176
11332
  GameAudioToggle.displayName = "GameAudioToggle";
11177
11333
  }
11178
11334
  });
11335
+ function pickPath(entry) {
11336
+ if (Array.isArray(entry.path)) {
11337
+ return entry.path[Math.floor(Math.random() * entry.path.length)];
11338
+ }
11339
+ return entry.path;
11340
+ }
11341
+ function useGameAudio({
11342
+ manifest,
11343
+ baseUrl = "",
11344
+ initialMuted = false,
11345
+ initialVolume = 1
11346
+ }) {
11347
+ const [muted, setMutedState] = useState(initialMuted);
11348
+ const [masterVolume, setMasterVolumeState] = useState(initialVolume);
11349
+ const mutedRef = useRef(muted);
11350
+ const volumeRef = useRef(masterVolume);
11351
+ const manifestRef = useRef(manifest);
11352
+ mutedRef.current = muted;
11353
+ volumeRef.current = masterVolume;
11354
+ manifestRef.current = manifest;
11355
+ const poolsRef = useRef(/* @__PURE__ */ new Map());
11356
+ const getOrCreateElement = useCallback((key) => {
11357
+ const entry = manifestRef.current[key];
11358
+ if (!entry) return null;
11359
+ let pool = poolsRef.current.get(key);
11360
+ if (!pool) {
11361
+ pool = [];
11362
+ poolsRef.current.set(key, pool);
11363
+ }
11364
+ const maxSize = entry.poolSize ?? 1;
11365
+ for (const audio of pool) {
11366
+ if (audio.paused && (audio.ended || audio.currentTime === 0)) {
11367
+ return audio;
11368
+ }
11369
+ }
11370
+ if (pool.length < maxSize) {
11371
+ const src = baseUrl + pickPath(entry);
11372
+ const audio = new Audio(src);
11373
+ audio.loop = entry.loop ?? false;
11374
+ pool.push(audio);
11375
+ return audio;
11376
+ }
11377
+ if (!entry.loop) {
11378
+ let oldest = pool[0];
11379
+ for (const audio of pool) {
11380
+ if (audio.currentTime > oldest.currentTime) {
11381
+ oldest = audio;
11382
+ }
11383
+ }
11384
+ oldest.pause();
11385
+ oldest.currentTime = 0;
11386
+ return oldest;
11387
+ }
11388
+ return null;
11389
+ }, [baseUrl]);
11390
+ const play = useCallback((key) => {
11391
+ if (mutedRef.current) return;
11392
+ const entry = manifestRef.current[key];
11393
+ if (!entry) return;
11394
+ const audio = getOrCreateElement(key);
11395
+ if (!audio) return;
11396
+ audio.volume = Math.min(1, (entry.volume ?? 1) * volumeRef.current);
11397
+ if (!entry.loop) {
11398
+ audio.currentTime = 0;
11399
+ }
11400
+ const promise = audio.play();
11401
+ if (promise) {
11402
+ promise.catch(() => {
11403
+ });
11404
+ }
11405
+ }, [getOrCreateElement]);
11406
+ const stop = useCallback((key) => {
11407
+ const pool = poolsRef.current.get(key);
11408
+ if (!pool) return;
11409
+ for (const audio of pool) {
11410
+ audio.pause();
11411
+ audio.currentTime = 0;
11412
+ }
11413
+ }, []);
11414
+ const currentMusicKeyRef = useRef(null);
11415
+ const currentMusicElRef = useRef(null);
11416
+ const musicFadeRef = useRef(null);
11417
+ const pendingMusicKeyRef = useRef(null);
11418
+ const clearMusicFade = useCallback(() => {
11419
+ if (musicFadeRef.current) {
11420
+ clearInterval(musicFadeRef.current);
11421
+ musicFadeRef.current = null;
11422
+ }
11423
+ }, []);
11424
+ const playMusic = useCallback((key) => {
11425
+ if (key === currentMusicKeyRef.current) return;
11426
+ pendingMusicKeyRef.current = key;
11427
+ const entry = manifestRef.current[key];
11428
+ if (!entry) return;
11429
+ const fadeDurationMs = entry.crossfadeDurationMs ?? 1500;
11430
+ const stepMs = 50;
11431
+ const totalSteps = Math.max(1, fadeDurationMs / stepMs);
11432
+ const targetVolume = Math.min(1, (entry.volume ?? 1) * volumeRef.current);
11433
+ clearMusicFade();
11434
+ const src = baseUrl + (Array.isArray(entry.path) ? entry.path[0] : entry.path);
11435
+ const incoming = new Audio(src);
11436
+ incoming.loop = true;
11437
+ incoming.volume = 0;
11438
+ const outgoing = currentMusicElRef.current;
11439
+ const outgoingStartVol = outgoing?.volume ?? 0;
11440
+ currentMusicKeyRef.current = key;
11441
+ currentMusicElRef.current = incoming;
11442
+ if (!mutedRef.current) {
11443
+ incoming.play().catch(() => {
11444
+ currentMusicKeyRef.current = null;
11445
+ currentMusicElRef.current = outgoing;
11446
+ });
11447
+ }
11448
+ let step = 0;
11449
+ musicFadeRef.current = setInterval(() => {
11450
+ step++;
11451
+ const progress = Math.min(step / totalSteps, 1);
11452
+ incoming.volume = Math.min(1, targetVolume * progress);
11453
+ if (outgoing) {
11454
+ outgoing.volume = Math.max(0, outgoingStartVol * (1 - progress));
11455
+ }
11456
+ if (progress >= 1) {
11457
+ clearMusicFade();
11458
+ if (outgoing) {
11459
+ outgoing.pause();
11460
+ outgoing.src = "";
11461
+ }
11462
+ }
11463
+ }, stepMs);
11464
+ }, [baseUrl, clearMusicFade]);
11465
+ const stopMusic = useCallback((fadeDurationMs = 1e3) => {
11466
+ const outgoing = currentMusicElRef.current;
11467
+ if (!outgoing) return;
11468
+ currentMusicKeyRef.current = null;
11469
+ currentMusicElRef.current = null;
11470
+ pendingMusicKeyRef.current = null;
11471
+ clearMusicFade();
11472
+ const startVolume = outgoing.volume;
11473
+ const stepMs = 50;
11474
+ const totalSteps = Math.max(1, fadeDurationMs / stepMs);
11475
+ let step = 0;
11476
+ musicFadeRef.current = setInterval(() => {
11477
+ step++;
11478
+ const progress = step / totalSteps;
11479
+ outgoing.volume = Math.max(0, startVolume * (1 - progress));
11480
+ if (progress >= 1) {
11481
+ clearMusicFade();
11482
+ outgoing.pause();
11483
+ outgoing.src = "";
11484
+ }
11485
+ }, stepMs);
11486
+ }, [clearMusicFade]);
11487
+ const stopAll = useCallback(() => {
11488
+ for (const pool of poolsRef.current.values()) {
11489
+ for (const audio of pool) {
11490
+ audio.pause();
11491
+ audio.currentTime = 0;
11492
+ }
11493
+ }
11494
+ stopMusic(0);
11495
+ }, [stopMusic]);
11496
+ const setMuted = useCallback((value) => {
11497
+ setMutedState(value);
11498
+ if (value) {
11499
+ for (const [key, pool] of poolsRef.current.entries()) {
11500
+ if (manifestRef.current[key]?.loop) {
11501
+ for (const audio of pool) {
11502
+ if (!audio.paused) audio.pause();
11503
+ }
11504
+ }
11505
+ }
11506
+ currentMusicElRef.current?.pause();
11507
+ } else {
11508
+ for (const [key, pool] of poolsRef.current.entries()) {
11509
+ const entry = manifestRef.current[key];
11510
+ if (entry?.loop && entry?.autostart) {
11511
+ for (const audio of pool) {
11512
+ if (audio.paused) audio.play().catch(() => {
11513
+ });
11514
+ }
11515
+ }
11516
+ }
11517
+ const musicEl = currentMusicElRef.current;
11518
+ if (musicEl) {
11519
+ musicEl.play().catch(() => {
11520
+ });
11521
+ }
11522
+ }
11523
+ }, []);
11524
+ const setMasterVolume = useCallback((volume) => {
11525
+ const clamped = Math.max(0, Math.min(1, volume));
11526
+ setMasterVolumeState(clamped);
11527
+ for (const [key, pool] of poolsRef.current.entries()) {
11528
+ const entryVol = manifestRef.current[key]?.volume ?? 1;
11529
+ for (const audio of pool) {
11530
+ audio.volume = Math.min(1, entryVol * clamped);
11531
+ }
11532
+ }
11533
+ if (!musicFadeRef.current && currentMusicElRef.current) {
11534
+ const key = currentMusicKeyRef.current;
11535
+ const entryVol = key ? manifestRef.current[key]?.volume ?? 1 : 1;
11536
+ currentMusicElRef.current.volume = Math.min(1, entryVol * clamped);
11537
+ }
11538
+ }, []);
11539
+ const unlockedRef = useRef(false);
11540
+ useEffect(() => {
11541
+ const autoKeys = Object.keys(manifest).filter((k) => manifest[k].autostart);
11542
+ const hasPendingMusic = () => pendingMusicKeyRef.current !== null;
11543
+ const hasAutoStart = autoKeys.length > 0;
11544
+ if (!hasAutoStart && !hasPendingMusic()) return;
11545
+ const unlock = () => {
11546
+ if (unlockedRef.current) return;
11547
+ unlockedRef.current = true;
11548
+ if (!mutedRef.current) {
11549
+ for (const key of autoKeys) {
11550
+ play(key);
11551
+ }
11552
+ const pending = pendingMusicKeyRef.current;
11553
+ if (pending && pending !== currentMusicKeyRef.current) {
11554
+ playMusic(pending);
11555
+ }
11556
+ }
11557
+ };
11558
+ document.addEventListener("click", unlock, { once: true });
11559
+ document.addEventListener("keydown", unlock, { once: true });
11560
+ document.addEventListener("touchstart", unlock, { once: true });
11561
+ return () => {
11562
+ document.removeEventListener("click", unlock);
11563
+ document.removeEventListener("keydown", unlock);
11564
+ document.removeEventListener("touchstart", unlock);
11565
+ };
11566
+ }, [manifest, play, playMusic]);
11567
+ useEffect(() => {
11568
+ return () => {
11569
+ clearMusicFade();
11570
+ for (const pool of poolsRef.current.values()) {
11571
+ for (const audio of pool) {
11572
+ audio.pause();
11573
+ audio.src = "";
11574
+ }
11575
+ }
11576
+ poolsRef.current.clear();
11577
+ if (currentMusicElRef.current) {
11578
+ currentMusicElRef.current.pause();
11579
+ currentMusicElRef.current.src = "";
11580
+ currentMusicElRef.current = null;
11581
+ }
11582
+ };
11583
+ }, [clearMusicFade]);
11584
+ return {
11585
+ play,
11586
+ stop,
11587
+ stopAll,
11588
+ playMusic,
11589
+ stopMusic,
11590
+ muted,
11591
+ setMuted,
11592
+ masterVolume,
11593
+ setMasterVolume
11594
+ };
11595
+ }
11596
+ var init_useGameAudio = __esm({
11597
+ "hooks/useGameAudio.ts"() {
11598
+ "use client";
11599
+ useGameAudio.displayName = "useGameAudio";
11600
+ }
11601
+ });
11602
+ function GameAudioCue({
11603
+ cue,
11604
+ cueSeq,
11605
+ music,
11606
+ muted,
11607
+ volume,
11608
+ manifest,
11609
+ baseUrl
11610
+ }) {
11611
+ const { play, playMusic, stopMusic, setMuted, setMasterVolume } = useGameAudio({
11612
+ manifest,
11613
+ baseUrl,
11614
+ initialMuted: muted,
11615
+ initialVolume: volume
11616
+ });
11617
+ const prevCueSeqRef = useRef(cueSeq);
11618
+ useEffect(() => {
11619
+ if (cue && cueSeq !== void 0 && cueSeq !== prevCueSeqRef.current) {
11620
+ play(cue);
11621
+ }
11622
+ prevCueSeqRef.current = cueSeq;
11623
+ }, [cue, cueSeq, play]);
11624
+ useEffect(() => {
11625
+ if (music) playMusic(music);
11626
+ else stopMusic();
11627
+ }, [music, playMusic, stopMusic]);
11628
+ useEffect(() => {
11629
+ if (muted !== void 0) setMuted(muted);
11630
+ }, [muted, setMuted]);
11631
+ useEffect(() => {
11632
+ if (volume !== void 0) setMasterVolume(volume);
11633
+ }, [volume, setMasterVolume]);
11634
+ return null;
11635
+ }
11636
+ var init_GameAudioCue = __esm({
11637
+ "components/game/atoms/GameAudioCue.tsx"() {
11638
+ "use client";
11639
+ init_useGameAudio();
11640
+ GameAudioCue.displayName = "GameAudioCue";
11641
+ }
11642
+ });
11179
11643
  function isKnownState(s) {
11180
11644
  return s in DEFAULT_STATE_STYLES;
11181
11645
  }
@@ -11257,7 +11721,7 @@ function LinearView({
11257
11721
  /* @__PURE__ */ jsx(HStack, { className: "flex-wrap items-center", gap: "xs", children: trait.states.map((state, i) => {
11258
11722
  const isDone = i < currentIdx;
11259
11723
  const isCurrent = i === currentIdx;
11260
- return /* @__PURE__ */ jsxs(React86__default.Fragment, { children: [
11724
+ return /* @__PURE__ */ jsxs(React87__default.Fragment, { children: [
11261
11725
  i > 0 && /* @__PURE__ */ jsx(
11262
11726
  Typography,
11263
11727
  {
@@ -11792,7 +12256,7 @@ function SequenceBar({
11792
12256
  else onSlotRemove?.(index);
11793
12257
  }, [emit, slotRemoveEvent, onSlotRemove, playing]);
11794
12258
  const paddedSlots = Array.from({ length: maxSlots }, (_, i) => slots[i]);
11795
- return /* @__PURE__ */ jsx(HStack, { className: cn("items-center", className), gap: "sm", children: paddedSlots.map((slot, i) => /* @__PURE__ */ jsxs(React86__default.Fragment, { children: [
12259
+ return /* @__PURE__ */ jsx(HStack, { className: cn("items-center", className), gap: "sm", children: paddedSlots.map((slot, i) => /* @__PURE__ */ jsxs(React87__default.Fragment, { children: [
11796
12260
  i > 0 && /* @__PURE__ */ jsx(
11797
12261
  Typography,
11798
12262
  {
@@ -11874,15 +12338,18 @@ var init_StateJsonView = __esm({
11874
12338
  StateJsonView.displayName = "StateJsonView";
11875
12339
  }
11876
12340
  });
11877
- var GAME_FONTS, GameShell;
11878
- var init_GameShell = __esm({
11879
- "components/game/templates/GameShell.tsx"() {
11880
- init_cn();
11881
- init_Box();
11882
- init_Card();
11883
- init_Typography();
11884
- init_AtlasImage();
11885
- GAME_FONTS = {
12341
+
12342
+ // lib/gameFonts.ts
12343
+ function resolveGameFontFamily(input) {
12344
+ if (!input) return void 0;
12345
+ const resolved = GAME_FONT_KEYS[input];
12346
+ if (resolved) return `'${resolved}', ui-sans-serif, system-ui, sans-serif`;
12347
+ return input;
12348
+ }
12349
+ var GAME_FONT_KEYS;
12350
+ var init_gameFonts = __esm({
12351
+ "lib/gameFonts.ts"() {
12352
+ GAME_FONT_KEYS = {
11886
12353
  fredoka: "Fredoka",
11887
12354
  future: "Kenney Future",
11888
12355
  "future-narrow": "Kenney Future Narrow",
@@ -11890,6 +12357,17 @@ var init_GameShell = __esm({
11890
12357
  blocks: "Kenney Blocks",
11891
12358
  mini: "Kenney Mini"
11892
12359
  };
12360
+ }
12361
+ });
12362
+ var GameShell;
12363
+ var init_GameShell = __esm({
12364
+ "components/game/templates/GameShell.tsx"() {
12365
+ init_cn();
12366
+ init_gameFonts();
12367
+ init_Box();
12368
+ init_Card();
12369
+ init_Typography();
12370
+ init_AtlasImage();
11893
12371
  GameShell = ({
11894
12372
  appName = "Game",
11895
12373
  hud,
@@ -11903,7 +12381,7 @@ var init_GameShell = __esm({
11903
12381
  fontFamily,
11904
12382
  "data-theme": dataTheme
11905
12383
  }) => {
11906
- const font = fontFamily ? GAME_FONTS[fontFamily] ?? fontFamily : void 0;
12384
+ const displayFont = resolveGameFontFamily(fontFamily);
11907
12385
  return /* @__PURE__ */ jsxs(
11908
12386
  Box,
11909
12387
  {
@@ -11922,7 +12400,7 @@ var init_GameShell = __esm({
11922
12400
  // passed — an always-on inline stamp would shadow the orbital's
11923
12401
  // inline-theme font-family-display token (inline style beats the
11924
12402
  // theme provider's vars for the whole shell subtree).
11925
- ...font ? { "--font-family-display": `'${font}', ui-sans-serif, system-ui, sans-serif` } : {}
12403
+ ...displayFont ? { "--font-family-display": displayFont } : {}
11926
12404
  },
11927
12405
  children: [
11928
12406
  backgroundAsset && /* @__PURE__ */ jsx(
@@ -12120,14 +12598,15 @@ function drawArrowHead(ctx, x1, y1, x2, y2, size) {
12120
12598
  ctx.closePath();
12121
12599
  ctx.fill();
12122
12600
  }
12123
- function drawShape(ctx, shape, width, height, allShapes) {
12601
+ function drawShape(ctx, shape, width, height, allShapes, fontFamily) {
12124
12602
  ctx.save();
12125
12603
  const opacity = shape.opacity ?? 1;
12126
12604
  ctx.globalAlpha = opacity;
12127
12605
  const stroke = resolveColor2(shape.color, ctx, "#333333");
12128
12606
  const fill = shape.fill ? resolveColor2(shape.fill, ctx, "#cccccc") : void 0;
12129
12607
  ctx.lineWidth = shape.lineWidth ?? 2;
12130
- if (shape.dash) ctx.setLineDash([...DASH_PATTERNS[shape.dash]]);
12608
+ const dashPattern = shape.dash ? DASH_PATTERNS[shape.dash] : void 0;
12609
+ if (dashPattern) ctx.setLineDash([...dashPattern]);
12131
12610
  switch (shape.type) {
12132
12611
  case "grid": {
12133
12612
  const step = shape.step ?? 40;
@@ -12249,7 +12728,7 @@ function drawShape(ctx, shape, width, height, allShapes) {
12249
12728
  case "text": {
12250
12729
  if (shape.x == null || shape.y == null || !shape.text) break;
12251
12730
  ctx.fillStyle = stroke;
12252
- ctx.font = `${shape.fontSize ?? 14}px ${themeBodyFont(ctx.canvas)}`;
12731
+ ctx.font = `${shape.fontSize ?? 14}px ${shape.fontFamily ?? fontFamily ?? themeBodyFont(ctx.canvas)}`;
12253
12732
  ctx.textAlign = shape.align ?? "left";
12254
12733
  ctx.textBaseline = "middle";
12255
12734
  ctx.fillText(shape.text, shape.x, shape.y);
@@ -12291,7 +12770,7 @@ function drawShape(ctx, shape, width, height, allShapes) {
12291
12770
  }
12292
12771
  ctx.restore();
12293
12772
  }
12294
- function readoutShapes(readouts, width) {
12773
+ function readoutShapes(readouts, width, fontFamily) {
12295
12774
  const out = [];
12296
12775
  const chipH = 18;
12297
12776
  const gap = 6;
@@ -12315,13 +12794,14 @@ function readoutShapes(readouts, width) {
12315
12794
  text,
12316
12795
  color: "#ffffff",
12317
12796
  fontSize: 10,
12318
- align: "center"
12797
+ align: "center",
12798
+ fontFamily
12319
12799
  });
12320
12800
  rightEdge = chipX - gap;
12321
12801
  }
12322
12802
  return out;
12323
12803
  }
12324
- function traceShapes(panel, k, width, height) {
12804
+ function traceShapes(panel, k, width, height, fontFamily) {
12325
12805
  const w = panel.width ?? Math.round(width * 0.32);
12326
12806
  const h = panel.height ?? Math.round(height * 0.28);
12327
12807
  const x = panel.x ?? width - w - 8;
@@ -12375,14 +12855,14 @@ function traceShapes(panel, k, width, height) {
12375
12855
  out.push({ type: "circle", x: last.x, y: last.y, radius: 2, color, fill: color });
12376
12856
  }
12377
12857
  if (series.label) {
12378
- out.push({ type: "text", x: x + 6, y: y + 10 + 11 * j, text: series.label, color, fontSize: 9 });
12858
+ out.push({ type: "text", x: x + 6, y: y + 10 + 11 * j, text: series.label, color, fontSize: 9, fontFamily });
12379
12859
  }
12380
12860
  });
12381
12861
  if (panel.yLabel) {
12382
- out.push({ type: "text", x: x + w - 6, y: y + 10, text: panel.yLabel, color: "#6b7280", fontSize: 9, align: "right" });
12862
+ out.push({ type: "text", x: x + w - 6, y: y + 10, text: panel.yLabel, color: "#6b7280", fontSize: 9, align: "right", fontFamily });
12383
12863
  }
12384
12864
  if (panel.xLabel) {
12385
- out.push({ type: "text", x: x + w - 6, y: y + h - 6, text: panel.xLabel, color: "#6b7280", fontSize: 9, align: "right" });
12865
+ out.push({ type: "text", x: x + w - 6, y: y + h - 6, text: panel.xLabel, color: "#6b7280", fontSize: 9, align: "right", fontFamily });
12386
12866
  }
12387
12867
  return out;
12388
12868
  }
@@ -12405,13 +12885,14 @@ var init_LearningCanvas = __esm({
12405
12885
  init_useEventBus();
12406
12886
  init_webPainter2d();
12407
12887
  init_paintDispatch();
12408
- DASH_PATTERNS = { dashed: [6, 4], dotted: [2, 3] };
12888
+ DASH_PATTERNS = { solid: [], dashed: [6, 4], dotted: [2, 3] };
12409
12889
  TRACE_SERIES_COLORS = ["#2563eb", "#dc2626", "#16a34a", "#f59e0b"];
12410
12890
  LearningCanvas = ({
12411
12891
  className,
12412
12892
  width = 600,
12413
12893
  height = 400,
12414
12894
  backgroundColor,
12895
+ fontFamily,
12415
12896
  shapes = [],
12416
12897
  drawables,
12417
12898
  projector,
@@ -12447,10 +12928,10 @@ var init_LearningCanvas = __esm({
12447
12928
  }, [shapes]);
12448
12929
  const derivedShapes = useMemo(() => {
12449
12930
  if (!traces?.length && !readouts?.length) return shapes;
12450
- const traceOut = (traces ?? []).flatMap((panel, k) => traceShapes(panel, k, width, height));
12451
- const readoutOut = readouts?.length ? readoutShapes(readouts, width) : [];
12931
+ const traceOut = (traces ?? []).flatMap((panel, k) => traceShapes(panel, k, width, height, fontFamily));
12932
+ const readoutOut = readouts?.length ? readoutShapes(readouts, width, fontFamily) : [];
12452
12933
  return [...shapes, ...traceOut, ...readoutOut];
12453
- }, [shapes, traces, readouts, width, height]);
12934
+ }, [shapes, traces, readouts, width, height, fontFamily]);
12454
12935
  const draw = useCallback(() => {
12455
12936
  const _perfT = perfStart("learningcanvas:paint");
12456
12937
  const canvas = canvasRef.current;
@@ -12469,15 +12950,15 @@ var init_LearningCanvas = __esm({
12469
12950
  ctx.fillRect(0, 0, width, height);
12470
12951
  }
12471
12952
  for (const shape of derivedShapes) {
12472
- if (shape.type !== "text") drawShape(ctx, shape, width, height, derivedShapes);
12953
+ if (shape.type !== "text") drawShape(ctx, shape, width, height, derivedShapes, fontFamily);
12473
12954
  }
12474
12955
  for (const shape of derivedShapes) {
12475
- if (shape.type === "text") drawShape(ctx, shape, width, height, derivedShapes);
12956
+ if (shape.type === "text") drawShape(ctx, shape, width, height, derivedShapes, fontFamily);
12476
12957
  }
12477
12958
  if (drawables?.length && projector) {
12478
12959
  const painter = createWebPainter(ctx, invalidateRef.current);
12479
12960
  const timeMs = needsAnim && typeof performance !== "undefined" ? performance.now() : 0;
12480
- const dctx = { projector, time: timeMs, invalidate: invalidateRef.current, fontFamily: themeBodyFont(canvas) };
12961
+ const dctx = { projector, time: timeMs, invalidate: invalidateRef.current, fontFamily: fontFamily || themeBodyFont(canvas) };
12481
12962
  for (const node of drawables) {
12482
12963
  paintDrawable(painter, node, dctx);
12483
12964
  }
@@ -12639,7 +13120,7 @@ var init_ErrorBoundary = __esm({
12639
13120
  }
12640
13121
  );
12641
13122
  };
12642
- ErrorBoundary = class extends React86__default.Component {
13123
+ ErrorBoundary = class extends React87__default.Component {
12643
13124
  constructor(props) {
12644
13125
  super(props);
12645
13126
  __publicField(this, "reset", () => {
@@ -12908,7 +13389,7 @@ var init_Container = __esm({
12908
13389
  as: Component = "div"
12909
13390
  }) => {
12910
13391
  const resolvedSize = maxWidth ?? size ?? "lg";
12911
- return React86__default.createElement(
13392
+ return React87__default.createElement(
12912
13393
  Component,
12913
13394
  {
12914
13395
  className: cn(
@@ -17076,6 +17557,250 @@ var init_EmptyState = __esm({
17076
17557
  EmptyState.displayName = "EmptyState";
17077
17558
  }
17078
17559
  });
17560
+
17561
+ // lib/editorMotions.ts
17562
+ function clamp(value, min, max) {
17563
+ return Math.max(min, Math.min(max, value));
17564
+ }
17565
+ function computeLines(text) {
17566
+ const lines = [];
17567
+ let start = 0;
17568
+ for (let i = 0; i <= text.length; i++) {
17569
+ if (i === text.length || text[i] === "\n") {
17570
+ lines.push({ start, end: i });
17571
+ start = i + 1;
17572
+ }
17573
+ }
17574
+ return lines;
17575
+ }
17576
+ function lineIndexAt(lines, pos) {
17577
+ for (let i = 0; i < lines.length; i++) {
17578
+ if (pos <= lines[i].end) return i;
17579
+ }
17580
+ return lines.length - 1;
17581
+ }
17582
+ function findWords(text) {
17583
+ const words = [];
17584
+ const re = /\w+|\S+/g;
17585
+ let m;
17586
+ while ((m = re.exec(text)) !== null) {
17587
+ words.push({ start: m.index, end: m.index + m[0].length });
17588
+ }
17589
+ return words;
17590
+ }
17591
+ function nextWordStart(text, pos) {
17592
+ for (const w of findWords(text)) {
17593
+ if (w.start > pos) return w.start;
17594
+ }
17595
+ return text.length;
17596
+ }
17597
+ function prevWordStart(text, pos) {
17598
+ let result = 0;
17599
+ for (const w of findWords(text)) {
17600
+ if (w.start < pos) result = w.start;
17601
+ else break;
17602
+ }
17603
+ return result;
17604
+ }
17605
+ function nextWordEnd(text, pos) {
17606
+ for (const w of findWords(text)) {
17607
+ const lastChar = w.end - 1;
17608
+ if (lastChar > pos) return lastChar;
17609
+ }
17610
+ return text.length > 0 ? text.length - 1 : 0;
17611
+ }
17612
+ function firstNonBlank(text, line) {
17613
+ let i = line.start;
17614
+ while (i < line.end && (text[i] === " " || text[i] === " ")) i++;
17615
+ return i;
17616
+ }
17617
+ function nextParagraphBoundary(lines, fromLineIdx, textLength) {
17618
+ for (let i = fromLineIdx + 1; i < lines.length; i++) {
17619
+ if (lines[i].start === lines[i].end) return lines[i].start;
17620
+ }
17621
+ return textLength;
17622
+ }
17623
+ function prevParagraphBoundary(lines, fromLineIdx) {
17624
+ for (let i = fromLineIdx - 1; i >= 0; i--) {
17625
+ if (lines[i].start === lines[i].end) return lines[i].start;
17626
+ }
17627
+ return 0;
17628
+ }
17629
+ function applyMotion(text, caret, motion, count) {
17630
+ const n = Math.max(1, count);
17631
+ const lines = computeLines(text);
17632
+ const lineIdx = lineIndexAt(lines, caret);
17633
+ const line = lines[lineIdx];
17634
+ switch (motion) {
17635
+ case "left":
17636
+ return clamp(caret - n, line.start, line.end);
17637
+ case "right":
17638
+ return clamp(caret + n, line.start, line.end);
17639
+ case "up": {
17640
+ const col = caret - line.start;
17641
+ const targetIdx = clamp(lineIdx - n, 0, lines.length - 1);
17642
+ const target = lines[targetIdx];
17643
+ return clamp(target.start + col, target.start, target.end);
17644
+ }
17645
+ case "down": {
17646
+ const col = caret - line.start;
17647
+ const targetIdx = clamp(lineIdx + n, 0, lines.length - 1);
17648
+ const target = lines[targetIdx];
17649
+ return clamp(target.start + col, target.start, target.end);
17650
+ }
17651
+ case "word-forward": {
17652
+ let pos = caret;
17653
+ for (let i = 0; i < n; i++) pos = nextWordStart(text, pos);
17654
+ return pos;
17655
+ }
17656
+ case "word-back": {
17657
+ let pos = caret;
17658
+ for (let i = 0; i < n; i++) pos = prevWordStart(text, pos);
17659
+ return pos;
17660
+ }
17661
+ case "word-end": {
17662
+ let pos = caret;
17663
+ for (let i = 0; i < n; i++) pos = nextWordEnd(text, pos);
17664
+ return pos;
17665
+ }
17666
+ case "line-start":
17667
+ return line.start;
17668
+ case "line-end":
17669
+ return line.end > line.start ? line.end - 1 : line.start;
17670
+ case "first-nonblank":
17671
+ return firstNonBlank(text, line);
17672
+ case "doc-start":
17673
+ return 0;
17674
+ case "doc-end":
17675
+ return text.length;
17676
+ case "paragraph-forward": {
17677
+ let pos = caret;
17678
+ for (let i = 0; i < n; i++) {
17679
+ pos = nextParagraphBoundary(lines, lineIndexAt(lines, pos), text.length);
17680
+ }
17681
+ return pos;
17682
+ }
17683
+ case "paragraph-back": {
17684
+ let pos = caret;
17685
+ for (let i = 0; i < n; i++) {
17686
+ pos = prevParagraphBoundary(lines, lineIndexAt(lines, pos));
17687
+ }
17688
+ return pos;
17689
+ }
17690
+ case "line":
17691
+ case "selection":
17692
+ return caret;
17693
+ default: {
17694
+ const _exhaustive = motion;
17695
+ return _exhaustive;
17696
+ }
17697
+ }
17698
+ }
17699
+ function motionRange(text, caret, motion, count, selection) {
17700
+ if (motion === "selection") {
17701
+ if (!selection) return [caret, caret];
17702
+ return [Math.min(selection[0], selection[1]), Math.max(selection[0], selection[1])];
17703
+ }
17704
+ const lines = computeLines(text);
17705
+ if (motion === "line") {
17706
+ const n = Math.max(1, count);
17707
+ const startIdx = lineIndexAt(lines, caret);
17708
+ const endIdx = clamp(startIdx + n - 1, 0, lines.length - 1);
17709
+ const start2 = lines[startIdx].start;
17710
+ const rawEnd = lines[endIdx].end;
17711
+ const end2 = rawEnd < text.length ? rawEnd + 1 : rawEnd;
17712
+ return [start2, end2];
17713
+ }
17714
+ const newCaret = applyMotion(text, caret, motion, count);
17715
+ let start = Math.min(caret, newCaret);
17716
+ let end = Math.max(caret, newCaret);
17717
+ if (motion === "word-end" || motion === "line-end") {
17718
+ end = Math.min(Math.max(start, newCaret) + 1, text.length);
17719
+ } else if (motion === "word-forward" && newCaret > caret) {
17720
+ const startLine = lineIndexAt(lines, caret);
17721
+ const endLine = lineIndexAt(lines, newCaret);
17722
+ if (endLine !== startLine) {
17723
+ end = lines[startLine].end;
17724
+ }
17725
+ }
17726
+ return [start, end];
17727
+ }
17728
+ function applyOperator(text, range, operator, register) {
17729
+ const start = clamp(range[0], 0, text.length);
17730
+ const end = clamp(range[1], start, text.length);
17731
+ const removed = text.slice(start, end);
17732
+ if (operator === "yank") {
17733
+ return { text, caret: start, register: removed };
17734
+ }
17735
+ return { text: text.slice(0, start) + text.slice(end), caret: start, register: removed };
17736
+ }
17737
+ var init_editorMotions = __esm({
17738
+ "lib/editorMotions.ts"() {
17739
+ }
17740
+ });
17741
+ function isMotionPayload(payload) {
17742
+ return !!payload && typeof payload.editorId === "string" && typeof payload.motion === "string" && typeof payload.count === "number";
17743
+ }
17744
+ function isOperatePayload(payload) {
17745
+ return !!payload && typeof payload.editorId === "string" && typeof payload.operator === "string" && typeof payload.motion === "string" && typeof payload.count === "number";
17746
+ }
17747
+ function isInsertTextPayload(payload) {
17748
+ return !!payload && typeof payload.editorId === "string" && typeof payload.text === "string";
17749
+ }
17750
+ function isSetModePayload(payload) {
17751
+ return !!payload && typeof payload.editorId === "string" && typeof payload.mode === "string" && typeof payload.caret === "string";
17752
+ }
17753
+ function useEditorCapabilities(args) {
17754
+ const [caretMode, setCaretMode] = useState("bar");
17755
+ const registerRef = useRef("");
17756
+ useEventListener(`UI:${args.events.onMotion}`, (evt) => {
17757
+ if (!args.editorId || !isMotionPayload(evt.payload) || evt.payload.editorId !== args.editorId) return;
17758
+ const ta = args.textareaRef.current;
17759
+ if (!ta) return;
17760
+ const { motion, count } = evt.payload;
17761
+ const newCaret = applyMotion(ta.value, ta.selectionStart, motion, count);
17762
+ if (ta.selectionStart !== ta.selectionEnd) {
17763
+ ta.setSelectionRange(ta.selectionStart, newCaret);
17764
+ } else {
17765
+ ta.setSelectionRange(newCaret, newCaret);
17766
+ }
17767
+ });
17768
+ useEventListener(`UI:${args.events.onOperate}`, (evt) => {
17769
+ if (!args.editorId || !isOperatePayload(evt.payload) || evt.payload.editorId !== args.editorId) return;
17770
+ const ta = args.textareaRef.current;
17771
+ if (!ta) return;
17772
+ const { operator, motion, count } = evt.payload;
17773
+ const selection = motion === "selection" ? [ta.selectionStart, ta.selectionEnd] : void 0;
17774
+ const range = motionRange(ta.value, ta.selectionStart, motion, count, selection);
17775
+ const result = applyOperator(ta.value, range, operator, registerRef.current);
17776
+ registerRef.current = result.register;
17777
+ if (operator === "yank") {
17778
+ ta.setSelectionRange(range[0], range[0]);
17779
+ } else {
17780
+ ta.setRangeText("", range[0], range[1], "end");
17781
+ }
17782
+ args.applyChange(ta.value);
17783
+ });
17784
+ useEventListener(`UI:${args.events.onInsertText}`, (evt) => {
17785
+ if (!args.editorId || !isInsertTextPayload(evt.payload) || evt.payload.editorId !== args.editorId) return;
17786
+ const ta = args.textareaRef.current;
17787
+ if (!ta) return;
17788
+ ta.setRangeText(evt.payload.text, ta.selectionStart, ta.selectionEnd, "end");
17789
+ args.applyChange(ta.value);
17790
+ });
17791
+ useEventListener(`UI:${args.events.onSetMode}`, (evt) => {
17792
+ if (!args.editorId || !isSetModePayload(evt.payload) || evt.payload.editorId !== args.editorId) return;
17793
+ setCaretMode(evt.payload.caret);
17794
+ });
17795
+ return { caretMode };
17796
+ }
17797
+ var init_useEditorCapabilities = __esm({
17798
+ "components/core/molecules/markdown/useEditorCapabilities.ts"() {
17799
+ "use client";
17800
+ init_useEventBus();
17801
+ init_editorMotions();
17802
+ }
17803
+ });
17079
17804
  function isLanguageRegistered(lang) {
17080
17805
  return CODE_LANGUAGE_SET.has(lang) || dynamicallyLoaded.has(lang);
17081
17806
  }
@@ -17161,7 +17886,36 @@ function useLanguageReady(language) {
17161
17886
  }, [language]);
17162
17887
  return ready;
17163
17888
  }
17164
- var dynamicallyLoaded, codeLanguageLoader, orbStyleOverrides, orbStyle, loloStyleOverrides, loloStyle, log6, CODE_LANGUAGES, CODE_LANGUAGE_SET, DIFF_STYLES, DIFF_STYLE_FALLBACK, LINE_PROPS_FN, HIDDEN_LINE_NUMBERS, CodeBlock;
17889
+ function resolveHighlightStyle(lang) {
17890
+ if (lang === "orb") return orbStyle;
17891
+ if (lang === "lolo") return loloStyle;
17892
+ return dark;
17893
+ }
17894
+ function plainCodeColorOf(style) {
17895
+ return style['code[class*="language-"]']?.color ?? "#d4d4d4";
17896
+ }
17897
+ function buildLineProps(errorLines, extraClassName) {
17898
+ return (lineNumber) => {
17899
+ const base = {
17900
+ "data-line": String(lineNumber - 1),
17901
+ ...extraClassName ? { className: extraClassName } : {}
17902
+ };
17903
+ const severity = errorLines?.get(lineNumber);
17904
+ if (!severity) return base;
17905
+ return {
17906
+ ...base,
17907
+ style: {
17908
+ display: "block",
17909
+ backgroundColor: severity === "error" ? "rgba(248, 113, 113, 0.18)" : "rgba(251, 191, 36, 0.18)",
17910
+ // amber-400 @ 18%
17911
+ borderLeft: `3px solid ${severity === "error" ? "#ef4444" : "#f59e0b"}`,
17912
+ paddingLeft: "0.5rem",
17913
+ marginLeft: "-0.5rem"
17914
+ }
17915
+ };
17916
+ };
17917
+ }
17918
+ var dynamicallyLoaded, codeLanguageLoader, orbStyleOverrides, orbStyle, loloStyleOverrides, loloStyle, log6, CODE_LANGUAGES, CODE_LANGUAGE_SET, DIFF_STYLES, DIFF_STYLE_FALLBACK, LINE_PROPS_FN, HIDDEN_LINE_NUMBERS, HIGHLIGHT_CAPACITY_BYTES, MONO_FONT_FAMILY, VIEWER_LINE_NUMBER_STYLE, CodeBlock;
17165
17919
  var init_CodeBlock = __esm({
17166
17920
  "components/core/molecules/markdown/CodeBlock.tsx"() {
17167
17921
  init_cn();
@@ -17177,6 +17931,7 @@ var init_CodeBlock = __esm({
17177
17931
  init_Textarea();
17178
17932
  init_Icon();
17179
17933
  init_useEventBus();
17934
+ init_useEditorCapabilities();
17180
17935
  SyntaxHighlighter.registerLanguage("json", langJson);
17181
17936
  SyntaxHighlighter.registerLanguage("javascript", langJavascript);
17182
17937
  SyntaxHighlighter.registerLanguage("js", langJavascript);
@@ -17394,7 +18149,17 @@ var init_CodeBlock = __esm({
17394
18149
  DIFF_STYLE_FALLBACK = { bg: "", prefix: " ", text: "text-foreground" };
17395
18150
  LINE_PROPS_FN = (n) => ({ "data-line": String(n - 1) });
17396
18151
  HIDDEN_LINE_NUMBERS = { display: "none" };
17397
- CodeBlock = React86__default.memo(
18152
+ HIGHLIGHT_CAPACITY_BYTES = 512 * 1024;
18153
+ MONO_FONT_FAMILY = 'ui-monospace, SFMono-Regular, Menlo, Monaco, "Cascadia Mono", "Courier New", monospace';
18154
+ VIEWER_LINE_NUMBER_STYLE = {
18155
+ minWidth: "2.5em",
18156
+ paddingRight: "1rem",
18157
+ textAlign: "right",
18158
+ userSelect: "none",
18159
+ opacity: 0.5,
18160
+ fontVariantNumeric: "tabular-nums"
18161
+ };
18162
+ CodeBlock = React87__default.memo(
17398
18163
  ({
17399
18164
  code: rawCode,
17400
18165
  language = "text",
@@ -17418,13 +18183,39 @@ var init_CodeBlock = __esm({
17418
18183
  actions,
17419
18184
  isLoading = false,
17420
18185
  error,
17421
- showCopy
18186
+ showCopy,
18187
+ // editor capability surface — P1 wires these
18188
+ editorId,
18189
+ onEditorFocus = "EDITOR_FOCUS",
18190
+ onEditorBlur = "EDITOR_BLUR",
18191
+ onMotion = "MOTION",
18192
+ onOperate = "OPERATE",
18193
+ onInsertText = "INSERT_TEXT",
18194
+ onSetMode = "SET_MODE",
18195
+ motions = [
18196
+ "left",
18197
+ "right",
18198
+ "up",
18199
+ "down",
18200
+ "word-forward",
18201
+ "word-back",
18202
+ "word-end",
18203
+ "line-start",
18204
+ "line-end",
18205
+ "first-nonblank",
18206
+ "doc-start",
18207
+ "doc-end",
18208
+ "paragraph-forward",
18209
+ "paragraph-back",
18210
+ "line",
18211
+ "selection"
18212
+ ],
18213
+ operators = ["delete", "yank", "change"]
17422
18214
  }) => {
17423
18215
  const code = typeof rawCode === "string" ? rawCode : String(rawCode ?? "");
17424
- const isOrb = language === "orb";
17425
- const isLolo = language === "lolo";
17426
- const activeStyle = isOrb ? orbStyle : isLolo ? loloStyle : dark;
17427
- const languageReady = useLanguageReady(language);
18216
+ const activeStyle = resolveHighlightStyle(language);
18217
+ const overCapacity = code.length > HIGHLIGHT_CAPACITY_BYTES;
18218
+ const plainCodeColor = plainCodeColorOf(activeStyle);
17428
18219
  const eventBus = useEventBus();
17429
18220
  const { t } = useTranslate();
17430
18221
  const scrollRef = useRef(null);
@@ -17436,6 +18227,9 @@ var init_CodeBlock = __esm({
17436
18227
  const activeFile = files?.[activeFileIndex];
17437
18228
  const activeCode = activeFile?.code ?? code;
17438
18229
  const activeLanguage = activeFile?.language ?? language;
18230
+ const languageReady = useLanguageReady(activeLanguage);
18231
+ const viewerStyle = resolveHighlightStyle(activeLanguage);
18232
+ const viewerPlainCodeColor = plainCodeColorOf(viewerStyle);
17439
18233
  const diffLines = useMemo(() => {
17440
18234
  if (propDiff) return propDiff;
17441
18235
  if (mode === "diff" && oldValue !== void 0 && newValue !== void 0) {
@@ -17465,33 +18259,33 @@ var init_CodeBlock = __esm({
17465
18259
  ov.scrollLeft = ta.scrollLeft;
17466
18260
  }
17467
18261
  }, []);
17468
- const errorLineProps = useMemo(() => {
17469
- if (!errorLines || errorLines.size === 0) {
17470
- return LINE_PROPS_FN;
17471
- }
17472
- return (lineNumber) => {
17473
- const severity = errorLines.get(lineNumber);
17474
- if (!severity) {
17475
- return { "data-line": String(lineNumber - 1) };
17476
- }
17477
- return {
17478
- "data-line": String(lineNumber - 1),
17479
- style: {
17480
- display: "block",
17481
- backgroundColor: severity === "error" ? "rgba(248, 113, 113, 0.18)" : "rgba(251, 191, 36, 0.18)",
17482
- // amber-400 @ 18%
17483
- borderLeft: `3px solid ${severity === "error" ? "#ef4444" : "#f59e0b"}`,
17484
- paddingLeft: "0.5rem",
17485
- marginLeft: "-0.5rem"
17486
- }
17487
- };
17488
- };
17489
- }, [errorLines]);
18262
+ const handleEditableChange = useCallback((v) => {
18263
+ lastPropCodeRef.current = v;
18264
+ setEditableValue(v);
18265
+ onChange?.(v);
18266
+ }, [onChange]);
18267
+ const { caretMode } = useEditorCapabilities({
18268
+ editorId: editable ? editorId : void 0,
18269
+ textareaRef: editableTextareaRef,
18270
+ events: { onMotion, onOperate, onInsertText, onSetMode },
18271
+ applyChange: handleEditableChange
18272
+ });
18273
+ const [caretIndex, setCaretIndex] = useState(0);
18274
+ const caretRowCol = useMemo(() => {
18275
+ const before = editableValue.slice(0, Math.min(caretIndex, editableValue.length));
18276
+ const lines = before.split("\n");
18277
+ return { row: lines.length - 1, col: lines[lines.length - 1].length };
18278
+ }, [editableValue, caretIndex]);
18279
+ const errorLineProps = useMemo(() => buildLineProps(errorLines), [errorLines]);
18280
+ const viewerLineProps = useMemo(
18281
+ () => buildLineProps(errorLines, "px-4 py-0.5 hover:bg-muted/50"),
18282
+ [errorLines]
18283
+ );
17490
18284
  const isFoldable = foldableProp ?? true;
17491
18285
  const [collapsed, setCollapsed] = useState(() => /* @__PURE__ */ new Set());
17492
18286
  const foldRegions = useMemo(
17493
- () => isFoldable ? computeFoldRegions(code) : [],
17494
- [code, isFoldable]
18287
+ () => isFoldable && !overCapacity ? computeFoldRegions(code) : [],
18288
+ [code, isFoldable, overCapacity]
17495
18289
  );
17496
18290
  const foldStartMap = useMemo(() => {
17497
18291
  const m = /* @__PURE__ */ new Map();
@@ -17525,8 +18319,67 @@ var init_CodeBlock = __esm({
17525
18319
  useEffect(() => {
17526
18320
  setCollapsed(/* @__PURE__ */ new Set());
17527
18321
  }, [code]);
18322
+ const editableOverCapacity = editableValue.length > HIGHLIGHT_CAPACITY_BYTES;
18323
+ const editableHighlightedElement = useMemo(
18324
+ () => editableOverCapacity ? /* @__PURE__ */ jsx(
18325
+ "div",
18326
+ {
18327
+ style: {
18328
+ padding: "1rem",
18329
+ margin: 0,
18330
+ whiteSpace: "pre",
18331
+ minWidth: "100%",
18332
+ color: plainCodeColor,
18333
+ fontFamily: 'ui-monospace, SFMono-Regular, Menlo, Monaco, "Cascadia Mono", "Courier New", monospace',
18334
+ fontSize: "13px",
18335
+ lineHeight: "1.5"
18336
+ },
18337
+ children: editableValue || " "
18338
+ }
18339
+ ) : /* @__PURE__ */ jsx(
18340
+ SyntaxHighlighter,
18341
+ {
18342
+ PreTag: "div",
18343
+ language,
18344
+ style: activeStyle,
18345
+ wrapLines: errorLines && errorLines.size > 0,
18346
+ lineProps: errorLineProps,
18347
+ customStyle: {
18348
+ backgroundColor: "transparent",
18349
+ borderRadius: 0,
18350
+ padding: "1rem",
18351
+ margin: 0,
18352
+ whiteSpace: "pre",
18353
+ minWidth: "100%",
18354
+ fontFamily: 'ui-monospace, SFMono-Regular, Menlo, Monaco, "Cascadia Mono", "Courier New", monospace',
18355
+ fontSize: "13px",
18356
+ lineHeight: "1.5"
18357
+ },
18358
+ codeTagProps: {
18359
+ style: {
18360
+ fontFamily: 'ui-monospace, SFMono-Regular, Menlo, Monaco, "Cascadia Mono", "Courier New", monospace',
18361
+ fontSize: "13px",
18362
+ lineHeight: "1.5"
18363
+ }
18364
+ },
18365
+ children: editableValue || " "
18366
+ }
18367
+ ),
18368
+ [editableValue, editableOverCapacity, plainCodeColor, language, activeStyle, errorLines, errorLineProps, languageReady]
18369
+ );
17528
18370
  const highlightedElement = useMemo(
17529
- () => /* @__PURE__ */ jsx(
18371
+ () => overCapacity ? /* @__PURE__ */ jsx(
18372
+ "div",
18373
+ {
18374
+ style: {
18375
+ margin: 0,
18376
+ whiteSpace: "pre",
18377
+ minWidth: "100%",
18378
+ color: plainCodeColor
18379
+ },
18380
+ children: code
18381
+ }
18382
+ ) : /* @__PURE__ */ jsx(
17530
18383
  SyntaxHighlighter,
17531
18384
  {
17532
18385
  PreTag: "div",
@@ -17548,8 +18401,112 @@ var init_CodeBlock = __esm({
17548
18401
  children: code
17549
18402
  }
17550
18403
  ),
17551
- [code, language, activeStyle, languageReady]
18404
+ [code, overCapacity, plainCodeColor, language, activeStyle, languageReady]
18405
+ );
18406
+ const viewerOverCapacity = activeCode.length > HIGHLIGHT_CAPACITY_BYTES;
18407
+ const viewerHighlightedElement = useMemo(
18408
+ () => viewerOverCapacity ? /* @__PURE__ */ jsx(
18409
+ "div",
18410
+ {
18411
+ className: "px-4 py-0.5",
18412
+ style: {
18413
+ margin: 0,
18414
+ whiteSpace: wrap ? "pre-wrap" : "pre",
18415
+ wordBreak: wrap ? "break-all" : "normal",
18416
+ color: viewerPlainCodeColor,
18417
+ fontFamily: MONO_FONT_FAMILY,
18418
+ fontSize: "12px",
18419
+ lineHeight: "1.6"
18420
+ },
18421
+ children: activeCode
18422
+ }
18423
+ ) : /* @__PURE__ */ jsx(
18424
+ SyntaxHighlighter,
18425
+ {
18426
+ PreTag: "div",
18427
+ language: activeLanguage,
18428
+ style: viewerStyle,
18429
+ wrapLines: true,
18430
+ wrapLongLines: wrap,
18431
+ showLineNumbers,
18432
+ lineNumberStyle: VIEWER_LINE_NUMBER_STYLE,
18433
+ lineProps: viewerLineProps,
18434
+ customStyle: {
18435
+ backgroundColor: "transparent",
18436
+ borderRadius: 0,
18437
+ padding: "0.25rem 0",
18438
+ margin: 0,
18439
+ whiteSpace: wrap ? "pre-wrap" : "pre",
18440
+ wordBreak: wrap ? "break-all" : "normal",
18441
+ fontFamily: MONO_FONT_FAMILY,
18442
+ fontSize: "12px",
18443
+ lineHeight: "1.6"
18444
+ },
18445
+ codeTagProps: { style: { fontFamily: MONO_FONT_FAMILY, fontSize: "12px", lineHeight: "1.6" } },
18446
+ children: activeCode
18447
+ }
18448
+ ),
18449
+ [activeCode, viewerOverCapacity, viewerPlainCodeColor, activeLanguage, viewerStyle, wrap, showLineNumbers, viewerLineProps, languageReady]
17552
18450
  );
18451
+ const diffOverCapacity = useMemo(
18452
+ () => !!diffLines && diffLines.reduce((n, l) => n + l.content.length + 1, 0) > HIGHLIGHT_CAPACITY_BYTES,
18453
+ [diffLines]
18454
+ );
18455
+ const diffRowElements = useMemo(() => {
18456
+ if (!diffLines) return null;
18457
+ return diffLines.map((line, idx) => {
18458
+ const style = DIFF_STYLES[line.type] ?? DIFF_STYLE_FALLBACK;
18459
+ return /* @__PURE__ */ jsxs(HStack, { gap: "none", align: "start", className: cn(style.bg, "px-4 py-0.5"), children: [
18460
+ showLineNumbers && /* @__PURE__ */ jsx(
18461
+ Typography,
18462
+ {
18463
+ variant: "caption",
18464
+ color: "secondary",
18465
+ className: "w-8 text-right mr-3 select-none tabular-nums flex-shrink-0",
18466
+ children: line.lineNumber ?? ""
18467
+ }
18468
+ ),
18469
+ /* @__PURE__ */ jsxs(
18470
+ Typography,
18471
+ {
18472
+ variant: "caption",
18473
+ className: cn("font-mono flex-1 min-w-0", style.text, wrap ? "whitespace-pre-wrap break-all" : "whitespace-pre"),
18474
+ children: [
18475
+ /* @__PURE__ */ jsx(Box, { as: "span", className: "select-none opacity-50 mr-2", children: style.prefix }),
18476
+ diffOverCapacity ? line.content || " " : /* @__PURE__ */ jsx(
18477
+ SyntaxHighlighter,
18478
+ {
18479
+ PreTag: "span",
18480
+ CodeTag: "span",
18481
+ language: activeLanguage,
18482
+ style: viewerStyle,
18483
+ customStyle: {
18484
+ display: "inline",
18485
+ background: "transparent",
18486
+ padding: 0,
18487
+ margin: 0,
18488
+ whiteSpace: wrap ? "pre-wrap" : "pre",
18489
+ wordBreak: wrap ? "break-all" : "normal",
18490
+ fontFamily: "inherit",
18491
+ fontSize: "inherit",
18492
+ lineHeight: "inherit"
18493
+ },
18494
+ codeTagProps: {
18495
+ style: {
18496
+ whiteSpace: wrap ? "pre-wrap" : "pre",
18497
+ fontFamily: "inherit",
18498
+ fontSize: "inherit"
18499
+ }
18500
+ },
18501
+ children: line.content || " "
18502
+ }
18503
+ )
18504
+ ]
18505
+ }
18506
+ )
18507
+ ] }, idx);
18508
+ });
18509
+ }, [diffLines, showLineNumbers, wrap, diffOverCapacity, activeLanguage, viewerStyle, languageReady]);
17553
18510
  useLayoutEffect(() => {
17554
18511
  const container = codeRef.current;
17555
18512
  if (!container) return;
@@ -17693,7 +18650,6 @@ var init_CodeBlock = __esm({
17693
18650
  label: file.label,
17694
18651
  content: null
17695
18652
  }));
17696
- const lines = activeCode.split("\n");
17697
18653
  return /* @__PURE__ */ jsx(Card, { className: cn("overflow-hidden", className), children: /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column" }, children: [
17698
18654
  tabItems && tabItems.length > 1 && /* @__PURE__ */ jsx(Box, { className: "border-b border-border", children: /* @__PURE__ */ jsx(
17699
18655
  Tabs,
@@ -17756,49 +18712,7 @@ var init_CodeBlock = __esm({
17756
18712
  ]
17757
18713
  }
17758
18714
  ),
17759
- /* @__PURE__ */ jsx(Box, { className: "overflow-auto bg-muted/20", style: { maxHeight }, children: diffLines ? /* @__PURE__ */ jsx("div", { style: { display: "flex", flexDirection: "column" }, className: "font-mono text-xs", children: diffLines.map((line, idx) => {
17760
- const style = DIFF_STYLES[line.type] ?? DIFF_STYLE_FALLBACK;
17761
- return /* @__PURE__ */ jsxs(HStack, { gap: "none", align: "start", className: cn(style.bg, "px-4 py-0.5"), children: [
17762
- showLineNumbers && /* @__PURE__ */ jsx(
17763
- Typography,
17764
- {
17765
- variant: "caption",
17766
- color: "secondary",
17767
- className: "w-8 text-right mr-3 select-none tabular-nums flex-shrink-0",
17768
- children: line.lineNumber ?? ""
17769
- }
17770
- ),
17771
- /* @__PURE__ */ jsxs(
17772
- Typography,
17773
- {
17774
- variant: "caption",
17775
- className: cn("font-mono flex-1 min-w-0", style.text, wrap ? "whitespace-pre-wrap break-all" : "whitespace-pre"),
17776
- children: [
17777
- /* @__PURE__ */ jsx(Box, { as: "span", className: "select-none opacity-50 mr-2", children: style.prefix }),
17778
- line.content
17779
- ]
17780
- }
17781
- )
17782
- ] }, idx);
17783
- }) }) : /* @__PURE__ */ jsx("div", { style: { display: "flex", flexDirection: "column" }, className: "font-mono text-xs", children: lines.map((line, idx) => /* @__PURE__ */ jsxs(HStack, { gap: "none", align: "start", className: "px-4 py-0.5 hover:bg-muted/50", children: [
17784
- showLineNumbers && /* @__PURE__ */ jsx(
17785
- Typography,
17786
- {
17787
- variant: "caption",
17788
- color: "secondary",
17789
- className: "w-8 text-right mr-4 select-none tabular-nums flex-shrink-0",
17790
- children: idx + 1
17791
- }
17792
- ),
17793
- /* @__PURE__ */ jsx(
17794
- Typography,
17795
- {
17796
- variant: "caption",
17797
- className: cn("font-mono flex-1 min-w-0", wrap ? "whitespace-pre-wrap break-all" : "whitespace-pre"),
17798
- children: line || " "
17799
- }
17800
- )
17801
- ] }, idx)) }) })
18715
+ /* @__PURE__ */ jsx(Box, { className: "overflow-auto bg-muted/20", style: { maxHeight }, children: diffLines ? /* @__PURE__ */ jsx("div", { style: { display: "flex", flexDirection: "column" }, className: "font-mono text-xs", children: diffRowElements }) : /* @__PURE__ */ jsx("div", { className: "font-mono text-xs", children: viewerHighlightedElement }) })
17802
18716
  ] }) });
17803
18717
  }
17804
18718
  const hasHeader = showLanguageBadge || effectiveCopy;
@@ -17877,35 +18791,7 @@ var init_CodeBlock = __esm({
17877
18791
  overflow: "hidden",
17878
18792
  pointerEvents: "none"
17879
18793
  },
17880
- children: /* @__PURE__ */ jsx(
17881
- SyntaxHighlighter,
17882
- {
17883
- PreTag: "div",
17884
- language,
17885
- style: activeStyle,
17886
- wrapLines: errorLines && errorLines.size > 0,
17887
- lineProps: errorLineProps,
17888
- customStyle: {
17889
- backgroundColor: "transparent",
17890
- borderRadius: 0,
17891
- padding: "1rem",
17892
- margin: 0,
17893
- whiteSpace: "pre",
17894
- minWidth: "100%",
17895
- fontFamily: 'ui-monospace, SFMono-Regular, Menlo, Monaco, "Cascadia Mono", "Courier New", monospace',
17896
- fontSize: "13px",
17897
- lineHeight: "1.5"
17898
- },
17899
- codeTagProps: {
17900
- style: {
17901
- fontFamily: 'ui-monospace, SFMono-Regular, Menlo, Monaco, "Cascadia Mono", "Courier New", monospace',
17902
- fontSize: "13px",
17903
- lineHeight: "1.5"
17904
- }
17905
- },
17906
- children: editableValue || " "
17907
- }
17908
- )
18794
+ children: editableHighlightedElement
17909
18795
  }
17910
18796
  ),
17911
18797
  /* @__PURE__ */ jsx(
@@ -17913,13 +18799,11 @@ var init_CodeBlock = __esm({
17913
18799
  {
17914
18800
  ref: editableTextareaRef,
17915
18801
  defaultValue: code,
17916
- onChange: (e) => {
17917
- const v = e.target.value;
17918
- lastPropCodeRef.current = v;
17919
- setEditableValue(v);
17920
- onChange?.(v);
17921
- },
18802
+ onChange: (e) => handleEditableChange(e.target.value),
17922
18803
  onScroll: handleEditableScroll,
18804
+ onSelect: (e) => setCaretIndex(e.currentTarget.selectionStart),
18805
+ onFocus: editorId ? () => eventBus.emit(`UI:${onEditorFocus}`, { editorId }) : void 0,
18806
+ onBlur: editorId ? () => eventBus.emit(`UI:${onEditorBlur}`, { editorId }) : void 0,
17923
18807
  spellCheck: false,
17924
18808
  style: {
17925
18809
  position: "absolute",
@@ -17934,7 +18818,7 @@ var init_CodeBlock = __esm({
17934
18818
  resize: "none",
17935
18819
  backgroundColor: "transparent",
17936
18820
  color: "transparent",
17937
- caretColor: "#e6e6e6",
18821
+ caretColor: caretMode === "block" ? "transparent" : "#e6e6e6",
17938
18822
  WebkitTextFillColor: "transparent",
17939
18823
  fontFamily: 'ui-monospace, SFMono-Regular, Menlo, Monaco, "Cascadia Mono", "Courier New", monospace',
17940
18824
  fontSize: "13px",
@@ -17945,6 +18829,22 @@ var init_CodeBlock = __esm({
17945
18829
  }
17946
18830
  },
17947
18831
  editableTextareaKey
18832
+ ),
18833
+ caretMode !== "bar" && /* @__PURE__ */ jsx(
18834
+ "span",
18835
+ {
18836
+ "aria-hidden": true,
18837
+ style: {
18838
+ position: "absolute",
18839
+ top: `calc(1rem + ${caretRowCol.row * 19.5}px)`,
18840
+ left: `calc(1rem + ${caretRowCol.col}ch)`,
18841
+ width: "1ch",
18842
+ height: caretMode === "block" ? "19.5px" : "2px",
18843
+ backgroundColor: caretMode === "block" ? "rgba(230, 230, 230, 0.5)" : void 0,
18844
+ borderBottom: caretMode === "underline" ? "2px solid #e6e6e6" : void 0,
18845
+ pointerEvents: "none"
18846
+ }
18847
+ }
17948
18848
  )
17949
18849
  ]
17950
18850
  }
@@ -17972,55 +18872,175 @@ var init_CodeBlock = __esm({
17972
18872
  )
17973
18873
  ] });
17974
18874
  },
17975
- (prev, next) => prev.language === next.language && prev.code === next.code && prev.showCopyButton === next.showCopyButton && prev.showCopy === next.showCopy && prev.maxHeight === next.maxHeight && prev.foldable === next.foldable && prev.editable === next.editable && prev.onChange === next.onChange && prev.errorLines === next.errorLines && prev.mode === next.mode && prev.title === next.title && prev.diff === next.diff && prev.files === next.files && prev.actions === next.actions && prev.isLoading === next.isLoading && prev.error === next.error
18875
+ (prev, next) => prev.language === next.language && prev.code === next.code && prev.showCopyButton === next.showCopyButton && prev.showCopy === next.showCopy && prev.maxHeight === next.maxHeight && prev.foldable === next.foldable && prev.editable === next.editable && prev.onChange === next.onChange && prev.errorLines === next.errorLines && prev.mode === next.mode && prev.title === next.title && prev.diff === next.diff && prev.files === next.files && prev.actions === next.actions && prev.isLoading === next.isLoading && prev.error === next.error && prev.editorId === next.editorId && prev.onEditorFocus === next.onEditorFocus && prev.onEditorBlur === next.onEditorBlur && prev.onMotion === next.onMotion && prev.onOperate === next.onOperate && prev.onInsertText === next.onInsertText && prev.onSetMode === next.onSetMode && prev.motions === next.motions && prev.operators === next.operators
17976
18876
  );
17977
18877
  CodeBlock.displayName = "CodeBlock";
17978
18878
  }
17979
18879
  });
18880
+
18881
+ // components/core/molecules/markdown/mermaidSource.ts
18882
+ function isQuoted(label) {
18883
+ const trimmed = label.trim();
18884
+ return trimmed.length === 0 || trimmed.startsWith('"') && trimmed.endsWith('"') && trimmed.length > 1;
18885
+ }
18886
+ function quote(label) {
18887
+ return `"${label.replace(/"/g, "#quot;")}"`;
18888
+ }
18889
+ function isIdentifierChar(ch) {
18890
+ return /[A-Za-z0-9_\-.]/.test(ch);
18891
+ }
18892
+ function declaredType(code) {
18893
+ for (const line of code.split("\n")) {
18894
+ const trimmed = line.trim();
18895
+ if (trimmed.length === 0 || trimmed.startsWith("%%")) continue;
18896
+ return trimmed;
18897
+ }
18898
+ return "";
18899
+ }
18900
+ function isFlowchart(code) {
18901
+ return FLOWCHART_DIRECTIVE.test(declaredType(code));
18902
+ }
18903
+ function quoteNodeLabels(code) {
18904
+ let out = "";
18905
+ let i = 0;
18906
+ while (i < code.length) {
18907
+ const shape = NODE_SHAPES.find(([open2]) => code.startsWith(open2, i));
18908
+ const precededByIdentifier = i > 0 && isIdentifierChar(code[i - 1] ?? "");
18909
+ if (shape === void 0 || !precededByIdentifier) {
18910
+ out += code[i];
18911
+ i += 1;
18912
+ continue;
18913
+ }
18914
+ const [open, close] = shape;
18915
+ const contentStart = i + open.length;
18916
+ const closeAt = code.indexOf(close, contentStart);
18917
+ const newlineAt = code.indexOf("\n", contentStart);
18918
+ if (closeAt === -1 || newlineAt !== -1 && newlineAt < closeAt) {
18919
+ out += code[i];
18920
+ i += 1;
18921
+ continue;
18922
+ }
18923
+ const label = code.slice(contentStart, closeAt);
18924
+ out += open + (isQuoted(label) ? label : quote(label)) + close;
18925
+ i = closeAt + close.length;
18926
+ }
18927
+ return out;
18928
+ }
18929
+ function quoteEdgeLabels(code) {
18930
+ return code.split("\n").map((line) => {
18931
+ let out = "";
18932
+ let rest = line;
18933
+ for (; ; ) {
18934
+ const open = rest.indexOf("|");
18935
+ if (open === -1) break;
18936
+ const close = rest.indexOf("|", open + 1);
18937
+ if (close === -1) break;
18938
+ const label = rest.slice(open + 1, close);
18939
+ out += rest.slice(0, open + 1) + (isQuoted(label) ? label : quote(label)) + "|";
18940
+ rest = rest.slice(close + 1);
18941
+ }
18942
+ return out + rest;
18943
+ }).join("\n");
18944
+ }
18945
+ function quoteSubgraphTitles(code) {
18946
+ return code.split("\n").map((line) => {
18947
+ const match = /^(\s*subgraph\s+)(.+?)(\s*)$/.exec(line);
18948
+ if (match === null) return line;
18949
+ const [, prefix, title, trailing] = match;
18950
+ if (title === void 0 || prefix === void 0) return line;
18951
+ if (isQuoted(title) || title.includes("[")) return line;
18952
+ return prefix + quote(title) + (trailing ?? "");
18953
+ }).join("\n");
18954
+ }
18955
+ function mermaidRepairCandidates(code) {
18956
+ if (!isFlowchart(code)) return [];
18957
+ const nodes = quoteNodeLabels(code);
18958
+ const nodesAndEdges = quoteEdgeLabels(nodes);
18959
+ const all = quoteSubgraphTitles(nodesAndEdges);
18960
+ const ordered2 = [nodes, nodesAndEdges, all];
18961
+ const seen = /* @__PURE__ */ new Set([code]);
18962
+ const candidates = [];
18963
+ for (const candidate of ordered2) {
18964
+ if (seen.has(candidate)) continue;
18965
+ seen.add(candidate);
18966
+ candidates.push(candidate);
18967
+ }
18968
+ return candidates;
18969
+ }
18970
+ var NODE_SHAPES, FLOWCHART_DIRECTIVE;
18971
+ var init_mermaidSource = __esm({
18972
+ "components/core/molecules/markdown/mermaidSource.ts"() {
18973
+ NODE_SHAPES = [
18974
+ ["[[", "]]"],
18975
+ ["[(", ")]"],
18976
+ ["([", "])"],
18977
+ ["((", "))"],
18978
+ ["{{", "}}"],
18979
+ ["[", "]"],
18980
+ ["(", ")"],
18981
+ ["{", "}"]
18982
+ ];
18983
+ FLOWCHART_DIRECTIVE = /^(?:graph|flowchart)\b/;
18984
+ }
18985
+ });
17980
18986
  function loadMermaid() {
17981
18987
  mermaidModule ?? (mermaidModule = import('mermaid').then((m) => m.default));
17982
18988
  return mermaidModule;
17983
18989
  }
17984
- var mermaidModule, MermaidDiagram;
18990
+ var log7, mermaidModule, MermaidDiagram;
17985
18991
  var init_MermaidDiagram = __esm({
17986
18992
  "components/core/molecules/markdown/MermaidDiagram.tsx"() {
17987
18993
  init_Box();
17988
18994
  init_Typography();
17989
18995
  init_CodeBlock();
18996
+ init_mermaidSource();
17990
18997
  init_cn();
18998
+ log7 = createLogger("almadar:ui:mermaid-diagram");
17991
18999
  mermaidModule = null;
17992
- MermaidDiagram = React86__default.memo(
19000
+ MermaidDiagram = React87__default.memo(
17993
19001
  ({ code, className }) => {
17994
19002
  const { resolvedMode } = useTheme();
19003
+ const { t } = useTranslate();
17995
19004
  const containerRef = useRef(null);
17996
- const [error, setError] = useState(null);
19005
+ const [unrenderable, setUnrenderable] = useState(false);
17997
19006
  const reactId = useId();
17998
19007
  useEffect(() => {
17999
19008
  let active = true;
18000
19009
  void (async () => {
18001
- try {
18002
- const mermaid = await loadMermaid();
18003
- mermaid.initialize({
18004
- startOnLoad: false,
18005
- securityLevel: "strict",
18006
- theme: resolvedMode === "dark" ? "dark" : "default"
18007
- });
18008
- const domId = `mermaid-${reactId.replace(/[^a-zA-Z0-9]/g, "")}`;
18009
- const { svg } = await mermaid.render(domId, code);
18010
- if (!active || !containerRef.current) return;
18011
- containerRef.current.innerHTML = svg;
18012
- setError(null);
18013
- } catch (err) {
18014
- if (active) setError(err instanceof Error ? err.message : String(err));
19010
+ const mermaid = await loadMermaid();
19011
+ mermaid.initialize({
19012
+ startOnLoad: false,
19013
+ securityLevel: "strict",
19014
+ theme: resolvedMode === "dark" ? "dark" : "default"
19015
+ });
19016
+ const domId = `mermaid-${reactId.replace(/[^a-zA-Z0-9]/g, "")}`;
19017
+ let firstError = null;
19018
+ for (const [index, source] of [code, ...mermaidRepairCandidates(code)].entries()) {
19019
+ try {
19020
+ const { svg } = await mermaid.render(domId, source);
19021
+ if (!active) return;
19022
+ const container = containerRef.current;
19023
+ if (container === null) return;
19024
+ container.innerHTML = svg;
19025
+ container.dataset.mermaidRepaired = String(index > 0);
19026
+ setUnrenderable(false);
19027
+ if (index > 0) log7.debug("mermaid:repaired", { candidate: index });
19028
+ return;
19029
+ } catch (err) {
19030
+ firstError ?? (firstError = err instanceof Error ? err : new Error(String(err)));
19031
+ }
18015
19032
  }
19033
+ if (!active) return;
19034
+ log7.warn("mermaid:unrenderable", { error: firstError?.message ?? "", code });
19035
+ setUnrenderable(true);
18016
19036
  })();
18017
19037
  return () => {
18018
19038
  active = false;
18019
19039
  };
18020
19040
  }, [code, resolvedMode, reactId]);
18021
19041
  return /* @__PURE__ */ jsxs(Box, { className: cn("not-prose my-4", className), children: [
18022
- error !== null && /* @__PURE__ */ jsxs(Box, { className: "space-y-2 mb-2", children: [
18023
- /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-error whitespace-pre-wrap", children: error }),
19042
+ unrenderable && /* @__PURE__ */ jsxs(Box, { className: "space-y-2 mb-2", "data-testid": "mermaid-unrenderable", children: [
19043
+ /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-muted-foreground", children: t("mermaid.unrenderable") }),
18024
19044
  /* @__PURE__ */ jsx(CodeBlock, { code, language: "mermaid" })
18025
19045
  ] }),
18026
19046
  /* @__PURE__ */ jsx(
@@ -18029,7 +19049,7 @@ var init_MermaidDiagram = __esm({
18029
19049
  ref: containerRef,
18030
19050
  "data-testid": "mermaid-diagram",
18031
19051
  className: "overflow-x-auto",
18032
- style: error !== null ? { display: "none" } : void 0
19052
+ style: unrenderable ? { display: "none" } : void 0
18033
19053
  }
18034
19054
  )
18035
19055
  ] });
@@ -18047,7 +19067,7 @@ var init_MarkdownContent = __esm({
18047
19067
  init_CodeBlock();
18048
19068
  init_MermaidDiagram();
18049
19069
  init_cn();
18050
- MarkdownContent = React86__default.memo(
19070
+ MarkdownContent = React87__default.memo(
18051
19071
  ({ content, direction = "ltr", className }) => {
18052
19072
  const { t: _t } = useTranslate();
18053
19073
  const safeContent = typeof content === "string" ? content : String(content ?? "");
@@ -19327,7 +20347,7 @@ var init_StateMachineView = __esm({
19327
20347
  style: { top: title ? 30 : 0 },
19328
20348
  children: [
19329
20349
  entity && /* @__PURE__ */ jsx(EntityBox, { entity, config }),
19330
- states.map((state) => renderStateNode ? /* @__PURE__ */ jsx(React86__default.Fragment, { children: renderStateNode(state, config) }, state.id) : /* @__PURE__ */ jsx(
20350
+ states.map((state) => renderStateNode ? /* @__PURE__ */ jsx(React87__default.Fragment, { children: renderStateNode(state, config) }, state.id) : /* @__PURE__ */ jsx(
19331
20351
  StateNode2,
19332
20352
  {
19333
20353
  state,
@@ -21384,14 +22404,14 @@ function useSafeEventBus2() {
21384
22404
  } };
21385
22405
  }
21386
22406
  }
21387
- var log7, lookStyles4, ButtonGroup;
22407
+ var log8, lookStyles4, ButtonGroup;
21388
22408
  var init_ButtonGroup = __esm({
21389
22409
  "components/core/molecules/ButtonGroup.tsx"() {
21390
22410
  "use client";
21391
22411
  init_cn();
21392
22412
  init_atoms();
21393
22413
  init_useEventBus();
21394
- log7 = createLogger("almadar:ui:button-group");
22414
+ log8 = createLogger("almadar:ui:button-group");
21395
22415
  lookStyles4 = {
21396
22416
  "right-aligned-buttons": "",
21397
22417
  "floating-bar": "fixed bottom-section left-1/2 -translate-x-1/2 shadow-elevation-toast bg-card p-card-sm rounded-container",
@@ -21472,7 +22492,7 @@ var init_ButtonGroup = __esm({
21472
22492
  {
21473
22493
  variant: "ghost",
21474
22494
  onClick: () => {
21475
- log7.debug("Filter clicked", { field: filter.field });
22495
+ log8.debug("Filter clicked", { field: filter.field });
21476
22496
  },
21477
22497
  children: filter.label
21478
22498
  },
@@ -24174,6 +25194,187 @@ var init_CodeRunnerPanel = __esm({
24174
25194
  CodeRunnerPanel.displayName = "CodeRunnerPanel";
24175
25195
  }
24176
25196
  });
25197
+ function matchesQuery(query, text) {
25198
+ if (!query) return true;
25199
+ let qi = 0;
25200
+ const q = query.toLowerCase();
25201
+ const t = text.toLowerCase();
25202
+ for (let ti = 0; ti < t.length && qi < q.length; ti++) {
25203
+ if (t[ti] === q[qi]) qi++;
25204
+ }
25205
+ return qi === q.length;
25206
+ }
25207
+ function commandMatches(command, query) {
25208
+ if (!query) return true;
25209
+ if (matchesQuery(query, command.label)) return true;
25210
+ return (command.keywords ?? []).some((keyword) => matchesQuery(query, keyword));
25211
+ }
25212
+ function dispatchCommandPaletteCommand(command, deps) {
25213
+ if (command.disabled) return;
25214
+ if (command.event) deps.emit(`UI:${command.event}`, { commandId: command.id });
25215
+ if (command.action) deps.emit(`UI:${command.action}`, command.actionPayload ?? {});
25216
+ deps.onSelect?.(command);
25217
+ }
25218
+ var UNGROUPED, CommandPalette;
25219
+ var init_CommandPalette = __esm({
25220
+ "components/core/molecules/CommandPalette.tsx"() {
25221
+ "use client";
25222
+ init_Box();
25223
+ init_Stack();
25224
+ init_Typography();
25225
+ init_Icon();
25226
+ init_Input();
25227
+ init_Badge();
25228
+ init_cn();
25229
+ init_useEventBus();
25230
+ init_Modal();
25231
+ UNGROUPED = /* @__PURE__ */ Symbol("command-palette-ungrouped");
25232
+ CommandPalette = ({
25233
+ open,
25234
+ onOpenChange,
25235
+ commands,
25236
+ onSelect,
25237
+ placeholder = "Type a command...",
25238
+ emptyLabel = "No matching commands",
25239
+ className
25240
+ }) => {
25241
+ const eventBus = useEventBus();
25242
+ const [query, setQuery] = useState("");
25243
+ const [highlightIndex, setHighlightIndex] = useState(0);
25244
+ const filtered = useMemo(
25245
+ () => commands.filter((command) => commandMatches(command, query)),
25246
+ [commands, query]
25247
+ );
25248
+ const groups = useMemo(() => {
25249
+ const order = [];
25250
+ const byGroup = /* @__PURE__ */ new Map();
25251
+ for (const command of filtered) {
25252
+ const key = command.group ?? UNGROUPED;
25253
+ if (!byGroup.has(key)) {
25254
+ byGroup.set(key, []);
25255
+ order.push(key);
25256
+ }
25257
+ byGroup.get(key).push(command);
25258
+ }
25259
+ return order.map((key) => ({ group: key === UNGROUPED ? void 0 : key, items: byGroup.get(key) }));
25260
+ }, [filtered]);
25261
+ const resetQuery = useCallback(() => {
25262
+ setQuery("");
25263
+ setHighlightIndex(0);
25264
+ }, []);
25265
+ const handleClose = useCallback(() => {
25266
+ resetQuery();
25267
+ onOpenChange(false);
25268
+ }, [onOpenChange, resetQuery]);
25269
+ const handleSelect = useCallback(
25270
+ (command) => {
25271
+ if (command.disabled) return;
25272
+ dispatchCommandPaletteCommand(command, { emit: eventBus.emit, onSelect });
25273
+ handleClose();
25274
+ },
25275
+ [eventBus, onSelect, handleClose]
25276
+ );
25277
+ const handleQueryChange = useCallback((e) => {
25278
+ setQuery(e.target.value);
25279
+ setHighlightIndex(0);
25280
+ }, []);
25281
+ const handleKeyDown = useCallback(
25282
+ (e) => {
25283
+ if (filtered.length === 0) return;
25284
+ if (e.key === "ArrowDown") {
25285
+ e.preventDefault();
25286
+ setHighlightIndex((prev) => prev < filtered.length - 1 ? prev + 1 : 0);
25287
+ } else if (e.key === "ArrowUp") {
25288
+ e.preventDefault();
25289
+ setHighlightIndex((prev) => prev > 0 ? prev - 1 : filtered.length - 1);
25290
+ } else if (e.key === "Enter") {
25291
+ e.preventDefault();
25292
+ const command = filtered[highlightIndex];
25293
+ if (command) handleSelect(command);
25294
+ }
25295
+ },
25296
+ [filtered, highlightIndex, handleSelect]
25297
+ );
25298
+ return /* @__PURE__ */ jsx(
25299
+ Modal,
25300
+ {
25301
+ isOpen: open,
25302
+ onClose: handleClose,
25303
+ onExited: resetQuery,
25304
+ showCloseButton: false,
25305
+ size: "md",
25306
+ className,
25307
+ children: /* @__PURE__ */ jsx(Box, { "data-testid": "command-palette", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
25308
+ /* @__PURE__ */ jsx(
25309
+ Input,
25310
+ {
25311
+ inputType: "search",
25312
+ placeholder,
25313
+ value: query,
25314
+ onChange: handleQueryChange,
25315
+ onKeyDown: handleKeyDown,
25316
+ leftIcon: "search",
25317
+ clearable: query.length > 0,
25318
+ onClear: resetQuery,
25319
+ autoFocus: true,
25320
+ "data-testid": "command-palette-input"
25321
+ }
25322
+ ),
25323
+ filtered.length === 0 ? /* @__PURE__ */ jsx(Box, { className: "px-2 py-6 text-center", "data-testid": "command-palette-empty", children: /* @__PURE__ */ jsx(Typography, { variant: "body", color: "muted", children: emptyLabel }) }) : /* @__PURE__ */ jsx(
25324
+ Box,
25325
+ {
25326
+ className: "max-h-80 overflow-y-auto",
25327
+ role: "listbox",
25328
+ "aria-label": placeholder,
25329
+ children: /* @__PURE__ */ jsx(VStack, { gap: "none", children: groups.map(({ group, items }) => /* @__PURE__ */ jsxs(Box, { children: [
25330
+ group ? /* @__PURE__ */ jsx(
25331
+ Typography,
25332
+ {
25333
+ variant: "caption",
25334
+ color: "muted",
25335
+ className: "px-3 pt-2 pb-1 block",
25336
+ children: group
25337
+ }
25338
+ ) : null,
25339
+ items.map((command) => {
25340
+ const index = filtered.indexOf(command);
25341
+ const isHighlighted = index === highlightIndex;
25342
+ return /* @__PURE__ */ jsxs(
25343
+ Box,
25344
+ {
25345
+ as: "button",
25346
+ role: "option",
25347
+ "aria-selected": isHighlighted,
25348
+ "aria-disabled": command.disabled || void 0,
25349
+ "data-testid": `command-palette-item-${command.id}`,
25350
+ onMouseEnter: () => !command.disabled && setHighlightIndex(index),
25351
+ onClick: () => handleSelect(command),
25352
+ className: cn(
25353
+ "w-full flex items-center gap-3 px-3 py-2 text-start rounded-sm",
25354
+ "text-sm transition-colors",
25355
+ "focus:outline-none",
25356
+ isHighlighted && "bg-muted",
25357
+ command.disabled && "opacity-50 cursor-not-allowed"
25358
+ ),
25359
+ children: [
25360
+ command.icon ? /* @__PURE__ */ jsx(Icon, { icon: command.icon, size: "sm", className: "flex-shrink-0" }) : null,
25361
+ /* @__PURE__ */ jsx(Typography, { variant: "small", className: "flex-1 truncate", children: command.label }),
25362
+ command.shortcut ? /* @__PURE__ */ jsx(Badge, { variant: "neutral", size: "sm", children: command.shortcut }) : null
25363
+ ]
25364
+ },
25365
+ command.id
25366
+ );
25367
+ })
25368
+ ] }, String(group ?? "__ungrouped__"))) })
25369
+ }
25370
+ )
25371
+ ] }) })
25372
+ }
25373
+ );
25374
+ };
25375
+ CommandPalette.displayName = "CommandPalette";
25376
+ }
25377
+ });
24177
25378
  function formatCount(count) {
24178
25379
  if (count >= 1e3) {
24179
25380
  return `${(count / 1e3).toFixed(1)}k`;
@@ -25435,7 +26636,7 @@ var init_Menu = __esm({
25435
26636
  "bottom-end": "bottom-start"
25436
26637
  };
25437
26638
  const effectivePosition = direction === "rtl" ? rtlMirror[position] ?? position : position;
25438
- const triggerElement = React86__default.isValidElement(trigger) ? React86__default.cloneElement(trigger, {
26639
+ const triggerElement = React87__default.isValidElement(trigger) ? React87__default.cloneElement(trigger, {
25439
26640
  ref: triggerRef,
25440
26641
  onClick: handleToggle
25441
26642
  }) : /* @__PURE__ */ jsx(
@@ -25538,14 +26739,14 @@ function useDataDnd(args) {
25538
26739
  const isZone = Boolean(dragGroup || accepts || sortable);
25539
26740
  const enabled = isZone || Boolean(dndRoot);
25540
26741
  const eventBus = useEventBus();
25541
- const parentRoot = React86__default.useContext(RootCtx);
26742
+ const parentRoot = React87__default.useContext(RootCtx);
25542
26743
  const isRoot = enabled && parentRoot === null;
25543
- const zoneId = React86__default.useId();
26744
+ const zoneId = React87__default.useId();
25544
26745
  const ownGroup = dragGroup ?? accepts ?? zoneId;
25545
- const [optimisticOrders, setOptimisticOrders] = React86__default.useState(() => /* @__PURE__ */ new Map());
25546
- const optimisticOrdersRef = React86__default.useRef(optimisticOrders);
26746
+ const [optimisticOrders, setOptimisticOrders] = React87__default.useState(() => /* @__PURE__ */ new Map());
26747
+ const optimisticOrdersRef = React87__default.useRef(optimisticOrders);
25547
26748
  optimisticOrdersRef.current = optimisticOrders;
25548
- const clearOptimisticOrder = React86__default.useCallback((group) => {
26749
+ const clearOptimisticOrder = React87__default.useCallback((group) => {
25549
26750
  setOptimisticOrders((prev) => {
25550
26751
  if (!prev.has(group)) return prev;
25551
26752
  const next = new Map(prev);
@@ -25570,7 +26771,7 @@ function useDataDnd(args) {
25570
26771
  const raw = it[dndItemIdField];
25571
26772
  return raw != null ? String(raw) : `__idx_${idx}`;
25572
26773
  }).join("|");
25573
- const itemIds = React86__default.useMemo(
26774
+ const itemIds = React87__default.useMemo(
25574
26775
  () => orderedItems.map((it, idx) => {
25575
26776
  const raw = it[dndItemIdField];
25576
26777
  return raw != null ? String(raw) : `__idx_${idx}`;
@@ -25581,7 +26782,7 @@ function useDataDnd(args) {
25581
26782
  const raw = it[dndItemIdField];
25582
26783
  return raw != null ? String(raw) : `__${idx}`;
25583
26784
  }).join("|");
25584
- React86__default.useEffect(() => {
26785
+ React87__default.useEffect(() => {
25585
26786
  const root = isRoot ? null : parentRoot;
25586
26787
  if (root) {
25587
26788
  root.clearOptimisticOrder(ownGroup);
@@ -25589,20 +26790,20 @@ function useDataDnd(args) {
25589
26790
  clearOptimisticOrder(ownGroup);
25590
26791
  }
25591
26792
  }, [itemsContentSig, ownGroup]);
25592
- const zonesRef = React86__default.useRef(/* @__PURE__ */ new Map());
25593
- const registerZone = React86__default.useCallback((zoneId2, meta2) => {
26793
+ const zonesRef = React87__default.useRef(/* @__PURE__ */ new Map());
26794
+ const registerZone = React87__default.useCallback((zoneId2, meta2) => {
25594
26795
  zonesRef.current.set(zoneId2, meta2);
25595
26796
  }, []);
25596
- const unregisterZone = React86__default.useCallback((zoneId2) => {
26797
+ const unregisterZone = React87__default.useCallback((zoneId2) => {
25597
26798
  zonesRef.current.delete(zoneId2);
25598
26799
  }, []);
25599
- const [activeDrag, setActiveDrag] = React86__default.useState(null);
25600
- const [overZoneGroup, setOverZoneGroup] = React86__default.useState(null);
25601
- const meta = React86__default.useMemo(
26800
+ const [activeDrag, setActiveDrag] = React87__default.useState(null);
26801
+ const [overZoneGroup, setOverZoneGroup] = React87__default.useState(null);
26802
+ const meta = React87__default.useMemo(
25602
26803
  () => ({ group: ownGroup, dropEvent, reorderEvent, positionEvent, itemIds, rawItems: items, idField: dndItemIdField }),
25603
26804
  [ownGroup, dropEvent, reorderEvent, positionEvent, itemIds, items, dndItemIdField]
25604
26805
  );
25605
- React86__default.useEffect(() => {
26806
+ React87__default.useEffect(() => {
25606
26807
  const target = isRoot ? null : parentRoot;
25607
26808
  if (!target) {
25608
26809
  zonesRef.current.set(zoneId, meta);
@@ -25621,7 +26822,7 @@ function useDataDnd(args) {
25621
26822
  }, [parentRoot, isRoot, zoneId, meta]);
25622
26823
  const sensors = useAlmadarDndSensors(true);
25623
26824
  const collisionDetection = almadarDndCollisionDetection;
25624
- const findZoneByItem = React86__default.useCallback(
26825
+ const findZoneByItem = React87__default.useCallback(
25625
26826
  (id) => {
25626
26827
  for (const z of zonesRef.current.values()) {
25627
26828
  if (z.itemIds.includes(id)) return z;
@@ -25630,7 +26831,7 @@ function useDataDnd(args) {
25630
26831
  },
25631
26832
  []
25632
26833
  );
25633
- React86__default.useCallback(
26834
+ React87__default.useCallback(
25634
26835
  (group) => {
25635
26836
  for (const z of zonesRef.current.values()) {
25636
26837
  if (z.group === group) return z;
@@ -25639,7 +26840,7 @@ function useDataDnd(args) {
25639
26840
  },
25640
26841
  []
25641
26842
  );
25642
- const handleDragEnd = React86__default.useCallback(
26843
+ const handleDragEnd = React87__default.useCallback(
25643
26844
  (event) => {
25644
26845
  const { active, over } = event;
25645
26846
  const activeIdStr = String(active.id);
@@ -25730,8 +26931,8 @@ function useDataDnd(args) {
25730
26931
  },
25731
26932
  [eventBus]
25732
26933
  );
25733
- const sortableData = React86__default.useMemo(() => ({ dndGroup: ownGroup }), [ownGroup]);
25734
- const SortableItem = React86__default.useCallback(
26934
+ const sortableData = React87__default.useMemo(() => ({ dndGroup: ownGroup }), [ownGroup]);
26935
+ const SortableItem = React87__default.useCallback(
25735
26936
  ({ id, children }) => {
25736
26937
  const {
25737
26938
  attributes,
@@ -25771,7 +26972,7 @@ function useDataDnd(args) {
25771
26972
  id: droppableId,
25772
26973
  data: sortableData
25773
26974
  });
25774
- const ctx = React86__default.useContext(RootCtx);
26975
+ const ctx = React87__default.useContext(RootCtx);
25775
26976
  const activeDrag2 = ctx?.activeDrag ?? null;
25776
26977
  const overZoneGroup2 = ctx?.overZoneGroup ?? null;
25777
26978
  const isThisZoneOver = overZoneGroup2 === ownGroup;
@@ -25786,7 +26987,7 @@ function useDataDnd(args) {
25786
26987
  showForeignPlaceholder,
25787
26988
  ctxAvailable: ctx != null
25788
26989
  });
25789
- React86__default.useEffect(() => {
26990
+ React87__default.useEffect(() => {
25790
26991
  dndLog.info("dropzone:isOver:change", { droppableId, group: ownGroup, isOver, isThisZoneOver, showForeignPlaceholder, activeDragSourceGroup: activeDrag2?.sourceGroup ?? null });
25791
26992
  }, [droppableId, isOver, isThisZoneOver, showForeignPlaceholder]);
25792
26993
  return /* @__PURE__ */ jsx(
@@ -25800,11 +27001,11 @@ function useDataDnd(args) {
25800
27001
  }
25801
27002
  );
25802
27003
  };
25803
- const rootContextValue = React86__default.useMemo(
27004
+ const rootContextValue = React87__default.useMemo(
25804
27005
  () => ({ registerZone, unregisterZone, activeDrag, overZoneGroup, optimisticOrders, clearOptimisticOrder }),
25805
27006
  [registerZone, unregisterZone, activeDrag, overZoneGroup, optimisticOrders, clearOptimisticOrder]
25806
27007
  );
25807
- const handleDragStart = React86__default.useCallback((event) => {
27008
+ const handleDragStart = React87__default.useCallback((event) => {
25808
27009
  const sourceZone = findZoneByItem(event.active.id);
25809
27010
  const rect = event.active.rect.current.initial;
25810
27011
  const height = rect?.height && rect.height > 0 ? rect.height : 64;
@@ -25823,7 +27024,7 @@ function useDataDnd(args) {
25823
27024
  isRoot
25824
27025
  });
25825
27026
  }, [findZoneByItem, isRoot, zoneId]);
25826
- const handleDragOver = React86__default.useCallback((event) => {
27027
+ const handleDragOver = React87__default.useCallback((event) => {
25827
27028
  const { active, over } = event;
25828
27029
  const overData = over?.data?.current;
25829
27030
  const overGroup = overData?.dndGroup ?? null;
@@ -25893,7 +27094,7 @@ function useDataDnd(args) {
25893
27094
  return next;
25894
27095
  });
25895
27096
  }, []);
25896
- const handleDragCancel = React86__default.useCallback((event) => {
27097
+ const handleDragCancel = React87__default.useCallback((event) => {
25897
27098
  setActiveDrag(null);
25898
27099
  setOverZoneGroup(null);
25899
27100
  dndLog.warn("dragCancel", {
@@ -25901,12 +27102,12 @@ function useDataDnd(args) {
25901
27102
  reason: "dnd-kit cancelled the drag (escape key, pointer interrupted, or external)"
25902
27103
  });
25903
27104
  }, []);
25904
- const handleDragEndWithCleanup = React86__default.useCallback((event) => {
27105
+ const handleDragEndWithCleanup = React87__default.useCallback((event) => {
25905
27106
  handleDragEnd(event);
25906
27107
  setActiveDrag(null);
25907
27108
  setOverZoneGroup(null);
25908
27109
  }, [handleDragEnd]);
25909
- const wrapContainer = React86__default.useCallback(
27110
+ const wrapContainer = React87__default.useCallback(
25910
27111
  (children) => {
25911
27112
  if (!enabled) return children;
25912
27113
  const strategy = layout === "grid" ? rectSortingStrategy : verticalListSortingStrategy;
@@ -25960,7 +27161,7 @@ var init_useDataDnd = __esm({
25960
27161
  init_useAlmadarDndCollision();
25961
27162
  init_Box();
25962
27163
  dndLog = createLogger("almadar:ui:dnd");
25963
- RootCtx = React86__default.createContext(null);
27164
+ RootCtx = React87__default.createContext(null);
25964
27165
  }
25965
27166
  });
25966
27167
  function renderIconInput(icon, props) {
@@ -26475,7 +27676,7 @@ function DataList({
26475
27676
  }) {
26476
27677
  const eventBus = useEventBus();
26477
27678
  const { t } = useTranslate();
26478
- const [visibleCount, setVisibleCount] = React86__default.useState(pageSize || Infinity);
27679
+ const [visibleCount, setVisibleCount] = React87__default.useState(pageSize || Infinity);
26479
27680
  const fieldDefs = fields ?? columns ?? [];
26480
27681
  const allDataRaw = Array.isArray(entity) ? entity : entity ? [entity] : [];
26481
27682
  const dnd = useDataDnd({
@@ -26491,14 +27692,14 @@ function DataList({
26491
27692
  dndRoot
26492
27693
  });
26493
27694
  const orderedData = dnd.orderedItems;
26494
- const allData = React86__default.useMemo(
27695
+ const allData = React87__default.useMemo(
26495
27696
  () => sortRows(orderedData, sortBy, sortDirection),
26496
27697
  [orderedData, sortBy, sortDirection]
26497
27698
  );
26498
27699
  const data = pageSize > 0 ? allData.slice(0, visibleCount) : allData;
26499
27700
  const hasMoreLocal = pageSize > 0 && visibleCount < allData.length;
26500
27701
  const hasRenderProp = typeof children === "function";
26501
- React86__default.useEffect(() => {
27702
+ React87__default.useEffect(() => {
26502
27703
  const renderItemTypeOf = typeof schemaRenderItem;
26503
27704
  const childrenTypeOf = typeof children;
26504
27705
  if (data.length > 0 && !hasRenderProp) {
@@ -26618,7 +27819,7 @@ function DataList({
26618
27819
  return v === void 0 || v === null || v === "" ? raw : String(v);
26619
27820
  };
26620
27821
  return /* @__PURE__ */ jsxs(VStack, { gap: "sm", className: cn("py-2", className), children: [
26621
- groups2.map((group, gi) => /* @__PURE__ */ jsxs(React86__default.Fragment, { children: [
27822
+ groups2.map((group, gi) => /* @__PURE__ */ jsxs(React87__default.Fragment, { children: [
26622
27823
  group.label && /* @__PURE__ */ jsx(Divider, { label: group.label, className: "my-2" }),
26623
27824
  group.items.map((itemData, index) => {
26624
27825
  const id = itemData.id || `${gi}-${index}`;
@@ -26834,7 +28035,7 @@ function DataList({
26834
28035
  className
26835
28036
  ),
26836
28037
  children: [
26837
- groups.map((group, gi) => /* @__PURE__ */ jsxs(React86__default.Fragment, { children: [
28038
+ groups.map((group, gi) => /* @__PURE__ */ jsxs(React87__default.Fragment, { children: [
26838
28039
  group.label && /* @__PURE__ */ jsx(Divider, { label: group.label, className: gi > 0 ? "mt-4" : "mt-0" }),
26839
28040
  group.items.map(
26840
28041
  (itemData, index) => renderItem(itemData, index, gi === groups.length - 1 && index === group.items.length - 1)
@@ -26921,7 +28122,7 @@ var init_FormSection = __esm({
26921
28122
  columns = 1,
26922
28123
  className
26923
28124
  }) => {
26924
- const [collapsed, setCollapsed] = React86__default.useState(defaultCollapsed);
28125
+ const [collapsed, setCollapsed] = React87__default.useState(defaultCollapsed);
26925
28126
  const { t } = useTranslate();
26926
28127
  const eventBus = useEventBus();
26927
28128
  const gridClass = {
@@ -26929,7 +28130,7 @@ var init_FormSection = __esm({
26929
28130
  2: "grid-cols-1 md:grid-cols-2",
26930
28131
  3: "grid-cols-1 md:grid-cols-2 lg:grid-cols-3"
26931
28132
  }[columns];
26932
- React86__default.useCallback(() => {
28133
+ React87__default.useCallback(() => {
26933
28134
  if (collapsible) {
26934
28135
  setCollapsed((prev) => !prev);
26935
28136
  eventBus.emit("UI:TOGGLE_COLLAPSE", { collapsed: !collapsed });
@@ -27483,10 +28684,10 @@ var init_FileTree = __esm({
27483
28684
  indent = 16
27484
28685
  }) => {
27485
28686
  const [overrides, setOverrides] = useState(() => /* @__PURE__ */ new Map());
27486
- const byId = React86__default.useMemo(() => new Map(items.map((node) => [node.id, node])), [items]);
27487
- const selectedAncestors = React86__default.useMemo(() => ancestorsOf(selectedId, byId), [selectedId, byId]);
27488
- const lastSelectedRef = React86__default.useRef(selectedId);
27489
- React86__default.useEffect(() => {
28687
+ const byId = React87__default.useMemo(() => new Map(items.map((node) => [node.id, node])), [items]);
28688
+ const selectedAncestors = React87__default.useMemo(() => ancestorsOf(selectedId, byId), [selectedId, byId]);
28689
+ const lastSelectedRef = React87__default.useRef(selectedId);
28690
+ React87__default.useEffect(() => {
27490
28691
  if (selectedId === lastSelectedRef.current) return;
27491
28692
  lastSelectedRef.current = selectedId;
27492
28693
  setOverrides((prev) => {
@@ -28256,7 +29457,7 @@ var init_Flex = __esm({
28256
29457
  flexStyle.flexBasis = typeof basis === "number" ? `${basis}px` : basis;
28257
29458
  }
28258
29459
  }
28259
- return React86__default.createElement(Component, {
29460
+ return React87__default.createElement(Component, {
28260
29461
  className: cn(
28261
29462
  inline ? "inline-flex" : "flex",
28262
29463
  directionStyles[direction],
@@ -28375,7 +29576,7 @@ var init_Grid = __esm({
28375
29576
  as: Component = "div"
28376
29577
  }) => {
28377
29578
  const mergedStyle = rows ? { gridTemplateRows: `repeat(${rows}, minmax(0, 1fr))`, ...style } : style;
28378
- return React86__default.createElement(
29579
+ return React87__default.createElement(
28379
29580
  Component,
28380
29581
  {
28381
29582
  className: cn(
@@ -28797,9 +29998,9 @@ var init_Popover = __esm({
28797
29998
  onMouseLeave: handleClose,
28798
29999
  onPointerDown: tapTriggerProps.onPointerDown
28799
30000
  };
28800
- const childElement = React86__default.isValidElement(children) ? children : /* @__PURE__ */ jsx("span", { children });
30001
+ const childElement = React87__default.isValidElement(children) ? children : /* @__PURE__ */ jsx("span", { children });
28801
30002
  const childPointerDown = childElement.props.onPointerDown;
28802
- const triggerElement = React86__default.cloneElement(
30003
+ const triggerElement = React87__default.cloneElement(
28803
30004
  childElement,
28804
30005
  {
28805
30006
  ref: triggerRef,
@@ -28863,9 +30064,9 @@ function debug(...args) {
28863
30064
  const [first, ...rest] = args;
28864
30065
  const message = typeof first === "string" ? first : "<debug>";
28865
30066
  if (rest.length === 0 && typeof first === "string") {
28866
- log8.debug(message);
30067
+ log9.debug(message);
28867
30068
  } else {
28868
- log8.debug(message, { args: rest.length > 0 ? formatArgs(rest) : formatArgs([first]) });
30069
+ log9.debug(message, { args: rest.length > 0 ? formatArgs(rest) : formatArgs([first]) });
28869
30070
  }
28870
30071
  }
28871
30072
  function debugGroup(label) {
@@ -28893,11 +30094,11 @@ function toLogMetaValue(v) {
28893
30094
  }
28894
30095
  return String(v);
28895
30096
  }
28896
- var NAMESPACE, log8;
30097
+ var NAMESPACE, log9;
28897
30098
  var init_debug = __esm({
28898
30099
  "lib/debug.ts"() {
28899
30100
  NAMESPACE = "almadar:ui:debug";
28900
- log8 = createLogger(NAMESPACE);
30101
+ log9 = createLogger(NAMESPACE);
28901
30102
  createLogger("almadar:ui:debug:input");
28902
30103
  createLogger("almadar:ui:debug:collision");
28903
30104
  createLogger("almadar:ui:debug:physics");
@@ -29413,9 +30614,9 @@ var init_Tooltip = __esm({
29413
30614
  if (hideTimeoutRef.current) clearTimeout(hideTimeoutRef.current);
29414
30615
  };
29415
30616
  }, []);
29416
- const triggerElement = React86__default.isValidElement(children) ? children : /* @__PURE__ */ jsx("span", { children });
30617
+ const triggerElement = React87__default.isValidElement(children) ? children : /* @__PURE__ */ jsx("span", { children });
29417
30618
  const childPointerDown = triggerElement.props.onPointerDown;
29418
- const trigger = React86__default.cloneElement(triggerElement, {
30619
+ const trigger = React87__default.cloneElement(triggerElement, {
29419
30620
  ref: triggerRef,
29420
30621
  onMouseEnter: handleMouseEnter,
29421
30622
  onMouseLeave: handleMouseLeave,
@@ -29505,7 +30706,7 @@ var init_WizardProgress = __esm({
29505
30706
  children: /* @__PURE__ */ jsx("div", { className: "flex items-center gap-2", children: normalizedSteps.map((step, index) => {
29506
30707
  const isActive = index === currentStep;
29507
30708
  const isCompleted = index < currentStep;
29508
- return /* @__PURE__ */ jsxs(React86__default.Fragment, { children: [
30709
+ return /* @__PURE__ */ jsxs(React87__default.Fragment, { children: [
29509
30710
  /* @__PURE__ */ jsx(
29510
30711
  "button",
29511
30712
  {
@@ -30550,6 +31751,7 @@ var init_MathCanvas = __esm({
30550
31751
  init_perf();
30551
31752
  init_atoms();
30552
31753
  init_Stack();
31754
+ init_gameFonts();
30553
31755
  init_LearningCanvas();
30554
31756
  MathCanvas = ({
30555
31757
  className,
@@ -30569,6 +31771,7 @@ var init_MathCanvas = __esm({
30569
31771
  showTickLabels = false,
30570
31772
  tickLabelFontSize = 10,
30571
31773
  labelFontSize = 12,
31774
+ fontFamily: fontFamilyProp,
30572
31775
  showCurveLabels = false,
30573
31776
  curves = [],
30574
31777
  points = [],
@@ -30591,6 +31794,7 @@ var init_MathCanvas = __esm({
30591
31794
  error
30592
31795
  }) => {
30593
31796
  const eventBus = useEventBus();
31797
+ const fontFamily = resolveGameFontFamily(fontFamilyProp);
30594
31798
  const keyMapKey = keyMap ? JSON.stringify(keyMap) : null;
30595
31799
  const keyUpMapKey = keyUpMap ? JSON.stringify(keyUpMap) : null;
30596
31800
  const stableKeyMap = useMemo(() => keyMap, [keyMapKey]);
@@ -30640,18 +31844,18 @@ var init_MathCanvas = __esm({
30640
31844
  let kx = 0;
30641
31845
  for (let x = Math.ceil(xMin / gridStep) * gridStep; x <= xMax; x += gridStep, kx++) {
30642
31846
  if (kx % labelEveryX === 0 && x !== 0) {
30643
- out.push({ type: "text", x: mapX(x), y: xAxisY + 12, text: formatTick(x), color: "#6b7280", fontSize: tickLabelFontSize, align: "center" });
31847
+ out.push({ type: "text", fontFamily, x: mapX(x), y: xAxisY + 12, text: formatTick(x), color: "#6b7280", fontSize: tickLabelFontSize, align: "center" });
30644
31848
  }
30645
31849
  }
30646
31850
  const labelEveryY = Math.max(1, Math.ceil((yMax - yMin) / gridStep / Math.floor(plotH / 28)));
30647
31851
  let ky = 0;
30648
31852
  for (let y = Math.ceil(yMin / gridStep) * gridStep; y <= yMax; y += gridStep, ky++) {
30649
31853
  if (ky % labelEveryY === 0 && y !== 0) {
30650
- out.push({ type: "text", x: yAxisX - 6, y: mapY(y), text: formatTick(y), color: "#6b7280", fontSize: tickLabelFontSize, align: "right" });
31854
+ out.push({ type: "text", fontFamily, x: yAxisX - 6, y: mapY(y), text: formatTick(y), color: "#6b7280", fontSize: tickLabelFontSize, align: "right" });
30651
31855
  }
30652
31856
  }
30653
31857
  if (xMin <= 0 && xMax >= 0 && yMin <= 0 && yMax >= 0) {
30654
- out.push({ type: "text", x: yAxisX - 6, y: xAxisY + 12, text: "0", color: "#6b7280", fontSize: tickLabelFontSize, align: "right" });
31858
+ out.push({ type: "text", fontFamily, x: yAxisX - 6, y: xAxisY + 12, text: "0", color: "#6b7280", fontSize: tickLabelFontSize, align: "right" });
30655
31859
  }
30656
31860
  }
30657
31861
  for (const region of regions) {
@@ -30678,6 +31882,7 @@ var init_MathCanvas = __esm({
30678
31882
  const mid = Math.floor(region.samples.length / 2);
30679
31883
  out.push({
30680
31884
  type: "text",
31885
+ fontFamily,
30681
31886
  x: mapX((first.x + last.x) / 2),
30682
31887
  y: (mapY(region.samples[mid].y) + mapY(baseline)) / 2,
30683
31888
  text: region.label,
@@ -30714,14 +31919,14 @@ var init_MathCanvas = __esm({
30714
31919
  const px = mapX(guide.at);
30715
31920
  out.push({ type: "line", x1: px, y1: margin, x2: px, y2: height - margin, color, dash });
30716
31921
  if (guide.label) {
30717
- out.push({ type: "text", x: px + 4, y: margin + 10, text: guide.label, color, fontSize: 11 });
31922
+ out.push({ type: "text", fontFamily, x: px + 4, y: margin + 10, text: guide.label, color, fontSize: 11 });
30718
31923
  }
30719
31924
  } else {
30720
31925
  if (guide.at < yMin || guide.at > yMax) continue;
30721
31926
  const py = mapY(guide.at);
30722
31927
  out.push({ type: "line", x1: margin, y1: py, x2: width - margin, y2: py, color, dash });
30723
31928
  if (guide.label) {
30724
- out.push({ type: "text", x: width - margin - 4, y: py - 8, text: guide.label, color, fontSize: labelFontSize, align: "right" });
31929
+ out.push({ type: "text", fontFamily, x: width - margin - 4, y: py - 8, text: guide.label, color, fontSize: labelFontSize, align: "right" });
30725
31930
  }
30726
31931
  }
30727
31932
  }
@@ -30760,6 +31965,7 @@ var init_MathCanvas = __esm({
30760
31965
  if (showCurveLabels && curve.label && lastInRange) {
30761
31966
  out.push({
30762
31967
  type: "text",
31968
+ fontFamily,
30763
31969
  x: mapX(lastInRange.x) + 6,
30764
31970
  y: mapY(lastInRange.y) - 6,
30765
31971
  text: curve.label,
@@ -30797,6 +32003,7 @@ var init_MathCanvas = __esm({
30797
32003
  if (hop.label) {
30798
32004
  out.push({
30799
32005
  type: "text",
32006
+ fontFamily,
30800
32007
  x: (x1 + x2) / 2,
30801
32008
  y: xAxisY - peak - 8,
30802
32009
  text: hop.label,
@@ -30824,6 +32031,7 @@ var init_MathCanvas = __esm({
30824
32031
  const rad = mid * Math.PI / 180;
30825
32032
  out.push({
30826
32033
  type: "text",
32034
+ fontFamily,
30827
32035
  x: mapX(angle.x + 1.35 * radius * Math.cos(rad)),
30828
32036
  y: mapY(angle.y + 1.35 * radius * Math.sin(rad)),
30829
32037
  text: angle.label,
@@ -30845,7 +32053,7 @@ var init_MathCanvas = __esm({
30845
32053
  fill: isOpen ? "#ffffff" : p.color ?? "#dc2626"
30846
32054
  });
30847
32055
  if (p.label) {
30848
- out.push({ type: "text", x: mapX(p.x) + 8, y: mapY(p.y) - 8, text: p.label, color: p.color ?? "#111827", fontSize: labelFontSize });
32056
+ out.push({ type: "text", fontFamily, x: mapX(p.x) + 8, y: mapY(p.y) - 8, text: p.label, color: p.color ?? "#111827", fontSize: labelFontSize });
30849
32057
  }
30850
32058
  }
30851
32059
  for (const v of vectors) {
@@ -30856,7 +32064,7 @@ var init_MathCanvas = __esm({
30856
32064
  const y2 = mapY(v.y + v.vy);
30857
32065
  out.push({ type: "arrow", x1, y1, x2, y2, color: v.color ?? "#7c3aed", lineWidth: 2 });
30858
32066
  if (v.label) {
30859
- out.push({ type: "text", x: x2 + 6, y: y2 - 6, text: v.label, color: v.color ?? "#7c3aed", fontSize: labelFontSize });
32067
+ out.push({ type: "text", fontFamily, x: x2 + 6, y: y2 - 6, text: v.label, color: v.color ?? "#7c3aed", fontSize: labelFontSize });
30860
32068
  }
30861
32069
  }
30862
32070
  out.push(...shapes);
@@ -30877,6 +32085,7 @@ var init_MathCanvas = __esm({
30877
32085
  showTickLabels,
30878
32086
  tickLabelFontSize,
30879
32087
  labelFontSize,
32088
+ fontFamily,
30880
32089
  showCurveLabels,
30881
32090
  curves,
30882
32091
  points,
@@ -30932,6 +32141,7 @@ var init_MathCanvas = __esm({
30932
32141
  width,
30933
32142
  height,
30934
32143
  backgroundColor,
32144
+ fontFamily,
30935
32145
  shapes: derivedShapes,
30936
32146
  drawables,
30937
32147
  projector,
@@ -32164,13 +33374,13 @@ var init_MapView = __esm({
32164
33374
  shadowSize: [41, 41]
32165
33375
  });
32166
33376
  L.Marker.prototype.options.icon = defaultIcon;
32167
- const { useEffect: useEffect64, useRef: useRef65, useCallback: useCallback92, useState: useState98 } = React86__default;
33377
+ const { useEffect: useEffect67, useRef: useRef69, useCallback: useCallback95, useState: useState102 } = React87__default;
32168
33378
  const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
32169
33379
  const { useEventBus: useEventBus2 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
32170
33380
  function MapUpdater({ centerLat, centerLng, zoom }) {
32171
33381
  const map = useMap();
32172
- const prevRef = useRef65({ centerLat, centerLng, zoom });
32173
- useEffect64(() => {
33382
+ const prevRef = useRef69({ centerLat, centerLng, zoom });
33383
+ useEffect67(() => {
32174
33384
  const prev = prevRef.current;
32175
33385
  if (prev.centerLat !== centerLat || prev.centerLng !== centerLng || prev.zoom !== zoom) {
32176
33386
  map.setView([centerLat, centerLng], zoom);
@@ -32181,7 +33391,7 @@ var init_MapView = __esm({
32181
33391
  }
32182
33392
  function MapClickHandler({ onMapClick }) {
32183
33393
  const map = useMap();
32184
- useEffect64(() => {
33394
+ useEffect67(() => {
32185
33395
  if (!onMapClick) return;
32186
33396
  const handler = (e) => {
32187
33397
  onMapClick(e.latlng.lat, e.latlng.lng);
@@ -32209,8 +33419,8 @@ var init_MapView = __esm({
32209
33419
  showAttribution = true
32210
33420
  }) {
32211
33421
  const eventBus = useEventBus2();
32212
- const [clickedPosition, setClickedPosition] = useState98(null);
32213
- const handleMapClick = useCallback92((lat, lng) => {
33422
+ const [clickedPosition, setClickedPosition] = useState102(null);
33423
+ const handleMapClick = useCallback95((lat, lng) => {
32214
33424
  if (showClickedPin) {
32215
33425
  setClickedPosition({ lat, lng });
32216
33426
  }
@@ -32219,7 +33429,7 @@ var init_MapView = __esm({
32219
33429
  eventBus.emit(`UI:${mapClickEvent}`, { latitude: lat, longitude: lng });
32220
33430
  }
32221
33431
  }, [onMapClick, mapClickEvent, eventBus, showClickedPin]);
32222
- const handleMarkerClick = useCallback92((marker) => {
33432
+ const handleMarkerClick = useCallback95((marker) => {
32223
33433
  onMarkerClick?.(marker);
32224
33434
  if (markerClickEvent) {
32225
33435
  eventBus.emit(`UI:${markerClickEvent}`, { ...marker });
@@ -33109,8 +34319,8 @@ function TableView({
33109
34319
  }) {
33110
34320
  const eventBus = useEventBus();
33111
34321
  const { t } = useTranslate();
33112
- const [visibleCount, setVisibleCount] = React86__default.useState(pageSize > 0 ? pageSize : Infinity);
33113
- const [localSelected, setLocalSelected] = React86__default.useState(/* @__PURE__ */ new Set());
34322
+ const [visibleCount, setVisibleCount] = React87__default.useState(pageSize > 0 ? pageSize : Infinity);
34323
+ const [localSelected, setLocalSelected] = React87__default.useState(/* @__PURE__ */ new Set());
33114
34324
  const colDefs = (Array.isArray(columns) ? columns : void 0) ?? (Array.isArray(fields) ? fields : void 0) ?? [];
33115
34325
  const actionDefs = Array.isArray(itemActions) ? itemActions : [];
33116
34326
  const allDataRaw = Array.isArray(entity) ? entity : entity ? [entity] : [];
@@ -33131,7 +34341,7 @@ function TableView({
33131
34341
  const hasMore = pageSize > 0 && visibleCount < ordered2.length;
33132
34342
  const hasRenderProp = typeof children === "function";
33133
34343
  const idField = dndItemIdField ?? "id";
33134
- React86__default.useEffect(() => {
34344
+ React87__default.useEffect(() => {
33135
34345
  tableViewLog.debug("render", {
33136
34346
  rowCount: data.length,
33137
34347
  colCount: colDefs.length,
@@ -33181,7 +34391,7 @@ function TableView({
33181
34391
  };
33182
34392
  eventBus.emit(`UI:${rowClickEvent}`, payload);
33183
34393
  };
33184
- const colFloors = React86__default.useMemo(
34394
+ const colFloors = React87__default.useMemo(
33185
34395
  () => colDefs.map((col) => {
33186
34396
  const longest = data.reduce((widest, row) => {
33187
34397
  const cell = formatCell(asFieldValue(getNestedValue(row, col.field ?? col.key)), col.format);
@@ -33324,12 +34534,12 @@ function TableView({
33324
34534
  ]
33325
34535
  }
33326
34536
  );
33327
- return dnd.isZone ? /* @__PURE__ */ jsx(dnd.SortableItem, { id: row[idField] ?? id, children: rowInner }, id) : /* @__PURE__ */ jsx(React86__default.Fragment, { children: rowInner }, id);
34537
+ return dnd.isZone ? /* @__PURE__ */ jsx(dnd.SortableItem, { id: row[idField] ?? id, children: rowInner }, id) : /* @__PURE__ */ jsx(React87__default.Fragment, { children: rowInner }, id);
33328
34538
  };
33329
34539
  const items = Array.from(data);
33330
34540
  const groups = groupBy ? groupData2(items, groupBy) : [{ label: "", items }];
33331
34541
  let runningIndex = 0;
33332
- const body = /* @__PURE__ */ jsx(Box, { role: "rowgroup", children: groups.map((group, gi) => /* @__PURE__ */ jsxs(React86__default.Fragment, { children: [
34542
+ const body = /* @__PURE__ */ jsx(Box, { role: "rowgroup", children: groups.map((group, gi) => /* @__PURE__ */ jsxs(React87__default.Fragment, { children: [
33333
34543
  group.label && /* @__PURE__ */ jsx(Divider, { label: group.label, className: gi > 0 ? "mt-3" : "mt-0" }),
33334
34544
  group.items.map((row) => renderRow(row, runningIndex++))
33335
34545
  ] }, gi)) });
@@ -34560,7 +35770,7 @@ var init_StepFlow = __esm({
34560
35770
  className
34561
35771
  }) => {
34562
35772
  if (orientation === "vertical") {
34563
- return /* @__PURE__ */ jsx(VStack, { gap: "none", className: cn("w-full", className), children: steps.map((step, index) => /* @__PURE__ */ jsx(React86__default.Fragment, { children: /* @__PURE__ */ jsxs(HStack, { gap: "md", align: "start", className: "w-full", children: [
35773
+ return /* @__PURE__ */ jsx(VStack, { gap: "none", className: cn("w-full", className), children: steps.map((step, index) => /* @__PURE__ */ jsx(React87__default.Fragment, { children: /* @__PURE__ */ jsxs(HStack, { gap: "md", align: "start", className: "w-full", children: [
34564
35774
  /* @__PURE__ */ jsxs(VStack, { gap: "none", align: "center", children: [
34565
35775
  /* @__PURE__ */ jsx(StepCircle, { step, index }),
34566
35776
  showConnectors && index < steps.length - 1 && /* @__PURE__ */ jsx(Box, { className: "w-px h-8 bg-border" })
@@ -34571,7 +35781,7 @@ var init_StepFlow = __esm({
34571
35781
  ] })
34572
35782
  ] }) }, index)) });
34573
35783
  }
34574
- 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(React86__default.Fragment, { children: [
35784
+ 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(React87__default.Fragment, { children: [
34575
35785
  /* @__PURE__ */ jsxs(VStack, { gap: "sm", align: "center", className: "flex-1 w-full md:w-auto", children: [
34576
35786
  /* @__PURE__ */ jsx(StepCircle, { step, index }),
34577
35787
  /* @__PURE__ */ jsx(Typography, { variant: "h4", className: "text-center", children: step.title }),
@@ -35561,7 +36771,7 @@ var init_LikertScale = __esm({
35561
36771
  md: "text-base",
35562
36772
  lg: "text-lg"
35563
36773
  };
35564
- LikertScale = React86__default.forwardRef(
36774
+ LikertScale = React87__default.forwardRef(
35565
36775
  ({
35566
36776
  question,
35567
36777
  options = DEFAULT_LIKERT_OPTIONS,
@@ -35573,7 +36783,7 @@ var init_LikertScale = __esm({
35573
36783
  variant = "radios",
35574
36784
  className
35575
36785
  }, ref) => {
35576
- const groupId = React86__default.useId();
36786
+ const groupId = React87__default.useId();
35577
36787
  const eventBus = useEventBus();
35578
36788
  const handleSelect = useCallback(
35579
36789
  (next) => {
@@ -37996,7 +39206,7 @@ var init_DocBreadcrumb = __esm({
37996
39206
  "aria-label": t("aria.breadcrumb"),
37997
39207
  children: /* @__PURE__ */ jsx(HStack, { gap: "xs", align: "center", wrap: true, children: items.map((item, idx) => {
37998
39208
  const isLast = idx === items.length - 1;
37999
- return /* @__PURE__ */ jsxs(React86__default.Fragment, { children: [
39209
+ return /* @__PURE__ */ jsxs(React87__default.Fragment, { children: [
38000
39210
  idx > 0 && /* @__PURE__ */ jsx(
38001
39211
  Icon,
38002
39212
  {
@@ -38865,7 +40075,7 @@ var init_MiniStateMachine = __esm({
38865
40075
  const x = 2 + i * (NODE_W + GAP + ARROW_W + GAP);
38866
40076
  const tc = transitionCounts[s.name] ?? 0;
38867
40077
  const role = getStateRole(s.name, s.isInitial ?? void 0, s.isTerminal ?? void 0, tc, maxTC);
38868
- return /* @__PURE__ */ jsxs(React86__default.Fragment, { children: [
40078
+ return /* @__PURE__ */ jsxs(React87__default.Fragment, { children: [
38869
40079
  /* @__PURE__ */ jsx(
38870
40080
  AvlState,
38871
40081
  {
@@ -39070,7 +40280,7 @@ var init_PageHeader = __esm({
39070
40280
  info: "bg-info/10 text-info"
39071
40281
  };
39072
40282
  return /* @__PURE__ */ jsxs(Box, { className: cn("mb-6", className), children: [
39073
- 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(React86__default.Fragment, { children: [
40283
+ 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(React87__default.Fragment, { children: [
39074
40284
  idx > 0 && /* @__PURE__ */ jsx(Typography, { variant: "small", color: "muted", children: "/" }),
39075
40285
  crumb.href ? /* @__PURE__ */ jsx(
39076
40286
  "a",
@@ -39428,7 +40638,7 @@ var init_Section = __esm({
39428
40638
  as: Component = "section"
39429
40639
  }) => {
39430
40640
  const hasHeader = title || description || action;
39431
- return React86__default.createElement(
40641
+ return React87__default.createElement(
39432
40642
  Component,
39433
40643
  {
39434
40644
  className: cn(
@@ -39802,7 +41012,7 @@ var init_WizardContainer = __esm({
39802
41012
  const isCompleted = index < currentStep;
39803
41013
  const stepKey = step.id ?? step.tabId ?? `step-${index}`;
39804
41014
  const stepTitle = step.title ?? step.name ?? `Step ${index + 1}`;
39805
- return /* @__PURE__ */ jsxs(React86__default.Fragment, { children: [
41015
+ return /* @__PURE__ */ jsxs(React87__default.Fragment, { children: [
39806
41016
  /* @__PURE__ */ jsx(
39807
41017
  Button,
39808
41018
  {
@@ -41589,7 +42799,7 @@ var init_ImportPreviewTree = __esm({
41589
42799
  const renderUnit = (unit, childrenByParent, depth) => {
41590
42800
  const summary = fieldSummary(unit);
41591
42801
  const children = childrenByParent.get(unit.ref) ?? [];
41592
- return /* @__PURE__ */ jsxs(React86__default.Fragment, { children: [
42802
+ return /* @__PURE__ */ jsxs(React87__default.Fragment, { children: [
41593
42803
  /* @__PURE__ */ jsxs(
41594
42804
  Box,
41595
42805
  {
@@ -41686,7 +42896,7 @@ var init_ImportProgress = __esm({
41686
42896
  PIPELINE.map((key, index) => {
41687
42897
  const isComplete = index < currentIndex;
41688
42898
  const isActive = index === currentIndex;
41689
- return /* @__PURE__ */ jsxs(React86__default.Fragment, { children: [
42899
+ return /* @__PURE__ */ jsxs(React87__default.Fragment, { children: [
41690
42900
  index > 0 ? /* @__PURE__ */ jsx(Box, { className: "h-px w-4 bg-border" }) : null,
41691
42901
  /* @__PURE__ */ jsxs(Box, { className: "flex items-center gap-1", "data-testid": `import-progress-step-${key}`, children: [
41692
42902
  /* @__PURE__ */ jsx(
@@ -42627,7 +43837,7 @@ var init_DetailPanel = __esm({
42627
43837
  }) => {
42628
43838
  const eventBus = useEventBus();
42629
43839
  const { t } = useTranslate();
42630
- const [titleDraft, setTitleDraft] = React86__default.useState(null);
43840
+ const [titleDraft, setTitleDraft] = React87__default.useState(null);
42631
43841
  const isFieldDefArray = (arr) => {
42632
43842
  if (!arr || arr.length === 0) return false;
42633
43843
  const first = arr[0];
@@ -43093,7 +44303,7 @@ var init_SplitPane = __esm({
43093
44303
  /* @__PURE__ */ jsx(
43094
44304
  "div",
43095
44305
  {
43096
- className: cn("overflow-auto", leftClassName),
44306
+ className: cn("flex flex-col overflow-auto", leftClassName),
43097
44307
  style: {
43098
44308
  [isHorizontal ? "width" : "height"]: `${ratio}%`,
43099
44309
  flexShrink: 0
@@ -43111,7 +44321,7 @@ var init_SplitPane = __esm({
43111
44321
  )
43112
44322
  }
43113
44323
  ),
43114
- /* @__PURE__ */ jsx("div", { className: cn("flex-1 overflow-auto", rightClassName), children: right })
44324
+ /* @__PURE__ */ jsx("div", { className: cn("flex flex-col flex-1 min-h-0 min-w-0 overflow-auto", rightClassName), children: right })
43115
44325
  ]
43116
44326
  }
43117
44327
  );
@@ -43157,7 +44367,7 @@ var init_DockLayout = __esm({
43157
44367
  const showBottomPanel = Boolean(bottomPanel) && !bottomPanelCollapsed;
43158
44368
  const showSecondarySidebar = Boolean(secondarySidebar) && !secondarySidebarCollapsed;
43159
44369
  const centerRow = /* @__PURE__ */ jsxs(HStack, { gap: "none", className: "flex-1 min-h-0 min-w-0", children: [
43160
- /* @__PURE__ */ jsx(Box, { className: cn("flex-1 min-w-0 h-full overflow-auto", mainClassName), children: main }),
44370
+ /* @__PURE__ */ jsx(Box, { className: cn("flex-1 min-w-0 min-h-0 overflow-auto", mainClassName), children: main }),
43161
44371
  showSecondarySidebar && /* @__PURE__ */ jsx(
43162
44372
  Box,
43163
44373
  {
@@ -43188,7 +44398,7 @@ var init_DockLayout = __esm({
43188
44398
  Box,
43189
44399
  {
43190
44400
  className: cn(
43191
- "flex-shrink-0 h-full overflow-auto border-r border-border",
44401
+ "flex-shrink-0 min-h-0 overflow-auto border-r border-border",
43192
44402
  railClassName
43193
44403
  ),
43194
44404
  style: { width: railWidth },
@@ -43237,7 +44447,7 @@ var init_DockLayout = __esm({
43237
44447
  }
43238
44448
  });
43239
44449
  function extractTitle(children) {
43240
- if (!React86__default.isValidElement(children)) return void 0;
44450
+ if (!React87__default.isValidElement(children)) return void 0;
43241
44451
  const props = children.props;
43242
44452
  if (typeof props.title === "string") {
43243
44453
  return props.title;
@@ -43599,7 +44809,7 @@ var init_Form = __esm({
43599
44809
  const isSchemaEntity = isOrbitalEntitySchema(entity);
43600
44810
  const resolvedEntity = isSchemaEntity ? entity : void 0;
43601
44811
  const entityName = typeof entity === "string" ? entity : resolvedEntity?.name;
43602
- const normalizedInitialData = React86__default.useMemo(() => {
44812
+ const normalizedInitialData = React87__default.useMemo(() => {
43603
44813
  const entityRowAsInitial = isPlainEntityRow(entity) ? entity : void 0;
43604
44814
  const callerInitial = initialData !== null && typeof initialData === "object" && !Array.isArray(initialData) ? initialData : {};
43605
44815
  const merged = entityRowAsInitial !== void 0 ? { ...entityRowAsInitial, ...callerInitial } : callerInitial;
@@ -43618,7 +44828,7 @@ var init_Form = __esm({
43618
44828
  }
43619
44829
  return normalized;
43620
44830
  }, [entity, initialData]);
43621
- const entityDerivedFields = React86__default.useMemo(() => {
44831
+ const entityDerivedFields = React87__default.useMemo(() => {
43622
44832
  if (fields && fields.length > 0) return void 0;
43623
44833
  if (!resolvedEntity) return void 0;
43624
44834
  return resolvedEntity.fields.map(
@@ -43639,16 +44849,16 @@ var init_Form = __esm({
43639
44849
  const conditionalFields = typeof conditionalFieldsRaw === "boolean" ? {} : conditionalFieldsRaw;
43640
44850
  const hiddenCalculations = typeof hiddenCalculationsRaw === "boolean" ? [] : hiddenCalculationsRaw;
43641
44851
  const violationTriggers = typeof violationTriggersRaw === "boolean" ? [] : violationTriggersRaw;
43642
- const [formData, setFormData] = React86__default.useState(
44852
+ const [formData, setFormData] = React87__default.useState(
43643
44853
  normalizedInitialData
43644
44854
  );
43645
- const [collapsedSections, setCollapsedSections] = React86__default.useState(
44855
+ const [collapsedSections, setCollapsedSections] = React87__default.useState(
43646
44856
  /* @__PURE__ */ new Set()
43647
44857
  );
43648
- const [submitError, setSubmitError] = React86__default.useState(null);
43649
- const formRef = React86__default.useRef(null);
44858
+ const [submitError, setSubmitError] = React87__default.useState(null);
44859
+ const formRef = React87__default.useRef(null);
43650
44860
  const formMode = props.mode;
43651
- const mountedRef = React86__default.useRef(false);
44861
+ const mountedRef = React87__default.useRef(false);
43652
44862
  if (!mountedRef.current) {
43653
44863
  mountedRef.current = true;
43654
44864
  debug("forms", "mount", {
@@ -43661,7 +44871,7 @@ var init_Form = __esm({
43661
44871
  });
43662
44872
  }
43663
44873
  const shouldShowCancel = showCancel ?? (fields && fields.length > 0);
43664
- const evalContext = React86__default.useMemo(
44874
+ const evalContext = React87__default.useMemo(
43665
44875
  () => ({
43666
44876
  formValues: formData,
43667
44877
  globalVariables: externalContext?.globalVariables ?? {},
@@ -43670,7 +44880,7 @@ var init_Form = __esm({
43670
44880
  }),
43671
44881
  [formData, externalContext]
43672
44882
  );
43673
- React86__default.useEffect(() => {
44883
+ React87__default.useEffect(() => {
43674
44884
  debug("forms", "initialData-sync", {
43675
44885
  mode: formMode,
43676
44886
  normalizedInitialData,
@@ -43681,7 +44891,7 @@ var init_Form = __esm({
43681
44891
  setFormData(normalizedInitialData);
43682
44892
  }
43683
44893
  }, [normalizedInitialData]);
43684
- const processCalculations = React86__default.useCallback(
44894
+ const processCalculations = React87__default.useCallback(
43685
44895
  (changedFieldId, newFormData) => {
43686
44896
  if (!hiddenCalculations.length) return;
43687
44897
  const context = {
@@ -43706,7 +44916,7 @@ var init_Form = __esm({
43706
44916
  },
43707
44917
  [hiddenCalculations, externalContext, eventBus]
43708
44918
  );
43709
- const checkViolations = React86__default.useCallback(
44919
+ const checkViolations = React87__default.useCallback(
43710
44920
  (changedFieldId, newFormData) => {
43711
44921
  if (!violationTriggers.length) return;
43712
44922
  const context = {
@@ -43744,7 +44954,7 @@ var init_Form = __esm({
43744
44954
  processCalculations(name, newFormData);
43745
44955
  checkViolations(name, newFormData);
43746
44956
  };
43747
- const isFieldVisible = React86__default.useCallback(
44957
+ const isFieldVisible = React87__default.useCallback(
43748
44958
  (fieldName2) => {
43749
44959
  const condition = conditionalFields[fieldName2];
43750
44960
  if (!condition) return true;
@@ -43752,7 +44962,7 @@ var init_Form = __esm({
43752
44962
  },
43753
44963
  [conditionalFields, evalContext]
43754
44964
  );
43755
- const isSectionVisible = React86__default.useCallback(
44965
+ const isSectionVisible = React87__default.useCallback(
43756
44966
  (section) => {
43757
44967
  if (!section.condition) return true;
43758
44968
  return Boolean(evaluateFormExpression(section.condition, evalContext));
@@ -43828,7 +45038,7 @@ var init_Form = __esm({
43828
45038
  eventBus.emit(`UI:${onCancel}`);
43829
45039
  }
43830
45040
  };
43831
- const renderField = React86__default.useCallback(
45041
+ const renderField = React87__default.useCallback(
43832
45042
  (field) => {
43833
45043
  const fieldName2 = field.name || field.field;
43834
45044
  if (!fieldName2) return null;
@@ -43850,7 +45060,7 @@ var init_Form = __esm({
43850
45060
  [formData, isFieldVisible, relationsData, relationsLoading, isLoading]
43851
45061
  );
43852
45062
  const effectiveFields = entityDerivedFields ?? fields;
43853
- const normalizedFields = React86__default.useMemo(() => {
45063
+ const normalizedFields = React87__default.useMemo(() => {
43854
45064
  if (!effectiveFields || effectiveFields.length === 0) return [];
43855
45065
  return effectiveFields.map((field) => {
43856
45066
  if (typeof field === "string") {
@@ -43885,7 +45095,7 @@ var init_Form = __esm({
43885
45095
  };
43886
45096
  });
43887
45097
  }, [effectiveFields, resolvedEntity, fieldOverrides]);
43888
- const schemaFields = React86__default.useMemo(() => {
45098
+ const schemaFields = React87__default.useMemo(() => {
43889
45099
  if (normalizedFields.length === 0) return null;
43890
45100
  if (isDebugEnabled()) {
43891
45101
  debugGroup(`Form: ${entityName || "unknown"}`);
@@ -43895,7 +45105,7 @@ var init_Form = __esm({
43895
45105
  }
43896
45106
  return normalizedFields.map(renderField).filter(Boolean);
43897
45107
  }, [normalizedFields, renderField, entityName, conditionalFields]);
43898
- const sectionElements = React86__default.useMemo(() => {
45108
+ const sectionElements = React87__default.useMemo(() => {
43899
45109
  if (!sections || sections.length === 0) return null;
43900
45110
  return sections.map((section) => {
43901
45111
  if (!isSectionVisible(section)) {
@@ -44731,7 +45941,7 @@ var init_List = __esm({
44731
45941
  if (entity && typeof entity === "object" && "id" in entity) return [entity];
44732
45942
  return [];
44733
45943
  }, [entity]);
44734
- const getItemActions = React86__default.useCallback(
45944
+ const getItemActions = React87__default.useCallback(
44735
45945
  (item) => {
44736
45946
  if (!itemActions) return [];
44737
45947
  if (typeof itemActions === "function") {
@@ -45213,7 +46423,7 @@ var init_MediaGallery = __esm({
45213
46423
  [selectable, selectedItems, selectionEvent, eventBus]
45214
46424
  );
45215
46425
  const entityData = Array.isArray(entity) ? entity : [];
45216
- const items = React86__default.useMemo(() => {
46426
+ const items = React87__default.useMemo(() => {
45217
46427
  if (propItems && propItems.length > 0) return propItems;
45218
46428
  if (entityData.length === 0) return [];
45219
46429
  return entityData.map((record, idx) => {
@@ -45378,7 +46588,7 @@ var init_MediaGallery = __esm({
45378
46588
  }
45379
46589
  });
45380
46590
  function extractTitle2(children) {
45381
- if (!React86__default.isValidElement(children)) return void 0;
46591
+ if (!React87__default.isValidElement(children)) return void 0;
45382
46592
  const props = children.props;
45383
46593
  if (typeof props.title === "string") {
45384
46594
  return props.title;
@@ -45652,7 +46862,7 @@ var init_debugRegistry = __esm({
45652
46862
  }
45653
46863
  });
45654
46864
  function useDebugData() {
45655
- const [data, setData] = React86.useState(() => ({
46865
+ const [data, setData] = React87.useState(() => ({
45656
46866
  traits: [],
45657
46867
  ticks: [],
45658
46868
  guards: [],
@@ -45666,7 +46876,7 @@ function useDebugData() {
45666
46876
  },
45667
46877
  lastUpdate: Date.now()
45668
46878
  }));
45669
- React86.useEffect(() => {
46879
+ React87.useEffect(() => {
45670
46880
  const updateData = () => {
45671
46881
  setData({
45672
46882
  traits: getAllTraits(),
@@ -45775,12 +46985,12 @@ function layoutGraph(states, transitions, initialState, width, height) {
45775
46985
  return positions;
45776
46986
  }
45777
46987
  function WalkMinimap() {
45778
- const [walkStep, setWalkStep] = React86.useState(null);
45779
- const [traits2, setTraits] = React86.useState([]);
45780
- const [coveredEdges, setCoveredEdges] = React86.useState([]);
45781
- const [completedTraits, setCompletedTraits] = React86.useState(/* @__PURE__ */ new Set());
45782
- const prevTraitRef = React86.useRef(null);
45783
- React86.useEffect(() => {
46988
+ const [walkStep, setWalkStep] = React87.useState(null);
46989
+ const [traits2, setTraits] = React87.useState([]);
46990
+ const [coveredEdges, setCoveredEdges] = React87.useState([]);
46991
+ const [completedTraits, setCompletedTraits] = React87.useState(/* @__PURE__ */ new Set());
46992
+ const prevTraitRef = React87.useRef(null);
46993
+ React87.useEffect(() => {
45784
46994
  const interval = setInterval(() => {
45785
46995
  const w = window;
45786
46996
  const step = w.__orbitalWalkStep;
@@ -46216,15 +47426,15 @@ var init_EntitiesTab = __esm({
46216
47426
  });
46217
47427
  function EventFlowTab({ events: events2 }) {
46218
47428
  const { t } = useTranslate();
46219
- const [filter, setFilter] = React86.useState("all");
46220
- const containerRef = React86.useRef(null);
46221
- const [autoScroll, setAutoScroll] = React86.useState(true);
46222
- React86.useEffect(() => {
47429
+ const [filter, setFilter] = React87.useState("all");
47430
+ const containerRef = React87.useRef(null);
47431
+ const [autoScroll, setAutoScroll] = React87.useState(true);
47432
+ React87.useEffect(() => {
46223
47433
  if (autoScroll && containerRef.current) {
46224
47434
  containerRef.current.scrollTop = containerRef.current.scrollHeight;
46225
47435
  }
46226
47436
  }, [events2.length, autoScroll]);
46227
- const filteredEvents = React86.useMemo(() => {
47437
+ const filteredEvents = React87.useMemo(() => {
46228
47438
  if (filter === "all") return events2;
46229
47439
  return events2.filter((e) => e.type === filter);
46230
47440
  }, [events2, filter]);
@@ -46340,7 +47550,7 @@ var init_EventFlowTab = __esm({
46340
47550
  });
46341
47551
  function GuardsPanel({ guards }) {
46342
47552
  const { t } = useTranslate();
46343
- const [filter, setFilter] = React86.useState("all");
47553
+ const [filter, setFilter] = React87.useState("all");
46344
47554
  if (guards.length === 0) {
46345
47555
  return /* @__PURE__ */ jsx(
46346
47556
  EmptyState,
@@ -46353,7 +47563,7 @@ function GuardsPanel({ guards }) {
46353
47563
  }
46354
47564
  const passedCount = guards.filter((g) => g.result).length;
46355
47565
  const failedCount = guards.length - passedCount;
46356
- const filteredGuards = React86.useMemo(() => {
47566
+ const filteredGuards = React87.useMemo(() => {
46357
47567
  if (filter === "all") return guards;
46358
47568
  if (filter === "passed") return guards.filter((g) => g.result);
46359
47569
  return guards.filter((g) => !g.result);
@@ -46516,10 +47726,10 @@ function EffectBadge({ effect }) {
46516
47726
  }
46517
47727
  function TransitionTimeline({ transitions }) {
46518
47728
  const { t } = useTranslate();
46519
- const containerRef = React86.useRef(null);
46520
- const [autoScroll, setAutoScroll] = React86.useState(true);
46521
- const [expandedId, setExpandedId] = React86.useState(null);
46522
- React86.useEffect(() => {
47729
+ const containerRef = React87.useRef(null);
47730
+ const [autoScroll, setAutoScroll] = React87.useState(true);
47731
+ const [expandedId, setExpandedId] = React87.useState(null);
47732
+ React87.useEffect(() => {
46523
47733
  if (autoScroll && containerRef.current) {
46524
47734
  containerRef.current.scrollTop = containerRef.current.scrollHeight;
46525
47735
  }
@@ -46799,9 +48009,9 @@ function getAllEvents(traits2) {
46799
48009
  function EventDispatcherTab({ traits: traits2, schema }) {
46800
48010
  const eventBus = useEventBus();
46801
48011
  const { t } = useTranslate();
46802
- const [log9, setLog] = React86.useState([]);
46803
- const prevStatesRef = React86.useRef(/* @__PURE__ */ new Map());
46804
- React86.useEffect(() => {
48012
+ const [log11, setLog] = React87.useState([]);
48013
+ const prevStatesRef = React87.useRef(/* @__PURE__ */ new Map());
48014
+ React87.useEffect(() => {
46805
48015
  for (const trait of traits2) {
46806
48016
  const prev = prevStatesRef.current.get(trait.id);
46807
48017
  if (prev && prev !== trait.currentState) {
@@ -46863,9 +48073,9 @@ function EventDispatcherTab({ traits: traits2, schema }) {
46863
48073
  /* @__PURE__ */ jsx(Typography, { variant: "small", weight: "medium", className: "text-muted-foreground mb-1", children: t("debug.otherEvents") }),
46864
48074
  /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-1", children: unavailableEvents.map((event) => /* @__PURE__ */ jsx(Badge, { variant: "default", size: "sm", className: "opacity-50", children: event }, event)) })
46865
48075
  ] }),
46866
- log9.length > 0 && /* @__PURE__ */ jsxs("div", { children: [
48076
+ log11.length > 0 && /* @__PURE__ */ jsxs("div", { children: [
46867
48077
  /* @__PURE__ */ jsx(Typography, { variant: "small", weight: "medium", className: "text-muted-foreground mb-1", children: t("debug.recentTransitions") }),
46868
- /* @__PURE__ */ jsx(Stack, { gap: "xs", children: log9.map((entry, i) => /* @__PURE__ */ jsxs(Typography, { variant: "small", className: "font-mono text-xs", children: [
48078
+ /* @__PURE__ */ jsx(Stack, { gap: "xs", children: log11.map((entry, i) => /* @__PURE__ */ jsxs(Typography, { variant: "small", className: "font-mono text-xs", children: [
46869
48079
  /* @__PURE__ */ jsx("span", { className: "text-primary", children: entry.traitName }),
46870
48080
  " ",
46871
48081
  /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: entry.from }),
@@ -46970,10 +48180,10 @@ function VerifyModePanel({
46970
48180
  localCount
46971
48181
  }) {
46972
48182
  const { t } = useTranslate();
46973
- const [expanded, setExpanded] = React86.useState(true);
46974
- const scrollRef = React86.useRef(null);
46975
- const prevCountRef = React86.useRef(0);
46976
- React86.useEffect(() => {
48183
+ const [expanded, setExpanded] = React87.useState(true);
48184
+ const scrollRef = React87.useRef(null);
48185
+ const prevCountRef = React87.useRef(0);
48186
+ React87.useEffect(() => {
46977
48187
  if (expanded && transitions.length > prevCountRef.current && scrollRef.current) {
46978
48188
  scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
46979
48189
  }
@@ -47030,10 +48240,10 @@ function RuntimeDebugger({
47030
48240
  schema
47031
48241
  }) {
47032
48242
  const { t } = useTranslate();
47033
- const [isCollapsed, setIsCollapsed] = React86.useState(mode === "verify" ? true : defaultCollapsed);
47034
- const [isVisible, setIsVisible] = React86.useState(mode === "inline" || mode === "verify" || isDebugEnabled2());
48243
+ const [isCollapsed, setIsCollapsed] = React87.useState(mode === "verify" ? true : defaultCollapsed);
48244
+ const [isVisible, setIsVisible] = React87.useState(mode === "inline" || mode === "verify" || isDebugEnabled2());
47035
48245
  const debugData = useDebugData();
47036
- React86.useEffect(() => {
48246
+ React87.useEffect(() => {
47037
48247
  if (mode === "inline") return;
47038
48248
  return onDebugToggle((enabled) => {
47039
48249
  setIsVisible(enabled);
@@ -47042,7 +48252,7 @@ function RuntimeDebugger({
47042
48252
  }
47043
48253
  });
47044
48254
  }, [mode]);
47045
- React86.useEffect(() => {
48255
+ React87.useEffect(() => {
47046
48256
  if (mode === "inline") return;
47047
48257
  const handleKeyDown = (e) => {
47048
48258
  if (e.key === "`" && isVisible) {
@@ -47473,7 +48683,7 @@ var init_StatCard = __esm({
47473
48683
  const labelToUse = propLabel ?? propTitle;
47474
48684
  const eventBus = useEventBus();
47475
48685
  const { t } = useTranslate();
47476
- const handleActionClick = React86__default.useCallback(() => {
48686
+ const handleActionClick = React87__default.useCallback(() => {
47477
48687
  if (action?.event) {
47478
48688
  eventBus.emit(`UI:${action.event}`, {});
47479
48689
  }
@@ -47484,7 +48694,7 @@ var init_StatCard = __esm({
47484
48694
  const data = Array.isArray(entity) ? entity : entity ? [entity] : [];
47485
48695
  const isLoading = externalLoading ?? false;
47486
48696
  const error = externalError;
47487
- const computeMetricValue = React86__default.useCallback(
48697
+ const computeMetricValue = React87__default.useCallback(
47488
48698
  (metric, items) => {
47489
48699
  if (metric.value !== void 0) {
47490
48700
  return metric.value;
@@ -47523,7 +48733,7 @@ var init_StatCard = __esm({
47523
48733
  },
47524
48734
  []
47525
48735
  );
47526
- const schemaStats = React86__default.useMemo(() => {
48736
+ const schemaStats = React87__default.useMemo(() => {
47527
48737
  if (!metrics || metrics.length === 0) return null;
47528
48738
  return metrics.map((metric) => ({
47529
48739
  label: metric.label,
@@ -47531,7 +48741,7 @@ var init_StatCard = __esm({
47531
48741
  format: metric.format
47532
48742
  }));
47533
48743
  }, [metrics, data, computeMetricValue]);
47534
- const calculatedTrend = React86__default.useMemo(() => {
48744
+ const calculatedTrend = React87__default.useMemo(() => {
47535
48745
  if (manualTrend !== void 0) return manualTrend;
47536
48746
  if (previousValue === void 0 || currentValue === void 0)
47537
48747
  return void 0;
@@ -48171,8 +49381,8 @@ var init_SubagentTracePanel = __esm({
48171
49381
  ] });
48172
49382
  };
48173
49383
  InlineActivityStream = ({ activities, autoScroll = true, className }) => {
48174
- const endRef = React86__default.useRef(null);
48175
- React86__default.useEffect(() => {
49384
+ const endRef = React87__default.useRef(null);
49385
+ React87__default.useEffect(() => {
48176
49386
  if (!autoScroll) return;
48177
49387
  endRef.current?.scrollIntoView({ behavior: "smooth", block: "end" });
48178
49388
  }, [activities.length, autoScroll]);
@@ -48266,7 +49476,7 @@ var init_SubagentTracePanel = __esm({
48266
49476
  };
48267
49477
  SubagentRichCard = ({ subagent }) => {
48268
49478
  const { t } = useTranslate();
48269
- const activities = React86__default.useMemo(
49479
+ const activities = React87__default.useMemo(
48270
49480
  () => subagentMessagesToActivities(subagent.messages),
48271
49481
  [subagent.messages]
48272
49482
  );
@@ -48343,8 +49553,8 @@ var init_SubagentTracePanel = __esm({
48343
49553
  ] });
48344
49554
  };
48345
49555
  CoordinatorConversation = ({ messages, autoScroll = true, className }) => {
48346
- const endRef = React86__default.useRef(null);
48347
- React86__default.useEffect(() => {
49556
+ const endRef = React87__default.useRef(null);
49557
+ React87__default.useEffect(() => {
48348
49558
  if (!autoScroll) return;
48349
49559
  endRef.current?.scrollIntoView({ behavior: "smooth", block: "end" });
48350
49560
  }, [messages.length, autoScroll]);
@@ -48779,7 +49989,7 @@ var init_Timeline = __esm({
48779
49989
  }) => {
48780
49990
  const { t } = useTranslate();
48781
49991
  const entityData = entity ?? [];
48782
- const items = React86__default.useMemo(() => {
49992
+ const items = React87__default.useMemo(() => {
48783
49993
  if (propItems) return propItems;
48784
49994
  if (entityData.length === 0) return [];
48785
49995
  return entityData.map((record, idx) => {
@@ -48881,7 +50091,7 @@ var init_Timeline = __esm({
48881
50091
  }
48882
50092
  });
48883
50093
  function extractToastProps(children) {
48884
- if (!React86__default.isValidElement(children)) {
50094
+ if (!React87__default.isValidElement(children)) {
48885
50095
  if (typeof children === "string") {
48886
50096
  return { message: children };
48887
50097
  }
@@ -48923,7 +50133,7 @@ var init_ToastSlot = __esm({
48923
50133
  eventBus.emit(`${prefix}CLOSE`);
48924
50134
  };
48925
50135
  if (!isVisible) return null;
48926
- const isCustomContent = React86__default.isValidElement(children) && !message;
50136
+ const isCustomContent = React87__default.isValidElement(children) && !message;
48927
50137
  return /* @__PURE__ */ jsx(Box, { className: "fixed bottom-4 right-4 z-50", children: isCustomContent ? children : /* @__PURE__ */ jsx(
48928
50138
  Toast,
48929
50139
  {
@@ -48991,6 +50201,7 @@ var init_component_registry_generated = __esm({
48991
50201
  init_ChoiceButton();
48992
50202
  init_CodeBlock();
48993
50203
  init_CodeRunnerPanel();
50204
+ init_CommandPalette();
48994
50205
  init_CommunityLinks();
48995
50206
  init_ConditionalWrapper();
48996
50207
  init_ConfettiEffect();
@@ -49055,6 +50266,7 @@ var init_component_registry_generated = __esm({
49055
50266
  init_FormSection();
49056
50267
  init_FormSectionHeader();
49057
50268
  init_FxOverlay();
50269
+ init_GameAudioCue();
49058
50270
  init_GameAudioToggle();
49059
50271
  init_GameHud();
49060
50272
  init_GameIcon();
@@ -49265,6 +50477,7 @@ var init_component_registry_generated = __esm({
49265
50477
  "ChoiceButton": ChoiceButton,
49266
50478
  "CodeBlock": CodeBlock,
49267
50479
  "CodeRunnerPanel": CodeRunnerPanel,
50480
+ "CommandPalette": CommandPalette,
49268
50481
  "CommunityLinks": CommunityLinks,
49269
50482
  "ConditionalWrapper": ConditionalWrapper,
49270
50483
  "ConfettiEffect": ConfettiEffect,
@@ -49331,6 +50544,7 @@ var init_component_registry_generated = __esm({
49331
50544
  "FormLayout": FormLayout,
49332
50545
  "FormSectionHeader": FormSectionHeader,
49333
50546
  "FxOverlay": FxOverlay,
50547
+ "GameAudioCue": GameAudioCue,
49334
50548
  "GameAudioToggle": GameAudioToggle,
49335
50549
  "GameHud": GameHud,
49336
50550
  "GameIcon": GameIcon,
@@ -49513,7 +50727,7 @@ function SuspenseConfigProvider({
49513
50727
  config,
49514
50728
  children
49515
50729
  }) {
49516
- return React86__default.createElement(
50730
+ return React87__default.createElement(
49517
50731
  SuspenseConfigContext.Provider,
49518
50732
  { value: config },
49519
50733
  children
@@ -49561,7 +50775,7 @@ function enrichFormFields(fields, entityDef) {
49561
50775
  }
49562
50776
  return { name: field, label: humanizeFieldName(field) };
49563
50777
  }
49564
- if (field && typeof field === "object" && !Array.isArray(field) && !React86__default.isValidElement(field) && !(field instanceof Date)) {
50778
+ if (field && typeof field === "object" && !Array.isArray(field) && !React87__default.isValidElement(field) && !(field instanceof Date)) {
49565
50779
  const obj = field;
49566
50780
  const fieldName2 = typeof obj.name === "string" ? obj.name : typeof obj.field === "string" ? obj.field : void 0;
49567
50781
  if (!fieldName2) return field;
@@ -49614,7 +50828,7 @@ function enrichDetailFields(fields, entityDef) {
49614
50828
  const meta = metaFor(field);
49615
50829
  return meta ? { key: field, ...meta } : field;
49616
50830
  }
49617
- if (field && typeof field === "object" && !Array.isArray(field) && !React86__default.isValidElement(field) && !(field instanceof Date)) {
50831
+ if (field && typeof field === "object" && !Array.isArray(field) && !React87__default.isValidElement(field) && !(field instanceof Date)) {
49618
50832
  const obj = field;
49619
50833
  const fieldName2 = typeof obj.key === "string" ? obj.key : typeof obj.name === "string" ? obj.name : void 0;
49620
50834
  if (!fieldName2 || obj.type) return field;
@@ -50073,7 +51287,7 @@ function renderPatternChildren(children, onDismiss, parentId = "root", parentPat
50073
51287
  const key = `${parentId}-${index}-trait:${traitName}`;
50074
51288
  return /* @__PURE__ */ jsx(TraitFrame, { traitName }, key);
50075
51289
  }
50076
- return /* @__PURE__ */ jsx(React86__default.Fragment, { children: child }, `${parentId}-${index}`);
51290
+ return /* @__PURE__ */ jsx(React87__default.Fragment, { children: child }, `${parentId}-${index}`);
50077
51291
  }
50078
51292
  if (!child || typeof child !== "object") return null;
50079
51293
  const childId = `${parentId}-${index}`;
@@ -50130,7 +51344,7 @@ function isPatternConfig(value) {
50130
51344
  if (value === null || value === void 0) return false;
50131
51345
  if (typeof value !== "object") return false;
50132
51346
  if (Array.isArray(value)) return false;
50133
- if (React86__default.isValidElement(value)) return false;
51347
+ if (React87__default.isValidElement(value)) return false;
50134
51348
  if (value instanceof Date) return false;
50135
51349
  if (typeof value === "function") return false;
50136
51350
  const record = value;
@@ -50143,9 +51357,9 @@ function renderPatternValue(value) {
50143
51357
  if (typeof value === "string") return renderPatternChildren(value, () => {
50144
51358
  });
50145
51359
  if (value instanceof Date) return value.toLocaleString();
50146
- if (React86__default.isValidElement(value)) return value;
51360
+ if (React87__default.isValidElement(value)) return value;
50147
51361
  if (Array.isArray(value)) {
50148
- return value.map((item, index) => /* @__PURE__ */ jsx(React86__default.Fragment, { children: renderPatternValue(item) }, index));
51362
+ return value.map((item, index) => /* @__PURE__ */ jsx(React87__default.Fragment, { children: renderPatternValue(item) }, index));
50149
51363
  }
50150
51364
  if (isPatternConfig(value)) {
50151
51365
  const { type, ...props } = value;
@@ -50155,7 +51369,7 @@ function renderPatternValue(value) {
50155
51369
  return null;
50156
51370
  }
50157
51371
  function isPlainConfigObject(value) {
50158
- if (React86__default.isValidElement(value)) return false;
51372
+ if (React87__default.isValidElement(value)) return false;
50159
51373
  if (value instanceof Date) return false;
50160
51374
  const proto = Object.getPrototypeOf(value);
50161
51375
  return proto === Object.prototype || proto === null;
@@ -50329,7 +51543,7 @@ function SlotContentRenderer({
50329
51543
  for (const slotKey of CONTENT_NODE_SLOTS) {
50330
51544
  const slotVal = restProps[slotKey];
50331
51545
  if (slotVal === void 0 || slotVal === null) continue;
50332
- if (React86__default.isValidElement(slotVal) || typeof slotVal === "string" || typeof slotVal === "number" || typeof slotVal === "boolean") continue;
51546
+ if (React87__default.isValidElement(slotVal) || typeof slotVal === "string" || typeof slotVal === "number" || typeof slotVal === "boolean") continue;
50333
51547
  const typelessChildren = !Array.isArray(slotVal) && typeof slotVal === "object" && !("type" in slotVal) && Array.isArray(slotVal.children) ? slotVal.children : void 0;
50334
51548
  if (typelessChildren !== void 0 || Array.isArray(slotVal) || typeof slotVal === "object" && "type" in slotVal) {
50335
51549
  nodeSlotOverrides[slotKey] = renderPatternChildren(
@@ -50383,7 +51597,7 @@ function SlotContentRenderer({
50383
51597
  const resolvedItems = Array.isArray(entityVal) && entityVal[0] !== "fn" ? entityVal : null;
50384
51598
  if (resolvedItems && resolvedItems.length > 0 && !finalProps.fields && !finalProps.columns) {
50385
51599
  const sample = resolvedItems[0];
50386
- if (sample && typeof sample === "object" && !Array.isArray(sample) && !React86__default.isValidElement(sample) && !(sample instanceof Date)) {
51600
+ if (sample && typeof sample === "object" && !Array.isArray(sample) && !React87__default.isValidElement(sample) && !(sample instanceof Date)) {
50387
51601
  const keys = Object.keys(sample).filter((k) => k !== "id" && k !== "_id");
50388
51602
  finalProps.fields = keys.map((k, i) => ({ name: k, variant: i === 0 ? "h4" : "body" }));
50389
51603
  }
@@ -50776,7 +51990,7 @@ function resolveLambdaBindings(body, params, item, index) {
50776
51990
  }
50777
51991
  return substituted;
50778
51992
  }
50779
- if (body !== null && typeof body === "object" && !React86__default.isValidElement(body) && !(body instanceof Date) && typeof body !== "function") {
51993
+ if (body !== null && typeof body === "object" && !React87__default.isValidElement(body) && !(body instanceof Date) && typeof body !== "function") {
50780
51994
  const out = {};
50781
51995
  for (const [k, v] of Object.entries(body)) {
50782
51996
  out[k] = recur(v);
@@ -50809,7 +52023,7 @@ function deferLambdaEntityExprs(value) {
50809
52023
  }
50810
52024
  return arr.map((v) => deferLambdaEntityExprs(v));
50811
52025
  }
50812
- if (value !== null && typeof value === "object" && !React86__default.isValidElement(value) && !(value instanceof Date) && typeof value !== "function" && !isRenderBindingMarker(value)) {
52026
+ if (value !== null && typeof value === "object" && !React87__default.isValidElement(value) && !(value instanceof Date) && typeof value !== "function" && !isRenderBindingMarker(value)) {
50813
52027
  const out = {};
50814
52028
  for (const [k, v] of Object.entries(value)) {
50815
52029
  out[k] = deferLambdaEntityExprs(v);
@@ -50823,7 +52037,7 @@ function makeLambdaFn(params, lambdaBody, callerKey) {
50823
52037
  const resolvedBody = deferLambdaEntityExprs(
50824
52038
  resolveLambdaBindings(lambdaBody, params, item, index)
50825
52039
  );
50826
- if (resolvedBody === null || typeof resolvedBody !== "object" || Array.isArray(resolvedBody) || typeof resolvedBody === "function" || React86__default.isValidElement(resolvedBody) || resolvedBody instanceof Date) {
52040
+ if (resolvedBody === null || typeof resolvedBody !== "object" || Array.isArray(resolvedBody) || typeof resolvedBody === "function" || React87__default.isValidElement(resolvedBody) || resolvedBody instanceof Date) {
50827
52041
  return null;
50828
52042
  }
50829
52043
  const record = resolvedBody;
@@ -50842,7 +52056,7 @@ function makeLambdaFn(params, lambdaBody, callerKey) {
50842
52056
  props: childProps,
50843
52057
  priority: 0
50844
52058
  };
50845
- return React86__default.createElement(SlotContentRenderer2, { content: childContent });
52059
+ return React87__default.createElement(SlotContentRenderer2, { content: childContent });
50846
52060
  };
50847
52061
  }
50848
52062
  function convertNode(node, callerKey) {
@@ -50862,7 +52076,7 @@ function convertNode(node, callerKey) {
50862
52076
  });
50863
52077
  return anyChanged ? mapped : node;
50864
52078
  }
50865
- if (typeof node === "object" && !React86__default.isValidElement(node) && !(node instanceof Date)) {
52079
+ if (typeof node === "object" && !React87__default.isValidElement(node) && !(node instanceof Date)) {
50866
52080
  return convertObjectProps(node);
50867
52081
  }
50868
52082
  return node;
@@ -51305,7 +52519,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
51305
52519
  };
51306
52520
  }, [traitBindings]);
51307
52521
  const executeTransitionEffects = useCallback(async (params) => {
51308
- const { binding, previousState, newState, payload, flushEvent, syncOnly, log: log9 } = params;
52522
+ const { binding, previousState, newState, payload, flushEvent, syncOnly, log: log11 } = params;
51309
52523
  const traitName = binding.trait.name;
51310
52524
  const linkedEntity = binding.linkedEntity || "";
51311
52525
  const entityId = payload?.entityId;
@@ -51434,7 +52648,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
51434
52648
  if (sharedKey !== void 0) {
51435
52649
  sharedWrites.push({ field, value });
51436
52650
  }
51437
- log9.debug("set:write", {
52651
+ log11.debug("set:write", {
51438
52652
  traitName,
51439
52653
  field,
51440
52654
  value: JSON.stringify(value),
@@ -51502,7 +52716,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
51502
52716
  mergeEntityFrame(sharedEntityStore.getSnapshot(sharedKey), sharedWrites)
51503
52717
  );
51504
52718
  }
51505
- log9.debug("effects:executed", () => ({
52719
+ log11.debug("effects:executed", () => ({
51506
52720
  traitName,
51507
52721
  transition: `${previousState}->${newState}`,
51508
52722
  event: flushEvent,
@@ -51512,7 +52726,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
51512
52726
  slotsTouched: Array.from(pendingSlots.keys()).join(",")
51513
52727
  }));
51514
52728
  for (const [slot, patterns] of pendingSlots) {
51515
- log9.debug("flush:slot", {
52729
+ log11.debug("flush:slot", {
51516
52730
  traitName,
51517
52731
  slot,
51518
52732
  patternCount: patterns.length,
@@ -51530,7 +52744,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
51530
52744
  publishBindingSnapshot(traitName, liveEntity);
51531
52745
  }
51532
52746
  } catch (error) {
51533
- log9.error("effects:error", {
52747
+ log11.error("effects:error", {
51534
52748
  traitName,
51535
52749
  transition: `${previousState}->${newState}`,
51536
52750
  event: flushEvent,
@@ -52712,11 +53926,20 @@ function BrowserPlayground({
52712
53926
  mode = "mock",
52713
53927
  initialPagePath,
52714
53928
  height,
52715
- className
53929
+ className,
53930
+ paused
52716
53931
  }) {
52717
53932
  const [runtime] = useState(
52718
53933
  () => new OrbitalServerRuntime({ mode, debug: false })
52719
53934
  );
53935
+ useEffect(() => {
53936
+ if (paused === void 0) return;
53937
+ if (paused) {
53938
+ runtime.pauseTicks();
53939
+ } else {
53940
+ runtime.resumeTicks();
53941
+ }
53942
+ }, [runtime, paused]);
52720
53943
  const registrationReady = useMemo(() => {
52721
53944
  const orbitalNames = schema.orbitals.map((o) => o.name);
52722
53945
  playgroundLog.debug("register:start", { schema: schema.name, orbitalNames });
@@ -52771,7 +53994,317 @@ function BrowserPlayground({
52771
53994
  );
52772
53995
  }
52773
53996
 
53997
+ // runtime/OrbitalPluginHost.tsx
53998
+ init_useEventBus();
53999
+ var log10 = createLogger("almadar:ui:plugin-host");
54000
+ var UI_SLOT_SET = new Set(UI_SLOTS);
54001
+ function isUISlot(value) {
54002
+ return UI_SLOT_SET.has(value);
54003
+ }
54004
+ var OrbitalPluginHostContext = createContext(null);
54005
+ function useOrbitalPluginHostContext(caller) {
54006
+ const ctx = useContext(OrbitalPluginHostContext);
54007
+ if (!ctx) {
54008
+ throw new Error(`${caller} must be used within an <OrbitalPluginHost>.`);
54009
+ }
54010
+ return ctx;
54011
+ }
54012
+ function isTraitState(value) {
54013
+ return value !== void 0 && typeof value.currentState === "string";
54014
+ }
54015
+ function toTraitState(runtime, orbital, trait, stateName, lastEvent) {
54016
+ if (runtime) {
54017
+ const raw = runtime.getState(orbital, trait);
54018
+ if (isTraitState(raw)) return raw;
54019
+ }
54020
+ return { traitName: trait, currentState: stateName, previousState: null, lastEvent, context: {} };
54021
+ }
54022
+ function isKeymapValue(value) {
54023
+ if (value === null || value === void 0 || typeof value !== "object" || Array.isArray(value)) return false;
54024
+ return Object.values(value).every((entry) => Array.isArray(entry) && entry.every((k) => typeof k === "string"));
54025
+ }
54026
+ function findInlineTrait(schema, orbitalName, traitName) {
54027
+ const orbital = schema.orbitals.find((o) => o.name === orbitalName);
54028
+ if (!orbital) return void 0;
54029
+ for (const ref of orbital.traits) {
54030
+ if (typeof ref === "string") continue;
54031
+ if ("ref" in ref) continue;
54032
+ if (ref.name === traitName) return ref;
54033
+ }
54034
+ return void 0;
54035
+ }
54036
+ function readKeymapConfig(trait, knob) {
54037
+ const declared = trait?.config?.[knob]?.default;
54038
+ return isKeymapValue(declared) ? declared : {};
54039
+ }
54040
+ function traitNamesOf(orbital) {
54041
+ const names = [];
54042
+ for (const ref of orbital.traits) {
54043
+ if (typeof ref === "string") {
54044
+ names.push(ref);
54045
+ } else if ("ref" in ref) {
54046
+ if (ref.name) names.push(ref.name);
54047
+ } else {
54048
+ names.push(ref.name);
54049
+ }
54050
+ }
54051
+ return names;
54052
+ }
54053
+ function useDeclaredCaptureTable(opts) {
54054
+ const { pluginId, orbital, trait, keymapKnob = "keymap", target = "shell" } = opts;
54055
+ const ctx = useOrbitalPluginHostContext("useDeclaredCaptureTable");
54056
+ return useMemo(() => {
54057
+ const schema = ctx.getPluginSchema(pluginId);
54058
+ const inlineTrait = schema ? findInlineTrait(schema, orbital, trait) : void 0;
54059
+ const keymap = readKeymapConfig(inlineTrait, keymapKnob);
54060
+ const currentState = ctx.getState(pluginId, orbital, trait)?.currentState;
54061
+ const keys = currentState !== void 0 ? keymap[currentState] ?? [] : [];
54062
+ return { [target]: { mode: currentState ?? "unknown", keys: new Set(keys) } };
54063
+ }, [ctx, pluginId, orbital, trait, keymapKnob, target]);
54064
+ }
54065
+ function useOrbitalPluginHost() {
54066
+ const ctx = useOrbitalPluginHostContext("useOrbitalPluginHost");
54067
+ return { getState: ctx.getState, lastEvent: ctx.lastEvent, errors: ctx.errors };
54068
+ }
54069
+ function buildMockEffectHandlers(opts) {
54070
+ const { pluginId, denySet, slotsRef, navigateRef, notifyRef } = opts;
54071
+ const handlers = {
54072
+ renderUI: (slot, pattern, props, priority) => {
54073
+ if (!isUISlot(slot)) {
54074
+ log10.warn("renderUI:unknown-slot", { pluginId, slot });
54075
+ return;
54076
+ }
54077
+ if (pattern === null) {
54078
+ slotsRef.current.clear(slot);
54079
+ return;
54080
+ }
54081
+ slotsRef.current.render({ target: slot, pattern: pattern.type, props, priority, sourceTrait: pluginId });
54082
+ }
54083
+ };
54084
+ if (denySet.has("navigate")) {
54085
+ handlers.navigate = (path) => log10.warn("navigate:denied", { pluginId, path });
54086
+ } else if (navigateRef.current) {
54087
+ handlers.navigate = (path) => navigateRef.current?.(path);
54088
+ }
54089
+ if (denySet.has("notify")) {
54090
+ handlers.notify = (message, type) => log10.warn("notify:denied", { pluginId, message, type });
54091
+ } else if (notifyRef.current) {
54092
+ handlers.notify = (message, type) => notifyRef.current?.(message, type);
54093
+ }
54094
+ if (denySet.has("persist")) {
54095
+ handlers.persist = async (action, entityType) => {
54096
+ log10.warn("persist:denied", { pluginId, action, entityType });
54097
+ return void 0;
54098
+ };
54099
+ }
54100
+ if (denySet.has("call-service")) {
54101
+ handlers.callService = async (service, action) => {
54102
+ log10.warn("call-service:denied", { pluginId, service, action });
54103
+ return null;
54104
+ };
54105
+ }
54106
+ return handlers;
54107
+ }
54108
+ function PluginRuntimeMount({
54109
+ plugin,
54110
+ mode,
54111
+ transport,
54112
+ deny,
54113
+ navigate,
54114
+ notify,
54115
+ onTransition,
54116
+ onDispatched,
54117
+ onError
54118
+ }) {
54119
+ const bus = useEventBus();
54120
+ const slots = useUISlots();
54121
+ const slotsRef = useRef(slots);
54122
+ slotsRef.current = slots;
54123
+ const navigateRef = useRef(navigate);
54124
+ navigateRef.current = navigate;
54125
+ const notifyRef = useRef(notify);
54126
+ notifyRef.current = notify;
54127
+ const [mockRuntime] = useState(() => {
54128
+ if (mode !== "mock") return void 0;
54129
+ return new OrbitalServerRuntime({
54130
+ mode: "mock",
54131
+ debug: false,
54132
+ effectHandlers: buildMockEffectHandlers({
54133
+ pluginId: plugin.id,
54134
+ denySet: new Set(deny ?? []),
54135
+ slotsRef,
54136
+ navigateRef,
54137
+ notifyRef
54138
+ })
54139
+ });
54140
+ });
54141
+ const registrationReady = useMemo(() => {
54142
+ if (mockRuntime) return mockRuntime.register(plugin.schema);
54143
+ if (mode === "server" && transport) return transport.register(plugin.schema);
54144
+ return Promise.resolve();
54145
+ }, [mockRuntime, transport, mode, plugin.schema]);
54146
+ useEffect(() => {
54147
+ if (mode === "server" && !transport) {
54148
+ onError(plugin.id, 'OrbitalPluginHost: mode "server" requires a transport');
54149
+ }
54150
+ }, [mode, transport, plugin.id, onError]);
54151
+ const teardownTimerRef = useRef(null);
54152
+ useEffect(() => {
54153
+ if (teardownTimerRef.current !== null) {
54154
+ clearTimeout(teardownTimerRef.current);
54155
+ teardownTimerRef.current = null;
54156
+ }
54157
+ return () => {
54158
+ teardownTimerRef.current = setTimeout(() => {
54159
+ teardownTimerRef.current = null;
54160
+ if (mockRuntime) {
54161
+ mockRuntime.unregisterAll();
54162
+ } else if (mode === "server" && transport) {
54163
+ void transport.unregister();
54164
+ }
54165
+ }, 0);
54166
+ };
54167
+ }, [mockRuntime, transport, mode]);
54168
+ const ownOrbitals = useMemo(
54169
+ () => new Set(plugin.schema.orbitals.map((o) => o.name)),
54170
+ [plugin.schema]
54171
+ );
54172
+ useEffect(() => {
54173
+ let cancelled = false;
54174
+ void registrationReady.then(() => {
54175
+ if (cancelled || !mockRuntime) return;
54176
+ const states = [];
54177
+ for (const orbital of plugin.schema.orbitals) {
54178
+ for (const traitName of traitNamesOf(orbital)) {
54179
+ const raw = mockRuntime.getState(orbital.name, traitName);
54180
+ if (isTraitState(raw)) states.push([orbital.name, traitName, raw]);
54181
+ }
54182
+ }
54183
+ if (states.length > 0) onDispatched(plugin.id, null, states);
54184
+ }).catch((err) => {
54185
+ if (!cancelled) onError(plugin.id, err instanceof Error ? err.message : String(err));
54186
+ });
54187
+ return () => {
54188
+ cancelled = true;
54189
+ };
54190
+ }, [registrationReady, mockRuntime, plugin, onDispatched, onError]);
54191
+ const dispatch = useCallback(
54192
+ async (row, payload) => {
54193
+ await registrationReady;
54194
+ let response;
54195
+ if (mockRuntime) {
54196
+ response = await mockRuntime.processOrbitalEvent(row.orbital, {
54197
+ event: row.trigger,
54198
+ payload,
54199
+ targetTrait: row.trait
54200
+ });
54201
+ } else if (mode === "server" && transport) {
54202
+ response = await transport.sendEvent(row.orbital, row.trigger, payload);
54203
+ } else {
54204
+ return;
54205
+ }
54206
+ if (!response.success) {
54207
+ onError(plugin.id, response.error ?? `${plugin.id}: ${row.trigger} failed`);
54208
+ }
54209
+ for (const entry of response.emittedEvents ?? []) {
54210
+ if (entry.event === row.trigger) continue;
54211
+ const sourceOrbital = entry.source?.orbital;
54212
+ if (sourceOrbital !== void 0 && ownOrbitals.has(sourceOrbital)) {
54213
+ bus.emit(`UI:${entry.event}`, entry.payload, entry.source);
54214
+ }
54215
+ }
54216
+ const states = [];
54217
+ for (const [traitName, stateName] of Object.entries(response.states)) {
54218
+ states.push([row.orbital, traitName, toTraitState(mockRuntime, row.orbital, traitName, stateName, row.trigger)]);
54219
+ onTransition?.(plugin.id, row.orbital, traitName, stateName);
54220
+ }
54221
+ onDispatched(plugin.id, row.trigger, states);
54222
+ },
54223
+ [registrationReady, mockRuntime, mode, transport, plugin, bus, ownOrbitals, onError, onTransition, onDispatched]
54224
+ );
54225
+ useEffect(() => {
54226
+ const unsubs = plugin.inbound.map(
54227
+ (row) => bus.on(`UI:${row.busEvent}`, (event) => {
54228
+ void dispatch(row, event.payload).catch((err) => {
54229
+ onError(plugin.id, err instanceof Error ? err.message : String(err));
54230
+ });
54231
+ })
54232
+ );
54233
+ return () => {
54234
+ for (const unsub of unsubs) unsub();
54235
+ };
54236
+ }, [bus, plugin, dispatch, onError]);
54237
+ return null;
54238
+ }
54239
+ function OrbitalPluginHost({
54240
+ plugins,
54241
+ mode = "mock",
54242
+ transport,
54243
+ deny,
54244
+ navigate,
54245
+ notify,
54246
+ onTransition,
54247
+ children
54248
+ }) {
54249
+ const [tick, setTick] = useState(0);
54250
+ const [errors, setErrors] = useState({});
54251
+ const statesRef = useRef(/* @__PURE__ */ new Map());
54252
+ const lastEventRef = useRef(/* @__PURE__ */ new Map());
54253
+ const pluginSchemas = useMemo(
54254
+ () => new Map(plugins.map((plugin) => [plugin.id, plugin.schema])),
54255
+ [plugins]
54256
+ );
54257
+ const handleDispatched = useCallback(
54258
+ (pluginId, trigger, states) => {
54259
+ if (trigger !== null) {
54260
+ lastEventRef.current.set(pluginId, trigger);
54261
+ }
54262
+ let byKey = statesRef.current.get(pluginId);
54263
+ if (!byKey) {
54264
+ byKey = /* @__PURE__ */ new Map();
54265
+ statesRef.current.set(pluginId, byKey);
54266
+ }
54267
+ for (const [orbital, trait, state] of states) {
54268
+ byKey.set(`${orbital}.${trait}`, state);
54269
+ }
54270
+ setTick((t) => t + 1);
54271
+ },
54272
+ []
54273
+ );
54274
+ const handleError = useCallback((pluginId, message) => {
54275
+ setErrors((prev) => prev[pluginId] === message ? prev : { ...prev, [pluginId]: message });
54276
+ }, []);
54277
+ const contextValue = useMemo(
54278
+ () => ({
54279
+ getState: (pluginId, orbital, trait) => statesRef.current.get(pluginId)?.get(`${orbital}.${trait}`),
54280
+ lastEvent: (pluginId) => lastEventRef.current.get(pluginId),
54281
+ errors,
54282
+ tick,
54283
+ getPluginSchema: (pluginId) => pluginSchemas.get(pluginId)
54284
+ }),
54285
+ [errors, tick, pluginSchemas]
54286
+ );
54287
+ return /* @__PURE__ */ jsxs(OrbitalPluginHostContext.Provider, { value: contextValue, children: [
54288
+ plugins.map((plugin) => /* @__PURE__ */ jsx(
54289
+ PluginRuntimeMount,
54290
+ {
54291
+ plugin,
54292
+ mode,
54293
+ transport,
54294
+ deny,
54295
+ navigate,
54296
+ notify,
54297
+ onTransition,
54298
+ onDispatched: handleDispatched,
54299
+ onError: handleError
54300
+ },
54301
+ plugin.id
54302
+ )),
54303
+ children ?? null
54304
+ ] });
54305
+ }
54306
+
52774
54307
  // runtime/index.ts
52775
54308
  init_perf();
52776
54309
 
52777
- export { BrowserPlayground, OrbPreview, clearSchemaCache, createClientEffectHandlers, profilerOnRender, usePerfBuffer, useResolvedSchema, useTraitStateMachine };
54310
+ export { BrowserPlayground, OrbPreview, OrbitalPluginHost, clearSchemaCache, createClientEffectHandlers, profilerOnRender, useDeclaredCaptureTable, useOrbitalPluginHost, usePerfBuffer, useResolvedSchema, useTraitStateMachine };