@almadar/ui 5.153.0 → 5.154.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.
@@ -5,8 +5,8 @@ import * as _almadar_runtime from '@almadar/runtime';
5
5
  import { TraitState, EffectHandlers } from '@almadar/runtime';
6
6
  import '../useEventBus-Ckr4wqW3.cjs';
7
7
  import { c as useUISlots } from '../UISlotContext-BlRDbHDy.cjs';
8
- import { a as EntityBindingSource, h as ServerBridgeTransport } from '../EntityBindingContext-CD9ZoXb4.cjs';
9
- export { b as EntitySchemaContextValue, c as EntitySchemaProvider, d as EntitySchemaProviderProps, e as ServerBridgeContextValue, f as ServerBridgeProvider, i as ServerClientEffect, T as TraitContext, k as TraitContextValue, l as TraitInstance, m as TraitProvider, n as TraitProviderProps, o as useEntitySchema, p as useEntitySchemaOptional, q as useServerBridge, r as useTrait, s as useTraitContext } from '../EntityBindingContext-CD9ZoXb4.cjs';
8
+ import { a as EntityBindingSource, h as ServerBridgeTransport } from '../EntityBindingContext-BfZGeDfX.cjs';
9
+ export { b as EntitySchemaContextValue, c as EntitySchemaProvider, d as EntitySchemaProviderProps, e as ServerBridgeContextValue, f as ServerBridgeProvider, i as ServerClientEffect, T as TraitContext, k as TraitContextValue, l as TraitInstance, m as TraitProvider, n as TraitProviderProps, o as useEntitySchema, p as useEntitySchemaOptional, q as useServerBridge, r as useTrait, s as useTraitContext } from '../EntityBindingContext-BfZGeDfX.cjs';
10
10
  import { PerfEntry } from '@almadar/runtime/ui';
11
11
  export { PERF_NAMESPACE, PerfEntry, PreparedPreviewSchema, adjustSchemaForMockData, buildMockData, clearPerf, perfEnd, perfStart, perfTime, prepareSchemaForPreview, wrapCallbackForEvent } from '@almadar/runtime/ui';
12
12
  import React__default, { ProfilerOnRenderCallback } from 'react';
