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,9 +1,9 @@
|
|
|
1
|
-
const {setStyles} = require("../../modules/chui_functions");
|
|
2
|
-
const {A11Y_FOCUSABLE_SELECTOR} = require("../../modules/chui_a11y/chui_a11y");
|
|
3
|
-
const {store:
|
|
4
|
-
const {ThemeToggle} = require("../chui_theme_toggle/theme_toggle");
|
|
5
|
-
const {Toggle} = require("../chui_inputs/chui_toggle/toggle");
|
|
6
|
-
const {I18n} = require("../../modules/chui_i18n/chui_i18n");
|
|
1
|
+
const { setStyles } = require("../../modules/chui_functions");
|
|
2
|
+
const { A11Y_FOCUSABLE_SELECTOR } = require("../../modules/chui_a11y/chui_a11y");
|
|
3
|
+
const { store: sharedStore } = require("../../modules/chui_store/chui_store");
|
|
4
|
+
const { ThemeToggle } = require("../chui_theme_toggle/theme_toggle");
|
|
5
|
+
const { Toggle } = require("../chui_inputs/chui_toggle/toggle");
|
|
6
|
+
const { I18n } = require("../../modules/chui_i18n/chui_i18n");
|
|
7
7
|
|
|
8
8
|
/** Заполнено ли текстовое поле: пустая строка равнозначна отсутствию */
|
|
9
9
|
const hasText = (value) => value !== undefined && value !== null && String(value).trim() !== "";
|
|
@@ -74,28 +74,30 @@ class Settings {
|
|
|
74
74
|
#rows = [];
|
|
75
75
|
/** Хранилище и ключ, под которым панель держит свои значения (без ключа — не держит) */
|
|
76
76
|
#store = undefined;
|
|
77
|
-
#
|
|
77
|
+
#storeKey = undefined;
|
|
78
78
|
/** Подписчики правки строки и её обработчик из опций */
|
|
79
|
-
#
|
|
80
|
-
#
|
|
79
|
+
#changeListeners = [];
|
|
80
|
+
#onChange = undefined;
|
|
81
81
|
/** Последние известные значения строк: расхождение со снимком и есть правка пользователя */
|
|
82
82
|
#seen = new Map();
|
|
83
83
|
|
|
84
|
-
constructor(
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
84
|
+
constructor(
|
|
85
|
+
options = {
|
|
86
|
+
id: String(),
|
|
87
|
+
title: String(),
|
|
88
|
+
description: String(),
|
|
89
|
+
sections: [],
|
|
90
|
+
store: undefined,
|
|
91
|
+
storeKey: String(),
|
|
92
|
+
onChange: undefined,
|
|
93
|
+
}
|
|
94
|
+
) {
|
|
93
95
|
setStyles(__dirname + "/styles.css", "chUiJS_Settings");
|
|
94
96
|
Settings.#counter += 1;
|
|
95
97
|
this.#id = options.id === undefined ? `chui_settings_${Settings.#counter}` : options.id;
|
|
96
|
-
this.#store = options.store === undefined ?
|
|
97
|
-
this.#
|
|
98
|
-
this.#
|
|
98
|
+
this.#store = options.store === undefined ? sharedStore : options.store;
|
|
99
|
+
this.#storeKey = hasText(options.storeKey) ? String(options.storeKey) : undefined;
|
|
100
|
+
this.#onChange = options.onChange;
|
|
99
101
|
this.#root.id = this.#id;
|
|
100
102
|
if (options.title !== undefined) {
|
|
101
103
|
const title = document.createElement("settings_title");
|
|
@@ -112,7 +114,7 @@ class Settings {
|
|
|
112
114
|
// контролы (сегментированный, оценка), у которых своего события в DOM нет
|
|
113
115
|
this.#root.addEventListener("change", this.#onUserEdit);
|
|
114
116
|
this.#root.addEventListener("click", this.#onUserEdit);
|
|
115
|
-
if (this.#
|
|
117
|
+
if (this.#storeKey !== undefined) this.restore();
|
|
116
118
|
// Снимок значений: от него панель отсчитывает правки пользователя
|
|
117
119
|
this.#remember();
|
|
118
120
|
}
|
|
@@ -128,7 +130,13 @@ class Settings {
|
|
|
128
130
|
|
|
129
131
|
/** Строки в порядке добавления: `{title, name, node, control, disabled}` */
|
|
130
132
|
getControls() {
|
|
131
|
-
return this.#rows.map((row) => ({
|
|
133
|
+
return this.#rows.map((row) => ({
|
|
134
|
+
title: row.title,
|
|
135
|
+
name: row.name,
|
|
136
|
+
node: row.node,
|
|
137
|
+
control: row.control,
|
|
138
|
+
disabled: row.disabled,
|
|
139
|
+
}));
|
|
132
140
|
}
|
|
133
141
|
|
|
134
142
|
/** Контрол строки: адрес — описание из `Settings.Row(...)`, название или имя */
|
|
@@ -138,8 +146,8 @@ class Settings {
|
|
|
138
146
|
}
|
|
139
147
|
|
|
140
148
|
/** Значение строки: адрес — описание из `Settings.Row(...)`, название или имя */
|
|
141
|
-
getValue(
|
|
142
|
-
const record = this.#findRow(
|
|
149
|
+
getValue(rowOrTitle = undefined) {
|
|
150
|
+
const record = this.#findRow(rowOrTitle);
|
|
143
151
|
return record === undefined ? undefined : this.#readValue(record.control);
|
|
144
152
|
}
|
|
145
153
|
|
|
@@ -153,14 +161,14 @@ class Settings {
|
|
|
153
161
|
}
|
|
154
162
|
|
|
155
163
|
/** Значения строк раздела: адрес — описание из `Settings.Section(...)` или заголовок */
|
|
156
|
-
getSectionValues(
|
|
157
|
-
const section = this.#findSection(
|
|
164
|
+
getSectionValues(sectionOrTitle = undefined) {
|
|
165
|
+
const section = this.#findSection(sectionOrTitle);
|
|
158
166
|
return section === undefined ? {} : this.#valuesOf((record) => record.section === section);
|
|
159
167
|
}
|
|
160
168
|
|
|
161
169
|
/** Выключена ли строка: `false` и для несуществующей */
|
|
162
|
-
isRowDisabled(
|
|
163
|
-
const record = this.#findRow(
|
|
170
|
+
isRowDisabled(rowOrTitle = undefined) {
|
|
171
|
+
const record = this.#findRow(rowOrTitle);
|
|
164
172
|
return record === undefined ? false : record.disabled;
|
|
165
173
|
}
|
|
166
174
|
|
|
@@ -171,27 +179,27 @@ class Settings {
|
|
|
171
179
|
* может вернуть), а программная запись уведомления не рождает.
|
|
172
180
|
*/
|
|
173
181
|
addChangeListener(listener = () => {}) {
|
|
174
|
-
this.#
|
|
182
|
+
this.#changeListeners.push(listener);
|
|
175
183
|
return this;
|
|
176
184
|
}
|
|
177
185
|
|
|
178
186
|
// ХРАНЕНИЕ
|
|
179
187
|
/** Ключ панели в хранилище; `undefined` — панель значения не хранит */
|
|
180
188
|
getStoreKey() {
|
|
181
|
-
return this.#
|
|
189
|
+
return this.#storeKey;
|
|
182
190
|
}
|
|
183
191
|
|
|
184
192
|
/** Записать значения панели в хранилище; без ключа — ничего не делает */
|
|
185
193
|
save() {
|
|
186
|
-
if (this.#
|
|
187
|
-
this.#store.set(this.#
|
|
194
|
+
if (this.#storeKey === undefined) return this;
|
|
195
|
+
this.#store.set(this.#storeKey, this.#storageValues());
|
|
188
196
|
return this;
|
|
189
197
|
}
|
|
190
198
|
|
|
191
199
|
/** Прочитать значения из хранилища и заполнить строки; без сохранённого панель не меняется */
|
|
192
200
|
restore() {
|
|
193
|
-
if (this.#
|
|
194
|
-
return this.setValues(this.#store.get(this.#
|
|
201
|
+
if (this.#storeKey === undefined) return this;
|
|
202
|
+
return this.setValues(this.#store.get(this.#storeKey, {}));
|
|
195
203
|
}
|
|
196
204
|
|
|
197
205
|
// SET
|
|
@@ -199,8 +207,8 @@ class Settings {
|
|
|
199
207
|
* Записать значение строки: адрес — описание из `Settings.Row(...)`, название или имя.
|
|
200
208
|
* Несуществующая строка и строка без писателя (кнопка) — без изменений.
|
|
201
209
|
*/
|
|
202
|
-
setValue(
|
|
203
|
-
const record = this.#findRow(
|
|
210
|
+
setValue(rowOrTitle = undefined, value = undefined) {
|
|
211
|
+
const record = this.#findRow(rowOrTitle);
|
|
204
212
|
if (record === undefined) return this;
|
|
205
213
|
this.#writeValue(record.control, value);
|
|
206
214
|
this.#remember();
|
|
@@ -217,8 +225,8 @@ class Settings {
|
|
|
217
225
|
}
|
|
218
226
|
|
|
219
227
|
/** Заполнить строки раздела: адрес — описание из `Settings.Section(...)` или заголовок */
|
|
220
|
-
setSectionValues(
|
|
221
|
-
const section = this.#findSection(
|
|
228
|
+
setSectionValues(sectionOrTitle = undefined, values = Object()) {
|
|
229
|
+
const section = this.#findSection(sectionOrTitle);
|
|
222
230
|
if (section === undefined) return this;
|
|
223
231
|
return this.#writeValues(values, (record) => record.section === section);
|
|
224
232
|
}
|
|
@@ -234,8 +242,8 @@ class Settings {
|
|
|
234
242
|
}
|
|
235
243
|
|
|
236
244
|
/** Выключить или включить строку: адресуется описанием из `Settings.Row(...)`, названием или именем */
|
|
237
|
-
setRowDisabled(
|
|
238
|
-
const record = this.#findRow(
|
|
245
|
+
setRowDisabled(rowOrTitle = undefined, disabled = Boolean()) {
|
|
246
|
+
const record = this.#findRow(rowOrTitle);
|
|
239
247
|
if (record === undefined) return this;
|
|
240
248
|
this.#setRowDisabled(record, disabled);
|
|
241
249
|
return this;
|
|
@@ -252,13 +260,14 @@ class Settings {
|
|
|
252
260
|
* действие, а не значение) ничего не меняет и потому ничего не сообщает.
|
|
253
261
|
*/
|
|
254
262
|
#onUserEdit = (event) => {
|
|
255
|
-
if (event.type === "click" && event.target instanceof Element && event.target.closest("button") !== null)
|
|
256
|
-
|
|
263
|
+
if (event.type === "click" && event.target instanceof Element && event.target.closest("button") !== null)
|
|
264
|
+
return;
|
|
265
|
+
if (this.#storeKey === undefined && this.#changeListeners.length === 0 && this.#onChange === undefined) return;
|
|
257
266
|
const changed = this.#changedRows();
|
|
258
267
|
if (changed.length === 0) return;
|
|
259
|
-
if (this.#
|
|
268
|
+
if (this.#storeKey !== undefined) this.save();
|
|
260
269
|
for (const record of changed) this.#emitChange(record);
|
|
261
|
-
}
|
|
270
|
+
};
|
|
262
271
|
|
|
263
272
|
/**
|
|
264
273
|
* Строки, значение которых разошлось со снимком; снимок тут же обновляется, поэтому одна и та же
|
|
@@ -284,10 +293,10 @@ class Settings {
|
|
|
284
293
|
section: record.section,
|
|
285
294
|
title: record.title,
|
|
286
295
|
name: record.name,
|
|
287
|
-
value: this.#readValue(record.control)
|
|
296
|
+
value: this.#readValue(record.control),
|
|
288
297
|
};
|
|
289
|
-
for (const listener of [...this.#
|
|
290
|
-
if (this.#
|
|
298
|
+
for (const listener of [...this.#changeListeners]) listener(change, this);
|
|
299
|
+
if (this.#onChange !== undefined) this.#onChange(change, this);
|
|
291
300
|
}
|
|
292
301
|
|
|
293
302
|
/** Снимок значений строк: от него панель отсчитывает следующие правки */
|
|
@@ -337,7 +346,8 @@ class Settings {
|
|
|
337
346
|
node.appendChild(head);
|
|
338
347
|
}
|
|
339
348
|
const rows = document.createElement("settings_rows");
|
|
340
|
-
for (const row of section.rows === undefined ? [] : section.rows)
|
|
349
|
+
for (const row of section.rows === undefined ? [] : section.rows)
|
|
350
|
+
rows.appendChild(this.#buildRow(row, section));
|
|
341
351
|
node.appendChild(rows);
|
|
342
352
|
return node;
|
|
343
353
|
}
|
|
@@ -350,12 +360,13 @@ class Settings {
|
|
|
350
360
|
const named = hasText(row.name);
|
|
351
361
|
node.classList.toggle("settings_row_control_only", solo);
|
|
352
362
|
node.classList.toggle("settings_row_stretch", row.stretch === true);
|
|
353
|
-
const
|
|
363
|
+
const descriptionId = solo ? undefined : this.#buildRowText(row, node);
|
|
354
364
|
const holder = document.createElement("settings_row_control");
|
|
355
|
-
const control =
|
|
365
|
+
const control =
|
|
366
|
+
row.control === undefined ? undefined : row.control instanceof Element ? row.control : row.control.set();
|
|
356
367
|
if (control !== undefined) {
|
|
357
368
|
holder.appendChild(control);
|
|
358
|
-
this.#applyControlA11y(control, titled ? String(row.title) : String(),
|
|
369
|
+
this.#applyControlA11y(control, titled ? String(row.title) : String(), descriptionId);
|
|
359
370
|
}
|
|
360
371
|
node.appendChild(holder);
|
|
361
372
|
// Храним исходный контрол (компонент или узел): findControl() возвращает его вместе с методами
|
|
@@ -364,16 +375,17 @@ class Settings {
|
|
|
364
375
|
section: section,
|
|
365
376
|
title: titled ? String(row.title) : String(),
|
|
366
377
|
// Ключ строки: имя постоянно, а название видно пользователю и меняется при переименовании
|
|
367
|
-
name: named ? String(row.name) :
|
|
378
|
+
name: named ? String(row.name) : titled ? String(row.title) : String(),
|
|
368
379
|
node: node,
|
|
369
380
|
holder: holder,
|
|
370
381
|
control: row.control,
|
|
371
382
|
disabled: false,
|
|
372
|
-
natives: []
|
|
383
|
+
natives: [],
|
|
373
384
|
};
|
|
374
385
|
// Запрет панель ставит и полям готового узла, поэтому их исходное состояние запоминаем заранее —
|
|
375
386
|
// иначе включение вернуло бы строку в другое состояние, чем было до выключения
|
|
376
|
-
for (const native of holder.querySelectorAll(Settings.#NATIVE_CONTROLS))
|
|
387
|
+
for (const native of holder.querySelectorAll(Settings.#NATIVE_CONTROLS))
|
|
388
|
+
record.natives.push({ node: native, disabled: native.disabled });
|
|
377
389
|
this.#rows.push(record);
|
|
378
390
|
if (row.disabled === true) this.#setRowDisabled(record, true);
|
|
379
391
|
return node;
|
|
@@ -382,7 +394,7 @@ class Settings {
|
|
|
382
394
|
/** Текст строки — название и описание; возвращает id описания (на него ссылается контрол) */
|
|
383
395
|
#buildRowText(row = Object(), node = new HTMLElement()) {
|
|
384
396
|
const text = document.createElement("settings_row_text");
|
|
385
|
-
let
|
|
397
|
+
let descriptionId = undefined;
|
|
386
398
|
if (hasText(row.title)) {
|
|
387
399
|
const title = document.createElement("settings_row_title");
|
|
388
400
|
title.innerText = String(row.title);
|
|
@@ -392,11 +404,11 @@ class Settings {
|
|
|
392
404
|
const description = document.createElement("settings_row_description");
|
|
393
405
|
description.innerText = String(row.description);
|
|
394
406
|
description.id = `${this.#id}_row_${this.#rows.length}_description`;
|
|
395
|
-
|
|
407
|
+
descriptionId = description.id;
|
|
396
408
|
text.appendChild(description);
|
|
397
409
|
}
|
|
398
410
|
node.appendChild(text);
|
|
399
|
-
return
|
|
411
|
+
return descriptionId;
|
|
400
412
|
}
|
|
401
413
|
|
|
402
414
|
/**
|
|
@@ -417,17 +429,23 @@ class Settings {
|
|
|
417
429
|
}
|
|
418
430
|
|
|
419
431
|
/** Строка по описанию из `Settings.Row(...)`, названию или имени (у строки-контрола их может и не быть) */
|
|
420
|
-
#findRow(
|
|
421
|
-
if (
|
|
422
|
-
return this.#rows.find(
|
|
423
|
-
|
|
424
|
-
|
|
432
|
+
#findRow(rowOrTitle = undefined) {
|
|
433
|
+
if (rowOrTitle === undefined || rowOrTitle === null) return undefined;
|
|
434
|
+
return this.#rows.find(
|
|
435
|
+
(row) =>
|
|
436
|
+
row.row === rowOrTitle ||
|
|
437
|
+
(row.title.length > 0 && row.title === rowOrTitle) ||
|
|
438
|
+
(row.name.length > 0 && row.name === rowOrTitle)
|
|
439
|
+
);
|
|
425
440
|
}
|
|
426
441
|
|
|
427
442
|
/** Раздел по описанию из `Settings.Section(...)` или по заголовку (у раздела без заголовка — только описание) */
|
|
428
|
-
#findSection(
|
|
429
|
-
if (
|
|
430
|
-
return this.#sections.find(
|
|
443
|
+
#findSection(sectionOrTitle = undefined) {
|
|
444
|
+
if (sectionOrTitle === undefined || sectionOrTitle === null) return undefined;
|
|
445
|
+
return this.#sections.find(
|
|
446
|
+
(section) =>
|
|
447
|
+
section === sectionOrTitle || (hasText(section.title) && String(section.title) === sectionOrTitle)
|
|
448
|
+
);
|
|
431
449
|
}
|
|
432
450
|
|
|
433
451
|
/** Карта «ключ — значение» по отобранным строкам; строка без имени и названия ключа дать не может */
|
|
@@ -459,18 +477,22 @@ class Settings {
|
|
|
459
477
|
* выбранные значения (свой `value` вернул бы только первый пункт).
|
|
460
478
|
*/
|
|
461
479
|
#readValue(control = undefined) {
|
|
462
|
-
if (control !== undefined && control !== null && typeof control.getValue === "function")
|
|
480
|
+
if (control !== undefined && control !== null && typeof control.getValue === "function")
|
|
481
|
+
return control.getValue();
|
|
463
482
|
const field = Settings.#valueField(control);
|
|
464
483
|
if (field === undefined) return undefined;
|
|
465
484
|
if (field.type === "checkbox" || field.type === "radio") return field.checked;
|
|
466
|
-
if (field.tagName === "SELECT" && field.multiple === true)
|
|
485
|
+
if (field.tagName === "SELECT" && field.multiple === true)
|
|
486
|
+
return Array.from(field.selectedOptions, (option) => option.value);
|
|
467
487
|
return field.value;
|
|
468
488
|
}
|
|
469
489
|
|
|
470
490
|
/** Поле готового узла, с которого панель читает значение */
|
|
471
491
|
static #valueField(control = undefined) {
|
|
472
492
|
if (!(control instanceof Element)) return undefined;
|
|
473
|
-
const field = control.matches(Settings.#NATIVE_VALUES)
|
|
493
|
+
const field = control.matches(Settings.#NATIVE_VALUES)
|
|
494
|
+
? control
|
|
495
|
+
: control.querySelector(Settings.#NATIVE_VALUES);
|
|
474
496
|
return field === null ? undefined : field;
|
|
475
497
|
}
|
|
476
498
|
|
|
@@ -515,48 +537,99 @@ class Settings {
|
|
|
515
537
|
* а связь через `<label>` признаём только когда в нём есть текст: у `Toggle` разметка —
|
|
516
538
|
* пустой `<label>` вокруг `input`, и без `aria-label` флажок остался бы без имени.
|
|
517
539
|
*/
|
|
518
|
-
#applyControlA11y(control = new HTMLElement(), label = String(),
|
|
540
|
+
#applyControlA11y(control = new HTMLElement(), label = String(), descriptionId = undefined) {
|
|
519
541
|
const role = control.getAttribute("role");
|
|
520
|
-
const target =
|
|
521
|
-
|
|
522
|
-
|
|
542
|
+
const target =
|
|
543
|
+
role === null || role === "presentation"
|
|
544
|
+
? control.matches(Settings.#FOCUSABLE)
|
|
545
|
+
? control
|
|
546
|
+
: control.querySelector(Settings.#FOCUSABLE)
|
|
547
|
+
: control;
|
|
523
548
|
if (target === null) return;
|
|
524
|
-
if (
|
|
549
|
+
if (descriptionId !== undefined) target.setAttribute("aria-describedby", descriptionId);
|
|
525
550
|
if (label.length === 0) return;
|
|
526
551
|
if (target.getAttribute("aria-label") !== null) return;
|
|
527
552
|
const wrapper = target.closest("label");
|
|
528
|
-
const labelled =
|
|
529
|
-
|
|
553
|
+
const labelled =
|
|
554
|
+
(wrapper !== null && wrapper.innerText.trim().length > 0) ||
|
|
555
|
+
(target.id !== "" && control.querySelector(`label[for="${target.id}"]`) !== null);
|
|
530
556
|
if (!labelled) target.setAttribute("aria-label", label);
|
|
531
557
|
}
|
|
532
558
|
|
|
533
|
-
static Section(options = {title: String(), description: String(), rows: []}) {
|
|
534
|
-
return {title: options.title, description: options.description, rows: options.rows};
|
|
559
|
+
static Section(options = { title: String(), description: String(), rows: [] }) {
|
|
560
|
+
return { title: options.title, description: options.description, rows: options.rows };
|
|
535
561
|
}
|
|
536
562
|
|
|
537
|
-
static Row(
|
|
538
|
-
|
|
563
|
+
static Row(
|
|
564
|
+
options = {
|
|
565
|
+
title: String(),
|
|
566
|
+
description: String(),
|
|
567
|
+
name: String(),
|
|
568
|
+
control: undefined,
|
|
569
|
+
disabled: Boolean(),
|
|
570
|
+
stretch: Boolean(),
|
|
571
|
+
}
|
|
572
|
+
) {
|
|
573
|
+
return {
|
|
574
|
+
title: options.title,
|
|
575
|
+
description: options.description,
|
|
576
|
+
name: options.name,
|
|
577
|
+
control: options.control,
|
|
578
|
+
disabled: options.disabled === true,
|
|
579
|
+
stretch: options.stretch === true,
|
|
580
|
+
};
|
|
539
581
|
}
|
|
540
582
|
|
|
541
583
|
/** Строка с переключателем темы: `control` — сам `ThemeToggle` */
|
|
542
|
-
static ThemeRow(
|
|
584
|
+
static ThemeRow(
|
|
585
|
+
options = {
|
|
586
|
+
title: I18n.t("graphics.settingsTheme"),
|
|
587
|
+
description: String(),
|
|
588
|
+
name: String(),
|
|
589
|
+
modes: [],
|
|
590
|
+
labels: {},
|
|
591
|
+
onChange: undefined,
|
|
592
|
+
disabled: Boolean(),
|
|
593
|
+
}
|
|
594
|
+
) {
|
|
543
595
|
const toggle = new ThemeToggle({
|
|
544
596
|
modes: options.modes,
|
|
545
597
|
labels: options.labels,
|
|
546
598
|
label: options.title === undefined ? I18n.t("graphics.settingsAppearance") : options.title,
|
|
547
|
-
onChange: options.onChange
|
|
599
|
+
onChange: options.onChange,
|
|
600
|
+
});
|
|
601
|
+
return Settings.Row({
|
|
602
|
+
title: options.title === undefined ? I18n.t("graphics.settingsTheme") : options.title,
|
|
603
|
+
description: options.description,
|
|
604
|
+
name: options.name,
|
|
605
|
+
control: toggle,
|
|
606
|
+
disabled: options.disabled,
|
|
548
607
|
});
|
|
549
|
-
return Settings.Row({title: options.title === undefined ? I18n.t("graphics.settingsTheme") : options.title, description: options.description, name: options.name, control: toggle, disabled: options.disabled});
|
|
550
608
|
}
|
|
551
609
|
|
|
552
610
|
/** Строка с флажком: `control` — сам `Toggle` */
|
|
553
|
-
static ToggleRow(
|
|
611
|
+
static ToggleRow(
|
|
612
|
+
options = {
|
|
613
|
+
title: String(),
|
|
614
|
+
description: String(),
|
|
615
|
+
name: String(),
|
|
616
|
+
value: Boolean(),
|
|
617
|
+
onChange: undefined,
|
|
618
|
+
disabled: Boolean(),
|
|
619
|
+
}
|
|
620
|
+
) {
|
|
554
621
|
// Подпись строки сразу уходит в сам переключатель: вне Settings он остаётся без имени
|
|
555
|
-
const toggle = new Toggle({label: options.title});
|
|
622
|
+
const toggle = new Toggle({ label: options.title });
|
|
556
623
|
if (options.value !== undefined) toggle.setValue(options.value === true);
|
|
557
624
|
if (options.onChange !== undefined) toggle.addChangeListener(options.onChange);
|
|
558
|
-
return Settings.Row({
|
|
625
|
+
return Settings.Row({
|
|
626
|
+
title: options.title,
|
|
627
|
+
description: options.description,
|
|
628
|
+
name: options.name,
|
|
629
|
+
control: toggle,
|
|
630
|
+
disabled: options.disabled,
|
|
631
|
+
});
|
|
559
632
|
}
|
|
560
633
|
}
|
|
561
634
|
|
|
562
|
-
exports.Settings = Settings
|
|
635
|
+
exports.Settings = Settings;
|
|
@@ -3,7 +3,7 @@ chui_settings {
|
|
|
3
3
|
display: block;
|
|
4
4
|
width: -webkit-fill-available;
|
|
5
5
|
box-sizing: border-box;
|
|
6
|
-
margin: var(--
|
|
6
|
+
margin: var(--block_margin);
|
|
7
7
|
color: var(--text_color);
|
|
8
8
|
font-size: var(--font_default_size);
|
|
9
9
|
}
|
|
@@ -28,14 +28,14 @@ settings_section {
|
|
|
28
28
|
display: block;
|
|
29
29
|
margin-bottom: 12px;
|
|
30
30
|
border: 1px solid var(--border_color);
|
|
31
|
-
border-radius: var(--
|
|
31
|
+
border-radius: var(--radius_sm);
|
|
32
32
|
background: var(--element_background_2);
|
|
33
33
|
overflow: hidden;
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
settings_section_head {
|
|
37
37
|
display: block;
|
|
38
|
-
padding: var(--
|
|
38
|
+
padding: var(--block_padding);
|
|
39
39
|
border-bottom: 1px solid var(--border_color);
|
|
40
40
|
}
|
|
41
41
|
|
|
@@ -60,7 +60,7 @@ settings_row {
|
|
|
60
60
|
align-items: center;
|
|
61
61
|
justify-content: space-between;
|
|
62
62
|
gap: 16px;
|
|
63
|
-
padding: var(--
|
|
63
|
+
padding: var(--block_padding);
|
|
64
64
|
}
|
|
65
65
|
|
|
66
66
|
/* Разделитель только между строками: у первой он уже есть в шапке раздела */
|