chuijs 4.0.2 → 4.0.4

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 (292) hide show
  1. package/CHANGELOG.md +597 -0
  2. package/README.md +43 -644
  3. package/framework/appLayout/default/chui_app_layout.js +602 -496
  4. package/framework/appLayout/default/global_style.css +288 -97
  5. package/framework/appLayout/default/main_theme_style.css +188 -101
  6. package/framework/components/chui_accordion/accordion.js +38 -35
  7. package/framework/components/chui_accordion/styles.css +13 -12
  8. package/framework/components/chui_action_sheet/action_sheet.js +93 -64
  9. package/framework/components/chui_action_sheet/styles.css +12 -5
  10. package/framework/components/chui_actions_bar/actions_bar.js +338 -0
  11. package/framework/components/chui_actions_bar/styles.css +139 -0
  12. package/framework/components/chui_affix/affix.js +16 -11
  13. package/framework/components/chui_affix/styles.css +5 -0
  14. package/framework/components/chui_alert/alert.js +34 -19
  15. package/framework/components/chui_alert/styles.css +7 -0
  16. package/framework/components/chui_avatar/avatar.js +36 -35
  17. package/framework/components/chui_avatar/styles.css +1 -1
  18. package/framework/components/chui_avatar_group/avatar_group.js +25 -23
  19. package/framework/components/chui_avatar_group/styles.css +1 -1
  20. package/framework/components/chui_backtop/backtop.js +60 -21
  21. package/framework/components/chui_backtop/styles.css +21 -0
  22. package/framework/components/chui_badge/badge.js +30 -28
  23. package/framework/components/chui_badge/styles.css +6 -6
  24. package/framework/components/chui_banner/banner.js +222 -0
  25. package/framework/components/chui_banner/styles.css +170 -0
  26. package/framework/components/chui_breadcrumb/breadcrumb.js +15 -13
  27. package/framework/components/chui_breadcrumb/styles.css +1 -1
  28. package/framework/components/chui_button/button.js +52 -36
  29. package/framework/components/chui_button/styles.css +7 -7
  30. package/framework/components/chui_calendar/calendar.js +18 -16
  31. package/framework/components/chui_card/card.js +52 -32
  32. package/framework/components/chui_card_scroll/card_scroll.js +169 -0
  33. package/framework/components/chui_card_scroll/styles.css +86 -0
  34. package/framework/components/chui_chat/chat.js +140 -79
  35. package/framework/components/chui_chat/styles.css +18 -7
  36. package/framework/components/chui_clipboard_history/clipboard_history.js +53 -39
  37. package/framework/components/chui_clipboard_history/styles.css +13 -9
  38. package/framework/components/chui_code/code.js +10 -10
  39. package/framework/components/chui_code/styles.css +4 -4
  40. package/framework/components/chui_code_editor/code_editor.js +73 -57
  41. package/framework/components/chui_code_editor/styles.css +6 -5
  42. package/framework/components/chui_command_palette/command_palette.js +87 -64
  43. package/framework/components/chui_command_palette/styles.css +5 -5
  44. package/framework/components/chui_console/console.js +13 -13
  45. package/framework/components/chui_console/styles.css +6 -3
  46. package/framework/components/chui_content_block/content_block.js +35 -21
  47. package/framework/components/chui_content_block/styles.css +2 -2
  48. package/framework/components/chui_context_menu/context_menu.js +171 -58
  49. package/framework/components/chui_context_menu/styles.css +82 -8
  50. package/framework/components/chui_custom_element/custom_element.js +25 -18
  51. package/framework/components/chui_data_grid/data_grid.js +633 -471
  52. package/framework/components/chui_data_grid/styles.css +24 -22
  53. package/framework/components/chui_descriptions/descriptions.js +34 -17
  54. package/framework/components/chui_descriptions/styles.css +1 -1
  55. package/framework/components/chui_details/details.js +42 -36
  56. package/framework/components/chui_details/styles.css +12 -11
  57. package/framework/components/chui_diff_viewer/diff_viewer.js +172 -147
  58. package/framework/components/chui_diff_viewer/styles.css +10 -10
  59. package/framework/components/chui_divider/divider.js +19 -17
  60. package/framework/components/chui_divider/styles.css +2 -2
  61. package/framework/components/chui_drawer/drawer.js +63 -38
  62. package/framework/components/chui_drawer/styles.css +18 -4
  63. package/framework/components/chui_drop_zone/drop_zone.js +37 -27
  64. package/framework/components/chui_drop_zone/styles.css +10 -6
  65. package/framework/components/chui_empty_state/empty_state.js +20 -15
  66. package/framework/components/chui_fieldset/fieldset.js +40 -23
  67. package/framework/components/chui_fieldset/styles.css +6 -6
  68. package/framework/components/chui_file_explorer/file_explorer.js +260 -189
  69. package/framework/components/chui_file_explorer/styles.css +8 -7
  70. package/framework/components/chui_form/form.js +40 -28
  71. package/framework/components/chui_form/styles.css +1 -1
  72. package/framework/components/chui_gantt/gantt.js +102 -78
  73. package/framework/components/chui_gantt/styles.css +5 -5
  74. package/framework/components/chui_graphs/graphs.js +376 -239
  75. package/framework/components/chui_graphs/styles.css +27 -6
  76. package/framework/components/chui_hero/hero.js +98 -37
  77. package/framework/components/chui_hero/styles.css +176 -7
  78. package/framework/components/chui_html_block/html_block.js +8 -8
  79. package/framework/components/chui_html_block/styles.css +3 -3
  80. package/framework/components/chui_hx/hx.js +3 -3
  81. package/framework/components/chui_hx/styles.css +13 -6
  82. package/framework/components/chui_icons/icons.js +2115 -2115
  83. package/framework/components/chui_icons/styles.css +4 -3
  84. package/framework/components/chui_inputs/chui_check_box/check_box.js +31 -19
  85. package/framework/components/chui_inputs/chui_check_box/styles.css +30 -21
  86. package/framework/components/chui_inputs/chui_chips/chips.js +141 -70
  87. package/framework/components/chui_inputs/chui_chips/styles.css +32 -7
  88. package/framework/components/chui_inputs/chui_color_picker/color_picker.js +55 -38
  89. package/framework/components/chui_inputs/chui_color_picker/styles.css +7 -7
  90. package/framework/components/chui_inputs/chui_combo_box/combo_box.js +127 -109
  91. package/framework/components/chui_inputs/chui_combo_box/styles.css +23 -21
  92. package/framework/components/chui_inputs/chui_date/date.js +161 -127
  93. package/framework/components/chui_inputs/chui_date/styles.css +20 -19
  94. package/framework/components/chui_inputs/chui_date_range/date_range.js +61 -50
  95. package/framework/components/chui_inputs/chui_date_range/styles.css +3 -3
  96. package/framework/components/chui_inputs/chui_datetime/datetime.js +47 -39
  97. package/framework/components/chui_inputs/chui_datetime/styles.css +3 -3
  98. package/framework/components/chui_inputs/chui_email/email.js +48 -36
  99. package/framework/components/chui_inputs/chui_email/styles.css +11 -11
  100. package/framework/components/chui_inputs/chui_file/file.js +71 -44
  101. package/framework/components/chui_inputs/chui_file/styles.css +23 -19
  102. package/framework/components/chui_inputs/chui_hotkey/hotkey.js +101 -76
  103. package/framework/components/chui_inputs/chui_hotkey/styles.css +6 -6
  104. package/framework/components/chui_inputs/chui_masked/masked.js +83 -72
  105. package/framework/components/chui_inputs/chui_masked/styles.css +5 -5
  106. package/framework/components/chui_inputs/chui_mention/mention.js +87 -40
  107. package/framework/components/chui_inputs/chui_mention/styles.css +14 -8
  108. package/framework/components/chui_inputs/chui_multi_combo_box/multi_combo_box.js +242 -212
  109. package/framework/components/chui_inputs/chui_multi_combo_box/styles.css +23 -15
  110. package/framework/components/chui_inputs/chui_number/number.js +84 -70
  111. package/framework/components/chui_inputs/chui_number/styles.css +13 -13
  112. package/framework/components/chui_inputs/chui_otp/otp.js +71 -62
  113. package/framework/components/chui_inputs/chui_otp/styles.css +5 -5
  114. package/framework/components/chui_inputs/chui_password/password.js +72 -56
  115. package/framework/components/chui_inputs/chui_password/styles.css +15 -15
  116. package/framework/components/chui_inputs/chui_radio_button/radio_button.js +37 -25
  117. package/framework/components/chui_inputs/chui_radio_button/styles.css +22 -22
  118. package/framework/components/chui_inputs/chui_rating/rating.js +54 -50
  119. package/framework/components/chui_inputs/chui_rating/styles.css +3 -3
  120. package/framework/components/chui_inputs/chui_select_box/select_box.js +132 -108
  121. package/framework/components/chui_inputs/chui_select_box/styles.css +21 -21
  122. package/framework/components/chui_inputs/chui_slider/slider.js +41 -38
  123. package/framework/components/chui_inputs/chui_slider/styles.css +7 -5
  124. package/framework/components/chui_inputs/chui_text/styles.css +14 -14
  125. package/framework/components/chui_inputs/chui_text/text.js +69 -52
  126. package/framework/components/chui_inputs/chui_text_area/styles.css +14 -14
  127. package/framework/components/chui_inputs/chui_text_area/text_area.js +59 -36
  128. package/framework/components/chui_inputs/chui_time/styles.css +18 -20
  129. package/framework/components/chui_inputs/chui_time/time.js +71 -49
  130. package/framework/components/chui_inputs/chui_toggle/styles.css +13 -6
  131. package/framework/components/chui_inputs/chui_toggle/toggle.js +27 -27
  132. package/framework/components/chui_json_editor/json_editor.js +137 -127
  133. package/framework/components/chui_json_editor/styles.css +5 -5
  134. package/framework/components/chui_json_viewer/json_viewer.js +133 -114
  135. package/framework/components/chui_json_viewer/styles.css +9 -8
  136. package/framework/components/chui_kanban/kanban.js +78 -60
  137. package/framework/components/chui_kanban/styles.css +8 -4
  138. package/framework/components/chui_kbd/kbd.js +12 -10
  139. package/framework/components/chui_kbd/styles.css +1 -1
  140. package/framework/components/chui_label/label.js +31 -29
  141. package/framework/components/chui_label/styles.css +3 -3
  142. package/framework/components/chui_link/link.js +36 -29
  143. package/framework/components/chui_link/styles.css +11 -4
  144. package/framework/components/chui_list/list.js +42 -38
  145. package/framework/components/chui_list/styles.css +4 -3
  146. package/framework/components/chui_markdown_editor/markdown_editor.js +125 -109
  147. package/framework/components/chui_markdown_editor/styles.css +5 -5
  148. package/framework/components/chui_media/audio.js +457 -364
  149. package/framework/components/chui_media/audio_styles.css +74 -37
  150. package/framework/components/chui_media/image.js +99 -64
  151. package/framework/components/chui_media/image_compare.js +86 -55
  152. package/framework/components/chui_media/image_compare_styles.css +5 -5
  153. package/framework/components/chui_media/image_styles.css +4 -4
  154. package/framework/components/chui_media/video.js +264 -171
  155. package/framework/components/chui_media/video_styles.css +57 -24
  156. package/framework/components/chui_menu_bar/menu_bar.js +67 -65
  157. package/framework/components/chui_menu_bar/styles.css +14 -12
  158. package/framework/components/chui_message_bar/message_bar.js +551 -0
  159. package/framework/components/chui_message_bar/styles.css +248 -0
  160. package/framework/components/chui_modal/modal.js +81 -56
  161. package/framework/components/chui_modal/styles.css +3 -2
  162. package/framework/components/chui_notification/notification.js +107 -69
  163. package/framework/components/chui_notification/notification_download.js +28 -77
  164. package/framework/components/chui_notification/notification_download_card.js +115 -0
  165. package/framework/components/chui_notification/notification_download_progress.css +5 -4
  166. package/framework/components/chui_notification/notification_download_progress.js +73 -105
  167. package/framework/components/chui_notification/notification_update.js +44 -37
  168. package/framework/components/chui_notification/status_plate.css +3 -3
  169. package/framework/components/chui_notification/status_plate.js +2 -2
  170. package/framework/components/chui_notification/styles.css +6 -1
  171. package/framework/components/chui_notification/styles_download.css +2 -2
  172. package/framework/components/chui_notification/styles_update.css +3 -3
  173. package/framework/components/chui_org_chart/org_chart.js +101 -62
  174. package/framework/components/chui_org_chart/styles.css +2 -2
  175. package/framework/components/chui_pagination/pagination.js +65 -30
  176. package/framework/components/chui_pagination/styles.css +1 -1
  177. package/framework/components/chui_paragraph/paragraph.js +2 -2
  178. package/framework/components/chui_paragraph/styles.css +3 -3
  179. package/framework/components/chui_popover/popover.js +77 -50
  180. package/framework/components/chui_popover/styles.css +1 -1
  181. package/framework/components/chui_popups/popups.js +210 -181
  182. package/framework/components/chui_popups/styles.css +7 -7
  183. package/framework/components/chui_print_button/print_button.js +48 -33
  184. package/framework/components/chui_progress_bar/progress_bar.js +49 -19
  185. package/framework/components/chui_progress_bar/styles.css +6 -6
  186. package/framework/components/chui_progress_ring/progress_ring.js +32 -30
  187. package/framework/components/chui_progress_ring/styles.css +1 -1
  188. package/framework/components/chui_qrcode/qrcode.js +85 -41
  189. package/framework/components/chui_query_builder/query_builder.js +263 -170
  190. package/framework/components/chui_query_builder/styles.css +4 -4
  191. package/framework/components/chui_radio_group/radio_group.js +36 -26
  192. package/framework/components/chui_radio_group/styles.css +2 -2
  193. package/framework/components/chui_result/result.js +41 -31
  194. package/framework/components/chui_result/styles.css +3 -3
  195. package/framework/components/chui_scheduler/scheduler.js +126 -104
  196. package/framework/components/chui_scheduler/styles.css +11 -7
  197. package/framework/components/chui_screen_spinner/screen_spinner.js +167 -0
  198. package/framework/components/chui_screen_spinner/styles.css +49 -0
  199. package/framework/components/chui_segmented_control/segmented_control.js +90 -27
  200. package/framework/components/chui_segmented_control/styles.css +32 -6
  201. package/framework/components/chui_settings/settings.js +160 -87
  202. package/framework/components/chui_settings/styles.css +4 -4
  203. package/framework/components/chui_shortcut_help/shortcut_help.js +82 -61
  204. package/framework/components/chui_sidebar_nav/sidebar_nav.js +132 -53
  205. package/framework/components/chui_sidebar_nav/styles.css +9 -3
  206. package/framework/components/chui_skeleton/skeleton.js +29 -24
  207. package/framework/components/chui_slideshow/slideshow.js +122 -103
  208. package/framework/components/chui_slideshow/styles.css +22 -16
  209. package/framework/components/chui_spinner/spinner.js +17 -17
  210. package/framework/components/chui_spinner/styles.css +0 -1
  211. package/framework/components/chui_split_button/split_button.js +53 -30
  212. package/framework/components/chui_split_button/styles.css +22 -6
  213. package/framework/components/chui_splitter/splitter.js +46 -39
  214. package/framework/components/chui_splitter/styles.css +2 -2
  215. package/framework/components/chui_statistic/statistic.js +111 -84
  216. package/framework/components/chui_status_bar/status_bar.js +11 -9
  217. package/framework/components/chui_status_bar/styles.css +2 -2
  218. package/framework/components/chui_stepper/stepper.js +230 -54
  219. package/framework/components/chui_stepper/styles.css +79 -14
  220. package/framework/components/chui_sticky_bar/sticky_bar.js +53 -17
  221. package/framework/components/chui_sticky_bar/styles.css +11 -7
  222. package/framework/components/chui_tabs/chui_tabs.js +100 -46
  223. package/framework/components/chui_tabs/styles.css +43 -15
  224. package/framework/components/chui_text_editor/styles.css +24 -23
  225. package/framework/components/chui_text_editor/text_editor.js +103 -79
  226. package/framework/components/chui_text_editor/text_editor_panel.js +428 -367
  227. package/framework/components/chui_theme_toggle/theme_toggle.js +46 -25
  228. package/framework/components/chui_timeline/styles.css +3 -1
  229. package/framework/components/chui_timeline/timeline.js +14 -12
  230. package/framework/components/chui_toast_queue/styles.css +11 -11
  231. package/framework/components/chui_toast_queue/toast_queue.js +82 -73
  232. package/framework/components/chui_toolbar/styles.css +2 -2
  233. package/framework/components/chui_toolbar/toolbar.js +20 -13
  234. package/framework/components/chui_tooltip/styles.css +2 -2
  235. package/framework/components/chui_tooltip/tooltip.js +40 -27
  236. package/framework/components/chui_tour/styles.css +12 -7
  237. package/framework/components/chui_tour/tour.js +132 -98
  238. package/framework/components/chui_transfer/styles.css +8 -7
  239. package/framework/components/chui_transfer/transfer.js +143 -123
  240. package/framework/components/chui_tree_table/styles.css +4 -4
  241. package/framework/components/chui_tree_table/tree_table.js +88 -74
  242. package/framework/components/chui_tree_view/styles.css +14 -10
  243. package/framework/components/chui_tree_view/tree_view.js +298 -253
  244. package/framework/components/chui_user_bar/styles.css +145 -0
  245. package/framework/components/chui_user_bar/user_bar.js +402 -0
  246. package/framework/components/chui_user_list_bar/styles.css +173 -0
  247. package/framework/components/chui_user_list_bar/user_list_bar.js +485 -0
  248. package/framework/components/chui_watermark/watermark.js +41 -33
  249. package/framework/components/chui_webview/styles.css +2 -2
  250. package/framework/components/chui_webview/webview.js +64 -52
  251. package/framework/components/chui_write_bar/styles.css +172 -0
  252. package/framework/components/chui_write_bar/write_bar.js +320 -0
  253. package/framework/main_window.js +1234 -0
  254. package/framework/modules/chui_a11y/chui_a11y.js +153 -123
  255. package/framework/modules/chui_animations/animations.js +105 -43
  256. package/framework/modules/chui_animations/motion.js +120 -0
  257. package/framework/modules/chui_animations/styles.css +37 -4
  258. package/framework/modules/chui_bridge/preload.js +36 -25
  259. package/framework/modules/chui_functions.js +69 -63
  260. package/framework/modules/chui_highlight/chui_highlight.js +25 -22
  261. package/framework/modules/chui_highlight/styles.css +13 -10
  262. package/framework/modules/chui_i18n/chui_i18n.js +12 -10
  263. package/framework/modules/chui_i18n/locales/a11y.js +5 -5
  264. package/framework/modules/chui_i18n/locales/app_layout.js +5 -5
  265. package/framework/modules/chui_i18n/locales/calendar.js +3 -3
  266. package/framework/modules/chui_i18n/locales/common.js +3 -3
  267. package/framework/modules/chui_i18n/locales/data.js +36 -26
  268. package/framework/modules/chui_i18n/locales/editors.js +40 -13
  269. package/framework/modules/chui_i18n/locales/feedback.js +65 -3
  270. package/framework/modules/chui_i18n/locales/forms.js +8 -8
  271. package/framework/modules/chui_i18n/locales/graphics.js +8 -8
  272. package/framework/modules/chui_i18n/locales/media.js +4 -4
  273. package/framework/modules/chui_i18n/locales/navigation.js +12 -8
  274. package/framework/modules/chui_i18n/locales/validate.js +3 -3
  275. package/framework/modules/chui_json/chui_json.js +11 -11
  276. package/framework/modules/chui_layout/chui_layout.js +12 -10
  277. package/framework/modules/chui_logger/chui_logger.js +47 -28
  278. package/framework/modules/chui_page/page.js +39 -33
  279. package/framework/modules/chui_palette/palette.js +61 -0
  280. package/framework/modules/chui_qr/chui_qr.js +179 -88
  281. package/framework/modules/chui_scrollbar/chui_scrollbar.js +79 -68
  282. package/framework/modules/chui_scrollbar/styles.css +4 -2
  283. package/framework/modules/chui_services/chui_channels.js +27 -13
  284. package/framework/modules/chui_services/chui_services.js +47 -39
  285. package/framework/modules/chui_services/desktop.js +108 -101
  286. package/framework/modules/chui_sortable/chui_sortable.js +33 -28
  287. package/framework/modules/chui_validate/chui_validate.js +10 -7
  288. package/framework/tray_bar/chui_menu_items.js +136 -46
  289. package/index.d.ts +5046 -0
  290. package/index.js +199 -1254
  291. package/package.json +81 -68
  292. package/framework/components/telegram_bot/chui_telegram_bot.js +0 -184
