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