@almadar/ui 4.10.7 → 4.11.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.
@@ -52200,6 +52200,38 @@ init_EntitySchemaContext();
52200
52200
  init_useEventBus();
52201
52201
  init_logger();
52202
52202
  var xOrbitalLog2 = createLogger("almadar:runtime:cross-orbital");
52203
+ function createHttpTransport(serverUrl) {
52204
+ return {
52205
+ register: async (schema) => {
52206
+ try {
52207
+ const res = await fetch(`${serverUrl}/register`, {
52208
+ method: "POST",
52209
+ headers: { "Content-Type": "application/json" },
52210
+ body: JSON.stringify({ schema })
52211
+ });
52212
+ const result = await res.json();
52213
+ return !!result.success;
52214
+ } catch (err) {
52215
+ console.error("[ServerBridge] Registration failed:", err);
52216
+ return false;
52217
+ }
52218
+ },
52219
+ unregister: async () => {
52220
+ try {
52221
+ await fetch(`${serverUrl}/unregister`, { method: "DELETE" });
52222
+ } catch {
52223
+ }
52224
+ },
52225
+ sendEvent: async (orbitalName, event, payload) => {
52226
+ const res = await fetch(`${serverUrl}/${orbitalName}/events`, {
52227
+ method: "POST",
52228
+ headers: { "Content-Type": "application/json" },
52229
+ body: JSON.stringify({ event, payload })
52230
+ });
52231
+ return res.json();
52232
+ }
52233
+ };
52234
+ }
52203
52235
  var ServerBridgeContext = React128.createContext(null);
