@almadar/ui 5.87.0 → 5.91.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.
Files changed (27) hide show
  1. package/dist/avl/index.cjs +1510 -1426
  2. package/dist/avl/index.js +500 -416
  3. package/dist/components/game/2d/{organisms → molecules}/ObjectRulePanel.d.ts +9 -4
  4. package/dist/components/game/2d/molecules/StateGraph.d.ts +38 -0
  5. package/dist/components/game/2d/molecules/StateJsonView.d.ts +37 -0
  6. package/dist/components/game/2d/{organisms → molecules}/TraitSlot.d.ts +6 -3
  7. package/dist/components/game/2d/{organisms → molecules}/TraitStateViewer.d.ts +0 -2
  8. package/dist/components/game/2d/molecules/VariablePanel.d.ts +28 -0
  9. package/dist/components/game/2d/molecules/index.d.ts +12 -11
  10. package/dist/components/game/2d/organisms/EventHandlerBoard.d.ts +1 -1
  11. package/dist/components/game/2d/organisms/SequenceBar.d.ts +1 -1
  12. package/dist/components/game/shared/lib/puzzleObject.d.ts +1 -1
  13. package/dist/components/index.cjs +275 -189
  14. package/dist/components/index.js +275 -190
  15. package/dist/providers/index.cjs +1377 -1293
  16. package/dist/providers/index.js +476 -392
  17. package/dist/runtime/index.cjs +1371 -1287
  18. package/dist/runtime/index.js +480 -396
  19. package/package.json +1 -1
  20. package/dist/components/game/2d/organisms/StateJsonView.d.ts +0 -17
  21. package/dist/components/game/2d/organisms/VariablePanel.d.ts +0 -22
  22. /package/dist/components/game/2d/{organisms → molecules}/ActionPalette.d.ts +0 -0
  23. /package/dist/components/game/2d/{organisms → molecules}/ActionTile.d.ts +0 -0
  24. /package/dist/components/game/2d/{organisms → molecules}/EventLog.d.ts +0 -0
  25. /package/dist/components/game/2d/{organisms → molecules}/RuleEditor.d.ts +0 -0
  26. /package/dist/components/game/2d/{organisms → molecules}/StateNode.d.ts +0 -0
  27. /package/dist/components/game/2d/{organisms → molecules}/TransitionArrow.d.ts +0 -0
