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,114 +1,175 @@
|
|
|
1
|
-
|
|
1
|
+
/** Виды движения: имя кадра даёт JS, а длительность и кривую — класс движения в styles.css */
|
|
2
|
+
const MOTION = {
|
|
3
|
+
ENTER: "enter",
|
|
4
|
+
EXIT: "exit",
|
|
5
|
+
POP: "pop",
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
/** Кадр появления всплывающей панели у триггера — общий кадр оболочки */
|
|
9
|
+
const PANEL_FRAME = "chui_panel_in";
|
|
2
10
|
|
|
3
11
|
class Animation {
|
|
4
12
|
#element = undefined;
|
|
5
13
|
|
|
6
14
|
constructor(element) {
|
|
7
|
-
require(
|
|
15
|
+
require("../chui_functions").setStyles(__dirname + "/styles.css", "chUiJS_Animations");
|
|
8
16
|
if (element !== undefined) this.#element = element;
|
|
9
17
|
}
|
|
10
18
|
|
|
19
|
+
/**
|
|
20
|
+
* Запустить кадры `name` как движение вида `kind`. Длительность и кривая — в `styles.css`
|
|
21
|
+
* по классу `data-motion`: вход базовый, выход короче, отклик с лёгким перелётом. Прежде
|
|
22
|
+
* время приходило из общего `animation-duration` на `*`, и все движения шли одним временем.
|
|
23
|
+
*/
|
|
24
|
+
#play(name = String(), kind = String()) {
|
|
25
|
+
this.#element.dataset.motion = kind;
|
|
26
|
+
this.#element.style.animationName = name;
|
|
27
|
+
}
|
|
28
|
+
|
|
11
29
|
/**
|
|
12
30
|
* Отменить незавершённое скрытие: его `animationend` (removeEvents) снимает у слоя
|
|
13
31
|
* `animation-name` и `display`. Если слой открыли заново раньше, чем анимация закрытия
|
|
14
32
|
* доиграла, этот обработчик прятал уже открытый слой — вид расходился с состоянием.
|
|
15
33
|
*/
|
|
16
34
|
#cancelHide() {
|
|
17
|
-
this.#element.removeEventListener(
|
|
18
|
-
this.#element.style.removeProperty(
|
|
35
|
+
this.#element.removeEventListener("animationend", removeEvents);
|
|
36
|
+
this.#element.style.removeProperty("animation-name");
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Кадр появления доигран — вид движения снимается, а имя кадра остаётся. По имени видно,
|
|
41
|
+
* что слой уже открыт (повторный показ не перезапускает кадр), а само оно без вида ничего
|
|
42
|
+
* не держит. Вид держит конечное состояние (`animation-fill-mode: both` в styles.css),
|
|
43
|
+
* и на слое оставался бы вычисленный `transform` — пусть и единичный: элемент с `transform`
|
|
44
|
+
* становится собственным «backdrop root», и размытие подложки перестаёт видеть содержимое
|
|
45
|
+
* под слоем (замер: меню контекста с блюром и без — картинка не менялась, пока вид стоял).
|
|
46
|
+
*
|
|
47
|
+
* Стрелочное поле, а не метод: у метода в слушателе нет `this`, и он падал бы на первом
|
|
48
|
+
* же конце кадра.
|
|
49
|
+
*/
|
|
50
|
+
#entranceEnd = (event) => {
|
|
51
|
+
if (event.target !== this.#element) return;
|
|
52
|
+
this.#element.removeEventListener("animationend", this.#entranceEnd);
|
|
53
|
+
this.#element.removeAttribute("data-motion");
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
/** Показать слой кадром появления и снять вид по концу кадра */
|
|
57
|
+
#enter(name = String(), kind = String()) {
|
|
58
|
+
this.#play(name, kind);
|
|
59
|
+
this.#element.addEventListener("animationend", this.#entranceEnd);
|
|
19
60
|
}
|
|
20
61
|
|
|
21
62
|
fadeIn() {
|
|
22
63
|
this.#cancelHide();
|
|
23
|
-
if (window.getComputedStyle(this.#element, null).display ===
|
|
24
|
-
if (this.#element.tagName !== "TABLE") this.#element.style.display =
|
|
64
|
+
if (window.getComputedStyle(this.#element, null).display === "none") {
|
|
65
|
+
if (this.#element.tagName !== "TABLE") this.#element.style.display = "flex";
|
|
25
66
|
}
|
|
26
|
-
this.#
|
|
27
|
-
this.#element.style.animationName = 'fade-in';
|
|
67
|
+
this.#enter("fade-in", MOTION.ENTER);
|
|
28
68
|
}
|
|
29
69
|
|
|
30
70
|
fadeOut() {
|
|
31
|
-
this.#element.style.transition = "transform .0s"
|
|
32
71
|
if (this.#element.style.animationName) {
|
|
33
|
-
this.#
|
|
34
|
-
this.#element.addEventListener(
|
|
72
|
+
this.#play("fade-out", MOTION.EXIT);
|
|
73
|
+
this.#element.addEventListener("animationend", removeEvents);
|
|
35
74
|
}
|
|
36
75
|
}
|
|
37
76
|
|
|
77
|
+
/**
|
|
78
|
+
* Появление всплывающей панели у триггера (список, меню, поповер): панель приходит
|
|
79
|
+
* сверху вниз и чуть вырастает. Вид `pop` — кривая с лёгким перелётом, поэтому
|
|
80
|
+
* открытие читается откликом, а не вспышкой: прежний `fadeIn` менял только прозрачность.
|
|
81
|
+
*
|
|
82
|
+
* Повторный показ уже открытой панели кадр не запускает: поле открывают и `focus`,
|
|
83
|
+
* и `click` — одно действие приходило сюда дважды, а `#cancelHide` перед кадром снимает
|
|
84
|
+
* имя кадра, поэтому второй вызов начинал его заново и панель мигала на открытии.
|
|
85
|
+
*/
|
|
86
|
+
panelIn() {
|
|
87
|
+
const open =
|
|
88
|
+
this.#element.style.animationName === PANEL_FRAME &&
|
|
89
|
+
window.getComputedStyle(this.#element, null).display !== "none";
|
|
90
|
+
if (open) return;
|
|
91
|
+
this.#cancelHide();
|
|
92
|
+
if (window.getComputedStyle(this.#element, null).display === "none") {
|
|
93
|
+
if (this.#element.tagName !== "TABLE") this.#element.style.display = "flex";
|
|
94
|
+
}
|
|
95
|
+
this.#play(PANEL_FRAME, MOTION.POP);
|
|
96
|
+
this.#element.addEventListener("animationend", this.#entranceEnd);
|
|
97
|
+
}
|
|
98
|
+
|
|
38
99
|
// SCALE
|
|
39
100
|
scaleIn() {
|
|
40
101
|
this.#cancelHide();
|
|
41
|
-
if (window.getComputedStyle(this.#element, null).display ===
|
|
42
|
-
if (this.#element.tagName !== "TABLE") this.#element.style.display =
|
|
102
|
+
if (window.getComputedStyle(this.#element, null).display === "none") {
|
|
103
|
+
if (this.#element.tagName !== "TABLE") this.#element.style.display = "flex";
|
|
43
104
|
}
|
|
44
|
-
this.#
|
|
105
|
+
this.#enter("scale-in", MOTION.POP);
|
|
45
106
|
}
|
|
46
107
|
|
|
47
108
|
scaleOut() {
|
|
48
109
|
if (this.#element.style.animationName) {
|
|
49
|
-
this.#
|
|
50
|
-
this.#element.addEventListener(
|
|
110
|
+
this.#play("scale-out", MOTION.EXIT);
|
|
111
|
+
this.#element.addEventListener("animationend", removeEvents);
|
|
51
112
|
}
|
|
52
113
|
}
|
|
53
114
|
|
|
54
115
|
// SLIDE RIGHT
|
|
55
116
|
slideRightIn() {
|
|
56
117
|
this.#cancelHide();
|
|
57
|
-
if (window.getComputedStyle(this.#element, null).display ===
|
|
58
|
-
if (this.#element.tagName !== "TABLE") this.#element.style.display =
|
|
118
|
+
if (window.getComputedStyle(this.#element, null).display === "none") {
|
|
119
|
+
if (this.#element.tagName !== "TABLE") this.#element.style.display = "flex";
|
|
59
120
|
}
|
|
60
|
-
this.#
|
|
121
|
+
this.#enter("slide-right-in", MOTION.ENTER);
|
|
61
122
|
}
|
|
62
123
|
|
|
63
124
|
slideRightOut() {
|
|
64
125
|
if (this.#element.style.animationName) {
|
|
65
|
-
this.#
|
|
66
|
-
this.#element.addEventListener(
|
|
126
|
+
this.#play("slide-right-out", MOTION.EXIT);
|
|
127
|
+
this.#element.addEventListener("animationend", removeEvents);
|
|
67
128
|
}
|
|
68
129
|
}
|
|
69
130
|
|
|
70
131
|
// SLIDE BOTTOM
|
|
71
132
|
slideBottomIn() {
|
|
72
133
|
this.#cancelHide();
|
|
73
|
-
if (window.getComputedStyle(this.#element, null).display ===
|
|
74
|
-
if (this.#element.tagName !== "TABLE") this.#element.style.display =
|
|
134
|
+
if (window.getComputedStyle(this.#element, null).display === "none") {
|
|
135
|
+
if (this.#element.tagName !== "TABLE") this.#element.style.display = "flex";
|
|
75
136
|
}
|
|
76
|
-
this.#
|
|
137
|
+
this.#enter("slide-bottom-in", MOTION.ENTER);
|
|
77
138
|
}
|
|
78
139
|
|
|
79
140
|
slideBottomOut() {
|
|
80
141
|
if (this.#element.style.animationName) {
|
|
81
|
-
this.#
|
|
82
|
-
this.#element.addEventListener(
|
|
142
|
+
this.#play("slide-bottom-out", MOTION.EXIT);
|
|
143
|
+
this.#element.addEventListener("animationend", removeEvents);
|
|
83
144
|
}
|
|
84
145
|
}
|
|
85
146
|
|
|
86
147
|
// REMOVE
|
|
87
148
|
slideBottomOutAndRemove() {
|
|
88
149
|
if (this.#element.style.animationName) {
|
|
89
|
-
this.#
|
|
90
|
-
this.#element.addEventListener(
|
|
150
|
+
this.#play("slide-bottom-out", MOTION.EXIT);
|
|
151
|
+
this.#element.addEventListener("animationend", removeEvents);
|
|
91
152
|
}
|
|
92
153
|
}
|
|
93
154
|
|
|
94
155
|
slideRightOutAndRemove() {
|
|
95
156
|
if (this.#element.style.animationName) {
|
|
96
|
-
this.#
|
|
97
|
-
this.#element.addEventListener(
|
|
157
|
+
this.#play("slide-right-out", MOTION.EXIT);
|
|
158
|
+
this.#element.addEventListener("animationend", removeEvents);
|
|
98
159
|
}
|
|
99
160
|
}
|
|
100
161
|
|
|
101
162
|
scaleOutAndRemove() {
|
|
102
163
|
if (this.#element.style.animationName) {
|
|
103
|
-
this.#
|
|
104
|
-
this.#element.addEventListener(
|
|
164
|
+
this.#play("scale-out", MOTION.EXIT);
|
|
165
|
+
this.#element.addEventListener("animationend", removeEvents2);
|
|
105
166
|
}
|
|
106
167
|
}
|
|
107
168
|
|
|
108
169
|
fadeOutAndRemove() {
|
|
109
170
|
if (this.#element.style.animationName) {
|
|
110
|
-
this.#
|
|
111
|
-
this.#element.addEventListener(
|
|
171
|
+
this.#play("fade-out", MOTION.EXIT);
|
|
172
|
+
this.#element.addEventListener("animationend", removeEvents2);
|
|
112
173
|
}
|
|
113
174
|
}
|
|
114
175
|
|
|
@@ -118,19 +179,20 @@ class Animation {
|
|
|
118
179
|
}
|
|
119
180
|
|
|
120
181
|
removeStyles() {
|
|
121
|
-
this.#element.removeAttribute("
|
|
182
|
+
this.#element.removeAttribute("data-motion");
|
|
183
|
+
this.#element.removeAttribute("style");
|
|
122
184
|
}
|
|
123
185
|
}
|
|
124
186
|
|
|
125
187
|
const removeEvents2 = (event) => {
|
|
126
|
-
event.target.remove()
|
|
127
|
-
event.target.removeEventListener(
|
|
128
|
-
}
|
|
188
|
+
event.target.remove();
|
|
189
|
+
event.target.removeEventListener("animationend", removeEvents2);
|
|
190
|
+
};
|
|
129
191
|
|
|
130
192
|
const removeEvents = (event) => {
|
|
131
|
-
event.target.style.removeProperty(
|
|
132
|
-
event.target.style.removeProperty(
|
|
133
|
-
event.target.removeEventListener(
|
|
134
|
-
}
|
|
193
|
+
event.target.style.removeProperty("animation-name");
|
|
194
|
+
event.target.style.removeProperty("display");
|
|
195
|
+
event.target.removeEventListener("animationend", removeEvents);
|
|
196
|
+
};
|
|
135
197
|
|
|
136
|
-
exports.Animation = Animation
|
|
198
|
+
exports.Animation = Animation;
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Общий ритм для тех, кто считает кадры сам: построение диаграмм, догоняющее значение,
|
|
3
|
+
* счётчики. Время и кривую берём из темы — те же токены, что у переходов и кадров CSS,
|
|
4
|
+
* поэтому движение на канвасе и в стилях читается одним ритмом, а не двумя.
|
|
5
|
+
*
|
|
6
|
+
* ```javascript
|
|
7
|
+
* const { animate } = require("../../modules/chui_animations/motion");
|
|
8
|
+
* animate((growth) => this.#draw(growth)); // рисуем полотно по мере роста
|
|
9
|
+
* ```
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
/** Уменьшенное движение: движение не запускаем, результат ставим сразу */
|
|
13
|
+
function reducedMotion() {
|
|
14
|
+
return (
|
|
15
|
+
typeof window !== "undefined" &&
|
|
16
|
+
typeof window.matchMedia === "function" &&
|
|
17
|
+
window.matchMedia("(prefers-reduced-motion: reduce)").matches
|
|
18
|
+
);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Время токена движения в миллисекундах: `--motion_base` → 250. Своё число здесь не годится —
|
|
23
|
+
* время живёт в теме, и его правка должна менять всё движение сразу.
|
|
24
|
+
*/
|
|
25
|
+
function tokenTime(name = "--motion_base") {
|
|
26
|
+
const source =
|
|
27
|
+
typeof window !== "undefined" && typeof window.getComputedStyle === "function"
|
|
28
|
+
? window.getComputedStyle(document.documentElement).getPropertyValue(name)
|
|
29
|
+
: "";
|
|
30
|
+
const seconds = Number.parseFloat(source);
|
|
31
|
+
return Number.isFinite(seconds) && seconds > 0 ? seconds * 1000 : 250;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** Торможение к покою — приближение кривой `--motion_ease`: движение заканчивается мягко */
|
|
35
|
+
function easeOut(t) {
|
|
36
|
+
return 1 - Math.pow(1 - t, 3);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Кадры движения: `step(0…1)` вызывается на каждом кадре до конца времени, затем один раз
|
|
41
|
+
* с единицей — так последний кадр всегда полный. Возвращает остановку: её зовут, когда
|
|
42
|
+
* началось новое движение по тому же значению (иначе два кадра спорили бы за результат).
|
|
43
|
+
* При уменьшенном движении и там, где кадров нет (jsdom без `pretendToBeVisual`), шаг
|
|
44
|
+
* выполняется сразу с единицей.
|
|
45
|
+
*/
|
|
46
|
+
function animate(step, options = {}) {
|
|
47
|
+
const duration = options.duration === undefined ? tokenTime() : options.duration;
|
|
48
|
+
if (typeof requestAnimationFrame !== "function" || reducedMotion() || !(duration > 0)) {
|
|
49
|
+
step(1);
|
|
50
|
+
return () => {};
|
|
51
|
+
}
|
|
52
|
+
const now = () => (typeof performance === "undefined" ? Date.now() : performance.now());
|
|
53
|
+
const start = now();
|
|
54
|
+
let stopped = false;
|
|
55
|
+
const frame = (time) => {
|
|
56
|
+
if (stopped) return;
|
|
57
|
+
const t = Math.min(1, (time - start) / duration);
|
|
58
|
+
step(options.linear === true ? t : easeOut(t));
|
|
59
|
+
if (t < 1) requestAnimationFrame(frame);
|
|
60
|
+
};
|
|
61
|
+
requestAnimationFrame(frame);
|
|
62
|
+
return () => {
|
|
63
|
+
stopped = true;
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/** Ждём, пока запрос сменит значение: событие приходит асинхронно, кадров на это не хватает */
|
|
68
|
+
function waitForFlip(media, before) {
|
|
69
|
+
if (media.matches !== before) return Promise.resolve();
|
|
70
|
+
return new Promise((resolve) => {
|
|
71
|
+
const done = () => {
|
|
72
|
+
if (media.matches === before) return;
|
|
73
|
+
media.removeEventListener("change", done);
|
|
74
|
+
resolve();
|
|
75
|
+
};
|
|
76
|
+
media.addEventListener("change", done);
|
|
77
|
+
// Страховка: если смена не дошла, работа всё равно завершается, а не висит
|
|
78
|
+
setTimeout(() => {
|
|
79
|
+
media.removeEventListener("change", done);
|
|
80
|
+
resolve();
|
|
81
|
+
}, 1000);
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Работа с общим кроссфейдом: браузер снимает страницу до и после неё и переводит один кадр
|
|
87
|
+
* в другой. Нужен там, где мгновенное переносит не CSS-переход, а перерисовка, — смена темы:
|
|
88
|
+
* она приходит сменой `prefers-color-scheme`, и переходы на такое изменение браузер не
|
|
89
|
+
* запускает (проверено замером: цвет подложки меняется кадром, хотя класс с временем перехода
|
|
90
|
+
* на корне уже стоит).
|
|
91
|
+
*
|
|
92
|
+
* `waitFor` — имя запроса, значение которого должно смениться внутри работы до снимка
|
|
93
|
+
* «после»: без ожидания снимок может быть взят до перекраски, и кроссфейд пойдёт из старой
|
|
94
|
+
* схемы в старую. Возвращает то же, что вернула работа.
|
|
95
|
+
*/
|
|
96
|
+
async function crossFade(work, options = {}) {
|
|
97
|
+
if (reducedMotion() || typeof document === "undefined" || typeof document.startViewTransition !== "function") {
|
|
98
|
+
return work();
|
|
99
|
+
}
|
|
100
|
+
const media = options.waitFor === undefined ? undefined : window.matchMedia(options.waitFor);
|
|
101
|
+
const before = media === undefined ? undefined : media.matches;
|
|
102
|
+
let value;
|
|
103
|
+
const transition = document.startViewTransition(async () => {
|
|
104
|
+
value = await work();
|
|
105
|
+
// Ждём саму смену запроса: без этого снимок «после» может быть взят до перекраски,
|
|
106
|
+
// и кроссфейд пойдёт из старой схемы в старую. Кадров здесь нет намеренно:
|
|
107
|
+
// на время обработчика браузер останавливает отрисовку, и `requestAnimationFrame`
|
|
108
|
+
// не срабатывает вовсе (проверено — обработчик из-за этого зависал) —
|
|
109
|
+
// снимок новый браузер делает сам, когда обработчик завершится
|
|
110
|
+
if (media !== undefined) await waitForFlip(media, before);
|
|
111
|
+
});
|
|
112
|
+
await transition.updateCallbackDone;
|
|
113
|
+
return value;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
exports.reducedMotion = reducedMotion;
|
|
117
|
+
exports.tokenTime = tokenTime;
|
|
118
|
+
exports.easeOut = easeOut;
|
|
119
|
+
exports.animate = animate;
|
|
120
|
+
exports.crossFade = crossFade;
|
|
@@ -1,3 +1,36 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Виды движения. Имя кадра даёт JS (`Animation`), а длительность и кривая живут здесь:
|
|
3
|
+
* так у одного вида одно время на всё приложение, а не у каждого вызова своё.
|
|
4
|
+
* Вход базовый (0.25s) с торможением к покою, выход короче (0.15s) — уход не задерживает
|
|
5
|
+
* следующий экран, отклик чуть перелетает (пружина) — так читаются всплывающие меню и диалог.
|
|
6
|
+
* Значения — из темы (`--motion_*` в global_style.css).
|
|
7
|
+
*/
|
|
8
|
+
[data-motion="enter"] {
|
|
9
|
+
animation-duration: var(--motion_base);
|
|
10
|
+
animation-timing-function: var(--motion_ease);
|
|
11
|
+
animation-fill-mode: both;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
[data-motion="exit"] {
|
|
15
|
+
animation-duration: var(--motion_fast);
|
|
16
|
+
animation-timing-function: var(--motion_ease);
|
|
17
|
+
animation-fill-mode: both;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
[data-motion="pop"] {
|
|
21
|
+
animation-duration: var(--motion_base);
|
|
22
|
+
animation-timing-function: var(--motion_spring);
|
|
23
|
+
animation-fill-mode: both;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/* Кадром владеет слой, а не переход: после выходного вида заполненный `transform` остаётся
|
|
27
|
+
на месте, а следующий кадр его не объявляет — переход вернул бы слой на место отдельным
|
|
28
|
+
движением, поверх проигрываемого. Поэтому у слоя выключен только `transform`, остальные
|
|
29
|
+
свойства живут по общему правилу `* { transition }` */
|
|
30
|
+
[data-motion] {
|
|
31
|
+
transition-property: background-color, color, border-color, box-shadow, filter, opacity;
|
|
32
|
+
}
|
|
33
|
+
|
|
1
34
|
/* FADE */
|
|
2
35
|
@keyframes fade-in {
|
|
3
36
|
from {
|
|
@@ -16,11 +49,11 @@
|
|
|
16
49
|
opacity: 0;
|
|
17
50
|
}
|
|
18
51
|
}
|
|
19
|
-
/* SCALE */
|
|
52
|
+
/* SCALE. Масштаб появления небольшой (0.92 вместо прежних 0.63): крупный «наезд» камеры выделял сам эффект, а не появление слоя */
|
|
20
53
|
@keyframes scale-in {
|
|
21
54
|
from {
|
|
22
55
|
opacity: 0;
|
|
23
|
-
transform: scale(0.
|
|
56
|
+
transform: scale(0.92);
|
|
24
57
|
}
|
|
25
58
|
to {
|
|
26
59
|
opacity: 1;
|
|
@@ -34,7 +67,7 @@
|
|
|
34
67
|
}
|
|
35
68
|
to {
|
|
36
69
|
opacity: 0;
|
|
37
|
-
transform: scale(0.
|
|
70
|
+
transform: scale(0.96);
|
|
38
71
|
}
|
|
39
72
|
}
|
|
40
73
|
/* SLIDE */
|
|
@@ -77,4 +110,4 @@
|
|
|
77
110
|
opacity: 0;
|
|
78
111
|
transform: translateY(100%);
|
|
79
112
|
}
|
|
80
|
-
}
|
|
113
|
+
}
|
|
@@ -1,8 +1,14 @@
|
|
|
1
|
-
const {contextBridge, ipcRenderer} = require("electron");
|
|
2
|
-
const {
|
|
1
|
+
const { contextBridge, ipcRenderer } = require("electron");
|
|
2
|
+
const {
|
|
3
|
+
SERVICES_CHANNELS,
|
|
4
|
+
SERVICES_CALLS,
|
|
5
|
+
SERVICES_SYNC_CALLS,
|
|
6
|
+
BRIDGE_CHANNELS,
|
|
7
|
+
BRIDGE_ARGS,
|
|
8
|
+
} = require("../chui_services/chui_channels");
|
|
3
9
|
// Мост переиспользует ту же обёртку сервисов, что и страница: разница только в транспорте
|
|
4
10
|
// (`Desktop` в preload'е сам вызовет ipcRenderer, потому что `window.chui` ему не виден)
|
|
5
|
-
const {Desktop} = require("../chui_services/desktop");
|
|
11
|
+
const { Desktop } = require("../chui_services/desktop");
|
|
6
12
|
|
|
7
13
|
/**
|
|
8
14
|
* Preload безопасного режима (`Main({security: {contextIsolation: true}})`).
|
|
@@ -32,7 +38,10 @@ function argValue(prefix = String()) {
|
|
|
32
38
|
|
|
33
39
|
const renderPath = argValue(BRIDGE_ARGS.RENDER);
|
|
34
40
|
const csp = argValue(BRIDGE_ARGS.CSP);
|
|
35
|
-
const channels = (argValue(BRIDGE_ARGS.CHANNELS) ?? "")
|
|
41
|
+
const channels = (argValue(BRIDGE_ARGS.CHANNELS) ?? "")
|
|
42
|
+
.split(",")
|
|
43
|
+
.map((channel) => channel.trim())
|
|
44
|
+
.filter(Boolean);
|
|
36
45
|
|
|
37
46
|
/**
|
|
38
47
|
* Content-Security-Policy вставляется в документ до его скриптов: preload выполняется раньше
|
|
@@ -50,7 +59,7 @@ function applyCsp() {
|
|
|
50
59
|
return true;
|
|
51
60
|
}
|
|
52
61
|
|
|
53
|
-
if (!applyCsp()) document.addEventListener("readystatechange", () => applyCsp(), {once: true});
|
|
62
|
+
if (!applyCsp()) document.addEventListener("readystatechange", () => applyCsp(), { once: true });
|
|
54
63
|
|
|
55
64
|
const call = (method = String(), ...args) => {
|
|
56
65
|
const channel = SERVICES_CALLS[method];
|
|
@@ -100,7 +109,7 @@ contextBridge.exposeInMainWorld("chui", {
|
|
|
100
109
|
versions: {
|
|
101
110
|
node: process.versions.node,
|
|
102
111
|
chrome: process.versions.chrome,
|
|
103
|
-
electron: process.versions.electron
|
|
112
|
+
electron: process.versions.electron,
|
|
104
113
|
},
|
|
105
114
|
platform: process.platform,
|
|
106
115
|
/** Путь к странице окна (как он задан в опции `render`) */
|
|
@@ -120,20 +129,20 @@ contextBridge.exposeInMainWorld("chui", {
|
|
|
120
129
|
copy: (text = String()) => Desktop.clipboard.history.copy(text),
|
|
121
130
|
remove: (target = undefined) => Desktop.clipboard.history.remove(target),
|
|
122
131
|
clear: () => Desktop.clipboard.history.clear(),
|
|
123
|
-
onChange: (listener = () => {}) => services.onClipboardHistory(listener)
|
|
124
|
-
}
|
|
132
|
+
onChange: (listener = () => {}) => services.onClipboardHistory(listener),
|
|
133
|
+
},
|
|
125
134
|
},
|
|
126
135
|
recent: {
|
|
127
136
|
add: (path = String(), name = undefined) => Desktop.recent.add(path, name),
|
|
128
137
|
clear: () => Desktop.recent.clear(),
|
|
129
|
-
list: () => Desktop.recent.list()
|
|
138
|
+
list: () => Desktop.recent.list(),
|
|
130
139
|
},
|
|
131
140
|
progress: {
|
|
132
141
|
set: (value = Number(), mode = "normal") => Desktop.progress.set(value, mode),
|
|
133
|
-
clear: () => Desktop.progress.clear()
|
|
142
|
+
clear: () => Desktop.progress.clear(),
|
|
134
143
|
},
|
|
135
144
|
shell: {
|
|
136
|
-
openExternal: (url = String()) => Desktop.shell.openExternal(url)
|
|
145
|
+
openExternal: (url = String()) => Desktop.shell.openExternal(url),
|
|
137
146
|
},
|
|
138
147
|
app: {
|
|
139
148
|
// Путь приходит значением, без промиса (синхронный канал), а `Desktop` в preload'е
|
|
@@ -148,36 +157,36 @@ contextBridge.exposeInMainWorld("chui", {
|
|
|
148
157
|
// Закрытие и перезапуск — как у `Desktop` из пакета: те же шаги, что у пункта меню.
|
|
149
158
|
// Отвечают значением, а не промисом (синхронный канал), поэтому `await` не нужен
|
|
150
159
|
quit: () => Desktop.app.quit(),
|
|
151
|
-
restart: () => Desktop.app.restart()
|
|
160
|
+
restart: () => Desktop.app.restart(),
|
|
152
161
|
},
|
|
153
162
|
dialog: {
|
|
154
163
|
open: (options = {}) => Desktop.dialog.open(options),
|
|
155
164
|
save: (options = {}) => Desktop.dialog.save(options),
|
|
156
|
-
message: (options = {}) => Desktop.dialog.message(options)
|
|
165
|
+
message: (options = {}) => Desktop.dialog.message(options),
|
|
157
166
|
},
|
|
158
167
|
session: {
|
|
159
168
|
getCacheSize: () => Desktop.session.getCacheSize(),
|
|
160
169
|
clearCache: () => Desktop.session.clearCache(),
|
|
161
|
-
clearStorageData: (options = {}) => Desktop.session.clearStorageData(options)
|
|
170
|
+
clearStorageData: (options = {}) => Desktop.session.clearStorageData(options),
|
|
162
171
|
},
|
|
163
172
|
print: {
|
|
164
173
|
page: (options = {}) => Desktop.print.page(options),
|
|
165
174
|
html: (html = String(), options = {}) => Desktop.print.html(html, options),
|
|
166
|
-
pdf: (html = String(), options = {}) => Desktop.print.pdf(html, options)
|
|
175
|
+
pdf: (html = String(), options = {}) => Desktop.print.pdf(html, options),
|
|
167
176
|
},
|
|
168
177
|
shortcuts: {
|
|
169
178
|
on: (accelerator = String(), handler = () => {}) => Desktop.shortcuts.on(accelerator, handler),
|
|
170
179
|
off: (accelerator = String(), handler = () => {}) => Desktop.shortcuts.off(accelerator, handler),
|
|
171
180
|
offAll: () => Desktop.shortcuts.offAll(),
|
|
172
|
-
get: () => Desktop.shortcuts.get()
|
|
173
|
-
}
|
|
181
|
+
get: () => Desktop.shortcuts.get(),
|
|
182
|
+
},
|
|
174
183
|
},
|
|
175
184
|
window: {
|
|
176
185
|
minimize: () => windowAction("minimize"),
|
|
177
186
|
toggleMaximize: () => windowAction("toggle-maximize"),
|
|
178
187
|
restore: () => windowAction("restore"),
|
|
179
188
|
close: () => windowAction("close"),
|
|
180
|
-
getState: () => ipcRenderer.invoke(BRIDGE_CHANNELS.WINDOW_STATE)
|
|
189
|
+
getState: () => ipcRenderer.invoke(BRIDGE_CHANNELS.WINDOW_STATE),
|
|
181
190
|
},
|
|
182
191
|
theme: {
|
|
183
192
|
get: () => ipcRenderer.invoke(BRIDGE_CHANNELS.THEME_GET),
|
|
@@ -187,7 +196,7 @@ contextBridge.exposeInMainWorld("chui", {
|
|
|
187
196
|
onChange: (listener = () => {}) => {
|
|
188
197
|
themeListeners.add(listener);
|
|
189
198
|
return () => themeListeners.delete(listener);
|
|
190
|
-
}
|
|
199
|
+
},
|
|
191
200
|
},
|
|
192
201
|
locale: {
|
|
193
202
|
get: () => ipcRenderer.invoke(BRIDGE_CHANNELS.LOCALE_GET),
|
|
@@ -196,17 +205,19 @@ contextBridge.exposeInMainWorld("chui", {
|
|
|
196
205
|
onChange: (listener = () => {}) => {
|
|
197
206
|
localeListeners.add(listener);
|
|
198
207
|
return () => localeListeners.delete(listener);
|
|
199
|
-
}
|
|
208
|
+
},
|
|
200
209
|
},
|
|
201
210
|
messaging: {
|
|
202
211
|
/** Каналы задаёт приложение: `security: {channels: ['preview:update']}` */
|
|
203
212
|
channels: [...channels],
|
|
204
213
|
send: (channel = String(), ...args) => {
|
|
205
|
-
if (!channels.includes(channel))
|
|
214
|
+
if (!channels.includes(channel))
|
|
215
|
+
throw new Error(`chui: канал «${channel}» не разрешён в security.channels`);
|
|
206
216
|
return ipcRenderer.invoke(BRIDGE_CHANNELS.MESSAGE, channel, ...args);
|
|
207
217
|
},
|
|
208
218
|
on: (channel = String(), listener = () => {}) => {
|
|
209
|
-
if (!channels.includes(channel))
|
|
219
|
+
if (!channels.includes(channel))
|
|
220
|
+
throw new Error(`chui: канал «${channel}» не разрешён в security.channels`);
|
|
210
221
|
const listeners = messageListeners.get(channel) ?? new Set();
|
|
211
222
|
listeners.add(listener);
|
|
212
223
|
messageListeners.set(channel, listeners);
|
|
@@ -214,8 +225,8 @@ contextBridge.exposeInMainWorld("chui", {
|
|
|
214
225
|
listeners.delete(listener);
|
|
215
226
|
if (listeners.size === 0) messageListeners.delete(channel);
|
|
216
227
|
};
|
|
217
|
-
}
|
|
218
|
-
}
|
|
228
|
+
},
|
|
229
|
+
},
|
|
219
230
|
});
|
|
220
231
|
|
|
221
232
|
// Скрипт страницы подключается здесь: в безопасном режиме `render` — это скрипт документа,
|
|
@@ -227,6 +238,6 @@ if (renderPath !== undefined) {
|
|
|
227
238
|
script.defer = true;
|
|
228
239
|
document.head.appendChild(script);
|
|
229
240
|
};
|
|
230
|
-
if (document.readyState === "loading") window.addEventListener("DOMContentLoaded", addPageScript, {once: true});
|
|
241
|
+
if (document.readyState === "loading") window.addEventListener("DOMContentLoaded", addPageScript, { once: true });
|
|
231
242
|
else addPageScript();
|
|
232
243
|
}
|