chuijs 4.0.3 → 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 (258) hide show
  1. package/CHANGELOG.md +536 -0
  2. package/framework/appLayout/default/chui_app_layout.js +361 -303
  3. package/framework/appLayout/default/global_style.css +243 -89
  4. package/framework/appLayout/default/main_theme_style.css +188 -101
  5. package/framework/components/chui_accordion/accordion.js +17 -17
  6. package/framework/components/chui_accordion/styles.css +7 -7
  7. package/framework/components/chui_action_sheet/action_sheet.js +35 -32
  8. package/framework/components/chui_action_sheet/styles.css +10 -4
  9. package/framework/components/chui_actions_bar/actions_bar.js +338 -0
  10. package/framework/components/chui_actions_bar/styles.css +139 -0
  11. package/framework/components/chui_affix/affix.js +4 -4
  12. package/framework/components/chui_affix/styles.css +5 -0
  13. package/framework/components/chui_alert/alert.js +11 -5
  14. package/framework/components/chui_alert/styles.css +7 -0
  15. package/framework/components/chui_avatar/avatar.js +13 -13
  16. package/framework/components/chui_avatar/styles.css +1 -1
  17. package/framework/components/chui_avatar_group/avatar_group.js +4 -4
  18. package/framework/components/chui_avatar_group/styles.css +1 -1
  19. package/framework/components/chui_backtop/backtop.js +25 -2
  20. package/framework/components/chui_backtop/styles.css +21 -0
  21. package/framework/components/chui_badge/badge.js +15 -15
  22. package/framework/components/chui_badge/styles.css +6 -6
  23. package/framework/components/chui_banner/banner.js +222 -0
  24. package/framework/components/chui_banner/styles.css +170 -0
  25. package/framework/components/chui_breadcrumb/styles.css +1 -1
  26. package/framework/components/chui_button/button.js +24 -28
  27. package/framework/components/chui_button/styles.css +5 -5
  28. package/framework/components/chui_calendar/calendar.js +6 -6
  29. package/framework/components/chui_card/card.js +14 -14
  30. package/framework/components/chui_card_scroll/card_scroll.js +169 -0
  31. package/framework/components/chui_card_scroll/styles.css +86 -0
  32. package/framework/components/chui_chat/chat.js +73 -51
  33. package/framework/components/chui_chat/styles.css +18 -7
  34. package/framework/components/chui_clipboard_history/clipboard_history.js +25 -20
  35. package/framework/components/chui_clipboard_history/styles.css +10 -8
  36. package/framework/components/chui_code/code.js +8 -8
  37. package/framework/components/chui_code/styles.css +2 -2
  38. package/framework/components/chui_code_editor/code_editor.js +26 -26
  39. package/framework/components/chui_code_editor/styles.css +3 -3
  40. package/framework/components/chui_command_palette/command_palette.js +29 -29
  41. package/framework/components/chui_command_palette/styles.css +5 -5
  42. package/framework/components/chui_console/console.js +9 -9
  43. package/framework/components/chui_console/styles.css +5 -2
  44. package/framework/components/chui_content_block/content_block.js +2 -2
  45. package/framework/components/chui_context_menu/context_menu.js +162 -54
  46. package/framework/components/chui_context_menu/styles.css +82 -8
  47. package/framework/components/chui_custom_element/custom_element.js +11 -11
  48. package/framework/components/chui_data_grid/data_grid.js +268 -268
  49. package/framework/components/chui_data_grid/styles.css +14 -14
  50. package/framework/components/chui_descriptions/styles.css +1 -1
  51. package/framework/components/chui_details/details.js +12 -12
  52. package/framework/components/chui_details/styles.css +7 -7
  53. package/framework/components/chui_diff_viewer/diff_viewer.js +88 -88
  54. package/framework/components/chui_diff_viewer/styles.css +9 -9
  55. package/framework/components/chui_divider/divider.js +6 -6
  56. package/framework/components/chui_divider/styles.css +2 -2
  57. package/framework/components/chui_drawer/drawer.js +37 -14
  58. package/framework/components/chui_drawer/styles.css +18 -4
  59. package/framework/components/chui_drop_zone/drop_zone.js +6 -6
  60. package/framework/components/chui_drop_zone/styles.css +10 -6
  61. package/framework/components/chui_fieldset/fieldset.js +6 -6
  62. package/framework/components/chui_fieldset/styles.css +5 -5
  63. package/framework/components/chui_file_explorer/file_explorer.js +115 -115
  64. package/framework/components/chui_file_explorer/styles.css +6 -6
  65. package/framework/components/chui_form/form.js +11 -11
  66. package/framework/components/chui_gantt/gantt.js +41 -41
  67. package/framework/components/chui_gantt/styles.css +5 -5
  68. package/framework/components/chui_graphs/graphs.js +82 -46
  69. package/framework/components/chui_graphs/styles.css +26 -5
  70. package/framework/components/chui_hero/hero.js +63 -20
  71. package/framework/components/chui_hero/styles.css +176 -7
  72. package/framework/components/chui_html_block/html_block.js +5 -5
  73. package/framework/components/chui_html_block/styles.css +1 -1
  74. package/framework/components/chui_hx/styles.css +2 -2
  75. package/framework/components/chui_icons/icons.js +7 -7
  76. package/framework/components/chui_icons/styles.css +2 -1
  77. package/framework/components/chui_inputs/chui_check_box/styles.css +12 -3
  78. package/framework/components/chui_inputs/chui_chips/chips.js +92 -31
  79. package/framework/components/chui_inputs/chui_chips/styles.css +28 -5
  80. package/framework/components/chui_inputs/chui_color_picker/color_picker.js +20 -15
  81. package/framework/components/chui_inputs/chui_color_picker/styles.css +7 -7
  82. package/framework/components/chui_inputs/chui_combo_box/combo_box.js +58 -58
  83. package/framework/components/chui_inputs/chui_combo_box/styles.css +9 -9
  84. package/framework/components/chui_inputs/chui_date/date.js +93 -95
  85. package/framework/components/chui_inputs/chui_date/styles.css +8 -8
  86. package/framework/components/chui_inputs/chui_date_range/date_range.js +22 -22
  87. package/framework/components/chui_inputs/chui_date_range/styles.css +3 -3
  88. package/framework/components/chui_inputs/chui_datetime/datetime.js +12 -12
  89. package/framework/components/chui_inputs/chui_datetime/styles.css +3 -3
  90. package/framework/components/chui_inputs/chui_email/email.js +10 -10
  91. package/framework/components/chui_inputs/chui_email/styles.css +6 -6
  92. package/framework/components/chui_inputs/chui_file/file.js +8 -8
  93. package/framework/components/chui_inputs/chui_file/styles.css +12 -9
  94. package/framework/components/chui_inputs/chui_hotkey/hotkey.js +39 -39
  95. package/framework/components/chui_inputs/chui_hotkey/styles.css +6 -6
  96. package/framework/components/chui_inputs/chui_masked/masked.js +44 -44
  97. package/framework/components/chui_inputs/chui_masked/styles.css +5 -5
  98. package/framework/components/chui_inputs/chui_mention/mention.js +13 -13
  99. package/framework/components/chui_inputs/chui_mention/styles.css +14 -8
  100. package/framework/components/chui_inputs/chui_multi_combo_box/multi_combo_box.js +147 -137
  101. package/framework/components/chui_inputs/chui_multi_combo_box/styles.css +14 -8
  102. package/framework/components/chui_inputs/chui_number/number.js +42 -45
  103. package/framework/components/chui_inputs/chui_number/styles.css +6 -6
  104. package/framework/components/chui_inputs/chui_otp/otp.js +32 -32
  105. package/framework/components/chui_inputs/chui_otp/styles.css +5 -5
  106. package/framework/components/chui_inputs/chui_password/password.js +30 -36
  107. package/framework/components/chui_inputs/chui_password/styles.css +7 -7
  108. package/framework/components/chui_inputs/chui_radio_button/styles.css +2 -2
  109. package/framework/components/chui_inputs/chui_rating/rating.js +28 -28
  110. package/framework/components/chui_inputs/chui_rating/styles.css +3 -3
  111. package/framework/components/chui_inputs/chui_select_box/select_box.js +54 -54
  112. package/framework/components/chui_inputs/chui_select_box/styles.css +10 -10
  113. package/framework/components/chui_inputs/chui_slider/slider.js +14 -14
  114. package/framework/components/chui_inputs/chui_slider/styles.css +5 -4
  115. package/framework/components/chui_inputs/chui_text/styles.css +7 -7
  116. package/framework/components/chui_inputs/chui_text/text.js +13 -17
  117. package/framework/components/chui_inputs/chui_text_area/styles.css +8 -8
  118. package/framework/components/chui_inputs/chui_text_area/text_area.js +23 -23
  119. package/framework/components/chui_inputs/chui_time/styles.css +13 -17
  120. package/framework/components/chui_inputs/chui_time/time.js +35 -24
  121. package/framework/components/chui_inputs/chui_toggle/styles.css +10 -3
  122. package/framework/components/chui_inputs/chui_toggle/toggle.js +16 -16
  123. package/framework/components/chui_json_editor/json_editor.js +87 -87
  124. package/framework/components/chui_json_editor/styles.css +5 -5
  125. package/framework/components/chui_json_viewer/json_viewer.js +80 -80
  126. package/framework/components/chui_json_viewer/styles.css +6 -6
  127. package/framework/components/chui_kanban/kanban.js +27 -27
  128. package/framework/components/chui_kanban/styles.css +8 -4
  129. package/framework/components/chui_kbd/styles.css +1 -1
  130. package/framework/components/chui_label/label.js +17 -17
  131. package/framework/components/chui_label/styles.css +1 -1
  132. package/framework/components/chui_link/link.js +9 -9
  133. package/framework/components/chui_link/styles.css +11 -4
  134. package/framework/components/chui_list/list.js +11 -11
  135. package/framework/components/chui_list/styles.css +2 -2
  136. package/framework/components/chui_markdown_editor/markdown_editor.js +66 -66
  137. package/framework/components/chui_markdown_editor/styles.css +5 -5
  138. package/framework/components/chui_media/audio.js +240 -246
  139. package/framework/components/chui_media/audio_styles.css +41 -23
  140. package/framework/components/chui_media/image.js +49 -46
  141. package/framework/components/chui_media/image_compare.js +35 -35
  142. package/framework/components/chui_media/image_compare_styles.css +5 -5
  143. package/framework/components/chui_media/image_styles.css +1 -1
  144. package/framework/components/chui_media/video.js +148 -148
  145. package/framework/components/chui_media/video_styles.css +27 -11
  146. package/framework/components/chui_menu_bar/menu_bar.js +54 -54
  147. package/framework/components/chui_menu_bar/styles.css +10 -10
  148. package/framework/components/chui_message_bar/message_bar.js +551 -0
  149. package/framework/components/chui_message_bar/styles.css +248 -0
  150. package/framework/components/chui_modal/modal.js +37 -13
  151. package/framework/components/chui_notification/notification.js +76 -54
  152. package/framework/components/chui_notification/notification_download.js +26 -81
  153. package/framework/components/chui_notification/notification_download_card.js +115 -0
  154. package/framework/components/chui_notification/notification_download_progress.css +2 -2
  155. package/framework/components/chui_notification/notification_download_progress.js +70 -108
  156. package/framework/components/chui_notification/notification_update.js +31 -31
  157. package/framework/components/chui_notification/status_plate.css +3 -3
  158. package/framework/components/chui_notification/styles.css +6 -1
  159. package/framework/components/chui_notification/styles_download.css +1 -1
  160. package/framework/components/chui_notification/styles_update.css +2 -2
  161. package/framework/components/chui_org_chart/org_chart.js +29 -29
  162. package/framework/components/chui_org_chart/styles.css +2 -2
  163. package/framework/components/chui_pagination/pagination.js +3 -3
  164. package/framework/components/chui_pagination/styles.css +1 -1
  165. package/framework/components/chui_paragraph/styles.css +2 -2
  166. package/framework/components/chui_popover/popover.js +29 -23
  167. package/framework/components/chui_popover/styles.css +1 -1
  168. package/framework/components/chui_popups/popups.js +124 -124
  169. package/framework/components/chui_popups/styles.css +5 -5
  170. package/framework/components/chui_print_button/print_button.js +15 -10
  171. package/framework/components/chui_progress_bar/progress_bar.js +34 -12
  172. package/framework/components/chui_progress_bar/styles.css +4 -4
  173. package/framework/components/chui_progress_ring/progress_ring.js +15 -15
  174. package/framework/components/chui_progress_ring/styles.css +1 -1
  175. package/framework/components/chui_qrcode/qrcode.js +12 -12
  176. package/framework/components/chui_query_builder/query_builder.js +46 -46
  177. package/framework/components/chui_query_builder/styles.css +4 -4
  178. package/framework/components/chui_radio_group/styles.css +1 -1
  179. package/framework/components/chui_result/result.js +15 -15
  180. package/framework/components/chui_result/styles.css +3 -3
  181. package/framework/components/chui_scheduler/scheduler.js +74 -74
  182. package/framework/components/chui_scheduler/styles.css +5 -5
  183. package/framework/components/chui_screen_spinner/screen_spinner.js +167 -0
  184. package/framework/components/chui_screen_spinner/styles.css +49 -0
  185. package/framework/components/chui_segmented_control/segmented_control.js +63 -6
  186. package/framework/components/chui_segmented_control/styles.css +32 -6
  187. package/framework/components/chui_settings/settings.js +45 -46
  188. package/framework/components/chui_settings/styles.css +4 -4
  189. package/framework/components/chui_shortcut_help/shortcut_help.js +32 -34
  190. package/framework/components/chui_sidebar_nav/sidebar_nav.js +98 -29
  191. package/framework/components/chui_sidebar_nav/styles.css +9 -3
  192. package/framework/components/chui_slideshow/slideshow.js +85 -85
  193. package/framework/components/chui_slideshow/styles.css +6 -6
  194. package/framework/components/chui_spinner/spinner.js +10 -10
  195. package/framework/components/chui_split_button/split_button.js +30 -12
  196. package/framework/components/chui_split_button/styles.css +21 -5
  197. package/framework/components/chui_splitter/splitter.js +11 -11
  198. package/framework/components/chui_splitter/styles.css +2 -2
  199. package/framework/components/chui_statistic/statistic.js +47 -47
  200. package/framework/components/chui_status_bar/styles.css +2 -2
  201. package/framework/components/chui_stepper/stepper.js +202 -31
  202. package/framework/components/chui_stepper/styles.css +79 -14
  203. package/framework/components/chui_sticky_bar/sticky_bar.js +44 -13
  204. package/framework/components/chui_sticky_bar/styles.css +10 -8
  205. package/framework/components/chui_tabs/chui_tabs.js +74 -26
  206. package/framework/components/chui_tabs/styles.css +40 -12
  207. package/framework/components/chui_text_editor/styles.css +7 -7
  208. package/framework/components/chui_text_editor/text_editor.js +56 -56
  209. package/framework/components/chui_text_editor/text_editor_panel.js +173 -174
  210. package/framework/components/chui_theme_toggle/theme_toggle.js +21 -5
  211. package/framework/components/chui_timeline/styles.css +3 -1
  212. package/framework/components/chui_toast_queue/styles.css +11 -11
  213. package/framework/components/chui_toast_queue/toast_queue.js +30 -27
  214. package/framework/components/chui_toolbar/styles.css +2 -2
  215. package/framework/components/chui_tooltip/styles.css +2 -2
  216. package/framework/components/chui_tooltip/tooltip.js +3 -3
  217. package/framework/components/chui_tour/styles.css +8 -8
  218. package/framework/components/chui_tour/tour.js +72 -72
  219. package/framework/components/chui_transfer/styles.css +6 -6
  220. package/framework/components/chui_transfer/transfer.js +93 -106
  221. package/framework/components/chui_tree_table/styles.css +4 -4
  222. package/framework/components/chui_tree_table/tree_table.js +45 -45
  223. package/framework/components/chui_tree_view/styles.css +10 -8
  224. package/framework/components/chui_tree_view/tree_view.js +185 -183
  225. package/framework/components/chui_user_bar/styles.css +145 -0
  226. package/framework/components/chui_user_bar/user_bar.js +402 -0
  227. package/framework/components/chui_user_list_bar/styles.css +173 -0
  228. package/framework/components/chui_user_list_bar/user_list_bar.js +485 -0
  229. package/framework/components/chui_watermark/watermark.js +17 -17
  230. package/framework/components/chui_webview/webview.js +9 -9
  231. package/framework/components/chui_write_bar/styles.css +172 -0
  232. package/framework/components/chui_write_bar/write_bar.js +320 -0
  233. package/framework/main_window.js +1234 -0
  234. package/framework/modules/chui_a11y/chui_a11y.js +78 -79
  235. package/framework/modules/chui_animations/animations.js +77 -15
  236. package/framework/modules/chui_animations/motion.js +120 -0
  237. package/framework/modules/chui_animations/styles.css +36 -3
  238. package/framework/modules/chui_functions.js +31 -27
  239. package/framework/modules/chui_highlight/styles.css +13 -10
  240. package/framework/modules/chui_i18n/chui_i18n.js +3 -3
  241. package/framework/modules/chui_i18n/locales/feedback.js +62 -0
  242. package/framework/modules/chui_i18n/locales/navigation.js +4 -0
  243. package/framework/modules/chui_json/chui_json.js +2 -2
  244. package/framework/modules/chui_logger/chui_logger.js +23 -8
  245. package/framework/modules/chui_page/page.js +10 -10
  246. package/framework/modules/chui_palette/palette.js +61 -0
  247. package/framework/modules/chui_qr/chui_qr.js +23 -23
  248. package/framework/modules/chui_scrollbar/chui_scrollbar.js +45 -45
  249. package/framework/modules/chui_scrollbar/styles.css +3 -3
  250. package/framework/modules/chui_services/chui_services.js +8 -8
  251. package/framework/modules/chui_services/desktop.js +77 -71
  252. package/framework/modules/chui_sortable/chui_sortable.js +17 -17
  253. package/framework/modules/chui_validate/chui_validate.js +3 -3
  254. package/framework/tray_bar/chui_menu_items.js +2 -2
  255. package/index.d.ts +266 -34
  256. package/index.js +20 -1168
  257. package/package.json +6 -4
  258. package/framework/components/telegram_bot/chui_telegram_bot.js +0 -191
