@almadar/ui 6.57.0 → 6.59.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.
Files changed (32) hide show
  1. package/dist/{AwaitingSkeletonContext-DPgW__WV.d.ts → AwaitingSkeletonContext-Bh399p1x.d.ts} +1 -3
  2. package/dist/{Canvas3DHost-DfAhg6EH.d.ts → Canvas3DHost-CNjANoaU.d.ts} +1 -1
  3. package/dist/{GameAudioProvider-DyBvYP2c.d.ts → GameAudioProvider-Dv_L-PHt.d.ts} +1 -1
  4. package/dist/{UISlotRenderer-NCGDIXN4.js → UISlotRenderer-YNY7V2UJ.js} +2 -2
  5. package/dist/avl/index.cjs +137 -71
  6. package/dist/avl/index.js +24 -8
  7. package/dist/{chunk-GZGDBS4S.js → chunk-7CVXM2KS.js} +1 -1
  8. package/dist/{chunk-PYJ2UQWM.js → chunk-E6MWYQVZ.js} +42 -35
  9. package/dist/{chunk-HA7CJWQX.js → chunk-J755QADM.js} +1184 -1184
  10. package/dist/{chunk-VHTJRS2N.js → chunk-L3MTZ3RH.js} +7 -0
  11. package/dist/{chunk-RHP5WL55.js → chunk-QJIAJ6EH.js} +77 -42
  12. package/dist/components/index.cjs +76 -32
  13. package/dist/components/index.d.ts +9 -7
  14. package/dist/components/index.js +5 -5
  15. package/dist/context/index.cjs +7 -0
  16. package/dist/context/index.js +1 -1
  17. package/dist/hooks/index.cjs +7 -0
  18. package/dist/hooks/index.js +1 -1
  19. package/dist/lib/drawable/three/index.d.ts +3 -3
  20. package/dist/lib/drawable/three/index.js +3 -3
  21. package/dist/lib/index.d.ts +2 -2
  22. package/dist/{paintDispatch-_6EhJCiL.d.ts → paintDispatch-Cp1_S93j.d.ts} +30 -2
  23. package/dist/providers/index.cjs +51 -50
  24. package/dist/providers/index.d.ts +4 -4
  25. package/dist/providers/index.js +8 -21
  26. package/dist/runtime/index.cjs +120 -70
  27. package/dist/runtime/index.d.ts +4 -4
  28. package/dist/runtime/index.js +4 -4
  29. package/dist/ssr/index.cjs +2 -0
  30. package/dist/ssr/index.js +2 -0
  31. package/dist/{verificationRegistry-CD7Xb40L.d.ts → verificationRegistry-B3dj1Zl8.d.ts} +1 -1
  32. package/package.json +9 -8
