@ticatec/uniface-element 0.2.4 → 0.3.0
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/dist/accordion/README.md +169 -0
- package/dist/accordion/README_CN.md +176 -0
- package/dist/action-bar/README.md +275 -0
- package/dist/action-bar/README_CN.md +285 -0
- package/dist/app-layout/README.md +374 -0
- package/dist/app-layout/README_CN.md +381 -0
- package/dist/app-top-bar/README.md +357 -0
- package/dist/app-top-bar/README_CN.md +365 -0
- package/dist/attachment-files/AttachmentFilesField.svelte +67 -1
- package/dist/attachment-files/AttachmentFilesField.svelte.d.ts +8 -1
- package/dist/base-calendar/CalendarBase.svelte +0 -3
- package/dist/box/README.md +385 -0
- package/dist/box/README_CN.md +393 -0
- package/dist/breadcrumbs/README.md +442 -0
- package/dist/breadcrumbs/README_CN.md +442 -0
- package/dist/button/Button.svelte +27 -7
- package/dist/button/Button.svelte.d.ts +3 -1
- package/dist/button/IconButton.svelte +26 -6
- package/dist/button/IconButton.svelte.d.ts +3 -1
- package/dist/button/IconButton_README.md +513 -0
- package/dist/button/IconButton_README_CN.md +513 -0
- package/dist/button/README.md +428 -0
- package/dist/button/README_CN.md +428 -0
- package/dist/button/TextButton.svelte +26 -6
- package/dist/button/TextButton.svelte.d.ts +3 -1
- package/dist/button/TextButton_README.md +571 -0
- package/dist/button/TextButton_README_CN.md +571 -0
- package/dist/card/README.md +666 -0
- package/dist/card/README_CN.md +666 -0
- package/dist/cascade-options-select/CascadeOptionSelect.svelte +43 -7
- package/dist/cascade-options-select/CascadeOptionSelect.svelte.d.ts +3 -4
- package/dist/cascade-options-select/README.md +663 -2
- package/dist/cascade-options-select/README_CN.md +664 -0
- package/dist/checkbox/CheckBox.svelte +20 -6
- package/dist/checkbox/CheckBox.svelte.d.ts +4 -2
- package/dist/checkbox/README.md +562 -0
- package/dist/checkbox/README_CN.md +727 -0
- package/dist/common-editor/NumberInput.svelte +39 -26
- package/dist/common-editor/NumberInput.svelte.d.ts +5 -1
- package/dist/concise-data-table/ConciseListTable.svelte +133 -36
- package/dist/concise-data-table/ConciseListTable.svelte.d.ts +8 -1
- package/dist/concise-data-table/DataCell.svelte +5 -6
- package/dist/concise-data-table/DataRow.svelte +22 -2
- package/dist/concise-data-table/DataRow.svelte.d.ts +1 -0
- package/dist/concise-data-table/README.md +606 -0
- package/dist/concise-data-table/README_CN.md +611 -0
- package/dist/context-menu/ContextMenu.svelte +138 -21
- package/dist/context-menu/ContextMenu.svelte.d.ts +5 -0
- package/dist/context-menu/ContextMenuItem.d.ts +20 -4
- package/dist/context-menu/README.md +551 -0
- package/dist/context-menu/README_CN.md +551 -0
- package/dist/criteria-field/CriteriaField.svelte +3 -5
- package/dist/criteria-field/README.md +532 -0
- package/dist/criteria-field/README_CN.md +532 -0
- package/dist/data-table/README.md +712 -0
- package/dist/data-table/README_CN.md +712 -0
- package/dist/date-picker/DatePicker.svelte +44 -7
- package/dist/date-picker/DatePicker.svelte.d.ts +3 -4
- package/dist/date-picker/DateTimePicker.svelte +32 -8
- package/dist/date-picker/DateTimePicker.svelte.d.ts +3 -4
- package/dist/date-picker/README.md +326 -0
- package/dist/date-picker/README_CN.md +316 -0
- package/dist/date-picker/ScrollBar.svelte +18 -8
- package/dist/date-picker/ScrollBar.svelte.d.ts +1 -1
- package/dist/date-picker/TimePanel.svelte +5 -5
- package/dist/date-picker/TimePanel.svelte.d.ts +1 -1
- package/dist/date-range/README.md +374 -0
- package/dist/date-range/README_CN.md +374 -0
- package/dist/dialog/README.md +596 -0
- package/dist/dialog/README_CN.md +596 -0
- package/dist/drawer/README.md +679 -1
- package/dist/drawer/README_CN.md +679 -0
- package/dist/group-box/group-check-box/GroupCheckBox.svelte +62 -5
- package/dist/group-box/group-check-box/GroupCheckBox.svelte.d.ts +7 -2
- package/dist/group-box/group-check-box/README.md +749 -0
- package/dist/group-box/group-check-box/README_CN.md +750 -0
- package/dist/group-box/group-radio-box/GroupRadioBox.svelte +69 -4
- package/dist/group-box/group-radio-box/GroupRadioBox.svelte.d.ts +8 -2
- package/dist/group-box/group-radio-box/README.md +920 -0
- package/dist/group-box/group-radio-box/README_CN.md +920 -0
- package/dist/image-files/README.md +1346 -0
- package/dist/image-files/README_CN.md +1346 -0
- package/dist/input-options-select/InputOptionsSelect.svelte +161 -65
- package/dist/input-options-select/InputOptionsSelect.svelte.d.ts +4 -1
- package/dist/lib/forwardAllEvents.d.ts +3 -0
- package/dist/lib/forwardAllEvents.js +24 -0
- package/dist/list-box/README.md +579 -0
- package/dist/list-box/README_CN.md +682 -0
- package/dist/lookup-editor/LookupEditor.svelte +15 -3
- package/dist/lookup-editor/LookupEditor.svelte.d.ts +3 -4
- package/dist/lookup-editor/README.md +684 -0
- package/dist/lookup-editor/README_CN.md +684 -0
- package/dist/memo-editor/MemoEditor.svelte +77 -27
- package/dist/memo-editor/MemoEditor.svelte.d.ts +6 -3
- package/dist/memo-editor/README.md +819 -0
- package/dist/memo-editor/README_CN.md +819 -0
- package/dist/message-box/README.md +398 -0
- package/dist/message-box/README_CN.md +398 -0
- package/dist/number-editor/NumberEditor.svelte +2 -2
- package/dist/number-editor/NumberEditor.svelte.d.ts +1 -1
- package/dist/number-editor/README.md +353 -22
- package/dist/number-editor/README_CN.md +357 -0
- package/dist/number-range/README.md +443 -0
- package/dist/number-range/README_CN.md +443 -0
- package/dist/options-multi-select/OptionsMultiSelect.svelte +87 -12
- package/dist/options-multi-select/OptionsMultiSelect.svelte.d.ts +3 -1
- package/dist/options-multi-select/README.md +480 -0
- package/dist/options-multi-select/README_CN.md +480 -0
- package/dist/options-select/OptionsSelect.svelte +36 -5
- package/dist/options-select/OptionsSelect.svelte.d.ts +3 -4
- package/dist/options-select/README.md +632 -0
- package/dist/options-select/README_CN.md +632 -0
- package/dist/page/README.md +605 -0
- package/dist/page/README_CN.md +605 -0
- package/dist/pagination/README.md +946 -0
- package/dist/pagination/README_CN.md +946 -0
- package/dist/pagination-panel/README.md +1075 -0
- package/dist/pagination-panel/README_CN.md +1075 -0
- package/dist/popup-hint/README.md +841 -0
- package/dist/popup-hint/README_CN.md +840 -0
- package/dist/progress-bar/README.md +242 -0
- package/dist/progress-bar/README_CN.md +242 -0
- package/dist/progress-step-bar/README.md +316 -0
- package/dist/progress-step-bar/README_CN.md +316 -0
- package/dist/prompts-text-editor/PromptsTextEditor.svelte +6 -3
- package/dist/prompts-text-editor/PromptsTextEditor.svelte.d.ts +3 -1
- package/dist/prompts-text-editor/README.md +329 -0
- package/dist/prompts-text-editor/README_CN.md +329 -0
- package/dist/property-editor/README.md +969 -0
- package/dist/property-editor/README_CN.md +969 -0
- package/dist/radio-button/README.md +372 -0
- package/dist/radio-button/README_CN.md +372 -0
- package/dist/radio-button/RadioButton.svelte +32 -3
- package/dist/radio-button/RadioButton.svelte.d.ts +12 -1
- package/dist/search-box/README.md +425 -0
- package/dist/search-box/README_CN.md +424 -0
- package/dist/search-box/SearchBox.svelte +22 -6
- package/dist/search-box/SearchBox.svelte.d.ts +4 -1
- package/dist/tabs/README.md +919 -0
- package/dist/tabs/README_CN.md +920 -0
- package/dist/tag/README.md +922 -0
- package/dist/tag/README_CN.md +922 -0
- package/dist/text-editor/PasswordEditor.svelte +17 -2
- package/dist/text-editor/PasswordEditor.svelte.d.ts +3 -3
- package/dist/text-editor/PasswordEditor_README.md +551 -0
- package/dist/text-editor/PasswordEditor_README_CN.md +551 -0
- package/dist/text-editor/README.md +466 -0
- package/dist/text-editor/README_CN.md +466 -0
- package/dist/text-editor/TextEditor.svelte +51 -19
- package/dist/text-editor/TextEditor.svelte.d.ts +0 -1
- package/dist/time-editor/README.md +498 -24
- package/dist/time-editor/README_CN.md +498 -0
- package/dist/time-editor/TimeEditor.svelte +7 -3
- package/dist/time-editor/TimeEditor.svelte.d.ts +3 -1
- package/dist/toast/README.md +667 -0
- package/dist/toast/README_CN.md +667 -0
- package/dist/transfer/README.md +795 -0
- package/dist/transfer/Transfer.svelte +6 -4
- package/dist/transfer/Transfer.svelte.d.ts +3 -1
- package/dist/tree-view/README.md +761 -0
- package/dist/tree-view/README_CN.md +761 -0
- package/dist/tree-view/TreeView.svelte +5 -3
- package/dist/tree-view/TreeView.svelte.d.ts +3 -1
- package/dist/unit-number-editor/README.md +546 -20
- package/dist/unit-number-editor/README_CN.md +525 -0
- package/dist/unit-number-editor/UnitNumberEditor.svelte +62 -8
- package/dist/unit-number-editor/UnitNumberEditor.svelte.d.ts +5 -1
- package/docs/form-field/cn/README_CN.md +364 -0
- package/docs/form-field/en/README.md +364 -0
- package/docs/form-panel/flex-form/cn/README_CN.md +586 -0
- package/docs/form-panel/flex-form/en/README.md +586 -0
- package/docs/form-panel/flex-row-form/cn/README_CN.md +787 -0
- package/docs/form-panel/flex-row-form/en/README.md +787 -0
- package/docs/form-panel/grid-form/en/README.md +744 -0
- package/package.json +1 -1
- package/dist/drawer/README-CN.md +0 -1
|
@@ -0,0 +1,364 @@
|
|
|
1
|
+
# FormField 表单字段组件
|
|
2
|
+
|
|
3
|
+
一个灵活的表单字段包装组件,为表单控件提供一致的标签、验证显示和布局选项。
|
|
4
|
+
|
|
5
|
+
## 特性
|
|
6
|
+
|
|
7
|
+
- **灵活布局**: 支持垂直和水平标签排列
|
|
8
|
+
- **验证显示**: 内置错误消息显示,样式一致
|
|
9
|
+
- **必填字段指示器**: 必填字段的可视化星号指示器
|
|
10
|
+
- **可自定义样式**: 支持CSS变量和标签自定义样式
|
|
11
|
+
- **响应式设计**: 适配不同屏幕尺寸和表单布局
|
|
12
|
+
- **无障碍访问**: 为屏幕阅读器提供适当的语义结构
|
|
13
|
+
|
|
14
|
+
## 安装
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm install @ticatec/uniface-element
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## 使用方法
|
|
21
|
+
|
|
22
|
+
### 基本用法
|
|
23
|
+
|
|
24
|
+
```svelte
|
|
25
|
+
<script>
|
|
26
|
+
import FormField from '@ticatec/uniface-element/form-field';
|
|
27
|
+
import TextEditor from '@ticatec/uniface-element/text-editor';
|
|
28
|
+
|
|
29
|
+
let name = '';
|
|
30
|
+
</script>
|
|
31
|
+
|
|
32
|
+
<FormField label="姓名">
|
|
33
|
+
<TextEditor bind:value={name} placeholder="请输入姓名" />
|
|
34
|
+
</FormField>
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### 必填字段
|
|
38
|
+
|
|
39
|
+
```svelte
|
|
40
|
+
<FormField required label="邮箱">
|
|
41
|
+
<TextEditor bind:value={email} placeholder="请输入邮箱地址" />
|
|
42
|
+
</FormField>
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### 带错误消息的字段
|
|
46
|
+
|
|
47
|
+
```svelte
|
|
48
|
+
<script>
|
|
49
|
+
let email = '';
|
|
50
|
+
let emailError = '请输入有效的邮箱地址';
|
|
51
|
+
</script>
|
|
52
|
+
|
|
53
|
+
<FormField required label="邮箱" error={emailError}>
|
|
54
|
+
<TextEditor bind:value={email} placeholder="请输入邮箱地址" />
|
|
55
|
+
</FormField>
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### 水平布局
|
|
59
|
+
|
|
60
|
+
```svelte
|
|
61
|
+
<div class="field-layout-horizontal">
|
|
62
|
+
<FormField label="出生日期">
|
|
63
|
+
<DatePicker bind:value={dateOfBirth} />
|
|
64
|
+
</FormField>
|
|
65
|
+
</div>
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### 自定义标签样式
|
|
69
|
+
|
|
70
|
+
```svelte
|
|
71
|
+
<FormField
|
|
72
|
+
label="重要字段"
|
|
73
|
+
label$style="color: #2F54EB; font-weight: bold;"
|
|
74
|
+
>
|
|
75
|
+
<TextEditor bind:value={value} />
|
|
76
|
+
</FormField>
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### 多行控件的顶部对齐标签
|
|
80
|
+
|
|
81
|
+
```svelte
|
|
82
|
+
<FormField
|
|
83
|
+
label="描述"
|
|
84
|
+
label$alignment="top"
|
|
85
|
+
>
|
|
86
|
+
<MemoEditor bind:value={description} resize="vertical" />
|
|
87
|
+
</FormField>
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## API 参考
|
|
91
|
+
|
|
92
|
+
### 属性
|
|
93
|
+
|
|
94
|
+
| 属性 | 类型 | 默认值 | 描述 |
|
|
95
|
+
|------|------|---------|-------------|
|
|
96
|
+
| `label` | `string` | `"Label:"` | 表单字段的标签文本 |
|
|
97
|
+
| `style` | `string` | `''` | 表单字段容器的自定义CSS样式 |
|
|
98
|
+
| `label$style` | `string \| null` | `null` | 标签元素的自定义CSS样式 |
|
|
99
|
+
| `required` | `boolean` | `false` | 字段是否必填(显示星号指示器) |
|
|
100
|
+
| `error` | `string \| null` | `null` | 在字段下方显示的错误消息 |
|
|
101
|
+
| `labelSuffix` | `string` | `':'` | 附加到标签后的文本(如冒号) |
|
|
102
|
+
| `label$alignment` | `'center' \| 'top'` | `'center'` | 标签的垂直对齐方式 |
|
|
103
|
+
| `height` | `string` | `null` | 字段容器的自定义高度 |
|
|
104
|
+
| `class` | `string` | `''` | 表单字段的额外CSS类 |
|
|
105
|
+
|
|
106
|
+
### 插槽
|
|
107
|
+
|
|
108
|
+
| 插槽 | 描述 |
|
|
109
|
+
|------|-------------|
|
|
110
|
+
| default | 表单控件内容(输入框、选择器等) |
|
|
111
|
+
|
|
112
|
+
## 布局类
|
|
113
|
+
|
|
114
|
+
### 水平布局
|
|
115
|
+
|
|
116
|
+
在父容器中添加 `field-layout-horizontal` 类来水平排列表单字段:
|
|
117
|
+
|
|
118
|
+
```svelte
|
|
119
|
+
<div class="field-layout-horizontal">
|
|
120
|
+
<FormField label="名">
|
|
121
|
+
<TextEditor bind:value={firstName} />
|
|
122
|
+
</FormField>
|
|
123
|
+
<FormField label="姓">
|
|
124
|
+
<TextEditor bind:value={lastName} />
|
|
125
|
+
</FormField>
|
|
126
|
+
</div>
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
## 样式
|
|
130
|
+
|
|
131
|
+
### CSS 变量
|
|
132
|
+
|
|
133
|
+
FormField组件使用CSS变量进行一致的主题化:
|
|
134
|
+
|
|
135
|
+
```css
|
|
136
|
+
:root {
|
|
137
|
+
--uniface-form-field-required-indicator-color: #ff3e00;
|
|
138
|
+
--uniface-form-field-label-color: #374151;
|
|
139
|
+
--uniface-form-field-invalid-message-color: #ff3e00;
|
|
140
|
+
--uniface-form-field-label-width: 120px;
|
|
141
|
+
--uniface-form-field-label-alignment: right;
|
|
142
|
+
--uniface-form-field-padding: 6px 4px;
|
|
143
|
+
--uniface-field-gap: 4px;
|
|
144
|
+
}
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### 自定义样式
|
|
148
|
+
|
|
149
|
+
```css
|
|
150
|
+
.custom-form-field {
|
|
151
|
+
--uniface-form-field-label-color: #2563eb;
|
|
152
|
+
--uniface-form-field-label-width: 150px;
|
|
153
|
+
}
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
## 示例
|
|
157
|
+
|
|
158
|
+
### 完整表单示例
|
|
159
|
+
|
|
160
|
+
```svelte
|
|
161
|
+
<script>
|
|
162
|
+
import FormField from '@ticatec/uniface-element/form-field';
|
|
163
|
+
import TextEditor from '@ticatec/uniface-element/text-editor';
|
|
164
|
+
import DatePicker from '@ticatec/uniface-element/date-picker';
|
|
165
|
+
import MemoEditor from '@ticatec/uniface-element/memo-editor';
|
|
166
|
+
|
|
167
|
+
let formData = {
|
|
168
|
+
name: '',
|
|
169
|
+
email: '',
|
|
170
|
+
dateOfBirth: null,
|
|
171
|
+
notes: ''
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
let errors = {};
|
|
175
|
+
|
|
176
|
+
function validateForm() {
|
|
177
|
+
errors = {};
|
|
178
|
+
|
|
179
|
+
if (!formData.name) {
|
|
180
|
+
errors.name = '姓名为必填项';
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
if (!formData.email) {
|
|
184
|
+
errors.email = '邮箱为必填项';
|
|
185
|
+
} else if (!/\S+@\S+\.\S+/.test(formData.email)) {
|
|
186
|
+
errors.email = '请输入有效的邮箱地址';
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
return Object.keys(errors).length === 0;
|
|
190
|
+
}
|
|
191
|
+
</script>
|
|
192
|
+
|
|
193
|
+
<form on:submit|preventDefault={validateForm}>
|
|
194
|
+
<FormField required label="姓名" error={errors.name}>
|
|
195
|
+
<TextEditor
|
|
196
|
+
variant="filled"
|
|
197
|
+
bind:value={formData.name}
|
|
198
|
+
placeholder="请输入您的姓名"
|
|
199
|
+
/>
|
|
200
|
+
</FormField>
|
|
201
|
+
|
|
202
|
+
<FormField required label="邮箱地址" error={errors.email}>
|
|
203
|
+
<TextEditor
|
|
204
|
+
variant="filled"
|
|
205
|
+
bind:value={formData.email}
|
|
206
|
+
placeholder="请输入邮箱地址"
|
|
207
|
+
/>
|
|
208
|
+
</FormField>
|
|
209
|
+
|
|
210
|
+
<div class="field-layout-horizontal">
|
|
211
|
+
<FormField label="出生日期">
|
|
212
|
+
<DatePicker variant="filled" bind:value={formData.dateOfBirth} />
|
|
213
|
+
</FormField>
|
|
214
|
+
</div>
|
|
215
|
+
|
|
216
|
+
<FormField label="备注" label$alignment="top">
|
|
217
|
+
<MemoEditor
|
|
218
|
+
variant="filled"
|
|
219
|
+
bind:value={formData.notes}
|
|
220
|
+
resize="vertical"
|
|
221
|
+
placeholder="请输入备注信息..."
|
|
222
|
+
/>
|
|
223
|
+
</FormField>
|
|
224
|
+
|
|
225
|
+
<button type="submit">提交</button>
|
|
226
|
+
</form>
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
### 响应式表单布局
|
|
230
|
+
|
|
231
|
+
```svelte
|
|
232
|
+
<div class="responsive-form">
|
|
233
|
+
<div class="field-row">
|
|
234
|
+
<FormField label="名" error={errors.firstName}>
|
|
235
|
+
<TextEditor bind:value={formData.firstName} />
|
|
236
|
+
</FormField>
|
|
237
|
+
|
|
238
|
+
<FormField label="姓" error={errors.lastName}>
|
|
239
|
+
<TextEditor bind:value={formData.lastName} />
|
|
240
|
+
</FormField>
|
|
241
|
+
</div>
|
|
242
|
+
|
|
243
|
+
<FormField label="邮箱地址" error={errors.email}>
|
|
244
|
+
<TextEditor bind:value={formData.email} />
|
|
245
|
+
</FormField>
|
|
246
|
+
</div>
|
|
247
|
+
|
|
248
|
+
<style>
|
|
249
|
+
.responsive-form {
|
|
250
|
+
max-width: 600px;
|
|
251
|
+
margin: 0 auto;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
.field-row {
|
|
255
|
+
display: grid;
|
|
256
|
+
grid-template-columns: 1fr 1fr;
|
|
257
|
+
gap: 16px;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
@media (max-width: 768px) {
|
|
261
|
+
.field-row {
|
|
262
|
+
grid-template-columns: 1fr;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
</style>
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
## 最佳实践
|
|
269
|
+
|
|
270
|
+
### 1. 一致的标签格式
|
|
271
|
+
|
|
272
|
+
在表单中使用一致的标签格式:
|
|
273
|
+
|
|
274
|
+
```svelte
|
|
275
|
+
<FormField label="名" labelSuffix="">
|
|
276
|
+
<TextEditor bind:value={firstName} />
|
|
277
|
+
</FormField>
|
|
278
|
+
|
|
279
|
+
<FormField label="姓" labelSuffix="">
|
|
280
|
+
<TextEditor bind:value={lastName} />
|
|
281
|
+
</FormField>
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
### 2. 必填字段指示器
|
|
285
|
+
|
|
286
|
+
始终用 `required` 属性标记必填字段:
|
|
287
|
+
|
|
288
|
+
```svelte
|
|
289
|
+
<FormField required label="邮箱">
|
|
290
|
+
<TextEditor bind:value={email} />
|
|
291
|
+
</FormField>
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
### 3. 错误处理
|
|
295
|
+
|
|
296
|
+
提供清晰、可操作的错误消息:
|
|
297
|
+
|
|
298
|
+
```svelte
|
|
299
|
+
<FormField
|
|
300
|
+
required
|
|
301
|
+
label="密码"
|
|
302
|
+
error={passwordError || (password && password.length < 8 ? '密码长度至少8位' : null)}
|
|
303
|
+
>
|
|
304
|
+
<TextEditor type="password" bind:value={password} />
|
|
305
|
+
</FormField>
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
### 4. 无障碍访问
|
|
309
|
+
|
|
310
|
+
确保表单的无障碍访问:
|
|
311
|
+
|
|
312
|
+
```svelte
|
|
313
|
+
<FormField
|
|
314
|
+
required
|
|
315
|
+
label="用户名"
|
|
316
|
+
error={usernameError}
|
|
317
|
+
>
|
|
318
|
+
<TextEditor
|
|
319
|
+
bind:value={username}
|
|
320
|
+
input$aria-describedby={usernameError ? 'username-error' : undefined}
|
|
321
|
+
/>
|
|
322
|
+
</FormField>
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
### 5. 布局考虑
|
|
326
|
+
|
|
327
|
+
对相关字段使用水平布局:
|
|
328
|
+
|
|
329
|
+
```svelte
|
|
330
|
+
<div class="field-layout-horizontal">
|
|
331
|
+
<FormField label="开始日期">
|
|
332
|
+
<DatePicker bind:value={startDate} />
|
|
333
|
+
</FormField>
|
|
334
|
+
|
|
335
|
+
<FormField label="结束日期">
|
|
336
|
+
<DatePicker bind:value={endDate} />
|
|
337
|
+
</FormField>
|
|
338
|
+
</div>
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
## 无障碍功能
|
|
342
|
+
|
|
343
|
+
- **语义化HTML**: 使用适当的表单字段结构
|
|
344
|
+
- **必填指示器**: 必填字段的可视化星号
|
|
345
|
+
- **错误关联**: 错误消息与字段正确关联
|
|
346
|
+
- **标签关联**: 标签与表单控件语义连接
|
|
347
|
+
- **键盘导航**: 支持标准表单导航模式
|
|
348
|
+
|
|
349
|
+
## 浏览器支持
|
|
350
|
+
|
|
351
|
+
- **现代浏览器**: Chrome、Firefox、Safari、Edge(最新版本)
|
|
352
|
+
- **移动浏览器**: iOS Safari、Chrome Mobile、Firefox Mobile
|
|
353
|
+
- **CSS Grid支持**: 布局功能必需
|
|
354
|
+
|
|
355
|
+
## 相关组件
|
|
356
|
+
|
|
357
|
+
- **TextEditor**: 单行文本输入组件
|
|
358
|
+
- **MemoEditor**: 多行文本区域组件
|
|
359
|
+
- **DatePicker**: 日期选择组件
|
|
360
|
+
- **DateTimePicker**: 日期时间选择组件
|
|
361
|
+
|
|
362
|
+
## 许可证
|
|
363
|
+
|
|
364
|
+
MIT许可证 - 详情请参阅LICENSE文件。
|
|
@@ -0,0 +1,364 @@
|
|
|
1
|
+
# FormField
|
|
2
|
+
|
|
3
|
+
A flexible form field wrapper component that provides consistent labeling, validation display, and layout options for form controls.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Flexible Layout**: Supports both vertical and horizontal label arrangements
|
|
8
|
+
- **Validation Display**: Built-in error message display with consistent styling
|
|
9
|
+
- **Required Field Indicator**: Visual asterisk indicator for required fields
|
|
10
|
+
- **Customizable Styling**: CSS variables and custom style support for labels
|
|
11
|
+
- **Responsive Design**: Adapts to different screen sizes and form layouts
|
|
12
|
+
- **Accessibility**: Proper semantic structure for screen readers
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm install @ticatec/uniface-element
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Usage
|
|
21
|
+
|
|
22
|
+
### Basic Usage
|
|
23
|
+
|
|
24
|
+
```svelte
|
|
25
|
+
<script>
|
|
26
|
+
import FormField from '@ticatec/uniface-element/form-field';
|
|
27
|
+
import TextEditor from '@ticatec/uniface-element/text-editor';
|
|
28
|
+
|
|
29
|
+
let name = '';
|
|
30
|
+
</script>
|
|
31
|
+
|
|
32
|
+
<FormField label="Name">
|
|
33
|
+
<TextEditor bind:value={name} placeholder="Enter your name" />
|
|
34
|
+
</FormField>
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### Required Field
|
|
38
|
+
|
|
39
|
+
```svelte
|
|
40
|
+
<FormField required label="Email">
|
|
41
|
+
<TextEditor bind:value={email} placeholder="Enter your email" />
|
|
42
|
+
</FormField>
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### Field with Error Message
|
|
46
|
+
|
|
47
|
+
```svelte
|
|
48
|
+
<script>
|
|
49
|
+
let email = '';
|
|
50
|
+
let emailError = 'Please enter a valid email address';
|
|
51
|
+
</script>
|
|
52
|
+
|
|
53
|
+
<FormField required label="Email" error={emailError}>
|
|
54
|
+
<TextEditor bind:value={email} placeholder="Enter your email" />
|
|
55
|
+
</FormField>
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Horizontal Layout
|
|
59
|
+
|
|
60
|
+
```svelte
|
|
61
|
+
<div class="field-layout-horizontal">
|
|
62
|
+
<FormField label="Date of Birth">
|
|
63
|
+
<DatePicker bind:value={dateOfBirth} />
|
|
64
|
+
</FormField>
|
|
65
|
+
</div>
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Custom Label Styling
|
|
69
|
+
|
|
70
|
+
```svelte
|
|
71
|
+
<FormField
|
|
72
|
+
label="Important Field"
|
|
73
|
+
label$style="color: #2F54EB; font-weight: bold;"
|
|
74
|
+
>
|
|
75
|
+
<TextEditor bind:value={value} />
|
|
76
|
+
</FormField>
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Top-Aligned Label for Multi-line Controls
|
|
80
|
+
|
|
81
|
+
```svelte
|
|
82
|
+
<FormField
|
|
83
|
+
label="Description"
|
|
84
|
+
label$alignment="top"
|
|
85
|
+
>
|
|
86
|
+
<MemoEditor bind:value={description} resize="vertical" />
|
|
87
|
+
</FormField>
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## API Reference
|
|
91
|
+
|
|
92
|
+
### Props
|
|
93
|
+
|
|
94
|
+
| Prop | Type | Default | Description |
|
|
95
|
+
|------|------|---------|-------------|
|
|
96
|
+
| `label` | `string` | `"Label:"` | The label text for the form field |
|
|
97
|
+
| `style` | `string` | `''` | Custom CSS styles for the form field container |
|
|
98
|
+
| `label$style` | `string \| null` | `null` | Custom CSS styles for the label element |
|
|
99
|
+
| `required` | `boolean` | `false` | Whether the field is required (shows asterisk indicator) |
|
|
100
|
+
| `error` | `string \| null` | `null` | Error message to display below the field |
|
|
101
|
+
| `labelSuffix` | `string` | `':'` | Text to append to the label (e.g., colon) |
|
|
102
|
+
| `label$alignment` | `'center' \| 'top'` | `'center'` | Vertical alignment of the label |
|
|
103
|
+
| `height` | `string` | `null` | Custom height for the field container |
|
|
104
|
+
| `class` | `string` | `''` | Additional CSS classes for the form field |
|
|
105
|
+
|
|
106
|
+
### Slots
|
|
107
|
+
|
|
108
|
+
| Slot | Description |
|
|
109
|
+
|------|-------------|
|
|
110
|
+
| default | The form control content (input, select, etc.) |
|
|
111
|
+
|
|
112
|
+
## Layout Classes
|
|
113
|
+
|
|
114
|
+
### Horizontal Layout
|
|
115
|
+
|
|
116
|
+
Add the `field-layout-horizontal` class to a parent container to arrange form fields horizontally:
|
|
117
|
+
|
|
118
|
+
```svelte
|
|
119
|
+
<div class="field-layout-horizontal">
|
|
120
|
+
<FormField label="First Name">
|
|
121
|
+
<TextEditor bind:value={firstName} />
|
|
122
|
+
</FormField>
|
|
123
|
+
<FormField label="Last Name">
|
|
124
|
+
<TextEditor bind:value={lastName} />
|
|
125
|
+
</FormField>
|
|
126
|
+
</div>
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
## Styling
|
|
130
|
+
|
|
131
|
+
### CSS Variables
|
|
132
|
+
|
|
133
|
+
The FormField component uses CSS variables for consistent theming:
|
|
134
|
+
|
|
135
|
+
```css
|
|
136
|
+
:root {
|
|
137
|
+
--uniface-form-field-required-indicator-color: #ff3e00;
|
|
138
|
+
--uniface-form-field-label-color: #374151;
|
|
139
|
+
--uniface-form-field-invalid-message-color: #ff3e00;
|
|
140
|
+
--uniface-form-field-label-width: 120px;
|
|
141
|
+
--uniface-form-field-label-alignment: right;
|
|
142
|
+
--uniface-form-field-padding: 6px 4px;
|
|
143
|
+
--uniface-field-gap: 4px;
|
|
144
|
+
}
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### Custom Styling
|
|
148
|
+
|
|
149
|
+
```css
|
|
150
|
+
.custom-form-field {
|
|
151
|
+
--uniface-form-field-label-color: #2563eb;
|
|
152
|
+
--uniface-form-field-label-width: 150px;
|
|
153
|
+
}
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
## Examples
|
|
157
|
+
|
|
158
|
+
### Complete Form Example
|
|
159
|
+
|
|
160
|
+
```svelte
|
|
161
|
+
<script>
|
|
162
|
+
import FormField from '@ticatec/uniface-element/form-field';
|
|
163
|
+
import TextEditor from '@ticatec/uniface-element/text-editor';
|
|
164
|
+
import DatePicker from '@ticatec/uniface-element/date-picker';
|
|
165
|
+
import MemoEditor from '@ticatec/uniface-element/memo-editor';
|
|
166
|
+
|
|
167
|
+
let formData = {
|
|
168
|
+
name: '',
|
|
169
|
+
email: '',
|
|
170
|
+
dateOfBirth: null,
|
|
171
|
+
notes: ''
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
let errors = {};
|
|
175
|
+
|
|
176
|
+
function validateForm() {
|
|
177
|
+
errors = {};
|
|
178
|
+
|
|
179
|
+
if (!formData.name) {
|
|
180
|
+
errors.name = 'Name is required';
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
if (!formData.email) {
|
|
184
|
+
errors.email = 'Email is required';
|
|
185
|
+
} else if (!/\S+@\S+\.\S+/.test(formData.email)) {
|
|
186
|
+
errors.email = 'Please enter a valid email address';
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
return Object.keys(errors).length === 0;
|
|
190
|
+
}
|
|
191
|
+
</script>
|
|
192
|
+
|
|
193
|
+
<form on:submit|preventDefault={validateForm}>
|
|
194
|
+
<FormField required label="Full Name" error={errors.name}>
|
|
195
|
+
<TextEditor
|
|
196
|
+
variant="filled"
|
|
197
|
+
bind:value={formData.name}
|
|
198
|
+
placeholder="Enter your full name"
|
|
199
|
+
/>
|
|
200
|
+
</FormField>
|
|
201
|
+
|
|
202
|
+
<FormField required label="Email Address" error={errors.email}>
|
|
203
|
+
<TextEditor
|
|
204
|
+
variant="filled"
|
|
205
|
+
bind:value={formData.email}
|
|
206
|
+
placeholder="Enter your email"
|
|
207
|
+
/>
|
|
208
|
+
</FormField>
|
|
209
|
+
|
|
210
|
+
<div class="field-layout-horizontal">
|
|
211
|
+
<FormField label="Date of Birth">
|
|
212
|
+
<DatePicker variant="filled" bind:value={formData.dateOfBirth} />
|
|
213
|
+
</FormField>
|
|
214
|
+
</div>
|
|
215
|
+
|
|
216
|
+
<FormField label="Additional Notes" label$alignment="top">
|
|
217
|
+
<MemoEditor
|
|
218
|
+
variant="filled"
|
|
219
|
+
bind:value={formData.notes}
|
|
220
|
+
resize="vertical"
|
|
221
|
+
placeholder="Enter any additional notes..."
|
|
222
|
+
/>
|
|
223
|
+
</FormField>
|
|
224
|
+
|
|
225
|
+
<button type="submit">Submit</button>
|
|
226
|
+
</form>
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
### Responsive Form Layout
|
|
230
|
+
|
|
231
|
+
```svelte
|
|
232
|
+
<div class="responsive-form">
|
|
233
|
+
<div class="field-row">
|
|
234
|
+
<FormField label="First Name" error={errors.firstName}>
|
|
235
|
+
<TextEditor bind:value={formData.firstName} />
|
|
236
|
+
</FormField>
|
|
237
|
+
|
|
238
|
+
<FormField label="Last Name" error={errors.lastName}>
|
|
239
|
+
<TextEditor bind:value={formData.lastName} />
|
|
240
|
+
</FormField>
|
|
241
|
+
</div>
|
|
242
|
+
|
|
243
|
+
<FormField label="Email Address" error={errors.email}>
|
|
244
|
+
<TextEditor bind:value={formData.email} />
|
|
245
|
+
</FormField>
|
|
246
|
+
</div>
|
|
247
|
+
|
|
248
|
+
<style>
|
|
249
|
+
.responsive-form {
|
|
250
|
+
max-width: 600px;
|
|
251
|
+
margin: 0 auto;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
.field-row {
|
|
255
|
+
display: grid;
|
|
256
|
+
grid-template-columns: 1fr 1fr;
|
|
257
|
+
gap: 16px;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
@media (max-width: 768px) {
|
|
261
|
+
.field-row {
|
|
262
|
+
grid-template-columns: 1fr;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
</style>
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
## Best Practices
|
|
269
|
+
|
|
270
|
+
### 1. Consistent Labeling
|
|
271
|
+
|
|
272
|
+
Use consistent label formatting across your forms:
|
|
273
|
+
|
|
274
|
+
```svelte
|
|
275
|
+
<FormField label="First Name" labelSuffix="">
|
|
276
|
+
<TextEditor bind:value={firstName} />
|
|
277
|
+
</FormField>
|
|
278
|
+
|
|
279
|
+
<FormField label="Last Name" labelSuffix="">
|
|
280
|
+
<TextEditor bind:value={lastName} />
|
|
281
|
+
</FormField>
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
### 2. Required Field Indicators
|
|
285
|
+
|
|
286
|
+
Always mark required fields with the `required` prop:
|
|
287
|
+
|
|
288
|
+
```svelte
|
|
289
|
+
<FormField required label="Email">
|
|
290
|
+
<TextEditor bind:value={email} />
|
|
291
|
+
</FormField>
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
### 3. Error Handling
|
|
295
|
+
|
|
296
|
+
Provide clear, actionable error messages:
|
|
297
|
+
|
|
298
|
+
```svelte
|
|
299
|
+
<FormField
|
|
300
|
+
required
|
|
301
|
+
label="Password"
|
|
302
|
+
error={passwordError || (password && password.length < 8 ? 'Password must be at least 8 characters' : null)}
|
|
303
|
+
>
|
|
304
|
+
<TextEditor type="password" bind:value={password} />
|
|
305
|
+
</FormField>
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
### 4. Accessibility
|
|
309
|
+
|
|
310
|
+
Ensure proper form accessibility:
|
|
311
|
+
|
|
312
|
+
```svelte
|
|
313
|
+
<FormField
|
|
314
|
+
required
|
|
315
|
+
label="Username"
|
|
316
|
+
error={usernameError}
|
|
317
|
+
>
|
|
318
|
+
<TextEditor
|
|
319
|
+
bind:value={username}
|
|
320
|
+
input$aria-describedby={usernameError ? 'username-error' : undefined}
|
|
321
|
+
/>
|
|
322
|
+
</FormField>
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
### 5. Layout Considerations
|
|
326
|
+
|
|
327
|
+
Use horizontal layout for related fields:
|
|
328
|
+
|
|
329
|
+
```svelte
|
|
330
|
+
<div class="field-layout-horizontal">
|
|
331
|
+
<FormField label="Start Date">
|
|
332
|
+
<DatePicker bind:value={startDate} />
|
|
333
|
+
</FormField>
|
|
334
|
+
|
|
335
|
+
<FormField label="End Date">
|
|
336
|
+
<DatePicker bind:value={endDate} />
|
|
337
|
+
</FormField>
|
|
338
|
+
</div>
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
## Accessibility Features
|
|
342
|
+
|
|
343
|
+
- **Semantic HTML**: Uses proper form field structure
|
|
344
|
+
- **Required Indicators**: Visual asterisk for required fields
|
|
345
|
+
- **Error Association**: Error messages are properly associated with fields
|
|
346
|
+
- **Label Association**: Labels are semantically connected to form controls
|
|
347
|
+
- **Keyboard Navigation**: Supports standard form navigation patterns
|
|
348
|
+
|
|
349
|
+
## Browser Support
|
|
350
|
+
|
|
351
|
+
- **Modern Browsers**: Chrome, Firefox, Safari, Edge (latest versions)
|
|
352
|
+
- **Mobile Browsers**: iOS Safari, Chrome Mobile, Firefox Mobile
|
|
353
|
+
- **CSS Grid Support**: Required for layout functionality
|
|
354
|
+
|
|
355
|
+
## Related Components
|
|
356
|
+
|
|
357
|
+
- **TextEditor**: Single-line text input component
|
|
358
|
+
- **MemoEditor**: Multi-line text area component
|
|
359
|
+
- **DatePicker**: Date selection component
|
|
360
|
+
- **DateTimePicker**: Date and time selection component
|
|
361
|
+
|
|
362
|
+
## License
|
|
363
|
+
|
|
364
|
+
MIT License - see LICENSE file for details.
|