@almadar/ui 2.1.2 → 2.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,17 +1,17 @@
1
+ import { DEFAULT_CONFIG, renderStateMachineToDomData, parseContentSegments } from '../chunk-N6DJVKZ6.js';
1
2
  import { useAuthContext } from '../chunk-BKC4XU44.js';
2
3
  export { ENTITY_EVENTS, useAgentChat, useAuthContext, useCompile, useConnectGitHub, useCreateEntity, useDeepAgentGeneration, useDeleteEntity, useDisconnectGitHub, useEntities, useEntitiesByType, useEntity as useEntityById, useEntityMutations, useExtensions, useFileEditor, useFileSystem, useGitHubBranches, useGitHubRepo, useGitHubRepos, useGitHubStatus, useInput, useOrbitalHistory, useOrbitalMutations, usePhysics, usePlayer, usePreview, useResolvedEntity, useSelectedEntity, useSendOrbitalEvent, useSingletonEntity, useUIEvents, useUpdateEntity, useValidation } from '../chunk-BKC4XU44.js';
3
- import { DEFAULT_CONFIG, renderStateMachineToDomData, parseContentSegments } from '../chunk-N6DJVKZ6.js';
4
4
  import '../chunk-XSEDIUM6.js';
5
- import { VStack, HStack, Typography, Button, Icon, Box, Card, Avatar, Badge, SearchInput, Checkbox, Menu as Menu$1, Pagination, LoadingState, EmptyState, Modal, ErrorState, QuizBlock, CodeBlock, ScaledDiagram, MarkdownContent, Divider, ProgressBar, Stack, Select, Drawer, Toast, Tabs, Input, ThemeToggle, HealthBar, ScoreDisplay, StateIndicator, Container, EntityDisplayEvents } from '../chunk-LB3HXNAR.js';
6
- export { Accordion, Card2 as ActionCard, Alert, Avatar, Badge, Box, Breadcrumb, Button, ButtonGroup, Card, CardBody, CardContent, CardFooter, CardGrid, CardHeader, CardTitle, Center, Checkbox, CodeBlock, ConditionalWrapper, Container, ControlButton, DataTable, DetailPanel, Divider, Drawer, EmptyState, EntityDisplayEvents, ErrorBoundary, ErrorState, FilterGroup, Flex, FloatingActionButton, Form, FormField, FormSectionHeader, Grid, HStack, Heading, HealthBar, Icon, Input, InputGroup, Label, LawReferenceTooltip, LoadingState, MarkdownContent, MasterDetail, Menu, Modal, Overlay, PageHeader, Pagination, Popover, ProgressBar, QuizBlock, Radio, RelationSelect, RepeatableFormSection, ScaledDiagram, ScoreDisplay, SearchInput, Select, SidePanel, SimpleGrid, Skeleton, SlotContentRenderer, Spacer, Spinner, Sprite, Stack, StatCard, StateIndicator, Switch, Tabs, Text, TextHighlight, Textarea, ThemeSelector, ThemeToggle, Toast, Tooltip, Typography, UISlotComponent, UISlotRenderer, VStack, ViolationAlert, WizardNavigation, WizardProgress, drawSprite } from '../chunk-LB3HXNAR.js';
7
- import '../chunk-BTXQJGFB.js';
5
+ import { VStack, HStack, Typography, Button, Icon, Box, Card, Avatar, Badge, SearchInput, Checkbox, Menu as Menu$1, Pagination, LoadingState, EmptyState, Modal, ErrorState, QuizBlock, CodeBlock, ScaledDiagram, MarkdownContent, Divider, ProgressBar, Stack, Select, Drawer, Toast, Tabs, Input, ThemeToggle, HealthBar, ScoreDisplay, StateIndicator, Container, EntityDisplayEvents } from '../chunk-LX4G4SVJ.js';
6
+ export { Accordion, Card2 as ActionCard, Alert, Avatar, Badge, Box, Breadcrumb, Button, ButtonGroup, Card, CardBody, CardContent, CardFooter, CardGrid, CardHeader, CardTitle, Center, Checkbox, CodeBlock, ConditionalWrapper, Container, ControlButton, DataTable, DetailPanel, Divider, Drawer, EmptyState, EntityDisplayEvents, ErrorBoundary, ErrorState, FilterGroup, Flex, FloatingActionButton, Form, FormField, FormSectionHeader, Grid, HStack, Heading, HealthBar, Icon, Input, InputGroup, Label, LawReferenceTooltip, LoadingState, MarkdownContent, MasterDetail, Menu, Modal, Overlay, PageHeader, Pagination, Popover, ProgressBar, QuizBlock, Radio, RelationSelect, RepeatableFormSection, ScaledDiagram, ScoreDisplay, SearchInput, Select, SidePanel, SimpleGrid, Skeleton, SlotContentRenderer, Spacer, Spinner, Sprite, Stack, StatCard, StateIndicator, Switch, Tabs, Text, TextHighlight, Textarea, ThemeSelector, ThemeToggle, Toast, Tooltip, Typography, UISlotComponent, UISlotRenderer, VStack, ViolationAlert, WizardNavigation, WizardProgress, drawSprite } from '../chunk-LX4G4SVJ.js';
7
+ import '../chunk-QU4JHKVC.js';
8
+ import { cn, getNestedValue } from '../chunk-KKCVDUK7.js';
9
+ export { cn } from '../chunk-KKCVDUK7.js';
8
10
  import { useTranslate } from '../chunk-PE2H3NAW.js';
9
11
  export { EntityDataProvider, I18nProvider, createTranslate, entityDataKeys, parseQueryBinding, useEntity, useEntityDataAdapter, useEntityDetail, useEntityList, useEntityListSuspense, useEntitySuspense, useQuerySingleton, useTranslate } from '../chunk-PE2H3NAW.js';
10
12
  import { useEventBus, useEventListener } from '../chunk-YXZM3WCF.js';
11
13
  export { useEmitEvent, useEventBus, useEventListener } from '../chunk-YXZM3WCF.js';
12
14
  export { DEFAULT_SLOTS, useUISlotManager } from '../chunk-7NEWMNNU.js';
13
- import { cn, getNestedValue } from '../chunk-KKCVDUK7.js';
14
- export { cn } from '../chunk-KKCVDUK7.js';
15
15
  export { clearEntities, getAllEntities, getByType, getEntity, getSingleton, removeEntity, spawnEntity, updateEntity, updateSingleton } from '../chunk-N7MVUW4R.js';
16
16
  import { __publicField } from '../chunk-PKBMQBKP.js';
17
17
  import * as React42 from 'react';