@@ -14,44 +14,50 @@
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
  // Стек открытых слоёв: нужен, чтобы вложенный слой не снимал фон-инерт у родителя
28
28
  static #stack = [];
29
- static #labelled_counter = 0;
29
+ static #labelledCounter = 0;
30
30
 
31
31
  #element = undefined;
32
32
  #role = "dialog";
33
33
  #label = undefined;
34
- #label_node = undefined;
35
- #described_by = undefined;
36
- #on_escape = undefined;
37
- #previous_focus = undefined;
38
- #is_open = false;
39
-
40
- constructor(element, options = {
41
- role: String(), label: String(), labelNode: undefined, describedBy: undefined,
42
- onEscape: undefined,
43
- }) {
34
+ #labelNode = undefined;
35
+ #describedBy = undefined;
36
+ #onEscape = undefined;
37
+ #previousFocus = undefined;
38
+ #isOpen = false;
39
+
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;
47
- this.#label_node = options.labelNode;
48
- this.#described_by = options.describedBy;
49
- this.#on_escape = options.onEscape;
53
+ this.#labelNode = options.labelNode;
54
+ this.#describedBy = options.describedBy;
55
+ this.#onEscape = options.onEscape;
50
56
  this.#applyAria();
51
57
  }
52
58
 
53
59
  get isOpen() {
54
- return this.#is_open;
60
+ return this.#isOpen;
55
61
  }
