@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.
- package/dist/{chunk-LB3HXNAR.js → chunk-LX4G4SVJ.js} +2 -2
- package/dist/{chunk-BTXQJGFB.js → chunk-QU4JHKVC.js} +24 -24
- package/dist/components/index.d.ts +80 -19
- package/dist/components/index.js +740 -623
- package/dist/context/index.js +2 -2
- package/dist/providers/index.js +4 -4
- package/package.json +1 -1
package/dist/components/index.js
CHANGED
|
@@ -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-
|
|
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-
|
|
7
|
-
import '../chunk-
|
|
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
|
|
7390
|
-
const eased = 1 - (1 -
|
|
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 (
|
|
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((
|
|
7425
|
-
name:
|
|
7426
|
-
currentState:
|
|
7427
|
-
states:
|
|
7428
|
-
cooldown:
|
|
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((
|
|
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((
|
|
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(
|
|
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(
|
|
7554
|
-
/* @__PURE__ */ jsxs(
|
|
7555
|
-
/* @__PURE__ */ jsxs(
|
|
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(
|
|
7584
|
+
sidebar && /* @__PURE__ */ jsx(Box, { className: "w-80 shrink-0", children: sidebar(ctx) })
|
|
7584
7585
|
] }),
|
|
7585
|
-
actions ? actions(ctx) : currentPhase !== "game_over" && /* @__PURE__ */ jsxs(
|
|
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
|
-
|
|
7588
|
+
Button,
|
|
7588
7589
|
{
|
|
7589
|
-
|
|
7590
|
+
variant: "secondary",
|
|
7591
|
+
className: "shadow-xl",
|
|
7590
7592
|
onClick: handleCancel,
|
|
7591
|
-
children: "
|
|
7593
|
+
children: t("battle.cancel")
|
|
7592
7594
|
}
|
|
7593
7595
|
),
|
|
7594
7596
|
/* @__PURE__ */ jsx(
|
|
7595
|
-
|
|
7597
|
+
Button,
|
|
7596
7598
|
{
|
|
7597
|
-
|
|
7599
|
+
variant: "primary",
|
|
7600
|
+
className: "shadow-xl",
|
|
7598
7601
|
onClick: handleEndTurn,
|
|
7599
|
-
children: "
|
|
7602
|
+
children: t("battle.endTurn")
|
|
7600
7603
|
}
|
|
7601
7604
|
)
|
|
7602
7605
|
] }),
|
|
7603
|
-
gameResult && (gameOverOverlay ? gameOverOverlay(ctx) : /* @__PURE__ */ jsx(
|
|
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
|
-
|
|
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" ? "
|
|
7615
|
+
children: gameResult === "victory" ? t("battle.victory") : t("battle.defeat")
|
|
7612
7616
|
}
|
|
7613
7617
|
),
|
|
7614
|
-
/* @__PURE__ */ jsxs("
|
|
7615
|
-
"
|
|
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
|
-
|
|
7624
|
+
Button,
|
|
7620
7625
|
{
|
|
7621
|
-
|
|
7626
|
+
variant: "primary",
|
|
7627
|
+
className: "px-8 py-3 font-semibold",
|
|
7622
7628
|
onClick: handleReset,
|
|
7623
|
-
children: "
|
|
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(
|
|
8972
|
-
|
|
8973
|
-
|
|
8974
|
-
|
|
8975
|
-
|
|
8976
|
-
|
|
8977
|
-
|
|
8978
|
-
|
|
8979
|
-
|
|
8980
|
-
|
|
8981
|
-
|
|
8982
|
-
|
|
8983
|
-
|
|
8984
|
-
|
|
8985
|
-
|
|
8986
|
-
|
|
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
|
-
|
|
8990
|
-
|
|
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(
|
|
9311
|
-
|
|
9312
|
-
|
|
9313
|
-
|
|
9314
|
-
|
|
9315
|
-
|
|
9316
|
-
|
|
9317
|
-
|
|
9318
|
-
|
|
9319
|
-
|
|
9320
|
-
|
|
9321
|
-
|
|
9322
|
-
|
|
9323
|
-
|
|
9324
|
-
className:
|
|
9325
|
-
"
|
|
9326
|
-
|
|
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
|
-
|
|
9336
|
-
|
|
9337
|
-
|
|
9338
|
-
|
|
9339
|
-
|
|
9340
|
-
|
|
9341
|
-
|
|
9342
|
-
|
|
9343
|
-
|
|
9344
|
-
|
|
9345
|
-
|
|
9346
|
-
|
|
9347
|
-
|
|
9348
|
-
|
|
9349
|
-
|
|
9350
|
-
|
|
9351
|
-
|
|
9352
|
-
|
|
9353
|
-
|
|
9354
|
-
|
|
9355
|
-
|
|
9356
|
-
|
|
9357
|
-
|
|
9358
|
-
|
|
9359
|
-
|
|
9360
|
-
|
|
9361
|
-
|
|
9362
|
-
|
|
9363
|
-
}
|
|
9364
|
-
|
|
9365
|
-
|
|
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(
|
|
9700
|
-
|
|
9701
|
-
|
|
9702
|
-
|
|
9703
|
-
|
|
9704
|
-
|
|
9705
|
-
|
|
9706
|
-
|
|
9707
|
-
|
|
9708
|
-
|
|
9709
|
-
|
|
9710
|
-
/* @__PURE__ */ jsxs(
|
|
9711
|
-
/* @__PURE__ */ jsx(Typography, { variant: "
|
|
9712
|
-
|
|
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
|
-
|
|
9716
|
-
|
|
9717
|
-
|
|
9718
|
-
|
|
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
|
-
|
|
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:
|
|
9795
|
-
|
|
9796
|
-
children: "
|
|
9816
|
+
onClick: handleStartAddTransition,
|
|
9817
|
+
disabled: !selectedState,
|
|
9818
|
+
children: selectedState ? t("stateArchitect.addTransition", { state: selectedState }) : t("stateArchitect.addTransitionPrompt")
|
|
9797
9819
|
}
|
|
9798
|
-
)
|
|
9799
|
-
|
|
9800
|
-
|
|
9801
|
-
|
|
9802
|
-
|
|
9803
|
-
|
|
9804
|
-
|
|
9805
|
-
|
|
9806
|
-
|
|
9807
|
-
|
|
9808
|
-
|
|
9809
|
-
|
|
9810
|
-
|
|
9811
|
-
|
|
9812
|
-
|
|
9813
|
-
|
|
9814
|
-
|
|
9815
|
-
|
|
9816
|
-
|
|
9817
|
-
|
|
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
|
-
|
|
9820
|
-
|
|
9821
|
-
|
|
9822
|
-
|
|
9823
|
-
|
|
9824
|
-
|
|
9825
|
-
|
|
9826
|
-
|
|
9827
|
-
/* @__PURE__ */
|
|
9828
|
-
|
|
9829
|
-
|
|
9830
|
-
|
|
9831
|
-
|
|
9832
|
-
|
|
9833
|
-
|
|
9834
|
-
|
|
9835
|
-
|
|
9836
|
-
|
|
9837
|
-
children: "\
|
|
9838
|
-
}
|
|
9839
|
-
|
|
9840
|
-
|
|
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(
|
|
9900
|
-
|
|
9901
|
-
|
|
9902
|
-
|
|
9903
|
-
|
|
9904
|
-
|
|
9905
|
-
|
|
9906
|
-
|
|
9907
|
-
|
|
9908
|
-
|
|
9909
|
-
|
|
9910
|
-
|
|
9911
|
-
|
|
9912
|
-
|
|
9913
|
-
|
|
9914
|
-
|
|
9915
|
-
|
|
9916
|
-
"
|
|
9917
|
-
|
|
9918
|
-
|
|
9919
|
-
|
|
9920
|
-
|
|
9921
|
-
|
|
9922
|
-
|
|
9923
|
-
|
|
9924
|
-
|
|
9925
|
-
|
|
9926
|
-
|
|
9927
|
-
|
|
9928
|
-
|
|
9929
|
-
|
|
9930
|
-
|
|
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
|
-
|
|
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
|
-
|
|
10011
|
+
t("simulator.target"),
|
|
10012
|
+
": ",
|
|
10013
|
+
entity.targetValue,
|
|
9936
10014
|
" ",
|
|
9937
|
-
|
|
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
|
-
|
|
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(
|
|
10031
|
-
|
|
10032
|
-
|
|
10033
|
-
|
|
10034
|
-
|
|
10035
|
-
|
|
10036
|
-
|
|
10037
|
-
|
|
10038
|
-
|
|
10039
|
-
|
|
10040
|
-
|
|
10041
|
-
|
|
10042
|
-
|
|
10043
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body",
|
|
10044
|
-
|
|
10045
|
-
|
|
10046
|
-
|
|
10047
|
-
|
|
10048
|
-
|
|
10049
|
-
|
|
10050
|
-
|
|
10051
|
-
|
|
10052
|
-
|
|
10053
|
-
|
|
10054
|
-
children:
|
|
10055
|
-
|
|
10056
|
-
|
|
10057
|
-
|
|
10058
|
-
|
|
10059
|
-
|
|
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
|
-
|
|
10063
|
-
|
|
10064
|
-
{
|
|
10065
|
-
|
|
10066
|
-
|
|
10067
|
-
|
|
10068
|
-
|
|
10069
|
-
|
|
10070
|
-
|
|
10071
|
-
|
|
10072
|
-
|
|
10073
|
-
|
|
10074
|
-
|
|
10075
|
-
|
|
10076
|
-
|
|
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(
|
|
10154
|
-
|
|
10155
|
-
|
|
10156
|
-
|
|
10157
|
-
|
|
10158
|
-
|
|
10159
|
-
|
|
10160
|
-
|
|
10161
|
-
|
|
10162
|
-
|
|
10163
|
-
|
|
10164
|
-
|
|
10165
|
-
|
|
10166
|
-
|
|
10167
|
-
|
|
10168
|
-
|
|
10169
|
-
|
|
10170
|
-
|
|
10171
|
-
|
|
10172
|
-
|
|
10173
|
-
|
|
10174
|
-
|
|
10175
|
-
|
|
10176
|
-
|
|
10177
|
-
|
|
10178
|
-
|
|
10179
|
-
|
|
10180
|
-
|
|
10181
|
-
|
|
10182
|
-
|
|
10183
|
-
|
|
10184
|
-
|
|
10185
|
-
|
|
10186
|
-
|
|
10187
|
-
|
|
10188
|
-
|
|
10189
|
-
|
|
10190
|
-
|
|
10191
|
-
|
|
10192
|
-
|
|
10193
|
-
|
|
10194
|
-
|
|
10195
|
-
|
|
10196
|
-
|
|
10197
|
-
|
|
10198
|
-
|
|
10199
|
-
|
|
10200
|
-
|
|
10201
|
-
|
|
10202
|
-
|
|
10203
|
-
|
|
10204
|
-
|
|
10205
|
-
|
|
10206
|
-
|
|
10207
|
-
|
|
10208
|
-
|
|
10209
|
-
|
|
10210
|
-
|
|
10211
|
-
|
|
10212
|
-
|
|
10213
|
-
|
|
10214
|
-
|
|
10215
|
-
|
|
10216
|
-
|
|
10217
|
-
|
|
10218
|
-
|
|
10219
|
-
|
|
10220
|
-
|
|
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(
|
|
10274
|
-
|
|
10275
|
-
|
|
10276
|
-
|
|
10277
|
-
|
|
10278
|
-
|
|
10279
|
-
|
|
10280
|
-
|
|
10281
|
-
|
|
10282
|
-
|
|
10283
|
-
|
|
10284
|
-
|
|
10285
|
-
|
|
10286
|
-
|
|
10287
|
-
|
|
10288
|
-
|
|
10289
|
-
|
|
10290
|
-
|
|
10291
|
-
|
|
10292
|
-
|
|
10293
|
-
|
|
10294
|
-
|
|
10295
|
-
|
|
10296
|
-
|
|
10297
|
-
|
|
10298
|
-
|
|
10299
|
-
|
|
10300
|
-
|
|
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
|
-
|
|
10323
|
-
|
|
10324
|
-
|
|
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(
|
|
10402
|
-
|
|
10403
|
-
|
|
10404
|
-
|
|
10405
|
-
|
|
10406
|
-
|
|
10407
|
-
|
|
10408
|
-
|
|
10409
|
-
|
|
10410
|
-
|
|
10411
|
-
] })
|
|
10412
|
-
|
|
10413
|
-
|
|
10414
|
-
|
|
10415
|
-
|
|
10416
|
-
|
|
10417
|
-
|
|
10418
|
-
|
|
10419
|
-
|
|
10420
|
-
|
|
10421
|
-
|
|
10422
|
-
|
|
10423
|
-
|
|
10424
|
-
|
|
10425
|
-
|
|
10426
|
-
|
|
10427
|
-
|
|
10428
|
-
|
|
10429
|
-
|
|
10430
|
-
|
|
10431
|
-
|
|
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__ */
|
|
10452
|
-
"
|
|
10453
|
-
|
|
10454
|
-
|
|
10455
|
-
|
|
10456
|
-
|
|
10457
|
-
|
|
10458
|
-
|
|
10459
|
-
|
|
10460
|
-
|
|
10461
|
-
|
|
10462
|
-
|
|
10463
|
-
|
|
10464
|
-
|
|
10465
|
-
|
|
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
|
-
|
|
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({
|