@@ -3,7 +3,7 @@ chui_kanban {
3
3
  display: block;
4
4
  width: -webkit-fill-available;
5
5
  box-sizing: border-box;
6
- margin: var(--margin);
6
+ margin: var(--block_margin);
7
7
  color: var(--text_color);
8
8
  font-size: var(--font_default_size);
9
9
  }
@@ -24,7 +24,7 @@ kanban_column {
24
24
  min-width: 0;
25
25
  background: var(--element_background);
26
26
  border: 1px solid var(--border_color);
27
- border-radius: var(--border_radius);
27
+ border-radius: var(--radius_sm);
28
28
  box-sizing: border-box;
29
29
  }
30
30
 
@@ -74,7 +74,7 @@ kanban_column.kanban_column_reject {
74
74
  }
75
75
 
76
76
  kanban_column.kanban_column_reject kanban_column_body {
77
- background: var(--badge_error_back);
77
+ background: var(--badge_error_background);
78
78
  }
79
79
 
80
80
  button.kanban_card {
@@ -84,7 +84,7 @@ button.kanban_card {
84
84
  padding: 8px 10px;
85
85
  border: 1px solid var(--border_color);
86
86
  border-inline-start: 3px solid var(--kanban_card_color, var(--blue_prime_background));
87
- border-radius: var(--border_radius);
87
+ border-radius: var(--radius_sm);
88
88
  background: var(--element_background_2);
89
89
  color: var(--text_color);
90
90
  font-family: inherit;
@@ -105,6 +105,10 @@ button.kanban_card:focus-visible {
105
105
  button.kanban_card.kanban_card_dragging {
106
106
  opacity: 0.5;
107
107
  cursor: grabbing;
108
+ /* Карточка чуть приподнята и наклонена: взятая в руку вещь, а не просто поблёкшая
109
+ строка. Тень — та же, что у поднятых слоёв */
110
+ transform: scale(1.02) rotate(1deg);
111
+ box-shadow: var(--box_shadow_drop);
108
112
  }
109
113
 
110
114
  kanban_card_title {
@@ -5,7 +5,7 @@ chui_kbd {
5
5
  gap: 4px;
6
6
  width: max-content;
7
7
  height: max-content;
8
- margin: var(--margin);
8
+ margin: var(--block_margin);
9
9
  font-size: var(--font_default_size);
10
10
  color: var(--text_color);
11
11
  }
@@ -1,7 +1,7 @@
1
1
  const { setStyles, htmlToMarkdown, markdownToHtml, optionOr } = require("../../modules/chui_functions");
2
2
 
3
3
  class Label {
4
- #chui_label = document.createElement(`chui_label`);
4
+ #chuiLabel = document.createElement(`chui_label`);
5
5
  constructor(
6
6
  options = {
7
7
  id: String(),
@@ -16,43 +16,43 @@ class Label {
16
16
  setStyles(__dirname + "/styles.css", "chUiJS_Label");
17
17
  // Стили текста лейбла: пустая заготовка опции равносильна отсутствующей
18
18
  const text = optionOr(options.text, undefined);
19
- const markdown_text = optionOr(options.markdownText, undefined);
20
- if (text !== undefined && markdown_text !== undefined) {
19
+ const markdownText = optionOr(options.markdownText, undefined);
20
+ if (text !== undefined && markdownText !== undefined) {
21
21
  throw new Error("Должна быть установлена одна опция text или markdownText");
22
22
  } else {
23
- if (text !== undefined) this.#chui_label.innerText = text;
24
- if (markdown_text !== undefined) this.#chui_label.innerHTML = markdownToHtml(markdown_text);
23
+ if (text !== undefined) this.#chuiLabel.innerText = text;
24
+ if (markdownText !== undefined) this.#chuiLabel.innerHTML = markdownToHtml(markdownText);
25
25
  }
26
26
  //
27
- if (options.id !== undefined) this.#chui_label.id = options.id;
28
- if (options.textAlign !== undefined) this.#chui_label.style.textAlign = options.textAlign;
29
- if (options.wordBreak !== undefined) this.#chui_label.style.wordBreak = options.wordBreak;
30
- if (options.width !== undefined) this.#chui_label.style.width = options.width;
31
- if (options.fontSize !== undefined) this.#chui_label.style.fontSize = options.fontSize;
27
+ if (options.id !== undefined) this.#chuiLabel.id = options.id;
28
+ if (options.textAlign !== undefined) this.#chuiLabel.style.textAlign = options.textAlign;
29
+ if (options.wordBreak !== undefined) this.#chuiLabel.style.wordBreak = options.wordBreak;
30
+ if (options.width !== undefined) this.#chuiLabel.style.width = options.width;
31
+ if (options.fontSize !== undefined) this.#chuiLabel.style.fontSize = options.fontSize;
32
32
  }
33
33
  // GET
34
34
  getId() {
35
- return this.#chui_label.id;
35
+ return this.#chuiLabel.id;
36
36
  }
37
37
  getText() {
38
- return this.#chui_label.innerText;
38
+ return this.#chuiLabel.innerText;
39
39
  }
40
40
  getMarkdownText() {
41
- return htmlToMarkdown(this.#chui_label.innerHTML);
41
+ return htmlToMarkdown(this.#chuiLabel.innerHTML);
42
42
  }
43
43
  // SET
44
44
  setId(id = String()) {
45
- this.#chui_label.id = id;
45
+ this.#chuiLabel.id = id;
46
46
  }
47
47
  setText(text = String()) {
48
- this.#chui_label.innerText = text;
48
+ this.#chuiLabel.innerText = text;
49
49
  }
50
50
  setMarkdownText(text = String()) {
51
- this.#chui_label.innerHTML = markdownToHtml(text);
51
+ this.#chuiLabel.innerHTML = markdownToHtml(text);
52
52
  }
53
53
  // RENDER
54
54
  set() {
55
- return this.#chui_label;
55
+ return this.#chuiLabel;
56
56
  }
57
57
  }
58
58
 
@@ -1,7 +1,7 @@
1
1
  chui_label {
2
2
  height: max-content;
3
3
  width: max-content;
4
- margin: var(--margin);
4
+ margin: var(--block_margin);
5
5
  font-size: var(--font_default_size);
6
6
  font-weight: 500;
7
7
  color: var(--text_color);
@@ -29,8 +29,8 @@ class Link {
29
29
  #icon = undefined;
30
30
  #id = undefined;
31
31
  #href = undefined;
32
- #click_event = undefined;
33
- #click_listeners = [];
32
+ #clickEvent = undefined;
33
+ #clickListeners = [];
34
34
  #disabled = false;
35
35
  #external = undefined;
36
36
 
@@ -54,14 +54,14 @@ class Link {
54
54
  this.#root.id = this.#id;
55
55
  this.#root.classList.add("chui_link");
56
56
  this.#external = options.external;
57
- this.#click_event = options.clickEvent;
57
+ this.#clickEvent = options.clickEvent;
58
58
  this.#root.addEventListener("click", this.#onClick);
59
59
  this.#root.innerText = options.text === undefined ? "" : options.text;
60
60
  if (options.title !== undefined) this.#root.setAttribute("title", options.title);
61
61
  if (options.width !== undefined) this.setWidth(options.width);
62
62
  if (options.href !== undefined) this.setHref(options.href);
63
63
  if (options.icon !== undefined) this.setIcon(options.icon);
64
- if (this.#href === undefined && this.#click_event !== undefined) this.#applyLinkRole();
64
+ if (this.#href === undefined && this.#clickEvent !== undefined) this.#applyLinkRole();
65
65
  if (options.disabled === true) this.setDisabled(true);
66
66
  if (options.clickListener !== undefined) this.addClickListener(options.clickListener);
67
67
  }
@@ -148,13 +148,13 @@ class Link {
148
148
 
149
149
  /** Свой обработчик клика; вызывается вместо открытия адреса */
150
150
  setClickEvent(listener = () => {}) {
151
- this.#click_event = listener;
151
+ this.#clickEvent = listener;
152
152
  if (this.#href === undefined) this.#applyLinkRole();
153
153
  return this;
154
154
  }
155
155
 
156
156
  addClickListener(listener = () => {}) {
157
- this.#click_listeners.push(listener);
157
+ this.#clickListeners.push(listener);
158
158
  return this;
159
159
  }
160
160
 
@@ -187,10 +187,10 @@ class Link {
187
187
  event.preventDefault();
188
188
  return;
189
189
  }
190
- for (const listener of [...this.#click_listeners]) listener(event);
191
- if (this.#click_event !== undefined) {
190
+ for (const listener of [...this.#clickListeners]) listener(event);
191
+ if (this.#clickEvent !== undefined) {
192
192
  event.preventDefault();
193
- this.#click_event(event);
193
+ this.#clickEvent(event);
194
194
  return;
195
195
  }
196
196
  if (!this.isExternal()) return;
@@ -3,17 +3,24 @@
3
3
  align-items: center;
4
4
  gap: 5px;
5
5
  width: max-content;
6
- margin: var(--margin);
6
+ margin: var(--block_margin);
7
7
  color: var(--link_color);
8
8
  font-size: var(--font_default_size);
9
- text-decoration: none;
9
+ /* Подчёркивание есть всегда, а видно становится на наведении: так строка не дёргает вёрстку
10
+ и не меняет высоту. Свой список перехода заменяет общее правило `*` целиком, поэтому
11
+ в нём перечислены все свойства ссылки: подчёркивание, цвет и притухание на нажатии */
12
+ text-decoration: underline transparent;
13
+ transition:
14
+ color var(--motion_fast) var(--motion_ease),
15
+ opacity var(--motion_fast) var(--motion_ease),
16
+ text-decoration-color var(--motion_fast) var(--motion_ease);
10
17
  cursor: pointer;
11
- border-radius: var(--border_radius);
18
+ border-radius: var(--radius_sm);
12
19
  outline: none;
13
20
  }
14
21
 
15
22
  .chui_link:hover {
16
- text-decoration: underline;
23
+ text-decoration-color: currentColor;
17
24
  }
18
25
 
19
26
  /* Нажатие: ссылка притухает на мгновение — заливка и белый текст ссылке неуместны */
@@ -33,7 +33,7 @@ class List {
33
33
  #rows = [];
34
34
  #selectable = false;
35
35
  #selected = -1;
36
- #on_select = undefined;
36
+ #onSelect = undefined;
37
37
  #listeners = [];
38
38
  #roving = undefined;
39
39
 
@@ -54,7 +54,7 @@ class List {
54
54
  this.#selectable = options.selectable === true;
55
55
  this.#root.setAttribute("role", this.#selectable ? "listbox" : "list");
56
56
  this.#root.setAttribute("aria-label", optionOr(options.label, I18n.t("common.list")));
57
- this.#on_select = options.onSelect;
57
+ this.#onSelect = options.onSelect;
58
58
  if (options.changeEvent !== undefined) this.addChangeListener(options.changeEvent);
59
59
  // Клавиатура списка выборов: одна остановка Tab на список
60
60
  if (this.#selectable) this.#roving = new RovingKeyboard(this.#root, { itemSelector: "chui_list_item" });
@@ -134,7 +134,7 @@ class List {
134
134
  #notify() {
135
135
  const item = this.#selected === -1 ? undefined : this.#items[this.#selected];
136
136
  for (const listener of [...this.#listeners]) listener(item, this.#selected, this);
137
- if (this.#on_select !== undefined) this.#on_select(item, this.#selected, this);
137
+ if (this.#onSelect !== undefined) this.#onSelect(item, this.#selected, this);
138
138
  }
139
139
 
140
140
  #render() {
@@ -159,9 +159,9 @@ class List {
159
159
 
160
160
  #applySelection() {
161
161
  this.#rows.forEach((row, index) => {
162
- const is_selected = this.#selectable && index === this.#selected;
163
- row.classList.toggle("list_item_active", is_selected);
164
- if (this.#selectable) row.setAttribute("aria-selected", is_selected ? "true" : "false");
162
+ const isSelected = this.#selectable && index === this.#selected;
163
+ row.classList.toggle("list_item_active", isSelected);
164
+ if (this.#selectable) row.setAttribute("aria-selected", isSelected ? "true" : "false");
165
165
  });
166
166
  }
167
167
 
@@ -185,7 +185,7 @@ class ListItem {
185
185
  #title = document.createElement("chui_list_item_title");
186
186
  #subtitle = document.createElement("chui_list_item_subtitle");
187
187
  #meta = document.createElement("chui_list_item_meta");
188
- #click_event = undefined;
188
+ #clickEvent = undefined;
189
189
  #disabled = false;
190
190
 
191
191
  constructor(
@@ -201,7 +201,7 @@ class ListItem {
201
201
  ) {
202
202
  ListItem.#counter += 1;
203
203
  this.#root.id = options.id === undefined ? `chui_list_item_${ListItem.#counter}` : options.id;
204
- this.#click_event = options.clickEvent;
204
+ this.#clickEvent = options.clickEvent;
205
205
  this.#content.appendChild(this.#title);
206
206
  this.#content.appendChild(this.#subtitle);
207
207
  this.#root.appendChild(this.#content);
@@ -282,7 +282,7 @@ class ListItem {
282
282
 
283
283
  /** Свой обработчик нажатия: строка получает настоящий `<button>` */
284
284
  setClickEvent(listener = undefined) {
285
- this.#click_event = listener;
285
+ this.#clickEvent = listener;
286
286
  this.#applyClickable();
287
287
  return this;
288
288
  }
@@ -294,7 +294,7 @@ class ListItem {
294
294
 
295
295
  // === ВНУТРЕННЕЕ ===
296
296
  #applyClickable() {
297
- if (this.#click_event === undefined) {
297
+ if (this.#clickEvent === undefined) {
298
298
  if (this.#button !== undefined) {
299
299
  this.#button.remove();
300
300
  this.#button = undefined;
@@ -314,7 +314,7 @@ class ListItem {
314
314
  this.#root.appendChild(this.#button);
315
315
  this.#button.addEventListener("click", () => {
316
316
  if (this.#disabled) return;
317
- this.#click_event();
317
+ this.#clickEvent();
318
318
  });
319
319
  this.setDisabled(this.#disabled);
320
320
  }
@@ -4,9 +4,9 @@ chui_list {
4
4
  flex-direction: column;
5
5
  box-sizing: border-box;
6
6
  width: -webkit-fill-available;
7
- margin: var(--margin);
7
+ margin: var(--block_margin);
8
8
  border: 1px solid var(--border_color);
9
- border-radius: var(--border_radius);
9
+ border-radius: var(--radius_sm);
10
10
  background: var(--element_background_2);
11
11
  overflow: hidden;
12
12
  color: var(--text_color);
@@ -80,20 +80,20 @@ class MarkdownEditor {
80
80
  #hint = document.createElement("markdown_editor_hint");
81
81
  #status = document.createElement("markdown_editor_status");
82
82
  #error = document.createElement("chui_error_message");
83
- #preview_button = undefined;
83
+ #previewButton = undefined;
84
84
  #actions = new Map();
85
85
  #id = undefined;
86
86
  #name = undefined;
87
- #title_text = undefined;
88
- #label_text = undefined;
89
- #preview_enabled = false;
90
- #preview_on = false;
91
- #max_length = undefined;
87
+ #titleText = undefined;
88
+ #labelText = undefined;
89
+ #previewEnabled = false;
90
+ #previewOn = false;
91
+ #maxLength = undefined;
92
92
  #width = undefined;
93
93
  #disabled = false;
94
- #read_only = false;
94
+ #readOnly = false;
95
95
  #listeners = [];
96
- #on_change = undefined;
96
+ #onChange = undefined;
97
97
 
98
98
  constructor(
99
99
  options = {
@@ -117,10 +117,10 @@ class MarkdownEditor {
117
117
  MarkdownEditor.#counter += 1;
118
118
  this.#id = options.id === undefined ? `chui_markdown_editor_${MarkdownEditor.#counter}` : options.id;
119
119
  this.#name = options.name;
120
- this.#label_text = options.label;
121
- this.#on_change = options.onChange;
122
- this.#preview_enabled = options.preview === true;
123
- this.#max_length = options.maxLength === undefined ? undefined : Number(options.maxLength);
120
+ this.#labelText = options.label;
121
+ this.#onChange = options.onChange;
122
+ this.#previewEnabled = options.preview === true;
123
+ this.#maxLength = options.maxLength === undefined ? undefined : Number(options.maxLength);
124
124
  this.#root.id = this.#id;
125
125
  this.#label.className = "markdown_editor_label";
126
126
  this.#toolbar.className = "markdown_editor_toolbar";
@@ -159,7 +159,7 @@ class MarkdownEditor {
159
159
  this.#root.appendChild(this.#status);
160
160
  if (options.width !== undefined) this.setWidth(options.width);
161
161
  this.setTitle(options.title);
162
- this.setLabel(this.#label_text === undefined ? I18n.t("editor.markdownText") : this.#label_text);
162
+ this.setLabel(this.#labelText === undefined ? I18n.t("editor.markdownText") : this.#labelText);
163
163
  if (options.hint !== undefined) this.setHint(options.hint);
164
164
  this.setRows(options.rows === undefined ? 8 : options.rows);
165
165
  this.setTextAreaValue(options.value === undefined ? "" : options.value);
@@ -182,12 +182,12 @@ class MarkdownEditor {
182
182
  }
183
183
 
184
184
  getTitle() {
185
- return this.#title_text;
185
+ return this.#titleText;
186
186
  }
187
187
 
188
188
  /** Доступное имя поля, заданное в `label` */
189
189
  getLabel() {
190
- return this.#label_text;
190
+ return this.#labelText;
191
191
  }
192
192
 
193
193
  /** Текст Markdown как есть */
@@ -201,11 +201,11 @@ class MarkdownEditor {
201
201
  }
202
202
 
203
203
  isPreview() {
204
- return this.#preview_on;
204
+ return this.#previewOn;
205
205
  }
206
206
 
207
207
  getMaxLength() {
208
- return this.#max_length;
208
+ return this.#maxLength;
209
209
  }
210
210
 
211
211
  /** Ширина поля (по умолчанию — общая ширина контрола `--control_width`) */
@@ -214,7 +214,7 @@ class MarkdownEditor {
214
214
  }
215
215
 
216
216
  isReadOnly() {
217
- return this.#read_only;
217
+ return this.#readOnly;
218
218
  }
219
219
 
220
220
  getDisabled() {
@@ -235,7 +235,7 @@ class MarkdownEditor {
235
235
  this.#hint.id = `${id}_hint`;
236
236
  // Подпись — настоящий <label>: её связь с полем не должна отставать от идентификаторов
237
237
  this.#label.setAttribute("for", this.#textarea.id);
238
- if (this.#preview_button !== undefined) this.#preview_button.setAttribute("aria-controls", this.#preview.id);
238
+ if (this.#previewButton !== undefined) this.#previewButton.setAttribute("aria-controls", this.#preview.id);
239
239
  this.#syncDescribedBy();
240
240
  return this;
241
241
  }
@@ -257,7 +257,7 @@ class MarkdownEditor {
257
257
 
258
258
  /** Подпись над полем; `undefined` её убирает (имя тогда даёт `label`) */
259
259
  setTitle(text = undefined) {
260
- this.#title_text = text;
260
+ this.#titleText = text;
261
261
  // `for` держим всегда: в разметке настоящий <label>, а подпись появляется и исчезает
262
262
  this.#label.setAttribute("for", this.#textarea.id);
263
263
  if (text === undefined || text === "") {
@@ -274,8 +274,8 @@ class MarkdownEditor {
274
274
 
275
275
  /** Имя поля, когда подписи в разметке нет */
276
276
  setLabel(text = undefined) {
277
- this.#label_text = text;
278
- if (this.#title_text === undefined || this.#title_text === "") {
277
+ this.#labelText = text;
278
+ if (this.#titleText === undefined || this.#titleText === "") {
279
279
  if (text === undefined) this.#textarea.removeAttribute("aria-label");
280
280
  else this.#textarea.setAttribute("aria-label", String(text));
281
281
  }
@@ -307,7 +307,7 @@ class MarkdownEditor {
307
307
  setValue(value = String(), silent = false) {
308
308
  const text = value === undefined || value === null ? "" : String(value);
309
309
  // В тихом режиме (так зовёт Form.setValues) слишком длинный текст не подставляем
310
- if (silent === true && this.#max_length !== undefined && text.length > this.#max_length) return this;
310
+ if (silent === true && this.#maxLength !== undefined && text.length > this.#maxLength) return this;
311
311
  this.setTextAreaValue(text);
312
312
  this.#syncCount();
313
313
  return this;
@@ -322,23 +322,23 @@ class MarkdownEditor {
322
322
 
323
323
  /** Предпросмотр: кнопка панели становится переключателем */
324
324
  setPreview(on = Boolean()) {
325
- if (!this.#preview_enabled) return this;
326
- this.#preview_on = on === true;
327
- this.#textarea.hidden = this.#preview_on;
328
- this.#preview.hidden = !this.#preview_on;
329
- if (this.#preview_on) this.#preview.innerHTML = this.getPreviewHtml();
330
- if (this.#preview_button !== undefined) {
331
- this.#preview_button.setAttribute("aria-pressed", this.#preview_on ? "true" : "false");
332
- this.#preview_button.setAttribute(
325
+ if (!this.#previewEnabled) return this;
326
+ this.#previewOn = on === true;
327
+ this.#textarea.hidden = this.#previewOn;
328
+ this.#preview.hidden = !this.#previewOn;
329
+ if (this.#previewOn) this.#preview.innerHTML = this.getPreviewHtml();
330
+ if (this.#previewButton !== undefined) {
331
+ this.#previewButton.setAttribute("aria-pressed", this.#previewOn ? "true" : "false");
332
+ this.#previewButton.setAttribute(
333
333
  "aria-label",
334
- this.#preview_on ? I18n.t("editor.showMarkup") : I18n.t("editor.showPreview")
334
+ this.#previewOn ? I18n.t("editor.showMarkup") : I18n.t("editor.showPreview")
335
335
  );
336
336
  }
337
337
  return this;
338
338
  }
339
339
 
340
340
  togglePreview() {
341
- return this.setPreview(!this.#preview_on);
341
+ return this.setPreview(!this.#previewOn);
342
342
  }
343
343
 
344
344
  /** Убирает или возвращает панель разметки (поле остаётся полем) */
@@ -357,10 +357,10 @@ class MarkdownEditor {
357
357
  return this.#eachLine(marker);
358
358
  }
359
359
 
360
- setReadOnly(read_only = Boolean()) {
361
- this.#read_only = read_only === true;
362
- this.#root.classList.toggle("markdown_editor_readonly", this.#read_only);
363
- this.#textarea.readOnly = this.#read_only;
360
+ setReadOnly(readOnly = Boolean()) {
361
+ this.#readOnly = readOnly === true;
362
+ this.#root.classList.toggle("markdown_editor_readonly", this.#readOnly);
363
+ this.#textarea.readOnly = this.#readOnly;
364
364
  this.#actionButtonState();
365
365
  return this;
366
366
  }
@@ -382,7 +382,7 @@ class MarkdownEditor {
382
382
  /** Фокус на текст; `Form` зовёт это при ошибке валидации */
383
383
  focus() {
384
384
  if (this.#disabled) return this;
385
- if (this.#preview_on) this.setPreview(false);
385
+ if (this.#previewOn) this.setPreview(false);
386
386
  this.#textarea.focus();
387
387
  return this;
388
388
  }
@@ -394,8 +394,8 @@ class MarkdownEditor {
394
394
 
395
395
  // === ВНУТРЕННЕЕ ===
396
396
  #accessibleName() {
397
- if (this.#title_text !== undefined && this.#title_text !== "") return this.#title_text;
398
- if (this.#label_text !== undefined && this.#label_text !== "") return this.#label_text;
397
+ if (this.#titleText !== undefined && this.#titleText !== "") return this.#titleText;
398
+ if (this.#labelText !== undefined && this.#labelText !== "") return this.#labelText;
399
399
  return I18n.t("editor.markdownText");
400
400
  }
401
401
 
@@ -403,8 +403,8 @@ class MarkdownEditor {
403
403
  // предпросмотр — не правка: его гасит только запрет самого поля (раньше setDisabled
404
404
  // включал кнопки обратно и затирал режим только для чтения)
405
405
  #actionButtonState() {
406
- for (const button of this.#actions.values()) button.disabled = this.#disabled || this.#read_only;
407
- if (this.#preview_button !== undefined) this.#preview_button.disabled = this.#disabled;
406
+ for (const button of this.#actions.values()) button.disabled = this.#disabled || this.#readOnly;
407
+ if (this.#previewButton !== undefined) this.#previewButton.disabled = this.#disabled;
408
408
  return this;
409
409
  }
410
410
 
@@ -428,27 +428,27 @@ class MarkdownEditor {
428
428
  this.#actions.set(action.id, button);
429
429
  this.#toolbar.appendChild(button);
430
430
  }
431
- if (!this.#preview_enabled) return;
431
+ if (!this.#previewEnabled) return;
432
432
  const divider = document.createElement("markdown_editor_divider");
433
433
  divider.setAttribute("aria-hidden", "true");
434
434
  this.#toolbar.appendChild(divider);
435
- this.#preview_button = document.createElement("button");
436
- this.#preview_button.type = "button";
437
- this.#preview_button.className = "markdown_editor_action markdown_editor_preview";
438
- this.#preview_button.setAttribute("aria-pressed", "false");
439
- this.#preview_button.setAttribute("aria-label", I18n.t("editor.showPreview"));
440
- this.#preview_button.setAttribute("aria-controls", this.#preview.id);
435
+ this.#previewButton = document.createElement("button");
436
+ this.#previewButton.type = "button";
437
+ this.#previewButton.className = "markdown_editor_action markdown_editor_preview";
438
+ this.#previewButton.setAttribute("aria-pressed", "false");
439
+ this.#previewButton.setAttribute("aria-label", I18n.t("editor.showPreview"));
440
+ this.#previewButton.setAttribute("aria-controls", this.#preview.id);
441
441
  const glyph = new Icon(Icons.ACTIONS.VISIBILITY, "18px").set();
442
442
  glyph.setAttribute("aria-hidden", "true");
443
- this.#preview_button.appendChild(glyph);
444
- this.#preview_button.addEventListener("click", () => this.togglePreview());
445
- this.#toolbar.appendChild(this.#preview_button);
443
+ this.#previewButton.appendChild(glyph);
444
+ this.#previewButton.addEventListener("click", () => this.togglePreview());
445
+ this.#toolbar.appendChild(this.#previewButton);
446
446
  }
447
447
 
448
448
  // Значение ставится программно: слушателей не дёргаем (как у других полей)
449
449
  setTextAreaValue(text = String()) {
450
450
  this.#textarea.value = text;
451
- if (this.#preview_on) this.#preview.innerHTML = this.getPreviewHtml();
451
+ if (this.#previewOn) this.#preview.innerHTML = this.getPreviewHtml();
452
452
  return this;
453
453
  }
454
454
 
@@ -461,11 +461,11 @@ class MarkdownEditor {
461
461
  }
462
462
 
463
463
  #syncCount() {
464
- const has_limit = this.#max_length !== undefined;
465
- this.#footer.hidden = !has_limit;
466
- if (!has_limit) return this;
467
- this.#count.innerText = `${this.getValue().length} / ${this.#max_length}`;
468
- this.#count.classList.toggle("markdown_editor_count_over", this.getValue().length > this.#max_length);
464
+ const hasLimit = this.#maxLength !== undefined;
465
+ this.#footer.hidden = !hasLimit;
466
+ if (!hasLimit) return this;
467
+ this.#count.innerText = `${this.getValue().length} / ${this.#maxLength}`;
468
+ this.#count.classList.toggle("markdown_editor_count_over", this.getValue().length > this.#maxLength);
469
469
  return this;
470
470
  }
471
471
 
@@ -476,11 +476,11 @@ class MarkdownEditor {
476
476
  #notify() {
477
477
  const value = this.getValue();
478
478
  for (const listener of [...this.#listeners]) listener(value, this);
479
- if (this.#on_change !== undefined) this.#on_change(value, this);
479
+ if (this.#onChange !== undefined) this.#onChange(value, this);
480
480
  }
481
481
 
482
482
  // Правка диапазона: вставка идёт командой, поэтому Ctrl+Z в поле её отменяет
483
- #replaceRange(start = Number(), end = Number(), text = String(), caret_start = Number(), caret_end = Number()) {
483
+ #replaceRange(start = Number(), end = Number(), text = String(), caretStart = Number(), caretEnd = Number()) {
484
484
  const textarea = this.#textarea;
485
485
  textarea.focus();
486
486
  textarea.setSelectionRange(start, end);
@@ -496,8 +496,8 @@ class MarkdownEditor {
496
496
  this.#syncCount();
497
497
  this.#notify();
498
498
  }
499
- if (this.#preview_on) this.#preview.innerHTML = this.getPreviewHtml();
500
- textarea.setSelectionRange(caret_start, caret_end);
499
+ if (this.#previewOn) this.#preview.innerHTML = this.getPreviewHtml();
500
+ textarea.setSelectionRange(caretStart, caretEnd);
501
501
  return this;
502
502
  }
503
503
 
@@ -534,7 +534,7 @@ class MarkdownEditor {
534
534
  }
535
535
 
536
536
  #apply(id = String()) {
537
- if (this.#disabled || this.#read_only) return this;
537
+ if (this.#disabled || this.#readOnly) return this;
538
538
  const action = ACTIONS.find((item) => item.id === id);
539
539
  const wrap = WRAPS[id];
540
540
  if (id === "link") this.#linkWrap();
@@ -567,14 +567,14 @@ class MarkdownEditor {
567
567
  }
568
568
 
569
569
  #onInput = () => {
570
- if (this.#disabled || this.#read_only) return;
570
+ if (this.#disabled || this.#readOnly) return;
571
571
  this.#syncCount();
572
- if (this.#preview_on) this.#preview.innerHTML = this.getPreviewHtml();
572
+ if (this.#previewOn) this.#preview.innerHTML = this.getPreviewHtml();
573
573
  this.#notify();
574
574
  };
575
575
 
576
576
  #onKeyDown = (event) => {
577
- if (this.#disabled || this.#read_only) return;
577
+ if (this.#disabled || this.#readOnly) return;
578
578
  if (event.ctrlKey !== true && event.metaKey !== true) return;
579
579
  const key = String(event.key).toLowerCase();
580
580
  if (key !== "b" && key !== "i" && key !== "k") return;