56
62
 
57
63
  setLabel(text = String()) {
@@ -60,18 +66,18 @@ class OverlayA11y {
60
66
  }
61
67
 
62
68
  open() {
63
- if (this.#is_open) return;
64
- this.#is_open = true;
69
+ if (this.#isOpen) return;
70
+ this.#isOpen = true;
65
71
  OverlayA11y.#stack.push(this);
66
- this.#previous_focus = document.activeElement;
72
+ this.#previousFocus = document.activeElement;
67
73
  OverlayA11y.#applyInert();
68
74
  document.addEventListener("keydown", this.#keydownEvent, true);
69
75
  this.#focusFirst();
70
76
  }
71
77
 
72
78
  close() {
73
- if (!this.#is_open) return;
74
- this.#is_open = false;
79
+ if (!this.#isOpen) return;
80
+ this.#isOpen = false;
75
81
  const index = OverlayA11y.#stack.indexOf(this);
76
82
  if (index !== -1) OverlayA11y.#stack.splice(index, 1);
77
83
  document.removeEventListener("keydown", this.#keydownEvent, true);
@@ -83,21 +89,21 @@ class OverlayA11y {
83
89
  const element = this.#element;
84
90
  element.setAttribute("role", this.#role);
85
91
  element.setAttribute("aria-modal", "true");
86
- if (this.#label_node !== undefined) {
87
- element.setAttribute("aria-labelledby", OverlayA11y.#ensureId(this.#label_node));
92
+ if (this.#labelNode !== undefined) {
93
+ element.setAttribute("aria-labelledby", OverlayA11y.#ensureId(this.#labelNode));
88
94
  element.removeAttribute("aria-label");
89
95
  } else if (this.#label !== undefined) {
90
96
  element.setAttribute("aria-label", this.#label);
91
97
  }
92
- if (this.#described_by !== undefined) {
93
- element.setAttribute("aria-describedby", OverlayA11y.#ensureId(this.#described_by));
98
+ if (this.#describedBy !== undefined) {
99
+ element.setAttribute("aria-describedby", OverlayA11y.#ensureId(this.#describedBy));
94
100
  }
95
101
  }
96
102
 
97
103
  static #ensureId(element) {
98
104
  if (element.id === undefined || element.id === "") {
99
- OverlayA11y.#labelled_counter += 1;
100
- element.id = "chui_a11y_node_" + OverlayA11y.#labelled_counter;
105
+ OverlayA11y.#labelledCounter += 1;
106
+ element.id = "chui_a11y_node_" + OverlayA11y.#labelledCounter;
101
107
  }
102
108
  return element.id;
103
109
  }
@@ -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() {
@@ -139,8 +146,8 @@ class OverlayA11y {
139
146
  }
140
147
 
141
148
  #restoreFocus() {
142
- const previous = this.#previous_focus;
143
- this.#previous_focus = undefined;
149
+ const previous = this.#previousFocus;
150
+ this.#previousFocus = undefined;
144
151
  if (previous !== undefined && previous !== null && document.body.contains(previous)) previous.focus();
145
152
  }
146
153
 
@@ -170,12 +177,12 @@ class OverlayA11y {
170
177
  if (event.key === "Escape") {
171
178
  event.preventDefault();
172
179
  event.stopPropagation();
173
- if (this.#on_escape !== undefined) this.#on_escape();
180
+ if (this.#onEscape !== undefined) this.#onEscape();
174
181
  else this.close();
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, меню шапки).
@@ -213,30 +226,37 @@ const isDisabled = (element) => element.disabled === true || element.getAttribut
213
226
  */
214
227
  class MenuKeyboard {
215
228
  #container = undefined;
216
- #item_selector = undefined;
229
+ #itemSelector = undefined;
217
230
  #role = "menu";
218
- #item_role = "menuitem";
219
- #submenu_selector = undefined;
220
- #on_submenu_open = undefined;
221
- #is_submenu = false;
222
- #type_buffer = "";
223
- #type_at = 0;
224
- #on_escape = undefined;
231
+ #itemRole = "menuitem";
232
+ #submenuSelector = undefined;
233
+ #onSubmenuOpen = undefined;
234
+ #isSubmenu = false;
235
+ #typeBuffer = "";
236
+ #typeAt = 0;
237
+ #onEscape = undefined;
225
238
  #trigger = undefined;
226
- #trigger_bound = false;
227
-
228
- constructor(container, options = {
229
- role: String(), itemRole: String(), itemSelector: String(),
230
- submenuSelector: String(), onEscape: undefined, trigger: undefined
231
- }) {
239
+ #triggerBound = false;
240
+
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
- if (options.itemRole !== undefined) this.#item_role = options.itemRole;
235
- this.#item_selector = options.itemSelector;
236
- this.#submenu_selector = options.submenuSelector;
237
- this.#on_escape = options.onEscape;
238
- this.#on_submenu_open = options.onSubmenuOpen;
239
- this.#is_submenu = options.submenu === true;
254
+ if (options.itemRole !== undefined) this.#itemRole = options.itemRole;
255
+ this.#itemSelector = options.itemSelector;
256
+ this.#submenuSelector = options.submenuSelector;
257
+ this.#onEscape = options.onEscape;
258
+ this.#onSubmenuOpen = options.onSubmenuOpen;
259
+ this.#isSubmenu = options.submenu === true;
240
260
  this.#trigger = options.trigger;
241
261
  container.setAttribute("role", this.#role);
242
262
  this.refresh();
@@ -245,17 +265,17 @@ class MenuKeyboard {
245
265
  // содержит контейнер (строка подменю — предок своей панели), то это тот же путь события:
246
266
  // второй обработчик на предке обработал бы одну клавишу дважды — пункт подменю срабатывал бы
247
267
  // от одного Enter дважды, а одна стрелка перескакивала бы через пункт.
248
- this.#trigger_bound = options.trigger !== undefined && options.trigger.contains(container) === false;
249
- if (this.#trigger_bound) options.trigger.addEventListener("keydown", this.#keydownEvent);
268
+ this.#triggerBound = options.trigger !== undefined && options.trigger.contains(container) === false;
269
+ if (this.#triggerBound) options.trigger.addEventListener("keydown", this.#keydownEvent);
250
270
  }
251
271
 
252
272
  /** Перечитать пункты: роли, tabindex, состояние триггера (в том числе в закрытом меню) */
253
273
  refresh() {
254
274
  for (const item of this.#allItems()) {
255
- if (item.getAttribute("role") === null) item.setAttribute("role", this.#item_role);
275
+ if (item.getAttribute("role") === null) item.setAttribute("role", this.#itemRole);
256
276
  if (item.getAttribute("tabindex") === null) item.setAttribute("tabindex", "-1");
257
277
  if (isDisabled(item)) item.setAttribute("aria-disabled", "true");
258
- if (this.#submenu_selector !== undefined && item.querySelector(this.#submenu_selector) !== null) {
278
+ if (this.#submenuSelector !== undefined && item.querySelector(this.#submenuSelector) !== null) {
259
279
  item.setAttribute("aria-haspopup", "true");
260
280
  }
261
281
  }
@@ -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.#itemSelector)].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
  // Для навигации — только видимые пункты своего уровня
@@ -309,7 +330,7 @@ class MenuKeyboard {
309
330
  }
310
331
 
311
332
  #openOrClick(item) {
312
- if (this.#submenu_selector !== undefined && item.querySelector(this.#submenu_selector) !== null) {
333
+ if (this.#submenuSelector !== undefined && item.querySelector(this.#submenuSelector) !== null) {
313
334
  this.#openSubmenu(item);
314
335
  return;
315
336
  }
@@ -317,11 +338,11 @@ class MenuKeyboard {
317
338
  }
318
339
 
319
340
  #openSubmenu(row) {
320
- if (this.#submenu_selector === undefined) return;
321
- const submenu = row.querySelector(this.#submenu_selector);
341
+ if (this.#submenuSelector === undefined) return;
342
+ const submenu = row.querySelector(this.#submenuSelector);
322
343
  if (submenu === null) return;
323
- if (this.#on_submenu_open !== undefined) this.#on_submenu_open(row);
324
- const first = [...submenu.querySelectorAll(this.#item_selector)].filter(isVisible)[0];
344
+ if (this.#onSubmenuOpen !== undefined) this.#onSubmenuOpen(row);
345
+ const first = [...submenu.querySelectorAll(this.#itemSelector)].filter(isVisible)[0];
325
346
  if (first !== undefined) first.focus();
326
347
  }
327
348
 
@@ -360,20 +381,20 @@ class MenuKeyboard {
360
381
  break;
361
382
  }
362
383
  case "ArrowLeft": {
363
- if (!this.#is_submenu) break;
384
+ if (!this.#isSubmenu) break;
364
385
  event.preventDefault();
365
- if (this.#on_escape !== undefined) this.#on_escape();
386
+ if (this.#onEscape !== undefined) this.#onEscape();
366
387
  if (this.#trigger !== undefined && document.body.contains(this.#trigger)) this.#trigger.focus();
367
388
  break;
368
389
  }
369
390
  case "Escape":
370
391
  event.preventDefault();
371
392
  event.stopPropagation();
372
- if (this.#on_escape !== undefined) this.#on_escape();
393
+ if (this.#onEscape !== undefined) this.#onEscape();
373
394
  if (this.#trigger !== undefined && document.body.contains(this.#trigger)) this.#trigger.focus();
374
395
  break;
375
396
  case "Tab":
376
- if (this.#on_escape !== undefined) this.#on_escape();
397
+ if (this.#onEscape !== undefined) this.#onEscape();
377
398
  break;
378
399
  default:
379
400
  // Type-ahead: набор букв переводит фокус на пункт с таким началом
@@ -382,19 +403,19 @@ class MenuKeyboard {
382
403
  }
383
404
  break;
384
405
  }
385
- }
406
+ };
386
407
 
387
408
  #typeahead(char) {
388
409
  const now = Date.now();
389
410
  // Буфер сбрасывается, если с прошлой буквы прошло больше 700 мс
390
- this.#type_buffer = (now - this.#type_at > 700 ? "" : this.#type_buffer) + char.toLowerCase();
391
- this.#type_at = now;
411
+ this.#typeBuffer = (now - this.#typeAt > 700 ? "" : this.#typeBuffer) + char.toLowerCase();
412
+ this.#typeAt = now;
392
413
  const items = this.#items();
393
414
  if (items.length === 0) return;
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.#typeBuffer));
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.#triggerBound)
437
+ this.#trigger.removeEventListener("keydown", this.#keydownEvent);
416
438
  }
417
439
  }
418
440
 
@@ -424,21 +446,28 @@ class MenuKeyboard {
424
446
  class ComboboxKeyboard {
425
447
  #input = undefined;
426
448
  #dropdown = undefined;
427
- #option_selector = undefined;
428
- #on_escape = undefined;
429
- #on_open = undefined;
449
+ #optionSelector = undefined;
450
+ #onEscape = undefined;
451
+ #onOpen = undefined;
430
452
  #active = undefined;
431
- #selection_state = undefined;
432
-
433
- constructor(input, options = {
434
- dropdown: undefined, optionSelector: String(), onEscape: undefined, onOpen: undefined, selectionState: undefined
435
- }) {
453
+ #selectionState = undefined;
454
+
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
- this.#option_selector = options.optionSelector;
439
- this.#on_escape = options.onEscape;
440
- this.#on_open = options.onOpen;
441
- this.#selection_state = options.selectionState;
467
+ this.#optionSelector = options.optionSelector;
468
+ this.#onEscape = options.onEscape;
469
+ this.#onOpen = options.onOpen;
470
+ this.#selectionState = options.selectionState;
442
471
  input.setAttribute("role", "combobox");
443
472
  input.setAttribute("aria-haspopup", "listbox");
444
473
  input.setAttribute("aria-expanded", "false");
@@ -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
  }
@@ -473,21 +503,21 @@ class ComboboxKeyboard {
473
503
 
474
504
  #allOptions() {
475
505
  if (this.#dropdown === undefined) return [];
476
- return [...this.#dropdown.querySelectorAll(this.#option_selector)];
506
+ return [...this.#dropdown.querySelectorAll(this.#optionSelector)];
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() {
484
514
  // Множественный выбор: `aria-selected` показывает выбор, а не наведение (его несёт
485
515
  // `aria-activedescendant`) — иначе пометка «под курсором» выглядела бы как отметка.
486
- const has_selection = typeof this.#selection_state === "function";
516
+ const hasSelection = typeof this.#selectionState === "function";
487
517
  for (const option of this.#allOptions()) {
488
518
  const active = option === this.#active;
489
519
  option.classList.toggle(ACTIVE_CLASS, active);
490
- const selected = has_selection ? this.#selection_state(option) === true : active;
520
+ const selected = hasSelection ? this.#selectionState(option) === true : active;
491
521
  option.setAttribute("aria-selected", selected ? "true" : "false");
492
522
  }
493
523
  if (this.#active === undefined) this.#input.removeAttribute("aria-activedescendant");
@@ -511,7 +541,7 @@ 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.#onOpen !== undefined) this.#onOpen();
515
545
  this.#move(event.key === "ArrowDown" ? 1 : -1);
516
546
  break;
517
547
  }
@@ -541,13 +571,13 @@ class ComboboxKeyboard {
541
571
  this.#applyActive();
542
572
  break;
543
573
  }
544
- if (this.#on_escape !== undefined) this.#on_escape();
574
+ if (this.#onEscape !== undefined) this.#onEscape();
545
575
  break;
546
576
  }
547
577
  default:
548
578
  break;
549
579
  }
550
- }
580
+ };
551
581
 
552
582
  destroy() {
553
583
  this.#input.removeEventListener("keydown", this.#keydownEvent);
@@ -563,26 +593,26 @@ class ComboboxKeyboard {
563
593
  */
564
594
  class RovingKeyboard {
565
595
  #container = undefined;
566
- #item_selector = undefined;
567
- #on_click = undefined;
596
+ #itemSelector = undefined;
597
+ #onClick = undefined;
568
598
 
569
599
  constructor(container, options = { itemSelector: String() }) {
570
600
  this.#container = container;
571
- this.#item_selector = options.itemSelector;
601
+ this.#itemSelector = options.itemSelector;
572
602
  this.refresh();
573
- this.#on_click = (event) => {
574
- const item = event.target instanceof Element ? event.target.closest(this.#item_selector) : null;
603
+ this.#onClick = (event) => {
604
+ const item = event.target instanceof Element ? event.target.closest(this.#itemSelector) : null;
575
605
  if (item === null || !this.#container.contains(item)) return;
576
606
  this.#applyStop(item);
577
607
  };
578
608
  container.addEventListener("keydown", this.#keydownEvent);
579
- container.addEventListener("click", this.#on_click);
609
+ container.addEventListener("click", this.#onClick);
580
610
  }
581
611
 
582
612
  /** Перечитать пункты: остановка остаётся на прежнем, если он ещё доступен */
583
613
  refresh() {
584
614
  const visible = this.#items();
585
- const current = visible.find(item => item.getAttribute("tabindex") === "0");
615
+ const current = visible.find((item) => item.getAttribute("tabindex") === "0");
586
616
  // Панель может быть ещё не в документе (размеры нулевые) — тогда остановку получает
587
617
  // первый пункт: без неё группа целиком выпала бы из обхода Tab
588
618
  const fallback = visible[0] === undefined ? this.#allItems()[0] : visible[0];
@@ -593,18 +623,18 @@ class RovingKeyboard {
593
623
 
594
624
  // Все пункты группы, включая скрытые: tabindex проставляется и до появления панели на экране
595
625
  #allItems() {
596
- return [...this.#container.querySelectorAll(this.#item_selector)];
626
+ return [...this.#container.querySelectorAll(this.#itemSelector)];
597
627
  }
598
628
 
599
629
  // Пункты, по которым ходит клавиатура: видимые и не запрещённые
600
630
  #items() {
601
- return this.#allItems().filter(item => !isDisabled(item) && isVisible(item));
631
+ return this.#allItems().filter((item) => !isDisabled(item) && isVisible(item));
602
632
  }
603
633
 
604
634
  #activeIndex(items) {
605
- const focused = items.findIndex(item => item === document.activeElement);
635
+ const focused = items.findIndex((item) => item === document.activeElement);
606
636
  if (focused !== -1) return focused;
607
- return items.findIndex(item => item.getAttribute("tabindex") === "0");
637
+ return items.findIndex((item) => item.getAttribute("tabindex") === "0");
608
638
  }
609
639
 
610
640
  #applyStop(item) {
@@ -655,14 +685,14 @@ class RovingKeyboard {
655
685
 
656
686
  destroy() {
657
687
  this.#container.removeEventListener("keydown", this.#keydownEvent);
658
- this.#container.removeEventListener("click", this.#on_click);
688
+ this.#container.removeEventListener("click", this.#onClick);
659
689
  }
660
690
  }
661
691
 
662
- exports.MenuKeyboard = MenuKeyboard
663
- exports.ComboboxKeyboard = ComboboxKeyboard
664
- exports.RovingKeyboard = RovingKeyboard
665
- exports.A11Y_ACTIVE_CLASS = ACTIVE_CLASS
692
+ exports.MenuKeyboard = MenuKeyboard;
693
+ exports.ComboboxKeyboard = ComboboxKeyboard;
694
+ exports.RovingKeyboard = RovingKeyboard;
695
+ exports.A11Y_ACTIVE_CLASS = ACTIVE_CLASS;
666
696
 
667
697
  /**
668
698
  * Перенести фокус на следующий (или предыдущий) видимый фокусируемый элемент страницы.
@@ -670,7 +700,7 @@ exports.A11Y_ACTIVE_CLASS = ACTIVE_CLASS
670
700
  * браузер уведёт фокус в `body`, а не к следующему полю. `skip` — узел или поддерево,
671
701
  * которое в обходе не участвует (например, сам список).
672
702
  */
673
- function moveFocusAway(from, options = {backwards: false, skip: undefined}) {
703
+ function moveFocusAway(from, options = { backwards: false, skip: undefined }) {
674
704
  const nodes = [...document.querySelectorAll(FOCUSABLE_SELECTOR)]
675
705
  .filter((node) => node.disabled !== true)
676
706
  .filter((node) => isVisible(node))
@@ -684,4 +714,4 @@ function moveFocusAway(from, options = {backwards: false, skip: undefined}) {
684
714
  return true;
685
715
  }
686
716
 
687
- exports.moveFocusAway = moveFocusAway
717
+ exports.moveFocusAway = moveFocusAway;