@grafana/ui
Version:
Grafana Components Library
137 lines (134 loc) • 4.81 kB
JavaScript
import React__default, { useContext, useCallback, useEffect } from 'react';
import { useMedia } from 'react-use';
import { store } from '@grafana/data';
import { useTheme2 } from '../../themes/ThemeContext.mjs';
import { clamp } from '../../utils/clamp.mjs';
;
const SidebarContext = React__default.createContext(void 0);
const useSidebarContext = () => useContext(SidebarContext);
const SIDE_BAR_WIDTH_ICON_ONLY = 5;
const SIDE_BAR_WIDTH_WITH_TEXT = 8;
function useSidebar({
hasOpenPane,
position = "right",
tabsMode,
defaultToCompact = true,
defaultToDocked = false,
bottomMargin = 2,
edgeMargin = 2,
contentMargin = 2,
persistenceKey,
onClosePane,
onGoBack,
canGoBack,
defaultIsHidden = false,
hiddenPersistenceKey
}) {
const theme = useTheme2();
const [isDocked, setIsDocked] = useSidebarSavedState(persistenceKey, "docked", defaultToDocked);
const [compact, setCompact] = useSidebarSavedState(persistenceKey, "compact", defaultToCompact);
const [paneWidth, setPaneWidth] = useSidebarSavedState(persistenceKey, "size", 240);
const [isHidden, setIsHidden] = useSidebarSavedState(
hiddenPersistenceKey != null ? hiddenPersistenceKey : persistenceKey,
"hidden",
defaultIsHidden
);
const isMobile = useMedia(`(max-width: ${theme.breakpoints.values.sm}px)`);
const isTemporarilyShown = isHidden && Boolean(hasOpenPane);
const effectiveIsHidden = isHidden && !isTemporarilyShown;
const effectiveIsDocked = !isTemporarilyShown && !isMobile && isDocked;
const [_, setCompactDrag] = React__default.useState(0);
const onToggleDock = useCallback(() => {
setIsDocked((prev) => !prev);
}, [setIsDocked]);
const prop = position === "right" ? "paddingRight" : "paddingLeft";
const toolbarWidth = ((compact ? SIDE_BAR_WIDTH_ICON_ONLY : SIDE_BAR_WIDTH_WITH_TEXT) + edgeMargin + contentMargin) * theme.spacing.gridSize;
const outerWrapperProps = effectiveIsHidden || isTemporarilyShown ? {} : {
style: {
[prop]: effectiveIsDocked && hasOpenPane ? paneWidth + toolbarWidth : toolbarWidth
}
};
const onResize = useCallback(
(diff) => {
setPaneWidth((prevWidth) => {
if (!hasOpenPane) {
setCompactDrag((prevDrag) => {
const newDrag = prevDrag + diff;
if (newDrag < -20 && !compact) {
setCompact(() => true);
return 0;
} else if (newDrag > 20 && compact) {
setCompact(() => false);
return 0;
}
return newDrag;
});
return prevWidth;
}
const maxWidth = Math.max(window.innerWidth * 0.5, 500);
return clamp(prevWidth + diff, 100, maxWidth);
});
},
[hasOpenPane, setCompact, setPaneWidth, compact]
);
const onToggleIsHidden = useCallback(() => setIsHidden((prev) => !prev), [setIsHidden]);
const setIsHiddenValue = useCallback((value) => setIsHidden(() => value), [setIsHidden]);
return {
isDocked: effectiveIsDocked,
onToggleDock: isMobile || isTemporarilyShown ? void 0 : onToggleDock,
onResize,
outerWrapperProps,
position,
compact,
hasOpenPane,
tabsMode,
paneWidth,
edgeMargin,
bottomMargin,
contentMargin,
isHidden: effectiveIsHidden,
isHiddenPreference: isHidden,
onClosePane,
onGoBack,
canGoBack,
onToggleIsHidden,
setIsHidden: setIsHiddenValue
};
}
function readFromStore(persistenceKey, subKey, defaultValue) {
if (!persistenceKey) {
return defaultValue;
}
if (typeof defaultValue === "boolean") {
return store.getBool(`grafana.ui.sidebar.${persistenceKey}.${subKey}`, defaultValue);
}
if (typeof defaultValue === "number") {
const value = Number.parseInt(store.get(`grafana.ui.sidebar.${persistenceKey}.${subKey}`), 10);
return Number.isNaN(value) ? defaultValue : value;
}
return defaultValue;
}
function useSidebarSavedState(persistenceKey, subKey, defaultValue) {
const [state, setState] = React__default.useState(() => readFromStore(persistenceKey, subKey, defaultValue));
useEffect(() => {
setState(readFromStore(persistenceKey, subKey, defaultValue));
}, [persistenceKey, subKey]);
const setPersisted = useCallback(
(cb) => {
setState((prevState) => {
const newState = cb(prevState);
if (!persistenceKey) {
return newState;
}
if (persistenceKey) {
store.set(`grafana.ui.sidebar.${persistenceKey}.${subKey}`, String(newState));
}
return newState;
});
},
[persistenceKey, subKey]
);
return [state, setPersisted];
}
export { SIDE_BAR_WIDTH_ICON_ONLY, SIDE_BAR_WIDTH_WITH_TEXT, SidebarContext, useSidebar, useSidebarContext, useSidebarSavedState };
//# sourceMappingURL=useSidebar.mjs.map