@delightui/components 0.1.105 → 0.1.107
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/README.md +104 -1
- package/dist/cjs/components/molecules/Modal/DemoModal.d.ts +8 -0
- package/dist/cjs/components/molecules/Modal/ModalContext/ModalContext.d.ts +41 -0
- package/dist/cjs/components/molecules/Modal/ModalContext/ModalContext.types.d.ts +87 -0
- package/dist/cjs/components/molecules/Modal/ModalContext/index.d.ts +3 -0
- package/dist/cjs/components/molecules/Modal/ModalContext/useModal.d.ts +34 -0
- package/dist/cjs/components/molecules/Modal/index.d.ts +2 -0
- package/dist/cjs/components/molecules/index.d.ts +2 -0
- package/dist/cjs/library.css +19 -6
- package/dist/cjs/library.js +3 -3
- package/dist/cjs/library.js.map +1 -1
- package/dist/esm/components/molecules/Modal/DemoModal.d.ts +8 -0
- package/dist/esm/components/molecules/Modal/ModalContext/ModalContext.d.ts +41 -0
- package/dist/esm/components/molecules/Modal/ModalContext/ModalContext.types.d.ts +87 -0
- package/dist/esm/components/molecules/Modal/ModalContext/index.d.ts +3 -0
- package/dist/esm/components/molecules/Modal/ModalContext/useModal.d.ts +34 -0
- package/dist/esm/components/molecules/Modal/index.d.ts +2 -0
- package/dist/esm/components/molecules/index.d.ts +2 -0
- package/dist/esm/library.css +19 -6
- package/dist/esm/library.js +3 -3
- package/dist/esm/library.js.map +1 -1
- package/dist/index.d.ts +108 -2
- package/docs/README.md +264 -0
- package/docs/components/atoms/ActionImage.md +119 -0
- package/docs/components/atoms/Button.md +197 -0
- package/docs/components/atoms/Checkbox.md +299 -0
- package/docs/components/atoms/CheckboxItem.md +314 -0
- package/docs/components/atoms/Chip.md +380 -0
- package/docs/components/atoms/CustomToggle.md +270 -0
- package/docs/components/atoms/Icon.md +365 -0
- package/docs/components/atoms/IconButton.md +407 -0
- package/docs/components/atoms/Image.md +448 -0
- package/docs/components/atoms/Input.md +430 -0
- package/docs/components/atoms/ListItem.md +502 -0
- package/docs/components/atoms/Password.md +472 -0
- package/docs/components/atoms/RadioButton.md +614 -0
- package/docs/components/atoms/RadioButtonItem.md +588 -0
- package/docs/components/atoms/ResponsiveComponent.md +612 -0
- package/docs/components/atoms/SelectListItem.md +609 -0
- package/docs/components/atoms/Slider.md +605 -0
- package/docs/components/atoms/Spinner.md +605 -0
- package/docs/components/atoms/Text.md +463 -0
- package/docs/components/atoms/TextArea.md +670 -0
- package/docs/components/atoms/ToastNotification.md +668 -0
- package/docs/components/atoms/Toggle.md +737 -0
- package/docs/components/atoms/ToggleButton.md +751 -0
- package/docs/components/atoms/Tooltip.md +391 -0
- package/docs/components/molecules/Accordion.md +440 -0
- package/docs/components/molecules/AccordionGroup.md +547 -0
- package/docs/components/molecules/ActionCard.md +546 -0
- package/docs/components/molecules/Breadcrumb.md +403 -0
- package/docs/components/molecules/Breadcrumbs.md +485 -0
- package/docs/components/molecules/ButtonGroup.md +383 -0
- package/docs/components/molecules/Card.md +298 -0
- package/docs/components/molecules/ChipInput.md +646 -0
- package/docs/components/molecules/ContextMenu.md +768 -0
- package/docs/components/molecules/CustomTimeSelector.md +116 -0
- package/docs/components/molecules/DatePicker.md +516 -0
- package/docs/components/molecules/DateTimeSelector.md +166 -0
- package/docs/components/molecules/FormField.md +312 -0
- package/docs/components/molecules/Grid.md +577 -0
- package/docs/components/molecules/GridItem.md +834 -0
- package/docs/components/molecules/GridList.md +244 -0
- package/docs/components/molecules/List.md +485 -0
- package/docs/components/molecules/Modal.md +470 -0
- package/docs/components/molecules/ModalFooter.md +702 -0
- package/docs/components/molecules/ModalHeader.md +756 -0
- package/docs/components/molecules/ModalProvider.md +205 -0
- package/docs/components/molecules/Nav.md +530 -0
- package/docs/components/molecules/NavItem.md +572 -0
- package/docs/components/molecules/NavLink.md +499 -0
- package/docs/components/molecules/Option.md +521 -0
- package/docs/components/molecules/Pagination.md +592 -0
- package/docs/components/molecules/PaginationNumberField.md +722 -0
- package/docs/components/molecules/Popover.md +516 -0
- package/docs/components/molecules/ProgressBar.md +624 -0
- package/docs/components/molecules/RadioGroup.md +831 -0
- package/docs/components/molecules/RepeaterList.md +185 -0
- package/docs/components/molecules/Select.md +402 -0
- package/docs/components/molecules/SortableTrigger.md +82 -0
- package/docs/components/molecules/useModal.md +379 -0
- package/docs/components/organisms/Dropzone.md +346 -0
- package/docs/components/organisms/DropzoneClear.md +135 -0
- package/docs/components/organisms/DropzoneContent.md +216 -0
- package/docs/components/organisms/DropzoneFilename.md +191 -0
- package/docs/components/organisms/DropzoneSupportedFormats.md +184 -0
- package/docs/components/organisms/DropzoneTrigger.md +209 -0
- package/docs/components/organisms/Form.md +533 -0
- package/docs/components/organisms/SlideOutPanel.md +662 -0
- package/docs/components/organisms/TabContent.md +902 -0
- package/docs/components/organisms/TabItem.md +1091 -0
- package/docs/components/organisms/Table.md +611 -0
- package/docs/components/organisms/TableBody.md +679 -0
- package/docs/components/organisms/TableCell.md +482 -0
- package/docs/components/organisms/TableHeader.md +513 -0
- package/docs/components/organisms/TableHeaderCell.md +661 -0
- package/docs/components/organisms/TableRow.md +715 -0
- package/docs/components/organisms/Tabs.md +1330 -0
- package/docs/components/utils/ConditionalView.md +568 -0
- package/docs/components/utils/RenderStateView.md +726 -0
- package/docs/components/utils/WrapTextNodes.md +614 -0
- package/package.json +3 -2
|
@@ -0,0 +1,670 @@
|
|
|
1
|
+
# TextArea
|
|
2
|
+
|
|
3
|
+
A multi-line text input component that extends the standard HTML textarea with enhanced form integration capabilities. It provides a consistent interface for collecting longer text inputs from users, with full support for controlled and uncontrolled usage patterns, validation, and accessibility features.
|
|
4
|
+
|
|
5
|
+
## Aliases
|
|
6
|
+
|
|
7
|
+
- TextArea
|
|
8
|
+
- MultilineInput
|
|
9
|
+
- TextBox
|
|
10
|
+
|
|
11
|
+
## Props Breakdown
|
|
12
|
+
|
|
13
|
+
**Extends:** `TextareaHTMLAttributes<HTMLTextAreaElement>` (excluding `value`) + `ControlledFormComponentProps<string>`
|
|
14
|
+
|
|
15
|
+
| Prop | Type | Default | Required | Description |
|
|
16
|
+
|------|------|---------|----------|-------------|
|
|
17
|
+
| `initialValue` | `string` | `undefined` | No | The initial value for the field |
|
|
18
|
+
| `checked` | `boolean` | `undefined` | No | The initial value for the field |
|
|
19
|
+
| `value` | `string` | `undefined` | No | The current value of the form field |
|
|
20
|
+
| `onValueChange` | `(value: string) => void` | `undefined` | No | Callback function that is called when the field value changes |
|
|
21
|
+
| `disabled` | `boolean` | `false` | No | Whether the form field is disabled and cannot be interacted with |
|
|
22
|
+
| `required` | `boolean` | `false` | No | Whether the form field must have a value |
|
|
23
|
+
| `invalid` | `boolean` | `false` | No | Whether the form field's current value is invalid |
|
|
24
|
+
| `id` | `string` | `undefined` | No | Id for the form field |
|
|
25
|
+
| `placeholder` | `string` | `undefined` | No | Placeholder text for the textarea |
|
|
26
|
+
| `rows` | `number` | `undefined` | No | Number of visible text lines for the control |
|
|
27
|
+
| `cols` | `number` | `undefined` | No | Visible width of the text control |
|
|
28
|
+
| `maxLength` | `number` | `undefined` | No | Maximum length of the input value |
|
|
29
|
+
| `minLength` | `number` | `undefined` | No | Minimum length of the input value |
|
|
30
|
+
| `readOnly` | `boolean` | `false` | No | Whether the textarea is read-only |
|
|
31
|
+
| `autoFocus` | `boolean` | `false` | No | Whether the textarea should be focused on mount |
|
|
32
|
+
| `wrap` | `string` | `undefined` | No | How the text in the textarea is to be wrapped when submitted |
|
|
33
|
+
| `resize` | `string` | `undefined` | No | CSS resize property |
|
|
34
|
+
|
|
35
|
+
Plus all standard HTML textarea attributes (name, form, autoComplete, spellCheck, etc.) except `value`.
|
|
36
|
+
|
|
37
|
+
## Examples
|
|
38
|
+
|
|
39
|
+
### Basic TextArea
|
|
40
|
+
|
|
41
|
+
```tsx
|
|
42
|
+
import { TextArea } from '@delightui/components';
|
|
43
|
+
|
|
44
|
+
function BasicTextAreaExample() {
|
|
45
|
+
const [message, setMessage] = useState('');
|
|
46
|
+
|
|
47
|
+
return (
|
|
48
|
+
<div>
|
|
49
|
+
<p>Character count: {message.length}</p>
|
|
50
|
+
<TextArea
|
|
51
|
+
value={message}
|
|
52
|
+
onValueChange={setMessage}
|
|
53
|
+
placeholder="Enter your message here..."
|
|
54
|
+
rows={4}
|
|
55
|
+
/>
|
|
56
|
+
</div>
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Form Integration
|
|
62
|
+
|
|
63
|
+
```tsx
|
|
64
|
+
import { Form, FormField, TextArea, Button } from '@delightui/components';
|
|
65
|
+
|
|
66
|
+
function TextAreaFormExample() {
|
|
67
|
+
const handleSubmit = (data: any) => {
|
|
68
|
+
console.log('Form submitted:', data);
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
return (
|
|
72
|
+
<Form onSubmit={handleSubmit}>
|
|
73
|
+
<FormField
|
|
74
|
+
name="description"
|
|
75
|
+
label="Description"
|
|
76
|
+
required
|
|
77
|
+
>
|
|
78
|
+
<TextArea
|
|
79
|
+
placeholder="Please provide a detailed description..."
|
|
80
|
+
rows={6}
|
|
81
|
+
maxLength={500}
|
|
82
|
+
/>
|
|
83
|
+
</FormField>
|
|
84
|
+
|
|
85
|
+
<FormField
|
|
86
|
+
name="comments"
|
|
87
|
+
label="Additional Comments"
|
|
88
|
+
>
|
|
89
|
+
<TextArea
|
|
90
|
+
placeholder="Any additional comments or feedback..."
|
|
91
|
+
rows={4}
|
|
92
|
+
/>
|
|
93
|
+
</FormField>
|
|
94
|
+
|
|
95
|
+
<Button type="submit">
|
|
96
|
+
Submit
|
|
97
|
+
</Button>
|
|
98
|
+
</Form>
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### TextArea with Character Counter
|
|
104
|
+
|
|
105
|
+
```tsx
|
|
106
|
+
import { TextArea, Text } from '@delightui/components';
|
|
107
|
+
|
|
108
|
+
function TextAreaWithCounterExample() {
|
|
109
|
+
const [content, setContent] = useState('');
|
|
110
|
+
const maxLength = 200;
|
|
111
|
+
|
|
112
|
+
const remainingChars = maxLength - content.length;
|
|
113
|
+
const isNearLimit = remainingChars <= 20;
|
|
114
|
+
const isOverLimit = remainingChars < 0;
|
|
115
|
+
|
|
116
|
+
return (
|
|
117
|
+
<div>
|
|
118
|
+
<TextArea
|
|
119
|
+
value={content}
|
|
120
|
+
onValueChange={setContent}
|
|
121
|
+
placeholder="Write your review..."
|
|
122
|
+
rows={6}
|
|
123
|
+
maxLength={maxLength}
|
|
124
|
+
invalid={isOverLimit}
|
|
125
|
+
/>
|
|
126
|
+
|
|
127
|
+
<div style={{
|
|
128
|
+
display: 'flex',
|
|
129
|
+
justifyContent: 'space-between',
|
|
130
|
+
alignItems: 'center',
|
|
131
|
+
marginTop: '8px'
|
|
132
|
+
}}>
|
|
133
|
+
<Text
|
|
134
|
+
size="small"
|
|
135
|
+
color={isOverLimit ? 'error' : isNearLimit ? 'warning' : 'secondary'}
|
|
136
|
+
>
|
|
137
|
+
{content.length} / {maxLength} characters
|
|
138
|
+
</Text>
|
|
139
|
+
|
|
140
|
+
{isOverLimit && (
|
|
141
|
+
<Text size="small" color="error">
|
|
142
|
+
{Math.abs(remainingChars)} characters over limit
|
|
143
|
+
</Text>
|
|
144
|
+
)}
|
|
145
|
+
</div>
|
|
146
|
+
</div>
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### Resizable TextArea
|
|
152
|
+
|
|
153
|
+
```tsx
|
|
154
|
+
import { TextArea } from '@delightui/components';
|
|
155
|
+
|
|
156
|
+
function ResizableTextAreaExample() {
|
|
157
|
+
const [content, setContent] = useState('');
|
|
158
|
+
|
|
159
|
+
return (
|
|
160
|
+
<div style={{ display: 'flex', flexDirection: 'column', gap: '20px' }}>
|
|
161
|
+
<div>
|
|
162
|
+
<Text weight="bold" style={{ marginBottom: '8px' }}>
|
|
163
|
+
Resizable (Default)
|
|
164
|
+
</Text>
|
|
165
|
+
<TextArea
|
|
166
|
+
value={content}
|
|
167
|
+
onValueChange={setContent}
|
|
168
|
+
placeholder="This textarea can be resized..."
|
|
169
|
+
rows={4}
|
|
170
|
+
/>
|
|
171
|
+
</div>
|
|
172
|
+
|
|
173
|
+
<div>
|
|
174
|
+
<Text weight="bold" style={{ marginBottom: '8px' }}>
|
|
175
|
+
Vertical Resize Only
|
|
176
|
+
</Text>
|
|
177
|
+
<TextArea
|
|
178
|
+
value={content}
|
|
179
|
+
onValueChange={setContent}
|
|
180
|
+
placeholder="This textarea can only be resized vertically..."
|
|
181
|
+
rows={4}
|
|
182
|
+
style={{ resize: 'vertical' }}
|
|
183
|
+
/>
|
|
184
|
+
</div>
|
|
185
|
+
|
|
186
|
+
<div>
|
|
187
|
+
<Text weight="bold" style={{ marginBottom: '8px' }}>
|
|
188
|
+
No Resize
|
|
189
|
+
</Text>
|
|
190
|
+
<TextArea
|
|
191
|
+
value={content}
|
|
192
|
+
onValueChange={setContent}
|
|
193
|
+
placeholder="This textarea cannot be resized..."
|
|
194
|
+
rows={4}
|
|
195
|
+
style={{ resize: 'none' }}
|
|
196
|
+
/>
|
|
197
|
+
</div>
|
|
198
|
+
</div>
|
|
199
|
+
);
|
|
200
|
+
}
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
### Auto-growing TextArea
|
|
204
|
+
|
|
205
|
+
```tsx
|
|
206
|
+
import { TextArea } from '@delightui/components';
|
|
207
|
+
|
|
208
|
+
function AutoGrowingTextAreaExample() {
|
|
209
|
+
const [content, setContent] = useState('');
|
|
210
|
+
|
|
211
|
+
// Calculate rows based on content
|
|
212
|
+
const calculateRows = (text: string) => {
|
|
213
|
+
const lines = text.split('\n').length;
|
|
214
|
+
const minRows = 3;
|
|
215
|
+
const maxRows = 10;
|
|
216
|
+
return Math.min(Math.max(lines, minRows), maxRows);
|
|
217
|
+
};
|
|
218
|
+
|
|
219
|
+
return (
|
|
220
|
+
<div>
|
|
221
|
+
<Text weight="bold" style={{ marginBottom: '8px' }}>
|
|
222
|
+
Auto-growing TextArea
|
|
223
|
+
</Text>
|
|
224
|
+
<Text size="small" color="secondary" style={{ marginBottom: '12px' }}>
|
|
225
|
+
This textarea grows as you type (min 3 rows, max 10 rows)
|
|
226
|
+
</Text>
|
|
227
|
+
|
|
228
|
+
<TextArea
|
|
229
|
+
value={content}
|
|
230
|
+
onValueChange={setContent}
|
|
231
|
+
placeholder="Start typing and watch the textarea grow..."
|
|
232
|
+
rows={calculateRows(content)}
|
|
233
|
+
style={{ resize: 'none' }}
|
|
234
|
+
/>
|
|
235
|
+
</div>
|
|
236
|
+
);
|
|
237
|
+
}
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
### Comment System Example
|
|
241
|
+
|
|
242
|
+
```tsx
|
|
243
|
+
import { TextArea, Button, Text } from '@delightui/components';
|
|
244
|
+
|
|
245
|
+
function CommentSystemExample() {
|
|
246
|
+
const [comment, setComment] = useState('');
|
|
247
|
+
const [comments, setComments] = useState([
|
|
248
|
+
{ id: 1, author: 'John Doe', content: 'Great article! Very informative.', time: '2 hours ago' },
|
|
249
|
+
{ id: 2, author: 'Jane Smith', content: 'I learned a lot from this. Thank you for sharing.', time: '1 hour ago' }
|
|
250
|
+
]);
|
|
251
|
+
|
|
252
|
+
const handleSubmit = () => {
|
|
253
|
+
if (comment.trim()) {
|
|
254
|
+
const newComment = {
|
|
255
|
+
id: comments.length + 1,
|
|
256
|
+
author: 'You',
|
|
257
|
+
content: comment,
|
|
258
|
+
time: 'Just now'
|
|
259
|
+
};
|
|
260
|
+
setComments([...comments, newComment]);
|
|
261
|
+
setComment('');
|
|
262
|
+
}
|
|
263
|
+
};
|
|
264
|
+
|
|
265
|
+
return (
|
|
266
|
+
<div style={{ maxWidth: '600px' }}>
|
|
267
|
+
<Text weight="bold" style={{ marginBottom: '16px' }}>
|
|
268
|
+
Comments ({comments.length})
|
|
269
|
+
</Text>
|
|
270
|
+
|
|
271
|
+
{/* Existing Comments */}
|
|
272
|
+
<div style={{ marginBottom: '24px' }}>
|
|
273
|
+
{comments.map((c) => (
|
|
274
|
+
<div key={c.id} style={{
|
|
275
|
+
border: '1px solid #eee',
|
|
276
|
+
borderRadius: '8px',
|
|
277
|
+
padding: '16px',
|
|
278
|
+
marginBottom: '12px'
|
|
279
|
+
}}>
|
|
280
|
+
<div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: '8px' }}>
|
|
281
|
+
<Text weight="bold">{c.author}</Text>
|
|
282
|
+
<Text size="small" color="secondary">{c.time}</Text>
|
|
283
|
+
</div>
|
|
284
|
+
<Text>{c.content}</Text>
|
|
285
|
+
</div>
|
|
286
|
+
))}
|
|
287
|
+
</div>
|
|
288
|
+
|
|
289
|
+
{/* Add Comment */}
|
|
290
|
+
<div style={{
|
|
291
|
+
border: '1px solid #ccc',
|
|
292
|
+
borderRadius: '8px',
|
|
293
|
+
padding: '16px',
|
|
294
|
+
backgroundColor: '#f9f9fa'
|
|
295
|
+
}}>
|
|
296
|
+
<Text weight="bold" style={{ marginBottom: '12px' }}>
|
|
297
|
+
Add a comment
|
|
298
|
+
</Text>
|
|
299
|
+
|
|
300
|
+
<TextArea
|
|
301
|
+
value={comment}
|
|
302
|
+
onValueChange={setComment}
|
|
303
|
+
placeholder="What are your thoughts?"
|
|
304
|
+
rows={4}
|
|
305
|
+
style={{ marginBottom: '12px' }}
|
|
306
|
+
/>
|
|
307
|
+
|
|
308
|
+
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
|
|
309
|
+
<Text size="small" color="secondary">
|
|
310
|
+
{comment.length} characters
|
|
311
|
+
</Text>
|
|
312
|
+
<Button
|
|
313
|
+
onClick={handleSubmit}
|
|
314
|
+
disabled={!comment.trim()}
|
|
315
|
+
size="Small"
|
|
316
|
+
>
|
|
317
|
+
Post Comment
|
|
318
|
+
</Button>
|
|
319
|
+
</div>
|
|
320
|
+
</div>
|
|
321
|
+
</div>
|
|
322
|
+
);
|
|
323
|
+
}
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
### Feedback Form
|
|
327
|
+
|
|
328
|
+
```tsx
|
|
329
|
+
import { Form, FormField, TextArea, Button, RadioButton, Text } from '@delightui/components';
|
|
330
|
+
|
|
331
|
+
function FeedbackFormExample() {
|
|
332
|
+
const [formData, setFormData] = useState({
|
|
333
|
+
rating: '',
|
|
334
|
+
feedback: '',
|
|
335
|
+
suggestions: ''
|
|
336
|
+
});
|
|
337
|
+
|
|
338
|
+
const handleSubmit = (data: any) => {
|
|
339
|
+
console.log('Feedback submitted:', data);
|
|
340
|
+
};
|
|
341
|
+
|
|
342
|
+
return (
|
|
343
|
+
<Form onSubmit={handleSubmit}>
|
|
344
|
+
<Text weight="bold" size="large" style={{ marginBottom: '20px' }}>
|
|
345
|
+
We'd love your feedback!
|
|
346
|
+
</Text>
|
|
347
|
+
|
|
348
|
+
<FormField
|
|
349
|
+
name="rating"
|
|
350
|
+
label="How would you rate your experience?"
|
|
351
|
+
required
|
|
352
|
+
>
|
|
353
|
+
<div style={{ display: 'flex', flexDirection: 'column', gap: '8px' }}>
|
|
354
|
+
<RadioButton name="rating" value="excellent">Excellent</RadioButton>
|
|
355
|
+
<RadioButton name="rating" value="good">Good</RadioButton>
|
|
356
|
+
<RadioButton name="rating" value="average">Average</RadioButton>
|
|
357
|
+
<RadioButton name="rating" value="poor">Poor</RadioButton>
|
|
358
|
+
</div>
|
|
359
|
+
</FormField>
|
|
360
|
+
|
|
361
|
+
<FormField
|
|
362
|
+
name="feedback"
|
|
363
|
+
label="Tell us about your experience"
|
|
364
|
+
required
|
|
365
|
+
>
|
|
366
|
+
<TextArea
|
|
367
|
+
placeholder="Please share your thoughts about our service..."
|
|
368
|
+
rows={5}
|
|
369
|
+
maxLength={1000}
|
|
370
|
+
/>
|
|
371
|
+
</FormField>
|
|
372
|
+
|
|
373
|
+
<FormField
|
|
374
|
+
name="suggestions"
|
|
375
|
+
label="Any suggestions for improvement?"
|
|
376
|
+
>
|
|
377
|
+
<TextArea
|
|
378
|
+
placeholder="How can we make your experience better?"
|
|
379
|
+
rows={4}
|
|
380
|
+
maxLength={500}
|
|
381
|
+
/>
|
|
382
|
+
</FormField>
|
|
383
|
+
|
|
384
|
+
<Button type="submit">
|
|
385
|
+
Submit Feedback
|
|
386
|
+
</Button>
|
|
387
|
+
</Form>
|
|
388
|
+
);
|
|
389
|
+
}
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
### Code Input TextArea
|
|
393
|
+
|
|
394
|
+
```tsx
|
|
395
|
+
import { TextArea, Button, Text } from '@delightui/components';
|
|
396
|
+
|
|
397
|
+
function CodeInputExample() {
|
|
398
|
+
const [code, setCode] = useState(`function greet(name) {
|
|
399
|
+
return \`Hello, \${name}!\`;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
console.log(greet('World'));`);
|
|
403
|
+
|
|
404
|
+
const lineCount = code.split('\n').length;
|
|
405
|
+
|
|
406
|
+
return (
|
|
407
|
+
<div style={{ maxWidth: '600px' }}>
|
|
408
|
+
<Text weight="bold" style={{ marginBottom: '8px' }}>
|
|
409
|
+
Code Editor
|
|
410
|
+
</Text>
|
|
411
|
+
|
|
412
|
+
<div style={{ position: 'relative' }}>
|
|
413
|
+
<TextArea
|
|
414
|
+
value={code}
|
|
415
|
+
onValueChange={setCode}
|
|
416
|
+
rows={12}
|
|
417
|
+
style={{
|
|
418
|
+
fontFamily: 'monospace',
|
|
419
|
+
fontSize: '14px',
|
|
420
|
+
resize: 'none',
|
|
421
|
+
paddingLeft: '50px'
|
|
422
|
+
}}
|
|
423
|
+
/>
|
|
424
|
+
|
|
425
|
+
{/* Line numbers */}
|
|
426
|
+
<div style={{
|
|
427
|
+
position: 'absolute',
|
|
428
|
+
left: '8px',
|
|
429
|
+
top: '8px',
|
|
430
|
+
fontFamily: 'monospace',
|
|
431
|
+
fontSize: '14px',
|
|
432
|
+
color: '#666',
|
|
433
|
+
lineHeight: '1.5',
|
|
434
|
+
pointerEvents: 'none'
|
|
435
|
+
}}>
|
|
436
|
+
{Array.from({ length: lineCount }, (_, i) => (
|
|
437
|
+
<div key={i}>{i + 1}</div>
|
|
438
|
+
))}
|
|
439
|
+
</div>
|
|
440
|
+
</div>
|
|
441
|
+
|
|
442
|
+
<div style={{
|
|
443
|
+
display: 'flex',
|
|
444
|
+
justifyContent: 'space-between',
|
|
445
|
+
alignItems: 'center',
|
|
446
|
+
marginTop: '8px'
|
|
447
|
+
}}>
|
|
448
|
+
<Text size="small" color="secondary">
|
|
449
|
+
Lines: {lineCount} | Characters: {code.length}
|
|
450
|
+
</Text>
|
|
451
|
+
|
|
452
|
+
<div style={{ display: 'flex', gap: '8px' }}>
|
|
453
|
+
<Button size="Small" type="Outlined" onClick={() => setCode('')}>
|
|
454
|
+
Clear
|
|
455
|
+
</Button>
|
|
456
|
+
<Button size="Small" onClick={() => console.log('Code executed:', code)}>
|
|
457
|
+
Run
|
|
458
|
+
</Button>
|
|
459
|
+
</div>
|
|
460
|
+
</div>
|
|
461
|
+
</div>
|
|
462
|
+
);
|
|
463
|
+
}
|
|
464
|
+
```
|
|
465
|
+
|
|
466
|
+
### Disabled and Read-only States
|
|
467
|
+
|
|
468
|
+
```tsx
|
|
469
|
+
import { TextArea, Text } from '@delightui/components';
|
|
470
|
+
|
|
471
|
+
function DisabledReadOnlyExample() {
|
|
472
|
+
const sampleText = "This is some sample content that demonstrates different states of the TextArea component.";
|
|
473
|
+
|
|
474
|
+
return (
|
|
475
|
+
<div style={{ display: 'flex', flexDirection: 'column', gap: '20px' }}>
|
|
476
|
+
<div>
|
|
477
|
+
<Text weight="bold" style={{ marginBottom: '8px' }}>
|
|
478
|
+
Normal TextArea
|
|
479
|
+
</Text>
|
|
480
|
+
<TextArea
|
|
481
|
+
value={sampleText}
|
|
482
|
+
placeholder="Type here..."
|
|
483
|
+
rows={3}
|
|
484
|
+
/>
|
|
485
|
+
</div>
|
|
486
|
+
|
|
487
|
+
<div>
|
|
488
|
+
<Text weight="bold" style={{ marginBottom: '8px' }}>
|
|
489
|
+
Disabled TextArea
|
|
490
|
+
</Text>
|
|
491
|
+
<TextArea
|
|
492
|
+
value={sampleText}
|
|
493
|
+
disabled
|
|
494
|
+
rows={3}
|
|
495
|
+
/>
|
|
496
|
+
</div>
|
|
497
|
+
|
|
498
|
+
<div>
|
|
499
|
+
<Text weight="bold" style={{ marginBottom: '8px' }}>
|
|
500
|
+
Read-only TextArea
|
|
501
|
+
</Text>
|
|
502
|
+
<TextArea
|
|
503
|
+
value={sampleText}
|
|
504
|
+
readOnly
|
|
505
|
+
rows={3}
|
|
506
|
+
/>
|
|
507
|
+
</div>
|
|
508
|
+
</div>
|
|
509
|
+
);
|
|
510
|
+
}
|
|
511
|
+
```
|
|
512
|
+
|
|
513
|
+
### Template System
|
|
514
|
+
|
|
515
|
+
```tsx
|
|
516
|
+
import { TextArea, Button, Text } from '@delightui/components';
|
|
517
|
+
|
|
518
|
+
function TemplateSystemExample() {
|
|
519
|
+
const [message, setMessage] = useState('');
|
|
520
|
+
|
|
521
|
+
const templates = [
|
|
522
|
+
{
|
|
523
|
+
name: 'Thank You',
|
|
524
|
+
content: 'Thank you for your interest in our services. We appreciate your business and look forward to working with you.'
|
|
525
|
+
},
|
|
526
|
+
{
|
|
527
|
+
name: 'Follow Up',
|
|
528
|
+
content: 'I wanted to follow up on our previous conversation. Please let me know if you have any questions or if there\'s anything else I can help you with.'
|
|
529
|
+
},
|
|
530
|
+
{
|
|
531
|
+
name: 'Apology',
|
|
532
|
+
content: 'I apologize for any inconvenience this may have caused. We are working to resolve the issue and will keep you updated on our progress.'
|
|
533
|
+
}
|
|
534
|
+
];
|
|
535
|
+
|
|
536
|
+
const useTemplate = (template: string) => {
|
|
537
|
+
setMessage(template);
|
|
538
|
+
};
|
|
539
|
+
|
|
540
|
+
return (
|
|
541
|
+
<div style={{ maxWidth: '600px' }}>
|
|
542
|
+
<Text weight="bold" style={{ marginBottom: '12px' }}>
|
|
543
|
+
Message Templates
|
|
544
|
+
</Text>
|
|
545
|
+
|
|
546
|
+
<div style={{ display: 'flex', gap: '8px', marginBottom: '16px', flexWrap: 'wrap' }}>
|
|
547
|
+
{templates.map((template, index) => (
|
|
548
|
+
<Button
|
|
549
|
+
key={index}
|
|
550
|
+
size="Small"
|
|
551
|
+
type="Outlined"
|
|
552
|
+
onClick={() => useTemplate(template.content)}
|
|
553
|
+
>
|
|
554
|
+
{template.name}
|
|
555
|
+
</Button>
|
|
556
|
+
))}
|
|
557
|
+
</div>
|
|
558
|
+
|
|
559
|
+
<TextArea
|
|
560
|
+
value={message}
|
|
561
|
+
onValueChange={setMessage}
|
|
562
|
+
placeholder="Type your message or select a template above..."
|
|
563
|
+
rows={6}
|
|
564
|
+
/>
|
|
565
|
+
|
|
566
|
+
<div style={{
|
|
567
|
+
display: 'flex',
|
|
568
|
+
justifyContent: 'space-between',
|
|
569
|
+
alignItems: 'center',
|
|
570
|
+
marginTop: '12px'
|
|
571
|
+
}}>
|
|
572
|
+
<Text size="small" color="secondary">
|
|
573
|
+
{message.length} characters
|
|
574
|
+
</Text>
|
|
575
|
+
|
|
576
|
+
<div style={{ display: 'flex', gap: '8px' }}>
|
|
577
|
+
<Button
|
|
578
|
+
size="Small"
|
|
579
|
+
type="Outlined"
|
|
580
|
+
onClick={() => setMessage('')}
|
|
581
|
+
disabled={!message}
|
|
582
|
+
>
|
|
583
|
+
Clear
|
|
584
|
+
</Button>
|
|
585
|
+
<Button
|
|
586
|
+
size="Small"
|
|
587
|
+
disabled={!message.trim()}
|
|
588
|
+
>
|
|
589
|
+
Send
|
|
590
|
+
</Button>
|
|
591
|
+
</div>
|
|
592
|
+
</div>
|
|
593
|
+
</div>
|
|
594
|
+
);
|
|
595
|
+
}
|
|
596
|
+
```
|
|
597
|
+
|
|
598
|
+
### Validation Example
|
|
599
|
+
|
|
600
|
+
```tsx
|
|
601
|
+
import { Form, FormField, TextArea, Button, Text } from '@delightui/components';
|
|
602
|
+
|
|
603
|
+
function ValidationExample() {
|
|
604
|
+
const [content, setContent] = useState('');
|
|
605
|
+
const [error, setError] = useState('');
|
|
606
|
+
|
|
607
|
+
const minLength = 50;
|
|
608
|
+
const maxLength = 500;
|
|
609
|
+
|
|
610
|
+
const validateContent = (value: string) => {
|
|
611
|
+
if (value.length < minLength) {
|
|
612
|
+
setError(`Content must be at least ${minLength} characters long`);
|
|
613
|
+
return false;
|
|
614
|
+
}
|
|
615
|
+
if (value.length > maxLength) {
|
|
616
|
+
setError(`Content must not exceed ${maxLength} characters`);
|
|
617
|
+
return false;
|
|
618
|
+
}
|
|
619
|
+
setError('');
|
|
620
|
+
return true;
|
|
621
|
+
};
|
|
622
|
+
|
|
623
|
+
const handleSubmit = (data: any) => {
|
|
624
|
+
if (validateContent(content)) {
|
|
625
|
+
console.log('Valid submission:', data);
|
|
626
|
+
}
|
|
627
|
+
};
|
|
628
|
+
|
|
629
|
+
return (
|
|
630
|
+
<Form onSubmit={handleSubmit}>
|
|
631
|
+
<FormField
|
|
632
|
+
name="content"
|
|
633
|
+
label="Content"
|
|
634
|
+
required
|
|
635
|
+
invalid={!!error}
|
|
636
|
+
message={error}
|
|
637
|
+
>
|
|
638
|
+
<TextArea
|
|
639
|
+
value={content}
|
|
640
|
+
onValueChange={(value) => {
|
|
641
|
+
setContent(value);
|
|
642
|
+
validateContent(value);
|
|
643
|
+
}}
|
|
644
|
+
placeholder={`Write your content here (${minLength}-${maxLength} characters)...`}
|
|
645
|
+
rows={6}
|
|
646
|
+
invalid={!!error}
|
|
647
|
+
/>
|
|
648
|
+
</FormField>
|
|
649
|
+
|
|
650
|
+
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginTop: '8px' }}>
|
|
651
|
+
<Text
|
|
652
|
+
size="small"
|
|
653
|
+
color={error ? 'error' : content.length < minLength ? 'warning' : 'success'}
|
|
654
|
+
>
|
|
655
|
+
{content.length} / {maxLength} characters
|
|
656
|
+
{content.length < minLength && ` (${minLength - content.length} more needed)`}
|
|
657
|
+
</Text>
|
|
658
|
+
</div>
|
|
659
|
+
|
|
660
|
+
<Button
|
|
661
|
+
type="submit"
|
|
662
|
+
disabled={!!error || content.length < minLength}
|
|
663
|
+
style={{ marginTop: '16px' }}
|
|
664
|
+
>
|
|
665
|
+
Submit
|
|
666
|
+
</Button>
|
|
667
|
+
</Form>
|
|
668
|
+
);
|
|
669
|
+
}
|
|
670
|
+
```
|