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,6 +1,6 @@
|
|
|
1
|
-
const {setStyles, optionOr, scrollParent} = require(
|
|
2
|
-
const {Icon, Icons} = require(
|
|
3
|
-
const {I18n} = require(
|
|
1
|
+
const { setStyles, optionOr, scrollParent } = require("../../modules/chui_functions");
|
|
2
|
+
const { Icon, Icons } = require("../chui_icons/icons");
|
|
3
|
+
const { I18n } = require("../../modules/chui_i18n/chui_i18n");
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Кнопка «наверх»: появляется, когда контейнер прокручен дальше порога, и возвращает его к началу.
|
|
@@ -32,7 +32,7 @@ const {I18n} = require('../../modules/chui_i18n/chui_i18n');
|
|
|
32
32
|
class Backtop {
|
|
33
33
|
static POSITION = {
|
|
34
34
|
FIXED: "fixed",
|
|
35
|
-
STICKY: "sticky"
|
|
35
|
+
STICKY: "sticky",
|
|
36
36
|
};
|
|
37
37
|
static #counter = 0;
|
|
38
38
|
static #DEFAULT_THRESHOLD = 200;
|
|
@@ -50,11 +50,19 @@ class Backtop {
|
|
|
50
50
|
#visible = false;
|
|
51
51
|
#destroyed = false;
|
|
52
52
|
|
|
53
|
-
constructor(
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
53
|
+
constructor(
|
|
54
|
+
options = {
|
|
55
|
+
id: String(),
|
|
56
|
+
target: undefined,
|
|
57
|
+
threshold: Number(),
|
|
58
|
+
position: String(),
|
|
59
|
+
bottom: String(),
|
|
60
|
+
inlineEnd: String(),
|
|
61
|
+
title: String(),
|
|
62
|
+
icon: undefined,
|
|
63
|
+
smooth: Boolean(),
|
|
64
|
+
}
|
|
65
|
+
) {
|
|
58
66
|
setStyles(__dirname + "/styles.css", "chUiJS_Backtop");
|
|
59
67
|
Backtop.#counter += 1;
|
|
60
68
|
this.#id = optionOr(options.id, `chui_backtop_${Backtop.#counter}`);
|
|
@@ -74,7 +82,7 @@ class Backtop {
|
|
|
74
82
|
this.setTitle(options.title);
|
|
75
83
|
this.setIcon(options.icon);
|
|
76
84
|
this.setSmooth(options.smooth !== false);
|
|
77
|
-
window.addEventListener("scroll", this.#onScroll, {capture: true, passive: true});
|
|
85
|
+
window.addEventListener("scroll", this.#onScroll, { capture: true, passive: true });
|
|
78
86
|
}
|
|
79
87
|
|
|
80
88
|
// GET
|
|
@@ -150,9 +158,14 @@ class Backtop {
|
|
|
150
158
|
|
|
151
159
|
/** Свой значок (имя из `Icons`, `Icon`, узел или компонент); `undefined` — стрелка вверх */
|
|
152
160
|
setIcon(icon = undefined) {
|
|
153
|
-
const node =
|
|
154
|
-
|
|
155
|
-
|
|
161
|
+
const node =
|
|
162
|
+
icon === undefined || icon === null || icon === ""
|
|
163
|
+
? new Icon(Icons.NAVIGATION.ARROW_UPWARD, "18px").set()
|
|
164
|
+
: typeof icon === "string"
|
|
165
|
+
? new Icon(icon, "18px").set()
|
|
166
|
+
: typeof icon.set === "function"
|
|
167
|
+
? icon.set()
|
|
168
|
+
: icon;
|
|
156
169
|
this.#icon.innerHTML = "";
|
|
157
170
|
this.#icon.appendChild(node);
|
|
158
171
|
return this;
|
|
@@ -175,8 +188,8 @@ class Backtop {
|
|
|
175
188
|
const container = this.#resolveTarget();
|
|
176
189
|
if (container === undefined) return this;
|
|
177
190
|
const behavior = this.#smooth && Backtop.#reducedMotion() === false ? "smooth" : "auto";
|
|
178
|
-
if (container === document.scrollingElement) window.scrollTo({top: 0, behavior: behavior});
|
|
179
|
-
else container.scrollTo({top: 0, behavior: behavior});
|
|
191
|
+
if (container === document.scrollingElement) window.scrollTo({ top: 0, behavior: behavior });
|
|
192
|
+
else container.scrollTo({ top: 0, behavior: behavior });
|
|
180
193
|
return this;
|
|
181
194
|
}
|
|
182
195
|
|
|
@@ -184,7 +197,8 @@ class Backtop {
|
|
|
184
197
|
destroy() {
|
|
185
198
|
if (this.#destroyed) return this;
|
|
186
199
|
this.#destroyed = true;
|
|
187
|
-
window.removeEventListener("scroll", this.#onScroll, {capture: true});
|
|
200
|
+
window.removeEventListener("scroll", this.#onScroll, { capture: true });
|
|
201
|
+
this.#root.removeEventListener("transitionend", this.#onHideEnd);
|
|
188
202
|
this.#root.remove();
|
|
189
203
|
return this;
|
|
190
204
|
}
|
|
@@ -196,8 +210,11 @@ class Backtop {
|
|
|
196
210
|
|
|
197
211
|
// === ВНУТРЕННЕЕ ===
|
|
198
212
|
static #reducedMotion() {
|
|
199
|
-
return
|
|
200
|
-
window
|
|
213
|
+
return (
|
|
214
|
+
typeof window !== "undefined" &&
|
|
215
|
+
typeof window.matchMedia === "function" &&
|
|
216
|
+
window.matchMedia("(prefers-reduced-motion: reduce)").matches
|
|
217
|
+
);
|
|
201
218
|
}
|
|
202
219
|
|
|
203
220
|
/** Контейнер прокрутки: свой `target`, иначе ближайший прокручиваемый предок кнопки */
|
|
@@ -222,9 +239,31 @@ class Backtop {
|
|
|
222
239
|
const visible = top > this.#threshold;
|
|
223
240
|
if (visible === this.#visible) return;
|
|
224
241
|
this.#visible = visible;
|
|
225
|
-
this.#
|
|
226
|
-
|
|
242
|
+
this.#show(visible);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* Показ и уход идут движением (переход в styles.css). Узел встаёт в раскладку до класса —
|
|
247
|
+
* иначе перехода не было бы вовсе, — а `hidden` возвращается по концу ухода: в закреплённом
|
|
248
|
+
* положении он держит место в раскладке панели, и снять его до ухода значило бы оборвать его.
|
|
249
|
+
*/
|
|
250
|
+
#show(visible) {
|
|
251
|
+
if (visible) {
|
|
252
|
+
this.#root.hidden = false;
|
|
253
|
+
requestAnimationFrame(() => {
|
|
254
|
+
if (this.#visible === true) this.#root.classList.add("backtop_visible");
|
|
255
|
+
});
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
this.#root.classList.remove("backtop_visible");
|
|
259
|
+
this.#root.addEventListener("transitionend", this.#onHideEnd);
|
|
227
260
|
}
|
|
261
|
+
|
|
262
|
+
#onHideEnd = (event) => {
|
|
263
|
+
if (event.target !== this.#root || event.propertyName !== "opacity") return;
|
|
264
|
+
this.#root.removeEventListener("transitionend", this.#onHideEnd);
|
|
265
|
+
if (this.#visible === false) this.#root.hidden = true;
|
|
266
|
+
};
|
|
228
267
|
}
|
|
229
268
|
|
|
230
|
-
exports.Backtop = Backtop
|
|
269
|
+
exports.Backtop = Backtop;
|
|
@@ -6,6 +6,27 @@ chui_backtop {
|
|
|
6
6
|
--backtop_inline_end: 24px;
|
|
7
7
|
width: max-content;
|
|
8
8
|
height: max-content;
|
|
9
|
+
opacity: 1;
|
|
10
|
+
transform: none;
|
|
11
|
+
/* Появление и уход — движение, а не снятие узла: кнопка поднимается на месте и гаснет.
|
|
12
|
+
`hidden` включает JS по концу ухода: в закреплённом положении он держит место
|
|
13
|
+
в раскладке панели, поэтому снимать его заранее нельзя */
|
|
14
|
+
transition:
|
|
15
|
+
opacity var(--motion_base) var(--motion_ease),
|
|
16
|
+
transform var(--motion_base) var(--motion_ease),
|
|
17
|
+
visibility var(--motion_none) linear;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/* Скрытая кнопка не ловит курсор и не попадает в обход Tab: `visibility` переключается
|
|
21
|
+
сразу при показе и только в конце ухода */
|
|
22
|
+
chui_backtop:not(.backtop_visible) {
|
|
23
|
+
opacity: 0;
|
|
24
|
+
transform: translateY(8px);
|
|
25
|
+
visibility: hidden;
|
|
26
|
+
transition:
|
|
27
|
+
opacity var(--motion_fast) var(--motion_ease),
|
|
28
|
+
transform var(--motion_fast) var(--motion_ease),
|
|
29
|
+
visibility var(--motion_none) linear var(--motion_fast);
|
|
9
30
|
}
|
|
10
31
|
|
|
11
32
|
chui_backtop[hidden] {
|
|
@@ -1,61 +1,63 @@
|
|
|
1
|
-
const {setStyles, markdownToHtml, htmlToMarkdown, optionOr} = require("../../modules/chui_functions");
|
|
1
|
+
const { setStyles, markdownToHtml, htmlToMarkdown, optionOr } = require("../../modules/chui_functions");
|
|
2
2
|
|
|
3
3
|
class Badge {
|
|
4
|
-
#
|
|
5
|
-
constructor(
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
4
|
+
#chuiBadge = document.createElement(`chui_badge`);
|
|
5
|
+
constructor(
|
|
6
|
+
options = {
|
|
7
|
+
id: String(),
|
|
8
|
+
text: String(),
|
|
9
|
+
markdownText: String(),
|
|
10
|
+
style: undefined,
|
|
11
|
+
}
|
|
12
|
+
) {
|
|
13
|
+
setStyles(__dirname + "/styles.css", "chUiJS_Badge");
|
|
14
|
+
if (options.id !== undefined) this.#chuiBadge.id = options.id;
|
|
13
15
|
const style = optionOr(options.style, undefined);
|
|
14
|
-
if (style !== undefined) this.#
|
|
16
|
+
if (style !== undefined) this.#chuiBadge.classList.add(style);
|
|
15
17
|
// Стили текста баджей: пустая заготовка опции равносильна отсутствующей
|
|
16
18
|
const text = optionOr(options.text, undefined);
|
|
17
|
-
const
|
|
18
|
-
if (text !== undefined &&
|
|
19
|
+
const markdownText = optionOr(options.markdownText, undefined);
|
|
20
|
+
if (text !== undefined && markdownText !== undefined) {
|
|
19
21
|
throw new Error("Должна быть установлена одна опция text или markdownText");
|
|
20
22
|
} else {
|
|
21
|
-
if (text !== undefined) this.#
|
|
22
|
-
if (
|
|
23
|
+
if (text !== undefined) this.#chuiBadge.innerText = text;
|
|
24
|
+
if (markdownText !== undefined) this.#chuiBadge.innerHTML = markdownToHtml(markdownText);
|
|
23
25
|
}
|
|
24
26
|
}
|
|
25
27
|
// GET
|
|
26
28
|
getId() {
|
|
27
|
-
return this.#
|
|
29
|
+
return this.#chuiBadge.id;
|
|
28
30
|
}
|
|
29
31
|
getText() {
|
|
30
|
-
return this.#
|
|
32
|
+
return this.#chuiBadge.innerText;
|
|
31
33
|
}
|
|
32
34
|
getMarkdownText() {
|
|
33
|
-
return htmlToMarkdown(this.#
|
|
35
|
+
return htmlToMarkdown(this.#chuiBadge.innerHTML);
|
|
34
36
|
}
|
|
35
37
|
// SET
|
|
36
38
|
setText(text = String()) {
|
|
37
|
-
this.#
|
|
39
|
+
this.#chuiBadge.innerText = text;
|
|
38
40
|
}
|
|
39
41
|
setMarkdownText(text = String()) {
|
|
40
|
-
this.#
|
|
42
|
+
this.#chuiBadge.innerHTML = markdownToHtml(text);
|
|
41
43
|
}
|
|
42
44
|
setId(id = String()) {
|
|
43
|
-
this.#
|
|
45
|
+
this.#chuiBadge.id = id;
|
|
44
46
|
}
|
|
45
47
|
setStyle(style = String()) {
|
|
46
48
|
// Пустая строка — «не задана»: `classList.add("")` бросает исключение
|
|
47
49
|
const known = optionOr(style, undefined);
|
|
48
|
-
if (known !== undefined) this.#
|
|
50
|
+
if (known !== undefined) this.#chuiBadge.classList.add(known);
|
|
49
51
|
}
|
|
50
52
|
// RENDER
|
|
51
53
|
set() {
|
|
52
|
-
return this.#
|
|
54
|
+
return this.#chuiBadge;
|
|
53
55
|
}
|
|
54
56
|
static STYLE = {
|
|
55
|
-
ERROR:
|
|
56
|
-
SUCCESS:
|
|
57
|
-
WARNING:
|
|
58
|
-
}
|
|
57
|
+
ERROR: "badge_error",
|
|
58
|
+
SUCCESS: "badge_success",
|
|
59
|
+
WARNING: "badge_warning",
|
|
60
|
+
};
|
|
59
61
|
}
|
|
60
62
|
|
|
61
|
-
exports.Badge = Badge
|
|
63
|
+
exports.Badge = Badge;
|
|
@@ -12,9 +12,9 @@ chui_badge {
|
|
|
12
12
|
height: max-content;
|
|
13
13
|
width: max-content;
|
|
14
14
|
padding: 2px 8px;
|
|
15
|
-
margin: var(--
|
|
15
|
+
margin: var(--block_margin);
|
|
16
16
|
border-radius: var(--radius_pill);
|
|
17
|
-
background: var(--
|
|
17
|
+
background: var(--badge_cancel_background);
|
|
18
18
|
color: var(--badge_cancel_text);
|
|
19
19
|
font-size: var(--font_labels_size);
|
|
20
20
|
font-weight: 500;
|
|
@@ -41,20 +41,20 @@ chui_badge strong {
|
|
|
41
41
|
|
|
42
42
|
/* Код в метке — тем же моношрифтом, что в остальных местах с разметкой */
|
|
43
43
|
chui_badge code {
|
|
44
|
-
font-family: var(--
|
|
44
|
+
font-family: var(--font_mono);
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
.badge_error {
|
|
48
|
-
background: var(--
|
|
48
|
+
background: var(--badge_error_background);
|
|
49
49
|
color: var(--badge_error_text);
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
.badge_success {
|
|
53
|
-
background: var(--
|
|
53
|
+
background: var(--badge_success_background);
|
|
54
54
|
color: var(--badge_success_text);
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
.badge_warning {
|
|
58
|
-
background: var(--
|
|
58
|
+
background: var(--badge_warning_background);
|
|
59
59
|
color: var(--badge_warning_text);
|
|
60
60
|
}
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
const { setStyles, optionOr, markdownToHtml } = require("../../modules/chui_functions");
|
|
2
|
+
const { Icon } = require("../chui_icons/icons");
|
|
3
|
+
const { I18n } = require("../../modules/chui_i18n/chui_i18n");
|
|
4
|
+
const { makeKeyboardButton } = require("../../modules/chui_a11y/chui_a11y");
|
|
5
|
+
const { tokenTime } = require("../../modules/chui_animations/motion");
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Баннер — карточка-объявление: картинка или значок, заголовок с подзаголовком, действия
|
|
9
|
+
* и закрытие.
|
|
10
|
+
*
|
|
11
|
+
* Баннер стоит в потоке страницы, а не всплывает слоем: для модального сообщения есть
|
|
12
|
+
* `Popup`, для сообщения о состоянии — `Alert`, для всплывающего — `Toast`. От `Alert` он
|
|
13
|
+
* отличается задачей: там состояние (ошибка, предупреждение), здесь предложение — «попробуйте
|
|
14
|
+
* новое», «настройте», «посмотрите» — поэтому у баннера крупный материал, картинка и действия
|
|
15
|
+
* кнопками.
|
|
16
|
+
*
|
|
17
|
+
* Два вида (`mode`) и два размера (`size`):
|
|
18
|
+
* - `tint` — значок в цветной плашке, `image` — фотография; фото занимает кромку карточки
|
|
19
|
+
* целиком и не затемняется: текст лежит рядом, а не поверх снимка, поэтому подпись читается
|
|
20
|
+
* при любом кадре (всплывающие подписи поверх фото требуют затемнения на глаз — в тёмной
|
|
21
|
+
* и светлой схеме оно даёт разный результат);
|
|
22
|
+
* - `s` — строка: плашка слева, заголовок и подзаголовок рядом, действия справа;
|
|
23
|
+
* - `m` — карточка: картинка сверху во всю ширину, под ней заголовок, подзаголовок, текст
|
|
24
|
+
* и действия.
|
|
25
|
+
*
|
|
26
|
+
* Опции: `id`, `title`, `subtitle`, `text`, `markdownText`, `icon`, `image`, `mode`, `size`,
|
|
27
|
+
* `actions`, `closable`, `onClose`, `onClick`.
|
|
28
|
+
*
|
|
29
|
+
* Методы: `setTitle(text)`, `setSubtitle(text)`, `setText(text)`, `setMarkdownText(md)`,
|
|
30
|
+
* `setIcon(glyph)`, `setImage(src)`, `setMode(mode)`, `setSize(size)`, `addActions(...actions)`,
|
|
31
|
+
* `setClosable(bool)`, `close()`, `isClosed()`, `set()`, `destroy()`.
|
|
32
|
+
*/
|
|
33
|
+
class Banner {
|
|
34
|
+
static MODE = { TINT: "tint", IMAGE: "image" };
|
|
35
|
+
static SIZE = { S: "s", M: "m" };
|
|
36
|
+
|
|
37
|
+
#root = document.createElement("chui_banner");
|
|
38
|
+
#media = document.createElement("banner_media");
|
|
39
|
+
#content = document.createElement("banner_content");
|
|
40
|
+
#title = undefined;
|
|
41
|
+
#subtitle = undefined;
|
|
42
|
+
#text = undefined;
|
|
43
|
+
#actions = document.createElement("banner_actions");
|
|
44
|
+
#close = undefined;
|
|
45
|
+
#image = undefined;
|
|
46
|
+
#onClose = undefined;
|
|
47
|
+
#onClick = undefined;
|
|
48
|
+
#closed = false;
|
|
49
|
+
#removed = false;
|
|
50
|
+
|
|
51
|
+
constructor(options = {}) {
|
|
52
|
+
setStyles(__dirname + "/styles.css", "chUiJS_Banner");
|
|
53
|
+
if (options.id !== undefined) this.#root.id = options.id;
|
|
54
|
+
this.setSize(optionOr(options.size, Banner.SIZE.M));
|
|
55
|
+
this.setMode(optionOr(options.mode, Banner.MODE.TINT));
|
|
56
|
+
this.#onClose = typeof options.onClose === "function" ? options.onClose : undefined;
|
|
57
|
+
this.#onClick = typeof options.onClick === "function" ? options.onClick : undefined;
|
|
58
|
+
this.#root.append(this.#media, this.#content, this.#actions);
|
|
59
|
+
if (options.title !== undefined) this.setTitle(options.title);
|
|
60
|
+
if (options.subtitle !== undefined) this.setSubtitle(options.subtitle);
|
|
61
|
+
if (options.markdownText !== undefined) this.setMarkdownText(options.markdownText);
|
|
62
|
+
else if (options.text !== undefined) this.setText(options.text);
|
|
63
|
+
if (options.icon !== undefined) this.setIcon(options.icon);
|
|
64
|
+
if (options.image !== undefined) this.setImage(options.image);
|
|
65
|
+
if (Array.isArray(options.actions)) this.addActions(...options.actions);
|
|
66
|
+
if (options.closable === true) this.setClosable(true);
|
|
67
|
+
if (this.#onClick !== undefined) this.#makeClickable();
|
|
68
|
+
this.#syncName();
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// GET
|
|
72
|
+
isClosed() {
|
|
73
|
+
return this.#closed;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// SET
|
|
77
|
+
setTitle(text = String()) {
|
|
78
|
+
this.#title = this.#writeText(this.#title, "banner_title", text, "title");
|
|
79
|
+
this.#syncName();
|
|
80
|
+
return this;
|
|
81
|
+
}
|
|
82
|
+
setSubtitle(text = String()) {
|
|
83
|
+
this.#subtitle = this.#writeText(this.#subtitle, "banner_subtitle", text, "subtitle");
|
|
84
|
+
return this;
|
|
85
|
+
}
|
|
86
|
+
setText(text = String()) {
|
|
87
|
+
this.#text = this.#writeText(this.#text, "banner_text", text, "text");
|
|
88
|
+
return this;
|
|
89
|
+
}
|
|
90
|
+
/** Разметка в теле баннера: тот же приём, что у `Alert` — текст приходит готовым HTML */
|
|
91
|
+
setMarkdownText(markdown = String()) {
|
|
92
|
+
if (this.#text === undefined) this.#text = this.#insertText("banner_text", "text");
|
|
93
|
+
this.#text.innerHTML = markdownToHtml(String(markdown));
|
|
94
|
+
return this;
|
|
95
|
+
}
|
|
96
|
+
/** Значок в плашке: состояние `tint`. Прежняя картинка при этом уходит */
|
|
97
|
+
setIcon(glyph = String()) {
|
|
98
|
+
const icon = new Icon(String(glyph), "22px").set();
|
|
99
|
+
this.#media.replaceChildren(icon);
|
|
100
|
+
this.#root.dataset.mode = Banner.MODE.TINT;
|
|
101
|
+
this.#image = undefined;
|
|
102
|
+
return this;
|
|
103
|
+
}
|
|
104
|
+
/** Фотография на кромке карточки: состояние `image` */
|
|
105
|
+
setImage(src = String()) {
|
|
106
|
+
if (this.#image === undefined) {
|
|
107
|
+
this.#image = document.createElement("img");
|
|
108
|
+
// Картинка здесь украшение: смысл несёт заголовок, поэтому подпись пуста
|
|
109
|
+
this.#image.alt = "";
|
|
110
|
+
this.#image.loading = "lazy";
|
|
111
|
+
}
|
|
112
|
+
this.#image.src = String(src);
|
|
113
|
+
this.#media.replaceChildren(this.#image);
|
|
114
|
+
this.#root.dataset.mode = Banner.MODE.IMAGE;
|
|
115
|
+
return this;
|
|
116
|
+
}
|
|
117
|
+
setMode(mode = String()) {
|
|
118
|
+
this.#root.dataset.mode = mode === Banner.MODE.IMAGE ? Banner.MODE.IMAGE : Banner.MODE.TINT;
|
|
119
|
+
return this;
|
|
120
|
+
}
|
|
121
|
+
setSize(size = String()) {
|
|
122
|
+
this.#root.dataset.size = size === Banner.SIZE.S ? Banner.SIZE.S : Banner.SIZE.M;
|
|
123
|
+
return this;
|
|
124
|
+
}
|
|
125
|
+
/** Действия баннера: компоненты фреймворка (у них есть `set()`) или готовые узлы */
|
|
126
|
+
addActions(...actions) {
|
|
127
|
+
for (const action of actions) {
|
|
128
|
+
if (action === undefined || action === null) continue;
|
|
129
|
+
this.#actions.appendChild(typeof action.set === "function" ? action.set() : action);
|
|
130
|
+
}
|
|
131
|
+
return this;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Кнопка закрытия — настоящий `<button>`: у неё есть мышь, клавиатура и имя
|
|
135
|
+
* для скринридера (подписи в баннере нет, имя даёт словарь).
|
|
136
|
+
*/
|
|
137
|
+
setClosable(boolean = Boolean()) {
|
|
138
|
+
if (boolean !== true) {
|
|
139
|
+
if (this.#close !== undefined) this.#close.remove();
|
|
140
|
+
this.#close = undefined;
|
|
141
|
+
return this;
|
|
142
|
+
}
|
|
143
|
+
if (this.#close === undefined) {
|
|
144
|
+
this.#close = document.createElement("button");
|
|
145
|
+
this.#close.type = "button";
|
|
146
|
+
this.#close.className = "banner_close";
|
|
147
|
+
this.#close.innerHTML = new Icon("close", "16px").getHTML();
|
|
148
|
+
this.#close.setAttribute("aria-label", I18n.t("a11y.closeMessage"));
|
|
149
|
+
this.#close.setAttribute("title", I18n.t("common.close"));
|
|
150
|
+
this.#close.addEventListener("click", () => this.close());
|
|
151
|
+
this.#root.appendChild(this.#close);
|
|
152
|
+
}
|
|
153
|
+
return this;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Закрытие: баннер гаснет и сходит общим кадром ухода, а узел убирается по его концу.
|
|
158
|
+
* Слушатель одноразовый (проверка цели): иначе он поймал бы любой конец кадра на узле.
|
|
159
|
+
* Срок из токена страхует случай, когда кадр не проиграется вовсе — у скрытого узла
|
|
160
|
+
* `animationend` не приходит.
|
|
161
|
+
*/
|
|
162
|
+
close() {
|
|
163
|
+
if (this.#closed === true) return this;
|
|
164
|
+
this.#closed = true;
|
|
165
|
+
if (this.#onClose !== undefined) this.#onClose(this);
|
|
166
|
+
const finish = () => {
|
|
167
|
+
if (this.#removed === true) return;
|
|
168
|
+
this.#removed = true;
|
|
169
|
+
this.#root.removeEventListener("animationend", finish);
|
|
170
|
+
this.#root.remove();
|
|
171
|
+
};
|
|
172
|
+
this.#root.addEventListener("animationend", finish);
|
|
173
|
+
this.#root.classList.add("banner_leaving");
|
|
174
|
+
setTimeout(finish, tokenTime("--motion_fast"));
|
|
175
|
+
return this;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
set() {
|
|
179
|
+
return this.#root;
|
|
180
|
+
}
|
|
181
|
+
/** Узлы баннера уходят из документа вместе со своими слушателями; работа снимается явно */
|
|
182
|
+
destroy() {
|
|
183
|
+
this.#onClick = undefined;
|
|
184
|
+
this.#onClose = undefined;
|
|
185
|
+
this.#removed = true;
|
|
186
|
+
this.#root.remove();
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// === ВНУТРЕННЕЕ ===
|
|
190
|
+
#writeText(node = undefined, className = String(), text = String(), key = String()) {
|
|
191
|
+
const target = node === undefined ? this.#insertText(className, key) : node;
|
|
192
|
+
target.innerText = String(text);
|
|
193
|
+
return target;
|
|
194
|
+
}
|
|
195
|
+
#insertText(className = String(), key = String()) {
|
|
196
|
+
const node = document.createElement(`banner_${key}`);
|
|
197
|
+
node.className = className;
|
|
198
|
+
this.#content.appendChild(node);
|
|
199
|
+
return node;
|
|
200
|
+
}
|
|
201
|
+
/** Клик по всей карточке: роль кнопки, обход клавиатурой и активация Enter/Space */
|
|
202
|
+
#makeClickable() {
|
|
203
|
+
makeKeyboardButton(this.#root);
|
|
204
|
+
this.#root.addEventListener("click", () => {
|
|
205
|
+
if (this.#onClick !== undefined) this.#onClick(this);
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Имя баннера для скринридера: заголовок, а без него — общая подпись из словаря.
|
|
210
|
+
* У кликабельного баннера имя обязательно: без него роль кнопки читается как «кнопка».
|
|
211
|
+
*/
|
|
212
|
+
#syncName() {
|
|
213
|
+
const title = this.#title === undefined ? "" : this.#title.innerText.trim();
|
|
214
|
+
const name = title === "" ? I18n.t("feedback.banner") : title;
|
|
215
|
+
if (this.#onClick === undefined && this.#root.getAttribute("role") === null) {
|
|
216
|
+
this.#root.setAttribute("role", "region");
|
|
217
|
+
}
|
|
218
|
+
this.#root.setAttribute("aria-label", name);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
exports.Banner = Banner;
|