@almadar/ui 4.6.14 → 4.8.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 +162 -51
- package/dist/avl/index.js +162 -51
- package/dist/components/atoms/Card.d.ts +2 -0
- package/dist/components/index.cjs +38 -70
- package/dist/components/index.js +39 -71
- package/dist/components/molecules/DataGrid.d.ts +1 -3
- package/dist/components/molecules/DataList.d.ts +1 -3
- package/dist/docs/index.d.cts +2 -0
- package/dist/hooks/index.cjs +33 -62
- package/dist/hooks/index.d.ts +1 -1
- package/dist/hooks/index.js +34 -63
- package/dist/hooks/useUIEvents.d.ts +31 -26
- package/dist/lib/index.cjs +3 -3
- package/dist/lib/index.js +3 -3
- package/dist/marketing/index.d.cts +2 -0
- package/dist/providers/index.cjs +6 -9
- package/dist/providers/index.js +6 -9
- package/dist/runtime/OrbPreview.d.ts +9 -1
- package/dist/runtime/index.cjs +159 -48
- package/dist/runtime/index.js +159 -48
- package/dist/runtime/useTraitStateMachine.d.ts +21 -2
- package/package.json +2 -2
package/dist/runtime/index.js
CHANGED
|
@@ -1071,13 +1071,23 @@ function SlotsProvider({ children }) {
|
|
|
1071
1071
|
const setSlotPatterns = useCallback((slot, patterns, source) => {
|
|
1072
1072
|
const sourceKey = source?.trait ?? DEFAULT_SOURCE_KEY;
|
|
1073
1073
|
const entityProp = patterns[0]?.pattern && typeof patterns[0].pattern === "object" ? patterns[0].pattern.entity : void 0;
|
|
1074
|
+
const firstPatternType = patterns[0]?.pattern && typeof patterns[0].pattern === "object" ? patterns[0].pattern.type : void 0;
|
|
1074
1075
|
slotLog.debug("setSlotPatterns", {
|
|
1075
1076
|
slot,
|
|
1076
1077
|
sourceKey,
|
|
1077
1078
|
patternCount: patterns.length,
|
|
1078
|
-
firstPatternType
|
|
1079
|
+
firstPatternType,
|
|
1079
1080
|
entityRefId: refId(entityProp)
|
|
1080
1081
|
});
|
|
1082
|
+
if (source?.trait) {
|
|
1083
|
+
xOrbitalLog.info("slot-set", {
|
|
1084
|
+
slot,
|
|
1085
|
+
sourceTrait: source.trait,
|
|
1086
|
+
patternCount: patterns.length,
|
|
1087
|
+
firstPatternType,
|
|
1088
|
+
state: source.state
|
|
1089
|
+
});
|
|
1090
|
+
}
|
|
1081
1091
|
setSlots((prev) => {
|
|
1082
1092
|
const prevSlot = prev[slot] ?? {};
|
|
1083
1093
|
return {
|
|
@@ -1099,6 +1109,7 @@ function SlotsProvider({ children }) {
|
|
|
1099
1109
|
});
|
|
1100
1110
|
}, []);
|
|
1101
1111
|
const clearSlotForSource = useCallback((slot, sourceTrait) => {
|
|
1112
|
+
xOrbitalLog.info("slot-clear-source", { slot, sourceTrait });
|
|
1102
1113
|
setSlots((prev) => {
|
|
1103
1114
|
const existing = prev[slot];
|
|
1104
1115
|
if (!existing || !(sourceTrait in existing)) return prev;
|
|
@@ -1139,11 +1150,12 @@ function useSlotsActions() {
|
|
|
1139
1150
|
}
|
|
1140
1151
|
return actions;
|
|
1141
1152
|
}
|
|
1142
|
-
var slotLog, refIds, nextRefId, DEFAULT_SOURCE_KEY, SlotsStateContext, SlotsActionsContext;
|
|
1153
|
+
var slotLog, xOrbitalLog, refIds, nextRefId, DEFAULT_SOURCE_KEY, SlotsStateContext, SlotsActionsContext;
|
|
1143
1154
|
var init_SlotsContext = __esm({
|
|
1144
1155
|
"runtime/ui/SlotsContext.tsx"() {
|
|
1145
1156
|
init_logger();
|
|
1146
1157
|
slotLog = createLogger("almadar:ui:slot-render");
|
|
1158
|
+
xOrbitalLog = createLogger("almadar:runtime:cross-orbital");
|
|
1147
1159
|
refIds = /* @__PURE__ */ new WeakMap();
|
|
1148
1160
|
nextRefId = 1;
|
|
1149
1161
|
DEFAULT_SOURCE_KEY = "__default__";
|
|
@@ -8137,7 +8149,7 @@ var init_MapView = __esm({
|
|
|
8137
8149
|
shadowSize: [41, 41]
|
|
8138
8150
|
});
|
|
8139
8151
|
L.Marker.prototype.options.icon = defaultIcon;
|
|
8140
|
-
const { useEffect: useEffect68, useRef: useRef65, useCallback: useCallback110, useState:
|
|
8152
|
+
const { useEffect: useEffect68, useRef: useRef65, useCallback: useCallback110, useState: useState102 } = React115__default;
|
|
8141
8153
|
const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
|
|
8142
8154
|
const { useEventBus: useEventBus2 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
|
|
8143
8155
|
function MapUpdater({ centerLat, centerLng, zoom }) {
|
|
@@ -8181,7 +8193,7 @@ var init_MapView = __esm({
|
|
|
8181
8193
|
showAttribution = true
|
|
8182
8194
|
}) {
|
|
8183
8195
|
const eventBus = useEventBus2();
|
|
8184
|
-
const [clickedPosition, setClickedPosition] =
|
|
8196
|
+
const [clickedPosition, setClickedPosition] = useState102(null);
|
|
8185
8197
|
const handleMapClick = useCallback110((lat, lng) => {
|
|
8186
8198
|
if (showClickedPin) {
|
|
8187
8199
|
setClickedPosition({ lat, lng });
|
|
@@ -18494,8 +18506,7 @@ function formatValue(value, format) {
|
|
|
18494
18506
|
}
|
|
18495
18507
|
function DataGrid({
|
|
18496
18508
|
entity,
|
|
18497
|
-
fields
|
|
18498
|
-
columns: columnsProp,
|
|
18509
|
+
fields,
|
|
18499
18510
|
itemActions,
|
|
18500
18511
|
cols,
|
|
18501
18512
|
gap = "md",
|
|
@@ -18516,7 +18527,6 @@ function DataGrid({
|
|
|
18516
18527
|
const { t } = useTranslate();
|
|
18517
18528
|
const [selectedIds, setSelectedIds] = useState(/* @__PURE__ */ new Set());
|
|
18518
18529
|
const [visibleCount, setVisibleCount] = useState(pageSize || Infinity);
|
|
18519
|
-
const fields = fieldsProp ?? columnsProp ?? [];
|
|
18520
18530
|
const allData = Array.isArray(entity) ? entity : entity ? [entity] : [];
|
|
18521
18531
|
const data = pageSize > 0 ? allData.slice(0, visibleCount) : allData;
|
|
18522
18532
|
const hasMoreLocal = pageSize > 0 && visibleCount < allData.length;
|
|
@@ -18859,8 +18869,7 @@ function groupData(items, field) {
|
|
|
18859
18869
|
}
|
|
18860
18870
|
function DataList({
|
|
18861
18871
|
entity,
|
|
18862
|
-
fields
|
|
18863
|
-
columns: columnsProp,
|
|
18872
|
+
fields,
|
|
18864
18873
|
itemActions,
|
|
18865
18874
|
gap = "none",
|
|
18866
18875
|
variant = "default",
|
|
@@ -18889,7 +18898,6 @@ function DataList({
|
|
|
18889
18898
|
const eventBus = useEventBus();
|
|
18890
18899
|
const { t } = useTranslate();
|
|
18891
18900
|
const [visibleCount, setVisibleCount] = React115__default.useState(pageSize || Infinity);
|
|
18892
|
-
const fields = fieldsProp ?? columnsProp ?? [];
|
|
18893
18901
|
const allData = Array.isArray(entity) ? entity : entity ? [entity] : [];
|
|
18894
18902
|
const data = pageSize > 0 ? allData.slice(0, visibleCount) : allData;
|
|
18895
18903
|
const hasMoreLocal = pageSize > 0 && visibleCount < allData.length;
|
|
@@ -38134,6 +38142,7 @@ function useTraitStateMachine(traitBindings, slotsActions, options) {
|
|
|
38134
38142
|
const eventBus = useEventBus();
|
|
38135
38143
|
const { entities } = useEntitySchema();
|
|
38136
38144
|
const traitConfigsByName = options?.traitConfigsByName;
|
|
38145
|
+
const orbitalsByTrait = options?.orbitalsByTrait;
|
|
38137
38146
|
const manager = useMemo(() => {
|
|
38138
38147
|
const traitDefs = traitBindings.map(toTraitDefinition);
|
|
38139
38148
|
const m = new StateMachineManager(traitDefs);
|
|
@@ -38582,7 +38591,10 @@ function useTraitStateMachine(traitBindings, slotsActions, options) {
|
|
|
38582
38591
|
if (!LIFECYCLE_EVENTS.has(normalizedEvent)) {
|
|
38583
38592
|
for (const { traitName, result } of results) {
|
|
38584
38593
|
if (!result.executed) continue;
|
|
38585
|
-
|
|
38594
|
+
const orbitalName = orbitalsByTrait?.[traitName];
|
|
38595
|
+
if (!orbitalName) continue;
|
|
38596
|
+
eventBus.emit(`UI:${orbitalName}.${traitName}.${normalizedEvent}`, payload, {
|
|
38597
|
+
orbital: orbitalName,
|
|
38586
38598
|
trait: traitName,
|
|
38587
38599
|
fromBridge: true
|
|
38588
38600
|
});
|
|
@@ -38593,7 +38605,13 @@ function useTraitStateMachine(traitBindings, slotsActions, options) {
|
|
|
38593
38605
|
}
|
|
38594
38606
|
const onEventProcessed = optionsRef.current?.onEventProcessed;
|
|
38595
38607
|
if (onEventProcessed) {
|
|
38596
|
-
|
|
38608
|
+
const dispatchedOrbitals = /* @__PURE__ */ new Set();
|
|
38609
|
+
for (const { traitName, result } of results) {
|
|
38610
|
+
if (!result.executed) continue;
|
|
38611
|
+
const orbital = orbitalsByTrait?.[traitName];
|
|
38612
|
+
if (orbital) dispatchedOrbitals.add(orbital);
|
|
38613
|
+
}
|
|
38614
|
+
await onEventProcessed(normalizedEvent, payload, dispatchedOrbitals);
|
|
38597
38615
|
}
|
|
38598
38616
|
}, [entities, eventBus]);
|
|
38599
38617
|
const drainEventQueue = useCallback(async () => {
|
|
@@ -38637,26 +38655,34 @@ function useTraitStateMachine(traitBindings, slotsActions, options) {
|
|
|
38637
38655
|
}
|
|
38638
38656
|
console.log("[TraitStateMachine] Subscribing to events:", Array.from(allEvents));
|
|
38639
38657
|
const unsubscribes = [];
|
|
38640
|
-
for (const
|
|
38641
|
-
|
|
38642
|
-
|
|
38658
|
+
for (const binding of traitBindings) {
|
|
38659
|
+
const traitName = binding.trait.name;
|
|
38660
|
+
const orbitalName = orbitalsByTrait?.[traitName];
|
|
38661
|
+
if (!orbitalName) continue;
|
|
38662
|
+
for (const transition of binding.trait.transitions) {
|
|
38663
|
+
const eventKey = transition.event;
|
|
38664
|
+
if (eventKey === "INIT" || eventKey === "LOAD" || eventKey === "$MOUNT") {
|
|
38665
|
+
continue;
|
|
38666
|
+
}
|
|
38667
|
+
const unsub = eventBus.on(`UI:${orbitalName}.${traitName}.${eventKey}`, (event) => {
|
|
38668
|
+
if (event.source && event.source.fromBridge) {
|
|
38669
|
+
return;
|
|
38670
|
+
}
|
|
38671
|
+
enqueueAndDrain(eventKey, event.payload);
|
|
38672
|
+
});
|
|
38673
|
+
unsubscribes.push(unsub);
|
|
38643
38674
|
}
|
|
38644
|
-
const unsub = eventBus.on(`UI:${eventKey}`, (event) => {
|
|
38645
|
-
console.log("[TraitStateMachine] Received event:", `UI:${eventKey}`, event);
|
|
38646
|
-
enqueueAndDrain(eventKey, event.payload);
|
|
38647
|
-
});
|
|
38648
|
-
unsubscribes.push(unsub);
|
|
38649
38675
|
}
|
|
38650
38676
|
for (const binding of traitBindings) {
|
|
38677
|
+
const ownOrbital = orbitalsByTrait?.[binding.trait.name];
|
|
38651
38678
|
const listens = binding.trait.listens ?? [];
|
|
38652
38679
|
for (const listen of listens) {
|
|
38653
|
-
const
|
|
38654
|
-
|
|
38655
|
-
|
|
38656
|
-
|
|
38657
|
-
|
|
38658
|
-
|
|
38659
|
-
console.log("[TraitStateMachine] listens", binding.trait.name, listen.event, "\u2192", listen.triggers, "from", event.source?.trait);
|
|
38680
|
+
const sourceTrait = listen.source?.trait;
|
|
38681
|
+
if (!sourceTrait) continue;
|
|
38682
|
+
const sourceOrbital = listen.source?.orbital ?? ownOrbital;
|
|
38683
|
+
if (!sourceOrbital) continue;
|
|
38684
|
+
const busKey = `UI:${sourceOrbital}.${sourceTrait}.${listen.event}`;
|
|
38685
|
+
const unsub = eventBus.on(busKey, (event) => {
|
|
38660
38686
|
enqueueAndDrain(listen.triggers, event.payload);
|
|
38661
38687
|
});
|
|
38662
38688
|
unsubscribes.push(unsub);
|
|
@@ -38803,6 +38829,8 @@ init_EntitySchemaContext();
|
|
|
38803
38829
|
|
|
38804
38830
|
// runtime/ServerBridge.tsx
|
|
38805
38831
|
init_useEventBus();
|
|
38832
|
+
init_logger();
|
|
38833
|
+
var xOrbitalLog2 = createLogger("almadar:runtime:cross-orbital");
|
|
38806
38834
|
var ServerBridgeContext = createContext(null);
|
|
38807
38835
|
function useServerBridge() {
|
|
38808
38836
|
const ctx = useContext(ServerBridgeContext);
|
|
@@ -38880,8 +38908,22 @@ function ServerBridgeProvider({
|
|
|
38880
38908
|
}
|
|
38881
38909
|
if (result.emittedEvents) {
|
|
38882
38910
|
for (const emitted of result.emittedEvents) {
|
|
38883
|
-
|
|
38884
|
-
|
|
38911
|
+
const evTrait = emitted.source?.trait;
|
|
38912
|
+
if (!evTrait) {
|
|
38913
|
+
xOrbitalLog2.warn("emit:dropped-no-source", {
|
|
38914
|
+
event: emitted.event,
|
|
38915
|
+
dispatchOrbital: orbitalName
|
|
38916
|
+
});
|
|
38917
|
+
continue;
|
|
38918
|
+
}
|
|
38919
|
+
const key = emitted.source?.orbital ? `UI:${emitted.source.orbital}.${evTrait}.${emitted.event}` : `UI:${evTrait}.${emitted.event}`;
|
|
38920
|
+
xOrbitalLog2.info("emit:rebroadcast", {
|
|
38921
|
+
busKey: key,
|
|
38922
|
+
sourceOrbital: emitted.source?.orbital,
|
|
38923
|
+
sourceTrait: evTrait,
|
|
38924
|
+
dispatchOrbital: orbitalName
|
|
38925
|
+
});
|
|
38926
|
+
eventBus.emit(key, emitted.payload);
|
|
38885
38927
|
}
|
|
38886
38928
|
}
|
|
38887
38929
|
} else if (result.error) {
|
|
@@ -39002,6 +39044,10 @@ function prepareSchemaForPreview(input) {
|
|
|
39002
39044
|
const schema = adjustSchemaForMockData(parsed, mockData);
|
|
39003
39045
|
return { schema, mockData };
|
|
39004
39046
|
}
|
|
39047
|
+
|
|
39048
|
+
// runtime/OrbPreview.tsx
|
|
39049
|
+
init_logger();
|
|
39050
|
+
var xOrbitalLog3 = createLogger("almadar:runtime:cross-orbital");
|
|
39005
39051
|
function normalizeChild(child) {
|
|
39006
39052
|
if (typeof child === "string") return child;
|
|
39007
39053
|
if (child === null || typeof child !== "object" || Array.isArray(child)) {
|
|
@@ -39081,6 +39127,11 @@ function applyServerEffects(effects, uiSlots, onNavigate) {
|
|
|
39081
39127
|
const patternRecord = eff.pattern;
|
|
39082
39128
|
const { type: patternType, children, ...inlineProps } = patternRecord;
|
|
39083
39129
|
const normalizedChildren = Array.isArray(children) ? children.map((c) => normalizeChild(c)) : children;
|
|
39130
|
+
xOrbitalLog3.info("slot-write", {
|
|
39131
|
+
slot: eff.slot,
|
|
39132
|
+
sourceTrait: eff.traitName ?? "server",
|
|
39133
|
+
patternType: typeof patternType === "string" ? patternType : void 0
|
|
39134
|
+
});
|
|
39084
39135
|
uiSlots.render({
|
|
39085
39136
|
target: eff.slot,
|
|
39086
39137
|
pattern: patternType,
|
|
@@ -39095,19 +39146,26 @@ function applyServerEffects(effects, uiSlots, onNavigate) {
|
|
|
39095
39146
|
}
|
|
39096
39147
|
}
|
|
39097
39148
|
}
|
|
39098
|
-
function TraitInitializer({ traits: traits2, orbitalNames, onNavigate, onLocalFallback, persistence, traitConfigsByName }) {
|
|
39149
|
+
function TraitInitializer({ traits: traits2, orbitalNames, onNavigate, onLocalFallback, persistence, traitConfigsByName, orbitalsByTrait }) {
|
|
39099
39150
|
const slotsActions = useSlotsActions();
|
|
39100
39151
|
const bridge = useServerBridge();
|
|
39101
39152
|
const uiSlots = useUISlots();
|
|
39102
|
-
const onEventProcessed = useCallback(async (event, payload) => {
|
|
39153
|
+
const onEventProcessed = useCallback(async (event, payload, dispatchedOrbitals) => {
|
|
39103
39154
|
if (!bridge.connected || !orbitalNames?.length) return;
|
|
39104
|
-
|
|
39155
|
+
const targets = dispatchedOrbitals && dispatchedOrbitals.size > 0 ? orbitalNames.filter((n) => dispatchedOrbitals.has(n)) : orbitalNames;
|
|
39156
|
+
xOrbitalLog3.info("TraitInitializer:fanout", {
|
|
39157
|
+
event,
|
|
39158
|
+
sentTo: targets,
|
|
39159
|
+
skipped: orbitalNames.filter((n) => !targets.includes(n)),
|
|
39160
|
+
dispatchedOrbitalsSize: dispatchedOrbitals?.size ?? 0
|
|
39161
|
+
});
|
|
39162
|
+
for (const name of targets) {
|
|
39105
39163
|
const { effects, meta } = await bridge.sendEvent(name, event, payload);
|
|
39106
39164
|
recordServerResponse(name, event, meta);
|
|
39107
39165
|
applyServerEffects(effects, uiSlots, onNavigate);
|
|
39108
39166
|
}
|
|
39109
39167
|
}, [bridge.connected, bridge.sendEvent, orbitalNames, uiSlots, onNavigate]);
|
|
39110
|
-
const opts = orbitalNames ? { onEventProcessed, navigate: onNavigate, traitConfigsByName } : { navigate: onNavigate, persistence, traitConfigsByName };
|
|
39168
|
+
const opts = orbitalNames ? { onEventProcessed, navigate: onNavigate, traitConfigsByName, orbitalsByTrait } : { navigate: onNavigate, persistence, traitConfigsByName, orbitalsByTrait };
|
|
39111
39169
|
const { sendEvent } = useTraitStateMachine(traits2, slotsActions, opts);
|
|
39112
39170
|
const initSentRef = useRef(false);
|
|
39113
39171
|
useEffect(() => {
|
|
@@ -39157,27 +39215,68 @@ function SchemaRunner({ schema, serverUrl, mockData, pageName, onNavigate, onLoc
|
|
|
39157
39215
|
const allPageTraits = useMemo(() => {
|
|
39158
39216
|
if (pageName && traits2.length > 0) return traits2;
|
|
39159
39217
|
if (!ir?.pages || ir.pages.size <= 1) return traits2;
|
|
39160
|
-
const
|
|
39218
|
+
const firstPage = ir.pages.values().next().value;
|
|
39219
|
+
if (!firstPage) return traits2;
|
|
39220
|
+
const firstPageTraits = [];
|
|
39161
39221
|
const seen = /* @__PURE__ */ new Set();
|
|
39162
|
-
for (const
|
|
39163
|
-
|
|
39164
|
-
|
|
39165
|
-
|
|
39166
|
-
|
|
39167
|
-
if (name && !seen.has(name)) {
|
|
39168
|
-
seen.add(name);
|
|
39169
|
-
combined.push(t);
|
|
39170
|
-
}
|
|
39222
|
+
for (const binding of firstPage.traits) {
|
|
39223
|
+
const name = binding.trait.name;
|
|
39224
|
+
if (name && !seen.has(name)) {
|
|
39225
|
+
seen.add(name);
|
|
39226
|
+
firstPageTraits.push(binding);
|
|
39171
39227
|
}
|
|
39172
39228
|
}
|
|
39173
|
-
return
|
|
39229
|
+
return firstPageTraits.length > 0 ? firstPageTraits : traits2;
|
|
39174
39230
|
}, [ir, traits2, pageName]);
|
|
39175
|
-
|
|
39231
|
+
useMemo(() => {
|
|
39176
39232
|
const parsed = schema;
|
|
39177
39233
|
const orbitals = parsed?.orbitals;
|
|
39178
39234
|
if (!orbitals) return [];
|
|
39179
39235
|
return orbitals.filter((o) => typeof o.name === "string").map((o) => o.name);
|
|
39180
39236
|
}, [schema]);
|
|
39237
|
+
const orbitalsByTrait = useMemo(() => {
|
|
39238
|
+
const map = {};
|
|
39239
|
+
const parsed = schema;
|
|
39240
|
+
if (!parsed?.orbitals) return map;
|
|
39241
|
+
for (const orb of parsed.orbitals) {
|
|
39242
|
+
for (const traitRef of orb.traits) {
|
|
39243
|
+
let traitName;
|
|
39244
|
+
if (typeof traitRef === "string") {
|
|
39245
|
+
const parts = traitRef.split(".");
|
|
39246
|
+
traitName = parts[parts.length - 1];
|
|
39247
|
+
} else if ("ref" in traitRef && typeof traitRef.ref === "string") {
|
|
39248
|
+
const parts = traitRef.ref.split(".");
|
|
39249
|
+
traitName = traitRef.name ?? parts[parts.length - 1];
|
|
39250
|
+
} else if ("name" in traitRef && typeof traitRef.name === "string") {
|
|
39251
|
+
traitName = traitRef.name;
|
|
39252
|
+
}
|
|
39253
|
+
if (traitName) map[traitName] = orb.name;
|
|
39254
|
+
}
|
|
39255
|
+
}
|
|
39256
|
+
return map;
|
|
39257
|
+
}, [schema]);
|
|
39258
|
+
const pageOrbitalNames = useMemo(() => {
|
|
39259
|
+
const set = /* @__PURE__ */ new Set();
|
|
39260
|
+
for (const binding of allPageTraits) {
|
|
39261
|
+
const orb = orbitalsByTrait[binding.trait.name];
|
|
39262
|
+
if (orb) set.add(orb);
|
|
39263
|
+
}
|
|
39264
|
+
return Array.from(set);
|
|
39265
|
+
}, [allPageTraits, orbitalsByTrait]);
|
|
39266
|
+
useEffect(() => {
|
|
39267
|
+
const traitNames = allPageTraits.map((b) => b.trait.name);
|
|
39268
|
+
const orbitalsByTraitForPage = {};
|
|
39269
|
+
for (const name of traitNames) {
|
|
39270
|
+
const orb = orbitalsByTrait[name];
|
|
39271
|
+
if (orb) orbitalsByTraitForPage[name] = orb;
|
|
39272
|
+
}
|
|
39273
|
+
xOrbitalLog3.info("SchemaRunner:mount", {
|
|
39274
|
+
pageName,
|
|
39275
|
+
traitNames,
|
|
39276
|
+
orbitalsByTraitForPage,
|
|
39277
|
+
pageOrbitalNames: pageOrbitalNames.join(",")
|
|
39278
|
+
});
|
|
39279
|
+
}, [pageName, allPageTraits, orbitalsByTrait, pageOrbitalNames]);
|
|
39181
39280
|
const traitConfigsByName = useMemo(() => {
|
|
39182
39281
|
const map = {};
|
|
39183
39282
|
const parsed = schema;
|
|
@@ -39218,8 +39317,9 @@ function SchemaRunner({ schema, serverUrl, mockData, pageName, onNavigate, onLoc
|
|
|
39218
39317
|
TraitInitializer,
|
|
39219
39318
|
{
|
|
39220
39319
|
traits: allPageTraits,
|
|
39221
|
-
orbitalNames: serverUrl ?
|
|
39320
|
+
orbitalNames: serverUrl ? pageOrbitalNames : void 0,
|
|
39222
39321
|
traitConfigsByName,
|
|
39322
|
+
orbitalsByTrait,
|
|
39223
39323
|
onNavigate,
|
|
39224
39324
|
onLocalFallback,
|
|
39225
39325
|
persistence
|
|
@@ -39241,7 +39341,8 @@ function OrbPreview({
|
|
|
39241
39341
|
autoMock = false,
|
|
39242
39342
|
height = "400px",
|
|
39243
39343
|
className,
|
|
39244
|
-
serverUrl
|
|
39344
|
+
serverUrl,
|
|
39345
|
+
initialPagePath
|
|
39245
39346
|
}) {
|
|
39246
39347
|
const [localFallback, setLocalFallback] = useState(false);
|
|
39247
39348
|
const eventBus = useEventBus();
|
|
@@ -39287,7 +39388,17 @@ function OrbPreview({
|
|
|
39287
39388
|
return [];
|
|
39288
39389
|
}
|
|
39289
39390
|
}, [parsedSchema]);
|
|
39290
|
-
const
|
|
39391
|
+
const initialPageName = useMemo(() => {
|
|
39392
|
+
if (!initialPagePath) return void 0;
|
|
39393
|
+
const match = pages.find(({ page }) => page.path === initialPagePath);
|
|
39394
|
+
return match?.page.name;
|
|
39395
|
+
}, [pages, initialPagePath]);
|
|
39396
|
+
const [currentPage, setCurrentPage] = useState(initialPageName);
|
|
39397
|
+
useEffect(() => {
|
|
39398
|
+
if (initialPageName && initialPageName !== currentPage) {
|
|
39399
|
+
setCurrentPage(initialPageName);
|
|
39400
|
+
}
|
|
39401
|
+
}, [initialPageName, currentPage]);
|
|
39291
39402
|
const handleNavigate = useCallback((path) => {
|
|
39292
39403
|
const match = pages.find(({ page }) => page.path === path);
|
|
39293
39404
|
if (match) {
|
|
@@ -32,8 +32,18 @@ export interface TraitStateMachineResult {
|
|
|
32
32
|
canHandleEvent: (traitName: string, eventKey: string) => boolean;
|
|
33
33
|
}
|
|
34
34
|
export interface UseTraitStateMachineOptions {
|
|
35
|
-
/**
|
|
36
|
-
|
|
35
|
+
/**
|
|
36
|
+
* Callback invoked after each event is processed (for server forwarding).
|
|
37
|
+
*
|
|
38
|
+
* `dispatchedOrbitals` is the set of orbital names whose traits actually
|
|
39
|
+
* executed a transition for this event. The server-bridge fan-out should
|
|
40
|
+
* be scoped to this set; sending the event to other orbitals fires
|
|
41
|
+
* same-named transitions in unrelated orbitals and stacks their UI into
|
|
42
|
+
* the wrong slot (gap #11 in `docs/Almadar_Std_Verification.md`). Empty
|
|
43
|
+
* set means no local transition matched — leave the legacy fallback to
|
|
44
|
+
* the consumer.
|
|
45
|
+
*/
|
|
46
|
+
onEventProcessed?: (eventKey: string, payload?: EventPayload, dispatchedOrbitals?: Set<string>) => void | Promise<void>;
|
|
37
47
|
/** Router navigate function for navigate effects */
|
|
38
48
|
navigate?: (path: string, params?: Record<string, unknown>) => void;
|
|
39
49
|
/** Notification function for notify effects */
|
|
@@ -57,6 +67,15 @@ export interface UseTraitStateMachineOptions {
|
|
|
57
67
|
* caller assembles this map from the orbital schema directly.
|
|
58
68
|
*/
|
|
59
69
|
traitConfigsByName?: Record<string, import('@almadar/core').TraitConfig>;
|
|
70
|
+
/**
|
|
71
|
+
* Trait → orbital map built from `schema.orbitals[].traits[]` by the
|
|
72
|
+
* caller. Threaded down so bus emits (`UI:Orbital.Trait.Event`) and
|
|
73
|
+
* subscriptions can carry the qualified `Orbital.Trait` scope —
|
|
74
|
+
* gap #13 unification. Same mechanism as `traitConfigsByName`: the
|
|
75
|
+
* orbital boundary doesn't propagate through `@almadar/core`'s
|
|
76
|
+
* `ResolvedTraitBinding`, so the caller assembles the map directly.
|
|
77
|
+
*/
|
|
78
|
+
orbitalsByTrait?: Record<string, string>;
|
|
60
79
|
}
|
|
61
80
|
/**
|
|
62
81
|
* useTraitStateMachine - Manages state machines for multiple traits
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@almadar/ui",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.8.0",
|
|
4
4
|
"description": "React UI components, hooks, and providers for Almadar",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/components/index.js",
|
|
@@ -121,7 +121,7 @@
|
|
|
121
121
|
"@almadar/core": "^7.0.0",
|
|
122
122
|
"@almadar/evaluator": ">=2.9.2",
|
|
123
123
|
"@almadar/patterns": ">=2.17.1",
|
|
124
|
-
"@almadar/runtime": "^5.
|
|
124
|
+
"@almadar/runtime": "^5.5.0",
|
|
125
125
|
"@almadar/std": ">=6.4.1",
|
|
126
126
|
"@almadar/syntax": ">=1.3.1",
|
|
127
127
|
"@xyflow/react": "12.10.1",
|