@almadar/ui 5.86.0 → 5.89.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 (35) hide show
  1. package/dist/avl/index.cjs +3435 -1250
  2. package/dist/avl/index.js +2485 -300
  3. package/dist/components/game/2d/molecules/StateGraph.d.ts +38 -0
  4. package/dist/components/game/2d/molecules/index.d.ts +24 -15
  5. package/dist/components/game/2d/organisms/BuilderBoard.d.ts +60 -0
  6. package/dist/components/game/2d/organisms/ClassifierBoard.d.ts +66 -0
  7. package/dist/components/game/2d/organisms/DebuggerBoard.d.ts +61 -0
  8. package/dist/components/game/2d/organisms/EventHandlerBoard.d.ts +42 -0
  9. package/dist/components/game/2d/organisms/NegotiatorBoard.d.ts +56 -0
  10. package/dist/components/game/2d/{molecules → organisms}/SequenceBar.d.ts +3 -8
  11. package/dist/components/game/2d/organisms/SequencerBoard.d.ts +69 -0
  12. package/dist/components/game/2d/organisms/SimulatorBoard.d.ts +58 -0
  13. package/dist/components/game/2d/organisms/StateArchitectBoard.d.ts +61 -0
  14. package/dist/components/game/shared/lib/puzzleObject.d.ts +1 -1
  15. package/dist/components/index.cjs +3168 -1351
  16. package/dist/components/index.js +2199 -391
  17. package/dist/providers/index.cjs +3295 -1110
  18. package/dist/providers/index.js +2454 -269
  19. package/dist/runtime/index.cjs +3291 -1106
  20. package/dist/runtime/index.js +2460 -275
  21. package/package.json +1 -1
  22. /package/dist/components/game/2d/{molecules → organisms}/ActionPalette.d.ts +0 -0
  23. /package/dist/components/game/2d/{molecules → organisms}/ActionTile.d.ts +0 -0
  24. /package/dist/components/game/2d/{molecules → organisms}/EventLog.d.ts +0 -0
  25. /package/dist/components/game/2d/{molecules → organisms}/ObjectRulePanel.d.ts +0 -0
  26. /package/dist/components/game/2d/{molecules → organisms}/RuleEditor.d.ts +0 -0
  27. /package/dist/components/game/2d/{molecules → organisms}/SimulationCanvas.d.ts +0 -0
  28. /package/dist/components/game/2d/{molecules → organisms}/SimulationControls.d.ts +0 -0
  29. /package/dist/components/game/2d/{molecules → organisms}/SimulationGraph.d.ts +0 -0
  30. /package/dist/components/game/2d/{molecules → organisms}/StateJsonView.d.ts +0 -0
  31. /package/dist/components/game/2d/{molecules → organisms}/StateNode.d.ts +0 -0
  32. /package/dist/components/game/2d/{molecules → organisms}/TraitSlot.d.ts +0 -0
  33. /package/dist/components/game/2d/{molecules → organisms}/TraitStateViewer.d.ts +0 -0
  34. /package/dist/components/game/2d/{molecules → organisms}/TransitionArrow.d.ts +0 -0
  35. /package/dist/components/game/2d/{molecules → organisms}/VariablePanel.d.ts +0 -0
@@ -1,12 +1,12 @@
1
1
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
2
- import * as React72 from 'react';
3
- import React72__default, { createContext, useContext, useMemo, useRef, useEffect, useCallback, useState, Suspense, lazy, useLayoutEffect, useId, useSyncExternalStore } from 'react';
2
+ import * as React74 from 'react';
3
+ import React74__default, { createContext, useContext, useMemo, useRef, useEffect, useCallback, useState, Suspense, lazy, useLayoutEffect, useId, useSyncExternalStore } from 'react';
4
4
  import { clsx } from 'clsx';
5
5
  import { twMerge } from 'tailwind-merge';
6
6
  import { EventBusContext, useTraitScope, useCurrentPagePath, useEntitySchemaOptional, TraitScopeProvider } from '@almadar/ui/providers';
7
7
  import { createLogger, isLogLevelEnabled } from '@almadar/logger';
8
8
  import * as LucideIcons2 from 'lucide-react';
9
- import { X, List, Printer, ChevronRight, ChevronLeft, RotateCcw, Play, Terminal, CheckCircle, XCircle, ChevronDown, Pause, SkipForward, Search, ChevronUp, MoreHorizontal, Package, Calendar, Pencil, Eye, Image as Image$1, Upload, ZoomIn, TrendingUp, TrendingDown, Minus, AlertCircle, Circle, Clock, CheckCircle2, Loader2, Code, FileText, WrapText, Check, Copy, HelpCircle, Type, Heading1, Heading2, Heading3, ListOrdered, Quote, GitBranch, Plus, ArrowRight, Trash, ArrowLeft, Menu as Menu$1, AlertTriangle, Trash2, Eraser, ZoomOut, Download, Lightbulb, PauseCircle, Link2, Tag, User, DollarSign } from 'lucide-react';
9
+ import { X, List, Printer, ChevronRight, ChevronLeft, CheckCircle, XCircle, Wrench, RotateCcw, Send, Play, Terminal, ChevronDown, Bug, ArrowRight, Pause, SkipForward, Search, ChevronUp, MoreHorizontal, Package, Calendar, Pencil, Eye, Image as Image$1, Upload, ZoomIn, TrendingUp, TrendingDown, Minus, AlertCircle, Circle, Clock, CheckCircle2, Loader2, Code, FileText, WrapText, Check, Copy, HelpCircle, Type, Heading1, Heading2, Heading3, ListOrdered, Quote, GitBranch, Plus, Trash, ArrowLeft, Menu as Menu$1, AlertTriangle, Trash2, Eraser, ZoomOut, Download, Lightbulb, PauseCircle, Link2, Tag, User, DollarSign } from 'lucide-react';
10
10
  import { useTranslate } from '@almadar/ui/hooks';
11
11
  import { useUISlots, useTheme } from '@almadar/ui/context';
12
12
  import { evaluate, createMinimalContext } from '@almadar/evaluator';
