@ticatec/uniface-element 0.2.4 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (176) hide show
  1. package/dist/accordion/README.md +169 -0
  2. package/dist/accordion/README_CN.md +176 -0
  3. package/dist/action-bar/README.md +275 -0
  4. package/dist/action-bar/README_CN.md +285 -0
  5. package/dist/app-layout/README.md +374 -0
  6. package/dist/app-layout/README_CN.md +381 -0
  7. package/dist/app-top-bar/README.md +357 -0
  8. package/dist/app-top-bar/README_CN.md +365 -0
  9. package/dist/attachment-files/AttachmentFilesField.svelte +67 -1
  10. package/dist/attachment-files/AttachmentFilesField.svelte.d.ts +8 -1
  11. package/dist/base-calendar/CalendarBase.svelte +0 -3
  12. package/dist/box/README.md +385 -0
  13. package/dist/box/README_CN.md +393 -0
  14. package/dist/breadcrumbs/README.md +442 -0
  15. package/dist/breadcrumbs/README_CN.md +442 -0
  16. package/dist/button/Button.svelte +27 -7
  17. package/dist/button/Button.svelte.d.ts +3 -1
  18. package/dist/button/IconButton.svelte +26 -6
  19. package/dist/button/IconButton.svelte.d.ts +3 -1
  20. package/dist/button/IconButton_README.md +513 -0
  21. package/dist/button/IconButton_README_CN.md +513 -0
  22. package/dist/button/README.md +428 -0
  23. package/dist/button/README_CN.md +428 -0
  24. package/dist/button/TextButton.svelte +26 -6
  25. package/dist/button/TextButton.svelte.d.ts +3 -1
  26. package/dist/button/TextButton_README.md +571 -0
  27. package/dist/button/TextButton_README_CN.md +571 -0
  28. package/dist/card/README.md +666 -0
  29. package/dist/card/README_CN.md +666 -0
  30. package/dist/cascade-options-select/CascadeOptionSelect.svelte +43 -7
  31. package/dist/cascade-options-select/CascadeOptionSelect.svelte.d.ts +3 -4
  32. package/dist/cascade-options-select/README.md +663 -2
  33. package/dist/cascade-options-select/README_CN.md +664 -0
  34. package/dist/checkbox/CheckBox.svelte +20 -6
  35. package/dist/checkbox/CheckBox.svelte.d.ts +4 -2
  36. package/dist/checkbox/README.md +562 -0
  37. package/dist/checkbox/README_CN.md +727 -0
  38. package/dist/common-editor/NumberInput.svelte +39 -26
  39. package/dist/common-editor/NumberInput.svelte.d.ts +5 -1
  40. package/dist/concise-data-table/ConciseListTable.svelte +133 -36
  41. package/dist/concise-data-table/ConciseListTable.svelte.d.ts +8 -1
  42. package/dist/concise-data-table/DataCell.svelte +5 -6
  43. package/dist/concise-data-table/DataRow.svelte +22 -2
  44. package/dist/concise-data-table/DataRow.svelte.d.ts +1 -0
  45. package/dist/concise-data-table/README.md +606 -0
  46. package/dist/concise-data-table/README_CN.md +611 -0
  47. package/dist/context-menu/ContextMenu.svelte +138 -21
  48. package/dist/context-menu/ContextMenu.svelte.d.ts +5 -0
  49. package/dist/context-menu/ContextMenuItem.d.ts +20 -4
  50. package/dist/context-menu/README.md +551 -0
  51. package/dist/context-menu/README_CN.md +551 -0
  52. package/dist/criteria-field/CriteriaField.svelte +3 -5
  53. package/dist/criteria-field/README.md +532 -0
  54. package/dist/criteria-field/README_CN.md +532 -0
  55. package/dist/data-table/README.md +712 -0
  56. package/dist/data-table/README_CN.md +712 -0
  57. package/dist/date-picker/DatePicker.svelte +44 -7
  58. package/dist/date-picker/DatePicker.svelte.d.ts +3 -4
  59. package/dist/date-picker/DateTimePicker.svelte +32 -8
  60. package/dist/date-picker/DateTimePicker.svelte.d.ts +3 -4
  61. package/dist/date-picker/README.md +326 -0
  62. package/dist/date-picker/README_CN.md +316 -0
  63. package/dist/date-picker/ScrollBar.svelte +18 -8
  64. package/dist/date-picker/ScrollBar.svelte.d.ts +1 -1
  65. package/dist/date-picker/TimePanel.svelte +5 -5
  66. package/dist/date-picker/TimePanel.svelte.d.ts +1 -1
  67. package/dist/date-range/README.md +374 -0
  68. package/dist/date-range/README_CN.md +374 -0
  69. package/dist/dialog/README.md +596 -0
  70. package/dist/dialog/README_CN.md +596 -0
  71. package/dist/drawer/README.md +679 -1
  72. package/dist/drawer/README_CN.md +679 -0
  73. package/dist/group-box/group-check-box/GroupCheckBox.svelte +62 -5
  74. package/dist/group-box/group-check-box/GroupCheckBox.svelte.d.ts +7 -2
  75. package/dist/group-box/group-check-box/README.md +749 -0
  76. package/dist/group-box/group-check-box/README_CN.md +750 -0
  77. package/dist/group-box/group-radio-box/GroupRadioBox.svelte +69 -4
  78. package/dist/group-box/group-radio-box/GroupRadioBox.svelte.d.ts +8 -2
  79. package/dist/group-box/group-radio-box/README.md +920 -0
  80. package/dist/group-box/group-radio-box/README_CN.md +920 -0
  81. package/dist/image-files/README.md +1346 -0
  82. package/dist/image-files/README_CN.md +1346 -0
  83. package/dist/input-options-select/InputOptionsSelect.svelte +161 -65
  84. package/dist/input-options-select/InputOptionsSelect.svelte.d.ts +4 -1
  85. package/dist/lib/forwardAllEvents.d.ts +3 -0
  86. package/dist/lib/forwardAllEvents.js +24 -0
  87. package/dist/list-box/README.md +579 -0
  88. package/dist/list-box/README_CN.md +682 -0
  89. package/dist/lookup-editor/LookupEditor.svelte +15 -3
  90. package/dist/lookup-editor/LookupEditor.svelte.d.ts +3 -4
  91. package/dist/lookup-editor/README.md +684 -0
  92. package/dist/lookup-editor/README_CN.md +684 -0
  93. package/dist/memo-editor/MemoEditor.svelte +77 -27
  94. package/dist/memo-editor/MemoEditor.svelte.d.ts +6 -3
  95. package/dist/memo-editor/README.md +819 -0
  96. package/dist/memo-editor/README_CN.md +819 -0
  97. package/dist/message-box/README.md +398 -0
  98. package/dist/message-box/README_CN.md +398 -0
  99. package/dist/number-editor/NumberEditor.svelte +2 -2
  100. package/dist/number-editor/NumberEditor.svelte.d.ts +1 -1
  101. package/dist/number-editor/README.md +353 -22
  102. package/dist/number-editor/README_CN.md +357 -0
  103. package/dist/number-range/README.md +443 -0
  104. package/dist/number-range/README_CN.md +443 -0
  105. package/dist/options-multi-select/OptionsMultiSelect.svelte +87 -12
  106. package/dist/options-multi-select/OptionsMultiSelect.svelte.d.ts +3 -1
  107. package/dist/options-multi-select/README.md +480 -0
  108. package/dist/options-multi-select/README_CN.md +480 -0
  109. package/dist/options-select/OptionsSelect.svelte +36 -5
  110. package/dist/options-select/OptionsSelect.svelte.d.ts +3 -4
  111. package/dist/options-select/README.md +632 -0
  112. package/dist/options-select/README_CN.md +632 -0
  113. package/dist/page/README.md +605 -0
  114. package/dist/page/README_CN.md +605 -0
  115. package/dist/pagination/README.md +946 -0
  116. package/dist/pagination/README_CN.md +946 -0
  117. package/dist/pagination-panel/README.md +1075 -0
  118. package/dist/pagination-panel/README_CN.md +1075 -0
  119. package/dist/popup-hint/README.md +841 -0
  120. package/dist/popup-hint/README_CN.md +840 -0
  121. package/dist/progress-bar/README.md +242 -0
  122. package/dist/progress-bar/README_CN.md +242 -0
  123. package/dist/progress-step-bar/README.md +316 -0
  124. package/dist/progress-step-bar/README_CN.md +316 -0
  125. package/dist/prompts-text-editor/PromptsTextEditor.svelte +6 -3
  126. package/dist/prompts-text-editor/PromptsTextEditor.svelte.d.ts +3 -1
  127. package/dist/prompts-text-editor/README.md +329 -0
  128. package/dist/prompts-text-editor/README_CN.md +329 -0
  129. package/dist/property-editor/README.md +969 -0
  130. package/dist/property-editor/README_CN.md +969 -0
  131. package/dist/radio-button/README.md +372 -0
  132. package/dist/radio-button/README_CN.md +372 -0
  133. package/dist/radio-button/RadioButton.svelte +32 -3
  134. package/dist/radio-button/RadioButton.svelte.d.ts +12 -1
  135. package/dist/search-box/README.md +425 -0
  136. package/dist/search-box/README_CN.md +424 -0
  137. package/dist/search-box/SearchBox.svelte +22 -6
  138. package/dist/search-box/SearchBox.svelte.d.ts +4 -1
  139. package/dist/tabs/README.md +919 -0
  140. package/dist/tabs/README_CN.md +920 -0
  141. package/dist/tag/README.md +922 -0
  142. package/dist/tag/README_CN.md +922 -0
  143. package/dist/text-editor/PasswordEditor.svelte +17 -2
  144. package/dist/text-editor/PasswordEditor.svelte.d.ts +3 -3
  145. package/dist/text-editor/PasswordEditor_README.md +551 -0
  146. package/dist/text-editor/PasswordEditor_README_CN.md +551 -0
  147. package/dist/text-editor/README.md +466 -0
  148. package/dist/text-editor/README_CN.md +466 -0
  149. package/dist/text-editor/TextEditor.svelte +51 -19
  150. package/dist/text-editor/TextEditor.svelte.d.ts +0 -1
  151. package/dist/time-editor/README.md +498 -24
  152. package/dist/time-editor/README_CN.md +498 -0
  153. package/dist/time-editor/TimeEditor.svelte +7 -3
  154. package/dist/time-editor/TimeEditor.svelte.d.ts +3 -1
  155. package/dist/toast/README.md +667 -0
  156. package/dist/toast/README_CN.md +667 -0
  157. package/dist/transfer/README.md +795 -0
  158. package/dist/transfer/Transfer.svelte +6 -4
  159. package/dist/transfer/Transfer.svelte.d.ts +3 -1
  160. package/dist/tree-view/README.md +761 -0
  161. package/dist/tree-view/README_CN.md +761 -0
  162. package/dist/tree-view/TreeView.svelte +5 -3
  163. package/dist/tree-view/TreeView.svelte.d.ts +3 -1
  164. package/dist/unit-number-editor/README.md +546 -20
  165. package/dist/unit-number-editor/README_CN.md +525 -0
  166. package/dist/unit-number-editor/UnitNumberEditor.svelte +62 -8
  167. package/dist/unit-number-editor/UnitNumberEditor.svelte.d.ts +5 -1
  168. package/docs/form-field/cn/README_CN.md +364 -0
  169. package/docs/form-field/en/README.md +364 -0
  170. package/docs/form-panel/flex-form/cn/README_CN.md +586 -0
  171. package/docs/form-panel/flex-form/en/README.md +586 -0
  172. package/docs/form-panel/flex-row-form/cn/README_CN.md +787 -0
  173. package/docs/form-panel/flex-row-form/en/README.md +787 -0
  174. package/docs/form-panel/grid-form/en/README.md +744 -0
  175. package/package.json +1 -1
  176. package/dist/drawer/README-CN.md +0 -1
