create-bdpamke-react-scaffold 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +62 -0
- package/bin/create-bdpamke-react-scaffold.js +101 -0
- package/package.json +39 -0
- package/template/.env.example +6 -0
- package/template/FUNCTIONS_EXAMPLES.md +480 -0
- package/template/HOWTOadd a page.md +166 -0
- package/template/REACT_PROPS_USEEFFECT.md +210 -0
- package/template/REGISTRATION_FLOW.md +268 -0
- package/template/USESTATE_EXAMPLES.md +451 -0
- package/template/components.json +20 -0
- package/template/index.html +13 -0
- package/template/jsconfig.json +19 -0
- package/template/package-lock.json +5988 -0
- package/template/package.json +73 -0
- package/template/postcss.config.cjs +6 -0
- package/template/public/images/BDPA_edited.png +0 -0
- package/template/server/server.js +86 -0
- package/template/server/utils/apiClient.js +59 -0
- package/template/server/utils/password.js +60 -0
- package/template/src/App.jsx +10 -0
- package/template/src/components/layout/Container.jsx +7 -0
- package/template/src/components/layout/Section.jsx +7 -0
- package/template/src/components/ui/accordion.jsx +41 -0
- package/template/src/components/ui/alert-dialog.jsx +99 -0
- package/template/src/components/ui/alert.jsx +47 -0
- package/template/src/components/ui/aspect-ratio.jsx +5 -0
- package/template/src/components/ui/avatar.jsx +35 -0
- package/template/src/components/ui/badge.jsx +34 -0
- package/template/src/components/ui/button.jsx +47 -0
- package/template/src/components/ui/calendar.jsx +173 -0
- package/template/src/components/ui/card.jsx +50 -0
- package/template/src/components/ui/carousel.jsx +194 -0
- package/template/src/components/ui/checkbox.jsx +22 -0
- package/template/src/components/ui/collapsible.jsx +11 -0
- package/template/src/components/ui/command.jsx +116 -0
- package/template/src/components/ui/dialog.jsx +94 -0
- package/template/src/components/ui/drawer.jsx +92 -0
- package/template/src/components/ui/dropdown-menu.jsx +155 -0
- package/template/src/components/ui/form.jsx +138 -0
- package/template/src/components/ui/hover-card.jsx +25 -0
- package/template/src/components/ui/icons.jsx +81 -0
- package/template/src/components/ui/input.jsx +19 -0
- package/template/src/components/ui/label.jsx +16 -0
- package/template/src/components/ui/menubar.jsx +200 -0
- package/template/src/components/ui/navigation-menu.jsx +104 -0
- package/template/src/components/ui/popover.jsx +25 -0
- package/template/src/components/ui/progress.jsx +20 -0
- package/template/src/components/ui/radio-group.jsx +29 -0
- package/template/src/components/ui/scroll-area.jsx +40 -0
- package/template/src/components/ui/select.jsx +120 -0
- package/template/src/components/ui/separator.jsx +25 -0
- package/template/src/components/ui/sheet.jsx +108 -0
- package/template/src/components/ui/skeleton.jsx +10 -0
- package/template/src/components/ui/slider.jsx +23 -0
- package/template/src/components/ui/sonner.jsx +42 -0
- package/template/src/components/ui/switch.jsx +24 -0
- package/template/src/components/ui/table.jsx +83 -0
- package/template/src/components/ui/tabs.jsx +41 -0
- package/template/src/components/ui/textarea.jsx +18 -0
- package/template/src/components/ui/toast.jsx +82 -0
- package/template/src/components/ui/toaster.jsx +33 -0
- package/template/src/components/ui/toggle.jsx +40 -0
- package/template/src/components/ui/tooltip.jsx +24 -0
- package/template/src/hooks/use-toast.js +155 -0
- package/template/src/index.css +61 -0
- package/template/src/index.js +6 -0
- package/template/src/lib/utils.js +11 -0
- package/template/src/main.jsx +15 -0
- package/template/src/pages/Home.jsx +26 -0
- package/template/tailwind.config.cjs +76 -0
- package/template/vite.config.mts +22 -0
|
@@ -0,0 +1,451 @@
|
|
|
1
|
+
# useState Examples
|
|
2
|
+
|
|
3
|
+
This guide explains how `useState` works in React with simple examples.
|
|
4
|
+
|
|
5
|
+
## 1. What `useState` does
|
|
6
|
+
|
|
7
|
+
`useState` lets a React component remember values between renders.
|
|
8
|
+
|
|
9
|
+
You usually use it for things like:
|
|
10
|
+
|
|
11
|
+
- text input values
|
|
12
|
+
- counters
|
|
13
|
+
- toggles
|
|
14
|
+
- form data
|
|
15
|
+
- API loading state
|
|
16
|
+
- error messages
|
|
17
|
+
|
|
18
|
+
Basic syntax:
|
|
19
|
+
|
|
20
|
+
```jsx
|
|
21
|
+
import { useState } from "react";
|
|
22
|
+
|
|
23
|
+
export default function Example() {
|
|
24
|
+
const [count, setCount] = useState(0);
|
|
25
|
+
|
|
26
|
+
return <p>{count}</p>;
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
In this example:
|
|
31
|
+
|
|
32
|
+
- `count` is the current state value
|
|
33
|
+
- `setCount` updates the state
|
|
34
|
+
- `0` is the initial value
|
|
35
|
+
|
|
36
|
+
## 2. Example: counter
|
|
37
|
+
|
|
38
|
+
```jsx
|
|
39
|
+
import { useState } from "react";
|
|
40
|
+
|
|
41
|
+
export default function CounterExample() {
|
|
42
|
+
const [count, setCount] = useState(0);
|
|
43
|
+
|
|
44
|
+
return (
|
|
45
|
+
<div>
|
|
46
|
+
<p>Count: {count}</p>
|
|
47
|
+
<button onClick={() => setCount(count + 1)}>Increase</button>
|
|
48
|
+
<button onClick={() => setCount(count - 1)}>Decrease</button>
|
|
49
|
+
<button onClick={() => setCount(0)}>Reset</button>
|
|
50
|
+
</div>
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
What happens here:
|
|
56
|
+
|
|
57
|
+
- clicking `Increase` adds `1`
|
|
58
|
+
- clicking `Decrease` subtracts `1`
|
|
59
|
+
- clicking `Reset` sets the value back to `0`
|
|
60
|
+
|
|
61
|
+
## 3. Example: text input
|
|
62
|
+
|
|
63
|
+
```jsx
|
|
64
|
+
import { useState } from "react";
|
|
65
|
+
|
|
66
|
+
export default function NameExample() {
|
|
67
|
+
const [name, setName] = useState("");
|
|
68
|
+
|
|
69
|
+
return (
|
|
70
|
+
<div>
|
|
71
|
+
<input
|
|
72
|
+
type="text"
|
|
73
|
+
value={name}
|
|
74
|
+
onChange={(event) => setName(event.target.value)}
|
|
75
|
+
placeholder="Enter your name"
|
|
76
|
+
/>
|
|
77
|
+
<p>Hello, {name || "friend"}.</p>
|
|
78
|
+
</div>
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
What happens here:
|
|
84
|
+
|
|
85
|
+
- the input shows the current `name`
|
|
86
|
+
- typing calls `setName(...)`
|
|
87
|
+
- the paragraph updates immediately
|
|
88
|
+
|
|
89
|
+
## 4. Example: boolean toggle
|
|
90
|
+
|
|
91
|
+
```jsx
|
|
92
|
+
import { useState } from "react";
|
|
93
|
+
|
|
94
|
+
export default function ToggleExample() {
|
|
95
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
96
|
+
|
|
97
|
+
return (
|
|
98
|
+
<div>
|
|
99
|
+
<button onClick={() => setIsOpen(!isOpen)}>
|
|
100
|
+
{isOpen ? "Hide" : "Show"}
|
|
101
|
+
</button>
|
|
102
|
+
|
|
103
|
+
{isOpen ? <p>The panel is open.</p> : null}
|
|
104
|
+
</div>
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
This is useful for:
|
|
110
|
+
|
|
111
|
+
- modals
|
|
112
|
+
- dropdowns
|
|
113
|
+
- accordions
|
|
114
|
+
- mobile menus
|
|
115
|
+
- show/hide sections
|
|
116
|
+
|
|
117
|
+
## 5. Example: multiple fields in one object
|
|
118
|
+
|
|
119
|
+
When a form has several related values, you can store them in one object.
|
|
120
|
+
|
|
121
|
+
```jsx
|
|
122
|
+
import { useState } from "react";
|
|
123
|
+
|
|
124
|
+
export default function FormExample() {
|
|
125
|
+
const [formData, setFormData] = useState({
|
|
126
|
+
email: "",
|
|
127
|
+
password: "",
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
const handleChange = (event) => {
|
|
131
|
+
const { name, value } = event.target;
|
|
132
|
+
|
|
133
|
+
setFormData((current) => ({
|
|
134
|
+
...current,
|
|
135
|
+
[name]: value,
|
|
136
|
+
}));
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
return (
|
|
140
|
+
<form>
|
|
141
|
+
<input
|
|
142
|
+
name="email"
|
|
143
|
+
type="email"
|
|
144
|
+
value={formData.email}
|
|
145
|
+
onChange={handleChange}
|
|
146
|
+
placeholder="Email"
|
|
147
|
+
/>
|
|
148
|
+
|
|
149
|
+
<input
|
|
150
|
+
name="password"
|
|
151
|
+
type="password"
|
|
152
|
+
value={formData.password}
|
|
153
|
+
onChange={handleChange}
|
|
154
|
+
placeholder="Password"
|
|
155
|
+
/>
|
|
156
|
+
|
|
157
|
+
<pre>{JSON.stringify(formData, null, 2)}</pre>
|
|
158
|
+
</form>
|
|
159
|
+
);
|
|
160
|
+
}
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
Why use this pattern:
|
|
164
|
+
|
|
165
|
+
- it keeps related form values together
|
|
166
|
+
- it scales better than many separate state variables
|
|
167
|
+
- it works well for registration and login forms
|
|
168
|
+
|
|
169
|
+
## 6. Example: array state
|
|
170
|
+
|
|
171
|
+
You can also store arrays in state.
|
|
172
|
+
|
|
173
|
+
```jsx
|
|
174
|
+
import { useState } from "react";
|
|
175
|
+
|
|
176
|
+
export default function TodoExample() {
|
|
177
|
+
const [items, setItems] = useState(["Learn React"]);
|
|
178
|
+
const [newItem, setNewItem] = useState("");
|
|
179
|
+
|
|
180
|
+
const addItem = () => {
|
|
181
|
+
if (!newItem.trim()) return;
|
|
182
|
+
|
|
183
|
+
setItems((current) => [...current, newItem]);
|
|
184
|
+
setNewItem("");
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
return (
|
|
188
|
+
<div>
|
|
189
|
+
<input
|
|
190
|
+
value={newItem}
|
|
191
|
+
onChange={(event) => setNewItem(event.target.value)}
|
|
192
|
+
placeholder="Add item"
|
|
193
|
+
/>
|
|
194
|
+
<button onClick={addItem}>Add</button>
|
|
195
|
+
|
|
196
|
+
<ul>
|
|
197
|
+
{items.map((item, index) => (
|
|
198
|
+
<li key={index}>{item}</li>
|
|
199
|
+
))}
|
|
200
|
+
</ul>
|
|
201
|
+
</div>
|
|
202
|
+
);
|
|
203
|
+
}
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
Common array operations with state:
|
|
207
|
+
|
|
208
|
+
- add item with `[...current, newItem]`
|
|
209
|
+
- remove item with `.filter(...)`
|
|
210
|
+
- update item with `.map(...)`
|
|
211
|
+
|
|
212
|
+
## 7. Example: loading and error state for API calls
|
|
213
|
+
|
|
214
|
+
This pattern is common when talking to a server.
|
|
215
|
+
|
|
216
|
+
```jsx
|
|
217
|
+
import { useState } from "react";
|
|
218
|
+
|
|
219
|
+
export default function ApiExample() {
|
|
220
|
+
const [loading, setLoading] = useState(false);
|
|
221
|
+
const [data, setData] = useState(null);
|
|
222
|
+
const [error, setError] = useState("");
|
|
223
|
+
|
|
224
|
+
const fetchHealth = async () => {
|
|
225
|
+
setLoading(true);
|
|
226
|
+
setError("");
|
|
227
|
+
|
|
228
|
+
try {
|
|
229
|
+
const response = await fetch("/api/health");
|
|
230
|
+
const result = await response.json();
|
|
231
|
+
setData(result);
|
|
232
|
+
} catch (err) {
|
|
233
|
+
setError("Failed to load API response.");
|
|
234
|
+
} finally {
|
|
235
|
+
setLoading(false);
|
|
236
|
+
}
|
|
237
|
+
};
|
|
238
|
+
|
|
239
|
+
return (
|
|
240
|
+
<div>
|
|
241
|
+
<button onClick={fetchHealth} disabled={loading}>
|
|
242
|
+
{loading ? "Loading..." : "Check API"}
|
|
243
|
+
</button>
|
|
244
|
+
|
|
245
|
+
{error ? <p>{error}</p> : null}
|
|
246
|
+
{data ? <pre>{JSON.stringify(data, null, 2)}</pre> : null}
|
|
247
|
+
</div>
|
|
248
|
+
);
|
|
249
|
+
}
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
This pattern is useful because it separates:
|
|
253
|
+
|
|
254
|
+
- the request state
|
|
255
|
+
- the successful response
|
|
256
|
+
- the failure message
|
|
257
|
+
|
|
258
|
+
## 8. Example: functional state updates
|
|
259
|
+
|
|
260
|
+
When the next state depends on the previous state, use the callback form.
|
|
261
|
+
|
|
262
|
+
```jsx
|
|
263
|
+
import { useState } from "react";
|
|
264
|
+
|
|
265
|
+
export default function FunctionalUpdateExample() {
|
|
266
|
+
const [count, setCount] = useState(0);
|
|
267
|
+
|
|
268
|
+
const addThree = () => {
|
|
269
|
+
setCount((current) => current + 1);
|
|
270
|
+
setCount((current) => current + 1);
|
|
271
|
+
setCount((current) => current + 1);
|
|
272
|
+
};
|
|
273
|
+
|
|
274
|
+
return (
|
|
275
|
+
<div>
|
|
276
|
+
<p>{count}</p>
|
|
277
|
+
<button onClick={addThree}>Add 3</button>
|
|
278
|
+
</div>
|
|
279
|
+
);
|
|
280
|
+
}
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
Why this matters:
|
|
284
|
+
|
|
285
|
+
- `setCount(count + 1)` can use an older value
|
|
286
|
+
- `setCount((current) => current + 1)` always uses the latest state
|
|
287
|
+
|
|
288
|
+
Use the functional form when:
|
|
289
|
+
|
|
290
|
+
- incrementing counters
|
|
291
|
+
- toggling based on previous value
|
|
292
|
+
- updating arrays or objects from current state
|
|
293
|
+
|
|
294
|
+
## 9. Example: registration form using `useState`
|
|
295
|
+
|
|
296
|
+
This example matches a real app pattern.
|
|
297
|
+
|
|
298
|
+
```jsx
|
|
299
|
+
import { useState } from "react";
|
|
300
|
+
|
|
301
|
+
export default function RegisterExample() {
|
|
302
|
+
const [email, setEmail] = useState("");
|
|
303
|
+
const [password, setPassword] = useState("");
|
|
304
|
+
const [message, setMessage] = useState("");
|
|
305
|
+
|
|
306
|
+
const handleSubmit = async (event) => {
|
|
307
|
+
event.preventDefault();
|
|
308
|
+
setMessage("");
|
|
309
|
+
|
|
310
|
+
try {
|
|
311
|
+
const response = await fetch("/api/register", {
|
|
312
|
+
method: "POST",
|
|
313
|
+
headers: {
|
|
314
|
+
"Content-Type": "application/json",
|
|
315
|
+
},
|
|
316
|
+
body: JSON.stringify({ email, password }),
|
|
317
|
+
});
|
|
318
|
+
|
|
319
|
+
const result = await response.json();
|
|
320
|
+
|
|
321
|
+
if (!response.ok) {
|
|
322
|
+
throw new Error(result.error || "Registration failed.");
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
setMessage("Registration submitted successfully.");
|
|
326
|
+
} catch (error) {
|
|
327
|
+
setMessage(error.message);
|
|
328
|
+
}
|
|
329
|
+
};
|
|
330
|
+
|
|
331
|
+
return (
|
|
332
|
+
<form onSubmit={handleSubmit}>
|
|
333
|
+
<input
|
|
334
|
+
type="email"
|
|
335
|
+
value={email}
|
|
336
|
+
onChange={(event) => setEmail(event.target.value)}
|
|
337
|
+
placeholder="Email"
|
|
338
|
+
/>
|
|
339
|
+
|
|
340
|
+
<input
|
|
341
|
+
type="password"
|
|
342
|
+
value={password}
|
|
343
|
+
onChange={(event) => setPassword(event.target.value)}
|
|
344
|
+
placeholder="Password"
|
|
345
|
+
/>
|
|
346
|
+
|
|
347
|
+
<button type="submit">Register</button>
|
|
348
|
+
<p>{message}</p>
|
|
349
|
+
</form>
|
|
350
|
+
);
|
|
351
|
+
}
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
Here `useState` is used for:
|
|
355
|
+
|
|
356
|
+
- `email`
|
|
357
|
+
- `password`
|
|
358
|
+
- `message`
|
|
359
|
+
|
|
360
|
+
That is a common and clean pattern for simple forms.
|
|
361
|
+
|
|
362
|
+
## 10. Common mistakes
|
|
363
|
+
|
|
364
|
+
### Mistake: updating objects without copying existing values
|
|
365
|
+
|
|
366
|
+
Wrong:
|
|
367
|
+
|
|
368
|
+
```jsx
|
|
369
|
+
setFormData({ email: "new@example.com" });
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
This replaces the whole object.
|
|
373
|
+
|
|
374
|
+
Better:
|
|
375
|
+
|
|
376
|
+
```jsx
|
|
377
|
+
setFormData((current) => ({
|
|
378
|
+
...current,
|
|
379
|
+
email: "new@example.com",
|
|
380
|
+
}));
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
### Mistake: mutating arrays directly
|
|
384
|
+
|
|
385
|
+
Wrong:
|
|
386
|
+
|
|
387
|
+
```jsx
|
|
388
|
+
items.push("New item");
|
|
389
|
+
setItems(items);
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
Better:
|
|
393
|
+
|
|
394
|
+
```jsx
|
|
395
|
+
setItems((current) => [...current, "New item"]);
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
### Mistake: expecting state to update immediately
|
|
399
|
+
|
|
400
|
+
Wrong expectation:
|
|
401
|
+
|
|
402
|
+
```jsx
|
|
403
|
+
setCount(count + 1);
|
|
404
|
+
console.log(count);
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
The `console.log` may still print the old value during that render cycle.
|
|
408
|
+
|
|
409
|
+
## 11. Quick rule of thumb
|
|
410
|
+
|
|
411
|
+
Use `useState` when:
|
|
412
|
+
|
|
413
|
+
- the value changes over time
|
|
414
|
+
- the UI should re-render when the value changes
|
|
415
|
+
- the value belongs to that component
|
|
416
|
+
|
|
417
|
+
Examples:
|
|
418
|
+
|
|
419
|
+
- form inputs
|
|
420
|
+
- open/closed UI state
|
|
421
|
+
- fetched API data
|
|
422
|
+
- loading indicators
|
|
423
|
+
- local validation messages
|
|
424
|
+
|
|
425
|
+
## 12. Summary
|
|
426
|
+
|
|
427
|
+
`useState` is one of the main React hooks.
|
|
428
|
+
|
|
429
|
+
It gives you:
|
|
430
|
+
|
|
431
|
+
- a current value
|
|
432
|
+
- a function to update that value
|
|
433
|
+
- automatic re-rendering when the value changes
|
|
434
|
+
|
|
435
|
+
Pattern:
|
|
436
|
+
|
|
437
|
+
```jsx
|
|
438
|
+
const [value, setValue] = useState(initialValue);
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
Examples in this guide covered:
|
|
442
|
+
|
|
443
|
+
- numbers
|
|
444
|
+
- strings
|
|
445
|
+
- booleans
|
|
446
|
+
- objects
|
|
447
|
+
- arrays
|
|
448
|
+
- forms
|
|
449
|
+
- API state
|
|
450
|
+
|
|
451
|
+
Once `useState` feels comfortable, the next hook to learn is usually `useEffect`.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://ui.shadcn.com/schema.json",
|
|
3
|
+
"style": "default",
|
|
4
|
+
"rsc": false,
|
|
5
|
+
"tsx": false,
|
|
6
|
+
"tailwind": {
|
|
7
|
+
"config": "tailwind.config.cjs",
|
|
8
|
+
"css": "src/index.css",
|
|
9
|
+
"baseColor": "slate",
|
|
10
|
+
"cssVariables": true,
|
|
11
|
+
"prefix": ""
|
|
12
|
+
},
|
|
13
|
+
"aliases": {
|
|
14
|
+
"components": "@/components",
|
|
15
|
+
"utils": "@/lib/utils",
|
|
16
|
+
"ui": "@/components/ui",
|
|
17
|
+
"lib": "@/lib",
|
|
18
|
+
"hooks": "@/hooks"
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<link rel="icon" type="image/png" href="/BDPA_edited.png" />
|
|
6
|
+
<title>BDPA React Scaffold and Demo</title>
|
|
7
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
8
|
+
</head>
|
|
9
|
+
<body class="bg-gray-100">
|
|
10
|
+
<div id="root"></div>
|
|
11
|
+
<script type="module" src="/src/main.jsx"></script>
|
|
12
|
+
</body>
|
|
13
|
+
</html>
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ESNext",
|
|
4
|
+
"module": "ESNext",
|
|
5
|
+
"moduleResolution": "bundler",
|
|
6
|
+
"jsx": "react-jsx",
|
|
7
|
+
"checkJs": true,
|
|
8
|
+
"strict": false,
|
|
9
|
+
"allowSyntheticDefaultImports": true,
|
|
10
|
+
"esModuleInterop": true,
|
|
11
|
+
"resolveJsonModule": true,
|
|
12
|
+
"baseUrl": ".",
|
|
13
|
+
"paths": {
|
|
14
|
+
"@/*": ["src/*"]
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"include": ["src", "index.html"],
|
|
18
|
+
"exclude": ["node_modules", "dist"]
|
|
19
|
+
}
|