@amboss/design-system 4.9.4-canary.2 → 4.9.4-canary.4

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 (31) hide show
  1. package/build/cjs/components/Layout/BottomBar/LayoutBottomBar.d.ts +3 -1
  2. package/build/cjs/components/Layout/BottomBar/LayoutBottomBar.js +1 -1
  3. package/build/cjs/components/Layout/BottomBar/LayoutBottomBarItem.d.ts +4 -0
  4. package/build/cjs/components/Layout/BottomBar/StyledLayoutBottomBar.d.ts +1 -1
  5. package/build/cjs/components/Layout/BottomBar/StyledLayoutBottomBar.js +1 -1
  6. package/build/cjs/components/Layout/BottomBar/StyledLayoutBottomBarSection.d.ts +3 -0
  7. package/build/cjs/components/Layout/BottomBar/StyledLayoutBottomBarSection.js +1 -1
  8. package/build/cjs/components/Layout/BottomBar/getBottomBarLayout.d.ts +5 -2
  9. package/build/cjs/components/Layout/BottomBar/getBottomBarLayout.js +1 -1
  10. package/build/cjs/components/Layout/LayoutCssVars.d.ts +1 -1
  11. package/build/cjs/components/Layout/LayoutCssVars.js +1 -1
  12. package/build/cjs/components/Layout/cssVarStore.d.ts +10 -3
  13. package/build/cjs/components/Layout/cssVarStore.js +1 -1
  14. package/build/esm/components/Layout/BottomBar/LayoutBottomBar.d.ts +3 -1
  15. package/build/esm/components/Layout/BottomBar/LayoutBottomBar.js +1 -1
  16. package/build/esm/components/Layout/BottomBar/LayoutBottomBarItem.d.ts +4 -0
  17. package/build/esm/components/Layout/BottomBar/StyledLayoutBottomBar.d.ts +1 -1
  18. package/build/esm/components/Layout/BottomBar/StyledLayoutBottomBar.js +1 -1
  19. package/build/esm/components/Layout/BottomBar/StyledLayoutBottomBarSection.d.ts +3 -0
  20. package/build/esm/components/Layout/BottomBar/StyledLayoutBottomBarSection.js +1 -1
  21. package/build/esm/components/Layout/BottomBar/getBottomBarLayout.d.ts +5 -2
  22. package/build/esm/components/Layout/BottomBar/getBottomBarLayout.js +1 -1
  23. package/build/esm/components/Layout/LayoutCssVars.d.ts +1 -1
  24. package/build/esm/components/Layout/LayoutCssVars.js +1 -1
  25. package/build/esm/components/Layout/cssVarStore.d.ts +10 -3
  26. package/build/esm/components/Layout/cssVarStore.js +1 -1
  27. package/package.json +1 -1
  28. package/build/cjs/components/Layout/BottomBar/getBottomBarOuterSpaceStyles.d.ts +0 -14
  29. package/build/cjs/components/Layout/BottomBar/getBottomBarOuterSpaceStyles.js +0 -1
  30. package/build/esm/components/Layout/BottomBar/getBottomBarOuterSpaceStyles.d.ts +0 -14
  31. package/build/esm/components/Layout/BottomBar/getBottomBarOuterSpaceStyles.js +0 -1
@@ -3,7 +3,9 @@ import type { ConditionalAccessibleName } from "../../../types/a11y";
3
3
  export type LayoutBottomBarProps = ConditionalAccessibleName & {
4
4
  /** Layout.BottomBarItem declarations for the page's actions. */
5
5
  children: ReactNode;
6
+ /** Background of each section; gaps stay transparent. Defaults to transparent. */
7
+ background?: "primary" | "secondary" | "transparent";
6
8
  /** Identifier applied to the action group. */
7
9
  "data-e2e-test-id"?: string;
8
10
  };
