@ticatec/uniface-element 0.2.0 → 0.2.2
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 +320 -1
- package/README_CN.md +392 -0
- package/dist/accordion/Accordion.svelte +1 -1
- package/dist/action-bar/ActionBar.svelte +7 -1
- package/dist/attachment-files/FileRender.svelte +1 -1
- package/dist/attachment-files/FileUploadBar.svelte +7 -6
- package/dist/attachment-files/FileUploadPanel.svelte +2 -2
- package/dist/base-calendar/DateContext.js +5 -4
- package/dist/base-calendar/YearPickupPanel.svelte +4 -4
- package/dist/card/Card.svelte +1 -1
- package/dist/card/Card.svelte.d.ts +1 -1
- package/dist/cascade-options-select/CascadeOptionSelect.svelte +2 -3
- package/dist/cascade-options-select/CascadeOptionSelect.svelte.d.ts +46 -1
- package/dist/cascade-options-select/CascadePanel.svelte +1 -1
- package/dist/checkbox/CheckBox.svelte +1 -1
- package/dist/color-picker/ColorPicker.svelte +9 -9
- package/dist/color-picker/ColorPicker.svelte.d.ts +0 -2
- package/dist/color-picker/ColorPickerPanel.svelte +11 -15
- package/dist/color-picker/ColorPickerPanel.svelte.d.ts +1 -1
- package/dist/common/CommonPicker.svelte +2 -2
- package/dist/common/CommonPicker.svelte.d.ts +1 -1
- package/dist/common/MouseClickHandler.d.ts +1 -1
- package/dist/common/Popover.svelte +28 -6
- package/dist/common/Popover.svelte.d.ts +9 -3
- package/dist/common/uniface-utils.js +6 -4
- package/dist/common-editor/CommonEditor.svelte +1 -1
- package/dist/common-editor/CommonEditor.svelte.d.ts +1 -1
- package/dist/common-editor/NumberInput.svelte +1 -1
- package/dist/common-editor/NumberInput.svelte.d.ts +1 -1
- package/dist/concise-data-table/ConciseListTable.svelte +7 -2
- package/dist/concise-data-table/ConciseListTable.svelte.d.ts +1 -0
- package/dist/concise-data-table/DataRow.svelte +1 -1
- package/dist/concise-data-table/TableOptions.d.ts +1 -1
- package/dist/data-table/DataTable.svelte +1 -1
- package/dist/data-table/parts/ActionsPanel.svelte +4 -3
- package/dist/data-table/parts/ActionsRow.svelte +3 -3
- package/dist/data-table/parts/ContentPanel.svelte +3 -2
- package/dist/data-table/parts/FixedColumnsPanel.svelte +0 -1
- package/dist/data-table/parts/FixedColumnsPanel.svelte.d.ts +1 -2
- package/dist/data-table/parts/FixedHeaderPanel.svelte +2 -2
- package/dist/data-table/parts/FixedRow.svelte +2 -1
- package/dist/data-table/parts/FixedRow.svelte.d.ts +1 -1
- package/dist/data-table/parts/HrefCell.svelte +23 -2
- package/dist/data-table/parts/PopupMenu.svelte +25 -2
- package/dist/data-table/parts/PopupMenu.svelte.d.ts +8 -1
- package/dist/date-picker/DatePicker.svelte +0 -1
- package/dist/date-picker/DateTimePicker.svelte +3 -3
- package/dist/date-picker/ScrollBar.svelte +4 -7
- package/dist/date-range/DateRangeEditor.svelte +1 -1
- package/dist/dialog/CommonDialog.svelte +8 -5
- package/dist/dialog/CommonDialog.svelte.d.ts +2 -1
- package/dist/dialog/Dialog.svelte +37 -12
- package/dist/dialog/Dialog.svelte.d.ts +4 -3
- package/dist/dialog/DialogBoard.svelte +11 -8
- package/dist/dialog/DialogWrapper.svelte +10 -0
- package/dist/{common-editor/DateInput.svelte.d.ts → dialog/DialogWrapper.svelte.d.ts} +6 -13
- package/dist/dialog/Dialogs.js +1 -1
- package/dist/dialog/ModalResult.d.ts +5 -0
- package/dist/dialog/ModalResult.js +5 -0
- package/dist/drawer/Drawer.svelte +1 -1
- package/dist/form-field/FormField.svelte +2 -1
- package/dist/form-field/FormField.svelte.d.ts +1 -0
- package/dist/form-panel/flex-row-form/FormContainer.svelte +1 -1
- package/dist/form-panel/grid-form/EmptyCell.svelte +8 -7
- package/dist/form-panel/grid-form/EmptyCell.svelte.d.ts +2 -2
- package/dist/form-panel/grid-form/GridField.svelte +1 -1
- package/dist/i18nRes/i18nRes.d.ts +2 -0
- package/dist/i18nRes/i18nRes.js +44 -0
- package/dist/i18nRes/index.d.ts +2 -0
- package/dist/i18nRes/index.js +2 -0
- package/dist/image-files/ImageFilesField.svelte +1 -1
- package/dist/indicator/IndicatorBoard.svelte +1 -1
- package/dist/inline-cell-editor/InvalidEditor.svelte +1 -0
- package/dist/input-options-select/InputOptionsSelect.svelte +6 -6
- package/dist/input-options-select/InputOptionsSelect.svelte.d.ts +1 -1
- package/dist/layout/flex/FlexBlock.svelte +1 -1
- package/dist/lookup-editor/LookupEditor.svelte +1 -1
- package/dist/memo-editor/MemoEditor.svelte +2 -2
- package/dist/message-box/IMessageBox.d.ts +2 -4
- package/dist/message-box/IMessageBox.js +4 -6
- package/dist/message-box/MessageBoxBoard.svelte +1 -3
- package/dist/options-multi-select/OptionsMultiSelect.svelte +1 -1
- package/dist/prompts-text-editor/PromptsTextEditor.svelte +2 -2
- package/dist/prompts-text-editor/PromptsTextEditor.svelte.d.ts +1 -1
- package/dist/property-editor/PropertyEditor.svelte +3 -3
- package/dist/text-editor/PasswordEditor.svelte +1 -1
- package/dist/transfer/Transfer.svelte +17 -12
- package/dist/transfer/Transfer.svelte.d.ts +0 -1
- package/dist/unit-number-editor/UnitNumberEditor.svelte +2 -2
- package/docs/buttons/cn/ActionBar.md +459 -0
- package/docs/buttons/cn/Button.md +228 -0
- package/docs/buttons/cn/IconButton.md +294 -0
- package/docs/buttons/cn/README.md +600 -0
- package/docs/buttons/cn/TextButton.md +163 -0
- package/docs/buttons/en/ActionBar.md +459 -0
- package/docs/buttons/en/Button.md +228 -0
- package/docs/buttons/en/IconButton.md +294 -0
- package/docs/buttons/en/README.md +600 -0
- package/docs/buttons/en/TextButton.md +163 -0
- package/docs/containers/cn/accordion.md +622 -0
- package/docs/containers/cn/box.md +445 -0
- package/docs/containers/cn/card.md +404 -0
- package/docs/containers/cn/page.md +576 -0
- package/docs/containers/cn/tabs.md +686 -0
- package/docs/containers/en/accordion.md +622 -0
- package/docs/containers/en/box.md +445 -0
- package/docs/containers/en/card.md +404 -0
- package/docs/containers/en/page.md +576 -0
- package/docs/containers/en/tabs.md +686 -0
- package/docs/data-display/cn/concise-data-table.md +731 -0
- package/docs/data-display/cn/listbox.md +786 -0
- package/docs/data-display/cn/treeview.md +863 -0
- package/docs/data-display/en/concise-data-table.md +732 -0
- package/docs/data-display/en/listbox.md +786 -0
- package/docs/data-display/en/treeview.md +863 -0
- package/docs/data-table/cn/README.md +596 -0
- package/docs/data-table/en/README.md +596 -0
- package/docs/dialog/cn/README.md +767 -0
- package/docs/dialog/en/README.md +767 -0
- package/docs/form/cn/README.md +847 -0
- package/docs/form/en/README.md +847 -0
- package/docs/form-components/cn/README.md +495 -0
- package/docs/form-components/cn/attachmentfilesfield.md +757 -0
- package/docs/form-components/cn/cascade-options-select.md +374 -0
- package/docs/form-components/cn/checkbox.md +58 -0
- package/docs/form-components/cn/date-picker.md +138 -0
- package/docs/form-components/cn/datetime-picker.md +228 -0
- package/docs/form-components/cn/group-checkbox.md +405 -0
- package/docs/form-components/cn/group-radiobox.md +525 -0
- package/docs/form-components/cn/imagefilesfield.md +651 -0
- package/docs/form-components/cn/input-options-select.md +250 -0
- package/docs/form-components/cn/lookup-editor.md +406 -0
- package/docs/form-components/cn/memoeditor.md +409 -0
- package/docs/form-components/cn/number-editor.md +261 -0
- package/docs/form-components/cn/options-multi-select.md +177 -0
- package/docs/form-components/cn/options-select.md +83 -0
- package/docs/form-components/cn/passwordeditor.md +538 -0
- package/docs/form-components/cn/prompts-text-editor.md +241 -0
- package/docs/form-components/cn/radiobutton.md +84 -0
- package/docs/form-components/cn/switch.md +178 -0
- package/docs/form-components/cn/text-editor.md +142 -0
- package/docs/form-components/cn/time-editor.md +159 -0
- package/docs/form-components/cn/unit-number-editor.md +164 -0
- package/docs/form-components/en/README.md +463 -0
- package/docs/form-components/en/attachmentfilesfield.md +757 -0
- package/docs/form-components/en/cascade-options-select.md +358 -0
- package/docs/form-components/en/checkbox.md +59 -0
- package/docs/form-components/en/date-picker.md +138 -0
- package/docs/form-components/en/datetime-picker.md +228 -0
- package/docs/form-components/en/group-checkbox.md +395 -0
- package/docs/form-components/en/group-radiobox.md +498 -0
- package/docs/form-components/en/imagefilesfield.md +651 -0
- package/docs/form-components/en/input-options-select.md +239 -0
- package/docs/form-components/en/lookup-editor.md +389 -0
- package/docs/form-components/en/memoeditor.md +409 -0
- package/docs/form-components/en/number-editor.md +249 -0
- package/docs/form-components/en/options-multi-select.md +177 -0
- package/docs/form-components/en/options-select.md +83 -0
- package/docs/form-components/en/passwordeditor.md +538 -0
- package/docs/form-components/en/prompts-text-editor.md +241 -0
- package/docs/form-components/en/radiobutton.md +84 -0
- package/docs/form-components/en/switch.md +180 -0
- package/docs/form-components/en/text-editor.md +142 -0
- package/docs/form-components/en/time-editor.md +159 -0
- package/docs/form-components/en/unit-number-editor.md +164 -0
- package/docs/form-layout/cn/criteria-field.md +652 -0
- package/docs/form-layout/cn/flex-form.md +454 -0
- package/docs/form-layout/cn/flex-row-form.md +542 -0
- package/docs/form-layout/cn/form-field.md +923 -0
- package/docs/form-layout/cn/grid-form.md +676 -0
- package/docs/form-layout/en/criteria-field.md +652 -0
- package/docs/form-layout/en/flex-form.md +454 -0
- package/docs/form-layout/en/flex-row-form.md +542 -0
- package/docs/form-layout/en/form-field.md +923 -0
- package/docs/form-layout/en/grid-form.md +676 -0
- package/docs/global/cn/README.md +534 -0
- package/docs/global/en/README.md +534 -0
- package/docs/layout/cn/classiclayout.md +460 -0
- package/docs/layout/cn/headerlayout.md +524 -0
- package/docs/layout/cn/sidebarlayout.md +263 -0
- package/docs/layout/en/classiclayout.md +951 -0
- package/docs/layout/en/headerlayout.md +524 -0
- package/docs/layout/en/sidebarlayout.md +262 -0
- package/docs/misc/cn/README.md +1217 -0
- package/docs/misc/en/README.md +1217 -0
- package/docs/navigation/cn/breadcrumb.md +291 -0
- package/docs/navigation/cn/navigator.md +322 -0
- package/docs/navigation/cn/navigatormenu.md +512 -0
- package/docs/navigation/cn/progressbar.md +199 -0
- package/docs/navigation/cn/progressstepbar.md +299 -0
- package/docs/navigation/en/breadcrumb.md +291 -0
- package/docs/navigation/en/navigator.md +322 -0
- package/docs/navigation/en/navigatormenu.md +512 -0
- package/docs/navigation/en/progressbar.md +199 -0
- package/docs/navigation/en/progressstepbar.md +299 -0
- package/docs/search-filters/cn/daterange.md +1156 -0
- package/docs/search-filters/cn/numberrange.md +688 -0
- package/docs/search-filters/cn/searchbox.md +1582 -0
- package/docs/search-filters/en/daterange.md +1156 -0
- package/docs/search-filters/en/numberrange.md +688 -0
- package/docs/search-filters/en/searchbox.md +1582 -0
- package/package.json +53 -13
- package/dist/common-editor/DateInput.svelte +0 -27
- package/dist/i18n_resources/index.d.ts +0 -3
- package/dist/i18n_resources/index.js +0 -3
- /package/dist/{i18n_resources → i18nRes}/uniface_cn_resource.d.ts +0 -0
- /package/dist/{i18n_resources → i18nRes}/uniface_cn_resource.js +0 -0
- /package/dist/{i18n_resources → i18nRes}/uniface_en_resource.d.ts +0 -0
- /package/dist/{i18n_resources → i18nRes}/uniface_en_resource.js +0 -0
|
@@ -0,0 +1,923 @@
|
|
|
1
|
+
# FormField Component
|
|
2
|
+
|
|
3
|
+
Form field component providing a form field container with label, error messages, and required indicators - the core component for form building.
|
|
4
|
+
|
|
5
|
+
## Properties
|
|
6
|
+
|
|
7
|
+
| Property | Type | Default | Description |
|
|
8
|
+
|----------|------|---------|-------------|
|
|
9
|
+
| `label` | `string` | `'Label:'` | Field label text |
|
|
10
|
+
| `style` | `string` | `''` | Custom styles |
|
|
11
|
+
| `label$style` | `string \| null` | `null` | Label styles |
|
|
12
|
+
| `required` | `boolean` | `false` | Whether field is required |
|
|
13
|
+
| `error` | `string \| null` | `null` | Error message |
|
|
14
|
+
| `labelSuffix` | `string` | `':'` | Label suffix |
|
|
15
|
+
| `label$alignment` | `'center' \| 'top'` | `'center'` | Label alignment |
|
|
16
|
+
| `class` | `string` | `''` | CSS class name |
|
|
17
|
+
|
|
18
|
+
## Usage Examples
|
|
19
|
+
|
|
20
|
+
### Basic Form Fields
|
|
21
|
+
|
|
22
|
+
```svelte
|
|
23
|
+
<script lang="ts">
|
|
24
|
+
import FormField, TextEditor, NumberEditor, DatePicker from '@ticatec/uniface-element/FormField, TextEditor, NumberEditor, DatePicker';
|
|
25
|
+
|
|
26
|
+
interface UserForm {
|
|
27
|
+
name: string;
|
|
28
|
+
age: number | null;
|
|
29
|
+
email: string;
|
|
30
|
+
birthDate: Date | null;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
let userForm: UserForm = {
|
|
34
|
+
name: '',
|
|
35
|
+
age: null,
|
|
36
|
+
email: '',
|
|
37
|
+
birthDate: null
|
|
38
|
+
};
|
|
39
|
+
</script>
|
|
40
|
+
|
|
41
|
+
<!-- Basic field -->
|
|
42
|
+
<FormField label="Name">
|
|
43
|
+
<TextEditor
|
|
44
|
+
variant="outlined"
|
|
45
|
+
bind:value={userForm.name}
|
|
46
|
+
placeholder="Enter name"
|
|
47
|
+
/>
|
|
48
|
+
</FormField>
|
|
49
|
+
|
|
50
|
+
<!-- Number field -->
|
|
51
|
+
<FormField label="Age">
|
|
52
|
+
<NumberEditor
|
|
53
|
+
variant="outlined"
|
|
54
|
+
bind:value={userForm.age}
|
|
55
|
+
min={1}
|
|
56
|
+
max={120}
|
|
57
|
+
placeholder="Enter age"
|
|
58
|
+
/>
|
|
59
|
+
</FormField>
|
|
60
|
+
|
|
61
|
+
<!-- Email field -->
|
|
62
|
+
<FormField label="Email">
|
|
63
|
+
<TextEditor
|
|
64
|
+
variant="outlined"
|
|
65
|
+
bind:value={userForm.email}
|
|
66
|
+
placeholder="Enter email address"
|
|
67
|
+
/>
|
|
68
|
+
</FormField>
|
|
69
|
+
|
|
70
|
+
<!-- Date field -->
|
|
71
|
+
<FormField label="Birth Date">
|
|
72
|
+
<DatePicker variant="outlined" bind:value={userForm.birthDate} />
|
|
73
|
+
</FormField>
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### Required Fields and Validation
|
|
77
|
+
|
|
78
|
+
```svelte
|
|
79
|
+
<script lang="ts">
|
|
80
|
+
import FormField, TextEditor, OptionsSelect from '@ticatec/uniface-element/FormField, TextEditor, OptionsSelect';
|
|
81
|
+
|
|
82
|
+
interface RegistrationForm {
|
|
83
|
+
username: string;
|
|
84
|
+
password: string;
|
|
85
|
+
email: string;
|
|
86
|
+
gender: string;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
let registrationForm: RegistrationForm = {
|
|
90
|
+
username: '',
|
|
91
|
+
password: '',
|
|
92
|
+
email: '',
|
|
93
|
+
gender: ''
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
let errors: Record<string, string> = {};
|
|
97
|
+
|
|
98
|
+
const genderOptions = [
|
|
99
|
+
{ code: 'male', text: 'Male' },
|
|
100
|
+
{ code: 'female', text: 'Female' },
|
|
101
|
+
{ code: 'other', text: 'Other' }
|
|
102
|
+
];
|
|
103
|
+
|
|
104
|
+
const validateForm = (): void => {
|
|
105
|
+
errors = {};
|
|
106
|
+
|
|
107
|
+
if (!registrationForm.username) {
|
|
108
|
+
errors.username = 'Username is required';
|
|
109
|
+
} else if (registrationForm.username.length < 3) {
|
|
110
|
+
errors.username = 'Username must be at least 3 characters';
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if (!registrationForm.password) {
|
|
114
|
+
errors.password = 'Password is required';
|
|
115
|
+
} else if (registrationForm.password.length < 8) {
|
|
116
|
+
errors.password = 'Password must be at least 8 characters';
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
if (!registrationForm.email) {
|
|
120
|
+
errors.email = 'Email is required';
|
|
121
|
+
} else if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(registrationForm.email)) {
|
|
122
|
+
errors.email = 'Please enter a valid email address';
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
const handleSubmit = (): void => {
|
|
127
|
+
validateForm();
|
|
128
|
+
if (Object.keys(errors).length === 0) {
|
|
129
|
+
console.log('Form submitted successfully', registrationForm);
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
</script>
|
|
133
|
+
|
|
134
|
+
<div class="registration-form">
|
|
135
|
+
<h3>User Registration</h3>
|
|
136
|
+
|
|
137
|
+
<!-- Required username field -->
|
|
138
|
+
<FormField required label="Username" error={errors.username}>
|
|
139
|
+
<TextEditor
|
|
140
|
+
variant="outlined"
|
|
141
|
+
bind:value={registrationForm.username}
|
|
142
|
+
placeholder="Enter username"
|
|
143
|
+
on:input={() => errors.username = ''}
|
|
144
|
+
/>
|
|
145
|
+
</FormField>
|
|
146
|
+
|
|
147
|
+
<!-- Required password field -->
|
|
148
|
+
<FormField required label="Password" error={errors.password}>
|
|
149
|
+
<TextEditor
|
|
150
|
+
variant="outlined"
|
|
151
|
+
type="password"
|
|
152
|
+
bind:value={registrationForm.password}
|
|
153
|
+
placeholder="Enter password"
|
|
154
|
+
on:input={() => errors.password = ''}
|
|
155
|
+
/>
|
|
156
|
+
</FormField>
|
|
157
|
+
|
|
158
|
+
<!-- Required email field -->
|
|
159
|
+
<FormField required label="Email Address" error={errors.email}>
|
|
160
|
+
<TextEditor
|
|
161
|
+
variant="outlined"
|
|
162
|
+
bind:value={registrationForm.email}
|
|
163
|
+
placeholder="Enter email address"
|
|
164
|
+
on:input={() => errors.email = ''}
|
|
165
|
+
/>
|
|
166
|
+
</FormField>
|
|
167
|
+
|
|
168
|
+
<!-- Optional gender field -->
|
|
169
|
+
<FormField label="Gender">
|
|
170
|
+
<OptionsSelect
|
|
171
|
+
variant="outlined"
|
|
172
|
+
options={genderOptions}
|
|
173
|
+
keyField="code"
|
|
174
|
+
textField="text"
|
|
175
|
+
bind:value={registrationForm.gender}
|
|
176
|
+
placeholder="Select gender"
|
|
177
|
+
/>
|
|
178
|
+
</FormField>
|
|
179
|
+
|
|
180
|
+
<div class="form-actions">
|
|
181
|
+
<button type="button" class="btn-primary" on:click={handleSubmit}>
|
|
182
|
+
Register
|
|
183
|
+
</button>
|
|
184
|
+
</div>
|
|
185
|
+
</div>
|
|
186
|
+
|
|
187
|
+
<style>
|
|
188
|
+
.registration-form {
|
|
189
|
+
max-width: 400px;
|
|
190
|
+
margin: 0 auto;
|
|
191
|
+
padding: 30px;
|
|
192
|
+
background: #f8f9fa;
|
|
193
|
+
border-radius: 8px;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
.registration-form h3 {
|
|
197
|
+
margin-bottom: 25px;
|
|
198
|
+
text-align: center;
|
|
199
|
+
color: #495057;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
.form-actions {
|
|
203
|
+
margin-top: 25px;
|
|
204
|
+
text-align: center;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
.btn-primary {
|
|
208
|
+
padding: 12px 40px;
|
|
209
|
+
background: #007bff;
|
|
210
|
+
color: white;
|
|
211
|
+
border: none;
|
|
212
|
+
border-radius: 4px;
|
|
213
|
+
font-size: 16px;
|
|
214
|
+
cursor: pointer;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
.btn-primary:hover {
|
|
218
|
+
background: #0056b3;
|
|
219
|
+
}
|
|
220
|
+
</style>
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
### Custom Label Styles and Alignment
|
|
224
|
+
|
|
225
|
+
```svelte
|
|
226
|
+
<script lang="ts">
|
|
227
|
+
import FormField, TextEditor, MemoEditor from '@ticatec/uniface-element/FormField, TextEditor, MemoEditor';
|
|
228
|
+
|
|
229
|
+
let contactData = {
|
|
230
|
+
name: '',
|
|
231
|
+
company: '',
|
|
232
|
+
position: '',
|
|
233
|
+
description: ''
|
|
234
|
+
};
|
|
235
|
+
</script>
|
|
236
|
+
|
|
237
|
+
<div class="contact-form">
|
|
238
|
+
<h3>Contact Information</h3>
|
|
239
|
+
|
|
240
|
+
<!-- Important field label style -->
|
|
241
|
+
<FormField
|
|
242
|
+
required
|
|
243
|
+
label="Name"
|
|
244
|
+
label$style="color: #dc3545; font-weight: 600; font-size: 16px;"
|
|
245
|
+
labelSuffix="*"
|
|
246
|
+
>
|
|
247
|
+
<TextEditor
|
|
248
|
+
variant="outlined"
|
|
249
|
+
bind:value={contactData.name}
|
|
250
|
+
placeholder="Enter contact name"
|
|
251
|
+
/>
|
|
252
|
+
</FormField>
|
|
253
|
+
|
|
254
|
+
<!-- Regular field label style -->
|
|
255
|
+
<FormField
|
|
256
|
+
label="Company Name"
|
|
257
|
+
label$style="color: #28a745; font-weight: 500;"
|
|
258
|
+
>
|
|
259
|
+
<TextEditor
|
|
260
|
+
variant="outlined"
|
|
261
|
+
bind:value={contactData.company}
|
|
262
|
+
placeholder="Enter company name"
|
|
263
|
+
/>
|
|
264
|
+
</FormField>
|
|
265
|
+
|
|
266
|
+
<!-- Custom label color -->
|
|
267
|
+
<FormField
|
|
268
|
+
label="Position"
|
|
269
|
+
label$style="color: #6f42c1; font-style: italic;"
|
|
270
|
+
>
|
|
271
|
+
<TextEditor
|
|
272
|
+
variant="outlined"
|
|
273
|
+
bind:value={contactData.position}
|
|
274
|
+
placeholder="Enter position"
|
|
275
|
+
/>
|
|
276
|
+
</FormField>
|
|
277
|
+
|
|
278
|
+
<!-- Top-aligned multiline text -->
|
|
279
|
+
<FormField
|
|
280
|
+
label="Detailed Description"
|
|
281
|
+
label$alignment="top"
|
|
282
|
+
label$style="color: #495057; font-weight: 500; padding-top: 8px;"
|
|
283
|
+
>
|
|
284
|
+
<MemoEditor
|
|
285
|
+
variant="outlined"
|
|
286
|
+
bind:value={contactData.description}
|
|
287
|
+
placeholder="Enter detailed description"
|
|
288
|
+
rows={4}
|
|
289
|
+
maxLength={500}
|
|
290
|
+
showIndicator
|
|
291
|
+
/>
|
|
292
|
+
</FormField>
|
|
293
|
+
</div>
|
|
294
|
+
|
|
295
|
+
<style>
|
|
296
|
+
.contact-form {
|
|
297
|
+
max-width: 600px;
|
|
298
|
+
margin: 0 auto;
|
|
299
|
+
padding: 30px;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
.contact-form h3 {
|
|
303
|
+
margin-bottom: 25px;
|
|
304
|
+
color: #495057;
|
|
305
|
+
border-bottom: 2px solid #007bff;
|
|
306
|
+
padding-bottom: 10px;
|
|
307
|
+
}
|
|
308
|
+
</style>
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
### Long Label Text Handling
|
|
312
|
+
|
|
313
|
+
```svelte
|
|
314
|
+
<script lang="ts">
|
|
315
|
+
import FormField, TextEditor, CheckBox from '@ticatec/uniface-element/FormField, TextEditor, CheckBox';
|
|
316
|
+
|
|
317
|
+
let advancedSettings = {
|
|
318
|
+
serverEndpoint: '',
|
|
319
|
+
apiKey: '',
|
|
320
|
+
enableLogging: false,
|
|
321
|
+
autoRetry: false
|
|
322
|
+
};
|
|
323
|
+
</script>
|
|
324
|
+
|
|
325
|
+
<div class="settings-form">
|
|
326
|
+
<h3>Advanced Settings</h3>
|
|
327
|
+
|
|
328
|
+
<!-- Long label with automatic ellipsis -->
|
|
329
|
+
<FormField
|
|
330
|
+
label="Server Endpoint URL Address (supports HTTP and HTTPS protocols)"
|
|
331
|
+
required
|
|
332
|
+
>
|
|
333
|
+
<TextEditor
|
|
334
|
+
variant="outlined"
|
|
335
|
+
bind:value={advancedSettings.serverEndpoint}
|
|
336
|
+
placeholder="Enter server endpoint URL"
|
|
337
|
+
/>
|
|
338
|
+
</FormField>
|
|
339
|
+
|
|
340
|
+
<!-- Long label with custom style -->
|
|
341
|
+
<FormField
|
|
342
|
+
label="API Key (for authentication and access control)"
|
|
343
|
+
label$style="font-size: 14px; line-height: 1.2; white-space: normal;"
|
|
344
|
+
required
|
|
345
|
+
>
|
|
346
|
+
<TextEditor
|
|
347
|
+
variant="outlined"
|
|
348
|
+
type="password"
|
|
349
|
+
bind:value={advancedSettings.apiKey}
|
|
350
|
+
placeholder="Enter API key"
|
|
351
|
+
/>
|
|
352
|
+
</FormField>
|
|
353
|
+
|
|
354
|
+
<!-- Switch type field -->
|
|
355
|
+
<FormField label="Enable Detailed Logging Feature" labelSuffix="">
|
|
356
|
+
<CheckBox
|
|
357
|
+
label="Log all API requests and response details"
|
|
358
|
+
bind:value={advancedSettings.enableLogging}
|
|
359
|
+
/>
|
|
360
|
+
</FormField>
|
|
361
|
+
|
|
362
|
+
<!-- Switch type field -->
|
|
363
|
+
<FormField label="Enable Auto Retry Mechanism" labelSuffix="">
|
|
364
|
+
<CheckBox
|
|
365
|
+
label="Automatically retry up to 3 times when request fails"
|
|
366
|
+
bind:value={advancedSettings.autoRetry}
|
|
367
|
+
/>
|
|
368
|
+
</FormField>
|
|
369
|
+
</div>
|
|
370
|
+
|
|
371
|
+
<style>
|
|
372
|
+
.settings-form {
|
|
373
|
+
max-width: 700px;
|
|
374
|
+
margin: 0 auto;
|
|
375
|
+
padding: 30px;
|
|
376
|
+
background: white;
|
|
377
|
+
border-radius: 8px;
|
|
378
|
+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
.settings-form h3 {
|
|
382
|
+
margin-bottom: 25px;
|
|
383
|
+
color: #333;
|
|
384
|
+
font-size: 20px;
|
|
385
|
+
}
|
|
386
|
+
</style>
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
### Combined Form Field Usage
|
|
390
|
+
|
|
391
|
+
```svelte
|
|
392
|
+
<script lang="ts">
|
|
393
|
+
import FormField, TextEditor, NumberEditor, DatePicker, OptionsSelect, CheckBox from '@ticatec/uniface-element/FormField, TextEditor, NumberEditor, DatePicker, OptionsSelect, CheckBox';
|
|
394
|
+
|
|
395
|
+
interface EmployeeForm {
|
|
396
|
+
personalInfo: {
|
|
397
|
+
firstName: string;
|
|
398
|
+
lastName: string;
|
|
399
|
+
email: string;
|
|
400
|
+
phone: string;
|
|
401
|
+
birthDate: Date | null;
|
|
402
|
+
};
|
|
403
|
+
workInfo: {
|
|
404
|
+
employeeId: string;
|
|
405
|
+
department: string;
|
|
406
|
+
position: string;
|
|
407
|
+
salary: number | null;
|
|
408
|
+
startDate: Date | null;
|
|
409
|
+
};
|
|
410
|
+
settings: {
|
|
411
|
+
receiveEmails: boolean;
|
|
412
|
+
isManager: boolean;
|
|
413
|
+
};
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
let employeeForm: EmployeeForm = {
|
|
417
|
+
personalInfo: {
|
|
418
|
+
firstName: '',
|
|
419
|
+
lastName: '',
|
|
420
|
+
email: '',
|
|
421
|
+
phone: '',
|
|
422
|
+
birthDate: null
|
|
423
|
+
},
|
|
424
|
+
workInfo: {
|
|
425
|
+
employeeId: '',
|
|
426
|
+
department: '',
|
|
427
|
+
position: '',
|
|
428
|
+
salary: null,
|
|
429
|
+
startDate: null
|
|
430
|
+
},
|
|
431
|
+
settings: {
|
|
432
|
+
receiveEmails: true,
|
|
433
|
+
isManager: false
|
|
434
|
+
}
|
|
435
|
+
};
|
|
436
|
+
|
|
437
|
+
let validationErrors: Record<string, string> = {};
|
|
438
|
+
|
|
439
|
+
const departments = [
|
|
440
|
+
{ code: 'engineering', text: 'Engineering' },
|
|
441
|
+
{ code: 'marketing', text: 'Marketing' },
|
|
442
|
+
{ code: 'sales', text: 'Sales' },
|
|
443
|
+
{ code: 'hr', text: 'Human Resources' }
|
|
444
|
+
];
|
|
445
|
+
|
|
446
|
+
const validateForm = (): boolean => {
|
|
447
|
+
validationErrors = {};
|
|
448
|
+
|
|
449
|
+
if (!employeeForm.personalInfo.firstName) {
|
|
450
|
+
validationErrors.firstName = 'First name is required';
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
if (!employeeForm.personalInfo.lastName) {
|
|
454
|
+
validationErrors.lastName = 'Last name is required';
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
if (!employeeForm.personalInfo.email) {
|
|
458
|
+
validationErrors.email = 'Email is required';
|
|
459
|
+
} else if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(employeeForm.personalInfo.email)) {
|
|
460
|
+
validationErrors.email = 'Please enter a valid email address';
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
if (!employeeForm.workInfo.employeeId) {
|
|
464
|
+
validationErrors.employeeId = 'Employee ID is required';
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
return Object.keys(validationErrors).length === 0;
|
|
468
|
+
};
|
|
469
|
+
|
|
470
|
+
const handleSave = (): void => {
|
|
471
|
+
if (validateForm()) {
|
|
472
|
+
console.log('Employee information saved successfully', employeeForm);
|
|
473
|
+
alert('Employee information has been saved');
|
|
474
|
+
}
|
|
475
|
+
};
|
|
476
|
+
|
|
477
|
+
const clearFieldError = (field: string): void => {
|
|
478
|
+
if (validationErrors[field]) {
|
|
479
|
+
validationErrors = { ...validationErrors };
|
|
480
|
+
delete validationErrors[field];
|
|
481
|
+
}
|
|
482
|
+
};
|
|
483
|
+
</script>
|
|
484
|
+
|
|
485
|
+
<div class="employee-form">
|
|
486
|
+
<h2>Employee Information Management</h2>
|
|
487
|
+
|
|
488
|
+
<!-- Personal Information Section -->
|
|
489
|
+
<section class="form-section">
|
|
490
|
+
<h3>Personal Information</h3>
|
|
491
|
+
|
|
492
|
+
<div class="form-row">
|
|
493
|
+
<div class="form-col">
|
|
494
|
+
<FormField required label="First Name" error={validationErrors.firstName}>
|
|
495
|
+
<TextEditor
|
|
496
|
+
variant="outlined"
|
|
497
|
+
bind:value={employeeForm.personalInfo.firstName}
|
|
498
|
+
placeholder="Enter first name"
|
|
499
|
+
on:input={() => clearFieldError('firstName')}
|
|
500
|
+
/>
|
|
501
|
+
</FormField>
|
|
502
|
+
</div>
|
|
503
|
+
|
|
504
|
+
<div class="form-col">
|
|
505
|
+
<FormField required label="Last Name" error={validationErrors.lastName}>
|
|
506
|
+
<TextEditor
|
|
507
|
+
variant="outlined"
|
|
508
|
+
bind:value={employeeForm.personalInfo.lastName}
|
|
509
|
+
placeholder="Enter last name"
|
|
510
|
+
on:input={() => clearFieldError('lastName')}
|
|
511
|
+
/>
|
|
512
|
+
</FormField>
|
|
513
|
+
</div>
|
|
514
|
+
</div>
|
|
515
|
+
|
|
516
|
+
<FormField required label="Email Address" error={validationErrors.email}>
|
|
517
|
+
<TextEditor
|
|
518
|
+
variant="outlined"
|
|
519
|
+
bind:value={employeeForm.personalInfo.email}
|
|
520
|
+
placeholder="Enter email address"
|
|
521
|
+
on:input={() => clearFieldError('email')}
|
|
522
|
+
/>
|
|
523
|
+
</FormField>
|
|
524
|
+
|
|
525
|
+
<FormField label="Phone Number">
|
|
526
|
+
<TextEditor
|
|
527
|
+
variant="outlined"
|
|
528
|
+
bind:value={employeeForm.personalInfo.phone}
|
|
529
|
+
placeholder="Enter phone number"
|
|
530
|
+
/>
|
|
531
|
+
</FormField>
|
|
532
|
+
|
|
533
|
+
<FormField label="Birth Date">
|
|
534
|
+
<DatePicker
|
|
535
|
+
variant="outlined"
|
|
536
|
+
bind:value={employeeForm.personalInfo.birthDate}
|
|
537
|
+
/>
|
|
538
|
+
</FormField>
|
|
539
|
+
</section>
|
|
540
|
+
|
|
541
|
+
<!-- Work Information Section -->
|
|
542
|
+
<section class="form-section">
|
|
543
|
+
<h3>Work Information</h3>
|
|
544
|
+
|
|
545
|
+
<FormField required label="Employee ID" error={validationErrors.employeeId}>
|
|
546
|
+
<TextEditor
|
|
547
|
+
variant="outlined"
|
|
548
|
+
bind:value={employeeForm.workInfo.employeeId}
|
|
549
|
+
placeholder="Enter employee ID"
|
|
550
|
+
on:input={() => clearFieldError('employeeId')}
|
|
551
|
+
/>
|
|
552
|
+
</FormField>
|
|
553
|
+
|
|
554
|
+
<div class="form-row">
|
|
555
|
+
<div class="form-col">
|
|
556
|
+
<FormField label="Department">
|
|
557
|
+
<OptionsSelect
|
|
558
|
+
variant="outlined"
|
|
559
|
+
options={departments}
|
|
560
|
+
keyField="code"
|
|
561
|
+
textField="text"
|
|
562
|
+
bind:value={employeeForm.workInfo.department}
|
|
563
|
+
placeholder="Select department"
|
|
564
|
+
/>
|
|
565
|
+
</FormField>
|
|
566
|
+
</div>
|
|
567
|
+
|
|
568
|
+
<div class="form-col">
|
|
569
|
+
<FormField label="Position">
|
|
570
|
+
<TextEditor
|
|
571
|
+
variant="outlined"
|
|
572
|
+
bind:value={employeeForm.workInfo.position}
|
|
573
|
+
placeholder="Enter position"
|
|
574
|
+
/>
|
|
575
|
+
</FormField>
|
|
576
|
+
</div>
|
|
577
|
+
</div>
|
|
578
|
+
|
|
579
|
+
<div class="form-row">
|
|
580
|
+
<div class="form-col">
|
|
581
|
+
<FormField label="Salary">
|
|
582
|
+
<NumberEditor
|
|
583
|
+
variant="outlined"
|
|
584
|
+
bind:value={employeeForm.workInfo.salary}
|
|
585
|
+
min={0}
|
|
586
|
+
precision={0}
|
|
587
|
+
placeholder="Enter salary"
|
|
588
|
+
/>
|
|
589
|
+
</FormField>
|
|
590
|
+
</div>
|
|
591
|
+
|
|
592
|
+
<div class="form-col">
|
|
593
|
+
<FormField label="Start Date">
|
|
594
|
+
<DatePicker
|
|
595
|
+
variant="outlined"
|
|
596
|
+
bind:value={employeeForm.workInfo.startDate}
|
|
597
|
+
/>
|
|
598
|
+
</FormField>
|
|
599
|
+
</div>
|
|
600
|
+
</div>
|
|
601
|
+
</section>
|
|
602
|
+
|
|
603
|
+
<!-- Settings Section -->
|
|
604
|
+
<section class="form-section">
|
|
605
|
+
<h3>Account Settings</h3>
|
|
606
|
+
|
|
607
|
+
<FormField label="Notification Preferences" labelSuffix="">
|
|
608
|
+
<CheckBox
|
|
609
|
+
label="Receive email notifications"
|
|
610
|
+
bind:value={employeeForm.settings.receiveEmails}
|
|
611
|
+
/>
|
|
612
|
+
</FormField>
|
|
613
|
+
|
|
614
|
+
<FormField label="Permission Settings" labelSuffix="">
|
|
615
|
+
<CheckBox
|
|
616
|
+
label="Administrator privileges"
|
|
617
|
+
bind:value={employeeForm.settings.isManager}
|
|
618
|
+
/>
|
|
619
|
+
</FormField>
|
|
620
|
+
</section>
|
|
621
|
+
|
|
622
|
+
<!-- Action Buttons -->
|
|
623
|
+
<div class="form-actions">
|
|
624
|
+
<button type="button" class="btn-secondary">
|
|
625
|
+
Cancel
|
|
626
|
+
</button>
|
|
627
|
+
<button type="button" class="btn-primary" on:click={handleSave}>
|
|
628
|
+
Save Employee Information
|
|
629
|
+
</button>
|
|
630
|
+
</div>
|
|
631
|
+
</div>
|
|
632
|
+
|
|
633
|
+
<style>
|
|
634
|
+
.employee-form {
|
|
635
|
+
max-width: 800px;
|
|
636
|
+
margin: 0 auto;
|
|
637
|
+
padding: 30px;
|
|
638
|
+
background: white;
|
|
639
|
+
border-radius: 12px;
|
|
640
|
+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
.employee-form h2 {
|
|
644
|
+
margin-bottom: 30px;
|
|
645
|
+
text-align: center;
|
|
646
|
+
color: #333;
|
|
647
|
+
font-size: 24px;
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
.form-section {
|
|
651
|
+
margin-bottom: 35px;
|
|
652
|
+
padding: 25px;
|
|
653
|
+
border: 1px solid #dee2e6;
|
|
654
|
+
border-radius: 8px;
|
|
655
|
+
background: #f8f9fa;
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
.form-section h3 {
|
|
659
|
+
margin: 0 0 20px 0;
|
|
660
|
+
color: #495057;
|
|
661
|
+
font-size: 18px;
|
|
662
|
+
border-bottom: 2px solid #007bff;
|
|
663
|
+
padding-bottom: 8px;
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
.form-row {
|
|
667
|
+
display: grid;
|
|
668
|
+
grid-template-columns: 1fr 1fr;
|
|
669
|
+
gap: 20px;
|
|
670
|
+
margin-bottom: 16px;
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
.form-col {
|
|
674
|
+
min-width: 0;
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
.form-actions {
|
|
678
|
+
display: flex;
|
|
679
|
+
gap: 15px;
|
|
680
|
+
justify-content: center;
|
|
681
|
+
padding-top: 25px;
|
|
682
|
+
border-top: 1px solid #dee2e6;
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
.btn-primary, .btn-secondary {
|
|
686
|
+
padding: 12px 24px;
|
|
687
|
+
border: none;
|
|
688
|
+
border-radius: 6px;
|
|
689
|
+
font-size: 14px;
|
|
690
|
+
font-weight: 500;
|
|
691
|
+
cursor: pointer;
|
|
692
|
+
transition: all 0.2s;
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
.btn-primary {
|
|
696
|
+
background: #007bff;
|
|
697
|
+
color: white;
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
.btn-secondary {
|
|
701
|
+
background: #6c757d;
|
|
702
|
+
color: white;
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
.btn-primary:hover {
|
|
706
|
+
background: #0056b3;
|
|
707
|
+
transform: translateY(-1px);
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
.btn-secondary:hover {
|
|
711
|
+
background: #545b62;
|
|
712
|
+
transform: translateY(-1px);
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
@media (max-width: 768px) {
|
|
716
|
+
.form-row {
|
|
717
|
+
grid-template-columns: 1fr;
|
|
718
|
+
gap: 16px;
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
.employee-form {
|
|
722
|
+
padding: 20px;
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
.form-section {
|
|
726
|
+
padding: 20px;
|
|
727
|
+
}
|
|
728
|
+
}
|
|
729
|
+
</style>
|
|
730
|
+
```
|
|
731
|
+
|
|
732
|
+
## Label Alignment
|
|
733
|
+
|
|
734
|
+
### Center Alignment (Default)
|
|
735
|
+
```svelte
|
|
736
|
+
<FormField label="Name" label$alignment="center">
|
|
737
|
+
<TextEditor />
|
|
738
|
+
</FormField>
|
|
739
|
+
```
|
|
740
|
+
|
|
741
|
+
### Top Alignment
|
|
742
|
+
```svelte
|
|
743
|
+
<!-- Suitable for multiline input controls -->
|
|
744
|
+
<FormField label="Detailed Description" label$alignment="top">
|
|
745
|
+
<MemoEditor rows={4} />
|
|
746
|
+
</FormField>
|
|
747
|
+
```
|
|
748
|
+
|
|
749
|
+
## Error Message Handling
|
|
750
|
+
|
|
751
|
+
```svelte
|
|
752
|
+
<script lang="ts">
|
|
753
|
+
let formData = { email: '' };
|
|
754
|
+
let errors: Record<string, string> = {};
|
|
755
|
+
|
|
756
|
+
const validateEmail = (): void => {
|
|
757
|
+
if (!formData.email) {
|
|
758
|
+
errors.email = 'Email is required';
|
|
759
|
+
} else if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(formData.email)) {
|
|
760
|
+
errors.email = 'Please enter a valid email address';
|
|
761
|
+
} else {
|
|
762
|
+
delete errors.email;
|
|
763
|
+
errors = { ...errors };
|
|
764
|
+
}
|
|
765
|
+
};
|
|
766
|
+
</script>
|
|
767
|
+
|
|
768
|
+
<FormField required label="Email" error={errors.email}>
|
|
769
|
+
<TextEditor
|
|
770
|
+
bind:value={formData.email}
|
|
771
|
+
on:blur={validateEmail}
|
|
772
|
+
/>
|
|
773
|
+
</FormField>
|
|
774
|
+
```
|
|
775
|
+
|
|
776
|
+
## Style Customization
|
|
777
|
+
|
|
778
|
+
```css
|
|
779
|
+
/* Form field container */
|
|
780
|
+
:global(.uniface-form-field) {
|
|
781
|
+
margin-bottom: 20px;
|
|
782
|
+
}
|
|
783
|
+
|
|
784
|
+
/* Form content area */
|
|
785
|
+
:global(.uniface-form-field .form-content) {
|
|
786
|
+
display: flex;
|
|
787
|
+
flex-direction: column;
|
|
788
|
+
gap: 8px;
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
/* Label styles */
|
|
792
|
+
:global(.uniface-form-field .field-label) {
|
|
793
|
+
font-weight: 500;
|
|
794
|
+
color: #495057;
|
|
795
|
+
margin-bottom: 4px;
|
|
796
|
+
}
|
|
797
|
+
|
|
798
|
+
/* Required indicator styles */
|
|
799
|
+
:global(.uniface-form-field .required-indicator) {
|
|
800
|
+
color: #dc3545;
|
|
801
|
+
margin-right: 4px;
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
/* Top-aligned label */
|
|
805
|
+
:global(.uniface-form-field .field-label.vert-top) {
|
|
806
|
+
align-self: flex-start;
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
/* Error message styles */
|
|
810
|
+
:global(.uniface-form-field .field-hint) {
|
|
811
|
+
color: #dc3545;
|
|
812
|
+
font-size: 12px;
|
|
813
|
+
margin-top: 4px;
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
/* Field content area */
|
|
817
|
+
:global(.uniface-form-field .field) {
|
|
818
|
+
flex: 1;
|
|
819
|
+
}
|
|
820
|
+
|
|
821
|
+
/* Horizontal layout styles */
|
|
822
|
+
:global(.field-layout-horizontal .uniface-form-field .form-content) {
|
|
823
|
+
flex-direction: row;
|
|
824
|
+
align-items: center;
|
|
825
|
+
gap: 12px;
|
|
826
|
+
}
|
|
827
|
+
|
|
828
|
+
:global(.field-layout-horizontal .uniface-form-field .field-label) {
|
|
829
|
+
flex-shrink: 0;
|
|
830
|
+
margin-bottom: 0;
|
|
831
|
+
min-width: 120px;
|
|
832
|
+
}
|
|
833
|
+
|
|
834
|
+
/* Responsive styles */
|
|
835
|
+
@media (max-width: 768px) {
|
|
836
|
+
:global(.field-layout-horizontal .uniface-form-field .form-content) {
|
|
837
|
+
flex-direction: column;
|
|
838
|
+
align-items: stretch;
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
:global(.field-layout-horizontal .uniface-form-field .field-label) {
|
|
842
|
+
min-width: auto;
|
|
843
|
+
margin-bottom: 4px;
|
|
844
|
+
}
|
|
845
|
+
}
|
|
846
|
+
```
|
|
847
|
+
|
|
848
|
+
## Best Practices
|
|
849
|
+
|
|
850
|
+
### 1. Use Required Indicators Appropriately
|
|
851
|
+
```svelte
|
|
852
|
+
<!-- Required fields -->
|
|
853
|
+
<FormField required label="Username">
|
|
854
|
+
<TextEditor />
|
|
855
|
+
</FormField>
|
|
856
|
+
|
|
857
|
+
<!-- Optional fields -->
|
|
858
|
+
<FormField label="Nickname">
|
|
859
|
+
<TextEditor />
|
|
860
|
+
</FormField>
|
|
861
|
+
```
|
|
862
|
+
|
|
863
|
+
### 2. Show Validation Errors Promptly
|
|
864
|
+
```svelte
|
|
865
|
+
<script lang="ts">
|
|
866
|
+
const clearError = (field: string): void => {
|
|
867
|
+
if (errors[field]) {
|
|
868
|
+
delete errors[field];
|
|
869
|
+
errors = { ...errors };
|
|
870
|
+
}
|
|
871
|
+
};
|
|
872
|
+
</script>
|
|
873
|
+
|
|
874
|
+
<FormField required label="Email" error={errors.email}>
|
|
875
|
+
<TextEditor
|
|
876
|
+
bind:value={formData.email}
|
|
877
|
+
on:input={() => clearError('email')}
|
|
878
|
+
/>
|
|
879
|
+
</FormField>
|
|
880
|
+
```
|
|
881
|
+
|
|
882
|
+
### 3. Choose Appropriate Label Alignment
|
|
883
|
+
```svelte
|
|
884
|
+
<!-- Single line input: use center alignment -->
|
|
885
|
+
<FormField label="Name" label$alignment="center">
|
|
886
|
+
<TextEditor />
|
|
887
|
+
</FormField>
|
|
888
|
+
|
|
889
|
+
<!-- Multiline input: use top alignment -->
|
|
890
|
+
<FormField label="Notes" label$alignment="top">
|
|
891
|
+
<MemoEditor rows={3} />
|
|
892
|
+
</FormField>
|
|
893
|
+
```
|
|
894
|
+
|
|
895
|
+
### 4. Customize Label Styles
|
|
896
|
+
```svelte
|
|
897
|
+
<!-- Highlight important fields -->
|
|
898
|
+
<FormField
|
|
899
|
+
required
|
|
900
|
+
label="Password"
|
|
901
|
+
label$style="color: #dc3545; font-weight: 600;"
|
|
902
|
+
>
|
|
903
|
+
<TextEditor type="password" />
|
|
904
|
+
</FormField>
|
|
905
|
+
|
|
906
|
+
<!-- De-emphasize secondary fields -->
|
|
907
|
+
<FormField
|
|
908
|
+
label="Notes"
|
|
909
|
+
label$style="color: #6c757d; font-size: 14px;"
|
|
910
|
+
>
|
|
911
|
+
<TextEditor />
|
|
912
|
+
</FormField>
|
|
913
|
+
```
|
|
914
|
+
|
|
915
|
+
## Component Advantages
|
|
916
|
+
|
|
917
|
+
1. **Complete Field Functionality** - Provides comprehensive field support with labels, required indicators, and error messages
|
|
918
|
+
2. **Flexible Layout Options** - Supports both center and top alignment for labels
|
|
919
|
+
3. **Rich Style Customization** - Supports customization of label styles, suffixes, and overall styling
|
|
920
|
+
4. **Comprehensive Validation Support** - Built-in error message display mechanism
|
|
921
|
+
5. **Responsive Friendly** - Supports responsive switching between horizontal and vertical layouts
|
|
922
|
+
6. **Easy Integration** - Seamlessly works with all form controls
|
|
923
|
+
7. **Consistency Assurance** - Unified field styling and behavior standards
|