chuijs 4.0.3 → 4.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +536 -0
- package/framework/appLayout/default/chui_app_layout.js +361 -303
- package/framework/appLayout/default/global_style.css +243 -89
- package/framework/appLayout/default/main_theme_style.css +188 -101
- package/framework/components/chui_accordion/accordion.js +17 -17
- package/framework/components/chui_accordion/styles.css +7 -7
- package/framework/components/chui_action_sheet/action_sheet.js +35 -32
- package/framework/components/chui_action_sheet/styles.css +10 -4
- 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 +4 -4
- package/framework/components/chui_affix/styles.css +5 -0
- package/framework/components/chui_alert/alert.js +11 -5
- package/framework/components/chui_alert/styles.css +7 -0
- package/framework/components/chui_avatar/avatar.js +13 -13
- package/framework/components/chui_avatar/styles.css +1 -1
- package/framework/components/chui_avatar_group/avatar_group.js +4 -4
- package/framework/components/chui_avatar_group/styles.css +1 -1
- package/framework/components/chui_backtop/backtop.js +25 -2
- package/framework/components/chui_backtop/styles.css +21 -0
- package/framework/components/chui_badge/badge.js +15 -15
- 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/styles.css +1 -1
- package/framework/components/chui_button/button.js +24 -28
- package/framework/components/chui_button/styles.css +5 -5
- package/framework/components/chui_calendar/calendar.js +6 -6
- package/framework/components/chui_card/card.js +14 -14
- 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 +73 -51
- package/framework/components/chui_chat/styles.css +18 -7
- package/framework/components/chui_clipboard_history/clipboard_history.js +25 -20
- package/framework/components/chui_clipboard_history/styles.css +10 -8
- package/framework/components/chui_code/code.js +8 -8
- package/framework/components/chui_code/styles.css +2 -2
- package/framework/components/chui_code_editor/code_editor.js +26 -26
- package/framework/components/chui_code_editor/styles.css +3 -3
- package/framework/components/chui_command_palette/command_palette.js +29 -29
- package/framework/components/chui_command_palette/styles.css +5 -5
- package/framework/components/chui_console/console.js +9 -9
- package/framework/components/chui_console/styles.css +5 -2
- package/framework/components/chui_content_block/content_block.js +2 -2
- package/framework/components/chui_context_menu/context_menu.js +162 -54
- package/framework/components/chui_context_menu/styles.css +82 -8
- package/framework/components/chui_custom_element/custom_element.js +11 -11
- package/framework/components/chui_data_grid/data_grid.js +268 -268
- package/framework/components/chui_data_grid/styles.css +14 -14
- package/framework/components/chui_descriptions/styles.css +1 -1
- package/framework/components/chui_details/details.js +12 -12
- package/framework/components/chui_details/styles.css +7 -7
- package/framework/components/chui_diff_viewer/diff_viewer.js +88 -88
- package/framework/components/chui_diff_viewer/styles.css +9 -9
- package/framework/components/chui_divider/divider.js +6 -6
- package/framework/components/chui_divider/styles.css +2 -2
- package/framework/components/chui_drawer/drawer.js +37 -14
- package/framework/components/chui_drawer/styles.css +18 -4
- package/framework/components/chui_drop_zone/drop_zone.js +6 -6
- package/framework/components/chui_drop_zone/styles.css +10 -6
- package/framework/components/chui_fieldset/fieldset.js +6 -6
- package/framework/components/chui_fieldset/styles.css +5 -5
- package/framework/components/chui_file_explorer/file_explorer.js +115 -115
- package/framework/components/chui_file_explorer/styles.css +6 -6
- package/framework/components/chui_form/form.js +11 -11
- package/framework/components/chui_gantt/gantt.js +41 -41
- package/framework/components/chui_gantt/styles.css +5 -5
- package/framework/components/chui_graphs/graphs.js +82 -46
- package/framework/components/chui_graphs/styles.css +26 -5
- package/framework/components/chui_hero/hero.js +63 -20
- package/framework/components/chui_hero/styles.css +176 -7
- package/framework/components/chui_html_block/html_block.js +5 -5
- package/framework/components/chui_html_block/styles.css +1 -1
- package/framework/components/chui_hx/styles.css +2 -2
- package/framework/components/chui_icons/icons.js +7 -7
- package/framework/components/chui_icons/styles.css +2 -1
- package/framework/components/chui_inputs/chui_check_box/styles.css +12 -3
- package/framework/components/chui_inputs/chui_chips/chips.js +92 -31
- package/framework/components/chui_inputs/chui_chips/styles.css +28 -5
- package/framework/components/chui_inputs/chui_color_picker/color_picker.js +20 -15
- package/framework/components/chui_inputs/chui_color_picker/styles.css +7 -7
- package/framework/components/chui_inputs/chui_combo_box/combo_box.js +58 -58
- package/framework/components/chui_inputs/chui_combo_box/styles.css +9 -9
- package/framework/components/chui_inputs/chui_date/date.js +93 -95
- package/framework/components/chui_inputs/chui_date/styles.css +8 -8
- package/framework/components/chui_inputs/chui_date_range/date_range.js +22 -22
- package/framework/components/chui_inputs/chui_date_range/styles.css +3 -3
- package/framework/components/chui_inputs/chui_datetime/datetime.js +12 -12
- package/framework/components/chui_inputs/chui_datetime/styles.css +3 -3
- package/framework/components/chui_inputs/chui_email/email.js +10 -10
- package/framework/components/chui_inputs/chui_email/styles.css +6 -6
- package/framework/components/chui_inputs/chui_file/file.js +8 -8
- package/framework/components/chui_inputs/chui_file/styles.css +12 -9
- package/framework/components/chui_inputs/chui_hotkey/hotkey.js +39 -39
- package/framework/components/chui_inputs/chui_hotkey/styles.css +6 -6
- package/framework/components/chui_inputs/chui_masked/masked.js +44 -44
- package/framework/components/chui_inputs/chui_masked/styles.css +5 -5
- package/framework/components/chui_inputs/chui_mention/mention.js +13 -13
- package/framework/components/chui_inputs/chui_mention/styles.css +14 -8
- package/framework/components/chui_inputs/chui_multi_combo_box/multi_combo_box.js +147 -137
- package/framework/components/chui_inputs/chui_multi_combo_box/styles.css +14 -8
- package/framework/components/chui_inputs/chui_number/number.js +42 -45
- package/framework/components/chui_inputs/chui_number/styles.css +6 -6
- package/framework/components/chui_inputs/chui_otp/otp.js +32 -32
- package/framework/components/chui_inputs/chui_otp/styles.css +5 -5
- package/framework/components/chui_inputs/chui_password/password.js +30 -36
- package/framework/components/chui_inputs/chui_password/styles.css +7 -7
- package/framework/components/chui_inputs/chui_radio_button/styles.css +2 -2
- package/framework/components/chui_inputs/chui_rating/rating.js +28 -28
- package/framework/components/chui_inputs/chui_rating/styles.css +3 -3
- package/framework/components/chui_inputs/chui_select_box/select_box.js +54 -54
- package/framework/components/chui_inputs/chui_select_box/styles.css +10 -10
- package/framework/components/chui_inputs/chui_slider/slider.js +14 -14
- package/framework/components/chui_inputs/chui_slider/styles.css +5 -4
- package/framework/components/chui_inputs/chui_text/styles.css +7 -7
- package/framework/components/chui_inputs/chui_text/text.js +13 -17
- package/framework/components/chui_inputs/chui_text_area/styles.css +8 -8
- package/framework/components/chui_inputs/chui_text_area/text_area.js +23 -23
- package/framework/components/chui_inputs/chui_time/styles.css +13 -17
- package/framework/components/chui_inputs/chui_time/time.js +35 -24
- package/framework/components/chui_inputs/chui_toggle/styles.css +10 -3
- package/framework/components/chui_inputs/chui_toggle/toggle.js +16 -16
- package/framework/components/chui_json_editor/json_editor.js +87 -87
- package/framework/components/chui_json_editor/styles.css +5 -5
- package/framework/components/chui_json_viewer/json_viewer.js +80 -80
- package/framework/components/chui_json_viewer/styles.css +6 -6
- package/framework/components/chui_kanban/kanban.js +27 -27
- package/framework/components/chui_kanban/styles.css +8 -4
- package/framework/components/chui_kbd/styles.css +1 -1
- package/framework/components/chui_label/label.js +17 -17
- package/framework/components/chui_label/styles.css +1 -1
- package/framework/components/chui_link/link.js +9 -9
- package/framework/components/chui_link/styles.css +11 -4
- package/framework/components/chui_list/list.js +11 -11
- package/framework/components/chui_list/styles.css +2 -2
- package/framework/components/chui_markdown_editor/markdown_editor.js +66 -66
- package/framework/components/chui_markdown_editor/styles.css +5 -5
- package/framework/components/chui_media/audio.js +240 -246
- package/framework/components/chui_media/audio_styles.css +41 -23
- package/framework/components/chui_media/image.js +49 -46
- package/framework/components/chui_media/image_compare.js +35 -35
- package/framework/components/chui_media/image_compare_styles.css +5 -5
- package/framework/components/chui_media/image_styles.css +1 -1
- package/framework/components/chui_media/video.js +148 -148
- package/framework/components/chui_media/video_styles.css +27 -11
- package/framework/components/chui_menu_bar/menu_bar.js +54 -54
- package/framework/components/chui_menu_bar/styles.css +10 -10
- 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 +37 -13
- package/framework/components/chui_notification/notification.js +76 -54
- package/framework/components/chui_notification/notification_download.js +26 -81
- package/framework/components/chui_notification/notification_download_card.js +115 -0
- package/framework/components/chui_notification/notification_download_progress.css +2 -2
- package/framework/components/chui_notification/notification_download_progress.js +70 -108
- package/framework/components/chui_notification/notification_update.js +31 -31
- package/framework/components/chui_notification/status_plate.css +3 -3
- package/framework/components/chui_notification/styles.css +6 -1
- package/framework/components/chui_notification/styles_download.css +1 -1
- package/framework/components/chui_notification/styles_update.css +2 -2
- package/framework/components/chui_org_chart/org_chart.js +29 -29
- package/framework/components/chui_org_chart/styles.css +2 -2
- package/framework/components/chui_pagination/pagination.js +3 -3
- package/framework/components/chui_pagination/styles.css +1 -1
- package/framework/components/chui_paragraph/styles.css +2 -2
- package/framework/components/chui_popover/popover.js +29 -23
- package/framework/components/chui_popover/styles.css +1 -1
- package/framework/components/chui_popups/popups.js +124 -124
- package/framework/components/chui_popups/styles.css +5 -5
- package/framework/components/chui_print_button/print_button.js +15 -10
- package/framework/components/chui_progress_bar/progress_bar.js +34 -12
- package/framework/components/chui_progress_bar/styles.css +4 -4
- package/framework/components/chui_progress_ring/progress_ring.js +15 -15
- package/framework/components/chui_progress_ring/styles.css +1 -1
- package/framework/components/chui_qrcode/qrcode.js +12 -12
- package/framework/components/chui_query_builder/query_builder.js +46 -46
- package/framework/components/chui_query_builder/styles.css +4 -4
- package/framework/components/chui_radio_group/styles.css +1 -1
- package/framework/components/chui_result/result.js +15 -15
- package/framework/components/chui_result/styles.css +3 -3
- package/framework/components/chui_scheduler/scheduler.js +74 -74
- package/framework/components/chui_scheduler/styles.css +5 -5
- 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 +63 -6
- package/framework/components/chui_segmented_control/styles.css +32 -6
- package/framework/components/chui_settings/settings.js +45 -46
- package/framework/components/chui_settings/styles.css +4 -4
- package/framework/components/chui_shortcut_help/shortcut_help.js +32 -34
- package/framework/components/chui_sidebar_nav/sidebar_nav.js +98 -29
- package/framework/components/chui_sidebar_nav/styles.css +9 -3
- package/framework/components/chui_slideshow/slideshow.js +85 -85
- package/framework/components/chui_slideshow/styles.css +6 -6
- package/framework/components/chui_spinner/spinner.js +10 -10
- package/framework/components/chui_split_button/split_button.js +30 -12
- package/framework/components/chui_split_button/styles.css +21 -5
- package/framework/components/chui_splitter/splitter.js +11 -11
- package/framework/components/chui_splitter/styles.css +2 -2
- package/framework/components/chui_statistic/statistic.js +47 -47
- package/framework/components/chui_status_bar/styles.css +2 -2
- package/framework/components/chui_stepper/stepper.js +202 -31
- package/framework/components/chui_stepper/styles.css +79 -14
- package/framework/components/chui_sticky_bar/sticky_bar.js +44 -13
- package/framework/components/chui_sticky_bar/styles.css +10 -8
- package/framework/components/chui_tabs/chui_tabs.js +74 -26
- package/framework/components/chui_tabs/styles.css +40 -12
- package/framework/components/chui_text_editor/styles.css +7 -7
- package/framework/components/chui_text_editor/text_editor.js +56 -56
- package/framework/components/chui_text_editor/text_editor_panel.js +173 -174
- package/framework/components/chui_theme_toggle/theme_toggle.js +21 -5
- package/framework/components/chui_timeline/styles.css +3 -1
- package/framework/components/chui_toast_queue/styles.css +11 -11
- package/framework/components/chui_toast_queue/toast_queue.js +30 -27
- package/framework/components/chui_toolbar/styles.css +2 -2
- package/framework/components/chui_tooltip/styles.css +2 -2
- package/framework/components/chui_tooltip/tooltip.js +3 -3
- package/framework/components/chui_tour/styles.css +8 -8
- package/framework/components/chui_tour/tour.js +72 -72
- package/framework/components/chui_transfer/styles.css +6 -6
- package/framework/components/chui_transfer/transfer.js +93 -106
- package/framework/components/chui_tree_table/styles.css +4 -4
- package/framework/components/chui_tree_table/tree_table.js +45 -45
- package/framework/components/chui_tree_view/styles.css +10 -8
- package/framework/components/chui_tree_view/tree_view.js +185 -183
- 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 +17 -17
- package/framework/components/chui_webview/webview.js +9 -9
- 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 +78 -79
- package/framework/modules/chui_animations/animations.js +77 -15
- package/framework/modules/chui_animations/motion.js +120 -0
- package/framework/modules/chui_animations/styles.css +36 -3
- package/framework/modules/chui_functions.js +31 -27
- package/framework/modules/chui_highlight/styles.css +13 -10
- package/framework/modules/chui_i18n/chui_i18n.js +3 -3
- package/framework/modules/chui_i18n/locales/feedback.js +62 -0
- package/framework/modules/chui_i18n/locales/navigation.js +4 -0
- package/framework/modules/chui_json/chui_json.js +2 -2
- package/framework/modules/chui_logger/chui_logger.js +23 -8
- package/framework/modules/chui_page/page.js +10 -10
- package/framework/modules/chui_palette/palette.js +61 -0
- package/framework/modules/chui_qr/chui_qr.js +23 -23
- package/framework/modules/chui_scrollbar/chui_scrollbar.js +45 -45
- package/framework/modules/chui_scrollbar/styles.css +3 -3
- package/framework/modules/chui_services/chui_services.js +8 -8
- package/framework/modules/chui_services/desktop.js +77 -71
- package/framework/modules/chui_sortable/chui_sortable.js +17 -17
- package/framework/modules/chui_validate/chui_validate.js +3 -3
- package/framework/tray_bar/chui_menu_items.js +2 -2
- package/index.d.ts +266 -34
- package/index.js +20 -1168
- package/package.json +6 -4
- package/framework/components/telegram_bot/chui_telegram_bot.js +0 -191
|
@@ -55,18 +55,18 @@ class ActionSheet {
|
|
|
55
55
|
#head = document.createElement("action_sheet_head");
|
|
56
56
|
#title = document.createElement("action_sheet_title");
|
|
57
57
|
#message = document.createElement("action_sheet_message");
|
|
58
|
-
#
|
|
58
|
+
#actionsNode = document.createElement("action_sheet_actions");
|
|
59
59
|
#cancel = document.createElement("button");
|
|
60
60
|
#actions = [];
|
|
61
61
|
#rows = [];
|
|
62
|
-
#
|
|
62
|
+
#cancelText = undefined;
|
|
63
63
|
#closable = true;
|
|
64
|
-
#
|
|
65
|
-
#
|
|
64
|
+
#closeOutside = true;
|
|
65
|
+
#labelledByTitle = false;
|
|
66
66
|
#chosen = undefined;
|
|
67
67
|
#a11y = undefined;
|
|
68
|
-
#
|
|
69
|
-
#
|
|
68
|
+
#onSelect = undefined;
|
|
69
|
+
#onClose = undefined;
|
|
70
70
|
isOpen = false;
|
|
71
71
|
|
|
72
72
|
constructor(
|
|
@@ -88,10 +88,10 @@ class ActionSheet {
|
|
|
88
88
|
this.#id = options.id === undefined ? `chui_action_sheet_${ActionSheet.#counter}` : options.id;
|
|
89
89
|
this.#sheet.id = this.#id;
|
|
90
90
|
this.#closable = options.closable !== false;
|
|
91
|
-
if (options.closeOnOutsideClick !== undefined) this.#
|
|
92
|
-
this.#
|
|
93
|
-
this.#
|
|
94
|
-
this.#
|
|
91
|
+
if (options.closeOnOutsideClick !== undefined) this.#closeOutside = options.closeOnOutsideClick !== false;
|
|
92
|
+
this.#cancelText = options.cancelText;
|
|
93
|
+
this.#onSelect = options.onSelect;
|
|
94
|
+
this.#onClose = options.onClose;
|
|
95
95
|
|
|
96
96
|
this.#title.id = `${this.#id}_title`;
|
|
97
97
|
this.#message.id = `${this.#id}_message`;
|
|
@@ -100,20 +100,20 @@ class ActionSheet {
|
|
|
100
100
|
this.#cancel.addEventListener("click", this.#onCancelClick);
|
|
101
101
|
|
|
102
102
|
this.#group.appendChild(this.#head);
|
|
103
|
-
this.#group.appendChild(this.#
|
|
103
|
+
this.#group.appendChild(this.#actionsNode);
|
|
104
104
|
this.#panel.appendChild(this.#group);
|
|
105
105
|
this.#panel.appendChild(this.#cancel);
|
|
106
106
|
this.#sheet.appendChild(this.#panel);
|
|
107
107
|
document.body.appendChild(this.#sheet);
|
|
108
108
|
// Заголовок в разметке — имя слоя; иначе имя берётся из label или словаря
|
|
109
109
|
const title = optionOr(options.title, undefined);
|
|
110
|
-
this.#
|
|
110
|
+
this.#labelledByTitle = title !== undefined;
|
|
111
111
|
if (title !== undefined) this.setTitle(title);
|
|
112
112
|
if (optionOr(options.message, undefined) !== undefined) this.setMessage(options.message);
|
|
113
113
|
this.#a11y = new OverlayA11y(this.#sheet, {
|
|
114
114
|
role: "dialog",
|
|
115
|
-
labelNode: this.#
|
|
116
|
-
label: this.#
|
|
115
|
+
labelNode: this.#labelledByTitle ? this.#title : undefined,
|
|
116
|
+
label: this.#labelledByTitle ? undefined : optionOr(options.label, I18n.t("feedback.actionSheet")),
|
|
117
117
|
onEscape: () => this.close(),
|
|
118
118
|
});
|
|
119
119
|
this.#syncCancelText();
|
|
@@ -146,7 +146,7 @@ class ActionSheet {
|
|
|
146
146
|
setTitle(text = String()) {
|
|
147
147
|
this.#title.innerText = text;
|
|
148
148
|
this.#syncHead();
|
|
149
|
-
if (!this.#
|
|
149
|
+
if (!this.#labelledByTitle) this.#a11y.setLabel(text);
|
|
150
150
|
return this;
|
|
151
151
|
}
|
|
152
152
|
setMessage(text = String()) {
|
|
@@ -155,7 +155,7 @@ class ActionSheet {
|
|
|
155
155
|
return this;
|
|
156
156
|
}
|
|
157
157
|
setCancelText(text = String()) {
|
|
158
|
-
this.#
|
|
158
|
+
this.#cancelText = text;
|
|
159
159
|
this.#syncCancelText();
|
|
160
160
|
return this;
|
|
161
161
|
}
|
|
@@ -163,7 +163,7 @@ class ActionSheet {
|
|
|
163
163
|
setActions(actions = []) {
|
|
164
164
|
this.#actions = [];
|
|
165
165
|
this.#rows = [];
|
|
166
|
-
this.#
|
|
166
|
+
this.#actionsNode.innerHTML = "";
|
|
167
167
|
for (const action of actions) this.#appendAction(action);
|
|
168
168
|
return this;
|
|
169
169
|
}
|
|
@@ -177,6 +177,7 @@ class ActionSheet {
|
|
|
177
177
|
this.isOpen = true;
|
|
178
178
|
this.#chosen = undefined;
|
|
179
179
|
this.#panel.style.animationName = "action_sheet_in";
|
|
180
|
+
this.#panel.dataset.motion = "enter";
|
|
180
181
|
new Animation(this.#sheet).fadeIn();
|
|
181
182
|
this.#a11y.open();
|
|
182
183
|
return this;
|
|
@@ -190,8 +191,9 @@ class ActionSheet {
|
|
|
190
191
|
this.isOpen = false;
|
|
191
192
|
this.#a11y.close();
|
|
192
193
|
this.#panel.style.animationName = "action_sheet_out";
|
|
194
|
+
this.#panel.dataset.motion = "exit";
|
|
193
195
|
new Animation(this.#sheet).fadeOut();
|
|
194
|
-
if (this.#chosen === undefined && this.#
|
|
196
|
+
if (this.#chosen === undefined && this.#onClose !== undefined) this.#onClose();
|
|
195
197
|
return this;
|
|
196
198
|
}
|
|
197
199
|
/** Полное удаление: закрыть слой, снять слушатели и убрать занавес из документа */
|
|
@@ -211,12 +213,13 @@ class ActionSheet {
|
|
|
211
213
|
* Временный слой после ответа убирается: иначе каждый вызов оставлял бы узел в документе */
|
|
212
214
|
static show(options = {}) {
|
|
213
215
|
return new Promise((resolve) => {
|
|
214
|
-
let sheet;
|
|
215
216
|
const answer = (value) => {
|
|
216
217
|
resolve(value);
|
|
217
218
|
sheet.destroy();
|
|
218
219
|
};
|
|
219
|
-
|
|
220
|
+
// Слой собирается один раз, и `answer` зовут только после сборки:
|
|
221
|
+
// к моменту вызова имя уже определено, поэтому здесь можно `const`
|
|
222
|
+
const sheet = new ActionSheet(
|
|
220
223
|
Object.assign({}, options, {
|
|
221
224
|
onSelect: (action, index) => {
|
|
222
225
|
if (options.onSelect !== undefined) options.onSelect(action, index);
|
|
@@ -256,19 +259,19 @@ class ActionSheet {
|
|
|
256
259
|
row.addEventListener("click", () => this.#choose(action, this.#actions.indexOf(action)));
|
|
257
260
|
this.#actions.push(action);
|
|
258
261
|
this.#rows.push(row);
|
|
259
|
-
this.#
|
|
262
|
+
this.#actionsNode.appendChild(row);
|
|
260
263
|
return row;
|
|
261
264
|
}
|
|
262
265
|
#choose(action = {}, index = -1) {
|
|
263
266
|
if (action.disabled === true) return;
|
|
264
267
|
this.#chosen = action;
|
|
265
268
|
if (action.onClick !== undefined) action.onClick(action, index);
|
|
266
|
-
if (this.#
|
|
269
|
+
if (this.#onSelect !== undefined) this.#onSelect(action, index);
|
|
267
270
|
this.close();
|
|
268
271
|
}
|
|
269
272
|
#onCancelClick = () => this.close();
|
|
270
273
|
#onSheetClick = (event) => {
|
|
271
|
-
if (!this.#
|
|
274
|
+
if (!this.#closeOutside || event.target !== this.#sheet) return;
|
|
272
275
|
this.close();
|
|
273
276
|
};
|
|
274
277
|
// После анимации имя снимается: иначе следующий показ не проиграется заново
|
|
@@ -278,18 +281,18 @@ class ActionSheet {
|
|
|
278
281
|
};
|
|
279
282
|
/** Заголовок и пояснение показываются, только когда заданы; пояснение — описание слоя */
|
|
280
283
|
#syncHead() {
|
|
281
|
-
const
|
|
282
|
-
const
|
|
283
|
-
if (
|
|
284
|
-
if (!
|
|
285
|
-
if (
|
|
286
|
-
if (!
|
|
287
|
-
this.#head.style.display =
|
|
288
|
-
if (
|
|
284
|
+
const hasTitle = this.#title.innerText.trim() !== "";
|
|
285
|
+
const hasMessage = this.#message.innerText.trim() !== "";
|
|
286
|
+
if (hasTitle && this.#title.parentElement === null) this.#head.appendChild(this.#title);
|
|
287
|
+
if (!hasTitle && this.#title.parentElement !== null) this.#title.remove();
|
|
288
|
+
if (hasMessage && this.#message.parentElement === null) this.#head.appendChild(this.#message);
|
|
289
|
+
if (!hasMessage && this.#message.parentElement !== null) this.#message.remove();
|
|
290
|
+
this.#head.style.display = hasTitle || hasMessage ? "" : "none";
|
|
291
|
+
if (hasMessage) this.#sheet.setAttribute("aria-describedby", this.#message.id);
|
|
289
292
|
else this.#sheet.removeAttribute("aria-describedby");
|
|
290
293
|
}
|
|
291
294
|
#syncCancelText() {
|
|
292
|
-
this.#cancel.innerText = this.#
|
|
295
|
+
this.#cancel.innerText = this.#cancelText === undefined ? I18n.t("common.cancel") : this.#cancelText;
|
|
293
296
|
this.#cancel.style.display = this.#closable ? "" : "none";
|
|
294
297
|
}
|
|
295
298
|
}
|
|
@@ -26,7 +26,13 @@ action_sheet_panel {
|
|
|
26
26
|
width: min(480px, 100%);
|
|
27
27
|
max-height: 80vh;
|
|
28
28
|
overflow-y: auto;
|
|
29
|
-
animation: action_sheet_in var(--
|
|
29
|
+
animation: action_sheet_in var(--motion_base) var(--motion_ease);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/* Вид движения ставит action_sheet.js: выезд идёт базовым временем из правила выше, а уход
|
|
33
|
+
берёт короткое — закрытие не задерживает следующий экран */
|
|
34
|
+
action_sheet_panel[data-motion="exit"] {
|
|
35
|
+
animation-duration: var(--motion_fast);
|
|
30
36
|
}
|
|
31
37
|
|
|
32
38
|
@keyframes action_sheet_in {
|
|
@@ -68,7 +74,7 @@ action_sheet_head {
|
|
|
68
74
|
display: flex;
|
|
69
75
|
flex-direction: column;
|
|
70
76
|
gap: 2px;
|
|
71
|
-
padding: var(--control_padding) var(--
|
|
77
|
+
padding: var(--control_padding) var(--block_padding);
|
|
72
78
|
text-align: center;
|
|
73
79
|
border-bottom: 1px solid var(--border_color);
|
|
74
80
|
}
|
|
@@ -102,7 +108,7 @@ action_sheet_actions {
|
|
|
102
108
|
width: 100%;
|
|
103
109
|
box-sizing: border-box;
|
|
104
110
|
min-height: 44px;
|
|
105
|
-
padding: var(--
|
|
111
|
+
padding: var(--block_padding);
|
|
106
112
|
background: transparent;
|
|
107
113
|
border: none;
|
|
108
114
|
border-top: 1px solid var(--border_color);
|
|
@@ -172,7 +178,7 @@ action_sheet_action_description {
|
|
|
172
178
|
width: 100%;
|
|
173
179
|
box-sizing: border-box;
|
|
174
180
|
min-height: 44px;
|
|
175
|
-
padding: var(--
|
|
181
|
+
padding: var(--block_padding);
|
|
176
182
|
border-radius: var(--radius_md);
|
|
177
183
|
background: var(--modal_background);
|
|
178
184
|
border: 1px solid var(--border_color);
|
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
const { Icon } = require("../chui_icons/icons");
|
|
2
|
+
const { I18n } = require("../../modules/chui_i18n/chui_i18n");
|
|
3
|
+
const { Toolbar } = require("../chui_toolbar/toolbar");
|
|
4
|
+
const { optionOr, setStyles } = require("../../modules/chui_functions");
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Действие панели: значок с подписью, состоянием переключателя и счётчиком.
|
|
8
|
+
*
|
|
9
|
+
* Это настоящий `<button>`: клавиатура, фокус и роль у него уже есть. Переключатель
|
|
10
|
+
* (`toggle`) объявляет себя `aria-pressed` — «закреплено», «без звука» это состояние,
|
|
11
|
+
* а не действие, и скринридер обязан его читать. Опасное действие (удалить, очистить)
|
|
12
|
+
* помечается `danger` — подписью красного цвета, без отдельной иконки-предупреждения.
|
|
13
|
+
*/
|
|
14
|
+
class ActionsBarButton {
|
|
15
|
+
static #counter = 0;
|
|
16
|
+
|
|
17
|
+
#root = document.createElement("button");
|
|
18
|
+
#iconNode = document.createElement("actions_bar_button_icon");
|
|
19
|
+
#text = document.createElement("actions_bar_button_text");
|
|
20
|
+
#badge = document.createElement("actions_bar_badge");
|
|
21
|
+
#id = undefined;
|
|
22
|
+
#label = undefined;
|
|
23
|
+
#active = false;
|
|
24
|
+
#toggle = false;
|
|
25
|
+
#disabled = false;
|
|
26
|
+
#danger = false;
|
|
27
|
+
#onClick = undefined;
|
|
28
|
+
#onToggle = undefined;
|
|
29
|
+
|
|
30
|
+
constructor(options = {}) {
|
|
31
|
+
const id = optionOr(options.id, undefined);
|
|
32
|
+
this.#id = id === undefined ? String((ActionsBarButton.#counter += 1)) : String(id);
|
|
33
|
+
this.#label = options.label === undefined ? "" : String(options.label);
|
|
34
|
+
this.#toggle = options.toggle === true;
|
|
35
|
+
this.#danger = options.danger === true;
|
|
36
|
+
this.#onClick = typeof options.onClick === "function" ? options.onClick : undefined;
|
|
37
|
+
// Свой слушатель состояния — им о переключении узнаёт панель (публичного `onToggle` нет)
|
|
38
|
+
this.#onToggle = typeof options.onToggle === "function" ? options.onToggle : undefined;
|
|
39
|
+
this.#root.type = "button";
|
|
40
|
+
this.#root.className = "actions_bar_button";
|
|
41
|
+
this.#root.dataset.id = this.#id;
|
|
42
|
+
if (optionOr(options.icon, undefined) !== undefined)
|
|
43
|
+
this.#iconNode.innerHTML = new Icon(options.icon, "18px").getHTML();
|
|
44
|
+
this.#iconNode.setAttribute("aria-hidden", "true");
|
|
45
|
+
this.#text.innerText = this.#label;
|
|
46
|
+
this.#root.append(this.#iconNode, this.#text);
|
|
47
|
+
// Значка нет — кнопка подписью не обходится: имя ей даёт подсказка или словарь
|
|
48
|
+
if (this.#label === "") this.setLabel(optionOr(options.hint, I18n.t("feedback.actionsBarButton")));
|
|
49
|
+
else this.#syncName();
|
|
50
|
+
if (this.#danger === true) this.#root.dataset.danger = "true";
|
|
51
|
+
if (this.#toggle === true) this.setActive(options.active === true);
|
|
52
|
+
if (options.badge !== undefined) this.setBadge(options.badge);
|
|
53
|
+
if (options.disabled === true) this.setDisabled(true);
|
|
54
|
+
this.#root.addEventListener("click", () => {
|
|
55
|
+
if (this.#disabled === true) return;
|
|
56
|
+
if (this.#toggle === true) {
|
|
57
|
+
this.setActive(this.#active === false);
|
|
58
|
+
if (this.#onToggle !== undefined) this.#onToggle(this);
|
|
59
|
+
}
|
|
60
|
+
if (this.#onClick !== undefined) this.#onClick(this, this.#active);
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
getId() {
|
|
65
|
+
return this.#id;
|
|
66
|
+
}
|
|
67
|
+
getLabel() {
|
|
68
|
+
return this.#text.innerText;
|
|
69
|
+
}
|
|
70
|
+
/** Переключатель включён: «закреплено», «без звука» */
|
|
71
|
+
isActive() {
|
|
72
|
+
return this.#active;
|
|
73
|
+
}
|
|
74
|
+
isDisabled() {
|
|
75
|
+
return this.#disabled;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Состояние переключателя: видно подложкой, скринридеру — через `aria-pressed`.
|
|
80
|
+
* У обычного действия состояния нет: `setActive` на нём ничего не делает — подсветка
|
|
81
|
+
* без программного состояния читалась бы как выбранное действие
|
|
82
|
+
*/
|
|
83
|
+
setActive(boolean = Boolean()) {
|
|
84
|
+
if (this.#toggle !== true) return this;
|
|
85
|
+
this.#active = boolean === true;
|
|
86
|
+
this.#root.dataset.active = this.#active ? "true" : "false";
|
|
87
|
+
this.#root.setAttribute("aria-pressed", this.#active ? "true" : "false");
|
|
88
|
+
return this;
|
|
89
|
+
}
|
|
90
|
+
setDisabled(boolean = Boolean()) {
|
|
91
|
+
this.#disabled = boolean === true;
|
|
92
|
+
this.#root.disabled = this.#disabled;
|
|
93
|
+
return this;
|
|
94
|
+
}
|
|
95
|
+
/** Счётчик действия: число показывает плашка, скринридеру оно попадает в имя */
|
|
96
|
+
setBadge(count = Number()) {
|
|
97
|
+
const value = Number(count);
|
|
98
|
+
const shown = Number.isFinite(value) && value > 0 ? String(value) : "";
|
|
99
|
+
this.#badge.innerText = shown;
|
|
100
|
+
this.#badge.hidden = shown === "";
|
|
101
|
+
if (shown !== "" && this.#badge.parentNode === null) this.#root.appendChild(this.#badge);
|
|
102
|
+
this.#syncName(shown);
|
|
103
|
+
return this;
|
|
104
|
+
}
|
|
105
|
+
setLabel(text = String()) {
|
|
106
|
+
const label = String(text);
|
|
107
|
+
if (this.#label === "") {
|
|
108
|
+
// Кнопка без подписи: имя живёт только в атрибутах и подсказке
|
|
109
|
+
this.#root.setAttribute("aria-label", label);
|
|
110
|
+
this.#root.title = label;
|
|
111
|
+
return this;
|
|
112
|
+
}
|
|
113
|
+
this.#root.setAttribute("aria-label", label);
|
|
114
|
+
this.#text.innerText = label;
|
|
115
|
+
return this;
|
|
116
|
+
}
|
|
117
|
+
/** Имя кнопки: своя подпись или значок с подсказкой, плюс счётчик, если он есть */
|
|
118
|
+
#syncName(count = undefined) {
|
|
119
|
+
if (this.#label === "") return;
|
|
120
|
+
const shown = count === undefined ? (this.#badge.hidden ? "" : this.#badge.innerText) : count;
|
|
121
|
+
this.#root.setAttribute(
|
|
122
|
+
"aria-label",
|
|
123
|
+
shown === "" ? this.#label : `${this.#label}, ${I18n.t("feedback.actionsBarBadge", { value: shown })}`
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
set() {
|
|
128
|
+
return this.#root;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Панель действий — что можно сделать с тем, о чём сейчас речь.
|
|
134
|
+
*
|
|
135
|
+
* Пятая часть мессенджера: список разговоров слева, шапка разговора, **панель действий**,
|
|
136
|
+
* лента сообщений и панель ввода — так собирается экран переписки. Панель ставят и под
|
|
137
|
+
* шапкой разговора, и в карточке файла или профиля: она не полагает, о чём именно действия.
|
|
138
|
+
*
|
|
139
|
+
* Действия — подписанные кнопки со значком: «Закрепить», «Без звука», «Найти в переписке»,
|
|
140
|
+
* «Очистить историю». Часть из них — переключатели (`toggle: true`): у них есть состояние,
|
|
141
|
+
* и оно объявляется `aria-pressed`, а видно по подложке. Опасное действие помечается
|
|
142
|
+
* `danger: true` — подписью красного цвета.
|
|
143
|
+
*
|
|
144
|
+
* Панель держит `Toolbar` внутри: стрелки ←/→ ходят по действиям, Home и End ведут к краям,
|
|
145
|
+
* а Tab проходит по кнопкам по очереди — каждая из них настоящий `<button>`, как у полосы
|
|
146
|
+
* пользователя и панели ввода. Строка клавиатуры внутри панели своей кромки не рисует:
|
|
147
|
+
* панель и полоса — одна поверхность, и вложенная ступень здесь была бы лишней.
|
|
148
|
+
*
|
|
149
|
+
* ```javascript
|
|
150
|
+
* const actions = new ActionsBar({
|
|
151
|
+
* title: 'Разговор',
|
|
152
|
+
* actions: [
|
|
153
|
+
* { id: 'pin', icon: Icons.CONTENT.PUSH_PIN, label: 'Закрепить', toggle: true },
|
|
154
|
+
* { id: 'mute', icon: Icons.SOCIAL.NOTIFICATIONS_OFF, label: 'Без звука', toggle: true, active: true },
|
|
155
|
+
* { id: 'find', icon: Icons.ACTIONS.SEARCH, label: 'Найти в переписке', onClick: () => find() },
|
|
156
|
+
* { id: 'clear', icon: Icons.ACTIONS.DELETE, label: 'Очистить историю', danger: true, onClick: () => clear() },
|
|
157
|
+
* ],
|
|
158
|
+
* onChange: (button) => Log.info(button.getId(), button.isActive()),
|
|
159
|
+
* });
|
|
160
|
+
* ```
|
|
161
|
+
*
|
|
162
|
+
* Опции: `id`, `title`, `label`, `orientation`, `actions`, `onChange`.
|
|
163
|
+
* Действие: `{ id, icon, label, hint, badge, toggle, active, danger, disabled, onClick }`;
|
|
164
|
+
* фабрика — `ActionsBar.Button(...)`.
|
|
165
|
+
* API: `setTitle(text)`, `getTitle()`, `setLabel(text)`, `setOrientation(o)`, `getOrientation()`,
|
|
166
|
+
* `addAction(options)`, `removeAction(id)`, `setActions(list)`, `clear()`, `getActions()`,
|
|
167
|
+
* `getAction(id)`, `setActive(id, bool)`, `toggle(id)`, `getActive()`, `setDisabled(id, bool)`,
|
|
168
|
+
* `setBadge(id, count)`, `getToolbar()`, `set()`, `destroy()`.
|
|
169
|
+
* Константа: `ActionsBar.ORIENTATION.{HORIZONTAL, VERTICAL}`.
|
|
170
|
+
*
|
|
171
|
+
* **Строка или столбец.** По умолчанию действия идут строкой с переносом — так панель стоит
|
|
172
|
+
* под шапкой разговора. `ORIENTATION.VERTICAL` ставит их столбцом во всю ширину, как пункты
|
|
173
|
+
* меню: в таком виде панель кладут в выпадающее меню — например, в кнопку «⋯» полосы
|
|
174
|
+
* пользователя (`UserBar({ menu: [...] })`), и отдельная полоса в шапке не нужна.
|
|
175
|
+
*/
|
|
176
|
+
class ActionsBar {
|
|
177
|
+
/** Фабрика действия: `ActionsBar.Button({ icon, label, toggle, danger, onClick })` */
|
|
178
|
+
static Button = (options = {}) => new ActionsBarButton(options);
|
|
179
|
+
static ORIENTATION = Toolbar.ORIENTATION;
|
|
180
|
+
static #counter = 0;
|
|
181
|
+
|
|
182
|
+
#id = undefined;
|
|
183
|
+
#root = document.createElement("chui_actions_bar");
|
|
184
|
+
#title = document.createElement("actions_bar_title");
|
|
185
|
+
#toolbar = undefined;
|
|
186
|
+
#actions = [];
|
|
187
|
+
#label = undefined;
|
|
188
|
+
#orientation = undefined;
|
|
189
|
+
#onChange = undefined;
|
|
190
|
+
|
|
191
|
+
constructor(
|
|
192
|
+
options = {
|
|
193
|
+
id: String(),
|
|
194
|
+
title: String(),
|
|
195
|
+
label: String(),
|
|
196
|
+
orientation: String(),
|
|
197
|
+
actions: [],
|
|
198
|
+
onChange: undefined,
|
|
199
|
+
}
|
|
200
|
+
) {
|
|
201
|
+
setStyles(__dirname + "/styles.css", "chUiJS_ActionsBar");
|
|
202
|
+
ActionsBar.#counter += 1;
|
|
203
|
+
this.#id = options.id === undefined ? `chui_actions_bar_${ActionsBar.#counter}` : options.id;
|
|
204
|
+
this.#root.id = this.#id;
|
|
205
|
+
this.#label = options.label;
|
|
206
|
+
this.#onChange = typeof options.onChange === "function" ? options.onChange : undefined;
|
|
207
|
+
this.#toolbar = new Toolbar({ label: this.#labelText() });
|
|
208
|
+
this.setOrientation(
|
|
209
|
+
options.orientation === undefined ? ActionsBar.ORIENTATION.HORIZONTAL : options.orientation
|
|
210
|
+
);
|
|
211
|
+
this.#title.hidden = true;
|
|
212
|
+
this.#root.append(this.#title, this.#toolbar.set());
|
|
213
|
+
if (options.title !== undefined) this.setTitle(options.title);
|
|
214
|
+
if (Array.isArray(options.actions)) for (const action of options.actions) this.addAction(action);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// GET
|
|
218
|
+
getId() {
|
|
219
|
+
return this.#id;
|
|
220
|
+
}
|
|
221
|
+
getTitle() {
|
|
222
|
+
return this.#title.hidden ? "" : this.#title.innerText;
|
|
223
|
+
}
|
|
224
|
+
getOrientation() {
|
|
225
|
+
return this.#orientation;
|
|
226
|
+
}
|
|
227
|
+
getActions() {
|
|
228
|
+
return this.#actions.slice();
|
|
229
|
+
}
|
|
230
|
+
getAction(id = String()) {
|
|
231
|
+
return this.#actions.find((button) => button.getId() === String(id));
|
|
232
|
+
}
|
|
233
|
+
/** Идентификаторы включённых переключателей — состояние панели одним списком */
|
|
234
|
+
getActive() {
|
|
235
|
+
return this.#actions.filter((button) => button.isActive() === true).map((button) => button.getId());
|
|
236
|
+
}
|
|
237
|
+
/** Полоса действий: нужна тому, кто ставит в панель своё рядом с кнопками */
|
|
238
|
+
getToolbar() {
|
|
239
|
+
return this.#toolbar;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// SET
|
|
243
|
+
/** Подпись панели: над действиями, объясняет, к чему они относятся */
|
|
244
|
+
setTitle(text = String()) {
|
|
245
|
+
this.#title.innerText = String(text);
|
|
246
|
+
this.#title.hidden = this.#title.innerText.trim() === "";
|
|
247
|
+
return this;
|
|
248
|
+
}
|
|
249
|
+
/** Имя панели для скринридера: по умолчанию — общая подпись из словаря */
|
|
250
|
+
setLabel(text = String()) {
|
|
251
|
+
this.#label = text;
|
|
252
|
+
this.#toolbar.setLabel(this.#labelText());
|
|
253
|
+
return this;
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Строка или столбец: столбец — вид меню, в нём действия идут во всю ширину.
|
|
257
|
+
* Ориентацию несёт и полоса внутри (`Toolbar`), и сама панель — по ней считаются отступы
|
|
258
|
+
*/
|
|
259
|
+
setOrientation(orientation = String()) {
|
|
260
|
+
this.#orientation =
|
|
261
|
+
orientation === ActionsBar.ORIENTATION.VERTICAL
|
|
262
|
+
? ActionsBar.ORIENTATION.VERTICAL
|
|
263
|
+
: ActionsBar.ORIENTATION.HORIZONTAL;
|
|
264
|
+
this.#root.dataset.orientation = this.#orientation;
|
|
265
|
+
this.#toolbar.setOrientation(this.#orientation);
|
|
266
|
+
return this;
|
|
267
|
+
}
|
|
268
|
+
setActions(actions = []) {
|
|
269
|
+
this.clear();
|
|
270
|
+
for (const action of actions) this.addAction(action);
|
|
271
|
+
return this;
|
|
272
|
+
}
|
|
273
|
+
addAction(options = {}) {
|
|
274
|
+
const button =
|
|
275
|
+
options instanceof ActionsBarButton
|
|
276
|
+
? options
|
|
277
|
+
: new ActionsBarButton(Object.assign({}, options, { onToggle: (instance) => this.#notify(instance) }));
|
|
278
|
+
this.#actions.push(button);
|
|
279
|
+
this.#toolbar.add(button);
|
|
280
|
+
return button;
|
|
281
|
+
}
|
|
282
|
+
removeAction(id = String()) {
|
|
283
|
+
const index = this.#actions.findIndex((button) => button.getId() === String(id));
|
|
284
|
+
if (index === -1) return this;
|
|
285
|
+
const [button] = this.#actions.splice(index, 1);
|
|
286
|
+
button.set().remove();
|
|
287
|
+
return this;
|
|
288
|
+
}
|
|
289
|
+
clear() {
|
|
290
|
+
for (const button of this.#actions) button.set().remove();
|
|
291
|
+
this.#actions = [];
|
|
292
|
+
return this;
|
|
293
|
+
}
|
|
294
|
+
/** Включить или выключить переключатель из кода: состояние то же, что после щелчка */
|
|
295
|
+
setActive(id = String(), boolean = Boolean()) {
|
|
296
|
+
const button = this.getAction(id);
|
|
297
|
+
if (button === undefined || button.isActive() === boolean) return this;
|
|
298
|
+
button.setActive(boolean);
|
|
299
|
+
this.#notify(button);
|
|
300
|
+
return this;
|
|
301
|
+
}
|
|
302
|
+
toggle(id = String()) {
|
|
303
|
+
const button = this.getAction(id);
|
|
304
|
+
if (button === undefined) return this;
|
|
305
|
+
return this.setActive(id, button.isActive() === false);
|
|
306
|
+
}
|
|
307
|
+
setDisabled(id = String(), boolean = Boolean()) {
|
|
308
|
+
const button = this.getAction(id);
|
|
309
|
+
if (button !== undefined) button.setDisabled(boolean);
|
|
310
|
+
return this;
|
|
311
|
+
}
|
|
312
|
+
setBadge(id = String(), count = Number()) {
|
|
313
|
+
const button = this.getAction(id);
|
|
314
|
+
if (button !== undefined) button.setBadge(count);
|
|
315
|
+
return this;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
set() {
|
|
319
|
+
return this.#root;
|
|
320
|
+
}
|
|
321
|
+
destroy() {
|
|
322
|
+
this.#actions = [];
|
|
323
|
+
this.#onChange = undefined;
|
|
324
|
+
this.#root.remove();
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
// === ВНУТРЕННЕЕ ===
|
|
328
|
+
/** О смене состояния сообщается один раз: и после щелчка, и после правки из кода */
|
|
329
|
+
#notify(button) {
|
|
330
|
+
if (this.#onChange !== undefined) this.#onChange(button, this);
|
|
331
|
+
}
|
|
332
|
+
#labelText() {
|
|
333
|
+
return optionOr(this.#label, undefined) === undefined ? I18n.t("feedback.actionsBar") : String(this.#label);
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
exports.ActionsBar = ActionsBar;
|
|
338
|
+
exports.ActionsBarButton = ActionsBarButton;
|