@homebound/beam 4.24.0 → 4.25.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -6894,17 +6894,17 @@ function useComputed(fn, deps) {
6894
6894
  hasRan: false
6895
6895
  });
6896
6896
  useMemo5(() => {
6897
- const { current } = ref;
6898
- if (current.runner) {
6899
- current.runner();
6897
+ const { current: current2 } = ref;
6898
+ if (current2.runner) {
6899
+ current2.runner();
6900
6900
  }
6901
- current.hasRan = false;
6902
- current.runner = autorun(() => {
6903
- const { value: oldValue, hasRan } = current;
6901
+ current2.hasRan = false;
6902
+ current2.runner = autorun(() => {
6903
+ const { value: oldValue, hasRan } = current2;
6904
6904
  const newValue = fn(oldValue);
6905
6905
  if (hasRan && shallowEqual(newValue, oldValue)) return;
6906
- current.value = newValue;
6907
- current.hasRan = true;
6906
+ current2.value = newValue;
6907
+ current2.hasRan = true;
6908
6908
  if (hasRan) {
6909
6909
  setTick((tick) => tick + 1);
6910
6910
  }
@@ -6930,6 +6930,7 @@ function useHover2(props) {
6930
6930
  var beamEnvironmentBannerLayoutHeightVar = "--beam-environment-banner-height";
6931
6931
  var beamNavbarLayoutHeightVar = "--beam-navbar-layout-height";
6932
6932
  var beamPageHeaderLayoutHeightVar = "--beam-page-header-layout-height";
6933
+ var beamPageBannerHeightVar = "--beam-page-banner-height";
6933
6934
  var beamLayoutViewportWidthVar = "--beam-layout-viewport-width";
6934
6935
  var beamLayoutViewportHeightVar = "--beam-layout-viewport-height";
6935
6936
  var beamSideNavLayoutWidthVar = "--beam-side-nav-layout-width";
@@ -6963,24 +6964,27 @@ function documentScrollBodyMinHeight() {
6963
6964
  function documentScrollRightPaneWidthCss(maxPx) {
6964
6965
  return `min(${maxPx}px, ${documentScrollChromeWidth()})`;
6965
6966
  }
6966
- function bannerAndNavbarChromeTop() {
6967
+ function belowNavbarOffset() {
6967
6968
  return `calc(var(${beamEnvironmentBannerLayoutHeightVar}, 0px) + var(${beamNavbarLayoutHeightVar}, 0px))`;
6968
6969
  }
6970
+ function pageBannerOffset() {
6971
+ return `calc(var(${beamEnvironmentBannerLayoutHeightVar}, 0px) + var(${beamNavbarLayoutHeightVar}, 0px) + var(${beamPageHeaderLayoutHeightVar}, 0px))`;
6972
+ }
6969
6973
  function stickyNavAndHeaderOffset(basePx = 0) {
6970
- return `calc(${basePx}px + var(${beamEnvironmentBannerLayoutHeightVar}, 0px) + var(${beamNavbarLayoutHeightVar}, 0px) + var(${beamPageHeaderLayoutHeightVar}, 0px))`;
6974
+ return `calc(${basePx}px + var(${beamEnvironmentBannerLayoutHeightVar}, 0px) + var(${beamNavbarLayoutHeightVar}, 0px) + var(${beamPageHeaderLayoutHeightVar}, 0px) + var(${beamPageBannerHeightVar}, 0px))`;
6971
6975
  }
6972
6976
  function stickyNavAndHeaderOffsetPx(el) {
6973
6977
  const styles = getComputedStyle(el);
6974
6978
  const read = (name) => parseFloat(styles.getPropertyValue(name)) || 0;
6975
- return read(beamEnvironmentBannerLayoutHeightVar) + read(beamNavbarLayoutHeightVar) + read(beamPageHeaderLayoutHeightVar);
6979
+ return read(beamEnvironmentBannerLayoutHeightVar) + read(beamNavbarLayoutHeightVar) + read(beamPageHeaderLayoutHeightVar) + read(beamPageBannerHeightVar);
6976
6980
  }
6977
6981
  function stickyTableHeaderOffsetPx(el) {
6978
6982
  const styles = getComputedStyle(el);
6979
6983
  const read = (name) => parseFloat(styles.getPropertyValue(name)) || 0;
6980
- return read(beamEnvironmentBannerLayoutHeightVar) + read(beamNavbarLayoutHeightVar) + read(beamPageHeaderLayoutHeightVar) + read(beamTableActionsHeightVar);
6984
+ return read(beamEnvironmentBannerLayoutHeightVar) + read(beamNavbarLayoutHeightVar) + read(beamPageHeaderLayoutHeightVar) + read(beamPageBannerHeightVar) + read(beamTableActionsHeightVar);
6981
6985
  }
6982
6986
  function stickyTableHeaderOffset(basePx = 0) {
6983
- return `calc(${basePx}px + var(${beamEnvironmentBannerLayoutHeightVar}, 0px) + var(${beamNavbarLayoutHeightVar}, 0px) + var(${beamPageHeaderLayoutHeightVar}, 0px) + var(${beamTableActionsHeightVar}, 0px))`;
6987
+ return `calc(${basePx}px + var(${beamEnvironmentBannerLayoutHeightVar}, 0px) + var(${beamNavbarLayoutHeightVar}, 0px) + var(${beamPageHeaderLayoutHeightVar}, 0px) + var(${beamPageBannerHeightVar}, 0px) + var(${beamTableActionsHeightVar}, 0px))`;
6984
6988
  }
6985
6989
  function getFloatingBottomOffset(basePx = 0) {
6986
6990
  return `calc(${basePx}px + var(${beamWorkflowLayoutFooterHeightVar}, 0px))`;
@@ -7010,6 +7014,9 @@ var zIndices = {
7010
7014
  rightPane: 60,
7011
7015
  // Workflow floating right-pane triggers — above the pane, below sticky headers.
7012
7016
  rightPaneTriggers: 65,
7017
+ // Stay-pinned page banner under the header — above the floating triggers it pins above, and below
7018
+ // pageStickyHeader so the auto-hiding header paints over it during the slide.
7019
+ pageBanner: 68,
7013
7020
  pageStickyHeader: 70,
7014
7021
  // Sticky mobile action footer (workflow layouts) — same tier as pageStickyHeader; header and footer never overlap on screen.
7015
7022
  pageStickyFooter: 70,
@@ -7163,8 +7170,8 @@ function SortHeader(props) {
7163
7170
  const {
7164
7171
  tableState
7165
7172
  } = useContext5(TableStateContext);
7166
- const current = useComputed(() => tableState.sortState?.current, [tableState]);
7167
- const sorted = sortKey === current?.columnId ? current?.direction : void 0;
7173
+ const current2 = useComputed(() => tableState.sortState?.current, [tableState]);
7174
+ const sorted = sortKey === current2?.columnId ? current2?.direction : void 0;
7168
7175
  const toggleSort = useCallback2(() => tableState.setSortKey(sortKey), [sortKey, tableState]);
7169
7176
  const sortVisible = isHovered || sorted !== void 0;
7170
7177
  const tid = useTestIds(props, "sortHeader");
@@ -8357,8 +8364,8 @@ function sortRows(columns, rows, sortState, caseSensitive) {
8357
8364
  return sorted;
8358
8365
  }
8359
8366
  function sortFn(columns, sortState, caseSensitive) {
8360
- const { current, persistent } = sortState ?? {};
8361
- const { columnId, direction } = current ?? {};
8367
+ const { current: current2, persistent } = sortState ?? {};
8368
+ const { columnId, direction } = current2 ?? {};
8362
8369
  const { columnId: persistentSortColumnId, direction: persistentSortDirection } = persistent ?? {};
8363
8370
  const column2 = columns.find((c) => c.id === columnId);
8364
8371
  const invert = direction === "DESC";
@@ -19925,18 +19932,18 @@ function initializeOptions(optionsOrLoad, getOptionValue, getOptionLabel, unsetL
19925
19932
  } else {
19926
19933
  const {
19927
19934
  options,
19928
- current
19935
+ current: current2
19929
19936
  } = optionsOrLoad;
19930
19937
  if (options) {
19931
19938
  userOptions.push(...options);
19932
19939
  }
19933
- if (current) {
19934
- const toCheck = Array.isArray(current) ? current : [current];
19935
- toCheck.forEach((current2) => {
19936
- const value = getOptionValue(current2);
19940
+ if (current2) {
19941
+ const toCheck = Array.isArray(current2) ? current2 : [current2];
19942
+ toCheck.forEach((current3) => {
19943
+ const value = getOptionValue(current3);
19937
19944
  const found = options && options.find((o) => getOptionValue(o) === value);
19938
19945
  if (!found) {
19939
- userOptions.push(current2);
19946
+ userOptions.push(current3);
19940
19947
  }
19941
19948
  });
19942
19949
  }
@@ -29557,7 +29564,7 @@ function SideNavLayoutContent(props) {
29557
29564
  const collapsed = navState === "collapse";
29558
29565
  const showRail = navState !== "hidden" && !showMobileSubNav;
29559
29566
  const railOffsetPx = !showRail ? 0 : !bp.mdAndUp || collapsed ? railCollapsedWidthPx : railWidthPx;
29560
- const navTop = bannerAndNavbarChromeTop();
29567
+ const navTop = belowNavbarOffset();
29561
29568
  const railViewportHeight = `calc(var(${beamLayoutViewportHeightVar}, 100vh) - var(${beamEnvironmentBannerLayoutHeightVar}, 0px) - var(${beamNavbarLayoutHeightVar}, 0px))`;
29562
29569
  const rail = showRail && /* @__PURE__ */ jsxs126("div", { ...trussProps136({
29563
29570
  ...{
@@ -29879,14 +29886,14 @@ function useActiveJumpLink(sectionIds) {
29879
29886
  const first = ids.map((id) => document.getElementById(id)).find((el) => el !== null);
29880
29887
  if (!first) return;
29881
29888
  const headerOffset = stickyNavAndHeaderOffsetPx(first);
29882
- let current = ids[0];
29889
+ let current2 = ids[0];
29883
29890
  for (const id of ids) {
29884
29891
  const el = document.getElementById(id);
29885
29892
  if (el && el.getBoundingClientRect().top - headerOffset <= activationLeadPx) {
29886
- current = id;
29893
+ current2 = id;
29887
29894
  }
29888
29895
  }
29889
- setActiveId(current);
29896
+ setActiveId(current2);
29890
29897
  };
29891
29898
  update();
29892
29899
  window.addEventListener("scroll", update, { passive: true });
@@ -29973,12 +29980,66 @@ function FormSectionLayout(props) {
29973
29980
  return /* @__PURE__ */ jsx242(DocumentScrollOverlayRightPaneLayout, { paneWidth: rightPane.width, children: body });
29974
29981
  }
29975
29982
 
29983
+ // src/layouts/PageBanner/usePageBanner.tsx
29984
+ import { useEffect as useEffect40, useId as useId4, useLayoutEffect as useLayoutEffect14 } from "react";
29985
+
29986
+ // src/layouts/PageBanner/pageBannerStore.ts
29987
+ var current;
29988
+ var listeners = /* @__PURE__ */ new Set();
29989
+ var pageBannerStore = {
29990
+ subscribe: (listener) => {
29991
+ listeners.add(listener);
29992
+ return () => {
29993
+ listeners.delete(listener);
29994
+ };
29995
+ },
29996
+ getSnapshot: () => current?.banner
29997
+ };
29998
+ function notify() {
29999
+ listeners.forEach((listener) => listener());
30000
+ }
30001
+ function hasPageBannerSubscriber() {
30002
+ return listeners.size > 0;
30003
+ }
30004
+ function setPageBanner(id, banner) {
30005
+ const previous = current;
30006
+ if (previous?.id === id && previous.banner === banner) return;
30007
+ if (previous && previous.id !== id && process.env.NODE_ENV !== "production") {
30008
+ console.warn("[usePageBanner] A second page banner replaced the first; a layout shows one at a time.");
30009
+ }
30010
+ current = { id, banner };
30011
+ notify();
30012
+ }
30013
+ function clearPageBanner(id) {
30014
+ if (current?.id !== id) return;
30015
+ current = void 0;
30016
+ notify();
30017
+ }
30018
+
30019
+ // src/layouts/PageBanner/usePageBanner.tsx
30020
+ function usePageBanner(banner) {
30021
+ const id = useId4();
30022
+ useLayoutEffect14(() => {
30023
+ if (!banner) return;
30024
+ setPageBanner(id, banner);
30025
+ return () => clearPageBanner(id);
30026
+ }, [id, banner]);
30027
+ useEffect40(() => {
30028
+ if (!banner || hasPageBannerSubscriber() || process.env.NODE_ENV === "production") return;
30029
+ console.warn("[usePageBanner] No page layout above this component; the banner will not render.");
30030
+ }, [banner]);
30031
+ }
30032
+ function PageBanner(props) {
30033
+ usePageBanner(props);
30034
+ return null;
30035
+ }
30036
+
29976
30037
  // src/layouts/NavbarLayout/NavbarLayout.tsx
29977
30038
  import { useMemo as useMemo58, useRef as useRef72 } from "react";
29978
30039
  import { mergeProps as mergeProps41, maybeCssVar as maybeCssVar69 } from "@homebound/truss/runtime";
29979
30040
 
29980
30041
  // src/layouts/useAutoHideOnScroll.ts
29981
- import { useLayoutEffect as useLayoutEffect14, useRef as useRef71, useState as useState62 } from "react";
30042
+ import { useLayoutEffect as useLayoutEffect15, useRef as useRef71, useState as useState62 } from "react";
29982
30043
  var THRESHOLD = 80;
29983
30044
  function getInitialAutoHideState() {
29984
30045
  if (typeof window === "undefined" || window.scrollY <= 0) {
@@ -29994,7 +30055,7 @@ function useAutoHideOnScroll(spacerRef, enabled, getTopOffset) {
29994
30055
  getTopOffsetRef.current = getTopOffset;
29995
30056
  const lastScrollY = useRef71(Number.POSITIVE_INFINITY);
29996
30057
  const lastScrollHeight = useRef71(0);
29997
- useLayoutEffect14(() => {
30058
+ useLayoutEffect15(() => {
29998
30059
  if (!enabled) {
29999
30060
  stateRef.current = "resting";
30000
30061
  lastScrollY.current = Number.POSITIVE_INFINITY;
@@ -30060,7 +30121,7 @@ function useAutoHideOnScroll(spacerRef, enabled, getTopOffset) {
30060
30121
 
30061
30122
  // src/layouts/useMeasuredHeight.ts
30062
30123
  import { useResizeObserver as useResizeObserver12 } from "@react-aria/utils";
30063
- import { useCallback as useCallback44, useLayoutEffect as useLayoutEffect15, useState as useState63 } from "react";
30124
+ import { useCallback as useCallback44, useLayoutEffect as useLayoutEffect16, useState as useState63 } from "react";
30064
30125
  function useMeasuredHeight(ref, enabled) {
30065
30126
  const [height, setHeight] = useState63(0);
30066
30127
  const syncElementHeight = useCallback44(() => {
@@ -30069,16 +30130,16 @@ function useMeasuredHeight(ref, enabled) {
30069
30130
  setHeight((prev) => prev === next ? prev : next);
30070
30131
  }, [ref]);
30071
30132
  useResizeObserver12({ ref, onResize: syncElementHeight });
30072
- useLayoutEffect15(() => {
30133
+ useLayoutEffect16(() => {
30073
30134
  syncElementHeight();
30074
30135
  }, [enabled, syncElementHeight]);
30075
30136
  return height;
30076
30137
  }
30077
30138
 
30078
30139
  // src/layouts/useTransitionAfterPaint.ts
30079
- import { useLayoutEffect as useLayoutEffect16 } from "react";
30140
+ import { useLayoutEffect as useLayoutEffect17 } from "react";
30080
30141
  function useTransitionAfterPaint(ref, transition) {
30081
- useLayoutEffect16(() => {
30142
+ useLayoutEffect17(() => {
30082
30143
  const el = ref.current;
30083
30144
  if (!el) return;
30084
30145
  const id = requestAnimationFrame(() => {
@@ -30155,14 +30216,14 @@ function NavbarLayout(props) {
30155
30216
  }
30156
30217
 
30157
30218
  // src/layouts/PageHeaderLayout/PageHeaderLayout.tsx
30158
- import { useCallback as useCallback45, useMemo as useMemo59, useRef as useRef73 } from "react";
30219
+ import { useCallback as useCallback46, useMemo as useMemo59, useRef as useRef74 } from "react";
30159
30220
 
30160
30221
  // src/hooks/useDocumentTitle.tsx
30161
- import { useLayoutEffect as useLayoutEffect17 } from "react";
30222
+ import { useLayoutEffect as useLayoutEffect18 } from "react";
30162
30223
  function useDocumentTitle(...titleSegments) {
30163
30224
  const config = useDocumentTitleConfig();
30164
30225
  const pageTitle = joinDocumentTitleSegments(...titleSegments);
30165
- useLayoutEffect17(() => {
30226
+ useLayoutEffect18(() => {
30166
30227
  if (!config || !pageTitle || typeof document === "undefined") {
30167
30228
  return;
30168
30229
  }
@@ -30267,94 +30328,162 @@ function PageHeader2(props) {
30267
30328
  ] }) });
30268
30329
  }
30269
30330
 
30331
+ // src/layouts/PageBanner/internal/usePageBannerSlot.tsx
30332
+ import { useCallback as useCallback45, useLayoutEffect as useLayoutEffect19, useRef as useRef73, useState as useState64 } from "react";
30333
+
30334
+ // src/layouts/PageBanner/internal/PageBannerSlot.tsx
30335
+ import { trussProps as trussProps144, maybeCssVar as maybeCssVar70 } from "@homebound/truss/runtime";
30336
+ import { jsx as jsx247 } from "react/jsx-runtime";
30337
+ var __maybeInc34 = (inc) => {
30338
+ return typeof inc === "string" ? inc : `calc(var(--t-spacing) * ${inc})`;
30339
+ };
30340
+ function PageBannerSlot(props) {
30341
+ const {
30342
+ banner,
30343
+ metricsRef
30344
+ } = props;
30345
+ const tid = useTestIds(props, "pageBannerSlot");
30346
+ return /* @__PURE__ */ jsx247("div", { ref: metricsRef, ...trussProps144({
30347
+ flexShrink: "fs0",
30348
+ width: ["w_var", {
30349
+ "--width": maybeCssVar70(__maybeInc34(`min(100%, ${documentScrollChromeWidth()})`))
30350
+ }],
30351
+ transition: "transitionTop",
30352
+ position: "sticky",
30353
+ top: ["top_var", {
30354
+ "--top": maybeCssVar70(__maybeInc34(pageBannerOffset()))
30355
+ }],
30356
+ left: ["left_var", {
30357
+ "--left": maybeCssVar70(__maybeInc34(documentScrollChromeLeft()))
30358
+ }],
30359
+ zIndex: ["z_var", {
30360
+ "--zIndex": maybeCssVar70(zIndices.pageBanner)
30361
+ }]
30362
+ }), ...tid.bannerSticky, children: /* @__PURE__ */ jsx247(StatusBanner, { ...banner, sticky: true, ...tid.banner }) });
30363
+ }
30364
+
30365
+ // src/layouts/PageBanner/internal/usePageBannerSlot.tsx
30366
+ import { jsx as jsx248 } from "react/jsx-runtime";
30367
+ function usePageBannerSlot(bannerProp, testIds) {
30368
+ const publishedBanner = usePublishedPageBanner();
30369
+ const banner = publishedBanner ?? bannerProp;
30370
+ const metricsRef = useRef73(null);
30371
+ const height = useMeasuredHeight(metricsRef, banner != null);
30372
+ const slot = banner ? /* @__PURE__ */ jsx248(PageBannerSlot, { ...testIds, banner, metricsRef }) : null;
30373
+ return { slot, height };
30374
+ }
30375
+ function usePublishedPageBanner() {
30376
+ const [banner, setBanner] = useState64(pageBannerStore.getSnapshot);
30377
+ const sync = useCallback45(() => {
30378
+ const next = pageBannerStore.getSnapshot();
30379
+ setBanner((prev) => prev === next ? prev : next);
30380
+ }, []);
30381
+ useLayoutEffect19(() => {
30382
+ sync();
30383
+ return pageBannerStore.subscribe(sync);
30384
+ }, [sync]);
30385
+ return banner;
30386
+ }
30387
+
30270
30388
  // src/layouts/useBannerAndNavbarHeight.ts
30271
30389
  function useBannerAndNavbarHeight() {
30272
30390
  return useEnvironmentBannerLayoutHeight() + useNavbarLayoutHeight();
30273
30391
  }
30274
30392
 
30275
30393
  // src/layouts/PageHeaderLayout/PageHeaderLayout.tsx
30276
- import { mergeProps as mergeProps42, maybeCssVar as maybeCssVar70 } from "@homebound/truss/runtime";
30277
- import { jsx as jsx247, jsxs as jsxs134 } from "react/jsx-runtime";
30278
- var __maybeInc34 = (inc) => {
30394
+ import { mergeProps as mergeProps42, maybeCssVar as maybeCssVar71 } from "@homebound/truss/runtime";
30395
+ import { jsx as jsx249, jsxs as jsxs134 } from "react/jsx-runtime";
30396
+ var __maybeInc35 = (inc) => {
30279
30397
  return typeof inc === "string" ? inc : `calc(var(--t-spacing) * ${inc})`;
30280
30398
  };
30281
30399
  function PageHeaderLayout(props) {
30282
30400
  const {
30283
30401
  pageHeader,
30402
+ banner: bannerProp,
30284
30403
  children
30285
30404
  } = props;
30286
30405
  const tid = useTestIds(props, "pageHeaderLayout");
30406
+ const {
30407
+ slot: bannerSlot,
30408
+ height: bannerHeight
30409
+ } = usePageBannerSlot(bannerProp, tid);
30287
30410
  const bannerAndNavbarHeight = useBannerAndNavbarHeight();
30288
- const bannerAndNavbarHeightRef = useRef73(bannerAndNavbarHeight);
30411
+ const bannerAndNavbarHeightRef = useRef74(bannerAndNavbarHeight);
30289
30412
  bannerAndNavbarHeightRef.current = bannerAndNavbarHeight;
30290
- const getBannerAndNavbarHeight = useCallback45(() => bannerAndNavbarHeightRef.current, []);
30291
- const headerMetricsRef = useRef73(null);
30292
- const spacerRef = useRef73(null);
30413
+ const getBannerAndNavbarHeight = useCallback46(() => bannerAndNavbarHeightRef.current, []);
30414
+ const headerMetricsRef = useRef74(null);
30415
+ const spacerRef = useRef74(null);
30293
30416
  const headerHeight = useMeasuredHeight(headerMetricsRef, true);
30294
30417
  const {
30295
30418
  state: autoHideState
30296
30419
  } = useAutoHideOnScroll(spacerRef, true, getBannerAndNavbarHeight);
30297
30420
  const headerOccupiesPosition = autoHideState !== "hidden";
30298
- const cssVars = headerHeight > 0 && headerOccupiesPosition ? {
30299
- [beamPageHeaderLayoutHeightVar]: `${headerHeight}px`
30300
- } : void 0;
30421
+ const cssVars = {};
30422
+ if (headerHeight > 0 && headerOccupiesPosition) {
30423
+ cssVars[beamPageHeaderLayoutHeightVar] = `${headerHeight}px`;
30424
+ }
30425
+ if (bannerHeight > 0) {
30426
+ cssVars[beamPageBannerHeightVar] = `${bannerHeight}px`;
30427
+ }
30428
+ const style = Object.keys(cssVars).length > 0 ? cssVars : void 0;
30301
30429
  const headerLeft = documentScrollChromeLeft();
30302
30430
  const headerWidth = documentScrollChromeWidth();
30303
- const outerTop = bannerAndNavbarChromeTop();
30431
+ const outerTop = belowNavbarOffset();
30304
30432
  const innerCss = {
30305
30433
  position: "fixed",
30306
30434
  left: ["left_var", {
30307
- "--left": maybeCssVar70(__maybeInc34(headerLeft))
30435
+ "--left": maybeCssVar71(__maybeInc35(headerLeft))
30308
30436
  }],
30309
30437
  width: ["w_var", {
30310
- "--width": maybeCssVar70(__maybeInc34(headerWidth))
30438
+ "--width": maybeCssVar71(__maybeInc35(headerWidth))
30311
30439
  }],
30312
30440
  zIndex: ["z_var", {
30313
- "--zIndex": maybeCssVar70(zIndices.pageStickyHeader)
30441
+ "--zIndex": maybeCssVar71(zIndices.pageStickyHeader)
30314
30442
  }]
30315
30443
  };
30316
30444
  useTransitionAfterPaint(headerMetricsRef, "all 200ms cubic-bezier(0.4, 0, 0.2, 1)");
30317
30445
  const innerStyle = {
30318
30446
  top: autoHideState === "hidden" ? `calc(${outerTop} - ${headerHeight}px)` : outerTop
30319
30447
  };
30320
- const pageHeaderEl = useMemo59(() => /* @__PURE__ */ jsx247(PageHeader2, { ...pageHeader }), [pageHeader]);
30321
- return /* @__PURE__ */ jsx247(DocumentScrollLayoutProvider, { children: /* @__PURE__ */ jsxs134("div", { ...mergeProps42(void 0, cssVars, {
30448
+ const pageHeaderEl = useMemo59(() => /* @__PURE__ */ jsx249(PageHeader2, { ...pageHeader }), [pageHeader]);
30449
+ return /* @__PURE__ */ jsx249(DocumentScrollLayoutProvider, { children: /* @__PURE__ */ jsxs134("div", { ...mergeProps42(void 0, style, {
30322
30450
  display: "df",
30323
30451
  flexDirection: "fdc",
30324
30452
  width: "w100"
30325
30453
  }), ...tid, children: [
30326
- /* @__PURE__ */ jsx247("div", { ref: spacerRef, ...mergeProps42(void 0, {
30454
+ /* @__PURE__ */ jsx249("div", { ref: spacerRef, ...mergeProps42(void 0, {
30327
30455
  height: headerHeight
30328
30456
  }, {
30329
30457
  flexShrink: "fs0",
30330
30458
  width: "w100"
30331
- }), children: /* @__PURE__ */ jsx247("div", { ref: headerMetricsRef, ...mergeProps42(void 0, innerStyle, innerCss), ...tid.pageHeader, children: pageHeaderEl }) }),
30332
- /* @__PURE__ */ jsx247("div", { className: "df fdc fg1 mh0 w100 n_has_data_self_top_spaced_first_child_pt3", ...tid.body, children })
30459
+ }), children: /* @__PURE__ */ jsx249("div", { ref: headerMetricsRef, ...mergeProps42(void 0, innerStyle, innerCss), ...tid.pageHeader, children: pageHeaderEl }) }),
30460
+ bannerSlot,
30461
+ /* @__PURE__ */ jsx249("div", { className: "df fdc fg1 mh0 w100 n_has_data_self_top_spaced_first_child_pt3", ...tid.body, children })
30333
30462
  ] }) });
30334
30463
  }
30335
30464
 
30336
30465
  // src/layouts/Workflow/WorkflowPageLayout.tsx
30337
- import { useLayoutEffect as useLayoutEffect18, useRef as useRef75 } from "react";
30466
+ import { useLayoutEffect as useLayoutEffect20, useRef as useRef76 } from "react";
30338
30467
 
30339
30468
  // src/components/Headers/WorkflowHeader.tsx
30340
- import { jsx as jsx248 } from "react/jsx-runtime";
30469
+ import { jsx as jsx250 } from "react/jsx-runtime";
30341
30470
  function WorkflowHeader(props) {
30342
30471
  const { stepperTabs, ...otherProps } = props;
30343
30472
  const tid = useTestIds(otherProps, "header");
30344
- return /* @__PURE__ */ jsx248(
30473
+ return /* @__PURE__ */ jsx250(
30345
30474
  BaseHeader,
30346
30475
  {
30347
30476
  ...otherProps,
30348
- bottomSlot: stepperTabs ? /* @__PURE__ */ jsx248(StepperTabs, { ...stepperTabs, ...tid.stepperTabs }) : void 0
30477
+ bottomSlot: stepperTabs ? /* @__PURE__ */ jsx250(StepperTabs, { ...stepperTabs, ...tid.stepperTabs }) : void 0
30349
30478
  }
30350
30479
  );
30351
30480
  }
30352
30481
 
30353
30482
  // src/layouts/Workflow/RightPaneTriggers.tsx
30354
- import { useCallback as useCallback46 } from "react";
30355
- import { trussProps as trussProps144, maybeCssVar as maybeCssVar71 } from "@homebound/truss/runtime";
30356
- import { jsx as jsx249 } from "react/jsx-runtime";
30357
- var __maybeInc35 = (inc) => {
30483
+ import { useCallback as useCallback47 } from "react";
30484
+ import { trussProps as trussProps145, maybeCssVar as maybeCssVar72 } from "@homebound/truss/runtime";
30485
+ import { jsx as jsx251 } from "react/jsx-runtime";
30486
+ var __maybeInc36 = (inc) => {
30358
30487
  return typeof inc === "string" ? inc : `calc(var(--t-spacing) * ${inc})`;
30359
30488
  };
30360
30489
  function WorkflowPageRightPaneTriggers(props) {
@@ -30372,14 +30501,14 @@ function WorkflowPageRightPaneTriggers(props) {
30372
30501
  } = useRightPaneActions();
30373
30502
  const tid = useTestIds(props, "rightPaneTriggers");
30374
30503
  const pageTriggerInsetPx = 24;
30375
- const onClick = useCallback46((trigger) => {
30504
+ const onClick = useCallback47((trigger) => {
30376
30505
  openRightPane({
30377
- content: /* @__PURE__ */ jsx249(RightPanePanel, { title: trigger.label, children: trigger.content })
30506
+ content: /* @__PURE__ */ jsx251(RightPanePanel, { title: trigger.label, children: trigger.content })
30378
30507
  });
30379
30508
  }, [openRightPane]);
30380
- return /* @__PURE__ */ jsx249("div", { ...tid, "aria-hidden": isRightPaneOpen, ...isRightPaneOpen ? {
30509
+ return /* @__PURE__ */ jsx251("div", { ...tid, "aria-hidden": isRightPaneOpen, ...isRightPaneOpen ? {
30381
30510
  inert: true
30382
- } : {}, ...trussProps144({
30511
+ } : {}, ...trussProps145({
30383
30512
  ...{
30384
30513
  display: "df",
30385
30514
  alignItems: "aic",
@@ -30393,40 +30522,40 @@ function WorkflowPageRightPaneTriggers(props) {
30393
30522
  ...!isMobile && {
30394
30523
  position: "fixed",
30395
30524
  top: ["top_var", {
30396
- "--top": maybeCssVar71(__maybeInc35(stickyNavAndHeaderOffset(pageTriggerInsetPx)))
30525
+ "--top": maybeCssVar72(__maybeInc36(stickyNavAndHeaderOffset(pageTriggerInsetPx)))
30397
30526
  }],
30398
30527
  right: ["right_var", {
30399
30528
  "--right": `${pageTriggerInsetPx}px`
30400
30529
  }],
30401
30530
  zIndex: ["z_var", {
30402
- "--zIndex": maybeCssVar71(zIndices.rightPaneTriggers)
30531
+ "--zIndex": maybeCssVar72(zIndices.rightPaneTriggers)
30403
30532
  }]
30404
30533
  },
30405
30534
  // Desktop only — on `sm` the full-bleed pane covers the header slot.
30406
30535
  ...!isMobile && (isRightPaneOpen ? {
30407
30536
  transform: ["transform_var", {
30408
- "--transform": maybeCssVar71(`translateX(calc(100% + ${pageTriggerInsetPx}px))`)
30537
+ "--transform": maybeCssVar72(`translateX(calc(100% + ${pageTriggerInsetPx}px))`)
30409
30538
  }],
30410
30539
  pointerEvents: "pen"
30411
30540
  } : {
30412
30541
  transform: "tf_translateX_0"
30413
30542
  })
30414
- }), children: triggers.map((trigger) => /* @__PURE__ */ jsx249(IconButton, { icon: trigger.icon, label: trigger.label, variant: "circle", compact: isMobile, onClick: () => onClick(trigger), ...tid[trigger.icon] }, trigger.label)) });
30543
+ }), children: triggers.map((trigger) => /* @__PURE__ */ jsx251(IconButton, { icon: trigger.icon, label: trigger.label, variant: "circle", compact: isMobile, onClick: () => onClick(trigger), ...tid[trigger.icon] }, trigger.label)) });
30415
30544
  }
30416
30545
 
30417
30546
  // src/layouts/Workflow/useUnsavedChangesGuard.tsx
30418
- import { useEffect as useEffect40, useRef as useRef74 } from "react";
30547
+ import { useEffect as useEffect41, useRef as useRef75 } from "react";
30419
30548
  import { useBlocker } from "react-router-dom";
30420
- import { jsx as jsx250 } from "react/jsx-runtime";
30549
+ import { jsx as jsx252 } from "react/jsx-runtime";
30421
30550
  function useUnsavedChangesGuard(options) {
30422
30551
  const { isDirty, allowNavigation, onCancel } = options;
30423
30552
  const { openModal } = useModal();
30424
- const isDirtyRef = useRef74(isDirty);
30553
+ const isDirtyRef = useRef75(isDirty);
30425
30554
  isDirtyRef.current = isDirty;
30426
- const allowNavigationRef = useRef74(allowNavigation);
30555
+ const allowNavigationRef = useRef75(allowNavigation);
30427
30556
  allowNavigationRef.current = allowNavigation;
30428
- const allowCancelNavigationRef = useRef74(false);
30429
- useEffect40(() => {
30557
+ const allowCancelNavigationRef = useRef75(false);
30558
+ useEffect41(() => {
30430
30559
  const onBeforeUnload = (e) => {
30431
30560
  if (isDirtyRef.current?.()) {
30432
30561
  e.preventDefault();
@@ -30453,7 +30582,7 @@ function useUnsavedChangesGuard(options) {
30453
30582
  }
30454
30583
  openModal({
30455
30584
  allowClosing: false,
30456
- content: /* @__PURE__ */ jsx250(ConfirmCloseModal, { onClose: () => confirmCancel(e) })
30585
+ content: /* @__PURE__ */ jsx252(ConfirmCloseModal, { onClose: () => confirmCancel(e) })
30457
30586
  });
30458
30587
  };
30459
30588
  const navigationBlocker = blocker.state === "blocked" ? { proceed: () => blocker.proceed?.(), cancelNavigation: () => blocker.reset?.() } : void 0;
@@ -30462,10 +30591,10 @@ function useUnsavedChangesGuard(options) {
30462
30591
  function UnsavedChangesNavigationModal(props) {
30463
30592
  const { proceed, cancelNavigation } = props;
30464
30593
  const { openModal, closeModal } = useModal();
30465
- useEffect40(() => {
30594
+ useEffect41(() => {
30466
30595
  openModal({
30467
30596
  allowClosing: false,
30468
- content: /* @__PURE__ */ jsx250(ConfirmCloseModal, { title: "Leave page?", onClose: proceed, onContinue: cancelNavigation })
30597
+ content: /* @__PURE__ */ jsx252(ConfirmCloseModal, { title: "Leave page?", onClose: proceed, onContinue: cancelNavigation })
30469
30598
  });
30470
30599
  return () => closeModal();
30471
30600
  }, []);
@@ -30473,7 +30602,7 @@ function UnsavedChangesNavigationModal(props) {
30473
30602
  }
30474
30603
 
30475
30604
  // src/layouts/Workflow/WorkflowActions.tsx
30476
- import { jsx as jsx251, jsxs as jsxs135 } from "react/jsx-runtime";
30605
+ import { jsx as jsx253, jsxs as jsxs135 } from "react/jsx-runtime";
30477
30606
  function WorkflowActions(props) {
30478
30607
  const {
30479
30608
  onCancel,
@@ -30492,11 +30621,11 @@ function WorkflowActions(props) {
30492
30621
  } = useBreakpoint();
30493
30622
  const primaryVariant = aiMode ? "ai" : "primary";
30494
30623
  return /* @__PURE__ */ jsxs135("div", { className: "df aic jcsb sm_w100", children: [
30495
- /* @__PURE__ */ jsx251("div", { className: "df aic", children: !isFirstStep && isMobile && onBack && /* @__PURE__ */ jsx251(IconButton, { icon: "arrowBack", label: "Back", onClick: onBack }) }),
30624
+ /* @__PURE__ */ jsx253("div", { className: "df aic", children: !isFirstStep && isMobile && onBack && /* @__PURE__ */ jsx253(IconButton, { icon: "arrowBack", label: "Back", onClick: onBack }) }),
30496
30625
  /* @__PURE__ */ jsxs135("div", { className: "df aic g_1", children: [
30497
- /* @__PURE__ */ jsx251(Button, { label: "Cancel", variant: "quaternary", onClick: onCancel }),
30498
- onSaveAndExit && /* @__PURE__ */ jsx251(Button, { label: "Save & Exit", variant: "secondary", onClick: onSaveAndExit }),
30499
- isLastStep ? /* @__PURE__ */ jsx251(Button, { label: completeLabel, variant: primaryVariant, onClick: onComplete, disabled: primaryDisabled }) : /* @__PURE__ */ jsx251(Button, { label: "Continue", variant: primaryVariant, onClick: async () => {
30626
+ /* @__PURE__ */ jsx253(Button, { label: "Cancel", variant: "quaternary", onClick: onCancel }),
30627
+ onSaveAndExit && /* @__PURE__ */ jsx253(Button, { label: "Save & Exit", variant: "secondary", onClick: onSaveAndExit }),
30628
+ isLastStep ? /* @__PURE__ */ jsx253(Button, { label: completeLabel, variant: primaryVariant, onClick: onComplete, disabled: primaryDisabled }) : /* @__PURE__ */ jsx253(Button, { label: "Continue", variant: primaryVariant, onClick: async () => {
30500
30629
  await onContinue?.();
30501
30630
  }, disabled: primaryDisabled })
30502
30631
  ] })
@@ -30504,9 +30633,9 @@ function WorkflowActions(props) {
30504
30633
  }
30505
30634
 
30506
30635
  // src/layouts/Workflow/WorkflowPageLayout.tsx
30507
- import { trussProps as trussProps145, mergeProps as mergeProps43, maybeCssVar as maybeCssVar72 } from "@homebound/truss/runtime";
30508
- import { jsx as jsx252, jsxs as jsxs136 } from "react/jsx-runtime";
30509
- var __maybeInc36 = (inc) => {
30636
+ import { trussProps as trussProps146, mergeProps as mergeProps43, maybeCssVar as maybeCssVar73 } from "@homebound/truss/runtime";
30637
+ import { jsx as jsx254, jsxs as jsxs136 } from "react/jsx-runtime";
30638
+ var __maybeInc37 = (inc) => {
30510
30639
  return typeof inc === "string" ? inc : `calc(var(--t-spacing) * ${inc})`;
30511
30640
  };
30512
30641
  var mobileFooterHeightPx = 80;
@@ -30522,9 +30651,14 @@ function WorkflowPageLayout(props) {
30522
30651
  breadcrumbs,
30523
30652
  onCancel,
30524
30653
  rightPaneTriggers,
30654
+ banner: bannerProp,
30525
30655
  ...actionProps
30526
30656
  } = props;
30527
30657
  const tid = useTestIds(props, "workflowPageLayout");
30658
+ const {
30659
+ slot: bannerSlot,
30660
+ height: bannerHeight
30661
+ } = usePageBannerSlot(bannerProp, tid);
30528
30662
  const {
30529
30663
  sm: isMobile
30530
30664
  } = useBreakpoint();
@@ -30536,18 +30670,23 @@ function WorkflowPageLayout(props) {
30536
30670
  allowNavigation,
30537
30671
  onCancel
30538
30672
  });
30539
- const actions = /* @__PURE__ */ jsx252(WorkflowActions, { ...actionProps, aiMode, onCancel: onCancelClick });
30673
+ const actions = /* @__PURE__ */ jsx254(WorkflowActions, { ...actionProps, aiMode, onCancel: onCancelClick });
30540
30674
  const triggers = rightPaneTriggers ?? [];
30541
- const pageTriggers = triggers.length > 0 ? /* @__PURE__ */ jsx252(WorkflowPageRightPaneTriggers, { triggers }) : void 0;
30542
- const headerMetricsRef = useRef75(null);
30675
+ const pageTriggers = triggers.length > 0 ? /* @__PURE__ */ jsx254(WorkflowPageRightPaneTriggers, { triggers }) : void 0;
30676
+ const headerMetricsRef = useRef76(null);
30543
30677
  const headerHeight = useMeasuredHeight(headerMetricsRef, true);
30544
30678
  const headerWidth = documentScrollChromeWidth();
30545
- const outerTop = bannerAndNavbarChromeTop();
30546
- const cssVars = headerHeight > 0 ? {
30547
- [beamPageHeaderLayoutHeightVar]: `${headerHeight}px`
30548
- } : void 0;
30679
+ const outerTop = belowNavbarOffset();
30680
+ const cssVars = {};
30681
+ if (headerHeight > 0) {
30682
+ cssVars[beamPageHeaderLayoutHeightVar] = `${headerHeight}px`;
30683
+ }
30684
+ if (bannerHeight > 0) {
30685
+ cssVars[beamPageBannerHeightVar] = `${bannerHeight}px`;
30686
+ }
30687
+ const style = Object.keys(cssVars).length > 0 ? cssVars : void 0;
30549
30688
  const showFooter = isMobile;
30550
- useLayoutEffect18(() => {
30689
+ useLayoutEffect20(() => {
30551
30690
  const root = document.documentElement;
30552
30691
  const previous = root.style.getPropertyValue(beamWorkflowLayoutFooterHeightVar);
30553
30692
  root.style.setProperty(beamWorkflowLayoutFooterHeightVar, showFooter ? `${mobileFooterHeightPx}px` : "0px");
@@ -30560,31 +30699,32 @@ function WorkflowPageLayout(props) {
30560
30699
  };
30561
30700
  }, [showFooter]);
30562
30701
  return /* @__PURE__ */ jsxs136(DocumentScrollLayoutProvider, { children: [
30563
- /* @__PURE__ */ jsxs136("div", { ...mergeProps43(void 0, cssVars, {
30702
+ /* @__PURE__ */ jsxs136("div", { ...mergeProps43(void 0, style, {
30564
30703
  display: "df",
30565
30704
  flexDirection: "fdc",
30566
30705
  width: "w100"
30567
30706
  }), ...tid, children: [
30568
- /* @__PURE__ */ jsx252("div", { ...mergeProps43(void 0, {
30707
+ /* @__PURE__ */ jsx254("div", { ...mergeProps43(void 0, {
30569
30708
  height: headerHeight
30570
30709
  }, {
30571
30710
  flexShrink: "fs0",
30572
30711
  width: "w100"
30573
- }), children: /* @__PURE__ */ jsx252("div", { ref: headerMetricsRef, ...trussProps145({
30712
+ }), children: /* @__PURE__ */ jsx254("div", { ref: headerMetricsRef, ...trussProps146({
30574
30713
  position: "fixed",
30575
30714
  left: "l_0",
30576
30715
  width: ["w_var", {
30577
- "--width": maybeCssVar72(__maybeInc36(headerWidth))
30716
+ "--width": maybeCssVar73(__maybeInc37(headerWidth))
30578
30717
  }],
30579
30718
  zIndex: ["z_var", {
30580
- "--zIndex": maybeCssVar72(zIndices.pageStickyHeader)
30719
+ "--zIndex": maybeCssVar73(zIndices.pageStickyHeader)
30581
30720
  }],
30582
30721
  top: ["top_var", {
30583
- "--top": maybeCssVar72(__maybeInc36(outerTop))
30722
+ "--top": maybeCssVar73(__maybeInc37(outerTop))
30584
30723
  }],
30585
30724
  transition: "transitionAll"
30586
- }), ...tid.header, children: /* @__PURE__ */ jsx252(WorkflowHeader, { title, documentTitleSuffix, breadcrumbs, rightSlot: isMobile ? pageTriggers : actions, stepperTabs }) }) }),
30587
- /* @__PURE__ */ jsx252("div", { ...trussProps145({
30725
+ }), ...tid.header, children: /* @__PURE__ */ jsx254(WorkflowHeader, { title, documentTitleSuffix, breadcrumbs, rightSlot: isMobile ? pageTriggers : actions, stepperTabs }) }) }),
30726
+ bannerSlot,
30727
+ /* @__PURE__ */ jsx254("div", { ...trussProps146({
30588
30728
  ...{
30589
30729
  display: "df",
30590
30730
  flexDirection: "fdc",
@@ -30596,29 +30736,29 @@ function WorkflowPageLayout(props) {
30596
30736
  ...aiMode && {
30597
30737
  backgroundImage: "aiBackground",
30598
30738
  minHeight: ["mh_var", {
30599
- "--minHeight": maybeCssVar72(documentScrollBodyMinHeight())
30739
+ "--minHeight": maybeCssVar73(documentScrollBodyMinHeight())
30600
30740
  }]
30601
30741
  }
30602
- }), ...tid.body, children: triggers.length > 0 ? /* @__PURE__ */ jsx252(DocumentScrollOverlayRightPaneLayout, { children }) : children }),
30742
+ }), ...tid.body, children: triggers.length > 0 ? /* @__PURE__ */ jsx254(DocumentScrollOverlayRightPaneLayout, { children }) : children }),
30603
30743
  !isMobile && pageTriggers,
30604
- showFooter && /* @__PURE__ */ jsx252("div", { ...trussProps145({
30744
+ showFooter && /* @__PURE__ */ jsx254("div", { ...trussProps146({
30605
30745
  flexShrink: "fs0",
30606
30746
  width: "w100",
30607
30747
  height: ["h_var", {
30608
30748
  "--height": `${mobileFooterHeightPx}px`
30609
30749
  }]
30610
- }), children: /* @__PURE__ */ jsx252("div", { ...trussProps145({
30750
+ }), children: /* @__PURE__ */ jsx254("div", { ...trussProps146({
30611
30751
  ...{
30612
30752
  position: "fixed",
30613
30753
  bottom: "bot_0",
30614
30754
  width: ["w_var", {
30615
- "--width": maybeCssVar72(__maybeInc36(headerWidth))
30755
+ "--width": maybeCssVar73(__maybeInc37(headerWidth))
30616
30756
  }],
30617
30757
  height: ["h_var", {
30618
30758
  "--height": `${mobileFooterHeightPx}px`
30619
30759
  }],
30620
30760
  zIndex: ["z_var", {
30621
- "--zIndex": maybeCssVar72(zIndices.pageStickyFooter)
30761
+ "--zIndex": maybeCssVar73(zIndices.pageStickyFooter)
30622
30762
  }],
30623
30763
  display: "df",
30624
30764
  alignItems: "aic",
@@ -30636,12 +30776,12 @@ function WorkflowPageLayout(props) {
30636
30776
  ...pageContentPaddingX
30637
30777
  }), ...tid.footer, children: actions }) })
30638
30778
  ] }),
30639
- navigationBlocker && /* @__PURE__ */ jsx252(UnsavedChangesNavigationModal, { ...navigationBlocker })
30779
+ navigationBlocker && /* @__PURE__ */ jsx254(UnsavedChangesNavigationModal, { ...navigationBlocker })
30640
30780
  ] });
30641
30781
  }
30642
30782
 
30643
30783
  // src/layouts/Workflow/FocusedFormLayout.tsx
30644
- import { jsx as jsx253 } from "react/jsx-runtime";
30784
+ import { jsx as jsx255 } from "react/jsx-runtime";
30645
30785
  function FocusedFormLayout(props) {
30646
30786
  const {
30647
30787
  onCancel,
@@ -30653,15 +30793,17 @@ function FocusedFormLayout(props) {
30653
30793
  allowNavigation,
30654
30794
  aiMode,
30655
30795
  rightPaneTriggers,
30796
+ banner,
30656
30797
  children,
30657
30798
  ...headerProps
30658
30799
  } = props;
30659
30800
  const tid = useTestIds(props, "focusedFormLayout");
30660
- return /* @__PURE__ */ jsx253(
30801
+ return /* @__PURE__ */ jsx255(
30661
30802
  WorkflowPageLayout,
30662
30803
  {
30663
30804
  ...tid,
30664
30805
  ...headerProps,
30806
+ banner,
30665
30807
  aiMode,
30666
30808
  isDirty,
30667
30809
  allowNavigation,
@@ -30677,8 +30819,8 @@ function FocusedFormLayout(props) {
30677
30819
  }
30678
30820
 
30679
30821
  // src/layouts/Workflow/StepperLayout.tsx
30680
- import { useState as useState64 } from "react";
30681
- import { jsx as jsx254 } from "react/jsx-runtime";
30822
+ import { useState as useState65 } from "react";
30823
+ import { jsx as jsx256 } from "react/jsx-runtime";
30682
30824
  function StepperLayout(props) {
30683
30825
  const {
30684
30826
  steps,
@@ -30690,10 +30832,11 @@ function StepperLayout(props) {
30690
30832
  isDirty,
30691
30833
  allowNavigation,
30692
30834
  aiMode,
30835
+ banner,
30693
30836
  ...headerProps
30694
30837
  } = props;
30695
30838
  const stepTabs = steps.map((step) => ({ ...step, value: defaultTestId(step.label) }));
30696
- const [currentStep, setCurrentStep] = useState64(() => getInitialStep(stepTabs, defaultStep));
30839
+ const [currentStep, setCurrentStep] = useState65(() => getInitialStep(stepTabs, defaultStep));
30697
30840
  const tid = useTestIds(props, "stepperLayout");
30698
30841
  const { closeRightPane } = useRightPaneActions();
30699
30842
  const currentIndex = hasStep(stepTabs, currentStep) ? stepTabs.findIndex((step) => step.value === currentStep) : 0;
@@ -30705,11 +30848,12 @@ function StepperLayout(props) {
30705
30848
  closeRightPane();
30706
30849
  setCurrentStep(value);
30707
30850
  }
30708
- return /* @__PURE__ */ jsx254(
30851
+ return /* @__PURE__ */ jsx256(
30709
30852
  WorkflowPageLayout,
30710
30853
  {
30711
30854
  ...tid,
30712
30855
  ...headerProps,
30856
+ banner,
30713
30857
  aiMode,
30714
30858
  stepperTabs: { steps: stepTabs, currentStep, onChange: goToStep },
30715
30859
  isDirty,
@@ -30748,7 +30892,7 @@ function getInitialStep(steps, defaultStep) {
30748
30892
 
30749
30893
  // src/forms/BoundChipSelectField.tsx
30750
30894
  import { Observer as Observer19 } from "mobx-react";
30751
- import { jsx as jsx255 } from "react/jsx-runtime";
30895
+ import { jsx as jsx257 } from "react/jsx-runtime";
30752
30896
  function BoundChipSelectField(props) {
30753
30897
  const {
30754
30898
  field,
@@ -30764,7 +30908,7 @@ function BoundChipSelectField(props) {
30764
30908
  ...others
30765
30909
  } = props;
30766
30910
  const testId = useTestIds(props, field.key);
30767
- return /* @__PURE__ */ jsx255(Observer19, { children: () => /* @__PURE__ */ jsx255(
30911
+ return /* @__PURE__ */ jsx257(Observer19, { children: () => /* @__PURE__ */ jsx257(
30768
30912
  ChipSelectField,
30769
30913
  {
30770
30914
  label,
@@ -30794,12 +30938,12 @@ function BoundChipSelectField(props) {
30794
30938
  }
30795
30939
 
30796
30940
  // src/forms/BoundSelectAndTextField.tsx
30797
- import { jsx as jsx256, jsxs as jsxs137 } from "react/jsx-runtime";
30941
+ import { jsx as jsx258, jsxs as jsxs137 } from "react/jsx-runtime";
30798
30942
  function BoundSelectAndTextField(props) {
30799
30943
  const { selectFieldProps, textFieldProps, compact = true } = props;
30800
30944
  const tid = useTestIds(props);
30801
30945
  return /* @__PURE__ */ jsxs137(CompoundField, { children: [
30802
- /* @__PURE__ */ jsx256(
30946
+ /* @__PURE__ */ jsx258(
30803
30947
  BoundSelectField,
30804
30948
  {
30805
30949
  ...tid[defaultTestId(selectFieldProps.label ?? selectFieldProps.field.key)],
@@ -30808,7 +30952,7 @@ function BoundSelectAndTextField(props) {
30808
30952
  compact
30809
30953
  }
30810
30954
  ),
30811
- /* @__PURE__ */ jsx256(
30955
+ /* @__PURE__ */ jsx258(
30812
30956
  BoundTextField,
30813
30957
  {
30814
30958
  ...tid[defaultTestId(textFieldProps.label ?? textFieldProps.field.key)],
@@ -30820,8 +30964,8 @@ function BoundSelectAndTextField(props) {
30820
30964
  }
30821
30965
 
30822
30966
  // src/forms/FormHeading.tsx
30823
- import { trussProps as trussProps146 } from "@homebound/truss/runtime";
30824
- import { jsx as jsx257 } from "react/jsx-runtime";
30967
+ import { trussProps as trussProps147 } from "@homebound/truss/runtime";
30968
+ import { jsx as jsx259 } from "react/jsx-runtime";
30825
30969
  function FormHeading(props) {
30826
30970
  const {
30827
30971
  title,
@@ -30831,7 +30975,7 @@ function FormHeading(props) {
30831
30975
  } = props;
30832
30976
  return (
30833
30977
  // Add space before the heading, but only if it's not first.
30834
- /* @__PURE__ */ jsx257("h3", { ...trussProps146({
30978
+ /* @__PURE__ */ jsx259("h3", { ...trussProps147({
30835
30979
  ...{
30836
30980
  fontWeight: "fw4",
30837
30981
  fontSize: "fz_16px",
@@ -30847,9 +30991,9 @@ function FormHeading(props) {
30847
30991
  FormHeading.isFormHeading = true;
30848
30992
 
30849
30993
  // src/forms/StaticField.tsx
30850
- import { useId as useId4 } from "@react-aria/utils";
30851
- import { trussProps as trussProps147 } from "@homebound/truss/runtime";
30852
- import { jsx as jsx258, jsxs as jsxs138 } from "react/jsx-runtime";
30994
+ import { useId as useId5 } from "@react-aria/utils";
30995
+ import { trussProps as trussProps148 } from "@homebound/truss/runtime";
30996
+ import { jsx as jsx260, jsxs as jsxs138 } from "react/jsx-runtime";
30853
30997
  function StaticField(props) {
30854
30998
  const {
30855
30999
  fieldProps
@@ -30861,15 +31005,15 @@ function StaticField(props) {
30861
31005
  children
30862
31006
  } = props;
30863
31007
  const tid = useTestIds(props, typeof label === "string" ? defaultTestId(label) : "staticField");
30864
- const id = useId4();
30865
- return /* @__PURE__ */ jsxs138("div", { ...trussProps147({
31008
+ const id = useId5();
31009
+ return /* @__PURE__ */ jsxs138("div", { ...trussProps148({
30866
31010
  ...labelStyle === "left" ? {
30867
31011
  display: "df",
30868
31012
  justifyContent: "jcsb",
30869
31013
  maxWidth: "maxw100"
30870
31014
  } : {}
30871
31015
  }), ...tid.container, children: [
30872
- /* @__PURE__ */ jsx258("label", { ...trussProps147({
31016
+ /* @__PURE__ */ jsx260("label", { ...trussProps148({
30873
31017
  display: "db",
30874
31018
  fontWeight: "fw4",
30875
31019
  fontSize: "fz_14px",
@@ -30879,7 +31023,7 @@ function StaticField(props) {
30879
31023
  }],
30880
31024
  marginBottom: "mb_4px"
30881
31025
  }), htmlFor: id, ...tid.label, children: label }),
30882
- /* @__PURE__ */ jsx258("div", { id, ...trussProps147({
31026
+ /* @__PURE__ */ jsx260("div", { id, ...trussProps148({
30883
31027
  fontWeight: "fw4",
30884
31028
  fontSize: "fz_14px",
30885
31029
  lineHeight: "lh_20px",
@@ -30896,9 +31040,9 @@ function StaticField(props) {
30896
31040
  }
30897
31041
 
30898
31042
  // src/hooks/useFilter.ts
30899
- import { useState as useState65 } from "react";
31043
+ import { useState as useState66 } from "react";
30900
31044
  function useFilter4({ filterDefs }) {
30901
- const [filter, setFilter] = useState65(
31045
+ const [filter, setFilter] = useState66(
30902
31046
  Object.fromEntries(
30903
31047
  safeEntries(filterDefs).filter(([key, def]) => def(key).defaultValue !== void 0).map(([key, def]) => [key, def(key).defaultValue])
30904
31048
  )
@@ -30907,10 +31051,10 @@ function useFilter4({ filterDefs }) {
30907
31051
  }
30908
31052
 
30909
31053
  // src/inputs/Autocomplete.tsx
30910
- import { useCallback as useCallback47, useRef as useRef76 } from "react";
31054
+ import { useCallback as useCallback48, useRef as useRef77 } from "react";
30911
31055
  import { useComboBox as useComboBox3, useOverlayPosition as useOverlayPosition6 } from "react-aria";
30912
31056
  import { Item as Item5, useComboBoxState as useComboBoxState3 } from "react-stately";
30913
- import { Fragment as Fragment53, jsx as jsx259, jsxs as jsxs139 } from "react/jsx-runtime";
31057
+ import { Fragment as Fragment53, jsx as jsx261, jsxs as jsxs139 } from "react/jsx-runtime";
30914
31058
  function Autocomplete(props) {
30915
31059
  const {
30916
31060
  onSelect,
@@ -30927,8 +31071,8 @@ function Autocomplete(props) {
30927
31071
  } = props;
30928
31072
  const { effectiveValue, proposalProps } = useAiProposal(value, proposedValue);
30929
31073
  const disabledOptionsWithReasons = Object.fromEntries(disabledOptions?.map(disabledOptionToKeyedTuple) ?? []);
30930
- const comboBoxChildren = useCallback47(
30931
- (item) => /* @__PURE__ */ jsx259(Item5, { textValue: getOptionLabel(item), children: getOptionMenuLabel ? getOptionMenuLabel(item) : getOptionLabel(item) }, getOptionValue(item)),
31074
+ const comboBoxChildren = useCallback48(
31075
+ (item) => /* @__PURE__ */ jsx261(Item5, { textValue: getOptionLabel(item), children: getOptionMenuLabel ? getOptionMenuLabel(item) : getOptionLabel(item) }, getOptionValue(item)),
30932
31076
  [getOptionValue, getOptionLabel, getOptionMenuLabel]
30933
31077
  );
30934
31078
  const comboBoxProps = {
@@ -30952,10 +31096,10 @@ function Autocomplete(props) {
30952
31096
  ...others
30953
31097
  };
30954
31098
  const state = useComboBoxState3(comboBoxProps);
30955
- const inputWrapRef = useRef76(null);
30956
- const inputRef = useRef76(null);
30957
- const listBoxRef = useRef76(null);
30958
- const popoverRef = useRef76(null);
31099
+ const inputWrapRef = useRef77(null);
31100
+ const inputRef = useRef77(null);
31101
+ const listBoxRef = useRef77(null);
31102
+ const popoverRef = useRef77(null);
30959
31103
  const { inputProps, listBoxProps, labelProps } = useComboBox3(
30960
31104
  {
30961
31105
  ...comboBoxProps,
@@ -30982,7 +31126,7 @@ function Autocomplete(props) {
30982
31126
  minWidth: 200
30983
31127
  };
30984
31128
  return /* @__PURE__ */ jsxs139(Fragment53, { children: [
30985
- /* @__PURE__ */ jsx259(
31129
+ /* @__PURE__ */ jsx261(
30986
31130
  TextFieldBase,
30987
31131
  {
30988
31132
  inputRef,
@@ -30992,11 +31136,11 @@ function Autocomplete(props) {
30992
31136
  onChange: onInputChange,
30993
31137
  ...proposalProps,
30994
31138
  clearable: true,
30995
- startAdornment: "startAdornment" in props ? props.startAdornment : /* @__PURE__ */ jsx259(Icon, { icon: "search" }),
31139
+ startAdornment: "startAdornment" in props ? props.startAdornment : /* @__PURE__ */ jsx261(Icon, { icon: "search" }),
30996
31140
  ...others
30997
31141
  }
30998
31142
  ),
30999
- state.isOpen && /* @__PURE__ */ jsx259(
31143
+ state.isOpen && /* @__PURE__ */ jsx261(
31000
31144
  Popover,
31001
31145
  {
31002
31146
  triggerRef: inputRef,
@@ -31005,7 +31149,7 @@ function Autocomplete(props) {
31005
31149
  onClose: () => state.close(),
31006
31150
  isOpen: state.isOpen,
31007
31151
  minWidth: 200,
31008
- children: /* @__PURE__ */ jsx259(
31152
+ children: /* @__PURE__ */ jsx261(
31009
31153
  ListBox,
31010
31154
  {
31011
31155
  ...listBoxProps,
@@ -31023,11 +31167,11 @@ function Autocomplete(props) {
31023
31167
  }
31024
31168
 
31025
31169
  // src/inputs/ToggleButton.tsx
31026
- import { useRef as useRef77, useState as useState66 } from "react";
31170
+ import { useRef as useRef78, useState as useState67 } from "react";
31027
31171
  import { useFocusRing as useFocusRing22, useHover as useHover26, usePress as usePress2, useSwitch as useSwitch2, VisuallyHidden as VisuallyHidden10 } from "react-aria";
31028
31172
  import { useToggleState as useToggleState2 } from "react-stately";
31029
- import { trussProps as trussProps148 } from "@homebound/truss/runtime";
31030
- import { jsx as jsx260, jsxs as jsxs140 } from "react/jsx-runtime";
31173
+ import { trussProps as trussProps149 } from "@homebound/truss/runtime";
31174
+ import { jsx as jsx262, jsxs as jsxs140 } from "react/jsx-runtime";
31031
31175
  function ToggleButton(props) {
31032
31176
  const {
31033
31177
  selected: isSelected = false,
@@ -31038,7 +31182,7 @@ function ToggleButton(props) {
31038
31182
  __storyState,
31039
31183
  ...otherProps
31040
31184
  } = props;
31041
- const [asyncInProgress, setAsyncInProgress] = useState66(false);
31185
+ const [asyncInProgress, setAsyncInProgress] = useState67(false);
31042
31186
  const isDisabled = !!disabled || asyncInProgress;
31043
31187
  const ariaProps = {
31044
31188
  "aria-label": label,
@@ -31057,8 +31201,8 @@ function ToggleButton(props) {
31057
31201
  return result;
31058
31202
  }
31059
31203
  });
31060
- const labelRef = useRef77(null);
31061
- const ref = useRef77(null);
31204
+ const labelRef = useRef78(null);
31205
+ const ref = useRef78(null);
31062
31206
  const tid = useTestIds(otherProps, label);
31063
31207
  const {
31064
31208
  isPressed: isPressedFromEvents,
@@ -31091,7 +31235,7 @@ function ToggleButton(props) {
31091
31235
  ...focusProps,
31092
31236
  ...hoverProps,
31093
31237
  ...pressProps,
31094
- ...trussProps148({
31238
+ ...trussProps149({
31095
31239
  // Gray500 off-state has no semantic match — keep palette (OnSurfaceMuted is Gray700).
31096
31240
  ...{
31097
31241
  borderRadius: "br4",
@@ -31132,9 +31276,9 @@ function ToggleButton(props) {
31132
31276
  title: tooltip,
31133
31277
  placement: "top",
31134
31278
  children: /* @__PURE__ */ jsxs140("label", { ...labelAttrs, children: [
31135
- icon && /* @__PURE__ */ jsx260(Icon, { icon }),
31279
+ icon && /* @__PURE__ */ jsx262(Icon, { icon }),
31136
31280
  label,
31137
- /* @__PURE__ */ jsx260(VisuallyHidden10, { children: /* @__PURE__ */ jsx260("input", { ref, ...inputProps, ...tid.value }) })
31281
+ /* @__PURE__ */ jsx262(VisuallyHidden10, { children: /* @__PURE__ */ jsx262("input", { ref, ...inputProps, ...tid.value }) })
31138
31282
  ] })
31139
31283
  });
31140
31284
  }
@@ -31285,6 +31429,7 @@ export {
31285
31429
  NavbarLayout,
31286
31430
  NumberField,
31287
31431
  OpenModal,
31432
+ PageBanner,
31288
31433
  PageHeaderLayout,
31289
31434
  Pagination,
31290
31435
  Palette,
@@ -31355,19 +31500,20 @@ export {
31355
31500
  actionColumn,
31356
31501
  applyRowFn,
31357
31502
  assignDefaultColumnIds,
31358
- bannerAndNavbarChromeTop,
31359
31503
  beamEnvironmentBannerLayoutHeightVar,
31360
31504
  beamFloatingRightOffsetVar,
31361
31505
  beamLayoutContentPaddingXVar,
31362
31506
  beamLayoutViewportHeightVar,
31363
31507
  beamLayoutViewportWidthVar,
31364
31508
  beamNavbarLayoutHeightVar,
31509
+ beamPageBannerHeightVar,
31365
31510
  beamPageHeaderLayoutHeightVar,
31366
31511
  beamRightPaneContentMinVar,
31367
31512
  beamRightPaneWidthVar,
31368
31513
  beamSideNavLayoutWidthVar,
31369
31514
  beamTableActionsHeightVar,
31370
31515
  beamWorkflowLayoutFooterHeightVar,
31516
+ belowNavbarOffset,
31371
31517
  booleanFilter,
31372
31518
  boundCheckboxField,
31373
31519
  boundCheckboxGroupField,
@@ -31481,6 +31627,7 @@ export {
31481
31627
  nonKindGridColumnKeys,
31482
31628
  numberRangeFilter,
31483
31629
  numericColumn,
31630
+ pageBannerOffset,
31484
31631
  pageContentGutterPx,
31485
31632
  pageContentPaddingX,
31486
31633
  parseDate,
@@ -31544,6 +31691,7 @@ export {
31544
31691
  useHasSideNavLayoutProvider,
31545
31692
  useHover2 as useHover,
31546
31693
  useModal,
31694
+ usePageBanner,
31547
31695
  usePersistedFilter,
31548
31696
  useQueryState,
31549
31697
  useResponsiveGrid,