@geomak/ui 5.5.3 → 5.7.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 +830 -127
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +629 -188
- package/dist/index.d.ts +629 -188
- package/dist/index.js +819 -129
- package/dist/index.js.map +1 -1
- package/dist/styles.css +34 -0
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -75,7 +75,7 @@ var FleetIcon = ({ color = "#fff", size = 30 }) => /* @__PURE__ */ jsxRuntime.js
|
|
|
75
75
|
/* @__PURE__ */ jsxRuntime.jsx("defs", { children: /* @__PURE__ */ jsxRuntime.jsx("clipPath", { id: "clip0_327_836", children: /* @__PURE__ */ jsxRuntime.jsx("rect", { width: "30", height: "30", fill: color }) }) })
|
|
76
76
|
] });
|
|
77
77
|
var Performance = ({ color = "#fff", size = 30 }) => /* @__PURE__ */ jsxRuntime.jsx("svg", { width: size, height: size, viewBox: "0 0 30 30", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M5.64 25.515H24.36C26.0709 23.3842 27.0024 20.7327 27 18C27 11.385 21.63 6 15 6C8.37 6 3 11.385 3 18C3 20.85 3.99 23.445 5.64 25.515ZM13.5 9C13.5 8.175 14.175 7.5 15 7.5C15.825 7.5 16.5 8.175 16.5 9C16.5 9.84 15.825 10.5 15 10.5C14.175 10.5 13.5 9.84 13.5 9ZM6 12C6 11.175 6.675 10.5 7.5 10.5C8.325 10.5 9 11.175 9 12C9 12.84 8.325 13.5 7.5 13.5C6.675 13.5 6 12.84 6 12ZM12.78 17.1C14.04 15.855 22.545 11.85 22.545 11.85C22.545 11.85 18.555 20.37 17.31 21.615C16.05 22.875 14.04 22.875 12.78 21.615C12.1819 21.016 11.8459 20.204 11.8459 19.3575C11.8459 18.511 12.1819 17.699 12.78 17.1ZM4.5 19.5C4.5 18.675 5.175 18 6 18C6.825 18 7.5 18.675 7.5 19.5C7.5 20.34 6.825 21 6 21C5.175 21 4.5 20.34 4.5 19.5ZM13.5 19.5C13.5 18.675 14.175 18 15 18C15.825 18 16.5 18.675 16.5 19.5C16.5 20.34 15.825 21 15 21C14.175 21 13.5 20.34 13.5 19.5ZM22.5 19.5C22.5 18.675 23.175 18 24 18C24.825 18 25.5 18.675 25.5 19.5C25.5 20.34 24.825 21 24 21C23.175 21 22.5 20.34 22.5 19.5Z", fill: color }) });
|
|
78
|
-
var
|
|
78
|
+
var Map2 = ({ color = "#fff", size = 30 }) => /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: size, height: size, viewBox: "0 0 34 30", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [
|
|
79
79
|
/* @__PURE__ */ jsxRuntime.jsx("g", { clipPath: "url(#clip0_327_830)", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M16.875 0C12.7975 0 9.49219 3.30527 9.49219 7.38281C9.49219 10.6793 14.3174 16.6875 16.166 18.8684C16.5404 19.3102 17.2102 19.3102 17.584 18.8684C19.4326 16.6875 24.2578 10.6793 24.2578 7.38281C24.2578 3.30527 20.9525 0 16.875 0ZM16.875 9.84375C15.5156 9.84375 14.4141 8.74219 14.4141 7.38281C14.4141 6.02344 15.5156 4.92188 16.875 4.92188C18.2344 4.92188 19.3359 6.02344 19.3359 7.38281C19.3359 8.74219 18.2344 9.84375 16.875 9.84375ZM1.17891 12.6533C0.830964 12.7925 0.532694 13.0327 0.322564 13.343C0.112435 13.6533 8.33325e-05 14.0194 0 14.3941L0 29.0613C0 29.7246 0.669727 30.1781 1.28555 29.932L9.375 26.25V12.593C8.85703 11.6566 8.4334 10.7449 8.12988 9.87305L1.17891 12.6533ZM16.875 21.0744C16.0506 21.0744 15.2707 20.7123 14.7357 20.0807C13.5838 18.7213 12.3586 17.1732 11.25 15.5854V26.2494L22.5 29.9994V15.5859C21.3914 17.1732 20.1668 18.7219 19.0143 20.0812C18.4793 20.7123 17.6994 21.0744 16.875 21.0744ZM32.4645 9.44297L24.375 13.125V30L32.5711 26.7217C32.9191 26.5826 33.2174 26.3424 33.4275 26.0321C33.6377 25.7218 33.75 25.3556 33.75 24.9809V10.3137C33.75 9.65039 33.0803 9.19688 32.4645 9.44297Z", fill: color }) }),
|
|
80
80
|
/* @__PURE__ */ jsxRuntime.jsx("defs", { children: /* @__PURE__ */ jsxRuntime.jsx("clipPath", { id: "clip0_327_830", children: /* @__PURE__ */ jsxRuntime.jsx("rect", { width: "33.75", height: "30", fill: color }) }) })
|
|
81
81
|
] });
|
|
@@ -162,7 +162,7 @@ Icon.Minus = Minus;
|
|
|
162
162
|
Icon.Dashboard = Dashboard;
|
|
163
163
|
Icon.FleetIcon = FleetIcon;
|
|
164
164
|
Icon.Performance = Performance;
|
|
165
|
-
Icon.Map =
|
|
165
|
+
Icon.Map = Map2;
|
|
166
166
|
Icon.CharterParty = CharterParty;
|
|
167
167
|
Icon.Compliance = Compliance;
|
|
168
168
|
Icon.Applications = Applications;
|
|
@@ -2179,6 +2179,51 @@ function fieldShell({
|
|
|
2179
2179
|
"placeholder:text-foreground-muted"
|
|
2180
2180
|
].filter(Boolean).join(" ");
|
|
2181
2181
|
}
|
|
2182
|
+
function FieldHelpIcon({ text }) {
|
|
2183
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Tooltip, { title: text, placement: "top", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2184
|
+
"button",
|
|
2185
|
+
{
|
|
2186
|
+
type: "button",
|
|
2187
|
+
"aria-label": "More information",
|
|
2188
|
+
className: "inline-flex items-center justify-center rounded-full text-foreground-muted transition-colors hover:text-foreground focus:outline-none focus-visible:text-accent",
|
|
2189
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs("svg", { viewBox: "0 0 16 16", className: "h-3.5 w-3.5", fill: "none", stroke: "currentColor", strokeWidth: 1.5, "aria-hidden": "true", children: [
|
|
2190
|
+
/* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "8", cy: "8", r: "6.25" }),
|
|
2191
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", d: "M8 7.4v3.4" }),
|
|
2192
|
+
/* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "8", cy: "5.1", r: "0.65", fill: "currentColor", stroke: "none" })
|
|
2193
|
+
] })
|
|
2194
|
+
}
|
|
2195
|
+
) });
|
|
2196
|
+
}
|
|
2197
|
+
function FieldLabel({
|
|
2198
|
+
label,
|
|
2199
|
+
htmlFor,
|
|
2200
|
+
required,
|
|
2201
|
+
helperText,
|
|
2202
|
+
horizontal = false,
|
|
2203
|
+
style,
|
|
2204
|
+
width,
|
|
2205
|
+
className = ""
|
|
2206
|
+
}) {
|
|
2207
|
+
if (label == null && helperText == null) return null;
|
|
2208
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2209
|
+
"div",
|
|
2210
|
+
{
|
|
2211
|
+
style: { width: horizontal ? width : void 0, ...style },
|
|
2212
|
+
className: [
|
|
2213
|
+
"flex items-center gap-1",
|
|
2214
|
+
horizontal ? "mt-2 flex-shrink-0 whitespace-nowrap" : "",
|
|
2215
|
+
className
|
|
2216
|
+
].filter(Boolean).join(" "),
|
|
2217
|
+
children: [
|
|
2218
|
+
label != null && /* @__PURE__ */ jsxRuntime.jsxs("label", { htmlFor, className: "text-sm font-medium text-foreground select-none", children: [
|
|
2219
|
+
label,
|
|
2220
|
+
required && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-status-error ml-0.5", "aria-hidden": "true", children: "*" })
|
|
2221
|
+
] }),
|
|
2222
|
+
helperText != null && /* @__PURE__ */ jsxRuntime.jsx(FieldHelpIcon, { text: helperText })
|
|
2223
|
+
]
|
|
2224
|
+
}
|
|
2225
|
+
);
|
|
2226
|
+
}
|
|
2182
2227
|
function Field({
|
|
2183
2228
|
label,
|
|
2184
2229
|
htmlFor,
|
|
@@ -2186,6 +2231,7 @@ function Field({
|
|
|
2186
2231
|
errorMessage,
|
|
2187
2232
|
layout = "vertical",
|
|
2188
2233
|
required,
|
|
2234
|
+
helperText,
|
|
2189
2235
|
labelStyle,
|
|
2190
2236
|
labelWidth,
|
|
2191
2237
|
className = "",
|
|
@@ -2202,21 +2248,16 @@ function Field({
|
|
|
2202
2248
|
className
|
|
2203
2249
|
].filter(Boolean).join(" "),
|
|
2204
2250
|
children: [
|
|
2205
|
-
|
|
2206
|
-
|
|
2251
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2252
|
+
FieldLabel,
|
|
2207
2253
|
{
|
|
2254
|
+
label,
|
|
2208
2255
|
htmlFor,
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
horizontal ? "mt-2 flex-shrink-0 whitespace-nowrap" : ""
|
|
2215
|
-
].filter(Boolean).join(" "),
|
|
2216
|
-
children: [
|
|
2217
|
-
label,
|
|
2218
|
-
required && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-status-error ml-0.5", "aria-hidden": "true", children: "*" })
|
|
2219
|
-
]
|
|
2256
|
+
required,
|
|
2257
|
+
helperText,
|
|
2258
|
+
horizontal,
|
|
2259
|
+
style: labelStyle,
|
|
2260
|
+
width: labelWidth
|
|
2220
2261
|
}
|
|
2221
2262
|
),
|
|
2222
2263
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col min-w-0 flex-1", children: [
|
|
@@ -2228,8 +2269,8 @@ function Field({
|
|
|
2228
2269
|
);
|
|
2229
2270
|
}
|
|
2230
2271
|
var SearchIcon = /* @__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" }) });
|
|
2231
|
-
var SearchInput = React8__default.default.forwardRef(function SearchInput2({ value, onChange, disabled, label, htmlFor, placeholder, name, inputStyle, style, layout = "vertical", size = "md", icon }, ref) {
|
|
2232
|
-
return /* @__PURE__ */ jsxRuntime.jsx(Field, { label, htmlFor, layout, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2272
|
+
var SearchInput = React8__default.default.forwardRef(function SearchInput2({ value, onChange, disabled, label, htmlFor, placeholder, name, inputStyle, style, layout = "vertical", size = "md", icon, helperText }, ref) {
|
|
2273
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Field, { label, htmlFor, layout, helperText, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2233
2274
|
"div",
|
|
2234
2275
|
{
|
|
2235
2276
|
className: `flex items-center ${fieldShell({ size, disabled, focusWithin: true })}`,
|
|
@@ -2276,6 +2317,90 @@ function Tag({ children, onRemove, removeLabel, disabled }) {
|
|
|
2276
2317
|
)
|
|
2277
2318
|
] });
|
|
2278
2319
|
}
|
|
2320
|
+
function MultiTagRow({
|
|
2321
|
+
values,
|
|
2322
|
+
disabled,
|
|
2323
|
+
labelFor,
|
|
2324
|
+
onRemove
|
|
2325
|
+
}) {
|
|
2326
|
+
const wrapRef = React8.useRef(null);
|
|
2327
|
+
const measureRef = React8.useRef(null);
|
|
2328
|
+
const [visibleCount, setVisibleCount] = React8.useState(values.length);
|
|
2329
|
+
const key = values.map(String).join("|");
|
|
2330
|
+
React8.useLayoutEffect(() => {
|
|
2331
|
+
const wrap = wrapRef.current;
|
|
2332
|
+
const measure = measureRef.current;
|
|
2333
|
+
if (!wrap || !measure) return;
|
|
2334
|
+
const GAP = 6;
|
|
2335
|
+
const recompute = () => {
|
|
2336
|
+
const avail = wrap.clientWidth;
|
|
2337
|
+
const tagEls = Array.from(measure.querySelectorAll("[data-mt]"));
|
|
2338
|
+
const moreEl = measure.querySelector("[data-mm]");
|
|
2339
|
+
const widths = tagEls.map((e) => e.offsetWidth);
|
|
2340
|
+
const moreW = moreEl ? moreEl.offsetWidth : 0;
|
|
2341
|
+
if (widths.length === 0) {
|
|
2342
|
+
setVisibleCount(0);
|
|
2343
|
+
return;
|
|
2344
|
+
}
|
|
2345
|
+
let used = 0;
|
|
2346
|
+
let count = 0;
|
|
2347
|
+
for (let i = 0; i < widths.length; i++) {
|
|
2348
|
+
const w = widths[i] + (i > 0 ? GAP : 0);
|
|
2349
|
+
if (used + w <= avail) {
|
|
2350
|
+
used += w;
|
|
2351
|
+
count++;
|
|
2352
|
+
} else break;
|
|
2353
|
+
}
|
|
2354
|
+
if (count < widths.length) {
|
|
2355
|
+
while (count > 0) {
|
|
2356
|
+
let t = 0;
|
|
2357
|
+
for (let i = 0; i < count; i++) t += widths[i] + (i > 0 ? GAP : 0);
|
|
2358
|
+
t += GAP + moreW;
|
|
2359
|
+
if (t <= avail) break;
|
|
2360
|
+
count--;
|
|
2361
|
+
}
|
|
2362
|
+
}
|
|
2363
|
+
setVisibleCount(count);
|
|
2364
|
+
};
|
|
2365
|
+
recompute();
|
|
2366
|
+
const ro = new ResizeObserver(recompute);
|
|
2367
|
+
ro.observe(wrap);
|
|
2368
|
+
return () => ro.disconnect();
|
|
2369
|
+
}, [key]);
|
|
2370
|
+
const hidden = values.length - visibleCount;
|
|
2371
|
+
const moreChip = (n) => /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex items-center flex-shrink-0 rounded-md border border-border bg-surface-raised text-foreground-secondary text-xs px-2 py-0.5", children: [
|
|
2372
|
+
"+",
|
|
2373
|
+
n,
|
|
2374
|
+
" more"
|
|
2375
|
+
] });
|
|
2376
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: wrapRef, className: "relative flex-1 min-w-0 flex flex-nowrap items-center gap-1.5 overflow-hidden", children: [
|
|
2377
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
2378
|
+
"div",
|
|
2379
|
+
{
|
|
2380
|
+
ref: measureRef,
|
|
2381
|
+
"aria-hidden": "true",
|
|
2382
|
+
className: "absolute invisible pointer-events-none flex flex-nowrap items-center gap-1.5",
|
|
2383
|
+
style: { left: -9999, top: -9999 },
|
|
2384
|
+
children: [
|
|
2385
|
+
values.map((val) => /* @__PURE__ */ jsxRuntime.jsx("span", { "data-mt": true, children: /* @__PURE__ */ jsxRuntime.jsx(Tag, { removeLabel: "x", onRemove: () => {
|
|
2386
|
+
}, children: labelFor(val) }) }, `m-${val}`)),
|
|
2387
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { "data-mm": true, children: moreChip(values.length) })
|
|
2388
|
+
]
|
|
2389
|
+
}
|
|
2390
|
+
),
|
|
2391
|
+
values.slice(0, visibleCount).map((val) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
2392
|
+
Tag,
|
|
2393
|
+
{
|
|
2394
|
+
disabled,
|
|
2395
|
+
removeLabel: `Remove ${labelFor(val)}`,
|
|
2396
|
+
onRemove: () => onRemove(val),
|
|
2397
|
+
children: labelFor(val)
|
|
2398
|
+
},
|
|
2399
|
+
String(val)
|
|
2400
|
+
)),
|
|
2401
|
+
hidden > 0 && moreChip(hidden)
|
|
2402
|
+
] });
|
|
2403
|
+
}
|
|
2279
2404
|
function Dropdown({
|
|
2280
2405
|
isMultiselect = false,
|
|
2281
2406
|
hasSearch = true,
|
|
@@ -2285,6 +2410,8 @@ function Dropdown({
|
|
|
2285
2410
|
onChange,
|
|
2286
2411
|
disabled,
|
|
2287
2412
|
layout = "horizontal",
|
|
2413
|
+
helperText,
|
|
2414
|
+
required,
|
|
2288
2415
|
errorMessage,
|
|
2289
2416
|
style = {},
|
|
2290
2417
|
htmlFor,
|
|
@@ -2345,13 +2472,15 @@ function Dropdown({
|
|
|
2345
2472
|
{
|
|
2346
2473
|
className: `flex ${layout === "vertical" ? "flex-col gap-1.5" : "flex-row items-start gap-3"}`,
|
|
2347
2474
|
children: [
|
|
2348
|
-
|
|
2349
|
-
|
|
2475
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2476
|
+
FieldLabel,
|
|
2350
2477
|
{
|
|
2351
|
-
|
|
2478
|
+
label,
|
|
2352
2479
|
htmlFor,
|
|
2353
|
-
|
|
2354
|
-
|
|
2480
|
+
required,
|
|
2481
|
+
helperText,
|
|
2482
|
+
horizontal: layout === "horizontal",
|
|
2483
|
+
style: labelStyle
|
|
2355
2484
|
}
|
|
2356
2485
|
),
|
|
2357
2486
|
/* @__PURE__ */ jsxRuntime.jsxs(Popover__namespace.Root, { open: open && !disabled, onOpenChange: (o) => !disabled && setOpen(o), children: [
|
|
@@ -2364,8 +2493,8 @@ function Dropdown({
|
|
|
2364
2493
|
"aria-haspopup": "listbox",
|
|
2365
2494
|
"aria-invalid": hasError || void 0,
|
|
2366
2495
|
"aria-describedby": hasError ? errorId : void 0,
|
|
2367
|
-
style,
|
|
2368
|
-
className: `flex items-center justify-between gap-2 cursor-pointer select-none min-h-[36px] px-3 py-1.5 ${
|
|
2496
|
+
style: { width: 240, ...style },
|
|
2497
|
+
className: `flex items-center justify-between gap-2 cursor-pointer select-none min-h-[36px] px-3 py-1.5 ${fieldShell({ size, hasError, disabled, sized: false })}`,
|
|
2369
2498
|
tabIndex: disabled ? -1 : 0,
|
|
2370
2499
|
onKeyDown: (e) => {
|
|
2371
2500
|
if (disabled) return;
|
|
@@ -2375,16 +2504,15 @@ function Dropdown({
|
|
|
2375
2504
|
}
|
|
2376
2505
|
},
|
|
2377
2506
|
children: [
|
|
2378
|
-
|
|
2379
|
-
|
|
2507
|
+
!value || Array.isArray(value) && value.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1 min-w-0 truncate text-foreground-muted text-sm", children: placeholder }) : Array.isArray(value) ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
2508
|
+
MultiTagRow,
|
|
2380
2509
|
{
|
|
2510
|
+
values: value,
|
|
2381
2511
|
disabled,
|
|
2382
|
-
|
|
2383
|
-
onRemove:
|
|
2384
|
-
|
|
2385
|
-
|
|
2386
|
-
String(val)
|
|
2387
|
-
)) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
2512
|
+
labelFor,
|
|
2513
|
+
onRemove: removeSelected
|
|
2514
|
+
}
|
|
2515
|
+
) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 min-w-0 flex items-center overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2388
2516
|
Tag,
|
|
2389
2517
|
{
|
|
2390
2518
|
disabled,
|
|
@@ -3324,6 +3452,7 @@ function TextInput({
|
|
|
3324
3452
|
size = "md",
|
|
3325
3453
|
onBlur,
|
|
3326
3454
|
errorMessage,
|
|
3455
|
+
helperText,
|
|
3327
3456
|
required,
|
|
3328
3457
|
prefix,
|
|
3329
3458
|
suffix
|
|
@@ -3356,9 +3485,9 @@ function TextInput({
|
|
|
3356
3485
|
htmlFor,
|
|
3357
3486
|
errorId,
|
|
3358
3487
|
errorMessage,
|
|
3488
|
+
helperText,
|
|
3359
3489
|
layout,
|
|
3360
3490
|
required,
|
|
3361
|
-
className: style ? void 0 : void 0,
|
|
3362
3491
|
children: hasAdornment ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3363
3492
|
"div",
|
|
3364
3493
|
{
|
|
@@ -3385,6 +3514,7 @@ function NumberInput({
|
|
|
3385
3514
|
layout = "vertical",
|
|
3386
3515
|
size = "md",
|
|
3387
3516
|
errorMessage,
|
|
3517
|
+
helperText,
|
|
3388
3518
|
required,
|
|
3389
3519
|
inputStyle,
|
|
3390
3520
|
labelStyle,
|
|
@@ -3433,6 +3563,7 @@ function NumberInput({
|
|
|
3433
3563
|
htmlFor,
|
|
3434
3564
|
errorId,
|
|
3435
3565
|
errorMessage,
|
|
3566
|
+
helperText,
|
|
3436
3567
|
layout,
|
|
3437
3568
|
required,
|
|
3438
3569
|
labelStyle,
|
|
@@ -3518,6 +3649,7 @@ function Password({
|
|
|
3518
3649
|
size = "md",
|
|
3519
3650
|
onBlur,
|
|
3520
3651
|
errorMessage,
|
|
3652
|
+
helperText,
|
|
3521
3653
|
required,
|
|
3522
3654
|
showIcon,
|
|
3523
3655
|
hideIcon
|
|
@@ -3532,6 +3664,7 @@ function Password({
|
|
|
3532
3664
|
htmlFor,
|
|
3533
3665
|
errorId,
|
|
3534
3666
|
errorMessage,
|
|
3667
|
+
helperText,
|
|
3535
3668
|
layout,
|
|
3536
3669
|
required,
|
|
3537
3670
|
children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -3586,10 +3719,14 @@ function Checkbox({
|
|
|
3586
3719
|
errorMessage,
|
|
3587
3720
|
disabled = false,
|
|
3588
3721
|
layout = "horizontal",
|
|
3589
|
-
labelPosition = "right"
|
|
3722
|
+
labelPosition = "right",
|
|
3723
|
+
helperText,
|
|
3724
|
+
required
|
|
3590
3725
|
}) {
|
|
3591
3726
|
const isChecked = checked ?? value ?? false;
|
|
3592
3727
|
const labelFirst = labelPosition === "left";
|
|
3728
|
+
const errorId = React8.useId();
|
|
3729
|
+
const hasError = errorMessage != null;
|
|
3593
3730
|
const box = /* @__PURE__ */ jsxRuntime.jsx(
|
|
3594
3731
|
CheckboxPrimitive__namespace.Root,
|
|
3595
3732
|
{
|
|
@@ -3608,30 +3745,38 @@ function Checkbox({
|
|
|
3608
3745
|
"disabled:cursor-not-allowed"
|
|
3609
3746
|
].join(" "),
|
|
3610
3747
|
"aria-label": typeof label === "string" ? label : void 0,
|
|
3748
|
+
"aria-invalid": hasError || void 0,
|
|
3749
|
+
"aria-describedby": hasError ? errorId : void 0,
|
|
3611
3750
|
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" }) }) })
|
|
3612
3751
|
}
|
|
3613
3752
|
);
|
|
3614
|
-
const labelEl = label && /* @__PURE__ */ jsxRuntime.
|
|
3753
|
+
const labelEl = label && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm text-foreground-secondary select-none leading-snug", children: [
|
|
3754
|
+
label,
|
|
3755
|
+
required && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-status-error ml-0.5", "aria-hidden": "true", children: "*" })
|
|
3756
|
+
] });
|
|
3615
3757
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
3616
|
-
/* @__PURE__ */ jsxRuntime.
|
|
3617
|
-
|
|
3618
|
-
|
|
3619
|
-
|
|
3620
|
-
|
|
3621
|
-
|
|
3622
|
-
|
|
3623
|
-
|
|
3624
|
-
|
|
3625
|
-
|
|
3626
|
-
|
|
3627
|
-
|
|
3628
|
-
|
|
3629
|
-
|
|
3630
|
-
|
|
3631
|
-
|
|
3632
|
-
|
|
3633
|
-
|
|
3634
|
-
|
|
3758
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
|
|
3759
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3760
|
+
"label",
|
|
3761
|
+
{
|
|
3762
|
+
htmlFor,
|
|
3763
|
+
className: [
|
|
3764
|
+
"inline-flex",
|
|
3765
|
+
layout === "vertical" ? "flex-col items-start gap-1.5" : "flex-row items-center gap-2.5",
|
|
3766
|
+
disabled ? "cursor-not-allowed opacity-50" : "cursor-pointer"
|
|
3767
|
+
].join(" "),
|
|
3768
|
+
children: labelFirst ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
3769
|
+
labelEl,
|
|
3770
|
+
box
|
|
3771
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
3772
|
+
box,
|
|
3773
|
+
labelEl
|
|
3774
|
+
] })
|
|
3775
|
+
}
|
|
3776
|
+
),
|
|
3777
|
+
helperText != null && /* @__PURE__ */ jsxRuntime.jsx(FieldHelpIcon, { text: helperText })
|
|
3778
|
+
] }),
|
|
3779
|
+
errorMessage && /* @__PURE__ */ jsxRuntime.jsx("span", { id: errorId, className: "text-xs text-status-error mt-0.5", children: errorMessage })
|
|
3635
3780
|
] });
|
|
3636
3781
|
}
|
|
3637
3782
|
var DOT_SIZE = {
|
|
@@ -3656,6 +3801,7 @@ function RadioGroup({
|
|
|
3656
3801
|
size = "md",
|
|
3657
3802
|
disabled,
|
|
3658
3803
|
required,
|
|
3804
|
+
helperText,
|
|
3659
3805
|
errorMessage
|
|
3660
3806
|
}) {
|
|
3661
3807
|
const errorId = React8.useId();
|
|
@@ -3670,6 +3816,7 @@ function RadioGroup({
|
|
|
3670
3816
|
errorId,
|
|
3671
3817
|
errorMessage,
|
|
3672
3818
|
required,
|
|
3819
|
+
helperText,
|
|
3673
3820
|
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3674
3821
|
RadioGroupPrimitive__namespace.Root,
|
|
3675
3822
|
{
|
|
@@ -3720,7 +3867,8 @@ function RadioGroup({
|
|
|
3720
3867
|
]
|
|
3721
3868
|
}
|
|
3722
3869
|
);
|
|
3723
|
-
|
|
3870
|
+
const rowClass = labelFirst && layout === "vertical" ? "grid grid-cols-[1fr_auto] items-start gap-2.5" : "flex items-start gap-2.5";
|
|
3871
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: rowClass, children: labelFirst ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
3724
3872
|
labelEl,
|
|
3725
3873
|
dot
|
|
3726
3874
|
] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
@@ -3734,28 +3882,73 @@ function RadioGroup({
|
|
|
3734
3882
|
);
|
|
3735
3883
|
}
|
|
3736
3884
|
function Switch({
|
|
3737
|
-
checked
|
|
3885
|
+
checked,
|
|
3886
|
+
defaultChecked = false,
|
|
3738
3887
|
onChange,
|
|
3739
3888
|
checkedIcon,
|
|
3740
|
-
uncheckedIcon
|
|
3889
|
+
uncheckedIcon,
|
|
3890
|
+
label,
|
|
3891
|
+
layout = "horizontal",
|
|
3892
|
+
helperText,
|
|
3893
|
+
offLabel,
|
|
3894
|
+
onLabel,
|
|
3895
|
+
name,
|
|
3896
|
+
required,
|
|
3897
|
+
disabled,
|
|
3898
|
+
errorMessage
|
|
3741
3899
|
}) {
|
|
3742
3900
|
const id = React8.useId();
|
|
3743
|
-
|
|
3744
|
-
|
|
3901
|
+
const errorId = React8.useId();
|
|
3902
|
+
const hasError = errorMessage != null;
|
|
3903
|
+
const isControlled = checked !== void 0;
|
|
3904
|
+
const [internal, setInternal] = React8.useState(defaultChecked);
|
|
3905
|
+
const isOn = isControlled ? checked : internal;
|
|
3906
|
+
const handle = (c) => {
|
|
3907
|
+
if (!isControlled) setInternal(c);
|
|
3908
|
+
onChange?.({ target: { checked: c, name } });
|
|
3909
|
+
};
|
|
3910
|
+
const stateLabel = (active) => [
|
|
3911
|
+
"text-sm select-none transition-colors",
|
|
3912
|
+
active ? "text-foreground font-medium" : "text-foreground-muted",
|
|
3913
|
+
disabled ? "opacity-50" : "cursor-pointer"
|
|
3914
|
+
].filter(Boolean).join(" ");
|
|
3915
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
3916
|
+
Field,
|
|
3745
3917
|
{
|
|
3746
|
-
|
|
3747
|
-
|
|
3748
|
-
|
|
3749
|
-
|
|
3750
|
-
|
|
3751
|
-
|
|
3752
|
-
|
|
3753
|
-
|
|
3754
|
-
|
|
3755
|
-
|
|
3756
|
-
|
|
3918
|
+
label,
|
|
3919
|
+
htmlFor: id,
|
|
3920
|
+
errorId,
|
|
3921
|
+
errorMessage,
|
|
3922
|
+
layout,
|
|
3923
|
+
required,
|
|
3924
|
+
helperText,
|
|
3925
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2.5", children: [
|
|
3926
|
+
offLabel != null && /* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: id, className: stateLabel(!isOn), children: offLabel }),
|
|
3927
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3928
|
+
SwitchPrimitive__namespace.Root,
|
|
3929
|
+
{
|
|
3930
|
+
id,
|
|
3931
|
+
name,
|
|
3932
|
+
checked: isOn,
|
|
3933
|
+
onCheckedChange: handle,
|
|
3934
|
+
disabled,
|
|
3935
|
+
required,
|
|
3936
|
+
"aria-invalid": hasError || void 0,
|
|
3937
|
+
"aria-describedby": hasError ? errorId : void 0,
|
|
3938
|
+
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 disabled:opacity-50 disabled:cursor-not-allowed",
|
|
3939
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3940
|
+
SwitchPrimitive__namespace.Thumb,
|
|
3941
|
+
{
|
|
3942
|
+
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]",
|
|
3943
|
+
children: checkedIcon && uncheckedIcon ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex items-center justify-center w-3 h-3", children: isOn ? checkedIcon : uncheckedIcon }) : null
|
|
3944
|
+
}
|
|
3945
|
+
)
|
|
3946
|
+
}
|
|
3947
|
+
),
|
|
3948
|
+
onLabel != null && /* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: id, className: stateLabel(isOn), children: onLabel })
|
|
3949
|
+
] })
|
|
3757
3950
|
}
|
|
3758
|
-
)
|
|
3951
|
+
);
|
|
3759
3952
|
}
|
|
3760
3953
|
function AutoComplete({
|
|
3761
3954
|
disabled,
|
|
@@ -3774,6 +3967,7 @@ function AutoComplete({
|
|
|
3774
3967
|
size = "md",
|
|
3775
3968
|
icon,
|
|
3776
3969
|
errorMessage,
|
|
3970
|
+
helperText,
|
|
3777
3971
|
required,
|
|
3778
3972
|
htmlFor
|
|
3779
3973
|
}) {
|
|
@@ -3832,6 +4026,7 @@ function AutoComplete({
|
|
|
3832
4026
|
htmlFor,
|
|
3833
4027
|
errorId,
|
|
3834
4028
|
errorMessage,
|
|
4029
|
+
helperText,
|
|
3835
4030
|
layout,
|
|
3836
4031
|
required,
|
|
3837
4032
|
children: /* @__PURE__ */ jsxRuntime.jsxs(Popover__namespace.Root, { open: open && !disabled, onOpenChange: (o) => !disabled && setOpen(o), children: [
|
|
@@ -3931,6 +4126,8 @@ function TreeSelect({
|
|
|
3931
4126
|
onChange,
|
|
3932
4127
|
disabled,
|
|
3933
4128
|
layout = "horizontal",
|
|
4129
|
+
helperText,
|
|
4130
|
+
required,
|
|
3934
4131
|
errorMessage,
|
|
3935
4132
|
style,
|
|
3936
4133
|
htmlFor,
|
|
@@ -4016,12 +4213,14 @@ function TreeSelect({
|
|
|
4016
4213
|
};
|
|
4017
4214
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
4018
4215
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: `flex ${layout === "vertical" ? "flex-col gap-1" : "flex-row items-center gap-2"}`, children: [
|
|
4019
|
-
|
|
4020
|
-
|
|
4216
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4217
|
+
FieldLabel,
|
|
4021
4218
|
{
|
|
4022
|
-
|
|
4219
|
+
label,
|
|
4023
4220
|
htmlFor,
|
|
4024
|
-
|
|
4221
|
+
required,
|
|
4222
|
+
helperText,
|
|
4223
|
+
horizontal: layout === "horizontal"
|
|
4025
4224
|
}
|
|
4026
4225
|
),
|
|
4027
4226
|
/* @__PURE__ */ jsxRuntime.jsxs(Popover__namespace.Root, { open: open && !disabled, onOpenChange: (o) => !disabled && setOpen(o), children: [
|
|
@@ -4183,6 +4382,7 @@ function FileInput({
|
|
|
4183
4382
|
hint,
|
|
4184
4383
|
maxSize,
|
|
4185
4384
|
errorMessage,
|
|
4385
|
+
helperText,
|
|
4186
4386
|
disabled,
|
|
4187
4387
|
required,
|
|
4188
4388
|
icon
|
|
@@ -4229,6 +4429,7 @@ function FileInput({
|
|
|
4229
4429
|
htmlFor,
|
|
4230
4430
|
errorId,
|
|
4231
4431
|
errorMessage: effectiveError,
|
|
4432
|
+
helperText,
|
|
4232
4433
|
required,
|
|
4233
4434
|
children: [
|
|
4234
4435
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -4367,6 +4568,8 @@ function DatePicker({
|
|
|
4367
4568
|
htmlFor,
|
|
4368
4569
|
name: _name,
|
|
4369
4570
|
layout = "horizontal",
|
|
4571
|
+
helperText,
|
|
4572
|
+
required,
|
|
4370
4573
|
disabled,
|
|
4371
4574
|
errorMessage,
|
|
4372
4575
|
min,
|
|
@@ -4458,12 +4661,14 @@ function DatePicker({
|
|
|
4458
4661
|
const displayValue = value ? format(value) : "";
|
|
4459
4662
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
4460
4663
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: `flex ${layout === "vertical" ? "flex-col gap-1.5" : "flex-row items-start gap-3"}`, children: [
|
|
4461
|
-
|
|
4462
|
-
|
|
4664
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4665
|
+
FieldLabel,
|
|
4463
4666
|
{
|
|
4464
|
-
|
|
4667
|
+
label,
|
|
4465
4668
|
htmlFor,
|
|
4466
|
-
|
|
4669
|
+
required,
|
|
4670
|
+
helperText,
|
|
4671
|
+
horizontal: layout === "horizontal"
|
|
4467
4672
|
}
|
|
4468
4673
|
),
|
|
4469
4674
|
/* @__PURE__ */ jsxRuntime.jsxs(Popover__namespace.Root, { open: open && !disabled, onOpenChange: (o) => !disabled && setOpen(o), children: [
|
|
@@ -4682,6 +4887,7 @@ function TextArea({
|
|
|
4682
4887
|
showCount = false,
|
|
4683
4888
|
resize,
|
|
4684
4889
|
errorMessage,
|
|
4890
|
+
helperText,
|
|
4685
4891
|
required,
|
|
4686
4892
|
style,
|
|
4687
4893
|
inputStyle
|
|
@@ -4707,6 +4913,7 @@ function TextArea({
|
|
|
4707
4913
|
htmlFor,
|
|
4708
4914
|
errorId,
|
|
4709
4915
|
errorMessage,
|
|
4916
|
+
helperText,
|
|
4710
4917
|
layout,
|
|
4711
4918
|
required,
|
|
4712
4919
|
children: [
|
|
@@ -4747,51 +4954,84 @@ function SegmentedControl({
|
|
|
4747
4954
|
size = "md",
|
|
4748
4955
|
fullWidth = false,
|
|
4749
4956
|
disabled,
|
|
4957
|
+
label,
|
|
4958
|
+
layout = "vertical",
|
|
4959
|
+
helperText,
|
|
4960
|
+
name,
|
|
4961
|
+
required,
|
|
4962
|
+
errorMessage,
|
|
4750
4963
|
"aria-label": ariaLabel
|
|
4751
4964
|
}) {
|
|
4752
4965
|
const sz = SIZE[size];
|
|
4753
|
-
|
|
4754
|
-
|
|
4966
|
+
const groupId = React8.useId();
|
|
4967
|
+
const errorId = React8.useId();
|
|
4968
|
+
const hasError = errorMessage != null;
|
|
4969
|
+
const isControlled = value !== void 0;
|
|
4970
|
+
const [internal, setInternal] = React8.useState(defaultValue);
|
|
4971
|
+
const current = isControlled ? value : internal;
|
|
4972
|
+
const handle = (v) => {
|
|
4973
|
+
if (!v) return;
|
|
4974
|
+
if (!isControlled) setInternal(v);
|
|
4975
|
+
onChange?.(v);
|
|
4976
|
+
};
|
|
4977
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
4978
|
+
Field,
|
|
4755
4979
|
{
|
|
4756
|
-
|
|
4757
|
-
|
|
4758
|
-
|
|
4759
|
-
|
|
4760
|
-
|
|
4761
|
-
|
|
4762
|
-
|
|
4763
|
-
|
|
4764
|
-
|
|
4765
|
-
|
|
4766
|
-
|
|
4767
|
-
|
|
4768
|
-
|
|
4769
|
-
|
|
4770
|
-
|
|
4771
|
-
|
|
4772
|
-
|
|
4773
|
-
|
|
4774
|
-
|
|
4775
|
-
|
|
4776
|
-
|
|
4777
|
-
|
|
4778
|
-
|
|
4779
|
-
|
|
4780
|
-
|
|
4781
|
-
|
|
4782
|
-
"
|
|
4783
|
-
|
|
4784
|
-
|
|
4785
|
-
|
|
4786
|
-
|
|
4787
|
-
|
|
4788
|
-
|
|
4789
|
-
|
|
4790
|
-
|
|
4791
|
-
|
|
4792
|
-
|
|
4793
|
-
|
|
4794
|
-
|
|
4980
|
+
label,
|
|
4981
|
+
htmlFor: groupId,
|
|
4982
|
+
errorId,
|
|
4983
|
+
errorMessage,
|
|
4984
|
+
layout,
|
|
4985
|
+
required,
|
|
4986
|
+
helperText,
|
|
4987
|
+
children: [
|
|
4988
|
+
name && /* @__PURE__ */ jsxRuntime.jsx("input", { type: "hidden", name, value: current ?? "" }),
|
|
4989
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4990
|
+
ToggleGroup__namespace.Root,
|
|
4991
|
+
{
|
|
4992
|
+
id: groupId,
|
|
4993
|
+
type: "single",
|
|
4994
|
+
value: current,
|
|
4995
|
+
onValueChange: handle,
|
|
4996
|
+
disabled,
|
|
4997
|
+
"aria-label": ariaLabel ?? (typeof label === "string" ? label : void 0),
|
|
4998
|
+
"aria-invalid": hasError || void 0,
|
|
4999
|
+
"aria-describedby": hasError ? errorId : void 0,
|
|
5000
|
+
className: [
|
|
5001
|
+
"inline-flex items-center gap-1 rounded-lg border bg-surface-raised p-1",
|
|
5002
|
+
hasError ? "border-status-error" : "border-border",
|
|
5003
|
+
sz.h,
|
|
5004
|
+
fullWidth ? "flex w-full" : "w-fit",
|
|
5005
|
+
disabled ? "opacity-60 cursor-not-allowed" : ""
|
|
5006
|
+
].filter(Boolean).join(" "),
|
|
5007
|
+
children: options.map((opt) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
5008
|
+
ToggleGroup__namespace.Item,
|
|
5009
|
+
{
|
|
5010
|
+
value: opt.value,
|
|
5011
|
+
disabled: opt.disabled,
|
|
5012
|
+
className: [
|
|
5013
|
+
"inline-flex items-center justify-center gap-1.5 rounded-md select-none whitespace-nowrap",
|
|
5014
|
+
"transition-colors duration-150 h-full",
|
|
5015
|
+
sz.text,
|
|
5016
|
+
sz.pad,
|
|
5017
|
+
fullWidth ? "flex-1" : "",
|
|
5018
|
+
// Resting: muted text, transparent. Hover lifts the text.
|
|
5019
|
+
"text-foreground-secondary hover:text-foreground",
|
|
5020
|
+
// Active: surface-white pill + accent text + subtle shadow.
|
|
5021
|
+
"data-[state=on]:bg-surface data-[state=on]:text-accent data-[state=on]:shadow-sm",
|
|
5022
|
+
"focus:outline-none focus-visible:ring-[3px] focus-visible:ring-focus-ring",
|
|
5023
|
+
"disabled:opacity-40 disabled:cursor-not-allowed"
|
|
5024
|
+
].filter(Boolean).join(" "),
|
|
5025
|
+
children: [
|
|
5026
|
+
opt.icon && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-shrink-0", children: opt.icon }),
|
|
5027
|
+
opt.label
|
|
5028
|
+
]
|
|
5029
|
+
},
|
|
5030
|
+
opt.value
|
|
5031
|
+
))
|
|
5032
|
+
}
|
|
5033
|
+
)
|
|
5034
|
+
]
|
|
4795
5035
|
}
|
|
4796
5036
|
);
|
|
4797
5037
|
}
|
|
@@ -4814,6 +5054,8 @@ function Slider({
|
|
|
4814
5054
|
size = "md",
|
|
4815
5055
|
disabled,
|
|
4816
5056
|
errorMessage,
|
|
5057
|
+
helperText,
|
|
5058
|
+
required,
|
|
4817
5059
|
name,
|
|
4818
5060
|
htmlFor
|
|
4819
5061
|
}) {
|
|
@@ -4833,7 +5075,13 @@ function Slider({
|
|
|
4833
5075
|
const valueText = current.map(formatValue).join(" \u2013 ");
|
|
4834
5076
|
return /* @__PURE__ */ jsxRuntime.jsxs(Field, { label: void 0, errorId, errorMessage, children: [
|
|
4835
5077
|
(label || showValue) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between mb-2", children: [
|
|
4836
|
-
label && /* @__PURE__ */ jsxRuntime.
|
|
5078
|
+
label && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center gap-1", children: [
|
|
5079
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { htmlFor, className: "text-sm font-medium text-foreground select-none", children: [
|
|
5080
|
+
label,
|
|
5081
|
+
required && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-status-error ml-0.5", "aria-hidden": "true", children: "*" })
|
|
5082
|
+
] }),
|
|
5083
|
+
helperText != null && /* @__PURE__ */ jsxRuntime.jsx(FieldHelpIcon, { text: helperText })
|
|
5084
|
+
] }),
|
|
4837
5085
|
showValue && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-foreground-secondary tabular-nums", children: valueText })
|
|
4838
5086
|
] }),
|
|
4839
5087
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -4905,6 +5153,7 @@ function TagsInput({
|
|
|
4905
5153
|
size = "md",
|
|
4906
5154
|
disabled,
|
|
4907
5155
|
errorMessage,
|
|
5156
|
+
helperText,
|
|
4908
5157
|
required,
|
|
4909
5158
|
maxTags,
|
|
4910
5159
|
dedupe = true,
|
|
@@ -4972,6 +5221,7 @@ function TagsInput({
|
|
|
4972
5221
|
htmlFor,
|
|
4973
5222
|
errorId,
|
|
4974
5223
|
errorMessage: errorText,
|
|
5224
|
+
helperText,
|
|
4975
5225
|
layout,
|
|
4976
5226
|
required,
|
|
4977
5227
|
children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -5039,6 +5289,8 @@ function OtpInput({
|
|
|
5039
5289
|
disabled,
|
|
5040
5290
|
errorMessage,
|
|
5041
5291
|
required,
|
|
5292
|
+
layout = "vertical",
|
|
5293
|
+
helperText,
|
|
5042
5294
|
groupAfter
|
|
5043
5295
|
}) {
|
|
5044
5296
|
const errorId = React8.useId();
|
|
@@ -5092,7 +5344,7 @@ function OtpInput({
|
|
|
5092
5344
|
emit(valid.join(""));
|
|
5093
5345
|
focusBox(valid.length);
|
|
5094
5346
|
};
|
|
5095
|
-
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: [
|
|
5347
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Field, { label, htmlFor, errorId, errorMessage, required, layout, helperText, 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: [
|
|
5096
5348
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5097
5349
|
"input",
|
|
5098
5350
|
{
|
|
@@ -5144,7 +5396,10 @@ function Rating({
|
|
|
5144
5396
|
disabled,
|
|
5145
5397
|
icon = Star,
|
|
5146
5398
|
errorMessage,
|
|
5147
|
-
name
|
|
5399
|
+
name,
|
|
5400
|
+
layout = "vertical",
|
|
5401
|
+
helperText,
|
|
5402
|
+
required
|
|
5148
5403
|
}) {
|
|
5149
5404
|
const errorId = React8.useId();
|
|
5150
5405
|
const [internal, setInternal] = React8.useState(defaultValue);
|
|
@@ -5174,7 +5429,7 @@ function Rating({
|
|
|
5174
5429
|
commit(count);
|
|
5175
5430
|
}
|
|
5176
5431
|
};
|
|
5177
|
-
return /* @__PURE__ */ jsxRuntime.jsx(Field, { label, errorId, errorMessage, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
5432
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Field, { label, errorId, errorMessage, layout, required, helperText, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
5178
5433
|
"div",
|
|
5179
5434
|
{
|
|
5180
5435
|
role: interactive ? "slider" : "img",
|
|
@@ -5266,6 +5521,7 @@ function TimePicker({
|
|
|
5266
5521
|
minuteStep = 1,
|
|
5267
5522
|
disabled,
|
|
5268
5523
|
errorMessage,
|
|
5524
|
+
helperText,
|
|
5269
5525
|
required,
|
|
5270
5526
|
style
|
|
5271
5527
|
}) {
|
|
@@ -5298,7 +5554,7 @@ function TimePicker({
|
|
|
5298
5554
|
},
|
|
5299
5555
|
n
|
|
5300
5556
|
)) });
|
|
5301
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(Field, { label, htmlFor, errorId, errorMessage, layout, required, children: [
|
|
5557
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(Field, { label, htmlFor, errorId, errorMessage, helperText, layout, required, children: [
|
|
5302
5558
|
/* @__PURE__ */ jsxRuntime.jsxs(Popover__namespace.Root, { open: open && !disabled, onOpenChange: (o) => !disabled && setOpen(o), children: [
|
|
5303
5559
|
/* @__PURE__ */ jsxRuntime.jsx(Popover__namespace.Trigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
5304
5560
|
"button",
|
|
@@ -5390,6 +5646,7 @@ function DateRangePicker({
|
|
|
5390
5646
|
format = defaultFmt,
|
|
5391
5647
|
disabled,
|
|
5392
5648
|
errorMessage,
|
|
5649
|
+
helperText,
|
|
5393
5650
|
required,
|
|
5394
5651
|
style
|
|
5395
5652
|
}) {
|
|
@@ -5462,7 +5719,7 @@ function DateRangePicker({
|
|
|
5462
5719
|
] })
|
|
5463
5720
|
] });
|
|
5464
5721
|
};
|
|
5465
|
-
return /* @__PURE__ */ jsxRuntime.jsx(Field, { label, htmlFor, errorId, errorMessage, layout, required, children: /* @__PURE__ */ jsxRuntime.jsxs(Popover__namespace.Root, { open: open && !disabled, onOpenChange: (o) => {
|
|
5722
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Field, { label, htmlFor, errorId, errorMessage, helperText, layout, required, children: /* @__PURE__ */ jsxRuntime.jsxs(Popover__namespace.Root, { open: open && !disabled, onOpenChange: (o) => {
|
|
5466
5723
|
if (!disabled) {
|
|
5467
5724
|
setOpen(o);
|
|
5468
5725
|
if (!o) {
|
|
@@ -5570,6 +5827,7 @@ function ColorPicker({
|
|
|
5570
5827
|
allowCustom = true,
|
|
5571
5828
|
disabled,
|
|
5572
5829
|
errorMessage,
|
|
5830
|
+
helperText,
|
|
5573
5831
|
required,
|
|
5574
5832
|
placeholder = "Pick a colour\u2026"
|
|
5575
5833
|
}) {
|
|
@@ -5587,7 +5845,7 @@ function ColorPicker({
|
|
|
5587
5845
|
setDraft(hex);
|
|
5588
5846
|
if (HEX_RE.test(hex)) onChange?.(hex);
|
|
5589
5847
|
};
|
|
5590
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(Field, { label, htmlFor, errorId, errorMessage, layout, required, children: [
|
|
5848
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(Field, { label, htmlFor, errorId, errorMessage, helperText, layout, required, children: [
|
|
5591
5849
|
/* @__PURE__ */ jsxRuntime.jsxs(Popover__namespace.Root, { open: open && !disabled, onOpenChange: (o) => !disabled && setOpen(o), children: [
|
|
5592
5850
|
/* @__PURE__ */ jsxRuntime.jsx(Popover__namespace.Trigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
5593
5851
|
"button",
|
|
@@ -5662,6 +5920,438 @@ function ColorPicker({
|
|
|
5662
5920
|
] });
|
|
5663
5921
|
}
|
|
5664
5922
|
|
|
5923
|
+
// src/form/path.ts
|
|
5924
|
+
function deepClone(v) {
|
|
5925
|
+
if (v === null || typeof v !== "object") return v;
|
|
5926
|
+
if (v instanceof Date) return new Date(v.getTime());
|
|
5927
|
+
if (Array.isArray(v)) return v.map(deepClone);
|
|
5928
|
+
const out = {};
|
|
5929
|
+
for (const k in v) out[k] = deepClone(v[k]);
|
|
5930
|
+
return out;
|
|
5931
|
+
}
|
|
5932
|
+
function getPath(obj, path) {
|
|
5933
|
+
if (!path) return obj;
|
|
5934
|
+
const parts = path.split(".");
|
|
5935
|
+
let cur = obj;
|
|
5936
|
+
for (const p of parts) {
|
|
5937
|
+
if (cur == null || typeof cur !== "object") return void 0;
|
|
5938
|
+
cur = cur[p];
|
|
5939
|
+
}
|
|
5940
|
+
return cur;
|
|
5941
|
+
}
|
|
5942
|
+
function setPath(obj, path, value) {
|
|
5943
|
+
const parts = path.split(".");
|
|
5944
|
+
const root = Array.isArray(obj) ? [...obj] : { ...obj ?? {} };
|
|
5945
|
+
let cur = root;
|
|
5946
|
+
for (let i = 0; i < parts.length - 1; i++) {
|
|
5947
|
+
const p = parts[i];
|
|
5948
|
+
const nextIsIndex = /^\d+$/.test(parts[i + 1]);
|
|
5949
|
+
const child = cur[p];
|
|
5950
|
+
const next = Array.isArray(child) ? [...child] : child && typeof child === "object" ? { ...child } : nextIsIndex ? [] : {};
|
|
5951
|
+
cur[p] = next;
|
|
5952
|
+
cur = next;
|
|
5953
|
+
}
|
|
5954
|
+
cur[parts[parts.length - 1]] = value;
|
|
5955
|
+
return root;
|
|
5956
|
+
}
|
|
5957
|
+
|
|
5958
|
+
// src/form/validate.ts
|
|
5959
|
+
function isEmpty(v) {
|
|
5960
|
+
return v == null || v === "" || v === false || Array.isArray(v) && v.length === 0;
|
|
5961
|
+
}
|
|
5962
|
+
var boundValue = (b) => typeof b === "number" ? b : b.value;
|
|
5963
|
+
var boundMessage = (b, fallback) => typeof b === "number" ? fallback : b.message ?? fallback;
|
|
5964
|
+
function isRequired(rules) {
|
|
5965
|
+
if (!rules) return false;
|
|
5966
|
+
const list = Array.isArray(rules) ? rules : [rules];
|
|
5967
|
+
return list.some((r) => !!r.required);
|
|
5968
|
+
}
|
|
5969
|
+
async function runFieldRules(value, rules, values) {
|
|
5970
|
+
if (!rules) return void 0;
|
|
5971
|
+
const list = Array.isArray(rules) ? rules : [rules];
|
|
5972
|
+
for (const rule of list) {
|
|
5973
|
+
if (rule.required && isEmpty(value)) {
|
|
5974
|
+
return typeof rule.required === "string" ? rule.required : rule.message ?? "This field is required";
|
|
5975
|
+
}
|
|
5976
|
+
if (isEmpty(value)) {
|
|
5977
|
+
if (rule.validate) {
|
|
5978
|
+
const res = await rule.validate(value, values);
|
|
5979
|
+
if (res) return typeof res === "string" ? res : rule.message ?? "Invalid value";
|
|
5980
|
+
}
|
|
5981
|
+
continue;
|
|
5982
|
+
}
|
|
5983
|
+
if (rule.pattern) {
|
|
5984
|
+
const re = rule.pattern instanceof RegExp ? rule.pattern : rule.pattern.value;
|
|
5985
|
+
const msg = rule.pattern instanceof RegExp ? rule.message ?? "Invalid format" : rule.pattern.message ?? rule.message ?? "Invalid format";
|
|
5986
|
+
if (typeof value === "string" && !re.test(value)) return msg;
|
|
5987
|
+
}
|
|
5988
|
+
if (rule.min != null && typeof value === "number") {
|
|
5989
|
+
const m = boundValue(rule.min);
|
|
5990
|
+
if (value < m) return boundMessage(rule.min, rule.message ?? `Must be at least ${m}`);
|
|
5991
|
+
}
|
|
5992
|
+
if (rule.max != null && typeof value === "number") {
|
|
5993
|
+
const m = boundValue(rule.max);
|
|
5994
|
+
if (value > m) return boundMessage(rule.max, rule.message ?? `Must be at most ${m}`);
|
|
5995
|
+
}
|
|
5996
|
+
if (rule.minLength != null) {
|
|
5997
|
+
const len = value?.length;
|
|
5998
|
+
const m = boundValue(rule.minLength);
|
|
5999
|
+
if (typeof len === "number" && len < m)
|
|
6000
|
+
return boundMessage(rule.minLength, rule.message ?? `Must be at least ${m} characters`);
|
|
6001
|
+
}
|
|
6002
|
+
if (rule.maxLength != null) {
|
|
6003
|
+
const len = value?.length;
|
|
6004
|
+
const m = boundValue(rule.maxLength);
|
|
6005
|
+
if (typeof len === "number" && len > m)
|
|
6006
|
+
return boundMessage(rule.maxLength, rule.message ?? `Must be at most ${m} characters`);
|
|
6007
|
+
}
|
|
6008
|
+
if (rule.validate) {
|
|
6009
|
+
const res = await rule.validate(value, values);
|
|
6010
|
+
if (res) return typeof res === "string" ? res : rule.message ?? "Invalid value";
|
|
6011
|
+
}
|
|
6012
|
+
}
|
|
6013
|
+
return void 0;
|
|
6014
|
+
}
|
|
6015
|
+
var patterns = {
|
|
6016
|
+
email: /^[^\s@]+@[^\s@]+\.[^\s@]+$/,
|
|
6017
|
+
url: /^https?:\/\/[^\s/$.?#].[^\s]*$/i,
|
|
6018
|
+
// Loose international phone: + and 7-15 digits, spaces/dashes allowed.
|
|
6019
|
+
phone: /^\+?[\d\s-]{7,15}$/,
|
|
6020
|
+
// Digits only.
|
|
6021
|
+
digits: /^\d+$/
|
|
6022
|
+
};
|
|
6023
|
+
|
|
6024
|
+
// src/form/store.ts
|
|
6025
|
+
var FormStore = class {
|
|
6026
|
+
listeners = /* @__PURE__ */ new Set();
|
|
6027
|
+
fieldCache = /* @__PURE__ */ new Map();
|
|
6028
|
+
values;
|
|
6029
|
+
errors = {};
|
|
6030
|
+
touched = {};
|
|
6031
|
+
submitted = false;
|
|
6032
|
+
validating = false;
|
|
6033
|
+
initialValues;
|
|
6034
|
+
rules;
|
|
6035
|
+
validateOn;
|
|
6036
|
+
// Field-array key bookkeeping (stable React keys across reorder/removal).
|
|
6037
|
+
keys = {};
|
|
6038
|
+
keySeq = 1;
|
|
6039
|
+
// Root snapshot — a new ref on every change, for form-level subscribers.
|
|
6040
|
+
rootSnap = { v: 0 };
|
|
6041
|
+
constructor(opts = {}) {
|
|
6042
|
+
this.initialValues = deepClone(opts.initialValues ?? {});
|
|
6043
|
+
this.values = deepClone(opts.initialValues ?? {});
|
|
6044
|
+
this.rules = { ...opts.rules ?? {} };
|
|
6045
|
+
this.validateOn = opts.validateOn ?? ["onChange", "onBlur", "onSubmit"];
|
|
6046
|
+
}
|
|
6047
|
+
// ── subscription ────────────────────────────────────────────────────────
|
|
6048
|
+
subscribe = (l) => {
|
|
6049
|
+
this.listeners.add(l);
|
|
6050
|
+
return () => {
|
|
6051
|
+
this.listeners.delete(l);
|
|
6052
|
+
};
|
|
6053
|
+
};
|
|
6054
|
+
emit() {
|
|
6055
|
+
this.rootSnap = { v: this.rootSnap.v + 1 };
|
|
6056
|
+
this.listeners.forEach((l) => l());
|
|
6057
|
+
}
|
|
6058
|
+
getRootSnapshot = () => this.rootSnap;
|
|
6059
|
+
getFieldSnapshot = (name) => {
|
|
6060
|
+
const value = getPath(this.values, name);
|
|
6061
|
+
const error = this.errors[name];
|
|
6062
|
+
const showError = (!!this.touched[name] || this.submitted) && error != null;
|
|
6063
|
+
const prev = this.fieldCache.get(name);
|
|
6064
|
+
if (prev && Object.is(prev.value, value) && prev.error === error && prev.showError === showError) {
|
|
6065
|
+
return prev.snap;
|
|
6066
|
+
}
|
|
6067
|
+
const snap = { value, error, showError };
|
|
6068
|
+
this.fieldCache.set(name, { value, error, showError, snap });
|
|
6069
|
+
return snap;
|
|
6070
|
+
};
|
|
6071
|
+
// ── rule registry (for dynamic / array fields) ──────────────────────────
|
|
6072
|
+
setRule(name, rules) {
|
|
6073
|
+
if (rules == null) delete this.rules[name];
|
|
6074
|
+
else this.rules[name] = rules;
|
|
6075
|
+
}
|
|
6076
|
+
removeRule(name) {
|
|
6077
|
+
delete this.rules[name];
|
|
6078
|
+
}
|
|
6079
|
+
getRule(name) {
|
|
6080
|
+
return this.rules[name];
|
|
6081
|
+
}
|
|
6082
|
+
// ── reads ────────────────────────────────────────────────────────────────
|
|
6083
|
+
getValues = () => this.values;
|
|
6084
|
+
getValue = (name) => getPath(this.values, name);
|
|
6085
|
+
get isValid() {
|
|
6086
|
+
return Object.values(this.errors).every((e) => !e);
|
|
6087
|
+
}
|
|
6088
|
+
// ── writes ────────────────────────────────────────────────────────────────
|
|
6089
|
+
setValue = (name, value, opts = {}) => {
|
|
6090
|
+
this.values = setPath(this.values, name, value);
|
|
6091
|
+
if (opts.touch) this.touched = { ...this.touched, [name]: true };
|
|
6092
|
+
this.emit();
|
|
6093
|
+
const shouldValidate = opts.validate ?? this.validateOn.includes("onChange");
|
|
6094
|
+
if (shouldValidate) void this.validateField(name);
|
|
6095
|
+
};
|
|
6096
|
+
setValues = (patch, opts = {}) => {
|
|
6097
|
+
for (const k of Object.keys(patch)) this.values = setPath(this.values, k, patch[k]);
|
|
6098
|
+
this.emit();
|
|
6099
|
+
if (opts.validate) void this.validateAll();
|
|
6100
|
+
};
|
|
6101
|
+
setError = (name, error) => {
|
|
6102
|
+
if (this.errors[name] === error) return;
|
|
6103
|
+
this.errors = { ...this.errors, [name]: error || void 0 };
|
|
6104
|
+
this.emit();
|
|
6105
|
+
};
|
|
6106
|
+
touch = (name, opts = {}) => {
|
|
6107
|
+
if (!this.touched[name]) {
|
|
6108
|
+
this.touched = { ...this.touched, [name]: true };
|
|
6109
|
+
this.emit();
|
|
6110
|
+
}
|
|
6111
|
+
if (opts.validate ?? this.validateOn.includes("onBlur")) void this.validateField(name);
|
|
6112
|
+
};
|
|
6113
|
+
setSubmitted = (v) => {
|
|
6114
|
+
this.submitted = v;
|
|
6115
|
+
this.emit();
|
|
6116
|
+
};
|
|
6117
|
+
// ── validation ─────────────────────────────────────────────────────────────
|
|
6118
|
+
async validateField(name) {
|
|
6119
|
+
const err = await runFieldRules(getPath(this.values, name), this.rules[name], this.values);
|
|
6120
|
+
this.setError(name, err);
|
|
6121
|
+
return err;
|
|
6122
|
+
}
|
|
6123
|
+
async validateAll() {
|
|
6124
|
+
this.validating = true;
|
|
6125
|
+
this.emit();
|
|
6126
|
+
const names = Object.keys(this.rules);
|
|
6127
|
+
const entries = await Promise.all(
|
|
6128
|
+
names.map(async (n) => [n, await runFieldRules(getPath(this.values, n), this.rules[n], this.values)])
|
|
6129
|
+
);
|
|
6130
|
+
const errors = {};
|
|
6131
|
+
for (const [n, e] of entries) errors[n] = e;
|
|
6132
|
+
this.errors = errors;
|
|
6133
|
+
this.validating = false;
|
|
6134
|
+
this.emit();
|
|
6135
|
+
return errors;
|
|
6136
|
+
}
|
|
6137
|
+
reset = (values) => {
|
|
6138
|
+
this.values = deepClone(values ?? this.initialValues);
|
|
6139
|
+
this.errors = {};
|
|
6140
|
+
this.touched = {};
|
|
6141
|
+
this.submitted = false;
|
|
6142
|
+
this.keys = {};
|
|
6143
|
+
this.fieldCache.clear();
|
|
6144
|
+
this.emit();
|
|
6145
|
+
};
|
|
6146
|
+
// ── field arrays ───────────────────────────────────────────────────────────
|
|
6147
|
+
getKeys(name) {
|
|
6148
|
+
const arr = getPath(this.values, name) ?? [];
|
|
6149
|
+
let keys = this.keys[name];
|
|
6150
|
+
if (!keys || keys.length !== arr.length) {
|
|
6151
|
+
keys = arr.map((_, i) => keys && keys[i] != null ? keys[i] : this.keySeq++);
|
|
6152
|
+
this.keys[name] = keys;
|
|
6153
|
+
}
|
|
6154
|
+
return keys;
|
|
6155
|
+
}
|
|
6156
|
+
arrayAppend = (name, item = {}) => {
|
|
6157
|
+
const arr = [...getPath(this.values, name) ?? []];
|
|
6158
|
+
arr.push(item);
|
|
6159
|
+
this.keys[name] = [...this.getKeys(name), this.keySeq++];
|
|
6160
|
+
this.setValue(name, arr, { validate: false });
|
|
6161
|
+
};
|
|
6162
|
+
arrayRemove = (name, index) => {
|
|
6163
|
+
const arr = [...getPath(this.values, name) ?? []];
|
|
6164
|
+
arr.splice(index, 1);
|
|
6165
|
+
const k = [...this.getKeys(name)];
|
|
6166
|
+
k.splice(index, 1);
|
|
6167
|
+
this.keys[name] = k;
|
|
6168
|
+
this.clearBranch(name);
|
|
6169
|
+
this.setValue(name, arr, { validate: false });
|
|
6170
|
+
};
|
|
6171
|
+
arrayMove = (name, from, to) => {
|
|
6172
|
+
const arr = [...getPath(this.values, name) ?? []];
|
|
6173
|
+
if (from < 0 || to < 0 || from >= arr.length || to >= arr.length) return;
|
|
6174
|
+
const [moved] = arr.splice(from, 1);
|
|
6175
|
+
arr.splice(to, 0, moved);
|
|
6176
|
+
const k = [...this.getKeys(name)];
|
|
6177
|
+
const [mk] = k.splice(from, 1);
|
|
6178
|
+
k.splice(to, 0, mk);
|
|
6179
|
+
this.keys[name] = k;
|
|
6180
|
+
this.clearBranch(name);
|
|
6181
|
+
this.setValue(name, arr, { validate: false });
|
|
6182
|
+
};
|
|
6183
|
+
/** Drop any errors/touched flags under `name.` — used when an array shifts. */
|
|
6184
|
+
clearBranch(name) {
|
|
6185
|
+
const prefix = name + ".";
|
|
6186
|
+
const errors = {};
|
|
6187
|
+
for (const k of Object.keys(this.errors)) if (!k.startsWith(prefix)) errors[k] = this.errors[k];
|
|
6188
|
+
const touched = {};
|
|
6189
|
+
for (const k of Object.keys(this.touched)) if (!k.startsWith(prefix)) touched[k] = this.touched[k];
|
|
6190
|
+
this.errors = errors;
|
|
6191
|
+
this.touched = touched;
|
|
6192
|
+
}
|
|
6193
|
+
};
|
|
6194
|
+
|
|
6195
|
+
// src/form/bindings.ts
|
|
6196
|
+
var getTarget = (arg) => {
|
|
6197
|
+
const t = arg?.target;
|
|
6198
|
+
return t && typeof t === "object" ? t : void 0;
|
|
6199
|
+
};
|
|
6200
|
+
var ADAPTERS = {
|
|
6201
|
+
value: { prop: "value", toValue: (v) => v, applyEmpty: false, empty: void 0 },
|
|
6202
|
+
native: { prop: "value", toValue: (e) => getTarget(e)?.value, applyEmpty: true, empty: "" },
|
|
6203
|
+
checked: { prop: "checked", toValue: (e) => getTarget(e)?.checked, applyEmpty: true, empty: false },
|
|
6204
|
+
target: { prop: "value", toValue: (e) => getTarget(e)?.value, applyEmpty: false, empty: void 0 }
|
|
6205
|
+
};
|
|
6206
|
+
function buildBindings(store, name, kind, snap) {
|
|
6207
|
+
const a = ADAPTERS[kind];
|
|
6208
|
+
const raw = snap.value;
|
|
6209
|
+
const value = a.applyEmpty ? raw ?? a.empty : raw;
|
|
6210
|
+
return {
|
|
6211
|
+
name,
|
|
6212
|
+
id: name,
|
|
6213
|
+
htmlFor: name,
|
|
6214
|
+
required: isRequired(store.getRule(name)) || void 0,
|
|
6215
|
+
errorMessage: snap.showError ? snap.error : void 0,
|
|
6216
|
+
[a.prop]: value,
|
|
6217
|
+
onChange: (arg) => store.setValue(name, a.toValue(arg), { touch: true }),
|
|
6218
|
+
onBlur: () => store.touch(name)
|
|
6219
|
+
};
|
|
6220
|
+
}
|
|
6221
|
+
|
|
6222
|
+
// src/form/useForm.ts
|
|
6223
|
+
function useForm(options = {}) {
|
|
6224
|
+
const ref = React8.useRef(null);
|
|
6225
|
+
if (ref.current === null) ref.current = new FormStore(options);
|
|
6226
|
+
const store = ref.current;
|
|
6227
|
+
React8.useSyncExternalStore(store.subscribe, store.getRootSnapshot, store.getRootSnapshot);
|
|
6228
|
+
const make = React8.useCallback(
|
|
6229
|
+
(kind) => (name, rules) => {
|
|
6230
|
+
if (rules !== void 0) store.setRule(name, rules);
|
|
6231
|
+
return buildBindings(store, name, kind, store.getFieldSnapshot(name));
|
|
6232
|
+
},
|
|
6233
|
+
[store]
|
|
6234
|
+
);
|
|
6235
|
+
return {
|
|
6236
|
+
store,
|
|
6237
|
+
values: store.values,
|
|
6238
|
+
errors: store.errors,
|
|
6239
|
+
touched: store.touched,
|
|
6240
|
+
submitted: store.submitted,
|
|
6241
|
+
isSubmitting: store.validating,
|
|
6242
|
+
isValid: store.isValid,
|
|
6243
|
+
getValue: store.getValue,
|
|
6244
|
+
getValues: store.getValues,
|
|
6245
|
+
setValue: (name, value) => store.setValue(name, value),
|
|
6246
|
+
setValues: (patch) => store.setValues(patch),
|
|
6247
|
+
setError: store.setError,
|
|
6248
|
+
validateField: (name) => store.validateField(name),
|
|
6249
|
+
validateAll: () => store.validateAll(),
|
|
6250
|
+
reset: store.reset,
|
|
6251
|
+
field: make("value"),
|
|
6252
|
+
fieldNative: make("native"),
|
|
6253
|
+
fieldChecked: make("checked"),
|
|
6254
|
+
fieldTarget: make("target")
|
|
6255
|
+
};
|
|
6256
|
+
}
|
|
6257
|
+
var FormContext = React8.createContext(null);
|
|
6258
|
+
function useFormStore() {
|
|
6259
|
+
const store = React8.useContext(FormContext);
|
|
6260
|
+
if (!store) {
|
|
6261
|
+
throw new Error("useFormStore must be used within a <Form>. Did you forget to wrap your fields?");
|
|
6262
|
+
}
|
|
6263
|
+
return store;
|
|
6264
|
+
}
|
|
6265
|
+
function Form({
|
|
6266
|
+
form,
|
|
6267
|
+
onFinish,
|
|
6268
|
+
onFinishFailed,
|
|
6269
|
+
action,
|
|
6270
|
+
children,
|
|
6271
|
+
...rest
|
|
6272
|
+
}) {
|
|
6273
|
+
const ref = React8.useRef(null);
|
|
6274
|
+
const bypass = React8.useRef(false);
|
|
6275
|
+
const handleSubmit = async (e) => {
|
|
6276
|
+
if (bypass.current) {
|
|
6277
|
+
bypass.current = false;
|
|
6278
|
+
return;
|
|
6279
|
+
}
|
|
6280
|
+
e.preventDefault();
|
|
6281
|
+
const store = form.store;
|
|
6282
|
+
store.setSubmitted(true);
|
|
6283
|
+
const errors = await store.validateAll();
|
|
6284
|
+
const hasError = Object.values(errors).some(Boolean);
|
|
6285
|
+
if (hasError) {
|
|
6286
|
+
onFinishFailed?.(errors, store.getValues());
|
|
6287
|
+
focusFirstError(ref.current, errors);
|
|
6288
|
+
return;
|
|
6289
|
+
}
|
|
6290
|
+
if (onFinish) {
|
|
6291
|
+
await onFinish(store.getValues());
|
|
6292
|
+
return;
|
|
6293
|
+
}
|
|
6294
|
+
if (typeof action === "function") {
|
|
6295
|
+
action(new FormData(ref.current));
|
|
6296
|
+
return;
|
|
6297
|
+
}
|
|
6298
|
+
if (typeof action === "string") {
|
|
6299
|
+
bypass.current = true;
|
|
6300
|
+
ref.current.requestSubmit();
|
|
6301
|
+
}
|
|
6302
|
+
};
|
|
6303
|
+
return /* @__PURE__ */ jsxRuntime.jsx(FormContext.Provider, { value: form.store, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
6304
|
+
"form",
|
|
6305
|
+
{
|
|
6306
|
+
ref,
|
|
6307
|
+
noValidate: true,
|
|
6308
|
+
action: typeof action === "string" ? action : void 0,
|
|
6309
|
+
onSubmit: handleSubmit,
|
|
6310
|
+
...rest,
|
|
6311
|
+
children
|
|
6312
|
+
}
|
|
6313
|
+
) });
|
|
6314
|
+
}
|
|
6315
|
+
function focusFirstError(formEl, errors) {
|
|
6316
|
+
if (!formEl) return;
|
|
6317
|
+
const firstName = Object.keys(errors).find((k) => errors[k]);
|
|
6318
|
+
if (!firstName) return;
|
|
6319
|
+
const el = formEl.querySelector(`[name="${CSS.escape(firstName)}"], #${CSS.escape(firstName)}`);
|
|
6320
|
+
el?.focus();
|
|
6321
|
+
}
|
|
6322
|
+
function useFormField(name, options = {}) {
|
|
6323
|
+
const store = useFormStore();
|
|
6324
|
+
const { kind = "value", rules } = options;
|
|
6325
|
+
if (rules !== void 0 && store.getRule(name) !== rules) store.setRule(name, rules);
|
|
6326
|
+
React8.useEffect(() => {
|
|
6327
|
+
return () => {
|
|
6328
|
+
if (rules !== void 0) store.removeRule(name);
|
|
6329
|
+
};
|
|
6330
|
+
}, [store, name]);
|
|
6331
|
+
const snap = React8.useSyncExternalStore(
|
|
6332
|
+
store.subscribe,
|
|
6333
|
+
() => store.getFieldSnapshot(name)
|
|
6334
|
+
);
|
|
6335
|
+
return buildBindings(store, name, kind, snap);
|
|
6336
|
+
}
|
|
6337
|
+
function FormField({ name, kind, rules, children }) {
|
|
6338
|
+
const field = useFormField(name, { kind, rules });
|
|
6339
|
+
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: children(field) });
|
|
6340
|
+
}
|
|
6341
|
+
function useFieldArray(name) {
|
|
6342
|
+
const store = useFormStore();
|
|
6343
|
+
React8.useSyncExternalStore(store.subscribe, store.getRootSnapshot, store.getRootSnapshot);
|
|
6344
|
+
const arr = store.getValue(name) ?? [];
|
|
6345
|
+
const keys = store.getKeys(name);
|
|
6346
|
+
return {
|
|
6347
|
+
fields: arr.map((_, i) => ({ key: keys[i], name: `${name}.${i}`, index: i })),
|
|
6348
|
+
append: (item = {}) => store.arrayAppend(name, item),
|
|
6349
|
+
remove: (index) => store.arrayRemove(name, index),
|
|
6350
|
+
move: (from, to) => store.arrayMove(name, from, to),
|
|
6351
|
+
replace: (items) => store.setValue(name, items, { validate: false })
|
|
6352
|
+
};
|
|
6353
|
+
}
|
|
6354
|
+
|
|
5665
6355
|
Object.defineProperty(exports, "COLORS", {
|
|
5666
6356
|
enumerable: true,
|
|
5667
6357
|
get: function () { return chunk255PCZIW_cjs.colors_default; }
|
|
@@ -5694,8 +6384,14 @@ exports.Drawer = Drawer;
|
|
|
5694
6384
|
exports.Dropdown = Dropdown;
|
|
5695
6385
|
exports.FadingBase = FadingBase;
|
|
5696
6386
|
exports.Field = Field;
|
|
6387
|
+
exports.FieldHelpIcon = FieldHelpIcon;
|
|
6388
|
+
exports.FieldLabel = FieldLabel;
|
|
5697
6389
|
exports.FileInput = FileInput;
|
|
5698
6390
|
exports.Flex = Flex;
|
|
6391
|
+
exports.Form = Form;
|
|
6392
|
+
exports.FormContext = FormContext;
|
|
6393
|
+
exports.FormField = FormField;
|
|
6394
|
+
exports.FormStore = FormStore;
|
|
5699
6395
|
exports.Grid = Grid2;
|
|
5700
6396
|
exports.GridCard = GridCard;
|
|
5701
6397
|
exports.Icon = icons_default;
|
|
@@ -5738,6 +6434,13 @@ exports.TreeSelect = TreeSelect;
|
|
|
5738
6434
|
exports.Typography = Typography;
|
|
5739
6435
|
exports.Wizard = Wizard;
|
|
5740
6436
|
exports.fieldShell = fieldShell;
|
|
6437
|
+
exports.isRequired = isRequired;
|
|
6438
|
+
exports.patterns = patterns;
|
|
6439
|
+
exports.runFieldRules = runFieldRules;
|
|
6440
|
+
exports.useFieldArray = useFieldArray;
|
|
6441
|
+
exports.useForm = useForm;
|
|
6442
|
+
exports.useFormField = useFormField;
|
|
6443
|
+
exports.useFormStore = useFormStore;
|
|
5741
6444
|
exports.useNotification = useNotification;
|
|
5742
6445
|
//# sourceMappingURL=index.cjs.map
|
|
5743
6446
|
//# sourceMappingURL=index.cjs.map
|