chuijs 4.0.1 → 4.0.3

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 (222) hide show
  1. package/CHANGELOG.md +113 -0
  2. package/README.md +43 -632
  3. package/framework/appLayout/default/chui_app_layout.js +314 -273
  4. package/framework/appLayout/default/global_style.css +93 -53
  5. package/framework/components/chui_accordion/accordion.js +29 -26
  6. package/framework/components/chui_accordion/styles.css +6 -5
  7. package/framework/components/chui_action_sheet/action_sheet.js +59 -33
  8. package/framework/components/chui_action_sheet/styles.css +2 -1
  9. package/framework/components/chui_affix/affix.js +11 -6
  10. package/framework/components/chui_alert/alert.js +23 -14
  11. package/framework/components/chui_avatar/avatar.js +23 -22
  12. package/framework/components/chui_avatar_group/avatar_group.js +21 -19
  13. package/framework/components/chui_backtop/backtop.js +35 -19
  14. package/framework/components/chui_badge/badge.js +15 -13
  15. package/framework/components/chui_breadcrumb/breadcrumb.js +15 -13
  16. package/framework/components/chui_button/button.js +42 -22
  17. package/framework/components/chui_button/styles.css +2 -2
  18. package/framework/components/chui_calendar/calendar.js +12 -10
  19. package/framework/components/chui_card/card.js +43 -23
  20. package/framework/components/chui_chat/chat.js +72 -33
  21. package/framework/components/chui_clipboard_history/clipboard_history.js +30 -21
  22. package/framework/components/chui_clipboard_history/styles.css +4 -2
  23. package/framework/components/chui_code/code.js +2 -2
  24. package/framework/components/chui_code/styles.css +2 -2
  25. package/framework/components/chui_code_editor/code_editor.js +47 -31
  26. package/framework/components/chui_code_editor/styles.css +3 -2
  27. package/framework/components/chui_command_palette/command_palette.js +60 -37
  28. package/framework/components/chui_console/console.js +5 -5
  29. package/framework/components/chui_console/styles.css +1 -1
  30. package/framework/components/chui_content_block/content_block.js +33 -19
  31. package/framework/components/chui_content_block/styles.css +2 -2
  32. package/framework/components/chui_context_menu/context_menu.js +9 -4
  33. package/framework/components/chui_custom_element/custom_element.js +22 -15
  34. package/framework/components/chui_data_grid/data_grid.js +396 -234
  35. package/framework/components/chui_data_grid/styles.css +10 -8
  36. package/framework/components/chui_descriptions/descriptions.js +34 -17
  37. package/framework/components/chui_details/details.js +32 -26
  38. package/framework/components/chui_details/styles.css +5 -4
  39. package/framework/components/chui_diff_viewer/diff_viewer.js +91 -66
  40. package/framework/components/chui_diff_viewer/styles.css +1 -1
  41. package/framework/components/chui_divider/divider.js +13 -11
  42. package/framework/components/chui_drawer/drawer.js +27 -25
  43. package/framework/components/chui_drop_zone/drop_zone.js +31 -21
  44. package/framework/components/chui_empty_state/empty_state.js +20 -15
  45. package/framework/components/chui_fieldset/fieldset.js +37 -20
  46. package/framework/components/chui_fieldset/styles.css +1 -1
  47. package/framework/components/chui_file_explorer/file_explorer.js +157 -86
  48. package/framework/components/chui_file_explorer/styles.css +2 -1
  49. package/framework/components/chui_form/form.js +31 -19
  50. package/framework/components/chui_form/styles.css +1 -1
  51. package/framework/components/chui_gantt/gantt.js +64 -40
  52. package/framework/components/chui_graphs/graphs.js +301 -200
  53. package/framework/components/chui_graphs/styles.css +1 -1
  54. package/framework/components/chui_hero/hero.js +40 -22
  55. package/framework/components/chui_html_block/html_block.js +6 -6
  56. package/framework/components/chui_html_block/styles.css +2 -2
  57. package/framework/components/chui_hx/hx.js +3 -3
  58. package/framework/components/chui_hx/styles.css +11 -4
  59. package/framework/components/chui_icons/icons.js +2109 -2109
  60. package/framework/components/chui_icons/styles.css +2 -2
  61. package/framework/components/chui_inputs/chui_check_box/check_box.js +31 -19
  62. package/framework/components/chui_inputs/chui_check_box/styles.css +18 -18
  63. package/framework/components/chui_inputs/chui_chips/chips.js +50 -40
  64. package/framework/components/chui_inputs/chui_chips/styles.css +4 -2
  65. package/framework/components/chui_inputs/chui_color_picker/color_picker.js +36 -24
  66. package/framework/components/chui_inputs/chui_combo_box/combo_box.js +100 -82
  67. package/framework/components/chui_inputs/chui_combo_box/styles.css +14 -12
  68. package/framework/components/chui_inputs/chui_date/date.js +102 -66
  69. package/framework/components/chui_inputs/chui_date/styles.css +12 -11
  70. package/framework/components/chui_inputs/chui_date_range/date_range.js +40 -29
  71. package/framework/components/chui_inputs/chui_datetime/datetime.js +35 -27
  72. package/framework/components/chui_inputs/chui_email/email.js +43 -31
  73. package/framework/components/chui_inputs/chui_email/styles.css +5 -5
  74. package/framework/components/chui_inputs/chui_file/file.js +68 -41
  75. package/framework/components/chui_inputs/chui_file/styles.css +13 -12
  76. package/framework/components/chui_inputs/chui_hotkey/hotkey.js +61 -36
  77. package/framework/components/chui_inputs/chui_masked/masked.js +39 -28
  78. package/framework/components/chui_inputs/chui_mention/mention.js +77 -30
  79. package/framework/components/chui_inputs/chui_multi_combo_box/multi_combo_box.js +173 -153
  80. package/framework/components/chui_inputs/chui_multi_combo_box/styles.css +9 -7
  81. package/framework/components/chui_inputs/chui_number/number.js +58 -41
  82. package/framework/components/chui_inputs/chui_number/styles.css +7 -7
  83. package/framework/components/chui_inputs/chui_otp/otp.js +38 -29
  84. package/framework/components/chui_inputs/chui_password/password.js +58 -36
  85. package/framework/components/chui_inputs/chui_password/styles.css +8 -8
  86. package/framework/components/chui_inputs/chui_radio_button/radio_button.js +37 -25
  87. package/framework/components/chui_inputs/chui_radio_button/styles.css +20 -20
  88. package/framework/components/chui_inputs/chui_rating/rating.js +26 -22
  89. package/framework/components/chui_inputs/chui_select_box/select_box.js +102 -78
  90. package/framework/components/chui_inputs/chui_select_box/styles.css +11 -11
  91. package/framework/components/chui_inputs/chui_slider/slider.js +29 -26
  92. package/framework/components/chui_inputs/chui_slider/styles.css +2 -1
  93. package/framework/components/chui_inputs/chui_text/styles.css +8 -8
  94. package/framework/components/chui_inputs/chui_text/text.js +65 -44
  95. package/framework/components/chui_inputs/chui_text_area/styles.css +6 -6
  96. package/framework/components/chui_inputs/chui_text_area/text_area.js +51 -28
  97. package/framework/components/chui_inputs/chui_time/styles.css +5 -3
  98. package/framework/components/chui_inputs/chui_time/time.js +38 -27
  99. package/framework/components/chui_inputs/chui_toggle/styles.css +3 -3
  100. package/framework/components/chui_inputs/chui_toggle/toggle.js +16 -16
  101. package/framework/components/chui_json_editor/json_editor.js +53 -43
  102. package/framework/components/chui_json_viewer/json_viewer.js +52 -33
  103. package/framework/components/chui_json_viewer/styles.css +3 -2
  104. package/framework/components/chui_kanban/kanban.js +52 -34
  105. package/framework/components/chui_kbd/kbd.js +12 -10
  106. package/framework/components/chui_label/label.js +14 -12
  107. package/framework/components/chui_label/styles.css +2 -2
  108. package/framework/components/chui_link/link.js +27 -20
  109. package/framework/components/chui_list/list.js +31 -27
  110. package/framework/components/chui_list/styles.css +2 -1
  111. package/framework/components/chui_markdown_editor/markdown_editor.js +60 -44
  112. package/framework/components/chui_media/audio.js +326 -227
  113. package/framework/components/chui_media/audio_styles.css +40 -21
  114. package/framework/components/chui_media/image.js +70 -38
  115. package/framework/components/chui_media/image_compare.js +52 -21
  116. package/framework/components/chui_media/image_styles.css +3 -3
  117. package/framework/components/chui_media/video.js +155 -62
  118. package/framework/components/chui_media/video_styles.css +33 -16
  119. package/framework/components/chui_menu_bar/menu_bar.js +26 -24
  120. package/framework/components/chui_menu_bar/styles.css +4 -2
  121. package/framework/components/chui_modal/modal.js +44 -43
  122. package/framework/components/chui_modal/styles.css +3 -2
  123. package/framework/components/chui_notification/notification.js +50 -34
  124. package/framework/components/chui_notification/notification_download.js +31 -25
  125. package/framework/components/chui_notification/notification_download_progress.css +3 -2
  126. package/framework/components/chui_notification/notification_download_progress.js +47 -41
  127. package/framework/components/chui_notification/notification_update.js +23 -16
  128. package/framework/components/chui_notification/status_plate.js +2 -2
  129. package/framework/components/chui_notification/styles_download.css +1 -1
  130. package/framework/components/chui_notification/styles_update.css +1 -1
  131. package/framework/components/chui_org_chart/org_chart.js +74 -35
  132. package/framework/components/chui_pagination/pagination.js +62 -27
  133. package/framework/components/chui_paragraph/paragraph.js +2 -2
  134. package/framework/components/chui_paragraph/styles.css +1 -1
  135. package/framework/components/chui_popover/popover.js +49 -28
  136. package/framework/components/chui_popups/popups.js +137 -108
  137. package/framework/components/chui_popups/styles.css +2 -2
  138. package/framework/components/chui_print_button/print_button.js +33 -23
  139. package/framework/components/chui_progress_bar/progress_bar.js +23 -15
  140. package/framework/components/chui_progress_bar/styles.css +2 -2
  141. package/framework/components/chui_progress_ring/progress_ring.js +17 -15
  142. package/framework/components/chui_qrcode/qrcode.js +75 -31
  143. package/framework/components/chui_query_builder/query_builder.js +216 -123
  144. package/framework/components/chui_radio_group/radio_group.js +36 -26
  145. package/framework/components/chui_radio_group/styles.css +1 -1
  146. package/framework/components/chui_result/result.js +26 -16
  147. package/framework/components/chui_scheduler/scheduler.js +57 -35
  148. package/framework/components/chui_scheduler/styles.css +6 -2
  149. package/framework/components/chui_segmented_control/segmented_control.js +27 -21
  150. package/framework/components/chui_settings/settings.js +122 -48
  151. package/framework/components/chui_shortcut_help/shortcut_help.js +55 -32
  152. package/framework/components/chui_sidebar_nav/sidebar_nav.js +33 -23
  153. package/framework/components/chui_skeleton/skeleton.js +29 -24
  154. package/framework/components/chui_slideshow/slideshow.js +60 -41
  155. package/framework/components/chui_slideshow/styles.css +18 -12
  156. package/framework/components/chui_spinner/spinner.js +8 -8
  157. package/framework/components/chui_spinner/styles.css +0 -1
  158. package/framework/components/chui_split_button/split_button.js +23 -18
  159. package/framework/components/chui_split_button/styles.css +1 -1
  160. package/framework/components/chui_splitter/splitter.js +35 -28
  161. package/framework/components/chui_statistic/statistic.js +65 -38
  162. package/framework/components/chui_status_bar/status_bar.js +11 -9
  163. package/framework/components/chui_stepper/stepper.js +27 -22
  164. package/framework/components/chui_sticky_bar/sticky_bar.js +9 -4
  165. package/framework/components/chui_sticky_bar/styles.css +3 -1
  166. package/framework/components/chui_tabs/chui_tabs.js +28 -22
  167. package/framework/components/chui_tabs/styles.css +3 -3
  168. package/framework/components/chui_text_editor/styles.css +20 -19
  169. package/framework/components/chui_text_editor/text_editor.js +85 -61
  170. package/framework/components/chui_text_editor/text_editor_panel.js +346 -284
  171. package/framework/components/chui_theme_toggle/theme_toggle.js +27 -22
  172. package/framework/components/chui_timeline/timeline.js +14 -12
  173. package/framework/components/chui_toast_queue/toast_queue.js +52 -46
  174. package/framework/components/chui_toolbar/toolbar.js +20 -13
  175. package/framework/components/chui_tooltip/tooltip.js +37 -24
  176. package/framework/components/chui_tour/styles.css +8 -3
  177. package/framework/components/chui_tour/tour.js +61 -27
  178. package/framework/components/chui_transfer/styles.css +2 -1
  179. package/framework/components/chui_transfer/transfer.js +75 -42
  180. package/framework/components/chui_tree_table/tree_table.js +43 -29
  181. package/framework/components/chui_tree_view/styles.css +4 -2
  182. package/framework/components/chui_tree_view/tree_view.js +142 -99
  183. package/framework/components/chui_watermark/watermark.js +24 -16
  184. package/framework/components/chui_webview/styles.css +2 -2
  185. package/framework/components/chui_webview/webview.js +62 -50
  186. package/framework/components/telegram_bot/chui_telegram_bot.js +71 -64
  187. package/framework/modules/chui_a11y/chui_a11y.js +77 -46
  188. package/framework/modules/chui_animations/animations.js +42 -42
  189. package/framework/modules/chui_animations/styles.css +1 -1
  190. package/framework/modules/chui_bridge/preload.js +56 -26
  191. package/framework/modules/chui_functions.js +52 -50
  192. package/framework/modules/chui_highlight/chui_highlight.js +25 -22
  193. package/framework/modules/chui_i18n/chui_i18n.js +9 -7
  194. package/framework/modules/chui_i18n/locales/a11y.js +5 -5
  195. package/framework/modules/chui_i18n/locales/app_layout.js +5 -5
  196. package/framework/modules/chui_i18n/locales/calendar.js +3 -3
  197. package/framework/modules/chui_i18n/locales/common.js +3 -3
  198. package/framework/modules/chui_i18n/locales/data.js +36 -26
  199. package/framework/modules/chui_i18n/locales/editors.js +40 -13
  200. package/framework/modules/chui_i18n/locales/feedback.js +3 -3
  201. package/framework/modules/chui_i18n/locales/forms.js +8 -8
  202. package/framework/modules/chui_i18n/locales/graphics.js +8 -8
  203. package/framework/modules/chui_i18n/locales/media.js +4 -4
  204. package/framework/modules/chui_i18n/locales/navigation.js +8 -8
  205. package/framework/modules/chui_i18n/locales/validate.js +3 -3
  206. package/framework/modules/chui_json/chui_json.js +9 -9
  207. package/framework/modules/chui_layout/chui_layout.js +12 -10
  208. package/framework/modules/chui_logger/chui_logger.js +29 -25
  209. package/framework/modules/chui_page/page.js +33 -27
  210. package/framework/modules/chui_page/styles.css +3 -26
  211. package/framework/modules/chui_qr/chui_qr.js +158 -67
  212. package/framework/modules/chui_scrollbar/chui_scrollbar.js +35 -24
  213. package/framework/modules/chui_scrollbar/styles.css +3 -1
  214. package/framework/modules/chui_services/chui_channels.js +76 -11
  215. package/framework/modules/chui_services/chui_services.js +39 -31
  216. package/framework/modules/chui_services/desktop.js +149 -30
  217. package/framework/modules/chui_sortable/chui_sortable.js +17 -12
  218. package/framework/modules/chui_validate/chui_validate.js +7 -4
  219. package/framework/tray_bar/chui_menu_items.js +136 -46
  220. package/index.d.ts +4814 -0
  221. package/index.js +449 -334
  222. package/package.json +79 -68
