@kubex/zinc 1.0.25 → 1.0.99

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 (199) hide show
  1. package/.claude/project.md +556 -0
  2. package/.github/workflows/js_build_and_deploy.yaml +9 -10
  3. package/dist/custom-elements.json +13575 -8856
  4. package/dist/vscode.html-custom-data.json +583 -48
  5. package/dist/web-types.json +1441 -181
  6. package/dist/zn.d.ts +1645 -660
  7. package/dist/zn.min.css +1 -1
  8. package/dist/zn.min.js +1412 -893
  9. package/docs/_utilities/code-previews.cjs +10 -1
  10. package/docs/assets/scripts/docs.js +42 -18
  11. package/docs/data/data-table.json +229 -66
  12. package/docs/data/empty.json +6 -0
  13. package/docs/data/products-table.json +41 -193
  14. package/docs/pages/components/action-bar.md +121 -6
  15. package/docs/pages/components/alert.md +118 -15
  16. package/docs/pages/components/animated-button.md +299 -0
  17. package/docs/pages/components/audio-select.md +534 -0
  18. package/docs/pages/components/bulk-actions.md +79 -5
  19. package/docs/pages/components/button-group.md +235 -27
  20. package/docs/pages/components/button.md +139 -1
  21. package/docs/pages/components/chart.md +365 -9
  22. package/docs/pages/components/checkbox.md +387 -58
  23. package/docs/pages/components/chip.md +253 -33
  24. package/docs/pages/components/collapsible.md +393 -46
  25. package/docs/pages/components/cols.md +152 -30
  26. package/docs/pages/components/confirm.md +182 -16
  27. package/docs/pages/components/copy-button.md +169 -6
  28. package/docs/pages/components/data-select.md +194 -15
  29. package/docs/pages/components/data-table-filter.md +96 -5
  30. package/docs/pages/components/data-table-search.md +451 -0
  31. package/docs/pages/components/data-table-sort.md +66 -5
  32. package/docs/pages/components/data-table.md +727 -66
  33. package/docs/pages/components/datepicker.md +402 -7
  34. package/docs/pages/components/defined-label.md +120 -5
  35. package/docs/pages/components/dialog.md +339 -59
  36. package/docs/pages/components/dropdown.md +366 -11
  37. package/docs/pages/components/editor.md +604 -7
  38. package/docs/pages/components/empty-state.md +315 -16
  39. package/docs/pages/components/expanding-action.md +212 -28
  40. package/docs/pages/components/file.md +421 -12
  41. package/docs/pages/components/filter-container.md +158 -5
  42. package/docs/pages/components/filter-wrapper.md +167 -6
  43. package/docs/pages/components/form-group.md +383 -6
  44. package/docs/pages/components/hover-container.md +237 -6
  45. package/docs/pages/components/icon-picker.md +121 -0
  46. package/docs/pages/components/icon.md +454 -48
  47. package/docs/pages/components/inline-edit.md +787 -19
  48. package/docs/pages/components/input-group.md +207 -13
  49. package/docs/pages/components/input.md +194 -0
  50. package/docs/pages/components/item.md +18 -0
  51. package/docs/pages/components/key-container.md +115 -0
  52. package/docs/pages/components/key.md +101 -0
  53. package/docs/pages/components/menu.md +512 -6
  54. package/docs/pages/components/note.md +239 -36
  55. package/docs/pages/components/opt-group.md +107 -0
  56. package/docs/pages/components/pagination.md +332 -6
  57. package/docs/pages/components/pane.md +222 -6
  58. package/docs/pages/components/panel.md +213 -26
  59. package/docs/pages/components/popup.md +1354 -6
  60. package/docs/pages/components/priority-list.md +233 -0
  61. package/docs/pages/components/progress-bar.md +387 -6
  62. package/docs/pages/components/radio-group.md +242 -5
  63. package/docs/pages/components/radio.md +474 -6
  64. package/docs/pages/components/rating.md +331 -7
  65. package/docs/pages/components/reveal.md +524 -6
  66. package/docs/pages/components/scroll-container.md +552 -6
  67. package/docs/pages/components/select.md +762 -160
  68. package/docs/pages/components/skeleton.md +473 -30
  69. package/docs/pages/components/slideout.md +261 -5
  70. package/docs/pages/components/sp.md +99 -41
  71. package/docs/pages/components/split-button.md +347 -9
  72. package/docs/pages/components/split-pane.md +445 -6
  73. package/docs/pages/components/stat.md +549 -9
  74. package/docs/pages/components/status-indicator.md +230 -1
  75. package/docs/pages/components/stepper.md +563 -6
  76. package/docs/pages/components/tabs.md +439 -13
  77. package/docs/pages/components/textarea.md +415 -17
  78. package/docs/pages/components/tile.md +385 -26
  79. package/docs/pages/components/toggle.md +424 -6
  80. package/docs/pages/components/tooltip.md +367 -0
  81. package/docs/pages/components/translation-group.md +210 -0
  82. package/docs/pages/components/translations.md +319 -19
  83. package/docs/pages/components/vertical-stepper.md +401 -8
  84. package/docs/pages/components/well.md +300 -3
  85. package/docs/pages/getting-started/form-controls.md +162 -0
  86. package/docs/pages/index.md +116 -15
  87. package/package.json +5 -6
  88. package/scss/_global-spacing.scss +4 -0
  89. package/scss/_root.scss +2 -2
  90. package/scss/boot.scss +19 -0
  91. package/scss/shared/layout.scss +5 -0
  92. package/scss/themes/_light.scss +3 -3
  93. package/src/components/alert/alert.scss +1 -0
  94. package/src/components/animated-button/README.md +306 -0
  95. package/src/components/animated-button/animated-button.component.ts +229 -0
  96. package/src/components/animated-button/animated-button.scss +228 -0
  97. package/src/components/animated-button/animated-button.test.ts +143 -0
  98. package/src/components/animated-button/index.ts +12 -0
  99. package/src/components/button/button.component.ts +5 -0
  100. package/src/components/button-group/button-group.component.ts +25 -13
  101. package/src/components/button-group/button-group.scss +6 -0
  102. package/src/components/checkbox/checkbox.component.ts +4 -0
  103. package/src/components/checkbox/checkbox.scss +7 -4
  104. package/src/components/checkbox-group/checkbox-group.scss +7 -0
  105. package/src/components/chip/chip.component.ts +7 -2
  106. package/src/components/chip/chip.scss +16 -2
  107. package/src/components/collapsible/collapsible.component.ts +27 -20
  108. package/src/components/cols/cols.component.ts +14 -2
  109. package/src/components/cols/cols.scss +6 -12
  110. package/src/components/confirm/confirm.component.ts +7 -0
  111. package/src/components/copy-button/copy-button.component.ts +12 -11
  112. package/src/components/data-select/data-select.component.ts +215 -44
  113. package/src/components/data-select/data-select.scss +66 -6
  114. package/src/components/data-select/providers/currency-data-provider.ts +20 -6
  115. package/src/components/data-select/providers/provider.ts +1 -0
  116. package/src/components/data-select/providers/us-state-data-provider.ts +68 -0
  117. package/src/components/data-table/data-table.component.ts +81 -22
  118. package/src/components/data-table-search/data-table-search.component.ts +184 -0
  119. package/src/components/data-table-search/data-table-search.scss +17 -0
  120. package/src/components/data-table-search/data-table-search.test.ts +11 -0
  121. package/src/components/data-table-search/index.ts +12 -0
  122. package/src/components/datepicker/datepicker.component.ts +347 -13
  123. package/src/components/dialog/dialog.component.ts +1 -1
  124. package/src/components/empty-state/empty-state.scss +6 -1
  125. package/src/components/header/header.scss +3 -3
  126. package/src/components/icon/icon.component.ts +23 -1
  127. package/src/components/icon/icon.scss +23 -0
  128. package/src/components/icon-picker/brand-icons.ts +24 -0
  129. package/src/components/icon-picker/icon-picker.component.ts +407 -0
  130. package/src/components/icon-picker/icon-picker.scss +205 -0
  131. package/src/components/icon-picker/index.ts +12 -0
  132. package/src/components/icon-picker/line-icons.ts +612 -0
  133. package/src/components/icon-picker/material-icons.ts +14543 -0
  134. package/src/components/inline-edit/inline-edit.component.ts +190 -46
  135. package/src/components/inline-edit/inline-edit.scss +29 -0
  136. package/src/components/inline-edit/inline-edit.test.ts +314 -1
  137. package/src/components/input/input.component.ts +324 -5
  138. package/src/components/input/input.scss +87 -0
  139. package/src/components/input-group/input-group.component.ts +28 -7
  140. package/src/components/input-group/input-group.scss +48 -10
  141. package/src/components/item/item.component.ts +24 -3
  142. package/src/components/item/item.scss +18 -0
  143. package/src/components/key/index.ts +12 -0
  144. package/src/components/key/key.component.ts +47 -0
  145. package/src/components/key/key.scss +38 -0
  146. package/src/components/key-container/index.ts +12 -0
  147. package/src/components/key-container/key-container.component.ts +142 -0
  148. package/src/components/key-container/key-container.scss +33 -0
  149. package/src/components/menu-item/menu-item.component.ts +20 -0
  150. package/src/components/menu-item/menu-item.scss +69 -2
  151. package/src/components/navbar/navbar.component.ts +103 -11
  152. package/src/components/navbar/navbar.scss +6 -1
  153. package/src/components/opt-group/index.ts +12 -0
  154. package/src/components/opt-group/opt-group.component.ts +74 -0
  155. package/src/components/opt-group/opt-group.scss +37 -0
  156. package/src/components/opt-group/opt-group.test.ts +27 -0
  157. package/src/components/option/option.component.ts +1 -16
  158. package/src/components/option/option.scss +4 -0
  159. package/src/components/panel/panel.component.ts +10 -8
  160. package/src/components/panel/panel.scss +20 -0
  161. package/src/components/priority-list/index.ts +12 -0
  162. package/src/components/priority-list/priority-list.component.ts +611 -0
  163. package/src/components/priority-list/priority-list.scss +185 -0
  164. package/src/components/priority-list/priority-list.test.ts +139 -0
  165. package/src/components/progress-bar/progress-bar.component.ts +22 -16
  166. package/src/components/radio/radio.scss +10 -3
  167. package/src/components/select/select.component.ts +812 -72
  168. package/src/components/select/select.scss +108 -2
  169. package/src/components/select/select.test.ts +147 -2
  170. package/src/components/settings-container/settings-container.component.ts +44 -19
  171. package/src/components/settings-container/settings-container.scss +1 -1
  172. package/src/components/skeleton/skeleton.component.ts +6 -1
  173. package/src/components/slideout/slideout.scss +8 -3
  174. package/src/components/sp/sp.component.ts +3 -1
  175. package/src/components/sp/sp.scss +19 -0
  176. package/src/components/stepper/stepper.component.ts +16 -10
  177. package/src/components/textarea/textarea.scss +0 -4
  178. package/src/components/tile/tile.component.ts +12 -3
  179. package/src/components/tile/tile.scss +1 -1
  180. package/src/components/timer/timer.component.ts +15 -2
  181. package/src/components/toggle/toggle.component.ts +29 -26
  182. package/src/components/toggle/toggle.scss +13 -1
  183. package/src/components/translation-group/index.ts +12 -0
  184. package/src/components/translation-group/translation-group.component.ts +207 -0
  185. package/src/components/translation-group/translation-group.scss +8 -0
  186. package/src/components/translations/translations.component.ts +90 -44
  187. package/src/components/translations/translations.scss +4 -0
  188. package/src/components/vertical-stepper/vertical-stepper.component.ts +14 -9
  189. package/src/events/events.ts +12 -7
  190. package/src/events/zn-language-change.ts +7 -0
  191. package/src/events/zn-purchase.ts +11 -0
  192. package/src/events/zn-redirect.ts +7 -0
  193. package/src/events/zn-reorder.ts +7 -0
  194. package/src/events/zn-search-change.ts +11 -0
  195. package/src/events/zn-submit.ts +1 -1
  196. package/src/form-control.scss +4 -0
  197. package/src/internal/form-navigation.ts +510 -0
  198. package/src/internal/form.ts +6 -0
  199. package/src/zinc.ts +91 -83
