UNPKG

3.71 kBJavaScriptView Raw
1import "core-js/modules/es.array.reduce.js";
2import { once } from '@storybook/client-logger';
3import isPlainObject from 'lodash/isPlainObject';
4import dedent from 'ts-dedent';
5const INCOMPATIBLE = Symbol('incompatible');
6
7const 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
46export 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};
55export 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};
75export 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