storybook-react-context
Version:
Manipulate React context inside Storybook. Read state and dispatch updates from outside of React component.
40 lines • 1.94 kB
JavaScript
import React from 'react';
import { makeDecorator, useArgs } from 'storybook/preview-api';
export const ContextValues = ({ children, contexts }) => {
// Retrieve context values using explicit calls to useContext
const contextValues = contexts.map((item) => React.useContext(item.context));
return children(contextValues);
};
export const withReactContext = makeDecorator({
name: 'storybook-react-context',
parameterName: 'reactContext',
// options - decorator argument, parameters - story parameter
wrapper: (storyFn, storyContext, { options, parameters }) => {
const {
// `contexts` is for multiple contexts
contexts = [],
// `context` and `contextValue` are for single context and is appended to `contexts`
context, contextValue, } = { ...options, ...parameters };
const allContexts = [...contexts];
if (context && contextValue) {
allContexts.push({ context, contextValue });
}
if (!allContexts.length) {
throw new Error(`At least one context is required. Please provide it in decorator options or story parameters.
Either \`contexts\` for multiple contexts or both \`context\` and \`contextValue\` must be set.`);
}
return allContexts.reduceRight((acc, { context: Context, contextValue }) => {
const providerValue = typeof contextValue === 'function'
? contextValue({ ...storyContext, useArgs })
: contextValue;
return React.createElement(Context.Provider, { value: providerValue }, acc);
}, React.createElement(ContextValues, { contexts: allContexts }, (contextValues) => storyFn({
...storyContext,
reactContext: {
values: contextValues,
value: contextValues[contextValues.length - 1],
},
})));
},
});
//# sourceMappingURL=decorator.js.map