UNPKG

25.2 kBJavaScriptView Raw
1import "core-js/modules/es.symbol.js";
2var _excluded = ["id"],
3 _excluded2 = ["kind", "story", "storyId"];
4
5function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }
6
7function _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; }
8
9import "regenerator-runtime/runtime.js";
10
11function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
12
13function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
14
15import "core-js/modules/es.object.to-string.js";
16import "core-js/modules/es.promise.js";
17import "core-js/modules/web.dom-collections.for-each.js";
18import "core-js/modules/es.object.keys.js";
19import "core-js/modules/es.array.find.js";
20import "core-js/modules/es.regexp.exec.js";
21import "core-js/modules/es.string.split.js";
22import "core-js/modules/es.array.includes.js";
23import "core-js/modules/es.array.concat.js";
24import "core-js/modules/es.function.name.js";
25import "core-js/modules/es.array.find-index.js";
26import "core-js/modules/es.string.includes.js";
27import "core-js/modules/es.object.assign.js";
28import "core-js/modules/es.array.filter.js";
29import "core-js/modules/es.array.from.js";
30import "core-js/modules/es.string.iterator.js";
31import "core-js/modules/es.array.iterator.js";
32import "core-js/modules/es.set.js";
33import "core-js/modules/web.dom-collections.iterator.js";
34import global from 'global';
35import { toId, sanitize } from '@storybook/csf';
36import { 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';
37import deprecate from 'util-deprecate';
38import { logger } from '@storybook/client-logger';
39import { getEventMetadata } from '../lib/events';
40import { denormalizeStoryParameters, transformStoriesRawToStoriesHash, isStory, isRoot, transformStoryIndexToStoriesHash, getComponentLookupList, getStoriesLookupList } from '../lib/stories';
41var DOCS_MODE = global.DOCS_MODE,
42 FEATURES = global.FEATURES,
43 fetch = global.fetch;
44var STORY_INDEX_PATH = './stories.json';
45var deprecatedOptionsParameterWarnings = ['enableShortcuts', 'theme', 'showRoots'].reduce(function (acc, option) {
46 acc[option] = deprecate(function () {}, "parameters.options.".concat(option, " is deprecated and will be removed in Storybook 7.0.\nTo change this setting, use `addons.setConfig`. See https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#deprecated-immutable-options-parameters\n "));
47 return acc;
48}, {});
49
50function checkDeprecatedOptionParameters(options) {
51 if (!options) {
52 return;
53 }
54
55 Object.keys(options).forEach(function (option) {
56 if (deprecatedOptionsParameterWarnings[option]) {
57 deprecatedOptionsParameterWarnings[option]();
58 }
59 });
60}
61
62export var init = function init(_ref) {
63 var fullAPI = _ref.fullAPI,
64 store = _ref.store,
65 navigate = _ref.navigate,
66 provider = _ref.provider,
67 initialStoryId = _ref.storyId,
68 initialViewMode = _ref.viewMode;
69 var api = {
70 storyId: toId,
71 getData: function getData(storyId, refId) {
72 var result = api.resolveStory(storyId, refId);
73 return isRoot(result) ? undefined : result;
74 },
75 isPrepared: function isPrepared(storyId, refId) {
76 var data = api.getData(storyId, refId);
77
78 if (data.isLeaf) {
79 return data.prepared;
80 } // Groups are always prepared :shrug:
81
82
83 return true;
84 },
85 resolveStory: function resolveStory(storyId, refId) {
86 var _store$getState = store.getState(),
87 refs = _store$getState.refs,
88 storiesHash = _store$getState.storiesHash;
89
90 if (refId) {
91 return refs[refId].stories ? refs[refId].stories[storyId] : undefined;
92 }
93
94 return storiesHash ? storiesHash[storyId] : undefined;
95 },
96 getCurrentStoryData: function getCurrentStoryData() {
97 var _store$getState2 = store.getState(),
98 storyId = _store$getState2.storyId,
99 refId = _store$getState2.refId;
100
101 return api.getData(storyId, refId);
102 },
103 getParameters: function getParameters(storyIdOrCombo, parameterName) {
104 var _ref2 = typeof storyIdOrCombo === 'string' ? {
105 storyId: storyIdOrCombo,
106 refId: undefined
107 } : storyIdOrCombo,
108 storyId = _ref2.storyId,
109 refId = _ref2.refId;
110
111 var data = api.getData(storyId, refId);
112
113 if (isStory(data)) {
114 var parameters = data.parameters;
115
116 if (parameters) {
117 return parameterName ? parameters[parameterName] : parameters;
118 }
119
120 return {};
121 }
122
123 return null;
124 },
125 getCurrentParameter: function getCurrentParameter(parameterName) {
126 var _store$getState3 = store.getState(),
127 storyId = _store$getState3.storyId,
128 refId = _store$getState3.refId;
129
130 var parameters = api.getParameters({
131 storyId: storyId,
132 refId: refId
133 }, parameterName); // FIXME Returning falsey parameters breaks a bunch of toolbars code,
134 // so this strange logic needs to be here until various client code is updated.
135
136 return parameters || undefined;
137 },
138 jumpToComponent: function jumpToComponent(direction) {
139 var _store$getState4 = store.getState(),
140 storiesHash = _store$getState4.storiesHash,
141 storyId = _store$getState4.storyId,
142 refs = _store$getState4.refs,
143 refId = _store$getState4.refId;
144
145 var story = api.getData(storyId, refId); // cannot navigate when there's no current selection
146
147 if (!story) {
148 return;
149 }
150
151 var hash = refId ? refs[refId].stories || {} : storiesHash;
152 var result = api.findSiblingStoryId(storyId, hash, direction, true);
153
154 if (result) {
155 api.selectStory(result, undefined, {
156 ref: refId
157 });
158 }
159 },
160 jumpToStory: function jumpToStory(direction) {
161 var _store$getState5 = store.getState(),
162 storiesHash = _store$getState5.storiesHash,
163 storyId = _store$getState5.storyId,
164 refs = _store$getState5.refs,
165 refId = _store$getState5.refId;
166
167 var story = api.getData(storyId, refId);
168
169 if (DOCS_MODE) {
170 api.jumpToComponent(direction);
171 return;
172 } // cannot navigate when there's no current selection
173
174
175 if (!story) {
176 return;
177 }
178
179 var hash = story.refId ? refs[story.refId].stories : storiesHash;
180 var result = api.findSiblingStoryId(storyId, hash, direction, false);
181
182 if (result) {
183 api.selectStory(result, undefined, {
184 ref: refId
185 });
186 }
187 },
188 setStories: function () {
189 var _setStories = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee(input, error) {
190 var hash;
191 return regeneratorRuntime.wrap(function _callee$(_context) {
192 while (1) {
193 switch (_context.prev = _context.next) {
194 case 0:
195 // Now create storiesHash by reordering the above by group
196 hash = transformStoriesRawToStoriesHash(input, {
197 provider: provider
198 });
199 _context.next = 3;
200 return store.setState({
201 storiesHash: hash,
202 storiesConfigured: true,
203 storiesFailed: error
204 });
205
206 case 3:
207 case "end":
208 return _context.stop();
209 }
210 }
211 }, _callee);
212 }));
213
214 function setStories(_x, _x2) {
215 return _setStories.apply(this, arguments);
216 }
217
218 return setStories;
219 }(),
220 selectFirstStory: function selectFirstStory() {
221 var _store$getState6 = store.getState(),
222 storiesHash = _store$getState6.storiesHash;
223
224 var firstStory = Object.keys(storiesHash).find(function (k) {
225 return !(storiesHash[k].children || Array.isArray(storiesHash[k]));
226 });
227
228 if (firstStory) {
229 api.selectStory(firstStory);
230 return;
231 }
232
233 navigate('/');
234 },
235 selectStory: function selectStory() {
236 var kindOrId = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : undefined;
237 var story = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : undefined;
238 var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
239 var ref = options.ref,
240 viewModeFromArgs = options.viewMode;
241
242 var _store$getState7 = store.getState(),
243 _store$getState7$view = _store$getState7.viewMode,
244 viewModeFromState = _store$getState7$view === void 0 ? 'story' : _store$getState7$view,
245 storyId = _store$getState7.storyId,
246 storiesHash = _store$getState7.storiesHash,
247 refs = _store$getState7.refs;
248
249 var hash = ref ? refs[ref].stories : storiesHash;
250 var kindSlug = storyId === null || storyId === void 0 ? void 0 : storyId.split('--', 2)[0];
251
252 if (!story) {
253 var s = kindOrId ? hash[kindOrId] || hash[sanitize(kindOrId)] : hash[kindSlug]; // eslint-disable-next-line no-nested-ternary
254
255 var id = s ? s.children ? s.children[0] : s.id : kindOrId;
256 var viewMode = s && !isRoot(s) && (viewModeFromArgs || s.parameters.viewMode) ? s.parameters.viewMode : viewModeFromState; // Some viewModes are not story-specific, and we should reset viewMode
257 // to 'story' if one of those is active when navigating to another story
258
259 if (['settings', 'about', 'release'].includes(viewMode)) {
260 viewMode = 'story';
261 }
262
263 var p = s && s.refId ? "/".concat(viewMode, "/").concat(s.refId, "_").concat(id) : "/".concat(viewMode, "/").concat(id);
264 navigate(p);
265 } else if (!kindOrId) {
266 // This is a slugified version of the kind, but that's OK, our toId function is idempotent
267 var _id = toId(kindSlug, story);
268
269 api.selectStory(_id, undefined, options);
270 } else {
271 var _id2 = ref ? "".concat(ref, "_").concat(toId(kindOrId, story)) : toId(kindOrId, story);
272
273 if (hash[_id2]) {
274 api.selectStory(_id2, undefined, options);
275 } else {
276 // Support legacy API with component permalinks, where kind is `x/y` but permalink is 'z'
277 var _k = hash[sanitize(kindOrId)];
278
279 if (_k && _k.children) {
280 var foundId = _k.children.find(function (childId) {
281 return hash[childId].name === story;
282 });
283
284 if (foundId) {
285 api.selectStory(foundId, undefined, options);
286 }
287 }
288 }
289 }
290 },
291 findLeafStoryId: function findLeafStoryId(storiesHash, storyId) {
292 if (storiesHash[storyId].isLeaf) {
293 return storyId;
294 }
295
296 var childStoryId = storiesHash[storyId].children[0];
297 return api.findLeafStoryId(storiesHash, childStoryId);
298 },
299 findSiblingStoryId: function findSiblingStoryId(storyId, hash, direction, toSiblingGroup) {
300 if (toSiblingGroup) {
301 var _lookupList = getComponentLookupList(hash);
302
303 var _index = _lookupList.findIndex(function (i) {
304 return i.includes(storyId);
305 }); // cannot navigate beyond fist or last
306
307
308 if (_index === _lookupList.length - 1 && direction > 0) {
309 return;
310 }
311
312 if (_index === 0 && direction < 0) {
313 return;
314 }
315
316 if (_lookupList[_index + direction]) {
317 // eslint-disable-next-line consistent-return
318 return _lookupList[_index + direction][0];
319 }
320
321 return;
322 }
323
324 var lookupList = getStoriesLookupList(hash);
325 var index = lookupList.indexOf(storyId); // cannot navigate beyond fist or last
326
327 if (index === lookupList.length - 1 && direction > 0) {
328 return;
329 }
330
331 if (index === 0 && direction < 0) {
332 return;
333 } // eslint-disable-next-line consistent-return
334
335
336 return lookupList[index + direction];
337 },
338 updateStoryArgs: function updateStoryArgs(story, updatedArgs) {
339 var storyId = story.id,
340 refId = story.refId;
341 fullAPI.emit(UPDATE_STORY_ARGS, {
342 storyId: storyId,
343 updatedArgs: updatedArgs,
344 options: {
345 target: refId ? "storybook-ref-".concat(refId) : 'storybook-preview-iframe'
346 }
347 });
348 },
349 resetStoryArgs: function resetStoryArgs(story, argNames) {
350 var storyId = story.id,
351 refId = story.refId;
352 fullAPI.emit(RESET_STORY_ARGS, {
353 storyId: storyId,
354 argNames: argNames,
355 options: {
356 target: refId ? "storybook-ref-".concat(refId) : 'storybook-preview-iframe'
357 }
358 });
359 },
360 fetchStoryList: function () {
361 var _fetchStoryList = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee2() {
362 var result, storyIndex;
363 return regeneratorRuntime.wrap(function _callee2$(_context2) {
364 while (1) {
365 switch (_context2.prev = _context2.next) {
366 case 0:
367 _context2.prev = 0;
368 _context2.next = 3;
369 return fetch(STORY_INDEX_PATH);
370
371 case 3:
372 result = _context2.sent;
373
374 if (!(result.status !== 200)) {
375 _context2.next = 10;
376 break;
377 }
378
379 _context2.t0 = Error;
380 _context2.next = 8;
381 return result.text();
382
383 case 8:
384 _context2.t1 = _context2.sent;
385 throw new _context2.t0(_context2.t1);
386
387 case 10:
388 _context2.next = 12;
389 return result.json();
390
391 case 12:
392 storyIndex = _context2.sent;
393
394 if (!(storyIndex.v !== 3)) {
395 _context2.next = 16;
396 break;
397 }
398
399 logger.warn("Skipping story index with version v".concat(storyIndex.v, ", awaiting SET_STORIES."));
400 return _context2.abrupt("return");
401
402 case 16:
403 _context2.next = 18;
404 return fullAPI.setStoryList(storyIndex);
405
406 case 18:
407 _context2.next = 23;
408 break;
409
410 case 20:
411 _context2.prev = 20;
412 _context2.t2 = _context2["catch"](0);
413 store.setState({
414 storiesConfigured: true,
415 storiesFailed: _context2.t2
416 });
417
418 case 23:
419 case "end":
420 return _context2.stop();
421 }
422 }
423 }, _callee2, null, [[0, 20]]);
424 }));
425
426 function fetchStoryList() {
427 return _fetchStoryList.apply(this, arguments);
428 }
429
430 return fetchStoryList;
431 }(),
432 setStoryList: function () {
433 var _setStoryList = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee3(storyIndex) {
434 var hash;
435 return regeneratorRuntime.wrap(function _callee3$(_context3) {
436 while (1) {
437 switch (_context3.prev = _context3.next) {
438 case 0:
439 hash = transformStoryIndexToStoriesHash(storyIndex, {
440 provider: provider
441 });
442 _context3.next = 3;
443 return store.setState({
444 storiesHash: hash,
445 storiesConfigured: true,
446 storiesFailed: null
447 });
448
449 case 3:
450 case "end":
451 return _context3.stop();
452 }
453 }
454 }, _callee3);
455 }));
456
457 function setStoryList(_x3) {
458 return _setStoryList.apply(this, arguments);
459 }
460
461 return setStoryList;
462 }(),
463 updateStory: function () {
464 var _updateStory = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee4(storyId, update, ref) {
465 var _store$getState8, storiesHash, _refId, _stories;
466
467 return regeneratorRuntime.wrap(function _callee4$(_context4) {
468 while (1) {
469 switch (_context4.prev = _context4.next) {
470 case 0:
471 if (ref) {
472 _context4.next = 7;
473 break;
474 }
475
476 _store$getState8 = store.getState(), storiesHash = _store$getState8.storiesHash;
477 storiesHash[storyId] = Object.assign({}, storiesHash[storyId], update);
478 _context4.next = 5;
479 return store.setState({
480 storiesHash: storiesHash
481 });
482
483 case 5:
484 _context4.next = 11;
485 break;
486
487 case 7:
488 _refId = ref.id, _stories = ref.stories;
489 _stories[storyId] = Object.assign({}, _stories[storyId], update);
490 _context4.next = 11;
491 return fullAPI.updateRef(_refId, {
492 stories: _stories
493 });
494
495 case 11:
496 case "end":
497 return _context4.stop();
498 }
499 }
500 }, _callee4);
501 }));
502
503 function updateStory(_x4, _x5, _x6) {
504 return _updateStory.apply(this, arguments);
505 }
506
507 return updateStory;
508 }()
509 };
510
511 var initModule = /*#__PURE__*/function () {
512 var _ref3 = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee5() {
513 var _provider$serverChann;
514
515 return regeneratorRuntime.wrap(function _callee5$(_context5) {
516 while (1) {
517 switch (_context5.prev = _context5.next) {
518 case 0:
519 // On initial load, the local iframe will select the first story (or other "selection specifier")
520 // and emit STORY_SPECIFIED with the id. We need to ensure we respond to this change.
521 fullAPI.on(STORY_SPECIFIED, function handler(_ref4) {
522 var storyId = _ref4.storyId,
523 viewMode = _ref4.viewMode;
524
525 var _getEventMetadata = getEventMetadata(this, fullAPI),
526 sourceType = _getEventMetadata.sourceType;
527
528 if (fullAPI.isSettingsScreenActive()) return;
529
530 if (sourceType === 'local') {
531 // Special case -- if we are already at the story being specified (i.e. the user started at a given story),
532 // we don't need to change URL. See https://github.com/storybookjs/storybook/issues/11677
533 var state = store.getState();
534
535 if (state.storyId !== storyId || state.viewMode !== viewMode) {
536 navigate("/".concat(viewMode, "/").concat(storyId));
537 }
538 }
539 });
540 fullAPI.on(STORY_CHANGED, function handler() {
541 var _getEventMetadata2 = getEventMetadata(this, fullAPI),
542 sourceType = _getEventMetadata2.sourceType;
543
544 if (sourceType === 'local') {
545 var options = fullAPI.getCurrentParameter('options');
546
547 if (options) {
548 checkDeprecatedOptionParameters(options);
549 fullAPI.setOptions(options);
550 }
551 }
552 });
553 fullAPI.on(STORY_PREPARED, function handler(_ref5) {
554 var id = _ref5.id,
555 update = _objectWithoutProperties(_ref5, _excluded);
556
557 var _getEventMetadata3 = getEventMetadata(this, fullAPI),
558 ref = _getEventMetadata3.ref,
559 sourceType = _getEventMetadata3.sourceType;
560
561 fullAPI.updateStory(id, Object.assign({}, update, {
562 prepared: true
563 }), ref);
564
565 if (!ref) {
566 if (!store.getState().hasCalledSetOptions) {
567 var options = update.parameters.options;
568 checkDeprecatedOptionParameters(options);
569 fullAPI.setOptions(options);
570 store.setState({
571 hasCalledSetOptions: true
572 });
573 }
574 } else {
575 fullAPI.updateRef(ref.id, {
576 ready: true
577 });
578 }
579
580 if (sourceType === 'local') {
581 var _store$getState9 = store.getState(),
582 _storyId = _store$getState9.storyId,
583 storiesHash = _store$getState9.storiesHash; // create a list of related stories to be preloaded
584
585
586 var toBePreloaded = Array.from(new Set([api.findSiblingStoryId(_storyId, storiesHash, 1, true), api.findSiblingStoryId(_storyId, storiesHash, -1, true)])).filter(Boolean);
587 fullAPI.emit(PRELOAD_STORIES, toBePreloaded);
588 }
589 });
590 fullAPI.on(SET_STORIES, function handler(data) {
591 var _getEventMetadata4 = getEventMetadata(this, fullAPI),
592 ref = _getEventMetadata4.ref;
593
594 var stories = data.v ? denormalizeStoryParameters(data) : data.stories;
595
596 if (!ref) {
597 if (!data.v) {
598 throw new Error('Unexpected legacy SET_STORIES event from local source');
599 }
600
601 fullAPI.setStories(stories);
602 var options = fullAPI.getCurrentParameter('options');
603 checkDeprecatedOptionParameters(options);
604 fullAPI.setOptions(options);
605 } else {
606 fullAPI.setRef(ref.id, Object.assign({}, ref, data, {
607 stories: stories
608 }), true);
609 }
610 });
611 fullAPI.on(SELECT_STORY, function handler(_ref6) {
612 var kind = _ref6.kind,
613 story = _ref6.story,
614 storyId = _ref6.storyId,
615 rest = _objectWithoutProperties(_ref6, _excluded2);
616
617 var _getEventMetadata5 = getEventMetadata(this, fullAPI),
618 ref = _getEventMetadata5.ref;
619
620 if (!ref) {
621 fullAPI.selectStory(storyId || kind, story, rest);
622 } else {
623 fullAPI.selectStory(storyId || kind, story, Object.assign({}, rest, {
624 ref: ref.id
625 }));
626 }
627 });
628 fullAPI.on(STORY_ARGS_UPDATED, function handleStoryArgsUpdated(_ref7) {
629 var storyId = _ref7.storyId,
630 args = _ref7.args;
631
632 var _getEventMetadata6 = getEventMetadata(this, fullAPI),
633 ref = _getEventMetadata6.ref;
634
635 fullAPI.updateStory(storyId, {
636 args: args
637 }, ref);
638 });
639 fullAPI.on(CONFIG_ERROR, function handleConfigError(err) {
640 store.setState({
641 storiesConfigured: true,
642 storiesFailed: err
643 });
644 });
645
646 if (!(FEATURES !== null && FEATURES !== void 0 && FEATURES.storyStoreV7)) {
647 _context5.next = 11;
648 break;
649 }
650
651 (_provider$serverChann = provider.serverChannel) === null || _provider$serverChann === void 0 ? void 0 : _provider$serverChann.on(STORY_INDEX_INVALIDATED, function () {
652 return fullAPI.fetchStoryList();
653 });
654 _context5.next = 11;
655 return fullAPI.fetchStoryList();
656
657 case 11:
658 case "end":
659 return _context5.stop();
660 }
661 }
662 }, _callee5);
663 }));
664
665 return function initModule() {
666 return _ref3.apply(this, arguments);
667 };
668 }();
669
670 return {
671 api: api,
672 state: {
673 storiesHash: {},
674 storyId: initialStoryId,
675 viewMode: initialViewMode,
676 storiesConfigured: false,
677 hasCalledSetOptions: false
678 },
679 init: initModule
680 };
681};
\No newline at end of file