chuijs 4.0.2 → 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 (221) hide show
  1. package/CHANGELOG.md +61 -0
  2. package/README.md +43 -644
  3. package/framework/appLayout/default/chui_app_layout.js +308 -260
  4. package/framework/appLayout/default/global_style.css +85 -48
  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 +36 -25
  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_qr/chui_qr.js +158 -67
  211. package/framework/modules/chui_scrollbar/chui_scrollbar.js +35 -24
  212. package/framework/modules/chui_scrollbar/styles.css +3 -1
  213. package/framework/modules/chui_services/chui_channels.js +27 -13
  214. package/framework/modules/chui_services/chui_services.js +39 -31
  215. package/framework/modules/chui_services/desktop.js +32 -31
  216. package/framework/modules/chui_sortable/chui_sortable.js +17 -12
  217. package/framework/modules/chui_validate/chui_validate.js +7 -4
  218. package/framework/tray_bar/chui_menu_items.js +136 -46
  219. package/index.d.ts +4814 -0
  220. package/index.js +385 -292
  221. package/package.json +79 -68
@@ -14,14 +14,14 @@
14
14
  * (popup_button_ok и подобным) tabindex выставляет вызывающий компонент.
15
15
  */
16
16
  const FOCUSABLE_SELECTOR = [
17
- 'a[href]',
18
- 'button:not([disabled])',
19
- 'input:not([disabled])',
20
- 'select:not([disabled])',
21
- 'textarea:not([disabled])',
17
+ "a[href]",
18
+ "button:not([disabled])",
19
+ "input:not([disabled])",
20
+ "select:not([disabled])",
21
+ "textarea:not([disabled])",
22
22
  '[contenteditable="true"]',
23
23
  '[tabindex]:not([tabindex="-1"])',
24
- ].join(', ');
24
+ ].join(", ");
25
25
 