@@ -40,8 +40,11 @@ interface UseTraitStateMachineOptions {
40
40
  * the consumer.
41
41
  */
42
42
  onEventProcessed?: (eventKey: string, payload?: EventPayload, dispatchedOrbitals?: Set<string>) => void | Promise<void>;
43
- /** Router navigate function for navigate effects */
44
- navigate?: (path: string, params?: Record<string, string>) => void;
43
+ /** Router navigate function for navigate effects. `crumb` labels the
44
+ * target page's navigation-stack entry (from the effect's options). */
45
+ navigate?: (path: string, params?: Record<string, string>, crumb?: string) => void;
46
+ /** Pop the orbital-scoped navigation stack (navigate-back effect). */
47
+ navigateBack?: () => void;
45
48
  /** Payload merged into the mount-time lifecycle INIT (route params from a parameterized page path). */
46
49
  initPayload?: EventPayload;
47
50
  /** Notification function for notify effects */
@@ -170,7 +173,11 @@ interface SlotSetter {
170
173
  interface CreateClientEffectHandlersOptions {
171
174
  eventBus: ClientEventBus;
172
175
  slotSetter: SlotSetter;
173
- navigate?: (path: string, params?: Record<string, string>) => void;
176
+ /** Navigate handler. `crumb` labels the target page's navigation-stack
177
+ * entry (from the navigate effect's `{ crumb: … }` options). */
178
+ navigate?: (path: string, params?: Record<string, string>, crumb?: string) => void;
179
+ /** Pop the orbital-scoped navigation stack (navigate-back effect). */
180
+ navigateBack?: () => void;
174
181
  notify?: (message: string, type: 'success' | 'error' | 'warning' | 'info') => void;
175
182
  /**
176
183
  * Live client-entity write target for `[runtime]` entities. `(set
@@ -5,8 +5,8 @@ import * as _almadar_runtime from '@almadar/runtime';
5
5
  import { TraitState, EffectHandlers } from '@almadar/runtime';
6
6
  import '../useEventBus-CQWyAWpK.js';
7
7
  import { c as useUISlots } from '../UISlotContext-CB89mv7N.js';
8
- import { a as EntityBindingSource, h as ServerBridgeTransport } from '../EntityBindingContext-CD9ZoXb4.js';
9
- export { b as EntitySchemaContextValue, c as EntitySchemaProvider, d as EntitySchemaProviderProps, e as ServerBridgeContextValue, f as ServerBridgeProvider, i as ServerClientEffect, T as TraitContext, k as TraitContextValue, l as TraitInstance, m as TraitProvider, n as TraitProviderProps, o as useEntitySchema, p as useEntitySchemaOptional, q as useServerBridge, r as useTrait, s as useTraitContext } from '../EntityBindingContext-CD9ZoXb4.js';
8
+ import { a as EntityBindingSource, h as ServerBridgeTransport } from '../EntityBindingContext-BfZGeDfX.js';
9
+ export { b as EntitySchemaContextValue, c as EntitySchemaProvider, d as EntitySchemaProviderProps, e as ServerBridgeContextValue, f as ServerBridgeProvider, i as ServerClientEffect, T as TraitContext, k as TraitContextValue, l as TraitInstance, m as TraitProvider, n as TraitProviderProps, o as useEntitySchema, p as useEntitySchemaOptional, q as useServerBridge, r as useTrait, s as useTraitContext } from '../EntityBindingContext-BfZGeDfX.js';
10
10
  import { PerfEntry } from '@almadar/runtime/ui';
11
11
  export { PERF_NAMESPACE, PerfEntry, PreparedPreviewSchema, adjustSchemaForMockData, buildMockData, clearPerf, perfEnd, perfStart, perfTime, prepareSchemaForPreview, wrapCallbackForEvent } from '@almadar/runtime/ui';
12
12
  import React__default, { ProfilerOnRenderCallback } from 'react';
@@ -40,8 +40,11 @@ interface UseTraitStateMachineOptions {
40
40
  * the consumer.
41
41
  */
42
42
  onEventProcessed?: (eventKey: string, payload?: EventPayload, dispatchedOrbitals?: Set<string>) => void | Promise<void>;
43
- /** Router navigate function for navigate effects */
44
- navigate?: (path: string, params?: Record<string, string>) => void;
43
+ /** Router navigate function for navigate effects. `crumb` labels the
44
+ * target page's navigation-stack entry (from the effect's options). */
45
+ navigate?: (path: string, params?: Record<string, string>, crumb?: string) => void;
46
+ /** Pop the orbital-scoped navigation stack (navigate-back effect). */
47
+ navigateBack?: () => void;
45
48
  /** Payload merged into the mount-time lifecycle INIT (route params from a parameterized page path). */
46
49
  initPayload?: EventPayload;
47
50
  /** Notification function for notify effects */
@@ -170,7 +173,11 @@ interface SlotSetter {
170
173
  interface CreateClientEffectHandlersOptions {
171
174
  eventBus: ClientEventBus;
172
175
  slotSetter: SlotSetter;
173
- navigate?: (path: string, params?: Record<string, string>) => void;
176
+ /** Navigate handler. `crumb` labels the target page's navigation-stack
177
+ * entry (from the navigate effect's `{ crumb: … }` options). */
178
+ navigate?: (path: string, params?: Record<string, string>, crumb?: string) => void;
179
+ /** Pop the orbital-scoped navigation stack (navigate-back effect). */
180
+ navigateBack?: () => void;
174
181
  notify?: (message: string, type: 'success' | 'error' | 'warning' | 'info') => void;
175
182
  /**
176
183
  * Live client-entity write target for `[runtime]` entities. `(set
@@ -1,6 +1,6 @@
1
1
  import * as React85 from 'react';
2
2
  import React85__default, { createContext, useContext, useMemo, useRef, useEffect, useCallback, Suspense, useState, useSyncExternalStore, useLayoutEffect, lazy, useId } from 'react';
3
- import { EventBusContext, useTraitScopeChain, useEntitySchemaOptional, useEntityBindingSnapshot, useTraitScope, useEntitySchema, getAllPages, matchPathAmong, CurrentPagePathProvider, OrbitalProvider, TraitScopeProvider, ServerBridgeProvider, useCurrentPagePath, useGameAudioContextOptional, VerificationProvider, EntitySchemaProvider, OrbitalThemeProvider, useServerBridge, EntityBindingContext } from '@almadar/ui/providers';
3
+ import { EventBusContext, useTraitScopeChain, useEntitySchemaOptional, useEntityBindingSnapshot, useTraitScope, useEntitySchema, getAllPages, matchPathAmong, CurrentPagePathProvider, NavStackProvider, OrbitalProvider, TraitScopeProvider, useNavStack, ServerBridgeProvider, useCurrentPagePath, useGameAudioContextOptional, VerificationProvider, EntitySchemaProvider, OrbitalThemeProvider, useServerBridge, EntityBindingContext } from '@almadar/ui/providers';
4
4
  export { EntitySchemaProvider, ServerBridgeProvider, TraitContext, TraitProvider, useEntitySchema, useEntitySchemaOptional, useServerBridge, useTrait, useTraitContext } from '@almadar/ui/providers';
5
5
  import { createLogger, setNamespaceLevel, isLogLevelEnabled } from '@almadar/logger';
6
6
  import { StateMachineManager, collectDeclaredConfigDefaults, resolveCallSitePayloadCaptures, createServerEffectHandlers, EffectExecutor, createContextFromBindings, createTickScheduler, isValidCronExpression, parseDurationString, InMemoryPersistence, normalizeCallSiteConfigToValues, interpolateValue } from '@almadar/runtime';
@@ -20960,17 +20960,27 @@ var init_Breadcrumb = __esm({
20960
20960
  init_useEventBus();
20961
20961
  Breadcrumb = ({
20962
20962
  items,
20963
+ fromNavStack = false,
20964
+ itemEvent,
20963
20965
  separator = "chevron-right",
20964
20966
  maxItems,
20965
20967
  className
20966
20968
  }) => {
20967
20969
  const eventBus = useEventBus();
20968
20970
  const { t } = useTranslate();
20969
- const displayItems = maxItems && items.length > maxItems ? [
20970
- ...items.slice(0, 1),
20971
+ const navStack = useNavStack();
20972
+ const sourceItems = fromNavStack ? navStack.entries.map((entry, i) => ({
20973
+ label: entry.label,
20974
+ path: entry.href,
20975
+ isCurrent: i === navStack.entries.length - 1,
20976
+ event: itemEvent
20977
+ })) : items ?? [];
20978
+ if (fromNavStack && sourceItems.length === 0) return null;
20979
+ const displayItems = maxItems && sourceItems.length > maxItems ? [
20980
+ ...sourceItems.slice(0, 1),
20971
20981
  { label: "...", isCurrent: false },
20972
- ...items.slice(-maxItems + 1)
20973
- ] : items;
20982
+ ...sourceItems.slice(-maxItems + 1)
20983
+ ] : sourceItems;
20974
20984
  return /* @__PURE__ */ jsx(
20975
20985
  "nav",
20976
20986
  {
@@ -20980,7 +20990,7 @@ var init_Breadcrumb = __esm({
20980
20990
  const isLast = index === displayItems.length - 1;
20981
20991
  const isEllipsis = item.label === "...";
20982
20992
  return /* @__PURE__ */ jsxs("li", { className: "flex items-center gap-2", children: [
20983
- isEllipsis ? /* @__PURE__ */ jsx(Typography, { variant: "small", color: "muted", children: item.label }) : item.href || item.path ? /* @__PURE__ */ jsxs(
20993
+ isEllipsis ? /* @__PURE__ */ jsx(Typography, { variant: "small", color: "muted", children: item.label }) : (item.href || item.path) && !item.event && !fromNavStack ? /* @__PURE__ */ jsxs(
20984
20994
  "a",
20985
20995
  {
20986
20996
  href: item.href || item.path,
@@ -21006,7 +21016,12 @@ var init_Breadcrumb = __esm({
21006
21016
  {
21007
21017
  type: "button",
21008
21018
  onClick: () => {
21009
- if (item.event) eventBus.emit(`UI:${item.event}`, { label: item.label });
21019
+ const href = item.path ?? item.href;
21020
+ if (item.event) {
21021
+ eventBus.emit(`UI:${item.event}`, { label: item.label, href, index });
21022
+ } else if (fromNavStack && href) {
21023
+ navStack.goTo(href);
21024
+ }
21010
21025
  item.onClick?.();
21011
21026
  },
21012
21027
  className: cn(
@@ -41605,6 +41620,7 @@ var init_DetailPanel = __esm({
41605
41620
  init_Box();
41606
41621
  init_Stack();
41607
41622
  init_SimpleGrid();
41623
+ init_Menu();
41608
41624
  init_LoadingState();
41609
41625
  init_ErrorState();
41610
41626
  init_EmptyState();
@@ -41622,6 +41638,7 @@ var init_DetailPanel = __esm({
41622
41638
  avatar,
41623
41639
  sections: propSections,
41624
41640
  actions,
41641
+ maxInlineActions,
41625
41642
  backAction,
41626
41643
  footer,
41627
41644
  slideOver = false,
@@ -41856,7 +41873,7 @@ var init_DetailPanel = __esm({
41856
41873
  }
41857
41874
  ) }),
41858
41875
  /* @__PURE__ */ jsxs(HStack, { justify: "end", align: "center", gap: "xs", children: [
41859
- otherActions.map((action, idx) => /* @__PURE__ */ jsx(
41876
+ (maxInlineActions != null ? otherActions.slice(0, maxInlineActions) : otherActions).map((action, idx) => /* @__PURE__ */ jsx(
41860
41877
  Button,
41861
41878
  {
41862
41879
  variant: action.variant || "secondary",
@@ -41871,6 +41888,22 @@ var init_DetailPanel = __esm({
41871
41888
  },
41872
41889
  idx
41873
41890
  )),
41891
+ maxInlineActions != null && otherActions.length > maxInlineActions && /* @__PURE__ */ jsx(
41892
+ Menu,
41893
+ {
41894
+ position: "bottom-end",
41895
+ trigger: /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "sm", "aria-label": t("common.actions"), "data-testid": "action-overflow", children: /* @__PURE__ */ jsx(Icon, { name: "more-horizontal", size: "xs" }) }),
41896
+ items: otherActions.slice(maxInlineActions).map((action) => ({
41897
+ // ONE firing path: onClick → handleActionClick (emits with
41898
+ // the {id, row} payload). Passing `event` too would make
41899
+ // Menu emit a second, payload-less copy of the same event.
41900
+ label: action.label,
41901
+ icon: action.icon,
41902
+ variant: action.variant === "danger" ? "danger" : "default",
41903
+ onClick: () => handleActionClick(action, normalizedData)
41904
+ }))
41905
+ }
41906
+ ),
41874
41907
  /* @__PURE__ */ jsx(
41875
41908
  Button,
41876
41909
  {
@@ -49315,7 +49348,7 @@ function runTickFrame(entityId, orderedWriters, store) {
49315
49348
  }
49316
49349
  var log3 = createLogger("almadar:ui:effects:client-handlers");
49317
49350
  function createClientEffectHandlers(options) {
49318
- const { eventBus, slotSetter, navigate, notify, callService, liveEntity } = options;
49351
+ const { eventBus, slotSetter, navigate, navigateBack, notify, callService, liveEntity } = options;
49319
49352
  return {
49320
49353
  emit: (event, payload, source) => {
49321
49354
  const prefixedEvent = event.startsWith("UI:") ? event : `UI:${event}`;
@@ -49365,6 +49398,9 @@ function createClientEffectHandlers(options) {
49365
49398
  }
49366
49399
  log3.warn("No navigate handler, ignoring", { path });
49367
49400
  }),
49401
+ navigateBack: navigateBack ?? (() => {
49402
+ log3.warn("No navigate-back handler, ignoring");
49403
+ }),
49368
49404
  notify: notify ?? ((msg, type) => {
49369
49405
  log3.debug("notify", { type, message: msg });
49370
49406
  })
@@ -50004,6 +50040,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
50004
50040
  }
50005
50041
  },
50006
50042
  navigate: optionsRef.current?.navigate,
50043
+ navigateBack: optionsRef.current?.navigateBack,
50007
50044
  notify: optionsRef.current?.notify,
50008
50045
  callService: optionsRef.current?.callService,
50009
50046
  // The canonical client `set` writes `(set @entity.X)` straight into
@@ -50065,6 +50102,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
50065
50102
  emit: clientHandlers.emit,
50066
50103
  renderUI: clientHandlers.renderUI,
50067
50104
  navigate: clientHandlers.navigate,
50105
+ navigateBack: clientHandlers.navigateBack,
50068
50106
  notify: clientHandlers.notify
50069
50107
  };
50070
50108
  }
@@ -50787,7 +50825,7 @@ function normalizeChild(child) {
50787
50825
  props: { ...rest, ...normalizedChildren !== void 0 ? { children: normalizedChildren } : {} }
50788
50826
  };
50789
50827
  }
50790
- function applyServerEffects(effects, uiSlots, onNavigate, embeddedTraits, activeTraits) {
50828
+ function applyServerEffects(effects, uiSlots, onNavigate, embeddedTraits, activeTraits, onNavigateBack) {
50791
50829
  for (const eff of effects) {
50792
50830
  if (eff.type === "render-ui" && eff.slot && eff.pattern) {
50793
50831
  if (eff.traitName && activeTraits && !activeTraits.has(eff.traitName)) {
@@ -50833,7 +50871,9 @@ function applyServerEffects(effects, uiSlots, onNavigate, embeddedTraits, active
50833
50871
  });
50834
50872
  }
50835
50873
  } else if (eff.type === "navigate" && eff.route && onNavigate) {
50836
- onNavigate(eff.route, eff.params);
50874
+ onNavigate(eff.route, eff.params, eff.crumb);
50875
+ } else if (eff.type === "navigate-back" && onNavigateBack) {
50876
+ onNavigateBack();
50837
50877
  }
50838
50878
  }
50839
50879
  }
@@ -50856,7 +50896,17 @@ function collectServerActiveTraits(ir, allTraits, mountedTraitNames) {
50856
50896
  }
50857
50897
  return active;
50858
50898
  }
50859
- function TraitInitializer({ traits: traits2, routeParams, orbitalNames, onNavigate, onLocalFallback, persistence, traitConfigsByName, orbitalsByTrait, embeddedTraits, serverActiveTraits, children }) {
50899
+ function NavStackRefBridge({ apiRef }) {
50900
+ const api = useNavStack();
50901
+ useEffect(() => {
50902
+ apiRef.current = api;
50903
+ return () => {
50904
+ apiRef.current = null;
50905
+ };
50906
+ }, [api, apiRef]);
50907
+ return null;
50908
+ }
50909
+ function TraitInitializer({ traits: traits2, routeParams, orbitalNames, onNavigate, onNavigateBack, onLocalFallback, persistence, traitConfigsByName, orbitalsByTrait, embeddedTraits, serverActiveTraits, children }) {
50860
50910
  const bridge = useServerBridge();
50861
50911
  const activeTraitNames = useMemo(
50862
50912
  () => new Set(traits2.map((b) => b.trait.name).filter((n) => !!n)),
@@ -50882,10 +50932,10 @@ function TraitInitializer({ traits: traits2, routeParams, orbitalNames, onNaviga
50882
50932
  for (const name of targets) {
50883
50933
  const { effects, meta } = await bridge.sendEvent(name, event, withActiveTraits(payload));
50884
50934
  recordServerResponse(name, event, meta);
50885
- applyServerEffects(effects, uiSlots, onNavigate, embeddedTraits, activeTraitNames);
50935
+ applyServerEffects(effects, uiSlots, onNavigate, embeddedTraits, activeTraitNames, onNavigateBack);
50886
50936
  }
50887
- }, [bridge.connected, bridge.sendEvent, orbitalNames, uiSlots, onNavigate, embeddedTraits, activeTraitNames, withActiveTraits]);
50888
- const opts = orbitalNames ? { onEventProcessed, navigate: onNavigate, traitConfigsByName, orbitalsByTrait, embeddedTraits, initPayload: routeParams } : { navigate: onNavigate, persistence, traitConfigsByName, orbitalsByTrait, embeddedTraits, initPayload: routeParams };
50937
+ }, [bridge.connected, bridge.sendEvent, orbitalNames, uiSlots, onNavigate, onNavigateBack, embeddedTraits, activeTraitNames, withActiveTraits]);
50938
+ const opts = orbitalNames ? { onEventProcessed, navigate: onNavigate, navigateBack: onNavigateBack, traitConfigsByName, orbitalsByTrait, embeddedTraits, initPayload: routeParams } : { navigate: onNavigate, navigateBack: onNavigateBack, persistence, traitConfigsByName, orbitalsByTrait, embeddedTraits, initPayload: routeParams };
50889
50939
  const { sendEvent, entityBindingSource } = useTraitStateMachine(traits2, uiSlots, opts);
50890
50940
  const initSentRef = useRef(false);
50891
50941
  const prevTraitsRef = useRef(void 0);
@@ -50944,13 +50994,13 @@ function TraitInitializer({ traits: traits2, routeParams, orbitalNames, onNaviga
50944
50994
  effects: effectTraces,
50945
50995
  timestamp: Date.now()
50946
50996
  });
50947
- applyServerEffects(effects, uiSlots, onNavigate, embeddedTraits, activeTraitNames);
50997
+ applyServerEffects(effects, uiSlots, onNavigate, embeddedTraits, activeTraitNames, onNavigateBack);
50948
50998
  }
50949
50999
  })();
50950
- }, [bridge.connected, orbitalNames, bridge.sendEvent, uiSlots, onNavigate, embeddedTraits, activeTraitNames, withActiveTraits, routeParams]);
51000
+ }, [bridge.connected, orbitalNames, bridge.sendEvent, uiSlots, onNavigate, onNavigateBack, embeddedTraits, activeTraitNames, withActiveTraits, routeParams]);
50951
51001
  return /* @__PURE__ */ jsx(EntityBindingContext.Provider, { value: entityBindingSource, children });
50952
51002
  }
50953
- function SchemaRunner({ schema, serverUrl, transport, mockData, pageName, routeParams, onNavigate, onLocalFallback, persistence }) {
51003
+ function SchemaRunner({ schema, serverUrl, transport, mockData, pageName, routeParams, onNavigate, onNavigateBack, onLocalFallback, persistence }) {
50954
51004
  const { traits: traits2, allEntities, allTraits, ir } = useResolvedSchema(schema, pageName);
50955
51005
  const allPageTraits = useMemo(() => {
50956
51006
  let base;
@@ -51098,6 +51148,7 @@ function SchemaRunner({ schema, serverUrl, transport, mockData, pageName, routeP
51098
51148
  embeddedTraits,
51099
51149
  serverActiveTraits,
51100
51150
  onNavigate,
51151
+ onNavigateBack,
51101
51152
  onLocalFallback,
51102
51153
  persistence,
51103
51154
  children: /* @__PURE__ */ jsx(OrbitalThemeProvider, { theme: activeOrbitalTheme, children: /* @__PURE__ */ jsx(Box, { className: "h-full min-h-full overflow-auto p-4", children: /* @__PURE__ */ jsx(UISlotRenderer, { includeHud: true, hudMode: "inline", includeFloating: true }) }) })
@@ -51190,6 +51241,15 @@ function OrbPreview({
51190
51241
  const resolved = pages.find((p) => p.page.name === activePageName)?.page.path;
51191
51242
  return resolved ?? initialPagePath;
51192
51243
  }, [pages, currentPage, initialPagePath]);
51244
+ const navPages = useMemo(
51245
+ () => pages.filter((p) => typeof p.page.path === "string" && p.page.path.length > 0).map((p) => ({ path: p.page.path, name: p.page.name, orbital: p.orbitalName })),
51246
+ [pages]
51247
+ );
51248
+ const concreteCurrentPath = useMemo(() => {
51249
+ const pattern = currentPagePath ?? "/";
51250
+ return pattern.replace(/:([A-Za-z0-9_]+)/g, (whole, key) => routeParams[key] ?? whole);
51251
+ }, [currentPagePath, routeParams]);
51252
+ const navStackRef = useRef(null);
51193
51253
  const handleNavigate = useCallback((path) => {
51194
51254
  const hit = matchPathAmong(pages, path, (entry) => entry.page.path);
51195
51255
  const match = hit?.candidate;
@@ -51211,6 +51271,16 @@ function OrbPreview({
51211
51271
  }
51212
51272
  }
51213
51273
  }, [pages]);
51274
+ const handleNavigateEffect = useCallback(
51275
+ (path, _params, crumb) => {
51276
+ navStackRef.current?.beginNavigate(path, crumb);
51277
+ handleNavigate(path);
51278
+ },
51279
+ [handleNavigate]
51280
+ );
51281
+ const handleNavigateBack = useCallback(() => {
51282
+ navStackRef.current?.back();
51283
+ }, []);
51214
51284
  useEffect(() => {
51215
51285
  const unsubscribe = eventBus.on("UI:NAVIGATE", (event) => {
51216
51286
  const url = event.payload?.url;
@@ -51263,20 +51333,33 @@ function OrbPreview({
51263
51333
  style: { height },
51264
51334
  children: [
51265
51335
  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: "Preview server unreachable \u2014 running locally. Server-side state and persistence are disabled." }) }),
51266
- /* @__PURE__ */ jsx(CurrentPagePathProvider, { value: currentPagePath, children: /* @__PURE__ */ jsx(OrbitalProvider, { initialData: effectiveMockData, skipTheme: true, verification: true, isolated, children: /* @__PURE__ */ jsx(UISlotProvider, { children: /* @__PURE__ */ jsx(
51267
- SchemaRunner,
51336
+ /* @__PURE__ */ jsx(CurrentPagePathProvider, { value: currentPagePath, children: /* @__PURE__ */ jsxs(
51337
+ NavStackProvider,
51268
51338
  {
51269
- schema: parseResult.schema,
51270
- serverUrl,
51271
- transport,
51272
- mockData: effectiveMockData,
51273
- pageName: currentPage,
51274
- routeParams,
51275
- onNavigate: handleNavigate,
51276
- onLocalFallback: handleLocalFallback,
51277
- persistence
51278
- }
51279
- ) }) }) })
51339
+ pages: navPages,
51340
+ currentPath: concreteCurrentPath,
51341
+ navigate: handleNavigate,
51342
+ storageKey: `almadar:navstack:${parseResult.schema.name ?? "preview"}`,
51343
+ children: [
51344
+ /* @__PURE__ */ jsx(NavStackRefBridge, { apiRef: navStackRef }),
51345
+ /* @__PURE__ */ jsx(OrbitalProvider, { initialData: effectiveMockData, skipTheme: true, verification: true, isolated, children: /* @__PURE__ */ jsx(UISlotProvider, { children: /* @__PURE__ */ jsx(
51346
+ SchemaRunner,
51347
+ {
51348
+ schema: parseResult.schema,
51349
+ serverUrl,
51350
+ transport,
51351
+ mockData: effectiveMockData,
51352
+ pageName: currentPage,
51353
+ routeParams,
51354
+ onNavigate: handleNavigateEffect,
51355
+ onNavigateBack: handleNavigateBack,
51356
+ onLocalFallback: handleLocalFallback,
51357
+ persistence
51358
+ }
51359
+ ) }) })
51360
+ ]
51361
+ }
51362
+ ) })
51280
51363
  ]
51281
51364
  }
51282
51365
  );
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@almadar/ui",
3
- "version": "5.153.0",
3
+ "version": "5.154.0",
4
4
  "description": "React UI components, hooks, and providers for Almadar",
5
5
  "type": "module",
6
6
  "sideEffects": [
@@ -118,11 +118,11 @@
118
118
  "access": "public"
119
119
  },
120
120
  "dependencies": {
121
- "@almadar/core": "^10.63.0",
121
+ "@almadar/core": "^10.64.0",
122
122
  "@almadar/evaluator": "^2.41.0",
123
123
  "@almadar/logger": "^1.11.0",
124
- "@almadar/runtime": "^6.55.0",
125
- "@almadar/std": "^16.179.0",
124
+ "@almadar/runtime": "^6.56.0",
125
+ "@almadar/std": "^16.180.0",
126
126
  "@almadar/syntax": "^1.15.0",
127
127
  "@dnd-kit/core": "^6.3.1",
128
128
  "@dnd-kit/sortable": "^10.0.0",