1 | import "core-js/modules/es.array.reduce.js";
|
2 | import { once } from '@storybook/client-logger';
|
3 | import isPlainObject from 'lodash/isPlainObject';
|
4 | import dedent from 'ts-dedent';
|
5 | const INCOMPATIBLE = Symbol('incompatible');
|
6 |
|
7 | const map = (arg, type) => {
|
8 | if (arg === undefined || arg === null || !type) return arg;
|
9 |
|
10 | switch (type.name) {
|
11 | case 'string':
|
12 | return String(arg);
|
13 |
|
14 | case 'enum':
|
15 | return arg;
|
16 |
|
17 | case 'number':
|
18 | return Number(arg);
|
19 |
|
20 | case 'boolean':
|
21 | return arg === 'true';
|
22 |
|
23 | case 'array':
|
24 | if (!type.value || !Array.isArray(arg)) return INCOMPATIBLE;
|
25 | return arg.reduce((acc, item, index) => {
|
26 | const mapped = map(item, type.value);
|
27 | if (mapped !== INCOMPATIBLE) acc[index] = mapped;
|
28 | return acc;
|
29 | }, new Array(arg.length));
|
30 |
|
31 | case 'object':
|
32 | if (typeof arg === 'string' || typeof arg === 'number') return arg;
|
33 | if (!type.value || typeof arg !== 'object') return INCOMPATIBLE;
|
34 | return Object.entries(arg).reduce((acc, [key, val]) => {
|
35 | const mapped = map(val, type.value[key]);
|
36 | return mapped === INCOMPATIBLE ? acc : Object.assign(acc, {
|
37 | [key]: mapped
|
38 | });
|
39 | }, {});
|
40 |
|
41 | default:
|
42 | return INCOMPATIBLE;
|
43 | }
|
44 | };
|
45 |
|
46 | export const mapArgsToTypes = (args, argTypes) => {
|
47 | return Object.entries(args).reduce((acc, [key, value]) => {
|
48 | if (!argTypes[key]) return acc;
|
49 | const mapped = map(value, argTypes[key].type);
|
50 | return mapped === INCOMPATIBLE ? acc : Object.assign(acc, {
|
51 | [key]: mapped
|
52 | });
|
53 | }, {});
|
54 | };
|
55 | export const combineArgs = (value, update) => {
|
56 | if (Array.isArray(value) && Array.isArray(update)) {
|
57 | return update.reduce((acc, upd, index) => {
|
58 | acc[index] = combineArgs(value[index], update[index]);
|
59 | return acc;
|
60 | }, [...value]).filter(v => v !== undefined);
|
61 | }
|
62 |
|
63 | if (!isPlainObject(value) || !isPlainObject(update)) return update;
|
64 | return Object.keys(Object.assign({}, value, update)).reduce((acc, key) => {
|
65 | if (key in update) {
|
66 | const combined = combineArgs(value[key], update[key]);
|
67 | if (combined !== undefined) acc[key] = combined;
|
68 | } else {
|
69 | acc[key] = value[key];
|
70 | }
|
71 |
|
72 | return acc;
|
73 | }, {});
|
74 | };
|
75 | export const validateOptions = (args, argTypes) => {
|
76 | return Object.entries(argTypes).reduce((acc, [key, {
|
77 | options
|
78 | }]) => {
|
79 | if (!options) {
|
80 | if (key in args) {
|
81 | acc[key] = args[key];
|
82 | }
|
83 |
|
84 | return acc;
|
85 | }
|
86 |
|
87 | if (!Array.isArray(options)) {
|
88 | once.error(dedent`
|
89 | Invalid argType: '${key}.options' should be an array.
|
90 |
|
91 | More info: https://storybook.js.org/docs/react/api/argtypes
|
92 | `);
|
93 | acc[key] = args[key];
|
94 | return acc;
|
95 | }
|
96 |
|
97 | if (options.some(opt => opt && ['object', 'function'].includes(typeof opt))) {
|
98 | once.error(dedent`
|
99 | Invalid argType: '${key}.options' should only contain primitives. Use a 'mapping' for complex values.
|
100 |
|
101 | More info: https://storybook.js.org/docs/react/writing-stories/args#mapping-to-complex-arg-values
|
102 | `);
|
103 | acc[key] = args[key];
|
104 | return acc;
|
105 | }
|
106 |
|
107 | const isArray = Array.isArray(args[key]);
|
108 | const invalidIndex = isArray && args[key].findIndex(val => !options.includes(val));
|
109 | const isValidArray = isArray && invalidIndex === -1;
|
110 |
|
111 | if (args[key] === undefined || options.includes(args[key]) || isValidArray) {
|
112 | acc[key] = args[key];
|
113 | return acc;
|
114 | }
|
115 |
|
116 | const field = isArray ? `${key}[${invalidIndex}]` : key;
|
117 | const supportedOptions = options.map(opt => typeof opt === 'string' ? `'${opt}'` : String(opt)).join(', ');
|
118 | once.warn(`Received illegal value for '${field}'. Supported options: ${supportedOptions}`);
|
119 | return acc;
|
120 | }, {});
|
121 | }; |
\ | No newline at end of file |