@almadar/ui 2.1.11 → 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,17 +1,19 @@
1
- import { useAuthContext } from '../chunk-6OACETQB.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-6OACETQB.js';
1
+ import { useAuthContext } from '../chunk-42WRQA7T.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-42WRQA7T.js';
3
3
  import { DEFAULT_CONFIG, renderStateMachineToDomData, parseContentSegments } from '../chunk-N6DJVKZ6.js';
4
4
  import '../chunk-3HJHHULT.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, EntityDisplayEvents, HealthBar, ScoreDisplay, StateIndicator, Container } from '../chunk-CTNDYHXY.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-CTNDYHXY.js';
7
- import '../chunk-BTXQJGFB.js';
8
- import { useTranslate } from '../chunk-JLEMVREZ.js';
9
- export { EntityDataProvider, I18nProvider, createTranslate, entityDataKeys, parseQueryBinding, useEntity, useEntityDataAdapter, useEntityDetail, useEntityList, useEntityListSuspense, useEntitySuspense, useQuerySingleton, useTranslate } from '../chunk-JLEMVREZ.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, EntityDisplayEvents, HealthBar, ScoreDisplay, StateIndicator, Container } from '../chunk-HWZL7IZG.js';
6
+ export { Accordion, Card2 as ActionCard, Alert, Avatar, Badge, Box, Breadcrumb, Button, ButtonGroup, CalendarGrid, Card, CardBody, CardContent, CardFooter, CardGrid, CardHeader, CardTitle, Center, ChartLegend, Checkbox, CodeBlock, ConditionalWrapper, Container, ControlButton, DataGrid, DataList, DataTable, DateRangeSelector, DayCell, DetailPanel, Divider, Drawer, EmptyState, EntityDisplayEvents, ErrorBoundary, ErrorState, FilterGroup, Flex, FlipCard, FlipContainer, FloatingActionButton, Form, FormField, FormSectionHeader, GraphView, Grid, HStack, Heading, HealthBar, Icon, Input, InputGroup, Label, LawReferenceTooltip, LineChart, LoadingState, MarkdownContent, MasterDetail, Menu, Modal, Overlay, PageHeader, Pagination, Popover, ProgressBar, ProgressDots, 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, TimeSlotCell, Toast, Tooltip, Typography, UISlotComponent, UISlotRenderer, VStack, ViolationAlert, WizardNavigation, WizardProgress, drawSprite } from '../chunk-HWZL7IZG.js';
7
+ import '../chunk-DKQN5FVU.js';
8
+ import { useTranslate } from '../chunk-GOZKH7QW.js';
9
+ export { EntityDataProvider, I18nProvider, createTranslate, entityDataKeys, parseQueryBinding, useEntity, useEntityDataAdapter, useEntityDetail, useEntityList, useEntityListSuspense, useEntitySuspense, useQuerySingleton, useTranslate } from '../chunk-GOZKH7QW.js';
10
10
  import { useEventBus, useEventListener } from '../chunk-YXZM3WCF.js';
11
11
  export { useEmitEvent, useEventBus, useEventListener } from '../chunk-YXZM3WCF.js';
12
- export { DEFAULT_SLOTS, useUISlotManager } from '../chunk-7NEWMNNU.js';
12
+ export { DEFAULT_SLOTS, useUISlotManager } from '../chunk-3JGAROCW.js';
13
13
  import { cn, getNestedValue } from '../chunk-KKCVDUK7.js';
14
14
  export { cn } from '../chunk-KKCVDUK7.js';
15
+ import '../chunk-TSETXL2E.js';
16
+ import '../chunk-K2D5D3WK.js';
15
17
  export { clearEntities, getAllEntities, getByType, getEntity, getSingleton, removeEntity, spawnEntity, updateEntity, updateSingleton } from '../chunk-N7MVUW4R.js';
16
18
  import { __publicField } from '../chunk-PKBMQBKP.js';
17
19
  import * as React from 'react';
@@ -446,7 +448,7 @@ var SidebarNavItem = ({ item, collapsed }) => {
446
448
  )
447
449
  }
448
450
  ),
449
- !collapsed && /* @__PURE__ */ jsx(Typography, { variant: "body", className: "font-medium truncate flex-1 text-left", children: item.label }),
451
+ !collapsed && /* @__PURE__ */ jsx(Typography, { variant: "body", color: isActive ? "inherit" : "primary", className: "font-medium truncate flex-1 text-left", children: item.label }),
450
452
  !collapsed && item.badge !== void 0 && /* @__PURE__ */ jsx(Badge, { variant: "danger", size: "sm", children: item.badge }),