@@ -7333,6 +7333,7 @@ function BattleBoard({
7333
7333
  const currentTurn = entity.turn;
7334
7334
  const gameResult = entity.gameResult;
7335
7335
  const eventBus = useEventBus();
7336
+ const { t } = useTranslate();
7336
7337
  const [hoveredTile, setHoveredTile] = useState(null);
7337
7338
  const [isShaking, setIsShaking] = useState(false);
7338
7339
  const selectedUnit = useMemo(
@@ -7386,11 +7387,11 @@ function BattleBoard({
7386
7387
  const anim2 = movementAnimRef.current;
7387
7388
  if (!anim2) return;
7388
7389
  anim2.elapsed += 16;
7389
- const t = Math.min(anim2.elapsed / anim2.duration, 1);
7390
- const eased = 1 - (1 - t) * (1 - t);
7390
+ const t2 = Math.min(anim2.elapsed / anim2.duration, 1);
7391
+ const eased = 1 - (1 - t2) * (1 - t2);
7391
7392
  const cx = anim2.from.x + (anim2.to.x - anim2.from.x) * eased;
7392
7393
  const cy = anim2.from.y + (anim2.to.y - anim2.from.y) * eased;
7393
- if (t >= 1) {
7394
+ if (t2 >= 1) {
7394
7395
  movementAnimRef.current = null;
7395
7396
  setMovingPositions((prev) => {
7396
7397
  const next = new Map(prev);
@@ -7421,16 +7422,16 @@ function BattleBoard({
7421
7422
  unitType: unit.unitType,
7422
7423
  heroId: unit.heroId,
7423
7424
  sprite: unit.sprite,
7424
- traits: unit.traits?.map((t) => ({
7425
- name: t.name,
7426
- currentState: t.currentState,
7427
- states: t.states,
7428
- cooldown: t.cooldown ?? 0
7425
+ traits: unit.traits?.map((t2) => ({
7426
+ name: t2.name,
7427
+ currentState: t2.currentState,
7428
+ states: t2.states,
7429
+ cooldown: t2.cooldown ?? 0
7429
7430
  }))
7430
7431
  };
7431
7432
  });
7432
7433
  }, [units, movingPositions]);
7433
- const maxY = Math.max(...tiles.map((t) => t.y), 0);
7434
+ const maxY = Math.max(...tiles.map((t2) => t2.y), 0);
7434
7435
  const baseOffsetX = (maxY + 1) * (TILE_WIDTH * scale / 2);
7435
7436
  const tileToScreen = useCallback(
7436
7437
  (tx, ty) => isoToScreen(tx, ty, scale, baseOffsetX),
@@ -7458,7 +7459,7 @@ function BattleBoard({
7458
7459
  eventBus.emit(`UI:${unitClickEvent}`, { unitId });
7459
7460
  }
7460
7461
  if (currentPhase === "action" && selectedUnit) {
7461
- if (unit.team === "enemy" && attackTargets.some((t) => t.x === unit.position.x && t.y === unit.position.y)) {
7462
+ if (unit.team === "enemy" && attackTargets.some((t2) => t2.x === unit.position.x && t2.y === unit.position.y)) {
7462
7463
  const damage = calculateDamage2 ? calculateDamage2(selectedUnit, unit) : Math.max(1, selectedUnit.attack - unit.defense);
7463
7464
  setIsShaking(true);
7464
7465
  setTimeout(() => setIsShaking(false), 300);
@@ -7535,7 +7536,7 @@ function BattleBoard({
7535
7536
  ]
7536
7537
  );
7537
7538
  const shakeStyle = isShaking ? { animation: "battle-shake 0.3s ease-in-out" } : {};
7538
- return /* @__PURE__ */ jsxs("div", { className: cn("battle-board relative flex flex-col min-h-[600px] bg-[var(--color-background)]", className), children: [
7539
+ return /* @__PURE__ */ jsxs(VStack, { className: cn("battle-board relative min-h-[600px] bg-[var(--color-background)]", className), gap: "none", children: [
7539
7540
  /* @__PURE__ */ jsx("style", { children: `
7540
7541
  @keyframes battle-shake {
7541
7542
  0%, 100% { transform: translate(0, 0); }
@@ -7550,9 +7551,9 @@ function BattleBoard({
7550
7551
  90% { transform: translate(-2px, 1px); }
7551
7552
  }
7552
7553
  ` }),
7553
- header && /* @__PURE__ */ jsx("div", { className: "p-4", children: header(ctx) }),
7554
- /* @__PURE__ */ jsxs("div", { className: "flex flex-1 gap-4 p-4 pt-0", children: [
7555
- /* @__PURE__ */ jsxs("div", { className: "relative flex-1", style: shakeStyle, children: [
7554
+ header && /* @__PURE__ */ jsx(Box, { className: "p-4", children: header(ctx) }),
7555
+ /* @__PURE__ */ jsxs(HStack, { className: "flex-1 gap-4 p-4 pt-0", gap: "none", children: [
7556
+ /* @__PURE__ */ jsxs(Box, { className: "relative flex-1", style: shakeStyle, children: [
7556
7557
  /* @__PURE__ */ jsx(
7557
7558
  IsometricCanvas_default,
7558
7559
  {
@@ -7580,47 +7581,52 @@ function BattleBoard({
7580
7581
  ),
7581
7582
  overlay && overlay(ctx)
7582
7583
  ] }),
7583
- sidebar && /* @__PURE__ */ jsx("div", { className: "w-80 shrink-0", children: sidebar(ctx) })
7584
+ sidebar && /* @__PURE__ */ jsx(Box, { className: "w-80 shrink-0", children: sidebar(ctx) })
7584
7585
  ] }),
7585
- actions ? actions(ctx) : currentPhase !== "game_over" && /* @__PURE__ */ jsxs("div", { className: "fixed bottom-6 right-6 z-50 flex gap-2", children: [
7586
+ actions ? actions(ctx) : currentPhase !== "game_over" && /* @__PURE__ */ jsxs(HStack, { className: "fixed bottom-6 right-6 z-50", gap: "sm", children: [
7586
7587
  (currentPhase === "movement" || currentPhase === "action") && /* @__PURE__ */ jsx(
7587
- "button",
7588
+ Button,
7588
7589
  {
7589
- className: "px-4 py-2 rounded-lg bg-[var(--color-surface)] text-[var(--color-foreground)] border border-[var(--color-border)] shadow-xl hover:opacity-90",
7590
+ variant: "secondary",
7591
+ className: "shadow-xl",
7590
7592
  onClick: handleCancel,
7591
- children: "Cancel"
7593
+ children: t("battle.cancel")
7592
7594
  }
7593
7595
  ),
7594
7596
  /* @__PURE__ */ jsx(
7595
- "button",
7597
+ Button,
7596
7598
  {
7597
- className: "px-4 py-2 rounded-lg bg-[var(--color-primary)] text-white shadow-xl hover:opacity-90",
7599
+ variant: "primary",
7600
+ className: "shadow-xl",
7598
7601
  onClick: handleEndTurn,
7599
- children: "End Turn"
7602
+ children: t("battle.endTurn")
7600
7603
  }
7601
7604
  )
7602
7605
  ] }),
7603
- gameResult && (gameOverOverlay ? gameOverOverlay(ctx) : /* @__PURE__ */ jsx("div", { className: "absolute inset-0 z-50 flex items-center justify-center bg-black/70 backdrop-blur-sm rounded-xl", children: /* @__PURE__ */ jsxs("div", { className: "text-center space-y-6 p-8", children: [
7606
+ gameResult && (gameOverOverlay ? gameOverOverlay(ctx) : /* @__PURE__ */ jsx(Box, { className: "absolute inset-0 z-50 flex items-center justify-center bg-black/70 backdrop-blur-sm rounded-xl", children: /* @__PURE__ */ jsxs(VStack, { className: "text-center p-8", gap: "lg", children: [
7604
7607
  /* @__PURE__ */ jsx(
7605
- "h2",
7608
+ Typography,
7606
7609
  {
7610
+ variant: "h2",
7607
7611
  className: cn(
7608
7612
  "text-4xl font-black tracking-widest uppercase",
7609
7613
  gameResult === "victory" ? "text-yellow-400" : "text-red-500"
7610
7614
  ),
7611
- children: gameResult === "victory" ? "Victory!" : "Defeat"
7615
+ children: gameResult === "victory" ? t("battle.victory") : t("battle.defeat")
7612
7616
  }
7613
7617
  ),
7614
- /* @__PURE__ */ jsxs("p", { className: "text-gray-300", children: [
7615
- "Turns played: ",
7618
+ /* @__PURE__ */ jsxs(Typography, { variant: "body1", className: "text-gray-300", children: [
7619
+ t("battle.turnsPlayed"),
7620
+ ": ",
7616
7621
  currentTurn
7617
7622
  ] }),
7618
7623
  /* @__PURE__ */ jsx(
7619
- "button",
7624
+ Button,
7620
7625
  {
7621
- className: "px-8 py-3 rounded-lg bg-[var(--color-primary)] text-white font-semibold hover:opacity-90",
7626
+ variant: "primary",
7627
+ className: "px-8 py-3 font-semibold",
7622
7628
  onClick: handleReset,
7623
- children: "Play Again"
7629
+ children: t("battle.playAgain")
7624
7630
  }
7625
7631
  )
7626
7632
  ] }) }))
@@ -8716,6 +8722,7 @@ function ActionTile({
8716
8722
  categoryColors,
8717
8723
  className
8718
8724
  }) {
8725
+ useTranslate();
8719
8726
  const config = SIZE_CONFIG3[size];
8720
8727
  const catColor = categoryColors?.[action.category];
8721
8728
  const handleDragStart = useCallback((e) => {
@@ -8743,7 +8750,7 @@ function ActionTile({
8743
8750
  draggable: !disabled,
8744
8751
  onDragStart: handleDragStart,
8745
8752
  children: [
8746
- /* @__PURE__ */ jsx(Typography, { variant: "body1", className: cn(config.icon, "leading-none"), children: action.iconEmoji || "\u2726" }),
8753
+ action.iconUrl ? /* @__PURE__ */ jsx("img", { src: action.iconUrl, alt: "", className: "w-8 h-8 object-contain" }) : /* @__PURE__ */ jsx(Typography, { variant: "body1", className: cn(config.icon, "leading-none"), children: action.iconEmoji || "\u2726" }),
8747
8754
  /* @__PURE__ */ jsx(Typography, { variant: "caption", className: cn(config.text, "text-foreground font-medium whitespace-nowrap"), children: action.name })
8748
8755
  ]
8749
8756
  }
@@ -8856,6 +8863,7 @@ function SequencerBoard({
8856
8863
  }) {
8857
8864
  const { emit } = useEventBus();
8858
8865
  const { t } = useTranslate();
8866
+ const [headerError, setHeaderError] = useState(false);
8859
8867
  const [slots, setSlots] = useState(
8860
8868
  () => Array.from({ length: entity.maxSlots }, () => void 0)
8861
8869
  );
@@ -8968,64 +8976,76 @@ function SequencerBoard({
8968
8976
  const hasFeedback = slotFeedback.some((f) => f !== null);
8969
8977
  const correctCount = slotFeedback.filter((f) => f === "correct").length;
8970
8978
  const encourageKey = ENCOURAGEMENT_KEYS[Math.min(attempts - 1, ENCOURAGEMENT_KEYS.length - 1)] ?? ENCOURAGEMENT_KEYS[0];
8971
- return /* @__PURE__ */ jsxs(VStack, { className: cn("p-4 gap-6", className), children: [
8972
- /* @__PURE__ */ jsxs(VStack, { gap: "xs", children: [
8973
- /* @__PURE__ */ jsx(Typography, { variant: "h4", className: "text-foreground", children: entity.title }),
8974
- /* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground", children: entity.description })
8975
- ] }),
8976
- showHint && /* @__PURE__ */ jsx(Box, { className: "p-3 rounded-lg bg-accent/10 border border-accent/30", children: /* @__PURE__ */ jsxs(HStack, { className: "items-start", gap: "xs", children: [
8977
- /* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-accent font-bold shrink-0", children: "\u{1F4A1} " + t("game.hint") + ":" }),
8978
- /* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-foreground", children: entity.hint })
8979
- ] }) }),
8980
- filledSlots.length > 0 && /* @__PURE__ */ jsx(TraitStateViewer, { trait: machine, variant: "linear", size: "md" }),
8981
- /* @__PURE__ */ jsxs(VStack, { gap: "xs", children: [
8982
- /* @__PURE__ */ jsxs(HStack, { className: "items-center justify-between", children: [
8983
- /* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground font-medium", children: t("sequencer.yourSequence") + ":" }),
8984
- hasFeedback && playState === "idle" && /* @__PURE__ */ jsxs(Typography, { variant: "caption", className: "text-muted-foreground", children: [
8985
- `${correctCount}/${entity.maxSlots} `,
8986
- "\u2705"
8979
+ return /* @__PURE__ */ jsxs(
8980
+ VStack,
8981
+ {
8982
+ className: cn("p-4 gap-6", className),
8983
+ style: {
8984
+ backgroundImage: entity.theme?.background ? `url(${entity.theme.background})` : void 0,
8985
+ backgroundSize: "cover",
8986
+ backgroundPosition: "center"
8987
+ },
8988
+ children: [
8989
+ entity.headerImage && !headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 overflow-hidden rounded-lg", children: /* @__PURE__ */ jsx("img", { src: entity.headerImage, alt: "", onError: () => setHeaderError(true), className: "w-full h-full object-cover" }) }) : entity.headerImage && headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 rounded-lg bg-gradient-to-br from-[var(--color-muted)] to-[var(--color-accent)] opacity-60" }) : null,
8990
+ /* @__PURE__ */ jsxs(VStack, { gap: "xs", children: [
8991
+ /* @__PURE__ */ jsx(Typography, { variant: "h4", className: "text-foreground", children: entity.title }),
8992
+ /* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground", children: entity.description })
8993
+ ] }),
8994
+ showHint && /* @__PURE__ */ jsx(Box, { className: "p-3 rounded-lg bg-accent/10 border border-accent/30", children: /* @__PURE__ */ jsxs(HStack, { className: "items-start", gap: "xs", children: [
8995
+ /* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-accent font-bold shrink-0", children: "\u{1F4A1} " + t("game.hint") + ":" }),
8996
+ /* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-foreground", children: entity.hint })
8997
+ ] }) }),
8998
+ filledSlots.length > 0 && /* @__PURE__ */ jsx(TraitStateViewer, { trait: machine, variant: "linear", size: "md" }),
8999
+ /* @__PURE__ */ jsxs(VStack, { gap: "xs", children: [
9000
+ /* @__PURE__ */ jsxs(HStack, { className: "items-center justify-between", children: [
9001
+ /* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground font-medium", children: t("sequencer.yourSequence") + ":" }),
9002
+ hasFeedback && playState === "idle" && /* @__PURE__ */ jsxs(Typography, { variant: "caption", className: "text-muted-foreground", children: [
9003
+ `${correctCount}/${entity.maxSlots} `,
9004
+ "\u2705"
9005
+ ] })
9006
+ ] }),
9007
+ /* @__PURE__ */ jsx(
9008
+ SequenceBar,
9009
+ {
9010
+ slots,
9011
+ maxSlots: entity.maxSlots,
9012
+ onSlotDrop: handleSlotDrop,
9013
+ onSlotRemove: handleSlotRemove,
9014
+ playing: playState === "playing",
9015
+ currentStep,
9016
+ categoryColors,
9017
+ slotFeedback,
9018
+ size: "lg"
9019
+ }
9020
+ )
9021
+ ] }),
9022
+ playState !== "playing" && /* @__PURE__ */ jsx(
9023
+ ActionPalette,
9024
+ {
9025
+ actions: entity.availableActions,
9026
+ usedActionIds: usedIds,
9027
+ allowDuplicates: entity.allowDuplicates !== false,
9028
+ categoryColors,
9029
+ label: t("sequencer.dragActions")
9030
+ }
9031
+ ),
9032
+ hasFeedback && playState === "idle" && attempts > 0 && /* @__PURE__ */ jsx(Box, { className: "p-3 rounded-lg bg-warning/10 border border-warning/30 text-center", children: /* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-foreground", children: t(encourageKey) }) }),
9033
+ playState === "success" && /* @__PURE__ */ jsx(Box, { className: "p-4 rounded-lg bg-success/20 border border-success text-center", children: /* @__PURE__ */ jsx(Typography, { variant: "h5", className: "text-success", children: entity.successMessage || t("sequencer.levelComplete") }) }),
9034
+ /* @__PURE__ */ jsxs(HStack, { gap: "sm", children: [
9035
+ /* @__PURE__ */ jsx(
9036
+ Button,
9037
+ {
9038
+ variant: "primary",
9039
+ onClick: handlePlay,
9040
+ disabled: !canPlay,
9041
+ children: "\u25B6 " + t("game.play")
9042
+ }
9043
+ ),
9044
+ /* @__PURE__ */ jsx(Button, { variant: "ghost", onClick: handleReset, children: "\u21BA " + t("game.reset") })
8987
9045
  ] })
8988
- ] }),
8989
- /* @__PURE__ */ jsx(
8990
- SequenceBar,
8991
- {
8992
- slots,
8993
- maxSlots: entity.maxSlots,
8994
- onSlotDrop: handleSlotDrop,
8995
- onSlotRemove: handleSlotRemove,
8996
- playing: playState === "playing",
8997
- currentStep,
8998
- categoryColors,
8999
- slotFeedback,
9000
- size: "lg"
9001
- }
9002
- )
9003
- ] }),
9004
- playState !== "playing" && /* @__PURE__ */ jsx(
9005
- ActionPalette,
9006
- {
9007
- actions: entity.availableActions,
9008
- usedActionIds: usedIds,
9009
- allowDuplicates: entity.allowDuplicates !== false,
9010
- categoryColors,
9011
- label: t("sequencer.dragActions")
9012
- }
9013
- ),
9014
- hasFeedback && playState === "idle" && attempts > 0 && /* @__PURE__ */ jsx(Box, { className: "p-3 rounded-lg bg-warning/10 border border-warning/30 text-center", children: /* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-foreground", children: t(encourageKey) }) }),
9015
- playState === "success" && /* @__PURE__ */ jsx(Box, { className: "p-4 rounded-lg bg-success/20 border border-success text-center", children: /* @__PURE__ */ jsx(Typography, { variant: "h5", className: "text-success", children: entity.successMessage || t("sequencer.levelComplete") }) }),
9016
- /* @__PURE__ */ jsxs(HStack, { gap: "sm", children: [
9017
- /* @__PURE__ */ jsx(
9018
- Button,
9019
- {
9020
- variant: "primary",
9021
- onClick: handlePlay,
9022
- disabled: !canPlay,
9023
- children: "\u25B6 " + t("game.play")
9024
- }
9025
- ),
9026
- /* @__PURE__ */ jsx(Button, { variant: "ghost", onClick: handleReset, children: "\u21BA " + t("game.reset") })
9027
- ] })
9028
- ] });
9046
+ ]
9047
+ }
9048
+ );
9029
9049
  }
9030
9050
  SequencerBoard.displayName = "SequencerBoard";
9031
9051
  function RuleEditor({
@@ -9203,6 +9223,7 @@ function EventHandlerBoard({
9203
9223
  const [selectedObjectId, setSelectedObjectId] = useState(
9204
9224
  entity.objects[0]?.id || null
9205
9225
  );
9226
+ const [headerError, setHeaderError] = useState(false);
9206
9227
  const [playState, setPlayState] = useState("editing");
9207
9228
  const [eventLog, setEventLog] = useState([]);
9208
9229
  const [attempts, setAttempts] = useState(0);
@@ -9307,64 +9328,76 @@ function EventHandlerBoard({
9307
9328
  });
9308
9329
  const showHint = attempts >= 3 && entity.hint;
9309
9330
  const encourageKey = ENCOURAGEMENT_KEYS2[Math.min(attempts - 1, ENCOURAGEMENT_KEYS2.length - 1)] ?? ENCOURAGEMENT_KEYS2[0];
9310
- return /* @__PURE__ */ jsxs(VStack, { className: cn("p-4 gap-6", className), children: [
9311
- /* @__PURE__ */ jsxs(VStack, { gap: "xs", children: [
9312
- /* @__PURE__ */ jsx(Typography, { variant: "h4", className: "text-foreground", children: entity.title }),
9313
- /* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground", children: entity.description }),
9314
- /* @__PURE__ */ jsxs(HStack, { className: "items-center p-2 rounded bg-primary/10 border border-primary/30", gap: "xs", children: [
9315
- /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-primary font-bold", children: t("game.goal") + ":" }),
9316
- /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-foreground", children: entity.goalCondition })
9317
- ] })
9318
- ] }),
9319
- /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
9320
- /* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground font-medium", children: t("eventHandler.clickObject") + ":" }),
9321
- /* @__PURE__ */ jsx(HStack, { className: "flex-wrap", gap: "sm", children: objectViewers.map(({ obj, machine }) => /* @__PURE__ */ jsx(
9322
- Box,
9323
- {
9324
- className: cn(
9325
- "p-3 rounded-lg border-2 cursor-pointer transition-all hover:scale-105",
9326
- selectedObjectId === obj.id ? "border-primary bg-primary/10" : "border-border bg-card hover:border-muted-foreground"
9327
- ),
9328
- onClick: () => setSelectedObjectId(obj.id),
9329
- children: /* @__PURE__ */ jsxs(VStack, { gap: "xs", className: "items-center min-w-[120px]", children: [
9330
- /* @__PURE__ */ jsx(Typography, { variant: "h5", children: obj.icon }),
9331
- /* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-foreground font-medium", children: obj.name }),
9332
- /* @__PURE__ */ jsx(TraitStateViewer, { trait: machine, variant: "compact", size: "sm" })
9331
+ return /* @__PURE__ */ jsxs(
9332
+ VStack,
9333
+ {
9334
+ className: cn("p-4 gap-6", className),
9335
+ style: {
9336
+ backgroundImage: entity.theme?.background ? `url(${entity.theme.background})` : void 0,
9337
+ backgroundSize: "cover",
9338
+ backgroundPosition: "center"
9339
+ },
9340
+ children: [
9341
+ entity.headerImage && !headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 overflow-hidden rounded-lg", children: /* @__PURE__ */ jsx("img", { src: entity.headerImage, alt: "", onError: () => setHeaderError(true), className: "w-full h-full object-cover" }) }) : entity.headerImage && headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 rounded-lg bg-gradient-to-br from-[var(--color-muted)] to-[var(--color-accent)] opacity-60" }) : null,
9342
+ /* @__PURE__ */ jsxs(VStack, { gap: "xs", children: [
9343
+ /* @__PURE__ */ jsx(Typography, { variant: "h4", className: "text-foreground", children: entity.title }),
9344
+ /* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground", children: entity.description }),
9345
+ /* @__PURE__ */ jsxs(HStack, { className: "items-center p-2 rounded bg-primary/10 border border-primary/30", gap: "xs", children: [
9346
+ /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-primary font-bold", children: t("game.goal") + ":" }),
9347
+ /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-foreground", children: entity.goalCondition })
9333
9348
  ] })
9334
- },
9335
- obj.id
9336
- )) })
9337
- ] }),
9338
- selectedObject && /* @__PURE__ */ jsx(
9339
- ObjectRulePanel,
9340
- {
9341
- object: selectedObject,
9342
- onRulesChange: handleRulesChange,
9343
- disabled: playState !== "editing"
9344
- }
9345
- ),
9346
- eventLog.length > 0 && /* @__PURE__ */ jsx(EventLog, { entries: eventLog }),
9347
- playState === "success" && /* @__PURE__ */ jsx(Box, { className: "p-4 rounded-lg bg-success/20 border border-success text-center", children: /* @__PURE__ */ jsx(Typography, { variant: "h5", className: "text-success", children: entity.successMessage || t("eventHandler.chainComplete") }) }),
9348
- playState === "fail" && /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
9349
- /* @__PURE__ */ jsx(Box, { className: "p-4 rounded-lg bg-warning/10 border border-warning/30 text-center", children: /* @__PURE__ */ jsx(Typography, { variant: "body1", className: "text-foreground font-medium", children: t(encourageKey) }) }),
9350
- showHint && /* @__PURE__ */ jsx(Box, { className: "p-3 rounded-lg bg-accent/10 border border-accent/30", children: /* @__PURE__ */ jsxs(HStack, { className: "items-start", gap: "xs", children: [
9351
- /* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-accent font-bold shrink-0", children: "\u{1F4A1} " + t("game.hint") + ":" }),
9352
- /* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-foreground", children: entity.hint })
9353
- ] }) })
9354
- ] }),
9355
- /* @__PURE__ */ jsxs(HStack, { gap: "sm", children: [
9356
- playState === "fail" ? /* @__PURE__ */ jsx(Button, { variant: "primary", onClick: handleTryAgain, children: "\u{1F504} " + t("puzzle.tryAgainButton") }) : /* @__PURE__ */ jsx(
9357
- Button,
9358
- {
9359
- variant: "primary",
9360
- onClick: handlePlay,
9361
- disabled: playState !== "editing",
9362
- children: "\u25B6 " + t("game.play")
9363
- }
9364
- ),
9365
- /* @__PURE__ */ jsx(Button, { variant: "ghost", onClick: handleReset, children: "\u21BA " + t("game.reset") })
9366
- ] })
9367
- ] });
9349
+ ] }),
9350
+ /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
9351
+ /* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground font-medium", children: t("eventHandler.clickObject") + ":" }),
9352
+ /* @__PURE__ */ jsx(HStack, { className: "flex-wrap", gap: "sm", children: objectViewers.map(({ obj, machine }) => /* @__PURE__ */ jsx(
9353
+ Box,
9354
+ {
9355
+ className: cn(
9356
+ "p-3 rounded-lg border-2 cursor-pointer transition-all hover:scale-105",
9357
+ selectedObjectId === obj.id ? "border-primary bg-primary/10" : "border-border bg-card hover:border-muted-foreground"
9358
+ ),
9359
+ onClick: () => setSelectedObjectId(obj.id),
9360
+ children: /* @__PURE__ */ jsxs(VStack, { gap: "xs", className: "items-center min-w-[120px]", children: [
9361
+ /* @__PURE__ */ jsx(Typography, { variant: "h5", children: obj.icon }),
9362
+ /* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-foreground font-medium", children: obj.name }),
9363
+ /* @__PURE__ */ jsx(TraitStateViewer, { trait: machine, variant: "compact", size: "sm" })
9364
+ ] })
9365
+ },
9366
+ obj.id
9367
+ )) })
9368
+ ] }),
9369
+ selectedObject && /* @__PURE__ */ jsx(
9370
+ ObjectRulePanel,
9371
+ {
9372
+ object: selectedObject,
9373
+ onRulesChange: handleRulesChange,
9374
+ disabled: playState !== "editing"
9375
+ }
9376
+ ),
9377
+ eventLog.length > 0 && /* @__PURE__ */ jsx(EventLog, { entries: eventLog }),
9378
+ playState === "success" && /* @__PURE__ */ jsx(Box, { className: "p-4 rounded-lg bg-success/20 border border-success text-center", children: /* @__PURE__ */ jsx(Typography, { variant: "h5", className: "text-success", children: entity.successMessage || t("eventHandler.chainComplete") }) }),
9379
+ playState === "fail" && /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
9380
+ /* @__PURE__ */ jsx(Box, { className: "p-4 rounded-lg bg-warning/10 border border-warning/30 text-center", children: /* @__PURE__ */ jsx(Typography, { variant: "body1", className: "text-foreground font-medium", children: t(encourageKey) }) }),
9381
+ showHint && /* @__PURE__ */ jsx(Box, { className: "p-3 rounded-lg bg-accent/10 border border-accent/30", children: /* @__PURE__ */ jsxs(HStack, { className: "items-start", gap: "xs", children: [
9382
+ /* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-accent font-bold shrink-0", children: "\u{1F4A1} " + t("game.hint") + ":" }),
9383
+ /* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-foreground", children: entity.hint })
9384
+ ] }) })
9385
+ ] }),
9386
+ /* @__PURE__ */ jsxs(HStack, { gap: "sm", children: [
9387
+ playState === "fail" ? /* @__PURE__ */ jsx(Button, { variant: "primary", onClick: handleTryAgain, children: "\u{1F504} " + t("puzzle.tryAgainButton") }) : /* @__PURE__ */ jsx(
9388
+ Button,
9389
+ {
9390
+ variant: "primary",
9391
+ onClick: handlePlay,
9392
+ disabled: playState !== "editing",
9393
+ children: "\u25B6 " + t("game.play")
9394
+ }
9395
+ ),
9396
+ /* @__PURE__ */ jsx(Button, { variant: "ghost", onClick: handleReset, children: "\u21BA " + t("game.reset") })
9397
+ ] })
9398
+ ]
9399
+ }
9400
+ );
9368
9401
  }
9369
9402
  EventHandlerBoard.displayName = "EventHandlerBoard";
9370
9403
  function StateNode2({
@@ -9574,6 +9607,7 @@ function StateArchitectBoard({
9574
9607
  const { emit } = useEventBus();
9575
9608
  const { t } = useTranslate();
9576
9609
  const [transitions, setTransitions] = useState(entity.transitions);
9610
+ const [headerError, setHeaderError] = useState(false);
9577
9611
  const [playState, setPlayState] = useState("editing");
9578
9612
  const [currentState, setCurrentState] = useState(entity.initialState);
9579
9613
  const [selectedState, setSelectedState] = useState(null);
@@ -9696,150 +9730,162 @@ function StateArchitectBoard({
9696
9730
  ...t2.guardHint ? { guard: t2.guardHint } : {}
9697
9731
  }))
9698
9732
  }), [entity, transitions]);
9699
- return /* @__PURE__ */ jsxs(VStack, { className: cn("p-4 gap-6", className), children: [
9700
- /* @__PURE__ */ jsxs(VStack, { gap: "xs", children: [
9701
- /* @__PURE__ */ jsx(Typography, { variant: "h4", className: "text-foreground", children: entity.title }),
9702
- /* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground", children: entity.description }),
9703
- /* @__PURE__ */ jsxs(HStack, { className: "items-center p-2 rounded bg-warning/10 border border-warning/30", gap: "xs", children: [
9704
- /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-warning font-bold", children: t("game.hint") + ":" }),
9705
- /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-foreground", children: entity.hint })
9706
- ] })
9707
- ] }),
9708
- /* @__PURE__ */ jsxs(HStack, { className: "flex-wrap items-start", gap: "lg", children: [
9709
- /* @__PURE__ */ jsxs(VStack, { gap: "sm", className: "flex-1 min-w-[300px]", children: [
9710
- /* @__PURE__ */ jsxs(HStack, { className: "items-center justify-between", children: [
9711
- /* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground font-medium", children: t("stateArchitect.graph") }),
9712
- addingFrom && /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-accent animate-pulse", children: t("stateArchitect.clickTarget", { state: addingFrom || "" }) })
9733
+ return /* @__PURE__ */ jsxs(
9734
+ VStack,
9735
+ {
9736
+ className: cn("p-4 gap-6", className),
9737
+ style: {
9738
+ backgroundImage: entity.theme?.background ? `url(${entity.theme.background})` : void 0,
9739
+ backgroundSize: "cover",
9740
+ backgroundPosition: "center"
9741
+ },
9742
+ children: [
9743
+ entity.headerImage && !headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 overflow-hidden rounded-lg", children: /* @__PURE__ */ jsx("img", { src: entity.headerImage, alt: "", onError: () => setHeaderError(true), className: "w-full h-full object-cover" }) }) : entity.headerImage && headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 rounded-lg bg-gradient-to-br from-[var(--color-muted)] to-[var(--color-accent)] opacity-60" }) : null,
9744
+ /* @__PURE__ */ jsxs(VStack, { gap: "xs", children: [
9745
+ /* @__PURE__ */ jsx(Typography, { variant: "h4", className: "text-foreground", children: entity.title }),
9746
+ /* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground", children: entity.description }),
9747
+ /* @__PURE__ */ jsxs(HStack, { className: "items-center p-2 rounded bg-warning/10 border border-warning/30", gap: "xs", children: [
9748
+ /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-warning font-bold", children: t("game.hint") + ":" }),
9749
+ /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-foreground", children: entity.hint })
9750
+ ] })
9713
9751
  ] }),
9714
- /* @__PURE__ */ jsxs(
9715
- Box,
9716
- {
9717
- position: "relative",
9718
- className: "rounded-lg border border-border bg-background overflow-hidden",
9719
- style: { width: GRAPH_W, height: GRAPH_H },
9720
- children: [
9721
- /* @__PURE__ */ jsxs(
9722
- "svg",
9723
- {
9724
- width: GRAPH_W,
9725
- height: GRAPH_H,
9726
- className: "absolute inset-0",
9727
- style: { pointerEvents: "none" },
9728
- children: [
9729
- /* @__PURE__ */ jsxs("defs", { children: [
9730
- /* @__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)" }) }),
9731
- /* @__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)" }) })
9732
- ] }),
9733
- transitions.map((t2) => {
9734
- const fromPos = positions[t2.from];
9735
- const toPos = positions[t2.to];
9736
- if (!fromPos || !toPos) return null;
9737
- const isActive = t2.from === currentState;
9738
- return /* @__PURE__ */ jsx(
9739
- TransitionArrow,
9740
- {
9741
- from: fromPos,
9742
- to: toPos,
9743
- eventLabel: t2.event,
9744
- guardHint: t2.guardHint,
9745
- isActive
9746
- },
9747
- t2.id
9748
- );
9749
- })
9750
- ]
9751
- }
9752
- ),
9753
- entity.states.map((state) => /* @__PURE__ */ jsx(
9754
- StateNode2,
9755
- {
9756
- name: state,
9757
- position: positions[state],
9758
- isCurrent: state === currentState,
9759
- isSelected: state === selectedState,
9760
- isInitial: state === entity.initialState,
9761
- onClick: () => handleStateClick(state)
9762
- },
9763
- state
9764
- ))
9765
- ]
9766
- }
9767
- ),
9768
- playState === "editing" && /* @__PURE__ */ jsx(HStack, { gap: "sm", children: /* @__PURE__ */ jsx(
9769
- Button,
9770
- {
9771
- variant: "ghost",
9772
- onClick: handleStartAddTransition,
9773
- disabled: !selectedState,
9774
- children: selectedState ? t("stateArchitect.addTransition", { state: selectedState }) : t("stateArchitect.addTransitionPrompt")
9775
- }
9776
- ) }),
9777
- transitions.length > 0 && /* @__PURE__ */ jsxs(VStack, { gap: "xs", className: "p-3 rounded-lg bg-muted/50 border border-border", children: [
9778
- /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-muted-foreground font-medium", children: t("stateArchitect.transitions", { count: transitions.length }) + ":" }),
9779
- transitions.map((t2) => /* @__PURE__ */ jsxs(HStack, { className: "items-center text-xs", gap: "xs", children: [
9780
- /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-foreground", children: t2.from }),
9781
- /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-muted-foreground", children: "\u2014[" }),
9782
- /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-accent font-medium", children: t2.event }),
9783
- /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-muted-foreground", children: "]\u2192" }),
9784
- /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-success", children: t2.to }),
9785
- t2.guardHint && /* @__PURE__ */ jsxs(Typography, { variant: "caption", className: "text-warning", children: [
9786
- "(",
9787
- t2.guardHint,
9788
- ")"
9752
+ /* @__PURE__ */ jsxs(HStack, { className: "flex-wrap items-start", gap: "lg", children: [
9753
+ /* @__PURE__ */ jsxs(VStack, { gap: "sm", className: "flex-1 min-w-[300px]", children: [
9754
+ /* @__PURE__ */ jsxs(HStack, { className: "items-center justify-between", children: [
9755
+ /* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground font-medium", children: t("stateArchitect.graph") }),
9756
+ addingFrom && /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-accent animate-pulse", children: t("stateArchitect.clickTarget", { state: addingFrom || "" }) })
9789
9757
  ] }),
9790
- playState === "editing" && /* @__PURE__ */ jsx(
9758
+ /* @__PURE__ */ jsxs(
9759
+ Box,
9760
+ {
9761
+ position: "relative",
9762
+ className: "rounded-lg border border-border bg-background overflow-hidden",
9763
+ style: { width: GRAPH_W, height: GRAPH_H },
9764
+ children: [
9765
+ /* @__PURE__ */ jsxs(
9766
+ "svg",
9767
+ {
9768
+ width: GRAPH_W,
9769
+ height: GRAPH_H,
9770
+ className: "absolute inset-0",
9771
+ style: { pointerEvents: "none" },
9772
+ children: [
9773
+ /* @__PURE__ */ jsxs("defs", { children: [
9774
+ /* @__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)" }) }),
9775
+ /* @__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)" }) })
9776
+ ] }),
9777
+ transitions.map((t2) => {
9778
+ const fromPos = positions[t2.from];
9779
+ const toPos = positions[t2.to];
9780
+ if (!fromPos || !toPos) return null;
9781
+ const isActive = t2.from === currentState;
9782
+ return /* @__PURE__ */ jsx(
9783
+ TransitionArrow,
9784
+ {
9785
+ from: fromPos,
9786
+ to: toPos,
9787
+ eventLabel: t2.event,
9788
+ guardHint: t2.guardHint,
9789
+ isActive
9790
+ },
9791
+ t2.id
9792
+ );
9793
+ })
9794
+ ]
9795
+ }
9796
+ ),
9797
+ entity.states.map((state) => /* @__PURE__ */ jsx(
9798
+ StateNode2,
9799
+ {
9800
+ name: state,
9801
+ position: positions[state],
9802
+ isCurrent: state === currentState,
9803
+ isSelected: state === selectedState,
9804
+ isInitial: state === entity.initialState,
9805
+ onClick: () => handleStateClick(state)
9806
+ },
9807
+ state
9808
+ ))
9809
+ ]
9810
+ }
9811
+ ),
9812
+ playState === "editing" && /* @__PURE__ */ jsx(HStack, { gap: "sm", children: /* @__PURE__ */ jsx(
9791
9813
  Button,
9792
9814
  {
9793
9815
  variant: "ghost",
9794
- onClick: () => handleRemoveTransition(t2.id),
9795
- className: "text-xs ml-auto",
9796
- children: "\xD7"
9816
+ onClick: handleStartAddTransition,
9817
+ disabled: !selectedState,
9818
+ children: selectedState ? t("stateArchitect.addTransition", { state: selectedState }) : t("stateArchitect.addTransitionPrompt")
9797
9819
  }
9798
- )
9799
- ] }, t2.id))
9800
- ] })
9801
- ] }),
9802
- /* @__PURE__ */ jsxs(VStack, { gap: "sm", className: "w-[280px] shrink-0", children: [
9803
- /* @__PURE__ */ jsx(TraitStateViewer, { trait: machine, variant: "full", size: "sm" }),
9804
- /* @__PURE__ */ jsx(
9805
- VariablePanel,
9806
- {
9807
- entityName: entity.entityName,
9808
- variables
9809
- }
9810
- ),
9811
- testResults.length > 0 && /* @__PURE__ */ jsxs(VStack, { className: "p-3 rounded-lg bg-card border border-border", gap: "xs", children: [
9812
- /* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground font-medium", children: t("stateArchitect.testResults") + ":" }),
9813
- testResults.map((r, i) => /* @__PURE__ */ jsxs(HStack, { className: "items-center text-xs", gap: "xs", children: [
9814
- /* @__PURE__ */ jsx(Typography, { variant: "caption", className: r.passed ? "text-success" : "text-error", children: r.passed ? "\u2714" : "\u2717" }),
9815
- /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-foreground flex-1", children: r.label }),
9816
- !r.passed && /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-error", children: t("stateArchitect.gotState", { state: r.actualState }) })
9817
- ] }, i))
9820
+ ) }),
9821
+ transitions.length > 0 && /* @__PURE__ */ jsxs(VStack, { gap: "xs", className: "p-3 rounded-lg bg-muted/50 border border-border", children: [
9822
+ /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-muted-foreground font-medium", children: t("stateArchitect.transitions", { count: transitions.length }) + ":" }),
9823
+ transitions.map((t2) => /* @__PURE__ */ jsxs(HStack, { className: "items-center text-xs", gap: "xs", children: [
9824
+ /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-foreground", children: t2.from }),
9825
+ /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-muted-foreground", children: "\u2014[" }),
9826
+ /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-accent font-medium", children: t2.event }),
9827
+ /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-muted-foreground", children: "]\u2192" }),
9828
+ /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-success", children: t2.to }),
9829
+ t2.guardHint && /* @__PURE__ */ jsxs(Typography, { variant: "caption", className: "text-warning", children: [
9830
+ "(",
9831
+ t2.guardHint,
9832
+ ")"
9833
+ ] }),
9834
+ playState === "editing" && /* @__PURE__ */ jsx(
9835
+ Button,
9836
+ {
9837
+ variant: "ghost",
9838
+ onClick: () => handleRemoveTransition(t2.id),
9839
+ className: "text-xs ml-auto",
9840
+ children: "\xD7"
9841
+ }
9842
+ )
9843
+ ] }, t2.id))
9844
+ ] })
9845
+ ] }),
9846
+ /* @__PURE__ */ jsxs(VStack, { gap: "sm", className: "w-[280px] shrink-0", children: [
9847
+ /* @__PURE__ */ jsx(TraitStateViewer, { trait: machine, variant: "full", size: "sm" }),
9848
+ /* @__PURE__ */ jsx(
9849
+ VariablePanel,
9850
+ {
9851
+ entityName: entity.entityName,
9852
+ variables
9853
+ }
9854
+ ),
9855
+ testResults.length > 0 && /* @__PURE__ */ jsxs(VStack, { className: "p-3 rounded-lg bg-card border border-border", gap: "xs", children: [
9856
+ /* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground font-medium", children: t("stateArchitect.testResults") + ":" }),
9857
+ testResults.map((r, i) => /* @__PURE__ */ jsxs(HStack, { className: "items-center text-xs", gap: "xs", children: [
9858
+ /* @__PURE__ */ jsx(Typography, { variant: "caption", className: r.passed ? "text-success" : "text-error", children: r.passed ? "\u2714" : "\u2717" }),
9859
+ /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-foreground flex-1", children: r.label }),
9860
+ !r.passed && /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-error", children: t("stateArchitect.gotState", { state: r.actualState }) })
9861
+ ] }, i))
9862
+ ] }),
9863
+ entity.showCodeView !== false && /* @__PURE__ */ jsx(CodeView, { data: codeData, label: "View Code" })
9864
+ ] })
9818
9865
  ] }),
9819
- entity.showCodeView !== false && /* @__PURE__ */ jsx(CodeView, { data: codeData, label: "View Code" })
9820
- ] })
9821
- ] }),
9822
- playState === "success" && /* @__PURE__ */ jsx(Box, { className: "p-4 rounded-lg bg-success/20 border border-success text-center", children: /* @__PURE__ */ jsx(Typography, { variant: "h5", className: "text-success", children: entity.successMessage || t("stateArchitect.allPassed") }) }),
9823
- playState === "fail" && /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
9824
- /* @__PURE__ */ jsx(Box, { className: "p-4 rounded-lg 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]) }) }),
9825
- attempts >= 3 && entity.hint && /* @__PURE__ */ jsx(Box, { className: "p-3 rounded-lg bg-accent/10 border border-accent/30", children: /* @__PURE__ */ jsxs(HStack, { className: "items-start", gap: "xs", children: [
9826
- /* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-accent font-bold shrink-0", children: "\u{1F4A1} " + t("game.hint") + ":" }),
9827
- /* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-foreground", children: entity.hint })
9828
- ] }) })
9829
- ] }),
9830
- /* @__PURE__ */ jsxs(HStack, { gap: "sm", children: [
9831
- playState === "fail" ? /* @__PURE__ */ jsx(Button, { variant: "primary", onClick: handleTryAgain, children: "\u{1F504} " + t("puzzle.tryAgainButton") }) : /* @__PURE__ */ jsx(
9832
- Button,
9833
- {
9834
- variant: "primary",
9835
- onClick: handleTest,
9836
- disabled: playState !== "editing",
9837
- children: "\u25B6 " + t("game.runTests")
9838
- }
9839
- ),
9840
- /* @__PURE__ */ jsx(Button, { variant: "ghost", onClick: handleReset, children: "\u21BA " + t("game.reset") })
9841
- ] })
9842
- ] });
9866
+ playState === "success" && /* @__PURE__ */ jsx(Box, { className: "p-4 rounded-lg bg-success/20 border border-success text-center", children: /* @__PURE__ */ jsx(Typography, { variant: "h5", className: "text-success", children: entity.successMessage || t("stateArchitect.allPassed") }) }),
9867
+ playState === "fail" && /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
9868
+ /* @__PURE__ */ jsx(Box, { className: "p-4 rounded-lg 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]) }) }),
9869
+ attempts >= 3 && entity.hint && /* @__PURE__ */ jsx(Box, { className: "p-3 rounded-lg bg-accent/10 border border-accent/30", children: /* @__PURE__ */ jsxs(HStack, { className: "items-start", gap: "xs", children: [
9870
+ /* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-accent font-bold shrink-0", children: "\u{1F4A1} " + t("game.hint") + ":" }),
9871
+ /* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-foreground", children: entity.hint })
9872
+ ] }) })
9873
+ ] }),
9874
+ /* @__PURE__ */ jsxs(HStack, { gap: "sm", children: [
9875
+ playState === "fail" ? /* @__PURE__ */ jsx(Button, { variant: "primary", onClick: handleTryAgain, children: "\u{1F504} " + t("puzzle.tryAgainButton") }) : /* @__PURE__ */ jsx(
9876
+ Button,
9877
+ {
9878
+ variant: "primary",
9879
+ onClick: handleTest,
9880
+ disabled: playState !== "editing",
9881
+ children: "\u25B6 " + t("game.runTests")
9882
+ }
9883
+ ),
9884
+ /* @__PURE__ */ jsx(Button, { variant: "ghost", onClick: handleReset, children: "\u21BA " + t("game.reset") })
9885
+ ] })
9886
+ ]
9887
+ }
9888
+ );
9843
9889
  }
9844
9890
  StateArchitectBoard.displayName = "StateArchitectBoard";
9845
9891
  function SimulatorBoard({
@@ -9856,6 +9902,7 @@ function SimulatorBoard({
9856
9902
  }
9857
9903
  return init;
9858
9904
  });
9905
+ const [headerError, setHeaderError] = useState(false);
9859
9906
  const [submitted, setSubmitted] = useState(false);
9860
9907
  const [attempts, setAttempts] = useState(0);
9861
9908
  const [showHint, setShowHint] = useState(false);
@@ -9896,83 +9943,95 @@ function SimulatorBoard({
9896
9943
  setAttempts(0);
9897
9944
  setShowHint(false);
9898
9945
  };
9899
- return /* @__PURE__ */ jsx(Box, { className, children: /* @__PURE__ */ jsxs(VStack, { gap: "lg", className: "p-4", children: [
9900
- /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
9901
- /* @__PURE__ */ jsx(Typography, { variant: "h4", weight: "bold", children: entity.title }),
9902
- /* @__PURE__ */ jsx(Typography, { variant: "body", children: entity.description })
9903
- ] }) }),
9904
- /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "md", children: [
9905
- /* @__PURE__ */ jsx(Typography, { variant: "small", weight: "bold", className: "uppercase tracking-wider text-[var(--color-muted-foreground)]", children: t("simulator.parameters") }),
9906
- entity.parameters.map((param) => /* @__PURE__ */ jsxs(VStack, { gap: "xs", children: [
9907
- /* @__PURE__ */ jsxs(HStack, { justify: "between", align: "center", children: [
9908
- /* @__PURE__ */ jsx(Typography, { variant: "body", weight: "medium", children: param.label }),
9909
- /* @__PURE__ */ jsxs(Badge, { size: "sm", children: [
9910
- values[param.id],
9911
- " ",
9912
- param.unit
9913
- ] })
9914
- ] }),
9915
- /* @__PURE__ */ jsx(
9916
- "input",
9917
- {
9918
- type: "range",
9919
- min: param.min,
9920
- max: param.max,
9921
- step: param.step,
9922
- value: values[param.id],
9923
- onChange: (e) => handleParameterChange(param.id, Number(e.target.value)),
9924
- disabled: submitted,
9925
- className: "w-full accent-[var(--color-foreground)]"
9926
- }
9927
- ),
9928
- /* @__PURE__ */ jsxs(HStack, { justify: "between", children: [
9929
- /* @__PURE__ */ jsxs(Typography, { variant: "caption", className: "text-[var(--color-muted-foreground)]", children: [
9930
- param.min,
9946
+ return /* @__PURE__ */ jsx(
9947
+ Box,
9948
+ {
9949
+ className,
9950
+ style: {
9951
+ backgroundImage: entity.theme?.background ? `url(${entity.theme.background})` : void 0,
9952
+ backgroundSize: "cover",
9953
+ backgroundPosition: "center"
9954
+ },
9955
+ children: /* @__PURE__ */ jsxs(VStack, { gap: "lg", className: "p-4", children: [
9956
+ entity.headerImage && !headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 overflow-hidden rounded-lg", children: /* @__PURE__ */ jsx("img", { src: entity.headerImage, alt: "", onError: () => setHeaderError(true), className: "w-full h-full object-cover" }) }) : entity.headerImage && headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 rounded-lg bg-gradient-to-br from-[var(--color-muted)] to-[var(--color-accent)] opacity-60" }) : null,
9957
+ /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
9958
+ /* @__PURE__ */ jsx(Typography, { variant: "h4", weight: "bold", children: entity.title }),
9959
+ /* @__PURE__ */ jsx(Typography, { variant: "body", children: entity.description })
9960
+ ] }) }),
9961
+ /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "md", children: [
9962
+ /* @__PURE__ */ jsx(Typography, { variant: "small", weight: "bold", className: "uppercase tracking-wider text-[var(--color-muted-foreground)]", children: t("simulator.parameters") }),
9963
+ entity.parameters.map((param) => /* @__PURE__ */ jsxs(VStack, { gap: "xs", children: [
9964
+ /* @__PURE__ */ jsxs(HStack, { justify: "between", align: "center", children: [
9965
+ /* @__PURE__ */ jsx(Typography, { variant: "body", weight: "medium", children: param.label }),
9966
+ /* @__PURE__ */ jsxs(Badge, { size: "sm", children: [
9967
+ values[param.id],
9968
+ " ",
9969
+ param.unit
9970
+ ] })
9971
+ ] }),
9972
+ /* @__PURE__ */ jsx(
9973
+ "input",
9974
+ {
9975
+ type: "range",
9976
+ min: param.min,
9977
+ max: param.max,
9978
+ step: param.step,
9979
+ value: values[param.id],
9980
+ onChange: (e) => handleParameterChange(param.id, Number(e.target.value)),
9981
+ disabled: submitted,
9982
+ className: "w-full accent-[var(--color-foreground)]"
9983
+ }
9984
+ ),
9985
+ /* @__PURE__ */ jsxs(HStack, { justify: "between", children: [
9986
+ /* @__PURE__ */ jsxs(Typography, { variant: "caption", className: "text-[var(--color-muted-foreground)]", children: [
9987
+ param.min,
9988
+ " ",
9989
+ param.unit
9990
+ ] }),
9991
+ /* @__PURE__ */ jsxs(Typography, { variant: "caption", className: "text-[var(--color-muted-foreground)]", children: [
9992
+ param.max,
9993
+ " ",
9994
+ param.unit
9995
+ ] })
9996
+ ] })
9997
+ ] }, param.id))
9998
+ ] }) }),
9999
+ /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", align: "center", children: [
10000
+ /* @__PURE__ */ jsx(Typography, { variant: "small", weight: "bold", className: "uppercase tracking-wider text-[var(--color-muted-foreground)]", children: entity.outputLabel }),
10001
+ /* @__PURE__ */ jsxs(Typography, { variant: "h3", weight: "bold", children: [
10002
+ output.toFixed(2),
9931
10003
  " ",
9932
- param.unit
10004
+ entity.outputUnit
10005
+ ] }),
10006
+ submitted && /* @__PURE__ */ jsxs(HStack, { gap: "xs", align: "center", children: [
10007
+ /* @__PURE__ */ jsx(Icon, { icon: isCorrect ? CheckCircle : XCircle, size: "sm", className: isCorrect ? "text-green-600" : "text-red-600" }),
10008
+ /* @__PURE__ */ jsx(Typography, { variant: "body", className: isCorrect ? "text-green-600" : "text-red-600", children: isCorrect ? entity.successMessage ?? t("simulator.correct") : entity.failMessage ?? t("simulator.incorrect") })
9933
10009
  ] }),
9934
10010
  /* @__PURE__ */ jsxs(Typography, { variant: "caption", className: "text-[var(--color-muted-foreground)]", children: [
9935
- param.max,
10011
+ t("simulator.target"),
10012
+ ": ",
10013
+ entity.targetValue,
9936
10014
  " ",
9937
- param.unit
10015
+ entity.outputUnit,
10016
+ " (\xB1",
10017
+ entity.targetTolerance,
10018
+ ")"
10019
+ ] })
10020
+ ] }) }),
10021
+ showHint && entity.hint && /* @__PURE__ */ jsx(Card, { className: "p-4 border-l-4 border-l-yellow-500", children: /* @__PURE__ */ jsx(Typography, { variant: "body", children: entity.hint }) }),
10022
+ /* @__PURE__ */ jsxs(HStack, { gap: "sm", justify: "center", children: [
10023
+ !submitted ? /* @__PURE__ */ jsxs(Button, { variant: "primary", onClick: handleSubmit, children: [
10024
+ /* @__PURE__ */ jsx(Icon, { icon: Play, size: "sm" }),
10025
+ t("simulator.simulate")
10026
+ ] }) : !isCorrect ? /* @__PURE__ */ jsx(Button, { variant: "primary", onClick: handleReset, children: t("simulator.tryAgain") }) : null,
10027
+ /* @__PURE__ */ jsxs(Button, { variant: "secondary", onClick: handleFullReset, children: [
10028
+ /* @__PURE__ */ jsx(Icon, { icon: RotateCcw, size: "sm" }),
10029
+ t("simulator.reset")
9938
10030
  ] })
9939
10031
  ] })
9940
- ] }, param.id))
9941
- ] }) }),
9942
- /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", align: "center", children: [
9943
- /* @__PURE__ */ jsx(Typography, { variant: "small", weight: "bold", className: "uppercase tracking-wider text-[var(--color-muted-foreground)]", children: entity.outputLabel }),
9944
- /* @__PURE__ */ jsxs(Typography, { variant: "h3", weight: "bold", children: [
9945
- output.toFixed(2),
9946
- " ",
9947
- entity.outputUnit
9948
- ] }),
9949
- submitted && /* @__PURE__ */ jsxs(HStack, { gap: "xs", align: "center", children: [
9950
- /* @__PURE__ */ jsx(Icon, { icon: isCorrect ? CheckCircle : XCircle, size: "sm", className: isCorrect ? "text-green-600" : "text-red-600" }),
9951
- /* @__PURE__ */ jsx(Typography, { variant: "body", className: isCorrect ? "text-green-600" : "text-red-600", children: isCorrect ? entity.successMessage ?? t("simulator.correct") : entity.failMessage ?? t("simulator.incorrect") })
9952
- ] }),
9953
- /* @__PURE__ */ jsxs(Typography, { variant: "caption", className: "text-[var(--color-muted-foreground)]", children: [
9954
- t("simulator.target"),
9955
- ": ",
9956
- entity.targetValue,
9957
- " ",
9958
- entity.outputUnit,
9959
- " (\xB1",
9960
- entity.targetTolerance,
9961
- ")"
9962
10032
  ] })
9963
- ] }) }),
9964
- showHint && entity.hint && /* @__PURE__ */ jsx(Card, { className: "p-4 border-l-4 border-l-yellow-500", children: /* @__PURE__ */ jsx(Typography, { variant: "body", children: entity.hint }) }),
9965
- /* @__PURE__ */ jsxs(HStack, { gap: "sm", justify: "center", children: [
9966
- !submitted ? /* @__PURE__ */ jsxs(Button, { variant: "primary", onClick: handleSubmit, children: [
9967
- /* @__PURE__ */ jsx(Icon, { icon: Play, size: "sm" }),
9968
- t("simulator.simulate")
9969
- ] }) : !isCorrect ? /* @__PURE__ */ jsx(Button, { variant: "primary", onClick: handleReset, children: t("simulator.tryAgain") }) : null,
9970
- /* @__PURE__ */ jsxs(Button, { variant: "secondary", onClick: handleFullReset, children: [
9971
- /* @__PURE__ */ jsx(Icon, { icon: RotateCcw, size: "sm" }),
9972
- t("simulator.reset")
9973
- ] })
9974
- ] })
9975
- ] }) });
10033
+ }
10034
+ );
9976
10035
  }
9977
10036
  SimulatorBoard.displayName = "SimulatorBoard";
9978
10037
  function ClassifierBoard({
@@ -9983,6 +10042,7 @@ function ClassifierBoard({
9983
10042
  const { emit } = useEventBus();
9984
10043
  const { t } = useTranslate();
9985
10044
  const [assignments, setAssignments] = useState({});
10045
+ const [headerError, setHeaderError] = useState(false);
9986
10046
  const [submitted, setSubmitted] = useState(false);
9987
10047
  const [attempts, setAttempts] = useState(0);
9988
10048
  const [showHint, setShowHint] = useState(false);
@@ -10027,71 +10087,83 @@ function ClassifierBoard({
10027
10087
  setAttempts(0);
10028
10088
  setShowHint(false);
10029
10089
  };
10030
- return /* @__PURE__ */ jsx(Box, { className, children: /* @__PURE__ */ jsxs(VStack, { gap: "lg", className: "p-4", children: [
10031
- /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
10032
- /* @__PURE__ */ jsx(Typography, { variant: "h4", weight: "bold", children: entity.title }),
10033
- /* @__PURE__ */ jsx(Typography, { variant: "body", children: entity.description })
10034
- ] }) }),
10035
- unassignedItems.length > 0 && /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
10036
- /* @__PURE__ */ jsx(Typography, { variant: "small", weight: "bold", className: "uppercase tracking-wider text-[var(--color-muted-foreground)]", children: t("classifier.itemsToSort") }),
10037
- /* @__PURE__ */ jsx(HStack, { gap: "sm", className: "flex-wrap", children: unassignedItems.map((item) => /* @__PURE__ */ jsx(Badge, { size: "md", className: "cursor-pointer", children: item.label }, item.id)) })
10038
- ] }) }),
10039
- /* @__PURE__ */ jsx(VStack, { gap: "md", children: entity.categories.map((cat) => {
10040
- const catItems = entity.items.filter((item) => assignments[item.id] === cat.id);
10041
- return /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
10042
- /* @__PURE__ */ jsxs(HStack, { justify: "between", align: "center", children: [
10043
- /* @__PURE__ */ jsx(Typography, { variant: "body", weight: "bold", children: cat.label }),
10044
- /* @__PURE__ */ jsx(Badge, { size: "sm", children: catItems.length })
10045
- ] }),
10046
- /* @__PURE__ */ jsx(HStack, { gap: "xs", className: "flex-wrap min-h-[2rem]", children: catItems.map((item) => {
10047
- const result = results.find((r) => r.item.id === item.id);
10048
- return /* @__PURE__ */ jsxs(
10049
- Badge,
10050
- {
10051
- size: "sm",
10052
- className: `cursor-pointer ${result ? result.correct ? "border-green-500 bg-green-50 dark:bg-green-950" : "border-red-500 bg-red-50 dark:bg-red-950" : ""}`,
10053
- onClick: () => handleUnassign(item.id),
10054
- children: [
10055
- item.label,
10056
- result && /* @__PURE__ */ jsx(Icon, { icon: result.correct ? CheckCircle : XCircle, size: "xs", className: result.correct ? "text-green-600" : "text-red-600" })
10057
- ]
10058
- },
10059
- item.id
10060
- );
10090
+ return /* @__PURE__ */ jsx(
10091
+ Box,
10092
+ {
10093
+ className,
10094
+ style: {
10095
+ backgroundImage: entity.theme?.background ? `url(${entity.theme.background})` : void 0,
10096
+ backgroundSize: "cover",
10097
+ backgroundPosition: "center"
10098
+ },
10099
+ children: /* @__PURE__ */ jsxs(VStack, { gap: "lg", className: "p-4", children: [
10100
+ entity.headerImage && !headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 overflow-hidden rounded-lg", children: /* @__PURE__ */ jsx("img", { src: entity.headerImage, alt: "", onError: () => setHeaderError(true), className: "w-full h-full object-cover" }) }) : entity.headerImage && headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 rounded-lg bg-gradient-to-br from-[var(--color-muted)] to-[var(--color-accent)] opacity-60" }) : null,
10101
+ /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
10102
+ /* @__PURE__ */ jsx(Typography, { variant: "h4", weight: "bold", children: entity.title }),
10103
+ /* @__PURE__ */ jsx(Typography, { variant: "body", children: entity.description })
10104
+ ] }) }),
10105
+ unassignedItems.length > 0 && /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
10106
+ /* @__PURE__ */ jsx(Typography, { variant: "small", weight: "bold", className: "uppercase tracking-wider text-[var(--color-muted-foreground)]", children: t("classifier.itemsToSort") }),
10107
+ /* @__PURE__ */ jsx(HStack, { gap: "sm", className: "flex-wrap", children: unassignedItems.map((item) => /* @__PURE__ */ jsx(Badge, { size: "md", className: "cursor-pointer", children: item.label }, item.id)) })
10108
+ ] }) }),
10109
+ /* @__PURE__ */ jsx(VStack, { gap: "md", children: entity.categories.map((cat) => {
10110
+ const catItems = entity.items.filter((item) => assignments[item.id] === cat.id);
10111
+ return /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
10112
+ /* @__PURE__ */ jsxs(HStack, { justify: "between", align: "center", children: [
10113
+ /* @__PURE__ */ jsx(Typography, { variant: "body", weight: "bold", children: cat.label }),
10114
+ /* @__PURE__ */ jsx(Badge, { size: "sm", children: catItems.length })
10115
+ ] }),
10116
+ /* @__PURE__ */ jsx(HStack, { gap: "xs", className: "flex-wrap min-h-[2rem]", children: catItems.map((item) => {
10117
+ const result = results.find((r) => r.item.id === item.id);
10118
+ return /* @__PURE__ */ jsxs(
10119
+ Badge,
10120
+ {
10121
+ size: "sm",
10122
+ className: `cursor-pointer ${result ? result.correct ? "border-green-500 bg-green-50 dark:bg-green-950" : "border-red-500 bg-red-50 dark:bg-red-950" : ""}`,
10123
+ onClick: () => handleUnassign(item.id),
10124
+ children: [
10125
+ item.label,
10126
+ result && /* @__PURE__ */ jsx(Icon, { icon: result.correct ? CheckCircle : XCircle, size: "xs", className: result.correct ? "text-green-600" : "text-red-600" })
10127
+ ]
10128
+ },
10129
+ item.id
10130
+ );
10131
+ }) }),
10132
+ !submitted && unassignedItems.length > 0 && /* @__PURE__ */ jsx(HStack, { gap: "xs", className: "flex-wrap", children: unassignedItems.map((item) => /* @__PURE__ */ jsxs(
10133
+ Button,
10134
+ {
10135
+ size: "sm",
10136
+ variant: "ghost",
10137
+ onClick: () => handleAssign(item.id, cat.id),
10138
+ className: "text-xs opacity-50 hover:opacity-100",
10139
+ children: [
10140
+ "+ ",
10141
+ item.label
10142
+ ]
10143
+ },
10144
+ item.id
10145
+ )) })
10146
+ ] }) }, cat.id);
10061
10147
  }) }),
10062
- !submitted && unassignedItems.length > 0 && /* @__PURE__ */ jsx(HStack, { gap: "xs", className: "flex-wrap", children: unassignedItems.map((item) => /* @__PURE__ */ jsxs(
10063
- Button,
10064
- {
10065
- size: "sm",
10066
- variant: "ghost",
10067
- onClick: () => handleAssign(item.id, cat.id),
10068
- className: "text-xs opacity-50 hover:opacity-100",
10069
- children: [
10070
- "+ ",
10071
- item.label
10072
- ]
10073
- },
10074
- item.id
10075
- )) })
10076
- ] }) }, cat.id);
10077
- }) }),
10078
- submitted && /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", align: "center", children: [
10079
- /* @__PURE__ */ jsx(Icon, { icon: allCorrect ? CheckCircle : XCircle, size: "lg", className: allCorrect ? "text-green-600" : "text-red-600" }),
10080
- /* @__PURE__ */ jsx(Typography, { variant: "body", weight: "bold", children: allCorrect ? entity.successMessage ?? t("classifier.allCorrect") : `${correctCount}/${entity.items.length} ${t("classifier.correct")}` }),
10081
- !allCorrect && entity.failMessage && /* @__PURE__ */ jsx(Typography, { variant: "body", className: "text-[var(--color-muted-foreground)]", children: entity.failMessage })
10082
- ] }) }),
10083
- showHint && entity.hint && /* @__PURE__ */ jsx(Card, { className: "p-4 border-l-4 border-l-yellow-500", children: /* @__PURE__ */ jsx(Typography, { variant: "body", children: entity.hint }) }),
10084
- /* @__PURE__ */ jsxs(HStack, { gap: "sm", justify: "center", children: [
10085
- !submitted ? /* @__PURE__ */ jsxs(Button, { variant: "primary", onClick: handleSubmit, disabled: !allAssigned, children: [
10086
- /* @__PURE__ */ jsx(Icon, { icon: Send, size: "sm" }),
10087
- t("classifier.check")
10088
- ] }) : !allCorrect ? /* @__PURE__ */ jsx(Button, { variant: "primary", onClick: handleReset, children: t("classifier.tryAgain") }) : null,
10089
- /* @__PURE__ */ jsxs(Button, { variant: "secondary", onClick: handleFullReset, children: [
10090
- /* @__PURE__ */ jsx(Icon, { icon: RotateCcw, size: "sm" }),
10091
- t("classifier.reset")
10148
+ submitted && /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", align: "center", children: [
10149
+ /* @__PURE__ */ jsx(Icon, { icon: allCorrect ? CheckCircle : XCircle, size: "lg", className: allCorrect ? "text-green-600" : "text-red-600" }),
10150
+ /* @__PURE__ */ jsx(Typography, { variant: "body", weight: "bold", children: allCorrect ? entity.successMessage ?? t("classifier.allCorrect") : `${correctCount}/${entity.items.length} ${t("classifier.correct")}` }),
10151
+ !allCorrect && entity.failMessage && /* @__PURE__ */ jsx(Typography, { variant: "body", className: "text-[var(--color-muted-foreground)]", children: entity.failMessage })
10152
+ ] }) }),
10153
+ showHint && entity.hint && /* @__PURE__ */ jsx(Card, { className: "p-4 border-l-4 border-l-yellow-500", children: /* @__PURE__ */ jsx(Typography, { variant: "body", children: entity.hint }) }),
10154
+ /* @__PURE__ */ jsxs(HStack, { gap: "sm", justify: "center", children: [
10155
+ !submitted ? /* @__PURE__ */ jsxs(Button, { variant: "primary", onClick: handleSubmit, disabled: !allAssigned, children: [
10156
+ /* @__PURE__ */ jsx(Icon, { icon: Send, size: "sm" }),
10157
+ t("classifier.check")
10158
+ ] }) : !allCorrect ? /* @__PURE__ */ jsx(Button, { variant: "primary", onClick: handleReset, children: t("classifier.tryAgain") }) : null,
10159
+ /* @__PURE__ */ jsxs(Button, { variant: "secondary", onClick: handleFullReset, children: [
10160
+ /* @__PURE__ */ jsx(Icon, { icon: RotateCcw, size: "sm" }),
10161
+ t("classifier.reset")
10162
+ ] })
10163
+ ] })
10092
10164
  ] })
10093
- ] })
10094
- ] }) });
10165
+ }
10166
+ );
10095
10167
  }
10096
10168
  ClassifierBoard.displayName = "ClassifierBoard";
10097
10169
  function BuilderBoard({
@@ -10102,6 +10174,7 @@ function BuilderBoard({
10102
10174
  const { emit } = useEventBus();
10103
10175
  const { t } = useTranslate();
10104
10176
  const [placements, setPlacements] = useState({});
10177
+ const [headerError, setHeaderError] = useState(false);
10105
10178
  const [submitted, setSubmitted] = useState(false);
10106
10179
  const [attempts, setAttempts] = useState(0);
10107
10180
  const [showHint, setShowHint] = useState(false);
@@ -10150,77 +10223,95 @@ function BuilderBoard({
10150
10223
  setShowHint(false);
10151
10224
  };
10152
10225
  const getComponentById = (id) => entity.components.find((c) => c.id === id);
10153
- return /* @__PURE__ */ jsx(Box, { className, children: /* @__PURE__ */ jsxs(VStack, { gap: "lg", className: "p-4", children: [
10154
- /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
10155
- /* @__PURE__ */ jsx(Typography, { variant: "h4", weight: "bold", children: entity.title }),
10156
- /* @__PURE__ */ jsx(Typography, { variant: "body", children: entity.description })
10157
- ] }) }),
10158
- /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
10159
- /* @__PURE__ */ jsx(Typography, { variant: "small", weight: "bold", className: "uppercase tracking-wider text-[var(--color-muted-foreground)]", children: t("builder.components") }),
10160
- /* @__PURE__ */ jsxs(HStack, { gap: "sm", className: "flex-wrap", children: [
10161
- availableComponents.map((comp) => /* @__PURE__ */ jsxs(
10162
- Button,
10163
- {
10164
- size: "sm",
10165
- variant: selectedComponent === comp.id ? "primary" : "secondary",
10166
- onClick: () => setSelectedComponent(selectedComponent === comp.id ? null : comp.id),
10167
- disabled: submitted,
10168
- children: [
10169
- comp.iconEmoji && `${comp.iconEmoji} `,
10170
- comp.label
10171
- ]
10172
- },
10173
- comp.id
10174
- )),
10175
- availableComponents.length === 0 && !submitted && /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-[var(--color-muted-foreground)]", children: t("builder.allPlaced") })
10176
- ] })
10177
- ] }) }),
10178
- /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
10179
- /* @__PURE__ */ jsx(Typography, { variant: "small", weight: "bold", className: "uppercase tracking-wider text-[var(--color-muted-foreground)]", children: t("builder.blueprint") }),
10180
- /* @__PURE__ */ jsx(VStack, { gap: "sm", children: entity.slots.map((slot) => {
10181
- const placedComp = placements[slot.id] ? getComponentById(placements[slot.id]) : null;
10182
- const result = results.find((r) => r.slot.id === slot.id);
10183
- return /* @__PURE__ */ jsxs(
10184
- HStack,
10185
- {
10186
- gap: "sm",
10187
- align: "center",
10188
- className: `p-3 border-2 rounded ${result ? result.correct ? "border-green-500" : "border-red-500" : selectedComponent ? "border-dashed border-[var(--color-foreground)] cursor-pointer" : "border-[var(--color-border)]"}`,
10189
- onClick: () => handlePlaceComponent(slot.id),
10190
- children: [
10191
- /* @__PURE__ */ jsxs(VStack, { gap: "none", className: "flex-1", children: [
10192
- /* @__PURE__ */ jsx(Typography, { variant: "body", weight: "medium", children: slot.label }),
10193
- slot.description && /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-[var(--color-muted-foreground)]", children: slot.description })
10194
- ] }),
10195
- placedComp ? /* @__PURE__ */ jsxs(HStack, { gap: "xs", align: "center", children: [
10196
- /* @__PURE__ */ jsxs(Badge, { size: "sm", onClick: () => handleRemoveFromSlot(slot.id), children: [
10197
- placedComp.iconEmoji && `${placedComp.iconEmoji} `,
10198
- placedComp.label
10199
- ] }),
10200
- result && /* @__PURE__ */ jsx(Icon, { icon: result.correct ? CheckCircle : XCircle, size: "sm", className: result.correct ? "text-green-600" : "text-red-600" })
10201
- ] }) : /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-[var(--color-muted-foreground)]", children: t("builder.empty") })
10202
- ]
10203
- },
10204
- slot.id
10205
- );
10206
- }) })
10207
- ] }) }),
10208
- submitted && /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", align: "center", children: [
10209
- /* @__PURE__ */ jsx(Icon, { icon: allCorrect ? CheckCircle : XCircle, size: "lg", className: allCorrect ? "text-green-600" : "text-red-600" }),
10210
- /* @__PURE__ */ jsx(Typography, { variant: "body", weight: "bold", children: allCorrect ? entity.successMessage ?? t("builder.success") : entity.failMessage ?? t("builder.incorrect") })
10211
- ] }) }),
10212
- showHint && entity.hint && /* @__PURE__ */ jsx(Card, { className: "p-4 border-l-4 border-l-yellow-500", children: /* @__PURE__ */ jsx(Typography, { variant: "body", children: entity.hint }) }),
10213
- /* @__PURE__ */ jsxs(HStack, { gap: "sm", justify: "center", children: [
10214
- !submitted ? /* @__PURE__ */ jsxs(Button, { variant: "primary", onClick: handleSubmit, disabled: !allPlaced, children: [
10215
- /* @__PURE__ */ jsx(Icon, { icon: Wrench, size: "sm" }),
10216
- t("builder.build")
10217
- ] }) : !allCorrect ? /* @__PURE__ */ jsx(Button, { variant: "primary", onClick: handleReset, children: t("builder.tryAgain") }) : null,
10218
- /* @__PURE__ */ jsxs(Button, { variant: "secondary", onClick: handleFullReset, children: [
10219
- /* @__PURE__ */ jsx(Icon, { icon: RotateCcw, size: "sm" }),
10220
- t("builder.reset")
10226
+ return /* @__PURE__ */ jsx(
10227
+ Box,
10228
+ {
10229
+ className,
10230
+ style: {
10231
+ backgroundImage: entity.theme?.background ? `url(${entity.theme.background})` : void 0,
10232
+ backgroundSize: "cover",
10233
+ backgroundPosition: "center"
10234
+ },
10235
+ children: /* @__PURE__ */ jsxs(VStack, { gap: "lg", className: "p-4", children: [
10236
+ entity.headerImage && !headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 overflow-hidden rounded-lg", children: /* @__PURE__ */ jsx("img", { src: entity.headerImage, alt: "", onError: () => setHeaderError(true), className: "w-full h-full object-cover" }) }) : entity.headerImage && headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 rounded-lg bg-gradient-to-br from-[var(--color-muted)] to-[var(--color-accent)] opacity-60" }) : null,
10237
+ /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
10238
+ /* @__PURE__ */ jsx(Typography, { variant: "h4", weight: "bold", children: entity.title }),
10239
+ /* @__PURE__ */ jsx(Typography, { variant: "body", children: entity.description })
10240
+ ] }) }),
10241
+ /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
10242
+ /* @__PURE__ */ jsx(Typography, { variant: "small", weight: "bold", className: "uppercase tracking-wider text-[var(--color-muted-foreground)]", children: t("builder.components") }),
10243
+ /* @__PURE__ */ jsxs(HStack, { gap: "sm", className: "flex-wrap", children: [
10244
+ availableComponents.map((comp) => /* @__PURE__ */ jsxs(
10245
+ Button,
10246
+ {
10247
+ size: "sm",
10248
+ variant: selectedComponent === comp.id ? "primary" : "secondary",
10249
+ onClick: () => setSelectedComponent(selectedComponent === comp.id ? null : comp.id),
10250
+ disabled: submitted,
10251
+ children: [
10252
+ 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: [
10253
+ comp.iconEmoji,
10254
+ " "
10255
+ ] }) : null,
10256
+ comp.label
10257
+ ]
10258
+ },
10259
+ comp.id
10260
+ )),
10261
+ availableComponents.length === 0 && !submitted && /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-[var(--color-muted-foreground)]", children: t("builder.allPlaced") })
10262
+ ] })
10263
+ ] }) }),
10264
+ /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
10265
+ /* @__PURE__ */ jsx(Typography, { variant: "small", weight: "bold", className: "uppercase tracking-wider text-[var(--color-muted-foreground)]", children: t("builder.blueprint") }),
10266
+ /* @__PURE__ */ jsx(VStack, { gap: "sm", children: entity.slots.map((slot) => {
10267
+ const placedComp = placements[slot.id] ? getComponentById(placements[slot.id]) : null;
10268
+ const result = results.find((r) => r.slot.id === slot.id);
10269
+ return /* @__PURE__ */ jsxs(
10270
+ HStack,
10271
+ {
10272
+ gap: "sm",
10273
+ align: "center",
10274
+ className: `p-3 border-2 rounded ${result ? result.correct ? "border-green-500" : "border-red-500" : selectedComponent ? "border-dashed border-[var(--color-foreground)] cursor-pointer" : "border-[var(--color-border)]"}`,
10275
+ onClick: () => handlePlaceComponent(slot.id),
10276
+ children: [
10277
+ /* @__PURE__ */ jsxs(VStack, { gap: "none", className: "flex-1", children: [
10278
+ /* @__PURE__ */ jsx(Typography, { variant: "body", weight: "medium", children: slot.label }),
10279
+ slot.description && /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-[var(--color-muted-foreground)]", children: slot.description })
10280
+ ] }),
10281
+ placedComp ? /* @__PURE__ */ jsxs(HStack, { gap: "xs", align: "center", children: [
10282
+ /* @__PURE__ */ jsxs(Badge, { size: "sm", onClick: () => handleRemoveFromSlot(slot.id), children: [
10283
+ 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: [
10284
+ placedComp.iconEmoji,
10285
+ " "
10286
+ ] }) : null,
10287
+ placedComp.label
10288
+ ] }),
10289
+ result && /* @__PURE__ */ jsx(Icon, { icon: result.correct ? CheckCircle : XCircle, size: "sm", className: result.correct ? "text-green-600" : "text-red-600" })
10290
+ ] }) : /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-[var(--color-muted-foreground)]", children: t("builder.empty") })
10291
+ ]
10292
+ },
10293
+ slot.id
10294
+ );
10295
+ }) })
10296
+ ] }) }),
10297
+ submitted && /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", align: "center", children: [
10298
+ /* @__PURE__ */ jsx(Icon, { icon: allCorrect ? CheckCircle : XCircle, size: "lg", className: allCorrect ? "text-green-600" : "text-red-600" }),
10299
+ /* @__PURE__ */ jsx(Typography, { variant: "body", weight: "bold", children: allCorrect ? entity.successMessage ?? t("builder.success") : entity.failMessage ?? t("builder.incorrect") })
10300
+ ] }) }),
10301
+ showHint && entity.hint && /* @__PURE__ */ jsx(Card, { className: "p-4 border-l-4 border-l-yellow-500", children: /* @__PURE__ */ jsx(Typography, { variant: "body", children: entity.hint }) }),
10302
+ /* @__PURE__ */ jsxs(HStack, { gap: "sm", justify: "center", children: [
10303
+ !submitted ? /* @__PURE__ */ jsxs(Button, { variant: "primary", onClick: handleSubmit, disabled: !allPlaced, children: [
10304
+ /* @__PURE__ */ jsx(Icon, { icon: Wrench, size: "sm" }),
10305
+ t("builder.build")
10306
+ ] }) : !allCorrect ? /* @__PURE__ */ jsx(Button, { variant: "primary", onClick: handleReset, children: t("builder.tryAgain") }) : null,
10307
+ /* @__PURE__ */ jsxs(Button, { variant: "secondary", onClick: handleFullReset, children: [
10308
+ /* @__PURE__ */ jsx(Icon, { icon: RotateCcw, size: "sm" }),
10309
+ t("builder.reset")
10310
+ ] })
10311
+ ] })
10221
10312
  ] })
10222
- ] })
10223
- ] }) });
10313
+ }
10314
+ );
10224
10315
  }
10225
10316
  BuilderBoard.displayName = "BuilderBoard";
10226
10317
  function DebuggerBoard({
@@ -10231,6 +10322,7 @@ function DebuggerBoard({
10231
10322
  const { emit } = useEventBus();
10232
10323
  const { t } = useTranslate();
10233
10324
  const [flaggedLines, setFlaggedLines] = useState(/* @__PURE__ */ new Set());
10325
+ const [headerError, setHeaderError] = useState(false);
10234
10326
  const [submitted, setSubmitted] = useState(false);
10235
10327
  const [attempts, setAttempts] = useState(0);
10236
10328
  const [showHint, setShowHint] = useState(false);
@@ -10270,73 +10362,85 @@ function DebuggerBoard({
10270
10362
  setAttempts(0);
10271
10363
  setShowHint(false);
10272
10364
  };
10273
- return /* @__PURE__ */ jsx(Box, { className, children: /* @__PURE__ */ jsxs(VStack, { gap: "lg", className: "p-4", children: [
10274
- /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
10275
- /* @__PURE__ */ jsxs(HStack, { gap: "xs", align: "center", children: [
10276
- /* @__PURE__ */ jsx(Icon, { icon: Bug, size: "sm" }),
10277
- /* @__PURE__ */ jsx(Typography, { variant: "h4", weight: "bold", children: entity.title })
10278
- ] }),
10279
- /* @__PURE__ */ jsx(Typography, { variant: "body", children: entity.description }),
10280
- /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-[var(--color-muted-foreground)]", children: t("debugger.findBugs", { count: String(entity.bugCount) }) })
10281
- ] }) }),
10282
- /* @__PURE__ */ jsx(Card, { className: "p-0 overflow-hidden", children: /* @__PURE__ */ jsx(VStack, { gap: "none", children: entity.lines.map((line, i) => {
10283
- const isFlagged = flaggedLines.has(line.id);
10284
- let lineStyle = "";
10285
- if (submitted) {
10286
- if (line.isBug && isFlagged) lineStyle = "bg-green-50 dark:bg-green-950";
10287
- else if (line.isBug && !isFlagged) lineStyle = "bg-yellow-50 dark:bg-yellow-950";
10288
- else if (!line.isBug && isFlagged) lineStyle = "bg-red-50 dark:bg-red-950";
10289
- } else if (isFlagged) {
10290
- lineStyle = "bg-red-50 dark:bg-red-950";
10291
- }
10292
- return /* @__PURE__ */ jsxs(
10293
- HStack,
10294
- {
10295
- gap: "none",
10296
- align: "stretch",
10297
- className: `border-b border-[var(--color-border)] cursor-pointer hover:bg-[var(--color-muted)] ${lineStyle}`,
10298
- onClick: () => toggleLine(line.id),
10299
- children: [
10300
- /* @__PURE__ */ jsx(Box, { className: "w-10 flex-shrink-0 flex items-center justify-center border-r border-[var(--color-border)] text-[var(--color-muted-foreground)]", children: /* @__PURE__ */ jsx(Typography, { variant: "caption", children: i + 1 }) }),
10301
- /* @__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 }) }),
10302
- /* @__PURE__ */ jsxs(Box, { className: "w-8 flex-shrink-0 flex items-center justify-center", children: [
10303
- isFlagged && /* @__PURE__ */ jsx(Icon, { icon: Bug, size: "xs", className: "text-red-600" }),
10304
- submitted && line.isBug && !isFlagged && /* @__PURE__ */ jsx(Icon, { icon: Bug, size: "xs", className: "text-yellow-600" })
10305
- ] })
10306
- ]
10307
- },
10308
- line.id
10309
- );
10310
- }) }) }),
10311
- submitted && /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
10312
- /* @__PURE__ */ jsx(Typography, { variant: "body", weight: "bold", children: allCorrect ? entity.successMessage ?? t("debugger.allFound") : `${correctFlags.length}/${bugLines.length} ${t("debugger.bugsFound")}` }),
10313
- bugLines.map((line) => /* @__PURE__ */ jsxs(HStack, { gap: "xs", align: "start", children: [
10314
- /* @__PURE__ */ jsx(
10315
- Icon,
10316
- {
10317
- icon: flaggedLines.has(line.id) ? CheckCircle : XCircle,
10318
- size: "xs",
10319
- className: flaggedLines.has(line.id) ? "text-green-600 mt-0.5" : "text-yellow-600 mt-0.5"
10365
+ return /* @__PURE__ */ jsx(
10366
+ Box,
10367
+ {
10368
+ className,
10369
+ style: {
10370
+ backgroundImage: entity.theme?.background ? `url(${entity.theme.background})` : void 0,
10371
+ backgroundSize: "cover",
10372
+ backgroundPosition: "center"
10373
+ },
10374
+ children: /* @__PURE__ */ jsxs(VStack, { gap: "lg", className: "p-4", children: [
10375
+ entity.headerImage && !headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 overflow-hidden rounded-lg", children: /* @__PURE__ */ jsx("img", { src: entity.headerImage, alt: "", onError: () => setHeaderError(true), className: "w-full h-full object-cover" }) }) : entity.headerImage && headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 rounded-lg bg-gradient-to-br from-[var(--color-muted)] to-[var(--color-accent)] opacity-60" }) : null,
10376
+ /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
10377
+ /* @__PURE__ */ jsxs(HStack, { gap: "xs", align: "center", children: [
10378
+ /* @__PURE__ */ jsx(Icon, { icon: Bug, size: "sm" }),
10379
+ /* @__PURE__ */ jsx(Typography, { variant: "h4", weight: "bold", children: entity.title })
10380
+ ] }),
10381
+ /* @__PURE__ */ jsx(Typography, { variant: "body", children: entity.description }),
10382
+ /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-[var(--color-muted-foreground)]", children: t("debugger.findBugs", { count: String(entity.bugCount) }) })
10383
+ ] }) }),
10384
+ /* @__PURE__ */ jsx(Card, { className: "p-0 overflow-hidden", children: /* @__PURE__ */ jsx(VStack, { gap: "none", children: entity.lines.map((line, i) => {
10385
+ const isFlagged = flaggedLines.has(line.id);
10386
+ let lineStyle = "";
10387
+ if (submitted) {
10388
+ if (line.isBug && isFlagged) lineStyle = "bg-green-50 dark:bg-green-950";
10389
+ else if (line.isBug && !isFlagged) lineStyle = "bg-yellow-50 dark:bg-yellow-950";
10390
+ else if (!line.isBug && isFlagged) lineStyle = "bg-red-50 dark:bg-red-950";
10391
+ } else if (isFlagged) {
10392
+ lineStyle = "bg-red-50 dark:bg-red-950";
10320
10393
  }
10321
- ),
10322
- /* @__PURE__ */ jsxs(VStack, { gap: "none", children: [
10323
- /* @__PURE__ */ jsx(Typography, { variant: "caption", weight: "bold", className: "font-mono", children: line.content.trim() }),
10324
- line.explanation && /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-[var(--color-muted-foreground)]", children: line.explanation })
10394
+ return /* @__PURE__ */ jsxs(
10395
+ HStack,
10396
+ {
10397
+ gap: "none",
10398
+ align: "stretch",
10399
+ className: `border-b border-[var(--color-border)] cursor-pointer hover:bg-[var(--color-muted)] ${lineStyle}`,
10400
+ onClick: () => toggleLine(line.id),
10401
+ children: [
10402
+ /* @__PURE__ */ jsx(Box, { className: "w-10 flex-shrink-0 flex items-center justify-center border-r border-[var(--color-border)] text-[var(--color-muted-foreground)]", children: /* @__PURE__ */ jsx(Typography, { variant: "caption", children: i + 1 }) }),
10403
+ /* @__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 }) }),
10404
+ /* @__PURE__ */ jsxs(Box, { className: "w-8 flex-shrink-0 flex items-center justify-center", children: [
10405
+ isFlagged && /* @__PURE__ */ jsx(Icon, { icon: Bug, size: "xs", className: "text-red-600" }),
10406
+ submitted && line.isBug && !isFlagged && /* @__PURE__ */ jsx(Icon, { icon: Bug, size: "xs", className: "text-yellow-600" })
10407
+ ] })
10408
+ ]
10409
+ },
10410
+ line.id
10411
+ );
10412
+ }) }) }),
10413
+ submitted && /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
10414
+ /* @__PURE__ */ jsx(Typography, { variant: "body", weight: "bold", children: allCorrect ? entity.successMessage ?? t("debugger.allFound") : `${correctFlags.length}/${bugLines.length} ${t("debugger.bugsFound")}` }),
10415
+ bugLines.map((line) => /* @__PURE__ */ jsxs(HStack, { gap: "xs", align: "start", children: [
10416
+ /* @__PURE__ */ jsx(
10417
+ Icon,
10418
+ {
10419
+ icon: flaggedLines.has(line.id) ? CheckCircle : XCircle,
10420
+ size: "xs",
10421
+ className: flaggedLines.has(line.id) ? "text-green-600 mt-0.5" : "text-yellow-600 mt-0.5"
10422
+ }
10423
+ ),
10424
+ /* @__PURE__ */ jsxs(VStack, { gap: "none", children: [
10425
+ /* @__PURE__ */ jsx(Typography, { variant: "caption", weight: "bold", className: "font-mono", children: line.content.trim() }),
10426
+ line.explanation && /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-[var(--color-muted-foreground)]", children: line.explanation })
10427
+ ] })
10428
+ ] }, line.id))
10429
+ ] }) }),
10430
+ showHint && entity.hint && /* @__PURE__ */ jsx(Card, { className: "p-4 border-l-4 border-l-yellow-500", children: /* @__PURE__ */ jsx(Typography, { variant: "body", children: entity.hint }) }),
10431
+ /* @__PURE__ */ jsxs(HStack, { gap: "sm", justify: "center", children: [
10432
+ !submitted ? /* @__PURE__ */ jsxs(Button, { variant: "primary", onClick: handleSubmit, disabled: flaggedLines.size === 0, children: [
10433
+ /* @__PURE__ */ jsx(Icon, { icon: Send, size: "sm" }),
10434
+ t("debugger.submit")
10435
+ ] }) : !allCorrect ? /* @__PURE__ */ jsx(Button, { variant: "primary", onClick: handleReset, children: t("debugger.tryAgain") }) : null,
10436
+ /* @__PURE__ */ jsxs(Button, { variant: "secondary", onClick: handleFullReset, children: [
10437
+ /* @__PURE__ */ jsx(Icon, { icon: RotateCcw, size: "sm" }),
10438
+ t("debugger.reset")
10439
+ ] })
10325
10440
  ] })
10326
- ] }, line.id))
10327
- ] }) }),
10328
- showHint && entity.hint && /* @__PURE__ */ jsx(Card, { className: "p-4 border-l-4 border-l-yellow-500", children: /* @__PURE__ */ jsx(Typography, { variant: "body", children: entity.hint }) }),
10329
- /* @__PURE__ */ jsxs(HStack, { gap: "sm", justify: "center", children: [
10330
- !submitted ? /* @__PURE__ */ jsxs(Button, { variant: "primary", onClick: handleSubmit, disabled: flaggedLines.size === 0, children: [
10331
- /* @__PURE__ */ jsx(Icon, { icon: Send, size: "sm" }),
10332
- t("debugger.submit")
10333
- ] }) : !allCorrect ? /* @__PURE__ */ jsx(Button, { variant: "primary", onClick: handleReset, children: t("debugger.tryAgain") }) : null,
10334
- /* @__PURE__ */ jsxs(Button, { variant: "secondary", onClick: handleFullReset, children: [
10335
- /* @__PURE__ */ jsx(Icon, { icon: RotateCcw, size: "sm" }),
10336
- t("debugger.reset")
10337
10441
  ] })
10338
- ] })
10339
- ] }) });
10442
+ }
10443
+ );
10340
10444
  }