@@ -108,8 +108,6 @@ interface ServerBridgeContextValue {
108
108
  */
109
109
  type ServerBridgeTransport = EventTransport;
110
110
 
111
- /** Whether a `ServerBridgeProvider` is already above — a nested preview (a lazy page) reuses its registration. */
112
- declare function useHasServerBridge(): boolean;
113
111
  /**
114
112
  * Access the server bridge. Returns a no-op stub when outside the provider —
115
113
  * `useCircuitKernel` treats an absent/no-op transport as offline (plan G7).
@@ -230,4 +228,4 @@ declare function useAwaitingSkeleton(target: {
230
228
  trait: string;
231
229
  }): SkeletonNode | undefined;
232
230
 
233
- export { type AwaitingSkeletonSource as A, type EntityBindingSource as E, type ServerBridgeTransport as S, TraitContext as T, type EntitySchemaContextValue as a, EntitySchemaProvider as b, type EntitySchemaProviderProps as c, type ServerBridgeContextValue as d, ServerBridgeProvider as e, type TraitContextValue as f, type TraitInstance as g, TraitProvider as h, type TraitProviderProps as i, useEntitySchemaOptional as j, useServerBridge as k, useTrait as l, useTraitContext as m, AwaitingSkeletonContext as n, EntityBindingContext as o, type ServerBridgeProviderProps as p, useAwaitingSkeleton as q, useEntityBindingSnapshot as r, useHasServerBridge as s, useEntitySchema as u };
231
+ export { type AwaitingSkeletonSource as A, type EntityBindingSource as E, type ServerBridgeTransport as S, TraitContext as T, type EntitySchemaContextValue as a, EntitySchemaProvider as b, type EntitySchemaProviderProps as c, type ServerBridgeContextValue as d, ServerBridgeProvider as e, type TraitContextValue as f, type TraitInstance as g, TraitProvider as h, type TraitProviderProps as i, useEntitySchemaOptional as j, useServerBridge as k, useTrait as l, useTraitContext as m, AwaitingSkeletonContext as n, EntityBindingContext as o, type ServerBridgeProviderProps as p, useAwaitingSkeleton as q, useEntityBindingSnapshot as r, useEntitySchema as u };
@@ -1,7 +1,7 @@
1
1
  import { AnimationName, Asset, ScenePos, EventEmit, EventKey } from '@almadar/core';
2
2
  import React__default from 'react';
3
3
  import * as THREE from 'three';
4
- import { D as DrawableNode } from './paintDispatch-_6EhJCiL.js';
4
+ import { D as DrawableNode } from './paintDispatch-Cp1_S93j.js';
5
5
 
6
6
  /**
7
7
  * Sprite Sheet Animation Types
@@ -1,6 +1,6 @@
1
1
  import React__default from 'react';
2
2
  import { AudioManifest } from '@almadar/core';
3
- import { U as UiError } from './paintDispatch-_6EhJCiL.js';
3
+ import { U as UiError } from './paintDispatch-Cp1_S93j.js';
4
4
 
5
5
  /** Core owns the sound-manifest shape (`@almadar/core` `types/asset.ts`) so the
6
6
  * pattern extractor and the generated `.lolo` factories resolve the same
@@ -1,5 +1,5 @@
1
- export { SlotContainedContext, SlotContentRenderer, SuspenseConfigProvider, UISlotComponent, UISlotRenderer, renderPatternValue } from './chunk-PYJ2UQWM.js';
2
- import './chunk-HA7CJWQX.js';
1
+ export { SlotContainedContext, SlotContentRenderer, SuspenseConfigProvider, UISlotComponent, UISlotRenderer, renderPatternValue } from './chunk-E6MWYQVZ.js';
2
+ import './chunk-J755QADM.js';
3
3
  import './chunk-4ZGXIW3B.js';
4
4
  import './chunk-I5QOYW2Z.js';
5
5
  import './chunk-XJTHMW4G.js';
@@ -78,6 +78,7 @@ var utilities = require('@dnd-kit/utilities');
78
78
  var emojilib = require('emojilib');
79
79
  var d3Force = require('d3-force');
80
80
  var OrbitalServerRuntime = require('@almadar/runtime/OrbitalServerRuntime');
81
+ var mock = require('@almadar/db/mock');
81
82
 
82
83
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
83
84
 
@@ -614,8 +615,10 @@ var init_AvlFieldType = __esm({
614
615
  pattern: "hexagon",
615
616
  node: "hexagon",
616
617
  event: "hexagon",
618
+ EventAddress: "hexagon",
617
619
  SExpr: "hexagon",
618
620
  array: "bars",
621
+ tuple: "bars",
619
622
  relation: "link"
620
623
  };
621
624
  exports.AvlFieldType = ({
@@ -12178,6 +12181,7 @@ var init_Avatar = __esm({
12178
12181
  statusClasses[status],
12179
12182
  statusSizeClasses[size2]
12180
12183
  ),
12184
+ role: "img",
12181
12185
  "aria-label": t("avatar.status", { status: t(`avatar.status.${status}`) })
12182
12186
  }
12183
12187
  ),
@@ -14883,6 +14887,7 @@ var init_AnimatedGraphic = __esm({
14883
14887
  "div",
14884
14888
  {
14885
14889
  className: "w-full h-full [&>svg]:w-full [&>svg]:h-full",
14890
+ "aria-hidden": "true",
14886
14891
  dangerouslySetInnerHTML: { __html: resolvedSvg }
14887
14892
  }
14888
14893
  ) : children
@@ -17004,6 +17009,7 @@ var init_Tabs = __esm({
17004
17009
  }
17005
17010
  };
17006
17011
  const activeTabContent = safeItems.find((item) => item.id === activeTab)?.content;
17012
+ const rendersPanel = activeTabContent !== void 0 && activeTabContent !== null;
17007
17013
  if (safeItems.length === 0) {
17008
17014
  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") }) });
17009
17015
  }
@@ -17054,7 +17060,7 @@ var init_Tabs = __esm({
17054
17060
  id: tabId(item.id),
17055
17061
  role: "tab",
17056
17062
  "aria-selected": isActive,
17057
- "aria-controls": isActive ? panelId(item.id) : void 0,
17063
+ "aria-controls": isActive && rendersPanel ? panelId(item.id) : void 0,
17058
17064
  "aria-disabled": isDisabled,
17059
17065
  tabIndex: isActive ? 0 : -1,
17060
17066
  onClick: () => !isDisabled && handleTabChange(item.id, item.event),
@@ -17114,7 +17120,7 @@ var init_Tabs = __esm({
17114
17120
  )
17115
17121
  ] })
17116
17122
  ] }) : tablist,
17117
- activeTabContent !== void 0 && activeTabContent !== null && /* @__PURE__ */ jsxRuntime.jsx(
17123
+ rendersPanel && /* @__PURE__ */ jsxRuntime.jsx(
17118
17124
  Box,
17119
17125
  {
17120
17126
  role: "tabpanel",
@@ -35137,8 +35143,11 @@ function DataGrid({
35137
35143
  children: [
35138
35144
  imageField && (() => {
35139
35145
  const imgUrl = resolveImageUrl(core.getNestedValue(itemData, imageField));
35140
- if (!imgUrl) return null;
35141
- 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(
35146
+ const mediaClass = asRows ? "w-12 h-12 flex-shrink-0 overflow-hidden rounded-container" : "w-full aspect-video overflow-hidden rounded-t-container";
35147
+ if (!imgUrl) {
35148
+ 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" }) });
35149
+ }
35150
+ return /* @__PURE__ */ jsxRuntime.jsx(Box, { className: mediaClass, children: /* @__PURE__ */ jsxRuntime.jsx(
35142
35151
  "img",
35143
35152
  {
35144
35153
  src: imgUrl,
@@ -35171,7 +35180,7 @@ function DataGrid({
35171
35180
  Typography,
35172
35181
  {
35173
35182
  variant: titleField?.variant === "h3" && !asRows ? "h3" : "h4",
35174
- className: "font-semibold truncate min-w-0",
35183
+ className: cn("font-semibold min-w-0", asRows ? "truncate" : "line-clamp-2 break-words"),
35175
35184
  children: titleDisplay
35176
35185
  }
35177
35186
  )
@@ -35300,24 +35309,33 @@ var init_DataGrid = __esm({
35300
35309
  DataGrid.displayName = "DataGrid";
35301
35310
  }
35302
35311
  });
35303
- function renderIconInput2(icon, props) {
35304
- return typeof icon === "string" ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: icon, ...props }) : /* @__PURE__ */ jsxRuntime.jsx(Icon, { icon, ...props });
35305
- }
35306
- function formatValue2(value, format, fmt2, relationOptions) {
35307
- const relationDisplay = resolveRelationCellDisplay(value, relationOptions);
35308
- if (relationDisplay !== void 0) return relationDisplay;
35309
- return formatValue(value, format, fmt2);
35310
- }
35311
- function groupData(items, field) {
35312
+
35313
+ // lib/groupRows.ts
35314
+ function groupRows(items, field, format, fmt2 = {}) {
35312
35315
  const groups = /* @__PURE__ */ new Map();
35313
35316
  for (const item of items) {
35314
- const key = String(core.getNestedValue(item, field) ?? "");
35317
+ const raw = core.getNestedValue(item, field);
35318
+ const key = format ? formatValue(raw ?? void 0, format, fmt2) : String(raw ?? "");
35315
35319
  const group = groups.get(key);
35316
35320
  if (group) group.push(item);
35317
35321
  else groups.set(key, [item]);
35318
35322
  }
35319
35323
  return Array.from(groups.entries()).map(([label, groupItems]) => ({ label, items: groupItems }));
35320
35324
  }
35325
+ var init_groupRows = __esm({
35326
+ "lib/groupRows.ts"() {
35327
+ init_format();
35328
+ init_getNestedValue();
35329
+ }
35330
+ });
35331
+ function renderIconInput2(icon, props) {
35332
+ return typeof icon === "string" ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: icon, ...props }) : /* @__PURE__ */ jsxRuntime.jsx(Icon, { icon, ...props });
35333
+ }
35334
+ function formatValue2(value, format, fmt2, relationOptions) {
35335
+ const relationDisplay = resolveRelationCellDisplay(value, relationOptions);
35336
+ if (relationDisplay !== void 0) return relationDisplay;
35337
+ return formatValue(value, format, fmt2);
35338
+ }
35321
35339
  function DataList({
35322
35340
  entity,
35323
35341
  fields,
@@ -35328,6 +35346,7 @@ function DataList({
35328
35346
  gap = "none",
35329
35347
  variant = "default",
35330
35348
  groupBy,
35349
+ groupFormat,
35331
35350
  senderField,
35332
35351
  senderLabelField,
35333
35352
  currentUser,
@@ -35435,9 +35454,9 @@ function DataList({
35435
35454
  e.stopPropagation();
35436
35455
  fireRowAction(action, itemData, String(itemData.id ?? ""));
35437
35456
  };
35438
- const renderItemActions = (itemData, onPrimary = false) => {
35457
+ const renderItemActions = (itemData, onPrimary = false, only) => {
35439
35458
  if (!itemActions || itemActions.length === 0) return null;
35440
- const shown = rowActions(itemActions, itemData);
35459
+ const shown = only ?? rowActions(itemActions, itemData);
35441
35460
  if (shown.length === 0) return null;
35442
35461
  const inline = maxInlineActions != null ? shown.slice(0, maxInlineActions) : shown;
35443
35462
  const overflow = maxInlineActions != null ? shown.slice(maxInlineActions) : [];
@@ -35521,7 +35540,7 @@ function DataList({
35521
35540
  const isMessage = variant === "message";
35522
35541
  if (isMessage) {
35523
35542
  const items2 = [...data];
35524
- const groups2 = groupBy ? groupData(items2, groupBy) : [{ label: "", items: items2 }];
35543
+ const groups2 = groupBy ? groupRows(items2, groupBy, groupFormat, fmt2) : [{ label: "", items: items2 }];
35525
35544
  const contentField = (fieldDefs.find((f3) => f3.variant === "body") ?? titleField)?.name ?? "";
35526
35545
  const senderLabel = (itemData, raw) => {
35527
35546
  if (!senderLabelField) return raw;
@@ -35618,7 +35637,7 @@ function DataList({
35618
35637
  ] });
35619
35638
  }
35620
35639
  const items = [...data];
35621
- const groups = groupBy ? groupData(items, groupBy) : [{ label: "", items }];
35640
+ const groups = groupBy ? groupRows(items, groupBy, groupFormat, fmt2) : [{ label: "", items }];
35622
35641
  const idFieldName = dndItemIdField ?? "id";
35623
35642
  const renderItem = (itemData, index, isLast) => {
35624
35643
  const dndId = itemData[idFieldName] ?? `__idx_${index}`;
@@ -35629,7 +35648,11 @@ function DataList({
35629
35648
  const divider = (isCard || isCompact) && !isLast ? /* @__PURE__ */ jsxRuntime.jsx(Box, { className: cn("border-b border-border/40", isCompact ? "mx-4" : "mx-6") }) : null;
35630
35649
  if (hasRenderProp) {
35631
35650
  const id2 = itemData.id || String(index);
35632
- const actions = renderItemActions(itemData);
35651
+ const allActions = itemActions ? rowActions(itemActions, itemData) : [];
35652
+ const primaryActions = allActions.filter((a) => a.variant === "primary");
35653
+ const otherActions = allActions.filter((a) => a.variant !== "primary");
35654
+ const primary = primaryActions.length > 0 ? renderItemActions(itemData, false, primaryActions) : null;
35655
+ const actions = otherActions.length > 0 ? renderItemActions(itemData, false, otherActions) : null;
35633
35656
  return wrapDnd(
35634
35657
  /* @__PURE__ */ jsxRuntime.jsxs(
35635
35658
  Box,
@@ -35650,6 +35673,7 @@ function DataList({
35650
35673
  }
35651
35674
  ),
35652
35675
  /* @__PURE__ */ jsxRuntime.jsx(Box, { className: cn(onOpen && "relative"), children: itemRenderer(itemData, index) }),
35676
+ primary && /* @__PURE__ */ jsxRuntime.jsx(HStack, { justify: "end", className: cn("relative px-4 pb-3", STRETCHED_ABOVE), children: primary }),
35653
35677
  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: [
35654
35678
  /* @__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 }),
35655
35679
  /* @__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(
@@ -35657,7 +35681,7 @@ function DataList({
35657
35681
  {
35658
35682
  position: "bottom-end",
35659
35683
  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" }) }),
35660
- items: rowActions(itemActions ?? [], itemData).map((action) => ({
35684
+ items: otherActions.map((action) => ({
35661
35685
  label: action.label,
35662
35686
  icon: action.icon,
35663
35687
  variant: action.variant === "danger" ? "danger" : "default",
@@ -35848,6 +35872,7 @@ var init_DataList = __esm({
35848
35872
  init_format();
35849
35873
  init_relationLabel();
35850
35874
  init_getNestedValue();
35875
+ init_groupRows();
35851
35876
  init_useEventBus();
35852
35877
  init_useRowActions();
35853
35878
  init_Box();
@@ -36282,7 +36307,7 @@ var init_MapView = __esm({
36282
36307
  shadowSize: [41, 41]
36283
36308
  });
36284
36309
  L.Marker.prototype.options.icon = defaultIcon;
36285
- const { useEffect: useEffect85, useRef: useRef90, useCallback: useCallback108, useState: useState120 } = React96__namespace.default;
36310
+ const { useEffect: useEffect85, useRef: useRef90, useCallback: useCallback109, useState: useState120 } = React96__namespace.default;
36286
36311
  const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
36287
36312
  const { useEventBus: useEventBus2 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
36288
36313
  function MapUpdater({ centerLat, centerLng, zoom }) {
@@ -36331,7 +36356,7 @@ var init_MapView = __esm({
36331
36356
  const contentSurface = providers.useContentSurface(surface);
36332
36357
  const eventBus = useEventBus2();
36333
36358
  const [clickedPosition, setClickedPosition] = useState120(null);
36334
- const handleMapClick = useCallback108((lat, lng) => {
36359
+ const handleMapClick = useCallback109((lat, lng) => {
36335
36360
  if (showClickedPin) {
36336
36361
  setClickedPosition({ lat, lng });
36337
36362
  }
@@ -36340,7 +36365,7 @@ var init_MapView = __esm({
36340
36365
  eventBus.emit(`UI:${mapClickEvent}`, { latitude: lat, longitude: lng });
36341
36366
  }
36342
36367
  }, [onMapClick, mapClickEvent, eventBus, showClickedPin]);
36343
- const handleMarkerClick = useCallback108((marker) => {
36368
+ const handleMarkerClick = useCallback109((marker) => {
36344
36369
  onMarkerClick?.(marker);
36345
36370
  if (markerClickEvent) {
36346
36371
  eventBus.emit(`UI:${markerClickEvent}`, { ...marker });
@@ -36941,16 +36966,6 @@ function asFieldValue(v) {
36941
36966
  if (t === "object") return v;
36942
36967
  return void 0;
36943
36968
  }
36944
- function groupData2(items, field) {
36945
- const groups = /* @__PURE__ */ new Map();
36946
- for (const item of items) {
36947
- const key = String(core.getNestedValue(item, field) ?? "");
36948
- const group = groups.get(key);
36949
- if (group) group.push(item);
36950
- else groups.set(key, [item]);
36951
- }
36952
- return Array.from(groups.entries()).map(([label, groupItems]) => ({ label, items: groupItems }));
36953
- }
36954
36969
  function TableView({
36955
36970
  entity,
36956
36971
  columns,
@@ -37261,7 +37276,7 @@ function TableView({
37261
37276
  return dnd.isZone ? /* @__PURE__ */ jsxRuntime.jsx(dnd.SortableItem, { id: row[idField] ?? id, children: rowInner }, id) : /* @__PURE__ */ jsxRuntime.jsx(React96__namespace.default.Fragment, { children: rowInner }, id);
37262
37277
  };
37263
37278
  const items = Array.from(data);
37264
- const groups = groupBy ? groupData2(items, groupBy) : [{ label: "", items }];
37279
+ const groups = groupBy ? groupRows(items, groupBy) : [{ label: "", items }];
37265
37280
  let runningIndex = 0;
37266
37281
  const body = /* @__PURE__ */ jsxRuntime.jsx(Box, { role: "rowgroup", children: groups.map((group, gi) => /* @__PURE__ */ jsxRuntime.jsxs(React96__namespace.default.Fragment, { children: [
37267
37282
  group.label && /* @__PURE__ */ jsxRuntime.jsx(Divider, { label: group.label, className: gi > 0 ? "mt-3" : "mt-0" }),
@@ -37300,6 +37315,7 @@ var init_TableView = __esm({
37300
37315
  init_format();
37301
37316
  init_relationLabel();
37302
37317
  init_getNestedValue();
37318
+ init_groupRows();
37303
37319
  init_useEventBus();
37304
37320
  init_useRowActions();
37305
37321
  init_Box();
@@ -64609,6 +64625,22 @@ function useBusIngress(traitBindings, traitIndex, settle, eventBus, appTraitName
64609
64625
  });
64610
64626
  unsubscribes.push(unsub);
64611
64627
  }
64628
+ const routedBareEvents = /* @__PURE__ */ new Set();
64629
+ for (const binding of traitBindings) {
64630
+ for (const listen of binding.trait.listens ?? []) {
64631
+ if (listen.source !== void 0 && listen.source.kind !== "any") routedBareEvents.add(listen.event);
64632
+ }
64633
+ }
64634
+ for (const eventKey of routedBareEvents) {
64635
+ const unsub = eventBus.on(`UI:${eventKey}`, (event) => {
64636
+ if (deliveredHere(event.source) || event.source?.trait === void 0) return;
64637
+ for (const target of runtime.collectListenerTargets(traitIndex, event.source, eventKey, event.payload)) {
64638
+ log13.debug("listen-bare:fire", { event: eventKey, source: event.source.trait, listener: target.listenerTrait, triggers: target.triggers });
64639
+ dispatch(target.listenerTrait, target.triggers, target.payload, event.source);
64640
+ }
64641
+ });
64642
+ unsubscribes.push(unsub);
64643
+ }
64612
64644
  return () => {
64613
64645
  for (const unsub of unsubscribes) unsub();
64614
64646
  };
@@ -65519,9 +65551,16 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
65519
65551
  React96.useEffect(() => {
65520
65552
  if (!transport?.subscribe) return;
65521
65553
  return transport.subscribe((emitted, target) => {
65522
- for (const t2 of runtime.collectListenerTargets(traitIndex, emitted.source, emitted.event, emitted.payload)) {
65523
- void (target === "origin" ? progressAndSettle(t2.listenerTrait, t2.triggers, t2.payload) : dispatchAndSettle(t2.listenerTrait, t2.triggers, t2.payload));
65554
+ const listeners7 = runtime.collectListenerTargets(traitIndex, emitted.source, emitted.event, emitted.payload);
65555
+ if (target !== "origin") {
65556
+ for (const t2 of listeners7) void dispatchAndSettle(t2.listenerTrait, t2.triggers, t2.payload);
65557
+ return;
65558
+ }
65559
+ const caller = emitted.source?.trait;
65560
+ if (caller !== void 0 && traitIndex.byName.has(caller) && !listeners7.some((t2) => t2.listenerTrait === caller && t2.triggers === emitted.event)) {
65561
+ void progressAndSettle(caller, emitted.event, emitted.payload);
65524
65562
  }
65563
+ for (const t2 of listeners7) void progressAndSettle(t2.listenerTrait, t2.triggers, t2.payload);
65525
65564
  }, { clientId: getTabClientId() });
65526
65565
  }, [transport, traitIndex, progressAndSettle, dispatchAndSettle]);
65527
65566
  React96.useEffect(() => {
@@ -65531,7 +65570,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
65531
65570
  if (traitName === void 0 || !traitIndex.byName.has(traitName)) return;
65532
65571
  const composedBefore = new Map(store.callsitePayloads);
65533
65572
  void kernel.foldHostDispatch(request, response).then((outcome) => settleOutcome(traitName, request.event, request.payload, outcome, composedBefore));
65534
- });
65573
+ }, { clientId: getTabClientId() });
65535
65574
  }, [transport, traitIndex, kernel, store, settleOutcome]);
65536
65575
  const mountAndSettle = React96.useCallback(async (seeds, payload) => {
65537
65576
  const composedBefore = new Map(store.callsitePayloads);
@@ -65592,6 +65631,13 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
65592
65631
  prevActiveTraitNamesRef.current = nextActiveTraitNames;
65593
65632
  }, [traitBindings, uiSlots]);
65594
65633
  const mountedRef = React96.useRef(null);
65634
+ const aliveRef = React96.useRef(true);
65635
+ React96.useEffect(() => {
65636
+ aliveRef.current = true;
65637
+ return () => {
65638
+ aliveRef.current = false;
65639
+ };
65640
+ }, []);
65595
65641
  const mountKey = `${options.mountKey ?? ""}\0${JSON.stringify(Object.entries(options.initPayload ?? {}).sort(([a], [b]) => a.localeCompare(b)))}`;
65596
65642
  React96.useEffect(() => {
65597
65643
  const prev = mountedRef.current;
@@ -65622,6 +65668,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
65622
65668
  const failed = err instanceof runtime.TraitMountError ? err.trait : traits2.join(", ");
65623
65669
  const cause = err instanceof runtime.TraitMountError ? err.original : err;
65624
65670
  stateLog.warn("mount:failed", { traits: traits2, failed, error: message, stack: cause instanceof Error ? cause.stack : void 0 });
65671
+ if (!aliveRef.current) return;
65625
65672
  uiSlots.render({
65626
65673
  target: "main",
65627
65674
  pattern: "error-state",
@@ -65754,6 +65801,7 @@ function TraitInitializer({ traits: traits2, routeParams, mountKey, orbitals, on
65754
65801
  }
65755
65802
  var CONTENT_STAGE_WIDTH = 480;
65756
65803
  var NO_ORBITALS = [];
65804
+ var LazyPageOfRegisteredProgram = React96.createContext(false);
65757
65805
  function FitToBox({ children, mode = "box" }) {
65758
65806
  const outerRef = React96.useRef(null);
65759
65807
  const innerRef = React96.useRef(null);
@@ -65869,19 +65917,10 @@ function SchemaRunner({ schema, serverUrl, transport, getAccessToken, mockData,
65869
65917
  ),
65870
65918
  [schema, ir]
65871
65919
  );
65872
- const traitLinkedEntitiesMap = React96.useMemo(() => {
65873
- const map = /* @__PURE__ */ new Map();
65874
- if (ir) {
65875
- for (const page of ir.pages.values()) {
65876
- for (const binding of page.traits) {
65877
- if (binding.linkedEntity) {
65878
- map.set(binding.trait.name, binding.linkedEntity);
65879
- }
65880
- }
65881
- }
65882
- }
65883
- return map;
65884
- }, [ir]);
65920
+ const traitLinkedEntitiesMap = React96.useMemo(
65921
+ () => ir ? ui.buildTraitLinkedEntities(ir) : /* @__PURE__ */ new Map(),
65922
+ [ir]
65923
+ );
65885
65924
  const orbitalsByTraitMap = React96.useMemo(
65886
65925
  () => new Map(Object.entries(orbitalsByTrait)),
65887
65926
  [orbitalsByTrait]
@@ -66025,7 +66064,7 @@ function OrbPreview({
66025
66064
  if (localFallback) return;
66026
66065
  setLocalFallback(true);
66027
66066
  }, [localFallback]);
66028
- const hasOuterBridge = providers.useHasServerBridge();
66067
+ const isLazyPageOfRegisteredProgram = React96.useContext(LazyPageOfRegisteredProgram);
66029
66068
  const parseResult = React96.useMemo(() => {
66030
66069
  let parsed;
66031
66070
  if (typeof schema === "string") {
@@ -66049,7 +66088,7 @@ function OrbPreview({
66049
66088
  const persistence = React96.useMemo(() => {
66050
66089
  if (!parsedSchema || serverUrl || transport) return void 0;
66051
66090
  if (!autoMock) return void 0;
66052
- const adapter = new runtime.InMemoryPersistence();
66091
+ const adapter = new mock.InMemoryPersistence();
66053
66092
  adapter.seed(effectiveMockData);
66054
66093
  return adapter;
66055
66094
  }, [parsedSchema, serverUrl, transport, autoMock, effectiveMockData]);
@@ -66217,13 +66256,13 @@ function OrbPreview({
66217
66256
  navLog.info("interceptor:installed", { pageCount: pages.length, paths: pages.map((p) => p.page.path) });
66218
66257
  return () => el.removeEventListener("click", handler, true);
66219
66258
  }, [pages, handleNavigate, isolated, hostHrefBase]);
66220
- const withBridge = (node) => (serverUrl || transport) && !hasOuterBridge ? /* @__PURE__ */ jsxRuntime.jsx(providers.ServerBridgeProvider, { schema: parseResult.schema, serverUrl, transport, getAccessToken, children: node }) : node;
66259
+ const withBridge = (node) => (serverUrl || transport) && !isLazyPageOfRegisteredProgram ? /* @__PURE__ */ jsxRuntime.jsx(providers.ServerBridgeProvider, { schema: parseResult.schema, serverUrl, transport, getAccessToken, children: node }) : node;
66221
66260
  if (lazyRoute) {
66222
66261
  return withBridge(
66223
66262
  /* @__PURE__ */ jsxRuntime.jsxs(Box, { ref: containerRef, className: `overflow-auto ${className ?? ""}`, style: { height }, children: [
66224
66263
  lazyLoad.status === "loading" && /* @__PURE__ */ jsxRuntime.jsx(LoadingState, {}),
66225
66264
  lazyLoad.status === "error" && /* @__PURE__ */ jsxRuntime.jsx(ErrorState, { "data-testid": "lazy-page-error", message: lazyLoad.error }),
66226
- lazyLoad.status === "ready" && /* @__PURE__ */ jsxRuntime.jsx(
66265
+ lazyLoad.status === "ready" && /* @__PURE__ */ jsxRuntime.jsx(LazyPageOfRegisteredProgram.Provider, { value: true, children: /* @__PURE__ */ jsxRuntime.jsx(
66227
66266
  OrbPreview,
66228
66267
  {
66229
66268
  schema: lazyLoad.schema,
@@ -66243,7 +66282,7 @@ function OrbPreview({
66243
66282
  onUnmatchedNavigate: handleNavigate
66244
66283
  },
66245
66284
  lazyRoute.page.orbRef
66246
- )
66285
+ ) })
66247
66286
  ] })
66248
66287
  );
66249
66288
  }
@@ -66340,21 +66379,28 @@ function BrowserPlayground({
66340
66379
  runtime$1.resumeTicks();
66341
66380
  }
66342
66381
  }, [runtime$1, paused]);
66343
- const registrationReady = React96.useMemo(() => {
66344
- const orbitalNames = schema.orbitals.map((o) => o.name);
66345
- playgroundLog.debug("register:start", { schema: schema.name, orbitalNames });
66382
+ const lazySchemas = React96.useMemo(() => {
66346
66383
  const lazyPages = schema.lazyPages ?? [];
66347
- const lazy6 = lazyPages.length > 0 && lazyLoader !== void 0 ? Promise.all(lazyPages.map(async (page) => {
66384
+ if (lazyPages.length === 0 || lazyLoader === void 0) return Promise.resolve([]);
66385
+ return Promise.all(lazyPages.map(async (page) => {
66348
66386
  const loaded = await runtime.loadLazyPage(lazyLoader, page, schemaPath);
66349
66387
  if (!loaded.success) throw new Error(loaded.error);
66350
66388
  return loaded.data;
66351
- })) : Promise.resolve([]);
66352
- return lazy6.then(
66353
- (lazySchemas) => runtime$1.register(schema, { ...messages !== void 0 ? { messages } : {}, lazy: lazySchemas })
66354
- ).then(() => {
66355
- playgroundLog.debug("register:done", { schema: schema.name, orbitalNames });
66389
+ }));
66390
+ }, [schema.lazyPages, lazyLoader, schemaPath]);
66391
+ const registerProgram = React96.useCallback((program) => {
66392
+ const orbitalNames = program.orbitals.map((o) => o.name);
66393
+ playgroundLog.debug("register:start", { schema: program.name, orbitalNames });
66394
+ return lazySchemas.then((lazy6) => runtime$1.register(program, { ...messages !== void 0 ? { messages } : {}, lazy: lazy6 })).then(() => {
66395
+ playgroundLog.debug("register:done", { schema: program.name, orbitalNames });
66356
66396
  });
66357
- }, [runtime$1, schema, messages, lazyLoader, schemaPath]);
66397
+ }, [runtime$1, lazySchemas, messages]);
66398
+ const latestRegistration = React96.useRef(Promise.resolve());
66399
+ const registrationReady = React96.useMemo(() => {
66400
+ const ready = registerProgram(schema);
66401
+ latestRegistration.current = ready;
66402
+ return ready;
66403
+ }, [registerProgram, schema]);
66358
66404
  const teardownTimerRef = React96.useRef(null);
66359
66405
  React96.useEffect(() => {
66360
66406
  if (teardownTimerRef.current !== null) {
@@ -66372,18 +66418,22 @@ function BrowserPlayground({
66372
66418
  const transport = React96.useMemo(
66373
66419
  () => runtime.createInProcessTransport(
66374
66420
  async (orbitalName, request) => {
66375
- await registrationReady;
66421
+ await latestRegistration.current;
66376
66422
  return runtime$1.processOrbitalEvent(orbitalName, request);
66377
66423
  },
66378
66424
  {
66379
- // The program (lazy behaviors included) is registered above; the bridge only waits for it.
66380
- onRegister: () => registrationReady,
66425
+ // Registers what the bridge hands over (lazy behaviors included): a bridge that unregistered first gets it back.
66426
+ onRegister: (program) => {
66427
+ const ready = registerProgram(program);
66428
+ latestRegistration.current = ready;
66429
+ return ready;
66430
+ },
66381
66431
  onUnregister: () => {
66382
66432
  runtime$1.unregisterAll();
66383
66433
  }
66384
66434
  }
66385
66435
  ),
66386
- [runtime$1, registrationReady]
66436
+ [runtime$1, registerProgram, registrationReady]
66387
66437
  );
66388
66438
  const viewerLocale = locale ?? schema.locales?.[0];
66389
66439
  const i18n$1 = React96.useMemo(() => {
@@ -68511,7 +68561,7 @@ function FieldListEditor({
68511
68561
  Select,
68512
68562
  {
68513
68563
  value: field.type ?? "string",
68514
- onChange: (e) => updateAt(index, { type: e.target.value }),
68564
+ onChange: (e) => updateAt(index, fieldOfType(e.target.value)),
68515
68565
  options: FIELD_TYPE_OPTIONS
68516
68566
  }
68517
68567
  )
@@ -68641,6 +68691,22 @@ function EntityFieldMultiselect({
68641
68691
  ] })
68642
68692
  ] });
68643
68693
  }
68694
+ function fieldOfType(type) {
68695
+ switch (type) {
68696
+ case "enum":
68697
+ return { type };
68698
+ case "relation":
68699
+ return { type };
68700
+ case "union":
68701
+ return { type };
68702
+ case "array":
68703
+ return { type };
68704
+ case "object":
68705
+ return { type };
68706
+ default:
68707
+ return { type };
68708
+ }
68709
+ }
68644
68710
  function KnobField({
68645
68711
  question,
68646
68712
  value,
package/dist/avl/index.js CHANGED
@@ -1,13 +1,13 @@
1
- import { BrowserPlayground, collectEmbeddedTraits } from '../chunk-RHP5WL55.js';
2
- import { zoomReducer, initialZoomState, getBreadcrumbs } from '../chunk-GZGDBS4S.js';
1
+ import { BrowserPlayground, collectEmbeddedTraits } from '../chunk-QJIAJ6EH.js';
2
+ import { zoomReducer, initialZoomState, getBreadcrumbs } from '../chunk-7CVXM2KS.js';
3
3
  import { useTranslate as useTranslate$1 } from '../chunk-N7JIG57B.js';
4
- import '../chunk-VHTJRS2N.js';
4
+ import '../chunk-L3MTZ3RH.js';
5
5
  import '../chunk-YYYHH5BA.js';
6
6
  import { spacingTokenOf, positionOf, withPosition, snapToSpacingStep, defaultSpacingStepPx, spacingOf, withSizing, withSpacing, layoutOf, withLayout, sizingOf, DESIGN_COLOR_TOKENS, DESIGN_RADIUS_TOKENS, DESIGN_SPACING_SCALE, sizeLimitOf, withSizeLimit, isArbitraryClass, tokenOfDesignClass } from '../chunk-D2E44ODB.js';
7
- import { AvlGlyph, Popover, Button, Icon, Select, Badge, IconButton, AvlStateMachine, Input, AvlOrbital, AvlTrait, AvlEntity, AvlPage, AvlEvent, AvlGuard, AvlEffect, AvlState, useAlmadarDndSensors, almadarDndCollisionDetection, TagInput, Checkbox, Switch, CodeBlock, AvlFieldType, FileTree, AvlTransitionDetail, RangeSlider, computeTraitLayout, edgePath, Accordion, FormField, Radio, useCompactLayout, ButtonGroup } from '../chunk-PYJ2UQWM.js';
8
- export { AVL_GLYPH_KINDS, AvlApplication, AvlBinding, AvlBindingRef, AvlCircuit, AvlEffect, AvlEffectChip, AvlEntity, AvlEvent, AvlField, AvlFieldType, AvlGlyph, AvlGuard, AvlLiteral, AvlOperator, AvlOrbital, AvlPage, AvlPersistence, AvlSExpr, AvlState, AvlStateMachine, AvlTrait, AvlTransition, AvlTransitionDetail, AvlTransitionExplainer, BehaviorView, FIELD_TYPE_SHAPES, MiniStateMachine, ModuleCard, computeTraitLayout, edgePath } from '../chunk-PYJ2UQWM.js';
9
- import { avlSeries, STATE_COLORS, Box, HStack, VStack, avlTint, CONNECTION_COLORS, parseTraitLevel, parseApplicationLevel, parseOrbitalLevel, getStateRole, effectCategoryOf, EFFECT_CATEGORY_COLORS, pressableProps, traitTransitionRenderUi, traitEventWires } from '../chunk-HA7CJWQX.js';
10
- export { CONNECTION_COLORS, EFFECT_CATEGORY_COLORS, OPERATOR_CATEGORY_COLORS, STATE_COLORS, effectCategoryOf, getStateRole, parseApplicationLevel, parseOrbitalLevel, parseTraitLevel, parseTransitionLevel, traitLevelFromTrait } from '../chunk-HA7CJWQX.js';
7
+ import { AvlGlyph, Popover, Button, Icon, Select, Badge, IconButton, AvlStateMachine, Input, AvlOrbital, AvlTrait, AvlEntity, AvlPage, AvlEvent, AvlGuard, AvlEffect, AvlState, useAlmadarDndSensors, almadarDndCollisionDetection, TagInput, Checkbox, Switch, CodeBlock, AvlFieldType, FileTree, AvlTransitionDetail, RangeSlider, computeTraitLayout, edgePath, Accordion, FormField, Radio, useCompactLayout, ButtonGroup } from '../chunk-E6MWYQVZ.js';
8
+ export { AVL_GLYPH_KINDS, AvlApplication, AvlBinding, AvlBindingRef, AvlCircuit, AvlEffect, AvlEffectChip, AvlEntity, AvlEvent, AvlField, AvlFieldType, AvlGlyph, AvlGuard, AvlLiteral, AvlOperator, AvlOrbital, AvlPage, AvlPersistence, AvlSExpr, AvlState, AvlStateMachine, AvlTrait, AvlTransition, AvlTransitionDetail, AvlTransitionExplainer, BehaviorView, FIELD_TYPE_SHAPES, MiniStateMachine, ModuleCard, computeTraitLayout, edgePath } from '../chunk-E6MWYQVZ.js';
9
+ import { avlSeries, STATE_COLORS, Box, HStack, VStack, avlTint, CONNECTION_COLORS, parseTraitLevel, parseApplicationLevel, parseOrbitalLevel, getStateRole, effectCategoryOf, EFFECT_CATEGORY_COLORS, pressableProps, traitTransitionRenderUi, traitEventWires } from '../chunk-J755QADM.js';
10
+ export { CONNECTION_COLORS, EFFECT_CATEGORY_COLORS, OPERATOR_CATEGORY_COLORS, STATE_COLORS, effectCategoryOf, getStateRole, parseApplicationLevel, parseOrbitalLevel, parseTraitLevel, parseTransitionLevel, traitLevelFromTrait } from '../chunk-J755QADM.js';
11
11
  import { Typography, INLINE_TEXT_ATTR } from '../chunk-4ZGXIW3B.js';
12
12
  import { usePrefersReducedMotion } from '../chunk-I5QOYW2Z.js';
13
13
  import '../chunk-XJTHMW4G.js';
@@ -5279,7 +5279,7 @@ function FieldListEditor({
5279
5279
  Select,
5280
5280
  {
5281
5281
  value: field.type ?? "string",
5282
- onChange: (e) => updateAt(index, { type: e.target.value }),
5282
+ onChange: (e) => updateAt(index, fieldOfType(e.target.value)),
5283
5283
  options: FIELD_TYPE_OPTIONS
5284
5284
  }
5285
5285
  )
@@ -5409,6 +5409,22 @@ function EntityFieldMultiselect({
5409
5409
  ] })
5410
5410
  ] });
5411
5411
  }
5412
+ function fieldOfType(type) {
5413
+ switch (type) {
5414
+ case "enum":
5415
+ return { type };
5416
+ case "relation":
5417
+ return { type };
5418
+ case "union":
5419
+ return { type };
5420
+ case "array":
5421
+ return { type };
5422
+ case "object":
5423
+ return { type };
5424
+ default:
5425
+ return { type };
5426
+ }
5427
+ }
5412
5428
  function KnobField({
5413
5429
  question,
5414
5430
  value,
@@ -1,4 +1,4 @@
1
- import { avlBlend, AVL_INK, EFFECT_CATEGORY_COLORS, OPERATOR_CATEGORY_COLORS, avlTint, Box, VStack, effectCategoryOf } from './chunk-HA7CJWQX.js';
1
+ import { avlBlend, AVL_INK, EFFECT_CATEGORY_COLORS, OPERATOR_CATEGORY_COLORS, avlTint, Box, VStack, effectCategoryOf } from './chunk-J755QADM.js';
2
2
  import { Typography } from './chunk-4ZGXIW3B.js';
3
3
  import { Vector3, QuadraticBezierCurve3, MathUtils, Quaternion } from 'three';
4
4
  import { EntityPersistenceSchema } from '@almadar/core';