@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.
- package/dist/index.d.ts +420 -0
- package/dist/index.js +1710 -0
- package/dist/index.js.map +1 -0
- package/dist/locales/index.d.ts +34 -0
- package/dist/locales/index.js +40 -0
- package/dist/locales/index.js.map +1 -0
- package/dist/styles/index.css +8 -0
- package/package.json +24 -8
- package/src/components/alert.tsx +0 -45
- package/src/components/auth-header.tsx +0 -26
- package/src/components/button.tsx +0 -121
- package/src/components/command.tsx +0 -125
- package/src/components/dialog.tsx +0 -118
- package/src/components/form-fields/index.ts +0 -5
- package/src/components/form-fields/input-field.tsx +0 -131
- package/src/components/form-fields/label-field.tsx +0 -20
- package/src/components/form-fields/map-picker-field.tsx +0 -49
- package/src/components/form-fields/otp-field.tsx +0 -76
- package/src/components/form-fields/select-field.tsx +0 -77
- package/src/components/form.tsx +0 -138
- package/src/components/google-map-picker.tsx +0 -243
- package/src/components/input.tsx +0 -40
- package/src/components/label.tsx +0 -17
- package/src/components/loading.tsx +0 -19
- package/src/components/otp-input.tsx +0 -62
- package/src/components/password-checklist.tsx +0 -37
- package/src/components/popover.tsx +0 -31
- package/src/components/select-input.tsx +0 -236
- package/src/components/select.tsx +0 -143
- package/src/components/spinner.tsx +0 -61
- package/src/components/step-header.tsx +0 -16
- package/src/components/stepper.tsx +0 -69
- package/src/components/toast/index.ts +0 -2
- package/src/components/toast/toast-provider.tsx +0 -123
- package/src/components/toast/toast.tsx +0 -106
- package/src/components/tooltip.tsx +0 -56
- package/src/components/wrapper.tsx +0 -12
- package/src/index.ts +0 -27
- package/src/locales/es/ui.json +0 -28
- package/src/locales/index.ts +0 -7
- package/src/styles/index.css +0 -1
- package/src/types/password.ts +0 -12
- package/src/types/toast.ts +0 -19
- package/src/utils/cn.ts +0 -6
- package/src/utils/index.ts +0 -3
- package/src/utils/styles.ts +0 -19
- package/src/utils/toast-emitter.ts +0 -37
- package/src/vite-env.d.ts +0 -3
- /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
|