@underverse-ui/underverse 0.1.38 → 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.cjs +511 -155
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +41 -3
- package/dist/index.d.ts +41 -3
- package/dist/index.js +545 -189
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -5173,24 +5173,29 @@ var DateRangePicker = ({ startDate, endDate, onChange, placeholder = "Select dat
|
|
|
5173
5173
|
|
|
5174
5174
|
// ../../components/ui/TimePicker.tsx
|
|
5175
5175
|
import * as React22 from "react";
|
|
5176
|
-
import { Clock as Clock2, X as X8 } from "lucide-react";
|
|
5177
|
-
import { jsx as jsx29, jsxs as jsxs24 } from "react/jsx-runtime";
|
|
5176
|
+
import { Clock as Clock2, X as X8, Check as Check4 } from "lucide-react";
|
|
5177
|
+
import { Fragment as Fragment7, jsx as jsx29, jsxs as jsxs24 } from "react/jsx-runtime";
|
|
5178
5178
|
var pad = (n) => n.toString().padStart(2, "0");
|
|
5179
5179
|
function parseTime(input, fmt = "24", includeSeconds) {
|
|
5180
5180
|
if (!input) return null;
|
|
5181
|
-
|
|
5182
|
-
|
|
5183
|
-
|
|
5184
|
-
|
|
5185
|
-
|
|
5186
|
-
|
|
5187
|
-
|
|
5188
|
-
|
|
5189
|
-
|
|
5190
|
-
|
|
5191
|
-
|
|
5192
|
-
|
|
5193
|
-
|
|
5181
|
+
try {
|
|
5182
|
+
const s = input.trim().toUpperCase();
|
|
5183
|
+
const ampm = s.endsWith("AM") || s.endsWith("PM");
|
|
5184
|
+
const clean = s.replace(/\s*(AM|PM)\s*$/, "");
|
|
5185
|
+
const segs = clean.split(":");
|
|
5186
|
+
const h = Number(segs[0]);
|
|
5187
|
+
const m = Number(segs[1] ?? 0);
|
|
5188
|
+
const sec = Number(segs[2] ?? 0);
|
|
5189
|
+
if (Number.isNaN(h) || Number.isNaN(m) || Number.isNaN(sec)) return null;
|
|
5190
|
+
if (fmt === "12" || ampm) {
|
|
5191
|
+
const p = s.endsWith("PM") ? "PM" : "AM";
|
|
5192
|
+
return { h: Math.max(1, Math.min(12, h)), m: Math.max(0, Math.min(59, m)), s: Math.max(0, Math.min(59, sec)), p };
|
|
5193
|
+
}
|
|
5194
|
+
return { h: Math.max(0, Math.min(23, h)), m: Math.max(0, Math.min(59, m)), s: Math.max(0, Math.min(59, sec)) };
|
|
5195
|
+
} catch (error) {
|
|
5196
|
+
console.error("Error parsing time:", error);
|
|
5197
|
+
return null;
|
|
5198
|
+
}
|
|
5194
5199
|
}
|
|
5195
5200
|
function formatTime2({ h, m, s, p }, fmt, includeSeconds) {
|
|
5196
5201
|
if (fmt === "12") {
|
|
@@ -5226,6 +5231,16 @@ function TimePicker({
|
|
|
5226
5231
|
showNow = false,
|
|
5227
5232
|
showPresets = false,
|
|
5228
5233
|
allowManualInput = false,
|
|
5234
|
+
customPresets = [],
|
|
5235
|
+
minTime,
|
|
5236
|
+
maxTime,
|
|
5237
|
+
disabledTimes,
|
|
5238
|
+
error,
|
|
5239
|
+
success,
|
|
5240
|
+
helperText,
|
|
5241
|
+
animate = true,
|
|
5242
|
+
onOpen,
|
|
5243
|
+
onClose,
|
|
5229
5244
|
className,
|
|
5230
5245
|
...rest
|
|
5231
5246
|
}) {
|
|
@@ -5235,14 +5250,118 @@ function TimePicker({
|
|
|
5235
5250
|
const [open, setOpen] = React22.useState(false);
|
|
5236
5251
|
const [parts, setParts] = React22.useState(initial);
|
|
5237
5252
|
const [manualInput, setManualInput] = React22.useState("");
|
|
5253
|
+
const [focusedColumn, setFocusedColumn] = React22.useState(null);
|
|
5254
|
+
const hourScrollRef = React22.useRef(null);
|
|
5255
|
+
const minuteScrollRef = React22.useRef(null);
|
|
5256
|
+
const secondScrollRef = React22.useRef(null);
|
|
5238
5257
|
React22.useEffect(() => {
|
|
5239
5258
|
if (isControlled) {
|
|
5240
5259
|
const parsed = parseTime(value, format, includeSeconds);
|
|
5241
5260
|
if (parsed) setParts(parsed);
|
|
5242
5261
|
}
|
|
5243
5262
|
}, [value, isControlled, format, includeSeconds]);
|
|
5263
|
+
React22.useEffect(() => {
|
|
5264
|
+
if (!open) return;
|
|
5265
|
+
const scrollToSelected = (ref, targetValue, step) => {
|
|
5266
|
+
if (!ref.current) return;
|
|
5267
|
+
const buttons = ref.current.querySelectorAll("button");
|
|
5268
|
+
const targetIndex = Math.floor(targetValue / step);
|
|
5269
|
+
const targetButton = buttons[targetIndex];
|
|
5270
|
+
if (targetButton) {
|
|
5271
|
+
targetButton.scrollIntoView({ behavior: animate ? "smooth" : "auto", block: "center" });
|
|
5272
|
+
}
|
|
5273
|
+
};
|
|
5274
|
+
setTimeout(() => {
|
|
5275
|
+
scrollToSelected(hourScrollRef, parts.h, 1);
|
|
5276
|
+
scrollToSelected(minuteScrollRef, parts.m, minuteStep);
|
|
5277
|
+
if (includeSeconds) scrollToSelected(secondScrollRef, parts.s, secondStep);
|
|
5278
|
+
}, 50);
|
|
5279
|
+
}, [open, parts.h, parts.m, parts.s, minuteStep, secondStep, includeSeconds, animate]);
|
|
5280
|
+
const isTimeDisabled = React22.useCallback((timeStr) => {
|
|
5281
|
+
if (!disabledTimes) return false;
|
|
5282
|
+
if (typeof disabledTimes === "function") return disabledTimes(timeStr);
|
|
5283
|
+
return disabledTimes.includes(timeStr);
|
|
5284
|
+
}, [disabledTimes]);
|
|
5285
|
+
const isTimeInRange = React22.useCallback((timeStr) => {
|
|
5286
|
+
if (!minTime && !maxTime) return true;
|
|
5287
|
+
const parsed = parseTime(timeStr, format, includeSeconds);
|
|
5288
|
+
if (!parsed) return true;
|
|
5289
|
+
if (minTime) {
|
|
5290
|
+
const min = parseTime(minTime, format, includeSeconds);
|
|
5291
|
+
if (min) {
|
|
5292
|
+
const currentMinutes = parsed.h * 60 + parsed.m;
|
|
5293
|
+
const minMinutes = min.h * 60 + min.m;
|
|
5294
|
+
if (currentMinutes < minMinutes) return false;
|
|
5295
|
+
}
|
|
5296
|
+
}
|
|
5297
|
+
if (maxTime) {
|
|
5298
|
+
const max = parseTime(maxTime, format, includeSeconds);
|
|
5299
|
+
if (max) {
|
|
5300
|
+
const currentMinutes = parsed.h * 60 + parsed.m;
|
|
5301
|
+
const maxMinutes = max.h * 60 + max.m;
|
|
5302
|
+
if (currentMinutes > maxMinutes) return false;
|
|
5303
|
+
}
|
|
5304
|
+
}
|
|
5305
|
+
return true;
|
|
5306
|
+
}, [minTime, maxTime, format, includeSeconds]);
|
|
5244
5307
|
const emit = (next) => {
|
|
5245
|
-
|
|
5308
|
+
const timeStr = next ? formatTime2(next, format, includeSeconds) : void 0;
|
|
5309
|
+
if (timeStr && !isTimeInRange(timeStr)) return;
|
|
5310
|
+
if (timeStr && isTimeDisabled(timeStr)) return;
|
|
5311
|
+
onChange?.(timeStr);
|
|
5312
|
+
};
|
|
5313
|
+
const handleOpenChange = (newOpen) => {
|
|
5314
|
+
setOpen(newOpen);
|
|
5315
|
+
if (newOpen) {
|
|
5316
|
+
onOpen?.();
|
|
5317
|
+
} else {
|
|
5318
|
+
onClose?.();
|
|
5319
|
+
setFocusedColumn(null);
|
|
5320
|
+
}
|
|
5321
|
+
};
|
|
5322
|
+
const handleKeyDown = (e, column) => {
|
|
5323
|
+
if (!["ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight", "Home", "End", "PageUp", "PageDown"].includes(e.key)) return;
|
|
5324
|
+
e.preventDefault();
|
|
5325
|
+
let newParts = { ...parts };
|
|
5326
|
+
switch (column) {
|
|
5327
|
+
case "hour":
|
|
5328
|
+
if (e.key === "ArrowUp") newParts.h = format === "24" ? (parts.h + 1) % 24 : parts.h % 12 + 1;
|
|
5329
|
+
if (e.key === "ArrowDown") newParts.h = format === "24" ? (parts.h - 1 + 24) % 24 : (parts.h - 2 + 12) % 12 + 1;
|
|
5330
|
+
if (e.key === "Home") newParts.h = format === "24" ? 0 : 1;
|
|
5331
|
+
if (e.key === "End") newParts.h = format === "24" ? 23 : 12;
|
|
5332
|
+
if (e.key === "PageUp") newParts.h = format === "24" ? (parts.h + 6) % 24 : parts.h % 12 + 3;
|
|
5333
|
+
if (e.key === "PageDown") newParts.h = format === "24" ? (parts.h - 6 + 24) % 24 : (parts.h - 4 + 12) % 12 + 1;
|
|
5334
|
+
if (e.key === "ArrowRight") setFocusedColumn("minute");
|
|
5335
|
+
break;
|
|
5336
|
+
case "minute":
|
|
5337
|
+
if (e.key === "ArrowUp") newParts.m = (parts.m + minuteStep) % 60;
|
|
5338
|
+
if (e.key === "ArrowDown") newParts.m = (parts.m - minuteStep + 60) % 60;
|
|
5339
|
+
if (e.key === "Home") newParts.m = 0;
|
|
5340
|
+
if (e.key === "End") newParts.m = 59 - 59 % minuteStep;
|
|
5341
|
+
if (e.key === "PageUp") newParts.m = (parts.m + minuteStep * 3) % 60;
|
|
5342
|
+
if (e.key === "PageDown") newParts.m = (parts.m - minuteStep * 3 + 60) % 60;
|
|
5343
|
+
if (e.key === "ArrowLeft") setFocusedColumn("hour");
|
|
5344
|
+
if (e.key === "ArrowRight") setFocusedColumn(includeSeconds ? "second" : format === "12" ? "period" : null);
|
|
5345
|
+
break;
|
|
5346
|
+
case "second":
|
|
5347
|
+
if (e.key === "ArrowUp") newParts.s = (parts.s + secondStep) % 60;
|
|
5348
|
+
if (e.key === "ArrowDown") newParts.s = (parts.s - secondStep + 60) % 60;
|
|
5349
|
+
if (e.key === "Home") newParts.s = 0;
|
|
5350
|
+
if (e.key === "End") newParts.s = 59 - 59 % secondStep;
|
|
5351
|
+
if (e.key === "PageUp") newParts.s = (parts.s + secondStep * 3) % 60;
|
|
5352
|
+
if (e.key === "PageDown") newParts.s = (parts.s - secondStep * 3 + 60) % 60;
|
|
5353
|
+
if (e.key === "ArrowLeft") setFocusedColumn("minute");
|
|
5354
|
+
if (e.key === "ArrowRight" && format === "12") setFocusedColumn("period");
|
|
5355
|
+
break;
|
|
5356
|
+
case "period":
|
|
5357
|
+
if (e.key === "ArrowUp" || e.key === "ArrowDown" || e.key === "Home" || e.key === "End") {
|
|
5358
|
+
newParts.p = newParts.p === "AM" ? "PM" : "AM";
|
|
5359
|
+
}
|
|
5360
|
+
if (e.key === "ArrowLeft") setFocusedColumn(includeSeconds ? "second" : "minute");
|
|
5361
|
+
break;
|
|
5362
|
+
}
|
|
5363
|
+
setParts(newParts);
|
|
5364
|
+
emit(newParts);
|
|
5246
5365
|
};
|
|
5247
5366
|
const setNow = () => {
|
|
5248
5367
|
const now2 = /* @__PURE__ */ new Date();
|
|
@@ -5272,6 +5391,16 @@ function TimePicker({
|
|
|
5272
5391
|
const handleManualInput = (input) => {
|
|
5273
5392
|
setManualInput(input);
|
|
5274
5393
|
const parsed = parseTime(input, format, includeSeconds);
|
|
5394
|
+
if (parsed) {
|
|
5395
|
+
const timeStr = formatTime2(parsed, format, includeSeconds);
|
|
5396
|
+
if (isTimeInRange(timeStr) && !isTimeDisabled(timeStr)) {
|
|
5397
|
+
setParts(parsed);
|
|
5398
|
+
emit(parsed);
|
|
5399
|
+
}
|
|
5400
|
+
}
|
|
5401
|
+
};
|
|
5402
|
+
const handleCustomPreset = (time) => {
|
|
5403
|
+
const parsed = parseTime(time, format, includeSeconds);
|
|
5275
5404
|
if (parsed) {
|
|
5276
5405
|
setParts(parsed);
|
|
5277
5406
|
emit(parsed);
|
|
@@ -5293,23 +5422,30 @@ function TimePicker({
|
|
|
5293
5422
|
{
|
|
5294
5423
|
type: "button",
|
|
5295
5424
|
disabled,
|
|
5425
|
+
"aria-label": "Select time",
|
|
5426
|
+
"aria-haspopup": "dialog",
|
|
5427
|
+
"aria-expanded": open,
|
|
5296
5428
|
className: cn(
|
|
5297
|
-
"flex w-full items-center justify-between border
|
|
5429
|
+
"flex w-full items-center justify-between border bg-background",
|
|
5298
5430
|
sz.height,
|
|
5299
5431
|
sz.padding,
|
|
5300
5432
|
sz.text,
|
|
5301
5433
|
radiusClass,
|
|
5302
5434
|
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background",
|
|
5303
5435
|
"disabled:opacity-50 disabled:cursor-not-allowed",
|
|
5304
|
-
"
|
|
5436
|
+
"transition-all duration-200",
|
|
5437
|
+
error && "border-destructive focus-visible:ring-destructive",
|
|
5438
|
+
success && "border-green-500 focus-visible:ring-green-500",
|
|
5439
|
+
!error && !success && "border-input hover:bg-accent/5",
|
|
5440
|
+
animate && !disabled && "hover:shadow-md",
|
|
5305
5441
|
className
|
|
5306
5442
|
),
|
|
5307
5443
|
children: [
|
|
5308
5444
|
/* @__PURE__ */ jsxs24("div", { className: "flex items-center gap-2", children: [
|
|
5309
|
-
/* @__PURE__ */ jsx29(Clock2, { className: cn(sz.icon, "text-muted-foreground") }),
|
|
5445
|
+
/* @__PURE__ */ jsx29(Clock2, { className: cn(sz.icon, error ? "text-destructive" : success ? "text-green-500" : "text-muted-foreground") }),
|
|
5310
5446
|
/* @__PURE__ */ jsx29("span", { className: cn("truncate", !value && !defaultValue && "text-muted-foreground"), children: value || defaultValue ? display : placeholder })
|
|
5311
5447
|
] }),
|
|
5312
|
-
/* @__PURE__ */ jsx29("span", { className: cn("ml-2 transition-transform", open && "rotate-180"), children: /* @__PURE__ */ jsx29("svg", { className: sz.icon, fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx29("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M19 9l-7 7-7-7" }) }) })
|
|
5448
|
+
/* @__PURE__ */ jsx29("span", { className: cn("ml-2 transition-transform duration-200", open && "rotate-180"), children: /* @__PURE__ */ jsx29("svg", { className: sz.icon, fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx29("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M19 9l-7 7-7-7" }) }) })
|
|
5313
5449
|
]
|
|
5314
5450
|
}
|
|
5315
5451
|
);
|
|
@@ -5329,111 +5465,217 @@ function TimePicker({
|
|
|
5329
5465
|
"button",
|
|
5330
5466
|
{
|
|
5331
5467
|
type: "button",
|
|
5332
|
-
className:
|
|
5468
|
+
className: cn(
|
|
5469
|
+
"px-2 py-1.5 text-xs rounded-md border border-border hover:bg-accent/10 capitalize transition-all",
|
|
5470
|
+
animate && "hover:scale-105 active:scale-95"
|
|
5471
|
+
),
|
|
5333
5472
|
onClick: () => setPreset(preset),
|
|
5473
|
+
"aria-label": `Set time to ${preset}`,
|
|
5334
5474
|
children: preset
|
|
5335
5475
|
},
|
|
5336
5476
|
preset
|
|
5337
5477
|
)) }),
|
|
5338
|
-
/* @__PURE__ */
|
|
5339
|
-
|
|
5340
|
-
|
|
5341
|
-
|
|
5342
|
-
|
|
5478
|
+
customPresets && customPresets.length > 0 && /* @__PURE__ */ jsx29("div", { className: "grid grid-cols-2 gap-2", children: customPresets.map((preset, idx) => /* @__PURE__ */ jsx29(
|
|
5479
|
+
"button",
|
|
5480
|
+
{
|
|
5481
|
+
type: "button",
|
|
5482
|
+
className: cn(
|
|
5483
|
+
"px-2 py-1.5 text-xs rounded-md border border-border hover:bg-accent/10 transition-all",
|
|
5484
|
+
animate && "hover:scale-105 active:scale-95"
|
|
5485
|
+
),
|
|
5486
|
+
onClick: () => handleCustomPreset(preset.time),
|
|
5487
|
+
"aria-label": `Set time to ${preset.label}`,
|
|
5488
|
+
children: preset.label
|
|
5489
|
+
},
|
|
5490
|
+
idx
|
|
5491
|
+
)) }),
|
|
5492
|
+
/* @__PURE__ */ jsxs24("div", { className: "flex gap-3", children: [
|
|
5493
|
+
/* @__PURE__ */ jsxs24("div", { className: "flex-1 min-w-[70px]", children: [
|
|
5494
|
+
/* @__PURE__ */ jsx29("div", { className: "text-xs font-semibold text-muted-foreground mb-2 text-center", children: "Hour" }),
|
|
5495
|
+
/* @__PURE__ */ jsx29(
|
|
5496
|
+
"div",
|
|
5343
5497
|
{
|
|
5344
|
-
|
|
5345
|
-
className:
|
|
5346
|
-
|
|
5347
|
-
|
|
5348
|
-
|
|
5349
|
-
|
|
5350
|
-
|
|
5351
|
-
|
|
5352
|
-
|
|
5353
|
-
|
|
5354
|
-
|
|
5355
|
-
|
|
5356
|
-
|
|
5357
|
-
|
|
5358
|
-
|
|
5498
|
+
ref: hourScrollRef,
|
|
5499
|
+
className: "max-h-48 overflow-y-auto pr-1 space-y-1 scrollbar-thin scroll-smooth",
|
|
5500
|
+
role: "listbox",
|
|
5501
|
+
"aria-label": "Select hour",
|
|
5502
|
+
tabIndex: focusedColumn === "hour" ? 0 : -1,
|
|
5503
|
+
onKeyDown: (e) => handleKeyDown(e, "hour"),
|
|
5504
|
+
onFocus: () => setFocusedColumn("hour"),
|
|
5505
|
+
children: hours.map((h) => {
|
|
5506
|
+
const isSelected = format === "24" && parts.h === h || format === "12" && (parts.h % 12 || 12) === (h % 12 || 12);
|
|
5507
|
+
return /* @__PURE__ */ jsx29(
|
|
5508
|
+
"button",
|
|
5509
|
+
{
|
|
5510
|
+
type: "button",
|
|
5511
|
+
role: "option",
|
|
5512
|
+
"aria-selected": isSelected,
|
|
5513
|
+
className: cn(
|
|
5514
|
+
"w-full text-center px-3 py-2 rounded-md transition-all text-sm font-medium",
|
|
5515
|
+
"hover:bg-accent hover:scale-105 active:scale-95 focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1",
|
|
5516
|
+
isSelected && "bg-primary text-primary-foreground shadow-md",
|
|
5517
|
+
!isSelected && "text-foreground/80",
|
|
5518
|
+
animate && "transition-transform duration-150"
|
|
5519
|
+
),
|
|
5520
|
+
onClick: () => {
|
|
5521
|
+
const nextH = format === "24" ? h : (parts.p === "PM" ? h % 12 + 12 : h % 12) % 24;
|
|
5522
|
+
const next = { ...parts, h: format === "24" ? h : nextH === 0 && parts.p === "AM" ? 0 : nextH || (parts.p === "PM" ? 12 : 0) };
|
|
5523
|
+
setParts(next);
|
|
5524
|
+
emit(next);
|
|
5525
|
+
},
|
|
5526
|
+
children: pad(h)
|
|
5527
|
+
},
|
|
5528
|
+
h
|
|
5529
|
+
);
|
|
5530
|
+
})
|
|
5531
|
+
}
|
|
5532
|
+
)
|
|
5359
5533
|
] }),
|
|
5360
|
-
/* @__PURE__ */
|
|
5361
|
-
|
|
5362
|
-
/* @__PURE__ */ jsx29("div", { className: "
|
|
5363
|
-
|
|
5534
|
+
/* @__PURE__ */ jsx29("div", { className: "w-px bg-border/50 self-stretch my-8" }),
|
|
5535
|
+
/* @__PURE__ */ jsxs24("div", { className: "flex-1 min-w-[70px]", children: [
|
|
5536
|
+
/* @__PURE__ */ jsx29("div", { className: "text-xs font-semibold text-muted-foreground mb-2 text-center", children: "Min" }),
|
|
5537
|
+
/* @__PURE__ */ jsx29(
|
|
5538
|
+
"div",
|
|
5364
5539
|
{
|
|
5365
|
-
|
|
5366
|
-
className:
|
|
5367
|
-
|
|
5368
|
-
|
|
5369
|
-
|
|
5370
|
-
|
|
5371
|
-
|
|
5372
|
-
|
|
5373
|
-
|
|
5374
|
-
|
|
5375
|
-
|
|
5376
|
-
|
|
5377
|
-
|
|
5378
|
-
|
|
5540
|
+
ref: minuteScrollRef,
|
|
5541
|
+
className: "max-h-48 overflow-y-auto pr-1 space-y-1 scrollbar-thin scroll-smooth",
|
|
5542
|
+
role: "listbox",
|
|
5543
|
+
"aria-label": "Select minute",
|
|
5544
|
+
tabIndex: focusedColumn === "minute" ? 0 : -1,
|
|
5545
|
+
onKeyDown: (e) => handleKeyDown(e, "minute"),
|
|
5546
|
+
onFocus: () => setFocusedColumn("minute"),
|
|
5547
|
+
children: minutes.map((m) => {
|
|
5548
|
+
const isSelected = parts.m === m;
|
|
5549
|
+
return /* @__PURE__ */ jsx29(
|
|
5550
|
+
"button",
|
|
5551
|
+
{
|
|
5552
|
+
type: "button",
|
|
5553
|
+
role: "option",
|
|
5554
|
+
"aria-selected": isSelected,
|
|
5555
|
+
className: cn(
|
|
5556
|
+
"w-full text-center px-3 py-2 rounded-md transition-all text-sm font-medium",
|
|
5557
|
+
"hover:bg-accent hover:scale-105 active:scale-95 focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1",
|
|
5558
|
+
isSelected && "bg-primary text-primary-foreground shadow-md",
|
|
5559
|
+
!isSelected && "text-foreground/80",
|
|
5560
|
+
animate && "transition-transform duration-150"
|
|
5561
|
+
),
|
|
5562
|
+
onClick: () => {
|
|
5563
|
+
const next = { ...parts, m };
|
|
5564
|
+
setParts(next);
|
|
5565
|
+
emit(next);
|
|
5566
|
+
},
|
|
5567
|
+
children: pad(m)
|
|
5568
|
+
},
|
|
5569
|
+
m
|
|
5570
|
+
);
|
|
5571
|
+
})
|
|
5572
|
+
}
|
|
5573
|
+
)
|
|
5379
5574
|
] }),
|
|
5380
|
-
|
|
5381
|
-
|
|
5382
|
-
/* @__PURE__ */
|
|
5383
|
-
"
|
|
5384
|
-
|
|
5385
|
-
|
|
5386
|
-
|
|
5387
|
-
|
|
5388
|
-
|
|
5389
|
-
|
|
5390
|
-
|
|
5391
|
-
|
|
5392
|
-
|
|
5393
|
-
|
|
5394
|
-
|
|
5395
|
-
|
|
5396
|
-
|
|
5397
|
-
|
|
5398
|
-
|
|
5575
|
+
/* @__PURE__ */ jsx29("div", { className: "w-px bg-border/50 self-stretch my-8" }),
|
|
5576
|
+
includeSeconds && /* @__PURE__ */ jsxs24(Fragment7, { children: [
|
|
5577
|
+
/* @__PURE__ */ jsxs24("div", { className: "flex-1 min-w-[70px]", children: [
|
|
5578
|
+
/* @__PURE__ */ jsx29("div", { className: "text-xs font-semibold text-muted-foreground mb-2 text-center", children: "Sec" }),
|
|
5579
|
+
/* @__PURE__ */ jsx29(
|
|
5580
|
+
"div",
|
|
5581
|
+
{
|
|
5582
|
+
ref: secondScrollRef,
|
|
5583
|
+
className: "max-h-48 overflow-y-auto pr-1 space-y-1 scrollbar-thin scroll-smooth",
|
|
5584
|
+
role: "listbox",
|
|
5585
|
+
"aria-label": "Select second",
|
|
5586
|
+
tabIndex: focusedColumn === "second" ? 0 : -1,
|
|
5587
|
+
onKeyDown: (e) => handleKeyDown(e, "second"),
|
|
5588
|
+
onFocus: () => setFocusedColumn("second"),
|
|
5589
|
+
children: seconds.map((s) => {
|
|
5590
|
+
const isSelected = parts.s === s;
|
|
5591
|
+
return /* @__PURE__ */ jsx29(
|
|
5592
|
+
"button",
|
|
5593
|
+
{
|
|
5594
|
+
type: "button",
|
|
5595
|
+
role: "option",
|
|
5596
|
+
"aria-selected": isSelected,
|
|
5597
|
+
className: cn(
|
|
5598
|
+
"w-full text-center px-3 py-2 rounded-md transition-all text-sm font-medium",
|
|
5599
|
+
"hover:bg-accent hover:scale-105 active:scale-95 focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1",
|
|
5600
|
+
isSelected && "bg-primary text-primary-foreground shadow-md",
|
|
5601
|
+
!isSelected && "text-foreground/80",
|
|
5602
|
+
animate && "transition-transform duration-150"
|
|
5603
|
+
),
|
|
5604
|
+
onClick: () => {
|
|
5605
|
+
const next = { ...parts, s };
|
|
5606
|
+
setParts(next);
|
|
5607
|
+
emit(next);
|
|
5608
|
+
},
|
|
5609
|
+
children: pad(s)
|
|
5610
|
+
},
|
|
5611
|
+
s
|
|
5612
|
+
);
|
|
5613
|
+
})
|
|
5614
|
+
}
|
|
5615
|
+
)
|
|
5616
|
+
] }),
|
|
5617
|
+
/* @__PURE__ */ jsx29("div", { className: "w-px bg-border/50 self-stretch my-8" })
|
|
5399
5618
|
] }),
|
|
5400
5619
|
format === "12" && /* @__PURE__ */ jsxs24("div", { className: "w-20", children: [
|
|
5401
|
-
/* @__PURE__ */ jsx29("div", { className: "text-xs font-
|
|
5402
|
-
/* @__PURE__ */ jsx29(
|
|
5403
|
-
"
|
|
5620
|
+
/* @__PURE__ */ jsx29("div", { className: "text-xs font-semibold text-muted-foreground mb-2 text-center", children: "Period" }),
|
|
5621
|
+
/* @__PURE__ */ jsx29(
|
|
5622
|
+
"div",
|
|
5404
5623
|
{
|
|
5405
|
-
|
|
5406
|
-
|
|
5407
|
-
|
|
5408
|
-
|
|
5409
|
-
),
|
|
5410
|
-
|
|
5411
|
-
|
|
5412
|
-
|
|
5413
|
-
|
|
5414
|
-
|
|
5415
|
-
|
|
5416
|
-
|
|
5417
|
-
|
|
5418
|
-
|
|
5419
|
-
|
|
5420
|
-
|
|
5421
|
-
|
|
5422
|
-
|
|
5624
|
+
className: "flex flex-col gap-2",
|
|
5625
|
+
role: "radiogroup",
|
|
5626
|
+
"aria-label": "Select AM or PM",
|
|
5627
|
+
tabIndex: focusedColumn === "period" ? 0 : -1,
|
|
5628
|
+
onKeyDown: (e) => handleKeyDown(e, "period"),
|
|
5629
|
+
onFocus: () => setFocusedColumn("period"),
|
|
5630
|
+
children: ["AM", "PM"].map((p) => {
|
|
5631
|
+
const isSelected = parts.p === p;
|
|
5632
|
+
return /* @__PURE__ */ jsx29(
|
|
5633
|
+
"button",
|
|
5634
|
+
{
|
|
5635
|
+
type: "button",
|
|
5636
|
+
role: "radio",
|
|
5637
|
+
"aria-checked": isSelected,
|
|
5638
|
+
className: cn(
|
|
5639
|
+
"px-4 py-3 rounded-md transition-all text-sm font-semibold",
|
|
5640
|
+
"hover:bg-accent hover:scale-105 active:scale-95 focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1",
|
|
5641
|
+
isSelected && "bg-primary text-primary-foreground shadow-md",
|
|
5642
|
+
!isSelected && "text-foreground/80 border border-border",
|
|
5643
|
+
animate && "transition-transform duration-150"
|
|
5644
|
+
),
|
|
5645
|
+
onClick: () => {
|
|
5646
|
+
const pVal = p;
|
|
5647
|
+
let hour = parts.h;
|
|
5648
|
+
if (pVal === "AM" && hour >= 12) hour -= 12;
|
|
5649
|
+
if (pVal === "PM" && hour < 12) hour += 12;
|
|
5650
|
+
const next = { ...parts, p: pVal, h: hour };
|
|
5651
|
+
setParts(next);
|
|
5652
|
+
emit(next);
|
|
5653
|
+
},
|
|
5654
|
+
children: p
|
|
5655
|
+
},
|
|
5656
|
+
p
|
|
5657
|
+
);
|
|
5658
|
+
})
|
|
5659
|
+
}
|
|
5660
|
+
)
|
|
5423
5661
|
] })
|
|
5424
5662
|
] }),
|
|
5425
|
-
(showNow || clearable) && /* @__PURE__ */ jsxs24("div", { className: "flex items-center justify-between gap-2 pt-
|
|
5663
|
+
(showNow || clearable) && /* @__PURE__ */ jsxs24("div", { className: "flex items-center justify-between gap-2 pt-3 border-t border-border", children: [
|
|
5426
5664
|
showNow && /* @__PURE__ */ jsxs24(
|
|
5427
5665
|
"button",
|
|
5428
5666
|
{
|
|
5429
5667
|
type: "button",
|
|
5430
|
-
className:
|
|
5668
|
+
className: cn(
|
|
5669
|
+
"px-3 py-2 text-xs rounded-md border border-border hover:bg-accent/10 transition-all flex items-center gap-2 font-medium",
|
|
5670
|
+
animate && "hover:scale-105 active:scale-95"
|
|
5671
|
+
),
|
|
5431
5672
|
onClick: () => {
|
|
5432
5673
|
setNow();
|
|
5433
|
-
if (variant === "compact")
|
|
5674
|
+
if (variant === "compact") handleOpenChange(false);
|
|
5434
5675
|
},
|
|
5676
|
+
"aria-label": "Set current time",
|
|
5435
5677
|
children: [
|
|
5436
|
-
/* @__PURE__ */ jsx29(Clock2, { className: "w-3 h-3" }),
|
|
5678
|
+
/* @__PURE__ */ jsx29(Clock2, { className: "w-3.5 h-3.5" }),
|
|
5437
5679
|
"Now"
|
|
5438
5680
|
]
|
|
5439
5681
|
}
|
|
@@ -5443,14 +5685,18 @@ function TimePicker({
|
|
|
5443
5685
|
"button",
|
|
5444
5686
|
{
|
|
5445
5687
|
type: "button",
|
|
5446
|
-
className:
|
|
5688
|
+
className: cn(
|
|
5689
|
+
"px-3 py-2 text-xs rounded-md border border-border hover:bg-destructive/10 hover:text-destructive transition-all flex items-center gap-2 font-medium",
|
|
5690
|
+
animate && "hover:scale-105 active:scale-95"
|
|
5691
|
+
),
|
|
5447
5692
|
onClick: () => {
|
|
5448
5693
|
setParts(initial);
|
|
5449
5694
|
emit(void 0);
|
|
5450
|
-
|
|
5695
|
+
handleOpenChange(false);
|
|
5451
5696
|
},
|
|
5697
|
+
"aria-label": "Clear selected time",
|
|
5452
5698
|
children: [
|
|
5453
|
-
/* @__PURE__ */ jsx29(X8, { className: "w-3 h-3" }),
|
|
5699
|
+
/* @__PURE__ */ jsx29(X8, { className: "w-3.5 h-3.5" }),
|
|
5454
5700
|
"Clear"
|
|
5455
5701
|
]
|
|
5456
5702
|
}
|
|
@@ -5467,30 +5713,54 @@ function TimePicker({
|
|
|
5467
5713
|
] });
|
|
5468
5714
|
}
|
|
5469
5715
|
return /* @__PURE__ */ jsxs24("div", { className: "w-full", ...rest, children: [
|
|
5470
|
-
label && /* @__PURE__ */ jsx29("div", { className: "flex items-center justify-between mb-1.5", children: /* @__PURE__ */ jsxs24(
|
|
5471
|
-
label,
|
|
5472
|
-
|
|
5473
|
-
|
|
5716
|
+
label && /* @__PURE__ */ jsx29("div", { className: "flex items-center justify-between mb-1.5", children: /* @__PURE__ */ jsxs24(
|
|
5717
|
+
"label",
|
|
5718
|
+
{
|
|
5719
|
+
className: cn(sz.label, "font-medium", disabled ? "text-muted-foreground" : "text-foreground", "cursor-pointer"),
|
|
5720
|
+
onClick: () => !disabled && handleOpenChange(true),
|
|
5721
|
+
children: [
|
|
5722
|
+
label,
|
|
5723
|
+
required && /* @__PURE__ */ jsx29("span", { className: "text-destructive ml-1", children: "*" })
|
|
5724
|
+
]
|
|
5725
|
+
}
|
|
5726
|
+
) }),
|
|
5474
5727
|
/* @__PURE__ */ jsx29(
|
|
5475
5728
|
Popover,
|
|
5476
5729
|
{
|
|
5477
5730
|
trigger,
|
|
5478
5731
|
open,
|
|
5479
|
-
onOpenChange:
|
|
5732
|
+
onOpenChange: handleOpenChange,
|
|
5480
5733
|
placement: "bottom-start",
|
|
5481
5734
|
matchTriggerWidth: variant === "compact",
|
|
5482
5735
|
contentWidth,
|
|
5483
|
-
contentClassName: cn(
|
|
5736
|
+
contentClassName: cn(
|
|
5737
|
+
"p-4 rounded-lg border bg-popover shadow-xl backdrop-blur-md",
|
|
5738
|
+
error && "border-destructive",
|
|
5739
|
+
success && "border-green-500",
|
|
5740
|
+
!error && !success && "border-border",
|
|
5741
|
+
animate && "animate-in fade-in-0 zoom-in-95 duration-200"
|
|
5742
|
+
),
|
|
5484
5743
|
children: timePickerContent
|
|
5485
5744
|
}
|
|
5486
|
-
)
|
|
5745
|
+
),
|
|
5746
|
+
(error || success || helperText) && /* @__PURE__ */ jsxs24("div", { className: cn("mt-1.5 flex items-start gap-1.5", sz.label), children: [
|
|
5747
|
+
error && /* @__PURE__ */ jsxs24("div", { className: "flex items-center gap-1.5 text-destructive", children: [
|
|
5748
|
+
/* @__PURE__ */ jsx29(X8, { className: "w-3.5 h-3.5 flex-shrink-0" }),
|
|
5749
|
+
/* @__PURE__ */ jsx29("span", { children: error })
|
|
5750
|
+
] }),
|
|
5751
|
+
success && !error && /* @__PURE__ */ jsxs24("div", { className: "flex items-center gap-1.5 text-green-600", children: [
|
|
5752
|
+
/* @__PURE__ */ jsx29(Check4, { className: "w-3.5 h-3.5 flex-shrink-0" }),
|
|
5753
|
+
/* @__PURE__ */ jsx29("span", { children: "Valid time selected" })
|
|
5754
|
+
] }),
|
|
5755
|
+
helperText && !error && !success && /* @__PURE__ */ jsx29("span", { className: "text-muted-foreground", children: helperText })
|
|
5756
|
+
] })
|
|
5487
5757
|
] });
|
|
5488
5758
|
}
|
|
5489
5759
|
|
|
5490
5760
|
// ../../components/ui/Calendar.tsx
|
|
5491
5761
|
import * as React23 from "react";
|
|
5492
5762
|
import { ChevronLeft as ChevronLeft3, ChevronRight as ChevronRight4 } from "lucide-react";
|
|
5493
|
-
import { Fragment as
|
|
5763
|
+
import { Fragment as Fragment9, jsx as jsx30, jsxs as jsxs25 } from "react/jsx-runtime";
|
|
5494
5764
|
function startOfMonth(d) {
|
|
5495
5765
|
return new Date(d.getFullYear(), d.getMonth(), 1);
|
|
5496
5766
|
}
|
|
@@ -5734,7 +6004,7 @@ function Calendar2({
|
|
|
5734
6004
|
/* @__PURE__ */ jsx30("div", { className: "text-sm font-semibold", children: display === "week" ? `${labels?.month ? labels.month(weekDays[0]) : weekDays[0].toLocaleDateString("en-US", { month: "short" })} ${weekDays[0].getDate()} \u2013 ${labels?.month ? labels.month(weekDays[6]) : weekDays[6].toLocaleDateString("en-US", { month: "short" })} ${weekDays[6].getDate()}` : labels?.month ? labels.month(view) : view.toLocaleDateString("en-US", { month: "long", year: "numeric" }) }),
|
|
5735
6005
|
/* @__PURE__ */ jsx30("button", { onClick: () => goByView(1), disabled: nextDisabled, className: cn("p-1 rounded-md hover:bg-accent", nextDisabled && "opacity-40 cursor-not-allowed hover:bg-transparent"), "aria-label": labels?.next || (display === "week" ? "Next week" : "Next month"), children: /* @__PURE__ */ jsx30(ChevronRight4, { className: "h-4 w-4" }) })
|
|
5736
6006
|
] }),
|
|
5737
|
-
display === "week" ? /* @__PURE__ */ jsxs25(
|
|
6007
|
+
display === "week" ? /* @__PURE__ */ jsxs25(Fragment9, { children: [
|
|
5738
6008
|
showWeekdays && /* @__PURE__ */ jsx30("div", { className: cn("grid grid-cols-7", sz.grid, "mb-1 text-center text-muted-foreground font-medium"), children: weekdays.map((w) => /* @__PURE__ */ jsx30("div", { className: cn(sz.head), children: w }, `w-${w}`)) }),
|
|
5739
6009
|
/* @__PURE__ */ jsx30("div", { className: cn("grid grid-cols-7", sz.grid), children: weekDays.map((d, idx) => {
|
|
5740
6010
|
const inMonth = true;
|
|
@@ -6547,7 +6817,7 @@ Slider.displayName = "Slider";
|
|
|
6547
6817
|
// ../../components/ui/OverlayControls.tsx
|
|
6548
6818
|
import { Dot, Maximize2, Pause, Play, RotateCcw, RotateCw, Volume2, VolumeX } from "lucide-react";
|
|
6549
6819
|
import React27 from "react";
|
|
6550
|
-
import { Fragment as
|
|
6820
|
+
import { Fragment as Fragment10, jsx as jsx34, jsxs as jsxs29 } from "react/jsx-runtime";
|
|
6551
6821
|
function OverlayControls({
|
|
6552
6822
|
mode,
|
|
6553
6823
|
value,
|
|
@@ -6770,7 +7040,7 @@ function OverlayControls({
|
|
|
6770
7040
|
const handleSliderMouseLeave = () => {
|
|
6771
7041
|
setPreviewData(null);
|
|
6772
7042
|
};
|
|
6773
|
-
return /* @__PURE__ */ jsxs29(
|
|
7043
|
+
return /* @__PURE__ */ jsxs29(Fragment10, { children: [
|
|
6774
7044
|
keyboardFeedback && /* @__PURE__ */ jsx34(
|
|
6775
7045
|
"div",
|
|
6776
7046
|
{
|
|
@@ -6980,7 +7250,7 @@ function OverlayControls({
|
|
|
6980
7250
|
// ../../components/ui/CategoryTreeSelect.tsx
|
|
6981
7251
|
import { useState as useState24 } from "react";
|
|
6982
7252
|
import { ChevronRight as ChevronRight5, ChevronDown as ChevronDown3, Check as Check6 } from "lucide-react";
|
|
6983
|
-
import { Fragment as
|
|
7253
|
+
import { Fragment as Fragment11, jsx as jsx35, jsxs as jsxs30 } from "react/jsx-runtime";
|
|
6984
7254
|
function CategoryTreeSelect({ categories, value, onChange, placeholder = "Ch\u1ECDn danh m\u1EE5c", disabled }) {
|
|
6985
7255
|
const [isOpen, setIsOpen] = useState24(false);
|
|
6986
7256
|
const [expandedNodes, setExpandedNodes] = useState24(/* @__PURE__ */ new Set());
|
|
@@ -7103,7 +7373,7 @@ function CategoryTreeSelect({ categories, value, onChange, placeholder = "Ch\u1E
|
|
|
7103
7373
|
]
|
|
7104
7374
|
}
|
|
7105
7375
|
),
|
|
7106
|
-
isOpen && !disabled && /* @__PURE__ */ jsxs30(
|
|
7376
|
+
isOpen && !disabled && /* @__PURE__ */ jsxs30(Fragment11, { children: [
|
|
7107
7377
|
/* @__PURE__ */ jsx35("div", { className: "fixed inset-0 z-10", onClick: () => setIsOpen(false) }),
|
|
7108
7378
|
/* @__PURE__ */ jsx35(
|
|
7109
7379
|
"div",
|
|
@@ -7121,7 +7391,7 @@ function CategoryTreeSelect({ categories, value, onChange, placeholder = "Ch\u1E
|
|
|
7121
7391
|
}
|
|
7122
7392
|
|
|
7123
7393
|
// ../../components/ui/ImageUpload.tsx
|
|
7124
|
-
import { useState as useState25, useRef as
|
|
7394
|
+
import { useState as useState25, useRef as useRef10, useCallback as useCallback9 } from "react";
|
|
7125
7395
|
import { Upload, X as X9, Image as ImageIcon, Loader2 as Loader22, Check as Check7 } from "lucide-react";
|
|
7126
7396
|
import { useTranslations as useTranslations6 } from "next-intl";
|
|
7127
7397
|
import { jsx as jsx36, jsxs as jsxs31 } from "react/jsx-runtime";
|
|
@@ -7143,7 +7413,7 @@ function ImageUpload({
|
|
|
7143
7413
|
const [isDragging, setIsDragging] = useState25(false);
|
|
7144
7414
|
const [uploading, setUploading] = useState25(false);
|
|
7145
7415
|
const [uploadedImages, setUploadedImages] = useState25([]);
|
|
7146
|
-
const fileInputRef =
|
|
7416
|
+
const fileInputRef = useRef10(null);
|
|
7147
7417
|
const { addToast } = useToast();
|
|
7148
7418
|
const t = useTranslations6("OCR.imageUpload");
|
|
7149
7419
|
const previewSizes = {
|
|
@@ -7151,17 +7421,17 @@ function ImageUpload({
|
|
|
7151
7421
|
md: "w-24 h-24",
|
|
7152
7422
|
lg: "w-32 h-32"
|
|
7153
7423
|
};
|
|
7154
|
-
const handleDragOver =
|
|
7424
|
+
const handleDragOver = useCallback9((e) => {
|
|
7155
7425
|
e.preventDefault();
|
|
7156
7426
|
if (!disabled) {
|
|
7157
7427
|
setIsDragging(true);
|
|
7158
7428
|
}
|
|
7159
7429
|
}, [disabled]);
|
|
7160
|
-
const handleDragLeave =
|
|
7430
|
+
const handleDragLeave = useCallback9((e) => {
|
|
7161
7431
|
e.preventDefault();
|
|
7162
7432
|
setIsDragging(false);
|
|
7163
7433
|
}, []);
|
|
7164
|
-
const handleFiles =
|
|
7434
|
+
const handleFiles = useCallback9(async (files) => {
|
|
7165
7435
|
if (files.length === 0) return;
|
|
7166
7436
|
const validFiles = files.filter((file) => {
|
|
7167
7437
|
if (file.size > maxSize * 1024 * 1024) {
|
|
@@ -7225,14 +7495,14 @@ function ImageUpload({
|
|
|
7225
7495
|
setUploading(false);
|
|
7226
7496
|
}
|
|
7227
7497
|
}, [maxSize, addToast, onUpload]);
|
|
7228
|
-
const handleDrop =
|
|
7498
|
+
const handleDrop = useCallback9((e) => {
|
|
7229
7499
|
e.preventDefault();
|
|
7230
7500
|
setIsDragging(false);
|
|
7231
7501
|
if (disabled) return;
|
|
7232
7502
|
const files = Array.from(e.dataTransfer.files);
|
|
7233
7503
|
handleFiles(files);
|
|
7234
7504
|
}, [disabled, handleFiles]);
|
|
7235
|
-
const handleFileSelect =
|
|
7505
|
+
const handleFileSelect = useCallback9((e) => {
|
|
7236
7506
|
const files = Array.from(e.target.files || []);
|
|
7237
7507
|
handleFiles(files);
|
|
7238
7508
|
if (fileInputRef.current) {
|
|
@@ -7351,7 +7621,7 @@ function ImageUpload({
|
|
|
7351
7621
|
// ../../components/ui/Carousel.tsx
|
|
7352
7622
|
import * as React29 from "react";
|
|
7353
7623
|
import { ChevronLeft as ChevronLeft4, ChevronRight as ChevronRight6 } from "lucide-react";
|
|
7354
|
-
import { Fragment as
|
|
7624
|
+
import { Fragment as Fragment12, jsx as jsx37, jsxs as jsxs32 } from "react/jsx-runtime";
|
|
7355
7625
|
function Carousel({
|
|
7356
7626
|
children,
|
|
7357
7627
|
autoScroll = true,
|
|
@@ -7560,7 +7830,7 @@ function Carousel({
|
|
|
7560
7830
|
))
|
|
7561
7831
|
}
|
|
7562
7832
|
),
|
|
7563
|
-
showArrows && totalSlides > slidesToShow && /* @__PURE__ */ jsxs32(
|
|
7833
|
+
showArrows && totalSlides > slidesToShow && /* @__PURE__ */ jsxs32(Fragment12, { children: [
|
|
7564
7834
|
/* @__PURE__ */ jsx37(
|
|
7565
7835
|
Button_default,
|
|
7566
7836
|
{
|
|
@@ -7940,7 +8210,7 @@ function FallingIcons({
|
|
|
7940
8210
|
// ../../components/ui/List.tsx
|
|
7941
8211
|
import * as React31 from "react";
|
|
7942
8212
|
import { ChevronRight as ChevronRight7 } from "lucide-react";
|
|
7943
|
-
import { Fragment as
|
|
8213
|
+
import { Fragment as Fragment13, jsx as jsx39, jsxs as jsxs34 } from "react/jsx-runtime";
|
|
7944
8214
|
var SIZE_STYLES2 = {
|
|
7945
8215
|
xs: { itemPad: "px-2 py-1.5", densePad: "px-2 py-1", label: "text-xs", desc: "text-[11px]", icon: "h-3.5 w-3.5", avatar: "h-6 w-6" },
|
|
7946
8216
|
sm: { itemPad: "px-3 py-2", densePad: "px-3 py-1.5", label: "text-[13px]", desc: "text-[12px]", icon: "h-4 w-4", avatar: "h-8 w-8" },
|
|
@@ -8070,41 +8340,50 @@ var ListItem = React31.forwardRef(
|
|
|
8070
8340
|
setInternalExpanded(newExpanded);
|
|
8071
8341
|
}
|
|
8072
8342
|
};
|
|
8073
|
-
const
|
|
8074
|
-
|
|
8075
|
-
|
|
8076
|
-
|
|
8077
|
-
|
|
8078
|
-
|
|
8079
|
-
|
|
8080
|
-
|
|
8081
|
-
|
|
8082
|
-
|
|
8083
|
-
|
|
8084
|
-
|
|
8085
|
-
|
|
8086
|
-
|
|
8087
|
-
|
|
8088
|
-
|
|
8089
|
-
|
|
8090
|
-
|
|
8091
|
-
|
|
8092
|
-
|
|
8093
|
-
|
|
8094
|
-
|
|
8095
|
-
|
|
8096
|
-
|
|
8097
|
-
|
|
8098
|
-
|
|
8099
|
-
|
|
8100
|
-
|
|
8343
|
+
const headerProps = collapsible ? {
|
|
8344
|
+
role: "button",
|
|
8345
|
+
tabIndex: disabled ? -1 : 0,
|
|
8346
|
+
onClick: disabled ? void 0 : () => toggleExpanded(),
|
|
8347
|
+
onKeyDown: (e) => {
|
|
8348
|
+
if (disabled) return;
|
|
8349
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
8350
|
+
e.preventDefault();
|
|
8351
|
+
toggleExpanded();
|
|
8352
|
+
}
|
|
8353
|
+
}
|
|
8354
|
+
} : {};
|
|
8355
|
+
const inner = /* @__PURE__ */ jsxs34(Fragment13, { children: [
|
|
8356
|
+
/* @__PURE__ */ jsxs34(
|
|
8357
|
+
"div",
|
|
8358
|
+
{
|
|
8359
|
+
className: cn("flex items-center gap-3", padding, "group/item relative"),
|
|
8360
|
+
...headerProps,
|
|
8361
|
+
children: [
|
|
8362
|
+
avatar && /* @__PURE__ */ jsx39("div", { className: cn("shrink-0", sz.avatar), children: typeof avatar === "string" ? /* @__PURE__ */ jsx39("img", { src: avatar, alt: "", className: cn("rounded-full object-cover", sz.avatar) }) : avatar }),
|
|
8363
|
+
Left && !avatar && /* @__PURE__ */ jsx39("span", { className: cn("text-muted-foreground shrink-0", sz.icon), children: /* @__PURE__ */ jsx39(Left, { className: cn(sz.icon) }) }),
|
|
8364
|
+
/* @__PURE__ */ jsxs34("div", { className: "min-w-0 flex-1", children: [
|
|
8365
|
+
/* @__PURE__ */ jsxs34("div", { className: "flex items-center gap-2", children: [
|
|
8366
|
+
label && /* @__PURE__ */ jsx39("div", { className: cn(sz.label, "text-foreground font-medium truncate"), children: label }),
|
|
8367
|
+
badge && /* @__PURE__ */ jsx39("span", { className: cn("px-2 py-0.5 rounded-full text-[11px] font-medium shrink-0", BADGE_VARIANTS[badgeVariant]), children: badge })
|
|
8368
|
+
] }),
|
|
8369
|
+
description && /* @__PURE__ */ jsx39("div", { className: cn(sz.desc, "text-muted-foreground truncate mt-0.5"), children: description }),
|
|
8370
|
+
children && /* @__PURE__ */ jsx39("div", { className: "mt-1", children })
|
|
8371
|
+
] }),
|
|
8372
|
+
action && /* @__PURE__ */ jsx39("div", { className: "opacity-0 group-hover/item:opacity-100 transition-opacity shrink-0", children: action }),
|
|
8373
|
+
collapsible ? /* @__PURE__ */ jsx39(
|
|
8374
|
+
"span",
|
|
8375
|
+
{
|
|
8376
|
+
className: cn(
|
|
8377
|
+
"text-muted-foreground shrink-0 transition-transform cursor-pointer select-none",
|
|
8378
|
+
sz.icon,
|
|
8379
|
+
isExpanded && "rotate-90"
|
|
8380
|
+
),
|
|
8381
|
+
children: /* @__PURE__ */ jsx39(ChevronRight7, { className: cn(sz.icon) })
|
|
8101
8382
|
}
|
|
8102
|
-
}
|
|
8103
|
-
|
|
8104
|
-
|
|
8105
|
-
|
|
8106
|
-
) : Right && /* @__PURE__ */ jsx39("span", { className: cn("text-muted-foreground shrink-0", sz.icon), children: /* @__PURE__ */ jsx39(Right, { className: cn(sz.icon) }) })
|
|
8107
|
-
] }),
|
|
8383
|
+
) : Right && /* @__PURE__ */ jsx39("span", { className: cn("text-muted-foreground shrink-0", sz.icon), children: /* @__PURE__ */ jsx39(Right, { className: cn(sz.icon) }) })
|
|
8384
|
+
]
|
|
8385
|
+
}
|
|
8386
|
+
),
|
|
8108
8387
|
collapsible && isExpanded && expandContent && /* @__PURE__ */ jsx39("div", { className: cn("border-t border-border/50 bg-muted/20", padding, "pt-3"), children: expandContent })
|
|
8109
8388
|
] });
|
|
8110
8389
|
const baseCls = cn(
|
|
@@ -8117,14 +8396,24 @@ var ListItem = React31.forwardRef(
|
|
|
8117
8396
|
const A = as === "a" ? "a" : "a";
|
|
8118
8397
|
return /* @__PURE__ */ jsx39(A, { ref, href, className: cn(baseCls, "block"), ...rest, children: inner });
|
|
8119
8398
|
}
|
|
8120
|
-
if (as === "button"
|
|
8399
|
+
if (as === "button" && !collapsible) {
|
|
8121
8400
|
return /* @__PURE__ */ jsx39(
|
|
8122
8401
|
"button",
|
|
8123
8402
|
{
|
|
8124
8403
|
ref,
|
|
8125
8404
|
type: "button",
|
|
8126
8405
|
className: cn(baseCls, "text-left block w-full"),
|
|
8127
|
-
|
|
8406
|
+
...rest,
|
|
8407
|
+
children: inner
|
|
8408
|
+
}
|
|
8409
|
+
);
|
|
8410
|
+
}
|
|
8411
|
+
if (collapsible) {
|
|
8412
|
+
return /* @__PURE__ */ jsx39(
|
|
8413
|
+
"div",
|
|
8414
|
+
{
|
|
8415
|
+
ref,
|
|
8416
|
+
className: cn(baseCls, "text-left block w-full"),
|
|
8128
8417
|
...rest,
|
|
8129
8418
|
children: inner
|
|
8130
8419
|
}
|
|
@@ -8141,7 +8430,7 @@ var List_default = List;
|
|
|
8141
8430
|
// ../../components/ui/Watermark.tsx
|
|
8142
8431
|
import * as React32 from "react";
|
|
8143
8432
|
import { createPortal as createPortal9 } from "react-dom";
|
|
8144
|
-
import { Fragment as
|
|
8433
|
+
import { Fragment as Fragment14, jsx as jsx40, jsxs as jsxs35 } from "react/jsx-runtime";
|
|
8145
8434
|
var PRESETS2 = {
|
|
8146
8435
|
confidential: { text: "CONFIDENTIAL", color: "rgba(220, 38, 38, 0.15)", rotate: -22, fontSize: 16, fontWeight: "bold" },
|
|
8147
8436
|
draft: { text: "DRAFT", color: "rgba(59, 130, 246, 0.15)", rotate: -22, fontSize: 18, fontWeight: "bold" },
|
|
@@ -8178,16 +8467,27 @@ function useWatermarkDataURL(opts) {
|
|
|
8178
8467
|
const drawText = () => {
|
|
8179
8468
|
ctx.clearRect(0, 0, tileW, tileH);
|
|
8180
8469
|
ctx.save();
|
|
8181
|
-
|
|
8470
|
+
if (pattern === "grid") {
|
|
8471
|
+
ctx.translate(width / 2, height / 2);
|
|
8472
|
+
} else {
|
|
8473
|
+
ctx.translate(tileW / 2, tileH / 2);
|
|
8474
|
+
}
|
|
8182
8475
|
if (pattern === "diagonal") {
|
|
8183
8476
|
ctx.rotate(rotate * Math.PI / 180);
|
|
8184
|
-
} else if (pattern === "straight") {
|
|
8477
|
+
} else if (pattern === "straight" || pattern === "grid") {
|
|
8185
8478
|
}
|
|
8186
8479
|
if (text) {
|
|
8187
8480
|
const textLines = Array.isArray(text) ? text : [text];
|
|
8188
8481
|
ctx.font = `${fontStyle} ${fontWeight} ${fontSize}px ${fontFamily}`;
|
|
8189
8482
|
ctx.textAlign = "center";
|
|
8190
8483
|
ctx.textBaseline = "middle";
|
|
8484
|
+
if (opts.textShadow) {
|
|
8485
|
+
const shadowCol = opts.shadowColor || "rgba(255, 255, 255, 0.5)";
|
|
8486
|
+
ctx.shadowColor = shadowCol;
|
|
8487
|
+
ctx.shadowBlur = 8;
|
|
8488
|
+
ctx.shadowOffsetX = 0;
|
|
8489
|
+
ctx.shadowOffsetY = 0;
|
|
8490
|
+
}
|
|
8191
8491
|
if (gradient) {
|
|
8192
8492
|
const splitStops = (input) => {
|
|
8193
8493
|
const s = input.trim();
|
|
@@ -8269,9 +8569,19 @@ function useWatermarkDataURL(opts) {
|
|
|
8269
8569
|
return () => {
|
|
8270
8570
|
cancelled = true;
|
|
8271
8571
|
};
|
|
8272
|
-
}, [opts.text, opts.image, opts.width, opts.height, opts.gapX, opts.gapY, opts.rotate, opts.fontSize, opts.fontFamily, opts.fontWeight, opts.fontStyle, opts.color, opts.gradient, opts.pattern]);
|
|
8572
|
+
}, [opts.text, opts.image, opts.width, opts.height, opts.gapX, opts.gapY, opts.rotate, opts.fontSize, opts.fontFamily, opts.fontWeight, opts.fontStyle, opts.color, opts.gradient, opts.pattern, opts.textShadow, opts.shadowColor]);
|
|
8273
8573
|
return url;
|
|
8274
8574
|
}
|
|
8575
|
+
var getAnimationClass = (variant, visible) => {
|
|
8576
|
+
if (variant === "none") return "";
|
|
8577
|
+
const animations = {
|
|
8578
|
+
fade: visible ? "animate-in fade-in duration-300" : "animate-out fade-out duration-300",
|
|
8579
|
+
slide: visible ? "animate-in slide-in-from-top duration-500" : "animate-out slide-out-to-top duration-500",
|
|
8580
|
+
scale: visible ? "animate-in zoom-in duration-300" : "animate-out zoom-out duration-300",
|
|
8581
|
+
pulse: visible ? "animate-pulse" : "opacity-0"
|
|
8582
|
+
};
|
|
8583
|
+
return animations[variant] || "";
|
|
8584
|
+
};
|
|
8275
8585
|
var Watermark = ({
|
|
8276
8586
|
text: textProp,
|
|
8277
8587
|
image,
|
|
@@ -8295,13 +8605,40 @@ var Watermark = ({
|
|
|
8295
8605
|
pattern = "diagonal",
|
|
8296
8606
|
interactive = false,
|
|
8297
8607
|
animate = false,
|
|
8608
|
+
animationVariant = "fade",
|
|
8609
|
+
blur = false,
|
|
8610
|
+
blurAmount = 4,
|
|
8611
|
+
textShadow = false,
|
|
8612
|
+
shadowColor,
|
|
8613
|
+
darkMode = false,
|
|
8298
8614
|
overlayClassName,
|
|
8615
|
+
ariaLabel,
|
|
8299
8616
|
className,
|
|
8300
8617
|
style,
|
|
8301
8618
|
children,
|
|
8302
8619
|
...rest
|
|
8303
8620
|
}) => {
|
|
8304
8621
|
const [visible, setVisible] = React32.useState(true);
|
|
8622
|
+
const [isDark, setIsDark] = React32.useState(false);
|
|
8623
|
+
React32.useEffect(() => {
|
|
8624
|
+
if (!darkMode) return;
|
|
8625
|
+
const checkDarkMode = () => {
|
|
8626
|
+
const isDarkMode = document.documentElement.classList.contains("dark") || window.matchMedia("(prefers-color-scheme: dark)").matches;
|
|
8627
|
+
setIsDark(isDarkMode);
|
|
8628
|
+
};
|
|
8629
|
+
checkDarkMode();
|
|
8630
|
+
const observer = new MutationObserver(checkDarkMode);
|
|
8631
|
+
observer.observe(document.documentElement, {
|
|
8632
|
+
attributes: true,
|
|
8633
|
+
attributeFilter: ["class"]
|
|
8634
|
+
});
|
|
8635
|
+
const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
|
|
8636
|
+
mediaQuery.addEventListener("change", checkDarkMode);
|
|
8637
|
+
return () => {
|
|
8638
|
+
observer.disconnect();
|
|
8639
|
+
mediaQuery.removeEventListener("change", checkDarkMode);
|
|
8640
|
+
};
|
|
8641
|
+
}, [darkMode]);
|
|
8305
8642
|
const presetConfig = preset ? PRESETS2[preset] : null;
|
|
8306
8643
|
const text = textProp ?? presetConfig?.text;
|
|
8307
8644
|
const color = colorProp ?? presetConfig?.color ?? "rgba(0,0,0,0.15)";
|
|
@@ -8309,6 +8646,7 @@ var Watermark = ({
|
|
|
8309
8646
|
const fontSize = fontSizeProp ?? presetConfig?.fontSize ?? 14;
|
|
8310
8647
|
const fontWeight = fontWeightProp ?? presetConfig?.fontWeight ?? "normal";
|
|
8311
8648
|
const fontStyle = fontStyleProp ?? "normal";
|
|
8649
|
+
const finalOpacity = darkMode && isDark ? opacity * 1.3 : opacity;
|
|
8312
8650
|
const dataURL = useWatermarkDataURL({
|
|
8313
8651
|
text,
|
|
8314
8652
|
image,
|
|
@@ -8323,17 +8661,19 @@ var Watermark = ({
|
|
|
8323
8661
|
fontStyle,
|
|
8324
8662
|
color,
|
|
8325
8663
|
gradient,
|
|
8326
|
-
pattern
|
|
8664
|
+
pattern,
|
|
8665
|
+
textShadow,
|
|
8666
|
+
shadowColor
|
|
8327
8667
|
});
|
|
8328
8668
|
const overlayStyle = {
|
|
8329
8669
|
position: fullPage ? "fixed" : "absolute",
|
|
8330
8670
|
top: 0,
|
|
8331
8671
|
left: 0,
|
|
8332
8672
|
zIndex,
|
|
8333
|
-
opacity: visible ?
|
|
8673
|
+
opacity: visible ? finalOpacity : 0,
|
|
8334
8674
|
backgroundRepeat: "repeat",
|
|
8335
8675
|
backgroundPosition: `${offsetLeft}px ${offsetTop}px`,
|
|
8336
|
-
transition: animate ? "opacity 0.3s ease" : void 0
|
|
8676
|
+
transition: animate && animationVariant === "fade" ? "opacity 0.3s ease" : void 0
|
|
8337
8677
|
};
|
|
8338
8678
|
if (fullPage) {
|
|
8339
8679
|
overlayStyle.right = 0;
|
|
@@ -8343,17 +8683,33 @@ var Watermark = ({
|
|
|
8343
8683
|
overlayStyle.height = "100%";
|
|
8344
8684
|
}
|
|
8345
8685
|
if (dataURL) overlayStyle.backgroundImage = `url(${dataURL})`;
|
|
8686
|
+
const animationClass = animate ? getAnimationClass(animationVariant, visible) : "";
|
|
8687
|
+
const blurClass = blur ? `backdrop-blur-[${blurAmount}px]` : "";
|
|
8346
8688
|
const overlay = /* @__PURE__ */ jsx40(
|
|
8347
8689
|
"div",
|
|
8348
8690
|
{
|
|
8349
|
-
"
|
|
8350
|
-
|
|
8691
|
+
role: interactive ? "button" : void 0,
|
|
8692
|
+
"aria-label": ariaLabel || (interactive ? "Toggle watermark visibility" : "Watermark overlay"),
|
|
8693
|
+
"aria-hidden": !interactive,
|
|
8694
|
+
tabIndex: interactive ? 0 : void 0,
|
|
8695
|
+
className: cn(
|
|
8696
|
+
interactive ? "cursor-pointer" : "pointer-events-none",
|
|
8697
|
+
blurClass,
|
|
8698
|
+
animationClass,
|
|
8699
|
+
overlayClassName
|
|
8700
|
+
),
|
|
8351
8701
|
style: overlayStyle,
|
|
8352
|
-
onClick: interactive ? () => setVisible(!visible) : void 0
|
|
8702
|
+
onClick: interactive ? () => setVisible(!visible) : void 0,
|
|
8703
|
+
onKeyDown: interactive ? (e) => {
|
|
8704
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
8705
|
+
e.preventDefault();
|
|
8706
|
+
setVisible(!visible);
|
|
8707
|
+
}
|
|
8708
|
+
} : void 0
|
|
8353
8709
|
}
|
|
8354
8710
|
);
|
|
8355
8711
|
if (fullPage) {
|
|
8356
|
-
return /* @__PURE__ */ jsxs35(
|
|
8712
|
+
return /* @__PURE__ */ jsxs35(Fragment14, { children: [
|
|
8357
8713
|
children,
|
|
8358
8714
|
typeof window !== "undefined" ? createPortal9(overlay, document.body) : null
|
|
8359
8715
|
] });
|
|
@@ -9064,7 +9420,7 @@ function ColorPicker({
|
|
|
9064
9420
|
|
|
9065
9421
|
// ../../components/ui/Grid.tsx
|
|
9066
9422
|
import React35, { useId as useId6 } from "react";
|
|
9067
|
-
import { Fragment as
|
|
9423
|
+
import { Fragment as Fragment15, jsx as jsx43, jsxs as jsxs38 } from "react/jsx-runtime";
|
|
9068
9424
|
var BP_MIN = {
|
|
9069
9425
|
sm: 640,
|
|
9070
9426
|
md: 768,
|
|
@@ -9226,7 +9582,7 @@ var GridItem = React35.forwardRef(
|
|
|
9226
9582
|
st.opacity = 0;
|
|
9227
9583
|
st.animation = `uvGridItemFadeIn 0.5s ease-out forwards`;
|
|
9228
9584
|
}
|
|
9229
|
-
return /* @__PURE__ */ jsxs38(
|
|
9585
|
+
return /* @__PURE__ */ jsxs38(Fragment15, { children: [
|
|
9230
9586
|
animationDelay != null && /* @__PURE__ */ jsx43(
|
|
9231
9587
|
"style",
|
|
9232
9588
|
{
|
|
@@ -9256,16 +9612,16 @@ var Grid_default = Grid;
|
|
|
9256
9612
|
|
|
9257
9613
|
// ../../components/ui/ClientOnly.tsx
|
|
9258
9614
|
import { useEffect as useEffect18, useState as useState31 } from "react";
|
|
9259
|
-
import { Fragment as
|
|
9615
|
+
import { Fragment as Fragment16, jsx as jsx44 } from "react/jsx-runtime";
|
|
9260
9616
|
function ClientOnly({ children, fallback = null }) {
|
|
9261
9617
|
const [hasMounted, setHasMounted] = useState31(false);
|
|
9262
9618
|
useEffect18(() => {
|
|
9263
9619
|
setHasMounted(true);
|
|
9264
9620
|
}, []);
|
|
9265
9621
|
if (!hasMounted) {
|
|
9266
|
-
return /* @__PURE__ */ jsx44(
|
|
9622
|
+
return /* @__PURE__ */ jsx44(Fragment16, { children: fallback });
|
|
9267
9623
|
}
|
|
9268
|
-
return /* @__PURE__ */ jsx44(
|
|
9624
|
+
return /* @__PURE__ */ jsx44(Fragment16, { children });
|
|
9269
9625
|
}
|
|
9270
9626
|
|
|
9271
9627
|
// ../../components/ui/Loading.tsx
|
|
@@ -12042,9 +12398,9 @@ function AccessDenied({
|
|
|
12042
12398
|
|
|
12043
12399
|
// ../../components/ui/ThemeToggleHeadless.tsx
|
|
12044
12400
|
import { Moon, Sun, Monitor } from "lucide-react";
|
|
12045
|
-
import { useEffect as useEffect20, useRef as
|
|
12401
|
+
import { useEffect as useEffect20, useRef as useRef12, useState as useState32 } from "react";
|
|
12046
12402
|
import { createPortal as createPortal10 } from "react-dom";
|
|
12047
|
-
import { Fragment as
|
|
12403
|
+
import { Fragment as Fragment17, jsx as jsx52, jsxs as jsxs46 } from "react/jsx-runtime";
|
|
12048
12404
|
function ThemeToggleHeadless({
|
|
12049
12405
|
theme,
|
|
12050
12406
|
onChange,
|
|
@@ -12053,7 +12409,7 @@ function ThemeToggleHeadless({
|
|
|
12053
12409
|
}) {
|
|
12054
12410
|
const [isOpen, setIsOpen] = useState32(false);
|
|
12055
12411
|
const [mounted, setMounted] = useState32(false);
|
|
12056
|
-
const triggerRef =
|
|
12412
|
+
const triggerRef = useRef12(null);
|
|
12057
12413
|
const [dropdownPosition, setDropdownPosition] = useState32(null);
|
|
12058
12414
|
useEffect20(() => setMounted(true), []);
|
|
12059
12415
|
const themes = [
|
|
@@ -12095,7 +12451,7 @@ function ThemeToggleHeadless({
|
|
|
12095
12451
|
children: /* @__PURE__ */ jsx52(CurrentIcon, { className: "h-5 w-5" })
|
|
12096
12452
|
}
|
|
12097
12453
|
),
|
|
12098
|
-
isOpen && /* @__PURE__ */ jsxs46(
|
|
12454
|
+
isOpen && /* @__PURE__ */ jsxs46(Fragment17, { children: [
|
|
12099
12455
|
typeof window !== "undefined" && createPortal10(/* @__PURE__ */ jsx52("div", { className: "fixed inset-0 z-[9998]", onClick: () => setIsOpen(false) }), document.body),
|
|
12100
12456
|
typeof window !== "undefined" && dropdownPosition && createPortal10(
|
|
12101
12457
|
/* @__PURE__ */ jsx52(
|
|
@@ -12144,10 +12500,10 @@ function ThemeToggleHeadless({
|
|
|
12144
12500
|
}
|
|
12145
12501
|
|
|
12146
12502
|
// ../../components/ui/LanguageSwitcherHeadless.tsx
|
|
12147
|
-
import { useRef as
|
|
12503
|
+
import { useRef as useRef13, useState as useState33 } from "react";
|
|
12148
12504
|
import { createPortal as createPortal11 } from "react-dom";
|
|
12149
12505
|
import { Globe } from "lucide-react";
|
|
12150
|
-
import { Fragment as
|
|
12506
|
+
import { Fragment as Fragment18, jsx as jsx53, jsxs as jsxs47 } from "react/jsx-runtime";
|
|
12151
12507
|
function LanguageSwitcherHeadless({
|
|
12152
12508
|
locales,
|
|
12153
12509
|
currentLocale,
|
|
@@ -12157,7 +12513,7 @@ function LanguageSwitcherHeadless({
|
|
|
12157
12513
|
}) {
|
|
12158
12514
|
const [isOpen, setIsOpen] = useState33(false);
|
|
12159
12515
|
const [dropdownPosition, setDropdownPosition] = useState33(null);
|
|
12160
|
-
const triggerButtonRef =
|
|
12516
|
+
const triggerButtonRef = useRef13(null);
|
|
12161
12517
|
const currentLanguage = locales.find((l) => l.code === currentLocale) || locales[0];
|
|
12162
12518
|
const calculatePosition = () => {
|
|
12163
12519
|
const rect = triggerButtonRef.current?.getBoundingClientRect();
|
|
@@ -12192,7 +12548,7 @@ function LanguageSwitcherHeadless({
|
|
|
12192
12548
|
children: /* @__PURE__ */ jsx53(Globe, { className: "h-5 w-5" })
|
|
12193
12549
|
}
|
|
12194
12550
|
),
|
|
12195
|
-
isOpen && /* @__PURE__ */ jsxs47(
|
|
12551
|
+
isOpen && /* @__PURE__ */ jsxs47(Fragment18, { children: [
|
|
12196
12552
|
typeof window !== "undefined" && createPortal11(/* @__PURE__ */ jsx53("div", { className: "fixed inset-0 z-[9998]", onClick: () => setIsOpen(false) }), document.body),
|
|
12197
12553
|
typeof window !== "undefined" && dropdownPosition && createPortal11(
|
|
12198
12554
|
/* @__PURE__ */ jsx53(
|