@komensal/ui 0.1.0 → 0.2.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.
Files changed (49) hide show
  1. package/dist/index.d.ts +420 -0
  2. package/dist/index.js +1710 -0
  3. package/dist/index.js.map +1 -0
  4. package/dist/locales/index.d.ts +34 -0
  5. package/dist/locales/index.js +40 -0
  6. package/dist/locales/index.js.map +1 -0
  7. package/dist/styles/index.css +8 -0
  8. package/package.json +24 -8
  9. package/src/components/alert.tsx +0 -45
  10. package/src/components/auth-header.tsx +0 -26
  11. package/src/components/button.tsx +0 -121
  12. package/src/components/command.tsx +0 -125
  13. package/src/components/dialog.tsx +0 -118
  14. package/src/components/form-fields/index.ts +0 -5
  15. package/src/components/form-fields/input-field.tsx +0 -131
  16. package/src/components/form-fields/label-field.tsx +0 -20
  17. package/src/components/form-fields/map-picker-field.tsx +0 -49
  18. package/src/components/form-fields/otp-field.tsx +0 -76
  19. package/src/components/form-fields/select-field.tsx +0 -77
  20. package/src/components/form.tsx +0 -138
  21. package/src/components/google-map-picker.tsx +0 -243
  22. package/src/components/input.tsx +0 -40
  23. package/src/components/label.tsx +0 -17
  24. package/src/components/loading.tsx +0 -19
  25. package/src/components/otp-input.tsx +0 -62
  26. package/src/components/password-checklist.tsx +0 -37
  27. package/src/components/popover.tsx +0 -31
  28. package/src/components/select-input.tsx +0 -236
  29. package/src/components/select.tsx +0 -143
  30. package/src/components/spinner.tsx +0 -61
  31. package/src/components/step-header.tsx +0 -16
  32. package/src/components/stepper.tsx +0 -69
  33. package/src/components/toast/index.ts +0 -2
  34. package/src/components/toast/toast-provider.tsx +0 -123
  35. package/src/components/toast/toast.tsx +0 -106
  36. package/src/components/tooltip.tsx +0 -56
  37. package/src/components/wrapper.tsx +0 -12
  38. package/src/index.ts +0 -27
  39. package/src/locales/es/ui.json +0 -28
  40. package/src/locales/index.ts +0 -7
  41. package/src/styles/index.css +0 -1
  42. package/src/types/password.ts +0 -12
  43. package/src/types/toast.ts +0 -19
  44. package/src/utils/cn.ts +0 -6
  45. package/src/utils/index.ts +0 -3
  46. package/src/utils/styles.ts +0 -19
  47. package/src/utils/toast-emitter.ts +0 -37
  48. package/src/vite-env.d.ts +0 -3
  49. /package/{src → dist}/styles/theme.css +0 -0
