@almadar/ui 5.101.0 → 5.104.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.
- package/dist/avl/index.cjs +253 -49
- package/dist/avl/index.css +3 -3
- package/dist/avl/index.js +255 -51
- package/dist/components/core/atoms/AtlasImage.d.ts +2 -2
- package/dist/components/core/atoms/FlipContainer.d.ts +1 -1
- package/dist/components/core/molecules/Card.d.ts +1 -1
- package/dist/components/core/molecules/Chart.d.ts +3 -3
- package/dist/components/core/molecules/DataGrid.d.ts +1 -1
- package/dist/components/core/molecules/DataList.d.ts +1 -1
- package/dist/components/core/molecules/DocPagination.d.ts +8 -1
- package/dist/components/core/molecules/DocSearch.d.ts +8 -1
- package/dist/components/core/molecules/FlipCard.d.ts +1 -1
- package/dist/components/core/molecules/LineChart.d.ts +3 -1
- package/dist/components/core/molecules/MapView.d.ts +18 -1
- package/dist/components/core/molecules/SortableList.d.ts +1 -1
- package/dist/components/core/molecules/TableView.d.ts +1 -1
- package/dist/components/core/organisms/DataTable.d.ts +7 -3
- package/dist/components/core/organisms/debug/RuntimeDebugger.d.ts +10 -1
- package/dist/components/core/organisms/debug/tabs/EntitiesTab.d.ts +2 -1
- package/dist/components/core/organisms/debug/tabs/EventDispatcherTab.d.ts +2 -1
- package/dist/components/core/organisms/debug/tabs/EventFlowTab.d.ts +6 -1
- package/dist/components/core/organisms/debug/tabs/GuardsPanel.d.ts +6 -1
- package/dist/components/core/organisms/debug/tabs/ServerBridgeTab.d.ts +12 -1
- package/dist/components/core/organisms/debug/tabs/TicksTab.d.ts +2 -1
- package/dist/components/core/organisms/debug/tabs/TraitsTab.d.ts +2 -1
- package/dist/components/core/organisms/debug/tabs/TransitionTimeline.d.ts +11 -1
- package/dist/components/core/organisms/debug/tabs/VerificationTab.d.ts +8 -1
- package/dist/components/game/2d/atoms/ActionButton.d.ts +2 -1
- package/dist/components/game/2d/atoms/ChoiceButton.d.ts +2 -1
- package/dist/components/game/2d/atoms/ComboCounter.d.ts +2 -1
- package/dist/components/game/2d/atoms/ControlButton.d.ts +2 -1
- package/dist/components/game/2d/atoms/DamageNumber.d.ts +2 -1
- package/dist/components/game/2d/atoms/DialogueBubble.d.ts +2 -1
- package/dist/components/game/2d/atoms/GameIcon.d.ts +2 -1
- package/dist/components/game/2d/atoms/HealthBar.d.ts +2 -1
- package/dist/components/game/2d/atoms/ItemSlot.d.ts +2 -1
- package/dist/components/game/2d/atoms/MiniMap.d.ts +2 -1
- package/dist/components/game/2d/atoms/ResourceCounter.d.ts +2 -1
- package/dist/components/game/2d/atoms/ScoreDisplay.d.ts +2 -1
- package/dist/components/game/2d/atoms/StatusEffect.d.ts +2 -1
- package/dist/components/game/2d/atoms/TimerDisplay.d.ts +2 -1
- package/dist/components/game/2d/atoms/TurnIndicator.d.ts +2 -1
- package/dist/components/game/2d/atoms/WaypointMarker.d.ts +2 -1
- package/dist/components/game/2d/molecules/Canvas2D.d.ts +5 -4
- package/dist/components/game/2d/molecules/GameHud.d.ts +2 -1
- package/dist/components/game/2d/molecules/GameMenu.d.ts +2 -1
- package/dist/components/game/2d/molecules/InventoryGrid.d.ts +2 -1
- package/dist/components/game/2d/molecules/ResourceBar.d.ts +2 -1
- package/dist/components/game/2d/molecules/StatBadge.d.ts +2 -1
- package/dist/components/game/shared/lib/editorUtils.d.ts +8 -8
- package/dist/components/index.cjs +100 -24
- package/dist/components/index.css +3 -3
- package/dist/components/index.js +85 -13
- package/dist/hooks/index.cjs +71 -0
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/index.js +69 -2
- package/dist/hooks/useGitHub.d.ts +7 -7
- package/dist/hooks/useSharedEntityStore.d.ts +53 -0
- package/dist/hooks/useTraitStateMachine.d.ts +32 -1
- package/dist/marketing/index.cjs +2 -2
- package/dist/marketing/index.js +2 -2
- package/dist/providers/EventBusProvider.d.ts +1 -1
- package/dist/providers/SelectionProvider.d.ts +1 -1
- package/dist/providers/ServerBridge.d.ts +1 -1
- package/dist/providers/index.cjs +11 -5
- package/dist/providers/index.css +3 -3
- package/dist/providers/index.js +11 -5
- package/dist/runtime/index.cjs +253 -49
- package/dist/runtime/index.css +3 -3
- package/dist/runtime/index.js +255 -51
- package/package.json +11 -16
package/dist/runtime/index.cjs
CHANGED
|
@@ -7730,7 +7730,7 @@ function recordTransition(trace) {
|
|
|
7730
7730
|
...trace,
|
|
7731
7731
|
id: `t-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`
|
|
7732
7732
|
};
|
|
7733
|
-
|
|
7733
|
+
log4.debug("transition:recorded", { trait: trace.traitName, from: trace.from, to: trace.to, event: trace.event, effectCount: trace.effects.length });
|
|
7734
7734
|
getState().transitions.push(entry);
|
|
7735
7735
|
if (getState().transitions.length > MAX_TRANSITIONS) {
|
|
7736
7736
|
getState().transitions.shift();
|
|
@@ -7832,7 +7832,7 @@ function getTraitSnapshots() {
|
|
|
7832
7832
|
try {
|
|
7833
7833
|
snapshots.push(getter());
|
|
7834
7834
|
} catch (err) {
|
|
7835
|
-
|
|
7835
|
+
log4.error("traitSnapshot getter failed", { trait: traitName, err: String(err) });
|
|
7836
7836
|
}
|
|
7837
7837
|
}
|
|
7838
7838
|
return snapshots;
|
|
@@ -7931,10 +7931,10 @@ function updateAssetStatus(url, status) {
|
|
|
7931
7931
|
window.__orbitalVerification.assetStatus[url] = status;
|
|
7932
7932
|
}
|
|
7933
7933
|
}
|
|
7934
|
-
var
|
|
7934
|
+
var log4, MAX_TRANSITIONS;
|
|
7935
7935
|
var init_verificationRegistry = __esm({
|
|
7936
7936
|
"lib/verificationRegistry.ts"() {
|
|
7937
|
-
|
|
7937
|
+
log4 = logger.createLogger("almadar:bridge");
|
|
7938
7938
|
MAX_TRANSITIONS = 500;
|
|
7939
7939
|
exposeOnWindow();
|
|
7940
7940
|
}
|
|
@@ -10595,6 +10595,9 @@ var init_useUnitSpriteAtlas = __esm({
|
|
|
10595
10595
|
init_spriteAnimation();
|
|
10596
10596
|
}
|
|
10597
10597
|
});
|
|
10598
|
+
function normalizeBackdrop(bg) {
|
|
10599
|
+
return typeof bg === "string" ? { url: bg, role: "decoration", category: "background" } : bg;
|
|
10600
|
+
}
|
|
10598
10601
|
function SideView({
|
|
10599
10602
|
player,
|
|
10600
10603
|
platforms,
|
|
@@ -10604,7 +10607,7 @@ function SideView({
|
|
|
10604
10607
|
canvasHeight,
|
|
10605
10608
|
follow,
|
|
10606
10609
|
bgColor,
|
|
10607
|
-
backgroundImage,
|
|
10610
|
+
backgroundImage: backgroundImageRaw,
|
|
10608
10611
|
playerSprite,
|
|
10609
10612
|
tileSprites,
|
|
10610
10613
|
effects,
|
|
@@ -10612,6 +10615,7 @@ function SideView({
|
|
|
10612
10615
|
keyUpMap,
|
|
10613
10616
|
className
|
|
10614
10617
|
}) {
|
|
10618
|
+
const backgroundImage = normalizeBackdrop(backgroundImageRaw);
|
|
10615
10619
|
const canvasRef = React96.useRef(null);
|
|
10616
10620
|
const eventBus = useEventBus();
|
|
10617
10621
|
const keysRef = React96.useRef(/* @__PURE__ */ new Set());
|
|
@@ -10903,7 +10907,7 @@ function Canvas2D({
|
|
|
10903
10907
|
effects: _effectsPropRaw = [],
|
|
10904
10908
|
platforms,
|
|
10905
10909
|
player,
|
|
10906
|
-
backgroundImage,
|
|
10910
|
+
backgroundImage: backgroundImageRaw,
|
|
10907
10911
|
// Interaction state
|
|
10908
10912
|
selectedUnitId = null,
|
|
10909
10913
|
validMoves = [],
|
|
@@ -10944,6 +10948,7 @@ function Canvas2D({
|
|
|
10944
10948
|
// Remote asset loading
|
|
10945
10949
|
assetManifest
|
|
10946
10950
|
}) {
|
|
10951
|
+
const backgroundImage = normalizeBackdrop(backgroundImageRaw);
|
|
10947
10952
|
const isSide = projection === "side";
|
|
10948
10953
|
const isFree = projection === "free";
|
|
10949
10954
|
const flatLike = projection === "hex" || projection === "flat" || isFree;
|
|
@@ -17542,7 +17547,7 @@ var init_avl_elk_layout = __esm({
|
|
|
17542
17547
|
elk = new ELK__default.default();
|
|
17543
17548
|
}
|
|
17544
17549
|
});
|
|
17545
|
-
var
|
|
17550
|
+
var log5, SWIM_GUTTER, CENTER_W, BehaviorView;
|
|
17546
17551
|
var init_BehaviorView = __esm({
|
|
17547
17552
|
"components/avl/molecules/BehaviorView.tsx"() {
|
|
17548
17553
|
"use client";
|
|
@@ -17551,7 +17556,7 @@ var init_BehaviorView = __esm({
|
|
|
17551
17556
|
init_AvlSwimLane();
|
|
17552
17557
|
init_avl_atom_types();
|
|
17553
17558
|
init_avl_elk_layout();
|
|
17554
|
-
|
|
17559
|
+
log5 = logger.createLogger("almadar:ui:avl:behavior-view");
|
|
17555
17560
|
SWIM_GUTTER = 120;
|
|
17556
17561
|
CENTER_W = 360;
|
|
17557
17562
|
BehaviorView = ({ data }) => {
|
|
@@ -17562,7 +17567,7 @@ var init_BehaviorView = __esm({
|
|
|
17562
17567
|
const dataKey = React96.useMemo(() => JSON.stringify(traitData), [traitData]);
|
|
17563
17568
|
React96.useEffect(() => {
|
|
17564
17569
|
if (!traitData) return;
|
|
17565
|
-
computeTraitLayout(traitData).then(setLayout).catch((err) =>
|
|
17570
|
+
computeTraitLayout(traitData).then(setLayout).catch((err) => log5.error("compute-trait-layout-failed", { error: err instanceof Error ? err : String(err) }));
|
|
17566
17571
|
}, [dataKey]);
|
|
17567
17572
|
if (!traitData) {
|
|
17568
17573
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-lg border border-[var(--color-border)] bg-[var(--color-card)] p-4 text-center text-[var(--color-muted-foreground)] text-sm", children: t("avl.noTraitData") });
|
|
@@ -17754,9 +17759,9 @@ var init_BiologyCanvas = __esm({
|
|
|
17754
17759
|
}
|
|
17755
17760
|
});
|
|
17756
17761
|
|
|
17757
|
-
// node_modules/katex/dist/katex.min.css
|
|
17762
|
+
// node_modules/.pnpm/katex@0.16.47/node_modules/katex/dist/katex.min.css
|
|
17758
17763
|
var init_katex_min = __esm({
|
|
17759
|
-
"node_modules/katex/dist/katex.min.css"() {
|
|
17764
|
+
"node_modules/.pnpm/katex@0.16.47/node_modules/katex/dist/katex.min.css"() {
|
|
17760
17765
|
}
|
|
17761
17766
|
});
|
|
17762
17767
|
var Tabs;
|
|
@@ -18114,7 +18119,7 @@ function generateDiff(oldVal, newVal) {
|
|
|
18114
18119
|
}
|
|
18115
18120
|
return diff;
|
|
18116
18121
|
}
|
|
18117
|
-
var orbStyleOverrides, orbStyle, loloStyleOverrides, loloStyle,
|
|
18122
|
+
var orbStyleOverrides, orbStyle, loloStyleOverrides, loloStyle, log6, CODE_LANGUAGES, CODE_LANGUAGE_SET, DIFF_STYLES, DIFF_STYLE_FALLBACK, LINE_PROPS_FN, HIDDEN_LINE_NUMBERS, CodeBlock;
|
|
18118
18123
|
var init_CodeBlock = __esm({
|
|
18119
18124
|
"components/core/molecules/markdown/CodeBlock.tsx"() {
|
|
18120
18125
|
init_cn();
|
|
@@ -18197,7 +18202,7 @@ var init_CodeBlock = __esm({
|
|
|
18197
18202
|
"lolo-op-async": { color: syntax.ORB_COLORS.dark.async }
|
|
18198
18203
|
};
|
|
18199
18204
|
loloStyle = { ...dark__default.default, ...loloStyleOverrides };
|
|
18200
|
-
|
|
18205
|
+
log6 = logger.createLogger("almadar:ui:markdown-code");
|
|
18201
18206
|
CODE_LANGUAGES = [
|
|
18202
18207
|
"text",
|
|
18203
18208
|
"json",
|
|
@@ -18465,7 +18470,7 @@ var init_CodeBlock = __esm({
|
|
|
18465
18470
|
eventBus.emit("UI:COPY_CODE", { language: activeLanguage, success: true });
|
|
18466
18471
|
setTimeout(() => setCopied(false), 2e3);
|
|
18467
18472
|
} catch (err) {
|
|
18468
|
-
|
|
18473
|
+
log6.error("Failed to copy code", { error: err instanceof Error ? err : String(err) });
|
|
18469
18474
|
eventBus.emit("UI:COPY_CODE", { language: activeLanguage, success: false });
|
|
18470
18475
|
}
|
|
18471
18476
|
};
|
|
@@ -27330,14 +27335,14 @@ function useSafeEventBus3() {
|
|
|
27330
27335
|
} };
|
|
27331
27336
|
}
|
|
27332
27337
|
}
|
|
27333
|
-
var
|
|
27338
|
+
var log7, lookStyles5, ButtonGroup;
|
|
27334
27339
|
var init_ButtonGroup = __esm({
|
|
27335
27340
|
"components/core/molecules/ButtonGroup.tsx"() {
|
|
27336
27341
|
"use client";
|
|
27337
27342
|
init_cn();
|
|
27338
27343
|
init_atoms();
|
|
27339
27344
|
init_useEventBus();
|
|
27340
|
-
|
|
27345
|
+
log7 = logger.createLogger("almadar:ui:button-group");
|
|
27341
27346
|
lookStyles5 = {
|
|
27342
27347
|
"right-aligned-buttons": "",
|
|
27343
27348
|
"floating-bar": "fixed bottom-section left-1/2 -translate-x-1/2 shadow-elevation-toast bg-card p-card-sm rounded-container",
|
|
@@ -27418,7 +27423,7 @@ var init_ButtonGroup = __esm({
|
|
|
27418
27423
|
{
|
|
27419
27424
|
variant: "ghost",
|
|
27420
27425
|
onClick: () => {
|
|
27421
|
-
|
|
27426
|
+
log7.debug("Filter clicked", { field: filter.field });
|
|
27422
27427
|
},
|
|
27423
27428
|
children: filter.label
|
|
27424
27429
|
},
|
|
@@ -28327,9 +28332,9 @@ function debug(...args) {
|
|
|
28327
28332
|
const [first, ...rest] = args;
|
|
28328
28333
|
const message = typeof first === "string" ? first : "<debug>";
|
|
28329
28334
|
if (rest.length === 0 && typeof first === "string") {
|
|
28330
|
-
|
|
28335
|
+
log8.debug(message);
|
|
28331
28336
|
} else {
|
|
28332
|
-
|
|
28337
|
+
log8.debug(message, { args: rest.length > 0 ? formatArgs(rest) : formatArgs([first]) });
|
|
28333
28338
|
}
|
|
28334
28339
|
}
|
|
28335
28340
|
function debugGroup(label) {
|
|
@@ -28357,11 +28362,11 @@ function toLogMetaValue(v) {
|
|
|
28357
28362
|
}
|
|
28358
28363
|
return String(v);
|
|
28359
28364
|
}
|
|
28360
|
-
var NAMESPACE,
|
|
28365
|
+
var NAMESPACE, log8;
|
|
28361
28366
|
var init_debug = __esm({
|
|
28362
28367
|
"lib/debug.ts"() {
|
|
28363
28368
|
NAMESPACE = "almadar:ui:debug";
|
|
28364
|
-
|
|
28369
|
+
log8 = logger.createLogger(NAMESPACE);
|
|
28365
28370
|
logger.createLogger("almadar:ui:debug:input");
|
|
28366
28371
|
logger.createLogger("almadar:ui:debug:collision");
|
|
28367
28372
|
logger.createLogger("almadar:ui:debug:physics");
|
|
@@ -29767,8 +29772,9 @@ var init_LineChart = __esm({
|
|
|
29767
29772
|
const safeData = data ?? [];
|
|
29768
29773
|
const sortedData = React96.useMemo(() => {
|
|
29769
29774
|
if (safeData.length === 0) return [];
|
|
29775
|
+
if (!safeData.some((d) => d.date != null)) return [...safeData];
|
|
29770
29776
|
return [...safeData].sort(
|
|
29771
|
-
(a, b) => new Date(a.date).getTime() - new Date(b.date).getTime()
|
|
29777
|
+
(a, b) => new Date(a.date ?? 0).getTime() - new Date(b.date ?? 0).getTime()
|
|
29772
29778
|
);
|
|
29773
29779
|
}, [safeData]);
|
|
29774
29780
|
const points = React96.useMemo(() => {
|
|
@@ -30519,12 +30525,12 @@ var init_MapView = __esm({
|
|
|
30519
30525
|
shadowSize: [41, 41]
|
|
30520
30526
|
});
|
|
30521
30527
|
L.Marker.prototype.options.icon = defaultIcon;
|
|
30522
|
-
const { useEffect: useEffect67, useRef:
|
|
30528
|
+
const { useEffect: useEffect67, useRef: useRef66, useCallback: useCallback98, useState: useState97 } = React96__namespace.default;
|
|
30523
30529
|
const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
|
|
30524
30530
|
const { useEventBus: useEventBus2 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
|
|
30525
30531
|
function MapUpdater({ centerLat, centerLng, zoom }) {
|
|
30526
30532
|
const map = useMap();
|
|
30527
|
-
const prevRef =
|
|
30533
|
+
const prevRef = useRef66({ centerLat, centerLng, zoom });
|
|
30528
30534
|
useEffect67(() => {
|
|
30529
30535
|
const prev = prevRef.current;
|
|
30530
30536
|
if (prev.centerLat !== centerLat || prev.centerLng !== centerLng || prev.zoom !== zoom) {
|
|
@@ -43786,7 +43792,7 @@ function getAllEvents(traits2) {
|
|
|
43786
43792
|
function EventDispatcherTab({ traits: traits2, schema }) {
|
|
43787
43793
|
const eventBus = useEventBus();
|
|
43788
43794
|
const { t } = hooks.useTranslate();
|
|
43789
|
-
const [
|
|
43795
|
+
const [log10, setLog] = React96__namespace.useState([]);
|
|
43790
43796
|
const prevStatesRef = React96__namespace.useRef(/* @__PURE__ */ new Map());
|
|
43791
43797
|
React96__namespace.useEffect(() => {
|
|
43792
43798
|
for (const trait of traits2) {
|
|
@@ -43850,9 +43856,9 @@ function EventDispatcherTab({ traits: traits2, schema }) {
|
|
|
43850
43856
|
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "small", weight: "medium", className: "text-gray-500 mb-1", children: t("debug.otherEvents") }),
|
|
43851
43857
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap gap-1", children: unavailableEvents.map((event) => /* @__PURE__ */ jsxRuntime.jsx(Badge, { variant: "default", size: "sm", className: "opacity-50", children: event }, event)) })
|
|
43852
43858
|
] }),
|
|
43853
|
-
|
|
43859
|
+
log10.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
43854
43860
|
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "small", weight: "medium", className: "text-gray-500 mb-1", children: t("debug.recentTransitions") }),
|
|
43855
|
-
/* @__PURE__ */ jsxRuntime.jsx(Stack, { gap: "xs", children:
|
|
43861
|
+
/* @__PURE__ */ jsxRuntime.jsx(Stack, { gap: "xs", children: log10.map((entry, i) => /* @__PURE__ */ jsxRuntime.jsxs(Typography, { variant: "small", className: "font-mono text-xs", children: [
|
|
43856
43862
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-purple-400", children: entry.traitName }),
|
|
43857
43863
|
" ",
|
|
43858
43864
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-gray-500", children: entry.from }),
|
|
@@ -47562,7 +47568,67 @@ var init_UISlotRenderer = __esm({
|
|
|
47562
47568
|
|
|
47563
47569
|
// hooks/index.ts
|
|
47564
47570
|
init_useEventBus();
|
|
47565
|
-
var log2 = logger.createLogger("almadar:ui:
|
|
47571
|
+
var log2 = logger.createLogger("almadar:ui:shared-entity-store");
|
|
47572
|
+
var EMPTY_ENTITY_STATE = {};
|
|
47573
|
+
function createSharedEntityStore() {
|
|
47574
|
+
const states = /* @__PURE__ */ new Map();
|
|
47575
|
+
const subscribers2 = /* @__PURE__ */ new Map();
|
|
47576
|
+
const getSnapshot3 = (entityId) => states.get(entityId) ?? EMPTY_ENTITY_STATE;
|
|
47577
|
+
const subscribe2 = (entityId, callback) => {
|
|
47578
|
+
let set = subscribers2.get(entityId);
|
|
47579
|
+
if (!set) {
|
|
47580
|
+
set = /* @__PURE__ */ new Set();
|
|
47581
|
+
subscribers2.set(entityId, set);
|
|
47582
|
+
}
|
|
47583
|
+
set.add(callback);
|
|
47584
|
+
return () => {
|
|
47585
|
+
const current = subscribers2.get(entityId);
|
|
47586
|
+
if (!current) return;
|
|
47587
|
+
current.delete(callback);
|
|
47588
|
+
if (current.size === 0) {
|
|
47589
|
+
subscribers2.delete(entityId);
|
|
47590
|
+
}
|
|
47591
|
+
};
|
|
47592
|
+
};
|
|
47593
|
+
const commit = (entityId, nextState) => {
|
|
47594
|
+
states.set(entityId, nextState);
|
|
47595
|
+
const set = subscribers2.get(entityId);
|
|
47596
|
+
if (!set) return;
|
|
47597
|
+
set.forEach((callback) => {
|
|
47598
|
+
try {
|
|
47599
|
+
callback();
|
|
47600
|
+
} catch (error) {
|
|
47601
|
+
log2.error("Shared entity subscriber error", {
|
|
47602
|
+
entityId,
|
|
47603
|
+
error: error instanceof Error ? error : String(error)
|
|
47604
|
+
});
|
|
47605
|
+
}
|
|
47606
|
+
});
|
|
47607
|
+
};
|
|
47608
|
+
const seed = (entityId, initialState) => {
|
|
47609
|
+
if (!states.has(entityId)) {
|
|
47610
|
+
states.set(entityId, initialState);
|
|
47611
|
+
}
|
|
47612
|
+
};
|
|
47613
|
+
return { getSnapshot: getSnapshot3, subscribe: subscribe2, commit, seed };
|
|
47614
|
+
}
|
|
47615
|
+
function useSharedEntityStore() {
|
|
47616
|
+
const storeRef = React96.useRef(null);
|
|
47617
|
+
if (storeRef.current === null) {
|
|
47618
|
+
storeRef.current = createSharedEntityStore();
|
|
47619
|
+
}
|
|
47620
|
+
return storeRef.current;
|
|
47621
|
+
}
|
|
47622
|
+
function runTickFrame(entityId, orderedWriters, store) {
|
|
47623
|
+
let scratch = store.getSnapshot(entityId);
|
|
47624
|
+
for (const writer of orderedWriters) {
|
|
47625
|
+
const writes = writer(scratch);
|
|
47626
|
+
scratch = core.mergeEntityFrame(scratch, writes);
|
|
47627
|
+
}
|
|
47628
|
+
store.commit(entityId, scratch);
|
|
47629
|
+
return scratch;
|
|
47630
|
+
}
|
|
47631
|
+
var log3 = logger.createLogger("almadar:ui:effects:client-handlers");
|
|
47566
47632
|
function createClientEffectHandlers(options) {
|
|
47567
47633
|
const { eventBus, slotSetter, navigate, notify, callService, liveEntity } = options;
|
|
47568
47634
|
return {
|
|
@@ -47571,12 +47637,12 @@ function createClientEffectHandlers(options) {
|
|
|
47571
47637
|
eventBus.emit(prefixedEvent, payload);
|
|
47572
47638
|
},
|
|
47573
47639
|
persist: async () => {
|
|
47574
|
-
|
|
47640
|
+
log3.warn("persist is server-side only, ignored on client");
|
|
47575
47641
|
},
|
|
47576
47642
|
// @almadar/runtime EffectHandlers.set types value:unknown — should be FieldValue (upstream fix queued)
|
|
47577
47643
|
set: ((_entityId, field, value) => {
|
|
47578
47644
|
if (!liveEntity) {
|
|
47579
|
-
|
|
47645
|
+
log3.warn("set is server-side only, ignored on client (no live entity)");
|
|
47580
47646
|
return;
|
|
47581
47647
|
}
|
|
47582
47648
|
liveEntity[field] = value;
|
|
@@ -47608,10 +47674,10 @@ function createClientEffectHandlers(options) {
|
|
|
47608
47674
|
slotSetter.addPattern(slot, pattern, props);
|
|
47609
47675
|
},
|
|
47610
47676
|
navigate: navigate ?? ((path) => {
|
|
47611
|
-
|
|
47677
|
+
log3.warn("No navigate handler, ignoring", { path });
|
|
47612
47678
|
}),
|
|
47613
47679
|
notify: notify ?? ((msg, type) => {
|
|
47614
|
-
|
|
47680
|
+
log3.debug("notify", { type, message: msg });
|
|
47615
47681
|
})
|
|
47616
47682
|
};
|
|
47617
47683
|
}
|
|
@@ -47782,11 +47848,101 @@ function toTraitDefinition(binding) {
|
|
|
47782
47848
|
function normalizeEventKey(eventKey) {
|
|
47783
47849
|
return eventKey.startsWith("UI:") ? eventKey.slice(3) : eventKey;
|
|
47784
47850
|
}
|
|
47851
|
+
var SHARED_ENTITY_WRITE_OPS = /* @__PURE__ */ new Set(["set"]);
|
|
47852
|
+
var SHARED_ENTITY_RENDER_OPS = /* @__PURE__ */ new Set(["render-ui", "render"]);
|
|
47853
|
+
function collectAllTraitEffects(trait) {
|
|
47854
|
+
return [
|
|
47855
|
+
...trait.ticks.flatMap((t) => t.effects),
|
|
47856
|
+
...trait.transitions.flatMap((t) => t.effects)
|
|
47857
|
+
];
|
|
47858
|
+
}
|
|
47859
|
+
function effectsCallOp(effects, ops) {
|
|
47860
|
+
for (const effect of effects) {
|
|
47861
|
+
let found = false;
|
|
47862
|
+
core.walkSExpr(effect, (node) => {
|
|
47863
|
+
if (!found && Array.isArray(node) && typeof node[0] === "string" && ops.has(node[0])) {
|
|
47864
|
+
found = true;
|
|
47865
|
+
}
|
|
47866
|
+
});
|
|
47867
|
+
if (found) return true;
|
|
47868
|
+
}
|
|
47869
|
+
return false;
|
|
47870
|
+
}
|
|
47871
|
+
function createSharedEntityWriter(binding, tick, traitStatesRef, emit) {
|
|
47872
|
+
return (scratch) => {
|
|
47873
|
+
const traitName = binding.trait.name;
|
|
47874
|
+
const currentState = traitStatesRef.current.get(traitName)?.currentState ?? "";
|
|
47875
|
+
if (tick.appliesTo.length > 0 && !tick.appliesTo.includes(currentState)) return [];
|
|
47876
|
+
const scratchEntity = { ...scratch };
|
|
47877
|
+
const writes = [];
|
|
47878
|
+
const ctx = evaluator.createMinimalContext(scratchEntity, {}, currentState);
|
|
47879
|
+
const declaredDefaults = runtime.collectDeclaredConfigDefaults(binding.trait);
|
|
47880
|
+
const callSiteConfig = binding.config;
|
|
47881
|
+
if (declaredDefaults || callSiteConfig) {
|
|
47882
|
+
ctx.config = { ...declaredDefaults ?? {}, ...callSiteConfig ?? {} };
|
|
47883
|
+
}
|
|
47884
|
+
ctx.mutateEntity = (changes) => {
|
|
47885
|
+
for (const [field, value] of Object.entries(changes)) {
|
|
47886
|
+
const fieldValue = value;
|
|
47887
|
+
scratchEntity[field] = fieldValue;
|
|
47888
|
+
writes.push({ field, value: fieldValue });
|
|
47889
|
+
}
|
|
47890
|
+
};
|
|
47891
|
+
ctx.emit = (event, payload) => {
|
|
47892
|
+
emit(event, payload);
|
|
47893
|
+
};
|
|
47894
|
+
if (tick.guard !== void 0 && !evaluator.evaluateGuard(tick.guard, ctx)) {
|
|
47895
|
+
tickLog.debug("guard-blocked", { traitName, tick: tick.name, state: currentState });
|
|
47896
|
+
return [];
|
|
47897
|
+
}
|
|
47898
|
+
evaluator.executeEffects(tick.effects, ctx);
|
|
47899
|
+
return writes;
|
|
47900
|
+
};
|
|
47901
|
+
}
|
|
47785
47902
|
function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
47786
47903
|
const eventBus = useEventBus();
|
|
47787
47904
|
const { entities } = providers.useEntitySchema();
|
|
47788
47905
|
const traitConfigsByName = options?.traitConfigsByName;
|
|
47789
47906
|
const orbitalsByTrait = options?.orbitalsByTrait;
|
|
47907
|
+
const sharedEntityStore = useSharedEntityStore();
|
|
47908
|
+
const sharedGroups = React96.useMemo(() => {
|
|
47909
|
+
const groups = /* @__PURE__ */ new Map();
|
|
47910
|
+
for (const binding of traitBindings) {
|
|
47911
|
+
const linkedEntityName = binding.linkedEntity ?? binding.trait.linkedEntity;
|
|
47912
|
+
if (!linkedEntityName) continue;
|
|
47913
|
+
const entityDef = entities.get(linkedEntityName);
|
|
47914
|
+
if (!entityDef?.shared) continue;
|
|
47915
|
+
const orbitalName = orbitalsByTrait?.[binding.trait.name] ?? "";
|
|
47916
|
+
const storeKey = `${orbitalName}::${linkedEntityName}`;
|
|
47917
|
+
let group = groups.get(storeKey);
|
|
47918
|
+
if (!group) {
|
|
47919
|
+
let defaults;
|
|
47920
|
+
for (const field of entityDef.fields) {
|
|
47921
|
+
if (field.default !== void 0) {
|
|
47922
|
+
(defaults ?? (defaults = {}))[field.name] = field.default;
|
|
47923
|
+
}
|
|
47924
|
+
}
|
|
47925
|
+
group = { storeKey, entityName: linkedEntityName, writerBindings: [], renderBindings: [], defaults };
|
|
47926
|
+
groups.set(storeKey, group);
|
|
47927
|
+
}
|
|
47928
|
+
const allEffects = collectAllTraitEffects(binding.trait);
|
|
47929
|
+
if (effectsCallOp(allEffects, SHARED_ENTITY_WRITE_OPS)) group.writerBindings.push(binding);
|
|
47930
|
+
if (effectsCallOp(allEffects, SHARED_ENTITY_RENDER_OPS)) group.renderBindings.push(binding);
|
|
47931
|
+
}
|
|
47932
|
+
return groups;
|
|
47933
|
+
}, [traitBindings, entities, orbitalsByTrait]);
|
|
47934
|
+
for (const group of sharedGroups.values()) {
|
|
47935
|
+
if (group.defaults) sharedEntityStore.seed(group.storeKey, group.defaults);
|
|
47936
|
+
}
|
|
47937
|
+
const sharedKeyByTraitNameRef = React96.useRef(/* @__PURE__ */ new Map());
|
|
47938
|
+
React96.useEffect(() => {
|
|
47939
|
+
const map = /* @__PURE__ */ new Map();
|
|
47940
|
+
for (const group of sharedGroups.values()) {
|
|
47941
|
+
for (const binding of group.writerBindings) map.set(binding.trait.name, group.storeKey);
|
|
47942
|
+
for (const binding of group.renderBindings) map.set(binding.trait.name, group.storeKey);
|
|
47943
|
+
}
|
|
47944
|
+
sharedKeyByTraitNameRef.current = map;
|
|
47945
|
+
}, [sharedGroups]);
|
|
47790
47946
|
const manager = React96.useMemo(() => {
|
|
47791
47947
|
const traitDefs = traitBindings.map(toTraitDefinition);
|
|
47792
47948
|
const m = new runtime.StateMachineManager(traitDefs);
|
|
@@ -47969,14 +48125,21 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
47969
48125
|
};
|
|
47970
48126
|
}, [traitBindings]);
|
|
47971
48127
|
const executeTransitionEffects = React96.useCallback(async (params) => {
|
|
47972
|
-
const { binding, previousState, newState, payload, flushEvent, syncOnly, log:
|
|
48128
|
+
const { binding, previousState, newState, payload, flushEvent, syncOnly, log: log10 } = params;
|
|
47973
48129
|
const traitName = binding.trait.name;
|
|
47974
48130
|
const linkedEntity = binding.linkedEntity || "";
|
|
47975
48131
|
const entityId = payload?.entityId;
|
|
47976
|
-
|
|
47977
|
-
|
|
47978
|
-
|
|
47979
|
-
|
|
48132
|
+
const sharedKey = sharedKeyByTraitNameRef.current.get(traitName);
|
|
48133
|
+
let liveEntity;
|
|
48134
|
+
if (sharedKey !== void 0) {
|
|
48135
|
+
liveEntity = { ...sharedEntityStore.getSnapshot(sharedKey) };
|
|
48136
|
+
} else {
|
|
48137
|
+
let existing = traitFieldStatesRef.current.get(traitName);
|
|
48138
|
+
if (!existing) {
|
|
48139
|
+
existing = {};
|
|
48140
|
+
traitFieldStatesRef.current.set(traitName, existing);
|
|
48141
|
+
}
|
|
48142
|
+
liveEntity = existing;
|
|
47980
48143
|
}
|
|
47981
48144
|
const effects = syncOnly ? params.effects.filter(
|
|
47982
48145
|
(e) => Array.isArray(e) && SYNC_TICK_OPERATORS.has(String(e[0]))
|
|
@@ -48058,7 +48221,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
48058
48221
|
...handlers,
|
|
48059
48222
|
set: async (targetId, field, value) => {
|
|
48060
48223
|
if (baseSet) await baseSet(targetId, field, value);
|
|
48061
|
-
|
|
48224
|
+
log10.debug("set:write", {
|
|
48062
48225
|
traitName,
|
|
48063
48226
|
field,
|
|
48064
48227
|
value: JSON.stringify(value),
|
|
@@ -48098,17 +48261,20 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
48098
48261
|
const executor = new runtime.EffectExecutor({ handlers: trackingHandlers, bindings: bindingCtx, context: effectContext });
|
|
48099
48262
|
try {
|
|
48100
48263
|
await executor.executeAll(effects);
|
|
48101
|
-
|
|
48264
|
+
if (sharedKey !== void 0) {
|
|
48265
|
+
sharedEntityStore.commit(sharedKey, liveEntity);
|
|
48266
|
+
}
|
|
48267
|
+
log10.debug("effects:executed", () => ({
|
|
48102
48268
|
traitName,
|
|
48103
48269
|
transition: `${previousState}->${newState}`,
|
|
48104
48270
|
event: flushEvent,
|
|
48105
48271
|
effectCount: effects.length,
|
|
48106
48272
|
emitted: emittedDuringExec.join(","),
|
|
48107
|
-
entityAfter: JSON.stringify(
|
|
48273
|
+
entityAfter: JSON.stringify(liveEntity ?? {}),
|
|
48108
48274
|
slotsTouched: Array.from(pendingSlots.keys()).join(",")
|
|
48109
48275
|
}));
|
|
48110
48276
|
for (const [slot, patterns] of pendingSlots) {
|
|
48111
|
-
|
|
48277
|
+
log10.debug("flush:slot", {
|
|
48112
48278
|
traitName,
|
|
48113
48279
|
slot,
|
|
48114
48280
|
patternCount: patterns.length,
|
|
@@ -48123,7 +48289,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
48123
48289
|
});
|
|
48124
48290
|
}
|
|
48125
48291
|
} catch (error) {
|
|
48126
|
-
|
|
48292
|
+
log10.error("effects:error", {
|
|
48127
48293
|
traitName,
|
|
48128
48294
|
transition: `${previousState}->${newState}`,
|
|
48129
48295
|
event: flushEvent,
|
|
@@ -48132,14 +48298,16 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
48132
48298
|
});
|
|
48133
48299
|
}
|
|
48134
48300
|
return emittedDuringExec;
|
|
48135
|
-
}, [eventBus, flushSlot]);
|
|
48301
|
+
}, [eventBus, flushSlot, sharedEntityStore]);
|
|
48136
48302
|
const runTickEffects = React96.useCallback((tick, binding) => {
|
|
48137
48303
|
const traitName = binding.trait.name;
|
|
48138
48304
|
const currentState = traitStatesRef.current.get(traitName)?.currentState ?? "";
|
|
48139
48305
|
if (tick.appliesTo.length > 0 && !tick.appliesTo.includes(currentState)) return;
|
|
48140
48306
|
if (tick.guard !== void 0) {
|
|
48307
|
+
const sharedKey = sharedKeyByTraitNameRef.current.get(traitName);
|
|
48308
|
+
const entity = sharedKey !== void 0 ? sharedEntityStore.getSnapshot(sharedKey) : traitFieldStatesRef.current.get(traitName) ?? {};
|
|
48141
48309
|
const guardCtx = {
|
|
48142
|
-
entity
|
|
48310
|
+
entity,
|
|
48143
48311
|
payload: {},
|
|
48144
48312
|
state: currentState
|
|
48145
48313
|
};
|
|
@@ -48164,10 +48332,46 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
48164
48332
|
syncOnly: true,
|
|
48165
48333
|
log: tickLog
|
|
48166
48334
|
});
|
|
48167
|
-
}, [executeTransitionEffects]);
|
|
48335
|
+
}, [executeTransitionEffects, sharedEntityStore]);
|
|
48336
|
+
const emitFromSharedWriter = React96.useCallback((event, payload) => {
|
|
48337
|
+
const prefixedEvent = event.startsWith("UI:") ? event : `UI:${event}`;
|
|
48338
|
+
eventBus.emit(prefixedEvent, payload);
|
|
48339
|
+
}, [eventBus]);
|
|
48168
48340
|
React96.useEffect(() => {
|
|
48169
48341
|
const scheduler = runtime.createTickScheduler();
|
|
48342
|
+
const writerTraitNames = /* @__PURE__ */ new Set();
|
|
48343
|
+
for (const group of sharedGroups.values()) {
|
|
48344
|
+
const ticksByInterval = /* @__PURE__ */ new Map();
|
|
48345
|
+
for (const binding of group.writerBindings) {
|
|
48346
|
+
writerTraitNames.add(binding.trait.name);
|
|
48347
|
+
for (const tick of binding.trait.ticks ?? []) {
|
|
48348
|
+
const intervalKey = String(tick.interval);
|
|
48349
|
+
const entries = ticksByInterval.get(intervalKey) ?? [];
|
|
48350
|
+
entries.push({ binding, tick });
|
|
48351
|
+
ticksByInterval.set(intervalKey, entries);
|
|
48352
|
+
}
|
|
48353
|
+
}
|
|
48354
|
+
for (const entries of ticksByInterval.values()) {
|
|
48355
|
+
const interval = entries[0].tick.interval;
|
|
48356
|
+
const onDue = () => {
|
|
48357
|
+
const writers = entries.map(
|
|
48358
|
+
({ binding, tick }) => createSharedEntityWriter(binding, tick, traitStatesRef, emitFromSharedWriter)
|
|
48359
|
+
);
|
|
48360
|
+
runTickFrame(group.storeKey, writers, sharedEntityStore);
|
|
48361
|
+
};
|
|
48362
|
+
if (interval === "frame") {
|
|
48363
|
+
scheduler.add(0, onDue);
|
|
48364
|
+
} else if (typeof interval === "number") {
|
|
48365
|
+
scheduler.add(interval, onDue);
|
|
48366
|
+
} else if (runtime.isValidCronExpression(interval)) {
|
|
48367
|
+
scheduler.addCron(interval, onDue);
|
|
48368
|
+
} else {
|
|
48369
|
+
scheduler.add(runtime.parseDurationString(interval), onDue);
|
|
48370
|
+
}
|
|
48371
|
+
}
|
|
48372
|
+
}
|
|
48170
48373
|
for (const binding of traitBindings) {
|
|
48374
|
+
if (writerTraitNames.has(binding.trait.name)) continue;
|
|
48171
48375
|
for (const tick of binding.trait.ticks ?? []) {
|
|
48172
48376
|
if (tick.interval === "frame") {
|
|
48173
48377
|
scheduler.add(0, () => runTickEffects(tick, binding));
|
|
@@ -48181,7 +48385,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
48181
48385
|
}
|
|
48182
48386
|
}
|
|
48183
48387
|
return () => scheduler.stopAll();
|
|
48184
|
-
}, [traitBindings, runTickEffects]);
|
|
48388
|
+
}, [traitBindings, runTickEffects, sharedGroups, sharedEntityStore, emitFromSharedWriter]);
|
|
48185
48389
|
const processEventQueued = React96.useCallback(async (eventKey, payload) => {
|
|
48186
48390
|
const normalizedEvent = normalizeEventKey(eventKey);
|
|
48187
48391
|
const bindings = traitBindingsRef.current;
|
|
@@ -48701,7 +48905,7 @@ function buildOrbitalsByTrait(schema, resolvedPages = []) {
|
|
|
48701
48905
|
// runtime/OrbPreview.tsx
|
|
48702
48906
|
init_verificationRegistry();
|
|
48703
48907
|
var PERF_NAMESPACE = "almadar:perf:canvas";
|
|
48704
|
-
var
|
|
48908
|
+
var log9 = logger.createLogger(PERF_NAMESPACE);
|
|
48705
48909
|
var RING_SIZE = 50;
|
|
48706
48910
|
var ring = [];
|
|
48707
48911
|
var writeIdx = 0;
|
|
@@ -48756,7 +48960,7 @@ function perfEnd(name, startToken, detail) {
|
|
|
48756
48960
|
}
|
|
48757
48961
|
}
|
|
48758
48962
|
push({ name, durationMs, ts: endTs, detail });
|
|
48759
|
-
|
|
48963
|
+
log9.debug(name, () => ({ durationMs, ...detail ?? {} }));
|
|
48760
48964
|
}
|
|
48761
48965
|
function perfTime(name, fn, detail) {
|
|
48762
48966
|
const t = perfStart(name);
|
|
@@ -48774,7 +48978,7 @@ var profilerOnRender = (id, phase, actualDuration, baseDuration, _startTime, com
|
|
|
48774
48978
|
ts: commitTime,
|
|
48775
48979
|
detail: { baseDuration }
|
|
48776
48980
|
});
|
|
48777
|
-
|
|
48981
|
+
log9.debug(`profiler:${id}:${phase}`, () => ({ actualDuration, baseDuration }));
|
|
48778
48982
|
};
|
|
48779
48983
|
function getPerfSnapshot() {
|
|
48780
48984
|
if (ring.length < RING_SIZE) return ring.slice();
|
package/dist/runtime/index.css
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/* node_modules/katex/dist/katex.min.css */
|
|
1
|
+
/* node_modules/.pnpm/katex@0.16.47/node_modules/katex/dist/katex.min.css */
|
|
2
2
|
@font-face {
|
|
3
3
|
font-display: block;
|
|
4
4
|
font-family: KaTeX_AMS;
|
|
@@ -214,11 +214,11 @@
|
|
|
214
214
|
border-color: currentColor;
|
|
215
215
|
}
|
|
216
216
|
.katex .katex-version:after {
|
|
217
|
-
content: "0.16.
|
|
217
|
+
content: "0.16.47";
|
|
218
218
|
}
|
|
219
219
|
.katex .katex-mathml {
|
|
220
|
-
clip: rect(1px, 1px, 1px, 1px);
|
|
221
220
|
border: 0;
|
|
221
|
+
clip-path: inset(50%);
|
|
222
222
|
height: 1px;
|
|
223
223
|
overflow: hidden;
|
|
224
224
|
padding: 0;
|