52204
52236
  function useServerBridge() {
52205
52237
  const ctx = React128.useContext(ServerBridgeContext);
@@ -52212,40 +52244,34 @@ function useServerBridge() {
52212
52244
  function ServerBridgeProvider({
52213
52245
  schema,
52214
52246
  serverUrl,
52247
+ transport: customTransport,
52215
52248
  children
52216
52249
  }) {
52250
+ if (!serverUrl && !customTransport) {
52251
+ throw new Error("ServerBridgeProvider requires either serverUrl or transport");
52252
+ }
52253
+ if (serverUrl && customTransport) {
52254
+ throw new Error("ServerBridgeProvider accepts serverUrl OR transport, not both");
52255
+ }
52217
52256
  const eventBus = useEventBus();
52218
52257
  const [connected, setConnected] = React128.useState(false);
52219
- const registerSchema = React128.useCallback(async () => {
52220
- try {
52221
- const res = await fetch(`${serverUrl}/register`, {
52222
- method: "POST",
52223
- headers: { "Content-Type": "application/json" },
52224
- body: JSON.stringify({ schema })
52225
- });
52226
- const result = await res.json();
52227
- return !!result.success;
52228
- } catch (err) {
52229
- console.error("[ServerBridge] Registration failed:", err);
52230
- return false;
52231
- }
52232
- }, [schema, serverUrl]);
52233
- const unregisterSchema = React128.useCallback(async () => {
52234
- try {
52235
- await fetch(`${serverUrl}/unregister`, { method: "DELETE" });
52236
- } catch {
52237
- }
52238
- }, [serverUrl]);
52258
+ const transport = React128.useMemo(
52259
+ () => customTransport ?? createHttpTransport(serverUrl),
52260
+ [serverUrl, customTransport]
52261
+ );
52262
+ const registerSchema = React128.useCallback(
52263
+ async () => transport.register(schema),
52264
+ [schema, transport]
52265
+ );
52266
+ const unregisterSchema = React128.useCallback(
52267
+ async () => transport.unregister(),
52268
+ [transport]
52269
+ );
52239
52270
  const sendEvent = React128.useCallback(async (orbitalName, event, payload) => {
52240
52271
  const emptyMeta = { success: false, clientEffects: 0, dataEntities: {}, emittedEvents: [] };
52241
52272
  if (!connected) return { effects: [], meta: emptyMeta };
52242
52273
  try {
52243
- const res = await fetch(`${serverUrl}/${orbitalName}/events`, {
52244
- method: "POST",
52245
- headers: { "Content-Type": "application/json" },
52246
- body: JSON.stringify({ event, payload })
52247
- });
52248
- const result = await res.json();
52274
+ const result = await transport.sendEvent(orbitalName, event, payload);
52249
52275
  const effects = [];
52250
52276
  const responseData = result.data || {};
52251
52277
  const dataEntities = {};
@@ -52303,7 +52329,7 @@ function ServerBridgeProvider({
52303
52329
  console.error("[ServerBridge] Event send failed:", err);
52304
52330
  return { effects: [], meta: { ...emptyMeta, error: err instanceof Error ? err.message : String(err) } };
52305
52331
  }
52306
- }, [connected, serverUrl, eventBus]);
52332
+ }, [connected, transport, eventBus]);
52307
52333
  React128.useEffect(() => {
52308
52334
  if (!schema) return;
52309
52335
  let cancelled = false;
@@ -52579,7 +52605,7 @@ function TraitInitializer({ traits: traits2, orbitalNames, onNavigate, onLocalFa
52579
52605
  }, [bridge.connected, orbitalNames, bridge.sendEvent, uiSlots, onNavigate]);
52580
52606
  return null;
52581
52607
  }
52582
- function SchemaRunner({ schema, serverUrl, mockData, pageName, onNavigate, onLocalFallback, persistence }) {
52608
+ function SchemaRunner({ schema, serverUrl, transport, mockData, pageName, onNavigate, onLocalFallback, persistence }) {
52583
52609
  const { traits: traits2, allEntities, ir } = useResolvedSchema(schema, pageName);
52584
52610
  const allPageTraits = React128.useMemo(() => {
52585
52611
  if (pageName && traits2.length > 0) return traits2;
@@ -52693,7 +52719,7 @@ function SchemaRunner({ schema, serverUrl, mockData, pageName, onNavigate, onLoc
52693
52719
  TraitInitializer,
52694
52720
  {
52695
52721
  traits: allPageTraits,
52696
- orbitalNames: serverUrl ? pageOrbitalNames : void 0,
52722
+ orbitalNames: serverUrl || transport ? pageOrbitalNames : void 0,
52697
52723
  traitConfigsByName,
52698
52724
  orbitalsByTrait,
52699
52725
  onNavigate,
@@ -52706,8 +52732,8 @@ function SchemaRunner({ schema, serverUrl, mockData, pageName, onNavigate, onLoc
52706
52732
  ]
52707
52733
  }
52708
52734
  ) }) });
52709
- if (serverUrl) {
52710
- return /* @__PURE__ */ jsxRuntime.jsx(ServerBridgeProvider, { schema, serverUrl, children: inner });
52735
+ if (serverUrl || transport) {
52736
+ return /* @__PURE__ */ jsxRuntime.jsx(ServerBridgeProvider, { schema, serverUrl, transport, children: inner });
52711
52737
  }
52712
52738
  return inner;
52713
52739
  }
@@ -52718,8 +52744,12 @@ function OrbPreview({
52718
52744
  height = "400px",
52719
52745
  className,
52720
52746
  serverUrl,
52747
+ transport,
52721
52748
  initialPagePath
52722
52749
  }) {
52750
+ if (serverUrl && transport) {
52751
+ throw new Error("OrbPreview accepts serverUrl OR transport, not both");
52752
+ }
52723
52753
  const [localFallback, setLocalFallback] = React128.useState(false);
52724
52754
  const eventBus = useEventBus();
52725
52755
  const handleLocalFallback = React128.useCallback(() => {
@@ -52741,21 +52771,21 @@ function OrbPreview({
52741
52771
  } else {
52742
52772
  parsed = schema;
52743
52773
  }
52744
- if (autoMock && !serverUrl) {
52774
+ if (autoMock && !serverUrl && !transport) {
52745
52775
  const prepared = prepareSchemaForPreview(parsed);
52746
52776
  return { ok: true, schema: prepared.schema, mockData: prepared.mockData };
52747
52777
  }
52748
52778
  return { ok: true, schema: parsed, mockData: mockData ?? {} };
52749
- }, [schema, autoMock, serverUrl, mockData]);
52779
+ }, [schema, autoMock, serverUrl, transport, mockData]);
52750
52780
  const parsedSchema = parseResult.ok ? parseResult.schema : null;
52751
52781
  const effectiveMockData = parseResult.ok ? parseResult.mockData : {};
52752
52782
  const persistence = React128.useMemo(() => {
52753
- if (!parsedSchema || serverUrl) return void 0;
52783
+ if (!parsedSchema || serverUrl || transport) return void 0;
52754
52784
  if (!autoMock) return void 0;
52755
52785
  const adapter = new runtime.InMemoryPersistence();
52756
52786
  adapter.seed(effectiveMockData);
52757
52787
  return adapter;
52758
- }, [parsedSchema, serverUrl, autoMock, effectiveMockData]);
52788
+ }, [parsedSchema, serverUrl, transport, autoMock, effectiveMockData]);
52759
52789
  const pages = React128.useMemo(() => {
52760
52790
  if (!parsedSchema) return [];
52761
52791
  try {
@@ -52817,6 +52847,7 @@ function OrbPreview({
52817
52847
  {
52818
52848
  schema: parsedSchema,
52819
52849
  serverUrl,
52850
+ transport,
52820
52851
  mockData: effectiveMockData,
52821
52852
  pageName: currentPage,
52822
52853
  onNavigate: handleNavigate,
package/dist/avl/index.js CHANGED
@@ -52154,6 +52154,38 @@ init_EntitySchemaContext();
52154
52154
  init_useEventBus();
52155
52155
  init_logger();
52156
52156
  var xOrbitalLog2 = createLogger("almadar:runtime:cross-orbital");
52157
+ function createHttpTransport(serverUrl) {
52158
+ return {
52159
+ register: async (schema) => {
52160
+ try {
52161
+ const res = await fetch(`${serverUrl}/register`, {
52162
+ method: "POST",
52163
+ headers: { "Content-Type": "application/json" },
52164
+ body: JSON.stringify({ schema })
52165
+ });
52166
+ const result = await res.json();
52167
+ return !!result.success;
52168
+ } catch (err) {
52169
+ console.error("[ServerBridge] Registration failed:", err);
52170
+ return false;
52171
+ }
52172
+ },
52173
+ unregister: async () => {
52174
+ try {
52175
+ await fetch(`${serverUrl}/unregister`, { method: "DELETE" });
52176
+ } catch {
52177
+ }
52178
+ },
52179
+ sendEvent: async (orbitalName, event, payload) => {
52180
+ const res = await fetch(`${serverUrl}/${orbitalName}/events`, {
52181
+ method: "POST",
52182
+ headers: { "Content-Type": "application/json" },
52183
+ body: JSON.stringify({ event, payload })
52184
+ });
52185
+ return res.json();
52186
+ }
52187
+ };
52188
+ }
52157
52189
  var ServerBridgeContext = createContext(null);
52158
52190
  function useServerBridge() {
52159
52191
  const ctx = useContext(ServerBridgeContext);
@@ -52166,40 +52198,34 @@ function useServerBridge() {
52166
52198
  function ServerBridgeProvider({
52167
52199
  schema,
52168
52200
  serverUrl,
52201
+ transport: customTransport,
52169
52202
  children
52170
52203
  }) {
52204
+ if (!serverUrl && !customTransport) {
52205
+ throw new Error("ServerBridgeProvider requires either serverUrl or transport");
52206
+ }
52207
+ if (serverUrl && customTransport) {
52208
+ throw new Error("ServerBridgeProvider accepts serverUrl OR transport, not both");
52209
+ }
52171
52210
  const eventBus = useEventBus();
52172
52211
  const [connected, setConnected] = useState(false);
52173
- const registerSchema = useCallback(async () => {
52174
- try {
52175
- const res = await fetch(`${serverUrl}/register`, {
52176
- method: "POST",
52177
- headers: { "Content-Type": "application/json" },
52178
- body: JSON.stringify({ schema })
52179
- });
52180
- const result = await res.json();
52181
- return !!result.success;
52182
- } catch (err) {
52183
- console.error("[ServerBridge] Registration failed:", err);
52184
- return false;
52185
- }
52186
- }, [schema, serverUrl]);
52187
- const unregisterSchema = useCallback(async () => {
52188
- try {
52189
- await fetch(`${serverUrl}/unregister`, { method: "DELETE" });
52190
- } catch {
52191
- }
52192
- }, [serverUrl]);
52212
+ const transport = useMemo(
52213
+ () => customTransport ?? createHttpTransport(serverUrl),
52214
+ [serverUrl, customTransport]
52215
+ );
52216
+ const registerSchema = useCallback(
52217
+ async () => transport.register(schema),
52218
+ [schema, transport]
52219
+ );
52220
+ const unregisterSchema = useCallback(
52221
+ async () => transport.unregister(),
52222
+ [transport]
52223
+ );
52193
52224
  const sendEvent = useCallback(async (orbitalName, event, payload) => {
52194
52225
  const emptyMeta = { success: false, clientEffects: 0, dataEntities: {}, emittedEvents: [] };
52195
52226
  if (!connected) return { effects: [], meta: emptyMeta };
52196
52227
  try {
52197
- const res = await fetch(`${serverUrl}/${orbitalName}/events`, {
52198
- method: "POST",
52199
- headers: { "Content-Type": "application/json" },
52200
- body: JSON.stringify({ event, payload })
52201
- });
52202
- const result = await res.json();
52228
+ const result = await transport.sendEvent(orbitalName, event, payload);
52203
52229
  const effects = [];
52204
52230
  const responseData = result.data || {};
52205
52231
  const dataEntities = {};
@@ -52257,7 +52283,7 @@ function ServerBridgeProvider({
52257
52283
  console.error("[ServerBridge] Event send failed:", err);
52258
52284
  return { effects: [], meta: { ...emptyMeta, error: err instanceof Error ? err.message : String(err) } };
52259
52285
  }
52260
- }, [connected, serverUrl, eventBus]);
52286
+ }, [connected, transport, eventBus]);
52261
52287
  useEffect(() => {
52262
52288
  if (!schema) return;
52263
52289
  let cancelled = false;
@@ -52533,7 +52559,7 @@ function TraitInitializer({ traits: traits2, orbitalNames, onNavigate, onLocalFa
52533
52559
  }, [bridge.connected, orbitalNames, bridge.sendEvent, uiSlots, onNavigate]);
52534
52560
  return null;
52535
52561
  }
52536
- function SchemaRunner({ schema, serverUrl, mockData, pageName, onNavigate, onLocalFallback, persistence }) {
52562
+ function SchemaRunner({ schema, serverUrl, transport, mockData, pageName, onNavigate, onLocalFallback, persistence }) {
52537
52563
  const { traits: traits2, allEntities, ir } = useResolvedSchema(schema, pageName);
52538
52564
  const allPageTraits = useMemo(() => {
52539
52565
  if (pageName && traits2.length > 0) return traits2;
@@ -52647,7 +52673,7 @@ function SchemaRunner({ schema, serverUrl, mockData, pageName, onNavigate, onLoc
52647
52673
  TraitInitializer,
52648
52674
  {
52649
52675
  traits: allPageTraits,
52650
- orbitalNames: serverUrl ? pageOrbitalNames : void 0,
52676
+ orbitalNames: serverUrl || transport ? pageOrbitalNames : void 0,
52651
52677
  traitConfigsByName,
52652
52678
  orbitalsByTrait,
52653
52679
  onNavigate,
@@ -52660,8 +52686,8 @@ function SchemaRunner({ schema, serverUrl, mockData, pageName, onNavigate, onLoc
52660
52686
  ]
52661
52687
  }
52662
52688
  ) }) });
52663
- if (serverUrl) {
52664
- return /* @__PURE__ */ jsx(ServerBridgeProvider, { schema, serverUrl, children: inner });
52689
+ if (serverUrl || transport) {
52690
+ return /* @__PURE__ */ jsx(ServerBridgeProvider, { schema, serverUrl, transport, children: inner });
52665
52691
  }
52666
52692
  return inner;
52667
52693
  }
@@ -52672,8 +52698,12 @@ function OrbPreview({
52672
52698
  height = "400px",
52673
52699
  className,
52674
52700
  serverUrl,
52701
+ transport,
52675
52702
  initialPagePath
52676
52703
  }) {
52704
+ if (serverUrl && transport) {
52705
+ throw new Error("OrbPreview accepts serverUrl OR transport, not both");
52706
+ }
52677
52707
  const [localFallback, setLocalFallback] = useState(false);
52678
52708
  const eventBus = useEventBus();
52679
52709
  const handleLocalFallback = useCallback(() => {
@@ -52695,21 +52725,21 @@ function OrbPreview({
52695
52725
  } else {
52696
52726
  parsed = schema;
52697
52727
  }
52698
- if (autoMock && !serverUrl) {
52728
+ if (autoMock && !serverUrl && !transport) {
52699
52729
  const prepared = prepareSchemaForPreview(parsed);
52700
52730
  return { ok: true, schema: prepared.schema, mockData: prepared.mockData };
52701
52731
  }
52702
52732
  return { ok: true, schema: parsed, mockData: mockData ?? {} };
52703
- }, [schema, autoMock, serverUrl, mockData]);
52733
+ }, [schema, autoMock, serverUrl, transport, mockData]);
52704
52734
  const parsedSchema = parseResult.ok ? parseResult.schema : null;
52705
52735
  const effectiveMockData = parseResult.ok ? parseResult.mockData : {};
52706
52736
  const persistence = useMemo(() => {
52707
- if (!parsedSchema || serverUrl) return void 0;
52737
+ if (!parsedSchema || serverUrl || transport) return void 0;
52708
52738
  if (!autoMock) return void 0;
52709
52739
  const adapter = new InMemoryPersistence();
52710
52740
  adapter.seed(effectiveMockData);
52711
52741
  return adapter;
52712
- }, [parsedSchema, serverUrl, autoMock, effectiveMockData]);
52742
+ }, [parsedSchema, serverUrl, transport, autoMock, effectiveMockData]);
52713
52743
  const pages = useMemo(() => {
52714
52744
  if (!parsedSchema) return [];
52715
52745
  try {
@@ -52771,6 +52801,7 @@ function OrbPreview({
52771
52801
  {
52772
52802
  schema: parsedSchema,
52773
52803
  serverUrl,
52804
+ transport,
52774
52805
  mockData: effectiveMockData,
52775
52806
  pageName: currentPage,
52776
52807
  onNavigate: handleNavigate,
@@ -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
  }
@@ -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
- serverUrl: string;
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 {};
@@ -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: useEffect68, useRef: useRef65, useCallback: useCallback110, useState: useState102 } = React115__namespace.default;
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
- useEffect68(() => {
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
- useEffect68(() => {
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] = useState102(null);
8277
+ const [clickedPosition, setClickedPosition] = useState103(null);
8277
8278
  const handleMapClick = useCallback110((lat, lng) => {
8278
8279
  if (showClickedPin) {
8279
8280
  setClickedPosition({ lat, lng });
@@ -38980,6 +38981,38 @@ init_EntitySchemaContext();
38980
38981
  init_useEventBus();
38981
38982
  init_logger();
38982
38983
  var xOrbitalLog2 = createLogger("almadar:runtime:cross-orbital");
38984
+ function createHttpTransport(serverUrl) {
38985
+ return {
38986
+ register: async (schema) => {
38987
+ try {
38988
+ const res = await fetch(`${serverUrl}/register`, {
38989
+ method: "POST",
38990
+ headers: { "Content-Type": "application/json" },
38991
+ body: JSON.stringify({ schema })
38992
+ });
38993
+ const result = await res.json();
38994
+ return !!result.success;
38995
+ } catch (err) {
38996
+ console.error("[ServerBridge] Registration failed:", err);
38997
+ return false;
38998
+ }
38999
+ },
39000
+ unregister: async () => {
39001
+ try {
39002
+ await fetch(`${serverUrl}/unregister`, { method: "DELETE" });
39003
+ } catch {
39004
+ }
39005
+ },
39006
+ sendEvent: async (orbitalName, event, payload) => {
39007
+ const res = await fetch(`${serverUrl}/${orbitalName}/events`, {
39008
+ method: "POST",
39009
+ headers: { "Content-Type": "application/json" },
39010
+ body: JSON.stringify({ event, payload })
39011
+ });
39012
+ return res.json();
39013
+ }
39014
+ };
39015
+ }
38983
39016
  var ServerBridgeContext = React115.createContext(null);
38984
39017
  function useServerBridge() {
38985
39018
  const ctx = React115.useContext(ServerBridgeContext);
@@ -38992,40 +39025,34 @@ function useServerBridge() {
38992
39025
  function ServerBridgeProvider({
38993
39026
  schema,
38994
39027
  serverUrl,
39028
+ transport: customTransport,
38995
39029
  children
38996
39030
  }) {
39031
+ if (!serverUrl && !customTransport) {
39032
+ throw new Error("ServerBridgeProvider requires either serverUrl or transport");
39033
+ }
39034
+ if (serverUrl && customTransport) {
39035
+ throw new Error("ServerBridgeProvider accepts serverUrl OR transport, not both");
39036
+ }
38997
39037
  const eventBus = useEventBus();
38998
39038
  const [connected, setConnected] = React115.useState(false);
38999
- const registerSchema = React115.useCallback(async () => {
39000
- try {
39001
- const res = await fetch(`${serverUrl}/register`, {
39002
- method: "POST",
39003
- headers: { "Content-Type": "application/json" },
39004
- body: JSON.stringify({ schema })
39005
- });
39006
- const result = await res.json();
39007
- return !!result.success;
39008
- } catch (err) {
39009
- console.error("[ServerBridge] Registration failed:", err);
39010
- return false;
39011
- }
39012
- }, [schema, serverUrl]);
39013
- const unregisterSchema = React115.useCallback(async () => {
39014
- try {
39015
- await fetch(`${serverUrl}/unregister`, { method: "DELETE" });
39016
- } catch {
39017
- }
39018
- }, [serverUrl]);
39039
+ const transport = React115.useMemo(
39040
+ () => customTransport ?? createHttpTransport(serverUrl),
39041
+ [serverUrl, customTransport]
39042
+ );
39043
+ const registerSchema = React115.useCallback(
39044
+ async () => transport.register(schema),
39045
+ [schema, transport]
39046
+ );
39047
+ const unregisterSchema = React115.useCallback(
39048
+ async () => transport.unregister(),
39049
+ [transport]
39050
+ );
39019
39051
  const sendEvent = React115.useCallback(async (orbitalName, event, payload) => {
39020
39052
  const emptyMeta = { success: false, clientEffects: 0, dataEntities: {}, emittedEvents: [] };
39021
39053
  if (!connected) return { effects: [], meta: emptyMeta };
39022
39054
  try {
39023
- const res = await fetch(`${serverUrl}/${orbitalName}/events`, {
39024
- method: "POST",
39025
- headers: { "Content-Type": "application/json" },
39026
- body: JSON.stringify({ event, payload })
39027
- });
39028
- const result = await res.json();
39055
+ const result = await transport.sendEvent(orbitalName, event, payload);
39029
39056
  const effects = [];
39030
39057
  const responseData = result.data || {};
39031
39058
  const dataEntities = {};
@@ -39083,7 +39110,7 @@ function ServerBridgeProvider({
39083
39110
  console.error("[ServerBridge] Event send failed:", err);
39084
39111
  return { effects: [], meta: { ...emptyMeta, error: err instanceof Error ? err.message : String(err) } };
39085
39112
  }
39086
- }, [connected, serverUrl, eventBus]);
39113
+ }, [connected, transport, eventBus]);
39087
39114
  React115.useEffect(() => {
39088
39115
  if (!schema) return;
39089
39116
  let cancelled = false;
@@ -39359,7 +39386,7 @@ function TraitInitializer({ traits: traits2, orbitalNames, onNavigate, onLocalFa
39359
39386
  }, [bridge.connected, orbitalNames, bridge.sendEvent, uiSlots, onNavigate]);
39360
39387
  return null;
39361
39388
  }
39362
- function SchemaRunner({ schema, serverUrl, mockData, pageName, onNavigate, onLocalFallback, persistence }) {
39389
+ function SchemaRunner({ schema, serverUrl, transport, mockData, pageName, onNavigate, onLocalFallback, persistence }) {
39363
39390
  const { traits: traits2, allEntities, ir } = useResolvedSchema(schema, pageName);
39364
39391
  const allPageTraits = React115.useMemo(() => {
39365
39392
  if (pageName && traits2.length > 0) return traits2;
@@ -39473,7 +39500,7 @@ function SchemaRunner({ schema, serverUrl, mockData, pageName, onNavigate, onLoc
39473
39500
  TraitInitializer,
39474
39501
  {
39475
39502
  traits: allPageTraits,
39476
- orbitalNames: serverUrl ? pageOrbitalNames : void 0,
39503
+ orbitalNames: serverUrl || transport ? pageOrbitalNames : void 0,
39477
39504
  traitConfigsByName,
39478
39505
  orbitalsByTrait,
39479
39506
  onNavigate,
@@ -39486,8 +39513,8 @@ function SchemaRunner({ schema, serverUrl, mockData, pageName, onNavigate, onLoc
39486
39513
  ]
39487
39514
  }
39488
39515
  ) }) });
39489
- if (serverUrl) {
39490
- return /* @__PURE__ */ jsxRuntime.jsx(ServerBridgeProvider, { schema, serverUrl, children: inner });
39516
+ if (serverUrl || transport) {
39517
+ return /* @__PURE__ */ jsxRuntime.jsx(ServerBridgeProvider, { schema, serverUrl, transport, children: inner });
39491
39518
  }
39492
39519
  return inner;
39493
39520
  }
@@ -39498,8 +39525,12 @@ function OrbPreview({
39498
39525
  height = "400px",
39499
39526
  className,
39500
39527
  serverUrl,
39528
+ transport,
39501
39529
  initialPagePath
39502
39530
  }) {
39531
+ if (serverUrl && transport) {
39532
+ throw new Error("OrbPreview accepts serverUrl OR transport, not both");
39533
+ }
39503
39534
  const [localFallback, setLocalFallback] = React115.useState(false);
39504
39535
  const eventBus = useEventBus();
39505
39536
  const handleLocalFallback = React115.useCallback(() => {
@@ -39521,21 +39552,21 @@ function OrbPreview({
39521
39552
  } else {
39522
39553
  parsed = schema;
39523
39554
  }
39524
- if (autoMock && !serverUrl) {
39555
+ if (autoMock && !serverUrl && !transport) {
39525
39556
  const prepared = prepareSchemaForPreview(parsed);
39526
39557
  return { ok: true, schema: prepared.schema, mockData: prepared.mockData };
39527
39558
  }
39528
39559
  return { ok: true, schema: parsed, mockData: mockData ?? {} };
39529
- }, [schema, autoMock, serverUrl, mockData]);
39560
+ }, [schema, autoMock, serverUrl, transport, mockData]);
39530
39561
  const parsedSchema = parseResult.ok ? parseResult.schema : null;
39531
39562
  const effectiveMockData = parseResult.ok ? parseResult.mockData : {};
39532
39563
  const persistence = React115.useMemo(() => {
39533
- if (!parsedSchema || serverUrl) return void 0;
39564
+ if (!parsedSchema || serverUrl || transport) return void 0;
39534
39565
  if (!autoMock) return void 0;
39535
39566
  const adapter = new runtime.InMemoryPersistence();
39536
39567
  adapter.seed(effectiveMockData);
39537
39568
  return adapter;
39538
- }, [parsedSchema, serverUrl, autoMock, effectiveMockData]);
39569
+ }, [parsedSchema, serverUrl, transport, autoMock, effectiveMockData]);
39539
39570
  const pages = React115.useMemo(() => {
39540
39571
  if (!parsedSchema) return [];
39541
39572
  try {
@@ -39597,6 +39628,7 @@ function OrbPreview({
39597
39628
  {
39598
39629
  schema: parsedSchema,
39599
39630
  serverUrl,
39631
+ transport,
39600
39632
  mockData: effectiveMockData,
39601
39633
  pageName: currentPage,
39602
39634
  onNavigate: handleNavigate,
@@ -39609,7 +39641,50 @@ function OrbPreview({
39609
39641
  );
39610
39642
  }
39611
39643
  OrbPreview.displayName = "OrbPreview";
39644
+ function BrowserPlayground({
39645
+ schema,
39646
+ mode = "mock",
39647
+ initialPagePath,
39648
+ height,
39649
+ className
39650
+ }) {
39651
+ const [runtime] = React115.useState(
39652
+ () => new OrbitalServerRuntime.OrbitalServerRuntime({ mode, debug: false })
39653
+ );
39654
+ React115.useEffect(() => {
39655
+ void runtime.register(schema);
39656
+ return () => {
39657
+ runtime.unregisterAll();
39658
+ };
39659
+ }, [runtime, schema]);
39660
+ const transport = React115.useMemo(() => ({
39661
+ register: async (s) => {
39662
+ await runtime.register(s);
39663
+ return true;
39664
+ },
39665
+ unregister: async () => {
39666
+ runtime.unregisterAll();
39667
+ },
39668
+ sendEvent: async (orbitalName, event, payload) => {
39669
+ return runtime.processOrbitalEvent(orbitalName, {
39670
+ event,
39671
+ payload
39672
+ });
39673
+ }
39674
+ }), [runtime]);
39675
+ return /* @__PURE__ */ jsxRuntime.jsx(
39676
+ OrbPreview,
39677
+ {
39678
+ schema,
39679
+ transport,
39680
+ initialPagePath,
39681
+ height,
39682
+ className
39683
+ }
39684
+ );
39685
+ }
39612
39686
 
39687
+ exports.BrowserPlayground = BrowserPlayground;
39613
39688
  exports.EntitySchemaProvider = EntitySchemaProvider;
39614
39689
  exports.OrbPreview = OrbPreview;
39615
39690
  exports.ServerBridgeProvider = ServerBridgeProvider;
@@ -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';
@@ -37,6 +37,7 @@ import langGraphql from 'react-syntax-highlighter/dist/esm/languages/prism/graph
37
37
  import { isCircuitEvent, schemaToIR, getPage, clearSchemaCache as clearSchemaCache$1, isEntityCall, isInlineTrait } from '@almadar/core';
38
38
  import '@tanstack/react-query';
39
39
  import { StateMachineManager, createContextFromBindings, interpolateValue, createServerEffectHandlers, EffectExecutor, InMemoryPersistence } from '@almadar/runtime';
40
+ import { OrbitalServerRuntime } from '@almadar/runtime/OrbitalServerRuntime';
40
41
 
41
42
  var __defProp = Object.defineProperty;
42
43
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -8184,13 +8185,13 @@ var init_MapView = __esm({
8184
8185
  shadowSize: [41, 41]
8185
8186
  });
8186
8187
  L.Marker.prototype.options.icon = defaultIcon;
8187
- const { useEffect: useEffect68, useRef: useRef65, useCallback: useCallback110, useState: useState102 } = React115__default;
8188
+ const { useEffect: useEffect69, useRef: useRef65, useCallback: useCallback110, useState: useState103 } = React115__default;
8188
8189
  const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
8189
8190
  const { useEventBus: useEventBus2 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
8190
8191
  function MapUpdater({ centerLat, centerLng, zoom }) {
8191
8192
  const map = useMap();
8192
8193
  const prevRef = useRef65({ centerLat, centerLng, zoom });
8193
- useEffect68(() => {
8194
+ useEffect69(() => {
8194
8195
  const prev = prevRef.current;
8195
8196
  if (prev.centerLat !== centerLat || prev.centerLng !== centerLng || prev.zoom !== zoom) {
8196
8197
  map.setView([centerLat, centerLng], zoom);
@@ -8201,7 +8202,7 @@ var init_MapView = __esm({
8201
8202
  }
8202
8203
  function MapClickHandler({ onMapClick }) {
8203
8204
  const map = useMap();
8204
- useEffect68(() => {
8205
+ useEffect69(() => {
8205
8206
  if (!onMapClick) return;
8206
8207
  const handler = (e) => {
8207
8208
  onMapClick(e.latlng.lat, e.latlng.lng);
@@ -8228,7 +8229,7 @@ var init_MapView = __esm({
8228
8229
  showAttribution = true
8229
8230
  }) {
8230
8231
  const eventBus = useEventBus2();
8231
- const [clickedPosition, setClickedPosition] = useState102(null);
8232
+ const [clickedPosition, setClickedPosition] = useState103(null);
8232
8233
  const handleMapClick = useCallback110((lat, lng) => {
8233
8234
  if (showClickedPin) {
8234
8235
  setClickedPosition({ lat, lng });
@@ -38935,6 +38936,38 @@ init_EntitySchemaContext();
38935
38936
  init_useEventBus();
38936
38937
  init_logger();
38937
38938
  var xOrbitalLog2 = createLogger("almadar:runtime:cross-orbital");
38939
+ function createHttpTransport(serverUrl) {
38940
+ return {
38941
+ register: async (schema) => {
38942
+ try {
38943
+ const res = await fetch(`${serverUrl}/register`, {
38944
+ method: "POST",
38945
+ headers: { "Content-Type": "application/json" },
38946
+ body: JSON.stringify({ schema })
38947
+ });
38948
+ const result = await res.json();
38949
+ return !!result.success;
38950
+ } catch (err) {
38951
+ console.error("[ServerBridge] Registration failed:", err);
38952
+ return false;
38953
+ }
38954
+ },
38955
+ unregister: async () => {
38956
+ try {
38957
+ await fetch(`${serverUrl}/unregister`, { method: "DELETE" });
38958
+ } catch {
38959
+ }
38960
+ },
38961
+ sendEvent: async (orbitalName, event, payload) => {
38962
+ const res = await fetch(`${serverUrl}/${orbitalName}/events`, {
38963
+ method: "POST",
38964
+ headers: { "Content-Type": "application/json" },
38965
+ body: JSON.stringify({ event, payload })
38966
+ });
38967
+ return res.json();
38968
+ }
38969
+ };
38970
+ }
38938
38971
  var ServerBridgeContext = createContext(null);
38939
38972
  function useServerBridge() {
38940
38973
  const ctx = useContext(ServerBridgeContext);
@@ -38947,40 +38980,34 @@ function useServerBridge() {
38947
38980
  function ServerBridgeProvider({
38948
38981
  schema,
38949
38982
  serverUrl,
38983
+ transport: customTransport,
38950
38984
  children
38951
38985
  }) {
38986
+ if (!serverUrl && !customTransport) {
38987
+ throw new Error("ServerBridgeProvider requires either serverUrl or transport");
38988
+ }
38989
+ if (serverUrl && customTransport) {
38990
+ throw new Error("ServerBridgeProvider accepts serverUrl OR transport, not both");
38991
+ }
38952
38992
  const eventBus = useEventBus();
38953
38993
  const [connected, setConnected] = useState(false);
38954
- const registerSchema = useCallback(async () => {
38955
- try {
38956
- const res = await fetch(`${serverUrl}/register`, {
38957
- method: "POST",
38958
- headers: { "Content-Type": "application/json" },
38959
- body: JSON.stringify({ schema })
38960
- });
38961
- const result = await res.json();
38962
- return !!result.success;
38963
- } catch (err) {
38964
- console.error("[ServerBridge] Registration failed:", err);
38965
- return false;
38966
- }
38967
- }, [schema, serverUrl]);
38968
- const unregisterSchema = useCallback(async () => {
38969
- try {
38970
- await fetch(`${serverUrl}/unregister`, { method: "DELETE" });
38971
- } catch {
38972
- }
38973
- }, [serverUrl]);
38994
+ const transport = useMemo(
38995
+ () => customTransport ?? createHttpTransport(serverUrl),
38996
+ [serverUrl, customTransport]
38997
+ );
38998
+ const registerSchema = useCallback(
38999
+ async () => transport.register(schema),
39000
+ [schema, transport]
39001
+ );
39002
+ const unregisterSchema = useCallback(
39003
+ async () => transport.unregister(),
39004
+ [transport]
39005
+ );
38974
39006
  const sendEvent = useCallback(async (orbitalName, event, payload) => {
38975
39007
  const emptyMeta = { success: false, clientEffects: 0, dataEntities: {}, emittedEvents: [] };
38976
39008
  if (!connected) return { effects: [], meta: emptyMeta };
38977
39009
  try {
38978
- const res = await fetch(`${serverUrl}/${orbitalName}/events`, {
38979
- method: "POST",
38980
- headers: { "Content-Type": "application/json" },
38981
- body: JSON.stringify({ event, payload })
38982
- });
38983
- const result = await res.json();
39010
+ const result = await transport.sendEvent(orbitalName, event, payload);
38984
39011
  const effects = [];
38985
39012
  const responseData = result.data || {};
38986
39013
  const dataEntities = {};
@@ -39038,7 +39065,7 @@ function ServerBridgeProvider({
39038
39065
  console.error("[ServerBridge] Event send failed:", err);
39039
39066
  return { effects: [], meta: { ...emptyMeta, error: err instanceof Error ? err.message : String(err) } };
39040
39067
  }
39041
- }, [connected, serverUrl, eventBus]);
39068
+ }, [connected, transport, eventBus]);
39042
39069
  useEffect(() => {
39043
39070
  if (!schema) return;
39044
39071
  let cancelled = false;
@@ -39314,7 +39341,7 @@ function TraitInitializer({ traits: traits2, orbitalNames, onNavigate, onLocalFa
39314
39341
  }, [bridge.connected, orbitalNames, bridge.sendEvent, uiSlots, onNavigate]);
39315
39342
  return null;
39316
39343
  }
39317
- function SchemaRunner({ schema, serverUrl, mockData, pageName, onNavigate, onLocalFallback, persistence }) {
39344
+ function SchemaRunner({ schema, serverUrl, transport, mockData, pageName, onNavigate, onLocalFallback, persistence }) {
39318
39345
  const { traits: traits2, allEntities, ir } = useResolvedSchema(schema, pageName);
39319
39346
  const allPageTraits = useMemo(() => {
39320
39347
  if (pageName && traits2.length > 0) return traits2;
@@ -39428,7 +39455,7 @@ function SchemaRunner({ schema, serverUrl, mockData, pageName, onNavigate, onLoc
39428
39455
  TraitInitializer,
39429
39456
  {
39430
39457
  traits: allPageTraits,
39431
- orbitalNames: serverUrl ? pageOrbitalNames : void 0,
39458
+ orbitalNames: serverUrl || transport ? pageOrbitalNames : void 0,
39432
39459
  traitConfigsByName,
39433
39460
  orbitalsByTrait,
39434
39461
  onNavigate,
@@ -39441,8 +39468,8 @@ function SchemaRunner({ schema, serverUrl, mockData, pageName, onNavigate, onLoc
39441
39468
  ]
39442
39469
  }
39443
39470
  ) }) });
39444
- if (serverUrl) {
39445
- return /* @__PURE__ */ jsx(ServerBridgeProvider, { schema, serverUrl, children: inner });
39471
+ if (serverUrl || transport) {
39472
+ return /* @__PURE__ */ jsx(ServerBridgeProvider, { schema, serverUrl, transport, children: inner });
39446
39473
  }
39447
39474
  return inner;
39448
39475
  }
@@ -39453,8 +39480,12 @@ function OrbPreview({
39453
39480
  height = "400px",
39454
39481
  className,
39455
39482
  serverUrl,
39483
+ transport,
39456
39484
  initialPagePath
39457
39485
  }) {
39486
+ if (serverUrl && transport) {
39487
+ throw new Error("OrbPreview accepts serverUrl OR transport, not both");
39488
+ }
39458
39489
  const [localFallback, setLocalFallback] = useState(false);
39459
39490
  const eventBus = useEventBus();
39460
39491
  const handleLocalFallback = useCallback(() => {
@@ -39476,21 +39507,21 @@ function OrbPreview({
39476
39507
  } else {
39477
39508
  parsed = schema;
39478
39509
  }
39479
- if (autoMock && !serverUrl) {
39510
+ if (autoMock && !serverUrl && !transport) {
39480
39511
  const prepared = prepareSchemaForPreview(parsed);
39481
39512
  return { ok: true, schema: prepared.schema, mockData: prepared.mockData };
39482
39513
  }
39483
39514
  return { ok: true, schema: parsed, mockData: mockData ?? {} };
39484
- }, [schema, autoMock, serverUrl, mockData]);
39515
+ }, [schema, autoMock, serverUrl, transport, mockData]);
39485
39516
  const parsedSchema = parseResult.ok ? parseResult.schema : null;
39486
39517
  const effectiveMockData = parseResult.ok ? parseResult.mockData : {};
39487
39518
  const persistence = useMemo(() => {
39488
- if (!parsedSchema || serverUrl) return void 0;
39519
+ if (!parsedSchema || serverUrl || transport) return void 0;
39489
39520
  if (!autoMock) return void 0;
39490
39521
  const adapter = new InMemoryPersistence();
39491
39522
  adapter.seed(effectiveMockData);
39492
39523
  return adapter;
39493
- }, [parsedSchema, serverUrl, autoMock, effectiveMockData]);
39524
+ }, [parsedSchema, serverUrl, transport, autoMock, effectiveMockData]);
39494
39525
  const pages = useMemo(() => {
39495
39526
  if (!parsedSchema) return [];
39496
39527
  try {
@@ -39552,6 +39583,7 @@ function OrbPreview({
39552
39583
  {
39553
39584
  schema: parsedSchema,
39554
39585
  serverUrl,
39586
+ transport,
39555
39587
  mockData: effectiveMockData,
39556
39588
  pageName: currentPage,
39557
39589
  onNavigate: handleNavigate,
@@ -39564,5 +39596,47 @@ function OrbPreview({
39564
39596
  );
39565
39597
  }
39566
39598
  OrbPreview.displayName = "OrbPreview";
39599
+ function BrowserPlayground({
39600
+ schema,
39601
+ mode = "mock",
39602
+ initialPagePath,
39603
+ height,
39604
+ className
39605
+ }) {
39606
+ const [runtime] = useState(
39607
+ () => new OrbitalServerRuntime({ mode, debug: false })
39608
+ );
39609
+ useEffect(() => {
39610
+ void runtime.register(schema);
39611
+ return () => {
39612
+ runtime.unregisterAll();
39613
+ };
39614
+ }, [runtime, schema]);
39615
+ const transport = useMemo(() => ({
39616
+ register: async (s) => {
39617
+ await runtime.register(s);
39618
+ return true;
39619
+ },
39620
+ unregister: async () => {
39621
+ runtime.unregisterAll();
39622
+ },
39623
+ sendEvent: async (orbitalName, event, payload) => {
39624
+ return runtime.processOrbitalEvent(orbitalName, {
39625
+ event,
39626
+ payload
39627
+ });
39628
+ }
39629
+ }), [runtime]);
39630
+ return /* @__PURE__ */ jsx(
39631
+ OrbPreview,
39632
+ {
39633
+ schema,
39634
+ transport,
39635
+ initialPagePath,
39636
+ height,
39637
+ className
39638
+ }
39639
+ );
39640
+ }
39567
39641
 
39568
- export { EntitySchemaProvider, OrbPreview, ServerBridgeProvider, SlotsProvider, TraitContext, TraitProvider, adjustSchemaForMockData, buildMockData, clearSchemaCache, createClientEffectHandlers, prepareSchemaForPreview, useEntityDefinition, useEntitySchema, useEntitySchemaOptional, useResolvedSchema, useServerBridge, useSlotContent, useSlots, useSlotsActions, useTrait, useTraitContext, useTraitStateMachine };
39642
+ export { BrowserPlayground, EntitySchemaProvider, OrbPreview, ServerBridgeProvider, SlotsProvider, TraitContext, TraitProvider, adjustSchemaForMockData, buildMockData, clearSchemaCache, createClientEffectHandlers, prepareSchemaForPreview, useEntityDefinition, useEntitySchema, useEntitySchemaOptional, useResolvedSchema, useServerBridge, useSlotContent, useSlots, useSlotsActions, useTrait, useTraitContext, useTraitStateMachine };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@almadar/ui",
3
- "version": "4.10.7",
3
+ "version": "4.11.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.5.0",
124
+ "@almadar/runtime": "^5.7.0",
125
125
  "@almadar/std": ">=6.4.1",
126
126
  "@almadar/syntax": ">=1.3.1",
127
127
  "@xyflow/react": "12.10.1",