451
453
  collapsed && /* @__PURE__ */ jsx(Box, { className: cn(
452
454
  "absolute left-full ml-2 px-2 py-1 text-xs opacity-0 group-hover:opacity-100",
@@ -520,13 +522,7 @@ var Sidebar = ({
520
522
  ),
521
523
  onClick: handleLogoClick,
522
524
  children: [
523
- logo ? typeof logo === "string" ? (
524
- // eslint-disable-next-line almadar/no-raw-dom-elements -- semantic img with src/alt
525
- /* @__PURE__ */ jsx("img", { src: logo, alt: brandName, className: "h-8 w-8" })
526
- ) : logo : logoSrc ? (
527
- // eslint-disable-next-line almadar/no-raw-dom-elements -- semantic img with src/alt
528
- /* @__PURE__ */ jsx("img", { src: logoSrc, alt: brandName, className: "h-8 w-8" })
529
- ) : /* @__PURE__ */ jsx(Box, { className: "h-8 w-8 bg-[var(--color-primary)] flex items-center justify-center rounded-[var(--radius-sm)]", children: /* @__PURE__ */ jsx(Typography, { variant: "small", className: "text-[var(--color-primary-foreground)] font-bold text-sm", children: "K" }) }),
525
+ logo ? typeof logo === "string" ? /* @__PURE__ */ jsx("img", { src: logo, alt: brandName, className: "h-8 w-8" }) : logo : logoSrc ? /* @__PURE__ */ jsx("img", { src: logoSrc, alt: brandName, className: "h-8 w-8" }) : /* @__PURE__ */ jsx(Box, { className: "h-8 w-8 bg-[var(--color-primary)] flex items-center justify-center rounded-[var(--radius-sm)]", children: /* @__PURE__ */ jsx(Typography, { variant: "small", className: "text-[var(--color-primary-foreground)] font-bold text-sm", children: "K" }) }),
530
526
  !collapsed && /* @__PURE__ */ jsx(Typography, { variant: "body", className: "text-xl font-bold text-[var(--color-foreground)]", children: brandName })
531
527
  ]
532
528
  }
@@ -737,109 +733,90 @@ var Table = ({
737
733
  ) }),
738
734
  /* @__PURE__ */ jsx(Card, { children: /* @__PURE__ */ jsx(Box, { className: "overflow-x-auto", children: /* @__PURE__ */ jsxs("table", { className: "w-full", children: [
739
735
  /* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { className: "border-b-[length:var(--border-width)] border-[var(--color-table-border)]", children: [
740
- selectable && // eslint-disable-next-line almadar/no-raw-dom-elements -- native table elements needed
741
- /* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left bg-[var(--color-table-header)]", children: /* @__PURE__ */ jsx(
736
+ selectable && /* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-left bg-[var(--color-table-header)]", children: /* @__PURE__ */ jsx(
742
737
  Checkbox,
743
738
  {
744
739
  checked: allSelected,
745
740
  onChange: (e) => handleSelectAll(e.target.checked)
746
741
  }
747
742
  ) }),
748
- columns.map((column) => (
749
- // eslint-disable-next-line almadar/no-raw-dom-elements -- native table elements needed
750
- /* @__PURE__ */ jsx(
751
- "th",
752
- {
753
- className: cn(
754
- "px-4 py-3 text-left text-xs font-bold text-[var(--color-foreground)] uppercase tracking-wider bg-[var(--color-table-header)]",
755
- sortable && column.sortable && "cursor-pointer hover:bg-[var(--color-table-row-hover)]"
756
- ),
757
- style: { width: column.width },
758
- onClick: () => column.sortable && handleSort(column.key),
759
- children: /* @__PURE__ */ jsxs(HStack, { className: "flex items-center gap-2", children: [
760
- /* @__PURE__ */ jsx(Typography, { variant: "small", weight: "semibold", children: column.label }),
761
- sortable && column.sortable && resolvedSortColumn === column.key && /* @__PURE__ */ jsx(
762
- Icon,
763
- {
764
- icon: resolvedSortDirection === "asc" ? ArrowUp : ArrowDown,
765
- size: "sm"
766
- }
767
- )
768
- ] })
769
- },
770
- column.key
771
- )
743
+ columns.map((column) => /* @__PURE__ */ jsx(
744
+ "th",
745
+ {
746
+ className: cn(
747
+ "px-4 py-3 text-left text-xs font-bold text-[var(--color-foreground)] uppercase tracking-wider bg-[var(--color-table-header)]",
748
+ sortable && column.sortable && "cursor-pointer hover:bg-[var(--color-table-row-hover)]"
749
+ ),
750
+ style: { width: column.width },
751
+ onClick: () => column.sortable && handleSort(column.key),
752
+ children: /* @__PURE__ */ jsxs(HStack, { className: "flex items-center gap-2", children: [
753
+ /* @__PURE__ */ jsx(Typography, { variant: "small", weight: "semibold", children: column.label }),
754
+ sortable && column.sortable && resolvedSortColumn === column.key && /* @__PURE__ */ jsx(
755
+ Icon,
756
+ {
757
+ icon: resolvedSortDirection === "asc" ? ArrowUp : ArrowDown,
758
+ size: "sm"
759
+ }
760
+ )
761
+ ] })
762
+ },
763
+ column.key
772
764
  )),
773
- rowActions && // eslint-disable-next-line almadar/no-raw-dom-elements -- native table elements needed
774
- /* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-right", children: "Actions" })
765
+ rowActions && /* @__PURE__ */ jsx("th", { className: "px-4 py-3 text-right", children: "Actions" })
775
766
  ] }) }),
776
- /* @__PURE__ */ jsx("tbody", { children: loading || isLoading ? (
777
- // eslint-disable-next-line almadar/no-raw-dom-elements -- native table elements needed
778
- /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsx(
779
- "td",
780
- {
781
- colSpan: columns.length + (selectable ? 1 : 0) + (rowActions ? 1 : 0),
782
- className: "px-4 py-8 text-center",
783
- children: /* @__PURE__ */ jsx(Typography, { variant: "body", color: "secondary", children: t("common.loading") })
784
- }
785
- ) })
786
- ) : resolvedData.length === 0 ? (
787
- // eslint-disable-next-line almadar/no-raw-dom-elements -- native table elements needed
788
- /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsx(
789
- "td",
790
- {
791
- colSpan: columns.length + (selectable ? 1 : 0) + (rowActions ? 1 : 0),
792
- className: "px-4 py-8 text-center",
793
- children: /* @__PURE__ */ jsx(Typography, { variant: "body", color: "secondary", children: resolvedEmptyMessage })
794
- }
795
- ) })
796
- ) : resolvedData.map((row, index) => {
767
+ /* @__PURE__ */ jsx("tbody", { children: loading || isLoading ? /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsx(
768
+ "td",
769
+ {
770
+ colSpan: columns.length + (selectable ? 1 : 0) + (rowActions ? 1 : 0),
771
+ className: "px-4 py-8 text-center",
772
+ children: /* @__PURE__ */ jsx(Typography, { variant: "body", color: "secondary", children: t("common.loading") })
773
+ }
774
+ ) }) : resolvedData.length === 0 ? /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsx(
775
+ "td",
776
+ {
777
+ colSpan: columns.length + (selectable ? 1 : 0) + (rowActions ? 1 : 0),
778
+ className: "px-4 py-8 text-center",
779
+ children: /* @__PURE__ */ jsx(Typography, { variant: "body", color: "secondary", children: resolvedEmptyMessage })
780
+ }
781
+ ) }) : resolvedData.map((row, index) => {
797
782
  const rowKey = String(row.id ?? index);
798
783
  const isSelected = selectedRows.includes(rowKey);
799
- return (
800
- // eslint-disable-next-line almadar/no-raw-dom-elements -- native table elements needed
801
- /* @__PURE__ */ jsxs(
802
- "tr",
803
- {
804
- className: cn(
805
- "border-b border-[var(--color-table-border)] last:border-b-0",
806
- "hover:bg-[var(--color-table-row-hover)]",
807
- isSelected && "bg-[var(--color-table-header)] font-medium"
808
- ),
809
- children: [
810
- selectable && // eslint-disable-next-line almadar/no-raw-dom-elements -- native table elements needed
811
- /* @__PURE__ */ jsx("td", { className: "px-4 py-3", children: /* @__PURE__ */ jsx(
812
- Checkbox,
813
- {
814
- checked: isSelected,
815
- onChange: (e) => handleSelectRow(rowKey, e.target.checked)
816
- }
817
- ) }),
818
- columns.map((column) => (
819
- // eslint-disable-next-line almadar/no-raw-dom-elements -- native table elements needed
820
- /* @__PURE__ */ jsx("td", { className: "px-4 py-3", children: column.render ? column.render(row[column.key], row, index) : /* @__PURE__ */ jsx(Typography, { variant: "body", children: row[column.key]?.toString() || "-" }) }, column.key)
821
- )),
822
- rowActions && // eslint-disable-next-line almadar/no-raw-dom-elements -- native table elements needed
823
- /* @__PURE__ */ jsx("td", { className: "px-4 py-3 text-right", children: /* @__PURE__ */ jsx(
824
- Menu$1,
825
- {
826
- trigger: /* @__PURE__ */ jsx(
827
- Button,
828
- {
829
- variant: "ghost",
830
- size: "sm",
831
- icon: MoreVertical,
832
- children: "Actions"
833
- }
834
- ),
835
- items: rowActions(row),
836
- position: "bottom-right"
837
- }
838
- ) })
839
- ]
840
- },
841
- rowKey
842
- )
784
+ return /* @__PURE__ */ jsxs(
785
+ "tr",
786
+ {
787
+ className: cn(
788
+ "border-b border-[var(--color-table-border)] last:border-b-0",
789
+ "hover:bg-[var(--color-table-row-hover)]",
790
+ isSelected && "bg-[var(--color-table-header)] font-medium"
791
+ ),
792
+ children: [
793
+ selectable && /* @__PURE__ */ jsx("td", { className: "px-4 py-3", children: /* @__PURE__ */ jsx(
794
+ Checkbox,
795
+ {
796
+ checked: isSelected,
797
+ onChange: (e) => handleSelectRow(rowKey, e.target.checked)
798
+ }
799
+ ) }),
800
+ columns.map((column) => /* @__PURE__ */ jsx("td", { className: "px-4 py-3", children: column.render ? column.render(row[column.key], row, index) : /* @__PURE__ */ jsx(Typography, { variant: "body", children: row[column.key]?.toString() || "-" }) }, column.key)),
801
+ rowActions && /* @__PURE__ */ jsx("td", { className: "px-4 py-3 text-right", children: /* @__PURE__ */ jsx(
802
+ Menu$1,
803
+ {
804
+ trigger: /* @__PURE__ */ jsx(
805
+ Button,
806
+ {
807
+ variant: "ghost",
808
+ size: "sm",
809
+ icon: MoreVertical,
810
+ children: "Actions"
811
+ }
812
+ ),
813
+ items: rowActions(row),
814
+ position: "bottom-right"
815
+ }
816
+ ) })
817
+ ]
818
+ },
819
+ rowKey
843
820
  );
844
821
  }) })
845
822
  ] }) }) }),
