UNPKG

@ultraviolet/plus

Version:
130 lines (129 loc) 4.04 kB
"use client"; import { jsx } from "@emotion/react/jsx-runtime"; import { useContext, useState, useReducer, useRef, useCallback, useMemo, createContext } from "react"; import { NAVIGATION_WIDTH, ANIMATION_DURATION } from "./constants.js"; import NavigationLocales from "./locales/en.js"; const NavigationContext = createContext({ expanded: true, /** * This function will trigger the expand/collapse of the navigation and * will also trigger the animation */ toggleExpand: () => { }, animation: false, locales: NavigationLocales, pinItem: () => [], unpinItem: () => [], pinnedItems: [], pinLimit: 7, navigationRef: { current: null }, width: NAVIGATION_WIDTH, setWidth: () => { }, reorderItems: () => [], items: {}, registerItem: () => { }, setPinnedItems: () => { }, allowNavigationResize: true, setAllowNavigationResize: () => { }, shouldAnimate: true, animationType: "simple" }); const useNavigation = () => useContext(NavigationContext); const NavigationProvider = ({ children, pinnedFeature = false, initialPinned, initialExpanded = true, locales = NavigationLocales, pinLimit = 7, onExpandChange, initialWidth = NAVIGATION_WIDTH, initialAllowNavigationResize = true, animation: shouldAnimate = true, animationType }) => { const [expanded, setExpanded] = useState(initialExpanded); const [pinnedItems, setPinnedItems] = useState(initialPinned ?? []); const [animation, setAnimation] = useState(false); const [width, setWidth] = useState(initialWidth); const [allowNavigationResize, setAllowNavigationResize] = useState(initialAllowNavigationResize); const [items, registerItem] = useReducer((oldState, newState) => ({ ...oldState, ...newState }), {}); const navigationRef = useRef(null); const toggleExpand = useCallback((toggle) => { if (typeof toggle !== "boolean" && toggle !== void 0) { throw new Error("toggleExpand only accepts boolean or undefined as parameter. You most likely did <button onClick={toggleExpand}> instead of <button onClick={() => toggleExpand()}>"); } if (toggle !== void 0 && toggle === expanded) { return; } onExpandChange?.(!expanded); if (navigationRef.current) { navigationRef.current.style.width = ""; } if (shouldAnimate) { setAnimation(expanded ? "collapse" : "expand"); setTimeout(() => { setExpanded(toggle !== void 0 ? toggle : !expanded); setAnimation(false); }, ANIMATION_DURATION); } else { setExpanded(toggle !== void 0 ? toggle : !expanded); } }, [expanded, onExpandChange, shouldAnimate]); const pinItem = useCallback((item) => { const newValue = [...pinnedItems, item]; setPinnedItems(newValue); return newValue; }, [pinnedItems]); const unpinItem = useCallback((item) => { const newValue = pinnedItems.filter((localItem) => localItem !== item); setPinnedItems(newValue); return newValue; }, [pinnedItems]); const reorderItems = useCallback((initialIndex, endIndex) => { const newPinnedItems = [...pinnedItems]; const [removed] = newPinnedItems.splice(initialIndex, 1); newPinnedItems.splice(endIndex, 0, removed); setPinnedItems(newPinnedItems); return newPinnedItems; }, [pinnedItems]); const value = useMemo(() => ({ expanded, toggleExpand, pinnedItems, pinItem, unpinItem, pinnedFeature, locales, pinLimit, animation, setAnimation, navigationRef, width, setWidth, reorderItems, registerItem, items, setPinnedItems, allowNavigationResize, setAllowNavigationResize, shouldAnimate, animationType }), [expanded, toggleExpand, pinnedItems, pinItem, unpinItem, pinnedFeature, locales, pinLimit, animation, width, reorderItems, items, allowNavigationResize, shouldAnimate, animationType]); return /* @__PURE__ */ jsx(NavigationContext.Provider, { value, children }); }; export { NavigationContext, NavigationProvider, useNavigation };