@fiestaboard/ui 3.0.1 → 3.1.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.
@@ -0,0 +1,59 @@
1
+ import * as React from "react";
2
+ export interface JsonTreeLabels {
3
+ /**
4
+ * Accessible name (and tooltip) for a leaf's select button.
5
+ * Default: `` (path) => `Use path: ${path}` ``
6
+ */
7
+ selectPath?: (path: string) => string;
8
+ /**
9
+ * Accessible name for a branch's expand/collapse toggle — the visible
10
+ * `{3}` / `[2]` summary is decorative and hidden from assistive tech.
11
+ * Default: `` (path, count) => `${path} (${count} items)` ``
12
+ */
13
+ toggleNode?: (path: string, count: number) => string;
14
+ /** Stands in for the path of the root node, which has none. Default: `"root"` */
15
+ root?: string;
16
+ /** Announced politely after a leaf is selected. Default: `"Path copied"` */
17
+ selected?: string;
18
+ /** Shown in place of children for an empty object or array. Default: `"empty"` */
19
+ empty?: string;
20
+ }
21
+ export interface JsonTreeProps {
22
+ /** Any JSON-shaped value. Objects and arrays branch; everything else is a leaf. */
23
+ data: unknown;
24
+ /**
25
+ * Dot/bracket path of `data` itself, prefixed onto every child path.
26
+ * Defaults to `""`, which makes children read `a.b[0]` rather than `.a.b[0]`.
27
+ */
28
+ path?: string;
29
+ /**
30
+ * Called with the dot/bracket path of the leaf the user picked and its
31
+ * value. Omit for a read-only tree: the per-leaf select buttons disappear.
32
+ */
33
+ onSelect?: (path: string, value: unknown) => void;
34
+ /** Expand this node on first render. Default: `false`. */
35
+ defaultExpanded?: boolean;
36
+ /**
37
+ * Expand the first N levels on first render — `2` opens this node and its
38
+ * direct branch children. Default: `0`.
39
+ */
40
+ defaultExpandedDepth?: number;
41
+ labels?: JsonTreeLabels;
42
+ className?: string;
43
+ }
44
+ /**
45
+ * A collapsible JSON tree whose every leaf offers its own dot/bracket path.
46
+ *
47
+ * It knows nothing about plugins, settings, or where the data came from — it
48
+ * renders a value and reports the path the user picked — so any surface that
49
+ * needs "show me this response and let me point at part of it" can use it.
50
+ *
51
+ * Branches are nested WAI-ARIA **disclosures**, not a `role="tree"`: a correct
52
+ * tree owes callers a roving tabindex and full arrow-key navigation across a
53
+ * recursive component boundary, and a half-built one is worse than none — it
54
+ * would strip Tab access from the nested select buttons while advertising an
55
+ * interaction contract the widget doesn't honour. Disclosures are keyboard
56
+ * complete out of the box (Tab to reach, Enter/Space to toggle); Arrow
57
+ * Left/Right are wired up on top as the affordance tree users reach for.
58
+ */
59
+ export declare function JsonTree({ data, path, onSelect, defaultExpanded, defaultExpandedDepth, labels, className, }: JsonTreeProps): React.JSX.Element;
@@ -0,0 +1,122 @@
1
+ "use client";
2
+ import { cn as e } from "../../lib/utils.js";
3
+ import { Check as t, ChevronDown as n, ChevronRight as r, Copy as i } from "lucide-react";
4
+ import * as a from "react";
5
+ import { jsx as o, jsxs as s } from "react/jsx-runtime";
6
+ //#region src/components/containment/json-tree.tsx
7
+ var c = {
8
+ string: "text-success",
9
+ number: "text-warning",
10
+ boolean: "text-warning",
11
+ nullish: "text-muted-foreground italic",
12
+ other: "text-foreground"
13
+ }, l = "text-info", u = "text-tag-variable-foreground", d = "-ml-1 flex w-full items-center gap-1 rounded-sm px-1 py-0.5 text-left text-xs text-muted-foreground transition-colors duration-control hover:bg-muted/60 outline-none focus-visible:ring-ring/50 focus-visible:ring-[3px]", f = "shrink-0 rounded-sm p-0.5 opacity-0 transition-opacity duration-control hover:bg-muted group-hover:opacity-100 focus-visible:opacity-100 outline-none focus-visible:ring-ring/50 focus-visible:ring-[3px]", p = 1500;
14
+ function m(e) {
15
+ return typeof e == "object" && !!e;
16
+ }
17
+ function h(e) {
18
+ if (e == null) return c.nullish;
19
+ switch (typeof e) {
20
+ case "string": return c.string;
21
+ case "number":
22
+ case "bigint": return c.number;
23
+ case "boolean": return c.boolean;
24
+ default: return c.other;
25
+ }
26
+ }
27
+ function g(e) {
28
+ return e == null ? "null" : typeof e == "string" ? `"${e}"` : String(e);
29
+ }
30
+ function _({ data: c, path: v = "", onSelect: y, defaultExpanded: b = !1, defaultExpandedDepth: x = 0, labels: S, className: C }) {
31
+ let { selectPath: w = (e) => `Use path: ${e}`, toggleNode: T = (e, t) => `${e} (${t} ${t === 1 ? "item" : "items"})`, root: E = "root", selected: D = "Path copied", empty: O = "empty" } = S ?? {}, k = x > 0, [A, j] = a.useState(b || k), [M, N] = a.useState(b || k), [P, F] = a.useState(null), I = a.useId(), L = a.useRef(null);
32
+ a.useEffect(() => () => {
33
+ L.current !== null && clearTimeout(L.current);
34
+ }, []);
35
+ function R(e, t) {
36
+ y?.(e, t), F(e), L.current !== null && clearTimeout(L.current), L.current = setTimeout(() => F(null), p);
37
+ }
38
+ function z() {
39
+ j((e) => !e), N(!0);
40
+ }
41
+ function B(e) {
42
+ e.key === "ArrowRight" && !A ? (e.preventDefault(), z()) : e.key === "ArrowLeft" && A && (e.preventDefault(), j(!1));
43
+ }
44
+ if (!m(c)) return /* @__PURE__ */ o("span", {
45
+ "data-slot": "json-tree-value",
46
+ className: e("font-mono text-xs", h(c), C),
47
+ children: g(c)
48
+ });
49
+ let V = Array.isArray(c), H = V ? c.map((e, t) => [String(t), e]) : Object.entries(c), U = V ? `[${H.length}]` : `{${H.length}}`, W = Math.max(0, x - 1);
50
+ return /* @__PURE__ */ s("div", {
51
+ "data-slot": "json-tree",
52
+ className: e("ml-1", C),
53
+ children: [
54
+ /* @__PURE__ */ s("button", {
55
+ type: "button",
56
+ "aria-expanded": A,
57
+ "aria-controls": M ? I : void 0,
58
+ onClick: z,
59
+ onKeyDown: B,
60
+ className: d,
61
+ children: [
62
+ o(A ? n : r, { className: "size-3 shrink-0" }),
63
+ /* @__PURE__ */ o("span", {
64
+ "aria-hidden": "true",
65
+ className: "font-mono",
66
+ children: U
67
+ }),
68
+ /* @__PURE__ */ o("span", {
69
+ className: "sr-only",
70
+ children: T(v || E, H.length)
71
+ })
72
+ ]
73
+ }),
74
+ M && /* @__PURE__ */ o("span", {
75
+ role: "status",
76
+ className: "sr-only",
77
+ children: P === null ? "" : D
78
+ }),
79
+ M && /* @__PURE__ */ s("ul", {
80
+ id: I,
81
+ hidden: !A,
82
+ className: "ml-3 flex flex-col gap-0.5 border-l border-border pl-2 [&[hidden]]:hidden",
83
+ children: [H.length === 0 && /* @__PURE__ */ o("li", {
84
+ className: "text-xs italic text-muted-foreground",
85
+ children: O
86
+ }), H.map(([n, r]) => {
87
+ let a = V ? `${v}[${n}]` : v ? `${v}.${n}` : n, c = V ? `[${n}]:` : `${n}:`;
88
+ return /* @__PURE__ */ s("li", {
89
+ className: "flex items-start gap-1",
90
+ children: [/* @__PURE__ */ o("span", {
91
+ className: e("shrink-0 pt-0.5 font-mono text-xs font-medium", V ? u : l),
92
+ children: c
93
+ }), m(r) ? /* @__PURE__ */ o(_, {
94
+ data: r,
95
+ path: a,
96
+ onSelect: y,
97
+ defaultExpandedDepth: W,
98
+ labels: S
99
+ }) : /* @__PURE__ */ s("span", {
100
+ className: "group flex min-w-0 items-center gap-1",
101
+ children: [/* @__PURE__ */ o("span", {
102
+ className: e("truncate font-mono text-xs", h(r)),
103
+ children: g(r)
104
+ }), y && /* @__PURE__ */ o("button", {
105
+ type: "button",
106
+ onClick: () => R(a, r),
107
+ "aria-label": w(a),
108
+ title: w(a),
109
+ className: f,
110
+ children: P === a ? /* @__PURE__ */ o(t, { className: "size-3 text-success" }) : /* @__PURE__ */ o(i, { className: "size-3 text-muted-foreground" })
111
+ })]
112
+ })]
113
+ }, n);
114
+ })]
115
+ })
116
+ ]
117
+ });
118
+ }
119
+ //#endregion
120
+ export { _ as JsonTree };
121
+
122
+ //# sourceMappingURL=json-tree.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json-tree.js","names":[],"sources":["../../../src/components/containment/json-tree.tsx"],"mappings":"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"}
@@ -0,0 +1,49 @@
1
+ import { type VariantProps } from "class-variance-authority";
2
+ import * as React from "react";
3
+ declare const statusDotVariants: (props?: ({
4
+ status?: "info" | "success" | "warning" | "danger" | "neutral" | null | undefined;
5
+ size?: "sm" | "md" | "lg" | null | undefined;
6
+ pulse?: boolean | null | undefined;
7
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
8
+ export interface StatusDotProps extends Omit<React.ComponentProps<"span">, "children" | "color">, VariantProps<typeof statusDotVariants> {
9
+ /**
10
+ * Soft halo in the dot's own colour, colour-mixed to 50%. Purely
11
+ * decorative emphasis — it is never the only signal of anything.
12
+ */
13
+ glow?: boolean;
14
+ /**
15
+ * Text announced to assistive technology.
16
+ *
17
+ * Defaults to `null` — a DECORATIVE dot, `aria-hidden`, for the common case
18
+ * where the dot sits immediately beside text that already states the status
19
+ * ("● Running"). Announcing it there would produce "Running Running", and a
20
+ * bare unlabelled dot in the tree is worse than none.
21
+ *
22
+ * Pass a string for a STANDALONE dot that is the only carrier of the state
23
+ * (a header service indicator, a cell in a dense table). The dot then gets
24
+ * `role="status"` and an `sr-only` label, so the state is announced when it
25
+ * changes — which is also what keeps it clear of WCAG 1.4.1 (Use of Colour),
26
+ * since hue alone would otherwise be the entire message.
27
+ *
28
+ * There is deliberately no default label per status: "success" is not a
29
+ * sentence, and the real one ("Service running", "3 boards offline") is
30
+ * always the caller's to write.
31
+ */
32
+ label?: string | null;
33
+ }
34
+ /**
35
+ * Small coloured state indicator.
36
+ *
37
+ * Two supported shapes, and the `label` prop is what selects between them:
38
+ *
39
+ * <StatusDot status="success" /> Running decorative, aria-hidden
40
+ * <StatusDot status="success" label="Running" /> standalone, role="status"
41
+ *
42
+ * `role="status"` is a polite live region: the label is announced when it
43
+ * changes, which is the right behaviour for a dot tracking a connection. For
44
+ * a dot describing something static (a legend swatch, a row that never
45
+ * updates in place) pass `role="img"` — props spread over the computed
46
+ * attributes, so the override lands.
47
+ */
48
+ declare function StatusDot({ className, status, size, pulse, glow, label, style, ...props }: StatusDotProps): React.JSX.Element;
49
+ export { StatusDot, statusDotVariants };
@@ -0,0 +1,58 @@
1
+ import { cn as e } from "../../lib/utils.js";
2
+ import "react";
3
+ import { jsx as t } from "react/jsx-runtime";
4
+ import { cva as n } from "class-variance-authority";
5
+ //#region src/components/feedback/status-dot.tsx
6
+ var r = n("inline-block shrink-0 rounded-full align-middle transition-[background-color,box-shadow] duration-control", {
7
+ variants: {
8
+ status: {
9
+ success: "bg-success [--status-dot-color:var(--color-success)]",
10
+ warning: "bg-warning [--status-dot-color:var(--color-warning)]",
11
+ danger: "bg-destructive [--status-dot-color:var(--color-destructive)]",
12
+ info: "bg-info [--status-dot-color:var(--color-info)]",
13
+ neutral: "bg-muted-foreground [--status-dot-color:var(--color-muted-foreground)]"
14
+ },
15
+ size: {
16
+ sm: "size-1.5 [--status-dot-glow:4px]",
17
+ md: "size-2 [--status-dot-glow:6px]",
18
+ lg: "size-3 [--status-dot-glow:8px]"
19
+ },
20
+ pulse: {
21
+ true: "animate-pulse motion-reduce:animate-none",
22
+ false: ""
23
+ }
24
+ },
25
+ defaultVariants: {
26
+ status: "neutral",
27
+ size: "md",
28
+ pulse: !1
29
+ }
30
+ }), i = { boxShadow: "0 0 var(--status-dot-glow) color-mix(in oklch, var(--status-dot-color) 50%, transparent)" };
31
+ function a({ className: n, status: a = "neutral", size: o = "md", pulse: s = !1, glow: c = !1, label: l = null, style: u, ...d }) {
32
+ let f = l == null;
33
+ return /* @__PURE__ */ t("span", {
34
+ "data-slot": "status-dot",
35
+ "data-status": a,
36
+ "data-size": o,
37
+ role: f ? void 0 : "status",
38
+ "aria-hidden": f || void 0,
39
+ className: e(r({
40
+ status: a,
41
+ size: o,
42
+ pulse: s
43
+ }), n),
44
+ style: c ? {
45
+ ...i,
46
+ ...u
47
+ } : u,
48
+ ...d,
49
+ children: f ? null : /* @__PURE__ */ t("span", {
50
+ className: "sr-only",
51
+ children: l
52
+ })
53
+ });
54
+ }
55
+ //#endregion
56
+ export { a as StatusDot, r as statusDotVariants };
57
+
58
+ //# sourceMappingURL=status-dot.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status-dot.js","names":[],"sources":["../../../src/components/feedback/status-dot.tsx"],"mappings":";;;;;AAkBA,IAAM,IAAoB,EACxB,6GACA;CACE,UAAU;EACR,QAAQ;GACN,SAAS;GACT,SAAS;GACT,QAAQ;GACR,MAAM;GACN,SAAS;EACX;EAIA,MAAM;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;EACN;EAOA,OAAO;GACL,MAAM;GACN,OAAO;EACT;CACF;CACA,iBAAiB;EACf,QAAQ;EACR,MAAM;EACN,OAAO;CACT;AACF,CACF,GAMM,IAAkC,EACtC,WAAW,2FACb;AA4CA,SAAS,EAAU,EACjB,cACA,YAAS,WACT,UAAO,MACP,WAAQ,IACR,UAAO,IACP,WAAQ,MACR,UACA,GAAG,KACc;CACjB,IAAM,IAAa,KAAS;CAC5B,OACE,kBAAC,QAAD;EACE,aAAU;EACV,eAAa;EACb,aAAW;EACX,MAAM,IAAa,KAAA,IAAY;EAC/B,eAAa,KAAc,KAAA;EAC3B,WAAW,EAAG,EAAkB;GAAE;GAAQ;GAAM;EAAM,CAAC,GAAG,CAAS;EAEnE,OAAO,IAAO;GAAE,GAAG;GAAY,GAAG;EAAM,IAAI;EAC5C,GAAI;EASH,UAAA,IAAa,OAAO,kBAAC,QAAD;GAAM,WAAU;GAAW,UAAA;EAAY,CAAA;CACxD,CAAA;AAEV"}
@@ -0,0 +1,38 @@
1
+ import * as React from "react";
2
+ import { type InputProps } from "./input";
3
+ export interface SecretInputProps extends Omit<InputProps, "type"> {
4
+ /**
5
+ * Accessible name for the toggle while the secret is masked — i.e. the
6
+ * action the button performs. Defaults to English "Show"; apps that
7
+ * localize pass their own string (this package never depends on i18n).
8
+ */
9
+ showLabel?: string;
10
+ /** Accessible name for the toggle while the secret is revealed. Default "Hide". */
11
+ hideLabel?: string;
12
+ /** Initial visibility for the uncontrolled case. */
13
+ defaultVisible?: boolean;
14
+ /** Controlled visibility; pair with {@link SecretInputProps.onVisibleChange}. */
15
+ visible?: boolean;
16
+ /** Fired with the next visibility whenever the toggle is activated. */
17
+ onVisibleChange?: (visible: boolean) => void;
18
+ /**
19
+ * Disables only the toggle, leaving the field editable. For write-only
20
+ * secrets the server returns a placeholder (`"***"`) rather than the value,
21
+ * so there is nothing to reveal — but the user may still type a new one.
22
+ */
23
+ revealDisabled?: boolean;
24
+ /** Classes for the relative wrapper (e.g. `flex-1` in a settings row). */
25
+ containerClassName?: string;
26
+ }
27
+ /**
28
+ * Password/token field with a reveal toggle.
29
+ *
30
+ * Composes {@link Input} rather than re-declaring a bordered control, so the
31
+ * field can never drift from the design system's control tokens, and mounts
32
+ * the toggle inside the field as a ghost icon {@link Button}.
33
+ *
34
+ * Value styling defaults to `font-mono` — secrets are keys and tokens, where
35
+ * character-level legibility matters — and is overridable through `className`.
36
+ */
37
+ declare function SecretInput({ className, containerClassName, showLabel, hideLabel, defaultVisible, visible: visibleProp, onVisibleChange, revealDisabled, disabled, ref, ...props }: SecretInputProps): React.JSX.Element;
38
+ export { SecretInput };
@@ -0,0 +1,42 @@
1
+ "use client";
2
+ import { cn as e } from "../../lib/utils.js";
3
+ import { Button as t } from "./button.js";
4
+ import { Input as n } from "./input.js";
5
+ import { Eye as r, EyeOff as i } from "lucide-react";
6
+ import * as a from "react";
7
+ import { jsx as o, jsxs as s } from "react/jsx-runtime";
8
+ //#region src/components/forms/secret-input.tsx
9
+ function c({ className: c, containerClassName: l, showLabel: u = "Show", hideLabel: d = "Hide", defaultVisible: f = !1, visible: p, onVisibleChange: m, revealDisabled: h = !1, disabled: g, ref: _, ...v }) {
10
+ let [y, b] = a.useState(f), x = p !== void 0, S = (x ? p : y) && !h, C = () => {
11
+ let e = !S;
12
+ x || b(e), m?.(e);
13
+ }, w = S ? i : r;
14
+ return /* @__PURE__ */ s("div", {
15
+ "data-slot": "secret-input",
16
+ "data-visible": S ? "" : void 0,
17
+ className: e("relative w-full", l),
18
+ children: [/* @__PURE__ */ o(n, {
19
+ ref: _,
20
+ type: S ? "text" : "password",
21
+ disabled: g,
22
+ spellCheck: !1,
23
+ autoCapitalize: "none",
24
+ autoCorrect: "off",
25
+ className: e("pr-9 font-mono", c),
26
+ ...v
27
+ }), /* @__PURE__ */ o(t, {
28
+ type: "button",
29
+ variant: "ghost",
30
+ size: "icon-sm",
31
+ onClick: C,
32
+ disabled: g || h,
33
+ "aria-label": S ? d : u,
34
+ className: "absolute right-0.5 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground",
35
+ children: /* @__PURE__ */ o(w, { "aria-hidden": "true" })
36
+ })]
37
+ });
38
+ }
39
+ //#endregion
40
+ export { c as SecretInput };
41
+
42
+ //# sourceMappingURL=secret-input.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secret-input.js","names":[],"sources":["../../../src/components/forms/secret-input.tsx"],"mappings":";;;;;;;;AA4CA,SAAS,EAAY,EACnB,cACA,uBACA,eAAY,QACZ,eAAY,QACZ,oBAAiB,IACjB,SAAS,GACT,oBACA,oBAAiB,IACjB,aACA,QACA,GAAG,KACgB;CACnB,IAAM,CAAC,GAAqB,KAA0B,EAAM,SAAS,CAAc,GAC7E,IAAe,MAAgB,KAAA,GAO/B,KANU,IAAe,IAAc,MAMP,CAAC,GAEjC,UAAqB;EACzB,IAAM,IAAO,CAAC;EAEd,AADK,KAAc,EAAuB,CAAI,GAC9C,IAAkB,CAAI;CACxB,GAEM,IAAO,IAAqB,IAAS;CAE3C,OACE,kBAAC,OAAD;EACE,aAAU;EACV,gBAAc,IAAqB,KAAK,KAAA;EACxC,WAAW,EAAG,mBAAmB,CAAkB;EAHrD,UAAA,CAKE,kBAAC,GAAD;GACO;GACL,MAAM,IAAqB,SAAS;GAC1B;GAIV,YAAY;GACZ,gBAAe;GACf,aAAY;GACZ,WAAW,EAAG,kBAAkB,CAAS;GACzC,GAAI;EACL,CAAA,GACD,kBAAC,GAAD;GACE,MAAK;GACL,SAAQ;GACR,MAAK;GAGL,SAAS;GACT,UAAU,KAAY;GAOtB,cAAY,IAAqB,IAAY;GAC7C,WAAU;GAEV,UAAA,kBAAC,GAAD,EAAM,eAAY,OAAQ,CAAA;EACpB,CAAA,CACL;;AAET"}
@@ -0,0 +1,87 @@
1
+ import * as React from "react";
2
+ type HourCycle = "12" | "24";
3
+ export interface TimePickerPreset {
4
+ /** `HH:MM` value applied when the chip is activated. */
5
+ value: string;
6
+ /** Chip text. Defaults to the formatted `value`, so it follows `hourCycle`. */
7
+ label?: string;
8
+ }
9
+ /**
10
+ * Every user-visible string the picker renders on its own. All optional with
11
+ * English defaults — the package never resolves i18n, the app passes copy in.
12
+ */
13
+ export interface TimePickerLabels {
14
+ /** Accessible name of the popover panel. Default `"Choose a time"`. */
15
+ panel?: string;
16
+ /** Heading above the hour listbox. Default `"Hour"`. */
17
+ hour?: string;
18
+ /** Heading above the minute listbox. Default `"Minute"`. */
19
+ minute?: string;
20
+ /** Heading above the preset chips. Default `"Quick presets"`. */
21
+ quickPresets?: string;
22
+ /** Morning period suffix in 12-hour display. Default `"AM"`. */
23
+ am?: string;
24
+ /** Afternoon period suffix in 12-hour display. Default `"PM"`. */
25
+ pm?: string;
26
+ }
27
+ export interface TimePickerProps {
28
+ /**
29
+ * Current time as `HH:MM` (24-hour), controlled. Empty string means "unset".
30
+ * Pair with {@link TimePickerProps.onValueChange}; omit both for the
31
+ * uncontrolled form seeded by `defaultValue`.
32
+ */
33
+ value?: string;
34
+ /** Initial `HH:MM` value (uncontrolled). Default `""` — unset. */
35
+ defaultValue?: string;
36
+ /** Fired with the new `HH:MM` value whenever an hour, minute, or preset is chosen. */
37
+ onValueChange?: (value: string) => void;
38
+ /** Trigger text while the value is empty. Default `"00:00"`. */
39
+ placeholder?: string;
40
+ /** Classes for the trigger button. */
41
+ className?: string;
42
+ /** Classes for the popover panel. */
43
+ contentClassName?: string;
44
+ disabled?: boolean;
45
+ /** Forwarded to the trigger so an external `<Label htmlFor>` can name it. */
46
+ id?: string;
47
+ /**
48
+ * Accessible name when no visible label is associated. Composed with the
49
+ * trigger's own value text rather than replacing it, so the name reads
50
+ * `"Start time 8:00 PM"` — a bare `aria-label` would override the content
51
+ * and stop announcing the very value the control exists to report.
52
+ */
53
+ "aria-label"?: string;
54
+ /**
55
+ * Id of an external label. It is composed with the trigger's own value text,
56
+ * so the accessible name stays `"Start time 8:00 PM"` rather than collapsing
57
+ * to `"Start time"` the way a bare `<Label htmlFor>` association would.
58
+ */
59
+ "aria-labelledby"?: string;
60
+ "aria-describedby"?: string;
61
+ "aria-invalid"?: React.AriaAttributes["aria-invalid"];
62
+ /** Display format of the trigger and the hour list. Default `"12"`. */
63
+ hourCycle?: HourCycle;
64
+ /** Granularity of the minute list, in minutes. Default `5`. */
65
+ minuteStep?: number;
66
+ /** Preset chips. Pass `[]` to drop the section. Defaults to 8 AM / 12 PM / 6 PM / 8 PM / 12 AM. */
67
+ presets?: TimePickerPreset[];
68
+ labels?: TimePickerLabels;
69
+ /** Open the panel on first render (uncontrolled). */
70
+ defaultOpen?: boolean;
71
+ /** Controlled open state; pair with `onOpenChange`. */
72
+ open?: boolean;
73
+ onOpenChange?: (open: boolean) => void;
74
+ ref?: React.Ref<HTMLButtonElement>;
75
+ }
76
+ /**
77
+ * Time-of-day picker: a button showing the current time that opens a popover
78
+ * with an hour listbox, a minute listbox, and preset chips.
79
+ *
80
+ * Fully keyboard operable — Enter/Space on the trigger opens the panel and
81
+ * moves focus to the selected hour, Arrow/Home/End/PageUp/PageDown walk a
82
+ * list, Tab crosses to the minutes and the presets, Escape closes and returns
83
+ * focus to the trigger. Selection follows focus inside each list, so arrowing
84
+ * through hours updates `value` live the way a native `<select>` does.
85
+ */
86
+ declare function TimePicker({ value: valueProp, defaultValue, onValueChange, placeholder, className, contentClassName, disabled, id, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, "aria-describedby": ariaDescribedBy, "aria-invalid": ariaInvalid, hourCycle, minuteStep, presets, labels, defaultOpen, open: openProp, onOpenChange, ref, }: TimePickerProps): React.JSX.Element;
87
+ export { TimePicker };