26
26
  class OverlayA11y {
27
27
  // Стек открытых слоёв: нужен, чтобы вложенный слой не снимал фон-инерт у родителя
@@ -37,10 +37,16 @@ class OverlayA11y {
37
37
  #previous_focus = undefined;
38
38
  #is_open = false;
39
39
 
40
- constructor(element, options = {
41
- role: String(), label: String(), labelNode: undefined, describedBy: undefined,
42
- onEscape: undefined,
43
- }) {
40
+ constructor(
41
+ element,
42
+ options = {
43
+ role: String(),
44
+ label: String(),
45
+ labelNode: undefined,
46
+ describedBy: undefined,
47
+ onEscape: undefined,
48
+ }
49
+ ) {
44
50
  this.#element = element;
45
51
  if (options.role !== undefined) this.#role = options.role;
46
52
  this.#label = options.label;
@@ -125,8 +131,9 @@ class OverlayA11y {
125
131
  }
126
132
 
127
133
  #focusables() {
128
- return [...this.#element.querySelectorAll(FOCUSABLE_SELECTOR)]
129
- .filter(element => element.offsetWidth > 0 || element.offsetHeight > 0 || element === document.activeElement);
134
+ return [...this.#element.querySelectorAll(FOCUSABLE_SELECTOR)].filter(
135
+ (element) => element.offsetWidth > 0 || element.offsetHeight > 0 || element === document.activeElement
136
+ );
130
137
  }
131
138
 
132
139
  #focusFirst() {
@@ -175,7 +182,7 @@ class OverlayA11y {
175
182
  return;
176
183
  }
177
184
  if (event.key === "Tab") this.#trapFocus(event);
178
- }
185
+ };
179
186
  }
180
187
 
181
188
  /**
@@ -194,16 +201,22 @@ function makeKeyboardButton(element, role = "button") {
194
201
  return element;
195
202
  }
196
203
 
197
- exports.OverlayA11y = OverlayA11y
198
- exports.makeKeyboardButton = makeKeyboardButton
199
- exports.A11Y_FOCUSABLE_SELECTOR = FOCUSABLE_SELECTOR
204
+ exports.OverlayA11y = OverlayA11y;
205
+ exports.makeKeyboardButton = makeKeyboardButton;
206
+ exports.A11Y_FOCUSABLE_SELECTOR = FOCUSABLE_SELECTOR;
200
207
 
201
208
  // Подсветка активного пункта меню/опции, когда фокус остаётся на поле ввода
202
209
  const ACTIVE_CLASS = "chui_a11y_active";
203
210
 
204
- const isVisible = (element) => element.offsetWidth > 0 || element.offsetHeight > 0 || element === document.activeElement;
205
- const isDisabled = (element) => element.disabled === true || element.getAttribute("aria-disabled") === "true" ||
206
- (element.className !== undefined && String(element.className).split(" ").some(name => name.endsWith("_disabled")));
211
+ const isVisible = (element) =>
212
+ element.offsetWidth > 0 || element.offsetHeight > 0 || element === document.activeElement;
213
+ const isDisabled = (element) =>
214
+ element.disabled === true ||
215
+ element.getAttribute("aria-disabled") === "true" ||
216
+ (element.className !== undefined &&
217
+ String(element.className)
218
+ .split(" ")
219
+ .some((name) => name.endsWith("_disabled")));
207
220
 
208
221
  /**
209
222
  * Клавиатура для всплывающих меню (ContextMenu, MenuBar, меню шапки).
@@ -225,10 +238,17 @@ class MenuKeyboard {
225
238
  #trigger = undefined;
226
239
  #trigger_bound = false;
227
240
 
228
- constructor(container, options = {
229
- role: String(), itemRole: String(), itemSelector: String(),
230
- submenuSelector: String(), onEscape: undefined, trigger: undefined
231
- }) {
241
+ constructor(
242
+ container,
243
+ options = {
244
+ role: String(),
245
+ itemRole: String(),
246
+ itemSelector: String(),
247
+ submenuSelector: String(),
248
+ onEscape: undefined,
249
+ trigger: undefined,
250
+ }
251
+ ) {
232
252
  this.#container = container;
233
253
  if (options.role !== undefined) this.#role = options.role;
234
254
  if (options.itemRole !== undefined) this.#item_role = options.itemRole;
@@ -276,8 +296,9 @@ class MenuKeyboard {
276
296
 
277
297
  // Все пункты своего уровня (и скрытые — им тоже нужны роли и tabindex)
278
298
  #allItems() {
279
- return [...this.#container.querySelectorAll(this.#item_selector)]
280
- .filter(item => item.closest('[role="menu"]') === this.#container);
299
+ return [...this.#container.querySelectorAll(this.#item_selector)].filter(
300
+ (item) => item.closest('[role="menu"]') === this.#container
301
+ );
281
302
  }
282
303
 
283
304
  #focusItem(index) {
@@ -290,7 +311,7 @@ class MenuKeyboard {
290
311
  }
291
312
 
292
313
  #activeIndex(items) {
293
- return items.findIndex(item => item === document.activeElement || item.classList.contains(ACTIVE_CLASS));
314
+ return items.findIndex((item) => item === document.activeElement || item.classList.contains(ACTIVE_CLASS));
294
315
  }
295
316
 
296
317
  // Для навигации — только видимые пункты своего уровня
@@ -382,7 +403,7 @@ class MenuKeyboard {
382
403
  }
383
404
  break;
384
405
  }
385
- }
406
+ };
386
407
 
387
408
  #typeahead(char) {
388
409
  const now = Date.now();
@@ -394,7 +415,7 @@ class MenuKeyboard {
394
415
  const current = this.#activeIndex(items);
395
416
  // Ищем по кругу, начиная со следующего пункта
396
417
  const ordered = current === -1 ? items : [...items.slice(current + 1), ...items.slice(0, current + 1)];
397
- const match = ordered.find(item => this.#label(item).startsWith(this.#type_buffer));
418
+ const match = ordered.find((item) => this.#label(item).startsWith(this.#type_buffer));
398
419
  if (match !== undefined) this.#focusItem(items.indexOf(match));
399
420
  }
400
421
 
@@ -412,7 +433,8 @@ class MenuKeyboard {
412
433
 
413
434
  destroy() {
414
435
  this.#container.removeEventListener("keydown", this.#keydownEvent);
415
- if (this.#trigger !== undefined && this.#trigger_bound) this.#trigger.removeEventListener("keydown", this.#keydownEvent);
436
+ if (this.#trigger !== undefined && this.#trigger_bound)
437
+ this.#trigger.removeEventListener("keydown", this.#keydownEvent);
416
438
  }
417
439
  }
418
440
 
@@ -430,9 +452,16 @@ class ComboboxKeyboard {
430
452
  #active = undefined;
431
453
  #selection_state = undefined;
432
454
 
433
- constructor(input, options = {
434
- dropdown: undefined, optionSelector: String(), onEscape: undefined, onOpen: undefined, selectionState: undefined
435
- }) {
455
+ constructor(
456
+ input,
457
+ options = {
458
+ dropdown: undefined,
459
+ optionSelector: String(),
460
+ onEscape: undefined,
461
+ onOpen: undefined,
462
+ selectionState: undefined,
463
+ }
464
+ ) {
436
465
  this.#input = input;
437
466
  this.#dropdown = options.dropdown;
438
467
  this.#option_selector = options.optionSelector;
@@ -455,7 +484,8 @@ class ComboboxKeyboard {
455
484
  // Роли и id нужны всем опциям, даже когда дропдаун ещё закрыт
456
485
  for (const option of this.#allOptions()) {
457
486
  if (option.getAttribute("role") === null) option.setAttribute("role", "option");
458
- if (option.id === undefined || option.id === "") option.id = "chui_a11y_option_" + Math.random().toString(36).slice(2, 9);
487
+ if (option.id === undefined || option.id === "")
488
+ option.id = "chui_a11y_option_" + Math.random().toString(36).slice(2, 9);
459
489
  }
460
490
  this.#applyActive();
461
491
  }
@@ -477,7 +507,7 @@ class ComboboxKeyboard {
477
507
  }
478
508
 
479
509
  #options() {
480
- return this.#allOptions().filter(option => isVisible(option) && !isDisabled(option));
510
+ return this.#allOptions().filter((option) => isVisible(option) && !isDisabled(option));
481
511
  }
482
512
 
483
513
  #applyActive() {
@@ -511,7 +541,8 @@ class ComboboxKeyboard {
511
541
  case "ArrowDown":
512
542
  case "ArrowUp": {
513
543
  event.preventDefault();
514
- if (this.#input.getAttribute("aria-expanded") !== "true" && this.#on_open !== undefined) this.#on_open();
544
+ if (this.#input.getAttribute("aria-expanded") !== "true" && this.#on_open !== undefined)
545
+ this.#on_open();
515
546
  this.#move(event.key === "ArrowDown" ? 1 : -1);
516
547
  break;
517
548
  }
@@ -547,7 +578,7 @@ class ComboboxKeyboard {
547
578
  default:
548
579
  break;
549
580
  }
550
- }
581
+ };
551
582
 
552
583
  destroy() {
553
584
  this.#input.removeEventListener("keydown", this.#keydownEvent);
@@ -582,7 +613,7 @@ class RovingKeyboard {
582
613
  /** Перечитать пункты: остановка остаётся на прежнем, если он ещё доступен */
583
614
  refresh() {
584
615
  const visible = this.#items();
585
- const current = visible.find(item => item.getAttribute("tabindex") === "0");
616
+ const current = visible.find((item) => item.getAttribute("tabindex") === "0");
586
617
  // Панель может быть ещё не в документе (размеры нулевые) — тогда остановку получает
587
618
  // первый пункт: без неё группа целиком выпала бы из обхода Tab
588
619
  const fallback = visible[0] === undefined ? this.#allItems()[0] : visible[0];
@@ -598,13 +629,13 @@ class RovingKeyboard {
598
629
 
599
630
  // Пункты, по которым ходит клавиатура: видимые и не запрещённые
600
631
  #items() {
601
- return this.#allItems().filter(item => !isDisabled(item) && isVisible(item));
632
+ return this.#allItems().filter((item) => !isDisabled(item) && isVisible(item));
602
633
  }
603
634
 
604
635
  #activeIndex(items) {
605
- const focused = items.findIndex(item => item === document.activeElement);
636
+ const focused = items.findIndex((item) => item === document.activeElement);
606
637
  if (focused !== -1) return focused;
607
- return items.findIndex(item => item.getAttribute("tabindex") === "0");
638
+ return items.findIndex((item) => item.getAttribute("tabindex") === "0");
608
639
  }
609
640
 
610
641
  #applyStop(item) {
@@ -659,10 +690,10 @@ class RovingKeyboard {
659
690
  }
660
691
  }
