Skip to content

Commit

Permalink
pef: add provider to useSidebar hook
Browse files Browse the repository at this point in the history
  • Loading branch information
mayan-000 committed Feb 15, 2024
1 parent b955cea commit 01301d5
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 36 deletions.
2 changes: 0 additions & 2 deletions packages/design-system/src/components/sidebar/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,5 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/

export { default as useSidebar } from './useSidebar';
export * from './useSidebar';
export { default as Sidebar } from './sidebar';
124 changes: 90 additions & 34 deletions packages/design-system/src/components/sidebar/useSidebar/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,15 @@
/**
* External dependencies.
*/
import React, { useCallback, useEffect, useMemo, useState } from 'react';
import React, {
PropsWithChildren,
useCallback,
useEffect,
useMemo,
useState,
} from 'react';
import { createContext, useContextSelector } from 'use-context-selector';
import { noop } from '@ps-analysis-tool/common';

/**
* Internal dependencies.
Expand Down Expand Up @@ -45,32 +53,57 @@ export type SidebarItems = {
[key: string]: SidebarItemValue;
};

export interface SidebarOutput {
activePanel: React.ReactNode;
selectedItemKey: string | null; //Entire chained item key eg Privacy-Sandbox#cookies#frameUrl
currentItemKey: string | null; //Last sidebar item key in selectedItemKey eg frameUrl
sidebarItems: SidebarItems;
isSidebarFocused: boolean;
setIsSidebarFocused: React.Dispatch<boolean>;
updateSelectedItemKey: (key: string | null) => void;
onKeyNavigation: (
event: React.KeyboardEvent<HTMLDivElement>,
key: string | null
) => void;
toggleDropdown: (action: boolean, key: string) => void;
isKeyAncestor: (key: string) => boolean;
isKeySelected: (key: string) => boolean;
}

interface useSidebarProps {
data: SidebarItems;
defaultSelectedItemKey?: string | null;
}

const useSidebar = ({
export interface SidebarStoreContext {
state: {
activePanel: React.ReactNode;
selectedItemKey: string | null; //Entire chained item key eg Privacy-Sandbox#cookies#frameUrl
currentItemKey: string | null; //Last sidebar item key in selectedItemKey eg frameUrl
sidebarItems: SidebarItems;
isSidebarFocused: boolean;
};
actions: {
setIsSidebarFocused: React.Dispatch<boolean>;
updateSelectedItemKey: (key: string | null) => void;
onKeyNavigation: (
event: React.KeyboardEvent<HTMLDivElement>,
key: string | null
) => void;
toggleDropdown: (action: boolean, key: string) => void;
isKeyAncestor: (key: string) => boolean;
isKeySelected: (key: string) => boolean;
};
}

const initialState: SidebarStoreContext = {
state: {
activePanel: null,
selectedItemKey: null,
currentItemKey: null,
sidebarItems: {},
isSidebarFocused: true,
},
actions: {
setIsSidebarFocused: noop,
updateSelectedItemKey: noop,
onKeyNavigation: noop,
toggleDropdown: noop,
isKeyAncestor: () => false,
isKeySelected: () => false,
},
};

export const SidebarContext = createContext<SidebarStoreContext>(initialState);

export const SidebarProvider = ({
data,
defaultSelectedItemKey = null,
}: useSidebarProps): SidebarOutput => {
children,
}: PropsWithChildren<useSidebarProps>) => {
const [selectedItemKey, setSelectedItemKey] = useState<string | null>(null);
const [activePanel, setActivePanel] = useState<React.ReactNode>(); // TODO: Should we use React.ReactNode in state?
const [sidebarItems, setSidebarItems] = useState<SidebarItems>({});
Expand Down Expand Up @@ -222,19 +255,42 @@ const useSidebar = ({
[selectedItemKey]
);

return {
activePanel,
selectedItemKey,
currentItemKey,
sidebarItems,
isSidebarFocused,
setIsSidebarFocused,
updateSelectedItemKey,
onKeyNavigation,
toggleDropdown,
isKeyAncestor,
isKeySelected,
};
return (
<SidebarContext.Provider
value={{
state: {
activePanel,
selectedItemKey,
currentItemKey,
sidebarItems,
isSidebarFocused,
},
actions: {
setIsSidebarFocused,
updateSelectedItemKey,
onKeyNavigation,
toggleDropdown,
isKeyAncestor,
isKeySelected,
},
}}
>
{children}
</SidebarContext.Provider>
);
};

export default useSidebar;
export function useSidebar(): SidebarStoreContext;
export function useSidebar<T>(selector: (state: SidebarStoreContext) => T): T;

/**
* Hook to access the Sidebar context.
* @param selector Selector function to partially select state.
* @returns selected part of the state
*/
export function useSidebar<T>(
selector: (state: SidebarStoreContext) => T | SidebarStoreContext = (state) =>
state
) {
return useContextSelector(SidebarContext, selector);
}

0 comments on commit 01301d5

Please sign in to comment.