@@ -0,0 +1,920 @@
1
+ # GroupRadioBox
2
+
3
+ A flexible group radio box component that allows users to select a single option from a predefined list. Features comprehensive state management, custom styling variants, and focus/blur event handling for seamless form integration.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @ticatec/uniface-element
9
+ ```
10
+
11
+ ## Import
12
+
13
+ ```typescript
14
+ import GroupRadioBox from "@ticatec/uniface-element/GroupRadioBox";
15
+ import { DisplayMode } from "@ticatec/uniface-element";
16
+ import type { OnChangeHandler } from "@ticatec/uniface-element";
17
+ ```
18
+
19
+ ## Basic Usage
20
+
21
+ ```svelte
22
+ <script>
23
+ import GroupRadioBox from "@ticatec/uniface-element/GroupRadioBox";
24
+
25
+ const options = [
26
+ { code: "sm", text: "Small" },
27
+ { code: "md", text: "Medium" },
28
+ { code: "lg", text: "Large" },
29
+ { code: "xl", text: "Extra Large" }
30
+ ];
31
+
32
+ let selectedSize = "md";
33
+
34
+ function handleChange(value) {
35
+ console.log('Selected size:', value);
36
+ }
37
+ </script>
38
+
39
+ <GroupRadioBox
40
+ {options}
41
+ bind:value={selectedSize}
42
+ onchange={handleChange}
43
+ />
44
+ ```
45
+
46
+ ## Props
47
+
48
+ | Prop | Type | Default | Description |
49
+ |------|------|---------|-------------|
50
+ | `value` | `any` | required | Selected value |
51
+ | `options` | `Array<any>` | required | Array of option objects |
52
+ | `keyField` | `string` | `"code"` | Field name for option keys/values |
53
+ | `textField` | `string` | `"text"` | Field name for option display text |
54
+ | `disabled` | `boolean` | `false` | Whether the component is disabled |
55
+ | `readonly` | `boolean` | `false` | Whether the component is read-only |
56
+ | `displayMode` | `DisplayMode` | `DisplayMode.Edit` | Display mode (Edit or View) |
57
+ | `variant` | `"" \| "plain" \| "outlined" \| "filled"` | `""` | Visual variant |
58
+ | `compact` | `boolean` | `false` | Whether to use compact spacing |
59
+ | `disabledOptions` | `Array<string>` | `[]` | Array of option keys to disable |
60
+ | `style` | `string` | `""` | Additional CSS styles |
61
+ | `item$style` | `string` | `""` | CSS styles for individual radio button items |
62
+ | `onchange` | `OnChangeHandler<any>` | `null` | Change event handler |
63
+ | `onfocus` | `(() => void) \| null` | `null` | Focus event handler |
64
+ | `onblur` | `(() => void) \| null` | `null` | Blur event handler |
65
+
66
+ ## Methods
67
+
68
+ | Method | Description |
69
+ |--------|-------------|
70
+ | `setFocus()` | Programmatically focus the first enabled radio button |
71
+
72
+ ## Examples
73
+
74
+ ### Basic Selection
75
+
76
+ ```svelte
77
+ <script>
78
+ import GroupRadioBox from "@ticatec/uniface-element/GroupRadioBox";
79
+ import FormField from "@ticatec/uniface-element/FormField";
80
+
81
+ const priorities = [
82
+ { code: "low", text: "Low Priority" },
83
+ { code: "medium", text: "Medium Priority" },
84
+ { code: "high", text: "High Priority" },
85
+ { code: "urgent", text: "Urgent" }
86
+ ];
87
+
88
+ let taskPriority = "medium";
89
+
90
+ function handlePriorityChange(value) {
91
+ console.log('Priority changed to:', value);
92
+
93
+ // Handle priority-specific logic
94
+ if (value === 'urgent') {
95
+ console.log('Urgent task - notify team leads');
96
+ }
97
+ }
98
+ </script>
99
+
100
+ <div class="demo-section">
101
+ <FormField label="Task Priority">
102
+ <GroupRadioBox
103
+ options={priorities}
104
+ bind:value={taskPriority}
105
+ onchange={handlePriorityChange}
106
+ onfocus={() => console.log('Priority field focused')}
107
+ onblur={() => console.log('Priority field blurred')}
108
+ />
109
+ </FormField>
110
+
111
+ <div class="result">
112
+ <p><strong>Selected Priority:</strong> {taskPriority}</p>
113
+ <p><strong>Display Text:</strong> {priorities.find(p => p.code === taskPriority)?.text ?? 'None'}</p>
114
+ </div>
115
+ </div>
116
+
117
+ <style>
118
+ .demo-section {
119
+ margin: 20px;
120
+ padding: 20px;
121
+ border: 1px solid #e2e8f0;
122
+ border-radius: 8px;
123
+ }
124
+
125
+ .result {
126
+ margin-top: 16px;
127
+ padding: 12px;
128
+ background: #f8fafc;
129
+ border-radius: 6px;
130
+ }
131
+ </style>
132
+ ```
133
+
134
+ ### Different Visual Variants
135
+
136
+ ```svelte
137
+ <script>
138
+ import GroupRadioBox from "@ticatec/uniface-element/GroupRadioBox";
139
+ import FormField from "@ticatec/uniface-element/FormField";
140
+
141
+ const themes = [
142
+ { code: "light", text: "Light Theme" },
143
+ { code: "dark", text: "Dark Theme" },
144
+ { code: "auto", text: "Auto (System)" }
145
+ ];
146
+
147
+ let selectedTheme = "auto";
148
+ </script>
149
+
150
+ <div class="variants-demo">
151
+ <div class="variant-section">
152
+ <h3>Default Variant</h3>
153
+ <FormField label="Theme Preference">
154
+ <GroupRadioBox options={themes} bind:value={selectedTheme} />
155
+ </FormField>
156
+ </div>
157
+
158
+ <div class="variant-section">
159
+ <h3>Outlined Variant</h3>
160
+ <FormField label="Theme Preference">
161
+ <GroupRadioBox
162
+ options={themes}
163
+ variant="outlined"
164
+ bind:value={selectedTheme}
165
+ />
166
+ </FormField>
167
+ </div>
168
+
169
+ <div class="variant-section">
170
+ <h3>Filled Variant</h3>
171
+ <FormField label="Theme Preference">
172
+ <GroupRadioBox
173
+ options={themes}
174
+ variant="filled"
175
+ bind:value={selectedTheme}
176
+ />
177
+ </FormField>
178
+ </div>
179
+
180
+ <div class="variant-section">
181
+ <h3>Compact Variant</h3>
182
+ <FormField label="Theme Preference">
183
+ <GroupRadioBox
184
+ options={themes}
185
+ compact={true}
186
+ bind:value={selectedTheme}
187
+ />
188
+ </FormField>
189
+ </div>
190
+ </div>
191
+
192
+ <style>
193
+ .variants-demo {
194
+ display: grid;
195
+ grid-template-columns: 1fr 1fr;
196
+ gap: 20px;
197
+ margin: 20px;
198
+ }
199
+
200
+ .variant-section {
201
+ padding: 16px;
202
+ border: 1px solid #e2e8f0;
203
+ border-radius: 8px;
204
+ }
205
+ </style>
206
+ ```
207
+
208
+ ### Conditional Options and Dynamic Behavior
209
+
210
+ ```svelte
211
+ <script>
212
+ import GroupRadioBox from "@ticatec/uniface-element/GroupRadioBox";
213
+ import FormField from "@ticatec/uniface-element/FormField";
214
+
215
+ const paymentMethods = [
216
+ { code: "card", text: "Credit Card" },
217
+ { code: "paypal", text: "PayPal" },
218
+ { code: "bank", text: "Bank Transfer" },
219
+ { code: "crypto", text: "Cryptocurrency" },
220
+ { code: "cash", text: "Cash on Delivery" }
221
+ ];
222
+
223
+ let selectedPayment = "card";
224
+ let disabledOptions = [];
225
+ let orderTotal = 150.00;
226
+ let region = "domestic";
227
+
228
+ // Update available payment methods based on order conditions
229
+ $: {
230
+ disabledOptions = [];
231
+
232
+ // Disable crypto for small orders
233
+ if (orderTotal < 100) {
234
+ disabledOptions.push("crypto");
235
+ }
236
+
237
+ // Disable cash on delivery for international orders
238
+ if (region === "international") {
239
+ disabledOptions.push("cash");
240
+ }
241
+
242
+ // Auto-select available option if current selection becomes disabled
243
+ if (disabledOptions.includes(selectedPayment)) {
244
+ const availableOptions = paymentMethods.filter(method =>
245
+ !disabledOptions.includes(method.code)
246
+ );
247
+ if (availableOptions.length > 0) {
248
+ selectedPayment = availableOptions[0].code;
249
+ }
250
+ }
251
+ }
252
+
253
+ function handlePaymentChange(value) {
254
+ console.log('Payment method changed to:', value);
255
+
256
+ // Handle payment-specific logic
257
+ if (value === 'crypto') {
258
+ console.log('Crypto payment selected - show wallet options');
259
+ } else if (value === 'bank') {
260
+ console.log('Bank transfer selected - show bank details');
261
+ }
262
+ }
263
+ </script>
264
+
265
+ <div class="conditional-demo">
266
+ <div class="controls">
267
+ <FormField label="Order Total">
268
+ <input
269
+ type="number"
270
+ bind:value={orderTotal}
271
+ min="10"
272
+ step="10"
273
+ class="number-input"
274
+ />
275
+ </FormField>
276
+
277
+ <FormField label="Region">
278
+ <select bind:value={region} class="select-input">
279
+ <option value="domestic">Domestic</option>
280
+ <option value="international">International</option>
281
+ </select>
282
+ </FormField>
283
+ </div>
284
+
285
+ <FormField label="Payment Method">
286
+ <GroupRadioBox
287
+ options={paymentMethods}
288
+ bind:value={selectedPayment}
289
+ {disabledOptions}
290
+ onchange={handlePaymentChange}
291
+ variant="outlined"
292
+ />
293
+ </FormField>
294
+
295
+ <div class="info-panel">
296
+ <p><strong>Selected:</strong> {selectedPayment}</p>
297
+ <p><strong>Order Total:</strong> ${orderTotal}</p>
298
+ <p><strong>Region:</strong> {region}</p>
299
+ <p><strong>Disabled Methods:</strong> {disabledOptions.join(', ') || 'None'}</p>
300
+
301
+ {#if disabledOptions.includes('crypto')}
302
+ <p class="info-note">💡 Cryptocurrency payments require minimum $100 order</p>
303
+ {/if}
304
+
305
+ {#if disabledOptions.includes('cash')}
306
+ <p class="info-note">💡 Cash on delivery not available for international orders</p>
307
+ {/if}
308
+ </div>
309
+ </div>
310
+
311
+ <style>
312
+ .conditional-demo {
313
+ margin: 20px;
314
+ padding: 20px;
315
+ border: 1px solid #e2e8f0;
316
+ border-radius: 8px;
317
+ }
318
+
319
+ .controls {
320
+ display: grid;
321
+ grid-template-columns: 1fr 1fr;
322
+ gap: 16px;
323
+ margin-bottom: 20px;
324
+ }
325
+
326
+ .number-input, .select-input {
327
+ width: 100%;
328
+ padding: 8px 12px;
329
+ border: 1px solid #d1d5db;
330
+ border-radius: 6px;
331
+ }
332
+
333
+ .info-panel {
334
+ margin-top: 16px;
335
+ padding: 12px;
336
+ background: #f8fafc;
337
+ border-radius: 6px;
338
+ }
339
+
340
+ .info-note {
341
+ color: #6b7280;
342
+ font-style: italic;
343
+ margin-top: 8px;
344
+ }
345
+ </style>
346
+ ```
347
+
348
+ ### Custom Field Configuration
349
+
350
+ ```svelte
351
+ <script>
352
+ import GroupRadioBox from "@ticatec/uniface-element/GroupRadioBox";
353
+ import FormField from "@ticatec/uniface-element/FormField";
354
+
355
+ // Using custom field names
356
+ const departments = [
357
+ { id: "eng", name: "Engineering", active: true },
358
+ { id: "sales", name: "Sales & Marketing", active: true },
359
+ { id: "hr", name: "Human Resources", active: false },
360
+ { id: "finance", name: "Finance & Accounting", active: true }
361
+ ];
362
+
363
+ let selectedDepartment = "eng";
364
+
365
+ function handleDepartmentChange(value) {
366
+ const selected = departments.find(dept => dept.id === value);
367
+ console.log('Department changed:', selected);
368
+ }
369
+ </script>
370
+
371
+ <div class="custom-demo">
372
+ <FormField label="Select Department">
373
+ <GroupRadioBox
374
+ options={departments}
375
+ keyField="id"
376
+ textField="name"
377
+ bind:value={selectedDepartment}
378
+ onchange={handleDepartmentChange}
379
+ variant="filled"
380
+ style="padding: 16px; background: linear-gradient(145deg, #f8fafc, #e2e8f0);"
381
+ item$style="margin: 8px 0; padding: 6px 12px; border-radius: 8px; background: white;"
382
+ />
383
+ </FormField>
384
+
385
+ <div class="department-info">
386
+ {#each departments as dept}
387
+ {#if dept.id === selectedDepartment}
388
+ <div class="selected-dept">
389
+ <h4>{dept.name}</h4>
390
+ <p>Status: {dept.active ? '✅ Active' : '❌ Inactive'}</p>
391
+ <p>Department ID: {dept.id}</p>
392
+ </div>
393
+ {/if}
394
+ {/each}
395
+ </div>
396
+ </div>
397
+
398
+ <style>
399
+ .custom-demo {
400
+ margin: 20px;
401
+ padding: 20px;
402
+ border: 1px solid #e2e8f0;
403
+ border-radius: 8px;
404
+ }
405
+
406
+ .department-info {
407
+ margin-top: 16px;
408
+ }
409
+
410
+ .selected-dept {
411
+ padding: 16px;
412
+ background: #dbeafe;
413
+ border-radius: 8px;
414
+ border-left: 4px solid #3b82f6;
415
+ }
416
+ </style>
417
+ ```
418
+
419
+ ### Read-Only and Display Modes
420
+
421
+ ```svelte
422
+ <script>
423
+ import GroupRadioBox from "@ticatec/uniface-element/GroupRadioBox";
424
+ import FormField from "@ticatec/uniface-element/FormField";
425
+ import { DisplayMode } from "@ticatec/uniface-element";
426
+
427
+ const subscriptionPlans = [
428
+ { code: "basic", text: "Basic Plan" },
429
+ { code: "premium", text: "Premium Plan" },
430
+ { code: "enterprise", text: "Enterprise Plan" }
431
+ ];
432
+
433
+ let currentPlan = "premium"; // Pre-selected plan
434
+ </script>
435
+
436
+ <div class="readonly-demo">
437
+ <div class="mode-section">
438
+ <h3>Editable Mode</h3>
439
+ <FormField label="Change Subscription Plan">
440
+ <GroupRadioBox
441
+ options={subscriptionPlans}
442
+ bind:value={currentPlan}
443
+ />
444
+ </FormField>
445
+ </div>
446
+
447
+ <div class="mode-section">
448
+ <h3>Read-Only Mode</h3>
449
+ <FormField label="Current Plan (Read-Only)">
450
+ <GroupRadioBox
451
+ options={subscriptionPlans}
452
+ value={currentPlan}
453
+ readonly={true}
454
+ />
455
+ </FormField>
456
+ </div>
457
+
458
+ <div class="mode-section">
459
+ <h3>Disabled Mode</h3>
460
+ <FormField label="Plan Selection (Disabled)">
461
+ <GroupRadioBox
462
+ options={subscriptionPlans}
463
+ value={currentPlan}
464
+ disabled={true}
465
+ />
466
+ </FormField>
467
+ </div>
468
+
469
+ <div class="mode-section">
470
+ <h3>Display-Only Mode</h3>
471
+ <FormField label="Active Plan">
472
+ <GroupRadioBox
473
+ options={subscriptionPlans}
474
+ value={currentPlan}
475
+ displayMode={DisplayMode.View}
476
+ />
477
+ </FormField>
478
+ </div>
479
+ </div>
480
+
481
+ <style>
482
+ .readonly-demo {
483
+ display: grid;
484
+ grid-template-columns: 1fr 1fr;
485
+ gap: 20px;
486
+ margin: 20px;
487
+ }
488
+
489
+ .mode-section {
490
+ padding: 16px;
491
+ border: 1px solid #e2e8f0;
492
+ border-radius: 8px;
493
+ }
494
+ </style>
495
+ ```
496
+
497
+ ### Form Integration with Validation
498
+
499
+ ```svelte
500
+ <script>
501
+ import GroupRadioBox from "@ticatec/uniface-element/GroupRadioBox";
502
+ import FormField from "@ticatec/uniface-element/FormField";
503
+
504
+ const shippingOptions = [
505
+ { code: "standard", text: "Standard (5-7 days)" },
506
+ { code: "express", text: "Express (2-3 days)" },
507
+ { code: "overnight", text: "Overnight" }
508
+ ];
509
+
510
+ const countries = [
511
+ { code: "us", text: "United States" },
512
+ { code: "ca", text: "Canada" },
513
+ { code: "uk", text: "United Kingdom" },
514
+ { code: "au", text: "Australia" }
515
+ ];
516
+
517
+ let formData = {
518
+ name: '',
519
+ country: '',
520
+ shipping: ''
521
+ };
522
+
523
+ let errors = {};
524
+ let groupRadioBoxRef;
525
+
526
+ function validateForm() {
527
+ errors = {};
528
+
529
+ if (!formData.name.trim()) {
530
+ errors.name = 'Name is required';
531
+ }
532
+
533
+ if (!formData.country) {
534
+ errors.country = 'Please select a country';
535
+ }
536
+
537
+ if (!formData.shipping) {
538
+ errors.shipping = 'Please select a shipping option';
539
+ }
540
+
541
+ return Object.keys(errors).length === 0;
542
+ }
543
+
544
+ function handleSubmit() {
545
+ if (validateForm()) {
546
+ console.log('Form submitted:', formData);
547
+ alert('Order placed successfully!');
548
+ } else {
549
+ console.log('Validation errors:', errors);
550
+ // Focus first error field
551
+ if (errors.shipping) {
552
+ groupRadioBoxRef.setFocus();
553
+ }
554
+ }
555
+ }
556
+
557
+ function handleShippingChange(value) {
558
+ formData.shipping = value;
559
+ // Clear error when user makes a selection
560
+ if (errors.shipping && value) {
561
+ delete errors.shipping;
562
+ errors = { ...errors };
563
+ }
564
+ }
565
+
566
+ function handleCountryChange(value) {
567
+ formData.country = value;
568
+ // Clear shipping selection if changing country (different options might be available)
569
+ if (formData.shipping) {
570
+ formData.shipping = '';
571
+ }
572
+ // Clear error
573
+ if (errors.country && value) {
574
+ delete errors.country;
575
+ errors = { ...errors };
576
+ }
577
+ }
578
+ </script>
579
+
580
+ <div class="form-demo">
581
+ <form on:submit|preventDefault={handleSubmit}>
582
+ <FormField label="Full Name" error={errors.name}>
583
+ <input
584
+ type="text"
585
+ bind:value={formData.name}
586
+ class="form-input"
587
+ class:error={errors.name}
588
+ placeholder="Enter your full name"
589
+ />
590
+ </FormField>
591
+
592
+ <FormField label="Country" error={errors.country}>
593
+ <GroupRadioBox
594
+ options={countries}
595
+ bind:value={formData.country}
596
+ onchange={handleCountryChange}
597
+ variant="outlined"
598
+ />
599
+ </FormField>
600
+
601
+ <FormField label="Shipping Method" error={errors.shipping}>
602
+ <GroupRadioBox
603
+ bind:this={groupRadioBoxRef}
604
+ options={shippingOptions}
605
+ bind:value={formData.shipping}
606
+ onchange={handleShippingChange}
607
+ variant="outlined"
608
+ />
609
+ <p class="field-hint">Shipping costs will be calculated based on your selection</p>
610
+ </FormField>
611
+
612
+ <div class="form-actions">
613
+ <button type="submit" class="submit-btn">Place Order</button>
614
+ <button type="button" on:click={() => console.log(formData)} class="preview-btn">
615
+ Preview Order
616
+ </button>
617
+ </div>
618
+
619
+ {#if formData.country && formData.shipping}
620
+ <div class="order-summary">
621
+ <h4>Order Summary</h4>
622
+ <p>Ship to: {countries.find(c => c.code === formData.country)?.text}</p>
623
+ <p>Shipping: {shippingOptions.find(s => s.code === formData.shipping)?.text}</p>
624
+ </div>
625
+ {/if}
626
+ </form>
627
+ </div>
628
+
629
+ <style>
630
+ .form-demo {
631
+ max-width: 500px;
632
+ margin: 20px;
633
+ padding: 24px;
634
+ border: 1px solid #e2e8f0;
635
+ border-radius: 8px;
636
+ }
637
+
638
+ .form-input {
639
+ width: 100%;
640
+ padding: 8px 12px;
641
+ border: 1px solid #d1d5db;
642
+ border-radius: 6px;
643
+ }
644
+
645
+ .form-input.error {
646
+ border-color: #dc2626;
647
+ }
648
+
649
+ .field-hint {
650
+ margin-top: 4px;
651
+ font-size: 0.875rem;
652
+ color: #6b7280;
653
+ }
654
+
655
+ .form-actions {
656
+ display: flex;
657
+ gap: 12px;
658
+ margin-top: 20px;
659
+ }
660
+
661
+ .submit-btn, .preview-btn {
662
+ padding: 10px 20px;
663
+ border-radius: 6px;
664
+ border: none;
665
+ cursor: pointer;
666
+ }
667
+
668
+ .submit-btn {
669
+ background: #3b82f6;
670
+ color: white;
671
+ }
672
+
673
+ .preview-btn {
674
+ background: #f3f4f6;
675
+ color: #374151;
676
+ border: 1px solid #d1d5db;
677
+ }
678
+
679
+ .order-summary {
680
+ margin-top: 20px;
681
+ padding: 16px;
682
+ background: #f0f9ff;
683
+ border-radius: 8px;
684
+ border-left: 4px solid #3b82f6;
685
+ }
686
+ </style>
687
+ ```
688
+
689
+ ### Survey and Rating Implementation
690
+
691
+ ```svelte
692
+ <script>
693
+ import GroupRadioBox from "@ticatec/uniface-element/GroupRadioBox";
694
+ import FormField from "@ticatec/uniface-element/FormField";
695
+
696
+ const satisfactionLevels = [
697
+ { code: "1", text: "Very Dissatisfied" },
698
+ { code: "2", text: "Dissatisfied" },
699
+ { code: "3", text: "Neutral" },
700
+ { code: "4", text: "Satisfied" },
701
+ { code: "5", text: "Very Satisfied" }
702
+ ];
703
+
704
+ const frequencies = [
705
+ { code: "daily", text: "Daily" },
706
+ { code: "weekly", text: "Weekly" },
707
+ { code: "monthly", text: "Monthly" },
708
+ { code: "rarely", text: "Rarely" },
709
+ { code: "never", text: "Never" }
710
+ ];
711
+
712
+ let surveyData = {
713
+ satisfaction: '',
714
+ frequency: '',
715
+ recommendation: ''
716
+ };
717
+
718
+ let isCompleted = false;
719
+
720
+ $: isCompleted = surveyData.satisfaction && surveyData.frequency && surveyData.recommendation;
721
+
722
+ function handleSurveySubmit() {
723
+ if (isCompleted) {
724
+ console.log('Survey submitted:', surveyData);
725
+ alert('Thank you for your feedback!');
726
+ }
727
+ }
728
+
729
+ function getSatisfactionColor(level) {
730
+ const colors = {
731
+ '1': '#dc2626', '2': '#ea580c', '3': '#d97706',
732
+ '4': '#65a30d', '5': '#16a34a'
733
+ };
734
+ return colors[level] || '#6b7280';
735
+ }
736
+ </script>
737
+
738
+ <div class="survey-demo">
739
+ <h2>Customer Satisfaction Survey</h2>
740
+
741
+ <div class="survey-section">
742
+ <FormField label="How satisfied are you with our service?">
743
+ <GroupRadioBox
744
+ options={satisfactionLevels}
745
+ bind:value={surveyData.satisfaction}
746
+ variant="outlined"
747
+ item$style="padding: 12px; margin: 4px 0; border-radius: 8px;"
748
+ />
749
+ </FormField>
750
+
751
+ {#if surveyData.satisfaction}
752
+ <div class="satisfaction-feedback" style="color: {getSatisfactionColor(surveyData.satisfaction)}">
753
+ <strong>You selected: {satisfactionLevels.find(s => s.code === surveyData.satisfaction)?.text}</strong>
754
+ </div>
755
+ {/if}
756
+ </div>
757
+
758
+ <div class="survey-section">
759
+ <FormField label="How often do you use our service?">
760
+ <GroupRadioBox
761
+ options={frequencies}
762
+ bind:value={surveyData.frequency}
763
+ variant="filled"
764
+ compact={true}
765
+ />
766
+ </FormField>
767
+ </div>
768
+
769
+ <div class="survey-section">
770
+ <FormField label="Would you recommend us to others?">
771
+ <GroupRadioBox
772
+ options={[
773
+ { code: "yes", text: "Yes, definitely" },
774
+ { code: "maybe", text: "Maybe" },
775
+ { code: "no", text: "No, I wouldn't" }
776
+ ]}
777
+ bind:value={surveyData.recommendation}
778
+ variant="outlined"
779
+ />
780
+ </FormField>
781
+ </div>
782
+
783
+ <div class="survey-progress">
784
+ <div class="progress-bar">
785
+ <div
786
+ class="progress-fill"
787
+ style="width: {(Object.values(surveyData).filter(v => v).length / 3) * 100}%"
788
+ ></div>
789
+ </div>
790
+ <p>Progress: {Object.values(surveyData).filter(v => v).length}/3 questions completed</p>
791
+ </div>
792
+
793
+ <button
794
+ on:click={handleSurveySubmit}
795
+ disabled={!isCompleted}
796
+ class="submit-survey-btn"
797
+ class:disabled={!isCompleted}
798
+ >
799
+ Submit Survey
800
+ </button>
801
+ </div>
802
+
803
+ <style>
804
+ .survey-demo {
805
+ max-width: 600px;
806
+ margin: 20px;
807
+ padding: 24px;
808
+ border: 1px solid #e2e8f0;
809
+ border-radius: 8px;
810
+ }
811
+
812
+ .survey-section {
813
+ margin-bottom: 24px;
814
+ }
815
+
816
+ .satisfaction-feedback {
817
+ margin-top: 8px;
818
+ padding: 8px 12px;
819
+ background: #f0f9ff;
820
+ border-radius: 6px;
821
+ font-weight: 500;
822
+ }
823
+
824
+ .survey-progress {
825
+ margin: 24px 0;
826
+ }
827
+
828
+ .progress-bar {
829
+ height: 8px;
830
+ background: #e5e7eb;
831
+ border-radius: 4px;
832
+ overflow: hidden;
833
+ margin-bottom: 8px;
834
+ }
835
+
836
+ .progress-fill {
837
+ height: 100%;
838
+ background: #3b82f6;
839
+ transition: width 0.3s ease;
840
+ }
841
+
842
+ .submit-survey-btn {
843
+ width: 100%;
844
+ padding: 12px 24px;
845
+ background: #3b82f6;
846
+ color: white;
847
+ border: none;
848
+ border-radius: 8px;
849
+ font-size: 16px;
850
+ cursor: pointer;
851
+ transition: all 0.2s;
852
+ }
853
+
854
+ .submit-survey-btn:hover:not(.disabled) {
855
+ background: #2563eb;
856
+ }
857
+
858
+ .submit-survey-btn.disabled {
859
+ background: #d1d5db;
860
+ color: #9ca3af;
861
+ cursor: not-allowed;
862
+ }
863
+ </style>
864
+ ```
865
+
866
+ ## Styling
867
+
868
+ The GroupRadioBox component can be styled using CSS custom properties:
869
+
870
+ ```css
871
+ .uniface-group-box {
872
+ --radio-spacing: 8px;
873
+ --radio-padding: 4px 8px;
874
+ --border-color: #e2e8f0;
875
+ --background-color: #ffffff;
876
+ --hover-background: #f9fafb;
877
+ --selected-color: #3b82f6;
878
+ }
879
+
880
+ /* Variant-specific styling */
881
+ .uniface-group-box.outlined {
882
+ border: 1px solid var(--border-color);
883
+ border-radius: 6px;
884
+ padding: 12px;
885
+ }
886
+
887
+ .uniface-group-box.filled {
888
+ background-color: #f8fafc;
889
+ border-radius: 6px;
890
+ padding: 12px;
891
+ }
892
+
893
+ .uniface-group-box.compact {
894
+ --radio-spacing: 4px;
895
+ --radio-padding: 2px 4px;
896
+ }
897
+ ```
898
+
899
+ ## Accessibility
900
+
901
+ The GroupRadioBox component includes several accessibility features:
902
+
903
+ - Keyboard navigation between radio buttons
904
+ - Focus management with `setFocus()` method
905
+ - ARIA labels and radio group semantics
906
+ - Screen reader announcements for selection changes
907
+ - Proper tab order management
908
+
909
+ ## Best Practices
910
+
911
+ 1. **Option Management**: Keep option arrays stable to prevent unnecessary re-renders
912
+ 2. **Default Selection**: Always provide a sensible default value for better UX
913
+ 3. **Validation**: Implement proper validation for required selections
914
+ 4. **User Feedback**: Provide clear visual feedback for selection changes
915
+ 5. **Accessibility**: Always provide meaningful labels and group descriptions
916
+ 6. **State Management**: Handle focus/blur events appropriately for form validation
917
+
918
+ ## License
919
+
920
+ MIT