9
- export declare function LayoutBottomBar({ children, "data-e2e-test-id": dataE2eTestId, ...accessibleName }: LayoutBottomBarProps): ReactElement | null;
11
+ export declare function LayoutBottomBar({ children, background, "data-e2e-test-id": dataE2eTestId, ...accessibleName }: LayoutBottomBarProps): ReactElement | null;
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),Object.defineProperty(exports,"LayoutBottomBar",{enumerable:!0,get:function(){return LayoutBottomBar}});const _react=/*#__PURE__*/require("@swc/helpers/_/_interop_require_wildcard")._(require("react")),_react1=require("@emotion/react"),_LayoutPortal=require("../LayoutPortal"),_LayoutCssVars=require("../LayoutCssVars"),_constants=require("../-constants"),_useLayout=require("../useLayout"),_getBottomBarLayout=require("./getBottomBarLayout"),_StyledLayoutBottomBar=require("./StyledLayoutBottomBar"),_StyledLayoutBottomBarSection=require("./StyledLayoutBottomBarSection"),useGlobalCssVariables=(rowCount,hasRightPanel)=>{let rowHeight=(0,_react1.useTheme)().variables.layout.bottomBar.contentHeight.default,bottomBarHeightCssVar=(0,_LayoutCssVars.useLayoutVar)(_constants.BOTTOM_BAR_HEIGHT_VAR),rightPanelBottomBarHeightCssVar=(0,_LayoutCssVars.useLayoutVar)(_constants.RIGHT_PANEL_BOTTOM_BAR_HEIGHT_VAR);(0,_react.useLayoutEffect)(()=>{if(!rowCount){bottomBarHeightCssVar.remove(),rightPanelBottomBarHeightCssVar.remove();return}bottomBarHeightCssVar.set(`calc(${rowCount} * ${rowHeight} + env(safe-area-inset-bottom))`),rightPanelBottomBarHeightCssVar.set(hasRightPanel?`var(${_constants.BOTTOM_BAR_HEIGHT_VAR})`:"0px")},[rowCount,rowHeight,hasRightPanel,bottomBarHeightCssVar,rightPanelBottomBarHeightCssVar])};function LayoutBottomBar({children,"data-e2e-test-id":dataE2eTestId,...accessibleName}){let{leftPanel,content,splitview,rightPanel}=(0,_useLayout.useLayout)(),{sections,cells,rowCount,hasRightPanel}=(0,_getBottomBarLayout.getBottomBarLayout)(children,{leftPanel,content,splitview,rightPanel});return(useGlobalCssVariables(rowCount,hasRightPanel),sections.length)?_react.default.createElement(_LayoutPortal.LayoutPortal,null,_react.default.createElement(_StyledLayoutBottomBar.StyledLayoutBottomBar,{...accessibleName,role:"group",hasRightPanel:hasRightPanel,cells:cells,hasSplitColumns:"column"===content.presentation&&"column"===splitview.presentation,"data-ds-id":"LayoutBottomBar","data-e2e-test-id":dataE2eTestId},sections.map(section=>_react.default.createElement(_StyledLayoutBottomBarSection.StyledLayoutBottomBarSection,{key:section.region,"data-e2e-test-id":section["data-e2e-test-id"],columnIndex:section.columnIndex,rowIndex:section.rowIndex,fullWidth:"full"===section.placement},section.children)))):null}
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),Object.defineProperty(exports,"LayoutBottomBar",{enumerable:!0,get:function(){return LayoutBottomBar}});const _react=/*#__PURE__*/require("@swc/helpers/_/_interop_require_wildcard")._(require("react")),_react1=require("@emotion/react"),_LayoutPortal=require("../LayoutPortal"),_LayoutCssVars=require("../LayoutCssVars"),_constants=require("../-constants"),_useLayout=require("../useLayout"),_getBottomBarLayout=require("./getBottomBarLayout"),_StyledLayoutBottomBar=require("./StyledLayoutBottomBar"),_StyledLayoutBottomBarSection=require("./StyledLayoutBottomBarSection"),useGlobalCssVariables=(rowCount,hasRightPanel)=>{let rowHeight=(0,_react1.useTheme)().variables.layout.bottomBar.contentHeight.default,bottomBarHeightCssVar=(0,_LayoutCssVars.useLayoutVar)(_constants.BOTTOM_BAR_HEIGHT_VAR),rightPanelBottomBarHeightCssVar=(0,_LayoutCssVars.useLayoutVar)(_constants.RIGHT_PANEL_BOTTOM_BAR_HEIGHT_VAR);(0,_react.useLayoutEffect)(()=>{if(!rowCount){bottomBarHeightCssVar.remove(),rightPanelBottomBarHeightCssVar.remove();return}bottomBarHeightCssVar.set(`calc(${rowCount} * ${rowHeight} + env(safe-area-inset-bottom))`),rightPanelBottomBarHeightCssVar.set(hasRightPanel?`var(${_constants.BOTTOM_BAR_HEIGHT_VAR})`:"0px")},[rowCount,rowHeight,hasRightPanel,bottomBarHeightCssVar,rightPanelBottomBarHeightCssVar])};function LayoutBottomBar({children,background="transparent","data-e2e-test-id":dataE2eTestId,...accessibleName}){let{leftPanel,content,splitview,rightPanel}=(0,_useLayout.useLayout)(),{sections,cells,rowCount,hasRightPanel}=(0,_getBottomBarLayout.getBottomBarLayout)({children,layout:{leftPanel,content,splitview,rightPanel}});return(useGlobalCssVariables(rowCount,hasRightPanel),sections.length)?_react.default.createElement(_LayoutPortal.LayoutPortal,null,_react.default.createElement(_StyledLayoutBottomBar.StyledLayoutBottomBar,{...accessibleName,role:"group",hasRightPanel:hasRightPanel,cells:cells,hasFullWidthSection:sections.some(({placement})=>"full"===placement),"data-ds-id":"LayoutBottomBar","data-e2e-test-id":dataE2eTestId},sections.map(section=>_react.default.createElement(_StyledLayoutBottomBarSection.StyledLayoutBottomBarSection,{key:section.region,"data-ds-id":"LayoutBottomBarSection",background:background,"data-e2e-test-id":section["data-e2e-test-id"],columnIndex:section.columnIndex,rowIndex:section.rowIndex,fullWidth:"full"===section.placement,hasPanelDivider:"leftPanel"===section.region},section.children)))):null}
@@ -4,6 +4,10 @@ export type LayoutBottomBarFallback = "hide" | "remaining" | "full";
4
4
  export type LayoutBottomBarItemProps = {
5
5
  /** Layout region whose column the item follows. */
6
6
  region: SlotKey;
7
+ /** Bounds for column actions. Defaults to panel. Available lets content and
8
+ * split actions occupy their outer margins up to the side panels, keeping gaps.
9
+ * The child controls whether it fills these bounds; fallback is unchanged. */
10
+ boundary?: "panel" | "available";
7
11
  /** Placement when the region has no column. Defaults to hiding the item. */
8
12
  fallback?: LayoutBottomBarFallback;
9
13
  /** Actions supplied and styled by the consumer. */
@@ -1,7 +1,7 @@
1
1
  import type { BottomBarCell } from "./getBottomBarLayout";
2
2
  type StyledLayoutBottomBarProps = {
3
3
  hasRightPanel: boolean;
4
- hasSplitColumns: boolean;
4
+ hasFullWidthSection: boolean;
5
5
  cells: BottomBarCell[];
6
6
  };
7
7
  export declare const StyledLayoutBottomBar: import("@emotion/styled").StyledComponent<{
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),Object.defineProperty(exports,"StyledLayoutBottomBar",{enumerable:!0,get:function(){return StyledLayoutBottomBar}});const _styled=/*#__PURE__*/require("@swc/helpers/_/_interop_require_default")._(require("@emotion/styled")),_getBottomBarOuterSpaceStyles=require("./getBottomBarOuterSpaceStyles"),_constants=require("../-constants"),getRegionStart=region=>`var(${_constants.PANEL_START_VAR[region]}, 0px)`,getRegionWidth=region=>`var(${_constants.PANEL_WIDTH_VAR[region]}, 0px)`,getBottomBarCellWidth=cell=>{switch(cell.kind){case"leading-gap":return getRegionStart(cell.region);case"trailing-gap":return`max(0px, calc(100% - ${getRegionStart(cell.region)} - ${getRegionWidth(cell.region)}))`;case"column-gap":return`max(0px, calc(${getRegionStart(cell.region)} - ${getRegionStart(cell.previousRegion)} - ${getRegionWidth(cell.previousRegion)}))`;case"flexible-gap":return"minmax(0, 1fr)";default:{let{region,placement,fallback}=cell.section;if("remaining"===placement)return"max-content";if(cell.flexible)return"minmax(0, 1fr)";let columnWidth=cell.fillLeadingSpace?`calc(${getRegionWidth(region)} + ${getRegionStart(region)})`:getRegionWidth(region);return"remaining"===fallback?`minmax(max-content, ${columnWidth})`:columnWidth}}},StyledLayoutBottomBar=(0,_styled.default)("div",{target:"e7hwo8w0",label:"StyledLayoutBottomBar"})(({theme,hasRightPanel,cells})=>({display:"grid",gridTemplateColumns:cells.map(getBottomBarCellWidth).join(" ")||"minmax(0, 1fr)",gridAutoRows:theme.variables.layout.bottomBar.contentHeight.default,alignContent:"start",bottom:0,boxShadow:theme.values.elevation[2],boxSizing:"border-box",height:_constants.PAGE_BOTTOM_BAR_INSET,left:0,opacity:`var(${_constants.LAYOUT_REGIONS_READY_VAR}, 0)`,paddingBottom:"env(safe-area-inset-bottom)",position:"absolute",right:hasRightPanel?0:`calc(${getRegionWidth("rightPanel")} + min(${getRegionWidth("rightPanel")}, ${theme.variables.size.spacing.xxs}))`,zIndex:theme.variables.zIndex.dropdown}),_getBottomBarOuterSpaceStyles.getBottomBarOuterSpaceStyles);
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),Object.defineProperty(exports,"StyledLayoutBottomBar",{enumerable:!0,get:function(){return StyledLayoutBottomBar}});const _styled=/*#__PURE__*/require("@swc/helpers/_/_interop_require_default")._(require("@emotion/styled")),_constants=require("../-constants"),getRegionStart=region=>`var(${_constants.PANEL_START_VAR[region]}, 0px)`,getRegionWidth=region=>`var(${_constants.PANEL_WIDTH_VAR[region]}, 0px)`,getPanelBounds=region=>({start:getRegionStart(region),end:`calc(${getRegionStart(region)} + ${getRegionWidth(region)})`}),getBottomBarBounds=({cells,contentAreaEnd})=>{let bounds={leftPanel:getPanelBounds("leftPanel"),content:getPanelBounds("content"),splitview:getPanelBounds("splitview"),rightPanel:getPanelBounds("rightPanel")};return cells.forEach(cell=>{"section"===cell.kind&&"column"===cell.section.placement&&"available"===cell.section.boundary&&("content"===cell.section.region&&(bounds.content.start=`min(${bounds.content.start}, ${bounds.leftPanel.end})`),"splitview"===cell.section.region&&(bounds.splitview.end=`max(${bounds.splitview.end}, ${contentAreaEnd})`))}),bounds},getBottomBarCellWidth=(cell,bounds)=>{switch(cell.kind){case"leading-gap":return bounds[cell.region].start;case"trailing-gap":return`max(0px, calc(100% - ${bounds[cell.region].end}))`;case"column-gap":return`max(0px, calc(${bounds[cell.region].start} - ${bounds[cell.previousRegion].end}))`;case"flexible-gap":return"minmax(0, 1fr)";default:{let{region,placement,fallback}=cell.section;if("remaining"===placement)return"max-content";if(cell.flexible)return"minmax(0, 1fr)";let columnWidth=`max(0px, calc(${bounds[region].end} - ${bounds[region].start}))`;return"remaining"===fallback?`minmax(max-content, ${columnWidth})`:columnWidth}}},StyledLayoutBottomBar=(0,_styled.default)("div",{target:"eo8tbnx0",label:"StyledLayoutBottomBar"})(({theme,hasRightPanel,hasFullWidthSection,cells})=>{let rightPanelInset=`calc(${getRegionWidth("rightPanel")} + min(${getRegionWidth("rightPanel")}, ${theme.variables.size.spacing.xxs}))`,bounds=getBottomBarBounds({cells,contentAreaEnd:hasRightPanel?`calc(100% - ${rightPanelInset})`:"100%"}),sectionColumns=cells.flatMap((cell,index)=>"section"===cell.kind?[index+1]:[]),shadowColumns=hasFullWidthSection?"1 / -1":`${sectionColumns[0]} / ${sectionColumns[sectionColumns.length-1]+1}`;return{display:"grid",gridTemplateColumns:cells.map(cell=>getBottomBarCellWidth(cell,bounds)).join(" ")||"minmax(0, 1fr)",gridAutoRows:theme.variables.layout.bottomBar.contentHeight.default,alignContent:"start",bottom:0,boxSizing:"border-box",height:_constants.PAGE_BOTTOM_BAR_INSET,left:0,opacity:`var(${_constants.LAYOUT_REGIONS_READY_VAR}, 0)`,paddingBottom:"env(safe-area-inset-bottom)",position:"absolute",right:hasRightPanel?0:rightPanelInset,zIndex:theme.variables.zIndex.tooltip,"&::before":{content:'""',position:"absolute",inset:0,gridColumn:shadowColumns,boxShadow:theme.values.elevation[2],pointerEvents:"none"}}});
@@ -1,7 +1,10 @@
1
+ import type { LayoutBottomBarProps } from "./LayoutBottomBar";
1
2
  type StyledLayoutBottomBarSectionProps = {
3
+ background: NonNullable<LayoutBottomBarProps["background"]>;
2
4
  columnIndex?: number;
3
5
  rowIndex: number;
4
6
  fullWidth: boolean;
7
+ hasPanelDivider: boolean;
5
8
  };
