chuijs 4.0.2 → 4.0.3
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 +61 -0
- package/README.md +43 -644
- package/framework/appLayout/default/chui_app_layout.js +308 -260
- package/framework/appLayout/default/global_style.css +85 -48
- package/framework/components/chui_accordion/accordion.js +29 -26
- package/framework/components/chui_accordion/styles.css +6 -5
- package/framework/components/chui_action_sheet/action_sheet.js +59 -33
- package/framework/components/chui_action_sheet/styles.css +2 -1
- package/framework/components/chui_affix/affix.js +11 -6
- package/framework/components/chui_alert/alert.js +23 -14
- package/framework/components/chui_avatar/avatar.js +23 -22
- package/framework/components/chui_avatar_group/avatar_group.js +21 -19
- package/framework/components/chui_backtop/backtop.js +35 -19
- package/framework/components/chui_badge/badge.js +15 -13
- package/framework/components/chui_breadcrumb/breadcrumb.js +15 -13
- package/framework/components/chui_button/button.js +42 -22
- package/framework/components/chui_button/styles.css +2 -2
- package/framework/components/chui_calendar/calendar.js +12 -10
- package/framework/components/chui_card/card.js +43 -23
- package/framework/components/chui_chat/chat.js +72 -33
- package/framework/components/chui_clipboard_history/clipboard_history.js +30 -21
- package/framework/components/chui_clipboard_history/styles.css +4 -2
- package/framework/components/chui_code/code.js +2 -2
- package/framework/components/chui_code/styles.css +2 -2
- package/framework/components/chui_code_editor/code_editor.js +47 -31
- package/framework/components/chui_code_editor/styles.css +3 -2
- package/framework/components/chui_command_palette/command_palette.js +60 -37
- package/framework/components/chui_console/console.js +5 -5
- package/framework/components/chui_console/styles.css +1 -1
- package/framework/components/chui_content_block/content_block.js +33 -19
- package/framework/components/chui_content_block/styles.css +2 -2
- package/framework/components/chui_context_menu/context_menu.js +9 -4
- package/framework/components/chui_custom_element/custom_element.js +22 -15
- package/framework/components/chui_data_grid/data_grid.js +396 -234
- package/framework/components/chui_data_grid/styles.css +10 -8
- package/framework/components/chui_descriptions/descriptions.js +34 -17
- package/framework/components/chui_details/details.js +32 -26
- package/framework/components/chui_details/styles.css +5 -4
- package/framework/components/chui_diff_viewer/diff_viewer.js +91 -66
- package/framework/components/chui_diff_viewer/styles.css +1 -1
- package/framework/components/chui_divider/divider.js +13 -11
- package/framework/components/chui_drawer/drawer.js +27 -25
- package/framework/components/chui_drop_zone/drop_zone.js +31 -21
- package/framework/components/chui_empty_state/empty_state.js +20 -15
- package/framework/components/chui_fieldset/fieldset.js +37 -20
- package/framework/components/chui_fieldset/styles.css +1 -1
- package/framework/components/chui_file_explorer/file_explorer.js +157 -86
- package/framework/components/chui_file_explorer/styles.css +2 -1
- package/framework/components/chui_form/form.js +31 -19
- package/framework/components/chui_form/styles.css +1 -1
- package/framework/components/chui_gantt/gantt.js +64 -40
- package/framework/components/chui_graphs/graphs.js +301 -200
- package/framework/components/chui_graphs/styles.css +1 -1
- package/framework/components/chui_hero/hero.js +40 -22
- package/framework/components/chui_html_block/html_block.js +6 -6
- package/framework/components/chui_html_block/styles.css +2 -2
- package/framework/components/chui_hx/hx.js +3 -3
- package/framework/components/chui_hx/styles.css +11 -4
- package/framework/components/chui_icons/icons.js +2109 -2109
- package/framework/components/chui_icons/styles.css +2 -2
- package/framework/components/chui_inputs/chui_check_box/check_box.js +31 -19
- package/framework/components/chui_inputs/chui_check_box/styles.css +18 -18
- package/framework/components/chui_inputs/chui_chips/chips.js +50 -40
- package/framework/components/chui_inputs/chui_chips/styles.css +4 -2
- package/framework/components/chui_inputs/chui_color_picker/color_picker.js +36 -24
- package/framework/components/chui_inputs/chui_combo_box/combo_box.js +100 -82
- package/framework/components/chui_inputs/chui_combo_box/styles.css +14 -12
- package/framework/components/chui_inputs/chui_date/date.js +102 -66
- package/framework/components/chui_inputs/chui_date/styles.css +12 -11
- package/framework/components/chui_inputs/chui_date_range/date_range.js +40 -29
- package/framework/components/chui_inputs/chui_datetime/datetime.js +35 -27
- package/framework/components/chui_inputs/chui_email/email.js +43 -31
- package/framework/components/chui_inputs/chui_email/styles.css +5 -5
- package/framework/components/chui_inputs/chui_file/file.js +68 -41
- package/framework/components/chui_inputs/chui_file/styles.css +13 -12
- package/framework/components/chui_inputs/chui_hotkey/hotkey.js +61 -36
- package/framework/components/chui_inputs/chui_masked/masked.js +39 -28
- package/framework/components/chui_inputs/chui_mention/mention.js +77 -30
- package/framework/components/chui_inputs/chui_multi_combo_box/multi_combo_box.js +173 -153
- package/framework/components/chui_inputs/chui_multi_combo_box/styles.css +9 -7
- package/framework/components/chui_inputs/chui_number/number.js +58 -41
- package/framework/components/chui_inputs/chui_number/styles.css +7 -7
- package/framework/components/chui_inputs/chui_otp/otp.js +38 -29
- package/framework/components/chui_inputs/chui_password/password.js +58 -36
- package/framework/components/chui_inputs/chui_password/styles.css +8 -8
- package/framework/components/chui_inputs/chui_radio_button/radio_button.js +37 -25
- package/framework/components/chui_inputs/chui_radio_button/styles.css +20 -20
- package/framework/components/chui_inputs/chui_rating/rating.js +26 -22
- package/framework/components/chui_inputs/chui_select_box/select_box.js +102 -78
- package/framework/components/chui_inputs/chui_select_box/styles.css +11 -11
- package/framework/components/chui_inputs/chui_slider/slider.js +29 -26
- package/framework/components/chui_inputs/chui_slider/styles.css +2 -1
- package/framework/components/chui_inputs/chui_text/styles.css +8 -8
- package/framework/components/chui_inputs/chui_text/text.js +65 -44
- package/framework/components/chui_inputs/chui_text_area/styles.css +6 -6
- package/framework/components/chui_inputs/chui_text_area/text_area.js +51 -28
- package/framework/components/chui_inputs/chui_time/styles.css +5 -3
- package/framework/components/chui_inputs/chui_time/time.js +38 -27
- package/framework/components/chui_inputs/chui_toggle/styles.css +3 -3
- package/framework/components/chui_inputs/chui_toggle/toggle.js +16 -16
- package/framework/components/chui_json_editor/json_editor.js +53 -43
- package/framework/components/chui_json_viewer/json_viewer.js +52 -33
- package/framework/components/chui_json_viewer/styles.css +3 -2
- package/framework/components/chui_kanban/kanban.js +52 -34
- package/framework/components/chui_kbd/kbd.js +12 -10
- package/framework/components/chui_label/label.js +14 -12
- package/framework/components/chui_label/styles.css +2 -2
- package/framework/components/chui_link/link.js +27 -20
- package/framework/components/chui_list/list.js +31 -27
- package/framework/components/chui_list/styles.css +2 -1
- package/framework/components/chui_markdown_editor/markdown_editor.js +60 -44
- package/framework/components/chui_media/audio.js +326 -227
- package/framework/components/chui_media/audio_styles.css +40 -21
- package/framework/components/chui_media/image.js +70 -38
- package/framework/components/chui_media/image_compare.js +52 -21
- package/framework/components/chui_media/image_styles.css +3 -3
- package/framework/components/chui_media/video.js +155 -62
- package/framework/components/chui_media/video_styles.css +33 -16
- package/framework/components/chui_menu_bar/menu_bar.js +26 -24
- package/framework/components/chui_menu_bar/styles.css +4 -2
- package/framework/components/chui_modal/modal.js +44 -43
- package/framework/components/chui_modal/styles.css +3 -2
- package/framework/components/chui_notification/notification.js +50 -34
- package/framework/components/chui_notification/notification_download.js +31 -25
- package/framework/components/chui_notification/notification_download_progress.css +3 -2
- package/framework/components/chui_notification/notification_download_progress.js +47 -41
- package/framework/components/chui_notification/notification_update.js +23 -16
- package/framework/components/chui_notification/status_plate.js +2 -2
- package/framework/components/chui_notification/styles_download.css +1 -1
- package/framework/components/chui_notification/styles_update.css +1 -1
- package/framework/components/chui_org_chart/org_chart.js +74 -35
- package/framework/components/chui_pagination/pagination.js +62 -27
- package/framework/components/chui_paragraph/paragraph.js +2 -2
- package/framework/components/chui_paragraph/styles.css +1 -1
- package/framework/components/chui_popover/popover.js +49 -28
- package/framework/components/chui_popups/popups.js +137 -108
- package/framework/components/chui_popups/styles.css +2 -2
- package/framework/components/chui_print_button/print_button.js +33 -23
- package/framework/components/chui_progress_bar/progress_bar.js +23 -15
- package/framework/components/chui_progress_bar/styles.css +2 -2
- package/framework/components/chui_progress_ring/progress_ring.js +17 -15
- package/framework/components/chui_qrcode/qrcode.js +75 -31
- package/framework/components/chui_query_builder/query_builder.js +216 -123
- package/framework/components/chui_radio_group/radio_group.js +36 -26
- package/framework/components/chui_radio_group/styles.css +1 -1
- package/framework/components/chui_result/result.js +26 -16
- package/framework/components/chui_scheduler/scheduler.js +57 -35
- package/framework/components/chui_scheduler/styles.css +6 -2
- package/framework/components/chui_segmented_control/segmented_control.js +27 -21
- package/framework/components/chui_settings/settings.js +122 -48
- package/framework/components/chui_shortcut_help/shortcut_help.js +55 -32
- package/framework/components/chui_sidebar_nav/sidebar_nav.js +33 -23
- package/framework/components/chui_skeleton/skeleton.js +29 -24
- package/framework/components/chui_slideshow/slideshow.js +60 -41
- package/framework/components/chui_slideshow/styles.css +18 -12
- package/framework/components/chui_spinner/spinner.js +8 -8
- package/framework/components/chui_spinner/styles.css +0 -1
- package/framework/components/chui_split_button/split_button.js +23 -18
- package/framework/components/chui_split_button/styles.css +1 -1
- package/framework/components/chui_splitter/splitter.js +35 -28
- package/framework/components/chui_statistic/statistic.js +65 -38
- package/framework/components/chui_status_bar/status_bar.js +11 -9
- package/framework/components/chui_stepper/stepper.js +27 -22
- package/framework/components/chui_sticky_bar/sticky_bar.js +9 -4
- package/framework/components/chui_sticky_bar/styles.css +3 -1
- package/framework/components/chui_tabs/chui_tabs.js +28 -22
- package/framework/components/chui_tabs/styles.css +3 -3
- package/framework/components/chui_text_editor/styles.css +20 -19
- package/framework/components/chui_text_editor/text_editor.js +85 -61
- package/framework/components/chui_text_editor/text_editor_panel.js +346 -284
- package/framework/components/chui_theme_toggle/theme_toggle.js +27 -22
- package/framework/components/chui_timeline/timeline.js +14 -12
- package/framework/components/chui_toast_queue/toast_queue.js +52 -46
- package/framework/components/chui_toolbar/toolbar.js +20 -13
- package/framework/components/chui_tooltip/tooltip.js +37 -24
- package/framework/components/chui_tour/styles.css +8 -3
- package/framework/components/chui_tour/tour.js +61 -27
- package/framework/components/chui_transfer/styles.css +2 -1
- package/framework/components/chui_transfer/transfer.js +75 -42
- package/framework/components/chui_tree_table/tree_table.js +43 -29
- package/framework/components/chui_tree_view/styles.css +4 -2
- package/framework/components/chui_tree_view/tree_view.js +142 -99
- package/framework/components/chui_watermark/watermark.js +24 -16
- package/framework/components/chui_webview/styles.css +2 -2
- package/framework/components/chui_webview/webview.js +62 -50
- package/framework/components/telegram_bot/chui_telegram_bot.js +71 -64
- package/framework/modules/chui_a11y/chui_a11y.js +77 -46
- package/framework/modules/chui_animations/animations.js +42 -42
- package/framework/modules/chui_animations/styles.css +1 -1
- package/framework/modules/chui_bridge/preload.js +36 -25
- package/framework/modules/chui_functions.js +52 -50
- package/framework/modules/chui_highlight/chui_highlight.js +25 -22
- package/framework/modules/chui_i18n/chui_i18n.js +9 -7
- 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 +3 -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 +8 -8
- package/framework/modules/chui_i18n/locales/validate.js +3 -3
- package/framework/modules/chui_json/chui_json.js +9 -9
- package/framework/modules/chui_layout/chui_layout.js +12 -10
- package/framework/modules/chui_logger/chui_logger.js +29 -25
- package/framework/modules/chui_page/page.js +33 -27
- package/framework/modules/chui_qr/chui_qr.js +158 -67
- package/framework/modules/chui_scrollbar/chui_scrollbar.js +35 -24
- package/framework/modules/chui_scrollbar/styles.css +3 -1
- package/framework/modules/chui_services/chui_channels.js +27 -13
- package/framework/modules/chui_services/chui_services.js +39 -31
- package/framework/modules/chui_services/desktop.js +32 -31
- package/framework/modules/chui_sortable/chui_sortable.js +17 -12
- package/framework/modules/chui_validate/chui_validate.js +7 -4
- package/framework/tray_bar/chui_menu_items.js +136 -46
- package/index.d.ts +4814 -0
- package/index.js +385 -292
- package/package.json +79 -68
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
const { Icon, Icons } = require("../chui_icons/icons");
|
|
2
|
-
const {Label} = require(
|
|
3
|
-
const {makeKeyboardButton} = require("../../modules/chui_a11y/chui_a11y");
|
|
4
|
-
const {Log} = require("../../modules/chui_logger/chui_logger");
|
|
5
|
-
const {I18n} = require("../../modules/chui_i18n/chui_i18n");
|
|
6
|
-
const {setStyles, optionOr} = require("../../modules/chui_functions");
|
|
2
|
+
const { Label } = require("../chui_label/label");
|
|
3
|
+
const { makeKeyboardButton } = require("../../modules/chui_a11y/chui_a11y");
|
|
4
|
+
const { Log } = require("../../modules/chui_logger/chui_logger");
|
|
5
|
+
const { I18n } = require("../../modules/chui_i18n/chui_i18n");
|
|
6
|
+
const { setStyles, optionOr } = require("../../modules/chui_functions");
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Видеоплеер: кадр и плавающая полоса управления внутри кадра.
|
|
@@ -36,15 +36,28 @@ class Video {
|
|
|
36
36
|
#onPlay = () => this.#renderPlayState(true);
|
|
37
37
|
#onPause = () => this.#renderPlayState(false);
|
|
38
38
|
#onTimeUpdate = () => this.#renderProgress();
|
|
39
|
-
#onDurationChange = () => {
|
|
39
|
+
#onDurationChange = () => {
|
|
40
|
+
this.#setSliderMax();
|
|
41
|
+
this.#renderProgress();
|
|
42
|
+
};
|
|
40
43
|
#onBuffered = () => this.#displayBufferedAmount();
|
|
41
44
|
#onEnter = () => this.#openPanel();
|
|
42
45
|
#onLeave = () => this.#closePanel();
|
|
43
|
-
constructor(
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
46
|
+
constructor(
|
|
47
|
+
options = {
|
|
48
|
+
src: String(),
|
|
49
|
+
autoplay: Boolean(),
|
|
50
|
+
controls: Boolean(),
|
|
51
|
+
loop: Boolean(),
|
|
52
|
+
muted: Boolean(),
|
|
53
|
+
volume: Number(),
|
|
54
|
+
poster: String(),
|
|
55
|
+
width: String(),
|
|
56
|
+
height: String(),
|
|
57
|
+
label: String(),
|
|
58
|
+
}
|
|
59
|
+
) {
|
|
60
|
+
setStyles(__dirname + "/video_styles.css", "chUiJS_Video");
|
|
48
61
|
// Плеер — именованная группа: своих ролей у панели нет, а без имени скринридер
|
|
49
62
|
// читает подряд безымянные кнопки без контекста
|
|
50
63
|
this.#chui_vp_main.setAttribute("role", "group");
|
|
@@ -78,7 +91,7 @@ class Video {
|
|
|
78
91
|
this.#chui_vt.addEventListener("volumechange", () => this.#renderVolume());
|
|
79
92
|
this.#chui_vt.addEventListener("error", () => {
|
|
80
93
|
Log.error(`[Video] не удалось прочитать дорожку: ${this.getSrc()}`);
|
|
81
|
-
this.#setStatus(I18n.t("media.videoNotPlaying", {reason: I18n.t("media.error.sourceFailed")}));
|
|
94
|
+
this.#setStatus(I18n.t("media.videoNotPlaying", { reason: I18n.t("media.error.sourceFailed") }));
|
|
82
95
|
});
|
|
83
96
|
this.#chui_vp_main.addEventListener("mouseenter", this.#onEnter);
|
|
84
97
|
this.#chui_vp_main.addEventListener("mouseleave", this.#onLeave);
|
|
@@ -98,7 +111,7 @@ class Video {
|
|
|
98
111
|
this.#setButton(this.#chui_vp_play_pause, I18n.t("media.play"), Icons.AUDIO_VIDEO.PLAY_ARROW);
|
|
99
112
|
this.#setButton(this.#chui_vp_volume_icon, I18n.t("media.mute"), Icons.AUDIO_VIDEO.VOLUME_UP);
|
|
100
113
|
this.#setButton(this.#chui_vp_full_mode, I18n.t("media.fullscreen"), Icons.NAVIGATION.FULLSCREEN);
|
|
101
|
-
this.#chui_vp_time = new Label({text: this.#calculateTime(0)});
|
|
114
|
+
this.#chui_vp_time = new Label({ text: this.#calculateTime(0) });
|
|
102
115
|
this.#chui_vp_seek.type = "range";
|
|
103
116
|
this.#chui_vp_seek.id = "chui_vp_seek";
|
|
104
117
|
this.#chui_vp_seek.max = "0";
|
|
@@ -133,15 +146,17 @@ class Video {
|
|
|
133
146
|
if (!this.#controls) return;
|
|
134
147
|
this.#chui_vp_main.classList.add("vp_panel_open");
|
|
135
148
|
}
|
|
136
|
-
#closePanel() {
|
|
149
|
+
#closePanel() {
|
|
150
|
+
this.#chui_vp_main.classList.remove("vp_panel_open");
|
|
151
|
+
}
|
|
137
152
|
#playPause = async () => {
|
|
138
153
|
if (this.getPaused()) await this.play();
|
|
139
154
|
else this.pause();
|
|
140
|
-
}
|
|
155
|
+
};
|
|
141
156
|
#toggleFullscreen = async () => {
|
|
142
157
|
if (document.fullscreenElement === null) await this.requestFullscreen();
|
|
143
158
|
else await this.exitFullscreen();
|
|
144
|
-
}
|
|
159
|
+
};
|
|
145
160
|
#renderPlayState(playing) {
|
|
146
161
|
this.#setIcon(this.#chui_vp_play_pause, playing ? Icons.AUDIO_VIDEO.PAUSE : Icons.AUDIO_VIDEO.PLAY_ARROW);
|
|
147
162
|
this.#setLabel(this.#chui_vp_play_pause, playing ? I18n.t("media.pause") : I18n.t("media.play"));
|
|
@@ -150,21 +165,23 @@ class Video {
|
|
|
150
165
|
const доля = Math.min(100, Math.max(0, Math.round(this.#chui_vt.volume * 100)));
|
|
151
166
|
this.#chui_vp_volume.value = String(доля);
|
|
152
167
|
this.#chui_vp_volume.disabled = this.getMuted();
|
|
153
|
-
this.#chui_vp_main.style.setProperty(
|
|
154
|
-
this.#setIcon(
|
|
155
|
-
|
|
168
|
+
this.#chui_vp_main.style.setProperty("--volume-before-width", `${доля}%`);
|
|
169
|
+
this.#setIcon(
|
|
170
|
+
this.#chui_vp_volume_icon,
|
|
171
|
+
this.getMuted() || this.#chui_vt.volume === 0 ? Icons.AUDIO_VIDEO.VOLUME_OFF : Icons.AUDIO_VIDEO.VOLUME_UP
|
|
172
|
+
);
|
|
156
173
|
this.#chui_vp_volume_icon.setAttribute("aria-label", I18n.t(this.getMuted() ? "media.unmute" : "media.mute"));
|
|
157
|
-
}
|
|
174
|
+
};
|
|
158
175
|
#displayBufferedAmount = () => {
|
|
159
176
|
const max = Number(this.#chui_vp_seek.max);
|
|
160
177
|
if (!(max > 0)) return;
|
|
161
178
|
try {
|
|
162
|
-
const end = Math.floor(this.#chui_vt.buffered.end(0) / max * 100);
|
|
179
|
+
const end = Math.floor((this.#chui_vt.buffered.end(0) / max) * 100);
|
|
163
180
|
this.#chui_vp_seek_buf.style.width = `${Math.min(100, Math.max(0, end))}%`;
|
|
164
181
|
} catch (_error) {
|
|
165
182
|
// Буфер ещё пуст — рисовать нечего
|
|
166
183
|
}
|
|
167
|
-
}
|
|
184
|
+
};
|
|
168
185
|
// Длительность приходит с метаданными: без неё полоса прокрутки делила бы на ноль,
|
|
169
186
|
// а у живого потока её нет вовсе (duration = Infinity)
|
|
170
187
|
#setSliderMax = () => {
|
|
@@ -173,7 +190,7 @@ class Video {
|
|
|
173
190
|
this.#chui_vp_seek.max = known ? String(Math.floor(duration)) : "0";
|
|
174
191
|
// Без известной длительности ползунок бессмысленен: перетаскивание отправляло бы плеер в начало
|
|
175
192
|
this.#chui_vp_seek.disabled = !known;
|
|
176
|
-
}
|
|
193
|
+
};
|
|
177
194
|
#renderProgress = () => {
|
|
178
195
|
const max = Number(this.#chui_vp_seek.max);
|
|
179
196
|
const position = this.getCurrentTime();
|
|
@@ -181,24 +198,26 @@ class Video {
|
|
|
181
198
|
if (!(max > 0)) {
|
|
182
199
|
// «0:07 / 0:00» читалось бы как поломка: у источника без длительности показываем только прошедшее
|
|
183
200
|
this.#chui_vp_time.setText(this.#calculateTime(position));
|
|
184
|
-
this.#chui_vp_main.style.setProperty(
|
|
201
|
+
this.#chui_vp_main.style.setProperty("--seek-before-width", "0%");
|
|
185
202
|
return;
|
|
186
203
|
}
|
|
187
204
|
this.#chui_vp_time.setText(`${this.#calculateTime(position)} / ${this.#calculateTime(duration)}`);
|
|
188
205
|
this.#chui_vp_seek.value = String(Math.floor(position));
|
|
189
206
|
// Доля ограничена сотней: `max` — округлённая длительность, а позиция идёт дальше,
|
|
190
207
|
// и без ограничения полоса целиком заливалась акцентом
|
|
191
|
-
const доля = Math.min(100, Math.max(0, Math.floor(position / max * 100)));
|
|
192
|
-
this.#chui_vp_main.style.setProperty(
|
|
193
|
-
}
|
|
208
|
+
const доля = Math.min(100, Math.max(0, Math.floor((position / max) * 100)));
|
|
209
|
+
this.#chui_vp_main.style.setProperty("--seek-before-width", `${доля}%`);
|
|
210
|
+
};
|
|
194
211
|
#calculateTime = (secs) => {
|
|
195
212
|
const seconds = Number.isFinite(Number(secs)) ? Number(secs) : 0;
|
|
196
213
|
const minutes = Math.floor(seconds / 60);
|
|
197
214
|
const rest = Math.floor(seconds % 60);
|
|
198
215
|
const returnedSeconds = rest < 10 ? `0${rest}` : `${rest}`;
|
|
199
216
|
return `${minutes}:${returnedSeconds}`;
|
|
217
|
+
};
|
|
218
|
+
#setStatus(text) {
|
|
219
|
+
this.#status.innerText = text;
|
|
200
220
|
}
|
|
201
|
-
#setStatus(text) { this.#status.innerText = text; }
|
|
202
221
|
#setButton(node, label, icon) {
|
|
203
222
|
node.innerHTML = new Icon(icon, "18px").getHTML();
|
|
204
223
|
node.setAttribute("aria-label", label);
|
|
@@ -220,71 +239,143 @@ class Video {
|
|
|
220
239
|
if (!this.#controls) this.#closePanel();
|
|
221
240
|
return this;
|
|
222
241
|
}
|
|
223
|
-
getControls() {
|
|
242
|
+
getControls() {
|
|
243
|
+
return this.#controls;
|
|
244
|
+
}
|
|
224
245
|
// === СТАНДАРТНЫЕ ВОЗМОЖНОСТИ `<video>` ===
|
|
225
246
|
/** Сам элемент: для всего, чего нет в списке ниже */
|
|
226
|
-
getVideo() {
|
|
247
|
+
getVideo() {
|
|
248
|
+
return this.#chui_vt;
|
|
249
|
+
}
|
|
227
250
|
/** Воспроизведение: промис, как у `<video>` (разрешается, когда воспроизведение началось) */
|
|
228
|
-
play() {
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
251
|
+
play() {
|
|
252
|
+
return this.#chui_vt.play();
|
|
253
|
+
}
|
|
254
|
+
pause() {
|
|
255
|
+
this.#chui_vt.pause();
|
|
256
|
+
return this;
|
|
257
|
+
}
|
|
258
|
+
load() {
|
|
259
|
+
this.#chui_vt.load();
|
|
260
|
+
return this;
|
|
261
|
+
}
|
|
262
|
+
canPlayType(type = String()) {
|
|
263
|
+
return this.#chui_vt.canPlayType(type);
|
|
264
|
+
}
|
|
265
|
+
getSrc() {
|
|
266
|
+
return this.#chui_vt.getAttribute("src") ?? "";
|
|
267
|
+
}
|
|
233
268
|
setSrc(url = String()) {
|
|
234
269
|
this.#chui_vt.setAttribute("src", url);
|
|
235
270
|
this.#chui_vt.load();
|
|
236
271
|
return this;
|
|
237
272
|
}
|
|
238
|
-
getSrcObject() {
|
|
273
|
+
getSrcObject() {
|
|
274
|
+
return this.#chui_vt.srcObject;
|
|
275
|
+
}
|
|
239
276
|
/** Живой поток (камера, `getUserMedia`) — штатное `srcObject`, а не путь */
|
|
240
277
|
setSrcObject(object) {
|
|
241
278
|
this.#chui_vt.srcObject = object;
|
|
242
279
|
return this;
|
|
243
280
|
}
|
|
244
|
-
getPoster() {
|
|
281
|
+
getPoster() {
|
|
282
|
+
return this.#chui_vt.getAttribute("poster") ?? "";
|
|
283
|
+
}
|
|
245
284
|
setPoster(url = String()) {
|
|
246
285
|
if (url === "") this.#chui_vt.removeAttribute("poster");
|
|
247
286
|
else this.#chui_vt.setAttribute("poster", url);
|
|
248
287
|
return this;
|
|
249
288
|
}
|
|
250
|
-
getCurrentTime() {
|
|
289
|
+
getCurrentTime() {
|
|
290
|
+
return this.#chui_vt.currentTime;
|
|
291
|
+
}
|
|
251
292
|
setCurrentTime(seconds = Number()) {
|
|
252
293
|
this.#chui_vt.currentTime = Number(seconds);
|
|
253
294
|
// Подписи и заливка не ждут `timeupdate`: перемотка из кода видна сразу
|
|
254
295
|
this.#renderProgress();
|
|
255
296
|
return this;
|
|
256
297
|
}
|
|
257
|
-
getDuration() {
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
298
|
+
getDuration() {
|
|
299
|
+
return this.#chui_vt.duration;
|
|
300
|
+
}
|
|
301
|
+
getBuffered() {
|
|
302
|
+
return this.#chui_vt.buffered;
|
|
303
|
+
}
|
|
304
|
+
getPaused() {
|
|
305
|
+
return this.#chui_vt.paused;
|
|
306
|
+
}
|
|
307
|
+
getEnded() {
|
|
308
|
+
return this.#chui_vt.ended;
|
|
309
|
+
}
|
|
310
|
+
getReadyState() {
|
|
311
|
+
return this.#chui_vt.readyState;
|
|
312
|
+
}
|
|
313
|
+
getVolume() {
|
|
314
|
+
return this.#chui_vt.volume;
|
|
315
|
+
}
|
|
263
316
|
setVolume(value = Number()) {
|
|
264
317
|
this.#chui_vt.volume = Math.min(1, Math.max(0, Number(value)));
|
|
265
318
|
return this;
|
|
266
319
|
}
|
|
267
|
-
getMuted() {
|
|
320
|
+
getMuted() {
|
|
321
|
+
return this.#chui_vt.muted;
|
|
322
|
+
}
|
|
268
323
|
setMuted(boolean = Boolean()) {
|
|
269
324
|
this.#chui_vt.muted = boolean === true;
|
|
270
325
|
return this;
|
|
271
326
|
}
|
|
272
|
-
getPlaybackRate() {
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
327
|
+
getPlaybackRate() {
|
|
328
|
+
return this.#chui_vt.playbackRate;
|
|
329
|
+
}
|
|
330
|
+
setPlaybackRate(rate = Number()) {
|
|
331
|
+
this.#chui_vt.playbackRate = Number(rate);
|
|
332
|
+
return this;
|
|
333
|
+
}
|
|
334
|
+
getDefaultPlaybackRate() {
|
|
335
|
+
return this.#chui_vt.defaultPlaybackRate;
|
|
336
|
+
}
|
|
337
|
+
setDefaultPlaybackRate(rate = Number()) {
|
|
338
|
+
this.#chui_vt.defaultPlaybackRate = Number(rate);
|
|
339
|
+
return this;
|
|
340
|
+
}
|
|
341
|
+
getLoop() {
|
|
342
|
+
return this.#chui_vt.loop;
|
|
343
|
+
}
|
|
344
|
+
setLoop(boolean = Boolean()) {
|
|
345
|
+
this.#chui_vt.loop = boolean === true;
|
|
346
|
+
return this;
|
|
347
|
+
}
|
|
348
|
+
getAutoplay() {
|
|
349
|
+
return this.#chui_vt.autoplay;
|
|
350
|
+
}
|
|
351
|
+
setAutoplay(boolean = Boolean()) {
|
|
352
|
+
this.#chui_vt.autoplay = boolean === true;
|
|
353
|
+
return this;
|
|
354
|
+
}
|
|
355
|
+
getWidth() {
|
|
356
|
+
return getComputedStyle(this.#chui_vt).width;
|
|
357
|
+
}
|
|
358
|
+
setWidth(value = String()) {
|
|
359
|
+
this.#chui_vt.style.width = value;
|
|
360
|
+
return this;
|
|
361
|
+
}
|
|
362
|
+
getHeight() {
|
|
363
|
+
return getComputedStyle(this.#chui_vt).height;
|
|
364
|
+
}
|
|
365
|
+
setHeight(value = String()) {
|
|
366
|
+
this.#chui_vt.style.height = value;
|
|
367
|
+
return this;
|
|
368
|
+
}
|
|
369
|
+
getFullscreen() {
|
|
370
|
+
return this.#chui_vp_main === document.fullscreenElement;
|
|
371
|
+
}
|
|
285
372
|
/** Полный экран — на весь плеер, а не на кадр: иначе полоса управления осталась бы снаружи */
|
|
286
|
-
requestFullscreen() {
|
|
287
|
-
|
|
373
|
+
requestFullscreen() {
|
|
374
|
+
return this.#chui_vp_main.requestFullscreen({ navigationUI: "hide" });
|
|
375
|
+
}
|
|
376
|
+
exitFullscreen() {
|
|
377
|
+
return document.exitFullscreen();
|
|
378
|
+
}
|
|
288
379
|
addEventListener(type = String(), listener = () => {}) {
|
|
289
380
|
this.#chui_vt.addEventListener(type, listener);
|
|
290
381
|
return this;
|
|
@@ -293,7 +384,9 @@ class Video {
|
|
|
293
384
|
this.#chui_vt.removeEventListener(type, listener);
|
|
294
385
|
return this;
|
|
295
386
|
}
|
|
296
|
-
set() {
|
|
387
|
+
set() {
|
|
388
|
+
return this.#chui_vp_main;
|
|
389
|
+
}
|
|
297
390
|
detach() {
|
|
298
391
|
this.pause();
|
|
299
392
|
this.#chui_vp_main.remove();
|
|
@@ -320,4 +413,4 @@ class Video {
|
|
|
320
413
|
}
|
|
321
414
|
}
|
|
322
415
|
|
|
323
|
-
exports.Video = Video
|
|
416
|
+
exports.Video = Video;
|
|
@@ -64,7 +64,9 @@ chui_vp_main.vp_controls_off chui_vp_panel {
|
|
|
64
64
|
}
|
|
65
65
|
|
|
66
66
|
/* КНОПКИ: площадка 32px с глифом 18px */
|
|
67
|
-
chui_vp_play_pause,
|
|
67
|
+
chui_vp_play_pause,
|
|
68
|
+
chui_vp_volume_icon,
|
|
69
|
+
chui_vp_full_mode {
|
|
68
70
|
display: flex;
|
|
69
71
|
align-items: center;
|
|
70
72
|
justify-content: center;
|
|
@@ -97,12 +99,13 @@ chui_vp_play_pause:hover {
|
|
|
97
99
|
}
|
|
98
100
|
|
|
99
101
|
chui_vp_play_pause:active {
|
|
100
|
-
transform: scale(.96);
|
|
102
|
+
transform: scale(0.96);
|
|
101
103
|
}
|
|
102
104
|
|
|
103
105
|
/* Глифы отвечают на курсор акцентом — у всех, кроме главной кнопки: она сама светлая,
|
|
104
106
|
и её глиф должен остаться читаемым */
|
|
105
|
-
chui_vp_volume_icon:hover chui_icon,
|
|
107
|
+
chui_vp_volume_icon:hover chui_icon,
|
|
108
|
+
chui_vp_full_mode:hover chui_icon {
|
|
106
109
|
color: var(--blue_prime_background);
|
|
107
110
|
}
|
|
108
111
|
|
|
@@ -113,7 +116,7 @@ chui_vp_play_pause:active chui_icon {
|
|
|
113
116
|
|
|
114
117
|
chui_vp_volume_icon:active,
|
|
115
118
|
chui_vp_full_mode:active {
|
|
116
|
-
transform: scale(.94);
|
|
119
|
+
transform: scale(0.94);
|
|
117
120
|
}
|
|
118
121
|
|
|
119
122
|
chui_vp_volume_icon:active chui_icon,
|
|
@@ -123,8 +126,11 @@ chui_vp_full_mode:active chui_icon {
|
|
|
123
126
|
|
|
124
127
|
/* Кнопки полосы — кастомные теги, поэтому обводку фокуса рисуем сами.
|
|
125
128
|
`outline` не сдвигает вёрстку */
|
|
126
|
-
chui_vp_play_pause:focus-visible,
|
|
127
|
-
|
|
129
|
+
chui_vp_play_pause:focus-visible,
|
|
130
|
+
chui_vp_volume_icon:focus-visible,
|
|
131
|
+
chui_vp_full_mode:focus-visible,
|
|
132
|
+
#chui_vp_seek:focus-visible,
|
|
133
|
+
#chui_vp_volume:focus-visible {
|
|
128
134
|
outline: var(--focus_outline);
|
|
129
135
|
outline-offset: var(--focus_outline_offset);
|
|
130
136
|
}
|
|
@@ -162,7 +168,8 @@ chui_vp_seek_buf {
|
|
|
162
168
|
/* Прогресс и громкость — та же шкала, что у Audio: дорожка `--player_track_height`,
|
|
163
169
|
заливка градиентом по доле, ползунок виден и в покое и не выезжает за дорожку
|
|
164
170
|
(`padding-inline` на половину кружка) */
|
|
165
|
-
#chui_vp_seek,
|
|
171
|
+
#chui_vp_seek,
|
|
172
|
+
#chui_vp_volume {
|
|
166
173
|
margin: 0;
|
|
167
174
|
-webkit-appearance: none;
|
|
168
175
|
border-radius: var(--radius_pill);
|
|
@@ -194,24 +201,30 @@ chui_vp_seek_buf {
|
|
|
194
201
|
}
|
|
195
202
|
|
|
196
203
|
#chui_vp_seek {
|
|
197
|
-
background-image: linear-gradient(
|
|
204
|
+
background-image: linear-gradient(
|
|
205
|
+
to right,
|
|
198
206
|
var(--blue_prime_background) 0 var(--seek-before-width, 0%),
|
|
199
|
-
var(--ap_slider_background) var(--seek-before-width, 0%) 100%
|
|
207
|
+
var(--ap_slider_background) var(--seek-before-width, 0%) 100%
|
|
208
|
+
);
|
|
200
209
|
}
|
|
201
210
|
|
|
202
211
|
/* Громкость — ступень звука, а не время: заливка нейтральная, чтобы не читалась второй
|
|
203
212
|
полосой прогресса */
|
|
204
213
|
#chui_vp_volume {
|
|
205
|
-
background-image: linear-gradient(
|
|
214
|
+
background-image: linear-gradient(
|
|
215
|
+
to right,
|
|
206
216
|
var(--text_color) 0 var(--volume-before-width, 0%),
|
|
207
|
-
var(--ap_slider_background) var(--volume-before-width, 0%) 100%
|
|
217
|
+
var(--ap_slider_background) var(--volume-before-width, 0%) 100%
|
|
218
|
+
);
|
|
208
219
|
}
|
|
209
220
|
|
|
210
221
|
/* Выключенная громкость (нет звука) — заливка ступени приглушается, как у Audio */
|
|
211
222
|
#chui_vp_volume:disabled {
|
|
212
|
-
background-image: linear-gradient(
|
|
223
|
+
background-image: linear-gradient(
|
|
224
|
+
to right,
|
|
213
225
|
var(--ap_slider_buf_background) 0 var(--volume-before-width, 0%),
|
|
214
|
-
var(--ap_slider_background) var(--volume-before-width, 0%) 100%
|
|
226
|
+
var(--ap_slider_background) var(--volume-before-width, 0%) 100%
|
|
227
|
+
);
|
|
215
228
|
}
|
|
216
229
|
|
|
217
230
|
#chui_vp_seek::-webkit-slider-runnable-track,
|
|
@@ -224,7 +237,8 @@ chui_vp_seek_buf {
|
|
|
224
237
|
|
|
225
238
|
/* Ползунок виден всегда, но в покое он меньше — как у Audio. Ободок цвета полосы
|
|
226
239
|
управления нужен там, где заливка белая */
|
|
227
|
-
#chui_vp_seek::-webkit-slider-thumb,
|
|
240
|
+
#chui_vp_seek::-webkit-slider-thumb,
|
|
241
|
+
#chui_vp_volume::-webkit-slider-thumb {
|
|
228
242
|
-webkit-appearance: none;
|
|
229
243
|
border: none;
|
|
230
244
|
height: 9px;
|
|
@@ -254,10 +268,13 @@ chui_vp_main:hover #chui_vp_volume:not(:disabled)::-webkit-slider-thumb,
|
|
|
254
268
|
width: 12px;
|
|
255
269
|
margin-top: calc((var(--player_track_height) - 12px) / 2);
|
|
256
270
|
background-color: var(--player_thumb_background);
|
|
257
|
-
box-shadow:
|
|
271
|
+
box-shadow:
|
|
272
|
+
0 0 0 2px var(--header_background),
|
|
273
|
+
var(--box_shadow_main);
|
|
258
274
|
}
|
|
259
275
|
|
|
260
|
-
#chui_vp_seek:focus,
|
|
276
|
+
#chui_vp_seek:focus,
|
|
277
|
+
#chui_vp_volume:focus,
|
|
261
278
|
#chui_vp_seek:focus::-webkit-slider-runnable-track,
|
|
262
279
|
#chui_vp_volume:focus::-webkit-slider-runnable-track {
|
|
263
280
|
outline: none;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
const {Animation} = require("../../modules/chui_animations/animations");
|
|
2
|
-
const {MenuKeyboard, makeKeyboardButton} = require("../../modules/chui_a11y/chui_a11y");
|
|
1
|
+
const { Animation } = require("../../modules/chui_animations/animations");
|
|
2
|
+
const { MenuKeyboard, makeKeyboardButton } = require("../../modules/chui_a11y/chui_a11y");
|
|
3
3
|
|
|
4
4
|
const MENU_BAR_DROP_DOWN_ACTIVE_CLASS = "menu_bar_drop_down_button";
|
|
5
5
|
// Панель открывается под кнопкой с зазором и не подходит к краю окна ближе этого отступа
|
|
@@ -10,13 +10,13 @@ class MenuBar {
|
|
|
10
10
|
// Панели выпадающих списков лежат в body, а не в полосе (см. MenuBarDropDown), поэтому
|
|
11
11
|
// снятие полосы обязано убирать и их: экземпляр находится по узлу полосы
|
|
12
12
|
static #instances = new WeakMap();
|
|
13
|
-
#chui_menu_bar_main = document.createElement("chui_menu_bar_main")
|
|
13
|
+
#chui_menu_bar_main = document.createElement("chui_menu_bar_main");
|
|
14
14
|
#dropdowns = [];
|
|
15
15
|
constructor(options = { test: Boolean() }) {
|
|
16
|
-
require(
|
|
16
|
+
require("../../modules/chui_functions").setStyles(__dirname + "/styles.css", "chUiJS_MenuBar");
|
|
17
17
|
MenuBar.#instances.set(this.#chui_menu_bar_main, this);
|
|
18
|
-
if (options.test !== undefined) this.#chui_menu_bar_main.setAttribute("test", options.test)
|
|
19
|
-
this.#chui_menu_bar_main.addEventListener("wheel", this.#wheel_event, {passive: true});
|
|
18
|
+
if (options.test !== undefined) this.#chui_menu_bar_main.setAttribute("test", options.test);
|
|
19
|
+
this.#chui_menu_bar_main.addEventListener("wheel", this.#wheel_event, { passive: true });
|
|
20
20
|
}
|
|
21
21
|
/*
|
|
22
22
|
* Колесо мыши прокручивает полосу вбок.
|
|
@@ -33,8 +33,8 @@ class MenuBar {
|
|
|
33
33
|
};
|
|
34
34
|
addMenuItems(...components) {
|
|
35
35
|
for (let component of components) {
|
|
36
|
-
let element = component.set()
|
|
37
|
-
new Animation(element).fadeIn()
|
|
36
|
+
let element = component.set();
|
|
37
|
+
new Animation(element).fadeIn();
|
|
38
38
|
this.#chui_menu_bar_main.appendChild(element);
|
|
39
39
|
if (component instanceof MenuBarDropDown) this.#dropdowns.push(component);
|
|
40
40
|
}
|
|
@@ -59,8 +59,8 @@ class MenuBar {
|
|
|
59
59
|
set() {
|
|
60
60
|
return this.#chui_menu_bar_main;
|
|
61
61
|
}
|
|
62
|
-
static DROPDOWN(options = {title: String(), items: []}) {
|
|
63
|
-
return new MenuBarDropDown(options)
|
|
62
|
+
static DROPDOWN(options = { title: String(), items: [] }) {
|
|
63
|
+
return new MenuBarDropDown(options);
|
|
64
64
|
}
|
|
65
65
|
}
|
|
66
66
|
|
|
@@ -70,14 +70,15 @@ class MenuBarDropDown {
|
|
|
70
70
|
#mb_dd_dropdown = document.createElement("menu_bar_dropdown");
|
|
71
71
|
#is_open = false;
|
|
72
72
|
#keyboard = undefined;
|
|
73
|
-
constructor(options = {title: String(), items: []}) {
|
|
73
|
+
constructor(options = { title: String(), items: [] }) {
|
|
74
74
|
// Панель собирают и отдельно от полосы (`MenuBar.DROPDOWN`) — свои стили нужны здесь же
|
|
75
|
-
require(
|
|
75
|
+
require("../../modules/chui_functions").setStyles(__dirname + "/styles.css", "chUiJS_MenuBar");
|
|
76
76
|
// Пустой заголовок остаётся пустым: подстановка заготовки опции рисовала слово «undefined»
|
|
77
77
|
this.#mb_dd_button.innerText = options.title === undefined || options.title === null ? "" : options.title;
|
|
78
78
|
this.#mb_dd_dropdown.id = require("randomstring").generate();
|
|
79
|
-
this.#mb_dd_main.appendChild(this.#mb_dd_button)
|
|
80
|
-
for (let item of Array.isArray(options.items) ? options.items : [])
|
|
79
|
+
this.#mb_dd_main.appendChild(this.#mb_dd_button);
|
|
80
|
+
for (let item of Array.isArray(options.items) ? options.items : [])
|
|
81
|
+
this.#mb_dd_dropdown.appendChild(item.set());
|
|
81
82
|
// Панель лежит в document.body, а не рядом с кнопкой: шапка — сама с backdrop-filter,
|
|
82
83
|
// а элемент с backdrop-filter становится «backdrop root» — вложенная панель тогда не
|
|
83
84
|
// блюрит содержимое под собой (замер: детальность 33.4 и с блюром, и без него; вне шапки
|
|
@@ -89,7 +90,7 @@ class MenuBarDropDown {
|
|
|
89
90
|
this.#keyboard = new MenuKeyboard(this.#mb_dd_dropdown, {
|
|
90
91
|
itemSelector: "button",
|
|
91
92
|
onEscape: () => this.#close(),
|
|
92
|
-
trigger: this.#mb_dd_button
|
|
93
|
+
trigger: this.#mb_dd_button,
|
|
93
94
|
});
|
|
94
95
|
makeKeyboardButton(this.#mb_dd_button);
|
|
95
96
|
// Закрытый список тоже должен быть объявлен как закрытый: без этого у кнопки,
|
|
@@ -115,8 +116,8 @@ class MenuBarDropDown {
|
|
|
115
116
|
// fadeIn показывает панель (display: flex), и только после этого её можно измерить
|
|
116
117
|
new Animation(this.#mb_dd_dropdown).fadeIn();
|
|
117
118
|
this.#positionDropdown();
|
|
118
|
-
window.addEventListener(
|
|
119
|
-
window.addEventListener(
|
|
119
|
+
window.addEventListener("click", this.#window_click_event);
|
|
120
|
+
window.addEventListener("resize", this.#position_dropdown_event);
|
|
120
121
|
this.#keyboard.setExpanded(true);
|
|
121
122
|
}
|
|
122
123
|
#close() {
|
|
@@ -124,8 +125,8 @@ class MenuBarDropDown {
|
|
|
124
125
|
this.#is_open = false;
|
|
125
126
|
this.#mb_dd_button.classList.remove(MENU_BAR_DROP_DOWN_ACTIVE_CLASS);
|
|
126
127
|
new Animation(this.#mb_dd_dropdown).fadeOut();
|
|
127
|
-
window.removeEventListener(
|
|
128
|
-
window.removeEventListener(
|
|
128
|
+
window.removeEventListener("click", this.#window_click_event);
|
|
129
|
+
window.removeEventListener("resize", this.#position_dropdown_event);
|
|
129
130
|
this.#keyboard.setExpanded(false);
|
|
130
131
|
}
|
|
131
132
|
// position: fixed — координаты считаются от окна, поэтому панель пересчитывается и на resize
|
|
@@ -142,17 +143,18 @@ class MenuBarDropDown {
|
|
|
142
143
|
this.#mb_dd_dropdown.style.top = `${Math.round(button.bottom + MENU_BAR_DROPDOWN_GAP)}px`;
|
|
143
144
|
}
|
|
144
145
|
#mb_dd_button_click_event = () => {
|
|
145
|
-
if (this.#is_open) this.#close();
|
|
146
|
-
|
|
146
|
+
if (this.#is_open) this.#close();
|
|
147
|
+
else this.#open();
|
|
148
|
+
};
|
|
147
149
|
#mb_dd_dropdown_click_event = () => {
|
|
148
150
|
this.#close();
|
|
149
|
-
}
|
|
151
|
+
};
|
|
150
152
|
// «Снаружи» — это и кнопка с обёрткой, и сама панель: она теперь не их потомок
|
|
151
153
|
#window_click_event = (event) => {
|
|
152
154
|
if (!this.#is_open) return;
|
|
153
155
|
if (this.#mb_dd_main.contains(event.target) || this.#mb_dd_dropdown.contains(event.target)) return;
|
|
154
156
|
this.#close();
|
|
155
|
-
}
|
|
157
|
+
};
|
|
156
158
|
#position_dropdown_event = () => this.#positionDropdown();
|
|
157
159
|
/**
|
|
158
160
|
* Убрать панель из body, не трогая клавиатурный слой: панель живёт в body, а не в полосе,
|
|
@@ -175,4 +177,4 @@ class MenuBarDropDown {
|
|
|
175
177
|
}
|
|
176
178
|
}
|
|
177
179
|
|
|
178
|
-
exports.MenuBar = MenuBar
|
|
180
|
+
exports.MenuBar = MenuBar;
|
|
@@ -57,7 +57,8 @@ chui_menu_bar_main .chui_button:hover {
|
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
chui_menu_bar_main .chui_button:active:not(:disabled) {
|
|
60
|
-
background: var(--element_background_prime);
|
|
60
|
+
background: var(--element_background_prime);
|
|
61
|
+
color: var(--text_color_hover);
|
|
61
62
|
border: none;
|
|
62
63
|
}
|
|
63
64
|
|
|
@@ -173,7 +174,8 @@ menu_bar_dropdown .chui_button:hover {
|
|
|
173
174
|
}
|
|
174
175
|
|
|
175
176
|
menu_bar_dropdown .chui_button:active:not(:disabled) {
|
|
176
|
-
background: var(--element_background_prime);
|
|
177
|
+
background: var(--element_background_prime);
|
|
178
|
+
color: var(--text_color_hover);
|
|
177
179
|
border: none;
|
|
178
180
|
}
|
|
179
181
|
|