package/dist/index.js ADDED
@@ -0,0 +1,1710 @@
1
+ // src/components/alert.tsx
2
+ import { AlertCircle, CheckCircle2, Info, TriangleAlert } from "lucide-react";
3
+
4
+ // src/utils/cn.ts
5
+ import { clsx } from "clsx";
6
+ import { twMerge } from "tailwind-merge";
7
+ function cn(...inputs) {
8
+ return twMerge(clsx(inputs));
9
+ }
10
+
11
+ // src/utils/styles.ts
12
+ var inputBase = cn(
13
+ "flex w-full !h-[50px] rounded-[10px] px-3 gap-[10px] text-base font-normal justify-between items-center",
14
+ "border border-border bg-surface text-foreground",
15
+ "transition-all duration-200 ease-in-out",
16
+ "placeholder:text-icon-muted placeholder:text-sm placeholder:font-normal placeholder:leading-none",
17
+ "disabled:cursor-not-allowed disabled:bg-inactive disabled:text-inactive-text disabled:border-inactive disabled:placeholder:text-inactive-text"
18
+ );
19
+ var inputPlaceholder = cn("text-icon-muted text-sm font-normal leading-none");
20
+ var inputDisabled = cn("cursor-not-allowed opacity-50");
21
+ var inputFocus = cn(
22
+ "focus:outline-none focus-visible:outline-none",
23
+ "focus-visible:ring-2 focus-visible:ring-ring focus-visible:border-primary",
24
+ "data-[state=open]:ring-2 data-[state=open]:ring-ring data-[state=open]:border-primary"
25
+ );
26
+
27
+ // src/utils/toast-emitter.ts
28
+ var emitToast = null;
29
+ var toast = {
30
+ error(options) {
31
+ emit("error", options);
32
+ },
33
+ info(options) {
34
+ emit("info", options);
35
+ },
36
+ success(options) {
37
+ emit("success", options);
38
+ },
39
+ wait(options) {
40
+ emit("wait", options);
41
+ },
42
+ warning(options) {
43
+ emit("warning", options);
44
+ }
45
+ };
46
+ function registerToastEmitter(fn) {
47
+ emitToast = fn;
48
+ }
49
+ function emit(type, options) {
50
+ if (!emitToast) return;
51
+ if (typeof options === "string") {
52
+ emitToast(type, { title: options });
53
+ } else {
54
+ emitToast(type, options);
55
+ }
56
+ }
57
+
58
+ // src/components/alert.tsx
59
+ import { jsx, jsxs } from "react/jsx-runtime";
60
+ var variantStyles = {
61
+ error: { container: "bg-destructive-subtle text-destructive", icon: "text-destructive" },
62
+ info: { container: "bg-info-subtle text-info", icon: "text-info" },
63
+ success: { container: "bg-success-subtle text-success", icon: "text-success" },
64
+ warning: { container: "bg-warning-subtle text-warning", icon: "text-warning" }
65
+ };
66
+ var variantIcons = {
67
+ error: AlertCircle,
68
+ info: Info,
69
+ success: CheckCircle2,
70
+ warning: TriangleAlert
71
+ };
72
+ var Alert = ({ children, className, variant = "error", ...props }) => {
73
+ const styles = variantStyles[variant];
74
+ const Icon2 = variantIcons[variant];
75
+ return /* @__PURE__ */ jsxs(
76
+ "div",
77
+ {
78
+ "aria-live": "polite",
79
+ className: cn(
80
+ "flex items-center justify-center gap-2 rounded-[10px] px-4 py-3 text-sm",
81
+ styles.container,
82
+ className
83
+ ),
84
+ role: "alert",
85
+ ...props,
86
+ children: [
87
+ /* @__PURE__ */ jsx(Icon2, { className: cn("h-5 w-5 shrink-0", styles.icon) }),
88
+ /* @__PURE__ */ jsx("span", { children })
89
+ ]
90
+ }
91
+ );
92
+ };
93
+
94
+ // src/components/auth-header.tsx
95
+ import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
96
+ var AuthHeader = ({ children, logoAlt, mobileClassName }) => {
97
+ return /* @__PURE__ */ jsxs2(Fragment, { children: [
98
+ /* @__PURE__ */ jsxs2("div", { className: cn("flex min-h-0 shrink flex-col lg:hidden", mobileClassName), children: [
99
+ /* @__PURE__ */ jsx2("div", { className: "flex justify-center py-2", children: /* @__PURE__ */ jsx2("img", { alt: logoAlt, className: "h-11 md:h-12", src: "/logotipo_color.svg" }) }),
100
+ children
101
+ ] }),
102
+ /* @__PURE__ */ jsx2("div", { className: "absolute hidden p-10 lg:flex", children: /* @__PURE__ */ jsx2("img", { alt: logoAlt, className: "h-12.5 w-12.5", src: "/logo_color.svg" }) })
103
+ ] });
104
+ };
105
+
106
+ // src/components/button.tsx
107
+ import { Slot } from "@radix-ui/react-slot";
108
+ import { cva } from "class-variance-authority";
109
+ import * as React2 from "react";
110
+
111
+ // src/components/spinner.tsx
112
+ import clsx2 from "clsx";
113
+ import { useTranslation } from "react-i18next";
114
+ import { Fragment as Fragment2, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
115
+ var sizes = {
116
+ lg: "70",
117
+ md: "50",
118
+ sm: "20",
119
+ xl: "100",
120
+ xs: "5"
121
+ };
122
+ var variants = {
123
+ light: "var(--color-spinner-light)",
124
+ primary: "var(--color-spinner-primary)",
125
+ secondary: "var(--color-spinner-secondary)"
126
+ };
127
+ var Spinner = ({ className = "", size = "md", variant = "primary" }) => {
128
+ const { t } = useTranslation("ui");
129
+ return /* @__PURE__ */ jsxs3(Fragment2, { children: [
130
+ /* @__PURE__ */ jsx3(
131
+ "svg",
132
+ {
133
+ fill: "currentColor",
134
+ height: sizes[size],
135
+ stroke: variants[variant],
136
+ viewBox: "0 0 100 100",
137
+ width: sizes[size],
138
+ xmlns: "http://www.w3.org/2000/svg",
139
+ children: /* @__PURE__ */ jsxs3("g", { className: clsx2("spinner_V8m1", sizes[size], variants[variant], className), children: [
140
+ /* @__PURE__ */ jsx3("circle", { cx: "50", cy: "50", fill: "none", opacity: "0.25", r: "35", stroke: "currentColor", strokeWidth: "10" }),
141
+ /* @__PURE__ */ jsx3(
142
+ "circle",
143
+ {
144
+ cx: "50",
145
+ cy: "50",
146
+ fill: "none",
147
+ r: "35",
148
+ stroke: "currentColor",
149
+ strokeDasharray: "164.93361431346415 56.97787143782138",
150
+ strokeWidth: "10",
151
+ children: /* @__PURE__ */ jsx3(
152
+ "animateTransform",
153
+ {
154
+ attributeName: "transform",
155
+ dur: "1s",
156
+ keyTimes: "0;1",
157
+ repeatCount: "indefinite",
158
+ type: "rotate",
159
+ values: "0 50 50;360 50 50"
160
+ }
161
+ )
162
+ }
163
+ )
164
+ ] })
165
+ }
166
+ ),
167
+ /* @__PURE__ */ jsx3("span", { className: "sr-only", children: t("spinner.loading") })
168
+ ] });
169
+ };
170
+
171
+ // src/components/tooltip.tsx
172
+ import * as TooltipPrimitive from "@radix-ui/react-tooltip";
173
+ import * as React from "react";
174
+ import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
175
+ var TooltipProvider = TooltipPrimitive.Provider;
176
+ var TooltipRoot = TooltipPrimitive.Root;
177
+ var TooltipTrigger = TooltipPrimitive.Trigger;
178
+ var TooltipContent = React.forwardRef(({ className, sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsx4(TooltipPrimitive.Portal, { children: /* @__PURE__ */ jsx4(
179
+ TooltipPrimitive.Content,
180
+ {
181
+ className: cn(
182
+ "bg-tooltip text-tooltip-foreground animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 overflow-hidden rounded-md px-3 py-1.5 text-sm font-semibold shadow-sm",
183
+ className
184
+ ),
185
+ ref,
186
+ sideOffset,
187
+ ...props
188
+ }
189
+ ) }));
190
+ TooltipContent.displayName = TooltipPrimitive.Content.displayName;
191
+ var Tooltip = React.forwardRef(
192
+ ({ children, childrenClassName, className, message, sideTooltip = "top" }, ref) => {
193
+ return /* @__PURE__ */ jsx4(TooltipProvider, { children: /* @__PURE__ */ jsxs4(TooltipRoot, { children: [
194
+ /* @__PURE__ */ jsx4(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx4("div", { className: cn("", childrenClassName), ref, children }) }),
195
+ /* @__PURE__ */ jsx4(TooltipContent, { className: cn("", className), side: sideTooltip, children: /* @__PURE__ */ jsx4("p", { children: message }) })
196
+ ] }) });
197
+ }
198
+ );
199
+ Tooltip.displayName = "Tooltip";
200
+
201
+ // src/components/button.tsx
202
+ import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
203
+ var buttonVariants = cva(
204
+ "w-full inline-flex items-center justify-center gap-[10px] whitespace-nowrap rounded-[12px] border border-transparent text-base font-semibold transition-all duration-300 ease-in-out focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:bg-inactive disabled:text-inactive-text disabled:border-transparent cursor-pointer",
205
+ {
206
+ defaultVariants: {
207
+ hoverStyle: "none",
208
+ size: "default",
209
+ variant: "primary"
210
+ },
211
+ variants: {
212
+ hoverStyle: {
213
+ highlight: `
214
+ hover:bg-brand-subtle hover:border-primary hover:text-primary
215
+ `,
216
+ none: "",
217
+ shine: `
218
+ relative overflow-hidden
219
+ hover:-translate-y-[1px] hover:shadow-lg
220
+ before:content-[''] before:absolute before:top-0 before:left-[-100%]
221
+ before:w-full before:h-full
222
+ before:bg-[linear-gradient(90deg,transparent,rgba(255,255,255,0.15),transparent)]
223
+ before:transition-all before:duration-300
224
+ hover:before:left-[100%]
225
+ `
226
+ },
227
+ size: {
228
+ default: "h-14 px-4",
229
+ icon: "h-12 w-12 p-0",
230
+ lg: "h-14 px-12",
231
+ sm: "h-9 px-3 text-sm"
232
+ },
233
+ variant: {
234
+ destructive: "bg-destructive text-inverse hover:bg-destructive/90",
235
+ ghost: "bg-transparent border border-border text-foreground hover:bg-hover",
236
+ invisible: "bg-transparent rounded-none",
237
+ link: "text-muted underline-offset-4 hover:underline text-sm font-normal disabled:bg-transparent",
238
+ outline: "bg-surface border border-primary text-primary hover:bg-brand-subtle",
239
+ primary: "bg-primary text-inverse hover:bg-primary-hover active:bg-primary-dark",
240
+ tertiary: "bg-subtle border border-border text-foreground hover:bg-hover",
241
+ underline: "text-primary underline"
242
+ }
243
+ }
244
+ }
245
+ );
246
+ var Button = React2.forwardRef(
247
+ ({
248
+ asChild = false,
249
+ children,
250
+ childrenClassName,
251
+ className,
252
+ disabled,
253
+ hoverStyle,
254
+ icon,
255
+ iconLeft,
256
+ iconRight,
257
+ isLoading = false,
258
+ sideTooltip,
259
+ size,
260
+ tooltip,
261
+ variant,
262
+ ...props
263
+ }, ref) => {
264
+ const Comp = asChild ? Slot : "button";
265
+ const buttonNode = /* @__PURE__ */ jsxs5(
266
+ Comp,
267
+ {
268
+ className: cn(buttonVariants({ hoverStyle, size, variant }), isLoading && "relative opacity-40", className),
269
+ disabled: disabled === true || isLoading,
270
+ ref,
271
+ ...props,
272
+ children: [
273
+ iconLeft,
274
+ icon,
275
+ /* @__PURE__ */ jsx5("span", { className: cn("flex w-full items-center justify-center gap-2", childrenClassName), children }),
276
+ iconRight,
277
+ isLoading && /* @__PURE__ */ jsx5("div", { className: "absolute inset-0 flex items-center justify-center bg-black/10 backdrop-blur-sm", children: /* @__PURE__ */ jsx5(Spinner, { size: "sm" }) })
278
+ ]
279
+ }
280
+ );
281
+ return tooltip ? /* @__PURE__ */ jsx5(Tooltip, { childrenClassName: "flex items-center justify-center", message: tooltip, sideTooltip, children: buttonNode }) : buttonNode;
282
+ }
283
+ );
284
+ Button.displayName = "Button";
285
+
286
+ // src/components/command.tsx
287
+ import { MagnifyingGlassIcon } from "@radix-ui/react-icons";
288
+ import { Command as CommandPrimitive } from "cmdk";
289
+ import * as React4 from "react";
290
+
291
+ // src/components/dialog.tsx
292
+ import * as DialogPrimitive from "@radix-ui/react-dialog";
293
+ import { Cross2Icon } from "@radix-ui/react-icons";
294
+ import * as React3 from "react";
295
+ import { useTranslation as useTranslation2 } from "react-i18next";
296
+ import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
297
+ var Dialog = DialogPrimitive.Root;
298
+ var DialogTrigger = DialogPrimitive.Trigger;
299
+ var DialogPortal = DialogPrimitive.Portal;
300
+ var DialogClose = DialogPrimitive.Close;
301
+ var DialogOverlay = React3.forwardRef(({ className, isAbsolute = false, ...props }, ref) => /* @__PURE__ */ jsx6(
302
+ DialogPrimitive.Overlay,
303
+ {
304
+ className: cn(
305
+ "data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 bg-foreground/10 z-60 backdrop-blur-xs",
306
+ isAbsolute ? "absolute inset-0" : "fixed inset-0",
307
+ className
308
+ ),
309
+ ref,
310
+ ...props
311
+ }
312
+ ));
313
+ DialogOverlay.displayName = DialogPrimitive.Overlay.displayName;
314
+ var DialogContent = React3.forwardRef(
315
+ ({ children, className, container, isAbsolute = false, isCloseIcon = false, overlayClassName, ...props }, ref) => {
316
+ const { t } = useTranslation2("ui");
317
+ return /* @__PURE__ */ jsxs6(DialogPortal, { container, children: [
318
+ /* @__PURE__ */ jsx6(DialogOverlay, { className: overlayClassName, isAbsolute }),
319
+ /* @__PURE__ */ jsxs6(
320
+ DialogPrimitive.Content,
321
+ {
322
+ className: cn(
323
+ "bg-surface data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] z-70 grid w-[calc(100%-2rem)] max-w-lg translate-x-[-50%] translate-y-[-50%] gap-0 rounded-2xl p-6 px-0 shadow-lg duration-200 outline-none lg:px-0",
324
+ isAbsolute ? "absolute top-[50%] left-[50%]" : "fixed top-[50%] left-[50%]",
325
+ className
326
+ ),
327
+ ref,
328
+ ...props,
329
+ children: [
330
+ children,
331
+ isCloseIcon && /* @__PURE__ */ jsxs6(DialogPrimitive.Close, { className: "data-[state=open]:text-muted ring-offset-surface focus:ring-ring data-[state=open]:bg-hover border-border bg-border absolute top-11 right-8 flex h-8 w-8 min-w-8 cursor-pointer items-center justify-center rounded-full opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-none disabled:pointer-events-none", children: [
332
+ /* @__PURE__ */ jsx6(Cross2Icon, { className: "text-body hover:text-primary-dark h-4 w-4" }),
333
+ /* @__PURE__ */ jsx6("span", { className: "sr-only", children: t("dialog.close") })
334
+ ] })
335
+ ]
336
+ }
337
+ )
338
+ ] });
339
+ }
340
+ );
341
+ DialogContent.displayName = DialogPrimitive.Content.displayName;
342
+ var DialogHeader = ({ className, ...props }) => /* @__PURE__ */ jsx6("div", { className: cn("flex flex-col space-y-1.5 text-center sm:text-left", className), ...props });
343
+ DialogHeader.displayName = "DialogHeader";
344
+ var DialogFooter = ({ className, ...props }) => /* @__PURE__ */ jsx6(
345
+ "div",
346
+ {
347
+ className: cn("flex flex-col-reverse justify-center rounded-2xl sm:flex-row sm:space-x-2", className),
348
+ ...props
349
+ }
350
+ );
351
+ DialogFooter.displayName = "DialogFooter";
352
+ var DialogTitle = React3.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx6(
353
+ DialogPrimitive.Title,
354
+ {
355
+ className: cn("text-lg leading-none font-semibold tracking-tight", className),
356
+ ref,
357
+ ...props,
358
+ children: /* @__PURE__ */ jsx6("span", { children: props.children })
359
+ }
360
+ ));
361
+ DialogTitle.displayName = DialogPrimitive.Title.displayName;
362
+ var DialogDescription = React3.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx6(DialogPrimitive.Description, { className: cn("text-muted text-sm", className), ref, ...props, children: /* @__PURE__ */ jsx6("span", { children: props.children }) }));
363
+ DialogDescription.displayName = DialogPrimitive.Description.displayName;
364
+
365
+ // src/components/command.tsx
366
+ import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
367
+ var Command = React4.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx7(
368
+ CommandPrimitive,
369
+ {
370
+ className: cn("bg-surface text-foreground flex h-full w-full flex-col overflow-hidden rounded-md", className),
371
+ ref,
372
+ ...props
373
+ }
374
+ ));
375
+ Command.displayName = CommandPrimitive.displayName;
376
+ var CommandDialog = ({ children, ...props }) => {
377
+ return /* @__PURE__ */ jsx7(Dialog, { ...props, children: /* @__PURE__ */ jsx7(DialogContent, { className: "overflow-hidden p-0", children: /* @__PURE__ */ jsx7(Command, { className: "**:[[cmdk-group-heading]]:text-muted [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-input-wrapper]_svg]:h-5 [&_[cmdk-input-wrapper]_svg]:w-5 [&_[cmdk-item]_svg]:h-5 [&_[cmdk-item]_svg]:w-5 **:[[cmdk-group-heading]]:px-2 **:[[cmdk-group-heading]]:font-medium **:[[cmdk-group]]:px-2 **:[[cmdk-input]]:h-12 **:[[cmdk-item]]:px-2 **:[[cmdk-item]]:py-3", children }) }) });
378
+ };
379
+ var CommandInput = React4.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxs7("div", { className: "flex items-center border-b px-3", "cmdk-input-wrapper": "", children: [
380
+ /* @__PURE__ */ jsx7(MagnifyingGlassIcon, { className: "mr-2 h-4 w-4 shrink-0 opacity-50" }),
381
+ /* @__PURE__ */ jsx7(
382
+ CommandPrimitive.Input,
383
+ {
384
+ className: cn(
385
+ "placeholder:text-placeholder flex h-10 w-full rounded-md bg-transparent py-3 text-sm outline-none disabled:cursor-not-allowed disabled:opacity-50",
386
+ className
387
+ ),
388
+ ref,
389
+ ...props
390
+ }
391
+ )
392
+ ] }));
393
+ CommandInput.displayName = CommandPrimitive.Input.displayName;
394
+ var CommandList = React4.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx7(CommandPrimitive.List, { className: cn("max-h-75 overflow-x-hidden overflow-y-auto", className), ref, ...props }));
395
+ CommandList.displayName = CommandPrimitive.List.displayName;
396
+ var CommandEmpty = React4.forwardRef((props, ref) => /* @__PURE__ */ jsx7(CommandPrimitive.Empty, { className: "py-6 text-center text-sm", ref, ...props }));
397
+ CommandEmpty.displayName = CommandPrimitive.Empty.displayName;
398
+ var CommandGroup = React4.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx7(
399
+ CommandPrimitive.Group,
400
+ {
401
+ className: cn(
402
+ "text-foreground **:[[cmdk-group-heading]]:text-muted overflow-hidden p-1 **:[[cmdk-group-heading]]:px-2 **:[[cmdk-group-heading]]:py-1.5 **:[[cmdk-group-heading]]:text-xs **:[[cmdk-group-heading]]:font-medium",
403
+ className
404
+ ),
405
+ ref,
406
+ ...props
407
+ }
408
+ ));
409
+ CommandGroup.displayName = CommandPrimitive.Group.displayName;
410
+ var CommandSeparator = React4.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx7(CommandPrimitive.Separator, { className: cn("bg-border -mx-1 h-px", className), ref, ...props }));
411
+ CommandSeparator.displayName = CommandPrimitive.Separator.displayName;
412
+ var CommandItem = React4.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx7(
413
+ CommandPrimitive.Item,
414
+ {
415
+ className: cn(
416
+ "relative flex cursor-default items-center rounded-sm px-2 py-1.5 text-sm outline-none select-none data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50",
417
+ className
418
+ ),
419
+ ref,
420
+ ...props
421
+ }
422
+ ));
423
+ CommandItem.displayName = CommandPrimitive.Item.displayName;
424
+ var CommandShortcut = ({ className, ...props }) => {
425
+ return /* @__PURE__ */ jsx7("span", { className: cn("text-muted ml-auto text-xs tracking-widest", className), ...props });
426
+ };
427
+ CommandShortcut.displayName = "CommandShortcut";
428
+
429
+ // src/components/form.tsx
430
+ import { Slot as Slot2 } from "@radix-ui/react-slot";
431
+ import * as React6 from "react";
432
+ import { Controller, FormProvider, useFormContext } from "react-hook-form";
433
+
434
+ // src/components/label.tsx
435
+ import * as LabelPrimitive from "@radix-ui/react-label";
436
+ import { cva as cva2 } from "class-variance-authority";
437
+ import * as React5 from "react";
438
+ import { jsx as jsx8 } from "react/jsx-runtime";
439
+ var labelVariants = cva2("text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70");
440
+ var Label = React5.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx8(LabelPrimitive.Root, { className: cn(labelVariants(), className), ref, ...props }));
441
+ Label.displayName = LabelPrimitive.Root.displayName;
442
+
443
+ // src/components/form.tsx
444
+ import { jsx as jsx9 } from "react/jsx-runtime";
445
+ var Form = FormProvider;
446
+ var FormFieldContext = React6.createContext(null);
447
+ var FormField = ({
448
+ ...props
449
+ }) => {
450
+ return /* @__PURE__ */ jsx9(FormFieldContext.Provider, { value: { name: props.name }, children: /* @__PURE__ */ jsx9(Controller, { ...props }) });
451
+ };
452
+ var useFormField = () => {
453
+ const fieldContext = React6.useContext(FormFieldContext);
454
+ const itemContext = React6.useContext(FormItemContext);
455
+ const { formState, getFieldState } = useFormContext();
456
+ if (!fieldContext) {
457
+ throw new Error("useFormField must be used within <FormField>");
458
+ }
459
+ if (!itemContext) {
460
+ throw new Error("useFormField must be used within <FormItem>");
461
+ }
462
+ const fieldState = getFieldState(fieldContext.name, formState);
463
+ const { id } = itemContext;
464
+ return {
465
+ formDescriptionId: `${id}-form-item-description`,
466
+ formItemId: `${id}-form-item`,
467
+ formMessageId: `${id}-form-item-message`,
468
+ id,
469
+ name: fieldContext.name,
470
+ ...fieldState
471
+ };
472
+ };
473
+ var FormItemContext = React6.createContext(null);
474
+ var FormItem = React6.forwardRef(
475
+ ({ className, ...props }, ref) => {
476
+ const id = React6.useId();
477
+ return /* @__PURE__ */ jsx9(FormItemContext.Provider, { value: { id }, children: /* @__PURE__ */ jsx9("div", { className: cn("space-y-1", className), ref, ...props }) });
478
+ }
479
+ );
480
+ FormItem.displayName = "FormItem";
481
+ var FormLabel = React6.forwardRef(({ className, ...props }, ref) => {
482
+ const { error, formItemId } = useFormField();
483
+ return /* @__PURE__ */ jsx9(Label, { className: cn(error && "text-destructive", className), htmlFor: formItemId, ref, ...props });
484
+ });
485
+ FormLabel.displayName = "FormLabel";
486
+ var FormControl = React6.forwardRef(
487
+ ({ ...props }, ref) => {
488
+ const { error, formDescriptionId, formItemId, formMessageId } = useFormField();
489
+ return /* @__PURE__ */ jsx9(
490
+ Slot2,
491
+ {
492
+ "aria-describedby": !error ? `${formDescriptionId}` : `${formDescriptionId} ${formMessageId}`,
493
+ "aria-invalid": !!error,
494
+ id: formItemId,
495
+ ref,
496
+ ...props
497
+ }
498
+ );
499
+ }
500
+ );
501
+ FormControl.displayName = "FormControl";
502
+ var FormDescription = React6.forwardRef(
503
+ ({ className, ...props }, ref) => {
504
+ const { formDescriptionId } = useFormField();
505
+ return /* @__PURE__ */ jsx9("p", { className: cn("text-muted text-[0.8rem]", className), id: formDescriptionId, ref, ...props });
506
+ }
507
+ );
508
+ FormDescription.displayName = "FormDescription";
509
+ var FormMessage = React6.forwardRef(
510
+ ({ children, className, ...props }, ref) => {
511
+ const { error, formMessageId } = useFormField();
512
+ const body = error?.message ? String(error.message) : children;
513
+ if (!body) {
514
+ return null;
515
+ }
516
+ return /* @__PURE__ */ jsx9(
517
+ "p",
518
+ {
519
+ className: cn("text-destructive text-[0.8rem] font-medium", className),
520
+ id: formMessageId,
521
+ ref,
522
+ ...props,
523
+ children: body
524
+ }
525
+ );
526
+ }
527
+ );
528
+ FormMessage.displayName = "FormMessage";
529
+
530
+ // src/components/form-fields/input-field.tsx
531
+ import { useState } from "react";
532
+ import { useTranslation as useTranslation3 } from "react-i18next";
533
+ import { FaRegEye, FaRegEyeSlash } from "react-icons/fa6";
534
+ import { RxCross2 } from "react-icons/rx";
535
+
536
+ // src/components/input.tsx
537
+ import * as React7 from "react";
538
+ import { jsx as jsx10 } from "react/jsx-runtime";
539
+ var Input = React7.forwardRef(({ className, type, ...props }, ref) => {
540
+ return /* @__PURE__ */ jsx10(
541
+ "input",
542
+ {
543
+ className: cn(
544
+ inputBase,
545
+ inputFocus,
546
+ "file:border-0 file:bg-transparent file:text-base file:font-medium",
547
+ className
548
+ ),
549
+ onKeyDown: (e) => {
550
+ const key = e.key;
551
+ const allowedKeys = ["Backspace", "Tab", "Enter", "Escape", "ArrowLeft", "ArrowUp", "ArrowRight", "ArrowDown"];
552
+ if (allowedKeys.includes(key)) {
553
+ return;
554
+ }
555
+ if (!(key >= "0" && key <= "9") && type === "number") {
556
+ e.preventDefault();
557
+ }
558
+ if (type === "onlyText") {
559
+ const regex = /^[a-zA-ZáéíóúÁÉÍÓÚñÑ ]*$/;
560
+ if (!regex.test(key)) {
561
+ e.preventDefault();
562
+ }
563
+ }
564
+ },
565
+ ref,
566
+ type,
567
+ ...props
568
+ }
569
+ );
570
+ });
571
+ Input.displayName = "Input";
572
+
573
+ // src/components/form-fields/label-field.tsx
574
+ import { jsx as jsx11, jsxs as jsxs8 } from "react/jsx-runtime";
575
+ var LabelField = ({ label, labelClassName, name, visualRequired }) => {
576
+ return /* @__PURE__ */ jsxs8(
577
+ Label,
578
+ {
579
+ className: cn("text-body mb-2 text-start text-sm leading-none font-normal tracking-normal", labelClassName),
580
+ htmlFor: name,
581
+ children: [
582
+ /* @__PURE__ */ jsx11("span", { children: label }),
583
+ " ",
584
+ visualRequired && /* @__PURE__ */ jsx11("span", { className: "text-destructive", children: " *" })
585
+ ]
586
+ }
587
+ );
588
+ };
589
+
590
+ // src/components/form-fields/input-field.tsx
591
+ import { jsx as jsx12, jsxs as jsxs9 } from "react/jsx-runtime";
592
+ var InputField = ({
593
+ control,
594
+ disabled,
595
+ inputClassName,
596
+ isClearable,
597
+ label,
598
+ labelClassName,
599
+ mainClassName,
600
+ name,
601
+ onClear,
602
+ placeholder,
603
+ type = "text",
604
+ visualRequired
605
+ }) => {
606
+ const { t } = useTranslation3("ui");
607
+ const [isPasswordVisible, setIsPasswordVisible] = useState(false);
608
+ const togglePasswordVisibility = () => {
609
+ setIsPasswordVisible((prev) => !prev);
610
+ };
611
+ const isPassword = type === "password";
612
+ const inputType = isPassword ? isPasswordVisible ? "text" : "password" : type === "plate" ? "text" : type;
613
+ const isPlate = type === "plate";
614
+ return /* @__PURE__ */ jsx12(
615
+ FormField,
616
+ {
617
+ control,
618
+ name,
619
+ render: ({ field, fieldState }) => {
620
+ const hasError = !!fieldState.error;
621
+ return /* @__PURE__ */ jsxs9(FormItem, { className: cn("flex flex-col", mainClassName), children: [
622
+ /* @__PURE__ */ jsx12(
623
+ LabelField,
624
+ {
625
+ label,
626
+ labelClassName: cn(labelClassName, hasError && "text-destructive"),
627
+ name,
628
+ visualRequired
629
+ }
630
+ ),
631
+ /* @__PURE__ */ jsx12(FormControl, { children: /* @__PURE__ */ jsxs9("div", { className: "relative", children: [
632
+ /* @__PURE__ */ jsx12(
633
+ Input,
634
+ {
635
+ ...field,
636
+ autoComplete: isPassword ? "current-password" : void 0,
637
+ className: cn(
638
+ inputClassName,
639
+ isPlate && "uppercase",
640
+ hasError && "border-destructive",
641
+ isPassword && "pr-10 [&::-ms-reveal]:hidden"
642
+ ),
643
+ "data-no-password-toggle": true,
644
+ disabled,
645
+ maxLength: isPlate ? 6 : void 0,
646
+ min: type === "number" ? 0 : void 0,
647
+ onChange: (e) => {
648
+ let value = e.target.value;
649
+ if (isPlate) {
650
+ value = value.toUpperCase().replace(/[^A-Z0-9]/g, "").slice(0, 6);
651
+ }
652
+ field.onChange(value);
653
+ },
654
+ placeholder,
655
+ type: inputType,
656
+ value: field.value ?? ""
657
+ }
658
+ ),
659
+ /* @__PURE__ */ jsxs9("div", { className: "absolute inset-y-0 right-0 flex items-center space-x-2 pr-2", children: [
660
+ field.value && isClearable && /* @__PURE__ */ jsx12(
661
+ "button",
662
+ {
663
+ className: "focus:outline-none",
664
+ onClick: onClear,
665
+ title: t("inputField.clear"),
666
+ type: "button",
667
+ children: /* @__PURE__ */ jsx12(RxCross2, { size: 18 })
668
+ }
669
+ ),
670
+ type === "password" && /* @__PURE__ */ jsx12(
671
+ "button",
672
+ {
673
+ className: "focus:outline-none",
674
+ onClick: togglePasswordVisibility,
675
+ title: isPasswordVisible ? t("inputField.hidePassword") : t("inputField.showPassword"),
676
+ type: "button",
677
+ children: isPasswordVisible ? /* @__PURE__ */ jsx12(FaRegEye, { size: 18 }) : /* @__PURE__ */ jsx12(FaRegEyeSlash, { size: 20 })
678
+ }
679
+ )
680
+ ] })
681
+ ] }) }),
682
+ /* @__PURE__ */ jsx12(FormMessage, {})
683
+ ] });
684
+ }
685
+ }
686
+ );
687
+ };
688
+
689
+ // src/components/google-map-picker.tsx
690
+ import { AdvancedMarker, APIProvider, Map as Map2, useMap, useMapsLibrary } from "@vis.gl/react-google-maps";
691
+ import { useCallback, useEffect, useMemo, useRef, useState as useState2 } from "react";
692
+ import { jsx as jsx13, jsxs as jsxs10 } from "react/jsx-runtime";
693
+ var DEFAULT_CENTER = { lat: 4.711, lng: -74.0721 };
694
+ var PICKER_MAP_ID = "komensal-restaurant-map";
695
+ var SELECTED_ZOOM = 15;
696
+ var DEBOUNCE_MS = 300;
697
+ var CITY_ZOOM = 12;
698
+ var MapPickerContent = ({
699
+ centerOn,
700
+ disabled,
701
+ hasError,
702
+ locationQuery,
703
+ locationZoom,
704
+ onChange,
705
+ placeholder,
706
+ value
707
+ }) => {
708
+ const placesLib = useMapsLibrary("places");
709
+ const geocodingLib = useMapsLibrary("geocoding");
710
+ const map = useMap(PICKER_MAP_ID);
711
+ const onChangeRef = useRef(onChange);
712
+ const geocoder = useMemo(
713
+ () => geocodingLib ? new geocodingLib.Geocoder() : null,
714
+ [geocodingLib]
715
+ );
716
+ const debounceRef = useRef(null);
717
+ const [inputValue, setInputValue] = useState2(value);
718
+ const [suggestions, setSuggestions] = useState2([]);
719
+ const [showDropdown, setShowDropdown] = useState2(false);
720
+ const [sessionToken, setSessionToken] = useState2();
721
+ const [position, setPosition] = useState2(null);
722
+ useEffect(() => {
723
+ onChangeRef.current = onChange;
724
+ });
725
+ useEffect(() => {
726
+ setInputValue(value);
727
+ }, [value]);
728
+ useEffect(() => {
729
+ if (map && centerOn) {
730
+ map.panTo(centerOn);
731
+ map.setZoom(CITY_ZOOM);
732
+ }
733
+ }, [map, centerOn]);
734
+ useEffect(() => {
735
+ if (map && position) {
736
+ map.panTo(position);
737
+ map.setZoom(SELECTED_ZOOM);
738
+ }
739
+ }, [map, position]);
740
+ useEffect(() => {
741
+ if (!placesLib) return;
742
+ setSessionToken(new placesLib.AutocompleteSessionToken());
743
+ }, [placesLib]);
744
+ useEffect(() => {
745
+ if (!geocoder || !locationQuery || !map) return;
746
+ const g = geocoder;
747
+ const ctrl = { cancelled: false };
748
+ void (async () => {
749
+ try {
750
+ const { results } = await g.geocode({ address: locationQuery });
751
+ if (ctrl.cancelled || results.length === 0) return;
752
+ const loc = results[0].geometry.location;
753
+ map.panTo({ lat: loc.lat(), lng: loc.lng() });
754
+ map.setZoom(locationZoom ?? CITY_ZOOM);
755
+ } catch {
756
+ return;
757
+ }
758
+ })();
759
+ return () => {
760
+ ctrl.cancelled = true;
761
+ };
762
+ }, [geocoder, locationQuery, locationZoom, map]);
763
+ const fetchSuggestions = useCallback(
764
+ async (input) => {
765
+ if (!placesLib || input.length < 2) {
766
+ setSuggestions([]);
767
+ return;
768
+ }
769
+ try {
770
+ const result = await placesLib.AutocompleteSuggestion.fetchAutocompleteSuggestions({
771
+ input,
772
+ sessionToken
773
+ });
774
+ setSuggestions(result.suggestions);
775
+ setShowDropdown(true);
776
+ } catch {
777
+ setSuggestions([]);
778
+ }
779
+ },
780
+ [placesLib, sessionToken]
781
+ );
782
+ const reverseGeocode = useCallback(
783
+ async (latLng) => {
784
+ if (!geocoder) return;
785
+ try {
786
+ const { results } = await geocoder.geocode({ location: latLng });
787
+ if (results.length > 0) {
788
+ const address = results[0].formatted_address;
789
+ setInputValue(address);
790
+ onChangeRef.current(address);
791
+ }
792
+ } catch {
793
+ return;
794
+ }
795
+ },
796
+ [geocoder]
797
+ );
798
+ const handleInputChange = (e) => {
799
+ const val = e.target.value;
800
+ setInputValue(val);
801
+ onChangeRef.current(val);
802
+ if (debounceRef.current) clearTimeout(debounceRef.current);
803
+ debounceRef.current = setTimeout(() => void fetchSuggestions(val), DEBOUNCE_MS);
804
+ };
805
+ const handleSelect = async (suggestion) => {
806
+ const prediction = suggestion.placePrediction;
807
+ if (!prediction) return;
808
+ const place = prediction.toPlace();
809
+ await place.fetchFields({ fields: ["formattedAddress", "location"] });
810
+ const address = place.formattedAddress ?? prediction.text.text;
811
+ setInputValue(address);
812
+ onChangeRef.current(address);
813
+ setSuggestions([]);
814
+ setShowDropdown(false);
815
+ if (place.location) {
816
+ setPosition({ lat: place.location.lat(), lng: place.location.lng() });
817
+ }
818
+ if (placesLib) setSessionToken(new placesLib.AutocompleteSessionToken());
819
+ };
820
+ const handleBlur = () => {
821
+ setTimeout(() => setShowDropdown(false), 150);
822
+ };
823
+ const handleMapClick = useCallback(
824
+ (e) => {
825
+ if (disabled || !e.detail.latLng) return;
826
+ const latLng = e.detail.latLng;
827
+ setPosition(latLng);
828
+ void reverseGeocode(latLng);
829
+ },
830
+ [disabled, reverseGeocode]
831
+ );
832
+ const handleMarkerDragEnd = useCallback(
833
+ (e) => {
834
+ const latLng = e.latLng;
835
+ if (!latLng) return;
836
+ const pos = { lat: latLng.lat(), lng: latLng.lng() };
837
+ setPosition(pos);
838
+ void reverseGeocode(pos);
839
+ },
840
+ [reverseGeocode]
841
+ );
842
+ return /* @__PURE__ */ jsxs10("div", { className: "flex flex-col gap-3", children: [
843
+ /* @__PURE__ */ jsxs10("div", { className: "relative", children: [
844
+ /* @__PURE__ */ jsx13(
845
+ "input",
846
+ {
847
+ className: cn(inputBase, inputFocus, hasError && "border-destructive"),
848
+ disabled,
849
+ onBlur: handleBlur,
850
+ onChange: handleInputChange,
851
+ onFocus: () => suggestions.length > 0 && setShowDropdown(true),
852
+ placeholder,
853
+ type: "text",
854
+ value: inputValue
855
+ }
856
+ ),
857
+ showDropdown && suggestions.length > 0 && /* @__PURE__ */ jsx13("ul", { className: "border-border bg-surface absolute z-50 mt-1 w-full overflow-hidden rounded-[10px] border shadow-md", children: suggestions.map((suggestion) => /* @__PURE__ */ jsx13("li", { children: /* @__PURE__ */ jsx13(
858
+ "button",
859
+ {
860
+ className: "text-foreground hover:bg-hover w-full px-4 py-3 text-left text-sm transition-colors",
861
+ onClick: () => void handleSelect(suggestion),
862
+ type: "button",
863
+ children: suggestion.placePrediction?.text.text ?? ""
864
+ }
865
+ ) }, suggestion.placePrediction?.placeId ?? suggestion.placePrediction?.text.text)) })
866
+ ] }),
867
+ /* @__PURE__ */ jsx13("div", { className: "border-border h-59 overflow-hidden rounded-[10px] border md:h-87.5", children: /* @__PURE__ */ jsx13(
868
+ Map2,
869
+ {
870
+ defaultCenter: DEFAULT_CENTER,
871
+ defaultZoom: 5,
872
+ disableDefaultUI: true,
873
+ gestureHandling: "cooperative",
874
+ id: PICKER_MAP_ID,
875
+ mapId: import.meta.env.VITE_GOOGLE_MAPS_MAP_ID ?? "DEMO_MAP_ID",
876
+ onClick: handleMapClick,
877
+ style: { height: "100%", width: "100%" },
878
+ children: position && /* @__PURE__ */ jsx13(AdvancedMarker, { draggable: !disabled, onDragEnd: handleMarkerDragEnd, position })
879
+ }
880
+ ) })
881
+ ] });
882
+ };
883
+ var GoogleMapPicker = (props) => /* @__PURE__ */ jsx13(APIProvider, { apiKey: import.meta.env.VITE_GOOGLE_MAPS_API_KEY ?? "", language: "es", region: "CO", children: /* @__PURE__ */ jsx13(MapPickerContent, { ...props }) });
884
+
885
+ // src/components/form-fields/map-picker-field.tsx
886
+ import { jsx as jsx14, jsxs as jsxs11 } from "react/jsx-runtime";
887
+ var MapPickerField = ({
888
+ control,
889
+ label,
890
+ labelClassName,
891
+ mainClassName,
892
+ name,
893
+ visualRequired,
894
+ ...pickerProps
895
+ }) => /* @__PURE__ */ jsx14(
896
+ FormField,
897
+ {
898
+ control,
899
+ name,
900
+ render: ({ field, fieldState }) => /* @__PURE__ */ jsxs11(FormItem, { className: cn("flex flex-col", mainClassName), children: [
901
+ /* @__PURE__ */ jsx14(
902
+ LabelField,
903
+ {
904
+ label,
905
+ labelClassName: cn(labelClassName, fieldState.error && "text-destructive"),
906
+ name,
907
+ visualRequired
908
+ }
909
+ ),
910
+ /* @__PURE__ */ jsx14(FormControl, { children: /* @__PURE__ */ jsx14(
911
+ GoogleMapPicker,
912
+ {
913
+ ...pickerProps,
914
+ hasError: !!fieldState.error,
915
+ onChange: field.onChange,
916
+ value: field.value ?? ""
917
+ }
918
+ ) }),
919
+ /* @__PURE__ */ jsx14(FormMessage, {})
920
+ ] })
921
+ }
922
+ );
923
+
924
+ // src/components/otp-input.tsx
925
+ import { OTPInput, OTPInputContext } from "input-otp";
926
+ import React8 from "react";
927
+ import { jsx as jsx15, jsxs as jsxs12 } from "react/jsx-runtime";
928
+ function InputOTP({
929
+ className,
930
+ containerClassName,
931
+ ...props
932
+ }) {
933
+ return /* @__PURE__ */ jsx15(
934
+ OTPInput,
935
+ {
936
+ className: cn("disabled:cursor-not-allowed", className),
937
+ containerClassName: cn("flex items-center gap-2 has-disabled:opacity-50", containerClassName),
938
+ "data-slot": "input-otp",
939
+ ...props
940
+ }
941
+ );
942
+ }
943
+ function InputOTPGroup({ className, ...props }) {
944
+ return /* @__PURE__ */ jsx15("div", { className: cn("flex items-center gap-2", className), "data-slot": "input-otp-group", ...props });
945
+ }
946
+ function InputOTPSlot({
947
+ className,
948
+ index,
949
+ ...props
950
+ }) {
951
+ const inputOTPContext = React8.useContext(OTPInputContext);
952
+ const { char, hasFakeCaret, isActive } = inputOTPContext.slots[index] ?? {};
953
+ return /* @__PURE__ */ jsxs12(
954
+ "div",
955
+ {
956
+ className: cn(
957
+ "border-border text-foreground relative flex h-14 w-12 items-center justify-center rounded-[10px] border text-xl font-medium transition-all outline-none",
958
+ char ? "bg-brand-subtle" : "bg-transparent",
959
+ "data-[active=true]:border-primary data-[active=true]:ring-ring data-[active=true]:z-10 data-[active=true]:ring-2",
960
+ "aria-invalid:border-destructive data-[active=true]:aria-invalid:border-destructive data-[active=true]:aria-invalid:ring-destructive/40",
961
+ className
962
+ ),
963
+ "data-active": isActive,
964
+ "data-slot": "input-otp-slot",
965
+ ...props,
966
+ children: [
967
+ char,
968
+ hasFakeCaret && /* @__PURE__ */ jsx15("div", { className: "pointer-events-none absolute inset-0 flex items-center justify-center", children: /* @__PURE__ */ jsx15("div", { className: "animate-caret-blink bg-foreground h-6 w-px duration-1000" }) })
969
+ ]
970
+ }
971
+ );
972
+ }
973
+
974
+ // src/components/form-fields/otp-field.tsx
975
+ import { jsx as jsx16, jsxs as jsxs13 } from "react/jsx-runtime";
976
+ function OTPField({
977
+ autoFocus,
978
+ className,
979
+ containerClassName,
980
+ control,
981
+ disabled,
982
+ label,
983
+ labelClassName,
984
+ name,
985
+ otpLength = 6
986
+ }) {
987
+ return /* @__PURE__ */ jsx16(
988
+ FormField,
989
+ {
990
+ control,
991
+ name,
992
+ render: ({ field, fieldState }) => /* @__PURE__ */ jsxs13(FormItem, { className: cn("flex flex-col", className), children: [
993
+ label ? /* @__PURE__ */ jsx16(Label, { className: cn("text-start text-sm font-semibold", labelClassName), htmlFor: name, children: label }) : null,
994
+ /* @__PURE__ */ jsx16(FormControl, { children: /* @__PURE__ */ jsx16(
995
+ InputOTP,
996
+ {
997
+ "aria-invalid": fieldState.invalid || void 0,
998
+ autoComplete: "one-time-code",
999
+ autoFocus,
1000
+ containerClassName: cn("justify-center", containerClassName),
1001
+ disabled,
1002
+ id: name,
1003
+ inputMode: "numeric",
1004
+ maxLength: otpLength,
1005
+ onChange: (val) => field.onChange(val),
1006
+ onPaste: (e) => field.onChange(e.clipboardData.getData("text")),
1007
+ pattern: "[0-9]*",
1008
+ value: field.value ?? "",
1009
+ children: /* @__PURE__ */ jsx16(InputOTPGroup, { children: Array.from({ length: otpLength }).map((_, i) => /* @__PURE__ */ jsx16(InputOTPSlot, { "aria-invalid": fieldState.invalid || void 0, index: i }, i)) })
1010
+ }
1011
+ ) }),
1012
+ /* @__PURE__ */ jsx16(FormMessage, {})
1013
+ ] })
1014
+ }
1015
+ );
1016
+ }
1017
+
1018
+ // src/components/select-input.tsx
1019
+ import { ChevronDown, ChevronUp, Clock, XIcon } from "lucide-react";
1020
+ import { cloneElement, useCallback as useCallback2, useEffect as useEffect2, useMemo as useMemo2, useRef as useRef2, useState as useState3 } from "react";
1021
+ import { useTranslation as useTranslation4 } from "react-i18next";
1022
+
1023
+ // src/components/popover.tsx
1024
+ import * as PopoverPrimitive from "@radix-ui/react-popover";
1025
+ import * as React9 from "react";
1026
+ import { jsx as jsx17 } from "react/jsx-runtime";
1027
+ var Popover = PopoverPrimitive.Root;
1028
+ var PopoverTrigger = PopoverPrimitive.Trigger;
1029
+ var PopoverAnchor = PopoverPrimitive.Anchor;
1030
+ var PopoverContent = React9.forwardRef(({ align = "center", className, sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsx17(PopoverPrimitive.Portal, { children: /* @__PURE__ */ jsx17(
1031
+ PopoverPrimitive.Content,
1032
+ {
1033
+ align,
1034
+ className: cn(
1035
+ "text-foreground bg-surface data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-72 rounded-md border p-4 shadow-md outline-none",
1036
+ className
1037
+ ),
1038
+ ref,
1039
+ sideOffset,
1040
+ ...props
1041
+ }
1042
+ ) }));
1043
+ PopoverContent.displayName = PopoverPrimitive.Content.displayName;
1044
+
1045
+ // src/components/select-input.tsx
1046
+ import { Fragment as Fragment3, jsx as jsx18, jsxs as jsxs14 } from "react/jsx-runtime";
1047
+ var SelectInput = (props) => {
1048
+ const { t } = useTranslation4("ui");
1049
+ const {
1050
+ ableDeleteOption,
1051
+ className,
1052
+ disabled = false,
1053
+ error,
1054
+ items,
1055
+ labelKey = "label",
1056
+ leftIcon,
1057
+ loading = false,
1058
+ onBlur,
1059
+ onChange,
1060
+ onValueChangeCallBack = () => void 0,
1061
+ placeholder,
1062
+ placeholderClassName = "",
1063
+ search = false,
1064
+ timeField = false,
1065
+ value = "",
1066
+ valueKey = "value"
1067
+ } = props;
1068
+ const resolvedPlaceholder = placeholder ?? t("selectInput.placeholder");
1069
+ const divRef = useRef2(null);
1070
+ const [open, setOpen] = useState3(false);
1071
+ const [width, setWidth] = useState3(0);
1072
+ const [query, setQuery] = useState3("");
1073
+ const [valueItem, setValueItem] = useState3(value);
1074
+ const normalizeString = (str) => str.normalize("NFD").replace(/[̀-ͯ]/g, "").toLowerCase();
1075
+ const normalizedItems = useMemo2(() => {
1076
+ if (!items) return [];
1077
+ return items.map((it) => ({
1078
+ ...it,
1079
+ [labelKey]: String(it[labelKey]),
1080
+ [valueKey]: String(it[valueKey])
1081
+ }));
1082
+ }, [items, labelKey, valueKey]);
1083
+ const filteredOptions = useMemo2(() => {
1084
+ if (!query) return normalizedItems;
1085
+ return normalizedItems.filter(
1086
+ (el) => normalizeString(el[labelKey]).includes(normalizeString(query))
1087
+ );
1088
+ }, [normalizedItems, labelKey, query]);
1089
+ const onValueChange = useCallback2(
1090
+ (val) => {
1091
+ if (!normalizedItems.length) return;
1092
+ const item = normalizedItems.find((i) => i[valueKey] === val);
1093
+ if (item) {
1094
+ onValueChangeCallBack({
1095
+ label: item[labelKey],
1096
+ value: item[valueKey]
1097
+ });
1098
+ setValueItem(val);
1099
+ }
1100
+ },
1101
+ [normalizedItems, labelKey, valueKey, onValueChangeCallBack]
1102
+ );
1103
+ const buttonClassName = useMemo2(
1104
+ () => cn(
1105
+ inputBase,
1106
+ inputFocus,
1107
+ "hover:bg-surface",
1108
+ disabled && inputDisabled,
1109
+ error && "border-destructive",
1110
+ className
1111
+ ),
1112
+ [disabled, error, className]
1113
+ );
1114
+ const updateWidth = () => {
1115
+ if (divRef.current) {
1116
+ const { width: width2 } = divRef.current.getBoundingClientRect();
1117
+ setWidth(width2);
1118
+ }
1119
+ };
1120
+ useEffect2(() => {
1121
+ updateWidth();
1122
+ window.addEventListener("resize", updateWidth);
1123
+ return () => window.removeEventListener("resize", updateWidth);
1124
+ }, []);
1125
+ useEffect2(() => {
1126
+ setValueItem(value);
1127
+ }, [value]);
1128
+ return /* @__PURE__ */ jsx18("div", { className: "flex flex-col gap-1", children: /* @__PURE__ */ jsx18("div", { className: "relative flex flex-col justify-center", children: /* @__PURE__ */ jsxs14(Popover, { onOpenChange: setOpen, open, children: [
1129
+ /* @__PURE__ */ jsx18(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx18(
1130
+ Button,
1131
+ {
1132
+ "aria-expanded": open,
1133
+ className: buttonClassName,
1134
+ disabled,
1135
+ isLoading: loading,
1136
+ onBlur,
1137
+ ref: divRef,
1138
+ role: "combobox",
1139
+ variant: "primary",
1140
+ children: loading ? /* @__PURE__ */ jsxs14(Fragment3, { children: [
1141
+ t("selectInput.loading"),
1142
+ " ",
1143
+ /* @__PURE__ */ jsx18(Spinner, {})
1144
+ ] }) : /* @__PURE__ */ jsxs14("div", { className: "relative flex h-5 w-full items-center", children: [
1145
+ /* @__PURE__ */ jsxs14("div", { className: "flex w-full max-w-[90%] items-center truncate", children: [
1146
+ leftIcon && /* @__PURE__ */ jsx18("span", { className: "mr-2 shrink-0", children: cloneElement(leftIcon, { size: 20, strokeWidth: 1 }) }),
1147
+ valueItem ? filteredOptions.find((i) => i[valueKey] === valueItem)?.[labelKey] : /* @__PURE__ */ jsx18("span", { className: cn(inputPlaceholder, placeholderClassName), children: resolvedPlaceholder })
1148
+ ] }),
1149
+ timeField ? /* @__PURE__ */ jsx18("div", { className: "absolute top-0.5 right-0", children: /* @__PURE__ */ jsx18(Clock, { className: "ml-2 h-4 w-4 shrink-0 opacity-50" }) }) : /* @__PURE__ */ jsxs14("div", { className: "absolute top-0.5 right-0 flex gap-2", children: [
1150
+ ableDeleteOption && /* @__PURE__ */ jsx18(
1151
+ XIcon,
1152
+ {
1153
+ className: "z-100 h-4 w-4 shrink-0 opacity-50",
1154
+ onClick: (e) => {
1155
+ e.preventDefault();
1156
+ e.stopPropagation();
1157
+ onChange?.("");
1158
+ onValueChange("");
1159
+ setValueItem("");
1160
+ setQuery("");
1161
+ setOpen(false);
1162
+ }
1163
+ }
1164
+ ),
1165
+ !open ? /* @__PURE__ */ jsx18(ChevronDown, { className: "ml-2 h-4 w-4 shrink-0 opacity-50" }) : /* @__PURE__ */ jsx18(ChevronUp, { className: "ml-2 h-4 w-4 shrink-0 opacity-50" })
1166
+ ] })
1167
+ ] })
1168
+ }
1169
+ ) }),
1170
+ /* @__PURE__ */ jsx18(
1171
+ PopoverContent,
1172
+ {
1173
+ className: "bg-surface border-border z-100 rounded-sm p-1",
1174
+ onOpenAutoFocus: (e) => e.preventDefault(),
1175
+ style: { maxWidth: "auto", minWidth: `${width}px`, width: `${width}px` },
1176
+ children: /* @__PURE__ */ jsxs14(Command, { className: "flex w-full flex-col gap-2", children: [
1177
+ search && /* @__PURE__ */ jsx18(
1178
+ Input,
1179
+ {
1180
+ className: "mb-1 rounded-sm",
1181
+ onChange: (e) => setQuery(e.target.value),
1182
+ placeholder: t("selectInput.search"),
1183
+ value: query
1184
+ }
1185
+ ),
1186
+ /* @__PURE__ */ jsx18(CommandEmpty, { className: "text-center", children: t("selectInput.noResults") }),
1187
+ /* @__PURE__ */ jsx18(CommandList, { children: /* @__PURE__ */ jsx18(CommandGroup, { className: "p-0", children: filteredOptions.map((item) => {
1188
+ const labelValue = item[labelKey];
1189
+ const valueValue = item[valueKey];
1190
+ return /* @__PURE__ */ jsx18(
1191
+ CommandItem,
1192
+ {
1193
+ className: cn(
1194
+ "hover:bg-hover mt-0.5 mb-0.5 flex cursor-pointer items-center gap-2 rounded-sm py-2 pl-3",
1195
+ valueValue === value && "bg-inactive"
1196
+ ),
1197
+ onSelect: (currentValue) => {
1198
+ onChange?.(currentValue);
1199
+ onValueChange(currentValue);
1200
+ setOpen(false);
1201
+ setTimeout(() => setQuery(""), 100);
1202
+ },
1203
+ value: valueValue,
1204
+ children: labelValue.trim()
1205
+ },
1206
+ valueValue
1207
+ );
1208
+ }) }) })
1209
+ ] })
1210
+ }
1211
+ )
1212
+ ] }) }) });
1213
+ };
1214
+
1215
+ // src/components/form-fields/select-field.tsx
1216
+ import { jsx as jsx19, jsxs as jsxs15 } from "react/jsx-runtime";
1217
+ var SelectField = ({
1218
+ ableDeleteOption,
1219
+ className,
1220
+ control,
1221
+ disabled,
1222
+ label,
1223
+ labelClassName,
1224
+ mainClassName,
1225
+ name,
1226
+ options,
1227
+ placeholder,
1228
+ search,
1229
+ visualRequired
1230
+ }) => {
1231
+ return /* @__PURE__ */ jsx19(
1232
+ FormField,
1233
+ {
1234
+ control,
1235
+ name,
1236
+ render: ({ field, fieldState }) => {
1237
+ const hasError = !!fieldState.error;
1238
+ return /* @__PURE__ */ jsxs15(FormItem, { className: cn("flex flex-col", mainClassName), children: [
1239
+ /* @__PURE__ */ jsx19(
1240
+ LabelField,
1241
+ {
1242
+ label,
1243
+ labelClassName: cn(labelClassName, hasError && "text-destructive"),
1244
+ name,
1245
+ visualRequired
1246
+ }
1247
+ ),
1248
+ /* @__PURE__ */ jsx19(FormControl, { children: /* @__PURE__ */ jsx19(
1249
+ SelectInput,
1250
+ {
1251
+ ableDeleteOption,
1252
+ className,
1253
+ disabled,
1254
+ error: fieldState.error,
1255
+ items: options,
1256
+ onChange: field.onChange,
1257
+ placeholder,
1258
+ search,
1259
+ value: typeof field.value === "number" ? `${field.value}` : field.value
1260
+ }
1261
+ ) }),
1262
+ /* @__PURE__ */ jsx19(FormMessage, {})
1263
+ ] });
1264
+ }
1265
+ }
1266
+ );
1267
+ };
1268
+
1269
+ // src/components/loading.tsx
1270
+ import { jsx as jsx20 } from "react/jsx-runtime";
1271
+ function Loading({ className = "", isSpinner = true }) {
1272
+ return /* @__PURE__ */ jsx20("div", { className: cn("relative flex min-h-screen items-center justify-center gap-6", className), children: isSpinner && /* @__PURE__ */ jsx20("div", { className: "absolute right-0 bottom-0 m-10", children: /* @__PURE__ */ jsx20(Spinner, {}) }) });
1273
+ }
1274
+
1275
+ // src/components/password-checklist.tsx
1276
+ import { IoMdCheckmarkCircle, IoMdCloseCircle } from "react-icons/io";
1277
+ import { jsx as jsx21, jsxs as jsxs16 } from "react/jsx-runtime";
1278
+ var PasswordChecklist = ({ className, rules, value }) => {
1279
+ if (rules.length === 0) return null;
1280
+ return /* @__PURE__ */ jsx21("ul", { className: cn("flex flex-col gap-1", className), children: rules.map((rule) => {
1281
+ const isMet = rule.test(value);
1282
+ const Icon2 = isMet ? IoMdCheckmarkCircle : IoMdCloseCircle;
1283
+ return /* @__PURE__ */ jsxs16(
1284
+ "li",
1285
+ {
1286
+ className: cn(
1287
+ "flex items-center gap-2 text-xs transition-colors",
1288
+ isMet ? "text-success" : "text-inactive-text"
1289
+ ),
1290
+ children: [
1291
+ /* @__PURE__ */ jsx21(Icon2, { "aria-hidden": "true", className: "h-4 w-4 shrink-0" }),
1292
+ /* @__PURE__ */ jsx21("span", { children: rule.label })
1293
+ ]
1294
+ },
1295
+ rule.key
1296
+ );
1297
+ }) });
1298
+ };
1299
+
1300
+ // src/components/select.tsx
1301
+ import { CaretSortIcon, CheckIcon, ChevronDownIcon, ChevronUpIcon } from "@radix-ui/react-icons";
1302
+ import * as SelectPrimitive from "@radix-ui/react-select";
1303
+ import * as React11 from "react";
1304
+ import { jsx as jsx22, jsxs as jsxs17 } from "react/jsx-runtime";
1305
+ var Select = SelectPrimitive.Root;
1306
+ var SelectGroup = SelectPrimitive.Group;
1307
+ var SelectValue = SelectPrimitive.Value;
1308
+ var SelectTrigger = React11.forwardRef(({ children, className, ...props }, ref) => /* @__PURE__ */ jsxs17(
1309
+ SelectPrimitive.Trigger,
1310
+ {
1311
+ className: cn(
1312
+ "placeholder:text-placeholder border-border ring-offset-surface focus:ring-ring flex h-9 w-full items-center justify-between rounded-xl border bg-transparent px-3 py-2 text-sm whitespace-nowrap shadow-sm focus:ring-0 focus:outline-none disabled:cursor-not-allowed [&>span]:line-clamp-1",
1313
+ className
1314
+ ),
1315
+ ref,
1316
+ ...props,
1317
+ children: [
1318
+ children,
1319
+ /* @__PURE__ */ jsx22(SelectPrimitive.Icon, { asChild: true, children: /* @__PURE__ */ jsx22(CaretSortIcon, { className: "h-4 w-4 opacity-50" }) })
1320
+ ]
1321
+ }
1322
+ ));
1323
+ SelectTrigger.displayName = SelectPrimitive.Trigger.displayName;
1324
+ var SelectScrollUpButton = React11.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx22(
1325
+ SelectPrimitive.ScrollUpButton,
1326
+ {
1327
+ className: cn("flex cursor-default items-center justify-center py-1", className),
1328
+ ref,
1329
+ ...props,
1330
+ children: /* @__PURE__ */ jsx22(ChevronUpIcon, {})
1331
+ }
1332
+ ));
1333
+ SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName;
1334
+ var SelectScrollDownButton = React11.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx22(
1335
+ SelectPrimitive.ScrollDownButton,
1336
+ {
1337
+ className: cn("flex cursor-default items-center justify-center py-1", className),
1338
+ ref,
1339
+ ...props,
1340
+ children: /* @__PURE__ */ jsx22(ChevronDownIcon, {})
1341
+ }
1342
+ ));
1343
+ SelectScrollDownButton.displayName = SelectPrimitive.ScrollDownButton.displayName;
1344
+ var SelectContent = React11.forwardRef(({ children, className, position = "popper", ...props }, ref) => /* @__PURE__ */ jsx22(SelectPrimitive.Portal, { children: /* @__PURE__ */ jsxs17(
1345
+ SelectPrimitive.Content,
1346
+ {
1347
+ className: cn(
1348
+ "border-border text-foreground bg-surface data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 relative z-50 max-h-96 min-w-32 overflow-hidden rounded-lg border shadow-md",
1349
+ position === "popper" && "data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
1350
+ className
1351
+ ),
1352
+ position,
1353
+ ref,
1354
+ ...props,
1355
+ children: [
1356
+ /* @__PURE__ */ jsx22(SelectScrollUpButton, {}),
1357
+ /* @__PURE__ */ jsx22(
1358
+ SelectPrimitive.Viewport,
1359
+ {
1360
+ className: cn(
1361
+ "p-1",
1362
+ position === "popper" && "h-(--radix-select-trigger-height) w-full min-w-(--radix-select-trigger-width)"
1363
+ ),
1364
+ children
1365
+ }
1366
+ ),
1367
+ /* @__PURE__ */ jsx22(SelectScrollDownButton, {})
1368
+ ]
1369
+ }
1370
+ ) }));
1371
+ SelectContent.displayName = SelectPrimitive.Content.displayName;
1372
+ var SelectLabel = React11.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx22(SelectPrimitive.Label, { className: cn("px-2 py-1.5 text-sm font-semibold", className), ref, ...props }));
1373
+ SelectLabel.displayName = SelectPrimitive.Label.displayName;
1374
+ var SelectItem = React11.forwardRef(({ children, className, ...props }, ref) => /* @__PURE__ */ jsxs17(
1375
+ SelectPrimitive.Item,
1376
+ {
1377
+ className: cn(
1378
+ "focus:text-foreground focus:bg-hover relative flex w-full cursor-default items-center rounded-md py-1.5 pr-8 pl-2 text-sm outline-none select-none data-disabled:pointer-events-none data-disabled:opacity-50",
1379
+ className
1380
+ ),
1381
+ ref,
1382
+ ...props,
1383
+ children: [
1384
+ /* @__PURE__ */ jsx22("span", { className: "absolute right-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ jsx22(SelectPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx22(CheckIcon, { className: "h-4 w-4" }) }) }),
1385
+ /* @__PURE__ */ jsx22(SelectPrimitive.ItemText, { children: /* @__PURE__ */ jsx22("span", { children }) })
1386
+ ]
1387
+ }
1388
+ ));
1389
+ SelectItem.displayName = SelectPrimitive.Item.displayName;
1390
+ var SelectSeparator = React11.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx22(SelectPrimitive.Separator, { className: cn("bg-border -mx-1 my-1 h-px", className), ref, ...props }));
1391
+ SelectSeparator.displayName = SelectPrimitive.Separator.displayName;
1392
+
1393
+ // src/components/step-header.tsx
1394
+ import { jsx as jsx23, jsxs as jsxs18 } from "react/jsx-runtime";
1395
+ var StepHeader = ({ subtitle, subtitleClassName, title }) => /* @__PURE__ */ jsxs18("div", { className: "flex flex-col gap-1", children: [
1396
+ /* @__PURE__ */ jsx23("h1", { className: "text-title text-2xl font-bold", children: title }),
1397
+ subtitle !== void 0 && /* @__PURE__ */ jsx23("p", { className: cn("text-subtitle text-sm", subtitleClassName), children: subtitle })
1398
+ ] });
1399
+
1400
+ // src/components/stepper.tsx
1401
+ import { CheckIcon as CheckIcon2 } from "lucide-react";
1402
+ import { jsx as jsx24, jsxs as jsxs19 } from "react/jsx-runtime";
1403
+ var Stepper = ({ activeIndex, className, intermediate = false, steps }) => {
1404
+ return /* @__PURE__ */ jsx24("div", { className: cn("flex w-full items-start", className), children: steps.map((step, index) => {
1405
+ const isCompleted = intermediate ? index <= activeIndex : index < activeIndex;
1406
+ const isActive = !intermediate && index === activeIndex;
1407
+ return /* @__PURE__ */ jsxs19("div", { className: "flex flex-1 flex-col items-center", children: [
1408
+ /* @__PURE__ */ jsxs19("div", { className: "flex w-full items-center", children: [
1409
+ /* @__PURE__ */ jsx24(
1410
+ "div",
1411
+ {
1412
+ className: cn(
1413
+ "h-0.75 flex-1 self-center",
1414
+ isCompleted || isActive ? "bg-primary" : "bg-inactive",
1415
+ index === 0 && "rounded-l-full"
1416
+ )
1417
+ }
1418
+ ),
1419
+ /* @__PURE__ */ jsx24(
1420
+ "div",
1421
+ {
1422
+ "aria-current": isActive ? "step" : void 0,
1423
+ className: cn(
1424
+ "flex h-5.5 w-5.5 shrink-0 items-center justify-center rounded-full border text-xs font-semibold transition-colors md:h-6.5 md:w-6.5",
1425
+ isCompleted && "bg-primary border-primary text-inverse",
1426
+ isActive && "bg-primary border-primary text-inverse",
1427
+ !isCompleted && !isActive && "bg-inactive border-inactive text-surface"
1428
+ ),
1429
+ children: isCompleted ? /* @__PURE__ */ jsx24(CheckIcon2, { className: "h-4 w-4" }) : index + 1
1430
+ }
1431
+ ),
1432
+ /* @__PURE__ */ jsx24(
1433
+ "div",
1434
+ {
1435
+ className: cn(
1436
+ "relative h-0.75 flex-1 self-center",
1437
+ isCompleted ? "bg-primary" : "bg-inactive",
1438
+ index === steps.length - 1 && "rounded-r-full"
1439
+ ),
1440
+ children: index === 0 && /* @__PURE__ */ jsx24(
1441
+ "div",
1442
+ {
1443
+ className: cn(
1444
+ "absolute top-1/2 right-0 h-2.25 w-2.25 translate-x-1/2 -translate-y-1/2 rounded-full transition-colors",
1445
+ isCompleted ? "bg-primary" : "bg-inactive"
1446
+ )
1447
+ }
1448
+ )
1449
+ }
1450
+ )
1451
+ ] }),
1452
+ /* @__PURE__ */ jsx24("span", { className: cn("mt-1 text-xs font-normal", isCompleted || isActive ? "text-primary" : "text-muted"), children: step.label })
1453
+ ] }, step.label);
1454
+ }) });
1455
+ };
1456
+
1457
+ // src/components/toast/toast.tsx
1458
+ import { AlertTriangle, Check, X } from "lucide-react";
1459
+ import { useEffect as useEffect3, useMemo as useMemo3, useRef as useRef3, useState as useState4 } from "react";
1460
+ import { IoDocumentLockOutline, IoInformationCircle } from "react-icons/io5";
1461
+ import { jsx as jsx25, jsxs as jsxs20 } from "react/jsx-runtime";
1462
+ var EXIT_ANIMATION_MS = 200;
1463
+ function Toast({ duration = 2500, id, onClose, subtitle, title, type }) {
1464
+ const [leaving, setLeaving] = useState4(false);
1465
+ const startedAtRef = useRef3(Date.now());
1466
+ const timeoutRef = useRef3(null);
1467
+ const exitRef = useRef3(null);
1468
+ const Icon2 = useMemo3(() => {
1469
+ if (type === "success") return Check;
1470
+ if (type === "error") return X;
1471
+ if (type === "warning") return AlertTriangle;
1472
+ if (type === "info") return IoInformationCircle;
1473
+ return IoDocumentLockOutline;
1474
+ }, [type]);
1475
+ const styles = useMemo3(() => {
1476
+ if (type === "success") {
1477
+ return { border: "border-success", icon: "text-success", iconBorder: "border-success" };
1478
+ }
1479
+ if (type === "error") {
1480
+ return { border: "border-destructive", icon: "text-destructive", iconBorder: "border-destructive" };
1481
+ }
1482
+ if (type === "warning") {
1483
+ return { border: "border-warning", icon: "text-warning", iconBorder: "border-warning" };
1484
+ }
1485
+ if (type === "info") {
1486
+ return { border: "border-info", icon: "text-info", iconBorder: "border-info" };
1487
+ }
1488
+ return { border: "border-wait", icon: "text-wait", iconBorder: "border-wait" };
1489
+ }, [type]);
1490
+ useEffect3(() => {
1491
+ if (timeoutRef.current) clearTimeout(timeoutRef.current);
1492
+ if (exitRef.current) clearTimeout(exitRef.current);
1493
+ const elapsed = Date.now() - startedAtRef.current;
1494
+ const remaining = Math.max(0, duration - elapsed);
1495
+ timeoutRef.current = setTimeout(() => {
1496
+ setLeaving(true);
1497
+ exitRef.current = setTimeout(() => onClose(id), EXIT_ANIMATION_MS);
1498
+ }, remaining);
1499
+ return () => {
1500
+ if (timeoutRef.current) clearTimeout(timeoutRef.current);
1501
+ if (exitRef.current) clearTimeout(exitRef.current);
1502
+ };
1503
+ }, [id, duration, onClose]);
1504
+ return /* @__PURE__ */ jsxs20(
1505
+ "div",
1506
+ {
1507
+ "aria-live": "polite",
1508
+ className: [
1509
+ "relative",
1510
+ leaving ? "absolute top-0 right-0 left-0" : "",
1511
+ "flex w-108.5 max-w-[calc(100vw-2rem)] items-center justify-between",
1512
+ "min-h-16",
1513
+ "bg-surface rounded-[10px] border-2",
1514
+ "px-5 py-4.5",
1515
+ "shadow-[0_4px_20px_rgba(0,0,0,0.05)]",
1516
+ "transition-all duration-200 ease-out",
1517
+ styles.border,
1518
+ leaving ? "translate-y-2 opacity-0" : "translate-y-0 opacity-100"
1519
+ ].join(" "),
1520
+ role: "status",
1521
+ children: [
1522
+ /* @__PURE__ */ jsx25("div", { className: "min-w-0 pr-4", children: /* @__PURE__ */ jsx25("h4", { className: ["text-[16px] leading-normal font-semibold", "text-foreground", "line-clamp-2"].join(" "), children: title }) }),
1523
+ subtitle ? /* @__PURE__ */ jsx25("div", { className: "shrink-0 pr-4 text-left", children: /* @__PURE__ */ jsx25("div", { className: ["max-w-28 text-[14px] leading-[19.5px] font-normal", "text-body"].join(" "), children: subtitle }) }) : null,
1524
+ /* @__PURE__ */ jsx25(
1525
+ "div",
1526
+ {
1527
+ className: [
1528
+ "shrink-0",
1529
+ "flex h-8 w-8 min-w-8 items-center justify-center rounded-full border-2",
1530
+ styles.iconBorder
1531
+ ].join(" "),
1532
+ children: /* @__PURE__ */ jsx25(Icon2, { className: ["h-5 w-5", styles.icon].join(" ") })
1533
+ }
1534
+ )
1535
+ ]
1536
+ }
1537
+ );
1538
+ }
1539
+
1540
+ // src/components/toast/toast-provider.tsx
1541
+ import { useCallback as useCallback3, useEffect as useEffect4, useLayoutEffect, useMemo as useMemo4, useRef as useRef4, useState as useState5 } from "react";
1542
+ import { Fragment as Fragment4, jsx as jsx26 } from "react/jsx-runtime";
1543
+ function ToastProvider() {
1544
+ const [toasts, setToasts] = useState5([]);
1545
+ const itemRefs = useRef4(/* @__PURE__ */ new Map());
1546
+ const prevRects = useRef4(/* @__PURE__ */ new Map());
1547
+ const showToast = useCallback3((type, options) => {
1548
+ setToasts((prev) => [
1549
+ ...prev,
1550
+ {
1551
+ duration: 2500,
1552
+ id: crypto.randomUUID(),
1553
+ position: "top-right",
1554
+ type,
1555
+ ...options
1556
+ }
1557
+ ]);
1558
+ }, []);
1559
+ const removeToast = useCallback3((id) => {
1560
+ setToasts((prev) => prev.filter((t) => t.id !== id));
1561
+ }, []);
1562
+ useEffect4(() => {
1563
+ registerToastEmitter(showToast);
1564
+ return () => registerToastEmitter(null);
1565
+ }, [showToast]);
1566
+ const grouped = useMemo4(() => {
1567
+ return toasts.reduce((acc, toast2) => {
1568
+ const pos = toast2.position ?? "top";
1569
+ acc[pos] = [...acc[pos] ?? [], toast2];
1570
+ return acc;
1571
+ }, {});
1572
+ }, [toasts]);
1573
+ useLayoutEffect(() => {
1574
+ const newRects = /* @__PURE__ */ new Map();
1575
+ itemRefs.current.forEach((el, id) => {
1576
+ newRects.set(id, el.getBoundingClientRect());
1577
+ });
1578
+ newRects.forEach((newRect, id) => {
1579
+ const prevRect = prevRects.current.get(id);
1580
+ const el = itemRefs.current.get(id);
1581
+ if (!el || !prevRect) return;
1582
+ const dy = prevRect.top - newRect.top;
1583
+ if (dy === 0) return;
1584
+ el.style.transform = `translateY(${dy}px)`;
1585
+ el.style.transition = "transform 0s";
1586
+ requestAnimationFrame(() => {
1587
+ el.style.transition = "transform 200ms ease-out";
1588
+ el.style.transform = "";
1589
+ });
1590
+ });
1591
+ prevRects.current = newRects;
1592
+ }, [toasts]);
1593
+ const setItemRef = useCallback3((id) => {
1594
+ return (el) => {
1595
+ if (!el) {
1596
+ itemRefs.current.delete(id);
1597
+ prevRects.current.delete(id);
1598
+ return;
1599
+ }
1600
+ itemRefs.current.set(id, el);
1601
+ };
1602
+ }, []);
1603
+ return /* @__PURE__ */ jsx26(Fragment4, { children: Object.entries(grouped).map(([position, list]) => /* @__PURE__ */ jsx26("div", { className: `fixed z-4000 ${getPositionClass(position)}`, children: /* @__PURE__ */ jsx26("div", { className: "relative flex flex-col gap-3", children: list.map((toast2) => /* @__PURE__ */ jsx26("div", { ref: setItemRef(toast2.id), children: /* @__PURE__ */ jsx26(
1604
+ Toast,
1605
+ {
1606
+ duration: toast2.duration,
1607
+ id: toast2.id,
1608
+ onClose: removeToast,
1609
+ subtitle: toast2.subtitle,
1610
+ title: toast2.title,
1611
+ type: toast2.type
1612
+ }
1613
+ ) }, toast2.id)) }) }, position)) });
1614
+ }
1615
+ function getPositionClass(position) {
1616
+ const map = {
1617
+ bottom: "bottom-6 left-1/2 -translate-x-1/2",
1618
+ "bottom-left": "bottom-6 left-6",
1619
+ "bottom-right": "bottom-6 right-6",
1620
+ center: "top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2",
1621
+ "middle-bottom": "bottom-20 left-1/2 -translate-x-1/2",
1622
+ "middle-top": "top-20 left-1/2 -translate-x-1/2",
1623
+ top: "top-6 left-1/2 -translate-x-1/2",
1624
+ "top-left": "top-6 left-6",
1625
+ "top-right": "top-6 right-6"
1626
+ };
1627
+ return map[position];
1628
+ }
1629
+
1630
+ // src/components/wrapper.tsx
1631
+ import { jsx as jsx27 } from "react/jsx-runtime";
1632
+ var Wrapper = ({ children, className }) => {
1633
+ return /* @__PURE__ */ jsx27("div", { className: cn("mx-auto h-full w-full", className), children });
1634
+ };
1635
+ export {
1636
+ Alert,
1637
+ AuthHeader,
1638
+ Button,
1639
+ Command,
1640
+ CommandDialog,
1641
+ CommandEmpty,
1642
+ CommandGroup,
1643
+ CommandInput,
1644
+ CommandItem,
1645
+ CommandList,
1646
+ CommandSeparator,
1647
+ CommandShortcut,
1648
+ Dialog,
1649
+ DialogClose,
1650
+ DialogContent,
1651
+ DialogDescription,
1652
+ DialogFooter,
1653
+ DialogHeader,
1654
+ DialogOverlay,
1655
+ DialogPortal,
1656
+ DialogTitle,
1657
+ DialogTrigger,
1658
+ Form,
1659
+ FormControl,
1660
+ FormDescription,
1661
+ FormField,
1662
+ FormItem,
1663
+ FormLabel,
1664
+ FormMessage,
1665
+ GoogleMapPicker,
1666
+ Input,
1667
+ InputField,
1668
+ InputOTP,
1669
+ InputOTPGroup,
1670
+ InputOTPSlot,
1671
+ Label,
1672
+ LabelField,
1673
+ Loading,
1674
+ MapPickerField,
1675
+ OTPField,
1676
+ PasswordChecklist,
1677
+ Popover,
1678
+ PopoverAnchor,
1679
+ PopoverContent,
1680
+ PopoverTrigger,
1681
+ Select,
1682
+ SelectContent,
1683
+ SelectField,
1684
+ SelectGroup,
1685
+ SelectInput,
1686
+ SelectItem,
1687
+ SelectLabel,
1688
+ SelectScrollDownButton,
1689
+ SelectScrollUpButton,
1690
+ SelectSeparator,
1691
+ SelectTrigger,
1692
+ SelectValue,
1693
+ Spinner,
1694
+ StepHeader,
1695
+ Stepper,
1696
+ Toast,
1697
+ ToastProvider,
1698
+ Tooltip,
1699
+ Wrapper,
1700
+ buttonVariants,
1701
+ cn,
1702
+ inputBase,
1703
+ inputDisabled,
1704
+ inputFocus,
1705
+ inputPlaceholder,
1706
+ registerToastEmitter,
1707
+ toast,
1708
+ useFormField
1709
+ };
1710
+ //# sourceMappingURL=index.js.map