6
9
  export declare const StyledLayoutBottomBarSection: import("@emotion/styled").StyledComponent<{
7
10
  theme?: import("@emotion/react").Theme;
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),Object.defineProperty(exports,"StyledLayoutBottomBarSection",{enumerable:!0,get:function(){return StyledLayoutBottomBarSection}});const StyledLayoutBottomBarSection=(0,/*#__PURE__*/require("@swc/helpers/_/_interop_require_default")._(require("@emotion/styled")).default)("div",{target:"e4dy5fk0",label:"StyledLayoutBottomBarSection"})(({columnIndex,rowIndex,fullWidth})=>({gridColumn:fullWidth?"1 / -1":(columnIndex??0)+1,gridRow:rowIndex+1,alignItems:"center",boxSizing:"border-box",display:"flex",minWidth:0,whiteSpace:"nowrap"}));
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),Object.defineProperty(exports,"StyledLayoutBottomBarSection",{enumerable:!0,get:function(){return StyledLayoutBottomBarSection}});const StyledLayoutBottomBarSection=(0,/*#__PURE__*/require("@swc/helpers/_/_interop_require_default")._(require("@emotion/styled")).default)("div",{target:"e5xujxr0",label:"StyledLayoutBottomBarSection"})(({theme,background,columnIndex,rowIndex,fullWidth,hasPanelDivider})=>({gridColumn:fullWidth?"1 / -1":(columnIndex??0)+1,gridRow:rowIndex+1,alignItems:"center",boxSizing:"border-box",backgroundColor:"transparent"===background?"transparent":theme.values.color.background[background].default,display:"flex",minWidth:0,whiteSpace:"nowrap",...hasPanelDivider&&{position:"relative","&::after":{content:'""',position:"absolute",top:0,bottom:0,right:0,width:1,backgroundColor:theme.values.color.border.secondary.default,pointerEvents:"none"}}}));
@@ -18,7 +18,6 @@ export type BottomBarCell = {
18
18
  kind: "section";
19
19
  section: SharedSection;
20
20
  flexible: boolean;
21
- fillLeadingSpace: boolean;
22
21
  } | {
23
22
  kind: "leading-gap" | "trailing-gap";
24
23
  region: SlotKey;
@@ -35,5 +34,9 @@ type BottomBarArrangement = {
35
34
  rowCount: number;
36
35
  hasRightPanel: boolean;
37
36
  };
38
- export declare const getBottomBarLayout: (children: ReactNode, layout: BottomBarLayout) => BottomBarArrangement;
37
+ type BottomBarLayoutOptions = {
38
+ children: ReactNode;
39
+ layout: BottomBarLayout;
40
+ };
41
+ export declare const getBottomBarLayout: ({ children, layout, }: BottomBarLayoutOptions) => BottomBarArrangement;
39
42
  export {};
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),Object.defineProperty(exports,"getBottomBarLayout",{enumerable:!0,get:function(){return getBottomBarLayout}});const _react=require("react"),_constants=require("../-constants"),_LayoutBottomBarItem=require("./LayoutBottomBarItem"),getBottomBarItemMode=({region,fallback,layout})=>{let handle=layout[region];return"column"===handle.presentation?"column":("leftPanel"!==region||"sidebar"!==layout.leftPanel.state.variant)&&("rightPanel"!==region||"sidebar"!==layout.rightPanel.state.variant)||handle.isVisible||null===handle.animation?fallback:"column"},getVisibleSections=(children,layout)=>_react.Children.toArray(children).flatMap(child=>{if(!(0,_react.isValidElement)(child)||child.type!==_LayoutBottomBarItem.LayoutBottomBarItem||null==child.props.children||!1===child.props.children)return[];let{region,fallback="hide"}=child.props,placement=getBottomBarItemMode({region,fallback,layout});return"hide"===placement?[]:[{...child.props,placement,fallback}]}),shouldPreserveSplitColumnWidth=sections=>{let hasLeftFallback=sections.some(({region,fallback})=>"leftPanel"===region&&"remaining"===fallback),hasContentColumn=sections.some(({region,placement})=>"content"===region&&"column"===placement),hasSplitColumn=sections.some(({region,placement})=>"splitview"===region&&"column"===placement),hasRightFallback=sections.some(({region,fallback})=>"rightPanel"===region&&"remaining"===fallback);return hasLeftFallback&&hasContentColumn&&hasSplitColumn&&!hasRightFallback},getSharedRowCells=(sections,layout)=>{if(!sections.length)return[];let firstSection=sections[0],lastSection=sections[sections.length-1],hasRemainingActions=sections.some(({fallback})=>"remaining"===fallback),preserveSplitColumn=shouldPreserveSplitColumnWidth(sections),fillLeadingSpace="column"===firstSection.placement&&("content"===firstSection.region||"splitview"===firstSection.region)&&"column"!==layout.leftPanel.presentation,flexibleColumns={leftPanel:!1,content:hasRemainingActions,splitview:hasRemainingActions&&!preserveSplitColumn,rightPanel:!1},hasFlexibleColumn=sections.some(({region,placement})=>"column"===placement&&flexibleColumns[region]),needsFlexibleGap=hasRemainingActions&&!hasFlexibleColumn,rightActions=sections.find(({region})=>"rightPanel"===region);return[..."column"!==firstSection.placement||fillLeadingSpace?[]:[{kind:"leading-gap",region:firstSection.region}],...sections.flatMap((section,index)=>{let previousSection=sections[index-1];return[..."column"===section.placement&&previousSection?.placement==="column"?[{kind:"column-gap",region:section.region,previousRegion:previousSection.region}]:[],...needsFlexibleGap&&section===rightActions?[{kind:"flexible-gap"}]:[],{kind:"section",section,flexible:flexibleColumns[section.region],fillLeadingSpace:section===firstSection&&fillLeadingSpace&&!hasRemainingActions}]}),...!hasRemainingActions||preserveSplitColumn?[{kind:"trailing-gap",region:lastSection.region}]:[],...needsFlexibleGap&&!rightActions?[{kind:"flexible-gap"}]:[]]},getBottomBarLayout=(children,layout)=>{let sections=getVisibleSections(children,layout),sharedSections=_constants.PANEL_ORDER.flatMap(region=>sections.filter(section=>section.region===region&&"full"!==section.placement)),fullWidthSections=sections.filter(({placement})=>"full"===placement),sharedRowCount=+!!sharedSections.length,cells=getSharedRowCells(sharedSections,layout);return{cells,sections:[...cells.flatMap((cell,column)=>"section"===cell.kind?[{...cell.section,columnIndex:column,rowIndex:0}]:[]),...fullWidthSections.map((section,row)=>({...section,rowIndex:sharedRowCount+row}))],rowCount:sharedRowCount+fullWidthSections.length,hasRightPanel:sections.some(({region})=>"rightPanel"===region)}};
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),Object.defineProperty(exports,"getBottomBarLayout",{enumerable:!0,get:function(){return getBottomBarLayout}});const _react=require("react"),_constants=require("../-constants"),_LayoutBottomBarItem=require("./LayoutBottomBarItem"),getBottomBarItemMode=({region,fallback,layout})=>{let handle=layout[region];return"column"===handle.presentation?"column":("leftPanel"!==region||"sidebar"!==layout.leftPanel.state.variant)&&("rightPanel"!==region||"sidebar"!==layout.rightPanel.state.variant)||handle.isVisible||null===handle.animation?fallback:"column"},getVisibleSections=(children,layout)=>_react.Children.toArray(children).flatMap(child=>{if(!(0,_react.isValidElement)(child)||child.type!==_LayoutBottomBarItem.LayoutBottomBarItem||null==child.props.children||!1===child.props.children)return[];let{region,fallback="hide"}=child.props,placement=getBottomBarItemMode({region,fallback,layout});return"hide"===placement?[]:[{...child.props,placement,fallback}]}),shouldPreserveSplitColumnWidth=sections=>{let hasLeftFallback=sections.some(({region,fallback})=>"leftPanel"===region&&"remaining"===fallback),hasContentColumn=sections.some(({region,placement})=>"content"===region&&"column"===placement),hasSplitColumn=sections.some(({region,placement})=>"splitview"===region&&"column"===placement),hasRightFallback=sections.some(({region,fallback})=>"rightPanel"===region&&"remaining"===fallback);return hasLeftFallback&&hasContentColumn&&hasSplitColumn&&!hasRightFallback},getSharedRowCells=sections=>{if(!sections.length)return[];let firstSection=sections[0],lastSection=sections[sections.length-1],hasRemainingActions=sections.some(({fallback})=>"remaining"===fallback),preserveSplitColumn=shouldPreserveSplitColumnWidth(sections),flexibleColumns={leftPanel:!1,content:hasRemainingActions,splitview:hasRemainingActions&&!preserveSplitColumn,rightPanel:!1},hasFlexibleColumn=sections.some(({region,placement})=>"column"===placement&&flexibleColumns[region]),needsFlexibleGap=hasRemainingActions&&!hasFlexibleColumn,rightActions=sections.find(({region})=>"rightPanel"===region);return[..."column"===firstSection.placement?[{kind:"leading-gap",region:firstSection.region}]:[],...sections.flatMap((section,index)=>{let previousSection=sections[index-1];return[..."column"===section.placement&&previousSection?.placement==="column"?[{kind:"column-gap",region:section.region,previousRegion:previousSection.region}]:[],...needsFlexibleGap&&section===rightActions?[{kind:"flexible-gap"}]:[],{kind:"section",section,flexible:flexibleColumns[section.region]}]}),...!hasRemainingActions||preserveSplitColumn?[{kind:"trailing-gap",region:lastSection.region}]:[],...needsFlexibleGap&&!rightActions?[{kind:"flexible-gap"}]:[]]},getBottomBarLayout=({children,layout})=>{let sections=getVisibleSections(children,layout),sharedSections=_constants.PANEL_ORDER.flatMap(region=>sections.filter(section=>section.region===region&&"full"!==section.placement)),fullWidthSections=sections.filter(({placement})=>"full"===placement),sharedRowCount=+!!sharedSections.length,cells=getSharedRowCells(sharedSections);return{cells,sections:[...cells.flatMap((cell,column)=>"section"===cell.kind?[{...cell.section,columnIndex:column,rowIndex:0}]:[]),...fullWidthSections.map((section,row)=>({...section,rowIndex:sharedRowCount+row}))],rowCount:sharedRowCount+fullWidthSections.length,hasRightPanel:sections.some(({region})=>"rightPanel"===region)}};
@@ -8,7 +8,7 @@ export type LayoutVarHandle = {
8
8
  };
