@almadar/ui 5.101.0 → 5.103.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 +238 -40
- package/dist/avl/index.js +240 -42
- package/dist/components/index.cjs +89 -19
- package/dist/components/index.js +74 -8
- 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/useSharedEntityStore.d.ts +53 -0
- package/dist/hooks/useTraitStateMachine.d.ts +32 -1
- package/dist/runtime/index.cjs +242 -44
- package/dist/runtime/index.js +244 -46
- package/package.json +2 -2
|
@@ -36,8 +36,8 @@ var ReactMarkdown = require('react-markdown');
|
|
|
36
36
|
var remarkGfm = require('remark-gfm');
|
|
37
37
|
var remarkMath = require('remark-math');
|
|
38
38
|
var rehypeKatex = require('rehype-katex');
|
|
39
|
-
var core
|
|
40
|
-
var core = require('@dnd-kit/core');
|
|
39
|
+
var core = require('@almadar/core');
|
|
40
|
+
var core$1 = require('@dnd-kit/core');
|
|
41
41
|
var sortable = require('@dnd-kit/sortable');
|
|
42
42
|
var utilities = require('@dnd-kit/utilities');
|
|
43
43
|
var react = require('@xyflow/react');
|
|
@@ -13236,7 +13236,7 @@ function extractTrait(schema, trait, traitIndex) {
|
|
|
13236
13236
|
const traits2 = orbital.traits ?? [];
|
|
13237
13237
|
if (traitIndex < traits2.length) {
|
|
13238
13238
|
const traitRef = traits2[traitIndex];
|
|
13239
|
-
if (core
|
|
13239
|
+
if (core.isInlineTrait(traitRef)) return traitRef;
|
|
13240
13240
|
return null;
|
|
13241
13241
|
}
|
|
13242
13242
|
}
|
|
@@ -21562,12 +21562,12 @@ var init_Menu = __esm({
|
|
|
21562
21562
|
}
|
|
21563
21563
|
});
|
|
21564
21564
|
function useAlmadarDndSensors(withSortableKeyboard = true) {
|
|
21565
|
-
return core.useSensors(
|
|
21566
|
-
core.useSensor(core.PointerSensor, {
|
|
21565
|
+
return core$1.useSensors(
|
|
21566
|
+
core$1.useSensor(core$1.PointerSensor, {
|
|
21567
21567
|
activationConstraint: { distance: ALMADAR_DND_ACTIVATION_DISTANCE }
|
|
21568
21568
|
}),
|
|
21569
|
-
core.useSensor(
|
|
21570
|
-
core.KeyboardSensor,
|
|
21569
|
+
core$1.useSensor(
|
|
21570
|
+
core$1.KeyboardSensor,
|
|
21571
21571
|
withSortableKeyboard ? { coordinateGetter: sortable.sortableKeyboardCoordinates } : void 0
|
|
21572
21572
|
)
|
|
21573
21573
|
);
|
|
@@ -21578,11 +21578,11 @@ var init_useAlmadarDndCollision = __esm({
|
|
|
21578
21578
|
"use client";
|
|
21579
21579
|
ALMADAR_DND_ACTIVATION_DISTANCE = 5;
|
|
21580
21580
|
almadarDndCollisionDetection = (args) => {
|
|
21581
|
-
const pw = core.pointerWithin(args);
|
|
21581
|
+
const pw = core$1.pointerWithin(args);
|
|
21582
21582
|
if (pw.length > 0) return pw;
|
|
21583
|
-
const ri = core.rectIntersection(args);
|
|
21583
|
+
const ri = core$1.rectIntersection(args);
|
|
21584
21584
|
if (ri.length > 0) return ri;
|
|
21585
|
-
return core.closestCorners(args);
|
|
21585
|
+
return core$1.closestCorners(args);
|
|
21586
21586
|
};
|
|
21587
21587
|
}
|
|
21588
21588
|
});
|
|
@@ -21831,7 +21831,7 @@ function useDataDnd(args) {
|
|
|
21831
21831
|
);
|
|
21832
21832
|
const DropZoneShell = ({ children }) => {
|
|
21833
21833
|
const droppableId = `dnd-zone-${zoneId}`;
|
|
21834
|
-
const { setNodeRef, isOver } = core.useDroppable({
|
|
21834
|
+
const { setNodeRef, isOver } = core$1.useDroppable({
|
|
21835
21835
|
id: droppableId,
|
|
21836
21836
|
data: sortableData
|
|
21837
21837
|
});
|
|
@@ -21977,7 +21977,7 @@ function useDataDnd(args) {
|
|
|
21977
21977
|
if (!isZone) {
|
|
21978
21978
|
if (!isRoot) return children;
|
|
21979
21979
|
return /* @__PURE__ */ jsxRuntime.jsx(RootCtx.Provider, { value: rootContextValue, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
21980
|
-
core.DndContext,
|
|
21980
|
+
core$1.DndContext,
|
|
21981
21981
|
{
|
|
21982
21982
|
sensors,
|
|
21983
21983
|
collisionDetection,
|
|
@@ -21992,7 +21992,7 @@ function useDataDnd(args) {
|
|
|
21992
21992
|
const inner = /* @__PURE__ */ jsxRuntime.jsx(DropZoneShell, { children: /* @__PURE__ */ jsxRuntime.jsx(sortable.SortableContext, { items: itemIds, strategy, children }) });
|
|
21993
21993
|
if (isRoot) {
|
|
21994
21994
|
return /* @__PURE__ */ jsxRuntime.jsx(RootCtx.Provider, { value: rootContextValue, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
21995
|
-
core.DndContext,
|
|
21995
|
+
core$1.DndContext,
|
|
21996
21996
|
{
|
|
21997
21997
|
sensors,
|
|
21998
21998
|
collisionDetection,
|
|
@@ -32208,12 +32208,12 @@ var init_MapView = __esm({
|
|
|
32208
32208
|
shadowSize: [41, 41]
|
|
32209
32209
|
});
|
|
32210
32210
|
L.Marker.prototype.options.icon = defaultIcon;
|
|
32211
|
-
const { useEffect: useEffect70, useRef:
|
|
32211
|
+
const { useEffect: useEffect70, useRef: useRef66, useCallback: useCallback113, useState: useState108 } = React75__namespace.default;
|
|
32212
32212
|
const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
|
|
32213
32213
|
const { useEventBus: useEventBus2 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
|
|
32214
32214
|
function MapUpdater({ centerLat, centerLng, zoom }) {
|
|
32215
32215
|
const map = useMap();
|
|
32216
|
-
const prevRef =
|
|
32216
|
+
const prevRef = useRef66({ centerLat, centerLng, zoom });
|
|
32217
32217
|
useEffect70(() => {
|
|
32218
32218
|
const prev = prevRef.current;
|
|
32219
32219
|
if (prev.centerLat !== centerLat || prev.centerLng !== centerLng || prev.zoom !== zoom) {
|
|
@@ -45740,7 +45740,7 @@ function extractPayloadFields(schema, eventName) {
|
|
|
45740
45740
|
for (const orbital of schema.orbitals) {
|
|
45741
45741
|
const traitRefs = orbital.traits ?? [];
|
|
45742
45742
|
for (const traitRef of traitRefs) {
|
|
45743
|
-
if (!core
|
|
45743
|
+
if (!core.isInlineTrait(traitRef)) continue;
|
|
45744
45744
|
const inlineTrait = traitRef;
|
|
45745
45745
|
const sm = inlineTrait.stateMachine;
|
|
45746
45746
|
if (!sm) continue;
|
|
@@ -45811,7 +45811,7 @@ function getAllEvents(traits2) {
|
|
|
45811
45811
|
function EventDispatcherTab({ traits: traits2, schema }) {
|
|
45812
45812
|
const eventBus = useEventBus();
|
|
45813
45813
|
const { t } = hooks.useTranslate();
|
|
45814
|
-
const [
|
|
45814
|
+
const [log19, setLog] = React75__namespace.useState([]);
|
|
45815
45815
|
const prevStatesRef = React75__namespace.useRef(/* @__PURE__ */ new Map());
|
|
45816
45816
|
React75__namespace.useEffect(() => {
|
|
45817
45817
|
for (const trait of traits2) {
|
|
@@ -45875,9 +45875,9 @@ function EventDispatcherTab({ traits: traits2, schema }) {
|
|
|
45875
45875
|
/* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "small", weight: "medium", className: "text-gray-500 mb-1", children: t("debug.otherEvents") }),
|
|
45876
45876
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap gap-1", children: unavailableEvents.map((event) => /* @__PURE__ */ jsxRuntime.jsx(exports.Badge, { variant: "default", size: "sm", className: "opacity-50", children: event }, event)) })
|
|
45877
45877
|
] }),
|
|
45878
|
-
|
|
45878
|
+
log19.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
45879
45879
|
/* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "small", weight: "medium", className: "text-gray-500 mb-1", children: t("debug.recentTransitions") }),
|
|
45880
|
-
/* @__PURE__ */ jsxRuntime.jsx(exports.Stack, { gap: "xs", children:
|
|
45880
|
+
/* @__PURE__ */ jsxRuntime.jsx(exports.Stack, { gap: "xs", children: log19.map((entry, i) => /* @__PURE__ */ jsxRuntime.jsxs(exports.Typography, { variant: "small", className: "font-mono text-xs", children: [
|
|
45881
45881
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-purple-400", children: entry.traitName }),
|
|
45882
45882
|
" ",
|
|
45883
45883
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-gray-500", children: entry.from }),
|
|
@@ -51092,6 +51092,72 @@ function useTraitListens(dispatch, listens, eventBusInstance) {
|
|
|
51092
51092
|
};
|
|
51093
51093
|
}, [eventBus, dispatch, stableListens]);
|
|
51094
51094
|
}
|
|
51095
|
+
var log18 = logger.createLogger("almadar:ui:shared-entity-store");
|
|
51096
|
+
var EMPTY_ENTITY_STATE = {};
|
|
51097
|
+
function createSharedEntityStore() {
|
|
51098
|
+
const states = /* @__PURE__ */ new Map();
|
|
51099
|
+
const subscribers = /* @__PURE__ */ new Map();
|
|
51100
|
+
const getSnapshot2 = (entityId) => states.get(entityId) ?? EMPTY_ENTITY_STATE;
|
|
51101
|
+
const subscribe = (entityId, callback) => {
|
|
51102
|
+
let set = subscribers.get(entityId);
|
|
51103
|
+
if (!set) {
|
|
51104
|
+
set = /* @__PURE__ */ new Set();
|
|
51105
|
+
subscribers.set(entityId, set);
|
|
51106
|
+
}
|
|
51107
|
+
set.add(callback);
|
|
51108
|
+
return () => {
|
|
51109
|
+
const current = subscribers.get(entityId);
|
|
51110
|
+
if (!current) return;
|
|
51111
|
+
current.delete(callback);
|
|
51112
|
+
if (current.size === 0) {
|
|
51113
|
+
subscribers.delete(entityId);
|
|
51114
|
+
}
|
|
51115
|
+
};
|
|
51116
|
+
};
|
|
51117
|
+
const commit = (entityId, nextState) => {
|
|
51118
|
+
states.set(entityId, nextState);
|
|
51119
|
+
const set = subscribers.get(entityId);
|
|
51120
|
+
if (!set) return;
|
|
51121
|
+
set.forEach((callback) => {
|
|
51122
|
+
try {
|
|
51123
|
+
callback();
|
|
51124
|
+
} catch (error) {
|
|
51125
|
+
log18.error("Shared entity subscriber error", {
|
|
51126
|
+
entityId,
|
|
51127
|
+
error: error instanceof Error ? error : String(error)
|
|
51128
|
+
});
|
|
51129
|
+
}
|
|
51130
|
+
});
|
|
51131
|
+
};
|
|
51132
|
+
const seed = (entityId, initialState) => {
|
|
51133
|
+
if (!states.has(entityId)) {
|
|
51134
|
+
states.set(entityId, initialState);
|
|
51135
|
+
}
|
|
51136
|
+
};
|
|
51137
|
+
return { getSnapshot: getSnapshot2, subscribe, commit, seed };
|
|
51138
|
+
}
|
|
51139
|
+
function useSharedEntityStore() {
|
|
51140
|
+
const storeRef = React75.useRef(null);
|
|
51141
|
+
if (storeRef.current === null) {
|
|
51142
|
+
storeRef.current = createSharedEntityStore();
|
|
51143
|
+
}
|
|
51144
|
+
return storeRef.current;
|
|
51145
|
+
}
|
|
51146
|
+
function useSharedEntitySnapshot(store, entityId) {
|
|
51147
|
+
return React75.useSyncExternalStore(
|
|
51148
|
+
(onStoreChange) => store.subscribe(entityId, onStoreChange),
|
|
51149
|
+
() => store.getSnapshot(entityId)
|
|
51150
|
+
);
|
|
51151
|
+
}
|
|
51152
|
+
function runTickFrame(entityId, orderedWriters, store) {
|
|
51153
|
+
let scratch = store.getSnapshot(entityId);
|
|
51154
|
+
for (const writer of orderedWriters) {
|
|
51155
|
+
const writes = writer(scratch);
|
|
51156
|
+
scratch = core.mergeEntityFrame(scratch, writes);
|
|
51157
|
+
}
|
|
51158
|
+
store.commit(entityId, scratch);
|
|
51159
|
+
return scratch;
|
|
51160
|
+
}
|
|
51095
51161
|
|
|
51096
51162
|
// hooks/index.ts
|
|
51097
51163
|
init_useQuerySingleton();
|
|
@@ -51982,6 +52048,7 @@ exports.calculateAttackTargets = calculateAttackTargets;
|
|
|
51982
52048
|
exports.calculateValidMoves = calculateValidMoves;
|
|
51983
52049
|
exports.cn = cn;
|
|
51984
52050
|
exports.createInitialGameState = createInitialGameState;
|
|
52051
|
+
exports.createSharedEntityStore = createSharedEntityStore;
|
|
51985
52052
|
exports.createTranslate = createTranslate;
|
|
51986
52053
|
exports.createUnitAnimationState = createUnitAnimationState;
|
|
51987
52054
|
exports.drawSprite = drawSprite;
|
|
@@ -52010,6 +52077,7 @@ exports.resolveFieldMap = resolveFieldMap;
|
|
|
52010
52077
|
exports.resolveFrame = resolveFrame;
|
|
52011
52078
|
exports.resolveSheetDirection = resolveSheetDirection;
|
|
52012
52079
|
exports.rows = rows;
|
|
52080
|
+
exports.runTickFrame = runTickFrame;
|
|
52013
52081
|
exports.screenToIso = screenToIso;
|
|
52014
52082
|
exports.str = str;
|
|
52015
52083
|
exports.tickAnimationState = tickAnimationState;
|
|
@@ -52051,6 +52119,8 @@ exports.usePreview = usePreview;
|
|
|
52051
52119
|
exports.usePullToRefresh = usePullToRefresh;
|
|
52052
52120
|
exports.useQuerySingleton = useQuerySingleton;
|
|
52053
52121
|
exports.useRenderInterpolation = useRenderInterpolation;
|
|
52122
|
+
exports.useSharedEntitySnapshot = useSharedEntitySnapshot;
|
|
52123
|
+
exports.useSharedEntityStore = useSharedEntityStore;
|
|
52054
52124
|
exports.useSwipeGesture = useSwipeGesture;
|
|
52055
52125
|
exports.useTapReveal = useTapReveal;
|
|
52056
52126
|
exports.useTraitListens = useTraitListens;
|
package/dist/components/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
2
2
|
import * as React75 from 'react';
|
|
3
|
-
import React75__default, { createContext, useContext, useMemo, useRef, useEffect, useCallback, useState, Suspense, lazy, useLayoutEffect, useId
|
|
3
|
+
import React75__default, { createContext, useContext, useMemo, useRef, useEffect, useCallback, useState, Suspense, lazy, useSyncExternalStore, useLayoutEffect, useId } from 'react';
|
|
4
4
|
import { clsx } from 'clsx';
|
|
5
5
|
import { twMerge } from 'tailwind-merge';
|
|
6
6
|
import { EventBusContext, useTraitScope, useCurrentPagePath, useEntitySchemaOptional, TraitScopeProvider } from '@almadar/ui/providers';
|
|
@@ -36,7 +36,7 @@ import ReactMarkdown from 'react-markdown';
|
|
|
36
36
|
import remarkGfm from 'remark-gfm';
|
|
37
37
|
import remarkMath from 'remark-math';
|
|
38
38
|
import rehypeKatex from 'rehype-katex';
|
|
39
|
-
import { isInlineTrait } from '@almadar/core';
|
|
39
|
+
import { mergeEntityFrame, isInlineTrait } from '@almadar/core';
|
|
40
40
|
import { DndContext, useSensors, useSensor, PointerSensor, KeyboardSensor, useDroppable, pointerWithin, rectIntersection, closestCorners } from '@dnd-kit/core';
|
|
41
41
|
import { useSortable, arrayMove, sortableKeyboardCoordinates, SortableContext, rectSortingStrategy, verticalListSortingStrategy } from '@dnd-kit/sortable';
|
|
42
42
|
import { CSS } from '@dnd-kit/utilities';
|
|
@@ -32162,12 +32162,12 @@ var init_MapView = __esm({
|
|
|
32162
32162
|
shadowSize: [41, 41]
|
|
32163
32163
|
});
|
|
32164
32164
|
L.Marker.prototype.options.icon = defaultIcon;
|
|
32165
|
-
const { useEffect: useEffect70, useRef:
|
|
32165
|
+
const { useEffect: useEffect70, useRef: useRef66, useCallback: useCallback113, useState: useState108 } = React75__default;
|
|
32166
32166
|
const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
|
|
32167
32167
|
const { useEventBus: useEventBus2 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
|
|
32168
32168
|
function MapUpdater({ centerLat, centerLng, zoom }) {
|
|
32169
32169
|
const map = useMap();
|
|
32170
|
-
const prevRef =
|
|
32170
|
+
const prevRef = useRef66({ centerLat, centerLng, zoom });
|
|
32171
32171
|
useEffect70(() => {
|
|
32172
32172
|
const prev = prevRef.current;
|
|
32173
32173
|
if (prev.centerLat !== centerLat || prev.centerLng !== centerLng || prev.zoom !== zoom) {
|
|
@@ -45765,7 +45765,7 @@ function getAllEvents(traits2) {
|
|
|
45765
45765
|
function EventDispatcherTab({ traits: traits2, schema }) {
|
|
45766
45766
|
const eventBus = useEventBus();
|
|
45767
45767
|
const { t } = useTranslate();
|
|
45768
|
-
const [
|
|
45768
|
+
const [log19, setLog] = React75.useState([]);
|
|
45769
45769
|
const prevStatesRef = React75.useRef(/* @__PURE__ */ new Map());
|
|
45770
45770
|
React75.useEffect(() => {
|
|
45771
45771
|
for (const trait of traits2) {
|
|
@@ -45829,9 +45829,9 @@ function EventDispatcherTab({ traits: traits2, schema }) {
|
|
|
45829
45829
|
/* @__PURE__ */ jsx(Typography, { variant: "small", weight: "medium", className: "text-gray-500 mb-1", children: t("debug.otherEvents") }),
|
|
45830
45830
|
/* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-1", children: unavailableEvents.map((event) => /* @__PURE__ */ jsx(Badge, { variant: "default", size: "sm", className: "opacity-50", children: event }, event)) })
|
|
45831
45831
|
] }),
|
|
45832
|
-
|
|
45832
|
+
log19.length > 0 && /* @__PURE__ */ jsxs("div", { children: [
|
|
45833
45833
|
/* @__PURE__ */ jsx(Typography, { variant: "small", weight: "medium", className: "text-gray-500 mb-1", children: t("debug.recentTransitions") }),
|
|
45834
|
-
/* @__PURE__ */ jsx(Stack, { gap: "xs", children:
|
|
45834
|
+
/* @__PURE__ */ jsx(Stack, { gap: "xs", children: log19.map((entry, i) => /* @__PURE__ */ jsxs(Typography, { variant: "small", className: "font-mono text-xs", children: [
|
|
45835
45835
|
/* @__PURE__ */ jsx("span", { className: "text-purple-400", children: entry.traitName }),
|
|
45836
45836
|
" ",
|
|
45837
45837
|
/* @__PURE__ */ jsx("span", { className: "text-gray-500", children: entry.from }),
|
|
@@ -51046,6 +51046,72 @@ function useTraitListens(dispatch, listens, eventBusInstance) {
|
|
|
51046
51046
|
};
|
|
51047
51047
|
}, [eventBus, dispatch, stableListens]);
|
|
51048
51048
|
}
|
|
51049
|
+
var log18 = createLogger("almadar:ui:shared-entity-store");
|
|
51050
|
+
var EMPTY_ENTITY_STATE = {};
|
|
51051
|
+
function createSharedEntityStore() {
|
|
51052
|
+
const states = /* @__PURE__ */ new Map();
|
|
51053
|
+
const subscribers = /* @__PURE__ */ new Map();
|
|
51054
|
+
const getSnapshot2 = (entityId) => states.get(entityId) ?? EMPTY_ENTITY_STATE;
|
|
51055
|
+
const subscribe = (entityId, callback) => {
|
|
51056
|
+
let set = subscribers.get(entityId);
|
|
51057
|
+
if (!set) {
|
|
51058
|
+
set = /* @__PURE__ */ new Set();
|
|
51059
|
+
subscribers.set(entityId, set);
|
|
51060
|
+
}
|
|
51061
|
+
set.add(callback);
|
|
51062
|
+
return () => {
|
|
51063
|
+
const current = subscribers.get(entityId);
|
|
51064
|
+
if (!current) return;
|
|
51065
|
+
current.delete(callback);
|
|
51066
|
+
if (current.size === 0) {
|
|
51067
|
+
subscribers.delete(entityId);
|
|
51068
|
+
}
|
|
51069
|
+
};
|
|
51070
|
+
};
|
|
51071
|
+
const commit = (entityId, nextState) => {
|
|
51072
|
+
states.set(entityId, nextState);
|
|
51073
|
+
const set = subscribers.get(entityId);
|
|
51074
|
+
if (!set) return;
|
|
51075
|
+
set.forEach((callback) => {
|
|
51076
|
+
try {
|
|
51077
|
+
callback();
|
|
51078
|
+
} catch (error) {
|
|
51079
|
+
log18.error("Shared entity subscriber error", {
|
|
51080
|
+
entityId,
|
|
51081
|
+
error: error instanceof Error ? error : String(error)
|
|
51082
|
+
});
|
|
51083
|
+
}
|
|
51084
|
+
});
|
|
51085
|
+
};
|
|
51086
|
+
const seed = (entityId, initialState) => {
|
|
51087
|
+
if (!states.has(entityId)) {
|
|
51088
|
+
states.set(entityId, initialState);
|
|
51089
|
+
}
|
|
51090
|
+
};
|
|
51091
|
+
return { getSnapshot: getSnapshot2, subscribe, commit, seed };
|
|
51092
|
+
}
|
|
51093
|
+
function useSharedEntityStore() {
|
|
51094
|
+
const storeRef = useRef(null);
|
|
51095
|
+
if (storeRef.current === null) {
|
|
51096
|
+
storeRef.current = createSharedEntityStore();
|
|
51097
|
+
}
|
|
51098
|
+
return storeRef.current;
|
|
51099
|
+
}
|
|
51100
|
+
function useSharedEntitySnapshot(store, entityId) {
|
|
51101
|
+
return useSyncExternalStore(
|
|
51102
|
+
(onStoreChange) => store.subscribe(entityId, onStoreChange),
|
|
51103
|
+
() => store.getSnapshot(entityId)
|
|
51104
|
+
);
|
|
51105
|
+
}
|
|
51106
|
+
function runTickFrame(entityId, orderedWriters, store) {
|
|
51107
|
+
let scratch = store.getSnapshot(entityId);
|
|
51108
|
+
for (const writer of orderedWriters) {
|
|
51109
|
+
const writes = writer(scratch);
|
|
51110
|
+
scratch = mergeEntityFrame(scratch, writes);
|
|
51111
|
+
}
|
|
51112
|
+
store.commit(entityId, scratch);
|
|
51113
|
+
return scratch;
|
|
51114
|
+
}
|
|
51049
51115
|
|
|
51050
51116
|
// hooks/index.ts
|
|
51051
51117
|
init_useQuerySingleton();
|
|
@@ -51846,4 +51912,4 @@ function useGitHubBranches(owner, repo, enabled = true) {
|
|
|
51846
51912
|
});
|
|
51847
51913
|
}
|
|
51848
51914
|
|
|
51849
|
-
export { ALL_PRESETS, ALMADAR_DND_MIME, AR_BOOK_FIELDS, AboutPageTemplate, Accordion, ActionButton, Card2 as ActionCard, ActionPalette, ActionTile, ActivationBlock, Alert, AlgorithmCanvas, AnimatedCounter, AnimatedGraphic, AnimatedReveal, ArticleSection, Aside, AssetPicker, AtlasImage, AtlasPanel, AuthLayout, Avatar, Badge, BehaviorView, BiologyCanvas, BloomQuizBlock, BookChapterView, BookCoverPage, BookNavBar, BookTableOfContents, BookViewer, Box, BranchingLogicBuilder, Breadcrumb, BuilderBoard, Button, ButtonGroup, CTABanner, CalendarGrid, Canvas2D, Card, CardBody, CardContent, CardFooter, CardGrid, CardHeader, CardTitle, Carousel, CaseStudyCard, CaseStudyOrganism, Center, Chart, ChartLegend, ChatBar, Checkbox, ChemistryCanvas, ChoiceButton, ClassifierBoard, Coachmark, CodeBlock, CodeRunnerPanel, CollapsibleSection, ComboCounter, CommunityLinks, ConditionalWrapper, ConfettiEffect, ConfirmDialog, ConnectionBlock, Container, ContentRenderer, ContentSection, ControlButton, ControlGrid, CounterTemplate, DEFAULT_LIKERT_OPTIONS, DEFAULT_MATRIX_COLUMNS, DEFAULT_SLOTS, DIAMOND_TOP_Y, DamageNumber, DashboardGrid, DashboardLayout, DataGrid, DataList, DataTable, DateRangePicker, DateRangeSelector, DayCell, DebuggerBoard, DetailPanel, Dialog, DialogueBubble, Divider, DocBreadcrumb, DocPagination, DocSearch, DocSidebar, DocTOC, DocumentViewer, StateMachineView as DomStateMachineVisualizer, Drawer, DrawerSlot, ELEMENT_SELECTED_EVENT, EMPTY_EFFECT_STATE, EdgeDecoration, EditorCheckbox, EditorSelect, EditorSlider, EditorTextInput, EditorToolbar, EmptyState, EntityDisplayEvents, ErrorBoundary, ErrorState, EventHandlerBoard, EventLog, FEATURE_COLORS, FEATURE_TYPES, FLOOR_HEIGHT, FeatureCard, FeatureDetailPageTemplate, FeatureGrid, FeatureGridOrganism, FileTree, FilterGroup, FilterPill, Flex, FlipCard, FlipContainer, FloatingActionButton, Form, FormActions, FormField, FormLayout, FormSection, FormSectionHeader, GameAudioContext, GameAudioProvider, GameAudioToggle, GameCard, GameHud, GameIcon, GameMenu, GameShell, GameTemplate, GenericAppTemplate, GeometricPattern, GradientDivider, GraphCanvas, GraphView, Grid, GridPicker, HStack, Header, HealthBar, HeroOrganism, HeroSection, I18nProvider, IDENTITY_BOOK_FIELDS, Icon, IconPicker, InfiniteScrollSentinel, Input, InputGroup, InstallBox, InventoryGrid, ItemSlot, JazariStateMachine, JsonTreeEditor, Label, LandingPageTemplate, LawReferenceTooltip, LearningCanvas, Lightbox, LikertScale, LineChart2 as LineChart, List3 as List, LoadingState, MapView, MarkdownContent, MarketingFooter, MarketingStatCard, MasterDetail, MasterDetailLayout, MathCanvas, MatrixQuestion, MediaGallery, Menu, Meter, MiniMap, Modal, ModalSlot, ModuleCard, Navigation, NegotiatorBoard, NodeSlotEditor, NotifyListener, NumberStepper, ObjectRulePanel, OnboardingSpotlight, OptionConstraintGroup, StateMachineView as OrbitalStateMachineView, OrbitalVisualization, Overlay, PageHeader, Pagination, PatternTile, PhysicsCanvas, Popover, PositionedCanvas, PricingCard, PricingGrid, PricingOrganism, PricingPageTemplate, ProgressBar, ProgressDots, PropertyInspector, PullQuote, PullToRefresh, QrScanner, QuizBlock, Radio, RangeSlider, ReflectionBlock, RelationSelect, RepeatableFormSection, ReplyTree, ResourceBar, ResourceCounter, RichBlockEditor, RuleEditor, RuntimeDebugger, SHEET_COLUMNS, SPRITE_SHEET_LAYOUT, ScaledDiagram, ScoreDisplay, SearchInput, Section, SectionHeader, SegmentRenderer, Select, SequenceBar, SequencerBoard, ServiceCatalog, ShowcaseCard, ShowcaseOrganism, SidePanel, Sidebar, SignaturePad, SimpleGrid, SimulatorBoard, Skeleton, SlotContentRenderer, SocialProof, SortableList, Spacer, Sparkline, Spinner, Split, SplitPane, SplitSection, Sprite, Stack, StarRating, StatBadge, StatCard, StatDisplay, StateArchitectBoard, StateGraph, StateIndicator, StateJsonView, StateMachineView, StateNode2 as StateNode, StatsGrid, StatsOrganism, StatusBar, StatusDot, StatusEffect, StepFlow, StepFlowOrganism, SubagentTracePanel, SvgBranch, SvgConnection, SvgFlow, SvgGrid, SvgLobe, SvgMesh, SvgMorph, SvgNode, SvgPulse, SvgRing, SvgShield, SvgStack, SwipeableRow, Switch, TERRAIN_COLORS, TILE_HEIGHT, TILE_WIDTH, TabbedContainer, TableView, Tabs, TagCloud, TagInput, TeamCard, TeamOrganism, TerrainPalette, TextHighlight, Textarea, ThemeToggle, TimeSlotCell, Timeline, TimerDisplay, Toast, ToastSlot, Tooltip, TraitFrame, TraitSlot, TraitStateViewer, TransitionArrow, TrendIndicator, TurnIndicator, TypewriterText, Typography, UISlotComponent, UISlotRenderer, UploadDropZone, VStack, VariablePanel, VersionDiff, ViolationAlert, VoteStack, WaypointMarker, WizardContainer, WizardNavigation, WizardProgress, boardEntity, bool, calculateAttackTargets, calculateValidMoves, cn, createInitialGameState, createTranslate, createUnitAnimationState, drawSprite, getCurrentFrame, getTileDimensions, inferDirection, isoToScreen, makeAsset, makeAssetMap, mapBookData, num, objAvailableActions, objAvailableEvents, objCurrentState, objIcon, objId, objMaxRules, objName, objRules, objStates, parseEditFocus, parseLessonSegments, parseMarkdownWithCodeBlocks, parseQueryBinding, pendulum, projectileMotion, resolveFieldMap, resolveFrame, resolveSheetDirection, rows, screenToIso, springOscillator, str, tickAnimationState, toCodeLanguage, transitionAnimation, unitHealth, unitPosition, unitTeam, useAgentChat, useAnchorRect, useAtlasSliceDataUrl, useAuthContext, useCamera, useCanvasGestures, useCompile, useConnectGitHub, useDeepAgentGeneration, useDisconnectGitHub, useDragReorder, useDraggable, useDropZone, useEmitEvent, useEventBus, useEventListener, useExtensions, useFileEditor, useFileSystem, useGameAudio, useGameAudioContext, useGitHubBranches, useGitHubRepo, useGitHubRepos, useGitHubStatus, useImageCache, useInfiniteScroll, useLongPress, useOrbitalHistory, usePreview, usePullToRefresh, useQuerySingleton, useRenderInterpolation, useSwipeGesture, useTapReveal, useTraitListens, useTranslate127 as useTranslate, useUIEvents, useUISlotManager, useUnitSpriteAtlas, useValidation, vec2 };
|
|
51915
|
+
export { ALL_PRESETS, ALMADAR_DND_MIME, AR_BOOK_FIELDS, AboutPageTemplate, Accordion, ActionButton, Card2 as ActionCard, ActionPalette, ActionTile, ActivationBlock, Alert, AlgorithmCanvas, AnimatedCounter, AnimatedGraphic, AnimatedReveal, ArticleSection, Aside, AssetPicker, AtlasImage, AtlasPanel, AuthLayout, Avatar, Badge, BehaviorView, BiologyCanvas, BloomQuizBlock, BookChapterView, BookCoverPage, BookNavBar, BookTableOfContents, BookViewer, Box, BranchingLogicBuilder, Breadcrumb, BuilderBoard, Button, ButtonGroup, CTABanner, CalendarGrid, Canvas2D, Card, CardBody, CardContent, CardFooter, CardGrid, CardHeader, CardTitle, Carousel, CaseStudyCard, CaseStudyOrganism, Center, Chart, ChartLegend, ChatBar, Checkbox, ChemistryCanvas, ChoiceButton, ClassifierBoard, Coachmark, CodeBlock, CodeRunnerPanel, CollapsibleSection, ComboCounter, CommunityLinks, ConditionalWrapper, ConfettiEffect, ConfirmDialog, ConnectionBlock, Container, ContentRenderer, ContentSection, ControlButton, ControlGrid, CounterTemplate, DEFAULT_LIKERT_OPTIONS, DEFAULT_MATRIX_COLUMNS, DEFAULT_SLOTS, DIAMOND_TOP_Y, DamageNumber, DashboardGrid, DashboardLayout, DataGrid, DataList, DataTable, DateRangePicker, DateRangeSelector, DayCell, DebuggerBoard, DetailPanel, Dialog, DialogueBubble, Divider, DocBreadcrumb, DocPagination, DocSearch, DocSidebar, DocTOC, DocumentViewer, StateMachineView as DomStateMachineVisualizer, Drawer, DrawerSlot, ELEMENT_SELECTED_EVENT, EMPTY_EFFECT_STATE, EdgeDecoration, EditorCheckbox, EditorSelect, EditorSlider, EditorTextInput, EditorToolbar, EmptyState, EntityDisplayEvents, ErrorBoundary, ErrorState, EventHandlerBoard, EventLog, FEATURE_COLORS, FEATURE_TYPES, FLOOR_HEIGHT, FeatureCard, FeatureDetailPageTemplate, FeatureGrid, FeatureGridOrganism, FileTree, FilterGroup, FilterPill, Flex, FlipCard, FlipContainer, FloatingActionButton, Form, FormActions, FormField, FormLayout, FormSection, FormSectionHeader, GameAudioContext, GameAudioProvider, GameAudioToggle, GameCard, GameHud, GameIcon, GameMenu, GameShell, GameTemplate, GenericAppTemplate, GeometricPattern, GradientDivider, GraphCanvas, GraphView, Grid, GridPicker, HStack, Header, HealthBar, HeroOrganism, HeroSection, I18nProvider, IDENTITY_BOOK_FIELDS, Icon, IconPicker, InfiniteScrollSentinel, Input, InputGroup, InstallBox, InventoryGrid, ItemSlot, JazariStateMachine, JsonTreeEditor, Label, LandingPageTemplate, LawReferenceTooltip, LearningCanvas, Lightbox, LikertScale, LineChart2 as LineChart, List3 as List, LoadingState, MapView, MarkdownContent, MarketingFooter, MarketingStatCard, MasterDetail, MasterDetailLayout, MathCanvas, MatrixQuestion, MediaGallery, Menu, Meter, MiniMap, Modal, ModalSlot, ModuleCard, Navigation, NegotiatorBoard, NodeSlotEditor, NotifyListener, NumberStepper, ObjectRulePanel, OnboardingSpotlight, OptionConstraintGroup, StateMachineView as OrbitalStateMachineView, OrbitalVisualization, Overlay, PageHeader, Pagination, PatternTile, PhysicsCanvas, Popover, PositionedCanvas, PricingCard, PricingGrid, PricingOrganism, PricingPageTemplate, ProgressBar, ProgressDots, PropertyInspector, PullQuote, PullToRefresh, QrScanner, QuizBlock, Radio, RangeSlider, ReflectionBlock, RelationSelect, RepeatableFormSection, ReplyTree, ResourceBar, ResourceCounter, RichBlockEditor, RuleEditor, RuntimeDebugger, SHEET_COLUMNS, SPRITE_SHEET_LAYOUT, ScaledDiagram, ScoreDisplay, SearchInput, Section, SectionHeader, SegmentRenderer, Select, SequenceBar, SequencerBoard, ServiceCatalog, ShowcaseCard, ShowcaseOrganism, SidePanel, Sidebar, SignaturePad, SimpleGrid, SimulatorBoard, Skeleton, SlotContentRenderer, SocialProof, SortableList, Spacer, Sparkline, Spinner, Split, SplitPane, SplitSection, Sprite, Stack, StarRating, StatBadge, StatCard, StatDisplay, StateArchitectBoard, StateGraph, StateIndicator, StateJsonView, StateMachineView, StateNode2 as StateNode, StatsGrid, StatsOrganism, StatusBar, StatusDot, StatusEffect, StepFlow, StepFlowOrganism, SubagentTracePanel, SvgBranch, SvgConnection, SvgFlow, SvgGrid, SvgLobe, SvgMesh, SvgMorph, SvgNode, SvgPulse, SvgRing, SvgShield, SvgStack, SwipeableRow, Switch, TERRAIN_COLORS, TILE_HEIGHT, TILE_WIDTH, TabbedContainer, TableView, Tabs, TagCloud, TagInput, TeamCard, TeamOrganism, TerrainPalette, TextHighlight, Textarea, ThemeToggle, TimeSlotCell, Timeline, TimerDisplay, Toast, ToastSlot, Tooltip, TraitFrame, TraitSlot, TraitStateViewer, TransitionArrow, TrendIndicator, TurnIndicator, TypewriterText, Typography, UISlotComponent, UISlotRenderer, UploadDropZone, VStack, VariablePanel, VersionDiff, ViolationAlert, VoteStack, WaypointMarker, WizardContainer, WizardNavigation, WizardProgress, boardEntity, bool, calculateAttackTargets, calculateValidMoves, cn, createInitialGameState, createSharedEntityStore, createTranslate, createUnitAnimationState, drawSprite, getCurrentFrame, getTileDimensions, inferDirection, isoToScreen, makeAsset, makeAssetMap, mapBookData, num, objAvailableActions, objAvailableEvents, objCurrentState, objIcon, objId, objMaxRules, objName, objRules, objStates, parseEditFocus, parseLessonSegments, parseMarkdownWithCodeBlocks, parseQueryBinding, pendulum, projectileMotion, resolveFieldMap, resolveFrame, resolveSheetDirection, rows, runTickFrame, screenToIso, springOscillator, str, tickAnimationState, toCodeLanguage, transitionAnimation, unitHealth, unitPosition, unitTeam, useAgentChat, useAnchorRect, useAtlasSliceDataUrl, useAuthContext, useCamera, useCanvasGestures, useCompile, useConnectGitHub, useDeepAgentGeneration, useDisconnectGitHub, useDragReorder, useDraggable, useDropZone, useEmitEvent, useEventBus, useEventListener, useExtensions, useFileEditor, useFileSystem, useGameAudio, useGameAudioContext, useGitHubBranches, useGitHubRepo, useGitHubRepos, useGitHubStatus, useImageCache, useInfiniteScroll, useLongPress, useOrbitalHistory, usePreview, usePullToRefresh, useQuerySingleton, useRenderInterpolation, useSharedEntitySnapshot, useSharedEntityStore, useSwipeGesture, useTapReveal, useTraitListens, useTranslate127 as useTranslate, useUIEvents, useUISlotManager, useUnitSpriteAtlas, useValidation, vec2 };
|
package/dist/hooks/index.cjs
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
var react = require('react');
|
|
4
4
|
var logger = require('@almadar/logger');
|
|
5
5
|
var providers = require('@almadar/ui/providers');
|
|
6
|
+
var core = require('@almadar/core');
|
|
6
7
|
var reactQuery = require('@tanstack/react-query');
|
|
7
8
|
|
|
8
9
|
var log = logger.createLogger("almadar:ui:orbital-history");
|
|
@@ -1405,6 +1406,72 @@ function useTraitListens(dispatch, listens, eventBusInstance) {
|
|
|
1405
1406
|
};
|
|
1406
1407
|
}, [eventBus, dispatch, stableListens]);
|
|
1407
1408
|
}
|
|
1409
|
+
var log12 = logger.createLogger("almadar:ui:shared-entity-store");
|
|
1410
|
+
var EMPTY_ENTITY_STATE = {};
|
|
1411
|
+
function createSharedEntityStore() {
|
|
1412
|
+
const states = /* @__PURE__ */ new Map();
|
|
1413
|
+
const subscribers = /* @__PURE__ */ new Map();
|
|
1414
|
+
const getSnapshot = (entityId) => states.get(entityId) ?? EMPTY_ENTITY_STATE;
|
|
1415
|
+
const subscribe = (entityId, callback) => {
|
|
1416
|
+
let set = subscribers.get(entityId);
|
|
1417
|
+
if (!set) {
|
|
1418
|
+
set = /* @__PURE__ */ new Set();
|
|
1419
|
+
subscribers.set(entityId, set);
|
|
1420
|
+
}
|
|
1421
|
+
set.add(callback);
|
|
1422
|
+
return () => {
|
|
1423
|
+
const current = subscribers.get(entityId);
|
|
1424
|
+
if (!current) return;
|
|
1425
|
+
current.delete(callback);
|
|
1426
|
+
if (current.size === 0) {
|
|
1427
|
+
subscribers.delete(entityId);
|
|
1428
|
+
}
|
|
1429
|
+
};
|
|
1430
|
+
};
|
|
1431
|
+
const commit = (entityId, nextState) => {
|
|
1432
|
+
states.set(entityId, nextState);
|
|
1433
|
+
const set = subscribers.get(entityId);
|
|
1434
|
+
if (!set) return;
|
|
1435
|
+
set.forEach((callback) => {
|
|
1436
|
+
try {
|
|
1437
|
+
callback();
|
|
1438
|
+
} catch (error) {
|
|
1439
|
+
log12.error("Shared entity subscriber error", {
|
|
1440
|
+
entityId,
|
|
1441
|
+
error: error instanceof Error ? error : String(error)
|
|
1442
|
+
});
|
|
1443
|
+
}
|
|
1444
|
+
});
|
|
1445
|
+
};
|
|
1446
|
+
const seed = (entityId, initialState) => {
|
|
1447
|
+
if (!states.has(entityId)) {
|
|
1448
|
+
states.set(entityId, initialState);
|
|
1449
|
+
}
|
|
1450
|
+
};
|
|
1451
|
+
return { getSnapshot, subscribe, commit, seed };
|
|
1452
|
+
}
|
|
1453
|
+
function useSharedEntityStore() {
|
|
1454
|
+
const storeRef = react.useRef(null);
|
|
1455
|
+
if (storeRef.current === null) {
|
|
1456
|
+
storeRef.current = createSharedEntityStore();
|
|
1457
|
+
}
|
|
1458
|
+
return storeRef.current;
|
|
1459
|
+
}
|
|
1460
|
+
function useSharedEntitySnapshot(store, entityId) {
|
|
1461
|
+
return react.useSyncExternalStore(
|
|
1462
|
+
(onStoreChange) => store.subscribe(entityId, onStoreChange),
|
|
1463
|
+
() => store.getSnapshot(entityId)
|
|
1464
|
+
);
|
|
1465
|
+
}
|
|
1466
|
+
function runTickFrame(entityId, orderedWriters, store) {
|
|
1467
|
+
let scratch = store.getSnapshot(entityId);
|
|
1468
|
+
for (const writer of orderedWriters) {
|
|
1469
|
+
const writes = writer(scratch);
|
|
1470
|
+
scratch = core.mergeEntityFrame(scratch, writes);
|
|
1471
|
+
}
|
|
1472
|
+
store.commit(entityId, scratch);
|
|
1473
|
+
return scratch;
|
|
1474
|
+
}
|
|
1408
1475
|
var queryStores = /* @__PURE__ */ new Map();
|
|
1409
1476
|
function getOrCreateStore(query) {
|
|
1410
1477
|
if (!queryStores.has(query)) {
|
|
@@ -2740,8 +2807,10 @@ function useGitHubBranches(owner, repo, enabled = true) {
|
|
|
2740
2807
|
exports.ALMADAR_DND_MIME = ALMADAR_DND_MIME;
|
|
2741
2808
|
exports.DEFAULT_SLOTS = DEFAULT_SLOTS;
|
|
2742
2809
|
exports.I18nProvider = I18nProvider;
|
|
2810
|
+
exports.createSharedEntityStore = createSharedEntityStore;
|
|
2743
2811
|
exports.createTranslate = createTranslate;
|
|
2744
2812
|
exports.parseQueryBinding = parseQueryBinding;
|
|
2813
|
+
exports.runTickFrame = runTickFrame;
|
|
2745
2814
|
exports.useAgentChat = useAgentChat;
|
|
2746
2815
|
exports.useAuthContext = useAuthContext;
|
|
2747
2816
|
exports.useCanvasGestures = useCanvasGestures;
|
|
@@ -2769,6 +2838,8 @@ exports.usePreview = usePreview;
|
|
|
2769
2838
|
exports.usePullToRefresh = usePullToRefresh;
|
|
2770
2839
|
exports.useQuerySingleton = useQuerySingleton;
|
|
2771
2840
|
exports.useRenderInterpolation = useRenderInterpolation;
|
|
2841
|
+
exports.useSharedEntitySnapshot = useSharedEntitySnapshot;
|
|
2842
|
+
exports.useSharedEntityStore = useSharedEntityStore;
|
|
2772
2843
|
exports.useSwipeGesture = useSwipeGesture;
|
|
2773
2844
|
exports.useTapReveal = useTapReveal;
|
|
2774
2845
|
exports.useTraitListens = useTraitListens;
|
package/dist/hooks/index.d.ts
CHANGED
|
@@ -16,6 +16,7 @@ export type { BusEvent, BusEventSource, BusEventListener, Unsubscribe, EventBusC
|
|
|
16
16
|
export type { BusEventListener as EventListener } from '../types/event-bus-types';
|
|
17
17
|
export { useUISlotManager, DEFAULT_SLOTS, type UISlot, type SlotAnimation, type SlotContent, type SlotRenderConfig, type SlotChangeCallback, type UISlotManager, } from './useUISlots';
|
|
18
18
|
export { useUIEvents, useTraitListens, type TraitListenSpec } from './useUIEvents';
|
|
19
|
+
export { createSharedEntityStore, useSharedEntityStore, useSharedEntitySnapshot, runTickFrame, type SharedEntityStore, type SharedEntitySubscriber, type SharedEntityWriter, } from './useSharedEntityStore';
|
|
19
20
|
export { useQuerySingleton, parseQueryBinding, type QueryState, type QuerySingletonEntity, type QuerySingletonResult, type QuerySingletonState, } from './useQuerySingleton';
|
|
20
21
|
export { useTranslate, I18nProvider, createTranslate, type TranslateFunction, type I18nContextValue, } from './useTranslate';
|
|
21
22
|
export { useAuthContext, type AuthUser, type AuthContextValue, } from './useAuthContext';
|
package/dist/hooks/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { createContext, useCallback, useState, useEffect, useMemo, useContext, useRef } from 'react';
|
|
1
|
+
import { createContext, useCallback, useState, useEffect, useMemo, useContext, useRef, useSyncExternalStore } from 'react';
|
|
2
2
|
import { createLogger } from '@almadar/logger';
|
|
3
3
|
import { EventBusContext, useTraitScope } from '@almadar/ui/providers';
|
|
4
|
+
import { mergeEntityFrame } from '@almadar/core';
|
|
4
5
|
import { useQuery, useQueryClient, useMutation } from '@tanstack/react-query';
|
|
5
6
|
|
|
6
7
|
var log = createLogger("almadar:ui:orbital-history");
|
|
@@ -1403,6 +1404,72 @@ function useTraitListens(dispatch, listens, eventBusInstance) {
|
|
|
1403
1404
|
};
|
|
1404
1405
|
}, [eventBus, dispatch, stableListens]);
|
|
1405
1406
|
}
|
|
1407
|
+
var log12 = createLogger("almadar:ui:shared-entity-store");
|
|
1408
|
+
var EMPTY_ENTITY_STATE = {};
|
|
1409
|
+
function createSharedEntityStore() {
|
|
1410
|
+
const states = /* @__PURE__ */ new Map();
|
|
1411
|
+
const subscribers = /* @__PURE__ */ new Map();
|
|
1412
|
+
const getSnapshot = (entityId) => states.get(entityId) ?? EMPTY_ENTITY_STATE;
|
|
1413
|
+
const subscribe = (entityId, callback) => {
|
|
1414
|
+
let set = subscribers.get(entityId);
|
|
1415
|
+
if (!set) {
|
|
1416
|
+
set = /* @__PURE__ */ new Set();
|
|
1417
|
+
subscribers.set(entityId, set);
|
|
1418
|
+
}
|
|
1419
|
+
set.add(callback);
|
|
1420
|
+
return () => {
|
|
1421
|
+
const current = subscribers.get(entityId);
|
|
1422
|
+
if (!current) return;
|
|
1423
|
+
current.delete(callback);
|
|
1424
|
+
if (current.size === 0) {
|
|
1425
|
+
subscribers.delete(entityId);
|
|
1426
|
+
}
|
|
1427
|
+
};
|
|
1428
|
+
};
|
|
1429
|
+
const commit = (entityId, nextState) => {
|
|
1430
|
+
states.set(entityId, nextState);
|
|
1431
|
+
const set = subscribers.get(entityId);
|
|
1432
|
+
if (!set) return;
|
|
1433
|
+
set.forEach((callback) => {
|
|
1434
|
+
try {
|
|
1435
|
+
callback();
|
|
1436
|
+
} catch (error) {
|
|
1437
|
+
log12.error("Shared entity subscriber error", {
|
|
1438
|
+
entityId,
|
|
1439
|
+
error: error instanceof Error ? error : String(error)
|
|
1440
|
+
});
|
|
1441
|
+
}
|
|
1442
|
+
});
|
|
1443
|
+
};
|
|
1444
|
+
const seed = (entityId, initialState) => {
|
|
1445
|
+
if (!states.has(entityId)) {
|
|
1446
|
+
states.set(entityId, initialState);
|
|
1447
|
+
}
|
|
1448
|
+
};
|
|
1449
|
+
return { getSnapshot, subscribe, commit, seed };
|
|
1450
|
+
}
|
|
1451
|
+
function useSharedEntityStore() {
|
|
1452
|
+
const storeRef = useRef(null);
|
|
1453
|
+
if (storeRef.current === null) {
|
|
1454
|
+
storeRef.current = createSharedEntityStore();
|
|
1455
|
+
}
|
|
1456
|
+
return storeRef.current;
|
|
1457
|
+
}
|
|
1458
|
+
function useSharedEntitySnapshot(store, entityId) {
|
|
1459
|
+
return useSyncExternalStore(
|
|
1460
|
+
(onStoreChange) => store.subscribe(entityId, onStoreChange),
|
|
1461
|
+
() => store.getSnapshot(entityId)
|
|
1462
|
+
);
|
|
1463
|
+
}
|
|
1464
|
+
function runTickFrame(entityId, orderedWriters, store) {
|
|
1465
|
+
let scratch = store.getSnapshot(entityId);
|
|
1466
|
+
for (const writer of orderedWriters) {
|
|
1467
|
+
const writes = writer(scratch);
|
|
1468
|
+
scratch = mergeEntityFrame(scratch, writes);
|
|
1469
|
+
}
|
|
1470
|
+
store.commit(entityId, scratch);
|
|
1471
|
+
return scratch;
|
|
1472
|
+
}
|
|
1406
1473
|
var queryStores = /* @__PURE__ */ new Map();
|
|
1407
1474
|
function getOrCreateStore(query) {
|
|
1408
1475
|
if (!queryStores.has(query)) {
|
|
@@ -2735,4 +2802,4 @@ function useGitHubBranches(owner, repo, enabled = true) {
|
|
|
2735
2802
|
});
|
|
2736
2803
|
}
|
|
2737
2804
|
|
|
2738
|
-
export { ALMADAR_DND_MIME, DEFAULT_SLOTS, I18nProvider, createTranslate, parseQueryBinding, useAgentChat, useAuthContext, useCanvasGestures, useCompile, useConnectGitHub, useDeepAgentGeneration, useDisconnectGitHub, useDragReorder, useDraggable, useDropZone, useEmitEvent, useEventBus, useEventListener, useExtensions, useFileEditor, useFileSystem, useGitHubBranches, useGitHubRepo, useGitHubRepos, useGitHubStatus, useInfiniteScroll, useLongPress, useOrbitalHistory, usePreview, usePullToRefresh, useQuerySingleton, useRenderInterpolation, useSwipeGesture, useTapReveal, useTraitListens, useTranslate, useUIEvents, useUISlotManager, useValidation };
|
|
2805
|
+
export { ALMADAR_DND_MIME, DEFAULT_SLOTS, I18nProvider, createSharedEntityStore, createTranslate, parseQueryBinding, runTickFrame, useAgentChat, useAuthContext, useCanvasGestures, useCompile, useConnectGitHub, useDeepAgentGeneration, useDisconnectGitHub, useDragReorder, useDraggable, useDropZone, useEmitEvent, useEventBus, useEventListener, useExtensions, useFileEditor, useFileSystem, useGitHubBranches, useGitHubRepo, useGitHubRepos, useGitHubStatus, useInfiniteScroll, useLongPress, useOrbitalHistory, usePreview, usePullToRefresh, useQuerySingleton, useRenderInterpolation, useSharedEntitySnapshot, useSharedEntityStore, useSwipeGesture, useTapReveal, useTraitListens, useTranslate, useUIEvents, useUISlotManager, useValidation };
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type { EntityFieldWrite, EntityFrameState } from '@almadar/core';
|
|
2
|
+
/** Notification callback fired after a `commit()` for the subscribed entity id. */
|
|
3
|
+
export type SharedEntitySubscriber = () => void;
|
|
4
|
+
/**
|
|
5
|
+
* One writer trait's per-frame step: reads the live running scratch
|
|
6
|
+
* (reflecting every earlier writer's writes this frame) and returns its own
|
|
7
|
+
* field writes. Pure — writers never call `store.commit`; only `runTickFrame`
|
|
8
|
+
* does, once per frame.
|
|
9
|
+
*/
|
|
10
|
+
export type SharedEntityWriter = (scratch: EntityFrameState) => readonly EntityFieldWrite[];
|
|
11
|
+
/** Manager surface, keyed by entity id. */
|
|
12
|
+
export interface SharedEntityStore {
|
|
13
|
+
getSnapshot: (entityId: string) => EntityFrameState;
|
|
14
|
+
subscribe: (entityId: string, callback: SharedEntitySubscriber) => () => void;
|
|
15
|
+
commit: (entityId: string, nextState: EntityFrameState) => void;
|
|
16
|
+
/**
|
|
17
|
+
* Set the initial state for an entity id, but ONLY if nothing is committed
|
|
18
|
+
* yet — idempotent, and (unlike `commit`) does NOT notify subscribers, so it
|
|
19
|
+
* is safe to call during render. Both execution paths seed from the entity's
|
|
20
|
+
* declared field defaults at init, so frame 0 reads the defaults on both.
|
|
21
|
+
*/
|
|
22
|
+
seed: (entityId: string, initialState: EntityFrameState) => void;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Create a standalone shared-entity store. Plain factory — no React — so a
|
|
26
|
+
* clock owner (the interpreter's TickScheduler, or a codegen rAF
|
|
27
|
+
* `useEffect`) can hold one instance and pass it to `runTickFrame` without
|
|
28
|
+
* going through a hook.
|
|
29
|
+
*/
|
|
30
|
+
export declare function createSharedEntityStore(): SharedEntityStore;
|
|
31
|
+
/**
|
|
32
|
+
* React hook: one stable `SharedEntityStore` instance for this component's
|
|
33
|
+
* lifetime (useUISlotManager's ref-backed-instance pattern — no re-creation
|
|
34
|
+
* across re-renders). Callers own one store per running orbital instance and
|
|
35
|
+
* thread it to each writer trait plus the render trait via `runTickFrame` /
|
|
36
|
+
* `useSharedEntitySnapshot`.
|
|
37
|
+
*/
|
|
38
|
+
export declare function useSharedEntityStore(): SharedEntityStore;
|
|
39
|
+
/**
|
|
40
|
+
* Bridge one entity's snapshot into React via `useSyncExternalStore` (the
|
|
41
|
+
* codebase's established store->React bridge, see `lib/perf.ts`). The render
|
|
42
|
+
* trait re-renders exactly when `runTickFrame` commits this entity — never on
|
|
43
|
+
* an intermediate per-writer write, since those never call `store.commit`.
|
|
44
|
+
*/
|
|
45
|
+
export declare function useSharedEntitySnapshot(store: SharedEntityStore, entityId: string): EntityFrameState;
|
|
46
|
+
/**
|
|
47
|
+
* Run one frame for `entityId`: fold each writer's writes into a running
|
|
48
|
+
* scratch in binding order via `mergeEntityFrame` (field-level, so writer
|
|
49
|
+
* k+1 reads writer k's same-frame writes), then commit the merged result
|
|
50
|
+
* exactly ONCE. Clock-agnostic — the caller (a TickScheduler tick or a
|
|
51
|
+
* codegen rAF loop) invokes this once per frame; it owns no timer itself.
|
|
52
|
+
*/
|
|
53
|
+
export declare function runTickFrame(entityId: string, orderedWriters: readonly SharedEntityWriter[], store: SharedEntityStore): EntityFrameState;
|