@almadar/ui 2.15.7 → 2.15.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.
@@ -1,8 +1,8 @@
1
1
  import { useAssetLoader, useGameCanvas3DEvents, ModelLoader, Canvas3DLoadingState, Canvas3DErrorBoundary, UnitRenderer, TileRenderer, Scene3D, PhysicsObject3D, Lighting3D, FeatureRenderer3D, FeatureRenderer, Camera3D } from './chunk-4N3BAPDB.js';
2
2
  import { useTheme, useUISlots } from './chunk-DKQN5FVU.js';
3
+ import { cn, DEFAULT_CONFIG, debugGroup, debug, debugGroupEnd, updateAssetStatus, bindCanvasCapture, getNestedValue, isDebugEnabled, renderStateMachineToDomData, parseContentSegments, isDebugEnabled2, onDebugToggle, subscribeToTraitChanges, subscribeToTickChanges, subscribeToGuardChanges, subscribeToDebugEvents, subscribeToVerification, getEntitySnapshot, getSummary, getBridgeHealth, getTransitions, getAllChecks, getDebugEvents, getGuardHistory, getAllTicks, getAllTraits } from './chunk-XL7WB2O5.js';
3
4
  import { useTranslate, useInfiniteScroll, useQuerySingleton, useLongPress, useSwipeGesture, useDragReorder, usePullToRefresh, useAuthContext } from './chunk-CDIOHSKG.js';
4
5
  import { useEventBus, useEventListener } from './chunk-YXZM3WCF.js';
5
- import { cn, DEFAULT_CONFIG, debugGroup, debug, debugGroupEnd, updateAssetStatus, bindCanvasCapture, getNestedValue, isDebugEnabled, renderStateMachineToDomData, parseContentSegments, isDebugEnabled2, onDebugToggle, subscribeToTraitChanges, subscribeToTickChanges, subscribeToGuardChanges, subscribeToDebugEvents, subscribeToVerification, getEntitySnapshot, getSummary, getBridgeHealth, getTransitions, getAllChecks, getDebugEvents, getGuardHistory, getAllTicks, getAllTraits } from './chunk-XL7WB2O5.js';
6
6
  import { isPortalSlot } from './chunk-K2D5D3WK.js';
7
7
  import { __publicField } from './chunk-PKBMQBKP.js';
8
8
  import * as LucideIcons from 'lucide-react';
