@mattermost/compass-ui 0.1.0-alpha.16 → 0.1.0-alpha.18
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/components/error-message/ErrorMessage.cjs +1 -1
- package/dist/components/error-message/ErrorMessage.cjs.map +1 -1
- package/dist/components/error-message/ErrorMessage.d.ts +2 -3
- package/dist/components/error-message/ErrorMessage.d.ts.map +1 -1
- package/dist/components/error-message/ErrorMessage.js +16 -14
- package/dist/components/error-message/ErrorMessage.js.map +1 -1
- package/dist/components/field/FieldClearButton.cjs +2 -0
- package/dist/components/field/FieldClearButton.cjs.map +1 -0
- package/dist/components/field/FieldClearButton.css +1 -0
- package/dist/components/field/FieldClearButton.d.ts +17 -0
- package/dist/components/field/FieldClearButton.d.ts.map +1 -0
- package/dist/components/field/FieldClearButton.js +40 -0
- package/dist/components/field/FieldClearButton.js.map +1 -0
- package/dist/components/field/FieldClearButton.module.scss.cjs +2 -0
- package/dist/components/field/FieldClearButton.module.scss.cjs.map +1 -0
- package/dist/components/field/FieldClearButton.module.scss.js +7 -0
- package/dist/components/field/FieldClearButton.module.scss.js.map +1 -0
- package/dist/components/field/fieldDescribedBy.cjs +2 -0
- package/dist/components/field/fieldDescribedBy.cjs.map +1 -0
- package/dist/components/field/fieldDescribedBy.d.ts +11 -0
- package/dist/components/field/fieldDescribedBy.d.ts.map +1 -0
- package/dist/components/field/fieldDescribedBy.js +15 -0
- package/dist/components/field/fieldDescribedBy.js.map +1 -0
- package/dist/components/field/useFieldClear.cjs +2 -0
- package/dist/components/field/useFieldClear.cjs.map +1 -0
- package/dist/components/field/useFieldClear.d.ts +21 -0
- package/dist/components/field/useFieldClear.d.ts.map +1 -0
- package/dist/components/field/useFieldClear.js +73 -0
- package/dist/components/field/useFieldClear.js.map +1 -0
- package/dist/components/field-message/FieldMessage.cjs +2 -0
- package/dist/components/field-message/FieldMessage.cjs.map +1 -0
- package/dist/components/field-message/FieldMessage.css +1 -0
- package/dist/components/field-message/FieldMessage.d.ts +17 -0
- package/dist/components/field-message/FieldMessage.d.ts.map +1 -0
- package/dist/components/field-message/FieldMessage.js +28 -0
- package/dist/components/field-message/FieldMessage.js.map +1 -0
- package/dist/components/field-message/FieldMessage.module.scss.cjs +2 -0
- package/dist/components/field-message/FieldMessage.module.scss.cjs.map +1 -0
- package/dist/components/field-message/FieldMessage.module.scss.js +13 -0
- package/dist/components/field-message/FieldMessage.module.scss.js.map +1 -0
- package/dist/components/field-message/index.cjs +2 -0
- package/dist/components/field-message/index.cjs.map +1 -0
- package/dist/components/field-message/index.d.ts +3 -0
- package/dist/components/field-message/index.d.ts.map +1 -0
- package/dist/components/field-message/index.js +5 -0
- package/dist/components/field-message/index.js.map +1 -0
- package/dist/components/password-input/PasswordInput.cjs +2 -0
- package/dist/components/password-input/PasswordInput.cjs.map +1 -0
- package/dist/components/password-input/PasswordInput.css +1 -0
- package/dist/components/password-input/PasswordInput.d.ts +49 -0
- package/dist/components/password-input/PasswordInput.d.ts.map +1 -0
- package/dist/components/password-input/PasswordInput.js +140 -0
- package/dist/components/password-input/PasswordInput.js.map +1 -0
- package/dist/components/password-input/PasswordInput.module.scss.cjs +2 -0
- package/dist/components/password-input/PasswordInput.module.scss.cjs.map +1 -0
- package/dist/components/password-input/PasswordInput.module.scss.js +18 -0
- package/dist/components/password-input/PasswordInput.module.scss.js.map +1 -0
- package/dist/components/password-input/index.cjs +2 -0
- package/dist/components/password-input/index.cjs.map +1 -0
- package/dist/components/password-input/index.d.ts +3 -0
- package/dist/components/password-input/index.d.ts.map +1 -0
- package/dist/components/password-input/index.js +5 -0
- package/dist/components/password-input/index.js.map +1 -0
- package/dist/components/search-input/SearchInput.cjs +1 -1
- package/dist/components/search-input/SearchInput.cjs.map +1 -1
- package/dist/components/search-input/SearchInput.css +1 -1
- package/dist/components/search-input/SearchInput.d.ts +8 -0
- package/dist/components/search-input/SearchInput.d.ts.map +1 -1
- package/dist/components/search-input/SearchInput.js +114 -115
- package/dist/components/search-input/SearchInput.js.map +1 -1
- package/dist/components/search-input/SearchInput.module.scss.cjs +1 -1
- package/dist/components/search-input/SearchInput.module.scss.js +15 -16
- package/dist/components/search-input/SearchInput.module.scss.js.map +1 -1
- package/dist/components/section-notice/SectionNotice.css +1 -1
- package/dist/components/section-notice/SectionNotice.module.scss.cjs +1 -1
- package/dist/components/section-notice/SectionNotice.module.scss.js +12 -12
- package/dist/components/text-area/TextArea.cjs +1 -1
- package/dist/components/text-area/TextArea.cjs.map +1 -1
- package/dist/components/text-area/TextArea.css +1 -1
- package/dist/components/text-area/TextArea.d.ts +8 -0
- package/dist/components/text-area/TextArea.d.ts.map +1 -1
- package/dist/components/text-area/TextArea.js +86 -67
- package/dist/components/text-area/TextArea.js.map +1 -1
- package/dist/components/text-area/TextArea.module.scss.cjs +1 -1
- package/dist/components/text-area/TextArea.module.scss.js +12 -10
- package/dist/components/text-area/TextArea.module.scss.js.map +1 -1
- package/dist/components/text-input/TextInput.cjs +1 -1
- package/dist/components/text-input/TextInput.cjs.map +1 -1
- package/dist/components/text-input/TextInput.css +1 -1
- package/dist/components/text-input/TextInput.d.ts +38 -1
- package/dist/components/text-input/TextInput.d.ts.map +1 -1
- package/dist/components/text-input/TextInput.js +149 -93
- package/dist/components/text-input/TextInput.js.map +1 -1
- package/dist/components/text-input/TextInput.module.scss.cjs +1 -1
- package/dist/components/text-input/TextInput.module.scss.js +19 -14
- package/dist/components/text-input/TextInput.module.scss.js.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +133 -129
- package/dist/index.js.map +1 -1
- package/package.json +7 -1
- package/dist/components/error-message/ErrorMessage.css +0 -1
- package/dist/components/error-message/ErrorMessage.module.scss.cjs +0 -2
- package/dist/components/error-message/ErrorMessage.module.scss.cjs.map +0 -1
- package/dist/components/error-message/ErrorMessage.module.scss.js +0 -9
- package/dist/components/error-message/ErrorMessage.module.scss.js.map +0 -1
|
@@ -1,94 +1,113 @@
|
|
|
1
|
-
import { jsxs as
|
|
2
|
-
import { forwardRef as
|
|
3
|
-
import {
|
|
1
|
+
import { jsxs as c, jsx as x } from "react/jsx-runtime";
|
|
2
|
+
import { forwardRef as B, useId as C, useState as h, useCallback as _ } from "react";
|
|
3
|
+
import { mergeFieldDescribedBy as P, hasFieldMessage as L, isFieldInvalid as ee } from "../field/fieldDescribedBy.js";
|
|
4
|
+
import te from "../field-message/FieldMessage.js";
|
|
5
|
+
import { toKebab as ae } from "../../utils/string.js";
|
|
4
6
|
import e from "./TextArea.module.scss.js";
|
|
5
|
-
const
|
|
7
|
+
const ne = B(
|
|
6
8
|
function({
|
|
7
9
|
className: j = "",
|
|
8
|
-
size:
|
|
9
|
-
label:
|
|
10
|
-
invalid:
|
|
11
|
-
maxLength:
|
|
12
|
-
showCharacterCount:
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
10
|
+
size: M = "medium",
|
|
11
|
+
label: n,
|
|
12
|
+
invalid: V = !1,
|
|
13
|
+
maxLength: a,
|
|
14
|
+
showCharacterCount: f = !1,
|
|
15
|
+
message: u,
|
|
16
|
+
messageTone: b,
|
|
17
|
+
id: $,
|
|
18
|
+
value: m,
|
|
19
|
+
defaultValue: p,
|
|
20
|
+
placeholder: g,
|
|
21
|
+
onFocus: l,
|
|
22
|
+
onBlur: i,
|
|
23
|
+
onChange: r,
|
|
24
|
+
disabled: w,
|
|
21
25
|
readOnly: z,
|
|
22
26
|
rows: A = 3,
|
|
23
|
-
"aria-describedby":
|
|
24
|
-
...
|
|
25
|
-
},
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
),
|
|
27
|
+
"aria-describedby": T,
|
|
28
|
+
...k
|
|
29
|
+
}, D) {
|
|
30
|
+
const K = C(), o = $ ?? K, s = m !== void 0, [R, S] = h(
|
|
31
|
+
p ?? ""
|
|
32
|
+
), d = s ? m : R, U = d != null && d !== "", [q, I] = h(!1), E = q || U, G = _(
|
|
29
33
|
(t) => {
|
|
30
|
-
|
|
34
|
+
I(!0), l == null || l(t);
|
|
31
35
|
},
|
|
32
|
-
[
|
|
33
|
-
),
|
|
36
|
+
[l]
|
|
37
|
+
), H = _(
|
|
34
38
|
(t) => {
|
|
35
|
-
|
|
39
|
+
I(!1), i == null || i(t);
|
|
36
40
|
},
|
|
37
|
-
[
|
|
38
|
-
),
|
|
41
|
+
[i]
|
|
42
|
+
), J = _(
|
|
39
43
|
(t) => {
|
|
40
|
-
|
|
44
|
+
s || S(t.target.value), r == null || r(t);
|
|
41
45
|
},
|
|
42
|
-
[
|
|
43
|
-
),
|
|
46
|
+
[s, r]
|
|
47
|
+
), N = ee(V, u, b), v = L(u), O = e[`text-area--size-${ae(M)}`], Q = N ? e["text-area--invalid"] : "", W = n != null && E ? e["text-area--label-floated"] : "", X = [
|
|
44
48
|
e["text-area"],
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
49
|
+
O,
|
|
50
|
+
Q,
|
|
51
|
+
W,
|
|
48
52
|
j
|
|
49
|
-
].filter(Boolean).join(" "),
|
|
50
|
-
return /* @__PURE__ */
|
|
51
|
-
/* @__PURE__ */
|
|
52
|
-
|
|
53
|
-
/* @__PURE__ */
|
|
53
|
+
].filter(Boolean).join(" "), Y = typeof d == "string" ? d.length : 0, F = f && a != null ? `${o}-counter` : void 0, y = v ? `${o}-message` : void 0, Z = b ?? "error";
|
|
54
|
+
return /* @__PURE__ */ c("div", { className: X, children: [
|
|
55
|
+
/* @__PURE__ */ c("div", { className: e["text-area__wrapper"], children: [
|
|
56
|
+
n != null && /* @__PURE__ */ x("label", { className: e["text-area__label"], htmlFor: o, children: n }),
|
|
57
|
+
/* @__PURE__ */ x(
|
|
54
58
|
"textarea",
|
|
55
59
|
{
|
|
56
|
-
ref:
|
|
57
|
-
id:
|
|
60
|
+
ref: D,
|
|
61
|
+
id: o,
|
|
58
62
|
className: e["text-area__input"],
|
|
59
|
-
value:
|
|
60
|
-
defaultValue:
|
|
61
|
-
placeholder:
|
|
62
|
-
maxLength:
|
|
63
|
-
disabled:
|
|
63
|
+
value: s ? m : void 0,
|
|
64
|
+
defaultValue: s ? void 0 : p,
|
|
65
|
+
placeholder: g,
|
|
66
|
+
maxLength: a,
|
|
67
|
+
disabled: w,
|
|
64
68
|
readOnly: z,
|
|
65
69
|
rows: A,
|
|
66
|
-
"aria-invalid":
|
|
67
|
-
"aria-describedby":
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
70
|
+
"aria-invalid": N ? !0 : void 0,
|
|
71
|
+
"aria-describedby": P(
|
|
72
|
+
T,
|
|
73
|
+
y,
|
|
74
|
+
F
|
|
75
|
+
),
|
|
76
|
+
onFocus: G,
|
|
77
|
+
onBlur: H,
|
|
78
|
+
onChange: J,
|
|
79
|
+
...k
|
|
72
80
|
}
|
|
73
81
|
)
|
|
74
82
|
] }),
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
83
|
+
(v || f && a != null) && /* @__PURE__ */ c("div", { className: e["text-area__footer"], children: [
|
|
84
|
+
v && /* @__PURE__ */ x(
|
|
85
|
+
te,
|
|
86
|
+
{
|
|
87
|
+
id: y,
|
|
88
|
+
className: e["text-area__footer-message"],
|
|
89
|
+
message: u,
|
|
90
|
+
tone: Z
|
|
91
|
+
}
|
|
92
|
+
),
|
|
93
|
+
f && a != null && /* @__PURE__ */ c(
|
|
94
|
+
"div",
|
|
95
|
+
{
|
|
96
|
+
id: F,
|
|
97
|
+
className: e["text-area__counter"],
|
|
98
|
+
"aria-live": "polite",
|
|
99
|
+
children: [
|
|
100
|
+
Y,
|
|
101
|
+
" / ",
|
|
102
|
+
a
|
|
103
|
+
]
|
|
104
|
+
}
|
|
105
|
+
)
|
|
106
|
+
] })
|
|
88
107
|
] });
|
|
89
108
|
}
|
|
90
109
|
);
|
|
91
110
|
export {
|
|
92
|
-
|
|
111
|
+
ne as default
|
|
93
112
|
};
|
|
94
113
|
//# sourceMappingURL=TextArea.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TextArea.js","sources":["../../../src/components/text-area/TextArea.tsx"],"sourcesContent":["import type { TextareaHTMLAttributes, ReactNode, ChangeEvent } from 'react';\nimport { forwardRef, useId, useState, useCallback } from 'react';\nimport { toKebab } from '@/utils/string';\nimport styles from './TextArea.module.scss';\n\nexport type TextAreaSize = 'small' | 'medium' | 'large';\n\nexport interface TextAreaProps extends Omit<\n TextareaHTMLAttributes<HTMLTextAreaElement>,\n 'size'\n> {\n /** Optional CSS class name. */\n className?: string;\n /** When true, shows invalid/error styling. */\n invalid?: boolean;\n /** Floating label content. When provided, label floats on focus or when value is non-empty. */\n label?: ReactNode;\n /** Max length for the textarea; used with showCharacterCount for counter. */\n maxLength?: number;\n /** When true with maxLength, shows \"current / max\" character count below textarea. */\n showCharacterCount?: boolean;\n /** Size variant. Default: Medium. */\n size?: TextAreaSize;\n}\n\n/**\n * Text Areas let people write long-form text that spans multiple lines — descriptions,\n * channel purposes, message drafts, admin notes. They share their visual rhythm with Text\n * Input but trade the single-line constraint for room to breathe.\n */\nconst TextArea = forwardRef<HTMLTextAreaElement, TextAreaProps>(\n function TextArea(\n {\n className = '',\n size = 'medium',\n label,\n invalid = false,\n maxLength,\n showCharacterCount = false,\n id: idProp,\n value: valueProp,\n defaultValue,\n placeholder,\n onFocus,\n onBlur,\n onChange,\n disabled,\n readOnly,\n rows = 3,\n 'aria-describedby': describedBy,\n ...rest\n },\n ref,\n ) {\n const generatedId = useId();\n const id = idProp ?? generatedId;\n\n const isControlled = valueProp !== undefined;\n const [uncontrolledValue, setUncontrolledValue] = useState(\n defaultValue ?? '',\n );\n const value = isControlled ? (valueProp as string) : uncontrolledValue;\n const hasValue = value != null && value !== '';\n\n const [isFocused, setIsFocused] = useState(false);\n const labelFloated = isFocused || hasValue;\n\n const handleFocus = useCallback(\n (e: React.FocusEvent<HTMLTextAreaElement>) => {\n setIsFocused(true);\n onFocus?.(e);\n },\n [onFocus],\n );\n const handleBlur = useCallback(\n (e: React.FocusEvent<HTMLTextAreaElement>) => {\n setIsFocused(false);\n onBlur?.(e);\n },\n [onBlur],\n );\n const handleChange = useCallback(\n (e: ChangeEvent<HTMLTextAreaElement>) => {\n if (!isControlled) setUncontrolledValue(e.target.value);\n onChange?.(e);\n },\n [isControlled, onChange],\n );\n\n const sizeClass = styles[`text-area--size-${toKebab(size)}`];\n const invalidClass =
|
|
1
|
+
{"version":3,"file":"TextArea.js","sources":["../../../src/components/text-area/TextArea.tsx"],"sourcesContent":["import type { TextareaHTMLAttributes, ReactNode, ChangeEvent } from 'react';\nimport { forwardRef, useId, useState, useCallback } from 'react';\nimport {\n hasFieldMessage,\n isFieldInvalid,\n mergeFieldDescribedBy,\n} from '@/components/field/fieldDescribedBy';\nimport FieldMessage from '@/components/field-message/FieldMessage';\nimport type { FieldMessageTone } from '@/components/field-message/FieldMessage';\nimport { toKebab } from '@/utils/string';\nimport styles from './TextArea.module.scss';\n\nexport type TextAreaSize = 'small' | 'medium' | 'large';\n\nexport interface TextAreaProps extends Omit<\n TextareaHTMLAttributes<HTMLTextAreaElement>,\n 'size'\n> {\n /** Optional CSS class name. */\n className?: string;\n /** When true, shows invalid/error styling. */\n invalid?: boolean;\n /** Floating label content. When provided, label floats on focus or when value is non-empty. */\n label?: ReactNode;\n /** Max length for the textarea; used with showCharacterCount for counter. */\n maxLength?: number;\n /** When true with maxLength, shows \"current / max\" character count below textarea. */\n showCharacterCount?: boolean;\n /** Size variant. Default: Medium. */\n size?: TextAreaSize;\n /**\n * Field message under the field. Accepts translated nodes (e.g. `<FormattedMessage/>`).\n * Defaults to error tone (invalid chrome) when set without `messageTone`.\n */\n message?: ReactNode;\n /** Visual tone for `message`. Default: `error` when `message` is set. */\n messageTone?: FieldMessageTone;\n}\n\n/**\n * Text Areas let people write long-form text that spans multiple lines — descriptions,\n * channel purposes, message drafts, admin notes. They share their visual rhythm with Text\n * Input but trade the single-line constraint for room to breathe.\n */\nconst TextArea = forwardRef<HTMLTextAreaElement, TextAreaProps>(\n function TextArea(\n {\n className = '',\n size = 'medium',\n label,\n invalid = false,\n maxLength,\n showCharacterCount = false,\n message,\n messageTone,\n id: idProp,\n value: valueProp,\n defaultValue,\n placeholder,\n onFocus,\n onBlur,\n onChange,\n disabled,\n readOnly,\n rows = 3,\n 'aria-describedby': describedBy,\n ...rest\n },\n ref,\n ) {\n const generatedId = useId();\n const id = idProp ?? generatedId;\n\n const isControlled = valueProp !== undefined;\n const [uncontrolledValue, setUncontrolledValue] = useState(\n defaultValue ?? '',\n );\n const value = isControlled ? (valueProp as string) : uncontrolledValue;\n const hasValue = value != null && value !== '';\n\n const [isFocused, setIsFocused] = useState(false);\n const labelFloated = isFocused || hasValue;\n\n const handleFocus = useCallback(\n (e: React.FocusEvent<HTMLTextAreaElement>) => {\n setIsFocused(true);\n onFocus?.(e);\n },\n [onFocus],\n );\n const handleBlur = useCallback(\n (e: React.FocusEvent<HTMLTextAreaElement>) => {\n setIsFocused(false);\n onBlur?.(e);\n },\n [onBlur],\n );\n const handleChange = useCallback(\n (e: ChangeEvent<HTMLTextAreaElement>) => {\n if (!isControlled) setUncontrolledValue(e.target.value);\n onChange?.(e);\n },\n [isControlled, onChange],\n );\n\n const showInvalid = isFieldInvalid(invalid, message, messageTone);\n const showMessage = hasFieldMessage(message);\n const sizeClass = styles[`text-area--size-${toKebab(size)}`];\n const invalidClass = showInvalid ? styles['text-area--invalid'] : '';\n const labelFloatedClass =\n label != null && labelFloated ? styles['text-area--label-floated'] : '';\n\n const rootClass = [\n styles['text-area'],\n sizeClass,\n invalidClass,\n labelFloatedClass,\n className,\n ]\n .filter(Boolean)\n .join(' ');\n\n const currentLength = typeof value === 'string' ? value.length : 0;\n const counterId =\n showCharacterCount && maxLength != null ? `${id}-counter` : undefined;\n const messageId = showMessage ? `${id}-message` : undefined;\n const resolvedTone = messageTone ?? 'error';\n\n return (\n <div className={rootClass}>\n <div className={styles['text-area__wrapper']}>\n {label != null && (\n <label className={styles['text-area__label']} htmlFor={id}>\n {label}\n </label>\n )}\n <textarea\n ref={ref}\n id={id}\n className={styles['text-area__input']}\n value={isControlled ? valueProp : undefined}\n defaultValue={isControlled ? undefined : defaultValue}\n placeholder={placeholder}\n maxLength={maxLength}\n disabled={disabled}\n readOnly={readOnly}\n rows={rows}\n aria-invalid={showInvalid ? true : undefined}\n aria-describedby={mergeFieldDescribedBy(\n describedBy,\n messageId,\n counterId,\n )}\n onFocus={handleFocus}\n onBlur={handleBlur}\n onChange={handleChange}\n {...rest}\n />\n </div>\n {(showMessage || (showCharacterCount && maxLength != null)) && (\n <div className={styles['text-area__footer']}>\n {showMessage && (\n <FieldMessage\n id={messageId}\n className={styles['text-area__footer-message']}\n message={message}\n tone={resolvedTone}\n />\n )}\n {showCharacterCount && maxLength != null && (\n <div\n id={counterId}\n className={styles['text-area__counter']}\n aria-live=\"polite\"\n >\n {currentLength} / {maxLength}\n </div>\n )}\n </div>\n )}\n </div>\n );\n },\n);\n\nexport default TextArea;\n"],"names":["TextArea","forwardRef","className","size","label","invalid","maxLength","showCharacterCount","message","messageTone","idProp","valueProp","defaultValue","placeholder","onFocus","onBlur","onChange","disabled","readOnly","rows","describedBy","rest","ref","generatedId","useId","id","isControlled","uncontrolledValue","setUncontrolledValue","useState","value","hasValue","isFocused","setIsFocused","labelFloated","handleFocus","useCallback","e","handleBlur","handleChange","showInvalid","isFieldInvalid","showMessage","hasFieldMessage","sizeClass","styles","toKebab","invalidClass","labelFloatedClass","rootClass","currentLength","counterId","messageId","resolvedTone","jsxs","jsx","mergeFieldDescribedBy","FieldMessage"],"mappings":";;;;;;AA4CA,MAAMA,KAAWC;AAAA,EACf,SACE;AAAA,IACE,WAAAC,IAAY;AAAA,IACZ,MAAAC,IAAO;AAAA,IACP,OAAAC;AAAA,IACA,SAAAC,IAAU;AAAA,IACV,WAAAC;AAAA,IACA,oBAAAC,IAAqB;AAAA,IACrB,SAAAC;AAAA,IACA,aAAAC;AAAA,IACA,IAAIC;AAAA,IACJ,OAAOC;AAAA,IACP,cAAAC;AAAA,IACA,aAAAC;AAAA,IACA,SAAAC;AAAA,IACA,QAAAC;AAAA,IACA,UAAAC;AAAA,IACA,UAAAC;AAAA,IACA,UAAAC;AAAA,IACA,MAAAC,IAAO;AAAA,IACP,oBAAoBC;AAAA,IACpB,GAAGC;AAAA,EAAA,GAELC,GACA;AACA,UAAMC,IAAcC,EAAA,GACdC,IAAKf,KAAUa,GAEfG,IAAef,MAAc,QAC7B,CAACgB,GAAmBC,CAAoB,IAAIC;AAAA,MAChDjB,KAAgB;AAAA,IAAA,GAEZkB,IAAQJ,IAAgBf,IAAuBgB,GAC/CI,IAAWD,KAAS,QAAQA,MAAU,IAEtC,CAACE,GAAWC,CAAY,IAAIJ,EAAS,EAAK,GAC1CK,IAAeF,KAAaD,GAE5BI,IAAcC;AAAA,MAClB,CAACC,MAA6C;AAC5C,QAAAJ,EAAa,EAAI,GACjBnB,KAAA,QAAAA,EAAUuB;AAAA,MACZ;AAAA,MACA,CAACvB,CAAO;AAAA,IAAA,GAEJwB,IAAaF;AAAA,MACjB,CAACC,MAA6C;AAC5C,QAAAJ,EAAa,EAAK,GAClBlB,KAAA,QAAAA,EAASsB;AAAA,MACX;AAAA,MACA,CAACtB,CAAM;AAAA,IAAA,GAEHwB,IAAeH;AAAA,MACnB,CAACC,MAAwC;AACvC,QAAKX,KAAcE,EAAqBS,EAAE,OAAO,KAAK,GACtDrB,KAAA,QAAAA,EAAWqB;AAAA,MACb;AAAA,MACA,CAACX,GAAcV,CAAQ;AAAA,IAAA,GAGnBwB,IAAcC,GAAepC,GAASG,GAASC,CAAW,GAC1DiC,IAAcC,EAAgBnC,CAAO,GACrCoC,IAAYC,EAAO,mBAAmBC,GAAQ3C,CAAI,CAAC,EAAE,GACrD4C,IAAeP,IAAcK,EAAO,oBAAoB,IAAI,IAC5DG,IACJ5C,KAAS,QAAQ8B,IAAeW,EAAO,0BAA0B,IAAI,IAEjEI,IAAY;AAAA,MAChBJ,EAAO,WAAW;AAAA,MAClBD;AAAA,MACAG;AAAA,MACAC;AAAA,MACA9C;AAAA,IAAA,EAEC,OAAO,OAAO,EACd,KAAK,GAAG,GAELgD,IAAgB,OAAOpB,KAAU,WAAWA,EAAM,SAAS,GAC3DqB,IACJ5C,KAAsBD,KAAa,OAAO,GAAGmB,CAAE,aAAa,QACxD2B,IAAYV,IAAc,GAAGjB,CAAE,aAAa,QAC5C4B,IAAe5C,KAAe;AAEpC,WACE,gBAAA6C,EAAC,OAAA,EAAI,WAAWL,GACd,UAAA;AAAA,MAAA,gBAAAK,EAAC,OAAA,EAAI,WAAWT,EAAO,oBAAoB,GACxC,UAAA;AAAA,QAAAzC,KAAS,0BACP,SAAA,EAAM,WAAWyC,EAAO,kBAAkB,GAAG,SAASpB,GACpD,UAAArB,EAAA,CACH;AAAA,QAEF,gBAAAmD;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,KAAAjC;AAAA,YACA,IAAAG;AAAA,YACA,WAAWoB,EAAO,kBAAkB;AAAA,YACpC,OAAOnB,IAAef,IAAY;AAAA,YAClC,cAAce,IAAe,SAAYd;AAAA,YACzC,aAAAC;AAAA,YACA,WAAAP;AAAA,YACA,UAAAW;AAAA,YACA,UAAAC;AAAA,YACA,MAAAC;AAAA,YACA,gBAAcqB,IAAc,KAAO;AAAA,YACnC,oBAAkBgB;AAAA,cAChBpC;AAAA,cACAgC;AAAA,cACAD;AAAA,YAAA;AAAA,YAEF,SAAShB;AAAA,YACT,QAAQG;AAAA,YACR,UAAUC;AAAA,YACT,GAAGlB;AAAA,UAAA;AAAA,QAAA;AAAA,MACN,GACF;AAAA,OACEqB,KAAgBnC,KAAsBD,KAAa,2BAClD,OAAA,EAAI,WAAWuC,EAAO,mBAAmB,GACvC,UAAA;AAAA,QAAAH,KACC,gBAAAa;AAAA,UAACE;AAAA,UAAA;AAAA,YACC,IAAIL;AAAA,YACJ,WAAWP,EAAO,2BAA2B;AAAA,YAC7C,SAAArC;AAAA,YACA,MAAM6C;AAAA,UAAA;AAAA,QAAA;AAAA,QAGT9C,KAAsBD,KAAa,QAClC,gBAAAgD;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,IAAIH;AAAA,YACJ,WAAWN,EAAO,oBAAoB;AAAA,YACtC,aAAU;AAAA,YAET,UAAA;AAAA,cAAAK;AAAA,cAAc;AAAA,cAAI5C;AAAA,YAAA;AAAA,UAAA;AAAA,QAAA;AAAA,MACrB,EAAA,CAEJ;AAAA,IAAA,GAEJ;AAAA,EAEJ;AACF;"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});require('./TextArea.css');const e={"text-area":"_text-
|
|
1
|
+
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});require('./TextArea.css');const e={"text-area":"_text-area_r07x5_2","text-area__wrapper":"_text-area__wrapper_r07x5_8","text-area__input":"_text-area__input_r07x5_15","text-area__label":"_text-area__label_r07x5_25","text-area--label-floated":"_text-area--label-floated_r07x5_44","text-area__footer":"_text-area__footer_r07x5_75","text-area__footer-message":"_text-area__footer-message_r07x5_81","text-area__counter":"_text-area__counter_r07x5_85","text-area--size-small":"_text-area--size-small_r07x5_94","text-area--size-medium":"_text-area--size-medium_r07x5_109","text-area--size-large":"_text-area--size-large_r07x5_124","text-area--invalid":"_text-area--invalid_r07x5_146"};exports.default=e;
|
|
2
2
|
//# sourceMappingURL=TextArea.module.scss.cjs.map
|
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
import './TextArea.css';const e = {
|
|
2
|
-
"text-area": "_text-
|
|
3
|
-
"text-area__wrapper": "_text-
|
|
4
|
-
"text-area__input": "_text-
|
|
5
|
-
"text-area__label": "_text-
|
|
6
|
-
"text-area--label-floated": "_text-area--label-
|
|
7
|
-
"text-
|
|
8
|
-
"text-
|
|
9
|
-
"text-
|
|
10
|
-
"text-area--size-
|
|
11
|
-
"text-area--
|
|
2
|
+
"text-area": "_text-area_r07x5_2",
|
|
3
|
+
"text-area__wrapper": "_text-area__wrapper_r07x5_8",
|
|
4
|
+
"text-area__input": "_text-area__input_r07x5_15",
|
|
5
|
+
"text-area__label": "_text-area__label_r07x5_25",
|
|
6
|
+
"text-area--label-floated": "_text-area--label-floated_r07x5_44",
|
|
7
|
+
"text-area__footer": "_text-area__footer_r07x5_75",
|
|
8
|
+
"text-area__footer-message": "_text-area__footer-message_r07x5_81",
|
|
9
|
+
"text-area__counter": "_text-area__counter_r07x5_85",
|
|
10
|
+
"text-area--size-small": "_text-area--size-small_r07x5_94",
|
|
11
|
+
"text-area--size-medium": "_text-area--size-medium_r07x5_109",
|
|
12
|
+
"text-area--size-large": "_text-area--size-large_r07x5_124",
|
|
13
|
+
"text-area--invalid": "_text-area--invalid_r07x5_146"
|
|
12
14
|
};
|
|
13
15
|
export {
|
|
14
16
|
e as default
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TextArea.module.scss.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"TextArea.module.scss.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const
|
|
1
|
+
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const e=require("react/jsx-runtime"),s=require("react"),V=require("../icon/Icon.cjs"),xe=require("../field/FieldClearButton.cjs"),C=require("../field/fieldDescribedBy.cjs"),pe=require("../field/useFieldClear.cjs"),_e=require("../field-message/FieldMessage.cjs"),ve=require("../../utils/string.cjs"),t=require("./TextInput.module.scss.cjs"),he={small:"12",medium:"16",large:"16"},je=s.forwardRef(function({className:$="",size:f="medium",label:x,leadingIcon:p,trailingIcon:_,invalid:E=!1,maxLength:i,showCharacterCount:v=!1,message:h,messageTone:N,clearable:P=!1,onClear:O,clearLabel:U="Clear",clearButtonProps:Z,trailingAction:I,id:A,value:j,defaultValue:g,placeholder:G,onFocus:u,onBlur:d,onChange:c,onKeyDown:H,disabled:y,readOnly:F,"aria-describedby":J,...Q},a){const W=s.useId(),o=A??W,m=s.useRef(null),X=s.useCallback(l=>{if(m.current=l,typeof a=="function"){const K=a(l);return()=>{m.current=null,typeof K=="function"&&K()}}a&&(a.current=l)},[a]),n=j!==void 0,[Y,q]=s.useState(g??""),r=n?j:Y,S=r!=null&&r!=="",[L,w]=s.useState(!1),ee=L||S,te=s.useCallback(l=>{w(!0),u==null||u(l)},[u]),le=s.useCallback(l=>{w(!1),d==null||d(l)},[d]),M=s.useCallback(l=>{n||q(l.target.value),c==null||c(l)},[n,c]),{showClearButton:R,handleClear:se,handleKeyDown:ne}=pe.useFieldClear({disabled:!!(y||F),hasValue:S,clearEnabled:P,isControlled:n,onClear:O,onChange:M,onKeyDown:H,inputRef:m,setUncontrolledValue:q}),k=C.isFieldInvalid(E,h,N),b=C.hasFieldMessage(h),ie=t.default[`text-input--size-${ve.toKebab(f)}`],ae=k?t.default["text-input--invalid"]:"",ue=x!=null&&ee?t.default["text-input--label-floated"]:"",de=p!=null?t.default["text-input--has-leading-icon"]:"",ce=_!=null||R?t.default["text-input--has-trailing-icon"]:"",T=he[f],oe=[t.default["text-input"],ie,ae,ue,de,ce,$].filter(Boolean).join(" "),re=typeof r=="string"?r.length:0,B=v&&i!=null?`${o}-counter`:void 0,D=b?`${o}-message`:void 0,fe=N??"error",z=e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:t.default["text-input__wrapper"],children:[x!=null&&e.jsx("label",{className:t.default["text-input__label"],htmlFor:o,children:x}),e.jsxs("div",{className:t.default["text-input__inner"],children:[p!=null&&e.jsx("span",{className:t.default["text-input__leading-icon"],children:e.jsx(V.IconSlotContext.Provider,{value:{size:T},children:p})}),e.jsx("input",{ref:X,id:o,className:t.default["text-input__input"],value:n?j:void 0,defaultValue:n?void 0:g,placeholder:G,maxLength:i,disabled:y,readOnly:F,"aria-invalid":k?!0:void 0,"aria-describedby":C.mergeFieldDescribedBy(J,D,B),onFocus:te,onBlur:le,onChange:M,onKeyDown:ne,...Q}),_!=null&&e.jsx("span",{className:t.default["text-input__trailing-icon"],children:e.jsx(V.IconSlotContext.Provider,{value:{size:T},children:_})}),R&&e.jsx("span",{className:t.default["text-input__trailing-icon"],children:e.jsx(xe.default,{size:f,clearLabel:U,clearButtonProps:Z,onClick:se})})]})]}),(b||v&&i!=null)&&e.jsxs("div",{className:t.default["text-input__footer"],children:[b&&e.jsx(_e.default,{id:D,className:t.default["text-input__footer-message"],message:h,tone:fe}),v&&i!=null&&e.jsxs("div",{id:B,className:t.default["text-input__counter"],"aria-live":"polite",children:[re," / ",i]})]})]});return e.jsx("div",{className:oe,children:I!=null?e.jsxs("div",{className:t.default["text-input__row"],children:[e.jsx("div",{className:t.default["text-input__field"],children:z}),e.jsx("div",{className:t.default["text-input__trailing-action"],children:I})]}):z})});exports.default=je;
|
|
2
2
|
//# sourceMappingURL=TextInput.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TextInput.cjs","sources":["../../../src/components/text-input/TextInput.tsx"],"sourcesContent":["import type {\n InputHTMLAttributes,\n ReactNode,\n ChangeEvent,\n RefCallback,\n} from 'react';\nimport { forwardRef, useId, useState, useCallback, useRef } from 'react';\nimport { IconSlotContext } from '@/components/icon/Icon';\nimport { toKebab } from '@/utils/string';\nimport styles from './TextInput.module.scss';\n\nexport type TextInputSize = 'small' | 'medium' | 'large';\n\nexport interface TextInputProps extends Omit<\n InputHTMLAttributes<HTMLInputElement>,\n 'size'\n> {\n /** Optional CSS class name. */\n className?: string;\n /** When true, shows invalid/error styling. */\n invalid?: boolean;\n /** Floating label content. When provided, label floats on focus or when value is non-empty. */\n label?: ReactNode;\n /** Leading icon — pass `<Icon glyph={<SearchIcon />} />`; TextInput provides the correct size via context. */\n leadingIcon?: ReactNode;\n /** Max length for the input; used with showCharacterCount for counter. */\n maxLength?: number;\n /** When true with maxLength, shows \"current / max\" character count below input. */\n showCharacterCount?: boolean;\n /** Size variant. Figma: Small (32px), Medium (40px), Large (48px). Default: Medium. */\n size?: TextInputSize;\n /** Trailing icon — pass `<Icon glyph={<SomeIcon />} />`; TextInput provides the correct size via context. */\n trailingIcon?: ReactNode;\n}\n\n/**\n * Text Inputs let people enter and edit a single line of text — names, emails, search\n * queries, channel titles. They're the workhorse of every form and modal in Mattermost.\n */\nconst TextInput = forwardRef<HTMLInputElement, TextInputProps>(\n function TextInput(\n {\n className = '',\n size = 'medium',\n label,\n leadingIcon,\n trailingIcon,\n invalid = false,\n maxLength,\n showCharacterCount = false,\n id: idProp,\n value: valueProp,\n defaultValue,\n placeholder,\n onFocus,\n onBlur,\n onChange,\n disabled,\n readOnly,\n 'aria-describedby': describedBy,\n ...rest\n },\n ref,\n ) {\n const generatedId = useId();\n const id = idProp ?? generatedId;\n const inputRef = useRef<HTMLInputElement | null>(null);\n\n const setInputRef = useCallback(\n (node: HTMLInputElement | null) => {\n inputRef.current = node;\n if (typeof ref === 'function') {\n const cleanup = (ref as RefCallback<HTMLInputElement>)(node);\n return () => {\n inputRef.current = null;\n if (typeof cleanup === 'function') cleanup();\n };\n }\n if (ref) ref.current = node;\n },\n [ref],\n );\n\n const isControlled = valueProp !== undefined;\n const [uncontrolledValue, setUncontrolledValue] = useState(\n defaultValue ?? '',\n );\n const value = isControlled ? (valueProp as string) : uncontrolledValue;\n const hasValue = value != null && value !== '';\n\n const [isFocused, setIsFocused] = useState(false);\n const labelFloated = isFocused || hasValue;\n\n const handleFocus = useCallback(\n (e: React.FocusEvent<HTMLInputElement>) => {\n setIsFocused(true);\n onFocus?.(e);\n },\n [onFocus],\n );\n const handleBlur = useCallback(\n (e: React.FocusEvent<HTMLInputElement>) => {\n setIsFocused(false);\n onBlur?.(e);\n },\n [onBlur],\n );\n const handleChange = useCallback(\n (e: ChangeEvent<HTMLInputElement>) => {\n if (!isControlled) setUncontrolledValue(e.target.value);\n onChange?.(e);\n },\n [isControlled, onChange],\n );\n\n const sizeClass = styles[`text-input--size-${toKebab(size)}`];\n const invalidClass = invalid ? styles['text-input--invalid'] : '';\n const labelFloatedClass =\n label != null && labelFloated ? styles['text-input--label-floated'] : '';\n const hasLeadingClass =\n leadingIcon != null ? styles['text-input--has-leading-icon'] : '';\n const hasTrailingClass =\n trailingIcon != null ? styles['text-input--has-trailing-icon'] : '';\n\n const rootClass = [\n styles['text-input'],\n sizeClass,\n invalidClass,\n labelFloatedClass,\n hasLeadingClass,\n hasTrailingClass,\n className,\n ]\n .filter(Boolean)\n .join(' ');\n\n const currentLength = typeof value === 'string' ? value.length : 0;\n const counterId =\n showCharacterCount && maxLength != null ? `${id}-counter` : undefined;\n\n return (\n <div className={rootClass}>\n <div className={styles['text-input__wrapper']}>\n <label className={styles['text-input__inner']}>\n {label != null && (\n <span className={styles['text-input__label']}>{label}</span>\n )}\n {leadingIcon != null && (\n <span className={styles['text-input__leading-icon']}>\n <IconSlotContext.Provider value={{ size: '16' }}>\n {leadingIcon}\n </IconSlotContext.Provider>\n </span>\n )}\n <input\n ref={setInputRef}\n id={id}\n className={styles['text-input__input']}\n value={isControlled ? valueProp : undefined}\n defaultValue={isControlled ? undefined : defaultValue}\n placeholder={placeholder}\n maxLength={maxLength}\n disabled={disabled}\n readOnly={readOnly}\n aria-invalid={invalid ? true : undefined}\n aria-describedby={\n [describedBy, counterId].filter(Boolean).join(' ') || undefined\n }\n onFocus={handleFocus}\n onBlur={handleBlur}\n onChange={handleChange}\n {...rest}\n />\n {trailingIcon != null && (\n <span className={styles['text-input__trailing-icon']}>\n <IconSlotContext.Provider value={{ size: '16' }}>\n {trailingIcon}\n </IconSlotContext.Provider>\n </span>\n )}\n </label>\n </div>\n {showCharacterCount && maxLength != null && (\n <div\n id={counterId}\n className={styles['text-input__counter']}\n aria-live=\"polite\"\n >\n {currentLength} / {maxLength}\n </div>\n )}\n </div>\n );\n },\n);\n\nexport default TextInput;\n"],"names":["TextInput","forwardRef","className","size","label","leadingIcon","trailingIcon","invalid","maxLength","showCharacterCount","idProp","valueProp","defaultValue","placeholder","onFocus","onBlur","onChange","disabled","readOnly","describedBy","rest","ref","generatedId","useId","id","inputRef","useRef","setInputRef","useCallback","node","cleanup","isControlled","uncontrolledValue","setUncontrolledValue","useState","value","hasValue","isFocused","setIsFocused","labelFloated","handleFocus","e","handleBlur","handleChange","sizeClass","styles","toKebab","invalidClass","labelFloatedClass","hasLeadingClass","hasTrailingClass","rootClass","currentLength","counterId","jsxs","jsx","IconSlotContext"],"mappings":"+QAuCMA,EAAYC,EAAAA,WAChB,SACE,CACE,UAAAC,EAAY,GACZ,KAAAC,EAAO,SACP,MAAAC,EACA,YAAAC,EACA,aAAAC,EACA,QAAAC,EAAU,GACV,UAAAC,EACA,mBAAAC,EAAqB,GACrB,GAAIC,EACJ,MAAOC,EACP,aAAAC,EACA,YAAAC,EACA,QAAAC,EACA,OAAAC,EACA,SAAAC,EACA,SAAAC,EACA,SAAAC,EACA,mBAAoBC,EACpB,GAAGC,CAAA,EAELC,EACA,CACA,MAAMC,EAAcC,EAAAA,MAAA,EACdC,EAAKd,GAAUY,EACfG,EAAWC,EAAAA,OAAgC,IAAI,EAE/CC,EAAcC,EAAAA,YACjBC,GAAkC,CAEjC,GADAJ,EAAS,QAAUI,EACf,OAAOR,GAAQ,WAAY,CAC7B,MAAMS,EAAWT,EAAsCQ,CAAI,EAC3D,MAAO,IAAM,CACXJ,EAAS,QAAU,KACf,OAAOK,GAAY,YAAYA,EAAA,CACrC,CACF,CACIT,MAAS,QAAUQ,EACzB,EACA,CAACR,CAAG,CAAA,EAGAU,EAAepB,IAAc,OAC7B,CAACqB,EAAmBC,CAAoB,EAAIC,EAAAA,SAChDtB,GAAgB,EAAA,EAEZuB,EAAQJ,EAAgBpB,EAAuBqB,EAC/CI,EAAWD,GAAS,MAAQA,IAAU,GAEtC,CAACE,EAAWC,CAAY,EAAIJ,EAAAA,SAAS,EAAK,EAC1CK,EAAeF,GAAaD,EAE5BI,EAAcZ,EAAAA,YACjBa,GAA0C,CACzCH,EAAa,EAAI,EACjBxB,GAAA,MAAAA,EAAU2B,EACZ,EACA,CAAC3B,CAAO,CAAA,EAEJ4B,EAAad,EAAAA,YAChBa,GAA0C,CACzCH,EAAa,EAAK,EAClBvB,GAAA,MAAAA,EAAS0B,EACX,EACA,CAAC1B,CAAM,CAAA,EAEH4B,EAAef,EAAAA,YAClBa,GAAqC,CAC/BV,GAAcE,EAAqBQ,EAAE,OAAO,KAAK,EACtDzB,GAAA,MAAAA,EAAWyB,EACb,EACA,CAACV,EAAcf,CAAQ,CAAA,EAGnB4B,EAAYC,EAAAA,QAAO,oBAAoBC,EAAAA,QAAQ3C,CAAI,CAAC,EAAE,EACtD4C,EAAexC,EAAUsC,UAAO,qBAAqB,EAAI,GACzDG,EACJ5C,GAAS,MAAQmC,EAAeM,EAAAA,QAAO,2BAA2B,EAAI,GAClEI,EACJ5C,GAAe,KAAOwC,EAAAA,QAAO,8BAA8B,EAAI,GAC3DK,EACJ5C,GAAgB,KAAOuC,EAAAA,QAAO,+BAA+B,EAAI,GAE7DM,EAAY,CAChBN,EAAAA,QAAO,YAAY,EACnBD,EACAG,EACAC,EACAC,EACAC,EACAhD,CAAA,EAEC,OAAO,OAAO,EACd,KAAK,GAAG,EAELkD,EAAgB,OAAOjB,GAAU,SAAWA,EAAM,OAAS,EAC3DkB,EACJ5C,GAAsBD,GAAa,KAAO,GAAGgB,CAAE,WAAa,OAE9D,OACE8B,EAAAA,KAAC,MAAA,CAAI,UAAWH,EACd,SAAA,CAAAI,EAAAA,IAAC,MAAA,CAAI,UAAWV,EAAAA,QAAO,qBAAqB,EAC1C,gBAAC,QAAA,CAAM,UAAWA,EAAAA,QAAO,mBAAmB,EACzC,SAAA,CAAAzC,GAAS,MACRmD,MAAC,OAAA,CAAK,UAAWV,EAAAA,QAAO,mBAAmB,EAAI,SAAAzC,EAAM,EAEtDC,GAAe,MACdkD,EAAAA,IAAC,QAAK,UAAWV,EAAAA,QAAO,0BAA0B,EAChD,SAAAU,EAAAA,IAACC,EAAAA,gBAAgB,SAAhB,CAAyB,MAAO,CAAE,KAAM,IAAA,EACtC,WACH,EACF,EAEFD,EAAAA,IAAC,QAAA,CACC,IAAK5B,EACL,GAAAH,EACA,UAAWqB,EAAAA,QAAO,mBAAmB,EACrC,MAAOd,EAAepB,EAAY,OAClC,aAAcoB,EAAe,OAAYnB,EACzC,YAAAC,EACA,UAAAL,EACA,SAAAS,EACA,SAAAC,EACA,eAAcX,EAAU,GAAO,OAC/B,mBACE,CAACY,EAAakC,CAAS,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG,GAAK,OAExD,QAASb,EACT,OAAQE,EACR,SAAUC,EACT,GAAGvB,CAAA,CAAA,EAELd,GAAgB,MACfiD,EAAAA,IAAC,QAAK,UAAWV,EAAAA,QAAO,2BAA2B,EACjD,SAAAU,EAAAA,IAACC,EAAAA,gBAAgB,SAAhB,CAAyB,MAAO,CAAE,KAAM,MACtC,WACH,CAAA,CACF,CAAA,CAAA,CAEJ,CAAA,CACF,EACC/C,GAAsBD,GAAa,MAClC8C,EAAAA,KAAC,MAAA,CACC,GAAID,EACJ,UAAWR,EAAAA,QAAO,qBAAqB,EACvC,YAAU,SAET,SAAA,CAAAO,EAAc,MAAI5C,CAAA,CAAA,CAAA,CACrB,EAEJ,CAEJ,CACF"}
|
|
1
|
+
{"version":3,"file":"TextInput.cjs","sources":["../../../src/components/text-input/TextInput.tsx"],"sourcesContent":["import type {\n InputHTMLAttributes,\n ReactNode,\n ChangeEvent,\n RefCallback,\n KeyboardEvent,\n} from 'react';\nimport { forwardRef, useId, useState, useCallback, useRef } from 'react';\nimport { IconSlotContext } from '@/components/icon/Icon';\nimport type { IconSize } from '@/components/icon/Icon';\nimport FieldClearButton from '@/components/field/FieldClearButton';\nimport {\n hasFieldMessage,\n isFieldInvalid,\n mergeFieldDescribedBy,\n} from '@/components/field/fieldDescribedBy';\nimport { useFieldClear } from '@/components/field/useFieldClear';\nimport FieldMessage from '@/components/field-message/FieldMessage';\nimport type { FieldMessageTone } from '@/components/field-message/FieldMessage';\nimport type { BuiltInButtonProps } from '@/utils/props';\nimport { toKebab } from '@/utils/string';\nimport styles from './TextInput.module.scss';\n\nexport type TextInputSize = 'small' | 'medium' | 'large';\n\n/** Matches FieldClearButton / in-field chrome for each Text Input size. */\nconst ICON_SIZE_MAP: Record<TextInputSize, IconSize> = {\n small: '12',\n medium: '16',\n large: '16',\n};\n\nexport interface TextInputProps extends Omit<\n InputHTMLAttributes<HTMLInputElement>,\n 'size'\n> {\n /** Optional CSS class name. */\n className?: string;\n /** When true, shows invalid/error styling. */\n invalid?: boolean;\n /** Floating label content. When provided, label floats on focus or when value is non-empty. */\n label?: ReactNode;\n /** Leading icon — pass `<Icon glyph={<SearchIcon />} />`; TextInput provides the correct size via context. */\n leadingIcon?: ReactNode;\n /** Max length for the input; used with showCharacterCount for counter. */\n maxLength?: number;\n /** When true with maxLength, shows \"current / max\" character count below input. */\n showCharacterCount?: boolean;\n /** Size variant. Figma: Small (32px), Medium (40px), Large (48px). Default: Medium. */\n size?: TextInputSize;\n /**\n * Native input `type`. For passwords with show/hide, prefer `PasswordInput`\n * over composing `type=\"password\"` here.\n */\n type?: InputHTMLAttributes<HTMLInputElement>['type'];\n /**\n * Trailing icon inside the field — pass `<Icon glyph={<GlobeIcon />} />`. Sized via\n * context from `size`. When `clearable` is also set, clear renders after this icon.\n * For password show/hide, use `PasswordInput` instead (don’t combine clear with\n * password reveal). Combobox owns its own clear/chevron.\n */\n trailingIcon?: ReactNode;\n /**\n * Field message under the field. Accepts translated nodes (e.g. `<FormattedMessage/>`).\n * Defaults to error tone (invalid chrome) when set without `messageTone`.\n */\n message?: ReactNode;\n /** Visual tone for `message`. Default: `error` when `message` is set. */\n messageTone?: FieldMessageTone;\n /**\n * When true, shows a clear button while the field has a non-empty value and is not disabled.\n * Default: false.\n */\n clearable?: boolean;\n /** Called when the clear button is pressed. Omit to use built-in clearing. */\n onClear?: () => void;\n /** Accessible name for the clear button. Default: \"Clear\". */\n clearLabel?: string;\n /** Extra attributes for the clear button (e.g. `data-testid`). */\n clearButtonProps?: BuiltInButtonProps;\n /**\n * Rendered outside the border, beside the control (same height as the field). Use for\n * labeled actions like Copy (`Button`, primary by default). Password show/hide belongs\n * on `PasswordInput`. Message and counter stay as wide as the field column, not under\n * the action.\n */\n trailingAction?: ReactNode;\n}\n\n/**\n * Text Inputs let people enter and edit a single line of text — names, emails, search\n * queries, channel titles. They're the workhorse of every form and modal in Mattermost.\n */\nconst TextInput = forwardRef<HTMLInputElement, TextInputProps>(\n function TextInput(\n {\n className = '',\n size = 'medium',\n label,\n leadingIcon,\n trailingIcon,\n invalid = false,\n maxLength,\n showCharacterCount = false,\n message,\n messageTone,\n clearable = false,\n onClear,\n clearLabel = 'Clear',\n clearButtonProps,\n trailingAction,\n id: idProp,\n value: valueProp,\n defaultValue,\n placeholder,\n onFocus,\n onBlur,\n onChange,\n onKeyDown,\n disabled,\n readOnly,\n 'aria-describedby': describedBy,\n ...rest\n },\n ref,\n ) {\n const generatedId = useId();\n const id = idProp ?? generatedId;\n const inputRef = useRef<HTMLInputElement | null>(null);\n\n const setInputRef = useCallback(\n (node: HTMLInputElement | null) => {\n inputRef.current = node;\n if (typeof ref === 'function') {\n const cleanup = (ref as RefCallback<HTMLInputElement>)(node);\n return () => {\n inputRef.current = null;\n if (typeof cleanup === 'function') cleanup();\n };\n }\n if (ref) ref.current = node;\n },\n [ref],\n );\n\n const isControlled = valueProp !== undefined;\n const [uncontrolledValue, setUncontrolledValue] = useState(\n defaultValue ?? '',\n );\n const value = isControlled ? (valueProp as string) : uncontrolledValue;\n const hasValue = value != null && value !== '';\n\n const [isFocused, setIsFocused] = useState(false);\n const labelFloated = isFocused || hasValue;\n\n const handleFocus = useCallback(\n (e: React.FocusEvent<HTMLInputElement>) => {\n setIsFocused(true);\n onFocus?.(e);\n },\n [onFocus],\n );\n const handleBlur = useCallback(\n (e: React.FocusEvent<HTMLInputElement>) => {\n setIsFocused(false);\n onBlur?.(e);\n },\n [onBlur],\n );\n const handleChange = useCallback(\n (e: ChangeEvent<HTMLInputElement>) => {\n if (!isControlled) setUncontrolledValue(e.target.value);\n onChange?.(e);\n },\n [isControlled, onChange],\n );\n\n const { showClearButton, handleClear, handleKeyDown } = useFieldClear({\n disabled: Boolean(disabled || readOnly),\n hasValue,\n clearEnabled: clearable,\n isControlled,\n onClear,\n onChange: handleChange as (e: ChangeEvent<HTMLInputElement>) => void,\n onKeyDown: onKeyDown as\n | ((e: KeyboardEvent<HTMLInputElement>) => void)\n | undefined,\n inputRef,\n setUncontrolledValue,\n });\n\n const showInvalid = isFieldInvalid(invalid, message, messageTone);\n const showMessage = hasFieldMessage(message);\n const sizeClass = styles[`text-input--size-${toKebab(size)}`];\n const invalidClass = showInvalid ? styles['text-input--invalid'] : '';\n const labelFloatedClass =\n label != null && labelFloated ? styles['text-input--label-floated'] : '';\n const hasLeadingClass =\n leadingIcon != null ? styles['text-input--has-leading-icon'] : '';\n const hasTrailingClass =\n trailingIcon != null || showClearButton\n ? styles['text-input--has-trailing-icon']\n : '';\n const iconSize = ICON_SIZE_MAP[size];\n\n const rootClass = [\n styles['text-input'],\n sizeClass,\n invalidClass,\n labelFloatedClass,\n hasLeadingClass,\n hasTrailingClass,\n className,\n ]\n .filter(Boolean)\n .join(' ');\n\n const currentLength = typeof value === 'string' ? value.length : 0;\n const counterId =\n showCharacterCount && maxLength != null ? `${id}-counter` : undefined;\n const messageId = showMessage ? `${id}-message` : undefined;\n const resolvedTone = messageTone ?? 'error';\n\n const fieldBody = (\n <>\n <div className={styles['text-input__wrapper']}>\n {label != null && (\n <label className={styles['text-input__label']} htmlFor={id}>\n {label}\n </label>\n )}\n <div className={styles['text-input__inner']}>\n {leadingIcon != null && (\n <span className={styles['text-input__leading-icon']}>\n <IconSlotContext.Provider value={{ size: iconSize }}>\n {leadingIcon}\n </IconSlotContext.Provider>\n </span>\n )}\n <input\n ref={setInputRef}\n id={id}\n className={styles['text-input__input']}\n value={isControlled ? valueProp : undefined}\n defaultValue={isControlled ? undefined : defaultValue}\n placeholder={placeholder}\n maxLength={maxLength}\n disabled={disabled}\n readOnly={readOnly}\n aria-invalid={showInvalid ? true : undefined}\n aria-describedby={mergeFieldDescribedBy(\n describedBy,\n messageId,\n counterId,\n )}\n onFocus={handleFocus}\n onBlur={handleBlur}\n onChange={handleChange}\n onKeyDown={handleKeyDown}\n {...rest}\n />\n {trailingIcon != null && (\n <span className={styles['text-input__trailing-icon']}>\n <IconSlotContext.Provider value={{ size: iconSize }}>\n {trailingIcon}\n </IconSlotContext.Provider>\n </span>\n )}\n {showClearButton && (\n <span className={styles['text-input__trailing-icon']}>\n <FieldClearButton\n size={size}\n clearLabel={clearLabel}\n clearButtonProps={clearButtonProps}\n onClick={handleClear}\n />\n </span>\n )}\n </div>\n </div>\n {(showMessage || (showCharacterCount && maxLength != null)) && (\n <div className={styles['text-input__footer']}>\n {showMessage && (\n <FieldMessage\n id={messageId}\n className={styles['text-input__footer-message']}\n message={message}\n tone={resolvedTone}\n />\n )}\n {showCharacterCount && maxLength != null && (\n <div\n id={counterId}\n className={styles['text-input__counter']}\n aria-live=\"polite\"\n >\n {currentLength} / {maxLength}\n </div>\n )}\n </div>\n )}\n </>\n );\n\n return (\n <div className={rootClass}>\n {trailingAction != null ? (\n <div className={styles['text-input__row']}>\n <div className={styles['text-input__field']}>{fieldBody}</div>\n <div className={styles['text-input__trailing-action']}>\n {trailingAction}\n </div>\n </div>\n ) : (\n fieldBody\n )}\n </div>\n );\n },\n);\n\nexport default TextInput;\n"],"names":["ICON_SIZE_MAP","TextInput","forwardRef","className","size","label","leadingIcon","trailingIcon","invalid","maxLength","showCharacterCount","message","messageTone","clearable","onClear","clearLabel","clearButtonProps","trailingAction","idProp","valueProp","defaultValue","placeholder","onFocus","onBlur","onChange","onKeyDown","disabled","readOnly","describedBy","rest","ref","generatedId","useId","id","inputRef","useRef","setInputRef","useCallback","node","cleanup","isControlled","uncontrolledValue","setUncontrolledValue","useState","value","hasValue","isFocused","setIsFocused","labelFloated","handleFocus","e","handleBlur","handleChange","showClearButton","handleClear","handleKeyDown","useFieldClear","showInvalid","isFieldInvalid","showMessage","hasFieldMessage","sizeClass","styles","toKebab","invalidClass","labelFloatedClass","hasLeadingClass","hasTrailingClass","iconSize","rootClass","currentLength","counterId","messageId","resolvedTone","fieldBody","jsxs","Fragment","jsx","IconSlotContext","mergeFieldDescribedBy","FieldClearButton","FieldMessage"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
._text-
|
|
1
|
+
._text-input_3inqk_2{display:flex;flex-direction:column;gap:var(--spacing-xs);width:100%}._text-input__row_3inqk_8{display:flex;align-items:flex-start;gap:var(--spacing-xs);width:100%}._text-input__field_3inqk_14{display:flex;flex-direction:column;gap:var(--spacing-xs);flex:1 1 0;min-width:0}._text-input__trailing-action_3inqk_21{display:inline-flex;align-items:stretch;flex-shrink:0}._text-input__trailing-action_3inqk_21>*{box-sizing:border-box;height:var(--text-input-control-height);min-height:var(--text-input-control-height)}._text-input__wrapper_3inqk_31{position:relative;display:flex;flex-direction:column;min-height:0;background-color:var(--center-channel-bg);border-radius:var(--radius-s);box-shadow:inset 0 0 0 1px rgba(var(--center-channel-color-rgb),.16);transition:box-shadow var(--duration-quick) var(--ease-transition);cursor:text}._text-input_3inqk_2:has(._text-input__input_3inqk_42:not(:disabled)):hover:not(:focus-within) ._text-input__wrapper_3inqk_31{box-shadow:inset 0 0 0 1px rgba(var(--center-channel-color-rgb),.24)}._text-input_3inqk_2:has(._text-input__input_3inqk_42:focus-visible) ._text-input__wrapper_3inqk_31{box-shadow:inset 0 0 0 1px var(--focus-ring-color),0 0 0 1px var(--focus-ring-color)}._text-input_3inqk_2:has(._text-input__input_3inqk_42:disabled) ._text-input__wrapper_3inqk_31{background-color:var(--center-channel-bg);opacity:.56;cursor:not-allowed}._text-input__label_3inqk_53{position:absolute;left:var(--spacing-xs);top:50%;padding:0 var(--spacing-xxxs);transform:translateY(-50%);margin:0;font-family:Open Sans,sans-serif;font-size:var(--font-size-75);line-height:var(--line-height-25);font-weight:var(--font-weight-regular);color:rgba(var(--center-channel-color-rgb),.64);background-color:var(--center-channel-bg);pointer-events:none;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:calc(100% - 24px);transition:transform var(--duration-quick) var(--ease-transition),font-size var(--duration-quick) var(--ease-transition),color var(--duration-quick) var(--ease-transition),top var(--duration-quick) var(--ease-transition),left var(--duration-quick) var(--ease-transition)}._text-input--label-floated_3inqk_73 ._text-input__label_3inqk_53{top:0;transform:translateY(-50%);font-size:var(--font-size-25);line-height:14px;color:rgba(var(--center-channel-color-rgb),.64)}._text-input__inner_3inqk_80{display:flex;align-items:center;flex:1;width:100%;min-width:0;box-sizing:border-box;margin:0;cursor:text}._text-input__input_3inqk_42{flex:1 1 0;width:100%;min-width:0;min-height:100%;margin:0;padding:0;border:0;background:transparent;font-family:Open Sans,sans-serif;font-size:var(--font-size-75);line-height:var(--line-height-25);font-weight:var(--font-weight-regular);color:var(--center-channel-color)}._text-input__input_3inqk_42:focus{outline:none}._text-input__input_3inqk_42::placeholder{color:rgba(var(--center-channel-color-rgb),.64)}._text-input__leading-icon_3inqk_111,._text-input__trailing-icon_3inqk_111{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;color:rgba(var(--center-channel-color-rgb),.64)}._text-input__leading-icon_3inqk_111{margin-right:var(--spacing-xs)}._text-input__trailing-icon_3inqk_111{margin-left:var(--spacing-xs)}._text-input__footer_3inqk_124{display:flex;align-items:flex-start;gap:var(--spacing-xs);width:100%}._text-input__footer-message_3inqk_130{flex:1 1 0;min-width:0}._text-input__counter_3inqk_134{flex-shrink:0;margin-inline-start:auto;font-family:Open Sans,sans-serif;font-size:var(--font-size-75);font-weight:var(--font-weight-regular);line-height:var(--line-height-75);color:rgba(var(--center-channel-color-rgb),.64)}._text-input--size-small_3inqk_143{--text-input-control-height: 32px}._text-input--size-small_3inqk_143 ._text-input__wrapper_3inqk_31{min-height:var(--text-input-control-height)}._text-input--size-small_3inqk_143 ._text-input__inner_3inqk_80{padding:var(--spacing-xs) var(--spacing-m)}._text-input--size-small_3inqk_143 ._text-input__input_3inqk_42{font-size:var(--font-size-75);line-height:var(--line-height-25)}._text-input--size-small_3inqk_143._text-input--label-floated_3inqk_73 ._text-input__label_3inqk_53{top:0;transform:translateY(-50%);font-size:var(--font-size-25);line-height:14px}._text-input--size-medium_3inqk_162{--text-input-control-height: 40px}._text-input--size-medium_3inqk_162 ._text-input__wrapper_3inqk_31{min-height:var(--text-input-control-height)}._text-input--size-medium_3inqk_162 ._text-input__inner_3inqk_80{padding:var(--spacing-s) var(--spacing-l)}._text-input--size-medium_3inqk_162 ._text-input__input_3inqk_42{font-size:var(--font-size-100);line-height:var(--line-height-100)}._text-input--size-medium_3inqk_162 ._text-input__label_3inqk_53{font-size:var(--font-size-100);left:var(--spacing-m)}._text-input--size-medium_3inqk_162._text-input--label-floated_3inqk_73 ._text-input__label_3inqk_53{top:0;transform:translateY(-50%);font-size:var(--font-size-25);line-height:14px}._text-input--size-large_3inqk_185{--text-input-control-height: 48px}._text-input--size-large_3inqk_185 ._text-input__wrapper_3inqk_31{min-height:var(--text-input-control-height)}._text-input--size-large_3inqk_185 ._text-input__inner_3inqk_80{padding:var(--spacing-m) var(--spacing-l)}._text-input--size-large_3inqk_185 ._text-input__input_3inqk_42{font-size:var(--font-size-200);line-height:var(--line-height-200)}._text-input--size-large_3inqk_185 ._text-input__label_3inqk_53{font-size:var(--font-size-200);line-height:var(--line-height-200);left:var(--spacing-m)}._text-input--size-large_3inqk_185._text-input--label-floated_3inqk_73 ._text-input__label_3inqk_53{top:0;transform:translateY(-50%);font-size:var(--font-size-25);line-height:14px}._text-input--has-leading-icon_3inqk_209 ._text-input__label_3inqk_53{left:28px}._text-input--has-leading-icon_3inqk_209._text-input--label-floated_3inqk_73 ._text-input__label_3inqk_53{left:var(--spacing-xs)}._text-input--has-leading-icon_3inqk_209._text-input--size-medium_3inqk_162 ._text-input__label_3inqk_53,._text-input--has-leading-icon_3inqk_209._text-input--size-large_3inqk_185 ._text-input__label_3inqk_53{left:36px}._text-input--has-leading-icon_3inqk_209._text-input--size-medium_3inqk_162._text-input--label-floated_3inqk_73 ._text-input__label_3inqk_53,._text-input--has-leading-icon_3inqk_209._text-input--size-large_3inqk_185._text-input--label-floated_3inqk_73 ._text-input__label_3inqk_53{left:var(--spacing-m)}._text-input_3inqk_2:has(._text-input__input_3inqk_42:focus-visible) ._text-input__label_3inqk_53{color:var(--button-bg)}._text-input_3inqk_2:has(._text-input__label_3inqk_53):not(._text-input--label-floated_3inqk_73) ._text-input__input_3inqk_42::placeholder{color:transparent}._text-input--invalid_3inqk_227 ._text-input__wrapper_3inqk_31{box-shadow:inset 0 0 0 1px var(--error-text, var(--color-danger))}._text-input--invalid_3inqk_227:has(._text-input__input_3inqk_42:focus-visible) ._text-input__wrapper_3inqk_31{box-shadow:inset 0 0 0 1px var(--error-text, var(--color-danger)),0 0 0 1px var(--error-text, var(--color-danger))}._text-input--invalid_3inqk_227 ._text-input__label_3inqk_53{color:var(--error-text, var(--color-danger))}._text-input--invalid_3inqk_227:has(._text-input__input_3inqk_42:focus-visible) ._text-input__label_3inqk_53{color:var(--error-text, var(--color-danger))}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { InputHTMLAttributes, ReactNode } from 'react';
|
|
2
|
+
import { FieldMessageTone } from '../field-message/FieldMessage';
|
|
3
|
+
import { BuiltInButtonProps } from '../../utils/props';
|
|
2
4
|
export type TextInputSize = 'small' | 'medium' | 'large';
|
|
3
5
|
export interface TextInputProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'size'> {
|
|
4
6
|
/** Optional CSS class name. */
|
|
@@ -15,8 +17,43 @@ export interface TextInputProps extends Omit<InputHTMLAttributes<HTMLInputElemen
|
|
|
15
17
|
showCharacterCount?: boolean;
|
|
16
18
|
/** Size variant. Figma: Small (32px), Medium (40px), Large (48px). Default: Medium. */
|
|
17
19
|
size?: TextInputSize;
|
|
18
|
-
/**
|
|
20
|
+
/**
|
|
21
|
+
* Native input `type`. For passwords with show/hide, prefer `PasswordInput`
|
|
22
|
+
* over composing `type="password"` here.
|
|
23
|
+
*/
|
|
24
|
+
type?: InputHTMLAttributes<HTMLInputElement>['type'];
|
|
25
|
+
/**
|
|
26
|
+
* Trailing icon inside the field — pass `<Icon glyph={<GlobeIcon />} />`. Sized via
|
|
27
|
+
* context from `size`. When `clearable` is also set, clear renders after this icon.
|
|
28
|
+
* For password show/hide, use `PasswordInput` instead (don’t combine clear with
|
|
29
|
+
* password reveal). Combobox owns its own clear/chevron.
|
|
30
|
+
*/
|
|
19
31
|
trailingIcon?: ReactNode;
|
|
32
|
+
/**
|
|
33
|
+
* Field message under the field. Accepts translated nodes (e.g. `<FormattedMessage/>`).
|
|
34
|
+
* Defaults to error tone (invalid chrome) when set without `messageTone`.
|
|
35
|
+
*/
|
|
36
|
+
message?: ReactNode;
|
|
37
|
+
/** Visual tone for `message`. Default: `error` when `message` is set. */
|
|
38
|
+
messageTone?: FieldMessageTone;
|
|
39
|
+
/**
|
|
40
|
+
* When true, shows a clear button while the field has a non-empty value and is not disabled.
|
|
41
|
+
* Default: false.
|
|
42
|
+
*/
|
|
43
|
+
clearable?: boolean;
|
|
44
|
+
/** Called when the clear button is pressed. Omit to use built-in clearing. */
|
|
45
|
+
onClear?: () => void;
|
|
46
|
+
/** Accessible name for the clear button. Default: "Clear". */
|
|
47
|
+
clearLabel?: string;
|
|
48
|
+
/** Extra attributes for the clear button (e.g. `data-testid`). */
|
|
49
|
+
clearButtonProps?: BuiltInButtonProps;
|
|
50
|
+
/**
|
|
51
|
+
* Rendered outside the border, beside the control (same height as the field). Use for
|
|
52
|
+
* labeled actions like Copy (`Button`, primary by default). Password show/hide belongs
|
|
53
|
+
* on `PasswordInput`. Message and counter stay as wide as the field column, not under
|
|
54
|
+
* the action.
|
|
55
|
+
*/
|
|
56
|
+
trailingAction?: ReactNode;
|
|
20
57
|
}
|
|
21
58
|
/**
|
|
22
59
|
* Text Inputs let people enter and edit a single line of text — names, emails, search
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TextInput.d.ts","sourceRoot":"","sources":["../../../src/components/text-input/TextInput.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,mBAAmB,EACnB,SAAS,
|
|
1
|
+
{"version":3,"file":"TextInput.d.ts","sourceRoot":"","sources":["../../../src/components/text-input/TextInput.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,mBAAmB,EACnB,SAAS,EAIV,MAAM,OAAO,CAAC;AAYf,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wCAAwC,CAAC;AAC/E,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAIxD,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAC;AASzD,MAAM,WAAW,cAAe,SAAQ,IAAI,CAC1C,mBAAmB,CAAC,gBAAgB,CAAC,EACrC,MAAM,CACP;IACC,+BAA+B;IAC/B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,8CAA8C;IAC9C,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,+FAA+F;IAC/F,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,8GAA8G;IAC9G,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,0EAA0E;IAC1E,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mFAAmF;IACnF,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,uFAAuF;IACvF,IAAI,CAAC,EAAE,aAAa,CAAC;IACrB;;;OAGG;IACH,IAAI,CAAC,EAAE,mBAAmB,CAAC,gBAAgB,CAAC,CAAC,MAAM,CAAC,CAAC;IACrD;;;;;OAKG;IACH,YAAY,CAAC,EAAE,SAAS,CAAC;IACzB;;;OAGG;IACH,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB,yEAAyE;IACzE,WAAW,CAAC,EAAE,gBAAgB,CAAC;IAC/B;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,8EAA8E;IAC9E,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,8DAA8D;IAC9D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,kEAAkE;IAClE,gBAAgB,CAAC,EAAE,kBAAkB,CAAC;IACtC;;;;;OAKG;IACH,cAAc,CAAC,EAAE,SAAS,CAAC;CAC5B;AAED;;;GAGG;AACH,QAAA,MAAM,SAAS,6GAkOd,CAAC;AAEF,eAAe,SAAS,CAAC"}
|