@almadar/ui 2.1.2 → 2.1.4
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-BKC4XU44.js → chunk-E3EXHX2Z.js} +1 -1
- package/dist/{chunk-PE2H3NAW.js → chunk-JLEMVREZ.js} +89 -89
- package/dist/{chunk-LB3HXNAR.js → chunk-Y7AFNUT2.js} +78 -96
- package/dist/components/index.d.ts +128 -111
- package/dist/components/index.js +843 -728
- package/dist/hooks/index.js +2 -2
- package/dist/providers/index.js +5 -5
- package/package.json +1 -1
- package/themes/trait-wars.css +154 -3
package/dist/components/index.js
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
import { useAuthContext } from '../chunk-BKC4XU44.js';
|
|
2
|
-
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
1
|
import { DEFAULT_CONFIG, renderStateMachineToDomData, parseContentSegments } from '../chunk-N6DJVKZ6.js';
|
|
2
|
+
import { useAuthContext } from '../chunk-E3EXHX2Z.js';
|
|
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-E3EXHX2Z.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-
|
|
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-Y7AFNUT2.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-Y7AFNUT2.js';
|
|
7
7
|
import '../chunk-BTXQJGFB.js';
|
|
8
|
-
import {
|
|
9
|
-
export {
|
|
8
|
+
import { cn, getNestedValue } from '../chunk-KKCVDUK7.js';
|
|
9
|
+
export { cn } from '../chunk-KKCVDUK7.js';
|
|
10
|
+
import { useTranslate } from '../chunk-JLEMVREZ.js';
|
|
11
|
+
export { EntityDataProvider, I18nProvider, createTranslate, entityDataKeys, parseQueryBinding, useEntity, useEntityDataAdapter, useEntityDetail, useEntityList, useEntityListSuspense, useEntitySuspense, useQuerySingleton, useTranslate } from '../chunk-JLEMVREZ.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';
|
|
18
|
-
import React42__default, { createContext, useState,
|
|
18
|
+
import React42__default, { createContext, useState, useCallback, useMemo, useEffect, useRef, useContext } from 'react';
|
|
19
19
|
import { ChevronDown, X, Menu, ChevronRight, ChevronLeft, ArrowUp, ArrowDown, MoreVertical, Package, Check, AlertTriangle, Trash2, List as List$1, Printer, CheckCircle, XCircle, Play, RotateCcw, Send, Wrench, Bug, ArrowRight, Pause, SkipForward, Zap, Sword, Move, Heart, Shield, AlertCircle, Circle, Clock, CheckCircle2, Image as Image$1, Upload, ZoomIn, Eraser, FileText, ZoomOut, Download, Code, WrapText, Copy, Settings, Search, Bell, LogOut, Calendar, Pencil, Eye, MoreHorizontal, Minus, Plus } from 'lucide-react';
|
|
20
20
|
import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
|
|
21
21
|
import { createPortal } from 'react-dom';
|
|
@@ -417,13 +417,13 @@ var SidebarNavItem = ({ item, collapsed }) => {
|
|
|
417
417
|
"w-full flex items-center gap-3 px-3 py-2.5 transition-all duration-[var(--transition-fast)] group relative",
|
|
418
418
|
"rounded-[var(--radius-sm)] border-[length:var(--border-width-thin)] border-transparent",
|
|
419
419
|
isActive ? [
|
|
420
|
-
"bg-[var(--color-
|
|
420
|
+
"bg-[var(--color-primary)] text-[var(--color-primary-foreground)]",
|
|
421
421
|
"font-medium shadow-[var(--shadow-sm)]",
|
|
422
|
-
"border-[var(--color-
|
|
422
|
+
"border-[var(--color-primary)] translate-x-1 -translate-y-0.5"
|
|
423
423
|
].join(" ") : [
|
|
424
424
|
"text-[var(--color-foreground)]",
|
|
425
425
|
"hover:bg-[var(--color-muted)] hover:border-[var(--color-border)]",
|
|
426
|
-
"active:bg-[var(--color-
|
|
426
|
+
"active:bg-[var(--color-primary)] active:text-[var(--color-primary-foreground)]"
|
|
427
427
|
].join(" ")
|
|
428
428
|
),
|
|
429
429
|
title: collapsed ? item.label : void 0,
|
|
@@ -434,7 +434,7 @@ var SidebarNavItem = ({ item, collapsed }) => {
|
|
|
434
434
|
size: 20,
|
|
435
435
|
className: cn(
|
|
436
436
|
"min-w-[20px] flex-shrink-0",
|
|
437
|
-
isActive && "text-[var(--color-
|
|
437
|
+
isActive && "text-[var(--color-primary-foreground)]"
|
|
438
438
|
)
|
|
439
439
|
}
|
|
440
440
|
),
|
|
@@ -460,22 +460,36 @@ var Sidebar = ({
|
|
|
460
460
|
footerContent,
|
|
461
461
|
collapsed: controlledCollapsed,
|
|
462
462
|
defaultCollapsed = false,
|
|
463
|
-
|
|
463
|
+
collapseChangeEvent,
|
|
464
464
|
hideCollapseButton = false,
|
|
465
465
|
showCloseButton = false,
|
|
466
|
-
|
|
467
|
-
|
|
466
|
+
closeEvent,
|
|
467
|
+
logoClickEvent,
|
|
468
468
|
className
|
|
469
469
|
}) => {
|
|
470
|
+
const { emit } = useEventBus();
|
|
471
|
+
const { t } = useTranslate();
|
|
470
472
|
const [internalCollapsed, setInternalCollapsed] = useState(defaultCollapsed);
|
|
471
473
|
const collapsed = controlledCollapsed !== void 0 ? controlledCollapsed : internalCollapsed;
|
|
472
|
-
const handleToggle = () => {
|
|
474
|
+
const handleToggle = useCallback(() => {
|
|
473
475
|
const newCollapsed = !collapsed;
|
|
474
476
|
if (controlledCollapsed === void 0) {
|
|
475
477
|
setInternalCollapsed(newCollapsed);
|
|
476
478
|
}
|
|
477
|
-
|
|
478
|
-
|
|
479
|
+
if (collapseChangeEvent) {
|
|
480
|
+
emit(collapseChangeEvent, { collapsed: newCollapsed });
|
|
481
|
+
}
|
|
482
|
+
}, [collapsed, controlledCollapsed, collapseChangeEvent, emit]);
|
|
483
|
+
const handleClose = useCallback(() => {
|
|
484
|
+
if (closeEvent) {
|
|
485
|
+
emit(closeEvent, {});
|
|
486
|
+
}
|
|
487
|
+
}, [closeEvent, emit]);
|
|
488
|
+
const handleLogoClick = useCallback(() => {
|
|
489
|
+
if (logoClickEvent) {
|
|
490
|
+
emit(logoClickEvent, {});
|
|
491
|
+
}
|
|
492
|
+
}, [logoClickEvent, emit]);
|
|
479
493
|
return /* @__PURE__ */ jsxs(
|
|
480
494
|
Box,
|
|
481
495
|
{
|
|
@@ -496,7 +510,7 @@ var Sidebar = ({
|
|
|
496
510
|
"flex items-center gap-3 cursor-pointer",
|
|
497
511
|
collapsed && "justify-center w-full"
|
|
498
512
|
),
|
|
499
|
-
onClick:
|
|
513
|
+
onClick: handleLogoClick,
|
|
500
514
|
children: [
|
|
501
515
|
logo ? typeof logo === "string" ? (
|
|
502
516
|
// eslint-disable-next-line almadar/no-raw-dom-elements -- semantic img with src/alt
|
|
@@ -519,7 +533,7 @@ var Sidebar = ({
|
|
|
519
533
|
"rounded-[var(--radius-sm)]",
|
|
520
534
|
collapsed && "mx-auto"
|
|
521
535
|
),
|
|
522
|
-
title: collapsed ? "
|
|
536
|
+
title: collapsed ? t("sidebar.expand") : t("sidebar.collapse"),
|
|
523
537
|
children: collapsed ? /* @__PURE__ */ jsx(ChevronRight, { size: 18 }) : /* @__PURE__ */ jsx(ChevronLeft, { size: 18 })
|
|
524
538
|
}
|
|
525
539
|
),
|
|
@@ -527,9 +541,9 @@ var Sidebar = ({
|
|
|
527
541
|
Button,
|
|
528
542
|
{
|
|
529
543
|
variant: "ghost",
|
|
530
|
-
onClick:
|
|
544
|
+
onClick: handleClose,
|
|
531
545
|
className: "p-1.5 hover:bg-[var(--color-muted)] text-[var(--color-foreground)] lg:hidden rounded-[var(--radius-sm)]",
|
|
532
|
-
"aria-label": "
|
|
546
|
+
"aria-label": t("sidebar.close"),
|
|
533
547
|
children: /* @__PURE__ */ jsx(X, { size: 18 })
|
|
534
548
|
}
|
|
535
549
|
)
|
|
@@ -635,7 +649,6 @@ var Table = ({
|
|
|
635
649
|
columns,
|
|
636
650
|
// EntityDisplayProps
|
|
637
651
|
entity,
|
|
638
|
-
data,
|
|
639
652
|
className,
|
|
640
653
|
isLoading,
|
|
641
654
|
error,
|
|
@@ -664,7 +677,7 @@ var Table = ({
|
|
|
664
677
|
const eventBus = useEventBus();
|
|
665
678
|
const resolvedEmptyMessage = emptyMessage ?? t("empty.noData");
|
|
666
679
|
const resolvedSearchPlaceholder = searchPlaceholder ?? t("common.search");
|
|
667
|
-
const resolvedData = Array.isArray(
|
|
680
|
+
const resolvedData = Array.isArray(entity) ? entity : [];
|
|
668
681
|
const resolvedSortColumn = sortColumnProp ?? sortBy;
|
|
669
682
|
const resolvedSortDirection = sortDirectionProp ?? entitySortDirection ?? void 0;
|
|
670
683
|
const resolvedCurrentPage = currentPageProp ?? page ?? 1;
|
|
@@ -994,7 +1007,6 @@ var ProgressIndicator = ({ value }) => {
|
|
|
994
1007
|
};
|
|
995
1008
|
var List = ({
|
|
996
1009
|
entity,
|
|
997
|
-
data,
|
|
998
1010
|
isLoading = false,
|
|
999
1011
|
error,
|
|
1000
1012
|
selectable = false,
|
|
@@ -1010,14 +1022,12 @@ var List = ({
|
|
|
1010
1022
|
const eventBus = useEventBus();
|
|
1011
1023
|
const { t } = useTranslate();
|
|
1012
1024
|
const resolvedEmptyMessage = emptyMessage ?? t("empty.noData");
|
|
1013
|
-
const entityName = typeof entity === "string" ? entity : void 0;
|
|
1014
1025
|
const effectiveFieldNames = normalizeFields(fields).length > 0 ? normalizeFields(fields) : fieldNames;
|
|
1015
1026
|
const rawItems = useMemo(() => {
|
|
1016
|
-
|
|
1017
|
-
if (
|
|
1018
|
-
if (d && typeof d === "object" && "id" in d) return [d];
|
|
1027
|
+
if (Array.isArray(entity)) return entity;
|
|
1028
|
+
if (entity && typeof entity === "object" && "id" in entity) return [entity];
|
|
1019
1029
|
return [];
|
|
1020
|
-
}, [
|
|
1030
|
+
}, [entity]);
|
|
1021
1031
|
const getItemActions = React42__default.useCallback(
|
|
1022
1032
|
(item) => {
|
|
1023
1033
|
if (!itemActions) return [];
|
|
@@ -1033,26 +1043,25 @@ var List = ({
|
|
|
1033
1043
|
/\{\{(\w+)\}\}/g,
|
|
1034
1044
|
(_, key) => String(item[key] || item.id || "")
|
|
1035
1045
|
);
|
|
1036
|
-
eventBus.emit("UI:NAVIGATE", { url, row: item
|
|
1046
|
+
eventBus.emit("UI:NAVIGATE", { url, row: item });
|
|
1037
1047
|
return;
|
|
1038
1048
|
}
|
|
1039
1049
|
if (action.event) {
|
|
1040
1050
|
eventBus.emit(`UI:${action.event}`, {
|
|
1041
|
-
row: item
|
|
1042
|
-
entity: entityName
|
|
1051
|
+
row: item
|
|
1043
1052
|
});
|
|
1044
1053
|
}
|
|
1045
1054
|
}
|
|
1046
1055
|
}));
|
|
1047
1056
|
},
|
|
1048
|
-
[itemActions, eventBus
|
|
1057
|
+
[itemActions, eventBus]
|
|
1049
1058
|
);
|
|
1050
1059
|
const normalizedItemActions = itemActions ? getItemActions : void 0;
|
|
1051
1060
|
if (isLoading) {
|
|
1052
1061
|
return /* @__PURE__ */ jsx(
|
|
1053
1062
|
LoadingState,
|
|
1054
1063
|
{
|
|
1055
|
-
message:
|
|
1064
|
+
message: "Loading items...",
|
|
1056
1065
|
className
|
|
1057
1066
|
}
|
|
1058
1067
|
);
|
|
@@ -1062,7 +1071,7 @@ var List = ({
|
|
|
1062
1071
|
EmptyState,
|
|
1063
1072
|
{
|
|
1064
1073
|
icon: Package,
|
|
1065
|
-
title:
|
|
1074
|
+
title: "Error loading items",
|
|
1066
1075
|
description: error.message,
|
|
1067
1076
|
className
|
|
1068
1077
|
}
|
|
@@ -1109,7 +1118,7 @@ var List = ({
|
|
|
1109
1118
|
}
|
|
1110
1119
|
};
|
|
1111
1120
|
const handleRowClick = (item) => {
|
|
1112
|
-
eventBus.emit("UI:VIEW", { row: item
|
|
1121
|
+
eventBus.emit("UI:VIEW", { row: item });
|
|
1113
1122
|
};
|
|
1114
1123
|
const defaultRenderItem = (item, index, isLast) => {
|
|
1115
1124
|
const isSelected = selectedIds.map(String).includes(item.id);
|
|
@@ -1325,7 +1334,7 @@ var List = ({
|
|
|
1325
1334
|
EmptyState,
|
|
1326
1335
|
{
|
|
1327
1336
|
icon: Package,
|
|
1328
|
-
title:
|
|
1337
|
+
title: "No items found",
|
|
1329
1338
|
description: resolvedEmptyMessage,
|
|
1330
1339
|
className
|
|
1331
1340
|
}
|
|
@@ -3376,7 +3385,7 @@ var PRINT_STYLES = `
|
|
|
3376
3385
|
}
|
|
3377
3386
|
`;
|
|
3378
3387
|
var BookViewer = ({
|
|
3379
|
-
|
|
3388
|
+
entity,
|
|
3380
3389
|
initialPage = 0,
|
|
3381
3390
|
fieldMap,
|
|
3382
3391
|
className
|
|
@@ -3386,10 +3395,11 @@ var BookViewer = ({
|
|
|
3386
3395
|
const [currentPage, setCurrentPage] = useState(initialPage);
|
|
3387
3396
|
const resolvedFieldMap = useMemo(() => resolveFieldMap(fieldMap), [fieldMap]);
|
|
3388
3397
|
const book = useMemo(() => {
|
|
3389
|
-
const
|
|
3398
|
+
const entityArray = Array.isArray(entity) ? entity : entity ? [entity] : [];
|
|
3399
|
+
const raw = entityArray[0];
|
|
3390
3400
|
if (!raw) return null;
|
|
3391
3401
|
return mapBookData(raw, resolvedFieldMap);
|
|
3392
|
-
}, [
|
|
3402
|
+
}, [entity, resolvedFieldMap]);
|
|
3393
3403
|
const direction = book?.direction ?? "ltr";
|
|
3394
3404
|
const chapters = useMemo(() => book ? flattenChapters(book) : [], [book]);
|
|
3395
3405
|
const totalPages = 2 + chapters.length;
|
|
@@ -7333,6 +7343,7 @@ function BattleBoard({
|
|
|
7333
7343
|
const currentTurn = entity.turn;
|
|
7334
7344
|
const gameResult = entity.gameResult;
|
|
7335
7345
|
const eventBus = useEventBus();
|
|
7346
|
+
const { t } = useTranslate();
|
|
7336
7347
|
const [hoveredTile, setHoveredTile] = useState(null);
|
|
7337
7348
|
const [isShaking, setIsShaking] = useState(false);
|
|
7338
7349
|
const selectedUnit = useMemo(
|
|
@@ -7386,11 +7397,11 @@ function BattleBoard({
|
|
|
7386
7397
|
const anim2 = movementAnimRef.current;
|
|
7387
7398
|
if (!anim2) return;
|
|
7388
7399
|
anim2.elapsed += 16;
|
|
7389
|
-
const
|
|
7390
|
-
const eased = 1 - (1 -
|
|
7400
|
+
const t2 = Math.min(anim2.elapsed / anim2.duration, 1);
|
|
7401
|
+
const eased = 1 - (1 - t2) * (1 - t2);
|
|
7391
7402
|
const cx = anim2.from.x + (anim2.to.x - anim2.from.x) * eased;
|
|
7392
7403
|
const cy = anim2.from.y + (anim2.to.y - anim2.from.y) * eased;
|
|
7393
|
-
if (
|
|
7404
|
+
if (t2 >= 1) {
|
|
7394
7405
|
movementAnimRef.current = null;
|
|
7395
7406
|
setMovingPositions((prev) => {
|
|
7396
7407
|
const next = new Map(prev);
|
|
@@ -7421,16 +7432,16 @@ function BattleBoard({
|
|
|
7421
7432
|
unitType: unit.unitType,
|
|
7422
7433
|
heroId: unit.heroId,
|
|
7423
7434
|
sprite: unit.sprite,
|
|
7424
|
-
traits: unit.traits?.map((
|
|
7425
|
-
name:
|
|
7426
|
-
currentState:
|
|
7427
|
-
states:
|
|
7428
|
-
cooldown:
|
|
7435
|
+
traits: unit.traits?.map((t2) => ({
|
|
7436
|
+
name: t2.name,
|
|
7437
|
+
currentState: t2.currentState,
|
|
7438
|
+
states: t2.states,
|
|
7439
|
+
cooldown: t2.cooldown ?? 0
|
|
7429
7440
|
}))
|
|
7430
7441
|
};
|
|
7431
7442
|
});
|
|
7432
7443
|
}, [units, movingPositions]);
|
|
7433
|
-
const maxY = Math.max(...tiles.map((
|
|
7444
|
+
const maxY = Math.max(...tiles.map((t2) => t2.y), 0);
|
|
7434
7445
|
const baseOffsetX = (maxY + 1) * (TILE_WIDTH * scale / 2);
|
|
7435
7446
|
const tileToScreen = useCallback(
|
|
7436
7447
|
(tx, ty) => isoToScreen(tx, ty, scale, baseOffsetX),
|
|
@@ -7458,7 +7469,7 @@ function BattleBoard({
|
|
|
7458
7469
|
eventBus.emit(`UI:${unitClickEvent}`, { unitId });
|
|
7459
7470
|
}
|
|
7460
7471
|
if (currentPhase === "action" && selectedUnit) {
|
|
7461
|
-
if (unit.team === "enemy" && attackTargets.some((
|
|
7472
|
+
if (unit.team === "enemy" && attackTargets.some((t2) => t2.x === unit.position.x && t2.y === unit.position.y)) {
|
|
7462
7473
|
const damage = calculateDamage2 ? calculateDamage2(selectedUnit, unit) : Math.max(1, selectedUnit.attack - unit.defense);
|
|
7463
7474
|
setIsShaking(true);
|
|
7464
7475
|
setTimeout(() => setIsShaking(false), 300);
|
|
@@ -7535,7 +7546,7 @@ function BattleBoard({
|
|
|
7535
7546
|
]
|
|
7536
7547
|
);
|
|
7537
7548
|
const shakeStyle = isShaking ? { animation: "battle-shake 0.3s ease-in-out" } : {};
|
|
7538
|
-
return /* @__PURE__ */ jsxs(
|
|
7549
|
+
return /* @__PURE__ */ jsxs(VStack, { className: cn("battle-board relative min-h-[600px] bg-[var(--color-background)]", className), gap: "none", children: [
|
|
7539
7550
|
/* @__PURE__ */ jsx("style", { children: `
|
|
7540
7551
|
@keyframes battle-shake {
|
|
7541
7552
|
0%, 100% { transform: translate(0, 0); }
|
|
@@ -7550,9 +7561,9 @@ function BattleBoard({
|
|
|
7550
7561
|
90% { transform: translate(-2px, 1px); }
|
|
7551
7562
|
}
|
|
7552
7563
|
` }),
|
|
7553
|
-
header && /* @__PURE__ */ jsx(
|
|
7554
|
-
/* @__PURE__ */ jsxs(
|
|
7555
|
-
/* @__PURE__ */ jsxs(
|
|
7564
|
+
header && /* @__PURE__ */ jsx(Box, { className: "p-4", children: header(ctx) }),
|
|
7565
|
+
/* @__PURE__ */ jsxs(HStack, { className: "flex-1 gap-4 p-4 pt-0", gap: "none", children: [
|
|
7566
|
+
/* @__PURE__ */ jsxs(Box, { className: "relative flex-1", style: shakeStyle, children: [
|
|
7556
7567
|
/* @__PURE__ */ jsx(
|
|
7557
7568
|
IsometricCanvas_default,
|
|
7558
7569
|
{
|
|
@@ -7580,47 +7591,52 @@ function BattleBoard({
|
|
|
7580
7591
|
),
|
|
7581
7592
|
overlay && overlay(ctx)
|
|
7582
7593
|
] }),
|
|
7583
|
-
sidebar && /* @__PURE__ */ jsx(
|
|
7594
|
+
sidebar && /* @__PURE__ */ jsx(Box, { className: "w-80 shrink-0", children: sidebar(ctx) })
|
|
7584
7595
|
] }),
|
|
7585
|
-
actions ? actions(ctx) : currentPhase !== "game_over" && /* @__PURE__ */ jsxs(
|
|
7596
|
+
actions ? actions(ctx) : currentPhase !== "game_over" && /* @__PURE__ */ jsxs(HStack, { className: "fixed bottom-6 right-6 z-50", gap: "sm", children: [
|
|
7586
7597
|
(currentPhase === "movement" || currentPhase === "action") && /* @__PURE__ */ jsx(
|
|
7587
|
-
|
|
7598
|
+
Button,
|
|
7588
7599
|
{
|
|
7589
|
-
|
|
7600
|
+
variant: "secondary",
|
|
7601
|
+
className: "shadow-xl",
|
|
7590
7602
|
onClick: handleCancel,
|
|
7591
|
-
children: "
|
|
7603
|
+
children: t("battle.cancel")
|
|
7592
7604
|
}
|
|
7593
7605
|
),
|
|
7594
7606
|
/* @__PURE__ */ jsx(
|
|
7595
|
-
|
|
7607
|
+
Button,
|
|
7596
7608
|
{
|
|
7597
|
-
|
|
7609
|
+
variant: "primary",
|
|
7610
|
+
className: "shadow-xl",
|
|
7598
7611
|
onClick: handleEndTurn,
|
|
7599
|
-
children: "
|
|
7612
|
+
children: t("battle.endTurn")
|
|
7600
7613
|
}
|
|
7601
7614
|
)
|
|
7602
7615
|
] }),
|
|
7603
|
-
gameResult && (gameOverOverlay ? gameOverOverlay(ctx) : /* @__PURE__ */ jsx(
|
|
7616
|
+
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
7617
|
/* @__PURE__ */ jsx(
|
|
7605
|
-
|
|
7618
|
+
Typography,
|
|
7606
7619
|
{
|
|
7620
|
+
variant: "h2",
|
|
7607
7621
|
className: cn(
|
|
7608
7622
|
"text-4xl font-black tracking-widest uppercase",
|
|
7609
7623
|
gameResult === "victory" ? "text-yellow-400" : "text-red-500"
|
|
7610
7624
|
),
|
|
7611
|
-
children: gameResult === "victory" ? "
|
|
7625
|
+
children: gameResult === "victory" ? t("battle.victory") : t("battle.defeat")
|
|
7612
7626
|
}
|
|
7613
7627
|
),
|
|
7614
|
-
/* @__PURE__ */ jsxs("
|
|
7615
|
-
"
|
|
7628
|
+
/* @__PURE__ */ jsxs(Typography, { variant: "body1", className: "text-gray-300", children: [
|
|
7629
|
+
t("battle.turnsPlayed"),
|
|
7630
|
+
": ",
|
|
7616
7631
|
currentTurn
|
|
7617
7632
|
] }),
|
|
7618
7633
|
/* @__PURE__ */ jsx(
|
|
7619
|
-
|
|
7634
|
+
Button,
|
|
7620
7635
|
{
|
|
7621
|
-
|
|
7636
|
+
variant: "primary",
|
|
7637
|
+
className: "px-8 py-3 font-semibold",
|
|
7622
7638
|
onClick: handleReset,
|
|
7623
|
-
children: "
|
|
7639
|
+
children: t("battle.playAgain")
|
|
7624
7640
|
}
|
|
7625
7641
|
)
|
|
7626
7642
|
] }) }))
|
|
@@ -8716,6 +8732,7 @@ function ActionTile({
|
|
|
8716
8732
|
categoryColors,
|
|
8717
8733
|
className
|
|
8718
8734
|
}) {
|
|
8735
|
+
useTranslate();
|
|
8719
8736
|
const config = SIZE_CONFIG3[size];
|
|
8720
8737
|
const catColor = categoryColors?.[action.category];
|
|
8721
8738
|
const handleDragStart = useCallback((e) => {
|
|
@@ -8743,7 +8760,7 @@ function ActionTile({
|
|
|
8743
8760
|
draggable: !disabled,
|
|
8744
8761
|
onDragStart: handleDragStart,
|
|
8745
8762
|
children: [
|
|
8746
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body1", className: cn(config.icon, "leading-none"), children: action.iconEmoji || "\u2726" }),
|
|
8763
|
+
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
8764
|
/* @__PURE__ */ jsx(Typography, { variant: "caption", className: cn(config.text, "text-foreground font-medium whitespace-nowrap"), children: action.name })
|
|
8748
8765
|
]
|
|
8749
8766
|
}
|
|
@@ -8856,6 +8873,7 @@ function SequencerBoard({
|
|
|
8856
8873
|
}) {
|
|
8857
8874
|
const { emit } = useEventBus();
|
|
8858
8875
|
const { t } = useTranslate();
|
|
8876
|
+
const [headerError, setHeaderError] = useState(false);
|
|
8859
8877
|
const [slots, setSlots] = useState(
|
|
8860
8878
|
() => Array.from({ length: entity.maxSlots }, () => void 0)
|
|
8861
8879
|
);
|
|
@@ -8968,64 +8986,76 @@ function SequencerBoard({
|
|
|
8968
8986
|
const hasFeedback = slotFeedback.some((f) => f !== null);
|
|
8969
8987
|
const correctCount = slotFeedback.filter((f) => f === "correct").length;
|
|
8970
8988
|
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
|
-
|
|
8989
|
+
return /* @__PURE__ */ jsxs(
|
|
8990
|
+
VStack,
|
|
8991
|
+
{
|
|
8992
|
+
className: cn("p-4 gap-6", className),
|
|
8993
|
+
style: {
|
|
8994
|
+
backgroundImage: entity.theme?.background ? `url(${entity.theme.background})` : void 0,
|
|
8995
|
+
backgroundSize: "cover",
|
|
8996
|
+
backgroundPosition: "center"
|
|
8997
|
+
},
|
|
8998
|
+
children: [
|
|
8999
|
+
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,
|
|
9000
|
+
/* @__PURE__ */ jsxs(VStack, { gap: "xs", children: [
|
|
9001
|
+
/* @__PURE__ */ jsx(Typography, { variant: "h4", className: "text-foreground", children: entity.title }),
|
|
9002
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground", children: entity.description })
|
|
9003
|
+
] }),
|
|
9004
|
+
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: [
|
|
9005
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-accent font-bold shrink-0", children: "\u{1F4A1} " + t("game.hint") + ":" }),
|
|
9006
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-foreground", children: entity.hint })
|
|
9007
|
+
] }) }),
|
|
9008
|
+
filledSlots.length > 0 && /* @__PURE__ */ jsx(TraitStateViewer, { trait: machine, variant: "linear", size: "md" }),
|
|
9009
|
+
/* @__PURE__ */ jsxs(VStack, { gap: "xs", children: [
|
|
9010
|
+
/* @__PURE__ */ jsxs(HStack, { className: "items-center justify-between", children: [
|
|
9011
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground font-medium", children: t("sequencer.yourSequence") + ":" }),
|
|
9012
|
+
hasFeedback && playState === "idle" && /* @__PURE__ */ jsxs(Typography, { variant: "caption", className: "text-muted-foreground", children: [
|
|
9013
|
+
`${correctCount}/${entity.maxSlots} `,
|
|
9014
|
+
"\u2705"
|
|
9015
|
+
] })
|
|
9016
|
+
] }),
|
|
9017
|
+
/* @__PURE__ */ jsx(
|
|
9018
|
+
SequenceBar,
|
|
9019
|
+
{
|
|
9020
|
+
slots,
|
|
9021
|
+
maxSlots: entity.maxSlots,
|
|
9022
|
+
onSlotDrop: handleSlotDrop,
|
|
9023
|
+
onSlotRemove: handleSlotRemove,
|
|
9024
|
+
playing: playState === "playing",
|
|
9025
|
+
currentStep,
|
|
9026
|
+
categoryColors,
|
|
9027
|
+
slotFeedback,
|
|
9028
|
+
size: "lg"
|
|
9029
|
+
}
|
|
9030
|
+
)
|
|
9031
|
+
] }),
|
|
9032
|
+
playState !== "playing" && /* @__PURE__ */ jsx(
|
|
9033
|
+
ActionPalette,
|
|
9034
|
+
{
|
|
9035
|
+
actions: entity.availableActions,
|
|
9036
|
+
usedActionIds: usedIds,
|
|
9037
|
+
allowDuplicates: entity.allowDuplicates !== false,
|
|
9038
|
+
categoryColors,
|
|
9039
|
+
label: t("sequencer.dragActions")
|
|
9040
|
+
}
|
|
9041
|
+
),
|
|
9042
|
+
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) }) }),
|
|
9043
|
+
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") }) }),
|
|
9044
|
+
/* @__PURE__ */ jsxs(HStack, { gap: "sm", children: [
|
|
9045
|
+
/* @__PURE__ */ jsx(
|
|
9046
|
+
Button,
|
|
9047
|
+
{
|
|
9048
|
+
variant: "primary",
|
|
9049
|
+
onClick: handlePlay,
|
|
9050
|
+
disabled: !canPlay,
|
|
9051
|
+
children: "\u25B6 " + t("game.play")
|
|
9052
|
+
}
|
|
9053
|
+
),
|
|
9054
|
+
/* @__PURE__ */ jsx(Button, { variant: "ghost", onClick: handleReset, children: "\u21BA " + t("game.reset") })
|
|
8987
9055
|
] })
|
|
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
|
-
] });
|
|
9056
|
+
]
|
|
9057
|
+
}
|
|
9058
|
+
);
|
|
9029
9059
|
}
|
|
9030
9060
|
SequencerBoard.displayName = "SequencerBoard";
|
|
9031
9061
|
function RuleEditor({
|
|
@@ -9203,6 +9233,7 @@ function EventHandlerBoard({
|
|
|
9203
9233
|
const [selectedObjectId, setSelectedObjectId] = useState(
|
|
9204
9234
|
entity.objects[0]?.id || null
|
|
9205
9235
|
);
|
|
9236
|
+
const [headerError, setHeaderError] = useState(false);
|
|
9206
9237
|
const [playState, setPlayState] = useState("editing");
|
|
9207
9238
|
const [eventLog, setEventLog] = useState([]);
|
|
9208
9239
|
const [attempts, setAttempts] = useState(0);
|
|
@@ -9307,64 +9338,76 @@ function EventHandlerBoard({
|
|
|
9307
9338
|
});
|
|
9308
9339
|
const showHint = attempts >= 3 && entity.hint;
|
|
9309
9340
|
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" })
|
|
9341
|
+
return /* @__PURE__ */ jsxs(
|
|
9342
|
+
VStack,
|
|
9343
|
+
{
|
|
9344
|
+
className: cn("p-4 gap-6", className),
|
|
9345
|
+
style: {
|
|
9346
|
+
backgroundImage: entity.theme?.background ? `url(${entity.theme.background})` : void 0,
|
|
9347
|
+
backgroundSize: "cover",
|
|
9348
|
+
backgroundPosition: "center"
|
|
9349
|
+
},
|
|
9350
|
+
children: [
|
|
9351
|
+
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,
|
|
9352
|
+
/* @__PURE__ */ jsxs(VStack, { gap: "xs", children: [
|
|
9353
|
+
/* @__PURE__ */ jsx(Typography, { variant: "h4", className: "text-foreground", children: entity.title }),
|
|
9354
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground", children: entity.description }),
|
|
9355
|
+
/* @__PURE__ */ jsxs(HStack, { className: "items-center p-2 rounded bg-primary/10 border border-primary/30", gap: "xs", children: [
|
|
9356
|
+
/* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-primary font-bold", children: t("game.goal") + ":" }),
|
|
9357
|
+
/* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-foreground", children: entity.goalCondition })
|
|
9333
9358
|
] })
|
|
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
|
-
|
|
9359
|
+
] }),
|
|
9360
|
+
/* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
|
|
9361
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground font-medium", children: t("eventHandler.clickObject") + ":" }),
|
|
9362
|
+
/* @__PURE__ */ jsx(HStack, { className: "flex-wrap", gap: "sm", children: objectViewers.map(({ obj, machine }) => /* @__PURE__ */ jsx(
|
|
9363
|
+
Box,
|
|
9364
|
+
{
|
|
9365
|
+
className: cn(
|
|
9366
|
+
"p-3 rounded-lg border-2 cursor-pointer transition-all hover:scale-105",
|
|
9367
|
+
selectedObjectId === obj.id ? "border-primary bg-primary/10" : "border-border bg-card hover:border-muted-foreground"
|
|
9368
|
+
),
|
|
9369
|
+
onClick: () => setSelectedObjectId(obj.id),
|
|
9370
|
+
children: /* @__PURE__ */ jsxs(VStack, { gap: "xs", className: "items-center min-w-[120px]", children: [
|
|
9371
|
+
/* @__PURE__ */ jsx(Typography, { variant: "h5", children: obj.icon }),
|
|
9372
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-foreground font-medium", children: obj.name }),
|
|
9373
|
+
/* @__PURE__ */ jsx(TraitStateViewer, { trait: machine, variant: "compact", size: "sm" })
|
|
9374
|
+
] })
|
|
9375
|
+
},
|
|
9376
|
+
obj.id
|
|
9377
|
+
)) })
|
|
9378
|
+
] }),
|
|
9379
|
+
selectedObject && /* @__PURE__ */ jsx(
|
|
9380
|
+
ObjectRulePanel,
|
|
9381
|
+
{
|
|
9382
|
+
object: selectedObject,
|
|
9383
|
+
onRulesChange: handleRulesChange,
|
|
9384
|
+
disabled: playState !== "editing"
|
|
9385
|
+
}
|
|
9386
|
+
),
|
|
9387
|
+
eventLog.length > 0 && /* @__PURE__ */ jsx(EventLog, { entries: eventLog }),
|
|
9388
|
+
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") }) }),
|
|
9389
|
+
playState === "fail" && /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
|
|
9390
|
+
/* @__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) }) }),
|
|
9391
|
+
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: [
|
|
9392
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-accent font-bold shrink-0", children: "\u{1F4A1} " + t("game.hint") + ":" }),
|
|
9393
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-foreground", children: entity.hint })
|
|
9394
|
+
] }) })
|
|
9395
|
+
] }),
|
|
9396
|
+
/* @__PURE__ */ jsxs(HStack, { gap: "sm", children: [
|
|
9397
|
+
playState === "fail" ? /* @__PURE__ */ jsx(Button, { variant: "primary", onClick: handleTryAgain, children: "\u{1F504} " + t("puzzle.tryAgainButton") }) : /* @__PURE__ */ jsx(
|
|
9398
|
+
Button,
|
|
9399
|
+
{
|
|
9400
|
+
variant: "primary",
|
|
9401
|
+
onClick: handlePlay,
|
|
9402
|
+
disabled: playState !== "editing",
|
|
9403
|
+
children: "\u25B6 " + t("game.play")
|
|
9404
|
+
}
|
|
9405
|
+
),
|
|
9406
|
+
/* @__PURE__ */ jsx(Button, { variant: "ghost", onClick: handleReset, children: "\u21BA " + t("game.reset") })
|
|
9407
|
+
] })
|
|
9408
|
+
]
|
|
9409
|
+
}
|
|
9410
|
+
);
|
|
9368
9411
|
}
|
|
9369
9412
|
EventHandlerBoard.displayName = "EventHandlerBoard";
|
|
9370
9413
|
function StateNode2({
|
|
@@ -9574,6 +9617,7 @@ function StateArchitectBoard({
|
|
|
9574
9617
|
const { emit } = useEventBus();
|
|
9575
9618
|
const { t } = useTranslate();
|
|
9576
9619
|
const [transitions, setTransitions] = useState(entity.transitions);
|
|
9620
|
+
const [headerError, setHeaderError] = useState(false);
|
|
9577
9621
|
const [playState, setPlayState] = useState("editing");
|
|
9578
9622
|
const [currentState, setCurrentState] = useState(entity.initialState);
|
|
9579
9623
|
const [selectedState, setSelectedState] = useState(null);
|
|
@@ -9696,150 +9740,162 @@ function StateArchitectBoard({
|
|
|
9696
9740
|
...t2.guardHint ? { guard: t2.guardHint } : {}
|
|
9697
9741
|
}))
|
|
9698
9742
|
}), [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
|
-
|
|
9743
|
+
return /* @__PURE__ */ jsxs(
|
|
9744
|
+
VStack,
|
|
9745
|
+
{
|
|
9746
|
+
className: cn("p-4 gap-6", className),
|
|
9747
|
+
style: {
|
|
9748
|
+
backgroundImage: entity.theme?.background ? `url(${entity.theme.background})` : void 0,
|
|
9749
|
+
backgroundSize: "cover",
|
|
9750
|
+
backgroundPosition: "center"
|
|
9751
|
+
},
|
|
9752
|
+
children: [
|
|
9753
|
+
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,
|
|
9754
|
+
/* @__PURE__ */ jsxs(VStack, { gap: "xs", children: [
|
|
9755
|
+
/* @__PURE__ */ jsx(Typography, { variant: "h4", className: "text-foreground", children: entity.title }),
|
|
9756
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground", children: entity.description }),
|
|
9757
|
+
/* @__PURE__ */ jsxs(HStack, { className: "items-center p-2 rounded bg-warning/10 border border-warning/30", gap: "xs", children: [
|
|
9758
|
+
/* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-warning font-bold", children: t("game.hint") + ":" }),
|
|
9759
|
+
/* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-foreground", children: entity.hint })
|
|
9760
|
+
] })
|
|
9713
9761
|
] }),
|
|
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
|
-
")"
|
|
9762
|
+
/* @__PURE__ */ jsxs(HStack, { className: "flex-wrap items-start", gap: "lg", children: [
|
|
9763
|
+
/* @__PURE__ */ jsxs(VStack, { gap: "sm", className: "flex-1 min-w-[300px]", children: [
|
|
9764
|
+
/* @__PURE__ */ jsxs(HStack, { className: "items-center justify-between", children: [
|
|
9765
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground font-medium", children: t("stateArchitect.graph") }),
|
|
9766
|
+
addingFrom && /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-accent animate-pulse", children: t("stateArchitect.clickTarget", { state: addingFrom || "" }) })
|
|
9789
9767
|
] }),
|
|
9790
|
-
|
|
9768
|
+
/* @__PURE__ */ jsxs(
|
|
9769
|
+
Box,
|
|
9770
|
+
{
|
|
9771
|
+
position: "relative",
|
|
9772
|
+
className: "rounded-lg border border-border bg-background overflow-hidden",
|
|
9773
|
+
style: { width: GRAPH_W, height: GRAPH_H },
|
|
9774
|
+
children: [
|
|
9775
|
+
/* @__PURE__ */ jsxs(
|
|
9776
|
+
"svg",
|
|
9777
|
+
{
|
|
9778
|
+
width: GRAPH_W,
|
|
9779
|
+
height: GRAPH_H,
|
|
9780
|
+
className: "absolute inset-0",
|
|
9781
|
+
style: { pointerEvents: "none" },
|
|
9782
|
+
children: [
|
|
9783
|
+
/* @__PURE__ */ jsxs("defs", { children: [
|
|
9784
|
+
/* @__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)" }) }),
|
|
9785
|
+
/* @__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)" }) })
|
|
9786
|
+
] }),
|
|
9787
|
+
transitions.map((t2) => {
|
|
9788
|
+
const fromPos = positions[t2.from];
|
|
9789
|
+
const toPos = positions[t2.to];
|
|
9790
|
+
if (!fromPos || !toPos) return null;
|
|
9791
|
+
const isActive = t2.from === currentState;
|
|
9792
|
+
return /* @__PURE__ */ jsx(
|
|
9793
|
+
TransitionArrow,
|
|
9794
|
+
{
|
|
9795
|
+
from: fromPos,
|
|
9796
|
+
to: toPos,
|
|
9797
|
+
eventLabel: t2.event,
|
|
9798
|
+
guardHint: t2.guardHint,
|
|
9799
|
+
isActive
|
|
9800
|
+
},
|
|
9801
|
+
t2.id
|
|
9802
|
+
);
|
|
9803
|
+
})
|
|
9804
|
+
]
|
|
9805
|
+
}
|
|
9806
|
+
),
|
|
9807
|
+
entity.states.map((state) => /* @__PURE__ */ jsx(
|
|
9808
|
+
StateNode2,
|
|
9809
|
+
{
|
|
9810
|
+
name: state,
|
|
9811
|
+
position: positions[state],
|
|
9812
|
+
isCurrent: state === currentState,
|
|
9813
|
+
isSelected: state === selectedState,
|
|
9814
|
+
isInitial: state === entity.initialState,
|
|
9815
|
+
onClick: () => handleStateClick(state)
|
|
9816
|
+
},
|
|
9817
|
+
state
|
|
9818
|
+
))
|
|
9819
|
+
]
|
|
9820
|
+
}
|
|
9821
|
+
),
|
|
9822
|
+
playState === "editing" && /* @__PURE__ */ jsx(HStack, { gap: "sm", children: /* @__PURE__ */ jsx(
|
|
9791
9823
|
Button,
|
|
9792
9824
|
{
|
|
9793
9825
|
variant: "ghost",
|
|
9794
|
-
onClick:
|
|
9795
|
-
|
|
9796
|
-
children: "
|
|
9826
|
+
onClick: handleStartAddTransition,
|
|
9827
|
+
disabled: !selectedState,
|
|
9828
|
+
children: selectedState ? t("stateArchitect.addTransition", { state: selectedState }) : t("stateArchitect.addTransitionPrompt")
|
|
9797
9829
|
}
|
|
9798
|
-
)
|
|
9799
|
-
|
|
9800
|
-
|
|
9801
|
-
|
|
9802
|
-
|
|
9803
|
-
|
|
9804
|
-
|
|
9805
|
-
|
|
9806
|
-
|
|
9807
|
-
|
|
9808
|
-
|
|
9809
|
-
|
|
9810
|
-
|
|
9811
|
-
|
|
9812
|
-
|
|
9813
|
-
|
|
9814
|
-
|
|
9815
|
-
|
|
9816
|
-
|
|
9817
|
-
|
|
9830
|
+
) }),
|
|
9831
|
+
transitions.length > 0 && /* @__PURE__ */ jsxs(VStack, { gap: "xs", className: "p-3 rounded-lg bg-muted/50 border border-border", children: [
|
|
9832
|
+
/* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-muted-foreground font-medium", children: t("stateArchitect.transitions", { count: transitions.length }) + ":" }),
|
|
9833
|
+
transitions.map((t2) => /* @__PURE__ */ jsxs(HStack, { className: "items-center text-xs", gap: "xs", children: [
|
|
9834
|
+
/* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-foreground", children: t2.from }),
|
|
9835
|
+
/* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-muted-foreground", children: "\u2014[" }),
|
|
9836
|
+
/* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-accent font-medium", children: t2.event }),
|
|
9837
|
+
/* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-muted-foreground", children: "]\u2192" }),
|
|
9838
|
+
/* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-success", children: t2.to }),
|
|
9839
|
+
t2.guardHint && /* @__PURE__ */ jsxs(Typography, { variant: "caption", className: "text-warning", children: [
|
|
9840
|
+
"(",
|
|
9841
|
+
t2.guardHint,
|
|
9842
|
+
")"
|
|
9843
|
+
] }),
|
|
9844
|
+
playState === "editing" && /* @__PURE__ */ jsx(
|
|
9845
|
+
Button,
|
|
9846
|
+
{
|
|
9847
|
+
variant: "ghost",
|
|
9848
|
+
onClick: () => handleRemoveTransition(t2.id),
|
|
9849
|
+
className: "text-xs ml-auto",
|
|
9850
|
+
children: "\xD7"
|
|
9851
|
+
}
|
|
9852
|
+
)
|
|
9853
|
+
] }, t2.id))
|
|
9854
|
+
] })
|
|
9855
|
+
] }),
|
|
9856
|
+
/* @__PURE__ */ jsxs(VStack, { gap: "sm", className: "w-[280px] shrink-0", children: [
|
|
9857
|
+
/* @__PURE__ */ jsx(TraitStateViewer, { trait: machine, variant: "full", size: "sm" }),
|
|
9858
|
+
/* @__PURE__ */ jsx(
|
|
9859
|
+
VariablePanel,
|
|
9860
|
+
{
|
|
9861
|
+
entityName: entity.entityName,
|
|
9862
|
+
variables
|
|
9863
|
+
}
|
|
9864
|
+
),
|
|
9865
|
+
testResults.length > 0 && /* @__PURE__ */ jsxs(VStack, { className: "p-3 rounded-lg bg-card border border-border", gap: "xs", children: [
|
|
9866
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground font-medium", children: t("stateArchitect.testResults") + ":" }),
|
|
9867
|
+
testResults.map((r, i) => /* @__PURE__ */ jsxs(HStack, { className: "items-center text-xs", gap: "xs", children: [
|
|
9868
|
+
/* @__PURE__ */ jsx(Typography, { variant: "caption", className: r.passed ? "text-success" : "text-error", children: r.passed ? "\u2714" : "\u2717" }),
|
|
9869
|
+
/* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-foreground flex-1", children: r.label }),
|
|
9870
|
+
!r.passed && /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-error", children: t("stateArchitect.gotState", { state: r.actualState }) })
|
|
9871
|
+
] }, i))
|
|
9872
|
+
] }),
|
|
9873
|
+
entity.showCodeView !== false && /* @__PURE__ */ jsx(CodeView, { data: codeData, label: "View Code" })
|
|
9874
|
+
] })
|
|
9818
9875
|
] }),
|
|
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
|
-
] });
|
|
9876
|
+
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") }) }),
|
|
9877
|
+
playState === "fail" && /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
|
|
9878
|
+
/* @__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]) }) }),
|
|
9879
|
+
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: [
|
|
9880
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-accent font-bold shrink-0", children: "\u{1F4A1} " + t("game.hint") + ":" }),
|
|
9881
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-foreground", children: entity.hint })
|
|
9882
|
+
] }) })
|
|
9883
|
+
] }),
|
|
9884
|
+
/* @__PURE__ */ jsxs(HStack, { gap: "sm", children: [
|
|
9885
|
+
playState === "fail" ? /* @__PURE__ */ jsx(Button, { variant: "primary", onClick: handleTryAgain, children: "\u{1F504} " + t("puzzle.tryAgainButton") }) : /* @__PURE__ */ jsx(
|
|
9886
|
+
Button,
|
|
9887
|
+
{
|
|
9888
|
+
variant: "primary",
|
|
9889
|
+
onClick: handleTest,
|
|
9890
|
+
disabled: playState !== "editing",
|
|
9891
|
+
children: "\u25B6 " + t("game.runTests")
|
|
9892
|
+
}
|
|
9893
|
+
),
|
|
9894
|
+
/* @__PURE__ */ jsx(Button, { variant: "ghost", onClick: handleReset, children: "\u21BA " + t("game.reset") })
|
|
9895
|
+
] })
|
|
9896
|
+
]
|
|
9897
|
+
}
|
|
9898
|
+
);
|
|
9843
9899
|
}
|
|
9844
9900
|
StateArchitectBoard.displayName = "StateArchitectBoard";
|
|
9845
9901
|
function SimulatorBoard({
|
|
@@ -9856,6 +9912,7 @@ function SimulatorBoard({
|
|
|
9856
9912
|
}
|
|
9857
9913
|
return init;
|
|
9858
9914
|
});
|
|
9915
|
+
const [headerError, setHeaderError] = useState(false);
|
|
9859
9916
|
const [submitted, setSubmitted] = useState(false);
|
|
9860
9917
|
const [attempts, setAttempts] = useState(0);
|
|
9861
9918
|
const [showHint, setShowHint] = useState(false);
|
|
@@ -9896,83 +9953,95 @@ function SimulatorBoard({
|
|
|
9896
9953
|
setAttempts(0);
|
|
9897
9954
|
setShowHint(false);
|
|
9898
9955
|
};
|
|
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
|
-
|
|
9956
|
+
return /* @__PURE__ */ jsx(
|
|
9957
|
+
Box,
|
|
9958
|
+
{
|
|
9959
|
+
className,
|
|
9960
|
+
style: {
|
|
9961
|
+
backgroundImage: entity.theme?.background ? `url(${entity.theme.background})` : void 0,
|
|
9962
|
+
backgroundSize: "cover",
|
|
9963
|
+
backgroundPosition: "center"
|
|
9964
|
+
},
|
|
9965
|
+
children: /* @__PURE__ */ jsxs(VStack, { gap: "lg", className: "p-4", children: [
|
|
9966
|
+
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,
|
|
9967
|
+
/* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
|
|
9968
|
+
/* @__PURE__ */ jsx(Typography, { variant: "h4", weight: "bold", children: entity.title }),
|
|
9969
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body", children: entity.description })
|
|
9970
|
+
] }) }),
|
|
9971
|
+
/* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "md", children: [
|
|
9972
|
+
/* @__PURE__ */ jsx(Typography, { variant: "small", weight: "bold", className: "uppercase tracking-wider text-[var(--color-muted-foreground)]", children: t("simulator.parameters") }),
|
|
9973
|
+
entity.parameters.map((param) => /* @__PURE__ */ jsxs(VStack, { gap: "xs", children: [
|
|
9974
|
+
/* @__PURE__ */ jsxs(HStack, { justify: "between", align: "center", children: [
|
|
9975
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body", weight: "medium", children: param.label }),
|
|
9976
|
+
/* @__PURE__ */ jsxs(Badge, { size: "sm", children: [
|
|
9977
|
+
values[param.id],
|
|
9978
|
+
" ",
|
|
9979
|
+
param.unit
|
|
9980
|
+
] })
|
|
9981
|
+
] }),
|
|
9982
|
+
/* @__PURE__ */ jsx(
|
|
9983
|
+
"input",
|
|
9984
|
+
{
|
|
9985
|
+
type: "range",
|
|
9986
|
+
min: param.min,
|
|
9987
|
+
max: param.max,
|
|
9988
|
+
step: param.step,
|
|
9989
|
+
value: values[param.id],
|
|
9990
|
+
onChange: (e) => handleParameterChange(param.id, Number(e.target.value)),
|
|
9991
|
+
disabled: submitted,
|
|
9992
|
+
className: "w-full accent-[var(--color-foreground)]"
|
|
9993
|
+
}
|
|
9994
|
+
),
|
|
9995
|
+
/* @__PURE__ */ jsxs(HStack, { justify: "between", children: [
|
|
9996
|
+
/* @__PURE__ */ jsxs(Typography, { variant: "caption", className: "text-[var(--color-muted-foreground)]", children: [
|
|
9997
|
+
param.min,
|
|
9998
|
+
" ",
|
|
9999
|
+
param.unit
|
|
10000
|
+
] }),
|
|
10001
|
+
/* @__PURE__ */ jsxs(Typography, { variant: "caption", className: "text-[var(--color-muted-foreground)]", children: [
|
|
10002
|
+
param.max,
|
|
10003
|
+
" ",
|
|
10004
|
+
param.unit
|
|
10005
|
+
] })
|
|
10006
|
+
] })
|
|
10007
|
+
] }, param.id))
|
|
10008
|
+
] }) }),
|
|
10009
|
+
/* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", align: "center", children: [
|
|
10010
|
+
/* @__PURE__ */ jsx(Typography, { variant: "small", weight: "bold", className: "uppercase tracking-wider text-[var(--color-muted-foreground)]", children: entity.outputLabel }),
|
|
10011
|
+
/* @__PURE__ */ jsxs(Typography, { variant: "h3", weight: "bold", children: [
|
|
10012
|
+
output.toFixed(2),
|
|
9931
10013
|
" ",
|
|
9932
|
-
|
|
10014
|
+
entity.outputUnit
|
|
10015
|
+
] }),
|
|
10016
|
+
submitted && /* @__PURE__ */ jsxs(HStack, { gap: "xs", align: "center", children: [
|
|
10017
|
+
/* @__PURE__ */ jsx(Icon, { icon: isCorrect ? CheckCircle : XCircle, size: "sm", className: isCorrect ? "text-green-600" : "text-red-600" }),
|
|
10018
|
+
/* @__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
10019
|
] }),
|
|
9934
10020
|
/* @__PURE__ */ jsxs(Typography, { variant: "caption", className: "text-[var(--color-muted-foreground)]", children: [
|
|
9935
|
-
|
|
10021
|
+
t("simulator.target"),
|
|
10022
|
+
": ",
|
|
10023
|
+
entity.targetValue,
|
|
9936
10024
|
" ",
|
|
9937
|
-
|
|
10025
|
+
entity.outputUnit,
|
|
10026
|
+
" (\xB1",
|
|
10027
|
+
entity.targetTolerance,
|
|
10028
|
+
")"
|
|
10029
|
+
] })
|
|
10030
|
+
] }) }),
|
|
10031
|
+
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 }) }),
|
|
10032
|
+
/* @__PURE__ */ jsxs(HStack, { gap: "sm", justify: "center", children: [
|
|
10033
|
+
!submitted ? /* @__PURE__ */ jsxs(Button, { variant: "primary", onClick: handleSubmit, children: [
|
|
10034
|
+
/* @__PURE__ */ jsx(Icon, { icon: Play, size: "sm" }),
|
|
10035
|
+
t("simulator.simulate")
|
|
10036
|
+
] }) : !isCorrect ? /* @__PURE__ */ jsx(Button, { variant: "primary", onClick: handleReset, children: t("simulator.tryAgain") }) : null,
|
|
10037
|
+
/* @__PURE__ */ jsxs(Button, { variant: "secondary", onClick: handleFullReset, children: [
|
|
10038
|
+
/* @__PURE__ */ jsx(Icon, { icon: RotateCcw, size: "sm" }),
|
|
10039
|
+
t("simulator.reset")
|
|
9938
10040
|
] })
|
|
9939
10041
|
] })
|
|
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
|
-
] })
|
|
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
10042
|
] })
|
|
9974
|
-
|
|
9975
|
-
|
|
10043
|
+
}
|
|
10044
|
+
);
|
|
9976
10045
|
}
|
|
9977
10046
|
SimulatorBoard.displayName = "SimulatorBoard";
|
|
9978
10047
|
function ClassifierBoard({
|
|
@@ -9983,6 +10052,7 @@ function ClassifierBoard({
|
|
|
9983
10052
|
const { emit } = useEventBus();
|
|
9984
10053
|
const { t } = useTranslate();
|
|
9985
10054
|
const [assignments, setAssignments] = useState({});
|
|
10055
|
+
const [headerError, setHeaderError] = useState(false);
|
|
9986
10056
|
const [submitted, setSubmitted] = useState(false);
|
|
9987
10057
|
const [attempts, setAttempts] = useState(0);
|
|
9988
10058
|
const [showHint, setShowHint] = useState(false);
|
|
@@ -10027,71 +10097,88 @@ function ClassifierBoard({
|
|
|
10027
10097
|
setAttempts(0);
|
|
10028
10098
|
setShowHint(false);
|
|
10029
10099
|
};
|
|
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
|
-
|
|
10055
|
-
|
|
10056
|
-
|
|
10057
|
-
|
|
10058
|
-
|
|
10059
|
-
|
|
10060
|
-
|
|
10100
|
+
return /* @__PURE__ */ jsx(
|
|
10101
|
+
Box,
|
|
10102
|
+
{
|
|
10103
|
+
className,
|
|
10104
|
+
style: {
|
|
10105
|
+
backgroundImage: entity.theme?.background ? `url(${entity.theme.background})` : void 0,
|
|
10106
|
+
backgroundSize: "cover",
|
|
10107
|
+
backgroundPosition: "center"
|
|
10108
|
+
},
|
|
10109
|
+
children: /* @__PURE__ */ jsxs(VStack, { gap: "lg", className: "p-4", children: [
|
|
10110
|
+
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,
|
|
10111
|
+
/* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
|
|
10112
|
+
/* @__PURE__ */ jsx(Typography, { variant: "h4", weight: "bold", children: entity.title }),
|
|
10113
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body", children: entity.description })
|
|
10114
|
+
] }) }),
|
|
10115
|
+
unassignedItems.length > 0 && /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
|
|
10116
|
+
/* @__PURE__ */ jsx(Typography, { variant: "small", weight: "bold", className: "uppercase tracking-wider text-[var(--color-muted-foreground)]", children: t("classifier.itemsToSort") }),
|
|
10117
|
+
/* @__PURE__ */ jsx(HStack, { gap: "sm", className: "flex-wrap", children: unassignedItems.map((item) => /* @__PURE__ */ jsxs(Badge, { size: "md", className: "cursor-pointer", children: [
|
|
10118
|
+
item.iconUrl && /* @__PURE__ */ jsx("img", { src: item.iconUrl, alt: "", className: "w-4 h-4 object-contain inline-block" }),
|
|
10119
|
+
item.label
|
|
10120
|
+
] }, item.id)) })
|
|
10121
|
+
] }) }),
|
|
10122
|
+
/* @__PURE__ */ jsx(VStack, { gap: "md", children: entity.categories.map((cat) => {
|
|
10123
|
+
const catItems = entity.items.filter((item) => assignments[item.id] === cat.id);
|
|
10124
|
+
return /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
|
|
10125
|
+
cat.imageUrl && /* @__PURE__ */ jsx(Box, { className: "w-full h-16 overflow-hidden rounded-md", children: /* @__PURE__ */ jsx("img", { src: cat.imageUrl, alt: "", className: "w-full h-full object-cover" }) }),
|
|
10126
|
+
/* @__PURE__ */ jsxs(HStack, { justify: "between", align: "center", children: [
|
|
10127
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body", weight: "bold", children: cat.label }),
|
|
10128
|
+
/* @__PURE__ */ jsx(Badge, { size: "sm", children: catItems.length })
|
|
10129
|
+
] }),
|
|
10130
|
+
/* @__PURE__ */ jsx(HStack, { gap: "xs", className: "flex-wrap min-h-[2rem]", children: catItems.map((item) => {
|
|
10131
|
+
const result = results.find((r) => r.item.id === item.id);
|
|
10132
|
+
return /* @__PURE__ */ jsxs(
|
|
10133
|
+
Badge,
|
|
10134
|
+
{
|
|
10135
|
+
size: "sm",
|
|
10136
|
+
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" : ""}`,
|
|
10137
|
+
onClick: () => handleUnassign(item.id),
|
|
10138
|
+
children: [
|
|
10139
|
+
item.iconUrl && /* @__PURE__ */ jsx("img", { src: item.iconUrl, alt: "", className: "w-3 h-3 object-contain inline-block" }),
|
|
10140
|
+
item.label,
|
|
10141
|
+
result && /* @__PURE__ */ jsx(Icon, { icon: result.correct ? CheckCircle : XCircle, size: "xs", className: result.correct ? "text-green-600" : "text-red-600" })
|
|
10142
|
+
]
|
|
10143
|
+
},
|
|
10144
|
+
item.id
|
|
10145
|
+
);
|
|
10146
|
+
}) }),
|
|
10147
|
+
!submitted && unassignedItems.length > 0 && /* @__PURE__ */ jsx(HStack, { gap: "xs", className: "flex-wrap", children: unassignedItems.map((item) => /* @__PURE__ */ jsxs(
|
|
10148
|
+
Button,
|
|
10149
|
+
{
|
|
10150
|
+
size: "sm",
|
|
10151
|
+
variant: "ghost",
|
|
10152
|
+
onClick: () => handleAssign(item.id, cat.id),
|
|
10153
|
+
className: "text-xs opacity-50 hover:opacity-100",
|
|
10154
|
+
children: [
|
|
10155
|
+
"+ ",
|
|
10156
|
+
item.label
|
|
10157
|
+
]
|
|
10158
|
+
},
|
|
10159
|
+
item.id
|
|
10160
|
+
)) })
|
|
10161
|
+
] }) }, cat.id);
|
|
10061
10162
|
}) }),
|
|
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")
|
|
10163
|
+
submitted && /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", align: "center", children: [
|
|
10164
|
+
/* @__PURE__ */ jsx(Icon, { icon: allCorrect ? CheckCircle : XCircle, size: "lg", className: allCorrect ? "text-green-600" : "text-red-600" }),
|
|
10165
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body", weight: "bold", children: allCorrect ? entity.successMessage ?? t("classifier.allCorrect") : `${correctCount}/${entity.items.length} ${t("classifier.correct")}` }),
|
|
10166
|
+
!allCorrect && entity.failMessage && /* @__PURE__ */ jsx(Typography, { variant: "body", className: "text-[var(--color-muted-foreground)]", children: entity.failMessage })
|
|
10167
|
+
] }) }),
|
|
10168
|
+
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 }) }),
|
|
10169
|
+
/* @__PURE__ */ jsxs(HStack, { gap: "sm", justify: "center", children: [
|
|
10170
|
+
!submitted ? /* @__PURE__ */ jsxs(Button, { variant: "primary", onClick: handleSubmit, disabled: !allAssigned, children: [
|
|
10171
|
+
/* @__PURE__ */ jsx(Icon, { icon: Send, size: "sm" }),
|
|
10172
|
+
t("classifier.check")
|
|
10173
|
+
] }) : !allCorrect ? /* @__PURE__ */ jsx(Button, { variant: "primary", onClick: handleReset, children: t("classifier.tryAgain") }) : null,
|
|
10174
|
+
/* @__PURE__ */ jsxs(Button, { variant: "secondary", onClick: handleFullReset, children: [
|
|
10175
|
+
/* @__PURE__ */ jsx(Icon, { icon: RotateCcw, size: "sm" }),
|
|
10176
|
+
t("classifier.reset")
|
|
10177
|
+
] })
|
|
10178
|
+
] })
|
|
10092
10179
|
] })
|
|
10093
|
-
|
|
10094
|
-
|
|
10180
|
+
}
|
|
10181
|
+
);
|
|
10095
10182
|
}
|
|
10096
10183
|
ClassifierBoard.displayName = "ClassifierBoard";
|
|
10097
10184
|
function BuilderBoard({
|
|
@@ -10102,6 +10189,7 @@ function BuilderBoard({
|
|
|
10102
10189
|
const { emit } = useEventBus();
|
|
10103
10190
|
const { t } = useTranslate();
|
|
10104
10191
|
const [placements, setPlacements] = useState({});
|
|
10192
|
+
const [headerError, setHeaderError] = useState(false);
|
|
10105
10193
|
const [submitted, setSubmitted] = useState(false);
|
|
10106
10194
|
const [attempts, setAttempts] = useState(0);
|
|
10107
10195
|
const [showHint, setShowHint] = useState(false);
|
|
@@ -10150,77 +10238,95 @@ function BuilderBoard({
|
|
|
10150
10238
|
setShowHint(false);
|
|
10151
10239
|
};
|
|
10152
10240
|
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
|
-
|
|
10241
|
+
return /* @__PURE__ */ jsx(
|
|
10242
|
+
Box,
|
|
10243
|
+
{
|
|
10244
|
+
className,
|
|
10245
|
+
style: {
|
|
10246
|
+
backgroundImage: entity.theme?.background ? `url(${entity.theme.background})` : void 0,
|
|
10247
|
+
backgroundSize: "cover",
|
|
10248
|
+
backgroundPosition: "center"
|
|
10249
|
+
},
|
|
10250
|
+
children: /* @__PURE__ */ jsxs(VStack, { gap: "lg", className: "p-4", children: [
|
|
10251
|
+
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,
|
|
10252
|
+
/* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
|
|
10253
|
+
/* @__PURE__ */ jsx(Typography, { variant: "h4", weight: "bold", children: entity.title }),
|
|
10254
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body", children: entity.description })
|
|
10255
|
+
] }) }),
|
|
10256
|
+
/* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
|
|
10257
|
+
/* @__PURE__ */ jsx(Typography, { variant: "small", weight: "bold", className: "uppercase tracking-wider text-[var(--color-muted-foreground)]", children: t("builder.components") }),
|
|
10258
|
+
/* @__PURE__ */ jsxs(HStack, { gap: "sm", className: "flex-wrap", children: [
|
|
10259
|
+
availableComponents.map((comp) => /* @__PURE__ */ jsxs(
|
|
10260
|
+
Button,
|
|
10261
|
+
{
|
|
10262
|
+
size: "sm",
|
|
10263
|
+
variant: selectedComponent === comp.id ? "primary" : "secondary",
|
|
10264
|
+
onClick: () => setSelectedComponent(selectedComponent === comp.id ? null : comp.id),
|
|
10265
|
+
disabled: submitted,
|
|
10266
|
+
children: [
|
|
10267
|
+
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: [
|
|
10268
|
+
comp.iconEmoji,
|
|
10269
|
+
" "
|
|
10270
|
+
] }) : null,
|
|
10271
|
+
comp.label
|
|
10272
|
+
]
|
|
10273
|
+
},
|
|
10274
|
+
comp.id
|
|
10275
|
+
)),
|
|
10276
|
+
availableComponents.length === 0 && !submitted && /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-[var(--color-muted-foreground)]", children: t("builder.allPlaced") })
|
|
10277
|
+
] })
|
|
10278
|
+
] }) }),
|
|
10279
|
+
/* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
|
|
10280
|
+
/* @__PURE__ */ jsx(Typography, { variant: "small", weight: "bold", className: "uppercase tracking-wider text-[var(--color-muted-foreground)]", children: t("builder.blueprint") }),
|
|
10281
|
+
/* @__PURE__ */ jsx(VStack, { gap: "sm", children: entity.slots.map((slot) => {
|
|
10282
|
+
const placedComp = placements[slot.id] ? getComponentById(placements[slot.id]) : null;
|
|
10283
|
+
const result = results.find((r) => r.slot.id === slot.id);
|
|
10284
|
+
return /* @__PURE__ */ jsxs(
|
|
10285
|
+
HStack,
|
|
10286
|
+
{
|
|
10287
|
+
gap: "sm",
|
|
10288
|
+
align: "center",
|
|
10289
|
+
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)]"}`,
|
|
10290
|
+
onClick: () => handlePlaceComponent(slot.id),
|
|
10291
|
+
children: [
|
|
10292
|
+
/* @__PURE__ */ jsxs(VStack, { gap: "none", className: "flex-1", children: [
|
|
10293
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body", weight: "medium", children: slot.label }),
|
|
10294
|
+
slot.description && /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-[var(--color-muted-foreground)]", children: slot.description })
|
|
10295
|
+
] }),
|
|
10296
|
+
placedComp ? /* @__PURE__ */ jsxs(HStack, { gap: "xs", align: "center", children: [
|
|
10297
|
+
/* @__PURE__ */ jsxs(Badge, { size: "sm", onClick: () => handleRemoveFromSlot(slot.id), children: [
|
|
10298
|
+
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: [
|
|
10299
|
+
placedComp.iconEmoji,
|
|
10300
|
+
" "
|
|
10301
|
+
] }) : null,
|
|
10302
|
+
placedComp.label
|
|
10303
|
+
] }),
|
|
10304
|
+
result && /* @__PURE__ */ jsx(Icon, { icon: result.correct ? CheckCircle : XCircle, size: "sm", className: result.correct ? "text-green-600" : "text-red-600" })
|
|
10305
|
+
] }) : /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-[var(--color-muted-foreground)]", children: t("builder.empty") })
|
|
10306
|
+
]
|
|
10307
|
+
},
|
|
10308
|
+
slot.id
|
|
10309
|
+
);
|
|
10310
|
+
}) })
|
|
10311
|
+
] }) }),
|
|
10312
|
+
submitted && /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", align: "center", children: [
|
|
10313
|
+
/* @__PURE__ */ jsx(Icon, { icon: allCorrect ? CheckCircle : XCircle, size: "lg", className: allCorrect ? "text-green-600" : "text-red-600" }),
|
|
10314
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body", weight: "bold", children: allCorrect ? entity.successMessage ?? t("builder.success") : entity.failMessage ?? t("builder.incorrect") })
|
|
10315
|
+
] }) }),
|
|
10316
|
+
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 }) }),
|
|
10317
|
+
/* @__PURE__ */ jsxs(HStack, { gap: "sm", justify: "center", children: [
|
|
10318
|
+
!submitted ? /* @__PURE__ */ jsxs(Button, { variant: "primary", onClick: handleSubmit, disabled: !allPlaced, children: [
|
|
10319
|
+
/* @__PURE__ */ jsx(Icon, { icon: Wrench, size: "sm" }),
|
|
10320
|
+
t("builder.build")
|
|
10321
|
+
] }) : !allCorrect ? /* @__PURE__ */ jsx(Button, { variant: "primary", onClick: handleReset, children: t("builder.tryAgain") }) : null,
|
|
10322
|
+
/* @__PURE__ */ jsxs(Button, { variant: "secondary", onClick: handleFullReset, children: [
|
|
10323
|
+
/* @__PURE__ */ jsx(Icon, { icon: RotateCcw, size: "sm" }),
|
|
10324
|
+
t("builder.reset")
|
|
10325
|
+
] })
|
|
10326
|
+
] })
|
|
10221
10327
|
] })
|
|
10222
|
-
|
|
10223
|
-
|
|
10328
|
+
}
|
|
10329
|
+
);
|
|
10224
10330
|
}
|
|
10225
10331
|
BuilderBoard.displayName = "BuilderBoard";
|
|
10226
10332
|
function DebuggerBoard({
|
|
@@ -10231,6 +10337,7 @@ function DebuggerBoard({
|
|
|
10231
10337
|
const { emit } = useEventBus();
|
|
10232
10338
|
const { t } = useTranslate();
|
|
10233
10339
|
const [flaggedLines, setFlaggedLines] = useState(/* @__PURE__ */ new Set());
|
|
10340
|
+
const [headerError, setHeaderError] = useState(false);
|
|
10234
10341
|
const [submitted, setSubmitted] = useState(false);
|
|
10235
10342
|
const [attempts, setAttempts] = useState(0);
|
|
10236
10343
|
const [showHint, setShowHint] = useState(false);
|
|
@@ -10270,73 +10377,85 @@ function DebuggerBoard({
|
|
|
10270
10377
|
setAttempts(0);
|
|
10271
10378
|
setShowHint(false);
|
|
10272
10379
|
};
|
|
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"
|
|
10380
|
+
return /* @__PURE__ */ jsx(
|
|
10381
|
+
Box,
|
|
10382
|
+
{
|
|
10383
|
+
className,
|
|
10384
|
+
style: {
|
|
10385
|
+
backgroundImage: entity.theme?.background ? `url(${entity.theme.background})` : void 0,
|
|
10386
|
+
backgroundSize: "cover",
|
|
10387
|
+
backgroundPosition: "center"
|
|
10388
|
+
},
|
|
10389
|
+
children: /* @__PURE__ */ jsxs(VStack, { gap: "lg", className: "p-4", children: [
|
|
10390
|
+
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,
|
|
10391
|
+
/* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
|
|
10392
|
+
/* @__PURE__ */ jsxs(HStack, { gap: "xs", align: "center", children: [
|
|
10393
|
+
/* @__PURE__ */ jsx(Icon, { icon: Bug, size: "sm" }),
|
|
10394
|
+
/* @__PURE__ */ jsx(Typography, { variant: "h4", weight: "bold", children: entity.title })
|
|
10395
|
+
] }),
|
|
10396
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body", children: entity.description }),
|
|
10397
|
+
/* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-[var(--color-muted-foreground)]", children: t("debugger.findBugs", { count: String(entity.bugCount) }) })
|
|
10398
|
+
] }) }),
|
|
10399
|
+
/* @__PURE__ */ jsx(Card, { className: "p-0 overflow-hidden", children: /* @__PURE__ */ jsx(VStack, { gap: "none", children: entity.lines.map((line, i) => {
|
|
10400
|
+
const isFlagged = flaggedLines.has(line.id);
|
|
10401
|
+
let lineStyle = "";
|
|
10402
|
+
if (submitted) {
|
|
10403
|
+
if (line.isBug && isFlagged) lineStyle = "bg-green-50 dark:bg-green-950";
|
|
10404
|
+
else if (line.isBug && !isFlagged) lineStyle = "bg-yellow-50 dark:bg-yellow-950";
|
|
10405
|
+
else if (!line.isBug && isFlagged) lineStyle = "bg-red-50 dark:bg-red-950";
|
|
10406
|
+
} else if (isFlagged) {
|
|
10407
|
+
lineStyle = "bg-red-50 dark:bg-red-950";
|
|
10320
10408
|
}
|
|
10321
|
-
|
|
10322
|
-
|
|
10323
|
-
|
|
10324
|
-
|
|
10409
|
+
return /* @__PURE__ */ jsxs(
|
|
10410
|
+
HStack,
|
|
10411
|
+
{
|
|
10412
|
+
gap: "none",
|
|
10413
|
+
align: "stretch",
|
|
10414
|
+
className: `border-b border-[var(--color-border)] cursor-pointer hover:bg-[var(--color-muted)] ${lineStyle}`,
|
|
10415
|
+
onClick: () => toggleLine(line.id),
|
|
10416
|
+
children: [
|
|
10417
|
+
/* @__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 }) }),
|
|
10418
|
+
/* @__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 }) }),
|
|
10419
|
+
/* @__PURE__ */ jsxs(Box, { className: "w-8 flex-shrink-0 flex items-center justify-center", children: [
|
|
10420
|
+
isFlagged && /* @__PURE__ */ jsx(Icon, { icon: Bug, size: "xs", className: "text-red-600" }),
|
|
10421
|
+
submitted && line.isBug && !isFlagged && /* @__PURE__ */ jsx(Icon, { icon: Bug, size: "xs", className: "text-yellow-600" })
|
|
10422
|
+
] })
|
|
10423
|
+
]
|
|
10424
|
+
},
|
|
10425
|
+
line.id
|
|
10426
|
+
);
|
|
10427
|
+
}) }) }),
|
|
10428
|
+
submitted && /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
|
|
10429
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body", weight: "bold", children: allCorrect ? entity.successMessage ?? t("debugger.allFound") : `${correctFlags.length}/${bugLines.length} ${t("debugger.bugsFound")}` }),
|
|
10430
|
+
bugLines.map((line) => /* @__PURE__ */ jsxs(HStack, { gap: "xs", align: "start", children: [
|
|
10431
|
+
/* @__PURE__ */ jsx(
|
|
10432
|
+
Icon,
|
|
10433
|
+
{
|
|
10434
|
+
icon: flaggedLines.has(line.id) ? CheckCircle : XCircle,
|
|
10435
|
+
size: "xs",
|
|
10436
|
+
className: flaggedLines.has(line.id) ? "text-green-600 mt-0.5" : "text-yellow-600 mt-0.5"
|
|
10437
|
+
}
|
|
10438
|
+
),
|
|
10439
|
+
/* @__PURE__ */ jsxs(VStack, { gap: "none", children: [
|
|
10440
|
+
/* @__PURE__ */ jsx(Typography, { variant: "caption", weight: "bold", className: "font-mono", children: line.content.trim() }),
|
|
10441
|
+
line.explanation && /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-[var(--color-muted-foreground)]", children: line.explanation })
|
|
10442
|
+
] })
|
|
10443
|
+
] }, line.id))
|
|
10444
|
+
] }) }),
|
|
10445
|
+
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 }) }),
|
|
10446
|
+
/* @__PURE__ */ jsxs(HStack, { gap: "sm", justify: "center", children: [
|
|
10447
|
+
!submitted ? /* @__PURE__ */ jsxs(Button, { variant: "primary", onClick: handleSubmit, disabled: flaggedLines.size === 0, children: [
|
|
10448
|
+
/* @__PURE__ */ jsx(Icon, { icon: Send, size: "sm" }),
|
|
10449
|
+
t("debugger.submit")
|
|
10450
|
+
] }) : !allCorrect ? /* @__PURE__ */ jsx(Button, { variant: "primary", onClick: handleReset, children: t("debugger.tryAgain") }) : null,
|
|
10451
|
+
/* @__PURE__ */ jsxs(Button, { variant: "secondary", onClick: handleFullReset, children: [
|
|
10452
|
+
/* @__PURE__ */ jsx(Icon, { icon: RotateCcw, size: "sm" }),
|
|
10453
|
+
t("debugger.reset")
|
|
10454
|
+
] })
|
|
10325
10455
|
] })
|
|
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
10456
|
] })
|
|
10338
|
-
|
|
10339
|
-
|
|
10457
|
+
}
|
|
10458
|
+
);
|
|
10340
10459
|
}
|
|
10341
10460
|
DebuggerBoard.displayName = "DebuggerBoard";
|
|
10342
10461
|
function getOpponentAction(strategy, actions, history) {
|
|
@@ -10362,6 +10481,7 @@ function NegotiatorBoard({
|
|
|
10362
10481
|
const { emit } = useEventBus();
|
|
10363
10482
|
const { t } = useTranslate();
|
|
10364
10483
|
const [history, setHistory] = useState([]);
|
|
10484
|
+
const [headerError, setHeaderError] = useState(false);
|
|
10365
10485
|
const [showHint, setShowHint] = useState(false);
|
|
10366
10486
|
const currentRound = history.length;
|
|
10367
10487
|
const isComplete = currentRound >= entity.totalRounds;
|
|
@@ -10398,76 +10518,88 @@ function NegotiatorBoard({
|
|
|
10398
10518
|
setShowHint(false);
|
|
10399
10519
|
};
|
|
10400
10520
|
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
|
|
10521
|
+
return /* @__PURE__ */ jsx(
|
|
10522
|
+
Box,
|
|
10523
|
+
{
|
|
10524
|
+
className,
|
|
10525
|
+
style: {
|
|
10526
|
+
backgroundImage: entity.theme?.background ? `url(${entity.theme.background})` : void 0,
|
|
10527
|
+
backgroundSize: "cover",
|
|
10528
|
+
backgroundPosition: "center"
|
|
10529
|
+
},
|
|
10530
|
+
children: /* @__PURE__ */ jsxs(VStack, { gap: "lg", className: "p-4", children: [
|
|
10531
|
+
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,
|
|
10532
|
+
/* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
|
|
10533
|
+
/* @__PURE__ */ jsx(Typography, { variant: "h4", weight: "bold", children: entity.title }),
|
|
10534
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body", children: entity.description }),
|
|
10535
|
+
/* @__PURE__ */ jsxs(HStack, { gap: "md", children: [
|
|
10536
|
+
/* @__PURE__ */ jsx(Badge, { size: "sm", children: t("negotiator.round", { current: String(currentRound), total: String(entity.totalRounds) }) }),
|
|
10537
|
+
/* @__PURE__ */ jsxs(Badge, { size: "sm", children: [
|
|
10538
|
+
t("negotiator.target"),
|
|
10539
|
+
": ",
|
|
10540
|
+
entity.targetScore
|
|
10541
|
+
] })
|
|
10542
|
+
] })
|
|
10543
|
+
] }) }),
|
|
10544
|
+
/* @__PURE__ */ jsxs(HStack, { gap: "md", justify: "center", children: [
|
|
10545
|
+
/* @__PURE__ */ jsx(Card, { className: "p-4 flex-1 text-center", children: /* @__PURE__ */ jsxs(VStack, { gap: "xs", align: "center", children: [
|
|
10546
|
+
/* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-[var(--color-muted-foreground)]", children: t("negotiator.you") }),
|
|
10547
|
+
/* @__PURE__ */ jsx(Typography, { variant: "h3", weight: "bold", children: playerTotal })
|
|
10548
|
+
] }) }),
|
|
10549
|
+
/* @__PURE__ */ jsx(Card, { className: "p-4 flex-1 text-center", children: /* @__PURE__ */ jsxs(VStack, { gap: "xs", align: "center", children: [
|
|
10550
|
+
/* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-[var(--color-muted-foreground)]", children: t("negotiator.opponent") }),
|
|
10551
|
+
/* @__PURE__ */ jsx(Typography, { variant: "h3", weight: "bold", children: opponentTotal })
|
|
10552
|
+
] }) })
|
|
10450
10553
|
] }),
|
|
10451
|
-
/* @__PURE__ */
|
|
10452
|
-
"
|
|
10453
|
-
|
|
10454
|
-
|
|
10455
|
-
|
|
10456
|
-
|
|
10457
|
-
|
|
10458
|
-
|
|
10459
|
-
|
|
10460
|
-
|
|
10461
|
-
|
|
10462
|
-
|
|
10463
|
-
|
|
10464
|
-
|
|
10465
|
-
|
|
10554
|
+
!isComplete && /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
|
|
10555
|
+
/* @__PURE__ */ jsx(Typography, { variant: "small", weight: "bold", className: "uppercase tracking-wider text-[var(--color-muted-foreground)]", children: t("negotiator.chooseAction") }),
|
|
10556
|
+
/* @__PURE__ */ jsx(HStack, { gap: "sm", justify: "center", className: "flex-wrap", children: entity.actions.map((action) => /* @__PURE__ */ jsx(
|
|
10557
|
+
Button,
|
|
10558
|
+
{
|
|
10559
|
+
variant: "primary",
|
|
10560
|
+
onClick: () => handleAction(action.id),
|
|
10561
|
+
children: action.label
|
|
10562
|
+
},
|
|
10563
|
+
action.id
|
|
10564
|
+
)) })
|
|
10565
|
+
] }) }),
|
|
10566
|
+
history.length > 0 && /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
|
|
10567
|
+
/* @__PURE__ */ jsx(Typography, { variant: "small", weight: "bold", className: "uppercase tracking-wider text-[var(--color-muted-foreground)]", children: t("negotiator.history") }),
|
|
10568
|
+
history.map((round) => /* @__PURE__ */ jsxs(HStack, { gap: "sm", align: "center", className: "text-sm", children: [
|
|
10569
|
+
/* @__PURE__ */ jsxs(Badge, { size: "sm", children: [
|
|
10570
|
+
"R",
|
|
10571
|
+
round.round
|
|
10572
|
+
] }),
|
|
10573
|
+
/* @__PURE__ */ jsx(Typography, { variant: "caption", children: getActionLabel(round.playerAction) }),
|
|
10574
|
+
/* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-[var(--color-muted-foreground)]", children: "vs" }),
|
|
10575
|
+
/* @__PURE__ */ jsx(Typography, { variant: "caption", children: getActionLabel(round.opponentAction) }),
|
|
10576
|
+
/* @__PURE__ */ jsx(Icon, { icon: ArrowRight, size: "xs" }),
|
|
10577
|
+
/* @__PURE__ */ jsxs(Typography, { variant: "caption", weight: "bold", className: "text-green-600", children: [
|
|
10578
|
+
"+",
|
|
10579
|
+
round.playerPayoff
|
|
10580
|
+
] }),
|
|
10581
|
+
/* @__PURE__ */ jsxs(Typography, { variant: "caption", className: "text-[var(--color-muted-foreground)]", children: [
|
|
10582
|
+
"/ +",
|
|
10583
|
+
round.opponentPayoff
|
|
10584
|
+
] })
|
|
10585
|
+
] }, round.round))
|
|
10586
|
+
] }) }),
|
|
10587
|
+
isComplete && /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", align: "center", children: [
|
|
10588
|
+
/* @__PURE__ */ jsx(Icon, { icon: CheckCircle, size: "lg", className: won ? "text-green-600" : "text-red-600" }),
|
|
10589
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body", weight: "bold", children: won ? entity.successMessage ?? t("negotiator.success") : entity.failMessage ?? t("negotiator.failed") }),
|
|
10590
|
+
/* @__PURE__ */ jsxs(Typography, { variant: "caption", className: "text-[var(--color-muted-foreground)]", children: [
|
|
10591
|
+
t("negotiator.finalScore"),
|
|
10592
|
+
": ",
|
|
10593
|
+
playerTotal,
|
|
10594
|
+
"/",
|
|
10595
|
+
entity.targetScore
|
|
10596
|
+
] })
|
|
10597
|
+
] }) }),
|
|
10598
|
+
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 }) }),
|
|
10599
|
+
isComplete && !won && /* @__PURE__ */ jsx(HStack, { justify: "center", children: /* @__PURE__ */ jsx(Button, { variant: "primary", onClick: handleReset, children: t("negotiator.playAgain") }) })
|
|
10466
10600
|
] })
|
|
10467
|
-
|
|
10468
|
-
|
|
10469
|
-
isComplete && !won && /* @__PURE__ */ jsx(HStack, { justify: "center", children: /* @__PURE__ */ jsx(Button, { variant: "primary", onClick: handleReset, children: t("negotiator.playAgain") }) })
|
|
10470
|
-
] }) });
|
|
10601
|
+
}
|
|
10602
|
+
);
|
|
10471
10603
|
}
|
|
10472
10604
|
NegotiatorBoard.displayName = "NegotiatorBoard";
|
|
10473
10605
|
function SimulationCanvas({
|
|
@@ -11289,10 +11421,10 @@ var Chart = ({
|
|
|
11289
11421
|
const handleAction = useCallback(
|
|
11290
11422
|
(action) => {
|
|
11291
11423
|
if (action.event) {
|
|
11292
|
-
eventBus.emit(`UI:${action.event}`, {
|
|
11424
|
+
eventBus.emit(`UI:${action.event}`, {});
|
|
11293
11425
|
}
|
|
11294
11426
|
},
|
|
11295
|
-
[eventBus
|
|
11427
|
+
[eventBus]
|
|
11296
11428
|
);
|
|
11297
11429
|
const normalizedData = useMemo(() => {
|
|
11298
11430
|
if (simpleData) return simpleData;
|
|
@@ -11392,10 +11524,10 @@ var Meter = ({
|
|
|
11392
11524
|
const handleAction = useCallback(
|
|
11393
11525
|
(action) => {
|
|
11394
11526
|
if (action.event) {
|
|
11395
|
-
eventBus.emit(`UI:${action.event}`, {
|
|
11527
|
+
eventBus.emit(`UI:${action.event}`, { value });
|
|
11396
11528
|
}
|
|
11397
11529
|
},
|
|
11398
|
-
[eventBus,
|
|
11530
|
+
[eventBus, value]
|
|
11399
11531
|
);
|
|
11400
11532
|
const percentage = useMemo(() => {
|
|
11401
11533
|
const range = max - min;
|
|
@@ -11580,7 +11712,6 @@ var STATUS_STYLES3 = {
|
|
|
11580
11712
|
var Timeline = ({
|
|
11581
11713
|
title,
|
|
11582
11714
|
items: propItems,
|
|
11583
|
-
data,
|
|
11584
11715
|
fields,
|
|
11585
11716
|
itemActions,
|
|
11586
11717
|
entity,
|
|
@@ -11588,19 +11719,12 @@ var Timeline = ({
|
|
|
11588
11719
|
error,
|
|
11589
11720
|
className
|
|
11590
11721
|
}) => {
|
|
11591
|
-
const
|
|
11592
|
-
const
|
|
11593
|
-
(action, item) => {
|
|
11594
|
-
if (action.event) {
|
|
11595
|
-
eventBus.emit(`UI:${action.event}`, { entity, row: item });
|
|
11596
|
-
}
|
|
11597
|
-
},
|
|
11598
|
-
[eventBus, entity]
|
|
11599
|
-
);
|
|
11722
|
+
const { t } = useTranslate();
|
|
11723
|
+
const entityData = Array.isArray(entity) ? entity : [];
|
|
11600
11724
|
const items = React42__default.useMemo(() => {
|
|
11601
11725
|
if (propItems) return propItems;
|
|
11602
|
-
if (
|
|
11603
|
-
return
|
|
11726
|
+
if (entityData.length === 0) return [];
|
|
11727
|
+
return entityData.map((record, idx) => {
|
|
11604
11728
|
const titleField = fields?.[0] || "title";
|
|
11605
11729
|
const descField = fields?.[1] || "description";
|
|
11606
11730
|
const dateField = fields?.find(
|
|
@@ -11617,7 +11741,7 @@ var Timeline = ({
|
|
|
11617
11741
|
status: record[statusField] || "pending"
|
|
11618
11742
|
};
|
|
11619
11743
|
});
|
|
11620
|
-
}, [propItems,
|
|
11744
|
+
}, [propItems, entityData, fields]);
|
|
11621
11745
|
if (isLoading) {
|
|
11622
11746
|
return /* @__PURE__ */ jsx(LoadingState, { message: "Loading timeline...", className });
|
|
11623
11747
|
}
|
|
@@ -11677,12 +11801,12 @@ var Timeline = ({
|
|
|
11677
11801
|
item.description && /* @__PURE__ */ jsx(Typography, { variant: "small", color: "secondary", children: item.description }),
|
|
11678
11802
|
item.tags && item.tags.length > 0 && /* @__PURE__ */ jsx(HStack, { gap: "xs", wrap: true, children: item.tags.map((tag, tagIdx) => /* @__PURE__ */ jsx(Badge, { variant: "default", children: tag }, tagIdx)) }),
|
|
11679
11803
|
itemActions && itemActions.length > 0 && /* @__PURE__ */ jsx(HStack, { gap: "xs", className: "mt-1", children: itemActions.map((action, actionIdx) => /* @__PURE__ */ jsx(
|
|
11680
|
-
|
|
11804
|
+
Box,
|
|
11681
11805
|
{
|
|
11682
|
-
|
|
11806
|
+
action: action.event,
|
|
11807
|
+
actionPayload: { row: item },
|
|
11683
11808
|
className: "cursor-pointer hover:opacity-80 transition-opacity",
|
|
11684
|
-
|
|
11685
|
-
children: action.label
|
|
11809
|
+
children: /* @__PURE__ */ jsx(Badge, { variant: "default", children: action.label })
|
|
11686
11810
|
},
|
|
11687
11811
|
actionIdx
|
|
11688
11812
|
)) })
|
|
@@ -11707,11 +11831,10 @@ var ASPECT_CLASSES = {
|
|
|
11707
11831
|
var MediaGallery = ({
|
|
11708
11832
|
title,
|
|
11709
11833
|
items: propItems,
|
|
11710
|
-
data,
|
|
11711
11834
|
columns = 3,
|
|
11712
11835
|
selectable = false,
|
|
11713
11836
|
selectedItems = [],
|
|
11714
|
-
|
|
11837
|
+
selectionEvent = "SELECTION_CHANGE",
|
|
11715
11838
|
showUpload = false,
|
|
11716
11839
|
actions,
|
|
11717
11840
|
aspectRatio = "square",
|
|
@@ -11721,42 +11844,35 @@ var MediaGallery = ({
|
|
|
11721
11844
|
className
|
|
11722
11845
|
}) => {
|
|
11723
11846
|
const eventBus = useEventBus();
|
|
11847
|
+
const { t } = useTranslate();
|
|
11724
11848
|
const [lightboxItem, setLightboxItem] = useState(null);
|
|
11725
|
-
const
|
|
11726
|
-
|
|
11727
|
-
if (action.event) {
|
|
11728
|
-
eventBus.emit(`UI:${action.event}`, { entity });
|
|
11729
|
-
}
|
|
11730
|
-
},
|
|
11731
|
-
[eventBus, entity]
|
|
11732
|
-
);
|
|
11849
|
+
const closeLightbox = useCallback(() => setLightboxItem(null), []);
|
|
11850
|
+
useEventListener("UI:LIGHTBOX_CLOSE", closeLightbox);
|
|
11733
11851
|
const handleItemClick = useCallback(
|
|
11734
11852
|
(item) => {
|
|
11735
11853
|
if (selectable) {
|
|
11736
11854
|
const isSelected = selectedItems.includes(item.id);
|
|
11737
11855
|
const newSelection = isSelected ? selectedItems.filter((id) => id !== item.id) : [...selectedItems, item.id];
|
|
11738
|
-
|
|
11856
|
+
eventBus.emit(`UI:${selectionEvent}`, { selection: newSelection });
|
|
11739
11857
|
} else {
|
|
11740
11858
|
setLightboxItem(item);
|
|
11741
11859
|
}
|
|
11742
|
-
eventBus.emit("UI:MEDIA_SELECT", {
|
|
11860
|
+
eventBus.emit("UI:MEDIA_SELECT", { row: item });
|
|
11743
11861
|
},
|
|
11744
|
-
[selectable, selectedItems,
|
|
11862
|
+
[selectable, selectedItems, selectionEvent, eventBus]
|
|
11745
11863
|
);
|
|
11746
|
-
const
|
|
11747
|
-
eventBus.emit("UI:MEDIA_UPLOAD", { entity });
|
|
11748
|
-
}, [eventBus, entity]);
|
|
11864
|
+
const entityData = Array.isArray(entity) ? entity : [];
|
|
11749
11865
|
const items = React42__default.useMemo(() => {
|
|
11750
11866
|
if (propItems) return propItems;
|
|
11751
|
-
if (
|
|
11752
|
-
return
|
|
11867
|
+
if (entityData.length === 0) return [];
|
|
11868
|
+
return entityData.map((record, idx) => ({
|
|
11753
11869
|
id: String(record.id ?? idx),
|
|
11754
11870
|
src: String(record.src ?? record.url ?? record.image ?? ""),
|
|
11755
11871
|
alt: record.alt ? String(record.alt) : void 0,
|
|
11756
11872
|
thumbnail: record.thumbnail ? String(record.thumbnail) : void 0,
|
|
11757
11873
|
caption: record.caption ? String(record.caption) : record.title ? String(record.title) : void 0
|
|
11758
11874
|
}));
|
|
11759
|
-
}, [propItems,
|
|
11875
|
+
}, [propItems, entityData]);
|
|
11760
11876
|
if (isLoading) {
|
|
11761
11877
|
return /* @__PURE__ */ jsx(LoadingState, { message: "Loading media...", className });
|
|
11762
11878
|
}
|
|
@@ -11792,17 +11908,16 @@ var MediaGallery = ({
|
|
|
11792
11908
|
variant: "secondary",
|
|
11793
11909
|
size: "sm",
|
|
11794
11910
|
icon: Upload,
|
|
11795
|
-
|
|
11911
|
+
action: "MEDIA_UPLOAD",
|
|
11796
11912
|
children: "Upload"
|
|
11797
11913
|
}
|
|
11798
11914
|
),
|
|
11799
11915
|
actions?.map((action, idx) => /* @__PURE__ */ jsx(
|
|
11800
|
-
|
|
11916
|
+
Box,
|
|
11801
11917
|
{
|
|
11802
|
-
|
|
11918
|
+
action: action.event,
|
|
11803
11919
|
className: "cursor-pointer hover:opacity-80 transition-opacity",
|
|
11804
|
-
|
|
11805
|
-
children: action.label
|
|
11920
|
+
children: /* @__PURE__ */ jsx(Badge, { variant: "default", children: action.label })
|
|
11806
11921
|
},
|
|
11807
11922
|
idx
|
|
11808
11923
|
))
|
|
@@ -11872,7 +11987,7 @@ var MediaGallery = ({
|
|
|
11872
11987
|
Box,
|
|
11873
11988
|
{
|
|
11874
11989
|
className: "fixed inset-0 z-50 bg-[var(--color-background)]/80 backdrop-blur-sm flex items-center justify-center",
|
|
11875
|
-
|
|
11990
|
+
action: "LIGHTBOX_CLOSE",
|
|
11876
11991
|
children: /* @__PURE__ */ jsxs(
|
|
11877
11992
|
VStack,
|
|
11878
11993
|
{
|
|
@@ -11887,7 +12002,7 @@ var MediaGallery = ({
|
|
|
11887
12002
|
variant: "ghost",
|
|
11888
12003
|
size: "sm",
|
|
11889
12004
|
icon: X,
|
|
11890
|
-
|
|
12005
|
+
action: "LIGHTBOX_CLOSE",
|
|
11891
12006
|
className: "text-white hover:bg-white/20"
|
|
11892
12007
|
}
|
|
11893
12008
|
) }),
|
|
@@ -12004,15 +12119,15 @@ var SignaturePad = ({
|
|
|
12004
12119
|
setHasSignature(false);
|
|
12005
12120
|
onChange?.(null);
|
|
12006
12121
|
if (clearEvent) {
|
|
12007
|
-
eventBus.emit(`UI:${clearEvent}`, {
|
|
12122
|
+
eventBus.emit(`UI:${clearEvent}`, {});
|
|
12008
12123
|
}
|
|
12009
|
-
}, [onChange, clearEvent, eventBus
|
|
12124
|
+
}, [onChange, clearEvent, eventBus]);
|
|
12010
12125
|
const confirmSignature = useCallback(() => {
|
|
12011
12126
|
const dataUrl = canvasRef.current?.toDataURL("image/png") ?? null;
|
|
12012
12127
|
if (signEvent) {
|
|
12013
|
-
eventBus.emit(`UI:${signEvent}`, {
|
|
12128
|
+
eventBus.emit(`UI:${signEvent}`, { signature: dataUrl });
|
|
12014
12129
|
}
|
|
12015
|
-
}, [signEvent, eventBus
|
|
12130
|
+
}, [signEvent, eventBus]);
|
|
12016
12131
|
if (isLoading) {
|
|
12017
12132
|
return /* @__PURE__ */ jsx(LoadingState, { message: "Loading signature pad...", className });
|
|
12018
12133
|
}
|
|
@@ -12109,34 +12224,34 @@ var DocumentViewer = ({
|
|
|
12109
12224
|
const handleAction = useCallback(
|
|
12110
12225
|
(action) => {
|
|
12111
12226
|
if (action.event) {
|
|
12112
|
-
eventBus.emit(`UI:${action.event}`, {
|
|
12227
|
+
eventBus.emit(`UI:${action.event}`, { page: currentPage });
|
|
12113
12228
|
}
|
|
12114
12229
|
},
|
|
12115
|
-
[eventBus,
|
|
12230
|
+
[eventBus, currentPage]
|
|
12116
12231
|
);
|
|
12117
12232
|
const handleDownload = useCallback(() => {
|
|
12118
12233
|
const downloadSrc = documents?.[activeDocIndex]?.src ?? src;
|
|
12119
12234
|
if (downloadSrc) {
|
|
12120
|
-
eventBus.emit("UI:DOCUMENT_DOWNLOAD", {
|
|
12235
|
+
eventBus.emit("UI:DOCUMENT_DOWNLOAD", { src: downloadSrc });
|
|
12121
12236
|
window.open(downloadSrc, "_blank");
|
|
12122
12237
|
}
|
|
12123
|
-
}, [documents, activeDocIndex, src, eventBus
|
|
12238
|
+
}, [documents, activeDocIndex, src, eventBus]);
|
|
12124
12239
|
const handlePrint = useCallback(() => {
|
|
12125
|
-
eventBus.emit("UI:DOCUMENT_PRINT", {
|
|
12240
|
+
eventBus.emit("UI:DOCUMENT_PRINT", {});
|
|
12126
12241
|
window.print();
|
|
12127
|
-
}, [eventBus
|
|
12242
|
+
}, [eventBus]);
|
|
12128
12243
|
const handleZoomIn = useCallback(() => setZoom((z) => Math.min(z + 25, 200)), []);
|
|
12129
12244
|
const handleZoomOut = useCallback(() => setZoom((z) => Math.max(z - 25, 50)), []);
|
|
12130
12245
|
const handlePagePrev = useCallback(() => {
|
|
12131
12246
|
setCurrentPage((p2) => Math.max(p2 - 1, 1));
|
|
12132
|
-
eventBus.emit("UI:DOCUMENT_PAGE_CHANGE", {
|
|
12133
|
-
}, [eventBus,
|
|
12247
|
+
eventBus.emit("UI:DOCUMENT_PAGE_CHANGE", { page: currentPage - 1 });
|
|
12248
|
+
}, [eventBus, currentPage]);
|
|
12134
12249
|
const handlePageNext = useCallback(() => {
|
|
12135
12250
|
if (totalPages) {
|
|
12136
12251
|
setCurrentPage((p2) => Math.min(p2 + 1, totalPages));
|
|
12137
|
-
eventBus.emit("UI:DOCUMENT_PAGE_CHANGE", {
|
|
12252
|
+
eventBus.emit("UI:DOCUMENT_PAGE_CHANGE", { page: currentPage + 1 });
|
|
12138
12253
|
}
|
|
12139
|
-
}, [totalPages, eventBus,
|
|
12254
|
+
}, [totalPages, eventBus, currentPage]);
|
|
12140
12255
|
if (isLoading) {
|
|
12141
12256
|
return /* @__PURE__ */ jsx(LoadingState, { message: "Loading document...", className });
|
|
12142
12257
|
}
|
|
@@ -12310,19 +12425,19 @@ var GraphCanvas = ({
|
|
|
12310
12425
|
const handleAction = useCallback(
|
|
12311
12426
|
(action) => {
|
|
12312
12427
|
if (action.event) {
|
|
12313
|
-
eventBus.emit(`UI:${action.event}`, {
|
|
12428
|
+
eventBus.emit(`UI:${action.event}`, {});
|
|
12314
12429
|
}
|
|
12315
12430
|
},
|
|
12316
|
-
[eventBus
|
|
12431
|
+
[eventBus]
|
|
12317
12432
|
);
|
|
12318
12433
|
const handleNodeClick = useCallback(
|
|
12319
12434
|
(node) => {
|
|
12320
12435
|
if (nodeClickEvent) {
|
|
12321
|
-
eventBus.emit(`UI:${nodeClickEvent}`, {
|
|
12436
|
+
eventBus.emit(`UI:${nodeClickEvent}`, { row: node });
|
|
12322
12437
|
}
|
|
12323
12438
|
onNodeClick?.(node);
|
|
12324
12439
|
},
|
|
12325
|
-
[nodeClickEvent, eventBus,
|
|
12440
|
+
[nodeClickEvent, eventBus, onNodeClick]
|
|
12326
12441
|
);
|
|
12327
12442
|
const groups = useMemo(
|
|
12328
12443
|
() => [...new Set(propNodes.map((n) => n.group).filter(Boolean))],
|
|
@@ -12634,10 +12749,10 @@ var CodeViewer = ({
|
|
|
12634
12749
|
const handleAction = useCallback(
|
|
12635
12750
|
(action) => {
|
|
12636
12751
|
if (action.event) {
|
|
12637
|
-
eventBus.emit(`UI:${action.event}`, {
|
|
12752
|
+
eventBus.emit(`UI:${action.event}`, {});
|
|
12638
12753
|
}
|
|
12639
12754
|
},
|
|
12640
|
-
[eventBus
|
|
12755
|
+
[eventBus]
|
|
12641
12756
|
);
|
|
12642
12757
|
const activeFile = files?.[activeFileIndex];
|
|
12643
12758
|
const activeCode = activeFile?.code ?? code ?? "";
|
|
@@ -12654,11 +12769,11 @@ var CodeViewer = ({
|
|
|
12654
12769
|
try {
|
|
12655
12770
|
await navigator.clipboard.writeText(activeCode);
|
|
12656
12771
|
setCopied(true);
|
|
12657
|
-
eventBus.emit("UI:CODE_COPY", {
|
|
12772
|
+
eventBus.emit("UI:CODE_COPY", { language: activeLanguage });
|
|
12658
12773
|
setTimeout(() => setCopied(false), 2e3);
|
|
12659
12774
|
} catch {
|
|
12660
12775
|
}
|
|
12661
|
-
}, [activeCode, eventBus,
|
|
12776
|
+
}, [activeCode, eventBus, activeLanguage]);
|
|
12662
12777
|
const tabItems = files?.map((file, idx) => ({
|
|
12663
12778
|
id: `file-${idx}`,
|
|
12664
12779
|
label: file.label,
|