@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
|
@@ -1,4 +1,33 @@
|
|
|
1
1
|
import type { ReactNode } from 'react';
|
|
2
|
+
import type { BusEventSource, EventPayload } from '@almadar/core';
|
|
3
|
+
interface OrbitalEventResponse {
|
|
4
|
+
success: boolean;
|
|
5
|
+
transitioned: boolean;
|
|
6
|
+
states: Record<string, string>;
|
|
7
|
+
/**
|
|
8
|
+
* Server-cascade events carried back in the response. Each entry has a
|
|
9
|
+
* `source: BusEventSource` stamped by the compiled handler (`emit ...
|
|
10
|
+
* { source: __ORBITAL_SOURCE }`) so the client can re-broadcast on the
|
|
11
|
+
* qualified `UI:Orbital.Trait.EVENT` bus key (gap #13).
|
|
12
|
+
*/
|
|
13
|
+
emittedEvents?: Array<{
|
|
14
|
+
event: string;
|
|
15
|
+
payload?: EventPayload;
|
|
16
|
+
source?: BusEventSource;
|
|
17
|
+
}>;
|
|
18
|
+
data?: Record<string, unknown[]>;
|
|
19
|
+
clientEffects?: unknown[];
|
|
20
|
+
/**
|
|
21
|
+
* Same effects as `clientEffects`, paired with the trait that produced
|
|
22
|
+
* each one. When present, prefer this for trait attribution. Falls back
|
|
23
|
+
* to legacy `clientEffects` parsing on older servers.
|
|
24
|
+
*/
|
|
25
|
+
clientEffectsByTrait?: Array<{
|
|
26
|
+
traitName: string;
|
|
27
|
+
effect: unknown[];
|
|
28
|
+
}>;
|
|
29
|
+
error?: string;
|
|
30
|
+
}
|
|
2
31
|
export interface ServerClientEffect {
|
|
3
32
|
type: 'render-ui' | 'navigate' | 'notify';
|
|
4
33
|
slot?: string;
|
|
@@ -31,13 +60,40 @@ export interface ServerBridgeContextValue {
|
|
|
31
60
|
connected: boolean;
|
|
32
61
|
sendEvent: (orbitalName: string, event: string, payload?: Record<string, unknown>) => Promise<SendEventResult>;
|
|
33
62
|
}
|
|
63
|
+
/**
|
|
64
|
+
* Transport adapter for ServerBridgeProvider. Decouples the bridge's
|
|
65
|
+
* cascade-rebroadcast / effect-parsing logic from its wire format.
|
|
66
|
+
*
|
|
67
|
+
* - The `serverUrl` mode (default) uses an HTTP transport that POSTs to
|
|
68
|
+
* `/register`, `/unregister`, `/:orbital/events`. This is what canonical
|
|
69
|
+
* playground-runtime (`tools/runtime-verify`) and apps/builder-server
|
|
70
|
+
* speak.
|
|
71
|
+
* - The `transport` mode lets a consumer plug in a direct function-call
|
|
72
|
+
* adapter — used by `<BrowserPlayground>` to invoke
|
|
73
|
+
* `OrbitalServerRuntime.processOrbitalEvent` in-process, no HTTP, no
|
|
74
|
+
* server. Both modes return the same `OrbitalEventResponse` shape so the
|
|
75
|
+
* cascade-rebroadcast logic is identical downstream.
|
|
76
|
+
*/
|
|
77
|
+
export interface ServerBridgeTransport {
|
|
78
|
+
register: (schema: unknown) => Promise<boolean>;
|
|
79
|
+
unregister: () => Promise<void>;
|
|
80
|
+
sendEvent: (orbitalName: string, event: string, payload?: Record<string, unknown>) => Promise<OrbitalEventResponse>;
|
|
81
|
+
}
|
|
34
82
|
/**
|
|
35
83
|
* Access the server bridge. Returns a no-op stub when outside the provider.
|
|
36
84
|
*/
|
|
37
85
|
export declare function useServerBridge(): ServerBridgeContextValue;
|
|
38
86
|
export interface ServerBridgeProviderProps {
|
|
39
87
|
schema: unknown;
|
|
40
|
-
|
|
88
|
+
/** HTTP server URL (canonical playground-runtime / apps/builder-server). */
|
|
89
|
+
serverUrl?: string;
|
|
90
|
+
/**
|
|
91
|
+
* Custom transport adapter. Use this for in-process execution (e.g.
|
|
92
|
+
* `<BrowserPlayground>` invokes `OrbitalServerRuntime.processOrbitalEvent`
|
|
93
|
+
* directly). Mutually exclusive with `serverUrl`.
|
|
94
|
+
*/
|
|
95
|
+
transport?: ServerBridgeTransport;
|
|
41
96
|
children: ReactNode;
|
|
42
97
|
}
|
|
43
|
-
export declare function ServerBridgeProvider({ schema, serverUrl, children, }: ServerBridgeProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
98
|
+
export declare function ServerBridgeProvider({ schema, serverUrl, transport: customTransport, children, }: ServerBridgeProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
99
|
+
export {};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Embed-aware slot routing — static analysis pass.
|
|
3
|
+
*
|
|
4
|
+
* Walks every trait's `transitions[].effects` looking for `render-ui`
|
|
5
|
+
* patterns whose tree contains `@trait.<Name>` string literals. Returns
|
|
6
|
+
* the flat set of trait names that are referenced this way by some
|
|
7
|
+
* sibling layout.
|
|
8
|
+
*
|
|
9
|
+
* Used by `<OrbPreview>` to route `applyServerEffects` — when an
|
|
10
|
+
* embedded trait's render-ui effect arrives, the runtime updates that
|
|
11
|
+
* trait's per-trait sidecar (`traitIndexRef`) only and skips the slot
|
|
12
|
+
* write. The sibling layout owns the slot and embeds the trait's frame
|
|
13
|
+
* via `<TraitFrame>`. Mirrors the compiled-path codegen which inlines
|
|
14
|
+
* the atom views as JSX inside the layout's pattern, never having them
|
|
15
|
+
* write a shared slot.
|
|
16
|
+
*
|
|
17
|
+
* The walker is a structural twin of
|
|
18
|
+
* `packages/almadar-runtime/src/resolver/reference-resolver.ts`'s
|
|
19
|
+
* `renameEventsInRenderUiConfig` — same recursive pattern shape, just
|
|
20
|
+
* collecting `@trait.X` substrings instead of renaming events.
|
|
21
|
+
*
|
|
22
|
+
* @packageDocumentation
|
|
23
|
+
*/
|
|
24
|
+
import type { OrbitalSchema } from '@almadar/core';
|
|
25
|
+
/**
|
|
26
|
+
* Build the flat set of trait names that are referenced via `@trait.X`
|
|
27
|
+
* by at least one trait's render-ui in the resolved schema.
|
|
28
|
+
*
|
|
29
|
+
* Safe to call on the resolved (post-inline) schema. Memoize by
|
|
30
|
+
* reference at the call site.
|
|
31
|
+
*/
|
|
32
|
+
export declare function collectEmbeddedTraits(schema: OrbitalSchema | undefined | null): ReadonlySet<string>;
|
package/dist/runtime/index.cjs
CHANGED
|
@@ -37,6 +37,7 @@ var langGraphql = require('react-syntax-highlighter/dist/esm/languages/prism/gra
|
|
|
37
37
|
var core = require('@almadar/core');
|
|
38
38
|
require('@tanstack/react-query');
|
|
39
39
|
var runtime = require('@almadar/runtime');
|
|
40
|
+
var OrbitalServerRuntime = require('@almadar/runtime/OrbitalServerRuntime');
|
|
40
41
|
|
|
41
42
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
42
43
|
|
|
@@ -8229,13 +8230,13 @@ var init_MapView = __esm({
|
|
|
8229
8230
|
shadowSize: [41, 41]
|
|
8230
8231
|
});
|
|
8231
8232
|
L.Marker.prototype.options.icon = defaultIcon;
|
|
8232
|
-
const { useEffect:
|
|
8233
|
+
const { useEffect: useEffect69, useRef: useRef65, useCallback: useCallback110, useState: useState103 } = React115__namespace.default;
|
|
8233
8234
|
const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
|
|
8234
8235
|
const { useEventBus: useEventBus2 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
|
|
8235
8236
|
function MapUpdater({ centerLat, centerLng, zoom }) {
|
|
8236
8237
|
const map = useMap();
|
|
8237
8238
|
const prevRef = useRef65({ centerLat, centerLng, zoom });
|
|
8238
|
-
|
|
8239
|
+
useEffect69(() => {
|
|
8239
8240
|
const prev = prevRef.current;
|
|
8240
8241
|
if (prev.centerLat !== centerLat || prev.centerLng !== centerLng || prev.zoom !== zoom) {
|
|
8241
8242
|
map.setView([centerLat, centerLng], zoom);
|
|
@@ -8246,7 +8247,7 @@ var init_MapView = __esm({
|
|
|
8246
8247
|
}
|
|
8247
8248
|
function MapClickHandler({ onMapClick }) {
|
|
8248
8249
|
const map = useMap();
|
|
8249
|
-
|
|
8250
|
+
useEffect69(() => {
|
|
8250
8251
|
if (!onMapClick) return;
|
|
8251
8252
|
const handler = (e) => {
|
|
8252
8253
|
onMapClick(e.latlng.lat, e.latlng.lng);
|
|
@@ -8273,7 +8274,7 @@ var init_MapView = __esm({
|
|
|
8273
8274
|
showAttribution = true
|
|
8274
8275
|
}) {
|
|
8275
8276
|
const eventBus = useEventBus2();
|
|
8276
|
-
const [clickedPosition, setClickedPosition] =
|
|
8277
|
+
const [clickedPosition, setClickedPosition] = useState103(null);
|
|
8277
8278
|
const handleMapClick = useCallback110((lat, lng) => {
|
|
8278
8279
|
if (showClickedPin) {
|
|
8279
8280
|
setClickedPosition({ lat, lng });
|
|
@@ -38973,6 +38974,78 @@ init_Box();
|
|
|
38973
38974
|
init_Typography();
|
|
38974
38975
|
init_UISlotRenderer();
|
|
38975
38976
|
init_useEventBus();
|
|
38977
|
+
|
|
38978
|
+
// runtime/embedded-traits.ts
|
|
38979
|
+
var TRAIT_BINDING_PREFIX = "@trait.";
|
|
38980
|
+
function collectTraitRefsFromValue(value, into) {
|
|
38981
|
+
if (value === null || value === void 0) return;
|
|
38982
|
+
if (typeof value === "string") {
|
|
38983
|
+
if (value.startsWith(TRAIT_BINDING_PREFIX)) {
|
|
38984
|
+
const rest = value.slice(TRAIT_BINDING_PREFIX.length);
|
|
38985
|
+
const dot = rest.indexOf(".");
|
|
38986
|
+
const traitName = dot === -1 ? rest : rest.slice(0, dot);
|
|
38987
|
+
if (traitName.length > 0) into.add(traitName);
|
|
38988
|
+
}
|
|
38989
|
+
return;
|
|
38990
|
+
}
|
|
38991
|
+
if (Array.isArray(value)) {
|
|
38992
|
+
for (const item of value) collectTraitRefsFromValue(item, into);
|
|
38993
|
+
return;
|
|
38994
|
+
}
|
|
38995
|
+
if (typeof value === "object") {
|
|
38996
|
+
for (const v of Object.values(value)) {
|
|
38997
|
+
collectTraitRefsFromValue(v, into);
|
|
38998
|
+
}
|
|
38999
|
+
}
|
|
39000
|
+
}
|
|
39001
|
+
function collectTraitRefsFromEffects(effects, into) {
|
|
39002
|
+
if (!effects) return;
|
|
39003
|
+
for (const effect of effects) {
|
|
39004
|
+
if (!Array.isArray(effect)) continue;
|
|
39005
|
+
if (effect[0] === "render-ui" && effect.length >= 3) {
|
|
39006
|
+
collectTraitRefsFromValue(effect[2], into);
|
|
39007
|
+
continue;
|
|
39008
|
+
}
|
|
39009
|
+
for (let i = 1; i < effect.length; i++) {
|
|
39010
|
+
const arg = effect[i];
|
|
39011
|
+
if (Array.isArray(arg)) collectTraitRefsFromEffects([arg], into);
|
|
39012
|
+
else collectTraitRefsFromValue(arg, into);
|
|
39013
|
+
}
|
|
39014
|
+
}
|
|
39015
|
+
}
|
|
39016
|
+
function collectEmbeddedTraits(schema) {
|
|
39017
|
+
const out = /* @__PURE__ */ new Set();
|
|
39018
|
+
if (!schema?.orbitals) return out;
|
|
39019
|
+
for (const orbital of schema.orbitals) {
|
|
39020
|
+
if (!orbital || typeof orbital !== "object") continue;
|
|
39021
|
+
const traits2 = orbital.traits;
|
|
39022
|
+
if (!Array.isArray(traits2)) continue;
|
|
39023
|
+
for (const trait of traits2) {
|
|
39024
|
+
if (!trait || typeof trait !== "object") continue;
|
|
39025
|
+
const resolved = trait._resolved;
|
|
39026
|
+
const target = resolved && typeof resolved === "object" ? resolved : trait;
|
|
39027
|
+
const stateMachine = target.stateMachine;
|
|
39028
|
+
const transitions = stateMachine?.transitions;
|
|
39029
|
+
if (!Array.isArray(transitions)) continue;
|
|
39030
|
+
for (const t of transitions) {
|
|
39031
|
+
if (!t || typeof t !== "object") continue;
|
|
39032
|
+
const effects = t.effects;
|
|
39033
|
+
collectTraitRefsFromEffects(effects, out);
|
|
39034
|
+
}
|
|
39035
|
+
const initialEffects = target.initialEffects;
|
|
39036
|
+
collectTraitRefsFromEffects(initialEffects, out);
|
|
39037
|
+
const ticks2 = target.ticks;
|
|
39038
|
+
if (Array.isArray(ticks2)) {
|
|
39039
|
+
for (const tick of ticks2) {
|
|
39040
|
+
collectTraitRefsFromEffects(tick?.effects, out);
|
|
39041
|
+
}
|
|
39042
|
+
}
|
|
39043
|
+
}
|
|
39044
|
+
}
|
|
39045
|
+
return out;
|
|
39046
|
+
}
|
|
39047
|
+
|
|
39048
|
+
// runtime/OrbPreview.tsx
|
|
38976
39049
|
init_SlotsContext();
|
|
38977
39050
|
init_EntitySchemaContext();
|
|
38978
39051
|
|
|
@@ -38980,6 +39053,38 @@ init_EntitySchemaContext();
|
|
|
38980
39053
|
init_useEventBus();
|
|
38981
39054
|
init_logger();
|
|
38982
39055
|
var xOrbitalLog2 = createLogger("almadar:runtime:cross-orbital");
|
|
39056
|
+
function createHttpTransport(serverUrl) {
|
|
39057
|
+
return {
|
|
39058
|
+
register: async (schema) => {
|
|
39059
|
+
try {
|
|
39060
|
+
const res = await fetch(`${serverUrl}/register`, {
|
|
39061
|
+
method: "POST",
|
|
39062
|
+
headers: { "Content-Type": "application/json" },
|
|
39063
|
+
body: JSON.stringify({ schema })
|
|
39064
|
+
});
|
|
39065
|
+
const result = await res.json();
|
|
39066
|
+
return !!result.success;
|
|
39067
|
+
} catch (err) {
|
|
39068
|
+
console.error("[ServerBridge] Registration failed:", err);
|
|
39069
|
+
return false;
|
|
39070
|
+
}
|
|
39071
|
+
},
|
|
39072
|
+
unregister: async () => {
|
|
39073
|
+
try {
|
|
39074
|
+
await fetch(`${serverUrl}/unregister`, { method: "DELETE" });
|
|
39075
|
+
} catch {
|
|
39076
|
+
}
|
|
39077
|
+
},
|
|
39078
|
+
sendEvent: async (orbitalName, event, payload) => {
|
|
39079
|
+
const res = await fetch(`${serverUrl}/${orbitalName}/events`, {
|
|
39080
|
+
method: "POST",
|
|
39081
|
+
headers: { "Content-Type": "application/json" },
|
|
39082
|
+
body: JSON.stringify({ event, payload })
|
|
39083
|
+
});
|
|
39084
|
+
return res.json();
|
|
39085
|
+
}
|
|
39086
|
+
};
|
|
39087
|
+
}
|
|
38983
39088
|
var ServerBridgeContext = React115.createContext(null);
|
|
38984
39089
|
function useServerBridge() {
|
|
38985
39090
|
const ctx = React115.useContext(ServerBridgeContext);
|
|
@@ -38992,40 +39097,34 @@ function useServerBridge() {
|
|
|
38992
39097
|
function ServerBridgeProvider({
|
|
38993
39098
|
schema,
|
|
38994
39099
|
serverUrl,
|
|
39100
|
+
transport: customTransport,
|
|
38995
39101
|
children
|
|
38996
39102
|
}) {
|
|
39103
|
+
if (!serverUrl && !customTransport) {
|
|
39104
|
+
throw new Error("ServerBridgeProvider requires either serverUrl or transport");
|
|
39105
|
+
}
|
|
39106
|
+
if (serverUrl && customTransport) {
|
|
39107
|
+
throw new Error("ServerBridgeProvider accepts serverUrl OR transport, not both");
|
|
39108
|
+
}
|
|
38997
39109
|
const eventBus = useEventBus();
|
|
38998
39110
|
const [connected, setConnected] = React115.useState(false);
|
|
38999
|
-
const
|
|
39000
|
-
|
|
39001
|
-
|
|
39002
|
-
|
|
39003
|
-
|
|
39004
|
-
|
|
39005
|
-
|
|
39006
|
-
|
|
39007
|
-
|
|
39008
|
-
|
|
39009
|
-
|
|
39010
|
-
|
|
39011
|
-
}
|
|
39012
|
-
}, [schema, serverUrl]);
|
|
39013
|
-
const unregisterSchema = React115.useCallback(async () => {
|
|
39014
|
-
try {
|
|
39015
|
-
await fetch(`${serverUrl}/unregister`, { method: "DELETE" });
|
|
39016
|
-
} catch {
|
|
39017
|
-
}
|
|
39018
|
-
}, [serverUrl]);
|
|
39111
|
+
const transport = React115.useMemo(
|
|
39112
|
+
() => customTransport ?? createHttpTransport(serverUrl),
|
|
39113
|
+
[serverUrl, customTransport]
|
|
39114
|
+
);
|
|
39115
|
+
const registerSchema = React115.useCallback(
|
|
39116
|
+
async () => transport.register(schema),
|
|
39117
|
+
[schema, transport]
|
|
39118
|
+
);
|
|
39119
|
+
const unregisterSchema = React115.useCallback(
|
|
39120
|
+
async () => transport.unregister(),
|
|
39121
|
+
[transport]
|
|
39122
|
+
);
|
|
39019
39123
|
const sendEvent = React115.useCallback(async (orbitalName, event, payload) => {
|
|
39020
39124
|
const emptyMeta = { success: false, clientEffects: 0, dataEntities: {}, emittedEvents: [] };
|
|
39021
39125
|
if (!connected) return { effects: [], meta: emptyMeta };
|
|
39022
39126
|
try {
|
|
39023
|
-
const
|
|
39024
|
-
method: "POST",
|
|
39025
|
-
headers: { "Content-Type": "application/json" },
|
|
39026
|
-
body: JSON.stringify({ event, payload })
|
|
39027
|
-
});
|
|
39028
|
-
const result = await res.json();
|
|
39127
|
+
const result = await transport.sendEvent(orbitalName, event, payload);
|
|
39029
39128
|
const effects = [];
|
|
39030
39129
|
const responseData = result.data || {};
|
|
39031
39130
|
const dataEntities = {};
|
|
@@ -39083,7 +39182,7 @@ function ServerBridgeProvider({
|
|
|
39083
39182
|
console.error("[ServerBridge] Event send failed:", err);
|
|
39084
39183
|
return { effects: [], meta: { ...emptyMeta, error: err instanceof Error ? err.message : String(err) } };
|
|
39085
39184
|
}
|
|
39086
|
-
}, [connected,
|
|
39185
|
+
}, [connected, transport, eventBus]);
|
|
39087
39186
|
React115.useEffect(() => {
|
|
39088
39187
|
if (!schema) return;
|
|
39089
39188
|
let cancelled = false;
|
|
@@ -39270,32 +39369,49 @@ function SlotBridge() {
|
|
|
39270
39369
|
}, [slots, render, clear]);
|
|
39271
39370
|
return null;
|
|
39272
39371
|
}
|
|
39273
|
-
function applyServerEffects(effects, uiSlots, onNavigate) {
|
|
39372
|
+
function applyServerEffects(effects, uiSlots, onNavigate, embeddedTraits) {
|
|
39274
39373
|
for (const eff of effects) {
|
|
39275
39374
|
if (eff.type === "render-ui" && eff.slot && eff.pattern) {
|
|
39276
39375
|
const patternRecord = eff.pattern;
|
|
39277
39376
|
const { type: patternType, children, ...inlineProps } = patternRecord;
|
|
39278
39377
|
const normalizedChildren = Array.isArray(children) ? children.map((c) => normalizeChild(c)) : children;
|
|
39279
|
-
|
|
39280
|
-
|
|
39281
|
-
|
|
39282
|
-
|
|
39283
|
-
|
|
39284
|
-
|
|
39285
|
-
|
|
39286
|
-
|
|
39287
|
-
|
|
39288
|
-
|
|
39289
|
-
|
|
39290
|
-
}
|
|
39291
|
-
sourceTrait
|
|
39292
|
-
|
|
39378
|
+
const sourceTrait = eff.traitName ?? "server";
|
|
39379
|
+
const isEmbedded = embeddedTraits?.has(sourceTrait) ?? false;
|
|
39380
|
+
const props = {
|
|
39381
|
+
...inlineProps,
|
|
39382
|
+
...normalizedChildren !== void 0 ? { children: normalizedChildren } : {}
|
|
39383
|
+
};
|
|
39384
|
+
if (isEmbedded) {
|
|
39385
|
+
xOrbitalLog3.info("slot:embed-routed", {
|
|
39386
|
+
sourceTrait,
|
|
39387
|
+
slot: eff.slot,
|
|
39388
|
+
patternType: typeof patternType === "string" ? patternType : void 0
|
|
39389
|
+
});
|
|
39390
|
+
uiSlots.updateTraitContent(sourceTrait, {
|
|
39391
|
+
pattern: patternType,
|
|
39392
|
+
props,
|
|
39393
|
+
priority: 0,
|
|
39394
|
+
animation: "fade"
|
|
39395
|
+
});
|
|
39396
|
+
} else {
|
|
39397
|
+
xOrbitalLog3.info("slot-write", {
|
|
39398
|
+
slot: eff.slot,
|
|
39399
|
+
sourceTrait,
|
|
39400
|
+
patternType: typeof patternType === "string" ? patternType : void 0
|
|
39401
|
+
});
|
|
39402
|
+
uiSlots.render({
|
|
39403
|
+
target: eff.slot,
|
|
39404
|
+
pattern: patternType,
|
|
39405
|
+
props,
|
|
39406
|
+
sourceTrait
|
|
39407
|
+
});
|
|
39408
|
+
}
|
|
39293
39409
|
} else if (eff.type === "navigate" && eff.route && onNavigate) {
|
|
39294
39410
|
onNavigate(eff.route, eff.params);
|
|
39295
39411
|
}
|
|
39296
39412
|
}
|
|
39297
39413
|
}
|
|
39298
|
-
function TraitInitializer({ traits: traits2, orbitalNames, onNavigate, onLocalFallback, persistence, traitConfigsByName, orbitalsByTrait }) {
|
|
39414
|
+
function TraitInitializer({ traits: traits2, orbitalNames, onNavigate, onLocalFallback, persistence, traitConfigsByName, orbitalsByTrait, embeddedTraits }) {
|
|
39299
39415
|
const slotsActions = useSlotsActions();
|
|
39300
39416
|
const bridge = useServerBridge();
|
|
39301
39417
|
const uiSlots = context.useUISlots();
|
|
@@ -39311,9 +39427,9 @@ function TraitInitializer({ traits: traits2, orbitalNames, onNavigate, onLocalFa
|
|
|
39311
39427
|
for (const name of targets) {
|
|
39312
39428
|
const { effects, meta } = await bridge.sendEvent(name, event, payload);
|
|
39313
39429
|
recordServerResponse(name, event, meta);
|
|
39314
|
-
applyServerEffects(effects, uiSlots, onNavigate);
|
|
39430
|
+
applyServerEffects(effects, uiSlots, onNavigate, embeddedTraits);
|
|
39315
39431
|
}
|
|
39316
|
-
}, [bridge.connected, bridge.sendEvent, orbitalNames, uiSlots, onNavigate]);
|
|
39432
|
+
}, [bridge.connected, bridge.sendEvent, orbitalNames, uiSlots, onNavigate, embeddedTraits]);
|
|
39317
39433
|
const opts = orbitalNames ? { onEventProcessed, navigate: onNavigate, traitConfigsByName, orbitalsByTrait } : { navigate: onNavigate, persistence, traitConfigsByName, orbitalsByTrait };
|
|
39318
39434
|
const { sendEvent } = useTraitStateMachine(traits2, slotsActions, opts);
|
|
39319
39435
|
const initSentRef = React115.useRef(false);
|
|
@@ -39353,13 +39469,13 @@ function TraitInitializer({ traits: traits2, orbitalNames, onNavigate, onLocalFa
|
|
|
39353
39469
|
effects: effectTraces,
|
|
39354
39470
|
timestamp: Date.now()
|
|
39355
39471
|
});
|
|
39356
|
-
applyServerEffects(effects, uiSlots, onNavigate);
|
|
39472
|
+
applyServerEffects(effects, uiSlots, onNavigate, embeddedTraits);
|
|
39357
39473
|
}
|
|
39358
39474
|
})();
|
|
39359
|
-
}, [bridge.connected, orbitalNames, bridge.sendEvent, uiSlots, onNavigate]);
|
|
39475
|
+
}, [bridge.connected, orbitalNames, bridge.sendEvent, uiSlots, onNavigate, embeddedTraits]);
|
|
39360
39476
|
return null;
|
|
39361
39477
|
}
|
|
39362
|
-
function SchemaRunner({ schema, serverUrl, mockData, pageName, onNavigate, onLocalFallback, persistence }) {
|
|
39478
|
+
function SchemaRunner({ schema, serverUrl, transport, mockData, pageName, onNavigate, onLocalFallback, persistence }) {
|
|
39363
39479
|
const { traits: traits2, allEntities, ir } = useResolvedSchema(schema, pageName);
|
|
39364
39480
|
const allPageTraits = React115.useMemo(() => {
|
|
39365
39481
|
if (pageName && traits2.length > 0) return traits2;
|
|
@@ -39462,6 +39578,9 @@ function SchemaRunner({ schema, serverUrl, mockData, pageName, onNavigate, onLoc
|
|
|
39462
39578
|
}
|
|
39463
39579
|
return map;
|
|
39464
39580
|
}, [schema]);
|
|
39581
|
+
const embeddedTraits = React115.useMemo(() => {
|
|
39582
|
+
return collectEmbeddedTraits(schema);
|
|
39583
|
+
}, [schema]);
|
|
39465
39584
|
const inner = /* @__PURE__ */ jsxRuntime.jsx(providers.VerificationProvider, { enabled: true, children: /* @__PURE__ */ jsxRuntime.jsx(SlotsProvider, { children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
39466
39585
|
EntitySchemaProvider,
|
|
39467
39586
|
{
|
|
@@ -39473,9 +39592,10 @@ function SchemaRunner({ schema, serverUrl, mockData, pageName, onNavigate, onLoc
|
|
|
39473
39592
|
TraitInitializer,
|
|
39474
39593
|
{
|
|
39475
39594
|
traits: allPageTraits,
|
|
39476
|
-
orbitalNames: serverUrl ? pageOrbitalNames : void 0,
|
|
39595
|
+
orbitalNames: serverUrl || transport ? pageOrbitalNames : void 0,
|
|
39477
39596
|
traitConfigsByName,
|
|
39478
39597
|
orbitalsByTrait,
|
|
39598
|
+
embeddedTraits,
|
|
39479
39599
|
onNavigate,
|
|
39480
39600
|
onLocalFallback,
|
|
39481
39601
|
persistence
|
|
@@ -39486,8 +39606,8 @@ function SchemaRunner({ schema, serverUrl, mockData, pageName, onNavigate, onLoc
|
|
|
39486
39606
|
]
|
|
39487
39607
|
}
|
|
39488
39608
|
) }) });
|
|
39489
|
-
if (serverUrl) {
|
|
39490
|
-
return /* @__PURE__ */ jsxRuntime.jsx(ServerBridgeProvider, { schema, serverUrl, children: inner });
|
|
39609
|
+
if (serverUrl || transport) {
|
|
39610
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ServerBridgeProvider, { schema, serverUrl, transport, children: inner });
|
|
39491
39611
|
}
|
|
39492
39612
|
return inner;
|
|
39493
39613
|
}
|
|
@@ -39498,8 +39618,12 @@ function OrbPreview({
|
|
|
39498
39618
|
height = "400px",
|
|
39499
39619
|
className,
|
|
39500
39620
|
serverUrl,
|
|
39621
|
+
transport,
|
|
39501
39622
|
initialPagePath
|
|
39502
39623
|
}) {
|
|
39624
|
+
if (serverUrl && transport) {
|
|
39625
|
+
throw new Error("OrbPreview accepts serverUrl OR transport, not both");
|
|
39626
|
+
}
|
|
39503
39627
|
const [localFallback, setLocalFallback] = React115.useState(false);
|
|
39504
39628
|
const eventBus = useEventBus();
|
|
39505
39629
|
const handleLocalFallback = React115.useCallback(() => {
|
|
@@ -39521,21 +39645,21 @@ function OrbPreview({
|
|
|
39521
39645
|
} else {
|
|
39522
39646
|
parsed = schema;
|
|
39523
39647
|
}
|
|
39524
|
-
if (autoMock && !serverUrl) {
|
|
39648
|
+
if (autoMock && !serverUrl && !transport) {
|
|
39525
39649
|
const prepared = prepareSchemaForPreview(parsed);
|
|
39526
39650
|
return { ok: true, schema: prepared.schema, mockData: prepared.mockData };
|
|
39527
39651
|
}
|
|
39528
39652
|
return { ok: true, schema: parsed, mockData: mockData ?? {} };
|
|
39529
|
-
}, [schema, autoMock, serverUrl, mockData]);
|
|
39653
|
+
}, [schema, autoMock, serverUrl, transport, mockData]);
|
|
39530
39654
|
const parsedSchema = parseResult.ok ? parseResult.schema : null;
|
|
39531
39655
|
const effectiveMockData = parseResult.ok ? parseResult.mockData : {};
|
|
39532
39656
|
const persistence = React115.useMemo(() => {
|
|
39533
|
-
if (!parsedSchema || serverUrl) return void 0;
|
|
39657
|
+
if (!parsedSchema || serverUrl || transport) return void 0;
|
|
39534
39658
|
if (!autoMock) return void 0;
|
|
39535
39659
|
const adapter = new runtime.InMemoryPersistence();
|
|
39536
39660
|
adapter.seed(effectiveMockData);
|
|
39537
39661
|
return adapter;
|
|
39538
|
-
}, [parsedSchema, serverUrl, autoMock, effectiveMockData]);
|
|
39662
|
+
}, [parsedSchema, serverUrl, transport, autoMock, effectiveMockData]);
|
|
39539
39663
|
const pages = React115.useMemo(() => {
|
|
39540
39664
|
if (!parsedSchema) return [];
|
|
39541
39665
|
try {
|
|
@@ -39597,6 +39721,7 @@ function OrbPreview({
|
|
|
39597
39721
|
{
|
|
39598
39722
|
schema: parsedSchema,
|
|
39599
39723
|
serverUrl,
|
|
39724
|
+
transport,
|
|
39600
39725
|
mockData: effectiveMockData,
|
|
39601
39726
|
pageName: currentPage,
|
|
39602
39727
|
onNavigate: handleNavigate,
|
|
@@ -39609,7 +39734,50 @@ function OrbPreview({
|
|
|
39609
39734
|
);
|
|
39610
39735
|
}
|
|
39611
39736
|
OrbPreview.displayName = "OrbPreview";
|
|
39737
|
+
function BrowserPlayground({
|
|
39738
|
+
schema,
|
|
39739
|
+
mode = "mock",
|
|
39740
|
+
initialPagePath,
|
|
39741
|
+
height,
|
|
39742
|
+
className
|
|
39743
|
+
}) {
|
|
39744
|
+
const [runtime] = React115.useState(
|
|
39745
|
+
() => new OrbitalServerRuntime.OrbitalServerRuntime({ mode, debug: false })
|
|
39746
|
+
);
|
|
39747
|
+
React115.useEffect(() => {
|
|
39748
|
+
void runtime.register(schema);
|
|
39749
|
+
return () => {
|
|
39750
|
+
runtime.unregisterAll();
|
|
39751
|
+
};
|
|
39752
|
+
}, [runtime, schema]);
|
|
39753
|
+
const transport = React115.useMemo(() => ({
|
|
39754
|
+
register: async (s) => {
|
|
39755
|
+
await runtime.register(s);
|
|
39756
|
+
return true;
|
|
39757
|
+
},
|
|
39758
|
+
unregister: async () => {
|
|
39759
|
+
runtime.unregisterAll();
|
|
39760
|
+
},
|
|
39761
|
+
sendEvent: async (orbitalName, event, payload) => {
|
|
39762
|
+
return runtime.processOrbitalEvent(orbitalName, {
|
|
39763
|
+
event,
|
|
39764
|
+
payload
|
|
39765
|
+
});
|
|
39766
|
+
}
|
|
39767
|
+
}), [runtime]);
|
|
39768
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
39769
|
+
OrbPreview,
|
|
39770
|
+
{
|
|
39771
|
+
schema,
|
|
39772
|
+
transport,
|
|
39773
|
+
initialPagePath,
|
|
39774
|
+
height,
|
|
39775
|
+
className
|
|
39776
|
+
}
|
|
39777
|
+
);
|
|
39778
|
+
}
|
|
39612
39779
|
|
|
39780
|
+
exports.BrowserPlayground = BrowserPlayground;
|
|
39613
39781
|
exports.EntitySchemaProvider = EntitySchemaProvider;
|
|
39614
39782
|
exports.OrbPreview = OrbPreview;
|
|
39615
39783
|
exports.ServerBridgeProvider = ServerBridgeProvider;
|
package/dist/runtime/index.d.ts
CHANGED
|
@@ -13,6 +13,7 @@ export { TraitProvider, TraitContext, useTraitContext, useTrait, type TraitConte
|
|
|
13
13
|
export { SlotsProvider, useSlots, useSlotContent, useSlotsActions, type SlotsState, type SlotState, type SlotPatternEntry, type SlotSource, type SlotsActions, type SlotsProviderProps, } from './ui/SlotsContext';
|
|
14
14
|
export { createClientEffectHandlers, type ClientEventBus, type SlotSetter, type CreateClientEffectHandlersOptions, } from './createClientEffectHandlers';
|
|
15
15
|
export { OrbPreview, type OrbPreviewProps } from './OrbPreview';
|
|
16
|
+
export { BrowserPlayground, type BrowserPlaygroundProps } from './BrowserPlayground';
|
|
16
17
|
export { prepareSchemaForPreview, buildMockData, adjustSchemaForMockData, type PreparedPreviewSchema, } from './prepareSchemaForPreview';
|
|
17
|
-
export { ServerBridgeProvider, useServerBridge, type ServerBridgeContextValue, type ServerClientEffect } from './ServerBridge';
|
|
18
|
+
export { ServerBridgeProvider, useServerBridge, type ServerBridgeContextValue, type ServerBridgeTransport, type ServerClientEffect } from './ServerBridge';
|
|
18
19
|
export type { ResolvedTraitBinding, ResolvedTrait, ResolvedEntity, ResolvedPage, ResolvedIR, } from './types';
|