@openwarelabs/ui 0.3.0 → 0.4.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/README.md +9 -8
- package/dist/components/Calendar/Calendar.d.cts +58 -0
- package/dist/components/Calendar/Calendar.d.ts +58 -0
- package/dist/components/Calendar/DateRangePicker.d.cts +39 -0
- package/dist/components/Calendar/DateRangePicker.d.ts +39 -0
- package/dist/components/Calendar/RangeCalendar.d.cts +38 -0
- package/dist/components/Calendar/RangeCalendar.d.ts +38 -0
- package/dist/components/Calendar/dates.d.cts +13 -0
- package/dist/components/Calendar/dates.d.ts +13 -0
- package/dist/components/ColorPicker/ColorArea.d.cts +44 -0
- package/dist/components/ColorPicker/ColorArea.d.ts +44 -0
- package/dist/components/ColorPicker/ColorSlider.d.cts +53 -0
- package/dist/components/ColorPicker/ColorSlider.d.ts +53 -0
- package/dist/components/ColorPicker/ColorSwatchPicker.d.cts +43 -0
- package/dist/components/ColorPicker/ColorSwatchPicker.d.ts +43 -0
- package/dist/components/ColorPicker/color.d.cts +91 -0
- package/dist/components/ColorPicker/color.d.ts +91 -0
- package/dist/components/DateField/DateField.d.cts +47 -0
- package/dist/components/DateField/DateField.d.ts +47 -0
- package/dist/components/DateField/SegmentedField.d.cts +63 -0
- package/dist/components/DateField/SegmentedField.d.ts +63 -0
- package/dist/components/DateField/TimeField.d.cts +52 -0
- package/dist/components/DateField/TimeField.d.ts +52 -0
- package/dist/components/Field/Field.d.cts +17 -5
- package/dist/components/Field/Field.d.ts +17 -5
- package/dist/components/FileDropZone/FileDropZone.d.cts +1 -1
- package/dist/components/FileDropZone/FileDropZone.d.ts +1 -1
- package/dist/components/Form/Form.d.cts +63 -0
- package/dist/components/Form/Form.d.ts +63 -0
- package/dist/components/InputOTP/InputOTP.d.cts +7 -1
- package/dist/components/InputOTP/InputOTP.d.ts +7 -1
- package/dist/components/ListBox/ListBox.d.cts +65 -0
- package/dist/components/ListBox/ListBox.d.ts +65 -0
- package/dist/components/Meter/Meter.d.cts +62 -0
- package/dist/components/Meter/Meter.d.ts +62 -0
- package/dist/components/Slider/Slider.d.cts +7 -1
- package/dist/components/Slider/Slider.d.ts +7 -1
- package/dist/components/ToggleButtonGroup/ToggleButtonGroup.d.cts +74 -0
- package/dist/components/ToggleButtonGroup/ToggleButtonGroup.d.ts +74 -0
- package/dist/components/Toolbar/Toolbar.d.cts +36 -0
- package/dist/components/Toolbar/Toolbar.d.ts +36 -0
- package/dist/components.css +1007 -12
- package/dist/index.cjs +3999 -1261
- package/dist/index.cjs.map +4 -4
- package/dist/index.d.cts +25 -0
- package/dist/index.d.ts +25 -0
- package/dist/index.js +3955 -1191
- package/dist/index.js.map +4 -4
- package/dist/openware-ui.iife.js +6 -6
- package/dist/styles.css +1007 -12
- package/package.json +1 -1
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { type PointerEvent as ReactPointerEvent } from "react";
|
|
2
|
+
/** Red, green and blue from 0 to 255, alpha from 0 to 1. */
|
|
3
|
+
export interface Rgba {
|
|
4
|
+
r: number;
|
|
5
|
+
g: number;
|
|
6
|
+
b: number;
|
|
7
|
+
a: number;
|
|
8
|
+
}
|
|
9
|
+
/** Hue in degrees, saturation and brightness (value) from 0 to 100, alpha from 0 to 1. */
|
|
10
|
+
export interface Hsva {
|
|
11
|
+
h: number;
|
|
12
|
+
s: number;
|
|
13
|
+
v: number;
|
|
14
|
+
a: number;
|
|
15
|
+
}
|
|
16
|
+
/** Hue in degrees, saturation and lightness from 0 to 100, alpha from 0 to 1. */
|
|
17
|
+
export interface Hsla {
|
|
18
|
+
h: number;
|
|
19
|
+
s: number;
|
|
20
|
+
l: number;
|
|
21
|
+
a: number;
|
|
22
|
+
}
|
|
23
|
+
export declare const clamp: (n: number, min: number, max: number) => number;
|
|
24
|
+
/** "#0d9488", "#0d9488cc", "#0d9" or "0d9488" → its channels; anything else → null. */
|
|
25
|
+
export declare function parseHex(color: string): Rgba | null;
|
|
26
|
+
/** Whether a hex colour spells out its alpha (#rgba or #rrggbbaa). */
|
|
27
|
+
export declare const hasAlpha: (color: string) => boolean;
|
|
28
|
+
/** Lowercase "#rrggbb", or "#rrggbbaa" with `alpha`. */
|
|
29
|
+
export declare function toHex({ r, g, b, a }: Rgba, alpha?: boolean): string;
|
|
30
|
+
/** The same colour written one way, so "#0D9488" and "#0d9488" compare equal. Invalid colours come back as given. */
|
|
31
|
+
export declare function normalizeHex(color: string): string;
|
|
32
|
+
export declare function rgbToHsv({ r, g, b, a }: Rgba): Hsva;
|
|
33
|
+
export declare function hsvToRgb({ h, s, v, a }: Hsva): Rgba;
|
|
34
|
+
export declare function hsvToHsl({ h, s, v, a }: Hsva): Hsla;
|
|
35
|
+
export declare function hslToHsv({ h, s, l, a }: Hsla): Hsva;
|
|
36
|
+
/** A way of seeing a colour that a control edits, and how to read a hex into it without losing what a grey can't hold. */
|
|
37
|
+
export interface ColorModel<M extends {
|
|
38
|
+
h: number;
|
|
39
|
+
}> {
|
|
40
|
+
read(rgba: Rgba, previous: M | undefined): M;
|
|
41
|
+
write(model: M): Rgba;
|
|
42
|
+
}
|
|
43
|
+
export declare const hsvModel: ColorModel<Hsva>;
|
|
44
|
+
export declare const hslModel: ColorModel<Hsla>;
|
|
45
|
+
/**
|
|
46
|
+
* A hex colour that a parent may control, seen through a model (HSV or HSL). The model is kept between renders
|
|
47
|
+
* and only read again from the hex when the hex changes from outside, so greys and black keep their hue.
|
|
48
|
+
* `hue`, when given, is the hue to show while the colour is a grey.
|
|
49
|
+
*/
|
|
50
|
+
export declare function useColorModel<M extends {
|
|
51
|
+
h: number;
|
|
52
|
+
}>(value: string | undefined, defaultValue: string, onChange: ((color: string) => void) | undefined, model: ColorModel<M>, { hue, alpha }?: {
|
|
53
|
+
hue?: number;
|
|
54
|
+
alpha?: boolean;
|
|
55
|
+
}): {
|
|
56
|
+
value: M;
|
|
57
|
+
rgba: Rgba;
|
|
58
|
+
hex: string;
|
|
59
|
+
set: (next: M) => string;
|
|
60
|
+
latest: () => string;
|
|
61
|
+
};
|
|
62
|
+
/**
|
|
63
|
+
* Pointer dragging over an element: reports where the pointer is as fractions of its box (0 to 1, from the top
|
|
64
|
+
* left), keeps reporting outside it through pointer capture, and calls onEnd when the pointer lets go. onStart runs
|
|
65
|
+
* on press, to focus the control. `pointerFocus` is true from a press until a key or a blur: the control was focused
|
|
66
|
+
* by the pointer and shows no focus ring, the way :focus-visible would if it were a native control.
|
|
67
|
+
*/
|
|
68
|
+
export declare function useDrag({ onMove, onEnd, onStart, disabled, }: {
|
|
69
|
+
onMove(x: number, y: number): void;
|
|
70
|
+
onEnd(): void;
|
|
71
|
+
onStart?(): void;
|
|
72
|
+
disabled?: boolean;
|
|
73
|
+
}): {
|
|
74
|
+
dragging: boolean;
|
|
75
|
+
pointerFocus: boolean;
|
|
76
|
+
/** For the input's onKeyDown and onBlur: the focus ring shows again. */
|
|
77
|
+
keyboard: () => void;
|
|
78
|
+
handlers: {
|
|
79
|
+
onPointerDown(event: ReactPointerEvent<HTMLElement>): void;
|
|
80
|
+
onPointerMove(event: ReactPointerEvent<HTMLElement>): void;
|
|
81
|
+
onLostPointerCapture(): void;
|
|
82
|
+
};
|
|
83
|
+
};
|
|
84
|
+
/** Whether light (white) or dark (slate 900) ink reads better on a colour; a translucent colour is seen over white. */
|
|
85
|
+
export declare function inkFor({ r, g, b, a }: Rgba): "light" | "dark";
|
|
86
|
+
/** A short description of a colour for screen readers: "dark teal", "light grey", "greyish blue". */
|
|
87
|
+
export declare function describeColor(rgba: Rgba): string;
|
|
88
|
+
/** The pure hue, as a hex: what a hue slider's thumb shows. */
|
|
89
|
+
export declare const hueHex: (h: number) => string;
|
|
90
|
+
/** The six stops of the hue wheel, red to red. */
|
|
91
|
+
export declare const hueStops = "#ff0000 0%, #ffff00 16.67%, #00ff00 33.33%, #00ffff 50%, #0000ff 66.67%, #ff00ff 83.33%, #ff0000 100%";
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { type PointerEvent as ReactPointerEvent } from "react";
|
|
2
|
+
/** Red, green and blue from 0 to 255, alpha from 0 to 1. */
|
|
3
|
+
export interface Rgba {
|
|
4
|
+
r: number;
|
|
5
|
+
g: number;
|
|
6
|
+
b: number;
|
|
7
|
+
a: number;
|
|
8
|
+
}
|
|
9
|
+
/** Hue in degrees, saturation and brightness (value) from 0 to 100, alpha from 0 to 1. */
|
|
10
|
+
export interface Hsva {
|
|
11
|
+
h: number;
|
|
12
|
+
s: number;
|
|
13
|
+
v: number;
|
|
14
|
+
a: number;
|
|
15
|
+
}
|
|
16
|
+
/** Hue in degrees, saturation and lightness from 0 to 100, alpha from 0 to 1. */
|
|
17
|
+
export interface Hsla {
|
|
18
|
+
h: number;
|
|
19
|
+
s: number;
|
|
20
|
+
l: number;
|
|
21
|
+
a: number;
|
|
22
|
+
}
|
|
23
|
+
export declare const clamp: (n: number, min: number, max: number) => number;
|
|
24
|
+
/** "#0d9488", "#0d9488cc", "#0d9" or "0d9488" → its channels; anything else → null. */
|
|
25
|
+
export declare function parseHex(color: string): Rgba | null;
|
|
26
|
+
/** Whether a hex colour spells out its alpha (#rgba or #rrggbbaa). */
|
|
27
|
+
export declare const hasAlpha: (color: string) => boolean;
|
|
28
|
+
/** Lowercase "#rrggbb", or "#rrggbbaa" with `alpha`. */
|
|
29
|
+
export declare function toHex({ r, g, b, a }: Rgba, alpha?: boolean): string;
|
|
30
|
+
/** The same colour written one way, so "#0D9488" and "#0d9488" compare equal. Invalid colours come back as given. */
|
|
31
|
+
export declare function normalizeHex(color: string): string;
|
|
32
|
+
export declare function rgbToHsv({ r, g, b, a }: Rgba): Hsva;
|
|
33
|
+
export declare function hsvToRgb({ h, s, v, a }: Hsva): Rgba;
|
|
34
|
+
export declare function hsvToHsl({ h, s, v, a }: Hsva): Hsla;
|
|
35
|
+
export declare function hslToHsv({ h, s, l, a }: Hsla): Hsva;
|
|
36
|
+
/** A way of seeing a colour that a control edits, and how to read a hex into it without losing what a grey can't hold. */
|
|
37
|
+
export interface ColorModel<M extends {
|
|
38
|
+
h: number;
|
|
39
|
+
}> {
|
|
40
|
+
read(rgba: Rgba, previous: M | undefined): M;
|
|
41
|
+
write(model: M): Rgba;
|
|
42
|
+
}
|
|
43
|
+
export declare const hsvModel: ColorModel<Hsva>;
|
|
44
|
+
export declare const hslModel: ColorModel<Hsla>;
|
|
45
|
+
/**
|
|
46
|
+
* A hex colour that a parent may control, seen through a model (HSV or HSL). The model is kept between renders
|
|
47
|
+
* and only read again from the hex when the hex changes from outside, so greys and black keep their hue.
|
|
48
|
+
* `hue`, when given, is the hue to show while the colour is a grey.
|
|
49
|
+
*/
|
|
50
|
+
export declare function useColorModel<M extends {
|
|
51
|
+
h: number;
|
|
52
|
+
}>(value: string | undefined, defaultValue: string, onChange: ((color: string) => void) | undefined, model: ColorModel<M>, { hue, alpha }?: {
|
|
53
|
+
hue?: number;
|
|
54
|
+
alpha?: boolean;
|
|
55
|
+
}): {
|
|
56
|
+
value: M;
|
|
57
|
+
rgba: Rgba;
|
|
58
|
+
hex: string;
|
|
59
|
+
set: (next: M) => string;
|
|
60
|
+
latest: () => string;
|
|
61
|
+
};
|
|
62
|
+
/**
|
|
63
|
+
* Pointer dragging over an element: reports where the pointer is as fractions of its box (0 to 1, from the top
|
|
64
|
+
* left), keeps reporting outside it through pointer capture, and calls onEnd when the pointer lets go. onStart runs
|
|
65
|
+
* on press, to focus the control. `pointerFocus` is true from a press until a key or a blur: the control was focused
|
|
66
|
+
* by the pointer and shows no focus ring, the way :focus-visible would if it were a native control.
|
|
67
|
+
*/
|
|
68
|
+
export declare function useDrag({ onMove, onEnd, onStart, disabled, }: {
|
|
69
|
+
onMove(x: number, y: number): void;
|
|
70
|
+
onEnd(): void;
|
|
71
|
+
onStart?(): void;
|
|
72
|
+
disabled?: boolean;
|
|
73
|
+
}): {
|
|
74
|
+
dragging: boolean;
|
|
75
|
+
pointerFocus: boolean;
|
|
76
|
+
/** For the input's onKeyDown and onBlur: the focus ring shows again. */
|
|
77
|
+
keyboard: () => void;
|
|
78
|
+
handlers: {
|
|
79
|
+
onPointerDown(event: ReactPointerEvent<HTMLElement>): void;
|
|
80
|
+
onPointerMove(event: ReactPointerEvent<HTMLElement>): void;
|
|
81
|
+
onLostPointerCapture(): void;
|
|
82
|
+
};
|
|
83
|
+
};
|
|
84
|
+
/** Whether light (white) or dark (slate 900) ink reads better on a colour; a translucent colour is seen over white. */
|
|
85
|
+
export declare function inkFor({ r, g, b, a }: Rgba): "light" | "dark";
|
|
86
|
+
/** A short description of a colour for screen readers: "dark teal", "light grey", "greyish blue". */
|
|
87
|
+
export declare function describeColor(rgba: Rgba): string;
|
|
88
|
+
/** The pure hue, as a hex: what a hue slider's thumb shows. */
|
|
89
|
+
export declare const hueHex: (h: number) => string;
|
|
90
|
+
/** The six stops of the hue wheel, red to red. */
|
|
91
|
+
export declare const hueStops = "#ff0000 0%, #ffff00 16.67%, #00ff00 33.33%, #00ffff 50%, #0000ff 66.67%, #ff00ff 83.33%, #ff0000 100%";
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
|
+
import { type ISODate } from "../Calendar/dates.cjs";
|
|
3
|
+
export interface DateFieldProps {
|
|
4
|
+
/** The date as "YYYY-MM-DD", or "" while any part is empty. */
|
|
5
|
+
value?: ISODate;
|
|
6
|
+
/** @default "" */
|
|
7
|
+
defaultValue?: ISODate;
|
|
8
|
+
/** Called with "YYYY-MM-DD" when the date is complete and whenever it changes after that, and with "" when a part is cleared. */
|
|
9
|
+
onChange?(value: ISODate): void;
|
|
10
|
+
/** The earliest valid date, "YYYY-MM-DD". An earlier one shows the field as invalid. */
|
|
11
|
+
min?: ISODate;
|
|
12
|
+
/** The latest valid date, "YYYY-MM-DD". A later one shows the field as invalid. */
|
|
13
|
+
max?: ISODate;
|
|
14
|
+
/** The order of day, month and year and the separators between them follow this locale: dd/mm/yyyy in "en-IE",
|
|
15
|
+
* mm/dd/yyyy in "en-US", dd.mm.yyyy in "de-CH". Defaults to the browser's. */
|
|
16
|
+
locale?: string;
|
|
17
|
+
/** sm 32px for toolbars and settings rows, md 40px in forms.
|
|
18
|
+
* @default "md" */
|
|
19
|
+
size?: "sm" | "md";
|
|
20
|
+
/** Shows the field as wrong: a red border, and a red halo when focused. Also sets aria-invalid. A date outside
|
|
21
|
+
* min and max does this by itself.
|
|
22
|
+
* @default false */
|
|
23
|
+
isInvalid?: boolean;
|
|
24
|
+
/** @default false */
|
|
25
|
+
disabled?: boolean;
|
|
26
|
+
/** The date can be focused and read but not changed.
|
|
27
|
+
* @default false */
|
|
28
|
+
readOnly?: boolean;
|
|
29
|
+
/** The form field name: a hidden input carries the "YYYY-MM-DD" value. */
|
|
30
|
+
name?: string;
|
|
31
|
+
/** Inside the field, before the date: a 16px calendar icon. */
|
|
32
|
+
startContent?: ReactNode;
|
|
33
|
+
/** Goes on the group. Field sets it, and its label then names the group and focuses the first segment when clicked. */
|
|
34
|
+
id?: string;
|
|
35
|
+
/** Names the date for screen readers when there's no visible label. */
|
|
36
|
+
"aria-label"?: string;
|
|
37
|
+
"aria-labelledby"?: string;
|
|
38
|
+
/** Field points it at its hint and error; each segment is described by them. */
|
|
39
|
+
"aria-describedby"?: string;
|
|
40
|
+
className?: string;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* A date typed into day, month and year segments in the locale's order, like macOS's date fields. Each segment
|
|
44
|
+
* takes digits and moves on when it's full; the arrow keys step it. Pair it with a Calendar in a Popover, or use
|
|
45
|
+
* DatePicker, when people would rather pick from a month.
|
|
46
|
+
*/
|
|
47
|
+
export declare const DateField: import("react").ForwardRefExoticComponent<DateFieldProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
|
+
import { type ISODate } from "../Calendar/dates.js";
|
|
3
|
+
export interface DateFieldProps {
|
|
4
|
+
/** The date as "YYYY-MM-DD", or "" while any part is empty. */
|
|
5
|
+
value?: ISODate;
|
|
6
|
+
/** @default "" */
|
|
7
|
+
defaultValue?: ISODate;
|
|
8
|
+
/** Called with "YYYY-MM-DD" when the date is complete and whenever it changes after that, and with "" when a part is cleared. */
|
|
9
|
+
onChange?(value: ISODate): void;
|
|
10
|
+
/** The earliest valid date, "YYYY-MM-DD". An earlier one shows the field as invalid. */
|
|
11
|
+
min?: ISODate;
|
|
12
|
+
/** The latest valid date, "YYYY-MM-DD". A later one shows the field as invalid. */
|
|
13
|
+
max?: ISODate;
|
|
14
|
+
/** The order of day, month and year and the separators between them follow this locale: dd/mm/yyyy in "en-IE",
|
|
15
|
+
* mm/dd/yyyy in "en-US", dd.mm.yyyy in "de-CH". Defaults to the browser's. */
|
|
16
|
+
locale?: string;
|
|
17
|
+
/** sm 32px for toolbars and settings rows, md 40px in forms.
|
|
18
|
+
* @default "md" */
|
|
19
|
+
size?: "sm" | "md";
|
|
20
|
+
/** Shows the field as wrong: a red border, and a red halo when focused. Also sets aria-invalid. A date outside
|
|
21
|
+
* min and max does this by itself.
|
|
22
|
+
* @default false */
|
|
23
|
+
isInvalid?: boolean;
|
|
24
|
+
/** @default false */
|
|
25
|
+
disabled?: boolean;
|
|
26
|
+
/** The date can be focused and read but not changed.
|
|
27
|
+
* @default false */
|
|
28
|
+
readOnly?: boolean;
|
|
29
|
+
/** The form field name: a hidden input carries the "YYYY-MM-DD" value. */
|
|
30
|
+
name?: string;
|
|
31
|
+
/** Inside the field, before the date: a 16px calendar icon. */
|
|
32
|
+
startContent?: ReactNode;
|
|
33
|
+
/** Goes on the group. Field sets it, and its label then names the group and focuses the first segment when clicked. */
|
|
34
|
+
id?: string;
|
|
35
|
+
/** Names the date for screen readers when there's no visible label. */
|
|
36
|
+
"aria-label"?: string;
|
|
37
|
+
"aria-labelledby"?: string;
|
|
38
|
+
/** Field points it at its hint and error; each segment is described by them. */
|
|
39
|
+
"aria-describedby"?: string;
|
|
40
|
+
className?: string;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* A date typed into day, month and year segments in the locale's order, like macOS's date fields. Each segment
|
|
44
|
+
* takes digits and moves on when it's full; the arrow keys step it. Pair it with a Calendar in a Popover, or use
|
|
45
|
+
* DatePicker, when people would rather pick from a month.
|
|
46
|
+
*/
|
|
47
|
+
export declare const DateField: import("react").ForwardRefExoticComponent<DateFieldProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { type ForwardedRef, type ReactNode } from "react";
|
|
2
|
+
export type SegmentType = "day" | "month" | "year" | "hour" | "minute" | "second" | "dayPeriod";
|
|
3
|
+
/** Values by segment; a key set to undefined clears that segment. */
|
|
4
|
+
export type SegmentValues = {
|
|
5
|
+
[Type in SegmentType]?: number | undefined;
|
|
6
|
+
};
|
|
7
|
+
export interface Segment {
|
|
8
|
+
type: SegmentType;
|
|
9
|
+
/** Read out as the segment's name: "Day", "Hour". */
|
|
10
|
+
label: string;
|
|
11
|
+
value: number | undefined;
|
|
12
|
+
min: number;
|
|
13
|
+
max: number;
|
|
14
|
+
/** Shown while it's empty: "dd", "––". */
|
|
15
|
+
placeholder: string;
|
|
16
|
+
/** The value as shown: "07", "PM". */
|
|
17
|
+
format(value: number): string;
|
|
18
|
+
/** The value as read out (aria-valuetext): "10 – October". */
|
|
19
|
+
describe(value: number): string;
|
|
20
|
+
/** Up or Down on an empty segment starts here, without stepping. */
|
|
21
|
+
start: number;
|
|
22
|
+
/** Up and Down move by this, landing on its multiples. */
|
|
23
|
+
step?: number;
|
|
24
|
+
/** PageUp and PageDown move by this. */
|
|
25
|
+
page: number;
|
|
26
|
+
/** Past the max goes round to the min. The year stops instead. */
|
|
27
|
+
wrap: boolean;
|
|
28
|
+
/** Typing only sets the value once it's whole or the segment loses focus, so a year of 2026 doesn't pass through 0002. */
|
|
29
|
+
deferTyping?: boolean;
|
|
30
|
+
/** Letters that set a value: a and p for AM and PM. */
|
|
31
|
+
letters?: Record<string, number>;
|
|
32
|
+
/** Kept this many digits wide, so the field doesn't change width as it fills. */
|
|
33
|
+
width?: 2 | 4;
|
|
34
|
+
}
|
|
35
|
+
export type Part = Segment | {
|
|
36
|
+
type: "literal";
|
|
37
|
+
text: string;
|
|
38
|
+
};
|
|
39
|
+
export interface SegmentedFieldProps {
|
|
40
|
+
parts: Part[];
|
|
41
|
+
/** The field's whole value, for the hidden input. */
|
|
42
|
+
value: string;
|
|
43
|
+
onSegmentsChange(changes: SegmentValues): void;
|
|
44
|
+
/** Reads pasted text in the field's own format, such as "2026-10-13"; null when it can't. */
|
|
45
|
+
parsePaste?(text: string): SegmentValues | null;
|
|
46
|
+
/** The locale's digits, 0 to 9. */
|
|
47
|
+
digits: string[];
|
|
48
|
+
forwardedRef: ForwardedRef<HTMLDivElement>;
|
|
49
|
+
id?: string;
|
|
50
|
+
name?: string;
|
|
51
|
+
size: "sm" | "md";
|
|
52
|
+
isInvalid: boolean;
|
|
53
|
+
disabled: boolean;
|
|
54
|
+
readOnly: boolean;
|
|
55
|
+
startContent?: ReactNode;
|
|
56
|
+
className?: string;
|
|
57
|
+
"aria-label"?: string;
|
|
58
|
+
"aria-labelledby"?: string;
|
|
59
|
+
"aria-describedby"?: string;
|
|
60
|
+
}
|
|
61
|
+
export declare function SegmentedField({ parts, value, onSegmentsChange, parsePaste, digits, forwardedRef, id, name, size, isInvalid, disabled, readOnly, startContent, className, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, "aria-describedby": ariaDescribedBy, }: SegmentedFieldProps): import("react").JSX.Element;
|
|
62
|
+
/** The locale's digits, 0 to 9, so typed and shown numbers follow its numbering system. */
|
|
63
|
+
export declare function localeDigits(locale: string | undefined): string[];
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { type ForwardedRef, type ReactNode } from "react";
|
|
2
|
+
export type SegmentType = "day" | "month" | "year" | "hour" | "minute" | "second" | "dayPeriod";
|
|
3
|
+
/** Values by segment; a key set to undefined clears that segment. */
|
|
4
|
+
export type SegmentValues = {
|
|
5
|
+
[Type in SegmentType]?: number | undefined;
|
|
6
|
+
};
|
|
7
|
+
export interface Segment {
|
|
8
|
+
type: SegmentType;
|
|
9
|
+
/** Read out as the segment's name: "Day", "Hour". */
|
|
10
|
+
label: string;
|
|
11
|
+
value: number | undefined;
|
|
12
|
+
min: number;
|
|
13
|
+
max: number;
|
|
14
|
+
/** Shown while it's empty: "dd", "––". */
|
|
15
|
+
placeholder: string;
|
|
16
|
+
/** The value as shown: "07", "PM". */
|
|
17
|
+
format(value: number): string;
|
|
18
|
+
/** The value as read out (aria-valuetext): "10 – October". */
|
|
19
|
+
describe(value: number): string;
|
|
20
|
+
/** Up or Down on an empty segment starts here, without stepping. */
|
|
21
|
+
start: number;
|
|
22
|
+
/** Up and Down move by this, landing on its multiples. */
|
|
23
|
+
step?: number;
|
|
24
|
+
/** PageUp and PageDown move by this. */
|
|
25
|
+
page: number;
|
|
26
|
+
/** Past the max goes round to the min. The year stops instead. */
|
|
27
|
+
wrap: boolean;
|
|
28
|
+
/** Typing only sets the value once it's whole or the segment loses focus, so a year of 2026 doesn't pass through 0002. */
|
|
29
|
+
deferTyping?: boolean;
|
|
30
|
+
/** Letters that set a value: a and p for AM and PM. */
|
|
31
|
+
letters?: Record<string, number>;
|
|
32
|
+
/** Kept this many digits wide, so the field doesn't change width as it fills. */
|
|
33
|
+
width?: 2 | 4;
|
|
34
|
+
}
|
|
35
|
+
export type Part = Segment | {
|
|
36
|
+
type: "literal";
|
|
37
|
+
text: string;
|
|
38
|
+
};
|
|
39
|
+
export interface SegmentedFieldProps {
|
|
40
|
+
parts: Part[];
|
|
41
|
+
/** The field's whole value, for the hidden input. */
|
|
42
|
+
value: string;
|
|
43
|
+
onSegmentsChange(changes: SegmentValues): void;
|
|
44
|
+
/** Reads pasted text in the field's own format, such as "2026-10-13"; null when it can't. */
|
|
45
|
+
parsePaste?(text: string): SegmentValues | null;
|
|
46
|
+
/** The locale's digits, 0 to 9. */
|
|
47
|
+
digits: string[];
|
|
48
|
+
forwardedRef: ForwardedRef<HTMLDivElement>;
|
|
49
|
+
id?: string;
|
|
50
|
+
name?: string;
|
|
51
|
+
size: "sm" | "md";
|
|
52
|
+
isInvalid: boolean;
|
|
53
|
+
disabled: boolean;
|
|
54
|
+
readOnly: boolean;
|
|
55
|
+
startContent?: ReactNode;
|
|
56
|
+
className?: string;
|
|
57
|
+
"aria-label"?: string;
|
|
58
|
+
"aria-labelledby"?: string;
|
|
59
|
+
"aria-describedby"?: string;
|
|
60
|
+
}
|
|
61
|
+
export declare function SegmentedField({ parts, value, onSegmentsChange, parsePaste, digits, forwardedRef, id, name, size, isInvalid, disabled, readOnly, startContent, className, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, "aria-describedby": ariaDescribedBy, }: SegmentedFieldProps): import("react").JSX.Element;
|
|
62
|
+
/** The locale's digits, 0 to 9, so typed and shown numbers follow its numbering system. */
|
|
63
|
+
export declare function localeDigits(locale: string | undefined): string[];
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
|
+
export interface TimeFieldProps {
|
|
3
|
+
/** The time on a 24-hour clock, "HH:MM", or "HH:MM:SS" when granularity is "second"; "" while any part is empty. */
|
|
4
|
+
value?: string;
|
|
5
|
+
/** @default "" */
|
|
6
|
+
defaultValue?: string;
|
|
7
|
+
/** Called with "HH:MM" (or "HH:MM:SS") when the time is complete and whenever it changes after that, and with "" when a part is cleared. */
|
|
8
|
+
onChange?(value: string): void;
|
|
9
|
+
/** 12 shows hours 1–12 and an AM/PM segment; 24 shows 00–23. Defaults to the locale's clock. */
|
|
10
|
+
hourCycle?: 12 | 24;
|
|
11
|
+
/** "second" adds a seconds segment.
|
|
12
|
+
* @default "minute" */
|
|
13
|
+
granularity?: "minute" | "second";
|
|
14
|
+
/** Up and Down move the minutes by this much, landing on its multiples: 5, 15. Typed minutes can still be anything.
|
|
15
|
+
* @default 1 */
|
|
16
|
+
minuteStep?: number;
|
|
17
|
+
/** The earliest valid time, "HH:MM". An earlier one shows the field as invalid. */
|
|
18
|
+
min?: string;
|
|
19
|
+
/** The latest valid time, "HH:MM". A later one shows the field as invalid. */
|
|
20
|
+
max?: string;
|
|
21
|
+
/** The separators, the AM/PM words and where they go follow this locale. Defaults to the browser's. */
|
|
22
|
+
locale?: string;
|
|
23
|
+
/** sm 32px for toolbars and settings rows, md 40px in forms.
|
|
24
|
+
* @default "md" */
|
|
25
|
+
size?: "sm" | "md";
|
|
26
|
+
/** Shows the field as wrong: a red border, and a red halo when focused. Also sets aria-invalid. A time outside
|
|
27
|
+
* min and max does this by itself.
|
|
28
|
+
* @default false */
|
|
29
|
+
isInvalid?: boolean;
|
|
30
|
+
/** @default false */
|
|
31
|
+
disabled?: boolean;
|
|
32
|
+
/** The time can be focused and read but not changed.
|
|
33
|
+
* @default false */
|
|
34
|
+
readOnly?: boolean;
|
|
35
|
+
/** The form field name: a hidden input carries the "HH:MM" value. */
|
|
36
|
+
name?: string;
|
|
37
|
+
/** Inside the field, before the time: a 16px clock icon. */
|
|
38
|
+
startContent?: ReactNode;
|
|
39
|
+
/** Goes on the group. Field sets it, and its label then names the group and focuses the first segment when clicked. */
|
|
40
|
+
id?: string;
|
|
41
|
+
/** Names the time for screen readers when there's no visible label. */
|
|
42
|
+
"aria-label"?: string;
|
|
43
|
+
"aria-labelledby"?: string;
|
|
44
|
+
/** Field points it at its hint and error; each segment is described by them. */
|
|
45
|
+
"aria-describedby"?: string;
|
|
46
|
+
className?: string;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* A time typed into hour, minute and optional second segments, with AM/PM on a 12-hour clock. It works like
|
|
50
|
+
* DateField: digits fill a segment and move on, the arrow keys step it, and the value is always on a 24-hour clock.
|
|
51
|
+
*/
|
|
52
|
+
export declare const TimeField: import("react").ForwardRefExoticComponent<TimeFieldProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
|
+
export interface TimeFieldProps {
|
|
3
|
+
/** The time on a 24-hour clock, "HH:MM", or "HH:MM:SS" when granularity is "second"; "" while any part is empty. */
|
|
4
|
+
value?: string;
|
|
5
|
+
/** @default "" */
|
|
6
|
+
defaultValue?: string;
|
|
7
|
+
/** Called with "HH:MM" (or "HH:MM:SS") when the time is complete and whenever it changes after that, and with "" when a part is cleared. */
|
|
8
|
+
onChange?(value: string): void;
|
|
9
|
+
/** 12 shows hours 1–12 and an AM/PM segment; 24 shows 00–23. Defaults to the locale's clock. */
|
|
10
|
+
hourCycle?: 12 | 24;
|
|
11
|
+
/** "second" adds a seconds segment.
|
|
12
|
+
* @default "minute" */
|
|
13
|
+
granularity?: "minute" | "second";
|
|
14
|
+
/** Up and Down move the minutes by this much, landing on its multiples: 5, 15. Typed minutes can still be anything.
|
|
15
|
+
* @default 1 */
|
|
16
|
+
minuteStep?: number;
|
|
17
|
+
/** The earliest valid time, "HH:MM". An earlier one shows the field as invalid. */
|
|
18
|
+
min?: string;
|
|
19
|
+
/** The latest valid time, "HH:MM". A later one shows the field as invalid. */
|
|
20
|
+
max?: string;
|
|
21
|
+
/** The separators, the AM/PM words and where they go follow this locale. Defaults to the browser's. */
|
|
22
|
+
locale?: string;
|
|
23
|
+
/** sm 32px for toolbars and settings rows, md 40px in forms.
|
|
24
|
+
* @default "md" */
|
|
25
|
+
size?: "sm" | "md";
|
|
26
|
+
/** Shows the field as wrong: a red border, and a red halo when focused. Also sets aria-invalid. A time outside
|
|
27
|
+
* min and max does this by itself.
|
|
28
|
+
* @default false */
|
|
29
|
+
isInvalid?: boolean;
|
|
30
|
+
/** @default false */
|
|
31
|
+
disabled?: boolean;
|
|
32
|
+
/** The time can be focused and read but not changed.
|
|
33
|
+
* @default false */
|
|
34
|
+
readOnly?: boolean;
|
|
35
|
+
/** The form field name: a hidden input carries the "HH:MM" value. */
|
|
36
|
+
name?: string;
|
|
37
|
+
/** Inside the field, before the time: a 16px clock icon. */
|
|
38
|
+
startContent?: ReactNode;
|
|
39
|
+
/** Goes on the group. Field sets it, and its label then names the group and focuses the first segment when clicked. */
|
|
40
|
+
id?: string;
|
|
41
|
+
/** Names the time for screen readers when there's no visible label. */
|
|
42
|
+
"aria-label"?: string;
|
|
43
|
+
"aria-labelledby"?: string;
|
|
44
|
+
/** Field points it at its hint and error; each segment is described by them. */
|
|
45
|
+
"aria-describedby"?: string;
|
|
46
|
+
className?: string;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* A time typed into hour, minute and optional second segments, with AM/PM on a 12-hour clock. It works like
|
|
50
|
+
* DateField: digits fill a segment and move on, the arrow keys step it, and the value is always on a 24-hour clock.
|
|
51
|
+
*/
|
|
52
|
+
export declare const TimeField: import("react").ForwardRefExoticComponent<TimeFieldProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
@@ -1,18 +1,30 @@
|
|
|
1
1
|
import { type ReactElement, type ReactNode } from "react";
|
|
2
|
+
import { type ValidityMessages } from "../Form/Form.cjs";
|
|
2
3
|
export interface FieldProps {
|
|
3
|
-
/** The label, set above the control. */
|
|
4
|
-
label
|
|
4
|
+
/** The label, set above the control. Leave it out for a control that has its own, like a Checkbox. */
|
|
5
|
+
label?: ReactNode;
|
|
5
6
|
/** One control: an Input, Textarea, Select, or any element that takes an id. */
|
|
6
7
|
children: ReactElement;
|
|
7
8
|
/** A muted line under the control. */
|
|
8
9
|
hint?: ReactNode;
|
|
9
|
-
/** An error under the control; it also marks the control invalid. */
|
|
10
|
+
/** An error under the control; it also marks the control invalid. Inside a Form, it takes the place of the Form's. */
|
|
10
11
|
error?: ReactNode;
|
|
12
|
+
/**
|
|
13
|
+
* The field's name, for a control with no `name` of its own (Select, Combobox, Switch, DatePicker): Field submits
|
|
14
|
+
* the control's `value` (or `checked`) under it in a hidden input, and inside a Form shows the Form's error for it.
|
|
15
|
+
* The control must be controlled; a string, a number, true or an array of them is sent.
|
|
16
|
+
*/
|
|
17
|
+
name?: string;
|
|
18
|
+
/**
|
|
19
|
+
* Inside a Form, what to say when one of the browser's checks fails, in place of its own message: one string for
|
|
20
|
+
* any check, or one per check, like { valueMissing: "Enter your work email.", typeMismatch: "…" }.
|
|
21
|
+
*/
|
|
22
|
+
errorMessages?: ValidityMessages;
|
|
11
23
|
className?: string;
|
|
12
24
|
}
|
|
13
25
|
/**
|
|
14
26
|
* A label above a control, with an optional hint and error below. Field wires them together:
|
|
15
27
|
* it gives the control an id (unless it has one), points aria-describedby at the hint and error,
|
|
16
|
-
* and marks it invalid when there is an error.
|
|
28
|
+
* and marks it invalid when there is an error. Inside a Form, it shows the Form's error for its control's name.
|
|
17
29
|
*/
|
|
18
|
-
export declare function Field({ label, children, hint, error, className }: FieldProps): import("react").JSX.Element;
|
|
30
|
+
export declare function Field({ label, children, hint, error, name: nameProp, errorMessages, className }: FieldProps): import("react").JSX.Element;
|
|
@@ -1,18 +1,30 @@
|
|
|
1
1
|
import { type ReactElement, type ReactNode } from "react";
|
|
2
|
+
import { type ValidityMessages } from "../Form/Form.js";
|
|
2
3
|
export interface FieldProps {
|
|
3
|
-
/** The label, set above the control. */
|
|
4
|
-
label
|
|
4
|
+
/** The label, set above the control. Leave it out for a control that has its own, like a Checkbox. */
|
|
5
|
+
label?: ReactNode;
|
|
5
6
|
/** One control: an Input, Textarea, Select, or any element that takes an id. */
|
|
6
7
|
children: ReactElement;
|
|
7
8
|
/** A muted line under the control. */
|
|
8
9
|
hint?: ReactNode;
|
|
9
|
-
/** An error under the control; it also marks the control invalid. */
|
|
10
|
+
/** An error under the control; it also marks the control invalid. Inside a Form, it takes the place of the Form's. */
|
|
10
11
|
error?: ReactNode;
|
|
12
|
+
/**
|
|
13
|
+
* The field's name, for a control with no `name` of its own (Select, Combobox, Switch, DatePicker): Field submits
|
|
14
|
+
* the control's `value` (or `checked`) under it in a hidden input, and inside a Form shows the Form's error for it.
|
|
15
|
+
* The control must be controlled; a string, a number, true or an array of them is sent.
|
|
16
|
+
*/
|
|
17
|
+
name?: string;
|
|
18
|
+
/**
|
|
19
|
+
* Inside a Form, what to say when one of the browser's checks fails, in place of its own message: one string for
|
|
20
|
+
* any check, or one per check, like { valueMissing: "Enter your work email.", typeMismatch: "…" }.
|
|
21
|
+
*/
|
|
22
|
+
errorMessages?: ValidityMessages;
|
|
11
23
|
className?: string;
|
|
12
24
|
}
|
|
13
25
|
/**
|
|
14
26
|
* A label above a control, with an optional hint and error below. Field wires them together:
|
|
15
27
|
* it gives the control an id (unless it has one), points aria-describedby at the hint and error,
|
|
16
|
-
* and marks it invalid when there is an error.
|
|
28
|
+
* and marks it invalid when there is an error. Inside a Form, it shows the Form's error for its control's name.
|
|
17
29
|
*/
|
|
18
|
-
export declare function Field({ label, children, hint, error, className }: FieldProps): import("react").JSX.Element;
|
|
30
|
+
export declare function Field({ label, children, hint, error, name: nameProp, errorMessages, className }: FieldProps): import("react").JSX.Element;
|
|
@@ -18,7 +18,7 @@ export interface FileDropZoneProps {
|
|
|
18
18
|
* @default <UploadIcon /> */
|
|
19
19
|
icon?: ReactNode;
|
|
20
20
|
disabled?: boolean;
|
|
21
|
-
/** The form field name for the file input. */
|
|
21
|
+
/** The form field name for the file input. A form submits the files from the last accepted pick or drop. */
|
|
22
22
|
name?: string;
|
|
23
23
|
className?: string;
|
|
24
24
|
}
|
|
@@ -18,7 +18,7 @@ export interface FileDropZoneProps {
|
|
|
18
18
|
* @default <UploadIcon /> */
|
|
19
19
|
icon?: ReactNode;
|
|
20
20
|
disabled?: boolean;
|
|
21
|
-
/** The form field name for the file input. */
|
|
21
|
+
/** The form field name for the file input. A form submits the files from the last accepted pick or drop. */
|
|
22
22
|
name?: string;
|
|
23
23
|
className?: string;
|
|
24
24
|
}
|