@homebound/beam 3.71.0 → 3.72.1

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.d.cts CHANGED
@@ -9963,7 +9963,7 @@ type WorkflowActionsProps = {
9963
9963
  primaryDisabled?: boolean;
9964
9964
  };
9965
9965
 
9966
- type StepperTabsStep = Pick<StepperTabProps, "label" | "value" | "completed" | "disabled"> & Partial<Pick<WorkflowActionsProps, "onContinue">>;
9966
+ type StepperTabsStep = Pick<StepperTabProps, "label" | "value" | "disabled"> & Partial<Pick<WorkflowActionsProps, "onContinue">>;
9967
9967
  type StepperTabsProps = {
9968
9968
  steps: StepperTabsStep[];
9969
9969
  currentStep: StepperTabsStep["value"];
@@ -10256,10 +10256,16 @@ type PageHeaderLayoutProps<V extends string, X> = {
10256
10256
  /** Page header + body shell with auto-hide chrome. Contract: `docs/layouts.md`. */
10257
10257
  declare function PageHeaderLayout<V extends string, X extends Only<TabsContentXss, X>>(props: PageHeaderLayoutProps<V, X>): JSX.Element;
10258
10258
 
10259
- /** A `WorkflowLayout` step: a `StepperTabsStep` (minus `value`, which is derived from `label`) plus the page content rendered while it's active — `completed` also gates the Continue/Complete CTA when this is the active step. */
10259
+ /**
10260
+ * A `WorkflowLayout` step: a `StepperTabsStep` (minus `value`, which is derived from `label`) plus
10261
+ * page content. Stepper chrome marks prior steps complete via current-step index; `isValid` only
10262
+ * gates the Continue/Complete CTA for the active step.
10263
+ */
10260
10264
  type WorkflowLayoutStep = Omit<StepperTabsStep, "value"> & {
10261
10265
  /** Rendered as the page body while this is the active step. */
10262
10266
  content: ReactNode;
10267
+ /** Gates Continue/Complete for the active step (form validity) */
10268
+ isValid: boolean;
10263
10269
  };
10264
10270
  type WorkflowLayoutProps = Pick<BaseHeaderProps, "title" | "documentTitleSuffix" | "breadcrumbs"> & Pick<WorkflowActionsProps, "onCancel" | "completeLabel" | "onComplete" | "onSaveAndExit"> & {
10265
10271
  /** The workflow's steps; the active step's `content` is the body, and it drives the header's tab strip. */
@@ -10274,8 +10280,9 @@ type WorkflowLayoutProps = Pick<BaseHeaderProps, "title" | "documentTitleSuffix"
10274
10280
  *
10275
10281
  * A standalone, full-page layout for step-based workflow pages — nest it directly under
10276
10282
  * `EnvironmentBannerLayout`, never under `NavbarLayout`/`SideNavLayout`/`PageHeaderLayout`. Unlike
10277
- * `PageHeaderLayout`, the header here never auto-hides; the stepper tabs collapse to a condensed
10278
- * indicator bar on mobile instead.
10283
+ * `PageHeaderLayout`, the header here never auto-hides. The stepper tabs always collapse to a condensed
10284
+ * indicator bar on mobile, and on larger viewports also collapse once scrolled past a threshold,
10285
+ * re-expanding on scroll-up (even before reaching the top).
10279
10286
  *
10280
10287
  * Owns the workflow's fixed CTA set (Back/Cancel/Save & Exit/Continue-or-Complete) via `WorkflowActions`
10281
10288
  * so it can move them into a mobile footer at the `sm` breakpoint — `WorkflowHeader` itself is not part
package/dist/index.d.ts CHANGED
@@ -9963,7 +9963,7 @@ type WorkflowActionsProps = {
9963
9963
  primaryDisabled?: boolean;
9964
9964
  };
9965
9965
 
9966
- type StepperTabsStep = Pick<StepperTabProps, "label" | "value" | "completed" | "disabled"> & Partial<Pick<WorkflowActionsProps, "onContinue">>;
9966
+ type StepperTabsStep = Pick<StepperTabProps, "label" | "value" | "disabled"> & Partial<Pick<WorkflowActionsProps, "onContinue">>;
9967
9967
  type StepperTabsProps = {
9968
9968
  steps: StepperTabsStep[];
9969
9969
  currentStep: StepperTabsStep["value"];
@@ -10256,10 +10256,16 @@ type PageHeaderLayoutProps<V extends string, X> = {
10256
10256
  /** Page header + body shell with auto-hide chrome. Contract: `docs/layouts.md`. */
10257
10257
  declare function PageHeaderLayout<V extends string, X extends Only<TabsContentXss, X>>(props: PageHeaderLayoutProps<V, X>): JSX.Element;
10258
10258
 
10259
- /** A `WorkflowLayout` step: a `StepperTabsStep` (minus `value`, which is derived from `label`) plus the page content rendered while it's active — `completed` also gates the Continue/Complete CTA when this is the active step. */
10259
+ /**
10260
+ * A `WorkflowLayout` step: a `StepperTabsStep` (minus `value`, which is derived from `label`) plus
10261
+ * page content. Stepper chrome marks prior steps complete via current-step index; `isValid` only
10262
+ * gates the Continue/Complete CTA for the active step.
10263
+ */
10260
10264
  type WorkflowLayoutStep = Omit<StepperTabsStep, "value"> & {
10261
10265
  /** Rendered as the page body while this is the active step. */
10262
10266
  content: ReactNode;
10267
+ /** Gates Continue/Complete for the active step (form validity) */
10268
+ isValid: boolean;
10263
10269
  };
10264
10270
  type WorkflowLayoutProps = Pick<BaseHeaderProps, "title" | "documentTitleSuffix" | "breadcrumbs"> & Pick<WorkflowActionsProps, "onCancel" | "completeLabel" | "onComplete" | "onSaveAndExit"> & {
10265
10271
  /** The workflow's steps; the active step's `content` is the body, and it drives the header's tab strip. */
@@ -10274,8 +10280,9 @@ type WorkflowLayoutProps = Pick<BaseHeaderProps, "title" | "documentTitleSuffix"
10274
10280
  *
10275
10281
  * A standalone, full-page layout for step-based workflow pages — nest it directly under
10276
10282
  * `EnvironmentBannerLayout`, never under `NavbarLayout`/`SideNavLayout`/`PageHeaderLayout`. Unlike
10277
- * `PageHeaderLayout`, the header here never auto-hides; the stepper tabs collapse to a condensed
10278
- * indicator bar on mobile instead.
10283
+ * `PageHeaderLayout`, the header here never auto-hides. The stepper tabs always collapse to a condensed
10284
+ * indicator bar on mobile, and on larger viewports also collapse once scrolled past a threshold,
10285
+ * re-expanding on scroll-up (even before reaching the top).
10279
10286
  *
10280
10287
  * Owns the workflow's fixed CTA set (Back/Cancel/Save & Exit/Continue-or-Complete) via `WorkflowActions`
10281
10288
  * so it can move them into a mobile footer at the `sm` breakpoint — `WorkflowHeader` itself is not part
package/dist/index.js CHANGED
@@ -25159,8 +25159,8 @@ function StepIcon({
25159
25159
  // src/components/StepperTabs/StepperTab.tsx
25160
25160
  import { useRef as useRef62 } from "react";
25161
25161
  import { mergeProps as mergeProps30, useButton as useButton13, useFocusRing as useFocusRing18, useHover as useHover22, VisuallyHidden as VisuallyHidden10 } from "react-aria";
25162
- import { trussProps as trussProps113, maybeCssVar as maybeCssVar53 } from "@homebound/truss/runtime";
25163
- import { jsx as jsx200, jsxs as jsxs100 } from "react/jsx-runtime";
25162
+ import { trussProps as trussProps113 } from "@homebound/truss/runtime";
25163
+ import { Fragment as Fragment45, jsx as jsx200, jsxs as jsxs100 } from "react/jsx-runtime";
25164
25164
  function StepperTab(props) {
25165
25165
  const {
25166
25166
  label,
@@ -25195,65 +25195,86 @@ function StepperTab(props) {
25195
25195
  ...stepperTabStyles.baseStyles,
25196
25196
  ...getStateStyles(active, completed),
25197
25197
  ...isHovered && !disabled ? stepperTabStyles.hoverStyles : {},
25198
- ...collapsed ? getCollapsedStyles(active, completed) : {},
25198
+ ...collapsed ? stepperTabStyles.collapsedStyles : {},
25199
25199
  ...disabled ? stepperTabStyles.disabledStyles : {},
25200
25200
  ...isFocusVisible ? stepperTabStyles.focusRingStyles : {}
25201
25201
  }), ...tid[defaultTestId(value)], children: [
25202
- /* @__PURE__ */ jsx200("span", { className: "oh d_negwebkit_box wbo_vertical to_ellipsis wlc_1", children: label }),
25203
- completed && /* @__PURE__ */ jsx200("span", { className: "fs0 ml1", children: /* @__PURE__ */ jsx200(Icon, { icon: "check", inc: 2.5, ...tid.check }) }),
25202
+ !collapsed && /* @__PURE__ */ jsxs100(Fragment45, { children: [
25203
+ /* @__PURE__ */ jsxs100("span", { className: "dg jic mw0", children: [
25204
+ /* @__PURE__ */ jsx200("span", { className: "fw6 fz_14px lh_20px visibility_hidden gridArea_1_1 oh d_negwebkit_box wbo_vertical to_ellipsis wlc_1 wordBreak_break_all", "aria-hidden": true, children: label }),
25205
+ /* @__PURE__ */ jsx200("span", { ...trussProps113({
25206
+ gridArea: "gridArea_1_1",
25207
+ overflow: "oh",
25208
+ display: "d_negwebkit_box",
25209
+ WebkitBoxOrient: "wbo_vertical",
25210
+ textOverflow: "to_ellipsis",
25211
+ WebkitLineClamp: "wlc_1",
25212
+ wordBreak: "wordBreak_break_all",
25213
+ ...active ? {
25214
+ fontWeight: "fw6",
25215
+ fontSize: "fz_14px",
25216
+ lineHeight: "lh_20px"
25217
+ } : {}
25218
+ }), children: label })
25219
+ ] }),
25220
+ /* @__PURE__ */ jsx200("span", { ...trussProps113({
25221
+ flexShrink: "fs0",
25222
+ marginLeft: "ml1",
25223
+ transition: "transitionAll",
25224
+ opacity: "o0",
25225
+ transform: "transform_scale_0_75_translateY_100",
25226
+ ...completed ? {
25227
+ opacity: "o100",
25228
+ transform: "transform_scale_1_translateY_0"
25229
+ } : {}
25230
+ }), children: /* @__PURE__ */ jsx200(Icon, { icon: "check", inc: 2.5, ...tid.check }) })
25231
+ ] }),
25232
+ /* @__PURE__ */ jsx200("span", { "aria-hidden": true, ...trussProps113(getIndicatorStyles(active, completed, disabled)), ...tid.indicator }),
25204
25233
  /* @__PURE__ */ jsx200(VisuallyHidden10, { children: completed ? "Complete" : "Not Complete" })
25205
25234
  ] });
25206
25235
  }
25207
- function withBorderBottom(color) {
25236
+ function getStateStyles(active, completed) {
25208
25237
  return {
25209
- ...{
25210
- borderBottomStyle: "bbs_solid",
25211
- borderBottomWidth: ["borderBottomWidth_var", {
25212
- "--borderBottomWidth": maybeCssVar53(`3px`)
25238
+ color: ["color_var", {
25239
+ "--color": "var(--b-on-surface-muted)"
25240
+ }],
25241
+ ...active || completed ? {
25242
+ color: ["color_var", {
25243
+ "--color": "var(--b-choice-selected)"
25213
25244
  }]
25214
- },
25215
- ...color
25245
+ } : {}
25216
25246
  };
25217
25247
  }
25218
- function getStateStyles(active, completed) {
25248
+ function getIndicatorStyles(active, completed, disabled) {
25219
25249
  return {
25220
25250
  ...{
25221
- color: "gray400",
25222
- ...active || completed ? {
25223
- color: "blue700"
25224
- } : {},
25225
- ...active ? {
25226
- fontWeight: "fw6",
25227
- fontSize: "fz_14px",
25228
- lineHeight: "lh_20px"
25251
+ position: "absolute",
25252
+ left: "left0",
25253
+ right: "right0",
25254
+ bottom: "bottom0",
25255
+ height: ["h_var", {
25256
+ "--height": `${active ? activeIndicatorHeightPx : inactiveIndicatorHeightPx}px`
25257
+ }],
25258
+ backgroundColor: ["bgColor_var", {
25259
+ "--backgroundColor": "var(--b-field-border-default)"
25260
+ }],
25261
+ ...(active || completed) && !disabled ? {
25262
+ backgroundColor: ["bgColor_var", {
25263
+ "--backgroundColor": "var(--b-primary)"
25264
+ }]
25229
25265
  } : {}
25230
- },
25231
- ...withBorderBottom(active || completed ? {
25232
- borderColor: "bcBlue600"
25233
- } : {
25234
- borderColor: "bcGray300"
25235
- })
25236
- };
25237
- }
25238
- function getCollapsedStyles(active, completed) {
25239
- return {
25240
- ...{
25241
- cursor: "cursor_default",
25242
- height: "h_0px",
25243
- paddingTop: "pt0",
25244
- paddingBottom: "pb0"
25245
- },
25246
- ...active || completed ? {
25247
- borderColor: "bcBlue600"
25248
- } : {
25249
- borderColor: "bcGray300"
25250
25266
  }
25251
25267
  };
25252
25268
  }
25269
+ var activeIndicatorHeightPx = 3;
25270
+ var inactiveIndicatorHeightPx = 2;
25253
25271
  var stepperTabStyles = {
25272
+ // No overflow:hidden — collapsed indicators are absolute and must paint outside the 0-height box.
25254
25273
  baseStyles: {
25274
+ position: "relative",
25255
25275
  display: "df",
25256
25276
  alignItems: "aic",
25277
+ justifyContent: "jcfs",
25257
25278
  flexGrow: "fg1",
25258
25279
  paddingTop: "pt1",
25259
25280
  paddingBottom: "pb1",
@@ -25262,10 +25283,11 @@ var stepperTabStyles = {
25262
25283
  fontWeight: "fw4",
25263
25284
  fontSize: "fz_14px",
25264
25285
  lineHeight: "lh_20px",
25265
- overflow: "oh",
25286
+ color: ["color_var", {
25287
+ "--color": "var(--b-on-surface-muted)"
25288
+ }],
25266
25289
  textAlign: "tal",
25267
- height: "h_48px",
25268
- transition: "transitionAll"
25290
+ height: "h_40px"
25269
25291
  },
25270
25292
  hoverStyles: {
25271
25293
  backgroundColor: "bgGray100"
@@ -25274,11 +25296,17 @@ var stepperTabStyles = {
25274
25296
  boxShadow: "bshFocus",
25275
25297
  outline: "outline0"
25276
25298
  },
25277
- // Disabled always wins over both the state's and the collapsed border color.
25299
+ collapsedStyles: {
25300
+ cursor: "cursor_default",
25301
+ height: "h_0px",
25302
+ paddingTop: "pt0",
25303
+ paddingBottom: "pb0"
25304
+ },
25278
25305
  disabledStyles: {
25279
- color: "gray400",
25280
- cursor: "cursorNotAllowed",
25281
- borderColor: "bcGray300"
25306
+ color: ["color_var", {
25307
+ "--color": "var(--b-text-disabled)"
25308
+ }],
25309
+ cursor: "cursorNotAllowed"
25282
25310
  }
25283
25311
  };
25284
25312
 
@@ -25299,6 +25327,7 @@ function StepperTabs(props) {
25299
25327
  } = useBreakpoint();
25300
25328
  const collapsed = isMobile || !!forceCollapsed;
25301
25329
  const capWidth = steps.length <= 3;
25330
+ const currentStepIndex = Math.max(0, steps.findIndex((step) => step.value === currentStep));
25302
25331
  return /* @__PURE__ */ jsx201("nav", { "aria-label": "steps", className: "w100", ...tid, children: /* @__PURE__ */ jsx201("ol", { ...trussProps114({
25303
25332
  padding: "p_0",
25304
25333
  margin: "m_0",
@@ -25311,8 +25340,9 @@ function StepperTabs(props) {
25311
25340
  borderBottomStyle: "bbs_solid",
25312
25341
  borderBottomWidth: "bbw_1px",
25313
25342
  borderColor: "bcGray400"
25314
- }), children: steps.map((step) => {
25315
- const isCurrent = step.value === currentStep;
25343
+ }), children: steps.map((step, idx) => {
25344
+ const isCurrent = idx === currentStepIndex;
25345
+ const isCompleted = idx < currentStepIndex;
25316
25346
  return /* @__PURE__ */ createElement7("li", { ...trussProps114({
25317
25347
  display: "df",
25318
25348
  flexGrow: "fg1",
@@ -25325,7 +25355,7 @@ function StepperTabs(props) {
25325
25355
  "--maxWidth": `${maxStepWidthPx}px`
25326
25356
  }]
25327
25357
  } : {}
25328
- }), key: step.value, "aria-current": isCurrent, ...tid.step }, /* @__PURE__ */ jsx201(StepperTab, { label: step.label, value: step.value, active: isCurrent, completed: step.completed, disabled: step.disabled, collapsed, onClick: onChange, ...tid.tab }));
25358
+ }), key: step.value, "aria-current": isCurrent, ...tid.step }, /* @__PURE__ */ jsx201(StepperTab, { label: step.label, value: step.value, active: isCurrent, completed: isCompleted, disabled: step.disabled, collapsed, onClick: onChange, ...tid.tab }));
25329
25359
  }) }) });
25330
25360
  }
25331
25361
  var maxStepWidthPx = 280;
@@ -25512,7 +25542,7 @@ function canClose(canCloseCheck) {
25512
25542
 
25513
25543
  // src/components/SuperDrawer/SuperDrawerContent.tsx
25514
25544
  import { trussProps as trussProps116, mergeProps as mergeProps31 } from "@homebound/truss/runtime";
25515
- import { Fragment as Fragment45, jsx as jsx204, jsxs as jsxs102 } from "react/jsx-runtime";
25545
+ import { Fragment as Fragment46, jsx as jsx204, jsxs as jsxs102 } from "react/jsx-runtime";
25516
25546
  var SuperDrawerContent = ({
25517
25547
  children,
25518
25548
  actions
@@ -25571,7 +25601,7 @@ var SuperDrawerContent = ({
25571
25601
  }) }, "content");
25572
25602
  }
25573
25603
  }
25574
- return /* @__PURE__ */ jsxs102(Fragment45, { children: [
25604
+ return /* @__PURE__ */ jsxs102(Fragment46, { children: [
25575
25605
  wrapWithMotionAndMaybeBack(children),
25576
25606
  actions && /* @__PURE__ */ jsx204("footer", { ...trussProps116({
25577
25607
  borderTopStyle: "bts_solid",
@@ -25634,13 +25664,13 @@ import { useEffect as useEffect37, useMemo as useMemo55, useRef as useRef63, use
25634
25664
  import { mergeProps as mergeProps32, useFocusRing as useFocusRing19, useHover as useHover23 } from "react-aria";
25635
25665
  import { matchPath } from "react-router";
25636
25666
  import { Link as Link7, useLocation as useLocation2 } from "react-router-dom";
25637
- import { trussProps as trussProps117, maybeCssVar as maybeCssVar54 } from "@homebound/truss/runtime";
25638
- import { Fragment as Fragment46, jsx as jsx205, jsxs as jsxs103 } from "react/jsx-runtime";
25667
+ import { trussProps as trussProps117, maybeCssVar as maybeCssVar53 } from "@homebound/truss/runtime";
25668
+ import { Fragment as Fragment47, jsx as jsx205, jsxs as jsxs103 } from "react/jsx-runtime";
25639
25669
  function TabsWithContent(props) {
25640
25670
  const styles = hideTabs(props) ? {} : {
25641
25671
  paddingTop: "pt3"
25642
25672
  };
25643
- return /* @__PURE__ */ jsxs103(Fragment46, { children: [
25673
+ return /* @__PURE__ */ jsxs103(Fragment47, { children: [
25644
25674
  /* @__PURE__ */ jsx205(Tabs, { ...props }),
25645
25675
  /* @__PURE__ */ jsx205(TabContent, { ...props, contentXss: {
25646
25676
  ...styles,
@@ -25791,7 +25821,7 @@ function TabImpl(props) {
25791
25821
  onClick: () => onClick(tab.value)
25792
25822
  }
25793
25823
  });
25794
- const tabLabel = /* @__PURE__ */ jsxs103(Fragment46, { children: [
25824
+ const tabLabel = /* @__PURE__ */ jsxs103(Fragment47, { children: [
25795
25825
  label,
25796
25826
  (icon || endAdornment) && /* @__PURE__ */ jsx205("span", { className: "ml1", children: icon ? /* @__PURE__ */ jsx205(Icon, { icon }) : endAdornment })
25797
25827
  ] });
@@ -25812,7 +25842,7 @@ function getTabStyles() {
25812
25842
  const borderBottomStyles = {
25813
25843
  borderBottomStyle: "bbs_solid",
25814
25844
  borderBottomWidth: ["borderBottomWidth_var", {
25815
- "--borderBottomWidth": maybeCssVar54(`${borderBottomWidthPx}px`)
25845
+ "--borderBottomWidth": maybeCssVar53(`${borderBottomWidthPx}px`)
25816
25846
  }],
25817
25847
  paddingBottom: ["pb_var", {
25818
25848
  "--paddingBottom": `${verticalPaddingPx - borderBottomWidthPx}px`
@@ -25932,7 +25962,7 @@ function useToast() {
25932
25962
  }
25933
25963
 
25934
25964
  // src/layouts/SideNavLayout/SideNavLayout.tsx
25935
- import { trussProps as trussProps118, mergeProps as mergeProps33, maybeCssVar as maybeCssVar55 } from "@homebound/truss/runtime";
25965
+ import { trussProps as trussProps118, mergeProps as mergeProps33, maybeCssVar as maybeCssVar54 } from "@homebound/truss/runtime";
25936
25966
  import { jsx as jsx207, jsxs as jsxs105 } from "react/jsx-runtime";
25937
25967
  var __maybeInc23 = (inc) => {
25938
25968
  return typeof inc === "string" ? inc : `calc(var(--t-spacing) * ${inc})`;
@@ -25986,14 +26016,14 @@ function SideNavLayoutContent(props) {
25986
26016
  position: "sticky",
25987
26017
  left: "left0",
25988
26018
  zIndex: ["z_var", {
25989
- "--zIndex": maybeCssVar55(zIndices.sideNav)
26019
+ "--zIndex": maybeCssVar54(zIndices.sideNav)
25990
26020
  }],
25991
26021
  top: ["top_var", {
25992
- "--top": maybeCssVar55(__maybeInc23(navTop))
26022
+ "--top": maybeCssVar54(__maybeInc23(navTop))
25993
26023
  }],
25994
26024
  alignSelf: "asfs",
25995
26025
  height: ["h_var", {
25996
- "--height": maybeCssVar55(__maybeInc23(railViewportHeight))
26026
+ "--height": maybeCssVar54(__maybeInc23(railViewportHeight))
25997
26027
  }],
25998
26028
  width: ["w_var", {
25999
26029
  "--width": `${collapsed ? railCollapsedWidthPx : railWidthPx}px`
@@ -26003,11 +26033,11 @@ function SideNavLayoutContent(props) {
26003
26033
  position: "fixed",
26004
26034
  left: "left0",
26005
26035
  top: ["top_var", {
26006
- "--top": maybeCssVar55(__maybeInc23(navTop))
26036
+ "--top": maybeCssVar54(__maybeInc23(navTop))
26007
26037
  }],
26008
26038
  bottom: "bottom0",
26009
26039
  zIndex: ["z_var", {
26010
- "--zIndex": maybeCssVar55(zIndices.sideNav)
26040
+ "--zIndex": maybeCssVar54(zIndices.sideNav)
26011
26041
  }]
26012
26042
  },
26013
26043
  ...collapsed ? {
@@ -26046,7 +26076,7 @@ function SideNavLayoutContent(props) {
26046
26076
  }
26047
26077
 
26048
26078
  // src/layouts/EnvironmentBannerLayout/EnvironmentBannerLayout.tsx
26049
- import { trussProps as trussProps119, mergeProps as mergeProps34, maybeCssVar as maybeCssVar56 } from "@homebound/truss/runtime";
26079
+ import { trussProps as trussProps119, mergeProps as mergeProps34, maybeCssVar as maybeCssVar55 } from "@homebound/truss/runtime";
26050
26080
  import { jsx as jsx208, jsxs as jsxs106 } from "react/jsx-runtime";
26051
26081
  var __maybeInc24 = (inc) => {
26052
26082
  return typeof inc === "string" ? inc : `calc(var(--t-spacing) * ${inc})`;
@@ -26079,10 +26109,10 @@ function EnvironmentBannerLayout(props) {
26079
26109
  top: "top0",
26080
26110
  left: "left0",
26081
26111
  zIndex: ["z_var", {
26082
- "--zIndex": maybeCssVar56(zIndices.environmentBanner)
26112
+ "--zIndex": maybeCssVar55(zIndices.environmentBanner)
26083
26113
  }],
26084
26114
  width: ["w_var", {
26085
- "--width": maybeCssVar56(__maybeInc24(innerWidth))
26115
+ "--width": maybeCssVar55(__maybeInc24(innerWidth))
26086
26116
  }]
26087
26117
  }), ...tid.bannerSticky, children: /* @__PURE__ */ jsx208(EnvironmentBanner, { ...environmentBanner, ...tid.environmentBanner }) }) }),
26088
26118
  children
@@ -26125,7 +26155,7 @@ function FormSectionLayout(props) {
26125
26155
 
26126
26156
  // src/layouts/NavbarLayout/NavbarLayout.tsx
26127
26157
  import { useMemo as useMemo56, useRef as useRef65 } from "react";
26128
- import { mergeProps as mergeProps35, maybeCssVar as maybeCssVar57 } from "@homebound/truss/runtime";
26158
+ import { mergeProps as mergeProps35, maybeCssVar as maybeCssVar56 } from "@homebound/truss/runtime";
26129
26159
 
26130
26160
  // src/layouts/useAutoHideOnScroll.ts
26131
26161
  import { useLayoutEffect as useLayoutEffect8, useRef as useRef64, useState as useState57 } from "react";
@@ -26275,10 +26305,10 @@ function NavbarLayout(props) {
26275
26305
  position: "sticky",
26276
26306
  left: "left0",
26277
26307
  zIndex: ["z_var", {
26278
- "--zIndex": maybeCssVar57(zIndices.navbar)
26308
+ "--zIndex": maybeCssVar56(zIndices.navbar)
26279
26309
  }],
26280
26310
  width: ["w_var", {
26281
- "--width": maybeCssVar57(__maybeInc25(innerWidth))
26311
+ "--width": maybeCssVar56(__maybeInc25(innerWidth))
26282
26312
  }]
26283
26313
  }
26284
26314
  ) : (
@@ -26287,10 +26317,10 @@ function NavbarLayout(props) {
26287
26317
  position: "fixed",
26288
26318
  left: "left0",
26289
26319
  zIndex: ["z_var", {
26290
- "--zIndex": maybeCssVar57(zIndices.navbar)
26320
+ "--zIndex": maybeCssVar56(zIndices.navbar)
26291
26321
  }],
26292
26322
  width: ["w_var", {
26293
- "--width": maybeCssVar57(__maybeInc25(innerWidth))
26323
+ "--width": maybeCssVar56(__maybeInc25(innerWidth))
26294
26324
  }],
26295
26325
  transition: "transitionTop"
26296
26326
  }
@@ -26396,7 +26426,7 @@ function useBannerAndNavbarHeight() {
26396
26426
  }
26397
26427
 
26398
26428
  // src/layouts/PageHeaderLayout/PageHeaderLayout.tsx
26399
- import { mergeProps as mergeProps36, maybeCssVar as maybeCssVar58 } from "@homebound/truss/runtime";
26429
+ import { mergeProps as mergeProps36, maybeCssVar as maybeCssVar57 } from "@homebound/truss/runtime";
26400
26430
  import { jsx as jsx214, jsxs as jsxs110 } from "react/jsx-runtime";
26401
26431
  var __maybeInc26 = (inc) => {
26402
26432
  return typeof inc === "string" ? inc : `calc(var(--t-spacing) * ${inc})`;
@@ -26428,24 +26458,24 @@ function PageHeaderLayout(props) {
26428
26458
  const innerCss = autoHideState === "static" ? {
26429
26459
  position: "sticky",
26430
26460
  left: ["left_var", {
26431
- "--left": maybeCssVar58(__maybeInc26(headerLeft))
26461
+ "--left": maybeCssVar57(__maybeInc26(headerLeft))
26432
26462
  }],
26433
26463
  width: ["w_var", {
26434
- "--width": maybeCssVar58(__maybeInc26(headerWidth))
26464
+ "--width": maybeCssVar57(__maybeInc26(headerWidth))
26435
26465
  }],
26436
26466
  zIndex: ["z_var", {
26437
- "--zIndex": maybeCssVar58(zIndices.pageStickyHeader)
26467
+ "--zIndex": maybeCssVar57(zIndices.pageStickyHeader)
26438
26468
  }]
26439
26469
  } : {
26440
26470
  position: "fixed",
26441
26471
  left: ["left_var", {
26442
- "--left": maybeCssVar58(__maybeInc26(headerLeft))
26472
+ "--left": maybeCssVar57(__maybeInc26(headerLeft))
26443
26473
  }],
26444
26474
  width: ["w_var", {
26445
- "--width": maybeCssVar58(__maybeInc26(headerWidth))
26475
+ "--width": maybeCssVar57(__maybeInc26(headerWidth))
26446
26476
  }],
26447
26477
  zIndex: ["z_var", {
26448
- "--zIndex": maybeCssVar58(zIndices.pageStickyHeader)
26478
+ "--zIndex": maybeCssVar57(zIndices.pageStickyHeader)
26449
26479
  }],
26450
26480
  transition: "transitionTop"
26451
26481
  };
@@ -26469,7 +26499,7 @@ function PageHeaderLayout(props) {
26469
26499
  }
26470
26500
 
26471
26501
  // src/layouts/WorkflowLayout/WorkflowLayout.tsx
26472
- import { useLayoutEffect as useLayoutEffect10, useRef as useRef68, useState as useState59 } from "react";
26502
+ import { useLayoutEffect as useLayoutEffect11, useRef as useRef69, useState as useState60 } from "react";
26473
26503
 
26474
26504
  // src/components/Headers/WorkflowHeader.tsx
26475
26505
  import { jsx as jsx215 } from "react/jsx-runtime";
@@ -26479,14 +26509,65 @@ function WorkflowHeader(props) {
26479
26509
  return /* @__PURE__ */ jsx215(BaseHeader, { ...otherProps, bottomSlot: /* @__PURE__ */ jsx215(StepperTabs, { ...stepperTabs, ...tid.stepperTabs }) });
26480
26510
  }
26481
26511
 
26512
+ // src/layouts/useScrollCollapse.ts
26513
+ import { useLayoutEffect as useLayoutEffect10, useRef as useRef67, useState as useState59 } from "react";
26514
+ function useScrollCollapse(enabled, restingOffset) {
26515
+ const [collapsed, setCollapsed] = useState59(() => typeof window !== "undefined" && window.scrollY > 0);
26516
+ const collapsedRef = useRef67(collapsed);
26517
+ collapsedRef.current = collapsed;
26518
+ const restingOffsetRef = useRef67(restingOffset);
26519
+ restingOffsetRef.current = restingOffset;
26520
+ const lastScrollYRef = useRef67(Number.POSITIVE_INFINITY);
26521
+ const lastScrollHeightRef = useRef67(0);
26522
+ useLayoutEffect10(() => {
26523
+ lastScrollHeightRef.current = document.documentElement.scrollHeight;
26524
+ }, [restingOffset]);
26525
+ useLayoutEffect10(() => {
26526
+ if (!enabled) return;
26527
+ const commit = (next) => {
26528
+ if (next !== collapsedRef.current) {
26529
+ collapsedRef.current = next;
26530
+ setCollapsed(next);
26531
+ }
26532
+ };
26533
+ const updateCollapsed = () => {
26534
+ const doc = document.documentElement;
26535
+ const currentY = window.scrollY;
26536
+ if (currentY <= 0) {
26537
+ lastScrollYRef.current = 0;
26538
+ lastScrollHeightRef.current = doc.scrollHeight;
26539
+ commit(false);
26540
+ return;
26541
+ }
26542
+ const currentScrollHeight = doc.scrollHeight;
26543
+ const scrollHeightChanged = lastScrollHeightRef.current !== 0 && currentScrollHeight !== lastScrollHeightRef.current;
26544
+ const dy = currentY - lastScrollYRef.current;
26545
+ lastScrollYRef.current = currentY;
26546
+ lastScrollHeightRef.current = currentScrollHeight;
26547
+ if (currentY <= restingOffsetRef.current) return;
26548
+ if (scrollHeightChanged) {
26549
+ commit(true);
26550
+ return;
26551
+ }
26552
+ const atBottom = currentY >= doc.scrollHeight - doc.clientHeight;
26553
+ if (dy > 0) commit(true);
26554
+ else if (dy < 0 && !atBottom) commit(false);
26555
+ };
26556
+ updateCollapsed();
26557
+ window.addEventListener("scroll", updateCollapsed, { passive: true });
26558
+ return () => window.removeEventListener("scroll", updateCollapsed);
26559
+ }, [enabled]);
26560
+ return collapsed;
26561
+ }
26562
+
26482
26563
  // src/layouts/WorkflowLayout/useUnsavedChangesGuard.tsx
26483
- import { useEffect as useEffect38, useRef as useRef67 } from "react";
26564
+ import { useEffect as useEffect38, useRef as useRef68 } from "react";
26484
26565
  import { useBlocker } from "react-router-dom";
26485
26566
  import { jsx as jsx216 } from "react/jsx-runtime";
26486
26567
  function useUnsavedChangesGuard(options) {
26487
26568
  const { isDirty, onCancel } = options;
26488
26569
  const { openModal } = useModal();
26489
- const isDirtyRef = useRef67(isDirty);
26570
+ const isDirtyRef = useRef68(isDirty);
26490
26571
  isDirtyRef.current = isDirty;
26491
26572
  useEffect38(() => {
26492
26573
  const onBeforeUnload = (e) => {
@@ -26550,7 +26631,7 @@ function WorkflowActions(props) {
26550
26631
  }
26551
26632
 
26552
26633
  // src/layouts/WorkflowLayout/WorkflowLayout.tsx
26553
- import { trussProps as trussProps123, mergeProps as mergeProps37, maybeCssVar as maybeCssVar59 } from "@homebound/truss/runtime";
26634
+ import { trussProps as trussProps123, mergeProps as mergeProps37, maybeCssVar as maybeCssVar58 } from "@homebound/truss/runtime";
26554
26635
  import { jsx as jsx218, jsxs as jsxs112 } from "react/jsx-runtime";
26555
26636
  var __maybeInc27 = (inc) => {
26556
26637
  return typeof inc === "string" ? inc : `calc(var(--t-spacing) * ${inc})`;
@@ -26566,11 +26647,11 @@ function WorkflowLayout(props) {
26566
26647
  isDirty,
26567
26648
  ...headerProps
26568
26649
  } = props;
26569
- const tabSteps = steps.map((step) => ({
26650
+ const stepTabs = steps.map((step) => ({
26570
26651
  ...step,
26571
26652
  value: defaultTestId(step.label)
26572
26653
  }));
26573
- const [currentStep, setCurrentStep] = useState59(() => getInitialStep(tabSteps, defaultStep));
26654
+ const [currentStep, setCurrentStep] = useState60(() => getInitialStep(stepTabs, defaultStep));
26574
26655
  const tid = useTestIds(props, "workflowLayout");
26575
26656
  const {
26576
26657
  sm: isMobile
@@ -26582,28 +26663,30 @@ function WorkflowLayout(props) {
26582
26663
  isDirty,
26583
26664
  onCancel
26584
26665
  });
26585
- const headerMetricsRef = useRef68(null);
26666
+ const bannerAndNavbarHeight = useBannerAndNavbarHeight();
26667
+ const headerMetricsRef = useRef69(null);
26586
26668
  const headerHeight = useMeasuredHeight(headerMetricsRef, true);
26587
- const collapsed = isMobile;
26669
+ const scrollCollapsed = useScrollCollapse(!isMobile, bannerAndNavbarHeight + headerHeight);
26670
+ const collapsed = isMobile || scrollCollapsed;
26588
26671
  const headerWidth = documentScrollChromeWidth();
26589
26672
  const outerTop = bannerAndNavbarChromeTop();
26590
26673
  const cssVars = headerHeight > 0 ? {
26591
26674
  [beamPageHeaderLayoutHeightVar]: `${headerHeight}px`
26592
26675
  } : void 0;
26593
- const currentIndex = isValidStep(tabSteps, currentStep) ? tabSteps.findIndex((step) => step.value === currentStep) : 0;
26676
+ const currentIndex = isValidStep(stepTabs, currentStep) ? stepTabs.findIndex((step) => step.value === currentStep) : 0;
26594
26677
  const isFirstStep = currentIndex <= 0;
26595
- const isLastStep = currentIndex === tabSteps.length - 1;
26596
- const activeStep = tabSteps[currentIndex];
26597
- const buttons = /* @__PURE__ */ jsx218(WorkflowActions, { isFirstStep, isLastStep, isMobile, onBack: () => setCurrentStep(tabSteps[currentIndex - 1].value), onCancel: onCancelClick, onSaveAndExit, completeLabel, onComplete, primaryDisabled: !activeStep?.completed, onContinue: async () => {
26678
+ const isLastStep = currentIndex === stepTabs.length - 1;
26679
+ const activeStep = stepTabs[currentIndex];
26680
+ const buttons = /* @__PURE__ */ jsx218(WorkflowActions, { isFirstStep, isLastStep, isMobile, onBack: () => setCurrentStep(stepTabs[currentIndex - 1].value), onCancel: onCancelClick, onSaveAndExit, completeLabel, onComplete, primaryDisabled: !activeStep?.isValid, onContinue: async () => {
26598
26681
  const onContinue = activeStep?.onContinue;
26599
26682
  if (onContinue) {
26600
26683
  const allowed = await onContinue();
26601
26684
  if (allowed === false) return;
26602
26685
  }
26603
- setCurrentStep(tabSteps[currentIndex + 1].value);
26686
+ setCurrentStep(stepTabs[currentIndex + 1].value);
26604
26687
  } });
26605
26688
  const showFooter = isMobile;
26606
- useLayoutEffect10(() => {
26689
+ useLayoutEffect11(() => {
26607
26690
  const root = document.documentElement;
26608
26691
  const previous = root.style.getPropertyValue(beamWorkflowLayoutFooterHeightVar);
26609
26692
  root.style.setProperty(beamWorkflowLayoutFooterHeightVar, showFooter ? `${mobileFooterHeightPx}px` : "0px");
@@ -26616,7 +26699,7 @@ function WorkflowLayout(props) {
26616
26699
  };
26617
26700
  }, [showFooter]);
26618
26701
  const headerEl = /* @__PURE__ */ jsx218(WorkflowHeader, { ...headerProps, rightSlot: isMobile ? void 0 : buttons, stepperTabs: {
26619
- steps: tabSteps,
26702
+ steps: stepTabs,
26620
26703
  currentStep,
26621
26704
  onChange: setCurrentStep,
26622
26705
  collapsed
@@ -26631,13 +26714,13 @@ function WorkflowLayout(props) {
26631
26714
  position: "sticky",
26632
26715
  left: "left0",
26633
26716
  width: ["w_var", {
26634
- "--width": maybeCssVar59(__maybeInc27(headerWidth))
26717
+ "--width": maybeCssVar58(__maybeInc27(headerWidth))
26635
26718
  }],
26636
26719
  zIndex: ["z_var", {
26637
- "--zIndex": maybeCssVar59(zIndices.pageStickyHeader)
26720
+ "--zIndex": maybeCssVar58(zIndices.pageStickyHeader)
26638
26721
  }],
26639
26722
  top: ["top_var", {
26640
- "--top": maybeCssVar59(__maybeInc27(outerTop))
26723
+ "--top": maybeCssVar58(__maybeInc27(outerTop))
26641
26724
  }]
26642
26725
  }), ...tid.header, children: headerEl }),
26643
26726
  /* @__PURE__ */ jsx218("div", { className: "df fdc fg1 mh0 w100", ...tid.body, children: activeStep?.content }),
@@ -26652,13 +26735,13 @@ function WorkflowLayout(props) {
26652
26735
  position: "fixed",
26653
26736
  bottom: "bottom0",
26654
26737
  width: ["w_var", {
26655
- "--width": maybeCssVar59(__maybeInc27(headerWidth))
26738
+ "--width": maybeCssVar58(__maybeInc27(headerWidth))
26656
26739
  }],
26657
26740
  height: ["h_var", {
26658
26741
  "--height": `${mobileFooterHeightPx}px`
26659
26742
  }],
26660
26743
  zIndex: ["z_var", {
26661
- "--zIndex": maybeCssVar59(zIndices.pageStickyFooter)
26744
+ "--zIndex": maybeCssVar58(zIndices.pageStickyFooter)
26662
26745
  }],
26663
26746
  display: "df",
26664
26747
  alignItems: "aic",