@galaxy-io/dls 1.4.15 → 1.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assets/components/GalaxyFilamentWordmarkDark.d.ts +3 -0
- package/dist/assets/components/GalaxyFilamentWordmarkDark.js +14 -0
- package/dist/assets/components/GalaxyFilamentWordmarkLight.d.ts +3 -0
- package/dist/assets/components/GalaxyFilamentWordmarkLight.js +14 -0
- package/dist/icons/GalaxyFilamentWordmark.d.ts +11 -0
- package/dist/icons/GalaxyFilamentWordmark.js +25 -0
- package/dist/inputs/CheckboxInput.d.ts +11 -14
- package/dist/inputs/CheckboxInput.js +10 -27
- package/dist/inputs/ColorInput.d.ts +4 -2
- package/dist/inputs/ColorInput.js +14 -28
- package/dist/inputs/CopyInput.d.ts +4 -2
- package/dist/inputs/CopyInput.js +11 -3
- package/dist/inputs/DateInput.d.ts +4 -2
- package/dist/inputs/DateInput.js +24 -31
- package/dist/inputs/Input.d.ts +82 -5
- package/dist/inputs/Input.js +111 -33
- package/dist/inputs/MultiSelectInput.d.ts +4 -4
- package/dist/inputs/MultiSelectInput.js +38 -45
- package/dist/inputs/MultiTextInput.d.ts +5 -16
- package/dist/inputs/MultiTextInput.js +24 -31
- package/dist/inputs/NumberInput.d.ts +1 -1
- package/dist/inputs/NumberInput.js +10 -2
- package/dist/inputs/PasswordInput.d.ts +4 -3
- package/dist/inputs/PasswordInput.js +6 -3
- package/dist/inputs/RadioInput.d.ts +11 -14
- package/dist/inputs/RadioInput.js +18 -34
- package/dist/inputs/SelectInput.d.ts +5 -14
- package/dist/inputs/SelectInput.js +35 -57
- package/dist/inputs/SliderInput.d.ts +9 -1
- package/dist/inputs/SliderInput.js +47 -21
- package/dist/inputs/SwitcherInput.d.ts +7 -2
- package/dist/inputs/SwitcherInput.js +10 -9
- package/dist/inputs/TextAreaInput.d.ts +5 -18
- package/dist/inputs/TextAreaInput.js +29 -57
- package/dist/inputs/TextInput.d.ts +6 -2
- package/dist/inputs/TextInput.js +2 -1
- package/dist/inputs/ToggleInput.d.ts +10 -1
- package/dist/inputs/ToggleInput.js +31 -9
- package/dist/styles.css +15 -15
- package/dist/table/TableSelectCell.js +5 -4
- package/package.json +1 -1
package/dist/inputs/Input.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { type Ref } from "react";
|
|
2
2
|
import { type Icon as PhosphorIcon } from "@phosphor-icons/react";
|
|
3
|
+
import type { Theme } from "../theme/types";
|
|
4
|
+
import { TextSize } from "../text/Text";
|
|
3
5
|
export interface InputLabelProps {
|
|
4
6
|
label: string;
|
|
5
7
|
/** Adds an info icon beside the label with this content on hover. */
|
|
@@ -18,8 +20,79 @@ export declare enum InputSize {
|
|
|
18
20
|
MEDIUM = "MEDIUM",
|
|
19
21
|
LARGE = "LARGE"
|
|
20
22
|
}
|
|
23
|
+
/**
|
|
24
|
+
* Field height for an `InputSize`. The single source of truth — every input in
|
|
25
|
+
* the family routes through this. Call it from inside a Linaria interpolation:
|
|
26
|
+
*
|
|
27
|
+
* ```
|
|
28
|
+
* height: ${({ $size }) => getInputHeight($size)};
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
export declare function getInputHeight(size: InputSize): string;
|
|
32
|
+
/** `getInputHeight` unwrapped, for callers that need to do arithmetic on it. */
|
|
33
|
+
export declare function getInputHeightValue(size: InputSize): number;
|
|
34
|
+
/**
|
|
35
|
+
* Horizontal inset for an `InputSize` — 6 / 8 / 12px. Returned as a number so
|
|
36
|
+
* `TextAreaInput` can fold it into its computed `min-height`; most callers want
|
|
37
|
+
* `getInputPadding` instead.
|
|
38
|
+
*/
|
|
39
|
+
export declare function getInputPaddingValue(size: InputSize): number;
|
|
40
|
+
/** `getInputPaddingValue` as a CSS length. */
|
|
41
|
+
export declare function getInputPadding(size: InputSize): string;
|
|
42
|
+
/** Type step for an `InputSize` — `body_sm` / `body_md` / `body_lg`. */
|
|
43
|
+
export declare function getInputFontSize(theme: Theme, size: InputSize): string;
|
|
44
|
+
/** The line height paired with `getInputFontSize`. */
|
|
45
|
+
export declare function getInputLineHeight(theme: Theme, size: InputSize): string;
|
|
46
|
+
/** Icon px for an `InputSize` — 12 / 14 / 16, for icons sitting inside a field. */
|
|
47
|
+
export declare function getInputIconSize(size: InputSize): number;
|
|
48
|
+
/**
|
|
49
|
+
* `getInputFontSize` for copy that renders through `Text` rather than through a
|
|
50
|
+
* raw `<input>` — the trigger labels in `SelectInput`, `DateInput`, `ColorInput`.
|
|
51
|
+
*/
|
|
52
|
+
export declare function getInputTextSize(size: InputSize): TextSize;
|
|
53
|
+
/**
|
|
54
|
+
* Hit-target box for the boolean controls — 12 / 16 / 20px. Shared by the
|
|
55
|
+
* `CheckboxInput` square and the `RadioInput` circle, which are sized as targets
|
|
56
|
+
* rather than off the type scale, so they do not follow `getInputHeight`.
|
|
57
|
+
*/
|
|
58
|
+
export declare function getInputControlSize(size: InputSize): string;
|
|
59
|
+
/**
|
|
60
|
+
* Surface color for any input. Mirrors `DropdownVariant` so a field and the
|
|
61
|
+
* panel it sits in can be tuned to the same step of the neutral stack.
|
|
62
|
+
*
|
|
63
|
+
* Paints the *resting* surface only — state colors (checked, selected, filled)
|
|
64
|
+
* are fixed tokens and are not affected by the variant.
|
|
65
|
+
*
|
|
66
|
+
* `TRANSPARENT` drops both the fill and the border. `CheckboxInput` and
|
|
67
|
+
* `RadioInput` keep their hairline under it, or they would be invisible.
|
|
68
|
+
*/
|
|
69
|
+
export declare enum InputVariant {
|
|
70
|
+
TRANSPARENT = "TRANSPARENT",
|
|
71
|
+
BASE = "BASE",
|
|
72
|
+
PRIMARY = "PRIMARY",
|
|
73
|
+
SECONDARY = "SECONDARY",
|
|
74
|
+
TERTIARY = "TERTIARY"
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Surface fill for an `InputVariant`. The single source of truth — every input
|
|
78
|
+
* routes through this. Call it from inside a Linaria interpolation:
|
|
79
|
+
*
|
|
80
|
+
* ```
|
|
81
|
+
* background-color: ${({ theme, $variant }) => getInputSurfaceColor(theme, $variant)};
|
|
82
|
+
* ```
|
|
83
|
+
*/
|
|
84
|
+
export declare function getInputSurfaceColor(theme: Theme, variant?: InputVariant): string;
|
|
85
|
+
/**
|
|
86
|
+
* Resting border for an `InputVariant`. Callers short-circuit their own error,
|
|
87
|
+
* focus and active colors before falling back to this.
|
|
88
|
+
*
|
|
89
|
+
* Returns `"transparent"` rather than `"none"` so the box model stays identical
|
|
90
|
+
* across variants.
|
|
91
|
+
*/
|
|
92
|
+
export declare function getInputBorderColor(theme: Theme, variant?: InputVariant): string;
|
|
21
93
|
export declare const StyledInput: import("react").ComponentType<Pick<import("react").ClassAttributes<HTMLInputElement> & import("react").InputHTMLAttributes<HTMLInputElement> & {
|
|
22
94
|
$size: InputSize;
|
|
95
|
+
$variant?: InputVariant;
|
|
23
96
|
$width?: number | string;
|
|
24
97
|
$fillWidth?: boolean;
|
|
25
98
|
$isError?: boolean;
|
|
@@ -28,13 +101,14 @@ export declare const StyledInput: import("react").ComponentType<Pick<import("rea
|
|
|
28
101
|
$isMonospace?: boolean;
|
|
29
102
|
$isDisabled?: boolean;
|
|
30
103
|
} & {
|
|
31
|
-
theme:
|
|
104
|
+
theme: Theme;
|
|
32
105
|
} & {
|
|
33
106
|
as?: React.ElementType;
|
|
34
|
-
}, "$width" | "$fillWidth" | "$size" | "$isMonospace" | "as" | "$isError" | "$hasLeadingIcon" | "$hasTrailingAction" | "$isDisabled" | keyof import("react").ClassAttributes<HTMLInputElement> | keyof import("react").InputHTMLAttributes<HTMLInputElement>> & {
|
|
35
|
-
theme?: import("@callstack/react-theme-provider").$DeepPartial<
|
|
107
|
+
}, "$width" | "$fillWidth" | "$size" | "$variant" | "$isMonospace" | "as" | "$isError" | "$hasLeadingIcon" | "$hasTrailingAction" | "$isDisabled" | keyof import("react").ClassAttributes<HTMLInputElement> | keyof import("react").InputHTMLAttributes<HTMLInputElement>> & {
|
|
108
|
+
theme?: import("@callstack/react-theme-provider").$DeepPartial<Theme> | undefined;
|
|
36
109
|
}> & import("@callstack/react-theme-provider/typings/hoist-non-react-statics").NonReactStatics<import("react").ComponentType<import("react").ClassAttributes<HTMLInputElement> & import("react").InputHTMLAttributes<HTMLInputElement> & {
|
|
37
110
|
$size: InputSize;
|
|
111
|
+
$variant?: InputVariant;
|
|
38
112
|
$width?: number | string;
|
|
39
113
|
$fillWidth?: boolean;
|
|
40
114
|
$isError?: boolean;
|
|
@@ -43,13 +117,14 @@ export declare const StyledInput: import("react").ComponentType<Pick<import("rea
|
|
|
43
117
|
$isMonospace?: boolean;
|
|
44
118
|
$isDisabled?: boolean;
|
|
45
119
|
} & {
|
|
46
|
-
theme:
|
|
120
|
+
theme: Theme;
|
|
47
121
|
} & {
|
|
48
122
|
as?: React.ElementType;
|
|
49
123
|
}> & {
|
|
50
124
|
__wyw_meta: unknown;
|
|
51
125
|
} & import("react").FunctionComponent<import("react").ClassAttributes<HTMLInputElement> & import("react").InputHTMLAttributes<HTMLInputElement> & {
|
|
52
126
|
$size: InputSize;
|
|
127
|
+
$variant?: InputVariant;
|
|
53
128
|
$width?: number | string;
|
|
54
129
|
$fillWidth?: boolean;
|
|
55
130
|
$isError?: boolean;
|
|
@@ -58,7 +133,7 @@ export declare const StyledInput: import("react").ComponentType<Pick<import("rea
|
|
|
58
133
|
$isMonospace?: boolean;
|
|
59
134
|
$isDisabled?: boolean;
|
|
60
135
|
} & {
|
|
61
|
-
theme:
|
|
136
|
+
theme: Theme;
|
|
62
137
|
} & {
|
|
63
138
|
as?: React.ElementType;
|
|
64
139
|
}>, {}>;
|
|
@@ -74,6 +149,8 @@ export interface InputProps<T> {
|
|
|
74
149
|
parse: (value: T) => T;
|
|
75
150
|
/** Called with the parsed value on every keystroke. */
|
|
76
151
|
onChange: (value: T) => void;
|
|
152
|
+
/** Field surface color. @default InputVariant.PRIMARY */
|
|
153
|
+
variant?: InputVariant;
|
|
77
154
|
/** @default InputSize.MEDIUM */
|
|
78
155
|
size?: InputSize;
|
|
79
156
|
/** The underlying `<input type>`. Wrappers set it. */
|
package/dist/inputs/Input.js
CHANGED
|
@@ -49,32 +49,118 @@ var InputSize = /* @__PURE__ */ function(InputSize) {
|
|
|
49
49
|
InputSize["LARGE"] = "LARGE";
|
|
50
50
|
return InputSize;
|
|
51
51
|
}({});
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
52
|
+
/**
|
|
53
|
+
* Field height for an `InputSize`. The single source of truth — every input in
|
|
54
|
+
* the family routes through this. Call it from inside a Linaria interpolation:
|
|
55
|
+
*
|
|
56
|
+
* ```
|
|
57
|
+
* height: ${({ $size }) => getInputHeight($size)};
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
function getInputHeight(size) {
|
|
61
|
+
return `${getInputHeightValue(size)}px`;
|
|
62
|
+
}
|
|
63
|
+
/** `getInputHeight` unwrapped, for callers that need to do arithmetic on it. */
|
|
64
|
+
function getInputHeightValue(size) {
|
|
65
|
+
return match(size).returnType().with("SMALL", () => 24).with("MEDIUM", () => 28).with("LARGE", () => 32).exhaustive();
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Horizontal inset for an `InputSize` — 6 / 8 / 12px. Returned as a number so
|
|
69
|
+
* `TextAreaInput` can fold it into its computed `min-height`; most callers want
|
|
70
|
+
* `getInputPadding` instead.
|
|
71
|
+
*/
|
|
72
|
+
function getInputPaddingValue(size) {
|
|
73
|
+
return match(size).returnType().with("SMALL", () => 6).with("MEDIUM", () => 8).with("LARGE", () => 12).exhaustive();
|
|
74
|
+
}
|
|
75
|
+
/** `getInputPaddingValue` as a CSS length. */
|
|
76
|
+
function getInputPadding(size) {
|
|
77
|
+
return `${getInputPaddingValue(size)}px`;
|
|
78
|
+
}
|
|
79
|
+
/** Type step for an `InputSize` — `body_sm` / `body_md` / `body_lg`. */
|
|
80
|
+
function getInputFontSize(theme, size) {
|
|
81
|
+
return match(size).returnType().with("SMALL", () => theme.font.sans.size.body_sm).with("MEDIUM", () => theme.font.sans.size.body_md).with("LARGE", () => theme.font.sans.size.body_lg).exhaustive();
|
|
82
|
+
}
|
|
83
|
+
/** The line height paired with `getInputFontSize`. */
|
|
84
|
+
function getInputLineHeight(theme, size) {
|
|
85
|
+
return match(size).returnType().with("SMALL", () => theme.font.sans.height.body_sm).with("MEDIUM", () => theme.font.sans.height.body_md).with("LARGE", () => theme.font.sans.height.body_lg).exhaustive();
|
|
86
|
+
}
|
|
87
|
+
/** Icon px for an `InputSize` — 12 / 14 / 16, for icons sitting inside a field. */
|
|
88
|
+
function getInputIconSize(size) {
|
|
89
|
+
return match(size).returnType().with("SMALL", () => 12).with("MEDIUM", () => 14).with("LARGE", () => 16).exhaustive();
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* `getInputFontSize` for copy that renders through `Text` rather than through a
|
|
93
|
+
* raw `<input>` — the trigger labels in `SelectInput`, `DateInput`, `ColorInput`.
|
|
94
|
+
*/
|
|
95
|
+
function getInputTextSize(size) {
|
|
96
|
+
return match(size).returnType().with("SMALL", () => TextSize.BODY_SM).with("MEDIUM", () => TextSize.BODY_MD).with("LARGE", () => TextSize.BODY_LG).exhaustive();
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Hit-target box for the boolean controls — 12 / 16 / 20px. Shared by the
|
|
100
|
+
* `CheckboxInput` square and the `RadioInput` circle, which are sized as targets
|
|
101
|
+
* rather than off the type scale, so they do not follow `getInputHeight`.
|
|
102
|
+
*/
|
|
103
|
+
function getInputControlSize(size) {
|
|
104
|
+
return match(size).returnType().with("SMALL", () => "12px").with("MEDIUM", () => "16px").with("LARGE", () => "20px").exhaustive();
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Surface color for any input. Mirrors `DropdownVariant` so a field and the
|
|
108
|
+
* panel it sits in can be tuned to the same step of the neutral stack.
|
|
109
|
+
*
|
|
110
|
+
* Paints the *resting* surface only — state colors (checked, selected, filled)
|
|
111
|
+
* are fixed tokens and are not affected by the variant.
|
|
112
|
+
*
|
|
113
|
+
* `TRANSPARENT` drops both the fill and the border. `CheckboxInput` and
|
|
114
|
+
* `RadioInput` keep their hairline under it, or they would be invisible.
|
|
115
|
+
*/
|
|
116
|
+
var InputVariant = /* @__PURE__ */ function(InputVariant) {
|
|
117
|
+
InputVariant["TRANSPARENT"] = "TRANSPARENT";
|
|
118
|
+
InputVariant["BASE"] = "BASE";
|
|
119
|
+
InputVariant["PRIMARY"] = "PRIMARY";
|
|
120
|
+
InputVariant["SECONDARY"] = "SECONDARY";
|
|
121
|
+
InputVariant["TERTIARY"] = "TERTIARY";
|
|
122
|
+
return InputVariant;
|
|
123
|
+
}({});
|
|
124
|
+
/**
|
|
125
|
+
* Surface fill for an `InputVariant`. The single source of truth — every input
|
|
126
|
+
* routes through this. Call it from inside a Linaria interpolation:
|
|
127
|
+
*
|
|
128
|
+
* ```
|
|
129
|
+
* background-color: ${({ theme, $variant }) => getInputSurfaceColor(theme, $variant)};
|
|
130
|
+
* ```
|
|
131
|
+
*/
|
|
132
|
+
function getInputSurfaceColor(theme, variant) {
|
|
133
|
+
return match(variant).returnType().with("TRANSPARENT", () => "transparent").with("BASE", () => theme.color.background.base).with("PRIMARY", () => theme.color.background.primary).with("SECONDARY", () => theme.color.background.secondary).with("TERTIARY", () => theme.color.background.tertiary).with(void 0, () => theme.color.background.primary).exhaustive();
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Resting border for an `InputVariant`. Callers short-circuit their own error,
|
|
137
|
+
* focus and active colors before falling back to this.
|
|
138
|
+
*
|
|
139
|
+
* Returns `"transparent"` rather than `"none"` so the box model stays identical
|
|
140
|
+
* across variants.
|
|
141
|
+
*/
|
|
142
|
+
function getInputBorderColor(theme, variant) {
|
|
143
|
+
return variant === "TRANSPARENT" ? "transparent" : theme.color.border.primary;
|
|
144
|
+
}
|
|
145
|
+
/** Space between a trailing action button and the text it must not overlap. */
|
|
146
|
+
var _exp = () => ({ $size }) => getInputHeight($size);
|
|
55
147
|
var _exp2 = () => ({ $fillWidth, $width }) => $fillWidth ? "100%" : $width ? getCssSizeValue($width) : "auto";
|
|
56
|
-
var _exp3 = () => ({ theme }) => theme
|
|
57
|
-
var _exp4 = () => ({ theme, $isError }) => {
|
|
148
|
+
var _exp3 = () => ({ theme, $variant }) => getInputSurfaceColor(theme, $variant);
|
|
149
|
+
var _exp4 = () => ({ theme, $variant, $isError }) => {
|
|
58
150
|
if ($isError) return theme.color.border.error;
|
|
59
|
-
return theme
|
|
151
|
+
return getInputBorderColor(theme, $variant);
|
|
60
152
|
};
|
|
61
153
|
var _exp5 = () => ({ theme }) => theme.color.text.primary;
|
|
62
|
-
var _exp6 = () => ({ theme, $size }) =>
|
|
63
|
-
|
|
64
|
-
};
|
|
65
|
-
var _exp7 = () => ({ theme, $size }) => {
|
|
66
|
-
return match($size).with("SMALL", () => theme.font.sans.height.body_sm).with("MEDIUM", () => theme.font.sans.height.body_md).with("LARGE", () => theme.font.sans.height.body_lg).exhaustive();
|
|
67
|
-
};
|
|
68
|
-
var _exp8 = () => ({ theme, $size }) => {
|
|
69
|
-
return match($size).with("SMALL", () => theme.font.sans.weight.regular).with("MEDIUM", () => theme.font.sans.weight.regular).with("LARGE", () => theme.font.sans.weight.regular).exhaustive();
|
|
70
|
-
};
|
|
154
|
+
var _exp6 = () => ({ theme, $size }) => getInputFontSize(theme, $size);
|
|
155
|
+
var _exp7 = () => ({ theme, $size }) => getInputLineHeight(theme, $size);
|
|
156
|
+
var _exp8 = () => ({ theme }) => theme.font.sans.weight.regular;
|
|
71
157
|
var _exp9 = () => ({ theme, $isMonospace }) => $isMonospace ? theme.font.mono.family : theme.font.sans.family;
|
|
72
158
|
var _exp0 = () => ({ $size, $hasLeadingIcon, $hasTrailingAction }) => {
|
|
73
|
-
const leftPadding =
|
|
74
|
-
return `0 ${
|
|
159
|
+
const leftPadding = $hasLeadingIcon ? getInputHeight($size) : getInputPadding($size);
|
|
160
|
+
return `0 ${$hasTrailingAction ? `${getInputPaddingValue($size) + getInputIconSize($size) + 10}px` : getInputPadding($size)} 0 ${leftPadding}`;
|
|
75
161
|
};
|
|
76
162
|
var _exp1 = () => ({ $isDisabled }) => $isDisabled ? .5 : 1;
|
|
77
|
-
var _exp10 = () => ({ theme }) => theme
|
|
163
|
+
var _exp10 = () => ({ theme, $variant }) => getInputBorderColor(theme, $variant);
|
|
78
164
|
var _exp11 = () => ({ theme }) => theme.color.border.selected;
|
|
79
165
|
var _exp12 = () => ({ theme }) => theme.color.text.tertiary;
|
|
80
166
|
var StyledInput = withTheme(/*#__PURE__*/ styled("input")({
|
|
@@ -105,18 +191,14 @@ var InputContainer = /*#__PURE__*/ styled("div")({
|
|
|
105
191
|
propsAsIs: false,
|
|
106
192
|
vars: { "ixmrsxd-0": [_exp13()] }
|
|
107
193
|
});
|
|
108
|
-
var _exp14 = () => ({ $size }) =>
|
|
109
|
-
return match($size).with("SMALL", () => "6px").with("MEDIUM", () => "8px").with("LARGE", () => "12px").exhaustive();
|
|
110
|
-
};
|
|
194
|
+
var _exp14 = () => ({ $size }) => getInputPadding($size);
|
|
111
195
|
var LeadingIconWrapper = withTheme(/*#__PURE__*/ styled("div")({
|
|
112
196
|
name: "LeadingIconWrapper",
|
|
113
197
|
class: "l8jap54",
|
|
114
198
|
propsAsIs: false,
|
|
115
199
|
vars: { "l8jap54-0": [_exp14()] }
|
|
116
200
|
}));
|
|
117
|
-
var _exp15 = () => ({ $size }) =>
|
|
118
|
-
return match($size).with("SMALL", () => "6px").with("MEDIUM", () => "8px").with("LARGE", () => "12px").exhaustive();
|
|
119
|
-
};
|
|
201
|
+
var _exp15 = () => ({ $size }) => getInputPadding($size);
|
|
120
202
|
var _exp16 = () => ({ $isDisabled }) => $isDisabled ? "not-allowed" : "pointer";
|
|
121
203
|
var TrailingActionButton = /*#__PURE__*/ styled("button")({
|
|
122
204
|
name: "TrailingActionButton",
|
|
@@ -127,11 +209,6 @@ var TrailingActionButton = /*#__PURE__*/ styled("button")({
|
|
|
127
209
|
"t16cwjje-1": [_exp16()]
|
|
128
210
|
}
|
|
129
211
|
});
|
|
130
|
-
var INPUT_SIZE_TO_ICON_SIZE_MAP = {
|
|
131
|
-
["SMALL"]: 12,
|
|
132
|
-
["MEDIUM"]: 14,
|
|
133
|
-
["LARGE"]: 14
|
|
134
|
-
};
|
|
135
212
|
/**
|
|
136
213
|
* The generic text field every typed input wraps. Renders the label, the field,
|
|
137
214
|
* the leading/trailing affordances and the error line.
|
|
@@ -140,7 +217,7 @@ var INPUT_SIZE_TO_ICON_SIZE_MAP = {
|
|
|
140
217
|
* pin `type` and `parse` for you. Use this directly only for a value type none of
|
|
141
218
|
* them cover.
|
|
142
219
|
*/
|
|
143
|
-
var Input = forwardRef(({ parse, onChange, size = "MEDIUM", type, value, label, labelTooltip, error, placeholder, leading, trailing, isRequired, isDisabled, autoFocus, min, max, step, onFocus, onBlur, onKeyDown, width, fillWidth, isMonospace }, ref) => {
|
|
220
|
+
var Input = forwardRef(({ parse, onChange, variant = "PRIMARY", size = "MEDIUM", type, value, label, labelTooltip, error, placeholder, leading, trailing, isRequired, isDisabled, autoFocus, min, max, step, onFocus, onBlur, onKeyDown, width, fillWidth, isMonospace }, ref) => {
|
|
144
221
|
const handleChange = (e) => {
|
|
145
222
|
onChange(parse(e.target.value));
|
|
146
223
|
};
|
|
@@ -165,11 +242,12 @@ var Input = forwardRef(({ parse, onChange, size = "MEDIUM", type, value, label,
|
|
|
165
242
|
children: /* @__PURE__ */ jsx(Icon, {
|
|
166
243
|
component: leading.icon,
|
|
167
244
|
variant: isDisabled ? IconVariant.DISABLED : IconVariant.SECONDARY,
|
|
168
|
-
size:
|
|
245
|
+
size: getInputIconSize(size)
|
|
169
246
|
})
|
|
170
247
|
}),
|
|
171
248
|
/* @__PURE__ */ jsx(StyledInput, {
|
|
172
249
|
$size: size,
|
|
250
|
+
$variant: variant,
|
|
173
251
|
$width: width,
|
|
174
252
|
$fillWidth: fillWidth || hasLeading || hasTrailing,
|
|
175
253
|
$isError: !!error,
|
|
@@ -202,7 +280,7 @@ var Input = forwardRef(({ parse, onChange, size = "MEDIUM", type, value, label,
|
|
|
202
280
|
children: /* @__PURE__ */ jsx(Icon, {
|
|
203
281
|
component: trailing.icon,
|
|
204
282
|
variant: IconVariant.SECONDARY,
|
|
205
|
-
size:
|
|
283
|
+
size: getInputIconSize(size)
|
|
206
284
|
})
|
|
207
285
|
})
|
|
208
286
|
]
|
|
@@ -218,4 +296,4 @@ var Input = forwardRef(({ parse, onChange, size = "MEDIUM", type, value, label,
|
|
|
218
296
|
var InputWithDisplayName = Input;
|
|
219
297
|
InputWithDisplayName.displayName = "Input";
|
|
220
298
|
//#endregion
|
|
221
|
-
export { InputLabel, InputSize, StyledInput, Input as default };
|
|
299
|
+
export { InputLabel, InputSize, InputVariant, StyledInput, Input as default, getInputBorderColor, getInputControlSize, getInputFontSize, getInputHeight, getInputHeightValue, getInputIconSize, getInputLineHeight, getInputPadding, getInputPaddingValue, getInputSurfaceColor, getInputTextSize };
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { type ReactNode } from "react";
|
|
2
2
|
import type { Icon as PhosphorIcon } from "@phosphor-icons/react";
|
|
3
3
|
import { DropdownPosition } from "../dropdown/Dropdown";
|
|
4
|
-
import { InputSize } from "./Input";
|
|
5
|
-
import {
|
|
4
|
+
import { InputSize, InputVariant } from "./Input";
|
|
5
|
+
import { type SelectInputOption } from "./SelectInput";
|
|
6
6
|
export interface PinnedOptions {
|
|
7
7
|
id: string;
|
|
8
8
|
label: string;
|
|
@@ -13,8 +13,8 @@ export interface MultiSelectInputProps {
|
|
|
13
13
|
label?: string;
|
|
14
14
|
/** Phosphor icon *component* on the trigger. */
|
|
15
15
|
icon?: PhosphorIcon;
|
|
16
|
-
/** @default
|
|
17
|
-
variant?:
|
|
16
|
+
/** Trigger surface color. @default InputVariant.PRIMARY */
|
|
17
|
+
variant?: InputVariant;
|
|
18
18
|
/** @default InputSize.MEDIUM */
|
|
19
19
|
size?: InputSize;
|
|
20
20
|
/** Every choice. Order is preserved. */
|
|
@@ -5,36 +5,38 @@ import Text, { TextSize, TextVariant } from "../text/Text.js";
|
|
|
5
5
|
import FlexItem from "../containers/FlexItem.js";
|
|
6
6
|
import Icon, { IconVariant } from "../icons/Icon.js";
|
|
7
7
|
import FlexWrapper, { AlignItems, FlexDirection } from "../containers/FlexWrapper.js";
|
|
8
|
-
import
|
|
8
|
+
import { InputLabel, InputSize, InputVariant, getInputBorderColor, getInputFontSize, getInputHeight, getInputIconSize, getInputLineHeight, getInputPadding, getInputSurfaceColor, getInputTextSize } from "./Input.js";
|
|
9
|
+
import CheckboxInput from "./CheckboxInput.js";
|
|
9
10
|
import Dropdown, { DropdownPosition, DropdownVariant } from "../dropdown/Dropdown.js";
|
|
10
|
-
import { InputLabel, InputSize } from "./Input.js";
|
|
11
11
|
import HorizontalDivider from "../dividers/HorizontalDivider.js";
|
|
12
12
|
import { useElementWidth } from "../hooks/useElementWidth.js";
|
|
13
13
|
import { useControlledOpenState, useDebouncedValue } from "./hooks.js";
|
|
14
|
-
import {
|
|
14
|
+
import { INPUT_VARIANT_TO_ICON_VARIANT_MAP } from "./SelectInput.js";
|
|
15
15
|
/* empty css */
|
|
16
16
|
import { styled } from "@linaria/react";
|
|
17
|
-
import { match } from "ts-pattern";
|
|
18
17
|
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
19
18
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
20
19
|
import { ArrowCounterClockwiseIcon, CaretDownIcon } from "@phosphor-icons/react";
|
|
21
20
|
//#region src/inputs/MultiSelectInput.tsx
|
|
22
|
-
var
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
21
|
+
var INPUT_VARIANT_TO_DROPDOWN_VARIANT = {
|
|
22
|
+
[InputVariant.TRANSPARENT]: DropdownVariant.TRANSPARENT,
|
|
23
|
+
[InputVariant.PRIMARY]: DropdownVariant.PRIMARY,
|
|
24
|
+
[InputVariant.SECONDARY]: DropdownVariant.SECONDARY,
|
|
25
|
+
[InputVariant.TERTIARY]: DropdownVariant.TERTIARY,
|
|
26
|
+
[InputVariant.BASE]: DropdownVariant.PRIMARY
|
|
27
27
|
};
|
|
28
|
+
var _exp = () => ({ $size }) => `0 ${getInputPadding($size)}`;
|
|
29
|
+
var _exp2 = () => ({ $size }) => getInputHeight($size);
|
|
28
30
|
var _exp3 = () => ({ $fillWidth, $width }) => $fillWidth ? "100%" : $width ? getCssSizeValue($width) : "auto";
|
|
29
31
|
var _exp4 = () => ({ $isDisabled }) => $isDisabled ? "not-allowed" : "pointer";
|
|
30
32
|
var _exp5 = () => ({ $isDisabled }) => $isDisabled ? .5 : 1;
|
|
31
|
-
var _exp6 = () => ({ theme }) => theme
|
|
32
|
-
var _exp7 = () => ({ theme, $isActive, $isError }) => {
|
|
33
|
+
var _exp6 = () => ({ theme, $variant }) => getInputSurfaceColor(theme, $variant);
|
|
34
|
+
var _exp7 = () => ({ theme, $variant, $isActive, $isError }) => {
|
|
33
35
|
if ($isActive) return theme.color.border.selected;
|
|
34
36
|
if ($isError) return theme.color.border.error;
|
|
35
|
-
return theme
|
|
37
|
+
return getInputBorderColor(theme, $variant);
|
|
36
38
|
};
|
|
37
|
-
var _exp8 = () => ({ theme, $isActive }) => $isActive ? theme.color.border.selected : theme
|
|
39
|
+
var _exp8 = () => ({ theme, $variant, $isActive }) => $isActive ? theme.color.border.selected : getInputBorderColor(theme, $variant);
|
|
38
40
|
var StyledMultiSelectInput = withTheme(/*#__PURE__*/ styled("div")({
|
|
39
41
|
name: "StyledMultiSelectInput",
|
|
40
42
|
class: "sf4kgcu",
|
|
@@ -50,16 +52,10 @@ var StyledMultiSelectInput = withTheme(/*#__PURE__*/ styled("div")({
|
|
|
50
52
|
"sf4kgcu-7": [_exp8()]
|
|
51
53
|
}
|
|
52
54
|
}));
|
|
53
|
-
var _exp9 = () => ({ $size }) =>
|
|
54
|
-
return match($size).with(InputSize.SMALL, () => "24px").with(InputSize.MEDIUM, () => "28px").with(InputSize.LARGE, () => "32px").exhaustive();
|
|
55
|
-
};
|
|
55
|
+
var _exp9 = () => ({ $size }) => getInputHeight($size);
|
|
56
56
|
var _exp0 = () => ({ theme }) => theme.color.text.primary;
|
|
57
|
-
var _exp1 = () => ({ theme, $size }) =>
|
|
58
|
-
|
|
59
|
-
};
|
|
60
|
-
var _exp10 = () => ({ theme, $size }) => {
|
|
61
|
-
return match($size).with(InputSize.SMALL, () => theme.font.sans.height.body_sm).with(InputSize.MEDIUM, () => theme.font.sans.height.body_md).with(InputSize.LARGE, () => theme.font.sans.height.body_lg).exhaustive();
|
|
62
|
-
};
|
|
57
|
+
var _exp1 = () => ({ theme, $size }) => getInputFontSize(theme, $size);
|
|
58
|
+
var _exp10 = () => ({ theme, $size }) => getInputLineHeight(theme, $size);
|
|
63
59
|
var _exp11 = () => ({ theme }) => theme.font.sans.weight.medium;
|
|
64
60
|
var _exp12 = () => ({ theme }) => theme.font.sans.family;
|
|
65
61
|
var _exp13 = () => ({ theme }) => theme.color.text.tertiary;
|
|
@@ -98,8 +94,8 @@ var MultiSelectInputOptionsContainer = /*#__PURE__*/ styled("div")({
|
|
|
98
94
|
propsAsIs: false,
|
|
99
95
|
vars: { "m1ybiav6-0": [_exp16()] }
|
|
100
96
|
});
|
|
101
|
-
var _exp17 = () => ({ theme, $isFocused }) => $isFocused ? theme.color.background.
|
|
102
|
-
var _exp18 = () => ({ theme }) => theme.color.background.
|
|
97
|
+
var _exp17 = () => ({ theme, $isFocused }) => $isFocused ? theme.color.background.secondary : "transparent";
|
|
98
|
+
var _exp18 = () => ({ theme }) => theme.color.background.secondary;
|
|
103
99
|
var MultiSelectInputOption = withTheme(/*#__PURE__*/ styled("div")({
|
|
104
100
|
name: "MultiSelectInputOption",
|
|
105
101
|
class: "m78p4ib",
|
|
@@ -125,19 +121,13 @@ var OptionIconSlot = /*#__PURE__*/ styled("span")({
|
|
|
125
121
|
class: "o16no7ck",
|
|
126
122
|
propsAsIs: false
|
|
127
123
|
});
|
|
128
|
-
var SELECT_INPUT_VARIANT_TO_CHECKBOX_INPUT_VARIANT = {
|
|
129
|
-
[SelectInputVariant.BASE]: CheckboxInputVariant.SECONDARY,
|
|
130
|
-
[SelectInputVariant.PRIMARY]: CheckboxInputVariant.SECONDARY,
|
|
131
|
-
[SelectInputVariant.SECONDARY]: CheckboxInputVariant.SECONDARY,
|
|
132
|
-
[SelectInputVariant.TERTIARY]: CheckboxInputVariant.PRIMARY
|
|
133
|
-
};
|
|
134
124
|
/**
|
|
135
125
|
* Multi-choice dropdown. Same option shape and search contract as `SelectInput`,
|
|
136
126
|
* but the panel stays open across picks and the trigger summarizes what's chosen.
|
|
137
127
|
*
|
|
138
128
|
* Controlled: `onChange` hands back the complete next selection, not a delta.
|
|
139
129
|
*/
|
|
140
|
-
var MultiSelectInput = ({ label, icon, variant =
|
|
130
|
+
var MultiSelectInput = ({ label, icon, variant = InputVariant.PRIMARY, size = InputSize.MEDIUM, options, value, placeholder = "Select options...", onChange, width, fillWidth, dropdownWidth, dropdownPlacement = DropdownPosition.BOTTOM_START, isDisabled = false, isRequired = false, isOpen: controlledIsOpen, isIconTrailing, onOpenChange, onReset, pinnedOptions = [], maxDisplayItems = 3, renderSelectedText, renderSelectedContent, error, onSearch, debounceMs = 300 }) => {
|
|
141
131
|
const isSearchable = !!onSearch;
|
|
142
132
|
const [isHovered, setIsHovered] = useState(false);
|
|
143
133
|
const [searchTerm, setSearchTerm] = useState("");
|
|
@@ -174,7 +164,7 @@ var MultiSelectInput = ({ label, icon, variant = SelectInputVariant.PRIMARY, siz
|
|
|
174
164
|
}
|
|
175
165
|
const renderIcon = useCallback(() => {
|
|
176
166
|
if (!icon) return null;
|
|
177
|
-
let iconVariant =
|
|
167
|
+
let iconVariant = INPUT_VARIANT_TO_ICON_VARIANT_MAP[variant];
|
|
178
168
|
if (isDisabled) iconVariant = IconVariant.TERTIARY;
|
|
179
169
|
return /* @__PURE__ */ jsx(FlexItem, {
|
|
180
170
|
shrink: 0,
|
|
@@ -182,7 +172,7 @@ var MultiSelectInput = ({ label, icon, variant = SelectInputVariant.PRIMARY, siz
|
|
|
182
172
|
children: /* @__PURE__ */ jsx(Icon, {
|
|
183
173
|
component: icon,
|
|
184
174
|
variant: iconVariant,
|
|
185
|
-
size:
|
|
175
|
+
size: getInputIconSize(size)
|
|
186
176
|
})
|
|
187
177
|
});
|
|
188
178
|
}, [
|
|
@@ -335,6 +325,7 @@ var MultiSelectInput = ({ label, icon, variant = SelectInputVariant.PRIMARY, siz
|
|
|
335
325
|
optionsRefs.current[index] = el;
|
|
336
326
|
},
|
|
337
327
|
$isFocused: isPinnedOptionFocused(index),
|
|
328
|
+
$size: size,
|
|
338
329
|
onClick: (e) => {
|
|
339
330
|
e.preventDefault();
|
|
340
331
|
handlePinnedOptionToggle(pinnedOption);
|
|
@@ -345,7 +336,8 @@ var MultiSelectInput = ({ label, icon, variant = SelectInputVariant.PRIMARY, siz
|
|
|
345
336
|
gap: 8,
|
|
346
337
|
fillWidth: true,
|
|
347
338
|
children: [/* @__PURE__ */ jsx(CheckboxInput, {
|
|
348
|
-
variant
|
|
339
|
+
variant,
|
|
340
|
+
size,
|
|
349
341
|
isChecked: isPinnedOptionSelected(pinnedOption),
|
|
350
342
|
onChange: noop
|
|
351
343
|
}), /* @__PURE__ */ jsx(FlexItem, {
|
|
@@ -354,7 +346,7 @@ var MultiSelectInput = ({ label, icon, variant = SelectInputVariant.PRIMARY, siz
|
|
|
354
346
|
minWidth: 0,
|
|
355
347
|
children: /* @__PURE__ */ jsx(Text, {
|
|
356
348
|
variant: TextVariant.PRIMARY,
|
|
357
|
-
size:
|
|
349
|
+
size: getInputTextSize(size),
|
|
358
350
|
cursor: !effectiveIsDisabled ? "pointer" : "not-allowed",
|
|
359
351
|
isEllipsis: true,
|
|
360
352
|
children: pinnedOption.label
|
|
@@ -386,7 +378,8 @@ var MultiSelectInput = ({ label, icon, variant = SelectInputVariant.PRIMARY, siz
|
|
|
386
378
|
fillWidth: true,
|
|
387
379
|
children: [
|
|
388
380
|
/* @__PURE__ */ jsx(CheckboxInput, {
|
|
389
|
-
variant
|
|
381
|
+
variant,
|
|
382
|
+
size,
|
|
390
383
|
isChecked: isOptionSelected(option.id),
|
|
391
384
|
onChange: noop
|
|
392
385
|
}),
|
|
@@ -397,7 +390,7 @@ var MultiSelectInput = ({ label, icon, variant = SelectInputVariant.PRIMARY, siz
|
|
|
397
390
|
minWidth: 0,
|
|
398
391
|
children: /* @__PURE__ */ jsx(Text, {
|
|
399
392
|
variant: option.variant ?? TextVariant.PRIMARY,
|
|
400
|
-
size:
|
|
393
|
+
size: getInputTextSize(size),
|
|
401
394
|
cursor: !effectiveIsDisabled ? "pointer" : "not-allowed",
|
|
402
395
|
isEllipsis: true,
|
|
403
396
|
children: option.label
|
|
@@ -410,7 +403,7 @@ var MultiSelectInput = ({ label, icon, variant = SelectInputVariant.PRIMARY, siz
|
|
|
410
403
|
style: { padding: "8px" },
|
|
411
404
|
children: /* @__PURE__ */ jsx(Text, {
|
|
412
405
|
variant: TextVariant.TERTIARY,
|
|
413
|
-
size:
|
|
406
|
+
size: getInputTextSize(size),
|
|
414
407
|
children: "No options found"
|
|
415
408
|
})
|
|
416
409
|
})
|
|
@@ -421,16 +414,17 @@ var MultiSelectInput = ({ label, icon, variant = SelectInputVariant.PRIMARY, siz
|
|
|
421
414
|
}), /* @__PURE__ */ jsx(PinnedOptionButton, {
|
|
422
415
|
onClick: handleReset,
|
|
423
416
|
$isFocused: false,
|
|
417
|
+
$size: size,
|
|
424
418
|
children: /* @__PURE__ */ jsxs(FlexWrapper, {
|
|
425
419
|
alignItems: AlignItems.CENTER,
|
|
426
420
|
gap: 8,
|
|
427
421
|
children: [/* @__PURE__ */ jsx(Icon, {
|
|
428
422
|
component: ArrowCounterClockwiseIcon,
|
|
429
423
|
variant: IconVariant.TERTIARY,
|
|
430
|
-
size:
|
|
424
|
+
size: getInputIconSize(size)
|
|
431
425
|
}), /* @__PURE__ */ jsx(Text, {
|
|
432
426
|
variant: TextVariant.PRIMARY,
|
|
433
|
-
size:
|
|
427
|
+
size: getInputTextSize(size),
|
|
434
428
|
cursor: !effectiveIsDisabled ? "pointer" : "not-allowed",
|
|
435
429
|
children: "Reset"
|
|
436
430
|
})]
|
|
@@ -467,7 +461,7 @@ var MultiSelectInput = ({ label, icon, variant = SelectInputVariant.PRIMARY, siz
|
|
|
467
461
|
isRequired
|
|
468
462
|
}),
|
|
469
463
|
/* @__PURE__ */ jsx(Dropdown, {
|
|
470
|
-
variant:
|
|
464
|
+
variant: INPUT_VARIANT_TO_DROPDOWN_VARIANT[variant],
|
|
471
465
|
body: dropdownBody,
|
|
472
466
|
isOpen: visible,
|
|
473
467
|
onClose: handleClose,
|
|
@@ -492,7 +486,6 @@ var MultiSelectInput = ({ label, icon, variant = SelectInputVariant.PRIMARY, siz
|
|
|
492
486
|
!isIconTrailing && renderIcon(),
|
|
493
487
|
/* @__PURE__ */ jsx(StyledSearchInput, {
|
|
494
488
|
ref: inputRef,
|
|
495
|
-
$variant: variant,
|
|
496
489
|
$size: size,
|
|
497
490
|
$isActive: visible ?? false,
|
|
498
491
|
$isDisabled: effectiveIsDisabled,
|
|
@@ -514,7 +507,7 @@ var MultiSelectInput = ({ label, icon, variant = SelectInputVariant.PRIMARY, siz
|
|
|
514
507
|
deg: -180,
|
|
515
508
|
children: /* @__PURE__ */ jsx(Icon, {
|
|
516
509
|
component: CaretDownIcon,
|
|
517
|
-
size:
|
|
510
|
+
size: getInputIconSize(size),
|
|
518
511
|
variant: !effectiveIsDisabled && (isHovered || visible) ? IconVariant.SECONDARY : IconVariant.TERTIARY
|
|
519
512
|
})
|
|
520
513
|
}) }),
|
|
@@ -542,7 +535,7 @@ var MultiSelectInput = ({ label, icon, variant = SelectInputVariant.PRIMARY, siz
|
|
|
542
535
|
!isIconTrailing && renderIcon(),
|
|
543
536
|
renderSelectedContent ? renderSelectedContent(value, placeholder) : /* @__PURE__ */ jsx(Text, {
|
|
544
537
|
variant: textVariant,
|
|
545
|
-
size:
|
|
538
|
+
size: getInputTextSize(size),
|
|
546
539
|
cursor: !effectiveIsDisabled ? "pointer" : "not-allowed",
|
|
547
540
|
isEllipsis: true,
|
|
548
541
|
children: displayValue
|
|
@@ -552,7 +545,7 @@ var MultiSelectInput = ({ label, icon, variant = SelectInputVariant.PRIMARY, siz
|
|
|
552
545
|
deg: -180,
|
|
553
546
|
children: /* @__PURE__ */ jsx(Icon, {
|
|
554
547
|
component: CaretDownIcon,
|
|
555
|
-
size:
|
|
548
|
+
size: getInputIconSize(size),
|
|
556
549
|
variant: !effectiveIsDisabled && (isHovered || visible) ? IconVariant.SECONDARY : IconVariant.TERTIARY
|
|
557
550
|
})
|
|
558
551
|
}) }),
|
|
@@ -1,24 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
export declare enum MultiTextInputSize {
|
|
3
|
-
SMALL = "SMALL",
|
|
4
|
-
MEDIUM = "MEDIUM",
|
|
5
|
-
LARGE = "LARGE"
|
|
6
|
-
}
|
|
7
|
-
/** Color of the chips created from entered values. */
|
|
8
|
-
export declare enum MultiTextInputVariant {
|
|
9
|
-
PRIMARY = "PRIMARY",
|
|
10
|
-
SECONDARY = "SECONDARY",
|
|
11
|
-
TERTIARY = "TERTIARY"
|
|
12
|
-
}
|
|
1
|
+
import { InputSize, InputVariant } from "./Input";
|
|
13
2
|
export interface MultiTextInputProps {
|
|
14
3
|
/** Controlled list of entered values, one chip each. */
|
|
15
4
|
value: string[];
|
|
16
5
|
/** Called with the full next list, not a delta. */
|
|
17
6
|
onChange: (value: string[]) => void;
|
|
18
|
-
/** @default
|
|
19
|
-
variant?:
|
|
20
|
-
/** @default
|
|
21
|
-
size?:
|
|
7
|
+
/** Field surface color. @default InputVariant.PRIMARY */
|
|
8
|
+
variant?: InputVariant;
|
|
9
|
+
/** @default InputSize.MEDIUM */
|
|
10
|
+
size?: InputSize;
|
|
22
11
|
placeholder?: string;
|
|
23
12
|
label?: string;
|
|
24
13
|
/** Message under the field; also switches the border to the error color. */
|