@@ -227,7 +227,7 @@ var init_SvgFlow = __esm({
227
227
  width = 100,
228
228
  height = 100
229
229
  }) => {
230
- const markerId = React72__default.useMemo(() => {
230
+ const markerId = React74__default.useMemo(() => {
231
231
  flowIdCounter += 1;
232
232
  return `almadar-flow-arrow-${flowIdCounter}`;
233
233
  }, []);
@@ -820,7 +820,7 @@ var init_SvgRing = __esm({
820
820
  width = 100,
821
821
  height = 100
822
822
  }) => {
823
- const gradientId = React72__default.useMemo(() => {
823
+ const gradientId = React74__default.useMemo(() => {
824
824
  ringIdCounter += 1;
825
825
  return `almadar-ring-glow-${ringIdCounter}`;
826
826
  }, []);
@@ -1232,7 +1232,7 @@ function loadLib(key, importer) {
1232
1232
  return p;
1233
1233
  }
1234
1234
  function lazyFamilyIcon(libKey, importer, pick, fallbackName, family) {
1235
- const Lazy = React72__default.lazy(async () => {
1235
+ const Lazy = React74__default.lazy(async () => {
1236
1236
  const lib = await loadLib(libKey, importer);
1237
1237
  const Comp = pick(lib);
1238
1238
  if (!Comp) {
@@ -1242,7 +1242,7 @@ function lazyFamilyIcon(libKey, importer, pick, fallbackName, family) {
1242
1242
  return { default: Comp };
1243
1243
  });
1244
1244
  const Wrapped = (props) => /* @__PURE__ */ jsx(
1245
- React72__default.Suspense,
1245
+ React74__default.Suspense,
1246
1246
  {
1247
1247
  fallback: /* @__PURE__ */ jsx(
1248
1248
  "span",
@@ -1973,7 +1973,7 @@ var init_Icon = __esm({
1973
1973
  const directIcon = typeof icon === "string" ? void 0 : icon;
1974
1974
  const effectiveName = typeof icon === "string" ? icon : name;
1975
1975
  const family = useIconFamily();
1976
- const RenderedComponent = React72__default.useMemo(() => {
1976
+ const RenderedComponent = React74__default.useMemo(() => {
1977
1977
  if (directIcon) return null;
1978
1978
  return effectiveName ? resolveIconForFamily(effectiveName, family) : null;
1979
1979
  }, [directIcon, effectiveName, family]);
@@ -2035,7 +2035,7 @@ function resolveIconProp(value, sizeClass) {
2035
2035
  const IconComp = value;
2036
2036
  return /* @__PURE__ */ jsx(IconComp, { className: sizeClass });
2037
2037
  }
2038
- if (React72__default.isValidElement(value)) {
2038
+ if (React74__default.isValidElement(value)) {
2039
2039
  return value;
2040
2040
  }
2041
2041
  if (typeof value === "object" && value !== null && isIconLike(value)) {
@@ -2111,7 +2111,7 @@ var init_Button = __esm({
2111
2111
  md: "h-icon-default w-icon-default",
2112
2112
  lg: "h-icon-default w-icon-default"
2113
2113
  };
2114
- Button = React72__default.forwardRef(
2114
+ Button = React74__default.forwardRef(
2115
2115
  ({
2116
2116
  className,
2117
2117
  variant = "primary",
@@ -2181,7 +2181,7 @@ var init_Input = __esm({
2181
2181
  init_cn();
2182
2182
  init_Icon();
2183
2183
  init_useEventBus();
2184
- Input = React72__default.forwardRef(
2184
+ Input = React74__default.forwardRef(
2185
2185
  ({
2186
2186
  className,
2187
2187
  inputType,
@@ -2341,7 +2341,7 @@ var Label;
2341
2341
  var init_Label = __esm({
2342
2342
  "components/core/atoms/Label.tsx"() {
2343
2343
  init_cn();
2344
- Label = React72__default.forwardRef(
2344
+ Label = React74__default.forwardRef(
2345
2345
  ({ className, required, children, ...props }, ref) => {
2346
2346
  return /* @__PURE__ */ jsxs(
2347
2347
  "label",
@@ -2368,7 +2368,7 @@ var init_Textarea = __esm({
2368
2368
  "components/core/atoms/Textarea.tsx"() {
2369
2369
  init_cn();
2370
2370
  init_useEventBus();
2371
- Textarea = React72__default.forwardRef(
2371
+ Textarea = React74__default.forwardRef(
2372
2372
  ({ className, error, onChange, ...props }, ref) => {
2373
2373
  const eventBus = useEventBus();
2374
2374
  const handleChange = (e) => {
@@ -2607,7 +2607,7 @@ var init_Select = __esm({
2607
2607
  init_cn();
2608
2608
  init_Icon();
2609
2609
  init_useEventBus();
2610
- Select = React72__default.forwardRef(
2610
+ Select = React74__default.forwardRef(
2611
2611
  (props, _ref) => {
2612
2612
  const { multiple, searchable, clearable } = props;
2613
2613
  if (multiple || searchable || clearable) {
@@ -2624,7 +2624,7 @@ var init_Checkbox = __esm({
2624
2624
  "components/core/atoms/Checkbox.tsx"() {
2625
2625
  init_cn();
2626
2626
  init_useEventBus();
2627
- Checkbox = React72__default.forwardRef(
2627
+ Checkbox = React74__default.forwardRef(
2628
2628
  ({ className, label, id, onChange, ...props }, ref) => {
2629
2629
  const inputId = id || `checkbox-${Math.random().toString(36).substr(2, 9)}`;
2630
2630
  const eventBus = useEventBus();
@@ -2678,7 +2678,7 @@ var init_Spinner = __esm({
2678
2678
  md: "h-6 w-6",
2679
2679
  lg: "h-8 w-8"
2680
2680
  };
2681
- Spinner = React72__default.forwardRef(
2681
+ Spinner = React74__default.forwardRef(
2682
2682
  ({ className, size = "md", overlay, ...props }, ref) => {
2683
2683
  if (overlay) {
2684
2684
  return /* @__PURE__ */ jsx(
@@ -2768,7 +2768,7 @@ var init_Card = __esm({
2768
2768
  chip: "shadow-none rounded-pill border-[length:var(--border-width)] border-border",
2769
2769
  "tile-image-first": "p-0 overflow-hidden"
2770
2770
  };
2771
- Card = React72__default.forwardRef(
2771
+ Card = React74__default.forwardRef(
2772
2772
  ({
2773
2773
  className,
2774
2774
  variant = "bordered",
@@ -2816,9 +2816,9 @@ var init_Card = __esm({
2816
2816
  }
2817
2817
  );
2818
2818
  Card.displayName = "Card";
2819
- CardHeader = React72__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("mb-4", className), ...props }));
2819
+ CardHeader = React74__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("mb-4", className), ...props }));
2820
2820
  CardHeader.displayName = "CardHeader";
2821
- CardTitle = React72__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
2821
+ CardTitle = React74__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
2822
2822
  "h3",
2823
2823
  {
2824
2824
  ref,
@@ -2831,11 +2831,11 @@ var init_Card = __esm({
2831
2831
  }
2832
2832
  ));
2833
2833
  CardTitle.displayName = "CardTitle";
2834
- CardContent = React72__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("", className), ...props }));
2834
+ CardContent = React74__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("", className), ...props }));
2835
2835
  CardContent.displayName = "CardContent";
2836
2836
  CardBody = CardContent;
2837
2837
  CardBody.displayName = "CardBody";
2838
- CardFooter = React72__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
2838
+ CardFooter = React74__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
2839
2839
  "div",
2840
2840
  {
2841
2841
  ref,
@@ -2888,7 +2888,7 @@ var init_Badge = __esm({
2888
2888
  md: "px-2.5 py-1 text-sm",
2889
2889
  lg: "px-3 py-1.5 text-base"
2890
2890
  };
2891
- Badge = React72__default.forwardRef(
2891
+ Badge = React74__default.forwardRef(
2892
2892
  ({ className, variant = "default", size = "sm", amount, label, icon, iconAsset, children, onRemove, removeLabel, ...props }, ref) => {
2893
2893
  const iconSizes3 = {
2894
2894
  sm: "h-icon-default w-icon-default",
@@ -2982,7 +2982,7 @@ var init_FilterPill = __esm({
2982
2982
  md: "w-3.5 h-3.5",
2983
2983
  lg: "w-4 h-4"
2984
2984
  };
2985
- FilterPill = React72__default.forwardRef(
2985
+ FilterPill = React74__default.forwardRef(
2986
2986
  ({
2987
2987
  className,
2988
2988
  variant = "default",
@@ -3111,8 +3111,8 @@ var init_Avatar = __esm({
3111
3111
  actionPayload
3112
3112
  }) => {
3113
3113
  const eventBus = useEventBus();
3114
- const [imgFailed, setImgFailed] = React72__default.useState(false);
3115
- React72__default.useEffect(() => {
3114
+ const [imgFailed, setImgFailed] = React74__default.useState(false);
3115
+ React74__default.useEffect(() => {
3116
3116
  setImgFailed(false);
3117
3117
  }, [src]);
3118
3118
  const initials = providedInitials ?? (name ? generateInitials(name) : void 0);
@@ -3364,7 +3364,7 @@ var init_Box = __esm({
3364
3364
  fixed: "fixed",
3365
3365
  sticky: "sticky"
3366
3366
  };
3367
- Box = React72__default.forwardRef(
3367
+ Box = React74__default.forwardRef(
3368
3368
  ({
3369
3369
  padding,
3370
3370
  paddingX,
@@ -3429,7 +3429,7 @@ var init_Box = __esm({
3429
3429
  onPointerDown?.(e);
3430
3430
  }, [hoverEvent, tapReveal, triggerProps, onPointerDown]);
3431
3431
  const isClickable = action || onClick;
3432
- return React72__default.createElement(
3432
+ return React74__default.createElement(
3433
3433
  Component,
3434
3434
  {
3435
3435
  ref,
@@ -3483,7 +3483,7 @@ var init_Center = __esm({
3483
3483
  as: Component = "div"
3484
3484
  }) => {
3485
3485
  const mergedStyle = minHeight ? { minHeight, ...style } : style;
3486
- return React72__default.createElement(Component, {
3486
+ return React74__default.createElement(Component, {
3487
3487
  className: cn(
3488
3488
  inline ? "inline-flex" : "flex",
3489
3489
  horizontal && "justify-center",
@@ -3751,7 +3751,7 @@ var init_Radio = __esm({
3751
3751
  md: "w-2.5 h-2.5",
3752
3752
  lg: "w-3 h-3"
3753
3753
  };
3754
- Radio = React72__default.forwardRef(
3754
+ Radio = React74__default.forwardRef(
3755
3755
  ({
3756
3756
  label,
3757
3757
  helperText,
@@ -3768,12 +3768,12 @@ var init_Radio = __esm({
3768
3768
  onChange,
3769
3769
  ...props
3770
3770
  }, ref) => {
3771
- const reactId = React72__default.useId();
3771
+ const reactId = React74__default.useId();
3772
3772
  const baseId = id || `radio-${reactId}`;
3773
3773
  const hasError = !!error;
3774
3774
  const eventBus = useEventBus();
3775
- const [selected, setSelected] = React72__default.useState(value);
3776
- React72__default.useEffect(() => {
3775
+ const [selected, setSelected] = React74__default.useState(value);
3776
+ React74__default.useEffect(() => {
3777
3777
  if (value !== void 0) setSelected(value);
3778
3778
  }, [value]);
3779
3779
  const pick = (next, e) => {
@@ -3955,7 +3955,7 @@ var init_Switch = __esm({
3955
3955
  "components/core/atoms/Switch.tsx"() {
3956
3956
  "use client";
3957
3957
  init_cn();
3958
- Switch = React72.forwardRef(
3958
+ Switch = React74.forwardRef(
3959
3959
  ({
3960
3960
  checked,
3961
3961
  defaultChecked = false,
@@ -3966,10 +3966,10 @@ var init_Switch = __esm({
3966
3966
  name,
3967
3967
  className
3968
3968
  }, ref) => {
3969
- const [isChecked, setIsChecked] = React72.useState(
3969
+ const [isChecked, setIsChecked] = React74.useState(
3970
3970
  checked !== void 0 ? checked : defaultChecked
3971
3971
  );
3972
- React72.useEffect(() => {
3972
+ React74.useEffect(() => {
3973
3973
  if (checked !== void 0) {
3974
3974
  setIsChecked(checked);
3975
3975
  }
@@ -4132,7 +4132,7 @@ var init_Stack = __esm({
4132
4132
  };
4133
4133
  const isHorizontal = direction === "horizontal";
4134
4134
  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";
4135
- return React72__default.createElement(
4135
+ return React74__default.createElement(
4136
4136
  Component,
4137
4137
  {
4138
4138
  className: cn(
@@ -4328,7 +4328,7 @@ var init_Typography = __esm({
4328
4328
  }) => {
4329
4329
  const variant = variantProp ?? (level ? `h${level}` : "body1");
4330
4330
  const Component = as || defaultElements[variant];
4331
- return React72__default.createElement(
4331
+ return React74__default.createElement(
4332
4332
  Component,
4333
4333
  {
4334
4334
  id,
@@ -4487,7 +4487,7 @@ var Dialog;
4487
4487
  var init_Dialog = __esm({
4488
4488
  "components/core/atoms/Dialog.tsx"() {
4489
4489
  init_cn();
4490
- Dialog = React72__default.forwardRef(
4490
+ Dialog = React74__default.forwardRef(
4491
4491
  ({
4492
4492
  role = "dialog",
4493
4493
  "aria-modal": ariaModal = true,
@@ -4513,7 +4513,7 @@ var Aside;
4513
4513
  var init_Aside = __esm({
4514
4514
  "components/core/atoms/Aside.tsx"() {
4515
4515
  init_cn();
4516
- Aside = React72__default.forwardRef(
4516
+ Aside = React74__default.forwardRef(
4517
4517
  ({ className, children, ...rest }, ref) => /* @__PURE__ */ jsx("aside", { ref, className: cn(className), ...rest, children })
4518
4518
  );
4519
4519
  Aside.displayName = "Aside";
@@ -4592,9 +4592,9 @@ var init_LawReferenceTooltip = __esm({
4592
4592
  className
4593
4593
  }) => {
4594
4594
  const { t } = useTranslate();
4595
- const [isVisible, setIsVisible] = React72__default.useState(false);
4596
- const timeoutRef = React72__default.useRef(null);
4597
- const triggerRef = React72__default.useRef(null);
4595
+ const [isVisible, setIsVisible] = React74__default.useState(false);
4596
+ const timeoutRef = React74__default.useRef(null);
4597
+ const triggerRef = React74__default.useRef(null);
4598
4598
  const handleMouseEnter = () => {
4599
4599
  if (timeoutRef.current) clearTimeout(timeoutRef.current);
4600
4600
  timeoutRef.current = setTimeout(() => setIsVisible(true), 200);
@@ -4605,7 +4605,7 @@ var init_LawReferenceTooltip = __esm({
4605
4605
  };
4606
4606
  const { revealed, triggerProps } = useTapReveal({ refs: [triggerRef] });
4607
4607
  const open = isVisible || revealed;
4608
- React72__default.useEffect(() => {
4608
+ React74__default.useEffect(() => {
4609
4609
  return () => {
4610
4610
  if (timeoutRef.current) clearTimeout(timeoutRef.current);
4611
4611
  };
@@ -4815,7 +4815,7 @@ var init_StatusDot = __esm({
4815
4815
  md: "w-2.5 h-2.5",
4816
4816
  lg: "w-3 h-3"
4817
4817
  };
4818
- StatusDot = React72__default.forwardRef(
4818
+ StatusDot = React74__default.forwardRef(
4819
4819
  ({ className, status = "offline", pulse = false, size = "md", label, ...props }, ref) => {
4820
4820
  return /* @__PURE__ */ jsx(
4821
4821
  "span",
@@ -4869,7 +4869,7 @@ var init_TrendIndicator = __esm({
4869
4869
  down: "trending-down",
4870
4870
  flat: "arrow-right"
4871
4871
  };
4872
- TrendIndicator = React72__default.forwardRef(
4872
+ TrendIndicator = React74__default.forwardRef(
4873
4873
  ({
4874
4874
  className,
4875
4875
  value,
@@ -4936,7 +4936,7 @@ var init_RangeSlider = __esm({
4936
4936
  md: "w-4 h-4",
4937
4937
  lg: "w-5 h-5"
4938
4938
  };
4939
- RangeSlider = React72__default.forwardRef(
4939
+ RangeSlider = React74__default.forwardRef(
4940
4940
  ({
4941
4941
  className,
4942
4942
  min = 0,
@@ -5530,7 +5530,7 @@ var init_ContentSection = __esm({
5530
5530
  md: "py-16",
5531
5531
  lg: "py-24"
5532
5532
  };
5533
- ContentSection = React72__default.forwardRef(
5533
+ ContentSection = React74__default.forwardRef(
5534
5534
  ({ children, background = "default", padding = "lg", id, className }, ref) => {
5535
5535
  return /* @__PURE__ */ jsx(
5536
5536
  Box,
@@ -6064,7 +6064,7 @@ var init_AnimatedReveal = __esm({
6064
6064
  "scale-up": { opacity: 1, transform: "scale(1) translateY(0)" },
6065
6065
  "none": {}
6066
6066
  };
6067
- AnimatedReveal = React72__default.forwardRef(
6067
+ AnimatedReveal = React74__default.forwardRef(
6068
6068
  ({
6069
6069
  trigger = "scroll",
6070
6070
  animation = "fade-up",
@@ -6224,7 +6224,7 @@ var init_AnimatedGraphic = __esm({
6224
6224
  "components/marketing/atoms/AnimatedGraphic.tsx"() {
6225
6225
  "use client";
6226
6226
  init_cn();
6227
- AnimatedGraphic = React72__default.forwardRef(
6227
+ AnimatedGraphic = React74__default.forwardRef(
6228
6228
  ({
6229
6229
  src,
6230
6230
  svgContent,
@@ -6247,7 +6247,7 @@ var init_AnimatedGraphic = __esm({
6247
6247
  const fetchedSvg = useFetchedSvg(svgContent ? void 0 : src);
6248
6248
  const resolvedSvg = svgContent ?? fetchedSvg;
6249
6249
  const prevAnimateRef = useRef(animate);
6250
- const setRef = React72__default.useCallback(
6250
+ const setRef = React74__default.useCallback(
6251
6251
  (node) => {
6252
6252
  containerRef.current = node;
6253
6253
  if (typeof ref === "function") ref(node);
@@ -6920,7 +6920,7 @@ var init_ErrorBoundary = __esm({
6920
6920
  }
6921
6921
  );
6922
6922
  };
6923
- ErrorBoundary = class extends React72__default.Component {
6923
+ ErrorBoundary = class extends React74__default.Component {
6924
6924
  constructor(props) {
6925
6925
  super(props);
6926
6926
  __publicField(this, "reset", () => {
@@ -7216,7 +7216,7 @@ var init_Container = __esm({
7216
7216
  as: Component = "div"
7217
7217
  }) => {
7218
7218
  const resolvedSize = maxWidth ?? size ?? "lg";
7219
- return React72__default.createElement(
7219
+ return React74__default.createElement(
7220
7220
  Component,
7221
7221
  {
7222
7222
  className: cn(
@@ -8102,7 +8102,7 @@ function ActionTile({
8102
8102
  }
8103
8103
  var DRAG_MIME, SIZE_CONFIG;
8104
8104
  var init_ActionTile = __esm({
8105
- "components/game/2d/molecules/ActionTile.tsx"() {
8105
+ "components/game/2d/organisms/ActionTile.tsx"() {
8106
8106
  init_atoms();
8107
8107
  init_cn();
8108
8108
  DRAG_MIME = "application/x-almadar-slot-item";
@@ -8139,7 +8139,7 @@ function ActionPalette({
8139
8139
  ] });
8140
8140
  }
8141
8141
  var init_ActionPalette = __esm({
8142
- "components/game/2d/molecules/ActionPalette.tsx"() {
8142
+ "components/game/2d/organisms/ActionPalette.tsx"() {
8143
8143
  init_atoms();
8144
8144
  init_cn();
8145
8145
  init_ActionTile();
@@ -10410,7 +10410,7 @@ var init_CodeBlock = __esm({
10410
10410
  DIFF_STYLE_FALLBACK = { bg: "", prefix: " ", text: "text-foreground" };
10411
10411
  LINE_PROPS_FN = (n) => ({ "data-line": String(n - 1) });
10412
10412
  HIDDEN_LINE_NUMBERS = { display: "none" };
10413
- CodeBlock = React72__default.memo(
10413
+ CodeBlock = React74__default.memo(
10414
10414
  ({
10415
10415
  code: rawCode,
10416
10416
  language = "text",
@@ -10997,7 +10997,7 @@ var init_MarkdownContent = __esm({
10997
10997
  init_Box();
10998
10998
  init_CodeBlock();
10999
10999
  init_cn();
11000
- MarkdownContent = React72__default.memo(
11000
+ MarkdownContent = React74__default.memo(
11001
11001
  ({ content, direction = "ltr", className }) => {
11002
11002
  const { t: _t } = useTranslate();
11003
11003
  const safeContent = typeof content === "string" ? content : String(content ?? "");
@@ -12324,7 +12324,7 @@ var init_StateMachineView = __esm({
12324
12324
  style: { top: title ? 30 : 0 },
12325
12325
  children: [
12326
12326
  entity && /* @__PURE__ */ jsx(EntityBox, { entity, config }),
12327
- states.map((state) => renderStateNode ? /* @__PURE__ */ jsx(React72__default.Fragment, { children: renderStateNode(state, config) }, state.id) : /* @__PURE__ */ jsx(
12327
+ states.map((state) => renderStateNode ? /* @__PURE__ */ jsx(React74__default.Fragment, { children: renderStateNode(state, config) }, state.id) : /* @__PURE__ */ jsx(
12328
12328
  StateNode,
12329
12329
  {
12330
12330
  state,
@@ -14363,6 +14363,221 @@ var init_Breadcrumb = __esm({
14363
14363
  Breadcrumb.displayName = "Breadcrumb";
14364
14364
  }
14365
14365
  });
14366
+
14367
+ // components/game/shared/boardEntity.ts
14368
+ function boardEntity(entity) {
14369
+ if (!entity) return void 0;
14370
+ return Array.isArray(entity) ? entity[0] : entity;
14371
+ }
14372
+ function str(v) {
14373
+ return v == null ? "" : String(v);
14374
+ }
14375
+ function num(v, fallback = 0) {
14376
+ const n = Number(v);
14377
+ return Number.isFinite(n) ? n : fallback;
14378
+ }
14379
+ function bool(v) {
14380
+ return Boolean(v);
14381
+ }
14382
+ function rows(v) {
14383
+ return Array.isArray(v) ? v : [];
14384
+ }
14385
+ function vec2(v) {
14386
+ const o = v ?? {};
14387
+ return { x: num(o.x), y: num(o.y) };
14388
+ }
14389
+ function unitPosition(u) {
14390
+ return vec2(u.position);
14391
+ }
14392
+ function unitTeam(u) {
14393
+ return str(u.team);
14394
+ }
14395
+ function unitHealth(u) {
14396
+ return num(u.health);
14397
+ }
14398
+ var init_boardEntity = __esm({
14399
+ "components/game/shared/boardEntity.ts"() {
14400
+ }
14401
+ });
14402
+ function BuilderBoard({
14403
+ entity,
14404
+ completeEvent = "PUZZLE_COMPLETE",
14405
+ placeEvent,
14406
+ checkEvent,
14407
+ playAgainEvent,
14408
+ assetManifest,
14409
+ className
14410
+ }) {
14411
+ const ui = assetManifest?.ui;
14412
+ const { emit } = useEventBus();
14413
+ const { t } = useTranslate();
14414
+ const resolved = boardEntity(entity);
14415
+ const [headerError, setHeaderError] = useState(false);
14416
+ const [selectedComponent, setSelectedComponent] = useState(null);
14417
+ const components = rows(resolved?.components).map((r) => ({
14418
+ id: str(r.id),
14419
+ label: str(r.label),
14420
+ description: str(r.description) || void 0,
14421
+ iconEmoji: str(r.iconEmoji) || void 0,
14422
+ iconUrl: str(r.iconUrl) || void 0,
14423
+ category: str(r.category) || void 0
14424
+ }));
14425
+ const slots = rows(resolved?.slots).map((r) => ({
14426
+ id: str(r.id),
14427
+ label: str(r.label) || void 0,
14428
+ description: str(r.description) || void 0,
14429
+ requiredComponentId: str(r.requiredComponentId),
14430
+ placedComponentId: str(r.placedComponentId) || void 0
14431
+ }));
14432
+ const placements = {};
14433
+ for (const slot of slots) {
14434
+ if (slot.placedComponentId) placements[slot.id] = slot.placedComponentId;
14435
+ }
14436
+ const attempts = num(resolved?.attempts);
14437
+ const result = str(resolved?.result) || "none";
14438
+ const submitted = result === "win";
14439
+ const usedComponentIds = new Set(Object.values(placements));
14440
+ const availableComponents = components.filter((c) => !usedComponentIds.has(c.id));
14441
+ const allPlaced = slots.length > 0 && slots.every((s) => Boolean(placements[s.id]));
14442
+ const results = submitted ? slots.map((slot) => ({
14443
+ slot,
14444
+ placed: placements[slot.id],
14445
+ correct: placements[slot.id] === slot.requiredComponentId
14446
+ })) : [];
14447
+ const showHint = attempts >= 2 && Boolean(str(resolved?.hint));
14448
+ const handlePlaceComponent = (slotId) => {
14449
+ if (submitted || !selectedComponent) return;
14450
+ if (placeEvent) emit(`UI:${placeEvent}`, { slotId, componentId: selectedComponent });
14451
+ setSelectedComponent(null);
14452
+ };
14453
+ const handleRemoveFromSlot = (slotId) => {
14454
+ if (submitted) return;
14455
+ if (placeEvent) emit(`UI:${placeEvent}`, { slotId, componentId: "" });
14456
+ };
14457
+ const handleSubmit = () => {
14458
+ if (checkEvent) emit(`UI:${checkEvent}`, {});
14459
+ const solved = slots.length > 0 && slots.every((s) => placements[s.id] === s.requiredComponentId);
14460
+ if (solved && completeEvent) {
14461
+ emit(`UI:${completeEvent}`, { success: true, attempts: attempts + 1 });
14462
+ }
14463
+ };
14464
+ const handlePlayAgain = () => {
14465
+ setSelectedComponent(null);
14466
+ if (playAgainEvent) emit(`UI:${playAgainEvent}`, {});
14467
+ };
14468
+ const getComponentById = (id) => components.find((c) => c.id === id);
14469
+ if (!resolved) return null;
14470
+ const theme = resolved.theme ?? void 0;
14471
+ const themeBackground = theme?.background;
14472
+ const headerImage = str(resolved.headerImage);
14473
+ const hint = str(resolved.hint);
14474
+ return /* @__PURE__ */ jsx(
14475
+ Box,
14476
+ {
14477
+ className,
14478
+ style: {
14479
+ backgroundImage: themeBackground ? `url(${themeBackground})` : void 0,
14480
+ backgroundSize: "cover",
14481
+ backgroundPosition: "center"
14482
+ },
14483
+ children: /* @__PURE__ */ jsxs(VStack, { gap: "lg", className: "p-4", children: [
14484
+ headerImage && !headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 overflow-hidden rounded-container", children: /* @__PURE__ */ jsx("img", { src: headerImage, alt: "", onError: () => setHeaderError(true), className: "w-full h-full object-cover" }) }) : headerImage && headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 rounded-container bg-gradient-to-br from-muted to-accent opacity-60" }) : null,
14485
+ /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
14486
+ /* @__PURE__ */ jsx(Typography, { variant: "h4", weight: "bold", children: str(resolved.title) }),
14487
+ /* @__PURE__ */ jsx(Typography, { variant: "body", children: str(resolved.description) })
14488
+ ] }) }),
14489
+ /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
14490
+ /* @__PURE__ */ jsx(Typography, { variant: "small", weight: "bold", className: "uppercase tracking-wider text-muted-foreground", children: t("builder.components") }),
14491
+ /* @__PURE__ */ jsxs(HStack, { gap: "sm", className: "flex-wrap", children: [
14492
+ availableComponents.map((comp) => /* @__PURE__ */ jsxs(
14493
+ Button,
14494
+ {
14495
+ size: "sm",
14496
+ variant: selectedComponent === comp.id ? "primary" : "secondary",
14497
+ onClick: () => setSelectedComponent(selectedComponent === comp.id ? null : comp.id),
14498
+ disabled: submitted,
14499
+ children: [
14500
+ comp.iconUrl ? /* @__PURE__ */ jsx("img", { src: comp.iconUrl, alt: "", className: "w-5 h-5 object-contain inline-block mr-1" }) : comp.iconEmoji ? /* @__PURE__ */ jsxs(Fragment, { children: [
14501
+ comp.iconEmoji,
14502
+ " "
14503
+ ] }) : null,
14504
+ comp.label
14505
+ ]
14506
+ },
14507
+ comp.id
14508
+ )),
14509
+ availableComponents.length === 0 && !submitted && /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-muted-foreground", children: t("builder.allPlaced") })
14510
+ ] })
14511
+ ] }) }),
14512
+ /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
14513
+ /* @__PURE__ */ jsx(Typography, { variant: "small", weight: "bold", className: "uppercase tracking-wider text-muted-foreground", children: t("builder.blueprint") }),
14514
+ /* @__PURE__ */ jsx(VStack, { gap: "sm", children: slots.map((slot) => {
14515
+ const placedComp = placements[slot.id] ? getComponentById(placements[slot.id]) : null;
14516
+ const result2 = results.find((r) => r.slot.id === slot.id);
14517
+ return /* @__PURE__ */ jsxs(
14518
+ HStack,
14519
+ {
14520
+ gap: "sm",
14521
+ align: "center",
14522
+ className: `p-3 border-2 rounded ${result2 ? result2.correct ? "border-success" : "border-error" : selectedComponent ? "border-dashed border-foreground cursor-pointer" : "border-border"}`,
14523
+ onClick: () => handlePlaceComponent(slot.id),
14524
+ children: [
14525
+ /* @__PURE__ */ jsxs(VStack, { gap: "none", className: "flex-1", children: [
14526
+ /* @__PURE__ */ jsx(Typography, { variant: "body", weight: "medium", children: slot.label }),
14527
+ slot.description && /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-muted-foreground", children: slot.description })
14528
+ ] }),
14529
+ placedComp ? /* @__PURE__ */ jsxs(HStack, { gap: "xs", align: "center", children: [
14530
+ /* @__PURE__ */ jsxs(Badge, { size: "sm", onClick: () => handleRemoveFromSlot(slot.id), children: [
14531
+ placedComp.iconUrl ? /* @__PURE__ */ jsx("img", { src: placedComp.iconUrl, alt: "", className: "w-4 h-4 object-contain inline-block mr-1" }) : placedComp.iconEmoji ? /* @__PURE__ */ jsxs(Fragment, { children: [
14532
+ placedComp.iconEmoji,
14533
+ " "
14534
+ ] }) : null,
14535
+ placedComp.label
14536
+ ] }),
14537
+ result2 && /* @__PURE__ */ jsx(
14538
+ GameIcon,
14539
+ {
14540
+ icon: result2.correct ? CheckCircle : XCircle,
14541
+ assetUrl: result2.correct ? ui?.["correct"] : ui?.["incorrect"],
14542
+ size: "sm",
14543
+ className: result2.correct ? "text-success" : "text-error"
14544
+ }
14545
+ )
14546
+ ] }) : /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-muted-foreground", children: t("builder.empty") })
14547
+ ]
14548
+ },
14549
+ slot.id
14550
+ );
14551
+ }) })
14552
+ ] }) }),
14553
+ submitted && /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", align: "center", children: [
14554
+ /* @__PURE__ */ jsx(GameIcon, { icon: CheckCircle, assetUrl: ui?.["correct"], size: "lg", className: "text-success" }),
14555
+ /* @__PURE__ */ jsx(Typography, { variant: "body", weight: "bold", children: str(resolved.successMessage) || t("builder.success") })
14556
+ ] }) }),
14557
+ showHint && hint && /* @__PURE__ */ jsx(Card, { className: "p-4 border-l-4 border-l-warning", children: /* @__PURE__ */ jsx(Typography, { variant: "body", children: hint }) }),
14558
+ /* @__PURE__ */ jsxs(HStack, { gap: "sm", justify: "center", children: [
14559
+ !submitted && /* @__PURE__ */ jsxs(Button, { variant: "primary", onClick: handleSubmit, disabled: !allPlaced, children: [
14560
+ /* @__PURE__ */ jsx(GameIcon, { icon: Wrench, assetUrl: ui?.["build"], size: "sm" }),
14561
+ t("builder.build")
14562
+ ] }),
14563
+ /* @__PURE__ */ jsxs(Button, { variant: "secondary", onClick: handlePlayAgain, children: [
14564
+ /* @__PURE__ */ jsx(GameIcon, { icon: RotateCcw, assetUrl: ui?.["reset"], size: "sm" }),
14565
+ t("builder.reset")
14566
+ ] })
14567
+ ] })
14568
+ ] })
14569
+ }
14570
+ );
14571
+ }
14572
+ var init_BuilderBoard = __esm({
14573
+ "components/game/2d/organisms/BuilderBoard.tsx"() {
14574
+ init_atoms();
14575
+ init_useEventBus();
14576
+ init_boardEntity();
14577
+ init_GameIcon();
14578
+ BuilderBoard.displayName = "BuilderBoard";
14579
+ }
14580
+ });
14366
14581
  function useSwipeGesture(callbacks, options = {}) {
14367
14582
  const { threshold = 50, velocityThreshold = 0.3, preventDefault = false } = options;
14368
14583
  const startX = useRef(0);
@@ -14733,8 +14948,8 @@ function MiniMap({
14733
14948
  tileAssets,
14734
14949
  unitAssets
14735
14950
  }) {
14736
- const canvasRef = React72.useRef(null);
14737
- const imgCacheRef = React72.useRef(/* @__PURE__ */ new Map());
14951
+ const canvasRef = React74.useRef(null);
14952
+ const imgCacheRef = React74.useRef(/* @__PURE__ */ new Map());
14738
14953
  function loadImg(url) {
14739
14954
  const cached = imgCacheRef.current.get(url);
14740
14955
  if (cached) return cached.complete ? cached : null;
@@ -14749,7 +14964,7 @@ function MiniMap({
14749
14964
  imgCacheRef.current.set(url, img);
14750
14965
  return null;
14751
14966
  }
14752
- React72.useEffect(() => {
14967
+ React74.useEffect(() => {
14753
14968
  const canvas = canvasRef.current;
14754
14969
  if (!canvas) return;
14755
14970
  const ctx = canvas.getContext("2d");
@@ -18831,6 +19046,170 @@ var init_ChoiceButton = __esm({
18831
19046
  ChoiceButton.displayName = "ChoiceButton";
18832
19047
  }
18833
19048
  });
19049
+ function ClassifierBoard({
19050
+ entity,
19051
+ completeEvent = "PUZZLE_COMPLETE",
19052
+ assignEvent,
19053
+ checkEvent,
19054
+ playAgainEvent,
19055
+ assetManifest,
19056
+ className
19057
+ }) {
19058
+ const ui = assetManifest?.ui;
19059
+ const { emit } = useEventBus();
19060
+ const { t } = useTranslate();
19061
+ const resolved = boardEntity(entity);
19062
+ const [headerError, setHeaderError] = useState(false);
19063
+ const items = rows(resolved?.items);
19064
+ const categories = rows(resolved?.categories);
19065
+ const result = str(resolved?.result);
19066
+ const submitted = result === "win";
19067
+ const attempts = num(resolved?.attempts);
19068
+ const assignments = items.reduce((acc, item) => {
19069
+ if (item.assignedCategory != null && item.assignedCategory !== "") acc[item.id] = item.assignedCategory;
19070
+ return acc;
19071
+ }, {});
19072
+ const unassignedItems = items.filter((item) => !assignments[item.id]);
19073
+ const allAssigned = items.length > 0 && Object.keys(assignments).length === items.length;
19074
+ const results = submitted ? items.map((item) => ({
19075
+ item,
19076
+ assigned: assignments[item.id],
19077
+ correct: assignments[item.id] === item.correctCategory
19078
+ })) : [];
19079
+ const allCorrect = result === "win";
19080
+ const correctCount = results.filter((r) => r.correct).length;
19081
+ const showHint = attempts >= 2 && Boolean(str(resolved?.hint));
19082
+ const handleAssign = (itemId, categoryId) => {
19083
+ if (submitted) return;
19084
+ if (assignEvent) emit(`UI:${assignEvent}`, { itemId, categoryId });
19085
+ };
19086
+ const handleUnassign = (itemId) => {
19087
+ if (submitted) return;
19088
+ if (assignEvent) emit(`UI:${assignEvent}`, { itemId, categoryId: "" });
19089
+ };
19090
+ const handleSubmit = () => {
19091
+ if (checkEvent) emit(`UI:${checkEvent}`, {});
19092
+ if (allAssigned && items.every((item) => assignments[item.id] === item.correctCategory)) {
19093
+ emit(`UI:${completeEvent}`, { success: true, attempts: attempts + 1 });
19094
+ }
19095
+ };
19096
+ const handleFullReset = () => {
19097
+ if (playAgainEvent) emit(`UI:${playAgainEvent}`, {});
19098
+ };
19099
+ if (!resolved) return null;
19100
+ const theme = resolved.theme ?? void 0;
19101
+ const themeBackground = theme?.background;
19102
+ const headerImage = str(resolved.headerImage);
19103
+ const hint = str(resolved.hint);
19104
+ const failMessage = str(resolved.failMessage);
19105
+ return /* @__PURE__ */ jsx(
19106
+ Box,
19107
+ {
19108
+ className,
19109
+ style: {
19110
+ backgroundImage: themeBackground ? `url(${themeBackground})` : void 0,
19111
+ backgroundSize: "cover",
19112
+ backgroundPosition: "center"
19113
+ },
19114
+ children: /* @__PURE__ */ jsxs(VStack, { gap: "lg", className: "p-4", children: [
19115
+ headerImage && !headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 overflow-hidden rounded-container", children: /* @__PURE__ */ jsx("img", { src: headerImage, alt: "", onError: () => setHeaderError(true), className: "w-full h-full object-cover" }) }) : headerImage && headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 rounded-container bg-gradient-to-br from-muted to-accent opacity-60" }) : null,
19116
+ /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
19117
+ /* @__PURE__ */ jsx(Typography, { variant: "h4", weight: "bold", children: str(resolved.title) }),
19118
+ /* @__PURE__ */ jsx(Typography, { variant: "body", children: str(resolved.description) })
19119
+ ] }) }),
19120
+ unassignedItems.length > 0 && /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
19121
+ /* @__PURE__ */ jsx(Typography, { variant: "small", weight: "bold", className: "uppercase tracking-wider text-muted-foreground", children: t("classifier.itemsToSort") }),
19122
+ /* @__PURE__ */ jsx(HStack, { gap: "sm", className: "flex-wrap", children: unassignedItems.map((item) => /* @__PURE__ */ jsxs(Badge, { size: "md", className: "cursor-pointer", children: [
19123
+ item.iconUrl && /* @__PURE__ */ jsx("img", { src: item.iconUrl, alt: "", className: "w-4 h-4 object-contain inline-block" }),
19124
+ item.label
19125
+ ] }, item.id)) })
19126
+ ] }) }),
19127
+ /* @__PURE__ */ jsx(VStack, { gap: "md", children: categories.map((cat) => {
19128
+ const catItems = items.filter((item) => assignments[item.id] === cat.id);
19129
+ return /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
19130
+ cat.imageUrl && /* @__PURE__ */ jsx(Box, { className: "w-full h-16 overflow-hidden rounded-container", children: /* @__PURE__ */ jsx("img", { src: cat.imageUrl, alt: "", className: "w-full h-full object-cover" }) }),
19131
+ /* @__PURE__ */ jsxs(HStack, { justify: "between", align: "center", children: [
19132
+ /* @__PURE__ */ jsx(Typography, { variant: "body", weight: "bold", children: cat.label }),
19133
+ /* @__PURE__ */ jsx(Badge, { size: "sm", children: catItems.length })
19134
+ ] }),
19135
+ /* @__PURE__ */ jsx(HStack, { gap: "xs", className: "flex-wrap min-h-[2rem]", children: catItems.map((item) => {
19136
+ const result2 = results.find((r) => r.item.id === item.id);
19137
+ return /* @__PURE__ */ jsxs(
19138
+ Badge,
19139
+ {
19140
+ size: "sm",
19141
+ className: `cursor-pointer ${result2 ? result2.correct ? "border-success bg-success/10" : "border-error bg-error/10" : ""}`,
19142
+ onClick: () => handleUnassign(item.id),
19143
+ children: [
19144
+ item.iconUrl && /* @__PURE__ */ jsx("img", { src: item.iconUrl, alt: "", className: "w-3 h-3 object-contain inline-block" }),
19145
+ item.label,
19146
+ result2 && /* @__PURE__ */ jsx(
19147
+ GameIcon,
19148
+ {
19149
+ icon: result2.correct ? CheckCircle : XCircle,
19150
+ assetUrl: result2.correct ? ui?.["correct"] : ui?.["incorrect"],
19151
+ size: "sm",
19152
+ className: result2.correct ? "text-success" : "text-error"
19153
+ }
19154
+ )
19155
+ ]
19156
+ },
19157
+ item.id
19158
+ );
19159
+ }) }),
19160
+ !submitted && unassignedItems.length > 0 && /* @__PURE__ */ jsx(HStack, { gap: "xs", className: "flex-wrap", children: unassignedItems.map((item) => /* @__PURE__ */ jsxs(
19161
+ Button,
19162
+ {
19163
+ size: "sm",
19164
+ variant: "ghost",
19165
+ onClick: () => handleAssign(item.id, cat.id),
19166
+ className: "text-xs opacity-50 hover:opacity-100",
19167
+ children: [
19168
+ "+ ",
19169
+ item.label
19170
+ ]
19171
+ },
19172
+ item.id
19173
+ )) })
19174
+ ] }) }, cat.id);
19175
+ }) }),
19176
+ submitted && /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", align: "center", children: [
19177
+ /* @__PURE__ */ jsx(
19178
+ GameIcon,
19179
+ {
19180
+ icon: allCorrect ? CheckCircle : XCircle,
19181
+ assetUrl: allCorrect ? ui?.["correct"] : ui?.["incorrect"],
19182
+ size: "lg",
19183
+ className: allCorrect ? "text-success" : "text-error"
19184
+ }
19185
+ ),
19186
+ /* @__PURE__ */ jsx(Typography, { variant: "body", weight: "bold", children: allCorrect ? str(resolved.successMessage) || t("classifier.allCorrect") : `${correctCount}/${items.length} ${t("classifier.correct")}` }),
19187
+ !allCorrect && failMessage && /* @__PURE__ */ jsx(Typography, { variant: "body", className: "text-muted-foreground", children: failMessage })
19188
+ ] }) }),
19189
+ showHint && hint && /* @__PURE__ */ jsx(Card, { className: "p-4 border-l-4 border-l-warning", children: /* @__PURE__ */ jsx(Typography, { variant: "body", children: hint }) }),
19190
+ /* @__PURE__ */ jsxs(HStack, { gap: "sm", justify: "center", children: [
19191
+ !submitted && /* @__PURE__ */ jsxs(Button, { variant: "primary", onClick: handleSubmit, disabled: !allAssigned, children: [
19192
+ /* @__PURE__ */ jsx(GameIcon, { icon: Send, assetUrl: ui?.["send"], size: "sm" }),
19193
+ t("classifier.check")
19194
+ ] }),
19195
+ /* @__PURE__ */ jsxs(Button, { variant: "secondary", onClick: handleFullReset, children: [
19196
+ /* @__PURE__ */ jsx(GameIcon, { icon: RotateCcw, assetUrl: ui?.["reset"], size: "sm" }),
19197
+ t("classifier.reset")
19198
+ ] })
19199
+ ] })
19200
+ ] })
19201
+ }
19202
+ );
19203
+ }
19204
+ var init_ClassifierBoard = __esm({
19205
+ "components/game/2d/organisms/ClassifierBoard.tsx"() {
19206
+ init_atoms();
19207
+ init_useEventBus();
19208
+ init_boardEntity();
19209
+ init_GameIcon();
19210
+ ClassifierBoard.displayName = "ClassifierBoard";
19211
+ }
19212
+ });
18834
19213
  var CodeRunnerPanel;
18835
19214
  var init_CodeRunnerPanel = __esm({
18836
19215
  "components/core/organisms/CodeRunnerPanel.tsx"() {
@@ -19264,9 +19643,9 @@ function ControlButton({
19264
19643
  className
19265
19644
  }) {
19266
19645
  const eventBus = useEventBus();
19267
- const [isPressed, setIsPressed] = React72.useState(false);
19646
+ const [isPressed, setIsPressed] = React74.useState(false);
19268
19647
  const actualPressed = pressed ?? isPressed;
19269
- const handlePointerDown = React72.useCallback(
19648
+ const handlePointerDown = React74.useCallback(
19270
19649
  (e) => {
19271
19650
  e.preventDefault();
19272
19651
  if (disabled) return;
@@ -19276,7 +19655,7 @@ function ControlButton({
19276
19655
  },
19277
19656
  [disabled, pressEvent, eventBus, onPress]
19278
19657
  );
19279
- const handlePointerUp = React72.useCallback(
19658
+ const handlePointerUp = React74.useCallback(
19280
19659
  (e) => {
19281
19660
  e.preventDefault();
19282
19661
  if (disabled) return;
@@ -19286,7 +19665,7 @@ function ControlButton({
19286
19665
  },
19287
19666
  [disabled, releaseEvent, eventBus, onRelease]
19288
19667
  );
19289
- const handlePointerLeave = React72.useCallback(
19668
+ const handlePointerLeave = React74.useCallback(
19290
19669
  (e) => {
19291
19670
  if (isPressed) {
19292
19671
  setIsPressed(false);
@@ -19379,8 +19758,8 @@ function ControlGrid({
19379
19758
  className
19380
19759
  }) {
19381
19760
  const eventBus = useEventBus();
19382
- const [active, setActive] = React72.useState(/* @__PURE__ */ new Set());
19383
- const handlePress = React72.useCallback(
19761
+ const [active, setActive] = React74.useState(/* @__PURE__ */ new Set());
19762
+ const handlePress = React74.useCallback(
19384
19763
  (id) => {
19385
19764
  setActive((prev) => new Set(prev).add(id));
19386
19765
  if (actionEvent) eventBus.emit(`UI:${actionEvent}`, { id, pressed: true });
@@ -19394,7 +19773,7 @@ function ControlGrid({
19394
19773
  },
19395
19774
  [kind, actionEvent, directionEvent, directionEvents, eventBus, onAction, onDirection]
19396
19775
  );
19397
- const handleRelease = React72.useCallback(
19776
+ const handleRelease = React74.useCallback(
19398
19777
  (id) => {
19399
19778
  setActive((prev) => {
19400
19779
  const next = new Set(prev);
@@ -20660,8 +21039,8 @@ var init_Menu = __esm({
20660
21039
  "bottom-end": "bottom-start"
20661
21040
  };
20662
21041
  const effectivePosition = direction === "rtl" ? rtlMirror[position] ?? position : position;
20663
- const triggerChild = React72__default.isValidElement(trigger) ? trigger : /* @__PURE__ */ jsx(Typography, { variant: "small", as: "span", children: trigger });
20664
- const triggerElement = React72__default.cloneElement(
21042
+ const triggerChild = React74__default.isValidElement(trigger) ? trigger : /* @__PURE__ */ jsx(Typography, { variant: "small", as: "span", children: trigger });
21043
+ const triggerElement = React74__default.cloneElement(
20665
21044
  triggerChild,
20666
21045
  {
20667
21046
  ref: triggerRef,
@@ -20756,14 +21135,14 @@ function useDataDnd(args) {
20756
21135
  const isZone = Boolean(dragGroup || accepts || sortable);
20757
21136
  const enabled = isZone || Boolean(dndRoot);
20758
21137
  const eventBus = useEventBus();
20759
- const parentRoot = React72__default.useContext(RootCtx);
21138
+ const parentRoot = React74__default.useContext(RootCtx);
20760
21139
  const isRoot = enabled && parentRoot === null;
20761
- const zoneId = React72__default.useId();
21140
+ const zoneId = React74__default.useId();
20762
21141
  const ownGroup = dragGroup ?? accepts ?? zoneId;
20763
- const [optimisticOrders, setOptimisticOrders] = React72__default.useState(() => /* @__PURE__ */ new Map());
20764
- const optimisticOrdersRef = React72__default.useRef(optimisticOrders);
21142
+ const [optimisticOrders, setOptimisticOrders] = React74__default.useState(() => /* @__PURE__ */ new Map());
21143
+ const optimisticOrdersRef = React74__default.useRef(optimisticOrders);
20765
21144
  optimisticOrdersRef.current = optimisticOrders;
20766
- const clearOptimisticOrder = React72__default.useCallback((group) => {
21145
+ const clearOptimisticOrder = React74__default.useCallback((group) => {
20767
21146
  setOptimisticOrders((prev) => {
20768
21147
  if (!prev.has(group)) return prev;
20769
21148
  const next = new Map(prev);
@@ -20788,7 +21167,7 @@ function useDataDnd(args) {
20788
21167
  const raw = it[dndItemIdField];
20789
21168
  return raw != null ? String(raw) : `__idx_${idx}`;
20790
21169
  }).join("|");
20791
- const itemIds = React72__default.useMemo(
21170
+ const itemIds = React74__default.useMemo(
20792
21171
  () => orderedItems.map((it, idx) => {
20793
21172
  const raw = it[dndItemIdField];
20794
21173
  return raw != null ? String(raw) : `__idx_${idx}`;
@@ -20799,7 +21178,7 @@ function useDataDnd(args) {
20799
21178
  const raw = it[dndItemIdField];
20800
21179
  return raw != null ? String(raw) : `__${idx}`;
20801
21180
  }).join("|");
20802
- React72__default.useEffect(() => {
21181
+ React74__default.useEffect(() => {
20803
21182
  const root = isRoot ? null : parentRoot;
20804
21183
  if (root) {
20805
21184
  root.clearOptimisticOrder(ownGroup);
@@ -20807,20 +21186,20 @@ function useDataDnd(args) {
20807
21186
  clearOptimisticOrder(ownGroup);
20808
21187
  }
20809
21188
  }, [itemsContentSig, ownGroup]);
20810
- const zonesRef = React72__default.useRef(/* @__PURE__ */ new Map());
20811
- const registerZone = React72__default.useCallback((zoneId2, meta2) => {
21189
+ const zonesRef = React74__default.useRef(/* @__PURE__ */ new Map());
21190
+ const registerZone = React74__default.useCallback((zoneId2, meta2) => {
20812
21191
  zonesRef.current.set(zoneId2, meta2);
20813
21192
  }, []);
20814
- const unregisterZone = React72__default.useCallback((zoneId2) => {
21193
+ const unregisterZone = React74__default.useCallback((zoneId2) => {
20815
21194
  zonesRef.current.delete(zoneId2);
20816
21195
  }, []);
20817
- const [activeDrag, setActiveDrag] = React72__default.useState(null);
20818
- const [overZoneGroup, setOverZoneGroup] = React72__default.useState(null);
20819
- const meta = React72__default.useMemo(
21196
+ const [activeDrag, setActiveDrag] = React74__default.useState(null);
21197
+ const [overZoneGroup, setOverZoneGroup] = React74__default.useState(null);
21198
+ const meta = React74__default.useMemo(
20820
21199
  () => ({ group: ownGroup, dropEvent, reorderEvent, positionEvent, itemIds, rawItems: items, idField: dndItemIdField }),
20821
21200
  [ownGroup, dropEvent, reorderEvent, positionEvent, itemIds, items, dndItemIdField]
20822
21201
  );
20823
- React72__default.useEffect(() => {
21202
+ React74__default.useEffect(() => {
20824
21203
  const target = isRoot ? null : parentRoot;
20825
21204
  if (!target) {
20826
21205
  zonesRef.current.set(zoneId, meta);
@@ -20839,7 +21218,7 @@ function useDataDnd(args) {
20839
21218
  }, [parentRoot, isRoot, zoneId, meta]);
20840
21219
  const sensors = useAlmadarDndSensors(true);
20841
21220
  const collisionDetection = almadarDndCollisionDetection;
20842
- const findZoneByItem = React72__default.useCallback(
21221
+ const findZoneByItem = React74__default.useCallback(
20843
21222
  (id) => {
20844
21223
  for (const z of zonesRef.current.values()) {
20845
21224
  if (z.itemIds.includes(id)) return z;
@@ -20848,7 +21227,7 @@ function useDataDnd(args) {
20848
21227
  },
20849
21228
  []
20850
21229
  );
20851
- React72__default.useCallback(
21230
+ React74__default.useCallback(
20852
21231
  (group) => {
20853
21232
  for (const z of zonesRef.current.values()) {
20854
21233
  if (z.group === group) return z;
@@ -20857,7 +21236,7 @@ function useDataDnd(args) {
20857
21236
  },
20858
21237
  []
20859
21238
  );
20860
- const handleDragEnd = React72__default.useCallback(
21239
+ const handleDragEnd = React74__default.useCallback(
20861
21240
  (event) => {
20862
21241
  const { active, over } = event;
20863
21242
  const activeIdStr = String(active.id);
@@ -20948,8 +21327,8 @@ function useDataDnd(args) {
20948
21327
  },
20949
21328
  [eventBus]
20950
21329
  );
20951
- const sortableData = React72__default.useMemo(() => ({ dndGroup: ownGroup }), [ownGroup]);
20952
- const SortableItem = React72__default.useCallback(
21330
+ const sortableData = React74__default.useMemo(() => ({ dndGroup: ownGroup }), [ownGroup]);
21331
+ const SortableItem = React74__default.useCallback(
20953
21332
  ({ id, children }) => {
20954
21333
  const {
20955
21334
  attributes,
@@ -20989,7 +21368,7 @@ function useDataDnd(args) {
20989
21368
  id: droppableId,
20990
21369
  data: sortableData
20991
21370
  });
20992
- const ctx = React72__default.useContext(RootCtx);
21371
+ const ctx = React74__default.useContext(RootCtx);
20993
21372
  const activeDrag2 = ctx?.activeDrag ?? null;
20994
21373
  const overZoneGroup2 = ctx?.overZoneGroup ?? null;
20995
21374
  const isThisZoneOver = overZoneGroup2 === ownGroup;
@@ -21004,7 +21383,7 @@ function useDataDnd(args) {
21004
21383
  showForeignPlaceholder,
21005
21384
  ctxAvailable: ctx != null
21006
21385
  });
21007
- React72__default.useEffect(() => {
21386
+ React74__default.useEffect(() => {
21008
21387
  dndLog.info("dropzone:isOver:change", { droppableId, group: ownGroup, isOver, isThisZoneOver, showForeignPlaceholder, activeDragSourceGroup: activeDrag2?.sourceGroup ?? null });
21009
21388
  }, [droppableId, isOver, isThisZoneOver, showForeignPlaceholder]);
21010
21389
  return /* @__PURE__ */ jsx(
@@ -21018,11 +21397,11 @@ function useDataDnd(args) {
21018
21397
  }
21019
21398
  );
21020
21399
  };
21021
- const rootContextValue = React72__default.useMemo(
21400
+ const rootContextValue = React74__default.useMemo(
21022
21401
  () => ({ registerZone, unregisterZone, activeDrag, overZoneGroup, optimisticOrders, clearOptimisticOrder }),
21023
21402
  [registerZone, unregisterZone, activeDrag, overZoneGroup, optimisticOrders, clearOptimisticOrder]
21024
21403
  );
21025
- const handleDragStart = React72__default.useCallback((event) => {
21404
+ const handleDragStart = React74__default.useCallback((event) => {
21026
21405
  const sourceZone = findZoneByItem(event.active.id);
21027
21406
  const rect = event.active.rect.current.initial;
21028
21407
  const height = rect?.height && rect.height > 0 ? rect.height : 64;
@@ -21041,7 +21420,7 @@ function useDataDnd(args) {
21041
21420
  isRoot
21042
21421
  });
21043
21422
  }, [findZoneByItem, isRoot, zoneId]);
21044
- const handleDragOver = React72__default.useCallback((event) => {
21423
+ const handleDragOver = React74__default.useCallback((event) => {
21045
21424
  const { active, over } = event;
21046
21425
  const overData = over?.data?.current;
21047
21426
  const overGroup = overData?.dndGroup ?? null;
@@ -21111,7 +21490,7 @@ function useDataDnd(args) {
21111
21490
  return next;
21112
21491
  });
21113
21492
  }, []);
21114
- const handleDragCancel = React72__default.useCallback((event) => {
21493
+ const handleDragCancel = React74__default.useCallback((event) => {
21115
21494
  setActiveDrag(null);
21116
21495
  setOverZoneGroup(null);
21117
21496
  dndLog.warn("dragCancel", {
@@ -21119,12 +21498,12 @@ function useDataDnd(args) {
21119
21498
  reason: "dnd-kit cancelled the drag (escape key, pointer interrupted, or external)"
21120
21499
  });
21121
21500
  }, []);
21122
- const handleDragEndWithCleanup = React72__default.useCallback((event) => {
21501
+ const handleDragEndWithCleanup = React74__default.useCallback((event) => {
21123
21502
  handleDragEnd(event);
21124
21503
  setActiveDrag(null);
21125
21504
  setOverZoneGroup(null);
21126
21505
  }, [handleDragEnd]);
21127
- const wrapContainer = React72__default.useCallback(
21506
+ const wrapContainer = React74__default.useCallback(
21128
21507
  (children) => {
21129
21508
  if (!enabled) return children;
21130
21509
  const strategy = layout === "grid" ? rectSortingStrategy : verticalListSortingStrategy;
@@ -21178,7 +21557,7 @@ var init_useDataDnd = __esm({
21178
21557
  init_useAlmadarDndCollision();
21179
21558
  init_Box();
21180
21559
  dndLog = createLogger("almadar:ui:dnd");
21181
- RootCtx = React72__default.createContext(null);
21560
+ RootCtx = React74__default.createContext(null);
21182
21561
  }
21183
21562
  });
21184
21563
  function renderIconInput(icon, props) {
@@ -21704,7 +22083,7 @@ function DataList({
21704
22083
  }) {
21705
22084
  const eventBus = useEventBus();
21706
22085
  const { t } = useTranslate();
21707
- const [visibleCount, setVisibleCount] = React72__default.useState(pageSize || Infinity);
22086
+ const [visibleCount, setVisibleCount] = React74__default.useState(pageSize || Infinity);
21708
22087
  const fieldDefs = fields ?? columns ?? [];
21709
22088
  const allDataRaw = Array.isArray(entity) ? entity : entity ? [entity] : [];
21710
22089
  const dnd = useDataDnd({
@@ -21723,7 +22102,7 @@ function DataList({
21723
22102
  const data = pageSize > 0 ? allData.slice(0, visibleCount) : allData;
21724
22103
  const hasMoreLocal = pageSize > 0 && visibleCount < allData.length;
21725
22104
  const hasRenderProp = typeof children === "function";
21726
- React72__default.useEffect(() => {
22105
+ React74__default.useEffect(() => {
21727
22106
  const renderItemTypeOf = typeof schemaRenderItem;
21728
22107
  const childrenTypeOf = typeof children;
21729
22108
  if (data.length > 0 && !hasRenderProp) {
@@ -21827,7 +22206,7 @@ function DataList({
21827
22206
  const items2 = [...data];
21828
22207
  const groups2 = groupBy ? groupData(items2, groupBy) : [{ label: "", items: items2 }];
21829
22208
  const contentField = titleField?.name ?? fieldDefs[0]?.name ?? "";
21830
- return /* @__PURE__ */ jsx(VStack, { gap: "sm", className: cn("py-2", className), children: groups2.map((group, gi) => /* @__PURE__ */ jsxs(React72__default.Fragment, { children: [
22209
+ return /* @__PURE__ */ jsx(VStack, { gap: "sm", className: cn("py-2", className), children: groups2.map((group, gi) => /* @__PURE__ */ jsxs(React74__default.Fragment, { children: [
21831
22210
  group.label && /* @__PURE__ */ jsx(Divider, { label: group.label, className: "my-2" }),
21832
22211
  group.items.map((itemData, index) => {
21833
22212
  const id = itemData.id || `${gi}-${index}`;
@@ -21968,7 +22347,7 @@ function DataList({
21968
22347
  className
21969
22348
  ),
21970
22349
  children: [
21971
- groups.map((group, gi) => /* @__PURE__ */ jsxs(React72__default.Fragment, { children: [
22350
+ groups.map((group, gi) => /* @__PURE__ */ jsxs(React74__default.Fragment, { children: [
21972
22351
  group.label && /* @__PURE__ */ jsx(Divider, { label: group.label, className: gi > 0 ? "mt-4" : "mt-0" }),
21973
22352
  group.items.map(
21974
22353
  (itemData, index) => renderItem(itemData, index, gi === groups.length - 1 && index === group.items.length - 1)
@@ -22075,8 +22454,8 @@ function ScalarControl({
22075
22454
  }
22076
22455
  const numeric = typeof value === "number";
22077
22456
  const initial = value === null ? "" : String(value);
22078
- const [draft, setDraft] = React72__default.useState(initial);
22079
- React72__default.useEffect(() => setDraft(initial), [initial]);
22457
+ const [draft, setDraft] = React74__default.useState(initial);
22458
+ React74__default.useEffect(() => setDraft(initial), [initial]);
22080
22459
  const commit = () => {
22081
22460
  if (numeric) {
22082
22461
  const n = draft.trim() === "" ? 0 : Number(draft);
@@ -22144,8 +22523,8 @@ function Row({
22144
22523
  onRemove,
22145
22524
  readonly
22146
22525
  }) {
22147
- const [keyDraft, setKeyDraft] = React72__default.useState(rowKey);
22148
- React72__default.useEffect(() => setKeyDraft(rowKey), [rowKey]);
22526
+ const [keyDraft, setKeyDraft] = React74__default.useState(rowKey);
22527
+ React74__default.useEffect(() => setKeyDraft(rowKey), [rowKey]);
22149
22528
  const container = isObj(value) || isArr(value);
22150
22529
  return /* @__PURE__ */ jsxs(VStack, { gap: "none", className: "group w-max min-w-full", children: [
22151
22530
  /* @__PURE__ */ jsxs(HStack, { gap: "xs", align: "center", className: "py-0.5 w-max", children: [
@@ -22188,7 +22567,7 @@ function ContainerNode({
22188
22567
  depth,
22189
22568
  readonly
22190
22569
  }) {
22191
- const [open, setOpen] = React72__default.useState(depth < 2);
22570
+ const [open, setOpen] = React74__default.useState(depth < 2);
22192
22571
  const array = isArr(value);
22193
22572
  const entries = array ? value.map((v, i) => [String(i), v]) : Object.entries(value);
22194
22573
  const setObjValue = (key, next) => {
@@ -22330,7 +22709,7 @@ var init_FormSection = __esm({
22330
22709
  columns = 1,
22331
22710
  className
22332
22711
  }) => {
22333
- const [collapsed, setCollapsed] = React72__default.useState(defaultCollapsed);
22712
+ const [collapsed, setCollapsed] = React74__default.useState(defaultCollapsed);
22334
22713
  const { t } = useTranslate();
22335
22714
  const eventBus = useEventBus();
22336
22715
  const gridClass = {
@@ -22338,7 +22717,7 @@ var init_FormSection = __esm({
22338
22717
  2: "grid-cols-1 md:grid-cols-2",
22339
22718
  3: "grid-cols-1 md:grid-cols-2 lg:grid-cols-3"
22340
22719
  }[columns];
22341
- React72__default.useCallback(() => {
22720
+ React74__default.useCallback(() => {
22342
22721
  if (collapsible) {
22343
22722
  setCollapsed((prev) => !prev);
22344
22723
  eventBus.emit("UI:TOGGLE_COLLAPSE", { collapsed: !collapsed });
@@ -22746,8 +23125,8 @@ function TextLikeControl({
22746
23125
  onCommit
22747
23126
  }) {
22748
23127
  const initial = value === void 0 || value === null ? "" : String(value);
22749
- const [draft, setDraft] = React72__default.useState(initial);
22750
- React72__default.useEffect(() => setDraft(initial), [initial]);
23128
+ const [draft, setDraft] = React74__default.useState(initial);
23129
+ React74__default.useEffect(() => setDraft(initial), [initial]);
22751
23130
  const commit = () => {
22752
23131
  if (numeric) {
22753
23132
  const n = draft.trim() === "" ? 0 : Number(draft);
@@ -22932,14 +23311,14 @@ var init_NodeSlotEditor = __esm({
22932
23311
  isObj2 = (v) => v !== null && v !== void 0 && typeof v === "object" && !Array.isArray(v);
22933
23312
  NodeSlotEditor = ({ value, onChange, className }) => {
22934
23313
  const { type, props, wasArray } = normalize(value);
22935
- const patterns = React72__default.useMemo(() => {
23314
+ const patterns = React74__default.useMemo(() => {
22936
23315
  try {
22937
23316
  return [...getKnownPatterns()].sort();
22938
23317
  } catch {
22939
23318
  return [];
22940
23319
  }
22941
23320
  }, []);
22942
- const options = React72__default.useMemo(
23321
+ const options = React74__default.useMemo(
22943
23322
  () => [{ value: "", label: "\u2014 none \u2014" }, ...patterns.map((p) => ({ value: p, label: p }))],
22944
23323
  [patterns]
22945
23324
  );
@@ -22951,7 +23330,7 @@ var init_NodeSlotEditor = __esm({
22951
23330
  const pattern = { type: nextType, ...nextProps };
22952
23331
  onChange(wasArray || value === void 0 ? [pattern] : pattern);
22953
23332
  };
22954
- const schemaEntries = React72__default.useMemo(() => {
23333
+ const schemaEntries = React74__default.useMemo(() => {
22955
23334
  if (!type) return [];
22956
23335
  const def = getPatternDefinition(type);
22957
23336
  if (!def?.propsSchema) return [];
@@ -23853,7 +24232,7 @@ var init_Flex = __esm({
23853
24232
  flexStyle.flexBasis = typeof basis === "number" ? `${basis}px` : basis;
23854
24233
  }
23855
24234
  }
23856
- return React72__default.createElement(Component, {
24235
+ return React74__default.createElement(Component, {
23857
24236
  className: cn(
23858
24237
  inline ? "inline-flex" : "flex",
23859
24238
  directionStyles[direction],
@@ -23972,7 +24351,7 @@ var init_Grid = __esm({
23972
24351
  as: Component = "div"
23973
24352
  }) => {
23974
24353
  const mergedStyle = rows2 ? { gridTemplateRows: `repeat(${rows2}, minmax(0, 1fr))`, ...style } : style;
23975
- return React72__default.createElement(
24354
+ return React74__default.createElement(
23976
24355
  Component,
23977
24356
  {
23978
24357
  className: cn(
@@ -24168,9 +24547,9 @@ var init_Popover = __esm({
24168
24547
  onMouseLeave: handleClose,
24169
24548
  onPointerDown: tapTriggerProps.onPointerDown
24170
24549
  };
24171
- const childElement = React72__default.isValidElement(children) ? children : /* @__PURE__ */ jsx("span", { children });
24550
+ const childElement = React74__default.isValidElement(children) ? children : /* @__PURE__ */ jsx("span", { children });
24172
24551
  const childPointerDown = childElement.props.onPointerDown;
24173
- const triggerElement = React72__default.cloneElement(
24552
+ const triggerElement = React74__default.cloneElement(
24174
24553
  childElement,
24175
24554
  {
24176
24555
  ref: triggerRef,
@@ -25022,9 +25401,9 @@ var init_Tooltip = __esm({
25022
25401
  if (hideTimeoutRef.current) clearTimeout(hideTimeoutRef.current);
25023
25402
  };
25024
25403
  }, []);
25025
- const triggerElement = React72__default.isValidElement(children) ? children : /* @__PURE__ */ jsx("span", { children });
25404
+ const triggerElement = React74__default.isValidElement(children) ? children : /* @__PURE__ */ jsx("span", { children });
25026
25405
  const childPointerDown = triggerElement.props.onPointerDown;
25027
- const trigger = React72__default.cloneElement(triggerElement, {
25406
+ const trigger = React74__default.cloneElement(triggerElement, {
25028
25407
  ref: triggerRef,
25029
25408
  onMouseEnter: handleMouseEnter,
25030
25409
  onMouseLeave: handleMouseLeave,
@@ -25114,7 +25493,7 @@ var init_WizardProgress = __esm({
25114
25493
  children: /* @__PURE__ */ jsx("div", { className: "flex items-center gap-2", children: normalizedSteps.map((step, index) => {
25115
25494
  const isActive = index === currentStep;
25116
25495
  const isCompleted = index < currentStep;
25117
- return /* @__PURE__ */ jsxs(React72__default.Fragment, { children: [
25496
+ return /* @__PURE__ */ jsxs(React74__default.Fragment, { children: [
25118
25497
  /* @__PURE__ */ jsx(
25119
25498
  "button",
25120
25499
  {
@@ -26162,42 +26541,6 @@ var init_effects = __esm({
26162
26541
  }
26163
26542
  });
26164
26543
 
26165
- // components/game/shared/boardEntity.ts
26166
- function boardEntity(entity) {
26167
- if (!entity) return void 0;
26168
- return Array.isArray(entity) ? entity[0] : entity;
26169
- }
26170
- function str(v) {
26171
- return v == null ? "" : String(v);
26172
- }
26173
- function num(v, fallback = 0) {
26174
- const n = Number(v);
26175
- return Number.isFinite(n) ? n : fallback;
26176
- }
26177
- function bool(v) {
26178
- return Boolean(v);
26179
- }
26180
- function rows(v) {
26181
- return Array.isArray(v) ? v : [];
26182
- }
26183
- function vec2(v) {
26184
- const o = v ?? {};
26185
- return { x: num(o.x), y: num(o.y) };
26186
- }
26187
- function unitPosition(u) {
26188
- return vec2(u.position);
26189
- }
26190
- function unitTeam(u) {
26191
- return str(u.team);
26192
- }
26193
- function unitHealth(u) {
26194
- return num(u.health);
26195
- }
26196
- var init_boardEntity = __esm({
26197
- "components/game/shared/boardEntity.ts"() {
26198
- }
26199
- });
26200
-
26201
26544
  // components/game/shared/makeAsset.ts
26202
26545
  function makeAsset(url, role, overrides = {}) {
26203
26546
  const defaults = ROLE_DEFAULTS[role] ?? { dimension: "2d", animations: ["static"], aspect: "1:1" };
@@ -26263,7 +26606,7 @@ function GameCard({
26263
26606
  className
26264
26607
  }) {
26265
26608
  const eventBus = useEventBus();
26266
- const handleClick = React72.useCallback(() => {
26609
+ const handleClick = React74.useCallback(() => {
26267
26610
  if (disabled) return;
26268
26611
  onClick?.(id);
26269
26612
  if (clickEvent) eventBus.emit(`UI:${clickEvent}`, { cardId: id });
@@ -27155,7 +27498,7 @@ function InventoryGrid({
27155
27498
  const eventBus = useEventBus();
27156
27499
  const slotCount = totalSlots ?? items.length;
27157
27500
  const emptySlotCount = Math.max(0, slotCount - items.length);
27158
- const handleSelect = React72.useCallback(
27501
+ const handleSelect = React74.useCallback(
27159
27502
  (id) => {
27160
27503
  onSelect?.(id);
27161
27504
  if (selectEvent) {
@@ -27372,7 +27715,7 @@ function GameMenu({
27372
27715
  }) {
27373
27716
  const resolvedOptions = options ?? menuItems ?? DEFAULT_MENU_OPTIONS;
27374
27717
  const eventBus = useEventBus();
27375
- const handleOptionClick = React72.useCallback(
27718
+ const handleOptionClick = React74.useCallback(
27376
27719
  (option) => {
27377
27720
  if (option.event) {
27378
27721
  eventBus.emit(`UI:${option.event}`, { option });
@@ -27449,6 +27792,214 @@ var init_GameMenu = __esm({
27449
27792
  GameMenu.displayName = "GameMenu";
27450
27793
  }
27451
27794
  });
27795
+ function StateNode2({
27796
+ name,
27797
+ isCurrent = false,
27798
+ isSelected = false,
27799
+ isInitial = false,
27800
+ position,
27801
+ onClick,
27802
+ className
27803
+ }) {
27804
+ return /* @__PURE__ */ jsx(
27805
+ Box,
27806
+ {
27807
+ position: "absolute",
27808
+ display: "flex",
27809
+ className: cn(
27810
+ "items-center justify-center rounded-pill border-3 transition-all cursor-pointer select-none",
27811
+ "min-w-[80px] h-[80px] px-3",
27812
+ isCurrent && "bg-primary/20 border-primary shadow-lg shadow-primary/30 scale-110",
27813
+ isSelected && !isCurrent && "bg-accent/20 border-accent ring-2 ring-accent/50",
27814
+ !isCurrent && !isSelected && "bg-card border-border hover:border-muted-foreground hover:scale-105",
27815
+ className
27816
+ ),
27817
+ style: {
27818
+ left: position.x,
27819
+ top: position.y,
27820
+ transform: "translate(-50%, -50%)"
27821
+ },
27822
+ onClick,
27823
+ children: /* @__PURE__ */ jsxs(Box, { className: "text-center", children: [
27824
+ isInitial && /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-muted-foreground text-xs block", children: "\u25B6 start" }),
27825
+ /* @__PURE__ */ jsx(
27826
+ Typography,
27827
+ {
27828
+ variant: "body2",
27829
+ className: cn(
27830
+ "font-bold whitespace-nowrap",
27831
+ isCurrent ? "text-primary" : "text-foreground"
27832
+ ),
27833
+ children: name
27834
+ }
27835
+ )
27836
+ ] })
27837
+ }
27838
+ );
27839
+ }
27840
+ var init_StateNode = __esm({
27841
+ "components/game/2d/organisms/StateNode.tsx"() {
27842
+ init_atoms();
27843
+ init_cn();
27844
+ StateNode2.displayName = "StateNode";
27845
+ }
27846
+ });
27847
+ function TransitionArrow({
27848
+ from,
27849
+ to,
27850
+ eventLabel,
27851
+ guardHint,
27852
+ isActive = false,
27853
+ onClick,
27854
+ className
27855
+ }) {
27856
+ const dx = to.x - from.x;
27857
+ const dy = to.y - from.y;
27858
+ const dist = Math.sqrt(dx * dx + dy * dy);
27859
+ if (dist === 0) return /* @__PURE__ */ jsx(Fragment, {});
27860
+ const nx = dx / dist;
27861
+ const ny = dy / dist;
27862
+ const startX = from.x + nx * NODE_RADIUS;
27863
+ const startY = from.y + ny * NODE_RADIUS;
27864
+ const endX = to.x - nx * NODE_RADIUS;
27865
+ const endY = to.y - ny * NODE_RADIUS;
27866
+ const midX = (startX + endX) / 2;
27867
+ const midY = (startY + endY) / 2;
27868
+ const perpX = -ny * 20;
27869
+ const perpY = nx * 20;
27870
+ const ctrlX = midX + perpX;
27871
+ const ctrlY = midY + perpY;
27872
+ const path = `M ${startX} ${startY} Q ${ctrlX} ${ctrlY} ${endX} ${endY}`;
27873
+ return /* @__PURE__ */ jsxs("g", { className: cn("cursor-pointer", className), onClick, children: [
27874
+ /* @__PURE__ */ jsx(
27875
+ "path",
27876
+ {
27877
+ d: path,
27878
+ fill: "none",
27879
+ stroke: isActive ? "var(--color-primary)" : "var(--color-border)",
27880
+ strokeWidth: isActive ? 3 : 2,
27881
+ markerEnd: isActive ? "url(#arrowhead-active)" : "url(#arrowhead)"
27882
+ }
27883
+ ),
27884
+ /* @__PURE__ */ jsx(
27885
+ "text",
27886
+ {
27887
+ x: ctrlX,
27888
+ y: ctrlY - 8,
27889
+ textAnchor: "middle",
27890
+ fill: isActive ? "var(--color-primary)" : "var(--color-foreground)",
27891
+ fontSize: 12,
27892
+ fontWeight: isActive ? "bold" : "normal",
27893
+ className: "select-none",
27894
+ children: eventLabel
27895
+ }
27896
+ ),
27897
+ guardHint && /* @__PURE__ */ jsx(
27898
+ "text",
27899
+ {
27900
+ x: ctrlX,
27901
+ y: ctrlY + 6,
27902
+ textAnchor: "middle",
27903
+ fill: "var(--color-warning)",
27904
+ fontSize: 10,
27905
+ className: "select-none",
27906
+ children: "\u26A0 " + guardHint
27907
+ }
27908
+ )
27909
+ ] });
27910
+ }
27911
+ var NODE_RADIUS;
27912
+ var init_TransitionArrow = __esm({
27913
+ "components/game/2d/organisms/TransitionArrow.tsx"() {
27914
+ init_cn();
27915
+ NODE_RADIUS = 40;
27916
+ TransitionArrow.displayName = "TransitionArrow";
27917
+ }
27918
+ });
27919
+ function layoutStates(states, width, height) {
27920
+ const cx = width / 2;
27921
+ const cy = height / 2;
27922
+ const radius = Math.min(cx, cy) - 60;
27923
+ const positions = {};
27924
+ states.forEach((state, i) => {
27925
+ const angle = 2 * Math.PI * i / Math.max(states.length, 1) - Math.PI / 2;
27926
+ positions[state] = { x: cx + radius * Math.cos(angle), y: cy + radius * Math.sin(angle) };
27927
+ });
27928
+ return positions;
27929
+ }
27930
+ function StateGraph({
27931
+ states,
27932
+ transitions = [],
27933
+ currentState,
27934
+ selectedState,
27935
+ addingFrom,
27936
+ initialState,
27937
+ width = 500,
27938
+ height = 400,
27939
+ nodeClickEvent,
27940
+ className
27941
+ }) {
27942
+ const eventBus = useEventBus();
27943
+ const nodes = states ?? [];
27944
+ const positions = React74.useMemo(() => layoutStates(nodes, width, height), [nodes, width, height]);
27945
+ return /* @__PURE__ */ jsxs(
27946
+ Box,
27947
+ {
27948
+ position: "relative",
27949
+ className: cn("rounded-container border border-border bg-background overflow-hidden", className),
27950
+ style: { width, height },
27951
+ children: [
27952
+ /* @__PURE__ */ jsxs("svg", { width, height, className: "absolute inset-0", style: { pointerEvents: "none" }, children: [
27953
+ /* @__PURE__ */ jsxs("defs", { children: [
27954
+ /* @__PURE__ */ jsx("marker", { id: "arrowhead", markerWidth: "10", markerHeight: "7", refX: "10", refY: "3.5", orient: "auto", children: /* @__PURE__ */ jsx("polygon", { points: "0 0, 10 3.5, 0 7", fill: "var(--color-border)" }) }),
27955
+ /* @__PURE__ */ jsx("marker", { id: "arrowhead-active", markerWidth: "10", markerHeight: "7", refX: "10", refY: "3.5", orient: "auto", children: /* @__PURE__ */ jsx("polygon", { points: "0 0, 10 3.5, 0 7", fill: "var(--color-primary)" }) })
27956
+ ] }),
27957
+ transitions.map((tr, i) => {
27958
+ const fromPos = positions[tr.from];
27959
+ const toPos = positions[tr.to];
27960
+ if (!fromPos || !toPos) return null;
27961
+ return /* @__PURE__ */ jsx(
27962
+ TransitionArrow,
27963
+ {
27964
+ from: fromPos,
27965
+ to: toPos,
27966
+ eventLabel: tr.event,
27967
+ guardHint: tr.guardHint,
27968
+ isActive: tr.from === currentState
27969
+ },
27970
+ `${tr.from}-${tr.event}-${tr.to}-${i}`
27971
+ );
27972
+ })
27973
+ ] }),
27974
+ nodes.map((state) => {
27975
+ const pos = positions[state];
27976
+ if (!pos) return null;
27977
+ return /* @__PURE__ */ jsx(
27978
+ StateNode2,
27979
+ {
27980
+ name: state,
27981
+ position: pos,
27982
+ isCurrent: state === currentState,
27983
+ isSelected: state === selectedState || state === addingFrom,
27984
+ isInitial: state === initialState,
27985
+ onClick: nodeClickEvent ? () => eventBus.emit(`UI:${nodeClickEvent}`, { stateId: state }) : void 0
27986
+ },
27987
+ state
27988
+ );
27989
+ })
27990
+ ]
27991
+ }
27992
+ );
27993
+ }
27994
+ var init_StateGraph = __esm({
27995
+ "components/game/2d/molecules/StateGraph.tsx"() {
27996
+ init_atoms();
27997
+ init_cn();
27998
+ init_useEventBus();
27999
+ init_StateNode();
28000
+ init_TransitionArrow();
28001
+ }
28002
+ });
27452
28003
  function pickPath(entry) {
27453
28004
  if (Array.isArray(entry.path)) {
27454
28005
  return entry.path[Math.floor(Math.random() * entry.path.length)];
@@ -27826,7 +28377,7 @@ function LinearView({
27826
28377
  /* @__PURE__ */ jsx(HStack, { className: "flex-wrap items-center", gap: "xs", children: trait.states.map((state, i) => {
27827
28378
  const isDone = i < currentIdx;
27828
28379
  const isCurrent = i === currentIdx;
27829
- return /* @__PURE__ */ jsxs(React72__default.Fragment, { children: [
28380
+ return /* @__PURE__ */ jsxs(React74__default.Fragment, { children: [
27830
28381
  i > 0 && /* @__PURE__ */ jsx(
27831
28382
  Typography,
27832
28383
  {
@@ -28023,7 +28574,7 @@ function TraitStateViewer({
28023
28574
  }
28024
28575
  var SIZE_CONFIG2;
28025
28576
  var init_TraitStateViewer = __esm({
28026
- "components/game/2d/molecules/TraitStateViewer.tsx"() {
28577
+ "components/game/2d/organisms/TraitStateViewer.tsx"() {
28027
28578
  "use client";
28028
28579
  init_cn();
28029
28580
  init_Box();
@@ -28230,7 +28781,7 @@ function TraitSlot({
28230
28781
  }
28231
28782
  var SIZE_CONFIG3, DRAG_MIME2;
28232
28783
  var init_TraitSlot = __esm({
28233
- "components/game/2d/molecules/TraitSlot.tsx"() {
28784
+ "components/game/2d/organisms/TraitSlot.tsx"() {
28234
28785
  "use client";
28235
28786
  init_cn();
28236
28787
  init_useEventBus();
@@ -28436,8 +28987,6 @@ function SequenceBar({
28436
28987
  maxSlots,
28437
28988
  onSlotDrop,
28438
28989
  onSlotRemove,
28439
- slotDropEvent,
28440
- slotRemoveEvent,
28441
28990
  playing = false,
28442
28991
  currentStep = -1,
28443
28992
  categoryColors,
@@ -28445,19 +28994,16 @@ function SequenceBar({
28445
28994
  size = "lg",
28446
28995
  className
28447
28996
  }) {
28448
- const { emit } = useEventBus();
28449
28997
  const handleDrop = useCallback((index) => (item) => {
28450
28998
  if (playing) return;
28451
- if (slotDropEvent) emit(`UI:${slotDropEvent}`, { slotIndex: index, actionId: item.id });
28452
- onSlotDrop?.(index, item);
28453
- }, [onSlotDrop, slotDropEvent, emit, playing]);
28999
+ onSlotDrop(index, item);
29000
+ }, [onSlotDrop, playing]);
28454
29001
  const handleRemove = useCallback((index) => () => {
28455
29002
  if (playing) return;
28456
- if (slotRemoveEvent) emit(`UI:${slotRemoveEvent}`, { slotIndex: index });
28457
- onSlotRemove?.(index);
28458
- }, [onSlotRemove, slotRemoveEvent, emit, playing]);
29003
+ onSlotRemove(index);
29004
+ }, [onSlotRemove, playing]);
28459
29005
  const paddedSlots = Array.from({ length: maxSlots }, (_, i) => slots[i]);
28460
- return /* @__PURE__ */ jsx(HStack, { className: cn("items-center", className), gap: "sm", children: paddedSlots.map((slot, i) => /* @__PURE__ */ jsxs(React72__default.Fragment, { children: [
29006
+ return /* @__PURE__ */ jsx(HStack, { className: cn("items-center", className), gap: "sm", children: paddedSlots.map((slot, i) => /* @__PURE__ */ jsxs(React74__default.Fragment, { children: [
28461
29007
  i > 0 && /* @__PURE__ */ jsx(
28462
29008
  Typography,
28463
29009
  {
@@ -28487,14 +29033,281 @@ function SequenceBar({
28487
29033
  ] }, i)) });
28488
29034
  }
28489
29035
  var init_SequenceBar = __esm({
28490
- "components/game/2d/molecules/SequenceBar.tsx"() {
29036
+ "components/game/2d/organisms/SequenceBar.tsx"() {
28491
29037
  init_atoms();
28492
29038
  init_cn();
28493
- init_useEventBus();
28494
29039
  init_TraitSlot();
28495
29040
  SequenceBar.displayName = "SequenceBar";
28496
29041
  }
28497
29042
  });
29043
+ function computeSlotFeedback(playerSeq, solutions) {
29044
+ let bestSolution = solutions[0];
29045
+ let bestMatches = -1;
29046
+ for (const sol of solutions) {
29047
+ const matches = sol.filter((id, i) => id === playerSeq[i]).length;
29048
+ if (matches > bestMatches) {
29049
+ bestMatches = matches;
29050
+ bestSolution = sol;
29051
+ }
29052
+ }
29053
+ return playerSeq.map(
29054
+ (id, i) => id !== void 0 && id === bestSolution[i] ? "correct" : "wrong"
29055
+ );
29056
+ }
29057
+ function isFieldRecord(v) {
29058
+ return typeof v === "object" && v !== null && !Array.isArray(v) && !(v instanceof Date);
29059
+ }
29060
+ function assetFromField(v) {
29061
+ if (!isFieldRecord(v)) return void 0;
29062
+ const url = typeof v.url === "string" ? v.url : void 0;
29063
+ const role = typeof v.role === "string" ? v.role : void 0;
29064
+ const category = typeof v.category === "string" ? v.category : "";
29065
+ if (!url || !role) return void 0;
29066
+ return {
29067
+ url,
29068
+ role,
29069
+ category,
29070
+ name: typeof v.name === "string" ? v.name : void 0,
29071
+ thumbnailUrl: typeof v.thumbnailUrl === "string" ? v.thumbnailUrl : void 0,
29072
+ style: typeof v.style === "string" ? v.style : void 0,
29073
+ variant: typeof v.variant === "string" ? v.variant : void 0,
29074
+ dimension: typeof v.dimension === "string" ? v.dimension : void 0,
29075
+ aspect: typeof v.aspect === "string" ? v.aspect : void 0
29076
+ };
29077
+ }
29078
+ function slotItemFromField(fv) {
29079
+ if (!isFieldRecord(fv)) return void 0;
29080
+ const id = typeof fv.id === "string" ? fv.id : void 0;
29081
+ const name = typeof fv.name === "string" ? fv.name : void 0;
29082
+ const category = typeof fv.category === "string" ? fv.category : void 0;
29083
+ if (!id || !name || !category) return void 0;
29084
+ return {
29085
+ id,
29086
+ name,
29087
+ category,
29088
+ description: typeof fv.description === "string" ? fv.description : void 0,
29089
+ iconEmoji: typeof fv.iconEmoji === "string" ? fv.iconEmoji : void 0,
29090
+ iconUrl: assetFromField(fv.iconUrl)
29091
+ };
29092
+ }
29093
+ function SequencerBoard({
29094
+ entity,
29095
+ categoryColors,
29096
+ stepDurationMs = 1e3,
29097
+ playEvent,
29098
+ completeEvent,
29099
+ placeEvent,
29100
+ removeEvent,
29101
+ checkEvent,
29102
+ playAgainEvent,
29103
+ stepEvent,
29104
+ className
29105
+ }) {
29106
+ const { emit } = useEventBus();
29107
+ const { t } = useTranslate();
29108
+ const resolved = boardEntity(entity);
29109
+ const maxSlots = num(resolved?.maxSlots) || 3;
29110
+ const solutions = Array.isArray(resolved?.solutions) ? resolved.solutions : [];
29111
+ const availableActions = (Array.isArray(resolved?.availableActions) ? resolved.availableActions : []).reduce((acc, fv) => {
29112
+ const item = slotItemFromField(fv);
29113
+ if (item) acc.push(item);
29114
+ return acc;
29115
+ }, []);
29116
+ const allowDuplicates = resolved?.allowDuplicates !== false;
29117
+ const entitySlots = Array.isArray(resolved?.slots) ? resolved.slots : [];
29118
+ const entityResult = str(resolved?.result);
29119
+ const entityAttempts = num(resolved?.attempts);
29120
+ const entityCurrentStep = typeof resolved?.currentStep === "number" ? resolved.currentStep : -1;
29121
+ const slots = Array.from({ length: maxSlots }, (_, i) => {
29122
+ const entitySlot = entitySlots.find((s) => s.index === i);
29123
+ if (!entitySlot?.placedActionId) return void 0;
29124
+ return availableActions.find((a) => a.id === entitySlot.placedActionId);
29125
+ });
29126
+ const isSuccess = entityResult === "win";
29127
+ const attempts = entityAttempts;
29128
+ const isPlayingBack = entityCurrentStep >= 0 && !isSuccess;
29129
+ const currentStep = entityCurrentStep;
29130
+ const [headerError, setHeaderError] = useState(false);
29131
+ const [slotFeedback, setSlotFeedback] = useState(
29132
+ () => Array.from({ length: maxSlots }, () => null)
29133
+ );
29134
+ const timerRef = useRef(null);
29135
+ useEffect(() => () => {
29136
+ if (timerRef.current) clearTimeout(timerRef.current);
29137
+ }, []);
29138
+ const handleSlotDrop = useCallback((index, item) => {
29139
+ setSlotFeedback((prev) => {
29140
+ const next = [...prev];
29141
+ next[index] = null;
29142
+ return next;
29143
+ });
29144
+ emit("UI:PLAY_SOUND", { key: "drop_slot" });
29145
+ if (placeEvent) emit(`UI:${placeEvent}`, { slotIndex: index, actionId: item.id });
29146
+ }, [emit, placeEvent]);
29147
+ const handleSlotRemove = useCallback((index) => {
29148
+ setSlotFeedback((prev) => {
29149
+ const next = [...prev];
29150
+ next[index] = null;
29151
+ return next;
29152
+ });
29153
+ emit("UI:PLAY_SOUND", { key: "back" });
29154
+ if (removeEvent) emit(`UI:${removeEvent}`, { slotIndex: index });
29155
+ }, [emit, removeEvent]);
29156
+ const handleReset = useCallback(() => {
29157
+ if (timerRef.current) clearTimeout(timerRef.current);
29158
+ setSlotFeedback(Array.from({ length: maxSlots }, () => null));
29159
+ if (playAgainEvent) emit(`UI:${playAgainEvent}`, {});
29160
+ }, [maxSlots, playAgainEvent, emit]);
29161
+ const filledSlots = slots.filter((s) => !!s);
29162
+ const canPlay = filledSlots.length > 0 && !isPlayingBack && !isSuccess;
29163
+ const handlePlay = useCallback(() => {
29164
+ if (!canPlay) return;
29165
+ setSlotFeedback(Array.from({ length: maxSlots }, () => null));
29166
+ emit("UI:PLAY_SOUND", { key: "confirm" });
29167
+ const sequence = slots.map((s) => s?.id || "");
29168
+ const playerIds = slots.filter(Boolean).map((s) => s?.id || "");
29169
+ if (playEvent) emit(`UI:${playEvent}`, { sequence });
29170
+ let step = 0;
29171
+ const advance = () => {
29172
+ step++;
29173
+ if (stepEvent) emit(`UI:${stepEvent}`, { step });
29174
+ if (step >= maxSlots) {
29175
+ if (checkEvent) emit(`UI:${checkEvent}`, { sequence: playerIds });
29176
+ const playerSeq = slots.map((s) => s?.id);
29177
+ const success = solutions.some(
29178
+ (sol) => sol.length === playerIds.length && sol.every((id, i) => id === playerIds[i])
29179
+ );
29180
+ if (success) {
29181
+ emit("UI:PLAY_SOUND", { key: "levelComplete" });
29182
+ if (completeEvent) emit(`UI:${completeEvent}`, { success: true, sequence: playerIds });
29183
+ } else {
29184
+ const feedback = computeSlotFeedback(playerSeq, solutions);
29185
+ setSlotFeedback(feedback);
29186
+ emit("UI:PLAY_SOUND", { key: "fail" });
29187
+ const correctCount2 = feedback.filter((f3) => f3 === "correct").length;
29188
+ for (let ci = 0; ci < correctCount2; ci++) {
29189
+ setTimeout(() => {
29190
+ emit("UI:PLAY_SOUND", { key: "correctSlot" });
29191
+ }, 300 + ci * 150);
29192
+ }
29193
+ }
29194
+ } else {
29195
+ timerRef.current = setTimeout(advance, stepDurationMs);
29196
+ }
29197
+ };
29198
+ timerRef.current = setTimeout(advance, stepDurationMs);
29199
+ }, [canPlay, slots, maxSlots, solutions, stepDurationMs, playEvent, completeEvent, checkEvent, emit]);
29200
+ const machine = {
29201
+ name: str(resolved?.title),
29202
+ description: str(resolved?.description),
29203
+ states: slots.map((s, i) => stepLabel(s, i)),
29204
+ currentState: currentStep >= 0 ? stepLabel(slots[currentStep], currentStep) : "__idle__",
29205
+ transitions: slots.slice(0, -1).map((s, i) => ({
29206
+ from: stepLabel(s, i),
29207
+ to: stepLabel(slots[i + 1], i + 1),
29208
+ event: "NEXT"
29209
+ }))
29210
+ };
29211
+ const usedIds = !allowDuplicates ? slots.filter(Boolean).map((s) => s?.id || "") : [];
29212
+ const hint = str(resolved?.hint);
29213
+ const showHint = attempts >= 3 && !!hint;
29214
+ const hasFeedback = slotFeedback.some((f3) => f3 !== null);
29215
+ const correctCount = slotFeedback.filter((f3) => f3 === "correct").length;
29216
+ const encourageKey = ENCOURAGEMENT_KEYS[Math.min(attempts - 1, ENCOURAGEMENT_KEYS.length - 1)] ?? ENCOURAGEMENT_KEYS[0];
29217
+ if (!resolved) return null;
29218
+ const theme = resolved.theme ?? void 0;
29219
+ const themeBackground = theme?.background;
29220
+ const headerImage = str(resolved.headerImage);
29221
+ return /* @__PURE__ */ jsxs(
29222
+ VStack,
29223
+ {
29224
+ className: cn("p-4 gap-6", className),
29225
+ style: {
29226
+ backgroundImage: themeBackground ? `url(${themeBackground})` : void 0,
29227
+ backgroundSize: "cover",
29228
+ backgroundPosition: "center"
29229
+ },
29230
+ children: [
29231
+ headerImage && !headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 overflow-hidden rounded-container", children: /* @__PURE__ */ jsx("img", { src: headerImage, alt: "", onError: () => setHeaderError(true), className: "w-full h-full object-cover" }) }) : headerImage && headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 rounded-container bg-gradient-to-br from-muted to-accent opacity-60" }) : null,
29232
+ /* @__PURE__ */ jsxs(VStack, { gap: "xs", children: [
29233
+ /* @__PURE__ */ jsx(Typography, { variant: "h4", className: "text-foreground", children: str(resolved.title) }),
29234
+ /* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground", children: str(resolved.description) })
29235
+ ] }),
29236
+ showHint && /* @__PURE__ */ jsx(Box, { className: "p-3 rounded-container bg-accent/10 border border-accent/30", children: /* @__PURE__ */ jsxs(HStack, { className: "items-start", gap: "xs", children: [
29237
+ /* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-accent font-bold shrink-0", children: "\u{1F4A1} " + t("game.hint") + ":" }),
29238
+ /* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-foreground", children: hint })
29239
+ ] }) }),
29240
+ filledSlots.length > 0 && /* @__PURE__ */ jsx(TraitStateViewer, { trait: machine, variant: "linear", size: "md" }),
29241
+ /* @__PURE__ */ jsxs(VStack, { gap: "xs", children: [
29242
+ /* @__PURE__ */ jsxs(HStack, { className: "items-center justify-between", children: [
29243
+ /* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground font-medium", children: t("sequencer.yourSequence") + ":" }),
29244
+ hasFeedback && !isPlayingBack && !isSuccess && /* @__PURE__ */ jsxs(Typography, { variant: "caption", className: "text-muted-foreground", children: [
29245
+ `${correctCount}/${maxSlots} `,
29246
+ "\u2705"
29247
+ ] })
29248
+ ] }),
29249
+ /* @__PURE__ */ jsx(
29250
+ SequenceBar,
29251
+ {
29252
+ slots,
29253
+ maxSlots,
29254
+ onSlotDrop: handleSlotDrop,
29255
+ onSlotRemove: handleSlotRemove,
29256
+ playing: isPlayingBack,
29257
+ currentStep,
29258
+ categoryColors,
29259
+ slotFeedback,
29260
+ size: "lg"
29261
+ }
29262
+ )
29263
+ ] }),
29264
+ !isPlayingBack && /* @__PURE__ */ jsx(
29265
+ ActionPalette,
29266
+ {
29267
+ actions: availableActions,
29268
+ usedActionIds: usedIds,
29269
+ allowDuplicates,
29270
+ categoryColors,
29271
+ label: t("sequencer.dragActions")
29272
+ }
29273
+ ),
29274
+ hasFeedback && !isPlayingBack && !isSuccess && attempts > 0 && /* @__PURE__ */ jsx(Box, { className: "p-3 rounded-container bg-warning/10 border border-warning/30 text-center", children: /* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-foreground", children: t(encourageKey) }) }),
29275
+ isSuccess && /* @__PURE__ */ jsx(Box, { className: "p-4 rounded-container bg-success/20 border border-success text-center", children: /* @__PURE__ */ jsx(Typography, { variant: "h5", className: "text-success", children: str(resolved.successMessage) || t("sequencer.levelComplete") }) }),
29276
+ /* @__PURE__ */ jsxs(HStack, { gap: "sm", children: [
29277
+ /* @__PURE__ */ jsx(
29278
+ Button,
29279
+ {
29280
+ variant: "primary",
29281
+ onClick: handlePlay,
29282
+ disabled: !canPlay,
29283
+ children: "\u25B6 " + t("game.play")
29284
+ }
29285
+ ),
29286
+ /* @__PURE__ */ jsx(Button, { variant: "ghost", onClick: handleReset, children: "\u21BA " + t("game.reset") })
29287
+ ] })
29288
+ ]
29289
+ }
29290
+ );
29291
+ }
29292
+ var ENCOURAGEMENT_KEYS, stepLabel;
29293
+ var init_SequencerBoard = __esm({
29294
+ "components/game/2d/organisms/SequencerBoard.tsx"() {
29295
+ init_atoms();
29296
+ init_cn();
29297
+ init_useEventBus();
29298
+ init_TraitStateViewer();
29299
+ init_boardEntity();
29300
+ init_SequenceBar();
29301
+ init_ActionPalette();
29302
+ ENCOURAGEMENT_KEYS = [
29303
+ "puzzle.tryAgain1",
29304
+ "puzzle.tryAgain2",
29305
+ "puzzle.tryAgain3"
29306
+ ];
29307
+ stepLabel = (slot, i) => slot ? `${i + 1}. ${slot.name}` : `Step ${i + 1}`;
29308
+ SequencerBoard.displayName = "SequencerBoard";
29309
+ }
29310
+ });
28498
29311
  function RuleEditor({
28499
29312
  rule,
28500
29313
  availableEvents,
@@ -28538,7 +29351,7 @@ function RuleEditor({
28538
29351
  ] });
28539
29352
  }
28540
29353
  var init_RuleEditor = __esm({
28541
- "components/game/2d/molecules/RuleEditor.tsx"() {
29354
+ "components/game/2d/organisms/RuleEditor.tsx"() {
28542
29355
  init_atoms();
28543
29356
  init_cn();
28544
29357
  RuleEditor.displayName = "RuleEditor";
@@ -28579,7 +29392,7 @@ function EventLog({
28579
29392
  }
28580
29393
  var STATUS_STYLES, STATUS_DOTS;
28581
29394
  var init_EventLog = __esm({
28582
- "components/game/2d/molecules/EventLog.tsx"() {
29395
+ "components/game/2d/organisms/EventLog.tsx"() {
28583
29396
  init_atoms();
28584
29397
  init_cn();
28585
29398
  STATUS_STYLES = {
@@ -28707,7 +29520,7 @@ function ObjectRulePanel({
28707
29520
  }
28708
29521
  var nextRuleId;
28709
29522
  var init_ObjectRulePanel = __esm({
28710
- "components/game/2d/molecules/ObjectRulePanel.tsx"() {
29523
+ "components/game/2d/organisms/ObjectRulePanel.tsx"() {
28711
29524
  init_atoms();
28712
29525
  init_cn();
28713
29526
  init_TraitStateViewer();
@@ -28717,128 +29530,218 @@ var init_ObjectRulePanel = __esm({
28717
29530
  ObjectRulePanel.displayName = "ObjectRulePanel";
28718
29531
  }
28719
29532
  });
28720
- function StateNode2({
28721
- name,
28722
- isCurrent = false,
28723
- isSelected = false,
28724
- isInitial = false,
28725
- position,
28726
- onClick,
29533
+ function EventHandlerBoard({
29534
+ entity,
29535
+ stepDurationMs = 800,
29536
+ playEvent,
29537
+ completeEvent,
29538
+ editRuleEvent,
29539
+ playAgainEvent,
28727
29540
  className
28728
29541
  }) {
28729
- return /* @__PURE__ */ jsx(
28730
- Box,
29542
+ const { emit } = useEventBus();
29543
+ const { t } = useTranslate();
29544
+ const resolved = boardEntity(entity);
29545
+ const objects = rows(resolved?.objects);
29546
+ const entityResult = str(resolved?.result) || "none";
29547
+ const isSuccess = entityResult === "win";
29548
+ const attempts = typeof resolved?.attempts === "number" ? resolved.attempts : 0;
29549
+ const [selectedObjectId, setSelectedObjectId] = useState(
29550
+ objects[0] ? objId(objects[0]) : null
29551
+ );
29552
+ const [headerError, setHeaderError] = useState(false);
29553
+ const [isPlaying, setIsPlaying] = useState(false);
29554
+ const [eventLog, setEventLog] = useState([]);
29555
+ const timerRef = useRef(null);
29556
+ const logIdCounter = useRef(0);
29557
+ useEffect(() => () => {
29558
+ if (timerRef.current) clearTimeout(timerRef.current);
29559
+ }, []);
29560
+ const selectedObject = objects.find((o) => objId(o) === selectedObjectId) ?? null;
29561
+ const handleRulesChange = useCallback((objectId, rules) => {
29562
+ if (editRuleEvent) emit(`UI:${editRuleEvent}`, { objectId, rules });
29563
+ }, [editRuleEvent, emit]);
29564
+ const addLogEntry = useCallback((icon, message, status = "done") => {
29565
+ const id = `log-${logIdCounter.current++}`;
29566
+ setEventLog((prev) => [...prev, { id, timestamp: Date.now(), icon, message, status }]);
29567
+ }, []);
29568
+ const handlePlay = useCallback(() => {
29569
+ if (isPlaying || isSuccess) return;
29570
+ if (playEvent) emit(`UI:${playEvent}`, {});
29571
+ setIsPlaying(true);
29572
+ setEventLog([]);
29573
+ const allRules = [];
29574
+ objects.forEach((obj) => {
29575
+ objRules(obj).forEach((rule) => {
29576
+ allRules.push({ object: obj, rule });
29577
+ });
29578
+ });
29579
+ const triggers = Array.isArray(resolved?.triggerEvents) ? resolved.triggerEvents : [];
29580
+ const goalEvent = str(resolved?.goalEvent);
29581
+ const eventQueue = [...triggers];
29582
+ const firedEvents = /* @__PURE__ */ new Set();
29583
+ let stepIdx = 0;
29584
+ let goalReached = false;
29585
+ const processNext = () => {
29586
+ if (eventQueue.length === 0 || stepIdx > 20) {
29587
+ setIsPlaying(false);
29588
+ if (goalReached && completeEvent) emit(`UI:${completeEvent}`, { success: true });
29589
+ return;
29590
+ }
29591
+ const currentEvent = eventQueue.shift();
29592
+ if (firedEvents.has(currentEvent)) {
29593
+ timerRef.current = setTimeout(processNext, 100);
29594
+ return;
29595
+ }
29596
+ firedEvents.add(currentEvent);
29597
+ const matching = allRules.filter((r) => r.rule.whenEvent === currentEvent);
29598
+ if (matching.length === 0) {
29599
+ addLogEntry("\u26A1", t("eventHandler.noListeners", { event: currentEvent }), "done");
29600
+ } else {
29601
+ matching.forEach(({ object, rule }) => {
29602
+ addLogEntry(objIcon(object), t("eventHandler.heardEvent", { object: objName(object), event: currentEvent, action: rule.thenAction }), "done");
29603
+ eventQueue.push(rule.thenAction);
29604
+ if (rule.thenAction === goalEvent) {
29605
+ goalReached = true;
29606
+ }
29607
+ });
29608
+ }
29609
+ if (currentEvent === goalEvent) {
29610
+ goalReached = true;
29611
+ }
29612
+ stepIdx++;
29613
+ timerRef.current = setTimeout(processNext, stepDurationMs);
29614
+ };
29615
+ if (triggers.length > 0) {
29616
+ addLogEntry("\u{1F3AC}", t("eventHandler.simulationStarted", { events: triggers.join(", ") }), "active");
29617
+ }
29618
+ timerRef.current = setTimeout(processNext, stepDurationMs);
29619
+ }, [isPlaying, isSuccess, objects, resolved, stepDurationMs, playEvent, completeEvent, emit, addLogEntry, t]);
29620
+ const handleTryAgain = useCallback(() => {
29621
+ if (timerRef.current) clearTimeout(timerRef.current);
29622
+ setIsPlaying(false);
29623
+ setEventLog([]);
29624
+ }, []);
29625
+ const handleReset = useCallback(() => {
29626
+ if (timerRef.current) clearTimeout(timerRef.current);
29627
+ setIsPlaying(false);
29628
+ setEventLog([]);
29629
+ setSelectedObjectId(objects[0] ? objId(objects[0]) : null);
29630
+ if (playAgainEvent) emit(`UI:${playAgainEvent}`, {});
29631
+ }, [objects, playAgainEvent, emit]);
29632
+ if (!resolved) return null;
29633
+ const objectViewers = objects.map((obj) => {
29634
+ const states = objStates(obj);
29635
+ const currentState = objCurrentState(obj);
29636
+ const machine = {
29637
+ name: objName(obj),
29638
+ states,
29639
+ currentState,
29640
+ transitions: objRules(obj).map((r) => ({
29641
+ from: currentState,
29642
+ to: states.find((s) => s !== currentState) || currentState,
29643
+ event: r.whenEvent
29644
+ }))
29645
+ };
29646
+ return { obj, machine };
29647
+ });
29648
+ const hint = str(resolved.hint);
29649
+ const showHint = attempts >= 3 && hint;
29650
+ const theme = resolved.theme ?? void 0;
29651
+ const themeBackground = theme?.background;
29652
+ const headerImage = str(resolved.headerImage);
29653
+ const encourageKey = ENCOURAGEMENT_KEYS2[Math.min(attempts - 1, ENCOURAGEMENT_KEYS2.length - 1)] ?? ENCOURAGEMENT_KEYS2[0];
29654
+ return /* @__PURE__ */ jsxs(
29655
+ VStack,
28731
29656
  {
28732
- position: "absolute",
28733
- display: "flex",
28734
- className: cn(
28735
- "items-center justify-center rounded-pill border-3 transition-all cursor-pointer select-none",
28736
- "min-w-[80px] h-[80px] px-3",
28737
- isCurrent && "bg-primary/20 border-primary shadow-lg shadow-primary/30 scale-110",
28738
- isSelected && !isCurrent && "bg-accent/20 border-accent ring-2 ring-accent/50",
28739
- !isCurrent && !isSelected && "bg-card border-border hover:border-muted-foreground hover:scale-105",
28740
- className
28741
- ),
29657
+ className: cn("p-4 gap-6", className),
28742
29658
  style: {
28743
- left: position.x,
28744
- top: position.y,
28745
- transform: "translate(-50%, -50%)"
29659
+ backgroundImage: themeBackground ? `url(${themeBackground})` : void 0,
29660
+ backgroundSize: "cover",
29661
+ backgroundPosition: "center"
28746
29662
  },
28747
- onClick,
28748
- children: /* @__PURE__ */ jsxs(Box, { className: "text-center", children: [
28749
- isInitial && /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-muted-foreground text-xs block", children: "\u25B6 start" }),
28750
- /* @__PURE__ */ jsx(
28751
- Typography,
29663
+ children: [
29664
+ headerImage && !headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 overflow-hidden rounded-container", children: /* @__PURE__ */ jsx("img", { src: headerImage, alt: "", onError: () => setHeaderError(true), className: "w-full h-full object-cover" }) }) : headerImage && headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 rounded-container bg-gradient-to-br from-muted to-accent opacity-60" }) : null,
29665
+ /* @__PURE__ */ jsxs(VStack, { gap: "xs", children: [
29666
+ /* @__PURE__ */ jsx(Typography, { variant: "h4", className: "text-foreground", children: str(resolved.title) }),
29667
+ /* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground", children: str(resolved.description) }),
29668
+ /* @__PURE__ */ jsxs(HStack, { className: "items-center p-2 rounded bg-primary/10 border border-primary/30", gap: "xs", children: [
29669
+ /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-primary font-bold", children: t("game.goal") + ":" }),
29670
+ /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-foreground", children: str(resolved.goalCondition) })
29671
+ ] })
29672
+ ] }),
29673
+ /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
29674
+ /* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground font-medium", children: t("eventHandler.clickObject") + ":" }),
29675
+ /* @__PURE__ */ jsx(HStack, { className: "flex-wrap", gap: "sm", children: objectViewers.map(({ obj, machine }) => {
29676
+ const oid = objId(obj);
29677
+ return /* @__PURE__ */ jsx(
29678
+ Box,
29679
+ {
29680
+ className: cn(
29681
+ "p-3 rounded-container border-2 cursor-pointer transition-all hover:scale-105",
29682
+ selectedObjectId === oid ? "border-primary bg-primary/10" : "border-border bg-card hover:border-muted-foreground"
29683
+ ),
29684
+ onClick: () => setSelectedObjectId(oid),
29685
+ children: /* @__PURE__ */ jsxs(VStack, { gap: "xs", className: "items-center min-w-[120px]", children: [
29686
+ /* @__PURE__ */ jsx(Typography, { variant: "h5", children: objIcon(obj) }),
29687
+ /* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-foreground font-medium", children: objName(obj) }),
29688
+ /* @__PURE__ */ jsx(TraitStateViewer, { trait: machine, variant: "compact", size: "sm" })
29689
+ ] })
29690
+ },
29691
+ oid
29692
+ );
29693
+ }) })
29694
+ ] }),
29695
+ selectedObject && /* @__PURE__ */ jsx(
29696
+ ObjectRulePanel,
28752
29697
  {
28753
- variant: "body2",
28754
- className: cn(
28755
- "font-bold whitespace-nowrap",
28756
- isCurrent ? "text-primary" : "text-foreground"
28757
- ),
28758
- children: name
29698
+ object: selectedObject,
29699
+ onRulesChange: handleRulesChange,
29700
+ disabled: isPlaying
28759
29701
  }
28760
- )
28761
- ] })
29702
+ ),
29703
+ eventLog.length > 0 && /* @__PURE__ */ jsx(EventLog, { entries: eventLog }),
29704
+ isSuccess && /* @__PURE__ */ jsx(Box, { className: "p-4 rounded-container bg-success/20 border border-success text-center", children: /* @__PURE__ */ jsx(Typography, { variant: "h5", className: "text-success", children: str(resolved.successMessage) || t("eventHandler.chainComplete") }) }),
29705
+ !isPlaying && !isSuccess && attempts > 0 && /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
29706
+ /* @__PURE__ */ jsx(Box, { className: "p-4 rounded-container bg-warning/10 border border-warning/30 text-center", children: /* @__PURE__ */ jsx(Typography, { variant: "body1", className: "text-foreground font-medium", children: t(encourageKey) }) }),
29707
+ showHint && /* @__PURE__ */ jsx(Box, { className: "p-3 rounded-container bg-accent/10 border border-accent/30", children: /* @__PURE__ */ jsxs(HStack, { className: "items-start", gap: "xs", children: [
29708
+ /* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-accent font-bold shrink-0", children: "\u{1F4A1} " + t("game.hint") + ":" }),
29709
+ /* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-foreground", children: hint })
29710
+ ] }) })
29711
+ ] }),
29712
+ /* @__PURE__ */ jsxs(HStack, { gap: "sm", children: [
29713
+ !isPlaying && !isSuccess && attempts > 0 ? /* @__PURE__ */ jsx(Button, { variant: "primary", onClick: handleTryAgain, children: "\u{1F504} " + t("puzzle.tryAgainButton") }) : /* @__PURE__ */ jsx(
29714
+ Button,
29715
+ {
29716
+ variant: "primary",
29717
+ onClick: handlePlay,
29718
+ disabled: isPlaying || isSuccess,
29719
+ children: "\u25B6 " + t("game.play")
29720
+ }
29721
+ ),
29722
+ /* @__PURE__ */ jsx(Button, { variant: "ghost", onClick: handleReset, children: "\u21BA " + t("game.reset") })
29723
+ ] })
29724
+ ]
28762
29725
  }
28763
29726
  );
28764
29727
  }
28765
- var init_StateNode = __esm({
28766
- "components/game/2d/molecules/StateNode.tsx"() {
29728
+ var ENCOURAGEMENT_KEYS2;
29729
+ var init_EventHandlerBoard = __esm({
29730
+ "components/game/2d/organisms/EventHandlerBoard.tsx"() {
28767
29731
  init_atoms();
28768
29732
  init_cn();
28769
- StateNode2.displayName = "StateNode";
28770
- }
28771
- });
28772
- function TransitionArrow({
28773
- from,
28774
- to,
28775
- eventLabel,
28776
- guardHint,
28777
- isActive = false,
28778
- onClick,
28779
- className
28780
- }) {
28781
- const dx = to.x - from.x;
28782
- const dy = to.y - from.y;
28783
- const dist = Math.sqrt(dx * dx + dy * dy);
28784
- if (dist === 0) return /* @__PURE__ */ jsx(Fragment, {});
28785
- const nx = dx / dist;
28786
- const ny = dy / dist;
28787
- const startX = from.x + nx * NODE_RADIUS;
28788
- const startY = from.y + ny * NODE_RADIUS;
28789
- const endX = to.x - nx * NODE_RADIUS;
28790
- const endY = to.y - ny * NODE_RADIUS;
28791
- const midX = (startX + endX) / 2;
28792
- const midY = (startY + endY) / 2;
28793
- const perpX = -ny * 20;
28794
- const perpY = nx * 20;
28795
- const ctrlX = midX + perpX;
28796
- const ctrlY = midY + perpY;
28797
- const path = `M ${startX} ${startY} Q ${ctrlX} ${ctrlY} ${endX} ${endY}`;
28798
- return /* @__PURE__ */ jsxs("g", { className: cn("cursor-pointer", className), onClick, children: [
28799
- /* @__PURE__ */ jsx(
28800
- "path",
28801
- {
28802
- d: path,
28803
- fill: "none",
28804
- stroke: isActive ? "var(--color-primary)" : "var(--color-border)",
28805
- strokeWidth: isActive ? 3 : 2,
28806
- markerEnd: isActive ? "url(#arrowhead-active)" : "url(#arrowhead)"
28807
- }
28808
- ),
28809
- /* @__PURE__ */ jsx(
28810
- "text",
28811
- {
28812
- x: ctrlX,
28813
- y: ctrlY - 8,
28814
- textAnchor: "middle",
28815
- fill: isActive ? "var(--color-primary)" : "var(--color-foreground)",
28816
- fontSize: 12,
28817
- fontWeight: isActive ? "bold" : "normal",
28818
- className: "select-none",
28819
- children: eventLabel
28820
- }
28821
- ),
28822
- guardHint && /* @__PURE__ */ jsx(
28823
- "text",
28824
- {
28825
- x: ctrlX,
28826
- y: ctrlY + 6,
28827
- textAnchor: "middle",
28828
- fill: "var(--color-warning)",
28829
- fontSize: 10,
28830
- className: "select-none",
28831
- children: "\u26A0 " + guardHint
28832
- }
28833
- )
28834
- ] });
28835
- }
28836
- var NODE_RADIUS;
28837
- var init_TransitionArrow = __esm({
28838
- "components/game/2d/molecules/TransitionArrow.tsx"() {
28839
- init_cn();
28840
- NODE_RADIUS = 40;
28841
- TransitionArrow.displayName = "TransitionArrow";
29733
+ init_useEventBus();
29734
+ init_TraitStateViewer();
29735
+ init_ObjectRulePanel();
29736
+ init_EventLog();
29737
+ init_puzzleObject();
29738
+ init_boardEntity();
29739
+ ENCOURAGEMENT_KEYS2 = [
29740
+ "puzzle.tryAgain1",
29741
+ "puzzle.tryAgain2",
29742
+ "puzzle.tryAgain3"
29743
+ ];
29744
+ EventHandlerBoard.displayName = "EventHandlerBoard";
28842
29745
  }
28843
29746
  });
28844
29747
  function VariablePanel({
@@ -28885,7 +29788,7 @@ function VariablePanel({
28885
29788
  }
28886
29789
  var numField;
28887
29790
  var init_VariablePanel = __esm({
28888
- "components/game/2d/molecules/VariablePanel.tsx"() {
29791
+ "components/game/2d/organisms/VariablePanel.tsx"() {
28889
29792
  init_atoms();
28890
29793
  init_cn();
28891
29794
  numField = (v, fallback = 0) => {
@@ -28920,12 +29823,890 @@ function StateJsonView({
28920
29823
  ] });
28921
29824
  }
28922
29825
  var init_StateJsonView = __esm({
28923
- "components/game/2d/molecules/StateJsonView.tsx"() {
29826
+ "components/game/2d/organisms/StateJsonView.tsx"() {
28924
29827
  init_atoms();
28925
29828
  init_cn();
28926
29829
  StateJsonView.displayName = "StateJsonView";
28927
29830
  }
28928
29831
  });
29832
+ function layoutStates2(states, width, height) {
29833
+ const cx = width / 2;
29834
+ const cy = height / 2;
29835
+ const radius = Math.min(cx, cy) - 60;
29836
+ const positions = {};
29837
+ states.forEach((state, i) => {
29838
+ const angle = 2 * Math.PI * i / states.length - Math.PI / 2;
29839
+ positions[state] = {
29840
+ x: cx + radius * Math.cos(angle),
29841
+ y: cy + radius * Math.sin(angle)
29842
+ };
29843
+ });
29844
+ return positions;
29845
+ }
29846
+ function StateArchitectBoard({
29847
+ entity,
29848
+ stepDurationMs = 600,
29849
+ testEvent,
29850
+ completeEvent,
29851
+ addTransitionEvent,
29852
+ removeTransitionEvent,
29853
+ playAgainEvent,
29854
+ className
29855
+ }) {
29856
+ const { emit } = useEventBus();
29857
+ const { t } = useTranslate();
29858
+ const resolved = boardEntity(entity);
29859
+ const entityStates = Array.isArray(resolved?.states) ? resolved.states : [];
29860
+ const initialState = str(resolved?.initialState);
29861
+ const entityName = str(resolved?.entityName);
29862
+ const availableEvents = Array.isArray(resolved?.availableEvents) ? resolved.availableEvents : [];
29863
+ const testCases = (Array.isArray(resolved?.testCases) ? resolved.testCases : []).map((item) => {
29864
+ const o = typeof item === "object" && item !== null && !Array.isArray(item) ? item : {};
29865
+ const eventsField = o["events"];
29866
+ return {
29867
+ events: Array.isArray(eventsField) ? eventsField : [],
29868
+ expectedState: str(o["expectedState"]),
29869
+ label: str(o["label"])
29870
+ };
29871
+ });
29872
+ const entityTransitions = (Array.isArray(resolved?.transitions) ? resolved.transitions : []).map((item) => {
29873
+ const o = typeof item === "object" && item !== null && !Array.isArray(item) ? item : {};
29874
+ return {
29875
+ id: str(o["id"]),
29876
+ from: str(o["from"]),
29877
+ to: str(o["to"]),
29878
+ event: str(o["event"]),
29879
+ ...o["guardHint"] ? { guardHint: str(o["guardHint"]) } : {}
29880
+ };
29881
+ });
29882
+ const entityVariables = rows(resolved?.variables);
29883
+ const transitions = entityTransitions;
29884
+ const attempts = typeof resolved?.attempts === "number" ? resolved.attempts : 0;
29885
+ const entityResult = str(resolved?.result) || "none";
29886
+ const isSuccess = entityResult === "win";
29887
+ const [isTesting, setIsTesting] = useState(false);
29888
+ const [headerError, setHeaderError] = useState(false);
29889
+ const [currentState, setCurrentState] = useState(initialState);
29890
+ const [selectedState, setSelectedState] = useState(null);
29891
+ const [testResults, setTestResults] = useState([]);
29892
+ const [variables, setVariables] = useState(() => [...entityVariables]);
29893
+ const timerRef = useRef(null);
29894
+ const [addingFrom, setAddingFrom] = useState(null);
29895
+ useEffect(() => () => {
29896
+ if (timerRef.current) clearTimeout(timerRef.current);
29897
+ }, []);
29898
+ const GRAPH_W = 500;
29899
+ const GRAPH_H = 400;
29900
+ const positions = useMemo(() => layoutStates2(entityStates, GRAPH_W, GRAPH_H), [entityStates]);
29901
+ const handleStateClick = useCallback((state) => {
29902
+ if (isTesting) return;
29903
+ if (addingFrom) {
29904
+ if (addingFrom !== state) {
29905
+ const event = availableEvents[0] || "EVENT";
29906
+ const newTrans = {
29907
+ id: `t-${nextTransId++}`,
29908
+ from: addingFrom,
29909
+ to: state,
29910
+ event
29911
+ };
29912
+ if (addTransitionEvent) emit(`UI:${addTransitionEvent}`, { id: newTrans.id, from: newTrans.from, to: newTrans.to, event: newTrans.event });
29913
+ }
29914
+ setAddingFrom(null);
29915
+ } else {
29916
+ setSelectedState(state);
29917
+ }
29918
+ }, [isTesting, addingFrom, availableEvents, addTransitionEvent, emit]);
29919
+ const handleStartAddTransition = useCallback(() => {
29920
+ if (!selectedState) return;
29921
+ setAddingFrom(selectedState);
29922
+ }, [selectedState]);
29923
+ const handleRemoveTransition = useCallback((transId) => {
29924
+ if (removeTransitionEvent) emit(`UI:${removeTransitionEvent}`, { id: transId });
29925
+ }, [removeTransitionEvent, emit]);
29926
+ const machine = useMemo(() => ({
29927
+ name: entityName,
29928
+ description: str(resolved?.description),
29929
+ states: entityStates,
29930
+ currentState,
29931
+ transitions: transitions.map((t2) => ({
29932
+ from: t2.from,
29933
+ to: t2.to,
29934
+ event: t2.event,
29935
+ guardHint: t2.guardHint
29936
+ }))
29937
+ }), [entityName, resolved, entityStates, currentState, transitions]);
29938
+ const handleTest = useCallback(() => {
29939
+ if (isTesting) return;
29940
+ if (testEvent) emit(`UI:${testEvent}`, {});
29941
+ setIsTesting(true);
29942
+ setTestResults([]);
29943
+ const results = [];
29944
+ let testIdx = 0;
29945
+ const runNextTest = () => {
29946
+ if (testIdx >= testCases.length) {
29947
+ const allPassed = results.every((r) => r.passed);
29948
+ setIsTesting(false);
29949
+ setTestResults(results);
29950
+ if (allPassed && completeEvent) {
29951
+ emit(`UI:${completeEvent}`, {
29952
+ success: true,
29953
+ passedTests: results.filter((r) => r.passed).length
29954
+ });
29955
+ }
29956
+ return;
29957
+ }
29958
+ const testCase = testCases[testIdx];
29959
+ if (!testCase) return;
29960
+ let state = initialState;
29961
+ for (const event of testCase.events) {
29962
+ const trans = transitions.find((t2) => t2.from === state && t2.event === event);
29963
+ if (trans) {
29964
+ state = trans.to;
29965
+ }
29966
+ }
29967
+ setCurrentState(state);
29968
+ results.push({
29969
+ label: testCase.label,
29970
+ passed: state === testCase.expectedState,
29971
+ actualState: state,
29972
+ expectedState: testCase.expectedState
29973
+ });
29974
+ testIdx++;
29975
+ timerRef.current = setTimeout(runNextTest, stepDurationMs);
29976
+ };
29977
+ timerRef.current = setTimeout(runNextTest, stepDurationMs);
29978
+ }, [isTesting, transitions, testCases, initialState, stepDurationMs, testEvent, completeEvent, emit]);
29979
+ const handleTryAgain = useCallback(() => {
29980
+ if (timerRef.current) clearTimeout(timerRef.current);
29981
+ setIsTesting(false);
29982
+ setCurrentState(initialState);
29983
+ setTestResults([]);
29984
+ }, [initialState]);
29985
+ const handleReset = useCallback(() => {
29986
+ if (timerRef.current) clearTimeout(timerRef.current);
29987
+ setIsTesting(false);
29988
+ setCurrentState(initialState);
29989
+ setTestResults([]);
29990
+ setVariables([...entityVariables]);
29991
+ setSelectedState(null);
29992
+ setAddingFrom(null);
29993
+ if (playAgainEvent) emit(`UI:${playAgainEvent}`, {});
29994
+ }, [initialState, entityVariables, playAgainEvent, emit]);
29995
+ const codeData = useMemo(() => ({
29996
+ name: entityName,
29997
+ states: entityStates,
29998
+ initialState,
29999
+ transitions: transitions.map((t2) => ({
30000
+ from: t2.from,
30001
+ to: t2.to,
30002
+ event: t2.event,
30003
+ ...t2.guardHint ? { guard: t2.guardHint } : {}
30004
+ }))
30005
+ }), [entityName, entityStates, initialState, transitions]);
30006
+ if (!resolved) return null;
30007
+ const theme = resolved.theme ?? void 0;
30008
+ const themeBackground = theme?.background;
30009
+ const headerImage = str(resolved.headerImage);
30010
+ const hint = str(resolved.hint);
30011
+ return /* @__PURE__ */ jsxs(
30012
+ VStack,
30013
+ {
30014
+ className: cn("p-4 gap-6", className),
30015
+ style: {
30016
+ backgroundImage: themeBackground ? `url(${themeBackground})` : void 0,
30017
+ backgroundSize: "cover",
30018
+ backgroundPosition: "center"
30019
+ },
30020
+ children: [
30021
+ headerImage && !headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 overflow-hidden rounded-container", children: /* @__PURE__ */ jsx("img", { src: headerImage, alt: "", onError: () => setHeaderError(true), className: "w-full h-full object-cover" }) }) : headerImage && headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 rounded-container bg-gradient-to-br from-muted to-accent opacity-60" }) : null,
30022
+ /* @__PURE__ */ jsxs(VStack, { gap: "xs", children: [
30023
+ /* @__PURE__ */ jsx(Typography, { variant: "h4", className: "text-foreground", children: str(resolved.title) }),
30024
+ /* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground", children: str(resolved.description) }),
30025
+ /* @__PURE__ */ jsxs(HStack, { className: "items-center p-2 rounded bg-warning/10 border border-warning/30", gap: "xs", children: [
30026
+ /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-warning font-bold", children: t("game.hint") + ":" }),
30027
+ /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-foreground", children: hint })
30028
+ ] })
30029
+ ] }),
30030
+ /* @__PURE__ */ jsxs(HStack, { className: "flex-wrap items-start", gap: "lg", children: [
30031
+ /* @__PURE__ */ jsxs(VStack, { gap: "sm", className: "flex-1 min-w-[300px]", children: [
30032
+ /* @__PURE__ */ jsxs(HStack, { className: "items-center justify-between", children: [
30033
+ /* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground font-medium", children: t("stateArchitect.graph") }),
30034
+ addingFrom && /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-accent animate-pulse", children: t("stateArchitect.clickTarget", { state: addingFrom || "" }) })
30035
+ ] }),
30036
+ /* @__PURE__ */ jsxs(
30037
+ Box,
30038
+ {
30039
+ position: "relative",
30040
+ className: "rounded-container border border-border bg-background overflow-hidden",
30041
+ style: { width: GRAPH_W, height: GRAPH_H },
30042
+ children: [
30043
+ /* @__PURE__ */ jsxs(
30044
+ "svg",
30045
+ {
30046
+ width: GRAPH_W,
30047
+ height: GRAPH_H,
30048
+ className: "absolute inset-0",
30049
+ style: { pointerEvents: "none" },
30050
+ children: [
30051
+ /* @__PURE__ */ jsxs("defs", { children: [
30052
+ /* @__PURE__ */ jsx("marker", { id: "arrowhead", markerWidth: "10", markerHeight: "7", refX: "10", refY: "3.5", orient: "auto", children: /* @__PURE__ */ jsx("polygon", { points: "0 0, 10 3.5, 0 7", fill: "var(--color-border)" }) }),
30053
+ /* @__PURE__ */ jsx("marker", { id: "arrowhead-active", markerWidth: "10", markerHeight: "7", refX: "10", refY: "3.5", orient: "auto", children: /* @__PURE__ */ jsx("polygon", { points: "0 0, 10 3.5, 0 7", fill: "var(--color-primary)" }) })
30054
+ ] }),
30055
+ transitions.map((t2) => {
30056
+ const fromPos = positions[t2.from];
30057
+ const toPos = positions[t2.to];
30058
+ if (!fromPos || !toPos) return null;
30059
+ const isActive = t2.from === currentState;
30060
+ return /* @__PURE__ */ jsx(
30061
+ TransitionArrow,
30062
+ {
30063
+ from: fromPos,
30064
+ to: toPos,
30065
+ eventLabel: t2.event,
30066
+ guardHint: t2.guardHint,
30067
+ isActive
30068
+ },
30069
+ t2.id
30070
+ );
30071
+ })
30072
+ ]
30073
+ }
30074
+ ),
30075
+ entityStates.map((state) => /* @__PURE__ */ jsx(
30076
+ StateNode2,
30077
+ {
30078
+ name: state,
30079
+ position: positions[state],
30080
+ isCurrent: state === currentState,
30081
+ isSelected: state === selectedState,
30082
+ isInitial: state === initialState,
30083
+ onClick: () => handleStateClick(state)
30084
+ },
30085
+ state
30086
+ ))
30087
+ ]
30088
+ }
30089
+ ),
30090
+ !isTesting && /* @__PURE__ */ jsx(HStack, { gap: "sm", children: /* @__PURE__ */ jsx(
30091
+ Button,
30092
+ {
30093
+ variant: "ghost",
30094
+ onClick: handleStartAddTransition,
30095
+ disabled: !selectedState,
30096
+ children: selectedState ? t("stateArchitect.addTransition", { state: selectedState }) : t("stateArchitect.addTransitionPrompt")
30097
+ }
30098
+ ) }),
30099
+ transitions.length > 0 && /* @__PURE__ */ jsxs(VStack, { gap: "xs", className: "p-3 rounded-container bg-muted/50 border border-border", children: [
30100
+ /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-muted-foreground font-medium", children: t("stateArchitect.transitions", { count: transitions.length }) + ":" }),
30101
+ transitions.map((t2) => /* @__PURE__ */ jsxs(HStack, { className: "items-center text-xs", gap: "xs", children: [
30102
+ /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-foreground", children: t2.from }),
30103
+ /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-muted-foreground", children: "\u2014[" }),
30104
+ /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-accent font-medium", children: t2.event }),
30105
+ /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-muted-foreground", children: "]\u2192" }),
30106
+ /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-success", children: t2.to }),
30107
+ t2.guardHint && /* @__PURE__ */ jsxs(Typography, { variant: "caption", className: "text-warning", children: [
30108
+ "(",
30109
+ t2.guardHint,
30110
+ ")"
30111
+ ] }),
30112
+ !isTesting && /* @__PURE__ */ jsx(
30113
+ Button,
30114
+ {
30115
+ variant: "ghost",
30116
+ onClick: () => handleRemoveTransition(t2.id),
30117
+ className: "text-xs ml-auto",
30118
+ children: "\xD7"
30119
+ }
30120
+ )
30121
+ ] }, t2.id))
30122
+ ] })
30123
+ ] }),
30124
+ /* @__PURE__ */ jsxs(VStack, { gap: "sm", className: "w-[280px] shrink-0", children: [
30125
+ /* @__PURE__ */ jsx(TraitStateViewer, { trait: machine, variant: "full", size: "sm" }),
30126
+ /* @__PURE__ */ jsx(
30127
+ VariablePanel,
30128
+ {
30129
+ entityName,
30130
+ variables
30131
+ }
30132
+ ),
30133
+ testResults.length > 0 && /* @__PURE__ */ jsxs(VStack, { className: "p-3 rounded-container bg-card border border-border", gap: "xs", children: [
30134
+ /* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground font-medium", children: t("stateArchitect.testResults") + ":" }),
30135
+ testResults.map((r, i) => /* @__PURE__ */ jsxs(HStack, { className: "items-center text-xs", gap: "xs", children: [
30136
+ /* @__PURE__ */ jsx(Typography, { variant: "caption", className: r.passed ? "text-success" : "text-error", children: r.passed ? "\u2714" : "\u2717" }),
30137
+ /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-foreground flex-1", children: r.label }),
30138
+ !r.passed && /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-error", children: t("stateArchitect.gotState", { state: r.actualState }) })
30139
+ ] }, i))
30140
+ ] }),
30141
+ resolved.showCodeView !== false && /* @__PURE__ */ jsx(StateJsonView, { data: codeData, label: "View Code" })
30142
+ ] })
30143
+ ] }),
30144
+ isSuccess && /* @__PURE__ */ jsx(Box, { className: "p-4 rounded-container bg-success/20 border border-success text-center", children: /* @__PURE__ */ jsx(Typography, { variant: "h5", className: "text-success", children: str(resolved.successMessage) || t("stateArchitect.allPassed") }) }),
30145
+ !isTesting && !isSuccess && testResults.some((r) => !r.passed) && /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
30146
+ /* @__PURE__ */ jsx(Box, { className: "p-4 rounded-container bg-warning/10 border border-warning/30 text-center", children: /* @__PURE__ */ jsx(Typography, { variant: "body1", className: "text-foreground font-medium", children: t(ENCOURAGEMENT_KEYS3[Math.min(attempts - 1, ENCOURAGEMENT_KEYS3.length - 1)] ?? ENCOURAGEMENT_KEYS3[0]) }) }),
30147
+ !isSuccess && attempts >= 2 && Boolean(str(resolved?.hint)) && /* @__PURE__ */ jsx(Box, { className: "p-3 rounded-container bg-accent/10 border border-accent/30", children: /* @__PURE__ */ jsxs(HStack, { className: "items-start", gap: "xs", children: [
30148
+ /* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-accent font-bold shrink-0", children: "\u{1F4A1} " + t("game.hint") + ":" }),
30149
+ /* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-foreground", children: hint })
30150
+ ] }) })
30151
+ ] }),
30152
+ /* @__PURE__ */ jsxs(HStack, { gap: "sm", children: [
30153
+ !isTesting && !isSuccess && testResults.some((r) => !r.passed) ? /* @__PURE__ */ jsx(Button, { variant: "primary", onClick: handleTryAgain, children: "\u{1F504} " + t("puzzle.tryAgainButton") }) : /* @__PURE__ */ jsx(
30154
+ Button,
30155
+ {
30156
+ variant: "primary",
30157
+ onClick: handleTest,
30158
+ disabled: isTesting,
30159
+ children: "\u25B6 " + t("game.runTests")
30160
+ }
30161
+ ),
30162
+ /* @__PURE__ */ jsx(Button, { variant: "ghost", onClick: handleReset, children: "\u21BA " + t("game.reset") })
30163
+ ] })
30164
+ ]
30165
+ }
30166
+ );
30167
+ }
30168
+ var ENCOURAGEMENT_KEYS3, nextTransId;
30169
+ var init_StateArchitectBoard = __esm({
30170
+ "components/game/2d/organisms/StateArchitectBoard.tsx"() {
30171
+ init_atoms();
30172
+ init_cn();
30173
+ init_useEventBus();
30174
+ init_TraitStateViewer();
30175
+ init_StateNode();
30176
+ init_TransitionArrow();
30177
+ init_VariablePanel();
30178
+ init_StateJsonView();
30179
+ init_boardEntity();
30180
+ ENCOURAGEMENT_KEYS3 = [
30181
+ "puzzle.tryAgain1",
30182
+ "puzzle.tryAgain2",
30183
+ "puzzle.tryAgain3"
30184
+ ];
30185
+ nextTransId = 100;
30186
+ StateArchitectBoard.displayName = "StateArchitectBoard";
30187
+ }
30188
+ });
30189
+ function readSimulatorParameters(v) {
30190
+ if (!Array.isArray(v)) return [];
30191
+ const result = [];
30192
+ for (const item of v) {
30193
+ if (typeof item === "object" && item !== null && !Array.isArray(item) && !(item instanceof Date)) {
30194
+ const param = item;
30195
+ if ("id" in item && "label" in item && "unit" in item && "min" in item && "max" in item && "step" in item) {
30196
+ result.push({
30197
+ id: str(param.id),
30198
+ label: str(param.label),
30199
+ unit: str(param.unit),
30200
+ min: num(param.min),
30201
+ max: num(param.max),
30202
+ step: num(param.step),
30203
+ initial: num(param.initial),
30204
+ correct: num(param.correct),
30205
+ tolerance: num(param.tolerance)
30206
+ });
30207
+ }
30208
+ }
30209
+ }
30210
+ return result;
30211
+ }
30212
+ function SimulatorBoard({
30213
+ entity,
30214
+ completeEvent = "PUZZLE_COMPLETE",
30215
+ setAEvent,
30216
+ setBEvent,
30217
+ checkEvent,
30218
+ playAgainEvent,
30219
+ assetManifest,
30220
+ className
30221
+ }) {
30222
+ const ui = assetManifest?.ui;
30223
+ const { emit } = useEventBus();
30224
+ const { t } = useTranslate();
30225
+ const resolved = boardEntity(entity);
30226
+ const parameters = readSimulatorParameters(resolved?.parameters);
30227
+ const [headerError, setHeaderError] = useState(false);
30228
+ if (!resolved) return null;
30229
+ const paramA = num(resolved.paramA);
30230
+ const paramB = num(resolved.paramB);
30231
+ const output = num(resolved.output);
30232
+ const targetValue = num(resolved.target);
30233
+ const targetTolerance = num(resolved.tolerance);
30234
+ const attempts = num(resolved.attempts);
30235
+ const result = str(resolved.result);
30236
+ const isWin = result === "win";
30237
+ const isComplete = result !== "none" && result !== "";
30238
+ const paramAValue = parameters[0];
30239
+ const paramBValue = parameters[1];
30240
+ const sliderValues = [paramA, paramB];
30241
+ const sliderEvents = [setAEvent, setBEvent];
30242
+ const handleParameterChange = (index, value) => {
30243
+ if (isComplete) return;
30244
+ const ev = sliderEvents[index];
30245
+ if (ev) emit(`UI:${ev}`, { value });
30246
+ };
30247
+ const handleCheck = () => {
30248
+ if (checkEvent) emit(`UI:${checkEvent}`, {});
30249
+ };
30250
+ const handlePlayAgain = () => {
30251
+ if (playAgainEvent) emit(`UI:${playAgainEvent}`, {});
30252
+ };
30253
+ const themeBackground = (() => {
30254
+ const t2 = resolved.theme;
30255
+ if (typeof t2 === "object" && t2 !== null && !Array.isArray(t2) && !(t2 instanceof Date)) {
30256
+ const bg = t2.background;
30257
+ return str(bg);
30258
+ }
30259
+ return "";
30260
+ })();
30261
+ const headerImage = str(resolved.headerImage);
30262
+ const hint = str(resolved.hint);
30263
+ const showHint = isComplete && !isWin && attempts >= 2 && Boolean(hint);
30264
+ const outputLabel = str(resolved.outputLabel);
30265
+ const outputUnit = str(resolved.outputUnit);
30266
+ return /* @__PURE__ */ jsx(
30267
+ Box,
30268
+ {
30269
+ className,
30270
+ style: {
30271
+ backgroundImage: themeBackground ? `url(${themeBackground})` : void 0,
30272
+ backgroundSize: "cover",
30273
+ backgroundPosition: "center"
30274
+ },
30275
+ children: /* @__PURE__ */ jsxs(VStack, { gap: "lg", className: "p-4", children: [
30276
+ headerImage && !headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 overflow-hidden rounded-container", children: /* @__PURE__ */ jsx("img", { src: headerImage, alt: "", onError: () => setHeaderError(true), className: "w-full h-full object-cover" }) }) : headerImage && headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 rounded-container bg-gradient-to-br from-muted to-accent opacity-60" }) : null,
30277
+ /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
30278
+ /* @__PURE__ */ jsx(Typography, { variant: "h4", weight: "bold", children: str(resolved.title) }),
30279
+ /* @__PURE__ */ jsx(Typography, { variant: "body", children: str(resolved.description) })
30280
+ ] }) }),
30281
+ /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "md", children: [
30282
+ /* @__PURE__ */ jsx(Typography, { variant: "small", weight: "bold", className: "uppercase tracking-wider text-muted-foreground", children: t("simulator.parameters") }),
30283
+ [paramAValue, paramBValue].map(
30284
+ (param, index) => param ? /* @__PURE__ */ jsxs(VStack, { gap: "xs", children: [
30285
+ /* @__PURE__ */ jsxs(HStack, { justify: "between", align: "center", children: [
30286
+ /* @__PURE__ */ jsx(Typography, { variant: "body", weight: "medium", children: param.label }),
30287
+ /* @__PURE__ */ jsxs(Badge, { size: "sm", children: [
30288
+ sliderValues[index],
30289
+ " ",
30290
+ param.unit
30291
+ ] })
30292
+ ] }),
30293
+ /* @__PURE__ */ jsx(
30294
+ "input",
30295
+ {
30296
+ type: "range",
30297
+ min: param.min,
30298
+ max: param.max,
30299
+ step: param.step,
30300
+ value: sliderValues[index],
30301
+ onChange: (e) => handleParameterChange(index, Number(e.target.value)),
30302
+ disabled: isComplete,
30303
+ className: "w-full accent-foreground"
30304
+ }
30305
+ ),
30306
+ /* @__PURE__ */ jsxs(HStack, { justify: "between", children: [
30307
+ /* @__PURE__ */ jsxs(Typography, { variant: "caption", className: "text-muted-foreground", children: [
30308
+ param.min,
30309
+ " ",
30310
+ param.unit
30311
+ ] }),
30312
+ /* @__PURE__ */ jsxs(Typography, { variant: "caption", className: "text-muted-foreground", children: [
30313
+ param.max,
30314
+ " ",
30315
+ param.unit
30316
+ ] })
30317
+ ] })
30318
+ ] }, param.id ?? index) : null
30319
+ )
30320
+ ] }) }),
30321
+ /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", align: "center", children: [
30322
+ /* @__PURE__ */ jsx(Typography, { variant: "small", weight: "bold", className: "uppercase tracking-wider text-muted-foreground", children: outputLabel }),
30323
+ /* @__PURE__ */ jsxs(Typography, { variant: "h3", weight: "bold", children: [
30324
+ output.toFixed(2),
30325
+ " ",
30326
+ outputUnit
30327
+ ] }),
30328
+ isComplete && /* @__PURE__ */ jsxs(HStack, { gap: "xs", align: "center", children: [
30329
+ /* @__PURE__ */ jsx(
30330
+ GameIcon,
30331
+ {
30332
+ icon: isWin ? CheckCircle : XCircle,
30333
+ assetUrl: isWin ? ui?.["correct"] : ui?.["incorrect"],
30334
+ size: "sm",
30335
+ className: isWin ? "text-success" : "text-error"
30336
+ }
30337
+ ),
30338
+ /* @__PURE__ */ jsx(Typography, { variant: "body", className: isWin ? "text-success" : "text-error", children: isWin ? str(resolved.successMessage) || t("simulator.correct") : str(resolved.failMessage) || t("simulator.incorrect") })
30339
+ ] }),
30340
+ /* @__PURE__ */ jsxs(Typography, { variant: "caption", className: "text-muted-foreground", children: [
30341
+ t("simulator.target"),
30342
+ ": ",
30343
+ targetValue,
30344
+ " ",
30345
+ outputUnit,
30346
+ " (\xB1",
30347
+ targetTolerance,
30348
+ ")"
30349
+ ] })
30350
+ ] }) }),
30351
+ showHint && hint && /* @__PURE__ */ jsx(Card, { className: "p-4 border-l-4 border-l-warning", children: /* @__PURE__ */ jsx(Typography, { variant: "body", children: hint }) }),
30352
+ /* @__PURE__ */ jsxs(HStack, { gap: "sm", justify: "center", children: [
30353
+ !isComplete ? /* @__PURE__ */ jsxs(Button, { variant: "primary", onClick: handleCheck, children: [
30354
+ /* @__PURE__ */ jsx(GameIcon, { icon: Play, assetUrl: ui?.["play"], size: "sm" }),
30355
+ t("simulator.simulate")
30356
+ ] }) : null,
30357
+ /* @__PURE__ */ jsxs(Button, { variant: "secondary", onClick: handlePlayAgain, children: [
30358
+ /* @__PURE__ */ jsx(GameIcon, { icon: RotateCcw, assetUrl: ui?.["reset"], size: "sm" }),
30359
+ t("simulator.reset")
30360
+ ] })
30361
+ ] })
30362
+ ] })
30363
+ }
30364
+ );
30365
+ }
30366
+ var init_SimulatorBoard = __esm({
30367
+ "components/game/2d/organisms/SimulatorBoard.tsx"() {
30368
+ init_atoms();
30369
+ init_useEventBus();
30370
+ init_boardEntity();
30371
+ init_GameIcon();
30372
+ SimulatorBoard.displayName = "SimulatorBoard";
30373
+ }
30374
+ });
30375
+ function toDebuggerLine(v) {
30376
+ if (v === null || typeof v !== "object" || Array.isArray(v) || v instanceof Date) return null;
30377
+ const id = v["id"];
30378
+ const content = v["content"];
30379
+ const isBug = v["isBug"];
30380
+ if (typeof id !== "string" || typeof content !== "string" || typeof isBug !== "boolean") return null;
30381
+ const isFlagged = v["isFlagged"];
30382
+ const explanation = v["explanation"];
30383
+ return {
30384
+ id,
30385
+ content,
30386
+ isBug,
30387
+ isFlagged: typeof isFlagged === "boolean" ? isFlagged : void 0,
30388
+ explanation: typeof explanation === "string" ? explanation : void 0
30389
+ };
30390
+ }
30391
+ function DebuggerBoard({
30392
+ entity,
30393
+ completeEvent = "PUZZLE_COMPLETE",
30394
+ toggleFlagEvent,
30395
+ checkEvent,
30396
+ playAgainEvent,
30397
+ assetManifest,
30398
+ className
30399
+ }) {
30400
+ const ui = assetManifest?.ui;
30401
+ const { emit } = useEventBus();
30402
+ const { t } = useTranslate();
30403
+ const resolved = boardEntity(entity);
30404
+ const [headerError, setHeaderError] = useState(false);
30405
+ const lines = Array.isArray(resolved?.lines) ? resolved.lines.flatMap((v) => {
30406
+ const l = toDebuggerLine(v);
30407
+ return l ? [l] : [];
30408
+ }) : [];
30409
+ const result = str(resolved?.result) || "none";
30410
+ const attempts = num(resolved?.attempts);
30411
+ const submitted = result === "win";
30412
+ const showHint = !submitted && attempts >= 2 && Boolean(str(resolved?.hint));
30413
+ const bugLines = lines.filter((l) => l.isBug);
30414
+ const flaggedLines = lines.filter((l) => l.isFlagged);
30415
+ const correctFlags = lines.filter((l) => l.isBug && l.isFlagged);
30416
+ const falseFlags = lines.filter((l) => !l.isBug && l.isFlagged);
30417
+ const allCorrect = submitted;
30418
+ const toggleLine = (lineId) => {
30419
+ if (submitted) return;
30420
+ if (toggleFlagEvent) emit(`UI:${toggleFlagEvent}`, { lineId });
30421
+ };
30422
+ const handleSubmit = useCallback(() => {
30423
+ if (checkEvent) emit(`UI:${checkEvent}`, {});
30424
+ const correct = correctFlags.length === bugLines.length && falseFlags.length === 0;
30425
+ if (correct) emit(`UI:${completeEvent}`, { success: true, attempts: attempts + 1 });
30426
+ }, [checkEvent, correctFlags.length, bugLines.length, falseFlags.length, attempts, completeEvent, emit]);
30427
+ const handleReset = () => {
30428
+ if (playAgainEvent) emit(`UI:${playAgainEvent}`, {});
30429
+ };
30430
+ if (!resolved) return null;
30431
+ const theme = resolved.theme ?? void 0;
30432
+ const themeBackground = theme?.background;
30433
+ const headerImage = str(resolved.headerImage);
30434
+ const hint = str(resolved.hint);
30435
+ return /* @__PURE__ */ jsx(
30436
+ Box,
30437
+ {
30438
+ className,
30439
+ style: {
30440
+ backgroundImage: themeBackground ? `url(${themeBackground})` : void 0,
30441
+ backgroundSize: "cover",
30442
+ backgroundPosition: "center"
30443
+ },
30444
+ children: /* @__PURE__ */ jsxs(VStack, { gap: "lg", className: "p-4", children: [
30445
+ headerImage && !headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 overflow-hidden rounded-container", children: /* @__PURE__ */ jsx("img", { src: headerImage, alt: "", onError: () => setHeaderError(true), className: "w-full h-full object-cover" }) }) : headerImage && headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 rounded-container bg-gradient-to-br from-muted to-accent opacity-60" }) : null,
30446
+ /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
30447
+ /* @__PURE__ */ jsxs(HStack, { gap: "xs", align: "center", children: [
30448
+ /* @__PURE__ */ jsx(GameIcon, { icon: Bug, assetUrl: ui?.["bug"], size: "sm" }),
30449
+ /* @__PURE__ */ jsx(Typography, { variant: "h4", weight: "bold", children: str(resolved.title) })
30450
+ ] }),
30451
+ /* @__PURE__ */ jsx(Typography, { variant: "body", children: str(resolved.description) }),
30452
+ /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-muted-foreground", children: t("debugger.findBugs", { count: String(lines.filter((l) => l.isBug).length) }) })
30453
+ ] }) }),
30454
+ /* @__PURE__ */ jsx(Card, { className: "p-0 overflow-hidden", children: /* @__PURE__ */ jsx(VStack, { gap: "none", children: lines.map((line, i) => {
30455
+ const isFlagged = !!line.isFlagged;
30456
+ let lineStyle = "";
30457
+ if (submitted) {
30458
+ if (line.isBug && isFlagged) lineStyle = "bg-success/10";
30459
+ else if (line.isBug && !isFlagged) lineStyle = "bg-warning/10";
30460
+ else if (!line.isBug && isFlagged) lineStyle = "bg-error/10";
30461
+ } else if (isFlagged) {
30462
+ lineStyle = "bg-error/10";
30463
+ }
30464
+ return /* @__PURE__ */ jsxs(
30465
+ HStack,
30466
+ {
30467
+ gap: "none",
30468
+ align: "stretch",
30469
+ className: `border-b border-border cursor-pointer hover:bg-muted ${lineStyle}`,
30470
+ onClick: () => toggleLine(line.id),
30471
+ children: [
30472
+ /* @__PURE__ */ jsx(Box, { className: "w-10 flex-shrink-0 flex items-center justify-center border-r border-border text-muted-foreground", children: /* @__PURE__ */ jsx(Typography, { variant: "caption", children: i + 1 }) }),
30473
+ /* @__PURE__ */ jsx(Box, { className: "flex-1 px-3 py-1.5 font-mono text-sm whitespace-pre", children: /* @__PURE__ */ jsx(Typography, { variant: "body", className: "font-mono text-sm", children: line.content }) }),
30474
+ /* @__PURE__ */ jsxs(Box, { className: "w-8 flex-shrink-0 flex items-center justify-center", children: [
30475
+ isFlagged && /* @__PURE__ */ jsx(GameIcon, { icon: Bug, assetUrl: ui?.["bug"], size: "sm", className: "text-error" }),
30476
+ submitted && line.isBug && !isFlagged && /* @__PURE__ */ jsx(GameIcon, { icon: Bug, assetUrl: ui?.["bug"], size: "sm", className: "text-warning" })
30477
+ ] })
30478
+ ]
30479
+ },
30480
+ line.id
30481
+ );
30482
+ }) }) }),
30483
+ submitted && /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
30484
+ /* @__PURE__ */ jsx(Typography, { variant: "body", weight: "bold", children: allCorrect ? str(resolved.successMessage) || t("debugger.allFound") : `${correctFlags.length}/${bugLines.length} ${t("debugger.bugsFound")}` }),
30485
+ bugLines.map((line) => /* @__PURE__ */ jsxs(HStack, { gap: "xs", align: "start", children: [
30486
+ /* @__PURE__ */ jsx(
30487
+ GameIcon,
30488
+ {
30489
+ icon: line.isFlagged ? CheckCircle : XCircle,
30490
+ assetUrl: line.isFlagged ? ui?.["correct"] : ui?.["incorrect"],
30491
+ size: "sm",
30492
+ className: line.isFlagged ? "text-success mt-0.5" : "text-warning mt-0.5"
30493
+ }
30494
+ ),
30495
+ /* @__PURE__ */ jsxs(VStack, { gap: "none", children: [
30496
+ /* @__PURE__ */ jsx(Typography, { variant: "caption", weight: "bold", className: "font-mono", children: line.content.trim() }),
30497
+ line.explanation && /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-muted-foreground", children: line.explanation })
30498
+ ] })
30499
+ ] }, line.id))
30500
+ ] }) }),
30501
+ showHint && hint && /* @__PURE__ */ jsx(Card, { className: "p-4 border-l-4 border-l-warning", children: /* @__PURE__ */ jsx(Typography, { variant: "body", children: hint }) }),
30502
+ /* @__PURE__ */ jsxs(HStack, { gap: "sm", justify: "center", children: [
30503
+ !submitted && /* @__PURE__ */ jsxs(Button, { variant: "primary", onClick: handleSubmit, disabled: flaggedLines.length === 0, children: [
30504
+ /* @__PURE__ */ jsx(GameIcon, { icon: Send, assetUrl: ui?.["send"], size: "sm" }),
30505
+ t("debugger.submit")
30506
+ ] }),
30507
+ /* @__PURE__ */ jsxs(Button, { variant: "secondary", onClick: handleReset, children: [
30508
+ /* @__PURE__ */ jsx(GameIcon, { icon: RotateCcw, assetUrl: ui?.["reset"], size: "sm" }),
30509
+ t("debugger.reset")
30510
+ ] })
30511
+ ] })
30512
+ ] })
30513
+ }
30514
+ );
30515
+ }
30516
+ var init_DebuggerBoard = __esm({
30517
+ "components/game/2d/organisms/DebuggerBoard.tsx"() {
30518
+ init_atoms();
30519
+ init_useEventBus();
30520
+ init_boardEntity();
30521
+ init_GameIcon();
30522
+ DebuggerBoard.displayName = "DebuggerBoard";
30523
+ }
30524
+ });
30525
+ function NegotiatorBoard({
30526
+ entity,
30527
+ completeEvent = "PUZZLE_COMPLETE",
30528
+ playRoundEvent,
30529
+ finishEvent,
30530
+ playAgainEvent,
30531
+ assetManifest,
30532
+ className
30533
+ }) {
30534
+ const ui = assetManifest?.ui;
30535
+ const { emit } = useEventBus();
30536
+ const { t } = useTranslate();
30537
+ const resolved = boardEntity(entity);
30538
+ const [history, setHistory] = useState([]);
30539
+ const [headerError, setHeaderError] = useState(false);
30540
+ const [showHint, setShowHint] = useState(false);
30541
+ const totalRounds = num(resolved?.maxRounds);
30542
+ const targetScore = num(resolved?.targetScore);
30543
+ const currentRound = num(resolved?.round);
30544
+ const result = str(resolved?.result) || "none";
30545
+ const playerTotal = num(resolved?.score);
30546
+ const isComplete = result !== "none" || totalRounds > 0 && currentRound >= totalRounds;
30547
+ const won = result === "win";
30548
+ const lastPlayerAction = str(resolved?.lastPlayerAction);
30549
+ const lastOpponentAction = str(resolved?.lastOpponentAction);
30550
+ const lastPayoff = num(resolved?.lastPayoff);
30551
+ const actions = Array.isArray(resolved?.actions) ? resolved.actions.flatMap((item) => {
30552
+ if (item !== null && typeof item === "object" && !Array.isArray(item) && !(item instanceof Date) && typeof item.id === "string" && typeof item.label === "string")
30553
+ return [{ id: item.id, label: item.label, description: typeof item.description === "string" ? item.description : void 0 }];
30554
+ return [];
30555
+ }) : [];
30556
+ const payoffMatrix = Array.isArray(resolved?.payoffMatrix) ? resolved.payoffMatrix.flatMap((item) => {
30557
+ if (item !== null && typeof item === "object" && !Array.isArray(item) && !(item instanceof Date) && typeof item.playerAction === "string" && typeof item.opponentAction === "string")
30558
+ return [{ playerAction: item.playerAction, opponentAction: item.opponentAction, playerPayoff: typeof item.playerPayoff === "number" ? item.playerPayoff : 0, opponentPayoff: typeof item.opponentPayoff === "number" ? item.opponentPayoff : 0 }];
30559
+ return [];
30560
+ }) : [];
30561
+ const prevRoundRef = useRef(currentRound);
30562
+ useEffect(() => {
30563
+ if (currentRound > prevRoundRef.current && lastPlayerAction) {
30564
+ const opponentPayoffEntry = payoffMatrix.find(
30565
+ (p) => p.playerAction === lastPlayerAction && p.opponentAction === lastOpponentAction
30566
+ );
30567
+ setHistory((prev) => [
30568
+ ...prev,
30569
+ {
30570
+ round: currentRound,
30571
+ playerAction: lastPlayerAction,
30572
+ opponentAction: lastOpponentAction,
30573
+ playerPayoff: lastPayoff,
30574
+ opponentPayoff: opponentPayoffEntry?.opponentPayoff ?? 0
30575
+ }
30576
+ ]);
30577
+ }
30578
+ prevRoundRef.current = currentRound;
30579
+ }, [currentRound, lastPlayerAction, lastOpponentAction, lastPayoff, payoffMatrix]);
30580
+ const opponentTotal = useMemo(() => history.reduce((s, r) => s + r.opponentPayoff, 0), [history]);
30581
+ const handleAction = useCallback((actionId) => {
30582
+ if (isComplete) return;
30583
+ if (playRoundEvent) {
30584
+ emit(`UI:${playRoundEvent}`, { playerAction: actionId, payoff: 0 });
30585
+ }
30586
+ if (totalRounds > 0 && currentRound + 1 >= totalRounds) {
30587
+ if (finishEvent) {
30588
+ emit(`UI:${finishEvent}`, {});
30589
+ }
30590
+ if (str(resolved?.hint)) {
30591
+ setShowHint(true);
30592
+ }
30593
+ }
30594
+ }, [isComplete, resolved, totalRounds, currentRound, playRoundEvent, finishEvent, emit]);
30595
+ const handleReset = useCallback(() => {
30596
+ setHistory([]);
30597
+ setShowHint(false);
30598
+ prevRoundRef.current = 0;
30599
+ if (playAgainEvent) {
30600
+ emit(`UI:${playAgainEvent}`, {});
30601
+ }
30602
+ }, [playAgainEvent, emit]);
30603
+ const completedRef = useRef(false);
30604
+ useEffect(() => {
30605
+ if (result === "win" && !completedRef.current) {
30606
+ completedRef.current = true;
30607
+ emit(`UI:${completeEvent}`, { success: true, score: playerTotal });
30608
+ } else if (result === "none") {
30609
+ completedRef.current = false;
30610
+ }
30611
+ }, [result, playerTotal, completeEvent, emit]);
30612
+ const getActionLabel = (id) => actions.find((a) => a.id === id)?.label ?? id;
30613
+ if (!resolved) return null;
30614
+ const theme = resolved.theme ?? void 0;
30615
+ const themeBackground = theme?.background;
30616
+ const headerImage = str(resolved.headerImage);
30617
+ const hint = str(resolved.hint);
30618
+ return /* @__PURE__ */ jsx(
30619
+ Box,
30620
+ {
30621
+ className,
30622
+ style: {
30623
+ backgroundImage: themeBackground ? `url(${themeBackground})` : void 0,
30624
+ backgroundSize: "cover",
30625
+ backgroundPosition: "center"
30626
+ },
30627
+ children: /* @__PURE__ */ jsxs(VStack, { gap: "lg", className: "p-4", children: [
30628
+ headerImage && !headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 overflow-hidden rounded-container", children: /* @__PURE__ */ jsx("img", { src: headerImage, alt: "", onError: () => setHeaderError(true), className: "w-full h-full object-cover" }) }) : headerImage && headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 rounded-container bg-gradient-to-br from-muted to-accent opacity-60" }) : null,
30629
+ /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
30630
+ /* @__PURE__ */ jsx(Typography, { variant: "h4", weight: "bold", children: str(resolved.title) }),
30631
+ /* @__PURE__ */ jsx(Typography, { variant: "body", children: str(resolved.description) }),
30632
+ /* @__PURE__ */ jsxs(HStack, { gap: "md", children: [
30633
+ /* @__PURE__ */ jsx(Badge, { size: "sm", children: t("negotiator.round", { current: String(currentRound), total: String(totalRounds) }) }),
30634
+ /* @__PURE__ */ jsxs(Badge, { size: "sm", children: [
30635
+ t("negotiator.target"),
30636
+ ": ",
30637
+ targetScore
30638
+ ] })
30639
+ ] })
30640
+ ] }) }),
30641
+ /* @__PURE__ */ jsxs(HStack, { gap: "md", justify: "center", children: [
30642
+ /* @__PURE__ */ jsx(Card, { className: "p-4 flex-1 text-center", children: /* @__PURE__ */ jsxs(VStack, { gap: "xs", align: "center", children: [
30643
+ /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-muted-foreground", children: t("negotiator.you") }),
30644
+ /* @__PURE__ */ jsx(Typography, { variant: "h3", weight: "bold", children: playerTotal })
30645
+ ] }) }),
30646
+ /* @__PURE__ */ jsx(Card, { className: "p-4 flex-1 text-center", children: /* @__PURE__ */ jsxs(VStack, { gap: "xs", align: "center", children: [
30647
+ /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-muted-foreground", children: t("negotiator.opponent") }),
30648
+ /* @__PURE__ */ jsx(Typography, { variant: "h3", weight: "bold", children: opponentTotal })
30649
+ ] }) })
30650
+ ] }),
30651
+ !isComplete && /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
30652
+ /* @__PURE__ */ jsx(Typography, { variant: "small", weight: "bold", className: "uppercase tracking-wider text-muted-foreground", children: t("negotiator.chooseAction") }),
30653
+ /* @__PURE__ */ jsx(HStack, { gap: "sm", justify: "center", className: "flex-wrap", children: actions.map((action) => /* @__PURE__ */ jsx(
30654
+ Button,
30655
+ {
30656
+ variant: "primary",
30657
+ onClick: () => handleAction(action.id),
30658
+ children: action.label
30659
+ },
30660
+ action.id
30661
+ )) })
30662
+ ] }) }),
30663
+ history.length > 0 && /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
30664
+ /* @__PURE__ */ jsx(Typography, { variant: "small", weight: "bold", className: "uppercase tracking-wider text-muted-foreground", children: t("negotiator.history") }),
30665
+ history.map((round) => /* @__PURE__ */ jsxs(HStack, { gap: "sm", align: "center", className: "text-sm", children: [
30666
+ /* @__PURE__ */ jsxs(Badge, { size: "sm", children: [
30667
+ "R",
30668
+ round.round
30669
+ ] }),
30670
+ /* @__PURE__ */ jsx(Typography, { variant: "caption", children: getActionLabel(round.playerAction) }),
30671
+ /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-muted-foreground", children: "vs" }),
30672
+ /* @__PURE__ */ jsx(Typography, { variant: "caption", children: getActionLabel(round.opponentAction) }),
30673
+ /* @__PURE__ */ jsx(GameIcon, { icon: ArrowRight, assetUrl: ui?.["arrow"], size: "sm" }),
30674
+ /* @__PURE__ */ jsxs(Typography, { variant: "caption", weight: "bold", className: "text-success", children: [
30675
+ "+",
30676
+ round.playerPayoff
30677
+ ] }),
30678
+ /* @__PURE__ */ jsxs(Typography, { variant: "caption", className: "text-muted-foreground", children: [
30679
+ "/ +",
30680
+ round.opponentPayoff
30681
+ ] })
30682
+ ] }, round.round))
30683
+ ] }) }),
30684
+ isComplete && /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", align: "center", children: [
30685
+ /* @__PURE__ */ jsx(GameIcon, { icon: CheckCircle, assetUrl: ui?.["correct"], size: "lg", className: won ? "text-success" : "text-error" }),
30686
+ /* @__PURE__ */ jsx(Typography, { variant: "body", weight: "bold", children: won ? str(resolved.successMessage) || t("negotiator.success") : str(resolved.failMessage) || t("negotiator.failed") }),
30687
+ /* @__PURE__ */ jsxs(Typography, { variant: "caption", className: "text-muted-foreground", children: [
30688
+ t("negotiator.finalScore"),
30689
+ ": ",
30690
+ playerTotal,
30691
+ "/",
30692
+ targetScore
30693
+ ] })
30694
+ ] }) }),
30695
+ showHint && hint && !won && /* @__PURE__ */ jsx(Card, { className: "p-4 border-l-4 border-l-warning", children: /* @__PURE__ */ jsx(Typography, { variant: "body", children: hint }) }),
30696
+ isComplete && !won && /* @__PURE__ */ jsx(HStack, { justify: "center", children: /* @__PURE__ */ jsx(Button, { variant: "primary", onClick: handleReset, children: t("negotiator.playAgain") }) })
30697
+ ] })
30698
+ }
30699
+ );
30700
+ }
30701
+ var init_NegotiatorBoard = __esm({
30702
+ "components/game/2d/organisms/NegotiatorBoard.tsx"() {
30703
+ init_atoms();
30704
+ init_useEventBus();
30705
+ init_boardEntity();
30706
+ init_GameIcon();
30707
+ NegotiatorBoard.displayName = "NegotiatorBoard";
30708
+ }
30709
+ });
28929
30710
 
28930
30711
  // components/game/shared/lib/mechanics.ts
28931
30712
  var projectileMotion, pendulum, springOscillator;
@@ -29140,7 +30921,7 @@ function SimulationCanvas({
29140
30921
  }
29141
30922
  var PRESET_BY_ID;
29142
30923
  var init_SimulationCanvas = __esm({
29143
- "components/game/2d/molecules/SimulationCanvas.tsx"() {
30924
+ "components/game/2d/organisms/SimulationCanvas.tsx"() {
29144
30925
  init_cn();
29145
30926
  init_atoms();
29146
30927
  init_verificationRegistry();
@@ -29258,7 +31039,7 @@ function SimulationControls({
29258
31039
  ] });
29259
31040
  }
29260
31041
  var init_SimulationControls = __esm({
29261
- "components/game/2d/molecules/SimulationControls.tsx"() {
31042
+ "components/game/2d/organisms/SimulationControls.tsx"() {
29262
31043
  init_useEventBus();
29263
31044
  init_atoms();
29264
31045
  init_GameIcon();
@@ -29323,7 +31104,7 @@ function SimulationGraph({
29323
31104
  ] }) });
29324
31105
  }
29325
31106
  var init_SimulationGraph = __esm({
29326
- "components/game/2d/molecules/SimulationGraph.tsx"() {
31107
+ "components/game/2d/organisms/SimulationGraph.tsx"() {
29327
31108
  init_atoms();
29328
31109
  SimulationGraph.displayName = "SimulationGraph";
29329
31110
  }
@@ -29562,6 +31343,7 @@ var init_molecules = __esm({
29562
31343
  init_ResourceBar();
29563
31344
  init_GameHud();
29564
31345
  init_GameMenu();
31346
+ init_StateGraph();
29565
31347
  init_Canvas2D();
29566
31348
  init_useUnitSpriteAtlas();
29567
31349
  init_GameAudioProvider();
@@ -29574,14 +31356,22 @@ var init_molecules = __esm({
29574
31356
  init_ActionTile();
29575
31357
  init_ActionPalette();
29576
31358
  init_SequenceBar();
31359
+ init_SequencerBoard();
29577
31360
  init_RuleEditor();
29578
31361
  init_EventLog();
29579
31362
  init_ObjectRulePanel();
31363
+ init_EventHandlerBoard();
29580
31364
  init_puzzleObject();
29581
31365
  init_StateNode();
29582
31366
  init_TransitionArrow();
29583
31367
  init_VariablePanel();
29584
31368
  init_StateJsonView();
31369
+ init_StateArchitectBoard();
31370
+ init_SimulatorBoard();
31371
+ init_ClassifierBoard();
31372
+ init_BuilderBoard();
31373
+ init_DebuggerBoard();
31374
+ init_NegotiatorBoard();
29585
31375
  init_SimulationCanvas();
29586
31376
  init_SimulationControls();
29587
31377
  init_SimulationGraph();
@@ -30189,13 +31979,13 @@ var init_MapView = __esm({
30189
31979
  shadowSize: [41, 41]
30190
31980
  });
30191
31981
  L.Marker.prototype.options.icon = defaultIcon;
30192
- const { useEffect: useEffect67, useRef: useRef62, useCallback: useCallback109, useState: useState100 } = React72__default;
31982
+ const { useEffect: useEffect71, useRef: useRef66, useCallback: useCallback114, useState: useState108 } = React74__default;
30193
31983
  const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
30194
31984
  const { useEventBus: useEventBus2 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
30195
31985
  function MapUpdater({ centerLat, centerLng, zoom }) {
30196
31986
  const map = useMap();
30197
- const prevRef = useRef62({ centerLat, centerLng, zoom });
30198
- useEffect67(() => {
31987
+ const prevRef = useRef66({ centerLat, centerLng, zoom });
31988
+ useEffect71(() => {
30199
31989
  const prev = prevRef.current;
30200
31990
  if (prev.centerLat !== centerLat || prev.centerLng !== centerLng || prev.zoom !== zoom) {
30201
31991
  map.setView([centerLat, centerLng], zoom);
@@ -30206,7 +31996,7 @@ var init_MapView = __esm({
30206
31996
  }
30207
31997
  function MapClickHandler({ onMapClick }) {
30208
31998
  const map = useMap();
30209
- useEffect67(() => {
31999
+ useEffect71(() => {
30210
32000
  if (!onMapClick) return;
30211
32001
  const handler = (e) => {
30212
32002
  onMapClick(e.latlng.lat, e.latlng.lng);
@@ -30234,8 +32024,8 @@ var init_MapView = __esm({
30234
32024
  showAttribution = true
30235
32025
  }) {
30236
32026
  const eventBus = useEventBus2();
30237
- const [clickedPosition, setClickedPosition] = useState100(null);
30238
- const handleMapClick = useCallback109((lat, lng) => {
32027
+ const [clickedPosition, setClickedPosition] = useState108(null);
32028
+ const handleMapClick = useCallback114((lat, lng) => {
30239
32029
  if (showClickedPin) {
30240
32030
  setClickedPosition({ lat, lng });
30241
32031
  }
@@ -30244,7 +32034,7 @@ var init_MapView = __esm({
30244
32034
  eventBus.emit(`UI:${mapClickEvent}`, { latitude: lat, longitude: lng });
30245
32035
  }
30246
32036
  }, [onMapClick, mapClickEvent, eventBus, showClickedPin]);
30247
- const handleMarkerClick = useCallback109((marker) => {
32037
+ const handleMarkerClick = useCallback114((marker) => {
30248
32038
  onMarkerClick?.(marker);
30249
32039
  if (markerClickEvent) {
30250
32040
  eventBus.emit(`UI:${markerClickEvent}`, { ...marker });
@@ -31104,8 +32894,8 @@ function TableView({
31104
32894
  }) {
31105
32895
  const eventBus = useEventBus();
31106
32896
  const { t } = useTranslate();
31107
- const [visibleCount, setVisibleCount] = React72__default.useState(pageSize > 0 ? pageSize : Infinity);
31108
- const [localSelected, setLocalSelected] = React72__default.useState(/* @__PURE__ */ new Set());
32897
+ const [visibleCount, setVisibleCount] = React74__default.useState(pageSize > 0 ? pageSize : Infinity);
32898
+ const [localSelected, setLocalSelected] = React74__default.useState(/* @__PURE__ */ new Set());
31109
32899
  const colDefs = columns ?? fields ?? [];
31110
32900
  const allDataRaw = Array.isArray(entity) ? entity : entity ? [entity] : [];
31111
32901
  const dnd = useDataDnd({
@@ -31300,12 +33090,12 @@ function TableView({
31300
33090
  ]
31301
33091
  }
31302
33092
  );
31303
- return dnd.isZone ? /* @__PURE__ */ jsx(dnd.SortableItem, { id: row[idField] ?? id, children: rowInner }, id) : /* @__PURE__ */ jsx(React72__default.Fragment, { children: rowInner }, id);
33093
+ return dnd.isZone ? /* @__PURE__ */ jsx(dnd.SortableItem, { id: row[idField] ?? id, children: rowInner }, id) : /* @__PURE__ */ jsx(React74__default.Fragment, { children: rowInner }, id);
31304
33094
  };
31305
33095
  const items = Array.from(data);
31306
33096
  const groups = groupBy ? groupData2(items, groupBy) : [{ label: "", items }];
31307
33097
  let runningIndex = 0;
31308
- const body = /* @__PURE__ */ jsx(Box, { role: "rowgroup", children: groups.map((group, gi) => /* @__PURE__ */ jsxs(React72__default.Fragment, { children: [
33098
+ const body = /* @__PURE__ */ jsx(Box, { role: "rowgroup", children: groups.map((group, gi) => /* @__PURE__ */ jsxs(React74__default.Fragment, { children: [
31309
33099
  group.label && /* @__PURE__ */ jsx(Divider, { label: group.label, className: gi > 0 ? "mt-3" : "mt-0" }),
31310
33100
  group.items.map((row) => renderRow(row, runningIndex++))
31311
33101
  ] }, gi)) });
@@ -32662,7 +34452,7 @@ var init_StepFlow = __esm({
32662
34452
  className
32663
34453
  }) => {
32664
34454
  if (orientation === "vertical") {
32665
- return /* @__PURE__ */ jsx(VStack, { gap: "none", className: cn("w-full", className), children: steps.map((step, index) => /* @__PURE__ */ jsx(React72__default.Fragment, { children: /* @__PURE__ */ jsxs(HStack, { gap: "md", align: "start", className: "w-full", children: [
34455
+ return /* @__PURE__ */ jsx(VStack, { gap: "none", className: cn("w-full", className), children: steps.map((step, index) => /* @__PURE__ */ jsx(React74__default.Fragment, { children: /* @__PURE__ */ jsxs(HStack, { gap: "md", align: "start", className: "w-full", children: [
32666
34456
  /* @__PURE__ */ jsxs(VStack, { gap: "none", align: "center", children: [
32667
34457
  /* @__PURE__ */ jsx(StepCircle, { step, index }),
32668
34458
  showConnectors && index < steps.length - 1 && /* @__PURE__ */ jsx(Box, { className: "w-px h-8 bg-border" })
@@ -32673,7 +34463,7 @@ var init_StepFlow = __esm({
32673
34463
  ] })
32674
34464
  ] }) }, index)) });
32675
34465
  }
32676
- 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(React72__default.Fragment, { children: [
34466
+ 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(React74__default.Fragment, { children: [
32677
34467
  /* @__PURE__ */ jsxs(VStack, { gap: "sm", align: "center", className: "flex-1 w-full md:w-auto", children: [
32678
34468
  /* @__PURE__ */ jsx(StepCircle, { step, index }),
32679
34469
  /* @__PURE__ */ jsx(Typography, { variant: "h4", className: "text-center", children: step.title }),
@@ -33658,7 +35448,7 @@ var init_LikertScale = __esm({
33658
35448
  md: "text-base",
33659
35449
  lg: "text-lg"
33660
35450
  };
33661
- LikertScale = React72__default.forwardRef(
35451
+ LikertScale = React74__default.forwardRef(
33662
35452
  ({
33663
35453
  question,
33664
35454
  options = DEFAULT_LIKERT_OPTIONS,
@@ -33670,7 +35460,7 @@ var init_LikertScale = __esm({
33670
35460
  variant = "radios",
33671
35461
  className
33672
35462
  }, ref) => {
33673
- const groupId = React72__default.useId();
35463
+ const groupId = React74__default.useId();
33674
35464
  const eventBus = useEventBus();
33675
35465
  const handleSelect = useCallback(
33676
35466
  (next) => {
@@ -35952,7 +37742,7 @@ var init_DocBreadcrumb = __esm({
35952
37742
  "aria-label": t("aria.breadcrumb"),
35953
37743
  children: /* @__PURE__ */ jsx(HStack, { gap: "xs", align: "center", wrap: true, children: items.map((item, idx) => {
35954
37744
  const isLast = idx === items.length - 1;
35955
- return /* @__PURE__ */ jsxs(React72__default.Fragment, { children: [
37745
+ return /* @__PURE__ */ jsxs(React74__default.Fragment, { children: [
35956
37746
  idx > 0 && /* @__PURE__ */ jsx(
35957
37747
  Icon,
35958
37748
  {
@@ -36821,7 +38611,7 @@ var init_MiniStateMachine = __esm({
36821
38611
  const x = 2 + i * (NODE_W + GAP2 + ARROW_W + GAP2);
36822
38612
  const tc = transitionCounts[s.name] ?? 0;
36823
38613
  const role = getStateRole(s.name, s.isInitial ?? void 0, s.isTerminal ?? void 0, tc, maxTC);
36824
- return /* @__PURE__ */ jsxs(React72__default.Fragment, { children: [
38614
+ return /* @__PURE__ */ jsxs(React74__default.Fragment, { children: [
36825
38615
  /* @__PURE__ */ jsx(
36826
38616
  AvlState,
36827
38617
  {
@@ -37025,7 +38815,7 @@ var init_PageHeader = __esm({
37025
38815
  info: "bg-info/10 text-info"
37026
38816
  };
37027
38817
  return /* @__PURE__ */ jsxs(Box, { className: cn("mb-6", className), children: [
37028
- 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(React72__default.Fragment, { children: [
38818
+ 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(React74__default.Fragment, { children: [
37029
38819
  idx > 0 && /* @__PURE__ */ jsx(Typography, { variant: "small", color: "muted", children: "/" }),
37030
38820
  crumb.href ? /* @__PURE__ */ jsx(
37031
38821
  "a",
@@ -37383,7 +39173,7 @@ var init_Section = __esm({
37383
39173
  as: Component = "section"
37384
39174
  }) => {
37385
39175
  const hasHeader = title || description || action;
37386
- return React72__default.createElement(
39176
+ return React74__default.createElement(
37387
39177
  Component,
37388
39178
  {
37389
39179
  className: cn(
@@ -37757,7 +39547,7 @@ var init_WizardContainer = __esm({
37757
39547
  const isCompleted = index < currentStep;
37758
39548
  const stepKey = step.id ?? step.tabId ?? `step-${index}`;
37759
39549
  const stepTitle = step.title ?? step.name ?? `Step ${index + 1}`;
37760
- return /* @__PURE__ */ jsxs(React72__default.Fragment, { children: [
39550
+ return /* @__PURE__ */ jsxs(React74__default.Fragment, { children: [
37761
39551
  /* @__PURE__ */ jsx(
37762
39552
  Button,
37763
39553
  {
@@ -40406,7 +42196,7 @@ var init_DetailPanel = __esm({
40406
42196
  }
40407
42197
  });
40408
42198
  function extractTitle(children) {
40409
- if (!React72__default.isValidElement(children)) return void 0;
42199
+ if (!React74__default.isValidElement(children)) return void 0;
40410
42200
  const props = children.props;
40411
42201
  if (typeof props.title === "string") {
40412
42202
  return props.title;
@@ -40756,12 +42546,12 @@ var init_Form = __esm({
40756
42546
  const isSchemaEntity = isOrbitalEntitySchema(entity);
40757
42547
  const resolvedEntity = isSchemaEntity ? entity : void 0;
40758
42548
  const entityName = typeof entity === "string" ? entity : resolvedEntity?.name;
40759
- const normalizedInitialData = React72__default.useMemo(() => {
42549
+ const normalizedInitialData = React74__default.useMemo(() => {
40760
42550
  const entityRowAsInitial = isPlainEntityRow(entity) ? entity : void 0;
40761
42551
  const callerInitial = initialData !== null && typeof initialData === "object" && !Array.isArray(initialData) ? initialData : {};
40762
42552
  return entityRowAsInitial !== void 0 ? { ...entityRowAsInitial, ...callerInitial } : callerInitial;
40763
42553
  }, [entity, initialData]);
40764
- const entityDerivedFields = React72__default.useMemo(() => {
42554
+ const entityDerivedFields = React74__default.useMemo(() => {
40765
42555
  if (fields && fields.length > 0) return void 0;
40766
42556
  if (!resolvedEntity) return void 0;
40767
42557
  return resolvedEntity.fields.map(
@@ -40782,16 +42572,16 @@ var init_Form = __esm({
40782
42572
  const conditionalFields = typeof conditionalFieldsRaw === "boolean" ? {} : conditionalFieldsRaw;
40783
42573
  const hiddenCalculations = typeof hiddenCalculationsRaw === "boolean" ? [] : hiddenCalculationsRaw;
40784
42574
  const violationTriggers = typeof violationTriggersRaw === "boolean" ? [] : violationTriggersRaw;
40785
- const [formData, setFormData] = React72__default.useState(
42575
+ const [formData, setFormData] = React74__default.useState(
40786
42576
  normalizedInitialData
40787
42577
  );
40788
- const [collapsedSections, setCollapsedSections] = React72__default.useState(
42578
+ const [collapsedSections, setCollapsedSections] = React74__default.useState(
40789
42579
  /* @__PURE__ */ new Set()
40790
42580
  );
40791
- const [submitError, setSubmitError] = React72__default.useState(null);
40792
- const formRef = React72__default.useRef(null);
42581
+ const [submitError, setSubmitError] = React74__default.useState(null);
42582
+ const formRef = React74__default.useRef(null);
40793
42583
  const formMode = props.mode;
40794
- const mountedRef = React72__default.useRef(false);
42584
+ const mountedRef = React74__default.useRef(false);
40795
42585
  if (!mountedRef.current) {
40796
42586
  mountedRef.current = true;
40797
42587
  debug("forms", "mount", {
@@ -40804,7 +42594,7 @@ var init_Form = __esm({
40804
42594
  });
40805
42595
  }
40806
42596
  const shouldShowCancel = showCancel ?? (fields && fields.length > 0);
40807
- const evalContext = React72__default.useMemo(
42597
+ const evalContext = React74__default.useMemo(
40808
42598
  () => ({
40809
42599
  formValues: formData,
40810
42600
  globalVariables: externalContext?.globalVariables ?? {},
@@ -40813,7 +42603,7 @@ var init_Form = __esm({
40813
42603
  }),
40814
42604
  [formData, externalContext]
40815
42605
  );
40816
- React72__default.useEffect(() => {
42606
+ React74__default.useEffect(() => {
40817
42607
  debug("forms", "initialData-sync", {
40818
42608
  mode: formMode,
40819
42609
  normalizedInitialData,
@@ -40824,7 +42614,7 @@ var init_Form = __esm({
40824
42614
  setFormData(normalizedInitialData);
40825
42615
  }
40826
42616
  }, [normalizedInitialData]);
40827
- const processCalculations = React72__default.useCallback(
42617
+ const processCalculations = React74__default.useCallback(
40828
42618
  (changedFieldId, newFormData) => {
40829
42619
  if (!hiddenCalculations.length) return;
40830
42620
  const context = {
@@ -40849,7 +42639,7 @@ var init_Form = __esm({
40849
42639
  },
40850
42640
  [hiddenCalculations, externalContext, eventBus]
40851
42641
  );
40852
- const checkViolations = React72__default.useCallback(
42642
+ const checkViolations = React74__default.useCallback(
40853
42643
  (changedFieldId, newFormData) => {
40854
42644
  if (!violationTriggers.length) return;
40855
42645
  const context = {
@@ -40887,7 +42677,7 @@ var init_Form = __esm({
40887
42677
  processCalculations(name, newFormData);
40888
42678
  checkViolations(name, newFormData);
40889
42679
  };
40890
- const isFieldVisible = React72__default.useCallback(
42680
+ const isFieldVisible = React74__default.useCallback(
40891
42681
  (fieldName) => {
40892
42682
  const condition = conditionalFields[fieldName];
40893
42683
  if (!condition) return true;
@@ -40895,7 +42685,7 @@ var init_Form = __esm({
40895
42685
  },
40896
42686
  [conditionalFields, evalContext]
40897
42687
  );
40898
- const isSectionVisible = React72__default.useCallback(
42688
+ const isSectionVisible = React74__default.useCallback(
40899
42689
  (section) => {
40900
42690
  if (!section.condition) return true;
40901
42691
  return Boolean(evaluateFormExpression(section.condition, evalContext));
@@ -40971,7 +42761,7 @@ var init_Form = __esm({
40971
42761
  eventBus.emit(`UI:${onCancel}`);
40972
42762
  }
40973
42763
  };
40974
- const renderField = React72__default.useCallback(
42764
+ const renderField = React74__default.useCallback(
40975
42765
  (field) => {
40976
42766
  const fieldName = field.name || field.field;
40977
42767
  if (!fieldName) return null;
@@ -40992,7 +42782,7 @@ var init_Form = __esm({
40992
42782
  [formData, isFieldVisible, relationsData, relationsLoading, isLoading]
40993
42783
  );
40994
42784
  const effectiveFields = entityDerivedFields ?? fields;
40995
- const normalizedFields = React72__default.useMemo(() => {
42785
+ const normalizedFields = React74__default.useMemo(() => {
40996
42786
  if (!effectiveFields || effectiveFields.length === 0) return [];
40997
42787
  return effectiveFields.map((field) => {
40998
42788
  if (typeof field === "string") {
@@ -41016,7 +42806,7 @@ var init_Form = __esm({
41016
42806
  return field;
41017
42807
  });
41018
42808
  }, [effectiveFields, resolvedEntity]);
41019
- const schemaFields = React72__default.useMemo(() => {
42809
+ const schemaFields = React74__default.useMemo(() => {
41020
42810
  if (normalizedFields.length === 0) return null;
41021
42811
  if (isDebugEnabled()) {
41022
42812
  debugGroup(`Form: ${entityName || "unknown"}`);
@@ -41026,7 +42816,7 @@ var init_Form = __esm({
41026
42816
  }
41027
42817
  return normalizedFields.map(renderField).filter(Boolean);
41028
42818
  }, [normalizedFields, renderField, entityName, conditionalFields]);
41029
- const sectionElements = React72__default.useMemo(() => {
42819
+ const sectionElements = React74__default.useMemo(() => {
41030
42820
  if (!sections || sections.length === 0) return null;
41031
42821
  return sections.map((section) => {
41032
42822
  if (!isSectionVisible(section)) {
@@ -41751,7 +43541,7 @@ var init_List = __esm({
41751
43541
  if (entity && typeof entity === "object" && "id" in entity) return [entity];
41752
43542
  return [];
41753
43543
  }, [entity]);
41754
- const getItemActions = React72__default.useCallback(
43544
+ const getItemActions = React74__default.useCallback(
41755
43545
  (item) => {
41756
43546
  if (!itemActions) return [];
41757
43547
  if (typeof itemActions === "function") {
@@ -42226,7 +44016,7 @@ var init_MediaGallery = __esm({
42226
44016
  [selectable, selectedItems, selectionEvent, eventBus]
42227
44017
  );
42228
44018
  const entityData = Array.isArray(entity) ? entity : [];
42229
- const items = React72__default.useMemo(() => {
44019
+ const items = React74__default.useMemo(() => {
42230
44020
  if (propItems) return propItems;
42231
44021
  if (entityData.length === 0) return [];
42232
44022
  return entityData.map((record, idx) => {
@@ -42389,7 +44179,7 @@ var init_MediaGallery = __esm({
42389
44179
  }
42390
44180
  });
42391
44181
  function extractTitle2(children) {
42392
- if (!React72__default.isValidElement(children)) return void 0;
44182
+ if (!React74__default.isValidElement(children)) return void 0;
42393
44183
  const props = children.props;
42394
44184
  if (typeof props.title === "string") {
42395
44185
  return props.title;
@@ -42644,7 +44434,7 @@ var init_debugRegistry = __esm({
42644
44434
  }
42645
44435
  });
42646
44436
  function useDebugData() {
42647
- const [data, setData] = React72.useState(() => ({
44437
+ const [data, setData] = React74.useState(() => ({
42648
44438
  traits: [],
42649
44439
  ticks: [],
42650
44440
  guards: [],
@@ -42658,7 +44448,7 @@ function useDebugData() {
42658
44448
  },
42659
44449
  lastUpdate: Date.now()
42660
44450
  }));
42661
- React72.useEffect(() => {
44451
+ React74.useEffect(() => {
42662
44452
  const updateData = () => {
42663
44453
  setData({
42664
44454
  traits: getAllTraits(),
@@ -42767,12 +44557,12 @@ function layoutGraph(states, transitions, initialState, width, height) {
42767
44557
  return positions;
42768
44558
  }
42769
44559
  function WalkMinimap() {
42770
- const [walkStep, setWalkStep] = React72.useState(null);
42771
- const [traits2, setTraits] = React72.useState([]);
42772
- const [coveredEdges, setCoveredEdges] = React72.useState([]);
42773
- const [completedTraits, setCompletedTraits] = React72.useState(/* @__PURE__ */ new Set());
42774
- const prevTraitRef = React72.useRef(null);
42775
- React72.useEffect(() => {
44560
+ const [walkStep, setWalkStep] = React74.useState(null);
44561
+ const [traits2, setTraits] = React74.useState([]);
44562
+ const [coveredEdges, setCoveredEdges] = React74.useState([]);
44563
+ const [completedTraits, setCompletedTraits] = React74.useState(/* @__PURE__ */ new Set());
44564
+ const prevTraitRef = React74.useRef(null);
44565
+ React74.useEffect(() => {
42776
44566
  const interval = setInterval(() => {
42777
44567
  const w = window;
42778
44568
  const step = w.__orbitalWalkStep;
@@ -43208,15 +44998,15 @@ var init_EntitiesTab = __esm({
43208
44998
  });
43209
44999
  function EventFlowTab({ events: events2 }) {
43210
45000
  const { t } = useTranslate();
43211
- const [filter, setFilter] = React72.useState("all");
43212
- const containerRef = React72.useRef(null);
43213
- const [autoScroll, setAutoScroll] = React72.useState(true);
43214
- React72.useEffect(() => {
45001
+ const [filter, setFilter] = React74.useState("all");
45002
+ const containerRef = React74.useRef(null);
45003
+ const [autoScroll, setAutoScroll] = React74.useState(true);
45004
+ React74.useEffect(() => {
43215
45005
  if (autoScroll && containerRef.current) {
43216
45006
  containerRef.current.scrollTop = containerRef.current.scrollHeight;
43217
45007
  }
43218
45008
  }, [events2.length, autoScroll]);
43219
- const filteredEvents = React72.useMemo(() => {
45009
+ const filteredEvents = React74.useMemo(() => {
43220
45010
  if (filter === "all") return events2;
43221
45011
  return events2.filter((e) => e.type === filter);
43222
45012
  }, [events2, filter]);
@@ -43332,7 +45122,7 @@ var init_EventFlowTab = __esm({
43332
45122
  });
43333
45123
  function GuardsPanel({ guards }) {
43334
45124
  const { t } = useTranslate();
43335
- const [filter, setFilter] = React72.useState("all");
45125
+ const [filter, setFilter] = React74.useState("all");
43336
45126
  if (guards.length === 0) {
43337
45127
  return /* @__PURE__ */ jsx(
43338
45128
  EmptyState,
@@ -43345,7 +45135,7 @@ function GuardsPanel({ guards }) {
43345
45135
  }
43346
45136
  const passedCount = guards.filter((g) => g.result).length;
43347
45137
  const failedCount = guards.length - passedCount;
43348
- const filteredGuards = React72.useMemo(() => {
45138
+ const filteredGuards = React74.useMemo(() => {
43349
45139
  if (filter === "all") return guards;
43350
45140
  if (filter === "passed") return guards.filter((g) => g.result);
43351
45141
  return guards.filter((g) => !g.result);
@@ -43508,10 +45298,10 @@ function EffectBadge({ effect }) {
43508
45298
  }
43509
45299
  function TransitionTimeline({ transitions }) {
43510
45300
  const { t } = useTranslate();
43511
- const containerRef = React72.useRef(null);
43512
- const [autoScroll, setAutoScroll] = React72.useState(true);
43513
- const [expandedId, setExpandedId] = React72.useState(null);
43514
- React72.useEffect(() => {
45301
+ const containerRef = React74.useRef(null);
45302
+ const [autoScroll, setAutoScroll] = React74.useState(true);
45303
+ const [expandedId, setExpandedId] = React74.useState(null);
45304
+ React74.useEffect(() => {
43515
45305
  if (autoScroll && containerRef.current) {
43516
45306
  containerRef.current.scrollTop = containerRef.current.scrollHeight;
43517
45307
  }
@@ -43791,9 +45581,9 @@ function getAllEvents(traits2) {
43791
45581
  function EventDispatcherTab({ traits: traits2, schema }) {
43792
45582
  const eventBus = useEventBus();
43793
45583
  const { t } = useTranslate();
43794
- const [log18, setLog] = React72.useState([]);
43795
- const prevStatesRef = React72.useRef(/* @__PURE__ */ new Map());
43796
- React72.useEffect(() => {
45584
+ const [log18, setLog] = React74.useState([]);
45585
+ const prevStatesRef = React74.useRef(/* @__PURE__ */ new Map());
45586
+ React74.useEffect(() => {
43797
45587
  for (const trait of traits2) {
43798
45588
  const prev = prevStatesRef.current.get(trait.id);
43799
45589
  if (prev && prev !== trait.currentState) {
@@ -43962,10 +45752,10 @@ function VerifyModePanel({
43962
45752
  localCount
43963
45753
  }) {
43964
45754
  const { t } = useTranslate();
43965
- const [expanded, setExpanded] = React72.useState(true);
43966
- const scrollRef = React72.useRef(null);
43967
- const prevCountRef = React72.useRef(0);
43968
- React72.useEffect(() => {
45755
+ const [expanded, setExpanded] = React74.useState(true);
45756
+ const scrollRef = React74.useRef(null);
45757
+ const prevCountRef = React74.useRef(0);
45758
+ React74.useEffect(() => {
43969
45759
  if (expanded && transitions.length > prevCountRef.current && scrollRef.current) {
43970
45760
  scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
43971
45761
  }
@@ -44022,10 +45812,10 @@ function RuntimeDebugger({
44022
45812
  schema
44023
45813
  }) {
44024
45814
  const { t } = useTranslate();
44025
- const [isCollapsed, setIsCollapsed] = React72.useState(mode === "verify" ? true : defaultCollapsed);
44026
- const [isVisible, setIsVisible] = React72.useState(mode === "inline" || mode === "verify" || isDebugEnabled2());
45815
+ const [isCollapsed, setIsCollapsed] = React74.useState(mode === "verify" ? true : defaultCollapsed);
45816
+ const [isVisible, setIsVisible] = React74.useState(mode === "inline" || mode === "verify" || isDebugEnabled2());
44027
45817
  const debugData = useDebugData();
44028
- React72.useEffect(() => {
45818
+ React74.useEffect(() => {
44029
45819
  if (mode === "inline") return;
44030
45820
  return onDebugToggle((enabled) => {
44031
45821
  setIsVisible(enabled);
@@ -44034,7 +45824,7 @@ function RuntimeDebugger({
44034
45824
  }
44035
45825
  });
44036
45826
  }, [mode]);
44037
- React72.useEffect(() => {
45827
+ React74.useEffect(() => {
44038
45828
  if (mode === "inline") return;
44039
45829
  const handleKeyDown = (e) => {
44040
45830
  if (e.key === "`" && isVisible) {
@@ -44554,7 +46344,7 @@ var init_StatCard = __esm({
44554
46344
  const labelToUse = propLabel ?? propTitle;
44555
46345
  const eventBus = useEventBus();
44556
46346
  const { t } = useTranslate();
44557
- const handleActionClick = React72__default.useCallback(() => {
46347
+ const handleActionClick = React74__default.useCallback(() => {
44558
46348
  if (action?.event) {
44559
46349
  eventBus.emit(`UI:${action.event}`, {});
44560
46350
  }
@@ -44565,7 +46355,7 @@ var init_StatCard = __esm({
44565
46355
  const data = Array.isArray(entity) ? entity : entity ? [entity] : [];
44566
46356
  const isLoading = externalLoading ?? false;
44567
46357
  const error = externalError;
44568
- const computeMetricValue = React72__default.useCallback(
46358
+ const computeMetricValue = React74__default.useCallback(
44569
46359
  (metric, items) => {
44570
46360
  if (metric.value !== void 0) {
44571
46361
  return metric.value;
@@ -44604,7 +46394,7 @@ var init_StatCard = __esm({
44604
46394
  },
44605
46395
  []
44606
46396
  );
44607
- const schemaStats = React72__default.useMemo(() => {
46397
+ const schemaStats = React74__default.useMemo(() => {
44608
46398
  if (!metrics || metrics.length === 0) return null;
44609
46399
  return metrics.map((metric) => ({
44610
46400
  label: metric.label,
@@ -44612,7 +46402,7 @@ var init_StatCard = __esm({
44612
46402
  format: metric.format
44613
46403
  }));
44614
46404
  }, [metrics, data, computeMetricValue]);
44615
- const calculatedTrend = React72__default.useMemo(() => {
46405
+ const calculatedTrend = React74__default.useMemo(() => {
44616
46406
  if (manualTrend !== void 0) return manualTrend;
44617
46407
  if (previousValue === void 0 || currentValue2 === void 0)
44618
46408
  return void 0;
@@ -45252,8 +47042,8 @@ var init_SubagentTracePanel = __esm({
45252
47042
  ] });
45253
47043
  };
45254
47044
  InlineActivityStream = ({ activities, autoScroll = true, className }) => {
45255
- const endRef = React72__default.useRef(null);
45256
- React72__default.useEffect(() => {
47045
+ const endRef = React74__default.useRef(null);
47046
+ React74__default.useEffect(() => {
45257
47047
  if (!autoScroll) return;
45258
47048
  endRef.current?.scrollIntoView({ behavior: "smooth", block: "end" });
45259
47049
  }, [activities.length, autoScroll]);
@@ -45347,7 +47137,7 @@ var init_SubagentTracePanel = __esm({
45347
47137
  };
45348
47138
  SubagentRichCard = ({ subagent }) => {
45349
47139
  const { t } = useTranslate();
45350
- const activities = React72__default.useMemo(
47140
+ const activities = React74__default.useMemo(
45351
47141
  () => subagentMessagesToActivities(subagent.messages),
45352
47142
  [subagent.messages]
45353
47143
  );
@@ -45424,8 +47214,8 @@ var init_SubagentTracePanel = __esm({
45424
47214
  ] });
45425
47215
  };
45426
47216
  CoordinatorConversation = ({ messages, autoScroll = true, className }) => {
45427
- const endRef = React72__default.useRef(null);
45428
- React72__default.useEffect(() => {
47217
+ const endRef = React74__default.useRef(null);
47218
+ React74__default.useEffect(() => {
45429
47219
  if (!autoScroll) return;
45430
47220
  endRef.current?.scrollIntoView({ behavior: "smooth", block: "end" });
45431
47221
  }, [messages.length, autoScroll]);
@@ -45855,7 +47645,7 @@ var init_Timeline = __esm({
45855
47645
  }) => {
45856
47646
  const { t } = useTranslate();
45857
47647
  const entityData = entity ?? [];
45858
- const items = React72__default.useMemo(() => {
47648
+ const items = React74__default.useMemo(() => {
45859
47649
  if (propItems) return propItems;
45860
47650
  if (entityData.length === 0) return [];
45861
47651
  return entityData.map((record, idx) => {
@@ -45957,7 +47747,7 @@ var init_Timeline = __esm({
45957
47747
  }
45958
47748
  });
45959
47749
  function extractToastProps(children) {
45960
- if (!React72__default.isValidElement(children)) {
47750
+ if (!React74__default.isValidElement(children)) {
45961
47751
  if (typeof children === "string") {
45962
47752
  return { message: children };
45963
47753
  }
@@ -45999,7 +47789,7 @@ var init_ToastSlot = __esm({
45999
47789
  eventBus.emit(`${prefix}CLOSE`);
46000
47790
  };
46001
47791
  if (!isVisible) return null;
46002
- const isCustomContent = React72__default.isValidElement(children) && !message;
47792
+ const isCustomContent = React74__default.isValidElement(children) && !message;
46003
47793
  return /* @__PURE__ */ jsx(Box, { className: "fixed bottom-4 right-4 z-50", children: isCustomContent ? children : /* @__PURE__ */ jsx(
46004
47794
  Toast,
46005
47795
  {
@@ -46016,7 +47806,7 @@ var init_ToastSlot = __esm({
46016
47806
  }
46017
47807
  });
46018
47808
  function lazyThree(name, loader) {
46019
- const Lazy = React72__default.lazy(
47809
+ const Lazy = React74__default.lazy(
46020
47810
  () => loader().then((m) => {
46021
47811
  const Resolved = m[name];
46022
47812
  if (!Resolved) {
@@ -46028,13 +47818,13 @@ function lazyThree(name, loader) {
46028
47818
  })
46029
47819
  );
46030
47820
  function ThreeWrapper(props) {
46031
- return React72__default.createElement(
47821
+ return React74__default.createElement(
46032
47822
  ThreeBoundary,
46033
47823
  { name },
46034
- React72__default.createElement(
46035
- React72__default.Suspense,
47824
+ React74__default.createElement(
47825
+ React74__default.Suspense,
46036
47826
  { fallback: null },
46037
- React72__default.createElement(Lazy, props)
47827
+ React74__default.createElement(Lazy, props)
46038
47828
  )
46039
47829
  );
46040
47830
  }
@@ -46070,6 +47860,7 @@ var init_component_registry_generated = __esm({
46070
47860
  init_LayoutPatterns();
46071
47861
  init_BranchingLogicBuilder();
46072
47862
  init_Breadcrumb();
47863
+ init_BuilderBoard();
46073
47864
  init_CTABanner();
46074
47865
  init_CalendarGrid();
46075
47866
  init_Canvas2D();
@@ -46085,6 +47876,7 @@ var init_component_registry_generated = __esm({
46085
47876
  init_Checkbox();
46086
47877
  init_ChemistryCanvas();
46087
47878
  init_ChoiceButton();
47879
+ init_ClassifierBoard();
46088
47880
  init_CodeBlock();
46089
47881
  init_CodeRunnerPanel();
46090
47882
  init_ComboCounter();
@@ -46108,6 +47900,7 @@ var init_component_registry_generated = __esm({
46108
47900
  init_DateRangePicker();
46109
47901
  init_DateRangeSelector();
46110
47902
  init_DayCell();
47903
+ init_DebuggerBoard();
46111
47904
  init_DetailPanel();
46112
47905
  init_Dialog();
46113
47906
  init_DialogueBubble();
@@ -46123,6 +47916,7 @@ var init_component_registry_generated = __esm({
46123
47916
  init_EmptyState();
46124
47917
  init_ErrorBoundary();
46125
47918
  init_ErrorState();
47919
+ init_EventHandlerBoard();
46126
47920
  init_EventLog();
46127
47921
  init_FeatureCard();
46128
47922
  init_FeatureDetailPageTemplate();
@@ -46189,6 +47983,7 @@ var init_component_registry_generated = __esm({
46189
47983
  init_ModalSlot();
46190
47984
  init_ModuleCard();
46191
47985
  init_Navigation();
47986
+ init_NegotiatorBoard();
46192
47987
  init_NumberStepper();
46193
47988
  init_OptionConstraintGroup();
46194
47989
  init_OrbitalVisualization();
@@ -46227,6 +48022,7 @@ var init_component_registry_generated = __esm({
46227
48022
  init_SegmentRenderer();
46228
48023
  init_Select();
46229
48024
  init_SequenceBar();
48025
+ init_SequencerBoard();
46230
48026
  init_ServiceCatalog();
46231
48027
  init_ShowcaseCard();
46232
48028
  init_ShowcaseOrganism();
@@ -46235,6 +48031,7 @@ var init_component_registry_generated = __esm({
46235
48031
  init_SignaturePad();
46236
48032
  init_SimpleGrid();
46237
48033
  init_SimulationCanvas();
48034
+ init_SimulatorBoard();
46238
48035
  init_Skeleton();
46239
48036
  init_SocialProof();
46240
48037
  init_SortableList();
@@ -46248,6 +48045,8 @@ var init_component_registry_generated = __esm({
46248
48045
  init_StatBadge();
46249
48046
  init_StatCard();
46250
48047
  init_StatDisplay();
48048
+ init_StateArchitectBoard();
48049
+ init_StateGraph();
46251
48050
  init_StateIndicator();
46252
48051
  init_StateMachineView();
46253
48052
  init_StatsGrid();
@@ -46302,7 +48101,7 @@ var init_component_registry_generated = __esm({
46302
48101
  init_WizardContainer();
46303
48102
  init_WizardNavigation();
46304
48103
  init_WizardProgress();
46305
- ThreeBoundary = class extends React72__default.Component {
48104
+ ThreeBoundary = class extends React74__default.Component {
46306
48105
  constructor() {
46307
48106
  super(...arguments);
46308
48107
  __publicField(this, "state", { failed: false });
@@ -46312,7 +48111,7 @@ var init_component_registry_generated = __esm({
46312
48111
  }
46313
48112
  render() {
46314
48113
  if (this.state.failed) {
46315
- return React72__default.createElement(
48114
+ return React74__default.createElement(
46316
48115
  "div",
46317
48116
  {
46318
48117
  "data-testid": "three-unavailable",
@@ -46358,6 +48157,7 @@ var init_component_registry_generated = __esm({
46358
48157
  "BoxPattern": BoxPattern,
46359
48158
  "BranchingLogicBuilder": BranchingLogicBuilder,
46360
48159
  "Breadcrumb": Breadcrumb,
48160
+ "BuilderBoard": BuilderBoard,
46361
48161
  "Button": ButtonPattern,
46362
48162
  "ButtonPattern": ButtonPattern,
46363
48163
  "CTABanner": CTABanner,
@@ -46375,6 +48175,7 @@ var init_component_registry_generated = __esm({
46375
48175
  "Checkbox": Checkbox,
46376
48176
  "ChemistryCanvas": ChemistryCanvas,
46377
48177
  "ChoiceButton": ChoiceButton,
48178
+ "ClassifierBoard": ClassifierBoard,
46378
48179
  "CodeBlock": CodeBlock,
46379
48180
  "CodeRunnerPanel": CodeRunnerPanel,
46380
48181
  "ComboCounter": ComboCounter,
@@ -46398,6 +48199,7 @@ var init_component_registry_generated = __esm({
46398
48199
  "DateRangePicker": DateRangePicker,
46399
48200
  "DateRangeSelector": DateRangeSelector,
46400
48201
  "DayCell": DayCell,
48202
+ "DebuggerBoard": DebuggerBoard,
46401
48203
  "DetailPanel": DetailPanel,
46402
48204
  "Dialog": Dialog,
46403
48205
  "DialogueBubble": DialogueBubble,
@@ -46415,6 +48217,7 @@ var init_component_registry_generated = __esm({
46415
48217
  "EmptyState": EmptyState,
46416
48218
  "ErrorBoundary": ErrorBoundary,
46417
48219
  "ErrorState": ErrorState,
48220
+ "EventHandlerBoard": EventHandlerBoard,
46418
48221
  "EventLog": EventLog,
46419
48222
  "FeatureCard": FeatureCard,
46420
48223
  "FeatureDetailPageTemplate": FeatureDetailPageTemplate,
@@ -46489,6 +48292,7 @@ var init_component_registry_generated = __esm({
46489
48292
  "ModalSlot": ModalSlot,
46490
48293
  "ModuleCard": ModuleCard,
46491
48294
  "Navigation": Navigation,
48295
+ "NegotiatorBoard": NegotiatorBoard,
46492
48296
  "NumberStepper": NumberStepper,
46493
48297
  "OptionConstraintGroup": OptionConstraintGroup,
46494
48298
  "OrbitalVisualization": OrbitalVisualization,
@@ -46527,6 +48331,7 @@ var init_component_registry_generated = __esm({
46527
48331
  "SegmentRenderer": SegmentRenderer,
46528
48332
  "Select": Select,
46529
48333
  "SequenceBar": SequenceBar,
48334
+ "SequencerBoard": SequencerBoard,
46530
48335
  "ServiceCatalog": ServiceCatalog,
46531
48336
  "ShowcaseCard": ShowcaseCard,
46532
48337
  "ShowcaseOrganism": ShowcaseOrganism,
@@ -46535,6 +48340,7 @@ var init_component_registry_generated = __esm({
46535
48340
  "SignaturePad": SignaturePad,
46536
48341
  "SimpleGrid": SimpleGrid,
46537
48342
  "SimulationCanvas": SimulationCanvas,
48343
+ "SimulatorBoard": SimulatorBoard,
46538
48344
  "Skeleton": Skeleton,
46539
48345
  "SocialProof": SocialProof,
46540
48346
  "SortableList": SortableList,
@@ -46551,6 +48357,8 @@ var init_component_registry_generated = __esm({
46551
48357
  "StatBadge": StatBadge,
46552
48358
  "StatCard": StatCard,
46553
48359
  "StatDisplay": StatDisplay,
48360
+ "StateArchitectBoard": StateArchitectBoard,
48361
+ "StateGraph": StateGraph,
46554
48362
  "StateIndicator": StateIndicator,
46555
48363
  "StateMachineView": StateMachineView,
46556
48364
  "StatsGrid": StatsGrid,
@@ -46624,7 +48432,7 @@ function SuspenseConfigProvider({
46624
48432
  config,
46625
48433
  children
46626
48434
  }) {
46627
- return React72__default.createElement(
48435
+ return React74__default.createElement(
46628
48436
  SuspenseConfigContext.Provider,
46629
48437
  { value: config },
46630
48438
  children
@@ -46666,7 +48474,7 @@ function enrichFormFields(fields, entityDef) {
46666
48474
  }
46667
48475
  return { name: field, label: field.replace(/([a-z])([A-Z])/g, "$1 $2").replace(/\b\w/g, (c) => c.toUpperCase()) };
46668
48476
  }
46669
- if (field && typeof field === "object" && !Array.isArray(field) && !React72__default.isValidElement(field) && !(field instanceof Date)) {
48477
+ if (field && typeof field === "object" && !Array.isArray(field) && !React74__default.isValidElement(field) && !(field instanceof Date)) {
46670
48478
  const obj = field;
46671
48479
  const fieldName = typeof obj.name === "string" ? obj.name : typeof obj.field === "string" ? obj.field : void 0;
46672
48480
  if (!fieldName) return field;
@@ -47119,7 +48927,7 @@ function renderPatternChildren(children, onDismiss, parentId = "root", parentPat
47119
48927
  const key = `${parentId}-${index}-trait:${traitName}`;
47120
48928
  return /* @__PURE__ */ jsx(TraitFrame, { traitName }, key);
47121
48929
  }
47122
- return /* @__PURE__ */ jsx(React72__default.Fragment, { children: child }, `${parentId}-${index}`);
48930
+ return /* @__PURE__ */ jsx(React74__default.Fragment, { children: child }, `${parentId}-${index}`);
47123
48931
  }
47124
48932
  if (!child || typeof child !== "object") return null;
47125
48933
  const childId = `${parentId}-${index}`;
@@ -47159,14 +48967,14 @@ function isPatternConfig(value) {
47159
48967
  if (value === null || value === void 0) return false;
47160
48968
  if (typeof value !== "object") return false;
47161
48969
  if (Array.isArray(value)) return false;
47162
- if (React72__default.isValidElement(value)) return false;
48970
+ if (React74__default.isValidElement(value)) return false;
47163
48971
  if (value instanceof Date) return false;
47164
48972
  if (typeof value === "function") return false;
47165
48973
  const record = value;
47166
48974
  return "type" in record && typeof record.type === "string" && getComponentForPattern$1(record.type) !== null;
47167
48975
  }
47168
48976
  function isPlainConfigObject(value) {
47169
- if (React72__default.isValidElement(value)) return false;
48977
+ if (React74__default.isValidElement(value)) return false;
47170
48978
  if (value instanceof Date) return false;
47171
48979
  const proto = Object.getPrototypeOf(value);
47172
48980
  return proto === Object.prototype || proto === null;
@@ -47292,7 +49100,7 @@ function SlotContentRenderer({
47292
49100
  for (const slotKey of CONTENT_NODE_SLOTS) {
47293
49101
  const slotVal = restProps[slotKey];
47294
49102
  if (slotVal === void 0 || slotVal === null) continue;
47295
- if (React72__default.isValidElement(slotVal) || typeof slotVal === "string" || typeof slotVal === "number" || typeof slotVal === "boolean") continue;
49103
+ if (React74__default.isValidElement(slotVal) || typeof slotVal === "string" || typeof slotVal === "number" || typeof slotVal === "boolean") continue;
47296
49104
  if (Array.isArray(slotVal) || typeof slotVal === "object" && "type" in slotVal) {
47297
49105
  nodeSlotOverrides[slotKey] = renderPatternChildren(
47298
49106
  slotVal,
@@ -47341,7 +49149,7 @@ function SlotContentRenderer({
47341
49149
  const resolvedItems = Array.isArray(entityVal) && entityVal[0] !== "fn" ? entityVal : null;
47342
49150
  if (resolvedItems && resolvedItems.length > 0 && !finalProps.fields && !finalProps.columns) {
47343
49151
  const sample = resolvedItems[0];
47344
- if (sample && typeof sample === "object" && !Array.isArray(sample) && !React72__default.isValidElement(sample) && !(sample instanceof Date)) {
49152
+ if (sample && typeof sample === "object" && !Array.isArray(sample) && !React74__default.isValidElement(sample) && !(sample instanceof Date)) {
47345
49153
  const keys = Object.keys(sample).filter((k) => k !== "id" && k !== "_id");
47346
49154
  finalProps.fields = keys.map((k, i) => ({ name: k, variant: i === 0 ? "h4" : "body" }));
47347
49155
  }
@@ -49641,7 +51449,7 @@ var I18nContext = createContext({
49641
51449
  });
49642
51450
  I18nContext.displayName = "I18nContext";
49643
51451
  var I18nProvider = I18nContext.Provider;
49644
- function useTranslate119() {
51452
+ function useTranslate127() {
49645
51453
  return useContext(I18nContext);
49646
51454
  }
49647
51455
  function createTranslate(messages) {
@@ -49842,4 +51650,4 @@ function useGitHubBranches(owner, repo, enabled = true) {
49842
51650
  });
49843
51651
  }
49844
51652
 
49845
- export { ALL_PRESETS, ALMADAR_DND_MIME, AR_BOOK_FIELDS, AboutPageTemplate, Accordion, ActionButton, Card2 as ActionCard, ActionPalette, ActionTile, ActivationBlock, Alert, AnimatedCounter, AnimatedGraphic, AnimatedReveal, ArticleSection, Aside, AssetPicker, AuthLayout, Avatar, Badge, BehaviorView, BiologyCanvas, BloomQuizBlock, BookChapterView, BookCoverPage, BookNavBar, BookTableOfContents, BookViewer, Box, BranchingLogicBuilder, Breadcrumb, Button, ButtonGroup, CTABanner, CalendarGrid, Canvas2D, Card, CardBody, CardContent, CardFooter, CardGrid, CardHeader, CardTitle, Carousel, CaseStudyCard, CaseStudyOrganism, Center, Chart, ChartLegend, ChatBar, Checkbox, ChemistryCanvas, ChoiceButton, Coachmark, CodeBlock, CodeRunnerPanel, CollapsibleSection, ComboCounter, CommunityLinks, ConditionalWrapper, ConfettiEffect, ConfirmDialog, ConnectionBlock, Container, ContentRenderer, ContentSection, ControlButton, ControlGrid, CounterTemplate, DEFAULT_LIKERT_OPTIONS, DEFAULT_MATRIX_COLUMNS, DEFAULT_SLOTS, DIAMOND_TOP_Y, DamageNumber, DashboardGrid, DashboardLayout, DataGrid, DataList, DataTable, DateRangePicker, DateRangeSelector, DayCell, DetailPanel, Dialog, DialogueBubble, Divider, DocBreadcrumb, DocPagination, DocSearch, DocSidebar, DocTOC, DocumentViewer, StateMachineView as DomStateMachineVisualizer, Drawer, DrawerSlot, ELEMENT_SELECTED_EVENT, EMPTY_EFFECT_STATE, EdgeDecoration, EditorCheckbox, EditorSelect, EditorSlider, EditorTextInput, EditorToolbar, EmptyState, EntityDisplayEvents, ErrorBoundary, ErrorState, EventLog, FEATURE_COLORS, FEATURE_TYPES, FLOOR_HEIGHT, FeatureCard, FeatureDetailPageTemplate, FeatureGrid, FeatureGridOrganism, FileTree, FilterGroup, FilterPill, Flex, FlipCard, FlipContainer, FloatingActionButton, Form, FormActions, FormField, FormLayout, FormSection, FormSectionHeader, GameAudioContext, GameAudioProvider, GameAudioToggle, GameCard, GameHud, GameIcon, GameMenu, GameShell, GameTemplate, GenericAppTemplate, GeometricPattern, GradientDivider, GraphCanvas, GraphView, Grid, GridPicker, HStack, Header, HealthBar, HeroOrganism, HeroSection, I18nProvider, IDENTITY_BOOK_FIELDS, Icon, IconPicker, InfiniteScrollSentinel, Input, InputGroup, InstallBox, InventoryGrid, ItemSlot, JazariStateMachine, JsonTreeEditor, Label, LandingPageTemplate, LawReferenceTooltip, LearningCanvas, Lightbox, LikertScale, LineChart2 as LineChart, List3 as List, LoadingState, MapView, MarkdownContent, MarketingFooter, MarketingStatCard, MasterDetail, MasterDetailLayout, MathCanvas, MatrixQuestion, MediaGallery, Menu, Meter, MiniMap, Modal, ModalSlot, ModuleCard, Navigation, NodeSlotEditor, NotifyListener, NumberStepper, ObjectRulePanel, OnboardingSpotlight, OptionConstraintGroup, StateMachineView as OrbitalStateMachineView, OrbitalVisualization, Overlay, PageHeader, Pagination, PatternTile, PhysicsCanvas, Popover, PositionedCanvas, PricingCard, PricingGrid, PricingOrganism, PricingPageTemplate, ProgressBar, ProgressDots, PropertyInspector, PullQuote, PullToRefresh, QrScanner, QuizBlock, Radio, RangeSlider, ReflectionBlock, RelationSelect, RepeatableFormSection, ReplyTree, ResourceBar, ResourceCounter, RichBlockEditor, RuleEditor, RuntimeDebugger, SHEET_COLUMNS, SPRITE_SHEET_LAYOUT, ScaledDiagram, ScoreDisplay, SearchInput, Section, SectionHeader, SegmentRenderer, Select, SequenceBar, ServiceCatalog, ShowcaseCard, ShowcaseOrganism, SidePanel, Sidebar, SignaturePad, SimpleGrid, SimulationCanvas, SimulationControls, SimulationGraph, Skeleton, SlotContentRenderer, SocialProof, SortableList, Spacer, Sparkline, Spinner, Split, SplitPane, SplitSection, Sprite, Stack, StarRating, StatBadge, StatCard, StatDisplay, StateIndicator, StateJsonView, StateMachineView, StateNode2 as StateNode, StatsGrid, StatsOrganism, StatusBar, StatusDot, StatusEffect, StepFlow, StepFlowOrganism, SubagentTracePanel, SvgBranch, SvgConnection, SvgFlow, SvgGrid, SvgLobe, SvgMesh, SvgMorph, SvgNode, SvgPulse, SvgRing, SvgShield, SvgStack, SwipeableRow, Switch, TERRAIN_COLORS, TILE_HEIGHT, TILE_WIDTH, TabbedContainer, TableView, Tabs, TagCloud, TagInput, TeamCard, TeamOrganism, TerrainPalette, TextHighlight, Textarea, ThemeToggle, TimeSlotCell, Timeline, TimerDisplay, Toast, ToastSlot, Tooltip, TraitFrame, TraitSlot, TraitStateViewer, TransitionArrow, TrendIndicator, TurnIndicator, TypewriterText, Typography, UISlotComponent, UISlotRenderer, UploadDropZone, VStack, VariablePanel, VersionDiff, ViolationAlert, VoteStack, WaypointMarker, WizardContainer, WizardNavigation, WizardProgress, boardEntity, bool, calculateAttackTargets, calculateValidMoves, cn, createInitialGameState, createTranslate, createUnitAnimationState, drawSprite, getCurrentFrame, getTileDimensions, inferDirection, isoToScreen, makeAsset, makeAssetMap, mapBookData, num, objAvailableActions, objAvailableEvents, objCurrentState, objIcon, objId, objMaxRules, objName, objRules, objStates, parseEditFocus, parseLessonSegments, parseMarkdownWithCodeBlocks, parseQueryBinding, pendulum, projectileMotion, resolveFieldMap, resolveFrame, resolveSheetDirection, rows, screenToIso, springOscillator, str, tickAnimationState, toCodeLanguage, transitionAnimation, unitHealth, unitPosition, unitTeam, useAgentChat, useAnchorRect, useAuthContext, useCamera, useCanvasGestures, useCompile, useConnectGitHub, useDeepAgentGeneration, useDisconnectGitHub, useDragReorder, useDraggable, useDropZone, useEmitEvent, useEventBus, useEventListener, useExtensions, useFileEditor, useFileSystem, useGameAudio, useGameAudioContext, useGitHubBranches, useGitHubRepo, useGitHubRepos, useGitHubStatus, useImageCache, useInfiniteScroll, useLongPress, useOrbitalHistory, usePreview, usePullToRefresh, useQuerySingleton, useRenderInterpolation, useSwipeGesture, useTapReveal, useTraitListens, useTranslate119 as useTranslate, useUIEvents, useUISlotManager, useUnitSpriteAtlas, useValidation, vec2 };
51653
+ export { ALL_PRESETS, ALMADAR_DND_MIME, AR_BOOK_FIELDS, AboutPageTemplate, Accordion, ActionButton, Card2 as ActionCard, ActionPalette, ActionTile, ActivationBlock, Alert, AnimatedCounter, AnimatedGraphic, AnimatedReveal, ArticleSection, Aside, AssetPicker, AuthLayout, Avatar, Badge, BehaviorView, BiologyCanvas, BloomQuizBlock, BookChapterView, BookCoverPage, BookNavBar, BookTableOfContents, BookViewer, Box, BranchingLogicBuilder, Breadcrumb, BuilderBoard, Button, ButtonGroup, CTABanner, CalendarGrid, Canvas2D, Card, CardBody, CardContent, CardFooter, CardGrid, CardHeader, CardTitle, Carousel, CaseStudyCard, CaseStudyOrganism, Center, Chart, ChartLegend, ChatBar, Checkbox, ChemistryCanvas, ChoiceButton, ClassifierBoard, Coachmark, CodeBlock, CodeRunnerPanel, CollapsibleSection, ComboCounter, CommunityLinks, ConditionalWrapper, ConfettiEffect, ConfirmDialog, ConnectionBlock, Container, ContentRenderer, ContentSection, ControlButton, ControlGrid, CounterTemplate, DEFAULT_LIKERT_OPTIONS, DEFAULT_MATRIX_COLUMNS, DEFAULT_SLOTS, DIAMOND_TOP_Y, DamageNumber, DashboardGrid, DashboardLayout, DataGrid, DataList, DataTable, DateRangePicker, DateRangeSelector, DayCell, DebuggerBoard, DetailPanel, Dialog, DialogueBubble, Divider, DocBreadcrumb, DocPagination, DocSearch, DocSidebar, DocTOC, DocumentViewer, StateMachineView as DomStateMachineVisualizer, Drawer, DrawerSlot, ELEMENT_SELECTED_EVENT, EMPTY_EFFECT_STATE, EdgeDecoration, EditorCheckbox, EditorSelect, EditorSlider, EditorTextInput, EditorToolbar, EmptyState, EntityDisplayEvents, ErrorBoundary, ErrorState, EventHandlerBoard, EventLog, FEATURE_COLORS, FEATURE_TYPES, FLOOR_HEIGHT, FeatureCard, FeatureDetailPageTemplate, FeatureGrid, FeatureGridOrganism, FileTree, FilterGroup, FilterPill, Flex, FlipCard, FlipContainer, FloatingActionButton, Form, FormActions, FormField, FormLayout, FormSection, FormSectionHeader, GameAudioContext, GameAudioProvider, GameAudioToggle, GameCard, GameHud, GameIcon, GameMenu, GameShell, GameTemplate, GenericAppTemplate, GeometricPattern, GradientDivider, GraphCanvas, GraphView, Grid, GridPicker, HStack, Header, HealthBar, HeroOrganism, HeroSection, I18nProvider, IDENTITY_BOOK_FIELDS, Icon, IconPicker, InfiniteScrollSentinel, Input, InputGroup, InstallBox, InventoryGrid, ItemSlot, JazariStateMachine, JsonTreeEditor, Label, LandingPageTemplate, LawReferenceTooltip, LearningCanvas, Lightbox, LikertScale, LineChart2 as LineChart, List3 as List, LoadingState, MapView, MarkdownContent, MarketingFooter, MarketingStatCard, MasterDetail, MasterDetailLayout, MathCanvas, MatrixQuestion, MediaGallery, Menu, Meter, MiniMap, Modal, ModalSlot, ModuleCard, Navigation, NegotiatorBoard, NodeSlotEditor, NotifyListener, NumberStepper, ObjectRulePanel, OnboardingSpotlight, OptionConstraintGroup, StateMachineView as OrbitalStateMachineView, OrbitalVisualization, Overlay, PageHeader, Pagination, PatternTile, PhysicsCanvas, Popover, PositionedCanvas, PricingCard, PricingGrid, PricingOrganism, PricingPageTemplate, ProgressBar, ProgressDots, PropertyInspector, PullQuote, PullToRefresh, QrScanner, QuizBlock, Radio, RangeSlider, ReflectionBlock, RelationSelect, RepeatableFormSection, ReplyTree, ResourceBar, ResourceCounter, RichBlockEditor, RuleEditor, RuntimeDebugger, SHEET_COLUMNS, SPRITE_SHEET_LAYOUT, ScaledDiagram, ScoreDisplay, SearchInput, Section, SectionHeader, SegmentRenderer, Select, SequenceBar, SequencerBoard, ServiceCatalog, ShowcaseCard, ShowcaseOrganism, SidePanel, Sidebar, SignaturePad, SimpleGrid, SimulationCanvas, SimulationControls, SimulationGraph, SimulatorBoard, Skeleton, SlotContentRenderer, SocialProof, SortableList, Spacer, Sparkline, Spinner, Split, SplitPane, SplitSection, Sprite, Stack, StarRating, StatBadge, StatCard, StatDisplay, StateArchitectBoard, StateGraph, StateIndicator, StateJsonView, StateMachineView, StateNode2 as StateNode, StatsGrid, StatsOrganism, StatusBar, StatusDot, StatusEffect, StepFlow, StepFlowOrganism, SubagentTracePanel, SvgBranch, SvgConnection, SvgFlow, SvgGrid, SvgLobe, SvgMesh, SvgMorph, SvgNode, SvgPulse, SvgRing, SvgShield, SvgStack, SwipeableRow, Switch, TERRAIN_COLORS, TILE_HEIGHT, TILE_WIDTH, TabbedContainer, TableView, Tabs, TagCloud, TagInput, TeamCard, TeamOrganism, TerrainPalette, TextHighlight, Textarea, ThemeToggle, TimeSlotCell, Timeline, TimerDisplay, Toast, ToastSlot, Tooltip, TraitFrame, TraitSlot, TraitStateViewer, TransitionArrow, TrendIndicator, TurnIndicator, TypewriterText, Typography, UISlotComponent, UISlotRenderer, UploadDropZone, VStack, VariablePanel, VersionDiff, ViolationAlert, VoteStack, WaypointMarker, WizardContainer, WizardNavigation, WizardProgress, boardEntity, bool, calculateAttackTargets, calculateValidMoves, cn, createInitialGameState, createTranslate, createUnitAnimationState, drawSprite, getCurrentFrame, getTileDimensions, inferDirection, isoToScreen, makeAsset, makeAssetMap, mapBookData, num, objAvailableActions, objAvailableEvents, objCurrentState, objIcon, objId, objMaxRules, objName, objRules, objStates, parseEditFocus, parseLessonSegments, parseMarkdownWithCodeBlocks, parseQueryBinding, pendulum, projectileMotion, resolveFieldMap, resolveFrame, resolveSheetDirection, rows, screenToIso, springOscillator, str, tickAnimationState, toCodeLanguage, transitionAnimation, unitHealth, unitPosition, unitTeam, useAgentChat, useAnchorRect, useAuthContext, useCamera, useCanvasGestures, useCompile, useConnectGitHub, useDeepAgentGeneration, useDisconnectGitHub, useDragReorder, useDraggable, useDropZone, useEmitEvent, useEventBus, useEventListener, useExtensions, useFileEditor, useFileSystem, useGameAudio, useGameAudioContext, useGitHubBranches, useGitHubRepo, useGitHubRepos, useGitHubStatus, useImageCache, useInfiniteScroll, useLongPress, useOrbitalHistory, usePreview, usePullToRefresh, useQuerySingleton, useRenderInterpolation, useSwipeGesture, useTapReveal, useTraitListens, useTranslate127 as useTranslate, useUIEvents, useUISlotManager, useUnitSpriteAtlas, useValidation, vec2 };