@amboss/design-system 4.8.1 → 4.8.2-canary.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/build/cjs/components/Internal/Panel/Panel.d.ts +7 -3
- package/build/cjs/components/Internal/Panel/Panel.js +1 -1
- package/build/cjs/components/Internal/PanelHeader/PanelHeader.d.ts +12 -4
- package/build/cjs/components/Internal/PanelHeader/PanelHeader.js +1 -1
- package/build/cjs/components/Internal/Sandwich/-types.d.ts +5 -0
- package/build/cjs/components/Internal/Sandwich/Sandwich.d.ts +1 -1
- package/build/cjs/components/Internal/Sandwich/Sandwich.js +1 -1
- package/build/cjs/components/Layout/-constants.d.ts +4 -0
- package/build/cjs/components/Layout/-constants.js +1 -1
- package/build/cjs/components/Layout/-types.d.ts +62 -14
- package/build/cjs/components/Layout/Layout.d.ts +4 -0
- package/build/cjs/components/Layout/Layout.js +1 -1
- package/build/cjs/components/Layout/LeftNavBar/LeftNavBar.d.ts +17 -0
- package/build/cjs/components/Layout/LeftNavBar/LeftNavBar.js +1 -0
- package/build/cjs/components/Layout/LeftNavBar/LeftNavBarFooter.d.ts +7 -0
- package/build/cjs/components/Layout/LeftNavBar/LeftNavBarFooter.js +1 -0
- package/build/cjs/components/Layout/LeftPanel/LeftBarLayers.d.ts +44 -0
- package/build/cjs/components/Layout/LeftPanel/LeftBarLayers.js +1 -0
- package/build/cjs/components/Layout/LeftPanel/LeftBarToggle.d.ts +14 -0
- package/build/cjs/components/Layout/LeftPanel/LeftBarToggle.js +1 -0
- package/build/cjs/components/Layout/LeftPanel/LeftPanel.d.ts +2 -2
- package/build/cjs/components/Layout/LeftPanel/LeftPanel.js +1 -1
- package/build/cjs/components/Layout/LeftPanel/LeftPanelDocked.d.ts +12 -7
- package/build/cjs/components/Layout/LeftPanel/LeftPanelDocked.js +1 -1
- package/build/cjs/components/Layout/LeftPanel/LeftPanelDrawer.js +1 -1
- package/build/cjs/components/Layout/LeftPanel/LeftPanelFooter.js +1 -1
- package/build/cjs/components/Layout/LeftPanel/LeftPanelHeader.d.ts +5 -3
- package/build/cjs/components/Layout/LeftPanel/LeftPanelHeader.js +1 -1
- package/build/cjs/components/Layout/LeftPanel/LeftPanelOffcanvas.d.ts +28 -0
- package/build/cjs/components/Layout/LeftPanel/LeftPanelOffcanvas.js +1 -0
- package/build/cjs/components/Layout/LeftPanel/useLeftBarContext.d.ts +11 -0
- package/build/cjs/components/Layout/LeftPanel/useLeftBarContext.js +1 -0
- package/build/cjs/components/Layout/LeftPanel/useLeftPanelCollapseContext.d.ts +11 -0
- package/build/cjs/components/Layout/LeftPanel/useLeftPanelCollapseContext.js +1 -0
- package/build/cjs/components/Layout/reducer.js +1 -1
- package/build/cjs/components/Layout/registry.d.ts +11 -0
- package/build/cjs/components/Layout/registry.js +1 -1
- package/build/cjs/components/Layout/rules.js +1 -1
- package/build/cjs/components/Layout/useLayout.js +1 -1
- package/build/cjs/components/Layout/useLayoutRules.js +1 -1
- package/build/cjs/components/Layout/useLeftPanelId.d.ts +6 -0
- package/build/cjs/components/Layout/useLeftPanelId.js +1 -0
- package/build/cjs/components/Layout/usePanelDockedSlide.d.ts +11 -6
- package/build/cjs/components/Layout/usePanelDockedSlide.js +1 -1
- package/build/cjs/shared/mixins/getLeftPanelFadeStyles.d.ts +19 -0
- package/build/cjs/shared/mixins/getLeftPanelFadeStyles.js +1 -0
- package/build/cjs/shared/mixins/index.d.ts +1 -0
- package/build/cjs/shared/mixins/index.js +1 -1
- package/build/cjs/web-tokens/_sizes.json +64 -54
- package/build/cjs/web-tokens/visualConfig.d.ts +8 -0
- package/build/cjs/web-tokens/visualConfig.js +1 -1
- package/build/esm/components/Internal/Panel/Panel.d.ts +7 -3
- package/build/esm/components/Internal/Panel/Panel.js +1 -1
- package/build/esm/components/Internal/PanelHeader/PanelHeader.d.ts +12 -4
- package/build/esm/components/Internal/PanelHeader/PanelHeader.js +1 -1
- package/build/esm/components/Internal/Sandwich/-types.d.ts +5 -0
- package/build/esm/components/Internal/Sandwich/Sandwich.d.ts +1 -1
- package/build/esm/components/Internal/Sandwich/Sandwich.js +1 -1
- package/build/esm/components/Layout/-constants.d.ts +4 -0
- package/build/esm/components/Layout/-constants.js +1 -1
- package/build/esm/components/Layout/-types.d.ts +62 -14
- package/build/esm/components/Layout/Layout.d.ts +4 -0
- package/build/esm/components/Layout/Layout.js +1 -1
- package/build/esm/components/Layout/LeftNavBar/LeftNavBar.d.ts +17 -0
- package/build/esm/components/Layout/LeftNavBar/LeftNavBar.js +1 -0
- package/build/esm/components/Layout/LeftNavBar/LeftNavBarFooter.d.ts +7 -0
- package/build/esm/components/Layout/LeftNavBar/LeftNavBarFooter.js +1 -0
- package/build/esm/components/Layout/LeftPanel/LeftBarLayers.d.ts +44 -0
- package/build/esm/components/Layout/LeftPanel/LeftBarLayers.js +1 -0
- package/build/esm/components/Layout/LeftPanel/LeftBarToggle.d.ts +14 -0
- package/build/esm/components/Layout/LeftPanel/LeftBarToggle.js +1 -0
- package/build/esm/components/Layout/LeftPanel/LeftPanel.d.ts +2 -2
- package/build/esm/components/Layout/LeftPanel/LeftPanel.js +1 -1
- package/build/esm/components/Layout/LeftPanel/LeftPanelDocked.d.ts +12 -7
- package/build/esm/components/Layout/LeftPanel/LeftPanelDocked.js +1 -1
- package/build/esm/components/Layout/LeftPanel/LeftPanelDrawer.js +1 -1
- package/build/esm/components/Layout/LeftPanel/LeftPanelFooter.js +1 -1
- package/build/esm/components/Layout/LeftPanel/LeftPanelHeader.d.ts +5 -3
- package/build/esm/components/Layout/LeftPanel/LeftPanelHeader.js +1 -1
- package/build/esm/components/Layout/LeftPanel/LeftPanelOffcanvas.d.ts +28 -0
- package/build/esm/components/Layout/LeftPanel/LeftPanelOffcanvas.js +1 -0
- package/build/esm/components/Layout/LeftPanel/useLeftBarContext.d.ts +11 -0
- package/build/esm/components/Layout/LeftPanel/useLeftBarContext.js +1 -0
- package/build/esm/components/Layout/LeftPanel/useLeftPanelCollapseContext.d.ts +11 -0
- package/build/esm/components/Layout/LeftPanel/useLeftPanelCollapseContext.js +1 -0
- package/build/esm/components/Layout/reducer.js +1 -1
- package/build/esm/components/Layout/registry.d.ts +11 -0
- package/build/esm/components/Layout/registry.js +1 -1
- package/build/esm/components/Layout/rules.js +1 -1
- package/build/esm/components/Layout/useLayout.js +1 -1
- package/build/esm/components/Layout/useLayoutRules.js +1 -1
- package/build/esm/components/Layout/useLeftPanelId.d.ts +6 -0
- package/build/esm/components/Layout/useLeftPanelId.js +1 -0
- package/build/esm/components/Layout/usePanelDockedSlide.d.ts +11 -6
- package/build/esm/components/Layout/usePanelDockedSlide.js +1 -1
- package/build/esm/shared/mixins/getLeftPanelFadeStyles.d.ts +19 -0
- package/build/esm/shared/mixins/getLeftPanelFadeStyles.js +1 -0
- package/build/esm/shared/mixins/index.d.ts +1 -0
- package/build/esm/shared/mixins/index.js +1 -1
- package/build/esm/web-tokens/_sizes.json +64 -54
- package/build/esm/web-tokens/visualConfig.d.ts +8 -0
- package/build/esm/web-tokens/visualConfig.js +1 -1
- package/build/scss/_dark.scss +1 -1
- package/build/scss/_variables.scss +3 -0
- package/package.json +1 -1
- package/build/cjs/components/Layout/PanelSlideBody.d.ts +0 -18
- package/build/cjs/components/Layout/PanelSlideBody.js +0 -1
- package/build/esm/components/Layout/PanelSlideBody.d.ts +0 -18
- package/build/esm/components/Layout/PanelSlideBody.js +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
import React,{useCallback,useEffect,useMemo,useRef,useState}from"react";import styled from"@emotion/styled";import{Panel}from"../Internal/Panel/Panel";import{LayoutFloat}from"../Internal/LayoutFloat/LayoutFloat";import{useBreakpoints}from"../../shared/useBreakpoints";import{PAGE_BOTTOM_BAR_INSET,PANEL_ORDER,PANEL_WIDTH_VAR,Slot}from"./-constants";import{useLayoutPanelsEnabled,useLayoutPersistence,useLayoutStore}from"./context";import{MobileSplitStackContext}from"./Split/MobileSplitView/useMobileSplitStack";import{useMobileSplitViewEnabled}from"./Split/MobileSplitView/useMobileSplitView";import{LayoutProvider}from"./LayoutProvider";import{Content}from"./Content/Content";import{RightPanel}from"./RightPanel/RightPanel";import{RightPanelHeader}from"./RightPanel/RightPanelHeader";import{RightPanelFooter}from"./RightPanel/RightPanelFooter";import{LeftPanel}from"./LeftPanel/LeftPanel";import{LeftPanelHeader}from"./LeftPanel/LeftPanelHeader";import{LeftPanelFooter}from"./LeftPanel/LeftPanelFooter";import{Split}from"./Split/Split";import{SplitHeader}from"./Split/SplitHeader";import{SplitFooter}from"./Split/SplitFooter";import{LayoutPortalContext,PanelRegistryContext,PanelDeclarationsContext,PanelPresenceContext,PanelAnimationContext}from"./registry";import{usePortalTargets}from"./usePortalTargets";import{LayoutFloatDragProvider}from"../Internal/LayoutFloat/LayoutFloatDragProvider";import{useLayoutVar}from"./LayoutCssVars";import{useLayout}from"./useLayout";import{useLayoutRules}from"./useLayoutRules";import{DEFAULT_LAYOUT_RULES}from"./rules";let resizableFromState=slotState=>"sidePanel"===slotState.kind?slotState.resizable:void 0,useGlobalCssVariables=slotHosts=>{let leftPanelWidthCssVar=useLayoutVar(PANEL_WIDTH_VAR.leftPanel),contentWidthCssVar=useLayoutVar(PANEL_WIDTH_VAR.content),rightPanelWidthCssVar=useLayoutVar(PANEL_WIDTH_VAR.rightPanel);useEffect(()=>{let targets=[[Slot.leftPanel,leftPanelWidthCssVar],[Slot.content,contentWidthCssVar],[Slot.rightPanel,rightPanelWidthCssVar]],observers=[];return targets.forEach(([slot,handle])=>{let node=slotHosts[slot]??null;if(!node)return void handle.set("0px");let publishNodeWidth=()=>handle.set(`${node.getBoundingClientRect().width}px`);if(publishNodeWidth(),"undefined"==typeof ResizeObserver)return;let observer=new ResizeObserver(publishNodeWidth);observer.observe(node),observers.push(observer)}),()=>observers.forEach(observer=>observer.disconnect())},[leftPanelWidthCssVar,contentWidthCssVar,rightPanelWidthCssVar,slotHosts])},StyledLayout=styled("div",{target:"e1kuzc310",label:"StyledLayout"})({position:"relative",height:"100%",width:"100%"}),StyledPanelHost=styled("div",{target:"e1kuzc311",label:"StyledPanelHost"})({position:"relative",height:"100%",width:"100%"});export const PANEL_HOST_DS_ID="PanelHost";let StyledContentColumn=styled("div",{shouldForwardProp:prop=>"isSplitOpen"!==prop,target:"e1kuzc312",label:"StyledContentColumn"})(({isSplitOpen,theme})=>({display:"flex",height:`calc(100% - ${PAGE_BOTTOM_BAR_INSET})`,width:"100%",...isSplitOpen&&{maxWidth:theme.variables.layout.split.maxWidth.default,marginInline:"auto",gap:theme.variables.size.spacing.xxs}})),StyledContentColumnHalf=styled("div",{target:"e1kuzc313",label:"StyledContentColumnHalf"})({position:"relative",height:"100%",flex:"1 1 0",minWidth:0}),StyledMobileSplitStackHost=styled("div",{target:"e1kuzc314",label:"StyledMobileSplitStackHost"})({position:"absolute",top:0,left:0,right:0,bottom:PAGE_BOTTOM_BAR_INSET,overflow:"hidden",pointerEvents:"none"}),isPanelPresent=({slot,declared,present,isShown})=>!!declared[slot]&&(isShown(slot)||present[slot]),defaultSizeFor=({slot,panel,panelState})=>slot===Slot.content?void 0:panel?.defaultSize!==void 0?panel.defaultSize:panel?.resizable!==!1?panelState.size:void 0,childFor=(slot,contentColumn,slotHostRefs)=>slot===Slot.content?contentColumn:React.createElement(StyledPanelHost,{"data-ds-id":"PanelHost",ref:slotHostRefs[slot]});export const Layout=function({children,persistenceKey,storage,rules=DEFAULT_LAYOUT_RULES,additionalRulesData}){let[declared,setDeclared]=useState({}),layout=useLayout(),{state:layoutState,...panelCallbacks}=layout;useLayoutRules({layout,declared,rules,additionalData:additionalRulesData});let{dispatch}=useLayoutStore(),persistence=useLayoutPersistence(),resolvedKey=persistenceKey??persistence.persistenceKey,resolvedStorage=storage??persistence.storage,{isMobile}=useBreakpoints(),showMobileSplitStack=useMobileSplitViewEnabled(),[mobileSplitStackHost,setMobileSplitStackHost]=useState(null),[splitCount,setSplitCount]=useState(0),registerSplit=useCallback(()=>(setSplitCount(count=>count+1),()=>setSplitCount(count=>count-1)),[]),mobileSplitStack=useMemo(()=>({host:mobileSplitStackHost,isSplitPresent:splitCount>0,registerSplit}),[mobileSplitStackHost,splitCount,registerSplit]),panelsEnabled=useLayoutPanelsEnabled(),rightPanelVariant=layoutState[Slot.rightPanel].variant??declared[Slot.rightPanel]?.variant??"sidebar",isRightPanelFloating=!0===panelsEnabled&&!isMobile&&"float"===rightPanelVariant,isShown=slot=>layoutState[slot].visible&&!(slot===Slot.rightPanel&&(isRightPanelFloating||isMobile)),[present,setPresent]=useState({}),presence=useMemo(()=>({setPresent:(slot,isPresent)=>setPresent(prev=>prev[slot]===isPresent?prev:{...prev,[slot]:isPresent})}),[]),panelHandles=useRef({}),panelElements=useRef({}),resizeSuppressed=useRef({}),animationControl=useMemo(()=>({setHandle:(slot,handle)=>{panelHandles.current[slot]=handle},getHandle:slot=>panelHandles.current[slot]??null,setElement:(slot,element)=>{panelElements.current[slot]=element},getElement:slot=>panelElements.current[slot]??null,setResizeSuppressed:(slot,suppressed)=>{resizeSuppressed.current[slot]=suppressed}}),[]),panelRefCallbacks=useMemo(()=>{let handleCallbacks=new Map,elementCallbacks=new Map;return{handleFor:id=>{let callback=handleCallbacks.get(id);return callback||(callback=handle=>animationControl.setHandle(id,handle),handleCallbacks.set(id,callback)),callback},elementFor:id=>{let callback=elementCallbacks.get(id);return callback||(callback=element=>animationControl.setElement(id,element),elementCallbacks.set(id,callback)),callback}}},[animationControl]),shouldSuppressLayoutCallback=useCallback(()=>Object.values(resizeSuppressed.current).some(Boolean),[]),registry=useMemo(()=>({register:(slot,reg)=>setDeclared(prev=>({...prev,[slot]:reg})),unregister:slot=>setDeclared(prev=>{if(!(slot in prev))return prev;let next={...prev};return delete next[slot],next})}),[]),{portalTargets,slotHosts,slotHostRefs,floatHostRef}=usePortalTargets({slots:PANEL_ORDER,floatableSlot:Slot.rightPanel,isFloating:isRightPanelFloating});useGlobalCssVariables(slotHosts);let rowSlots=PANEL_ORDER.filter(slot=>slot!==Slot.splitview),declaredSlots=rowSlots.filter(slot=>declared[slot]),isSolo=declaredSlots.length<=1,soloSlot=declaredSlots[0],isSplitOpen=isPanelPresent({slot:Slot.splitview,declared,present,isShown})&&isPanelPresent({slot:Slot.content,declared,present,isShown}),contentColumn=React.createElement(StyledContentColumn,{isSplitOpen:isSplitOpen},React.createElement(StyledContentColumnHalf,{ref:slotHostRefs[Slot.content]}),isSplitOpen&&React.createElement(StyledContentColumnHalf,{ref:slotHostRefs[Slot.splitview]})),panelItems=rowSlots.filter(slot=>isPanelPresent({slot,declared,present,isShown})).map(slot=>{let panel=declared[slot],panelState=layoutState[slot];return{id:slot,child:childFor(slot,contentColumn,slotHostRefs),defaultSize:defaultSizeFor({slot,panel,panelState}),minSize:panel?.minSize??panelState.minSize,maxSize:panel?.maxSize??panelState.maxSize,collapsible:slot!==Slot.content&&(panel?.collapsible??!0),lockWidthOnWindowResize:panel?.lockWidthOnWindowResize,resizable:panel?.resizable??resizableFromState(panelState)}}),soloHost=soloSlot&&isShown(soloSlot)?childFor(soloSlot,contentColumn,slotHostRefs):null,panelGroup=panelItems.length>0?React.createElement(Panel,{key:resolvedKey,panels:panelItems,persistenceKey:resolvedKey,storage:resolvedStorage,onResize:(id,size)=>dispatch({type:"resize",slot:id,size}),onCollapse:id=>panelCallbacks[id].hide(),panelHandleFor:panelRefCallbacks.handleFor,panelElementFor:panelRefCallbacks.elementFor,shouldSuppressLayoutCallback:shouldSuppressLayoutCallback}):null;return React.createElement(PanelRegistryContext.Provider,{value:registry},React.createElement(PanelDeclarationsContext.Provider,{value:declared},React.createElement(PanelPresenceContext.Provider,{value:presence},React.createElement(PanelAnimationContext.Provider,{value:animationControl},React.createElement(LayoutPortalContext.Provider,{value:portalTargets},React.createElement(LayoutFloatDragProvider,null,React.createElement(MobileSplitStackContext.Provider,{value:mobileSplitStack},React.createElement(StyledLayout,{"data-ds-id":"Layout"},isSolo?soloHost:panelGroup,isRightPanelFloating&&layoutState[Slot.rightPanel].visible&&React.createElement(LayoutFloat,{hostRef:floatHostRef}),children,showMobileSplitStack&&React.createElement(StyledMobileSplitStackHost,{ref:setMobileSplitStackHost})))))))))};Layout.Provider=LayoutProvider,Layout.LeftPanel=LeftPanel,Layout.LeftPanelHeader=LeftPanelHeader,Layout.LeftPanelFooter=LeftPanelFooter,Layout.RightPanel=RightPanel,Layout.RightPanelHeader=RightPanelHeader,Layout.RightPanelFooter=RightPanelFooter,Layout.Content=Content,Layout.Split=Split,Layout.SplitHeader=SplitHeader,Layout.SplitFooter=SplitFooter;
|
|
1
|
+
import React,{useCallback,useEffect,useMemo,useRef,useState}from"react";import styled from"@emotion/styled";import{Panel}from"../Internal/Panel/Panel";import{LayoutFloat}from"../Internal/LayoutFloat/LayoutFloat";import{useBreakpoints}from"../../shared/useBreakpoints";import{PAGE_BOTTOM_BAR_INSET,PANEL_ORDER,PANEL_WIDTH_VAR,Slot}from"./-constants";import{useLayoutPanelsEnabled,useLayoutPersistence,useLayoutStore}from"./context";import{MobileSplitStackContext}from"./Split/MobileSplitView/useMobileSplitStack";import{useMobileSplitViewEnabled}from"./Split/MobileSplitView/useMobileSplitView";import{LayoutProvider}from"./LayoutProvider";import{Content}from"./Content/Content";import{RightPanel}from"./RightPanel/RightPanel";import{RightPanelHeader}from"./RightPanel/RightPanelHeader";import{RightPanelFooter}from"./RightPanel/RightPanelFooter";import{LeftPanel}from"./LeftPanel/LeftPanel";import{LeftPanelHeader}from"./LeftPanel/LeftPanelHeader";import{LeftPanelFooter}from"./LeftPanel/LeftPanelFooter";import{LeftNavBar}from"./LeftNavBar/LeftNavBar";import{LeftNavBarFooter}from"./LeftNavBar/LeftNavBarFooter";import{Split}from"./Split/Split";import{SplitHeader}from"./Split/SplitHeader";import{SplitFooter}from"./Split/SplitFooter";import{LayoutPortalContext,PanelRegistryContext,PanelDeclarationsContext,PanelPresenceContext,PanelAnimationContext,PanelRowContext}from"./registry";import{usePortalTargets}from"./usePortalTargets";import{LayoutFloatDragProvider}from"../Internal/LayoutFloat/LayoutFloatDragProvider";import{useLayoutVar}from"./LayoutCssVars";import{useLayout}from"./useLayout";import{useLayoutRules}from"./useLayoutRules";import{DEFAULT_LAYOUT_RULES}from"./rules";let resizableFromState=slotState=>"sidePanel"===slotState.kind?slotState.resizable:void 0,useGlobalCssVariables=slotHosts=>{let leftPanelWidthCssVar=useLayoutVar(PANEL_WIDTH_VAR.leftPanel),contentWidthCssVar=useLayoutVar(PANEL_WIDTH_VAR.content),rightPanelWidthCssVar=useLayoutVar(PANEL_WIDTH_VAR.rightPanel);useEffect(()=>{let targets=[[Slot.leftPanel,leftPanelWidthCssVar],[Slot.content,contentWidthCssVar],[Slot.rightPanel,rightPanelWidthCssVar]],observers=[];return targets.forEach(([slot,handle])=>{let node=slotHosts[slot]??null;if(!node)return void handle.set("0px");let publishNodeWidth=()=>handle.set(`${node.getBoundingClientRect().width}px`);if(publishNodeWidth(),"undefined"==typeof ResizeObserver)return;let observer=new ResizeObserver(publishNodeWidth);observer.observe(node),observers.push(observer)}),()=>observers.forEach(observer=>observer.disconnect())},[leftPanelWidthCssVar,contentWidthCssVar,rightPanelWidthCssVar,slotHosts])},StyledLayout=styled("div",{target:"e1no219g0",label:"StyledLayout"})({position:"relative",height:"100%",width:"100%"}),StyledPanelRow=styled("div",{target:"e1no219g1",label:"StyledPanelRow"})(({theme,hasOffcanvasLeftBar})=>({height:"100%",boxSizing:"border-box",...hasOffcanvasLeftBar&&{paddingLeft:theme.variables.size.dimension.leftNavBar.width}})),StyledPanelHost=styled("div",{target:"e1no219g2",label:"StyledPanelHost"})({position:"relative",height:"100%",width:"100%"});export const PANEL_HOST_DS_ID="PanelHost";let StyledContentColumn=styled("div",{shouldForwardProp:prop=>"isSplitOpen"!==prop,target:"e1no219g3",label:"StyledContentColumn"})(({isSplitOpen,theme})=>({display:"flex",height:`calc(100% - ${PAGE_BOTTOM_BAR_INSET})`,width:"100%",...isSplitOpen&&{maxWidth:theme.variables.layout.split.maxWidth.default,marginInline:"auto",gap:theme.variables.size.spacing.xxs}})),StyledContentColumnHalf=styled("div",{target:"e1no219g4",label:"StyledContentColumnHalf"})({position:"relative",height:"100%",flex:"1 1 0",minWidth:0}),StyledMobileSplitStackHost=styled("div",{target:"e1no219g5",label:"StyledMobileSplitStackHost"})({position:"absolute",top:0,left:0,right:0,bottom:PAGE_BOTTOM_BAR_INSET,overflow:"hidden",pointerEvents:"none"}),isPanelPresent=({slot,declared,present,isShown})=>!!declared[slot]&&(isShown(slot)||present[slot]),defaultSizeFor=({slot,panel,panelState})=>slot===Slot.content?void 0:panel?.defaultSize!==void 0?panel.defaultSize:panel?.resizable!==!1?panelState.size:void 0,childFor=(slot,contentColumn,slotHostRefs)=>slot===Slot.content?contentColumn:React.createElement(StyledPanelHost,{"data-ds-id":"PanelHost",ref:slotHostRefs[slot]});export const Layout=function({children,persistenceKey,storage,rules=DEFAULT_LAYOUT_RULES,additionalRulesData}){let[declared,setDeclared]=useState({}),layout=useLayout(),{state:layoutState,...panelCallbacks}=layout;useLayoutRules({layout,declared,rules,additionalData:additionalRulesData});let{dispatch}=useLayoutStore(),persistence=useLayoutPersistence(),resolvedKey=persistenceKey??persistence.persistenceKey,resolvedStorage=storage??persistence.storage,{isMobile}=useBreakpoints(),showMobileSplitStack=useMobileSplitViewEnabled(),[mobileSplitStackHost,setMobileSplitStackHost]=useState(null),[splitCount,setSplitCount]=useState(0),registerSplit=useCallback(()=>(setSplitCount(count=>count+1),()=>setSplitCount(count=>count-1)),[]),mobileSplitStack=useMemo(()=>({host:mobileSplitStackHost,isSplitPresent:splitCount>0,registerSplit}),[mobileSplitStackHost,splitCount,registerSplit]),panelsEnabled=useLayoutPanelsEnabled(),rightPanelVariant=layoutState[Slot.rightPanel].variant??declared[Slot.rightPanel]?.variant??"sidebar",isRightPanelFloating=!0===panelsEnabled&&!isMobile&&"float"===rightPanelVariant,hasOffcanvasLeftBar=!!declared[Slot.leftPanel]&&"offcanvas"===layoutState[Slot.leftPanel].variant,isShown=slot=>layoutState[slot].visible&&!(slot===Slot.rightPanel&&(isRightPanelFloating||isMobile))&&!(slot===Slot.leftPanel&&hasOffcanvasLeftBar),[present,setPresent]=useState({}),presence=useMemo(()=>({setPresent:(slot,isPresent)=>setPresent(prev=>prev[slot]===isPresent?prev:{...prev,[slot]:isPresent})}),[]),panelHandles=useRef({}),panelElements=useRef({}),resizeSuppressed=useRef({}),animationControl=useMemo(()=>({setHandle:(slot,handle)=>{panelHandles.current[slot]=handle},getHandle:slot=>panelHandles.current[slot]??null,setElement:(slot,element)=>{panelElements.current[slot]=element},getElement:slot=>panelElements.current[slot]??null,setResizeSuppressed:(slot,suppressed)=>{resizeSuppressed.current[slot]=suppressed}}),[]),panelRefCallbacks=useMemo(()=>{let handleCallbacks=new Map,elementCallbacks=new Map;return{handleFor:id=>{let callback=handleCallbacks.get(id);return callback||(callback=handle=>animationControl.setHandle(id,handle),handleCallbacks.set(id,callback)),callback},elementFor:id=>{let callback=elementCallbacks.get(id);return callback||(callback=element=>animationControl.setElement(id,element),elementCallbacks.set(id,callback)),callback}}},[animationControl]),shouldSuppressLayoutCallback=useCallback(()=>Object.values(resizeSuppressed.current).some(Boolean),[]),registry=useMemo(()=>({register:(slot,reg)=>setDeclared(prev=>({...prev,[slot]:reg})),unregister:slot=>setDeclared(prev=>{if(!(slot in prev))return prev;let next={...prev};return delete next[slot],next})}),[]),{portalTargets,slotHosts,slotHostRefs,floatHostRef}=usePortalTargets({slots:PANEL_ORDER,floatableSlot:Slot.rightPanel,isFloating:isRightPanelFloating});useGlobalCssVariables(slotHosts);let rowSlots=PANEL_ORDER.filter(slot=>slot!==Slot.splitview),declaredSlots=rowSlots.filter(slot=>declared[slot]),isSolo=declaredSlots.length<=1,soloSlot=declaredSlots[0],isSplitOpen=isPanelPresent({slot:Slot.splitview,declared,present,isShown})&&isPanelPresent({slot:Slot.content,declared,present,isShown}),contentColumn=React.createElement(StyledContentColumn,{isSplitOpen:isSplitOpen},React.createElement(StyledContentColumnHalf,{ref:slotHostRefs[Slot.content]}),isSplitOpen&&React.createElement(StyledContentColumnHalf,{ref:slotHostRefs[Slot.splitview]})),panelItems=rowSlots.filter(slot=>isPanelPresent({slot,declared,present,isShown})).map(slot=>{let panel=declared[slot],panelState=layoutState[slot];return{id:slot,child:childFor(slot,contentColumn,slotHostRefs),defaultSize:defaultSizeFor({slot,panel,panelState}),minSize:panel?.minSize??panelState.minSize,maxSize:panel?.maxSize??panelState.maxSize,collapsible:slot!==Slot.content&&(panel?.collapsible??!0),lockWidthOnWindowResize:panel?.lockWidthOnWindowResize,resizable:panel?.resizable??resizableFromState(panelState)}}),rowKey=panelItems.map(item=>item.id).join(","),soloHost=soloSlot&&isShown(soloSlot)?childFor(soloSlot,contentColumn,slotHostRefs):null,panelGroup=panelItems.length>0?React.createElement(Panel,{key:resolvedKey,panels:panelItems,persistenceKey:resolvedKey,storage:resolvedStorage,onResize:(id,size)=>{isShown(id)&&dispatch({type:"resize",slot:id,size:declared[id]?.lockWidthOnWindowResize?Math.round(size.inPixels):`${size.asPercentage}%`})},onCollapse:id=>panelCallbacks[id].hide(),panelHandleFor:panelRefCallbacks.handleFor,panelElementFor:panelRefCallbacks.elementFor,shouldSuppressLayoutCallback:shouldSuppressLayoutCallback}):null;return React.createElement(PanelRegistryContext.Provider,{value:registry},React.createElement(PanelDeclarationsContext.Provider,{value:declared},React.createElement(PanelPresenceContext.Provider,{value:presence},React.createElement(PanelAnimationContext.Provider,{value:animationControl},React.createElement(PanelRowContext.Provider,{value:rowKey},React.createElement(LayoutPortalContext.Provider,{value:portalTargets},React.createElement(LayoutFloatDragProvider,null,React.createElement(MobileSplitStackContext.Provider,{value:mobileSplitStack},React.createElement(StyledLayout,{"data-ds-id":"Layout"},React.createElement(StyledPanelRow,{hasOffcanvasLeftBar:hasOffcanvasLeftBar},isSolo?soloHost:panelGroup),isRightPanelFloating&&layoutState[Slot.rightPanel].visible&&React.createElement(LayoutFloat,{hostRef:floatHostRef}),children,showMobileSplitStack&&React.createElement(StyledMobileSplitStackHost,{ref:setMobileSplitStackHost}))))))))))};Layout.Provider=LayoutProvider,Layout.LeftPanel=LeftPanel,Layout.LeftNavBar=LeftNavBar,Layout.LeftNavBarFooter=LeftNavBarFooter,Layout.LeftPanelHeader=LeftPanelHeader,Layout.LeftPanelFooter=LeftPanelFooter,Layout.RightPanel=RightPanel,Layout.RightPanelHeader=RightPanelHeader,Layout.RightPanelFooter=RightPanelFooter,Layout.Content=Content,Layout.Split=Split,Layout.SplitHeader=SplitHeader,Layout.SplitFooter=SplitFooter;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import type { LeftNavBarProps } from "../-types";
|
|
3
|
+
/**
|
|
4
|
+
* What `Layout.LeftPanel` shows in the left bar beneath the button that opens
|
|
5
|
+
* it, for panels whose left bar carries something other than the panel's own
|
|
6
|
+
* leading column - persistent destinations beside an article outline, say.
|
|
7
|
+
* Author it among the panel's children; it renders into the layer behind the
|
|
8
|
+
* panel, so opening widens that one column rather than adding a second box.
|
|
9
|
+
*
|
|
10
|
+
* Optional: the bar keeps its open button either way. This only fills the strip
|
|
11
|
+
* below it, on its own terms - scrolling, and sticking a
|
|
12
|
+
* `Layout.LeftNavBarFooter` to the bottom.
|
|
13
|
+
*
|
|
14
|
+
* Renders nothing where the panel has no left bar, so the mobile drawer shows
|
|
15
|
+
* the panel's own content alone even though the left bar is authored among it.
|
|
16
|
+
*/
|
|
17
|
+
export declare function LeftNavBar({ children, "data-e2e-test-id": dataE2eTestId, }: LeftNavBarProps): React.ReactElement | null;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import React from"react";import{createPortal}from"react-dom";import styled from"@emotion/styled";import{Sandwich}from"../../Internal/Sandwich/Sandwich";import{useLeftBarContext}from"../LeftPanel/useLeftBarContext";let StyledNavBarFrame=styled("div",{target:"e1e9dsmx0",label:"StyledNavBarFrame"})({height:"100%"});export function LeftNavBar({children,"data-e2e-test-id":dataE2eTestId}){let{slotNode}=useLeftBarContext();return slotNode?createPortal(React.createElement(StyledNavBarFrame,{"data-ds-id":"LeftNavBar","data-e2e-test-id":dataE2eTestId},React.createElement(Sandwich,{hideScrollbar:!0},children)),slotNode):null}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import type { LeftNavBarFooterProps } from "../-types";
|
|
3
|
+
/**
|
|
4
|
+
* Optional sticky footer for `Layout.LeftNavBar` - place it among the left bar's
|
|
5
|
+
* children; it sticks to the bottom while the rest of the content scrolls.
|
|
6
|
+
*/
|
|
7
|
+
export declare function LeftNavBarFooter({ children, "data-e2e-test-id": dataE2eTestId, }: LeftNavBarFooterProps): React.ReactElement;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import React from"react";import{Sandwich}from"../../Internal/Sandwich/Sandwich";export function LeftNavBarFooter({children,"data-e2e-test-id":dataE2eTestId}){return React.createElement(Sandwich.Footer,{"data-e2e-test-id":dataE2eTestId},children)}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import type { CSSObject, Theme } from "@emotion/react";
|
|
3
|
+
import type { ForwardedScrollProps, LeftPanelSlotProps } from "../-types";
|
|
4
|
+
/**
|
|
5
|
+
* The box the layers live in: one surface, one divider, and a clip. Shared by
|
|
6
|
+
* the two presentations that carry a left bar - the in-row column and the offcanvas
|
|
7
|
+
* overlay - which differ only in how they are positioned and sized.
|
|
8
|
+
*
|
|
9
|
+
* The surface is painted here, once and constantly, so nothing new appears
|
|
10
|
+
* mid-collapse: were each layer to paint its own, fading the panel's would only
|
|
11
|
+
* uncover the left bar's, identical and full-width, and the dissolve would reveal
|
|
12
|
+
* nothing.
|
|
13
|
+
*
|
|
14
|
+
* The divider is overlaid on the trailing edge rather than declared as a border,
|
|
15
|
+
* so it costs the box no width - the left bar's leading column and the header's
|
|
16
|
+
* trailing button are placed against the full width, and a border would put them
|
|
17
|
+
* half a pixel out.
|
|
18
|
+
*/
|
|
19
|
+
export declare const getLeftBarColumnStyles: (theme: Theme) => CSSObject;
|
|
20
|
+
/**
|
|
21
|
+
* Where the box's top edge sits: below a sticky subnav, by the offset the subnav
|
|
22
|
+
* publishes, and at the host's top when no subnav is mounted. The edge moves
|
|
23
|
+
* with the subnav, so the transition is the one the subnav slides with, and
|
|
24
|
+
* the two travel as one. `RightPanelDocked` tracks the same var the same way,
|
|
25
|
+
* so the two side panels stay level.
|
|
26
|
+
*/
|
|
27
|
+
export declare const LEFT_BAR_TOP_INSET: string;
|
|
28
|
+
export declare const getLeftBarTopTransition: (theme: Theme) => string;
|
|
29
|
+
export type LeftBarLayersProps = ForwardedScrollProps & {
|
|
30
|
+
children: React.ReactNode;
|
|
31
|
+
isVisible: boolean;
|
|
32
|
+
/** Width the panel's content holds on to while the box is narrower. */
|
|
33
|
+
openWidth: string;
|
|
34
|
+
slotProps: LeftPanelSlotProps;
|
|
35
|
+
"aria-label"?: string;
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* The left bar and the panel, stacked in one box. Whichever of the two is showing,
|
|
39
|
+
* the box's width alone does the animating: content and footer hold `openWidth`
|
|
40
|
+
* and are clipped as it narrows, so nothing in them moves, while the header is
|
|
41
|
+
* left to narrow with the box - which walks its trailing control down into the
|
|
42
|
+
* left bar.
|
|
43
|
+
*/
|
|
44
|
+
export declare const LeftBarLayers: React.FC<LeftBarLayersProps>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import React,{useEffect,useMemo,useRef,useState}from"react";import styled from"@emotion/styled";import{useDocument}from"../../../shared/useDocument";import{getLeftPanelFadeStyles}from"../../../shared/mixins";import{SUBNAV_OFFSET_VAR}from"../-constants";import{Sandwich}from"../../Internal/Sandwich/Sandwich";import{useLeftPanelId}from"../useLeftPanelId";import{LeftPanelCollapseProvider}from"./useLeftPanelCollapseContext";import{LeftBarProvider}from"./useLeftBarContext";import{LeftBarToggle}from"./LeftBarToggle";export const getLeftBarColumnStyles=theme=>({overflow:"hidden",backgroundColor:theme.values.color.background.primary.default,"&::after":{content:'""',position:"absolute",top:0,bottom:0,right:0,width:1,backgroundColor:theme.values.color.border.secondary.default}});export const LEFT_BAR_TOP_INSET=`var(${SUBNAV_OFFSET_VAR}, 0px)`;export const getLeftBarTopTransition=theme=>{let{duration,timingFunction}=theme.variables.animation.navSlide.open;return`top ${duration} ${timingFunction}`};let StyledLeftBarLayer=styled("div",{target:"e1gwfcgt0",label:"StyledLeftBarLayer"})(({isPanelOpen})=>({position:"absolute",inset:0,display:"flex",flexDirection:"column",visibility:isPanelOpen?"hidden":"visible"})),StyledNavBarSlot=styled("div",{target:"e1gwfcgt1",label:"StyledNavBarSlot"})({flex:"1 1 auto",minHeight:0}),StyledPanelLayer=styled("div",{target:"e1gwfcgt2",label:"StyledPanelLayer"})(({theme,isPanelOpen})=>{let{duration}=theme.variables.animation.navSlide.collapse;return{position:"absolute",inset:0,overflow:"hidden",visibility:isPanelOpen?"visible":"hidden",transition:isPanelOpen?"none":`visibility 0s linear ${duration}`,"@media (prefers-reduced-motion: reduce)":{transition:"none"}}}),StyledFadingContent=styled("div",{target:"e1gwfcgt3",label:"StyledFadingContent"})(({theme,isFaded,fixedContentWidth})=>({display:"flex",flexDirection:"column",flex:"1 0 auto",minWidth:fixedContentWidth,...getLeftPanelFadeStyles({theme,isFaded})})),handOverFocus=({document,from,to})=>{from&&to&&from.contains(document.activeElement)&&to.focus()};export const LeftBarLayers=({children,isVisible,openWidth,slotProps,"aria-label":ariaLabel,scrollContainerRef,onScroll})=>{let leftPanelId=useLeftPanelId(),document=useDocument(),leftBarLayerRef=useRef(null),panelLayerRef=useRef(null),toggleRef=useRef(null),[leftBarSlotNode,setLeftBarSlotNode]=useState(null),leftBarSlot=useMemo(()=>({slotNode:leftBarSlotNode}),[leftBarSlotNode]),isContentFaded=!isVisible,collapseState=useMemo(()=>({isContentFaded,fixedContentWidth:openWidth}),[isContentFaded,openWidth]),wasVisible=useRef(isVisible);return useEffect(()=>{isVisible!==wasVisible.current&&(wasVisible.current=isVisible,handOverFocus({document,from:isVisible?leftBarLayerRef.current:panelLayerRef.current,to:isVisible?panelLayerRef.current:toggleRef.current}))},[isVisible,document]),React.createElement(LeftBarProvider,{value:leftBarSlot},React.createElement(StyledLeftBarLayer,{isPanelOpen:isVisible,ref:leftBarLayerRef},React.createElement(LeftBarToggle,{...slotProps.toggleButton,buttonRef:toggleRef}),React.createElement(StyledNavBarSlot,{ref:setLeftBarSlotNode})),React.createElement(StyledPanelLayer,{ref:panelLayerRef,isPanelOpen:isVisible,id:leftPanelId,tabIndex:-1,role:ariaLabel?"region":void 0,"aria-label":ariaLabel},React.createElement(Sandwich,{hideScrollbar:!0,scrollRef:scrollContainerRef,onScroll:onScroll},React.createElement(LeftPanelCollapseProvider,{value:collapseState},React.createElement(StyledFadingContent,{isFaded:isContentFaded,fixedContentWidth:openWidth},children)))))};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import type { LeftPanelSlotProps } from "../-types";
|
|
3
|
+
export type LeftBarToggleProps = LeftPanelSlotProps["toggleButton"] & {
|
|
4
|
+
/** Handed out so the layer above can put focus here when the panel closes -
|
|
5
|
+
* this is the control that replaces the one the panel is taking away. */
|
|
6
|
+
buttonRef?: React.Ref<HTMLButtonElement>;
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* The one control the left bar always carries: the button that opens the panel
|
|
10
|
+
* back up. It belongs to the bar rather than to `Layout.LeftNavBar` - which only
|
|
11
|
+
* adds content beneath it - because a panel that authored no nav bar would
|
|
12
|
+
* otherwise close to a strip with no way back out of it.
|
|
13
|
+
*/
|
|
14
|
+
export declare function LeftBarToggle({ "aria-label": ariaLabel, "data-e2e-test-id": dataE2eTestId, buttonRef, }: LeftBarToggleProps): React.ReactElement;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import React from"react";import{Box}from"../../Box/Box";import{PictogramButton}from"../../PictogramButton/PictogramButton";import{Slot}from"../-constants";import{useLayout}from"../useLayout";import{useLeftPanelId}from"../useLeftPanelId";export function LeftBarToggle({"aria-label":ariaLabel,"data-e2e-test-id":dataE2eTestId,buttonRef}){let{show,isVisible}=useLayout()[Slot.leftPanel],leftPanelId=useLeftPanelId();return React.createElement(Box,{space:"s",vSpace:"xs"},React.createElement(PictogramButton,{ref:buttonRef,icon:"open-sidebar-left",size:"s",onClick:show,"aria-label":ariaLabel,"data-e2e-test-id":dataE2eTestId,"aria-controls":leftPanelId,"aria-expanded":isVisible}))}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import type { LeftPanelProps } from "../-types";
|
|
3
3
|
/**
|
|
4
|
-
* Left side panel. Picks its presentation by breakpoint: an in-flow
|
|
5
|
-
*
|
|
4
|
+
* Left side panel. Picks its presentation by breakpoint: an in-flow column on
|
|
5
|
+
* desktop ({@link LeftPanelDocked}) and a modal left-edge drawer on
|
|
6
6
|
* mobile ({@link LeftPanelDrawer}). Both are driven by the same `leftPanel`
|
|
7
7
|
* layout state, so `useLayout()` controls it the same way at any width.
|
|
8
8
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import React
|
|
1
|
+
import React,{useId}from"react";import{useTheme}from"@emotion/react";import{Slot}from"../-constants";import{useVisibleChange}from"../registry";import{useLayout}from"../useLayout";import{useCanRenderPanel}from"../context";import{LeftPanelIdContext}from"../useLeftPanelId";import{LeftPanelDocked}from"./LeftPanelDocked";import{LeftPanelDrawer}from"./LeftPanelDrawer";import{LeftPanelOffcanvas}from"./LeftPanelOffcanvas";export const LeftPanel=({children,slotProps,collapsible=!0,onVisibleChange,"aria-label":ariaLabel,scrollContainerRef,onScroll})=>{let{isVisible,hide,state}=useLayout()[Slot.leftPanel],canRender=useCanRenderPanel(),leftPanelId=useId(),openWidth=useTheme().variables.layout.leftPanel.width.open;if(useVisibleChange(isVisible,onVisibleChange),!canRender)return null;let drawer=React.createElement(LeftPanelDrawer,{isVisible:isVisible,hide:hide,"aria-label":ariaLabel,scrollContainerRef:scrollContainerRef,onScroll:onScroll},children),offcanvas=React.createElement(LeftPanelOffcanvas,{slotProps:slotProps,isVisible:isVisible,hide:hide,openWidth:openWidth,"aria-label":ariaLabel,scrollContainerRef:scrollContainerRef,onScroll:onScroll},children),docked=React.createElement(LeftPanelDocked,{slotProps:slotProps,"aria-label":ariaLabel,defaultSize:parseFloat(openWidth),collapsible:collapsible,scrollContainerRef:scrollContainerRef,onScroll:onScroll},children);return React.createElement(LeftPanelIdContext.Provider,{value:leftPanelId},{drawer,offcanvas,sidebar:docked}[state.variant])};
|
|
@@ -1,21 +1,26 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import type { ForwardedScrollProps,
|
|
2
|
+
import type { ForwardedScrollProps, LeftPanelSlotProps } from "../-types";
|
|
3
3
|
export type LeftPanelDockedProps = ForwardedScrollProps & {
|
|
4
4
|
children: React.ReactNode;
|
|
5
|
+
slotProps: LeftPanelSlotProps;
|
|
5
6
|
"aria-label"?: string;
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
maxSize?: Size;
|
|
7
|
+
/** Pixel width the column widens to. */
|
|
8
|
+
defaultSize: number;
|
|
9
9
|
collapsible?: boolean;
|
|
10
|
-
resizable?: boolean;
|
|
11
10
|
};
|
|
12
11
|
/**
|
|
13
12
|
* Docked (desktop) left panel. Declares the `leftPanel` slot and portals its
|
|
14
|
-
* content into the Group's host - an in-flow
|
|
13
|
+
* content into the Group's host - an in-flow column whose width
|
|
15
14
|
* slides open/closed via {@link usePanelDockedSlide} (when collapsible). Content
|
|
16
|
-
* lives in
|
|
15
|
+
* lives in {@link LeftBarLayers} so `Layout.LeftPanelHeader` /
|
|
17
16
|
* `Layout.LeftPanelFooter` children stick to the edges. The mobile presentation
|
|
18
17
|
* lives in {@link LeftPanelDrawer}; `LeftPanel` picks between the two by
|
|
19
18
|
* breakpoint.
|
|
19
|
+
*
|
|
20
|
+
* The column never leaves the row: it rests at the left bar's width and widens
|
|
21
|
+
* to `defaultSize`. Content and footer hold the open width and are clipped, so
|
|
22
|
+
* nothing in them moves - the panel simply shows less of itself. The header is
|
|
23
|
+
* left to narrow with the column, which walks a control at its trailing edge
|
|
24
|
+
* down into the left bar.
|
|
20
25
|
*/
|
|
21
26
|
export declare const LeftPanelDocked: React.FC<LeftPanelDockedProps>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import React from"react";import{Slot}from"../-constants";import{useLayoutPortal}from"../registry";import{usePanelDockedSlide}from"../usePanelDockedSlide";import{
|
|
1
|
+
import React from"react";import styled from"@emotion/styled";import{useTheme}from"@emotion/react";import{PAGE_BOTTOM_BAR_INSET,Slot}from"../-constants";import{useLayoutPortal}from"../registry";import{usePanelDockedSlide}from"../usePanelDockedSlide";import{LEFT_BAR_TOP_INSET,LeftBarLayers,getLeftBarColumnStyles,getLeftBarTopTransition}from"./LeftBarLayers";import{useLayout}from"../useLayout";let StyledLeftBarColumn=styled("div",{target:"e1crtgka0",label:"StyledLeftBarColumn"})(({theme})=>({position:"absolute",left:0,right:0,top:LEFT_BAR_TOP_INSET,bottom:PAGE_BOTTOM_BAR_INSET,transition:getLeftBarTopTransition(theme),"@media (prefers-reduced-motion: reduce)":{transition:"none"},...getLeftBarColumnStyles(theme)}));export const LeftPanelDocked=({children,slotProps,"aria-label":ariaLabel,defaultSize,collapsible=!0,scrollContainerRef,onScroll})=>{let theme=useTheme(),{isVisible}=useLayout()[Slot.leftPanel],{fixedWidth}=usePanelDockedSlide({slot:Slot.leftPanel,defaultSize,collapsible,resizable:!1,lockWidthOnWindowResize:!0,collapsedSize:parseFloat(theme.variables.size.dimension.leftNavBar.width)});return useLayoutPortal(Slot.leftPanel,React.createElement(StyledLeftBarColumn,null,React.createElement(LeftBarLayers,{isVisible:isVisible,slotProps:slotProps,openWidth:`${fixedWidth??defaultSize}px`,"aria-label":ariaLabel,scrollContainerRef:scrollContainerRef,onScroll:onScroll},children)))};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import React from"react";import styled from"@emotion/styled";import{Drawer}from"../../Internal/Drawer/Drawer";import{PanelContainer}from"../PanelContainer";let StyledLeftPanelBody=styled("div",{target:"
|
|
1
|
+
import React from"react";import styled from"@emotion/styled";import{Drawer}from"../../Internal/Drawer/Drawer";import{PanelContainer}from"../PanelContainer";import{useLeftPanelId}from"../useLeftPanelId";let StyledLeftPanelBody=styled("div",{target:"e158aetq0",label:"StyledLeftPanelBody"})({width:"80vw",height:"100dvh"});export const LeftPanelDrawer=({children,isVisible,hide,"aria-label":ariaLabel,scrollContainerRef,onScroll})=>{let leftPanelId=useLeftPanelId();return React.createElement(Drawer,{isVisible:isVisible,positionX:"left",handleClose:hide,"aria-label":ariaLabel},React.createElement(StyledLeftPanelBody,null,React.createElement(PanelContainer,{id:leftPanelId,scrollContainerRef:scrollContainerRef,onScroll:onScroll},children)))};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import React from"react";import{Sandwich}from"../../Internal/Sandwich/Sandwich";export function LeftPanelFooter({children,"data-e2e-test-id":dataE2eTestId}){return React.createElement(Sandwich.Footer,{"data-e2e-test-id":dataE2eTestId},children)}
|
|
1
|
+
import React from"react";import styled from"@emotion/styled";import{getLeftPanelFadeStyles}from"../../../shared/mixins";import{Sandwich}from"../../Internal/Sandwich/Sandwich";import{useLeftPanelCollapseContext}from"./useLeftPanelCollapseContext";let StyledFadingFooter=styled("div",{target:"eqmipoc0",label:"StyledFadingFooter"})(({theme,isFaded,fixedContentWidth})=>({minWidth:fixedContentWidth,...getLeftPanelFadeStyles({theme,isFaded})}));export function LeftPanelFooter({children,"data-e2e-test-id":dataE2eTestId}){let{isContentFaded,fixedContentWidth}=useLeftPanelCollapseContext();return React.createElement(Sandwich.Footer,{"data-e2e-test-id":dataE2eTestId},React.createElement(StyledFadingFooter,{isFaded:isContentFaded,fixedContentWidth:fixedContentWidth},children))}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import type { LeftPanelHeaderProps } from "../-types";
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* Header for the left panel. Place among `Layout.LeftPanel`'s children; it
|
|
5
|
+
* sticks to the top while the rest of the content scrolls. Content is a left
|
|
6
|
+
* slot, an optional title, a right slot, and beneath them whatever is passed as
|
|
7
|
+
* `children`.
|
|
6
8
|
*/
|
|
7
|
-
export declare function LeftPanelHeader({ leftSlot, rightSlot, "data-e2e-test-id": dataE2eTestId, }: LeftPanelHeaderProps): React.ReactElement;
|
|
9
|
+
export declare function LeftPanelHeader({ leftSlot, title, rightSlot, children, "data-e2e-test-id": dataE2eTestId, }: LeftPanelHeaderProps): React.ReactElement;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import React from"react";import{Sandwich}from"../../Internal/Sandwich/Sandwich";import{PanelHeader}from"../../Internal/PanelHeader/PanelHeader";export function LeftPanelHeader({leftSlot,rightSlot,"data-e2e-test-id":dataE2eTestId}){return React.createElement(Sandwich.Header,{"data-e2e-test-id":dataE2eTestId},React.createElement(PanelHeader,{leftSlot:leftSlot,rightSlot:rightSlot}))}
|
|
1
|
+
import React from"react";import styled from"@emotion/styled";import{getLeftPanelFadeStyles}from"../../../shared/mixins/getLeftPanelFadeStyles";import{Sandwich}from"../../Internal/Sandwich/Sandwich";import{PanelHeader}from"../../Internal/PanelHeader/PanelHeader";import{useLeftPanelCollapseContext}from"./useLeftPanelCollapseContext";let StyledHeaderStrip=styled("div",{target:"e183h5z80",label:"StyledHeaderStrip"})(({theme,isFaded,fixedContentWidth})=>({minWidth:fixedContentWidth,...getLeftPanelFadeStyles({theme,isFaded})}));export function LeftPanelHeader({leftSlot,title,rightSlot,children,"data-e2e-test-id":dataE2eTestId}){let{isContentFaded,fixedContentWidth}=useLeftPanelCollapseContext();return React.createElement(Sandwich.Header,{"data-e2e-test-id":dataE2eTestId},React.createElement(PanelHeader,{leftSlot:leftSlot,title:title,rightSlot:rightSlot,isContentFaded:isContentFaded}),children&&React.createElement(StyledHeaderStrip,{isFaded:isContentFaded,fixedContentWidth:fixedContentWidth},children))}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import type { ForwardedScrollProps, LeftPanelSlotProps } from "../-types";
|
|
3
|
+
export type LeftPanelOffcanvasProps = ForwardedScrollProps & {
|
|
4
|
+
children: React.ReactNode;
|
|
5
|
+
slotProps: LeftPanelSlotProps;
|
|
6
|
+
isVisible: boolean;
|
|
7
|
+
hide: () => void;
|
|
8
|
+
openWidth: string;
|
|
9
|
+
"aria-label"?: string;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Left panel as a non-modal overlay: a drawer without the dialog. Used when the
|
|
13
|
+
* docked budget has no column left but the panel should stay reachable - it
|
|
14
|
+
* opens over the row instead of taking a column from it, and instead of being
|
|
15
|
+
* hidden outright. The left bar stays on screen throughout; only the mobile drawer
|
|
16
|
+
* gives it up.
|
|
17
|
+
*
|
|
18
|
+
* Deliberately not a {@link Drawer}: a Drawer traps focus, claims `aria-modal`
|
|
19
|
+
* and covers the viewport with a click-catching layer. Here the page behind
|
|
20
|
+
* stays live and usable, so the panel is a plain `region` (named by
|
|
21
|
+
* `aria-label`) that happens to be layered - nothing about it is modal.
|
|
22
|
+
*
|
|
23
|
+
* It still dismisses like something laid over the page, because that is what it
|
|
24
|
+
* is: Escape and a click beyond its edge both close it back to its left bar. Only
|
|
25
|
+
* while it is open - closed, it is just the left bar, and the left bar is not something
|
|
26
|
+
* to dismiss.
|
|
27
|
+
*/
|
|
28
|
+
export declare const LeftPanelOffcanvas: React.FC<LeftPanelOffcanvasProps>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import React,{useRef}from"react";import styled from"@emotion/styled";import{useTheme}from"@emotion/react";import{LEFT_BAR_TOP_INSET,LeftBarLayers,getLeftBarColumnStyles,getLeftBarTopTransition}from"./LeftBarLayers";import{PAGE_BOTTOM_BAR_INSET,Slot}from"../-constants";import{useDeclarePanel}from"../registry";import{useOnEscapePress}from"../../../shared/useOnEscapePress";import{useOutsideClick}from"../../../shared/useOutsideClick";let getOffcanvasBoxStyles=(theme,{isVisible,leftBarWidth,openWidth})=>({position:"absolute",left:0,top:LEFT_BAR_TOP_INSET,bottom:PAGE_BOTTOM_BAR_INSET,zIndex:1,width:isVisible?openWidth:leftBarWidth}),StyledOffcanvasShadow=styled("div",{target:"elm45s90",label:"StyledOffcanvasShadow"})(({theme,...box})=>{let{duration,timingFunction}=theme.variables.animation.navSlide.collapse;return{...getOffcanvasBoxStyles(theme,box),pointerEvents:"none",boxShadow:theme.values.elevation[2],opacity:box.isVisible?theme.variables.opacity.visible:theme.variables.opacity.hidden,transition:[`width ${duration} ${timingFunction}`,`opacity ${duration} ${timingFunction}`,getLeftBarTopTransition(theme)].join(", "),"@media (prefers-reduced-motion: reduce)":{transition:"none"}}}),StyledOffcanvasColumn=styled("div",{target:"elm45s91",label:"StyledOffcanvasColumn"})(({theme,...box})=>{let{duration,timingFunction}=theme.variables.animation.navSlide.collapse;return{...getOffcanvasBoxStyles(theme,box),transition:[`width ${duration} ${timingFunction}`,getLeftBarTopTransition(theme)].join(", "),"@media (prefers-reduced-motion: reduce)":{transition:"none"},...getLeftBarColumnStyles(theme)}});export const LeftPanelOffcanvas=({children,slotProps,isVisible,hide,openWidth,"aria-label":ariaLabel,scrollContainerRef,onScroll})=>{let theme=useTheme();useDeclarePanel(Slot.leftPanel,{});let columnRef=useRef(null);useOnEscapePress(event=>{isVisible&&(event.preventDefault(),hide())},[isVisible,hide]),useOutsideClick(columnRef,hide,isVisible);let box={isVisible,leftBarWidth:theme.variables.size.dimension.leftNavBar.width,openWidth};return React.createElement(React.Fragment,null,React.createElement(StyledOffcanvasShadow,{...box,"aria-hidden":!0}),React.createElement(StyledOffcanvasColumn,{...box,ref:columnRef},React.createElement(LeftBarLayers,{isVisible:isVisible,slotProps:slotProps,openWidth:openWidth,"aria-label":ariaLabel,scrollContainerRef:scrollContainerRef,onScroll:onScroll},children)))};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export type LeftBarSlot = {
|
|
2
|
+
/** Static host the left bar's content portals into. Null until the layer
|
|
3
|
+
* behind the panel has mounted, and never provided at all by the
|
|
4
|
+
* presentations that carry no left bar - which is how `Layout.LeftNavBar`
|
|
5
|
+
* knows to render nothing on mobile, where the drawer shows the panel's own
|
|
6
|
+
* content alone. */
|
|
7
|
+
slotNode: HTMLElement | null;
|
|
8
|
+
};
|
|
9
|
+
export declare const LeftBarProvider: React.Provider<LeftBarSlot>;
|
|
10
|
+
/** The left bar slot behind the left panel, if this presentation has one. */
|
|
11
|
+
export declare const useLeftBarContext: () => LeftBarSlot;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{createContext,useContext}from"react";let LeftBarContext=createContext({slotNode:null});export const LeftBarProvider=LeftBarContext.Provider;export const useLeftBarContext=()=>useContext(LeftBarContext);
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/** How the left panel's parts have to behave while its column narrows to a left bar. */
|
|
2
|
+
export type LeftPanelCollapseState = {
|
|
3
|
+
/** The content is dissolving into the left bar beneath it. */
|
|
4
|
+
isContentFaded: boolean;
|
|
5
|
+
/** Width the content is held at while the column narrows around it, clipped
|
|
6
|
+
* at the column's edge so nothing inside reflows on the way down. */
|
|
7
|
+
fixedContentWidth?: string;
|
|
8
|
+
};
|
|
9
|
+
export declare const LeftPanelCollapseProvider: React.Provider<LeftPanelCollapseState>;
|
|
10
|
+
/** How the left panel's parts have to behave while its column narrows. */
|
|
11
|
+
export declare const useLeftPanelCollapseContext: () => LeftPanelCollapseState;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{createContext,useContext}from"react";let LeftPanelCollapseContext=createContext({isContentFaded:!1});export const LeftPanelCollapseProvider=LeftPanelCollapseContext.Provider;export const useLeftPanelCollapseContext=()=>useContext(LeftPanelCollapseContext);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
function sidePanelFields(config={}){return{kind:"sidePanel",visible:config.defaultVisible??!0,collapsible:config.collapsible??!0,resizable:config.resizable??!0,size:config.defaultSize,minSize:config.minSize,maxSize:config.maxSize}}function panelState(config={}){return{kind:"panel",visible:config.defaultVisible??!0,size:config.defaultSize,minSize:config.minSize,maxSize:config.maxSize}}export function createInitialState(config={}){return{leftPanel:{...sidePanelFields({resizable:!1
|
|
1
|
+
function sidePanelFields(config={}){return{kind:"sidePanel",visible:config.defaultVisible??!0,collapsible:config.collapsible??!0,resizable:config.resizable??!0,size:config.defaultSize,minSize:config.minSize,maxSize:config.maxSize}}function panelState(config={}){return{kind:"panel",visible:config.defaultVisible??!0,size:config.defaultSize,minSize:config.minSize,maxSize:config.maxSize}}export function createInitialState(config={}){return{leftPanel:{...sidePanelFields({...config.leftPanel,resizable:!1}),variant:config.leftPanel?.variant},rightPanel:{...sidePanelFields({defaultVisible:!1,...config.rightPanel}),variant:config.rightPanel?.variant},content:panelState(config.content),splitview:panelState({defaultVisible:!1,...config.splitview})}}export const layoutReducer=(state,action,initial)=>{switch(action.type){case"setVisible":{let slot=state[action.slot];if(slot.visible===action.visible)return state;return{...state,[action.slot]:{...slot,visible:action.visible}}}case"setVariant":{let panel=state[action.panel];if(panel.variant===action.variant)return state;return{...state,[action.panel]:{...panel,variant:action.variant}}}case"resize":{let slot=state[action.slot];if(slot.size===action.size)return state;return{...state,[action.slot]:{...slot,size:action.size}}}case"reset":if(!initial)return state;if(!action.slot)return initial;if(state[action.slot]===initial[action.slot])return state;return{...state,[action.slot]:initial[action.slot]};default:return state}};
|
|
@@ -40,6 +40,17 @@ export declare const PanelRegistryContext: React.Context<PanelRegistry>;
|
|
|
40
40
|
export declare function useDeclarePanel(slot: SlotKey, reg: PanelReg): void;
|
|
41
41
|
export type PanelDeclarations = Partial<Record<SlotKey, PanelReg>>;
|
|
42
42
|
export declare const PanelDeclarationsContext: React.Context<Partial<Record<"content" | "leftPanel" | "splitview" | "rightPanel", PanelReg>>>;
|
|
43
|
+
/**
|
|
44
|
+
* The ids of the columns in the resizable row, in order, joined with commas.
|
|
45
|
+
* Changes when a column joins or leaves the row, and only then. A column that
|
|
46
|
+
* has to hold a width of its own across such a change - the left bar column,
|
|
47
|
+
* which react-resizable-panels would otherwise put back at whatever width it
|
|
48
|
+
* had the last time the same set of columns was on screen - re-checks its rest
|
|
49
|
+
* against it.
|
|
50
|
+
*/
|
|
51
|
+
export declare const PanelRowContext: React.Context<string>;
|
|
52
|
+
/** The row's current column set, as a stable key. Empty outside a Layout. */
|
|
53
|
+
export declare const usePanelRow: () => string;
|
|
43
54
|
/**
|
|
44
55
|
* Keeps an animating-out panel in the resizable row while its exit plays - the
|
|
45
56
|
* Group would otherwise drop the column the instant it's hidden. The panel
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createContext,useContext,useEffect,useLayoutEffect,useRef}from"react";import{createPortal}from"react-dom";import{Slot}from"./-constants";import{useLayoutPanelsEnabled}from"./context";export const LayoutPortalContext=createContext({});export function useLayoutPortal(slot,children){let slotNode=useContext(LayoutPortalContext)[slot]??null;return slotNode?createPortal(children,slotNode):null}export const PanelRegistryContext=createContext(null);export function useDeclarePanel(slot,reg){let registry=useContext(PanelRegistryContext),declarationEnabled=!0===useLayoutPanelsEnabled()||slot===Slot.content,{defaultSize,minSize,maxSize,collapsible,resizable,lockWidthOnWindowResize,variant}=reg;useLayoutEffect(()=>{if(registry&&declarationEnabled)return registry.register(slot,{defaultSize,minSize,maxSize,collapsible,resizable,lockWidthOnWindowResize,variant}),()=>registry.unregister(slot)},[registry,declarationEnabled,slot,defaultSize,minSize,maxSize,collapsible,resizable,lockWidthOnWindowResize,variant])}export const PanelDeclarationsContext=createContext({});export const PanelPresenceContext=createContext(null);export function usePanelPresence(slot,isPresent){let presence=useContext(PanelPresenceContext);useLayoutEffect(()=>{if(presence)return presence.setPresent(slot,isPresent),()=>presence.setPresent(slot,!1)},[presence,slot,isPresent])}export const PanelAnimationContext=createContext(null);export function usePanelAnimationControl(){return useContext(PanelAnimationContext)}export function useRunCallbackOnValueChange(value,onChange){let prev=useRef(value);useEffect(()=>{prev.current!==value&&(prev.current=value,onChange?.(value))},[value,onChange])}export function useVisibleChange(visible,onChange){useRunCallbackOnValueChange(visible,onChange)}
|
|
1
|
+
import{createContext,useContext,useEffect,useLayoutEffect,useRef}from"react";import{createPortal}from"react-dom";import{Slot}from"./-constants";import{useLayoutPanelsEnabled}from"./context";export const LayoutPortalContext=createContext({});export function useLayoutPortal(slot,children){let slotNode=useContext(LayoutPortalContext)[slot]??null;return slotNode?createPortal(children,slotNode):null}export const PanelRegistryContext=createContext(null);export function useDeclarePanel(slot,reg){let registry=useContext(PanelRegistryContext),declarationEnabled=!0===useLayoutPanelsEnabled()||slot===Slot.content,{defaultSize,minSize,maxSize,collapsible,resizable,lockWidthOnWindowResize,variant}=reg;useLayoutEffect(()=>{if(registry&&declarationEnabled)return registry.register(slot,{defaultSize,minSize,maxSize,collapsible,resizable,lockWidthOnWindowResize,variant}),()=>registry.unregister(slot)},[registry,declarationEnabled,slot,defaultSize,minSize,maxSize,collapsible,resizable,lockWidthOnWindowResize,variant])}export const PanelDeclarationsContext=createContext({});export const PanelRowContext=createContext("");export const usePanelRow=()=>useContext(PanelRowContext);export const PanelPresenceContext=createContext(null);export function usePanelPresence(slot,isPresent){let presence=useContext(PanelPresenceContext);useLayoutEffect(()=>{if(presence)return presence.setPresent(slot,isPresent),()=>presence.setPresent(slot,!1)},[presence,slot,isPresent])}export const PanelAnimationContext=createContext(null);export function usePanelAnimationControl(){return useContext(PanelAnimationContext)}export function useRunCallbackOnValueChange(value,onChange){let prev=useRef(value);useEffect(()=>{prev.current!==value&&(prev.current=value,onChange?.(value))},[value,onChange])}export function useVisibleChange(visible,onChange){useRunCallbackOnValueChange(visible,onChange)}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export const DEFAULT_LAYOUT_RULES={maxDockedPanels:{xs:1,m:2,l:3},rightPanel:{priority:1,condition:({isLowPrio,isMobile,layout})=>{isLowPrio&&!isMobile&&layout.rightPanel.setVariant("float")}},splitview:{priority:2,condition:({isLowPrio,isMobile,layout})=>{isLowPrio&&!isMobile&&layout.splitview.hide()}},leftPanel:{priority:3,condition:({isLowPrio,isMobile,layout})=>{let variant=isMobile
|
|
1
|
+
let leftPanelVariantFor=({isMobile,isLowPrio})=>isMobile?"drawer":isLowPrio?"offcanvas":"sidebar";export const DEFAULT_LAYOUT_RULES={maxDockedPanels:{xs:1,m:2,l:3},rightPanel:{priority:1,condition:({isLowPrio,isMobile,layout})=>{isLowPrio&&!isMobile&&layout.rightPanel.setVariant("float")}},splitview:{priority:2,condition:({isLowPrio,isMobile,layout})=>{isLowPrio&&!isMobile&&layout.splitview.hide()}},leftPanel:{priority:3,condition:({isLowPrio,isMobile,layout})=>{let variant=leftPanelVariantFor({isMobile,isLowPrio});variant!==layout.leftPanel.state.variant&&(layout.leftPanel.setVariant(variant),"offcanvas"===variant&&layout.leftPanel.hide())}}};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{useContext}from"react";import{useLayoutSelector,useLayoutStore}from"./context";import{PanelDeclarationsContext}from"./registry";let selectAll=state=>state;function panelHandleActions({slot,visible,dispatch}){return{isVisible:visible,show:()=>dispatch({type:"setVisible",slot,visible:!0}),hide:()=>dispatch({type:"setVisible",slot,visible:!1}),reset:()=>dispatch({type:"reset",slot})}}export function useLayout(){let store=useLayoutStore(),state=useLayoutSelector(selectAll),declared=useContext(PanelDeclarationsContext),{dispatch}=store;return{state,leftPanel:{state:{...state.leftPanel,variant:state.leftPanel.variant??
|
|
1
|
+
import{useContext}from"react";import{useLayoutSelector,useLayoutStore}from"./context";import{PanelDeclarationsContext}from"./registry";import{DEFAULT_LEFT_PANEL_VARIANT}from"./-constants";let selectAll=state=>state;function panelHandleActions({slot,visible,dispatch}){return{isVisible:visible,show:()=>dispatch({type:"setVisible",slot,visible:!0}),hide:()=>dispatch({type:"setVisible",slot,visible:!1}),reset:()=>dispatch({type:"reset",slot})}}export function useLayout(){let store=useLayoutStore(),state=useLayoutSelector(selectAll),declared=useContext(PanelDeclarationsContext),{dispatch}=store;return{state,leftPanel:{state:{...state.leftPanel,variant:state.leftPanel.variant??DEFAULT_LEFT_PANEL_VARIANT},setVariant:variant=>dispatch({type:"setVariant",panel:"leftPanel",variant}),...panelHandleActions({slot:"leftPanel",visible:state.leftPanel.visible,dispatch})},rightPanel:{state:{...state.rightPanel,variant:state.rightPanel.variant??declared.rightPanel?.variant??"sidebar"},setVariant:variant=>dispatch({type:"setVariant",panel:"rightPanel",variant}),...panelHandleActions({slot:"rightPanel",visible:state.rightPanel.visible,dispatch})},content:{state:state.content,...panelHandleActions({slot:"content",visible:state.content.visible,dispatch})},splitview:{state:state.splitview,...panelHandleActions({slot:"splitview",visible:state.splitview.visible,dispatch})}}}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{useEffect,useRef}from"react";import{useBreakpoints}from"../../shared/useBreakpoints";import{PANEL_ORDER,Slot,TOGGLABLE_SLOTS}from"./-constants";let DEFAULT_PRIORITY={[Slot.rightPanel]:1,[Slot.splitview]:2,[Slot.leftPanel]:3},maxDockedFor=(maxDockedPanels,breakpoints)=>{let{xs,m=xs,l=m}=maxDockedPanels;return breakpoints.isMobile?xs:breakpoints.isTablet?m:l},isDockedPanel=({state,declared,slot})=>!!declared[slot]&&!!state[slot].visible&&(slot===Slot.rightPanel?"float"!==state.rightPanel.variant:slot!==Slot.leftPanel||
|
|
1
|
+
import{useEffect,useRef}from"react";import{useBreakpoints}from"../../shared/useBreakpoints";import{DEFAULT_LEFT_PANEL_VARIANT,PANEL_ORDER,Slot,TOGGLABLE_SLOTS}from"./-constants";let DEFAULT_PRIORITY={[Slot.rightPanel]:1,[Slot.splitview]:2,[Slot.leftPanel]:3},maxDockedFor=(maxDockedPanels,breakpoints)=>{let{xs,m=xs,l=m}=maxDockedPanels;return breakpoints.isMobile?xs:breakpoints.isTablet?m:l},isDockedPanel=({state,declared,slot})=>!!declared[slot]&&!!state[slot].visible&&(slot===Slot.rightPanel?"float"!==state.rightPanel.variant:slot!==Slot.leftPanel||(state.leftPanel.variant??DEFAULT_LEFT_PANEL_VARIANT)===DEFAULT_LEFT_PANEL_VARIANT),resolveLowPrioSlots=({rules,state,declared,breakpoints})=>{let freeSlots=Math.max(0,maxDockedFor(rules.maxDockedPanels,breakpoints)-1),priorityFor=slot=>rules[slot]?.priority??DEFAULT_PRIORITY[slot],outranks=(slot,other)=>{let byPriority=priorityFor(slot)-priorityFor(other);return 0!==byPriority?byPriority<0:PANEL_ORDER.indexOf(slot)<PANEL_ORDER.indexOf(other)},countStrongerDocked=slot=>TOGGLABLE_SLOTS.filter(other=>other!==slot&&isDockedPanel({state,declared,slot:other})&&outranks(other,slot)).length;return TOGGLABLE_SLOTS.filter(slot=>countStrongerDocked(slot)>=freeSlots)};export function useLayoutRules({layout,declared,rules,additionalData}){let layoutRef=useRef(layout);layoutRef.current=layout;let{isMobile,isTablet,isDesktop}=useBreakpoints(),{state}=layout;useEffect(()=>{if(!rules)return;let lowPrioSlots=resolveLowPrioSlots({rules,state,declared,breakpoints:{isMobile,isTablet,isDesktop}});TOGGLABLE_SLOTS.forEach(slot=>{let condition=rules[slot]?.condition;condition&&condition({...additionalData,isLowPrio:lowPrioSlots.includes(slot),isMobile,isTablet,isDesktop,layout:layoutRef.current})})},[rules,additionalData,state,declared,isMobile,isTablet,isDesktop])}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/** DOM id of the rendered left panel, generated once per `Layout`. Lets a
|
|
2
|
+
* control living OUTSIDE the panel - the nav left bar's open button - point
|
|
3
|
+
* `aria-controls` at it without the two components knowing each other. Empty
|
|
4
|
+
* outside a `Layout`, where there is no panel to reference. */
|
|
5
|
+
export declare const LeftPanelIdContext: React.Context<string>;
|
|
6
|
+
export declare const useLeftPanelId: () => string;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{createContext,useContext}from"react";export const LeftPanelIdContext=createContext("");export const useLeftPanelId=()=>useContext(LeftPanelIdContext);
|
|
@@ -14,6 +14,12 @@ export type PanelDockedSlideOptions = {
|
|
|
14
14
|
/** Forwarded to the declaration: lock the column's width when the window
|
|
15
15
|
* resizes. Doesn't affect the slide, which resizes the column outright. */
|
|
16
16
|
lockWidthOnWindowResize?: boolean;
|
|
17
|
+
/** Width the column rests at while hidden, instead of collapsing to nothing.
|
|
18
|
+
* Set it and the column never unmounts: closing narrows it to this, opening
|
|
19
|
+
* widens it back, so one box carries both states (a nav left bar that widens
|
|
20
|
+
* into the panel). The column stops being collapsible - there is no zero to
|
|
21
|
+
* collapse to - and this becomes its `minSize` while it is hidden. */
|
|
22
|
+
collapsedSize?: Size;
|
|
17
23
|
};
|
|
18
24
|
export type PanelDockedSlide = {
|
|
19
25
|
/** Whether the panel's content should render at all (entering, open, or
|
|
@@ -21,15 +27,14 @@ export type PanelDockedSlide = {
|
|
|
21
27
|
isMounted: boolean;
|
|
22
28
|
/** Body width (px) while the column slides; `null` at rest, where the body
|
|
23
29
|
* fills the column and the panel stays resizable. */
|
|
24
|
-
|
|
30
|
+
fixedWidth: number | null;
|
|
25
31
|
};
|
|
26
32
|
/**
|
|
27
33
|
* Animates a docked side panel's open/close as a width slide on its
|
|
28
34
|
* `react-resizable-panels` column, pushing neighbouring content smoothly
|
|
29
|
-
* instead of snapping. Slot-generic - works for either side panel
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
* reduced motion is requested. The mobile modal-drawer lifecycle lives in
|
|
35
|
+
* instead of snapping. Slot-generic - works for either side panel. Falls back to
|
|
36
|
+
* an instant open/close when the panel isn't collapsible, no handle is
|
|
37
|
+
* available, or reduced motion is requested. The mobile modal-drawer lifecycle lives in
|
|
33
38
|
* {@link useExitAnimation} and the Drawer's styled components.
|
|
34
39
|
*/
|
|
35
|
-
export declare function usePanelDockedSlide({ slot, defaultSize, minSize, maxSize, collapsible, resizable, lockWidthOnWindowResize, }: PanelDockedSlideOptions): PanelDockedSlide;
|
|
40
|
+
export declare function usePanelDockedSlide({ slot, defaultSize, minSize, maxSize, collapsible, resizable, lockWidthOnWindowResize, collapsedSize, }: PanelDockedSlideOptions): PanelDockedSlide;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{useLayoutEffect,useState}from"react";import{useTheme}from"@emotion/react";import{useWindow}from"../../shared/useWindow";import{prefersReducedMotion}from"../../shared/prefersReducedMotion";import{useDeclarePanel,usePanelAnimationControl,usePanelPresence}from"./registry";import{useLayout}from"./useLayout";let parseDurationMs=duration=>{let trimmed=duration.trim();return trimmed.endsWith("ms")?parseFloat(trimmed):trimmed.endsWith("s")?1e3*parseFloat(trimmed):parseFloat(trimmed)||0},resolveSizePx=(size,groupWidthPx)=>{if("number"==typeof size)return size;if("string"!=typeof size)return null;let parsed=parseFloat(size);return Number.isFinite(parsed)?size.trim().endsWith("px")?parsed:null!=groupWidthPx?parsed/100*groupWidthPx:null:null},groupColumnsOf=element=>{let columns=element.closest("[data-group]")?.querySelectorAll("[data-panel]");return columns?Array.from(columns):[element]},isHandleReady=handle=>{try{return handle.isCollapsed(),!0}catch{return!1}};export function usePanelDockedSlide({slot,defaultSize,minSize,maxSize,collapsible,resizable,lockWidthOnWindowResize}){let{isVisible,state}=useLayout()[slot],theme=useTheme(),window=useWindow(),animation=usePanelAnimationControl(),reducedMotion=prefersReducedMotion(window),[isMounted,setIsMounted]=useState(isVisible),[phase,setPhase]=useState("idle"),[
|
|
1
|
+
import{useLayoutEffect,useRef,useState}from"react";import{useTheme}from"@emotion/react";import{useWindow}from"../../shared/useWindow";import{prefersReducedMotion}from"../../shared/prefersReducedMotion";import{useDeclarePanel,usePanelAnimationControl,usePanelPresence,usePanelRow}from"./registry";import{useLayout}from"./useLayout";let parseDurationMs=duration=>{let trimmed=duration.trim();return trimmed.endsWith("ms")?parseFloat(trimmed):trimmed.endsWith("s")?1e3*parseFloat(trimmed):parseFloat(trimmed)||0},resolveSizePx=(size,groupWidthPx)=>{if("number"==typeof size)return size;if("string"!=typeof size)return null;let parsed=parseFloat(size);return Number.isFinite(parsed)?size.trim().endsWith("px")?parsed:null!=groupWidthPx?parsed/100*groupWidthPx:null:null},groupColumnsOf=element=>{let columns=element.closest("[data-group]")?.querySelectorAll("[data-panel]");return columns?Array.from(columns):[element]},isHandleReady=handle=>{try{return handle.isCollapsed(),!0}catch{return!1}},mountDefaultSizeFor=({collapsedSize,defaultSize,isVisible,isSlidingIn})=>void 0!==collapsedSize?isVisible?defaultSize:collapsedSize:isSlidingIn?0:defaultSize,minSizeFor=({collapsedSize,isVisible,minSize})=>void 0===collapsedSize?minSize:isVisible?minSize??collapsedSize:collapsedSize;export function usePanelDockedSlide({slot,defaultSize,minSize,maxSize,collapsible,resizable,lockWidthOnWindowResize,collapsedSize}){let{isVisible,state}=useLayout()[slot],theme=useTheme(),window=useWindow(),animation=usePanelAnimationControl(),rowKey=usePanelRow(),reducedMotion=prefersReducedMotion(window),hasCollapsedRest=void 0!==collapsedSize,isCollapsible=collapsible&&!hasCollapsedRest,[isMounted,setIsMounted]=useState(isVisible),[phase,setPhase]=useState("idle"),[fixedWidth,setFixedWidth]=useState(null),[prevVisible,setPrevVisible]=useState(isVisible);isVisible!==prevVisible&&(setPrevVisible(isVisible),setPhase(isVisible?"entering":"exiting"),isVisible&&setIsMounted(!0),animation?.setResizeSuppressed(slot,!0));let openSize=hasCollapsedRest?state.size??defaultSize:defaultSize;useDeclarePanel(slot,{defaultSize:mountDefaultSizeFor({collapsedSize,defaultSize:openSize,isVisible,isSlidingIn:"entering"===phase&&collapsible&&!reducedMotion}),minSize:minSizeFor({collapsedSize,isVisible,minSize}),maxSize,collapsible:isCollapsible,resizable,lockWidthOnWindowResize}),usePanelPresence(slot,hasCollapsedRest||isMounted);let latestRest=useRef({isVisible,openSize,phase});return latestRest.current={isVisible,openSize,phase},useLayoutEffect(()=>{if(!hasCollapsedRest)return;let frame=0,cancelled=!1,resizeToRest=attempt=>{if(cancelled)return;let handle=animation?.getHandle(slot)??null;if(handle&&isHandleReady(handle)){let rest=latestRest.current;if("idle"!==rest.phase)return;let restSize=rest.isVisible?rest.openSize??minSize:collapsedSize;try{void 0!==restSize&&handle.resize(restSize)}catch{}return}animation&&!(attempt>=30)&&(frame=window.requestAnimationFrame(()=>resizeToRest(attempt+1)))};return Promise.resolve().then(()=>resizeToRest(0)),()=>{cancelled=!0,window.cancelAnimationFrame(frame)}},[rowKey]),useLayoutEffect(()=>{if("idle"===phase)return;let cancelled=!1,frame=0,settleTimer=0,animatedColumns=[];animation?.setResizeSuppressed(slot,!0);let{duration,timingFunction}=hasCollapsedRest?theme.variables.animation.navSlide.collapse:theme.variables.animation.navSlide.open,durationMs=parseDurationMs(duration),setColumnTransitions=enabled=>{animatedColumns.forEach(column=>{enabled?column.style.setProperty("transition",`flex-grow ${duration} ${timingFunction}`):column.style.removeProperty("transition")})},targetSize=state.size??defaultSize??minSize,openColumn=(handle,targetPx)=>{handle.isCollapsed()&&handle.expand(),handle.resize(targetPx??targetSize??minSize??"20%")},settle=handle=>{if(setColumnTransitions(!1),animation?.setResizeSuppressed(slot,!1),"entering"===phase&&handle&&!hasCollapsedRest)try{handle.getSize().inPixels<1&&openColumn(handle,null)}catch{}setFixedWidth(null),"exiting"!==phase||hasCollapsedRest||setIsMounted(!1),setPhase("idle")},runSlide=(handle,element)=>{animatedColumns=groupColumnsOf(element);let groupWidthPx=element.closest("[data-group]")?.getBoundingClientRect().width??null,targetPx=resolveSizePx(targetSize,groupWidthPx),collapsedPx=resolveSizePx(collapsedSize,groupWidthPx);setFixedWidth("entering"===phase?targetPx:handle.getSize().inPixels),reducedMotion||setColumnTransitions(!0),element.getBoundingClientRect();try{"entering"===phase?openColumn(handle,targetPx):hasCollapsedRest?handle.resize(collapsedPx??collapsedSize):handle.collapse()}catch{settle(handle);return}settleTimer=window.setTimeout(()=>settle(handle),reducedMotion?0:durationMs+80)},waitsForRelaxedMinimum="exiting"===phase&&hasCollapsedRest,waitForColumn=attempt=>{if(cancelled)return;if(0===attempt&&waitsForRelaxedMinimum){frame=window.requestAnimationFrame(()=>waitForColumn(attempt+1));return}let handle=animation?.getHandle(slot)??null,element=animation?.getElement(slot)??null;return handle&&element&&isHandleReady(handle)?void runSlide(handle,element):"exiting"===phase||!animation||attempt>=30?void settle(handle):void(frame=window.requestAnimationFrame(()=>waitForColumn(attempt+1)))};return collapsible||hasCollapsedRest?waitForColumn(0):settle(animation?.getHandle(slot)??null),()=>{cancelled=!0,window.cancelAnimationFrame(frame),window.clearTimeout(settleTimer),setColumnTransitions(!1),animation?.setResizeSuppressed(slot,!1)}},[phase,slot,collapsible,hasCollapsedRest,reducedMotion,animation,window,theme]),{isMounted:hasCollapsedRest||isMounted,fixedWidth}}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { CSSObject, Theme } from "@emotion/react";
|
|
2
|
+
type PanelContentFadeOptions = {
|
|
3
|
+
theme: Theme;
|
|
4
|
+
/** Whether the content is currently faded out. */
|
|
5
|
+
isFaded: boolean;
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* Fades a docked panel's content out across its collapse, and back in at once
|
|
9
|
+
* when it reopens - the panel covers the left bar the instant it is shown, so
|
|
10
|
+
* there is nothing to reveal on the way in.
|
|
11
|
+
*
|
|
12
|
+
* Runs on the column's own slide timing, so the two move together.
|
|
13
|
+
*
|
|
14
|
+
* Applied per part rather than to the whole panel: a control at the header's
|
|
15
|
+
* trailing edge travels down onto the left bar's own and has to stay solid the
|
|
16
|
+
* whole way, so it is left out.
|
|
17
|
+
*/
|
|
18
|
+
export declare function getLeftPanelFadeStyles({ theme, isFaded, }: PanelContentFadeOptions): CSSObject;
|
|
19
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export function getLeftPanelFadeStyles({theme,isFaded}){let{duration,timingFunction}=theme.variables.animation.navSlide.collapse;return{opacity:isFaded?theme.variables.opacity.hidden:theme.variables.opacity.visible,transition:isFaded?`opacity ${duration} ${timingFunction}`:"none","@media (prefers-reduced-motion: reduce)":{transition:"none"}}}
|
|
@@ -6,4 +6,5 @@ export { getBaseButtonStyles } from "./Button/getBaseButtonStyles";
|
|
|
6
6
|
export { getPressedStyles } from "./Button/getPressedStyles";
|
|
7
7
|
export { getPillStyles } from "./Button/getPillStyles";
|
|
8
8
|
export { getFocusStyles } from "./getFocusStyles";
|
|
9
|
+
export { getLeftPanelFadeStyles } from "./getLeftPanelFadeStyles";
|
|
9
10
|
export { getPrimaryVariantStyles, getSecondaryVariantStyles, getTertiaryVariantStyles, } from "./Button/getVariantStyles";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export{getInputTextPlaceholder}from"./TextInput/getInputTextPlaceholder";export{getInputTextStyles}from"./TextInput/getInputTextStyles";export{getDisabledStyles}from"./Button/getDisabledStyles";export{getButtonAppearanceReset}from"./Button/getButtonAppearanceReset";export{getBaseButtonStyles}from"./Button/getBaseButtonStyles";export{getPressedStyles}from"./Button/getPressedStyles";export{getPillStyles}from"./Button/getPillStyles";export{getFocusStyles}from"./getFocusStyles";export{getPrimaryVariantStyles,getSecondaryVariantStyles,getTertiaryVariantStyles}from"./Button/getVariantStyles";
|
|
1
|
+
export{getInputTextPlaceholder}from"./TextInput/getInputTextPlaceholder";export{getInputTextStyles}from"./TextInput/getInputTextStyles";export{getDisabledStyles}from"./Button/getDisabledStyles";export{getButtonAppearanceReset}from"./Button/getButtonAppearanceReset";export{getBaseButtonStyles}from"./Button/getBaseButtonStyles";export{getPressedStyles}from"./Button/getPressedStyles";export{getPillStyles}from"./Button/getPillStyles";export{getFocusStyles}from"./getFocusStyles";export{getLeftPanelFadeStyles}from"./getLeftPanelFadeStyles";export{getPrimaryVariantStyles,getSecondaryVariantStyles,getTertiaryVariantStyles}from"./Button/getVariantStyles";
|