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, markdownToHtml, htmlToMarkdown, optionOr} = require(
|
|
1
|
+
const { setStyles, markdownToHtml, htmlToMarkdown, optionOr } = require("../../modules/chui_functions");
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Всплывающая подсказка (тултип) к любому элементу.
|
|
@@ -24,7 +24,7 @@ class Tooltip {
|
|
|
24
24
|
TOP: "top",
|
|
25
25
|
BOTTOM: "bottom",
|
|
26
26
|
LEFT: "left",
|
|
27
|
-
RIGHT: "right"
|
|
27
|
+
RIGHT: "right",
|
|
28
28
|
};
|
|
29
29
|
/** Зазор между целью и подсказкой, px */
|
|
30
30
|
static GAP = 8;
|
|
@@ -45,18 +45,20 @@ class Tooltip {
|
|
|
45
45
|
// destroy() сделан окончательным: после него инстанс не показывает подсказку и не вешает описания
|
|
46
46
|
#destroyed = false;
|
|
47
47
|
|
|
48
|
-
constructor(
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
48
|
+
constructor(
|
|
49
|
+
options = {
|
|
50
|
+
id: String(),
|
|
51
|
+
text: String(),
|
|
52
|
+
markdownText: String(),
|
|
53
|
+
placement: String(),
|
|
54
|
+
delay: Number(),
|
|
55
|
+
}
|
|
56
|
+
) {
|
|
55
57
|
setStyles(__dirname + "/styles.css", "chUiJS_Tooltip");
|
|
56
58
|
// Пустая заготовка опции равносильна отсутствующей
|
|
57
59
|
const text = optionOr(options.text, undefined);
|
|
58
|
-
const
|
|
59
|
-
if (text !== undefined &&
|
|
60
|
+
const markdownText = optionOr(options.markdownText, undefined);
|
|
61
|
+
if (text !== undefined && markdownText !== undefined) {
|
|
60
62
|
throw new Error("Должна быть установлена одна опция text или markdownText");
|
|
61
63
|
}
|
|
62
64
|
Tooltip.#counter += 1;
|
|
@@ -68,7 +70,7 @@ class Tooltip {
|
|
|
68
70
|
this.#tooltip.id = this.#id;
|
|
69
71
|
this.#tooltip.setAttribute("role", "tooltip");
|
|
70
72
|
if (text !== undefined) this.#tooltip.innerText = text;
|
|
71
|
-
if (
|
|
73
|
+
if (markdownText !== undefined) this.#tooltip.innerHTML = markdownToHtml(markdownText);
|
|
72
74
|
// Элемент живёт в body: координаты считаются в системе окна (position: fixed),
|
|
73
75
|
// а внутри карточек с backdrop-filter/filter предок стал бы системой отсчёта.
|
|
74
76
|
document.body.appendChild(this.#tooltip);
|
|
@@ -119,11 +121,15 @@ class Tooltip {
|
|
|
119
121
|
if (this.#destroyed) return this;
|
|
120
122
|
const element = Tooltip.#resolve(target);
|
|
121
123
|
if (element === undefined || element === null) return this;
|
|
122
|
-
if (this.#targets.some(entry => entry.element === element)) return this;
|
|
124
|
+
if (this.#targets.some((entry) => entry.element === element)) return this;
|
|
123
125
|
// Описание вешается на фокусируемый узел: у обёртки-компонента (Button → chui_button)
|
|
124
126
|
// свой aria-describedby скринридеру не достаётся — читают кнопку, а не обёртку
|
|
125
127
|
const described = Tooltip.#describedTarget(element);
|
|
126
|
-
const entry = {
|
|
128
|
+
const entry = {
|
|
129
|
+
element: element,
|
|
130
|
+
described: described,
|
|
131
|
+
describedBy: described.getAttribute("aria-describedby"),
|
|
132
|
+
};
|
|
127
133
|
entry.onMouseEnter = () => this.#scheduleShow(element);
|
|
128
134
|
entry.onMouseLeave = (event) => {
|
|
129
135
|
// Переход внутрь цели (к её детям) подсказку не закрывает
|
|
@@ -153,7 +159,7 @@ class Tooltip {
|
|
|
153
159
|
|
|
154
160
|
detach(target) {
|
|
155
161
|
const element = Tooltip.#resolve(target);
|
|
156
|
-
const index = this.#targets.findIndex(entry => entry.element === element);
|
|
162
|
+
const index = this.#targets.findIndex((entry) => entry.element === element);
|
|
157
163
|
if (index === -1) return this;
|
|
158
164
|
const entry = this.#targets[index];
|
|
159
165
|
element.removeEventListener("mouseenter", entry.onMouseEnter);
|
|
@@ -170,9 +176,12 @@ class Tooltip {
|
|
|
170
176
|
// ПОКАЗ / СКРЫТИЕ
|
|
171
177
|
show(target = undefined) {
|
|
172
178
|
if (this.#destroyed || !document.body.contains(this.#tooltip)) return;
|
|
173
|
-
const element =
|
|
174
|
-
|
|
175
|
-
|
|
179
|
+
const element =
|
|
180
|
+
target === undefined
|
|
181
|
+
? this.#current !== undefined
|
|
182
|
+
? this.#current
|
|
183
|
+
: Tooltip.#resolve((this.#targets[0] || {}).element)
|
|
184
|
+
: Tooltip.#resolve(target);
|
|
176
185
|
if (element === undefined || element === null || !document.body.contains(element)) return;
|
|
177
186
|
this.#clearTimer();
|
|
178
187
|
this.#current = element;
|
|
@@ -224,7 +233,7 @@ class Tooltip {
|
|
|
224
233
|
}
|
|
225
234
|
const ids = String(entry.describedBy === null ? "" : entry.describedBy)
|
|
226
235
|
.split(/\s+/)
|
|
227
|
-
.filter(id => id !== "");
|
|
236
|
+
.filter((id) => id !== "");
|
|
228
237
|
if (!ids.includes(this.#id)) ids.push(this.#id);
|
|
229
238
|
entry.described.setAttribute("aria-describedby", ids.join(" "));
|
|
230
239
|
}
|
|
@@ -265,9 +274,12 @@ class Tooltip {
|
|
|
265
274
|
let placement = this.#placement;
|
|
266
275
|
// Флип на противоположную сторону, если по выбранной подсказка не помещается
|
|
267
276
|
if (placement === Tooltip.PLACEMENT.TOP && rect.top - height - gap < edge) placement = Tooltip.PLACEMENT.BOTTOM;
|
|
268
|
-
else if (placement === Tooltip.PLACEMENT.BOTTOM && rect.bottom + height + gap > window.innerHeight - edge)
|
|
269
|
-
|
|
270
|
-
else if (placement === Tooltip.PLACEMENT.
|
|
277
|
+
else if (placement === Tooltip.PLACEMENT.BOTTOM && rect.bottom + height + gap > window.innerHeight - edge)
|
|
278
|
+
placement = Tooltip.PLACEMENT.TOP;
|
|
279
|
+
else if (placement === Tooltip.PLACEMENT.LEFT && rect.left - width - gap < edge)
|
|
280
|
+
placement = Tooltip.PLACEMENT.RIGHT;
|
|
281
|
+
else if (placement === Tooltip.PLACEMENT.RIGHT && rect.right + width + gap > window.innerWidth - edge)
|
|
282
|
+
placement = Tooltip.PLACEMENT.LEFT;
|
|
271
283
|
|
|
272
284
|
let left, top;
|
|
273
285
|
if (placement === Tooltip.PLACEMENT.LEFT || placement === Tooltip.PLACEMENT.RIGHT) {
|
|
@@ -303,10 +315,11 @@ class Tooltip {
|
|
|
303
315
|
#scheduleShow(element) {
|
|
304
316
|
if (!document.body.contains(element)) return;
|
|
305
317
|
this.#clearTimer();
|
|
306
|
-
if (this.#delay > 0)
|
|
307
|
-
this.#timer =
|
|
308
|
-
|
|
309
|
-
|
|
318
|
+
if (this.#delay > 0)
|
|
319
|
+
this.#timer = setTimeout(() => {
|
|
320
|
+
this.#timer = undefined;
|
|
321
|
+
this.show(element);
|
|
322
|
+
}, this.#delay);
|
|
310
323
|
else this.show(element);
|
|
311
324
|
}
|
|
312
325
|
|
|
@@ -317,4 +330,4 @@ class Tooltip {
|
|
|
317
330
|
}
|
|
318
331
|
}
|
|
319
332
|
|
|
320
|
-
exports.Tooltip = Tooltip
|
|
333
|
+
exports.Tooltip = Tooltip;
|
|
@@ -16,11 +16,16 @@ chui_tour {
|
|
|
16
16
|
Тень обрезается слоем, поэтому не вылезает за окно. */
|
|
17
17
|
tour_highlight {
|
|
18
18
|
position: absolute;
|
|
19
|
-
border-radius: var(--
|
|
20
|
-
box-shadow:
|
|
19
|
+
border-radius: var(--radius_sm);
|
|
20
|
+
box-shadow:
|
|
21
|
+
0 0 0 1px var(--blue_prime_background),
|
|
22
|
+
0 0 0 9999px var(--modal_scrim);
|
|
21
23
|
pointer-events: none;
|
|
22
|
-
transition:
|
|
23
|
-
|
|
24
|
+
transition:
|
|
25
|
+
left var(--motion_base) var(--motion_ease),
|
|
26
|
+
top var(--motion_base) var(--motion_ease),
|
|
27
|
+
width var(--motion_base) var(--motion_ease),
|
|
28
|
+
height var(--motion_base) var(--motion_ease);
|
|
24
29
|
}
|
|
25
30
|
|
|
26
31
|
/* Без затемнения остаётся только рамка подсветки */
|
|
@@ -82,7 +87,7 @@ chui_tour tour_counter {
|
|
|
82
87
|
height: var(--toolbar_control_size);
|
|
83
88
|
margin: 0;
|
|
84
89
|
padding: 0;
|
|
85
|
-
border-radius: var(--
|
|
90
|
+
border-radius: var(--radius_sm);
|
|
86
91
|
background: var(--button_background);
|
|
87
92
|
border: 1px solid var(--button_border_color);
|
|
88
93
|
color: var(--text_color);
|
|
@@ -115,8 +120,8 @@ chui_tour tour_counter {
|
|
|
115
120
|
.tour_next:hover {
|
|
116
121
|
/* Главное действие остаётся акцентным и под курсором: фон лишь чуть
|
|
117
122
|
разжижается, текст остаётся белым — иначе тёмное по синему */
|
|
118
|
-
background: var(--
|
|
119
|
-
border-color: var(--
|
|
123
|
+
background: var(--blue_prime_background_tint_strong);
|
|
124
|
+
border-color: var(--blue_prime_background_tint_strong);
|
|
120
125
|
color: var(--text_color_hover);
|
|
121
126
|
}
|
|
122
127
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
const { setStyles, markdownToHtml, optionOr } = require(
|
|
2
|
-
const { OverlayA11y } = require(
|
|
3
|
-
const { Popover } = require(
|
|
4
|
-
const { Icon, Icons } = require(
|
|
5
|
-
const { I18n } = require(
|
|
1
|
+
const { setStyles, markdownToHtml, optionOr } = require("../../modules/chui_functions");
|
|
2
|
+
const { OverlayA11y } = require("../../modules/chui_a11y/chui_a11y");
|
|
3
|
+
const { Popover } = require("../chui_popover/popover");
|
|
4
|
+
const { Icon, Icons } = require("../chui_icons/icons");
|
|
5
|
+
const { I18n } = require("../../modules/chui_i18n/chui_i18n");
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Пошаговое знакомство с интерфейсом: затемнённая подложка с «окном» вокруг цели
|
|
@@ -44,7 +44,7 @@ class Tour {
|
|
|
44
44
|
TOP: "top",
|
|
45
45
|
BOTTOM: "bottom",
|
|
46
46
|
LEFT: "left",
|
|
47
|
-
RIGHT: "right"
|
|
47
|
+
RIGHT: "right",
|
|
48
48
|
};
|
|
49
49
|
/** Зазор вокруг подсвеченной цели, px */
|
|
50
50
|
static PADDING = 6;
|
|
@@ -55,46 +55,55 @@ class Tour {
|
|
|
55
55
|
skip: Icons.AUDIO_VIDEO.SKIP_NEXT,
|
|
56
56
|
prev: Icons.NAVIGATION.ARROW_BACK,
|
|
57
57
|
next: Icons.NAVIGATION.ARROW_FORWARD,
|
|
58
|
-
finish: Icons.ACTIONS.DONE
|
|
58
|
+
finish: Icons.ACTIONS.DONE,
|
|
59
59
|
};
|
|
60
60
|
|
|
61
61
|
#id = require("randomstring").generate();
|
|
62
62
|
#layer = document.createElement("chui_tour");
|
|
63
63
|
#highlight = document.createElement("tour_highlight");
|
|
64
64
|
// Объявление для скринридера: узел носит класс общей утилиты скрытия (по нему его узнают стенды)
|
|
65
|
-
#status = Object.assign(document.createElement("chui_visually_hidden"), {className: "chui_visually_hidden"});
|
|
65
|
+
#status = Object.assign(document.createElement("chui_visually_hidden"), { className: "chui_visually_hidden" });
|
|
66
66
|
#popover = undefined;
|
|
67
67
|
#head = document.createElement("tour_head");
|
|
68
68
|
#title = document.createElement("tour_title");
|
|
69
|
-
#
|
|
69
|
+
#closeButton = document.createElement("button");
|
|
70
70
|
#text = document.createElement("tour_text");
|
|
71
71
|
#footer = document.createElement("tour_footer");
|
|
72
72
|
#counter = document.createElement("tour_counter");
|
|
73
|
-
#
|
|
74
|
-
#
|
|
75
|
-
#
|
|
73
|
+
#skipButton = document.createElement("button");
|
|
74
|
+
#prevButton = document.createElement("button");
|
|
75
|
+
#nextButton = document.createElement("button");
|
|
76
76
|
/** Значок кнопки «Далее»: на последнем шаге меняется на галочку «Готово» */
|
|
77
|
-
#
|
|
77
|
+
#nextIcon = undefined;
|
|
78
78
|
#steps = [];
|
|
79
79
|
#active = [];
|
|
80
80
|
#index = 0;
|
|
81
81
|
#mask = true;
|
|
82
82
|
#closable = true;
|
|
83
83
|
#keyboard = true;
|
|
84
|
-
#
|
|
84
|
+
#scrollIntoViewEnabled = true;
|
|
85
85
|
#label = undefined;
|
|
86
|
-
#
|
|
86
|
+
#isOpen = false;
|
|
87
87
|
#a11y = undefined;
|
|
88
|
-
#
|
|
89
|
-
#
|
|
90
|
-
#
|
|
88
|
+
#onFinish = undefined;
|
|
89
|
+
#onClose = undefined;
|
|
90
|
+
#onChange = undefined;
|
|
91
91
|
#destroyed = false;
|
|
92
92
|
|
|
93
|
-
constructor(
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
93
|
+
constructor(
|
|
94
|
+
options = {
|
|
95
|
+
id: String(),
|
|
96
|
+
steps: [],
|
|
97
|
+
mask: Boolean(),
|
|
98
|
+
closable: Boolean(),
|
|
99
|
+
keyboard: Boolean(),
|
|
100
|
+
scrollIntoView: Boolean(),
|
|
101
|
+
label: String(),
|
|
102
|
+
onFinish: undefined,
|
|
103
|
+
onClose: undefined,
|
|
104
|
+
onChange: undefined,
|
|
105
|
+
}
|
|
106
|
+
) {
|
|
98
107
|
setStyles(__dirname + "/styles.css", "chUiJS_Tour");
|
|
99
108
|
this.#steps = Array.isArray(options.steps) ? options.steps : [];
|
|
100
109
|
// Заготовка опции (`String()`) равносильна отсутствующей: иначе слой без аргументов
|
|
@@ -104,11 +113,11 @@ class Tour {
|
|
|
104
113
|
if (options.mask !== undefined) this.#mask = options.mask !== false;
|
|
105
114
|
if (options.closable !== undefined) this.#closable = options.closable !== false;
|
|
106
115
|
if (options.keyboard !== undefined) this.#keyboard = options.keyboard !== false;
|
|
107
|
-
if (options.scrollIntoView !== undefined) this.#
|
|
116
|
+
if (options.scrollIntoView !== undefined) this.#scrollIntoViewEnabled = options.scrollIntoView !== false;
|
|
108
117
|
this.#label = options.label;
|
|
109
|
-
this.#
|
|
110
|
-
this.#
|
|
111
|
-
this.#
|
|
118
|
+
this.#onFinish = options.onFinish;
|
|
119
|
+
this.#onClose = options.onClose;
|
|
120
|
+
this.#onChange = options.onChange;
|
|
112
121
|
|
|
113
122
|
this.#layer.id = this.#id;
|
|
114
123
|
this.#layer.dataset.mask = this.#mask ? "true" : "false";
|
|
@@ -117,32 +126,32 @@ class Tour {
|
|
|
117
126
|
this.#title.id = `${this.#id}_title`;
|
|
118
127
|
this.#text.id = `${this.#id}_text`;
|
|
119
128
|
// Кнопки создаются один раз: шаги только меняют их значки, имена и видимость
|
|
120
|
-
this.#
|
|
121
|
-
this.#
|
|
122
|
-
this.#
|
|
123
|
-
this.#
|
|
124
|
-
this.#
|
|
125
|
-
this.#
|
|
126
|
-
this.#
|
|
127
|
-
this.#
|
|
128
|
-
this.#
|
|
129
|
-
this.#
|
|
130
|
-
this.#
|
|
131
|
-
this.#
|
|
132
|
-
this.#
|
|
133
|
-
this.#nameButton(this.#
|
|
134
|
-
this.#nameButton(this.#
|
|
135
|
-
this.#nameButton(this.#
|
|
136
|
-
this.#
|
|
137
|
-
this.#
|
|
138
|
-
this.#
|
|
139
|
-
this.#
|
|
129
|
+
this.#closeButton.type = "button";
|
|
130
|
+
this.#closeButton.className = "tour_button tour_close";
|
|
131
|
+
this.#closeButton.appendChild(new Icon(Icons.NAVIGATION.CLOSE, "18px").set());
|
|
132
|
+
this.#skipButton.type = "button";
|
|
133
|
+
this.#skipButton.className = "tour_button tour_skip";
|
|
134
|
+
this.#skipButton.appendChild(new Icon(Tour.#ICONS.skip, "18px").set());
|
|
135
|
+
this.#prevButton.type = "button";
|
|
136
|
+
this.#prevButton.className = "tour_button tour_prev";
|
|
137
|
+
this.#prevButton.appendChild(new Icon(Tour.#ICONS.prev, "18px").set());
|
|
138
|
+
this.#nextButton.type = "button";
|
|
139
|
+
this.#nextButton.className = "tour_button tour_next";
|
|
140
|
+
this.#nextIcon = new Icon(Tour.#ICONS.next, "18px");
|
|
141
|
+
this.#nextButton.appendChild(this.#nextIcon.set());
|
|
142
|
+
this.#nameButton(this.#skipButton, "feedback.tourSkip");
|
|
143
|
+
this.#nameButton(this.#prevButton, "feedback.tourPrev");
|
|
144
|
+
this.#nameButton(this.#nextButton, "feedback.tourNext");
|
|
145
|
+
this.#closeButton.addEventListener("click", this.#onCloseClick);
|
|
146
|
+
this.#skipButton.addEventListener("click", this.#onCloseClick);
|
|
147
|
+
this.#prevButton.addEventListener("click", this.#onPrevClick);
|
|
148
|
+
this.#nextButton.addEventListener("click", this.#onNextClick);
|
|
140
149
|
this.#head.appendChild(this.#title);
|
|
141
|
-
this.#head.appendChild(this.#
|
|
150
|
+
this.#head.appendChild(this.#closeButton);
|
|
142
151
|
this.#footer.appendChild(this.#counter);
|
|
143
|
-
this.#footer.appendChild(this.#
|
|
144
|
-
this.#footer.appendChild(this.#
|
|
145
|
-
this.#footer.appendChild(this.#
|
|
152
|
+
this.#footer.appendChild(this.#skipButton);
|
|
153
|
+
this.#footer.appendChild(this.#prevButton);
|
|
154
|
+
this.#footer.appendChild(this.#nextButton);
|
|
146
155
|
this.#layer.appendChild(this.#highlight);
|
|
147
156
|
this.#layer.appendChild(this.#status);
|
|
148
157
|
// Подсказка — готовый Popover: он сам держит место у цели, следит за прокруткой
|
|
@@ -159,11 +168,11 @@ class Tour {
|
|
|
159
168
|
this.#a11y = new OverlayA11y(this.#layer, {
|
|
160
169
|
role: "dialog",
|
|
161
170
|
describedBy: this.#text,
|
|
162
|
-
onEscape: () => this.close()
|
|
171
|
+
onEscape: () => this.close(),
|
|
163
172
|
});
|
|
164
173
|
this.#a11y.setLabel(this.#label === undefined ? I18n.t("feedback.tourLabel") : this.#label);
|
|
165
|
-
this.#
|
|
166
|
-
this.#
|
|
174
|
+
this.#closeButton.setAttribute("aria-label", I18n.t("a11y.closeDialog"));
|
|
175
|
+
this.#closeButton.setAttribute("title", I18n.t("a11y.closeDialog"));
|
|
167
176
|
this.#layer.addEventListener("keydown", this.#onKeyDown);
|
|
168
177
|
window.addEventListener("resize", this.#onWindowChange);
|
|
169
178
|
window.addEventListener("scroll", this.#onWindowChange, true);
|
|
@@ -172,17 +181,20 @@ class Tour {
|
|
|
172
181
|
// ПОКАЗ / СКРЫТИЕ
|
|
173
182
|
/** Начать знакомство с первого шага; шаги без найденной цели в него не попадают */
|
|
174
183
|
start() {
|
|
175
|
-
if (this.#destroyed || this.#
|
|
176
|
-
this.#active = this.#steps.filter(
|
|
184
|
+
if (this.#destroyed || this.#isOpen) return this;
|
|
185
|
+
this.#active = this.#steps.filter(
|
|
186
|
+
(step) =>
|
|
187
|
+
step !== undefined && step !== null && (step.target === undefined || this.#targetOf(step) !== undefined)
|
|
188
|
+
);
|
|
177
189
|
if (this.#active.length === 0) return this;
|
|
178
190
|
this.#index = 0;
|
|
179
|
-
this.#
|
|
191
|
+
this.#isOpen = true;
|
|
180
192
|
this.#layer.style.display = "flex";
|
|
181
193
|
// Тексты берём в момент запуска: язык мог смениться после создания компонента
|
|
182
194
|
this.#a11y.setLabel(this.#label === undefined ? I18n.t("feedback.tourLabel") : this.#label);
|
|
183
|
-
this.#
|
|
184
|
-
this.#
|
|
185
|
-
this.#nameButton(this.#
|
|
195
|
+
this.#closeButton.setAttribute("aria-label", I18n.t("a11y.closeDialog"));
|
|
196
|
+
this.#closeButton.setAttribute("title", I18n.t("a11y.closeDialog"));
|
|
197
|
+
this.#nameButton(this.#skipButton, "feedback.tourSkip");
|
|
186
198
|
this.#a11y.open();
|
|
187
199
|
this.#applyStep(true);
|
|
188
200
|
return this;
|
|
@@ -190,7 +202,7 @@ class Tour {
|
|
|
190
202
|
|
|
191
203
|
/** Следующий шаг или завершение, если он последний */
|
|
192
204
|
next() {
|
|
193
|
-
if (!this.#
|
|
205
|
+
if (!this.#isOpen) return this;
|
|
194
206
|
if (this.#index >= this.#active.length - 1) return this.finish();
|
|
195
207
|
this.#index += 1;
|
|
196
208
|
this.#applyStep(false);
|
|
@@ -198,14 +210,14 @@ class Tour {
|
|
|
198
210
|
}
|
|
199
211
|
|
|
200
212
|
prev() {
|
|
201
|
-
if (!this.#
|
|
213
|
+
if (!this.#isOpen || this.#index === 0) return this;
|
|
202
214
|
this.#index -= 1;
|
|
203
215
|
this.#applyStep(false);
|
|
204
216
|
return this;
|
|
205
217
|
}
|
|
206
218
|
|
|
207
219
|
goTo(index = Number()) {
|
|
208
|
-
if (!this.#
|
|
220
|
+
if (!this.#isOpen) return this;
|
|
209
221
|
const position = Math.max(0, Math.min(Number(index) || 0, this.#active.length - 1));
|
|
210
222
|
if (position === this.#index) return this;
|
|
211
223
|
this.#index = position;
|
|
@@ -223,15 +235,23 @@ class Tour {
|
|
|
223
235
|
return this.#end(false);
|
|
224
236
|
}
|
|
225
237
|
|
|
226
|
-
isOpen() {
|
|
238
|
+
isOpen() {
|
|
239
|
+
return this.#isOpen;
|
|
240
|
+
}
|
|
227
241
|
/** Номер текущего шага; вне знакомства — 0 */
|
|
228
|
-
getIndex() {
|
|
229
|
-
|
|
242
|
+
getIndex() {
|
|
243
|
+
return this.#index;
|
|
244
|
+
}
|
|
245
|
+
getSteps() {
|
|
246
|
+
return [...this.#steps];
|
|
247
|
+
}
|
|
230
248
|
setSteps(steps = []) {
|
|
231
249
|
this.#steps = Array.isArray(steps) ? steps : [];
|
|
232
250
|
return this;
|
|
233
251
|
}
|
|
234
|
-
getId() {
|
|
252
|
+
getId() {
|
|
253
|
+
return this.#id;
|
|
254
|
+
}
|
|
235
255
|
|
|
236
256
|
/** Полное удаление: знакомство закрывается без уведомлений, слой и поповер убираются */
|
|
237
257
|
destroy() {
|
|
@@ -240,12 +260,12 @@ class Tour {
|
|
|
240
260
|
window.removeEventListener("resize", this.#onWindowChange);
|
|
241
261
|
window.removeEventListener("scroll", this.#onWindowChange, true);
|
|
242
262
|
this.#layer.removeEventListener("keydown", this.#onKeyDown);
|
|
243
|
-
this.#
|
|
244
|
-
this.#
|
|
245
|
-
this.#
|
|
246
|
-
this.#
|
|
247
|
-
if (this.#
|
|
248
|
-
this.#
|
|
263
|
+
this.#closeButton.removeEventListener("click", this.#onCloseClick);
|
|
264
|
+
this.#skipButton.removeEventListener("click", this.#onCloseClick);
|
|
265
|
+
this.#prevButton.removeEventListener("click", this.#onPrevClick);
|
|
266
|
+
this.#nextButton.removeEventListener("click", this.#onNextClick);
|
|
267
|
+
if (this.#isOpen) {
|
|
268
|
+
this.#isOpen = false;
|
|
249
269
|
this.#popover.close();
|
|
250
270
|
this.#a11y.close();
|
|
251
271
|
}
|
|
@@ -254,7 +274,9 @@ class Tour {
|
|
|
254
274
|
return this;
|
|
255
275
|
}
|
|
256
276
|
|
|
257
|
-
set() {
|
|
277
|
+
set() {
|
|
278
|
+
return this.#layer;
|
|
279
|
+
}
|
|
258
280
|
|
|
259
281
|
// === ВНУТРЕННЕЕ ===
|
|
260
282
|
/**
|
|
@@ -268,17 +290,17 @@ class Tour {
|
|
|
268
290
|
}
|
|
269
291
|
|
|
270
292
|
#end(completed = false) {
|
|
271
|
-
if (!this.#
|
|
293
|
+
if (!this.#isOpen) return this;
|
|
272
294
|
const index = this.#index;
|
|
273
|
-
this.#
|
|
295
|
+
this.#isOpen = false;
|
|
274
296
|
this.#popover.close();
|
|
275
297
|
this.#clearTriggerAria();
|
|
276
298
|
this.#a11y.close();
|
|
277
299
|
this.#layer.style.display = "none";
|
|
278
300
|
if (completed) {
|
|
279
|
-
if (this.#
|
|
280
|
-
} else if (this.#
|
|
281
|
-
this.#
|
|
301
|
+
if (this.#onFinish !== undefined) this.#onFinish();
|
|
302
|
+
} else if (this.#onClose !== undefined) {
|
|
303
|
+
this.#onClose(index);
|
|
282
304
|
}
|
|
283
305
|
return this;
|
|
284
306
|
}
|
|
@@ -300,24 +322,26 @@ class Tour {
|
|
|
300
322
|
this.#popover.set().setAttribute("aria-labelledby", this.#title.id);
|
|
301
323
|
this.#popover.set().removeAttribute("aria-label");
|
|
302
324
|
}
|
|
303
|
-
const
|
|
325
|
+
const hasText = step.text !== undefined || step.markdownText !== undefined;
|
|
304
326
|
if (step.markdownText !== undefined) this.#text.innerHTML = markdownToHtml(step.markdownText);
|
|
305
327
|
else if (step.text !== undefined) this.#text.innerText = String(step.text);
|
|
306
328
|
// Счётчик, значки и видимость закрывающих кнопок
|
|
307
|
-
this.#counter.innerText = I18n.t("feedback.tourStepOf", {index: this.#index + 1, total: this.#active.length});
|
|
308
|
-
this.#nameButton(this.#
|
|
329
|
+
this.#counter.innerText = I18n.t("feedback.tourStepOf", { index: this.#index + 1, total: this.#active.length });
|
|
330
|
+
this.#nameButton(this.#prevButton, "feedback.tourPrev");
|
|
309
331
|
// Последний шаг: «Далее» становится «Готово» — вместе с именем меняется и значок
|
|
310
|
-
this.#nameButton(this.#
|
|
311
|
-
this.#
|
|
312
|
-
this.#
|
|
313
|
-
this.#
|
|
314
|
-
this.#
|
|
315
|
-
this.#popover.setContent([this.#head,
|
|
332
|
+
this.#nameButton(this.#nextButton, last ? "feedback.tourFinish" : "feedback.tourNext");
|
|
333
|
+
this.#nextIcon.set().textContent = last ? Tour.#ICONS.finish : Tour.#ICONS.next;
|
|
334
|
+
this.#skipButton.style.display = this.#closable ? "" : "none";
|
|
335
|
+
this.#closeButton.style.display = this.#closable ? "" : "none";
|
|
336
|
+
this.#prevButton.style.display = this.#index === 0 ? "none" : "";
|
|
337
|
+
this.#popover.setContent([this.#head, hasText ? this.#text : undefined, this.#footer]);
|
|
316
338
|
if (previous !== undefined) {
|
|
317
339
|
if (this.#layer.contains(previous)) previous.focus();
|
|
318
|
-
else this.#
|
|
340
|
+
else this.#nextButton.focus();
|
|
319
341
|
}
|
|
320
|
-
this.#announce(
|
|
342
|
+
this.#announce(
|
|
343
|
+
`${this.#counter.innerText}${this.#title.innerText.trim() === "" ? "" : ". " + this.#title.innerText}`
|
|
344
|
+
);
|
|
321
345
|
// Цель: подвести в вид, измерить и поставить «окно» с подсказкой
|
|
322
346
|
this.#scrollIntoView(step);
|
|
323
347
|
this.#syncGeometry();
|
|
@@ -327,7 +351,7 @@ class Tour {
|
|
|
327
351
|
// Подсветка — не триггер: подсказку открывает знакомство, а не клик по окну
|
|
328
352
|
this.#clearTriggerAria();
|
|
329
353
|
if (step.onEnter !== undefined) step.onEnter(step, this.#index);
|
|
330
|
-
if (this.#
|
|
354
|
+
if (this.#onChange !== undefined) this.#onChange(step, this.#index);
|
|
331
355
|
}
|
|
332
356
|
|
|
333
357
|
/** Снять с подсветки aria триггера: поповер ставит их сам при показе и скрытии */
|
|
@@ -340,15 +364,20 @@ class Tour {
|
|
|
340
364
|
#targetOf(step = {}) {
|
|
341
365
|
const target = step.target;
|
|
342
366
|
if (target === undefined || target === null) return undefined;
|
|
343
|
-
const node =
|
|
367
|
+
const node =
|
|
368
|
+
typeof target === "string"
|
|
369
|
+
? document.querySelector(target)
|
|
370
|
+
: typeof target.set === "function"
|
|
371
|
+
? target.set()
|
|
372
|
+
: target;
|
|
344
373
|
return node instanceof Element ? node : undefined;
|
|
345
374
|
}
|
|
346
375
|
|
|
347
376
|
#scrollIntoView(step) {
|
|
348
|
-
if (!this.#
|
|
377
|
+
if (!this.#scrollIntoViewEnabled) return;
|
|
349
378
|
const node = this.#targetOf(step);
|
|
350
379
|
if (node === undefined) return;
|
|
351
|
-
node.scrollIntoView({block: "center", inline: "nearest"});
|
|
380
|
+
node.scrollIntoView({ block: "center", inline: "nearest" });
|
|
352
381
|
}
|
|
353
382
|
|
|
354
383
|
/** «Окно» вокруг цели: у шага без цели — точка в центре окна (подсказка встаёт у неё) */
|
|
@@ -360,10 +389,15 @@ class Tour {
|
|
|
360
389
|
let box;
|
|
361
390
|
if (node === undefined) {
|
|
362
391
|
const left = Math.max(0, (window.innerWidth - Tour.WIDTH) / 2);
|
|
363
|
-
box = {left: left, top: window.innerHeight / 2, width: 0, height: 0};
|
|
392
|
+
box = { left: left, top: window.innerHeight / 2, width: 0, height: 0 };
|
|
364
393
|
} else {
|
|
365
394
|
const rect = node.getBoundingClientRect();
|
|
366
|
-
box = {
|
|
395
|
+
box = {
|
|
396
|
+
left: rect.left - padding,
|
|
397
|
+
top: rect.top - padding,
|
|
398
|
+
width: rect.width + padding * 2,
|
|
399
|
+
height: rect.height + padding * 2,
|
|
400
|
+
};
|
|
367
401
|
}
|
|
368
402
|
this.#highlight.style.left = `${Math.round(box.left)}px`;
|
|
369
403
|
this.#highlight.style.top = `${Math.round(box.top)}px`;
|
|
@@ -395,9 +429,9 @@ class Tour {
|
|
|
395
429
|
}
|
|
396
430
|
};
|
|
397
431
|
#onWindowChange = () => {
|
|
398
|
-
if (!this.#
|
|
432
|
+
if (!this.#isOpen) return;
|
|
399
433
|
this.#syncGeometry();
|
|
400
434
|
};
|
|
401
435
|
}
|
|
402
436
|
|
|
403
|
-
exports.Tour = Tour
|
|
437
|
+
exports.Tour = Tour;
|
|
@@ -4,13 +4,13 @@ chui_transfer {
|
|
|
4
4
|
flex-direction: column;
|
|
5
5
|
width: max-content;
|
|
6
6
|
max-width: 100%;
|
|
7
|
-
margin: var(--
|
|
7
|
+
margin: var(--block_margin);
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
.transfer_label {
|
|
11
11
|
display: block;
|
|
12
12
|
width: max-content;
|
|
13
|
-
margin: var(--
|
|
13
|
+
margin: var(--block_margin);
|
|
14
14
|
color: var(--text_color);
|
|
15
15
|
font-size: var(--font_labels_size);
|
|
16
16
|
font-weight: 500;
|
|
@@ -33,7 +33,7 @@ chui_transfer {
|
|
|
33
33
|
border: none;
|
|
34
34
|
outline: 1px solid var(--red_prime_background);
|
|
35
35
|
outline-offset: 4px;
|
|
36
|
-
border-radius: var(--
|
|
36
|
+
border-radius: var(--radius_sm);
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
.transfer_pane {
|
|
@@ -75,10 +75,11 @@ chui_transfer {
|
|
|
75
75
|
min-height: var(--control_height);
|
|
76
76
|
margin: 0;
|
|
77
77
|
/* Место под кнопку очистки, чтобы текст не заезжал под неё; слева 11 px — как
|
|
78
|
-
у текстовых полей (--
|
|
79
|
-
padding-block: 0 0;
|
|
78
|
+
у текстовых полей (--block_padding_sm) */
|
|
79
|
+
padding-block: 0 0;
|
|
80
|
+
padding-inline: 11px 30px;
|
|
80
81
|
border: 1px solid var(--border_color);
|
|
81
|
-
border-radius: var(--
|
|
82
|
+
border-radius: var(--radius_sm);
|
|
82
83
|
background: var(--element_background);
|
|
83
84
|
color: var(--text_color);
|
|
84
85
|
font-family: inherit;
|
|
@@ -146,7 +147,7 @@ chui_transfer {
|
|
|
146
147
|
padding: 4px;
|
|
147
148
|
overflow: auto;
|
|
148
149
|
border: 1px solid var(--border_color);
|
|
149
|
-
border-radius: var(--
|
|
150
|
+
border-radius: var(--radius_sm);
|
|
150
151
|
background: var(--element_background);
|
|
151
152
|
}
|
|
152
153
|
|