@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
package/dist/avl/index.js
CHANGED
|
@@ -10,7 +10,7 @@ import * as LucideIcons2 from 'lucide-react';
|
|
|
10
10
|
import { Loader2, X, Code, FileText, WrapText, Check, Copy, Lightbulb, CheckCircle, List, Printer, ChevronRight, ChevronLeft, GitBranch, Pencil, Eye, Plus, ArrowRight, Trash, RotateCcw, Play, Terminal, XCircle, AlertTriangle, Trash2, Link2, ZoomOut, ZoomIn, Download, ChevronDown, Menu as Menu$1, Package, Calendar, MoreHorizontal, Image as Image$1, Upload, ArrowLeft, HelpCircle, PauseCircle, Search, Type, Heading1, Heading2, Heading3, ListOrdered, Quote, Minus, Eraser, TrendingUp, TrendingDown, AlertCircle, Circle, Clock, CheckCircle2, Bug, Send, ChevronUp, Wrench, Tag, User, DollarSign } from 'lucide-react';
|
|
11
11
|
import { createPortal } from 'react-dom';
|
|
12
12
|
import { UISlotProvider, useUISlots, useTheme } from '@almadar/ui/context';
|
|
13
|
-
import { evaluateGuard,
|
|
13
|
+
import { evaluateGuard, createMinimalContext, executeEffects, evaluate } from '@almadar/evaluator';
|
|
14
14
|
import { Link, Outlet, useLocation } from 'react-router-dom';
|
|
15
15
|
import SyntaxHighlighter from 'react-syntax-highlighter/dist/esm/prism-light.js';
|
|
16
16
|
import dark from 'react-syntax-highlighter/dist/esm/styles/prism/vsc-dark-plus.js';
|
|
@@ -35,7 +35,7 @@ import ReactMarkdown from 'react-markdown';
|
|
|
35
35
|
import remarkGfm from 'remark-gfm';
|
|
36
36
|
import remarkMath from 'remark-math';
|
|
37
37
|
import rehypeKatex from 'rehype-katex';
|
|
38
|
-
import { FieldTypeSchema, isInlineTrait, isPageReference, isEntityCall, schemaToIR, getPage, isCircuitEvent } from '@almadar/core';
|
|
38
|
+
import { FieldTypeSchema, isInlineTrait, isPageReference, isEntityCall, schemaToIR, getPage, isCircuitEvent, walkSExpr, mergeEntityFrame } from '@almadar/core';
|
|
39
39
|
import { useDroppable, useDraggable, DndContext, DragOverlay, useSensors, useSensor, PointerSensor, KeyboardSensor, pointerWithin, rectIntersection, closestCorners } from '@dnd-kit/core';
|
|
40
40
|
import { sortableKeyboardCoordinates, useSortable, arrayMove, SortableContext, rectSortingStrategy, verticalListSortingStrategy } from '@dnd-kit/sortable';
|
|
41
41
|
import { CSS } from '@dnd-kit/utilities';
|
|
@@ -33249,12 +33249,12 @@ var init_MapView = __esm({
|
|
|
33249
33249
|
shadowSize: [41, 41]
|
|
33250
33250
|
});
|
|
33251
33251
|
L.Marker.prototype.options.icon = defaultIcon;
|
|
33252
|
-
const { useEffect: useEffect71, useRef:
|
|
33252
|
+
const { useEffect: useEffect71, useRef: useRef68, useCallback: useCallback104, useState: useState105 } = React105__default;
|
|
33253
33253
|
const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
|
|
33254
33254
|
const { useEventBus: useEventBus2 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
|
|
33255
33255
|
function MapUpdater({ centerLat, centerLng, zoom }) {
|
|
33256
33256
|
const map = useMap();
|
|
33257
|
-
const prevRef =
|
|
33257
|
+
const prevRef = useRef68({ centerLat, centerLng, zoom });
|
|
33258
33258
|
useEffect71(() => {
|
|
33259
33259
|
const prev = prevRef.current;
|
|
33260
33260
|
if (prev.centerLat !== centerLat || prev.centerLng !== centerLng || prev.zoom !== zoom) {
|
|
@@ -46245,7 +46245,7 @@ function getAllEvents(traits2) {
|
|
|
46245
46245
|
function EventDispatcherTab({ traits: traits2, schema }) {
|
|
46246
46246
|
const eventBus = useEventBus();
|
|
46247
46247
|
const { t } = useTranslate();
|
|
46248
|
-
const [
|
|
46248
|
+
const [log12, setLog] = React105.useState([]);
|
|
46249
46249
|
const prevStatesRef = React105.useRef(/* @__PURE__ */ new Map());
|
|
46250
46250
|
React105.useEffect(() => {
|
|
46251
46251
|
for (const trait of traits2) {
|
|
@@ -46309,9 +46309,9 @@ function EventDispatcherTab({ traits: traits2, schema }) {
|
|
|
46309
46309
|
/* @__PURE__ */ jsx(Typography, { variant: "small", weight: "medium", className: "text-gray-500 mb-1", children: t("debug.otherEvents") }),
|
|
46310
46310
|
/* @__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)) })
|
|
46311
46311
|
] }),
|
|
46312
|
-
|
|
46312
|
+
log12.length > 0 && /* @__PURE__ */ jsxs("div", { children: [
|
|
46313
46313
|
/* @__PURE__ */ jsx(Typography, { variant: "small", weight: "medium", className: "text-gray-500 mb-1", children: t("debug.recentTransitions") }),
|
|
46314
|
-
/* @__PURE__ */ jsx(Stack, { gap: "xs", children:
|
|
46314
|
+
/* @__PURE__ */ jsx(Stack, { gap: "xs", children: log12.map((entry, i) => /* @__PURE__ */ jsxs(Typography, { variant: "small", className: "font-mono text-xs", children: [
|
|
46315
46315
|
/* @__PURE__ */ jsx("span", { className: "text-purple-400", children: entry.traitName }),
|
|
46316
46316
|
" ",
|
|
46317
46317
|
/* @__PURE__ */ jsx("span", { className: "text-gray-500", children: entry.from }),
|
|
@@ -53596,7 +53596,67 @@ function convertFnFormLambdasInProps(props) {
|
|
|
53596
53596
|
|
|
53597
53597
|
// hooks/index.ts
|
|
53598
53598
|
init_useEventBus();
|
|
53599
|
-
var log7 = createLogger("almadar:ui:
|
|
53599
|
+
var log7 = createLogger("almadar:ui:shared-entity-store");
|
|
53600
|
+
var EMPTY_ENTITY_STATE = {};
|
|
53601
|
+
function createSharedEntityStore() {
|
|
53602
|
+
const states = /* @__PURE__ */ new Map();
|
|
53603
|
+
const subscribers2 = /* @__PURE__ */ new Map();
|
|
53604
|
+
const getSnapshot2 = (entityId) => states.get(entityId) ?? EMPTY_ENTITY_STATE;
|
|
53605
|
+
const subscribe = (entityId, callback) => {
|
|
53606
|
+
let set = subscribers2.get(entityId);
|
|
53607
|
+
if (!set) {
|
|
53608
|
+
set = /* @__PURE__ */ new Set();
|
|
53609
|
+
subscribers2.set(entityId, set);
|
|
53610
|
+
}
|
|
53611
|
+
set.add(callback);
|
|
53612
|
+
return () => {
|
|
53613
|
+
const current = subscribers2.get(entityId);
|
|
53614
|
+
if (!current) return;
|
|
53615
|
+
current.delete(callback);
|
|
53616
|
+
if (current.size === 0) {
|
|
53617
|
+
subscribers2.delete(entityId);
|
|
53618
|
+
}
|
|
53619
|
+
};
|
|
53620
|
+
};
|
|
53621
|
+
const commit = (entityId, nextState) => {
|
|
53622
|
+
states.set(entityId, nextState);
|
|
53623
|
+
const set = subscribers2.get(entityId);
|
|
53624
|
+
if (!set) return;
|
|
53625
|
+
set.forEach((callback) => {
|
|
53626
|
+
try {
|
|
53627
|
+
callback();
|
|
53628
|
+
} catch (error) {
|
|
53629
|
+
log7.error("Shared entity subscriber error", {
|
|
53630
|
+
entityId,
|
|
53631
|
+
error: error instanceof Error ? error : String(error)
|
|
53632
|
+
});
|
|
53633
|
+
}
|
|
53634
|
+
});
|
|
53635
|
+
};
|
|
53636
|
+
const seed = (entityId, initialState) => {
|
|
53637
|
+
if (!states.has(entityId)) {
|
|
53638
|
+
states.set(entityId, initialState);
|
|
53639
|
+
}
|
|
53640
|
+
};
|
|
53641
|
+
return { getSnapshot: getSnapshot2, subscribe, commit, seed };
|
|
53642
|
+
}
|
|
53643
|
+
function useSharedEntityStore() {
|
|
53644
|
+
const storeRef = useRef(null);
|
|
53645
|
+
if (storeRef.current === null) {
|
|
53646
|
+
storeRef.current = createSharedEntityStore();
|
|
53647
|
+
}
|
|
53648
|
+
return storeRef.current;
|
|
53649
|
+
}
|
|
53650
|
+
function runTickFrame(entityId, orderedWriters, store) {
|
|
53651
|
+
let scratch = store.getSnapshot(entityId);
|
|
53652
|
+
for (const writer of orderedWriters) {
|
|
53653
|
+
const writes = writer(scratch);
|
|
53654
|
+
scratch = mergeEntityFrame(scratch, writes);
|
|
53655
|
+
}
|
|
53656
|
+
store.commit(entityId, scratch);
|
|
53657
|
+
return scratch;
|
|
53658
|
+
}
|
|
53659
|
+
var log8 = createLogger("almadar:ui:effects:client-handlers");
|
|
53600
53660
|
function createClientEffectHandlers(options) {
|
|
53601
53661
|
const { eventBus, slotSetter, navigate, notify, callService, liveEntity } = options;
|
|
53602
53662
|
return {
|
|
@@ -53605,12 +53665,12 @@ function createClientEffectHandlers(options) {
|
|
|
53605
53665
|
eventBus.emit(prefixedEvent, payload);
|
|
53606
53666
|
},
|
|
53607
53667
|
persist: async () => {
|
|
53608
|
-
|
|
53668
|
+
log8.warn("persist is server-side only, ignored on client");
|
|
53609
53669
|
},
|
|
53610
53670
|
// @almadar/runtime EffectHandlers.set types value:unknown — should be FieldValue (upstream fix queued)
|
|
53611
53671
|
set: ((_entityId, field, value) => {
|
|
53612
53672
|
if (!liveEntity) {
|
|
53613
|
-
|
|
53673
|
+
log8.warn("set is server-side only, ignored on client (no live entity)");
|
|
53614
53674
|
return;
|
|
53615
53675
|
}
|
|
53616
53676
|
liveEntity[field] = value;
|
|
@@ -53642,10 +53702,10 @@ function createClientEffectHandlers(options) {
|
|
|
53642
53702
|
slotSetter.addPattern(slot, pattern, props);
|
|
53643
53703
|
},
|
|
53644
53704
|
navigate: navigate ?? ((path) => {
|
|
53645
|
-
|
|
53705
|
+
log8.warn("No navigate handler, ignoring", { path });
|
|
53646
53706
|
}),
|
|
53647
53707
|
notify: notify ?? ((msg, type) => {
|
|
53648
|
-
|
|
53708
|
+
log8.debug("notify", { type, message: msg });
|
|
53649
53709
|
})
|
|
53650
53710
|
};
|
|
53651
53711
|
}
|
|
@@ -53690,11 +53750,101 @@ function toTraitDefinition(binding) {
|
|
|
53690
53750
|
function normalizeEventKey(eventKey) {
|
|
53691
53751
|
return eventKey.startsWith("UI:") ? eventKey.slice(3) : eventKey;
|
|
53692
53752
|
}
|
|
53753
|
+
var SHARED_ENTITY_WRITE_OPS = /* @__PURE__ */ new Set(["set"]);
|
|
53754
|
+
var SHARED_ENTITY_RENDER_OPS = /* @__PURE__ */ new Set(["render-ui", "render"]);
|
|
53755
|
+
function collectAllTraitEffects(trait) {
|
|
53756
|
+
return [
|
|
53757
|
+
...trait.ticks.flatMap((t) => t.effects),
|
|
53758
|
+
...trait.transitions.flatMap((t) => t.effects)
|
|
53759
|
+
];
|
|
53760
|
+
}
|
|
53761
|
+
function effectsCallOp(effects, ops) {
|
|
53762
|
+
for (const effect of effects) {
|
|
53763
|
+
let found = false;
|
|
53764
|
+
walkSExpr(effect, (node) => {
|
|
53765
|
+
if (!found && Array.isArray(node) && typeof node[0] === "string" && ops.has(node[0])) {
|
|
53766
|
+
found = true;
|
|
53767
|
+
}
|
|
53768
|
+
});
|
|
53769
|
+
if (found) return true;
|
|
53770
|
+
}
|
|
53771
|
+
return false;
|
|
53772
|
+
}
|
|
53773
|
+
function createSharedEntityWriter(binding, tick, traitStatesRef, emit) {
|
|
53774
|
+
return (scratch) => {
|
|
53775
|
+
const traitName = binding.trait.name;
|
|
53776
|
+
const currentState = traitStatesRef.current.get(traitName)?.currentState ?? "";
|
|
53777
|
+
if (tick.appliesTo.length > 0 && !tick.appliesTo.includes(currentState)) return [];
|
|
53778
|
+
const scratchEntity = { ...scratch };
|
|
53779
|
+
const writes = [];
|
|
53780
|
+
const ctx = createMinimalContext(scratchEntity, {}, currentState);
|
|
53781
|
+
const declaredDefaults = collectDeclaredConfigDefaults(binding.trait);
|
|
53782
|
+
const callSiteConfig = binding.config;
|
|
53783
|
+
if (declaredDefaults || callSiteConfig) {
|
|
53784
|
+
ctx.config = { ...declaredDefaults ?? {}, ...callSiteConfig ?? {} };
|
|
53785
|
+
}
|
|
53786
|
+
ctx.mutateEntity = (changes) => {
|
|
53787
|
+
for (const [field, value] of Object.entries(changes)) {
|
|
53788
|
+
const fieldValue = value;
|
|
53789
|
+
scratchEntity[field] = fieldValue;
|
|
53790
|
+
writes.push({ field, value: fieldValue });
|
|
53791
|
+
}
|
|
53792
|
+
};
|
|
53793
|
+
ctx.emit = (event, payload) => {
|
|
53794
|
+
emit(event, payload);
|
|
53795
|
+
};
|
|
53796
|
+
if (tick.guard !== void 0 && !evaluateGuard(tick.guard, ctx)) {
|
|
53797
|
+
tickLog.debug("guard-blocked", { traitName, tick: tick.name, state: currentState });
|
|
53798
|
+
return [];
|
|
53799
|
+
}
|
|
53800
|
+
executeEffects(tick.effects, ctx);
|
|
53801
|
+
return writes;
|
|
53802
|
+
};
|
|
53803
|
+
}
|
|
53693
53804
|
function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
53694
53805
|
const eventBus = useEventBus();
|
|
53695
53806
|
const { entities } = useEntitySchema();
|
|
53696
53807
|
const traitConfigsByName = options?.traitConfigsByName;
|
|
53697
53808
|
const orbitalsByTrait = options?.orbitalsByTrait;
|
|
53809
|
+
const sharedEntityStore = useSharedEntityStore();
|
|
53810
|
+
const sharedGroups = useMemo(() => {
|
|
53811
|
+
const groups = /* @__PURE__ */ new Map();
|
|
53812
|
+
for (const binding of traitBindings) {
|
|
53813
|
+
const linkedEntityName = binding.linkedEntity ?? binding.trait.linkedEntity;
|
|
53814
|
+
if (!linkedEntityName) continue;
|
|
53815
|
+
const entityDef = entities.get(linkedEntityName);
|
|
53816
|
+
if (!entityDef?.shared) continue;
|
|
53817
|
+
const orbitalName = orbitalsByTrait?.[binding.trait.name] ?? "";
|
|
53818
|
+
const storeKey = `${orbitalName}::${linkedEntityName}`;
|
|
53819
|
+
let group = groups.get(storeKey);
|
|
53820
|
+
if (!group) {
|
|
53821
|
+
let defaults;
|
|
53822
|
+
for (const field of entityDef.fields) {
|
|
53823
|
+
if (field.default !== void 0) {
|
|
53824
|
+
(defaults ?? (defaults = {}))[field.name] = field.default;
|
|
53825
|
+
}
|
|
53826
|
+
}
|
|
53827
|
+
group = { storeKey, entityName: linkedEntityName, writerBindings: [], renderBindings: [], defaults };
|
|
53828
|
+
groups.set(storeKey, group);
|
|
53829
|
+
}
|
|
53830
|
+
const allEffects = collectAllTraitEffects(binding.trait);
|
|
53831
|
+
if (effectsCallOp(allEffects, SHARED_ENTITY_WRITE_OPS)) group.writerBindings.push(binding);
|
|
53832
|
+
if (effectsCallOp(allEffects, SHARED_ENTITY_RENDER_OPS)) group.renderBindings.push(binding);
|
|
53833
|
+
}
|
|
53834
|
+
return groups;
|
|
53835
|
+
}, [traitBindings, entities, orbitalsByTrait]);
|
|
53836
|
+
for (const group of sharedGroups.values()) {
|
|
53837
|
+
if (group.defaults) sharedEntityStore.seed(group.storeKey, group.defaults);
|
|
53838
|
+
}
|
|
53839
|
+
const sharedKeyByTraitNameRef = useRef(/* @__PURE__ */ new Map());
|
|
53840
|
+
useEffect(() => {
|
|
53841
|
+
const map = /* @__PURE__ */ new Map();
|
|
53842
|
+
for (const group of sharedGroups.values()) {
|
|
53843
|
+
for (const binding of group.writerBindings) map.set(binding.trait.name, group.storeKey);
|
|
53844
|
+
for (const binding of group.renderBindings) map.set(binding.trait.name, group.storeKey);
|
|
53845
|
+
}
|
|
53846
|
+
sharedKeyByTraitNameRef.current = map;
|
|
53847
|
+
}, [sharedGroups]);
|
|
53698
53848
|
const manager = useMemo(() => {
|
|
53699
53849
|
const traitDefs = traitBindings.map(toTraitDefinition);
|
|
53700
53850
|
const m = new StateMachineManager(traitDefs);
|
|
@@ -53877,14 +54027,21 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
53877
54027
|
};
|
|
53878
54028
|
}, [traitBindings]);
|
|
53879
54029
|
const executeTransitionEffects = useCallback(async (params) => {
|
|
53880
|
-
const { binding, previousState, newState, payload, flushEvent, syncOnly, log:
|
|
54030
|
+
const { binding, previousState, newState, payload, flushEvent, syncOnly, log: log12 } = params;
|
|
53881
54031
|
const traitName = binding.trait.name;
|
|
53882
54032
|
const linkedEntity = binding.linkedEntity || "";
|
|
53883
54033
|
const entityId = payload?.entityId;
|
|
53884
|
-
|
|
53885
|
-
|
|
53886
|
-
|
|
53887
|
-
|
|
54034
|
+
const sharedKey = sharedKeyByTraitNameRef.current.get(traitName);
|
|
54035
|
+
let liveEntity;
|
|
54036
|
+
if (sharedKey !== void 0) {
|
|
54037
|
+
liveEntity = { ...sharedEntityStore.getSnapshot(sharedKey) };
|
|
54038
|
+
} else {
|
|
54039
|
+
let existing = traitFieldStatesRef.current.get(traitName);
|
|
54040
|
+
if (!existing) {
|
|
54041
|
+
existing = {};
|
|
54042
|
+
traitFieldStatesRef.current.set(traitName, existing);
|
|
54043
|
+
}
|
|
54044
|
+
liveEntity = existing;
|
|
53888
54045
|
}
|
|
53889
54046
|
const effects = syncOnly ? params.effects.filter(
|
|
53890
54047
|
(e) => Array.isArray(e) && SYNC_TICK_OPERATORS.has(String(e[0]))
|
|
@@ -53966,7 +54123,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
53966
54123
|
...handlers,
|
|
53967
54124
|
set: async (targetId, field, value) => {
|
|
53968
54125
|
if (baseSet) await baseSet(targetId, field, value);
|
|
53969
|
-
|
|
54126
|
+
log12.debug("set:write", {
|
|
53970
54127
|
traitName,
|
|
53971
54128
|
field,
|
|
53972
54129
|
value: JSON.stringify(value),
|
|
@@ -54006,17 +54163,20 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
54006
54163
|
const executor = new EffectExecutor({ handlers: trackingHandlers, bindings: bindingCtx, context: effectContext });
|
|
54007
54164
|
try {
|
|
54008
54165
|
await executor.executeAll(effects);
|
|
54009
|
-
|
|
54166
|
+
if (sharedKey !== void 0) {
|
|
54167
|
+
sharedEntityStore.commit(sharedKey, liveEntity);
|
|
54168
|
+
}
|
|
54169
|
+
log12.debug("effects:executed", () => ({
|
|
54010
54170
|
traitName,
|
|
54011
54171
|
transition: `${previousState}->${newState}`,
|
|
54012
54172
|
event: flushEvent,
|
|
54013
54173
|
effectCount: effects.length,
|
|
54014
54174
|
emitted: emittedDuringExec.join(","),
|
|
54015
|
-
entityAfter: JSON.stringify(
|
|
54175
|
+
entityAfter: JSON.stringify(liveEntity ?? {}),
|
|
54016
54176
|
slotsTouched: Array.from(pendingSlots.keys()).join(",")
|
|
54017
54177
|
}));
|
|
54018
54178
|
for (const [slot, patterns] of pendingSlots) {
|
|
54019
|
-
|
|
54179
|
+
log12.debug("flush:slot", {
|
|
54020
54180
|
traitName,
|
|
54021
54181
|
slot,
|
|
54022
54182
|
patternCount: patterns.length,
|
|
@@ -54031,7 +54191,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
54031
54191
|
});
|
|
54032
54192
|
}
|
|
54033
54193
|
} catch (error) {
|
|
54034
|
-
|
|
54194
|
+
log12.error("effects:error", {
|
|
54035
54195
|
traitName,
|
|
54036
54196
|
transition: `${previousState}->${newState}`,
|
|
54037
54197
|
event: flushEvent,
|
|
@@ -54040,14 +54200,16 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
54040
54200
|
});
|
|
54041
54201
|
}
|
|
54042
54202
|
return emittedDuringExec;
|
|
54043
|
-
}, [eventBus, flushSlot]);
|
|
54203
|
+
}, [eventBus, flushSlot, sharedEntityStore]);
|
|
54044
54204
|
const runTickEffects = useCallback((tick, binding) => {
|
|
54045
54205
|
const traitName = binding.trait.name;
|
|
54046
54206
|
const currentState = traitStatesRef.current.get(traitName)?.currentState ?? "";
|
|
54047
54207
|
if (tick.appliesTo.length > 0 && !tick.appliesTo.includes(currentState)) return;
|
|
54048
54208
|
if (tick.guard !== void 0) {
|
|
54209
|
+
const sharedKey = sharedKeyByTraitNameRef.current.get(traitName);
|
|
54210
|
+
const entity = sharedKey !== void 0 ? sharedEntityStore.getSnapshot(sharedKey) : traitFieldStatesRef.current.get(traitName) ?? {};
|
|
54049
54211
|
const guardCtx = {
|
|
54050
|
-
entity
|
|
54212
|
+
entity,
|
|
54051
54213
|
payload: {},
|
|
54052
54214
|
state: currentState
|
|
54053
54215
|
};
|
|
@@ -54072,10 +54234,46 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
54072
54234
|
syncOnly: true,
|
|
54073
54235
|
log: tickLog
|
|
54074
54236
|
});
|
|
54075
|
-
}, [executeTransitionEffects]);
|
|
54237
|
+
}, [executeTransitionEffects, sharedEntityStore]);
|
|
54238
|
+
const emitFromSharedWriter = useCallback((event, payload) => {
|
|
54239
|
+
const prefixedEvent = event.startsWith("UI:") ? event : `UI:${event}`;
|
|
54240
|
+
eventBus.emit(prefixedEvent, payload);
|
|
54241
|
+
}, [eventBus]);
|
|
54076
54242
|
useEffect(() => {
|
|
54077
54243
|
const scheduler = createTickScheduler();
|
|
54244
|
+
const writerTraitNames = /* @__PURE__ */ new Set();
|
|
54245
|
+
for (const group of sharedGroups.values()) {
|
|
54246
|
+
const ticksByInterval = /* @__PURE__ */ new Map();
|
|
54247
|
+
for (const binding of group.writerBindings) {
|
|
54248
|
+
writerTraitNames.add(binding.trait.name);
|
|
54249
|
+
for (const tick of binding.trait.ticks ?? []) {
|
|
54250
|
+
const intervalKey = String(tick.interval);
|
|
54251
|
+
const entries = ticksByInterval.get(intervalKey) ?? [];
|
|
54252
|
+
entries.push({ binding, tick });
|
|
54253
|
+
ticksByInterval.set(intervalKey, entries);
|
|
54254
|
+
}
|
|
54255
|
+
}
|
|
54256
|
+
for (const entries of ticksByInterval.values()) {
|
|
54257
|
+
const interval = entries[0].tick.interval;
|
|
54258
|
+
const onDue = () => {
|
|
54259
|
+
const writers = entries.map(
|
|
54260
|
+
({ binding, tick }) => createSharedEntityWriter(binding, tick, traitStatesRef, emitFromSharedWriter)
|
|
54261
|
+
);
|
|
54262
|
+
runTickFrame(group.storeKey, writers, sharedEntityStore);
|
|
54263
|
+
};
|
|
54264
|
+
if (interval === "frame") {
|
|
54265
|
+
scheduler.add(0, onDue);
|
|
54266
|
+
} else if (typeof interval === "number") {
|
|
54267
|
+
scheduler.add(interval, onDue);
|
|
54268
|
+
} else if (isValidCronExpression(interval)) {
|
|
54269
|
+
scheduler.addCron(interval, onDue);
|
|
54270
|
+
} else {
|
|
54271
|
+
scheduler.add(parseDurationString(interval), onDue);
|
|
54272
|
+
}
|
|
54273
|
+
}
|
|
54274
|
+
}
|
|
54078
54275
|
for (const binding of traitBindings) {
|
|
54276
|
+
if (writerTraitNames.has(binding.trait.name)) continue;
|
|
54079
54277
|
for (const tick of binding.trait.ticks ?? []) {
|
|
54080
54278
|
if (tick.interval === "frame") {
|
|
54081
54279
|
scheduler.add(0, () => runTickEffects(tick, binding));
|
|
@@ -54089,7 +54287,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
54089
54287
|
}
|
|
54090
54288
|
}
|
|
54091
54289
|
return () => scheduler.stopAll();
|
|
54092
|
-
}, [traitBindings, runTickEffects]);
|
|
54290
|
+
}, [traitBindings, runTickEffects, sharedGroups, sharedEntityStore, emitFromSharedWriter]);
|
|
54093
54291
|
const processEventQueued = useCallback(async (eventKey, payload) => {
|
|
54094
54292
|
const normalizedEvent = normalizeEventKey(eventKey);
|
|
54095
54293
|
const bindings = traitBindingsRef.current;
|
|
@@ -54433,7 +54631,7 @@ function buildOrbitalsByTrait(schema, resolvedPages = []) {
|
|
|
54433
54631
|
// runtime/OrbPreview.tsx
|
|
54434
54632
|
init_verificationRegistry();
|
|
54435
54633
|
var PERF_NAMESPACE = "almadar:perf:canvas";
|
|
54436
|
-
var
|
|
54634
|
+
var log9 = createLogger(PERF_NAMESPACE);
|
|
54437
54635
|
var RING_SIZE = 50;
|
|
54438
54636
|
var ring = [];
|
|
54439
54637
|
var writeIdx = 0;
|
|
@@ -54484,7 +54682,7 @@ function perfEnd(name, startToken, detail) {
|
|
|
54484
54682
|
}
|
|
54485
54683
|
}
|
|
54486
54684
|
push({ name, durationMs, ts: endTs, detail });
|
|
54487
|
-
|
|
54685
|
+
log9.debug(name, () => ({ durationMs, ...detail ?? {} }));
|
|
54488
54686
|
}
|
|
54489
54687
|
var profilerOnRender = (id, phase, actualDuration, baseDuration, _startTime, commitTime) => {
|
|
54490
54688
|
if (!isEnabled()) return;
|
|
@@ -54494,7 +54692,7 @@ var profilerOnRender = (id, phase, actualDuration, baseDuration, _startTime, com
|
|
|
54494
54692
|
ts: commitTime,
|
|
54495
54693
|
detail: { baseDuration }
|
|
54496
54694
|
});
|
|
54497
|
-
|
|
54695
|
+
log9.debug(`profiler:${id}:${phase}`, () => ({ actualDuration, baseDuration }));
|
|
54498
54696
|
};
|
|
54499
54697
|
|
|
54500
54698
|
// lib/prepareSchemaForPreview.ts
|
|
@@ -55136,7 +55334,7 @@ init_useEventBus();
|
|
|
55136
55334
|
// components/avl/hooks/useCanvasDnd.tsx
|
|
55137
55335
|
init_useEventBus();
|
|
55138
55336
|
init_useAlmadarDndCollision();
|
|
55139
|
-
var
|
|
55337
|
+
var log10 = createLogger("almadar:ui:canvas-dnd");
|
|
55140
55338
|
function useCanvasDraggable({
|
|
55141
55339
|
id,
|
|
55142
55340
|
payload,
|
|
@@ -55175,7 +55373,7 @@ function defaultEmit(eventBus, drop) {
|
|
|
55175
55373
|
if (payload.kind === "pattern") {
|
|
55176
55374
|
const patternType = payload.data["type"];
|
|
55177
55375
|
if (typeof patternType !== "string") {
|
|
55178
|
-
|
|
55376
|
+
log10.warn("default-emit:pattern:missing-type");
|
|
55179
55377
|
return;
|
|
55180
55378
|
}
|
|
55181
55379
|
const out = { patternType, containerNode: target.containerNode };
|
|
@@ -55184,23 +55382,23 @@ function defaultEmit(eventBus, drop) {
|
|
|
55184
55382
|
out.index = resolved.index;
|
|
55185
55383
|
}
|
|
55186
55384
|
eventBus.emit("UI:PATTERN_DROP", out);
|
|
55187
|
-
|
|
55385
|
+
log10.info("default-emit:pattern", { patternType, level: target.level });
|
|
55188
55386
|
return;
|
|
55189
55387
|
}
|
|
55190
55388
|
if (payload.kind === "behavior") {
|
|
55191
55389
|
const behaviorName = payload.data["name"];
|
|
55192
55390
|
if (typeof behaviorName !== "string") {
|
|
55193
|
-
|
|
55391
|
+
log10.warn("default-emit:behavior:missing-name");
|
|
55194
55392
|
return;
|
|
55195
55393
|
}
|
|
55196
55394
|
eventBus.emit("UI:BEHAVIOR_DROP", {
|
|
55197
55395
|
behaviorName,
|
|
55198
55396
|
containerNode: target.containerNode
|
|
55199
55397
|
});
|
|
55200
|
-
|
|
55398
|
+
log10.info("default-emit:behavior", { behaviorName, level: target.level });
|
|
55201
55399
|
return;
|
|
55202
55400
|
}
|
|
55203
|
-
|
|
55401
|
+
log10.debug("default-emit:unhandled-kind", { kind: payload.kind });
|
|
55204
55402
|
}
|
|
55205
55403
|
function CanvasDndProvider({
|
|
55206
55404
|
children,
|
|
@@ -55216,9 +55414,9 @@ function CanvasDndProvider({
|
|
|
55216
55414
|
if (payload) {
|
|
55217
55415
|
setActivePayload(payload);
|
|
55218
55416
|
eventBus.emit("UI:DRAG_START", { kind: payload.kind, data: payload.data });
|
|
55219
|
-
|
|
55417
|
+
log10.info("dragStart", { id: e.active.id, kind: payload.kind });
|
|
55220
55418
|
} else {
|
|
55221
|
-
|
|
55419
|
+
log10.warn("dragStart:missing-payload", { id: e.active.id });
|
|
55222
55420
|
}
|
|
55223
55421
|
}, [eventBus]);
|
|
55224
55422
|
const handleDragEnd = React105__default.useCallback((e) => {
|
|
@@ -55228,7 +55426,7 @@ function CanvasDndProvider({
|
|
|
55228
55426
|
const overData = e.over?.data.current;
|
|
55229
55427
|
const target = overData?.target;
|
|
55230
55428
|
const accepts = overData?.accepts;
|
|
55231
|
-
|
|
55429
|
+
log10.info("dragEnd", {
|
|
55232
55430
|
activeId: e.active.id,
|
|
55233
55431
|
overId: e.over?.id,
|
|
55234
55432
|
hasPayload: !!payload,
|
|
@@ -55240,7 +55438,7 @@ function CanvasDndProvider({
|
|
|
55240
55438
|
}
|
|
55241
55439
|
if (!payload || !target) return;
|
|
55242
55440
|
if (accepts && !accepts.includes(payload.kind)) {
|
|
55243
|
-
|
|
55441
|
+
log10.debug("dragEnd:rejected:kind", { kind: payload.kind, accepts: [...accepts] });
|
|
55244
55442
|
return;
|
|
55245
55443
|
}
|
|
55246
55444
|
const activator = e.activatorEvent;
|
|
@@ -55252,7 +55450,7 @@ function CanvasDndProvider({
|
|
|
55252
55450
|
}, [eventBus, onDrop]);
|
|
55253
55451
|
const handleDragCancel = React105__default.useCallback(() => {
|
|
55254
55452
|
setActivePayload(null);
|
|
55255
|
-
|
|
55453
|
+
log10.info("dragCancel");
|
|
55256
55454
|
}, []);
|
|
55257
55455
|
return /* @__PURE__ */ jsxs(
|
|
55258
55456
|
DndContext,
|
|
@@ -57085,7 +57283,7 @@ init_AvlTransitionLane();
|
|
|
57085
57283
|
init_AvlSwimLane();
|
|
57086
57284
|
init_avl_atom_types();
|
|
57087
57285
|
init_avl_elk_layout();
|
|
57088
|
-
var
|
|
57286
|
+
var log11 = createLogger("almadar:ui:avl:trait-scene");
|
|
57089
57287
|
var SWIM_GUTTER2 = 120;
|
|
57090
57288
|
var CENTER_W2 = 360;
|
|
57091
57289
|
var AvlTraitScene = ({
|
|
@@ -57098,7 +57296,7 @@ var AvlTraitScene = ({
|
|
|
57098
57296
|
const dataKey = useMemo(() => JSON.stringify(data), [data]);
|
|
57099
57297
|
useEffect(() => {
|
|
57100
57298
|
computeTraitLayout(data).then(setLayout).catch((error) => {
|
|
57101
|
-
|
|
57299
|
+
log11.error("computeTraitLayout failed", { error: error instanceof Error ? error : String(error) });
|
|
57102
57300
|
});
|
|
57103
57301
|
}, [dataKey]);
|
|
57104
57302
|
if (!layout) {
|