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
@@ -0,0 +1,139 @@
1
+ /* ── ActionsBar — панель действий ───────────────────────────────
2
+ Что можно сделать с тем, о чём сейчас речь: подпись и ряд кнопок со значками.
3
+ Панель не полагает, о чём действия: в переписке она встаёт под шапкой разговора,
4
+ в карточке — над содержимым, и в обоих случаях разделяется волосяной линией снизу. */
5
+
6
+ chui_actions_bar {
7
+ display: flex;
8
+ flex-direction: column;
9
+ gap: var(--control_padding_sm);
10
+ box-sizing: border-box;
11
+ width: -webkit-fill-available;
12
+ padding: var(--control_padding) var(--block_padding);
13
+ background: var(--element_background_2);
14
+ border-bottom: 1px solid var(--border_color);
15
+ font-size: var(--font_labels_size);
16
+ color: var(--text_color);
17
+ }
18
+
19
+ actions_bar_title {
20
+ display: block;
21
+ font-weight: 500;
22
+ color: var(--text_color_disabled);
23
+ }
24
+
25
+ actions_bar_title[hidden] {
26
+ display: none;
27
+ }
28
+
29
+ /* Полоса действий внутри панели своей кромки не рисует: панель и полоса — одна поверхность,
30
+ и вложенная ступень поверхности здесь была бы лишней. Кнопки переносятся по строкам:
31
+ в узкой колонке длинный ряд не ломает раскладку */
32
+ chui_actions_bar chui_toolbar {
33
+ display: flex;
34
+ flex-direction: row;
35
+ flex-wrap: wrap;
36
+ gap: 4px;
37
+ padding: 0;
38
+ background: transparent;
39
+ border: none;
40
+ }
41
+
42
+ /* Столбец — вид меню: действия идут друг под другом во всю ширину, как пункты списка */
43
+ chui_actions_bar[data-orientation="vertical"] chui_toolbar {
44
+ flex-direction: column;
45
+ flex-wrap: nowrap;
46
+ gap: 2px;
47
+ }
48
+
49
+ /* Кнопка действия: значок и подпись, одна мера с остальными контролами семьи */
50
+ .actions_bar_button {
51
+ display: flex;
52
+ flex-direction: row;
53
+ align-items: center;
54
+ gap: 6px;
55
+ box-sizing: border-box;
56
+ min-height: var(--control_height);
57
+ padding: var(--control_padding_sm) 10px;
58
+ border: none;
59
+ border-radius: var(--radius_sm);
60
+ background: transparent;
61
+ color: var(--text_color);
62
+ font-family: inherit;
63
+ font-size: var(--font_labels_size);
64
+ cursor: pointer;
65
+ }
66
+
67
+ .actions_bar_button:hover {
68
+ background: var(--element_background_hover);
69
+ }
70
+
71
+ /* Нажатие — заливка контрола, как у кнопок панели ввода */
72
+ .actions_bar_button:active:not(:disabled) {
73
+ background: var(--element_background);
74
+ }
75
+
76
+ /* Включённый переключатель: «закреплено», «без звука» — состояние видно подложкой */
77
+ .actions_bar_button[data-active="true"] {
78
+ background: var(--blue_prime_background_tint);
79
+ color: var(--blue_prime_background);
80
+ }
81
+
82
+ .actions_bar_button[data-danger="true"] {
83
+ color: var(--red_prime_background);
84
+ }
85
+
86
+ /* Пункт меню: подпись слева, счётчик у правого края */
87
+ chui_actions_bar[data-orientation="vertical"] .actions_bar_button {
88
+ width: -webkit-fill-available;
89
+ justify-content: flex-start;
90
+ text-align: start;
91
+ }
92
+
93
+ chui_actions_bar[data-orientation="vertical"] .actions_bar_button_text {
94
+ flex: 1 1 auto;
95
+ overflow: hidden;
96
+ text-overflow: ellipsis;
97
+ }
98
+
99
+ .actions_bar_button:disabled {
100
+ cursor: not-allowed;
101
+ background: transparent;
102
+ color: var(--text_color_disabled);
103
+ }
104
+
105
+ .actions_bar_button_icon {
106
+ display: flex;
107
+ align-items: center;
108
+ }
109
+
110
+ /* Значка нет — узел не занимает зазор строки */
111
+ .actions_bar_button_icon:empty {
112
+ display: none;
113
+ }
114
+
115
+ .actions_bar_button chui_icon {
116
+ color: inherit;
117
+ }
118
+
119
+ .actions_bar_button_text {
120
+ white-space: nowrap;
121
+ }
122
+
123
+ /* Счётчик действия: число показывает плашка, скринридеру оно попадает в имя */
124
+ actions_bar_badge {
125
+ box-sizing: border-box;
126
+ min-width: 16px;
127
+ padding-inline: 4px;
128
+ border-radius: var(--radius_pill);
129
+ background: var(--red_prime_background);
130
+ color: var(--text_color_hover);
131
+ font-size: 10px;
132
+ font-weight: 600;
133
+ line-height: 16px;
134
+ text-align: center;
135
+ }
136
+
137
+ actions_bar_badge[hidden] {
138
+ display: none;
139
+ }
@@ -42,7 +42,7 @@ class Affix {
42
42
  #observer = undefined;
43
43
  #pending = undefined;
44
44
  #destroyed = false;
45
- #on_change = undefined;
45
+ #onChange = undefined;
46
46
 
47
47
  constructor(
48
48
  options = {
@@ -63,7 +63,7 @@ class Affix {
63
63
  this.#root.appendChild(this.#body);
64
64
  this.#root.appendChild(this.#content);
65
65
  this.#target = options.target;
66
- this.#on_change = options.onChange;
66
+ this.#onChange = options.onChange;
67
67
  this.setOffset(options.offset === undefined ? 0 : options.offset);
68
68
  this.#observe();
69
69
  }
@@ -123,7 +123,7 @@ class Affix {
123
123
  }
124
124
 
125
125
  setOnChange(listener = undefined) {
126
- this.#on_change = listener;
126
+ this.#onChange = listener;
127
127
  return this;
128
128
  }
129
129
 
@@ -228,7 +228,7 @@ class Affix {
228
228
  this.#fixed = fixed;
229
229
  this.#root.dataset.fixed = fixed ? "true" : "false";
230
230
  this.#root.classList.toggle("affix_fixed", fixed);
231
- if (typeof this.#on_change === "function") this.#on_change(fixed, this);
231
+ if (typeof this.#onChange === "function") this.#onChange(fixed, this);
232
232
  }
233
233
  }
234
234
 
@@ -23,6 +23,11 @@ affix_body {
23
23
  inset-block-start: var(--affix_offset);
24
24
  z-index: 5;
25
25
  box-sizing: border-box;
26
+ /* Закрепление включает радиус и тень сразу: если тень гаснет плавно, а радиус щёлкает,
27
+ переход читается рваным. Свой список потому и перечисляет оба свойства */
28
+ transition:
29
+ border-radius var(--motion_fast) var(--motion_ease),
30
+ box-shadow var(--motion_fast) var(--motion_ease);
26
31
  }
27
32
 
28
33
  affix_content {
@@ -48,7 +48,7 @@ class Alert {
48
48
  #id = undefined;
49
49
  #style = Alert.STYLE.INFO;
50
50
  #dismissed = false;
51
- #custom_icon = false;
51
+ #customIcon = false;
52
52
 
53
53
  constructor(
54
54
  options = {
@@ -127,7 +127,7 @@ class Alert {
127
127
  this.#root.setAttribute("aria-live", assertive ? "assertive" : "polite");
128
128
  // Цвет и глиф плашки выбирает общий помощник семьи — по ключу стиля (`alert_error` → `error`).
129
129
  // Своя иконка (`setIcon`) важнее статусного глифа и остаётся собой
130
- if (this.#custom_icon === false)
130
+ if (this.#customIcon === false)
131
131
  setStatusPlate(this.#icon, typeof style === "string" ? style.replace("alert_", "") : undefined);
132
132
  return this;
133
133
  }
@@ -135,7 +135,7 @@ class Alert {
135
135
  /** Своя иконка вместо значка состояния (экземпляр `Icon` или готовый узел); цвет статуса остаётся */
136
136
  setIcon(icon = undefined) {
137
137
  if (icon === undefined || icon === null) return this;
138
- this.#custom_icon = true;
138
+ this.#customIcon = true;
139
139
  this.#icon.innerHTML = "";
140
140
  this.#icon.appendChild(icon instanceof Element ? icon : icon.set());
141
141
  return this;
@@ -233,11 +233,17 @@ class Alert {
233
233
  return this;
234
234
  }
235
235
 
236
- /** Убрать сообщение из документа */
236
+ /** Убрать сообщение из документа: уход идёт движением, узел убирается по концу кадра */
237
237
  dismiss() {
238
238
  if (this.#dismissed) return this;
239
239
  this.#dismissed = true;
240
- this.#root.remove();
240
+ this.#root.classList.add("alert_leaving");
241
+ const remove = (event) => {
242
+ if (event.target !== this.#root) return;
243
+ this.#root.removeEventListener("animationend", remove);
244
+ this.#root.remove();
245
+ };
246
+ this.#root.addEventListener("animationend", remove);
241
247
  return this;
242
248
  }
243
249
 
@@ -18,6 +18,13 @@ chui_alert {
18
18
  color: var(--text_color);
19
19
  font-size: var(--font_default_size);
20
20
  text-align: start;
21
+ /* Появление: сообщение встаёт на место — общий кадр из global_style.css */
22
+ animation: chui_appear_up var(--motion_base) var(--motion_ease);
23
+ }
24
+
25
+ /* Уход: сообщение гаснет и сходит вверх, узел убирается по концу кадра */
26
+ .alert_leaving {
27
+ animation: chui_leave_up var(--motion_fast) var(--motion_ease) forwards;
21
28
  }
22
29
 
23
30
  alert_content {
@@ -48,8 +48,8 @@ class Avatar {
48
48
 
49
49
  #root = document.createElement("chui_avatar");
50
50
  #image = document.createElement("img");
51
- #initials_node = document.createElement("avatar_initials");
52
- #status_node = document.createElement("avatar_status");
51
+ #initialsNode = document.createElement("avatar_initials");
52
+ #statusNode = document.createElement("avatar_status");
53
53
  #id = undefined;
54
54
  #name = undefined;
55
55
  #initials = undefined;
@@ -57,7 +57,7 @@ class Avatar {
57
57
  #status = undefined;
58
58
  #shape = Avatar.SHAPE.CIRCLE;
59
59
  #decorative = false;
60
- #click_listeners = [];
60
+ #clickListeners = [];
61
61
 
62
62
  constructor(
63
63
  options = {
@@ -84,9 +84,9 @@ class Avatar {
84
84
  this.#image.setAttribute("alt", "");
85
85
  this.#image.setAttribute("aria-hidden", "true");
86
86
  this.#root.appendChild(this.#image);
87
- this.#root.appendChild(this.#initials_node);
88
- this.#root.appendChild(this.#status_node);
89
- this.#status_node.setAttribute("aria-hidden", "true");
87
+ this.#root.appendChild(this.#initialsNode);
88
+ this.#root.appendChild(this.#statusNode);
89
+ this.#statusNode.setAttribute("aria-hidden", "true");
90
90
  this.setSize(options.size === undefined ? Avatar.SIZE.DEFAULT : options.size);
91
91
  this.setShape(options.shape === undefined ? Avatar.SHAPE.CIRCLE : options.shape);
92
92
  this.#renderInitials();
@@ -106,7 +106,7 @@ class Avatar {
106
106
  }
107
107
 
108
108
  getInitials() {
109
- return this.#initials_node.innerText;
109
+ return this.#initialsNode.innerText;
110
110
  }
111
111
 
112
112
  getImageSource() {
@@ -180,9 +180,9 @@ class Avatar {
180
180
  /** Значок состояния; `undefined` убирает его и слово из доступного имени */
181
181
  setStatus(status = undefined) {
182
182
  this.#status = status;
183
- this.#status_node.hidden = status === undefined;
184
- if (status !== undefined) this.#status_node.dataset.status = status;
185
- else this.#status_node.removeAttribute("data-status");
183
+ this.#statusNode.hidden = status === undefined;
184
+ if (status !== undefined) this.#statusNode.dataset.status = status;
185
+ else this.#statusNode.removeAttribute("data-status");
186
186
  this.#syncAria();
187
187
  return this;
188
188
  }
@@ -202,7 +202,7 @@ class Avatar {
202
202
  }
203
203
 
204
204
  addClickListener(listener = () => {}) {
205
- this.#click_listeners.push(listener);
205
+ this.#clickListeners.push(listener);
206
206
  return this;
207
207
  }
208
208
 
@@ -244,7 +244,7 @@ class Avatar {
244
244
  }
245
245
 
246
246
  #renderInitials() {
247
- this.#initials_node.innerText = this.#deriveInitials();
247
+ this.#initialsNode.innerText = this.#deriveInitials();
248
248
  this.#syncAria();
249
249
  }
250
250
 
@@ -264,7 +264,7 @@ class Avatar {
264
264
  }
265
265
 
266
266
  #onClick = (event) => {
267
- for (const listener of [...this.#click_listeners]) listener(event);
267
+ for (const listener of [...this.#clickListeners]) listener(event);
268
268
  };
269
269
  }
270
270
 
@@ -20,7 +20,7 @@ chui_avatar[data-shape="circle"] {
20
20
  }
21
21
 
22
22
  chui_avatar[data-shape="square"] {
23
- border-radius: var(--border_radius);
23
+ border-radius: var(--radius_sm);
24
24
  }
25
25
 
26
26
  chui_avatar img {
@@ -45,7 +45,7 @@ class AvatarGroup {
45
45
  #size = Avatar.SIZE.DEFAULT;
46
46
  #shape = undefined;
47
47
  #extra = undefined;
48
- #extra_listener = undefined;
48
+ #extraListener = undefined;
49
49
  #label = undefined;
50
50
 
51
51
  constructor(
@@ -64,7 +64,7 @@ class AvatarGroup {
64
64
  this.#id = optionOr(options.id, `chui_avatar_group_${AvatarGroup.#counter}`);
65
65
  this.#root.id = this.#id;
66
66
  this.#root.setAttribute("role", "group");
67
- this.#extra_listener = options.extraClickListener;
67
+ this.#extraListener = options.extraClickListener;
68
68
  this.setSize(optionOr(options.size, Avatar.SIZE.DEFAULT));
69
69
  if (options.shape !== undefined) this.#shape = options.shape;
70
70
  if (options.max !== undefined) this.setMax(options.max);
@@ -215,7 +215,7 @@ class AvatarGroup {
215
215
  const extra = document.createElement("avatar_group_extra");
216
216
  extra.className = "avatar_group_extra";
217
217
  extra.innerText = `+${hidden}`;
218
- if (this.#extra_listener === undefined) {
218
+ if (this.#extraListener === undefined) {
219
219
  extra.setAttribute("role", "img");
220
220
  extra.setAttribute("aria-label", I18n.t("feedback.avatarGroupMore", { count: hidden }));
221
221
  } else {
@@ -223,7 +223,7 @@ class AvatarGroup {
223
223
  extra.classList.add("avatar_group_extra_button");
224
224
  extra.setAttribute("aria-label", I18n.t("feedback.avatarGroupShowAll", { count: hidden }));
225
225
  makeKeyboardButton(extra);
226
- extra.addEventListener("click", (event) => this.#extra_listener(event, hidden, this));
226
+ extra.addEventListener("click", (event) => this.#extraListener(event, hidden, this));
227
227
  }
228
228
  this.#extra = extra;
229
229
  this.#root.appendChild(extra);
@@ -7,7 +7,7 @@ chui_avatar_group {
7
7
  flex-wrap: nowrap;
8
8
  width: max-content;
9
9
  height: max-content;
10
- margin: var(--margin);
10
+ margin: var(--block_margin);
11
11
  --avatar_size: 40px;
12
12
  --avatar_group_ring: var(--element_background_2);
13
13
  }
@@ -198,6 +198,7 @@ class Backtop {
198
198
  if (this.#destroyed) return this;
199
199
  this.#destroyed = true;
200
200
  window.removeEventListener("scroll", this.#onScroll, { capture: true });
201
+ this.#root.removeEventListener("transitionend", this.#onHideEnd);
201
202
  this.#root.remove();
202
203
  return this;
203
204
  }
@@ -238,9 +239,31 @@ class Backtop {
238
239
  const visible = top > this.#threshold;
239
240
  if (visible === this.#visible) return;
240
241
  this.#visible = visible;
241
- this.#root.hidden = visible === false;
242
- this.#root.classList.toggle("backtop_visible", visible);
242
+ this.#show(visible);
243
243
  }
244
+
245
+ /**
246
+ * Показ и уход идут движением (переход в styles.css). Узел встаёт в раскладку до класса —
247
+ * иначе перехода не было бы вовсе, — а `hidden` возвращается по концу ухода: в закреплённом
248
+ * положении он держит место в раскладке панели, и снять его до ухода значило бы оборвать его.
249
+ */
250
+ #show(visible) {
251
+ if (visible) {
252
+ this.#root.hidden = false;
253
+ requestAnimationFrame(() => {
254
+ if (this.#visible === true) this.#root.classList.add("backtop_visible");
255
+ });
256
+ return;
257
+ }
258
+ this.#root.classList.remove("backtop_visible");
259
+ this.#root.addEventListener("transitionend", this.#onHideEnd);
260
+ }
261
+
262
+ #onHideEnd = (event) => {
263
+ if (event.target !== this.#root || event.propertyName !== "opacity") return;
264
+ this.#root.removeEventListener("transitionend", this.#onHideEnd);
265
+ if (this.#visible === false) this.#root.hidden = true;
266
+ };
244
267
  }
245
268
 
246
269
  exports.Backtop = Backtop;
@@ -6,6 +6,27 @@ chui_backtop {
6
6
  --backtop_inline_end: 24px;
7
7
  width: max-content;
8
8
  height: max-content;
9
+ opacity: 1;
10
+ transform: none;
11
+ /* Появление и уход — движение, а не снятие узла: кнопка поднимается на месте и гаснет.
12
+ `hidden` включает JS по концу ухода: в закреплённом положении он держит место
13
+ в раскладке панели, поэтому снимать его заранее нельзя */
14
+ transition:
15
+ opacity var(--motion_base) var(--motion_ease),
16
+ transform var(--motion_base) var(--motion_ease),
17
+ visibility var(--motion_none) linear;
18
+ }
19
+
20
+ /* Скрытая кнопка не ловит курсор и не попадает в обход Tab: `visibility` переключается
21
+ сразу при показе и только в конце ухода */
22
+ chui_backtop:not(.backtop_visible) {
23
+ opacity: 0;
24
+ transform: translateY(8px);
25
+ visibility: hidden;
26
+ transition:
27
+ opacity var(--motion_fast) var(--motion_ease),
28
+ transform var(--motion_fast) var(--motion_ease),
29
+ visibility var(--motion_none) linear var(--motion_fast);
9
30
  }
10
31
 
11
32
  chui_backtop[hidden] {
@@ -1,7 +1,7 @@
1
1
  const { setStyles, markdownToHtml, htmlToMarkdown, optionOr } = require("../../modules/chui_functions");
2
2
 
3
3
  class Badge {
4
- #chui_badge = document.createElement(`chui_badge`);
4
+ #chuiBadge = document.createElement(`chui_badge`);
5
5
  constructor(
6
6
  options = {
7
7
  id: String(),
@@ -11,47 +11,47 @@ class Badge {
11
11
  }
12
12
  ) {
13
13
  setStyles(__dirname + "/styles.css", "chUiJS_Badge");
14
- if (options.id !== undefined) this.#chui_badge.id = options.id;
14
+ if (options.id !== undefined) this.#chuiBadge.id = options.id;
15
15
  const style = optionOr(options.style, undefined);
16
- if (style !== undefined) this.#chui_badge.classList.add(style);
16
+ if (style !== undefined) this.#chuiBadge.classList.add(style);
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_badge.innerText = text;
24
- if (markdown_text !== undefined) this.#chui_badge.innerHTML = markdownToHtml(markdown_text);
23
+ if (text !== undefined) this.#chuiBadge.innerText = text;
24
+ if (markdownText !== undefined) this.#chuiBadge.innerHTML = markdownToHtml(markdownText);
25
25
  }
26
26
  }
27
27
  // GET
28
28
  getId() {
29
- return this.#chui_badge.id;
29
+ return this.#chuiBadge.id;
30
30
  }
31
31
  getText() {
32
- return this.#chui_badge.innerText;
32
+ return this.#chuiBadge.innerText;
33
33
  }
34
34
  getMarkdownText() {
35
- return htmlToMarkdown(this.#chui_badge.innerHTML);
35
+ return htmlToMarkdown(this.#chuiBadge.innerHTML);
36
36
  }
37
37
  // SET
38
38
  setText(text = String()) {
39
- this.#chui_badge.innerText = text;
39
+ this.#chuiBadge.innerText = text;
40
40
  }
41
41
  setMarkdownText(text = String()) {
42
- this.#chui_badge.innerHTML = markdownToHtml(text);
42
+ this.#chuiBadge.innerHTML = markdownToHtml(text);
43
43
  }
44
44
  setId(id = String()) {
45
- this.#chui_badge.id = id;
45
+ this.#chuiBadge.id = id;
46
46
  }
47
47
  setStyle(style = String()) {
48
48
  // Пустая строка — «не задана»: `classList.add("")` бросает исключение
49
49
  const known = optionOr(style, undefined);
50
- if (known !== undefined) this.#chui_badge.classList.add(known);
50
+ if (known !== undefined) this.#chuiBadge.classList.add(known);
51
51
  }
52
52
  // RENDER
53
53
  set() {
54
- return this.#chui_badge;
54
+ return this.#chuiBadge;
55
55
  }
56
56
  static STYLE = {
57
57
  ERROR: "badge_error",
@@ -12,9 +12,9 @@ chui_badge {
12
12
  height: max-content;
13
13
  width: max-content;
14
14
  padding: 2px 8px;
15
- margin: var(--margin);
15
+ margin: var(--block_margin);
16
16
  border-radius: var(--radius_pill);
17
- background: var(--badge_cancel_back);
17
+ background: var(--badge_cancel_background);
18
18
  color: var(--badge_cancel_text);
19
19
  font-size: var(--font_labels_size);
20
20
  font-weight: 500;
@@ -41,20 +41,20 @@ chui_badge strong {
41
41
 
42
42
  /* Код в метке — тем же моношрифтом, что в остальных местах с разметкой */
43
43
  chui_badge code {
44
- font-family: var(--code_font, monospace);
44
+ font-family: var(--font_mono);
45
45
  }
46
46
 
47
47
  .badge_error {
48
- background: var(--badge_error_back);
48
+ background: var(--badge_error_background);
49
49
  color: var(--badge_error_text);
50
50
  }
51
51
 
52
52
  .badge_success {
53
- background: var(--badge_success_back);
53
+ background: var(--badge_success_background);
54
54
  color: var(--badge_success_text);
55
55
  }
56
56
 
57
57
  .badge_warning {
58
- background: var(--badge_warning_back);
58
+ background: var(--badge_warning_background);
59
59
  color: var(--badge_warning_text);
60
60
  }