@oatfi/ui 0.1.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.
@@ -0,0 +1,1602 @@
1
+ import { createTheme, ThemeProvider as ThemeProvider$2 } from '@mui/material/styles';
2
+ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
3
+ import { useMemo, useId, useRef, useState } from 'react';
4
+ import styled, { createGlobalStyle, ThemeProvider as ThemeProvider$1, useTheme as useTheme$1 } from 'styled-components';
5
+ import { TextField, InputAdornment, IconButton, FormControl, InputLabel as InputLabel$1, Select, MenuItem, FormHelperText, Autocomplete, Box, CircularProgress } from '@mui/material';
6
+ import CalendarMonthIcon from '@mui/icons-material/CalendarMonth';
7
+ import CloudUploadIcon from '@mui/icons-material/CloudUpload';
8
+ import CloseIcon from '@mui/icons-material/Close';
9
+ import IconButton$1 from '@mui/material/IconButton';
10
+ import Menu from '@mui/material/Menu';
11
+ import MenuItem$1 from '@mui/material/MenuItem';
12
+ import MoreVertIcon from '@mui/icons-material/MoreVert';
13
+
14
+ const defaultTheme = {
15
+ colors: {
16
+ primary: "#111827",
17
+ secondary: "#6B7280",
18
+ accent: "#2563EB",
19
+ background: "#FFFFFF",
20
+ surface: "#F3F4F6",
21
+ border: "#E5E7EB",
22
+ success: "#10B981",
23
+ default: "#6B7280",
24
+ warning: "#F59E42",
25
+ error: "#EF4444",
26
+ buttonPrimary: "#111827",
27
+ buttonSecondary: "#6B7280"
28
+ },
29
+ border: {
30
+ radius: "8px",
31
+ width: "1px",
32
+ color: "#E5E7EB"
33
+ },
34
+ typography: {
35
+ fontFamily: '"Geist", "Geist Sans", Arial, sans-serif'
36
+ }
37
+ };
38
+
39
+ const toPx = (value) => `${value}px`;
40
+ function mergeBranding(branding) {
41
+ const b = branding ?? {};
42
+ const primary = b.primaryColor ?? defaultTheme.colors.primary;
43
+ const secondary = b.secondaryColor ?? defaultTheme.colors.secondary;
44
+ return {
45
+ ...defaultTheme,
46
+ colors: {
47
+ ...defaultTheme.colors,
48
+ primary,
49
+ secondary,
50
+ buttonPrimary: b.primaryButtonColor ?? primary,
51
+ buttonSecondary: b.secondaryButtonColor ?? secondary
52
+ },
53
+ border: {
54
+ ...defaultTheme.border,
55
+ radius: b.borderRadius != null ? toPx(b.borderRadius) : defaultTheme.border.radius,
56
+ width: b.borderWidth != null ? toPx(b.borderWidth) : defaultTheme.border.width
57
+ },
58
+ typography: {
59
+ ...defaultTheme.typography,
60
+ fontFamily: b.fontFamily ?? defaultTheme.typography.fontFamily
61
+ }
62
+ };
63
+ }
64
+
65
+ function buildMuiTheme(theme) {
66
+ const { colors, border, typography } = theme;
67
+ return createTheme({
68
+ palette: {
69
+ primary: {
70
+ main: colors.accent,
71
+ contrastText: colors.background
72
+ },
73
+ secondary: {
74
+ main: colors.secondary
75
+ },
76
+ error: {
77
+ main: colors.error
78
+ },
79
+ warning: {
80
+ main: colors.warning
81
+ },
82
+ success: {
83
+ main: colors.success
84
+ },
85
+ background: {
86
+ default: colors.background,
87
+ paper: colors.surface
88
+ },
89
+ text: {
90
+ primary: colors.primary,
91
+ secondary: colors.secondary
92
+ }
93
+ },
94
+ typography: {
95
+ fontFamily: typography.fontFamily,
96
+ fontSize: 14
97
+ },
98
+ shape: {
99
+ borderRadius: parseInt(border.radius, 10)
100
+ },
101
+ components: {
102
+ MuiFormControlLabel: {
103
+ styleOverrides: {
104
+ label: {
105
+ fontSize: "12px",
106
+ fontWeight: 400
107
+ }
108
+ }
109
+ },
110
+ MuiPaper: {
111
+ styleOverrides: {
112
+ root: {
113
+ backgroundColor: colors.background,
114
+ border: `${border.width} solid ${border.color}`
115
+ }
116
+ },
117
+ defaultProps: {
118
+ elevation: 0
119
+ }
120
+ },
121
+ MuiLink: {
122
+ styleOverrides: {
123
+ root: {
124
+ cursor: "pointer",
125
+ fontSize: "16px",
126
+ fontWeight: 600,
127
+ fontFamily: typography.fontFamily
128
+ }
129
+ }
130
+ },
131
+ MuiTextField: {
132
+ styleOverrides: {
133
+ root: {
134
+ "& .MuiOutlinedInput-root": {
135
+ "& fieldset": {
136
+ borderColor: border.color,
137
+ borderWidth: border.width
138
+ },
139
+ "&:hover fieldset": {
140
+ borderColor: colors.accent
141
+ },
142
+ "&.Mui-focused fieldset": {
143
+ borderColor: colors.accent
144
+ },
145
+ "&.Mui-error fieldset": {
146
+ borderColor: colors.error
147
+ }
148
+ },
149
+ "& .MuiInputLabel-root, & .MuiFormLabel-root, & .MuiInputLabel-formControl": {
150
+ color: colors.secondary,
151
+ fontSize: "14px",
152
+ "&.Mui-focused": {
153
+ color: colors.accent
154
+ },
155
+ "&.Mui-error": {
156
+ color: colors.error
157
+ }
158
+ },
159
+ "& .MuiInputBase-input": {
160
+ fontSize: 14,
161
+ color: colors.primary,
162
+ "&::placeholder": {
163
+ color: colors.secondary,
164
+ opacity: 1
165
+ }
166
+ }
167
+ }
168
+ }
169
+ },
170
+ MuiSelect: {
171
+ styleOverrides: {
172
+ select: {
173
+ fontSize: 14
174
+ }
175
+ }
176
+ },
177
+ MuiInputBase: {
178
+ styleOverrides: {
179
+ root: {
180
+ fontSize: 14,
181
+ '& input[type="date"]::-webkit-calendar-picker-indicator': {
182
+ display: "none"
183
+ },
184
+ "& .Mui-error": {
185
+ color: colors.error
186
+ },
187
+ '& input[type="date"]::-webkit-inner-spin-button': {
188
+ display: "none"
189
+ },
190
+ '& input[type="date"]::-webkit-clear-button': {
191
+ display: "none"
192
+ }
193
+ }
194
+ }
195
+ },
196
+ MuiFormControl: {
197
+ styleOverrides: {
198
+ root: {
199
+ "& input::-webkit-datetime-edit": {
200
+ color: colors.secondary
201
+ },
202
+ "& .Mui-error": {
203
+ input: {
204
+ color: colors.error
205
+ },
206
+ label: {
207
+ color: colors.error
208
+ }
209
+ }
210
+ }
211
+ }
212
+ }
213
+ }
214
+ });
215
+ }
216
+
217
+ const GlobalStyle = createGlobalStyle`
218
+ * {
219
+ font-family: ${({ theme }) => theme.typography.fontFamily};
220
+ box-sizing: border-box;
221
+ }
222
+ `;
223
+ function ThemeProvider({ branding, children }) {
224
+ const theme = useMemo(() => mergeBranding(branding), [branding]);
225
+ const muiTheme = useMemo(() => buildMuiTheme(theme), [theme]);
226
+ return /* @__PURE__ */ jsxs(ThemeProvider$1, { theme, children: [
227
+ /* @__PURE__ */ jsx(GlobalStyle, {}),
228
+ /* @__PURE__ */ jsx(ThemeProvider$2, { theme: muiTheme, children })
229
+ ] });
230
+ }
231
+
232
+ const useTheme = () => useTheme$1();
233
+
234
+ const chevronDataUri = (color) => `data:image/svg+xml;utf8,<svg fill="${encodeURIComponent(
235
+ color
236
+ )}" height="20" viewBox="0 0 20 20" width="20" xmlns="http://www.w3.org/2000/svg"><path d="M7.293 7.293a1 1 0 011.414 0L10 8.586l1.293-1.293a1 1 0 111.414 1.414l-2 2a1 1 0 01-1.414 0l-2-2a1 1 0 010-1.414z"/></svg>`;
237
+ const InputWrapper = styled.div`
238
+ display: flex;
239
+ flex-direction: column;
240
+ gap: 5px;
241
+ width: 100%;
242
+
243
+ span.icon {
244
+ position: absolute;
245
+ right: 1rem;
246
+ top: 51%;
247
+ display: flex;
248
+ align-items: center;
249
+ cursor: pointer;
250
+ z-index: 1;
251
+ }
252
+
253
+ &.Werror span.icon {
254
+ top: 42%;
255
+ }
256
+ `;
257
+ const InputLabel = styled.label`
258
+ color: ${({ theme }) => theme.colors.primary};
259
+ font-size: 14px;
260
+ font-weight: 500;
261
+ margin-bottom: 4px;
262
+ `;
263
+ const InputError = styled.span`
264
+ color: ${({ theme }) => theme.colors.error};
265
+ font-size: 12px;
266
+ font-weight: 500;
267
+ margin-top: -4px;
268
+ padding-left: 5px;
269
+ `;
270
+ const BaseInput = styled.input`
271
+ display: flex;
272
+ padding: 9px;
273
+ border: ${({ theme }) => theme.border.width} solid ${({ theme }) => theme.border.color};
274
+ border-radius: ${({ theme }) => theme.border.radius};
275
+ background: ${({ theme }) => theme.colors.background};
276
+ color: ${({ theme }) => theme.colors.primary};
277
+ font-size: 14px;
278
+ font-family: ${({ theme }) => theme.typography.fontFamily};
279
+ outline: none;
280
+ transition: border-color 0.2s;
281
+
282
+ &[type='date'] {
283
+ &::-webkit-calendar-picker-indicator {
284
+ opacity: 0;
285
+ pointer-events: none;
286
+ }
287
+ &::-moz-calendar-picker-indicator {
288
+ opacity: 0;
289
+ pointer-events: none;
290
+ }
291
+ &::-ms-input-placeholder {
292
+ opacity: 0;
293
+ pointer-events: none;
294
+ }
295
+ }
296
+
297
+ &:focus {
298
+ border-color: ${({ theme }) => theme.colors.accent};
299
+ }
300
+
301
+ &::placeholder {
302
+ color: ${({ theme }) => theme.colors.secondary};
303
+ opacity: 1;
304
+ }
305
+
306
+ &.error {
307
+ border-color: ${({ theme }) => theme.colors.error};
308
+ color: ${({ theme }) => theme.colors.error};
309
+
310
+ &::placeholder {
311
+ color: ${({ theme }) => theme.colors.error};
312
+ opacity: 1;
313
+ }
314
+ }
315
+ `;
316
+ const SelectInput = styled(BaseInput)`
317
+ appearance: none;
318
+ background-image: url('${({ theme }) => chevronDataUri(theme.colors.default)}');
319
+ background-repeat: no-repeat;
320
+ background-position: right 12px center;
321
+ background-size: 20px 20px;
322
+ `;
323
+ const DropdownContainer = styled.div`
324
+ position: relative;
325
+ width: 100%;
326
+ `;
327
+ const AutocompleteInput = styled(BaseInput)`
328
+ cursor: pointer;
329
+ background-image: url('${({ theme }) => chevronDataUri(theme.colors.default)}');
330
+ background-repeat: no-repeat;
331
+ background-position: right 12px center;
332
+ background-size: 20px 20px;
333
+ width: 100%;
334
+ `;
335
+ const DropdownList = styled.div`
336
+ position: absolute;
337
+ top: 100%;
338
+ left: 0;
339
+ right: 0;
340
+ max-height: 200px;
341
+ overflow-y: auto;
342
+ background: ${({ theme }) => theme.colors.background};
343
+ border: ${({ theme }) => theme.border.width} solid ${({ theme }) => theme.border.color};
344
+ border-top: none;
345
+ border-radius: 0 0 ${({ theme }) => theme.border.radius} ${({ theme }) => theme.border.radius};
346
+ z-index: 1000;
347
+ display: ${({ $isOpen }) => $isOpen ? "block" : "none"};
348
+ box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
349
+ `;
350
+ const DropdownItem = styled.div`
351
+ padding: 8px 12px;
352
+ cursor: pointer;
353
+ background: ${({ $isSelected, theme }) => $isSelected ? theme.colors.accent + "20" : "transparent"};
354
+ color: ${({ theme }) => theme.colors.primary};
355
+ font-size: 14px;
356
+ border-bottom: 1px solid ${({ theme }) => theme.border.color};
357
+
358
+ &:hover {
359
+ background: ${({ theme }) => theme.colors.accent + "10"};
360
+ }
361
+
362
+ &:last-child {
363
+ border-bottom: none;
364
+ }
365
+ `;
366
+ const NoResults = styled.div`
367
+ padding: 12px;
368
+ text-align: center;
369
+ color: ${({ theme }) => theme.colors.secondary};
370
+ font-size: 14px;
371
+ `;
372
+
373
+ const H3 = styled.h3`
374
+ font-size: 18px;
375
+ font-weight: 500;
376
+ color: ${({ theme }) => theme.colors.primary};
377
+ `;
378
+ const H2 = styled.h2`
379
+ font-size: 24px;
380
+ font-weight: 600;
381
+ color: ${({ theme }) => theme.colors.primary};
382
+ `;
383
+ const H1 = styled.h1`
384
+ font-size: 32px;
385
+ font-weight: 600;
386
+ color: ${({ theme }) => theme.colors.primary};
387
+ `;
388
+ const Body100 = styled.p`
389
+ font-size: 12px;
390
+ font-weight: 400;
391
+ text-align: justify;
392
+ color: ${({ color, theme }) => color === "secondary" ? theme.colors.secondary : theme.colors.primary};
393
+ a {
394
+ font-size: 12px;
395
+ color: ${({ theme }) => theme.colors.primary};
396
+ text-decoration-color: ${({ theme }) => theme.colors.primary};
397
+ }
398
+ &.bold {
399
+ font-weight: 600;
400
+ }
401
+ span {
402
+ font-weight: 400;
403
+ }
404
+ `;
405
+ const Body200 = styled.p`
406
+ font-size: 14px;
407
+ font-weight: 400;
408
+ text-align: justify;
409
+ color: ${({ color, theme }) => color === "secondary" ? theme.colors.secondary : theme.colors.primary};
410
+ a {
411
+ font-size: 14px;
412
+ color: ${({ theme }) => theme.colors.primary};
413
+ text-decoration-color: ${({ theme }) => theme.colors.primary};
414
+ }
415
+ &.bold {
416
+ font-weight: 600;
417
+ }
418
+ span {
419
+ font-weight: 400;
420
+ }
421
+ `;
422
+ const Body400 = styled.p`
423
+ font-size: 11px;
424
+ font-weight: 400;
425
+ text-align: justify;
426
+ color: ${({ theme }) => theme.colors.primary};
427
+ `;
428
+ const Container = styled.div`
429
+ padding: 2rem;
430
+ border-radius: ${({ theme }) => theme.border.radius};
431
+ background-color: ${({ theme }) => theme.colors.background};
432
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
433
+ max-width: 1000px;
434
+ margin: 0 auto;
435
+ `;
436
+ const Content = styled.div`
437
+ margin-top: 1.5rem;
438
+ margin-bottom: 1.5rem;
439
+ `;
440
+ const ButtonContainer = styled.div`
441
+ display: flex;
442
+ justify-content: flex-end;
443
+ align-items: center;
444
+ gap: 1rem;
445
+ &.space-between {
446
+ justify-content: space-between;
447
+ }
448
+ `;
449
+ const Button = styled.button`
450
+ align-items: center;
451
+ background-color: ${({ theme }) => theme.colors.buttonPrimary};
452
+ border: none;
453
+ border-radius: ${({ theme }) => theme.border.radius};
454
+ color: ${({ theme }) => theme.colors.background};
455
+ cursor: pointer;
456
+ display: flex;
457
+ font-size: 14px;
458
+ gap: 0.25rem;
459
+ justify-content: center;
460
+ margin-top: 1rem;
461
+ padding: 0.75rem 1.5rem;
462
+ transition: background-color 0.2s ease;
463
+
464
+ &:disabled {
465
+ cursor: not-allowed;
466
+ opacity: 0.35;
467
+ }
468
+
469
+ &:hover {
470
+ background-color: ${({ theme }) => `${theme.colors.buttonPrimary}CC`};
471
+ }
472
+
473
+ &.secondary {
474
+ background-color: ${({ theme }) => theme.colors.background};
475
+ color: ${({ theme }) => theme.colors.buttonSecondary};
476
+ border: 1px solid ${({ theme }) => theme.colors.buttonSecondary};
477
+ &:hover {
478
+ background-color: ${({ theme }) => `${theme.colors.buttonSecondary}10`};
479
+ }
480
+ }
481
+
482
+ &.link {
483
+ background-color: transparent;
484
+ color: ${({ theme }) => theme.colors.accent};
485
+ border: none;
486
+ cursor: pointer;
487
+ margin: 0;
488
+ }
489
+ &.link:hover {
490
+ color: ${({ theme }) => theme.colors.accent};
491
+ text-decoration: underline;
492
+ }
493
+ &.no-padding {
494
+ padding: 0;
495
+ }
496
+ `;
497
+ const FlexRowWrapper = styled.div`
498
+ display: flex;
499
+ flex-direction: row;
500
+ .flex-row-item {
501
+ flex: 1;
502
+ }
503
+ `;
504
+ const FlexColumnWrapper = styled.div`
505
+ display: flex;
506
+ flex-direction: column;
507
+ gap: 10px;
508
+ `;
509
+ const DetailsContainer = styled.div`
510
+ position: relative;
511
+ display: flex;
512
+ flex-direction: column;
513
+ gap: 5px;
514
+ justify-content: space-between;
515
+ button {
516
+ color: ${({ theme }) => theme.colors.primary};
517
+ text-decoration-color: ${({ theme }) => theme.colors.primary};
518
+ }
519
+ `;
520
+ const DetailRow = styled.div`
521
+ display: flex;
522
+ flex-direction: row;
523
+ justify-content: space-between;
524
+ `;
525
+ const DetailElement = styled.div`
526
+ flex: 1;
527
+ p {
528
+ margin: 5px 0 0 0;
529
+ }
530
+ `;
531
+ const TermsList = styled.ul`
532
+ list-style-type: disc;
533
+ padding-left: 20px;
534
+ p {
535
+ margin: 0;
536
+ }
537
+ `;
538
+ const StatusTag = styled.div`
539
+ padding: 4px 8px;
540
+ border-radius: 4px;
541
+ color: ${({ theme }) => theme.colors.background};
542
+ display: flex;
543
+ flex-direction: row;
544
+ align-items: center;
545
+ text-transform: capitalize;
546
+ &.small {
547
+ font-size: 10px;
548
+ padding: 2px 4px;
549
+ }
550
+ &.success {
551
+ background-color: ${({ theme }) => theme.colors.success};
552
+ }
553
+ &.error {
554
+ background-color: ${({ theme }) => theme.colors.error};
555
+ }
556
+ &.warning {
557
+ background-color: ${({ theme }) => theme.colors.warning};
558
+ }
559
+ `;
560
+
561
+ const Form = styled.form`
562
+ max-width: 1000px;
563
+ margin: 0 auto;
564
+ `;
565
+ const FormTitle = styled.h2`
566
+ font-size: 1.5rem;
567
+ font-weight: 600;
568
+ margin-bottom: 2rem;
569
+ color: ${({ theme }) => theme.colors.primary};
570
+ `;
571
+ const FormSubtitle = styled.h3`
572
+ font-size: 14px;
573
+ font-weight: 500;
574
+ color: ${({ theme }) => theme.colors.primary};
575
+ `;
576
+ const FormRow = styled.div`
577
+ display: flex;
578
+ gap: 1rem;
579
+ margin-bottom: 1rem;
580
+ flex-wrap: wrap;
581
+
582
+ @media (max-width: 768px) {
583
+ flex-direction: column;
584
+ }
585
+ `;
586
+ const FormColumn = styled.div`
587
+ flex: 1;
588
+ min-width: 200px;
589
+ `;
590
+ const FormCheckboxLabel = styled.label`
591
+ display: flex;
592
+ align-items: center;
593
+ gap: 0.5rem;
594
+ cursor: pointer;
595
+ color: ${({ theme }) => theme.colors.primary};
596
+ font-size: 0.875rem;
597
+
598
+ input[type='checkbox'] {
599
+ margin: 0;
600
+ }
601
+ `;
602
+ const FormActions = styled.div`
603
+ margin-top: 2rem;
604
+ display: flex;
605
+ justify-content: flex-end;
606
+ `;
607
+
608
+ function TextInput({
609
+ label,
610
+ error,
611
+ value,
612
+ onChange,
613
+ placeholder,
614
+ type = "text",
615
+ required = false,
616
+ disabled = false,
617
+ className,
618
+ name,
619
+ testId,
620
+ max,
621
+ ignoreNumbers = false,
622
+ onlyNumbers = false
623
+ }) {
624
+ const handleChange = (e) => {
625
+ let newValue = e.target.value;
626
+ if (ignoreNumbers) {
627
+ newValue = newValue.replace(/[0-9]/g, "");
628
+ }
629
+ if (onlyNumbers) {
630
+ newValue = newValue.replace(/[^0-9]/g, "");
631
+ }
632
+ if (type === "number" && max !== void 0 && newValue !== "") {
633
+ const numericValue = parseFloat(newValue);
634
+ if (!isNaN(numericValue) && numericValue > max) {
635
+ return;
636
+ }
637
+ }
638
+ onChange(newValue);
639
+ };
640
+ return /* @__PURE__ */ jsx(
641
+ TextField,
642
+ {
643
+ label,
644
+ value,
645
+ onChange: handleChange,
646
+ placeholder,
647
+ type,
648
+ required,
649
+ disabled,
650
+ className,
651
+ name,
652
+ error: !!error,
653
+ helperText: error,
654
+ fullWidth: true,
655
+ variant: "outlined",
656
+ size: "small",
657
+ slotProps: {
658
+ htmlInput: {
659
+ ...type === "number" ? { max } : { maxLength: max },
660
+ "data-testid": testId
661
+ }
662
+ }
663
+ }
664
+ );
665
+ }
666
+
667
+ function EmailInput({ placeholder = "Enter email address", ...props }) {
668
+ return /* @__PURE__ */ jsx(TextInput, { ...props, type: "email", placeholder });
669
+ }
670
+
671
+ const formatPhoneNumber = (value) => {
672
+ if (!value) return "";
673
+ const phoneNumber = value.replace(/\D/g, "");
674
+ if (phoneNumber.length <= 3) {
675
+ return phoneNumber;
676
+ } else if (phoneNumber.length <= 6) {
677
+ return `(${phoneNumber.slice(0, 3)}) ${phoneNumber.slice(3)}`;
678
+ }
679
+ return `(${phoneNumber.slice(0, 3)}) ${phoneNumber.slice(3, 6)}-${phoneNumber.slice(6, 10)}`;
680
+ };
681
+ function PhoneInput({
682
+ placeholder = "(XXX) XXX-XXXX",
683
+ value,
684
+ onChange,
685
+ ...props
686
+ }) {
687
+ const handleChange = (maskedValue) => {
688
+ onChange(maskedValue.replace(/\D/g, "").slice(0, 10));
689
+ };
690
+ return /* @__PURE__ */ jsx(
691
+ TextInput,
692
+ {
693
+ ...props,
694
+ value: formatPhoneNumber(value),
695
+ onChange: handleChange,
696
+ placeholder,
697
+ max: 14
698
+ }
699
+ );
700
+ }
701
+
702
+ const formatDisplayValue$2 = (rawValue) => {
703
+ if (!rawValue) return "";
704
+ const digits = rawValue.replace(/[^\d]/g, "");
705
+ if (digits.length <= 3) return digits;
706
+ if (digits.length <= 5) return `${digits.slice(0, 3)}-${digits.slice(3)}`;
707
+ return `${digits.slice(0, 3)}-${digits.slice(3, 5)}-${digits.slice(5, 9)}`;
708
+ };
709
+ function SSNInput({
710
+ placeholder = "XXX-XX-XXXX",
711
+ value,
712
+ onChange,
713
+ ...props
714
+ }) {
715
+ return /* @__PURE__ */ jsx(
716
+ TextInput,
717
+ {
718
+ ...props,
719
+ value: formatDisplayValue$2(value),
720
+ onChange,
721
+ placeholder,
722
+ max: 11
723
+ }
724
+ );
725
+ }
726
+
727
+ const formatDisplayValue$1 = (rawValue) => {
728
+ if (!rawValue) return "";
729
+ const digits = rawValue.replace(/[^\d]/g, "");
730
+ if (digits.length <= 2) return digits;
731
+ if (digits.length <= 9) return `${digits.slice(0, 2)}-${digits.slice(2)}`;
732
+ return `${digits.slice(0, 2)}-${digits.slice(2, 9)}`;
733
+ };
734
+ function TaxIdInput({
735
+ placeholder = "XX-XXXXXXX",
736
+ value,
737
+ onChange,
738
+ ...props
739
+ }) {
740
+ return /* @__PURE__ */ jsx(
741
+ TextInput,
742
+ {
743
+ ...props,
744
+ value: formatDisplayValue$1(value),
745
+ onChange,
746
+ placeholder,
747
+ max: 10
748
+ }
749
+ );
750
+ }
751
+
752
+ const CurrencyInputWrapper = styled.div`
753
+ position: relative;
754
+ width: 100%;
755
+ `;
756
+ const CurrencyPrefix = styled.span`
757
+ position: absolute;
758
+ left: 9px;
759
+ top: 50%;
760
+ transform: translateY(-50%);
761
+ color: ${({ theme, $hasError }) => $hasError ? theme.colors.error : theme.colors.primary};
762
+ font-size: 14px;
763
+ font-family: ${({ theme }) => theme.typography.fontFamily};
764
+ pointer-events: none;
765
+ z-index: 1;
766
+ `;
767
+ const StyledBaseInput = styled(BaseInput)`
768
+ padding-left: calc(15px + 1ch);
769
+ width: 100%;
770
+ `;
771
+ const formatDisplayValue = (rawValue) => {
772
+ if (!rawValue || rawValue === "") return "";
773
+ const numericValue = rawValue.toString().replace(/[^\d.]/g, "");
774
+ if (numericValue === "" || numericValue === ".") return "";
775
+ const parts = numericValue.split(".");
776
+ const integerPart = parts[0] || "";
777
+ const decimalPart = parts[1] || "";
778
+ const formattedInteger = integerPart.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
779
+ const formattedDecimal = decimalPart.slice(0, 2);
780
+ if (formattedDecimal) {
781
+ return `${formattedInteger}.${formattedDecimal}`;
782
+ } else if (numericValue.includes(".")) {
783
+ return `${formattedInteger}.`;
784
+ }
785
+ return `${formattedInteger}`;
786
+ };
787
+ const extractRawValue = (formattedValue) => {
788
+ if (!formattedValue) return "";
789
+ const raw = formattedValue.replace(/[^\d.]/g, "");
790
+ const parts = raw.split(".");
791
+ if (parts.length > 2) {
792
+ return parts[0] + "." + parts.slice(1).join("");
793
+ }
794
+ return raw;
795
+ };
796
+ function CurrencyInput({
797
+ label,
798
+ value,
799
+ onChange,
800
+ placeholder,
801
+ required,
802
+ disabled,
803
+ error,
804
+ className,
805
+ name,
806
+ testId
807
+ }) {
808
+ const reactId = useId();
809
+ const inputId = `${reactId}-input`;
810
+ const errorId = `${reactId}-error`;
811
+ const handleChange = (e) => {
812
+ onChange(extractRawValue(e.target.value));
813
+ };
814
+ return /* @__PURE__ */ jsxs(InputWrapper, { className, children: [
815
+ label && /* @__PURE__ */ jsx(InputLabel, { htmlFor: inputId, children: label }),
816
+ /* @__PURE__ */ jsxs(CurrencyInputWrapper, { children: [
817
+ /* @__PURE__ */ jsx(CurrencyPrefix, { $hasError: !!error, children: "$" }),
818
+ /* @__PURE__ */ jsx(
819
+ StyledBaseInput,
820
+ {
821
+ id: inputId,
822
+ name,
823
+ type: "text",
824
+ value: formatDisplayValue(value || ""),
825
+ onChange: handleChange,
826
+ placeholder,
827
+ required,
828
+ disabled,
829
+ className: error ? "error" : "",
830
+ "aria-invalid": !!error,
831
+ "aria-describedby": error ? errorId : void 0,
832
+ "data-testid": testId
833
+ }
834
+ )
835
+ ] }),
836
+ error && /* @__PURE__ */ jsx(InputError, { id: errorId, children: error })
837
+ ] });
838
+ }
839
+
840
+ function DateInput({
841
+ label,
842
+ error,
843
+ value,
844
+ onChange,
845
+ required = false,
846
+ disabled = false,
847
+ className,
848
+ name,
849
+ testId,
850
+ min,
851
+ max
852
+ }) {
853
+ const inputRef = useRef(null);
854
+ const handleIconClick = () => {
855
+ const input = inputRef.current;
856
+ if (!input) return;
857
+ if (typeof input.showPicker === "function") {
858
+ input.showPicker();
859
+ } else {
860
+ input.focus();
861
+ }
862
+ };
863
+ return /* @__PURE__ */ jsx(
864
+ TextField,
865
+ {
866
+ label,
867
+ value,
868
+ onChange: (e) => onChange(e.target.value),
869
+ type: "date",
870
+ required,
871
+ disabled,
872
+ className,
873
+ name,
874
+ error: !!error,
875
+ helperText: error,
876
+ fullWidth: true,
877
+ variant: "outlined",
878
+ size: "small",
879
+ inputRef,
880
+ slotProps: {
881
+ inputLabel: { shrink: true },
882
+ htmlInput: { min, max, "data-testid": testId },
883
+ input: {
884
+ endAdornment: /* @__PURE__ */ jsx(InputAdornment, { position: "end", children: /* @__PURE__ */ jsx(
885
+ IconButton,
886
+ {
887
+ onClick: handleIconClick,
888
+ edge: "end",
889
+ "aria-label": "Open date picker",
890
+ size: "small",
891
+ disabled,
892
+ children: /* @__PURE__ */ jsx(CalendarMonthIcon, { fontSize: "small" })
893
+ }
894
+ ) })
895
+ }
896
+ }
897
+ }
898
+ );
899
+ }
900
+
901
+ function DropDown({
902
+ label,
903
+ error,
904
+ value,
905
+ onChange,
906
+ options = [],
907
+ required = false,
908
+ disabled = false,
909
+ className,
910
+ name,
911
+ testId
912
+ }) {
913
+ const reactId = useId();
914
+ const labelId = `${reactId}-label`;
915
+ const selectId = `${reactId}-select`;
916
+ const selectDisplayProps = {
917
+ "data-testid": testId
918
+ };
919
+ const handleChange = (event) => {
920
+ onChange(event.target.value);
921
+ };
922
+ return /* @__PURE__ */ jsxs(
923
+ FormControl,
924
+ {
925
+ fullWidth: true,
926
+ error: !!error,
927
+ required,
928
+ disabled,
929
+ className,
930
+ size: "small",
931
+ children: [
932
+ label && /* @__PURE__ */ jsx(InputLabel$1, { id: labelId, sx: { fontSize: "14px" }, children: label }),
933
+ /* @__PURE__ */ jsx(
934
+ Select,
935
+ {
936
+ labelId: label ? labelId : void 0,
937
+ id: selectId,
938
+ name,
939
+ value: value || "",
940
+ onChange: handleChange,
941
+ label,
942
+ variant: "outlined",
943
+ SelectDisplayProps: selectDisplayProps,
944
+ children: options.map((opt, index) => /* @__PURE__ */ jsx(MenuItem, { value: opt.value, children: opt.label }, opt.value + index))
945
+ }
946
+ ),
947
+ error && /* @__PURE__ */ jsx(FormHelperText, { children: error })
948
+ ]
949
+ }
950
+ );
951
+ }
952
+
953
+ function SearchDropdown({
954
+ label,
955
+ error,
956
+ value,
957
+ onChange,
958
+ options,
959
+ placeholder = "Search...",
960
+ required = false,
961
+ disabled = false,
962
+ className,
963
+ multiple = false,
964
+ noResultsMessage = "No results found",
965
+ name,
966
+ testId
967
+ }) {
968
+ const getSelectedOption = () => {
969
+ if (!value) return multiple ? [] : null;
970
+ if (multiple) {
971
+ const selectedValues = Array.isArray(value) ? value : value.split(",").filter((v) => v.trim());
972
+ return options.filter((opt) => selectedValues.includes(opt.value));
973
+ }
974
+ const stringValue = Array.isArray(value) ? value[0] : value;
975
+ return options.find((opt) => opt.value === stringValue) || null;
976
+ };
977
+ const handleChange = (_event, newValue) => {
978
+ if (multiple) {
979
+ onChange(Array.isArray(newValue) ? newValue.map((opt) => opt.value) : []);
980
+ } else {
981
+ onChange(newValue && !Array.isArray(newValue) ? newValue.value : "");
982
+ }
983
+ };
984
+ return /* @__PURE__ */ jsx(
985
+ Autocomplete,
986
+ {
987
+ options,
988
+ value: getSelectedOption(),
989
+ onChange: handleChange,
990
+ getOptionLabel: (option) => option.label,
991
+ isOptionEqualToValue: (option, val) => option.value === val.value,
992
+ "data-testid": testId,
993
+ renderInput: (params) => /* @__PURE__ */ jsx(
994
+ TextField,
995
+ {
996
+ ...params,
997
+ label,
998
+ placeholder,
999
+ required,
1000
+ error: !!error,
1001
+ helperText: error,
1002
+ className,
1003
+ variant: "outlined",
1004
+ name
1005
+ }
1006
+ ),
1007
+ noOptionsText: noResultsMessage,
1008
+ size: "small",
1009
+ fullWidth: true,
1010
+ multiple,
1011
+ disabled,
1012
+ clearOnBlur: false,
1013
+ selectOnFocus: true,
1014
+ autoHighlight: true
1015
+ }
1016
+ );
1017
+ }
1018
+
1019
+ const FileInputContainer = styled.div`
1020
+ display: flex;
1021
+ flex-direction: column;
1022
+ gap: 4px;
1023
+ `;
1024
+ const FileInputWrapper = styled.div`
1025
+ position: relative;
1026
+ display: flex;
1027
+ align-items: center;
1028
+ gap: 12px;
1029
+ cursor: pointer;
1030
+ transition: border-color 0.2s;
1031
+ border-color: ${({ theme, $dragOver }) => $dragOver ? theme.colors.accent : void 0};
1032
+ background-color: ${({ theme, $dragOver }) => $dragOver ? theme.colors.surface : void 0};
1033
+
1034
+ &:hover {
1035
+ border-color: ${({ theme, $hasError }) => $hasError ? theme.colors.error : theme.colors.accent};
1036
+ }
1037
+
1038
+ &:focus-within {
1039
+ border-color: ${({ theme, $hasError }) => $hasError ? theme.colors.error : theme.colors.accent};
1040
+ }
1041
+ `;
1042
+ const HiddenFileInput = styled.input`
1043
+ position: absolute;
1044
+ opacity: 0;
1045
+ width: 0;
1046
+ height: 0;
1047
+ pointer-events: none;
1048
+ `;
1049
+ const UploadButton = styled.button`
1050
+ background: none;
1051
+ border: none;
1052
+ color: ${({ theme }) => theme.colors.primary};
1053
+ text-decoration: underline;
1054
+ cursor: pointer;
1055
+ font-size: 14px;
1056
+ padding: 0;
1057
+ display: flex;
1058
+ align-items: center;
1059
+ gap: 4px;
1060
+
1061
+ &:hover {
1062
+ color: ${({ theme }) => theme.colors.accent};
1063
+ }
1064
+ `;
1065
+ const FileName = styled.span`
1066
+ color: ${({ theme }) => theme.colors.primary};
1067
+ font-size: 14px;
1068
+ flex: 1;
1069
+ `;
1070
+ const UploadIcon = styled.span`
1071
+ color: ${({ theme }) => theme.colors.primary};
1072
+ display: flex;
1073
+ align-items: center;
1074
+ `;
1075
+ const FileSize = styled.span`
1076
+ color: ${({ theme }) => theme.colors.secondary};
1077
+ font-size: 12px;
1078
+ `;
1079
+ const ClearButton = styled.button`
1080
+ background: none;
1081
+ border: none;
1082
+ color: ${({ theme }) => theme.colors.secondary};
1083
+ cursor: pointer;
1084
+ padding: 4px;
1085
+ display: flex;
1086
+ align-items: center;
1087
+ justify-content: center;
1088
+ border-radius: 4px;
1089
+ transition: all 0.2s;
1090
+
1091
+ &:hover {
1092
+ color: ${({ theme }) => theme.colors.error};
1093
+ background-color: ${({ theme }) => theme.colors.error}20;
1094
+ }
1095
+ `;
1096
+ const FileRequirements = styled.div`
1097
+ margin-top: 8px;
1098
+ padding: 8px 12px;
1099
+ background: ${({ theme }) => theme.colors.background};
1100
+ border: 1px solid ${({ theme }) => theme.border.color};
1101
+ border-radius: ${({ theme }) => theme.border.radius};
1102
+ `;
1103
+ const formatFileSize = (bytes) => {
1104
+ if (bytes === 0) return "0 Bytes";
1105
+ const k = 1024;
1106
+ const sizes = ["Bytes", "KB", "MB", "GB"];
1107
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
1108
+ return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + " " + sizes[i];
1109
+ };
1110
+ function FileInput({
1111
+ label,
1112
+ error,
1113
+ value,
1114
+ onChange,
1115
+ placeholder = "Upload document",
1116
+ accept = ".png,.jpg,.jpeg,.pdf",
1117
+ maxSize = 10 * 1024 * 1024,
1118
+ required = false,
1119
+ className,
1120
+ showRequirements = true,
1121
+ name,
1122
+ testId
1123
+ }) {
1124
+ const fileInputRef = useRef(null);
1125
+ const [dragOver, setDragOver] = useState(false);
1126
+ const reactId = useId();
1127
+ const inputId = `${reactId}-input`;
1128
+ const errorId = `${reactId}-error`;
1129
+ const requirementsId = `${reactId}-requirements`;
1130
+ const describedBy = [error ? errorId : null, showRequirements ? requirementsId : null].filter(Boolean).join(" ");
1131
+ const validateFile = (file) => {
1132
+ const validTypes = accept.split(",").map((type) => type.trim().toLowerCase());
1133
+ const fileExtension = "." + (file.name.split(".").pop() ?? "").toLowerCase();
1134
+ if (!validTypes.includes(fileExtension)) {
1135
+ return `Invalid file type. Accepted types: ${accept}`;
1136
+ }
1137
+ if (file.size > maxSize) {
1138
+ return `File size too large. Maximum size: ${formatFileSize(maxSize)}`;
1139
+ }
1140
+ return null;
1141
+ };
1142
+ const handleFileSelect = (file) => {
1143
+ const validationError = validateFile(file);
1144
+ if (validationError) {
1145
+ onChange(null, validationError);
1146
+ return;
1147
+ }
1148
+ onChange(file, null);
1149
+ };
1150
+ const handleClick = () => {
1151
+ fileInputRef.current?.click();
1152
+ };
1153
+ const handleFileChange = (e) => {
1154
+ const file = e.target.files?.[0];
1155
+ if (file) handleFileSelect(file);
1156
+ };
1157
+ const handleDragOver = (e) => {
1158
+ e.preventDefault();
1159
+ setDragOver(true);
1160
+ };
1161
+ const handleDragLeave = (e) => {
1162
+ e.preventDefault();
1163
+ setDragOver(false);
1164
+ };
1165
+ const handleDrop = (e) => {
1166
+ e.preventDefault();
1167
+ setDragOver(false);
1168
+ const file = e.dataTransfer.files?.[0];
1169
+ if (file) handleFileSelect(file);
1170
+ };
1171
+ const handleClear = (e) => {
1172
+ e.stopPropagation();
1173
+ onChange(null, null);
1174
+ if (fileInputRef.current) fileInputRef.current.value = "";
1175
+ };
1176
+ const handleKeyDown = (e) => {
1177
+ if (e.key === "Enter" || e.key === " ") {
1178
+ e.preventDefault();
1179
+ handleClick();
1180
+ }
1181
+ };
1182
+ const acceptedTypesText = accept.split(",").map((type) => type.trim().toUpperCase().replace(".", "")).join(", ");
1183
+ return /* @__PURE__ */ jsxs(FileInputContainer, { className, children: [
1184
+ label && /* @__PURE__ */ jsx(InputLabel, { htmlFor: inputId, children: label }),
1185
+ /* @__PURE__ */ jsxs(
1186
+ FileInputWrapper,
1187
+ {
1188
+ $hasError: !!error,
1189
+ $dragOver: dragOver,
1190
+ role: "button",
1191
+ tabIndex: 0,
1192
+ "aria-label": label ? `${label}. ${placeholder}` : placeholder,
1193
+ "aria-invalid": !!error,
1194
+ "aria-describedby": describedBy || void 0,
1195
+ onClick: handleClick,
1196
+ onKeyDown: handleKeyDown,
1197
+ onDragOver: handleDragOver,
1198
+ onDragLeave: handleDragLeave,
1199
+ onDrop: handleDrop,
1200
+ children: [
1201
+ /* @__PURE__ */ jsx(UploadIcon, { children: /* @__PURE__ */ jsx(CloudUploadIcon, { fontSize: "small" }) }),
1202
+ /* @__PURE__ */ jsx(UploadButton, { as: "span", children: placeholder }),
1203
+ value && /* @__PURE__ */ jsxs(Fragment, { children: [
1204
+ /* @__PURE__ */ jsxs(FileName, { children: [
1205
+ value.name,
1206
+ /* @__PURE__ */ jsxs(FileSize, { children: [
1207
+ " (",
1208
+ formatFileSize(value.size),
1209
+ ")"
1210
+ ] })
1211
+ ] }),
1212
+ /* @__PURE__ */ jsx(
1213
+ ClearButton,
1214
+ {
1215
+ type: "button",
1216
+ onClick: handleClear,
1217
+ title: "Clear file",
1218
+ "aria-label": "Clear file",
1219
+ children: /* @__PURE__ */ jsx(CloseIcon, { fontSize: "small" })
1220
+ }
1221
+ )
1222
+ ] }),
1223
+ /* @__PURE__ */ jsx(
1224
+ HiddenFileInput,
1225
+ {
1226
+ ref: fileInputRef,
1227
+ id: inputId,
1228
+ name,
1229
+ type: "file",
1230
+ accept,
1231
+ onChange: handleFileChange,
1232
+ required,
1233
+ tabIndex: -1,
1234
+ "data-testid": testId
1235
+ }
1236
+ )
1237
+ ]
1238
+ }
1239
+ ),
1240
+ error && /* @__PURE__ */ jsx(InputError, { id: errorId, children: error }),
1241
+ showRequirements && /* @__PURE__ */ jsx(FileRequirements, { id: requirementsId, children: /* @__PURE__ */ jsxs(Body200, { children: [
1242
+ "File types accepted are ",
1243
+ acceptedTypesText,
1244
+ ", with a max. size of",
1245
+ " ",
1246
+ formatFileSize(maxSize)
1247
+ ] }) })
1248
+ ] });
1249
+ }
1250
+
1251
+ const RadioInput = styled.input.attrs({ type: "radio" })`
1252
+ appearance: none;
1253
+ width: 20px;
1254
+ height: 20px;
1255
+ border: 2px solid ${({ theme }) => theme.border.color};
1256
+ border-radius: 50%;
1257
+ margin: 0 0.5rem 0 0;
1258
+ flex-shrink: 0;
1259
+ cursor: pointer;
1260
+ position: relative;
1261
+ transition: all 0.2s;
1262
+
1263
+ &:checked {
1264
+ border-color: ${({ theme }) => theme.colors.primary};
1265
+ border-width: 6px;
1266
+ }
1267
+
1268
+ &:hover {
1269
+ border-color: ${({ theme }) => theme.colors.primary};
1270
+ }
1271
+
1272
+ &:disabled {
1273
+ opacity: 0.5;
1274
+ cursor: not-allowed;
1275
+ }
1276
+ `;
1277
+
1278
+ const CheckboxInput = styled.input.attrs({ type: "checkbox" })`
1279
+ appearance: none;
1280
+ width: 20px;
1281
+ height: 20px;
1282
+ border: 2px solid ${({ theme }) => theme.border.color};
1283
+ border-radius: 4px;
1284
+ margin: 0 0.5rem 0 0;
1285
+ flex-shrink: 0;
1286
+ cursor: pointer;
1287
+ position: relative;
1288
+ transition: all 0.2s;
1289
+
1290
+ &:checked {
1291
+ border-color: ${({ theme }) => theme.colors.primary};
1292
+ background-color: ${({ theme }) => theme.colors.primary};
1293
+ }
1294
+
1295
+ &:checked::after {
1296
+ content: '';
1297
+ position: absolute;
1298
+ left: 5px;
1299
+ top: 1px;
1300
+ width: 6px;
1301
+ height: 11px;
1302
+ border: solid white;
1303
+ border-width: 0 2px 2px 0;
1304
+ transform: rotate(45deg);
1305
+ }
1306
+
1307
+ &:hover {
1308
+ border-color: ${({ theme }) => theme.colors.primary};
1309
+ }
1310
+
1311
+ &:disabled {
1312
+ opacity: 0.5;
1313
+ cursor: not-allowed;
1314
+ }
1315
+ `;
1316
+
1317
+ const StepperContainer = styled.div`
1318
+ display: flex;
1319
+ flex-direction: column;
1320
+ gap: 1rem;
1321
+ `;
1322
+ const StepsContainer = styled.div`
1323
+ display: flex;
1324
+ justify-content: space-between;
1325
+ position: relative;
1326
+ `;
1327
+ const StepContent = styled.div``;
1328
+ const Step = styled.div`
1329
+ position: relative;
1330
+ z-index: 2;
1331
+ background: ${({ theme }) => theme.colors.background};
1332
+ padding: 0 1rem;
1333
+ display: flex;
1334
+ flex-direction: column;
1335
+ align-items: center;
1336
+ gap: 0.5rem;
1337
+ transition: all 0.2s ease-in-out;
1338
+ padding-bottom: 1rem;
1339
+ flex: 1;
1340
+ border-bottom: 1px solid;
1341
+ border-color: ${({ theme, $active, $completed }) => $active || $completed ? theme.colors.primary : theme.colors.border};
1342
+ `;
1343
+ const StepNumber = styled.div`
1344
+ width: 2rem;
1345
+ height: 2rem;
1346
+ border-radius: 50%;
1347
+ display: flex;
1348
+ align-items: center;
1349
+ justify-content: center;
1350
+ background: ${({ theme, $active, $completed }) => $completed ? theme.colors.primary : $active ? "white" : theme.colors.surface};
1351
+ color: ${({ theme, $active, $completed }) => $completed ? theme.colors.background : $active ? theme.colors.primary : theme.colors.secondary};
1352
+ font-weight: 500;
1353
+ transition: all 0.2s ease-in-out;
1354
+ border: 2px solid
1355
+ ${({ theme, $active, $completed }) => $active || $completed ? theme.colors.primary : theme.colors.border};
1356
+ `;
1357
+ const StepLabel = styled.span`
1358
+ color: ${({ theme, $active }) => $active ? theme.colors.primary : theme.colors.secondary};
1359
+ font-size: 0.875rem;
1360
+ font-weight: ${({ $active }) => $active ? 500 : 400};
1361
+ transition: all 0.2s ease-in-out;
1362
+ text-align: center;
1363
+ white-space: nowrap;
1364
+ `;
1365
+ function Stepper({ steps, currentStep, className, testId }) {
1366
+ return /* @__PURE__ */ jsxs(StepperContainer, { className, "data-testid": testId, children: [
1367
+ /* @__PURE__ */ jsx(StepsContainer, { children: steps.map((step, index) => {
1368
+ const active = index === currentStep;
1369
+ const completed = index < currentStep;
1370
+ return /* @__PURE__ */ jsxs(
1371
+ Step,
1372
+ {
1373
+ $active: active,
1374
+ $completed: completed,
1375
+ "aria-current": active ? "step" : void 0,
1376
+ children: [
1377
+ /* @__PURE__ */ jsx(StepNumber, { $active: active, $completed: completed, children: index + 1 }),
1378
+ /* @__PURE__ */ jsx(StepLabel, { $active: active, children: step.label })
1379
+ ]
1380
+ },
1381
+ "stepper-step-" + index
1382
+ );
1383
+ }) }),
1384
+ /* @__PURE__ */ jsx(StepContent, { children: steps[currentStep]?.component })
1385
+ ] });
1386
+ }
1387
+
1388
+ const TabsContainer = styled.div`
1389
+ display: flex;
1390
+ flex-direction: column;
1391
+ width: 100%;
1392
+ `;
1393
+ const TabList = styled.div`
1394
+ display: flex;
1395
+ border-bottom: 1px solid ${({ theme }) => theme.colors.border};
1396
+ margin-bottom: 1rem;
1397
+ `;
1398
+ const TabButton = styled.button`
1399
+ background: none;
1400
+ border: none;
1401
+ padding: 0.75rem 1.5rem;
1402
+ cursor: pointer;
1403
+ font-size: 0.875rem;
1404
+ font-weight: 500;
1405
+ color: ${({ theme, $active }) => $active ? theme.colors.primary : theme.colors.secondary};
1406
+ border-bottom: 2px solid ${({ theme, $active }) => $active ? theme.colors.primary : "transparent"};
1407
+ transition: all 0.2s ease-in-out;
1408
+ position: relative;
1409
+
1410
+ &:hover {
1411
+ color: ${({ theme }) => theme.colors.primary};
1412
+ background-color: ${({ theme }) => theme.colors.surface};
1413
+ }
1414
+
1415
+ &:focus-visible {
1416
+ outline: 2px solid ${({ theme }) => theme.colors.accent};
1417
+ outline-offset: -2px;
1418
+ }
1419
+ `;
1420
+ const TabContent = styled.div`
1421
+ padding: 1rem 0;
1422
+ min-height: 100px;
1423
+ `;
1424
+ function Tabs({
1425
+ tabs = [],
1426
+ defaultActiveTab = 0,
1427
+ className,
1428
+ onTabChange,
1429
+ testId
1430
+ }) {
1431
+ const [activeTab, setActiveTab] = useState(defaultActiveTab);
1432
+ const baseId = useId();
1433
+ const handleTabClick = (index) => {
1434
+ setActiveTab(index);
1435
+ onTabChange?.(index);
1436
+ };
1437
+ if (!tabs || tabs.length === 0) {
1438
+ return null;
1439
+ }
1440
+ const tabId = (i) => `${baseId}-tab-${i}`;
1441
+ const panelId = (i) => `${baseId}-panel-${i}`;
1442
+ return /* @__PURE__ */ jsxs(TabsContainer, { className, "data-testid": testId, children: [
1443
+ /* @__PURE__ */ jsx(TabList, { role: "tablist", children: tabs.map((tab, index) => {
1444
+ const active = index === activeTab;
1445
+ return /* @__PURE__ */ jsx(
1446
+ TabButton,
1447
+ {
1448
+ id: tabId(index),
1449
+ role: "tab",
1450
+ type: "button",
1451
+ $active: active,
1452
+ "aria-selected": active,
1453
+ "aria-controls": panelId(index),
1454
+ tabIndex: active ? 0 : -1,
1455
+ onClick: () => handleTabClick(index),
1456
+ children: tab.name
1457
+ },
1458
+ `tab-${index}`
1459
+ );
1460
+ }) }),
1461
+ /* @__PURE__ */ jsx(TabContent, { role: "tabpanel", id: panelId(activeTab), "aria-labelledby": tabId(activeTab), children: tabs[activeTab]?.content })
1462
+ ] });
1463
+ }
1464
+
1465
+ function Loader({ className, size, label = "Loading", testId }) {
1466
+ return /* @__PURE__ */ jsx(
1467
+ Box,
1468
+ {
1469
+ className,
1470
+ "data-testid": testId,
1471
+ sx: { display: "flex", justifyContent: "center", alignItems: "center" },
1472
+ children: /* @__PURE__ */ jsx(CircularProgress, { size, "aria-label": label })
1473
+ }
1474
+ );
1475
+ }
1476
+
1477
+ function DotsMenu({
1478
+ options,
1479
+ iconSize = "medium",
1480
+ ariaLabel = "more",
1481
+ testId
1482
+ }) {
1483
+ const [anchorEl, setAnchorEl] = useState(null);
1484
+ const open = Boolean(anchorEl);
1485
+ const baseId = useId();
1486
+ const buttonId = `${baseId}-button`;
1487
+ const menuId = `${baseId}-menu`;
1488
+ const handleClick = (event) => {
1489
+ setAnchorEl(event.currentTarget);
1490
+ };
1491
+ const handleClose = () => {
1492
+ setAnchorEl(null);
1493
+ };
1494
+ const handleOptionClick = (action) => {
1495
+ action();
1496
+ handleClose();
1497
+ };
1498
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
1499
+ /* @__PURE__ */ jsx(
1500
+ IconButton$1,
1501
+ {
1502
+ "aria-label": ariaLabel,
1503
+ id: buttonId,
1504
+ "data-testid": testId,
1505
+ "aria-controls": open ? menuId : void 0,
1506
+ "aria-haspopup": "true",
1507
+ "aria-expanded": open ? "true" : void 0,
1508
+ onClick: handleClick,
1509
+ size: iconSize,
1510
+ children: /* @__PURE__ */ jsx(MoreVertIcon, {})
1511
+ }
1512
+ ),
1513
+ /* @__PURE__ */ jsx(
1514
+ Menu,
1515
+ {
1516
+ id: menuId,
1517
+ anchorEl,
1518
+ open,
1519
+ onClose: handleClose,
1520
+ slotProps: {
1521
+ list: { "aria-labelledby": buttonId },
1522
+ paper: { style: { maxHeight: 200, width: "20ch" } }
1523
+ },
1524
+ children: options.map((option, idx) => /* @__PURE__ */ jsx(MenuItem$1, { onClick: () => handleOptionClick(option.action), children: option.label }, option.label + idx))
1525
+ }
1526
+ )
1527
+ ] });
1528
+ }
1529
+
1530
+ const PreviewCard = styled.div`
1531
+ display: flex;
1532
+ gap: 2rem;
1533
+ padding: 1.5rem;
1534
+ background: ${({ theme }) => theme.colors.background};
1535
+ border: ${({ theme }) => theme.border.width} solid ${({ theme }) => theme.border.color};
1536
+ border-radius: ${({ theme }) => theme.border.radius};
1537
+ `;
1538
+ const MainColumn = styled.div`
1539
+ display: flex;
1540
+ flex-direction: column;
1541
+ gap: 1rem;
1542
+ flex: 1;
1543
+ min-width: 0;
1544
+ `;
1545
+ const HeaderRow = styled.div`
1546
+ display: flex;
1547
+ align-items: center;
1548
+ justify-content: space-between;
1549
+ gap: 1rem;
1550
+ `;
1551
+ const SideColumn = styled.div`
1552
+ flex: 1;
1553
+ min-width: 0;
1554
+ `;
1555
+ function PreviewContent() {
1556
+ const [name, setName] = useState("Acme Corporation");
1557
+ const [plan, setPlan] = useState("growth");
1558
+ const [autopay, setAutopay] = useState(true);
1559
+ return /* @__PURE__ */ jsxs(PreviewCard, { "data-testid": "oatfi-ui-preview", children: [
1560
+ /* @__PURE__ */ jsxs(MainColumn, { children: [
1561
+ /* @__PURE__ */ jsxs(HeaderRow, { children: [
1562
+ /* @__PURE__ */ jsx(Body100, { className: "bold", children: "Partner" }),
1563
+ /* @__PURE__ */ jsx(StatusTag, { className: "success small", children: "Active" })
1564
+ ] }),
1565
+ /* @__PURE__ */ jsx(TextInput, { label: "Business name", value: name, onChange: setName }),
1566
+ /* @__PURE__ */ jsx(
1567
+ DropDown,
1568
+ {
1569
+ label: "Plan",
1570
+ value: plan,
1571
+ onChange: setPlan,
1572
+ options: [
1573
+ { value: "starter", label: "Starter" },
1574
+ { value: "growth", label: "Growth" },
1575
+ { value: "scale", label: "Scale" }
1576
+ ]
1577
+ }
1578
+ ),
1579
+ /* @__PURE__ */ jsxs(FormCheckboxLabel, { children: [
1580
+ /* @__PURE__ */ jsx(CheckboxInput, { checked: autopay, onChange: (e) => setAutopay(e.target.checked) }),
1581
+ "Enable automatic payments"
1582
+ ] }),
1583
+ /* @__PURE__ */ jsxs(ButtonContainer, { children: [
1584
+ /* @__PURE__ */ jsx(Button, { className: "secondary", children: "Cancel" }),
1585
+ /* @__PURE__ */ jsx(Button, { children: "Save changes" })
1586
+ ] })
1587
+ ] }),
1588
+ /* @__PURE__ */ jsx(SideColumn, { children: /* @__PURE__ */ jsx(
1589
+ Stepper,
1590
+ {
1591
+ currentStep: 1,
1592
+ steps: [{ label: "Connect" }, { label: "Verify" }, { label: "Done" }]
1593
+ }
1594
+ ) })
1595
+ ] });
1596
+ }
1597
+ function Preview({ branding, className }) {
1598
+ return /* @__PURE__ */ jsx(ThemeProvider, { branding, children: /* @__PURE__ */ jsx("div", { className, children: /* @__PURE__ */ jsx(PreviewContent, {}) }) });
1599
+ }
1600
+
1601
+ export { AutocompleteInput, BaseInput, Body100, Body200, Body400, Button, ButtonContainer, CheckboxInput, Container, Content, CurrencyInput, DateInput, DetailElement, DetailRow, DetailsContainer, DotsMenu, DropDown, DropdownContainer, DropdownItem, DropdownList, EmailInput, FileInput, FlexColumnWrapper, FlexRowWrapper, Form, FormActions, FormCheckboxLabel, FormColumn, FormRow, FormSubtitle, FormTitle, H1, H2, H3, InputError, InputLabel, InputWrapper, Loader, NoResults, PhoneInput, Preview, RadioInput, SSNInput, SearchDropdown, SelectInput, StatusTag, Stepper, Tabs, TaxIdInput, TermsList, TextInput, ThemeProvider, buildMuiTheme, defaultTheme, mergeBranding, useTheme };
1602
+ //# sourceMappingURL=index.esm.js.map