@almadar/ui 6.28.0 → 6.30.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 (54) hide show
  1. package/dist/{EntityBindingContext-C6FgxdfG.d.cts → EntityBindingContext-ChCONv2W.d.cts} +3 -39
  2. package/dist/{EntityBindingContext-C6FgxdfG.d.ts → EntityBindingContext-ChCONv2W.d.ts} +3 -39
  3. package/dist/avl/index.cjs +74 -48
  4. package/dist/avl/index.js +74 -48
  5. package/dist/components/index.cjs +54 -45
  6. package/dist/components/index.d.cts +1 -1
  7. package/dist/components/index.d.ts +1 -1
  8. package/dist/components/index.js +54 -45
  9. package/dist/context/index.cjs +135 -105
  10. package/dist/context/index.d.cts +2 -60
  11. package/dist/context/index.d.ts +2 -60
  12. package/dist/context/index.js +135 -105
  13. package/dist/lib/index.cjs +455 -0
  14. package/dist/lib/index.d.cts +42 -1
  15. package/dist/lib/index.d.ts +42 -1
  16. package/dist/lib/index.js +438 -1
  17. package/dist/marketing/index.cjs +4 -5
  18. package/dist/marketing/index.js +4 -5
  19. package/dist/providers/index.cjs +194 -156
  20. package/dist/providers/index.d.cts +1 -1
  21. package/dist/providers/index.d.ts +1 -1
  22. package/dist/providers/index.js +194 -156
  23. package/dist/runtime/index.cjs +74 -48
  24. package/dist/runtime/index.d.cts +16 -2
  25. package/dist/runtime/index.d.ts +16 -2
  26. package/dist/runtime/index.js +74 -48
  27. package/dist/themeTokens-DVRwufw8.d.cts +112 -0
  28. package/dist/themeTokens-DVRwufw8.d.ts +112 -0
  29. package/package.json +7 -6
  30. package/scripts/audit-tailwind-safelist.ts +4 -0
  31. package/tailwind-preset.cjs +155 -28
  32. package/themes/almadar-website.css +37 -107
  33. package/themes/almadar.css +37 -108
  34. package/themes/atelier.css +145 -240
  35. package/themes/bloomberg-dense.css +145 -252
  36. package/themes/clay.css +39 -137
  37. package/themes/comic.css +39 -145
  38. package/themes/corporate.css +39 -131
  39. package/themes/game-adventure.css +22 -87
  40. package/themes/game-rpg.css +22 -84
  41. package/themes/game-sci-fi.css +22 -88
  42. package/themes/game-ui-pack.css +22 -85
  43. package/themes/gazette.css +43 -135
  44. package/themes/glass.css +39 -148
  45. package/themes/kiosk.css +51 -146
  46. package/themes/linear-clean.css +145 -215
  47. package/themes/minimalist.css +39 -125
  48. package/themes/neon.css +39 -132
  49. package/themes/notion-editorial.css +145 -215
  50. package/themes/prism.css +37 -100
  51. package/themes/retro.css +39 -130
  52. package/themes/terminal.css +61 -152
  53. package/themes/trait-wars.css +121 -285
  54. package/themes/wireframe.css +41 -128
@@ -2936,6 +2936,13 @@ var init_slot_types = __esm({
2936
2936
  nextRefId = 1;
2937
2937
  }
2938
2938
  });
