@candidhealth/react-vitals 1.0.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs ADDED
@@ -0,0 +1,4315 @@
1
+ // src/core/button/Button.tsx
2
+ import * as React from "react";
3
+ import { twMerge } from "tailwind-merge";
4
+
5
+ // src/core/button/buttonStyles.ts
6
+ import { twJoin } from "tailwind-merge";
7
+ var linkStyles = "text-indigo-600 hover:underline active:text-indigo-400 focus:outline-indigo-400 focus:outline-offset-2";
8
+ var roundedMdStyles = {
9
+ none: "",
10
+ right: "rounded-r-md",
11
+ left: "rounded-l-md",
12
+ both: "rounded-md"
13
+ };
14
+ var roundedLgStyles = {
15
+ none: "",
16
+ right: "rounded-r-lg",
17
+ left: "rounded-l-lg",
18
+ both: "rounded-lg"
19
+ };
20
+ var roundedXlStyles = {
21
+ none: "",
22
+ right: "rounded-r-xl",
23
+ left: "rounded-l-xl",
24
+ both: "rounded-xl"
25
+ };
26
+ var borderRadiusStyles = {
27
+ default: {
28
+ xs: roundedMdStyles,
29
+ sm: roundedMdStyles,
30
+ md: roundedMdStyles,
31
+ lg: roundedLgStyles
32
+ },
33
+ large: {
34
+ xs: roundedLgStyles,
35
+ sm: roundedLgStyles,
36
+ md: roundedLgStyles,
37
+ lg: roundedXlStyles
38
+ }
39
+ };
40
+ var sizeStyles = {
41
+ xs: "h-xs gap-1 px-2 text-sm",
42
+ sm: "h-sm gap-1 px-2 text-sm",
43
+ md: "h-md gap-1.5 px-3 text-base",
44
+ lg: "h-lg gap-2 px-4 text-lg"
45
+ };
46
+ var colorStyles = {
47
+ default: {
48
+ primary: "bg-indigo-600 hover:bg-indigo-700 data-[state='open']:bg-indigo-700 border border-indigo-700 text-white",
49
+ default: "bg-white hover:bg-gray-100 data-[state='open']:bg-gray-100 border border-gray-200 text-gray-700",
50
+ danger: "bg-red-600 hover:bg-red-700 data-[state='open']:bg-red-700 border border-red-700 text-white",
51
+ error: "bg-white hover:bg-red-50 data-[state='open']:bg-red-50 text-red-500 border border-red-300"
52
+ },
53
+ transparent: {
54
+ primary: "bg-indigo-900/0 hover:bg-indigo-900/10 data-[state='open']:bg-indigo-900/10 text-indigo-700",
55
+ default: "bg-gray-900/0 hover:bg-gray-900/10 data-[state='open']:bg-gray-900/10 text-gray-700",
56
+ danger: "bg-red-900/0 hover:bg-red-900/10 data-[state='open']:bg-red-900/10 text-red-700",
57
+ error: "bg-red-900/0 hover:bg-red-900/10 data-[state='open']:bg-red-900/10 text-red-500"
58
+ },
59
+ dark: {
60
+ primary: "bg-indigo-600 hover:bg-indigo-700 data-[state='open']:bg-indigo-700 border border-indigo-700 text-white",
61
+ default: "bg-gray-900 hover:bg-gray-600 data-[state='open']:bg-gray-600 text-white",
62
+ danger: "bg-red-600 hover:bg-red-700 data-[state='open']:bg-red-700 text-white",
63
+ error: "bg-white hover:bg-red-50 data-[state='open']:bg-red-50 text-red-500"
64
+ }
65
+ };
66
+ var buttonStyles = ({
67
+ fullWidth = false,
68
+ size = "md",
69
+ intent = "default",
70
+ variant = "default",
71
+ soften = "both",
72
+ loading,
73
+ roundedness = "default"
74
+ }) => {
75
+ if (variant === "link") {
76
+ return twJoin(fullWidth && "w-full", loading && "animate-loading-pulse", linkStyles);
77
+ }
78
+ return twJoin(
79
+ "flex items-center justify-center whitespace-nowrap focus-visible:ring-2 focus-visible:ring-indigo-400 focus-visible:ring-inset disabled:pointer-events-none disabled:opacity-50",
80
+ fullWidth && "w-full",
81
+ borderRadiusStyles[roundedness][size][soften],
82
+ sizeStyles[size],
83
+ colorStyles[variant][intent],
84
+ loading && "animate-loading-pulse"
85
+ );
86
+ };
87
+
88
+ // src/core/button/Button.tsx
89
+ import { jsx } from "react/jsx-runtime";
90
+ var ButtonImpl = ({
91
+ fullWidth,
92
+ size,
93
+ intent,
94
+ variant,
95
+ disabled,
96
+ loading,
97
+ soften,
98
+ roundedness,
99
+ className,
100
+ children,
101
+ ...rest
102
+ }, ref) => {
103
+ return /* @__PURE__ */ jsx(
104
+ "button",
105
+ {
106
+ type: "button",
107
+ className: twMerge(buttonStyles({ fullWidth, size, intent, variant, loading, soften, roundedness }), className),
108
+ ...rest,
109
+ ref,
110
+ disabled: disabled || loading,
111
+ children
112
+ }
113
+ );
114
+ };
115
+ var Button = React.forwardRef(ButtonImpl);
116
+
117
+ // src/core/button/ButtonGroup.tsx
118
+ import { jsx as jsx2 } from "react/jsx-runtime";
119
+ var ButtonGroup = ({
120
+ size,
121
+ value,
122
+ onChange,
123
+ buttons
124
+ }) => /* @__PURE__ */ jsx2("div", { className: "flex", children: buttons.map((button, i) => /* @__PURE__ */ jsx2(
125
+ Button,
126
+ {
127
+ size,
128
+ onClick: () => onChange(button.value),
129
+ soften: i === 0 ? "left" : i === buttons.length - 1 ? "right" : "none",
130
+ intent: value === button.value ? "primary" : void 0,
131
+ children: button.content
132
+ },
133
+ button.value
134
+ )) });
135
+
136
+ // src/core/callout/Callout.tsx
137
+ import { faCircle, faCircleInfo, faDiamond, faTriangleExclamation } from "@fortawesome/free-solid-svg-icons";
138
+ import { twJoin as twJoin2 } from "tailwind-merge";
139
+
140
+ // src/core/icon/Icon.tsx
141
+ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
142
+ import { jsx as jsx3 } from "react/jsx-runtime";
143
+ var Icon = ({ icon }) => /* @__PURE__ */ jsx3(FontAwesomeIcon, { icon });
144
+
145
+ // src/core/callout/Callout.tsx
146
+ import { jsx as jsx4, jsxs } from "react/jsx-runtime";
147
+ var calloutBackgroundStyles = {
148
+ default: "bg-gray-100",
149
+ warning: "bg-yellow-50",
150
+ primary: "bg-indigo-50",
151
+ danger: "bg-red-50"
152
+ };
153
+ var calloutIconStyles = {
154
+ default: "text-gray-500",
155
+ warning: "text-yellow-700",
156
+ primary: "text-indigo-500",
157
+ danger: "text-red-800"
158
+ };
159
+ var calloutBorderStyles = {
160
+ default: "border-[1px] border-gray-200",
161
+ primary: "border-[1px] border-indigo-100",
162
+ warning: "border-[1px] border-yellow-200",
163
+ danger: "border-[1px] border-red-100"
164
+ };
165
+ var calloutIcons = {
166
+ default: faCircleInfo,
167
+ warning: faTriangleExclamation,
168
+ primary: faDiamond,
169
+ danger: faCircle
170
+ };
171
+ var Callout = ({
172
+ title,
173
+ intent = "default",
174
+ rightSlot,
175
+ children,
176
+ customIcon,
177
+ isAttachedAtBottom,
178
+ isCentered
179
+ }) => /* @__PURE__ */ jsxs(
180
+ "div",
181
+ {
182
+ className: twJoin2(
183
+ "flex w-full justify-between rounded-lg p-2.5",
184
+ calloutBackgroundStyles[intent],
185
+ calloutBorderStyles[intent],
186
+ isAttachedAtBottom ? "rounded-b-none" : "rounded-b-lg",
187
+ isCentered ? "items-center" : "items-start"
188
+ ),
189
+ children: [
190
+ /* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
191
+ /* @__PURE__ */ jsx4("div", { className: twJoin2("text-sm", title ? "leading-6.5" : "leading-5", calloutIconStyles[intent]), children: /* @__PURE__ */ jsx4(Icon, { icon: customIcon ?? calloutIcons[intent] }) }),
192
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-1 flex-col gap-1", children: [
193
+ title && /* @__PURE__ */ jsx4("div", { className: "leading-6.5 font-medium whitespace-pre-line text-gray-700", children: title }),
194
+ children && /* @__PURE__ */ jsx4("div", { className: "text-sm leading-5 text-gray-500", children })
195
+ ] })
196
+ ] }),
197
+ rightSlot
198
+ ]
199
+ }
200
+ );
201
+
202
+ // src/core/checkbox/Checkbox.tsx
203
+ import { forwardRef as forwardRef2, useEffect, useRef } from "react";
204
+ import { twJoin as twJoin3 } from "tailwind-merge";
205
+ import { jsx as jsx5 } from "react/jsx-runtime";
206
+ var Checkbox = forwardRef2(({ className, hasError, ...rest }, ref) => /* @__PURE__ */ jsx5(
207
+ "input",
208
+ {
209
+ type: "checkbox",
210
+ className: twJoin3(
211
+ className,
212
+ "block rounded-sm text-indigo-600 checked:bg-indigo-600 indeterminate:bg-indigo-600 focus:ring-0 focus:ring-offset-0 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-400 disabled:cursor-not-allowed disabled:bg-gray-200 disabled:hover:bg-gray-200",
213
+ hasError ? "border-red-300 text-red-900 placeholder-red-300" : "border-gray-200 disabled:border-gray-200"
214
+ ),
215
+ ...rest,
216
+ ref
217
+ }
218
+ ));
219
+ var IndeterminateCheckbox = ({
220
+ indeterminate = false,
221
+ ...rest
222
+ }) => {
223
+ const ref = useRef(null);
224
+ useEffect(() => {
225
+ if (ref.current) {
226
+ ref.current.indeterminate = indeterminate;
227
+ }
228
+ }, [indeterminate]);
229
+ return /* @__PURE__ */ jsx5(Checkbox, { ref, ...rest });
230
+ };
231
+
232
+ // src/core/collapsible/Collapsible.tsx
233
+ import { faChevronDown, faChevronRight } from "@fortawesome/free-solid-svg-icons";
234
+ import { Content, Root, Trigger } from "@radix-ui/react-collapsible";
235
+ import { useState } from "react";
236
+ import { twMerge as twMerge2 } from "tailwind-merge";
237
+ import { jsx as jsx6, jsxs as jsxs2 } from "react/jsx-runtime";
238
+ var Collapsible = ({
239
+ title,
240
+ children,
241
+ defaultOpen = false,
242
+ iconPosition = "left",
243
+ hideIcon,
244
+ open: controlledOpen,
245
+ setOpen: controlledSetOpen,
246
+ triggerClassName
247
+ }) => {
248
+ const isControlled = controlledOpen !== void 0 && controlledSetOpen !== void 0;
249
+ const [uncontrolledOpen, setUncontrolledOpen] = useState(defaultOpen);
250
+ const isOpen = isControlled ? controlledOpen : uncontrolledOpen;
251
+ const setIsOpen = isControlled ? controlledSetOpen : setUncontrolledOpen;
252
+ return /* @__PURE__ */ jsxs2(Root, { className: "flex flex-col gap-2", open: isOpen, onOpenChange: setIsOpen, children: [
253
+ /* @__PURE__ */ jsx6(
254
+ Trigger,
255
+ {
256
+ asChild: true,
257
+ className: twMerge2("flex cursor-pointer items-center gap-2 font-medium text-gray-500", triggerClassName),
258
+ children: /* @__PURE__ */ jsxs2("div", { children: [
259
+ !hideIcon && iconPosition === "left" && /* @__PURE__ */ jsx6("div", { className: "min-w-3.5", children: /* @__PURE__ */ jsx6(
260
+ Icon,
261
+ {
262
+ icon: isOpen ? faChevronDown : faChevronRight
263
+ }
264
+ ) }),
265
+ title,
266
+ !hideIcon && iconPosition === "right" && /* @__PURE__ */ jsx6("div", { className: "min-w-3.5", children: /* @__PURE__ */ jsx6(
267
+ Icon,
268
+ {
269
+ icon: isOpen ? faChevronDown : faChevronRight
270
+ }
271
+ ) })
272
+ ] })
273
+ }
274
+ ),
275
+ /* @__PURE__ */ jsx6(Content, { className: "overflow-y-hidden data-[state=closed]:animate-collapsible-up data-[state=open]:animate-collapsible-down", children: /* @__PURE__ */ jsx6("div", { className: "flex flex-col gap-2", children }) })
276
+ ] });
277
+ };
278
+
279
+ // src/core/collapsible-section/CollapsibleSection.tsx
280
+ import { faChevronDown as faChevronDown2 } from "@fortawesome/free-solid-svg-icons";
281
+ import { Slot } from "@radix-ui/react-slot";
282
+ import { twJoin as twJoin4 } from "tailwind-merge";
283
+
284
+ // src/core/utils/useToggle.tsx
285
+ import * as React3 from "react";
286
+
287
+ // src/core/utils/create-context-helper.tsx
288
+ import * as React2 from "react";
289
+ import { jsx as jsx7 } from "react/jsx-runtime";
290
+ var createContextHelper = (defaultContext) => {
291
+ const Context = React2.createContext(defaultContext);
292
+ const Provider3 = ({ children, ...rest }) => {
293
+ const value = React2.useMemo(() => rest, Object.values(rest));
294
+ return /* @__PURE__ */ jsx7(Context.Provider, { value, children });
295
+ };
296
+ const useContext7 = () => {
297
+ const context = React2.useContext(Context);
298
+ if (context) {
299
+ return context;
300
+ }
301
+ if (defaultContext !== void 0) {
302
+ return defaultContext;
303
+ }
304
+ throw new Error("Required context: useContext likely outside of a Provider");
305
+ };
306
+ return [Provider3, useContext7];
307
+ };
308
+
309
+ // src/core/utils/useToggle.tsx
310
+ import { jsx as jsx8 } from "react/jsx-runtime";
311
+ var [ToggleProvider, useToggleHook] = createContextHelper({
312
+ state: false,
313
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
314
+ update: () => {
315
+ },
316
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
317
+ toggle: () => {
318
+ }
319
+ });
320
+ var createToggleContextHelper = (defaultState = false) => {
321
+ const Provider3 = ({ children, state: initState }) => {
322
+ const hook = useToggle(initState ?? defaultState);
323
+ return /* @__PURE__ */ jsx8(ToggleProvider, { ...hook, children });
324
+ };
325
+ Provider3.displayName = "ToggleProvider";
326
+ return [Provider3, useToggleHook];
327
+ };
328
+ var [IsVisibleProvider, useIsVisible] = createToggleContextHelper(true);
329
+ var [IsEditingProvider, useIsEditing] = createToggleContextHelper(false);
330
+ var useToggle = (initState) => {
331
+ const [state, update] = React3.useState(initState ?? false);
332
+ const toggle = React3.useCallback(() => update((state2) => !state2), []);
333
+ return { state, update, toggle };
334
+ };
335
+
336
+ // src/core/collapsible-section/CollapsibleSection.tsx
337
+ import { jsx as jsx9, jsxs as jsxs3 } from "react/jsx-runtime";
338
+ var ToggleButton = ({ children, ...rest }) => {
339
+ const { state: isVisible, toggle } = useIsVisible();
340
+ return /* @__PURE__ */ jsx9(Slot, { onClick: toggle, children: /* @__PURE__ */ jsxs3(Button, { variant: "transparent", size: "xs", ...rest, children: [
341
+ /* @__PURE__ */ jsx9("span", { className: twJoin4("transition-transform", !isVisible && "-rotate-90"), children: /* @__PURE__ */ jsx9(Icon, { icon: faChevronDown2 }) }),
342
+ children
343
+ ] }) });
344
+ };
345
+ var Content2 = ({ children }) => {
346
+ const { state: isVisible } = useIsVisible();
347
+ if (isVisible) return children;
348
+ return null;
349
+ };
350
+ var CollapsibleSection = ({ children, defaultOpen }) => {
351
+ return /* @__PURE__ */ jsx9(IsVisibleProvider, { state: defaultOpen, children });
352
+ };
353
+ CollapsibleSection.ToggleButton = ToggleButton;
354
+ CollapsibleSection.Content = Content2;
355
+
356
+ // src/core/copyable/Copyable.tsx
357
+ import { faCheck, faCopy } from "@fortawesome/free-solid-svg-icons";
358
+ import * as RadixTooltip2 from "@radix-ui/react-tooltip";
359
+ import { twJoin as twJoin5 } from "tailwind-merge";
360
+
361
+ // src/core/tooltip/Tooltip.tsx
362
+ import * as RadixTooltip from "@radix-ui/react-tooltip";
363
+
364
+ // src/core/utils/useOverflowObserver.tsx
365
+ import * as React4 from "react";
366
+ var useOverflowObserver = () => {
367
+ const [hasOverflow, setHasOverflow] = React4.useState(false);
368
+ const elementRef = React4.useRef(null);
369
+ React4.useEffect(() => {
370
+ if (elementRef.current == null) return;
371
+ const resizeObserver = new ResizeObserver(([entry]) => {
372
+ window.requestAnimationFrame(() => {
373
+ const element = entry?.target;
374
+ const hasOverflowWidth = element.offsetWidth < element.scrollWidth;
375
+ const hasOverflowHeight = element.offsetHeight < element.scrollHeight;
376
+ const calcHasOverflow = hasOverflowWidth || hasOverflowHeight;
377
+ if (calcHasOverflow !== hasOverflow) {
378
+ setHasOverflow(calcHasOverflow);
379
+ }
380
+ });
381
+ });
382
+ resizeObserver.observe(elementRef.current);
383
+ return () => resizeObserver.disconnect();
384
+ }, [hasOverflow]);
385
+ return { elementRef, hasOverflow };
386
+ };
387
+
388
+ // src/core/tooltip/Tooltip.tsx
389
+ import { jsx as jsx10, jsxs as jsxs4 } from "react/jsx-runtime";
390
+ var TooltipContent = ({ children, variant = "dark", ...rest }) => {
391
+ return /* @__PURE__ */ jsx10(RadixTooltip.Portal, { children: /* @__PURE__ */ jsxs4(
392
+ RadixTooltip.Content,
393
+ {
394
+ ...rest,
395
+ hideWhenDetached: true,
396
+ sideOffset: 6,
397
+ className: `z-9000000000 max-w-prose rounded-lg px-5 py-3 text-sm break-words shadow-lg ${variant === "dark" ? "bg-gray-900 text-white" : "bg-white text-gray-600"}`,
398
+ children: [
399
+ children,
400
+ /* @__PURE__ */ jsx10(RadixTooltip.Arrow, { className: variant === "dark" ? "fill-gray-900" : "fill-white", offset: 8 })
401
+ ]
402
+ }
403
+ ) });
404
+ };
405
+ TooltipContent.displayName = RadixTooltip.Content.displayName;
406
+ var OverflowTrigger = ({
407
+ element,
408
+ ...rest
409
+ }) => {
410
+ const { elementRef, hasOverflow } = useOverflowObserver();
411
+ if (!hasOverflow) {
412
+ return element(elementRef);
413
+ }
414
+ return /* @__PURE__ */ jsx10(RadixTooltip.Trigger, { asChild: true, ...rest, children: element(elementRef) });
415
+ };
416
+ var TooltipTrigger = (props) => /* @__PURE__ */ jsx10(RadixTooltip.Trigger, { asChild: true, ...props });
417
+ var TooltipProvider = (props) => /* @__PURE__ */ jsx10(RadixTooltip.Provider, { disableHoverableContent: true, delayDuration: 0, ...props });
418
+ var TooltipRoot = (props) => /* @__PURE__ */ jsx10(RadixTooltip.Root, { ...props });
419
+ var Tooltip = ({ trigger, content, variant, side, ...rest }) => {
420
+ return /* @__PURE__ */ jsxs4(Tooltip.Root, { ...rest, children: [
421
+ /* @__PURE__ */ jsx10(Tooltip.Trigger, { children: trigger }),
422
+ content && /* @__PURE__ */ jsx10(Tooltip.Content, { side, variant, children: content })
423
+ ] });
424
+ };
425
+ Tooltip.Provider = TooltipProvider;
426
+ Tooltip.Root = TooltipRoot;
427
+ Tooltip.Trigger = TooltipTrigger;
428
+ Tooltip.OverflowTrigger = OverflowTrigger;
429
+ Tooltip.Content = TooltipContent;
430
+
431
+ // src/core/copyable/use-copyable.ts
432
+ import * as React5 from "react";
433
+ var waitMs = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
434
+ var oldSchoolCopy = (text) => {
435
+ const tempTextArea = document.createElement("textarea");
436
+ tempTextArea.value = text;
437
+ document.body.appendChild(tempTextArea);
438
+ tempTextArea.select();
439
+ document.execCommand("copy");
440
+ document.body.removeChild(tempTextArea);
441
+ };
442
+ var copyToClipboard = async (value) => {
443
+ try {
444
+ if (navigator?.clipboard?.writeText) {
445
+ await navigator.clipboard.writeText(value);
446
+ } else {
447
+ throw new Error("writeText not supported");
448
+ }
449
+ } catch {
450
+ oldSchoolCopy(value);
451
+ }
452
+ };
453
+ var useCopyable = () => {
454
+ const [state, setState] = React5.useState("idle");
455
+ const copy = React5.useCallback(async (value, onClick) => {
456
+ if (!value) {
457
+ return;
458
+ }
459
+ setState("copying");
460
+ await Promise.all([copyToClipboard(value), waitMs(350)]);
461
+ onClick?.();
462
+ setState("copied");
463
+ await waitMs(1750);
464
+ setState("idle");
465
+ }, []);
466
+ return { state, copy };
467
+ };
468
+
469
+ // src/core/copyable/Copyable.tsx
470
+ import { jsx as jsx11, jsxs as jsxs5 } from "react/jsx-runtime";
471
+ var Copyable = ({ children, value, tooltip, onClick, asChild }) => {
472
+ const { state, copy } = useCopyable();
473
+ const handleCopy = async (e) => {
474
+ e.stopPropagation();
475
+ await copy(value, onClick);
476
+ };
477
+ if (!value && tooltip) {
478
+ return /* @__PURE__ */ jsx11(Tooltip, { trigger: children, content: tooltip });
479
+ }
480
+ if (!value) {
481
+ return children;
482
+ }
483
+ return /* @__PURE__ */ jsxs5(RadixTooltip2.Root, { open: state === "copied" ? true : void 0, delayDuration: 150, children: [
484
+ /* @__PURE__ */ jsx11(
485
+ RadixTooltip2.Trigger,
486
+ {
487
+ asChild: true,
488
+ onClick: handleCopy,
489
+ className: twJoin5(
490
+ "w-fit cursor-pointer rounded-xs",
491
+ state !== "copied" && "hover:bg-[#E8E8EB] hover:shadow-[0_0_0_2px_#E8E8EB] active:opacity-60",
492
+ state === "copying" && "opacity-60"
493
+ ),
494
+ children: asChild ? children : /* @__PURE__ */ jsx11("span", { children })
495
+ }
496
+ ),
497
+ tooltip && state === "idle" && /* @__PURE__ */ jsx11(TooltipContent, { side: "bottom", children: tooltip }),
498
+ /* @__PURE__ */ jsx11(RadixTooltip2.Portal, { children: /* @__PURE__ */ jsx11(
499
+ RadixTooltip2.Content,
500
+ {
501
+ sideOffset: 6,
502
+ side: "right",
503
+ className: twJoin5(
504
+ "z-101 grid h-6 w-6 place-items-center rounded-sm bg-white shadow-lg",
505
+ state !== "copying" && "animate-fade-in"
506
+ ),
507
+ children: /* @__PURE__ */ jsx11("div", { className: state === "copied" ? "text-green-500" : "text-gray-500", children: /* @__PURE__ */ jsx11(
508
+ Icon,
509
+ {
510
+ icon: state === "copied" ? faCheck : faCopy
511
+ }
512
+ ) })
513
+ }
514
+ ) })
515
+ ] });
516
+ };
517
+
518
+ // src/core/date-picker/DatePickerRange.tsx
519
+ import { useCallback as useCallback4 } from "react";
520
+ import DatePickerLib from "react-datepicker";
521
+
522
+ // src/core/date-picker/DatePickerHeader.tsx
523
+ import { faChevronLeft, faChevronRight as faChevronRight2 } from "@fortawesome/free-solid-svg-icons";
524
+ import { getMonth, getYear } from "date-fns";
525
+ import { range } from "lodash-es";
526
+ import { jsx as jsx12, jsxs as jsxs6 } from "react/jsx-runtime";
527
+ var years = range(1920, getYear(/* @__PURE__ */ new Date()) + 1, 1).sort((a, b) => b - a);
528
+ var months = [
529
+ "January",
530
+ "February",
531
+ "March",
532
+ "April",
533
+ "May",
534
+ "June",
535
+ "July",
536
+ "August",
537
+ "September",
538
+ "October",
539
+ "November",
540
+ "December"
541
+ ];
542
+ var DatePickerHeader = ({
543
+ date,
544
+ decreaseMonth,
545
+ increaseMonth,
546
+ changeMonth,
547
+ changeYear,
548
+ prevMonthButtonDisabled,
549
+ nextMonthButtonDisabled
550
+ }) => {
551
+ const datePickerContainer = document.querySelector(".react-datepicker") ?? void 0;
552
+ return /* @__PURE__ */ jsx12("div", { className: "space-y-2 p-2", children: /* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-2", children: [
553
+ /* @__PURE__ */ jsx12(Button, { onClick: decreaseMonth, disabled: prevMonthButtonDisabled, variant: "transparent", size: "sm", children: /* @__PURE__ */ jsx12(Icon, { icon: faChevronLeft }) }),
554
+ /* @__PURE__ */ jsx12(
555
+ Select,
556
+ {
557
+ size: "sm",
558
+ popover: {
559
+ container: datePickerContainer
560
+ },
561
+ value: months[getMonth(date)],
562
+ onChange: (value) => changeMonth(months.indexOf(value)),
563
+ items: months.map((month) => ({ label: month, value: month }))
564
+ }
565
+ ),
566
+ /* @__PURE__ */ jsx12(
567
+ Select,
568
+ {
569
+ size: "sm",
570
+ popover: {
571
+ container: datePickerContainer
572
+ },
573
+ value: getYear(date).toString(),
574
+ onChange: (value) => changeYear(parseInt(value)),
575
+ items: years.map((year) => ({ label: year.toString(), value: year.toString() }))
576
+ }
577
+ ),
578
+ /* @__PURE__ */ jsx12(Button, { onClick: increaseMonth, disabled: nextMonthButtonDisabled, variant: "transparent", size: "sm", children: /* @__PURE__ */ jsx12(Icon, { icon: faChevronRight2 }) })
579
+ ] }) });
580
+ };
581
+
582
+ // src/core/date-picker/shared.tsx
583
+ import { faCalendar, faXmark } from "@fortawesome/free-solid-svg-icons";
584
+
585
+ // src/core/date-picker/DatePickerInput.tsx
586
+ import { forwardRef as forwardRef3 } from "react";
587
+ import { twJoin as twJoin6, twMerge as twMerge3 } from "tailwind-merge";
588
+
589
+ // src/core/types.ts
590
+ var RING_COLOR_CLASSNAME = "focus:ring-2 focus:ring-indigo-200";
591
+
592
+ // src/core/date-picker/DatePickerInput.tsx
593
+ import { Fragment, jsx as jsx13, jsxs as jsxs7 } from "react/jsx-runtime";
594
+ var DatePickerInput = forwardRef3(
595
+ ({ inputProps, errorNode, hasError, rightAction, disabled, className, ...rest }, ref) => {
596
+ const ringClassName = disabled ? "focus:outline-hidden focus:ring-0" : hasError ? "focus:outline-hidden focus:ring-red-500 focus:border-red-500" : RING_COLOR_CLASSNAME;
597
+ return /* @__PURE__ */ jsxs7(Fragment, { children: [
598
+ /* @__PURE__ */ jsxs7("div", { className: "relative block w-full rounded-md shadow-sm", children: [
599
+ /* @__PURE__ */ jsx13(
600
+ "input",
601
+ {
602
+ type: "text",
603
+ className: twMerge3(
604
+ "block w-full rounded-md disabled:bg-gray-100",
605
+ rightAction && "pr-8",
606
+ hasError ? "border-red-300 text-red-900 placeholder-red-300" : "border-gray-200",
607
+ ringClassName,
608
+ className,
609
+ inputProps?.className
610
+ ),
611
+ ref,
612
+ disabled,
613
+ autoComplete: "off",
614
+ ...rest,
615
+ ...inputProps
616
+ }
617
+ ),
618
+ rightAction && /* @__PURE__ */ jsx13("div", { className: twJoin6("absolute inset-y-0 right-0 flex items-center pr-3", disabled && "cursor-auto"), children: rightAction })
619
+ ] }),
620
+ hasError != null && errorNode != null && /* @__PURE__ */ jsx13("p", { className: "mt-2 max-h-[100px] overflow-auto text-sm text-red-600", children: errorNode })
621
+ ] });
622
+ }
623
+ );
624
+
625
+ // src/core/date-picker/shared.tsx
626
+ import { jsx as jsx14 } from "react/jsx-runtime";
627
+ var customInputFieldFactory = ({
628
+ inputProps,
629
+ errorNode,
630
+ hasError,
631
+ isEmpty,
632
+ disabled,
633
+ onClearInput
634
+ }) => /* @__PURE__ */ jsx14(
635
+ DatePickerInput,
636
+ {
637
+ inputProps,
638
+ errorNode,
639
+ hasError,
640
+ rightAction: isEmpty ? /* @__PURE__ */ jsx14("span", { className: "text-gray-300", children: /* @__PURE__ */ jsx14(Icon, { icon: faCalendar }) }) : !disabled ? /* @__PURE__ */ jsx14(Button, { size: "xs", onClick: onClearInput, variant: "transparent", children: /* @__PURE__ */ jsx14("span", { className: "text-gray-500", children: /* @__PURE__ */ jsx14(Icon, { icon: faXmark }) }) }) : null
641
+ }
642
+ );
643
+
644
+ // src/core/date-picker/TimeInput.tsx
645
+ import { useCallback as useCallback3, useState as useState5 } from "react";
646
+
647
+ // src/core/input/InputBox.tsx
648
+ import * as React6 from "react";
649
+ import { forwardRef as forwardRef5 } from "react";
650
+
651
+ // src/core/input/inputBoxStyles.ts
652
+ import { twJoin as twJoin7 } from "tailwind-merge";
653
+ var sizeStyles2 = {
654
+ sm: "h-sm gap-1 px-2 text-sm [&>input]:text-sm",
655
+ md: "h-md gap-2 px-2.5 text-base [&>input]:text-base",
656
+ lg: "h-lg gap-2.5 px-3 text-lg [&>input]:text-lg"
657
+ };
658
+ var defaultVariantStyles = "rounded-md border bg-white focus-within:outline focus:outline focus-within:outline-offset-0 focus:outline-offset-0 focus-within:outline-2 focus:outline-2";
659
+ var transparentVariantStyles = "border-none bg-transparent focus-within:outline-hidden focus:outline-hidden";
660
+ var variantStyles = {
661
+ default: {
662
+ default: `${defaultVariantStyles} disabled:bg-gray-100 disabled:text-gray-400 border-gray-200 focus-within:border-indigo-400 focus-within:outline-indigo-200 focus:border-indigo-400 focus:outline-indigo-200`,
663
+ error: `${defaultVariantStyles} border-red-300 focus-within:border-red-300 focus-within:outline-red-200 focus:border-red-300 focus:outline-red-200`,
664
+ warning: `${defaultVariantStyles} border-yellow-300 focus-within:border-yellow-300 focus-within:outline-yellow-200 focus:border-yellow-300 focus:outline-yellow-200`
665
+ },
666
+ transparent: {
667
+ default: `${transparentVariantStyles} disabled:bg-gray-100 disabled:text-gray-400`,
668
+ error: transparentVariantStyles,
669
+ warning: transparentVariantStyles
670
+ }
671
+ };
672
+ var inputBoxStyles = ({ size = "md", variant = "default", hasError, hasWarning }) => twJoin7(
673
+ "flex w-full items-center focus-within:ring-0 focus:ring-0 has-disabled:bg-gray-100 has-disabled:text-gray-400",
674
+ sizeStyles2[size],
675
+ variantStyles[variant][hasError ? "error" : hasWarning ? "warning" : "default"]
676
+ );
677
+ var inputStyles = "w-full text-gray-800 placeholder:text-gray-400 disabled:text-gray-400";
678
+
679
+ // src/core/input/InputBox.tsx
680
+ import { jsx as jsx15, jsxs as jsxs8 } from "react/jsx-runtime";
681
+ var NestedInputImpl = (props, ref) => {
682
+ return /* @__PURE__ */ jsx15(
683
+ "input",
684
+ {
685
+ type: "text",
686
+ className: `${inputStyles} border-none bg-transparent p-0 focus:ring-0 focus:outline-hidden`,
687
+ autoComplete: "off",
688
+ ...props,
689
+ ref
690
+ }
691
+ );
692
+ };
693
+ var NestedInput = forwardRef5(NestedInputImpl);
694
+ var InputBoxImpl = ({ children, ...style }, ref) => (
695
+ // Styling text to propagate stateful text color inheritance for the children of InputBox
696
+ // (think Icons, other non-input elements). Avoids style collisions when Input is used solo.
697
+ /* @__PURE__ */ jsx15("label", { ref, className: `${style.hasError ? "text-red-300" : "text-gray-400"} ${inputBoxStyles(style)}`, children })
698
+ );
699
+ var InputBox = React6.forwardRef(InputBoxImpl);
700
+ InputBox.Input = NestedInput;
701
+ var InputImpl = ({ size, variant, hasError, hasWarning, prefix, ...rest }, ref) => {
702
+ return prefix ? /* @__PURE__ */ jsxs8("div", { className: "flex flex-row items-center", children: [
703
+ /* @__PURE__ */ jsx15("label", { className: "p-1 text-gray-500", children: prefix }),
704
+ /* @__PURE__ */ jsx15(
705
+ "input",
706
+ {
707
+ type: "text",
708
+ className: `${inputStyles} ${inputBoxStyles({ size, variant, hasError, hasWarning })}`,
709
+ autoComplete: "off",
710
+ ...rest,
711
+ ref
712
+ }
713
+ )
714
+ ] }) : /* @__PURE__ */ jsx15(
715
+ "input",
716
+ {
717
+ type: "text",
718
+ className: `${inputStyles} ${inputBoxStyles({ size, variant, hasError, hasWarning })}`,
719
+ autoComplete: "off",
720
+ ...rest,
721
+ ref
722
+ }
723
+ );
724
+ };
725
+ var Input = forwardRef5(InputImpl);
726
+
727
+ // src/core/date-picker/TimeInput.tsx
728
+ import { jsx as jsx16 } from "react/jsx-runtime";
729
+ var TimeInput = ({
730
+ value: inputValue,
731
+ onChange
732
+ }) => {
733
+ const [value, setValue] = useState5(inputValue?.toString());
734
+ const handleUpdateTime = useCallback3(() => {
735
+ onChange?.(value);
736
+ }, [value, onChange]);
737
+ const handleKeyDown = (event) => {
738
+ if (event.key === "Enter") {
739
+ handleUpdateTime();
740
+ }
741
+ };
742
+ return /* @__PURE__ */ jsx16(
743
+ Input,
744
+ {
745
+ value,
746
+ onChange: (e) => setValue(e.target.value),
747
+ onBlur: handleUpdateTime,
748
+ onKeyDown: handleKeyDown,
749
+ type: "time",
750
+ required: true
751
+ }
752
+ );
753
+ };
754
+
755
+ // src/core/date-picker/DatePickerRange.tsx
756
+ import { jsx as jsx17 } from "react/jsx-runtime";
757
+ var DatePickerRange = ({
758
+ value = [void 0, void 0],
759
+ errorNode,
760
+ hasError,
761
+ inputProps,
762
+ placeholder,
763
+ onChange,
764
+ position = "bottom-start",
765
+ ...props
766
+ }) => {
767
+ const handleChange = useCallback4(
768
+ (date) => onChange?.([date[0] || void 0, date[1] || void 0]),
769
+ [onChange]
770
+ );
771
+ const clearDatePicker = useCallback4(
772
+ (e) => {
773
+ e.preventDefault();
774
+ onChange?.([void 0, void 0]);
775
+ },
776
+ [onChange]
777
+ );
778
+ return /* @__PURE__ */ jsx17(
779
+ DatePickerLib,
780
+ {
781
+ ...props,
782
+ className: "placeholder:text-gray-400",
783
+ selected: value[0],
784
+ onChange: handleChange,
785
+ startDate: value[0],
786
+ endDate: value[1],
787
+ dateFormat: props.showTimeInput ? "MM/dd/yyyy h:mm aa" : "MM/dd/yyyy",
788
+ selectsRange: true,
789
+ popperPlacement: position,
790
+ placeholderText: placeholder,
791
+ customInput: !props.inline ? customInputFieldFactory({
792
+ inputProps,
793
+ isEmpty: value[0] == null && value[1] == null,
794
+ disabled: props.disabled,
795
+ errorNode,
796
+ hasError,
797
+ onClearInput: clearDatePicker
798
+ }) : void 0,
799
+ customTimeInput: /* @__PURE__ */ jsx17(TimeInput, {}),
800
+ renderCustomHeader: DatePickerHeader
801
+ }
802
+ );
803
+ };
804
+
805
+ // src/core/date-picker/DatePickerSingle.tsx
806
+ import { useCallback as useCallback5 } from "react";
807
+ import DatePickerLib2 from "react-datepicker";
808
+ import { jsx as jsx18 } from "react/jsx-runtime";
809
+ var DatePickerSingle = ({
810
+ value,
811
+ errorNode,
812
+ hasError,
813
+ inputProps,
814
+ placeholder,
815
+ onChange,
816
+ position = "bottom-start",
817
+ preventOpenOnFocus = true,
818
+ ...props
819
+ }) => {
820
+ const handleChange = useCallback5((date) => onChange?.(date ?? void 0), [onChange]);
821
+ const clearDatePicker = useCallback5(
822
+ (e) => {
823
+ e.preventDefault();
824
+ onChange?.(void 0);
825
+ },
826
+ [onChange]
827
+ );
828
+ return /* @__PURE__ */ jsx18(
829
+ DatePickerLib2,
830
+ {
831
+ ...props,
832
+ className: "placeholder:text-gray-400",
833
+ preventOpenOnFocus,
834
+ selected: value,
835
+ onChange: handleChange,
836
+ timeInputLabel: "",
837
+ dateFormat: props.showTimeInput ? "MM/dd/yyyy h:mm aa" : "MM/dd/yyyy",
838
+ placeholderText: placeholder,
839
+ customInput: !props.inline ? customInputFieldFactory({
840
+ inputProps,
841
+ isEmpty: value == null,
842
+ disabled: props.disabled,
843
+ errorNode,
844
+ hasError,
845
+ onClearInput: clearDatePicker
846
+ }) : void 0,
847
+ customTimeInput: /* @__PURE__ */ jsx18(TimeInput, {}),
848
+ renderCustomHeader: DatePickerHeader,
849
+ popperPlacement: position
850
+ }
851
+ );
852
+ };
853
+
854
+ // src/core/date-picker/DatePicker.tsx
855
+ import { jsx as jsx19 } from "react/jsx-runtime";
856
+ var DatePicker = (props) => props.range ? /* @__PURE__ */ jsx19(DatePickerRange, { ...props }) : /* @__PURE__ */ jsx19(DatePickerSingle, { ...props });
857
+
858
+ // src/core/divider/Divider.tsx
859
+ import { twMerge as twMerge4 } from "tailwind-merge";
860
+ import { jsx as jsx20 } from "react/jsx-runtime";
861
+ var Divider = ({ className }) => /* @__PURE__ */ jsx20("div", { className: twMerge4("h-[1px] w-full border-b border-gray-200", className) });
862
+
863
+ // src/core/error-text/ErrorText.tsx
864
+ import { forwardRef as forwardRef6 } from "react";
865
+ import { twJoin as twJoin8 } from "tailwind-merge";
866
+ import { jsx as jsx21 } from "react/jsx-runtime";
867
+ var ErrorTextImpl = ({ className, ...props }, ref) => {
868
+ if (!props.children) {
869
+ return null;
870
+ }
871
+ return /* @__PURE__ */ jsx21("p", { ...props, ref, className: twJoin8("text-red-600", className) });
872
+ };
873
+ var ErrorText = forwardRef6(ErrorTextImpl);
874
+
875
+ // src/core/form/index.ts
876
+ import { FormProvider, useFieldArray, useFormState as useFormState2, useWatch, useController as useController2 } from "react-hook-form";
877
+
878
+ // src/core/form/components/ControlledField.tsx
879
+ import { createContext as createContext2, useContext as useContext2, useMemo as useMemo2 } from "react";
880
+
881
+ // src/core/form/hooks.ts
882
+ import { zodResolver } from "@hookform/resolvers/zod";
883
+ import * as React8 from "react";
884
+ import { useController, useForm as _useForm, useFormContext as _useFormContext, useFormState } from "react-hook-form";
885
+ var useForm = (schema, options) => {
886
+ const methods = _useForm(
887
+ options != null ? { resolver: zodResolver(schema), ...options } : { resolver: zodResolver(schema) }
888
+ );
889
+ const { setError } = methods;
890
+ const setRootError = React8.useCallback(
891
+ (message) => {
892
+ setError("root", { type: "root", message });
893
+ },
894
+ [setError]
895
+ );
896
+ return { ...methods, setRootError };
897
+ };
898
+ useForm.displayName = "useForm";
899
+ var useFormContext = () => {
900
+ const methods = _useFormContext();
901
+ const { setError } = methods;
902
+ const setRootError = React8.useCallback(
903
+ (message) => {
904
+ setError("root", { type: "root", message });
905
+ },
906
+ [setError]
907
+ );
908
+ return { ...methods, setRootError };
909
+ };
910
+ useFormContext.displayName = "useFormContext";
911
+ var useControlledFormField = ({ name: fieldName }) => {
912
+ const { field, fieldState } = useController({ name: fieldName });
913
+ const { error } = fieldState;
914
+ return { ...field, error };
915
+ };
916
+ useControlledFormField.displayName = "useControlledFormField";
917
+ var useUncontrolledFormField = ({ name: fieldName, ...changeHandlers }) => {
918
+ const { register, getFieldState } = useFormContext();
919
+ const formState = useFormState();
920
+ const memoizedRegister = React8.useCallback(() => {
921
+ if (!changeHandlers) {
922
+ return register(fieldName);
923
+ }
924
+ const { onChange, onBlur, ...restRegister } = register(fieldName);
925
+ const handleOnChange = async (event) => {
926
+ await onChange(event);
927
+ changeHandlers?.onChange?.(event);
928
+ };
929
+ const handleOnBlur = async (event) => {
930
+ await onBlur(event);
931
+ changeHandlers?.onBlur?.(event);
932
+ };
933
+ return {
934
+ // TODO: add id to register for easier linking with labels
935
+ // id: register().name,
936
+ ...restRegister,
937
+ onChange: changeHandlers?.onChange ? handleOnChange : onChange,
938
+ onBlur: changeHandlers?.onBlur ? handleOnBlur : onBlur
939
+ };
940
+ }, [changeHandlers, register, fieldName]);
941
+ const { error } = getFieldState(fieldName, formState);
942
+ return { register: memoizedRegister, error };
943
+ };
944
+ useUncontrolledFormField.displayName = "useUncontrolledFormField";
945
+
946
+ // src/core/form/components/ControlledField.tsx
947
+ import { Fragment as Fragment2, jsx as jsx22 } from "react/jsx-runtime";
948
+ var ControlledFieldContext = createContext2(void 0);
949
+ var ControlledFieldProvider = ({ children, ...restField }) => {
950
+ const field = useControlledFormField(restField);
951
+ const value = useMemo2(() => field, [field]);
952
+ return /* @__PURE__ */ jsx22(ControlledFieldContext.Provider, { value, children });
953
+ };
954
+ ControlledFieldProvider.displayName = "ControlledFieldProvider";
955
+ var useControlledField = () => {
956
+ const context = useContext2(ControlledFieldContext);
957
+ if (context) {
958
+ return context;
959
+ }
960
+ throw new Error("useControlledField must be used within ControlledFieldProvider");
961
+ };
962
+ useControlledField.displayName = "useControlledField";
963
+ var ControlledField = ({ render, ...restField }) => {
964
+ return /* @__PURE__ */ jsx22(Fragment2, { children: render(useControlledFormField(restField)) });
965
+ };
966
+ ControlledField.displayName = "ControlledField";
967
+
968
+ // src/core/form/components/UncontrolledField.tsx
969
+ import { createContext as createContext3, useContext as useContext3, useMemo as useMemo3 } from "react";
970
+ import { Fragment as Fragment3, jsx as jsx23 } from "react/jsx-runtime";
971
+ var UncontrolledFieldContext = createContext3(void 0);
972
+ var UncontrolledFieldProvider = ({
973
+ children,
974
+ ...restField
975
+ }) => {
976
+ const field = useUncontrolledFormField(restField);
977
+ const value = useMemo3(() => field, [field]);
978
+ return /* @__PURE__ */ jsx23(UncontrolledFieldContext.Provider, { value, children });
979
+ };
980
+ UncontrolledFieldProvider.displayName = "UncontrolledFieldProvider";
981
+ var useUncontrolledField = () => {
982
+ const context = useContext3(UncontrolledFieldContext);
983
+ if (context) {
984
+ return context;
985
+ }
986
+ throw new Error("useUncontrolledField must be used within UncontrolledFieldProvider");
987
+ };
988
+ useUncontrolledField.displayName = "useUncontrolledField";
989
+ var UncontrolledField = ({ render, ...restField }) => {
990
+ return /* @__PURE__ */ jsx23(Fragment3, { children: render(useUncontrolledFormField(restField)) });
991
+ };
992
+ UncontrolledField.displayName = "UncontrolledField";
993
+
994
+ // src/core/form/utils.ts
995
+ import { get } from "react-hook-form";
996
+ var getFieldError = (errors, name) => {
997
+ if (name == null || errors == null) {
998
+ return void 0;
999
+ }
1000
+ return get(errors, name);
1001
+ };
1002
+
1003
+ // src/core/form/components/form-item/index.tsx
1004
+ import { forwardRef as forwardRef11 } from "react";
1005
+
1006
+ // src/core/form/components/form-item/InlineFormItem.tsx
1007
+ import { forwardRef as forwardRef7 } from "react";
1008
+
1009
+ // src/core/form/components/form-item/FieldErrorTooltip.tsx
1010
+ import { jsx as jsx24 } from "react/jsx-runtime";
1011
+ var FieldErrorTooltip = ({ error, children }) => {
1012
+ return /* @__PURE__ */ jsx24(
1013
+ Tooltip,
1014
+ {
1015
+ variant: "light",
1016
+ open: error?.message ? void 0 : false,
1017
+ trigger: children,
1018
+ content: /* @__PURE__ */ jsx24(ErrorText, { children: error?.message })
1019
+ }
1020
+ );
1021
+ };
1022
+
1023
+ // src/core/form/components/form-item/InlineFormItem.tsx
1024
+ import { jsx as jsx25 } from "react/jsx-runtime";
1025
+ var InlineFormItem = forwardRef7(({ error, render }, ref) => {
1026
+ return /* @__PURE__ */ jsx25(FieldErrorTooltip, { error, children: /* @__PURE__ */ jsx25("span", { ref, children: render }) });
1027
+ });
1028
+
1029
+ // src/core/form/components/form-item/NoneFormItem.tsx
1030
+ import { forwardRef as forwardRef8 } from "react";
1031
+
1032
+ // src/core/form/components/form-item/FieldDescription.tsx
1033
+ import { twJoin as twJoin9 } from "tailwind-merge";
1034
+ import { jsx as jsx26 } from "react/jsx-runtime";
1035
+ var FieldDescription = ({ styles, children }) => {
1036
+ if (children == null) {
1037
+ return null;
1038
+ }
1039
+ return /* @__PURE__ */ jsx26("p", { className: twJoin9("text-sm text-gray-500", styles), children });
1040
+ };
1041
+
1042
+ // src/core/form/components/form-item/FieldErrorMessage.tsx
1043
+ import { faCircleExclamation } from "@fortawesome/free-solid-svg-icons";
1044
+
1045
+ // src/core/overflow-tooltip/OverflowTooltip.tsx
1046
+ import { jsx as jsx27, jsxs as jsxs9 } from "react/jsx-runtime";
1047
+ var OverflowTooltip = ({ element, tooltip, side, variant, ...props }) => {
1048
+ return /* @__PURE__ */ jsxs9(Tooltip.Root, { ...props, children: [
1049
+ /* @__PURE__ */ jsx27(Tooltip.OverflowTrigger, { element }),
1050
+ /* @__PURE__ */ jsx27(Tooltip.Content, { side, variant, children: tooltip })
1051
+ ] });
1052
+ };
1053
+
1054
+ // src/core/form/components/form-item/FieldErrorMessage.tsx
1055
+ import { jsx as jsx28, jsxs as jsxs10 } from "react/jsx-runtime";
1056
+ function handleErrorOrErrorArrayMessage(error) {
1057
+ if (!Array.isArray(error)) {
1058
+ return error.message;
1059
+ }
1060
+ if (error.length === 1) {
1061
+ return error[0].message;
1062
+ }
1063
+ return error.map((err, index) => `Item ${index + 1}: ${err.message}`).join(", ");
1064
+ }
1065
+ var FieldErrorMessage = ({ error }) => {
1066
+ if (error == null) {
1067
+ return null;
1068
+ }
1069
+ const message = handleErrorOrErrorArrayMessage(error);
1070
+ return /* @__PURE__ */ jsxs10("div", { className: "flex h-4.5 items-center gap-x-1 pt-0.5 text-sm", children: [
1071
+ /* @__PURE__ */ jsx28("span", { className: "text-red-400", children: /* @__PURE__ */ jsx28(Icon, { icon: faCircleExclamation }) }),
1072
+ /* @__PURE__ */ jsx28(
1073
+ OverflowTooltip,
1074
+ {
1075
+ tooltip: message,
1076
+ element: (ref) => /* @__PURE__ */ jsx28(ErrorText, { ref, className: "line-clamp-1 cursor-default break-all", children: message })
1077
+ }
1078
+ )
1079
+ ] });
1080
+ };
1081
+
1082
+ // src/core/form/components/form-item/FieldLabelWithTooltip.tsx
1083
+ import { faCircleQuestion } from "@fortawesome/free-solid-svg-icons";
1084
+ import { twJoin as twJoin11 } from "tailwind-merge";
1085
+
1086
+ // src/core/form/components/form-item/FieldLabel.tsx
1087
+ import { twJoin as twJoin10 } from "tailwind-merge";
1088
+ import { jsx as jsx29 } from "react/jsx-runtime";
1089
+ var FieldLabel = ({ styles, htmlFor, children }) => {
1090
+ if (children == null) {
1091
+ return null;
1092
+ }
1093
+ return /* @__PURE__ */ jsx29("label", { htmlFor, className: twJoin10("block text-sm font-normal text-gray-500", styles), children });
1094
+ };
1095
+
1096
+ // src/core/form/components/form-item/FieldLabelWithTooltip.tsx
1097
+ import { jsx as jsx30, jsxs as jsxs11 } from "react/jsx-runtime";
1098
+ var FieldLabelWithTooltip = ({ styles, label, options }) => {
1099
+ if (label == null) {
1100
+ return null;
1101
+ }
1102
+ return /* @__PURE__ */ jsxs11(FieldLabel, { styles: twJoin11("space-x-1", styles), children: [
1103
+ /* @__PURE__ */ jsx30("span", { children: label }),
1104
+ options?.optionalLabel && /* @__PURE__ */ jsx30("span", { className: "text-gray-400", children: "(Optional)" }),
1105
+ options?.tooltip && /* @__PURE__ */ jsx30(
1106
+ Tooltip,
1107
+ {
1108
+ content: options?.tooltip,
1109
+ trigger: /* @__PURE__ */ jsxs11("span", { className: "inline-flex items-baseline space-x-1", children: [
1110
+ /* @__PURE__ */ jsx30("span", { className: "leading-none", children: options.tooltipIcon ? options.tooltipIcon : /* @__PURE__ */ jsx30("span", { className: "text-gray-500", children: /* @__PURE__ */ jsx30(Icon, { icon: faCircleQuestion }) }) }),
1111
+ options?.tooltipLabel && /* @__PURE__ */ jsx30("span", { className: "font-normal text-gray-500", children: options?.tooltipLabel })
1112
+ ] })
1113
+ }
1114
+ ),
1115
+ options?.inlineLabelEndSlot
1116
+ ] });
1117
+ };
1118
+
1119
+ // src/core/form/components/form-item/NoneFormItem.tsx
1120
+ import { Fragment as Fragment4, jsx as jsx31, jsxs as jsxs12 } from "react/jsx-runtime";
1121
+ var NoneFormItemImpl = ({ label, options, render, error }, ref) => /* @__PURE__ */ jsxs12(Fragment4, { children: [
1122
+ /* @__PURE__ */ jsxs12("div", { children: [
1123
+ /* @__PURE__ */ jsx31(FieldLabelWithTooltip, { label, options }),
1124
+ /* @__PURE__ */ jsx31(FieldDescription, { styles: "pt-0.5", children: options?.description })
1125
+ ] }),
1126
+ /* @__PURE__ */ jsxs12("div", { ref, children: [
1127
+ render,
1128
+ /* @__PURE__ */ jsx31(FieldErrorMessage, { error }),
1129
+ options?.bottomSlot
1130
+ ] })
1131
+ ] });
1132
+ var NoneFormItem = forwardRef8(NoneFormItemImpl);
1133
+
1134
+ // src/core/form/components/form-item/SideBySideFormItem.tsx
1135
+ import { forwardRef as forwardRef9 } from "react";
1136
+ import { twJoin as twJoin12 } from "tailwind-merge";
1137
+ import { jsx as jsx32, jsxs as jsxs13 } from "react/jsx-runtime";
1138
+ var SideBySideFormItem = forwardRef9(
1139
+ ({ styles, label, options, render, error }, ref) => /* @__PURE__ */ jsxs13("div", { className: twJoin12("grid grid-cols-[minmax(0,2fr)_minmax(0,3fr)] gap-x-1", styles), ref, children: [
1140
+ /* @__PURE__ */ jsxs13("div", { className: "pt-2.5", children: [
1141
+ /* @__PURE__ */ jsx32(FieldLabelWithTooltip, { label, options }),
1142
+ /* @__PURE__ */ jsx32(FieldDescription, { styles: "pt-0.5", children: options?.description })
1143
+ ] }),
1144
+ /* @__PURE__ */ jsxs13("div", { children: [
1145
+ render,
1146
+ /* @__PURE__ */ jsx32(FieldErrorMessage, { error }),
1147
+ options?.bottomSlot
1148
+ ] })
1149
+ ] })
1150
+ );
1151
+
1152
+ // src/core/form/components/form-item/StackedFormItem.tsx
1153
+ import { forwardRef as forwardRef10 } from "react";
1154
+ import { twJoin as twJoin13 } from "tailwind-merge";
1155
+ import { jsx as jsx33, jsxs as jsxs14 } from "react/jsx-runtime";
1156
+ var StackedFormItem = forwardRef10(
1157
+ ({ styles, label, options, render, error }, ref) => /* @__PURE__ */ jsxs14("div", { className: styles || void 0, ref, children: [
1158
+ /* @__PURE__ */ jsx33(
1159
+ FieldLabelWithTooltip,
1160
+ {
1161
+ styles: twJoin13("flex items-baseline", options?.description == null && "pb-1"),
1162
+ label,
1163
+ options
1164
+ }
1165
+ ),
1166
+ /* @__PURE__ */ jsx33(FieldDescription, { styles: "pb-1", children: options?.description }),
1167
+ render,
1168
+ /* @__PURE__ */ jsx33(FieldErrorMessage, { error }),
1169
+ options?.bottomSlot
1170
+ ] })
1171
+ );
1172
+
1173
+ // src/core/form/components/form-item/index.tsx
1174
+ import { jsx as jsx34 } from "react/jsx-runtime";
1175
+ var FormItem = forwardRef11(({ layout = "stacked", ...rest }, ref) => {
1176
+ switch (layout) {
1177
+ case "inline":
1178
+ return /* @__PURE__ */ jsx34(InlineFormItem, { ...rest, ref });
1179
+ case "side-by-side":
1180
+ return /* @__PURE__ */ jsx34(SideBySideFormItem, { ...rest, ref });
1181
+ case "stacked":
1182
+ return /* @__PURE__ */ jsx34(StackedFormItem, { ...rest, ref });
1183
+ case "none":
1184
+ return /* @__PURE__ */ jsx34(NoneFormItem, { ...rest, ref });
1185
+ default:
1186
+ throw new Error(`Unknown form item layout: ${layout}`);
1187
+ }
1188
+ });
1189
+
1190
+ // src/core/form/components/FormInput.tsx
1191
+ import { jsx as jsx35 } from "react/jsx-runtime";
1192
+ var FormInput = ({
1193
+ name,
1194
+ styles,
1195
+ layout,
1196
+ label,
1197
+ options,
1198
+ onChange,
1199
+ onBlur,
1200
+ disabled,
1201
+ ...rest
1202
+ }) => /* @__PURE__ */ jsx35(
1203
+ UncontrolledField,
1204
+ {
1205
+ name,
1206
+ onChange,
1207
+ onBlur,
1208
+ render: ({ error, register }) => /* @__PURE__ */ jsx35(
1209
+ FormItem,
1210
+ {
1211
+ layout,
1212
+ styles,
1213
+ label,
1214
+ options,
1215
+ render: /* @__PURE__ */ jsx35(Input, { ...register(), ...rest, disabled, hasError: !disabled && (!!error || void 0) }),
1216
+ error
1217
+ }
1218
+ )
1219
+ }
1220
+ );
1221
+
1222
+ // src/core/form/components/FormDollarInput.tsx
1223
+ import { faCircleExclamation as faCircleExclamation2, faDollarSign, faTriangleExclamation as faTriangleExclamation2 } from "@fortawesome/free-solid-svg-icons";
1224
+ import { forwardRef as forwardRef12 } from "react";
1225
+ import { twJoin as twJoin14 } from "tailwind-merge";
1226
+
1227
+ // src/core/utils/useSyncState.ts
1228
+ import { useState as useState6 } from "react";
1229
+ var useSyncState = (upstream) => {
1230
+ const [prevUpstream, setPrevUpstream] = useState6(upstream);
1231
+ const [state, setState] = useState6(upstream);
1232
+ if (prevUpstream !== upstream) {
1233
+ setState(upstream);
1234
+ setPrevUpstream(upstream);
1235
+ }
1236
+ return [state, setState];
1237
+ };
1238
+
1239
+ // src/core/form/components/FormDollarInput.tsx
1240
+ import { jsx as jsx36, jsxs as jsxs15 } from "react/jsx-runtime";
1241
+ var twoDecimalFormatter = Intl.NumberFormat("en-US", {
1242
+ minimumFractionDigits: 2,
1243
+ maximumFractionDigits: 2
1244
+ });
1245
+ var formatInput = (value) => {
1246
+ return value.replaceAll(/[^0-9.,-]/g, "");
1247
+ };
1248
+ var roundToTwoDecimalPlaces = (value) => {
1249
+ return Math.round((value + Number.EPSILON) * 100) / 100;
1250
+ };
1251
+ var DollarInput = forwardRef12(
1252
+ ({ value, onChange, disabled = false, hasError = false, hasWarning = false, message }, ref) => {
1253
+ const [strValue, setStrValue] = useSyncState(value == null ? "" : twoDecimalFormatter.format(value / 100));
1254
+ const handleChange = (event) => {
1255
+ const inputValue = formatInput(event.target.value);
1256
+ if (!inputValue) {
1257
+ setStrValue("");
1258
+ return;
1259
+ }
1260
+ if (inputValue === "-" || inputValue === ".") {
1261
+ setStrValue(inputValue);
1262
+ return;
1263
+ }
1264
+ if (inputValue.split(".")?.[1]?.length > 2) return;
1265
+ const parsedValue = parseFloat(inputValue);
1266
+ if (!isNaN(parsedValue)) {
1267
+ setStrValue(inputValue);
1268
+ }
1269
+ };
1270
+ const handlePaste = (event) => {
1271
+ event.preventDefault();
1272
+ const pastedData = formatInput(event.clipboardData.getData("text"));
1273
+ const parsedAmount = parseFloat(pastedData);
1274
+ if (!isNaN(parsedAmount)) {
1275
+ setStrValue(twoDecimalFormatter.format(parsedAmount));
1276
+ onChange?.(roundToTwoDecimalPlaces(parsedAmount * 100));
1277
+ }
1278
+ };
1279
+ const handleBlur = () => {
1280
+ const parsedValue = parseFloat(strValue.replaceAll(",", ""));
1281
+ if (isNaN(parsedValue)) {
1282
+ onChange?.(null);
1283
+ } else {
1284
+ onChange?.(roundToTwoDecimalPlaces(parsedValue * 100));
1285
+ }
1286
+ };
1287
+ return /* @__PURE__ */ jsxs15("div", { className: "flex flex-col gap-0.5", children: [
1288
+ /* @__PURE__ */ jsxs15(
1289
+ "div",
1290
+ {
1291
+ className: twJoin14(
1292
+ "flex h-md w-full items-center rounded-sm py-2.5 text-base [&>input]:rounded-l-none! [&>input]:rounded-r-md!",
1293
+ disabled && "cursor-not-allowed [&>input]:cursor-not-allowed [&>input]:bg-gray-50! [&>input]:text-gray-500!"
1294
+ ),
1295
+ children: [
1296
+ /* @__PURE__ */ jsx36(
1297
+ "div",
1298
+ {
1299
+ className: twJoin14(
1300
+ "flex h-md w-9.5 items-center justify-center rounded-l-md border-y border-l px-2.5 text-sm text-gray-500",
1301
+ hasError ? "border-red-300 bg-red-200 text-red-700" : hasWarning ? "border-yellow-300 bg-yellow-100 text-yellow-700" : "border-gray-200 bg-gray-100"
1302
+ ),
1303
+ children: /* @__PURE__ */ jsx36(Icon, { icon: faDollarSign })
1304
+ }
1305
+ ),
1306
+ /* @__PURE__ */ jsx36(
1307
+ Input,
1308
+ {
1309
+ ref,
1310
+ variant: "default",
1311
+ disabled,
1312
+ value: strValue,
1313
+ hasError,
1314
+ hasWarning,
1315
+ onChange: handleChange,
1316
+ onBlur: handleBlur,
1317
+ onPaste: handlePaste,
1318
+ placeholder: "0.00"
1319
+ }
1320
+ )
1321
+ ]
1322
+ }
1323
+ ),
1324
+ hasWarning && message && /* @__PURE__ */ jsxs15("div", { className: "flex items-center gap-1 text-sm font-normal text-yellow-700", children: [
1325
+ /* @__PURE__ */ jsx36(Icon, { icon: faTriangleExclamation2 }),
1326
+ message
1327
+ ] }),
1328
+ hasError && message && /* @__PURE__ */ jsxs15("div", { className: "flex items-center gap-1 text-sm font-normal text-red-700", children: [
1329
+ /* @__PURE__ */ jsx36(Icon, { icon: faCircleExclamation2 }),
1330
+ message
1331
+ ] })
1332
+ ] });
1333
+ }
1334
+ );
1335
+ var FormDollarInput = forwardRef12(
1336
+ ({ name, layout, label, onChange, disabled, hasWarning = false, message, options }, ref) => /* @__PURE__ */ jsx36(
1337
+ ControlledField,
1338
+ {
1339
+ name,
1340
+ render: (field) => /* @__PURE__ */ jsx36(
1341
+ FormItem,
1342
+ {
1343
+ label,
1344
+ layout,
1345
+ options,
1346
+ error: field.error,
1347
+ render: /* @__PURE__ */ jsx36(
1348
+ DollarInput,
1349
+ {
1350
+ onChange: (cents) => {
1351
+ field.onChange(cents);
1352
+ onChange?.(cents);
1353
+ },
1354
+ value: field.value,
1355
+ disabled,
1356
+ hasError: !disabled && (!!field.error || void 0),
1357
+ hasWarning: !disabled && hasWarning,
1358
+ message,
1359
+ ref
1360
+ }
1361
+ )
1362
+ }
1363
+ )
1364
+ }
1365
+ )
1366
+ );
1367
+
1368
+ // src/core/form/components/FormPercentInput.tsx
1369
+ import { faCircleExclamation as faCircleExclamation3, faPercent, faTriangleExclamation as faTriangleExclamation3 } from "@fortawesome/free-solid-svg-icons";
1370
+ import { forwardRef as forwardRef13 } from "react";
1371
+ import { twJoin as twJoin15 } from "tailwind-merge";
1372
+ import { jsx as jsx37, jsxs as jsxs16 } from "react/jsx-runtime";
1373
+ var twoDecimalFormatter2 = Intl.NumberFormat("en-US", {
1374
+ minimumFractionDigits: 0,
1375
+ maximumFractionDigits: 2
1376
+ });
1377
+ var formatInput2 = (value) => {
1378
+ return value.replaceAll(/[^0-9.,]/g, "");
1379
+ };
1380
+ var roundToTwoDecimalPlaces2 = (value) => {
1381
+ return Math.round((value + Number.EPSILON) * 100) / 100;
1382
+ };
1383
+ var PercentInput = forwardRef13(
1384
+ ({ value, onChange, disabled = false, hasError = false, hasWarning = false, message }, ref) => {
1385
+ const [strValue, setStrValue] = useSyncState(value == null ? "" : twoDecimalFormatter2.format(value));
1386
+ const handleChange = (event) => {
1387
+ const inputValue = formatInput2(event.target.value);
1388
+ if (!inputValue) {
1389
+ setStrValue("");
1390
+ return;
1391
+ }
1392
+ if (inputValue === ".") {
1393
+ setStrValue(inputValue);
1394
+ return;
1395
+ }
1396
+ if (inputValue.split(".")?.[1]?.length > 2) return;
1397
+ const parsedValue = parseFloat(inputValue);
1398
+ if (!isNaN(parsedValue)) {
1399
+ setStrValue(inputValue);
1400
+ }
1401
+ };
1402
+ const handlePaste = (event) => {
1403
+ event.preventDefault();
1404
+ const pastedData = formatInput2(event.clipboardData.getData("text"));
1405
+ const parsedAmount = parseFloat(pastedData);
1406
+ if (!isNaN(parsedAmount)) {
1407
+ setStrValue(twoDecimalFormatter2.format(parsedAmount));
1408
+ onChange?.(roundToTwoDecimalPlaces2(parsedAmount));
1409
+ }
1410
+ };
1411
+ const handleBlur = () => {
1412
+ const parsedValue = parseFloat(strValue.replaceAll(",", ""));
1413
+ if (isNaN(parsedValue)) {
1414
+ onChange?.(null);
1415
+ } else {
1416
+ onChange?.(roundToTwoDecimalPlaces2(parsedValue));
1417
+ }
1418
+ };
1419
+ return /* @__PURE__ */ jsxs16("div", { className: "flex flex-col gap-0.5", children: [
1420
+ /* @__PURE__ */ jsxs16(
1421
+ "div",
1422
+ {
1423
+ className: twJoin15(
1424
+ "flex h-md w-full items-center rounded-sm py-2.5 text-base [&>input]:rounded-l-none! [&>input]:rounded-r-md!",
1425
+ disabled && "cursor-not-allowed [&>input]:cursor-not-allowed [&>input]:bg-gray-50! [&>input]:text-gray-500!"
1426
+ ),
1427
+ children: [
1428
+ /* @__PURE__ */ jsx37(
1429
+ "div",
1430
+ {
1431
+ className: twJoin15(
1432
+ "flex h-md w-9.5 items-center justify-center rounded-l-md border-y border-l px-2.5 text-sm text-gray-500",
1433
+ hasError ? "border-red-300 bg-red-200 text-red-700" : hasWarning ? "border-yellow-300 bg-yellow-100 text-yellow-700" : "border-gray-200 bg-gray-100"
1434
+ ),
1435
+ children: /* @__PURE__ */ jsx37(Icon, { icon: faPercent })
1436
+ }
1437
+ ),
1438
+ /* @__PURE__ */ jsx37(
1439
+ Input,
1440
+ {
1441
+ ref,
1442
+ variant: "default",
1443
+ disabled,
1444
+ value: strValue,
1445
+ hasError,
1446
+ hasWarning,
1447
+ onChange: handleChange,
1448
+ onBlur: handleBlur,
1449
+ onPaste: handlePaste,
1450
+ placeholder: "0"
1451
+ }
1452
+ )
1453
+ ]
1454
+ }
1455
+ ),
1456
+ hasWarning && message && /* @__PURE__ */ jsxs16("div", { className: "flex items-center gap-1 text-sm font-normal text-yellow-700", children: [
1457
+ /* @__PURE__ */ jsx37(Icon, { icon: faTriangleExclamation3 }),
1458
+ message
1459
+ ] }),
1460
+ hasError && message && /* @__PURE__ */ jsxs16("div", { className: "flex items-center gap-1 text-sm font-normal text-red-700", children: [
1461
+ /* @__PURE__ */ jsx37(Icon, { icon: faCircleExclamation3 }),
1462
+ message
1463
+ ] })
1464
+ ] });
1465
+ }
1466
+ );
1467
+ var FormPercentInput = forwardRef13(
1468
+ ({ name, layout, label, onChange, disabled, hasWarning = false, message, options }, ref) => /* @__PURE__ */ jsx37(
1469
+ ControlledField,
1470
+ {
1471
+ name,
1472
+ render: (field) => /* @__PURE__ */ jsx37(
1473
+ FormItem,
1474
+ {
1475
+ label,
1476
+ layout,
1477
+ options,
1478
+ error: field.error,
1479
+ render: /* @__PURE__ */ jsx37(
1480
+ PercentInput,
1481
+ {
1482
+ onChange: (percent) => {
1483
+ field.onChange(percent);
1484
+ onChange?.(percent);
1485
+ },
1486
+ value: field.value,
1487
+ disabled,
1488
+ hasError: !disabled && (!!field.error || void 0),
1489
+ hasWarning: !disabled && hasWarning,
1490
+ message,
1491
+ ref
1492
+ }
1493
+ )
1494
+ }
1495
+ )
1496
+ }
1497
+ )
1498
+ );
1499
+
1500
+ // src/core/form/components/FormCheckbox.tsx
1501
+ import { Fragment as Fragment5, jsx as jsx38, jsxs as jsxs17 } from "react/jsx-runtime";
1502
+ var FormCheckbox = ({ name, disabled, onChange: propsOnChange, children }) => {
1503
+ const {
1504
+ onChange,
1505
+ error,
1506
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
1507
+ value,
1508
+ ...field
1509
+ } = useControlledFormField({ name });
1510
+ const handleChange = (e) => {
1511
+ const { checked } = e.target;
1512
+ onChange(checked);
1513
+ propsOnChange?.(checked);
1514
+ };
1515
+ if (children == null) {
1516
+ return /* @__PURE__ */ jsxs17(Fragment5, { children: [
1517
+ /* @__PURE__ */ jsx38(
1518
+ Checkbox,
1519
+ {
1520
+ ...field,
1521
+ id: name,
1522
+ disabled,
1523
+ checked: !!value,
1524
+ onChange: handleChange,
1525
+ hasError: !!error
1526
+ }
1527
+ ),
1528
+ /* @__PURE__ */ jsx38(FieldErrorMessage, { error })
1529
+ ] });
1530
+ }
1531
+ return /* @__PURE__ */ jsxs17(ControlledFieldProvider, { name, children: [
1532
+ children,
1533
+ /* @__PURE__ */ jsx38(FieldErrorMessage, { error })
1534
+ ] });
1535
+ };
1536
+ function CheckboxImpl({ onChange: propsOnChange }) {
1537
+ const {
1538
+ name,
1539
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
1540
+ value,
1541
+ onChange,
1542
+ error,
1543
+ ...field
1544
+ } = useControlledField();
1545
+ const handleChange = (e) => {
1546
+ const { checked } = e.target;
1547
+ onChange(checked);
1548
+ propsOnChange?.(checked);
1549
+ };
1550
+ return /* @__PURE__ */ jsx38(Checkbox, { ...field, id: name, checked: !!value, onChange: handleChange, hasError: !!error });
1551
+ }
1552
+ function LabelImpl({ children, className }) {
1553
+ const { name } = useControlledField();
1554
+ return /* @__PURE__ */ jsx38(FieldLabel, { htmlFor: name, styles: className, children });
1555
+ }
1556
+ FormCheckbox.Label = LabelImpl;
1557
+ FormCheckbox.Checkbox = CheckboxImpl;
1558
+
1559
+ // src/core/form/components/ControlledFormItem.tsx
1560
+ import { jsx as jsx39 } from "react/jsx-runtime";
1561
+ var ControlledFormItem = ({
1562
+ name,
1563
+ styles,
1564
+ layout,
1565
+ label,
1566
+ options,
1567
+ render
1568
+ }) => {
1569
+ const field = useControlledFormField({ name });
1570
+ return /* @__PURE__ */ jsx39(
1571
+ FormItem,
1572
+ {
1573
+ layout,
1574
+ styles,
1575
+ label,
1576
+ options,
1577
+ render: render(field),
1578
+ error: field.error
1579
+ }
1580
+ );
1581
+ };
1582
+
1583
+ // src/core/select/props.ts
1584
+ var DEFAULT_NUM_VALUES_TO_SHOW = 2;
1585
+
1586
+ // src/core/select/selectItem.ts
1587
+ function doesSelectItemMatch(option, query) {
1588
+ if (!query) {
1589
+ return true;
1590
+ }
1591
+ if (option.isMatch) {
1592
+ return option.isMatch(query);
1593
+ }
1594
+ return option.label.toLowerCase().includes(query.toLowerCase());
1595
+ }
1596
+
1597
+ // src/core/select/useAsyncMultiSelect.ts
1598
+ import { useQuery } from "@tanstack/react-query";
1599
+ import { useEffect as useEffect3, useMemo as useMemo4, useState as useState7 } from "react";
1600
+ function useDebounce(value, delay) {
1601
+ const [debouncedValue, setDebouncedValue] = useState7(value);
1602
+ useEffect3(() => {
1603
+ const handler = setTimeout(() => {
1604
+ setDebouncedValue(value);
1605
+ }, delay);
1606
+ return () => {
1607
+ clearTimeout(handler);
1608
+ };
1609
+ }, [value, delay]);
1610
+ return debouncedValue;
1611
+ }
1612
+ function useAsyncMultiSelect({
1613
+ value,
1614
+ fetchValues,
1615
+ fetchOptions,
1616
+ objToItem,
1617
+ customValueToItem,
1618
+ queryKeyPrefix
1619
+ }) {
1620
+ const [query, setQuery] = useState7("");
1621
+ const [page, setPage] = useState7(void 0);
1622
+ const debouncedSearchTerm = useDebounce(query, 500);
1623
+ const key = Array.isArray(queryKeyPrefix) ? queryKeyPrefix : [queryKeyPrefix];
1624
+ const { data: fetchedValues } = useQuery({
1625
+ queryKey: [...key, "values", value],
1626
+ queryFn: () => fetchValues(value),
1627
+ enabled: !!value
1628
+ });
1629
+ const {
1630
+ data: fetchedOptions,
1631
+ isLoading: isLoadingOptions,
1632
+ error: optionsError
1633
+ } = useQuery({
1634
+ queryKey: [...key, "options", debouncedSearchTerm, page],
1635
+ queryFn: () => fetchOptions(debouncedSearchTerm, page)
1636
+ });
1637
+ const selectItems = useMemo4(() => {
1638
+ const fetchedValueItems = fetchedValues?.error === false ? fetchedValues.value.map(objToItem) : [];
1639
+ const customItems = customValueToItem ? value.filter((v) => !fetchedValueItems.some((i) => i.value === v)).map((v) => customValueToItem(v)) : [];
1640
+ const fetchedOptionItems = fetchedOptions?.error === false ? fetchedOptions.value.results.map(objToItem) : [];
1641
+ return [...fetchedValueItems, ...customItems, ...fetchedOptionItems];
1642
+ }, [objToItem, value, fetchedValues, fetchedOptions, customValueToItem]);
1643
+ const loadProps = {
1644
+ isLoading: isLoadingOptions,
1645
+ isError: !!(optionsError || !fetchedOptions || fetchedOptions.error),
1646
+ canLoadMore: !fetchedOptions?.error ? !!fetchedOptions?.value?.nextPage : false,
1647
+ onLoadMore: () => {
1648
+ if (!fetchedOptions?.error) {
1649
+ setPage(fetchedOptions?.value?.nextPage);
1650
+ }
1651
+ }
1652
+ };
1653
+ return {
1654
+ setQuery,
1655
+ selectItems,
1656
+ loadProps,
1657
+ queriedObjects: [
1658
+ ...fetchedValues?.error === false ? fetchedValues.value : [],
1659
+ ...fetchedOptions?.error === false ? fetchedOptions.value.results : []
1660
+ ]
1661
+ };
1662
+ }
1663
+ var useAsyncSelect = ({
1664
+ value,
1665
+ fetchValue,
1666
+ ...rest
1667
+ }) => useAsyncMultiSelect({
1668
+ value: value ? [value] : [],
1669
+ fetchValues: async (values) => {
1670
+ if (!values[0]) {
1671
+ return {
1672
+ error: false,
1673
+ value: []
1674
+ };
1675
+ }
1676
+ const result = await fetchValue(values[0]);
1677
+ if (result.error) return result;
1678
+ return {
1679
+ error: false,
1680
+ value: result.value ? [result.value] : []
1681
+ };
1682
+ },
1683
+ ...rest
1684
+ });
1685
+
1686
+ // src/core/select/AsyncMultiSelect.tsx
1687
+ import { DndContext, PointerSensor, useSensor, useSensors } from "@dnd-kit/core";
1688
+ import { SortableContext, verticalListSortingStrategy } from "@dnd-kit/sortable";
1689
+ import { faArrowTurnDown, faCheck as faCheck2, faMagnifyingGlass, faXmark as faXmark2 } from "@fortawesome/free-solid-svg-icons";
1690
+ import { useMemo as useMemo5, useRef as useRef4, useState as useState8 } from "react";
1691
+ import { twJoin as twJoin18 } from "tailwind-merge";
1692
+
1693
+ // src/core/dropdown-chevron/DropdownChevron.tsx
1694
+ import { faChevronDown as faChevronDown3 } from "@fortawesome/free-solid-svg-icons";
1695
+ import { twJoin as twJoin16 } from "tailwind-merge";
1696
+ import { jsx as jsx40 } from "react/jsx-runtime";
1697
+ var DropdownChevron = () => {
1698
+ return /* @__PURE__ */ jsx40("div", { className: twJoin16("w-3 text-sm text-gray-500"), children: /* @__PURE__ */ jsx40(Icon, { icon: faChevronDown3 }) });
1699
+ };
1700
+
1701
+ // src/core/popover/Popover.tsx
1702
+ import * as RadixPopover from "@radix-ui/react-popover";
1703
+ import { twMerge as twMerge5 } from "tailwind-merge";
1704
+ import { jsx as jsx41, jsxs as jsxs18 } from "react/jsx-runtime";
1705
+ var Popover = ({
1706
+ open,
1707
+ trigger,
1708
+ triggerClassName,
1709
+ children,
1710
+ arrowClassName,
1711
+ contentClassName,
1712
+ disabled,
1713
+ onOpenChange,
1714
+ alignContent,
1715
+ container,
1716
+ ...props
1717
+ }) => /* @__PURE__ */ jsxs18(RadixPopover.Root, { open, onOpenChange, children: [
1718
+ /* @__PURE__ */ jsx41(RadixPopover.Trigger, { asChild: true, disabled, className: triggerClassName, children: trigger }),
1719
+ /* @__PURE__ */ jsx41(
1720
+ PopoverBody,
1721
+ {
1722
+ align: alignContent,
1723
+ ...props,
1724
+ contentClassName,
1725
+ arrowClassName,
1726
+ container,
1727
+ children
1728
+ }
1729
+ )
1730
+ ] });
1731
+ var PopoverBody = ({ children, arrowClassName, contentClassName, container, ...props }) => {
1732
+ return /* @__PURE__ */ jsx41(RadixPopover.Portal, { container, children: /* @__PURE__ */ jsxs18(
1733
+ RadixPopover.Content,
1734
+ {
1735
+ ...props,
1736
+ className: twMerge5("isolate z-50 rounded-lg bg-white shadow-lg focus:outline-hidden", contentClassName),
1737
+ children: [
1738
+ children,
1739
+ /* @__PURE__ */ jsx41(RadixPopover.Arrow, { className: twMerge5("fill-white", arrowClassName), offset: 8 })
1740
+ ]
1741
+ }
1742
+ ) });
1743
+ };
1744
+ Popover.Root = (props) => /* @__PURE__ */ jsx41(RadixPopover.Root, { ...props });
1745
+ Popover.Trigger = (props) => /* @__PURE__ */ jsx41(RadixPopover.Trigger, { asChild: true, children: /* @__PURE__ */ jsx41(Button, { ...props }) });
1746
+ Popover.Body = PopoverBody;
1747
+ Popover.Close = (props) => /* @__PURE__ */ jsx41(RadixPopover.Close, { asChild: true, ...props });
1748
+
1749
+ // src/core/select/SelectListItem.tsx
1750
+ import { useSortable } from "@dnd-kit/sortable";
1751
+ import { CSS } from "@dnd-kit/utilities";
1752
+ import { faGripVertical } from "@fortawesome/free-solid-svg-icons";
1753
+ import { useEffect as useEffect4, useRef as useRef3 } from "react";
1754
+ import { twJoin as twJoin17 } from "tailwind-merge";
1755
+ import { jsx as jsx42, jsxs as jsxs19 } from "react/jsx-runtime";
1756
+ var SelectListItem = ({
1757
+ sortableId,
1758
+ children,
1759
+ onClick,
1760
+ disabled = false,
1761
+ focused = false
1762
+ }) => {
1763
+ const { setNodeRef, listeners, attributes, transform, transition } = useSortable({ id: sortableId ?? "" });
1764
+ const containerRef = useRef3(null);
1765
+ useEffect4(() => {
1766
+ if (focused && containerRef.current) {
1767
+ containerRef.current.scrollIntoView({ block: "nearest", inline: "nearest", behavior: "smooth" });
1768
+ }
1769
+ }, [focused]);
1770
+ return /* @__PURE__ */ jsxs19(
1771
+ "li",
1772
+ {
1773
+ ref: (ref) => {
1774
+ setNodeRef(ref);
1775
+ containerRef.current = ref;
1776
+ },
1777
+ onClick: disabled ? void 0 : onClick,
1778
+ className: twJoin17(
1779
+ "flex w-full items-center gap-2 rounded-lg px-2 py-1.5",
1780
+ disabled ? "cursor-not-allowed text-gray-400" : "cursor-pointer transition-colors duration-150 hover:bg-gray-100",
1781
+ focused && "bg-gray-100"
1782
+ ),
1783
+ style: {
1784
+ transform: CSS.Transform.toString(transform),
1785
+ transition
1786
+ },
1787
+ ...attributes,
1788
+ children: [
1789
+ sortableId && /* @__PURE__ */ jsx42(
1790
+ "div",
1791
+ {
1792
+ className: "cursor-grab font-medium active:cursor-grabbing",
1793
+ ...listeners,
1794
+ onClick: (e) => {
1795
+ e.stopPropagation();
1796
+ listeners?.onClick(e);
1797
+ },
1798
+ children: /* @__PURE__ */ jsx42(Icon, { icon: faGripVertical })
1799
+ }
1800
+ ),
1801
+ /* @__PURE__ */ jsx42("div", { className: "flex w-full flex-1 items-center justify-between", children })
1802
+ ]
1803
+ }
1804
+ );
1805
+ };
1806
+
1807
+ // src/core/select/AsyncMultiSelect.tsx
1808
+ import { Fragment as Fragment6, jsx as jsx43, jsxs as jsxs20 } from "react/jsx-runtime";
1809
+ var AsyncMultiSelect = ({
1810
+ value = [],
1811
+ onChange,
1812
+ disabled = false,
1813
+ ordered,
1814
+ variant,
1815
+ triggerPlaceholder,
1816
+ hideSearch = false,
1817
+ searchPlaceholder = "Search...",
1818
+ items,
1819
+ loadProps,
1820
+ onSearchChange,
1821
+ minSelection = 0,
1822
+ maxSelection = "unlimited",
1823
+ allowCustomValues,
1824
+ hasError,
1825
+ popover,
1826
+ isValidCustomValue = () => true,
1827
+ onSelectAll,
1828
+ numValuesToShow,
1829
+ emptyState,
1830
+ size,
1831
+ onOpen,
1832
+ onClose
1833
+ }) => {
1834
+ const [open, setOpen] = useState8(false);
1835
+ const [search, setSearch] = useState8("");
1836
+ const [focusIndex, setFocusIndex] = useState8(0);
1837
+ const inputRef = useRef4(null);
1838
+ const unselectedOptions = useMemo5(() => items.filter((item) => !value.includes(item.value)), [items, value]);
1839
+ const resetSearch = () => {
1840
+ setSearch("");
1841
+ onSearchChange?.("");
1842
+ };
1843
+ const handleClose = () => {
1844
+ setOpen(false);
1845
+ resetSearch();
1846
+ setFocusIndex(0);
1847
+ onClose?.();
1848
+ };
1849
+ const searchMatchesExistingOption = value.some((v) => v.toString().toLowerCase() === search.toLowerCase()) || unselectedOptions.find((opt) => opt.value?.toString().toLowerCase() === search.toLowerCase());
1850
+ const showCustomItem = allowCustomValues && !!search && !loadProps?.isLoading && !searchMatchesExistingOption && isValidCustomValue(search);
1851
+ const isCustomValueSelected = useMemo5(
1852
+ () => allowCustomValues && value.some((v) => !items.map((item) => item.value).includes(v)),
1853
+ [allowCustomValues, items, value]
1854
+ );
1855
+ const showCustomValue = isCustomValueSelected && !loadProps?.isLoading;
1856
+ const handleAddCustomItem = () => {
1857
+ if (maxSelection === 1) {
1858
+ setOpen(false);
1859
+ onChange?.([search]);
1860
+ } else {
1861
+ onChange?.([...value, search]);
1862
+ }
1863
+ resetSearch();
1864
+ };
1865
+ const handleOptionSelected = (val) => {
1866
+ if (maxSelection === 1) {
1867
+ onChange?.([val]);
1868
+ handleClose();
1869
+ } else {
1870
+ let items2 = ordered ? [...value, val] : [val, ...value];
1871
+ if (maxSelection !== "unlimited") {
1872
+ items2 = items2.slice(0, maxSelection);
1873
+ }
1874
+ onChange?.(items2);
1875
+ }
1876
+ if (inputRef.current) {
1877
+ inputRef.current.select();
1878
+ }
1879
+ };
1880
+ const totalNumItems = unselectedOptions.length + (showCustomItem ? 1 : 0);
1881
+ const handleKeyDown = (e) => {
1882
+ if (e.key === "ArrowDown") {
1883
+ e.preventDefault();
1884
+ setFocusIndex((prev) => (prev + 1) % totalNumItems);
1885
+ } else if (e.key === "ArrowUp") {
1886
+ e.preventDefault();
1887
+ setFocusIndex((prev) => Math.max(prev - 1, 0));
1888
+ } else if (e.key === "Enter") {
1889
+ e.preventDefault();
1890
+ if (focusIndex === 0 && showCustomItem) {
1891
+ handleAddCustomItem();
1892
+ } else if (totalNumItems > focusIndex) {
1893
+ const unselectedOptionsIndex = focusIndex - (showCustomItem ? 1 : 0);
1894
+ if (!unselectedOptions[unselectedOptionsIndex].disabled) {
1895
+ handleOptionSelected(unselectedOptions[unselectedOptionsIndex].value);
1896
+ }
1897
+ }
1898
+ } else if (e.key === "Tab") {
1899
+ e.preventDefault();
1900
+ setOpen(false);
1901
+ }
1902
+ };
1903
+ const handleSearchTermChange = (val) => {
1904
+ setSearch(val);
1905
+ setFocusIndex(0);
1906
+ onSearchChange?.(val);
1907
+ };
1908
+ const handleTriggerKeyDown = (e) => {
1909
+ if (!hideSearch && !e.ctrlKey && !e.metaKey && !e.altKey) {
1910
+ setOpen(true);
1911
+ onOpen?.();
1912
+ handleSearchTermChange(e.key);
1913
+ }
1914
+ };
1915
+ const valueToOptionMap = useMemo5(() => {
1916
+ const map = /* @__PURE__ */ new Map();
1917
+ items.forEach((item) => map.set(item.value, item));
1918
+ return map;
1919
+ }, [items]);
1920
+ const allValuesHaveOptions = useMemo5(
1921
+ () => value.every((val) => valueToOptionMap.has(val)) || showCustomValue,
1922
+ [value, valueToOptionMap, showCustomValue]
1923
+ );
1924
+ const triggerText = useMemo5(() => {
1925
+ if (value.length === 0) {
1926
+ return /* @__PURE__ */ jsx43("span", { className: "truncate", children: triggerPlaceholder ?? `Select ${maxSelection === 1 ? "an item..." : "items..."}` });
1927
+ }
1928
+ if (!allValuesHaveOptions) {
1929
+ return /* @__PURE__ */ jsx43("span", { className: "line-clamp-1", children: "Loading..." });
1930
+ }
1931
+ const optionMatchingFirstVal = valueToOptionMap.get(value[0]) || {
1932
+ label: value[0],
1933
+ icon: void 0
1934
+ };
1935
+ const firstValText = optionMatchingFirstVal ? optionMatchingFirstVal.label : value[0];
1936
+ const icon = value.length === 1 ? optionMatchingFirstVal?.icon : void 0;
1937
+ return /* @__PURE__ */ jsxs20(Fragment6, { children: [
1938
+ icon && /* @__PURE__ */ jsx43("span", { className: "mr-1 inline-flex items-center", children: icon }),
1939
+ /* @__PURE__ */ jsx43("span", { className: "line-clamp-1 text-left", children: `${firstValText}${value.length > 1 ? "," : ""}` }),
1940
+ value.length > 1 && /* @__PURE__ */ jsx43("span", { className: "whitespace-nowrap", children: `+${value.length - 1} more` })
1941
+ ] });
1942
+ }, [maxSelection, valueToOptionMap, triggerPlaceholder, value, allValuesHaveOptions]);
1943
+ return /* @__PURE__ */ jsx43(
1944
+ Popover,
1945
+ {
1946
+ open: open && !disabled,
1947
+ onOpenChange: (val) => {
1948
+ if (val) {
1949
+ setOpen(true);
1950
+ onOpen?.();
1951
+ } else {
1952
+ handleClose();
1953
+ }
1954
+ },
1955
+ alignContent: "start",
1956
+ disabled,
1957
+ triggerClassName: popover?.triggerClassName,
1958
+ contentClassName: popover?.contentClassName,
1959
+ container: popover?.container,
1960
+ trigger: popover?.customTrigger ?? (variant === "simple" ? /* @__PURE__ */ jsxs20(
1961
+ "div",
1962
+ {
1963
+ onKeyDown: handleTriggerKeyDown,
1964
+ className: twJoin18(
1965
+ "-mx-2 -my-1.5 flex cursor-pointer items-center justify-between gap-1.5 rounded-md px-2 py-1.5 transition-all duration-150",
1966
+ !disabled && "cursor-pointer hover:bg-gray-100"
1967
+ ),
1968
+ children: [
1969
+ /* @__PURE__ */ jsx43(
1970
+ "div",
1971
+ {
1972
+ className: twJoin18(
1973
+ "line-clamp-1 flex flex-1 items-center",
1974
+ value.length !== 0 ? "text-inherit" : "text-gray-500"
1975
+ ),
1976
+ children: triggerText
1977
+ }
1978
+ ),
1979
+ !disabled && /* @__PURE__ */ jsx43(DropdownChevron, {})
1980
+ ]
1981
+ }
1982
+ ) : /* @__PURE__ */ jsxs20("button", { onKeyDown: handleTriggerKeyDown, className: twJoin18("w-full", inputBoxStyles({ hasError, size })), children: [
1983
+ /* @__PURE__ */ jsx43(
1984
+ "span",
1985
+ {
1986
+ className: `mr-auto line-clamp-1 flex items-center space-x-1 text-left text-base ${value.length === 0 ? "text-gray-400" : "text-gray-800"}`,
1987
+ children: triggerText
1988
+ }
1989
+ ),
1990
+ /* @__PURE__ */ jsx43(DropdownChevron, {})
1991
+ ] })),
1992
+ children: /* @__PURE__ */ jsxs20("div", { className: "w-72", children: [
1993
+ (!hideSearch || allowCustomValues) && /* @__PURE__ */ jsx43("div", { children: /* @__PURE__ */ jsxs20(InputBox, { variant: "transparent", children: [
1994
+ /* @__PURE__ */ jsx43("div", { className: "w-3 text-sm text-gray-400", children: /* @__PURE__ */ jsx43(Icon, { icon: faMagnifyingGlass }) }),
1995
+ /* @__PURE__ */ jsx43(
1996
+ InputBox.Input,
1997
+ {
1998
+ ref: inputRef,
1999
+ value: search,
2000
+ onChange: (e) => handleSearchTermChange(e.target.value),
2001
+ placeholder: searchPlaceholder,
2002
+ onBlur: (e) => e.target.focus(),
2003
+ onKeyDown: handleKeyDown
2004
+ }
2005
+ )
2006
+ ] }) }),
2007
+ /* @__PURE__ */ jsxs20("ul", { className: "max-h-72 space-y-1 overflow-y-auto p-1", children: [
2008
+ !allValuesHaveOptions ? /* @__PURE__ */ jsx43(SelectListItem, { disabled: true, children: "Loading..." }) : /* @__PURE__ */ jsx43(
2009
+ SelectedItems,
2010
+ {
2011
+ value,
2012
+ onChange,
2013
+ search,
2014
+ valueToOptionMap,
2015
+ onSelectAll,
2016
+ minSelection,
2017
+ ordered,
2018
+ numValuesToShow
2019
+ }
2020
+ ),
2021
+ showCustomItem && /* @__PURE__ */ jsx43(SelectOption, { onClick: handleAddCustomItem, focused: showCustomItem && focusIndex === 0, children: /* @__PURE__ */ jsx43("span", { children: `"${search}"` }) }),
2022
+ unselectedOptions.map((item, i) => /* @__PURE__ */ jsx43(
2023
+ SelectOption,
2024
+ {
2025
+ onClick: () => handleOptionSelected(item.value),
2026
+ focused: focusIndex === (showCustomItem ? i + 1 : i),
2027
+ disabled: item.disabled,
2028
+ children: item.display ?? item.label
2029
+ },
2030
+ item.reactKey ?? item.value
2031
+ )),
2032
+ !loadProps ? (
2033
+ // no asynchronous loading
2034
+ unselectedOptions.length === 0 && (emptyState || /* @__PURE__ */ jsx43(SelectListItem, { disabled: true, children: "No results" }))
2035
+ ) : loadProps.isLoading ? /* @__PURE__ */ jsx43(SelectListItem, { disabled: true, children: "Loading..." }) : loadProps.isError ? /* @__PURE__ */ jsx43(SelectListItem, { disabled: true, children: "An error occurred" }) : unselectedOptions.length === 0 ? emptyState || /* @__PURE__ */ jsx43(SelectListItem, { disabled: true, children: "No results" }) : loadProps.canLoadMore ? /* @__PURE__ */ jsx43(
2036
+ "div",
2037
+ {
2038
+ className: "cursor-pointer px-2 py-1 text-sm font-medium text-indigo-600",
2039
+ onClick: loadProps.onLoadMore,
2040
+ children: "Load more..."
2041
+ }
2042
+ ) : null
2043
+ ] })
2044
+ ] })
2045
+ }
2046
+ );
2047
+ };
2048
+ var SelectOption = ({ children, focused, ...rest }) => /* @__PURE__ */ jsxs20(SelectListItem, { focused, ...rest, children: [
2049
+ children,
2050
+ focused && !rest.disabled && /* @__PURE__ */ jsx43("span", { className: "w-3 text-sm text-gray-500", children: /* @__PURE__ */ jsx43(Icon, { icon: faArrowTurnDown }) })
2051
+ ] });
2052
+ var SelectedItems = ({
2053
+ value = [],
2054
+ onChange,
2055
+ onSelectAll,
2056
+ minSelection,
2057
+ search,
2058
+ valueToOptionMap,
2059
+ ordered,
2060
+ numValuesToShow = DEFAULT_NUM_VALUES_TO_SHOW
2061
+ }) => {
2062
+ const [showAllValues, setShowAllValues] = useState8(false);
2063
+ const filteredSelectedValues = useMemo5(() => {
2064
+ return value.filter((v) => {
2065
+ if (!search) {
2066
+ return true;
2067
+ }
2068
+ const option = valueToOptionMap.get(v);
2069
+ if (!option) {
2070
+ return false;
2071
+ }
2072
+ return doesSelectItemMatch(option, search);
2073
+ });
2074
+ }, [value, search, valueToOptionMap]);
2075
+ const sensors = useSensors(
2076
+ useSensor(PointerSensor, {
2077
+ activationConstraint: {
2078
+ distance: 8
2079
+ }
2080
+ })
2081
+ );
2082
+ const onDragEnd = (event) => {
2083
+ const { active, over } = event;
2084
+ if (over && active.id !== over.id) {
2085
+ const newOrder = [...value];
2086
+ const activeIndex = newOrder.indexOf(active.id);
2087
+ const overIndex = newOrder.indexOf(over.id);
2088
+ newOrder.splice(activeIndex, 1);
2089
+ newOrder.splice(overIndex, 0, active.id);
2090
+ onChange?.(newOrder);
2091
+ }
2092
+ };
2093
+ return /* @__PURE__ */ jsx43(DndContext, { sensors, onDragEnd, children: /* @__PURE__ */ jsxs20(
2094
+ SortableContext,
2095
+ {
2096
+ disabled: !ordered,
2097
+ items: filteredSelectedValues.map((v) => ({ id: v, value: v })),
2098
+ strategy: verticalListSortingStrategy,
2099
+ children: [
2100
+ (filteredSelectedValues.length > numValuesToShow || onSelectAll) && /* @__PURE__ */ jsxs20("div", { className: "flex justify-between px-2 pt-1.5 pb-px text-sm", children: [
2101
+ /* @__PURE__ */ jsxs20("span", { className: "font-medium text-gray-500", children: [
2102
+ value.length,
2103
+ " selected",
2104
+ filteredSelectedValues.length < value.length ? ` (showing ${filteredSelectedValues.length})` : ""
2105
+ ] }),
2106
+ value.length > 0 ? /* @__PURE__ */ jsx43("span", { className: "cursor-pointer text-red-600 hover:underline", onClick: () => onChange?.([]), children: "Clear" }) : onSelectAll ? /* @__PURE__ */ jsx43("span", { className: "cursor-pointer text-indigo-700 hover:underline", onClick: onSelectAll, children: "Select all" }) : null
2107
+ ] }),
2108
+ filteredSelectedValues.length > 0 && /* @__PURE__ */ jsxs20(Fragment6, { children: [
2109
+ filteredSelectedValues.slice(0, showAllValues ? value.length : numValuesToShow).map((val) => {
2110
+ const item = valueToOptionMap.get(val);
2111
+ return /* @__PURE__ */ jsxs20(
2112
+ SelectListItem,
2113
+ {
2114
+ sortableId: ordered ? val : void 0,
2115
+ onClick: () => {
2116
+ const canRemove = minSelection === 0 || value.length !== 1;
2117
+ if (canRemove) {
2118
+ onChange?.(value.filter((v) => v !== val));
2119
+ }
2120
+ },
2121
+ children: [
2122
+ !item ? val : item.display ?? /* @__PURE__ */ jsxs20("div", { className: "flex items-center gap-2", children: [
2123
+ item.icon,
2124
+ /* @__PURE__ */ jsx43("span", { children: item.label })
2125
+ ] }),
2126
+ /* @__PURE__ */ jsx43("div", { className: "flex w-3 justify-center text-sm text-gray-500", children: /* @__PURE__ */ jsx43(
2127
+ Icon,
2128
+ {
2129
+ icon: minSelection === 1 ? faCheck2 : faXmark2
2130
+ }
2131
+ ) })
2132
+ ]
2133
+ },
2134
+ val
2135
+ );
2136
+ }),
2137
+ filteredSelectedValues.length > numValuesToShow && /* @__PURE__ */ jsx43(
2138
+ "div",
2139
+ {
2140
+ className: "cursor-pointer px-2 py-1 text-sm font-medium text-indigo-600",
2141
+ onClick: () => setShowAllValues((prev) => !prev),
2142
+ children: showAllValues ? "Show less" : `Show ${filteredSelectedValues.length - numValuesToShow} more selected`
2143
+ }
2144
+ )
2145
+ ] }),
2146
+ (filteredSelectedValues.length > 0 || onSelectAll) && /* @__PURE__ */ jsx43("li", { className: "py-0.5", children: /* @__PURE__ */ jsx43("hr", { className: "h-px bg-gray-200" }) })
2147
+ ]
2148
+ }
2149
+ ) });
2150
+ };
2151
+
2152
+ // src/core/select/AsyncSelect.tsx
2153
+ import { jsx as jsx44 } from "react/jsx-runtime";
2154
+ var AsyncSelect = ({
2155
+ value,
2156
+ onChange,
2157
+ allowUnselect = false,
2158
+ ...rest
2159
+ }) => {
2160
+ const multiValue = value ? [value] : [];
2161
+ return /* @__PURE__ */ jsx44(
2162
+ AsyncMultiSelect,
2163
+ {
2164
+ minSelection: allowUnselect ? 0 : 1,
2165
+ maxSelection: 1,
2166
+ value: multiValue,
2167
+ onChange: (val) => onChange?.(val[0]),
2168
+ ...rest
2169
+ }
2170
+ );
2171
+ };
2172
+
2173
+ // src/core/select/MultiSelect.tsx
2174
+ import { useMemo as useMemo6, useState as useState9 } from "react";
2175
+ import { jsx as jsx45 } from "react/jsx-runtime";
2176
+ var MultiSelect = ({
2177
+ value,
2178
+ items: options,
2179
+ onSearchChange,
2180
+ customValueToOption,
2181
+ ...rest
2182
+ }) => {
2183
+ const [query, setQuery] = useState9("");
2184
+ const optionsForValues = useMemo6(
2185
+ () => value?.map((val) => {
2186
+ const option = options.find((opt) => opt.value === val);
2187
+ if (option) return option;
2188
+ if (!customValueToOption) {
2189
+ return {
2190
+ value: val,
2191
+ label: val.toString()
2192
+ };
2193
+ }
2194
+ return customValueToOption(val);
2195
+ }) ?? [],
2196
+ [customValueToOption, options, value]
2197
+ );
2198
+ const optionsMatchingQuery = useMemo6(
2199
+ () => options.filter((option) => doesSelectItemMatch(option, query)),
2200
+ [query, options]
2201
+ );
2202
+ return /* @__PURE__ */ jsx45(
2203
+ AsyncMultiSelect,
2204
+ {
2205
+ value,
2206
+ items: [...optionsForValues, ...optionsMatchingQuery],
2207
+ onSearchChange: (q) => {
2208
+ setQuery(q);
2209
+ onSearchChange?.(q);
2210
+ },
2211
+ ...rest
2212
+ }
2213
+ );
2214
+ };
2215
+
2216
+ // src/core/select/Select.tsx
2217
+ import { jsx as jsx46 } from "react/jsx-runtime";
2218
+ function Select({ value, onChange, allowUnselect, ...rest }) {
2219
+ const multivalue = value || value === 0 ? [value] : [];
2220
+ return /* @__PURE__ */ jsx46(
2221
+ MultiSelect,
2222
+ {
2223
+ value: multivalue,
2224
+ onChange: (val) => onChange?.(val[0]),
2225
+ minSelection: allowUnselect ? 0 : 1,
2226
+ maxSelection: 1,
2227
+ ...rest
2228
+ }
2229
+ );
2230
+ }
2231
+
2232
+ // src/core/select/SelectWtihUnselect.tsx
2233
+ import { jsx as jsx47 } from "react/jsx-runtime";
2234
+ function SelectWithUnselect({
2235
+ value,
2236
+ onChange,
2237
+ ...rest
2238
+ }) {
2239
+ const multivalue = value || value === 0 ? [value] : [];
2240
+ return /* @__PURE__ */ jsx47(
2241
+ MultiSelect,
2242
+ {
2243
+ value: multivalue,
2244
+ onChange: (val) => onChange?.(val[0] ?? null),
2245
+ minSelection: 0,
2246
+ maxSelection: 1,
2247
+ ...rest
2248
+ }
2249
+ );
2250
+ }
2251
+
2252
+ // src/core/form/components/FormSelect.tsx
2253
+ import { jsx as jsx48 } from "react/jsx-runtime";
2254
+ var FormSelect = ({
2255
+ name,
2256
+ styles,
2257
+ layout,
2258
+ label,
2259
+ options,
2260
+ onChange,
2261
+ ...rest
2262
+ }) => {
2263
+ return /* @__PURE__ */ jsx48(
2264
+ ControlledFormItem,
2265
+ {
2266
+ name,
2267
+ layout,
2268
+ styles,
2269
+ label,
2270
+ options,
2271
+ render: (field) => /* @__PURE__ */ jsx48(
2272
+ Select,
2273
+ {
2274
+ ...rest,
2275
+ value: field.value,
2276
+ onChange: (value) => {
2277
+ field.onChange(value);
2278
+ onChange?.(value);
2279
+ },
2280
+ hasError: !!field.error
2281
+ }
2282
+ )
2283
+ }
2284
+ );
2285
+ };
2286
+
2287
+ // src/core/form/components/FormMultiSelect.tsx
2288
+ import { jsx as jsx49 } from "react/jsx-runtime";
2289
+ var FormMultiSelect = ({
2290
+ name,
2291
+ styles,
2292
+ layout,
2293
+ label,
2294
+ options,
2295
+ onChange,
2296
+ ...rest
2297
+ }) => {
2298
+ return /* @__PURE__ */ jsx49(
2299
+ ControlledFormItem,
2300
+ {
2301
+ name,
2302
+ layout,
2303
+ styles,
2304
+ label,
2305
+ options,
2306
+ render: (field) => /* @__PURE__ */ jsx49(
2307
+ MultiSelect,
2308
+ {
2309
+ ...rest,
2310
+ value: field.value,
2311
+ onChange: (value) => {
2312
+ field.onChange(value);
2313
+ onChange?.(value);
2314
+ },
2315
+ hasError: !!field.error
2316
+ }
2317
+ )
2318
+ }
2319
+ );
2320
+ };
2321
+
2322
+ // src/core/form/components/FormTextArea.tsx
2323
+ import { debounce } from "lodash-es";
2324
+
2325
+ // src/core/textarea/TextArea.tsx
2326
+ import { forwardRef as forwardRef14 } from "react";
2327
+ import { twMerge as twMerge6 } from "tailwind-merge";
2328
+ import { Fragment as Fragment7, jsx as jsx50, jsxs as jsxs21 } from "react/jsx-runtime";
2329
+ var TextAreaComp = forwardRef14(({ className, hasError, ...rest }, ref) => {
2330
+ const ringClassName = rest.disabled ? "focus:outline-hidden focus:ring-0" : hasError ? "focus:outline-hidden focus:ring-red-500 focus:border-red-500" : RING_COLOR_CLASSNAME;
2331
+ return /* @__PURE__ */ jsx50(
2332
+ "textarea",
2333
+ {
2334
+ ...rest,
2335
+ className: twMerge6(
2336
+ "block w-full resize-none rounded-md shadow-sm disabled:bg-gray-100",
2337
+ hasError ? "border-red-300 text-red-900 placeholder-red-300" : "border-gray-200 placeholder-gray-400 focus:border-indigo-400",
2338
+ ringClassName,
2339
+ className
2340
+ ),
2341
+ ref
2342
+ }
2343
+ );
2344
+ });
2345
+ var TextArea = forwardRef14(({ hasError, errorNode, ...rest }, ref) => /* @__PURE__ */ jsxs21(Fragment7, { children: [
2346
+ /* @__PURE__ */ jsx50(TextAreaComp, { ...rest, hasError, ref }),
2347
+ hasError && /* @__PURE__ */ jsx50(ErrorText, { className: "mt-2 text-sm", children: errorNode })
2348
+ ] }));
2349
+
2350
+ // src/core/form/components/FormTextArea.tsx
2351
+ import { jsx as jsx51 } from "react/jsx-runtime";
2352
+ var FormTextArea = ({
2353
+ name,
2354
+ styles,
2355
+ layout,
2356
+ label,
2357
+ options,
2358
+ debounce: debounceInterval,
2359
+ ...rest
2360
+ }) => /* @__PURE__ */ jsx51(
2361
+ UncontrolledField,
2362
+ {
2363
+ name,
2364
+ render: ({ error, register }) => {
2365
+ const controlFields = register();
2366
+ return /* @__PURE__ */ jsx51(
2367
+ FormItem,
2368
+ {
2369
+ layout,
2370
+ styles,
2371
+ label,
2372
+ options,
2373
+ render: /* @__PURE__ */ jsx51(
2374
+ TextArea,
2375
+ {
2376
+ ...controlFields,
2377
+ hasError: !!error || void 0,
2378
+ ...rest,
2379
+ onChange: debounceInterval ? debounce(controlFields.onChange, debounceInterval) : controlFields.onChange
2380
+ }
2381
+ ),
2382
+ error
2383
+ }
2384
+ );
2385
+ }
2386
+ }
2387
+ );
2388
+
2389
+ // src/core/form/components/FormSwitch.tsx
2390
+ import { twJoin as twJoin19 } from "tailwind-merge";
2391
+
2392
+ // src/core/switch/Switch.tsx
2393
+ import * as RadixSwitch from "@radix-ui/react-switch";
2394
+ import * as React10 from "react";
2395
+ import { jsx as jsx52 } from "react/jsx-runtime";
2396
+ var SwitchIdContext = React10.createContext(void 0);
2397
+ var useSwitchId = () => React10.useContext(SwitchIdContext);
2398
+ var SwitchControl = (props) => {
2399
+ const id = useSwitchId();
2400
+ return /* @__PURE__ */ jsx52(
2401
+ RadixSwitch.Root,
2402
+ {
2403
+ ...props,
2404
+ id,
2405
+ className: "flex h-5 w-9 shrink-0 items-center rounded-full bg-gray-200 focus:outline-hidden focus-visible:ring-2 focus-visible:ring-indigo-400 focus-visible:ring-offset-2 focus-visible:outline-hidden disabled:cursor-not-allowed disabled:bg-gray-100 data-[state=checked]:bg-indigo-700",
2406
+ children: /* @__PURE__ */ jsx52(RadixSwitch.SwitchThumb, { className: "block h-4 w-4 translate-x-0.5 rounded-full bg-white duration-100 data-disabled:shadow-none data-[state=checked]:translate-x-[18px]" })
2407
+ }
2408
+ );
2409
+ };
2410
+ var SwitchLabel = (props) => {
2411
+ const id = useSwitchId();
2412
+ return /* @__PURE__ */ jsx52("label", { ...props, htmlFor: id });
2413
+ };
2414
+ var Switch = ({ children, className, ...rest }) => {
2415
+ const autoId = React10.useId();
2416
+ if (children == null) {
2417
+ return /* @__PURE__ */ jsx52(SwitchControl, { ...rest });
2418
+ }
2419
+ return /* @__PURE__ */ jsx52(SwitchIdContext.Provider, { value: autoId, children: /* @__PURE__ */ jsx52("span", { className, children }) });
2420
+ };
2421
+ Switch.Control = SwitchControl;
2422
+ Switch.Label = SwitchLabel;
2423
+
2424
+ // src/core/form/components/FormSwitch.tsx
2425
+ import { jsx as jsx53, jsxs as jsxs22 } from "react/jsx-runtime";
2426
+ var FormSwitch = ({ name, styles, layout, label, options, onChange, ...props }) => {
2427
+ if (layout === "side-by-side") {
2428
+ return /* @__PURE__ */ jsx53(
2429
+ ControlledField,
2430
+ {
2431
+ name,
2432
+ render: (field) => /* @__PURE__ */ jsxs22("div", { className: twJoin19("flex items-start gap-x-2", styles), children: [
2433
+ /* @__PURE__ */ jsx53("div", { children: /* @__PURE__ */ jsx53(
2434
+ Switch,
2435
+ {
2436
+ ...props,
2437
+ checked: (
2438
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
2439
+ field.value
2440
+ ),
2441
+ onCheckedChange: (value) => {
2442
+ field.onChange(value);
2443
+ onChange?.(value);
2444
+ }
2445
+ }
2446
+ ) }),
2447
+ /* @__PURE__ */ jsxs22("div", { className: "pt-1", children: [
2448
+ /* @__PURE__ */ jsx53(FieldLabelWithTooltip, { label, options }),
2449
+ /* @__PURE__ */ jsx53(FieldDescription, { styles: "pt-0.5", children: options?.description }),
2450
+ /* @__PURE__ */ jsx53(FieldErrorMessage, { error: field.error }),
2451
+ options?.bottomSlot
2452
+ ] })
2453
+ ] })
2454
+ }
2455
+ );
2456
+ }
2457
+ return /* @__PURE__ */ jsx53(
2458
+ ControlledFormItem,
2459
+ {
2460
+ name,
2461
+ layout,
2462
+ styles,
2463
+ label,
2464
+ options,
2465
+ render: (field) => /* @__PURE__ */ jsx53(Switch, { ...props, checked: field.value, onCheckedChange: field.onChange })
2466
+ }
2467
+ );
2468
+ };
2469
+
2470
+ // src/core/radio-button-group/RadioButtonItem.tsx
2471
+ import { twJoin as twJoin20 } from "tailwind-merge";
2472
+ import { Fragment as Fragment8, jsx as jsx54, jsxs as jsxs23 } from "react/jsx-runtime";
2473
+ var RadioButtonItem = ({
2474
+ value,
2475
+ displayValue,
2476
+ description,
2477
+ expandedContents,
2478
+ expandedContentsStyle,
2479
+ disabled,
2480
+ isChecked,
2481
+ onSelect,
2482
+ asCard = false
2483
+ }) => /* @__PURE__ */ jsxs23(
2484
+ "div",
2485
+ {
2486
+ className: twJoin20(
2487
+ "flex flex-col gap-2",
2488
+ asCard && "rounded-md border px-3 py-2",
2489
+ asCard && !isChecked && "border-gray-200",
2490
+ asCard && isChecked && "border-indigo-500"
2491
+ ),
2492
+ children: [
2493
+ /* @__PURE__ */ jsxs23(
2494
+ "div",
2495
+ {
2496
+ className: twJoin20(
2497
+ "relative flex gap-2",
2498
+ disabled && "cursor-not-allowed opacity-30 *:cursor-not-allowed",
2499
+ expandedContentsStyle === "inline" ? "items-center" : "items-start"
2500
+ ),
2501
+ children: [
2502
+ /* @__PURE__ */ jsx54(
2503
+ "input",
2504
+ {
2505
+ onChange: (evt) => onSelect?.(evt.target.value),
2506
+ id: value,
2507
+ value,
2508
+ checked: isChecked,
2509
+ disabled,
2510
+ type: "radio",
2511
+ className: "mt-px border-gray-200 p-2 text-indigo-700 ring-0 ring-indigo-700"
2512
+ }
2513
+ ),
2514
+ expandedContentsStyle === "inline" ? /* @__PURE__ */ jsxs23("label", { htmlFor: value, className: "flex w-full flex-row gap-2.5", children: [
2515
+ /* @__PURE__ */ jsxs23("div", { className: "flex w-9/12 items-center gap-2", children: [
2516
+ /* @__PURE__ */ jsx54("div", { className: "font-medium", children: displayValue }),
2517
+ description && /* @__PURE__ */ jsx54("div", { id: `${value}-description`, className: "text-gray-500", children: description })
2518
+ ] }),
2519
+ /* @__PURE__ */ jsx54("div", { className: "flex w-3/12 items-center", children: expandedContents?.(!isChecked || !!disabled) })
2520
+ ] }) : /* @__PURE__ */ jsx54("label", { htmlFor: value, className: "flex flex-col gap-2", children: /* @__PURE__ */ jsx54("div", { className: "font-medium", children: displayValue }) })
2521
+ ]
2522
+ }
2523
+ ),
2524
+ expandedContentsStyle !== "inline" && /* @__PURE__ */ jsxs23(Fragment8, { children: [
2525
+ description && /* @__PURE__ */ jsx54("div", { id: `${value}-description`, className: "text-gray-500", children: description }),
2526
+ expandedContents?.(!isChecked || !!disabled)
2527
+ ] })
2528
+ ]
2529
+ }
2530
+ );
2531
+
2532
+ // src/core/radio-button-group/RadioButtonGroup.tsx
2533
+ import { jsx as jsx55 } from "react/jsx-runtime";
2534
+ var RadioButtonGroup = ({ className, items, onChange, value, asCards = false }) => /* @__PURE__ */ jsx55("fieldset", { className, children: /* @__PURE__ */ jsx55("div", { className: "space-y-3", children: items.map(
2535
+ ({ value: itemValue, displayValue, description, expandedContents, expandedContentsStyle, disabled }, index) => /* @__PURE__ */ jsx55(
2536
+ RadioButtonItem,
2537
+ {
2538
+ disabled,
2539
+ onSelect: onChange,
2540
+ isChecked: value === itemValue,
2541
+ value: itemValue,
2542
+ displayValue,
2543
+ description,
2544
+ expandedContents,
2545
+ expandedContentsStyle,
2546
+ asCard: asCards
2547
+ },
2548
+ index
2549
+ )
2550
+ ) }) });
2551
+
2552
+ // src/core/form/components/FormRadioButtonGroup.tsx
2553
+ import { Fragment as Fragment9, jsx as jsx56, jsxs as jsxs24 } from "react/jsx-runtime";
2554
+ var FormRadioButtonGroup = ({
2555
+ name,
2556
+ items,
2557
+ onChange,
2558
+ asCards = false,
2559
+ className
2560
+ }) => /* @__PURE__ */ jsx56(
2561
+ ControlledField,
2562
+ {
2563
+ name,
2564
+ render: (field) => /* @__PURE__ */ jsxs24(Fragment9, { children: [
2565
+ /* @__PURE__ */ jsx56(
2566
+ RadioButtonGroup,
2567
+ {
2568
+ ...field,
2569
+ className,
2570
+ items,
2571
+ onChange: (newValue) => {
2572
+ field.onChange(newValue);
2573
+ onChange?.(newValue);
2574
+ },
2575
+ asCards
2576
+ }
2577
+ ),
2578
+ /* @__PURE__ */ jsx56(FieldErrorMessage, { error: field.error })
2579
+ ] })
2580
+ }
2581
+ );
2582
+
2583
+ // src/core/form/components/FormDatePicker.tsx
2584
+ import { useCallback as useCallback7 } from "react";
2585
+ import { twJoin as twJoin21 } from "tailwind-merge";
2586
+ import { jsx as jsx57 } from "react/jsx-runtime";
2587
+ var FormDatePicker = ({
2588
+ name,
2589
+ styles,
2590
+ layout,
2591
+ label,
2592
+ onChange,
2593
+ options,
2594
+ containerRef,
2595
+ disabled,
2596
+ ...rest
2597
+ }) => {
2598
+ const {
2599
+ onChange: onChangeInternal,
2600
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
2601
+ value,
2602
+ error
2603
+ } = useControlledFormField({ name });
2604
+ const handleChange = useCallback7(
2605
+ (newValue) => {
2606
+ onChange?.(newValue ?? null);
2607
+ onChangeInternal(newValue ?? null);
2608
+ },
2609
+ [onChangeInternal, onChange]
2610
+ );
2611
+ return /* @__PURE__ */ jsx57(
2612
+ FormItem,
2613
+ {
2614
+ layout,
2615
+ styles,
2616
+ label,
2617
+ options,
2618
+ ref: containerRef,
2619
+ render: /* @__PURE__ */ jsx57("div", { className: twJoin21(disabled && "text-gray-500"), children: /* @__PURE__ */ jsx57(
2620
+ DatePicker,
2621
+ {
2622
+ ...rest,
2623
+ disabled,
2624
+ value: (
2625
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
2626
+ value
2627
+ ),
2628
+ onChange: handleChange,
2629
+ hasError: !!error
2630
+ }
2631
+ ) }),
2632
+ error
2633
+ }
2634
+ );
2635
+ };
2636
+
2637
+ // src/core/form/components/schemas/currency-schemas.ts
2638
+ import { z } from "zod";
2639
+ var CURRENCY_REGEX = /^-?(?:\d{1,3}(?:,\d{3})*|\d+|\.\d{1,2})(?:\.\d{1,2})?$/;
2640
+ var DOLLARS_STR_ERROR_MESSAGE = "Must use dollars and cents or whole numbers.";
2641
+ var dollarsStrSchema = z.string().regex(CURRENCY_REGEX, DOLLARS_STR_ERROR_MESSAGE);
2642
+ var requiredDollarsStrSchema = z.string().trim().nonempty("Required").regex(CURRENCY_REGEX, DOLLARS_STR_ERROR_MESSAGE);
2643
+ var requiredDollarsStrSchemaWithCustomMessage = (requiredError, invalidTypeError) => z.string().trim().nonempty(requiredError).regex(CURRENCY_REGEX, invalidTypeError);
2644
+ var requiredNonZeroDollarsStrSchema = requiredDollarsStrSchema.refine(
2645
+ (value) => parseFloat(value) !== 0,
2646
+ "Amount cannot be $0.00"
2647
+ );
2648
+ var requiredPositiveDollarsStrSchema = requiredDollarsStrSchema.refine(
2649
+ (value) => parseFloat(value) > 0,
2650
+ "Amount must be greater than $0.00"
2651
+ );
2652
+ var requiredPositiveOrZeroDollarsStrSchema = requiredDollarsStrSchema.refine(
2653
+ (value) => parseFloat(value) >= 0,
2654
+ "Amount must be greater than or equal to $0.00"
2655
+ );
2656
+
2657
+ // src/core/form/components/schemas/form-schemas.ts
2658
+ import { z as z3 } from "zod";
2659
+
2660
+ // src/core/form/components/schemas/helper-schemas.ts
2661
+ import { z as z2 } from "zod";
2662
+ var asOptional = (schema) => z2.union([
2663
+ // order is important: the empty-like literals must precede actual schema
2664
+ z2.literal(null).transform(() => void 0),
2665
+ z2.literal("").transform(() => void 0),
2666
+ z2.string().trim().transform((val) => val === "" ? void 0 : val).pipe(z2.undefined()),
2667
+ schema.optional()
2668
+ ]);
2669
+ var asNullish = (schema) => z2.union([
2670
+ // order is important: the empty-like literals must precede actual schema
2671
+ z2.literal(null).transform(() => void 0),
2672
+ z2.literal("").transform(() => void 0),
2673
+ z2.string().trim().transform((val) => val === "" ? void 0 : val).pipe(z2.undefined()),
2674
+ schema.nullish()
2675
+ ]);
2676
+ var asNumericStr = (schema, message = "Only numbers allowed") => schema.regex(/^\d+$/i, message);
2677
+ var asRequiredCustom = (message = "Required") => {
2678
+ return z2.custom((value) => {
2679
+ if (value == null || typeof value !== "object") {
2680
+ return !!value;
2681
+ }
2682
+ if (Array.isArray(value)) {
2683
+ return value.length > 0;
2684
+ }
2685
+ return Object.keys(value).length > 0;
2686
+ }, message);
2687
+ };
2688
+
2689
+ // src/core/form/components/schemas/form-schemas.ts
2690
+ var npiSchema = asNumericStr(z3.string().trim().nonempty("Required").length(10, "Must have 10 numbers"));
2691
+ var npiSchemaOptional = asOptional(asNumericStr(z3.string().trim()).length(10, "Must have 10 numbers"));
2692
+ var taxonomyCodeSchema = z3.string().trim().nonempty("Must contain characters, not just whitespace").length(10, "Must have 10 characters");
2693
+ var TAX_ID_REGEX = /^(([0-9]{9})|([0-9]{3}-[0-9]{2}-[0-9]{4})|([0-9]{2}-[0-9]{7}))$/i;
2694
+ var taxIdSchema = z3.string().trim().nonempty("Required").regex(TAX_ID_REGEX, "Must have 9 numbers formatted: XXXXXXXXX or XXX-XX-XXXX or XX-XXXXXXX");
2695
+
2696
+ // src/core/form/components/schemas/selected-amount-schema.ts
2697
+ import { z as z4 } from "zod";
2698
+ var selectedAmountSchema = z4.object({
2699
+ selected: asOptional(z4.boolean()),
2700
+ amountStr: asOptional(dollarsStrSchema)
2701
+ });
2702
+
2703
+ // src/core/form/components/schemas/utils.ts
2704
+ import { z as z5 } from "zod";
2705
+ var buildZodIssue = (path, message) => ({
2706
+ path: Array.isArray(path) ? path : [path],
2707
+ message,
2708
+ code: z5.ZodIssueCode.custom
2709
+ });
2710
+
2711
+ // src/core/drawer/Drawer.tsx
2712
+ import { forwardRef as forwardRef15, Suspense, useEffect as useEffect6, useRef as useRef6 } from "react";
2713
+ import { twJoin as twJoin23 } from "tailwind-merge";
2714
+
2715
+ // src/core/loaders/Spinner.tsx
2716
+ import { faSpinner } from "@fortawesome/free-solid-svg-icons";
2717
+ import { FontAwesomeIcon as FontAwesomeIcon2 } from "@fortawesome/react-fontawesome";
2718
+ import { twJoin as twJoin22 } from "tailwind-merge";
2719
+ import { jsx as jsx58 } from "react/jsx-runtime";
2720
+ var Spinner = ({ className, ...props }) => /* @__PURE__ */ jsx58(
2721
+ FontAwesomeIcon2,
2722
+ {
2723
+ ...props,
2724
+ className: twJoin22("animate-spin text-gray-400", className),
2725
+ icon: faSpinner
2726
+ }
2727
+ );
2728
+
2729
+ // src/core/loaders/LoadingState.tsx
2730
+ import { jsx as jsx59 } from "react/jsx-runtime";
2731
+ var LoadingStateTemplate = ({ children }) => /* @__PURE__ */ jsx59("div", { className: "inset-0 z-10 flex h-full items-center justify-center", children });
2732
+ var LoadingState = ({ size = "2x" }) => /* @__PURE__ */ jsx59(LoadingStateTemplate, { children: /* @__PURE__ */ jsx59(Spinner, { size }) });
2733
+
2734
+ // src/core/loaders/LoadingBar.tsx
2735
+ import { twMerge as twMerge7 } from "tailwind-merge";
2736
+ import { jsx as jsx60 } from "react/jsx-runtime";
2737
+ var LoadingBar = ({ className }) => /* @__PURE__ */ jsx60("div", { className: twMerge7("relative h-3 w-full overflow-hidden rounded-full bg-gray-100", className), children: /* @__PURE__ */ jsx60(
2738
+ "div",
2739
+ {
2740
+ className: "absolute inset-0 w-full animate-loading-slide bg-gradient-to-r from-transparent via-indigo-400/60 to-transparent",
2741
+ style: { width: "50%" }
2742
+ }
2743
+ ) });
2744
+
2745
+ // src/core/drawer/drawerState.ts
2746
+ import { createContext as createContext5, useContext as useContext5 } from "react";
2747
+ var DrawerStateContext = createContext5({
2748
+ isOpen: false,
2749
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
2750
+ onClose: () => {
2751
+ }
2752
+ });
2753
+ var useDrawer = () => {
2754
+ const context = useContext5(DrawerStateContext);
2755
+ if (context === void 0) {
2756
+ throw new Error("useDrawer must be used within a DrawerStateContext");
2757
+ }
2758
+ return context;
2759
+ };
2760
+
2761
+ // src/core/drawer/useDrawerResize.ts
2762
+ import { useCallback as useCallback8, useEffect as useEffect5, useRef as useRef5 } from "react";
2763
+ var MIN_LEFT_SPACE = 240;
2764
+ var MIN_WIDTH_PCT = 0.5;
2765
+ var MIN_WIDTH_PX = 500;
2766
+ var constraintPct = (val) => Math.min(1, Math.max(0, val));
2767
+ var localStoragePersist = (key) => ({
2768
+ load: () => {
2769
+ try {
2770
+ const val = localStorage.getItem(key);
2771
+ if (val && !Number.isNaN(Number(val))) {
2772
+ return constraintPct(Number(val));
2773
+ }
2774
+ return void 0;
2775
+ } catch {
2776
+ return void 0;
2777
+ }
2778
+ },
2779
+ save: (size) => {
2780
+ try {
2781
+ localStorage.setItem(key, constraintPct(size).toString());
2782
+ } catch {
2783
+ }
2784
+ }
2785
+ });
2786
+ var computeWidth = (pct) => window.innerWidth * pct;
2787
+ var computePct = (widthPx) => widthPx / window.innerWidth;
2788
+ var constrainedWidth = (width) => {
2789
+ const minWidth = Math.max(window.innerWidth * MIN_WIDTH_PCT, MIN_WIDTH_PX);
2790
+ const maxWidth = window.innerWidth - MIN_LEFT_SPACE;
2791
+ return Math.min(Math.max(width, minWidth), maxWidth);
2792
+ };
2793
+ var useDrawerResize = ({ slider, drawer, isOpen, defaultSizePct, persistWidth }) => {
2794
+ const widthPx = useRef5(computeWidth(defaultSizePct));
2795
+ const toggleOpen = useCallback8(
2796
+ (open) => {
2797
+ if (slider.current && drawer.current) {
2798
+ drawer.current.style.transition = `right 200ms ease-out, opacity 200ms`;
2799
+ slider.current.style.right = open ? `${widthPx.current}px` : "0";
2800
+ drawer.current.style.right = open ? "0" : `-200px`;
2801
+ drawer.current.style.opacity = open ? "1" : "0";
2802
+ drawer.current.style.pointerEvents = open ? "auto" : "none";
2803
+ }
2804
+ },
2805
+ [drawer, slider]
2806
+ );
2807
+ const setWidth = useCallback8(
2808
+ (width) => {
2809
+ widthPx.current = width;
2810
+ if (slider.current && drawer.current) {
2811
+ drawer.current.style.transition = "none";
2812
+ slider.current.style.right = `${width}px`;
2813
+ drawer.current.style.width = `${width}px`;
2814
+ }
2815
+ if (width !== 0) {
2816
+ persistWidth?.save?.(computePct(width));
2817
+ }
2818
+ },
2819
+ [drawer, persistWidth, slider]
2820
+ );
2821
+ useEffect5(() => {
2822
+ if (slider.current) {
2823
+ const onPointerDown = (e) => {
2824
+ document.body.style.userSelect = "none";
2825
+ const startX = e.clientX;
2826
+ const startWidth = widthPx.current;
2827
+ const onPointerMove = (evt) => {
2828
+ const newWidth = startWidth + (startX - evt.clientX);
2829
+ setWidth(constrainedWidth(newWidth));
2830
+ };
2831
+ const onPointerUp = () => {
2832
+ document.body.style.userSelect = "auto";
2833
+ window.removeEventListener("pointermove", onPointerMove);
2834
+ window.removeEventListener("pointerup", onPointerUp);
2835
+ };
2836
+ window.addEventListener("pointermove", onPointerMove);
2837
+ window.addEventListener("pointerup", onPointerUp);
2838
+ };
2839
+ const sliderNode = slider.current;
2840
+ sliderNode.addEventListener("pointerdown", onPointerDown);
2841
+ return () => {
2842
+ sliderNode.removeEventListener("pointerdown", onPointerDown);
2843
+ };
2844
+ }
2845
+ }, [setWidth, slider]);
2846
+ const loadWidth = useCallback8(() => {
2847
+ if (!isOpen) {
2848
+ toggleOpen(false);
2849
+ } else {
2850
+ const savedWidthPct = persistWidth?.load?.();
2851
+ const width = savedWidthPct ? constrainedWidth(computeWidth(savedWidthPct)) : computeWidth(defaultSizePct);
2852
+ setWidth(width);
2853
+ toggleOpen(true);
2854
+ }
2855
+ }, [defaultSizePct, isOpen, toggleOpen, persistWidth, setWidth]);
2856
+ useEffect5(() => {
2857
+ if (slider.current && drawer.current) {
2858
+ loadWidth();
2859
+ }
2860
+ }, [slider, drawer, loadWidth]);
2861
+ useEffect5(() => {
2862
+ window.addEventListener("resize", loadWidth);
2863
+ return () => window.removeEventListener("resize", loadWidth);
2864
+ }, [loadWidth]);
2865
+ };
2866
+
2867
+ // src/core/drawer/Drawer.tsx
2868
+ import { jsx as jsx61, jsxs as jsxs25 } from "react/jsx-runtime";
2869
+ var useKeypress = (key, action) => {
2870
+ useEffect6(() => {
2871
+ const onKeyup = (e) => {
2872
+ if (e.key === key) action();
2873
+ };
2874
+ document.addEventListener("keyup", onKeyup);
2875
+ return () => document.removeEventListener("keyup", onKeyup);
2876
+ }, [action, key]);
2877
+ };
2878
+ var drawerSizes = {
2879
+ sm: 1 / 2,
2880
+ md: 3 / 4,
2881
+ lg: 5 / 6
2882
+ };
2883
+ var Drawer = forwardRef15(
2884
+ ({ isOpen, onClose, onClickOutside, blurredOverlay, children, width = "md", persistWidth }, ref) => {
2885
+ const slider = useRef6(null);
2886
+ const drawer = useRef6(null);
2887
+ useDrawerResize({
2888
+ slider,
2889
+ drawer,
2890
+ isOpen,
2891
+ defaultSizePct: drawerSizes[width],
2892
+ persistWidth
2893
+ });
2894
+ useKeypress("Escape", () => {
2895
+ onClose?.();
2896
+ });
2897
+ return /* @__PURE__ */ jsxs25(
2898
+ DrawerStateContext.Provider,
2899
+ {
2900
+ value: {
2901
+ isOpen,
2902
+ onClose: () => onClose?.()
2903
+ },
2904
+ children: [
2905
+ /* @__PURE__ */ jsx61(
2906
+ "div",
2907
+ {
2908
+ className: twJoin23(
2909
+ "absolute inset-0 z-30 transition-all",
2910
+ isOpen && blurredOverlay && "bg-gray-500/10 backdrop-blur-sm",
2911
+ // If the drawer is open, and the blurredOverlay prop is given, stop the user from clicking through the overlay
2912
+ isOpen && blurredOverlay ? "pointer-events-auto" : "pointer-events-none"
2913
+ ),
2914
+ onClick: onClickOutside
2915
+ }
2916
+ ),
2917
+ /* @__PURE__ */ jsx61(
2918
+ "div",
2919
+ {
2920
+ ref: slider,
2921
+ className: twJoin23(
2922
+ "group absolute top-0 bottom-0 z-50 h-screen w-4 translate-x-1/2 cursor-col-resize",
2923
+ isOpen ? "block" : "hidden"
2924
+ ),
2925
+ children: /* @__PURE__ */ jsx61("div", { className: "absolute top-0 right-1.5 bottom-0 left-1.5 bg-indigo-700 opacity-0 transition-opacity group-hover:opacity-100" })
2926
+ }
2927
+ ),
2928
+ /* @__PURE__ */ jsx61(
2929
+ "div",
2930
+ {
2931
+ className: "absolute top-0 right-0 bottom-0 z-drawer flex flex-col overflow-y-hidden bg-gray-50 shadow",
2932
+ ref: drawer,
2933
+ children: /* @__PURE__ */ jsx61(
2934
+ "div",
2935
+ {
2936
+ ref,
2937
+ className: twJoin23(
2938
+ "relative flex w-full flex-1 flex-col overflow-hidden bg-white transition-all delay-100 duration-100 ease-in-out",
2939
+ isOpen ? "opacity-100" : "opacity-0"
2940
+ ),
2941
+ children: isOpen ? /* @__PURE__ */ jsx61(Suspense, { fallback: /* @__PURE__ */ jsx61(LoadingState, {}), children }) : void 0
2942
+ }
2943
+ )
2944
+ }
2945
+ )
2946
+ ]
2947
+ }
2948
+ );
2949
+ }
2950
+ );
2951
+
2952
+ // src/core/drawer/DrawerHeader.tsx
2953
+ import { faBookmark, faChevronDown as faChevronDown4, faChevronUp, faXmark as faXmark3 } from "@fortawesome/free-solid-svg-icons";
2954
+ import { twJoin as twJoin27 } from "tailwind-merge";
2955
+
2956
+ // src/core/text/Text.tsx
2957
+ import { twJoin as twJoin24 } from "tailwind-merge";
2958
+ import { jsx as jsx62 } from "react/jsx-runtime";
2959
+ var VARIANT_STYLES = {
2960
+ "marketing-headline": "text-marketing-headline",
2961
+ "headline-1": "text-headline-1",
2962
+ "headline-2": "text-headline-2",
2963
+ "headline-3": "text-headline-3",
2964
+ "headline-4": "text-headline-4",
2965
+ "title-1": "text-title-1",
2966
+ "title-2": "text-title-2",
2967
+ "title-3": "text-title-3",
2968
+ "body-1": "text-body-1",
2969
+ "body-2": "text-body-2",
2970
+ label: "text-label",
2971
+ footnote: "text-footnote",
2972
+ smallcaps: "text-smallcaps"
2973
+ };
2974
+ var Text = ({ as, variant = "body-1", children, className, ...props }) => {
2975
+ const Tag2 = as ?? "p";
2976
+ return /* @__PURE__ */ jsx62(Tag2, { ...props, className: twJoin24(VARIANT_STYLES[variant], className), children });
2977
+ };
2978
+
2979
+ // src/core/skeleton/Skeleton.tsx
2980
+ import { twMerge as twMerge8 } from "tailwind-merge";
2981
+ import { jsx as jsx63 } from "react/jsx-runtime";
2982
+ var Skeleton = ({ className }) => /* @__PURE__ */ jsx63("div", { className: twMerge8("animate-skeleton-pulse rounded-lg bg-gray-200", className) });
2983
+
2984
+ // src/core/skeleton/TabsSkeleton/TabsSkeleton.tsx
2985
+ import { twMerge as twMerge9 } from "tailwind-merge";
2986
+ import { jsx as jsx64 } from "react/jsx-runtime";
2987
+ var TabsSkeleton = ({ numTabs = 3, className, tabClassName = "h-8 w-32" }) => {
2988
+ return /* @__PURE__ */ jsx64("div", { className: twMerge9("flex gap-4", className), children: Array.from({ length: numTabs }).map((_, index) => /* @__PURE__ */ jsx64(Skeleton, { className: tabClassName }, index)) });
2989
+ };
2990
+
2991
+ // src/core/skeleton/TableSkeleton/TableSkeleton.tsx
2992
+ import { twJoin as twJoin25 } from "tailwind-merge";
2993
+ import { jsx as jsx65 } from "react/jsx-runtime";
2994
+ var TableSkeleton = ({
2995
+ numTableCols = 4,
2996
+ numTableRows = 3,
2997
+ className,
2998
+ rowHeight,
2999
+ hasBorder = false
3000
+ }) => {
3001
+ return /* @__PURE__ */ jsx65("table", { className: twJoin25("flex w-full flex-col gap-4", className), children: /* @__PURE__ */ jsx65("tbody", { className: twJoin25("flex flex-col", rowHeight === void 0 && "gap-4"), children: Array.from({ length: numTableRows }).map((_, index) => /* @__PURE__ */ jsx65(
3002
+ "tr",
3003
+ {
3004
+ className: twJoin25("flex gap-4", hasBorder && "px-2 not-last:border-b"),
3005
+ style: rowHeight ? { height: rowHeight } : void 0,
3006
+ children: Array.from({ length: numTableCols }).map((_2, index2) => {
3007
+ return /* @__PURE__ */ jsx65("td", { className: "flex grow items-center px-1", children: /* @__PURE__ */ jsx65(Skeleton, { className: twJoin25("w-full", rowHeight ? "h-3" : "h-6") }, index2) }, index2);
3008
+ })
3009
+ },
3010
+ index
3011
+ )) }) });
3012
+ };
3013
+
3014
+ // src/core/skeleton/TableSkeleton/TableCheckboxSkeleton.tsx
3015
+ import { twJoin as twJoin26 } from "tailwind-merge";
3016
+ import { jsx as jsx66 } from "react/jsx-runtime";
3017
+ var TableCheckboxSkeleton = ({
3018
+ numTableRows = 3,
3019
+ className,
3020
+ rowHeight,
3021
+ hasBorder = false
3022
+ }) => {
3023
+ return /* @__PURE__ */ jsx66("table", { className: twJoin26("flex w-full flex-col gap-4", className), children: /* @__PURE__ */ jsx66("tbody", { className: twJoin26("flex flex-col", rowHeight === void 0 && "gap-4"), children: Array.from({ length: numTableRows }).map((_, index) => /* @__PURE__ */ jsx66(
3024
+ "tr",
3025
+ {
3026
+ className: twJoin26("flex gap-4", hasBorder && "px-2 not-last:border-b"),
3027
+ style: rowHeight ? { height: rowHeight } : void 0,
3028
+ children: /* @__PURE__ */ jsx66("td", { className: "flex grow items-center px-1", children: /* @__PURE__ */ jsx66(Skeleton, { className: twJoin26("w-full, rounded-none", rowHeight ? "h-3" : "h-6") }, index) }, index)
3029
+ },
3030
+ index
3031
+ )) }) });
3032
+ };
3033
+
3034
+ // src/core/drawer/DrawerHeader.tsx
3035
+ import { Fragment as Fragment10, jsx as jsx67, jsxs as jsxs26 } from "react/jsx-runtime";
3036
+ var DrawerHeader = ({
3037
+ resource,
3038
+ pagination,
3039
+ title,
3040
+ subtitle,
3041
+ actions,
3042
+ closeAction,
3043
+ label
3044
+ }) => {
3045
+ const { onClose } = useDrawer();
3046
+ return /* @__PURE__ */ jsxs26("div", { className: "z-1 flex w-full flex-col items-stretch shadow", children: [
3047
+ /* @__PURE__ */ jsxs26("div", { className: "flex justify-between px-8 py-1 shadow-sm", children: [
3048
+ /* @__PURE__ */ jsx67("div", { className: "flex items-center gap-1.5 text-base text-gray-500", children: resource && /* @__PURE__ */ jsxs26(Fragment10, { children: [
3049
+ /* @__PURE__ */ jsx67(Icon, { icon: resource.icon || faBookmark }),
3050
+ /* @__PURE__ */ jsx67("div", { children: resource.name })
3051
+ ] }) }),
3052
+ /* @__PURE__ */ jsxs26("div", { className: "flex items-center gap-2", children: [
3053
+ pagination && /* @__PURE__ */ jsxs26("div", { className: "flex gap-1", children: [
3054
+ pagination.extra,
3055
+ /* @__PURE__ */ jsx67(Button, { size: "sm", onClick: pagination.onPrevious, disabled: !pagination.hasPrevious, children: /* @__PURE__ */ jsx67(Icon, { icon: faChevronUp }) }),
3056
+ /* @__PURE__ */ jsx67(Button, { size: "sm", onClick: pagination.onNext, disabled: !pagination.hasNext, children: /* @__PURE__ */ jsx67(Icon, { icon: faChevronDown4 }) })
3057
+ ] }),
3058
+ /* @__PURE__ */ jsx67("div", { "data-testid": "drawer-close", children: closeAction ? closeAction : /* @__PURE__ */ jsx67(Button, { size: "xs", variant: "transparent", onClick: onClose, children: /* @__PURE__ */ jsx67("span", { className: "text-xl text-gray-500", children: /* @__PURE__ */ jsx67(Icon, { icon: faXmark3 }) }) }) })
3059
+ ] })
3060
+ ] }),
3061
+ /* @__PURE__ */ jsxs26("div", { className: "flex items-center gap-2 px-8 py-2", children: [
3062
+ /* @__PURE__ */ jsxs26("div", { className: "flex min-w-0 shrink grow flex-col", children: [
3063
+ /* @__PURE__ */ jsx67(Text, { variant: "title-1", className: twJoin27(typeof title === "string" && "truncate"), children: title }),
3064
+ subtitle && /* @__PURE__ */ jsx67("div", { className: "text-base font-light", children: subtitle })
3065
+ ] }),
3066
+ label && /* @__PURE__ */ jsx67("div", { className: "flex items-center gap-2", children: label }),
3067
+ /* @__PURE__ */ jsx67("div", { className: "flex shrink-0 items-center gap-2", children: actions })
3068
+ ] })
3069
+ ] });
3070
+ };
3071
+ var DrawerHeaderSkeleton = () => /* @__PURE__ */ jsxs26("div", { className: "space-y-2 px-8 py-2", children: [
3072
+ /* @__PURE__ */ jsxs26("div", { className: "flex justify-between", children: [
3073
+ /* @__PURE__ */ jsx67(Skeleton, { className: "h-6 w-36" }),
3074
+ /* @__PURE__ */ jsx67(Skeleton, { className: "h-6 w-16" })
3075
+ ] }),
3076
+ /* @__PURE__ */ jsx67(Skeleton, { className: "h-8 w-28" })
3077
+ ] });
3078
+
3079
+ // src/core/empty-state/EmptyState.tsx
3080
+ import { faCircle as faCircle2 } from "@fortawesome/free-solid-svg-icons";
3081
+ import { FontAwesomeIcon as FontAwesomeIcon3 } from "@fortawesome/react-fontawesome";
3082
+ import { forwardRef as forwardRef16 } from "react";
3083
+ import { jsx as jsx68, jsxs as jsxs27 } from "react/jsx-runtime";
3084
+ var EmptyState = forwardRef16(
3085
+ ({ icon = faCircle2, title, description }, ref) => /* @__PURE__ */ jsxs27("div", { className: "flex flex-col items-center justify-center gap-3 p-4", ref, children: [
3086
+ /* @__PURE__ */ jsx68(FontAwesomeIcon3, { className: "text-gray-500 ring-transparent", icon, size: "2x" }),
3087
+ /* @__PURE__ */ jsxs27("div", { className: "flex max-w-prose flex-col text-center", children: [
3088
+ title && /* @__PURE__ */ jsx68("h2", { className: "text-sm leading-6 font-medium text-gray-500", children: title }),
3089
+ description && /* @__PURE__ */ jsx68("p", { className: "text-xs leading-5 font-normal text-gray-500", children: description })
3090
+ ] })
3091
+ ] })
3092
+ );
3093
+
3094
+ // src/core/header-tile/HeaderTile.tsx
3095
+ import { twJoin as twJoin28 } from "tailwind-merge";
3096
+ import { jsx as jsx69, jsxs as jsxs28 } from "react/jsx-runtime";
3097
+ var HeaderTileSimple = ({ title, content, className }) => /* @__PURE__ */ jsxs28(
3098
+ "div",
3099
+ {
3100
+ className: twJoin28(
3101
+ "flex min-h-18.5 flex-col items-start justify-between gap-2 rounded-md border border-gray-200 px-3 py-1.5",
3102
+ className
3103
+ ),
3104
+ children: [
3105
+ /* @__PURE__ */ jsx69("p", { className: "max-w-35 text-base text-gray-900", children: title }),
3106
+ /* @__PURE__ */ jsx69(Text, { children: content })
3107
+ ]
3108
+ }
3109
+ );
3110
+ var HeaderTileWithPopover = ({
3111
+ title,
3112
+ content,
3113
+ popover,
3114
+ className
3115
+ }) => /* @__PURE__ */ jsxs28(Popover.Root, { children: [
3116
+ /* @__PURE__ */ jsx69(Popover.Trigger, { className: twJoin28("flex h-auto! min-h-18.5 justify-start py-1.5", className), children: /* @__PURE__ */ jsxs28("span", { className: "flex flex-col items-start justify-between gap-2", children: [
3117
+ /* @__PURE__ */ jsx69("span", { className: "text-base text-gray-900", children: title }),
3118
+ /* @__PURE__ */ jsx69("span", { children: content })
3119
+ ] }) }),
3120
+ popover && /* @__PURE__ */ jsx69(Popover.Body, { contentClassName: "max-w-150 min-w-60 p-3", children: popover })
3121
+ ] });
3122
+ var HeaderTile = (props) => {
3123
+ if (props.popover) {
3124
+ return /* @__PURE__ */ jsx69(HeaderTileWithPopover, { ...props });
3125
+ }
3126
+ return /* @__PURE__ */ jsx69(HeaderTileSimple, { ...props });
3127
+ };
3128
+
3129
+ // src/core/label/Label.tsx
3130
+ import * as React11 from "react";
3131
+
3132
+ // src/core/label/labelStyles.ts
3133
+ import { twJoin as twJoin29 } from "tailwind-merge";
3134
+ var sizeStyles3 = {
3135
+ xs: "px-1 text-xs gap-0.5 h-4 rounded-md",
3136
+ sm: "h-5 gap-0.5 px-1 text-sm rounded-md",
3137
+ md: "h-6 gap-1 px-2 text-base rounded-lg",
3138
+ lg: "h-7 gap-1 px-2 text-lg rounded-lg"
3139
+ };
3140
+ var colorStyles2 = {
3141
+ default: {
3142
+ default: "bg-gray-100 text-gray-700 border border-gray-200",
3143
+ primary: "bg-indigo-100 text-indigo-700 border border-indigo-200",
3144
+ success: "bg-green-100 text-green-700 border border-green-200",
3145
+ warning: "bg-yellow-100 text-yellow-700 border border-yellow-200",
3146
+ danger: "bg-red-100 text-red-700 border border-red-200",
3147
+ disabled: "bg-gray-100 text-gray-400 border border-gray-200"
3148
+ },
3149
+ dark: {
3150
+ default: "bg-gray-700 text-gray-50 border border-gray-600",
3151
+ /**
3152
+ * Note(Stephen): We don't yet have tokens for all `intent` values for the dark variant.
3153
+ * Making them the same as default for now rather than wrestle with types as they are unused.
3154
+ */
3155
+ primary: "bg-gray-700 text-gray-50 border border-gray-600",
3156
+ success: "bg-gray-700 text-gray-50 border border-gray-600",
3157
+ warning: "bg-gray-700 text-gray-50 border border-gray-600",
3158
+ danger: "bg-gray-700 text-gray-50 border border-gray-600",
3159
+ disabled: "bg-gray-700 text-gray-50 border border-gray-600"
3160
+ }
3161
+ };
3162
+ var labelStyles = ({ intent = "default", size = "sm", variant = "default" }) => twJoin29(
3163
+ "inline-flex w-fit shrink-0 items-center justify-center truncate font-normal break-all",
3164
+ sizeStyles3[size],
3165
+ colorStyles2[variant][intent]
3166
+ );
3167
+
3168
+ // src/core/label/Label.tsx
3169
+ import { jsx as jsx70 } from "react/jsx-runtime";
3170
+ var LabelImpl2 = ({ children, intent, size, variant, ...rest }, ref) => {
3171
+ return /* @__PURE__ */ jsx70("span", { ref, className: labelStyles({ intent, size, variant }), ...rest, children });
3172
+ };
3173
+ var Label = React11.forwardRef(LabelImpl2);
3174
+
3175
+ // src/core/menu/Menu.tsx
3176
+ import { faEllipsis } from "@fortawesome/free-solid-svg-icons";
3177
+ import {
3178
+ Content as Content6,
3179
+ Item,
3180
+ Portal as Portal4,
3181
+ Root as Root6,
3182
+ Separator,
3183
+ Trigger as Trigger5
3184
+ } from "@radix-ui/react-dropdown-menu";
3185
+ import { twJoin as twJoin30 } from "tailwind-merge";
3186
+ import { jsx as jsx71, jsxs as jsxs29 } from "react/jsx-runtime";
3187
+ var MenuTrigger = ({ children, ...rest }) => {
3188
+ if (children == null) {
3189
+ return /* @__PURE__ */ jsx71(Trigger5, { asChild: true, children: /* @__PURE__ */ jsx71(Button, { ...rest, children: /* @__PURE__ */ jsx71(Icon, { icon: faEllipsis }) }) });
3190
+ }
3191
+ if (typeof children === "string") {
3192
+ return /* @__PURE__ */ jsx71(Trigger5, { asChild: true, children: /* @__PURE__ */ jsxs29(Button, { ...rest, children: [
3193
+ /* @__PURE__ */ jsx71("span", { children }),
3194
+ /* @__PURE__ */ jsx71(DropdownChevron, {})
3195
+ ] }) });
3196
+ }
3197
+ return /* @__PURE__ */ jsx71(Trigger5, { asChild: true, children: /* @__PURE__ */ jsx71(Button, { ...rest, children }) });
3198
+ };
3199
+ var MenuContent = ({ children, unrestrictedHeight = false, ...props }) => /* @__PURE__ */ jsx71(Portal4, { children: /* @__PURE__ */ jsx71(
3200
+ Content6,
3201
+ {
3202
+ collisionPadding: 8,
3203
+ sideOffset: 4,
3204
+ align: "end",
3205
+ className: "z-100 min-w-48 rounded-lg bg-white p-1.5 shadow-lg",
3206
+ ...props,
3207
+ children: /* @__PURE__ */ jsx71("div", { className: twJoin30("overflow-y-auto", !unrestrictedHeight && "max-h-[252px]"), children })
3208
+ }
3209
+ ) });
3210
+ var MenuItem = ({ loading, disabled, size = "default", ...rest }) => /* @__PURE__ */ jsx71(
3211
+ Item,
3212
+ {
3213
+ "data-loading": loading || void 0,
3214
+ disabled: loading || disabled,
3215
+ className: twJoin30(
3216
+ "on-menu-item-active group flex w-full cursor-pointer items-center rounded-md p-2 text-gray-700 outline-hidden select-none data-disabled:cursor-not-allowed data-disabled:text-gray-400 data-highlighted:bg-gray-100 data-loading:bg-transparent data-loading:text-gray-400",
3217
+ size === "default" ? "gap-1.5 text-sm" : "gap-2 text-base"
3218
+ ),
3219
+ ...rest
3220
+ }
3221
+ );
3222
+ var MenuItemWithDisabledTooltip = ({ tooltip, onSelect, ...props }) => {
3223
+ if (!props.disabled || !tooltip) {
3224
+ return /* @__PURE__ */ jsx71(MenuItem, { ...props, onSelect });
3225
+ }
3226
+ return /* @__PURE__ */ jsx71(
3227
+ Tooltip,
3228
+ {
3229
+ trigger: /* @__PURE__ */ jsx71("span", { children: /* @__PURE__ */ jsx71(MenuItem, { ...props }) }),
3230
+ content: tooltip,
3231
+ side: "left"
3232
+ }
3233
+ );
3234
+ };
3235
+ var MenuRoot = (props) => /* @__PURE__ */ jsx71(Root6, { modal: false, ...props });
3236
+ var MenuSeparator = () => /* @__PURE__ */ jsx71(Separator, { className: "my-[5px] h-px bg-gray-200" });
3237
+ var Menu = ({ children, trigger, align, variant = "default", triggerSize, ...rest }) => {
3238
+ switch (variant) {
3239
+ case "minimal":
3240
+ return /* @__PURE__ */ jsxs29(MenuRoot, { ...rest, children: [
3241
+ /* @__PURE__ */ jsx71(MenuTrigger, { ...rest, size: triggerSize || "xs", variant: "transparent", children: trigger }),
3242
+ /* @__PURE__ */ jsx71(MenuContent, { align, children })
3243
+ ] });
3244
+ case "default":
3245
+ default:
3246
+ return /* @__PURE__ */ jsxs29(MenuRoot, { ...rest, children: [
3247
+ /* @__PURE__ */ jsx71(MenuTrigger, { size: triggerSize, ...rest, children: trigger }),
3248
+ /* @__PURE__ */ jsx71(MenuContent, { align, children })
3249
+ ] });
3250
+ }
3251
+ };
3252
+ Menu.Root = MenuRoot;
3253
+ Menu.Trigger = MenuTrigger;
3254
+ Menu.RawTrigger = Trigger5;
3255
+ Menu.Content = MenuContent;
3256
+ Menu.Item = MenuItem;
3257
+ Menu.ItemWithDisabledToolTip = MenuItemWithDisabledTooltip;
3258
+ Menu.Separator = MenuSeparator;
3259
+
3260
+ // src/core/modal/components/ModalActions.tsx
3261
+ import { jsx as jsx72 } from "react/jsx-runtime";
3262
+ var ModalActions = ({ children }) => {
3263
+ if (children == null) {
3264
+ return null;
3265
+ }
3266
+ return /* @__PURE__ */ jsx72("div", { className: "sticky bottom-0 z-2 flex items-center justify-end gap-x-2 overflow-clip rounded-b-xl bg-white/80 px-8 pt-2 pb-6 backdrop-blur-sm", children });
3267
+ };
3268
+
3269
+ // src/core/modal/components/ModalBody.tsx
3270
+ import { jsx as jsx73 } from "react/jsx-runtime";
3271
+ var ModalBody = ({ children }) => {
3272
+ if (children == null) {
3273
+ return null;
3274
+ }
3275
+ return /* @__PURE__ */ jsx73("div", { className: "px-8 py-1.5", children });
3276
+ };
3277
+
3278
+ // src/core/modal/components/ModalCloseButton.tsx
3279
+ import { Close as Close2 } from "@radix-ui/react-dialog";
3280
+ import { jsx as jsx74 } from "react/jsx-runtime";
3281
+ var ModalCloseButton = (props) => /* @__PURE__ */ jsx74(Close2, { asChild: true, children: /* @__PURE__ */ jsx74(Button, { ...props }) });
3282
+
3283
+ // src/core/modal/components/ModalContent.tsx
3284
+ import { Content as Content7, Overlay, Portal as Portal5 } from "@radix-ui/react-dialog";
3285
+ import { twJoin as twJoin31 } from "tailwind-merge";
3286
+ import { jsx as jsx75 } from "react/jsx-runtime";
3287
+ var preventDismiss = (e) => e.preventDefault();
3288
+ var handleDismiss = (dismissible) => {
3289
+ if (dismissible) {
3290
+ return;
3291
+ }
3292
+ return preventDismiss;
3293
+ };
3294
+ var ModalContent = ({
3295
+ children,
3296
+ maxWidthClassName = "max-w-prose",
3297
+ overflowYClassName = "overflow-y-auto",
3298
+ onDismiss,
3299
+ dismissible = true,
3300
+ fullscreen,
3301
+ ...rest
3302
+ }) => /* @__PURE__ */ jsx75(Portal5, { children: /* @__PURE__ */ jsx75(
3303
+ Overlay,
3304
+ {
3305
+ className: "fixed inset-0 z-50 bg-black/50 data-[state=open]:animate-fade-in-custom-easing",
3306
+ children: /* @__PURE__ */ jsx75(
3307
+ Content7,
3308
+ {
3309
+ ...rest,
3310
+ className: twJoin31(
3311
+ fullscreen ? "h-[calc(100vh-1rem)] w-[calc(100vw-1rem)]" : `max-h-[calc(100vh-2rem)] w-[clamp(100vw-2rem,100%,100vw-2rem)] ${maxWidthClassName}`,
3312
+ `fixed top-1/2 left-1/2 flex -translate-x-1/2 -translate-y-1/2 flex-col rounded-xl bg-white shadow-lg focus:outline-hidden data-[state=open]:animate-fade-in-subtle-movement ${overflowYClassName}`
3313
+ ),
3314
+ onPointerDownOutside: fullscreen ? handleDismiss() : onDismiss ?? handleDismiss(dismissible),
3315
+ onEscapeKeyDown: fullscreen ? handleDismiss() : onDismiss ?? handleDismiss(dismissible),
3316
+ children: /* @__PURE__ */ jsx75("div", { className: "relative flex h-full min-w-0 flex-1 flex-col", children })
3317
+ }
3318
+ )
3319
+ }
3320
+ ) });
3321
+
3322
+ // src/core/modal/components/ModalDescription.tsx
3323
+ import { Description } from "@radix-ui/react-dialog";
3324
+ import { jsx as jsx76 } from "react/jsx-runtime";
3325
+ var ModalDescription = ({ children }) => {
3326
+ if (children == null) {
3327
+ return null;
3328
+ }
3329
+ return /* @__PURE__ */ jsx76(Description, { className: "pb-3 text-base/6 font-normal text-gray-700", children });
3330
+ };
3331
+
3332
+ // src/core/modal/components/ModalErrorCallout.tsx
3333
+ import { jsx as jsx77 } from "react/jsx-runtime";
3334
+ var ModalErrorCallout = ({ children }) => {
3335
+ if (!children) {
3336
+ return null;
3337
+ }
3338
+ return /* @__PURE__ */ jsx77("div", { className: "sticky top-14 z-10 px-5", children: /* @__PURE__ */ jsx77(Callout, { intent: "danger", children }) });
3339
+ };
3340
+
3341
+ // src/core/modal/components/ModalRoot.tsx
3342
+ import { Root as Root7 } from "@radix-ui/react-dialog";
3343
+ import { jsx as jsx78 } from "react/jsx-runtime";
3344
+ var ModalRoot = (props) => {
3345
+ return /* @__PURE__ */ jsx78(Root7, { ...props });
3346
+ };
3347
+
3348
+ // src/core/modal/components/ModalTitle.tsx
3349
+ import { Title } from "@radix-ui/react-dialog";
3350
+
3351
+ // src/core/modal/components/ModalCloseX.tsx
3352
+ import { faXmark as faXmark4 } from "@fortawesome/free-solid-svg-icons";
3353
+ import { Close as Close3 } from "@radix-ui/react-dialog";
3354
+ import { jsx as jsx79 } from "react/jsx-runtime";
3355
+ var ModalCloseX = () => /* @__PURE__ */ jsx79("span", { className: "absolute top-2.5 right-2.5", children: /* @__PURE__ */ jsx79(Close3, { asChild: true, "aria-label": "Close", children: /* @__PURE__ */ jsx79(Button, { variant: "transparent", children: /* @__PURE__ */ jsx79("span", { className: "px-0.5 text-xl text-gray-500", children: /* @__PURE__ */ jsx79(Icon, { icon: faXmark4 }) }) }) }) });
3356
+
3357
+ // src/core/modal/components/ModalTitle.tsx
3358
+ import { jsx as jsx80, jsxs as jsxs30 } from "react/jsx-runtime";
3359
+ var ModalTitle = ({ children, showX = true }) => {
3360
+ if (children == null) {
3361
+ return null;
3362
+ }
3363
+ return /* @__PURE__ */ jsxs30("div", { className: "sticky top-0 z-2 overflow-clip rounded-t-xl bg-white/80 px-8 pt-8 pb-1.5 backdrop-blur-sm", children: [
3364
+ /* @__PURE__ */ jsx80(Title, { className: "text-xl font-semibold text-gray-900", children }),
3365
+ showX && /* @__PURE__ */ jsx80(ModalCloseX, {})
3366
+ ] });
3367
+ };
3368
+
3369
+ // src/core/modal/components/ModalTriggerButton.tsx
3370
+ import { Trigger as Trigger6 } from "@radix-ui/react-dialog";
3371
+ import { jsx as jsx81 } from "react/jsx-runtime";
3372
+ var ModalTriggerButton = (props) => /* @__PURE__ */ jsx81(Trigger6, { asChild: true, children: /* @__PURE__ */ jsx81(Button, { ...props }) });
3373
+
3374
+ // src/core/modal/Modal.tsx
3375
+ import { Fragment as Fragment11, jsx as jsx82, jsxs as jsxs31 } from "react/jsx-runtime";
3376
+ var ModalBodyImpl = ({
3377
+ children,
3378
+ title,
3379
+ error,
3380
+ description,
3381
+ actions,
3382
+ showX = true
3383
+ }) => /* @__PURE__ */ jsxs31(Fragment11, { children: [
3384
+ /* @__PURE__ */ jsx82(ModalTitle, { showX, children: title }),
3385
+ /* @__PURE__ */ jsx82(ModalErrorCallout, { children: error }),
3386
+ (description || children) && /* @__PURE__ */ jsxs31(ModalBody, { children: [
3387
+ /* @__PURE__ */ jsx82(ModalDescription, { children: description }),
3388
+ children
3389
+ ] }),
3390
+ /* @__PURE__ */ jsx82(ModalActions, { children: actions })
3391
+ ] });
3392
+ var Modal = ({
3393
+ children,
3394
+ trigger,
3395
+ isOpen,
3396
+ onClose,
3397
+ onOpenChange,
3398
+ content,
3399
+ title,
3400
+ error,
3401
+ description,
3402
+ actions,
3403
+ ...rest
3404
+ }) => /* @__PURE__ */ jsxs31(
3405
+ ModalRoot,
3406
+ {
3407
+ open: isOpen,
3408
+ onOpenChange: (open) => {
3409
+ if (trigger) {
3410
+ onOpenChange?.(open);
3411
+ } else if (open === false) {
3412
+ onClose?.();
3413
+ }
3414
+ },
3415
+ children: [
3416
+ trigger,
3417
+ /* @__PURE__ */ jsx82(ModalContent, { "aria-describedby": description || void 0, ...rest, children: children !== void 0 ? children : /* @__PURE__ */ jsx82(ModalBodyImpl, { title, error, description, actions, children: content }) })
3418
+ ]
3419
+ }
3420
+ );
3421
+ Modal.Body = ModalBodyImpl;
3422
+ Modal.TriggerButton = ModalTriggerButton;
3423
+ Modal.CloseButton = ModalCloseButton;
3424
+
3425
+ // src/core/modal/FullscreenModalHeader.tsx
3426
+ import { Title as Title2 } from "@radix-ui/react-dialog";
3427
+ import { twJoin as twJoin32 } from "tailwind-merge";
3428
+ import { jsx as jsx83, jsxs as jsxs32 } from "react/jsx-runtime";
3429
+ var FullscreenModalHeader = ({
3430
+ className,
3431
+ title,
3432
+ description,
3433
+ leftSlot,
3434
+ rightSlot
3435
+ }) => {
3436
+ return /* @__PURE__ */ jsxs32("div", { className: twJoin32("flex items-center justify-between gap-4", className), children: [
3437
+ /* @__PURE__ */ jsxs32("div", { className: "flex flex-1 items-center gap-4", children: [
3438
+ leftSlot,
3439
+ /* @__PURE__ */ jsxs32("div", { className: "flex flex-col gap-1", children: [
3440
+ /* @__PURE__ */ jsx83(Title2, { className: "text-2xl font-medium text-gray-700", children: title }),
3441
+ description && /* @__PURE__ */ jsx83("div", { className: "text-base/6 text-gray-500", children: description })
3442
+ ] })
3443
+ ] }),
3444
+ /* @__PURE__ */ jsx83("div", { className: "flex gap-2", children: rightSlot })
3445
+ ] });
3446
+ };
3447
+
3448
+ // src/core/modal/FullscreenModal.tsx
3449
+ import { jsx as jsx84, jsxs as jsxs33 } from "react/jsx-runtime";
3450
+ var FullscreenModal = ({
3451
+ children,
3452
+ trigger,
3453
+ isOpen,
3454
+ onClose,
3455
+ onOpenChange,
3456
+ fullscreen = true,
3457
+ showX = false,
3458
+ title,
3459
+ ...rest
3460
+ }) => /* @__PURE__ */ jsxs33(
3461
+ ModalRoot,
3462
+ {
3463
+ open: isOpen,
3464
+ onOpenChange: (open) => {
3465
+ if (trigger) {
3466
+ onOpenChange?.(open);
3467
+ } else if (open === false) {
3468
+ onClose?.();
3469
+ }
3470
+ },
3471
+ children: [
3472
+ trigger,
3473
+ /* @__PURE__ */ jsx84(ModalContent, { fullscreen, ...rest, children: title ? /* @__PURE__ */ jsx84(Modal.Body, { title, showX, children }) : children })
3474
+ ]
3475
+ }
3476
+ );
3477
+ FullscreenModal.TriggerButton = ModalTriggerButton;
3478
+ FullscreenModal.CloseButton = ModalCloseButton;
3479
+ FullscreenModal.Header = FullscreenModalHeader;
3480
+
3481
+ // src/core/modal/AlertModal.tsx
3482
+ import { Fragment as Fragment12, jsx as jsx85, jsxs as jsxs34 } from "react/jsx-runtime";
3483
+ var ModalBodyImpl2 = ({ children, title, error, description, actions }) => /* @__PURE__ */ jsxs34(Fragment12, { children: [
3484
+ /* @__PURE__ */ jsx85(ModalTitle, { showX: false, children: title }),
3485
+ /* @__PURE__ */ jsx85(ModalErrorCallout, { children: error }),
3486
+ (description || children) && /* @__PURE__ */ jsxs34(ModalBody, { children: [
3487
+ /* @__PURE__ */ jsx85(ModalDescription, { children: description }),
3488
+ children
3489
+ ] }),
3490
+ /* @__PURE__ */ jsx85(ModalActions, { children: actions })
3491
+ ] });
3492
+ var AlertModal = ({
3493
+ children,
3494
+ trigger,
3495
+ isOpen,
3496
+ onOpenChange,
3497
+ onClose,
3498
+ content,
3499
+ title,
3500
+ error,
3501
+ description,
3502
+ actions,
3503
+ ...rest
3504
+ }) => /* @__PURE__ */ jsxs34(
3505
+ ModalRoot,
3506
+ {
3507
+ open: isOpen,
3508
+ onOpenChange: (open) => {
3509
+ if (trigger) {
3510
+ onOpenChange?.(open);
3511
+ } else if (open === false) {
3512
+ onClose?.();
3513
+ }
3514
+ },
3515
+ children: [
3516
+ trigger,
3517
+ /* @__PURE__ */ jsx85(ModalContent, { ...rest, dismissible: false, children: children !== void 0 ? children : /* @__PURE__ */ jsx85(ModalBodyImpl2, { title, error, description, actions, children: content }) })
3518
+ ]
3519
+ }
3520
+ );
3521
+ AlertModal.Body = ModalBodyImpl2;
3522
+ AlertModal.TriggerButton = ModalTriggerButton;
3523
+ AlertModal.CloseButton = ModalCloseButton;
3524
+
3525
+ // src/core/phone-number/PhoneNumber.tsx
3526
+ import "react-international-phone/style.css";
3527
+ import { getCountry, PhoneInput } from "react-international-phone";
3528
+ import { twJoin as twJoin33 } from "tailwind-merge";
3529
+ import { jsx as jsx86 } from "react/jsx-runtime";
3530
+ var PhoneNumber = ({
3531
+ hasError,
3532
+ onChange,
3533
+ ...props
3534
+ }) => {
3535
+ return /* @__PURE__ */ jsx86(
3536
+ PhoneInput,
3537
+ {
3538
+ defaultCountry: props.defaultCountry ?? "us",
3539
+ disableDialCodeAndPrefix: true,
3540
+ showDisabledDialCodeAndPrefix: true,
3541
+ inputClassName: twJoin33("flex-1 placeholder:text-gray-400", hasError ? "border-red-300!" : "border-gray-200!"),
3542
+ countrySelectorStyleProps: { className: "border-gray-200!" },
3543
+ onChange: (value, meta) => onChange(meta.inputValue ? value : void 0),
3544
+ ...props
3545
+ }
3546
+ );
3547
+ };
3548
+ var formatPhoneNumber = (input) => {
3549
+ if (!input) {
3550
+ return input;
3551
+ }
3552
+ const digitsOnly = input.replace(/\D/g, "");
3553
+ if (digitsOnly.length === 10) {
3554
+ return `+1${digitsOnly}`;
3555
+ }
3556
+ if (digitsOnly.length === 11 && digitsOnly.startsWith("1")) {
3557
+ return `+${digitsOnly}`;
3558
+ }
3559
+ return input;
3560
+ };
3561
+ var formatPhoneNumberForDisplay = (input) => {
3562
+ if (!input) {
3563
+ return input;
3564
+ }
3565
+ const digitsOnly = input.replace(/\D/g, "");
3566
+ if (digitsOnly.length === 11 && digitsOnly.startsWith("1")) {
3567
+ return `+1 (${digitsOnly.slice(1, 4)}) ${digitsOnly.slice(4, 7)}-${digitsOnly.slice(7)}`;
3568
+ }
3569
+ if (digitsOnly.length === 10) {
3570
+ return `(${digitsOnly.slice(0, 3)}) ${digitsOnly.slice(3, 6)}-${digitsOnly.slice(6)}`;
3571
+ }
3572
+ return input;
3573
+ };
3574
+ var isValidPhoneNumber = (input) => {
3575
+ if (!input) {
3576
+ return false;
3577
+ }
3578
+ if (input.startsWith("+1")) {
3579
+ return input.length === 12;
3580
+ }
3581
+ if (input.startsWith("1")) {
3582
+ return input.length === 11;
3583
+ }
3584
+ return true;
3585
+ };
3586
+
3587
+ // src/core/table/Table.tsx
3588
+ import { twJoin as twJoin35 } from "tailwind-merge";
3589
+
3590
+ // src/core/table/TableBody.tsx
3591
+ import { faTable } from "@fortawesome/free-solid-svg-icons";
3592
+
3593
+ // src/core/table/TableRow.tsx
3594
+ import { twJoin as twJoin34 } from "tailwind-merge";
3595
+
3596
+ // src/core/table/utils.ts
3597
+ import { flexRender } from "@tanstack/react-table";
3598
+ var isValidCell = (cell) => {
3599
+ if (!(cell.column.columnDef.cell instanceof Function)) {
3600
+ return null;
3601
+ }
3602
+ return cell.column.columnDef.cell(cell.getContext());
3603
+ };
3604
+ var renderHeader = (header) => {
3605
+ if (header.isPlaceholder) {
3606
+ return null;
3607
+ }
3608
+ return flexRender(header.column.columnDef.header, header.getContext());
3609
+ };
3610
+ var renderCell = (cell) => {
3611
+ if (isValidCell(cell) == null) {
3612
+ return null;
3613
+ }
3614
+ return flexRender(cell.column.columnDef.cell, cell.getContext());
3615
+ };
3616
+ var sumOffset = (offset, { getSize }) => getSize() + offset;
3617
+ var getCols = (item) => {
3618
+ const cols = item.getContext().table.getAllColumns();
3619
+ const index = cols.findIndex(({ id }) => id === item.column.id);
3620
+ return { cols, index };
3621
+ };
3622
+ var getLeftStickyOffset = (item) => {
3623
+ const { cols, index } = getCols(item);
3624
+ if (index === 0) {
3625
+ return 0;
3626
+ }
3627
+ return cols.slice(0, index).reduce(sumOffset, 0);
3628
+ };
3629
+ var getRightStickyOffset = (item) => {
3630
+ const { cols, index } = getCols(item);
3631
+ if (index === cols.length - 1) {
3632
+ return 0;
3633
+ }
3634
+ return cols.slice(0, index).reduceRight(sumOffset, 0);
3635
+ };
3636
+ var handleStyle = (item, _style) => {
3637
+ const style = _style ? { ..._style } : {};
3638
+ if (item.column.columnDef.meta?.unPadded) {
3639
+ style.padding = 0;
3640
+ style.paddingTop = 0;
3641
+ style.paddingRight = 0;
3642
+ style.paddingBottom = 0;
3643
+ style.paddingLeft = 0;
3644
+ }
3645
+ const size = item.column.getSize();
3646
+ if (!size) {
3647
+ return style;
3648
+ }
3649
+ style.width = size;
3650
+ style.minWidth = size;
3651
+ if (item.column.columnDef.meta?.sticky === "left") {
3652
+ style.position = "sticky";
3653
+ style.left = getLeftStickyOffset(item);
3654
+ }
3655
+ if (item.column.columnDef.meta?.sticky === "right") {
3656
+ style.position = "sticky";
3657
+ style.right = getRightStickyOffset(item);
3658
+ }
3659
+ return style;
3660
+ };
3661
+ var handleHeaderStyle = handleStyle;
3662
+ var handleCellStyle = handleStyle;
3663
+
3664
+ // src/core/table/TableRow.tsx
3665
+ import { jsx as jsx87 } from "react/jsx-runtime";
3666
+ var TableRow = ({ table, rowClassName, cellClassName, row }) => {
3667
+ const hasRowClick = !!table.options.meta?.onRowClick;
3668
+ const isStaticSubRow = !!table.options.meta?.staticSubRows;
3669
+ const onRowClick = (ev, row2) => {
3670
+ if (ev.target === ev.currentTarget) {
3671
+ table.options.meta?.onRowClick?.(row2);
3672
+ }
3673
+ };
3674
+ const cells = row.getVisibleCells();
3675
+ return /* @__PURE__ */ jsx87(
3676
+ "tr",
3677
+ {
3678
+ "data-active": table.options.meta?.activeRowId === row.id ? "" : void 0,
3679
+ "data-clickable": !isStaticSubRow && (hasRowClick || row.getCanExpand()) ? "" : void 0,
3680
+ "data-depth": isStaticSubRow ? row.depth : void 0,
3681
+ onClick: !isStaticSubRow && row.getCanExpand() ? row.getToggleExpandedHandler() : void 0,
3682
+ className: twJoin34(
3683
+ "data-[active]:bg-indigo-100 data-[clickable]:hover:cursor-pointer data-[clickable]:hover:bg-indigo-50 data-[active]:data-[clickable]:hover:bg-indigo-200",
3684
+ rowClassName
3685
+ ),
3686
+ children: cells.map((cell) => /* @__PURE__ */ jsx87(
3687
+ "td",
3688
+ {
3689
+ onClickCapture: hasRowClick ? (ev) => onRowClick(ev, row) : void 0,
3690
+ className: cellClassName,
3691
+ style: handleCellStyle(cell),
3692
+ children: renderCell(cell)
3693
+ },
3694
+ cell.id
3695
+ ))
3696
+ }
3697
+ );
3698
+ };
3699
+
3700
+ // src/core/table/TableBody.tsx
3701
+ import { jsx as jsx88, jsxs as jsxs35 } from "react/jsx-runtime";
3702
+ var TableBody = ({ table, loading, rootClassName, ...props }) => {
3703
+ const { rows } = table.getRowModel();
3704
+ if (loading && rows.length === 0) {
3705
+ return /* @__PURE__ */ jsx88("tbody", { className: rootClassName, children: /* @__PURE__ */ jsx88("tr", { children: /* @__PURE__ */ jsx88("td", { colSpan: table.getAllLeafColumns().length, className: "h-12 text-center align-middle text-gray-400", children: /* @__PURE__ */ jsx88(Spinner, {}) }) }) });
3706
+ }
3707
+ if (rows.length === 0) {
3708
+ return /* @__PURE__ */ jsx88("tbody", { className: rootClassName, children: /* @__PURE__ */ jsx88("tr", { children: /* @__PURE__ */ jsx88(EmptyRowsTd, { colSpan: table.getAllLeafColumns().length, emptyText: table.options.meta?.emptyText }) }) });
3709
+ }
3710
+ return /* @__PURE__ */ jsx88("tbody", { className: rootClassName, children: rows.map((row) => /* @__PURE__ */ jsx88(TableRow, { ...props, table, row }, row.id)) });
3711
+ };
3712
+ var EmptyRowsTd = ({ emptyText = "No rows found", ...props }) => /* @__PURE__ */ jsx88("td", { ...props, className: "h-12 text-center align-middle text-gray-400", children: /* @__PURE__ */ jsxs35("p", { className: "inline-flex items-center gap-2 text-2xl/none", children: [
3713
+ /* @__PURE__ */ jsx88("span", { children: /* @__PURE__ */ jsx88(Icon, { icon: faTable }) }),
3714
+ /* @__PURE__ */ jsx88("span", { className: "text-base/none font-medium", children: emptyText })
3715
+ ] }) });
3716
+
3717
+ // src/core/table/TableHeader.tsx
3718
+ import { faArrowDownWideShort, faArrowUpWideShort } from "@fortawesome/free-solid-svg-icons";
3719
+ import { jsx as jsx89, jsxs as jsxs36 } from "react/jsx-runtime";
3720
+ var TableHeader = ({ table, rootClassName, rowClassName, cellClassName }) => {
3721
+ return /* @__PURE__ */ jsx89("thead", { className: rootClassName, children: table.getHeaderGroups().map((headerGroup) => /* @__PURE__ */ jsx89("tr", { className: rowClassName, children: headerGroup.headers.map((header) => /* @__PURE__ */ jsx89(
3722
+ Th,
3723
+ {
3724
+ scope: "col",
3725
+ colSpan: header.colSpan,
3726
+ className: cellClassName,
3727
+ style: handleHeaderStyle(header),
3728
+ header,
3729
+ children: renderHeader(header)
3730
+ },
3731
+ header.id
3732
+ )) }, headerGroup.id)) });
3733
+ };
3734
+ var Th = ({
3735
+ header,
3736
+ children,
3737
+ ...props
3738
+ }) => {
3739
+ if (header.column.getIsSorted()) {
3740
+ return /* @__PURE__ */ jsxs36("th", { ...props, "data-clickable": "ok", onClick: header.column.getToggleSortingHandler(), children: [
3741
+ children,
3742
+ /* @__PURE__ */ jsx89("span", { className: "ml-1.5", children: /* @__PURE__ */ jsx89(SortIcon, { dir: header.column.getIsSorted() }) })
3743
+ ] });
3744
+ }
3745
+ if (header.column.getCanSort()) {
3746
+ return /* @__PURE__ */ jsxs36("th", { ...props, "data-clickable": "ok", onClick: header.column.getToggleSortingHandler(), children: [
3747
+ children,
3748
+ /* @__PURE__ */ jsx89("span", { className: "invisible ml-1.5 group-hover:visible", children: /* @__PURE__ */ jsx89(SortIcon, { dir: header.column.getNextSortingOrder() }) })
3749
+ ] });
3750
+ }
3751
+ return /* @__PURE__ */ jsx89("th", { ...props, children });
3752
+ };
3753
+ var SortIcon = ({ dir }) => {
3754
+ if (dir === "asc") {
3755
+ return /* @__PURE__ */ jsx89(Icon, { icon: faArrowUpWideShort });
3756
+ }
3757
+ if (dir === "desc") {
3758
+ return /* @__PURE__ */ jsx89(Icon, { icon: faArrowDownWideShort });
3759
+ }
3760
+ return null;
3761
+ };
3762
+
3763
+ // src/core/table/Table.tsx
3764
+ import { jsx as jsx90, jsxs as jsxs37 } from "react/jsx-runtime";
3765
+ var variants = {
3766
+ default: "default",
3767
+ seamless: "seamless",
3768
+ transparent: "transparent",
3769
+ subtable: "subtable"
3770
+ };
3771
+ var headerClassNames = (variant) => {
3772
+ switch (variant) {
3773
+ case variants.transparent:
3774
+ return {
3775
+ cellClassName: "text-left text-sm font-medium text-gray-500 whitespace-nowrap px-2.5 py-3"
3776
+ };
3777
+ case variants.subtable:
3778
+ return {
3779
+ rowClassName: "divide-x divide-gray-200",
3780
+ cellClassName: "text-left text-sm font-medium text-gray-500 whitespace-nowrap border-b bg-gray-100 px-2 py-1.5"
3781
+ };
3782
+ case variants.seamless:
3783
+ return {
3784
+ cellClassName: "text-left text-sm font-medium text-gray-500 whitespace-nowrap sticky top-0 z-1 border-b bg-gray-50 px-2 py-1.5 group data-[clickable]:cursor-pointer data-[clickable]:select-none data-[clickable]:hover:text-gray-800"
3785
+ };
3786
+ case variants.default:
3787
+ default:
3788
+ return {
3789
+ cellClassName: "text-left text-sm font-medium text-gray-500 whitespace-nowrap sticky top-0 z-1 border-b bg-gray-100 px-2 py-1.5 group data-[clickable]:cursor-pointer data-[clickable]:select-none data-[clickable]:hover:text-gray-800"
3790
+ };
3791
+ }
3792
+ };
3793
+ var bodyClassNames = (variant) => {
3794
+ switch (variant) {
3795
+ case variants.seamless:
3796
+ return {
3797
+ rowClassName: "[&:not(:last-child)_td]:border-gray-200",
3798
+ cellClassName: "text-sm text-gray-700 whitespace-nowrap h-fit"
3799
+ };
3800
+ case variants.transparent:
3801
+ return {
3802
+ rootClassName: "rounded-lg bg-white outline outline-1 outline-gray-200",
3803
+ rowClassName: "[&:not(:last-child)_td]:border-b [&:not(:last-child)_td]:border-gray-200 [&:first-child_td:first-child]:rounded-tl-lg [&:first-child_td:last-child]:rounded-tr-lg [&:last-child_td:first-child]:rounded-bl-lg [&:last-child_td:last-child]:rounded-br-lg",
3804
+ cellClassName: "text-sm text-gray-700 whitespace-nowrap p-2.5 py-1.5"
3805
+ };
3806
+ case variants.subtable:
3807
+ return {
3808
+ rowClassName: "[&:not(:last-child)_td]:border-b [&:not(:last-child)_td]:border-gray-200 divide-x divide-gray-200",
3809
+ cellClassName: "text-sm text-gray-700 whitespace-nowrap p-2"
3810
+ };
3811
+ case variants.default:
3812
+ default:
3813
+ return {
3814
+ rowClassName: "[&:not(:last-child)_td]:border-b [&:not(:last-child)_td]:border-gray-200 data-[depth='0']:bg-gray-50",
3815
+ cellClassName: "text-sm text-gray-700 whitespace-nowrap p-2"
3816
+ };
3817
+ }
3818
+ };
3819
+ var Table = ({ variant = "default", loading, fillHeight, ...props }) => {
3820
+ const uiLoading = loading ? "loading" : void 0;
3821
+ switch (variant) {
3822
+ case variants.transparent:
3823
+ return /* @__PURE__ */ jsxs37(
3824
+ "table",
3825
+ {
3826
+ "data-ui": uiLoading,
3827
+ className: "mb-auto min-w-full border-separate border-spacing-0 data-[ui=loading]:pointer-events-none data-[ui=loading]:opacity-60 data-[ui=loading]:select-none",
3828
+ children: [
3829
+ /* @__PURE__ */ jsx90(TableHeader, { ...props, ...headerClassNames(variant) }),
3830
+ /* @__PURE__ */ jsx90(TableBody, { ...props, ...bodyClassNames(variant), loading })
3831
+ ]
3832
+ }
3833
+ );
3834
+ case variants.subtable:
3835
+ return /* @__PURE__ */ jsx90("div", { className: "mb-auto min-w-full", children: /* @__PURE__ */ jsxs37(
3836
+ "table",
3837
+ {
3838
+ "data-ui": uiLoading,
3839
+ className: "min-w-full border-separate border-spacing-0 data-[ui=loading]:pointer-events-none data-[ui=loading]:opacity-60 data-[ui=loading]:select-none",
3840
+ children: [
3841
+ /* @__PURE__ */ jsx90(TableHeader, { ...props, ...headerClassNames(variant) }),
3842
+ /* @__PURE__ */ jsx90(TableBody, { ...props, ...bodyClassNames(variant), loading })
3843
+ ]
3844
+ }
3845
+ ) });
3846
+ case variants.seamless:
3847
+ case variants.default:
3848
+ default:
3849
+ return /* @__PURE__ */ jsx90("div", { className: twJoin35("mb-auto overflow-auto rounded-md border border-gray-200 bg-white", fillHeight && "h-full min-h-0"), children: /* @__PURE__ */ jsx90("div", { className: "min-w-full", children: /* @__PURE__ */ jsxs37(
3850
+ "table",
3851
+ {
3852
+ "data-ui": uiLoading,
3853
+ className: "relative min-w-full border-separate border-spacing-0 data-[ui=loading]:pointer-events-none data-[ui=loading]:opacity-60 data-[ui=loading]:select-none",
3854
+ children: [
3855
+ /* @__PURE__ */ jsx90(TableHeader, { ...props, ...headerClassNames(variant) }),
3856
+ /* @__PURE__ */ jsx90(TableBody, { ...props, ...bodyClassNames(variant), loading })
3857
+ ]
3858
+ }
3859
+ ) }) });
3860
+ }
3861
+ };
3862
+
3863
+ // src/core/table/useTable.ts
3864
+ import { getCoreRowModel, useReactTable } from "@tanstack/react-table";
3865
+ var useTable = (options) => {
3866
+ const enableSorting = !!options.state?.sorting && !!options.onSortingChange;
3867
+ return useReactTable({
3868
+ ...options,
3869
+ getCoreRowModel: getCoreRowModel(),
3870
+ // This is a hack to allow the columns to flex by default,
3871
+ // and, then when size is overridden, they become fixed
3872
+ defaultColumn: {
3873
+ ...options.defaultColumn,
3874
+ minSize: 0,
3875
+ size: 0
3876
+ },
3877
+ /* eslint-disable @typescript-eslint/no-unsafe-assignment */
3878
+ meta: {
3879
+ emptyText: options.emptyText,
3880
+ activeRowId: options.activeRowId,
3881
+ onRowClick: options.onRowClick,
3882
+ staticSubRows: options.staticSubRows
3883
+ },
3884
+ /* eslint-enable @typescript-eslint/no-unsafe-assignment */
3885
+ manualSorting: true,
3886
+ enableMultiSort: false,
3887
+ enableSorting
3888
+ });
3889
+ };
3890
+
3891
+ // src/core/tab-group/TabGroup.tsx
3892
+ import { ToggleGroup, ToggleGroupItem } from "@radix-ui/react-toggle-group";
3893
+ import { Fragment as Fragment13 } from "react";
3894
+ import { twJoin as twJoin36 } from "tailwind-merge";
3895
+ import { jsx as jsx91, jsxs as jsxs38 } from "react/jsx-runtime";
3896
+ var TabGroup = ({ tabs, currentTab, setCurrentTab }) => {
3897
+ return /* @__PURE__ */ jsx91(
3898
+ ToggleGroup,
3899
+ {
3900
+ type: "single",
3901
+ value: currentTab,
3902
+ onValueChange: (value) => {
3903
+ if (value) {
3904
+ setCurrentTab(value);
3905
+ }
3906
+ },
3907
+ className: "flex w-full justify-between gap-1 rounded-lg border border-gray-200 p-1",
3908
+ children: tabs.map(({ id, label, disabled }, index) => /* @__PURE__ */ jsxs38(Fragment13, { children: [
3909
+ /* @__PURE__ */ jsx91(
3910
+ ToggleGroupItem,
3911
+ {
3912
+ value: id,
3913
+ disabled,
3914
+ className: twJoin36(
3915
+ "flex w-full items-center justify-center rounded-md border px-2 py-2 transition",
3916
+ disabled && "cursor-not-allowed opacity-50",
3917
+ !disabled && "hover:bg-indigo-50 focus-visible:border-indigo-700 focus-visible:outline-none",
3918
+ id !== currentTab && "border-transparent",
3919
+ id !== currentTab && !disabled && "hover:border-indigo-200",
3920
+ id === currentTab && !disabled && "border border-indigo-400 bg-white ring-2 ring-indigo-100"
3921
+ ),
3922
+ children: label
3923
+ }
3924
+ ),
3925
+ index !== tabs.length - 1 && /* @__PURE__ */ jsx91("div", { className: "my-1 flex w-[1px] bg-gray-300" })
3926
+ ] }, id))
3927
+ }
3928
+ );
3929
+ };
3930
+
3931
+ // src/core/tabs/Tabs.tsx
3932
+ import {
3933
+ Content as Content8,
3934
+ List,
3935
+ Root as Root8
3936
+ } from "@radix-ui/react-tabs";
3937
+ import { twJoin as twJoin37 } from "tailwind-merge";
3938
+
3939
+ // src/core/tabs/Trigger.tsx
3940
+ import { Trigger as Trigger7 } from "@radix-ui/react-tabs";
3941
+ import { twMerge as twMerge10 } from "tailwind-merge";
3942
+ import { jsx as jsx92, jsxs as jsxs39 } from "react/jsx-runtime";
3943
+ var TabsTrigger = ({
3944
+ id,
3945
+ label,
3946
+ disabled,
3947
+ dataTestId,
3948
+ fsId,
3949
+ extra,
3950
+ className
3951
+ }) => /* @__PURE__ */ jsxs39(
3952
+ Trigger7,
3953
+ {
3954
+ className: twMerge10(
3955
+ "h-full space-x-1 border-b-2 px-1 py-1 font-medium whitespace-nowrap transition-colors duration-150 data-[state='active']:border-indigo-500 data-[state='active']:text-indigo-700 data-[state='inactive']:border-transparent data-[state='inactive']:text-gray-500 data-[state='inactive']:hover:border-gray-200 data-[state='inactive']:hover:text-gray-700",
3956
+ className
3957
+ ),
3958
+ value: id,
3959
+ disabled,
3960
+ "data-testid": dataTestId,
3961
+ "fs-id": fsId,
3962
+ children: [
3963
+ label,
3964
+ extra && /* @__PURE__ */ jsx92("span", { children: extra })
3965
+ ]
3966
+ }
3967
+ );
3968
+
3969
+ // src/core/tabs/Tabs.tsx
3970
+ import { jsx as jsx93, jsxs as jsxs40 } from "react/jsx-runtime";
3971
+ var [Provider2, useContext6] = createContextHelper();
3972
+ var Tabs = ({
3973
+ tabs,
3974
+ className,
3975
+ tabsListClassName,
3976
+ tabsListContainerClassName,
3977
+ tabsListTriggerClassName,
3978
+ currentTab,
3979
+ setCurrentTab,
3980
+ children,
3981
+ extraNode
3982
+ }) => {
3983
+ return /* @__PURE__ */ jsx93(Provider2, { currentTab, children: /* @__PURE__ */ jsxs40(Root8, { className, value: currentTab, onValueChange: (id) => setCurrentTab(id), children: [
3984
+ /* @__PURE__ */ jsxs40("div", { className: twJoin37("flex gap-4", tabsListContainerClassName), children: [
3985
+ /* @__PURE__ */ jsx93(List, { className: twJoin37("flex space-x-4 overflow-x-auto", tabsListClassName), children: tabs.map(({ id, label, disabled, fsId }) => /* @__PURE__ */ jsx93(
3986
+ TabsTrigger,
3987
+ {
3988
+ id,
3989
+ label,
3990
+ disabled,
3991
+ className: tabsListTriggerClassName,
3992
+ fsId
3993
+ },
3994
+ id
3995
+ )) }),
3996
+ extraNode
3997
+ ] }),
3998
+ children
3999
+ ] }) });
4000
+ };
4001
+ var TabContent = ({ id, ...rest }) => {
4002
+ return /* @__PURE__ */ jsx93(Content8, { value: id, ...rest });
4003
+ };
4004
+ var AlwaysMountedTabContent = ({
4005
+ id,
4006
+ visibleClassName,
4007
+ className,
4008
+ children
4009
+ }) => {
4010
+ const { currentTab } = useContext6();
4011
+ const visible = id === currentTab;
4012
+ return /* @__PURE__ */ jsx93("div", { className: twJoin37(visible ? visibleClassName : "hidden", className), children });
4013
+ };
4014
+ Tabs.TabContent = TabContent;
4015
+ Tabs.AlwaysMountedTabContent = AlwaysMountedTabContent;
4016
+ var createTypedTabs = () => ({
4017
+ Root: ({ currentTab, setCurrentTab, ...props }) => {
4018
+ const handleValueChange = setCurrentTab ? (value) => setCurrentTab(value) : void 0;
4019
+ return /* @__PURE__ */ jsx93(Root8, { ...props, value: currentTab, onValueChange: handleValueChange });
4020
+ },
4021
+ List: ({ className, ...props }) => /* @__PURE__ */ jsx93(List, { ...props, className: twJoin37("flex space-x-4 overflow-x-auto", className) }),
4022
+ Trigger: TabsTrigger,
4023
+ Content: TabContent
4024
+ });
4025
+
4026
+ // src/core/tabs/ScrollTabsLayout.tsx
4027
+ import { useCallback as useCallback9, useEffect as useEffect7, useRef as useRef7, useState as useState10 } from "react";
4028
+ import { twJoin as twJoin38 } from "tailwind-merge";
4029
+ import { Fragment as Fragment14, jsx as jsx94, jsxs as jsxs41 } from "react/jsx-runtime";
4030
+ var ScrollTabsLayout = ({ tabs, onSelectTab, sectionClassName }) => {
4031
+ const [selectedTabName, setSelectedTabName] = useState10(tabs[0].tabName);
4032
+ const scrollContainerRef = useRef7(null);
4033
+ const tabRefs = useRef7({});
4034
+ const handleSelectTab = useCallback9(
4035
+ (tabId) => {
4036
+ scrollContainerRef.current?.scrollTo({
4037
+ top: tabRefs.current[tabId].offsetTop,
4038
+ behavior: "smooth"
4039
+ });
4040
+ setSelectedTabName(tabId);
4041
+ onSelectTab?.(tabId);
4042
+ },
4043
+ [onSelectTab]
4044
+ );
4045
+ useEffect7(() => {
4046
+ const scrollContainer = scrollContainerRef.current;
4047
+ const handleScroll = (e) => {
4048
+ Object.entries(tabRefs.current).forEach(([tabName, tabRef]) => {
4049
+ if (e.currentTarget?.scrollTop >= tabRef.offsetTop) {
4050
+ setSelectedTabName(tabName);
4051
+ onSelectTab?.(tabName);
4052
+ }
4053
+ });
4054
+ };
4055
+ scrollContainer?.addEventListener("scroll", handleScroll);
4056
+ return () => {
4057
+ scrollContainer?.removeEventListener("scroll", handleScroll);
4058
+ };
4059
+ });
4060
+ return /* @__PURE__ */ jsxs41(Fragment14, { children: [
4061
+ /* @__PURE__ */ jsx94(
4062
+ Tabs,
4063
+ {
4064
+ currentTab: selectedTabName,
4065
+ setCurrentTab: handleSelectTab,
4066
+ tabs: tabs.map((tab) => ({ id: tab.tabName, label: tab.tabName }))
4067
+ }
4068
+ ),
4069
+ /* @__PURE__ */ jsx94("hr", {}),
4070
+ /* @__PURE__ */ jsxs41("div", { ref: scrollContainerRef, className: "relative h-screen overflow-y-auto", children: [
4071
+ tabs.map((tab) => /* @__PURE__ */ jsx94(
4072
+ "div",
4073
+ {
4074
+ ref: (el) => el ? tabRefs.current[tab.tabName] = el : void 0,
4075
+ className: twJoin38("first:pt-4", sectionClassName),
4076
+ children: tab.content
4077
+ },
4078
+ tab.tabName
4079
+ )),
4080
+ /* @__PURE__ */ jsx94("div", { className: "h-screen" })
4081
+ ] })
4082
+ ] });
4083
+ };
4084
+
4085
+ // src/core/tabs/ComposableTabs.tsx
4086
+ import { Content as Content9, List as List2, Root as Root9 } from "@radix-ui/react-tabs";
4087
+ import { twJoin as twJoin39 } from "tailwind-merge";
4088
+ import { jsx as jsx95, jsxs as jsxs42 } from "react/jsx-runtime";
4089
+ var [TabsProvider, useTabsContext] = createContextHelper();
4090
+ var ComposableTabsList = ({ className, containerClassName, extraNode }) => {
4091
+ const { tabs } = useTabsContext();
4092
+ return /* @__PURE__ */ jsxs42("div", { className: twJoin39("flex gap-4", containerClassName), children: [
4093
+ /* @__PURE__ */ jsx95(List2, { className: twJoin39("flex space-x-4 overflow-x-auto", className), children: tabs.map(({ id, label, disabled }) => /* @__PURE__ */ jsx95(TabsTrigger, { id, label, disabled }, id)) }),
4094
+ extraNode
4095
+ ] });
4096
+ };
4097
+ var ComposableTabContent = ({ id, ...rest }) => {
4098
+ return /* @__PURE__ */ jsx95(Content9, { value: id, ...rest });
4099
+ };
4100
+ var ComposableAlwaysMountedTabContent = ({
4101
+ id,
4102
+ visibleClassName,
4103
+ className,
4104
+ children
4105
+ }) => {
4106
+ const { currentTab } = useTabsContext();
4107
+ const visible = id === currentTab;
4108
+ return /* @__PURE__ */ jsx95("div", { className: twJoin39(visible ? visibleClassName : "hidden", className), children });
4109
+ };
4110
+ var ComposableTabsRoot = ({
4111
+ tabs,
4112
+ currentTab,
4113
+ setCurrentTab,
4114
+ className,
4115
+ children
4116
+ }) => {
4117
+ return /* @__PURE__ */ jsx95(TabsProvider, { tabs, currentTab, children: /* @__PURE__ */ jsx95(Root9, { className, value: currentTab, onValueChange: (id) => setCurrentTab(id), children }) });
4118
+ };
4119
+ var ComposableTabs = {
4120
+ Root: ComposableTabsRoot,
4121
+ List: ComposableTabsList,
4122
+ TabContent: ComposableTabContent,
4123
+ AlwaysMountedTabContent: ComposableAlwaysMountedTabContent
4124
+ };
4125
+
4126
+ // src/core/tag/Tag.tsx
4127
+ import { faXmark as faXmark5 } from "@fortawesome/free-solid-svg-icons";
4128
+ import * as React12 from "react";
4129
+ import { jsx as jsx96, jsxs as jsxs43 } from "react/jsx-runtime";
4130
+ var TagLabel = ({ children, removable, onRemove, intent = "default", ...rest }, ref) => /* @__PURE__ */ jsxs43(Label, { ...rest, ref, intent, children: [
4131
+ children,
4132
+ removable && /* @__PURE__ */ jsx96(
4133
+ "button",
4134
+ {
4135
+ className: "ml-1 inline-flex h-xs items-center px-1 text-gray-500 hover:text-gray-700 focus:outline-hidden",
4136
+ onClick: onRemove,
4137
+ children: /* @__PURE__ */ jsx96(Icon, { icon: faXmark5 })
4138
+ }
4139
+ )
4140
+ ] });
4141
+ var TagImpl = React12.forwardRef(TagLabel);
4142
+ var Tag = ({ tooltip, ...rest }) => {
4143
+ if (!tooltip) {
4144
+ return /* @__PURE__ */ jsx96(TagImpl, { ...rest });
4145
+ }
4146
+ return /* @__PURE__ */ jsx96(Tooltip, { trigger: /* @__PURE__ */ jsx96(TagImpl, { ...rest }), content: /* @__PURE__ */ jsx96("p", { className: "text-sm", children: tooltip }) });
4147
+ };
4148
+
4149
+ // src/core/utils/useIsHovered.ts
4150
+ import { useEffect as useEffect8, useState as useState11 } from "react";
4151
+ var useIsHovered = (ref) => {
4152
+ const [isHovered, setIsHovered] = useState11(false);
4153
+ useEffect8(() => {
4154
+ const handleMouseMove = () => {
4155
+ if (ref.current?.matches(":hover")) {
4156
+ setIsHovered(true);
4157
+ } else {
4158
+ setIsHovered(false);
4159
+ }
4160
+ };
4161
+ const handleScroll = () => {
4162
+ if (isHovered) {
4163
+ setIsHovered(false);
4164
+ }
4165
+ };
4166
+ window.addEventListener("mousemove", handleMouseMove);
4167
+ if (isHovered) {
4168
+ window.addEventListener("scroll", handleScroll, true);
4169
+ }
4170
+ return () => {
4171
+ window.removeEventListener("mousemove", handleMouseMove);
4172
+ window.removeEventListener("scroll", handleScroll, true);
4173
+ };
4174
+ }, [ref, isHovered]);
4175
+ return isHovered;
4176
+ };
4177
+ export {
4178
+ AlertModal,
4179
+ AsyncMultiSelect,
4180
+ AsyncSelect,
4181
+ Button,
4182
+ ButtonGroup,
4183
+ CURRENCY_REGEX,
4184
+ Callout,
4185
+ Checkbox,
4186
+ Collapsible,
4187
+ CollapsibleSection,
4188
+ ComposableTabs,
4189
+ ControlledField,
4190
+ ControlledFieldProvider,
4191
+ Copyable,
4192
+ DEFAULT_NUM_VALUES_TO_SHOW,
4193
+ DatePicker,
4194
+ Divider,
4195
+ DollarInput,
4196
+ Drawer,
4197
+ DrawerHeader,
4198
+ DrawerHeaderSkeleton,
4199
+ DrawerStateContext,
4200
+ DropdownChevron,
4201
+ EmptyState,
4202
+ ErrorText,
4203
+ FormCheckbox,
4204
+ FormDatePicker,
4205
+ FormDollarInput,
4206
+ FormInput,
4207
+ FormMultiSelect,
4208
+ FormPercentInput,
4209
+ FormProvider,
4210
+ FormRadioButtonGroup,
4211
+ FormSelect,
4212
+ FormSwitch,
4213
+ FormTextArea,
4214
+ FullscreenModal,
4215
+ HeaderTile,
4216
+ Icon,
4217
+ IndeterminateCheckbox,
4218
+ Input,
4219
+ InputBox,
4220
+ IsEditingProvider,
4221
+ IsVisibleProvider,
4222
+ Label,
4223
+ LoadingBar,
4224
+ LoadingState,
4225
+ Menu,
4226
+ MenuRoot,
4227
+ MenuSeparator,
4228
+ Modal,
4229
+ MultiSelect,
4230
+ OverflowTooltip,
4231
+ PercentInput,
4232
+ PhoneNumber,
4233
+ Popover,
4234
+ RING_COLOR_CLASSNAME,
4235
+ RadioButtonGroup,
4236
+ RadioButtonItem,
4237
+ ScrollTabsLayout,
4238
+ Select,
4239
+ SelectListItem,
4240
+ SelectWithUnselect,
4241
+ Skeleton,
4242
+ Spinner,
4243
+ Switch,
4244
+ TabGroup,
4245
+ Table,
4246
+ TableCheckboxSkeleton,
4247
+ TableSkeleton,
4248
+ Tabs,
4249
+ TabsSkeleton,
4250
+ TabsTrigger,
4251
+ Tag,
4252
+ Text,
4253
+ TextArea,
4254
+ TextAreaComp,
4255
+ Tooltip,
4256
+ TooltipContent,
4257
+ UncontrolledField,
4258
+ UncontrolledFieldProvider,
4259
+ asNullish,
4260
+ asNumericStr,
4261
+ asOptional,
4262
+ asRequiredCustom,
4263
+ buildZodIssue,
4264
+ buttonStyles,
4265
+ copyToClipboard,
4266
+ createContextHelper,
4267
+ createToggleContextHelper,
4268
+ createTypedTabs,
4269
+ doesSelectItemMatch,
4270
+ dollarsStrSchema,
4271
+ formatPhoneNumber,
4272
+ formatPhoneNumberForDisplay,
4273
+ getCountry,
4274
+ getFieldError,
4275
+ inputBoxStyles,
4276
+ inputStyles,
4277
+ isValidPhoneNumber,
4278
+ linkStyles,
4279
+ localStoragePersist,
4280
+ npiSchema,
4281
+ npiSchemaOptional,
4282
+ requiredDollarsStrSchema,
4283
+ requiredDollarsStrSchemaWithCustomMessage,
4284
+ requiredNonZeroDollarsStrSchema,
4285
+ requiredPositiveDollarsStrSchema,
4286
+ requiredPositiveOrZeroDollarsStrSchema,
4287
+ selectedAmountSchema,
4288
+ taxIdSchema,
4289
+ taxonomyCodeSchema,
4290
+ useAsyncMultiSelect,
4291
+ useAsyncSelect,
4292
+ useControlledField,
4293
+ useControlledFormField,
4294
+ useController2 as useController,
4295
+ useCopyable,
4296
+ useDebounce,
4297
+ useDrawer,
4298
+ useDrawerResize,
4299
+ useFieldArray,
4300
+ useForm,
4301
+ useFormContext,
4302
+ useFormState2 as useFormState,
4303
+ useIsEditing,
4304
+ useIsHovered,
4305
+ useIsVisible,
4306
+ useOverflowObserver,
4307
+ useSwitchId,
4308
+ useSyncState,
4309
+ useTable,
4310
+ useToggle,
4311
+ useUncontrolledField,
4312
+ useUncontrolledFormField,
4313
+ useWatch
4314
+ };
4315
+ //# sourceMappingURL=index.mjs.map