@koslibs/components 1.4.0 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/dist/components/Input/index.d.ts +2 -0
  3. package/dist/components/Input/index.js +1 -0
  4. package/dist/components/Input/index.module.js +25 -0
  5. package/dist/components/Input/index_module.css +312 -0
  6. package/dist/components/Input/input.d.ts +29 -0
  7. package/dist/components/Input/input.js +179 -0
  8. package/dist/components/Input/types.d.ts +115 -0
  9. package/dist/components/Input/types.js +0 -0
  10. package/dist/components/Input/vars.css +32 -0
  11. package/dist/components/Modal/components/content/index.js +3 -2
  12. package/dist/components/Modal/components/controls/index.js +3 -2
  13. package/dist/components/Modal/components/footer/index.js +3 -2
  14. package/dist/components/Modal/components/header/index.js +3 -2
  15. package/dist/components/Textarea/hooks/use-autosize.d.ts +2 -0
  16. package/dist/components/Textarea/hooks/use-autosize.js +106 -0
  17. package/dist/components/Textarea/index.d.ts +2 -0
  18. package/dist/components/Textarea/index.js +1 -0
  19. package/dist/components/Textarea/index.module.js +14 -0
  20. package/dist/components/Textarea/index_module.css +280 -0
  21. package/dist/components/Textarea/textarea.d.ts +27 -0
  22. package/dist/components/Textarea/textarea.js +173 -0
  23. package/dist/components/Textarea/types.d.ts +108 -0
  24. package/dist/components/Textarea/types.js +0 -0
  25. package/dist/components/Textarea/vars.css +9 -0
  26. package/dist/hooks/use-data-test-id.d.ts +5 -0
  27. package/dist/hooks/use-data-test-id.js +7 -0
  28. package/dist/index.d.ts +4 -0
  29. package/dist/index.js +2 -0
  30. package/package.json +2 -2
