@almadar/ui 6.57.0 → 6.58.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.
@@ -79,6 +79,7 @@ var utilities = require('@dnd-kit/utilities');
79
79
  var emojilib = require('emojilib');
80
80
  var d3Force = require('d3-force');
81
81
  var react = require('@xyflow/react');
82
+ var mock = require('@almadar/db/mock');
82
83
  var OrbitalServerRuntime = require('@almadar/runtime/OrbitalServerRuntime');
83
84
 
84
85
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
@@ -18786,6 +18787,7 @@ var init_Tabs = __esm({
18786
18787
  }
18787
18788
  };
18788
18789
  const activeTabContent = safeItems.find((item) => item.id === activeTab)?.content;
18790
+ const rendersPanel = activeTabContent !== void 0 && activeTabContent !== null;
18789
18791
  if (safeItems.length === 0) {
18790
18792
  return /* @__PURE__ */ jsxRuntime.jsx(Box, { ...domPassthrough(rest), className: cn("w-full", className), children: /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "small", color: "muted", className: "py-4", children: t("empty.noItems") }) });
18791
18793
  }
@@ -18836,7 +18838,7 @@ var init_Tabs = __esm({
18836
18838
  id: tabId(item.id),
18837
18839
  role: "tab",
18838
18840
  "aria-selected": isActive,
18839
- "aria-controls": isActive ? panelId(item.id) : void 0,
18841
+ "aria-controls": isActive && rendersPanel ? panelId(item.id) : void 0,
18840
18842
  "aria-disabled": isDisabled,
18841
18843
  tabIndex: isActive ? 0 : -1,
18842
18844
  onClick: () => !isDisabled && handleTabChange(item.id, item.event),
@@ -18896,7 +18898,7 @@ var init_Tabs = __esm({
18896
18898
  )
18897
18899
  ] })
18898
18900
  ] }) : tablist,