@@ -0,0 +1,534 @@
1
+ ---
2
+ meta:
3
+ title: Audio Select
4
+ description: Audio select allows you to choose audio files from a menu with built-in preview playback functionality.
5
+ layout: component
6
+ status: experimental
7
+ ---
8
+
9
+ ## Examples
10
+
11
+ ### Basic Audio Select
12
+
13
+ The audio select component combines a standard select dropdown with an integrated audio preview player. Use the `label` attribute to give the select an accessible label, provide an array of audio files via the `files` property, and control the selected value with the `value` attribute.
14
+
15
+ ```html:preview
16
+ <zn-audio-select
17
+ id="basic-audio-select"
18
+ label="Select an audio file"
19
+ placeholder="Choose a sound"
20
+ >
21
+ </zn-audio-select>
22
+
23
+ <script type="module">
24
+ const audioSelect = document.getElementById('basic-audio-select');
25
+
26
+ audioSelect.files = [
27
+ { name: 'Notification Sound', url: 'https://cdn.pixabay.com/download/audio/2022/03/15/audio_c8c8e8c5a3.mp3' },
28
+ { name: 'Alert Tone', url: 'https://cdn.pixabay.com/download/audio/2021/08/04/audio_12b0c7443c.mp3' },
29
+ { name: 'Chime', url: 'https://cdn.pixabay.com/download/audio/2022/03/10/audio_24f0b90e18.mp3' }
30
+ ];
31
+ </script>
32
+ ```
33
+
34
+ :::tip
35
+ The play/pause button in the prefix slot allows users to preview the selected audio file before confirming their choice. The audio automatically stops when a new selection is made or when the component is disconnected.
36
+ :::
37
+
38
+ ### Initial Value
39
+
40
+ Use the `value` attribute to set an initial selection. The value should match one of the URLs in your files array.
41
+
42
+ ```html:preview
43
+ <zn-audio-select
44
+ id="initial-value-audio"
45
+ label="Select notification sound"
46
+ placeholder="Choose a sound"
47
+ >
48
+ </zn-audio-select>
49
+
50
+ <script type="module">
51
+ const audioSelect = document.getElementById('initial-value-audio');
52
+
53
+ audioSelect.files = [
54
+ { name: 'Notification Sound', url: 'https://cdn.pixabay.com/download/audio/2022/03/15/audio_c8c8e8c5a3.mp3' },
55
+ { name: 'Alert Tone', url: 'https://cdn.pixabay.com/download/audio/2021/08/04/audio_12b0c7443c.mp3' },
56
+ { name: 'Chime', url: 'https://cdn.pixabay.com/download/audio/2022/03/10/audio_24f0b90e18.mp3' }
57
+ ];
58
+
59
+ // Set initial value
60
+ audioSelect.value = 'https://cdn.pixabay.com/download/audio/2021/08/04/audio_12b0c7443c.mp3';
61
+ </script>
62
+ ```
63
+
64
+ ### Custom Placeholder
65
+
66
+ Customize the placeholder text shown when no audio file is selected using the `placeholder` attribute.
67
+
68
+ ```html:preview
69
+ <zn-audio-select
70
+ id="custom-placeholder-audio"
71
+ label="Ringtone"
72
+ placeholder="Pick your ringtone"
73
+ >
74
+ </zn-audio-select>
75
+
76
+ <script type="module">
77
+ const audioSelect = document.getElementById('custom-placeholder-audio');
78
+
79
+ audioSelect.files = [
80
+ { name: 'Classic Ring', url: 'https://cdn.pixabay.com/download/audio/2022/03/15/audio_c8c8e8c5a3.mp3' },
81
+ { name: 'Modern Tone', url: 'https://cdn.pixabay.com/download/audio/2021/08/04/audio_12b0c7443c.mp3' },
82
+ { name: 'Gentle Chime', url: 'https://cdn.pixabay.com/download/audio/2022/03/10/audio_24f0b90e18.mp3' }
83
+ ];
84
+ </script>
85
+ ```
86
+
87
+ ### Interactive Preview Controls
88
+
89
+ The audio select includes an integrated play/pause checkbox in the prefix slot. Click the play button to preview the currently selected audio. The button automatically changes to a pause icon while audio is playing.
90
+
91
+ ```html:preview
92
+ <zn-audio-select
93
+ id="preview-demo-audio"
94
+ label="Test audio playback"
95
+ placeholder="Select to preview"
96
+ >
97
+ </zn-audio-select>
98
+
99
+ <div style="margin-top: 1rem; padding: 1rem; background: var(--zn-color-neutral-100); border-radius: 4px;">
100
+ <strong>Instructions:</strong>
101
+ <ol style="margin: 0.5rem 0 0 1.5rem; padding: 0;">
102
+ <li>Select an audio file from the dropdown</li>
103
+ <li>Click the play button (arrow icon) to start playback</li>
104
+ <li>Click the pause button to stop playback</li>
105
+ <li>Select a different file to automatically stop current playback</li>
106
+ </ol>
107
+ </div>
108
+
109
+ <script type="module">
110
+ const audioSelect = document.getElementById('preview-demo-audio');
111
+
112
+ audioSelect.files = [
113
+ { name: 'Short Beep', url: 'https://cdn.pixabay.com/download/audio/2022/03/15/audio_c8c8e8c5a3.mp3' },
114
+ { name: 'Notification Ping', url: 'https://cdn.pixabay.com/download/audio/2021/08/04/audio_12b0c7443c.mp3' },
115
+ { name: 'Alert Sound', url: 'https://cdn.pixabay.com/download/audio/2022/03/10/audio_24f0b90e18.mp3' }
116
+ ];
117
+ </script>
118
+ ```
119
+
120
+ :::tip
121
+ Audio playback is prevented when no file is selected. The play/pause button becomes functional only after selecting an audio file from the dropdown.
122
+ :::
123
+
124
+ ### Listening for Changes
125
+
126
+ The audio select emits a `zn-change` event when the selection changes. Access the selected URL through the `value` property.
127
+
128
+ ```html:preview
129
+ <zn-audio-select
130
+ id="event-audio-select"
131
+ label="Select your notification"
132
+ placeholder="Choose one"
133
+ >
134
+ </zn-audio-select>
135
+
136
+ <div style="margin-top: 1rem; padding: 1rem; background: var(--zn-color-neutral-100); border-radius: 4px;">
137
+ <strong>Selection:</strong>
138
+ <div id="audio-selection-log" style="margin-top: 0.5rem; font-family: monospace; font-size: 0.875rem;">
139
+ No selection yet
140
+ </div>
141
+ </div>
142
+
143
+ <script type="module">
144
+ const audioSelect = document.getElementById('event-audio-select');
145
+ const selectionLog = document.getElementById('audio-selection-log');
146
+
147
+ audioSelect.files = [
148
+ { name: 'Notification 1', url: 'https://cdn.pixabay.com/download/audio/2022/03/15/audio_c8c8e8c5a3.mp3' },
149
+ { name: 'Notification 2', url: 'https://cdn.pixabay.com/download/audio/2021/08/04/audio_12b0c7443c.mp3' },
150
+ { name: 'Notification 3', url: 'https://cdn.pixabay.com/download/audio/2022/03/10/audio_24f0b90e18.mp3' }
151
+ ];
152
+
153
+ audioSelect.addEventListener('zn-change', (e) => {
154
+ const selectedFile = audioSelect.files.find(f => f.url === e.target.value);
155
+ if (selectedFile) {
156
+ selectionLog.textContent = `Selected: ${selectedFile.name}\nURL: ${selectedFile.url}`;
157
+ } else {
158
+ selectionLog.textContent = 'No selection';
159
+ }
160
+ });
161
+ </script>
162
+ ```
163
+
164
+ ### Programmatic Control
165
+
166
+ Control the audio select programmatically by setting the `value` property or manipulating the `files` array.
167
+
168
+ ```html:preview
169
+ <zn-audio-select
170
+ id="programmatic-audio"
171
+ label="Programmable audio select"
172
+ placeholder="Select a sound"
173
+ >
174
+ </zn-audio-select>
175
+
176
+ <div style="margin-top: 1rem; display: flex; gap: 0.5rem; flex-wrap: wrap;">
177
+ <zn-button id="select-first" size="small">Select First</zn-button>
178
+ <zn-button id="select-second" size="small">Select Second</zn-button>
179
+ <zn-button id="clear-selection" size="small">Clear</zn-button>
180
+ <zn-button id="add-file" size="small">Add File</zn-button>
181
+ </div>
182
+
183
+ <script type="module">
184
+ const audioSelect = document.getElementById('programmatic-audio');
185
+
186
+ const initialFiles = [
187
+ { name: 'Sound A', url: 'https://cdn.pixabay.com/download/audio/2022/03/15/audio_c8c8e8c5a3.mp3' },
188
+ { name: 'Sound B', url: 'https://cdn.pixabay.com/download/audio/2021/08/04/audio_12b0c7443c.mp3' }
189
+ ];
190
+
191
+ audioSelect.files = [...initialFiles];
192
+
193
+ document.getElementById('select-first').addEventListener('click', () => {
194
+ audioSelect.value = audioSelect.files[0]?.url || '';
195
+ });
196
+
197
+ document.getElementById('select-second').addEventListener('click', () => {
198
+ audioSelect.value = audioSelect.files[1]?.url || '';
199
+ });
200
+
201
+ document.getElementById('clear-selection').addEventListener('click', () => {
202
+ audioSelect.value = '';
203
+ });
204
+
205
+ document.getElementById('add-file').addEventListener('click', () => {
206
+ const newFile = {
207
+ name: `Sound ${audioSelect.files.length + 1}`,
208
+ url: 'https://cdn.pixabay.com/download/audio/2022/03/10/audio_24f0b90e18.mp3'
209
+ };
210
+ audioSelect.files = [...audioSelect.files, newFile];
211
+ });
212
+ </script>
213
+ ```
214
+
215
+ ### Dynamic File Lists
216
+
217
+ Update the available audio files dynamically by setting the `files` property. This is useful for loading files from an API or updating based on user actions.
218
+
219
+ ```html:preview
220
+ <div class="form-spacing">
221
+ <zn-select id="category-selector" label="Audio category">
222
+ <zn-option value="">Select a category</zn-option>
223
+ <zn-option value="notifications">Notifications</zn-option>
224
+ <zn-option value="alarms">Alarms</zn-option>
225
+ <zn-option value="ringtones">Ringtones</zn-option>
226
+ </zn-select>
227
+
228
+ <zn-audio-select
229
+ id="dynamic-audio-select"
230
+ label="Available sounds"
231
+ placeholder="First select a category"
232
+ >
233
+ </zn-audio-select>
234
+ </div>
235
+
236
+ <script type="module">
237
+ const categorySelector = document.getElementById('category-selector');
238
+ const audioSelect = document.getElementById('dynamic-audio-select');
239
+
240
+ const audioCategories = {
241
+ notifications: [
242
+ { name: 'Gentle Ping', url: 'https://cdn.pixabay.com/download/audio/2022/03/15/audio_c8c8e8c5a3.mp3' },
243
+ { name: 'Quick Beep', url: 'https://cdn.pixabay.com/download/audio/2021/08/04/audio_12b0c7443c.mp3' }
244
+ ],
245
+ alarms: [
246
+ { name: 'Wake Up Call', url: 'https://cdn.pixabay.com/download/audio/2022/03/10/audio_24f0b90e18.mp3' },
247
+ { name: 'Morning Alert', url: 'https://cdn.pixabay.com/download/audio/2022/03/15/audio_c8c8e8c5a3.mp3' }
248
+ ],
249
+ ringtones: [
250
+ { name: 'Classic Ring', url: 'https://cdn.pixabay.com/download/audio/2021/08/04/audio_12b0c7443c.mp3' },
251
+ { name: 'Modern Tone', url: 'https://cdn.pixabay.com/download/audio/2022/03/10/audio_24f0b90e18.mp3' }
252
+ ]
253
+ };
254
+
255
+ categorySelector.addEventListener('zn-change', (e) => {
256
+ const category = e.target.value;
257
+ if (category && audioCategories[category]) {
258
+ audioSelect.files = audioCategories[category];
259
+ audioSelect.value = '';
260
+ audioSelect.placeholder = 'Select a sound';
261
+ } else {
262
+ audioSelect.files = [];
263
+ audioSelect.value = '';
264
+ audioSelect.placeholder = 'First select a category';
265
+ }
266
+ });
267
+ </script>
268
+ ```
269
+
270
+ ### Form Integration
271
+
272
+ The audio select component works with standard HTML forms. The selected audio URL is submitted as the form value.
273
+
274
+ ```html:preview
275
+ <form id="audio-form">
276
+ <zn-audio-select
277
+ id="form-audio-select"
278
+ name="notificationSound"
279
+ label="Notification sound"
280
+ placeholder="Choose your notification"
281
+ >
282
+ </zn-audio-select>
283
+ <br />
284
+ <zn-button type="submit" variant="primary">Submit</zn-button>
285
+ <zn-button type="reset">Reset</zn-button>
286
+ </form>
287
+
288
+ <script type="module">
289
+ const form = document.getElementById('audio-form');
290
+ const audioSelect = document.getElementById('form-audio-select');
291
+
292
+ audioSelect.files = [
293
+ { name: 'Chime', url: 'https://cdn.pixabay.com/download/audio/2022/03/15/audio_c8c8e8c5a3.mp3' },
294
+ { name: 'Bell', url: 'https://cdn.pixabay.com/download/audio/2021/08/04/audio_12b0c7443c.mp3' },
295
+ { name: 'Ding', url: 'https://cdn.pixabay.com/download/audio/2022/03/10/audio_24f0b90e18.mp3' }
296
+ ];
297
+
298
+ form.addEventListener('submit', (e) => {
299
+ e.preventDefault();
300
+ const formData = new FormData(form);
301
+ const data = Object.fromEntries(formData);
302
+ alert('Form submitted!\n\n' + JSON.stringify(data, null, 2));
303
+ });
304
+
305
+ form.addEventListener('reset', () => {
306
+ audioSelect.value = '';
307
+ });
308
+ </script>
309
+ ```
310
+
311
+ ### Real-world Example: Audio Settings Panel
312
+
313
+ A complete example showing how to use the audio select in a settings interface for configuring notification sounds.
314
+
315
+ ```html:preview
316
+ <div style="max-width: 600px; padding: 1.5rem; background: var(--zn-color-neutral-50); border-radius: 8px; border: 1px solid var(--zn-color-neutral-200);">
317
+ <h3 style="margin-top: 0;">Audio Notification Settings</h3>
318
+
319
+ <form id="notification-settings-form" class="form-spacing">
320
+ <zn-checkbox id="enable-notifications" checked>
321
+ Enable audio notifications
322
+ </zn-checkbox>
323
+
324
+ <zn-audio-select
325
+ id="new-message-sound"
326
+ name="newMessageSound"
327
+ label="New message"
328
+ placeholder="Select a sound"
329
+ >
330
+ </zn-audio-select>
331
+
332
+ <zn-audio-select
333
+ id="mention-sound"
334
+ name="mentionSound"
335
+ label="@mention"
336
+ placeholder="Select a sound"
337
+ >
338
+ </zn-audio-select>
339
+
340
+ <zn-audio-select
341
+ id="call-sound"
342
+ name="callSound"
343
+ label="Incoming call"
344
+ placeholder="Select a sound"
345
+ >
346
+ </zn-audio-select>
347
+
348
+ <div style="display: flex; gap: 0.5rem; margin-top: 1rem;">
349
+ <zn-button type="submit" variant="primary">Save Settings</zn-button>
350
+ <zn-button type="reset">Reset</zn-button>
351
+ </div>
352
+ </form>
353
+ </div>
354
+
355
+ <script type="module">
356
+ const form = document.getElementById('notification-settings-form');
357
+ const enableNotifications = document.getElementById('enable-notifications');
358
+ const newMessageSound = document.getElementById('new-message-sound');
359
+ const mentionSound = document.getElementById('mention-sound');
360
+ const callSound = document.getElementById('call-sound');
361
+
362
+ // Sample audio files
363
+ const audioFiles = [
364
+ { name: 'Gentle Ping', url: 'https://cdn.pixabay.com/download/audio/2022/03/15/audio_c8c8e8c5a3.mp3' },
365
+ { name: 'Quick Beep', url: 'https://cdn.pixabay.com/download/audio/2021/08/04/audio_12b0c7443c.mp3' },
366
+ { name: 'Soft Chime', url: 'https://cdn.pixabay.com/download/audio/2022/03/10/audio_24f0b90e18.mp3' }
367
+ ];
368
+
369
+ // Set audio files for all selects
370
+ [newMessageSound, mentionSound, callSound].forEach(select => {
371
+ select.files = audioFiles;
372
+ });
373
+
374
+ // Enable/disable audio selects based on checkbox
375
+ function updateAudioSelectsState() {
376
+ const enabled = enableNotifications.checked;
377
+ [newMessageSound, mentionSound, callSound].forEach(select => {
378
+ select.style.opacity = enabled ? '1' : '0.5';
379
+ select.style.pointerEvents = enabled ? 'auto' : 'none';
380
+ });
381
+ }
382
+
383
+ enableNotifications.addEventListener('zn-change', updateAudioSelectsState);
384
+ updateAudioSelectsState();
385
+
386
+ form.addEventListener('submit', (e) => {
387
+ e.preventDefault();
388
+ if (!enableNotifications.checked) {
389
+ alert('Audio notifications are disabled');
390
+ return;
391
+ }
392
+ const formData = new FormData(form);
393
+ const data = Object.fromEntries(formData);
394
+ alert('Settings saved!\n\n' + JSON.stringify(data, null, 2));
395
+ });
396
+ </script>
397
+ ```
398
+
399
+ ## Properties
400
+
401
+ | Property | Attribute | Description | Type | Default |
402
+ |----------|-----------|-------------|------|---------|
403
+ | `value` | `value` | The currently selected audio file URL. When set, the audio player loads this URL for preview. | `string` | `''` |
404
+ | `label` | `label` | The label text displayed above the select control. For labels containing HTML, use the `label` slot instead. | `string` | `''` |
405
+ | `placeholder` | `placeholder` | Placeholder text shown in the dropdown when no audio file is selected. | `string` | `''` |
406
+ | `files` | `files` | Array of audio files available for selection. Each file object must have `name` (display text) and `url` (audio file URL) properties. | `AudioFile[]` | `[]` |
407
+
408
+ ### AudioFile Interface
409
+
410
+ ```typescript
411
+ interface AudioFile {
412
+ name: string; // Display name shown in the dropdown
413
+ url: string; // URL to the audio file
414
+ }
415
+ ```
416
+
417
+ ## Events
418
+
419
+ | Event | Description | Event Detail |
420
+ |-------|-------------|--------------|
421
+ | `zn-change` | Emitted when the selected audio file changes. The event is triggered by the underlying `zn-select` component and bubbles up. Access the new value via `event.target.value`. | Inherited from `zn-select` |
422
+ | `zn-input` | Emitted when the select receives input. Inherited from the underlying `zn-select` component. | Inherited from `zn-select` |
423
+ | `zn-focus` | Emitted when the select gains focus. | Inherited from `zn-select` |
424
+ | `zn-blur` | Emitted when the select loses focus. | Inherited from `zn-select` |
425
+
426
+ :::tip
427
+ The audio select inherits all events from the `zn-select` component. Refer to the [select documentation](/components/select#events) for complete event details.
428
+ :::
429
+
430
+ ## Slots
431
+
432
+ | Name | Description |
433
+ |------|-------------|
434
+ | (default) | The default slot is not used in the audio select component. Options are generated automatically from the `files` property. |
435
+ | `actions` | Optional slot for action buttons or controls. Inherited from `zn-select`. |
436
+ | `footer` | Optional slot for footer content. Inherited from `zn-select`. |
437
+
438
+ :::warning
439
+ **Note:** Unlike the standard `zn-select`, the audio select component auto-generates its options from the `files` property. Manual `zn-option` elements in the default slot will be overwritten.
440
+ :::
441
+
442
+ ## CSS Parts
443
+
444
+ | Part | Description |
445
+ |------|-------------|
446
+ | `base` | The component's base wrapper element. |
447
+
448
+ :::tip
449
+ The audio select wraps a `zn-select` component internally, so all CSS parts from `zn-select` are also available. See the [select component CSS parts](/components/select#css-parts) for additional customization options.
450
+ :::
451
+
452
+ ## CSS Custom Properties
453
+
454
+ | Name | Description |
455
+ |------|-------------|
456
+ | `--example` | An example CSS custom property (inherited from base component). |
457
+
458
+ :::tip
459
+ The audio select inherits custom properties from the underlying `zn-select` component. See the [select documentation](/components/select) for available custom properties.
460
+ :::
461
+
462
+ ## Methods
463
+
464
+ The audio select component provides these methods:
465
+
466
+ | Method | Description | Arguments | Returns |
467
+ |--------|-------------|-----------|---------|
468
+ | `stopAudio()` | Stops any currently playing audio, resets playback to the beginning, and updates the play/pause button state. | None | `void` |
469
+
470
+ :::tip
471
+ Additional methods are available through the underlying `zn-select` component. Use standard DOM methods like `querySelector()` to access the internal select and call its methods (e.g., `focus()`, `blur()`, `show()`, `hide()`).
472
+ :::
473
+
474
+ ## Behavior Details
475
+
476
+ ### Audio Playback
477
+
478
+ - The audio preview player is implemented using the HTML5 `Audio` API
479
+ - Clicking play loads and plays the currently selected audio file
480
+ - Audio automatically stops when:
481
+ - The user clicks the pause button
482
+ - A different audio file is selected
483
+ - The component is disconnected from the DOM
484
+ - If audio playback fails (e.g., invalid URL, network error), an error is logged to the console and the button returns to the play state
485
+ - Attempting to play without selecting a file is prevented
486
+
487
+ ### Selection Behavior
488
+
489
+ - The component automatically creates a disabled placeholder option from the `placeholder` property
490
+ - Each file in the `files` array generates a corresponding `zn-option` element
491
+ - When `value` changes, any playing audio is automatically stopped and the new audio URL is loaded
492
+ - The internal `zn-select` handles all dropdown behavior, keyboard navigation, and accessibility features
493
+
494
+ ### Play/Pause Button
495
+
496
+ - Implemented as a `zn-checkbox` in the prefix slot
497
+ - Shows a play icon (arrow) when audio is not playing
498
+ - Shows a pause icon when audio is playing
499
+ - Uses primary color when checked (playing) and secondary color when unchecked (stopped)
500
+ - Button state is synchronized with audio playback state
501
+
502
+ ## Accessibility
503
+
504
+ The audio select component inherits all accessibility features from the underlying `zn-select` component:
505
+
506
+ - Proper ARIA labels and roles for screen readers
507
+ - Full keyboard navigation support
508
+ - Focus management
509
+ - High contrast mode support
510
+
511
+ The play/pause checkbox should include an `aria-label` for screen reader users (this is implemented by default in the component).
512
+
513
+ ## Best Practices
514
+
515
+ 1. **File URLs**: Ensure all audio file URLs are accessible and use HTTPS for security
516
+ 2. **File Formats**: Use widely supported audio formats (MP3, OGG, WAV) for maximum browser compatibility
517
+ 3. **File Names**: Provide clear, descriptive names in the `name` property for better user experience
518
+ 4. **File Size**: Keep audio files small for quick preview loading (notification sounds should typically be under 5 seconds)
519
+ 5. **Error Handling**: Audio playback errors are logged to the console but not shown to users; consider adding custom error handling for production use
520
+ 6. **Performance**: The component stops audio when disconnected, preventing memory leaks
521
+ 7. **Accessibility**: Always provide a meaningful `label` attribute for screen reader users
522
+
523
+ ## Browser Compatibility
524
+
525
+ The audio select component requires:
526
+ - Modern browser with Web Components support
527
+ - HTML5 Audio API support
528
+ - All browsers supported by the base Zinc component library
529
+
530
+ ## Related Components
531
+
532
+ - [Select](/components/select) - The underlying select component
533
+ - [Checkbox](/components/checkbox) - Used for the play/pause button
534
+ - [Option](/components/option) - Used for dropdown options
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  meta:
3
3
  title: Bulk Actions
4
- description:
4
+ description: A dynamic form builder component that allows users to create multiple field-value pairs for bulk operations. Supports various input types including text, select options, numbers, dates, and booleans.
5
5
  layout: component
6
6
  ---
7
7
 
@@ -15,12 +15,86 @@ layout: component
15
15
 
16
16
  ## Examples
17
17
 
18
- ### First Example
18
+ ### Basic Usage with Options
19
19
 
20
- TODO
20
+ Create a bulk actions component with predefined dropdown options for each action.
21
21
 
22
- ### Second Example
22
+ ```html:preview
23
+ <zn-bulk-actions
24
+ actions="[{&quot;id&quot;:&quot;status&quot;,&quot;name&quot;:&quot;status&quot;,&quot;options&quot;:{&quot;open&quot;:&quot;Open&quot;,&quot;in_progress&quot;:&quot;In Progress&quot;,&quot;closed&quot;:&quot;Closed&quot;}},{&quot;id&quot;:&quot;assignee&quot;,&quot;name&quot;:&quot;assignee&quot;,&quot;options&quot;:{&quot;john&quot;:&quot;John Doe&quot;,&quot;jane&quot;:&quot;Jane Smith&quot;,&quot;bob&quot;:&quot;Bob Johnson&quot;}}]"
25
+ name="ticket-actions">
26
+ </zn-bulk-actions>
27
+ ```
28
+
29
+ ### Text Input Fields
30
+
31
+ Use text input fields for free-form data entry by omitting the `options` property.
32
+
33
+ ```html:preview
34
+ <zn-bulk-actions
35
+ actions="[{&quot;id&quot;:&quot;tag&quot;,&quot;name&quot;:&quot;tag&quot;},{&quot;id&quot;:&quot;note&quot;,&quot;name&quot;:&quot;note&quot;},{&quot;id&quot;:&quot;reference&quot;,&quot;name&quot;:&quot;reference&quot;}]"
36
+ name="text-actions">
37
+ </zn-bulk-actions>
38
+ ```
39
+
40
+ ### Number Input Fields
41
+
42
+ Use the `type: "number"` property to create number input fields.
43
+
44
+ ```html:preview
45
+ <zn-bulk-actions
46
+ actions="[{&quot;id&quot;:&quot;quantity&quot;,&quot;name&quot;:&quot;quantity&quot;,&quot;type&quot;:&quot;number&quot;},{&quot;id&quot;:&quot;price&quot;,&quot;name&quot;:&quot;price&quot;,&quot;type&quot;:&quot;number&quot;},{&quot;id&quot;:&quot;discount&quot;,&quot;name&quot;:&quot;discount&quot;,&quot;type&quot;:&quot;number&quot;}]"
47
+ name="number-actions">
48
+ </zn-bulk-actions>
49
+ ```
50
+
51
+ ### Date Input Fields
52
+
53
+ Use the `type: "date"` property to create date picker fields.
54
+
55
+ ```html:preview
56
+ <zn-bulk-actions
57
+ actions="[{&quot;id&quot;:&quot;start_date&quot;,&quot;name&quot;:&quot;start date&quot;,&quot;type&quot;:&quot;date&quot;},{&quot;id&quot;:&quot;end_date&quot;,&quot;name&quot;:&quot;end date&quot;,&quot;type&quot;:&quot;date&quot;},{&quot;id&quot;:&quot;due_date&quot;,&quot;name&quot;:&quot;due date&quot;,&quot;type&quot;:&quot;date&quot;}]"
58
+ name="date-actions">
59
+ </zn-bulk-actions>
60
+ ```
61
+
62
+ ### Boolean Input Fields
63
+
64
+ Use the `type: "bool"` or `type: "boolean"` property to create true/false dropdown fields.
65
+
66
+ ```html:preview
67
+ <zn-bulk-actions
68
+ actions="[{&quot;id&quot;:&quot;active&quot;,&quot;name&quot;:&quot;active&quot;,&quot;type&quot;:&quot;bool&quot;},{&quot;id&quot;:&quot;featured&quot;,&quot;name&quot;:&quot;featured&quot;,&quot;type&quot;:&quot;boolean&quot;},{&quot;id&quot;:&quot;visible&quot;,&quot;name&quot;:&quot;visible&quot;,&quot;type&quot;:&quot;bool&quot;}]"
69
+ name="boolean-actions">
70
+ </zn-bulk-actions>
71
+ ```
72
+
73
+ ### Mixed Input Types
74
+
75
+ Combine different input types in a single bulk actions component.
23
76
 
24
- TODO
77
+ ```html:preview
78
+ <zn-bulk-actions
79
+ actions="[{&quot;id&quot;:&quot;category&quot;,&quot;name&quot;:&quot;category&quot;,&quot;options&quot;:{&quot;bug&quot;:&quot;Bug&quot;,&quot;feature&quot;:&quot;Feature&quot;,&quot;improvement&quot;:&quot;Improvement&quot;}},{&quot;id&quot;:&quot;effort&quot;,&quot;name&quot;:&quot;effort (hours)&quot;,&quot;type&quot;:&quot;number&quot;},{&quot;id&quot;:&quot;blocked&quot;,&quot;name&quot;:&quot;blocked&quot;,&quot;type&quot;:&quot;bool&quot;},{&quot;id&quot;:&quot;deadline&quot;,&quot;name&quot;:&quot;deadline&quot;,&quot;type&quot;:&quot;date&quot;},{&quot;id&quot;:&quot;description&quot;,&quot;name&quot;:&quot;description&quot;}]"
80
+ name="mixed-actions">
81
+ </zn-bulk-actions>
82
+ ```
83
+
84
+ ### In a Form Context
85
+
86
+ Use bulk actions within a form to collect structured data for submission.
87
+
88
+ ```html:preview
89
+ <form>
90
+ <h3>Update Multiple Items</h3>
91
+ <zn-bulk-actions
92
+ actions="[{&quot;id&quot;:&quot;priority&quot;,&quot;name&quot;:&quot;priority&quot;,&quot;options&quot;:{&quot;low&quot;:&quot;Low&quot;,&quot;medium&quot;:&quot;Medium&quot;,&quot;high&quot;:&quot;High&quot;,&quot;critical&quot;:&quot;Critical&quot;}},{&quot;id&quot;:&quot;department&quot;,&quot;name&quot;:&quot;department&quot;,&quot;options&quot;:{&quot;eng&quot;:&quot;Engineering&quot;,&quot;sales&quot;:&quot;Sales&quot;,&quot;support&quot;:&quot;Support&quot;}}]"
93
+ name="bulk-update">
94
+ </zn-bulk-actions>
95
+ <br />
96
+ <zn-button type="submit" color="success">Apply Changes</zn-button>
97
+ </form>
98
+ ```
25
99
 
26
100