@almadar/ui 6.53.1 → 6.55.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/{AwaitingSkeletonContext-Bh399p1x.d.ts → AwaitingSkeletonContext-DPgW__WV.d.ts} +3 -1
- package/dist/{Canvas3DHost-B-y2TNij.d.ts → Canvas3DHost-DfAhg6EH.d.ts} +2 -0
- package/dist/Typography-7PDT62PG.js +5 -0
- package/dist/{UISlotRenderer-P7A4SZSK.js → UISlotRenderer-QTHFT6Z4.js} +8 -8
- package/dist/avl/index.cjs +3031 -1790
- package/dist/avl/index.js +57 -745
- package/dist/{avl-3d-context-MAt_NuU9.d.ts → avl-3d-context-BpBKZIbc.d.ts} +1 -0
- package/dist/{chunk-ERXIHZW3.js → chunk-D2E44ODB.js} +29 -15
- package/dist/{chunk-UOTYAPV5.js → chunk-F4ZTPKZL.js} +3 -3
- package/dist/{chunk-53VTY5CC.js → chunk-FQM37C56.js} +352 -162
- package/dist/{chunk-HB4C27KU.js → chunk-HCSJHRC4.js} +1 -1
- package/dist/{chunk-7KSLPY56.js → chunk-HRCR53OW.js} +11 -1
- package/dist/{chunk-O7OLVVBR.js → chunk-Q47ZN2DW.js} +24 -22
- package/dist/{chunk-DQTV6QVS.js → chunk-QGH4NAQO.js} +53 -2
- package/dist/{chunk-QVXLKFUQ.js → chunk-RNY5LJXJ.js} +1 -1
- package/dist/{chunk-FUQASYEW.js → chunk-SGJHVPHC.js} +2 -2
- package/dist/{chunk-6O37FCX4.js → chunk-V3FGTQUE.js} +37 -2
- package/dist/{chunk-HUG25TT3.js → chunk-XZKGRSIO.js} +2745 -1644
- package/dist/{chunk-7LM6I3NA.js → chunk-Y53Q55H5.js} +522 -24
- package/dist/components/index.cjs +4614 -2858
- package/dist/components/index.d.ts +122 -53
- package/dist/components/index.js +16 -17
- package/dist/context/index.cjs +38 -1
- package/dist/context/index.d.ts +1 -1
- package/dist/context/index.js +3 -1
- package/dist/design-classes/index.cjs +29 -15
- package/dist/design-classes/index.d.cts +1 -0
- package/dist/design-classes/index.d.ts +1 -0
- package/dist/design-classes/index.js +29 -15
- package/dist/hooks/index.cjs +16 -1
- package/dist/hooks/index.d.ts +10 -1
- package/dist/hooks/index.js +3 -4
- package/dist/lib/drawable/three/index.cjs +444 -82
- package/dist/lib/drawable/three/index.d.ts +4 -4
- package/dist/lib/drawable/three/index.js +28 -24
- package/dist/lib/index.cjs +53 -3
- package/dist/lib/index.d.ts +1 -1
- package/dist/lib/index.js +4 -4
- package/dist/locales/index.cjs +33 -3
- package/dist/locales/index.js +23 -3
- package/dist/providers/index.cjs +4987 -3183
- package/dist/providers/index.d.ts +2 -2
- package/dist/providers/index.js +14 -11
- package/dist/runtime/index.cjs +8973 -7000
- package/dist/runtime/index.d.ts +28 -6
- package/dist/runtime/index.js +16 -13
- package/dist/ssr/index.cjs +26 -9
- package/dist/ssr/index.js +26 -9
- package/dist/{themeTokens-Ccu7EmGY.d.ts → themeTokens-D6MFwKrC.d.ts} +6 -2
- package/locales/ar.json +11 -1
- package/locales/en.json +11 -1
- package/locales/sl.json +11 -1
- package/package.json +8 -7
- package/scripts/audit-tailwind-safelist.ts +21 -1
- package/scripts/theme-contrast-audit.mjs +20 -1
- package/tailwind-preset.cjs +5 -6
- package/themes/_base.css +61 -0
- package/themes/_contract.md +37 -0
- package/themes/_fonts.css +6 -4
- package/themes/_presets.css +2 -0
- package/themes/almadar-heritage.css +455 -0
- package/themes/almadar-website.css +82 -0
- package/themes/almadar.css +82 -0
- package/themes/aqua.css +82 -0
- package/themes/arabesque.css +82 -0
- package/themes/art-deco.css +82 -0
- package/themes/art-nouveau.css +82 -0
- package/themes/atelier.css +82 -0
- package/themes/bauhaus.css +82 -0
- package/themes/bloomberg-dense.css +83 -1
- package/themes/blueprint.css +84 -0
- package/themes/clay.css +82 -0
- package/themes/comic.css +82 -0
- package/themes/constructivist.css +82 -0
- package/themes/corporate.css +82 -0
- package/themes/cyberpunk.css +82 -0
- package/themes/frutiger-aero.css +83 -0
- package/themes/game-adventure.css +15 -0
- package/themes/game-rpg.css +16 -0
- package/themes/game-sci-fi.css +15 -0
- package/themes/game-ui-pack.css +15 -0
- package/themes/gazette.css +82 -0
- package/themes/glass.css +82 -0
- package/themes/gothic.css +82 -0
- package/themes/ink-wash.css +82 -0
- package/themes/kawaii.css +82 -0
- package/themes/kiosk.css +82 -0
- package/themes/linear-clean.css +82 -0
- package/themes/luxury.css +82 -0
- package/themes/mac-classic.css +90 -8
- package/themes/material.css +82 -0
- package/themes/memphis.css +82 -0
- package/themes/mid-century.css +82 -0
- package/themes/minimalist.css +82 -0
- package/themes/mudcloth.css +82 -0
- package/themes/neon.css +83 -0
- package/themes/neumorphic.css +82 -0
- package/themes/newsprint.css +82 -0
- package/themes/notion-editorial.css +82 -0
- package/themes/orb.css +455 -0
- package/themes/pixel.css +82 -0
- package/themes/prism.css +82 -0
- package/themes/retro.css +83 -0
- package/themes/risograph.css +82 -0
- package/themes/scandi.css +82 -0
- package/themes/sketch.css +82 -0
- package/themes/solarpunk.css +82 -0
- package/themes/steampunk.css +82 -0
- package/themes/swiss.css +82 -0
- package/themes/terminal.css +84 -1
- package/themes/trait-wars.css +82 -0
- package/themes/ukiyo-e.css +82 -0
- package/themes/vaporwave.css +82 -0
- package/themes/victorian.css +82 -0
- package/themes/wabi-sabi.css +82 -0
- package/themes/win95.css +84 -0
- package/themes/wireframe.css +82 -0
- package/themes/zine.css +82 -0
- package/dist/Typography-7QEWUTW3.js +0 -5
- package/dist/chunk-E37BYSXY.js +0 -51
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
import { runTickFrame } from './chunk-
|
|
1
|
+
import { useTranslate, useRenderI18n, runTickFrame } from './chunk-QGH4NAQO.js';
|
|
2
2
|
import { ALL_SLOTS } from './chunk-VHTJRS2N.js';
|
|
3
|
-
import { UISlotRenderer } from './chunk-
|
|
4
|
-
import { Box } from './chunk-
|
|
5
|
-
import { Typography } from './chunk-
|
|
3
|
+
import { LoadingState, ErrorState, UISlotRenderer } from './chunk-XZKGRSIO.js';
|
|
4
|
+
import { Box } from './chunk-Y53Q55H5.js';
|
|
5
|
+
import { Typography } from './chunk-HCSJHRC4.js';
|
|
6
6
|
import { beginPending, endPending } from './chunk-JRW33U35.js';
|
|
7
7
|
import { useEventBus } from './chunk-6EV3OEBQ.js';
|
|
8
|
-
import { isNotificationSlot } from './chunk-PEST66PN.js';
|
|
9
8
|
import { registerTrait, unregisterTrait, perfTimeAsync } from './chunk-KQXXO42S.js';
|
|
10
|
-
import { bindTraitStateGetter, registerTraitSnapshot, recordTransition, recordingTransport, recordServerResponse } from './chunk-
|
|
9
|
+
import { bindTraitStateGetter, registerTraitSnapshot, recordTransition, recordingTransport, recordServerResponse } from './chunk-Q47ZN2DW.js';
|
|
10
|
+
import { isNotificationSlot } from './chunk-PEST66PN.js';
|
|
11
11
|
import React, { useState, useMemo, useEffect, useRef, useCallback, useSyncExternalStore } from 'react';
|
|
12
|
-
import { schemaToIR, getPage, clearSchemaCache as clearSchemaCache$1, applyListenPayloadMapping, buildResolvedTraitConfigs, collectCallsiteCaptureChildren, walkSExpr, isRenderBindingMarker, containsEntityBinding, isSExpr, isEventPayloadValue, RENDER_BINDING_MARKER } from '@almadar/core';
|
|
12
|
+
import { schemaToIR, getPage, clearSchemaCache as clearSchemaCache$1, traitsEmbeddedByEvent, traitReferencesCallsitePayload, configReferencesCallsitePayload, TRAIT_MOUNT_ERROR_TESTID, traitsEmbeddedByEffects, applyListenPayloadMapping, buildResolvedTraitConfigs, collectCallsiteCaptureChildren, orbitalInlineEntities, storesRowsInBrowser, walkSExpr, isRenderBindingMarker, containsEntityBinding, isSExpr, isEventPayloadValue, RENDER_BINDING_MARKER } from '@almadar/core';
|
|
13
13
|
import { createLogger } from '@almadar/logger';
|
|
14
|
-
import { collectListenerTargets, LIFECYCLE_EVENTS, InMemoryPersistence, createInProcessTransport, buildTraitIndex, createMemoryCircuitStore,
|
|
15
|
-
import { useUser, useArbitraryClassStyles, getAllPages, matchPathAmong, CurrentPagePathProvider, NavStackProvider, OrbitalProvider, useNavStack, VerificationProvider, EntitySchemaProvider, OrbitalThemeProvider,
|
|
14
|
+
import { collectListenerTargets, LIFECYCLE_EVENTS, TraitMountError, InMemoryPersistence, loadLazyPage, createInProcessTransport, buildTraitIndex, createMemoryCircuitStore, createLocalStoreTransport, createResidenceTransport, createClientKernel, createTickScheduler, isValidCronExpression, parseDurationString, UNMOUNT_EVENT, createClientEffectHandlers, EffectExecutor, isSExpression, collectDeclaredConfigDefaults, createContextFromBindings, openBrowserStore, browserStoreName, normalizeCallSiteConfigToValues } from '@almadar/runtime';
|
|
15
|
+
import { useUser, useHasServerBridge, useArbitraryClassStyles, getAllPages, matchPathAmong, CurrentPagePathProvider, NavStackProvider, OrbitalProvider, ServerBridgeProvider, useNavStack, VerificationProvider, EntitySchemaProvider, OrbitalThemeProvider, useServerBridge, EntityBindingContext, AwaitingSkeletonContext } from '@almadar/ui/providers';
|
|
16
16
|
import { evaluateListenPayloadExpr, evaluate, createMinimalContext, evaluateGuard, executeEffects } from '@almadar/evaluator';
|
|
17
17
|
import { getPatternDefinition } from '@almadar/core/patterns';
|
|
18
18
|
import { isKnownStdOperator } from '@almadar/std/registry';
|
|
@@ -20,9 +20,10 @@ import { prepareSchemaForPreview, collectTraitRefsFromResolvedTrait, buildOrbita
|
|
|
20
20
|
export { adjustSchemaForMockData, buildMockData, collectEmbeddedTraits, prepareSchemaForPreview } from '@almadar/runtime/ui';
|
|
21
21
|
import { useInRouterContext, useHref } from 'react-router-dom';
|
|
22
22
|
import { UISlotProvider, useUISlots } from '@almadar/ui/context';
|
|
23
|
-
import { useTranslate } from '@almadar/ui/hooks';
|
|
23
|
+
import { useTranslate as useTranslate$1, createTranslate, I18nProvider } from '@almadar/ui/hooks';
|
|
24
24
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
25
25
|
import { OrbitalServerRuntime } from '@almadar/runtime/OrbitalServerRuntime';
|
|
26
|
+
import { localeDirection } from '@almadar/core/i18n';
|
|
26
27
|
|
|
27
28
|
var resolvedSchemaLog = createLogger("almadar:ui:resolved-schema");
|
|
28
29
|
function useResolvedSchema(schema, pageName) {
|
|
@@ -172,9 +173,9 @@ function getTabClientId() {
|
|
|
172
173
|
return tabClientId;
|
|
173
174
|
}
|
|
174
175
|
var log = createLogger("almadar:ui:circuit-kernel");
|
|
175
|
-
function postUnmounts(transport, traits) {
|
|
176
|
+
function postUnmounts(transport, traits, locale) {
|
|
176
177
|
for (const [traitName, orbitalName] of traits) {
|
|
177
|
-
transport.send(orbitalName, { event: UNMOUNT_EVENT, targetTrait: traitName, clientId: getTabClientId() }).catch((err) => log.warn("unmount-post-failed", { trait: traitName, orbital: orbitalName, error: String(err) }));
|
|
178
|
+
transport.send(orbitalName, { event: UNMOUNT_EVENT, targetTrait: traitName, clientId: getTabClientId(), locale }).catch((err) => log.warn("unmount-post-failed", { trait: traitName, orbital: orbitalName, error: String(err) }));
|
|
178
179
|
}
|
|
179
180
|
}
|
|
180
181
|
function restrictTraitIndex(full, activeNames) {
|
|
@@ -185,16 +186,22 @@ function restrictTraitIndex(full, activeNames) {
|
|
|
185
186
|
return { byName, allEntities: full.allEntities, orbitals: full.orbitals };
|
|
186
187
|
}
|
|
187
188
|
function useCircuitKernel(traitBindings, options) {
|
|
189
|
+
const hostRunsProgram = options.transport?.hostsBrowserStore === true;
|
|
188
190
|
const fullTraitIndex = useMemo(
|
|
189
|
-
() => buildTraitIndex(options.orbitals, options.traitConfigsByName),
|
|
190
|
-
[options.orbitals, options.traitConfigsByName]
|
|
191
|
+
() => buildTraitIndex(options.orbitals, options.traitConfigsByName, { hostRunsProgram }),
|
|
192
|
+
[options.orbitals, options.traitConfigsByName, hostRunsProgram]
|
|
191
193
|
);
|
|
194
|
+
const appTraitNames = useMemo(() => new Set(fullTraitIndex.byName.keys()), [fullTraitIndex]);
|
|
192
195
|
const activeTraitKey = traitBindings.map((b) => b.trait.name).filter((n) => !!n).sort().join("\0");
|
|
193
196
|
const traitIndex = useMemo(
|
|
194
197
|
() => restrictTraitIndex(fullTraitIndex, new Set(activeTraitKey === "" ? [] : activeTraitKey.split("\0"))),
|
|
195
198
|
[activeTraitKey, fullTraitIndex]
|
|
196
199
|
);
|
|
197
200
|
const mountedRef = useRef(/* @__PURE__ */ new Map());
|
|
201
|
+
const { locale } = useTranslate();
|
|
202
|
+
const i18n = useRenderI18n();
|
|
203
|
+
const localeRef = useRef(locale);
|
|
204
|
+
localeRef.current = locale;
|
|
198
205
|
const transport = options.transport;
|
|
199
206
|
const topologyPending = options.awaitTopology === true;
|
|
200
207
|
useEffect(() => {
|
|
@@ -203,12 +210,12 @@ function useCircuitKernel(traitBindings, options) {
|
|
|
203
210
|
const dropped = [...mounted].filter(([name]) => !traitIndex.byName.has(name));
|
|
204
211
|
mounted.clear();
|
|
205
212
|
for (const [name, entry] of traitIndex.byName) mounted.set(name, entry.orbitalName);
|
|
206
|
-
postUnmounts(transport, dropped);
|
|
213
|
+
postUnmounts(transport, dropped, localeRef.current);
|
|
207
214
|
}, [traitIndex, transport, topologyPending]);
|
|
208
215
|
useEffect(() => {
|
|
209
216
|
if (transport === void 0) return;
|
|
210
217
|
const mounted = mountedRef.current;
|
|
211
|
-
return () => postUnmounts(transport, [...mounted]);
|
|
218
|
+
return () => postUnmounts(transport, [...mounted], localeRef.current);
|
|
212
219
|
}, [transport]);
|
|
213
220
|
const store = useMemo(() => {
|
|
214
221
|
const traitDefs = Array.from(traitIndex.byName.values(), (entry) => entry.traitDef);
|
|
@@ -219,42 +226,43 @@ function useCircuitKernel(traitBindings, options) {
|
|
|
219
226
|
};
|
|
220
227
|
return createMemoryCircuitStore(traitDefs, config, options.observer);
|
|
221
228
|
}, [traitIndex, options.guardMode, options.strictBindings, options.contextExtensions, options.observer]);
|
|
222
|
-
const
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
);
|
|
229
|
+
const localTransportOptions = {
|
|
230
|
+
traitIndex,
|
|
231
|
+
store,
|
|
232
|
+
...options.callService !== void 0 ? { callService: options.callService } : {},
|
|
233
|
+
...options.user !== void 0 ? { user: options.user } : {},
|
|
234
|
+
...options.guardMode !== void 0 ? { guardMode: options.guardMode } : {},
|
|
235
|
+
...options.strictBindings !== void 0 ? { strictBindings: options.strictBindings } : {},
|
|
236
|
+
...options.contextExtensions !== void 0 ? { contextExtensions: options.contextExtensions } : {},
|
|
237
|
+
...options.debug !== void 0 ? { debug: options.debug } : {},
|
|
238
|
+
...options.logContext !== void 0 ? { logContext: options.logContext } : {}
|
|
239
|
+
};
|
|
240
|
+
const offlineTransport = useMemo(
|
|
241
|
+
() => options.transport !== void 0 || options.persistence === void 0 ? void 0 : createLocalStoreTransport({ ...localTransportOptions, persistence: options.persistence }),
|
|
242
|
+
[
|
|
243
|
+
options.transport,
|
|
244
|
+
options.persistence,
|
|
245
|
+
traitIndex,
|
|
246
|
+
store,
|
|
247
|
+
options.callService,
|
|
248
|
+
options.user,
|
|
249
|
+
options.guardMode,
|
|
250
|
+
options.strictBindings,
|
|
251
|
+
options.contextExtensions,
|
|
252
|
+
options.debug,
|
|
253
|
+
options.logContext
|
|
254
|
+
]
|
|
255
|
+
);
|
|
256
|
+
const routedTransport = useMemo(() => {
|
|
257
|
+
if (options.browserStore === void 0) return void 0;
|
|
258
|
+
const local = createLocalStoreTransport({ ...localTransportOptions, traitIndex: fullTraitIndex, persistence: options.browserStore, clientRelays: true });
|
|
259
|
+
const remote = options.transport ?? offlineTransport;
|
|
260
|
+
return createResidenceTransport({ local, ...remote !== void 0 ? { remote } : {}, traitIndex: fullTraitIndex });
|
|
254
261
|
}, [
|
|
262
|
+
options.browserStore,
|
|
255
263
|
options.transport,
|
|
256
|
-
|
|
257
|
-
|
|
264
|
+
offlineTransport,
|
|
265
|
+
fullTraitIndex,
|
|
258
266
|
store,
|
|
259
267
|
options.callService,
|
|
260
268
|
options.user,
|
|
@@ -264,7 +272,7 @@ function useCircuitKernel(traitBindings, options) {
|
|
|
264
272
|
options.debug,
|
|
265
273
|
options.logContext
|
|
266
274
|
]);
|
|
267
|
-
const baseTransport = options.transport ?? offlineTransport;
|
|
275
|
+
const baseTransport = routedTransport ?? options.transport ?? offlineTransport;
|
|
268
276
|
const effectiveTransport = useMemo(
|
|
269
277
|
() => baseTransport === void 0 ? void 0 : recordingTransport(baseTransport),
|
|
270
278
|
[baseTransport]
|
|
@@ -289,6 +297,8 @@ function useCircuitKernel(traitBindings, options) {
|
|
|
289
297
|
store,
|
|
290
298
|
...options.persistence !== void 0 ? { persistence: options.persistence } : {},
|
|
291
299
|
...options.user !== void 0 ? { user: options.user } : {},
|
|
300
|
+
locale,
|
|
301
|
+
...i18n !== void 0 ? { messages: { [i18n.locale]: i18n.messages } } : {},
|
|
292
302
|
...options.guardMode !== void 0 ? { guardMode: options.guardMode } : {},
|
|
293
303
|
...options.strictBindings !== void 0 ? { strictBindings: options.strictBindings } : {},
|
|
294
304
|
...options.contextExtensions !== void 0 ? { contextExtensions: options.contextExtensions } : {},
|
|
@@ -304,6 +314,8 @@ function useCircuitKernel(traitBindings, options) {
|
|
|
304
314
|
store,
|
|
305
315
|
options.persistence,
|
|
306
316
|
options.user,
|
|
317
|
+
locale,
|
|
318
|
+
i18n,
|
|
307
319
|
options.guardMode,
|
|
308
320
|
options.strictBindings,
|
|
309
321
|
options.contextExtensions,
|
|
@@ -312,21 +324,29 @@ function useCircuitKernel(traitBindings, options) {
|
|
|
312
324
|
topology,
|
|
313
325
|
effectiveTransport
|
|
314
326
|
]);
|
|
315
|
-
const kernel = useMemo(() =>
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
327
|
+
const kernel = useMemo(() => {
|
|
328
|
+
const stamp = (request) => ({
|
|
329
|
+
...request,
|
|
330
|
+
clientId: request.clientId ?? getTabClientId(),
|
|
331
|
+
locale: request.locale ?? locale
|
|
332
|
+
});
|
|
333
|
+
return {
|
|
334
|
+
store: rawKernel.store,
|
|
335
|
+
dispatch: (request, hooks) => rawKernel.dispatch(stamp(request), hooks),
|
|
336
|
+
dispatchMount: (seeds, hooks, base = {}) => rawKernel.dispatchMount(seeds, hooks, stamp(base)),
|
|
337
|
+
dispatchProgress: (request) => rawKernel.dispatchProgress(stamp(request)),
|
|
338
|
+
foldHostDispatch: (request, response) => rawKernel.foldHostDispatch(request, response)
|
|
339
|
+
};
|
|
340
|
+
}, [rawKernel, locale]);
|
|
341
|
+
return { kernel, store, traitIndex, appTraitNames, transport: effectiveTransport };
|
|
322
342
|
}
|
|
323
343
|
var log2 = createLogger("almadar:ui:circuit:bus-ingress");
|
|
324
|
-
function useBusIngress(traitBindings, traitIndex, settle, eventBus) {
|
|
344
|
+
function useBusIngress(traitBindings, traitIndex, settle, eventBus, appTraitNames) {
|
|
325
345
|
useEffect(() => {
|
|
326
346
|
const unsubscribes = [];
|
|
327
347
|
const subscribedQualified = /* @__PURE__ */ new Set();
|
|
328
348
|
const subscribedBare = /* @__PURE__ */ new Set();
|
|
329
|
-
const deliveredHere = (source) => source?.dispatched === true && source.trait !== void 0 && traitIndex.byName.has(source.trait);
|
|
349
|
+
const deliveredHere = (source) => source?.dispatched === true && source.trait !== void 0 && (traitIndex.byName.has(source.trait) || appTraitNames.has(source.trait));
|
|
330
350
|
const claims = /* @__PURE__ */ new WeakMap();
|
|
331
351
|
const claim = (source, traitName, eventKey) => {
|
|
332
352
|
if (source === void 0) return true;
|
|
@@ -423,7 +443,7 @@ function useBusIngress(traitBindings, traitIndex, settle, eventBus) {
|
|
|
423
443
|
return () => {
|
|
424
444
|
for (const unsub of unsubscribes) unsub();
|
|
425
445
|
};
|
|
426
|
-
}, [traitBindings, traitIndex, settle, eventBus]);
|
|
446
|
+
}, [traitBindings, traitIndex, settle, eventBus, appTraitNames]);
|
|
427
447
|
}
|
|
428
448
|
var lambdaLog = createLogger("almadar:ui:fn-form-lambda");
|
|
429
449
|
function patternPropsSchema(patternType) {
|
|
@@ -498,7 +518,7 @@ function resolveLambdaBindings(body, params, item, index) {
|
|
|
498
518
|
return body;
|
|
499
519
|
}
|
|
500
520
|
var LazySlotContentRenderer = React.lazy(
|
|
501
|
-
() => import('./UISlotRenderer-
|
|
521
|
+
() => import('./UISlotRenderer-QTHFT6Z4.js').then((m) => ({ default: m.SlotContentRenderer }))
|
|
502
522
|
);
|
|
503
523
|
function deferLambdaEntityExprs(value) {
|
|
504
524
|
if (typeof value === "string") {
|
|
@@ -795,11 +815,12 @@ async function runCircuitEffects(params) {
|
|
|
795
815
|
// hooks/circuit/useCallsiteCapture.ts
|
|
796
816
|
var log4 = createLogger("almadar:ui:circuit:callsite-capture");
|
|
797
817
|
function useCallsiteCapture(traitBindings, store, traitIndex, slotFlush, options) {
|
|
798
|
-
return useCallback(async function reRender(traitName, callsitePayload, entityByTrait, visited = /* @__PURE__ */ new Set(), serverComposed = /* @__PURE__ */ new Set(), keepComposed = false) {
|
|
818
|
+
return useCallback(async function reRender(traitName, callsitePayload, entityByTrait, visited = /* @__PURE__ */ new Set(), serverComposed = /* @__PURE__ */ new Set(), keepComposed = false, composedBy) {
|
|
799
819
|
const children = options.callsiteCaptureChildrenByTrait?.get(traitName);
|
|
800
820
|
if (!children || children.size === 0) return;
|
|
801
821
|
const bindingMap = new Map(traitBindings.map((b) => [b.trait.name, b]));
|
|
802
822
|
for (const childName of children) {
|
|
823
|
+
if (composedBy !== void 0 && !composedBy.has(childName)) continue;
|
|
803
824
|
if (visited.has(childName)) continue;
|
|
804
825
|
visited.add(childName);
|
|
805
826
|
const childBinding = bindingMap.get(childName);
|
|
@@ -853,7 +874,7 @@ function useCallsiteCapture(traitBindings, store, traitIndex, slotFlush, options
|
|
|
853
874
|
{ event: lifecycleEvent, state: entry.result.previousState, entity: childBinding.linkedEntity }
|
|
854
875
|
);
|
|
855
876
|
}
|
|
856
|
-
await reRender(childName, composedWith, entityByTrait, visited, serverComposed, keepComposed);
|
|
877
|
+
await reRender(childName, composedWith, entityByTrait, visited, serverComposed, keepComposed, traitsEmbeddedByEffects(indexed.irTrait, entry.result.effects));
|
|
857
878
|
}
|
|
858
879
|
}, [traitBindings, store, traitIndex, slotFlush, options.callsiteCaptureChildrenByTrait, options.eventBus, options.navigate, options.navigateBack, options.user]);
|
|
859
880
|
}
|
|
@@ -1131,6 +1152,7 @@ function useAwaitingSkeletonSource(store, traitIndex, embeddedTraits) {
|
|
|
1131
1152
|
}
|
|
1132
1153
|
|
|
1133
1154
|
// hooks/useTraitStateMachine.ts
|
|
1155
|
+
var MOUNT_ERROR_SOURCE = "$mount";
|
|
1134
1156
|
var stateLog = createLogger("almadar:ui:state-transitions");
|
|
1135
1157
|
function diffDroppedTraitNames(prev, next) {
|
|
1136
1158
|
const dropped = [];
|
|
@@ -1145,15 +1167,17 @@ function normalizeEventKey(eventKey) {
|
|
|
1145
1167
|
function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
1146
1168
|
const eventBus = useEventBus();
|
|
1147
1169
|
const { user: contextViewer } = useUser();
|
|
1170
|
+
const { t } = useTranslate();
|
|
1148
1171
|
const userContext = options.user ?? contextViewer ?? void 0;
|
|
1149
1172
|
const observer = useMemo(() => createCircuitVerificationObserver(), []);
|
|
1150
|
-
const { kernel, store, traitIndex, transport } = useCircuitKernel(traitBindings, {
|
|
1173
|
+
const { kernel, store, traitIndex, appTraitNames, transport } = useCircuitKernel(traitBindings, {
|
|
1151
1174
|
orbitals: options.orbitals,
|
|
1152
1175
|
...options.traitConfigsByName !== void 0 ? { traitConfigsByName: options.traitConfigsByName } : {},
|
|
1153
1176
|
...options.transport !== void 0 ? { transport: options.transport } : {},
|
|
1154
1177
|
...options.carriesCircuitState !== void 0 ? { carriesCircuitState: options.carriesCircuitState } : {},
|
|
1155
1178
|
...options.awaitTopology !== void 0 ? { awaitTopology: options.awaitTopology } : {},
|
|
1156
1179
|
...options.persistence !== void 0 ? { persistence: options.persistence } : {},
|
|
1180
|
+
...options.browserStore !== void 0 ? { browserStore: options.browserStore } : {},
|
|
1157
1181
|
...options.callService !== void 0 ? { callService: options.callService } : {},
|
|
1158
1182
|
...userContext !== void 0 ? { user: userContext } : {},
|
|
1159
1183
|
...options.debug !== void 0 ? { debug: options.debug } : {},
|
|
@@ -1192,11 +1216,11 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
1192
1216
|
name: trait.name,
|
|
1193
1217
|
currentState: state?.currentState ?? trait.states[0]?.name ?? "unknown",
|
|
1194
1218
|
states: trait.states.map((s) => s.name),
|
|
1195
|
-
transitions: trait.transitions.flatMap((
|
|
1196
|
-
const froms = Array.isArray(
|
|
1197
|
-
return froms.map((f) => ({ from: f, to:
|
|
1219
|
+
transitions: trait.transitions.flatMap((t2) => {
|
|
1220
|
+
const froms = Array.isArray(t2.from) ? t2.from : [t2.from];
|
|
1221
|
+
return froms.map((f) => ({ from: f, to: t2.to, event: t2.event, guard: t2.guard ? String(t2.guard) : void 0 }));
|
|
1198
1222
|
}),
|
|
1199
|
-
guards: trait.transitions.filter((
|
|
1223
|
+
guards: trait.transitions.filter((t2) => t2.guard).map((t2) => ({ name: String(t2.guard) })),
|
|
1200
1224
|
transitionCount: 0
|
|
1201
1225
|
};
|
|
1202
1226
|
registerTrait(info);
|
|
@@ -1234,7 +1258,9 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
1234
1258
|
}
|
|
1235
1259
|
const repainted = new Set(repaints.map((e) => e.traitName));
|
|
1236
1260
|
const serverComposed = new Set([...store.callsitePayloads].filter(([child, composed]) => composedBefore.get(child) !== composed).map(([child]) => child));
|
|
1237
|
-
|
|
1261
|
+
const irTrait = traitIndex.byName.get(traitName)?.irTrait;
|
|
1262
|
+
const composedBy = irTrait !== void 0 ? traitsEmbeddedByEvent(irTrait, eventKey) : void 0;
|
|
1263
|
+
await reRenderCallsiteCaptureChildren(traitName, payload ?? {}, entityByTrait, repainted, serverComposed, false, composedBy);
|
|
1238
1264
|
}
|
|
1239
1265
|
options.onEventProcessed?.(eventKey, payload);
|
|
1240
1266
|
}, [traitIndex, store, reRenderCallsiteCaptureChildren, options.onEventProcessed]);
|
|
@@ -1303,11 +1329,20 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
1303
1329
|
useEffect(() => {
|
|
1304
1330
|
if (!transport?.subscribe) return;
|
|
1305
1331
|
return transport.subscribe((emitted, target) => {
|
|
1306
|
-
for (const
|
|
1307
|
-
void (target === "origin" ? progressAndSettle(
|
|
1332
|
+
for (const t2 of collectListenerTargets(traitIndex, emitted.source, emitted.event, emitted.payload)) {
|
|
1333
|
+
void (target === "origin" ? progressAndSettle(t2.listenerTrait, t2.triggers, t2.payload) : dispatchAndSettle(t2.listenerTrait, t2.triggers, t2.payload));
|
|
1308
1334
|
}
|
|
1309
1335
|
}, { clientId: getTabClientId() });
|
|
1310
1336
|
}, [transport, traitIndex, progressAndSettle, dispatchAndSettle]);
|
|
1337
|
+
useEffect(() => {
|
|
1338
|
+
if (!transport?.subscribeHostDispatches) return;
|
|
1339
|
+
return transport.subscribeHostDispatches((_orbitalName, request, response) => {
|
|
1340
|
+
const traitName = request.targetTrait;
|
|
1341
|
+
if (traitName === void 0 || !traitIndex.byName.has(traitName)) return;
|
|
1342
|
+
const composedBefore = new Map(store.callsitePayloads);
|
|
1343
|
+
void kernel.foldHostDispatch(request, response).then((outcome) => settleOutcome(traitName, request.event, request.payload, outcome, composedBefore));
|
|
1344
|
+
});
|
|
1345
|
+
}, [transport, traitIndex, kernel, store, settleOutcome]);
|
|
1311
1346
|
const mountAndSettle = useCallback(async (seeds, payload) => {
|
|
1312
1347
|
const composedBefore = new Map(store.callsitePayloads);
|
|
1313
1348
|
let beforeLocalPaint;
|
|
@@ -1341,7 +1376,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
1341
1376
|
await afterSettle(seed.trait, seed.event, payload, seed.local.transitioned, [...seed.local.clientEffectsByTrait ?? [], ...serverRepaints], composedBefore);
|
|
1342
1377
|
}
|
|
1343
1378
|
}, [kernel, slotFlush, traitIndex, store, eventBus, options.navigate, options.navigateBack, afterSettle]);
|
|
1344
|
-
useBusIngress(traitBindings, traitIndex, dispatchAndSettle, eventBus);
|
|
1379
|
+
useBusIngress(traitBindings, traitIndex, dispatchAndSettle, eventBus, appTraitNames);
|
|
1345
1380
|
const sendEvent = useCallback((eventKey, payload) => {
|
|
1346
1381
|
const normalized = normalizeEventKey(eventKey);
|
|
1347
1382
|
for (const [traitName] of traitIndex.byName) {
|
|
@@ -1376,25 +1411,70 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
1376
1411
|
for (const traitName of left) mount.initialized.delete(traitName);
|
|
1377
1412
|
store.mount.unmounted(left);
|
|
1378
1413
|
const entering = [];
|
|
1414
|
+
const embeddedChildren = new Set([...options.callsiteCaptureChildrenByTrait?.values() ?? []].flatMap((c) => [...c]));
|
|
1379
1415
|
for (const binding of traitBindings) {
|
|
1380
1416
|
const traitName = binding.trait.name;
|
|
1381
1417
|
if (mount.initialized.has(traitName)) continue;
|
|
1382
1418
|
mount.initialized.add(traitName);
|
|
1419
|
+
const indexed = traitIndex.byName.get(traitName);
|
|
1420
|
+
if (embeddedChildren.has(traitName) && indexed !== void 0 && (traitReferencesCallsitePayload(indexed.irTrait) || configReferencesCallsitePayload(indexed.config)) && store.manager.repaintLifecycleEvent(traitName) !== void 0 && !store.callsitePayloads.has(traitName)) {
|
|
1421
|
+
continue;
|
|
1422
|
+
}
|
|
1383
1423
|
const lifecycleEvent = LIFECYCLE_EVENTS.find((evt) => store.manager.canHandleEvent(traitName, evt));
|
|
1384
1424
|
if (lifecycleEvent !== void 0) entering.push({ trait: traitName, event: lifecycleEvent });
|
|
1385
1425
|
}
|
|
1386
1426
|
store.mount.mounting(entering.map((e) => e.trait));
|
|
1387
1427
|
if (entering.length > 0) {
|
|
1428
|
+
uiSlots.clearBySource("main", MOUNT_ERROR_SOURCE);
|
|
1388
1429
|
void mountAndSettle(entering, { ...options.initPayload ?? {} }).catch((err) => {
|
|
1389
|
-
|
|
1430
|
+
const traits = entering.map((e) => e.trait);
|
|
1431
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
1432
|
+
const failed = err instanceof TraitMountError ? err.trait : traits.join(", ");
|
|
1433
|
+
const cause = err instanceof TraitMountError ? err.original : err;
|
|
1434
|
+
stateLog.warn("mount:failed", { traits, failed, error: message, stack: cause instanceof Error ? cause.stack : void 0 });
|
|
1435
|
+
uiSlots.render({
|
|
1436
|
+
target: "main",
|
|
1437
|
+
pattern: "error-state",
|
|
1438
|
+
props: { title: t("error.traitMountFailed", { trait: failed }), message, "data-testid": TRAIT_MOUNT_ERROR_TESTID },
|
|
1439
|
+
sourceTrait: MOUNT_ERROR_SOURCE
|
|
1440
|
+
});
|
|
1390
1441
|
});
|
|
1391
1442
|
}
|
|
1392
1443
|
mountedRef.current = mount;
|
|
1393
|
-
}, [traitBindings, store, mountAndSettle, mountKey]);
|
|
1444
|
+
}, [traitBindings, store, mountAndSettle, mountKey, uiSlots, traitIndex, options.callsiteCaptureChildrenByTrait, t]);
|
|
1394
1445
|
useSyncExternalStore(store.subscribe, store.getVersion, store.getVersion);
|
|
1395
1446
|
const traitStates = useMemo(() => store.manager.getAllStates(), [store, store.getVersion()]);
|
|
1396
1447
|
return { traitStates, sendEvent, getTraitState, canHandleEvent, entityBindingSource, awaitingSkeletonSource };
|
|
1397
1448
|
}
|
|
1449
|
+
function useBrowserStore(appName, orbitals, locale) {
|
|
1450
|
+
const entities = useMemo(() => orbitals.flatMap(orbitalInlineEntities).filter(storesRowsInBrowser), [orbitals]);
|
|
1451
|
+
const [state, setState] = useState(() => entities.length === 0 ? { status: "none" } : { status: "opening" });
|
|
1452
|
+
useEffect(() => {
|
|
1453
|
+
if (entities.length === 0) {
|
|
1454
|
+
setState({ status: "none" });
|
|
1455
|
+
return;
|
|
1456
|
+
}
|
|
1457
|
+
let cancelled = false;
|
|
1458
|
+
let opened;
|
|
1459
|
+
setState({ status: "opening" });
|
|
1460
|
+
const open = async () => {
|
|
1461
|
+
try {
|
|
1462
|
+
const store = await openBrowserStore(browserStoreName(appName, locale), orbitals, void 0, locale);
|
|
1463
|
+
if (store === null) return;
|
|
1464
|
+
opened = store;
|
|
1465
|
+
if (!cancelled) setState({ status: "ready", store });
|
|
1466
|
+
} catch (err) {
|
|
1467
|
+
if (!cancelled) setState({ status: "failed", error: err instanceof Error ? err : new Error(String(err)) });
|
|
1468
|
+
}
|
|
1469
|
+
};
|
|
1470
|
+
void open();
|
|
1471
|
+
return () => {
|
|
1472
|
+
cancelled = true;
|
|
1473
|
+
opened?.close();
|
|
1474
|
+
};
|
|
1475
|
+
}, [appName, locale, entities, orbitals]);
|
|
1476
|
+
return state;
|
|
1477
|
+
}
|
|
1398
1478
|
|
|
1399
1479
|
// runtime/fitContent.ts
|
|
1400
1480
|
var IDENTITY = { scale: 1, x: 0, y: 0 };
|
|
@@ -1454,7 +1534,7 @@ function appPathFromHref(href, hostHrefBase) {
|
|
|
1454
1534
|
if (!href.startsWith(`${root}/`)) return null;
|
|
1455
1535
|
return href.slice(root.length);
|
|
1456
1536
|
}
|
|
1457
|
-
function TraitInitializer({ traits, routeParams, mountKey, orbitals, onNavigate, onNavigateBack, onLocalFallback, localFallbackTimeoutMs, persistence, traitConfigsByName, embeddedTraits, callsiteCaptureChildrenByTrait, hasBridge, children }) {
|
|
1537
|
+
function TraitInitializer({ traits, routeParams, mountKey, orbitals, onNavigate, onNavigateBack, onLocalFallback, localFallbackTimeoutMs, persistence, browserStore, traitConfigsByName, embeddedTraits, callsiteCaptureChildrenByTrait, hasBridge, children }) {
|
|
1458
1538
|
const bridge = useServerBridge();
|
|
1459
1539
|
const uiSlots = useUISlots();
|
|
1460
1540
|
useEffect(() => {
|
|
@@ -1473,11 +1553,13 @@ function TraitInitializer({ traits, routeParams, mountKey, orbitals, onNavigate,
|
|
|
1473
1553
|
...callsiteCaptureChildrenByTrait !== void 0 ? { callsiteCaptureChildrenByTrait } : {},
|
|
1474
1554
|
initPayload: routeParams,
|
|
1475
1555
|
...mountKey !== void 0 ? { mountKey } : {},
|
|
1476
|
-
...hasBridge ? { transport: bridge.transport, carriesCircuitState: bridge.carriesCircuitState, awaitTopology: !bridge.topologyKnown } : { persistence }
|
|
1556
|
+
...hasBridge ? { transport: bridge.transport, carriesCircuitState: bridge.carriesCircuitState, awaitTopology: !bridge.topologyKnown } : { persistence },
|
|
1557
|
+
...browserStore !== void 0 ? { browserStore } : {}
|
|
1477
1558
|
});
|
|
1478
1559
|
return /* @__PURE__ */ jsx(EntityBindingContext.Provider, { value: entityBindingSource, children: /* @__PURE__ */ jsx(AwaitingSkeletonContext.Provider, { value: awaitingSkeletonSource, children }) });
|
|
1479
1560
|
}
|
|
1480
1561
|
var CONTENT_STAGE_WIDTH = 480;
|
|
1562
|
+
var NO_ORBITALS = [];
|
|
1481
1563
|
function FitToBox({ children, mode = "box" }) {
|
|
1482
1564
|
const outerRef = useRef(null);
|
|
1483
1565
|
const innerRef = useRef(null);
|
|
@@ -1659,6 +1741,8 @@ function SchemaRunner({ schema, serverUrl, transport, getAccessToken, mockData,
|
|
|
1659
1741
|
return set;
|
|
1660
1742
|
}, [schema, pageName]);
|
|
1661
1743
|
const activeOrbitalTheme = useMemo(() => resolvePreviewTheme(schema, pageName), [schema, pageName]);
|
|
1744
|
+
const { locale } = useTranslate$1();
|
|
1745
|
+
const browserStore = useBrowserStore(schema.name ?? "app", transport?.hostsBrowserStore === true ? NO_ORBITALS : schema.orbitals, locale);
|
|
1662
1746
|
const inner = /* @__PURE__ */ jsx(VerificationProvider, { enabled: true, children: /* @__PURE__ */ jsx(
|
|
1663
1747
|
EntitySchemaProvider,
|
|
1664
1748
|
{
|
|
@@ -1681,13 +1765,15 @@ function SchemaRunner({ schema, serverUrl, transport, getAccessToken, mockData,
|
|
|
1681
1765
|
onLocalFallback,
|
|
1682
1766
|
localFallbackTimeoutMs,
|
|
1683
1767
|
persistence,
|
|
1768
|
+
...browserStore.status === "ready" ? { browserStore: browserStore.store } : {},
|
|
1684
1769
|
children: /* @__PURE__ */ jsx(OrbitalThemeProvider, { theme: activeOrbitalTheme, override: themeOverride, children: /* @__PURE__ */ jsx(Box, { className: "h-full min-h-full overflow-auto p-4", children: /* @__PURE__ */ jsx(UISlotRenderer, { includeHud: true, hudMode: "inline", includeFloating: true, pageKey: pageName }) }) })
|
|
1685
1770
|
}
|
|
1686
1771
|
)
|
|
1687
1772
|
}
|
|
1688
1773
|
) });
|
|
1689
|
-
if (
|
|
1690
|
-
|
|
1774
|
+
if (browserStore.status === "opening") return /* @__PURE__ */ jsx(LoadingState, {});
|
|
1775
|
+
if (browserStore.status === "failed") {
|
|
1776
|
+
return /* @__PURE__ */ jsx(ErrorState, { "data-testid": "browser-store-error", message: browserStore.error.message });
|
|
1691
1777
|
}
|
|
1692
1778
|
return inner;
|
|
1693
1779
|
}
|
|
@@ -1718,12 +1804,15 @@ function OrbPreview({
|
|
|
1718
1804
|
onPageChange,
|
|
1719
1805
|
user = null,
|
|
1720
1806
|
localFallbackTimeoutMs,
|
|
1721
|
-
themeOverride
|
|
1807
|
+
themeOverride,
|
|
1808
|
+
lazyLoader,
|
|
1809
|
+
schemaPath,
|
|
1810
|
+
onUnmatchedNavigate
|
|
1722
1811
|
}) {
|
|
1723
1812
|
if (serverUrl && transport) {
|
|
1724
1813
|
throw new Error("OrbPreview accepts serverUrl OR transport, not both");
|
|
1725
1814
|
}
|
|
1726
|
-
const { t } = useTranslate();
|
|
1815
|
+
const { t } = useTranslate$1();
|
|
1727
1816
|
const [localFallback, setLocalFallback] = useState(false);
|
|
1728
1817
|
const eventBus = useEventBus();
|
|
1729
1818
|
const inHostRouter = useInRouterContext();
|
|
@@ -1732,6 +1821,7 @@ function OrbPreview({
|
|
|
1732
1821
|
if (localFallback) return;
|
|
1733
1822
|
setLocalFallback(true);
|
|
1734
1823
|
}, [localFallback]);
|
|
1824
|
+
const hasOuterBridge = useHasServerBridge();
|
|
1735
1825
|
const parseResult = useMemo(() => {
|
|
1736
1826
|
let parsed;
|
|
1737
1827
|
if (typeof schema === "string") {
|
|
@@ -1767,12 +1857,44 @@ function OrbPreview({
|
|
|
1767
1857
|
return [];
|
|
1768
1858
|
}
|
|
1769
1859
|
}, [parsedSchema]);
|
|
1860
|
+
const lazyPages = useMemo(() => parsedSchema?.lazyPages ?? [], [parsedSchema]);
|
|
1861
|
+
const matchRoute = useCallback((path) => {
|
|
1862
|
+
const candidates = [
|
|
1863
|
+
...pages.map((entry) => ({ kind: "page", entry, path: entry.page.path })),
|
|
1864
|
+
...lazyPages.map((page) => ({ kind: "lazy", page, path: page.path }))
|
|
1865
|
+
];
|
|
1866
|
+
const hit = matchPathAmong(candidates, path, (c) => c.path);
|
|
1867
|
+
if (!hit) return null;
|
|
1868
|
+
return hit.candidate.kind === "page" ? { kind: "page", entry: hit.candidate.entry, params: hit.params } : { kind: "lazy", page: hit.candidate.page, params: hit.params };
|
|
1869
|
+
}, [pages, lazyPages]);
|
|
1870
|
+
const initialRoute = useMemo(
|
|
1871
|
+
() => initialPagePath ? matchRoute(initialPagePath) : null,
|
|
1872
|
+
[matchRoute, initialPagePath]
|
|
1873
|
+
);
|
|
1770
1874
|
const initialPageMatch = useMemo(() => {
|
|
1771
|
-
if (!
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1875
|
+
if (initialRoute?.kind !== "page" || !initialRoute.entry.page.name) return void 0;
|
|
1876
|
+
return { name: initialRoute.entry.page.name, params: initialRoute.params };
|
|
1877
|
+
}, [initialRoute]);
|
|
1878
|
+
const [lazyRoute, setLazyRoute] = useState(
|
|
1879
|
+
initialRoute?.kind === "lazy" && initialPagePath ? { page: initialRoute.page, path: initialPagePath } : null
|
|
1880
|
+
);
|
|
1881
|
+
const [lazyLoad, setLazyLoad] = useState({ status: "loading" });
|
|
1882
|
+
useEffect(() => {
|
|
1883
|
+
if (!lazyRoute) return;
|
|
1884
|
+
if (!lazyLoader) {
|
|
1885
|
+
setLazyLoad({ status: "error", error: `No loader for lazy page ${lazyRoute.page.path} (${lazyRoute.page.orbRef})` });
|
|
1886
|
+
return;
|
|
1887
|
+
}
|
|
1888
|
+
let cancelled = false;
|
|
1889
|
+
setLazyLoad({ status: "loading" });
|
|
1890
|
+
void loadLazyPage(lazyLoader, lazyRoute.page, schemaPath).then((result) => {
|
|
1891
|
+
if (cancelled) return;
|
|
1892
|
+
setLazyLoad(result.success ? { status: "ready", schema: result.data } : { status: "error", error: result.error });
|
|
1893
|
+
});
|
|
1894
|
+
return () => {
|
|
1895
|
+
cancelled = true;
|
|
1896
|
+
};
|
|
1897
|
+
}, [lazyRoute?.page, lazyLoader, schemaPath]);
|
|
1776
1898
|
const initialPageName = initialPageMatch?.name;
|
|
1777
1899
|
const [currentPage, setCurrentPage] = useState(initialPageName);
|
|
1778
1900
|
const [routeParams, setRouteParams] = useState(initialPageMatch?.params ?? {});
|
|
@@ -1782,8 +1904,9 @@ function OrbPreview({
|
|
|
1782
1904
|
prevInitialPagePathRef.current = initialPagePath;
|
|
1783
1905
|
setCurrentPage(initialPageName);
|
|
1784
1906
|
setRouteParams(initialPageMatch?.params ?? {});
|
|
1907
|
+
setLazyRoute(initialRoute?.kind === "lazy" && initialPagePath ? { page: initialRoute.page, path: initialPagePath } : null);
|
|
1785
1908
|
}
|
|
1786
|
-
}, [initialPagePath, initialPageName, initialPageMatch]);
|
|
1909
|
+
}, [initialPagePath, initialPageName, initialPageMatch, initialRoute]);
|
|
1787
1910
|
const currentPagePath = useMemo(() => {
|
|
1788
1911
|
const activePageName = currentPage ?? pages[0]?.page.name;
|
|
1789
1912
|
const resolved = pages.find((p) => p.page.name === activePageName)?.page.path;
|
|
@@ -1798,10 +1921,30 @@ function OrbPreview({
|
|
|
1798
1921
|
return pattern.replace(/:([A-Za-z0-9_]+)/g, (whole, key) => routeParams[key] ?? whole);
|
|
1799
1922
|
}, [currentPagePath, routeParams]);
|
|
1800
1923
|
const navStackRef = useRef(null);
|
|
1924
|
+
const announcePage = useCallback((path) => {
|
|
1925
|
+
if (onPageChange) {
|
|
1926
|
+
onPageChange(path);
|
|
1927
|
+
} else if (!isolated && typeof window !== "undefined") {
|
|
1928
|
+
const url = new URL(window.location.href);
|
|
1929
|
+
url.searchParams.set("page", path);
|
|
1930
|
+
window.history.pushState({}, "", url.toString());
|
|
1931
|
+
window.dispatchEvent(new PopStateEvent("popstate"));
|
|
1932
|
+
}
|
|
1933
|
+
}, [isolated, onPageChange]);
|
|
1801
1934
|
const handleNavigate = useCallback((path, navState) => {
|
|
1802
|
-
const
|
|
1803
|
-
|
|
1804
|
-
|
|
1935
|
+
const route = matchRoute(path);
|
|
1936
|
+
if (!route) {
|
|
1937
|
+
onUnmatchedNavigate?.(path);
|
|
1938
|
+
return;
|
|
1939
|
+
}
|
|
1940
|
+
if (route.kind === "lazy") {
|
|
1941
|
+
setLazyRoute({ page: route.page, path });
|
|
1942
|
+
announcePage(path);
|
|
1943
|
+
return;
|
|
1944
|
+
}
|
|
1945
|
+
setLazyRoute(null);
|
|
1946
|
+
const match = route.entry;
|
|
1947
|
+
const params = { ...route.params, ...navState ?? {} };
|
|
1805
1948
|
navLog.debug("handleNavigate", () => ({
|
|
1806
1949
|
path,
|
|
1807
1950
|
matched: match?.page.name ?? null,
|
|
@@ -1809,19 +1952,12 @@ function OrbPreview({
|
|
|
1809
1952
|
navState: navState ? JSON.stringify(navState) : void 0,
|
|
1810
1953
|
availablePaths: pages.map((p) => p.page.path)
|
|
1811
1954
|
}));
|
|
1812
|
-
if (match
|
|
1955
|
+
if (match.page.name) {
|
|
1813
1956
|
setRouteParams(params);
|
|
1814
1957
|
setCurrentPage(match.page.name);
|
|
1815
|
-
|
|
1816
|
-
onPageChange(path);
|
|
1817
|
-
} else if (!isolated && typeof window !== "undefined") {
|
|
1818
|
-
const url = new URL(window.location.href);
|
|
1819
|
-
url.searchParams.set("page", path);
|
|
1820
|
-
window.history.pushState({}, "", url.toString());
|
|
1821
|
-
window.dispatchEvent(new PopStateEvent("popstate"));
|
|
1822
|
-
}
|
|
1958
|
+
announcePage(path);
|
|
1823
1959
|
}
|
|
1824
|
-
}, [pages,
|
|
1960
|
+
}, [pages, matchRoute, announcePage, onUnmatchedNavigate]);
|
|
1825
1961
|
const handleNavigateEffect = useCallback(
|
|
1826
1962
|
(path, params, crumb) => {
|
|
1827
1963
|
navStackRef.current?.beginNavigate(path, crumb);
|
|
@@ -1886,64 +2022,96 @@ function OrbPreview({
|
|
|
1886
2022
|
navLog.info("interceptor:installed", { pageCount: pages.length, paths: pages.map((p) => p.page.path) });
|
|
1887
2023
|
return () => el.removeEventListener("click", handler, true);
|
|
1888
2024
|
}, [pages, handleNavigate, isolated, hostHrefBase]);
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
ref: containerRef,
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
inHostRouter ? /* @__PURE__ */ jsx(HostHrefBaseProbe, { onBase: setHostHrefBase }) : null,
|
|
1898
|
-
/* @__PURE__ */ jsx(CurrentPagePathProvider, { value: currentPagePath, children: /* @__PURE__ */ jsxs(
|
|
1899
|
-
NavStackProvider,
|
|
2025
|
+
const withBridge = (node) => (serverUrl || transport) && !hasOuterBridge ? /* @__PURE__ */ jsx(ServerBridgeProvider, { schema: parseResult.schema, serverUrl, transport, getAccessToken, children: node }) : node;
|
|
2026
|
+
if (lazyRoute) {
|
|
2027
|
+
return withBridge(
|
|
2028
|
+
/* @__PURE__ */ jsxs(Box, { ref: containerRef, className: `overflow-auto ${className ?? ""}`, style: { height }, children: [
|
|
2029
|
+
lazyLoad.status === "loading" && /* @__PURE__ */ jsx(LoadingState, {}),
|
|
2030
|
+
lazyLoad.status === "error" && /* @__PURE__ */ jsx(ErrorState, { "data-testid": "lazy-page-error", message: lazyLoad.error }),
|
|
2031
|
+
lazyLoad.status === "ready" && /* @__PURE__ */ jsx(
|
|
2032
|
+
OrbPreview,
|
|
1900
2033
|
{
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
}
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
2034
|
+
schema: lazyLoad.schema,
|
|
2035
|
+
autoMock,
|
|
2036
|
+
height: "100%",
|
|
2037
|
+
className: "border-0",
|
|
2038
|
+
serverUrl,
|
|
2039
|
+
transport,
|
|
2040
|
+
getAccessToken,
|
|
2041
|
+
initialPagePath: lazyRoute.path,
|
|
2042
|
+
user,
|
|
2043
|
+
isolated,
|
|
2044
|
+
fit,
|
|
2045
|
+
onPageChange: announcePage,
|
|
2046
|
+
themeOverride,
|
|
2047
|
+
lazyLoader,
|
|
2048
|
+
onUnmatchedNavigate: handleNavigate
|
|
2049
|
+
},
|
|
2050
|
+
lazyRoute.page.orbRef
|
|
2051
|
+
)
|
|
2052
|
+
] })
|
|
2053
|
+
);
|
|
2054
|
+
}
|
|
2055
|
+
return withBridge(
|
|
2056
|
+
/* @__PURE__ */ jsxs(
|
|
2057
|
+
Box,
|
|
2058
|
+
{
|
|
2059
|
+
ref: containerRef,
|
|
2060
|
+
className: `${fit ? "overflow-hidden" : "overflow-auto"} border border-[var(--color-border)] rounded-[var(--radius-md)] ${className ?? ""}`,
|
|
2061
|
+
style: { height },
|
|
2062
|
+
children: [
|
|
2063
|
+
localFallback && /* @__PURE__ */ jsx(Box, { className: "px-3 py-2 bg-[var(--color-warning)] bg-opacity-10 border-b border-[var(--color-warning)] flex items-center gap-2", children: /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-[var(--color-warning-foreground)] flex-1", children: t("orbPreview.serverUnreachable") }) }),
|
|
2064
|
+
inHostRouter ? /* @__PURE__ */ jsx(HostHrefBaseProbe, { onBase: setHostHrefBase }) : null,
|
|
2065
|
+
/* @__PURE__ */ jsx(CurrentPagePathProvider, { value: currentPagePath, children: /* @__PURE__ */ jsxs(
|
|
2066
|
+
NavStackProvider,
|
|
2067
|
+
{
|
|
2068
|
+
pages: navPages,
|
|
2069
|
+
currentPath: concreteCurrentPath,
|
|
2070
|
+
navigate: handleNavigate,
|
|
2071
|
+
storageKey: `almadar:navstack:${parseResult.schema.name ?? "preview"}`,
|
|
2072
|
+
children: [
|
|
2073
|
+
/* @__PURE__ */ jsx(NavStackRefBridge, { apiRef: navStackRef }),
|
|
2074
|
+
/* @__PURE__ */ jsx(OrbitalProvider, { initialData: effectiveMockData, skipTheme: true, verification: true, isolated, user, children: /* @__PURE__ */ jsx(UISlotProvider, { children: fit ? /* @__PURE__ */ jsx(FitToBox, { mode: fit === "content" ? "content" : "box", children: /* @__PURE__ */ jsx(
|
|
2075
|
+
SchemaRunner,
|
|
2076
|
+
{
|
|
2077
|
+
schema: parseResult.schema,
|
|
2078
|
+
serverUrl,
|
|
2079
|
+
transport,
|
|
2080
|
+
getAccessToken,
|
|
2081
|
+
mockData: effectiveMockData,
|
|
2082
|
+
pageName: currentPage,
|
|
2083
|
+
routeParams,
|
|
2084
|
+
onNavigate: handleNavigateEffect,
|
|
2085
|
+
onNavigateBack: handleNavigateBack,
|
|
2086
|
+
onLocalFallback: handleLocalFallback,
|
|
2087
|
+
localFallbackTimeoutMs,
|
|
2088
|
+
persistence,
|
|
2089
|
+
themeOverride
|
|
2090
|
+
}
|
|
2091
|
+
) }) : /* @__PURE__ */ jsx(
|
|
2092
|
+
SchemaRunner,
|
|
2093
|
+
{
|
|
2094
|
+
schema: parseResult.schema,
|
|
2095
|
+
serverUrl,
|
|
2096
|
+
transport,
|
|
2097
|
+
getAccessToken,
|
|
2098
|
+
mockData: effectiveMockData,
|
|
2099
|
+
pageName: currentPage,
|
|
2100
|
+
routeParams,
|
|
2101
|
+
onNavigate: handleNavigateEffect,
|
|
2102
|
+
onNavigateBack: handleNavigateBack,
|
|
2103
|
+
onLocalFallback: handleLocalFallback,
|
|
2104
|
+
localFallbackTimeoutMs,
|
|
2105
|
+
persistence,
|
|
2106
|
+
themeOverride
|
|
2107
|
+
}
|
|
2108
|
+
) }) })
|
|
2109
|
+
]
|
|
2110
|
+
}
|
|
2111
|
+
) })
|
|
2112
|
+
]
|
|
2113
|
+
}
|
|
2114
|
+
)
|
|
1947
2115
|
);
|
|
1948
2116
|
}
|
|
1949
2117
|
OrbPreview.displayName = "OrbPreview";
|
|
@@ -1957,7 +2125,11 @@ function BrowserPlayground({
|
|
|
1957
2125
|
paused,
|
|
1958
2126
|
fit,
|
|
1959
2127
|
onPageChange,
|
|
1960
|
-
viewer
|
|
2128
|
+
viewer,
|
|
2129
|
+
messages,
|
|
2130
|
+
locale,
|
|
2131
|
+
lazyLoader,
|
|
2132
|
+
schemaPath
|
|
1961
2133
|
}) {
|
|
1962
2134
|
const [runtime] = useState(
|
|
1963
2135
|
() => new OrbitalServerRuntime({ mode, debug: false, ...viewer !== void 0 ? { defaultUser: viewer } : {} })
|
|
@@ -1973,10 +2145,18 @@ function BrowserPlayground({
|
|
|
1973
2145
|
const registrationReady = useMemo(() => {
|
|
1974
2146
|
const orbitalNames = schema.orbitals.map((o) => o.name);
|
|
1975
2147
|
playgroundLog.debug("register:start", { schema: schema.name, orbitalNames });
|
|
1976
|
-
|
|
2148
|
+
const lazyPages = schema.lazyPages ?? [];
|
|
2149
|
+
const lazy = lazyPages.length > 0 && lazyLoader !== void 0 ? Promise.all(lazyPages.map(async (page) => {
|
|
2150
|
+
const loaded = await loadLazyPage(lazyLoader, page, schemaPath);
|
|
2151
|
+
if (!loaded.success) throw new Error(loaded.error);
|
|
2152
|
+
return loaded.data;
|
|
2153
|
+
})) : Promise.resolve([]);
|
|
2154
|
+
return lazy.then(
|
|
2155
|
+
(lazySchemas) => runtime.register(schema, { ...messages !== void 0 ? { messages } : {}, lazy: lazySchemas })
|
|
2156
|
+
).then(() => {
|
|
1977
2157
|
playgroundLog.debug("register:done", { schema: schema.name, orbitalNames });
|
|
1978
2158
|
});
|
|
1979
|
-
}, [runtime, schema]);
|
|
2159
|
+
}, [runtime, schema, messages, lazyLoader, schemaPath]);
|
|
1980
2160
|
const teardownTimerRef = useRef(null);
|
|
1981
2161
|
useEffect(() => {
|
|
1982
2162
|
if (teardownTimerRef.current !== null) {
|
|
@@ -1998,7 +2178,8 @@ function BrowserPlayground({
|
|
|
1998
2178
|
return runtime.processOrbitalEvent(orbitalName, request);
|
|
1999
2179
|
},
|
|
2000
2180
|
{
|
|
2001
|
-
|
|
2181
|
+
// The program (lazy behaviors included) is registered above; the bridge only waits for it.
|
|
2182
|
+
onRegister: () => registrationReady,
|
|
2002
2183
|
onUnregister: () => {
|
|
2003
2184
|
runtime.unregisterAll();
|
|
2004
2185
|
}
|
|
@@ -2006,7 +2187,13 @@ function BrowserPlayground({
|
|
|
2006
2187
|
),
|
|
2007
2188
|
[runtime, registrationReady]
|
|
2008
2189
|
);
|
|
2009
|
-
|
|
2190
|
+
const viewerLocale = locale ?? schema.locales?.[0];
|
|
2191
|
+
const i18n = useMemo(() => {
|
|
2192
|
+
if (viewerLocale === void 0 || messages === void 0) return void 0;
|
|
2193
|
+
const catalog = messages[viewerLocale] ?? {};
|
|
2194
|
+
return { locale: viewerLocale, direction: localeDirection(viewerLocale), t: createTranslate(catalog), messages: catalog };
|
|
2195
|
+
}, [viewerLocale, messages]);
|
|
2196
|
+
const preview = /* @__PURE__ */ jsx(
|
|
2010
2197
|
OrbPreview,
|
|
2011
2198
|
{
|
|
2012
2199
|
schema,
|
|
@@ -2017,9 +2204,12 @@ function BrowserPlayground({
|
|
|
2017
2204
|
fit,
|
|
2018
2205
|
onPageChange,
|
|
2019
2206
|
user: viewer ?? null,
|
|
2207
|
+
lazyLoader,
|
|
2208
|
+
schemaPath,
|
|
2020
2209
|
isolated: true
|
|
2021
2210
|
}
|
|
2022
2211
|
);
|
|
2212
|
+
return i18n !== void 0 ? /* @__PURE__ */ jsx(I18nProvider, { value: i18n, children: preview }) : preview;
|
|
2023
2213
|
}
|
|
2024
2214
|
|
|
2025
2215
|
export { BrowserPlayground, OrbPreview, clearSchemaCache, useResolvedSchema, useTraitStateMachine };
|