@komensal/ui 0.15.0 → 0.16.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.js CHANGED
@@ -1,134 +1,43 @@
1
- // src/components/add-tile.tsx
2
- import * as React from "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/color.ts
12
- function isLightColor(hex) {
13
- const normalized = hex.replace("#", "");
14
- const r = parseInt(normalized.slice(0, 2), 16);
15
- const g = parseInt(normalized.slice(2, 4), 16);
16
- const b = parseInt(normalized.slice(4, 6), 16);
17
- const luminance = (0.299 * r + 0.587 * g + 0.114 * b) / 255;
18
- return luminance > 0.6;
19
- }
20
-
21
- // src/utils/format.ts
22
- var DEFAULT_CURRENCY = "COP";
23
- var DEFAULT_LOCALE = "es-CO";
24
- function capitalize(value) {
25
- if (!value) return "";
26
- const trimmed = value.trimStart();
27
- if (trimmed.length === 0) return value;
28
- return trimmed.charAt(0).toLocaleUpperCase("es") + trimmed.slice(1);
29
- }
30
- function formatNumber(value, locale = DEFAULT_LOCALE) {
31
- return new Intl.NumberFormat(locale, { style: "decimal" }).format(value);
32
- }
33
- function formatPrice(value, locale = DEFAULT_LOCALE, currency = DEFAULT_CURRENCY) {
34
- return new Intl.NumberFormat(locale, {
35
- currency,
36
- maximumFractionDigits: 0,
37
- style: "currency"
38
- }).format(value);
39
- }
40
-
41
- // src/utils/styles.ts
42
- var inputSurface = cn(
43
- "w-full rounded-[10px] px-3 text-base font-normal",
44
- "border-border bg-surface text-foreground border",
45
- "transition-all duration-200 ease-in-out",
46
- "placeholder:text-icon-muted placeholder:text-sm placeholder:leading-none placeholder:font-normal",
47
- "disabled:bg-inactive disabled:text-inactive-text disabled:border-inactive disabled:placeholder:text-inactive-text disabled:cursor-not-allowed"
48
- );
49
- var inputBase = cn("flex !h-[50px] items-center justify-between gap-[10px]", inputSurface);
50
- var inputPlaceholder = cn("text-icon-muted text-sm leading-none font-normal");
51
- var inputDisabled = cn("cursor-not-allowed opacity-50");
52
- var inputCompact = cn(
53
- "border-border bg-surface text-foreground focus:border-primary focus:ring-ring h-9 w-full rounded-lg border px-2.5 text-sm focus:ring-2 focus:outline-none"
54
- );
55
- var inputFocus = cn(
56
- "focus:outline-none focus-visible:outline-none",
57
- "focus-visible:ring-ring focus-visible:border-primary focus-visible:ring-2",
58
- "data-[state=open]:ring-ring data-[state=open]:border-primary data-[state=open]:ring-2"
59
- );
60
-
61
- // src/utils/tag-emoji.ts
62
- var TAG_EMOJI_RULES = [
63
- { emoji: "\u{1F336}\uFE0F", keywords: ["picante", "picoso", "spicy"] },
64
- { emoji: "\u{1F95C}", keywords: ["nuez", "nueces", "mani", "cacahuate", "frutos secos"] },
65
- { emoji: "\u{1F331}", keywords: ["vegano", "vegetariano", "vegan"] },
66
- { emoji: "\u{1F33E}", keywords: ["sin gluten", "gluten free"] },
67
- { emoji: "\u{1F95B}", keywords: ["lacteos", "leche", "lactosa"] },
68
- { emoji: "\u{1F990}", keywords: ["marisco", "camaron"] },
69
- { emoji: "\u{1F525}", keywords: ["popular", "top ventas"] },
70
- { emoji: "\u{1F195}", keywords: ["nuevo", "new"] },
71
- { emoji: "\u{1F36C}", keywords: ["dulce"] },
72
- { emoji: "\u{1F9CA}", keywords: ["frio", "helado"] }
73
- ];
74
- function getTagEmoji(tag) {
75
- const normalized = normalize(tag);
76
- const match = TAG_EMOJI_RULES.find((rule) => rule.keywords.some((keyword) => normalized.includes(keyword)));
77
- return match?.emoji ?? null;
78
- }
79
- function normalize(text) {
80
- return text.toLowerCase().normalize("NFD").replace(/\p{Diacritic}/gu, "");
81
- }
82
-
83
- // src/utils/toast-emitter.ts
84
- var emitToast = null;
85
- var toast = {
86
- error(options) {
87
- emit("destructive", options);
88
- },
89
- info(options) {
90
- emit("info", options);
91
- },
92
- success(options) {
93
- emit("success", options);
94
- },
95
- wait(options) {
96
- emit("wait", options);
97
- },
98
- warning(options) {
99
- emit("warning", options);
100
- }
101
- };
102
- function registerToastEmitter(fn) {
103
- emitToast = fn;
104
- }
105
- function emit(type, options) {
106
- if (!emitToast) return;
107
- if (typeof options === "string") {
108
- emitToast(type, { title: options });
109
- } else {
110
- emitToast(type, options);
111
- }
112
- }
113
-
114
- // src/utils/url.ts
115
- function isSafeUrl(url) {
116
- try {
117
- const parsed = new URL(url, "https://placeholder.invalid");
118
- return parsed.protocol === "http:" || parsed.protocol === "https:";
119
- } catch {
120
- return false;
121
- }
122
- }
123
-
124
- // src/utils/z-index.ts
125
- var zPopover = "z-50";
126
- var zDialogOverlay = "z-60";
127
- var zDialogContent = "z-70";
128
- var zPopoverAboveDialog = "z-100";
129
- var zToast = "z-4000";
1
+ import {
2
+ Form,
3
+ FormControl,
4
+ FormField,
5
+ FormFieldShell,
6
+ FormItem,
7
+ FormMessage,
8
+ GoogleMapPicker,
9
+ Label,
10
+ LabelField,
11
+ MapPickerField,
12
+ capitalize,
13
+ cn,
14
+ focusRing,
15
+ formatNumber,
16
+ formatPrice,
17
+ getTagEmoji,
18
+ inputBase,
19
+ inputCompact,
20
+ inputDisabled,
21
+ inputFocus,
22
+ inputPlaceholder,
23
+ inputSurface,
24
+ isLightColor,
25
+ isSafeUrl,
26
+ registerToastEmitter,
27
+ toast,
28
+ useFormField,
29
+ zDialogContent,
30
+ zDialogOverlay,
31
+ zPopover,
32
+ zPopoverAboveDialog,
33
+ zToast
34
+ } from "./chunk-5VBG6IKL.js";
35
+ import {
36
+ ui_default
37
+ } from "./chunk-FDVY36KS.js";
130
38
 
131
39
  // src/components/add-tile.tsx
40
+ import * as React from "react";
132
41
  import { jsx, jsxs } from "react/jsx-runtime";