@@ -1,12 +1,12 @@
1
1
  const { Icon, Icons } = require("../chui_icons/icons");
2
- const {Label} = require('../chui_label/label');
3
- const Store = require('electron-store');
4
- const {makeKeyboardButton} = require("../../modules/chui_a11y/chui_a11y");
5
- const {Log} = require("../../modules/chui_logger/chui_logger");
6
- const {I18n} = require("../../modules/chui_i18n/chui_i18n");
7
- const {optionOr} = require("../../modules/chui_functions");
8
- const {Select} = require("../chui_inputs/chui_select_box/select_box");
9
- const {Toggle} = require("../chui_inputs/chui_toggle/toggle");
2
+ const { Label } = require("../chui_label/label");
3
+ const Store = require("electron-store");
4
+ const { makeKeyboardButton } = require("../../modules/chui_a11y/chui_a11y");
5
+ const { Log } = require("../../modules/chui_logger/chui_logger");
6
+ const { I18n } = require("../../modules/chui_i18n/chui_i18n");
7
+ const { optionOr } = require("../../modules/chui_functions");
8
+ const { Select } = require("../chui_inputs/chui_select_box/select_box");
9
+ const { Toggle } = require("../chui_inputs/chui_toggle/toggle");
10
10
  const store = new Store();
