@almadar/ui 2.1.5 → 2.1.8

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.
@@ -14,8 +14,8 @@ import ReactMarkdown from 'react-markdown';
14
14
  import remarkGfm from 'remark-gfm';
15
15
  import remarkMath from 'remark-math';
16
16
  import rehypeKatex from 'rehype-katex';
17
- import { Prism } from 'react-syntax-highlighter';
18
- import { vscDarkPlus } from 'react-syntax-highlighter/dist/cjs/styles/prism';
17
+ import SyntaxHighlighter from 'react-syntax-highlighter/dist/cjs/prism';
18
+ import dark from 'react-syntax-highlighter/dist/cjs/styles/prism/vsc-dark-plus';
19
19
 
20
20
  var variantStyles = {
21
21
  primary: [
@@ -808,6 +808,7 @@ var Box = React41__default.forwardRef(
808
808
  const eventBus = useEventBus();
809
809
  const handleClick = useCallback((e) => {
810
810
  if (action) {
811
+ e.stopPropagation();
811
812
  eventBus.emit(`UI:${action}`, actionPayload ?? {});
812
813
  }
813
814
  onClick?.(e);
@@ -4094,6 +4095,7 @@ var Menu2 = ({
4094
4095
  className
4095
4096
  }) => {
4096
4097
  const eventBus = useEventBus();
4098
+ const { t } = useTranslate();
4097
4099
  const [isOpen, setIsOpen] = useState(false);
4098
4100
  const [activeSubMenu, setActiveSubMenu] = useState(null);
4099
4101
  const [triggerRect, setTriggerRect] = useState(null);
@@ -4172,6 +4174,7 @@ var Menu2 = ({
4172
4174
  onClick: () => handleItemClick({ ...item, id: itemId }),
4173
4175
  disabled: item.disabled,
4174
4176
  onMouseEnter: () => hasSubMenu && setActiveSubMenu(itemId),
4177
+ "data-testid": item.event ? `action-${item.event}` : void 0,
4175
4178
  className: cn(
4176
4179
  "w-full flex items-center justify-between gap-3 px-4 py-2 text-left",
4177
4180
  "text-sm transition-colors",
@@ -5904,11 +5907,11 @@ var CodeBlock = React41__default.memo(
5904
5907
  padding: "1rem"
5905
5908
  },
5906
5909
  children: /* @__PURE__ */ jsx(
5907
- Prism,
5910
+ SyntaxHighlighter,
5908
5911
  {
5909
5912
  PreTag: "div",
5910
5913
  language,
5911
- style: vscDarkPlus,
5914
+ style: dark,
5912
5915
  customStyle: {
5913
5916
  backgroundColor: "transparent",
5914
5917
  borderRadius: 0,
@@ -7000,6 +7003,7 @@ var StatCard = ({
7000
7003
  variant: "ghost",
7001
7004
  onClick: handleActionClick,
7002
7005
  className: "mt-4 text-sm font-bold text-[var(--color-foreground)] hover:underline",
7006
+ "data-testid": action.event ? `action-${action.event}` : void 0,
7003
7007
  children: [
7004
7008
  action.label,
7005
7009
  " \u2192"
@@ -7208,13 +7212,14 @@ var DetailPanel = ({
7208
7212
  error
7209
7213
  }) => {
7210
7214
  const eventBus = useEventBus();
7215
+ const { t } = useTranslate();
7211
7216
  const isFieldDefArray = (arr) => {
7212
7217
  if (!arr || arr.length === 0) return false;
7213
7218
  const first = arr[0];
7214
7219
  return typeof first === "string" || typeof first === "object" && first !== null && "key" in first;
7215
7220
  };
7216
7221
  const effectiveFieldNames = isFieldDefArray(propFields) ? normalizeFieldDefs(propFields) : fieldNames;
7217
- const handleActionClick = useCallback(
7222
+ useCallback(
7218
7223
  (action, data2) => {
7219
7224
  if (action.navigatesTo) {
7220
7225
  const url = action.navigatesTo.replace(
@@ -7359,9 +7364,9 @@ var DetailPanel = ({
7359
7364
  return /* @__PURE__ */ jsx(
7360
7365
  ErrorState,
7361
7366
  {
7362
- title: "Error loading data",
7363
- message: error.message || "An error occurred while loading the data.",
7364
- onRetry: () => window.location.reload(),
7367
+ title: t("error.loadingData"),
7368
+ message: error.message || t("error.genericLoad"),
7369
+ retryEvent: "RETRY",
7365
7370
  className
7366
7371
  }
7367
7372
  );
@@ -7424,8 +7429,10 @@ var DetailPanel = ({
7424
7429
  Button,
7425
7430
  {
7426
7431
  variant: action.variant || "secondary",
7427
- onClick: () => handleActionClick(action, normalizedData),
7432
+ action: action.event,
7433
+ actionPayload: { row: normalizedData },
7428
7434
  icon: action.icon,
7435
+ "data-testid": action.event ? `action-${action.event}` : void 0,
7429
7436
  children: action.label
7430
7437
  },
7431
7438
  idx
@@ -8062,6 +8069,7 @@ var CardGrid = ({
8062
8069
  showTotal = true
8063
8070
  }) => {
8064
8071
  const eventBus = useEventBus();
8072
+ const { t } = useTranslate();
8065
8073
  const effectiveFieldNames = normalizeFields(fields).length > 0 ? normalizeFields(fields) : fieldNames ?? normalizeFields(columns);
8066
8074
  const gridTemplateColumns = `repeat(auto-fit, minmax(min(${minCardWidth}px, 100%), 1fr))`;
8067
8075
  const normalizedData = Array.isArray(entity) ? entity : entity ? [entity] : [];
@@ -8070,9 +8078,6 @@ var CardGrid = ({
8070
8078
  const handlePageChange = (newPage) => {
8071
8079
  eventBus.emit("UI:PAGINATE", { page: newPage, pageSize });
8072
8080
  };
8073
- const handleCardClick = (itemData) => {
8074
- eventBus.emit("UI:VIEW", { row: itemData });
8075
- };
8076
8081
  const renderContent = () => {
8077
8082
  if (children) {
8078
8083
  return children;
@@ -8117,7 +8122,8 @@ var CardGrid = ({
8117
8122
  "bg-[var(--color-card)] rounded-[var(--radius-lg)] border border-[var(--color-border)] p-4 shadow-[var(--shadow-sm)]",
8118
8123
  "cursor-pointer hover:border-[var(--color-primary)] transition-colors"
8119
8124
  ),
8120
- onClick: () => handleCardClick(itemData),
8125
+ action: "VIEW",
8126
+ actionPayload: { row: itemData },
8121
8127
  children: [
8122
8128
  cardFields.map((field) => {
8123
8129
  const value = getNestedValue(itemData, field);
@@ -8135,6 +8141,7 @@ var CardGrid = ({
8135
8141
  variant: buttonVariant,
8136
8142
  size: "sm",
8137
8143
  onClick: handleActionClick(action),
8144
+ "data-testid": action.event ? `action-${action.event}` : void 0,
8138
8145
  children: action.label
8139
8146
  },
8140
8147
  actionIdx
@@ -9227,11 +9234,26 @@ function UISlotComponent({
9227
9234
  slot,
9228
9235
  portal = false,
9229
9236
  position,
9230
- className
9237
+ className,
9238
+ children,
9239
+ pattern,
9240
+ sourceTrait
9231
9241
  }) {
9232
9242
  const { slots, clear } = useUISlots();
9233
9243
  const suspenseConfig = useContext(SuspenseConfigContext);
9234
9244
  const content = slots[slot];
9245
+ if (children !== void 0) {
9246
+ return /* @__PURE__ */ jsx(
9247
+ Box,
9248
+ {
9249
+ id: `slot-${slot}`,
9250
+ className: cn("ui-slot", `ui-slot-${slot}`, className),
9251
+ "data-pattern": pattern,
9252
+ "data-source-trait": sourceTrait,
9253
+ children
9254
+ }
9255
+ );
9256
+ }
9235
9257
  if (!content) {
9236
9258
  if (!portal) {
9237
9259
  return /* @__PURE__ */ jsx(
@@ -2809,10 +2809,16 @@ interface DetailPanelProps extends EntityDisplayProps {
2809
2809
  position?: "left" | "right";
2810
2810
  /** Panel width (CSS value, e.g., '400px', '50%') */
2811
2811
  width?: string;
2812
+ /** Entity ID for fetching specific entity */
2813
+ entityId?: string;
2814
+ /** Display fields (alias for fields) */
2815
+ displayFields?: readonly string[];
2816
+ /** Show actions flag */
2817
+ showActions?: boolean;
2812
2818
  }
2813
2819
  declare const DetailPanel: React__default.FC<DetailPanelProps>;
2814
2820
 
2815
- interface FormSectionProps {
2821
+ interface FormSectionProps extends EntityDisplayProps {
2816
2822
  /** Section title */
2817
2823
  title?: string;
2818
2824
  /** Section description */
@@ -2827,47 +2833,28 @@ interface FormSectionProps {
2827
2833
  card?: boolean;
2828
2834
  /** Grid columns for fields */
2829
2835
  columns?: 1 | 2 | 3;
2830
- className?: string;
2831
- /** Loading state */
2832
- isLoading?: boolean;
2833
- /** Error state */
2834
- error?: Error | null;
2835
- /** Entity name */
2836
- entity?: string;
2836
+ /** Entity ID for fetching specific entity */
2837
+ entityId?: string;
2837
2838
  }
2838
2839
  declare const FormSection$1: React__default.FC<FormSectionProps>;
2839
2840
  /**
2840
2841
  * Form layout with multiple sections
2841
2842
  */
2842
- interface FormLayoutProps {
2843
+ interface FormLayoutProps extends EntityDisplayProps {
2843
2844
  children: React__default.ReactNode;
2844
2845
  /** Show section dividers */
2845
2846
  dividers?: boolean;
2846
- className?: string;
2847
- /** Loading state */
2848
- isLoading?: boolean;
2849
- /** Error state */
2850
- error?: Error | null;
2851
- /** Entity name */
2852
- entity?: string;
2853
2847
  }
2854
2848
  declare const FormLayout: React__default.FC<FormLayoutProps>;
2855
2849
  /**
2856
2850
  * Form actions bar (submit/cancel buttons)
2857
2851
  */
2858
- interface FormActionsProps {
2852
+ interface FormActionsProps extends EntityDisplayProps {
2859
2853
  children: React__default.ReactNode;
2860
2854
  /** Sticky at bottom */
2861
2855
  sticky?: boolean;
2862
2856
  /** Alignment */
2863
2857
  align?: "left" | "right" | "between" | "center";
2864
- className?: string;
2865
- /** Loading state */
2866
- isLoading?: boolean;
2867
- /** Error state */
2868
- error?: Error | null;
2869
- /** Entity name */
2870
- entity?: string;
2871
2858
  }
2872
2859
  declare const FormActions: React__default.FC<FormActionsProps>;
2873
2860
 
@@ -7183,13 +7170,19 @@ interface UISlotComponentProps {
7183
7170
  isLoading?: boolean;
7184
7171
  error?: Error | null;
7185
7172
  entity?: string;
7173
+ /** Compiled mode: render children directly instead of resolving from context */
7174
+ children?: React__default.ReactNode;
7175
+ /** Pattern type for data-pattern attribute (compiled mode) */
7176
+ pattern?: string;
7177
+ /** Source trait name for data-source-trait attribute (compiled mode) */
7178
+ sourceTrait?: string;
7186
7179
  }
7187
7180
  /**
7188
7181
  * Individual slot renderer.
7189
7182
  *
7190
7183
  * Handles different slot types with appropriate wrappers.
7191
7184
  */
7192
- declare function UISlotComponent({ slot, portal, position, className, }: UISlotComponentProps): React__default.ReactElement | null;
7185
+ declare function UISlotComponent({ slot, portal, position, className, children, pattern, sourceTrait, }: UISlotComponentProps): React__default.ReactElement | null;
7193
7186
  interface SlotContentRendererProps {
7194
7187
  content: SlotContent;
7195
7188
  onDismiss: () => void;
@@ -2,8 +2,8 @@ import { DEFAULT_CONFIG, renderStateMachineToDomData, parseContentSegments } fro
2
2
  import { useAuthContext } from '../chunk-6OACETQB.js';
3
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-6OACETQB.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, 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';
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-BS6DAANP.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-BS6DAANP.js';
7
7
  import '../chunk-BTXQJGFB.js';
8
8
  import { cn, getNestedValue } from '../chunk-KKCVDUK7.js';
9
9
  export { cn } from '../chunk-KKCVDUK7.js';
@@ -14,8 +14,8 @@ export { useEmitEvent, useEventBus, useEventListener } from '../chunk-YXZM3WCF.j
14
14
  export { DEFAULT_SLOTS, useUISlotManager } from '../chunk-7NEWMNNU.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
- import * as React42 from 'react';
18
- import React42__default, { createContext, useState, useCallback, useMemo, useEffect, useRef, useContext } from 'react';
17
+ import * as React from 'react';
18
+ import React__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';
@@ -31,12 +31,20 @@ var FormSection = ({
31
31
  columns = 1,
32
32
  className
33
33
  }) => {
34
- const [collapsed, setCollapsed] = React42__default.useState(defaultCollapsed);
34
+ const [collapsed, setCollapsed] = React__default.useState(defaultCollapsed);
35
+ const { t } = useTranslate();
36
+ const eventBus = useEventBus();
35
37
  const gridClass = {
36
38
  1: "grid-cols-1",
37
39
  2: "grid-cols-1 md:grid-cols-2",
38
40
  3: "grid-cols-1 md:grid-cols-2 lg:grid-cols-3"
39
41
  }[columns];
42
+ React__default.useCallback(() => {
43
+ if (collapsible) {
44
+ setCollapsed((prev) => !prev);
45
+ eventBus.emit("UI:TOGGLE_COLLAPSE", { collapsed: !collapsed });
46
+ }
47
+ }, [collapsible, collapsed, eventBus]);
40
48
  const content = /* @__PURE__ */ jsxs(Fragment, { children: [
41
49
  (title || description) && /* @__PURE__ */ jsxs(VStack, { gap: "xs", className: "mb-4", children: [
42
50
  title && /* @__PURE__ */ jsxs(
@@ -45,7 +53,7 @@ var FormSection = ({
45
53
  justify: "between",
46
54
  align: "center",
47
55
  className: cn(collapsible && "cursor-pointer"),
48
- onClick: () => collapsible && setCollapsed(!collapsed),
56
+ action: collapsible ? "TOGGLE_COLLAPSE" : void 0,
49
57
  children: [
50
58
  /* @__PURE__ */ jsx(Typography, { variant: "h3", weight: "semibold", children: title }),
51
59
  collapsible && /* @__PURE__ */ jsx(
@@ -53,7 +61,7 @@ var FormSection = ({
53
61
  {
54
62
  variant: "ghost",
55
63
  size: "sm",
56
- onClick: () => setCollapsed(!collapsed),
64
+ action: "TOGGLE_COLLAPSE",
57
65
  children: /* @__PURE__ */ jsx(
58
66
  Icon,
59
67
  {
@@ -1028,7 +1036,7 @@ var List = ({
1028
1036
  if (entity && typeof entity === "object" && "id" in entity) return [entity];
1029
1037
  return [];
1030
1038
  }, [entity]);
1031
- const getItemActions = React42__default.useCallback(
1039
+ const getItemActions = React__default.useCallback(
1032
1040
  (item) => {
1033
1041
  if (!itemActions) return [];
1034
1042
  if (typeof itemActions === "function") {
@@ -1037,6 +1045,7 @@ var List = ({
1037
1045
  return itemActions.map((action, idx) => ({
1038
1046
  id: `${item.id}-action-${idx}`,
1039
1047
  label: action.label,
1048
+ event: action.event,
1040
1049
  onClick: () => {
1041
1050
  if (action.navigatesTo) {
1042
1051
  const url = action.navigatesTo.replace(
@@ -1117,9 +1126,6 @@ var List = ({
1117
1126
  eventBus.emit(`UI:${EntityDisplayEvents.DESELECT}`, { ids: newIds });
1118
1127
  }
1119
1128
  };
1120
- const handleRowClick = (item) => {
1121
- eventBus.emit("UI:VIEW", { row: item });
1122
- };
1123
1129
  const defaultRenderItem = (item, index, isLast) => {
1124
1130
  const isSelected = selectedIds.map(String).includes(item.id);
1125
1131
  const actions = normalizedItemActions ? normalizedItemActions(item) : [];
@@ -1130,8 +1136,9 @@ var List = ({
1130
1136
  const editAction = actions.find(
1131
1137
  (a) => a.label.toLowerCase().includes("edit")
1132
1138
  );
1133
- const hasExplicitClick = !!(item.onClick || viewAction?.onClick);
1134
- const handleClick = item.onClick || viewAction?.onClick || (() => handleRowClick(item));
1139
+ const hasExplicitClick = !!(viewAction?.event || item.onClick);
1140
+ const rowAction = viewAction?.event ?? "VIEW";
1141
+ const rowActionPayload = { row: item };
1135
1142
  const primaryField = effectiveFieldNames?.[0];
1136
1143
  const statusField = effectiveFieldNames?.find(
1137
1144
  (f) => f.toLowerCase().includes("status")
@@ -1166,20 +1173,28 @@ var List = ({
1166
1173
  isSelected && "bg-[var(--color-primary)]/10 shadow-inner",
1167
1174
  item.disabled && "opacity-50 cursor-not-allowed grayscale"
1168
1175
  ),
1169
- onClick: handleClick,
1176
+ action: rowAction,
1177
+ actionPayload: rowActionPayload,
1170
1178
  children: [
1171
- selectable && /* @__PURE__ */ jsx(Box, { className: "flex-shrink-0 pt-0.5", children: /* @__PURE__ */ jsx(
1172
- Checkbox,
1179
+ selectable && /* @__PURE__ */ jsx(
1180
+ Box,
1173
1181
  {
1174
- checked: isSelected,
1175
- onChange: (e) => handleSelect(item.id, e.target.checked),
1176
- onClick: (e) => e.stopPropagation(),
1177
- className: cn(
1178
- "transition-transform active:scale-95",
1179
- isSelected ? "border-[var(--color-primary)] bg-[var(--color-primary)]" : "border-[var(--color-border)]"
1182
+ className: "flex-shrink-0 pt-0.5",
1183
+ action: isSelected ? EntityDisplayEvents.DESELECT : EntityDisplayEvents.SELECT,
1184
+ actionPayload: { ids: isSelected ? selectedIds.filter((sid) => String(sid) !== item.id) : [...selectedIds.map(String), item.id] },
1185
+ children: /* @__PURE__ */ jsx(
1186
+ Checkbox,
1187
+ {
1188
+ checked: isSelected,
1189
+ onChange: (e) => handleSelect(item.id, e.target.checked),
1190
+ className: cn(
1191
+ "transition-transform active:scale-95",
1192
+ isSelected ? "border-[var(--color-primary)] bg-[var(--color-primary)]" : "border-[var(--color-border)]"
1193
+ )
1194
+ }
1180
1195
  )
1181
1196
  }
1182
- ) }),
1197
+ ),
1183
1198
  /* @__PURE__ */ jsxs(Box, { className: "flex-1 min-w-0 space-y-2.5", children: [
1184
1199
  /* @__PURE__ */ jsxs(HStack, { className: "flex items-center gap-4", children: [
1185
1200
  /* @__PURE__ */ jsx(
@@ -1262,10 +1277,7 @@ var List = ({
1262
1277
  Button,
1263
1278
  {
1264
1279
  variant: "ghost",
1265
- onClick: (e) => {
1266
- e.stopPropagation();
1267
- editAction.onClick?.();
1268
- },
1280
+ action: editAction.event,
1269
1281
  className: cn(
1270
1282
  "p-2 rounded-[var(--radius-lg)] transition-all duration-200",
1271
1283
  "hover:bg-[var(--color-primary)]/10 hover:text-[var(--color-primary)]",
@@ -1273,6 +1285,7 @@ var List = ({
1273
1285
  "active:scale-95"
1274
1286
  ),
1275
1287
  title: editAction.label,
1288
+ "data-testid": editAction.event ? `action-${editAction.event}` : void 0,
1276
1289
  children: /* @__PURE__ */ jsx(Pencil, { className: "w-4 h-4" })
1277
1290
  }
1278
1291
  ),
@@ -1280,10 +1293,7 @@ var List = ({
1280
1293
  Button,
1281
1294
  {
1282
1295
  variant: "ghost",
1283
- onClick: (e) => {
1284
- e.stopPropagation();
1285
- viewAction.onClick?.();
1286
- },
1296
+ action: viewAction.event,
1287
1297
  className: cn(
1288
1298
  "p-2 rounded-[var(--radius-lg)] transition-all duration-200",
1289
1299
  "hover:bg-[var(--color-muted)] hover:text-[var(--color-foreground)]",
@@ -1291,6 +1301,7 @@ var List = ({
1291
1301
  "active:scale-95"
1292
1302
  ),
1293
1303
  title: viewAction.label,
1304
+ "data-testid": viewAction.event ? `action-${viewAction.event}` : void 0,
1294
1305
  children: /* @__PURE__ */ jsx(Eye, { className: "w-4 h-4" })
1295
1306
  }
1296
1307
  ),
@@ -1530,7 +1541,7 @@ var WizardContainer = ({
1530
1541
  const isCompleted = index < currentStep;
1531
1542
  const stepKey = step.id ?? step.tabId ?? `step-${index}`;
1532
1543
  const stepTitle = step.title ?? step.name ?? `Step ${index + 1}`;
1533
- return /* @__PURE__ */ jsxs(React42__default.Fragment, { children: [
1544
+ return /* @__PURE__ */ jsxs(React__default.Fragment, { children: [
1534
1545
  /* @__PURE__ */ jsx(
1535
1546
  Button,
1536
1547
  {
@@ -2754,7 +2765,7 @@ var StateMachineView = ({
2754
2765
  style: { top: title ? 30 : 0 },
2755
2766
  children: [
2756
2767
  entity && /* @__PURE__ */ jsx(EntityBox, { entity, config }),
2757
- states.map((state) => renderStateNode ? /* @__PURE__ */ jsx(React42__default.Fragment, { children: renderStateNode(state, config) }, state.id) : /* @__PURE__ */ jsx(
2768
+ states.map((state) => renderStateNode ? /* @__PURE__ */ jsx(React__default.Fragment, { children: renderStateNode(state, config) }, state.id) : /* @__PURE__ */ jsx(
2758
2769
  StateNode,
2759
2770
  {
2760
2771
  state,
@@ -6769,7 +6780,7 @@ function GameMenu({
6769
6780
  } catch {
6770
6781
  }
6771
6782
  const eventBus = eventBusProp || eventBusFromHook;
6772
- const handleOptionClick = React42.useCallback(
6783
+ const handleOptionClick = React.useCallback(
6773
6784
  (option) => {
6774
6785
  if (option.event && eventBus) {
6775
6786
  eventBus.emit(`UI:${option.event}`, { option });
@@ -6892,7 +6903,7 @@ function GameOverScreen({
6892
6903
  } catch {
6893
6904
  }
6894
6905
  const eventBus = eventBusProp || eventBusFromHook;
6895
- const handleActionClick = React42.useCallback(
6906
+ const handleActionClick = React.useCallback(
6896
6907
  (action) => {
6897
6908
  if (action.event && eventBus) {
6898
6909
  eventBus.emit(`UI:${action.event}`, { action });
@@ -8159,7 +8170,7 @@ function LinearView({
8159
8170
  /* @__PURE__ */ jsx(HStack, { className: "flex-wrap items-center", gap: "xs", children: trait.states.map((state, i) => {
8160
8171
  const isDone = i < currentIdx;
8161
8172
  const isCurrent = i === currentIdx;
8162
- return /* @__PURE__ */ jsxs(React42__default.Fragment, { children: [
8173
+ return /* @__PURE__ */ jsxs(React__default.Fragment, { children: [
8163
8174
  i > 0 && /* @__PURE__ */ jsx(
8164
8175
  Typography,
8165
8176
  {
@@ -8813,7 +8824,7 @@ function SequenceBar({
8813
8824
  onSlotRemove(index);
8814
8825
  }, [onSlotRemove, playing]);
8815
8826
  const paddedSlots = Array.from({ length: maxSlots }, (_, i) => slots[i]);
8816
- return /* @__PURE__ */ jsx(HStack, { className: cn("items-center", className), gap: "sm", children: paddedSlots.map((slot, i) => /* @__PURE__ */ jsxs(React42__default.Fragment, { children: [
8827
+ return /* @__PURE__ */ jsx(HStack, { className: cn("items-center", className), gap: "sm", children: paddedSlots.map((slot, i) => /* @__PURE__ */ jsxs(React__default.Fragment, { children: [
8817
8828
  i > 0 && /* @__PURE__ */ jsx(
8818
8829
  Typography,
8819
8830
  {
@@ -11113,7 +11124,7 @@ function generateCombatMessage(event) {
11113
11124
  return event.message;
11114
11125
  }
11115
11126
  function extractTitle(children) {
11116
- if (!React42__default.isValidElement(children)) return void 0;
11127
+ if (!React__default.isValidElement(children)) return void 0;
11117
11128
  const props = children.props;
11118
11129
  if (typeof props.title === "string") {
11119
11130
  return props.title;
@@ -11148,7 +11159,7 @@ var ModalSlot = ({
11148
11159
  };
11149
11160
  ModalSlot.displayName = "ModalSlot";
11150
11161
  function extractTitle2(children) {
11151
- if (!React42__default.isValidElement(children)) return void 0;
11162
+ if (!React__default.isValidElement(children)) return void 0;
11152
11163
  const props = children.props;
11153
11164
  if (typeof props.title === "string") {
11154
11165
  return props.title;
@@ -11185,7 +11196,7 @@ var DrawerSlot = ({
11185
11196
  };
11186
11197
  DrawerSlot.displayName = "DrawerSlot";
11187
11198
  function extractToastProps(children) {
11188
- if (!React42__default.isValidElement(children)) {
11199
+ if (!React__default.isValidElement(children)) {
11189
11200
  if (typeof children === "string") {
11190
11201
  return { message: children };
11191
11202
  }
@@ -11216,7 +11227,7 @@ var ToastSlot = ({
11216
11227
  eventBus.emit("UI:CLOSE");
11217
11228
  };
11218
11229
  if (!isVisible) return null;
11219
- const isCustomContent = React42__default.isValidElement(children) && !message;
11230
+ const isCustomContent = React__default.isValidElement(children) && !message;
11220
11231
  return /* @__PURE__ */ jsx(Box, { className: "fixed bottom-4 right-4 z-50", children: isCustomContent ? children : /* @__PURE__ */ jsx(
11221
11232
  Toast,
11222
11233
  {
@@ -11721,7 +11732,7 @@ var Timeline = ({
11721
11732
  }) => {
11722
11733
  const { t } = useTranslate();
11723
11734
  const entityData = Array.isArray(entity) ? entity : [];
11724
- const items = React42__default.useMemo(() => {
11735
+ const items = React__default.useMemo(() => {
11725
11736
  if (propItems) return propItems;
11726
11737
  if (entityData.length === 0) return [];
11727
11738
  return entityData.map((record, idx) => {
@@ -11862,7 +11873,7 @@ var MediaGallery = ({
11862
11873
  [selectable, selectedItems, selectionEvent, eventBus]
11863
11874
  );
11864
11875
  const entityData = Array.isArray(entity) ? entity : [];
11865
- const items = React42__default.useMemo(() => {
11876
+ const items = React__default.useMemo(() => {
11866
11877
  if (propItems) return propItems;
11867
11878
  if (entityData.length === 0) return [];
11868
11879
  return entityData.map((record, idx) => ({
@@ -1,4 +1,4 @@
1
- import { SuspenseConfigProvider } from '../chunk-Y7AFNUT2.js';
1
+ import { SuspenseConfigProvider } from '../chunk-BS6DAANP.js';
2
2
  import { ThemeProvider } from '../chunk-BTXQJGFB.js';
3
3
  import { recordTransition, registerCheck, bindEventBus, bindTraitStateGetter } from '../chunk-45CTDYBT.js';
4
4
  import '../chunk-KKCVDUK7.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@almadar/ui",
3
- "version": "2.1.5",
3
+ "version": "2.1.8",
4
4
  "description": "React UI components, hooks, and providers for Almadar",
5
5
  "type": "module",
6
6
  "main": "./dist/components/index.js",
@@ -80,7 +80,7 @@
80
80
  "remark-gfm": "^4.0.0",
81
81
  "remark-math": "^6.0.0",
82
82
  "rehype-katex": "^7.0.0",
83
- "react-syntax-highlighter": "^15.6.1"
83
+ "react-syntax-highlighter": "^16.1.0"
84
84
  },
85
85
  "peerDependencies": {
86
86
  "react": ">=18.0.0",
@@ -117,6 +117,7 @@
117
117
  "vitest": "^1.4.0",
118
118
  "@testing-library/react": "^14.2.0",
119
119
  "@testing-library/jest-dom": "^6.4.0",
120
+ "@testing-library/user-event": "^14.5.0",
120
121
  "@vitest/ui": "^1.4.0",
121
122
  "jsdom": "^24.0.0",
122
123
  "@storybook/addon-docs": "^10.2.6",