10341
10445
  DebuggerBoard.displayName = "DebuggerBoard";
10342
10446
  function getOpponentAction(strategy, actions, history) {
@@ -10362,6 +10466,7 @@ function NegotiatorBoard({
10362
10466
  const { emit } = useEventBus();
10363
10467
  const { t } = useTranslate();
10364
10468
  const [history, setHistory] = useState([]);
10469
+ const [headerError, setHeaderError] = useState(false);
10365
10470
  const [showHint, setShowHint] = useState(false);
10366
10471
  const currentRound = history.length;
10367
10472
  const isComplete = currentRound >= entity.totalRounds;
@@ -10398,76 +10503,88 @@ function NegotiatorBoard({
10398
10503
  setShowHint(false);
10399
10504
  };
10400
10505
  const getActionLabel = (id) => entity.actions.find((a) => a.id === id)?.label ?? id;
10401
- return /* @__PURE__ */ jsx(Box, { className, children: /* @__PURE__ */ jsxs(VStack, { gap: "lg", className: "p-4", children: [
10402
- /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
10403
- /* @__PURE__ */ jsx(Typography, { variant: "h4", weight: "bold", children: entity.title }),
10404
- /* @__PURE__ */ jsx(Typography, { variant: "body", children: entity.description }),
10405
- /* @__PURE__ */ jsxs(HStack, { gap: "md", children: [
10406
- /* @__PURE__ */ jsx(Badge, { size: "sm", children: t("negotiator.round", { current: String(currentRound), total: String(entity.totalRounds) }) }),
10407
- /* @__PURE__ */ jsxs(Badge, { size: "sm", children: [
10408
- t("negotiator.target"),
10409
- ": ",
10410
- entity.targetScore
10411
- ] })
10412
- ] })
10413
- ] }) }),
10414
- /* @__PURE__ */ jsxs(HStack, { gap: "md", justify: "center", children: [
10415
- /* @__PURE__ */ jsx(Card, { className: "p-4 flex-1 text-center", children: /* @__PURE__ */ jsxs(VStack, { gap: "xs", align: "center", children: [
10416
- /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-[var(--color-muted-foreground)]", children: t("negotiator.you") }),
10417
- /* @__PURE__ */ jsx(Typography, { variant: "h3", weight: "bold", children: playerTotal })
10418
- ] }) }),
10419
- /* @__PURE__ */ jsx(Card, { className: "p-4 flex-1 text-center", children: /* @__PURE__ */ jsxs(VStack, { gap: "xs", align: "center", children: [
10420
- /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-[var(--color-muted-foreground)]", children: t("negotiator.opponent") }),
10421
- /* @__PURE__ */ jsx(Typography, { variant: "h3", weight: "bold", children: opponentTotal })
10422
- ] }) })
10423
- ] }),
10424
- !isComplete && /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
10425
- /* @__PURE__ */ jsx(Typography, { variant: "small", weight: "bold", className: "uppercase tracking-wider text-[var(--color-muted-foreground)]", children: t("negotiator.chooseAction") }),
10426
- /* @__PURE__ */ jsx(HStack, { gap: "sm", justify: "center", className: "flex-wrap", children: entity.actions.map((action) => /* @__PURE__ */ jsx(
10427
- Button,
10428
- {
10429
- variant: "primary",
10430
- onClick: () => handleAction(action.id),
10431
- children: action.label
10432
- },
10433
- action.id
10434
- )) })
10435
- ] }) }),
10436
- history.length > 0 && /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
10437
- /* @__PURE__ */ jsx(Typography, { variant: "small", weight: "bold", className: "uppercase tracking-wider text-[var(--color-muted-foreground)]", children: t("negotiator.history") }),
10438
- history.map((round) => /* @__PURE__ */ jsxs(HStack, { gap: "sm", align: "center", className: "text-sm", children: [
10439
- /* @__PURE__ */ jsxs(Badge, { size: "sm", children: [
10440
- "R",
10441
- round.round
10442
- ] }),
10443
- /* @__PURE__ */ jsx(Typography, { variant: "caption", children: getActionLabel(round.playerAction) }),
10444
- /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-[var(--color-muted-foreground)]", children: "vs" }),
10445
- /* @__PURE__ */ jsx(Typography, { variant: "caption", children: getActionLabel(round.opponentAction) }),
10446
- /* @__PURE__ */ jsx(Icon, { icon: ArrowRight, size: "xs" }),
10447
- /* @__PURE__ */ jsxs(Typography, { variant: "caption", weight: "bold", className: "text-green-600", children: [
10448
- "+",
10449
- round.playerPayoff
10506
+ return /* @__PURE__ */ jsx(
10507
+ Box,
10508
+ {
10509
+ className,
10510
+ style: {
10511
+ backgroundImage: entity.theme?.background ? `url(${entity.theme.background})` : void 0,
10512
+ backgroundSize: "cover",
10513
+ backgroundPosition: "center"
10514
+ },
10515
+ children: /* @__PURE__ */ jsxs(VStack, { gap: "lg", className: "p-4", children: [
10516
+ entity.headerImage && !headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 overflow-hidden rounded-lg", children: /* @__PURE__ */ jsx("img", { src: entity.headerImage, alt: "", onError: () => setHeaderError(true), className: "w-full h-full object-cover" }) }) : entity.headerImage && headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 rounded-lg bg-gradient-to-br from-[var(--color-muted)] to-[var(--color-accent)] opacity-60" }) : null,
10517
+ /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
10518
+ /* @__PURE__ */ jsx(Typography, { variant: "h4", weight: "bold", children: entity.title }),
10519
+ /* @__PURE__ */ jsx(Typography, { variant: "body", children: entity.description }),
10520
+ /* @__PURE__ */ jsxs(HStack, { gap: "md", children: [
10521
+ /* @__PURE__ */ jsx(Badge, { size: "sm", children: t("negotiator.round", { current: String(currentRound), total: String(entity.totalRounds) }) }),
10522
+ /* @__PURE__ */ jsxs(Badge, { size: "sm", children: [
10523
+ t("negotiator.target"),
10524
+ ": ",
10525
+ entity.targetScore
10526
+ ] })
10527
+ ] })
10528
+ ] }) }),
10529
+ /* @__PURE__ */ jsxs(HStack, { gap: "md", justify: "center", children: [
10530
+ /* @__PURE__ */ jsx(Card, { className: "p-4 flex-1 text-center", children: /* @__PURE__ */ jsxs(VStack, { gap: "xs", align: "center", children: [
10531
+ /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-[var(--color-muted-foreground)]", children: t("negotiator.you") }),
10532
+ /* @__PURE__ */ jsx(Typography, { variant: "h3", weight: "bold", children: playerTotal })
10533
+ ] }) }),
10534
+ /* @__PURE__ */ jsx(Card, { className: "p-4 flex-1 text-center", children: /* @__PURE__ */ jsxs(VStack, { gap: "xs", align: "center", children: [
10535
+ /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-[var(--color-muted-foreground)]", children: t("negotiator.opponent") }),
10536
+ /* @__PURE__ */ jsx(Typography, { variant: "h3", weight: "bold", children: opponentTotal })
10537
+ ] }) })
10450
10538
  ] }),
10451
- /* @__PURE__ */ jsxs(Typography, { variant: "caption", className: "text-[var(--color-muted-foreground)]", children: [
10452
- "/ +",
10453
- round.opponentPayoff
10454
- ] })
10455
- ] }, round.round))
10456
- ] }) }),
10457
- isComplete && /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", align: "center", children: [
10458
- /* @__PURE__ */ jsx(Icon, { icon: CheckCircle, size: "lg", className: won ? "text-green-600" : "text-red-600" }),
10459
- /* @__PURE__ */ jsx(Typography, { variant: "body", weight: "bold", children: won ? entity.successMessage ?? t("negotiator.success") : entity.failMessage ?? t("negotiator.failed") }),
10460
- /* @__PURE__ */ jsxs(Typography, { variant: "caption", className: "text-[var(--color-muted-foreground)]", children: [
10461
- t("negotiator.finalScore"),
10462
- ": ",
10463
- playerTotal,
10464
- "/",
10465
- entity.targetScore
10539
+ !isComplete && /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
10540
+ /* @__PURE__ */ jsx(Typography, { variant: "small", weight: "bold", className: "uppercase tracking-wider text-[var(--color-muted-foreground)]", children: t("negotiator.chooseAction") }),
10541
+ /* @__PURE__ */ jsx(HStack, { gap: "sm", justify: "center", className: "flex-wrap", children: entity.actions.map((action) => /* @__PURE__ */ jsx(
10542
+ Button,
10543
+ {
10544
+ variant: "primary",
10545
+ onClick: () => handleAction(action.id),
10546
+ children: action.label
10547
+ },
10548
+ action.id
10549
+ )) })
10550
+ ] }) }),
10551
+ history.length > 0 && /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
10552
+ /* @__PURE__ */ jsx(Typography, { variant: "small", weight: "bold", className: "uppercase tracking-wider text-[var(--color-muted-foreground)]", children: t("negotiator.history") }),
10553
+ history.map((round) => /* @__PURE__ */ jsxs(HStack, { gap: "sm", align: "center", className: "text-sm", children: [
10554
+ /* @__PURE__ */ jsxs(Badge, { size: "sm", children: [
10555
+ "R",
10556
+ round.round
10557
+ ] }),
10558
+ /* @__PURE__ */ jsx(Typography, { variant: "caption", children: getActionLabel(round.playerAction) }),
10559
+ /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-[var(--color-muted-foreground)]", children: "vs" }),
10560
+ /* @__PURE__ */ jsx(Typography, { variant: "caption", children: getActionLabel(round.opponentAction) }),
10561
+ /* @__PURE__ */ jsx(Icon, { icon: ArrowRight, size: "xs" }),
10562
+ /* @__PURE__ */ jsxs(Typography, { variant: "caption", weight: "bold", className: "text-green-600", children: [
10563
+ "+",
10564
+ round.playerPayoff
10565
+ ] }),
10566
+ /* @__PURE__ */ jsxs(Typography, { variant: "caption", className: "text-[var(--color-muted-foreground)]", children: [
10567
+ "/ +",
10568
+ round.opponentPayoff
10569
+ ] })
10570
+ ] }, round.round))
10571
+ ] }) }),
10572
+ isComplete && /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", align: "center", children: [
10573
+ /* @__PURE__ */ jsx(Icon, { icon: CheckCircle, size: "lg", className: won ? "text-green-600" : "text-red-600" }),
10574
+ /* @__PURE__ */ jsx(Typography, { variant: "body", weight: "bold", children: won ? entity.successMessage ?? t("negotiator.success") : entity.failMessage ?? t("negotiator.failed") }),
10575
+ /* @__PURE__ */ jsxs(Typography, { variant: "caption", className: "text-[var(--color-muted-foreground)]", children: [
10576
+ t("negotiator.finalScore"),
10577
+ ": ",
10578
+ playerTotal,
10579
+ "/",
10580
+ entity.targetScore
10581
+ ] })
10582
+ ] }) }),
10583
+ showHint && entity.hint && !won && /* @__PURE__ */ jsx(Card, { className: "p-4 border-l-4 border-l-yellow-500", children: /* @__PURE__ */ jsx(Typography, { variant: "body", children: entity.hint }) }),
10584
+ isComplete && !won && /* @__PURE__ */ jsx(HStack, { justify: "center", children: /* @__PURE__ */ jsx(Button, { variant: "primary", onClick: handleReset, children: t("negotiator.playAgain") }) })
10466
10585
  ] })
10467
- ] }) }),
10468
- showHint && entity.hint && !won && /* @__PURE__ */ jsx(Card, { className: "p-4 border-l-4 border-l-yellow-500", children: /* @__PURE__ */ jsx(Typography, { variant: "body", children: entity.hint }) }),
10469
- isComplete && !won && /* @__PURE__ */ jsx(HStack, { justify: "center", children: /* @__PURE__ */ jsx(Button, { variant: "primary", onClick: handleReset, children: t("negotiator.playAgain") }) })
10470
- ] }) });
10586
+ }
10587
+ );
10471
10588
  }
10472
10589
  NegotiatorBoard.displayName = "NegotiatorBoard";
10473
10590
  function SimulationCanvas({