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
@@ -1,23 +1,23 @@
1
- const { Animation } = require('../../../modules/chui_animations/animations');
2
- const { dropdownPlacement } = require('../../../modules/chui_functions');
3
- const { Icon, Icons } = require('../../chui_icons/icons');
4
- const {ComboboxKeyboard} = require('../../../modules/chui_a11y/chui_a11y');
5
- const {I18n} = require('../../../modules/chui_i18n/chui_i18n');
1
+ const { Animation } = require("../../../modules/chui_animations/animations");
2
+ const { dropdownPlacement } = require("../../../modules/chui_functions");
3
+ const { Icon, Icons } = require("../../chui_icons/icons");
4
+ const { ComboboxKeyboard } = require("../../../modules/chui_a11y/chui_a11y");
5
+ const { I18n } = require("../../../modules/chui_i18n/chui_i18n");
6
6
 
7
7
  const OPTION_ROW_HEIGHT = 33;
8
8
 
9
9
  class MultiComboBox {
10
10
  #id = require("randomstring").generate();
11
11
  #id_cb = require("randomstring").generate();
12
- #MultiComboBox_main = document.createElement('chui_multicombobox');
13
- #MultiComboBox_second = document.createElement('multicombobox');
14
- #MultiComboBox_options = document.createElement('multicombobox_options');
15
- #label = document.createElement('label');
16
- #input = document.createElement('input');
17
- #button_open = document.createElement('multicombo_button_open');
18
- #button_open_disabled = document.createElement('multicombo_button_open');
19
- #dropdown = document.createElement('multicombobox_dropdown');
20
- #more = document.createElement('multicombobox_option_added_more');
12
+ #MultiComboBox_main = document.createElement("chui_multicombobox");
13
+ #MultiComboBox_second = document.createElement("multicombobox");
14
+ #MultiComboBox_options = document.createElement("multicombobox_options");
15
+ #label = document.createElement("label");
16
+ #input = document.createElement("input");
17
+ #button_open = document.createElement("multicombo_button_open");
18
+ #button_open_disabled = document.createElement("multicombo_button_open");
19
+ #dropdown = document.createElement("multicombobox_dropdown");
20
+ #more = document.createElement("multicombobox_option_added_more");
21
21
  #overflow_frame = undefined;
22
22
  #overflow_observer = undefined;
23
23
  #a11y = undefined;
@@ -26,73 +26,85 @@ class MultiComboBox {
26
26
  if (!this.#MultiComboBox_second.contains(event.target)) this.#closeDropdown();
27
27
  };
28
28
  #dropdown_height = "max-content";
29
- #value = []
30
- constructor(options = {
31
- name: String(),
32
- title: String(),
33
- placeholder: String(),
34
- width: String(),
35
- required: Boolean(),
36
- optionsLen: String(),
37
- }) {
38
- require('../../../modules/chui_functions').setStyles(__dirname + "/styles.css", 'chUiJS_MultiComboBox');
29
+ #value = [];
30
+ constructor(
31
+ options = {
32
+ name: String(),
33
+ title: String(),
34
+ placeholder: String(),
35
+ width: String(),
36
+ required: Boolean(),
37
+ optionsLen: String(),
38
+ }
39
+ ) {
40
+ require("../../../modules/chui_functions").setStyles(__dirname + "/styles.css", "chUiJS_MultiComboBox");
39
41
  if (options.placeholder !== undefined) this.#input.placeholder = options.placeholder;
40
42
  if (options.width !== undefined) this.#MultiComboBox_main.style.width = options.width;
41
43
  if (options.title !== undefined) {
42
- this.#label.classList.add('multicombobox_label')
44
+ this.#label.classList.add("multicombobox_label");
43
45
  this.#label.innerText = options.title;
44
- this.#label.setAttribute('for', this.#id_cb);
46
+ this.#label.setAttribute("for", this.#id_cb);
45
47
  this.#MultiComboBox_main.appendChild(this.#label);
46
48
  }
47
49
  if (options.optionsLen !== undefined) {
48
- this.#dropdown_height = (OPTION_ROW_HEIGHT * options.optionsLen) + "px";
50
+ this.#dropdown_height = OPTION_ROW_HEIGHT * options.optionsLen + "px";
49
51
  }
50
52
  this.#dropdown.style.height = this.#dropdown_height;
51
53
  if (options.name !== undefined) this.#input.name = options.name;
52
54
  if (options.required !== undefined) this.#input.required = options.required;
53
- this.#input.setAttribute('id', this.#id_cb);
54
- this.#input.classList.add('multicombobox_input');
55
- this.#input.type = 'text';
55
+ this.#input.setAttribute("id", this.#id_cb);
56
+ this.#input.classList.add("multicombobox_input");
57
+ this.#input.type = "text";
56
58
  // Рамку и подпись активного поля держит общее правило темы (`multicombobox:focus-within`
57
59
  // в global_style.css): индайновые состояние и цвет подписи перебивали тему
58
60
  // и расходились с остальными полями
59
- this.#button_open.innerHTML = new Icon(Icons.HARDWARE.KEYBOARD_ARROW_DOWN, undefined, "var(--blue_prime_background)").getHTML();
60
- this.#button_open_disabled.innerHTML = new Icon(Icons.HARDWARE.KEYBOARD_ARROW_DOWN, undefined, "var(--text_color_disabled)").getHTML();
61
+ this.#button_open.innerHTML = new Icon(
62
+ Icons.HARDWARE.KEYBOARD_ARROW_DOWN,
63
+ undefined,
64
+ "var(--blue_prime_background)"
65
+ ).getHTML();
66
+ this.#button_open_disabled.innerHTML = new Icon(
67
+ Icons.HARDWARE.KEYBOARD_ARROW_DOWN,
68
+ undefined,
69
+ "var(--text_color_disabled)"
70
+ ).getHTML();
61
71
  // Курсор выключенного поля даёт `.multicombobox_disabled`: `cursor` наследуется
62
- this.#dropdown.setAttribute('id', this.#id);
63
- this.#MultiComboBox_second.appendChild(this.#MultiComboBox_options)
64
- this.#MultiComboBox_options.appendChild(this.#input)
72
+ this.#dropdown.setAttribute("id", this.#id);
73
+ this.#MultiComboBox_second.appendChild(this.#MultiComboBox_options);
74
+ this.#MultiComboBox_options.appendChild(this.#input);
65
75
  // Счётчик выбранных значений, не поместившихся в строку: поле держит одну линию
66
76
  // (--control_height) и не растёт от выбора (`#syncOverflow`)
67
77
  this.#more.hidden = true;
68
78
  this.#more.setAttribute("role", "img");
69
- this.#MultiComboBox_options.appendChild(this.#more)
79
+ this.#MultiComboBox_options.appendChild(this.#more);
70
80
  // Ширину строки задаёт вёрстка вокруг: о смене размера сообщает наблюдатель
71
81
  if (typeof ResizeObserver === "function") {
72
82
  this.#overflow_observer = new ResizeObserver(() => this.#scheduleOverflow());
73
83
  this.#overflow_observer.observe(this.#MultiComboBox_options);
74
84
  }
75
- this.#MultiComboBox_second.appendChild(this.#button_open)
76
- this.#MultiComboBox_second.appendChild(this.#dropdown)
85
+ this.#MultiComboBox_second.appendChild(this.#button_open);
86
+ this.#MultiComboBox_second.appendChild(this.#dropdown);
77
87
  //LISTENERS
78
- this.#input.addEventListener('focus', () => {
79
- this.#button_open.style.transform = 'rotate(180deg)'
80
- this.#dropdown.style.height = this.#dropdown_height
81
- })
82
- this.#input.addEventListener('blur', () => {
83
- this.#button_open.style.transform = 'rotate(0deg)'
84
- this.#dropdown.style.height = this.#dropdown_height
85
- })
86
- this.#MultiComboBox_second.addEventListener('click', (event) => {
88
+ this.#input.addEventListener("focus", () => {
89
+ this.#button_open.style.transform = "rotate(180deg)";
90
+ this.#dropdown.style.height = this.#dropdown_height;
91
+ });
92
+ this.#input.addEventListener("blur", () => {
93
+ this.#button_open.style.transform = "rotate(0deg)";
94
+ this.#dropdown.style.height = this.#dropdown_height;
95
+ });
96
+ this.#MultiComboBox_second.addEventListener("click", (event) => {
87
97
  if (!this.#input.disabled) {
88
- if (event.target.closest('multicombobox_dropdown') === null &&
89
- event.target.closest('multicombobox_option_added_main') === null) {
90
- this.#input.focus()
91
- this.#openDropdown()
98
+ if (
99
+ event.target.closest("multicombobox_dropdown") === null &&
100
+ event.target.closest("multicombobox_option_added_main") === null
101
+ ) {
102
+ this.#input.focus();
103
+ this.#openDropdown();
92
104
  }
93
105
  }
94
106
  });
