DocSpace-client/packages/shared/components/textarea/index.tsx

243 lines
6.5 KiB
TypeScript
Raw Normal View History

2023-01-20 15:46:39 +00:00
import React, { useRef, useState, useEffect } from "react";
import PropTypes from "prop-types";
2023-01-20 15:46:39 +00:00
import {
StyledTextarea,
StyledScrollbar,
StyledCopyIcon,
CopyIconWrapper,
Wrapper,
Numeration,
2023-01-20 15:46:39 +00:00
} from "./styled-textarea";
2023-11-10 07:20:02 +00:00
import { ColorTheme, ThemeType } from "../ColorTheme";
import Toast from "../toast";
import toastr from "../toast/toastr";
2023-01-20 15:46:39 +00:00
import { isJSON, beautifyJSON } from "./utils";
import copy from "copy-to-clipboard";
// eslint-disable-next-line react/prop-types, no-unused-vars
2023-11-27 06:58:19 +00:00
const jsonify = (value: any, isJSONField: any) => {
2023-06-07 07:33:42 +00:00
if (isJSONField && value && isJSON(value)) {
return beautifyJSON(value);
}
return value;
};
const Textarea = ({
className,
id,
isDisabled,
isReadOnly,
hasError,
heightScale,
maxLength,
name,
onChange,
placeholder,
style,
tabIndex,
value,
fontSize,
heightTextArea,
color,
theme,
autoFocus,
areaSelect,
2023-01-20 15:46:39 +00:00
isJSONField,
copyInfoText,
enableCopy,
hasNumeration,
isFullHeight,
2023-11-27 06:58:19 +00:00
classNameCopyIcon
}: any) => {
const areaRef = useRef(null);
2023-01-20 15:46:39 +00:00
const [isError, setIsError] = useState(hasError);
2023-06-07 07:33:42 +00:00
const modifiedValue = jsonify(value, isJSONField);
2023-01-20 15:46:39 +00:00
const lineHeight = 1.5;
const padding = 7;
const numberOfLines = modifiedValue.split("\n").length;
const textareaHeight = isFullHeight
? numberOfLines * fontSize * lineHeight + padding + 4
: heightTextArea;
const defaultPaddingLeft = 42;
const numberOfDigits =
String(numberOfLines).length - 2 > 0 ? String(numberOfLines).length : 0;
const paddingLeftProp = hasNumeration
? fontSize < 13
? `${defaultPaddingLeft + numberOfDigits * 6}px`
: `${((defaultPaddingLeft + numberOfDigits * 4) * fontSize) / 13}px`
: "8px";
const numerationValue = [];
for (let i = 1; i <= numberOfLines; i++) {
numerationValue.push(i);
}
2023-02-13 11:36:56 +00:00
function onTextareaClick() {
2023-11-27 06:58:19 +00:00
// @ts-expect-error TS(2531): Object is possibly 'null'.
2023-02-13 11:36:56 +00:00
areaRef.current.select();
}
useEffect(() => {
hasError !== isError && setIsError(hasError);
}, [hasError]);
2023-01-20 15:46:39 +00:00
useEffect(() => {
setIsError(isJSONField && (!value || !isJSON(value)));
2023-06-07 12:29:59 +00:00
}, [isJSONField, value]);
2023-01-20 15:46:39 +00:00
useEffect(() => {
if (areaSelect && areaRef.current) {
2023-11-27 06:58:19 +00:00
// @ts-expect-error TS(2339): Property 'select' does not exist on type 'never'.
areaRef.current.select();
}
}, [areaSelect]);
2023-11-27 06:58:19 +00:00
const WrappedStyledCopyIcon = ({
heightScale,
isJSONField,
...props
}: any) => (
<StyledCopyIcon {...props} />
);
return (
2023-02-13 11:36:56 +00:00
<Wrapper
className="textarea-wrapper"
2023-11-27 06:58:19 +00:00
// @ts-expect-error TS(2769): No overload matches this call.
2023-02-13 11:36:56 +00:00
isJSONField={isJSONField}
enableCopy={enableCopy}
onClick={onTextareaClick}
2023-02-13 11:36:56 +00:00
>
{enableCopy && (
<CopyIconWrapper
2023-06-30 09:55:31 +00:00
className={classNameCopyIcon}
2023-11-27 06:58:19 +00:00
// @ts-expect-error TS(2769): No overload matches this call.
isJSONField={isJSONField}
2023-01-22 11:45:41 +00:00
onClick={() => {
copy(modifiedValue);
2023-11-27 06:58:19 +00:00
// @ts-expect-error TS(2554): Expected 5 arguments, but got 1.
2023-01-22 11:45:41 +00:00
toastr.success(copyInfoText);
}}
>
<WrappedStyledCopyIcon heightScale={heightScale} />
</CopyIconWrapper>
2023-01-20 15:46:39 +00:00
)}
2023-11-27 06:58:19 +00:00
// @ts-expect-error TS(2322): Type '{ children: any[]; themeId: string; classNam... Remove this comment to see the full error message
<ColorTheme
themeId={ThemeType.Textarea}
className={className}
style={style}
stype="preMediumBlack"
2019-12-17 10:49:53 +00:00
isDisabled={isDisabled}
hasError={isError}
heightScale={heightScale}
heightTextArea={textareaHeight}
>
<Toast />
{hasNumeration && (
2023-11-27 06:58:19 +00:00
// @ts-expect-error TS(2769): No overload matches this call.
<Numeration fontSize={fontSize}>
{numerationValue.join("\n")}
</Numeration>
)}
<StyledTextarea
2023-11-27 06:58:19 +00:00
// @ts-expect-error TS(2769): No overload matches this call.
id={id}
paddingLeftProp={paddingLeftProp}
2023-02-13 11:36:56 +00:00
isJSONField={isJSONField}
enableCopy={enableCopy}
placeholder={placeholder}
2023-11-27 06:58:19 +00:00
onChange={(e: any) => onChange && onChange(e)}
maxLength={maxLength}
name={name}
tabIndex={tabIndex}
isDisabled={isDisabled}
disabled={isDisabled}
readOnly={isReadOnly}
value={isJSONField ? modifiedValue : value}
fontSize={fontSize}
color={color}
autoFocus={autoFocus}
ref={areaRef}
dir="auto"
/>
</ColorTheme>
</Wrapper>
);
};
Textarea.propTypes = {
/** Class name */
2019-12-17 10:49:53 +00:00
className: PropTypes.string,
/** Used as HTML `id` property */
id: PropTypes.string,
/** Indicates that the field cannot be used */
isDisabled: PropTypes.bool,
/** Indicates that the field is displaying read-only content */
isReadOnly: PropTypes.bool,
/** Indicates the input field has an error */
2020-07-08 13:57:34 +00:00
hasError: PropTypes.bool,
/** Indicates the input field has scale */
2020-07-13 11:15:44 +00:00
heightScale: PropTypes.bool,
/** Max value length */
maxLength: PropTypes.number,
/** Used as HTML `name` property */
name: PropTypes.string,
/** Sets a callback function that allows handling the component's changing events */
onChange: PropTypes.func,
/** Placeholder for Textarea */
placeholder: PropTypes.string,
/** Accepts css style */
2019-12-17 10:49:53 +00:00
style: PropTypes.oneOfType([PropTypes.object, PropTypes.array]),
/** Used as HTML `tabindex` property */
tabIndex: PropTypes.number,
/** Textarea value */
value: PropTypes.string,
/** Font-size value */
fontSize: PropTypes.number,
/** Text-area height value */
heightTextArea: PropTypes.number,
/** Specifies the text color */
color: PropTypes.string,
/** Default input property */
2022-05-20 11:07:46 +00:00
autoFocus: PropTypes.bool,
/** Allows selecting the textarea */
areaSelect: PropTypes.bool,
2023-01-20 15:46:39 +00:00
/** Prettifies Json and adds lines numeration */
isJSONField: PropTypes.bool,
/** Indicates the text of toast/informational alarm */
copyInfoText: PropTypes.string,
/** Shows copy icon */
enableCopy: PropTypes.bool,
/** Inserts numeration */
hasNumeration: PropTypes.bool,
/** Calculating height of content depending on number of lines */
isFullHeight: PropTypes.bool,
};
Textarea.defaultProps = {
isDisabled: false,
isReadOnly: false,
2020-07-08 13:57:34 +00:00
hasError: false,
2020-07-13 11:15:44 +00:00
heightScale: false,
placeholder: " ",
tabIndex: -1,
value: "",
fontSize: 13,
2022-05-20 11:07:46 +00:00
isAutoFocussed: false,
areaSelect: false,
2023-01-20 15:46:39 +00:00
isJSONField: false,
copyInfoText: "Content was copied successfully!",
enableCopy: false,
hasNumeration: false,
isFullHeight: false,
};
export default Textarea;