11
11
 
12
12
  /**
@@ -43,13 +43,28 @@ class Audio {
43
43
  #destroyed = false;
44
44
  #onPlay = () => this.#renderPlayState(true);
45
45
  #onPause = () => this.#renderPlayState(false);
46
- #onTimeUpdate = () => { this.#displayBufferedAmount(); this.#renderProgress(); };
47
- #onDurationChange = () => { this.#setSliderMax(); this.#renderProgress(); };
48
- constructor(options = {
49
- src: String(), autoplay: Boolean(), loop: Boolean(), muted: Boolean(), volume: Number(),
50
- pin: String(), width: String(), height: String(), label: String()
51
- }) {
52
- require('../../modules/chui_functions').setStyles(__dirname + "/audio_styles.css", 'chUiJS_Audio');
46
+ #onTimeUpdate = () => {
47
+ this.#displayBufferedAmount();
48
+ this.#renderProgress();
49
+ };
50
+ #onDurationChange = () => {
51
+ this.#setSliderMax();
52
+ this.#renderProgress();
53
+ };
54
+ constructor(
55
+ options = {
56
+ src: String(),
57
+ autoplay: Boolean(),
58
+ loop: Boolean(),
59
+ muted: Boolean(),
60
+ volume: Number(),
61
+ pin: String(),
62
+ width: String(),
63
+ height: String(),
64
+ label: String(),
65
+ }
66
+ ) {
67
+ require("../../modules/chui_functions").setStyles(__dirname + "/audio_styles.css", "chUiJS_Audio");
53
68
  this.#chui_at.preload = "metadata";
54
69
  this.#chui_at.controls = false;
55
70
  // Плеер — именованная группа: без имени скринридер читает подряд безымянные кнопки
@@ -64,8 +79,8 @@ class Audio {
64
79
  if (options.width !== undefined) this.#chui_ap_main.style.width = options.width;
65
80
  if (options.height !== undefined) this.#chui_ap_main.style.height = options.height;
66
81
  // ПОЛОСА ПРОГРЕССА
67
- this.#chui_ap_time1 = new Label({text: `0:00`});
68
- this.#chui_ap_time2 = new Label({text: `0:00`});
82
+ this.#chui_ap_time1 = new Label({ text: `0:00` });
83
+ this.#chui_ap_time2 = new Label({ text: `0:00` });
69
84
  this.#chui_ap_seek.type = "range";
70
85
  this.#chui_ap_seek.id = "chui_ap_seek";
71
86
  this.#chui_ap_seek.max = "0";
@@ -162,7 +177,7 @@ class Audio {
162
177
  if (this.#chui_ap_fx_dropdown.contains(event.target)) return;
163
178
  if (this.#chui_ap_fx_icon.contains(event.target)) return;
164
179
  this.#toggleFx(false);
165
- }
180
+ };
166
181
  #playPause = async () => {
167
182
  if (this.getPaused()) {
168
183
  try {
@@ -171,30 +186,37 @@ class Audio {
171
186
  Log.error(`Audio: воспроизведение не началось: ${error}`);
172
187
  }
173
188
  } else this.pause();
174
- }
189
+ };
175
190
  #renderPlayState(playing) {
176
- this.#setIcon(this.#chui_ap_play_pause, playing ? Icons.AUDIO_VIDEO.PAUSE : Icons.AUDIO_VIDEO.PLAY_ARROW, "18px");
191
+ this.#setIcon(
192
+ this.#chui_ap_play_pause,
193
+ playing ? Icons.AUDIO_VIDEO.PAUSE : Icons.AUDIO_VIDEO.PLAY_ARROW,
194
+ "18px"
195
+ );
177
196
  this.#setLabel(this.#chui_ap_play_pause, playing ? I18n.t("media.pause") : I18n.t("media.play"));
178
197
  }
179
198
  #renderVolume = () => {
180
199
  const доля = Math.min(100, Math.max(0, Math.round(this.#chui_at.volume * 100)));
181
200
  this.#chui_ap_volume.value = String(доля);
182
201
  this.#chui_ap_volume.disabled = this.getMuted();
183
- this.#chui_ap_main.style.setProperty('--volume-before-width', `${доля}%`);
184
- this.#setIcon(this.#chui_ap_volume_icon, this.getMuted() || доля === 0
185
- ? Icons.AUDIO_VIDEO.VOLUME_OFF : Icons.AUDIO_VIDEO.VOLUME_UP, "18px");
202
+ this.#chui_ap_main.style.setProperty("--volume-before-width", `${доля}%`);
203
+ this.#setIcon(
204
+ this.#chui_ap_volume_icon,
205
+ this.getMuted() || доля === 0 ? Icons.AUDIO_VIDEO.VOLUME_OFF : Icons.AUDIO_VIDEO.VOLUME_UP,
206
+ "18px"
207
+ );
186
208
  this.#setLabel(this.#chui_ap_volume_icon, I18n.t(this.getMuted() ? "media.unmute" : "media.mute"));
187
- }
209
+ };
188
210
  #displayBufferedAmount = () => {
189
211
  const max = Number(this.#chui_ap_seek.max);
190
212
  if (!(max > 0)) return;
191
213
  try {
192
- const конец = Math.floor(this.#chui_at.buffered.end(0) / max * 100);
214
+ const конец = Math.floor((this.#chui_at.buffered.end(0) / max) * 100);
193
215
  this.#chui_ap_seek_buf.style.width = `${Math.min(100, Math.max(0, конец))}%`;
194
216
  } catch (_error) {
195
217
  // Буфер ещё пуст (метаданные не пришли) — рисовать нечего
196
218
  }
197
- }
219
+ };
198
220
  // Длительность приходит с метаданными: без неё полоса прокрутки делила бы на ноль,
199
221
  // а у живого потока её нет вовсе (duration = Infinity)
200
222
  #setSliderMax = () => {
@@ -203,7 +225,7 @@ class Audio {
203
225
  this.#chui_ap_seek.max = известна ? String(Math.floor(duration)) : "0";
204
226
  // Без известной длительности ползунок бессмысленен: перетаскивание отправляло бы плеер в начало
205
227
  this.#chui_ap_seek.disabled = !известна;
206
- }
228
+ };
207
229
  #renderProgress = () => {
208
230
  const max = Number(this.#chui_ap_seek.max);
209
231
  const position = this.getCurrentTime();
@@ -212,7 +234,7 @@ class Audio {
212
234
  // «0:07 / 0:00» читалось бы как поломка: у источника без длительности только прошедшее
213
235
  this.#chui_ap_time1.setText(this.#calculateTime(position));
214
236
  this.#chui_ap_time2.setText("");
215
- this.#chui_ap_main.style.setProperty('--seek-before-width', '0%');
237
+ this.#chui_ap_main.style.setProperty("--seek-before-width", "0%");
216
238
  return;
217
239
  }
218
240
  this.#chui_ap_time1.setText(this.#calculateTime(position));
@@ -220,22 +242,24 @@ class Audio {
220
242
  this.#chui_ap_seek.value = String(position);
221
243
  // Доля ограничена сотней: `max` — округлённая длительность, а позиция идёт дальше,
222
244
  // и без ограничения полоса целиком заливалась акцентом
223
- const доля = Math.min(100, Math.max(0, Math.floor(position / max * 100)));
224
- this.#chui_ap_main.style.setProperty('--seek-before-width', `${доля}%`);
225
- }
245
+ const доля = Math.min(100, Math.max(0, Math.floor((position / max) * 100)));
246
+ this.#chui_ap_main.style.setProperty("--seek-before-width", `${доля}%`);
247
+ };
226
248
  #calculateTime = (secs) => {
227
249
  const seconds = Number.isFinite(Number(secs)) ? Number(secs) : 0;
228
250
  const minutes = Math.floor(seconds / 60);
229
251
  const rest = Math.floor(seconds % 60);
230
252
  return `${minutes}:${rest < 10 ? `0${rest}` : `${rest}`}`;
231
- }
253
+ };
232
254
  #onMediaError = () => {
233
255
  const код = this.#chui_at.error === null ? undefined : this.#chui_at.error.code;
234
256
  const причина = Audio.#ERRORS[код] === undefined ? "" : `: ${I18n.t(Audio.#ERRORS[код])}`;
235
257
  Log.error(`Audio: ошибка воспроизведения${причина}`);
236
- this.#setStatus(`${I18n.t("media.audioNotPlaying", {reason: I18n.t("media.error.interrupted")})}${причина}`);
258
+ this.#setStatus(`${I18n.t("media.audioNotPlaying", { reason: I18n.t("media.error.interrupted") })}${причина}`);
259
+ };
260
+ #setStatus(text) {
261
+ this.#status.innerText = text;
237
262
  }
238
- #setStatus(text) { this.#status.innerText = text; }
239
263
  #setButton(node, label, icon, size) {
240
264
  node.innerHTML = new Icon(icon, size).getHTML();
241
265
  node.setAttribute("aria-label", label);
@@ -285,67 +309,133 @@ class Audio {
285
309
  else this.#chui_ap_main.setAttribute("data_pin", значение);
286
310
  return this;
287
311
  }
288
- getPin() { return this.#pin; }
312
+ getPin() {
313
+ return this.#pin;
314
+ }
289
315
  // === ЭКВАЛАЙЗЕР ===
290
316
  /** Включить или выключить эквалайзер: то же, что делает выключатель в панели */