@@ -8148,7 +8148,7 @@ function ActionTile({
8148
8148
  }
8149
8149
  var DRAG_MIME, SIZE_CONFIG;
8150
8150
  var init_ActionTile = __esm({
8151
- "components/game/2d/organisms/ActionTile.tsx"() {
8151
+ "components/game/2d/molecules/ActionTile.tsx"() {
8152
8152
  init_atoms();
8153
8153
  init_cn();
8154
8154
  DRAG_MIME = "application/x-almadar-slot-item";
@@ -8185,7 +8185,7 @@ function ActionPalette({
8185
8185
  ] });
8186
8186
  }
8187
8187
  var init_ActionPalette = __esm({
8188
- "components/game/2d/organisms/ActionPalette.tsx"() {
8188
+ "components/game/2d/molecules/ActionPalette.tsx"() {
8189
8189
  init_atoms();
8190
8190
  init_cn();
8191
8191
  init_ActionTile();
@@ -27838,6 +27838,214 @@ var init_GameMenu = __esm({
27838
27838
  GameMenu.displayName = "GameMenu";
27839
27839
  }
27840
27840
  });
27841
+ function StateNode2({
27842
+ name,
27843
+ isCurrent = false,
27844
+ isSelected = false,
27845
+ isInitial = false,
27846
+ position,
27847
+ onClick,
27848
+ className
27849
+ }) {
27850
+ return /* @__PURE__ */ jsxRuntime.jsx(
27851
+ exports.Box,
27852
+ {
27853
+ position: "absolute",
27854
+ display: "flex",
27855
+ className: cn(
27856
+ "items-center justify-center rounded-pill border-3 transition-all cursor-pointer select-none",
27857
+ "min-w-[80px] h-[80px] px-3",
27858
+ isCurrent && "bg-primary/20 border-primary shadow-lg shadow-primary/30 scale-110",
27859
+ isSelected && !isCurrent && "bg-accent/20 border-accent ring-2 ring-accent/50",
27860
+ !isCurrent && !isSelected && "bg-card border-border hover:border-muted-foreground hover:scale-105",
27861
+ className
27862
+ ),
27863
+ style: {
27864
+ left: position.x,
27865
+ top: position.y,
27866
+ transform: "translate(-50%, -50%)"
27867
+ },
27868
+ onClick,
27869
+ children: /* @__PURE__ */ jsxRuntime.jsxs(exports.Box, { className: "text-center", children: [
27870
+ isInitial && /* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "caption", className: "text-muted-foreground text-xs block", children: "\u25B6 start" }),
27871
+ /* @__PURE__ */ jsxRuntime.jsx(
27872
+ exports.Typography,
27873
+ {
27874
+ variant: "body2",
27875
+ className: cn(
27876
+ "font-bold whitespace-nowrap",
27877
+ isCurrent ? "text-primary" : "text-foreground"
27878
+ ),
27879
+ children: name
27880
+ }
27881
+ )
27882
+ ] })
27883
+ }
27884
+ );
27885
+ }
27886
+ var init_StateNode = __esm({
27887
+ "components/game/2d/molecules/StateNode.tsx"() {
27888
+ init_atoms();
27889
+ init_cn();
27890
+ StateNode2.displayName = "StateNode";
27891
+ }
27892
+ });
27893
+ function TransitionArrow({
27894
+ from,
27895
+ to,
27896
+ eventLabel,
27897
+ guardHint,
27898
+ isActive = false,
27899
+ onClick,
27900
+ className
27901
+ }) {
27902
+ const dx = to.x - from.x;
27903
+ const dy = to.y - from.y;
27904
+ const dist = Math.sqrt(dx * dx + dy * dy);
27905
+ if (dist === 0) return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, {});
27906
+ const nx = dx / dist;
27907
+ const ny = dy / dist;
27908
+ const startX = from.x + nx * NODE_RADIUS;
27909
+ const startY = from.y + ny * NODE_RADIUS;
27910
+ const endX = to.x - nx * NODE_RADIUS;
27911
+ const endY = to.y - ny * NODE_RADIUS;
27912
+ const midX = (startX + endX) / 2;
27913
+ const midY = (startY + endY) / 2;
27914
+ const perpX = -ny * 20;
27915
+ const perpY = nx * 20;
27916
+ const ctrlX = midX + perpX;
27917
+ const ctrlY = midY + perpY;
27918
+ const path = `M ${startX} ${startY} Q ${ctrlX} ${ctrlY} ${endX} ${endY}`;
27919
+ return /* @__PURE__ */ jsxRuntime.jsxs("g", { className: cn("cursor-pointer", className), onClick, children: [
27920
+ /* @__PURE__ */ jsxRuntime.jsx(
27921
+ "path",
27922
+ {
27923
+ d: path,
27924
+ fill: "none",
27925
+ stroke: isActive ? "var(--color-primary)" : "var(--color-border)",
27926
+ strokeWidth: isActive ? 3 : 2,
27927
+ markerEnd: isActive ? "url(#arrowhead-active)" : "url(#arrowhead)"
27928
+ }
27929
+ ),
27930
+ /* @__PURE__ */ jsxRuntime.jsx(
27931
+ "text",
27932
+ {
27933
+ x: ctrlX,
27934
+ y: ctrlY - 8,
27935
+ textAnchor: "middle",
27936
+ fill: isActive ? "var(--color-primary)" : "var(--color-foreground)",
27937
+ fontSize: 12,
27938
+ fontWeight: isActive ? "bold" : "normal",
27939
+ className: "select-none",
27940
+ children: eventLabel
27941
+ }
27942
+ ),
27943
+ guardHint && /* @__PURE__ */ jsxRuntime.jsx(
27944
+ "text",
27945
+ {
27946
+ x: ctrlX,
27947
+ y: ctrlY + 6,
27948
+ textAnchor: "middle",
27949
+ fill: "var(--color-warning)",
27950
+ fontSize: 10,
27951
+ className: "select-none",
27952
+ children: "\u26A0 " + guardHint
27953
+ }
27954
+ )
27955
+ ] });
27956
+ }
27957
+ var NODE_RADIUS;
27958
+ var init_TransitionArrow = __esm({
27959
+ "components/game/2d/molecules/TransitionArrow.tsx"() {
27960
+ init_cn();
27961
+ NODE_RADIUS = 40;
27962
+ TransitionArrow.displayName = "TransitionArrow";
27963
+ }
27964
+ });
27965
+ function layoutStates(states, width, height) {
27966
+ const cx = width / 2;
27967
+ const cy = height / 2;
27968
+ const radius = Math.min(cx, cy) - 60;
27969
+ const positions = {};
27970
+ states.forEach((state, i) => {
27971
+ const angle = 2 * Math.PI * i / Math.max(states.length, 1) - Math.PI / 2;
27972
+ positions[state] = { x: cx + radius * Math.cos(angle), y: cy + radius * Math.sin(angle) };
27973
+ });
27974
+ return positions;
27975
+ }
27976
+ function StateGraph({
27977
+ states,
27978
+ transitions = [],
27979
+ currentState,
27980
+ selectedState,
27981
+ addingFrom,
27982
+ initialState,
27983
+ width = 500,
27984
+ height = 400,
27985
+ nodeClickEvent,
27986
+ className
27987
+ }) {
27988
+ const eventBus = useEventBus();
27989
+ const nodes = states ?? [];
27990
+ const positions = React74__namespace.useMemo(() => layoutStates(nodes, width, height), [nodes, width, height]);
27991
+ return /* @__PURE__ */ jsxRuntime.jsxs(
27992
+ exports.Box,
27993
+ {
27994
+ position: "relative",
27995
+ className: cn("rounded-container border border-border bg-background overflow-hidden", className),
27996
+ style: { width, height },
27997
+ children: [
27998
+ /* @__PURE__ */ jsxRuntime.jsxs("svg", { width, height, className: "absolute inset-0", style: { pointerEvents: "none" }, children: [
27999
+ /* @__PURE__ */ jsxRuntime.jsxs("defs", { children: [
28000
+ /* @__PURE__ */ jsxRuntime.jsx("marker", { id: "arrowhead", markerWidth: "10", markerHeight: "7", refX: "10", refY: "3.5", orient: "auto", children: /* @__PURE__ */ jsxRuntime.jsx("polygon", { points: "0 0, 10 3.5, 0 7", fill: "var(--color-border)" }) }),
28001
+ /* @__PURE__ */ jsxRuntime.jsx("marker", { id: "arrowhead-active", markerWidth: "10", markerHeight: "7", refX: "10", refY: "3.5", orient: "auto", children: /* @__PURE__ */ jsxRuntime.jsx("polygon", { points: "0 0, 10 3.5, 0 7", fill: "var(--color-primary)" }) })
28002
+ ] }),
28003
+ transitions.map((tr, i) => {
28004
+ const fromPos = positions[tr.from];
28005
+ const toPos = positions[tr.to];
28006
+ if (!fromPos || !toPos) return null;
28007
+ return /* @__PURE__ */ jsxRuntime.jsx(
28008
+ TransitionArrow,
28009
+ {
28010
+ from: fromPos,
28011
+ to: toPos,
28012
+ eventLabel: tr.event,
28013
+ guardHint: tr.guardHint,
28014
+ isActive: tr.from === currentState
28015
+ },
28016
+ `${tr.from}-${tr.event}-${tr.to}-${i}`
28017
+ );
28018
+ })
28019
+ ] }),
28020
+ nodes.map((state) => {
28021
+ const pos = positions[state];
28022
+ if (!pos) return null;
28023
+ return /* @__PURE__ */ jsxRuntime.jsx(
28024
+ StateNode2,
28025
+ {
28026
+ name: state,
28027
+ position: pos,
28028
+ isCurrent: state === currentState,
28029
+ isSelected: state === selectedState || state === addingFrom,
28030
+ isInitial: state === initialState,
28031
+ onClick: nodeClickEvent ? () => eventBus.emit(`UI:${nodeClickEvent}`, { stateId: state }) : void 0
28032
+ },
28033
+ state
28034
+ );
28035
+ })
28036
+ ]
28037
+ }
28038
+ );
28039
+ }
28040
+ var init_StateGraph = __esm({
28041
+ "components/game/2d/molecules/StateGraph.tsx"() {
28042
+ init_atoms();
28043
+ init_cn();
28044
+ init_useEventBus();
28045
+ init_StateNode();
28046
+ init_TransitionArrow();
28047
+ }
28048
+ });
27841
28049
  function pickPath(entry) {
27842
28050
  if (Array.isArray(entry.path)) {
27843
28051
  return entry.path[Math.floor(Math.random() * entry.path.length)];
@@ -28412,7 +28620,7 @@ function TraitStateViewer({
28412
28620
  }
28413
28621
  var SIZE_CONFIG2;
28414
28622
  var init_TraitStateViewer = __esm({
28415
- "components/game/2d/organisms/TraitStateViewer.tsx"() {
28623
+ "components/game/2d/molecules/TraitStateViewer.tsx"() {
28416
28624
  "use client";
28417
28625
  init_cn();
28418
28626
  init_Box();
@@ -28445,7 +28653,8 @@ function TraitSlot({
28445
28653
  onClick,
28446
28654
  onRemove,
28447
28655
  clickEvent,
28448
- removeEvent
28656
+ removeEvent,
28657
+ dropEvent
28449
28658
  }) {
28450
28659
  const { emit } = useEventBus();
28451
28660
  const [isHovered, setIsHovered] = React74.useState(false);
@@ -28477,29 +28686,30 @@ function TraitSlot({
28477
28686
  onDragStart?.(equippedItem);
28478
28687
  }, [equippedItem, draggable, onDragStart]);
28479
28688
  const handleDragOver = React74.useCallback((e) => {
28480
- if (locked || !onItemDrop) return;
28689
+ if (locked || !onItemDrop && !dropEvent) return;
28481
28690
  if (e.dataTransfer.types.includes(DRAG_MIME2)) {
28482
28691
  e.preventDefault();
28483
28692
  const allowed = e.dataTransfer.effectAllowed;
28484
28693
  e.dataTransfer.dropEffect = allowed === "copy" ? "copy" : "move";
28485
28694
  setIsDragOver(true);
28486
28695
  }
28487
- }, [locked, onItemDrop]);
28696
+ }, [locked, onItemDrop, dropEvent]);
28488
28697
  const handleDragLeave = React74.useCallback(() => {
28489
28698
  setIsDragOver(false);
28490
28699
  }, []);
28491
28700
  const handleDrop = React74.useCallback((e) => {
28492
28701
  e.preventDefault();
28493
28702
  setIsDragOver(false);
28494
- if (locked || !onItemDrop) return;
28703
+ if (locked || !onItemDrop && !dropEvent) return;
28495
28704
  const raw = e.dataTransfer.getData(DRAG_MIME2);
28496
28705
  if (!raw) return;
28497
28706
  try {
28498
28707
  const item = JSON.parse(raw);
28499
- onItemDrop(item);
28708
+ if (dropEvent) emit(`UI:${dropEvent}`, { slotNumber, itemId: item.id });
28709
+ else onItemDrop?.(item);
28500
28710
  } catch {
28501
28711
  }
28502
- }, [locked, onItemDrop]);
28712
+ }, [locked, onItemDrop, dropEvent, emit, slotNumber]);
28503
28713
  const getTooltipStyle = () => {
28504
28714
  if (!slotRef.current) return {};
28505
28715
  const rect = slotRef.current.getBoundingClientRect();
@@ -28619,7 +28829,7 @@ function TraitSlot({
28619
28829
  }
28620
28830
  var SIZE_CONFIG3, DRAG_MIME2;
28621
28831
  var init_TraitSlot = __esm({
28622
- "components/game/2d/organisms/TraitSlot.tsx"() {
28832
+ "components/game/2d/molecules/TraitSlot.tsx"() {
28623
28833
  "use client";
28624
28834
  init_cn();
28625
28835
  init_useEventBus();
@@ -29189,7 +29399,7 @@ function RuleEditor({
29189
29399
  ] });
29190
29400
  }
29191
29401
  var init_RuleEditor = __esm({
29192
- "components/game/2d/organisms/RuleEditor.tsx"() {
29402
+ "components/game/2d/molecules/RuleEditor.tsx"() {
29193
29403
  init_atoms();
29194
29404
  init_cn();
29195
29405
  RuleEditor.displayName = "RuleEditor";
@@ -29230,7 +29440,7 @@ function EventLog({
29230
29440
  }
29231
29441
  var STATUS_STYLES, STATUS_DOTS;
29232
29442
  var init_EventLog = __esm({
29233
- "components/game/2d/organisms/EventLog.tsx"() {
29443
+ "components/game/2d/molecules/EventLog.tsx"() {
29234
29444
  init_atoms();
29235
29445
  init_cn();
29236
29446
  STATUS_STYLES = {
@@ -29285,10 +29495,12 @@ var init_puzzleObject = __esm({
29285
29495
  function ObjectRulePanel({
29286
29496
  object,
29287
29497
  onRulesChange,
29498
+ rulesChangeEvent,
29288
29499
  disabled = false,
29289
29500
  className
29290
29501
  }) {
29291
29502
  const { t } = hooks.useTranslate();
29503
+ const { emit } = useEventBus();
29292
29504
  const id = objId(object);
29293
29505
  const name = objName(object);
29294
29506
  const icon = objIcon(object);
@@ -29299,15 +29511,19 @@ function ObjectRulePanel({
29299
29511
  const rules = objRules(object);
29300
29512
  const maxRules = objMaxRules(object);
29301
29513
  const canAdd = rules.length < maxRules;
29514
+ const emitRules = React74.useCallback((newRules) => {
29515
+ if (rulesChangeEvent) emit(`UI:${rulesChangeEvent}`, { objectId: id, rules: newRules });
29516
+ else onRulesChange?.(id, newRules);
29517
+ }, [rulesChangeEvent, emit, id, onRulesChange]);
29302
29518
  const handleRuleChange = React74.useCallback((index, updatedRule) => {
29303
29519
  const newRules = [...rules];
29304
29520
  newRules[index] = updatedRule;
29305
- onRulesChange(id, newRules);
29306
- }, [id, rules, onRulesChange]);
29521
+ emitRules(newRules);
29522
+ }, [rules, emitRules]);
29307
29523
  const handleRuleRemove = React74.useCallback((index) => {
29308
29524
  const newRules = rules.filter((_, i) => i !== index);
29309
- onRulesChange(id, newRules);
29310
- }, [id, rules, onRulesChange]);
29525
+ emitRules(newRules);
29526
+ }, [rules, emitRules]);
29311
29527
  const handleAddRule = React74.useCallback(() => {
29312
29528
  if (!canAdd || disabled) return;
29313
29529
  const firstEvent = availableEvents[0]?.value || "";
@@ -29317,8 +29533,8 @@ function ObjectRulePanel({
29317
29533
  whenEvent: firstEvent,
29318
29534
  thenAction: firstAction
29319
29535
  };
29320
- onRulesChange(id, [...rules, newRule]);
29321
- }, [canAdd, disabled, id, rules, availableEvents, availableActions, onRulesChange]);
29536
+ emitRules([...rules, newRule]);
29537
+ }, [canAdd, disabled, rules, availableEvents, availableActions, emitRules]);
29322
29538
  const machine = {
29323
29539
  name,
29324
29540
  states,
@@ -29358,9 +29574,10 @@ function ObjectRulePanel({
29358
29574
  }
29359
29575
  var nextRuleId;
29360
29576
  var init_ObjectRulePanel = __esm({
29361
- "components/game/2d/organisms/ObjectRulePanel.tsx"() {
29577
+ "components/game/2d/molecules/ObjectRulePanel.tsx"() {
29362
29578
  init_atoms();
29363
29579
  init_cn();
29580
+ init_useEventBus();
29364
29581
  init_TraitStateViewer();
29365
29582
  init_RuleEditor();
29366
29583
  init_puzzleObject();
@@ -29582,130 +29799,6 @@ var init_EventHandlerBoard = __esm({
29582
29799
  EventHandlerBoard.displayName = "EventHandlerBoard";
29583
29800
  }
29584
29801
  });
29585
- function StateNode2({
29586
- name,
29587
- isCurrent = false,
29588
- isSelected = false,
29589
- isInitial = false,
29590
- position,
29591
- onClick,
29592
- className
29593
- }) {
29594
- return /* @__PURE__ */ jsxRuntime.jsx(
29595
- exports.Box,
29596
- {
29597
- position: "absolute",
29598
- display: "flex",
29599
- className: cn(
29600
- "items-center justify-center rounded-pill border-3 transition-all cursor-pointer select-none",
29601
- "min-w-[80px] h-[80px] px-3",
29602
- isCurrent && "bg-primary/20 border-primary shadow-lg shadow-primary/30 scale-110",
29603
- isSelected && !isCurrent && "bg-accent/20 border-accent ring-2 ring-accent/50",
29604
- !isCurrent && !isSelected && "bg-card border-border hover:border-muted-foreground hover:scale-105",
29605
- className
29606
- ),
29607
- style: {
29608
- left: position.x,
29609
- top: position.y,
29610
- transform: "translate(-50%, -50%)"
29611
- },
29612
- onClick,
29613
- children: /* @__PURE__ */ jsxRuntime.jsxs(exports.Box, { className: "text-center", children: [
29614
- isInitial && /* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "caption", className: "text-muted-foreground text-xs block", children: "\u25B6 start" }),
29615
- /* @__PURE__ */ jsxRuntime.jsx(
29616
- exports.Typography,
29617
- {
29618
- variant: "body2",
29619
- className: cn(
29620
- "font-bold whitespace-nowrap",
29621
- isCurrent ? "text-primary" : "text-foreground"
29622
- ),
29623
- children: name
29624
- }
29625
- )
29626
- ] })
29627
- }
29628
- );
29629
- }
29630
- var init_StateNode = __esm({
29631
- "components/game/2d/organisms/StateNode.tsx"() {
29632
- init_atoms();
29633
- init_cn();
29634
- StateNode2.displayName = "StateNode";
29635
- }
29636
- });
29637
- function TransitionArrow({
29638
- from,
29639
- to,
29640
- eventLabel,
29641
- guardHint,
29642
- isActive = false,
29643
- onClick,
29644
- className
29645
- }) {
29646
- const dx = to.x - from.x;
29647
- const dy = to.y - from.y;
29648
- const dist = Math.sqrt(dx * dx + dy * dy);
29649
- if (dist === 0) return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, {});
29650
- const nx = dx / dist;
29651
- const ny = dy / dist;
29652
- const startX = from.x + nx * NODE_RADIUS;
29653
- const startY = from.y + ny * NODE_RADIUS;
29654
- const endX = to.x - nx * NODE_RADIUS;
29655
- const endY = to.y - ny * NODE_RADIUS;
29656
- const midX = (startX + endX) / 2;
29657
- const midY = (startY + endY) / 2;
29658
- const perpX = -ny * 20;
29659
- const perpY = nx * 20;
29660
- const ctrlX = midX + perpX;
29661
- const ctrlY = midY + perpY;
29662
- const path = `M ${startX} ${startY} Q ${ctrlX} ${ctrlY} ${endX} ${endY}`;
29663
- return /* @__PURE__ */ jsxRuntime.jsxs("g", { className: cn("cursor-pointer", className), onClick, children: [
29664
- /* @__PURE__ */ jsxRuntime.jsx(
29665
- "path",
29666
- {
29667
- d: path,
29668
- fill: "none",
29669
- stroke: isActive ? "var(--color-primary)" : "var(--color-border)",
29670
- strokeWidth: isActive ? 3 : 2,
29671
- markerEnd: isActive ? "url(#arrowhead-active)" : "url(#arrowhead)"
29672
- }
29673
- ),
29674
- /* @__PURE__ */ jsxRuntime.jsx(
29675
- "text",
29676
- {
29677
- x: ctrlX,
29678
- y: ctrlY - 8,
29679
- textAnchor: "middle",
29680
- fill: isActive ? "var(--color-primary)" : "var(--color-foreground)",
29681
- fontSize: 12,
29682
- fontWeight: isActive ? "bold" : "normal",
29683
- className: "select-none",
29684
- children: eventLabel
29685
- }
29686
- ),
29687
- guardHint && /* @__PURE__ */ jsxRuntime.jsx(
29688
- "text",
29689
- {
29690
- x: ctrlX,
29691
- y: ctrlY + 6,
29692
- textAnchor: "middle",
29693
- fill: "var(--color-warning)",
29694
- fontSize: 10,
29695
- className: "select-none",
29696
- children: "\u26A0 " + guardHint
29697
- }
29698
- )
29699
- ] });
29700
- }
29701
- var NODE_RADIUS;
29702
- var init_TransitionArrow = __esm({
29703
- "components/game/2d/organisms/TransitionArrow.tsx"() {
29704
- init_cn();
29705
- NODE_RADIUS = 40;
29706
- TransitionArrow.displayName = "TransitionArrow";
29707
- }
29708
- });
29709
29802
  function VariablePanel({
29710
29803
  entityName,
29711
29804
  variables,
@@ -29714,61 +29807,35 @@ function VariablePanel({
29714
29807
  const { t } = hooks.useTranslate();
29715
29808
  return /* @__PURE__ */ jsxRuntime.jsxs(exports.VStack, { className: cn("p-3 rounded-lg bg-card border border-border", className), gap: "sm", children: [
29716
29809
  /* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "body2", className: "text-muted-foreground font-medium", children: t("stateArchitect.variables", { name: entityName }) }),
29717
- variables.map((v) => {
29718
- const name = v.name == null ? "" : String(v.name);
29719
- const value = numField(v.value);
29720
- const max = numField(v.max, 100);
29721
- const min = numField(v.min, 0);
29722
- const unit = v.unit == null ? "" : String(v.unit);
29723
- const pct = Math.round((value - min) / (max - min) * 100);
29724
- const isHigh = pct > 80;
29725
- const isLow = pct < 20;
29726
- return /* @__PURE__ */ jsxRuntime.jsxs(exports.VStack, { gap: "none", children: [
29727
- /* @__PURE__ */ jsxRuntime.jsxs(exports.HStack, { className: "items-center justify-between", children: [
29728
- /* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "caption", className: "text-foreground font-medium", children: name }),
29729
- /* @__PURE__ */ jsxRuntime.jsxs(exports.Typography, { variant: "caption", className: cn(
29730
- isHigh ? "text-error" : isLow ? "text-warning" : "text-foreground"
29731
- ), children: [
29732
- value,
29733
- unit,
29734
- " / ",
29735
- max,
29736
- unit
29737
- ] })
29738
- ] }),
29739
- /* @__PURE__ */ jsxRuntime.jsx(
29740
- exports.ProgressBar,
29741
- {
29742
- value: pct,
29743
- color: isHigh ? "danger" : isLow ? "warning" : "primary",
29744
- size: "sm"
29745
- }
29746
- )
29747
- ] }, name);
29748
- })
29810
+ (variables ?? []).map((v) => /* @__PURE__ */ jsxRuntime.jsxs(exports.HStack, { className: "items-center justify-between", children: [
29811
+ /* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "caption", className: "text-foreground font-medium", children: v.name }),
29812
+ /* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "caption", className: "text-accent font-mono", children: v.value })
29813
+ ] }, v.name))
29749
29814
  ] });
29750
29815
  }
29751
- var numField;
29752
29816
  var init_VariablePanel = __esm({
29753
- "components/game/2d/organisms/VariablePanel.tsx"() {
29817
+ "components/game/2d/molecules/VariablePanel.tsx"() {
29754
29818
  init_atoms();
29755
29819
  init_cn();
29756
- numField = (v, fallback = 0) => {
29757
- const n = Number(v);
29758
- return Number.isFinite(n) ? n : fallback;
29759
- };
29760
29820
  VariablePanel.displayName = "VariablePanel";
29761
29821
  }
29762
29822
  });
29763
29823
  function StateJsonView({
29764
- data,
29824
+ name,
29825
+ initialState,
29826
+ states,
29827
+ transitions,
29765
29828
  label,
29766
29829
  defaultExpanded = false,
29767
29830
  className
29768
29831
  }) {
29769
29832
  const { t } = hooks.useTranslate();
29770
29833
  const [expanded, setExpanded] = React74.useState(defaultExpanded);
29771
- const jsonString = JSON.stringify(data, null, 2);
29834
+ const jsonString = JSON.stringify(
29835
+ { name, initialState, states: states ?? [], transitions: transitions ?? [] },
29836
+ null,
29837
+ 2
29838
+ );
29772
29839
  return /* @__PURE__ */ jsxRuntime.jsxs(exports.VStack, { className: cn("rounded-lg border border-border overflow-hidden", className), gap: "none", children: [
29773
29840
  /* @__PURE__ */ jsxRuntime.jsxs(exports.HStack, { className: "items-center justify-between p-2 bg-muted", gap: "sm", children: [
29774
29841
  /* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "caption", className: "text-muted-foreground font-medium", children: label ?? t("stateArchitect.viewCode") }),
@@ -29785,13 +29852,13 @@ function StateJsonView({
29785
29852
  ] });
29786
29853
  }
29787
29854
  var init_StateJsonView = __esm({
29788
- "components/game/2d/organisms/StateJsonView.tsx"() {
29855
+ "components/game/2d/molecules/StateJsonView.tsx"() {
29789
29856
  init_atoms();
29790
29857
  init_cn();
29791
29858
  StateJsonView.displayName = "StateJsonView";
29792
29859
  }
29793
29860
  });
29794
- function layoutStates(states, width, height) {
29861
+ function layoutStates2(states, width, height) {
29795
29862
  const cx = width / 2;
29796
29863
  const cy = height / 2;
29797
29864
  const radius = Math.min(cx, cy) - 60;
@@ -29859,7 +29926,7 @@ function StateArchitectBoard({
29859
29926
  }, []);
29860
29927
  const GRAPH_W = 500;
29861
29928
  const GRAPH_H = 400;
29862
- const positions = React74.useMemo(() => layoutStates(entityStates, GRAPH_W, GRAPH_H), [entityStates]);
29929
+ const positions = React74.useMemo(() => layoutStates2(entityStates, GRAPH_W, GRAPH_H), [entityStates]);
29863
29930
  const handleStateClick = React74.useCallback((state) => {
29864
29931
  if (isTesting) return;
29865
29932
  if (addingFrom) {
@@ -29954,7 +30021,7 @@ function StateArchitectBoard({
29954
30021
  setAddingFrom(null);
29955
30022
  if (playAgainEvent) emit(`UI:${playAgainEvent}`, {});
29956
30023
  }, [initialState, entityVariables, playAgainEvent, emit]);
29957
- const codeData = React74.useMemo(() => ({
30024
+ React74.useMemo(() => ({
29958
30025
  name: entityName,
29959
30026
  states: entityStates,
29960
30027
  initialState,
@@ -30089,7 +30156,7 @@ function StateArchitectBoard({
30089
30156
  VariablePanel,
30090
30157
  {
30091
30158
  entityName,
30092
- variables
30159
+ variables: variables.map((v) => ({ name: String(v.name ?? ""), value: String(v.value ?? "") }))
30093
30160
  }
30094
30161
  ),
30095
30162
  testResults.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(exports.VStack, { className: "p-3 rounded-container bg-card border border-border", gap: "xs", children: [
@@ -30100,7 +30167,16 @@ function StateArchitectBoard({
30100
30167
  !r.passed && /* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "caption", className: "text-error", children: t("stateArchitect.gotState", { state: r.actualState }) })
30101
30168
  ] }, i))
30102
30169
  ] }),
30103
- resolved.showCodeView !== false && /* @__PURE__ */ jsxRuntime.jsx(StateJsonView, { data: codeData, label: "View Code" })
30170
+ resolved.showCodeView !== false && /* @__PURE__ */ jsxRuntime.jsx(
30171
+ StateJsonView,
30172
+ {
30173
+ name: entityName,
30174
+ initialState,
30175
+ states: entityStates,
30176
+ transitions: transitions.map((tr) => ({ from: tr.from, to: tr.to, event: tr.event })),
30177
+ label: "View Code"
30178
+ }
30179
+ )
30104
30180
  ] })
30105
30181
  ] }),
30106
30182
  isSuccess && /* @__PURE__ */ jsxRuntime.jsx(exports.Box, { className: "p-4 rounded-container bg-success/20 border border-success text-center", children: /* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "h5", className: "text-success", children: str(resolved.successMessage) || t("stateArchitect.allPassed") }) }),
@@ -31305,6 +31381,7 @@ var init_molecules = __esm({
31305
31381
  init_ResourceBar();
31306
31382
  init_GameHud();
31307
31383
  init_GameMenu();
31384
+ init_StateGraph();
31308
31385
  init_Canvas2D();
31309
31386
  init_useUnitSpriteAtlas();
31310
31387
  init_GameAudioProvider();
@@ -47946,6 +48023,7 @@ var init_component_registry_generated = __esm({
47946
48023
  init_Navigation();
47947
48024
  init_NegotiatorBoard();
47948
48025
  init_NumberStepper();
48026
+ init_ObjectRulePanel();
47949
48027
  init_OptionConstraintGroup();
47950
48028
  init_OrbitalVisualization();
47951
48029
  init_Overlay();
@@ -48007,7 +48085,9 @@ var init_component_registry_generated = __esm({
48007
48085
  init_StatCard();
48008
48086
  init_StatDisplay();
48009
48087
  init_StateArchitectBoard();
48088
+ init_StateGraph();
48010
48089
  init_StateIndicator();
48090
+ init_StateJsonView();
48011
48091
  init_StateMachineView();
48012
48092
  init_StatsGrid();
48013
48093
  init_StatsOrganism();
@@ -48054,6 +48134,7 @@ var init_component_registry_generated = __esm({
48054
48134
  init_Typography();
48055
48135
  init_UISlotRenderer();
48056
48136
  init_UploadDropZone();
48137
+ init_VariablePanel();
48057
48138
  init_VersionDiff();
48058
48139
  init_ViolationAlert();
48059
48140
  init_VoteStack();
@@ -48254,6 +48335,7 @@ var init_component_registry_generated = __esm({
48254
48335
  "Navigation": exports.Navigation,
48255
48336
  "NegotiatorBoard": NegotiatorBoard,
48256
48337
  "NumberStepper": exports.NumberStepper,
48338
+ "ObjectRulePanel": ObjectRulePanel,
48257
48339
  "OptionConstraintGroup": exports.OptionConstraintGroup,
48258
48340
  "OrbitalVisualization": exports.OrbitalVisualization,
48259
48341
  "Overlay": exports.Overlay,
@@ -48318,7 +48400,9 @@ var init_component_registry_generated = __esm({
48318
48400
  "StatCard": exports.StatCard,
48319
48401
  "StatDisplay": exports.StatDisplay,
48320
48402
  "StateArchitectBoard": StateArchitectBoard,
48403
+ "StateGraph": StateGraph,
48321
48404
  "StateIndicator": StateIndicator,
48405
+ "StateJsonView": StateJsonView,
48322
48406
  "StateMachineView": exports.StateMachineView,
48323
48407
  "StatsGrid": exports.StatsGrid,
48324
48408
  "StatsOrganism": exports.StatsOrganism,
@@ -48366,6 +48450,7 @@ var init_component_registry_generated = __esm({
48366
48450
  "UISlotRenderer": UISlotRenderer,
48367
48451
  "UploadDropZone": exports.UploadDropZone,
48368
48452
  "VStack": exports.VStack,
48453
+ "VariablePanel": VariablePanel,
48369
48454
  "VersionDiff": exports.VersionDiff,
48370
48455
  "ViolationAlert": exports.ViolationAlert,
48371
48456
  "VoteStack": exports.VoteStack,
@@ -51675,6 +51760,7 @@ exports.SlotContentRenderer = SlotContentRenderer;
51675
51760
  exports.Sprite = Sprite;
51676
51761
  exports.StatBadge = StatBadge;
51677
51762
  exports.StateArchitectBoard = StateArchitectBoard;
51763
+ exports.StateGraph = StateGraph;
51678
51764
  exports.StateIndicator = StateIndicator;
51679
51765
  exports.StateJsonView = StateJsonView;
51680
51766
  exports.StateNode = StateNode2;