@geomak/ui 5.1.0 → 5.2.0
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 +288 -216
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +58 -6
- package/dist/index.d.ts +58 -6
- package/dist/index.js +288 -216
- package/dist/index.js.map +1 -1
- package/dist/styles.css +6 -4
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -2397,9 +2397,105 @@ function Dropdown({
|
|
|
2397
2397
|
]
|
|
2398
2398
|
}
|
|
2399
2399
|
),
|
|
2400
|
-
hasError && /* @__PURE__ */ jsxRuntime.jsx("div", { id: errorId, className: "text-
|
|
2400
|
+
hasError && /* @__PURE__ */ jsxRuntime.jsx("div", { id: errorId, className: "text-status-error text-xs mt-1", children: errorMessage })
|
|
2401
2401
|
] });
|
|
2402
2402
|
}
|
|
2403
|
+
var SHIMMER = [
|
|
2404
|
+
"relative overflow-hidden rounded-sm bg-surface-raised",
|
|
2405
|
+
'before:absolute before:inset-0 before:content-[""]',
|
|
2406
|
+
"before:bg-gradient-to-r before:from-transparent before:via-white/30 before:to-transparent",
|
|
2407
|
+
"before:animate-[shimmer_1.6s_linear_infinite]",
|
|
2408
|
+
// Respect prefers-reduced-motion — the resting bg-surface-raised is still
|
|
2409
|
+
// a perfectly legible placeholder for users who have animations off.
|
|
2410
|
+
"motion-reduce:before:hidden"
|
|
2411
|
+
].join(" ");
|
|
2412
|
+
function SkeletonBox({ width, height = 16, radius, className = "", style }) {
|
|
2413
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2414
|
+
"span",
|
|
2415
|
+
{
|
|
2416
|
+
role: "presentation",
|
|
2417
|
+
"aria-hidden": "true",
|
|
2418
|
+
className: `block ${SHIMMER} ${className}`,
|
|
2419
|
+
style: {
|
|
2420
|
+
width: width ?? "100%",
|
|
2421
|
+
height,
|
|
2422
|
+
borderRadius: radius ?? "var(--radius-md)",
|
|
2423
|
+
...style
|
|
2424
|
+
}
|
|
2425
|
+
}
|
|
2426
|
+
);
|
|
2427
|
+
}
|
|
2428
|
+
function SkeletonText({
|
|
2429
|
+
lines = 3,
|
|
2430
|
+
lastLineWidth = 60,
|
|
2431
|
+
lineHeight = 14,
|
|
2432
|
+
gap = 8,
|
|
2433
|
+
className = "",
|
|
2434
|
+
style
|
|
2435
|
+
}) {
|
|
2436
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2437
|
+
"div",
|
|
2438
|
+
{
|
|
2439
|
+
role: "presentation",
|
|
2440
|
+
"aria-hidden": "true",
|
|
2441
|
+
className: `flex flex-col ${className}`,
|
|
2442
|
+
style: { gap, ...style },
|
|
2443
|
+
children: Array.from({ length: lines }).map((_, i) => {
|
|
2444
|
+
const isLast = i === lines - 1;
|
|
2445
|
+
const width = isLast && lines > 1 ? `${lastLineWidth}%` : "100%";
|
|
2446
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2447
|
+
"span",
|
|
2448
|
+
{
|
|
2449
|
+
className: `block ${SHIMMER}`,
|
|
2450
|
+
style: { height: lineHeight, width, borderRadius: "var(--radius-sm)" }
|
|
2451
|
+
},
|
|
2452
|
+
i
|
|
2453
|
+
);
|
|
2454
|
+
})
|
|
2455
|
+
}
|
|
2456
|
+
);
|
|
2457
|
+
}
|
|
2458
|
+
function SkeletonCircle({ size = 40, className = "", style }) {
|
|
2459
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2460
|
+
"span",
|
|
2461
|
+
{
|
|
2462
|
+
role: "presentation",
|
|
2463
|
+
"aria-hidden": "true",
|
|
2464
|
+
className: `block flex-shrink-0 ${SHIMMER} ${className}`,
|
|
2465
|
+
style: {
|
|
2466
|
+
width: size,
|
|
2467
|
+
height: size,
|
|
2468
|
+
borderRadius: "50%",
|
|
2469
|
+
...style
|
|
2470
|
+
}
|
|
2471
|
+
}
|
|
2472
|
+
);
|
|
2473
|
+
}
|
|
2474
|
+
function SkeletonCard({ hasAvatar = true, lines = 3, className = "", style }) {
|
|
2475
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2476
|
+
"div",
|
|
2477
|
+
{
|
|
2478
|
+
role: "presentation",
|
|
2479
|
+
"aria-hidden": "true",
|
|
2480
|
+
className: `rounded-lg border border-border bg-surface p-4 ${className}`,
|
|
2481
|
+
style,
|
|
2482
|
+
children: [
|
|
2483
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3 mb-4", children: [
|
|
2484
|
+
hasAvatar && /* @__PURE__ */ jsxRuntime.jsx(SkeletonCircle, { size: 36 }),
|
|
2485
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 flex flex-col gap-2", children: [
|
|
2486
|
+
/* @__PURE__ */ jsxRuntime.jsx(SkeletonBox, { height: 12, width: "55%" }),
|
|
2487
|
+
/* @__PURE__ */ jsxRuntime.jsx(SkeletonBox, { height: 10, width: "35%" })
|
|
2488
|
+
] })
|
|
2489
|
+
] }),
|
|
2490
|
+
/* @__PURE__ */ jsxRuntime.jsx(SkeletonText, { lines, lastLineWidth: 55 }),
|
|
2491
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-4 flex gap-2", children: [
|
|
2492
|
+
/* @__PURE__ */ jsxRuntime.jsx(SkeletonBox, { height: 28, width: 72 }),
|
|
2493
|
+
/* @__PURE__ */ jsxRuntime.jsx(SkeletonBox, { height: 28, width: 56 })
|
|
2494
|
+
] })
|
|
2495
|
+
]
|
|
2496
|
+
}
|
|
2497
|
+
);
|
|
2498
|
+
}
|
|
2403
2499
|
var DEFAULT_PICKER = [
|
|
2404
2500
|
{ key: 1, value: 5, label: 5 },
|
|
2405
2501
|
{ key: 2, value: 10, label: 10 },
|
|
@@ -2585,7 +2681,9 @@ function Table({
|
|
|
2585
2681
|
expandRow = DEFAULT_EXPAND,
|
|
2586
2682
|
hasSearch = true,
|
|
2587
2683
|
footer = null,
|
|
2588
|
-
header = null
|
|
2684
|
+
header = null,
|
|
2685
|
+
loading = false,
|
|
2686
|
+
loadingRowCount = 8
|
|
2589
2687
|
}) {
|
|
2590
2688
|
const searchRef = React8.useRef(null);
|
|
2591
2689
|
const [searchTerm, setSearchTerm] = React8.useState("");
|
|
@@ -2669,9 +2767,16 @@ function Table({
|
|
|
2669
2767
|
)
|
|
2670
2768
|
] }),
|
|
2671
2769
|
/* @__PURE__ */ jsxRuntime.jsx("div", { children: header }),
|
|
2672
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-x-auto rounded-lg", children: /* @__PURE__ */ jsxRuntime.jsxs("table", { className: "w-full border-collapse", children: [
|
|
2770
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-x-auto rounded-lg", children: /* @__PURE__ */ jsxRuntime.jsxs("table", { className: "w-full border-collapse", "aria-busy": loading || void 0, children: [
|
|
2673
2771
|
/* @__PURE__ */ jsxRuntime.jsx(TableHeader, { columns, hasExpand: !!expandRow.enabled }),
|
|
2674
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2772
|
+
loading ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
2773
|
+
TableSkeletonBody,
|
|
2774
|
+
{
|
|
2775
|
+
columns,
|
|
2776
|
+
rowCount: loadingRowCount,
|
|
2777
|
+
hasExpand: !!expandRow.enabled
|
|
2778
|
+
}
|
|
2779
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
2675
2780
|
TableBody,
|
|
2676
2781
|
{
|
|
2677
2782
|
columns,
|
|
@@ -2684,6 +2789,23 @@ function Table({
|
|
|
2684
2789
|
/* @__PURE__ */ jsxRuntime.jsx("div", { children: footer })
|
|
2685
2790
|
] });
|
|
2686
2791
|
}
|
|
2792
|
+
function TableSkeletonBody({
|
|
2793
|
+
columns,
|
|
2794
|
+
rowCount,
|
|
2795
|
+
hasExpand
|
|
2796
|
+
}) {
|
|
2797
|
+
return /* @__PURE__ */ jsxRuntime.jsx("tbody", { "aria-hidden": "true", children: Array.from({ length: rowCount }).map((_, i) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2798
|
+
"tr",
|
|
2799
|
+
{
|
|
2800
|
+
className: `border-b border-border ${i % 2 === 0 ? "bg-surface" : "bg-surface-raised"}`,
|
|
2801
|
+
children: [
|
|
2802
|
+
hasExpand && /* @__PURE__ */ jsxRuntime.jsx("td", { className: "p-0 align-middle w-9" }),
|
|
2803
|
+
columns.map((col) => /* @__PURE__ */ jsxRuntime.jsx("td", { className: "py-3 px-3 align-middle", children: /* @__PURE__ */ jsxRuntime.jsx(SkeletonBox, { height: 12, width: `${50 + i % 4 * 12}%` }) }, col.key))
|
|
2804
|
+
]
|
|
2805
|
+
},
|
|
2806
|
+
i
|
|
2807
|
+
)) });
|
|
2808
|
+
}
|
|
2687
2809
|
function ThemeSwitch({ checked, onChange, label = "Toggle dark mode" }) {
|
|
2688
2810
|
const id = React8.useId();
|
|
2689
2811
|
return /* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: id, className: "flex items-center gap-2 cursor-pointer select-none", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -3116,102 +3238,6 @@ function ThemeProvider({
|
|
|
3116
3238
|
)
|
|
3117
3239
|
] });
|
|
3118
3240
|
}
|
|
3119
|
-
var SHIMMER = [
|
|
3120
|
-
"relative overflow-hidden rounded-sm bg-surface-raised",
|
|
3121
|
-
'before:absolute before:inset-0 before:content-[""]',
|
|
3122
|
-
"before:bg-gradient-to-r before:from-transparent before:via-white/30 before:to-transparent",
|
|
3123
|
-
"before:animate-[shimmer_1.6s_linear_infinite]",
|
|
3124
|
-
// Respect prefers-reduced-motion — the resting bg-surface-raised is still
|
|
3125
|
-
// a perfectly legible placeholder for users who have animations off.
|
|
3126
|
-
"motion-reduce:before:hidden"
|
|
3127
|
-
].join(" ");
|
|
3128
|
-
function SkeletonBox({ width, height = 16, radius, className = "", style }) {
|
|
3129
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
3130
|
-
"span",
|
|
3131
|
-
{
|
|
3132
|
-
role: "presentation",
|
|
3133
|
-
"aria-hidden": "true",
|
|
3134
|
-
className: `block ${SHIMMER} ${className}`,
|
|
3135
|
-
style: {
|
|
3136
|
-
width: width ?? "100%",
|
|
3137
|
-
height,
|
|
3138
|
-
borderRadius: radius ?? "var(--radius-md)",
|
|
3139
|
-
...style
|
|
3140
|
-
}
|
|
3141
|
-
}
|
|
3142
|
-
);
|
|
3143
|
-
}
|
|
3144
|
-
function SkeletonText({
|
|
3145
|
-
lines = 3,
|
|
3146
|
-
lastLineWidth = 60,
|
|
3147
|
-
lineHeight = 14,
|
|
3148
|
-
gap = 8,
|
|
3149
|
-
className = "",
|
|
3150
|
-
style
|
|
3151
|
-
}) {
|
|
3152
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
3153
|
-
"div",
|
|
3154
|
-
{
|
|
3155
|
-
role: "presentation",
|
|
3156
|
-
"aria-hidden": "true",
|
|
3157
|
-
className: `flex flex-col ${className}`,
|
|
3158
|
-
style: { gap, ...style },
|
|
3159
|
-
children: Array.from({ length: lines }).map((_, i) => {
|
|
3160
|
-
const isLast = i === lines - 1;
|
|
3161
|
-
const width = isLast && lines > 1 ? `${lastLineWidth}%` : "100%";
|
|
3162
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
3163
|
-
"span",
|
|
3164
|
-
{
|
|
3165
|
-
className: `block ${SHIMMER}`,
|
|
3166
|
-
style: { height: lineHeight, width, borderRadius: "var(--radius-sm)" }
|
|
3167
|
-
},
|
|
3168
|
-
i
|
|
3169
|
-
);
|
|
3170
|
-
})
|
|
3171
|
-
}
|
|
3172
|
-
);
|
|
3173
|
-
}
|
|
3174
|
-
function SkeletonCircle({ size = 40, className = "", style }) {
|
|
3175
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
3176
|
-
"span",
|
|
3177
|
-
{
|
|
3178
|
-
role: "presentation",
|
|
3179
|
-
"aria-hidden": "true",
|
|
3180
|
-
className: `block flex-shrink-0 ${SHIMMER} ${className}`,
|
|
3181
|
-
style: {
|
|
3182
|
-
width: size,
|
|
3183
|
-
height: size,
|
|
3184
|
-
borderRadius: "50%",
|
|
3185
|
-
...style
|
|
3186
|
-
}
|
|
3187
|
-
}
|
|
3188
|
-
);
|
|
3189
|
-
}
|
|
3190
|
-
function SkeletonCard({ hasAvatar = true, lines = 3, className = "", style }) {
|
|
3191
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3192
|
-
"div",
|
|
3193
|
-
{
|
|
3194
|
-
role: "presentation",
|
|
3195
|
-
"aria-hidden": "true",
|
|
3196
|
-
className: `rounded-lg border border-border bg-surface p-4 ${className}`,
|
|
3197
|
-
style,
|
|
3198
|
-
children: [
|
|
3199
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3 mb-4", children: [
|
|
3200
|
-
hasAvatar && /* @__PURE__ */ jsxRuntime.jsx(SkeletonCircle, { size: 36 }),
|
|
3201
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 flex flex-col gap-2", children: [
|
|
3202
|
-
/* @__PURE__ */ jsxRuntime.jsx(SkeletonBox, { height: 12, width: "55%" }),
|
|
3203
|
-
/* @__PURE__ */ jsxRuntime.jsx(SkeletonBox, { height: 10, width: "35%" })
|
|
3204
|
-
] })
|
|
3205
|
-
] }),
|
|
3206
|
-
/* @__PURE__ */ jsxRuntime.jsx(SkeletonText, { lines, lastLineWidth: 55 }),
|
|
3207
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-4 flex gap-2", children: [
|
|
3208
|
-
/* @__PURE__ */ jsxRuntime.jsx(SkeletonBox, { height: 28, width: 72 }),
|
|
3209
|
-
/* @__PURE__ */ jsxRuntime.jsx(SkeletonBox, { height: 28, width: 56 })
|
|
3210
|
-
] })
|
|
3211
|
-
]
|
|
3212
|
-
}
|
|
3213
|
-
);
|
|
3214
|
-
}
|
|
3215
3241
|
function TextInput({
|
|
3216
3242
|
value,
|
|
3217
3243
|
onChange,
|
|
@@ -3229,48 +3255,50 @@ function TextInput({
|
|
|
3229
3255
|
}) {
|
|
3230
3256
|
const errorId = React8.useId();
|
|
3231
3257
|
const hasError = errorMessage != null;
|
|
3232
|
-
return
|
|
3258
|
+
return (
|
|
3259
|
+
// In horizontal mode the row layout is [label, input-with-error-column].
|
|
3260
|
+
// The error sits under the input ONLY, not spanning the label too.
|
|
3261
|
+
// In vertical mode the whole thing is a column.
|
|
3233
3262
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
3234
3263
|
"div",
|
|
3235
3264
|
{
|
|
3236
|
-
className: `flex ${layout === "vertical" ? "flex-col" : "flex-row items-
|
|
3265
|
+
className: `flex ${layout === "vertical" ? "flex-col gap-1" : "flex-row items-start gap-2"}`,
|
|
3237
3266
|
style: style ?? {},
|
|
3238
3267
|
children: [
|
|
3239
|
-
label &&
|
|
3240
|
-
// <label htmlFor=…> announces as an unlabeled control in
|
|
3241
|
-
// some screen readers.
|
|
3242
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3268
|
+
label && /* @__PURE__ */ jsxRuntime.jsx(
|
|
3243
3269
|
"label",
|
|
3244
3270
|
{
|
|
3245
3271
|
style: { color: labelColor || void 0 },
|
|
3246
|
-
className: `text-sm font-medium
|
|
3272
|
+
className: `text-sm font-medium ${layout === "horizontal" ? "mt-2" : ""} max-content ${!labelColor && "text-foreground"}`,
|
|
3247
3273
|
htmlFor,
|
|
3248
3274
|
children: label
|
|
3249
3275
|
}
|
|
3250
3276
|
),
|
|
3251
|
-
/* @__PURE__ */ jsxRuntime.
|
|
3252
|
-
|
|
3253
|
-
|
|
3254
|
-
|
|
3255
|
-
|
|
3256
|
-
|
|
3257
|
-
|
|
3258
|
-
|
|
3259
|
-
|
|
3260
|
-
|
|
3261
|
-
|
|
3262
|
-
|
|
3263
|
-
|
|
3264
|
-
|
|
3265
|
-
|
|
3266
|
-
|
|
3267
|
-
|
|
3268
|
-
|
|
3277
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", children: [
|
|
3278
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3279
|
+
"input",
|
|
3280
|
+
{
|
|
3281
|
+
autoComplete: "off",
|
|
3282
|
+
disabled,
|
|
3283
|
+
value,
|
|
3284
|
+
onChange,
|
|
3285
|
+
onBlur,
|
|
3286
|
+
type: "text",
|
|
3287
|
+
name,
|
|
3288
|
+
id: htmlFor,
|
|
3289
|
+
"aria-invalid": hasError || void 0,
|
|
3290
|
+
"aria-describedby": hasError ? errorId : void 0,
|
|
3291
|
+
className: `${hasError ? "border border-status-error" : "border border-border"} bg-surface text-foreground p-2 h-9 w-60 rounded-lg disabled:bg-surface-raised disabled:text-foreground-muted disabled:cursor-not-allowed focus:outline-none focus:border-transparent focus:ring-2 focus:ring-accent transition-colors`,
|
|
3292
|
+
style: inputStyle ?? {},
|
|
3293
|
+
placeholder: placeholder ?? ""
|
|
3294
|
+
}
|
|
3295
|
+
),
|
|
3296
|
+
hasError && /* @__PURE__ */ jsxRuntime.jsx("div", { id: errorId, className: "text-status-error text-xs mt-1", children: errorMessage })
|
|
3297
|
+
] })
|
|
3269
3298
|
]
|
|
3270
3299
|
}
|
|
3271
|
-
)
|
|
3272
|
-
|
|
3273
|
-
] });
|
|
3300
|
+
)
|
|
3301
|
+
);
|
|
3274
3302
|
}
|
|
3275
3303
|
function NumberInput({
|
|
3276
3304
|
step = 1,
|
|
@@ -3412,64 +3440,71 @@ function Password({
|
|
|
3412
3440
|
const [passwordVisible, setPasswordVisible] = React8.useState(false);
|
|
3413
3441
|
const errorId = React8.useId();
|
|
3414
3442
|
const hasError = errorMessage != null;
|
|
3415
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3416
|
-
|
|
3417
|
-
|
|
3418
|
-
|
|
3419
|
-
|
|
3420
|
-
|
|
3421
|
-
|
|
3422
|
-
|
|
3423
|
-
children: label
|
|
3424
|
-
}
|
|
3425
|
-
),
|
|
3426
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
|
|
3427
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3428
|
-
"input",
|
|
3443
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3444
|
+
"div",
|
|
3445
|
+
{
|
|
3446
|
+
className: `flex ${layout === "vertical" ? "flex-col gap-1" : "flex-row items-start gap-2"}`,
|
|
3447
|
+
style: style ?? {},
|
|
3448
|
+
children: [
|
|
3449
|
+
label && /* @__PURE__ */ jsxRuntime.jsx(
|
|
3450
|
+
"label",
|
|
3429
3451
|
{
|
|
3430
|
-
|
|
3431
|
-
|
|
3432
|
-
|
|
3433
|
-
|
|
3434
|
-
onBlur,
|
|
3435
|
-
type: passwordVisible ? "text" : "password",
|
|
3436
|
-
name,
|
|
3437
|
-
id: htmlFor,
|
|
3438
|
-
"aria-invalid": hasError || void 0,
|
|
3439
|
-
"aria-describedby": hasError ? errorId : void 0,
|
|
3440
|
-
className: `${hasError ? "border border-status-error" : "border border-border"} bg-surface text-foreground p-2 h-9 w-52 mt-1 rounded-lg disabled:bg-surface-raised disabled:text-foreground-muted disabled:cursor-not-allowed focus:outline-none focus:border-transparent focus:ring-2 focus:ring-accent transition-colors`,
|
|
3441
|
-
style: inputStyle ?? {},
|
|
3442
|
-
placeholder: placeholder ?? ""
|
|
3452
|
+
style: { color: labelColor || void 0 },
|
|
3453
|
+
className: `text-sm font-medium ${layout === "horizontal" ? "mt-2" : ""} max-content ${!labelColor && "text-foreground"}`,
|
|
3454
|
+
htmlFor,
|
|
3455
|
+
children: label
|
|
3443
3456
|
}
|
|
3444
3457
|
),
|
|
3445
|
-
/* @__PURE__ */ jsxRuntime.
|
|
3446
|
-
"
|
|
3447
|
-
|
|
3448
|
-
|
|
3449
|
-
|
|
3450
|
-
|
|
3451
|
-
|
|
3452
|
-
|
|
3453
|
-
|
|
3454
|
-
|
|
3455
|
-
|
|
3456
|
-
|
|
3457
|
-
|
|
3458
|
-
|
|
3459
|
-
|
|
3460
|
-
|
|
3461
|
-
|
|
3462
|
-
|
|
3463
|
-
|
|
3464
|
-
|
|
3465
|
-
|
|
3458
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", children: [
|
|
3459
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
|
|
3460
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3461
|
+
"input",
|
|
3462
|
+
{
|
|
3463
|
+
autoComplete: "off",
|
|
3464
|
+
disabled,
|
|
3465
|
+
value,
|
|
3466
|
+
onChange,
|
|
3467
|
+
onBlur,
|
|
3468
|
+
type: passwordVisible ? "text" : "password",
|
|
3469
|
+
name,
|
|
3470
|
+
id: htmlFor,
|
|
3471
|
+
"aria-invalid": hasError || void 0,
|
|
3472
|
+
"aria-describedby": hasError ? errorId : void 0,
|
|
3473
|
+
className: `${hasError ? "border border-status-error" : "border border-border"} bg-surface text-foreground p-2 h-9 w-52 rounded-lg disabled:bg-surface-raised disabled:text-foreground-muted disabled:cursor-not-allowed focus:outline-none focus:border-transparent focus:ring-2 focus:ring-accent transition-colors`,
|
|
3474
|
+
style: inputStyle ?? {},
|
|
3475
|
+
placeholder: placeholder ?? ""
|
|
3476
|
+
}
|
|
3477
|
+
),
|
|
3478
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3479
|
+
"button",
|
|
3480
|
+
{
|
|
3481
|
+
type: "button",
|
|
3482
|
+
className: "cursor-pointer p-1 text-foreground-secondary hover:text-foreground rounded-md focus:outline-none focus-visible:ring-2 focus-visible:ring-accent",
|
|
3483
|
+
style: iconColor ? { color: iconColor } : void 0,
|
|
3484
|
+
onClick: () => setPasswordVisible(!passwordVisible),
|
|
3485
|
+
"aria-label": passwordVisible ? "Hide password" : "Show password",
|
|
3486
|
+
children: passwordVisible ? (
|
|
3487
|
+
/* EyeSlash */
|
|
3488
|
+
/* @__PURE__ */ jsxRuntime.jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "currentColor", className: "w-6 h-6", children: [
|
|
3489
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M3.53 2.47a.75.75 0 00-1.06 1.06l18 18a.75.75 0 101.06-1.06l-18-18zM22.676 12.553a11.249 11.249 0 01-2.631 4.31l-3.099-3.099a5.25 5.25 0 00-6.71-6.71L7.759 4.577a11.217 11.217 0 014.242-.827c4.97 0 9.185 3.223 10.675 7.69.12.362.12.752 0 1.113z" }),
|
|
3490
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M15.75 12c0 .18-.013.357-.037.53l-4.244-4.243A3.75 3.75 0 0115.75 12zM12.53 15.713l-4.243-4.244a3.75 3.75 0 004.243 4.243z" }),
|
|
3491
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M6.75 12c0-.619.107-1.213.304-1.764l-3.1-3.1a11.25 11.25 0 00-2.63 4.31c-.12.362-.12.752 0 1.114 1.489 4.467 5.704 7.69 10.675 7.69 1.5 0 2.933-.294 4.242-.827l-2.477-2.477A5.25 5.25 0 016.75 12z" })
|
|
3492
|
+
] })
|
|
3493
|
+
) : (
|
|
3494
|
+
/* Eye */
|
|
3495
|
+
/* @__PURE__ */ jsxRuntime.jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "currentColor", className: "w-6 h-6", children: [
|
|
3496
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12 15a3 3 0 100-6 3 3 0 000 6z" }),
|
|
3497
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { fillRule: "evenodd", d: "M1.323 11.447C2.811 6.976 7.028 3.75 12.001 3.75c4.97 0 9.185 3.223 10.675 7.69.12.362.12.752 0 1.113-1.487 4.471-5.705 7.697-10.677 7.697-4.97 0-9.186-3.223-10.675-7.69a1.762 1.762 0 010-1.113zM17.25 12a5.25 5.25 0 11-10.5 0 5.25 5.25 0 0110.5 0z", clipRule: "evenodd" })
|
|
3498
|
+
] })
|
|
3499
|
+
)
|
|
3500
|
+
}
|
|
3466
3501
|
)
|
|
3467
|
-
}
|
|
3468
|
-
|
|
3469
|
-
|
|
3470
|
-
|
|
3471
|
-
|
|
3472
|
-
|
|
3502
|
+
] }),
|
|
3503
|
+
hasError && /* @__PURE__ */ jsxRuntime.jsx("div", { id: errorId, className: "text-status-error text-xs mt-1", children: errorMessage })
|
|
3504
|
+
] })
|
|
3505
|
+
]
|
|
3506
|
+
}
|
|
3507
|
+
);
|
|
3473
3508
|
}
|
|
3474
3509
|
function Checkbox({
|
|
3475
3510
|
checked,
|
|
@@ -3582,15 +3617,54 @@ function AutoComplete({
|
|
|
3582
3617
|
inputStyle,
|
|
3583
3618
|
style,
|
|
3584
3619
|
layout = "vertical",
|
|
3585
|
-
items
|
|
3620
|
+
items,
|
|
3621
|
+
onSearch,
|
|
3622
|
+
debounce = 250,
|
|
3586
3623
|
onItemClick,
|
|
3587
|
-
emptyText = "No results found"
|
|
3624
|
+
emptyText = "No results found",
|
|
3625
|
+
loadingText = "Searching\u2026"
|
|
3588
3626
|
}) {
|
|
3589
3627
|
const [term, setTerm] = React8.useState("");
|
|
3590
3628
|
const [open, setOpen] = React8.useState(false);
|
|
3591
|
-
const
|
|
3629
|
+
const [asyncItems, setAsyncItems] = React8.useState([]);
|
|
3630
|
+
const [loading, setLoading] = React8.useState(false);
|
|
3631
|
+
const isAsync = typeof onSearch === "function";
|
|
3632
|
+
const debounceRef = React8.useRef(null);
|
|
3633
|
+
const requestIdRef = React8.useRef(0);
|
|
3634
|
+
const staticFiltered = isAsync || !items ? [] : term.trim() ? items.filter(
|
|
3592
3635
|
({ key, label: label2 }) => label2.toLowerCase().includes(term.toLowerCase()) || key.toLowerCase().includes(term.toLowerCase())
|
|
3593
3636
|
) : [];
|
|
3637
|
+
React8.useEffect(() => {
|
|
3638
|
+
if (!isAsync) return;
|
|
3639
|
+
if (debounceRef.current) clearTimeout(debounceRef.current);
|
|
3640
|
+
if (!term.trim()) {
|
|
3641
|
+
setAsyncItems([]);
|
|
3642
|
+
setLoading(false);
|
|
3643
|
+
return;
|
|
3644
|
+
}
|
|
3645
|
+
const myId = ++requestIdRef.current;
|
|
3646
|
+
setLoading(true);
|
|
3647
|
+
debounceRef.current = setTimeout(async () => {
|
|
3648
|
+
try {
|
|
3649
|
+
const res = await onSearch(term);
|
|
3650
|
+
if (myId === requestIdRef.current) {
|
|
3651
|
+
setAsyncItems(res);
|
|
3652
|
+
}
|
|
3653
|
+
} catch {
|
|
3654
|
+
if (myId === requestIdRef.current) {
|
|
3655
|
+
setAsyncItems([]);
|
|
3656
|
+
}
|
|
3657
|
+
} finally {
|
|
3658
|
+
if (myId === requestIdRef.current) {
|
|
3659
|
+
setLoading(false);
|
|
3660
|
+
}
|
|
3661
|
+
}
|
|
3662
|
+
}, debounce);
|
|
3663
|
+
return () => {
|
|
3664
|
+
if (debounceRef.current) clearTimeout(debounceRef.current);
|
|
3665
|
+
};
|
|
3666
|
+
}, [term, isAsync, debounce, onSearch]);
|
|
3667
|
+
const foundItems = isAsync ? asyncItems : staticFiltered;
|
|
3594
3668
|
const handleSelect = (item) => {
|
|
3595
3669
|
setTerm(`${item.label} (${item.value})`);
|
|
3596
3670
|
onItemClick?.(item.value);
|
|
@@ -3623,10 +3697,11 @@ function AutoComplete({
|
|
|
3623
3697
|
autoComplete: "off",
|
|
3624
3698
|
"aria-haspopup": "listbox",
|
|
3625
3699
|
"aria-expanded": open,
|
|
3626
|
-
"aria-autocomplete": "list"
|
|
3700
|
+
"aria-autocomplete": "list",
|
|
3701
|
+
"aria-busy": loading || void 0
|
|
3627
3702
|
}
|
|
3628
3703
|
),
|
|
3629
|
-
/* @__PURE__ */ jsxRuntime.jsx("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "currentColor", className: "w-5 h-5 flex-shrink-0 text-foreground-muted", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx("path", { fillRule: "evenodd", d: "M10.5 3.75a6.75 6.75 0 100 13.5 6.75 6.75 0 000-13.5zM2.25 10.5a8.25 8.25 0 1114.59 5.28l4.69 4.69a.75.75 0 11-1.06 1.06l-4.69-4.69A8.25 8.25 0 012.25 10.5z", clipRule: "evenodd" }) })
|
|
3704
|
+
loading ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "w-5 h-5 flex-shrink-0 flex items-center justify-center text-accent", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx(LoadingSpinner, { inline: true, size: "xs", spinnerColor: "currentColor" }) }) : /* @__PURE__ */ jsxRuntime.jsx("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "currentColor", className: "w-5 h-5 flex-shrink-0 text-foreground-muted", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx("path", { fillRule: "evenodd", d: "M10.5 3.75a6.75 6.75 0 100 13.5 6.75 6.75 0 000-13.5zM2.25 10.5a8.25 8.25 0 1114.59 5.28l4.69 4.69a.75.75 0 11-1.06 1.06l-4.69-4.69A8.25 8.25 0 012.25 10.5z", clipRule: "evenodd" }) })
|
|
3630
3705
|
] }) }),
|
|
3631
3706
|
/* @__PURE__ */ jsxRuntime.jsx(Popover__namespace.Portal, { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3632
3707
|
Popover__namespace.Content,
|
|
@@ -3635,36 +3710,33 @@ function AutoComplete({
|
|
|
3635
3710
|
sideOffset: 4,
|
|
3636
3711
|
onOpenAutoFocus: (e) => e.preventDefault(),
|
|
3637
3712
|
className: "w-64 bg-surface border border-border rounded-lg mt-1 shadow-md z-50 overflow-y-auto max-h-36 animate-in fade-in-0 zoom-in-95",
|
|
3638
|
-
children:
|
|
3639
|
-
|
|
3640
|
-
|
|
3641
|
-
|
|
3642
|
-
|
|
3643
|
-
|
|
3644
|
-
"
|
|
3645
|
-
|
|
3646
|
-
|
|
3647
|
-
|
|
3648
|
-
|
|
3649
|
-
|
|
3650
|
-
|
|
3651
|
-
|
|
3652
|
-
|
|
3653
|
-
handleSelect(item);
|
|
3654
|
-
}
|
|
3655
|
-
},
|
|
3656
|
-
children: [
|
|
3657
|
-
item.icon,
|
|
3658
|
-
/* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
3659
|
-
item.label,
|
|
3660
|
-
" (",
|
|
3661
|
-
item.value,
|
|
3662
|
-
")"
|
|
3663
|
-
] })
|
|
3664
|
-
]
|
|
3713
|
+
children: loading ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "h-full w-full flex items-center justify-center gap-2 py-4 text-sm text-foreground-secondary", children: [
|
|
3714
|
+
/* @__PURE__ */ jsxRuntime.jsx(LoadingSpinner, { inline: true, size: "xs" }),
|
|
3715
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: loadingText })
|
|
3716
|
+
] }) : foundItems.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-full w-full flex flex-col items-center justify-center py-4 text-sm text-foreground-secondary", children: emptyText }) : /* @__PURE__ */ jsxRuntime.jsx("div", { role: "listbox", children: foundItems.map((item) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3717
|
+
"div",
|
|
3718
|
+
{
|
|
3719
|
+
role: "option",
|
|
3720
|
+
tabIndex: 0,
|
|
3721
|
+
className: "text-sm flex items-center gap-2 p-2 transition-colors duration-150 hover:bg-surface-raised cursor-pointer text-foreground focus:outline-none focus-visible:ring-2 focus-visible:ring-accent",
|
|
3722
|
+
onClick: () => handleSelect(item),
|
|
3723
|
+
onKeyDown: (e) => {
|
|
3724
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
3725
|
+
e.preventDefault();
|
|
3726
|
+
handleSelect(item);
|
|
3727
|
+
}
|
|
3665
3728
|
},
|
|
3666
|
-
|
|
3667
|
-
|
|
3729
|
+
children: [
|
|
3730
|
+
item.icon,
|
|
3731
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
3732
|
+
item.label,
|
|
3733
|
+
" (",
|
|
3734
|
+
item.value,
|
|
3735
|
+
")"
|
|
3736
|
+
] })
|
|
3737
|
+
]
|
|
3738
|
+
},
|
|
3739
|
+
item.key
|
|
3668
3740
|
)) })
|
|
3669
3741
|
}
|
|
3670
3742
|
) })
|