-
Notifications
You must be signed in to change notification settings - Fork 42
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
296 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
--- | ||
group: Data Entry | ||
title: Textarea | ||
--- | ||
|
||
Multi-line plain text edit control. | ||
|
||
## When To Use | ||
|
||
It is desirable to allow users to enter large amounts of free-form text, such as comments on comments or feedback forms. | ||
|
||
## API | ||
|
||
### DTextareaProps | ||
|
||
Extend `React.InputHTMLAttributes<HTMLTextAreaElement>`, [DFormControl](/components/Form#DFormControl). | ||
|
||
<!-- prettier-ignore-start --> | ||
| Property | Description | Type | Default | | ||
| --- | --- | --- | --- | | ||
| dValue | Bind value | [string, Updater\<string\>?] | - | | ||
| dRows | Set the number of rows, `'auto'` means automatic change, and can also pass the maximum and minimum values | 'auto' \| { minRows?: number; maxRows?: number } | - | | ||
| dResizable | Whether the size can be changed | boolean | true | | ||
| dShowCount | Display the number of input words | boolean | `((num: number) => React.ReactNode)` | false | | ||
| onValueChange | Callback for binding value change | `(value: string) => void` | - | | ||
<!-- prettier-ignore-end --> | ||
|
||
### DTextareaRef | ||
|
||
```tsx | ||
export type DTextareaRef = HTMLTextAreaElement; | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
--- | ||
title: 文本域 | ||
--- | ||
|
||
多行纯文本编辑控件。 | ||
|
||
## 何时使用 | ||
|
||
希望允许用户输入大量自由格式的文本,例如对评论或反馈表的评论。 | ||
|
||
## API | ||
|
||
### DTextareaProps | ||
|
||
继承 `React.InputHTMLAttributes<HTMLTextAreaElement>`,[DFormControl](/components/Form#DFormControl)。 | ||
|
||
<!-- prettier-ignore-start --> | ||
| 参数 | 说明 | 类型 | 默认值 | | ||
| --- | --- | --- | --- | | ||
| dValue | 绑定值 | [string, Updater\<string\>?] | - | | ||
| dRows | 设置行数,`'auto'` 代表自动变化,也可传递最大最小值 | 'auto' \| { minRows?: number; maxRows?: number } | - | | ||
| dResizable | 尺寸是否可变化 | boolean | true | | ||
| dShowCount | 显示输入字数 | boolean | `((num: number) => React.ReactNode)` | false | | ||
| onValueChange | 绑定值改变的回调 | `(value: string) => void` | - | | ||
<!-- prettier-ignore-end --> | ||
|
||
### DTextareaRef | ||
|
||
```tsx | ||
export type DTextareaRef = HTMLTextAreaElement; | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
import type { Updater } from '../../hooks/immer'; | ||
import type { DFormControl } from '../form'; | ||
|
||
import { isFunction, isNumber, isUndefined } from 'lodash'; | ||
import React, { useEffect, useImperativeHandle, useMemo } from 'react'; | ||
import { useCallback } from 'react'; | ||
|
||
import { usePrefixConfig, useComponentConfig, useTwoWayBinding, useImmer, useRefCallback } from '../../hooks'; | ||
import { getClassName, mergeStyle } from '../../utils'; | ||
|
||
export type DTextareaRef = HTMLTextAreaElement; | ||
|
||
export interface DTextareaProps extends React.InputHTMLAttributes<HTMLTextAreaElement>, DFormControl { | ||
dValue?: [string, Updater<string>?]; | ||
dRows?: 'auto' | { minRows?: number; maxRows?: number }; | ||
dResizable?: boolean; | ||
dShowCount?: boolean | ((num: number) => React.ReactNode); | ||
onValueChange?: (value: string) => void; | ||
} | ||
|
||
export const DTextarea = React.forwardRef<DTextareaRef, DTextareaProps>((props, ref) => { | ||
const { | ||
dFormControlName, | ||
dValue, | ||
dRows, | ||
dResizable = true, | ||
dShowCount = false, | ||
onValueChange, | ||
className, | ||
style, | ||
maxLength, | ||
disabled, | ||
onClick, | ||
onFocus, | ||
onBlur, | ||
onChange, | ||
...restProps | ||
} = useComponentConfig(DTextarea.name, props); | ||
|
||
//#region Context | ||
const dPrefix = usePrefixConfig(); | ||
//#endregion | ||
|
||
//#region Ref | ||
const [textareaEl, textareaRef] = useRefCallback<HTMLTextAreaElement>(); | ||
//#endregion | ||
|
||
const [bindValue, changeBindValue] = useTwoWayBinding('', dValue, onValueChange, { | ||
name: dFormControlName, | ||
}); | ||
|
||
const [rowNum, setRowNum] = useImmer(1); | ||
|
||
const resizable = dResizable && isUndefined(dRows); | ||
const heightStyle = useMemo(() => { | ||
let overflow: 'hidden' | undefined; | ||
let height: number | undefined; | ||
let minHeight: number | undefined; | ||
let maxHeight: number | undefined; | ||
|
||
if (!isUndefined(dRows)) { | ||
height = rowNum * 24 + 8; | ||
if (dRows === 'auto') { | ||
overflow = 'hidden'; | ||
} else { | ||
if (isNumber(dRows.minRows)) { | ||
minHeight = dRows.minRows * 24 + 8; | ||
} | ||
if (isNumber(dRows.maxRows)) { | ||
maxHeight = dRows.maxRows * 24 + 8; | ||
if (maxHeight > height) { | ||
overflow = 'hidden'; | ||
} | ||
} | ||
} | ||
} | ||
return { overflow, height, minHeight, maxHeight }; | ||
}, [dRows, rowNum]); | ||
|
||
const handleChange = useCallback<React.ChangeEventHandler<HTMLTextAreaElement>>( | ||
(e) => { | ||
onChange?.(e); | ||
changeBindValue(e.currentTarget.value); | ||
|
||
const el = e.currentTarget; | ||
const overflow = el.style.overflow; | ||
const height = el.style.height; | ||
el.style.overflow = 'hidden'; | ||
el.style.height = '32px'; | ||
setRowNum((el.scrollHeight - 6) / 24); | ||
el.style.overflow = overflow; | ||
el.style.height = height; | ||
}, | ||
[changeBindValue, onChange, setRowNum] | ||
); | ||
|
||
useEffect(() => { | ||
if (textareaEl) { | ||
setRowNum((textareaEl.scrollHeight - 6) / 24); | ||
} | ||
}, [setRowNum, textareaEl]); | ||
|
||
useImperativeHandle<HTMLTextAreaElement | null, HTMLTextAreaElement | null>(ref, () => textareaEl, [textareaEl]); | ||
|
||
return ( | ||
<> | ||
<textarea | ||
{...restProps} | ||
ref={textareaRef} | ||
className={getClassName(className, `${dPrefix}textarea`)} | ||
style={mergeStyle(style, { | ||
resize: resizable ? undefined : 'none', | ||
...heightStyle, | ||
})} | ||
maxLength={maxLength} | ||
value={bindValue} | ||
disabled={disabled} | ||
aria-disabled={disabled} | ||
onChange={handleChange} | ||
/> | ||
<div className={`${dPrefix}textarea__count`} style={{ display: dShowCount === false ? 'none' : undefined }}> | ||
{isFunction(dShowCount) | ||
? dShowCount(bindValue.length) | ||
: isUndefined(maxLength) | ||
? bindValue.length | ||
: `${bindValue.length} / ${maxLength}`} | ||
</div> | ||
</> | ||
); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
--- | ||
title: | ||
en-US: Basic | ||
zh-Hant: 基本 | ||
--- | ||
|
||
# en-US | ||
|
||
The simplest usage. | ||
|
||
# zh-Hant | ||
|
||
最简单的用法。 | ||
|
||
```tsx | ||
import { DTextarea } from '@react-devui/ui'; | ||
|
||
export default function Demo() { | ||
return <DTextarea placeholder="Basic" rows="5" />; | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
--- | ||
title: | ||
en-US: Set the number of rows | ||
zh-Hant: 设置行数 | ||
--- | ||
|
||
# en-US | ||
|
||
You can set the number of rows in the textarea to automatically change or pass the maximum and minimum values. | ||
|
||
# zh-Hant | ||
|
||
可以设置文本域行数自动变化或者传递最大最小值。 | ||
|
||
```tsx | ||
import { DTextarea } from '@react-devui/ui'; | ||
|
||
export default function Demo() { | ||
return ( | ||
<> | ||
<DTextarea placeholder="Auto rows" dRows="auto" /> | ||
<br /> | ||
<DTextarea placeholder="minRows: 3, maxRows: 5" dRows={{ minRows: 3, maxRows: 5 }} /> | ||
</> | ||
); | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
--- | ||
title: | ||
en-US: The number of input words | ||
zh-Hant: 输入字数 | ||
--- | ||
|
||
# en-US | ||
|
||
Display the number of input words. | ||
|
||
# zh-Hant | ||
|
||
显示输入字数。 | ||
|
||
```tsx | ||
import { DTextarea } from '@react-devui/ui'; | ||
import { useImmer } from '@react-devui/ui/hooks'; | ||
|
||
export default function Demo() { | ||
const [value, setValue] = useImmer('Show count'); | ||
|
||
return ( | ||
<> | ||
<DTextarea placeholder="Show count" dValue={[value, setValue]} dShowCount /> | ||
<br /> | ||
<DTextarea placeholder="Show count" maxLength={100} dValue={[value, setValue]} dShowCount /> | ||
</> | ||
); | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
--- | ||
title: | ||
en-US: Disable | ||
zh-Hant: 禁用 | ||
--- | ||
|
||
# en-US | ||
|
||
Disable the textarea. | ||
|
||
# zh-Hant | ||
|
||
禁用文本域。 | ||
|
||
```tsx | ||
import { DTextarea } from '@react-devui/ui'; | ||
|
||
export default function Demo() { | ||
return <DTextarea placeholder="Show count" maxLength={100} disabled dShowCount />; | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export * from './Textarea'; |