@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,538 @@
1
+ # PasswordEditor Component
2
+
3
+ The PasswordEditor component provides a secure password input field with built-in visibility toggle functionality, allowing users to show/hide password content for better usability while maintaining security.
4
+
5
+ ## Features
6
+
7
+ - **Secure Password Input**: Standard password field with masked input
8
+ - **Visibility Toggle**: Eye icon to show/hide password text
9
+ - **CommonEditor Integration**: Built on the unified CommonEditor component
10
+ - **Variant Support**: Multiple styling variants (plain, outlined, filled)
11
+ - **State Management**: Handles readonly and disabled states appropriately
12
+ - **Event Forwarding**: Standard input events (blur, focus) are forwarded
13
+ - **Compact Mode**: Optional compact display mode
14
+
15
+ ## Import
16
+
17
+ ```typescript
18
+ import PasswordEditor from '@ticatec/uniface-element/PasswordEditor';
19
+ ```
20
+
21
+ ## Basic Usage
22
+
23
+ ### Simple Password Field
24
+
25
+ ```svelte
26
+ <script>
27
+ import PasswordEditor from '@ticatec/uniface-element/PasswordEditor';
28
+
29
+ let password = '';
30
+ </script>
31
+
32
+ <PasswordEditor
33
+ bind:value={password}
34
+ placeholder="Enter your password"
35
+ />
36
+ ```
37
+
38
+ ### Styled Password Field
39
+
40
+ ```svelte
41
+ <script>
42
+ import PasswordEditor from '@ticatec/uniface-element/PasswordEditor';
43
+
44
+ let userPassword = '';
45
+ </script>
46
+
47
+ <PasswordEditor
48
+ bind:value={userPassword}
49
+ variant="outlined"
50
+ placeholder="Password"
51
+ style="width: 300px;"
52
+ />
53
+ ```
54
+
55
+ ### Compact Password Field
56
+
57
+ ```svelte
58
+ <script>
59
+ import PasswordEditor from '@ticatec/uniface-element/PasswordEditor';
60
+
61
+ let pin = '';
62
+ </script>
63
+
64
+ <PasswordEditor
65
+ bind:value={pin}
66
+ compact={true}
67
+ variant="filled"
68
+ placeholder="PIN"
69
+ />
70
+ ```
71
+
72
+ ## API Reference
73
+
74
+ ### Props
75
+
76
+ | Property | Type | Default | Description |
77
+ |----------|------|---------|-------------|
78
+ | `value` | `string` | `''` | The password value |
79
+ | `disabled` | `boolean` | `false` | Whether the input is disabled |
80
+ | `readonly` | `boolean` | `false` | Whether the input is read-only |
81
+ | `variant` | `'' \| 'plain' \| 'outlined' \| 'filled'` | `''` | Visual variant |
82
+ | `compact` | `boolean` | `false` | Compact display mode |
83
+ | `style` | `string` | `''` | Additional CSS styles |
84
+
85
+ ### Events
86
+
87
+ - `on:blur` - Fired when input loses focus
88
+ - `on:focus` - Fired when input gains focus
89
+
90
+ ## Advanced Examples
91
+
92
+ ### Login Form
93
+
94
+ ```svelte
95
+ <script>
96
+ import PasswordEditor from '@ticatec/uniface-element/PasswordEditor';
97
+
98
+ let credentials = {
99
+ username: '',
100
+ password: ''
101
+ };
102
+
103
+ let loginError = '';
104
+ let isLoading = false;
105
+
106
+ const handleLogin = async () => {
107
+ if (!credentials.username || !credentials.password) {
108
+ loginError = 'Please enter both username and password';
109
+ return;
110
+ }
111
+
112
+ isLoading = true;
113
+ loginError = '';
114
+
115
+ try {
116
+ // Simulate login API call
117
+ await new Promise(resolve => setTimeout(resolve, 1000));
118
+
119
+ // Mock successful login
120
+ if (credentials.username === 'admin' && credentials.password === 'password123') {
121
+ alert('Login successful!');
122
+ credentials = { username: '', password: '' };
123
+ } else {
124
+ loginError = 'Invalid username or password';
125
+ }
126
+ } catch (error) {
127
+ loginError = 'Login failed. Please try again.';
128
+ } finally {
129
+ isLoading = false;
130
+ }
131
+ };
132
+
133
+ const handleKeyDown = (event) => {
134
+ if (event.key === 'Enter' && !isLoading) {
135
+ handleLogin();
136
+ }
137
+ };
138
+ </script>
139
+
140
+ <div class="login-form" style="max-width: 400px; margin: 50px auto; padding: 20px; border: 1px solid #ddd; border-radius: 8px;">
141
+ <h2 style="text-align: center; margin-bottom: 30px;">Login</h2>
142
+
143
+ <div class="form-field" style="margin-bottom: 20px;">
144
+ <label for="username" style="display: block; margin-bottom: 5px; font-weight: bold;">Username</label>
145
+ <input
146
+ id="username"
147
+ type="text"
148
+ bind:value={credentials.username}
149
+ placeholder="Enter username"
150
+ disabled={isLoading}
151
+ on:keydown={handleKeyDown}
152
+ style="width: 100%; padding: 10px; border: 1px solid #ccc; border-radius: 4px;"
153
+ />
154
+ </div>
155
+
156
+ <div class="form-field" style="margin-bottom: 20px;">
157
+ <label for="password" style="display: block; margin-bottom: 5px; font-weight: bold;">Password</label>
158
+ <PasswordEditor
159
+ bind:value={credentials.password}
160
+ variant="outlined"
161
+ disabled={isLoading}
162
+ placeholder="Enter password"
163
+ style="width: 100%;"
164
+ on:keydown={handleKeyDown}
165
+ />
166
+ </div>
167
+
168
+ {#if loginError}
169
+ <div class="error-message" style="color: #d32f2f; margin-bottom: 15px; font-size: 0.875em;">
170
+ {loginError}
171
+ </div>
172
+ {/if}
173
+
174
+ <button
175
+ on:click={handleLogin}
176
+ disabled={isLoading}
177
+ style="width: 100%; padding: 12px; background: #1976d2; color: white; border: none; border-radius: 4px; cursor: {isLoading ? 'not-allowed' : 'pointer'};"
178
+ >
179
+ {isLoading ? 'Logging in...' : 'Login'}
180
+ </button>
181
+ </div>
182
+ ```
183
+
184
+ ### Password Change Form
185
+
186
+ ```svelte
187
+ <script>
188
+ import PasswordEditor from '@ticatec/uniface-element/PasswordEditor';
189
+
190
+ let passwordForm = {
191
+ currentPassword: '',
192
+ newPassword: '',
193
+ confirmPassword: ''
194
+ };
195
+
196
+ let errors = {};
197
+ let showSuccess = false;
198
+
199
+ const validatePassword = (password) => {
200
+ if (password.length < 8) return 'Password must be at least 8 characters long';
201
+ if (!/(?=.*[a-z])/.test(password)) return 'Password must contain at least one lowercase letter';
202
+ if (!/(?=.*[A-Z])/.test(password)) return 'Password must contain at least one uppercase letter';
203
+ if (!/(?=.*\d)/.test(password)) return 'Password must contain at least one number';
204
+ if (!/(?=.*[@$!%*?&])/.test(password)) return 'Password must contain at least one special character';
205
+ return '';
206
+ };
207
+
208
+ const validateForm = () => {
209
+ errors = {};
210
+
211
+ if (!passwordForm.currentPassword) {
212
+ errors.currentPassword = 'Current password is required';
213
+ }
214
+
215
+ if (!passwordForm.newPassword) {
216
+ errors.newPassword = 'New password is required';
217
+ } else {
218
+ const passwordError = validatePassword(passwordForm.newPassword);
219
+ if (passwordError) errors.newPassword = passwordError;
220
+ }
221
+
222
+ if (!passwordForm.confirmPassword) {
223
+ errors.confirmPassword = 'Password confirmation is required';
224
+ } else if (passwordForm.newPassword !== passwordForm.confirmPassword) {
225
+ errors.confirmPassword = 'Passwords do not match';
226
+ }
227
+
228
+ return Object.keys(errors).length === 0;
229
+ };
230
+
231
+ const handleSubmit = () => {
232
+ if (validateForm()) {
233
+ // Simulate API call
234
+ setTimeout(() => {
235
+ showSuccess = true;
236
+ passwordForm = { currentPassword: '', newPassword: '', confirmPassword: '' };
237
+ setTimeout(() => showSuccess = false, 3000);
238
+ }, 500);
239
+ }
240
+ };
241
+
242
+ const handleFieldBlur = (field) => () => {
243
+ if (field === 'newPassword' && passwordForm.newPassword) {
244
+ const error = validatePassword(passwordForm.newPassword);
245
+ if (error) errors.newPassword = error;
246
+ else delete errors.newPassword;
247
+ errors = {...errors};
248
+ }
249
+
250
+ if (field === 'confirmPassword' && passwordForm.confirmPassword && passwordForm.newPassword) {
251
+ if (passwordForm.newPassword !== passwordForm.confirmPassword) {
252
+ errors.confirmPassword = 'Passwords do not match';
253
+ } else {
254
+ delete errors.confirmPassword;
255
+ }
256
+ errors = {...errors};
257
+ }
258
+ };
259
+ </script>
260
+
261
+ <div class="password-change-form" style="max-width: 500px; margin: 50px auto; padding: 30px; border: 1px solid #e0e0e0; border-radius: 8px; background: #fafafa;">
262
+ <h2 style="text-align: center; margin-bottom: 30px; color: #333;">Change Password</h2>
263
+
264
+ {#if showSuccess}
265
+ <div class="success-message" style="background: #d4edda; color: #155724; padding: 10px; border-radius: 4px; margin-bottom: 20px; text-align: center;">
266
+ Password changed successfully!
267
+ </div>
268
+ {/if}
269
+
270
+ <div class="form-field" style="margin-bottom: 25px;">
271
+ <label style="display: block; margin-bottom: 8px; font-weight: 600; color: #555;">Current Password</label>
272
+ <PasswordEditor
273
+ bind:value={passwordForm.currentPassword}
274
+ variant="outlined"
275
+ placeholder="Enter current password"
276
+ style="width: 100%;"
277
+ />
278
+ {#if errors.currentPassword}
279
+ <div class="field-error" style="color: #d32f2f; font-size: 0.875em; margin-top: 5px;">
280
+ {errors.currentPassword}
281
+ </div>
282
+ {/if}
283
+ </div>
284
+
285
+ <div class="form-field" style="margin-bottom: 25px;">
286
+ <label style="display: block; margin-bottom: 8px; font-weight: 600; color: #555;">New Password</label>
287
+ <PasswordEditor
288
+ bind:value={passwordForm.newPassword}
289
+ variant="outlined"
290
+ placeholder="Enter new password"
291
+ style="width: 100%;"
292
+ on:blur={handleFieldBlur('newPassword')}
293
+ />
294
+ {#if errors.newPassword}
295
+ <div class="field-error" style="color: #d32f2f; font-size: 0.875em; margin-top: 5px;">
296
+ {errors.newPassword}
297
+ </div>
298
+ {:else if passwordForm.newPassword}
299
+ <div class="password-requirements" style="font-size: 0.75em; color: #666; margin-top: 5px;">
300
+ Password must contain: 8+ characters, uppercase, lowercase, number, special character
301
+ </div>
302
+ {/if}
303
+ </div>
304
+
305
+ <div class="form-field" style="margin-bottom: 30px;">
306
+ <label style="display: block; margin-bottom: 8px; font-weight: 600; color: #555;">Confirm New Password</label>
307
+ <PasswordEditor
308
+ bind:value={passwordForm.confirmPassword}
309
+ variant="outlined"
310
+ placeholder="Confirm new password"
311
+ style="width: 100%;"
312
+ on:blur={handleFieldBlur('confirmPassword')}
313
+ />
314
+ {#if errors.confirmPassword}
315
+ <div class="field-error" style="color: #d32f2f; font-size: 0.875em; margin-top: 5px;">
316
+ {errors.confirmPassword}
317
+ </div>
318
+ {/if}
319
+ </div>
320
+
321
+ <div class="form-actions" style="display: flex; gap: 10px;">
322
+ <button
323
+ type="button"
324
+ on:click={() => passwordForm = { currentPassword: '', newPassword: '', confirmPassword: '' }}
325
+ style="flex: 1; padding: 12px; background: #f5f5f5; color: #333; border: 1px solid #ddd; border-radius: 4px; cursor: pointer;"
326
+ >
327
+ Cancel
328
+ </button>
329
+ <button
330
+ type="button"
331
+ on:click={handleSubmit}
332
+ style="flex: 2; padding: 12px; background: #1976d2; color: white; border: none; border-radius: 4px; cursor: pointer;"
333
+ >
334
+ Change Password
335
+ </button>
336
+ </div>
337
+ </div>
338
+ ```
339
+
340
+ ### Registration Form with Password Confirmation
341
+
342
+ ```svelte
343
+ <script>
344
+ import PasswordEditor from '@ticatec/uniface-element/PasswordEditor';
345
+
346
+ let registrationForm = {
347
+ email: '',
348
+ password: '',
349
+ confirmPassword: '',
350
+ acceptTerms: false
351
+ };
352
+
353
+ let fieldErrors = {};
354
+ let passwordStrength = '';
355
+
356
+ $: {
357
+ // Real-time password strength calculation
358
+ if (registrationForm.password) {
359
+ let strength = 0;
360
+ if (registrationForm.password.length >= 8) strength++;
361
+ if (/[A-Z]/.test(registrationForm.password)) strength++;
362
+ if (/[a-z]/.test(registrationForm.password)) strength++;
363
+ if (/\d/.test(registrationForm.password)) strength++;
364
+ if (/[@$!%*?&]/.test(registrationForm.password)) strength++;
365
+
366
+ switch (strength) {
367
+ case 0:
368
+ case 1: passwordStrength = 'Very Weak'; break;
369
+ case 2: passwordStrength = 'Weak'; break;
370
+ case 3: passwordStrength = 'Fair'; break;
371
+ case 4: passwordStrength = 'Good'; break;
372
+ case 5: passwordStrength = 'Strong'; break;
373
+ }
374
+ } else {
375
+ passwordStrength = '';
376
+ }
377
+ }
378
+
379
+ const getStrengthColor = (strength) => {
380
+ switch (strength) {
381
+ case 'Very Weak': return '#d32f2f';
382
+ case 'Weak': return '#f57c00';
383
+ case 'Fair': return '#fbc02d';
384
+ case 'Good': return '#388e3c';
385
+ case 'Strong': return '#1976d2';
386
+ default: return '#666';
387
+ }
388
+ };
389
+
390
+ const validateEmail = (email) => {
391
+ const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
392
+ return emailRegex.test(email);
393
+ };
394
+
395
+ const handleSubmit = () => {
396
+ fieldErrors = {};
397
+
398
+ if (!registrationForm.email) {
399
+ fieldErrors.email = 'Email is required';
400
+ } else if (!validateEmail(registrationForm.email)) {
401
+ fieldErrors.email = 'Please enter a valid email address';
402
+ }
403
+
404
+ if (!registrationForm.password) {
405
+ fieldErrors.password = 'Password is required';
406
+ } else if (passwordStrength === 'Very Weak' || passwordStrength === 'Weak') {
407
+ fieldErrors.password = 'Password is too weak';
408
+ }
409
+
410
+ if (!registrationForm.confirmPassword) {
411
+ fieldErrors.confirmPassword = 'Password confirmation is required';
412
+ } else if (registrationForm.password !== registrationForm.confirmPassword) {
413
+ fieldErrors.confirmPassword = 'Passwords do not match';
414
+ }
415
+
416
+ if (!registrationForm.acceptTerms) {
417
+ fieldErrors.terms = 'You must accept the terms and conditions';
418
+ }
419
+
420
+ if (Object.keys(fieldErrors).length === 0) {
421
+ alert('Registration successful!');
422
+ registrationForm = { email: '', password: '', confirmPassword: '', acceptTerms: false };
423
+ }
424
+
425
+ fieldErrors = {...fieldErrors};
426
+ };
427
+ </script>
428
+
429
+ <div class="registration-form" style="max-width: 450px; margin: 50px auto; padding: 30px; border: 1px solid #e0e0e0; border-radius: 12px; box-shadow: 0 4px 6px rgba(0,0,0,0.1);">
430
+ <h2 style="text-align: center; margin-bottom: 30px; color: #1976d2;">Create Account</h2>
431
+
432
+ <div class="form-field" style="margin-bottom: 20px;">
433
+ <label style="display: block; margin-bottom: 8px; font-weight: 600;">Email Address</label>
434
+ <input
435
+ type="email"
436
+ bind:value={registrationForm.email}
437
+ placeholder="your.email@example.com"
438
+ style="width: 100%; padding: 12px; border: 1px solid #ddd; border-radius: 6px; font-size: 14px;"
439
+ class:error={fieldErrors.email}
440
+ />
441
+ {#if fieldErrors.email}
442
+ <div class="error" style="color: #d32f2f; font-size: 0.875em; margin-top: 4px;">
443
+ {fieldErrors.email}
444
+ </div>
445
+ {/if}
446
+ </div>
447
+
448
+ <div class="form-field" style="margin-bottom: 20px;">
449
+ <label style="display: block; margin-bottom: 8px; font-weight: 600;">Password</label>
450
+ <PasswordEditor
451
+ bind:value={registrationForm.password}
452
+ variant="outlined"
453
+ placeholder="Create a strong password"
454
+ style="width: 100%;"
455
+ />
456
+ {#if passwordStrength}
457
+ <div class="password-strength" style="margin-top: 5px; font-size: 0.875em;">
458
+ Strength: <span style="color: {getStrengthColor(passwordStrength)}; font-weight: bold;">{passwordStrength}</span>
459
+ </div>
460
+ {/if}
461
+ {#if fieldErrors.password}
462
+ <div class="error" style="color: #d32f2f; font-size: 0.875em; margin-top: 4px;">
463
+ {fieldErrors.password}
464
+ </div>
465
+ {/if}
466
+ </div>
467
+
468
+ <div class="form-field" style="margin-bottom: 25px;">
469
+ <label style="display: block; margin-bottom: 8px; font-weight: 600;">Confirm Password</label>
470
+ <PasswordEditor
471
+ bind:value={registrationForm.confirmPassword}
472
+ variant="outlined"
473
+ placeholder="Confirm your password"
474
+ style="width: 100%;"
475
+ />
476
+ {#if fieldErrors.confirmPassword}
477
+ <div class="error" style="color: #d32f2f; font-size: 0.875em; margin-top: 4px;">
478
+ {fieldErrors.confirmPassword}
479
+ </div>
480
+ {/if}
481
+ </div>
482
+
483
+ <div class="form-field" style="margin-bottom: 25px;">
484
+ <label style="display: flex; align-items: center; font-size: 0.9em; color: #555;">
485
+ <input
486
+ type="checkbox"
487
+ bind:checked={registrationForm.acceptTerms}
488
+ style="margin-right: 8px;"
489
+ />
490
+ I agree to the <a href="#" style="color: #1976d2; text-decoration: none;">Terms and Conditions</a>
491
+ </label>
492
+ {#if fieldErrors.terms}
493
+ <div class="error" style="color: #d32f2f; font-size: 0.875em; margin-top: 4px;">
494
+ {fieldErrors.terms}
495
+ </div>
496
+ {/if}
497
+ </div>
498
+
499
+ <button
500
+ type="button"
501
+ on:click={handleSubmit}
502
+ style="width: 100%; padding: 14px; background: #1976d2; color: white; border: none; border-radius: 6px; font-size: 16px; font-weight: 600; cursor: pointer;"
503
+ >
504
+ Create Account
505
+ </button>
506
+ </div>
507
+ ```
508
+
509
+ ## Best Practices
510
+
511
+ 1. **Security First**: Never store or transmit passwords in plain text
512
+ 2. **Visibility Toggle**: The eye icon helps users verify their password entry
513
+ 3. **Validation**: Implement proper password strength validation
514
+ 4. **Accessibility**: Provide clear labels and appropriate ARIA attributes
515
+ 5. **Confirmation Fields**: Always include password confirmation in registration forms
516
+ 6. **Readonly States**: Handle readonly state appropriately to prevent toggle when not editable
517
+ 7. **Form Integration**: Use with proper form validation and submission handling
518
+
519
+ ## Styling Notes
520
+
521
+ - The component inherits styling from CommonEditor
522
+ - Eye icon changes based on current visibility state (eye/eye-off)
523
+ - Supports all CommonEditor variants and styling options
524
+ - Custom styles can be applied via the `style` prop
525
+
526
+ ## Security Considerations
527
+
528
+ - Password masking is handled automatically
529
+ - Visibility toggle is disabled in readonly mode
530
+ - Component doesn't store password history or implement auto-complete
531
+ - Use HTTPS in production for secure transmission
532
+
533
+ ## Accessibility Features
534
+
535
+ - Proper input type switching between "password" and "text"
536
+ - Focus management preserved during visibility toggle
537
+ - Screen reader compatible with standard input behaviors
538
+ - Clear visual indicators for interactive elements