@ticatec/uniface-element 0.2.0 → 0.2.1

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.
Files changed (126) hide show
  1. package/README.md +273 -1
  2. package/README_CN.md +341 -0
  3. package/dist/common/MouseClickHandler.d.ts +1 -1
  4. package/dist/dialog/CommonDialog.svelte +6 -3
  5. package/dist/dialog/CommonDialog.svelte.d.ts +2 -1
  6. package/dist/dialog/Dialog.svelte +36 -10
  7. package/dist/dialog/Dialog.svelte.d.ts +4 -3
  8. package/dist/dialog/DialogBoard.svelte +11 -8
  9. package/dist/dialog/DialogWrapper.svelte +10 -0
  10. package/dist/dialog/DialogWrapper.svelte.d.ts +22 -0
  11. package/dist/dialog/Dialogs.js +1 -1
  12. package/dist/dialog/ModalResult.d.ts +5 -0
  13. package/dist/dialog/ModalResult.js +5 -0
  14. package/docs/buttons/cn/ActionBar.md +459 -0
  15. package/docs/buttons/cn/Button.md +228 -0
  16. package/docs/buttons/cn/IconButton.md +294 -0
  17. package/docs/buttons/cn/README.md +600 -0
  18. package/docs/buttons/cn/TextButton.md +163 -0
  19. package/docs/buttons/en/ActionBar.md +459 -0
  20. package/docs/buttons/en/Button.md +228 -0
  21. package/docs/buttons/en/IconButton.md +294 -0
  22. package/docs/buttons/en/README.md +600 -0
  23. package/docs/buttons/en/TextButton.md +163 -0
  24. package/docs/containers/cn/accordion.md +622 -0
  25. package/docs/containers/cn/box.md +445 -0
  26. package/docs/containers/cn/card.md +404 -0
  27. package/docs/containers/cn/page.md +576 -0
  28. package/docs/containers/cn/tabs.md +686 -0
  29. package/docs/containers/en/accordion.md +622 -0
  30. package/docs/containers/en/box.md +445 -0
  31. package/docs/containers/en/card.md +404 -0
  32. package/docs/containers/en/page.md +576 -0
  33. package/docs/containers/en/tabs.md +686 -0
  34. package/docs/data-display/cn/concise-data-table.md +731 -0
  35. package/docs/data-display/cn/listbox.md +786 -0
  36. package/docs/data-display/cn/treeview.md +863 -0
  37. package/docs/data-display/en/concise-data-table.md +732 -0
  38. package/docs/data-display/en/listbox.md +786 -0
  39. package/docs/data-display/en/treeview.md +863 -0
  40. package/docs/data-table/cn/README.md +596 -0
  41. package/docs/data-table/en/README.md +596 -0
  42. package/docs/dialog/cn/README.md +767 -0
  43. package/docs/dialog/en/README.md +767 -0
  44. package/docs/form/cn/README.md +847 -0
  45. package/docs/form/en/README.md +847 -0
  46. package/docs/form-components/cn/README.md +495 -0
  47. package/docs/form-components/cn/attachmentfilesfield.md +757 -0
  48. package/docs/form-components/cn/cascade-options-select.md +374 -0
  49. package/docs/form-components/cn/checkbox.md +58 -0
  50. package/docs/form-components/cn/date-picker.md +138 -0
  51. package/docs/form-components/cn/datetime-picker.md +228 -0
  52. package/docs/form-components/cn/group-checkbox.md +405 -0
  53. package/docs/form-components/cn/group-radiobox.md +525 -0
  54. package/docs/form-components/cn/imagefilesfield.md +651 -0
  55. package/docs/form-components/cn/input-options-select.md +250 -0
  56. package/docs/form-components/cn/lookup-editor.md +406 -0
  57. package/docs/form-components/cn/memoeditor.md +409 -0
  58. package/docs/form-components/cn/number-editor.md +261 -0
  59. package/docs/form-components/cn/options-multi-select.md +177 -0
  60. package/docs/form-components/cn/options-select.md +83 -0
  61. package/docs/form-components/cn/passwordeditor.md +538 -0
  62. package/docs/form-components/cn/prompts-text-editor.md +241 -0
  63. package/docs/form-components/cn/radiobutton.md +84 -0
  64. package/docs/form-components/cn/switch.md +178 -0
  65. package/docs/form-components/cn/text-editor.md +142 -0
  66. package/docs/form-components/cn/time-editor.md +159 -0
  67. package/docs/form-components/cn/unit-number-editor.md +164 -0
  68. package/docs/form-components/en/README.md +463 -0
  69. package/docs/form-components/en/attachmentfilesfield.md +757 -0
  70. package/docs/form-components/en/cascade-options-select.md +358 -0
  71. package/docs/form-components/en/checkbox.md +59 -0
  72. package/docs/form-components/en/date-picker.md +138 -0
  73. package/docs/form-components/en/datetime-picker.md +228 -0
  74. package/docs/form-components/en/group-checkbox.md +395 -0
  75. package/docs/form-components/en/group-radiobox.md +498 -0
  76. package/docs/form-components/en/imagefilesfield.md +651 -0
  77. package/docs/form-components/en/input-options-select.md +239 -0
  78. package/docs/form-components/en/lookup-editor.md +389 -0
  79. package/docs/form-components/en/memoeditor.md +409 -0
  80. package/docs/form-components/en/number-editor.md +249 -0
  81. package/docs/form-components/en/options-multi-select.md +177 -0
  82. package/docs/form-components/en/options-select.md +83 -0
  83. package/docs/form-components/en/passwordeditor.md +538 -0
  84. package/docs/form-components/en/prompts-text-editor.md +241 -0
  85. package/docs/form-components/en/radiobutton.md +84 -0
  86. package/docs/form-components/en/switch.md +180 -0
  87. package/docs/form-components/en/text-editor.md +142 -0
  88. package/docs/form-components/en/time-editor.md +159 -0
  89. package/docs/form-components/en/unit-number-editor.md +164 -0
  90. package/docs/form-layout/cn/criteria-field.md +652 -0
  91. package/docs/form-layout/cn/flex-form.md +454 -0
  92. package/docs/form-layout/cn/flex-row-form.md +542 -0
  93. package/docs/form-layout/cn/form-field.md +923 -0
  94. package/docs/form-layout/cn/grid-form.md +676 -0
  95. package/docs/form-layout/en/criteria-field.md +652 -0
  96. package/docs/form-layout/en/flex-form.md +454 -0
  97. package/docs/form-layout/en/flex-row-form.md +542 -0
  98. package/docs/form-layout/en/form-field.md +923 -0
  99. package/docs/form-layout/en/grid-form.md +676 -0
  100. package/docs/global/cn/README.md +534 -0
  101. package/docs/global/en/README.md +534 -0
  102. package/docs/layout/cn/classiclayout.md +460 -0
  103. package/docs/layout/cn/headerlayout.md +524 -0
  104. package/docs/layout/cn/sidebarlayout.md +263 -0
  105. package/docs/layout/en/classiclayout.md +951 -0
  106. package/docs/layout/en/headerlayout.md +524 -0
  107. package/docs/layout/en/sidebarlayout.md +262 -0
  108. package/docs/misc/cn/README.md +1217 -0
  109. package/docs/misc/en/README.md +1217 -0
  110. package/docs/navigation/cn/breadcrumb.md +291 -0
  111. package/docs/navigation/cn/navigator.md +322 -0
  112. package/docs/navigation/cn/navigatormenu.md +512 -0
  113. package/docs/navigation/cn/progressbar.md +199 -0
  114. package/docs/navigation/cn/progressstepbar.md +299 -0
  115. package/docs/navigation/en/breadcrumb.md +291 -0
  116. package/docs/navigation/en/navigator.md +322 -0
  117. package/docs/navigation/en/navigatormenu.md +512 -0
  118. package/docs/navigation/en/progressbar.md +199 -0
  119. package/docs/navigation/en/progressstepbar.md +299 -0
  120. package/docs/search-filters/cn/daterange.md +1156 -0
  121. package/docs/search-filters/cn/numberrange.md +688 -0
  122. package/docs/search-filters/cn/searchbox.md +1582 -0
  123. package/docs/search-filters/en/daterange.md +1156 -0
  124. package/docs/search-filters/en/numberrange.md +688 -0
  125. package/docs/search-filters/en/searchbox.md +1582 -0
  126. package/package.json +38 -5
@@ -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