2939
+ var SlotContainedContext;
2940
+ var init_slotContained = __esm({
2941
+ "lib/slotContained.ts"() {
2942
+ "use client";
2943
+ SlotContainedContext = React87.createContext(false);
2944
+ }
2945
+ });
2939
2946
  function buildForkPaths(x, y, branches, scale) {
2940
2947
  const inLength = 30 * scale;
2941
2948
  const outLength = 30 * scale;
@@ -13935,11 +13942,10 @@ var init_HeroSection = __esm({
13935
13942
  };
13936
13943
  backgroundStyles = {
13937
13944
  dark: "bg-foreground text-background",
13938
- gradient: [
13939
- "bg-[radial-gradient(ellipse_at_top,var(--color-primary)/0.08,transparent_60%),",
13940
- "radial-gradient(ellipse_at_bottom_right,var(--color-accent)/0.06,transparent_50%)]",
13941
- "bg-background"
13942
- ].join(" "),
13945
+ // A single bracket value: joining this as two array entries put a space
13946
+ // inside the class (Tailwind splits utilities on whitespace), so neither
13947
+ // half was a valid utility and the gradient rendered as nothing.
13948
+ gradient: "bg-[radial-gradient(ellipse_at_top,var(--color-primary)/0.08,transparent_60%),radial-gradient(ellipse_at_bottom_right,var(--color-accent)/0.06,transparent_50%)] bg-background",
13943
13949
  subtle: "bg-muted/30"
13944
13950
  };
13945
13951
  MarketingImage = ({ src, alt, className }) => /* @__PURE__ */ jsxRuntime.jsx(
@@ -35697,7 +35703,6 @@ function TableView({
35697
35703
  columns,
35698
35704
  fields,
35699
35705
  itemActions,
35700
- maxInlineActions,
35701
35706
  itemClickEvent = "",
35702
35707
  selectable = false,
35703
35708
  selectEvent,
@@ -35731,8 +35736,7 @@ function TableView({
35731
35736
  const [localSelected, setLocalSelected] = React87__namespace.default.useState(/* @__PURE__ */ new Set());
35732
35737
  const colDefs = (Array.isArray(columns) ? columns : void 0) ?? (Array.isArray(fields) ? fields : void 0) ?? [];
35733
35738
  const actionDefs = Array.isArray(itemActions) ? itemActions : [];
35734
- const inlineActions = maxInlineActions != null ? actionDefs.slice(0, maxInlineActions) : [];
35735
- const overflowActions = maxInlineActions != null ? actionDefs.slice(maxInlineActions) : actionDefs;
35739
+ const overflowActions = actionDefs;
35736
35740
  const fireAction = (action, row) => eventBus.emit(`UI:${action.event}`, {
35737
35741
  id: row.id,
35738
35742
  row
@@ -35914,7 +35918,7 @@ function TableView({
35914
35918
  }
35915
35919
  return /* @__PURE__ */ jsxRuntime.jsx(Box, { role: "cell", className: cellBase, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate text-foreground", children: formatCell(raw, col.format, relationsData?.[col.field ?? col.key]) }) }, col.key);
35916
35920
  }),
35917
- hasActions && /* @__PURE__ */ jsxRuntime.jsxs(
35921
+ hasActions && /* @__PURE__ */ jsxRuntime.jsx(
35918
35922
  HStack,
35919
35923
  {
35920
35924
  gap: "xs",
@@ -35928,38 +35932,20 @@ function TableView({
35928
35932
  "border-l border-[var(--color-border)]",
35929
35933
  lk.striped && index % 2 === 1 ? "bg-[var(--color-surface-subtle)]" : "bg-[var(--color-card)] group-hover:bg-[var(--color-surface-subtle)]"
35930
35934
  ),
35931
- children: [
35932
- inlineActions.map((action) => /* @__PURE__ */ jsxRuntime.jsxs(
35933
- Button,
35934
- {
35935
- variant: action.variant ?? "ghost",
35936
- size: "sm",
35937
- onClick: () => fireAction(action, row),
35938
- "data-testid": `action-${action.event}`,
35939
- "data-row-id": String(row.id),
35940
- className: cn(action.variant === "danger" && "text-error hover:bg-error/10"),
35941
- children: [
35942
- action.icon && renderIconInput3(action.icon, { size: "xs", className: "mr-1" }),
35943
- action.label
35944
- ]
35945
- },
35946
- action.event
35947
- )),
35948
- overflowActions.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
35949
- Menu,
35950
- {
35951
- position: "bottom-end",
35952
- trigger: /* @__PURE__ */ jsxRuntime.jsx(Button, { variant: "ghost", size: "sm", "aria-label": t("common.actions"), "data-testid": "action-overflow", "data-row-id": String(row.id), children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: "more-horizontal", size: "xs" }) }),
35953
- items: overflowActions.map((action) => ({
35954
- label: action.label,
35955
- icon: action.icon,
35956
- event: action.event,
35957
- variant: action.variant === "danger" ? "danger" : "default",
35958
- onClick: () => fireAction(action, row)
35959
- }))
35960
- }
35961
- )
35962
- ]
35935
+ children: overflowActions.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
35936
+ Menu,
35937
+ {
35938
+ position: "bottom-end",
35939
+ trigger: /* @__PURE__ */ jsxRuntime.jsx(Button, { variant: "ghost", size: "sm", "aria-label": t("common.actions"), "data-testid": "action-overflow", "data-row-id": String(row.id), children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: "more-horizontal", size: "xs" }) }),
35940
+ items: overflowActions.map((action) => ({
35941
+ label: action.label,
35942
+ icon: action.icon,
35943
+ event: action.event,
35944
+ variant: action.variant === "danger" ? "danger" : "default",
35945
+ onClick: () => fireAction(action, row)
35946
+ }))
35947
+ }
35948
+ )
35963
35949
  }
35964
35950
  )
35965
35951
  ]
@@ -45247,6 +45233,7 @@ var init_DetailPanel = __esm({
45247
45233
  init_EmptyState();
45248
45234
  init_cn();
45249
45235
  init_portalRoot();
45236
+ init_slotContained();
45250
45237
  init_format();
45251
45238
  init_getNestedValue();
45252
45239
  init_relationLabel();
@@ -45278,6 +45265,7 @@ var init_DetailPanel = __esm({
45278
45265
  }) => {
45279
45266
  const eventBus = useEventBus();
45280
45267
  const { t } = hooks.useTranslate();
45268
+ const contained = React87.useContext(SlotContainedContext);
45281
45269
  const [titleDraft, setTitleDraft] = React87__namespace.default.useState(null);
45282
45270
  const isFieldDefArray = (arr) => {
45283
45271
  if (!arr || arr.length === 0) return false;
@@ -45665,8 +45653,9 @@ var init_DetailPanel = __esm({
45665
45653
  if (!slideOver) {
45666
45654
  return /* @__PURE__ */ jsxRuntime.jsx(Box, { className, children: content });
45667
45655
  }
45668
- const panel = /* @__PURE__ */ jsxRuntime.jsx(Box, { className: cn("fixed inset-y-0 right-0 w-full max-w-2xl bg-card shadow-lg z-50 overflow-y-auto p-6", className), children: content });
45669
- return typeof document === "undefined" ? panel : reactDom.createPortal(panel, getOrCreatePortalRoot());
45656
+ const panel = /* @__PURE__ */ jsxRuntime.jsx(Box, { className: cn(contained ? "absolute" : "fixed", "inset-y-0 right-0 w-full max-w-2xl bg-card shadow-lg z-50 overflow-y-auto p-6", className), children: content });
45657
+ if (contained || typeof document === "undefined") return panel;
45658
+ return reactDom.createPortal(panel, getOrCreatePortalRoot());
45670
45659
  };
45671
45660
  DetailPanel.displayName = "DetailPanel";
45672
45661
  }
@@ -52163,6 +52152,7 @@ var init_component_registry_generated = __esm({
52163
52152
  // components/core/organisms/UISlotRenderer.tsx
52164
52153
  var UISlotRenderer_exports = {};
52165
52154
  __export(UISlotRenderer_exports, {
52155
+ SlotContainedContext: () => SlotContainedContext,
52166
52156
  SlotContentRenderer: () => SlotContentRenderer,
52167
52157
  SuspenseConfigProvider: () => SuspenseConfigProvider,
52168
52158
  UISlotComponent: () => UISlotComponent,
@@ -52335,6 +52325,25 @@ function renderContainedPortal(t, slot, content, onDismiss) {
52335
52325
  }
52336
52326
  );
52337
52327
  case "drawer":
52328
+ if (content.pattern === "detail-panel" && content.props.slideOver === true) {
52329
+ return /* @__PURE__ */ jsxRuntime.jsx(
52330
+ Box,
52331
+ {
52332
+ id: slotId,
52333
+ className: "absolute inset-0 z-50 overflow-hidden",
52334
+ style: { backgroundColor: "rgba(0, 0, 0, 0.5)" },
52335
+ onClick: onDismiss,
52336
+ children: /* @__PURE__ */ jsxRuntime.jsx(
52337
+ Box,
52338
+ {
52339
+ className: "absolute inset-y-0 right-0 pointer-events-auto",
52340
+ onClick: (e) => e.stopPropagation(),
52341
+ children: slotContent
52342
+ }
52343
+ )
52344
+ }
52345
+ );
52346
+ }
52338
52347
  return /* @__PURE__ */ jsxRuntime.jsx(
52339
52348
  Box,
52340
52349
  {
@@ -53186,7 +53195,7 @@ function UISlotRenderer({
53186
53195
  }
53187
53196
  return wrapped;
53188
53197
  }
53189
- var scopeWrapLog, TRAIT_BINDING_RE, SuspenseConfigContext, SlotContainedContext, SLOT_SKELETON_MAP, CONTENT_NODE_SLOTS, PATTERNS_WITH_CHILDREN, traitRefPresenceCache;
53198
+ var scopeWrapLog, TRAIT_BINDING_RE, SuspenseConfigContext, SLOT_SKELETON_MAP, CONTENT_NODE_SLOTS, PATTERNS_WITH_CHILDREN, traitRefPresenceCache;
53190
53199
  var init_UISlotRenderer = __esm({
53191
53200
  "components/core/organisms/UISlotRenderer.tsx"() {
53192
53201
  "use client";
@@ -53201,6 +53210,7 @@ var init_UISlotRenderer = __esm({
53201
53210
  init_cn();
53202
53211
  init_format();
53203
53212
  init_portalRoot();
53213
+ init_slotContained();
53204
53214
  init_ErrorBoundary();
53205
53215
  init_Skeleton();
53206
53216
  init_renderer();
@@ -53210,7 +53220,6 @@ var init_UISlotRenderer = __esm({
53210
53220
  scopeWrapLog = logger.createLogger("almadar:ui:scope-wrap");
53211
53221
  TRAIT_BINDING_RE = /^@trait\.([A-Z][A-Za-z0-9]*)$/;
53212
53222
  SuspenseConfigContext = React87.createContext({ enabled: false });
53213
- SlotContainedContext = React87.createContext(false);
53214
53223
  SuspenseConfigProvider.displayName = "SuspenseConfigProvider";
53215
53224
  SLOT_SKELETON_MAP = {
53216
53225
  main: "table",
@@ -54678,6 +54687,9 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
54678
54687
  const normalizedEvent = normalizeEventKey(eventKey);
54679
54688
  return managerRef.current.canHandleEvent(traitName, normalizedEvent);
54680
54689
  }, []);
54690
+ const commitServerEntity = React87.useCallback((traitName, entity) => {
54691
+ traitFieldStatesRef.current.set(traitName, entity);
54692
+ }, []);
54681
54693
  React87.useEffect(() => {
54682
54694
  const allEvents = /* @__PURE__ */ new Set();
54683
54695
  for (const binding of traitBindings) {
@@ -54841,7 +54853,8 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
54841
54853
  sendEvent,
54842
54854
  getTraitState,
54843
54855
  canHandleEvent,
54844
- entityBindingSource
54856
+ entityBindingSource,
54857
+ commitServerEntity
54845
54858
  };
54846
54859
  }
54847
54860
  var resolvedSchemaLog = logger.createLogger("almadar:ui:resolved-schema");
@@ -54967,7 +54980,7 @@ function normalizeChild(child) {
54967
54980
  function effectResultsToTraces(results) {
54968
54981
  if (!results) return [];
54969
54982
  return results.map((r) => {
54970
- const resultId = r.data !== void 0 && r.data !== null && "id" in r.data && typeof r.data.id === "string" ? r.data.id : void 0;
54983
+ const resultId = typeof r.data === "object" && r.data !== null && !Array.isArray(r.data) && "id" in r.data && typeof r.data.id === "string" ? r.data.id : void 0;
54971
54984
  const outcome = r.denied ? "denied" : r.success ? "success" : "failed";
54972
54985
  return {
54973
54986
  type: r.effect,
@@ -55080,6 +55093,8 @@ function TraitInitializer({ traits: traits2, routeParams, orbitalNames, onNaviga
55080
55093
  [serverActiveTraits]
55081
55094
  );
55082
55095
  const uiSlots = context.useUISlots();
55096
+ const commitServerEntityRef = React87.useRef(() => {
55097
+ });
55083
55098
  const onEventProcessed = React87.useCallback((event, payload, dispatchedOrbitals, tick, sourceTrait, locallyEmitted, results, entityByTrait) => {
55084
55099
  if (!bridge.connected || !orbitalNames?.length) return;
55085
55100
  const targets = dispatchedOrbitals && dispatchedOrbitals.size > 0 ? orbitalNames.filter((n) => dispatchedOrbitals.has(n)) : orbitalNames;
@@ -55096,12 +55111,18 @@ function TraitInitializer({ traits: traits2, routeParams, orbitalNames, onNaviga
55096
55111
  }
55097
55112
  void bridge.sendEvent(name, event, withActiveTraits(payload), void 0, void 0, locallyEmitted, results, entityByTrait, user ?? void 0).then(({ effects, meta }) => {
55098
55113
  recordServerResponse(name, event, { ...meta, effectResults: effectResultsToTraces(meta.effectResults) });
55114
+ if (meta.entityByTrait) {
55115
+ for (const [traitName, entity] of Object.entries(meta.entityByTrait)) {
55116
+ commitServerEntityRef.current(traitName, entity);
55117
+ }
55118
+ }
55099
55119
  applyServerEffects(effects, uiSlots, onNavigate, embeddedTraits, activeTraitNamesRef.current, onNavigateBack);
55100
55120
  });
55101
55121
  }
55102
55122
  }, [bridge.connected, bridge.sendEvent, orbitalNames, uiSlots, onNavigate, onNavigateBack, embeddedTraits, activeTraitNames, withActiveTraits, user]);
55103
55123
  const opts = orbitalNames ? { onEventProcessed, navigate: onNavigate, navigateBack: onNavigateBack, traitConfigsByName, orbitalsByTrait, embeddedTraits, callsiteCaptureChildrenByTrait, initPayload: routeParams } : { navigate: onNavigate, navigateBack: onNavigateBack, persistence, traitConfigsByName, orbitalsByTrait, embeddedTraits, callsiteCaptureChildrenByTrait, initPayload: routeParams };
55104
- const { sendEvent, entityBindingSource } = useTraitStateMachine(traits2, uiSlots, opts);
55124
+ const { sendEvent, entityBindingSource, commitServerEntity } = useTraitStateMachine(traits2, uiSlots, opts);
55125
+ commitServerEntityRef.current = commitServerEntity;
55105
55126
  const initSentRef = React87.useRef(false);
55106
55127
  const prevTraitsRef = React87.useRef(void 0);
55107
55128
  const paramsKey = JSON.stringify(routeParams ?? {});
@@ -55153,6 +55174,11 @@ function TraitInitializer({ traits: traits2, routeParams, orbitalNames, onNaviga
55153
55174
  user ?? void 0
55154
55175
  );
55155
55176
  recordServerResponse(name, "INIT", { ...meta, effectResults: effectResultsToTraces(meta.effectResults) });
55177
+ if (meta.entityByTrait) {
55178
+ for (const [traitName, entity] of Object.entries(meta.entityByTrait)) {
55179
+ commitServerEntityRef.current(traitName, entity);
55180
+ }
55181
+ }
55156
55182
  const effectTraces = [
55157
55183
  { type: "fetch", args: [], status: "executed" },
55158
55184
  ...effects.map((eff) => ({
@@ -5,8 +5,8 @@ import * as _almadar_runtime from '@almadar/runtime';
5
5
  import { TraitState, TransitionResult, EffectHandlers } from '@almadar/runtime';
6
6
  import { K as KeyCaptureTable } from '../useKeyboardRouter-CVn8lfiX.cjs';
7
7
  import { c as useUISlots } from '../UISlotContext-BlRDbHDy.cjs';
8
- import { a as EntityBindingSource, h as ServerBridgeTransport, A as AccessTokenProvider } from '../EntityBindingContext-C6FgxdfG.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-C6FgxdfG.cjs';
8
+ import { a as EntityBindingSource, h as ServerBridgeTransport, A as AccessTokenProvider } from '../EntityBindingContext-ChCONv2W.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-ChCONv2W.cjs';
10
10
  import '../verificationRegistry-DTrKDRoa.cjs';
11
11
  export { PERF_NAMESPACE, PerfEntry, PreparedPreviewSchema, adjustSchemaForMockData, buildMockData, clearPerf, perfEnd, perfStart, perfTime, prepareSchemaForPreview, wrapCallbackForEvent } from '@almadar/runtime/ui';
12
12
  import React__default, { ReactNode } from 'react';
@@ -30,6 +30,20 @@ interface TraitStateMachineResult {
30
30
  /** Live per-trait binding surface for `EntityBindingContext` — the
31
31
  * renderer resolves `RenderBindingMarker` prop leaves against it. */
32
32
  entityBindingSource: EntityBindingSource;
33
+ /**
34
+ * Commit a trait's authoritative entity row, as returned by a stateless
35
+ * server response's `entityByTrait[traitName]` (Fix C, the entity
36
+ * round-trip). The stateless deployment has no server-held memory
37
+ * across requests, so a `set`-only field a trait wrote on a PRIOR
38
+ * request would otherwise vanish on the next one (`traitFieldStatesRef`
39
+ * only ever reflects THIS client's own local writes) — replacing it
40
+ * here with the server's own post-effects row keeps the two in sync,
41
+ * the same way a fresh `getById` already does within a single request.
42
+ * A full replace, not a merge: the server sends the whole row after its
43
+ * own effects ran, the same authoritative shape a `fetch`/`getById`
44
+ * would return.
45
+ */
46
+ commitServerEntity: (traitName: string, entity: EntityRow) => void;
33
47
  }
34
48
  interface UseTraitStateMachineOptions {
35
49
  /**
@@ -5,8 +5,8 @@ import * as _almadar_runtime from '@almadar/runtime';
5
5
  import { TraitState, TransitionResult, EffectHandlers } from '@almadar/runtime';
6
6
  import { K as KeyCaptureTable } from '../useKeyboardRouter-B1pIi9jo.js';
7
7
  import { c as useUISlots } from '../UISlotContext-CB89mv7N.js';
8
- import { a as EntityBindingSource, h as ServerBridgeTransport, A as AccessTokenProvider } from '../EntityBindingContext-C6FgxdfG.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-C6FgxdfG.js';
8
+ import { a as EntityBindingSource, h as ServerBridgeTransport, A as AccessTokenProvider } from '../EntityBindingContext-ChCONv2W.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-ChCONv2W.js';
10
10
  import '../verificationRegistry-Cwa52VyK.js';
11
11
  export { PERF_NAMESPACE, PerfEntry, PreparedPreviewSchema, adjustSchemaForMockData, buildMockData, clearPerf, perfEnd, perfStart, perfTime, prepareSchemaForPreview, wrapCallbackForEvent } from '@almadar/runtime/ui';
12
12
  import React__default, { ReactNode } from 'react';
@@ -30,6 +30,20 @@ interface TraitStateMachineResult {
30
30
  /** Live per-trait binding surface for `EntityBindingContext` — the
31
31
  * renderer resolves `RenderBindingMarker` prop leaves against it. */
32
32
  entityBindingSource: EntityBindingSource;
33
+ /**
34
+ * Commit a trait's authoritative entity row, as returned by a stateless
35
+ * server response's `entityByTrait[traitName]` (Fix C, the entity
36
+ * round-trip). The stateless deployment has no server-held memory
37
+ * across requests, so a `set`-only field a trait wrote on a PRIOR
38
+ * request would otherwise vanish on the next one (`traitFieldStatesRef`
39
+ * only ever reflects THIS client's own local writes) — replacing it
40
+ * here with the server's own post-effects row keeps the two in sync,
41
+ * the same way a fresh `getById` already does within a single request.
42
+ * A full replace, not a merge: the server sends the whole row after its
43
+ * own effects ran, the same authoritative shape a `fetch`/`getById`
44
+ * would return.
45
+ */
46
+ commitServerEntity: (traitName: string, entity: EntityRow) => void;
33
47
  }
34
48
  interface UseTraitStateMachineOptions {
35
49
  /**
@@ -2862,6 +2862,13 @@ var init_slot_types = __esm({
2862
2862
  nextRefId = 1;
2863
2863
  }
2864
2864
  });
2865
+ var SlotContainedContext;
2866
+ var init_slotContained = __esm({
2867
+ "lib/slotContained.ts"() {
2868
+ "use client";
2869
+ SlotContainedContext = createContext(false);
2870
+ }
2871
+ });
2865
2872
  function buildForkPaths(x, y, branches, scale) {
2866
2873
  const inLength = 30 * scale;
2867
2874
  const outLength = 30 * scale;
@@ -13861,11 +13868,10 @@ var init_HeroSection = __esm({
13861
13868
  };
13862
13869
  backgroundStyles = {
13863
13870
  dark: "bg-foreground text-background",
13864
- gradient: [
13865
- "bg-[radial-gradient(ellipse_at_top,var(--color-primary)/0.08,transparent_60%),",
13866
- "radial-gradient(ellipse_at_bottom_right,var(--color-accent)/0.06,transparent_50%)]",
13867
- "bg-background"
13868
- ].join(" "),
13871
+ // A single bracket value: joining this as two array entries put a space
13872
+ // inside the class (Tailwind splits utilities on whitespace), so neither
13873
+ // half was a valid utility and the gradient rendered as nothing.
13874
+ gradient: "bg-[radial-gradient(ellipse_at_top,var(--color-primary)/0.08,transparent_60%),radial-gradient(ellipse_at_bottom_right,var(--color-accent)/0.06,transparent_50%)] bg-background",
13869
13875
  subtle: "bg-muted/30"
13870
13876
  };
13871
13877
  MarketingImage = ({ src, alt, className }) => /* @__PURE__ */ jsx(
@@ -35623,7 +35629,6 @@ function TableView({
35623
35629
  columns,
35624
35630
  fields,
35625
35631
  itemActions,
35626
- maxInlineActions,
35627
35632
  itemClickEvent = "",
35628
35633
  selectable = false,
35629
35634
  selectEvent,
@@ -35657,8 +35662,7 @@ function TableView({
35657
35662
  const [localSelected, setLocalSelected] = React87__default.useState(/* @__PURE__ */ new Set());
35658
35663
  const colDefs = (Array.isArray(columns) ? columns : void 0) ?? (Array.isArray(fields) ? fields : void 0) ?? [];
35659
35664
  const actionDefs = Array.isArray(itemActions) ? itemActions : [];
35660
- const inlineActions = maxInlineActions != null ? actionDefs.slice(0, maxInlineActions) : [];
35661
- const overflowActions = maxInlineActions != null ? actionDefs.slice(maxInlineActions) : actionDefs;
35665
+ const overflowActions = actionDefs;
35662
35666
  const fireAction = (action, row) => eventBus.emit(`UI:${action.event}`, {
35663
35667
  id: row.id,
35664
35668
  row
@@ -35840,7 +35844,7 @@ function TableView({
35840
35844
  }
35841
35845
  return /* @__PURE__ */ jsx(Box, { role: "cell", className: cellBase, children: /* @__PURE__ */ jsx("span", { className: "truncate text-foreground", children: formatCell(raw, col.format, relationsData?.[col.field ?? col.key]) }) }, col.key);
35842
35846
  }),
35843
- hasActions && /* @__PURE__ */ jsxs(
35847
+ hasActions && /* @__PURE__ */ jsx(
35844
35848
  HStack,
35845
35849
  {
35846
35850
  gap: "xs",
@@ -35854,38 +35858,20 @@ function TableView({
35854
35858
  "border-l border-[var(--color-border)]",
35855
35859
  lk.striped && index % 2 === 1 ? "bg-[var(--color-surface-subtle)]" : "bg-[var(--color-card)] group-hover:bg-[var(--color-surface-subtle)]"
35856
35860
  ),
35857
- children: [
35858
- inlineActions.map((action) => /* @__PURE__ */ jsxs(
35859
- Button,
35860
- {
35861
- variant: action.variant ?? "ghost",
35862
- size: "sm",
35863
- onClick: () => fireAction(action, row),
35864
- "data-testid": `action-${action.event}`,
35865
- "data-row-id": String(row.id),
35866
- className: cn(action.variant === "danger" && "text-error hover:bg-error/10"),
35867
- children: [
35868
- action.icon && renderIconInput3(action.icon, { size: "xs", className: "mr-1" }),
35869
- action.label
35870
- ]
35871
- },
35872
- action.event
35873
- )),
35874
- overflowActions.length > 0 && /* @__PURE__ */ jsx(
35875
- Menu,
35876
- {
35877
- position: "bottom-end",
35878
- trigger: /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "sm", "aria-label": t("common.actions"), "data-testid": "action-overflow", "data-row-id": String(row.id), children: /* @__PURE__ */ jsx(Icon, { name: "more-horizontal", size: "xs" }) }),
35879
- items: overflowActions.map((action) => ({
35880
- label: action.label,
35881
- icon: action.icon,
35882
- event: action.event,
35883
- variant: action.variant === "danger" ? "danger" : "default",
35884
- onClick: () => fireAction(action, row)
35885
- }))
35886
- }
35887
- )
35888
- ]
35861
+ children: overflowActions.length > 0 && /* @__PURE__ */ jsx(
35862
+ Menu,
35863
+ {
35864
+ position: "bottom-end",
35865
+ trigger: /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "sm", "aria-label": t("common.actions"), "data-testid": "action-overflow", "data-row-id": String(row.id), children: /* @__PURE__ */ jsx(Icon, { name: "more-horizontal", size: "xs" }) }),
35866
+ items: overflowActions.map((action) => ({
35867
+ label: action.label,
35868
+ icon: action.icon,
35869
+ event: action.event,
35870
+ variant: action.variant === "danger" ? "danger" : "default",
35871
+ onClick: () => fireAction(action, row)
35872
+ }))
35873
+ }
35874
+ )
35889
35875
  }
35890
35876
  )
35891
35877
  ]
@@ -45173,6 +45159,7 @@ var init_DetailPanel = __esm({
45173
45159
  init_EmptyState();
45174
45160
  init_cn();
45175
45161
  init_portalRoot();
45162
+ init_slotContained();
45176
45163
  init_format();
45177
45164
  init_getNestedValue();
45178
45165
  init_relationLabel();
@@ -45204,6 +45191,7 @@ var init_DetailPanel = __esm({
45204
45191
  }) => {
45205
45192
  const eventBus = useEventBus();
45206
45193
  const { t } = useTranslate();
45194
+ const contained = useContext(SlotContainedContext);
45207
45195
  const [titleDraft, setTitleDraft] = React87__default.useState(null);
45208
45196
  const isFieldDefArray = (arr) => {
45209
45197
  if (!arr || arr.length === 0) return false;
@@ -45591,8 +45579,9 @@ var init_DetailPanel = __esm({
45591
45579
  if (!slideOver) {
45592
45580
  return /* @__PURE__ */ jsx(Box, { className, children: content });
45593
45581
  }
45594
- const panel = /* @__PURE__ */ jsx(Box, { className: cn("fixed inset-y-0 right-0 w-full max-w-2xl bg-card shadow-lg z-50 overflow-y-auto p-6", className), children: content });
45595
- return typeof document === "undefined" ? panel : createPortal(panel, getOrCreatePortalRoot());
45582
+ const panel = /* @__PURE__ */ jsx(Box, { className: cn(contained ? "absolute" : "fixed", "inset-y-0 right-0 w-full max-w-2xl bg-card shadow-lg z-50 overflow-y-auto p-6", className), children: content });
45583
+ if (contained || typeof document === "undefined") return panel;
45584
+ return createPortal(panel, getOrCreatePortalRoot());
45596
45585
  };
45597
45586
  DetailPanel.displayName = "DetailPanel";
45598
45587
  }
@@ -52089,6 +52078,7 @@ var init_component_registry_generated = __esm({
52089
52078
  // components/core/organisms/UISlotRenderer.tsx
52090
52079
  var UISlotRenderer_exports = {};
52091
52080
  __export(UISlotRenderer_exports, {
52081
+ SlotContainedContext: () => SlotContainedContext,
52092
52082
  SlotContentRenderer: () => SlotContentRenderer,
52093
52083
  SuspenseConfigProvider: () => SuspenseConfigProvider,
52094
52084
  UISlotComponent: () => UISlotComponent,
@@ -52261,6 +52251,25 @@ function renderContainedPortal(t, slot, content, onDismiss) {
52261
52251
  }
52262
52252
  );
52263
52253
  case "drawer":
52254
+ if (content.pattern === "detail-panel" && content.props.slideOver === true) {
52255
+ return /* @__PURE__ */ jsx(
52256
+ Box,
52257
+ {
52258
+ id: slotId,
52259
+ className: "absolute inset-0 z-50 overflow-hidden",
52260
+ style: { backgroundColor: "rgba(0, 0, 0, 0.5)" },
52261
+ onClick: onDismiss,
52262
+ children: /* @__PURE__ */ jsx(
52263
+ Box,
52264
+ {
52265
+ className: "absolute inset-y-0 right-0 pointer-events-auto",
52266
+ onClick: (e) => e.stopPropagation(),
52267
+ children: slotContent
52268
+ }
52269
+ )
52270
+ }
52271
+ );
52272
+ }
52264
52273
  return /* @__PURE__ */ jsx(
52265
52274
  Box,
52266
52275
  {
@@ -53112,7 +53121,7 @@ function UISlotRenderer({
53112
53121
  }
53113
53122
  return wrapped;
53114
53123
  }
53115
- var scopeWrapLog, TRAIT_BINDING_RE, SuspenseConfigContext, SlotContainedContext, SLOT_SKELETON_MAP, CONTENT_NODE_SLOTS, PATTERNS_WITH_CHILDREN, traitRefPresenceCache;
53124
+ var scopeWrapLog, TRAIT_BINDING_RE, SuspenseConfigContext, SLOT_SKELETON_MAP, CONTENT_NODE_SLOTS, PATTERNS_WITH_CHILDREN, traitRefPresenceCache;
53116
53125
  var init_UISlotRenderer = __esm({
53117
53126
  "components/core/organisms/UISlotRenderer.tsx"() {
53118
53127
  "use client";
@@ -53127,6 +53136,7 @@ var init_UISlotRenderer = __esm({
53127
53136
  init_cn();
53128
53137
  init_format();
53129
53138
  init_portalRoot();
53139
+ init_slotContained();
53130
53140
  init_ErrorBoundary();
53131
53141
  init_Skeleton();
53132
53142
  init_renderer();
@@ -53136,7 +53146,6 @@ var init_UISlotRenderer = __esm({
53136
53146
  scopeWrapLog = createLogger("almadar:ui:scope-wrap");
53137
53147
  TRAIT_BINDING_RE = /^@trait\.([A-Z][A-Za-z0-9]*)$/;
53138
53148
  SuspenseConfigContext = createContext({ enabled: false });
53139
- SlotContainedContext = createContext(false);
53140
53149
  SuspenseConfigProvider.displayName = "SuspenseConfigProvider";
53141
53150
  SLOT_SKELETON_MAP = {
53142
53151
  main: "table",
@@ -54604,6 +54613,9 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
54604
54613
  const normalizedEvent = normalizeEventKey(eventKey);
54605
54614
  return managerRef.current.canHandleEvent(traitName, normalizedEvent);
54606
54615
  }, []);
54616
+ const commitServerEntity = useCallback((traitName, entity) => {
54617
+ traitFieldStatesRef.current.set(traitName, entity);
54618
+ }, []);
54607
54619
  useEffect(() => {
54608
54620
  const allEvents = /* @__PURE__ */ new Set();
54609
54621
  for (const binding of traitBindings) {
@@ -54767,7 +54779,8 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
54767
54779
  sendEvent,
54768
54780
  getTraitState,
54769
54781
  canHandleEvent,
54770
- entityBindingSource
54782
+ entityBindingSource,
54783
+ commitServerEntity
54771
54784
  };
54772
54785
  }
54773
54786
  var resolvedSchemaLog = createLogger("almadar:ui:resolved-schema");
@@ -54893,7 +54906,7 @@ function normalizeChild(child) {
54893
54906
  function effectResultsToTraces(results) {
54894
54907
  if (!results) return [];
54895
54908
  return results.map((r) => {
54896
- const resultId = r.data !== void 0 && r.data !== null && "id" in r.data && typeof r.data.id === "string" ? r.data.id : void 0;
54909
+ const resultId = typeof r.data === "object" && r.data !== null && !Array.isArray(r.data) && "id" in r.data && typeof r.data.id === "string" ? r.data.id : void 0;
54897
54910
  const outcome = r.denied ? "denied" : r.success ? "success" : "failed";
54898
54911
  return {
54899
54912
  type: r.effect,
@@ -55006,6 +55019,8 @@ function TraitInitializer({ traits: traits2, routeParams, orbitalNames, onNaviga
55006
55019
  [serverActiveTraits]
55007
55020
  );
55008
55021
  const uiSlots = useUISlots();
55022
+ const commitServerEntityRef = useRef(() => {
55023
+ });
55009
55024
  const onEventProcessed = useCallback((event, payload, dispatchedOrbitals, tick, sourceTrait, locallyEmitted, results, entityByTrait) => {
55010
55025
  if (!bridge.connected || !orbitalNames?.length) return;
55011
55026
  const targets = dispatchedOrbitals && dispatchedOrbitals.size > 0 ? orbitalNames.filter((n) => dispatchedOrbitals.has(n)) : orbitalNames;
@@ -55022,12 +55037,18 @@ function TraitInitializer({ traits: traits2, routeParams, orbitalNames, onNaviga
55022
55037
  }
55023
55038
  void bridge.sendEvent(name, event, withActiveTraits(payload), void 0, void 0, locallyEmitted, results, entityByTrait, user ?? void 0).then(({ effects, meta }) => {
55024
55039
  recordServerResponse(name, event, { ...meta, effectResults: effectResultsToTraces(meta.effectResults) });
55040
+ if (meta.entityByTrait) {
55041
+ for (const [traitName, entity] of Object.entries(meta.entityByTrait)) {
55042
+ commitServerEntityRef.current(traitName, entity);
55043
+ }
55044
+ }
55025
55045
  applyServerEffects(effects, uiSlots, onNavigate, embeddedTraits, activeTraitNamesRef.current, onNavigateBack);
55026
55046
  });
55027
55047
  }
55028
55048
  }, [bridge.connected, bridge.sendEvent, orbitalNames, uiSlots, onNavigate, onNavigateBack, embeddedTraits, activeTraitNames, withActiveTraits, user]);
55029
55049
  const opts = orbitalNames ? { onEventProcessed, navigate: onNavigate, navigateBack: onNavigateBack, traitConfigsByName, orbitalsByTrait, embeddedTraits, callsiteCaptureChildrenByTrait, initPayload: routeParams } : { navigate: onNavigate, navigateBack: onNavigateBack, persistence, traitConfigsByName, orbitalsByTrait, embeddedTraits, callsiteCaptureChildrenByTrait, initPayload: routeParams };
55030
- const { sendEvent, entityBindingSource } = useTraitStateMachine(traits2, uiSlots, opts);
55050
+ const { sendEvent, entityBindingSource, commitServerEntity } = useTraitStateMachine(traits2, uiSlots, opts);
55051
+ commitServerEntityRef.current = commitServerEntity;
55031
55052
  const initSentRef = useRef(false);
55032
55053
  const prevTraitsRef = useRef(void 0);
55033
55054
  const paramsKey = JSON.stringify(routeParams ?? {});
@@ -55079,6 +55100,11 @@ function TraitInitializer({ traits: traits2, routeParams, orbitalNames, onNaviga
55079
55100
  user ?? void 0
55080
55101
  );
55081
55102
  recordServerResponse(name, "INIT", { ...meta, effectResults: effectResultsToTraces(meta.effectResults) });
55103
+ if (meta.entityByTrait) {
55104
+ for (const [traitName, entity] of Object.entries(meta.entityByTrait)) {
55105
+ commitServerEntityRef.current(traitName, entity);
55106
+ }
55107
+ }
55082
55108
  const effectTraces = [
55083
55109
  { type: "fetch", args: [], status: "executed" },
55084
55110
  ...effects.map((eff) => ({