661
692
 
662
- exports.MenuKeyboard = MenuKeyboard
663
- exports.ComboboxKeyboard = ComboboxKeyboard
664
- exports.RovingKeyboard = RovingKeyboard
665
- exports.A11Y_ACTIVE_CLASS = ACTIVE_CLASS
693
+ exports.MenuKeyboard = MenuKeyboard;
694
+ exports.ComboboxKeyboard = ComboboxKeyboard;
695
+ exports.RovingKeyboard = RovingKeyboard;
696
+ exports.A11Y_ACTIVE_CLASS = ACTIVE_CLASS;
666
697
 
667
698
  /**
668
699
  * Перенести фокус на следующий (или предыдущий) видимый фокусируемый элемент страницы.
@@ -670,7 +701,7 @@ exports.A11Y_ACTIVE_CLASS = ACTIVE_CLASS
670
701
  * браузер уведёт фокус в `body`, а не к следующему полю. `skip` — узел или поддерево,
671
702
  * которое в обходе не участвует (например, сам список).
672
703
  */
673
- function moveFocusAway(from, options = {backwards: false, skip: undefined}) {
704
+ function moveFocusAway(from, options = { backwards: false, skip: undefined }) {
674
705
  const nodes = [...document.querySelectorAll(FOCUSABLE_SELECTOR)]
675
706
  .filter((node) => node.disabled !== true)
676
707
  .filter((node) => isVisible(node))
@@ -684,4 +715,4 @@ function moveFocusAway(from, options = {backwards: false, skip: undefined}) {
684
715
  return true;
685
716
  }
686
717
 
687
- exports.moveFocusAway = moveFocusAway
718
+ exports.moveFocusAway = moveFocusAway;
@@ -4,7 +4,7 @@ class Animation {
4
4
  #element = undefined;
5
5
 
6
6
  constructor(element) {
7
- require('../chui_functions').setStyles(__dirname + "/styles.css", "chUiJS_Animations");
7
+ require("../chui_functions").setStyles(__dirname + "/styles.css", "chUiJS_Animations");
8
8
  if (element !== undefined) this.#element = element;
9
9
  }
10
10
 
@@ -14,101 +14,101 @@ class Animation {
14
14
  * доиграла, этот обработчик прятал уже открытый слой — вид расходился с состоянием.
15
15
  */
16
16
  #cancelHide() {
17
- this.#element.removeEventListener('animationend', removeEvents);
18
- this.#element.style.removeProperty('animation-name');
17
+ this.#element.removeEventListener("animationend", removeEvents);
18
+ this.#element.style.removeProperty("animation-name");
19
19
  }
20
20
 
21
21
  fadeIn() {
22
22
  this.#cancelHide();
23
- if (window.getComputedStyle(this.#element, null).display === 'none') {
24
- if (this.#element.tagName !== "TABLE") this.#element.style.display = 'flex';
23
+ if (window.getComputedStyle(this.#element, null).display === "none") {
24
+ if (this.#element.tagName !== "TABLE") this.#element.style.display = "flex";
25
25
  }
26
- this.#element.style.transition = "transform .0s"
27
- this.#element.style.animationName = 'fade-in';
26
+ this.#element.style.transition = "transform .0s";
27
+ this.#element.style.animationName = "fade-in";
28
28
  }
29
29
 
30
30
  fadeOut() {
31
- this.#element.style.transition = "transform .0s"
31
+ this.#element.style.transition = "transform .0s";
32
32
  if (this.#element.style.animationName) {
33
- this.#element.style.animationName = 'fade-out';
34
- this.#element.addEventListener('animationend', removeEvents);
33
+ this.#element.style.animationName = "fade-out";
34
+ this.#element.addEventListener("animationend", removeEvents);
35
35
  }
36
36
  }
37
37
 
38
38
  // SCALE
39
39
  scaleIn() {
40
40
  this.#cancelHide();
41
- if (window.getComputedStyle(this.#element, null).display === 'none') {
42
- if (this.#element.tagName !== "TABLE") this.#element.style.display = 'flex';
41
+ if (window.getComputedStyle(this.#element, null).display === "none") {
42
+ if (this.#element.tagName !== "TABLE") this.#element.style.display = "flex";
43
43
  }
44
- this.#element.style.animationName = 'scale-in';
44
+ this.#element.style.animationName = "scale-in";
45
45
  }
46
46
 
47
47
  scaleOut() {
48
48
  if (this.#element.style.animationName) {
49
- this.#element.style.animationName = 'scale-out';
50
- this.#element.addEventListener('animationend', removeEvents);
49
+ this.#element.style.animationName = "scale-out";
50
+ this.#element.addEventListener("animationend", removeEvents);
51
51
  }
52
52
  }
53
53
 
54
54
  // SLIDE RIGHT
55
55
  slideRightIn() {
56
56
  this.#cancelHide();
57
- if (window.getComputedStyle(this.#element, null).display === 'none') {
58
- if (this.#element.tagName !== "TABLE") this.#element.style.display = 'flex';
57
+ if (window.getComputedStyle(this.#element, null).display === "none") {
58
+ if (this.#element.tagName !== "TABLE") this.#element.style.display = "flex";
59
59
  }
60
- this.#element.style.animationName = 'slide-right-in';
60
+ this.#element.style.animationName = "slide-right-in";
61
61
  }
62
62
 
63
63
  slideRightOut() {
64
64
  if (this.#element.style.animationName) {
65
- this.#element.style.animationName = 'slide-right-out';
66
- this.#element.addEventListener('animationend', removeEvents);
65
+ this.#element.style.animationName = "slide-right-out";
66
+ this.#element.addEventListener("animationend", removeEvents);
67
67
  }
68
68
  }
69
69
 
70
70
  // SLIDE BOTTOM
71
71
  slideBottomIn() {
72
72
  this.#cancelHide();
73
- if (window.getComputedStyle(this.#element, null).display === 'none') {
74
- if (this.#element.tagName !== "TABLE") this.#element.style.display = 'flex';
73
+ if (window.getComputedStyle(this.#element, null).display === "none") {
74
+ if (this.#element.tagName !== "TABLE") this.#element.style.display = "flex";
75
75
  }
76
- this.#element.style.animationName = 'slide-bottom-in';
76
+ this.#element.style.animationName = "slide-bottom-in";
77
77
  }
78
78
 
79
79
  slideBottomOut() {
80
80
  if (this.#element.style.animationName) {
81
- this.#element.style.animationName = 'slide-bottom-out';
82
- this.#element.addEventListener('animationend', removeEvents);
81
+ this.#element.style.animationName = "slide-bottom-out";
82
+ this.#element.addEventListener("animationend", removeEvents);
83
83
  }
84
84
  }
85
85
 
86
86
  // REMOVE
87
87
  slideBottomOutAndRemove() {
88
88
  if (this.#element.style.animationName) {
89
- this.#element.style.animationName = 'slide-bottom-out';
90
- this.#element.addEventListener('animationend', removeEvents);
89
+ this.#element.style.animationName = "slide-bottom-out";
90
+ this.#element.addEventListener("animationend", removeEvents);
91
91
  }
92
92
  }
93
93
 
94
94
  slideRightOutAndRemove() {
95
95
  if (this.#element.style.animationName) {
96
- this.#element.style.animationName = 'slide-right-out';
97
- this.#element.addEventListener('animationend', removeEvents);
96
+ this.#element.style.animationName = "slide-right-out";
97
+ this.#element.addEventListener("animationend", removeEvents);
98
98
  }
99
99
  }
100
100
 
101
101
  scaleOutAndRemove() {
102
102
  if (this.#element.style.animationName) {
103
- this.#element.style.animationName = 'scale-out';
104
- this.#element.addEventListener('animationend', removeEvents2);
103
+ this.#element.style.animationName = "scale-out";
104
+ this.#element.addEventListener("animationend", removeEvents2);
105
105
  }
106
106
  }
107
107
 
108
108
  fadeOutAndRemove() {
109
109
  if (this.#element.style.animationName) {
110
- this.#element.style.animationName = 'fade-out';
111
- this.#element.addEventListener('animationend', removeEvents2);
110
+ this.#element.style.animationName = "fade-out";
111
+ this.#element.addEventListener("animationend", removeEvents2);
112
112
  }
113
113
  }
114
114
 
@@ -118,19 +118,19 @@ class Animation {
118
118
  }
119
119
 
120
120
  removeStyles() {
121
- this.#element.removeAttribute("style")
121
+ this.#element.removeAttribute("style");
122
122
  }
123
123
  }
124
124
 
125
125
  const removeEvents2 = (event) => {
126
- event.target.remove()
127
- event.target.removeEventListener('animationend', removeEvents2);
128
- }
126
+ event.target.remove();
127
+ event.target.removeEventListener("animationend", removeEvents2);
128
+ };
129
129
 
130
130
  const removeEvents = (event) => {
131
- event.target.style.removeProperty('animation-name');
132
- event.target.style.removeProperty('display');
133
- event.target.removeEventListener('animationend', removeEvents);
134
- }
131
+ event.target.style.removeProperty("animation-name");
132
+ event.target.style.removeProperty("display");
133
+ event.target.removeEventListener("animationend", removeEvents);
134
+ };
135
135
 
136
- exports.Animation = Animation
136
+ exports.Animation = Animation;
@@ -77,4 +77,4 @@
77
77
  opacity: 0;
78
78
  transform: translateY(100%);
79
79
  }
80
- }
80
+ }
@@ -1,8 +1,14 @@
1
- const {contextBridge, ipcRenderer} = require("electron");
2
- const {SERVICES_CHANNELS, SERVICES_CALLS, SERVICES_SYNC_CALLS, BRIDGE_CHANNELS, BRIDGE_ARGS} = require("../chui_services/chui_channels");
1
+ const { contextBridge, ipcRenderer } = require("electron");
2
+ const {
3
+ SERVICES_CHANNELS,
4
+ SERVICES_CALLS,
5
+ SERVICES_SYNC_CALLS,
6
+ BRIDGE_CHANNELS,
7
+ BRIDGE_ARGS,
8
+ } = require("../chui_services/chui_channels");
3
9
  // Мост переиспользует ту же обёртку сервисов, что и страница: разница только в транспорте
4
10
  // (`Desktop` в preload'е сам вызовет ipcRenderer, потому что `window.chui` ему не виден)
5
- const {Desktop} = require("../chui_services/desktop");
11
+ const { Desktop } = require("../chui_services/desktop");
6
12
 
7
13
  /**
8
14
  * Preload безопасного режима (`Main({security: {contextIsolation: true}})`).
@@ -32,7 +38,10 @@ function argValue(prefix = String()) {
32
38
 
33
39
  const renderPath = argValue(BRIDGE_ARGS.RENDER);
34
40
  const csp = argValue(BRIDGE_ARGS.CSP);
35
- const channels = (argValue(BRIDGE_ARGS.CHANNELS) ?? "").split(",").map((channel) => channel.trim()).filter(Boolean);
41
+ const channels = (argValue(BRIDGE_ARGS.CHANNELS) ?? "")
42
+ .split(",")
43
+ .map((channel) => channel.trim())
44
+ .filter(Boolean);
36
45
 
37
46
  /**
38
47
  * Content-Security-Policy вставляется в документ до его скриптов: preload выполняется раньше
@@ -50,7 +59,7 @@ function applyCsp() {
50
59
  return true;
51
60
  }
52
61
 
53
- if (!applyCsp()) document.addEventListener("readystatechange", () => applyCsp(), {once: true});
62
+ if (!applyCsp()) document.addEventListener("readystatechange", () => applyCsp(), { once: true });
54
63
 
55
64
  const call = (method = String(), ...args) => {
56
65
  const channel = SERVICES_CALLS[method];
@@ -100,7 +109,7 @@ contextBridge.exposeInMainWorld("chui", {
100
109
  versions: {
101
110
  node: process.versions.node,
102
111
  chrome: process.versions.chrome,
103
- electron: process.versions.electron
112
+ electron: process.versions.electron,
104
113
  },
105
114
  platform: process.platform,
106
115
  /** Путь к странице окна (как он задан в опции `render`) */
@@ -120,20 +129,20 @@ contextBridge.exposeInMainWorld("chui", {
120
129
  copy: (text = String()) => Desktop.clipboard.history.copy(text),
121
130
  remove: (target = undefined) => Desktop.clipboard.history.remove(target),
122
131
  clear: () => Desktop.clipboard.history.clear(),
123
- onChange: (listener = () => {}) => services.onClipboardHistory(listener)
124
- }
132
+ onChange: (listener = () => {}) => services.onClipboardHistory(listener),
133
+ },
125
134
  },
126
135
  recent: {
127
136
  add: (path = String(), name = undefined) => Desktop.recent.add(path, name),
128
137
  clear: () => Desktop.recent.clear(),
129
- list: () => Desktop.recent.list()
138
+ list: () => Desktop.recent.list(),
130
139
  },
131
140
  progress: {
132
141
  set: (value = Number(), mode = "normal") => Desktop.progress.set(value, mode),
133
- clear: () => Desktop.progress.clear()
142
+ clear: () => Desktop.progress.clear(),
134
143
  },
135
144
  shell: {
136
- openExternal: (url = String()) => Desktop.shell.openExternal(url)
145
+ openExternal: (url = String()) => Desktop.shell.openExternal(url),
137
146
  },
138
147
  app: {
139
148
  // Путь приходит значением, без промиса (синхронный канал), а `Desktop` в preload'е
@@ -148,36 +157,36 @@ contextBridge.exposeInMainWorld("chui", {
148
157
  // Закрытие и перезапуск — как у `Desktop` из пакета: те же шаги, что у пункта меню.
149
158
  // Отвечают значением, а не промисом (синхронный канал), поэтому `await` не нужен
150
159
  quit: () => Desktop.app.quit(),
151
- restart: () => Desktop.app.restart()
160
+ restart: () => Desktop.app.restart(),
152
161
  },
153
162
  dialog: {
154
163
  open: (options = {}) => Desktop.dialog.open(options),
155
164
  save: (options = {}) => Desktop.dialog.save(options),
156
- message: (options = {}) => Desktop.dialog.message(options)
165
+ message: (options = {}) => Desktop.dialog.message(options),
157
166
  },
158
167
  session: {
159
168
  getCacheSize: () => Desktop.session.getCacheSize(),
160
169
  clearCache: () => Desktop.session.clearCache(),
161
- clearStorageData: (options = {}) => Desktop.session.clearStorageData(options)
170
+ clearStorageData: (options = {}) => Desktop.session.clearStorageData(options),
162
171
  },
163
172
  print: {
164
173
  page: (options = {}) => Desktop.print.page(options),
165
174
  html: (html = String(), options = {}) => Desktop.print.html(html, options),
166
- pdf: (html = String(), options = {}) => Desktop.print.pdf(html, options)
175
+ pdf: (html = String(), options = {}) => Desktop.print.pdf(html, options),
167
176
  },
168
177
  shortcuts: {
169
178
  on: (accelerator = String(), handler = () => {}) => Desktop.shortcuts.on(accelerator, handler),
170
179
  off: (accelerator = String(), handler = () => {}) => Desktop.shortcuts.off(accelerator, handler),
171
180
  offAll: () => Desktop.shortcuts.offAll(),
172
- get: () => Desktop.shortcuts.get()
173
- }
181
+ get: () => Desktop.shortcuts.get(),
182
+ },
174
183
  },
175
184
  window: {
176
185
  minimize: () => windowAction("minimize"),
177
186
  toggleMaximize: () => windowAction("toggle-maximize"),
178
187
  restore: () => windowAction("restore"),
179
188
  close: () => windowAction("close"),
180
- getState: () => ipcRenderer.invoke(BRIDGE_CHANNELS.WINDOW_STATE)
189
+ getState: () => ipcRenderer.invoke(BRIDGE_CHANNELS.WINDOW_STATE),
181
190
  },
182
191
  theme: {
183
192
  get: () => ipcRenderer.invoke(BRIDGE_CHANNELS.THEME_GET),
@@ -187,7 +196,7 @@ contextBridge.exposeInMainWorld("chui", {
187
196
  onChange: (listener = () => {}) => {
188
197
  themeListeners.add(listener);
189
198
  return () => themeListeners.delete(listener);
190
- }
199
+ },
191
200
  },
192
201
  locale: {
193
202
  get: () => ipcRenderer.invoke(BRIDGE_CHANNELS.LOCALE_GET),
@@ -196,17 +205,19 @@ contextBridge.exposeInMainWorld("chui", {
196
205
  onChange: (listener = () => {}) => {
197
206
  localeListeners.add(listener);
198
207
  return () => localeListeners.delete(listener);
199
- }
208
+ },
200
209
  },
201
210
  messaging: {
202
211
  /** Каналы задаёт приложение: `security: {channels: ['preview:update']}` */
203
212
  channels: [...channels],
204
213
  send: (channel = String(), ...args) => {
205
- if (!channels.includes(channel)) throw new Error(`chui: канал «${channel}» не разрешён в security.channels`);
214
+ if (!channels.includes(channel))
215
+ throw new Error(`chui: канал «${channel}» не разрешён в security.channels`);
206
216
  return ipcRenderer.invoke(BRIDGE_CHANNELS.MESSAGE, channel, ...args);
207
217
  },
208
218
  on: (channel = String(), listener = () => {}) => {
209
- if (!channels.includes(channel)) throw new Error(`chui: канал «${channel}» не разрешён в security.channels`);
219
+ if (!channels.includes(channel))
220
+ throw new Error(`chui: канал «${channel}» не разрешён в security.channels`);
210
221
  const listeners = messageListeners.get(channel) ?? new Set();
211
222
  listeners.add(listener);
212
223
  messageListeners.set(channel, listeners);
@@ -214,8 +225,8 @@ contextBridge.exposeInMainWorld("chui", {
214
225
  listeners.delete(listener);
215
226
  if (listeners.size === 0) messageListeners.delete(channel);
216
227
  };
217
- }
218
- }
228
+ },
229
+ },
219
230
  });
220
231
 
221
232
  // Скрипт страницы подключается здесь: в безопасном режиме `render` — это скрипт документа,
@@ -227,6 +238,6 @@ if (renderPath !== undefined) {
227
238
  script.defer = true;
228
239
  document.head.appendChild(script);
229
240
  };
230
- if (document.readyState === "loading") window.addEventListener("DOMContentLoaded", addPageScript, {once: true});
241
+ if (document.readyState === "loading") window.addEventListener("DOMContentLoaded", addPageScript, { once: true });
231
242
  else addPageScript();
232
243
  }