9
9
  /**
10
10
  * Register one layout CSS var; returns a stable imperative handle. The var is
11
- * removed on unmount, so it only exists while its producer is mounted. Call
11
+ * removed on unmount only if this producer still owns the latest write. Call
12
12
  * `.set()` from wherever the value is known — an effect (state-driven vars like
13
13
  * the subnav offset) or a ResizeObserver (measured vars) — so updates publish
14
14
  * straight to the single `<LayoutCssVars>` sink and never re-render the producer.
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0});var target=exports,all={get LayoutCssVarStoreProvider(){return LayoutCssVarStoreProvider},get LayoutCssVars(){return LayoutCssVars},get useLayoutVar(){return useLayoutVar}};for(var name in all)Object.defineProperty(target,name,{enumerable:!0,get:Object.getOwnPropertyDescriptor(all,name).get});const _react=/*#__PURE__*/require("@swc/helpers/_/_interop_require_wildcard")._(require("react")),_react1=require("@emotion/react"),LayoutCssVarStoreContext=(0,_react.createContext)(null),LayoutCssVarStoreProvider=LayoutCssVarStoreContext.Provider,EMPTY_VARS={},NOOP_SUBSCRIBE=()=>()=>{},useLayoutVar=name=>{let store=(0,_react.useContext)(LayoutCssVarStoreContext);return(0,_react.useEffect)(()=>()=>store?.remove(name),[store,name]),(0,_react.useMemo)(()=>({set:value=>""===value?store?.remove(name):store?.set(name,value),remove:()=>store?.remove(name)}),[store,name])};function LayoutCssVars(){let store=(0,_react.useContext)(LayoutCssVarStoreContext),vars=(0,_react.useSyncExternalStore)(store?.subscribe??NOOP_SUBSCRIBE,store?store.getSnapshot:()=>EMPTY_VARS,()=>EMPTY_VARS);return _react.default.createElement(_react1.Global,{styles:[{":root":vars}]})}
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0});var target=exports,all={get LayoutCssVarStoreProvider(){return LayoutCssVarStoreProvider},get LayoutCssVars(){return LayoutCssVars},get useLayoutVar(){return useLayoutVar}};for(var name in all)Object.defineProperty(target,name,{enumerable:!0,get:Object.getOwnPropertyDescriptor(all,name).get});const _react=/*#__PURE__*/require("@swc/helpers/_/_interop_require_wildcard")._(require("react")),_react1=require("@emotion/react"),LayoutCssVarStoreContext=(0,_react.createContext)(null),LayoutCssVarStoreProvider=LayoutCssVarStoreContext.Provider,EMPTY_VARS={},NOOP_SUBSCRIBE=()=>()=>{},useLayoutVar=name=>{let store=(0,_react.useContext)(LayoutCssVarStoreContext),handle=(0,_react.useMemo)(()=>{let owner=Symbol(name);return{set:value=>""===value?store?.remove(name,owner):store?.set({name,value,owner}),remove:()=>store?.remove(name,owner)}},[store,name]);return(0,_react.useEffect)(()=>handle.remove,[handle]),handle};function LayoutCssVars(){let store=(0,_react.useContext)(LayoutCssVarStoreContext),vars=(0,_react.useSyncExternalStore)(store?.subscribe??NOOP_SUBSCRIBE,store?store.getSnapshot:()=>EMPTY_VARS,()=>EMPTY_VARS);return _react.default.createElement(_react1.Global,{styles:[{":root":vars}]})}
@@ -1,3 +1,8 @@
1
+ type LayoutCssVarWrite = {
2
+ name: string;
3
+ value: string;
4
+ owner: symbol;
5
+ };
1
6
  /**
2
7
  * Tiny pub/sub registry for the layout's CSS custom properties. Producers
3
8
  * publish a value by name (the component that owns the *why* — e.g. the NavBar
@@ -6,12 +11,14 @@
6
11
  * via the same `useSyncExternalStore` pattern.
7
12
  *
8
13
  * One name = one producer. The registry is keyed by name, so a second writer to
9
- * the same name last-wins; don't share a name across unrelated producers.
14
+ * the same name last-wins. Only that writer may remove it, so an old instance's
15
+ * delayed unmount cleanup cannot erase a replacement's value.
10
16
  */
11
17
  export type LayoutCssVarStore = {
12
18
  getSnapshot: () => Record<string, string>;
13
- set: (name: string, value: string) => void;
14
- remove: (name: string) => void;
19
+ set: (entry: LayoutCssVarWrite) => void;
20
+ remove: (name: string, owner: symbol) => void;
15
21
  subscribe: (listener: () => void) => () => void;
16
22
  };
17
23
  export declare function createLayoutCssVarStore(): LayoutCssVarStore;
24
+ export {};
@@ -1 +1 @@
1
- "use strict";function createLayoutCssVarStore(){let vars={},listeners=new Set,notify=()=>listeners.forEach(listener=>listener());return{getSnapshot:()=>vars,set:(name,value)=>{vars[name]!==value&&(vars={...vars,[name]:value},notify())},remove:name=>{if(!(name in vars))return;let next={...vars};delete next[name],vars=next,notify()},subscribe:listener=>(listeners.add(listener),()=>{listeners.delete(listener)})}}Object.defineProperty(exports,"__esModule",{value:!0}),Object.defineProperty(exports,"createLayoutCssVarStore",{enumerable:!0,get:function(){return createLayoutCssVarStore}});
1
+ "use strict";function createLayoutCssVarStore(){let vars={},owners=new Map,listeners=new Set,notify=()=>listeners.forEach(listener=>listener());return{getSnapshot:()=>vars,set:({name,value,owner})=>{owners.set(name,owner),vars[name]!==value&&(vars={...vars,[name]:value},notify())},remove:(name,owner)=>{if(owners.get(name)!==owner)return;owners.delete(name);let next={...vars};delete next[name],vars=next,notify()},subscribe:listener=>(listeners.add(listener),()=>{listeners.delete(listener)})}}Object.defineProperty(exports,"__esModule",{value:!0}),Object.defineProperty(exports,"createLayoutCssVarStore",{enumerable:!0,get:function(){return createLayoutCssVarStore}});
@@ -3,7 +3,9 @@ import type { ConditionalAccessibleName } from "../../../types/a11y";
3
3
  export type LayoutBottomBarProps = ConditionalAccessibleName & {
4
4
  /** Layout.BottomBarItem declarations for the page's actions. */
5
5
  children: ReactNode;
6
+ /** Background of each section; gaps stay transparent. Defaults to transparent. */
7
+ background?: "primary" | "secondary" | "transparent";
6
8
  /** Identifier applied to the action group. */
7
9
  "data-e2e-test-id"?: string;
8
10
  };
