@liguelead/design-system 0.0.28 → 0.0.30
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/components/Alert/Alert.stories.tsx +60 -0
- package/components/Button/Button.appearance.ts +2 -2
- package/components/Button/Button.stories.tsx +75 -0
- package/components/Checkbox/Checkbox.stories.tsx +42 -0
- package/components/Combobox/Combobox.stories.tsx +112 -0
- package/components/Combobox/Combobox.styles.ts +7 -3
- package/components/Combobox/Combobox.tsx +3 -10
- package/components/DatePicker/DatePicker.stories.tsx +108 -0
- package/components/DatePicker/DatePicker.styles.ts +394 -50
- package/components/DatePicker/DatePicker.tsx +353 -118
- package/components/DatePicker/DatePicker.types.ts +40 -24
- package/components/Dialog/Dialog.stories.tsx +63 -0
- package/components/IconButton/IconButton.stories.tsx +49 -0
- package/components/InputOpt/InputOpt.stories.tsx +61 -0
- package/components/LinkButton/LinkButton.stories.tsx +88 -0
- package/components/PageWrapper/PageWrapper.stories.tsx +153 -0
- package/components/RadioButton/RadioButton.stories.tsx +70 -0
- package/components/RequiredAsterisk/RequiredAsterisk.stories.tsx +44 -0
- package/components/SegmentedButton/SegmentedButton.stories.tsx +182 -0
- package/components/Select/Select.stories.tsx +63 -0
- package/components/Table/Table.stories.tsx +53 -0
- package/components/Table/Table.styles.ts +76 -0
- package/components/Table/Table.tsx +157 -0
- package/components/Table/Table.types.ts +16 -0
- package/components/Table/index.ts +1 -0
- package/components/Table/utils/getPageNumbers.ts +35 -0
- package/components/Table/utils/index.ts +1 -0
- package/components/Table/utils/types.ts +4 -0
- package/components/Text/Text.stories.tsx +61 -0
- package/components/Text/Text.types.ts +1 -0
- package/components/TextField/TextField.stories.tsx +84 -0
- package/components/Toaster/Toaster.stories.tsx +129 -0
- package/components/Toaster/Toaster.ts +19 -0
- package/components/Toaster/ToasterProvider.tsx +9 -1
- package/components/Wizard/Wizard.stories.tsx +186 -0
- package/components/index.ts +1 -0
- package/package.json +16 -3
|
@@ -1,139 +1,374 @@
|
|
|
1
|
-
import * as DropdownMenu from '@radix-ui/react-dropdown-menu'
|
|
2
1
|
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
}
|
|
15
|
-
import {
|
|
16
|
-
import
|
|
17
|
-
import { DatePickerProps, Months } from './DatePicker.types'
|
|
2
|
+
ChangeEvent,
|
|
3
|
+
forwardRef,
|
|
4
|
+
useEffect,
|
|
5
|
+
useId,
|
|
6
|
+
useMemo,
|
|
7
|
+
useRef,
|
|
8
|
+
useState
|
|
9
|
+
} from 'react'
|
|
10
|
+
import * as Popover from '@radix-ui/react-popover'
|
|
11
|
+
import { CalendarBlankIcon } from '@phosphor-icons/react'
|
|
12
|
+
import { format, parse, startOfDay, isValid } from 'date-fns'
|
|
13
|
+
import { DateRange, DayPicker } from 'react-day-picker'
|
|
14
|
+
import { ptBR } from 'react-day-picker/locale'
|
|
15
|
+
import 'react-day-picker/dist/style.css'
|
|
18
16
|
import {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
17
|
+
CalendarWrapper,
|
|
18
|
+
DatePickerContent,
|
|
19
|
+
DatePickerError,
|
|
20
|
+
DatePickerHiddenInput,
|
|
21
|
+
DatePickerInput,
|
|
22
|
+
DatePickerLabel,
|
|
23
|
+
DatePickerTrigger,
|
|
24
|
+
DatePickerTriggerWrapper,
|
|
25
|
+
IconSlot,
|
|
26
|
+
Wrapper
|
|
24
27
|
} from './DatePicker.styles'
|
|
25
|
-
import
|
|
28
|
+
import { DatePickerProps } from './DatePicker.types'
|
|
29
|
+
import RequiredAsterisk from '../RequiredAsterisk'
|
|
30
|
+
|
|
31
|
+
const serializeDate = (date?: Date) => {
|
|
32
|
+
if (!date || Number.isNaN(date.getTime())) return ''
|
|
33
|
+
return format(date, 'yyyy-MM-dd')
|
|
34
|
+
}
|
|
26
35
|
|
|
27
|
-
const
|
|
36
|
+
const DatePicker = forwardRef<HTMLInputElement, DatePickerProps>(
|
|
28
37
|
(
|
|
29
38
|
{
|
|
30
39
|
label,
|
|
31
40
|
error,
|
|
41
|
+
disabled = false,
|
|
42
|
+
className,
|
|
43
|
+
icon = true,
|
|
44
|
+
size = 'md',
|
|
45
|
+
placeholder = 'DD/MM/AAAA',
|
|
46
|
+
mode = 'single',
|
|
47
|
+
startDate,
|
|
48
|
+
endDate,
|
|
49
|
+
value,
|
|
50
|
+
rangeValue,
|
|
32
51
|
startYear = 1990,
|
|
33
|
-
endYear
|
|
34
|
-
startDate = new Date(),
|
|
35
|
-
icon = false,
|
|
52
|
+
endYear,
|
|
36
53
|
onChange,
|
|
37
|
-
|
|
54
|
+
onRangeChange,
|
|
55
|
+
captionLayout,
|
|
56
|
+
numberOfMonths,
|
|
57
|
+
inline = false,
|
|
58
|
+
required = false,
|
|
38
59
|
register,
|
|
39
|
-
|
|
40
|
-
}
|
|
60
|
+
dayPickerProps
|
|
61
|
+
},
|
|
41
62
|
ref
|
|
42
63
|
) => {
|
|
43
|
-
const
|
|
44
|
-
|
|
64
|
+
const today = useMemo(() => startOfDay(new Date()), [])
|
|
65
|
+
const {
|
|
66
|
+
captionLayout: dayPickerCaptionLayout,
|
|
67
|
+
numberOfMonths: dayPickerNumberOfMonths,
|
|
68
|
+
fromYear: dayPickerFromYear,
|
|
69
|
+
toYear: dayPickerToYear,
|
|
70
|
+
locale: dayPickerLocale,
|
|
71
|
+
today: dayPickerToday,
|
|
72
|
+
...restDayPickerProps
|
|
73
|
+
} = dayPickerProps ?? {}
|
|
74
|
+
|
|
75
|
+
const isRange = mode === 'range'
|
|
76
|
+
const resolvedStartYear = startYear ?? dayPickerFromYear ?? 1990
|
|
77
|
+
const resolvedEndYear = endYear ?? dayPickerToYear ?? today.getFullYear()
|
|
78
|
+
const monthsToRender =
|
|
79
|
+
numberOfMonths ?? dayPickerNumberOfMonths ?? (isRange ? 2 : 1)
|
|
80
|
+
const appliedCaptionLayout =
|
|
81
|
+
captionLayout ?? dayPickerCaptionLayout ?? 'label'
|
|
82
|
+
const resolvedLocale = dayPickerLocale ?? ptBR
|
|
83
|
+
const resolvedToday = dayPickerToday ?? today
|
|
84
|
+
const baseId = useId()
|
|
85
|
+
const errorId = `${baseId}-error`
|
|
86
|
+
const inputRef = useRef<HTMLInputElement | null>(null)
|
|
87
|
+
const [inputValue, setInputValue] = useState(() =>
|
|
88
|
+
!isRange && value ? format(value, 'dd/MM/yyyy') : ''
|
|
45
89
|
)
|
|
46
|
-
const lastYear =
|
|
47
|
-
endYear > startYear ? endYear + 1 : getYear(new Date()) + 1
|
|
48
|
-
const years = range(startYear, lastYear, 1)
|
|
49
90
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
91
|
+
useEffect(() => {
|
|
92
|
+
if (!isRange && value) {
|
|
93
|
+
setInputValue(format(value, 'dd/MM/yyyy'))
|
|
94
|
+
} else if (!isRange && !value) {
|
|
95
|
+
setInputValue('')
|
|
96
|
+
}
|
|
97
|
+
}, [value, isRange])
|
|
98
|
+
|
|
99
|
+
const hiddenValue = useMemo(() => {
|
|
100
|
+
if (isRange) {
|
|
101
|
+
if (!rangeValue?.from && !rangeValue?.to) return ''
|
|
102
|
+
return JSON.stringify({
|
|
103
|
+
from: rangeValue?.from ? serializeDate(rangeValue.from) : null,
|
|
104
|
+
to: rangeValue?.to ? serializeDate(rangeValue.to) : null
|
|
105
|
+
})
|
|
106
|
+
}
|
|
107
|
+
return value ? serializeDate(value) : ''
|
|
108
|
+
}, [isRange, rangeValue, value])
|
|
109
|
+
|
|
110
|
+
const displayValue = useMemo(() => {
|
|
111
|
+
if (isRange) {
|
|
112
|
+
if (rangeValue?.from && rangeValue?.to) {
|
|
113
|
+
return `${format(rangeValue.from, 'dd/MM/yyyy')} - ${format(
|
|
114
|
+
rangeValue.to,
|
|
115
|
+
'dd/MM/yyyy'
|
|
116
|
+
)}`
|
|
117
|
+
}
|
|
118
|
+
if (rangeValue?.from) return format(rangeValue.from, 'dd/MM/yyyy')
|
|
119
|
+
return placeholder
|
|
120
|
+
}
|
|
121
|
+
return value ? format(value, 'dd/MM/yyyy') : placeholder
|
|
122
|
+
}, [isRange, placeholder, rangeValue, value])
|
|
123
|
+
|
|
124
|
+
const isUsingPlaceholder = isRange ? !rangeValue?.from : !value
|
|
125
|
+
const parsedError =
|
|
126
|
+
typeof error === 'string'
|
|
127
|
+
? error
|
|
128
|
+
: typeof error === 'object' &&
|
|
129
|
+
error !== null &&
|
|
130
|
+
'message' in error
|
|
131
|
+
? String((error as { message?: string }).message ?? '')
|
|
132
|
+
: undefined
|
|
133
|
+
|
|
134
|
+
const handleSingleSelect = (date?: Date) => {
|
|
135
|
+
if (disabled) return
|
|
136
|
+
const nextDate = date
|
|
137
|
+
onChange?.(nextDate)
|
|
138
|
+
setInputValue(nextDate ? format(nextDate, 'dd/MM/yyyy') : '')
|
|
139
|
+
register?.onChange({
|
|
140
|
+
target: {
|
|
141
|
+
name: register?.name,
|
|
142
|
+
value: nextDate ? serializeDate(nextDate) : ''
|
|
143
|
+
}
|
|
144
|
+
} as unknown as ChangeEvent<HTMLInputElement>)
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const handleInputChange = (e: ChangeEvent<HTMLInputElement>) => {
|
|
148
|
+
if (disabled || isRange) return
|
|
149
|
+
const rawInput = e.target.value
|
|
150
|
+
const caret = e.target.selectionStart ?? rawInput.length
|
|
151
|
+
const digitsBeforeCaret = rawInput
|
|
152
|
+
.slice(0, caret)
|
|
153
|
+
.replace(/\D/g, '').length
|
|
154
|
+
const numbers = rawInput.replace(/\D/g, '').slice(0, 8)
|
|
155
|
+
|
|
156
|
+
let formatted = ''
|
|
157
|
+
if (numbers.length > 0) {
|
|
158
|
+
formatted = numbers.slice(0, 2)
|
|
159
|
+
if (numbers.length >= 3) formatted += '/' + numbers.slice(2, 4)
|
|
160
|
+
if (numbers.length >= 5) formatted += '/' + numbers.slice(4, 8)
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
const nextCaret = (() => {
|
|
164
|
+
if (digitsBeforeCaret <= 2) return digitsBeforeCaret
|
|
165
|
+
if (digitsBeforeCaret <= 4) return digitsBeforeCaret + 1
|
|
166
|
+
return digitsBeforeCaret + 2
|
|
167
|
+
})()
|
|
168
|
+
|
|
169
|
+
setInputValue(formatted)
|
|
170
|
+
requestAnimationFrame(() => {
|
|
171
|
+
const node = inputRef.current
|
|
172
|
+
if (!node) return
|
|
173
|
+
const safePos = Math.min(nextCaret, formatted.length)
|
|
174
|
+
node.setSelectionRange(safePos, safePos)
|
|
175
|
+
})
|
|
176
|
+
|
|
177
|
+
if (formatted.length === 10) {
|
|
178
|
+
const parsedDate = parse(formatted, 'dd/MM/yyyy', resolvedToday)
|
|
179
|
+
if (isValid(parsedDate)) {
|
|
180
|
+
onChange?.(parsedDate)
|
|
181
|
+
register?.onChange({
|
|
182
|
+
target: {
|
|
183
|
+
name: register?.name,
|
|
184
|
+
value: serializeDate(parsedDate)
|
|
185
|
+
}
|
|
186
|
+
} as unknown as ChangeEvent<HTMLInputElement>)
|
|
187
|
+
}
|
|
188
|
+
} else if (formatted === '') {
|
|
189
|
+
onChange?.(undefined)
|
|
190
|
+
register?.onChange({
|
|
191
|
+
target: {
|
|
192
|
+
name: register?.name,
|
|
193
|
+
value: ''
|
|
120
194
|
}
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
195
|
+
} as unknown as ChangeEvent<HTMLInputElement>)
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
const handleInputBlur = () => {
|
|
200
|
+
if (disabled || isRange) return
|
|
201
|
+
if (!inputValue) return
|
|
202
|
+
if (inputValue.length < 10) {
|
|
203
|
+
const fallback = value ? format(value, 'dd/MM/yyyy') : ''
|
|
204
|
+
setInputValue(fallback)
|
|
205
|
+
return
|
|
206
|
+
}
|
|
207
|
+
const parsedDate = parse(inputValue, 'dd/MM/yyyy', resolvedToday)
|
|
208
|
+
if (isValid(parsedDate)) {
|
|
209
|
+
setInputValue(format(parsedDate, 'dd/MM/yyyy'))
|
|
210
|
+
onChange?.(parsedDate)
|
|
211
|
+
register?.onChange({
|
|
212
|
+
target: {
|
|
213
|
+
name: register?.name,
|
|
214
|
+
value: serializeDate(parsedDate)
|
|
215
|
+
}
|
|
216
|
+
} as unknown as ChangeEvent<HTMLInputElement>)
|
|
217
|
+
} else {
|
|
218
|
+
const fallback = value ? format(value, 'dd/MM/yyyy') : ''
|
|
219
|
+
setInputValue(fallback)
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
const handleRangeSelect = (value?: DateRange) => {
|
|
224
|
+
if (disabled) return
|
|
225
|
+
const nextRange = value
|
|
226
|
+
onRangeChange?.(nextRange)
|
|
227
|
+
const serialized = nextRange
|
|
228
|
+
? JSON.stringify({
|
|
229
|
+
from: nextRange.from
|
|
230
|
+
? serializeDate(nextRange.from)
|
|
231
|
+
: null,
|
|
232
|
+
to: nextRange.to ? serializeDate(nextRange.to) : null
|
|
233
|
+
})
|
|
234
|
+
: ''
|
|
235
|
+
|
|
236
|
+
register?.onChange({
|
|
237
|
+
target: { name: register?.name, value: serialized }
|
|
238
|
+
} as unknown as ChangeEvent<HTMLInputElement>)
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
const picker = (
|
|
242
|
+
<CalendarWrapper $singleMonth={!isRange}>
|
|
243
|
+
{isRange ? (
|
|
244
|
+
<DayPicker
|
|
245
|
+
{...restDayPickerProps}
|
|
246
|
+
locale={resolvedLocale}
|
|
247
|
+
mode="range"
|
|
248
|
+
selected={rangeValue}
|
|
249
|
+
onSelect={handleRangeSelect}
|
|
250
|
+
|
|
251
|
+
captionLayout={appliedCaptionLayout}
|
|
252
|
+
navLayout="around"
|
|
253
|
+
fromYear={resolvedStartYear}
|
|
254
|
+
toYear={resolvedEndYear}
|
|
255
|
+
fromDate={startDate}
|
|
256
|
+
toDate={endDate}
|
|
257
|
+
today={resolvedToday}
|
|
258
|
+
numberOfMonths={monthsToRender}
|
|
259
|
+
required={false}
|
|
260
|
+
defaultMonth={rangeValue?.from ?? resolvedToday}
|
|
132
261
|
/>
|
|
133
|
-
|
|
134
|
-
|
|
262
|
+
) : (
|
|
263
|
+
<DayPicker
|
|
264
|
+
{...restDayPickerProps}
|
|
265
|
+
locale={resolvedLocale}
|
|
266
|
+
mode="single"
|
|
267
|
+
selected={value}
|
|
268
|
+
onSelect={handleSingleSelect}
|
|
269
|
+
captionLayout={appliedCaptionLayout}
|
|
270
|
+
navLayout="around"
|
|
271
|
+
fromYear={resolvedStartYear}
|
|
272
|
+
toYear={resolvedEndYear}
|
|
273
|
+
fromDate={startDate}
|
|
274
|
+
toDate={endDate}
|
|
275
|
+
today={resolvedToday}
|
|
276
|
+
numberOfMonths={monthsToRender}
|
|
277
|
+
required={false}
|
|
278
|
+
defaultMonth={value ?? resolvedToday}
|
|
279
|
+
/>
|
|
280
|
+
)}
|
|
281
|
+
</CalendarWrapper>
|
|
282
|
+
)
|
|
283
|
+
|
|
284
|
+
return (
|
|
285
|
+
<Wrapper className={className}>
|
|
286
|
+
{label && (
|
|
287
|
+
<DatePickerLabel>
|
|
288
|
+
{label} {required && <RequiredAsterisk />}
|
|
289
|
+
</DatePickerLabel>
|
|
290
|
+
)}
|
|
291
|
+
|
|
292
|
+
<DatePickerHiddenInput
|
|
293
|
+
type="hidden"
|
|
294
|
+
value={hiddenValue}
|
|
295
|
+
name={register?.name}
|
|
296
|
+
readOnly
|
|
297
|
+
ref={instance => {
|
|
298
|
+
if (typeof ref === 'function') {
|
|
299
|
+
ref(instance)
|
|
300
|
+
} else if (ref) {
|
|
301
|
+
ref.current = instance
|
|
302
|
+
}
|
|
303
|
+
register?.ref(instance)
|
|
304
|
+
}}
|
|
305
|
+
onChange={register?.onChange}
|
|
306
|
+
onBlur={register?.onBlur}
|
|
307
|
+
/>
|
|
308
|
+
|
|
309
|
+
{inline ? (
|
|
310
|
+
picker
|
|
311
|
+
) : (
|
|
312
|
+
<Popover.Root>
|
|
313
|
+
<DatePickerTriggerWrapper>
|
|
314
|
+
{icon && (
|
|
315
|
+
<Popover.Trigger asChild disabled={disabled}>
|
|
316
|
+
<IconSlot $disabled={disabled} as="button" type="button">
|
|
317
|
+
<CalendarBlankIcon size={16} />
|
|
318
|
+
</IconSlot>
|
|
319
|
+
</Popover.Trigger>
|
|
320
|
+
)}
|
|
321
|
+
|
|
322
|
+
{isRange ? (
|
|
323
|
+
<Popover.Trigger asChild disabled={disabled}>
|
|
324
|
+
<DatePickerTrigger
|
|
325
|
+
type="button"
|
|
326
|
+
disabled={disabled}
|
|
327
|
+
$hasIcon={icon}
|
|
328
|
+
$size={size}
|
|
329
|
+
$error={!!parsedError}
|
|
330
|
+
$isPlaceholder={isUsingPlaceholder}
|
|
331
|
+
aria-invalid={!!parsedError}
|
|
332
|
+
aria-describedby={parsedError ? errorId : undefined}
|
|
333
|
+
>
|
|
334
|
+
{displayValue}
|
|
335
|
+
</DatePickerTrigger>
|
|
336
|
+
</Popover.Trigger>
|
|
337
|
+
) : (
|
|
338
|
+
<Popover.Trigger asChild disabled={disabled}>
|
|
339
|
+
<DatePickerInput
|
|
340
|
+
type="text"
|
|
341
|
+
disabled={disabled}
|
|
342
|
+
$hasIcon={icon}
|
|
343
|
+
$size={size}
|
|
344
|
+
$error={!!parsedError}
|
|
345
|
+
placeholder={placeholder}
|
|
346
|
+
value={inputValue}
|
|
347
|
+
onChange={handleInputChange}
|
|
348
|
+
onBlur={handleInputBlur}
|
|
349
|
+
aria-invalid={!!parsedError}
|
|
350
|
+
aria-describedby={parsedError ? errorId : undefined}
|
|
351
|
+
ref={inputRef}
|
|
352
|
+
/>
|
|
353
|
+
</Popover.Trigger>
|
|
354
|
+
)}
|
|
355
|
+
</DatePickerTriggerWrapper>
|
|
356
|
+
|
|
357
|
+
<Popover.Portal>
|
|
358
|
+
<DatePickerContent sideOffset={8} align="start">
|
|
359
|
+
{picker}
|
|
360
|
+
</DatePickerContent>
|
|
361
|
+
</Popover.Portal>
|
|
362
|
+
</Popover.Root>
|
|
363
|
+
)}
|
|
364
|
+
|
|
365
|
+
{parsedError && (
|
|
366
|
+
<DatePickerError id={errorId}>{parsedError}</DatePickerError>
|
|
367
|
+
)}
|
|
368
|
+
</Wrapper>
|
|
135
369
|
)
|
|
136
370
|
}
|
|
137
371
|
)
|
|
138
372
|
|
|
139
|
-
|
|
373
|
+
DatePicker.displayName = 'DatePicker'
|
|
374
|
+
export default DatePicker
|
|
@@ -1,29 +1,45 @@
|
|
|
1
|
-
import { FieldValues,
|
|
1
|
+
import { FieldValues, UseFormRegisterReturn } from 'react-hook-form'
|
|
2
|
+
import { DateRange, DayPickerProps } from 'react-day-picker'
|
|
2
3
|
|
|
3
|
-
export
|
|
4
|
-
|
|
5
|
-
'Fevereiro',
|
|
6
|
-
'Março',
|
|
7
|
-
'Abril',
|
|
8
|
-
'Maio',
|
|
9
|
-
'Junho',
|
|
10
|
-
'Julho',
|
|
11
|
-
'Agosto',
|
|
12
|
-
'Setembro',
|
|
13
|
-
'Outubro',
|
|
14
|
-
'Novembro',
|
|
15
|
-
'Dezembro'
|
|
16
|
-
]
|
|
4
|
+
export type DatePickerMode = 'single' | 'range'
|
|
5
|
+
export type DatePickerSize = 'sm' | 'md' | 'lg'
|
|
17
6
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
onChange?: (date: Date) => void
|
|
23
|
-
error?: FieldValues
|
|
24
|
-
startDate?: Date
|
|
7
|
+
type DatePickerBaseProps = {
|
|
8
|
+
label?: string
|
|
9
|
+
error?: FieldValues | string | { message?: string } | null
|
|
10
|
+
disabled?: boolean
|
|
25
11
|
className?: string
|
|
12
|
+
required?: boolean
|
|
26
13
|
icon?: boolean
|
|
27
|
-
size?:
|
|
28
|
-
|
|
14
|
+
size?: DatePickerSize
|
|
15
|
+
placeholder?: string
|
|
16
|
+
startDate?: Date
|
|
17
|
+
endDate?: Date
|
|
18
|
+
startYear?: number
|
|
19
|
+
endYear?: number
|
|
20
|
+
captionLayout?: 'label' | 'dropdown' | 'dropdown-months' | 'dropdown-years'
|
|
21
|
+
numberOfMonths?: number
|
|
22
|
+
inline?: boolean
|
|
23
|
+
register?: UseFormRegisterReturn<string>
|
|
24
|
+
dayPickerProps?: Partial<
|
|
25
|
+
Omit<DayPickerProps, 'mode' | 'selected' | 'onSelect' | 'defaultMonth'>
|
|
26
|
+
>
|
|
29
27
|
}
|
|
28
|
+
|
|
29
|
+
export type DatePickerSingleProps = DatePickerBaseProps & {
|
|
30
|
+
mode?: 'single'
|
|
31
|
+
value?: Date | undefined
|
|
32
|
+
onChange?: (date: Date | undefined) => void
|
|
33
|
+
rangeValue?: never
|
|
34
|
+
onRangeChange?: never
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export type DatePickerRangeProps = DatePickerBaseProps & {
|
|
38
|
+
mode: 'range'
|
|
39
|
+
rangeValue?: DateRange | undefined
|
|
40
|
+
onRangeChange?: (range: DateRange | undefined) => void
|
|
41
|
+
value?: never
|
|
42
|
+
onChange?: never
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export type DatePickerProps = DatePickerSingleProps | DatePickerRangeProps
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite'
|
|
2
|
+
import Dialog from './Dialog'
|
|
3
|
+
import Button from '../Button/Button'
|
|
4
|
+
|
|
5
|
+
const meta: Meta<typeof Dialog> = {
|
|
6
|
+
title: 'Feedback/Dialog',
|
|
7
|
+
component: Dialog,
|
|
8
|
+
parameters: {
|
|
9
|
+
layout: 'centered'
|
|
10
|
+
},
|
|
11
|
+
tags: ['autodocs'],
|
|
12
|
+
argTypes: {
|
|
13
|
+
title: {
|
|
14
|
+
control: 'text',
|
|
15
|
+
description: 'Dialog title'
|
|
16
|
+
},
|
|
17
|
+
description: {
|
|
18
|
+
control: 'text',
|
|
19
|
+
description: 'Dialog description'
|
|
20
|
+
},
|
|
21
|
+
variant: {
|
|
22
|
+
control: 'select',
|
|
23
|
+
options: ['default', 'danger'],
|
|
24
|
+
description: 'Dialog variant'
|
|
25
|
+
},
|
|
26
|
+
confirmButton: {
|
|
27
|
+
control: 'boolean',
|
|
28
|
+
description: 'Show confirm button'
|
|
29
|
+
},
|
|
30
|
+
cancelButton: {
|
|
31
|
+
control: 'boolean',
|
|
32
|
+
description: 'Show cancel button'
|
|
33
|
+
},
|
|
34
|
+
confirmLabel: {
|
|
35
|
+
control: 'text',
|
|
36
|
+
description: 'Confirm button label'
|
|
37
|
+
},
|
|
38
|
+
cancelLabel: {
|
|
39
|
+
control: 'text',
|
|
40
|
+
description: 'Cancel button label'
|
|
41
|
+
},
|
|
42
|
+
confirmButtonColor: {
|
|
43
|
+
control: 'select',
|
|
44
|
+
options: ['primary', 'secondary'],
|
|
45
|
+
description: 'Confirm button color'
|
|
46
|
+
},
|
|
47
|
+
centerContent: {
|
|
48
|
+
control: 'boolean',
|
|
49
|
+
description: 'Center dialog content'
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export default meta
|
|
55
|
+
type Story = StoryObj<typeof meta>
|
|
56
|
+
|
|
57
|
+
export const Default: Story = {
|
|
58
|
+
args: {
|
|
59
|
+
title: 'Dialog Title',
|
|
60
|
+
description: 'This is a dialog description.',
|
|
61
|
+
trigger: <Button>Open Dialog</Button>
|
|
62
|
+
}
|
|
63
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite'
|
|
2
|
+
import IconButton from './IconButton'
|
|
3
|
+
import { themes } from '@liguelead/foundation'
|
|
4
|
+
import { iconMap } from '../../../stories/utils/icons'
|
|
5
|
+
|
|
6
|
+
const themeColors = Object.keys(themes.spa.colors)
|
|
7
|
+
|
|
8
|
+
const meta = {
|
|
9
|
+
title: 'Form/IconButton',
|
|
10
|
+
component: IconButton,
|
|
11
|
+
parameters: {
|
|
12
|
+
layout: 'centered',
|
|
13
|
+
},
|
|
14
|
+
tags: ['autodocs'],
|
|
15
|
+
argTypes: {
|
|
16
|
+
variant: {
|
|
17
|
+
control: 'select',
|
|
18
|
+
options: ['solid', 'outline', 'ghost', 'neutralOutline', 'neutralGhost'],
|
|
19
|
+
description: 'Visual style variant of the icon button'
|
|
20
|
+
},
|
|
21
|
+
size: {
|
|
22
|
+
control: 'select',
|
|
23
|
+
options: ['sm', 'md', 'lg'],
|
|
24
|
+
description: 'Size of the icon button'
|
|
25
|
+
},
|
|
26
|
+
color: {
|
|
27
|
+
control: 'select',
|
|
28
|
+
options: themeColors,
|
|
29
|
+
description: 'Color theme of the icon button'
|
|
30
|
+
},
|
|
31
|
+
disabled: {
|
|
32
|
+
control: 'boolean',
|
|
33
|
+
description: 'Whether the icon button is disabled'
|
|
34
|
+
},
|
|
35
|
+
children: {
|
|
36
|
+
control: false,
|
|
37
|
+
description: 'Icon content'
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
} satisfies Meta<typeof IconButton>
|
|
41
|
+
|
|
42
|
+
export default meta
|
|
43
|
+
type Story = StoryObj<typeof meta>
|
|
44
|
+
|
|
45
|
+
export const Default: Story = {
|
|
46
|
+
args: {
|
|
47
|
+
children: iconMap.HeartIcon,
|
|
48
|
+
},
|
|
49
|
+
}
|