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,9 +1,9 @@
1
- const {setStyles} = require("../../modules/chui_functions");
2
- const {A11Y_FOCUSABLE_SELECTOR} = require("../../modules/chui_a11y/chui_a11y");
3
- const {store: shared_store} = require("../../modules/chui_store/chui_store");
4
- const {ThemeToggle} = require("../chui_theme_toggle/theme_toggle");
5
- const {Toggle} = require("../chui_inputs/chui_toggle/toggle");
6
- const {I18n} = require("../../modules/chui_i18n/chui_i18n");
1
+ const { setStyles } = require("../../modules/chui_functions");
2
+ const { A11Y_FOCUSABLE_SELECTOR } = require("../../modules/chui_a11y/chui_a11y");
3
+ const { store: shared_store } = require("../../modules/chui_store/chui_store");
4
+ const { ThemeToggle } = require("../chui_theme_toggle/theme_toggle");
5
+ const { Toggle } = require("../chui_inputs/chui_toggle/toggle");
6
+ const { I18n } = require("../../modules/chui_i18n/chui_i18n");
7
7
 
8
8
  /** Заполнено ли текстовое поле: пустая строка равнозначна отсутствию */
9
9
  const hasText = (value) => value !== undefined && value !== null && String(value).trim() !== "";
@@ -81,15 +81,17 @@ class Settings {
81
81
  /** Последние известные значения строк: расхождение со снимком и есть правка пользователя */
82
82
  #seen = new Map();
83
83
 
84
- constructor(options = {
85
- id: String(),
86
- title: String(),
87
- description: String(),
88
- sections: [],
89
- store: undefined,
90
- storeKey: String(),
91
- onChange: undefined
92
- }) {
84
+ constructor(
85
+ options = {
86
+ id: String(),
87
+ title: String(),
88
+ description: String(),
89
+ sections: [],
90
+ store: undefined,
91
+ storeKey: String(),
92
+ onChange: undefined,
93
+ }
94
+ ) {
93
95
  setStyles(__dirname + "/styles.css", "chUiJS_Settings");
94
96
  Settings.#counter += 1;
95
97
  this.#id = options.id === undefined ? `chui_settings_${Settings.#counter}` : options.id;
@@ -128,7 +130,13 @@ class Settings {
128
130
 
129
131
  /** Строки в порядке добавления: `{title, name, node, control, disabled}` */
130
132
  getControls() {
131
- return this.#rows.map((row) => ({title: row.title, name: row.name, node: row.node, control: row.control, disabled: row.disabled}));
133
+ return this.#rows.map((row) => ({
134
+ title: row.title,
135
+ name: row.name,
136
+ node: row.node,
137
+ control: row.control,
138
+ disabled: row.disabled,
139
+ }));
132
140
  }
133
141
 
134
142
  /** Контрол строки: адрес — описание из `Settings.Row(...)`, название или имя */
@@ -252,13 +260,15 @@ class Settings {
252
260
  * действие, а не значение) ничего не меняет и потому ничего не сообщает.
253
261
  */
254
262
  #onUserEdit = (event) => {
255
- if (event.type === "click" && event.target instanceof Element && event.target.closest("button") !== null) return;
256
- if (this.#store_key === undefined && this.#change_listeners.length === 0 && this.#on_change === undefined) return;
263
+ if (event.type === "click" && event.target instanceof Element && event.target.closest("button") !== null)
264
+ return;
265
+ if (this.#store_key === undefined && this.#change_listeners.length === 0 && this.#on_change === undefined)
266
+ return;
257
267
  const changed = this.#changedRows();
258
268
  if (changed.length === 0) return;
259
269
  if (this.#store_key !== undefined) this.save();
260
270
  for (const record of changed) this.#emitChange(record);
261
- }
271
+ };
262
272
 
263
273
  /**
264
274
  * Строки, значение которых разошлось со снимком; снимок тут же обновляется, поэтому одна и та же
@@ -284,7 +294,7 @@ class Settings {
284
294
  section: record.section,
285
295
  title: record.title,
286
296
  name: record.name,
287
- value: this.#readValue(record.control)
297
+ value: this.#readValue(record.control),
288
298
  };
289
299
  for (const listener of [...this.#change_listeners]) listener(change, this);
290
300
  if (this.#on_change !== undefined) this.#on_change(change, this);
@@ -337,7 +347,8 @@ class Settings {
337
347
  node.appendChild(head);
338
348
  }
339
349
  const rows = document.createElement("settings_rows");
340
- for (const row of section.rows === undefined ? [] : section.rows) rows.appendChild(this.#buildRow(row, section));
350
+ for (const row of section.rows === undefined ? [] : section.rows)
351
+ rows.appendChild(this.#buildRow(row, section));
341
352
  node.appendChild(rows);
342
353
  return node;
343
354
  }
@@ -352,7 +363,8 @@ class Settings {
352
363
  node.classList.toggle("settings_row_stretch", row.stretch === true);
353
364
  const description_id = solo ? undefined : this.#buildRowText(row, node);
354
365
  const holder = document.createElement("settings_row_control");
355
- const control = row.control === undefined ? undefined : (row.control instanceof Element ? row.control : row.control.set());
366
+ const control =
367
+ row.control === undefined ? undefined : row.control instanceof Element ? row.control : row.control.set();
356
368
  if (control !== undefined) {
357
369
  holder.appendChild(control);
358
370
  this.#applyControlA11y(control, titled ? String(row.title) : String(), description_id);
@@ -364,16 +376,17 @@ class Settings {
364
376
  section: section,
365
377
  title: titled ? String(row.title) : String(),
366
378
  // Ключ строки: имя постоянно, а название видно пользователю и меняется при переименовании
367
- name: named ? String(row.name) : (titled ? String(row.title) : String()),
379
+ name: named ? String(row.name) : titled ? String(row.title) : String(),
368
380
  node: node,
369
381
  holder: holder,
370
382
  control: row.control,
371
383
  disabled: false,
372
- natives: []
384
+ natives: [],
373
385
  };
374
386
  // Запрет панель ставит и полям готового узла, поэтому их исходное состояние запоминаем заранее —
375
387
  // иначе включение вернуло бы строку в другое состояние, чем было до выключения
376
- for (const native of holder.querySelectorAll(Settings.#NATIVE_CONTROLS)) record.natives.push({node: native, disabled: native.disabled});
388
+ for (const native of holder.querySelectorAll(Settings.#NATIVE_CONTROLS))
389
+ record.natives.push({ node: native, disabled: native.disabled });
377
390
  this.#rows.push(record);
378
391
  if (row.disabled === true) this.#setRowDisabled(record, true);
379
392
  return node;
@@ -419,15 +432,21 @@ class Settings {
419
432
  /** Строка по описанию из `Settings.Row(...)`, названию или имени (у строки-контрола их может и не быть) */
420
433
  #findRow(row_or_title = undefined) {
421
434
  if (row_or_title === undefined || row_or_title === null) return undefined;
422
- return this.#rows.find((row) => row.row === row_or_title
423
- || (row.title.length > 0 && row.title === row_or_title)
424
- || (row.name.length > 0 && row.name === row_or_title));
435
+ return this.#rows.find(
436
+ (row) =>
437
+ row.row === row_or_title ||
438
+ (row.title.length > 0 && row.title === row_or_title) ||
439
+ (row.name.length > 0 && row.name === row_or_title)
440
+ );
425
441
  }