@@ -856,7 +833,7 @@ var Table = ({
856
833
  Table.displayName = "Table";
857
834
  function normalizeFields(fields) {
858
835
  if (!fields) return [];
859
- return fields.map((f) => typeof f === "string" ? f : f.key);
836
+ return fields.map((f) => typeof f === "string" ? f : f.key ?? f.name ?? "");
860
837
  }
861
838
  var STATUS_STYLES = {
862
839
  complete: {
@@ -4550,6 +4527,17 @@ function IsometricCanvas({
4550
4527
  if (isLoading) {
4551
4528
  return /* @__PURE__ */ jsx(LoadingState, { className });
4552
4529
  }
4530
+ if (sortedTiles.length === 0) {
4531
+ return /* @__PURE__ */ jsx(
4532
+ EmptyState,
4533
+ {
4534
+ title: t("canvas.emptyTitle"),
4535
+ message: t("canvas.emptyMessage"),
4536
+ icon: "map",
4537
+ className
4538
+ }
4539
+ );
4540
+ }
4553
4541
  return /* @__PURE__ */ jsxs(
4554
4542
  Box,
4555
4543
  {
@@ -4560,6 +4548,7 @@ function IsometricCanvas({
4560
4548
  "canvas",
4561
4549
  {
4562
4550
  ref: canvasRef,
4551
+ "data-testid": "game-canvas",
4563
4552
  onClick: handleClick,
4564
4553
  onMouseDown: enableCamera ? handleMouseDown : void 0,
4565
4554
  onMouseMove: handleMouseMoveWithCamera,
@@ -4574,6 +4563,27 @@ function IsometricCanvas({
4574
4563
  }
4575
4564
  }
4576
4565
  ),
4566
+ process.env.NODE_ENV !== "production" && /* @__PURE__ */ jsxs("div", { "data-game-actions": "", className: "sr-only", "aria-hidden": "true", children: [
4567
+ tileClickEvent && /* @__PURE__ */ jsx(
4568
+ "button",
4569
+ {
4570
+ "data-event": tileClickEvent,
4571
+ "data-x": "0",
4572
+ "data-y": "0",
4573
+ onClick: () => eventBus.emit(`UI:${tileClickEvent}`, { x: 0, y: 0 }),
4574
+ children: tileClickEvent
4575
+ }
4576
+ ),
4577
+ unitClickEvent && units && units.length > 0 && /* @__PURE__ */ jsx(
4578
+ "button",
4579
+ {
4580
+ "data-event": unitClickEvent,
4581
+ "data-unit-id": units[0].id,
4582
+ onClick: () => eventBus.emit(`UI:${unitClickEvent}`, { unitId: units[0].id }),
4583
+ children: unitClickEvent
4584
+ }
4585
+ )
4586
+ ] }),
4577
4587
  showMinimap && /* @__PURE__ */ jsx(
4578
4588
  "canvas",
4579
4589
  {
@@ -6734,7 +6744,8 @@ function GameHud({
6734
6744
  className,
6735
6745
  transparent = true
6736
6746
  }) {
6737
- const stats = propStats ?? items ?? (elements ? convertElementsToStats(elements) : []);
6747
+ const rawStats = propStats ?? items ?? (elements && Array.isArray(elements) ? convertElementsToStats(elements) : []);
6748
+ const stats = Array.isArray(rawStats) ? rawStats : [];
6738
6749
  const position = propPosition ?? "corners";
6739
6750
  if (position === "corners") {
6740
6751
  const leftStats = stats.slice(0, Math.ceil(stats.length / 2));
@@ -7004,10 +7015,13 @@ function InventoryPanel({
7004
7015
  const eventBus = useEventBus();
7005
7016
  const [hoveredSlot, setHoveredSlot] = useState(null);
7006
7017
  const [tooltipPosition, setTooltipPosition] = useState({ x: 0, y: 0 });
7007
- const slotArray = Array.from({ length: slots }, (_, index) => {
7008
- return items[index] ?? null;
7018
+ const safeItems = Array.isArray(items) ? items : [];
7019
+ const safeSlots = typeof slots === "number" && slots > 0 ? slots : 0;
7020
+ const safeColumns = typeof columns === "number" && columns > 0 ? columns : 1;
7021
+ const slotArray = Array.from({ length: safeSlots }, (_, index) => {
7022
+ return safeItems[index] ?? null;
7009
7023
  });
7010
- const rows = Math.ceil(slots / columns);
7024
+ const rows = Math.ceil(safeSlots / safeColumns);
7011
7025
  const handleSlotClick = useCallback((index) => {
7012
7026
  if (selectSlotEvent) eventBus.emit(`UI:${selectSlotEvent}`, { index });
7013
7027
  onSelectSlot?.(index);
@@ -7040,7 +7054,7 @@ function InventoryPanel({
7040
7054
  break;
7041
7055
  case "ArrowRight":
7042
7056
  e.preventDefault();
7043
- onSelectSlot?.(Math.min(index + 1, slots - 1));
7057
+ onSelectSlot?.(Math.min(index + 1, safeSlots - 1));
7044
7058
  break;
7045
7059
  case "ArrowLeft":
7046
7060
  e.preventDefault();
@@ -7048,14 +7062,14 @@ function InventoryPanel({
7048
7062
  break;
7049
7063
  case "ArrowDown":
7050
7064
  e.preventDefault();
7051
- onSelectSlot?.(Math.min(index + columns, slots - 1));
7065
+ onSelectSlot?.(Math.min(index + safeColumns, safeSlots - 1));
7052
7066
  break;
7053
7067
  case "ArrowUp":
7054
7068
  e.preventDefault();
7055
- onSelectSlot?.(Math.max(index - columns, 0));
7069
+ onSelectSlot?.(Math.max(index - safeColumns, 0));
7056
7070
  break;
7057
7071
  }
7058
- }, [slotArray, onUseItem, onDropItem, onSelectSlot, columns, slots, useItemEvent, dropItemEvent, eventBus]);
7072
+ }, [slotArray, onUseItem, onDropItem, onSelectSlot, safeColumns, safeSlots, useItemEvent, dropItemEvent, eventBus]);
7059
7073
  const handleMouseEnter = useCallback((e, index) => {
7060
7074
  if (showTooltips && slotArray[index]) {
7061
7075
  setHoveredSlot(index);
@@ -7075,7 +7089,7 @@ function InventoryPanel({
7075
7089
  {
7076
7090
  className: "grid gap-1 bg-gray-900 p-2 rounded-lg border border-gray-700",
7077
7091
  style: {
7078
- gridTemplateColumns: `repeat(${columns}, ${slotSize}px)`,
7092
+ gridTemplateColumns: `repeat(${safeColumns}, ${slotSize}px)`,
7079
7093
  gridTemplateRows: `repeat(${rows}, ${slotSize}px)`
7080
7094
  },
7081
7095
  children: slotArray.map((item, index) => /* @__PURE__ */ jsx(
@@ -7825,6 +7839,7 @@ function defaultIsInRange(from, to, range) {
7825
7839
  }
7826
7840
  function WorldMapBoard({
7827
7841
  entity,
7842
+ isLoading,
7828
7843
  scale = 0.4,
7829
7844
  unitScale = 2.5,
7830
7845
  allowMoveAllHeroes = false,
@@ -7849,12 +7864,13 @@ function WorldMapBoard({
7849
7864
  className
7850
7865
  }) {
7851
7866
  const eventBus = useEventBus();
7852
- const hexes = entity.hexes;
7853
- const heroes = entity.heroes;
7854
- const features = entity.features ?? [];
7855
- const selectedHeroId = entity.selectedHeroId;
7856
- const assetManifest = entity.assetManifest;
7857
- const backgroundImage = entity.backgroundImage;
7867
+ const resolved = Array.isArray(entity) ? entity[0] : entity;
7868
+ const hexes = resolved?.hexes ?? [];
7869
+ const heroes = resolved?.heroes ?? [];
7870
+ const features = resolved?.features ?? [];
7871
+ const selectedHeroId = resolved?.selectedHeroId;
7872
+ const assetManifest = resolved?.assetManifest;
7873
+ const backgroundImage = resolved?.backgroundImage;
7858
7874
  const [hoveredTile, setHoveredTile] = useState(null);
7859
7875
  const selectedHero = useMemo(
7860
7876
  () => heroes.find((h) => h.id === selectedHeroId) ?? null,
@@ -8010,6 +8026,9 @@ function WorldMapBoard({
8010
8026
  }),
8011
8027
  [hoveredTile, hoveredHex, hoveredHero, selectedHero, validMoves, selectHero, tileToScreen, scale]
8012
8028
  );
8029
+ if (isLoading || !resolved) {
8030
+ return /* @__PURE__ */ jsx(LoadingState, { message: "Loading map..." });
8031
+ }
8013
8032
  return /* @__PURE__ */ jsxs(VStack, { className: cn("world-map-board min-h-screen bg-[var(--color-background)]", className), gap: "none", children: [
8014
8033
  header && header(ctx),
8015
8034
  /* @__PURE__ */ jsxs(HStack, { className: "flex-1 overflow-hidden", gap: "none", children: [
@@ -11243,6 +11262,55 @@ var ToastSlot = ({
11243
11262
  ) });
11244
11263
  };
11245
11264
  ToastSlot.displayName = "ToastSlot";
11265
+ var nextId = 0;
11266
+ function NotifyListener() {
11267
+ const eventBus = useEventBus();
11268
+ const [items, setItems] = useState([]);
11269
+ const [portalRoot, setPortalRoot] = useState(null);
11270
+ useEffect(() => {
11271
+ let root = document.getElementById("ui-notify-portal-root");
11272
+ if (!root) {
11273
+ root = document.createElement("div");
11274
+ root.id = "ui-notify-portal-root";
11275
+ document.body.appendChild(root);
11276
+ }
11277
+ setPortalRoot(root);
11278
+ }, []);
11279
+ const handleDismiss = useCallback((id) => {
11280
+ setItems((prev) => prev.filter((item) => item.id !== id));
11281
+ }, []);
11282
+ useEffect(() => {
11283
+ const unsubscribe = eventBus.on("UI:NOTIFY", (event) => {
11284
+ const payload = event.payload ?? event;
11285
+ const message = typeof payload.message === "string" ? payload.message : "Notification";
11286
+ const severityMap = {
11287
+ success: "success",
11288
+ error: "error",
11289
+ warning: "warning",
11290
+ info: "info"
11291
+ };
11292
+ const variant = severityMap[String(payload.severity)] || "info";
11293
+ const id = ++nextId;
11294
+ setItems((prev) => [...prev, { id, message, variant }]);
11295
+ });
11296
+ return unsubscribe;
11297
+ }, [eventBus]);
11298
+ if (!portalRoot || items.length === 0) return null;
11299
+ return createPortal(
11300
+ /* @__PURE__ */ jsx(Box, { className: "fixed bottom-4 right-4 z-50 pointer-events-auto flex flex-col gap-2", children: items.map((item) => /* @__PURE__ */ jsx(
11301
+ Toast,
11302
+ {
11303
+ variant: item.variant,
11304
+ message: item.message,
11305
+ duration: 5e3,
11306
+ onDismiss: () => handleDismiss(item.id)
11307
+ },
11308
+ item.id
11309
+ )) }),
11310
+ portalRoot
11311
+ );
11312
+ }
11313
+ NotifyListener.displayName = "NotifyListener";
11246
11314
  var CHART_COLORS = [
11247
11315
  "var(--color-primary)",
11248
11316
  "var(--color-success)",
@@ -11363,7 +11431,7 @@ var PieChart = ({ data, height, showValues, donut = false }) => {
11363
11431
  ] }, idx)) })
11364
11432
  ] });
11365
11433
  };
11366
- var LineChart = ({ data, height, showValues, fill = false }) => {
11434
+ var LineChart2 = ({ data, height, showValues, fill = false }) => {
11367
11435
  const maxValue = Math.max(...data.map((d) => d.value), 1);
11368
11436
  const width = 400;
11369
11437
  const padding = { top: 20, right: 20, bottom: 30, left: 40 };
@@ -11479,8 +11547,8 @@ var Chart = ({
11479
11547
  ] }),
11480
11548
  /* @__PURE__ */ jsxs(Box, { className: "w-full", children: [
11481
11549
  chartType === "bar" && /* @__PURE__ */ jsx(BarChart, { data: normalizedData, height, showValues }),
11482
- chartType === "line" && /* @__PURE__ */ jsx(LineChart, { data: normalizedData, height, showValues }),
11483
- chartType === "area" && /* @__PURE__ */ jsx(LineChart, { data: normalizedData, height, showValues, fill: true }),
11550
+ chartType === "line" && /* @__PURE__ */ jsx(LineChart2, { data: normalizedData, height, showValues }),
11551
+ chartType === "area" && /* @__PURE__ */ jsx(LineChart2, { data: normalizedData, height, showValues, fill: true }),
11484
11552
  chartType === "pie" && /* @__PURE__ */ jsx(PieChart, { data: normalizedData, height, showValues: showLegend }),
11485
11553
  chartType === "donut" && /* @__PURE__ */ jsx(PieChart, { data: normalizedData, height, showValues: showLegend, donut: true })
11486
11554
  ] }),
@@ -13216,15 +13284,15 @@ var NavLink = ({
13216
13284
  to: item.href,
13217
13285
  className: cn(
13218
13286
  "flex items-center gap-3 px-3 py-2 rounded-[var(--radius-lg)] text-sm font-medium transition-colors",
13219
- isActive ? "bg-[var(--color-foreground)] text-[var(--color-background)] shadow-[var(--shadow-sm)]" : "text-[var(--color-muted-foreground)] hover:bg-[var(--color-muted)] hover:text-[var(--color-foreground)]"
13287
+ isActive ? "bg-[var(--color-primary)] text-[var(--color-primary-foreground)] shadow-[var(--shadow-sm)]" : "text-[var(--color-muted-foreground)] hover:bg-[var(--color-muted)] hover:text-[var(--color-foreground)]"
13220
13288
  ),
13221
13289
  children: [
13222
- /* @__PURE__ */ jsx(
13290
+ Icon3 && /* @__PURE__ */ jsx(
13223
13291
  Icon3,
13224
13292
  {
13225
13293
  className: cn(
13226
13294
  "h-5 w-5",
13227
- isActive ? "text-[var(--color-background)]" : "text-[var(--color-muted-foreground)]"
13295
+ isActive ? "text-[var(--color-primary-foreground)]" : "text-[var(--color-muted-foreground)]"
13228
13296
  )
13229
13297
  }
13230
13298
  ),
@@ -13232,6 +13300,7 @@ var NavLink = ({
13232
13300
  Typography,
13233
13301
  {
13234
13302
  variant: "small",
13303
+ color: isActive ? "inherit" : "primary",
13235
13304
  className: "flex-1",
13236
13305
  as: "span",
13237
13306
  children: item.label
@@ -13386,6 +13455,8 @@ function CounterMinimal({
13386
13455
  onIncrement,
13387
13456
  className
13388
13457
  }) {
13458
+ const resolved = entity && typeof entity === "object" && !Array.isArray(entity) ? entity : void 0;
13459
+ if (!resolved) return null;
13389
13460
  return /* @__PURE__ */ jsxs(HStack, { gap: "lg", align: "center", justify: "center", className, children: [
13390
13461
  /* @__PURE__ */ jsx(
13391
13462
  Button,
@@ -13393,9 +13464,9 @@ function CounterMinimal({
13393
13464
  variant: "secondary",
13394
13465
  size: sizeStyles[size].button,
13395
13466
  onClick: onDecrement,
13396
- disabled: entity.decrementDisabled,
13467
+ disabled: resolved.decrementDisabled,
13397
13468
  icon: Minus,
13398
- children: entity.decrementLabel
13469
+ children: resolved.decrementLabel
13399
13470
  }
13400
13471
  ),
13401
13472
  /* @__PURE__ */ jsx(
@@ -13406,7 +13477,7 @@ function CounterMinimal({
13406
13477
  sizeStyles[size].display,
13407
13478
  "font-bold tabular-nums min-w-[3ch] text-center"
13408
13479
  ),
13409
- children: entity.count
13480
+ children: resolved.count
13410
13481
  }
13411
13482
  ),
13412
13483
  /* @__PURE__ */ jsx(
@@ -13415,9 +13486,9 @@ function CounterMinimal({
13415
13486
  variant: "secondary",
13416
13487
  size: sizeStyles[size].button,
13417
13488
  onClick: onIncrement,
13418
- disabled: entity.incrementDisabled,
13489
+ disabled: resolved.incrementDisabled,
13419
13490
  icon: Plus,
13420
- children: entity.incrementLabel
13491
+ children: resolved.incrementLabel
13421
13492
  }
13422
13493
  )
13423
13494
  ] });
@@ -13433,6 +13504,8 @@ function CounterStandard({
13433
13504
  onReset,
13434
13505
  className
13435
13506
  }) {
13507
+ const resolved = entity && typeof entity === "object" && !Array.isArray(entity) ? entity : void 0;
13508
+ if (!resolved) return null;
13436
13509
  return /* @__PURE__ */ jsx(Container, { size: "sm", padding: "lg", className, children: /* @__PURE__ */ jsxs(VStack, { gap: "lg", align: "center", children: [
13437
13510
  /* @__PURE__ */ jsx(
13438
13511
  Typography,
@@ -13450,7 +13523,7 @@ function CounterStandard({
13450
13523
  sizeStyles[size].display,
13451
13524
  "font-bold tabular-nums text-primary-600"
13452
13525
  ),
13453
- children: entity.count
13526
+ children: resolved.count
13454
13527
  }
13455
13528
  ),
13456
13529
  /* @__PURE__ */ jsxs(HStack, { gap: "md", children: [
@@ -13460,7 +13533,7 @@ function CounterStandard({
13460
13533
  variant: "secondary",
13461
13534
  size: sizeStyles[size].button,
13462
13535
  onClick: onDecrement,
13463
- disabled: entity.decrementDisabled,
13536
+ disabled: resolved.decrementDisabled,
13464
13537
  icon: Minus
13465
13538
  }
13466
13539
  ),
@@ -13470,7 +13543,7 @@ function CounterStandard({
13470
13543
  variant: "primary",
13471
13544
  size: sizeStyles[size].button,
13472
13545
  onClick: onIncrement,
13473
- disabled: entity.incrementDisabled,
13546
+ disabled: resolved.incrementDisabled,
13474
13547
  icon: Plus
13475
13548
  }
13476
13549
  )
@@ -13498,6 +13571,8 @@ function CounterFull({
13498
13571
  onReset,
13499
13572
  className
13500
13573
  }) {
13574
+ const resolved = entity && typeof entity === "object" && !Array.isArray(entity) ? entity : void 0;
13575
+ if (!resolved) return null;
13501
13576
  return /* @__PURE__ */ jsx(Container, { size: "sm", padding: "lg", className, children: /* @__PURE__ */ jsxs(VStack, { gap: "xl", align: "center", children: [
13502
13577
  /* @__PURE__ */ jsx(
13503
13578
  Typography,
@@ -13516,10 +13591,10 @@ function CounterFull({
13516
13591
  sizeStyles[size].display,
13517
13592
  "font-bold tabular-nums text-primary-600"
13518
13593
  ),
13519
- children: entity.count
13594
+ children: resolved.count
13520
13595
  }
13521
13596
  ),
13522
- entity.rangeText && /* @__PURE__ */ jsx(Typography, { variant: "small", color: "muted", children: entity.rangeText })
13597
+ resolved.rangeText && /* @__PURE__ */ jsx(Typography, { variant: "small", color: "muted", children: resolved.rangeText })
13523
13598
  ] }),
13524
13599
  /* @__PURE__ */ jsxs(HStack, { gap: "md", children: [
13525
13600
  /* @__PURE__ */ jsx(
@@ -13528,9 +13603,9 @@ function CounterFull({
13528
13603
  variant: "secondary",
13529
13604
  size: sizeStyles[size].button,
13530
13605
  onClick: onDecrement,
13531
- disabled: entity.decrementDisabled,
13606
+ disabled: resolved.decrementDisabled,
13532
13607
  icon: Minus,
13533
- children: entity.decrementLabel
13608
+ children: resolved.decrementLabel
13534
13609
  }
13535
13610
  ),
13536
13611
  /* @__PURE__ */ jsx(
@@ -13539,9 +13614,9 @@ function CounterFull({
13539
13614
  variant: "primary",
13540
13615
  size: sizeStyles[size].button,
13541
13616
  onClick: onIncrement,
13542
- disabled: entity.incrementDisabled,
13617
+ disabled: resolved.incrementDisabled,
13543
13618
  icon: Plus,
13544
- children: entity.incrementLabel
13619
+ children: resolved.incrementLabel
13545
13620
  }
13546
13621
  )
13547
13622
  ] }),
@@ -13790,10 +13865,12 @@ function BattleTemplate({
13790
13865
  unitScale = 1,
13791
13866
  className
13792
13867
  }) {
13868
+ const resolved = entity && typeof entity === "object" && !Array.isArray(entity) ? entity : void 0;
13869
+ if (!resolved) return null;
13793
13870
  return /* @__PURE__ */ jsx(
13794
13871
  BattleBoard,
13795
13872
  {
13796
- entity,
13873
+ entity: resolved,
13797
13874
  scale,
13798
13875
  unitScale,
13799
13876
  tileClickEvent: "TILE_CLICK",
@@ -13813,10 +13890,12 @@ function CastleTemplate({
13813
13890
  scale = 0.45,
13814
13891
  className
13815
13892
  }) {
13893
+ const resolved = entity && typeof entity === "object" && !Array.isArray(entity) ? entity : void 0;
13894
+ if (!resolved) return null;
13816
13895
  return /* @__PURE__ */ jsx(
13817
13896
  CastleBoard,
13818
13897
  {
13819
- entity,
13898
+ entity: resolved,
13820
13899
  scale,
13821
13900
  featureClickEvent: "FEATURE_CLICK",
13822
13901
  unitClickEvent: "UNIT_CLICK",
@@ -13852,4 +13931,4 @@ function WorldMapTemplate({
13852
13931
  }
13853
13932
  WorldMapTemplate.displayName = "WorldMapTemplate";
13854
13933
 
13855
- export { ALL_PRESETS, AR_BOOK_FIELDS, ActionPalette, ActionTile, AuthLayout, BattleBoard, BattleTemplate, BookChapterView, BookCoverPage, BookNavBar, BookTableOfContents, BookViewer, BuilderBoard, CanvasEffect, CastleBoard, CastleTemplate, Chart, ClassifierBoard, CodeView, CodeViewer, CollapsibleSection, CombatLog, ConfirmDialog, ContentRenderer, CounterTemplate, DIAMOND_TOP_Y, DashboardGrid, DashboardLayout, DebuggerBoard, DialogueBox, DocumentViewer, StateMachineView as DomStateMachineVisualizer, DrawerSlot, EditorCheckbox, EditorSelect, EditorSlider, EditorTextInput, EditorToolbar, EventHandlerBoard, EventLog, FEATURE_COLORS, FEATURE_TYPES, FLOOR_HEIGHT, FormActions, FormLayout, FormSection, GameAudioContext, GameAudioProvider, GameAudioToggle, GameHud, GameMenu, GameOverScreen, GameShell, GameTemplate, GenericAppTemplate, GraphCanvas, Header, IDENTITY_BOOK_FIELDS, InventoryPanel, IsometricCanvas, JazariStateMachine, List, MediaGallery, Meter, ModalSlot, Navigation, NegotiatorBoard, ObjectRulePanel, StateMachineView as OrbitalStateMachineView, OrbitalVisualization, PhysicsManager, RuleEditor, SHEET_COLUMNS, SPRITE_SHEET_LAYOUT, Section, SequenceBar, SequencerBoard, Sidebar, SignaturePad, SimulationCanvas, SimulationControls, SimulationGraph, SimulatorBoard, Split, SplitPane, StateArchitectBoard, StateMachineView, StateNode2 as StateNode, StatusBar, TERRAIN_COLORS, TILE_HEIGHT, TILE_WIDTH, TabbedContainer, Table, TerrainPalette, Timeline, ToastSlot, TraitSlot, TraitStateViewer, TransitionArrow, UncontrolledBattleBoard, VariablePanel, WizardContainer, WorldMapBoard, WorldMapTemplate, applyTemporaryEffect, calculateAttackTargets, calculateDamage, calculateValidMoves, combatAnimations, combatClasses, combatEffects, createInitialGameState, createUnitAnimationState, generateCombatMessage, getCurrentFrame, inferDirection, isoToScreen, mapBookData, pendulum, projectileMotion, resolveFieldMap, resolveFrame, resolveSheetDirection, screenToIso, springOscillator, tickAnimationState, transitionAnimation, useBattleState, useCamera, useGameAudio, useGameAudioContext, useImageCache, usePhysics2D, useSpriteAnimations };
13934
+ export { ALL_PRESETS, AR_BOOK_FIELDS, ActionPalette, ActionTile, AuthLayout, BattleBoard, BattleTemplate, BookChapterView, BookCoverPage, BookNavBar, BookTableOfContents, BookViewer, BuilderBoard, CanvasEffect, CastleBoard, CastleTemplate, Chart, ClassifierBoard, CodeView, CodeViewer, CollapsibleSection, CombatLog, ConfirmDialog, ContentRenderer, CounterTemplate, DIAMOND_TOP_Y, DashboardGrid, DashboardLayout, DebuggerBoard, DialogueBox, DocumentViewer, StateMachineView as DomStateMachineVisualizer, DrawerSlot, EditorCheckbox, EditorSelect, EditorSlider, EditorTextInput, EditorToolbar, EventHandlerBoard, EventLog, FEATURE_COLORS, FEATURE_TYPES, FLOOR_HEIGHT, FormActions, FormLayout, FormSection, GameAudioContext, GameAudioProvider, GameAudioToggle, GameHud, GameMenu, GameOverScreen, GameShell, GameTemplate, GenericAppTemplate, GraphCanvas, Header, IDENTITY_BOOK_FIELDS, InventoryPanel, IsometricCanvas, JazariStateMachine, List, MediaGallery, Meter, ModalSlot, Navigation, NegotiatorBoard, NotifyListener, ObjectRulePanel, StateMachineView as OrbitalStateMachineView, OrbitalVisualization, PhysicsManager, RuleEditor, SHEET_COLUMNS, SPRITE_SHEET_LAYOUT, Section, SequenceBar, SequencerBoard, Sidebar, SignaturePad, SimulationCanvas, SimulationControls, SimulationGraph, SimulatorBoard, Split, SplitPane, StateArchitectBoard, StateMachineView, StateNode2 as StateNode, StatusBar, TERRAIN_COLORS, TILE_HEIGHT, TILE_WIDTH, TabbedContainer, Table, TerrainPalette, Timeline, ToastSlot, TraitSlot, TraitStateViewer, TransitionArrow, UncontrolledBattleBoard, VariablePanel, WizardContainer, WorldMapBoard, WorldMapTemplate, applyTemporaryEffect, calculateAttackTargets, calculateDamage, calculateValidMoves, combatAnimations, combatClasses, combatEffects, createInitialGameState, createUnitAnimationState, generateCombatMessage, getCurrentFrame, inferDirection, isoToScreen, mapBookData, pendulum, projectileMotion, resolveFieldMap, resolveFrame, resolveSheetDirection, screenToIso, springOscillator, tickAnimationState, transitionAnimation, useBattleState, useCamera, useGameAudio, useGameAudioContext, useImageCache, usePhysics2D, useSpriteAnimations };