1 | import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 |
|
22 |
|
23 |
|
24 |
|
25 |
|
26 | import { nanoid } from 'nanoid';
|
27 | import { generatePropCombinations } from './generatePropCombinations';
|
28 | import React from 'react';
|
29 |
|
30 |
|
31 |
|
32 |
|
33 |
|
34 |
|
35 |
|
36 |
|
37 |
|
38 |
|
39 | export function generateComponentExamples(Component, config) {
|
40 | const sectionProp = config.sectionProp,
|
41 | excludeProps = config.excludeProps,
|
42 | filter = config.filter;
|
43 | const PROPS_CACHE = [];
|
44 | const sections = [];
|
45 | const maxExamples = config.maxExamples ? config.maxExamples : 500;
|
46 | let exampleCount = 0;
|
47 | let propValues = {};
|
48 |
|
49 | const getParameters = page => {
|
50 | const examples = page.examples;
|
51 | const index = page.index;
|
52 | let parameters = {};
|
53 |
|
54 | if (typeof config.getParameters === 'function') {
|
55 | parameters = { ...config.getParameters({
|
56 | examples,
|
57 | index
|
58 | })
|
59 | };
|
60 | }
|
61 |
|
62 | return parameters;
|
63 | };
|
64 | |
65 |
|
66 |
|
67 |
|
68 |
|
69 |
|
70 |
|
71 | const mergeComponentPropsFromConfig = props => {
|
72 | let componentProps = props;
|
73 |
|
74 |
|
75 |
|
76 |
|
77 |
|
78 |
|
79 |
|
80 | if (typeof config.getComponentProps === 'function') {
|
81 | componentProps = { ...componentProps,
|
82 | ...config.getComponentProps(props)
|
83 | };
|
84 | }
|
85 |
|
86 | return componentProps;
|
87 | };
|
88 |
|
89 | const getExampleProps = props => {
|
90 | let exampleProps = {};
|
91 |
|
92 | if (typeof config.getExampleProps === 'function') {
|
93 | exampleProps = { ...config.getExampleProps(props)
|
94 | };
|
95 | }
|
96 |
|
97 | return exampleProps;
|
98 | };
|
99 |
|
100 | const addPage = section => {
|
101 | const page = {
|
102 | examples: [],
|
103 | index: section.pages.length
|
104 | };
|
105 | section.pages.push(page);
|
106 | return page;
|
107 | };
|
108 |
|
109 | const addExample = (sectionName, example) => {
|
110 | let section = sections.find(section => section.sectionName === sectionName);
|
111 |
|
112 | if (!section) {
|
113 | section = {
|
114 | sectionName: sectionName,
|
115 | propName: sectionProp,
|
116 | propValue: sectionName,
|
117 | pages: []
|
118 | };
|
119 | sections.push(section);
|
120 | }
|
121 |
|
122 | let page = section.pages[section.pages.length - 1];
|
123 | let maxExamplesPerPage = config.maxExamplesPerPage;
|
124 |
|
125 | if (typeof maxExamplesPerPage === 'function') {
|
126 | maxExamplesPerPage = maxExamplesPerPage(sectionName);
|
127 | }
|
128 |
|
129 | if (!page) {
|
130 | page = addPage(section);
|
131 | } else if (maxExamplesPerPage && page.examples.length % maxExamplesPerPage === 0 && page.examples.length > 0) {
|
132 | page = addPage(section);
|
133 | }
|
134 |
|
135 | page.examples.push(example);
|
136 | };
|
137 |
|
138 |
|
139 | const fastSerialize = props => {
|
140 | const strArr = [];
|
141 | objToString(props, strArr);
|
142 | return strArr.join('');
|
143 | };
|
144 |
|
145 | const objToString = (currObject, currString) => {
|
146 | if (!currObject) {
|
147 | return;
|
148 | }
|
149 |
|
150 | if ( React.isValidElement(currObject)) {
|
151 | currString.push(JSON.stringify(currObject));
|
152 | } else if (typeof currObject === 'object') {
|
153 | for (const _ref of Object.entries(currObject)) {
|
154 | var _ref2 = _slicedToArray(_ref, 2);
|
155 |
|
156 | const key = _ref2[0];
|
157 | const value = _ref2[1];
|
158 | currString.push(key);
|
159 | objToString(value, currString);
|
160 | }
|
161 | } else {
|
162 | currString.push(currObject);
|
163 | }
|
164 | };
|
165 |
|
166 | const maybeAddExample = props => {
|
167 | const componentProps = mergeComponentPropsFromConfig(props);
|
168 | const ignore = typeof filter === 'function' ? filter(componentProps) : false;
|
169 |
|
170 | if (ignore) {
|
171 | return;
|
172 | }
|
173 |
|
174 | const propsString = fastSerialize(componentProps);
|
175 |
|
176 | if (!PROPS_CACHE.includes(propsString)) {
|
177 | const key = nanoid();
|
178 | const exampleProps = getExampleProps(props);
|
179 | exampleCount++;
|
180 |
|
181 | if (exampleCount < maxExamples) {
|
182 | PROPS_CACHE.push(propsString);
|
183 | let sectionName = 'Examples';
|
184 |
|
185 | if (sectionProp && componentProps[sectionProp]) {
|
186 | sectionName = componentProps[sectionProp];
|
187 | }
|
188 |
|
189 | addExample(sectionName, {
|
190 | Component,
|
191 | componentProps,
|
192 | exampleProps,
|
193 | key
|
194 | });
|
195 | }
|
196 | }
|
197 | };
|
198 |
|
199 | if (isEmpty(config.propValues)) {
|
200 | maybeAddExample({});
|
201 | } else {
|
202 | if (Array.isArray(excludeProps)) {
|
203 | ;
|
204 | Object.keys(config.propValues).forEach(propName => {
|
205 | if (!excludeProps.includes(propName)) {
|
206 | propValues[propName] = config.propValues[propName];
|
207 | }
|
208 | });
|
209 | } else {
|
210 | propValues = config.propValues;
|
211 | }
|
212 |
|
213 |
|
214 | console.info(`Generating examples for ${Component.displayName} (${Object.keys(propValues).length} props):`, propValues);
|
215 |
|
216 |
|
217 | const combos = generatePropCombinations(propValues).filter(Boolean);
|
218 | let index = 0;
|
219 |
|
220 | while (index < combos.length && exampleCount < maxExamples) {
|
221 | const combo = combos[index];
|
222 |
|
223 | if (combo) {
|
224 | maybeAddExample(combo);
|
225 | index++;
|
226 | }
|
227 | }
|
228 | }
|
229 |
|
230 | if (exampleCount >= maxExamples) {
|
231 | console.error(`Too many examples for ${Component.displayName}! Add a filter to the config.`);
|
232 | }
|
233 |
|
234 |
|
235 | console.info(`Generated ${exampleCount} examples for ${Component.displayName}`);
|
236 | sections.forEach(_ref3 => {
|
237 | let pages = _ref3.pages;
|
238 | pages.forEach(page => {
|
239 |
|
240 | page.parameters = getParameters(page);
|
241 | });
|
242 | });
|
243 | return sections;
|
244 | }
|
245 |
|
246 | function isEmpty(obj) {
|
247 | if (typeof obj !== 'object') return true;
|
248 |
|
249 | for (const key in obj) {
|
250 | if (Object.hasOwnProperty.call(obj, key)) return false;
|
251 | }
|
252 |
|
253 | return true;
|
254 | }
|
255 |
|
256 | export default generateComponentExamples; |
\ | No newline at end of file |