@@ -7675,13 +7675,14 @@ var RepeatableFormSection = ({
7675
7675
  const { t } = useTranslate();
7676
7676
  const resolvedAddLabel = addLabel ?? t("common.add");
7677
7677
  const resolvedEmptyMessage = emptyMessage ?? t("empty.noItemsAdded");
7678
- const canAdd = !readOnly && items.length < maxItems;
7679
- const canRemove = !readOnly && items.length > minItems;
7678
+ const safeItems = items ?? [];
7679
+ const canAdd = !readOnly && safeItems.length < maxItems;
7680
+ const canRemove = !readOnly && safeItems.length > minItems;
7680
7681
  const handleAdd = useCallback(() => {
7681
7682
  onAdd?.();
7682
7683
  const eventPayload = {
7683
7684
  sectionType,
7684
- index: items.length
7685
+ index: safeItems.length
7685
7686
  };
7686
7687
  if (trackAddedInState && currentState) {
7687
7688
  eventPayload.addedInState = currentState;
@@ -7690,7 +7691,7 @@ var RepeatableFormSection = ({
7690
7691
  eventBus.emit("UI:SECTION_ADDED", eventPayload);
7691
7692
  }, [
7692
7693
  sectionType,
7693
- items.length,
7694
+ safeItems.length,
7694
7695
  onAdd,
7695
7696
  eventBus,
7696
7697
  trackAddedInState,
@@ -7709,7 +7710,7 @@ var RepeatableFormSection = ({
7709
7710
  /* @__PURE__ */ jsx(Typography, { variant: "h4", children: title }),
7710
7711
  /* @__PURE__ */ jsxs(Typography, { variant: "caption", color: "muted", children: [
7711
7712
  "(",
7712
- items.length,
7713
+ safeItems.length,
7713
7714
  maxItems !== Infinity ? `/${maxItems}` : "",
7714
7715
  ")"
7715
7716
  ] })
@@ -7719,13 +7720,13 @@ var RepeatableFormSection = ({
7719
7720
  resolvedAddLabel
7720
7721
  ] })
7721
7722
  ] }),
7722
- items.length === 0 ? /* @__PURE__ */ jsx(Card, { className: "p-6", children: /* @__PURE__ */ jsxs(VStack, { align: "center", gap: "sm", children: [
7723
+ safeItems.length === 0 ? /* @__PURE__ */ jsx(Card, { className: "p-6", children: /* @__PURE__ */ jsxs(VStack, { align: "center", gap: "sm", children: [
7723
7724
  /* @__PURE__ */ jsx(Typography, { variant: "body", color: "muted", children: resolvedEmptyMessage }),
7724
7725
  canAdd && /* @__PURE__ */ jsxs(Button, { variant: "primary", size: "sm", onClick: handleAdd, children: [
7725
7726
  /* @__PURE__ */ jsx(Icon, { name: "plus", size: "sm", className: "mr-1" }),
7726
7727
  resolvedAddLabel
7727
7728
  ] })
7728
- ] }) }) : /* @__PURE__ */ jsx(VStack, { gap: "sm", children: items.map((item, index) => /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
7729
+ ] }) }) : /* @__PURE__ */ jsx(VStack, { gap: "sm", children: safeItems.map((item, index) => /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
7729
7730
  showAuditInfo && (item.addedInState || item.addedAt) && /* @__PURE__ */ jsxs(
7730
7731
  HStack,
7731
7732
  {
@@ -7765,7 +7766,7 @@ var RepeatableFormSection = ({
7765
7766
  )
7766
7767
  ] })
7767
7768
  ] }) }, item.id)) }),
7768
- items.length < minItems && /* @__PURE__ */ jsxs(Typography, { variant: "caption", color: "warning", children: [
7769
+ safeItems.length < minItems && /* @__PURE__ */ jsxs(Typography, { variant: "caption", color: "warning", children: [
7769
7770
  "At least ",
7770
7771
  minItems,
7771
7772
  " item",
@@ -7792,9 +7793,16 @@ var ViolationAlert = ({
7792
7793
  onDismiss,
7793
7794
  onNavigateToField,
7794
7795
  compact = false,
7795
- className
7796
+ className,
7797
+ ...flatProps
7796
7798
  }) => {
7797
- const effectiveSeverity = severity ?? (violation.actionType === "measure" ? "warning" : "error");
7799
+ const resolvedViolation = violation ?? {
7800
+ law: "",
7801
+ article: "",
7802
+ message: flatProps.message ?? "Violation",
7803
+ actionType: "measure"
7804
+ };
7805
+ const effectiveSeverity = severity ?? (resolvedViolation.actionType === "measure" ? "warning" : "error");
7798
7806
  const bgColor = effectiveSeverity === "warning" ? "bg-[var(--color-warning)]/10 border-[var(--color-warning)]/30" : "bg-[var(--color-error)]/10 border-[var(--color-error)]/30";
7799
7807
  const textColor = effectiveSeverity === "warning" ? "text-[var(--color-warning)]" : "text-[var(--color-error)]";
7800
7808
  const iconColor = effectiveSeverity === "warning" ? "text-[var(--color-warning)]" : "text-[var(--color-error)]";
@@ -7812,7 +7820,7 @@ var ViolationAlert = ({
7812
7820
  /* @__PURE__ */ jsx(
7813
7821
  Icon,
7814
7822
  {
7815
- name: actionTypeIcons[violation.actionType],
7823
+ name: actionTypeIcons[resolvedViolation.actionType],
7816
7824
  size: "sm",
7817
7825
  className: iconColor
7818
7826
  }
@@ -7824,13 +7832,13 @@ var ViolationAlert = ({
7824
7832
  className: textColor,
7825
7833
  weight: "semibold",
7826
7834
  children: [
7827
- violation.law,
7835
+ resolvedViolation.law,
7828
7836
  " Art. ",
7829
- violation.article
7837
+ resolvedViolation.article
7830
7838
  ]
7831
7839
  }
7832
7840
  ),
7833
- /* @__PURE__ */ jsx(Typography, { variant: "caption", className: textColor, children: violation.message })
7841
+ /* @__PURE__ */ jsx(Typography, { variant: "caption", className: textColor, children: resolvedViolation.message })
7834
7842
  ] }),
7835
7843
  dismissible && onDismiss && /* @__PURE__ */ jsx(
7836
7844
  Button,
@@ -7860,23 +7868,23 @@ var ViolationAlert = ({
7860
7868
  /* @__PURE__ */ jsx(
7861
7869
  Icon,
7862
7870
  {
7863
- name: actionTypeIcons[violation.actionType],
7871
+ name: actionTypeIcons[resolvedViolation.actionType],
7864
7872
  size: "md",
7865
7873
  className: iconColor
7866
7874
  }
7867
7875
  ),
7868
7876
  /* @__PURE__ */ jsxs(VStack, { gap: "xs", children: [
7869
7877
  /* @__PURE__ */ jsxs(Typography, { variant: "label", weight: "bold", className: textColor, children: [
7870
- violation.law,
7878
+ resolvedViolation.law,
7871
7879
  " Art. ",
7872
- violation.article
7880
+ resolvedViolation.article
7873
7881
  ] }),
7874
7882
  /* @__PURE__ */ jsx(
7875
7883
  Typography,
7876
7884
  {
7877
7885
  variant: "caption",
7878
7886
  className: cn(textColor, "opacity-75"),
7879
- children: actionTypeLabels[violation.actionType]
7887
+ children: actionTypeLabels[resolvedViolation.actionType]
7880
7888
  }
7881
7889
  )
7882
7890
  ] })
@@ -7892,8 +7900,8 @@ var ViolationAlert = ({
7892
7900
  }
7893
7901
  )
7894
7902
  ] }),
7895
- /* @__PURE__ */ jsx(Typography, { variant: "body2", className: textColor, children: violation.message }),
7896
- (violation.adminAction || violation.penaltyAction) && /* @__PURE__ */ jsx(
7903
+ /* @__PURE__ */ jsx(Typography, { variant: "body2", className: textColor, children: resolvedViolation.message }),
7904
+ (resolvedViolation.adminAction || resolvedViolation.penaltyAction) && /* @__PURE__ */ jsx(
7897
7905
  Box,
7898
7906
  {
7899
7907
  className: cn(
@@ -7901,7 +7909,7 @@ var ViolationAlert = ({
7901
7909
  effectiveSeverity === "warning" ? "border-[var(--color-warning)]/30" : "border-[var(--color-error)]/30"
7902
7910
  ),
7903
7911
  children: /* @__PURE__ */ jsxs(VStack, { gap: "xs", children: [
7904
- violation.adminAction && /* @__PURE__ */ jsxs(HStack, { gap: "xs", align: "center", children: [
7912
+ resolvedViolation.adminAction && /* @__PURE__ */ jsxs(HStack, { gap: "xs", align: "center", children: [
7905
7913
  /* @__PURE__ */ jsx(
7906
7914
  Typography,
7907
7915
  {
@@ -7916,11 +7924,11 @@ var ViolationAlert = ({
7916
7924
  variant: "caption",
7917
7925
  weight: "semibold",
7918
7926
  className: textColor,
7919
- children: violation.adminAction
7927
+ children: resolvedViolation.adminAction
7920
7928
  }
7921
7929
  )
7922
7930
  ] }),
7923
- violation.penaltyAction && /* @__PURE__ */ jsxs(HStack, { gap: "xs", align: "center", children: [
7931
+ resolvedViolation.penaltyAction && /* @__PURE__ */ jsxs(HStack, { gap: "xs", align: "center", children: [
7924
7932
  /* @__PURE__ */ jsx(
7925
7933
  Typography,
7926
7934
  {
@@ -7935,19 +7943,19 @@ var ViolationAlert = ({
7935
7943
  variant: "caption",
7936
7944
  weight: "semibold",
7937
7945
  className: textColor,
7938
- children: violation.penaltyAction
7946
+ children: resolvedViolation.penaltyAction
7939
7947
  }
7940
7948
  )
7941
7949
  ] })
7942
7950
  ] })
7943
7951
  }
7944
7952
  ),
7945
- violation.fieldId && onNavigateToField && /* @__PURE__ */ jsxs(
7953
+ resolvedViolation.fieldId && onNavigateToField && /* @__PURE__ */ jsxs(
7946
7954
  Button,
7947
7955
  {
7948
7956
  variant: "ghost",
7949
7957
  size: "sm",
7950
- onClick: () => onNavigateToField(violation.fieldId),
7958
+ onClick: () => onNavigateToField(resolvedViolation.fieldId),
7951
7959
  className: cn(textColor, "self-start"),
7952
7960
  children: [
7953
7961
  /* @__PURE__ */ jsx(Icon, { name: "arrow-right", size: "sm", className: "mr-1" }),
@@ -13246,6 +13254,7 @@ var SwipeableRow = ({
13246
13254
  );
13247
13255
  };
13248
13256
  SwipeableRow.displayName = "SwipeableRow";
13257
+ var EMPTY_ITEMS = [];
13249
13258
  function useSafeEventBus9() {
13250
13259
  try {
13251
13260
  return useEventBus();
@@ -13257,7 +13266,7 @@ function useSafeEventBus9() {
13257
13266
  }
13258
13267
  }
13259
13268
  function SortableListInner({
13260
- items: initialItems,
13269
+ items: initialItems = EMPTY_ITEMS,
13261
13270
  renderItem,
13262
13271
  reorderEvent,
13263
13272
  reorderPayload,
@@ -13328,7 +13337,7 @@ function SortableListInner({
13328
13337
  ),
13329
13338
  children: [
13330
13339
  dragHandlePosition === "left" && dragHandle,
13331
- /* @__PURE__ */ jsx(Box, { className: "flex-1 min-w-0", children: renderItem(item, index) }),
13340
+ /* @__PURE__ */ jsx(Box, { className: "flex-1 min-w-0", children: typeof renderItem === "function" ? renderItem(item, index) : JSON.stringify(item) }),
13332
13341
  dragHandlePosition === "right" && dragHandle
13333
13342
  ]
13334
13343
  }
@@ -22574,9 +22583,10 @@ function EventHandlerBoard({
22574
22583
  }) {
22575
22584
  const { emit } = useEventBus();
22576
22585
  const { t } = useTranslate();
22577
- const [objects, setObjects] = useState(entity.objects);
22586
+ const entityObjects = entity?.objects ?? [];
22587
+ const [objects, setObjects] = useState(entityObjects);
22578
22588
  const [selectedObjectId, setSelectedObjectId] = useState(
22579
- entity.objects[0]?.id || null
22589
+ entityObjects[0]?.id || null
22580
22590
  );
22581
22591
  const [headerError, setHeaderError] = useState(false);
22582
22592
  const [playState, setPlayState] = useState("editing");
@@ -22662,12 +22672,12 @@ function EventHandlerBoard({
22662
22672
  }, []);
22663
22673
  const handleReset = useCallback(() => {
22664
22674
  if (timerRef.current) clearTimeout(timerRef.current);
22665
- setObjects(entity.objects);
22675
+ setObjects(entity?.objects ?? []);
22666
22676
  setPlayState("editing");
22667
22677
  setEventLog([]);
22668
- setSelectedObjectId(entity.objects[0]?.id || null);
22678
+ setSelectedObjectId((entity?.objects ?? [])[0]?.id || null);
22669
22679
  setAttempts(0);
22670
- }, [entity.objects]);
22680
+ }, [entity?.objects]);
22671
22681
  const objectViewers = objects.map((obj) => {
22672
22682
  const machine = {
22673
22683
  name: obj.name,
@@ -23250,9 +23260,10 @@ function SimulatorBoard({
23250
23260
  }) {
23251
23261
  const { emit } = useEventBus();
23252
23262
  const { t } = useTranslate();
23263
+ const parameters = entity?.parameters ?? [];
23253
23264
  const [values, setValues] = useState(() => {
23254
23265
  const init = {};
23255
- for (const p2 of entity.parameters) {
23266
+ for (const p2 of parameters) {
23256
23267
  init[p2.id] = p2.initial;
23257
23268
  }
23258
23269
  return init;
@@ -23269,8 +23280,10 @@ function SimulatorBoard({
23269
23280
  return 0;
23270
23281
  }
23271
23282
  }, [entity.computeExpression]);
23272
- const output = useMemo(() => computeOutput(values), [computeOutput, values]);
23273
- const isCorrect = Math.abs(output - entity.targetValue) <= entity.targetTolerance;
23283
+ const output = useMemo(() => computeOutput(values) ?? 0, [computeOutput, values]);
23284
+ const targetValue = entity?.targetValue ?? 0;
23285
+ const targetTolerance = entity?.targetTolerance ?? 0;
23286
+ const isCorrect = Math.abs(output - targetValue) <= targetTolerance;
23274
23287
  const handleParameterChange = (id, value) => {
23275
23288
  if (submitted) return;
23276
23289
  setValues((prev) => ({ ...prev, [id]: value }));
@@ -23290,7 +23303,7 @@ function SimulatorBoard({
23290
23303
  };
23291
23304
  const handleFullReset = () => {
23292
23305
  const init = {};
23293
- for (const p2 of entity.parameters) {
23306
+ for (const p2 of parameters) {
23294
23307
  init[p2.id] = p2.initial;
23295
23308
  }
23296
23309
  setValues(init);
@@ -23315,7 +23328,7 @@ function SimulatorBoard({
23315
23328
  ] }) }),
23316
23329
  /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "md", children: [
23317
23330
  /* @__PURE__ */ jsx(Typography, { variant: "small", weight: "bold", className: "uppercase tracking-wider text-[var(--color-muted-foreground)]", children: t("simulator.parameters") }),
23318
- entity.parameters.map((param) => /* @__PURE__ */ jsxs(VStack, { gap: "xs", children: [
23331
+ parameters.map((param) => /* @__PURE__ */ jsxs(VStack, { gap: "xs", children: [
23319
23332
  /* @__PURE__ */ jsxs(HStack, { justify: "between", align: "center", children: [
23320
23333
  /* @__PURE__ */ jsx(Typography, { variant: "body", weight: "medium", children: param.label }),
23321
23334
  /* @__PURE__ */ jsxs(Badge, { size: "sm", children: [
@@ -23365,11 +23378,11 @@ function SimulatorBoard({
23365
23378
  /* @__PURE__ */ jsxs(Typography, { variant: "caption", className: "text-[var(--color-muted-foreground)]", children: [
23366
23379
  t("simulator.target"),
23367
23380
  ": ",
23368
- entity.targetValue,
23381
+ targetValue,
23369
23382
  " ",
23370
- entity.outputUnit,
23383
+ entity?.outputUnit ?? "",
23371
23384
  " (\xB1",
23372
- entity.targetTolerance,
23385
+ targetTolerance,
23373
23386
  ")"
23374
23387
  ] })
23375
23388
  ] }) }),
@@ -23401,9 +23414,11 @@ function ClassifierBoard({
23401
23414
  const [submitted, setSubmitted] = useState(false);
23402
23415
  const [attempts, setAttempts] = useState(0);
23403
23416
  const [showHint, setShowHint] = useState(false);
23404
- const unassignedItems = entity.items.filter((item) => !assignments[item.id]);
23405
- const allAssigned = Object.keys(assignments).length === entity.items.length;
23406
- const results = submitted ? entity.items.map((item) => ({
23417
+ const items = entity?.items ?? [];
23418
+ const categories = entity?.categories ?? [];
23419
+ const unassignedItems = items.filter((item) => !assignments[item.id]);
23420
+ const allAssigned = Object.keys(assignments).length === items.length;
23421
+ const results = submitted ? items.map((item) => ({
23407
23422
  item,
23408
23423
  assigned: assignments[item.id],
23409
23424
  correct: assignments[item.id] === item.correctCategory
@@ -23425,11 +23440,11 @@ function ClassifierBoard({
23425
23440
  const handleSubmit = useCallback(() => {
23426
23441
  setSubmitted(true);
23427
23442
  setAttempts((a) => a + 1);
23428
- const correct = entity.items.every((item) => assignments[item.id] === item.correctCategory);
23443
+ const correct = items.every((item) => assignments[item.id] === item.correctCategory);
23429
23444
  if (correct) {
23430
23445
  emit(`UI:${completeEvent}`, { success: true, attempts: attempts + 1 });
23431
23446
  }
23432
- }, [entity.items, assignments, attempts, completeEvent, emit]);
23447
+ }, [items, assignments, attempts, completeEvent, emit]);
23433
23448
  const handleReset = () => {
23434
23449
  setSubmitted(false);
23435
23450
  if (attempts >= 2 && entity.hint) {
@@ -23464,8 +23479,8 @@ function ClassifierBoard({
23464
23479
  item.label
23465
23480
  ] }, item.id)) })
23466
23481
  ] }) }),
23467
- /* @__PURE__ */ jsx(VStack, { gap: "md", children: entity.categories.map((cat) => {
23468
- const catItems = entity.items.filter((item) => assignments[item.id] === cat.id);
23482
+ /* @__PURE__ */ jsx(VStack, { gap: "md", children: categories.map((cat) => {
23483
+ const catItems = items.filter((item) => assignments[item.id] === cat.id);
23469
23484
  return /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
23470
23485
  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" }) }),
23471
23486
  /* @__PURE__ */ jsxs(HStack, { justify: "between", align: "center", children: [
@@ -23507,7 +23522,7 @@ function ClassifierBoard({
23507
23522
  }) }),
23508
23523
  submitted && /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", align: "center", children: [
23509
23524
  /* @__PURE__ */ jsx(Icon, { icon: allCorrect ? CheckCircle : XCircle, size: "lg", className: allCorrect ? "text-green-600" : "text-red-600" }),
23510
- /* @__PURE__ */ jsx(Typography, { variant: "body", weight: "bold", children: allCorrect ? entity.successMessage ?? t("classifier.allCorrect") : `${correctCount}/${entity.items.length} ${t("classifier.correct")}` }),
23525
+ /* @__PURE__ */ jsx(Typography, { variant: "body", weight: "bold", children: allCorrect ? entity.successMessage ?? t("classifier.allCorrect") : `${correctCount}/${items.length} ${t("classifier.correct")}` }),
23511
23526
  !allCorrect && entity.failMessage && /* @__PURE__ */ jsx(Typography, { variant: "body", className: "text-[var(--color-muted-foreground)]", children: entity.failMessage })
23512
23527
  ] }) }),
23513
23528
  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 }) }),
@@ -23538,11 +23553,13 @@ function BuilderBoard({
23538
23553
  const [submitted, setSubmitted] = useState(false);
23539
23554
  const [attempts, setAttempts] = useState(0);
23540
23555
  const [showHint, setShowHint] = useState(false);
23556
+ const components = entity?.components ?? [];
23557
+ const slots = entity?.slots ?? [];
23541
23558
  const usedComponentIds = new Set(Object.values(placements));
23542
- const availableComponents = entity.components.filter((c) => !usedComponentIds.has(c.id));
23559
+ const availableComponents = components.filter((c) => !usedComponentIds.has(c.id));
23543
23560
  const [selectedComponent, setSelectedComponent] = useState(null);
23544
- const allPlaced = Object.keys(placements).length === entity.slots.length;
23545
- const results = submitted ? entity.slots.map((slot) => ({
23561
+ const allPlaced = Object.keys(placements).length === slots.length;
23562
+ const results = submitted ? slots.map((slot) => ({
23546
23563
  slot,
23547
23564
  placed: placements[slot.id],
23548
23565
  correct: placements[slot.id] === slot.acceptsComponentId
@@ -23564,11 +23581,11 @@ function BuilderBoard({
23564
23581
  const handleSubmit = useCallback(() => {
23565
23582
  setSubmitted(true);
23566
23583
  setAttempts((a) => a + 1);
23567
- const correct = entity.slots.every((slot) => placements[slot.id] === slot.acceptsComponentId);
23584
+ const correct = slots.every((slot) => placements[slot.id] === slot.acceptsComponentId);
23568
23585
  if (correct) {
23569
23586
  emit(`UI:${completeEvent}`, { success: true, attempts: attempts + 1 });
23570
23587
  }
23571
- }, [entity.slots, placements, attempts, completeEvent, emit]);
23588
+ }, [slots, placements, attempts, completeEvent, emit]);
23572
23589
  const handleReset = () => {
23573
23590
  setSubmitted(false);
23574
23591
  if (attempts >= 2 && entity.hint) {
@@ -23582,7 +23599,7 @@ function BuilderBoard({
23582
23599
  setAttempts(0);
23583
23600
  setShowHint(false);
23584
23601
  };
23585
- const getComponentById = (id) => entity.components.find((c) => c.id === id);
23602
+ const getComponentById = (id) => components.find((c) => c.id === id);
23586
23603
  return /* @__PURE__ */ jsx(
23587
23604
  Box,
23588
23605
  {
@@ -23623,7 +23640,7 @@ function BuilderBoard({
23623
23640
  ] }) }),
23624
23641
  /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
23625
23642
  /* @__PURE__ */ jsx(Typography, { variant: "small", weight: "bold", className: "uppercase tracking-wider text-[var(--color-muted-foreground)]", children: t("builder.blueprint") }),
23626
- /* @__PURE__ */ jsx(VStack, { gap: "sm", children: entity.slots.map((slot) => {
23643
+ /* @__PURE__ */ jsx(VStack, { gap: "sm", children: slots.map((slot) => {
23627
23644
  const placedComp = placements[slot.id] ? getComponentById(placements[slot.id]) : null;
23628
23645
  const result = results.find((r) => r.slot.id === slot.id);
23629
23646
  return /* @__PURE__ */ jsxs(
@@ -23698,9 +23715,10 @@ function DebuggerBoard({
23698
23715
  return next;
23699
23716
  });
23700
23717
  };
23701
- const bugLines = entity.lines.filter((l) => l.isBug);
23702
- const correctFlags = entity.lines.filter((l) => l.isBug && flaggedLines.has(l.id));
23703
- const falseFlags = entity.lines.filter((l) => !l.isBug && flaggedLines.has(l.id));
23718
+ const lines = entity?.lines ?? [];
23719
+ const bugLines = lines.filter((l) => l.isBug);
23720
+ const correctFlags = lines.filter((l) => l.isBug && flaggedLines.has(l.id));
23721
+ const falseFlags = lines.filter((l) => !l.isBug && flaggedLines.has(l.id));
23704
23722
  const allCorrect = submitted && correctFlags.length === bugLines.length && falseFlags.length === 0;
23705
23723
  const handleSubmit = useCallback(() => {
23706
23724
  setSubmitted(true);
@@ -23741,7 +23759,7 @@ function DebuggerBoard({
23741
23759
  /* @__PURE__ */ jsx(Typography, { variant: "body", children: entity.description }),
23742
23760
  /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-[var(--color-muted-foreground)]", children: t("debugger.findBugs", { count: String(entity.bugCount) }) })
23743
23761
  ] }) }),
23744
- /* @__PURE__ */ jsx(Card, { className: "p-0 overflow-hidden", children: /* @__PURE__ */ jsx(VStack, { gap: "none", children: entity.lines.map((line, i) => {
23762
+ /* @__PURE__ */ jsx(Card, { className: "p-0 overflow-hidden", children: /* @__PURE__ */ jsx(VStack, { gap: "none", children: lines.map((line, i) => {
23745
23763
  const isFlagged = flaggedLines.has(line.id);
23746
23764
  let lineStyle = "";
23747
23765
  if (submitted) {
@@ -23833,10 +23851,12 @@ function NegotiatorBoard({
23833
23851
  const playerTotal = history.reduce((s, r) => s + r.playerPayoff, 0);
23834
23852
  const opponentTotal = history.reduce((s, r) => s + r.opponentPayoff, 0);
23835
23853
  const won = isComplete && playerTotal >= entity.targetScore;
23854
+ const actions = entity?.actions ?? [];
23855
+ const payoffMatrix = entity?.payoffMatrix ?? [];
23836
23856
  const handleAction = useCallback((actionId) => {
23837
23857
  if (isComplete) return;
23838
- const opponentAction = getOpponentAction(entity.opponentStrategy, entity.actions, history);
23839
- const payoff = entity.payoffMatrix.find(
23858
+ const opponentAction = getOpponentAction(entity.opponentStrategy, actions, history);
23859
+ const payoff = payoffMatrix.find(
23840
23860
  (p2) => p2.playerAction === actionId && p2.opponentAction === opponentAction
23841
23861
  );
23842
23862
  const result = {
@@ -23857,12 +23877,12 @@ function NegotiatorBoard({
23857
23877
  setShowHint(true);
23858
23878
  }
23859
23879
  }
23860
- }, [isComplete, entity, history, currentRound, completeEvent, emit]);
23880
+ }, [isComplete, entity, actions, payoffMatrix, history, currentRound, completeEvent, emit]);
23861
23881
  const handleReset = () => {
23862
23882
  setHistory([]);
23863
23883
  setShowHint(false);
23864
23884
  };
23865
- const getActionLabel = (id) => entity.actions.find((a) => a.id === id)?.label ?? id;
23885
+ const getActionLabel = (id) => actions.find((a) => a.id === id)?.label ?? id;
23866
23886
  return /* @__PURE__ */ jsx(
23867
23887
  Box,
23868
23888
  {
@@ -23898,7 +23918,7 @@ function NegotiatorBoard({
23898
23918
  ] }),
23899
23919
  !isComplete && /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
23900
23920
  /* @__PURE__ */ jsx(Typography, { variant: "small", weight: "bold", className: "uppercase tracking-wider text-[var(--color-muted-foreground)]", children: t("negotiator.chooseAction") }),
23901
- /* @__PURE__ */ jsx(HStack, { gap: "sm", justify: "center", className: "flex-wrap", children: entity.actions.map((action) => /* @__PURE__ */ jsx(
23921
+ /* @__PURE__ */ jsx(HStack, { gap: "sm", justify: "center", className: "flex-wrap", children: actions.map((action) => /* @__PURE__ */ jsx(
23902
23922
  Button,
23903
23923
  {
23904
23924
  variant: "primary",
@@ -25174,7 +25194,7 @@ var DashboardLayout = ({
25174
25194
  sidebarOpen && /* @__PURE__ */ jsx(
25175
25195
  Box,
25176
25196
  {
25177
- className: "fixed inset-0 bg-[var(--color-foreground)]/50 dark:bg-[var(--color-foreground)]/70 z-40 lg:hidden",
25197
+ className: "fixed inset-0 bg-[var(--color-foreground)]/50 dark:bg-[var(--color-foreground)]/70 z-20 lg:hidden",
25178
25198
  onClick: () => setSidebarOpen(false)
25179
25199
  }
25180
25200
  ),
@@ -25183,7 +25203,7 @@ var DashboardLayout = ({
25183
25203
  {
25184
25204
  as: "aside",
25185
25205
  className: cn(
25186
- "fixed inset-y-0 left-0 z-50 w-64 bg-[var(--color-card)] dark:bg-[var(--color-card)] border-r border-[var(--color-border)] dark:border-[var(--color-border)]",
25206
+ "fixed inset-y-0 left-0 z-30 w-64 bg-[var(--color-card)] dark:bg-[var(--color-card)] border-r border-[var(--color-border)] dark:border-[var(--color-border)]",
25187
25207
  "transform transition-transform duration-200 ease-in-out lg:translate-x-0",
25188
25208
  sidebarOpen ? "translate-x-0" : "-translate-x-full"
25189
25209
  ),
@@ -25262,7 +25282,7 @@ var DashboardLayout = ({
25262
25282
  Box,
25263
25283
  {
25264
25284
  as: "header",
25265
- className: "sticky top-0 z-30 h-16 bg-[var(--color-card)] dark:bg-[var(--color-card)] border-b border-[var(--color-border)] dark:border-[var(--color-border)]",
25285
+ className: "sticky top-0 z-20 h-16 bg-[var(--color-card)] dark:bg-[var(--color-card)] border-b border-[var(--color-border)] dark:border-[var(--color-border)]",
25266
25286
  children: /* @__PURE__ */ jsxs(
25267
25287
  HStack,
25268
25288
  {
@@ -25345,11 +25365,11 @@ var DashboardLayout = ({
25345
25365
  /* @__PURE__ */ jsx(
25346
25366
  Box,
25347
25367
  {
25348
- className: "fixed inset-0 z-40",
25368
+ className: "fixed inset-0 z-20",
25349
25369
  onClick: () => setUserMenuOpen(false)
25350
25370
  }
25351
25371
  ),
25352
- /* @__PURE__ */ jsxs(Box, { className: "absolute right-0 mt-2 w-48 bg-[var(--color-card)] dark:bg-[var(--color-card)] rounded-[var(--radius-lg)] shadow-[var(--shadow-lg)] border border-[var(--color-border)] dark:border-[var(--color-border)] py-1 z-50", children: [
25372
+ /* @__PURE__ */ jsxs(Box, { className: "absolute right-0 mt-2 w-48 bg-[var(--color-card)] dark:bg-[var(--color-card)] rounded-[var(--radius-lg)] shadow-[var(--shadow-lg)] border border-[var(--color-border)] dark:border-[var(--color-border)] py-1 z-30", children: [
25353
25373
  /* @__PURE__ */ jsxs(Box, { className: "px-4 py-2 border-b border-[var(--color-border)] dark:border-[var(--color-border)]", children: [
25354
25374
  /* @__PURE__ */ jsx(
25355
25375
  Typography,
@@ -25415,7 +25435,10 @@ var NavLink = ({
25415
25435
  currentPath
25416
25436
  }) => {
25417
25437
  const isActive = currentPath === item.href || currentPath.startsWith(item.href + "/");
25418
- const Icon3 = item.icon;
25438
+ const iconClassName = cn(
25439
+ "h-5 w-5",
25440
+ isActive ? "text-[var(--color-primary-foreground)]" : "text-[var(--color-muted-foreground)]"
25441
+ );
25419
25442
  return /* @__PURE__ */ jsxs(
25420
25443
  Link,
25421
25444
  {
@@ -25425,15 +25448,7 @@ var NavLink = ({
25425
25448
  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)]"
25426
25449
  ),
25427
25450
  children: [
25428
- Icon3 && /* @__PURE__ */ jsx(
25429
- Icon3,
25430
- {
25431
- className: cn(
25432
- "h-5 w-5",
25433
- isActive ? "text-[var(--color-primary-foreground)]" : "text-[var(--color-muted-foreground)]"
25434
- )
25435
- }
25436
- ),
25451
+ item.icon && (typeof item.icon === "string" ? /* @__PURE__ */ jsx(Icon, { name: item.icon, className: iconClassName }) : /* @__PURE__ */ jsx(item.icon, { className: iconClassName })),
25437
25452
  /* @__PURE__ */ jsx(
25438
25453
  Typography,
25439
25454
  {
@@ -29684,8 +29699,9 @@ var PATTERNS_WITH_CHILDREN = /* @__PURE__ */ new Set([
29684
29699
  "popover",
29685
29700
  "container",
29686
29701
  "simple-grid",
29687
- "custom"
29688
- // Custom patterns support nested children
29702
+ "custom",
29703
+ "dashboard-layout",
29704
+ "game-shell"
29689
29705
  ]);
29690
29706
  function renderContainedPortal(slot, content, onDismiss) {
29691
29707
  const slotContent = /* @__PURE__ */ jsx(SlotContentRenderer, { content, onDismiss });
@@ -30031,14 +30047,15 @@ function getToastPosition(position) {
30031
30047
  return "top-4 right-4";
30032
30048
  }
30033
30049
  }
30034
- function renderPatternChildren(children, onDismiss) {
30050
+ function renderPatternChildren(children, onDismiss, parentId = "root") {
30035
30051
  if (!children || !Array.isArray(children) || children.length === 0) {
30036
30052
  return null;
30037
30053
  }
30038
30054
  return children.map((child, index) => {
30039
30055
  if (!child || typeof child !== "object") return null;
30056
+ const childId = `${parentId}-${index}`;
30040
30057
  const childContent = {
30041
- id: `child-${index}`,
30058
+ id: childId,
30042
30059
  pattern: child.type,
30043
30060
  props: child.props ?? {},
30044
30061
  priority: 0
@@ -30049,10 +30066,34 @@ function renderPatternChildren(children, onDismiss) {
30049
30066
  content: childContent,
30050
30067
  onDismiss
30051
30068
  },
30052
- `child-${index}-${child.type}`
30069
+ childId
30053
30070
  );
30054
30071
  });
30055
30072
  }
30073
+ function isPatternConfig(value) {
30074
+ return value !== null && typeof value === "object" && !Array.isArray(value) && "type" in value && typeof value.type === "string";
30075
+ }
30076
+ function renderPatternProps(props, onDismiss) {
30077
+ const rendered = {};
30078
+ for (const [key, value] of Object.entries(props)) {
30079
+ if (key === "children") {
30080
+ rendered[key] = value;
30081
+ } else if (isPatternConfig(value)) {
30082
+ const childContent = {
30083
+ id: `prop-${key}`,
30084
+ pattern: value.type,
30085
+ props: Object.fromEntries(
30086
+ Object.entries(value).filter(([k]) => k !== "type")
30087
+ ),
30088
+ priority: 0
30089
+ };
30090
+ rendered[key] = /* @__PURE__ */ jsx(SlotContentRenderer, { content: childContent, onDismiss });
30091
+ } else {
30092
+ rendered[key] = value;
30093
+ }
30094
+ }
30095
+ return rendered;
30096
+ }
30056
30097
  function SlotContentRenderer({
30057
30098
  content,
30058
30099
  onDismiss
@@ -30061,15 +30102,16 @@ function SlotContentRenderer({
30061
30102
  if (PatternComponent) {
30062
30103
  const supportsChildren = PATTERNS_WITH_CHILDREN.has(content.pattern);
30063
30104
  const childrenConfig = content.props.children;
30064
- const renderedChildren = supportsChildren ? renderPatternChildren(childrenConfig, onDismiss) : void 0;
30105
+ const renderedChildren = supportsChildren ? renderPatternChildren(childrenConfig, onDismiss, content.id) : void 0;
30065
30106
  const { children: _childrenConfig, ...restProps } = content.props;
30107
+ const renderedProps = renderPatternProps(restProps, onDismiss);
30066
30108
  return /* @__PURE__ */ jsx(
30067
30109
  Box,
30068
30110
  {
30069
30111
  className: "slot-content",
30070
30112
  "data-pattern": content.pattern,
30071
30113
  "data-id": content.id,
30072
- children: /* @__PURE__ */ jsx(PatternComponent, { ...restProps, children: renderedChildren })
30114
+ children: /* @__PURE__ */ jsx(PatternComponent, { ...renderedProps, children: renderedChildren })
30073
30115
  }
30074
30116
  );
30075
30117
  }
@@ -1,8 +1,8 @@
1
- import { SuspenseConfigProvider } from './chunk-K43H3ZDY.js';
1
+ import { SuspenseConfigProvider } from './chunk-ACUO2BBW.js';
2
2
  import { ThemeProvider } from './chunk-DKQN5FVU.js';
3
+ import { recordTransition, registerCheck, bindEventBus, bindTraitStateGetter } from './chunk-XL7WB2O5.js';
3
4
  import { SelectionProvider, EntityDataProvider } from './chunk-CDIOHSKG.js';
4
5
  import { useEventBus, EventBusProvider } from './chunk-YXZM3WCF.js';
5
- import { recordTransition, registerCheck, bindEventBus, bindTraitStateGetter } from './chunk-XL7WB2O5.js';
6
6
  import { useOfflineExecutor } from './chunk-K2D5D3WK.js';
7
7
  import { createContext, useState, useCallback, useMemo, useContext, useRef, useEffect } from 'react';
8
8
  import { jsx, Fragment } from 'react/jsx-runtime';
@@ -1,17 +1,17 @@
1
1
  export { ENTITY_EVENTS, useAgentChat, useCompile, useConnectGitHub, useCreateEntity, useDeepAgentGeneration, useDeleteEntity, useDisconnectGitHub, useEntities, useEntitiesByType, useEntity as useEntityById, useEntityMutations, useExtensions, useFileEditor, useFileSystem, useGitHubBranches, useGitHubRepo, useGitHubRepos, useGitHubStatus, useInput, useOrbitalHistory, useOrbitalMutations, usePhysics, usePinchZoom, usePlayer, usePreview, useResolvedEntity, useSelectedEntity, useSendOrbitalEvent, useSingletonEntity, useUIEvents, useUpdateEntity, useValidation } from '../chunk-SD3KVCY6.js';
2
2
  export { clearEntities, getAllEntities, getByType, getEntity, getSingleton, removeEntity, spawnEntity, updateEntity, updateSingleton } from '../chunk-N7MVUW4R.js';
3
3
  import '../chunk-3HJHHULT.js';
4
- import { VStack, HStack, Typography, Button, Icon, Box, Card, DataTable, Badge, Toast } from '../chunk-K43H3ZDY.js';
5
- export { ALL_PRESETS, AR_BOOK_FIELDS, Accordion, ActionButton, ActionButtons, Card2 as ActionCard, ActionPalette, ActionTile, Alert, AnimatedCounter, AuthLayout, Avatar, Badge, BattleBoard, BattleTemplate, BookChapterView, BookCoverPage, BookNavBar, BookTableOfContents, BookViewer, Box, Breadcrumb, BuilderBoard, Button, ButtonGroup, CalendarGrid, CanvasEffect, Card, CardBody, CardContent, CardFooter, CardGrid, CardHeader, CardTitle, Carousel, CastleBoard, CastleTemplate, Center, Chart, ChartLegend, Checkbox, ChoiceButton, ClassifierBoard, CodeBlock, CodeView, CodeViewer, CombatLog, ComboCounter, ConditionalWrapper, ConfettiEffect, ConfirmDialog, Container, ContentRenderer, ControlButton, CounterTemplate, CraftingRecipe, DIAMOND_TOP_Y, DPad, DamageNumber, DashboardGrid, DashboardLayout, DataGrid, DataList, DataTable, DateRangeSelector, DayCell, DebuggerBoard, DetailPanel, DialogueBox, DialogueBubble, Divider, DocumentViewer, StateMachineView as DomStateMachineVisualizer, Drawer, DrawerSlot, EmptyState, EnemyPlate, EntityDisplayEvents, ErrorBoundary, ErrorState, EventHandlerBoard, EventLog, FEATURE_COLORS, FLOOR_HEIGHT, FilterGroup, Flex, FlipCard, FlipContainer, FloatingActionButton, Form, FormField, FormSectionHeader, GameAudioContext, GameAudioProvider, GameAudioToggle, GameCanvas2D, GameHud, GameMenu, GameOverScreen, GameShell, GameTemplate, GenericAppTemplate, GraphCanvas, GraphView, Grid, HStack, Header, Heading, HealthBar, HealthPanel, IDENTITY_BOOK_FIELDS, Icon, InfiniteScrollSentinel, Input, InputGroup, InventoryGrid, InventoryPanel, IsometricCanvas, ItemSlot, JazariStateMachine, Label, LawReferenceTooltip, Lightbox, LineChart, List, LoadingState, MapView, MarkdownContent, MediaGallery, Menu, Meter, MiniMap, Modal, ModalSlot, Navigation, NegotiatorBoard, NumberStepper, ObjectRulePanel, StateMachineView as OrbitalStateMachineView, OrbitalVisualization, Overlay, PageHeader, Pagination, PlatformerCanvas, Popover, PowerupSlots, ProgressBar, ProgressDots, PullToRefresh, QuestTracker, QuizBlock, Radio, RangeSlider, RelationSelect, RepeatableFormSection, ResourceBar, ResourceCounter, RuleEditor, RuntimeDebugger, ScaledDiagram, ScoreBoard, ScoreDisplay, SearchInput, Section, Select, SequenceBar, SequencerBoard, SidePanel, Sidebar, SignaturePad, SimpleGrid, SimulationCanvas, SimulationControls, SimulationGraph, SimulatorBoard, Skeleton, SlotContentRenderer, SortableList, Spacer, Spinner, Split, SplitPane, Sprite, Stack, StarRating, StatBadge, StatCard, StatDisplay, StateArchitectBoard, StateIndicator, StateMachineView, StateNode, StatusDot, StatusEffect, SwipeableRow, Switch, TILE_HEIGHT, TILE_WIDTH, TabbedContainer, Table, Tabs, Text, TextHighlight, Textarea, ThemeSelector, ThemeToggle, TimeSlotCell, Timeline, TimerDisplay, Toast, ToastSlot, Tooltip, TraitSlot, TraitStateViewer, TransitionArrow, TrendIndicator, TurnIndicator, TurnPanel, TypewriterText, Typography, UISlotComponent, UISlotRenderer, UncontrolledBattleBoard, UnitCommandBar, UploadDropZone, VStack, VariablePanel, ViolationAlert, WaypointMarker, WizardContainer, WizardNavigation, WizardProgress, WorldMapBoard, WorldMapTemplate, XPBar, drawSprite, isoToScreen, mapBookData, pendulum, projectileMotion, resolveFieldMap, screenToIso, springOscillator, useBattleState, useCamera, useGameAudio, useGameAudioContext, useImageCache } from '../chunk-K43H3ZDY.js';
4
+ import { VStack, HStack, Typography, Button, Icon, Box, Card, DataTable, Badge, Toast } from '../chunk-ACUO2BBW.js';
5
+ export { ALL_PRESETS, AR_BOOK_FIELDS, Accordion, ActionButton, ActionButtons, Card2 as ActionCard, ActionPalette, ActionTile, Alert, AnimatedCounter, AuthLayout, Avatar, Badge, BattleBoard, BattleTemplate, BookChapterView, BookCoverPage, BookNavBar, BookTableOfContents, BookViewer, Box, Breadcrumb, BuilderBoard, Button, ButtonGroup, CalendarGrid, CanvasEffect, Card, CardBody, CardContent, CardFooter, CardGrid, CardHeader, CardTitle, Carousel, CastleBoard, CastleTemplate, Center, Chart, ChartLegend, Checkbox, ChoiceButton, ClassifierBoard, CodeBlock, CodeView, CodeViewer, CombatLog, ComboCounter, ConditionalWrapper, ConfettiEffect, ConfirmDialog, Container, ContentRenderer, ControlButton, CounterTemplate, CraftingRecipe, DIAMOND_TOP_Y, DPad, DamageNumber, DashboardGrid, DashboardLayout, DataGrid, DataList, DataTable, DateRangeSelector, DayCell, DebuggerBoard, DetailPanel, DialogueBox, DialogueBubble, Divider, DocumentViewer, StateMachineView as DomStateMachineVisualizer, Drawer, DrawerSlot, EmptyState, EnemyPlate, EntityDisplayEvents, ErrorBoundary, ErrorState, EventHandlerBoard, EventLog, FEATURE_COLORS, FLOOR_HEIGHT, FilterGroup, Flex, FlipCard, FlipContainer, FloatingActionButton, Form, FormField, FormSectionHeader, GameAudioContext, GameAudioProvider, GameAudioToggle, GameCanvas2D, GameHud, GameMenu, GameOverScreen, GameShell, GameTemplate, GenericAppTemplate, GraphCanvas, GraphView, Grid, HStack, Header, Heading, HealthBar, HealthPanel, IDENTITY_BOOK_FIELDS, Icon, InfiniteScrollSentinel, Input, InputGroup, InventoryGrid, InventoryPanel, IsometricCanvas, ItemSlot, JazariStateMachine, Label, LawReferenceTooltip, Lightbox, LineChart, List, LoadingState, MapView, MarkdownContent, MediaGallery, Menu, Meter, MiniMap, Modal, ModalSlot, Navigation, NegotiatorBoard, NumberStepper, ObjectRulePanel, StateMachineView as OrbitalStateMachineView, OrbitalVisualization, Overlay, PageHeader, Pagination, PlatformerCanvas, Popover, PowerupSlots, ProgressBar, ProgressDots, PullToRefresh, QuestTracker, QuizBlock, Radio, RangeSlider, RelationSelect, RepeatableFormSection, ResourceBar, ResourceCounter, RuleEditor, RuntimeDebugger, ScaledDiagram, ScoreBoard, ScoreDisplay, SearchInput, Section, Select, SequenceBar, SequencerBoard, SidePanel, Sidebar, SignaturePad, SimpleGrid, SimulationCanvas, SimulationControls, SimulationGraph, SimulatorBoard, Skeleton, SlotContentRenderer, SortableList, Spacer, Spinner, Split, SplitPane, Sprite, Stack, StarRating, StatBadge, StatCard, StatDisplay, StateArchitectBoard, StateIndicator, StateMachineView, StateNode, StatusDot, StatusEffect, SwipeableRow, Switch, TILE_HEIGHT, TILE_WIDTH, TabbedContainer, Table, Tabs, Text, TextHighlight, Textarea, ThemeSelector, ThemeToggle, TimeSlotCell, Timeline, TimerDisplay, Toast, ToastSlot, Tooltip, TraitSlot, TraitStateViewer, TransitionArrow, TrendIndicator, TurnIndicator, TurnPanel, TypewriterText, Typography, UISlotComponent, UISlotRenderer, UncontrolledBattleBoard, UnitCommandBar, UploadDropZone, VStack, VariablePanel, ViolationAlert, WaypointMarker, WizardContainer, WizardNavigation, WizardProgress, WorldMapBoard, WorldMapTemplate, XPBar, drawSprite, isoToScreen, mapBookData, pendulum, projectileMotion, resolveFieldMap, screenToIso, springOscillator, useBattleState, useCamera, useGameAudio, useGameAudioContext, useImageCache } from '../chunk-ACUO2BBW.js';
6
6
  import '../chunk-4N3BAPDB.js';
7
7
  import '../chunk-DKQN5FVU.js';
8
+ import { cn } from '../chunk-XL7WB2O5.js';
9
+ export { cn } from '../chunk-XL7WB2O5.js';
8
10
  import { useTranslate } from '../chunk-CDIOHSKG.js';
9
11
  export { EntityDataProvider, I18nProvider, createTranslate, entityDataKeys, parseQueryBinding, useAuthContext, useDragReorder, useEntity, useEntityDataAdapter, useEntityDetail, useEntityList, useEntityListSuspense, useEntitySuspense, useInfiniteScroll, useLongPress, usePullToRefresh, useQuerySingleton, useSwipeGesture, useTranslate } from '../chunk-CDIOHSKG.js';
10
12
  import { useEventBus } from '../chunk-YXZM3WCF.js';
11
13
  export { useEmitEvent, useEventBus, useEventListener } from '../chunk-YXZM3WCF.js';
12
14
  export { DEFAULT_SLOTS, useUISlotManager } from '../chunk-3JGAROCW.js';
13
- import { cn } from '../chunk-XL7WB2O5.js';
14
- export { cn } from '../chunk-XL7WB2O5.js';
15
15
  import '../chunk-QIABKRCN.js';
16
16
  import '../chunk-K2D5D3WK.js';
17
17
  import { __publicField } from '../chunk-PKBMQBKP.js';
@@ -65,6 +65,7 @@ interface SlotContentRendererProps {
65
65
  *
66
66
  * Dynamically renders pattern components from the registry.
67
67
  * For layout patterns with `hasChildren`, recursively renders nested patterns.
68
+ * For all patterns, named props containing pattern configs are also rendered.
68
69
  */
69
70
  declare function SlotContentRenderer({ content, onDismiss, }: SlotContentRendererProps): React.ReactElement;
70
71
  export interface UISlotRendererProps {
@@ -3,7 +3,8 @@ import { LucideIcon } from "lucide-react";
3
3
  export interface NavItem {
4
4
  label: string;
5
5
  href: string;
6
- icon?: LucideIcon;
6
+ /** Lucide icon component or string icon name (resolved by @almadar/ui Icon) */
7
+ icon?: LucideIcon | string;
7
8
  badge?: string | number;
8
9
  children?: NavItem[];
9
10
  }
@@ -1,11 +1,11 @@
1
- export { FetchedDataContext, FetchedDataProvider, OfflineModeProvider, OrbitalProvider, VerificationProvider, useFetchedData, useFetchedDataContext, useFetchedEntity, useOfflineMode, useOptionalOfflineMode } from '../chunk-GF6RQBO7.js';
2
- import '../chunk-K43H3ZDY.js';
1
+ export { FetchedDataContext, FetchedDataProvider, OfflineModeProvider, OrbitalProvider, VerificationProvider, useFetchedData, useFetchedDataContext, useFetchedEntity, useOfflineMode, useOptionalOfflineMode } from '../chunk-JJHCOO34.js';
2
+ import '../chunk-ACUO2BBW.js';
3
3
  import '../chunk-4N3BAPDB.js';
4
4
  import '../chunk-DKQN5FVU.js';
5
+ import '../chunk-XL7WB2O5.js';
5
6
  export { SelectionContext, SelectionProvider, useSelection, useSelectionOptional } from '../chunk-CDIOHSKG.js';
6
7
  export { EventBusContext, EventBusProvider } from '../chunk-YXZM3WCF.js';
7
8
  import '../chunk-3JGAROCW.js';
8
- import '../chunk-XL7WB2O5.js';
9
9
  import '../chunk-QIABKRCN.js';
10
10
  import '../chunk-K2D5D3WK.js';
11
11
  import '../chunk-PKBMQBKP.js';
@@ -1,14 +1,14 @@
1
1
  import '../chunk-SD3KVCY6.js';
2
2
  import '../chunk-N7MVUW4R.js';
3
3
  import '../chunk-3HJHHULT.js';
4
- import { useFetchedDataContext } from '../chunk-GF6RQBO7.js';
5
- import '../chunk-K43H3ZDY.js';
4
+ import { useFetchedDataContext } from '../chunk-JJHCOO34.js';
5
+ import '../chunk-ACUO2BBW.js';
6
6
  import '../chunk-4N3BAPDB.js';
7
7
  import '../chunk-DKQN5FVU.js';
8
+ import { registerTrait, unregisterTrait, updateTraitState, recordTransition } from '../chunk-XL7WB2O5.js';
8
9
  import '../chunk-CDIOHSKG.js';
9
10
  import { useEventBus } from '../chunk-YXZM3WCF.js';
10
11
  import '../chunk-3JGAROCW.js';
11
- import { registerTrait, unregisterTrait, updateTraitState, recordTransition } from '../chunk-XL7WB2O5.js';
12
12
  import '../chunk-QIABKRCN.js';
13
13
  import '../chunk-K2D5D3WK.js';
14
14
  import '../chunk-PKBMQBKP.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@almadar/ui",
3
- "version": "2.15.7",
3
+ "version": "2.15.8",
4
4
  "description": "React UI components, hooks, and providers for Almadar",
5
5
  "type": "module",
6
6
  "main": "./dist/components/index.js",
@@ -2,8 +2,12 @@
2
2
  * @almadar/ui Tailwind Preset
3
3
  *
4
4
  * Provides the complete Almadar design token system as a Tailwind preset.
5
- * Includes a safelist of all CSS-variable-based arbitrary classes used by
6
- * @almadar/ui components so Tailwind generates them without scanning node_modules.
5
+ * Includes a safelist for CSS-variable-based arbitrary classes that use
6
+ * bracket notation (Tailwind can't extract these from source scanning).
7
+ *
8
+ * Note: @almadar/ui dist content scanning is handled by tailwind.config.js
9
+ * in the shell template, not here. The config resolves the dist path via
10
+ * require.resolve('@almadar/ui') which works regardless of hoisting.
7
11
  *
8
12
  * Usage in tailwind.config.js:
9
13
  * presets: [require('@almadar/ui/tailwind-preset')]
@@ -13,6 +17,18 @@
13
17
  module.exports = {
14
18
  darkMode: 'class',
15
19
  safelist: [
20
+ // Standard utilities used via dynamic className from .orb schemas
21
+ 'p-4', 'p-6', 'p-8',
22
+ 'px-4', 'px-6', 'py-4', 'py-6',
23
+ 'mx-auto',
24
+ 'w-full',
25
+ 'max-w-sm', 'max-w-md', 'max-w-lg', 'max-w-xl', 'max-w-2xl', 'max-w-3xl', 'max-w-4xl', 'max-w-5xl', 'max-w-6xl', 'max-w-7xl',
26
+ 'min-h-screen',
27
+ 'gap-1', 'gap-2', 'gap-3', 'gap-4', 'gap-6', 'gap-8',
28
+ 'grid-cols-1', 'grid-cols-2', 'grid-cols-3', 'grid-cols-4',
29
+ 'sm:grid-cols-2', 'md:grid-cols-2', 'md:grid-cols-3', 'lg:grid-cols-3', 'lg:grid-cols-4',
30
+ 'text-center', 'text-left', 'text-right',
31
+ // CSS variable-based classes from @almadar/ui components
16
32
  'accent-[var(--color-foreground)]',
17
33
  'accent-[var(--color-primary)]',
18
34
  'active:bg-[var(--color-muted)]',