426
442
 
427
443
  /** Раздел по описанию из `Settings.Section(...)` или по заголовку (у раздела без заголовка — только описание) */
428
444
  #findSection(section_or_title = undefined) {
429
445
  if (section_or_title === undefined || section_or_title === null) return undefined;
430
- return this.#sections.find((section) => section === section_or_title || (hasText(section.title) && String(section.title) === section_or_title));
446
+ return this.#sections.find(
447
+ (section) =>
448
+ section === section_or_title || (hasText(section.title) && String(section.title) === section_or_title)
449
+ );
431
450
  }
432
451
 
433
452
  /** Карта «ключ — значение» по отобранным строкам; строка без имени и названия ключа дать не может */
@@ -459,18 +478,22 @@ class Settings {
459
478
  * выбранные значения (свой `value` вернул бы только первый пункт).
460
479
  */
461
480
  #readValue(control = undefined) {
462
- if (control !== undefined && control !== null && typeof control.getValue === "function") return control.getValue();
481
+ if (control !== undefined && control !== null && typeof control.getValue === "function")
482
+ return control.getValue();
463
483
  const field = Settings.#valueField(control);
464
484
  if (field === undefined) return undefined;
465
485
  if (field.type === "checkbox" || field.type === "radio") return field.checked;
466
- if (field.tagName === "SELECT" && field.multiple === true) return Array.from(field.selectedOptions, (option) => option.value);
486
+ if (field.tagName === "SELECT" && field.multiple === true)
487
+ return Array.from(field.selectedOptions, (option) => option.value);
467
488
  return field.value;
468
489
  }
