1 | const _excluded = ["id"],
|
2 | _excluded2 = ["kind", "story", "storyId"];
|
3 |
|
4 | function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
|
5 |
|
6 | import "core-js/modules/es.array.reduce.js";
|
7 | import global from 'global';
|
8 | import { toId, sanitize } from '@storybook/csf';
|
9 | import { PRELOAD_STORIES, STORY_PREPARED, UPDATE_STORY_ARGS, RESET_STORY_ARGS, STORY_ARGS_UPDATED, STORY_CHANGED, SELECT_STORY, SET_STORIES, STORY_SPECIFIED, STORY_INDEX_INVALIDATED, CONFIG_ERROR } from '@storybook/core-events';
|
10 | import deprecate from 'util-deprecate';
|
11 | import { logger } from '@storybook/client-logger';
|
12 | import { getEventMetadata } from '../lib/events';
|
13 | import { denormalizeStoryParameters, transformStoriesRawToStoriesHash, isStory, isRoot, transformStoryIndexToStoriesHash, getComponentLookupList, getStoriesLookupList } from '../lib/stories';
|
14 | const {
|
15 | DOCS_MODE,
|
16 | FEATURES,
|
17 | fetch
|
18 | } = global;
|
19 | const STORY_INDEX_PATH = './stories.json';
|
20 | const deprecatedOptionsParameterWarnings = ['enableShortcuts', 'theme', 'showRoots'].reduce((acc, option) => {
|
21 | acc[option] = deprecate(() => {}, `parameters.options.${option} is deprecated and will be removed in Storybook 7.0.
|
22 | To change this setting, use \`addons.setConfig\`. See https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#deprecated-immutable-options-parameters
|
23 | `);
|
24 | return acc;
|
25 | }, {});
|
26 |
|
27 | function checkDeprecatedOptionParameters(options) {
|
28 | if (!options) {
|
29 | return;
|
30 | }
|
31 |
|
32 | Object.keys(options).forEach(option => {
|
33 | if (deprecatedOptionsParameterWarnings[option]) {
|
34 | deprecatedOptionsParameterWarnings[option]();
|
35 | }
|
36 | });
|
37 | }
|
38 |
|
39 | export const init = ({
|
40 | fullAPI,
|
41 | store,
|
42 | navigate,
|
43 | provider,
|
44 | storyId: initialStoryId,
|
45 | viewMode: initialViewMode
|
46 | }) => {
|
47 | const api = {
|
48 | storyId: toId,
|
49 | getData: (storyId, refId) => {
|
50 | const result = api.resolveStory(storyId, refId);
|
51 | return isRoot(result) ? undefined : result;
|
52 | },
|
53 | isPrepared: (storyId, refId) => {
|
54 | const data = api.getData(storyId, refId);
|
55 |
|
56 | if (data.isLeaf) {
|
57 | return data.prepared;
|
58 | }
|
59 |
|
60 |
|
61 | return true;
|
62 | },
|
63 | resolveStory: (storyId, refId) => {
|
64 | const {
|
65 | refs,
|
66 | storiesHash
|
67 | } = store.getState();
|
68 |
|
69 | if (refId) {
|
70 | return refs[refId].stories ? refs[refId].stories[storyId] : undefined;
|
71 | }
|
72 |
|
73 | return storiesHash ? storiesHash[storyId] : undefined;
|
74 | },
|
75 | getCurrentStoryData: () => {
|
76 | const {
|
77 | storyId,
|
78 | refId
|
79 | } = store.getState();
|
80 | return api.getData(storyId, refId);
|
81 | },
|
82 | getParameters: (storyIdOrCombo, parameterName) => {
|
83 | const {
|
84 | storyId,
|
85 | refId
|
86 | } = typeof storyIdOrCombo === 'string' ? {
|
87 | storyId: storyIdOrCombo,
|
88 | refId: undefined
|
89 | } : storyIdOrCombo;
|
90 | const data = api.getData(storyId, refId);
|
91 |
|
92 | if (isStory(data)) {
|
93 | const {
|
94 | parameters
|
95 | } = data;
|
96 |
|
97 | if (parameters) {
|
98 | return parameterName ? parameters[parameterName] : parameters;
|
99 | }
|
100 |
|
101 | return {};
|
102 | }
|
103 |
|
104 | return null;
|
105 | },
|
106 | getCurrentParameter: parameterName => {
|
107 | const {
|
108 | storyId,
|
109 | refId
|
110 | } = store.getState();
|
111 | const parameters = api.getParameters({
|
112 | storyId,
|
113 | refId
|
114 | }, parameterName);
|
115 |
|
116 |
|
117 | return parameters || undefined;
|
118 | },
|
119 | jumpToComponent: direction => {
|
120 | const {
|
121 | storiesHash,
|
122 | storyId,
|
123 | refs,
|
124 | refId
|
125 | } = store.getState();
|
126 | const story = api.getData(storyId, refId);
|
127 |
|
128 | if (!story) {
|
129 | return;
|
130 | }
|
131 |
|
132 | const hash = refId ? refs[refId].stories || {} : storiesHash;
|
133 | const result = api.findSiblingStoryId(storyId, hash, direction, true);
|
134 |
|
135 | if (result) {
|
136 | api.selectStory(result, undefined, {
|
137 | ref: refId
|
138 | });
|
139 | }
|
140 | },
|
141 | jumpToStory: direction => {
|
142 | const {
|
143 | storiesHash,
|
144 | storyId,
|
145 | refs,
|
146 | refId
|
147 | } = store.getState();
|
148 | const story = api.getData(storyId, refId);
|
149 |
|
150 | if (DOCS_MODE) {
|
151 | api.jumpToComponent(direction);
|
152 | return;
|
153 | }
|
154 |
|
155 |
|
156 | if (!story) {
|
157 | return;
|
158 | }
|
159 |
|
160 | const hash = story.refId ? refs[story.refId].stories : storiesHash;
|
161 | const result = api.findSiblingStoryId(storyId, hash, direction, false);
|
162 |
|
163 | if (result) {
|
164 | api.selectStory(result, undefined, {
|
165 | ref: refId
|
166 | });
|
167 | }
|
168 | },
|
169 | setStories: async (input, error) => {
|
170 |
|
171 | const hash = transformStoriesRawToStoriesHash(input, {
|
172 | provider
|
173 | });
|
174 | await store.setState({
|
175 | storiesHash: hash,
|
176 | storiesConfigured: true,
|
177 | storiesFailed: error
|
178 | });
|
179 | },
|
180 | selectFirstStory: () => {
|
181 | const {
|
182 | storiesHash
|
183 | } = store.getState();
|
184 | const firstStory = Object.keys(storiesHash).find(k => !(storiesHash[k].children || Array.isArray(storiesHash[k])));
|
185 |
|
186 | if (firstStory) {
|
187 | api.selectStory(firstStory);
|
188 | return;
|
189 | }
|
190 |
|
191 | navigate('/');
|
192 | },
|
193 | selectStory: (kindOrId = undefined, story = undefined, options = {}) => {
|
194 | const {
|
195 | ref,
|
196 | viewMode: viewModeFromArgs
|
197 | } = options;
|
198 | const {
|
199 | viewMode: viewModeFromState = 'story',
|
200 | storyId,
|
201 | storiesHash,
|
202 | refs
|
203 | } = store.getState();
|
204 | const hash = ref ? refs[ref].stories : storiesHash;
|
205 | const kindSlug = storyId === null || storyId === void 0 ? void 0 : storyId.split('--', 2)[0];
|
206 |
|
207 | if (!story) {
|
208 | const s = kindOrId ? hash[kindOrId] || hash[sanitize(kindOrId)] : hash[kindSlug];
|
209 |
|
210 | const id = s ? s.children ? s.children[0] : s.id : kindOrId;
|
211 | let viewMode = s && !isRoot(s) && (viewModeFromArgs || s.parameters.viewMode) ? s.parameters.viewMode : viewModeFromState;
|
212 |
|
213 |
|
214 | if (['settings', 'about', 'release'].includes(viewMode)) {
|
215 | viewMode = 'story';
|
216 | }
|
217 |
|
218 | const p = s && s.refId ? `/${viewMode}/${s.refId}_${id}` : `/${viewMode}/${id}`;
|
219 | navigate(p);
|
220 | } else if (!kindOrId) {
|
221 |
|
222 | const id = toId(kindSlug, story);
|
223 | api.selectStory(id, undefined, options);
|
224 | } else {
|
225 | const id = ref ? `${ref}_${toId(kindOrId, story)}` : toId(kindOrId, story);
|
226 |
|
227 | if (hash[id]) {
|
228 | api.selectStory(id, undefined, options);
|
229 | } else {
|
230 |
|
231 | const k = hash[sanitize(kindOrId)];
|
232 |
|
233 | if (k && k.children) {
|
234 | const foundId = k.children.find(childId => hash[childId].name === story);
|
235 |
|
236 | if (foundId) {
|
237 | api.selectStory(foundId, undefined, options);
|
238 | }
|
239 | }
|
240 | }
|
241 | }
|
242 | },
|
243 |
|
244 | findLeafStoryId(storiesHash, storyId) {
|
245 | if (storiesHash[storyId].isLeaf) {
|
246 | return storyId;
|
247 | }
|
248 |
|
249 | const childStoryId = storiesHash[storyId].children[0];
|
250 | return api.findLeafStoryId(storiesHash, childStoryId);
|
251 | },
|
252 |
|
253 | findSiblingStoryId(storyId, hash, direction, toSiblingGroup) {
|
254 | if (toSiblingGroup) {
|
255 | const lookupList = getComponentLookupList(hash);
|
256 | const index = lookupList.findIndex(i => i.includes(storyId));
|
257 |
|
258 | if (index === lookupList.length - 1 && direction > 0) {
|
259 | return;
|
260 | }
|
261 |
|
262 | if (index === 0 && direction < 0) {
|
263 | return;
|
264 | }
|
265 |
|
266 | if (lookupList[index + direction]) {
|
267 |
|
268 | return lookupList[index + direction][0];
|
269 | }
|
270 |
|
271 | return;
|
272 | }
|
273 |
|
274 | const lookupList = getStoriesLookupList(hash);
|
275 | const index = lookupList.indexOf(storyId);
|
276 |
|
277 | if (index === lookupList.length - 1 && direction > 0) {
|
278 | return;
|
279 | }
|
280 |
|
281 | if (index === 0 && direction < 0) {
|
282 | return;
|
283 | }
|
284 |
|
285 |
|
286 | return lookupList[index + direction];
|
287 | },
|
288 |
|
289 | updateStoryArgs: (story, updatedArgs) => {
|
290 | const {
|
291 | id: storyId,
|
292 | refId
|
293 | } = story;
|
294 | fullAPI.emit(UPDATE_STORY_ARGS, {
|
295 | storyId,
|
296 | updatedArgs,
|
297 | options: {
|
298 | target: refId ? `storybook-ref-${refId}` : 'storybook-preview-iframe'
|
299 | }
|
300 | });
|
301 | },
|
302 | resetStoryArgs: (story, argNames) => {
|
303 | const {
|
304 | id: storyId,
|
305 | refId
|
306 | } = story;
|
307 | fullAPI.emit(RESET_STORY_ARGS, {
|
308 | storyId,
|
309 | argNames,
|
310 | options: {
|
311 | target: refId ? `storybook-ref-${refId}` : 'storybook-preview-iframe'
|
312 | }
|
313 | });
|
314 | },
|
315 | fetchStoryList: async () => {
|
316 | try {
|
317 | const result = await fetch(STORY_INDEX_PATH);
|
318 | if (result.status !== 200) throw new Error(await result.text());
|
319 | const storyIndex = await result.json();
|
320 |
|
321 | if (storyIndex.v !== 3) {
|
322 | logger.warn(`Skipping story index with version v${storyIndex.v}, awaiting SET_STORIES.`);
|
323 | return;
|
324 | }
|
325 |
|
326 | await fullAPI.setStoryList(storyIndex);
|
327 | } catch (err) {
|
328 | store.setState({
|
329 | storiesConfigured: true,
|
330 | storiesFailed: err
|
331 | });
|
332 | }
|
333 | },
|
334 | setStoryList: async storyIndex => {
|
335 | const hash = transformStoryIndexToStoriesHash(storyIndex, {
|
336 | provider
|
337 | });
|
338 | await store.setState({
|
339 | storiesHash: hash,
|
340 | storiesConfigured: true,
|
341 | storiesFailed: null
|
342 | });
|
343 | },
|
344 | updateStory: async (storyId, update, ref) => {
|
345 | if (!ref) {
|
346 | const {
|
347 | storiesHash
|
348 | } = store.getState();
|
349 | storiesHash[storyId] = Object.assign({}, storiesHash[storyId], update);
|
350 | await store.setState({
|
351 | storiesHash
|
352 | });
|
353 | } else {
|
354 | const {
|
355 | id: refId,
|
356 | stories
|
357 | } = ref;
|
358 | stories[storyId] = Object.assign({}, stories[storyId], update);
|
359 | await fullAPI.updateRef(refId, {
|
360 | stories
|
361 | });
|
362 | }
|
363 | }
|
364 | };
|
365 |
|
366 | const initModule = async () => {
|
367 |
|
368 |
|
369 | fullAPI.on(STORY_SPECIFIED, function handler({
|
370 | storyId,
|
371 | viewMode
|
372 | }) {
|
373 | const {
|
374 | sourceType
|
375 | } = getEventMetadata(this, fullAPI);
|
376 | if (fullAPI.isSettingsScreenActive()) return;
|
377 |
|
378 | if (sourceType === 'local') {
|
379 |
|
380 |
|
381 | const state = store.getState();
|
382 |
|
383 | if (state.storyId !== storyId || state.viewMode !== viewMode) {
|
384 | navigate(`/${viewMode}/${storyId}`);
|
385 | }
|
386 | }
|
387 | });
|
388 | fullAPI.on(STORY_CHANGED, function handler() {
|
389 | const {
|
390 | sourceType
|
391 | } = getEventMetadata(this, fullAPI);
|
392 |
|
393 | if (sourceType === 'local') {
|
394 | const options = fullAPI.getCurrentParameter('options');
|
395 |
|
396 | if (options) {
|
397 | checkDeprecatedOptionParameters(options);
|
398 | fullAPI.setOptions(options);
|
399 | }
|
400 | }
|
401 | });
|
402 | fullAPI.on(STORY_PREPARED, function handler(_ref) {
|
403 | let {
|
404 | id
|
405 | } = _ref,
|
406 | update = _objectWithoutPropertiesLoose(_ref, _excluded);
|
407 |
|
408 | const {
|
409 | ref,
|
410 | sourceType
|
411 | } = getEventMetadata(this, fullAPI);
|
412 | fullAPI.updateStory(id, Object.assign({}, update, {
|
413 | prepared: true
|
414 | }), ref);
|
415 |
|
416 | if (!ref) {
|
417 | if (!store.getState().hasCalledSetOptions) {
|
418 | const {
|
419 | options
|
420 | } = update.parameters;
|
421 | checkDeprecatedOptionParameters(options);
|
422 | fullAPI.setOptions(options);
|
423 | store.setState({
|
424 | hasCalledSetOptions: true
|
425 | });
|
426 | }
|
427 | } else {
|
428 | fullAPI.updateRef(ref.id, {
|
429 | ready: true
|
430 | });
|
431 | }
|
432 |
|
433 | if (sourceType === 'local') {
|
434 | const {
|
435 | storyId,
|
436 | storiesHash
|
437 | } = store.getState();
|
438 |
|
439 | const toBePreloaded = Array.from(new Set([api.findSiblingStoryId(storyId, storiesHash, 1, true), api.findSiblingStoryId(storyId, storiesHash, -1, true)])).filter(Boolean);
|
440 | fullAPI.emit(PRELOAD_STORIES, toBePreloaded);
|
441 | }
|
442 | });
|
443 | fullAPI.on(SET_STORIES, function handler(data) {
|
444 | const {
|
445 | ref
|
446 | } = getEventMetadata(this, fullAPI);
|
447 | const stories = data.v ? denormalizeStoryParameters(data) : data.stories;
|
448 |
|
449 | if (!ref) {
|
450 | if (!data.v) {
|
451 | throw new Error('Unexpected legacy SET_STORIES event from local source');
|
452 | }
|
453 |
|
454 | fullAPI.setStories(stories);
|
455 | const options = fullAPI.getCurrentParameter('options');
|
456 | checkDeprecatedOptionParameters(options);
|
457 | fullAPI.setOptions(options);
|
458 | } else {
|
459 | fullAPI.setRef(ref.id, Object.assign({}, ref, data, {
|
460 | stories
|
461 | }), true);
|
462 | }
|
463 | });
|
464 | fullAPI.on(SELECT_STORY, function handler(_ref2) {
|
465 | let {
|
466 | kind,
|
467 | story,
|
468 | storyId
|
469 | } = _ref2,
|
470 | rest = _objectWithoutPropertiesLoose(_ref2, _excluded2);
|
471 |
|
472 | const {
|
473 | ref
|
474 | } = getEventMetadata(this, fullAPI);
|
475 |
|
476 | if (!ref) {
|
477 | fullAPI.selectStory(storyId || kind, story, rest);
|
478 | } else {
|
479 | fullAPI.selectStory(storyId || kind, story, Object.assign({}, rest, {
|
480 | ref: ref.id
|
481 | }));
|
482 | }
|
483 | });
|
484 | fullAPI.on(STORY_ARGS_UPDATED, function handleStoryArgsUpdated({
|
485 | storyId,
|
486 | args
|
487 | }) {
|
488 | const {
|
489 | ref
|
490 | } = getEventMetadata(this, fullAPI);
|
491 | fullAPI.updateStory(storyId, {
|
492 | args
|
493 | }, ref);
|
494 | });
|
495 | fullAPI.on(CONFIG_ERROR, function handleConfigError(err) {
|
496 | store.setState({
|
497 | storiesConfigured: true,
|
498 | storiesFailed: err
|
499 | });
|
500 | });
|
501 |
|
502 | if (FEATURES !== null && FEATURES !== void 0 && FEATURES.storyStoreV7) {
|
503 | var _provider$serverChann;
|
504 |
|
505 | (_provider$serverChann = provider.serverChannel) === null || _provider$serverChann === void 0 ? void 0 : _provider$serverChann.on(STORY_INDEX_INVALIDATED, () => fullAPI.fetchStoryList());
|
506 | await fullAPI.fetchStoryList();
|
507 | }
|
508 | };
|
509 |
|
510 | return {
|
511 | api,
|
512 | state: {
|
513 | storiesHash: {},
|
514 | storyId: initialStoryId,
|
515 | viewMode: initialViewMode,
|
516 | storiesConfigured: false,
|
517 | hasCalledSetOptions: false
|
518 | },
|
519 | init: initModule
|
520 | };
|
521 | }; |
\ | No newline at end of file |