133
42
  var AddTile = React.forwardRef(
134
43
  ({ className, icon, label, labelClassName, ...props }, ref) => /* @__PURE__ */ jsxs(
@@ -165,22 +74,27 @@ var variantIcons = {
165
74
  success: CheckCircleIcon,
166
75
  warning: WarningIcon
167
76
  };
77
+ var variantRoles = {
78
+ destructive: "alert",
79
+ info: "status",
80
+ success: "status",
81
+ warning: "alert"
82
+ };
168
83
  var Alert = ({ children, className, variant = "destructive", ...props }) => {
169
84
  const styles = variantStyles[variant];
170
85
  const Icon = variantIcons[variant];
171
86
  return /* @__PURE__ */ jsxs2(
172
87
  "div",
173
88
  {
174
- "aria-live": "polite",
175
89
  className: cn(
176
90
  "flex items-center justify-center gap-2 rounded-[10px] px-4 py-3 text-sm",
177
91
  styles.container,
178
92
  className
179
93
  ),
180
- role: "alert",
94
+ role: variantRoles[variant],
181
95
  ...props,
182
96
  children: [
183
- /* @__PURE__ */ jsx2(Icon, { className: cn("h-5 w-5 shrink-0", styles.icon) }),
97
+ /* @__PURE__ */ jsx2(Icon, { "aria-hidden": true, className: cn("h-5 w-5 shrink-0", styles.icon) }),
184
98
  /* @__PURE__ */ jsx2("span", { children })
185
99
  ]
186
100
  }
@@ -208,64 +122,9 @@ var AuthHeader = ({
208
122
  // src/components/breadcrumb.tsx
209
123
  import * as React3 from "react";
210
124
 
211
- // src/components/skeleton.tsx
212
- import * as React2 from "react";
213
- import { jsx as jsx4 } from "react/jsx-runtime";
214
- var Skeleton = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx4("div", { className: cn("bg-inactive animate-pulse rounded-md", className), ref, ...props }));
215
- Skeleton.displayName = "Skeleton";
216
-
217
- // src/components/breadcrumb.tsx
218
- import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
219
- var Breadcrumb = React3.forwardRef(({ className, items, ...props }, ref) => /* @__PURE__ */ jsx5("div", { className: cn("flex items-center gap-1 text-sm", className), ref, ...props, children: items.map((item, index) => {
220
- const isLast = index === items.length - 1;
221
- return /* @__PURE__ */ jsxs4("span", { className: "flex items-center gap-1", children: [
222
- index > 0 && /* @__PURE__ */ jsx5("span", { className: "text-muted", children: "\u203A" }),
223
- item.loading ? /* @__PURE__ */ jsx5(Skeleton, { className: "h-4 w-20" }) : item.onClick && !isLast ? /* @__PURE__ */ jsx5("button", { className: "text-muted hover:text-foreground transition-colors", onClick: item.onClick, type: "button", children: item.label }) : /* @__PURE__ */ jsx5("span", { className: isLast ? "text-foreground font-semibold" : "text-muted font-normal", children: item.label })
224
- ] }, `${item.label}-${index}`);
225
- }) }));
226
- Breadcrumb.displayName = "Breadcrumb";
227
-
228
- // src/components/button.tsx
229
- import { Slot } from "@radix-ui/react-slot";
230
- import { cva } from "class-variance-authority";
231
- import * as React5 from "react";
232
-
233
- // src/components/spinner.tsx
234
- import clsx2 from "clsx";
235
-
236
125
  // src/lib/i18n.ts
237
126
  import i18n from "i18next";
238
127
  import { initReactI18next, useTranslation } from "react-i18next";
239
-
240
- // src/locales/es/ui.json
241
- var ui_default = {
242
- inputField: {
243
- showPassword: "Mostrar contrase\xF1a",
244
- hidePassword: "Ocultar contrase\xF1a",
245
- clear: "Limpiar"
246
- },
247
- dialog: {
248
- close: "Cerrar"
249
- },
250
- selectInput: {
251
- placeholder: "Selecciona...",
252
- loading: "Cargando...",
253
- search: "Buscar...",
254
- noResults: "Sin resultados.",
255
- clear: "Limpiar selecci\xF3n"
256
- },
257
- passwordChecklist: {
258
- minLength: "M\xEDnimo {{min}} caracteres",
259
- hasUpperAndLower: "Una may\xFAscula y min\xFAscula",
260
- hasNumber: "Un n\xFAmero",
261
- hasSpecialChar: "Un car\xE1cter especial"
262
- },
263
- spinner: {
264
- loading: "Cargando..."
265
- }
266
- };
267
-
268
- // src/lib/i18n.ts
269
128
  var uiI18n = i18n.createInstance();
270
129
  void uiI18n.use(initReactI18next).init({
271
130
  defaultNS: "ui",
@@ -278,7 +137,48 @@ void uiI18n.use(initReactI18next).init({
278
137
  var setUiLanguage = (lng) => uiI18n.changeLanguage(lng);
279
138
  var useUiT = () => useTranslation("ui", { i18n: uiI18n }).t;
280
139
 
140
+ // src/components/skeleton.tsx
141
+ import * as React2 from "react";
142
+ import { jsx as jsx4 } from "react/jsx-runtime";
143
+ var Skeleton = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx4("div", { className: cn("bg-inactive animate-pulse rounded-md", className), ref, ...props }));
144
+ Skeleton.displayName = "Skeleton";
145
+
146
+ // src/components/breadcrumb.tsx
147
+ import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
148
+ var Breadcrumb = React3.forwardRef(({ className, items, ...props }, ref) => {
149
+ const t = useUiT();
150
+ return /* @__PURE__ */ jsx5("nav", { "aria-label": t("breadcrumb.label"), ref, ...props, children: /* @__PURE__ */ jsx5("ol", { className: cn("flex items-center gap-1 text-sm", className), children: items.map((item, index) => {
151
+ const isLast = index === items.length - 1;
152
+ return /* @__PURE__ */ jsxs4("li", { className: "flex items-center gap-1", children: [
153
+ index > 0 && /* @__PURE__ */ jsx5("span", { "aria-hidden": true, className: "text-muted", children: "\u203A" }),
154
+ item.loading ? /* @__PURE__ */ jsx5(Skeleton, { className: "h-4 w-20" }) : item.onClick && !isLast ? /* @__PURE__ */ jsx5(
155
+ "button",
156
+ {
157
+ className: cn("text-muted hover:text-foreground rounded-sm transition-colors", focusRing),
158
+ onClick: item.onClick,
159
+ type: "button",
160
+ children: item.label
161
+ }
162
+ ) : /* @__PURE__ */ jsx5(
163
+ "span",
164
+ {
165
+ "aria-current": isLast ? "page" : void 0,
166
+ className: isLast ? "text-foreground font-semibold" : "text-muted font-normal",
167
+ children: item.label
168
+ }
169
+ )
170
+ ] }, `${item.label}-${index}`);
171
+ }) }) });
172
+ });
173
+ Breadcrumb.displayName = "Breadcrumb";
174
+
175
+ // src/components/button.tsx
176
+ import { Slot } from "@radix-ui/react-slot";
177
+ import { cva } from "class-variance-authority";
178
+ import * as React5 from "react";
179
+
281
180
  // src/components/spinner.tsx
181
+ import clsx from "clsx";
282
182
  import { Fragment as Fragment2, jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
283
183
  var sizes = {
284
184
  lg: "70",
@@ -298,13 +198,15 @@ var Spinner = ({ className = "", loadingLabel, size = "md", variant = "primary"
298
198
  /* @__PURE__ */ jsx6(
299
199
  "svg",
300
200
  {
201
+ "aria-hidden": true,
301
202
  fill: "currentColor",
203
+ focusable: "false",
302
204
  height: sizes[size],
303
205
  stroke: variants[variant],
304
206
  viewBox: "0 0 100 100",
305
207
  width: sizes[size],
306
208
  xmlns: "http://www.w3.org/2000/svg",
307
- children: /* @__PURE__ */ jsxs5("g", { className: clsx2("spinner_V8m1", className), children: [
209
+ children: /* @__PURE__ */ jsxs5("g", { className: clsx(className), children: [
308
210
  /* @__PURE__ */ jsx6("circle", { cx: "50", cy: "50", fill: "none", opacity: "0.25", r: "35", stroke: "currentColor", strokeWidth: "10" }),
309
211
  /* @__PURE__ */ jsx6(
310
212
  "circle",
@@ -332,7 +234,7 @@ var Spinner = ({ className = "", loadingLabel, size = "md", variant = "primary"
332
234
  ] })
333
235
  }
334
236
  ),
335
- /* @__PURE__ */ jsx6("span", { className: "sr-only", children: loadingLabel ?? t("spinner.loading") })
237
+ /* @__PURE__ */ jsx6("span", { className: "sr-only", role: "status", children: loadingLabel ?? t("spinner.loading") })
336
238
  ] });
337
239
  };
338
240
 
@@ -357,10 +259,10 @@ var TooltipContent = React4.forwardRef(({ className, sideOffset = 4, ...props },
357
259
  ) }));
358
260
  TooltipContent.displayName = TooltipPrimitive.Content.displayName;
359
261
  var Tooltip = React4.forwardRef(
360
- ({ children, childrenClassName, className, message, sideTooltip = "top" }, ref) => {
262
+ ({ asChild = false, children, childrenClassName, className, message, sideTooltip = "top" }, ref) => {
361
263
  return /* @__PURE__ */ jsx7(TooltipProvider, { children: /* @__PURE__ */ jsxs6(TooltipRoot, { children: [
362
- /* @__PURE__ */ jsx7(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx7("div", { className: cn("", childrenClassName), ref, children }) }),
363
- /* @__PURE__ */ jsx7(TooltipContent, { className: cn("", className), side: sideTooltip, children: /* @__PURE__ */ jsx7("p", { children: message }) })
264
+ /* @__PURE__ */ jsx7(TooltipTrigger, { asChild: true, children: asChild ? children : /* @__PURE__ */ jsx7("div", { className: childrenClassName, ref, children }) }),
265
+ /* @__PURE__ */ jsx7(TooltipContent, { className, side: sideTooltip, children: /* @__PURE__ */ jsx7("p", { children: message }) })
364
266
  ] }) });
365
267
  }
366
268
  );
@@ -369,7 +271,10 @@ Tooltip.displayName = "Tooltip";
369
271
  // src/components/button.tsx
370
272
  import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
371
273
  var buttonVariants = cva(
372
- "w-full inline-flex items-center justify-center gap-[10px] whitespace-nowrap rounded-[10px] 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",
274
+ [
275
+ "w-full inline-flex items-center justify-center gap-[10px] whitespace-nowrap rounded-[10px] border border-transparent text-base font-semibold transition-all duration-300 ease-in-out focus-visible:ring-offset-2 disabled:pointer-events-none disabled:bg-inactive disabled:text-inactive-text disabled:border-transparent cursor-pointer",
276
+ focusRing
277
+ ],
373
278
  {
374
279
  defaultVariants: {
375
280
  hoverStyle: "none",
@@ -387,7 +292,7 @@ var buttonVariants = cva(
387
292
  hover:-translate-y-[1px] hover:shadow-lg
388
293
  before:content-[''] before:absolute before:top-0 before:left-[-100%]
389
294
  before:w-full before:h-full
390
- before:bg-[linear-gradient(90deg,transparent,rgba(255,255,255,0.15),transparent)]
295
+ before:bg-linear-to-r before:from-transparent before:via-inverse/15 before:to-transparent
391
296
  before:transition-all before:duration-300
392
297
  hover:before:left-[100%]
393
298
  `
@@ -438,16 +343,22 @@ var Button = React5.forwardRef(
438
343
  Comp,
439
344
  {
440
345
  "aria-busy": isLoading || void 0,
441
- className: cn(buttonVariants({ hoverStyle, size, variant }), isLoading && "relative opacity-40", className),
346
+ className: cn(buttonVariants({ hoverStyle, size, variant }), isLoading && "relative", className),
442
347
  disabled: disabled === true || isLoading,
443
348
  ref,
444
349
  ...props,
445
350
  children: [
446
- iconLeft,
447
- icon,
448
- /* @__PURE__ */ jsx8("span", { className: cn("flex w-full items-center justify-center gap-2", childrenClassName), children }),
449
- iconRight,
450
- isLoading && /* @__PURE__ */ jsx8("div", { className: "absolute inset-0 flex items-center justify-center bg-black/10 backdrop-blur-sm", children: /* @__PURE__ */ jsx8(Spinner, { size: "sm" }) })
351
+ isLoading ? /* @__PURE__ */ jsx8("span", { className: "invisible contents", children: iconLeft }) : iconLeft,
352
+ isLoading ? /* @__PURE__ */ jsx8("span", { className: "invisible contents", children: icon }) : icon,
353
+ /* @__PURE__ */ jsx8(
354
+ "span",
355
+ {
356
+ className: cn("flex w-full items-center justify-center gap-2", isLoading && "invisible", childrenClassName),
357
+ children
358
+ }
359
+ ),
360
+ isLoading ? /* @__PURE__ */ jsx8("span", { className: "invisible contents", children: iconRight }) : iconRight,
361
+ isLoading && /* @__PURE__ */ jsx8("div", { className: "absolute inset-0 flex items-center justify-center rounded-[inherit]", children: /* @__PURE__ */ jsx8(Spinner, { size: "sm" }) })
451
362
  ]
452
363
  }
453
364
  );
@@ -461,7 +372,10 @@ import { cva as cva2 } from "class-variance-authority";
461
372
  import * as React6 from "react";
462
373
  import { jsx as jsx9 } from "react/jsx-runtime";
463
374
  var chipVariants = cva2(
464
- "focus-visible:ring-ring inline-flex cursor-pointer items-center justify-center rounded-full px-3 py-1.5 text-sm font-medium whitespace-nowrap transition-colors focus-visible:ring-2 focus-visible:outline-none",
375
+ [
376
+ "inline-flex cursor-pointer items-center justify-center rounded-full px-3 py-1.5 text-sm font-medium whitespace-nowrap transition-colors",
377
+ focusRing
378
+ ],
465
379
  {
466
380
  defaultVariants: {
467
381
  active: false
@@ -474,7 +388,16 @@ var chipVariants = cva2(
474
388
  }
475
389
  }
476
390
  );
477
- var Chip = React6.forwardRef(({ active, className, ...props }, ref) => /* @__PURE__ */ jsx9("button", { className: cn(chipVariants({ active }), className), ref, type: "button", ...props }));
391
+ var Chip = React6.forwardRef(({ active, className, ...props }, ref) => /* @__PURE__ */ jsx9(
392
+ "button",
393
+ {
394
+ "aria-pressed": active ?? void 0,
395
+ className: cn(chipVariants({ active }), className),
396
+ ref,
397
+ type: "button",
398
+ ...props
399
+ }
400
+ ));
478
401
  Chip.displayName = "Chip";
479
402
 
480
403
  // src/components/command.tsx
@@ -513,7 +436,7 @@ var DialogContent = React7.forwardRef(
513
436
  DialogPrimitive.Content,
514
437
  {
515
438
  className: cn(
516
- `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%] ${zDialogContent} grid w-[calc(100%-2rem)] max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 rounded-2xl p-6 shadow-lg duration-200 outline-none`,
439
+ `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 ${zDialogContent} grid w-[calc(100%-2rem)] max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 rounded-2xl p-6 shadow-lg duration-200 outline-none`,
517
440
  isAbsolute ? "absolute top-[50%] left-[50%]" : "fixed top-[50%] left-[50%]",
518
441
  className
519
442
  ),
@@ -521,10 +444,19 @@ var DialogContent = React7.forwardRef(
521
444
  ...props,
522
445
  children: [
523
446
  children,
524
- isCloseIcon && /* @__PURE__ */ jsxs8(DialogPrimitive.Close, { className: "data-[state=open]:text-muted ring-offset-surface focus:ring-ring data-[state=open]:bg-hover hover:bg-hover absolute top-5 right-5 flex h-8 w-8 min-w-8 cursor-pointer items-center justify-center rounded-full bg-transparent opacity-70 transition-all hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-none disabled:pointer-events-none", children: [
525
- /* @__PURE__ */ jsx10(XIcon, { className: "text-body h-4 w-4" }),
526
- /* @__PURE__ */ jsx10("span", { className: "sr-only", children: closeLabel ?? t("dialog.close") })
527
- ] })
447
+ isCloseIcon && /* @__PURE__ */ jsxs8(
448
+ DialogPrimitive.Close,
449
+ {
450
+ className: cn(
451
+ "data-[state=open]:text-muted ring-offset-surface data-[state=open]:bg-hover hover:bg-hover absolute top-5 right-5 flex h-8 w-8 min-w-8 cursor-pointer items-center justify-center rounded-full bg-transparent opacity-70 transition-all hover:opacity-100 focus-visible:opacity-100 focus-visible:ring-offset-2 disabled:pointer-events-none",
452
+ focusRing
453
+ ),
454
+ children: [
455
+ /* @__PURE__ */ jsx10(XIcon, { "aria-hidden": true, className: "text-body h-4 w-4" }),
456
+ /* @__PURE__ */ jsx10("span", { className: "sr-only", children: closeLabel ?? t("dialog.close") })
457
+ ]
458
+ }
459
+ )
528
460
  ]
529
461
  }
530
462
  )
@@ -541,12 +473,11 @@ var DialogTitle = React7.forwardRef(({ className, ...props }, ref) => /* @__PURE
541
473
  {
542
474
  className: cn("text-lg leading-none font-semibold tracking-tight", className),
543
475
  ref,
544
- ...props,
545
- children: /* @__PURE__ */ jsx10("span", { children: props.children })
476
+ ...props
546
477
  }
547
478
  ));
548
479
  DialogTitle.displayName = DialogPrimitive.Title.displayName;
549
- var DialogDescription = React7.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx10(DialogPrimitive.Description, { className: cn("text-muted text-sm", className), ref, ...props, children: /* @__PURE__ */ jsx10("span", { children: props.children }) }));
480
+ var DialogDescription = React7.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx10(DialogPrimitive.Description, { className: cn("text-muted text-sm", className), ref, ...props }));
550
481
  DialogDescription.displayName = DialogPrimitive.Description.displayName;
551
482
 
552
483
  // src/components/command.tsx
@@ -563,8 +494,8 @@ Command.displayName = CommandPrimitive.displayName;
563
494
  var CommandDialog = ({ children, ...props }) => {
564
495
  return /* @__PURE__ */ jsx11(Dialog, { ...props, children: /* @__PURE__ */ jsx11(DialogContent, { className: "overflow-hidden p-0", children: /* @__PURE__ */ jsx11(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 }) }) });
565
496
  };
566
- var CommandInput = React8.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxs9("div", { className: "flex items-center border-b px-3", "cmdk-input-wrapper": "", children: [
567
- /* @__PURE__ */ jsx11(MagnifyingGlassIcon, { className: "mr-2 h-4 w-4 shrink-0 opacity-50" }),
497
+ var CommandInput = React8.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxs9("div", { className: "border-border flex items-center border-b px-3", "cmdk-input-wrapper": "", children: [
498
+ /* @__PURE__ */ jsx11(MagnifyingGlassIcon, { "aria-hidden": true, className: "mr-2 h-4 w-4 shrink-0 opacity-50" }),
568
499
  /* @__PURE__ */ jsx11(
569
500
  CommandPrimitive.Input,
570
501
  {
@@ -613,93 +544,29 @@ var CommandShortcut = ({ className, ...props }) => {
613
544
  };
614
545
  CommandShortcut.displayName = "CommandShortcut";
615
546
 
616
- // src/components/form.tsx
617
- import { Slot as Slot2 } from "@radix-ui/react-slot";
618
- import * as React9 from "react";
619
- import { Controller, FormProvider, useFormContext } from "react-hook-form";
620
- import { jsx as jsx12 } from "react/jsx-runtime";
621
- var Form = FormProvider;
622
- var FormFieldContext = React9.createContext(null);
623
- var FormField = ({
624
- ...props
625
- }) => {
626
- return /* @__PURE__ */ jsx12(FormFieldContext.Provider, { value: { name: props.name }, children: /* @__PURE__ */ jsx12(Controller, { ...props }) });
627
- };
628
- var useFormField = () => {
629
- const fieldContext = React9.useContext(FormFieldContext);
630
- const itemContext = React9.useContext(FormItemContext);
631
- const { formState, getFieldState } = useFormContext();
632
- if (!fieldContext) {
633
- throw new Error("useFormField must be used within <FormField>");
634
- }
635
- if (!itemContext) {
636
- throw new Error("useFormField must be used within <FormItem>");
637
- }
638
- const fieldState = getFieldState(fieldContext.name, formState);
639
- const { id } = itemContext;
640
- return {
641
- formDescriptionId: `${id}-form-item-description`,
642
- formItemId: `${id}-form-item`,
643
- formMessageId: `${id}-form-item-message`,
644
- id,
645
- name: fieldContext.name,
646
- ...fieldState
647
- };
648
- };
649
- var FormItemContext = React9.createContext(null);
650
- var FormItem = React9.forwardRef(
651
- ({ className, ...props }, ref) => {
652
- const id = React9.useId();
653
- return /* @__PURE__ */ jsx12(FormItemContext.Provider, { value: { id }, children: /* @__PURE__ */ jsx12("div", { className: cn("space-y-1", className), ref, ...props }) });
654
- }
655
- );
656
- FormItem.displayName = "FormItem";
657
- var FormControl = React9.forwardRef(
658
- ({ ...props }, ref) => {
659
- const { error, formDescriptionId, formItemId, formMessageId } = useFormField();
660
- return /* @__PURE__ */ jsx12(
661
- Slot2,
662
- {
663
- "aria-describedby": !error ? `${formDescriptionId}` : `${formDescriptionId} ${formMessageId}`,
664
- "aria-invalid": !!error,
665
- id: formItemId,
666
- ref,
667
- ...props
668
- }
669
- );
670
- }
671
- );
672
- FormControl.displayName = "FormControl";
673
- var FormMessage = React9.forwardRef(
674
- ({ children, className, ...props }, ref) => {
675
- const { error, formMessageId } = useFormField();
676
- const body = error?.message ? String(error.message) : children;
677
- if (!body) {
678
- return null;
679
- }
680
- return /* @__PURE__ */ jsx12(
681
- "p",
682
- {
683
- className: cn("text-destructive text-[0.8rem] font-medium", className),
684
- id: formMessageId,
685
- ref,
686
- ...props,
687
- children: body
688
- }
689
- );
690
- }
691
- );
692
- FormMessage.displayName = "FormMessage";
693
-
694
547
  // src/components/form-fields/input-field.tsx
695
548
  import { EyeIcon, EyeSlashIcon, XIcon as XIcon2 } from "@phosphor-icons/react";
696
549
  import { useState } from "react";
697
550
 
698
551
  // src/components/input.tsx
699
- import * as React10 from "react";
700
- import { jsx as jsx13 } from "react/jsx-runtime";
701
- var Input = React10.forwardRef(({ className, onKeyDown, type, ...props }, ref) => {
702
- return /* @__PURE__ */ jsx13(
552
+ import * as React9 from "react";
553
+ import { jsx as jsx12 } from "react/jsx-runtime";
554
+ var NUMBER_ALLOWED_KEYS = /* @__PURE__ */ new Set([
555
+ "ArrowDown",
556
+ "ArrowLeft",
557
+ "ArrowRight",
558
+ "ArrowUp",
559
+ "Backspace",
560
+ "Delete",
561
+ "End",
562
+ "Enter",
563
+ "Escape",
564
+ "Home",
565
+ "Tab"
566
+ ]);
567
+ var isAllowedNumberKey = (event) => event.ctrlKey || event.metaKey || event.altKey || NUMBER_ALLOWED_KEYS.has(event.key) || /^[0-9]$/.test(event.key);
568
+ var Input = React9.forwardRef(({ className, onKeyDown, type, ...props }, ref) => {
569
+ return /* @__PURE__ */ jsx12(
703
570
  "input",
704
571
  {
705
572
  className: cn(
@@ -710,15 +577,8 @@ var Input = React10.forwardRef(({ className, onKeyDown, type, ...props }, ref) =
710
577
  ),
711
578
  onKeyDown: (e) => {
712
579
  onKeyDown?.(e);
713
- if (e.defaultPrevented) return;
714
- const key = e.key;
715
- const allowedKeys = ["Backspace", "Tab", "Enter", "Escape", "ArrowLeft", "ArrowUp", "ArrowRight", "ArrowDown"];
716
- if (allowedKeys.includes(key)) {
717
- return;
718
- }
719
- if (!(key >= "0" && key <= "9") && type === "number") {
720
- e.preventDefault();
721
- }
580
+ if (e.defaultPrevented || type !== "number") return;
581
+ if (!isAllowedNumberKey(e)) e.preventDefault();
722
582
  },
723
583
  ref,
724
584
  type,
@@ -728,69 +588,24 @@ var Input = React10.forwardRef(({ className, onKeyDown, type, ...props }, ref) =
728
588
  });
729
589
  Input.displayName = "Input";
730
590
 
731
- // src/components/label.tsx
732
- import * as LabelPrimitive from "@radix-ui/react-label";
733
- import { cva as cva3 } from "class-variance-authority";
734
- import * as React11 from "react";
735
- import { jsx as jsx14 } from "react/jsx-runtime";
736
- var labelVariants = cva3("text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70");
737
- var Label = React11.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx14(LabelPrimitive.Root, { className: cn(labelVariants(), className), ref, ...props }));
738
- Label.displayName = LabelPrimitive.Root.displayName;
739
-
740
- // src/components/form-fields/label-field.tsx
741
- import { jsx as jsx15, jsxs as jsxs10 } from "react/jsx-runtime";
742
- var LabelField = ({ label, labelClassName, name, visualRequired }) => {
743
- return /* @__PURE__ */ jsxs10(
744
- Label,
745
- {
746
- className: cn("text-body mb-2 text-start text-sm leading-none font-normal tracking-normal", labelClassName),
747
- htmlFor: name,
748
- children: [
749
- /* @__PURE__ */ jsx15("span", { children: label }),
750
- " ",
751
- visualRequired && /* @__PURE__ */ jsx15("span", { className: "text-destructive", children: " *" })
752
- ]
753
- }
754
- );
755
- };
756
-
757
- // src/components/form-fields/form-field-shell.tsx
758
- import { jsx as jsx16, jsxs as jsxs11 } from "react/jsx-runtime";
759
- var FormFieldShell = ({
760
- children,
761
- hasError,
762
- label,
763
- labelClassName,
764
- mainClassName,
765
- name,
766
- visualRequired
767
- }) => /* @__PURE__ */ jsxs11(FormItem, { className: cn("flex flex-col", mainClassName), children: [
768
- /* @__PURE__ */ jsx16(
769
- LabelField,
770
- {
771
- label,
772
- labelClassName: cn(labelClassName, hasError && "text-destructive"),
773
- name,
774
- visualRequired
775
- }
776
- ),
777
- /* @__PURE__ */ jsx16(FormControl, { children }),
778
- /* @__PURE__ */ jsx16(FormMessage, {})
779
- ] });
780
-
781
591
  // src/components/form-fields/input-field.tsx
782
- import { jsx as jsx17, jsxs as jsxs12 } from "react/jsx-runtime";
592
+ import { jsx as jsx13, jsxs as jsxs10 } from "react/jsx-runtime";
593
+ var iconButtonClassName = cn("flex items-center justify-center rounded-sm", focusRing);
783
594
  var InputField = ({
595
+ autoComplete,
784
596
  clearLabel,
785
597
  control,
786
598
  disabled,
787
599
  hidePasswordLabel,
788
600
  inputClassName,
601
+ inputMode,
789
602
  isClearable,
790
603
  label,
791
604
  labelClassName,
792
605
  mainClassName,
606
+ maxLength,
793
607
  name,
608
+ onBlur,
794
609
  onClear,
795
610
  placeholder,
796
611
  showPasswordLabel,
@@ -804,14 +619,16 @@ var InputField = ({
804
619
  };
805
620
  const isPassword = type === "password";
806
621
  const inputType = isPassword ? isPasswordVisible ? "text" : "password" : type;
807
- return /* @__PURE__ */ jsx17(
622
+ const resolvedClearLabel = clearLabel ?? t("inputField.clear");
623
+ const passwordToggleLabel = isPasswordVisible ? hidePasswordLabel ?? t("inputField.hidePassword") : showPasswordLabel ?? t("inputField.showPassword");
624
+ return /* @__PURE__ */ jsx13(
808
625
  FormField,
809
626
  {
810
627
  control,
811
628
  name,
812
629
  render: ({ field, fieldState }) => {
813
630
  const hasError = !!fieldState.error;
814
- return /* @__PURE__ */ jsx17(
631
+ return /* @__PURE__ */ jsx13(
815
632
  FormFieldShell,
816
633
  {
817
634
  hasError,
@@ -820,12 +637,13 @@ var InputField = ({
820
637
  mainClassName,
821
638
  name,
822
639
  visualRequired,
823
- children: /* @__PURE__ */ jsxs12("div", { className: "relative", children: [
824
- /* @__PURE__ */ jsx17(
640
+ children: (controlProps) => /* @__PURE__ */ jsxs10("div", { className: "relative", children: [
641
+ /* @__PURE__ */ jsx13(
825
642
  Input,
826
643
  {
827
644
  ...field,
828
- autoComplete: isPassword ? "current-password" : void 0,
645
+ ...controlProps,
646
+ autoComplete: autoComplete ?? (isPassword ? "current-password" : void 0),
829
647
  className: cn(
830
648
  inputClassName,
831
649
  hasError && "border-destructive",
@@ -835,31 +653,39 @@ var InputField = ({
835
653
  "data-bwignore": isPassword || void 0,
836
654
  "data-lpignore": isPassword || void 0,
837
655
  disabled,
656
+ inputMode,
657
+ maxLength,
838
658
  min: type === "number" ? 0 : void 0,
659
+ onBlur: (event) => {
660
+ field.onBlur();
661
+ onBlur?.(event);
662
+ },
839
663
  placeholder,
840
664
  type: inputType,
841
665
  value: field.value ?? ""
842
666
  }
843
667
  ),
844
- /* @__PURE__ */ jsxs12("div", { className: "absolute inset-y-0 right-0 flex items-center space-x-2 pr-2", children: [
845
- field.value && isClearable && /* @__PURE__ */ jsx17(
668
+ /* @__PURE__ */ jsxs10("div", { className: "absolute inset-y-0 right-0 flex items-center space-x-2 pr-2", children: [
669
+ field.value && isClearable && /* @__PURE__ */ jsx13(
846
670
  "button",
847
671
  {
848
- className: "focus:outline-none",
672
+ "aria-label": resolvedClearLabel,
673
+ className: iconButtonClassName,
849
674
  onClick: onClear,
850
- title: clearLabel ?? t("inputField.clear"),
675
+ title: resolvedClearLabel,
851
676
  type: "button",
852
- children: /* @__PURE__ */ jsx17(XIcon2, { size: 18 })
677
+ children: /* @__PURE__ */ jsx13(XIcon2, { "aria-hidden": true, size: 18 })
853
678
  }
854
679
  ),
855
- type === "password" && /* @__PURE__ */ jsx17(
680
+ isPassword && /* @__PURE__ */ jsx13(
856
681
  "button",
857
682
  {
858
- className: "focus:outline-none",
683
+ "aria-label": passwordToggleLabel,
684
+ className: iconButtonClassName,
859
685
  onClick: togglePasswordVisibility,
860
- title: isPasswordVisible ? hidePasswordLabel ?? t("inputField.hidePassword") : showPasswordLabel ?? t("inputField.showPassword"),
686
+ title: passwordToggleLabel,
861
687
  type: "button",
862
- children: isPasswordVisible ? /* @__PURE__ */ jsx17(EyeIcon, { size: 18 }) : /* @__PURE__ */ jsx17(EyeSlashIcon, { size: 20 })
688
+ children: isPasswordVisible ? /* @__PURE__ */ jsx13(EyeIcon, { "aria-hidden": true, size: 18 }) : /* @__PURE__ */ jsx13(EyeSlashIcon, { "aria-hidden": true, size: 20 })
863
689
  }
864
690
  )
865
691
  ] })
@@ -871,340 +697,16 @@ var InputField = ({
871
697
  );
872
698
  };
873
699
 
874
- // src/components/google-map-picker.tsx
875
- import { AdvancedMarker, APIProvider, Map as Map2 } from "@vis.gl/react-google-maps";
876
-
877
- // src/components/use-google-map-picker.ts
878
- import { useMap, useMapsLibrary } from "@vis.gl/react-google-maps";
879
- import { useCallback, useEffect, useMemo, useRef, useState as useState2 } from "react";
880
- var PICKER_MAP_ID = "komensal-restaurant-map";
881
- var SELECTED_ZOOM = 15;
882
- var CITY_ZOOM = 12;
883
- var DEBOUNCE_MS = 300;
884
- var BLUR_CLOSE_DELAY_MS = 150;
885
- var parseComponents = (components) => {
886
- const find = (type) => components.find((c) => c.types.includes(type));
887
- const country = find("country");
888
- const department = find("administrative_area_level_1");
889
- const city = find("locality") ?? find("administrative_area_level_2");
890
- return {
891
- city: city?.long ?? null,
892
- country: country?.short ?? null,
893
- countryName: country?.long ?? null,
894
- department: department?.long ?? null
895
- };
896
- };
897
- function useGoogleMapPicker({
898
- centerOn,
899
- countryCode,
900
- disabled,
901
- initialPosition,
902
- locationQuery,
903
- locationZoom,
904
- onAddressResolved,
905
- onChange,
906
- onError,
907
- value
908
- }) {
909
- const placesLib = useMapsLibrary("places");
910
- const geocodingLib = useMapsLibrary("geocoding");
911
- const map = useMap(PICKER_MAP_ID);
912
- const onChangeRef = useRef(onChange);
913
- const onResolvedRef = useRef(onAddressResolved);
914
- const onErrorRef = useRef(onError);
915
- const geocoder = useMemo(
916
- () => geocodingLib ? new geocodingLib.Geocoder() : null,
917
- [geocodingLib]
918
- );
919
- const debounceRef = useRef(null);
920
- const blurTimeoutRef = useRef(null);
921
- const [inputValue, setInputValue] = useState2(value);
922
- const [suggestions, setSuggestions] = useState2([]);
923
- const [showDropdown, setShowDropdown] = useState2(false);
924
- const [sessionToken, setSessionToken] = useState2();
925
- const [position, setPosition] = useState2(initialPosition ?? null);
926
- useEffect(() => {
927
- onChangeRef.current = onChange;
928
- onResolvedRef.current = onAddressResolved;
929
- onErrorRef.current = onError;
930
- });
931
- useEffect(
932
- () => () => {
933
- if (debounceRef.current) clearTimeout(debounceRef.current);
934
- if (blurTimeoutRef.current) clearTimeout(blurTimeoutRef.current);
935
- },
936
- []
937
- );
938
- const [prevValue, setPrevValue] = useState2(value);
939
- if (prevValue !== value) {
940
- setPrevValue(value);
941
- setInputValue(value);
942
- }
943
- useEffect(() => {
944
- if (map && centerOn) {
945
- map.panTo(centerOn);
946
- map.setZoom(CITY_ZOOM);
947
- }
948
- }, [map, centerOn]);
949
- useEffect(() => {
950
- if (map && position) {
951
- map.panTo(position);
952
- map.setZoom(SELECTED_ZOOM);
953
- }
954
- }, [map, position]);
955
- const [prevPlacesLib, setPrevPlacesLib] = useState2(placesLib);
956
- if (prevPlacesLib !== placesLib) {
957
- setPrevPlacesLib(placesLib);
958
- if (placesLib) setSessionToken(new placesLib.AutocompleteSessionToken());
959
- }
960
- useEffect(() => {
961
- if (!geocoder || !locationQuery || !map || position) return;
962
- const g = geocoder;
963
- const ctrl = { cancelled: false };
964
- void (async () => {
965
- try {
966
- const { results } = await g.geocode({ address: locationQuery });
967
- if (ctrl.cancelled || results.length === 0) return;
968
- const loc = results[0].geometry.location;
969
- map.panTo({ lat: loc.lat(), lng: loc.lng() });
970
- map.setZoom(locationZoom ?? CITY_ZOOM);
971
- } catch (error) {
972
- if (!ctrl.cancelled) {
973
- console.error("[GoogleMapPicker] geocode by query failed", error);
974
- onErrorRef.current?.(error);
975
- }
976
- }
977
- })();
978
- return () => {
979
- ctrl.cancelled = true;
980
- };
981
- }, [geocoder, locationQuery, locationZoom, map, position]);
982
- const fetchSuggestions = useCallback(
983
- async (input) => {
984
- if (!placesLib || input.length < 2) {
985
- setSuggestions([]);
986
- return;
987
- }
988
- try {
989
- const result = await placesLib.AutocompleteSuggestion.fetchAutocompleteSuggestions({
990
- includedRegionCodes: countryCode ? [countryCode.trim().toLowerCase()] : void 0,
991
- input,
992
- sessionToken
993
- });
994
- setSuggestions(result.suggestions);
995
- setShowDropdown(true);
996
- } catch (error) {
997
- console.error("[GoogleMapPicker] fetchAutocompleteSuggestions failed", error);
998
- onErrorRef.current?.(error);
999
- setSuggestions([]);
1000
- }
1001
- },
1002
- [placesLib, sessionToken, countryCode]
1003
- );
1004
- const reverseGeocode = useCallback(
1005
- async (latLng) => {
1006
- if (!geocoder) return;
1007
- try {
1008
- const { results } = await geocoder.geocode({ location: latLng });
1009
- if (results.length > 0) {
1010
- const result = results[0];
1011
- const address = result.formatted_address;
1012
- setInputValue(address);
1013
- onChangeRef.current(address);
1014
- const parts = parseComponents(
1015
- result.address_components.map((c) => ({ long: c.long_name, short: c.short_name, types: c.types }))
1016
- );
1017
- onResolvedRef.current?.({ address, lat: latLng.lat, lng: latLng.lng, ...parts });
1018
- }
1019
- } catch (error) {
1020
- console.error("[GoogleMapPicker] reverse geocode failed", error);
1021
- onErrorRef.current?.(error);
1022
- }
1023
- },
1024
- [geocoder]
1025
- );
1026
- const handleInputChange = (e) => {
1027
- const val = e.target.value;
1028
- setInputValue(val);
1029
- onChangeRef.current(val);
1030
- if (debounceRef.current) clearTimeout(debounceRef.current);
1031
- debounceRef.current = setTimeout(() => void fetchSuggestions(val), DEBOUNCE_MS);
1032
- };
1033
- const handleSelect = async (suggestion) => {
1034
- const prediction = suggestion.placePrediction;
1035
- if (!prediction) return;
1036
- const place = prediction.toPlace();
1037
- await place.fetchFields({ fields: ["formattedAddress", "location", "addressComponents"] });
1038
- const address = place.formattedAddress ?? prediction.text.text;
1039
- setInputValue(address);
1040
- onChangeRef.current(address);
1041
- setSuggestions([]);
1042
- setShowDropdown(false);
1043
- const lat = place.location?.lat() ?? null;
1044
- const lng = place.location?.lng() ?? null;
1045
- if (place.location) {
1046
- setPosition({ lat: place.location.lat(), lng: place.location.lng() });
1047
- }
1048
- const parts = parseComponents(
1049
- (place.addressComponents ?? []).map((c) => ({ long: c.longText, short: c.shortText, types: c.types }))
1050
- );
1051
- onResolvedRef.current?.({ address, lat, lng, ...parts });
1052
- if (placesLib) setSessionToken(new placesLib.AutocompleteSessionToken());
1053
- };
1054
- const handleBlur = () => {
1055
- if (blurTimeoutRef.current) clearTimeout(blurTimeoutRef.current);
1056
- blurTimeoutRef.current = setTimeout(() => setShowDropdown(false), BLUR_CLOSE_DELAY_MS);
1057
- };
1058
- const handleMapClick = useCallback(
1059
- (e) => {
1060
- if (disabled || !e.detail.latLng) return;
1061
- const latLng = e.detail.latLng;
1062
- setPosition(latLng);
1063
- void reverseGeocode(latLng);
1064
- },
1065
- [disabled, reverseGeocode]
1066
- );
1067
- const handleMarkerDragEnd = useCallback(
1068
- (e) => {
1069
- const latLng = e.latLng;
1070
- if (!latLng) return;
1071
- const pos = { lat: latLng.lat(), lng: latLng.lng() };
1072
- setPosition(pos);
1073
- void reverseGeocode(pos);
1074
- },
1075
- [reverseGeocode]
1076
- );
1077
- return {
1078
- handleBlur,
1079
- handleInputChange,
1080
- handleMapClick,
1081
- handleMarkerDragEnd,
1082
- handleSelect,
1083
- inputValue,
1084
- position,
1085
- setShowDropdown,
1086
- showDropdown,
1087
- suggestions
1088
- };
1089
- }
1090
-
1091
- // src/components/google-map-picker.tsx
1092
- import { jsx as jsx18, jsxs as jsxs13 } from "react/jsx-runtime";
1093
- var DEFAULT_CENTER = { lat: 4.711, lng: -74.0721 };
1094
- var MapPickerContent = (props) => {
1095
- const { disabled, hasError, mapId, placeholder } = props;
1096
- const {
1097
- handleBlur,
1098
- handleInputChange,
1099
- handleMapClick,
1100
- handleMarkerDragEnd,
1101
- handleSelect,
1102
- inputValue,
1103
- position,
1104
- setShowDropdown,
1105
- showDropdown,
1106
- suggestions
1107
- } = useGoogleMapPicker(props);
1108
- return /* @__PURE__ */ jsxs13("div", { className: "flex flex-col gap-3", children: [
1109
- /* @__PURE__ */ jsxs13("div", { className: "relative", children: [
1110
- /* @__PURE__ */ jsx18(
1111
- "input",
1112
- {
1113
- className: cn(inputBase, inputFocus, hasError && "border-destructive"),
1114
- disabled,
1115
- onBlur: handleBlur,
1116
- onChange: handleInputChange,
1117
- onFocus: () => suggestions.length > 0 && setShowDropdown(true),
1118
- placeholder,
1119
- type: "text",
1120
- value: inputValue
1121
- }
1122
- ),
1123
- showDropdown && suggestions.length > 0 && /* @__PURE__ */ jsx18(
1124
- "ul",
1125
- {
1126
- className: cn(
1127
- "border-border bg-surface absolute mt-1 w-full overflow-hidden rounded-[10px] border shadow-md",
1128
- zPopover
1129
- ),
1130
- children: suggestions.map((suggestion) => /* @__PURE__ */ jsx18("li", { children: /* @__PURE__ */ jsx18(
1131
- "button",
1132
- {
1133
- className: "text-foreground hover:bg-hover w-full px-4 py-3 text-left text-sm transition-colors",
1134
- onClick: () => void handleSelect(suggestion),
1135
- type: "button",
1136
- children: suggestion.placePrediction?.text.text ?? ""
1137
- }
1138
- ) }, suggestion.placePrediction?.placeId ?? suggestion.placePrediction?.text.text))
1139
- }
1140
- )
1141
- ] }),
1142
- /* @__PURE__ */ jsx18("div", { className: "border-border h-59 overflow-hidden rounded-[10px] border md:h-87.5", children: /* @__PURE__ */ jsx18(
1143
- Map2,
1144
- {
1145
- defaultCenter: DEFAULT_CENTER,
1146
- defaultZoom: 5,
1147
- disableDefaultUI: true,
1148
- gestureHandling: "cooperative",
1149
- id: PICKER_MAP_ID,
1150
- mapId: mapId ?? import.meta.env.VITE_GOOGLE_MAPS_MAP_ID ?? "DEMO_MAP_ID",
1151
- onClick: handleMapClick,
1152
- style: { height: "100%", width: "100%" },
1153
- children: position && /* @__PURE__ */ jsx18(AdvancedMarker, { draggable: !disabled, onDragEnd: handleMarkerDragEnd, position })
1154
- }
1155
- ) })
1156
- ] });
1157
- };
1158
- var GoogleMapPicker = (props) => /* @__PURE__ */ jsx18(APIProvider, { apiKey: props.apiKey ?? import.meta.env.VITE_GOOGLE_MAPS_API_KEY ?? "", language: "es", region: "CO", children: /* @__PURE__ */ jsx18(MapPickerContent, { ...props }) });
1159
-
1160
- // src/components/form-fields/map-picker-field.tsx
1161
- import { jsx as jsx19 } from "react/jsx-runtime";
1162
- var MapPickerField = ({
1163
- control,
1164
- label,
1165
- labelClassName,
1166
- mainClassName,
1167
- name,
1168
- visualRequired,
1169
- ...pickerProps
1170
- }) => /* @__PURE__ */ jsx19(
1171
- FormField,
1172
- {
1173
- control,
1174
- name,
1175
- render: ({ field, fieldState }) => /* @__PURE__ */ jsx19(
1176
- FormFieldShell,
1177
- {
1178
- hasError: !!fieldState.error,
1179
- label,
1180
- labelClassName,
1181
- mainClassName,
1182
- name,
1183
- visualRequired,
1184
- children: /* @__PURE__ */ jsx19(
1185
- GoogleMapPicker,
1186
- {
1187
- ...pickerProps,
1188
- hasError: !!fieldState.error,
1189
- onChange: field.onChange,
1190
- value: field.value ?? ""
1191
- }
1192
- )
1193
- }
1194
- )
1195
- }
1196
- );
1197
-
1198
700
  // src/components/otp-input.tsx
1199
701
  import { OTPInput, OTPInputContext } from "input-otp";
1200
- import React12 from "react";
1201
- import { jsx as jsx20, jsxs as jsxs14 } from "react/jsx-runtime";
702
+ import React10 from "react";
703
+ import { jsx as jsx14, jsxs as jsxs11 } from "react/jsx-runtime";
1202
704
  function InputOTP({
1203
705
  className,
1204
706
  containerClassName,
1205
707
  ...props
1206
708
  }) {
1207
- return /* @__PURE__ */ jsx20(
709
+ return /* @__PURE__ */ jsx14(
1208
710
  OTPInput,
1209
711
  {
1210
712
  className: cn("disabled:cursor-not-allowed", className),
@@ -1215,16 +717,16 @@ function InputOTP({
1215
717
  );
1216
718
  }
1217
719
  function InputOTPGroup({ className, ...props }) {
1218
- return /* @__PURE__ */ jsx20("div", { className: cn("flex items-center gap-2", className), "data-slot": "input-otp-group", ...props });
720
+ return /* @__PURE__ */ jsx14("div", { className: cn("flex items-center gap-2", className), "data-slot": "input-otp-group", ...props });
1219
721
  }
1220
722
  function InputOTPSlot({
1221
723
  className,
1222
724
  index,
1223
725
  ...props
1224
726
  }) {
1225
- const inputOTPContext = React12.useContext(OTPInputContext);
727
+ const inputOTPContext = React10.useContext(OTPInputContext);
1226
728
  const { char, hasFakeCaret, isActive } = inputOTPContext.slots[index] ?? {};
1227
- return /* @__PURE__ */ jsxs14(
729
+ return /* @__PURE__ */ jsxs11(
1228
730
  "div",
1229
731
  {
1230
732
  className: cn(
@@ -1239,14 +741,14 @@ function InputOTPSlot({
1239
741
  ...props,
1240
742
  children: [
1241
743
  char,
1242
- hasFakeCaret && /* @__PURE__ */ jsx20("div", { className: "pointer-events-none absolute inset-0 flex items-center justify-center", children: /* @__PURE__ */ jsx20("div", { className: "animate-caret-blink bg-foreground h-6 w-px duration-1000" }) })
744
+ hasFakeCaret && /* @__PURE__ */ jsx14("div", { className: "pointer-events-none absolute inset-0 flex items-center justify-center", children: /* @__PURE__ */ jsx14("div", { className: "animate-caret-blink bg-foreground h-6 w-px duration-1000" }) })
1243
745
  ]
1244
746
  }
1245
747
  );
1246
748
  }
1247
749
 
1248
750
  // src/components/form-fields/otp-field.tsx
1249
- import { jsx as jsx21, jsxs as jsxs15 } from "react/jsx-runtime";
751
+ import { jsx as jsx15, jsxs as jsxs12 } from "react/jsx-runtime";
1250
752
  function OTPField({
1251
753
  autoFocus,
1252
754
  className,
@@ -1259,13 +761,13 @@ function OTPField({
1259
761
  otpLength = 6,
1260
762
  visualRequired
1261
763
  }) {
1262
- return /* @__PURE__ */ jsx21(
764
+ return /* @__PURE__ */ jsx15(
1263
765
  FormField,
1264
766
  {
1265
767
  control,
1266
768
  name,
1267
- render: ({ field, fieldState }) => /* @__PURE__ */ jsxs15(FormItem, { className: cn("flex flex-col", className), children: [
1268
- label ? /* @__PURE__ */ jsx21(
769
+ render: ({ field, fieldState }) => /* @__PURE__ */ jsxs12(FormItem, { className: cn("flex flex-col", className), children: [
770
+ label ? /* @__PURE__ */ jsx15(
1269
771
  LabelField,
1270
772
  {
1271
773
  label,
@@ -1274,7 +776,7 @@ function OTPField({
1274
776
  visualRequired
1275
777
  }
1276
778
  ) : null,
1277
- /* @__PURE__ */ jsx21(FormControl, { children: /* @__PURE__ */ jsx21(
779
+ /* @__PURE__ */ jsx15(FormControl, { children: /* @__PURE__ */ jsx15(
1278
780
  InputOTP,
1279
781
  {
1280
782
  "aria-invalid": fieldState.invalid || void 0,
@@ -1282,17 +784,16 @@ function OTPField({
1282
784
  autoFocus,
1283
785
  containerClassName: cn("justify-center", containerClassName),
1284
786
  disabled,
1285
- id: name,
1286
787
  inputMode: "numeric",
1287
788
  maxLength: otpLength,
1288
789
  onChange: (val) => field.onChange(val),
1289
790
  onPaste: (e) => field.onChange(e.clipboardData.getData("text")),
1290
791
  pattern: "[0-9]*",
1291
792
  value: field.value ?? "",
1292
- children: /* @__PURE__ */ jsx21(InputOTPGroup, { children: Array.from({ length: otpLength }).map((_, i) => /* @__PURE__ */ jsx21(InputOTPSlot, { "aria-invalid": fieldState.invalid || void 0, index: i }, i)) })
793
+ children: /* @__PURE__ */ jsx15(InputOTPGroup, { children: Array.from({ length: otpLength }).map((_, i) => /* @__PURE__ */ jsx15(InputOTPSlot, { "aria-invalid": fieldState.invalid || void 0, index: i }, i)) })
1293
794
  }
1294
795
  ) }),
1295
- /* @__PURE__ */ jsx21(FormMessage, {})
796
+ /* @__PURE__ */ jsx15(FormMessage, {})
1296
797
  ] })
1297
798
  }
1298
799
  );
@@ -1300,15 +801,15 @@ function OTPField({
1300
801
 
1301
802
  // src/components/select-input.tsx
1302
803
  import { CaretDownIcon, CaretUpIcon, ClockIcon, XIcon as XIcon3 } from "@phosphor-icons/react";
1303
- import { cloneElement, useCallback as useCallback2, useId as useId2, useMemo as useMemo3, useState as useState4 } from "react";
804
+ import { cloneElement, useCallback, useEffect as useEffect3, useId, useMemo as useMemo2, useRef as useRef3, useState as useState3 } from "react";
1304
805
 
1305
806
  // src/components/popover.tsx
1306
807
  import * as PopoverPrimitive from "@radix-ui/react-popover";
1307
- import * as React13 from "react";
1308
- import { jsx as jsx22 } from "react/jsx-runtime";
808
+ import * as React11 from "react";
809
+ import { jsx as jsx16 } from "react/jsx-runtime";
1309
810
  var Popover = PopoverPrimitive.Root;
1310
811
  var PopoverTrigger = PopoverPrimitive.Trigger;
1311
- var PopoverContent = React13.forwardRef(({ align = "center", className, sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsx22(PopoverPrimitive.Portal, { children: /* @__PURE__ */ jsx22(
812
+ var PopoverContent = React11.forwardRef(({ align = "center", className, sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsx16(PopoverPrimitive.Portal, { children: /* @__PURE__ */ jsx16(
1312
813
  PopoverPrimitive.Content,
1313
814
  {
1314
815
  align,
@@ -1324,67 +825,90 @@ var PopoverContent = React13.forwardRef(({ align = "center", className, sideOffs
1324
825
  PopoverContent.displayName = PopoverPrimitive.Content.displayName;
1325
826
 
1326
827
  // src/components/time-columns.tsx
1327
- import * as React14 from "react";
1328
- import { jsx as jsx23, jsxs as jsxs16 } from "react/jsx-runtime";
828
+ import * as React12 from "react";
829
+ import { jsx as jsx17, jsxs as jsxs13 } from "react/jsx-runtime";
830
+ var optionClassName = cn(
831
+ "hover:bg-hover w-full cursor-pointer rounded-sm px-2 py-1.5 text-sm focus-visible:ring-inset",
832
+ focusRing
833
+ );
1329
834
  var TimeColumns = ({ hours, minutes, onSelectHour, onSelectMinute, value }) => {
835
+ const t = useUiT();
1330
836
  const [selectedHour, selectedMinute] = value ? value.split(":") : ["", ""];
1331
- const hourListRef = React14.useRef(null);
1332
- const minuteListRef = React14.useRef(null);
1333
- React14.useEffect(() => {
837
+ const hourListRef = React12.useRef(null);
838
+ const minuteListRef = React12.useRef(null);
839
+ React12.useEffect(() => {
1334
840
  hourListRef.current?.querySelector('[data-selected="true"]')?.scrollIntoView({ block: "center" });
1335
841
  minuteListRef.current?.querySelector('[data-selected="true"]')?.scrollIntoView({ block: "center" });
1336
842
  }, []);
1337
- return /* @__PURE__ */ jsxs16("div", { className: "divide-border flex divide-x", children: [
1338
- /* @__PURE__ */ jsx23("div", { className: "max-h-60 flex-1 overflow-y-auto", ref: hourListRef, children: hours.map((hour) => {
1339
- const isSelected = hour === selectedHour;
1340
- return /* @__PURE__ */ jsx23(
1341
- "button",
1342
- {
1343
- className: cn(
1344
- "hover:bg-hover flex w-full cursor-pointer items-center justify-center rounded-sm px-2 py-1.5 text-sm",
1345
- isSelected && "bg-inactive font-medium"
1346
- ),
1347
- "data-selected": isSelected,
1348
- onClick: () => onSelectHour(hour),
1349
- type: "button",
1350
- children: formatHour12(hour)
1351
- },
1352
- hour
1353
- );
1354
- }) }),
1355
- /* @__PURE__ */ jsx23("div", { className: "max-h-60 flex-1 overflow-y-auto", ref: minuteListRef, children: minutes.map((minute) => {
1356
- const isSelected = minute === selectedMinute;
1357
- return /* @__PURE__ */ jsx23(
1358
- "button",
1359
- {
1360
- className: cn(
1361
- "hover:bg-hover w-full cursor-pointer rounded-sm px-2 py-1.5 text-center text-sm",
1362
- isSelected && "bg-inactive font-medium"
1363
- ),
1364
- "data-selected": isSelected,
1365
- onClick: () => onSelectMinute(minute),
1366
- type: "button",
1367
- children: minute
1368
- },
1369
- minute
1370
- );
1371
- }) })
843
+ const formatHour12 = (hour) => {
844
+ const hourNum = Number(hour);
845
+ const period = hourNum >= 12 ? t("timeColumns.pm") : t("timeColumns.am");
846
+ const hour12 = hourNum % 12 === 0 ? 12 : hourNum % 12;
847
+ return `${hour12} ${period}`;
848
+ };
849
+ return /* @__PURE__ */ jsxs13("div", { className: "divide-border flex divide-x", children: [
850
+ /* @__PURE__ */ jsx17(
851
+ "div",
852
+ {
853
+ "aria-label": t("timeColumns.hours"),
854
+ className: "max-h-60 flex-1 overflow-y-auto",
855
+ ref: hourListRef,
856
+ role: "group",
857
+ children: hours.map((hour) => {
858
+ const isSelected = hour === selectedHour;
859
+ return /* @__PURE__ */ jsx17(
860
+ "button",
861
+ {
862
+ "aria-pressed": isSelected,
863
+ className: cn(
864
+ optionClassName,
865
+ "flex items-center justify-center",
866
+ isSelected && "bg-inactive font-medium"
867
+ ),
868
+ "data-selected": isSelected,
869
+ onClick: () => onSelectHour(hour),
870
+ type: "button",
871
+ children: formatHour12(hour)
872
+ },
873
+ hour
874
+ );
875
+ })
876
+ }
877
+ ),
878
+ /* @__PURE__ */ jsx17(
879
+ "div",
880
+ {
881
+ "aria-label": t("timeColumns.minutes"),
882
+ className: "max-h-60 flex-1 overflow-y-auto",
883
+ ref: minuteListRef,
884
+ role: "group",
885
+ children: minutes.map((minute) => {
886
+ const isSelected = minute === selectedMinute;
887
+ return /* @__PURE__ */ jsx17(
888
+ "button",
889
+ {
890
+ "aria-pressed": isSelected,
891
+ className: cn(optionClassName, "text-center", isSelected && "bg-inactive font-medium"),
892
+ "data-selected": isSelected,
893
+ onClick: () => onSelectMinute(minute),
894
+ type: "button",
895
+ children: minute
896
+ },
897
+ minute
898
+ );
899
+ })
900
+ }
901
+ )
1372
902
  ] });
1373
903
  };
1374
- function formatHour12(hour) {
1375
- const hourNum = Number(hour);
1376
- const period = hourNum >= 12 ? "PM" : "AM";
1377
- const hour12 = hourNum % 12 === 0 ? 12 : hourNum % 12;
1378
- return `${hour12} ${period}`;
1379
- }
1380
904
 
1381
905
  // src/components/use-select-input.ts
1382
- import { useEffect as useEffect3, useMemo as useMemo2, useRef as useRef3, useState as useState3 } from "react";
906
+ import { useEffect as useEffect2, useMemo, useRef as useRef2, useState as useState2 } from "react";
1383
907
  var normalizeString = (str) => str.normalize("NFD").replace(/[̀-ͯ]/g, "").toLowerCase();
1384
908
  function usePopoverWidth() {
1385
- const ref = useRef3(null);
1386
- const [width, setWidth] = useState3(0);
1387
- useEffect3(() => {
909
+ const ref = useRef2(null);
910
+ const [width, setWidth] = useState2(0);
911
+ useEffect2(() => {
1388
912
  const el = ref.current;
1389
913
  if (!el) return;
1390
914
  const updateWidth = () => setWidth(el.getBoundingClientRect().width);
@@ -1396,8 +920,8 @@ function usePopoverWidth() {
1396
920
  return { ref, width };
1397
921
  }
1398
922
  function useSelectFilter(items, labelKey, valueKey) {
1399
- const [query, setQuery] = useState3("");
1400
- const normalizedItems = useMemo2(() => {
923
+ const [query, setQuery] = useState2("");
924
+ const normalizedItems = useMemo(() => {
1401
925
  if (!items) return [];
1402
926
  return items.map((it) => ({
1403
927
  ...it,
@@ -1405,7 +929,7 @@ function useSelectFilter(items, labelKey, valueKey) {
1405
929
  [valueKey]: String(it[valueKey])
1406
930
  }));
1407
931
  }, [items, labelKey, valueKey]);
1408
- const filteredOptions = useMemo2(() => {
932
+ const filteredOptions = useMemo(() => {
1409
933
  if (!query) return normalizedItems;
1410
934
  return normalizedItems.filter((el) => normalizeString(el[labelKey]).includes(normalizeString(query)));
1411
935
  }, [normalizedItems, labelKey, query]);
@@ -1413,15 +937,20 @@ function useSelectFilter(items, labelKey, valueKey) {
1413
937
  }
1414
938
 
1415
939
  // src/components/select-input.tsx
1416
- import { Fragment as Fragment3, jsx as jsx24, jsxs as jsxs17 } from "react/jsx-runtime";
940
+ import { Fragment as Fragment3, jsx as jsx18, jsxs as jsxs14 } from "react/jsx-runtime";
1417
941
  var QUERY_RESET_DELAY_MS = 100;
1418
942
  var SelectInput = (props) => {
1419
943
  const t = useUiT();
1420
944
  const {
1421
945
  ableDeleteOption,
946
+ "aria-describedby": ariaDescribedBy,
947
+ "aria-invalid": ariaInvalid,
948
+ "aria-label": ariaLabel,
949
+ "aria-labelledby": ariaLabelledBy,
1422
950
  className,
1423
951
  disabled = false,
1424
952
  error,
953
+ id,
1425
954
  items,
1426
955
  labelKey = "label",
1427
956
  leftIcon,
@@ -1440,12 +969,19 @@ var SelectInput = (props) => {
1440
969
  valueKey = "value"
1441
970
  } = props;
1442
971
  const resolvedPlaceholder = placeholder ?? t("selectInput.placeholder");
1443
- const listboxId = useId2();
1444
- const [open, setOpen] = useState4(false);
1445
- const [valueItem, setValueItem] = useState4(value);
972
+ const listboxId = useId();
973
+ const [open, setOpen] = useState3(false);
974
+ const [valueItem, setValueItem] = useState3(value);
975
+ const queryResetRef = useRef3(null);
976
+ useEffect3(
977
+ () => () => {
978
+ if (queryResetRef.current) clearTimeout(queryResetRef.current);
979
+ },
980
+ []
981
+ );
1446
982
  const { ref: divRef, width } = usePopoverWidth();
1447
983
  const { filteredOptions, normalizedItems, query, setQuery } = useSelectFilter(items, labelKey, valueKey);
1448
- const onValueChange = useCallback2(
984
+ const onValueChange = useCallback(
1449
985
  (val) => {
1450
986
  if (!normalizedItems.length) return;
1451
987
  const item = normalizedItems.find((i) => i[valueKey] === val);
@@ -1459,13 +995,13 @@ var SelectInput = (props) => {
1459
995
  },
1460
996
  [normalizedItems, labelKey, valueKey, onValueChangeCallBack]
1461
997
  );
1462
- const timeHours = useMemo3(
998
+ const timeHours = useMemo2(
1463
999
  () => Array.from(new Set(normalizedItems.map((i) => i[valueKey].split(":")[0]))).sort(
1464
1000
  (a, b) => a.localeCompare(b)
1465
1001
  ),
1466
1002
  [normalizedItems, valueKey]
1467
1003
  );
1468
- const timeMinutes = useMemo3(
1004
+ const timeMinutes = useMemo2(
1469
1005
  () => Array.from(new Set(normalizedItems.map((i) => i[valueKey].split(":")[1]))).sort(
1470
1006
  (a, b) => a.localeCompare(b)
1471
1007
  ),
@@ -1484,7 +1020,7 @@ var SelectInput = (props) => {
1484
1020
  onValueChange(newValue);
1485
1021
  setOpen(false);
1486
1022
  };
1487
- const buttonClassName = useMemo3(
1023
+ const buttonClassName = useMemo2(
1488
1024
  () => cn(
1489
1025
  inputBase,
1490
1026
  inputFocus,
@@ -1495,53 +1031,58 @@ var SelectInput = (props) => {
1495
1031
  ),
1496
1032
  [disabled, error, className]
1497
1033
  );
1498
- const [prevValue, setPrevValue] = useState4(value);
1034
+ const [prevValue, setPrevValue] = useState3(value);
1499
1035
  if (prevValue !== value) {
1500
1036
  setPrevValue(value);
1501
1037
  setValueItem(value);
1502
1038
  }
1503
- return /* @__PURE__ */ jsx24("div", { className: "flex flex-col gap-1", children: /* @__PURE__ */ jsxs17("div", { className: "relative flex flex-col justify-center", children: [
1504
- /* @__PURE__ */ jsxs17(Popover, { onOpenChange: setOpen, open, children: [
1505
- /* @__PURE__ */ jsx24(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx24(
1039
+ return /* @__PURE__ */ jsx18("div", { className: "flex flex-col gap-1", children: /* @__PURE__ */ jsxs14("div", { className: "relative flex flex-col justify-center", children: [
1040
+ /* @__PURE__ */ jsxs14(Popover, { onOpenChange: setOpen, open, children: [
1041
+ /* @__PURE__ */ jsx18(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx18(
1506
1042
  Button,
1507
1043
  {
1044
+ "aria-busy": loading || void 0,
1508
1045
  "aria-controls": listboxId,
1046
+ "aria-describedby": ariaDescribedBy,
1509
1047
  "aria-expanded": open,
1510
1048
  "aria-haspopup": "listbox",
1049
+ "aria-invalid": ariaInvalid ?? (error ? true : void 0),
1050
+ "aria-label": ariaLabel,
1051
+ "aria-labelledby": ariaLabelledBy,
1511
1052
  className: buttonClassName,
1512
- disabled,
1513
- isLoading: loading,
1053
+ disabled: disabled || loading,
1054
+ id,
1514
1055
  onBlur,
1515
1056
  ref: divRef,
1516
1057
  role: "combobox",
1517
1058
  variant: "primary",
1518
- children: loading ? /* @__PURE__ */ jsxs17(Fragment3, { children: [
1059
+ children: loading ? /* @__PURE__ */ jsxs14(Fragment3, { children: [
1519
1060
  loadingLabel ?? t("selectInput.loading"),
1520
1061
  " ",
1521
- /* @__PURE__ */ jsx24(Spinner, {})
1522
- ] }) : /* @__PURE__ */ jsx24("div", { className: "relative flex h-5 w-full items-center", children: timeField ? /* @__PURE__ */ jsxs17("div", { className: "text-title flex w-full items-center justify-center gap-2 truncate text-sm", children: [
1523
- valueItem ? filteredOptions.find((i) => i[valueKey] === valueItem)?.[labelKey] : /* @__PURE__ */ jsx24("span", { className: cn(inputPlaceholder, placeholderClassName), children: resolvedPlaceholder }),
1524
- /* @__PURE__ */ jsx24(ClockIcon, { className: "text-border h-3.5 w-3.5 shrink-0" })
1525
- ] }) : /* @__PURE__ */ jsxs17(Fragment3, { children: [
1526
- /* @__PURE__ */ jsxs17("div", { className: "flex w-full max-w-[90%] items-center truncate", children: [
1527
- leftIcon && /* @__PURE__ */ jsx24("span", { className: "mr-2 shrink-0", children: cloneElement(leftIcon, { size: 20, strokeWidth: 1 }) }),
1528
- valueItem ? filteredOptions.find((i) => i[valueKey] === valueItem)?.[labelKey] : /* @__PURE__ */ jsx24("span", { className: cn(inputPlaceholder, placeholderClassName), children: resolvedPlaceholder })
1062
+ /* @__PURE__ */ jsx18(Spinner, { size: "sm" })
1063
+ ] }) : /* @__PURE__ */ jsx18("div", { className: "relative flex h-5 w-full items-center", children: timeField ? /* @__PURE__ */ jsxs14("div", { className: "text-title flex w-full items-center justify-center gap-2 truncate text-sm", children: [
1064
+ valueItem ? filteredOptions.find((i) => i[valueKey] === valueItem)?.[labelKey] : /* @__PURE__ */ jsx18("span", { className: cn(inputPlaceholder, placeholderClassName), children: resolvedPlaceholder }),
1065
+ /* @__PURE__ */ jsx18(ClockIcon, { "aria-hidden": true, className: "text-border h-3.5 w-3.5 shrink-0" })
1066
+ ] }) : /* @__PURE__ */ jsxs14(Fragment3, { children: [
1067
+ /* @__PURE__ */ jsxs14("div", { className: "flex w-full max-w-[90%] items-center truncate", children: [
1068
+ leftIcon && /* @__PURE__ */ jsx18("span", { className: "mr-2 shrink-0", children: cloneElement(leftIcon, { size: 20, strokeWidth: 1 }) }),
1069
+ valueItem ? filteredOptions.find((i) => i[valueKey] === valueItem)?.[labelKey] : /* @__PURE__ */ jsx18("span", { className: cn(inputPlaceholder, placeholderClassName), children: resolvedPlaceholder })
1529
1070
  ] }),
1530
- /* @__PURE__ */ jsxs17("div", { className: "absolute top-0.5 right-0 flex gap-2", children: [
1531
- ableDeleteOption && /* @__PURE__ */ jsx24("div", { "aria-hidden": true, className: "h-4 w-4 shrink-0" }),
1532
- !open ? /* @__PURE__ */ jsx24(CaretDownIcon, { className: "ml-2 h-4 w-4 shrink-0 opacity-50" }) : /* @__PURE__ */ jsx24(CaretUpIcon, { className: "ml-2 h-4 w-4 shrink-0 opacity-50" })
1071
+ /* @__PURE__ */ jsxs14("div", { className: "absolute top-0.5 right-0 flex gap-2", children: [
1072
+ ableDeleteOption && /* @__PURE__ */ jsx18("div", { "aria-hidden": true, className: "h-4 w-4 shrink-0" }),
1073
+ !open ? /* @__PURE__ */ jsx18(CaretDownIcon, { "aria-hidden": true, className: "ml-2 h-4 w-4 shrink-0 opacity-50" }) : /* @__PURE__ */ jsx18(CaretUpIcon, { "aria-hidden": true, className: "ml-2 h-4 w-4 shrink-0 opacity-50" })
1533
1074
  ] })
1534
1075
  ] }) })
1535
1076
  }
1536
1077
  ) }),
1537
- /* @__PURE__ */ jsx24(
1078
+ /* @__PURE__ */ jsx18(
1538
1079
  PopoverContent,
1539
1080
  {
1540
1081
  className: cn("bg-surface border-border rounded-sm p-1", zPopoverAboveDialog),
1541
1082
  id: listboxId,
1542
1083
  onOpenAutoFocus: (e) => e.preventDefault(),
1543
1084
  style: timeField ? { maxWidth: "auto", width: "180px" } : width > 0 ? { maxWidth: "auto", minWidth: `${width}px`, width: `${width}px` } : void 0,
1544
- children: timeField ? /* @__PURE__ */ jsx24(
1085
+ children: timeField ? /* @__PURE__ */ jsx18(
1545
1086
  TimeColumns,
1546
1087
  {
1547
1088
  hours: timeHours,
@@ -1550,8 +1091,8 @@ var SelectInput = (props) => {
1550
1091
  onSelectMinute: handleSelectMinute,
1551
1092
  value: valueItem
1552
1093
  }
1553
- ) : /* @__PURE__ */ jsxs17(Command, { className: "flex w-full flex-col gap-2", children: [
1554
- search && /* @__PURE__ */ jsx24(
1094
+ ) : /* @__PURE__ */ jsxs14(Command, { className: "flex w-full flex-col gap-2", children: [
1095
+ search && /* @__PURE__ */ jsx18(
1555
1096
  Input,
1556
1097
  {
1557
1098
  className: "mb-1 rounded-sm",
@@ -1560,11 +1101,11 @@ var SelectInput = (props) => {
1560
1101
  value: query
1561
1102
  }
1562
1103
  ),
1563
- /* @__PURE__ */ jsx24(CommandEmpty, { className: "text-center", children: noResultsLabel ?? t("selectInput.noResults") }),
1564
- /* @__PURE__ */ jsx24(CommandList, { children: /* @__PURE__ */ jsx24(CommandGroup, { className: "p-0", children: filteredOptions.map((item) => {
1104
+ /* @__PURE__ */ jsx18(CommandEmpty, { className: "text-center", children: noResultsLabel ?? t("selectInput.noResults") }),
1105
+ /* @__PURE__ */ jsx18(CommandList, { children: /* @__PURE__ */ jsx18(CommandGroup, { className: "p-0", children: filteredOptions.map((item) => {
1565
1106
  const labelValue = item[labelKey];
1566
1107
  const valueValue = item[valueKey];
1567
- return /* @__PURE__ */ jsx24(
1108
+ return /* @__PURE__ */ jsx18(
1568
1109
  CommandItem,
1569
1110
  {
1570
1111
  className: cn(
@@ -1575,7 +1116,8 @@ var SelectInput = (props) => {
1575
1116
  onChange?.(currentValue);
1576
1117
  onValueChange(currentValue);
1577
1118
  setOpen(false);
1578
- setTimeout(() => setQuery(""), QUERY_RESET_DELAY_MS);
1119
+ if (queryResetRef.current) clearTimeout(queryResetRef.current);
1120
+ queryResetRef.current = setTimeout(() => setQuery(""), QUERY_RESET_DELAY_MS);
1579
1121
  },
1580
1122
  value: valueValue,
1581
1123
  children: labelValue.trim()
@@ -1587,11 +1129,14 @@ var SelectInput = (props) => {
1587
1129
  }
1588
1130
  )
1589
1131
  ] }),
1590
- ableDeleteOption && !loading && !timeField && /* @__PURE__ */ jsx24(
1132
+ ableDeleteOption && !loading && !timeField && /* @__PURE__ */ jsx18(
1591
1133
  "button",
1592
1134
  {
1593
1135
  "aria-label": t("selectInput.clear"),
1594
- className: "absolute top-1/2 right-9 z-10 flex h-4 w-4 -translate-y-1/2 items-center justify-center",
1136
+ className: cn(
1137
+ "absolute top-1/2 right-7 z-10 flex h-8 w-8 -translate-y-1/2 items-center justify-center rounded-full",
1138
+ focusRing
1139
+ ),
1595
1140
  onClick: () => {
1596
1141
  onChange?.("");
1597
1142
  onValueChange("");
@@ -1600,14 +1145,14 @@ var SelectInput = (props) => {
1600
1145
  setOpen(false);
1601
1146
  },
1602
1147
  type: "button",
1603
- children: /* @__PURE__ */ jsx24(XIcon3, { className: "h-4 w-4 shrink-0 opacity-50" })
1148
+ children: /* @__PURE__ */ jsx18(XIcon3, { "aria-hidden": true, className: "h-4 w-4 shrink-0 opacity-50" })
1604
1149
  }
1605
1150
  )
1606
1151
  ] }) });
1607
1152
  };
1608
1153
 
1609
1154
  // src/components/form-fields/select-field.tsx
1610
- import { jsx as jsx25 } from "react/jsx-runtime";
1155
+ import { jsx as jsx19 } from "react/jsx-runtime";
1611
1156
  var SelectField = ({
1612
1157
  ableDeleteOption,
1613
1158
  className,
@@ -1623,14 +1168,14 @@ var SelectField = ({
1623
1168
  search,
1624
1169
  visualRequired
1625
1170
  }) => {
1626
- return /* @__PURE__ */ jsx25(
1171
+ return /* @__PURE__ */ jsx19(
1627
1172
  FormField,
1628
1173
  {
1629
1174
  control,
1630
1175
  name,
1631
1176
  render: ({ field, fieldState }) => {
1632
1177
  const hasError = !!fieldState.error;
1633
- return /* @__PURE__ */ jsx25(
1178
+ return /* @__PURE__ */ jsx19(
1634
1179
  FormFieldShell,
1635
1180
  {
1636
1181
  hasError,
@@ -1639,9 +1184,10 @@ var SelectField = ({
1639
1184
  mainClassName,
1640
1185
  name,
1641
1186
  visualRequired,
1642
- children: /* @__PURE__ */ jsx25(
1187
+ children: (controlProps) => /* @__PURE__ */ jsx19(
1643
1188
  SelectInput,
1644
1189
  {
1190
+ ...controlProps,
1645
1191
  ableDeleteOption,
1646
1192
  className,
1647
1193
  disabled,
@@ -1665,13 +1211,13 @@ var SelectField = ({
1665
1211
 
1666
1212
  // src/components/password-checklist.tsx
1667
1213
  import { CheckCircleIcon as CheckCircleIcon2, XCircleIcon } from "@phosphor-icons/react";
1668
- import { jsx as jsx26, jsxs as jsxs18 } from "react/jsx-runtime";
1214
+ import { jsx as jsx20, jsxs as jsxs15 } from "react/jsx-runtime";
1669
1215
  var PasswordChecklist = ({ className, rules, value }) => {
1670
1216
  if (rules.length === 0) return null;
1671
- return /* @__PURE__ */ jsx26("ul", { className: cn("flex flex-col gap-1", className), children: rules.map((rule) => {
1217
+ return /* @__PURE__ */ jsx20("ul", { className: cn("flex flex-col gap-1", className), children: rules.map((rule) => {
1672
1218
  const isMet = rule.test(value);
1673
1219
  const Icon = isMet ? CheckCircleIcon2 : XCircleIcon;
1674
- return /* @__PURE__ */ jsxs18(
1220
+ return /* @__PURE__ */ jsxs15(
1675
1221
  "li",
1676
1222
  {
1677
1223
  className: cn(
@@ -1679,8 +1225,8 @@ var PasswordChecklist = ({ className, rules, value }) => {
1679
1225
  isMet ? "text-success" : "text-inactive-text"
1680
1226
  ),
1681
1227
  children: [
1682
- /* @__PURE__ */ jsx26(Icon, { "aria-hidden": "true", className: "h-4 w-4 shrink-0" }),
1683
- /* @__PURE__ */ jsx26("span", { children: rule.label })
1228
+ /* @__PURE__ */ jsx20(Icon, { "aria-hidden": "true", className: "h-4 w-4 shrink-0" }),
1229
+ /* @__PURE__ */ jsx20("span", { children: rule.label })
1684
1230
  ]
1685
1231
  },
1686
1232
  rule.key
@@ -1689,22 +1235,22 @@ var PasswordChecklist = ({ className, rules, value }) => {
1689
1235
  };
1690
1236
 
1691
1237
  // src/components/step-header.tsx
1692
- import { jsx as jsx27, jsxs as jsxs19 } from "react/jsx-runtime";
1693
- var StepHeader = ({ subtitle, subtitleClassName, title }) => /* @__PURE__ */ jsxs19("div", { className: "flex flex-col gap-1", children: [
1694
- /* @__PURE__ */ jsx27("h1", { className: "text-title text-2xl font-bold", children: title }),
1695
- subtitle !== void 0 && /* @__PURE__ */ jsx27("p", { className: cn("text-subtitle text-sm", subtitleClassName), children: subtitle })
1238
+ import { jsx as jsx21, jsxs as jsxs16 } from "react/jsx-runtime";
1239
+ var StepHeader = ({ subtitle, subtitleClassName, title }) => /* @__PURE__ */ jsxs16("div", { className: "flex flex-col gap-1", children: [
1240
+ /* @__PURE__ */ jsx21("h1", { className: "text-title text-2xl font-bold", children: title }),
1241
+ subtitle !== void 0 && /* @__PURE__ */ jsx21("p", { className: cn("text-subtitle text-sm", subtitleClassName), children: subtitle })
1696
1242
  ] });
1697
1243
 
1698
1244
  // src/components/stepper.tsx
1699
1245
  import { CheckIcon } from "@phosphor-icons/react";
1700
- import { jsx as jsx28, jsxs as jsxs20 } from "react/jsx-runtime";
1246
+ import { jsx as jsx22, jsxs as jsxs17 } from "react/jsx-runtime";
1701
1247
  var Stepper = ({ activeIndex, className, intermediate = false, steps }) => {
1702
- return /* @__PURE__ */ jsx28("div", { className: cn("flex w-full items-start", className), children: steps.map((step, index) => {
1248
+ return /* @__PURE__ */ jsx22("div", { className: cn("flex w-full items-start", className), children: steps.map((step, index) => {
1703
1249
  const isCompleted = intermediate ? index <= activeIndex : index < activeIndex;
1704
1250
  const isActive = !intermediate && index === activeIndex;
1705
- return /* @__PURE__ */ jsxs20("div", { className: "flex flex-1 flex-col items-center", children: [
1706
- /* @__PURE__ */ jsxs20("div", { className: "flex w-full items-center", children: [
1707
- /* @__PURE__ */ jsx28(
1251
+ return /* @__PURE__ */ jsxs17("div", { className: "flex flex-1 flex-col items-center", children: [
1252
+ /* @__PURE__ */ jsxs17("div", { className: "flex w-full items-center", children: [
1253
+ /* @__PURE__ */ jsx22(
1708
1254
  "div",
1709
1255
  {
1710
1256
  className: cn(
@@ -1714,7 +1260,7 @@ var Stepper = ({ activeIndex, className, intermediate = false, steps }) => {
1714
1260
  )
1715
1261
  }
1716
1262
  ),
1717
- /* @__PURE__ */ jsx28(
1263
+ /* @__PURE__ */ jsx22(
1718
1264
  "div",
1719
1265
  {
1720
1266
  "aria-current": isActive ? "step" : void 0,
@@ -1722,12 +1268,12 @@ var Stepper = ({ activeIndex, className, intermediate = false, steps }) => {
1722
1268
  "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",
1723
1269
  isCompleted && "bg-primary border-primary text-inverse",
1724
1270
  isActive && "bg-primary border-primary text-inverse",
1725
- !isCompleted && !isActive && "bg-inactive border-inactive text-surface"
1271
+ !isCompleted && !isActive && "bg-inactive border-inactive text-inverse"
1726
1272
  ),
1727
- children: isCompleted ? /* @__PURE__ */ jsx28(CheckIcon, { className: "h-4 w-4" }) : index + 1
1273
+ children: isCompleted ? /* @__PURE__ */ jsx22(CheckIcon, { "aria-hidden": true, className: "h-4 w-4" }) : index + 1
1728
1274
  }
1729
1275
  ),
1730
- /* @__PURE__ */ jsx28(
1276
+ /* @__PURE__ */ jsx22(
1731
1277
  "div",
1732
1278
  {
1733
1279
  className: cn(
@@ -1735,7 +1281,7 @@ var Stepper = ({ activeIndex, className, intermediate = false, steps }) => {
1735
1281
  isCompleted ? "bg-primary" : "bg-inactive",
1736
1282
  index === steps.length - 1 && "rounded-r-full"
1737
1283
  ),
1738
- children: index === 0 && /* @__PURE__ */ jsx28(
1284
+ children: index === 0 && /* @__PURE__ */ jsx22(
1739
1285
  "div",
1740
1286
  {
1741
1287
  className: cn(
@@ -1747,39 +1293,40 @@ var Stepper = ({ activeIndex, className, intermediate = false, steps }) => {
1747
1293
  }
1748
1294
  )
1749
1295
  ] }),
1750
- /* @__PURE__ */ jsx28("span", { className: cn("mt-1 text-xs font-normal", isCompleted || isActive ? "text-primary" : "text-muted"), children: step.label })
1296
+ /* @__PURE__ */ jsx22("span", { className: cn("mt-1 text-xs font-normal", isCompleted || isActive ? "text-primary" : "text-muted"), children: step.label })
1751
1297
  ] }, step.label);
1752
1298
  }) });
1753
1299
  };
1754
1300
 
1755
1301
  // src/components/switch.tsx
1756
1302
  import * as SwitchPrimitive from "@radix-ui/react-switch";
1757
- import * as React15 from "react";
1758
- import { jsx as jsx29 } from "react/jsx-runtime";
1759
- var Switch = React15.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx29(
1303
+ import * as React13 from "react";
1304
+ import { jsx as jsx23 } from "react/jsx-runtime";
1305
+ var Switch = React13.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx23(
1760
1306
  SwitchPrimitive.Root,
1761
1307
  {
1762
1308
  className: cn(
1763
- "border-border focus-visible:ring-ring data-[state=checked]:bg-success data-[state=unchecked]:bg-inactive relative inline-flex h-[26px] w-[50px] shrink-0 cursor-pointer items-center rounded-full border transition-colors focus-visible:ring-2 focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50",
1309
+ "border-border data-[state=checked]:bg-success data-[state=unchecked]:bg-inactive relative inline-flex h-[26px] w-[50px] shrink-0 cursor-pointer items-center rounded-full border transition-colors disabled:cursor-not-allowed disabled:opacity-50",
1310
+ focusRing,
1764
1311
  className
1765
1312
  ),
1766
1313
  ref,
1767
1314
  ...props,
1768
- children: /* @__PURE__ */ jsx29(SwitchPrimitive.Thumb, { className: "bg-surface pointer-events-none absolute top-[3px] left-[3px] block h-[18px] w-[18px] rounded-full shadow-lg transition-transform data-[state=checked]:translate-x-6" })
1315
+ children: /* @__PURE__ */ jsx23(SwitchPrimitive.Thumb, { className: "bg-surface pointer-events-none absolute top-[3px] left-[3px] block h-[18px] w-[18px] rounded-full shadow-lg transition-transform data-[state=checked]:translate-x-6" })
1769
1316
  }
1770
1317
  ));
1771
1318
  Switch.displayName = SwitchPrimitive.Root.displayName;
1772
1319
 
1773
1320
  // src/components/textarea.tsx
1774
- import * as React16 from "react";
1775
- import { jsx as jsx30 } from "react/jsx-runtime";
1776
- var Textarea = React16.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx30("textarea", { className: cn(inputSurface, inputFocus, "block h-28 resize-none py-3", className), ref, ...props }));
1321
+ import * as React14 from "react";
1322
+ import { jsx as jsx24 } from "react/jsx-runtime";
1323
+ var Textarea = React14.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx24("textarea", { className: cn(inputSurface, inputFocus, "block h-28 resize-none py-3", className), ref, ...props }));
1777
1324
  Textarea.displayName = "Textarea";
1778
1325
 
1779
1326
  // src/components/toast/toast.tsx
1780
1327
  import { CheckIcon as CheckIcon2, FileLockIcon, InfoIcon as InfoIcon2, WarningIcon as WarningIcon2, XIcon as XIcon4 } from "@phosphor-icons/react";
1781
- import { useEffect as useEffect4, useRef as useRef4, useState as useState5 } from "react";
1782
- import { jsx as jsx31, jsxs as jsxs21 } from "react/jsx-runtime";
1328
+ import { useEffect as useEffect4, useRef as useRef4, useState as useState4 } from "react";
1329
+ import { jsx as jsx25, jsxs as jsxs18 } from "react/jsx-runtime";
1783
1330
  var EXIT_ANIMATION_MS = 200;
1784
1331
  var typeIcons = {
1785
1332
  destructive: XIcon4,
@@ -1796,7 +1343,7 @@ var typeStyles = {
1796
1343
  warning: { border: "border-warning", icon: "text-warning", iconBorder: "border-warning" }
1797
1344
  };
1798
1345
  function Toast({ duration = 2500, id, onClose, subtitle, title, type }) {
1799
- const [leaving, setLeaving] = useState5(false);
1346
+ const [leaving, setLeaving] = useState4(false);
1800
1347
  const startedAtRef = useRef4(Date.now());
1801
1348
  const timeoutRef = useRef4(null);
1802
1349
  const exitRef = useRef4(null);
@@ -1816,10 +1363,9 @@ function Toast({ duration = 2500, id, onClose, subtitle, title, type }) {
1816
1363
  if (exitRef.current) clearTimeout(exitRef.current);
1817
1364
  };
1818
1365
  }, [id, duration, onClose]);
1819
- return /* @__PURE__ */ jsxs21(
1366
+ return /* @__PURE__ */ jsxs18(
1820
1367
  "div",
1821
1368
  {
1822
- "aria-live": "polite",
1823
1369
  className: cn(
1824
1370
  "relative",
1825
1371
  leaving ? "absolute top-0 right-0 left-0" : "",
@@ -1832,19 +1378,19 @@ function Toast({ duration = 2500, id, onClose, subtitle, title, type }) {
1832
1378
  styles.border,
1833
1379
  leaving ? "translate-y-2 opacity-0" : "translate-y-0 opacity-100"
1834
1380
  ),
1835
- role: "status",
1381
+ role: type === "destructive" ? "alert" : "status",
1836
1382
  children: [
1837
- /* @__PURE__ */ jsx31("div", { className: "min-w-0 pr-4", children: /* @__PURE__ */ jsx31("h4", { className: cn("text-[16px] leading-normal font-semibold", "text-foreground", "line-clamp-2"), children: title }) }),
1838
- subtitle ? /* @__PURE__ */ jsx31("div", { className: "shrink-0 pr-4 text-left", children: /* @__PURE__ */ jsx31("div", { className: cn("max-w-28 text-[14px] leading-[19.5px] font-normal", "text-body"), children: subtitle }) }) : null,
1839
- /* @__PURE__ */ jsx31(
1383
+ /* @__PURE__ */ jsx25("div", { className: "min-w-0 pr-4", children: /* @__PURE__ */ jsx25("h4", { className: cn("text-base leading-normal font-semibold", "text-foreground", "line-clamp-2"), children: title }) }),
1384
+ subtitle ? /* @__PURE__ */ jsx25("div", { className: "shrink-0 pr-4 text-left", children: /* @__PURE__ */ jsx25("div", { className: cn("max-w-28 text-sm font-normal", "text-body"), children: subtitle }) }) : null,
1385
+ /* @__PURE__ */ jsx25(
1840
1386
  "div",
1841
1387
  {
1842
1388
  className: cn(
1843
1389
  "shrink-0",
1844
- "flex h-8 w-8 min-w-8 items-center justify-center rounded-full border-2",
1390
+ "flex size-8 min-w-8 items-center justify-center rounded-full border-2",
1845
1391
  styles.iconBorder
1846
1392
  ),
1847
- children: /* @__PURE__ */ jsx31(Icon, { className: cn("h-5 w-5", styles.icon) })
1393
+ children: /* @__PURE__ */ jsx25(Icon, { "aria-hidden": true, className: cn("h-5 w-5", styles.icon) })
1848
1394
  }
1849
1395
  )
1850
1396
  ]
@@ -1853,13 +1399,13 @@ function Toast({ duration = 2500, id, onClose, subtitle, title, type }) {
1853
1399
  }
1854
1400
 
1855
1401
  // src/components/toast/toast-provider.tsx
1856
- import { useCallback as useCallback3, useEffect as useEffect5, useLayoutEffect, useMemo as useMemo4, useRef as useRef5, useState as useState6 } from "react";
1857
- import { Fragment as Fragment4, jsx as jsx32 } from "react/jsx-runtime";
1402
+ import { useCallback as useCallback2, useEffect as useEffect5, useLayoutEffect, useMemo as useMemo3, useRef as useRef5, useState as useState5 } from "react";
1403
+ import { Fragment as Fragment4, jsx as jsx26 } from "react/jsx-runtime";
1858
1404
  function ToastProvider() {
1859
- const [toasts, setToasts] = useState6([]);
1405
+ const [toasts, setToasts] = useState5([]);
1860
1406
  const itemRefs = useRef5(/* @__PURE__ */ new Map());
1861
1407
  const prevRects = useRef5(/* @__PURE__ */ new Map());
1862
- const showToast = useCallback3((type, options) => {
1408
+ const showToast = useCallback2((type, options) => {
1863
1409
  setToasts((prev) => [
1864
1410
  ...prev,
1865
1411
  {
@@ -1871,14 +1417,14 @@ function ToastProvider() {
1871
1417
  }
1872
1418
  ]);
1873
1419
  }, []);
1874
- const removeToast = useCallback3((id) => {
1420
+ const removeToast = useCallback2((id) => {
1875
1421
  setToasts((prev) => prev.filter((t) => t.id !== id));
1876
1422
  }, []);
1877
1423
  useEffect5(() => {
1878
1424
  registerToastEmitter(showToast);
1879
1425
  return () => registerToastEmitter(null);
1880
1426
  }, [showToast]);
1881
- const grouped = useMemo4(() => {
1427
+ const grouped = useMemo3(() => {
1882
1428
  return toasts.reduce((acc, toast2) => {
1883
1429
  const pos = toast2.position ?? "top";
1884
1430
  acc[pos] = [...acc[pos] ?? [], toast2];
@@ -1905,7 +1451,7 @@ function ToastProvider() {
1905
1451
  });
1906
1452
  prevRects.current = newRects;
1907
1453
  }, [toasts]);
1908
- const setItemRef = useCallback3((id) => {
1454
+ const setItemRef = useCallback2((id) => {
1909
1455
  return (el) => {
1910
1456
  if (!el) {
1911
1457
  itemRefs.current.delete(id);
@@ -1915,7 +1461,7 @@ function ToastProvider() {
1915
1461
  itemRefs.current.set(id, el);
1916
1462
  };
1917
1463
  }, []);
1918
- return /* @__PURE__ */ jsx32(Fragment4, { children: Object.entries(grouped).map(([position, list]) => /* @__PURE__ */ jsx32("div", { className: `fixed ${zToast} ${getPositionClass(position)}`, children: /* @__PURE__ */ jsx32("div", { className: "relative flex flex-col gap-3", children: list.map((toast2) => /* @__PURE__ */ jsx32("div", { ref: setItemRef(toast2.id), children: /* @__PURE__ */ jsx32(
1464
+ return /* @__PURE__ */ jsx26(Fragment4, { children: Object.entries(grouped).map(([position, list]) => /* @__PURE__ */ jsx26("div", { className: `fixed ${zToast} ${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(
1919
1465
  Toast,
1920
1466
  {
1921
1467
  duration: toast2.duration,
@@ -1943,9 +1489,9 @@ function getPositionClass(position) {
1943
1489
  }
1944
1490
 
1945
1491
  // src/components/wrapper.tsx
1946
- import { jsx as jsx33 } from "react/jsx-runtime";
1492
+ import { jsx as jsx27 } from "react/jsx-runtime";
1947
1493
  var Wrapper = ({ children, className }) => {
1948
- return /* @__PURE__ */ jsx33("div", { className: cn("mx-auto h-full w-full", className), children });
1494
+ return /* @__PURE__ */ jsx27("div", { className: cn("mx-auto h-full w-full", className), children });
1949
1495
  };
1950
1496
  export {
1951
1497
  AddTile,
@@ -2003,11 +1549,16 @@ export {
2003
1549
  Toast,
2004
1550
  ToastProvider,
2005
1551
  Tooltip,
1552
+ TooltipContent,
1553
+ TooltipProvider,
1554
+ TooltipRoot,
1555
+ TooltipTrigger,
2006
1556
  Wrapper,
2007
1557
  buttonVariants,
2008
1558
  capitalize,
2009
1559
  chipVariants,
2010
1560
  cn,
1561
+ focusRing,
2011
1562
  formatNumber,
2012
1563
  formatPrice,
2013
1564
  getTagEmoji,