UNPKG

4.01 kBJavaScriptView Raw
1import React, { useMemo } from 'react';
2import { atom, useAtom, useAtomValue, useSetAtom, getDefaultStore } from 'jotai';
3import { useTheme as useEmotionTheme } from 'emotion-theming';
4const storyContextAtom = atom(null);
5/**
6 * Hook that returns a function to set the current story context.
7 */
8export function useSetStoryContext() {
9 return useSetAtom(storyContextAtom);
10}
11/**
12 * Hook to read the current story context.
13 */
14export function useStoryContext() {
15 return useAtomValue(storyContextAtom);
16}
17/**
18 * Hook that reads the value of a specific story context parameter.
19 */
20export function useStoryContextParam(name, defaultValue) {
21 var _a;
22 const paramAtom = useMemo(() => atom((get) => { var _a, _b; return (_b = (_a = get(storyContextAtom)) === null || _a === void 0 ? void 0 : _a.parameters) === null || _b === void 0 ? void 0 : _b[name]; }), [name]);
23 return (_a = useAtomValue(paramAtom)) !== null && _a !== void 0 ? _a : defaultValue;
24}
25/**
26 * Hook that indicates if `storyId` is the currently selected story.
27 */
28export function useIsStorySelected(storyId) {
29 return useAtomValue(useMemo(() => atom((get) => { var _a; return ((_a = get(storyContextAtom)) === null || _a === void 0 ? void 0 : _a.id) === storyId; }), [storyId]));
30}
31/**
32 * Hook that indicates if `title` is the currently selected story section.
33 */
34export function useIsStorySectionSelected(title) {
35 return useAtomValue(useMemo(() => atom((get) => { var _a; return ((_a = get(storyContextAtom)) === null || _a === void 0 ? void 0 : _a.title) === title; }), [title]));
36}
37/**
38 * Hook that causes a re-render when the currently selected story is changed.
39 */
40export function useUpdateOnStoryChanged() {
41 useAtomValue(useMemo(() => atom((get) => { var _a; return (_a = get(storyContextAtom)) === null || _a === void 0 ? void 0 : _a.id; }), []));
42}
43/**
44 * Hook that gets the current theme values.
45 */
46export function useTheme() {
47 return useEmotionTheme();
48}
49/**
50 * A boolean atom creator for an atom that can only be toggled between
51 * true/false.
52 *
53 * @see {@link https://jotai.org/docs/recipes/atom-creators#atomwithtoggle}
54 */
55export function atomWithToggle(initialValue) {
56 const anAtom = atom(initialValue, (get, set, nextValue) => {
57 const update = nextValue !== null && nextValue !== void 0 ? nextValue : !get(anAtom);
58 set(anAtom, update);
59 });
60 return anAtom;
61}
62const isUIVisibleAtom = atomWithToggle(true);
63/**
64 * Hook that retrieves the current state, and a setter, for the `isUIVisible`
65 * atom.
66 */
67export function useIsUIVisible() {
68 return useAtom(isUIVisibleAtom);
69}
70const isSplitPanelVisibleAtom = atomWithToggle(false);
71/**
72 * Hook that retrieves the current state, and a setter, for the
73 * `isSplitPanelVisibleAtom` atom.
74 */
75export function useIsSplitPanelVisible() {
76 return useAtom(isSplitPanelVisibleAtom);
77}
78/**
79 * Sync the UI atom states with external values, such as from Story parameters.
80 */
81export function syncExternalUI({ isUIVisible, isSplitPanelVisible }) {
82 const jotaiStore = getDefaultStore();
83 if (isUIVisible !== undefined) {
84 jotaiStore.set(isUIVisibleAtom, isUIVisible);
85 }
86 if (isSplitPanelVisible !== undefined) {
87 jotaiStore.set(isSplitPanelVisibleAtom, isSplitPanelVisible);
88 }
89}
90const selectedAddonAtom = atom(undefined);
91/**
92 * Hook that manages the state for the currently selected addon.
93 *
94 * This value persists across stories, so that the same addon will be selected
95 * when switching stories.
96 */
97export function useSelectedAddon(initialValue) {
98 const result = useAtom(selectedAddonAtom);
99 const set = result[1];
100 React.useEffect(() => {
101 const jotaiStore = getDefaultStore();
102 // Only apply the initial value once, and only if the atom doesn't have a
103 // value yet.
104 if (jotaiStore.get(selectedAddonAtom) === undefined) {
105 set(initialValue);
106 }
107 // eslint-disable-next-line react-hooks/exhaustive-deps
108 }, []);
109 return result;
110}