Skip to content

Commit

Permalink
Merge pull request #10123 from storybookjs/feature/global-args-exports
Browse files Browse the repository at this point in the history
Core: Add globalArgs/globalArgTypes `preview.js` exports
  • Loading branch information
shilman committed Mar 13, 2020
2 parents 5c184af + 7552ab0 commit e75d6d4
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 5 deletions.
12 changes: 12 additions & 0 deletions examples/official-storybook/preview.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,4 +57,16 @@ addParameters({

export const parameters = {
exportedParameter: 'exportedParameter',
args: { invalid1: 'will warn' },
};

export const args = { invalid2: 'will warn' };

export const globalArgs = {
foo: 'fooValue',
};

export const globalArgTypes = {
foo: { defaultValue: 'fooDefaultValue' },
bar: { defaultValue: 'barDefaultValue' },
};
20 changes: 20 additions & 0 deletions lib/client-api/src/story_store.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,26 @@ describe('preview.story_store', () => {
});
});

it('is initialized to the default values stored in parameters.globalArgsTypes on the first story', () => {
const store = new StoryStore({ channel });
addStoryToStore(store, 'a', '1', () => 0, {
globalArgs: {
arg1: 'arg1',
arg2: 2,
},
globalArgTypes: {
arg2: { defaultValue: 'arg2' },
arg3: { defaultValue: { complex: { object: ['type'] } } },
},
});
store.finishConfiguring();
expect(store.getRawStory('a', '1').globalArgs).toEqual({
arg1: 'arg1',
arg2: 2,
arg3: { complex: { object: ['type'] } },
});
});

it('on HMR it sensibly re-initializes with memory', () => {
const store = new StoryStore({ channel });
addons.setChannel(channel);
Expand Down
37 changes: 35 additions & 2 deletions lib/client-api/src/story_store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,18 @@ const includeStory = (story: StoreItem, options: StoryOptions = { includeDocsOnl
return !isStoryDocsOnly(story.parameters);
};

const checkGlobalArgs = (parameters: Parameters) => {
const { globalArgs, globalArgTypes } = parameters;
if (globalArgs || globalArgTypes) {
throw new Error(
`Global args/argTypes can only be set globally: ${JSON.stringify({
globalArgs,
globalArgTypes,
})}`
);
}
};

type AllowUnsafeOption = { allowUnsafe?: boolean };

const toExtracted = <T>(obj: T) =>
Expand Down Expand Up @@ -138,9 +150,19 @@ export default class StoryStore {
const storyIds = Object.keys(this._stories);
if (storyIds.length) {
const {
parameters: { globalArgs },
parameters: { globalArgs: initialGlobalArgs, globalArgTypes },
} = this.fromId(storyIds[0]);

const defaultGlobalArgs: Args = globalArgTypes
? Object.entries(globalArgTypes as Record<string, { defaultValue: any }>).reduce(
(acc, [arg, { defaultValue }]) => {
if (defaultValue) acc[arg] = defaultValue;
return acc;
},
{} as Args
)
: {};

// To deal with HMR, we consider the previous value of global args, and:
// 1. Remove any keys that are not in the new parameter
// 2. Preference any keys that were already set
Expand All @@ -151,12 +173,20 @@ export default class StoryStore {

return acc;
},
globalArgs
{ ...defaultGlobalArgs, ...initialGlobalArgs }
);
}
}

addGlobalMetadata({ parameters, decorators }: StoryMetadata) {
if (parameters) {
const { args, argTypes } = parameters;
if (args || argTypes)
logger.warn(
'Found args/argTypes in global parameters.',
JSON.stringify({ args, argTypes })
);
}
const globalParameters = this._globalMetadata.parameters;

this._globalMetadata.parameters = combineParameters(globalParameters, parameters);
Expand All @@ -180,6 +210,7 @@ export default class StoryStore {

addKindMetadata(kind: string, { parameters, decorators }: StoryMetadata) {
this.ensureKind(kind);
if (parameters) checkGlobalArgs(parameters);
this._kinds[kind].parameters = combineParameters(this._kinds[kind].parameters, parameters);

this._kinds[kind].decorators.push(...decorators);
Expand Down Expand Up @@ -213,6 +244,8 @@ export default class StoryStore {
'Cannot add a story when not configuring, see https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#story-store-immutable-outside-of-configuration'
);

if (storyParameters) checkGlobalArgs(storyParameters);

const { _stories } = this;

if (_stories[id]) {
Expand Down
8 changes: 5 additions & 3 deletions lib/core/src/server/preview/iframe-webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,15 @@ export default ({
const configFilename = match[1];
virtualModuleMapping[entryFilename] = `
import { addDecorator, addParameters, addParameterEnhancer } from '@storybook/client-api';
import { logger } from '@storybook/client-logger';
const { decorators, parameters,parameterEnhancers } = require(${JSON.stringify(
const { decorators, parameters, parameterEnhancers, globalArgs, globalArgTypes, args, argTypes } = require(${JSON.stringify(
configFilename
)});
if(args || argTypes) logger.warn('Invalid args/argTypes in config, ignoring.', JSON.stringify({ args, argTypes }));
if (decorators) decorators.forEach(decorator => addDecorator(decorator));
if (parameters) addParameters(parameters);
if (parameters || globalArgs || globalArgTypes) addParameters({ ...parameters, globalArgs, globalArgTypes });
if (parameterEnhancers) parameterEnhancers.forEach(enhancer => addParameterEnhancer(enhancer));
`;
}
Expand Down

0 comments on commit e75d6d4

Please sign in to comment.