chuijs 4.0.2 → 4.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +597 -0
- package/README.md +43 -644
- package/framework/appLayout/default/chui_app_layout.js +602 -496
- package/framework/appLayout/default/global_style.css +288 -97
- package/framework/appLayout/default/main_theme_style.css +188 -101
- package/framework/components/chui_accordion/accordion.js +38 -35
- package/framework/components/chui_accordion/styles.css +13 -12
- package/framework/components/chui_action_sheet/action_sheet.js +93 -64
- package/framework/components/chui_action_sheet/styles.css +12 -5
- package/framework/components/chui_actions_bar/actions_bar.js +338 -0
- package/framework/components/chui_actions_bar/styles.css +139 -0
- package/framework/components/chui_affix/affix.js +16 -11
- package/framework/components/chui_affix/styles.css +5 -0
- package/framework/components/chui_alert/alert.js +34 -19
- package/framework/components/chui_alert/styles.css +7 -0
- package/framework/components/chui_avatar/avatar.js +36 -35
- package/framework/components/chui_avatar/styles.css +1 -1
- package/framework/components/chui_avatar_group/avatar_group.js +25 -23
- package/framework/components/chui_avatar_group/styles.css +1 -1
- package/framework/components/chui_backtop/backtop.js +60 -21
- package/framework/components/chui_backtop/styles.css +21 -0
- package/framework/components/chui_badge/badge.js +30 -28
- package/framework/components/chui_badge/styles.css +6 -6
- package/framework/components/chui_banner/banner.js +222 -0
- package/framework/components/chui_banner/styles.css +170 -0
- package/framework/components/chui_breadcrumb/breadcrumb.js +15 -13
- package/framework/components/chui_breadcrumb/styles.css +1 -1
- package/framework/components/chui_button/button.js +52 -36
- package/framework/components/chui_button/styles.css +7 -7
- package/framework/components/chui_calendar/calendar.js +18 -16
- package/framework/components/chui_card/card.js +52 -32
- package/framework/components/chui_card_scroll/card_scroll.js +169 -0
- package/framework/components/chui_card_scroll/styles.css +86 -0
- package/framework/components/chui_chat/chat.js +140 -79
- package/framework/components/chui_chat/styles.css +18 -7
- package/framework/components/chui_clipboard_history/clipboard_history.js +53 -39
- package/framework/components/chui_clipboard_history/styles.css +13 -9
- package/framework/components/chui_code/code.js +10 -10
- package/framework/components/chui_code/styles.css +4 -4
- package/framework/components/chui_code_editor/code_editor.js +73 -57
- package/framework/components/chui_code_editor/styles.css +6 -5
- package/framework/components/chui_command_palette/command_palette.js +87 -64
- package/framework/components/chui_command_palette/styles.css +5 -5
- package/framework/components/chui_console/console.js +13 -13
- package/framework/components/chui_console/styles.css +6 -3
- package/framework/components/chui_content_block/content_block.js +35 -21
- package/framework/components/chui_content_block/styles.css +2 -2
- package/framework/components/chui_context_menu/context_menu.js +171 -58
- package/framework/components/chui_context_menu/styles.css +82 -8
- package/framework/components/chui_custom_element/custom_element.js +25 -18
- package/framework/components/chui_data_grid/data_grid.js +633 -471
- package/framework/components/chui_data_grid/styles.css +24 -22
- package/framework/components/chui_descriptions/descriptions.js +34 -17
- package/framework/components/chui_descriptions/styles.css +1 -1
- package/framework/components/chui_details/details.js +42 -36
- package/framework/components/chui_details/styles.css +12 -11
- package/framework/components/chui_diff_viewer/diff_viewer.js +172 -147
- package/framework/components/chui_diff_viewer/styles.css +10 -10
- package/framework/components/chui_divider/divider.js +19 -17
- package/framework/components/chui_divider/styles.css +2 -2
- package/framework/components/chui_drawer/drawer.js +63 -38
- package/framework/components/chui_drawer/styles.css +18 -4
- package/framework/components/chui_drop_zone/drop_zone.js +37 -27
- package/framework/components/chui_drop_zone/styles.css +10 -6
- package/framework/components/chui_empty_state/empty_state.js +20 -15
- package/framework/components/chui_fieldset/fieldset.js +40 -23
- package/framework/components/chui_fieldset/styles.css +6 -6
- package/framework/components/chui_file_explorer/file_explorer.js +260 -189
- package/framework/components/chui_file_explorer/styles.css +8 -7
- package/framework/components/chui_form/form.js +40 -28
- package/framework/components/chui_form/styles.css +1 -1
- package/framework/components/chui_gantt/gantt.js +102 -78
- package/framework/components/chui_gantt/styles.css +5 -5
- package/framework/components/chui_graphs/graphs.js +376 -239
- package/framework/components/chui_graphs/styles.css +27 -6
- package/framework/components/chui_hero/hero.js +98 -37
- package/framework/components/chui_hero/styles.css +176 -7
- package/framework/components/chui_html_block/html_block.js +8 -8
- package/framework/components/chui_html_block/styles.css +3 -3
- package/framework/components/chui_hx/hx.js +3 -3
- package/framework/components/chui_hx/styles.css +13 -6
- package/framework/components/chui_icons/icons.js +2115 -2115
- package/framework/components/chui_icons/styles.css +4 -3
- package/framework/components/chui_inputs/chui_check_box/check_box.js +31 -19
- package/framework/components/chui_inputs/chui_check_box/styles.css +30 -21
- package/framework/components/chui_inputs/chui_chips/chips.js +141 -70
- package/framework/components/chui_inputs/chui_chips/styles.css +32 -7
- package/framework/components/chui_inputs/chui_color_picker/color_picker.js +55 -38
- package/framework/components/chui_inputs/chui_color_picker/styles.css +7 -7
- package/framework/components/chui_inputs/chui_combo_box/combo_box.js +127 -109
- package/framework/components/chui_inputs/chui_combo_box/styles.css +23 -21
- package/framework/components/chui_inputs/chui_date/date.js +161 -127
- package/framework/components/chui_inputs/chui_date/styles.css +20 -19
- package/framework/components/chui_inputs/chui_date_range/date_range.js +61 -50
- package/framework/components/chui_inputs/chui_date_range/styles.css +3 -3
- package/framework/components/chui_inputs/chui_datetime/datetime.js +47 -39
- package/framework/components/chui_inputs/chui_datetime/styles.css +3 -3
- package/framework/components/chui_inputs/chui_email/email.js +48 -36
- package/framework/components/chui_inputs/chui_email/styles.css +11 -11
- package/framework/components/chui_inputs/chui_file/file.js +71 -44
- package/framework/components/chui_inputs/chui_file/styles.css +23 -19
- package/framework/components/chui_inputs/chui_hotkey/hotkey.js +101 -76
- package/framework/components/chui_inputs/chui_hotkey/styles.css +6 -6
- package/framework/components/chui_inputs/chui_masked/masked.js +83 -72
- package/framework/components/chui_inputs/chui_masked/styles.css +5 -5
- package/framework/components/chui_inputs/chui_mention/mention.js +87 -40
- package/framework/components/chui_inputs/chui_mention/styles.css +14 -8
- package/framework/components/chui_inputs/chui_multi_combo_box/multi_combo_box.js +242 -212
- package/framework/components/chui_inputs/chui_multi_combo_box/styles.css +23 -15
- package/framework/components/chui_inputs/chui_number/number.js +84 -70
- package/framework/components/chui_inputs/chui_number/styles.css +13 -13
- package/framework/components/chui_inputs/chui_otp/otp.js +71 -62
- package/framework/components/chui_inputs/chui_otp/styles.css +5 -5
- package/framework/components/chui_inputs/chui_password/password.js +72 -56
- package/framework/components/chui_inputs/chui_password/styles.css +15 -15
- package/framework/components/chui_inputs/chui_radio_button/radio_button.js +37 -25
- package/framework/components/chui_inputs/chui_radio_button/styles.css +22 -22
- package/framework/components/chui_inputs/chui_rating/rating.js +54 -50
- package/framework/components/chui_inputs/chui_rating/styles.css +3 -3
- package/framework/components/chui_inputs/chui_select_box/select_box.js +132 -108
- package/framework/components/chui_inputs/chui_select_box/styles.css +21 -21
- package/framework/components/chui_inputs/chui_slider/slider.js +41 -38
- package/framework/components/chui_inputs/chui_slider/styles.css +7 -5
- package/framework/components/chui_inputs/chui_text/styles.css +14 -14
- package/framework/components/chui_inputs/chui_text/text.js +69 -52
- package/framework/components/chui_inputs/chui_text_area/styles.css +14 -14
- package/framework/components/chui_inputs/chui_text_area/text_area.js +59 -36
- package/framework/components/chui_inputs/chui_time/styles.css +18 -20
- package/framework/components/chui_inputs/chui_time/time.js +71 -49
- package/framework/components/chui_inputs/chui_toggle/styles.css +13 -6
- package/framework/components/chui_inputs/chui_toggle/toggle.js +27 -27
- package/framework/components/chui_json_editor/json_editor.js +137 -127
- package/framework/components/chui_json_editor/styles.css +5 -5
- package/framework/components/chui_json_viewer/json_viewer.js +133 -114
- package/framework/components/chui_json_viewer/styles.css +9 -8
- package/framework/components/chui_kanban/kanban.js +78 -60
- package/framework/components/chui_kanban/styles.css +8 -4
- package/framework/components/chui_kbd/kbd.js +12 -10
- package/framework/components/chui_kbd/styles.css +1 -1
- package/framework/components/chui_label/label.js +31 -29
- package/framework/components/chui_label/styles.css +3 -3
- package/framework/components/chui_link/link.js +36 -29
- package/framework/components/chui_link/styles.css +11 -4
- package/framework/components/chui_list/list.js +42 -38
- package/framework/components/chui_list/styles.css +4 -3
- package/framework/components/chui_markdown_editor/markdown_editor.js +125 -109
- package/framework/components/chui_markdown_editor/styles.css +5 -5
- package/framework/components/chui_media/audio.js +457 -364
- package/framework/components/chui_media/audio_styles.css +74 -37
- package/framework/components/chui_media/image.js +99 -64
- package/framework/components/chui_media/image_compare.js +86 -55
- package/framework/components/chui_media/image_compare_styles.css +5 -5
- package/framework/components/chui_media/image_styles.css +4 -4
- package/framework/components/chui_media/video.js +264 -171
- package/framework/components/chui_media/video_styles.css +57 -24
- package/framework/components/chui_menu_bar/menu_bar.js +67 -65
- package/framework/components/chui_menu_bar/styles.css +14 -12
- package/framework/components/chui_message_bar/message_bar.js +551 -0
- package/framework/components/chui_message_bar/styles.css +248 -0
- package/framework/components/chui_modal/modal.js +81 -56
- package/framework/components/chui_modal/styles.css +3 -2
- package/framework/components/chui_notification/notification.js +107 -69
- package/framework/components/chui_notification/notification_download.js +28 -77
- package/framework/components/chui_notification/notification_download_card.js +115 -0
- package/framework/components/chui_notification/notification_download_progress.css +5 -4
- package/framework/components/chui_notification/notification_download_progress.js +73 -105
- package/framework/components/chui_notification/notification_update.js +44 -37
- package/framework/components/chui_notification/status_plate.css +3 -3
- package/framework/components/chui_notification/status_plate.js +2 -2
- package/framework/components/chui_notification/styles.css +6 -1
- package/framework/components/chui_notification/styles_download.css +2 -2
- package/framework/components/chui_notification/styles_update.css +3 -3
- package/framework/components/chui_org_chart/org_chart.js +101 -62
- package/framework/components/chui_org_chart/styles.css +2 -2
- package/framework/components/chui_pagination/pagination.js +65 -30
- package/framework/components/chui_pagination/styles.css +1 -1
- package/framework/components/chui_paragraph/paragraph.js +2 -2
- package/framework/components/chui_paragraph/styles.css +3 -3
- package/framework/components/chui_popover/popover.js +77 -50
- package/framework/components/chui_popover/styles.css +1 -1
- package/framework/components/chui_popups/popups.js +210 -181
- package/framework/components/chui_popups/styles.css +7 -7
- package/framework/components/chui_print_button/print_button.js +48 -33
- package/framework/components/chui_progress_bar/progress_bar.js +49 -19
- package/framework/components/chui_progress_bar/styles.css +6 -6
- package/framework/components/chui_progress_ring/progress_ring.js +32 -30
- package/framework/components/chui_progress_ring/styles.css +1 -1
- package/framework/components/chui_qrcode/qrcode.js +85 -41
- package/framework/components/chui_query_builder/query_builder.js +263 -170
- package/framework/components/chui_query_builder/styles.css +4 -4
- package/framework/components/chui_radio_group/radio_group.js +36 -26
- package/framework/components/chui_radio_group/styles.css +2 -2
- package/framework/components/chui_result/result.js +41 -31
- package/framework/components/chui_result/styles.css +3 -3
- package/framework/components/chui_scheduler/scheduler.js +126 -104
- package/framework/components/chui_scheduler/styles.css +11 -7
- package/framework/components/chui_screen_spinner/screen_spinner.js +167 -0
- package/framework/components/chui_screen_spinner/styles.css +49 -0
- package/framework/components/chui_segmented_control/segmented_control.js +90 -27
- package/framework/components/chui_segmented_control/styles.css +32 -6
- package/framework/components/chui_settings/settings.js +160 -87
- package/framework/components/chui_settings/styles.css +4 -4
- package/framework/components/chui_shortcut_help/shortcut_help.js +82 -61
- package/framework/components/chui_sidebar_nav/sidebar_nav.js +132 -53
- package/framework/components/chui_sidebar_nav/styles.css +9 -3
- package/framework/components/chui_skeleton/skeleton.js +29 -24
- package/framework/components/chui_slideshow/slideshow.js +122 -103
- package/framework/components/chui_slideshow/styles.css +22 -16
- package/framework/components/chui_spinner/spinner.js +17 -17
- package/framework/components/chui_spinner/styles.css +0 -1
- package/framework/components/chui_split_button/split_button.js +53 -30
- package/framework/components/chui_split_button/styles.css +22 -6
- package/framework/components/chui_splitter/splitter.js +46 -39
- package/framework/components/chui_splitter/styles.css +2 -2
- package/framework/components/chui_statistic/statistic.js +111 -84
- package/framework/components/chui_status_bar/status_bar.js +11 -9
- package/framework/components/chui_status_bar/styles.css +2 -2
- package/framework/components/chui_stepper/stepper.js +230 -54
- package/framework/components/chui_stepper/styles.css +79 -14
- package/framework/components/chui_sticky_bar/sticky_bar.js +53 -17
- package/framework/components/chui_sticky_bar/styles.css +11 -7
- package/framework/components/chui_tabs/chui_tabs.js +100 -46
- package/framework/components/chui_tabs/styles.css +43 -15
- package/framework/components/chui_text_editor/styles.css +24 -23
- package/framework/components/chui_text_editor/text_editor.js +103 -79
- package/framework/components/chui_text_editor/text_editor_panel.js +428 -367
- package/framework/components/chui_theme_toggle/theme_toggle.js +46 -25
- package/framework/components/chui_timeline/styles.css +3 -1
- package/framework/components/chui_timeline/timeline.js +14 -12
- package/framework/components/chui_toast_queue/styles.css +11 -11
- package/framework/components/chui_toast_queue/toast_queue.js +82 -73
- package/framework/components/chui_toolbar/styles.css +2 -2
- package/framework/components/chui_toolbar/toolbar.js +20 -13
- package/framework/components/chui_tooltip/styles.css +2 -2
- package/framework/components/chui_tooltip/tooltip.js +40 -27
- package/framework/components/chui_tour/styles.css +12 -7
- package/framework/components/chui_tour/tour.js +132 -98
- package/framework/components/chui_transfer/styles.css +8 -7
- package/framework/components/chui_transfer/transfer.js +143 -123
- package/framework/components/chui_tree_table/styles.css +4 -4
- package/framework/components/chui_tree_table/tree_table.js +88 -74
- package/framework/components/chui_tree_view/styles.css +14 -10
- package/framework/components/chui_tree_view/tree_view.js +298 -253
- package/framework/components/chui_user_bar/styles.css +145 -0
- package/framework/components/chui_user_bar/user_bar.js +402 -0
- package/framework/components/chui_user_list_bar/styles.css +173 -0
- package/framework/components/chui_user_list_bar/user_list_bar.js +485 -0
- package/framework/components/chui_watermark/watermark.js +41 -33
- package/framework/components/chui_webview/styles.css +2 -2
- package/framework/components/chui_webview/webview.js +64 -52
- package/framework/components/chui_write_bar/styles.css +172 -0
- package/framework/components/chui_write_bar/write_bar.js +320 -0
- package/framework/main_window.js +1234 -0
- package/framework/modules/chui_a11y/chui_a11y.js +153 -123
- package/framework/modules/chui_animations/animations.js +105 -43
- package/framework/modules/chui_animations/motion.js +120 -0
- package/framework/modules/chui_animations/styles.css +37 -4
- package/framework/modules/chui_bridge/preload.js +36 -25
- package/framework/modules/chui_functions.js +69 -63
- package/framework/modules/chui_highlight/chui_highlight.js +25 -22
- package/framework/modules/chui_highlight/styles.css +13 -10
- package/framework/modules/chui_i18n/chui_i18n.js +12 -10
- package/framework/modules/chui_i18n/locales/a11y.js +5 -5
- package/framework/modules/chui_i18n/locales/app_layout.js +5 -5
- package/framework/modules/chui_i18n/locales/calendar.js +3 -3
- package/framework/modules/chui_i18n/locales/common.js +3 -3
- package/framework/modules/chui_i18n/locales/data.js +36 -26
- package/framework/modules/chui_i18n/locales/editors.js +40 -13
- package/framework/modules/chui_i18n/locales/feedback.js +65 -3
- package/framework/modules/chui_i18n/locales/forms.js +8 -8
- package/framework/modules/chui_i18n/locales/graphics.js +8 -8
- package/framework/modules/chui_i18n/locales/media.js +4 -4
- package/framework/modules/chui_i18n/locales/navigation.js +12 -8
- package/framework/modules/chui_i18n/locales/validate.js +3 -3
- package/framework/modules/chui_json/chui_json.js +11 -11
- package/framework/modules/chui_layout/chui_layout.js +12 -10
- package/framework/modules/chui_logger/chui_logger.js +47 -28
- package/framework/modules/chui_page/page.js +39 -33
- package/framework/modules/chui_palette/palette.js +61 -0
- package/framework/modules/chui_qr/chui_qr.js +179 -88
- package/framework/modules/chui_scrollbar/chui_scrollbar.js +79 -68
- package/framework/modules/chui_scrollbar/styles.css +4 -2
- package/framework/modules/chui_services/chui_channels.js +27 -13
- package/framework/modules/chui_services/chui_services.js +47 -39
- package/framework/modules/chui_services/desktop.js +108 -101
- package/framework/modules/chui_sortable/chui_sortable.js +33 -28
- package/framework/modules/chui_validate/chui_validate.js +10 -7
- package/framework/tray_bar/chui_menu_items.js +136 -46
- package/index.d.ts +5046 -0
- package/index.js +199 -1254
- package/package.json +81 -68
- package/framework/components/telegram_bot/chui_telegram_bot.js +0 -184
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const {setStyles, optionOr, scrollParent} = require(
|
|
1
|
+
const { setStyles, optionOr, scrollParent } = require("../../modules/chui_functions");
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Прилипающая полоса: остаётся у верха области прокрутки, пока её содержимое не кончилось.
|
|
@@ -31,8 +31,11 @@ const {setStyles, optionOr, scrollParent} = require('../../modules/chui_function
|
|
|
31
31
|
* пересекает границу ровно в момент закрепления и даёт неустойчивый сигнал на дробных пикселях.
|
|
32
32
|
* Поэтому раз в кадр сравниваются верх полосы и верх области прокрутки; слушатель `scroll` —
|
|
33
33
|
* пассивный, работа сведена к одному замеру на кадр через `requestAnimationFrame`.
|
|
34
|
-
*
|
|
35
|
-
*
|
|
34
|
+
* * **Пока узел не в документе, контейнер не ищется.** Прокручиваемого предка у такого узла нет,
|
|
35
|
+
* и поиск вернул бы документ: порог встал бы на нуле, и полоса никогда не «закрепилась» бы —
|
|
36
|
+
* в разметке она осталась бы без фона, рамки и тени. Поэтому компонент ждёт появления узла
|
|
37
|
+
* в документе (наблюдателем, а не опросом по кадрам) и только потом подключается.
|
|
38
|
+
* * Доступность: компонент ничего не объявляет и не перехватывает — содержимое остаётся обычным
|
|
36
39
|
* содержимым. `destroy()` снимает слушатели; повторный вызов безвреден.
|
|
37
40
|
*/
|
|
38
41
|
class StickyBar {
|
|
@@ -44,15 +47,22 @@ class StickyBar {
|
|
|
44
47
|
#offset = "0px";
|
|
45
48
|
#target = undefined;
|
|
46
49
|
#stuck = false;
|
|
47
|
-
#
|
|
50
|
+
#onChange = undefined;
|
|
48
51
|
#container = undefined;
|
|
49
52
|
#destroyed = false;
|
|
50
53
|
#frame = 0;
|
|
51
54
|
#pending = 0;
|
|
55
|
+
// Наблюдатель за вставкой узла в документ: до неё области прокрутки ещё нет
|
|
56
|
+
#insert = undefined;
|
|
52
57
|
|
|
53
|
-
constructor(
|
|
54
|
-
|
|
55
|
-
|
|
58
|
+
constructor(
|
|
59
|
+
options = {
|
|
60
|
+
id: String(),
|
|
61
|
+
offset: Number(),
|
|
62
|
+
target: undefined,
|
|
63
|
+
onChange: undefined,
|
|
64
|
+
}
|
|
65
|
+
) {
|
|
56
66
|
setStyles(__dirname + "/styles.css", "chUiJS_StickyBar");
|
|
57
67
|
StickyBar.#counter += 1;
|
|
58
68
|
this.#id = optionOr(options.id, `chui_sticky_bar_${StickyBar.#counter}`);
|
|
@@ -61,7 +71,7 @@ class StickyBar {
|
|
|
61
71
|
this.#root.dataset.stuck = "false";
|
|
62
72
|
this.#root.appendChild(this.#content);
|
|
63
73
|
this.#target = options.target;
|
|
64
|
-
this.#
|
|
74
|
+
this.#onChange = options.onChange;
|
|
65
75
|
this.setOffset(options.offset === undefined ? 0 : options.offset);
|
|
66
76
|
this.#observe();
|
|
67
77
|
}
|
|
@@ -107,13 +117,13 @@ class StickyBar {
|
|
|
107
117
|
/** Отступ закрепления: число пикселей или строка CSS (`"12px"`, `"var(--header_height)"`) */
|
|
108
118
|
setOffset(offset = Number()) {
|
|
109
119
|
this.#offset = typeof offset === "string" ? offset : `${Number(offset) || 0}px`;
|
|
110
|
-
this.#root.style.setProperty("--
|
|
120
|
+
this.#root.style.setProperty("--sticky_bar_offset", this.#offset);
|
|
111
121
|
this.update();
|
|
112
122
|
return this;
|
|
113
123
|
}
|
|
114
124
|
|
|
115
125
|
setOnChange(listener = undefined) {
|
|
116
|
-
this.#
|
|
126
|
+
this.#onChange = listener;
|
|
117
127
|
return this;
|
|
118
128
|
}
|
|
119
129
|
|
|
@@ -155,8 +165,9 @@ class StickyBar {
|
|
|
155
165
|
// === ВНУТРЕННЕЕ ===
|
|
156
166
|
/**
|
|
157
167
|
* Первое подключение — на следующем кадре: узел обычно вставляют в документ сразу после
|
|
158
|
-
* `set()`, и только тогда виден настоящий контейнер прокрутки.
|
|
159
|
-
*
|
|
168
|
+
* `set()`, и только тогда виден настоящий контейнер прокрутки. Если к этому кадру узел ещё
|
|
169
|
+
* не в документе (страница собирается позже), ждём вставки — иначе контейнером стал бы документ.
|
|
170
|
+
* Повторные вызовы ничего не делают, пока подключение не снято.
|
|
160
171
|
*/
|
|
161
172
|
#observe() {
|
|
162
173
|
if (this.#destroyed === true) return;
|
|
@@ -169,6 +180,13 @@ class StickyBar {
|
|
|
169
180
|
|
|
170
181
|
#attach() {
|
|
171
182
|
if (this.#destroyed === true) return;
|
|
183
|
+
// Узел ещё не в документе: прокручиваемого предка у него нет, и поиск контейнера вернул бы
|
|
184
|
+
// документ — порог встал бы на нуле, и полоса никогда не «закрепилась» бы (без фона, рамки
|
|
185
|
+
// и тени). Ждём вставки наблюдателем, а не опросом по кадрам
|
|
186
|
+
if (this.#root.isConnected === false) {
|
|
187
|
+
this.#awaitInsert();
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
172
190
|
this.#container = this.getTarget();
|
|
173
191
|
if (this.#container instanceof Element) {
|
|
174
192
|
this.#container.addEventListener("scroll", this.#onScroll, { passive: true });
|
|
@@ -177,7 +195,25 @@ class StickyBar {
|
|
|
177
195
|
this.#schedule();
|
|
178
196
|
}
|
|
179
197
|
|
|
198
|
+
/** Ждём появления узла в документе; наблюдатель снимается сразу после вставки или в `detach()` */
|
|
199
|
+
#awaitInsert() {
|
|
200
|
+
if (this.#insert !== undefined || this.#destroyed === true) return;
|
|
201
|
+
this.#insert = new MutationObserver(() => {
|
|
202
|
+
if (this.#root.isConnected === false) return;
|
|
203
|
+
this.#dropInsert();
|
|
204
|
+
this.#attach();
|
|
205
|
+
});
|
|
206
|
+
this.#insert.observe(document.body, { childList: true, subtree: true });
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
#dropInsert() {
|
|
210
|
+
if (this.#insert === undefined) return;
|
|
211
|
+
this.#insert.disconnect();
|
|
212
|
+
this.#insert = undefined;
|
|
213
|
+
}
|
|
214
|
+
|
|
180
215
|
#detach() {
|
|
216
|
+
this.#dropInsert();
|
|
181
217
|
if (this.#container instanceof Element) {
|
|
182
218
|
this.#container.removeEventListener("scroll", this.#onScroll);
|
|
183
219
|
}
|
|
@@ -213,17 +249,17 @@ class StickyBar {
|
|
|
213
249
|
if (!(container instanceof Element) || this.#root.isConnected === false) return;
|
|
214
250
|
// Порог — от края содержимого контейнера: собственный отступ прокрутки браузер
|
|
215
251
|
// учитывает сам, а рамку — нет, поэтому она прибавляется отдельно
|
|
216
|
-
const
|
|
217
|
-
const padding = Number.parseFloat(
|
|
218
|
-
const
|
|
252
|
+
const containerStyle = window.getComputedStyle(container);
|
|
253
|
+
const padding = Number.parseFloat(containerStyle.paddingTop) || 0;
|
|
254
|
+
const referenceTop = container.getBoundingClientRect().top + container.clientTop + padding;
|
|
219
255
|
const inset = Number.parseFloat(window.getComputedStyle(this.#root).top);
|
|
220
256
|
const offset = Number.isFinite(inset) ? inset : 0;
|
|
221
|
-
const stuck = this.#root.getBoundingClientRect().top <=
|
|
257
|
+
const stuck = this.#root.getBoundingClientRect().top <= referenceTop + offset + 1;
|
|
222
258
|
if (stuck === this.#stuck) return;
|
|
223
259
|
this.#stuck = stuck;
|
|
224
260
|
this.#root.dataset.stuck = String(stuck);
|
|
225
261
|
this.#root.classList.toggle("sticky_bar_stuck", stuck);
|
|
226
|
-
if (typeof this.#
|
|
262
|
+
if (typeof this.#onChange === "function") this.#onChange(stuck);
|
|
227
263
|
}
|
|
228
264
|
}
|
|
229
265
|
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/* Прилипающая полоса: корень сам липнет к верху области прокрутки, поэтому место в потоке
|
|
2
|
-
сохраняется и подпорка-заглушка не нужна. Отступ задаёт компонент переменной `--
|
|
2
|
+
сохраняется и подпорка-заглушка не нужна. Отступ задаёт компонент переменной `--sticky_bar_offset`
|
|
3
3
|
(число или CSS-значение); отсчитывается он от края содержимого области прокрутки. */
|
|
4
4
|
chui_sticky_bar {
|
|
5
|
-
--
|
|
5
|
+
--sticky_bar_offset: 0px;
|
|
6
6
|
display: block;
|
|
7
7
|
position: sticky;
|
|
8
|
-
inset-block-start: var(--
|
|
8
|
+
inset-block-start: var(--sticky_bar_offset);
|
|
9
9
|
width: -webkit-fill-available;
|
|
10
10
|
/* Ниже шапки (999) и выше содержимого страницы: полоса — слой над текстом, но под оболочкой */
|
|
11
11
|
z-index: 6;
|
|
@@ -24,14 +24,18 @@ sticky_bar_content {
|
|
|
24
24
|
padding: 8px 10px;
|
|
25
25
|
border: 1px solid transparent;
|
|
26
26
|
border-radius: var(--radius_md);
|
|
27
|
-
transition:
|
|
27
|
+
transition:
|
|
28
|
+
background-color var(--motion_fast) var(--motion_ease),
|
|
29
|
+
box-shadow var(--motion_fast) var(--motion_ease);
|
|
28
30
|
}
|
|
29
31
|
|
|
30
|
-
/* Закреплённая полоса читается отдельным слоем:
|
|
31
|
-
|
|
32
|
+
/* Закреплённая полоса читается отдельным слоем: волосяной край и тень, а заливка — цвет
|
|
33
|
+
подложки (`--bar_background`), как у шапки, меню маршрутов и ящика уведомлений: полоса
|
|
34
|
+
выходит из подложки, а не лежит на ней светлой плашкой. В покое она — обычная строка
|
|
35
|
+
содержимого, ни фона, ни тени */
|
|
32
36
|
chui_sticky_bar[data-stuck="true"] sticky_bar_content {
|
|
33
37
|
border-color: var(--border_color);
|
|
34
|
-
background: var(--
|
|
38
|
+
background: var(--bar_background);
|
|
35
39
|
backdrop-filter: var(--global_blur);
|
|
36
40
|
box-shadow: var(--box_shadow_main);
|
|
37
41
|
}
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
|
|
2
|
-
const {Icon, Icons} = require(
|
|
3
|
-
const {makeKeyboardButton} = require(
|
|
4
|
-
const {I18n} = require(
|
|
1
|
+
const { Animation } = require("../../modules/chui_animations/animations");
|
|
2
|
+
const { Icon, Icons } = require("../chui_icons/icons");
|
|
3
|
+
const { makeKeyboardButton } = require("../../modules/chui_a11y/chui_a11y");
|
|
4
|
+
const { I18n } = require("../../modules/chui_i18n/chui_i18n");
|
|
5
5
|
|
|
6
6
|
/** Идентификаторы вкладок для aria-controls/aria-labelledby */
|
|
7
|
-
let
|
|
7
|
+
let a11yTabCounter = 0;
|
|
8
8
|
|
|
9
9
|
class Tab {
|
|
10
|
-
#tab = document.createElement(
|
|
11
|
-
#
|
|
10
|
+
#tab = document.createElement("tab");
|
|
11
|
+
#tabContent = [];
|
|
12
12
|
#title = String();
|
|
13
13
|
#closable = false;
|
|
14
14
|
#close = undefined;
|
|
@@ -19,7 +19,7 @@ class Tab {
|
|
|
19
19
|
if (options.closable === true) this.setClosable(true);
|
|
20
20
|
}
|
|
21
21
|
addContent(...contents) {
|
|
22
|
-
for (
|
|
22
|
+
for (const content of contents) this.#tabContent.push(content);
|
|
23
23
|
}
|
|
24
24
|
getTab() {
|
|
25
25
|
return this.#tab;
|
|
@@ -28,7 +28,7 @@ class Tab {
|
|
|
28
28
|
return this.#title;
|
|
29
29
|
}
|
|
30
30
|
getContent() {
|
|
31
|
-
return this.#
|
|
31
|
+
return this.#tabContent;
|
|
32
32
|
}
|
|
33
33
|
/**
|
|
34
34
|
* Закрываемая вкладка: у неё появляется кнопка закрытия, а `Tabs` закрывает её
|
|
@@ -42,7 +42,7 @@ class Tab {
|
|
|
42
42
|
this.#close = document.createElement("button");
|
|
43
43
|
this.#close.type = "button";
|
|
44
44
|
this.#close.className = "tab_close";
|
|
45
|
-
this.#close.setAttribute("aria-label", I18n.t("navigation.closeTab", {title: this.#title}));
|
|
45
|
+
this.#close.setAttribute("aria-label", I18n.t("navigation.closeTab", { title: this.#title }));
|
|
46
46
|
this.#close.setAttribute("title", I18n.t("common.close"));
|
|
47
47
|
this.#close.appendChild(new Icon(Icons.NAVIGATION.CLOSE, "14px").set());
|
|
48
48
|
this.#tab.appendChild(this.#close);
|
|
@@ -72,25 +72,29 @@ class Tabs {
|
|
|
72
72
|
#active = -1;
|
|
73
73
|
// Вкладка, содержимое которой сейчас в панели: индекс меняется при закрытии соседей
|
|
74
74
|
#rendered = undefined;
|
|
75
|
-
#
|
|
76
|
-
#tabs = document.createElement(
|
|
77
|
-
#
|
|
78
|
-
#list = document.createElement(
|
|
79
|
-
#content = document.createElement(
|
|
80
|
-
#status = document.createElement(
|
|
81
|
-
|
|
82
|
-
#
|
|
75
|
+
#idContents = require("randomstring").generate();
|
|
76
|
+
#tabs = document.createElement("tabs");
|
|
77
|
+
#idList = require("randomstring").generate();
|
|
78
|
+
#list = document.createElement("list");
|
|
79
|
+
#content = document.createElement("content");
|
|
80
|
+
#status = document.createElement("tabs_status");
|
|
81
|
+
// Отложенный кадр пересчёта подложки выбранной вкладки
|
|
82
|
+
#indicatorFrame = undefined;
|
|
83
|
+
#onTabClose = undefined;
|
|
84
|
+
#animationendEvent = () => {
|
|
83
85
|
// Следы анимации снимаются точечно: `removeAttribute("style")` снёс бы и чужие
|
|
84
86
|
// инлайновые значения, если они появятся
|
|
85
87
|
this.#content.style.removeProperty("animation-name");
|
|
86
88
|
this.#content.style.removeProperty("transition");
|
|
87
89
|
this.#content.style.removeProperty("display");
|
|
88
90
|
};
|
|
89
|
-
constructor(
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
this.#
|
|
91
|
+
constructor(
|
|
92
|
+
options = { width: String(), default: Number(), tabs: [], closable: Boolean(), onTabClose: undefined }
|
|
93
|
+
) {
|
|
94
|
+
require("../../modules/chui_functions").setStyles(__dirname + "/styles.css", "chUiJS_Tabs");
|
|
95
|
+
this.#onTabClose = options.onTabClose;
|
|
96
|
+
this.#list.id = this.#idList;
|
|
97
|
+
this.#content.id = this.#idContents;
|
|
94
98
|
// Доступность: tablist/tab/tabpanel с roving tabindex
|
|
95
99
|
this.#list.setAttribute("role", "tablist");
|
|
96
100
|
this.#content.setAttribute("role", "tabpanel");
|
|
@@ -143,10 +147,9 @@ class Tabs {
|
|
|
143
147
|
* сразу становится активной.
|
|
144
148
|
*/
|
|
145
149
|
addTab(tab = undefined, index = undefined) {
|
|
146
|
-
if (tab === undefined || typeof tab.getTab !== "function")
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
: Math.max(0, Math.min(Number(index), this.#items.length));
|
|
150
|
+
if (tab === undefined || typeof tab.getTab !== "function")
|
|
151
|
+
throw new Error("Tabs.addTab(): нужен экземпляр Tab");
|
|
152
|
+
const at = index === undefined ? this.#items.length : Math.max(0, Math.min(Number(index), this.#items.length));
|
|
150
153
|
this.#items.splice(at, 0, tab);
|
|
151
154
|
this.#bindTab(tab, at);
|
|
152
155
|
// Новая вкладка встала не позже активной — активная сдвинулась на место вправо
|
|
@@ -165,8 +168,10 @@ class Tabs {
|
|
|
165
168
|
if (!Number.isInteger(at) || at < 0 || at >= this.#items.length) return this;
|
|
166
169
|
const tab = this.#items[at];
|
|
167
170
|
// Смотрим на вкладку, а не на её место: индекс активной мог сдвинуться при закрытии
|
|
168
|
-
const
|
|
169
|
-
|
|
171
|
+
const closingRendered = tab === this.#rendered;
|
|
172
|
+
// Уход идёт движением: узел убирается по концу кадра, а состав и индексы меняются
|
|
173
|
+
// сразу — иначе активная вкладка считалась бы по несуществующему узлу
|
|
174
|
+
this.#leaveNode(tab.getTab());
|
|
170
175
|
this.#items.splice(at, 1);
|
|
171
176
|
// Активная вкладка осталась собой, но её место сдвинулось
|
|
172
177
|
if (at < this.#active) this.#active -= 1;
|
|
@@ -175,14 +180,19 @@ class Tabs {
|
|
|
175
180
|
this.#rendered = undefined;
|
|
176
181
|
this.#content.innerHTML = "";
|
|
177
182
|
this.#content.removeAttribute("aria-labelledby");
|
|
178
|
-
this.#announce(I18n.t("navigation.tabClosedNothing", {title: tab.getTitle()}));
|
|
183
|
+
this.#announce(I18n.t("navigation.tabClosedNothing", { title: tab.getTitle() }));
|
|
179
184
|
return this;
|
|
180
185
|
}
|
|
181
|
-
if (
|
|
182
|
-
this.#activate(this.#active,
|
|
183
|
-
this.#announce(
|
|
184
|
-
|
|
185
|
-
|
|
186
|
+
if (closingRendered) this.#active = Math.min(at, this.#items.length - 1);
|
|
187
|
+
this.#activate(this.#active, closingRendered);
|
|
188
|
+
this.#announce(
|
|
189
|
+
closingRendered
|
|
190
|
+
? I18n.t("navigation.tabClosedOpened", {
|
|
191
|
+
title: tab.getTitle(),
|
|
192
|
+
active: this.#items[this.#active].getTitle(),
|
|
193
|
+
})
|
|
194
|
+
: I18n.t("navigation.tabClosed", { title: tab.getTitle() })
|
|
195
|
+
);
|
|
186
196
|
return this;
|
|
187
197
|
}
|
|
188
198
|
|
|
@@ -190,11 +200,11 @@ class Tabs {
|
|
|
190
200
|
// так `Tab.setClosable()` работает и после того, как вкладка встала в панель
|
|
191
201
|
#bindTab(tab = new Tab(), at = Number()) {
|
|
192
202
|
const node = tab.getTab();
|
|
193
|
-
if (node.id === undefined || node.id === "") node.id = "chui_a11y_tab_" + (
|
|
203
|
+
if (node.id === undefined || node.id === "") node.id = "chui_a11y_tab_" + (a11yTabCounter += 1);
|
|
194
204
|
node.setAttribute("role", "tab");
|
|
195
205
|
node.setAttribute("tabindex", "-1");
|
|
196
206
|
node.setAttribute("aria-selected", "false");
|
|
197
|
-
node.setAttribute("aria-controls", this.#
|
|
207
|
+
node.setAttribute("aria-controls", this.#idContents);
|
|
198
208
|
makeKeyboardButton(node, "tab");
|
|
199
209
|
node.addEventListener("click", () => this.#activate(this.#items.indexOf(tab), false));
|
|
200
210
|
const before = this.#list.children[at];
|
|
@@ -216,7 +226,7 @@ class Tabs {
|
|
|
216
226
|
#requestClose(tab = new Tab()) {
|
|
217
227
|
const at = this.#items.indexOf(tab);
|
|
218
228
|
if (at === -1 || !tab.isClosable()) return false;
|
|
219
|
-
if (this.#
|
|
229
|
+
if (this.#onTabClose !== undefined && this.#onTabClose(tab, at) === false) return false;
|
|
220
230
|
this.closeTab(at);
|
|
221
231
|
return true;
|
|
222
232
|
}
|
|
@@ -240,17 +250,61 @@ class Tabs {
|
|
|
240
250
|
this.#renderContent(tab);
|
|
241
251
|
this.#rendered = tab;
|
|
242
252
|
}
|
|
253
|
+
// Подложка выбранной вкладки: место и ширину снимаем по вёрстке
|
|
254
|
+
this.#scheduleIndicator();
|
|
243
255
|
if (focus) tab.getTab().focus();
|
|
244
256
|
return true;
|
|
245
257
|
}
|
|
246
258
|
|
|
259
|
+
/** Подложку двигают после раскладки: место вкладки читается только из вёрстки */
|
|
260
|
+
#scheduleIndicator() {
|
|
261
|
+
if (typeof requestAnimationFrame !== "function") {
|
|
262
|
+
this.#syncIndicator();
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
265
|
+
if (this.#indicatorFrame !== undefined) return;
|
|
266
|
+
this.#indicatorFrame = requestAnimationFrame(() => {
|
|
267
|
+
this.#indicatorFrame = undefined;
|
|
268
|
+
this.#syncIndicator();
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/** Уход узла: он гаснет и сходит вверх, а из документа убирается по концу кадра */
|
|
273
|
+
#leaveNode(node) {
|
|
274
|
+
node.classList.add("tab_leaving");
|
|
275
|
+
const done = (event) => {
|
|
276
|
+
if (event.target !== node) return;
|
|
277
|
+
node.removeEventListener("animationend", done);
|
|
278
|
+
node.remove();
|
|
279
|
+
};
|
|
280
|
+
node.addEventListener("animationend", done);
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* Место и ширина подложки выбранной вкладки. Ноль — выбора нет или вёрстки ещё нет:
|
|
285
|
+
* подложки нулевой ширины не видно, поэтому до первой раскладки вид прежний.
|
|
286
|
+
*/
|
|
287
|
+
#syncIndicator() {
|
|
288
|
+
const item = this.#items[this.#active];
|
|
289
|
+
const tab = item === undefined ? undefined : item.getTab();
|
|
290
|
+
if (tab === undefined || tab.offsetWidth === 0) {
|
|
291
|
+
this.#list.style.setProperty("--tabs_width", "0px");
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
294
|
+
// В RTL началом ряда служит правый край: подложка стоит у него и едет влево
|
|
295
|
+
const rtl = window.getComputedStyle(this.#list).direction === "rtl";
|
|
296
|
+
const x = rtl ? this.#list.clientWidth - (tab.offsetLeft + tab.offsetWidth) : tab.offsetLeft;
|
|
297
|
+
this.#list.style.setProperty("--tabs_offset", `${rtl ? -x : x}px`);
|
|
298
|
+
this.#list.style.setProperty("--tabs_width", `${tab.offsetWidth}px`);
|
|
299
|
+
}
|
|
300
|
+
|
|
247
301
|
#renderContent(tab = new Tab()) {
|
|
248
302
|
this.#content.innerHTML = "";
|
|
249
303
|
for (const con of tab.getContent()) this.#content.appendChild(con.set());
|
|
250
304
|
new Animation(this.#content).fadeIn();
|
|
251
305
|
// Анимация ставит инлайн-стиль: снимаем его по завершении, иначе он копится
|
|
252
|
-
this.#content.removeEventListener("animationend", this.#
|
|
253
|
-
this.#content.addEventListener("animationend", this.#
|
|
306
|
+
this.#content.removeEventListener("animationend", this.#animationendEvent);
|
|
307
|
+
this.#content.addEventListener("animationend", this.#animationendEvent);
|
|
254
308
|
}
|
|
255
309
|
|
|
256
310
|
#onListKeyDown = (event) => {
|
|
@@ -274,15 +328,15 @@ class Tabs {
|
|
|
274
328
|
};
|
|
275
329
|
|
|
276
330
|
// Активная вкладка: aria-selected, tabindex и связь с панелью
|
|
277
|
-
#applyAria(
|
|
331
|
+
#applyAria(activeTab) {
|
|
278
332
|
for (const item of this.#items) {
|
|
279
333
|
const tab = item.getTab();
|
|
280
|
-
const selected = tab ===
|
|
334
|
+
const selected = tab === activeTab;
|
|
281
335
|
tab.setAttribute("aria-selected", selected ? "true" : "false");
|
|
282
336
|
tab.setAttribute("tabindex", selected ? "0" : "-1");
|
|
283
337
|
}
|
|
284
|
-
if (
|
|
285
|
-
this.#content.setAttribute("aria-labelledby",
|
|
338
|
+
if (activeTab.id !== undefined && activeTab.id !== "") {
|
|
339
|
+
this.#content.setAttribute("aria-labelledby", activeTab.id);
|
|
286
340
|
}
|
|
287
341
|
}
|
|
288
342
|
|
|
@@ -295,5 +349,5 @@ class Tabs {
|
|
|
295
349
|
}
|
|
296
350
|
}
|
|
297
351
|
|
|
298
|
-
exports.Tab = Tab
|
|
299
|
-
exports.Tabs = Tabs
|
|
352
|
+
exports.Tab = Tab;
|
|
353
|
+
exports.Tabs = Tabs;
|
|
@@ -9,16 +9,38 @@ list {
|
|
|
9
9
|
вокруг которого вкладки плавали без границ */
|
|
10
10
|
padding: 3px;
|
|
11
11
|
border: 1px solid var(--border_color);
|
|
12
|
-
border-radius: var(--
|
|
12
|
+
border-radius: var(--radius_sm);
|
|
13
13
|
background: var(--element_background);
|
|
14
|
-
margin: var(--
|
|
14
|
+
margin: var(--block_margin) 0;
|
|
15
|
+
/* Место и ширина подложки выбранной вкладки: считает JS по вёрстке, нули — выбора нет */
|
|
16
|
+
--tabs_offset: 0px;
|
|
17
|
+
--tabs_width: 0px;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/* Подложка выбранной вкладки: одна и та же деталь переезжает между вкладками, вместо
|
|
21
|
+
мгновенной смены заливки — как у SegmentedControl. Отступ по вертикали равен отступу
|
|
22
|
+
дорожки, поэтому подложка встаёт в ряд вкладок */
|
|
23
|
+
list::before {
|
|
24
|
+
content: "";
|
|
25
|
+
position: absolute;
|
|
26
|
+
z-index: 0;
|
|
27
|
+
inset-block: 3px;
|
|
28
|
+
inset-inline-start: 0;
|
|
29
|
+
width: var(--tabs_width);
|
|
30
|
+
border-radius: var(--radius_sm);
|
|
31
|
+
background: var(--blue_prime_background);
|
|
32
|
+
transform: translateX(var(--tabs_offset));
|
|
33
|
+
transition:
|
|
34
|
+
transform var(--motion_base) var(--motion_ease),
|
|
35
|
+
width var(--motion_base) var(--motion_ease);
|
|
36
|
+
pointer-events: none;
|
|
15
37
|
}
|
|
16
38
|
|
|
17
39
|
tab {
|
|
18
40
|
cursor: pointer;
|
|
19
41
|
/* Отступ даёт только `gap` дорожки: свой `margin` добавлял к нему ещё по 1 px
|
|
20
42
|
и дорожка вырастала на 2 px без причины */
|
|
21
|
-
padding: var(--
|
|
43
|
+
padding: var(--block_padding_sm);
|
|
22
44
|
min-height: var(--control_height);
|
|
23
45
|
box-sizing: border-box;
|
|
24
46
|
font-size: var(--font_default_size);
|
|
@@ -28,12 +50,13 @@ tab {
|
|
|
28
50
|
gap: 4px;
|
|
29
51
|
font-weight: 500;
|
|
30
52
|
color: var(--text_color);
|
|
31
|
-
border-radius: var(--
|
|
53
|
+
border-radius: var(--radius_sm);
|
|
32
54
|
}
|
|
33
55
|
|
|
34
56
|
/* Наведение — нейтральная тонировка, а не заливка во весь акцент: полная заливка
|
|
35
|
-
срабатывала на каждое наведение и перетягивала внимание (то же решение, что у Button)
|
|
36
|
-
|
|
57
|
+
срабатывала на каждое наведение и перетягивала внимание (то же решение, что у Button).
|
|
58
|
+
У выбранной вкладки заливку несёт подложка, поэтому она наведение не ловит */
|
|
59
|
+
tab:not(.tab_active):hover {
|
|
37
60
|
background: var(--element_background_hover);
|
|
38
61
|
}
|
|
39
62
|
|
|
@@ -43,35 +66,40 @@ tab:active {
|
|
|
43
66
|
}
|
|
44
67
|
|
|
45
68
|
tabs {
|
|
46
|
-
margin: var(--
|
|
69
|
+
margin: var(--block_margin);
|
|
47
70
|
display: flex;
|
|
48
71
|
flex-direction: column;
|
|
49
72
|
justify-content: flex-start;
|
|
50
|
-
align-items: flex-start
|
|
73
|
+
align-items: flex-start;
|
|
51
74
|
}
|
|
52
75
|
|
|
53
76
|
content {
|
|
54
77
|
display: flex;
|
|
55
|
-
flex-direction:column;
|
|
78
|
+
flex-direction: column;
|
|
56
79
|
width: -webkit-fill-available;
|
|
57
80
|
padding: var(--control_padding);
|
|
58
|
-
border-radius: var(--
|
|
81
|
+
border-radius: var(--radius_sm);
|
|
59
82
|
background: transparent;
|
|
60
83
|
border: none;
|
|
61
84
|
}
|
|
62
85
|
|
|
63
86
|
.tab_active {
|
|
64
|
-
/* Выбранная вкладка —
|
|
87
|
+
/* Выбранная вкладка — белый текст на подложке-акценте, как у выбранного сегмента
|
|
65
88
|
SegmentedControl и у нажатой Button. Прежняя «тонировка + акцентный текст» давала
|
|
66
89
|
синий текст на синей тонировке (контраст ≈2.5:1) и читалась грязным пятном */
|
|
67
|
-
background:
|
|
90
|
+
background: transparent;
|
|
68
91
|
color: var(--text_color_hover);
|
|
69
92
|
font-weight: 600;
|
|
70
93
|
}
|
|
71
94
|
|
|
72
|
-
/*
|
|
95
|
+
/* Уход закрываемой вкладки: она гаснет и сходит вверх, а из дорожки убирается по концу кадра */
|
|
96
|
+
.tab_leaving {
|
|
97
|
+
animation: chui_leave_up var(--motion_fast) var(--motion_ease) forwards;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/* Наведение на выбранной вкладке ничего не меняет: отклик уже в самой подложке */
|
|
73
101
|
.tab_active:hover {
|
|
74
|
-
background:
|
|
102
|
+
background: transparent;
|
|
75
103
|
color: var(--text_color_hover);
|
|
76
104
|
}
|
|
77
105
|
|
|
@@ -96,7 +124,7 @@ tab:has(.tab_close) {
|
|
|
96
124
|
/* Цвет наследуется от вкладки: крестик не отваливается от подписи, а наглухо
|
|
97
125
|
серый читался в ней случайной точкой */
|
|
98
126
|
color: inherit;
|
|
99
|
-
opacity: .6;
|
|
127
|
+
opacity: 0.6;
|
|
100
128
|
cursor: pointer;
|
|
101
129
|
}
|
|
102
130
|
|