jvetrau-ds 0.2.8 → 0.2.9
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/components/flip-list/flip-list.cjs +29 -15
- package/components/flip-list/flip-list.cjs.map +1 -1
- package/components/flip-list/flip-list.css +64 -31
- package/components/flip-list/flip-list.d.ts +2 -0
- package/components/flip-list/flip-list.js +28 -15
- package/components/flip-list/flip-list.js.map +1 -1
- package/components/index.cjs +1 -1
- package/components/index.d.ts +4 -4
- package/components/index.js +1 -1
- package/components/input/index.cjs +1 -10
- package/components/input/index.d.ts +2 -2
- package/components/input/index.js +1 -1
- package/components/input/input.cjs +12 -11
- package/components/input/input.cjs.map +1 -1
- package/components/input/input.d.ts +2 -2
- package/components/input/input.js +12 -8
- package/components/input/input.js.map +1 -1
- package/components/select/select.cjs +12 -4
- package/components/select/select.cjs.map +1 -1
- package/components/select/select.css +17 -1
- package/components/select/select.d.ts +2 -0
- package/components/select/select.js +12 -4
- package/components/select/select.js.map +1 -1
- package/components/textarea/textarea.cjs +68 -4
- package/components/textarea/textarea.cjs.map +1 -1
- package/components/textarea/textarea.css +25 -0
- package/components/textarea/textarea.d.ts +3 -0
- package/components/textarea/textarea.js +68 -4
- package/components/textarea/textarea.js.map +1 -1
- package/index.d.ts +1 -1
- package/package.json +1 -1
- package/styles.css +106 -32
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/select/select.tsx"],"names":["classnames","jsx"],"mappings":";;;;;
|
|
1
|
+
{"version":3,"sources":["../../../src/components/select/select.tsx"],"names":["classnames","jsx"],"mappings":";;;;;AAcA,MAAM,SAAgC,CAAC;AAAA,EACrC,KAAA,GAAQ,SAAA;AAAA,EACR,KAAA,GAAQ,SAAA;AAAA,EACR,SAAA,GAAY,EAAA;AAAA,EACZ,QAAA,GAAW,KAAA;AAAA,EACX,QAAA;AAAA,EACA,GAAG;AACL,CAAA,KAAM;AACJ,EAAA,MAAM,OAAA,GAAUA,qBAAA;AAAA,IACd,QAAA;AAAA,IACA,SAAA;AAAA,IACA;AAAA,MACE,iBACE,KAAA,KAAU,OAAA;AAAA,MACZ,mBACE,KAAA,KAAU,SAAA;AAAA,MACZ,uBACE,KAAA,KAAU,OAAA;AAAA,MACZ,yBACE,KAAA,KAAU,SAAA;AAAA,MACZ,qBACE,KAAA,KAAU;AAAA;AACd,GACF;AAEA,EAAA,uBACEC,cAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,OAAA,EACd,QAAA,kBAAAA,cAAA;AAAA,IAAC,QAAA;AAAA,IAAA;AAAA,MACC,SAAA,EAAU,eAAA;AAAA,MACV,QAAA;AAAA,MACC,GAAG,KAAA;AAAA,MAEH;AAAA;AAAA,GACH,EACF,CAAA;AAEJ,CAAA;AAEA,IAAO,cAAA,GAAQ","file":"select.cjs","sourcesContent":["import React from 'react';\nimport { classnames } from '../helpers/classnames';\n\ntype SelectWidth =\n | 'short'\n | 'default'\n | 'max';\n\nexport interface SelectProps\n extends React.SelectHTMLAttributes<HTMLSelectElement> {\n state?: 'default' | 'error' | 'success';\n width?: SelectWidth;\n}\n\nconst Select: React.FC<SelectProps> = ({\n state = 'default',\n width = 'default',\n className = '',\n disabled = false,\n children,\n ...props\n}) => {\n const classes = classnames(\n 'select',\n className,\n {\n 'select--error':\n state === 'error',\n 'select--success':\n state === 'success',\n 'select--width-short':\n width === 'short',\n 'select--width-default':\n width === 'default',\n 'select--width-max':\n width === 'max',\n },\n );\n\n return (\n <div className={classes}>\n <select\n className=\"select__field\"\n disabled={disabled}\n {...props}\n >\n {children}\n </select>\n </div>\n );\n};\n\nexport default Select;\n"]}
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
|
|
31
31
|
position: relative;
|
|
32
32
|
display: inline-block;
|
|
33
|
-
|
|
33
|
+
box-sizing: border-box;
|
|
34
34
|
|
|
35
35
|
/* border */
|
|
36
36
|
--select-border-width: var(--size-border-width-base);
|
|
@@ -51,6 +51,21 @@
|
|
|
51
51
|
--select-transition-duration: 0.2s;
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
+
.select--width-short {
|
|
55
|
+
/* size */
|
|
56
|
+
width: fit-content;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
.select--width-default {
|
|
60
|
+
/* size */
|
|
61
|
+
width: 400px;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.select--width-max {
|
|
65
|
+
/* size */
|
|
66
|
+
width: 100%;
|
|
67
|
+
}
|
|
68
|
+
|
|
54
69
|
.select__field {
|
|
55
70
|
/* color */
|
|
56
71
|
background: var(--select-bg);
|
|
@@ -61,6 +76,7 @@
|
|
|
61
76
|
letter-spacing: inherit;
|
|
62
77
|
|
|
63
78
|
/* size */
|
|
79
|
+
box-sizing: border-box;
|
|
64
80
|
width: 100%;
|
|
65
81
|
height: var(--select-height);
|
|
66
82
|
padding-left: var(--select-padding-x);
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
+
type SelectWidth = 'short' | 'default' | 'max';
|
|
2
3
|
export interface SelectProps extends React.SelectHTMLAttributes<HTMLSelectElement> {
|
|
3
4
|
state?: 'default' | 'error' | 'success';
|
|
5
|
+
width?: SelectWidth;
|
|
4
6
|
}
|
|
5
7
|
declare const Select: React.FC<SelectProps>;
|
|
6
8
|
export default Select;
|
|
@@ -3,15 +3,23 @@ import { classnames } from '../helpers/classnames';
|
|
|
3
3
|
|
|
4
4
|
const Select = ({
|
|
5
5
|
state = "default",
|
|
6
|
+
width = "default",
|
|
6
7
|
className = "",
|
|
7
8
|
disabled = false,
|
|
8
9
|
children,
|
|
9
10
|
...props
|
|
10
11
|
}) => {
|
|
11
|
-
const classes = classnames(
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
const classes = classnames(
|
|
13
|
+
"select",
|
|
14
|
+
className,
|
|
15
|
+
{
|
|
16
|
+
"select--error": state === "error",
|
|
17
|
+
"select--success": state === "success",
|
|
18
|
+
"select--width-short": width === "short",
|
|
19
|
+
"select--width-default": width === "default",
|
|
20
|
+
"select--width-max": width === "max"
|
|
21
|
+
}
|
|
22
|
+
);
|
|
15
23
|
return /* @__PURE__ */ jsx("div", { className: classes, children: /* @__PURE__ */ jsx(
|
|
16
24
|
"select",
|
|
17
25
|
{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/select/select.tsx"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"sources":["../../../src/components/select/select.tsx"],"names":[],"mappings":";;;AAcA,MAAM,SAAgC,CAAC;AAAA,EACrC,KAAA,GAAQ,SAAA;AAAA,EACR,KAAA,GAAQ,SAAA;AAAA,EACR,SAAA,GAAY,EAAA;AAAA,EACZ,QAAA,GAAW,KAAA;AAAA,EACX,QAAA;AAAA,EACA,GAAG;AACL,CAAA,KAAM;AACJ,EAAA,MAAM,OAAA,GAAU,UAAA;AAAA,IACd,QAAA;AAAA,IACA,SAAA;AAAA,IACA;AAAA,MACE,iBACE,KAAA,KAAU,OAAA;AAAA,MACZ,mBACE,KAAA,KAAU,SAAA;AAAA,MACZ,uBACE,KAAA,KAAU,OAAA;AAAA,MACZ,yBACE,KAAA,KAAU,SAAA;AAAA,MACZ,qBACE,KAAA,KAAU;AAAA;AACd,GACF;AAEA,EAAA,uBACE,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,OAAA,EACd,QAAA,kBAAA,GAAA;AAAA,IAAC,QAAA;AAAA,IAAA;AAAA,MACC,SAAA,EAAU,eAAA;AAAA,MACV,QAAA;AAAA,MACC,GAAG,KAAA;AAAA,MAEH;AAAA;AAAA,GACH,EACF,CAAA;AAEJ,CAAA;AAEA,IAAO,cAAA,GAAQ","file":"select.js","sourcesContent":["import React from 'react';\nimport { classnames } from '../helpers/classnames';\n\ntype SelectWidth =\n | 'short'\n | 'default'\n | 'max';\n\nexport interface SelectProps\n extends React.SelectHTMLAttributes<HTMLSelectElement> {\n state?: 'default' | 'error' | 'success';\n width?: SelectWidth;\n}\n\nconst Select: React.FC<SelectProps> = ({\n state = 'default',\n width = 'default',\n className = '',\n disabled = false,\n children,\n ...props\n}) => {\n const classes = classnames(\n 'select',\n className,\n {\n 'select--error':\n state === 'error',\n 'select--success':\n state === 'success',\n 'select--width-short':\n width === 'short',\n 'select--width-default':\n width === 'default',\n 'select--width-max':\n width === 'max',\n },\n );\n\n return (\n <div className={classes}>\n <select\n className=\"select__field\"\n disabled={disabled}\n {...props}\n >\n {children}\n </select>\n </div>\n );\n};\n\nexport default Select;\n"]}
|
|
@@ -1,23 +1,87 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var jsxRuntime = require('react/jsx-runtime');
|
|
4
|
+
var react = require('react');
|
|
4
5
|
var classnames = require('../helpers/classnames');
|
|
5
6
|
|
|
7
|
+
function parsePixelValue(value) {
|
|
8
|
+
const parsed = Number.parseFloat(value);
|
|
9
|
+
return Number.isFinite(parsed) ? parsed : 0;
|
|
10
|
+
}
|
|
6
11
|
const Textarea = ({
|
|
7
12
|
state = "default",
|
|
13
|
+
width = "default",
|
|
14
|
+
autoGrow = false,
|
|
8
15
|
className = "",
|
|
9
16
|
disabled = false,
|
|
17
|
+
onInput,
|
|
10
18
|
...props
|
|
11
19
|
}) => {
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
20
|
+
const textareaRef = react.useRef(null);
|
|
21
|
+
const resizeToContent = react.useCallback(() => {
|
|
22
|
+
const textarea = textareaRef.current;
|
|
23
|
+
if (!autoGrow || !textarea) {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
const computedStyle = window.getComputedStyle(textarea);
|
|
27
|
+
const lineHeight = parsePixelValue(
|
|
28
|
+
computedStyle.lineHeight
|
|
29
|
+
);
|
|
30
|
+
const borderHeight = parsePixelValue(
|
|
31
|
+
computedStyle.borderTopWidth
|
|
32
|
+
) + parsePixelValue(
|
|
33
|
+
computedStyle.borderBottomWidth
|
|
34
|
+
);
|
|
35
|
+
const minHeight = parsePixelValue(
|
|
36
|
+
computedStyle.minHeight
|
|
37
|
+
);
|
|
38
|
+
const previousMinHeight = textarea.style.minHeight;
|
|
39
|
+
textarea.style.minHeight = "0px";
|
|
40
|
+
textarea.style.setProperty(
|
|
41
|
+
"--textarea-auto-height",
|
|
42
|
+
"0px"
|
|
43
|
+
);
|
|
44
|
+
const contentHeight = textarea.scrollHeight;
|
|
45
|
+
textarea.style.minHeight = previousMinHeight;
|
|
46
|
+
const nextHeight = Math.max(
|
|
47
|
+
contentHeight + lineHeight + borderHeight,
|
|
48
|
+
minHeight
|
|
49
|
+
);
|
|
50
|
+
textarea.style.setProperty(
|
|
51
|
+
"--textarea-auto-height",
|
|
52
|
+
`${nextHeight}px`
|
|
53
|
+
);
|
|
54
|
+
}, [autoGrow]);
|
|
55
|
+
react.useLayoutEffect(() => {
|
|
56
|
+
resizeToContent();
|
|
57
|
+
}, [
|
|
58
|
+
resizeToContent,
|
|
59
|
+
props.value,
|
|
60
|
+
width
|
|
61
|
+
]);
|
|
62
|
+
const handleInput = (event) => {
|
|
63
|
+
resizeToContent();
|
|
64
|
+
onInput?.(event);
|
|
65
|
+
};
|
|
66
|
+
const classes = classnames.classnames(
|
|
67
|
+
"textarea",
|
|
68
|
+
className,
|
|
69
|
+
{
|
|
70
|
+
"textarea--error": state === "error",
|
|
71
|
+
"textarea--success": state === "success",
|
|
72
|
+
"textarea--width-short": width === "short",
|
|
73
|
+
"textarea--width-default": width === "default",
|
|
74
|
+
"textarea--width-max": width === "max",
|
|
75
|
+
"textarea--auto-grow": autoGrow
|
|
76
|
+
}
|
|
77
|
+
);
|
|
16
78
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
17
79
|
"textarea",
|
|
18
80
|
{
|
|
81
|
+
ref: textareaRef,
|
|
19
82
|
className: classes,
|
|
20
83
|
disabled,
|
|
84
|
+
onInput: handleInput,
|
|
21
85
|
...props
|
|
22
86
|
}
|
|
23
87
|
);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/textarea/textarea.tsx"],"names":["classnames","jsx"],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../../../src/components/textarea/textarea.tsx"],"names":["useRef","useCallback","useLayoutEffect","classnames","jsx"],"mappings":";;;;;;AAmBA,SAAS,gBAAgB,KAAA,EAAe;AACtC,EAAA,MAAM,MAAA,GAAS,MAAA,CAAO,UAAA,CAAW,KAAK,CAAA;AAEtC,EAAA,OAAO,MAAA,CAAO,QAAA,CAAS,MAAM,CAAA,GACzB,MAAA,GACA,CAAA;AACN;AAEA,MAAM,WAAoC,CAAC;AAAA,EACzC,KAAA,GAAQ,SAAA;AAAA,EACR,KAAA,GAAQ,SAAA;AAAA,EACR,QAAA,GAAW,KAAA;AAAA,EACX,SAAA,GAAY,EAAA;AAAA,EACZ,QAAA,GAAW,KAAA;AAAA,EACX,OAAA;AAAA,EACA,GAAG;AACL,CAAA,KAAM;AACJ,EAAA,MAAM,WAAA,GACJA,aAA4B,IAAI,CAAA;AAElC,EAAA,MAAM,eAAA,GACJC,kBAAY,MAAM;AAChB,IAAA,MAAM,WACJ,WAAA,CAAY,OAAA;AAEd,IAAA,IAAI,CAAC,QAAA,IAAY,CAAC,QAAA,EAAU;AAC1B,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,aAAA,GACJ,MAAA,CAAO,gBAAA,CAAiB,QAAQ,CAAA;AAElC,IAAA,MAAM,UAAA,GACJ,eAAA;AAAA,MACE,aAAA,CAAc;AAAA,KAChB;AAEF,IAAA,MAAM,YAAA,GACJ,eAAA;AAAA,MACE,aAAA,CAAc;AAAA,KAChB,GACA,eAAA;AAAA,MACE,aAAA,CAAc;AAAA,KAChB;AAEF,IAAA,MAAM,SAAA,GACJ,eAAA;AAAA,MACE,aAAA,CAAc;AAAA,KAChB;AAEF,IAAA,MAAM,iBAAA,GACJ,SAAS,KAAA,CAAM,SAAA;AAEjB,IAAA,QAAA,CAAS,MAAM,SAAA,GACb,KAAA;AAEF,IAAA,QAAA,CAAS,KAAA,CAAM,WAAA;AAAA,MACb,wBAAA;AAAA,MACA;AAAA,KACF;AAEA,IAAA,MAAM,gBACJ,QAAA,CAAS,YAAA;AAEX,IAAA,QAAA,CAAS,MAAM,SAAA,GACb,iBAAA;AAEF,IAAA,MAAM,aAAa,IAAA,CAAK,GAAA;AAAA,MACtB,gBACE,UAAA,GACA,YAAA;AAAA,MACF;AAAA,KACF;AAEA,IAAA,QAAA,CAAS,KAAA,CAAM,WAAA;AAAA,MACb,wBAAA;AAAA,MACA,GAAG,UAAU,CAAA,EAAA;AAAA,KACf;AAAA,EACF,CAAA,EAAG,CAAC,QAAQ,CAAC,CAAA;AAEf,EAAAC,qBAAA,CAAgB,MAAM;AACpB,IAAA,eAAA,EAAgB;AAAA,EAClB,CAAA,EAAG;AAAA,IACD,eAAA;AAAA,IACA,KAAA,CAAM,KAAA;AAAA,IACN;AAAA,GACD,CAAA;AAED,EAAA,MAAM,WAAA,GAAc,CAClB,KAAA,KACG;AACH,IAAA,eAAA,EAAgB;AAChB,IAAA,OAAA,GAAU,KAAK,CAAA;AAAA,EACjB,CAAA;AAEA,EAAA,MAAM,OAAA,GAAUC,qBAAA;AAAA,IACd,UAAA;AAAA,IACA,SAAA;AAAA,IACA;AAAA,MACE,mBACE,KAAA,KAAU,OAAA;AAAA,MACZ,qBACE,KAAA,KAAU,SAAA;AAAA,MACZ,yBACE,KAAA,KAAU,OAAA;AAAA,MACZ,2BACE,KAAA,KAAU,SAAA;AAAA,MACZ,uBACE,KAAA,KAAU,KAAA;AAAA,MACZ,qBAAA,EACE;AAAA;AACJ,GACF;AAEA,EAAA,uBACEC,cAAA;AAAA,IAAC,UAAA;AAAA,IAAA;AAAA,MACC,GAAA,EAAK,WAAA;AAAA,MACL,SAAA,EAAW,OAAA;AAAA,MACX,QAAA;AAAA,MACA,OAAA,EAAS,WAAA;AAAA,MACR,GAAG;AAAA;AAAA,GACN;AAEJ,CAAA;AAEA,IAAO,gBAAA,GAAQ","file":"textarea.cjs","sourcesContent":["import React, {\n useCallback,\n useLayoutEffect,\n useRef,\n} from 'react';\nimport { classnames } from '../helpers/classnames';\n\ntype TextareaWidth =\n | 'short'\n | 'default'\n | 'max';\n\nexport interface TextareaProps\n extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {\n state?: 'default' | 'error' | 'success';\n width?: TextareaWidth;\n autoGrow?: boolean;\n}\n\nfunction parsePixelValue(value: string) {\n const parsed = Number.parseFloat(value);\n\n return Number.isFinite(parsed)\n ? parsed\n : 0;\n}\n\nconst Textarea: React.FC<TextareaProps> = ({\n state = 'default',\n width = 'default',\n autoGrow = false,\n className = '',\n disabled = false,\n onInput,\n ...props\n}) => {\n const textareaRef =\n useRef<HTMLTextAreaElement>(null);\n\n const resizeToContent =\n useCallback(() => {\n const textarea =\n textareaRef.current;\n\n if (!autoGrow || !textarea) {\n return;\n }\n\n const computedStyle =\n window.getComputedStyle(textarea);\n\n const lineHeight =\n parsePixelValue(\n computedStyle.lineHeight,\n );\n\n const borderHeight =\n parsePixelValue(\n computedStyle.borderTopWidth,\n ) +\n parsePixelValue(\n computedStyle.borderBottomWidth,\n );\n\n const minHeight =\n parsePixelValue(\n computedStyle.minHeight,\n );\n\n const previousMinHeight =\n textarea.style.minHeight;\n\n textarea.style.minHeight =\n '0px';\n\n textarea.style.setProperty(\n '--textarea-auto-height',\n '0px',\n );\n\n const contentHeight =\n textarea.scrollHeight;\n\n textarea.style.minHeight =\n previousMinHeight;\n\n const nextHeight = Math.max(\n contentHeight +\n lineHeight +\n borderHeight,\n minHeight,\n );\n\n textarea.style.setProperty(\n '--textarea-auto-height',\n `${nextHeight}px`,\n );\n }, [autoGrow]);\n\n useLayoutEffect(() => {\n resizeToContent();\n }, [\n resizeToContent,\n props.value,\n width,\n ]);\n\n const handleInput = (\n event: React.InputEvent<HTMLTextAreaElement>,\n ) => {\n resizeToContent();\n onInput?.(event);\n };\n\n const classes = classnames(\n 'textarea',\n className,\n {\n 'textarea--error':\n state === 'error',\n 'textarea--success':\n state === 'success',\n 'textarea--width-short':\n width === 'short',\n 'textarea--width-default':\n width === 'default',\n 'textarea--width-max':\n width === 'max',\n 'textarea--auto-grow':\n autoGrow,\n },\n );\n\n return (\n <textarea\n ref={textareaRef}\n className={classes}\n disabled={disabled}\n onInput={handleInput}\n {...props}\n />\n );\n};\n\nexport default Textarea;\n"]}
|
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
--textarea-padding-x: var(--padding-control-horz);
|
|
27
27
|
--textarea-padding-y: var(--padding-control-horz);
|
|
28
28
|
|
|
29
|
+
box-sizing: border-box;
|
|
29
30
|
min-height: var(--textarea-min-height);
|
|
30
31
|
padding: var(--textarea-padding-y) var(--textarea-padding-x);
|
|
31
32
|
|
|
@@ -55,6 +56,30 @@
|
|
|
55
56
|
background-color var(--textarea-transition-duration) ease;
|
|
56
57
|
}
|
|
57
58
|
|
|
59
|
+
.textarea--width-short {
|
|
60
|
+
/* size */
|
|
61
|
+
width: auto;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.textarea--width-default {
|
|
65
|
+
/* size */
|
|
66
|
+
width: 400px;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.textarea--width-max {
|
|
70
|
+
/* size */
|
|
71
|
+
width: 100%;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.textarea--auto-grow {
|
|
75
|
+
/* size */
|
|
76
|
+
height: var(--textarea-auto-height);
|
|
77
|
+
|
|
78
|
+
/* motion */
|
|
79
|
+
overflow-y: hidden;
|
|
80
|
+
resize: none;
|
|
81
|
+
}
|
|
82
|
+
|
|
58
83
|
.textarea::placeholder {
|
|
59
84
|
color: var(--textarea-placeholder);
|
|
60
85
|
}
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
+
type TextareaWidth = 'short' | 'default' | 'max';
|
|
2
3
|
export interface TextareaProps extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {
|
|
3
4
|
state?: 'default' | 'error' | 'success';
|
|
5
|
+
width?: TextareaWidth;
|
|
6
|
+
autoGrow?: boolean;
|
|
4
7
|
}
|
|
5
8
|
declare const Textarea: React.FC<TextareaProps>;
|
|
6
9
|
export default Textarea;
|
|
@@ -1,21 +1,85 @@
|
|
|
1
1
|
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { useRef, useCallback, useLayoutEffect } from 'react';
|
|
2
3
|
import { classnames } from '../helpers/classnames';
|
|
3
4
|
|
|
5
|
+
function parsePixelValue(value) {
|
|
6
|
+
const parsed = Number.parseFloat(value);
|
|
7
|
+
return Number.isFinite(parsed) ? parsed : 0;
|
|
8
|
+
}
|
|
4
9
|
const Textarea = ({
|
|
5
10
|
state = "default",
|
|
11
|
+
width = "default",
|
|
12
|
+
autoGrow = false,
|
|
6
13
|
className = "",
|
|
7
14
|
disabled = false,
|
|
15
|
+
onInput,
|
|
8
16
|
...props
|
|
9
17
|
}) => {
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
18
|
+
const textareaRef = useRef(null);
|
|
19
|
+
const resizeToContent = useCallback(() => {
|
|
20
|
+
const textarea = textareaRef.current;
|
|
21
|
+
if (!autoGrow || !textarea) {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
const computedStyle = window.getComputedStyle(textarea);
|
|
25
|
+
const lineHeight = parsePixelValue(
|
|
26
|
+
computedStyle.lineHeight
|
|
27
|
+
);
|
|
28
|
+
const borderHeight = parsePixelValue(
|
|
29
|
+
computedStyle.borderTopWidth
|
|
30
|
+
) + parsePixelValue(
|
|
31
|
+
computedStyle.borderBottomWidth
|
|
32
|
+
);
|
|
33
|
+
const minHeight = parsePixelValue(
|
|
34
|
+
computedStyle.minHeight
|
|
35
|
+
);
|
|
36
|
+
const previousMinHeight = textarea.style.minHeight;
|
|
37
|
+
textarea.style.minHeight = "0px";
|
|
38
|
+
textarea.style.setProperty(
|
|
39
|
+
"--textarea-auto-height",
|
|
40
|
+
"0px"
|
|
41
|
+
);
|
|
42
|
+
const contentHeight = textarea.scrollHeight;
|
|
43
|
+
textarea.style.minHeight = previousMinHeight;
|
|
44
|
+
const nextHeight = Math.max(
|
|
45
|
+
contentHeight + lineHeight + borderHeight,
|
|
46
|
+
minHeight
|
|
47
|
+
);
|
|
48
|
+
textarea.style.setProperty(
|
|
49
|
+
"--textarea-auto-height",
|
|
50
|
+
`${nextHeight}px`
|
|
51
|
+
);
|
|
52
|
+
}, [autoGrow]);
|
|
53
|
+
useLayoutEffect(() => {
|
|
54
|
+
resizeToContent();
|
|
55
|
+
}, [
|
|
56
|
+
resizeToContent,
|
|
57
|
+
props.value,
|
|
58
|
+
width
|
|
59
|
+
]);
|
|
60
|
+
const handleInput = (event) => {
|
|
61
|
+
resizeToContent();
|
|
62
|
+
onInput?.(event);
|
|
63
|
+
};
|
|
64
|
+
const classes = classnames(
|
|
65
|
+
"textarea",
|
|
66
|
+
className,
|
|
67
|
+
{
|
|
68
|
+
"textarea--error": state === "error",
|
|
69
|
+
"textarea--success": state === "success",
|
|
70
|
+
"textarea--width-short": width === "short",
|
|
71
|
+
"textarea--width-default": width === "default",
|
|
72
|
+
"textarea--width-max": width === "max",
|
|
73
|
+
"textarea--auto-grow": autoGrow
|
|
74
|
+
}
|
|
75
|
+
);
|
|
14
76
|
return /* @__PURE__ */ jsx(
|
|
15
77
|
"textarea",
|
|
16
78
|
{
|
|
79
|
+
ref: textareaRef,
|
|
17
80
|
className: classes,
|
|
18
81
|
disabled,
|
|
82
|
+
onInput: handleInput,
|
|
19
83
|
...props
|
|
20
84
|
}
|
|
21
85
|
);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/textarea/textarea.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../../../src/components/textarea/textarea.tsx"],"names":[],"mappings":";;;;AAmBA,SAAS,gBAAgB,KAAA,EAAe;AACtC,EAAA,MAAM,MAAA,GAAS,MAAA,CAAO,UAAA,CAAW,KAAK,CAAA;AAEtC,EAAA,OAAO,MAAA,CAAO,QAAA,CAAS,MAAM,CAAA,GACzB,MAAA,GACA,CAAA;AACN;AAEA,MAAM,WAAoC,CAAC;AAAA,EACzC,KAAA,GAAQ,SAAA;AAAA,EACR,KAAA,GAAQ,SAAA;AAAA,EACR,QAAA,GAAW,KAAA;AAAA,EACX,SAAA,GAAY,EAAA;AAAA,EACZ,QAAA,GAAW,KAAA;AAAA,EACX,OAAA;AAAA,EACA,GAAG;AACL,CAAA,KAAM;AACJ,EAAA,MAAM,WAAA,GACJ,OAA4B,IAAI,CAAA;AAElC,EAAA,MAAM,eAAA,GACJ,YAAY,MAAM;AAChB,IAAA,MAAM,WACJ,WAAA,CAAY,OAAA;AAEd,IAAA,IAAI,CAAC,QAAA,IAAY,CAAC,QAAA,EAAU;AAC1B,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,aAAA,GACJ,MAAA,CAAO,gBAAA,CAAiB,QAAQ,CAAA;AAElC,IAAA,MAAM,UAAA,GACJ,eAAA;AAAA,MACE,aAAA,CAAc;AAAA,KAChB;AAEF,IAAA,MAAM,YAAA,GACJ,eAAA;AAAA,MACE,aAAA,CAAc;AAAA,KAChB,GACA,eAAA;AAAA,MACE,aAAA,CAAc;AAAA,KAChB;AAEF,IAAA,MAAM,SAAA,GACJ,eAAA;AAAA,MACE,aAAA,CAAc;AAAA,KAChB;AAEF,IAAA,MAAM,iBAAA,GACJ,SAAS,KAAA,CAAM,SAAA;AAEjB,IAAA,QAAA,CAAS,MAAM,SAAA,GACb,KAAA;AAEF,IAAA,QAAA,CAAS,KAAA,CAAM,WAAA;AAAA,MACb,wBAAA;AAAA,MACA;AAAA,KACF;AAEA,IAAA,MAAM,gBACJ,QAAA,CAAS,YAAA;AAEX,IAAA,QAAA,CAAS,MAAM,SAAA,GACb,iBAAA;AAEF,IAAA,MAAM,aAAa,IAAA,CAAK,GAAA;AAAA,MACtB,gBACE,UAAA,GACA,YAAA;AAAA,MACF;AAAA,KACF;AAEA,IAAA,QAAA,CAAS,KAAA,CAAM,WAAA;AAAA,MACb,wBAAA;AAAA,MACA,GAAG,UAAU,CAAA,EAAA;AAAA,KACf;AAAA,EACF,CAAA,EAAG,CAAC,QAAQ,CAAC,CAAA;AAEf,EAAA,eAAA,CAAgB,MAAM;AACpB,IAAA,eAAA,EAAgB;AAAA,EAClB,CAAA,EAAG;AAAA,IACD,eAAA;AAAA,IACA,KAAA,CAAM,KAAA;AAAA,IACN;AAAA,GACD,CAAA;AAED,EAAA,MAAM,WAAA,GAAc,CAClB,KAAA,KACG;AACH,IAAA,eAAA,EAAgB;AAChB,IAAA,OAAA,GAAU,KAAK,CAAA;AAAA,EACjB,CAAA;AAEA,EAAA,MAAM,OAAA,GAAU,UAAA;AAAA,IACd,UAAA;AAAA,IACA,SAAA;AAAA,IACA;AAAA,MACE,mBACE,KAAA,KAAU,OAAA;AAAA,MACZ,qBACE,KAAA,KAAU,SAAA;AAAA,MACZ,yBACE,KAAA,KAAU,OAAA;AAAA,MACZ,2BACE,KAAA,KAAU,SAAA;AAAA,MACZ,uBACE,KAAA,KAAU,KAAA;AAAA,MACZ,qBAAA,EACE;AAAA;AACJ,GACF;AAEA,EAAA,uBACE,GAAA;AAAA,IAAC,UAAA;AAAA,IAAA;AAAA,MACC,GAAA,EAAK,WAAA;AAAA,MACL,SAAA,EAAW,OAAA;AAAA,MACX,QAAA;AAAA,MACA,OAAA,EAAS,WAAA;AAAA,MACR,GAAG;AAAA;AAAA,GACN;AAEJ,CAAA;AAEA,IAAO,gBAAA,GAAQ","file":"textarea.js","sourcesContent":["import React, {\n useCallback,\n useLayoutEffect,\n useRef,\n} from 'react';\nimport { classnames } from '../helpers/classnames';\n\ntype TextareaWidth =\n | 'short'\n | 'default'\n | 'max';\n\nexport interface TextareaProps\n extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {\n state?: 'default' | 'error' | 'success';\n width?: TextareaWidth;\n autoGrow?: boolean;\n}\n\nfunction parsePixelValue(value: string) {\n const parsed = Number.parseFloat(value);\n\n return Number.isFinite(parsed)\n ? parsed\n : 0;\n}\n\nconst Textarea: React.FC<TextareaProps> = ({\n state = 'default',\n width = 'default',\n autoGrow = false,\n className = '',\n disabled = false,\n onInput,\n ...props\n}) => {\n const textareaRef =\n useRef<HTMLTextAreaElement>(null);\n\n const resizeToContent =\n useCallback(() => {\n const textarea =\n textareaRef.current;\n\n if (!autoGrow || !textarea) {\n return;\n }\n\n const computedStyle =\n window.getComputedStyle(textarea);\n\n const lineHeight =\n parsePixelValue(\n computedStyle.lineHeight,\n );\n\n const borderHeight =\n parsePixelValue(\n computedStyle.borderTopWidth,\n ) +\n parsePixelValue(\n computedStyle.borderBottomWidth,\n );\n\n const minHeight =\n parsePixelValue(\n computedStyle.minHeight,\n );\n\n const previousMinHeight =\n textarea.style.minHeight;\n\n textarea.style.minHeight =\n '0px';\n\n textarea.style.setProperty(\n '--textarea-auto-height',\n '0px',\n );\n\n const contentHeight =\n textarea.scrollHeight;\n\n textarea.style.minHeight =\n previousMinHeight;\n\n const nextHeight = Math.max(\n contentHeight +\n lineHeight +\n borderHeight,\n minHeight,\n );\n\n textarea.style.setProperty(\n '--textarea-auto-height',\n `${nextHeight}px`,\n );\n }, [autoGrow]);\n\n useLayoutEffect(() => {\n resizeToContent();\n }, [\n resizeToContent,\n props.value,\n width,\n ]);\n\n const handleInput = (\n event: React.InputEvent<HTMLTextAreaElement>,\n ) => {\n resizeToContent();\n onInput?.(event);\n };\n\n const classes = classnames(\n 'textarea',\n className,\n {\n 'textarea--error':\n state === 'error',\n 'textarea--success':\n state === 'success',\n 'textarea--width-short':\n width === 'short',\n 'textarea--width-default':\n width === 'default',\n 'textarea--width-max':\n width === 'max',\n 'textarea--auto-grow':\n autoGrow,\n },\n );\n\n return (\n <textarea\n ref={textareaRef}\n className={classes}\n disabled={disabled}\n onInput={handleInput}\n {...props}\n />\n );\n};\n\nexport default Textarea;\n"]}
|
package/index.d.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
export { default as Button, buttonLink, } from './components/button';
|
|
6
6
|
export type { ButtonProps, } from './components/button';
|
|
7
7
|
export { default as Input } from './components/input';
|
|
8
|
-
export type { InputProps
|
|
8
|
+
export type { InputProps } from './components/input';
|
|
9
9
|
export { default as Textarea } from './components/textarea';
|
|
10
10
|
export type { TextareaProps } from './components/textarea';
|
|
11
11
|
export { default as Select } from './components/select';
|
package/package.json
CHANGED
package/styles.css
CHANGED
|
@@ -2758,7 +2758,7 @@
|
|
|
2758
2758
|
--flip-list-open-content-gap:
|
|
2759
2759
|
var(--font-h2-margin);
|
|
2760
2760
|
--flip-list-trigger-column-gap:
|
|
2761
|
-
var(--margin-
|
|
2761
|
+
var(--margin-icon);
|
|
2762
2762
|
--flip-list-scroll-margin-block-start:
|
|
2763
2763
|
0px;
|
|
2764
2764
|
|
|
@@ -2831,74 +2831,92 @@
|
|
|
2831
2831
|
/* motion */
|
|
2832
2832
|
}
|
|
2833
2833
|
|
|
2834
|
-
.flip-
|
|
2834
|
+
.flip-list__status {
|
|
2835
|
+
/* color */
|
|
2836
|
+
|
|
2837
|
+
/* typography */
|
|
2838
|
+
|
|
2839
|
+
/* size */
|
|
2840
|
+
--flip-list-status-gap:
|
|
2841
|
+
var(--margin-tag);
|
|
2842
|
+
|
|
2843
|
+
display: block;
|
|
2844
|
+
align-self: flex-start;
|
|
2845
|
+
min-width: 0;
|
|
2846
|
+
max-width: 100%;
|
|
2847
|
+
margin:
|
|
2848
|
+
0
|
|
2849
|
+
0
|
|
2850
|
+
var(--flip-list-status-gap)
|
|
2851
|
+
0;
|
|
2852
|
+
|
|
2853
|
+
/* border */
|
|
2854
|
+
|
|
2855
|
+
/* depth */
|
|
2856
|
+
|
|
2857
|
+
/* motion */
|
|
2858
|
+
}
|
|
2859
|
+
|
|
2860
|
+
.flip-list__heading {
|
|
2835
2861
|
/* color */
|
|
2836
|
-
background: transparent;
|
|
2837
|
-
color: var(--flip-list-trigger-color);
|
|
2838
2862
|
|
|
2839
2863
|
/* typography */
|
|
2840
|
-
font: inherit;
|
|
2841
|
-
text-align: left;
|
|
2842
2864
|
|
|
2843
2865
|
/* size */
|
|
2844
2866
|
display: flex;
|
|
2845
2867
|
align-items: center;
|
|
2846
|
-
justify-content: space-between;
|
|
2847
2868
|
gap: var(--flip-list-trigger-column-gap);
|
|
2848
2869
|
width: 100%;
|
|
2849
2870
|
min-width: 0;
|
|
2850
2871
|
max-width: 100%;
|
|
2851
|
-
padding: 0;
|
|
2852
2872
|
|
|
2853
2873
|
/* border */
|
|
2854
|
-
border: 0;
|
|
2855
2874
|
|
|
2856
2875
|
/* depth */
|
|
2857
2876
|
|
|
2858
2877
|
/* motion */
|
|
2859
|
-
cursor: pointer;
|
|
2860
2878
|
}
|
|
2861
2879
|
|
|
2862
|
-
.flip-list__trigger
|
|
2880
|
+
.flip-list__trigger {
|
|
2863
2881
|
/* color */
|
|
2882
|
+
background: transparent;
|
|
2883
|
+
color: var(--flip-list-trigger-color);
|
|
2864
2884
|
|
|
2865
2885
|
/* typography */
|
|
2886
|
+
font: inherit;
|
|
2887
|
+
text-align: left;
|
|
2866
2888
|
|
|
2867
2889
|
/* size */
|
|
2890
|
+
display: flex;
|
|
2891
|
+
flex: 0 1 auto;
|
|
2892
|
+
align-items: center;
|
|
2893
|
+
min-width: 0;
|
|
2894
|
+
max-width: 100%;
|
|
2895
|
+
padding: 0;
|
|
2868
2896
|
|
|
2869
2897
|
/* border */
|
|
2870
|
-
|
|
2871
|
-
var(--size-border-width-focus)
|
|
2872
|
-
solid
|
|
2873
|
-
currentColor;
|
|
2874
|
-
outline-offset:
|
|
2875
|
-
var(--size-border-offset-focus);
|
|
2898
|
+
border: 0;
|
|
2876
2899
|
|
|
2877
2900
|
/* depth */
|
|
2878
2901
|
|
|
2879
2902
|
/* motion */
|
|
2903
|
+
cursor: pointer;
|
|
2880
2904
|
}
|
|
2881
2905
|
|
|
2882
|
-
.flip-
|
|
2906
|
+
.flip-list__trigger:focus-visible {
|
|
2883
2907
|
/* color */
|
|
2884
2908
|
|
|
2885
2909
|
/* typography */
|
|
2886
2910
|
|
|
2887
2911
|
/* size */
|
|
2888
|
-
--flip-list-status-gap:
|
|
2889
|
-
var(--margin-tag);
|
|
2890
|
-
|
|
2891
|
-
display: block;
|
|
2892
|
-
align-self: flex-start;
|
|
2893
|
-
min-width: 0;
|
|
2894
|
-
max-width: 100%;
|
|
2895
|
-
margin:
|
|
2896
|
-
0
|
|
2897
|
-
0
|
|
2898
|
-
var(--flip-list-status-gap)
|
|
2899
|
-
0;
|
|
2900
2912
|
|
|
2901
2913
|
/* border */
|
|
2914
|
+
outline:
|
|
2915
|
+
var(--size-border-width-focus)
|
|
2916
|
+
solid
|
|
2917
|
+
currentColor;
|
|
2918
|
+
outline-offset:
|
|
2919
|
+
var(--size-border-offset-focus);
|
|
2902
2920
|
|
|
2903
2921
|
/* depth */
|
|
2904
2922
|
|
|
@@ -2927,7 +2945,6 @@
|
|
|
2927
2945
|
text-underline-offset: from-font;
|
|
2928
2946
|
|
|
2929
2947
|
/* size */
|
|
2930
|
-
flex: 1 1 auto;
|
|
2931
2948
|
min-width: 0;
|
|
2932
2949
|
max-width: 100%;
|
|
2933
2950
|
overflow-wrap: anywhere;
|
|
@@ -2955,6 +2972,21 @@
|
|
|
2955
2972
|
/* motion */
|
|
2956
2973
|
}
|
|
2957
2974
|
|
|
2975
|
+
.flip-list__status-icon {
|
|
2976
|
+
/* color */
|
|
2977
|
+
|
|
2978
|
+
/* typography */
|
|
2979
|
+
|
|
2980
|
+
/* size */
|
|
2981
|
+
flex: 0 0 auto;
|
|
2982
|
+
|
|
2983
|
+
/* border */
|
|
2984
|
+
|
|
2985
|
+
/* depth */
|
|
2986
|
+
|
|
2987
|
+
/* motion */
|
|
2988
|
+
}
|
|
2989
|
+
|
|
2958
2990
|
.flip-list__meta {
|
|
2959
2991
|
/* color */
|
|
2960
2992
|
color: var(--flip-list-meta-color);
|
|
@@ -2976,6 +3008,7 @@
|
|
|
2976
3008
|
flex: 0 0 auto;
|
|
2977
3009
|
min-width: 0;
|
|
2978
3010
|
max-width: 100%;
|
|
3011
|
+
margin-left: auto;
|
|
2979
3012
|
|
|
2980
3013
|
/* border */
|
|
2981
3014
|
|
|
@@ -4264,7 +4297,7 @@
|
|
|
4264
4297
|
|
|
4265
4298
|
position: relative;
|
|
4266
4299
|
display: inline-block;
|
|
4267
|
-
|
|
4300
|
+
box-sizing: border-box;
|
|
4268
4301
|
|
|
4269
4302
|
/* border */
|
|
4270
4303
|
--select-border-width: var(--size-border-width-base);
|
|
@@ -4285,6 +4318,21 @@
|
|
|
4285
4318
|
--select-transition-duration: 0.2s;
|
|
4286
4319
|
}
|
|
4287
4320
|
|
|
4321
|
+
.select--width-short {
|
|
4322
|
+
/* size */
|
|
4323
|
+
width: fit-content;
|
|
4324
|
+
}
|
|
4325
|
+
|
|
4326
|
+
.select--width-default {
|
|
4327
|
+
/* size */
|
|
4328
|
+
width: 400px;
|
|
4329
|
+
}
|
|
4330
|
+
|
|
4331
|
+
.select--width-max {
|
|
4332
|
+
/* size */
|
|
4333
|
+
width: 100%;
|
|
4334
|
+
}
|
|
4335
|
+
|
|
4288
4336
|
.select__field {
|
|
4289
4337
|
/* color */
|
|
4290
4338
|
background: var(--select-bg);
|
|
@@ -4295,6 +4343,7 @@
|
|
|
4295
4343
|
letter-spacing: inherit;
|
|
4296
4344
|
|
|
4297
4345
|
/* size */
|
|
4346
|
+
box-sizing: border-box;
|
|
4298
4347
|
width: 100%;
|
|
4299
4348
|
height: var(--select-height);
|
|
4300
4349
|
padding-left: var(--select-padding-x);
|
|
@@ -4700,6 +4749,7 @@
|
|
|
4700
4749
|
--textarea-padding-x: var(--padding-control-horz);
|
|
4701
4750
|
--textarea-padding-y: var(--padding-control-horz);
|
|
4702
4751
|
|
|
4752
|
+
box-sizing: border-box;
|
|
4703
4753
|
min-height: var(--textarea-min-height);
|
|
4704
4754
|
padding: var(--textarea-padding-y) var(--textarea-padding-x);
|
|
4705
4755
|
|
|
@@ -4729,6 +4779,30 @@
|
|
|
4729
4779
|
background-color var(--textarea-transition-duration) ease;
|
|
4730
4780
|
}
|
|
4731
4781
|
|
|
4782
|
+
.textarea--width-short {
|
|
4783
|
+
/* size */
|
|
4784
|
+
width: auto;
|
|
4785
|
+
}
|
|
4786
|
+
|
|
4787
|
+
.textarea--width-default {
|
|
4788
|
+
/* size */
|
|
4789
|
+
width: 400px;
|
|
4790
|
+
}
|
|
4791
|
+
|
|
4792
|
+
.textarea--width-max {
|
|
4793
|
+
/* size */
|
|
4794
|
+
width: 100%;
|
|
4795
|
+
}
|
|
4796
|
+
|
|
4797
|
+
.textarea--auto-grow {
|
|
4798
|
+
/* size */
|
|
4799
|
+
height: var(--textarea-auto-height);
|
|
4800
|
+
|
|
4801
|
+
/* motion */
|
|
4802
|
+
overflow-y: hidden;
|
|
4803
|
+
resize: none;
|
|
4804
|
+
}
|
|
4805
|
+
|
|
4732
4806
|
.textarea::placeholder {
|
|
4733
4807
|
color: var(--textarea-placeholder);
|
|
4734
4808
|
}
|