@almadar/ui 4.10.7 → 4.12.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 +189 -56
- package/dist/avl/index.js +189 -56
- package/dist/components/index.cjs +12 -1
- package/dist/components/index.js +12 -1
- package/dist/context/index.cjs +12 -1
- package/dist/context/index.js +12 -1
- package/dist/hooks/index.cjs +12 -1
- package/dist/hooks/index.js +12 -1
- package/dist/hooks/useUISlots.d.ts +14 -0
- package/dist/runtime/BrowserPlayground.d.ts +34 -0
- package/dist/runtime/OrbPreview.d.ts +8 -1
- package/dist/runtime/ServerBridge.d.ts +58 -2
- package/dist/runtime/embedded-traits.d.ts +32 -0
- package/dist/runtime/index.cjs +227 -59
- package/dist/runtime/index.d.ts +2 -1
- package/dist/runtime/index.js +227 -60
- package/package.json +2 -2
package/dist/avl/index.js
CHANGED
|
@@ -4446,6 +4446,16 @@ function useUISlotManager() {
|
|
|
4446
4446
|
},
|
|
4447
4447
|
[]
|
|
4448
4448
|
);
|
|
4449
|
+
const updateTraitContent = useCallback(
|
|
4450
|
+
(traitName, content) => {
|
|
4451
|
+
const id = generateId();
|
|
4452
|
+
const fullContent = { ...content, id, sourceTrait: traitName };
|
|
4453
|
+
indexTraitRender(traitName, fullContent);
|
|
4454
|
+
notifyTraitSubscribers(traitName, fullContent);
|
|
4455
|
+
return id;
|
|
4456
|
+
},
|
|
4457
|
+
[indexTraitRender, notifyTraitSubscribers]
|
|
4458
|
+
);
|
|
4449
4459
|
return {
|
|
4450
4460
|
slots,
|
|
4451
4461
|
render,
|
|
@@ -4457,7 +4467,8 @@ function useUISlotManager() {
|
|
|
4457
4467
|
hasContent,
|
|
4458
4468
|
getContent,
|
|
4459
4469
|
getTraitContent,
|
|
4460
|
-
subscribeTrait
|
|
4470
|
+
subscribeTrait,
|
|
4471
|
+
updateTraitContent
|
|
4461
4472
|
};
|
|
4462
4473
|
}
|
|
4463
4474
|
var DEFAULT_SOURCE_KEY, MULTI_SOURCE_STACK_TRAIT, ALL_SLOTS, DEFAULT_SLOTS, DEFAULT_SOURCES, idCounter;
|
|
@@ -51496,6 +51507,76 @@ function useResolvedSchema(schema, pageName) {
|
|
|
51496
51507
|
return result;
|
|
51497
51508
|
}
|
|
51498
51509
|
|
|
51510
|
+
// runtime/embedded-traits.ts
|
|
51511
|
+
var TRAIT_BINDING_PREFIX = "@trait.";
|
|
51512
|
+
function collectTraitRefsFromValue(value, into) {
|
|
51513
|
+
if (value === null || value === void 0) return;
|
|
51514
|
+
if (typeof value === "string") {
|
|
51515
|
+
if (value.startsWith(TRAIT_BINDING_PREFIX)) {
|
|
51516
|
+
const rest = value.slice(TRAIT_BINDING_PREFIX.length);
|
|
51517
|
+
const dot = rest.indexOf(".");
|
|
51518
|
+
const traitName = dot === -1 ? rest : rest.slice(0, dot);
|
|
51519
|
+
if (traitName.length > 0) into.add(traitName);
|
|
51520
|
+
}
|
|
51521
|
+
return;
|
|
51522
|
+
}
|
|
51523
|
+
if (Array.isArray(value)) {
|
|
51524
|
+
for (const item of value) collectTraitRefsFromValue(item, into);
|
|
51525
|
+
return;
|
|
51526
|
+
}
|
|
51527
|
+
if (typeof value === "object") {
|
|
51528
|
+
for (const v of Object.values(value)) {
|
|
51529
|
+
collectTraitRefsFromValue(v, into);
|
|
51530
|
+
}
|
|
51531
|
+
}
|
|
51532
|
+
}
|
|
51533
|
+
function collectTraitRefsFromEffects(effects, into) {
|
|
51534
|
+
if (!effects) return;
|
|
51535
|
+
for (const effect of effects) {
|
|
51536
|
+
if (!Array.isArray(effect)) continue;
|
|
51537
|
+
if (effect[0] === "render-ui" && effect.length >= 3) {
|
|
51538
|
+
collectTraitRefsFromValue(effect[2], into);
|
|
51539
|
+
continue;
|
|
51540
|
+
}
|
|
51541
|
+
for (let i = 1; i < effect.length; i++) {
|
|
51542
|
+
const arg = effect[i];
|
|
51543
|
+
if (Array.isArray(arg)) collectTraitRefsFromEffects([arg], into);
|
|
51544
|
+
else collectTraitRefsFromValue(arg, into);
|
|
51545
|
+
}
|
|
51546
|
+
}
|
|
51547
|
+
}
|
|
51548
|
+
function collectEmbeddedTraits(schema) {
|
|
51549
|
+
const out = /* @__PURE__ */ new Set();
|
|
51550
|
+
if (!schema?.orbitals) return out;
|
|
51551
|
+
for (const orbital of schema.orbitals) {
|
|
51552
|
+
if (!orbital || typeof orbital !== "object") continue;
|
|
51553
|
+
const traits2 = orbital.traits;
|
|
51554
|
+
if (!Array.isArray(traits2)) continue;
|
|
51555
|
+
for (const trait of traits2) {
|
|
51556
|
+
if (!trait || typeof trait !== "object") continue;
|
|
51557
|
+
const resolved = trait._resolved;
|
|
51558
|
+
const target = resolved && typeof resolved === "object" ? resolved : trait;
|
|
51559
|
+
const stateMachine = target.stateMachine;
|
|
51560
|
+
const transitions = stateMachine?.transitions;
|
|
51561
|
+
if (!Array.isArray(transitions)) continue;
|
|
51562
|
+
for (const t of transitions) {
|
|
51563
|
+
if (!t || typeof t !== "object") continue;
|
|
51564
|
+
const effects = t.effects;
|
|
51565
|
+
collectTraitRefsFromEffects(effects, out);
|
|
51566
|
+
}
|
|
51567
|
+
const initialEffects = target.initialEffects;
|
|
51568
|
+
collectTraitRefsFromEffects(initialEffects, out);
|
|
51569
|
+
const ticks2 = target.ticks;
|
|
51570
|
+
if (Array.isArray(ticks2)) {
|
|
51571
|
+
for (const tick of ticks2) {
|
|
51572
|
+
collectTraitRefsFromEffects(tick?.effects, out);
|
|
51573
|
+
}
|
|
51574
|
+
}
|
|
51575
|
+
}
|
|
51576
|
+
}
|
|
51577
|
+
return out;
|
|
51578
|
+
}
|
|
51579
|
+
|
|
51499
51580
|
// hooks/index.ts
|
|
51500
51581
|
init_useEventBus();
|
|
51501
51582
|
init_useUISlots();
|
|
@@ -52154,6 +52235,38 @@ init_EntitySchemaContext();
|
|
|
52154
52235
|
init_useEventBus();
|
|
52155
52236
|
init_logger();
|
|
52156
52237
|
var xOrbitalLog2 = createLogger("almadar:runtime:cross-orbital");
|
|
52238
|
+
function createHttpTransport(serverUrl) {
|
|
52239
|
+
return {
|
|
52240
|
+
register: async (schema) => {
|
|
52241
|
+
try {
|
|
52242
|
+
const res = await fetch(`${serverUrl}/register`, {
|
|
52243
|
+
method: "POST",
|
|
52244
|
+
headers: { "Content-Type": "application/json" },
|
|
52245
|
+
body: JSON.stringify({ schema })
|
|
52246
|
+
});
|
|
52247
|
+
const result = await res.json();
|
|
52248
|
+
return !!result.success;
|
|
52249
|
+
} catch (err) {
|
|
52250
|
+
console.error("[ServerBridge] Registration failed:", err);
|
|
52251
|
+
return false;
|
|
52252
|
+
}
|
|
52253
|
+
},
|
|
52254
|
+
unregister: async () => {
|
|
52255
|
+
try {
|
|
52256
|
+
await fetch(`${serverUrl}/unregister`, { method: "DELETE" });
|
|
52257
|
+
} catch {
|
|
52258
|
+
}
|
|
52259
|
+
},
|
|
52260
|
+
sendEvent: async (orbitalName, event, payload) => {
|
|
52261
|
+
const res = await fetch(`${serverUrl}/${orbitalName}/events`, {
|
|
52262
|
+
method: "POST",
|
|
52263
|
+
headers: { "Content-Type": "application/json" },
|
|
52264
|
+
body: JSON.stringify({ event, payload })
|
|
52265
|
+
});
|
|
52266
|
+
return res.json();
|
|
52267
|
+
}
|
|
52268
|
+
};
|
|
52269
|
+
}
|
|
52157
52270
|
var ServerBridgeContext = createContext(null);
|
|
52158
52271
|
function useServerBridge() {
|
|
52159
52272
|
const ctx = useContext(ServerBridgeContext);
|
|
@@ -52166,40 +52279,34 @@ function useServerBridge() {
|
|
|
52166
52279
|
function ServerBridgeProvider({
|
|
52167
52280
|
schema,
|
|
52168
52281
|
serverUrl,
|
|
52282
|
+
transport: customTransport,
|
|
52169
52283
|
children
|
|
52170
52284
|
}) {
|
|
52285
|
+
if (!serverUrl && !customTransport) {
|
|
52286
|
+
throw new Error("ServerBridgeProvider requires either serverUrl or transport");
|
|
52287
|
+
}
|
|
52288
|
+
if (serverUrl && customTransport) {
|
|
52289
|
+
throw new Error("ServerBridgeProvider accepts serverUrl OR transport, not both");
|
|
52290
|
+
}
|
|
52171
52291
|
const eventBus = useEventBus();
|
|
52172
52292
|
const [connected, setConnected] = useState(false);
|
|
52173
|
-
const
|
|
52174
|
-
|
|
52175
|
-
|
|
52176
|
-
|
|
52177
|
-
|
|
52178
|
-
|
|
52179
|
-
|
|
52180
|
-
|
|
52181
|
-
|
|
52182
|
-
|
|
52183
|
-
|
|
52184
|
-
|
|
52185
|
-
}
|
|
52186
|
-
}, [schema, serverUrl]);
|
|
52187
|
-
const unregisterSchema = useCallback(async () => {
|
|
52188
|
-
try {
|
|
52189
|
-
await fetch(`${serverUrl}/unregister`, { method: "DELETE" });
|
|
52190
|
-
} catch {
|
|
52191
|
-
}
|
|
52192
|
-
}, [serverUrl]);
|
|
52293
|
+
const transport = useMemo(
|
|
52294
|
+
() => customTransport ?? createHttpTransport(serverUrl),
|
|
52295
|
+
[serverUrl, customTransport]
|
|
52296
|
+
);
|
|
52297
|
+
const registerSchema = useCallback(
|
|
52298
|
+
async () => transport.register(schema),
|
|
52299
|
+
[schema, transport]
|
|
52300
|
+
);
|
|
52301
|
+
const unregisterSchema = useCallback(
|
|
52302
|
+
async () => transport.unregister(),
|
|
52303
|
+
[transport]
|
|
52304
|
+
);
|
|
52193
52305
|
const sendEvent = useCallback(async (orbitalName, event, payload) => {
|
|
52194
52306
|
const emptyMeta = { success: false, clientEffects: 0, dataEntities: {}, emittedEvents: [] };
|
|
52195
52307
|
if (!connected) return { effects: [], meta: emptyMeta };
|
|
52196
52308
|
try {
|
|
52197
|
-
const
|
|
52198
|
-
method: "POST",
|
|
52199
|
-
headers: { "Content-Type": "application/json" },
|
|
52200
|
-
body: JSON.stringify({ event, payload })
|
|
52201
|
-
});
|
|
52202
|
-
const result = await res.json();
|
|
52309
|
+
const result = await transport.sendEvent(orbitalName, event, payload);
|
|
52203
52310
|
const effects = [];
|
|
52204
52311
|
const responseData = result.data || {};
|
|
52205
52312
|
const dataEntities = {};
|
|
@@ -52257,7 +52364,7 @@ function ServerBridgeProvider({
|
|
|
52257
52364
|
console.error("[ServerBridge] Event send failed:", err);
|
|
52258
52365
|
return { effects: [], meta: { ...emptyMeta, error: err instanceof Error ? err.message : String(err) } };
|
|
52259
52366
|
}
|
|
52260
|
-
}, [connected,
|
|
52367
|
+
}, [connected, transport, eventBus]);
|
|
52261
52368
|
useEffect(() => {
|
|
52262
52369
|
if (!schema) return;
|
|
52263
52370
|
let cancelled = false;
|
|
@@ -52444,32 +52551,49 @@ function SlotBridge() {
|
|
|
52444
52551
|
}, [slots, render, clear]);
|
|
52445
52552
|
return null;
|
|
52446
52553
|
}
|
|
52447
|
-
function applyServerEffects(effects, uiSlots, onNavigate) {
|
|
52554
|
+
function applyServerEffects(effects, uiSlots, onNavigate, embeddedTraits) {
|
|
52448
52555
|
for (const eff of effects) {
|
|
52449
52556
|
if (eff.type === "render-ui" && eff.slot && eff.pattern) {
|
|
52450
52557
|
const patternRecord = eff.pattern;
|
|
52451
52558
|
const { type: patternType, children, ...inlineProps } = patternRecord;
|
|
52452
52559
|
const normalizedChildren = Array.isArray(children) ? children.map((c) => normalizeChild(c)) : children;
|
|
52453
|
-
|
|
52454
|
-
|
|
52455
|
-
|
|
52456
|
-
|
|
52457
|
-
|
|
52458
|
-
|
|
52459
|
-
|
|
52460
|
-
|
|
52461
|
-
|
|
52462
|
-
|
|
52463
|
-
|
|
52464
|
-
}
|
|
52465
|
-
sourceTrait
|
|
52466
|
-
|
|
52560
|
+
const sourceTrait = eff.traitName ?? "server";
|
|
52561
|
+
const isEmbedded = embeddedTraits?.has(sourceTrait) ?? false;
|
|
52562
|
+
const props = {
|
|
52563
|
+
...inlineProps,
|
|
52564
|
+
...normalizedChildren !== void 0 ? { children: normalizedChildren } : {}
|
|
52565
|
+
};
|
|
52566
|
+
if (isEmbedded) {
|
|
52567
|
+
xOrbitalLog3.info("slot:embed-routed", {
|
|
52568
|
+
sourceTrait,
|
|
52569
|
+
slot: eff.slot,
|
|
52570
|
+
patternType: typeof patternType === "string" ? patternType : void 0
|
|
52571
|
+
});
|
|
52572
|
+
uiSlots.updateTraitContent(sourceTrait, {
|
|
52573
|
+
pattern: patternType,
|
|
52574
|
+
props,
|
|
52575
|
+
priority: 0,
|
|
52576
|
+
animation: "fade"
|
|
52577
|
+
});
|
|
52578
|
+
} else {
|
|
52579
|
+
xOrbitalLog3.info("slot-write", {
|
|
52580
|
+
slot: eff.slot,
|
|
52581
|
+
sourceTrait,
|
|
52582
|
+
patternType: typeof patternType === "string" ? patternType : void 0
|
|
52583
|
+
});
|
|
52584
|
+
uiSlots.render({
|
|
52585
|
+
target: eff.slot,
|
|
52586
|
+
pattern: patternType,
|
|
52587
|
+
props,
|
|
52588
|
+
sourceTrait
|
|
52589
|
+
});
|
|
52590
|
+
}
|
|
52467
52591
|
} else if (eff.type === "navigate" && eff.route && onNavigate) {
|
|
52468
52592
|
onNavigate(eff.route, eff.params);
|
|
52469
52593
|
}
|
|
52470
52594
|
}
|
|
52471
52595
|
}
|
|
52472
|
-
function TraitInitializer({ traits: traits2, orbitalNames, onNavigate, onLocalFallback, persistence, traitConfigsByName, orbitalsByTrait }) {
|
|
52596
|
+
function TraitInitializer({ traits: traits2, orbitalNames, onNavigate, onLocalFallback, persistence, traitConfigsByName, orbitalsByTrait, embeddedTraits }) {
|
|
52473
52597
|
const slotsActions = useSlotsActions();
|
|
52474
52598
|
const bridge = useServerBridge();
|
|
52475
52599
|
const uiSlots = useUISlots();
|
|
@@ -52485,9 +52609,9 @@ function TraitInitializer({ traits: traits2, orbitalNames, onNavigate, onLocalFa
|
|
|
52485
52609
|
for (const name of targets) {
|
|
52486
52610
|
const { effects, meta } = await bridge.sendEvent(name, event, payload);
|
|
52487
52611
|
recordServerResponse(name, event, meta);
|
|
52488
|
-
applyServerEffects(effects, uiSlots, onNavigate);
|
|
52612
|
+
applyServerEffects(effects, uiSlots, onNavigate, embeddedTraits);
|
|
52489
52613
|
}
|
|
52490
|
-
}, [bridge.connected, bridge.sendEvent, orbitalNames, uiSlots, onNavigate]);
|
|
52614
|
+
}, [bridge.connected, bridge.sendEvent, orbitalNames, uiSlots, onNavigate, embeddedTraits]);
|
|
52491
52615
|
const opts = orbitalNames ? { onEventProcessed, navigate: onNavigate, traitConfigsByName, orbitalsByTrait } : { navigate: onNavigate, persistence, traitConfigsByName, orbitalsByTrait };
|
|
52492
52616
|
const { sendEvent } = useTraitStateMachine(traits2, slotsActions, opts);
|
|
52493
52617
|
const initSentRef = useRef(false);
|
|
@@ -52527,13 +52651,13 @@ function TraitInitializer({ traits: traits2, orbitalNames, onNavigate, onLocalFa
|
|
|
52527
52651
|
effects: effectTraces,
|
|
52528
52652
|
timestamp: Date.now()
|
|
52529
52653
|
});
|
|
52530
|
-
applyServerEffects(effects, uiSlots, onNavigate);
|
|
52654
|
+
applyServerEffects(effects, uiSlots, onNavigate, embeddedTraits);
|
|
52531
52655
|
}
|
|
52532
52656
|
})();
|
|
52533
|
-
}, [bridge.connected, orbitalNames, bridge.sendEvent, uiSlots, onNavigate]);
|
|
52657
|
+
}, [bridge.connected, orbitalNames, bridge.sendEvent, uiSlots, onNavigate, embeddedTraits]);
|
|
52534
52658
|
return null;
|
|
52535
52659
|
}
|
|
52536
|
-
function SchemaRunner({ schema, serverUrl, mockData, pageName, onNavigate, onLocalFallback, persistence }) {
|
|
52660
|
+
function SchemaRunner({ schema, serverUrl, transport, mockData, pageName, onNavigate, onLocalFallback, persistence }) {
|
|
52537
52661
|
const { traits: traits2, allEntities, ir } = useResolvedSchema(schema, pageName);
|
|
52538
52662
|
const allPageTraits = useMemo(() => {
|
|
52539
52663
|
if (pageName && traits2.length > 0) return traits2;
|
|
@@ -52636,6 +52760,9 @@ function SchemaRunner({ schema, serverUrl, mockData, pageName, onNavigate, onLoc
|
|
|
52636
52760
|
}
|
|
52637
52761
|
return map;
|
|
52638
52762
|
}, [schema]);
|
|
52763
|
+
const embeddedTraits = useMemo(() => {
|
|
52764
|
+
return collectEmbeddedTraits(schema);
|
|
52765
|
+
}, [schema]);
|
|
52639
52766
|
const inner = /* @__PURE__ */ jsx(VerificationProvider, { enabled: true, children: /* @__PURE__ */ jsx(SlotsProvider, { children: /* @__PURE__ */ jsxs(
|
|
52640
52767
|
EntitySchemaProvider,
|
|
52641
52768
|
{
|
|
@@ -52647,9 +52774,10 @@ function SchemaRunner({ schema, serverUrl, mockData, pageName, onNavigate, onLoc
|
|
|
52647
52774
|
TraitInitializer,
|
|
52648
52775
|
{
|
|
52649
52776
|
traits: allPageTraits,
|
|
52650
|
-
orbitalNames: serverUrl ? pageOrbitalNames : void 0,
|
|
52777
|
+
orbitalNames: serverUrl || transport ? pageOrbitalNames : void 0,
|
|
52651
52778
|
traitConfigsByName,
|
|
52652
52779
|
orbitalsByTrait,
|
|
52780
|
+
embeddedTraits,
|
|
52653
52781
|
onNavigate,
|
|
52654
52782
|
onLocalFallback,
|
|
52655
52783
|
persistence
|
|
@@ -52660,8 +52788,8 @@ function SchemaRunner({ schema, serverUrl, mockData, pageName, onNavigate, onLoc
|
|
|
52660
52788
|
]
|
|
52661
52789
|
}
|
|
52662
52790
|
) }) });
|
|
52663
|
-
if (serverUrl) {
|
|
52664
|
-
return /* @__PURE__ */ jsx(ServerBridgeProvider, { schema, serverUrl, children: inner });
|
|
52791
|
+
if (serverUrl || transport) {
|
|
52792
|
+
return /* @__PURE__ */ jsx(ServerBridgeProvider, { schema, serverUrl, transport, children: inner });
|
|
52665
52793
|
}
|
|
52666
52794
|
return inner;
|
|
52667
52795
|
}
|
|
@@ -52672,8 +52800,12 @@ function OrbPreview({
|
|
|
52672
52800
|
height = "400px",
|
|
52673
52801
|
className,
|
|
52674
52802
|
serverUrl,
|
|
52803
|
+
transport,
|
|
52675
52804
|
initialPagePath
|
|
52676
52805
|
}) {
|
|
52806
|
+
if (serverUrl && transport) {
|
|
52807
|
+
throw new Error("OrbPreview accepts serverUrl OR transport, not both");
|
|
52808
|
+
}
|
|
52677
52809
|
const [localFallback, setLocalFallback] = useState(false);
|
|
52678
52810
|
const eventBus = useEventBus();
|
|
52679
52811
|
const handleLocalFallback = useCallback(() => {
|
|
@@ -52695,21 +52827,21 @@ function OrbPreview({
|
|
|
52695
52827
|
} else {
|
|
52696
52828
|
parsed = schema;
|
|
52697
52829
|
}
|
|
52698
|
-
if (autoMock && !serverUrl) {
|
|
52830
|
+
if (autoMock && !serverUrl && !transport) {
|
|
52699
52831
|
const prepared = prepareSchemaForPreview(parsed);
|
|
52700
52832
|
return { ok: true, schema: prepared.schema, mockData: prepared.mockData };
|
|
52701
52833
|
}
|
|
52702
52834
|
return { ok: true, schema: parsed, mockData: mockData ?? {} };
|
|
52703
|
-
}, [schema, autoMock, serverUrl, mockData]);
|
|
52835
|
+
}, [schema, autoMock, serverUrl, transport, mockData]);
|
|
52704
52836
|
const parsedSchema = parseResult.ok ? parseResult.schema : null;
|
|
52705
52837
|
const effectiveMockData = parseResult.ok ? parseResult.mockData : {};
|
|
52706
52838
|
const persistence = useMemo(() => {
|
|
52707
|
-
if (!parsedSchema || serverUrl) return void 0;
|
|
52839
|
+
if (!parsedSchema || serverUrl || transport) return void 0;
|
|
52708
52840
|
if (!autoMock) return void 0;
|
|
52709
52841
|
const adapter = new InMemoryPersistence();
|
|
52710
52842
|
adapter.seed(effectiveMockData);
|
|
52711
52843
|
return adapter;
|
|
52712
|
-
}, [parsedSchema, serverUrl, autoMock, effectiveMockData]);
|
|
52844
|
+
}, [parsedSchema, serverUrl, transport, autoMock, effectiveMockData]);
|
|
52713
52845
|
const pages = useMemo(() => {
|
|
52714
52846
|
if (!parsedSchema) return [];
|
|
52715
52847
|
try {
|
|
@@ -52771,6 +52903,7 @@ function OrbPreview({
|
|
|
52771
52903
|
{
|
|
52772
52904
|
schema: parsedSchema,
|
|
52773
52905
|
serverUrl,
|
|
52906
|
+
transport,
|
|
52774
52907
|
mockData: effectiveMockData,
|
|
52775
52908
|
pageName: currentPage,
|
|
52776
52909
|
onNavigate: handleNavigate,
|
|
@@ -41153,6 +41153,16 @@ function useUISlotManager() {
|
|
|
41153
41153
|
},
|
|
41154
41154
|
[]
|
|
41155
41155
|
);
|
|
41156
|
+
const updateTraitContent = React111.useCallback(
|
|
41157
|
+
(traitName, content) => {
|
|
41158
|
+
const id = generateId();
|
|
41159
|
+
const fullContent = { ...content, id, sourceTrait: traitName };
|
|
41160
|
+
indexTraitRender(traitName, fullContent);
|
|
41161
|
+
notifyTraitSubscribers(traitName, fullContent);
|
|
41162
|
+
return id;
|
|
41163
|
+
},
|
|
41164
|
+
[indexTraitRender, notifyTraitSubscribers]
|
|
41165
|
+
);
|
|
41156
41166
|
return {
|
|
41157
41167
|
slots,
|
|
41158
41168
|
render,
|
|
@@ -41164,7 +41174,8 @@ function useUISlotManager() {
|
|
|
41164
41174
|
hasContent,
|
|
41165
41175
|
getContent,
|
|
41166
41176
|
getTraitContent,
|
|
41167
|
-
subscribeTrait
|
|
41177
|
+
subscribeTrait,
|
|
41178
|
+
updateTraitContent
|
|
41168
41179
|
};
|
|
41169
41180
|
}
|
|
41170
41181
|
|
package/dist/components/index.js
CHANGED
|
@@ -41108,6 +41108,16 @@ function useUISlotManager() {
|
|
|
41108
41108
|
},
|
|
41109
41109
|
[]
|
|
41110
41110
|
);
|
|
41111
|
+
const updateTraitContent = useCallback(
|
|
41112
|
+
(traitName, content) => {
|
|
41113
|
+
const id = generateId();
|
|
41114
|
+
const fullContent = { ...content, id, sourceTrait: traitName };
|
|
41115
|
+
indexTraitRender(traitName, fullContent);
|
|
41116
|
+
notifyTraitSubscribers(traitName, fullContent);
|
|
41117
|
+
return id;
|
|
41118
|
+
},
|
|
41119
|
+
[indexTraitRender, notifyTraitSubscribers]
|
|
41120
|
+
);
|
|
41111
41121
|
return {
|
|
41112
41122
|
slots,
|
|
41113
41123
|
render,
|
|
@@ -41119,7 +41129,8 @@ function useUISlotManager() {
|
|
|
41119
41129
|
hasContent,
|
|
41120
41130
|
getContent,
|
|
41121
41131
|
getTraitContent,
|
|
41122
|
-
subscribeTrait
|
|
41132
|
+
subscribeTrait,
|
|
41133
|
+
updateTraitContent
|
|
41123
41134
|
};
|
|
41124
41135
|
}
|
|
41125
41136
|
|
package/dist/context/index.cjs
CHANGED
|
@@ -305,6 +305,16 @@ function useUISlotManager() {
|
|
|
305
305
|
},
|
|
306
306
|
[]
|
|
307
307
|
);
|
|
308
|
+
const updateTraitContent = react.useCallback(
|
|
309
|
+
(traitName, content) => {
|
|
310
|
+
const id = generateId();
|
|
311
|
+
const fullContent = { ...content, id, sourceTrait: traitName };
|
|
312
|
+
indexTraitRender(traitName, fullContent);
|
|
313
|
+
notifyTraitSubscribers(traitName, fullContent);
|
|
314
|
+
return id;
|
|
315
|
+
},
|
|
316
|
+
[indexTraitRender, notifyTraitSubscribers]
|
|
317
|
+
);
|
|
308
318
|
return {
|
|
309
319
|
slots,
|
|
310
320
|
render,
|
|
@@ -316,7 +326,8 @@ function useUISlotManager() {
|
|
|
316
326
|
hasContent,
|
|
317
327
|
getContent,
|
|
318
328
|
getTraitContent,
|
|
319
|
-
subscribeTrait
|
|
329
|
+
subscribeTrait,
|
|
330
|
+
updateTraitContent
|
|
320
331
|
};
|
|
321
332
|
}
|
|
322
333
|
var UISlotContext = react.createContext(null);
|
package/dist/context/index.js
CHANGED
|
@@ -303,6 +303,16 @@ function useUISlotManager() {
|
|
|
303
303
|
},
|
|
304
304
|
[]
|
|
305
305
|
);
|
|
306
|
+
const updateTraitContent = useCallback(
|
|
307
|
+
(traitName, content) => {
|
|
308
|
+
const id = generateId();
|
|
309
|
+
const fullContent = { ...content, id, sourceTrait: traitName };
|
|
310
|
+
indexTraitRender(traitName, fullContent);
|
|
311
|
+
notifyTraitSubscribers(traitName, fullContent);
|
|
312
|
+
return id;
|
|
313
|
+
},
|
|
314
|
+
[indexTraitRender, notifyTraitSubscribers]
|
|
315
|
+
);
|
|
306
316
|
return {
|
|
307
317
|
slots,
|
|
308
318
|
render,
|
|
@@ -314,7 +324,8 @@ function useUISlotManager() {
|
|
|
314
324
|
hasContent,
|
|
315
325
|
getContent,
|
|
316
326
|
getTraitContent,
|
|
317
|
-
subscribeTrait
|
|
327
|
+
subscribeTrait,
|
|
328
|
+
updateTraitContent
|
|
318
329
|
};
|
|
319
330
|
}
|
|
320
331
|
var UISlotContext = createContext(null);
|
package/dist/hooks/index.cjs
CHANGED
|
@@ -1348,6 +1348,16 @@ function useUISlotManager() {
|
|
|
1348
1348
|
},
|
|
1349
1349
|
[]
|
|
1350
1350
|
);
|
|
1351
|
+
const updateTraitContent = react.useCallback(
|
|
1352
|
+
(traitName, content) => {
|
|
1353
|
+
const id = generateId();
|
|
1354
|
+
const fullContent = { ...content, id, sourceTrait: traitName };
|
|
1355
|
+
indexTraitRender(traitName, fullContent);
|
|
1356
|
+
notifyTraitSubscribers(traitName, fullContent);
|
|
1357
|
+
return id;
|
|
1358
|
+
},
|
|
1359
|
+
[indexTraitRender, notifyTraitSubscribers]
|
|
1360
|
+
);
|
|
1351
1361
|
return {
|
|
1352
1362
|
slots,
|
|
1353
1363
|
render,
|
|
@@ -1359,7 +1369,8 @@ function useUISlotManager() {
|
|
|
1359
1369
|
hasContent,
|
|
1360
1370
|
getContent,
|
|
1361
1371
|
getTraitContent,
|
|
1362
|
-
subscribeTrait
|
|
1372
|
+
subscribeTrait,
|
|
1373
|
+
updateTraitContent
|
|
1363
1374
|
};
|
|
1364
1375
|
}
|
|
1365
1376
|
var UI_PREFIX = "UI:";
|
package/dist/hooks/index.js
CHANGED
|
@@ -1346,6 +1346,16 @@ function useUISlotManager() {
|
|
|
1346
1346
|
},
|
|
1347
1347
|
[]
|
|
1348
1348
|
);
|
|
1349
|
+
const updateTraitContent = useCallback(
|
|
1350
|
+
(traitName, content) => {
|
|
1351
|
+
const id = generateId();
|
|
1352
|
+
const fullContent = { ...content, id, sourceTrait: traitName };
|
|
1353
|
+
indexTraitRender(traitName, fullContent);
|
|
1354
|
+
notifyTraitSubscribers(traitName, fullContent);
|
|
1355
|
+
return id;
|
|
1356
|
+
},
|
|
1357
|
+
[indexTraitRender, notifyTraitSubscribers]
|
|
1358
|
+
);
|
|
1349
1359
|
return {
|
|
1350
1360
|
slots,
|
|
1351
1361
|
render,
|
|
@@ -1357,7 +1367,8 @@ function useUISlotManager() {
|
|
|
1357
1367
|
hasContent,
|
|
1358
1368
|
getContent,
|
|
1359
1369
|
getTraitContent,
|
|
1360
|
-
subscribeTrait
|
|
1370
|
+
subscribeTrait,
|
|
1371
|
+
updateTraitContent
|
|
1361
1372
|
};
|
|
1362
1373
|
}
|
|
1363
1374
|
var UI_PREFIX = "UI:";
|
|
@@ -119,6 +119,20 @@ export interface UISlotManager {
|
|
|
119
119
|
* the trait they embed actually changes — not on every slot update.
|
|
120
120
|
*/
|
|
121
121
|
subscribeTrait: (traitName: string, callback: TraitChangeCallback) => () => void;
|
|
122
|
+
/**
|
|
123
|
+
* Update only the per-trait sidecar without writing to any slot.
|
|
124
|
+
*
|
|
125
|
+
* Used for embed-aware slot routing: when a trait is referenced via
|
|
126
|
+
* `@trait.X` by a sibling layout's render-ui, its render output should
|
|
127
|
+
* not stack into the same slot the layout writes — the layout owns the
|
|
128
|
+
* slot and embeds the trait's frame via `<TraitFrame>`. This method
|
|
129
|
+
* keeps the per-trait sidecar (`traitIndexRef`) up-to-date so
|
|
130
|
+
* `<TraitFrame>` re-renders, while leaving `slots[target]` untouched.
|
|
131
|
+
*
|
|
132
|
+
* Mirrors what the compiled-path codegen does structurally — atoms
|
|
133
|
+
* inlined as JSX inside the layout's pattern, not writing slots.
|
|
134
|
+
*/
|
|
135
|
+
updateTraitContent: (traitName: string, content: Omit<SlotContent, 'id' | 'sourceTrait'>) => string;
|
|
122
136
|
}
|
|
123
137
|
declare const DEFAULT_SLOTS: Record<UISlot, SlotContent | null>;
|
|
124
138
|
/**
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BrowserPlayground — in-browser Almadar runtime mount.
|
|
3
|
+
*
|
|
4
|
+
* Runs `OrbitalServerRuntime` (mock mode) in-process and threads it through
|
|
5
|
+
* `<OrbPreview>` via the `ServerBridgeTransport` adapter. Equivalent to
|
|
6
|
+
* canonical playground-runtime's server-mode mount, but without Express,
|
|
7
|
+
* fork, or HTTP — invokes `runtime.processOrbitalEvent` directly.
|
|
8
|
+
*
|
|
9
|
+
* Same React tree as `runtime-verify` (and apps/builder server-mode) speak,
|
|
10
|
+
* so any `@almadar/runtime` fix flows in through one bump cycle.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```tsx
|
|
14
|
+
* <BrowserPlayground schema={schema} mode="mock" height="100%" />
|
|
15
|
+
* ```
|
|
16
|
+
*
|
|
17
|
+
* @packageDocumentation
|
|
18
|
+
*/
|
|
19
|
+
import React from 'react';
|
|
20
|
+
import type { OrbitalSchema } from '@almadar/core';
|
|
21
|
+
export interface BrowserPlaygroundProps {
|
|
22
|
+
/** OrbitalSchema to render. */
|
|
23
|
+
schema: OrbitalSchema;
|
|
24
|
+
/** Persistence mode for the in-process runtime. Default: 'mock' (Faker-seeded MockPersistenceAdapter). */
|
|
25
|
+
mode?: 'mock';
|
|
26
|
+
/** Initial page path to render (forwarded to OrbPreview). */
|
|
27
|
+
initialPagePath?: string;
|
|
28
|
+
/** Preview container height. Default: '400px'. */
|
|
29
|
+
height?: string;
|
|
30
|
+
/** CSS class for the outer container. */
|
|
31
|
+
className?: string;
|
|
32
|
+
}
|
|
33
|
+
export declare function BrowserPlayground({ schema, mode, initialPagePath, height, className, }: BrowserPlaygroundProps): React.ReactElement;
|
|
34
|
+
export default BrowserPlayground;
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
*/
|
|
14
14
|
import React from 'react';
|
|
15
15
|
import type { OrbitalSchema, EntityData } from '@almadar/core';
|
|
16
|
+
import { type ServerBridgeTransport } from './ServerBridge';
|
|
16
17
|
export interface OrbPreviewProps {
|
|
17
18
|
/**
|
|
18
19
|
* The orbital schema. Accepts a JSON string or an `OrbitalSchema` object
|
|
@@ -42,6 +43,12 @@ export interface OrbPreviewProps {
|
|
|
42
43
|
className?: string;
|
|
43
44
|
/** Server URL for dual execution (e.g. "/api/orbitals"). When set, events are forwarded to the server. */
|
|
44
45
|
serverUrl?: string;
|
|
46
|
+
/**
|
|
47
|
+
* Custom transport for in-process execution. Mutually exclusive with
|
|
48
|
+
* `serverUrl`. Used by `<BrowserPlayground>` to invoke
|
|
49
|
+
* `OrbitalServerRuntime.processOrbitalEvent` directly without HTTP.
|
|
50
|
+
*/
|
|
51
|
+
transport?: ServerBridgeTransport;
|
|
45
52
|
/**
|
|
46
53
|
* Initial page path to render (e.g. `/deals`). Resolves against the
|
|
47
54
|
* schema's `pages[]` to seed `currentPage` so the right orbital's traits
|
|
@@ -64,7 +71,7 @@ export interface OrbPreviewProps {
|
|
|
64
71
|
* <OrbPreview schema={schema} serverUrl="/api/orbitals" />
|
|
65
72
|
* ```
|
|
66
73
|
*/
|
|
67
|
-
export declare function OrbPreview({ schema, mockData, autoMock, height, className, serverUrl, initialPagePath, }: OrbPreviewProps): React.ReactElement;
|
|
74
|
+
export declare function OrbPreview({ schema, mockData, autoMock, height, className, serverUrl, transport, initialPagePath, }: OrbPreviewProps): React.ReactElement;
|
|
68
75
|
export declare namespace OrbPreview {
|
|
69
76
|
var displayName: string;
|
|
70
77
|
}
|