291
- setEqualizerEnabled(boolean = Boolean()) { return this.#chui_audio_fx.setEnabled(boolean), this; }
292
- isEqualizerEnabled() { return this.#chui_audio_fx.isEnabled(); }
317
+ setEqualizerEnabled(boolean = Boolean()) {
318
+ return (this.#chui_audio_fx.setEnabled(boolean), this);
319
+ }
320
+ isEqualizerEnabled() {
321
+ return this.#chui_audio_fx.isEnabled();
322
+ }
293
323
  /** Раскрыть или свернуть панель эквалайзера */
294
- setEqualizerOpen(open = Boolean()) { this.#toggleFx(open === true); return this; }
324
+ setEqualizerOpen(open = Boolean()) {
325
+ this.#toggleFx(open === true);
326
+ return this;
327
+ }
295
328
  /** Показать панель эквалайзера, если она скрыта, и наоборот */
296
- isEqualizerOpen() { return this.#chui_ap_fx_dropdown.classList.contains("fx_open"); }
329
+ isEqualizerOpen() {
330
+ return this.#chui_ap_fx_dropdown.classList.contains("fx_open");
331
+ }
297
332
  /** Прочитать сохранённое состояние эквалайзера из настроек */
298
- restoreFX() { this.#chui_audio_fx.restore(); return this; }
333
+ restoreFX() {
334
+ this.#chui_audio_fx.restore();
335
+ return this;
336
+ }
299
337
  // === СТАНДАРТНЫЕ ВОЗМОЖНОСТИ `<audio>` ===
300
338
  /** Сам элемент: для всего, чего нет в списке ниже */
301
- getAudio() { return this.#chui_at; }
339
+ getAudio() {
340
+ return this.#chui_at;
341
+ }
302
342
  /** Воспроизведение: промис, как у `<audio>` */
303
- play() { return this.#chui_at.play(); }
304
- pause() { this.#chui_at.pause(); return this; }
305
- load() { this.#chui_at.load(); return this; }
306
- canPlayType(type = String()) { return this.#chui_at.canPlayType(type); }
307
- getSrc() { return this.#chui_at.getAttribute("src") ?? ""; }
343
+ play() {
344
+ return this.#chui_at.play();
345
+ }
346
+ pause() {
347
+ this.#chui_at.pause();
348
+ return this;
349
+ }
350
+ load() {
351
+ this.#chui_at.load();
352
+ return this;
353
+ }
354
+ canPlayType(type = String()) {
355
+ return this.#chui_at.canPlayType(type);
356
+ }
357
+ getSrc() {
358
+ return this.#chui_at.getAttribute("src") ?? "";
359
+ }
308
360
  setSrc(url = String()) {
309
361
  this.#chui_at.setAttribute("src", url);
310
362
  this.#chui_at.load();
311
363
  return this;
312
364
  }
313
- getSrcObject() { return this.#chui_at.srcObject; }
365
+ getSrcObject() {
366
+ return this.#chui_at.srcObject;
367
+ }
314
368
  /** Живой поток — штатное `srcObject`, а не путь */
315
369
  setSrcObject(object) {
316
370
  this.#chui_at.srcObject = object;
317
371
  return this;
318
372
  }
319
- getCurrentTime() { return this.#chui_at.currentTime; }
373
+ getCurrentTime() {
374
+ return this.#chui_at.currentTime;
375
+ }
320
376
  setCurrentTime(seconds = Number()) {
321
377
  this.#chui_at.currentTime = Number(seconds);
322
378
  // Подписи и заливка не ждут `timeupdate`: перемотка из кода видна сразу
323
379
  this.#renderProgress();
324
380
  return this;
325
381
  }
326
- getDuration() { return this.#chui_at.duration; }
327
- getBuffered() { return this.#chui_at.buffered; }
328
- getPaused() { return this.#chui_at.paused; }
329
- getEnded() { return this.#chui_at.ended; }
330
- getReadyState() { return this.#chui_at.readyState; }
331
- getVolume() { return this.#chui_at.volume; }
382
+ getDuration() {
383
+ return this.#chui_at.duration;
384
+ }
385
+ getBuffered() {
386
+ return this.#chui_at.buffered;
387
+ }
388
+ getPaused() {
389
+ return this.#chui_at.paused;
390
+ }
391
+ getEnded() {
392
+ return this.#chui_at.ended;
393
+ }
394
+ getReadyState() {
395
+ return this.#chui_at.readyState;
396
+ }
397
+ getVolume() {
398
+ return this.#chui_at.volume;
399
+ }
332
400
  setVolume(value = Number()) {
333
401
  this.#chui_at.volume = Math.min(1, Math.max(0, Number(value)));
334
402
  return this;
335
403
  }
336
- getMuted() { return this.#chui_at.muted; }
404
+ getMuted() {
405
+ return this.#chui_at.muted;
406
+ }
337
407
  setMuted(boolean = Boolean()) {
338
408
  this.#chui_at.muted = boolean === true;
339
409
  return this;
340
410
  }
341
- getPlaybackRate() { return this.#chui_at.playbackRate; }
342
- setPlaybackRate(rate = Number()) { this.#chui_at.playbackRate = Number(rate); return this; }
343
- getDefaultPlaybackRate() { return this.#chui_at.defaultPlaybackRate; }
344
- setDefaultPlaybackRate(rate = Number()) { this.#chui_at.defaultPlaybackRate = Number(rate); return this; }
345
- getLoop() { return this.#chui_at.loop; }
346
- setLoop(boolean = Boolean()) { this.#chui_at.loop = boolean === true; return this; }
347
- getAutoplay() { return this.#chui_at.autoplay; }
348
- setAutoplay(boolean = Boolean()) { this.#chui_at.autoplay = boolean === true; return this; }
411
+ getPlaybackRate() {
412
+ return this.#chui_at.playbackRate;
413
+ }
414
+ setPlaybackRate(rate = Number()) {
415
+ this.#chui_at.playbackRate = Number(rate);
416
+ return this;
417
+ }
418
+ getDefaultPlaybackRate() {
419
+ return this.#chui_at.defaultPlaybackRate;
420
+ }
421
+ setDefaultPlaybackRate(rate = Number()) {
422
+ this.#chui_at.defaultPlaybackRate = Number(rate);
423
+ return this;
424
+ }
425
+ getLoop() {
426
+ return this.#chui_at.loop;
427
+ }
428
+ setLoop(boolean = Boolean()) {
429
+ this.#chui_at.loop = boolean === true;
430
+ return this;
431
+ }
432
+ getAutoplay() {
433
+ return this.#chui_at.autoplay;
434
+ }
435
+ setAutoplay(boolean = Boolean()) {
436
+ this.#chui_at.autoplay = boolean === true;
437
+ return this;
438
+ }
349
439
  addEventListener(type = String(), listener = () => {}) {
350
440
  this.#chui_at.addEventListener(type, listener);
351
441
  return this;
@@ -354,7 +444,9 @@ class Audio {
354
444
  this.#chui_at.removeEventListener(type, listener);
355
445
  return this;
356
446
  }
357
- set() { return this.#chui_ap_main; }
447
+ set() {
448
+ return this.#chui_ap_main;
449
+ }
358
450
  detach() {
359
451
  this.pause();
360
452
  this.#chui_ap_main.remove();
@@ -366,7 +458,7 @@ class Audio {
366
458
  this.#destroyed = true;
367
459
  this.#chui_at.pause();
368
460
  this.#chui_at.removeAttribute("src");
369
- this.#chui_at.load(); // отпускает декодер и прочитанный файл
461
+ this.#chui_at.load(); // отпускает декодер и прочитанный файл
370
462
  this.#unsetMediaActions();
371
463
  document.removeEventListener("mousedown", this.#onFxOutside);
372
464
  this.#chui_audio_fx.destroy();
@@ -378,34 +470,34 @@ class Audio {
378
470
  2: "media.error.notFound",
379
471
  3: "media.error.decode",
380
472
  4: "media.error.format",
381
- }
473
+ };
382
474
  }
383
475
  class AudioFX {
384
- #chui_ap_equalizer_main = document.createElement('chui_ap_equalizer_main')
385
- #chui_ap_equalizer_controls = document.createElement('chui_ap_equalizer_controls')
386
- #chui_ap_equalizer_block = document.createElement('chui_ap_equalizer_block')
387
- #chui_ap_equalizer_preamp_block = document.createElement("chui_ap_equalizer_preamp_block")
388
- #chui_ap_equalizer_band_block = document.createElement("chui_ap_equalizer_band_block")
476
+ #chui_ap_equalizer_main = document.createElement("chui_ap_equalizer_main");
477
+ #chui_ap_equalizer_controls = document.createElement("chui_ap_equalizer_controls");
478
+ #chui_ap_equalizer_block = document.createElement("chui_ap_equalizer_block");
479
+ #chui_ap_equalizer_preamp_block = document.createElement("chui_ap_equalizer_preamp_block");
480
+ #chui_ap_equalizer_band_block = document.createElement("chui_ap_equalizer_band_block");
389
481
  /* Поле пресетов и переключатель — общекитовые `Select` и `Toggle`, вложенные в панель:
390
482
  клавиатура, роли и состояния у них уже есть, а размеры для полосы панели задаёт
391
483
  `audio_styles.css`. Прежде тут были свои элементы, и список пресетов ломался:
392
484
  при ограниченной высоте слоя `Select` сжимал строки до 11 px — лечится `flex: none`
393
485
  у опций (`chui_select_box/styles.css`) */
394
- #switch = new Toggle({ label: I18n.t("media.enableEqualizer") })
395
- #presets = new Select()
396
- #eqBands = [60, 170, 310, 600, 1000, 3000, 6000, 12000, 14000, 16000]
486
+ #switch = new Toggle({ label: I18n.t("media.enableEqualizer") });
487
+ #presets = new Select();
488
+ #eqBands = [60, 170, 310, 600, 1000, 3000, 6000, 12000, 14000, 16000];
397
489
  // Слайдеры эквалайзера по id: узлы свои, берём их из карты, а не поиском по документу
398
490
  #nodes = new Map();
399
491
  #media = undefined;
400
492
  #filters = undefined;
401
- #fx_status = "chuijs.framework.settings.fx_status"
402
- #fx_preset = "chuijs.framework.settings.fx_preset"
493
+ #fx_status = "chuijs.framework.settings.fx_status";
494
+ #fx_preset = "chuijs.framework.settings.fx_preset";
403
495
  #audioContext = new AudioContext();
404
496
  #destroyed = false;
405
497
  constructor(audio) {
406
498
  this.#media = this.#audioContext.createMediaElementSource(audio);
407
499
  this.#filters = this.#eqBands.map((band, i) => {
408
- let filter = this.#audioContext.createBiquadFilter()
500
+ let filter = this.#audioContext.createBiquadFilter();
409
501
  if (i === 0) {
410
502
  filter.type = "lowshelf";
411
503
  } else if (i === this.#eqBands.length - 1) {
@@ -413,55 +505,58 @@ class AudioFX {
413
505
  } else {
414
506
  filter.type = "peaking";
415
507
  }
416
- filter.gain.value = 0
417
- filter.Q.value = 1
418
- filter.frequency.value = band
419
- return filter
420
- })
508
+ filter.gain.value = 0;
509
+ filter.Q.value = 1;
510
+ filter.frequency.value = band;
511
+ return filter;
512
+ });
421
513
  this.#filters.reduce((prev, curr) => {
422
- prev.connect(curr)
423
- return curr
424
- })
514
+ prev.connect(curr);
515
+ return curr;
516
+ });
425
517
  this.#media.connect(this.#filters[0]);
426
518
  this.#filters[this.#filters.length - 1].connect(this.#audioContext.destination);
427
519
  //
428
- this.#chui_ap_equalizer_preamp_block.appendChild(this.#setSliderPreamp(this.#filters))
429
- this.#filters.forEach((filter) => this.#chui_ap_equalizer_band_block.appendChild(this.#setSliderBand(filter)))
520
+ this.#chui_ap_equalizer_preamp_block.appendChild(this.#setSliderPreamp(this.#filters));
521
+ this.#filters.forEach((filter) => this.#chui_ap_equalizer_band_block.appendChild(this.#setSliderBand(filter)));
430
522
  // Пресеты: подпись варианта — перевод, значение — имя пресета, поэтому выбор
431
523
  // читается из события списка, а не сверкой подписи
432
- this.#presets.addOptions(...AudioFX.PRESETS.map((preset) => ({
433
- title: I18n.t(preset.titleKey), value: preset.name
434
- })))
524
+ this.#presets.addOptions(
525
+ ...AudioFX.PRESETS.map((preset) => ({
526
+ title: I18n.t(preset.titleKey),
527
+ value: preset.name,
528
+ }))
529
+ );
435
530
  // Видимой подписи у поля нет: имя для скринридера ставим вводу (так же делал
436
531
  // прежний свой список, у которого подписи не было вовсе)
437
- this.#presets.set().querySelector("input").setAttribute("aria-label", I18n.t("media.preset"))
438
- this.#presets.addValueChangeListener((event) => this.#usePreset(event.detail.value))
532
+ this.#presets.set().querySelector("input").setAttribute("aria-label", I18n.t("media.preset"));
533
+ this.#presets.addValueChangeListener((event) => this.#usePreset(event.detail.value));
439
534
  // Переключатель — общекитовый `Toggle`; подпись он отдаёт в `aria-label`
440
535
  this.#switch.addChangeListener(() => {
441
- if (this.#switch.getValue()) this.#fx_ON(this.#audioContext)
442
- else this.#fx_OFF(this.#audioContext)
443
- })
536
+ if (this.#switch.getValue()) this.#fx_ON(this.#audioContext);
537
+ else this.#fx_OFF(this.#audioContext);
538
+ });
444
539
  //
445
- this.#chui_ap_equalizer_controls.appendChild(this.#presets.set())
446
- this.#chui_ap_equalizer_controls.appendChild(this.#switch.set())
540
+ this.#chui_ap_equalizer_controls.appendChild(this.#presets.set());
541
+ this.#chui_ap_equalizer_controls.appendChild(this.#switch.set());
447
542
  //
448
- this.#chui_ap_equalizer_block.appendChild(this.#chui_ap_equalizer_preamp_block)
449
- this.#chui_ap_equalizer_block.appendChild(this.#chui_ap_equalizer_band_block)
543
+ this.#chui_ap_equalizer_block.appendChild(this.#chui_ap_equalizer_preamp_block);
544
+ this.#chui_ap_equalizer_block.appendChild(this.#chui_ap_equalizer_band_block);
450
545
  //
451
- this.#chui_ap_equalizer_main.appendChild(this.#chui_ap_equalizer_controls)
452
- this.#chui_ap_equalizer_main.appendChild(this.#chui_ap_equalizer_block)
546
+ this.#chui_ap_equalizer_main.appendChild(this.#chui_ap_equalizer_controls);
547
+ this.#chui_ap_equalizer_main.appendChild(this.#chui_ap_equalizer_block);
453
548
  // По умолчанию эквалайзер выключен — и вид полосы должен говорить то же: пока
454
549
  // `restoreFX()` не позвал хозяин, выключатель выключен, а дорожки уже серые
455
- this.#setStatusBlock(false)
550
+ this.#setStatusBlock(false);
456
551
  }
457
552
  #usePreset(name = String()) {
458
- this.#filters.forEach((filter) => this.#setPreset(filter, name, true))
459
- this.#setPresetName(name)
553
+ this.#filters.forEach((filter) => this.#setPreset(filter, name, true));
554
+ this.#setPresetName(name);
460
555
  }
461
556
  /** Имя пресета в поле: значение ставится извне, поэтому без уведомления слушателей */
462
557
  #setPresetName(name = String()) {
463
- const known = AudioFX.PRESETS.some((preset) => preset.name === name)
464
- this.#presets.setValue(known ? name : AudioFX.PRESETS[0].name, true)
558
+ const known = AudioFX.PRESETS.some((preset) => preset.name === name);
559
+ this.#presets.setValue(known ? name : AudioFX.PRESETS[0].name, true);
465
560
  }
466
561
  #fx_ON(audioContext) {
467
562
  try {
@@ -472,146 +567,147 @@ class AudioFX {
472
567
  this.#media.connect(this.#filters[0]);
473
568
  this.#filters[this.#filters.length - 1].connect(audioContext.destination);
474
569
  }
475
- store.delete(this.#fx_status)
476
- store.set(this.#fx_status, true)
477
- this.#setStatusBlock(true)
570
+ store.delete(this.#fx_status);
571
+ store.set(this.#fx_status, true);
572
+ this.#setStatusBlock(true);
478
573
  }
479
574
  #fx_OFF(audioContext) {
480
575
  this.#filters[this.#filters.length - 1].disconnect(audioContext.destination);
481
576
  this.#media.disconnect(this.#filters[0]);
482
577
  this.#media.connect(audioContext.destination);
483
- store.delete(this.#fx_status)
484
- store.set(this.#fx_status, false)
485
- this.#setStatusBlock(false)
578
+ store.delete(this.#fx_status);
579
+ store.set(this.#fx_status, false);
580
+ this.#setStatusBlock(false);
486
581
  }
487
582
  #setPreset(filter, name) {
488
- store.delete(this.#fx_preset)
489
- store.set(this.#fx_preset, name)
490
- let filter_test = this.#getPreset(name)
491
- this.#renderPreampSlider(undefined, filter_test, filter)
492
- let input = filter_test.inputs.filter(input => input.id === String(filter.frequency.value))[0]
493
- this.#renderSlider(input, filter, filter_test.preamp)
583
+ store.delete(this.#fx_preset);
584
+ store.set(this.#fx_preset, name);
585
+ let filter_test = this.#getPreset(name);
586
+ this.#renderPreampSlider(undefined, filter_test, filter);
587
+ let input = filter_test.inputs.filter((input) => input.id === String(filter.frequency.value))[0];
588
+ this.#renderSlider(input, filter, filter_test.preamp);
494
589
  }
495
590
  #setStatusBlock(status) {
496
591
  //
497
592
  // Поле пресетов при выключенном эквалайзере не отвечает, а выключатель трогать
498
593
  // нельзя: он и есть способ включить эквалайзер обратно (родной флажок в выключенном
499
594
  // состоянии не шлёт `change` — включить было бы нечем)
500
- this.#presets.setDisabled(!status)
595
+ this.#presets.setDisabled(!status);
501
596
  //
502
597
  for (let band of this.#eqBands) {
503
598
  let sliderBand = this.#node(String(band));
504
599
  sliderBand.disabled = !status;
505
600
  if (status) {
506
- sliderBand.style.cursor = "pointer"
507
- this.#chui_ap_equalizer_preamp_block.classList.remove("chui_ap_equalizer_disabled")
508
- this.#chui_ap_equalizer_band_block.classList.remove("chui_ap_equalizer_disabled")
601
+ sliderBand.style.cursor = "pointer";
602
+ this.#chui_ap_equalizer_preamp_block.classList.remove("chui_ap_equalizer_disabled");
603
+ this.#chui_ap_equalizer_band_block.classList.remove("chui_ap_equalizer_disabled");
509
604
  } else {
510
- sliderBand.style.cursor = "not-allowed"
511
- this.#chui_ap_equalizer_preamp_block.classList.add("chui_ap_equalizer_disabled")
512
- this.#chui_ap_equalizer_band_block.classList.add("chui_ap_equalizer_disabled")
605
+ sliderBand.style.cursor = "not-allowed";
606
+ this.#chui_ap_equalizer_preamp_block.classList.add("chui_ap_equalizer_disabled");
607
+ this.#chui_ap_equalizer_band_block.classList.add("chui_ap_equalizer_disabled");
513
608
  }
514
609
  }
515
610
  //
516
611
  let sliderPreamp = this.#node("preamp");
517
612
  sliderPreamp.disabled = !status;
518
613
  if (status) {
519
- sliderPreamp.style.cursor = "pointer"
520
- this.#chui_ap_equalizer_preamp_block.classList.remove("chui_ap_equalizer_disabled")
521
- this.#chui_ap_equalizer_band_block.classList.remove("chui_ap_equalizer_disabled")
614
+ sliderPreamp.style.cursor = "pointer";
615
+ this.#chui_ap_equalizer_preamp_block.classList.remove("chui_ap_equalizer_disabled");
616
+ this.#chui_ap_equalizer_band_block.classList.remove("chui_ap_equalizer_disabled");
522
617
  } else {
523
- sliderPreamp.style.cursor = "not-allowed"
524
- this.#chui_ap_equalizer_preamp_block.classList.add("chui_ap_equalizer_disabled")
525
- this.#chui_ap_equalizer_band_block.classList.add("chui_ap_equalizer_disabled")
618
+ sliderPreamp.style.cursor = "not-allowed";
619
+ this.#chui_ap_equalizer_preamp_block.classList.add("chui_ap_equalizer_disabled");
620
+ this.#chui_ap_equalizer_band_block.classList.add("chui_ap_equalizer_disabled");
526
621
  }
527
622
  }
528
623
  #getPreset(name) {
529
- return AudioFX.PRESETS.filter(preset => preset.name === name)[0];
624
+ return AudioFX.PRESETS.filter((preset) => preset.name === name)[0];
530
625
  }
531
626
  /** Узел эквалайзера по id — из карты слайдеров этого эквалайзера */
532
627
  #node(id = String()) {
533
628
  return this.#nodes.get(id);
534
629
  }
535
630
  #setSliderPreamp(filters) {
536
- let sliderMain = document.createElement("chui_eq_slider_main")
537
- let val = document.createElement("slider_label")
538
- let slider = document.createElement('input')
539
- let label = document.createElement("slider_label")
540
- sliderMain.id = "preamp_main"
541
- slider.id = "preamp"
542
- slider.type = 'range'
543
- slider.className = 'eq_slider_test'
544
- slider.step = "1"
545
- slider.min = "-10"
546
- slider.max = "10"
547
- slider.value = "0"
548
- slider.setAttribute("aria-label", I18n.t("media.preamp"))
549
- slider.setAttribute("aria-valuetext", I18n.t("media.decibels", {value: 0}))
631
+ let sliderMain = document.createElement("chui_eq_slider_main");
632
+ let val = document.createElement("slider_label");
633
+ let slider = document.createElement("input");
634
+ let label = document.createElement("slider_label");
635
+ sliderMain.id = "preamp_main";
636
+ slider.id = "preamp";
637
+ slider.type = "range";
638
+ slider.className = "eq_slider_test";
639
+ slider.step = "1";
640
+ slider.min = "-10";
641
+ slider.max = "10";
642
+ slider.value = "0";
643
+ slider.setAttribute("aria-label", I18n.t("media.preamp"));
644
+ slider.setAttribute("aria-valuetext", I18n.t("media.decibels", { value: 0 }));
550
645
  // Доля заливки рельса: заливка рисуется градиентом по тому же числу, что у полос
551
646
  // прогресса и громкости
552
- slider.style.setProperty('--fx-before-width', `50%`);
553
- slider.oninput = (e) => this.#renderPreampSlider(e.target, this.#getPreset(store.get(this.#fx_preset)), filters)
554
- val.id = "val_preamp"
647
+ slider.style.setProperty("--fx-before-width", `50%`);
648
+ slider.oninput = (e) =>
649
+ this.#renderPreampSlider(e.target, this.#getPreset(store.get(this.#fx_preset)), filters);
650
+ val.id = "val_preamp";
555
651
  this.#nodes.set("preamp", slider);
556
652
  this.#nodes.set("val_preamp", val);
557
- val.innerText = String(slider.value)
558
- label.innerText = "AMP"
559
- sliderMain.appendChild(val)
560
- sliderMain.appendChild(slider)
561
- sliderMain.appendChild(label)
562
- return sliderMain
653
+ val.innerText = String(slider.value);
654
+ label.innerText = "AMP";
655
+ sliderMain.appendChild(val);
656
+ sliderMain.appendChild(slider);
657
+ sliderMain.appendChild(label);
658
+ return sliderMain;
563
659
  }
564
660
  #setSliderBand(filter) {
565
661
  let freq_value = String(filter.frequency.value);
566
- let sliderMain = document.createElement("chui_eq_slider_main")
567
- let val = document.createElement("slider_label")
568
- let slider = document.createElement('input')
569
- let label = document.createElement("slider_label")
570
- slider.id = freq_value
571
- slider.type = 'range'
572
- slider.className = 'eq_slider_test'
573
- slider.step = "0.1"
574
- slider.min = "-10"
575
- slider.max = "10"
576
- slider.value = String(filter.gain.value)
577
- slider.setAttribute("aria-label", I18n.t("media.hertzGain", {freq: freq_value}))
578
- slider.setAttribute("aria-valuetext", I18n.t("media.decibels", {value: slider.value}))
579
- slider.style.setProperty('--fx-before-width', `50%`);
580
- slider.oninput = (e) => this.#renderSlider(e.target, filter, Number(this.#node("preamp").value))
581
- val.id = "val_" + freq_value
662
+ let sliderMain = document.createElement("chui_eq_slider_main");
663
+ let val = document.createElement("slider_label");
664
+ let slider = document.createElement("input");
665
+ let label = document.createElement("slider_label");
666
+ slider.id = freq_value;
667
+ slider.type = "range";
668
+ slider.className = "eq_slider_test";
669
+ slider.step = "0.1";
670
+ slider.min = "-10";
671
+ slider.max = "10";
672
+ slider.value = String(filter.gain.value);
673
+ slider.setAttribute("aria-label", I18n.t("media.hertzGain", { freq: freq_value }));
674
+ slider.setAttribute("aria-valuetext", I18n.t("media.decibels", { value: slider.value }));
675
+ slider.style.setProperty("--fx-before-width", `50%`);
676
+ slider.oninput = (e) => this.#renderSlider(e.target, filter, Number(this.#node("preamp").value));
677
+ val.id = "val_" + freq_value;
582
678
  this.#nodes.set(freq_value, slider);
583
679
  this.#nodes.set("val_" + freq_value, val);
584
- val.innerText = String(slider.value)
585
- label.innerText = freq_value.replace("000", "K")
586
- sliderMain.appendChild(val)
587
- sliderMain.appendChild(slider)
588
- sliderMain.appendChild(label)
589
- return sliderMain
680
+ val.innerText = String(slider.value);
681
+ label.innerText = freq_value.replace("000", "K");
682
+ sliderMain.appendChild(val);
683
+ sliderMain.appendChild(slider);
684
+ sliderMain.appendChild(label);
685
+ return sliderMain;
590
686
  }
591
687
  restore() {
592
688
  setTimeout(() => {
593
689
  if (this.#destroyed) return;
594
- let status = store.get(this.#fx_status)
595
- let preset = store.get(this.#fx_preset)
690
+ let status = store.get(this.#fx_status);
691
+ let preset = store.get(this.#fx_preset);
596
692
  if (status) {
597
- this.#fx_ON(this.#audioContext)
598
- this.#switch.setValue(true)
599
- this.#setPresetName(store.get(this.#fx_preset))
600
- this.#setStatusBlock(status)
693
+ this.#fx_ON(this.#audioContext);
694
+ this.#switch.setValue(true);
695
+ this.#setPresetName(store.get(this.#fx_preset));
696
+ this.#setStatusBlock(status);
601
697
  } else {
602
- this.#fx_OFF(this.#audioContext)
603
- this.#switch.setValue(false)
698
+ this.#fx_OFF(this.#audioContext);
699
+ this.#switch.setValue(false);
604
700
  if (status === undefined || preset === undefined) {
605
- this.#setPresetName("Default")
701
+ this.#setPresetName("Default");
606
702
  } else {
607
- this.#setPresetName(store.get(this.#fx_preset))
703
+ this.#setPresetName(store.get(this.#fx_preset));
608
704
  }
609
- this.#setStatusBlock(status)
705
+ this.#setStatusBlock(status);
610
706
  }
611
- }, 250)
707
+ }, 250);
612
708
  }
613
709
  set() {
614
- return this.#chui_ap_equalizer_main
710
+ return this.#chui_ap_equalizer_main;
615
711
  }
616
712
  /** Включить или выключить эквалайзер: тот же путь, что у выключателя в панели */
617
713
  setEnabled(boolean = Boolean()) {
@@ -623,7 +719,9 @@ class AudioFX {
623
719
  return this;
624
720
  }
625
721
  /** Состояние выключателя в панели */
626
- isEnabled() { return this.#switch.getValue(); }
722
+ isEnabled() {
723
+ return this.#switch.getValue();
724
+ }
627
725
  /**
628
726
  * Отпустить звуковой граф: контекст держит аудиопоток, а Chromium разрешает ограниченное
629
727
  * число контекстов на страницу. Повторный вызов безопасен.
@@ -640,30 +738,30 @@ class AudioFX {
640
738
  let p_slider = this.#node("preamp");
641
739
  let p_val = this.#node("val_preamp");
642
740
  if (input === undefined) {
643
- p_slider.value = preset.preamp
741
+ p_slider.value = preset.preamp;
644
742
  } else {
645
- p_slider.value = input.value
646
- preset.inputs.forEach(inp => {
647
- let slid = this.#node(inp.id)
648
- filters.forEach(filter => {
743
+ p_slider.value = input.value;
744
+ preset.inputs.forEach((inp) => {
745
+ let slid = this.#node(inp.id);
746
+ filters.forEach((filter) => {
649
747
  if (String(inp.id) === String(filter.frequency.value)) {
650
- filter.gain.value = Number(slid.value) + Number(input.value)
748
+ filter.gain.value = Number(slid.value) + Number(input.value);
651
749
  }
652
- })
653
- })
750
+ });
751
+ });
654
752
  }
655
- p_val.innerText = String(p_slider.value)
656
- p_slider.setAttribute("aria-valuetext", I18n.t("media.decibels", {value: p_slider.value}))
657
- p_slider.style.setProperty('--fx-before-width', `${(50 + (p_slider.value * 5)).toFixed(1)}%`);
753
+ p_val.innerText = String(p_slider.value);
754
+ p_slider.setAttribute("aria-valuetext", I18n.t("media.decibels", { value: p_slider.value }));
755
+ p_slider.style.setProperty("--fx-before-width", `${(50 + p_slider.value * 5).toFixed(1)}%`);
658
756
  }
659
757
  #renderSlider(input, filter, preamp) {
660
758
  let slider = this.#node(input.id);
661
759
  let val = this.#node("val_" + input.id);
662
- slider.value = input.value
663
- filter.gain.value = Number(Number(slider.value) + preamp)
664
- val.innerText = String(slider.value)
665
- slider.setAttribute("aria-valuetext", I18n.t("media.decibels", {value: slider.value}))
666
- slider.style.setProperty('--fx-before-width', `${(50 + (slider.value * 5)).toFixed(1)}%`);
760
+ slider.value = input.value;
761
+ filter.gain.value = Number(Number(slider.value) + preamp);
762
+ val.innerText = String(slider.value);
763
+ slider.setAttribute("aria-valuetext", I18n.t("media.decibels", { value: slider.value }));
764
+ slider.style.setProperty("--fx-before-width", `${(50 + slider.value * 5).toFixed(1)}%`);
667
765
  }
668
766
  // ya.music.Audio.fx
669
767
  static PRESETS = [
@@ -682,7 +780,7 @@ class AudioFX {
682
780
  { id: "12000", value: 0 },
683
781
  { id: "14000", value: 0 },
684
782
  { id: "16000", value: 0 },
685
- ]
783
+ ],
686
784
  },
687
785
  {
688
786
  name: "Classical",
@@ -699,7 +797,7 @@ class AudioFX {
699
797
  { id: "12000", value: -3.5 },
700
798
  { id: "14000", value: -3.5 },
701
799
  { id: "16000", value: -4.5 },
702
- ]
800
+ ],
703
801
  },
704
802
  {
705
803
  name: "Club",
@@ -716,7 +814,7 @@ class AudioFX {
716
814
  { id: "12000", value: -0.5 },
717
815
  { id: "14000", value: -0.5 },
718
816
  { id: "16000", value: -0.5 },
719
- ]
817
+ ],
720
818
  },
721
819
  {
722
820
  name: "Dance",
@@ -733,7 +831,7 @@ class AudioFX {
733
831
  { id: "12000", value: -3.5 },
734
832
  { id: "14000", value: -0.5 },
735
833
  { id: "16000", value: -0.5 },
736
- ]
834
+ ],
737
835
  },
738
836
  {
739
837
  name: "Full Bass",
@@ -750,7 +848,7 @@ class AudioFX {
750
848
  { id: "12000", value: -5 },
751
849
  { id: "14000", value: -5.5 },
752
850
  { id: "16000", value: -5.5 },
753
- ]
851
+ ],
754
852
  },
755
853
  {
756
854
  name: "Full Treble",
@@ -767,7 +865,7 @@ class AudioFX {
767
865
  { id: "12000", value: 8 },
768
866
  { id: "14000", value: 8 },
769
867
  { id: "16000", value: 8 },
770
- ]
868
+ ],
771
869
  },
772
870
  {
773
871
  name: "Full Bass & Treble",
@@ -784,7 +882,7 @@ class AudioFX {
784
882
  { id: "12000", value: 5.5 },
785
883
  { id: "14000", value: 6 },
786
884
  { id: "16000", value: 6 },
787
- ]
885
+ ],
788
886
  },
789
887
  {
790
888
  name: "Laptop Speakers / Headphone",
@@ -801,7 +899,7 @@ class AudioFX {
801
899
  { id: "12000", value: 4.5 },
802
900
  { id: "14000", value: 6 },
803
901
  { id: "16000", value: 7 },
804
- ]
902
+ ],
805
903
  },
806
904
  {
807
905
  name: "Large Hall",
@@ -818,7 +916,7 @@ class AudioFX {
818
916
  { id: "12000", value: -2 },
819
917
  { id: "14000", value: -0.5 },
820
918
  { id: "16000", value: -0.5 },
821
- ]
919
+ ],
822
920
  },
823
921
  {
824
922
  name: "Live",
@@ -835,7 +933,7 @@ class AudioFX {
835
933
  { id: "12000", value: 1 },
836
934
  { id: "14000", value: 1 },
837
935
  { id: "16000", value: 1 },
838
- ]
936
+ ],
839
937
  },
840
938
  {
841
939
  name: "Party",
@@ -852,7 +950,7 @@ class AudioFX {
852
950
  { id: "12000", value: -0.5 },
853
951
  { id: "14000", value: 3.5 },
854
952
  { id: "16000", value: 3.5 },
855
- ]
953
+ ],
856
954
  },
857
955
  {
858
956
  name: "Pop",
@@ -869,7 +967,7 @@ class AudioFX {
869
967
  { id: "12000", value: -1 },
870
968
  { id: "14000", value: -0.5 },
871
969
  { id: "16000", value: -0.5 },
872
- ]
970
+ ],
873
971
  },
874
972
  {
875
973
  name: "Reggae",
@@ -886,7 +984,7 @@ class AudioFX {
886
984
  { id: "12000", value: -0.5 },
887
985
  { id: "14000", value: -0.5 },
888
986
  { id: "16000", value: -0.5 },
889
- ]
987
+ ],
890
988
  },
891
989
  {
892
990
  name: "Ska",
@@ -903,7 +1001,7 @@ class AudioFX {
903
1001
  { id: "12000", value: 4.5 },
904
1002
  { id: "14000", value: 5.5 },
905
1003
  { id: "16000", value: 4.5 },
906
- ]
1004
+ ],
907
1005
  },
908
1006
  {
909
1007
  name: "Soft",
@@ -920,7 +1018,7 @@ class AudioFX {
920
1018
  { id: "12000", value: 4.5 },
921
1019
  { id: "14000", value: 5.5 },
922
1020
  { id: "16000", value: 6 },
923
- ]
1021
+ ],
924
1022
  },
925
1023
  {
926
1024
  name: "Rock",
@@ -937,7 +1035,7 @@ class AudioFX {
937
1035
  { id: "12000", value: 5.5 },
938
1036
  { id: "14000", value: 5.5 },
939
1037
  { id: "16000", value: 5.5 },
940
- ]
1038
+ ],
941
1039
  },
942
1040
  {
943
1041
  name: "Soft Rock",
@@ -954,7 +1052,7 @@ class AudioFX {
954
1052
  { id: "12000", value: -0.5 },
955
1053
  { id: "14000", value: 1 },
956
1054
  { id: "16000", value: 4 },
957
- ]
1055
+ ],
958
1056
  },
959
1057
  {
960
1058
  name: "Techno",
@@ -971,8 +1069,9 @@ class AudioFX {
971
1069
  { id: "12000", value: 4.5 },
972
1070
  { id: "14000", value: 4.5 },
973
1071
  { id: "16000", value: 4 },
974
- ]
975
- }]
1072
+ ],
1073
+ },
1074
+ ];
976
1075
  }
977
1076
 
978
- exports.Audio = Audio
1077
+ exports.Audio = Audio;