@almadar/ui 2.2.0 → 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.
@@ -2,8 +2,8 @@ import { useAuthContext } from '../chunk-42WRQA7T.js';
2
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-CC3UOKHI.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-CC3UOKHI.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
7
  import '../chunk-DKQN5FVU.js';
8
8
  import { useTranslate } from '../chunk-GOZKH7QW.js';
9
9
  export { EntityDataProvider, I18nProvider, createTranslate, entityDataKeys, parseQueryBinding, useEntity, useEntityDataAdapter, useEntityDetail, useEntityList, useEntityListSuspense, useEntitySuspense, useQuerySingleton, useTranslate } from '../chunk-GOZKH7QW.js';
@@ -13,6 +13,7 @@ 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
15
  import '../chunk-TSETXL2E.js';
16
+ import '../chunk-K2D5D3WK.js';
16
17
  export { clearEntities, getAllEntities, getByType, getEntity, getSingleton, removeEntity, spawnEntity, updateEntity, updateSingleton } from '../chunk-N7MVUW4R.js';
17
18
  import { __publicField } from '../chunk-PKBMQBKP.js';
18
19
  import * as React from 'react';
@@ -832,7 +833,7 @@ var Table = ({
832
833
  Table.displayName = "Table";
833
834
  function normalizeFields(fields) {
834
835
  if (!fields) return [];
835
- return fields.map((f) => typeof f === "string" ? f : f.key);
836
+ return fields.map((f) => typeof f === "string" ? f : f.key ?? f.name ?? "");
836
837
  }
837
838
  var STATUS_STYLES = {
838
839
  complete: {
@@ -4526,6 +4527,17 @@ function IsometricCanvas({
4526
4527
  if (isLoading) {
4527
4528
  return /* @__PURE__ */ jsx(LoadingState, { className });
4528
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
+ }
4529
4541
  return /* @__PURE__ */ jsxs(
4530
4542
  Box,
4531
4543
  {
@@ -4536,6 +4548,7 @@ function IsometricCanvas({
4536
4548
  "canvas",
4537
4549
  {
4538
4550
  ref: canvasRef,
4551
+ "data-testid": "game-canvas",
4539
4552
  onClick: handleClick,
4540
4553
  onMouseDown: enableCamera ? handleMouseDown : void 0,
4541
4554
  onMouseMove: handleMouseMoveWithCamera,
@@ -4550,6 +4563,27 @@ function IsometricCanvas({
4550
4563
  }
4551
4564
  }
4552
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
+ ] }),
4553
4587
  showMinimap && /* @__PURE__ */ jsx(
4554
4588
  "canvas",
4555
4589
  {
@@ -6710,7 +6744,8 @@ function GameHud({
6710
6744
  className,
6711
6745
  transparent = true
6712
6746
  }) {
6713
- 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 : [];
6714
6749
  const position = propPosition ?? "corners";
6715
6750
  if (position === "corners") {
6716
6751
  const leftStats = stats.slice(0, Math.ceil(stats.length / 2));
@@ -6980,10 +7015,13 @@ function InventoryPanel({
6980
7015
  const eventBus = useEventBus();
6981
7016
  const [hoveredSlot, setHoveredSlot] = useState(null);
6982
7017
  const [tooltipPosition, setTooltipPosition] = useState({ x: 0, y: 0 });
6983
- const slotArray = Array.from({ length: slots }, (_, index) => {
6984
- 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;
6985
7023
  });
6986
- const rows = Math.ceil(slots / columns);
7024
+ const rows = Math.ceil(safeSlots / safeColumns);
6987
7025
  const handleSlotClick = useCallback((index) => {
6988
7026
  if (selectSlotEvent) eventBus.emit(`UI:${selectSlotEvent}`, { index });
6989
7027
  onSelectSlot?.(index);
@@ -7016,7 +7054,7 @@ function InventoryPanel({
7016
7054
  break;
7017
7055
  case "ArrowRight":
7018
7056
  e.preventDefault();
7019
- onSelectSlot?.(Math.min(index + 1, slots - 1));
7057
+ onSelectSlot?.(Math.min(index + 1, safeSlots - 1));
7020
7058
  break;
7021
7059
  case "ArrowLeft":
7022
7060
  e.preventDefault();
@@ -7024,14 +7062,14 @@ function InventoryPanel({
7024
7062
  break;
7025
7063
  case "ArrowDown":
7026
7064
  e.preventDefault();
7027
- onSelectSlot?.(Math.min(index + columns, slots - 1));
7065
+ onSelectSlot?.(Math.min(index + safeColumns, safeSlots - 1));
7028
7066
  break;
7029
7067
  case "ArrowUp":
7030
7068
  e.preventDefault();
7031
- onSelectSlot?.(Math.max(index - columns, 0));
7069
+ onSelectSlot?.(Math.max(index - safeColumns, 0));
7032
7070
  break;
7033
7071
  }
7034
- }, [slotArray, onUseItem, onDropItem, onSelectSlot, columns, slots, useItemEvent, dropItemEvent, eventBus]);
7072
+ }, [slotArray, onUseItem, onDropItem, onSelectSlot, safeColumns, safeSlots, useItemEvent, dropItemEvent, eventBus]);
7035
7073
  const handleMouseEnter = useCallback((e, index) => {
7036
7074
  if (showTooltips && slotArray[index]) {
7037
7075
  setHoveredSlot(index);
@@ -7051,7 +7089,7 @@ function InventoryPanel({
7051
7089
  {
7052
7090
  className: "grid gap-1 bg-gray-900 p-2 rounded-lg border border-gray-700",
7053
7091
  style: {
7054
- gridTemplateColumns: `repeat(${columns}, ${slotSize}px)`,
7092
+ gridTemplateColumns: `repeat(${safeColumns}, ${slotSize}px)`,
7055
7093
  gridTemplateRows: `repeat(${rows}, ${slotSize}px)`
7056
7094
  },
7057
7095
  children: slotArray.map((item, index) => /* @__PURE__ */ jsx(
@@ -11224,6 +11262,55 @@ var ToastSlot = ({
11224
11262
  ) });
11225
11263
  };
11226
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";
11227
11314
  var CHART_COLORS = [
11228
11315
  "var(--color-primary)",
11229
11316
  "var(--color-success)",
@@ -11344,7 +11431,7 @@ var PieChart = ({ data, height, showValues, donut = false }) => {
11344
11431
  ] }, idx)) })
11345
11432
  ] });
11346
11433
  };
11347
- var LineChart = ({ data, height, showValues, fill = false }) => {
11434
+ var LineChart2 = ({ data, height, showValues, fill = false }) => {
11348
11435
  const maxValue = Math.max(...data.map((d) => d.value), 1);
11349
11436
  const width = 400;
11350
11437
  const padding = { top: 20, right: 20, bottom: 30, left: 40 };
@@ -11460,8 +11547,8 @@ var Chart = ({
11460
11547
  ] }),
11461
11548
  /* @__PURE__ */ jsxs(Box, { className: "w-full", children: [
11462
11549
  chartType === "bar" && /* @__PURE__ */ jsx(BarChart, { data: normalizedData, height, showValues }),
11463
- chartType === "line" && /* @__PURE__ */ jsx(LineChart, { data: normalizedData, height, showValues }),
11464
- 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 }),
11465
11552
  chartType === "pie" && /* @__PURE__ */ jsx(PieChart, { data: normalizedData, height, showValues: showLegend }),
11466
11553
  chartType === "donut" && /* @__PURE__ */ jsx(PieChart, { data: normalizedData, height, showValues: showLegend, donut: true })
11467
11554
  ] }),
@@ -13844,4 +13931,4 @@ function WorldMapTemplate({
13844
13931
  }
13845
13932
  WorldMapTemplate.displayName = "WorldMapTemplate";
13846
13933
 
13847
- 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 };
@@ -1,4 +1,4 @@
1
- import { SuspenseConfigProvider } from '../chunk-CC3UOKHI.js';
1
+ import { SuspenseConfigProvider } from '../chunk-HWZL7IZG.js';
2
2
  import { ThemeProvider } from '../chunk-DKQN5FVU.js';
3
3
  import { SelectionProvider, EntityDataProvider } from '../chunk-GOZKH7QW.js';
4
4
  export { SelectionContext, SelectionProvider, useSelection, useSelectionOptional } from '../chunk-GOZKH7QW.js';
@@ -8,7 +8,7 @@ import '../chunk-3JGAROCW.js';
8
8
  import { recordTransition, registerCheck, bindEventBus, bindTraitStateGetter } from '../chunk-45CTDYBT.js';
9
9
  import '../chunk-KKCVDUK7.js';
10
10
  import '../chunk-TSETXL2E.js';
11
- import { useOfflineExecutor } from '../chunk-PL7MD6GF.js';
11
+ import { useOfflineExecutor } from '../chunk-K2D5D3WK.js';
12
12
  import '../chunk-PKBMQBKP.js';
13
13
  import { createContext, useState, useCallback, useMemo, useContext, useRef, useEffect } from 'react';
14
14
  import { jsx, Fragment } from 'react/jsx-runtime';
@@ -344,7 +344,7 @@ declare function getSlotDefinition(slot: UISlot): SlotDefinition;
344
344
  /**
345
345
  * Check if a slot is a portal slot.
346
346
  */
347
- declare function isPortalSlot(slot: UISlot): boolean;
347
+ declare function isPortalSlot(slot: string): boolean;
348
348
  /**
349
349
  * Check if a slot is an inline slot.
350
350
  */