18899
- activeTabContent !== void 0 && activeTabContent !== null && /* @__PURE__ */ jsxRuntime.jsx(
18901
+ rendersPanel && /* @__PURE__ */ jsxRuntime.jsx(
18900
18902
  Box,
18901
18903
  {
18902
18904
  role: "tabpanel",
@@ -34207,8 +34209,11 @@ function DataGrid({
34207
34209
  children: [
34208
34210
  imageField && (() => {
34209
34211
  const imgUrl = resolveImageUrl(core.getNestedValue(itemData, imageField));
34210
- if (!imgUrl) return null;
34211
- return /* @__PURE__ */ jsxRuntime.jsx(Box, { className: asRows ? "w-12 h-12 flex-shrink-0 overflow-hidden rounded-container" : "w-full aspect-video overflow-hidden rounded-t-container", children: /* @__PURE__ */ jsxRuntime.jsx(
34212
+ const mediaClass = asRows ? "w-12 h-12 flex-shrink-0 overflow-hidden rounded-container" : "w-full aspect-video overflow-hidden rounded-t-container";
34213
+ if (!imgUrl) {
34214
+ return /* @__PURE__ */ jsxRuntime.jsx(Box, { "data-media-placeholder": true, "aria-hidden": "true", className: cn(mediaClass, "flex items-center justify-center bg-muted text-muted-foreground"), children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: "image", size: asRows ? "sm" : "lg" }) });
34215
+ }
34216
+ return /* @__PURE__ */ jsxRuntime.jsx(Box, { className: mediaClass, children: /* @__PURE__ */ jsxRuntime.jsx(
34212
34217
  "img",
34213
34218
  {
34214
34219
  src: imgUrl,
@@ -34241,7 +34246,7 @@ function DataGrid({
34241
34246
  Typography,
34242
34247
  {
34243
34248
  variant: titleField?.variant === "h3" && !asRows ? "h3" : "h4",
34244
- className: "font-semibold truncate min-w-0",
34249
+ className: cn("font-semibold min-w-0", asRows ? "truncate" : "line-clamp-2 break-words"),
34245
34250
  children: titleDisplay
34246
34251
  }
34247
34252
  )
@@ -34370,24 +34375,33 @@ var init_DataGrid = __esm({
34370
34375
  DataGrid.displayName = "DataGrid";
34371
34376
  }
34372
34377
  });
34373
- function renderIconInput2(icon, props) {
34374
- return typeof icon === "string" ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: icon, ...props }) : /* @__PURE__ */ jsxRuntime.jsx(Icon, { icon, ...props });
34375
- }
34376
- function formatValue2(value, format, fmt2, relationOptions) {
34377
- const relationDisplay = resolveRelationCellDisplay(value, relationOptions);
34378
- if (relationDisplay !== void 0) return relationDisplay;
34379
- return formatValue(value, format, fmt2);
34380
- }
34381
- function groupData(items, field) {
34378
+
34379
+ // lib/groupRows.ts
34380
+ function groupRows(items, field, format, fmt2 = {}) {
34382
34381
  const groups = /* @__PURE__ */ new Map();
34383
34382
  for (const item of items) {
34384
- const key = String(core.getNestedValue(item, field) ?? "");
34383
+ const raw = core.getNestedValue(item, field);
34384
+ const key = format ? formatValue(raw ?? void 0, format, fmt2) : String(raw ?? "");
34385
34385
  const group = groups.get(key);
34386
34386
  if (group) group.push(item);
34387
34387
  else groups.set(key, [item]);
34388
34388
  }
34389
34389
  return Array.from(groups.entries()).map(([label, groupItems]) => ({ label, items: groupItems }));
34390
34390
  }
34391
+ var init_groupRows = __esm({
34392
+ "lib/groupRows.ts"() {
34393
+ init_format();
34394
+ init_getNestedValue();
34395
+ }
34396
+ });
34397
+ function renderIconInput2(icon, props) {
34398
+ return typeof icon === "string" ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: icon, ...props }) : /* @__PURE__ */ jsxRuntime.jsx(Icon, { icon, ...props });
34399
+ }
34400
+ function formatValue2(value, format, fmt2, relationOptions) {
34401
+ const relationDisplay = resolveRelationCellDisplay(value, relationOptions);
34402
+ if (relationDisplay !== void 0) return relationDisplay;
34403
+ return formatValue(value, format, fmt2);
34404
+ }
34391
34405
  function DataList({
34392
34406
  entity,
34393
34407
  fields,
@@ -34398,6 +34412,7 @@ function DataList({
34398
34412
  gap = "none",
34399
34413
  variant = "default",
34400
34414
  groupBy,
34415
+ groupFormat,
34401
34416
  senderField,
34402
34417
  senderLabelField,
34403
34418
  currentUser,
@@ -34505,9 +34520,9 @@ function DataList({
34505
34520
  e.stopPropagation();
34506
34521
  fireRowAction(action, itemData, String(itemData.id ?? ""));
34507
34522
  };
34508
- const renderItemActions = (itemData, onPrimary = false) => {
34523
+ const renderItemActions = (itemData, onPrimary = false, only) => {
34509
34524
  if (!itemActions || itemActions.length === 0) return null;
34510
- const shown = rowActions(itemActions, itemData);
34525
+ const shown = only ?? rowActions(itemActions, itemData);
34511
34526
  if (shown.length === 0) return null;
34512
34527
  const inline = maxInlineActions != null ? shown.slice(0, maxInlineActions) : shown;
34513
34528
  const overflow = maxInlineActions != null ? shown.slice(maxInlineActions) : [];
@@ -34591,7 +34606,7 @@ function DataList({
34591
34606
  const isMessage = variant === "message";
34592
34607
  if (isMessage) {
34593
34608
  const items2 = [...data];
34594
- const groups2 = groupBy ? groupData(items2, groupBy) : [{ label: "", items: items2 }];
34609
+ const groups2 = groupBy ? groupRows(items2, groupBy, groupFormat, fmt2) : [{ label: "", items: items2 }];
34595
34610
  const contentField = (fieldDefs.find((f3) => f3.variant === "body") ?? titleField)?.name ?? "";
34596
34611
  const senderLabel = (itemData, raw) => {
34597
34612
  if (!senderLabelField) return raw;
@@ -34688,7 +34703,7 @@ function DataList({
34688
34703
  ] });
34689
34704
  }
34690
34705
  const items = [...data];
34691
- const groups = groupBy ? groupData(items, groupBy) : [{ label: "", items }];
34706
+ const groups = groupBy ? groupRows(items, groupBy, groupFormat, fmt2) : [{ label: "", items }];
34692
34707
  const idFieldName = dndItemIdField ?? "id";
34693
34708
  const renderItem = (itemData, index, isLast) => {
34694
34709
  const dndId = itemData[idFieldName] ?? `__idx_${index}`;
@@ -34699,7 +34714,11 @@ function DataList({
34699
34714
  const divider = (isCard || isCompact) && !isLast ? /* @__PURE__ */ jsxRuntime.jsx(Box, { className: cn("border-b border-border/40", isCompact ? "mx-4" : "mx-6") }) : null;
34700
34715
  if (hasRenderProp) {
34701
34716
  const id2 = itemData.id || String(index);
34702
- const actions = renderItemActions(itemData);
34717
+ const allActions = itemActions ? rowActions(itemActions, itemData) : [];
34718
+ const primaryActions = allActions.filter((a) => a.variant === "primary");
34719
+ const otherActions = allActions.filter((a) => a.variant !== "primary");
34720
+ const primary = primaryActions.length > 0 ? renderItemActions(itemData, false, primaryActions) : null;
34721
+ const actions = otherActions.length > 0 ? renderItemActions(itemData, false, otherActions) : null;
34703
34722
  return wrapDnd(
34704
34723
  /* @__PURE__ */ jsxRuntime.jsxs(
34705
34724
  Box,
@@ -34720,6 +34739,7 @@ function DataList({
34720
34739
  }
34721
34740
  ),
34722
34741
  /* @__PURE__ */ jsxRuntime.jsx(Box, { className: cn(onOpen && "relative"), children: itemRenderer(itemData, index) }),
34742
+ primary && /* @__PURE__ */ jsxRuntime.jsx(HStack, { justify: "end", className: cn("relative px-4 pb-3", STRETCHED_ABOVE), children: primary }),
34723
34743
  actions && /* @__PURE__ */ jsxRuntime.jsxs(Box, { onClick: (e) => e.stopPropagation(), className: "absolute top-2 right-2 z-10 opacity-0 group-hover/rowactions:opacity-100 focus-within:opacity-100 [@media(pointer:coarse)]:opacity-100 transition-opacity duration-fast", children: [
34724
34744
  /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "rounded-container border border-border bg-card/95 backdrop-blur-sm shadow-elevation-popover surface-material p-0.5 [@media(pointer:coarse)]:hidden", children: actions }),
34725
34745
  /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "hidden [@media(pointer:coarse)]:block rounded-container border border-border bg-card/95 backdrop-blur-sm shadow-elevation-popover surface-material p-0.5", children: /* @__PURE__ */ jsxRuntime.jsx(
@@ -34727,7 +34747,7 @@ function DataList({
34727
34747
  {
34728
34748
  position: "bottom-end",
34729
34749
  trigger: /* @__PURE__ */ jsxRuntime.jsx(Button, { variant: "ghost", size: "sm", "aria-label": t("common.actions"), "data-testid": "action-overflow", children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: "more-horizontal", size: "xs" }) }),
34730
- items: rowActions(itemActions ?? [], itemData).map((action) => ({
34750
+ items: otherActions.map((action) => ({
34731
34751
  label: action.label,
34732
34752
  icon: action.icon,
34733
34753
  variant: action.variant === "danger" ? "danger" : "default",
@@ -34918,6 +34938,7 @@ var init_DataList = __esm({
34918
34938
  init_format();
34919
34939
  init_relationLabel();
34920
34940
  init_getNestedValue();
34941
+ init_groupRows();
34921
34942
  init_useEventBus();
34922
34943
  init_useRowActions();
34923
34944
  init_Box();
@@ -35352,7 +35373,7 @@ var init_MapView = __esm({
35352
35373
  shadowSize: [41, 41]
35353
35374
  });
35354
35375
  L.Marker.prototype.options.icon = defaultIcon;
35355
- const { useEffect: useEffect82, useRef: useRef90, useCallback: useCallback100, useState: useState111 } = React98__namespace.default;
35376
+ const { useEffect: useEffect82, useRef: useRef90, useCallback: useCallback101, useState: useState111 } = React98__namespace.default;
35356
35377
  const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
35357
35378
  const { useEventBus: useEventBus2 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
35358
35379
  function MapUpdater({ centerLat, centerLng, zoom }) {
@@ -35401,7 +35422,7 @@ var init_MapView = __esm({
35401
35422
  const contentSurface = providers.useContentSurface(surface);
35402
35423
  const eventBus = useEventBus2();
35403
35424
  const [clickedPosition, setClickedPosition] = useState111(null);
35404
- const handleMapClick = useCallback100((lat, lng) => {
35425
+ const handleMapClick = useCallback101((lat, lng) => {
35405
35426
  if (showClickedPin) {
35406
35427
  setClickedPosition({ lat, lng });
35407
35428
  }
@@ -35410,7 +35431,7 @@ var init_MapView = __esm({
35410
35431
  eventBus.emit(`UI:${mapClickEvent}`, { latitude: lat, longitude: lng });
35411
35432
  }
35412
35433
  }, [onMapClick, mapClickEvent, eventBus, showClickedPin]);
35413
- const handleMarkerClick = useCallback100((marker) => {
35434
+ const handleMarkerClick = useCallback101((marker) => {
35414
35435
  onMarkerClick?.(marker);
35415
35436
  if (markerClickEvent) {
35416
35437
  eventBus.emit(`UI:${markerClickEvent}`, { ...marker });
@@ -36011,16 +36032,6 @@ function asFieldValue(v) {
36011
36032
  if (t === "object") return v;
36012
36033
  return void 0;
36013
36034
  }
36014
- function groupData2(items, field) {
36015
- const groups = /* @__PURE__ */ new Map();
36016
- for (const item of items) {
36017
- const key = String(core.getNestedValue(item, field) ?? "");
36018
- const group = groups.get(key);
36019
- if (group) group.push(item);
36020
- else groups.set(key, [item]);
36021
- }
36022
- return Array.from(groups.entries()).map(([label, groupItems]) => ({ label, items: groupItems }));
36023
- }
36024
36035
  function TableView({
36025
36036
  entity,
36026
36037
  columns,
@@ -36331,7 +36342,7 @@ function TableView({
36331
36342
  return dnd.isZone ? /* @__PURE__ */ jsxRuntime.jsx(dnd.SortableItem, { id: row[idField] ?? id, children: rowInner }, id) : /* @__PURE__ */ jsxRuntime.jsx(React98__namespace.default.Fragment, { children: rowInner }, id);
36332
36343
  };
36333
36344
  const items = Array.from(data);
36334
- const groups = groupBy ? groupData2(items, groupBy) : [{ label: "", items }];
36345
+ const groups = groupBy ? groupRows(items, groupBy) : [{ label: "", items }];
36335
36346
  let runningIndex = 0;
36336
36347
  const body = /* @__PURE__ */ jsxRuntime.jsx(Box, { role: "rowgroup", children: groups.map((group, gi) => /* @__PURE__ */ jsxRuntime.jsxs(React98__namespace.default.Fragment, { children: [
36337
36348
  group.label && /* @__PURE__ */ jsxRuntime.jsx(Divider, { label: group.label, className: gi > 0 ? "mt-3" : "mt-0" }),
@@ -36370,6 +36381,7 @@ var init_TableView = __esm({
36370
36381
  init_format();
36371
36382
  init_relationLabel();
36372
36383
  init_getNestedValue();
36384
+ init_groupRows();
36373
36385
  init_useEventBus();
36374
36386
  init_useRowActions();
36375
36387
  init_Box();
@@ -58089,6 +58101,22 @@ function useBusIngress(traitBindings, traitIndex, settle, eventBus, appTraitName
58089
58101
  });
58090
58102
  unsubscribes.push(unsub);
58091
58103
  }
58104
+ const routedBareEvents = /* @__PURE__ */ new Set();
58105
+ for (const binding of traitBindings) {
58106
+ for (const listen of binding.trait.listens ?? []) {
58107
+ if (listen.source !== void 0 && listen.source.kind !== "any") routedBareEvents.add(listen.event);
58108
+ }
58109
+ }
58110
+ for (const eventKey of routedBareEvents) {
58111
+ const unsub = eventBus.on(`UI:${eventKey}`, (event) => {
58112
+ if (deliveredHere(event.source) || event.source?.trait === void 0) return;
58113
+ for (const target of runtime.collectListenerTargets(traitIndex, event.source, eventKey, event.payload)) {
58114
+ log5.debug("listen-bare:fire", { event: eventKey, source: event.source.trait, listener: target.listenerTrait, triggers: target.triggers });
58115
+ dispatch(target.listenerTrait, target.triggers, target.payload, event.source);
58116
+ }
58117
+ });
58118
+ unsubscribes.push(unsub);
58119
+ }
58092
58120
  return () => {
58093
58121
  for (const unsub of unsubscribes) unsub();
58094
58122
  };
@@ -58999,9 +59027,16 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
58999
59027
  React98.useEffect(() => {
59000
59028
  if (!transport?.subscribe) return;
59001
59029
  return transport.subscribe((emitted, target) => {
59002
- for (const t2 of runtime.collectListenerTargets(traitIndex, emitted.source, emitted.event, emitted.payload)) {
59003
- void (target === "origin" ? progressAndSettle(t2.listenerTrait, t2.triggers, t2.payload) : dispatchAndSettle(t2.listenerTrait, t2.triggers, t2.payload));
59030
+ const listeners7 = runtime.collectListenerTargets(traitIndex, emitted.source, emitted.event, emitted.payload);
59031
+ if (target !== "origin") {
59032
+ for (const t2 of listeners7) void dispatchAndSettle(t2.listenerTrait, t2.triggers, t2.payload);
59033
+ return;
59004
59034
  }
59035
+ const caller = emitted.source?.trait;
59036
+ if (caller !== void 0 && traitIndex.byName.has(caller) && !listeners7.some((t2) => t2.listenerTrait === caller && t2.triggers === emitted.event)) {
59037
+ void progressAndSettle(caller, emitted.event, emitted.payload);
59038
+ }
59039
+ for (const t2 of listeners7) void progressAndSettle(t2.listenerTrait, t2.triggers, t2.payload);
59005
59040
  }, { clientId: getTabClientId() });
59006
59041
  }, [transport, traitIndex, progressAndSettle, dispatchAndSettle]);
59007
59042
  React98.useEffect(() => {
@@ -59011,7 +59046,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
59011
59046
  if (traitName === void 0 || !traitIndex.byName.has(traitName)) return;
59012
59047
  const composedBefore = new Map(store.callsitePayloads);
59013
59048
  void kernel.foldHostDispatch(request, response).then((outcome) => settleOutcome(traitName, request.event, request.payload, outcome, composedBefore));
59014
- });
59049
+ }, { clientId: getTabClientId() });
59015
59050
  }, [transport, traitIndex, kernel, store, settleOutcome]);
59016
59051
  const mountAndSettle = React98.useCallback(async (seeds, payload) => {
59017
59052
  const composedBefore = new Map(store.callsitePayloads);
@@ -59072,6 +59107,13 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
59072
59107
  prevActiveTraitNamesRef.current = nextActiveTraitNames;
59073
59108
  }, [traitBindings, uiSlots]);
59074
59109
  const mountedRef = React98.useRef(null);
59110
+ const aliveRef = React98.useRef(true);
59111
+ React98.useEffect(() => {
59112
+ aliveRef.current = true;
59113
+ return () => {
59114
+ aliveRef.current = false;
59115
+ };
59116
+ }, []);
59075
59117
  const mountKey = `${options.mountKey ?? ""}\0${JSON.stringify(Object.entries(options.initPayload ?? {}).sort(([a], [b]) => a.localeCompare(b)))}`;
59076
59118
  React98.useEffect(() => {
59077
59119
  const prev = mountedRef.current;
@@ -59102,6 +59144,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
59102
59144
  const failed = err instanceof runtime.TraitMountError ? err.trait : traits2.join(", ");
59103
59145
  const cause = err instanceof runtime.TraitMountError ? err.original : err;
59104
59146
  stateLog.warn("mount:failed", { traits: traits2, failed, error: message, stack: cause instanceof Error ? cause.stack : void 0 });
59147
+ if (!aliveRef.current) return;
59105
59148
  uiSlots.render({
59106
59149
  target: "main",
59107
59150
  pattern: "error-state",
@@ -59337,6 +59380,7 @@ function TraitInitializer({ traits: traits2, routeParams, mountKey, orbitals, on
59337
59380
  }
59338
59381
  var CONTENT_STAGE_WIDTH = 480;
59339
59382
  var NO_ORBITALS = [];
59383
+ var LazyPageOfRegisteredProgram = React98.createContext(false);
59340
59384
  function FitToBox({ children, mode = "box" }) {
59341
59385
  const outerRef = React98.useRef(null);
59342
59386
  const innerRef = React98.useRef(null);
@@ -59608,7 +59652,7 @@ function OrbPreview({
59608
59652
  if (localFallback) return;
59609
59653
  setLocalFallback(true);
59610
59654
  }, [localFallback]);
59611
- const hasOuterBridge = providers.useHasServerBridge();
59655
+ const isLazyPageOfRegisteredProgram = React98.useContext(LazyPageOfRegisteredProgram);
59612
59656
  const parseResult = React98.useMemo(() => {
59613
59657
  let parsed;
59614
59658
  if (typeof schema === "string") {
@@ -59632,7 +59676,7 @@ function OrbPreview({
59632
59676
  const persistence = React98.useMemo(() => {
59633
59677
  if (!parsedSchema || serverUrl || transport) return void 0;
59634
59678
  if (!autoMock) return void 0;
59635
- const adapter = new runtime.InMemoryPersistence();
59679
+ const adapter = new mock.InMemoryPersistence();
59636
59680
  adapter.seed(effectiveMockData);
59637
59681
  return adapter;
59638
59682
  }, [parsedSchema, serverUrl, transport, autoMock, effectiveMockData]);
@@ -59800,13 +59844,13 @@ function OrbPreview({
59800
59844
  navLog.info("interceptor:installed", { pageCount: pages.length, paths: pages.map((p) => p.page.path) });
59801
59845
  return () => el.removeEventListener("click", handler, true);
59802
59846
  }, [pages, handleNavigate, isolated, hostHrefBase]);
59803
- const withBridge = (node) => (serverUrl || transport) && !hasOuterBridge ? /* @__PURE__ */ jsxRuntime.jsx(providers.ServerBridgeProvider, { schema: parseResult.schema, serverUrl, transport, getAccessToken, children: node }) : node;
59847
+ const withBridge = (node) => (serverUrl || transport) && !isLazyPageOfRegisteredProgram ? /* @__PURE__ */ jsxRuntime.jsx(providers.ServerBridgeProvider, { schema: parseResult.schema, serverUrl, transport, getAccessToken, children: node }) : node;
59804
59848
  if (lazyRoute) {
59805
59849
  return withBridge(
59806
59850
  /* @__PURE__ */ jsxRuntime.jsxs(Box, { ref: containerRef, className: `overflow-auto ${className ?? ""}`, style: { height }, children: [
59807
59851
  lazyLoad.status === "loading" && /* @__PURE__ */ jsxRuntime.jsx(LoadingState, {}),
59808
59852
  lazyLoad.status === "error" && /* @__PURE__ */ jsxRuntime.jsx(ErrorState, { "data-testid": "lazy-page-error", message: lazyLoad.error }),
59809
- lazyLoad.status === "ready" && /* @__PURE__ */ jsxRuntime.jsx(
59853
+ lazyLoad.status === "ready" && /* @__PURE__ */ jsxRuntime.jsx(LazyPageOfRegisteredProgram.Provider, { value: true, children: /* @__PURE__ */ jsxRuntime.jsx(
59810
59854
  OrbPreview,
59811
59855
  {
59812
59856
  schema: lazyLoad.schema,
@@ -59826,7 +59870,7 @@ function OrbPreview({
59826
59870
  onUnmatchedNavigate: handleNavigate
59827
59871
  },
59828
59872
  lazyRoute.page.orbRef
59829
- )
59873
+ ) })
59830
59874
  ] })
59831
59875
  );
59832
59876
  }
@@ -59923,21 +59967,28 @@ function BrowserPlayground({
59923
59967
  runtime$1.resumeTicks();
59924
59968
  }
59925
59969
  }, [runtime$1, paused]);
59926
- const registrationReady = React98.useMemo(() => {
59927
- const orbitalNames = schema.orbitals.map((o) => o.name);
59928
- playgroundLog.debug("register:start", { schema: schema.name, orbitalNames });
59970
+ const lazySchemas = React98.useMemo(() => {
59929
59971
  const lazyPages = schema.lazyPages ?? [];
59930
- const lazy6 = lazyPages.length > 0 && lazyLoader !== void 0 ? Promise.all(lazyPages.map(async (page) => {
59972
+ if (lazyPages.length === 0 || lazyLoader === void 0) return Promise.resolve([]);
59973
+ return Promise.all(lazyPages.map(async (page) => {
59931
59974
  const loaded = await runtime.loadLazyPage(lazyLoader, page, schemaPath);
59932
59975
  if (!loaded.success) throw new Error(loaded.error);
59933
59976
  return loaded.data;
59934
- })) : Promise.resolve([]);
59935
- return lazy6.then(
59936
- (lazySchemas) => runtime$1.register(schema, { ...messages !== void 0 ? { messages } : {}, lazy: lazySchemas })
59937
- ).then(() => {
59938
- playgroundLog.debug("register:done", { schema: schema.name, orbitalNames });
59977
+ }));
59978
+ }, [schema.lazyPages, lazyLoader, schemaPath]);
59979
+ const registerProgram = React98.useCallback((program) => {
59980
+ const orbitalNames = program.orbitals.map((o) => o.name);
59981
+ playgroundLog.debug("register:start", { schema: program.name, orbitalNames });
59982
+ return lazySchemas.then((lazy6) => runtime$1.register(program, { ...messages !== void 0 ? { messages } : {}, lazy: lazy6 })).then(() => {
59983
+ playgroundLog.debug("register:done", { schema: program.name, orbitalNames });
59939
59984
  });
59940
- }, [runtime$1, schema, messages, lazyLoader, schemaPath]);
59985
+ }, [runtime$1, lazySchemas, messages]);
59986
+ const latestRegistration = React98.useRef(Promise.resolve());
59987
+ const registrationReady = React98.useMemo(() => {
59988
+ const ready = registerProgram(schema);
59989
+ latestRegistration.current = ready;
59990
+ return ready;
59991
+ }, [registerProgram, schema]);
59941
59992
  const teardownTimerRef = React98.useRef(null);
59942
59993
  React98.useEffect(() => {
59943
59994
  if (teardownTimerRef.current !== null) {
@@ -59955,18 +60006,22 @@ function BrowserPlayground({
59955
60006
  const transport = React98.useMemo(
59956
60007
  () => runtime.createInProcessTransport(
59957
60008
  async (orbitalName, request) => {
59958
- await registrationReady;
60009
+ await latestRegistration.current;
59959
60010
  return runtime$1.processOrbitalEvent(orbitalName, request);
59960
60011
  },
59961
60012
  {
59962
- // The program (lazy behaviors included) is registered above; the bridge only waits for it.
59963
- onRegister: () => registrationReady,
60013
+ // Registers what the bridge hands over (lazy behaviors included): a bridge that unregistered first gets it back.
60014
+ onRegister: (program) => {
60015
+ const ready = registerProgram(program);
60016
+ latestRegistration.current = ready;
60017
+ return ready;
60018
+ },
59964
60019
  onUnregister: () => {
59965
60020
  runtime$1.unregisterAll();
59966
60021
  }
59967
60022
  }
59968
60023
  ),
59969
- [runtime$1, registrationReady]
60024
+ [runtime$1, registerProgram, registrationReady]
59970
60025
  );
59971
60026
  const viewerLocale = locale ?? schema.locales?.[0];
59972
60027
  const i18n$1 = React98.useMemo(() => {
@@ -1,9 +1,9 @@
1
- import { EventPayload, OrbitalDefinition, ServiceParams, TraitConfig, UserContext, ResolvedTraitBinding, ResolvedPage, ResolvedEntity, ResolvedTrait, ResolvedIR, OrbitalSchema, PatternConfig, ResolvedPatternProps, EventSource, SExpr, EntityData, MessageCatalogs } from '@almadar/core';
1
+ import { EventPayload, OrbitalDefinition, PersistenceAdapter, ServiceParams, TraitConfig, UserContext, ResolvedTraitBinding, ResolvedPage, ResolvedEntity, ResolvedTrait, ResolvedIR, OrbitalSchema, PatternConfig, ResolvedPatternProps, EventSource, SExpr, EntityData, MessageCatalogs } from '@almadar/core';
2
2
  export { ResolvedEntity, ResolvedIR, ResolvedPage, ResolvedTrait, ResolvedTraitBinding } from '@almadar/core';
3
- import { TraitState, EventTransport, PersistenceAdapter, AccessTokenProvider, SchemaLoader } from '@almadar/runtime';
3
+ import { TraitState, EventTransport, AccessTokenProvider, SchemaLoader } from '@almadar/runtime';
4
4
  export { AccessTokenProvider, ClientEventBus, CreateClientEffectHandlersOptions, SlotSetter, createClientEffectHandlers } from '@almadar/runtime';
5
- import { E as EntityBindingSource, A as AwaitingSkeletonSource, S as ServerBridgeTransport } from '../AwaitingSkeletonContext-DPgW__WV.js';
6
- export { a as EntitySchemaContextValue, b as EntitySchemaProvider, c as EntitySchemaProviderProps, d as ServerBridgeContextValue, e as ServerBridgeProvider, T as TraitContext, f as TraitContextValue, g as TraitInstance, h as TraitProvider, i as TraitProviderProps, u as useEntitySchema, j as useEntitySchemaOptional, k as useServerBridge, l as useTrait, m as useTraitContext } from '../AwaitingSkeletonContext-DPgW__WV.js';
5
+ import { E as EntityBindingSource, A as AwaitingSkeletonSource, S as ServerBridgeTransport } from '../AwaitingSkeletonContext-Bh399p1x.js';
6
+ export { a as EntitySchemaContextValue, b as EntitySchemaProvider, c as EntitySchemaProviderProps, d as ServerBridgeContextValue, e as ServerBridgeProvider, T as TraitContext, f as TraitContextValue, g as TraitInstance, h as TraitProvider, i as TraitProviderProps, u as useEntitySchema, j as useEntitySchemaOptional, k as useServerBridge, l as useTrait, m as useTraitContext } from '../AwaitingSkeletonContext-Bh399p1x.js';
7
7
  import { c as useUISlots } from '../UISlotContext-CS487Uoc.js';
8
8
  export { PERF_NAMESPACE, PerfEntry, PreparedPreviewSchema, adjustSchemaForMockData, buildMockData, clearPerf, perfEnd, perfStart, perfTime, prepareSchemaForPreview, wrapCallbackForEvent } from '@almadar/runtime/ui';
9
9
  import React__default, { ReactNode } from 'react';
@@ -1,9 +1,9 @@
1
- export { BrowserPlayground, OrbPreview, adjustSchemaForMockData, buildMockData, clearSchemaCache, prepareSchemaForPreview, useResolvedSchema, useTraitStateMachine } from '../chunk-RHP5WL55.js';
1
+ export { BrowserPlayground, OrbPreview, adjustSchemaForMockData, buildMockData, clearSchemaCache, prepareSchemaForPreview, useResolvedSchema, useTraitStateMachine } from '../chunk-HB3D3HUJ.js';
2
2
  export { assertUniqueSlotsPerHost } from '../chunk-O2EIWXWE.js';
3
3
  import '../chunk-N7JIG57B.js';
4
4
  import '../chunk-VHTJRS2N.js';
5
5
  import '../chunk-YYYHH5BA.js';
6
- export { wrapCallbackForEvent } from '../chunk-PYJ2UQWM.js';
6
+ export { wrapCallbackForEvent } from '../chunk-I2ZNE5TD.js';
7
7
  import '../chunk-HA7CJWQX.js';
8
8
  import '../chunk-4ZGXIW3B.js';
9
9
  import '../chunk-I5QOYW2Z.js';
@@ -1,4 +1,4 @@
1
- import { D as DrawableNode } from './paintDispatch-_6EhJCiL.js';
1
+ import { D as DrawableNode } from './paintDispatch-BN8Vbzgs.js';
2
2
  import { OrbitalVerificationAPI, TraitStateSnapshot, EventPayload, BusEvent, VerificationCheck, BridgeHealth, VerificationSnapshot, VerificationSummary, TransitionTrace, OrbitalEventRequest, OrbitalEventResponse, ServerResponseTrace, EffectTrace, CheckStatus, ServerEffectResult, AssetLoadStatus } from '@almadar/core';
3
3
  import { EventTransport } from '@almadar/runtime';
4
4
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@almadar/ui",
3
- "version": "6.57.0",
3
+ "version": "6.58.0",
4
4
  "description": "React UI components, hooks, and providers for Almadar",
5
5
  "type": "module",
6
6
  "sideEffects": [
@@ -126,12 +126,13 @@
126
126
  "access": "public"
127
127
  },
128
128
  "dependencies": {
129
- "@almadar/core": "^10.119.0",
130
- "@almadar/evaluator": "^2.55.0",
131
- "@almadar/logger": "^1.16.0",
132
- "@almadar/runtime": "^6.104.0",
133
- "@almadar/std": "^16.244.0",
134
- "@almadar/syntax": "^1.19.0",
129
+ "@almadar/core": "^10.120.0",
130
+ "@almadar/db": "^0.1.1",
131
+ "@almadar/evaluator": "^2.55.1",
132
+ "@almadar/logger": "^1.17.0",
133
+ "@almadar/runtime": "^6.105.0",
134
+ "@almadar/std": "^16.245.0",
135
+ "@almadar/syntax": "^1.19.1",
135
136
  "@dnd-kit/core": "^6.3.1",
136
137
  "@dnd-kit/sortable": "^10.0.0",
137
138
  "@dnd-kit/utilities": "^3.2.2",
@@ -191,7 +192,7 @@
191
192
  }
192
193
  },
193
194
  "devDependencies": {
194
- "@almadar-io/behaviors": "^0.16.191",
195
+ "@almadar-io/behaviors": "^0.16.193",
195
196
  "@almadar/eslint-plugin": "^2.21.0",
196
197
  "@react-three/drei": "^10.7.7",
197
198
  "@react-three/fiber": "^9.6.0",