1 | const _excluded = ["full", "panel", "nav", "shortcuts", "addonPanel", "tabs", "addons", "panelRight", "stories", "selectedKind", "selectedStory", "path"],
|
2 | _excluded2 = ["store", "navigate", "state", "provider", "fullAPI"];
|
3 | import "core-js/modules/es.array.reduce.js";
|
4 |
|
5 | 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; }
|
6 |
|
7 | import { once } from '@storybook/client-logger';
|
8 | import { NAVIGATE_URL, STORY_ARGS_UPDATED, SET_CURRENT_STORY, GLOBALS_UPDATED, UPDATE_QUERY_PARAMS } from '@storybook/core-events';
|
9 | import { queryFromLocation, buildArgsParam } from '@storybook/router';
|
10 | import { toId, sanitize } from '@storybook/csf';
|
11 | import deepEqual from 'fast-deep-equal';
|
12 | import global from 'global';
|
13 | import dedent from 'ts-dedent';
|
14 | import { isStory } from '../lib/stories';
|
15 | const {
|
16 | window: globalWindow
|
17 | } = global;
|
18 |
|
19 | const parseBoolean = value => {
|
20 | if (value === 'true' || value === '1') return true;
|
21 | if (value === 'false' || value === '0') return false;
|
22 | return undefined;
|
23 | };
|
24 |
|
25 |
|
26 |
|
27 |
|
28 |
|
29 |
|
30 |
|
31 |
|
32 |
|
33 |
|
34 | let prevParams;
|
35 |
|
36 | const initialUrlSupport = ({
|
37 | state: {
|
38 | location,
|
39 | path,
|
40 | viewMode,
|
41 | storyId: storyIdFromUrl
|
42 | },
|
43 | singleStory
|
44 | }) => {
|
45 | const _queryFromLocation = queryFromLocation(location),
|
46 | {
|
47 | full,
|
48 | panel,
|
49 | nav,
|
50 | shortcuts,
|
51 | addonPanel,
|
52 | tabs,
|
53 | addons,
|
54 |
|
55 | panelRight,
|
56 |
|
57 | stories,
|
58 |
|
59 | selectedKind,
|
60 |
|
61 | selectedStory
|
62 |
|
63 | } = _queryFromLocation,
|
64 | otherParams = _objectWithoutPropertiesLoose(_queryFromLocation, _excluded);
|
65 |
|
66 | const layout = {
|
67 | isFullscreen: parseBoolean(full),
|
68 | showNav: !singleStory && parseBoolean(nav),
|
69 | showPanel: parseBoolean(panel),
|
70 | panelPosition: ['right', 'bottom'].includes(panel) ? panel : undefined,
|
71 | showTabs: parseBoolean(tabs)
|
72 | };
|
73 | const ui = {
|
74 | enableShortcuts: parseBoolean(shortcuts)
|
75 | };
|
76 | const selectedPanel = addonPanel || undefined;
|
77 |
|
78 | if (addons === '0') {
|
79 | once.warn(dedent`
|
80 | The 'addons' query param is deprecated and will be removed in Storybook 7.0. Use 'panel=false' instead.
|
81 |
|
82 | More info: https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#deprecated-layout-url-params
|
83 | `);
|
84 | layout.showPanel = false;
|
85 | }
|
86 |
|
87 |
|
88 | if (panelRight === '1') {
|
89 | once.warn(dedent`
|
90 | The 'panelRight' query param is deprecated and will be removed in Storybook 7.0. Use 'panel=right' instead.
|
91 |
|
92 | More info: https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#deprecated-layout-url-params
|
93 | `);
|
94 | layout.panelPosition = 'right';
|
95 | }
|
96 |
|
97 |
|
98 | if (stories === '0') {
|
99 | once.warn(dedent`
|
100 | The 'stories' query param is deprecated and will be removed in Storybook 7.0. Use 'nav=false' instead.
|
101 |
|
102 | More info: https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#deprecated-layout-url-params
|
103 | `);
|
104 | layout.showNav = false;
|
105 | }
|
106 |
|
107 |
|
108 |
|
109 |
|
110 | let storyId = storyIdFromUrl;
|
111 |
|
112 | if (!storyId && selectedKind) {
|
113 | once.warn(dedent`
|
114 | The 'selectedKind' and 'selectedStory' query params are deprecated and will be removed in Storybook 7.0. Use 'path' instead.
|
115 |
|
116 | More info: https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#deprecated-layout-url-params
|
117 | `);
|
118 | storyId = selectedStory ? toId(selectedKind, selectedStory) : sanitize(selectedKind);
|
119 | }
|
120 |
|
121 |
|
122 | const customQueryParams = deepEqual(prevParams, otherParams) ? prevParams : otherParams;
|
123 | prevParams = customQueryParams;
|
124 | return {
|
125 | viewMode,
|
126 | layout,
|
127 | ui,
|
128 | selectedPanel,
|
129 | location,
|
130 | path,
|
131 | customQueryParams,
|
132 | storyId
|
133 | };
|
134 | };
|
135 |
|
136 | export const init = _ref => {
|
137 | let {
|
138 | store,
|
139 | navigate,
|
140 | state,
|
141 | provider,
|
142 | fullAPI
|
143 | } = _ref,
|
144 | rest = _objectWithoutPropertiesLoose(_ref, _excluded2);
|
145 |
|
146 | const navigateTo = (path, queryParams = {}, options = {}) => {
|
147 | const params = Object.entries(queryParams).filter(([, v]) => v).sort(([a], [b]) => a < b ? -1 : 1).map(([k, v]) => `${k}=${v}`);
|
148 | const to = [path, ...params].join('&');
|
149 | return navigate(to, options);
|
150 | };
|
151 |
|
152 | const api = {
|
153 | getQueryParam(key) {
|
154 | const {
|
155 | customQueryParams
|
156 | } = store.getState();
|
157 | return customQueryParams ? customQueryParams[key] : undefined;
|
158 | },
|
159 |
|
160 | getUrlState() {
|
161 | const {
|
162 | path,
|
163 | customQueryParams,
|
164 | storyId,
|
165 | url,
|
166 | viewMode
|
167 | } = store.getState();
|
168 | return {
|
169 | path,
|
170 | queryParams: customQueryParams,
|
171 | storyId,
|
172 | url,
|
173 | viewMode
|
174 | };
|
175 | },
|
176 |
|
177 | setQueryParams(input) {
|
178 | const {
|
179 | customQueryParams
|
180 | } = store.getState();
|
181 | const queryParams = {};
|
182 | const update = Object.assign({}, customQueryParams, Object.entries(input).reduce((acc, [key, value]) => {
|
183 | if (value !== null) {
|
184 | acc[key] = value;
|
185 | }
|
186 |
|
187 | return acc;
|
188 | }, queryParams));
|
189 |
|
190 | if (!deepEqual(customQueryParams, update)) {
|
191 | store.setState({
|
192 | customQueryParams: update
|
193 | });
|
194 | fullAPI.emit(UPDATE_QUERY_PARAMS, update);
|
195 | }
|
196 | },
|
197 |
|
198 | navigateUrl(url, options) {
|
199 | navigate(url, Object.assign({}, options, {
|
200 | plain: true
|
201 | }));
|
202 | }
|
203 |
|
204 | };
|
205 |
|
206 | const initModule = () => {
|
207 |
|
208 | const updateArgsParam = () => {
|
209 | const {
|
210 | path,
|
211 | queryParams,
|
212 | viewMode
|
213 | } = fullAPI.getUrlState();
|
214 | if (viewMode !== 'story') return;
|
215 | const currentStory = fullAPI.getCurrentStoryData();
|
216 | if (!isStory(currentStory)) return;
|
217 | const {
|
218 | args,
|
219 | initialArgs
|
220 | } = currentStory;
|
221 | const argsString = buildArgsParam(initialArgs, args);
|
222 | navigateTo(path, Object.assign({}, queryParams, {
|
223 | args: argsString
|
224 | }), {
|
225 | replace: true
|
226 | });
|
227 | api.setQueryParams({
|
228 | args: argsString
|
229 | });
|
230 | };
|
231 |
|
232 | fullAPI.on(SET_CURRENT_STORY, () => updateArgsParam());
|
233 | let handleOrId;
|
234 | fullAPI.on(STORY_ARGS_UPDATED, () => {
|
235 | if ('requestIdleCallback' in globalWindow) {
|
236 | if (handleOrId) globalWindow.cancelIdleCallback(handleOrId);
|
237 | handleOrId = globalWindow.requestIdleCallback(updateArgsParam, {
|
238 | timeout: 1000
|
239 | });
|
240 | } else {
|
241 | if (handleOrId) clearTimeout(handleOrId);
|
242 | setTimeout(updateArgsParam, 100);
|
243 | }
|
244 | });
|
245 | fullAPI.on(GLOBALS_UPDATED, ({
|
246 | globals,
|
247 | initialGlobals
|
248 | }) => {
|
249 | const {
|
250 | path,
|
251 | queryParams
|
252 | } = fullAPI.getUrlState();
|
253 | const globalsString = buildArgsParam(initialGlobals, globals);
|
254 | navigateTo(path, Object.assign({}, queryParams, {
|
255 | globals: globalsString
|
256 | }), {
|
257 | replace: true
|
258 | });
|
259 | api.setQueryParams({
|
260 | globals: globalsString
|
261 | });
|
262 | });
|
263 | fullAPI.on(NAVIGATE_URL, (url, options) => {
|
264 | fullAPI.navigateUrl(url, options);
|
265 | });
|
266 |
|
267 | if (fullAPI.showReleaseNotesOnLaunch()) {
|
268 | navigate('/settings/release-notes');
|
269 | }
|
270 | };
|
271 |
|
272 | return {
|
273 | api,
|
274 | state: initialUrlSupport(Object.assign({
|
275 | store,
|
276 | navigate,
|
277 | state,
|
278 | provider,
|
279 | fullAPI
|
280 | }, rest)),
|
281 | init: initModule
|
282 | };
|
283 | }; |
\ | No newline at end of file |