9
- export declare function LayoutBottomBar({ children, "data-e2e-test-id": dataE2eTestId, ...accessibleName }: LayoutBottomBarProps): ReactElement | null;
11
+ export declare function LayoutBottomBar({ children, background, "data-e2e-test-id": dataE2eTestId, ...accessibleName }: LayoutBottomBarProps): ReactElement | null;
@@ -1 +1 @@
1
- import React,{useLayoutEffect}from"react";import{useTheme}from"@emotion/react";import{LayoutPortal}from"../LayoutPortal";import{useLayoutVar}from"../LayoutCssVars";import{BOTTOM_BAR_HEIGHT_VAR,RIGHT_PANEL_BOTTOM_BAR_HEIGHT_VAR}from"../-constants";import{useLayout}from"../useLayout";import{getBottomBarLayout}from"./getBottomBarLayout";import{StyledLayoutBottomBar}from"./StyledLayoutBottomBar";import{StyledLayoutBottomBarSection}from"./StyledLayoutBottomBarSection";let useGlobalCssVariables=(rowCount,hasRightPanel)=>{let rowHeight=useTheme().variables.layout.bottomBar.contentHeight.default,bottomBarHeightCssVar=useLayoutVar(BOTTOM_BAR_HEIGHT_VAR),rightPanelBottomBarHeightCssVar=useLayoutVar(RIGHT_PANEL_BOTTOM_BAR_HEIGHT_VAR);useLayoutEffect(()=>{if(!rowCount){bottomBarHeightCssVar.remove(),rightPanelBottomBarHeightCssVar.remove();return}bottomBarHeightCssVar.set(`calc(${rowCount} * ${rowHeight} + env(safe-area-inset-bottom))`),rightPanelBottomBarHeightCssVar.set(hasRightPanel?`var(${BOTTOM_BAR_HEIGHT_VAR})`:"0px")},[rowCount,rowHeight,hasRightPanel,bottomBarHeightCssVar,rightPanelBottomBarHeightCssVar])};export function LayoutBottomBar({children,"data-e2e-test-id":dataE2eTestId,...accessibleName}){let{leftPanel,content,splitview,rightPanel}=useLayout(),{sections,cells,rowCount,hasRightPanel}=getBottomBarLayout(children,{leftPanel,content,splitview,rightPanel});return(useGlobalCssVariables(rowCount,hasRightPanel),sections.length)?React.createElement(LayoutPortal,null,React.createElement(StyledLayoutBottomBar,{...accessibleName,role:"group",hasRightPanel:hasRightPanel,cells:cells,hasSplitColumns:"column"===content.presentation&&"column"===splitview.presentation,"data-ds-id":"LayoutBottomBar","data-e2e-test-id":dataE2eTestId},sections.map(section=>React.createElement(StyledLayoutBottomBarSection,{key:section.region,"data-e2e-test-id":section["data-e2e-test-id"],columnIndex:section.columnIndex,rowIndex:section.rowIndex,fullWidth:"full"===section.placement},section.children)))):null}
1
+ import React,{useLayoutEffect}from"react";import{useTheme}from"@emotion/react";import{LayoutPortal}from"../LayoutPortal";import{useLayoutVar}from"../LayoutCssVars";import{BOTTOM_BAR_HEIGHT_VAR,RIGHT_PANEL_BOTTOM_BAR_HEIGHT_VAR}from"../-constants";import{useLayout}from"../useLayout";import{getBottomBarLayout}from"./getBottomBarLayout";import{StyledLayoutBottomBar}from"./StyledLayoutBottomBar";import{StyledLayoutBottomBarSection}from"./StyledLayoutBottomBarSection";let useGlobalCssVariables=(rowCount,hasRightPanel)=>{let rowHeight=useTheme().variables.layout.bottomBar.contentHeight.default,bottomBarHeightCssVar=useLayoutVar(BOTTOM_BAR_HEIGHT_VAR),rightPanelBottomBarHeightCssVar=useLayoutVar(RIGHT_PANEL_BOTTOM_BAR_HEIGHT_VAR);useLayoutEffect(()=>{if(!rowCount){bottomBarHeightCssVar.remove(),rightPanelBottomBarHeightCssVar.remove();return}bottomBarHeightCssVar.set(`calc(${rowCount} * ${rowHeight} + env(safe-area-inset-bottom))`),rightPanelBottomBarHeightCssVar.set(hasRightPanel?`var(${BOTTOM_BAR_HEIGHT_VAR})`:"0px")},[rowCount,rowHeight,hasRightPanel,bottomBarHeightCssVar,rightPanelBottomBarHeightCssVar])};export function LayoutBottomBar({children,background="transparent","data-e2e-test-id":dataE2eTestId,...accessibleName}){let{leftPanel,content,splitview,rightPanel}=useLayout(),{sections,cells,rowCount,hasRightPanel}=getBottomBarLayout({children,layout:{leftPanel,content,splitview,rightPanel}});return(useGlobalCssVariables(rowCount,hasRightPanel),sections.length)?React.createElement(LayoutPortal,null,React.createElement(StyledLayoutBottomBar,{...accessibleName,role:"group",hasRightPanel:hasRightPanel,cells:cells,hasFullWidthSection:sections.some(({placement})=>"full"===placement),"data-ds-id":"LayoutBottomBar","data-e2e-test-id":dataE2eTestId},sections.map(section=>React.createElement(StyledLayoutBottomBarSection,{key:section.region,"data-ds-id":"LayoutBottomBarSection",background:background,"data-e2e-test-id":section["data-e2e-test-id"],columnIndex:section.columnIndex,rowIndex:section.rowIndex,fullWidth:"full"===section.placement,hasPanelDivider:"leftPanel"===section.region},section.children)))):null}
@@ -4,6 +4,10 @@ export type LayoutBottomBarFallback = "hide" | "remaining" | "full";
4
4
  export type LayoutBottomBarItemProps = {
5
5
  /** Layout region whose column the item follows. */
6
6
  region: SlotKey;
7
+ /** Bounds for column actions. Defaults to panel. Available lets content and
8
+ * split actions occupy their outer margins up to the side panels, keeping gaps.
9
+ * The child controls whether it fills these bounds; fallback is unchanged. */
10
+ boundary?: "panel" | "available";
7
11
  /** Placement when the region has no column. Defaults to hiding the item. */
8
12
  fallback?: LayoutBottomBarFallback;
9
13
  /** Actions supplied and styled by the consumer. */
@@ -1,7 +1,7 @@
1
1
  import type { BottomBarCell } from "./getBottomBarLayout";
2
2
  type StyledLayoutBottomBarProps = {
3
3
  hasRightPanel: boolean;
4
- hasSplitColumns: boolean;
4
+ hasFullWidthSection: boolean;
5
5
  cells: BottomBarCell[];
6
6
  };
7
7
  export declare const StyledLayoutBottomBar: import("@emotion/styled").StyledComponent<{
@@ -1 +1 @@
1
- import styled from"@emotion/styled";import{getBottomBarOuterSpaceStyles}from"./getBottomBarOuterSpaceStyles";import{LAYOUT_REGIONS_READY_VAR,PAGE_BOTTOM_BAR_INSET,PANEL_WIDTH_VAR,PANEL_START_VAR}from"../-constants";let getRegionStart=region=>`var(${PANEL_START_VAR[region]}, 0px)`,getRegionWidth=region=>`var(${PANEL_WIDTH_VAR[region]}, 0px)`,getBottomBarCellWidth=cell=>{switch(cell.kind){case"leading-gap":return getRegionStart(cell.region);case"trailing-gap":return`max(0px, calc(100% - ${getRegionStart(cell.region)} - ${getRegionWidth(cell.region)}))`;case"column-gap":return`max(0px, calc(${getRegionStart(cell.region)} - ${getRegionStart(cell.previousRegion)} - ${getRegionWidth(cell.previousRegion)}))`;case"flexible-gap":return"minmax(0, 1fr)";default:{let{region,placement,fallback}=cell.section;if("remaining"===placement)return"max-content";if(cell.flexible)return"minmax(0, 1fr)";let columnWidth=cell.fillLeadingSpace?`calc(${getRegionWidth(region)} + ${getRegionStart(region)})`:getRegionWidth(region);return"remaining"===fallback?`minmax(max-content, ${columnWidth})`:columnWidth}}};export const StyledLayoutBottomBar=styled("div",{target:"e7hwo8w0",label:"StyledLayoutBottomBar"})(({theme,hasRightPanel,cells})=>({display:"grid",gridTemplateColumns:cells.map(getBottomBarCellWidth).join(" ")||"minmax(0, 1fr)",gridAutoRows:theme.variables.layout.bottomBar.contentHeight.default,alignContent:"start",bottom:0,boxShadow:theme.values.elevation[2],boxSizing:"border-box",height:PAGE_BOTTOM_BAR_INSET,left:0,opacity:`var(${LAYOUT_REGIONS_READY_VAR}, 0)`,paddingBottom:"env(safe-area-inset-bottom)",position:"absolute",right:hasRightPanel?0:`calc(${getRegionWidth("rightPanel")} + min(${getRegionWidth("rightPanel")}, ${theme.variables.size.spacing.xxs}))`,zIndex:theme.variables.zIndex.dropdown}),getBottomBarOuterSpaceStyles);
1
+ import styled from"@emotion/styled";import{LAYOUT_REGIONS_READY_VAR,PAGE_BOTTOM_BAR_INSET,PANEL_WIDTH_VAR,PANEL_START_VAR}from"../-constants";let getRegionStart=region=>`var(${PANEL_START_VAR[region]}, 0px)`,getRegionWidth=region=>`var(${PANEL_WIDTH_VAR[region]}, 0px)`,getPanelBounds=region=>({start:getRegionStart(region),end:`calc(${getRegionStart(region)} + ${getRegionWidth(region)})`}),getBottomBarBounds=({cells,contentAreaEnd})=>{let bounds={leftPanel:getPanelBounds("leftPanel"),content:getPanelBounds("content"),splitview:getPanelBounds("splitview"),rightPanel:getPanelBounds("rightPanel")};return cells.forEach(cell=>{"section"===cell.kind&&"column"===cell.section.placement&&"available"===cell.section.boundary&&("content"===cell.section.region&&(bounds.content.start=`min(${bounds.content.start}, ${bounds.leftPanel.end})`),"splitview"===cell.section.region&&(bounds.splitview.end=`max(${bounds.splitview.end}, ${contentAreaEnd})`))}),bounds},getBottomBarCellWidth=(cell,bounds)=>{switch(cell.kind){case"leading-gap":return bounds[cell.region].start;case"trailing-gap":return`max(0px, calc(100% - ${bounds[cell.region].end}))`;case"column-gap":return`max(0px, calc(${bounds[cell.region].start} - ${bounds[cell.previousRegion].end}))`;case"flexible-gap":return"minmax(0, 1fr)";default:{let{region,placement,fallback}=cell.section;if("remaining"===placement)return"max-content";if(cell.flexible)return"minmax(0, 1fr)";let columnWidth=`max(0px, calc(${bounds[region].end} - ${bounds[region].start}))`;return"remaining"===fallback?`minmax(max-content, ${columnWidth})`:columnWidth}}};export const StyledLayoutBottomBar=styled("div",{target:"eo8tbnx0",label:"StyledLayoutBottomBar"})(({theme,hasRightPanel,hasFullWidthSection,cells})=>{let rightPanelInset=`calc(${getRegionWidth("rightPanel")} + min(${getRegionWidth("rightPanel")}, ${theme.variables.size.spacing.xxs}))`,bounds=getBottomBarBounds({cells,contentAreaEnd:hasRightPanel?`calc(100% - ${rightPanelInset})`:"100%"}),sectionColumns=cells.flatMap((cell,index)=>"section"===cell.kind?[index+1]:[]),shadowColumns=hasFullWidthSection?"1 / -1":`${sectionColumns[0]} / ${sectionColumns[sectionColumns.length-1]+1}`;return{display:"grid",gridTemplateColumns:cells.map(cell=>getBottomBarCellWidth(cell,bounds)).join(" ")||"minmax(0, 1fr)",gridAutoRows:theme.variables.layout.bottomBar.contentHeight.default,alignContent:"start",bottom:0,boxSizing:"border-box",height:PAGE_BOTTOM_BAR_INSET,left:0,opacity:`var(${LAYOUT_REGIONS_READY_VAR}, 0)`,paddingBottom:"env(safe-area-inset-bottom)",position:"absolute",right:hasRightPanel?0:rightPanelInset,zIndex:theme.variables.zIndex.tooltip,"&::before":{content:'""',position:"absolute",inset:0,gridColumn:shadowColumns,boxShadow:theme.values.elevation[2],pointerEvents:"none"}}});
@@ -1,7 +1,10 @@
1
+ import type { LayoutBottomBarProps } from "./LayoutBottomBar";
1
2
  type StyledLayoutBottomBarSectionProps = {
3
+ background: NonNullable<LayoutBottomBarProps["background"]>;
2
4
  columnIndex?: number;
3
5
  rowIndex: number;
4
6
  fullWidth: boolean;
7
+ hasPanelDivider: boolean;
5
8
  };
6
9
  export declare const StyledLayoutBottomBarSection: import("@emotion/styled").StyledComponent<{
7
10
  theme?: import("@emotion/react").Theme;
@@ -1 +1 @@
1
- import styled from"@emotion/styled";export const StyledLayoutBottomBarSection=styled("div",{target:"e4dy5fk0",label:"StyledLayoutBottomBarSection"})(({columnIndex,rowIndex,fullWidth})=>({gridColumn:fullWidth?"1 / -1":(columnIndex??0)+1,gridRow:rowIndex+1,alignItems:"center",boxSizing:"border-box",display:"flex",minWidth:0,whiteSpace:"nowrap"}));
1
+ import styled from"@emotion/styled";export const StyledLayoutBottomBarSection=styled("div",{target:"e5xujxr0",label:"StyledLayoutBottomBarSection"})(({theme,background,columnIndex,rowIndex,fullWidth,hasPanelDivider})=>({gridColumn:fullWidth?"1 / -1":(columnIndex??0)+1,gridRow:rowIndex+1,alignItems:"center",boxSizing:"border-box",backgroundColor:"transparent"===background?"transparent":theme.values.color.background[background].default,display:"flex",minWidth:0,whiteSpace:"nowrap",...hasPanelDivider&&{position:"relative","&::after":{content:'""',position:"absolute",top:0,bottom:0,right:0,width:1,backgroundColor:theme.values.color.border.secondary.default,pointerEvents:"none"}}}));
@@ -18,7 +18,6 @@ export type BottomBarCell = {
18
18
  kind: "section";
19
19
  section: SharedSection;
20
20
  flexible: boolean;
21
- fillLeadingSpace: boolean;
22
21
  } | {
23
22
  kind: "leading-gap" | "trailing-gap";
24
23
  region: SlotKey;
@@ -35,5 +34,9 @@ type BottomBarArrangement = {
35
34
  rowCount: number;
36
35
  hasRightPanel: boolean;
37
36
  };
38
- export declare const getBottomBarLayout: (children: ReactNode, layout: BottomBarLayout) => BottomBarArrangement;
37
+ type BottomBarLayoutOptions = {
38
+ children: ReactNode;
39
+ layout: BottomBarLayout;
40
+ };
41
+ export declare const getBottomBarLayout: ({ children, layout, }: BottomBarLayoutOptions) => BottomBarArrangement;
39
42
  export {};
@@ -1 +1 @@
1
- import{Children,isValidElement}from"react";import{PANEL_ORDER}from"../-constants";import{LayoutBottomBarItem}from"./LayoutBottomBarItem";let getBottomBarItemMode=({region,fallback,layout})=>{let handle=layout[region];return"column"===handle.presentation?"column":("leftPanel"!==region||"sidebar"!==layout.leftPanel.state.variant)&&("rightPanel"!==region||"sidebar"!==layout.rightPanel.state.variant)||handle.isVisible||null===handle.animation?fallback:"column"},getVisibleSections=(children,layout)=>Children.toArray(children).flatMap(child=>{if(!isValidElement(child)||child.type!==LayoutBottomBarItem||null==child.props.children||!1===child.props.children)return[];let{region,fallback="hide"}=child.props,placement=getBottomBarItemMode({region,fallback,layout});return"hide"===placement?[]:[{...child.props,placement,fallback}]}),shouldPreserveSplitColumnWidth=sections=>{let hasLeftFallback=sections.some(({region,fallback})=>"leftPanel"===region&&"remaining"===fallback),hasContentColumn=sections.some(({region,placement})=>"content"===region&&"column"===placement),hasSplitColumn=sections.some(({region,placement})=>"splitview"===region&&"column"===placement),hasRightFallback=sections.some(({region,fallback})=>"rightPanel"===region&&"remaining"===fallback);return hasLeftFallback&&hasContentColumn&&hasSplitColumn&&!hasRightFallback},getSharedRowCells=(sections,layout)=>{if(!sections.length)return[];let firstSection=sections[0],lastSection=sections[sections.length-1],hasRemainingActions=sections.some(({fallback})=>"remaining"===fallback),preserveSplitColumn=shouldPreserveSplitColumnWidth(sections),fillLeadingSpace="column"===firstSection.placement&&("content"===firstSection.region||"splitview"===firstSection.region)&&"column"!==layout.leftPanel.presentation,flexibleColumns={leftPanel:!1,content:hasRemainingActions,splitview:hasRemainingActions&&!preserveSplitColumn,rightPanel:!1},hasFlexibleColumn=sections.some(({region,placement})=>"column"===placement&&flexibleColumns[region]),needsFlexibleGap=hasRemainingActions&&!hasFlexibleColumn,rightActions=sections.find(({region})=>"rightPanel"===region);return[..."column"!==firstSection.placement||fillLeadingSpace?[]:[{kind:"leading-gap",region:firstSection.region}],...sections.flatMap((section,index)=>{let previousSection=sections[index-1];return[..."column"===section.placement&&previousSection?.placement==="column"?[{kind:"column-gap",region:section.region,previousRegion:previousSection.region}]:[],...needsFlexibleGap&&section===rightActions?[{kind:"flexible-gap"}]:[],{kind:"section",section,flexible:flexibleColumns[section.region],fillLeadingSpace:section===firstSection&&fillLeadingSpace&&!hasRemainingActions}]}),...!hasRemainingActions||preserveSplitColumn?[{kind:"trailing-gap",region:lastSection.region}]:[],...needsFlexibleGap&&!rightActions?[{kind:"flexible-gap"}]:[]]};export const getBottomBarLayout=(children,layout)=>{let sections=getVisibleSections(children,layout),sharedSections=PANEL_ORDER.flatMap(region=>sections.filter(section=>section.region===region&&"full"!==section.placement)),fullWidthSections=sections.filter(({placement})=>"full"===placement),sharedRowCount=+!!sharedSections.length,cells=getSharedRowCells(sharedSections,layout);return{cells,sections:[...cells.flatMap((cell,column)=>"section"===cell.kind?[{...cell.section,columnIndex:column,rowIndex:0}]:[]),...fullWidthSections.map((section,row)=>({...section,rowIndex:sharedRowCount+row}))],rowCount:sharedRowCount+fullWidthSections.length,hasRightPanel:sections.some(({region})=>"rightPanel"===region)}};
1
+ import{Children,isValidElement}from"react";import{PANEL_ORDER}from"../-constants";import{LayoutBottomBarItem}from"./LayoutBottomBarItem";let getBottomBarItemMode=({region,fallback,layout})=>{let handle=layout[region];return"column"===handle.presentation?"column":("leftPanel"!==region||"sidebar"!==layout.leftPanel.state.variant)&&("rightPanel"!==region||"sidebar"!==layout.rightPanel.state.variant)||handle.isVisible||null===handle.animation?fallback:"column"},getVisibleSections=(children,layout)=>Children.toArray(children).flatMap(child=>{if(!isValidElement(child)||child.type!==LayoutBottomBarItem||null==child.props.children||!1===child.props.children)return[];let{region,fallback="hide"}=child.props,placement=getBottomBarItemMode({region,fallback,layout});return"hide"===placement?[]:[{...child.props,placement,fallback}]}),shouldPreserveSplitColumnWidth=sections=>{let hasLeftFallback=sections.some(({region,fallback})=>"leftPanel"===region&&"remaining"===fallback),hasContentColumn=sections.some(({region,placement})=>"content"===region&&"column"===placement),hasSplitColumn=sections.some(({region,placement})=>"splitview"===region&&"column"===placement),hasRightFallback=sections.some(({region,fallback})=>"rightPanel"===region&&"remaining"===fallback);return hasLeftFallback&&hasContentColumn&&hasSplitColumn&&!hasRightFallback},getSharedRowCells=sections=>{if(!sections.length)return[];let firstSection=sections[0],lastSection=sections[sections.length-1],hasRemainingActions=sections.some(({fallback})=>"remaining"===fallback),preserveSplitColumn=shouldPreserveSplitColumnWidth(sections),flexibleColumns={leftPanel:!1,content:hasRemainingActions,splitview:hasRemainingActions&&!preserveSplitColumn,rightPanel:!1},hasFlexibleColumn=sections.some(({region,placement})=>"column"===placement&&flexibleColumns[region]),needsFlexibleGap=hasRemainingActions&&!hasFlexibleColumn,rightActions=sections.find(({region})=>"rightPanel"===region);return[..."column"===firstSection.placement?[{kind:"leading-gap",region:firstSection.region}]:[],...sections.flatMap((section,index)=>{let previousSection=sections[index-1];return[..."column"===section.placement&&previousSection?.placement==="column"?[{kind:"column-gap",region:section.region,previousRegion:previousSection.region}]:[],...needsFlexibleGap&&section===rightActions?[{kind:"flexible-gap"}]:[],{kind:"section",section,flexible:flexibleColumns[section.region]}]}),...!hasRemainingActions||preserveSplitColumn?[{kind:"trailing-gap",region:lastSection.region}]:[],...needsFlexibleGap&&!rightActions?[{kind:"flexible-gap"}]:[]]};export const getBottomBarLayout=({children,layout})=>{let sections=getVisibleSections(children,layout),sharedSections=PANEL_ORDER.flatMap(region=>sections.filter(section=>section.region===region&&"full"!==section.placement)),fullWidthSections=sections.filter(({placement})=>"full"===placement),sharedRowCount=+!!sharedSections.length,cells=getSharedRowCells(sharedSections);return{cells,sections:[...cells.flatMap((cell,column)=>"section"===cell.kind?[{...cell.section,columnIndex:column,rowIndex:0}]:[]),...fullWidthSections.map((section,row)=>({...section,rowIndex:sharedRowCount+row}))],rowCount:sharedRowCount+fullWidthSections.length,hasRightPanel:sections.some(({region})=>"rightPanel"===region)}};
@@ -8,7 +8,7 @@ export type LayoutVarHandle = {
8
8
  };
9
9
  /**
10
10
  * Register one layout CSS var; returns a stable imperative handle. The var is
11
- * removed on unmount, so it only exists while its producer is mounted. Call
11
+ * removed on unmount only if this producer still owns the latest write. Call
12
12
  * `.set()` from wherever the value is known — an effect (state-driven vars like
13
13
  * the subnav offset) or a ResizeObserver (measured vars) — so updates publish
14
14
  * straight to the single `<LayoutCssVars>` sink and never re-render the producer.
@@ -1 +1 @@
1
- import React,{createContext,useContext,useEffect,useMemo,useSyncExternalStore}from"react";import{Global}from"@emotion/react";let LayoutCssVarStoreContext=createContext(null);export const LayoutCssVarStoreProvider=LayoutCssVarStoreContext.Provider;let EMPTY_VARS={},NOOP_SUBSCRIBE=()=>()=>{};export const useLayoutVar=name=>{let store=useContext(LayoutCssVarStoreContext);return useEffect(()=>()=>store?.remove(name),[store,name]),useMemo(()=>({set:value=>""===value?store?.remove(name):store?.set(name,value),remove:()=>store?.remove(name)}),[store,name])};export function LayoutCssVars(){let store=useContext(LayoutCssVarStoreContext),vars=useSyncExternalStore(store?.subscribe??NOOP_SUBSCRIBE,store?store.getSnapshot:()=>EMPTY_VARS,()=>EMPTY_VARS);return React.createElement(Global,{styles:[{":root":vars}]})}
1
+ import React,{createContext,useContext,useEffect,useMemo,useSyncExternalStore}from"react";import{Global}from"@emotion/react";let LayoutCssVarStoreContext=createContext(null);export const LayoutCssVarStoreProvider=LayoutCssVarStoreContext.Provider;let EMPTY_VARS={},NOOP_SUBSCRIBE=()=>()=>{};export const useLayoutVar=name=>{let store=useContext(LayoutCssVarStoreContext),handle=useMemo(()=>{let owner=Symbol(name);return{set:value=>""===value?store?.remove(name,owner):store?.set({name,value,owner}),remove:()=>store?.remove(name,owner)}},[store,name]);return useEffect(()=>handle.remove,[handle]),handle};export function LayoutCssVars(){let store=useContext(LayoutCssVarStoreContext),vars=useSyncExternalStore(store?.subscribe??NOOP_SUBSCRIBE,store?store.getSnapshot:()=>EMPTY_VARS,()=>EMPTY_VARS);return React.createElement(Global,{styles:[{":root":vars}]})}
@@ -1,3 +1,8 @@
1
+ type LayoutCssVarWrite = {
2
+ name: string;
3
+ value: string;
4
+ owner: symbol;
5
+ };
1
6
  /**
2
7
  * Tiny pub/sub registry for the layout's CSS custom properties. Producers
3
8
  * publish a value by name (the component that owns the *why* — e.g. the NavBar
@@ -6,12 +11,14 @@
6
11
  * via the same `useSyncExternalStore` pattern.
7
12
  *
8
13
  * One name = one producer. The registry is keyed by name, so a second writer to
9
- * the same name last-wins; don't share a name across unrelated producers.
14
+ * the same name last-wins. Only that writer may remove it, so an old instance's
15
+ * delayed unmount cleanup cannot erase a replacement's value.
10
16
  */
11
17
  export type LayoutCssVarStore = {
12
18
  getSnapshot: () => Record<string, string>;
13
- set: (name: string, value: string) => void;
14
- remove: (name: string) => void;
19
+ set: (entry: LayoutCssVarWrite) => void;
20
+ remove: (name: string, owner: symbol) => void;
15
21
  subscribe: (listener: () => void) => () => void;
16
22
  };
17
23
  export declare function createLayoutCssVarStore(): LayoutCssVarStore;
24
+ export {};
@@ -1 +1 @@
1
- export function createLayoutCssVarStore(){let vars={},listeners=new Set,notify=()=>listeners.forEach(listener=>listener());return{getSnapshot:()=>vars,set:(name,value)=>{vars[name]!==value&&(vars={...vars,[name]:value},notify())},remove:name=>{if(!(name in vars))return;let next={...vars};delete next[name],vars=next,notify()},subscribe:listener=>(listeners.add(listener),()=>{listeners.delete(listener)})}}
1
+ export function createLayoutCssVarStore(){let vars={},owners=new Map,listeners=new Set,notify=()=>listeners.forEach(listener=>listener());return{getSnapshot:()=>vars,set:({name,value,owner})=>{owners.set(name,owner),vars[name]!==value&&(vars={...vars,[name]:value},notify())},remove:(name,owner)=>{if(owners.get(name)!==owner)return;owners.delete(name);let next={...vars};delete next[name],vars=next,notify()},subscribe:listener=>(listeners.add(listener),()=>{listeners.delete(listener)})}}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@amboss/design-system",
3
- "version": "4.9.4-canary.2",
3
+ "version": "4.9.4-canary.4",
4
4
  "description": "the design system for AMBOSS products",
5
5
  "author": "AMBOSS",
6
6
  "license": "ISC",
@@ -1,14 +0,0 @@
1
- import type { CSSObject, Theme } from "@emotion/react";
2
- import type { BottomBarCell } from "./getBottomBarLayout";
3
- type BottomBarOuterSpaceStylesOptions = {
4
- theme: Theme;
5
- hasRightPanel: boolean;
6
- hasSplitColumns: boolean;
7
- cells: BottomBarCell[];
8
- };
9
- /**
10
- * Fills the side margins left by the content/split max-width in the first row.
11
- * Region gaps stay transparent; action sizing and placement are unaffected.
12
- */
13
- export declare const getBottomBarOuterSpaceStyles: ({ theme, hasRightPanel, hasSplitColumns, cells, }: BottomBarOuterSpaceStylesOptions) => CSSObject;
14
- export {};
@@ -1 +0,0 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),Object.defineProperty(exports,"getBottomBarOuterSpaceStyles",{enumerable:!0,get:function(){return getBottomBarOuterSpaceStyles}});const _constants=require("../-constants"),getRegionEnd=region=>`calc(var(${_constants.PANEL_START_VAR[region]}, 0px) + var(${_constants.PANEL_WIDTH_VAR[region]}, 0px))`,hasColumnActions=(cells,region)=>cells.some(cell=>"section"===cell.kind&&cell.section.region===region&&"column"===cell.section.placement),getBottomBarOuterSpaceStyles=({theme,hasRightPanel,hasSplitColumns,cells})=>{let leftPanelEnd=getRegionEnd("leftPanel"),splitEnd=getRegionEnd("splitview"),rightPanelWidth=`var(${_constants.PANEL_WIDTH_VAR.rightPanel}, 0px)`,rightPanelGap=`min(${rightPanelWidth}, ${theme.variables.size.spacing.xxs})`,contentAreaEnd=hasRightPanel?`calc(100% - ${rightPanelWidth} - ${rightPanelGap})`:"100%";return{"&::before, &::after":{position:"absolute",top:0,height:theme.variables.layout.bottomBar.contentHeight.default,backgroundColor:theme.values.color.background.primary.default,pointerEvents:"none",zIndex:-1},"&::before":{content:hasSplitColumns&&hasColumnActions(cells,"content")?'""':"none",left:leftPanelEnd,width:`max(0px, calc(var(${_constants.PANEL_START_VAR.content}, 0px) - ${leftPanelEnd}))`},"&::after":{content:hasSplitColumns&&hasColumnActions(cells,"splitview")?'""':"none",left:splitEnd,width:`max(0px, calc(${contentAreaEnd} - ${splitEnd}))`}}};
@@ -1,14 +0,0 @@
1
- import type { CSSObject, Theme } from "@emotion/react";
2
- import type { BottomBarCell } from "./getBottomBarLayout";
3
- type BottomBarOuterSpaceStylesOptions = {
4
- theme: Theme;
5
- hasRightPanel: boolean;
6
- hasSplitColumns: boolean;
7
- cells: BottomBarCell[];
8
- };
9
- /**
10
- * Fills the side margins left by the content/split max-width in the first row.
11
- * Region gaps stay transparent; action sizing and placement are unaffected.
12
- */
13
- export declare const getBottomBarOuterSpaceStyles: ({ theme, hasRightPanel, hasSplitColumns, cells, }: BottomBarOuterSpaceStylesOptions) => CSSObject;
14
- export {};
@@ -1 +0,0 @@
1
- import{PANEL_START_VAR,PANEL_WIDTH_VAR}from"../-constants";let getRegionEnd=region=>`calc(var(${PANEL_START_VAR[region]}, 0px) + var(${PANEL_WIDTH_VAR[region]}, 0px))`,hasColumnActions=(cells,region)=>cells.some(cell=>"section"===cell.kind&&cell.section.region===region&&"column"===cell.section.placement);export const getBottomBarOuterSpaceStyles=({theme,hasRightPanel,hasSplitColumns,cells})=>{let leftPanelEnd=getRegionEnd("leftPanel"),splitEnd=getRegionEnd("splitview"),rightPanelWidth=`var(${PANEL_WIDTH_VAR.rightPanel}, 0px)`,rightPanelGap=`min(${rightPanelWidth}, ${theme.variables.size.spacing.xxs})`,contentAreaEnd=hasRightPanel?`calc(100% - ${rightPanelWidth} - ${rightPanelGap})`:"100%";return{"&::before, &::after":{position:"absolute",top:0,height:theme.variables.layout.bottomBar.contentHeight.default,backgroundColor:theme.values.color.background.primary.default,pointerEvents:"none",zIndex:-1},"&::before":{content:hasSplitColumns&&hasColumnActions(cells,"content")?'""':"none",left:leftPanelEnd,width:`max(0px, calc(var(${PANEL_START_VAR.content}, 0px) - ${leftPanelEnd}))`},"&::after":{content:hasSplitColumns&&hasColumnActions(cells,"splitview")?'""':"none",left:splitEnd,width:`max(0px, calc(${contentAreaEnd} - ${splitEnd}))`}}};