95
- this.#MultiComboBox_main.appendChild(this.#MultiComboBox_second)
107
+ this.#MultiComboBox_main.appendChild(this.#MultiComboBox_second);
96
108
  // Клавиатура и aria: фокус в поле, стрелки по опциям, Enter переключает чекбокс, Escape закрывает.
97
109
  // `selectionState` отделяет выбор от наведения: `aria-selected` читается с чекбокса.
98
110
  this.#a11y = new ComboboxKeyboard(this.#input, {
@@ -103,7 +115,7 @@ class MultiComboBox {
103
115
  return box !== null && box.checked === true;
104
116
  },
105
117
  onEscape: () => this.#closeDropdown(),
106
- onOpen: () => this.#openDropdown()
118
+ onOpen: () => this.#openDropdown(),
107
119
  });
108
120
  // Список допускает несколько выбранных пунктов
109
121
  this.#dropdown.setAttribute("aria-multiselectable", "true");
@@ -116,21 +128,21 @@ class MultiComboBox {
116
128
  this.#scheduleOverflow();
117
129
  this.#a11y.setExpanded(true);
118
130
  // Слушатель окна нужен только пока список открыт: закрытие по клику снаружи
119
- window.addEventListener('click', this.#window_click_event);
131
+ window.addEventListener("click", this.#window_click_event);
120
132
  }
121
133
  #closeDropdown() {
122
134
  new Animation(this.#dropdown).fadeOut();
123
135
  if (this.#a11y !== undefined) this.#a11y.setExpanded(false);
124
- window.removeEventListener('click', this.#window_click_event);
136
+ window.removeEventListener("click", this.#window_click_event);
125
137
  }
126
138
  /** Полное удаление: снять слушатели окна и клавиатурный слой */
127
139
  destroy() {
128
- window.removeEventListener('click', this.#window_click_event);
140
+ window.removeEventListener("click", this.#window_click_event);
129
141
  this.#a11y.destroy();
130
142
  this.#closeDropdown();
131
143
  }
132
144
  addValueChangeListener(listener = () => {}) {
133
- this.#MultiComboBox_main.addEventListener("chui_multi_combo_option_changed", listener)
145
+ this.#MultiComboBox_main.addEventListener("chui_multi_combo_option_changed", listener);
134
146
  }
135
147
  clearDropdown() {
136
148
  this.#dropdown.innerHTML = "";
@@ -138,182 +150,186 @@ class MultiComboBox {
138
150
  addOptionsWithSections(options = []) {
139
151
  for (let sect of options) {
140
152
  const section = document.createElement(`section`);
141
- const section_title = document.createElement("label")
142
- section.className = "multi_combobox_section"
143
- section_title.className = "multi_combobox_section_title"
153
+ const section_title = document.createElement("label");
154
+ section.className = "multi_combobox_section";
155
+ section_title.className = "multi_combobox_section_title";
144
156
  section_title.innerText = sect.title;
145
- section.appendChild(section_title)
157
+ section.appendChild(section_title);
146
158
 
147
159
  for (let opt of sect.options) {
148
160
  const id_name = require("randomstring").generate();
149
161
  const option = document.createElement(`label`);
150
- option.className = "multi_combobox_option"
151
- option.setAttribute("option_title", opt.title)
162
+ option.className = "multi_combobox_option";
163
+ option.setAttribute("option_title", opt.title);
152
164
  const checkbox_input_check = document.createElement("input_check");
153
- checkbox_input_check.className = "checkmark"
165
+ checkbox_input_check.className = "checkmark";
154
166
  const checkbox_input_label = document.createElement("input_text");
155
- checkbox_input_label.className = "option_input_label"
167
+ checkbox_input_label.className = "option_input_label";
156
168
  checkbox_input_label.innerText = opt.title;
157
169
  const checkbox_input = document.createElement("input");
158
- checkbox_input.className = "option_input"
159
- checkbox_input.type = "checkbox"
170
+ checkbox_input.className = "option_input";
171
+ checkbox_input.type = "checkbox";
160
172
  checkbox_input.id = id_name;
161
173
  checkbox_input.name = id_name;
162
174
  //
163
- option.appendChild(checkbox_input)
164
- option.appendChild(checkbox_input_check)
165
- option.appendChild(checkbox_input_label)
166
- section.appendChild(option)
175
+ option.appendChild(checkbox_input);
176
+ option.appendChild(checkbox_input_check);
177
+ option.appendChild(checkbox_input_label);
178
+ section.appendChild(option);
167
179
  //
168
180
  checkbox_input.addEventListener("change", (evt) => {
169
- this.#input.value = ""
181
+ this.#input.value = "";
170
182
  // Выбор пункта — то же, что `aria-selected` у опции (см. `selectionState`)
171
- option.setAttribute("aria-selected", evt.target.checked ? "true" : "false")
183
+ option.setAttribute("aria-selected", evt.target.checked ? "true" : "false");
172
184
  if (evt.target.checked) {
173
- const test_main = document.createElement("multicombobox_option_added_main")
185
+ const test_main = document.createElement("multicombobox_option_added_main");
174
186
  // Метка и чекбокс — два узла: id у каждого свой, иначе в документе два одинаковых id
175
- test_main.id = id_name + "_chip"
176
- const test_body = document.createElement("multicombobox_option_added_body")
187
+ test_main.id = id_name + "_chip";
188
+ const test_body = document.createElement("multicombobox_option_added_body");
177
189
  test_body.innerText = sect.title + ": " + opt.title;
178
190
  test_body.title = sect.title + ": " + opt.title;
179
- const test_remove = document.createElement("multicombobox_option_added_remove")
180
- test_remove.innerHTML = new Icon(Icons.NAVIGATION.CLOSE, "12px").getHTML()
181
- test_remove.addEventListener("click", () => checkbox_input.click())
182
- test_main.appendChild(test_body)
183
- test_main.appendChild(test_remove)
184
- this.#MultiComboBox_options.insertBefore(test_main, this.#input)
191
+ const test_remove = document.createElement("multicombobox_option_added_remove");
192
+ test_remove.innerHTML = new Icon(Icons.NAVIGATION.CLOSE, "12px").getHTML();
193
+ test_remove.addEventListener("click", () => checkbox_input.click());
194
+ test_main.appendChild(test_body);
195
+ test_main.appendChild(test_remove);
196
+ this.#MultiComboBox_options.insertBefore(test_main, this.#input);
185
197
  this.#value.push({
186
198
  id: id_name,
187
199
  section: sect.title,
188
- option: opt
189
- })
200
+ option: opt,
201
+ });
190
202
  // Новая метка могла не влезть в строку — пересчёт счётчика «+N»
191
203
  this.#scheduleOverflow();
192
204
  } else {
193
- this.#removeOptionById(id_name)
205
+ this.#removeOptionById(id_name);
194
206
  }
195
207
  //
196
208
  const eventAwesome = new CustomEvent("chui_multi_combo_option_changed", {
197
209
  detail: {
198
- values: this.#value
210
+ values: this.#value,
199
211
  },
200
212
  });
201
- this.#MultiComboBox_main.dispatchEvent(eventAwesome)
202
- })
213
+ this.#MultiComboBox_main.dispatchEvent(eventAwesome);
214
+ });
203
215
  }
204
216
  this.#dropdown.appendChild(section);
205
217
  }
206
- this.#input.removeEventListener('input', this.#filter_options_event);
207
- this.#input.addEventListener('input', this.#filter_sections_event);
218
+ this.#input.removeEventListener("input", this.#filter_options_event);
219
+ this.#input.addEventListener("input", this.#filter_sections_event);
208
220
  }
209
221
  addOptions(...options) {
210
222
  for (let opt of options) {
211
223
  // Свой id на каждый вариант: одинаковые подписи больше не дают дубликатов id в документе
212
224
  const id_name = require("randomstring").generate();
213
225
  const option = document.createElement(`label`);
214
- option.className = "multi_combobox_option"
215
- option.setAttribute("option_title", opt.title)
226
+ option.className = "multi_combobox_option";
227
+ option.setAttribute("option_title", opt.title);
216
228
  const checkbox_input_check = document.createElement("input_check");
217
- checkbox_input_check.className = "checkmark"
229
+ checkbox_input_check.className = "checkmark";
218
230
  const checkbox_input_label = document.createElement("input_text");
219
- checkbox_input_label.className = "option_input_label"
231
+ checkbox_input_label.className = "option_input_label";
220
232
  checkbox_input_label.innerText = opt.title;
221
233
  const checkbox_input = document.createElement("input");
222
- checkbox_input.className = "option_input"
223
- checkbox_input.type = "checkbox"
234
+ checkbox_input.className = "option_input";
235
+ checkbox_input.type = "checkbox";
224
236
  checkbox_input.id = id_name;
225
237
  checkbox_input.name = id_name;
226
238
  //
227
- option.appendChild(checkbox_input)
228
- option.appendChild(checkbox_input_check)
229
- option.appendChild(checkbox_input_label)
239
+ option.appendChild(checkbox_input);
240
+ option.appendChild(checkbox_input_check);
241
+ option.appendChild(checkbox_input_label);
230
242
  //
231
243
  checkbox_input.addEventListener("change", (evt) => {
232
- this.#input.value = ""
244
+ this.#input.value = "";
233
245
  // Выбор пункта — то же, что `aria-selected` у опции (см. `selectionState`)
234
- option.setAttribute("aria-selected", evt.target.checked ? "true" : "false")
235
- const test_main = document.createElement("multicombobox_option_added_main")
236
- test_main.id = id_name + "_chip"
237
- const test_body = document.createElement("multicombobox_option_added_body")
246
+ option.setAttribute("aria-selected", evt.target.checked ? "true" : "false");
247
+ const test_main = document.createElement("multicombobox_option_added_main");
248
+ test_main.id = id_name + "_chip";
249
+ const test_body = document.createElement("multicombobox_option_added_body");
238
250
  test_body.innerText = opt.title;
239
251
  test_body.title = opt.title;
240
- const test_remove = document.createElement("multicombobox_option_added_remove")
241
- test_remove.innerHTML = new Icon(Icons.NAVIGATION.CLOSE, "12px").getHTML()
242
- test_main.appendChild(test_body)
243
- test_main.appendChild(test_remove)
252
+ const test_remove = document.createElement("multicombobox_option_added_remove");
253
+ test_remove.innerHTML = new Icon(Icons.NAVIGATION.CLOSE, "12px").getHTML();
254
+ test_main.appendChild(test_body);
255
+ test_main.appendChild(test_remove);
244
256
  //
245
- test_remove.addEventListener("click", () => checkbox_input.click())
257
+ test_remove.addEventListener("click", () => checkbox_input.click());
246
258
  //
247
259
  if (evt.target.checked) {
248
- this.#MultiComboBox_options.insertBefore(test_main, this.#input)
249
- this.#value.push(opt)
260
+ this.#MultiComboBox_options.insertBefore(test_main, this.#input);
261
+ this.#value.push(opt);
250
262
  // Новая метка могла не влезть в строку — пересчёт счётчика «+N»
251
263
  this.#scheduleOverflow();
252
264
  } else {
253
265
  // Метка снимается по своему id, а значение — по самому описанию варианта
254
- this.#removeOptionById(id_name)
255
- const index = this.#value.indexOf(opt)
256
- if (index !== -1) this.#value.splice(index, 1)
266
+ this.#removeOptionById(id_name);
267
+ const index = this.#value.indexOf(opt);
268
+ if (index !== -1) this.#value.splice(index, 1);
257
269
  }
258
270
  const eventAwesome = new CustomEvent("chui_multi_combo_option_changed", {
259
271
  detail: {
260
- values: this.#value
272
+ values: this.#value,
261
273
  },
262
274
  });
263
- this.#MultiComboBox_main.dispatchEvent(eventAwesome)
264
- })
275
+ this.#MultiComboBox_main.dispatchEvent(eventAwesome);
276
+ });
265
277
  this.#dropdown.appendChild(option);
266
278
  }
267
- this.#input.removeEventListener('input', this.#filter_sections_event);
268
- this.#input.addEventListener('input', this.#filter_options_event);
279
+ this.#input.removeEventListener("input", this.#filter_sections_event);
280
+ this.#input.addEventListener("input", this.#filter_options_event);
269
281
  }
270
282
  #filter_sections_event = (event) => {
271
283
  let dropdown = this.#dropdown;
272
284
  for (let section of dropdown.childNodes) {
273
285
  for (let option of section.childNodes) {
274
- let attr = option.getAttribute("option_title")
286
+ let attr = option.getAttribute("option_title");
275
287
  if (attr) {
276
288
  if (!attr.toLowerCase().includes(event.target.value.toLowerCase())) {
277
- option.style.display = 'none'
278
- dropdown.style.height = 'max-content'
289
+ option.style.display = "none";
290
+ dropdown.style.height = "max-content";
279
291
  } else {
280
- option.style.display = 'flex'
281
- dropdown.style.height = this.#dropdown_height
292
+ option.style.display = "flex";
293
+ dropdown.style.height = this.#dropdown_height;
282
294
  }
283
295
  }
284
296
  }
285
297
  }
286
- }
298
+ };
287
299
  #filter_options_event = (event) => {
