@geomak/ui 5.4.0 → 5.5.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 +831 -182
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +202 -11
- package/dist/index.d.ts +202 -11
- package/dist/index.js +827 -183
- package/dist/index.js.map +1 -1
- package/dist/styles.css +59 -23
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1835,8 +1835,8 @@ function CatalogCarousel({ items, buttonText, onOpen }) {
|
|
|
1835
1835
|
)
|
|
1836
1836
|
] }) });
|
|
1837
1837
|
}
|
|
1838
|
-
function Catalog({ display = "grid", items = [], buttonText, onOpen }) {
|
|
1839
|
-
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full h-full", children:
|
|
1838
|
+
function Catalog({ display: display2 = "grid", items = [], buttonText, onOpen }) {
|
|
1839
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full h-full", children: display2 === "grid" ? /* @__PURE__ */ jsxRuntime.jsx(CatalogGrid, { items, buttonText, onOpen }) : /* @__PURE__ */ jsxRuntime.jsx(CatalogCarousel, { items, buttonText, onOpen }) });
|
|
1840
1840
|
}
|
|
1841
1841
|
function ContextMenu({ items, children }) {
|
|
1842
1842
|
return /* @__PURE__ */ jsxRuntime.jsxs(ContextMenuPrimitive__namespace.Root, { children: [
|
|
@@ -2175,9 +2175,9 @@ var FIELD_SIZE = {
|
|
|
2175
2175
|
lg: { control: "h-control-lg", text: "text-sm", padX: "px-3.5", gap: "gap-2.5" }
|
|
2176
2176
|
};
|
|
2177
2177
|
var FOCUS_WITHIN = "focus-within:outline-none focus-within:border-accent focus-within:ring-[3px] focus-within:ring-focus-ring";
|
|
2178
|
-
var
|
|
2178
|
+
var FOCUS_ELEMENT = "focus:outline-none focus:border-accent focus:ring-[3px] focus:ring-focus-ring data-[state=open]:border-accent data-[state=open]:ring-[3px] data-[state=open]:ring-focus-ring";
|
|
2179
2179
|
var FOCUS_WITHIN_ERROR = "focus-within:border-status-error focus-within:ring-focus-ring-error";
|
|
2180
|
-
var
|
|
2180
|
+
var FOCUS_ELEMENT_ERROR = "focus:border-status-error focus:ring-focus-ring-error data-[state=open]:border-status-error data-[state=open]:ring-focus-ring-error";
|
|
2181
2181
|
function fieldShell({
|
|
2182
2182
|
size = "md",
|
|
2183
2183
|
hasError = false,
|
|
@@ -2196,8 +2196,8 @@ function fieldShell({
|
|
|
2196
2196
|
// hover (only when interactive + no error)
|
|
2197
2197
|
disabled ? "bg-surface-raised text-foreground-muted cursor-not-allowed" : hasError ? "" : "hover:border-border-strong",
|
|
2198
2198
|
// focus
|
|
2199
|
-
focusWithin ? FOCUS_WITHIN :
|
|
2200
|
-
hasError ? focusWithin ? FOCUS_WITHIN_ERROR :
|
|
2199
|
+
focusWithin ? FOCUS_WITHIN : FOCUS_ELEMENT,
|
|
2200
|
+
hasError ? focusWithin ? FOCUS_WITHIN_ERROR : FOCUS_ELEMENT_ERROR : "",
|
|
2201
2201
|
// placeholder colour for native inputs
|
|
2202
2202
|
"placeholder:text-foreground-muted"
|
|
2203
2203
|
].filter(Boolean).join(" ");
|
|
@@ -2232,7 +2232,9 @@ function Field({
|
|
|
2232
2232
|
style: { width: horizontal ? labelWidth : void 0, ...labelStyle },
|
|
2233
2233
|
className: [
|
|
2234
2234
|
"text-sm font-medium text-foreground select-none",
|
|
2235
|
-
horizontal
|
|
2235
|
+
// In horizontal layout the label must not wrap onto
|
|
2236
|
+
// multiple lines (e.g. "Report date", "Select option").
|
|
2237
|
+
horizontal ? "mt-2 flex-shrink-0 whitespace-nowrap" : ""
|
|
2236
2238
|
].filter(Boolean).join(" "),
|
|
2237
2239
|
children: [
|
|
2238
2240
|
label,
|
|
@@ -2278,14 +2280,24 @@ var SearchInput = React8__default.default.forwardRef(function SearchInput2({ val
|
|
|
2278
2280
|
) });
|
|
2279
2281
|
});
|
|
2280
2282
|
var SearchInput_default = SearchInput;
|
|
2281
|
-
function
|
|
2282
|
-
return /* @__PURE__ */ jsxRuntime.
|
|
2283
|
-
"
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2283
|
+
function Tag({ children, onRemove, removeLabel, disabled }) {
|
|
2284
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex items-center gap-1 rounded-md border border-border bg-surface-raised text-foreground text-xs pl-2 pr-1 py-0.5 max-w-full", children: [
|
|
2285
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children }),
|
|
2286
|
+
onRemove && /* @__PURE__ */ jsxRuntime.jsx(
|
|
2287
|
+
"button",
|
|
2288
|
+
{
|
|
2289
|
+
type: "button",
|
|
2290
|
+
disabled,
|
|
2291
|
+
onClick: (e) => {
|
|
2292
|
+
e.stopPropagation();
|
|
2293
|
+
onRemove();
|
|
2294
|
+
},
|
|
2295
|
+
"aria-label": removeLabel ?? "Remove",
|
|
2296
|
+
className: "inline-flex items-center justify-center w-4 h-4 flex-shrink-0 rounded text-foreground-muted hover:text-status-error hover:bg-surface transition-colors focus:outline-none focus-visible:ring-1 focus-visible:ring-accent disabled:cursor-not-allowed",
|
|
2297
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "10", height: "10", viewBox: "0 0 20 20", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M15 5L5 15M5 5l10 10", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }) })
|
|
2298
|
+
}
|
|
2299
|
+
)
|
|
2300
|
+
] });
|
|
2289
2301
|
}
|
|
2290
2302
|
function Dropdown({
|
|
2291
2303
|
isMultiselect = false,
|
|
@@ -2302,7 +2314,6 @@ function Dropdown({
|
|
|
2302
2314
|
items = [],
|
|
2303
2315
|
labelStyle = {},
|
|
2304
2316
|
placeholder,
|
|
2305
|
-
showSelectedCount = false,
|
|
2306
2317
|
size = "md"
|
|
2307
2318
|
}) {
|
|
2308
2319
|
const [open, setOpen] = React8.useState(false);
|
|
@@ -2330,6 +2341,17 @@ function Dropdown({
|
|
|
2330
2341
|
setOpen(false);
|
|
2331
2342
|
}
|
|
2332
2343
|
};
|
|
2344
|
+
const removeSelected = (key) => {
|
|
2345
|
+
if (isMultiselect) {
|
|
2346
|
+
const next = selectedItems.filter((it) => it !== key);
|
|
2347
|
+
setSelectedItems(next);
|
|
2348
|
+
onChange?.({ target: { value: next, id: htmlFor, name } });
|
|
2349
|
+
} else {
|
|
2350
|
+
setSelectedItems([]);
|
|
2351
|
+
onChange?.({ target: { value: "", id: htmlFor, name } });
|
|
2352
|
+
}
|
|
2353
|
+
};
|
|
2354
|
+
const labelFor = (key) => innerItems.find((it) => it.key === key)?.label ?? String(key);
|
|
2333
2355
|
const onSearchChange = (e) => {
|
|
2334
2356
|
const term = e.target.value;
|
|
2335
2357
|
setSearchTerm(term);
|
|
@@ -2340,16 +2362,16 @@ function Dropdown({
|
|
|
2340
2362
|
);
|
|
2341
2363
|
};
|
|
2342
2364
|
const isSelected = (key) => Array.isArray(value) ? value.includes(key) : value === key;
|
|
2343
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", {
|
|
2365
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2344
2366
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
2345
2367
|
"div",
|
|
2346
2368
|
{
|
|
2347
|
-
className: `flex ${layout === "vertical" ? "flex-col" : "flex-row items-
|
|
2369
|
+
className: `flex ${layout === "vertical" ? "flex-col gap-1.5" : "flex-row items-start gap-3"}`,
|
|
2348
2370
|
children: [
|
|
2349
2371
|
label && /* @__PURE__ */ jsxRuntime.jsx(
|
|
2350
2372
|
"label",
|
|
2351
2373
|
{
|
|
2352
|
-
className:
|
|
2374
|
+
className: `text-sm font-medium select-none text-foreground ${layout === "horizontal" ? "mt-2 flex-shrink-0 whitespace-nowrap" : ""}`,
|
|
2353
2375
|
htmlFor,
|
|
2354
2376
|
style: labelStyle,
|
|
2355
2377
|
children: label
|
|
@@ -2366,7 +2388,7 @@ function Dropdown({
|
|
|
2366
2388
|
"aria-invalid": hasError || void 0,
|
|
2367
2389
|
"aria-describedby": hasError ? errorId : void 0,
|
|
2368
2390
|
style,
|
|
2369
|
-
className: `flex items-center justify-between cursor-pointer select-none ${fieldShell({ size, hasError, disabled })}`,
|
|
2391
|
+
className: `flex items-center justify-between gap-1 cursor-pointer select-none min-h-[36px] px-3 py-1.5 ${fieldShell({ size, hasError, disabled, sized: false })}`,
|
|
2370
2392
|
tabIndex: disabled ? -1 : 0,
|
|
2371
2393
|
onKeyDown: (e) => {
|
|
2372
2394
|
if (disabled) return;
|
|
@@ -2379,18 +2401,25 @@ function Dropdown({
|
|
|
2379
2401
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2380
2402
|
"div",
|
|
2381
2403
|
{
|
|
2382
|
-
className: `${!style?.width ? "min-w-[200px]" : ""} flex items-center gap-1
|
|
2383
|
-
children: !value || Array.isArray(value) && value.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-foreground-muted text-sm", children: placeholder }) : Array.isArray(value) ? /* @__PURE__ */ jsxRuntime.
|
|
2384
|
-
|
|
2385
|
-
|
|
2386
|
-
|
|
2387
|
-
|
|
2388
|
-
|
|
2389
|
-
|
|
2390
|
-
|
|
2391
|
-
)
|
|
2392
|
-
|
|
2393
|
-
|
|
2404
|
+
className: `${!style?.width ? "min-w-[200px]" : ""} flex flex-wrap items-center gap-1.5`,
|
|
2405
|
+
children: !value || Array.isArray(value) && value.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-foreground-muted text-sm", children: placeholder }) : Array.isArray(value) ? value.map((val) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
2406
|
+
Tag,
|
|
2407
|
+
{
|
|
2408
|
+
disabled,
|
|
2409
|
+
removeLabel: `Remove ${labelFor(val)}`,
|
|
2410
|
+
onRemove: () => removeSelected(val),
|
|
2411
|
+
children: labelFor(val)
|
|
2412
|
+
},
|
|
2413
|
+
String(val)
|
|
2414
|
+
)) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
2415
|
+
Tag,
|
|
2416
|
+
{
|
|
2417
|
+
disabled,
|
|
2418
|
+
removeLabel: `Remove ${labelFor(value)}`,
|
|
2419
|
+
onRemove: () => removeSelected(value),
|
|
2420
|
+
children: labelFor(value)
|
|
2421
|
+
}
|
|
2422
|
+
)
|
|
2394
2423
|
}
|
|
2395
2424
|
),
|
|
2396
2425
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: `flex-shrink-0 ml-2 text-foreground-muted transition-transform duration-200 ${open ? "rotate-180" : "rotate-0"}`, "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, className: "h-4 w-4", children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M19 9l-7 7-7-7" }) }) })
|
|
@@ -3584,74 +3613,54 @@ function Checkbox({
|
|
|
3584
3613
|
name,
|
|
3585
3614
|
htmlFor,
|
|
3586
3615
|
errorMessage,
|
|
3587
|
-
disabled = false
|
|
3616
|
+
disabled = false,
|
|
3617
|
+
layout = "horizontal",
|
|
3618
|
+
labelPosition = "right"
|
|
3588
3619
|
}) {
|
|
3589
3620
|
const isChecked = checked ?? value ?? false;
|
|
3621
|
+
const labelFirst = labelPosition === "left";
|
|
3622
|
+
const box = /* @__PURE__ */ jsxRuntime.jsx(
|
|
3623
|
+
CheckboxPrimitive__namespace.Root,
|
|
3624
|
+
{
|
|
3625
|
+
id: htmlFor,
|
|
3626
|
+
name,
|
|
3627
|
+
checked: isChecked,
|
|
3628
|
+
disabled,
|
|
3629
|
+
onCheckedChange: (c) => onChange?.({ target: { checked: !!c, id: htmlFor, name } }),
|
|
3630
|
+
className: [
|
|
3631
|
+
"relative flex h-[18px] w-[18px] flex-shrink-0 items-center justify-center",
|
|
3632
|
+
"rounded-sm border transition-colors duration-150",
|
|
3633
|
+
"border-border-strong bg-surface",
|
|
3634
|
+
"data-[state=checked]:bg-accent data-[state=checked]:border-accent",
|
|
3635
|
+
// Focus halo matches the field tokens for a consistent look.
|
|
3636
|
+
"focus:outline-none focus-visible:ring-[3px] focus-visible:ring-focus-ring",
|
|
3637
|
+
"disabled:cursor-not-allowed"
|
|
3638
|
+
].join(" "),
|
|
3639
|
+
"aria-label": typeof label === "string" ? label : void 0,
|
|
3640
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(CheckboxPrimitive__namespace.Indicator, { className: "flex items-center justify-center data-[state=checked]:animate-check-pop", children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "11", height: "9", viewBox: "0 0 11 9", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M1 4.5L4 7.5L10 1", stroke: "white", strokeWidth: "1.8", strokeLinecap: "round", strokeLinejoin: "round" }) }) })
|
|
3641
|
+
}
|
|
3642
|
+
);
|
|
3643
|
+
const labelEl = label && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-foreground-secondary select-none leading-snug", children: label });
|
|
3590
3644
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
3591
|
-
/* @__PURE__ */ jsxRuntime.
|
|
3645
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3592
3646
|
"label",
|
|
3593
3647
|
{
|
|
3594
3648
|
htmlFor,
|
|
3595
3649
|
className: [
|
|
3596
|
-
"inline-flex
|
|
3650
|
+
"inline-flex",
|
|
3651
|
+
layout === "vertical" ? "flex-col items-start gap-1.5" : "flex-row items-center gap-2.5",
|
|
3597
3652
|
disabled ? "cursor-not-allowed opacity-50" : "cursor-pointer"
|
|
3598
3653
|
].join(" "),
|
|
3599
|
-
children: [
|
|
3600
|
-
|
|
3601
|
-
|
|
3602
|
-
|
|
3603
|
-
|
|
3604
|
-
|
|
3605
|
-
|
|
3606
|
-
disabled,
|
|
3607
|
-
onCheckedChange: (c) => onChange?.({ target: { checked: !!c, id: htmlFor, name } }),
|
|
3608
|
-
className: [
|
|
3609
|
-
// Box
|
|
3610
|
-
"relative flex h-[18px] w-[18px] flex-shrink-0 items-center justify-center",
|
|
3611
|
-
"rounded-sm border transition-colors duration-150",
|
|
3612
|
-
// Unchecked
|
|
3613
|
-
"border-border-strong bg-surface",
|
|
3614
|
-
// Checked
|
|
3615
|
-
"data-[state=checked]:bg-accent data-[state=checked]:border-accent",
|
|
3616
|
-
// Focus
|
|
3617
|
-
"focus:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-1",
|
|
3618
|
-
// Disabled
|
|
3619
|
-
"disabled:cursor-not-allowed"
|
|
3620
|
-
].join(" "),
|
|
3621
|
-
"aria-label": typeof label === "string" ? label : void 0,
|
|
3622
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3623
|
-
CheckboxPrimitive__namespace.Indicator,
|
|
3624
|
-
{
|
|
3625
|
-
className: "flex items-center justify-center data-[state=checked]:animate-check-pop",
|
|
3626
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3627
|
-
"svg",
|
|
3628
|
-
{
|
|
3629
|
-
width: "11",
|
|
3630
|
-
height: "9",
|
|
3631
|
-
viewBox: "0 0 11 9",
|
|
3632
|
-
fill: "none",
|
|
3633
|
-
"aria-hidden": "true",
|
|
3634
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3635
|
-
"path",
|
|
3636
|
-
{
|
|
3637
|
-
d: "M1 4.5L4 7.5L10 1",
|
|
3638
|
-
stroke: "white",
|
|
3639
|
-
strokeWidth: "1.8",
|
|
3640
|
-
strokeLinecap: "round",
|
|
3641
|
-
strokeLinejoin: "round"
|
|
3642
|
-
}
|
|
3643
|
-
)
|
|
3644
|
-
}
|
|
3645
|
-
)
|
|
3646
|
-
}
|
|
3647
|
-
)
|
|
3648
|
-
}
|
|
3649
|
-
),
|
|
3650
|
-
label && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-foreground-secondary select-none leading-snug", children: label })
|
|
3651
|
-
]
|
|
3654
|
+
children: labelFirst ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
3655
|
+
labelEl,
|
|
3656
|
+
box
|
|
3657
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
3658
|
+
box,
|
|
3659
|
+
labelEl
|
|
3660
|
+
] })
|
|
3652
3661
|
}
|
|
3653
3662
|
),
|
|
3654
|
-
errorMessage && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-status-error
|
|
3663
|
+
errorMessage && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-status-error mt-0.5", children: errorMessage })
|
|
3655
3664
|
] });
|
|
3656
3665
|
}
|
|
3657
3666
|
var DOT_SIZE = {
|
|
@@ -3757,12 +3766,12 @@ function Switch({
|
|
|
3757
3766
|
id,
|
|
3758
3767
|
checked,
|
|
3759
3768
|
onCheckedChange: (c) => onChange?.({ target: { checked: c } }),
|
|
3760
|
-
className: "relative inline-flex h-6 w-
|
|
3769
|
+
className: "relative inline-flex h-6 w-11 flex-shrink-0 items-center rounded-full bg-foreground-secondary data-[state=checked]:bg-accent transition-colors focus:outline-none focus-visible:ring-[3px] focus-visible:ring-focus-ring",
|
|
3761
3770
|
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3762
3771
|
SwitchPrimitive__namespace.Thumb,
|
|
3763
3772
|
{
|
|
3764
|
-
className: "pointer-events-none
|
|
3765
|
-
children: checkedIcon && uncheckedIcon ? checked ? checkedIcon : uncheckedIcon : null
|
|
3773
|
+
className: "pointer-events-none flex h-5 w-5 items-center justify-center rounded-full bg-background text-foreground shadow transition-transform duration-200 data-[state=checked]:translate-x-[22px] data-[state=unchecked]:translate-x-[2px]",
|
|
3774
|
+
children: checkedIcon && uncheckedIcon ? checked ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex items-center justify-center w-3 h-3", children: checkedIcon }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex items-center justify-center w-3 h-3", children: uncheckedIcon }) : null
|
|
3766
3775
|
}
|
|
3767
3776
|
)
|
|
3768
3777
|
}
|
|
@@ -3783,8 +3792,13 @@ function AutoComplete({
|
|
|
3783
3792
|
emptyText = "No results found",
|
|
3784
3793
|
loadingText = "Searching\u2026",
|
|
3785
3794
|
size = "md",
|
|
3786
|
-
icon
|
|
3795
|
+
icon,
|
|
3796
|
+
errorMessage,
|
|
3797
|
+
required,
|
|
3798
|
+
htmlFor
|
|
3787
3799
|
}) {
|
|
3800
|
+
const errorId = React8.useId();
|
|
3801
|
+
const hasError = errorMessage != null;
|
|
3788
3802
|
const [term, setTerm] = React8.useState("");
|
|
3789
3803
|
const [open, setOpen] = React8.useState(false);
|
|
3790
3804
|
const [asyncItems, setAsyncItems] = React8.useState([]);
|
|
@@ -3831,78 +3845,82 @@ function AutoComplete({
|
|
|
3831
3845
|
onItemClick?.(item.value);
|
|
3832
3846
|
setOpen(false);
|
|
3833
3847
|
};
|
|
3834
|
-
return /* @__PURE__ */ jsxRuntime.
|
|
3835
|
-
|
|
3848
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
3849
|
+
Field,
|
|
3836
3850
|
{
|
|
3837
|
-
|
|
3838
|
-
|
|
3839
|
-
|
|
3840
|
-
|
|
3841
|
-
|
|
3842
|
-
|
|
3843
|
-
|
|
3844
|
-
|
|
3845
|
-
|
|
3846
|
-
|
|
3847
|
-
value: term,
|
|
3848
|
-
onChange: (e) => {
|
|
3849
|
-
setTerm(e.target.value);
|
|
3850
|
-
setOpen(true);
|
|
3851
|
-
},
|
|
3852
|
-
onFocus: () => setOpen(true),
|
|
3853
|
-
type: "text",
|
|
3854
|
-
name,
|
|
3855
|
-
className: "min-w-0 flex-1 bg-transparent outline-none disabled:cursor-not-allowed placeholder:text-foreground-muted",
|
|
3856
|
-
style: inputStyle,
|
|
3857
|
-
placeholder: placeholder ?? "",
|
|
3858
|
-
autoComplete: "off",
|
|
3859
|
-
"aria-haspopup": "listbox",
|
|
3860
|
-
"aria-expanded": open,
|
|
3861
|
-
"aria-autocomplete": "list",
|
|
3862
|
-
"aria-busy": loading || void 0
|
|
3863
|
-
}
|
|
3864
|
-
),
|
|
3865
|
-
loading ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-2 w-4 h-4 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("span", { className: "ml-2 flex-shrink-0 text-foreground-muted", children: icon ?? /* @__PURE__ */ jsxRuntime.jsx("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "currentColor", className: "w-4 h-4", "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" }) }) })
|
|
3866
|
-
] }) }),
|
|
3867
|
-
/* @__PURE__ */ jsxRuntime.jsx(Popover__namespace.Portal, { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3868
|
-
Popover__namespace.Content,
|
|
3851
|
+
label,
|
|
3852
|
+
htmlFor,
|
|
3853
|
+
errorId,
|
|
3854
|
+
errorMessage,
|
|
3855
|
+
layout,
|
|
3856
|
+
required,
|
|
3857
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(Popover__namespace.Root, { open: open && !disabled, onOpenChange: (o) => !disabled && setOpen(o), children: [
|
|
3858
|
+
/* @__PURE__ */ jsxRuntime.jsx(Popover__namespace.Anchor, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `flex items-center ${fieldShell({ size, hasError, disabled, focusWithin: true })}`, style, children: [
|
|
3859
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3860
|
+
"input",
|
|
3869
3861
|
{
|
|
3870
|
-
|
|
3871
|
-
|
|
3872
|
-
|
|
3873
|
-
|
|
3874
|
-
|
|
3875
|
-
|
|
3876
|
-
|
|
3877
|
-
|
|
3878
|
-
|
|
3879
|
-
|
|
3880
|
-
|
|
3881
|
-
|
|
3882
|
-
|
|
3883
|
-
|
|
3884
|
-
|
|
3885
|
-
|
|
3886
|
-
|
|
3887
|
-
|
|
3888
|
-
|
|
3889
|
-
|
|
3890
|
-
children: [
|
|
3891
|
-
item.icon,
|
|
3892
|
-
/* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
3893
|
-
item.label,
|
|
3894
|
-
" (",
|
|
3895
|
-
item.value,
|
|
3896
|
-
")"
|
|
3897
|
-
] })
|
|
3898
|
-
]
|
|
3899
|
-
},
|
|
3900
|
-
item.key
|
|
3901
|
-
)) })
|
|
3862
|
+
id: htmlFor,
|
|
3863
|
+
disabled,
|
|
3864
|
+
value: term,
|
|
3865
|
+
onChange: (e) => {
|
|
3866
|
+
setTerm(e.target.value);
|
|
3867
|
+
setOpen(true);
|
|
3868
|
+
},
|
|
3869
|
+
onFocus: () => setOpen(true),
|
|
3870
|
+
type: "text",
|
|
3871
|
+
name,
|
|
3872
|
+
className: "min-w-0 flex-1 bg-transparent outline-none disabled:cursor-not-allowed placeholder:text-foreground-muted",
|
|
3873
|
+
style: inputStyle,
|
|
3874
|
+
placeholder: placeholder ?? "",
|
|
3875
|
+
autoComplete: "off",
|
|
3876
|
+
"aria-haspopup": "listbox",
|
|
3877
|
+
"aria-expanded": open,
|
|
3878
|
+
"aria-autocomplete": "list",
|
|
3879
|
+
"aria-busy": loading || void 0,
|
|
3880
|
+
"aria-invalid": hasError || void 0,
|
|
3881
|
+
"aria-describedby": hasError ? errorId : void 0
|
|
3902
3882
|
}
|
|
3903
|
-
)
|
|
3904
|
-
|
|
3905
|
-
|
|
3883
|
+
),
|
|
3884
|
+
loading ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-2 w-4 h-4 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("span", { className: "ml-2 flex-shrink-0 text-foreground-muted", children: icon ?? /* @__PURE__ */ jsxRuntime.jsx("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "currentColor", className: "w-4 h-4", "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" }) }) })
|
|
3885
|
+
] }) }),
|
|
3886
|
+
/* @__PURE__ */ jsxRuntime.jsx(Popover__namespace.Portal, { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3887
|
+
Popover__namespace.Content,
|
|
3888
|
+
{
|
|
3889
|
+
align: "start",
|
|
3890
|
+
sideOffset: 4,
|
|
3891
|
+
onOpenAutoFocus: (e) => e.preventDefault(),
|
|
3892
|
+
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",
|
|
3893
|
+
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: [
|
|
3894
|
+
/* @__PURE__ */ jsxRuntime.jsx(LoadingSpinner, { inline: true, size: "xs" }),
|
|
3895
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: loadingText })
|
|
3896
|
+
] }) : 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(
|
|
3897
|
+
"div",
|
|
3898
|
+
{
|
|
3899
|
+
role: "option",
|
|
3900
|
+
tabIndex: 0,
|
|
3901
|
+
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",
|
|
3902
|
+
onClick: () => handleSelect(item),
|
|
3903
|
+
onKeyDown: (e) => {
|
|
3904
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
3905
|
+
e.preventDefault();
|
|
3906
|
+
handleSelect(item);
|
|
3907
|
+
}
|
|
3908
|
+
},
|
|
3909
|
+
children: [
|
|
3910
|
+
item.icon,
|
|
3911
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
3912
|
+
item.label,
|
|
3913
|
+
" (",
|
|
3914
|
+
item.value,
|
|
3915
|
+
")"
|
|
3916
|
+
] })
|
|
3917
|
+
]
|
|
3918
|
+
},
|
|
3919
|
+
item.key
|
|
3920
|
+
)) })
|
|
3921
|
+
}
|
|
3922
|
+
) })
|
|
3923
|
+
] })
|
|
3906
3924
|
}
|
|
3907
3925
|
);
|
|
3908
3926
|
}
|
|
@@ -4982,27 +5000,13 @@ function TagsInput({
|
|
|
4982
5000
|
className: `flex flex-wrap items-center gap-1.5 min-h-[36px] ${fieldShell({ size, hasError, disabled, focusWithin: true, sized: false })} px-2 py-1.5`,
|
|
4983
5001
|
onClick: () => inputRef.current?.focus(),
|
|
4984
5002
|
children: [
|
|
4985
|
-
tags.map((tag, idx) => /* @__PURE__ */ jsxRuntime.
|
|
4986
|
-
|
|
5003
|
+
tags.map((tag, idx) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
5004
|
+
Tag,
|
|
4987
5005
|
{
|
|
4988
|
-
|
|
4989
|
-
|
|
4990
|
-
|
|
4991
|
-
|
|
4992
|
-
"button",
|
|
4993
|
-
{
|
|
4994
|
-
type: "button",
|
|
4995
|
-
disabled,
|
|
4996
|
-
onClick: (e) => {
|
|
4997
|
-
e.stopPropagation();
|
|
4998
|
-
removeTag(idx);
|
|
4999
|
-
},
|
|
5000
|
-
"aria-label": `Remove ${tag}`,
|
|
5001
|
-
className: "inline-flex items-center justify-center w-4 h-4 rounded text-foreground-muted hover:text-status-error hover:bg-surface transition-colors focus:outline-none focus-visible:ring-1 focus-visible:ring-accent",
|
|
5002
|
-
children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "10", height: "10", viewBox: "0 0 20 20", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M15 5L5 15M5 5l10 10", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }) })
|
|
5003
|
-
}
|
|
5004
|
-
)
|
|
5005
|
-
]
|
|
5006
|
+
disabled,
|
|
5007
|
+
removeLabel: `Remove ${tag}`,
|
|
5008
|
+
onRemove: () => removeTag(idx),
|
|
5009
|
+
children: tag
|
|
5006
5010
|
},
|
|
5007
5011
|
`${tag}-${idx}`
|
|
5008
5012
|
)),
|
|
@@ -5036,6 +5040,646 @@ function TagsInput({
|
|
|
5036
5040
|
}
|
|
5037
5041
|
);
|
|
5038
5042
|
}
|
|
5043
|
+
var BOX_SIZE = {
|
|
5044
|
+
sm: "h-9 w-8 text-sm",
|
|
5045
|
+
md: "h-11 w-10 text-base",
|
|
5046
|
+
lg: "h-14 w-12 text-lg"
|
|
5047
|
+
};
|
|
5048
|
+
function OtpInput({
|
|
5049
|
+
length = 6,
|
|
5050
|
+
value = "",
|
|
5051
|
+
onChange,
|
|
5052
|
+
onComplete,
|
|
5053
|
+
label,
|
|
5054
|
+
htmlFor,
|
|
5055
|
+
name,
|
|
5056
|
+
mode = "numeric",
|
|
5057
|
+
masked = false,
|
|
5058
|
+
size = "md",
|
|
5059
|
+
disabled,
|
|
5060
|
+
errorMessage,
|
|
5061
|
+
required,
|
|
5062
|
+
groupAfter
|
|
5063
|
+
}) {
|
|
5064
|
+
const errorId = React8.useId();
|
|
5065
|
+
const hasError = errorMessage != null;
|
|
5066
|
+
const refs = React8.useRef([]);
|
|
5067
|
+
const chars = Array.from({ length }, (_, i) => value[i] ?? "");
|
|
5068
|
+
const pattern = mode === "numeric" ? /[0-9]/ : /[a-zA-Z0-9]/;
|
|
5069
|
+
const emit = (next) => {
|
|
5070
|
+
onChange?.(next);
|
|
5071
|
+
if (next.length === length && !next.includes(" ") && [...next].every(Boolean)) {
|
|
5072
|
+
onComplete?.(next);
|
|
5073
|
+
}
|
|
5074
|
+
};
|
|
5075
|
+
const setCharAt = (idx, char) => {
|
|
5076
|
+
const arr = chars.slice();
|
|
5077
|
+
arr[idx] = char;
|
|
5078
|
+
emit(arr.join(""));
|
|
5079
|
+
};
|
|
5080
|
+
const focusBox = (idx) => {
|
|
5081
|
+
const el = refs.current[Math.max(0, Math.min(length - 1, idx))];
|
|
5082
|
+
el?.focus();
|
|
5083
|
+
el?.select();
|
|
5084
|
+
};
|
|
5085
|
+
const onBoxChange = (idx, raw) => {
|
|
5086
|
+
const char = raw.slice(-1);
|
|
5087
|
+
if (char && !pattern.test(char)) return;
|
|
5088
|
+
setCharAt(idx, char);
|
|
5089
|
+
if (char) focusBox(idx + 1);
|
|
5090
|
+
};
|
|
5091
|
+
const onKeyDown = (idx, e) => {
|
|
5092
|
+
if (e.key === "Backspace") {
|
|
5093
|
+
if (chars[idx]) {
|
|
5094
|
+
setCharAt(idx, "");
|
|
5095
|
+
} else if (idx > 0) {
|
|
5096
|
+
setCharAt(idx - 1, "");
|
|
5097
|
+
focusBox(idx - 1);
|
|
5098
|
+
}
|
|
5099
|
+
} else if (e.key === "ArrowLeft") {
|
|
5100
|
+
e.preventDefault();
|
|
5101
|
+
focusBox(idx - 1);
|
|
5102
|
+
} else if (e.key === "ArrowRight") {
|
|
5103
|
+
e.preventDefault();
|
|
5104
|
+
focusBox(idx + 1);
|
|
5105
|
+
}
|
|
5106
|
+
};
|
|
5107
|
+
const onPaste = (e) => {
|
|
5108
|
+
e.preventDefault();
|
|
5109
|
+
const text = e.clipboardData.getData("text").trim();
|
|
5110
|
+
const valid = [...text].filter((c) => pattern.test(c)).slice(0, length);
|
|
5111
|
+
if (valid.length === 0) return;
|
|
5112
|
+
emit(valid.join(""));
|
|
5113
|
+
focusBox(valid.length);
|
|
5114
|
+
};
|
|
5115
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Field, { label, htmlFor, errorId, errorMessage, required, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-2", role: "group", "aria-label": typeof label === "string" ? label : "One-time code", children: chars.map((char, idx) => /* @__PURE__ */ jsxRuntime.jsxs(React8__default.default.Fragment, { children: [
|
|
5116
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5117
|
+
"input",
|
|
5118
|
+
{
|
|
5119
|
+
ref: (el) => {
|
|
5120
|
+
refs.current[idx] = el;
|
|
5121
|
+
},
|
|
5122
|
+
id: idx === 0 ? htmlFor : void 0,
|
|
5123
|
+
name: idx === 0 ? name : void 0,
|
|
5124
|
+
value: char,
|
|
5125
|
+
disabled,
|
|
5126
|
+
inputMode: mode === "numeric" ? "numeric" : "text",
|
|
5127
|
+
autoComplete: idx === 0 ? "one-time-code" : "off",
|
|
5128
|
+
type: masked && char ? "password" : "text",
|
|
5129
|
+
maxLength: 1,
|
|
5130
|
+
"aria-label": `Digit ${idx + 1}`,
|
|
5131
|
+
"aria-invalid": hasError || void 0,
|
|
5132
|
+
"aria-describedby": hasError ? errorId : void 0,
|
|
5133
|
+
onChange: (e) => onBoxChange(idx, e.target.value),
|
|
5134
|
+
onKeyDown: (e) => onKeyDown(idx, e),
|
|
5135
|
+
onPaste,
|
|
5136
|
+
onFocus: (e) => e.target.select(),
|
|
5137
|
+
className: [
|
|
5138
|
+
BOX_SIZE[size],
|
|
5139
|
+
"text-center font-medium rounded-lg border bg-surface text-foreground",
|
|
5140
|
+
"transition-[border-color,box-shadow] duration-150",
|
|
5141
|
+
hasError ? "border-status-error" : "border-border",
|
|
5142
|
+
"hover:border-border-strong",
|
|
5143
|
+
"focus:outline-none focus:border-accent focus:ring-[3px] focus:ring-focus-ring",
|
|
5144
|
+
"disabled:bg-surface-raised disabled:text-foreground-muted disabled:cursor-not-allowed"
|
|
5145
|
+
].join(" ")
|
|
5146
|
+
}
|
|
5147
|
+
),
|
|
5148
|
+
groupAfter && (idx + 1) % groupAfter === 0 && idx < length - 1 && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "w-2 text-center text-foreground-muted", "aria-hidden": "true", children: "\xB7" })
|
|
5149
|
+
] }, idx)) }) });
|
|
5150
|
+
}
|
|
5151
|
+
var ICON_SIZE = { sm: "w-4 h-4", md: "w-5 h-5", lg: "w-7 h-7" };
|
|
5152
|
+
var Star = (filled) => /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: filled ? "currentColor" : "none", stroke: "currentColor", strokeWidth: filled ? 0 : 1.5, className: "w-full h-full", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M11.48 3.5a.56.56 0 011.04 0l2.13 4.77 5.18.5a.56.56 0 01.32.97l-3.9 3.46 1.15 5.1a.56.56 0 01-.83.6L12 16.8l-4.57 2.6a.56.56 0 01-.83-.6l1.15-5.1-3.9-3.46a.56.56 0 01.32-.97l5.18-.5L11.48 3.5z" }) });
|
|
5153
|
+
function Rating({
|
|
5154
|
+
value,
|
|
5155
|
+
defaultValue = 0,
|
|
5156
|
+
onChange,
|
|
5157
|
+
count = 5,
|
|
5158
|
+
allowHalf = false,
|
|
5159
|
+
readOnly = false,
|
|
5160
|
+
clearable = true,
|
|
5161
|
+
label,
|
|
5162
|
+
size = "md",
|
|
5163
|
+
disabled,
|
|
5164
|
+
icon = Star,
|
|
5165
|
+
errorMessage,
|
|
5166
|
+
name
|
|
5167
|
+
}) {
|
|
5168
|
+
const errorId = React8.useId();
|
|
5169
|
+
const [internal, setInternal] = React8.useState(defaultValue);
|
|
5170
|
+
const [hover, setHover] = React8.useState(null);
|
|
5171
|
+
const current = value ?? internal;
|
|
5172
|
+
const display2 = hover ?? current;
|
|
5173
|
+
const interactive = !readOnly && !disabled;
|
|
5174
|
+
const commit = (next) => {
|
|
5175
|
+
const v = clearable && next === current ? 0 : next;
|
|
5176
|
+
setInternal(v);
|
|
5177
|
+
onChange?.(v);
|
|
5178
|
+
};
|
|
5179
|
+
const onKeyDown = (e) => {
|
|
5180
|
+
if (!interactive) return;
|
|
5181
|
+
const step = allowHalf ? 0.5 : 1;
|
|
5182
|
+
if (e.key === "ArrowRight" || e.key === "ArrowUp") {
|
|
5183
|
+
e.preventDefault();
|
|
5184
|
+
commit(Math.min(count, current + step));
|
|
5185
|
+
} else if (e.key === "ArrowLeft" || e.key === "ArrowDown") {
|
|
5186
|
+
e.preventDefault();
|
|
5187
|
+
commit(Math.max(0, current - step));
|
|
5188
|
+
} else if (e.key === "Home") {
|
|
5189
|
+
e.preventDefault();
|
|
5190
|
+
commit(0);
|
|
5191
|
+
} else if (e.key === "End") {
|
|
5192
|
+
e.preventDefault();
|
|
5193
|
+
commit(count);
|
|
5194
|
+
}
|
|
5195
|
+
};
|
|
5196
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Field, { label, errorId, errorMessage, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
5197
|
+
"div",
|
|
5198
|
+
{
|
|
5199
|
+
role: interactive ? "slider" : "img",
|
|
5200
|
+
"aria-label": typeof label === "string" ? label : "Rating",
|
|
5201
|
+
"aria-valuenow": interactive ? current : void 0,
|
|
5202
|
+
"aria-valuemin": interactive ? 0 : void 0,
|
|
5203
|
+
"aria-valuemax": interactive ? count : void 0,
|
|
5204
|
+
"aria-valuetext": `${current} of ${count}`,
|
|
5205
|
+
tabIndex: interactive ? 0 : -1,
|
|
5206
|
+
onKeyDown,
|
|
5207
|
+
onMouseLeave: () => setHover(null),
|
|
5208
|
+
className: "inline-flex items-center gap-1 text-accent focus:outline-none focus-visible:ring-[3px] focus-visible:ring-focus-ring rounded-md w-max",
|
|
5209
|
+
children: [
|
|
5210
|
+
name && /* @__PURE__ */ jsxRuntime.jsx("input", { type: "hidden", name, value: current }),
|
|
5211
|
+
Array.from({ length: count }, (_, i) => {
|
|
5212
|
+
const starValue = i + 1;
|
|
5213
|
+
const fillFraction = Math.max(0, Math.min(1, display2 - i));
|
|
5214
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
5215
|
+
"span",
|
|
5216
|
+
{
|
|
5217
|
+
className: `relative ${ICON_SIZE[size]} ${interactive ? "cursor-pointer" : ""} ${disabled ? "opacity-50" : ""}`,
|
|
5218
|
+
onMouseMove: (e) => {
|
|
5219
|
+
if (!interactive) return;
|
|
5220
|
+
if (allowHalf) {
|
|
5221
|
+
const rect = e.currentTarget.getBoundingClientRect();
|
|
5222
|
+
const half = e.clientX - rect.left < rect.width / 2;
|
|
5223
|
+
setHover(i + (half ? 0.5 : 1));
|
|
5224
|
+
} else {
|
|
5225
|
+
setHover(starValue);
|
|
5226
|
+
}
|
|
5227
|
+
},
|
|
5228
|
+
onClick: (e) => {
|
|
5229
|
+
if (!interactive) return;
|
|
5230
|
+
if (allowHalf) {
|
|
5231
|
+
const rect = e.currentTarget.getBoundingClientRect();
|
|
5232
|
+
const half = e.clientX - rect.left < rect.width / 2;
|
|
5233
|
+
commit(i + (half ? 0.5 : 1));
|
|
5234
|
+
} else {
|
|
5235
|
+
commit(starValue);
|
|
5236
|
+
}
|
|
5237
|
+
},
|
|
5238
|
+
children: [
|
|
5239
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute inset-0 text-foreground-muted", children: icon(false) }),
|
|
5240
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5241
|
+
"span",
|
|
5242
|
+
{
|
|
5243
|
+
className: "absolute inset-y-0 left-0 overflow-hidden",
|
|
5244
|
+
style: { width: `${fillFraction * 100}%` },
|
|
5245
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: `block absolute inset-y-0 left-0 ${ICON_SIZE[size]} max-w-none`, children: icon(true) })
|
|
5246
|
+
}
|
|
5247
|
+
)
|
|
5248
|
+
]
|
|
5249
|
+
},
|
|
5250
|
+
i
|
|
5251
|
+
);
|
|
5252
|
+
})
|
|
5253
|
+
]
|
|
5254
|
+
}
|
|
5255
|
+
) });
|
|
5256
|
+
}
|
|
5257
|
+
var pad = (n) => n.toString().padStart(2, "0");
|
|
5258
|
+
function parse(value) {
|
|
5259
|
+
if (!value) return null;
|
|
5260
|
+
const [h, m, s] = value.split(":").map(Number);
|
|
5261
|
+
if (Number.isNaN(h) || Number.isNaN(m)) return null;
|
|
5262
|
+
return { h, m, s: Number.isNaN(s) ? 0 : s };
|
|
5263
|
+
}
|
|
5264
|
+
function display(value, use12, withSeconds) {
|
|
5265
|
+
const p = parse(value);
|
|
5266
|
+
if (!p) return "";
|
|
5267
|
+
if (use12) {
|
|
5268
|
+
const period = p.h >= 12 ? "PM" : "AM";
|
|
5269
|
+
const h12 = p.h % 12 === 0 ? 12 : p.h % 12;
|
|
5270
|
+
return `${h12}:${pad(p.m)}${withSeconds ? `:${pad(p.s)}` : ""} ${period}`;
|
|
5271
|
+
}
|
|
5272
|
+
return `${pad(p.h)}:${pad(p.m)}${withSeconds ? `:${pad(p.s)}` : ""}`;
|
|
5273
|
+
}
|
|
5274
|
+
function TimePicker({
|
|
5275
|
+
value,
|
|
5276
|
+
onChange,
|
|
5277
|
+
label,
|
|
5278
|
+
htmlFor,
|
|
5279
|
+
name,
|
|
5280
|
+
placeholder = "Select a time\u2026",
|
|
5281
|
+
layout = "vertical",
|
|
5282
|
+
size = "md",
|
|
5283
|
+
use12Hours = false,
|
|
5284
|
+
withSeconds = false,
|
|
5285
|
+
minuteStep = 1,
|
|
5286
|
+
disabled,
|
|
5287
|
+
errorMessage,
|
|
5288
|
+
required,
|
|
5289
|
+
style
|
|
5290
|
+
}) {
|
|
5291
|
+
const errorId = React8.useId();
|
|
5292
|
+
const hasError = errorMessage != null;
|
|
5293
|
+
const [open, setOpen] = React8.useState(false);
|
|
5294
|
+
const parsed = parse(value) ?? { h: 0, m: 0, s: 0 };
|
|
5295
|
+
const update = (next) => {
|
|
5296
|
+
const merged = { ...parsed, ...next };
|
|
5297
|
+
onChange?.(`${pad(merged.h)}:${pad(merged.m)}${withSeconds ? `:${pad(merged.s)}` : ""}`);
|
|
5298
|
+
};
|
|
5299
|
+
const hours = use12Hours ? Array.from({ length: 12 }, (_, i) => i + 1) : Array.from({ length: 24 }, (_, i) => i);
|
|
5300
|
+
const minutes = Array.from({ length: Math.ceil(60 / minuteStep) }, (_, i) => i * minuteStep);
|
|
5301
|
+
const seconds = Array.from({ length: 60 }, (_, i) => i);
|
|
5302
|
+
const selectedHourCol = use12Hours ? parsed.h % 12 === 0 ? 12 : parsed.h % 12 : parsed.h;
|
|
5303
|
+
const period = parsed.h >= 12 ? "PM" : "AM";
|
|
5304
|
+
const setHour12 = (h12, p) => {
|
|
5305
|
+
const h24 = p === "AM" ? h12 === 12 ? 0 : h12 : h12 === 12 ? 12 : h12 + 12;
|
|
5306
|
+
update({ h: h24 });
|
|
5307
|
+
};
|
|
5308
|
+
const Column = ({ items, selected, onPick, fmt }) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col overflow-y-auto max-h-48 w-14 hidden-scrollbar", role: "listbox", children: items.map((n) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
5309
|
+
"button",
|
|
5310
|
+
{
|
|
5311
|
+
type: "button",
|
|
5312
|
+
role: "option",
|
|
5313
|
+
"aria-selected": selected === n,
|
|
5314
|
+
onClick: () => onPick(n),
|
|
5315
|
+
className: `py-1.5 text-sm rounded-md text-center transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-accent ${selected === n ? "bg-accent text-accent-fg" : "text-foreground hover:bg-surface-raised"}`,
|
|
5316
|
+
children: fmt ? fmt(n) : pad(n)
|
|
5317
|
+
},
|
|
5318
|
+
n
|
|
5319
|
+
)) });
|
|
5320
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(Field, { label, htmlFor, errorId, errorMessage, layout, required, children: [
|
|
5321
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Popover__namespace.Root, { open: open && !disabled, onOpenChange: (o) => !disabled && setOpen(o), children: [
|
|
5322
|
+
/* @__PURE__ */ jsxRuntime.jsx(Popover__namespace.Trigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
5323
|
+
"button",
|
|
5324
|
+
{
|
|
5325
|
+
id: htmlFor,
|
|
5326
|
+
type: "button",
|
|
5327
|
+
disabled,
|
|
5328
|
+
style,
|
|
5329
|
+
"aria-invalid": hasError || void 0,
|
|
5330
|
+
"aria-describedby": hasError ? errorId : void 0,
|
|
5331
|
+
className: `flex items-center justify-between cursor-pointer select-none ${!style?.width ? "min-w-[160px]" : ""} ${fieldShell({ size, hasError, disabled })}`,
|
|
5332
|
+
children: [
|
|
5333
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: `text-sm truncate ${value ? "" : "text-foreground-muted"}`, children: display(value, use12Hours, withSeconds) || placeholder }),
|
|
5334
|
+
/* @__PURE__ */ jsxRuntime.jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 1.75, className: "w-4 h-4 flex-shrink-0 text-foreground-muted ml-2", "aria-hidden": "true", children: [
|
|
5335
|
+
/* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "12", r: "9" }),
|
|
5336
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12 7v5l3 2", strokeLinecap: "round" })
|
|
5337
|
+
] })
|
|
5338
|
+
]
|
|
5339
|
+
}
|
|
5340
|
+
) }),
|
|
5341
|
+
/* @__PURE__ */ jsxRuntime.jsx(Popover__namespace.Portal, { children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
5342
|
+
Popover__namespace.Content,
|
|
5343
|
+
{
|
|
5344
|
+
align: "start",
|
|
5345
|
+
sideOffset: 4,
|
|
5346
|
+
className: "bg-surface text-foreground border border-border rounded-lg shadow-md z-50 p-2 flex gap-1 animate-in fade-in-0 zoom-in-95",
|
|
5347
|
+
children: [
|
|
5348
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5349
|
+
Column,
|
|
5350
|
+
{
|
|
5351
|
+
items: hours,
|
|
5352
|
+
selected: selectedHourCol,
|
|
5353
|
+
onPick: (h) => use12Hours ? setHour12(h, period) : update({ h }),
|
|
5354
|
+
fmt: use12Hours ? (n) => String(n) : pad
|
|
5355
|
+
}
|
|
5356
|
+
),
|
|
5357
|
+
/* @__PURE__ */ jsxRuntime.jsx(Column, { items: minutes, selected: parsed.m, onPick: (m) => update({ m }) }),
|
|
5358
|
+
withSeconds && /* @__PURE__ */ jsxRuntime.jsx(Column, { items: seconds, selected: parsed.s, onPick: (s) => update({ s }) }),
|
|
5359
|
+
use12Hours && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-1 w-12", children: ["AM", "PM"].map((p) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
5360
|
+
"button",
|
|
5361
|
+
{
|
|
5362
|
+
type: "button",
|
|
5363
|
+
onClick: () => setHour12(selectedHourCol, p),
|
|
5364
|
+
className: `py-1.5 text-sm rounded-md transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-accent ${period === p ? "bg-accent text-accent-fg" : "text-foreground hover:bg-surface-raised"}`,
|
|
5365
|
+
children: p
|
|
5366
|
+
},
|
|
5367
|
+
p
|
|
5368
|
+
)) })
|
|
5369
|
+
]
|
|
5370
|
+
}
|
|
5371
|
+
) })
|
|
5372
|
+
] }),
|
|
5373
|
+
name && /* @__PURE__ */ jsxRuntime.jsx("input", { type: "hidden", name, value: value ?? "" })
|
|
5374
|
+
] });
|
|
5375
|
+
}
|
|
5376
|
+
var MONTH_NAMES2 = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
|
|
5377
|
+
var WEEKDAY = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
|
|
5378
|
+
var startOfMonth2 = (d) => new Date(d.getFullYear(), d.getMonth(), 1);
|
|
5379
|
+
var addMonths2 = (d, n) => new Date(d.getFullYear(), d.getMonth() + n, 1);
|
|
5380
|
+
var addDays2 = (d, n) => {
|
|
5381
|
+
const c = new Date(d);
|
|
5382
|
+
c.setDate(c.getDate() + n);
|
|
5383
|
+
return c;
|
|
5384
|
+
};
|
|
5385
|
+
var isSameDay2 = (a, b) => a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate();
|
|
5386
|
+
var startOfDay = (d) => new Date(d.getFullYear(), d.getMonth(), d.getDate());
|
|
5387
|
+
var defaultFmt = (d) => `${d.getFullYear()}-${`${d.getMonth() + 1}`.padStart(2, "0")}-${`${d.getDate()}`.padStart(2, "0")}`;
|
|
5388
|
+
function buildGrid2(viewMonth, weekStartsOn) {
|
|
5389
|
+
const first = startOfMonth2(viewMonth);
|
|
5390
|
+
const offset = (first.getDay() - weekStartsOn + 7) % 7;
|
|
5391
|
+
const gridStart = addDays2(first, -offset);
|
|
5392
|
+
return Array.from({ length: 42 }, (_, i) => {
|
|
5393
|
+
const d = addDays2(gridStart, i);
|
|
5394
|
+
return { date: d, outside: d.getMonth() !== viewMonth.getMonth() };
|
|
5395
|
+
});
|
|
5396
|
+
}
|
|
5397
|
+
function DateRangePicker({
|
|
5398
|
+
value = { start: null, end: null },
|
|
5399
|
+
onChange,
|
|
5400
|
+
label,
|
|
5401
|
+
htmlFor,
|
|
5402
|
+
placeholder = "Select a date range\u2026",
|
|
5403
|
+
layout = "vertical",
|
|
5404
|
+
size = "md",
|
|
5405
|
+
min,
|
|
5406
|
+
max,
|
|
5407
|
+
weekStartsOn = 0,
|
|
5408
|
+
presets,
|
|
5409
|
+
format = defaultFmt,
|
|
5410
|
+
disabled,
|
|
5411
|
+
errorMessage,
|
|
5412
|
+
required,
|
|
5413
|
+
style
|
|
5414
|
+
}) {
|
|
5415
|
+
const errorId = React8.useId();
|
|
5416
|
+
const hasError = errorMessage != null;
|
|
5417
|
+
const [open, setOpen] = React8.useState(false);
|
|
5418
|
+
const [leftMonth, setLeftMonth] = React8.useState(() => startOfMonth2(value.start ?? /* @__PURE__ */ new Date()));
|
|
5419
|
+
const [pendingStart, setPendingStart] = React8.useState(null);
|
|
5420
|
+
const [hoverDate, setHoverDate] = React8.useState(null);
|
|
5421
|
+
const weekdays = React8.useMemo(
|
|
5422
|
+
() => WEEKDAY.slice(weekStartsOn).concat(WEEKDAY.slice(0, weekStartsOn)),
|
|
5423
|
+
[weekStartsOn]
|
|
5424
|
+
);
|
|
5425
|
+
const isDisabled = (d) => min && d < startOfDay(min) || max && d > startOfDay(max);
|
|
5426
|
+
const effective = pendingStart ? { start: pendingStart, end: hoverDate } : value;
|
|
5427
|
+
const inRange = (d) => {
|
|
5428
|
+
const { start, end } = effective;
|
|
5429
|
+
if (!start || !end) return false;
|
|
5430
|
+
const [a, b] = start <= end ? [start, end] : [end, start];
|
|
5431
|
+
return d >= startOfDay(a) && d <= startOfDay(b);
|
|
5432
|
+
};
|
|
5433
|
+
const onDayClick = (d) => {
|
|
5434
|
+
if (isDisabled(d)) return;
|
|
5435
|
+
if (!pendingStart) {
|
|
5436
|
+
setPendingStart(d);
|
|
5437
|
+
setHoverDate(d);
|
|
5438
|
+
onChange?.({ start: d, end: null });
|
|
5439
|
+
} else {
|
|
5440
|
+
const [start, end] = pendingStart <= d ? [pendingStart, d] : [d, pendingStart];
|
|
5441
|
+
onChange?.({ start, end });
|
|
5442
|
+
setPendingStart(null);
|
|
5443
|
+
setHoverDate(null);
|
|
5444
|
+
setOpen(false);
|
|
5445
|
+
}
|
|
5446
|
+
};
|
|
5447
|
+
const triggerText = value.start && value.end ? `${format(value.start)} \u2013 ${format(value.end)}` : value.start ? `${format(value.start)} \u2013 \u2026` : "";
|
|
5448
|
+
const renderMonth = (viewMonth) => {
|
|
5449
|
+
const cells = buildGrid2(viewMonth, weekStartsOn);
|
|
5450
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
5451
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-sm font-semibold text-center mb-2 select-none", children: [
|
|
5452
|
+
MONTH_NAMES2[viewMonth.getMonth()],
|
|
5453
|
+
" ",
|
|
5454
|
+
viewMonth.getFullYear()
|
|
5455
|
+
] }),
|
|
5456
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-7 gap-y-1", children: [
|
|
5457
|
+
weekdays.map((w) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-[11px] font-medium text-foreground-muted uppercase text-center", children: w }, w)),
|
|
5458
|
+
cells.map(({ date, outside }) => {
|
|
5459
|
+
const dis = isDisabled(date);
|
|
5460
|
+
const isStart = effective.start && isSameDay2(date, effective.start);
|
|
5461
|
+
const isEnd = effective.end && isSameDay2(date, effective.end);
|
|
5462
|
+
const within = inRange(date) && !isStart && !isEnd;
|
|
5463
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
5464
|
+
"button",
|
|
5465
|
+
{
|
|
5466
|
+
type: "button",
|
|
5467
|
+
disabled: dis,
|
|
5468
|
+
onMouseEnter: () => pendingStart && setHoverDate(date),
|
|
5469
|
+
onClick: () => onDayClick(date),
|
|
5470
|
+
className: [
|
|
5471
|
+
"h-8 text-xs font-medium transition-colors",
|
|
5472
|
+
"focus:outline-none focus-visible:ring-2 focus-visible:ring-accent",
|
|
5473
|
+
"disabled:opacity-30 disabled:cursor-not-allowed",
|
|
5474
|
+
isStart || isEnd ? "bg-accent text-accent-fg rounded-md" : within ? "bg-surface-raised text-foreground rounded-none" : outside ? "text-foreground-muted hover:bg-surface-raised rounded-md" : "text-foreground hover:bg-surface-raised rounded-md"
|
|
5475
|
+
].join(" "),
|
|
5476
|
+
children: date.getDate()
|
|
5477
|
+
},
|
|
5478
|
+
defaultFmt(date)
|
|
5479
|
+
);
|
|
5480
|
+
})
|
|
5481
|
+
] })
|
|
5482
|
+
] });
|
|
5483
|
+
};
|
|
5484
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Field, { label, htmlFor, errorId, errorMessage, layout, required, children: /* @__PURE__ */ jsxRuntime.jsxs(Popover__namespace.Root, { open: open && !disabled, onOpenChange: (o) => {
|
|
5485
|
+
if (!disabled) {
|
|
5486
|
+
setOpen(o);
|
|
5487
|
+
if (!o) {
|
|
5488
|
+
setPendingStart(null);
|
|
5489
|
+
setHoverDate(null);
|
|
5490
|
+
}
|
|
5491
|
+
}
|
|
5492
|
+
}, children: [
|
|
5493
|
+
/* @__PURE__ */ jsxRuntime.jsx(Popover__namespace.Trigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
5494
|
+
"button",
|
|
5495
|
+
{
|
|
5496
|
+
id: htmlFor,
|
|
5497
|
+
type: "button",
|
|
5498
|
+
disabled,
|
|
5499
|
+
style,
|
|
5500
|
+
"aria-invalid": hasError || void 0,
|
|
5501
|
+
"aria-describedby": hasError ? errorId : void 0,
|
|
5502
|
+
className: `flex items-center justify-between cursor-pointer select-none ${!style?.width ? "min-w-[240px]" : ""} ${fieldShell({ size, hasError, disabled })}`,
|
|
5503
|
+
children: [
|
|
5504
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: `text-sm truncate ${triggerText ? "" : "text-foreground-muted"}`, children: triggerText || placeholder }),
|
|
5505
|
+
/* @__PURE__ */ jsxRuntime.jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 1.75, className: "w-4 h-4 flex-shrink-0 text-foreground-muted ml-2", "aria-hidden": "true", children: [
|
|
5506
|
+
/* @__PURE__ */ jsxRuntime.jsx("rect", { x: "3", y: "5", width: "18", height: "16", rx: "2" }),
|
|
5507
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M3 9h18M8 3v4M16 3v4", strokeLinecap: "round" })
|
|
5508
|
+
] })
|
|
5509
|
+
]
|
|
5510
|
+
}
|
|
5511
|
+
) }),
|
|
5512
|
+
/* @__PURE__ */ jsxRuntime.jsx(Popover__namespace.Portal, { children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
5513
|
+
Popover__namespace.Content,
|
|
5514
|
+
{
|
|
5515
|
+
align: "start",
|
|
5516
|
+
sideOffset: 4,
|
|
5517
|
+
className: "bg-surface text-foreground border border-border rounded-lg shadow-md z-50 p-3 flex gap-3 animate-in fade-in-0 zoom-in-95",
|
|
5518
|
+
children: [
|
|
5519
|
+
presets && presets.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-1 pr-3 border-r border-border min-w-[120px]", children: presets.map((p) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
5520
|
+
"button",
|
|
5521
|
+
{
|
|
5522
|
+
type: "button",
|
|
5523
|
+
onClick: () => {
|
|
5524
|
+
onChange?.(p.range());
|
|
5525
|
+
setOpen(false);
|
|
5526
|
+
},
|
|
5527
|
+
className: "text-left text-xs px-2 py-1.5 rounded-md text-foreground-secondary hover:bg-surface-raised hover:text-foreground transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-accent",
|
|
5528
|
+
children: p.label
|
|
5529
|
+
},
|
|
5530
|
+
p.label
|
|
5531
|
+
)) }),
|
|
5532
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-4", children: [
|
|
5533
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
|
|
5534
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5535
|
+
"button",
|
|
5536
|
+
{
|
|
5537
|
+
type: "button",
|
|
5538
|
+
onClick: () => setLeftMonth(addMonths2(leftMonth, -1)),
|
|
5539
|
+
"aria-label": "Previous month",
|
|
5540
|
+
className: "absolute -top-1 left-0 w-7 h-7 inline-flex items-center justify-center rounded-md hover:bg-surface-raised focus:outline-none focus-visible:ring-2 focus-visible:ring-accent",
|
|
5541
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, className: "w-4 h-4", children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M15 19l-7-7 7-7" }) })
|
|
5542
|
+
}
|
|
5543
|
+
),
|
|
5544
|
+
renderMonth(leftMonth)
|
|
5545
|
+
] }),
|
|
5546
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
|
|
5547
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5548
|
+
"button",
|
|
5549
|
+
{
|
|
5550
|
+
type: "button",
|
|
5551
|
+
onClick: () => setLeftMonth(addMonths2(leftMonth, 1)),
|
|
5552
|
+
"aria-label": "Next month",
|
|
5553
|
+
className: "absolute -top-1 right-0 w-7 h-7 inline-flex items-center justify-center rounded-md hover:bg-surface-raised focus:outline-none focus-visible:ring-2 focus-visible:ring-accent",
|
|
5554
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, className: "w-4 h-4", children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M9 5l7 7-7 7" }) })
|
|
5555
|
+
}
|
|
5556
|
+
),
|
|
5557
|
+
renderMonth(addMonths2(leftMonth, 1))
|
|
5558
|
+
] })
|
|
5559
|
+
] })
|
|
5560
|
+
]
|
|
5561
|
+
}
|
|
5562
|
+
) })
|
|
5563
|
+
] }) });
|
|
5564
|
+
}
|
|
5565
|
+
var DEFAULT_SWATCHES = [
|
|
5566
|
+
"#0466c8",
|
|
5567
|
+
"#1e8449",
|
|
5568
|
+
"#d68910",
|
|
5569
|
+
"#c0392b",
|
|
5570
|
+
"#8e44ad",
|
|
5571
|
+
"#16a085",
|
|
5572
|
+
"#2c3e50",
|
|
5573
|
+
"#7f8c8d",
|
|
5574
|
+
"#e84393",
|
|
5575
|
+
"#00b894",
|
|
5576
|
+
"#fdcb6e",
|
|
5577
|
+
"#0a1929"
|
|
5578
|
+
];
|
|
5579
|
+
var HEX_RE = /^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/;
|
|
5580
|
+
function ColorPicker({
|
|
5581
|
+
value = "",
|
|
5582
|
+
onChange,
|
|
5583
|
+
label,
|
|
5584
|
+
htmlFor,
|
|
5585
|
+
name,
|
|
5586
|
+
layout = "vertical",
|
|
5587
|
+
size = "md",
|
|
5588
|
+
swatches = DEFAULT_SWATCHES,
|
|
5589
|
+
allowCustom = true,
|
|
5590
|
+
disabled,
|
|
5591
|
+
errorMessage,
|
|
5592
|
+
required,
|
|
5593
|
+
placeholder = "Pick a colour\u2026"
|
|
5594
|
+
}) {
|
|
5595
|
+
const errorId = React8.useId();
|
|
5596
|
+
const hasError = errorMessage != null;
|
|
5597
|
+
const [open, setOpen] = React8.useState(false);
|
|
5598
|
+
const [draft, setDraft] = React8.useState(value);
|
|
5599
|
+
const valid = HEX_RE.test(value);
|
|
5600
|
+
const pick = (hex) => {
|
|
5601
|
+
onChange?.(hex);
|
|
5602
|
+
setDraft(hex);
|
|
5603
|
+
};
|
|
5604
|
+
const commitDraft = (raw) => {
|
|
5605
|
+
const hex = raw.startsWith("#") ? raw : `#${raw}`;
|
|
5606
|
+
setDraft(hex);
|
|
5607
|
+
if (HEX_RE.test(hex)) onChange?.(hex);
|
|
5608
|
+
};
|
|
5609
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(Field, { label, htmlFor, errorId, errorMessage, layout, required, children: [
|
|
5610
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Popover__namespace.Root, { open: open && !disabled, onOpenChange: (o) => !disabled && setOpen(o), children: [
|
|
5611
|
+
/* @__PURE__ */ jsxRuntime.jsx(Popover__namespace.Trigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
5612
|
+
"button",
|
|
5613
|
+
{
|
|
5614
|
+
id: htmlFor,
|
|
5615
|
+
type: "button",
|
|
5616
|
+
disabled,
|
|
5617
|
+
"aria-invalid": hasError || void 0,
|
|
5618
|
+
"aria-describedby": hasError ? errorId : void 0,
|
|
5619
|
+
className: `flex items-center gap-2 cursor-pointer select-none ${fieldShell({ size, hasError, disabled })}`,
|
|
5620
|
+
children: [
|
|
5621
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5622
|
+
"span",
|
|
5623
|
+
{
|
|
5624
|
+
className: "h-4 w-4 flex-shrink-0 rounded border border-border",
|
|
5625
|
+
style: { backgroundColor: valid ? value : "transparent" },
|
|
5626
|
+
"aria-hidden": "true"
|
|
5627
|
+
}
|
|
5628
|
+
),
|
|
5629
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: `flex-1 text-left text-sm truncate ${valid ? "text-foreground" : "text-foreground-muted"}`, children: valid ? value.toLowerCase() : placeholder })
|
|
5630
|
+
]
|
|
5631
|
+
}
|
|
5632
|
+
) }),
|
|
5633
|
+
/* @__PURE__ */ jsxRuntime.jsx(Popover__namespace.Portal, { children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
5634
|
+
Popover__namespace.Content,
|
|
5635
|
+
{
|
|
5636
|
+
align: "start",
|
|
5637
|
+
sideOffset: 4,
|
|
5638
|
+
className: "bg-surface text-foreground border border-border rounded-lg shadow-md z-50 p-3 w-56 animate-in fade-in-0 zoom-in-95",
|
|
5639
|
+
children: [
|
|
5640
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-6 gap-2 mb-3", children: swatches.map((sw) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
5641
|
+
"button",
|
|
5642
|
+
{
|
|
5643
|
+
type: "button",
|
|
5644
|
+
onClick: () => {
|
|
5645
|
+
pick(sw);
|
|
5646
|
+
setOpen(false);
|
|
5647
|
+
},
|
|
5648
|
+
"aria-label": sw,
|
|
5649
|
+
className: `h-7 w-7 rounded-md border transition-transform hover:scale-110 focus:outline-none focus-visible:ring-2 focus-visible:ring-accent ${value.toLowerCase() === sw.toLowerCase() ? "border-accent ring-2 ring-focus-ring" : "border-border"}`,
|
|
5650
|
+
style: { backgroundColor: sw }
|
|
5651
|
+
},
|
|
5652
|
+
sw
|
|
5653
|
+
)) }),
|
|
5654
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
5655
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5656
|
+
"input",
|
|
5657
|
+
{
|
|
5658
|
+
value: draft,
|
|
5659
|
+
onChange: (e) => commitDraft(e.target.value),
|
|
5660
|
+
placeholder: "#0466c8",
|
|
5661
|
+
"aria-label": "Hex colour",
|
|
5662
|
+
className: `flex-1 ${fieldShell({ size: "sm" })}`
|
|
5663
|
+
}
|
|
5664
|
+
),
|
|
5665
|
+
allowCustom && /* @__PURE__ */ jsxRuntime.jsx(
|
|
5666
|
+
"input",
|
|
5667
|
+
{
|
|
5668
|
+
type: "color",
|
|
5669
|
+
value: valid ? value : "#000000",
|
|
5670
|
+
onChange: (e) => pick(e.target.value),
|
|
5671
|
+
"aria-label": "Custom colour",
|
|
5672
|
+
className: "h-7 w-9 rounded-md border border-border bg-surface cursor-pointer p-0.5"
|
|
5673
|
+
}
|
|
5674
|
+
)
|
|
5675
|
+
] })
|
|
5676
|
+
]
|
|
5677
|
+
}
|
|
5678
|
+
) })
|
|
5679
|
+
] }),
|
|
5680
|
+
name && /* @__PURE__ */ jsxRuntime.jsx("input", { type: "hidden", name, value: valid ? value : "" })
|
|
5681
|
+
] });
|
|
5682
|
+
}
|
|
5039
5683
|
|
|
5040
5684
|
Object.defineProperty(exports, "COLORS", {
|
|
5041
5685
|
enumerable: true,
|
|
@@ -5062,7 +5706,9 @@ exports.Catalog = Catalog;
|
|
|
5062
5706
|
exports.CatalogCarousel = CatalogCarousel;
|
|
5063
5707
|
exports.CatalogGrid = CatalogGrid;
|
|
5064
5708
|
exports.Checkbox = Checkbox;
|
|
5709
|
+
exports.ColorPicker = ColorPicker;
|
|
5065
5710
|
exports.ContextMenu = ContextMenu;
|
|
5711
|
+
exports.DateRangePicker = DateRangePicker;
|
|
5066
5712
|
exports.Drawer = Drawer;
|
|
5067
5713
|
exports.Dropdown = Dropdown;
|
|
5068
5714
|
exports.FadingBase = FadingBase;
|
|
@@ -5079,9 +5725,11 @@ exports.Modal = Modal;
|
|
|
5079
5725
|
exports.NotificationProvider = NotificationProvider;
|
|
5080
5726
|
exports.NumberInput = NumberInput;
|
|
5081
5727
|
exports.OpaqueGridCard = OpaqueGridCard;
|
|
5728
|
+
exports.OtpInput = OtpInput;
|
|
5082
5729
|
exports.Password = Password;
|
|
5083
5730
|
exports.Portal = Portal;
|
|
5084
5731
|
exports.RadioGroup = RadioGroup;
|
|
5732
|
+
exports.Rating = Rating;
|
|
5085
5733
|
exports.ScalableContainer = ScalableContainer;
|
|
5086
5734
|
exports.SearchInput = SearchInput_default;
|
|
5087
5735
|
exports.SegmentedControl = SegmentedControl;
|
|
@@ -5100,6 +5748,7 @@ exports.TextArea = TextArea;
|
|
|
5100
5748
|
exports.TextInput = TextInput;
|
|
5101
5749
|
exports.ThemeProvider = ThemeProvider;
|
|
5102
5750
|
exports.ThemeSwitch = ThemeSwitch;
|
|
5751
|
+
exports.TimePicker = TimePicker;
|
|
5103
5752
|
exports.ToggleButton = ToggleButton;
|
|
5104
5753
|
exports.Tooltip = Tooltip;
|
|
5105
5754
|
exports.TooltipProvider = TooltipProvider;
|