Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(textarea): allowinputovermax支持超出字数限制可以输入 #838

Merged
merged 8 commits into from
Jun 7, 2022
2 changes: 0 additions & 2 deletions src/menu/__tests__/__snapshots__/menu.test.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -831,7 +831,6 @@ exports[`double.jsx 1`] = `
>
<div
class="t-tabs__bar t-is-top"
style="transform: translateX(0px);"
/>
<div
class="t-tabs__bar t-is-top"
Expand Down Expand Up @@ -972,7 +971,6 @@ exports[`double.jsx 1`] = `
>
<div
class="t-tabs__bar t-is-top"
style="transform: translateX(0px);"
/>
<div
class="t-tabs__bar t-is-top"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ exports[`close-all.jsx 1`] = `
exports[`content.jsx 1`] = `
<DocumentFragment>
<div
class="tdesign-demo-block-columns"
class="tdesign-demo-block-column"
>
<div
class="t-notification t-is-info"
Expand Down
2 changes: 1 addition & 1 deletion src/notification/_example/content.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Notification } from 'tdesign-react';

export default function NotificationExample() {
return (
<div className="tdesign-demo-block-columns">
<div className="tdesign-demo-block-column">
<Notification title="自定义内容(字符串)" content="这是一条消息通知" />
<Notification title="自定义内容" content={<div>这是一条消息通知</div>} />
</div>
Expand Down
12 changes: 6 additions & 6 deletions src/tabs/TabBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,14 @@ const TabBar: React.FC<TabBarProps> = (props) => {
const [barStyle, setBarStyle] = useState<CSSProperties>({});
const tabsClassPrefix = `${classPrefix}-tabs`;

const computeStyle = ({ tabPosition, activeId }) => {
const computeStyle = () => {
const isHorizontal = ['bottom', 'top'].includes(tabPosition);
const transformPosition = isHorizontal ? 'translateX' : 'translateY';
const itemProp = isHorizontal ? 'width' : 'height';
const barBorderProp = isHorizontal ? 'width' : 'height';

let offset = 0;

if (containerRef.current) {
const itemsRef = containerRef.current.querySelectorAll('.t-tabs__nav-item');

Expand Down Expand Up @@ -48,12 +49,11 @@ const TabBar: React.FC<TabBarProps> = (props) => {
};

useEffect(() => {
computeStyle({
tabPosition,
activeId,
});
if (containerRef.current) {
setTimeout(() => computeStyle());
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [tabPosition, activeId]);
}, [tabPosition, activeId, containerRef.current]);

return (
<div
Expand Down
8 changes: 0 additions & 8 deletions src/tabs/__tests__/__snapshots__/tabs.test.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,6 @@ exports[`ban.jsx 1`] = `
>
<div
class="t-tabs__bar t-is-top"
style="transform: translateX(0px);"
/>
<div
class="t-tabs__bar t-is-top"
Expand Down Expand Up @@ -175,7 +174,6 @@ exports[`base.jsx 1`] = `
>
<div
class="t-tabs__bar t-is-top"
style="transform: translateX(0px);"
/>
<div
class="t-tabs__bar t-is-top"
Expand Down Expand Up @@ -320,7 +318,6 @@ exports[`combination.jsx 1`] = `
>
<div
class="t-tabs__bar t-is-top"
style="transform: translateX(0px);"
/>
<div
class="t-tabs__bar t-is-top"
Expand Down Expand Up @@ -976,7 +973,6 @@ exports[`icon.jsx 1`] = `
>
<div
class="t-tabs__bar t-is-top"
style="transform: translateX(0px);"
/>
<div
class="t-tabs__bar t-is-top"
Expand Down Expand Up @@ -1281,7 +1277,6 @@ exports[`position.jsx 1`] = `
>
<div
class="t-tabs__bar t-is-top"
style="transform: translateX(0px);"
/>
<div
class="t-tabs__bar t-is-top"
Expand Down Expand Up @@ -1382,7 +1377,6 @@ exports[`size.jsx 1`] = `
>
<div
class="t-tabs__bar t-is-top"
style="transform: translateX(0px);"
/>
<div
class="t-tabs__bar t-is-top"
Expand Down Expand Up @@ -1460,7 +1454,6 @@ exports[`size.jsx 1`] = `
>
<div
class="t-tabs__bar t-is-top"
style="transform: translateX(0px);"
/>
<div
class="t-tabs__bar t-is-top"
Expand Down Expand Up @@ -1547,7 +1540,6 @@ exports[`theme.jsx 1`] = `
>
<div
class="t-tabs__bar t-is-top"
style="transform: translateX(0px);"
/>
<div
class="t-tabs__bar t-is-top"
Expand Down
32 changes: 22 additions & 10 deletions src/textarea/Textarea.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,21 +30,23 @@ const Textarea = forwardRef((props: TextareaProps, ref: TextareaRefInterface) =>
autosize,
status,
tips,
allowInputOverMax,
...otherProps
} = props;

const [value = '', setValue] = useControlled(props, 'value', props.onChange);
const [isFocused, setIsFocused] = useState(false);
const [isOvermax, setIsOvermax] = useState(false);
const [textareaStyle, setTextareaStyle] = useState({});
const hasMaxcharacter = typeof maxcharacter !== 'undefined';
const textareaRef: React.RefObject<HTMLTextAreaElement> = useRef();
const wrapperRef: React.RefObject<HTMLDivElement> = useRef();
const currentLength = useMemo(() => (value ? String(value).length : 0), [value]);
const characterLength = useMemo(() => {
const characterInfo = getCharacterLength(String(value), maxcharacter);
const characterInfo = getCharacterLength(String(value), allowInputOverMax ? Infinity : maxcharacter);
if (typeof characterInfo === 'object') return characterInfo.length;
return characterInfo;
}, [value, maxcharacter]);
}, [value, allowInputOverMax, maxcharacter]);

const { classPrefix } = useConfig();

Expand Down Expand Up @@ -84,13 +86,20 @@ const Textarea = forwardRef((props: TextareaProps, ref: TextareaRefInterface) =>
function inputValueChangeHandle(e: React.FormEvent<HTMLTextAreaElement>) {
const { target } = e;
let val = (target as HTMLInputElement).value;
if (maxcharacter && maxcharacter >= 0) {
if (!allowInputOverMax && maxcharacter && maxcharacter >= 0) {
const stringInfo = getCharacterLength(val, maxcharacter);
val = typeof stringInfo === 'object' && stringInfo.characters;
}
setValue(val, { e });
}

const renderLimitText = (current: number, max: number) => (
<span className={`${classPrefix}-textarea__limit`}>
{isOvermax ? <span className={`${classPrefix}-textarea__tips--warning`}> {current}</span> : `${current}`}
{`/${max}`}
</span>
);

useEffect(() => {
// 当未设置 autosize 时,需要将 textarea 的 height 设置为 auto,以支持原生的 textarea rows 属性
if (autosize === false) {
Expand All @@ -102,6 +111,13 @@ const Textarea = forwardRef((props: TextareaProps, ref: TextareaRefInterface) =>
adjustTextareaHeight();
}, [adjustTextareaHeight, value]);

useEffect(() => {
if (allowInputOverMax) {
setIsOvermax(!!(maxlength && currentLength > maxlength) || !!(maxcharacter && characterLength > maxcharacter));
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [characterLength]);

useImperativeHandle(ref as TextareaRefInterface, () => ({
currentElement: wrapperRef.current,
textareaElement: textareaRef.current,
Expand All @@ -118,19 +134,15 @@ const Textarea = forwardRef((props: TextareaProps, ref: TextareaRefInterface) =>
readOnly={readonly}
autoFocus={autofocus}
disabled={disabled}
maxLength={maxlength}
maxLength={allowInputOverMax ? Infinity : maxlength}
onChange={inputValueChangeHandle}
onKeyDown={(e) => onKeydown(e.currentTarget.value, { e })}
onKeyPress={(e) => onKeypress(e.currentTarget.value, { e })}
onKeyUp={(e) => onKeyup(e.currentTarget.value, { e })}
ref={textareaRef}
/>
{hasMaxcharacter ? (
<span className={`${classPrefix}-textarea__limit`}>{`${characterLength}/${maxcharacter}`}</span>
) : null}
{!hasMaxcharacter && maxlength ? (
<span className={`${classPrefix}-textarea__limit`}>{`${currentLength}/${maxlength}`}</span>
) : null}
{hasMaxcharacter && renderLimitText(characterLength, maxcharacter)}
{!hasMaxcharacter && maxlength && renderLimitText(currentLength, maxlength)}
{tips ? (
<div
className={classNames(`${classPrefix}-textarea__tips`, {
Expand Down
Loading