288
300
  let dropdown = this.#dropdown;
289
301
  let query = event.target.value.toLowerCase();
290
302
  for (let option of dropdown.childNodes) {
291
303
  if (typeof option.getAttribute !== "function") continue;
292
- let title = option.getAttribute('option_title');
304
+ let title = option.getAttribute("option_title");
293
305
  if (title === null) continue;
294
306
  if (!title.toLowerCase().includes(query)) {
295
- option.style.display = 'none'
296
- dropdown.style.height = 'max-content'
307
+ option.style.display = "none";
308
+ dropdown.style.height = "max-content";
297
309
  } else {
298
- option.style.display = 'flex'
299
- dropdown.style.height = this.#dropdown_height
310
+ option.style.display = "flex";
311
+ dropdown.style.height = this.#dropdown_height;
300
312
  }
301
313
  }
314
+ };
315
+ getName() {
316
+ return this.#input.name;
317
+ }
318
+ getValue() {
319
+ return this.#value;
302
320
  }
303
- getName() { return this.#input.name; }
304
- getValue() { return this.#value }
305
321
  setDisabled(boolean = Boolean()) {
306
- this.#input.disabled = boolean
322
+ this.#input.disabled = boolean;
307
323
  if (boolean) {
308
- this.#MultiComboBox_second.classList.add("multicombobox_disabled")
309
- this.#input.className = "multicombobox_input_disabled"
310
- this.#label.className = "multicombobox_label_disabled"
324
+ this.#MultiComboBox_second.classList.add("multicombobox_disabled");
325
+ this.#input.className = "multicombobox_input_disabled";
326
+ this.#label.className = "multicombobox_label_disabled";
311
327
  this.#button_open.remove();
312
328
  this.#MultiComboBox_second.appendChild(this.#button_open_disabled);
313
329
  } else {
314
- this.#MultiComboBox_second.classList.remove("multicombobox_disabled")
315
- this.#input.className = "multicombobox_input"
316
- this.#label.className = "multicombobox_label"
330
+ this.#MultiComboBox_second.classList.remove("multicombobox_disabled");
331
+ this.#input.className = "multicombobox_input";
332
+ this.#label.className = "multicombobox_label";
317
333
  this.#button_open_disabled.remove();
318
334
  this.#MultiComboBox_second.appendChild(this.#button_open);
319
335
  }
@@ -322,25 +338,25 @@ class MultiComboBox {
322
338
  // У метки свой id (id чекбокса + «_chip»): сам чекбокс из разметки не убирается
323
339
  const chip_id = id + "_chip";
324
340
  for (let node of [...this.#MultiComboBox_options.childNodes]) {
325
- if (node.id === chip_id) node.remove()
341
+ if (node.id === chip_id) node.remove();
326
342
  }
327
- const index = this.#value.findIndex((item) => item.id === id)
328
- if (index !== -1) this.#value.splice(index, 1)
343
+ const index = this.#value.findIndex((item) => item.id === id);
344
+ if (index !== -1) this.#value.splice(index, 1);
329
345
  // Место в строке освободилось: прежде скрытые значения могут вернуться
330
346
  this.#scheduleOverflow();
331
347
  }
332
348
  clear() {
333
- this.#input.value = ""
334
- this.#value = []
349
+ this.#input.value = "";
350
+ this.#value = [];
335
351
  for (let node of [...this.#MultiComboBox_options.childNodes]) {
336
- if (node !== this.#input && node !== this.#more) node.remove()
352
+ if (node !== this.#input && node !== this.#more) node.remove();
337
353
  }
338
354
  for (let checkbox of this.#dropdown.querySelectorAll('input[type="checkbox"]')) {
339
355
  checkbox.checked = false;
340
356
  }
341
357
  // Отметка выбора снимается вместе с чекбоксами: прежде `aria-selected` оставался
342
358
  // «true» и список после сброса формы показывал прошлый выбор
343
- for (let option of this.#dropdown.querySelectorAll('.multi_combobox_option')) {
359
+ for (let option of this.#dropdown.querySelectorAll(".multi_combobox_option")) {
344
360
  option.setAttribute("aria-selected", "false");
345
361
  }
346
362
  this.#scheduleOverflow();
@@ -349,11 +365,11 @@ class MultiComboBox {
349
365
  const placement = dropdownPlacement(this.#dropdown, this.#MultiComboBox_second);
350
366
  // Зазор до поля держит CSS (`top: calc(100% + 4px)`), как у остальных списков:
351
367
  // прежде отступ задавался числом в пикселях под высоту прежнего поля 35 px
352
- this.#dropdown.style.top = placement.up ? 'auto' : '';
353
- this.#dropdown.style.bottom = placement.up ? 'calc(100% + 4px)' : '';
368
+ this.#dropdown.style.top = placement.up ? "auto" : "";
369
+ this.#dropdown.style.bottom = placement.up ? "calc(100% + 4px)" : "";
354
370
  // Слой не вылезает за видимую часть контейнера: лишнее уходит в прокрутку списка
355
371
  if (placement.maxHeight > 0) this.#dropdown.style.maxHeight = `${placement.maxHeight}px`;
356
- else this.#dropdown.style.removeProperty('max-height');
372
+ else this.#dropdown.style.removeProperty("max-height");
357
373
  }
358
374
 
359
375
  /**
@@ -378,7 +394,7 @@ class MultiComboBox {
378
394
  // Не помещается: ищем, сколько значений показать числом, чтобы строка сошлась
379
395
  for (let hidden = 1; hidden <= chips.length; hidden += 1) {
380
396
  this.#more.innerText = `+${hidden}`;
381
- this.#more.setAttribute("aria-label", I18n.t("forms.multiComboMore", {count: hidden}));
397
+ this.#more.setAttribute("aria-label", I18n.t("forms.multiComboMore", { count: hidden }));
382
398
  this.#more.hidden = false;
383
399
  const counter = this.#more.getBoundingClientRect().width + gap;
384
400
  if (total(chips.length - hidden) + counter + reserve <= available) {
@@ -398,13 +414,17 @@ class MultiComboBox {
398
414
  this.#syncOverflow();
399
415
  });
400
416
  }
401
- set() { return this.#MultiComboBox_main; }
417
+ set() {
418
+ return this.#MultiComboBox_main;
419
+ }
402
420
  }
403
421
 
404
422
  function setOptionDisplay(element) {
405
423
  // Скрытая фильтром секция возвращается снятием инлайнового `display`:
406
424
  // базовый вид строки (флекс) задаёт CSS
407
- for (let option of element.childNodes) { option.style.removeProperty("display"); }
425
+ for (let option of element.childNodes) {
426
+ option.style.removeProperty("display");
427
+ }
408
428
  }
409
429
 
410
- exports.MultiComboBox = MultiComboBox
430
+ exports.MultiComboBox = MultiComboBox;
@@ -10,7 +10,7 @@ chui_multicombobox {
10
10
  flex-direction: column;
11
11
  height: max-content;
12
12
  margin: var(--margin);
13
- width: var(--control_width)
13
+ width: var(--control_width);
14
14
  }
15
15
 
16
16
  multicombobox {
@@ -48,7 +48,8 @@ multicombobox_options {
48
48
  flex: 1 1 40px;
49
49
  min-width: 40px;
50
50
  margin: 0;
51
- padding-block: var(--control_padding) var(--control_padding); padding-inline: 6px 0;
51
+ padding-block: var(--control_padding) var(--control_padding);
52
+ padding-inline: 6px 0;
52
53
  background: transparent;
53
54
  color: var(--text_color);
54
55
  border: none;
@@ -90,8 +91,8 @@ multicombobox_dropdown {
90
91
  /* Только нижний отступ: боковой сдвигал подпись вправо от коробки поля */
91
92
  margin: 0 0 var(--margin);
92
93
  font-size: var(--font_labels_size);
93
- font-weight:500;
94
- color: var(--text_color)
94
+ font-weight: 500;
95
+ color: var(--text_color);
95
96
  }
96
97
 
97
98
  multicombo_button_open {
@@ -158,7 +159,8 @@ multicombo_button_open {
158
159
  flex: 1 1 40px;
159
160
  min-width: 40px;
160
161
  margin: 0;
161
- padding-block: var(--control_padding) var(--control_padding); padding-inline: 10px 0;
162
+ padding-block: var(--control_padding) var(--control_padding);
163
+ padding-inline: 10px 0;
162
164
  border: none;
163
165
  box-shadow: none;
164
166
  font-size: var(--font_default_size);
@@ -170,8 +172,8 @@ multicombo_button_open {
170
172
  width: max-content;
171
173
  margin: 0 0 var(--margin);
172
174
  font-size: var(--font_labels_size);
173
- font-weight:500;
174
- color: var(--text_color_disabled)
175
+ font-weight: 500;
176
+ color: var(--text_color_disabled);
175
177
  }
176
178
 
177
179
  multicombobox_option_added_main {