@@ -0,0 +1,115 @@
1
+ import type { ChangeEvent, CSSProperties, InputHTMLAttributes, MouseEvent, ReactNode } from 'react';
2
+ export type InputProps = Omit<InputHTMLAttributes<HTMLInputElement>, 'size' | 'value' | 'defaultValue' | 'maxLength' | 'onChange' | 'children'> & {
3
+ /**
4
+ * Значение управляемого поля.
5
+ */
6
+ value?: string;
7
+ /**
8
+ * Начальное значение неуправляемого поля.
9
+ */
10
+ defaultValue?: string;
11
+ /**
12
+ * Максимальная длина ввода. Передаётся в нативный maxLength.
13
+ * Длина считается в кодовых единицах UTF-16, как в HTML input.
14
+ */
15
+ maxLength?: number;
16
+ /**
17
+ * Показывает текущую длину и maxLength, например 13/64.
18
+ * Работает только при заданном неотрицательном целом maxLength.
19
+ * При inner расположен внутри поля, при outer — рядом с внешним label.
20
+ * @default false
21
+ */
22
+ showValueLength?: boolean;
23
+ /**
24
+ * Вид поля: белый primary или светлый secondary.
25
+ * @default 'primary'
26
+ */
27
+ view?: 'primary' | 'secondary';
28
+ /**
29
+ * Высота поля в пикселях без внешнего label и сообщения.
30
+ * @default 40
31
+ */
32
+ size?: 40 | 48 | 56 | 64 | 72;
33
+ /**
34
+ * Растягивает компонент на ширину контейнера.
35
+ * @default false
36
+ */
37
+ block?: boolean;
38
+ /**
39
+ * Название поля. Связывается с input через htmlFor и id.
40
+ */
41
+ label?: ReactNode;
42
+ /**
43
+ * Положение label: снаружи или внутри поля.
44
+ * Внутренний label поднимается при фокусе или заполнении поля.
45
+ * @default 'outer'
46
+ */
47
+ labelView?: 'outer' | 'inner';
48
+ /**
49
+ * Подсказка под полем. При наличии сообщения об ошибке заменяется им.
50
+ */
51
+ hint?: ReactNode;
52
+ /**
53
+ * Сообщение об ошибке или true для состояния ошибки без сообщения.
54
+ * Сообщение заменяет hint; без hint отображается только состояние ошибки.
55
+ */
56
+ error?: ReactNode | boolean;
57
+ /**
58
+ * Аддон слева от значения, например иконка поиска.
59
+ */
60
+ leftAddon?: ReactNode;
61
+ /**
62
+ * Аддон справа от значения, например единица измерения или кнопка.
63
+ */
64
+ rightAddon?: ReactNode;
65
+ /**
66
+ * Показывает кнопку очистки заполненного поля. Скрыта в disabled и readOnly.
67
+ * @default false
68
+ */
69
+ clear?: boolean;
70
+ /**
71
+ * Доступное имя кнопки очистки.
72
+ * @default 'Очистить поле'
73
+ */
74
+ clearLabel?: string;
75
+ /**
76
+ * Обработчик ввода с нативным событием React и текущим значением.
77
+ */
78
+ onChange?: (event: ChangeEvent<HTMLInputElement>, payload: {
79
+ value: string;
80
+ }) => void;
81
+ /**
82
+ * Обработчик очистки. Не вызывает onChange.
83
+ * Для управляемого поля обновите value в этом обработчике.
84
+ */
85
+ onClear?: (event: MouseEvent<HTMLButtonElement>) => void;
86
+ /**
87
+ * Класс обёртки компонента.
88
+ */
89
+ className?: string;
90
+ /**
91
+ * Стили обёртки компонента, включая ширину и CSS-переменные.
92
+ */
93
+ style?: CSSProperties;
94
+ /**
95
+ * Класс визуального поля с аддонами.
96
+ */
97
+ fieldClassName?: string;
98
+ /**
99
+ * Класс нативного input.
100
+ */
101
+ inputClassName?: string;
102
+ /**
103
+ * Класс label.
104
+ */
105
+ labelClassName?: string;
106
+ /**
107
+ * Класс подсказки или сообщения об ошибке.
108
+ */
109
+ messageClassName?: string;
110
+ /**
111
+ * Идентификатор нативного input. Части получают суффиксы -form-control,
112
+ * -field, -label, -hint, -error, -left-addon, -right-addon, -clear и -counter.
113
+ */
114
+ dataTestId?: string;
115
+ };
File without changes
@@ -0,0 +1,32 @@
1
+ :root {
2
+ --input-primary-background-color: #fff;
3
+ --input-secondary-background-color: #f5f3ec;
4
+ --input-color: #1c1a18;
5
+ --input-placeholder-color: #736554;
6
+ --input-label-color: #736554;
7
+ --input-hint-color: #736554;
8
+ --input-icon-color: #736554;
9
+ --input-border-color: transparent;
10
+ --input-hover-border-color: #c8beaa;
11
+ --input-focus-border-color: #d95300;
12
+ --input-error-border-color: #ef5350;
13
+ --input-error-message-color: #b42318;
14
+ --input-disabled-background-color: #cfd1cb;
15
+ --input-disabled-color: #858981;
16
+ --input-read-only-border-color: #c8beaa;
17
+ --input-border-radius: 8px;
18
+ --input-gap: 8px;
19
+ --input-icon-size: 16px;
20
+ --input-width: 320px;
21
+ --input-font-size-40: 13px;
22
+ --input-font-size-48: 13px;
23
+ --input-font-size-56: 14px;
24
+ --input-font-size-64: 14px;
25
+ --input-font-size-72: 16px;
26
+ --input-padding-40: 12px;
27
+ --input-padding-48: 12px;
28
+ --input-padding-56: 16px;
29
+ --input-padding-64: 16px;
30
+ --input-padding-72: 20px;
31
+ }
32
+
@@ -1,16 +1,17 @@
1
1
  import { jsx } from "react/jsx-runtime";
2
2
  import classnames from "classnames";
3
3
  import { forwardRef, useContext } from "react";
4
+ import { useDataTestId } from "../../../../hooks/use-data-test-id.js";
4
5
  import { ModalContext } from "../../context.js";
5
6
  import index_module from "./index.module.js";
