@koslibs/components 1.5.0 → 1.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +31 -0
- package/README.md +85 -0
- package/dist/components/Button/button.js +20 -4
- package/dist/components/Button/index_module.css +1 -27
- package/dist/components/Collapse/collapse.js +3 -1
- package/dist/components/Collapse/index_module.css +2 -4
- package/dist/components/Input/index_module.css +9 -20
- package/dist/components/Input/input.d.ts +1 -1
- package/dist/components/Input/vars.css +7 -7
- package/dist/components/Modal/components/footer/index_module.css +1 -1
- package/dist/components/Modal/components/header/index.d.ts +1 -1
- package/dist/components/Modal/components/header/index_module.css +3 -3
- package/dist/components/Modal/index_module.css +2 -2
- package/dist/components/Popover/components/popover-surface/index.js +1 -1
- package/dist/components/Popover/{use-popover-position.d.ts → hooks/use-popover-position.d.ts} +1 -1
- package/dist/components/Spinner/preset_module.css +3 -1
- package/dist/components/Tabs/context.d.ts +10 -0
- package/dist/components/Tabs/context.js +3 -0
- package/dist/components/Tabs/hooks/use-tab-indicator.d.ts +11 -0
- package/dist/components/Tabs/hooks/use-tab-indicator.js +43 -0
- package/dist/components/Tabs/index.d.ts +3 -0
- package/dist/components/Tabs/index.js +2 -0
- package/dist/components/Tabs/index.module.js +12 -0
- package/dist/components/Tabs/index_module.css +92 -0
- package/dist/components/Tabs/tab.d.ts +9 -0
- package/dist/components/Tabs/tab.js +38 -0
- package/dist/components/Tabs/tabs.d.ts +13 -0
- package/dist/components/Tabs/tabs.js +116 -0
- package/dist/components/Tabs/types.d.ts +61 -0
- package/dist/components/Tabs/types.js +0 -0
- package/dist/components/Tabs/vars.css +20 -0
- package/dist/components/Textarea/hooks/use-autosize.d.ts +2 -0
- package/dist/components/Textarea/hooks/use-autosize.js +106 -0
- package/dist/components/Textarea/index.d.ts +2 -0
- package/dist/components/Textarea/index.js +1 -0
- package/dist/components/Textarea/index.module.js +14 -0
- package/dist/components/Textarea/index_module.css +269 -0
- package/dist/components/Textarea/textarea.d.ts +27 -0
- package/dist/components/Textarea/textarea.js +173 -0
- package/dist/components/Textarea/types.d.ts +108 -0
- package/dist/components/Textarea/types.js +0 -0
- package/dist/components/Textarea/vars.css +9 -0
- package/dist/components/Typography/index.d.ts +1 -1
- package/dist/components/Typography/index_module.css +2 -2
- package/dist/components/Typography/preset.module.js +2 -0
- package/dist/components/Typography/preset_module.css +4 -0
- package/dist/components/Typography/shared.d.ts +1 -1
- package/dist/components/Typography/text.d.ts +1 -1
- package/dist/components/Typography/vars.css +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.js +2 -0
- package/dist/styles/theme.css +1 -0
- package/dist/styles/variables.css +63 -0
- package/package.json +2 -1
- /package/dist/components/Popover/{use-popover-position.js → hooks/use-popover-position.js} +0 -0
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
@import "../../styles/theme.css";
|
|
2
|
+
@import "./vars.css";
|
|
3
|
+
|
|
4
|
+
.component-mEZo4o {
|
|
5
|
+
width: 100%;
|
|
6
|
+
min-width: 0;
|
|
7
|
+
font-family: var(--font-primary);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
.list-pbTqPB {
|
|
11
|
+
gap: var(--tabs-gap);
|
|
12
|
+
box-shadow: inset 0 -1px var(--tabs-divider-color);
|
|
13
|
+
display: flex;
|
|
14
|
+
position: relative;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.tab-yKhKqB {
|
|
18
|
+
justify-content: center;
|
|
19
|
+
align-items: center;
|
|
20
|
+
gap: var(--tabs-gap);
|
|
21
|
+
box-sizing: border-box;
|
|
22
|
+
margin: var(--size-0);
|
|
23
|
+
padding: var(--size-0) var(--tabs-padding);
|
|
24
|
+
border-radius: var(--tabs-border-radius);
|
|
25
|
+
color: var(--tabs-muted-color);
|
|
26
|
+
white-space: nowrap;
|
|
27
|
+
cursor: pointer;
|
|
28
|
+
-webkit-tap-highlight-color: transparent;
|
|
29
|
+
background: none;
|
|
30
|
+
border: 0;
|
|
31
|
+
outline: none;
|
|
32
|
+
flex: none;
|
|
33
|
+
display: inline-flex;
|
|
34
|
+
position: relative;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.size40-F0WNwL {
|
|
38
|
+
height: var(--tabs-height-40);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
.size48-cLRBaS {
|
|
42
|
+
height: var(--tabs-height-48);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.tab-yKhKqB:after {
|
|
46
|
+
height: var(--tabs-indicator-height);
|
|
47
|
+
content: "";
|
|
48
|
+
background: none;
|
|
49
|
+
position: absolute;
|
|
50
|
+
bottom: 0;
|
|
51
|
+
left: 0;
|
|
52
|
+
right: 0;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.tab-yKhKqB:hover:not(:disabled) {
|
|
56
|
+
color: var(--tabs-color);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
.tab-yKhKqB:hover:not(:disabled):not(.selected-Lm0vXW):after {
|
|
60
|
+
background: var(--tabs-hover-indicator-color);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.tab-yKhKqB.selected-Lm0vXW, .tab-yKhKqB .counter-Tokn9i {
|
|
64
|
+
color: var(--tabs-color);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.indicator-LDebsI {
|
|
68
|
+
height: var(--tabs-indicator-height);
|
|
69
|
+
background: var(--tabs-indicator-color);
|
|
70
|
+
pointer-events: none;
|
|
71
|
+
transition: transform var(--tabs-indicator-transition-duration) ease,
|
|
72
|
+
width var(--tabs-indicator-transition-duration) ease;
|
|
73
|
+
position: absolute;
|
|
74
|
+
bottom: 0;
|
|
75
|
+
left: 0;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.tab-yKhKqB .counter-Tokn9i {
|
|
79
|
+
padding: var(--size-0) var(--tabs-counter-padding);
|
|
80
|
+
border-radius: var(--tabs-counter-border-radius);
|
|
81
|
+
background: var(--tabs-counter-background-color);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
.tab-yKhKqB:disabled, .tab-yKhKqB:disabled .counter-Tokn9i {
|
|
85
|
+
color: var(--tabs-disabled-color);
|
|
86
|
+
cursor: default;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
.tab-yKhKqB:disabled .counter-Tokn9i {
|
|
90
|
+
background: var(--tabs-disabled-counter-background-color);
|
|
91
|
+
}
|
|
92
|
+
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { TabProps } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Кнопка вкладки с заголовком, счётчиком и состоянием выбора из Tabs.
|
|
4
|
+
* Содержимое выбранной вкладки отображается отдельно в приложении.
|
|
5
|
+
*/
|
|
6
|
+
export declare const Tab: {
|
|
7
|
+
({ id, title, count, disabled }: TabProps): import("react").JSX.Element;
|
|
8
|
+
displayName: string;
|
|
9
|
+
};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import classnames from "classnames";
|
|
3
|
+
import { useContext } from "react";
|
|
4
|
+
import { useDataTestId } from "../../hooks/use-data-test-id.js";
|
|
5
|
+
import { TypographyText } from "../Typography/text.js";
|
|
6
|
+
import { TabsContext } from "./context.js";
|
|
7
|
+
import index_module from "./index.module.js";
|
|
8
|
+
const Tab = ({ id, title, count, disabled = false })=>{
|
|
9
|
+
const context = useContext(TabsContext);
|
|
10
|
+
const getDataTestId = useDataTestId(context?.dataTestId);
|
|
11
|
+
if (!context) throw new Error('Tab must be rendered inside Tabs.');
|
|
12
|
+
const { selectedId, size, registerTab, selectTab } = context;
|
|
13
|
+
const selected = id === selectedId;
|
|
14
|
+
return /*#__PURE__*/ jsxs("button", {
|
|
15
|
+
ref: (button)=>registerTab(id, button),
|
|
16
|
+
type: "button",
|
|
17
|
+
disabled: disabled,
|
|
18
|
+
className: classnames(index_module.tab, index_module[`size${size}`], {
|
|
19
|
+
[index_module.selected]: selected
|
|
20
|
+
}),
|
|
21
|
+
onClick: (event)=>selectTab(id, event),
|
|
22
|
+
"data-test-id": getDataTestId(`tab-${id}`),
|
|
23
|
+
children: [
|
|
24
|
+
/*#__PURE__*/ jsx(TypographyText, {
|
|
25
|
+
size: 14,
|
|
26
|
+
weight: "medium",
|
|
27
|
+
children: title
|
|
28
|
+
}),
|
|
29
|
+
void 0 !== count && Number.isInteger(count) && count >= 0 && /*#__PURE__*/ jsx(TypographyText, {
|
|
30
|
+
size: 11,
|
|
31
|
+
className: index_module.counter,
|
|
32
|
+
children: count
|
|
33
|
+
})
|
|
34
|
+
]
|
|
35
|
+
});
|
|
36
|
+
};
|
|
37
|
+
Tab.displayName = 'Tab';
|
|
38
|
+
export { Tab };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
export declare const Tabs: import("react").ForwardRefExoticComponent<Omit<import("react").HTMLAttributes<HTMLDivElement>, "children" | "onChange"> & {
|
|
3
|
+
children?: ReactNode;
|
|
4
|
+
selectedId?: string;
|
|
5
|
+
defaultSelectedId?: string;
|
|
6
|
+
onChange?: (event: import("react").MouseEvent<HTMLButtonElement>, payload: {
|
|
7
|
+
selectedId: string;
|
|
8
|
+
}) => void;
|
|
9
|
+
size?: 40 | 48;
|
|
10
|
+
emptyState?: ReactNode;
|
|
11
|
+
listClassName?: string;
|
|
12
|
+
dataTestId?: string;
|
|
13
|
+
} & import("react").RefAttributes<HTMLDivElement>>;
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import classnames from "classnames";
|
|
3
|
+
import { Children, Fragment, forwardRef, isValidElement, useLayoutEffect, useMemo, useRef, useState } from "react";
|
|
4
|
+
import { useDataTestId } from "../../hooks/use-data-test-id.js";
|
|
5
|
+
import { TabsContext } from "./context.js";
|
|
6
|
+
import { useTabIndicator } from "./hooks/use-tab-indicator.js";
|
|
7
|
+
import { Tab } from "./tab.js";
|
|
8
|
+
import index_module from "./index.module.js";
|
|
9
|
+
function collectTabs(children) {
|
|
10
|
+
const items = [];
|
|
11
|
+
const ids = new Set();
|
|
12
|
+
const collect = (nodes)=>{
|
|
13
|
+
Children.forEach(nodes, (child)=>{
|
|
14
|
+
if (null == child || 'boolean' == typeof child) return;
|
|
15
|
+
if (/*#__PURE__*/ isValidElement(child) && child.type === Fragment) return void collect(child.props.children);
|
|
16
|
+
if (!/*#__PURE__*/ isValidElement(child) || child.type !== Tab) throw new Error('Tabs accepts only Tab elements and Fragments.');
|
|
17
|
+
if (ids.has(child.props.id)) throw new Error(`Tabs requires unique Tab ids: "${child.props.id}" is duplicated.`);
|
|
18
|
+
ids.add(child.props.id);
|
|
19
|
+
items.push(child.props);
|
|
20
|
+
});
|
|
21
|
+
};
|
|
22
|
+
collect(children);
|
|
23
|
+
return items;
|
|
24
|
+
}
|
|
25
|
+
function resolveValue(items, value, previous) {
|
|
26
|
+
const index = items.findIndex((item)=>item.id === value);
|
|
27
|
+
if (index >= 0 && !items[index].disabled) return value;
|
|
28
|
+
if (index < 0) {
|
|
29
|
+
const previousIndex = previous.items.findIndex((item)=>item.id === value);
|
|
30
|
+
if (previousIndex >= 0) {
|
|
31
|
+
const neighbors = [
|
|
32
|
+
...previous.items.slice(previousIndex + 1),
|
|
33
|
+
...previous.items.slice(0, previousIndex).reverse()
|
|
34
|
+
];
|
|
35
|
+
const neighbor = neighbors.find((candidate)=>items.some((item)=>item.id === candidate.id && !item.disabled));
|
|
36
|
+
if (neighbor) return neighbor.id;
|
|
37
|
+
}
|
|
38
|
+
if (items.some((item)=>item.id === previous.value && !item.disabled)) return previous.value;
|
|
39
|
+
}
|
|
40
|
+
const start = Math.max(0, index);
|
|
41
|
+
return items.slice(start).find((item)=>!item.disabled)?.id ?? items.slice(0, start).reverse().find((item)=>!item.disabled)?.id;
|
|
42
|
+
}
|
|
43
|
+
const Tabs = /*#__PURE__*/ forwardRef(({ children, selectedId, defaultSelectedId, onChange, size = 40, emptyState, listClassName, dataTestId, className, ...restProps }, ref)=>{
|
|
44
|
+
const getDataTestId = useDataTestId(dataTestId);
|
|
45
|
+
const items = useMemo(()=>collectTabs(children), [
|
|
46
|
+
children
|
|
47
|
+
]);
|
|
48
|
+
const [internalValue, setInternalValue] = useState(defaultSelectedId);
|
|
49
|
+
const previousSelection = useRef({
|
|
50
|
+
items
|
|
51
|
+
});
|
|
52
|
+
const selectedValue = resolveValue(items, selectedId ?? internalValue, previousSelection.current);
|
|
53
|
+
const listRef = useRef(null);
|
|
54
|
+
const buttons = useRef(new Map());
|
|
55
|
+
useLayoutEffect(()=>{
|
|
56
|
+
previousSelection.current = {
|
|
57
|
+
items,
|
|
58
|
+
value: selectedValue
|
|
59
|
+
};
|
|
60
|
+
if (void 0 === selectedId && internalValue !== selectedValue) setInternalValue(selectedValue);
|
|
61
|
+
}, [
|
|
62
|
+
items,
|
|
63
|
+
selectedValue,
|
|
64
|
+
selectedId,
|
|
65
|
+
internalValue
|
|
66
|
+
]);
|
|
67
|
+
const indicatorRef = useTabIndicator({
|
|
68
|
+
selectedId: selectedValue,
|
|
69
|
+
items,
|
|
70
|
+
size,
|
|
71
|
+
listRef,
|
|
72
|
+
buttons
|
|
73
|
+
});
|
|
74
|
+
const select = (id, event)=>{
|
|
75
|
+
if (id === selectedValue) return;
|
|
76
|
+
if (void 0 === selectedId) setInternalValue(id);
|
|
77
|
+
onChange?.(event, {
|
|
78
|
+
selectedId: id
|
|
79
|
+
});
|
|
80
|
+
};
|
|
81
|
+
return /*#__PURE__*/ jsx("div", {
|
|
82
|
+
...restProps,
|
|
83
|
+
ref: ref,
|
|
84
|
+
className: classnames(index_module.component, className),
|
|
85
|
+
"data-test-id": dataTestId,
|
|
86
|
+
children: void 0 === selectedValue ? emptyState : /*#__PURE__*/ jsx(TabsContext.Provider, {
|
|
87
|
+
value: {
|
|
88
|
+
selectedId: selectedValue,
|
|
89
|
+
size,
|
|
90
|
+
dataTestId,
|
|
91
|
+
registerTab: (id, button)=>{
|
|
92
|
+
if (button) buttons.current.set(id, button);
|
|
93
|
+
else buttons.current.delete(id);
|
|
94
|
+
},
|
|
95
|
+
selectTab: select
|
|
96
|
+
},
|
|
97
|
+
children: /*#__PURE__*/ jsxs("div", {
|
|
98
|
+
ref: listRef,
|
|
99
|
+
className: classnames(index_module.list, listClassName),
|
|
100
|
+
"data-test-id": getDataTestId('list'),
|
|
101
|
+
children: [
|
|
102
|
+
items.map((item)=>/*#__PURE__*/ jsx(Tab, {
|
|
103
|
+
...item
|
|
104
|
+
}, item.id)),
|
|
105
|
+
/*#__PURE__*/ jsx("div", {
|
|
106
|
+
ref: indicatorRef,
|
|
107
|
+
className: index_module.indicator,
|
|
108
|
+
"data-test-id": getDataTestId('indicator')
|
|
109
|
+
})
|
|
110
|
+
]
|
|
111
|
+
})
|
|
112
|
+
})
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
Tabs.displayName = 'Tabs';
|
|
116
|
+
export { Tabs };
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import type { HTMLAttributes, MouseEvent, ReactNode } from 'react';
|
|
2
|
+
export type TabProps = {
|
|
3
|
+
/**
|
|
4
|
+
* Уникальный стабильный идентификатор вкладки.
|
|
5
|
+
*/
|
|
6
|
+
id: string;
|
|
7
|
+
/**
|
|
8
|
+
* Текст заголовка вкладки.
|
|
9
|
+
*/
|
|
10
|
+
title: ReactNode;
|
|
11
|
+
/**
|
|
12
|
+
* Неотрицательное целое число. Неизвестное значение скрывается, 0 отображается.
|
|
13
|
+
*/
|
|
14
|
+
count?: number;
|
|
15
|
+
/**
|
|
16
|
+
* Запрещает выбор вкладки.
|
|
17
|
+
* @default false
|
|
18
|
+
*/
|
|
19
|
+
disabled?: boolean;
|
|
20
|
+
};
|
|
21
|
+
export type TabsProps = Omit<HTMLAttributes<HTMLDivElement>, 'children' | 'onChange'> & {
|
|
22
|
+
/**
|
|
23
|
+
* Дочерние Tab в порядке отображения. id должны быть уникальными.
|
|
24
|
+
* Поддерживаются массивы, условные элементы и Fragment.
|
|
25
|
+
*/
|
|
26
|
+
children?: ReactNode;
|
|
27
|
+
/**
|
|
28
|
+
* Идентификатор активной вкладки в controlled-режиме.
|
|
29
|
+
*/
|
|
30
|
+
selectedId?: string;
|
|
31
|
+
/**
|
|
32
|
+
* Начальная вкладка в uncontrolled-режиме. По умолчанию — первая доступная.
|
|
33
|
+
*/
|
|
34
|
+
defaultSelectedId?: string;
|
|
35
|
+
/**
|
|
36
|
+
* Запрос выбора другой вкладки пользователем: событие и { selectedId }.
|
|
37
|
+
* В controlled-режиме обновите selectedId. Повторный выбор и изменение children
|
|
38
|
+
* не вызывают обработчик.
|
|
39
|
+
*/
|
|
40
|
+
onChange?: (event: MouseEvent<HTMLButtonElement>, payload: {
|
|
41
|
+
selectedId: string;
|
|
42
|
+
}) => void;
|
|
43
|
+
/**
|
|
44
|
+
* Высота заголовков вкладок в пикселях.
|
|
45
|
+
* @default 40
|
|
46
|
+
*/
|
|
47
|
+
size?: 40 | 48;
|
|
48
|
+
/**
|
|
49
|
+
* Общее пустое состояние, когда нет доступных вкладок.
|
|
50
|
+
*/
|
|
51
|
+
emptyState?: ReactNode;
|
|
52
|
+
/**
|
|
53
|
+
* Класс ряда заголовков.
|
|
54
|
+
*/
|
|
55
|
+
listClassName?: string;
|
|
56
|
+
/**
|
|
57
|
+
* Идентификатор корня. Части получают суффиксы -list, -indicator,
|
|
58
|
+
* -tab-{id}.
|
|
59
|
+
*/
|
|
60
|
+
dataTestId?: string;
|
|
61
|
+
};
|
|
File without changes
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
:root {
|
|
2
|
+
--tabs-color: #1c1a18;
|
|
3
|
+
--tabs-muted-color: #736554;
|
|
4
|
+
--tabs-disabled-color: #9da099;
|
|
5
|
+
--tabs-indicator-color: #d95300;
|
|
6
|
+
--tabs-hover-indicator-color: #c8beaa;
|
|
7
|
+
--tabs-counter-background-color: #e0dbce;
|
|
8
|
+
--tabs-disabled-counter-background-color: #e0dbce73;
|
|
9
|
+
--tabs-divider-color: #e0dbce;
|
|
10
|
+
--tabs-height-40: 40px;
|
|
11
|
+
--tabs-height-48: 48px;
|
|
12
|
+
--tabs-padding: var(--size-12);
|
|
13
|
+
--tabs-gap: var(--size-8);
|
|
14
|
+
--tabs-border-radius: var(--border-radius-4);
|
|
15
|
+
--tabs-indicator-height: 2px;
|
|
16
|
+
--tabs-indicator-transition-duration: .2s;
|
|
17
|
+
--tabs-counter-padding: var(--size-6);
|
|
18
|
+
--tabs-counter-border-radius: var(--border-radius-pill);
|
|
19
|
+
}
|
|
20
|
+
|
|
@@ -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 @@
|
|
|
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;
|