@ourtrip/ui 1.0.5 → 1.0.7
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/package.json +6 -5
- package/src/components/accordion.tsx +0 -52
- package/src/components/alert.tsx +0 -56
- package/src/components/badge.tsx +0 -84
- package/src/components/breadcrumbs.tsx +0 -48
- package/src/components/button.tsx +0 -187
- package/src/components/card.tsx +0 -23
- package/src/components/checkbox.tsx +0 -70
- package/src/components/collapse.tsx +0 -56
- package/src/components/divider.tsx +0 -28
- package/src/components/input.tsx +0 -105
- package/src/components/modal.tsx +0 -40
- package/src/components/phone.tsx +0 -104
- package/src/components/popover.tsx +0 -31
- package/src/components/radio.tsx +0 -44
- package/src/components/range.tsx +0 -54
- package/src/components/select.tsx +0 -160
- package/src/components/sheet.tsx +0 -140
- package/src/components/stars.tsx +0 -30
- package/src/components/step-marker.tsx +0 -49
- package/src/components/switch.tsx +0 -42
- package/src/components/tag.tsx +0 -52
- package/src/components/tooltip.tsx +0 -30
- package/src/index.tsx +0 -22
- package/src/utils/classes.ts +0 -2
- package/src/utils/validation.ts +0 -164
- package/tsconfig.json +0 -18
- package/webpack.config.js +0 -31
package/src/components/stars.tsx
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import React, { FC } from 'react';
|
|
4
|
-
import { Star } from '@phosphor-icons/react';
|
|
5
|
-
|
|
6
|
-
interface IStars {
|
|
7
|
-
rate: number;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
const Stars: FC<IStars> = ({ rate }: IStars) => {
|
|
11
|
-
return (
|
|
12
|
-
<div className='flex items-center gap-0.5'>
|
|
13
|
-
{Array.from({ length: 5 }).map((_, index) => (
|
|
14
|
-
<Star
|
|
15
|
-
key={`${rate}${index}`}
|
|
16
|
-
weight={rate > index ? 'fill' : 'light'}
|
|
17
|
-
className={`text-yellow-300 ${
|
|
18
|
-
rate > index ? 'text-yellow-300' : ''
|
|
19
|
-
} ${index > 0 ? 'hidden md:block' : ''}`}
|
|
20
|
-
size={12}
|
|
21
|
-
/>
|
|
22
|
-
))}
|
|
23
|
-
<p className='text-sm text-primary-900 font-medium block md:hidden'>
|
|
24
|
-
{rate}
|
|
25
|
-
</p>
|
|
26
|
-
</div>
|
|
27
|
-
);
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
export default Stars;
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import React, { FC } from 'react';
|
|
4
|
-
import { Check } from '@phosphor-icons/react';
|
|
5
|
-
import classNames from 'classnames';
|
|
6
|
-
|
|
7
|
-
type StepMarkerProps = {
|
|
8
|
-
step: number;
|
|
9
|
-
title: string;
|
|
10
|
-
subtitle?: string;
|
|
11
|
-
checked: boolean;
|
|
12
|
-
active: boolean;
|
|
13
|
-
onClick?: () => void;
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
const StepMarker: FC<StepMarkerProps> = ({
|
|
17
|
-
step,
|
|
18
|
-
title,
|
|
19
|
-
subtitle,
|
|
20
|
-
checked,
|
|
21
|
-
active,
|
|
22
|
-
onClick
|
|
23
|
-
}) => {
|
|
24
|
-
const classes = classNames(
|
|
25
|
-
'w-full md:w-12 h-12 flex-none rounded-default flex justify-center items-center font-medium',
|
|
26
|
-
{
|
|
27
|
-
'bg-green-500 text-white': checked,
|
|
28
|
-
'bg-white text-gray-500': !checked,
|
|
29
|
-
'border-2 bg-gray-100 border-primary-500': active
|
|
30
|
-
}
|
|
31
|
-
);
|
|
32
|
-
|
|
33
|
-
return (
|
|
34
|
-
<div
|
|
35
|
-
className='w-full flex flex-col items-center text-center gap-3 md:flex-row md:items-center md:text-left'
|
|
36
|
-
onClick={onClick}
|
|
37
|
-
>
|
|
38
|
-
<div className={classes}>{checked ? <Check size={22} /> : step}</div>
|
|
39
|
-
<div>
|
|
40
|
-
<h3 className='text-sm md:text-base whitespace-nowrap'>{title}</h3>
|
|
41
|
-
{subtitle && (
|
|
42
|
-
<p className='text-sm text-gray-500 whitespace-nowrap'>{subtitle}</p>
|
|
43
|
-
)}
|
|
44
|
-
</div>
|
|
45
|
-
</div>
|
|
46
|
-
);
|
|
47
|
-
};
|
|
48
|
-
|
|
49
|
-
export default StepMarker;
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import React, { FC } from 'react';
|
|
4
|
-
import { motion } from 'framer-motion';
|
|
5
|
-
|
|
6
|
-
interface ISwitch {
|
|
7
|
-
onChange?: (on: boolean) => void;
|
|
8
|
-
on: boolean;
|
|
9
|
-
disabled?: boolean;
|
|
10
|
-
label: string;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
const spring = {
|
|
14
|
-
type: 'spring',
|
|
15
|
-
stiffness: 700,
|
|
16
|
-
damping: 30
|
|
17
|
-
};
|
|
18
|
-
const Switch: FC<ISwitch> = ({ on, onChange, disabled, label }: ISwitch) => {
|
|
19
|
-
return (
|
|
20
|
-
<button
|
|
21
|
-
className='flex flex-row items-center cursor-pointer select-none border-none bg-transparent'
|
|
22
|
-
disabled={disabled}
|
|
23
|
-
onClick={() => onChange?.(!on)}
|
|
24
|
-
aria-label={label}
|
|
25
|
-
>
|
|
26
|
-
<div
|
|
27
|
-
className={`w-[35px] h-[20px] flex flex-row items-center p-[5px] rounded-[50px] transition-colors duration-200 ${
|
|
28
|
-
on ? 'bg-primary-500 justify-end' : 'bg-gray-200 justify-start'
|
|
29
|
-
}`}
|
|
30
|
-
>
|
|
31
|
-
<motion.div
|
|
32
|
-
className={`w-[10px] h-[10px] rounded-full ${
|
|
33
|
-
on ? 'bg-white' : 'bg-gray-500'
|
|
34
|
-
}`}
|
|
35
|
-
transition={spring}
|
|
36
|
-
/>
|
|
37
|
-
</div>
|
|
38
|
-
</button>
|
|
39
|
-
);
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
export default Switch;
|
package/src/components/tag.tsx
DELETED
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import React, { FC, ReactNode } from 'react';
|
|
4
|
-
|
|
5
|
-
export type TagColor = 'primary' | 'secondary' | 'white';
|
|
6
|
-
|
|
7
|
-
interface ITagProps {
|
|
8
|
-
color: TagColor;
|
|
9
|
-
children: ReactNode;
|
|
10
|
-
onClick?: () => void;
|
|
11
|
-
iconLeft?: ReactNode;
|
|
12
|
-
iconRight?: ReactNode;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
const Tag: FC<ITagProps> = ({
|
|
16
|
-
color,
|
|
17
|
-
children,
|
|
18
|
-
onClick,
|
|
19
|
-
iconLeft,
|
|
20
|
-
iconRight
|
|
21
|
-
}) => {
|
|
22
|
-
const baseClasses =
|
|
23
|
-
'rounded-button px-4 py-2 flex items-center justify-between border-0 cursor-pointer transition-all duration-300 ease-in-out font-medium';
|
|
24
|
-
|
|
25
|
-
const colorClasses = {
|
|
26
|
-
primary: 'text-primary-900 bg-white hover:bg-gray-200',
|
|
27
|
-
secondary:
|
|
28
|
-
'text-secondary-800 bg-secondary-100 hover:text-white hover:bg-secondary-800',
|
|
29
|
-
white: 'text-primary-900 bg-white hover:bg-gray-200'
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
return (
|
|
33
|
-
<button
|
|
34
|
-
onClick={() => onClick?.()}
|
|
35
|
-
className={`${baseClasses} ${colorClasses[color]}`}
|
|
36
|
-
>
|
|
37
|
-
{iconLeft && (
|
|
38
|
-
<span className='flex items-center justify-center mr-2'>
|
|
39
|
-
{iconLeft}
|
|
40
|
-
</span>
|
|
41
|
-
)}
|
|
42
|
-
{children}
|
|
43
|
-
{iconRight && (
|
|
44
|
-
<span className='flex items-center justify-center ml-2'>
|
|
45
|
-
{iconRight}
|
|
46
|
-
</span>
|
|
47
|
-
)}
|
|
48
|
-
</button>
|
|
49
|
-
);
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
export default Tag;
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import React, { FC, ReactNode } from 'react';
|
|
4
|
-
|
|
5
|
-
interface ITooltip {
|
|
6
|
-
text: string;
|
|
7
|
-
active: boolean;
|
|
8
|
-
children: ReactNode;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
const Tooltip: FC<ITooltip> = ({ text, active, children }: ITooltip) => {
|
|
12
|
-
return (
|
|
13
|
-
<div className='relative flex flex-col justify-center items-center group'>
|
|
14
|
-
<div className='w-full'>{children}</div>
|
|
15
|
-
<div
|
|
16
|
-
className={`
|
|
17
|
-
absolute top-[calc(100%+8px)] p-[5px_10px] text-white bg-primary-900
|
|
18
|
-
text-[14px] rounded-[8px] flex-col items-center gap-[5px] transition-all
|
|
19
|
-
${active ? 'group-hover:flex' : 'hidden'}
|
|
20
|
-
before:content-[''] before:absolute before:w-2 before:h-2 before:bg-primary-900
|
|
21
|
-
before:rotate-45 before:top-[-4px]
|
|
22
|
-
`}
|
|
23
|
-
>
|
|
24
|
-
{text}
|
|
25
|
-
</div>
|
|
26
|
-
</div>
|
|
27
|
-
);
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
export default Tooltip;
|
package/src/index.tsx
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
export { default as Accordion } from './components/accordion';
|
|
2
|
-
export { default as Alert } from './components/alert';
|
|
3
|
-
export { default as Badge } from './components/badge';
|
|
4
|
-
export { default as Breadcrumbs } from './components/breadcrumbs';
|
|
5
|
-
export { default as Button } from './components/button';
|
|
6
|
-
export { default as Card } from './components/card';
|
|
7
|
-
export { default as Checkbox } from './components/checkbox';
|
|
8
|
-
export { default as Collapse } from './components/collapse';
|
|
9
|
-
export { default as Divider } from './components/divider';
|
|
10
|
-
export { default as Input } from './components/input';
|
|
11
|
-
export { default as Modal } from './components/modal';
|
|
12
|
-
export { default as PhoneInput } from './components/phone';
|
|
13
|
-
export { Popover, PopoverContent, PopoverTrigger } from './components/popover';
|
|
14
|
-
export { default as Radio } from './components/radio';
|
|
15
|
-
export { default as Range } from './components/range';
|
|
16
|
-
export { Select, SelectContent, SelectTrigger } from './components/select';
|
|
17
|
-
export { Sheet, SheetContent, SheetTrigger } from './components/sheet';
|
|
18
|
-
export { default as Stars } from './components/stars';
|
|
19
|
-
export { default as StepMarker } from './components/step-marker';
|
|
20
|
-
export { default as Switch } from './components/switch';
|
|
21
|
-
export { default as Tag } from './components/tag';
|
|
22
|
-
export { default as Tooltip } from './components/tooltip';
|
package/src/utils/classes.ts
DELETED
package/src/utils/validation.ts
DELETED
|
@@ -1,164 +0,0 @@
|
|
|
1
|
-
import { isBefore, isValid, parse, subYears } from 'date-fns';
|
|
2
|
-
|
|
3
|
-
export const isValidCpf = (formatedCpf: string): boolean => {
|
|
4
|
-
const cpf = formatedCpf.replace(/\D/g, '');
|
|
5
|
-
|
|
6
|
-
if (cpf.length !== 11 || /^(\d)\1+$/.test(cpf)) {
|
|
7
|
-
return false;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
// Calcular el primer dígito verificador
|
|
11
|
-
let soma = 0;
|
|
12
|
-
|
|
13
|
-
for (let i = 0; i < 9; i++) {
|
|
14
|
-
soma += parseInt(cpf.charAt(i), 10) * (10 - i);
|
|
15
|
-
}
|
|
16
|
-
let digito1 = 11 - (soma % 11);
|
|
17
|
-
if (digito1 > 9) {
|
|
18
|
-
digito1 = 0;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
// Calcular el segundo dígito verificador
|
|
22
|
-
soma = 0;
|
|
23
|
-
for (let i = 0; i < 10; i++) {
|
|
24
|
-
soma += parseInt(cpf.charAt(i), 10) * (11 - i);
|
|
25
|
-
}
|
|
26
|
-
let digito2 = 11 - (soma % 11);
|
|
27
|
-
if (digito2 > 9) {
|
|
28
|
-
digito2 = 0;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
// Verificar si los dígitos verificadores son iguales a los últimos dos dígitos del CPF
|
|
32
|
-
if (
|
|
33
|
-
parseInt(cpf.charAt(9), 10) === digito1 &&
|
|
34
|
-
parseInt(cpf.charAt(10), 10) === digito2
|
|
35
|
-
) {
|
|
36
|
-
return true;
|
|
37
|
-
}
|
|
38
|
-
return false;
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
export const isValidCNPJ = (formatedCnpj: string): boolean => {
|
|
42
|
-
const cnpj = formatedCnpj.replace(/[^\d]+/g, '');
|
|
43
|
-
|
|
44
|
-
if (cnpj.length !== 14) {
|
|
45
|
-
return false;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
if (/^(\d)\1+$/.test(cnpj)) {
|
|
49
|
-
return false;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
let length = cnpj.length - 2;
|
|
53
|
-
let numbers = cnpj.substring(0, length);
|
|
54
|
-
const digitosVerificadores = cnpj.substring(length);
|
|
55
|
-
|
|
56
|
-
let soma = 0;
|
|
57
|
-
let pos = length - 7;
|
|
58
|
-
|
|
59
|
-
for (let i = length; i >= 1; i--) {
|
|
60
|
-
soma += parseInt(numbers.charAt(length - i), 10) * pos--;
|
|
61
|
-
if (pos < 2) {
|
|
62
|
-
pos = 9;
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
const resultado = soma % 11 < 2 ? 0 : 11 - (soma % 11);
|
|
67
|
-
|
|
68
|
-
if (resultado !== parseInt(digitosVerificadores.charAt(0), 10)) {
|
|
69
|
-
return false;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
length += 1;
|
|
73
|
-
numbers = cnpj.substring(0, length);
|
|
74
|
-
soma = 0;
|
|
75
|
-
pos = length - 7;
|
|
76
|
-
|
|
77
|
-
for (let i = length; i >= 1; i--) {
|
|
78
|
-
soma += parseInt(numbers.charAt(length - i), 10) * pos--;
|
|
79
|
-
if (pos < 2) {
|
|
80
|
-
pos = 9;
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
const segundoDigito = soma % 11 < 2 ? 0 : 11 - (soma % 11);
|
|
85
|
-
|
|
86
|
-
return segundoDigito === parseInt(digitosVerificadores.charAt(1), 10);
|
|
87
|
-
};
|
|
88
|
-
|
|
89
|
-
export const isCPF = (document: string) => {
|
|
90
|
-
const onlyNumbers = document?.replace(/\D/g, '');
|
|
91
|
-
|
|
92
|
-
if (onlyNumbers?.length === 11 && isValidCpf(onlyNumbers)) return true;
|
|
93
|
-
|
|
94
|
-
return false;
|
|
95
|
-
};
|
|
96
|
-
|
|
97
|
-
export const isCNPJ = (document: string) => {
|
|
98
|
-
const onlyNumbers = document?.replace(/\D/g, '');
|
|
99
|
-
|
|
100
|
-
if (onlyNumbers?.length === 14 && isValidCNPJ(onlyNumbers)) return true;
|
|
101
|
-
|
|
102
|
-
return false;
|
|
103
|
-
};
|
|
104
|
-
|
|
105
|
-
export const isFullName = (name: string) =>
|
|
106
|
-
/^(?:[A-Za-zÀ-ÿ]{2,}(?: [A-Za-zÀ-ÿ]{2,})+)$/.test(name.trim());
|
|
107
|
-
|
|
108
|
-
export const isValidName = (name: string) =>
|
|
109
|
-
/^[A-Za-zÀ-ÿ\s.'-]+(?: [A-Za-zÀ-ÿ\s.'-]+)*$/.test(name.trim());
|
|
110
|
-
|
|
111
|
-
export const isValidEmail = (email: string) =>
|
|
112
|
-
/^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$/.test(email.trim());
|
|
113
|
-
|
|
114
|
-
export const isValidPhoneNumber = (number: string) => {
|
|
115
|
-
const phoneNumber = number.replace('-', '');
|
|
116
|
-
return /^\d{8}$/.test(phoneNumber) || /^\d{9}$/.test(phoneNumber);
|
|
117
|
-
};
|
|
118
|
-
|
|
119
|
-
export const isValidNumberCode = (numberCode: string) =>
|
|
120
|
-
/^\d{2}$/.test(numberCode.replace(/[()]/g, ''));
|
|
121
|
-
|
|
122
|
-
export const isValidDDD = (areaCode: string) => {
|
|
123
|
-
const dddList = [
|
|
124
|
-
11, 12, 13, 14, 15, 16, 17, 18, 19, 21, 22, 24, 27, 28, 31, 32, 33, 34, 35,
|
|
125
|
-
37, 38, 41, 42, 43, 44, 45, 46, 47, 48, 49, 51, 53, 54, 55, 61, 62, 64, 63,
|
|
126
|
-
65, 66, 67, 68, 69, 71, 73, 74, 75, 77, 79, 81, 82, 83, 84, 85, 86, 87, 88,
|
|
127
|
-
89, 91, 92, 93, 94, 95, 96, 97, 98, 99
|
|
128
|
-
];
|
|
129
|
-
|
|
130
|
-
return dddList.includes(parseFloat(areaCode?.replace(/\D/g, '')));
|
|
131
|
-
};
|
|
132
|
-
|
|
133
|
-
export const isValidChildDate = (date?: string) => {
|
|
134
|
-
if (!date) return 'Data inválida';
|
|
135
|
-
|
|
136
|
-
const birthDate = parse(date, 'yyyy-MM-dd', new Date());
|
|
137
|
-
|
|
138
|
-
if (!isValid(birthDate)) {
|
|
139
|
-
return 'Data inválida';
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
const currentDate = new Date();
|
|
143
|
-
const adultAge = subYears(currentDate, 18);
|
|
144
|
-
|
|
145
|
-
if (isBefore(adultAge, birthDate) && isBefore(birthDate, currentDate)) {
|
|
146
|
-
return true;
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
return 'Idade deve ser entre 1 a 17 anos';
|
|
150
|
-
};
|
|
151
|
-
|
|
152
|
-
export const isValidAdult = (date?: string) => {
|
|
153
|
-
if (!date) return 'Data inválida';
|
|
154
|
-
|
|
155
|
-
const birthDate = parse(date, 'yyyy-MM-dd', new Date());
|
|
156
|
-
|
|
157
|
-
if (!isValid(birthDate)) {
|
|
158
|
-
return 'Data inválida';
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
const adultAge = subYears(new Date(), 18);
|
|
162
|
-
|
|
163
|
-
return isBefore(birthDate, adultAge) || 'Adulto deve ter mais de 18 anos';
|
|
164
|
-
};
|
package/tsconfig.json
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"target": "ES5",
|
|
4
|
-
"module": "ESNext",
|
|
5
|
-
"lib": ["dom", "es6", "es2017"],
|
|
6
|
-
"jsx": "react",
|
|
7
|
-
"declaration": true,
|
|
8
|
-
"declarationDir": "./dist/types",
|
|
9
|
-
"outDir": "./dist",
|
|
10
|
-
"strict": true,
|
|
11
|
-
"moduleResolution": "node",
|
|
12
|
-
"esModuleInterop": true,
|
|
13
|
-
"skipLibCheck": true,
|
|
14
|
-
"forceConsistentCasingInFileNames": true,
|
|
15
|
-
"allowSyntheticDefaultImports": true
|
|
16
|
-
},
|
|
17
|
-
"include": ["src"],
|
|
18
|
-
}
|
package/webpack.config.js
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
const path = require('path');
|
|
2
|
-
|
|
3
|
-
module.exports = {
|
|
4
|
-
mode: 'production',
|
|
5
|
-
entry: './src/index.tsx', // ponto de entrada da sua biblioteca
|
|
6
|
-
output: {
|
|
7
|
-
path: path.resolve(__dirname, 'dist'),
|
|
8
|
-
filename: 'index.js', // bundle final
|
|
9
|
-
library: '@ourtrip/ui', // nome da sua biblioteca
|
|
10
|
-
libraryTarget: 'umd', // gera um bundle compatível com diversos ambientes (CommonJS, AMD, global)
|
|
11
|
-
globalObject: 'this' // necessário para que funcione no Node.js e no browser
|
|
12
|
-
},
|
|
13
|
-
resolve: {
|
|
14
|
-
extensions: ['.ts', '.tsx', '.js']
|
|
15
|
-
},
|
|
16
|
-
// Marque o React e o ReactDOM como "externals" para não incluí-los no bundle final
|
|
17
|
-
externals: {
|
|
18
|
-
react: 'react',
|
|
19
|
-
'react-dom': 'react-dom'
|
|
20
|
-
},
|
|
21
|
-
module: {
|
|
22
|
-
rules: [
|
|
23
|
-
{
|
|
24
|
-
test: /\.tsx?$/,
|
|
25
|
-
use: 'ts-loader',
|
|
26
|
-
exclude: /node_modules/
|
|
27
|
-
}
|
|
28
|
-
]
|
|
29
|
-
},
|
|
30
|
-
devtool: 'source-map' // gera sourcemaps para facilitar o debug
|
|
31
|
-
};
|