6
7
  const Content = /*#__PURE__*/ forwardRef(({ children, className, dataTestId, ...restProps }, ref)=>{
7
8
  const { dataTestId: modalDataTestId } = useContext(ModalContext);
8
- const testId = dataTestId ?? modalDataTestId;
9
+ const getDataTestId = useDataTestId(dataTestId ?? modalDataTestId);
9
10
  return /*#__PURE__*/ jsx("div", {
10
11
  ...restProps,
11
12
  ref: ref,
12
13
  className: classnames(index_module.component, className),
13
- "data-test-id": testId ? `${testId}-content` : void 0,
14
+ "data-test-id": getDataTestId('content'),
14
15
  children: children
15
16
  });
16
17
  });
@@ -1,16 +1,17 @@
1
1
  import { jsx, jsxs } from "react/jsx-runtime";
2
2
  import classnames from "classnames";
3
3
  import react, { forwardRef, useContext } from "react";
4
+ import { useDataTestId } from "../../../../hooks/use-data-test-id.js";
4
5
  import { ModalContext } from "../../context.js";
5
6
  import index_module from "./index.module.js";
6
7
  const Controls = /*#__PURE__*/ forwardRef(({ primary, secondary, layout = 'end', gap = 12, className, children, dataTestId, ...restProps }, ref)=>{
7
8
  const { dataTestId: modalDataTestId } = useContext(ModalContext);
8
- const testId = dataTestId ?? modalDataTestId;
9
+ const getDataTestId = useDataTestId(dataTestId ?? modalDataTestId);
9
10
  return /*#__PURE__*/ jsx("div", {
10
11
  ...restProps,
11
12
  ref: ref,
12
13
  className: classnames(index_module.component, index_module[layout], index_module[`gap-${gap}`], className),
13
- "data-test-id": testId ? `${testId}-controls` : void 0,
14
+ "data-test-id": getDataTestId('controls'),
14
15
  children: children ?? /*#__PURE__*/ jsxs(react.Fragment, {
15
16
  children: [
16
17
  secondary,
@@ -1,16 +1,17 @@
1
1
  import { jsx } from "react/jsx-runtime";
2
2
  import classnames from "classnames";
3
3
  import { forwardRef, useContext } from "react";
4
+ import { useDataTestId } from "../../../../hooks/use-data-test-id.js";
4
5
  import { ModalContext } from "../../context.js";
5
6
  import index_module from "./index.module.js";
6
7
  const Footer = /*#__PURE__*/ forwardRef(({ children, className, dataTestId, ...restProps }, ref)=>{
7
8
  const { dataTestId: modalDataTestId } = useContext(ModalContext);
8
- const testId = dataTestId ?? modalDataTestId;
9
+ const getDataTestId = useDataTestId(dataTestId ?? modalDataTestId);
9
10
  return /*#__PURE__*/ jsx("div", {
10
11
  ...restProps,
11
12
  ref: ref,
12
13
  className: classnames(index_module.component, className),
13
- "data-test-id": testId ? `${testId}-footer` : void 0,
14
+ "data-test-id": getDataTestId('footer'),
14
15
  children: children
15
16
  });
16
17
  });
@@ -2,13 +2,14 @@ import { jsx, jsxs } from "react/jsx-runtime";
2
2
  import { CrossHeavyMIcon } from "@koslibs/icons/CrossHeavyMIcon";
3
3
  import classnames from "classnames";
4
4
  import { forwardRef, useContext } from "react";
5
+ import { useDataTestId } from "../../../../hooks/use-data-test-id.js";
5
6
  import { Button } from "../../../Button/index.js";
6
7
  import { TypographyText } from "../../../Typography/index.js";
7
8
  import { ModalContext } from "../../context.js";
8
9
  import index_module from "./index.module.js";
9
10
  const Header = /*#__PURE__*/ forwardRef(({ title, subtitle, hasCloser = true, className, dataTestId, ...restProps }, ref)=>{
10
11
  const { onClose, dataTestId: modalDataTestId } = useContext(ModalContext);
11
- const testId = dataTestId ?? modalDataTestId;
12
+ const getDataTestId = useDataTestId(dataTestId ?? modalDataTestId);
12
13
  const handleClick = ()=>{
13
14
  onClose?.();
14
15
  };
@@ -16,7 +17,7 @@ const Header = /*#__PURE__*/ forwardRef(({ title, subtitle, hasCloser = true, cl
16
17
  ...restProps,
17
18
  ref: ref,
18
19
  className: classnames(index_module.component, className),
19
- "data-test-id": testId ? `${testId}-header` : void 0,
20
+ "data-test-id": getDataTestId('header'),
20
21
  children: [
21
22
  /*#__PURE__*/ jsxs("div", {
22
23
  className: index_module.content,
@@ -0,0 +1,2 @@
1
+ import { type RefObject } from 'react';
2
+ export declare function useAutosize(ref: RefObject<HTMLTextAreaElement>, autosize: boolean, minRows: number, maxRows?: number, formId?: string): void;
@@ -0,0 +1,106 @@
1
+ import { useEffect, useLayoutEffect, useRef } from "react";
2
+ const useBrowserLayoutEffect = "u" < typeof document ? useEffect : useLayoutEffect;
3
+ function useAutosize(ref, autosize, minRows, maxRows, formId) {
4
+ const updateRef = useRef();
5
+ useBrowserLayoutEffect(()=>{
6
+ if (!autosize) return;
7
+ const textarea = ref.current;
8
+ if (!textarea) return;
9
+ const doc = textarea.ownerDocument;
10
+ const view = doc.defaultView;
11
+ if (!view) return;
12
+ const measure = doc.createElement('textarea');
13
+ measure.tabIndex = -1;
14
+ Object.assign(measure.style, {
15
+ position: 'absolute',
16
+ visibility: 'hidden',
17
+ pointerEvents: 'none',
18
+ height: '0',
19
+ minHeight: '0',
20
+ maxHeight: 'none',
21
+ padding: '0',
22
+ border: '0',
23
+ boxSizing: 'content-box',
24
+ overflow: 'hidden',
25
+ top: '0',
26
+ left: '0'
27
+ });
28
+ doc.body.append(measure);
29
+ const update = ()=>{
30
+ const computed = view.getComputedStyle(textarea);
31
+ const width = textarea.clientWidth;
32
+ if (!width) return;
33
+ Object.assign(measure.style, {
34
+ width: `${width}px`,
35
+ fontFamily: computed.fontFamily,
36
+ fontSize: computed.fontSize,
37
+ fontWeight: computed.fontWeight,
38
+ fontStyle: computed.fontStyle,
39
+ lineHeight: computed.lineHeight,
40
+ letterSpacing: computed.letterSpacing,
41
+ textIndent: computed.textIndent,
42
+ textTransform: computed.textTransform,
43
+ wordBreak: computed.wordBreak,
44
+ overflowWrap: computed.overflowWrap
45
+ });
46
+ measure.wrap = textarea.wrap;
47
+ const lineHeight = parseFloat(computed.lineHeight);
48
+ if (!Number.isFinite(lineHeight) || lineHeight <= 0) return;
49
+ measure.value = textarea.value || textarea.placeholder || ' ';
50
+ const height = Math.min(Math.max(measure.scrollHeight, minRows * lineHeight), void 0 === maxRows ? 1 / 0 : maxRows * lineHeight);
51
+ textarea.style.height = `${height}px`;
52
+ };
53
+ update();
54
+ updateRef.current = update;
55
+ const handleInput = ()=>{
56
+ queueMicrotask(()=>{
57
+ if (measure.isConnected) update();
58
+ });
59
+ };
60
+ textarea.addEventListener('input', handleInput);
61
+ const handleReset = (event)=>{
62
+ setTimeout(()=>{
63
+ if (measure.isConnected && !event.defaultPrevented) update();
64
+ }, 0);
65
+ };
66
+ const form = textarea.form;
67
+ form?.addEventListener('reset', handleReset);
68
+ let previousWidth = textarea.clientWidth;
69
+ const observer = "u" < typeof ResizeObserver ? void 0 : new ResizeObserver(()=>{
70
+ const width = textarea.clientWidth;
71
+ if (width !== previousWidth) {
72
+ previousWidth = width;
73
+ update();
74
+ }
75
+ });
76
+ observer?.observe(textarea);
77
+ view.addEventListener('resize', update);
78
+ doc.fonts?.addEventListener('loadingdone', update);
79
+ return ()=>{
80
+ observer?.disconnect();
81
+ view.removeEventListener('resize', update);
82
+ textarea.removeEventListener('input', handleInput);
83
+ form?.removeEventListener('reset', handleReset);
84
+ doc.fonts?.removeEventListener('loadingdone', update);
85
+ measure.remove();
86
+ updateRef.current = void 0;
87
+ };
88
+ }, [
89
+ ref,
90
+ autosize,
91
+ minRows,
92
+ maxRows,
93
+ formId
94
+ ]);
95
+ useBrowserLayoutEffect(()=>{
96
+ updateRef.current?.();
97
+ });
98
+ useBrowserLayoutEffect(()=>{
99
+ if (!autosize) ref.current?.style.removeProperty('height');
100
+ }, [
101
+ ref,
102
+ autosize,
103
+ minRows
104
+ ]);
105
+ }
106
+ export { useAutosize };
@@ -0,0 +1,2 @@
1
+ export { Textarea } from './textarea.js';
2
+ export type { TextareaProps } from './types.js';
@@ -0,0 +1 @@
1
+ export { Textarea } from "./textarea.js";
@@ -0,0 +1,14 @@
1
+ import "./index_module.css";
2
+ const index_module = {
3
+ component: "component-K9LhZN",
4
+ field: "field-GADSqb",
5
+ textarea: "textarea-vCe_J9",
6
+ value: "value-pi9twE",
7
+ header: "header-AqxZRm",
8
+ innerHeader: "innerHeader-N47qW7",
9
+ counter: "counter-XxZoUu",
10
+ label: "label-fhdpHS",
11
+ clear: "clear-BZMCFP",
12
+ message: "message-_mT8Ov"
13
+ };
14
+ export default index_module;
@@ -0,0 +1,280 @@
1
+ @import "../../styles/theme.css";
2
+ @import "./vars.css";
3
+
4
+ .component-K9LhZN {
5
+ --field-background: var(--input-primary-background-color);
6
+ --field-border: var(--input-border-color);
7
+ --field-color: var(--input-color);
8
+ --field-label-color: var(--input-label-color);
9
+ --field-placeholder-color: var(--input-placeholder-color);
10
+ --field-icon-color: var(--input-icon-color);
11
+ gap: var(--input-gap);
12
+ width: var(--textarea-width);
13
+ vertical-align: top;
14
+ min-width: 0;
15
+ max-width: 100%;
16
+ font-family: var(--font-primary);
17
+ color: var(--field-color);
18
+ flex-direction: column;
19
+ display: inline-flex;
20
+
21
+ &[data-block] {
22
+ width: 100%;
23
+ display: flex;
24
+ }
25
+
26
+ &[data-view="secondary"] {
27
+ --field-background: var(--input-secondary-background-color);
28
+ }
29
+
30
+ &[data-read-only] {
31
+ --field-border: var(--input-read-only-border-color);
32
+ }
33
+
34
+ &[data-error] {
35
+ --field-border: var(--input-error-border-color);
36
+ }
37
+
38
+ &[data-disabled] {
39
+ --field-background: var(--input-disabled-background-color);
40
+ --field-border: transparent;
41
+ --field-color: var(--input-disabled-color);
42
+ --field-label-color: var(--input-disabled-color);
43
+ --field-placeholder-color: var(--input-disabled-color);
44
+ --field-icon-color: var(--input-disabled-color);
45
+ }
46
+ }
47
+
48
+ .field-GADSqb {
49
+ box-sizing: border-box;
50
+ align-items: flex-start;
51
+ gap: var(--input-gap);
52
+ width: 100%;
53
+ padding: var(--textarea-padding);
54
+ border-radius: var(--input-border-radius);
55
+ background: var(--field-background);
56
+ box-shadow: inset 0 0 0 1px var(--field-border);
57
+ cursor: text;
58
+ display: flex;
59
+ }
60
+
61
+ @media (hover: hover) {
62
+ .component-K9LhZN:not([data-disabled], [data-read-only], [data-error]) .field-GADSqb:hover {
63
+ box-shadow: inset 0 0 0 1px var(--input-hover-border-color);
64
+ }
65
+ }
66
+
67
+ .component-K9LhZN:not([data-disabled]) .field-GADSqb:focus-within {
68
+ box-shadow: none;
69
+ outline: 2px solid var(--input-focus-border-color);
70
+ outline-offset: 0;
71
+ }
72
+
73
+ .component-K9LhZN[data-error]:not([data-disabled]) .field-GADSqb:focus-within {
74
+ outline-color: var(--input-error-border-color);
75
+ }
76
+
77
+ .component-K9LhZN[data-disabled] .field-GADSqb, .textarea-vCe_J9:disabled {
78
+ cursor: not-allowed;
79
+ }
80
+
81
+ .value-pi9twE {
82
+ flex-direction: column;
83
+ flex: 1;
84
+ min-width: 0;
85
+ display: flex;
86
+ position: relative;
87
+ }
88
+
89
+ .header-AqxZRm {
90
+ align-items: baseline;
91
+ gap: var(--input-gap);
92
+ min-width: 0;
93
+ display: flex;
94
+ }
95
+
96
+ .innerHeader-N47qW7 {
97
+ width: 100%;
98
+ height: 15px;
99
+ position: absolute;
100
+ top: 0;
101
+ left: 0;
102
+ }
103
+
104
+ .component-K9LhZN .counter-XxZoUu {
105
+ color: var(--field-label-color);
106
+ white-space: nowrap;
107
+ text-align: right;
108
+ font-variant-numeric: tabular-nums;
109
+ flex-shrink: 0;
110
+ margin-left: auto;
111
+ line-height: 16px;
112
+ }
113
+
114
+ .innerHeader-N47qW7 .counter-XxZoUu {
115
+ line-height: 15px;
116
+ }
117
+
118
+ .label-fhdpHS {
119
+ min-width: 0;
120
+ color: var(--field-label-color);
121
+ overflow-wrap: anywhere;
122
+ cursor: inherit;
123
+ flex: 1;
124
+ font-size: 13px;
125
+ line-height: 16px;
126
+ display: block;
127
+ }
128
+
129
+ .component-K9LhZN[data-inner-label] .label-fhdpHS {
130
+ white-space: nowrap;
131
+ text-overflow: ellipsis;
132
+ font-size: var(--textarea-font-size);
133
+ line-height: var(--textarea-line-height);
134
+ transition: transform .18s, font-size .18s, line-height .18s;
135
+ overflow: hidden;
136
+ transform: translateY(7.5px);
137
+
138
+ & > span {
139
+ font-size: inherit;
140
+ line-height: inherit;
141
+ }
142
+ }
143
+
144
+ .component-K9LhZN[data-inner-label][data-filled] .label-fhdpHS, .component-K9LhZN[data-inner-label]:not([data-disabled], [data-read-only]) .value-pi9twE:focus-within .label-fhdpHS {
145
+ font-size: 12px;
146
+ line-height: 15px;
147
+ transform: translateY(0);
148
+ }
149
+
150
+ .component-K9LhZN[data-inner-label] .value-pi9twE:has(.textarea-vCe_J9:autofill) .label-fhdpHS {
151
+ font-size: 12px;
152
+ line-height: 15px;
153
+ transform: translateY(0);
154
+ }
155
+
156
+ .component-K9LhZN[data-inner-header] .textarea-vCe_J9 {
157
+ margin-top: 15px;
158
+ }
159
+
160
+ .component-K9LhZN[data-inner-label] .textarea-vCe_J9::placeholder {
161
+ opacity: 0;
162
+ transition: opacity .18s;
163
+ }
164
+
165
+ .component-K9LhZN[data-inner-label]:not([data-disabled], [data-read-only]) .textarea-vCe_J9:focus::placeholder {
166
+ opacity: 1;
167
+ }
168
+
169
+ .textarea-vCe_J9 {
170
+ box-sizing: border-box;
171
+ width: 100%;
172
+ min-width: 0;
173
+ height: calc(var(--textarea-rows) * var(--textarea-line-height));
174
+ min-height: calc(var(--textarea-rows) * var(--textarea-line-height));
175
+ color: var(--field-color);
176
+ font-family: var(--font-primary);
177
+ font-size: var(--textarea-font-size);
178
+ font-weight: 400;
179
+ line-height: var(--textarea-line-height);
180
+ overflow-wrap: break-word;
181
+ resize: none;
182
+ appearance: none;
183
+ scrollbar-color: auto;
184
+ scrollbar-width: auto;
185
+ background: none;
186
+ border: 0;
187
+ border-radius: 0;
188
+ outline: none;
189
+ margin: 0;
190
+ padding: 0;
191
+ display: block;
192
+ overflow: auto;
193
+
194
+ &::-webkit-scrollbar {
195
+ background: none;
196
+ width: 6px;
197
+ height: 6px;
198
+ }
199
+
200
+ &::-webkit-scrollbar-button {
201
+ width: 0;
202
+ height: 0;
203
+ display: none;
204
+ }
205
+
206
+ &::-webkit-scrollbar-track {
207
+ background: none;
208
+ }
209
+
210
+ &::-webkit-scrollbar-track-piece {
211
+ background: none;
212
+ }
213
+
214
+ &::-webkit-scrollbar-corner {
215
+ background: none;
216
+ }
217
+
218
+ &::-webkit-scrollbar-thumb {
219
+ background: var(--field-icon-color);
220
+ border-radius: 999px;
221
+ }
222
+
223
+ &::placeholder {
224
+ color: var(--field-placeholder-color);
225
+ opacity: 1;
226
+ }
227
+
228
+ &:disabled {
229
+ opacity: 1;
230
+ -webkit-text-fill-color: var(--field-color);
231
+ }
232
+ }
233
+
234
+ @supports not selector(::-webkit-scrollbar) {
235
+ .textarea-vCe_J9 {
236
+ scrollbar-width: thin;
237
+ scrollbar-color: var(--field-icon-color) transparent;
238
+ }
239
+ }
240
+
241
+ .component-K9LhZN[data-resize] .textarea-vCe_J9 {
242
+ resize: vertical;
243
+ }
244
+
245
+ .component-K9LhZN .clear-BZMCFP {
246
+ width: 24px;
247
+ min-width: 0;
248
+ height: 24px;
249
+ min-height: 0;
250
+ color: var(--field-icon-color);
251
+ background: none;
252
+ flex: 0 0 24px;
253
+ margin: 0 -4px;
254
+ padding: 0;
255
+
256
+ &:hover, &:active {
257
+ color: var(--field-icon-color);
258
+ }
259
+
260
+ & svg {
261
+ width: var(--input-icon-size);
262
+ height: var(--input-icon-size);
263
+ display: block;
264
+ }
265
+ }
266
+
267
+ .component-K9LhZN .message-_mT8Ov {
268
+ color: var(--input-hint-color);
269
+ overflow-wrap: anywhere;
270
+ line-height: 15px;
271
+ }
272
+
273
+ .component-K9LhZN[data-error] .message-_mT8Ov {
274
+ color: var(--input-error-message-color);
275
+ }
276
+
277
+ .component-K9LhZN[data-disabled] .message-_mT8Ov {
278
+ color: var(--input-disabled-color);
279
+ }
280
+
@@ -0,0 +1,27 @@
1
+ import { type ChangeEvent, type MouseEvent } from 'react';
2
+ export declare const Textarea: import("react").ForwardRefExoticComponent<Omit<import("react").TextareaHTMLAttributes<HTMLTextAreaElement>, "value" | "defaultValue" | "children" | "onChange" | "maxLength" | "rows"> & {
3
+ value?: string;
4
+ defaultValue?: string;
5
+ maxLength?: number;
6
+ showValueLength?: boolean;
7
+ view?: "primary" | "secondary";
8
+ block?: boolean;
9
+ label?: import("react").ReactNode;
10
+ labelView?: "outer" | "inner";
11
+ hint?: import("react").ReactNode;
12
+ error?: import("react").ReactNode | boolean;
13
+ minRows?: number;
14
+ maxRows?: number;
15
+ autosize?: boolean;
16
+ resize?: boolean;
17
+ clear?: boolean;
18
+ onChange?: (event: ChangeEvent<HTMLTextAreaElement>, payload: {
19
+ value: string;
20
+ }) => void;
21
+ onClear?: (event: MouseEvent<HTMLButtonElement>) => void;
22
+ fieldClassName?: string;
23
+ textareaClassName?: string;
24
+ labelClassName?: string;
25
+ messageClassName?: string;
26
+ dataTestId?: string;
27
+ } & import("react").RefAttributes<HTMLTextAreaElement>>;