469
490
 
470
491
  /** Поле готового узла, с которого панель читает значение */
471
492
  static #valueField(control = undefined) {
472
493
  if (!(control instanceof Element)) return undefined;
473
- const field = control.matches(Settings.#NATIVE_VALUES) ? control : control.querySelector(Settings.#NATIVE_VALUES);
494
+ const field = control.matches(Settings.#NATIVE_VALUES)
495
+ ? control
496
+ : control.querySelector(Settings.#NATIVE_VALUES);
474
497
  return field === null ? undefined : field;
475
498
  }
476
499
 
@@ -517,46 +540,97 @@ class Settings {
517
540
  */
518
541
  #applyControlA11y(control = new HTMLElement(), label = String(), description_id = undefined) {
519
542
  const role = control.getAttribute("role");
520
- const target = role === null || role === "presentation"
521
- ? (control.matches(Settings.#FOCUSABLE) ? control : control.querySelector(Settings.#FOCUSABLE))
522
- : control;
543
+ const target =
544
+ role === null || role === "presentation"
545
+ ? control.matches(Settings.#FOCUSABLE)
546
+ ? control
547
+ : control.querySelector(Settings.#FOCUSABLE)
548
+ : control;
523
549
  if (target === null) return;
524
550
  if (description_id !== undefined) target.setAttribute("aria-describedby", description_id);
525
551
  if (label.length === 0) return;
526
552
  if (target.getAttribute("aria-label") !== null) return;
527
553
  const wrapper = target.closest("label");
528
- const labelled = (wrapper !== null && wrapper.innerText.trim().length > 0)
529
- || (target.id !== "" && control.querySelector(`label[for="${target.id}"]`) !== null);
554
+ const labelled =
555
+ (wrapper !== null && wrapper.innerText.trim().length > 0) ||
556
+ (target.id !== "" && control.querySelector(`label[for="${target.id}"]`) !== null);
530
557
  if (!labelled) target.setAttribute("aria-label", label);
531
558
  }
532
559
 
533
- static Section(options = {title: String(), description: String(), rows: []}) {
534
- return {title: options.title, description: options.description, rows: options.rows};
560
+ static Section(options = { title: String(), description: String(), rows: [] }) {
561
+ return { title: options.title, description: options.description, rows: options.rows };
535
562
  }
536
563
 
537
- static Row(options = {title: String(), description: String(), name: String(), control: undefined, disabled: Boolean(), stretch: Boolean()}) {
538
- return {title: options.title, description: options.description, name: options.name, control: options.control, disabled: options.disabled === true, stretch: options.stretch === true};
564
+ static Row(
565
+ options = {
566
+ title: String(),
567
+ description: String(),
568
+ name: String(),
569
+ control: undefined,
570
+ disabled: Boolean(),
571
+ stretch: Boolean(),
572
+ }
573
+ ) {
574
+ return {
575
+ title: options.title,
576
+ description: options.description,
577
+ name: options.name,
578
+ control: options.control,
579
+ disabled: options.disabled === true,
580
+ stretch: options.stretch === true,
581
+ };
539
582
  }
540
583
 
541
584
  /** Строка с переключателем темы: `control` — сам `ThemeToggle` */
542
- static ThemeRow(options = {title: I18n.t("graphics.settingsTheme"), description: String(), name: String(), modes: [], labels: {}, onChange: undefined, disabled: Boolean()}) {
585
+ static ThemeRow(
586
+ options = {
587
+ title: I18n.t("graphics.settingsTheme"),
588
+ description: String(),
589
+ name: String(),
590
+ modes: [],
591
+ labels: {},
592
+ onChange: undefined,
593
+ disabled: Boolean(),
594
+ }
595
+ ) {
543
596
  const toggle = new ThemeToggle({
544
597
  modes: options.modes,
545
598
  labels: options.labels,
546
599
  label: options.title === undefined ? I18n.t("graphics.settingsAppearance") : options.title,
547
- onChange: options.onChange
600
+ onChange: options.onChange,
601
+ });
602
+ return Settings.Row({
603
+ title: options.title === undefined ? I18n.t("graphics.settingsTheme") : options.title,
604
+ description: options.description,
605
+ name: options.name,
606
+ control: toggle,
607
+ disabled: options.disabled,
548
608
  });
549
- return Settings.Row({title: options.title === undefined ? I18n.t("graphics.settingsTheme") : options.title, description: options.description, name: options.name, control: toggle, disabled: options.disabled});
550
609
  }
551
610
 
552
611
  /** Строка с флажком: `control` — сам `Toggle` */
553
- static ToggleRow(options = {title: String(), description: String(), name: String(), value: Boolean(), onChange: undefined, disabled: Boolean()}) {
612
+ static ToggleRow(
613
+ options = {
614
+ title: String(),
615
+ description: String(),
616
+ name: String(),
617
+ value: Boolean(),
618
+ onChange: undefined,
619
+ disabled: Boolean(),
620
+ }
621
+ ) {
554
622
  // Подпись строки сразу уходит в сам переключатель: вне Settings он остаётся без имени
555
- const toggle = new Toggle({label: options.title});
623
+ const toggle = new Toggle({ label: options.title });
556
624
  if (options.value !== undefined) toggle.setValue(options.value === true);
557
625
  if (options.onChange !== undefined) toggle.addChangeListener(options.onChange);
558
- return Settings.Row({title: options.title, description: options.description, name: options.name, control: toggle, disabled: options.disabled});
626
+ return Settings.Row({
627
+ title: options.title,
628
+ description: options.description,
629
+ name: options.name,
630
+ control: toggle,
631
+ disabled: options.disabled,
632
+ });
559
633
  }
560
634
  }
561
635
 
562
- exports.Settings = Settings
636
+ exports.Settings = Settings;
@@ -1,7 +1,7 @@
1
- const {setStyles, optionOr} = require('../../modules/chui_functions');
2
- const {TextInput} = require('../chui_inputs/chui_text/text');
3
- const {Kbd} = require('../chui_kbd/kbd');
4
- const {I18n} = require('../../modules/chui_i18n/chui_i18n');
1
+ const { setStyles, optionOr } = require("../../modules/chui_functions");
2
+ const { TextInput } = require("../chui_inputs/chui_text/text");
3
+ const { Kbd } = require("../chui_kbd/kbd");
4
+ const { I18n } = require("../../modules/chui_i18n/chui_i18n");
5
5
 
6
6
  /**
7
7
  * Шпаргалка горячих клавиш: сочетания с пояснениями, разложенные по группам.
@@ -59,11 +59,20 @@ class ShortcutHelp {
59
59
  #empty_text = undefined;
60
60
  #kbd_size = Kbd.SIZE.DEFAULT;
61
61
 
62
- constructor(options = {
63
- id: String(), title: undefined, groups: [], items: [],
64
- columns: Number(), searchable: Boolean(), searchPlaceholder: String(),
65
- emptyText: String(), label: String(), kbdSize: String()
66
- }) {
62
+ constructor(
63
+ options = {
64
+ id: String(),
65
+ title: undefined,
66
+ groups: [],
67
+ items: [],
68
+ columns: Number(),
69
+ searchable: Boolean(),
70
+ searchPlaceholder: String(),
71
+ emptyText: String(),
72
+ label: String(),
73
+ kbdSize: String(),
74
+ }
75
+ ) {
67
76
  setStyles(__dirname + "/styles.css", "chUiJS_ShortcutHelp");
68
77
  ShortcutHelp.#counter += 1;
69
78
  this.#id = optionOr(options.id, `chui_shortcut_help_${ShortcutHelp.#counter}`);
@@ -110,7 +119,11 @@ class ShortcutHelp {
110
119
  getGroups() {
111
120
  return this.#source.map((group) => ({
112
121
  title: group.title,
113
- items: group.items.map((item) => ({keys: [...item.keys], description: item.description, label: item.label}))
122
+ items: group.items.map((item) => ({
123
+ keys: [...item.keys],
124
+ description: item.description,
125
+ label: item.label,
126
+ })),
114
127
  }));
115
128
  }
116
129
 
@@ -129,7 +142,10 @@ class ShortcutHelp {
129
142
 
130
143
  /** Сколько строк видно с учётом фильтра */
131
144
  getVisibleCount() {
132
- return this.#groups.reduce((sum, group) => sum + group.rows.filter((row) => row.node.hidden !== true).length, 0);
145
+ return this.#groups.reduce(
146
+ (sum, group) => sum + group.rows.filter((row) => row.node.hidden !== true).length,
147
+ 0
148
+ );
133
149
  }
134
150
 
135
151
  // SET
@@ -143,7 +159,9 @@ class ShortcutHelp {
143
159
  setTitle(text = undefined) {
144
160
  this.#title_hidden = text === null;
145
161
  this.#title_value = typeof text === "string" && text !== "" ? text : undefined;
146
- this.#title.innerText = this.#title_hidden ? "" : optionOr(this.#title_value, I18n.t("navigation.shortcutHelp"));
162
+ this.#title.innerText = this.#title_hidden
163
+ ? ""
164
+ : optionOr(this.#title_value, I18n.t("navigation.shortcutHelp"));
147
165
  this.#title.hidden = this.#title_hidden;
148
166
  this.#syncAria();
149
167
  return this;
@@ -172,12 +190,15 @@ class ShortcutHelp {
172
190
  placeholder: optionOr(this.#placeholder, I18n.t("navigation.shortcutHelpSearch")),
173
191
  width: "100%",
174
192
  // Слушатель обновляет и строки, и объявление найденного числа
175
- inputListener: () => this.#syncSearch()
193
+ inputListener: () => this.#syncSearch(),
176
194
  });
177
195
  // Видимой подписи у поля нет, а пл҃ейсхолдер — не имя: имя ставим явно
178
196
  const search_field = this.#input.set().querySelector("input");
179
197
  if (search_field !== null) {
180
- search_field.setAttribute("aria-label", optionOr(this.#placeholder, I18n.t("navigation.shortcutHelpSearch")));
198
+ search_field.setAttribute(
199
+ "aria-label",
200
+ optionOr(this.#placeholder, I18n.t("navigation.shortcutHelpSearch"))
201
+ );
181
202
  }
182
203
  this.#search.appendChild(this.#input.set());
183
204
  }
@@ -189,7 +210,7 @@ class ShortcutHelp {
189
210
 
190
211
  /** Заменить содержимое целиком */
191
212
  setGroups(groups = []) {
192
- this.#source = ShortcutHelp.#normalizeSource({groups: groups});
213
+ this.#source = ShortcutHelp.#normalizeSource({ groups: groups });
193
214
  this.#render();
194
215
  return this;
195
216
  }
@@ -197,7 +218,7 @@ class ShortcutHelp {
197
218
  /** Добавить группу: `add({title: 'Правка', items: [...]})` */
198
219
  addGroup(group = undefined) {
199
220
  if (group === undefined || group === null) return this;
200
- this.#source = ShortcutHelp.#normalizeSource({groups: [...this.#source, group]});
221
+ this.#source = ShortcutHelp.#normalizeSource({ groups: [...this.#source, group] });
201
222
  this.#render();
202
223
  return this;
203
224
  }
@@ -217,27 +238,30 @@ class ShortcutHelp {
217
238
  /** `groups` плюс короткая форма `items` (одна группа без заголовка) */
218
239
  static #normalizeSource(options = {}) {
219
240
  const groups = [];
220
- const items = (options.items === undefined ? [] : options.items).map((item) => ShortcutHelp.#normalizeItem(item));
221
- if (items.length > 0) groups.push({title: "", items: items});
241
+ const items = (options.items === undefined ? [] : options.items).map((item) =>
242
+ ShortcutHelp.#normalizeItem(item)
243
+ );
244
+ if (items.length > 0) groups.push({ title: "", items: items });
222
245
  for (const group of options.groups === undefined ? [] : options.groups) {
223
246
  groups.push({
224
247
  title: group.title === undefined ? "" : String(group.title),
225
- items: (group.items === undefined ? [] : group.items).map((item) => ShortcutHelp.#normalizeItem(item))
248
+ items: (group.items === undefined ? [] : group.items).map((item) => ShortcutHelp.#normalizeItem(item)),
226
249
  });
227
250
  }
228
251
  return groups;
229
252
  }
230
253
 
231
254
  static #normalizeItem(item = {}) {
232
- const keys = item.keys === undefined || item.keys === null
233
- ? []
234
- : (Array.isArray(item.keys) ? item.keys : String(item.keys).split("+"))
235
- .map((key) => String(key).trim())
236
- .filter((key) => key.length > 0);
255
+ const keys =
256
+ item.keys === undefined || item.keys === null
257
+ ? []
258
+ : (Array.isArray(item.keys) ? item.keys : String(item.keys).split("+"))
259
+ .map((key) => String(key).trim())
260
+ .filter((key) => key.length > 0);
237
261
  return {
238
262
  keys: keys,
239
263
  description: item.description === undefined ? "" : String(item.description),
240
- label: item.label
264
+ label: item.label,
241
265
  };
242
266
  }
243
267
 
@@ -270,7 +294,7 @@ class ShortcutHelp {
270
294
  if (item.keys.length > 0) {
271
295
  const keys = document.createElement("shortcut_help_keys");
272
296
  // Сочетание рисует Kbd: клавиша — настоящий <kbd>, значковым нужен label
273
- keys.appendChild(new Kbd({keys: item.keys, size: this.#kbd_size, label: item.label}).set());
297
+ keys.appendChild(new Kbd({ keys: item.keys, size: this.#kbd_size, label: item.label }).set());
274
298
  line.appendChild(keys);
275
299
  }
276
300
  const text = document.createElement("shortcut_help_text");
@@ -278,11 +302,11 @@ class ShortcutHelp {
278
302
  line.appendChild(text);
279
303
  row.appendChild(line);
280
304
  list.appendChild(row);
281
- rows.push({node: row, search: `${item.description} ${item.keys.join(" ")}`.toLowerCase()});
305
+ rows.push({ node: row, search: `${item.description} ${item.keys.join(" ")}`.toLowerCase() });
282
306
  }
283
307
  node.appendChild(list);
284
308
  this.#groups_node.appendChild(node);
285
- this.#groups.push({node: node, rows: rows});
309
+ this.#groups.push({ node: node, rows: rows });
286
310
  });
287
311
  this.#empty.innerText = optionOr(this.#empty_text, I18n.t("navigation.shortcutHelpEmpty"));
288
312
  this.#syncSearch();
@@ -313,9 +337,8 @@ class ShortcutHelp {
313
337
  #syncSearch() {
314
338
  this.#search.hidden = this.#searchable !== true;
315
339
  const visible = this.#filter(this.#input === undefined ? "" : this.#input.getValue());
316
- this.#status.innerText = this.#searchable === true
317
- ? I18n.t("navigation.shortcutHelpCount", {count: visible})
318
- : "";
340
+ this.#status.innerText =
341
+ this.#searchable === true ? I18n.t("navigation.shortcutHelpCount", { count: visible }) : "";
319
342
  // Без поиска пустая строка не показывается: скрывать нечего
320
343
  if (this.#searchable !== true) this.#empty.hidden = true;
321
344
  }
@@ -333,4 +356,4 @@ class ShortcutHelp {
333
356
  }
334
357
  }
335
358
 
336
- exports.ShortcutHelp = ShortcutHelp
359
+ exports.ShortcutHelp = ShortcutHelp;
@@ -1,6 +1,6 @@
1
- const {setStyles} = require("../../modules/chui_functions");
2
- const {Icon, Icons} = require("../chui_icons/icons");
3
- const {I18n} = require("../../modules/chui_i18n/chui_i18n");
1
+ const { setStyles } = require("../../modules/chui_functions");
2
+ const { Icon, Icons } = require("../chui_icons/icons");
3
+ const { I18n } = require("../../modules/chui_i18n/chui_i18n");
4
4
 
5
5
  /** Служебные ключи пункта: всё остальное — данные пункта */
6
6
  const SERVICE_KEYS = ["id", "type", "title", "icon", "badge", "children", "disabled", "href"];
@@ -69,18 +69,20 @@ class SidebarNav {
69
69
  #active_id = undefined;
70
70
  #focus_id = undefined;
71
71
 
72
- constructor(options = {
73
- id: String(),
74
- title: String(),
75
- label: String(),
76
- items: Array(),
77
- value: String(),
78
- collapsible: Boolean(),
79
- collapsed: Boolean(),
80
- onSelect: undefined,
81
- onToggle: undefined,
82
- changeEvent: undefined
83
- }) {
72
+ constructor(
73
+ options = {
74
+ id: String(),
75
+ title: String(),
76
+ label: String(),
77
+ items: Array(),
78
+ value: String(),
79
+ collapsible: Boolean(),
80
+ collapsed: Boolean(),
81
+ onSelect: undefined,
82
+ onToggle: undefined,
83
+ changeEvent: undefined,
84
+ }
85
+ ) {
84
86
  setStyles(__dirname + "/styles.css", "chUiJS_SidebarNav");
85
87
  SidebarNav.#counter += 1;
86
88
  this.#id = options.id === undefined ? `chui_sidebar_nav_${SidebarNav.#counter}` : options.id;
@@ -203,7 +205,7 @@ class SidebarNav {
203
205
  let section = undefined;
204
206
  for (const item of Array.isArray(items) ? items : []) {
205
207
  if (item !== null && typeof item === "object" && item.type === "section") {
206
- section = {type: "section", title: item.title === undefined ? "" : String(item.title), children: []};
208
+ section = { type: "section", title: item.title === undefined ? "" : String(item.title), children: [] };
207
209
  this.#items.push(section);
208
210
  continue;
209
211
  }
@@ -285,7 +287,10 @@ class SidebarNav {
285
287
  this.#root.classList.toggle("sidebar_nav_collapsed", this.#collapsed);
286
288
  if (this.#collapse !== undefined) {
287
289
  this.#collapse.setAttribute("aria-expanded", this.#collapsed ? "false" : "true");
288
- this.#collapse.setAttribute("aria-label", this.#collapsed ? I18n.t("navigation.sidebarExpand") : I18n.t("navigation.sidebarCollapse"));
290
+ this.#collapse.setAttribute(
291
+ "aria-label",
292
+ this.#collapsed ? I18n.t("navigation.sidebarExpand") : I18n.t("navigation.sidebarCollapse")
293
+ );
289
294
  }
290
295
  this.#render();
291
296
  return this;
@@ -319,7 +324,7 @@ class SidebarNav {
319
324
 
320
325
  // === ВНУТРЕННЕЕ ===
321
326
  static #toNode(item = Object()) {
322
- const source = typeof item === "string" ? {title: item} : item;
327
+ const source = typeof item === "string" ? { title: item } : item;
323
328
  const data = {};
324
329
  for (const key of Object.keys(source === null ? {} : source)) {
325
330
  if (!SERVICE_KEYS.includes(key)) data[key] = source[key];
@@ -341,13 +346,17 @@ class SidebarNav {
341
346
 
342
347
  #describeEntry(node) {
343
348
  if (node.type === "section") {
344
- return {type: "section", title: node.title, children: node.children.map((child) => this.#describeEntry(child))};
349
+ return {
350
+ type: "section",
351
+ title: node.title,
352
+ children: node.children.map((child) => this.#describeEntry(child)),
353
+ };
345
354
  }
346
355
  return this.#describe(node);
347
356
  }
348
357
 
349
358
  #describe(node) {
350
- const descriptor = {id: node.id, title: node.title, icon: node.icon};
359
+ const descriptor = { id: node.id, title: node.title, icon: node.icon };
351
360
  if (node.badge !== undefined) descriptor.badge = node.badge;
352
361
  for (const key of Object.keys(node.data)) descriptor[key] = node.data[key];
353
362
  descriptor.disabled = node.disabled;
@@ -377,7 +386,8 @@ class SidebarNav {
377
386
  #siblingsOf(node) {
378
387
  const parent = this.#parentNode(node);
379
388
  if (parent !== undefined) return parent.children;
380
- for (const entry of this.#items) if (entry.type === "section" && entry.children.includes(node)) return entry.children;
389
+ for (const entry of this.#items)
390
+ if (entry.type === "section" && entry.children.includes(node)) return entry.children;
381
391
  return this.#items;
382
392
  }
383
393
 
@@ -604,7 +614,7 @@ class SidebarNav {
604
614
  const link = target === undefined ? null : target.closest(".sidebar_nav_link");
605
615
  if (link !== null && link !== undefined) return link;
606
616
  const id = this.#active_id;
607
- return id === undefined ? null : this.#links().find((node) => node.dataset.id === id) ?? null;
617
+ return id === undefined ? null : (this.#links().find((node) => node.dataset.id === id) ?? null);
608
618
  }
609
619
 
610
620
  #onClick = (event) => {
@@ -663,4 +673,4 @@ class SidebarNav {
663
673
  };
664
674
  }
665
675
 
666
- exports.SidebarNav = SidebarNav
676
+ exports.SidebarNav = SidebarNav;