chuijs 4.0.3 → 4.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +536 -0
- package/framework/appLayout/default/chui_app_layout.js +361 -303
- package/framework/appLayout/default/global_style.css +243 -89
- package/framework/appLayout/default/main_theme_style.css +188 -101
- package/framework/components/chui_accordion/accordion.js +17 -17
- package/framework/components/chui_accordion/styles.css +7 -7
- package/framework/components/chui_action_sheet/action_sheet.js +35 -32
- package/framework/components/chui_action_sheet/styles.css +10 -4
- package/framework/components/chui_actions_bar/actions_bar.js +338 -0
- package/framework/components/chui_actions_bar/styles.css +139 -0
- package/framework/components/chui_affix/affix.js +4 -4
- package/framework/components/chui_affix/styles.css +5 -0
- package/framework/components/chui_alert/alert.js +11 -5
- package/framework/components/chui_alert/styles.css +7 -0
- package/framework/components/chui_avatar/avatar.js +13 -13
- package/framework/components/chui_avatar/styles.css +1 -1
- package/framework/components/chui_avatar_group/avatar_group.js +4 -4
- package/framework/components/chui_avatar_group/styles.css +1 -1
- package/framework/components/chui_backtop/backtop.js +25 -2
- package/framework/components/chui_backtop/styles.css +21 -0
- package/framework/components/chui_badge/badge.js +15 -15
- package/framework/components/chui_badge/styles.css +6 -6
- package/framework/components/chui_banner/banner.js +222 -0
- package/framework/components/chui_banner/styles.css +170 -0
- package/framework/components/chui_breadcrumb/styles.css +1 -1
- package/framework/components/chui_button/button.js +24 -28
- package/framework/components/chui_button/styles.css +5 -5
- package/framework/components/chui_calendar/calendar.js +6 -6
- package/framework/components/chui_card/card.js +14 -14
- package/framework/components/chui_card_scroll/card_scroll.js +169 -0
- package/framework/components/chui_card_scroll/styles.css +86 -0
- package/framework/components/chui_chat/chat.js +73 -51
- package/framework/components/chui_chat/styles.css +18 -7
- package/framework/components/chui_clipboard_history/clipboard_history.js +25 -20
- package/framework/components/chui_clipboard_history/styles.css +10 -8
- package/framework/components/chui_code/code.js +8 -8
- package/framework/components/chui_code/styles.css +2 -2
- package/framework/components/chui_code_editor/code_editor.js +26 -26
- package/framework/components/chui_code_editor/styles.css +3 -3
- package/framework/components/chui_command_palette/command_palette.js +29 -29
- package/framework/components/chui_command_palette/styles.css +5 -5
- package/framework/components/chui_console/console.js +9 -9
- package/framework/components/chui_console/styles.css +5 -2
- package/framework/components/chui_content_block/content_block.js +2 -2
- package/framework/components/chui_context_menu/context_menu.js +162 -54
- package/framework/components/chui_context_menu/styles.css +82 -8
- package/framework/components/chui_custom_element/custom_element.js +11 -11
- package/framework/components/chui_data_grid/data_grid.js +268 -268
- package/framework/components/chui_data_grid/styles.css +14 -14
- package/framework/components/chui_descriptions/styles.css +1 -1
- package/framework/components/chui_details/details.js +12 -12
- package/framework/components/chui_details/styles.css +7 -7
- package/framework/components/chui_diff_viewer/diff_viewer.js +88 -88
- package/framework/components/chui_diff_viewer/styles.css +9 -9
- package/framework/components/chui_divider/divider.js +6 -6
- package/framework/components/chui_divider/styles.css +2 -2
- package/framework/components/chui_drawer/drawer.js +37 -14
- package/framework/components/chui_drawer/styles.css +18 -4
- package/framework/components/chui_drop_zone/drop_zone.js +6 -6
- package/framework/components/chui_drop_zone/styles.css +10 -6
- package/framework/components/chui_fieldset/fieldset.js +6 -6
- package/framework/components/chui_fieldset/styles.css +5 -5
- package/framework/components/chui_file_explorer/file_explorer.js +115 -115
- package/framework/components/chui_file_explorer/styles.css +6 -6
- package/framework/components/chui_form/form.js +11 -11
- package/framework/components/chui_gantt/gantt.js +41 -41
- package/framework/components/chui_gantt/styles.css +5 -5
- package/framework/components/chui_graphs/graphs.js +82 -46
- package/framework/components/chui_graphs/styles.css +26 -5
- package/framework/components/chui_hero/hero.js +63 -20
- package/framework/components/chui_hero/styles.css +176 -7
- package/framework/components/chui_html_block/html_block.js +5 -5
- package/framework/components/chui_html_block/styles.css +1 -1
- package/framework/components/chui_hx/styles.css +2 -2
- package/framework/components/chui_icons/icons.js +7 -7
- package/framework/components/chui_icons/styles.css +2 -1
- package/framework/components/chui_inputs/chui_check_box/styles.css +12 -3
- package/framework/components/chui_inputs/chui_chips/chips.js +92 -31
- package/framework/components/chui_inputs/chui_chips/styles.css +28 -5
- package/framework/components/chui_inputs/chui_color_picker/color_picker.js +20 -15
- package/framework/components/chui_inputs/chui_color_picker/styles.css +7 -7
- package/framework/components/chui_inputs/chui_combo_box/combo_box.js +58 -58
- package/framework/components/chui_inputs/chui_combo_box/styles.css +9 -9
- package/framework/components/chui_inputs/chui_date/date.js +93 -95
- package/framework/components/chui_inputs/chui_date/styles.css +8 -8
- package/framework/components/chui_inputs/chui_date_range/date_range.js +22 -22
- package/framework/components/chui_inputs/chui_date_range/styles.css +3 -3
- package/framework/components/chui_inputs/chui_datetime/datetime.js +12 -12
- package/framework/components/chui_inputs/chui_datetime/styles.css +3 -3
- package/framework/components/chui_inputs/chui_email/email.js +10 -10
- package/framework/components/chui_inputs/chui_email/styles.css +6 -6
- package/framework/components/chui_inputs/chui_file/file.js +8 -8
- package/framework/components/chui_inputs/chui_file/styles.css +12 -9
- package/framework/components/chui_inputs/chui_hotkey/hotkey.js +39 -39
- package/framework/components/chui_inputs/chui_hotkey/styles.css +6 -6
- package/framework/components/chui_inputs/chui_masked/masked.js +44 -44
- package/framework/components/chui_inputs/chui_masked/styles.css +5 -5
- package/framework/components/chui_inputs/chui_mention/mention.js +13 -13
- package/framework/components/chui_inputs/chui_mention/styles.css +14 -8
- package/framework/components/chui_inputs/chui_multi_combo_box/multi_combo_box.js +147 -137
- package/framework/components/chui_inputs/chui_multi_combo_box/styles.css +14 -8
- package/framework/components/chui_inputs/chui_number/number.js +42 -45
- package/framework/components/chui_inputs/chui_number/styles.css +6 -6
- package/framework/components/chui_inputs/chui_otp/otp.js +32 -32
- package/framework/components/chui_inputs/chui_otp/styles.css +5 -5
- package/framework/components/chui_inputs/chui_password/password.js +30 -36
- package/framework/components/chui_inputs/chui_password/styles.css +7 -7
- package/framework/components/chui_inputs/chui_radio_button/styles.css +2 -2
- package/framework/components/chui_inputs/chui_rating/rating.js +28 -28
- package/framework/components/chui_inputs/chui_rating/styles.css +3 -3
- package/framework/components/chui_inputs/chui_select_box/select_box.js +54 -54
- package/framework/components/chui_inputs/chui_select_box/styles.css +10 -10
- package/framework/components/chui_inputs/chui_slider/slider.js +14 -14
- package/framework/components/chui_inputs/chui_slider/styles.css +5 -4
- package/framework/components/chui_inputs/chui_text/styles.css +7 -7
- package/framework/components/chui_inputs/chui_text/text.js +13 -17
- package/framework/components/chui_inputs/chui_text_area/styles.css +8 -8
- package/framework/components/chui_inputs/chui_text_area/text_area.js +23 -23
- package/framework/components/chui_inputs/chui_time/styles.css +13 -17
- package/framework/components/chui_inputs/chui_time/time.js +35 -24
- package/framework/components/chui_inputs/chui_toggle/styles.css +10 -3
- package/framework/components/chui_inputs/chui_toggle/toggle.js +16 -16
- package/framework/components/chui_json_editor/json_editor.js +87 -87
- package/framework/components/chui_json_editor/styles.css +5 -5
- package/framework/components/chui_json_viewer/json_viewer.js +80 -80
- package/framework/components/chui_json_viewer/styles.css +6 -6
- package/framework/components/chui_kanban/kanban.js +27 -27
- package/framework/components/chui_kanban/styles.css +8 -4
- package/framework/components/chui_kbd/styles.css +1 -1
- package/framework/components/chui_label/label.js +17 -17
- package/framework/components/chui_label/styles.css +1 -1
- package/framework/components/chui_link/link.js +9 -9
- package/framework/components/chui_link/styles.css +11 -4
- package/framework/components/chui_list/list.js +11 -11
- package/framework/components/chui_list/styles.css +2 -2
- package/framework/components/chui_markdown_editor/markdown_editor.js +66 -66
- package/framework/components/chui_markdown_editor/styles.css +5 -5
- package/framework/components/chui_media/audio.js +240 -246
- package/framework/components/chui_media/audio_styles.css +41 -23
- package/framework/components/chui_media/image.js +49 -46
- package/framework/components/chui_media/image_compare.js +35 -35
- package/framework/components/chui_media/image_compare_styles.css +5 -5
- package/framework/components/chui_media/image_styles.css +1 -1
- package/framework/components/chui_media/video.js +148 -148
- package/framework/components/chui_media/video_styles.css +27 -11
- package/framework/components/chui_menu_bar/menu_bar.js +54 -54
- package/framework/components/chui_menu_bar/styles.css +10 -10
- package/framework/components/chui_message_bar/message_bar.js +551 -0
- package/framework/components/chui_message_bar/styles.css +248 -0
- package/framework/components/chui_modal/modal.js +37 -13
- package/framework/components/chui_notification/notification.js +76 -54
- package/framework/components/chui_notification/notification_download.js +26 -81
- package/framework/components/chui_notification/notification_download_card.js +115 -0
- package/framework/components/chui_notification/notification_download_progress.css +2 -2
- package/framework/components/chui_notification/notification_download_progress.js +70 -108
- package/framework/components/chui_notification/notification_update.js +31 -31
- package/framework/components/chui_notification/status_plate.css +3 -3
- package/framework/components/chui_notification/styles.css +6 -1
- package/framework/components/chui_notification/styles_download.css +1 -1
- package/framework/components/chui_notification/styles_update.css +2 -2
- package/framework/components/chui_org_chart/org_chart.js +29 -29
- package/framework/components/chui_org_chart/styles.css +2 -2
- package/framework/components/chui_pagination/pagination.js +3 -3
- package/framework/components/chui_pagination/styles.css +1 -1
- package/framework/components/chui_paragraph/styles.css +2 -2
- package/framework/components/chui_popover/popover.js +29 -23
- package/framework/components/chui_popover/styles.css +1 -1
- package/framework/components/chui_popups/popups.js +124 -124
- package/framework/components/chui_popups/styles.css +5 -5
- package/framework/components/chui_print_button/print_button.js +15 -10
- package/framework/components/chui_progress_bar/progress_bar.js +34 -12
- package/framework/components/chui_progress_bar/styles.css +4 -4
- package/framework/components/chui_progress_ring/progress_ring.js +15 -15
- package/framework/components/chui_progress_ring/styles.css +1 -1
- package/framework/components/chui_qrcode/qrcode.js +12 -12
- package/framework/components/chui_query_builder/query_builder.js +46 -46
- package/framework/components/chui_query_builder/styles.css +4 -4
- package/framework/components/chui_radio_group/styles.css +1 -1
- package/framework/components/chui_result/result.js +15 -15
- package/framework/components/chui_result/styles.css +3 -3
- package/framework/components/chui_scheduler/scheduler.js +74 -74
- package/framework/components/chui_scheduler/styles.css +5 -5
- package/framework/components/chui_screen_spinner/screen_spinner.js +167 -0
- package/framework/components/chui_screen_spinner/styles.css +49 -0
- package/framework/components/chui_segmented_control/segmented_control.js +63 -6
- package/framework/components/chui_segmented_control/styles.css +32 -6
- package/framework/components/chui_settings/settings.js +45 -46
- package/framework/components/chui_settings/styles.css +4 -4
- package/framework/components/chui_shortcut_help/shortcut_help.js +32 -34
- package/framework/components/chui_sidebar_nav/sidebar_nav.js +98 -29
- package/framework/components/chui_sidebar_nav/styles.css +9 -3
- package/framework/components/chui_slideshow/slideshow.js +85 -85
- package/framework/components/chui_slideshow/styles.css +6 -6
- package/framework/components/chui_spinner/spinner.js +10 -10
- package/framework/components/chui_split_button/split_button.js +30 -12
- package/framework/components/chui_split_button/styles.css +21 -5
- package/framework/components/chui_splitter/splitter.js +11 -11
- package/framework/components/chui_splitter/styles.css +2 -2
- package/framework/components/chui_statistic/statistic.js +47 -47
- package/framework/components/chui_status_bar/styles.css +2 -2
- package/framework/components/chui_stepper/stepper.js +202 -31
- package/framework/components/chui_stepper/styles.css +79 -14
- package/framework/components/chui_sticky_bar/sticky_bar.js +44 -13
- package/framework/components/chui_sticky_bar/styles.css +10 -8
- package/framework/components/chui_tabs/chui_tabs.js +74 -26
- package/framework/components/chui_tabs/styles.css +40 -12
- package/framework/components/chui_text_editor/styles.css +7 -7
- package/framework/components/chui_text_editor/text_editor.js +56 -56
- package/framework/components/chui_text_editor/text_editor_panel.js +173 -174
- package/framework/components/chui_theme_toggle/theme_toggle.js +21 -5
- package/framework/components/chui_timeline/styles.css +3 -1
- package/framework/components/chui_toast_queue/styles.css +11 -11
- package/framework/components/chui_toast_queue/toast_queue.js +30 -27
- package/framework/components/chui_toolbar/styles.css +2 -2
- package/framework/components/chui_tooltip/styles.css +2 -2
- package/framework/components/chui_tooltip/tooltip.js +3 -3
- package/framework/components/chui_tour/styles.css +8 -8
- package/framework/components/chui_tour/tour.js +72 -72
- package/framework/components/chui_transfer/styles.css +6 -6
- package/framework/components/chui_transfer/transfer.js +93 -106
- package/framework/components/chui_tree_table/styles.css +4 -4
- package/framework/components/chui_tree_table/tree_table.js +45 -45
- package/framework/components/chui_tree_view/styles.css +10 -8
- package/framework/components/chui_tree_view/tree_view.js +185 -183
- package/framework/components/chui_user_bar/styles.css +145 -0
- package/framework/components/chui_user_bar/user_bar.js +402 -0
- package/framework/components/chui_user_list_bar/styles.css +173 -0
- package/framework/components/chui_user_list_bar/user_list_bar.js +485 -0
- package/framework/components/chui_watermark/watermark.js +17 -17
- package/framework/components/chui_webview/webview.js +9 -9
- package/framework/components/chui_write_bar/styles.css +172 -0
- package/framework/components/chui_write_bar/write_bar.js +320 -0
- package/framework/main_window.js +1234 -0
- package/framework/modules/chui_a11y/chui_a11y.js +78 -79
- package/framework/modules/chui_animations/animations.js +77 -15
- package/framework/modules/chui_animations/motion.js +120 -0
- package/framework/modules/chui_animations/styles.css +36 -3
- package/framework/modules/chui_functions.js +31 -27
- package/framework/modules/chui_highlight/styles.css +13 -10
- package/framework/modules/chui_i18n/chui_i18n.js +3 -3
- package/framework/modules/chui_i18n/locales/feedback.js +62 -0
- package/framework/modules/chui_i18n/locales/navigation.js +4 -0
- package/framework/modules/chui_json/chui_json.js +2 -2
- package/framework/modules/chui_logger/chui_logger.js +23 -8
- package/framework/modules/chui_page/page.js +10 -10
- package/framework/modules/chui_palette/palette.js +61 -0
- package/framework/modules/chui_qr/chui_qr.js +23 -23
- package/framework/modules/chui_scrollbar/chui_scrollbar.js +45 -45
- package/framework/modules/chui_scrollbar/styles.css +3 -3
- package/framework/modules/chui_services/chui_services.js +8 -8
- package/framework/modules/chui_services/desktop.js +77 -71
- package/framework/modules/chui_sortable/chui_sortable.js +17 -17
- package/framework/modules/chui_validate/chui_validate.js +3 -3
- package/framework/tray_bar/chui_menu_items.js +2 -2
- package/index.d.ts +266 -34
- package/index.js +20 -1168
- package/package.json +6 -4
- package/framework/components/telegram_bot/chui_telegram_bot.js +0 -191
|
@@ -44,20 +44,20 @@ class Rating {
|
|
|
44
44
|
#title = document.createElement("rating_title");
|
|
45
45
|
#row = document.createElement("rating_row");
|
|
46
46
|
#track = document.createElement("rating_track");
|
|
47
|
-
#
|
|
47
|
+
#valueText = document.createElement("rating_value");
|
|
48
48
|
#id = undefined;
|
|
49
49
|
#name = undefined;
|
|
50
50
|
#label = undefined;
|
|
51
|
-
#
|
|
51
|
+
#titleText = undefined;
|
|
52
52
|
#max = 5;
|
|
53
53
|
#value = 0;
|
|
54
|
-
#
|
|
54
|
+
#readOnly = false;
|
|
55
55
|
#disabled = false;
|
|
56
56
|
#size = Rating.SIZE.DEFAULT;
|
|
57
57
|
#icon = Icons.TOGGLE.STAR;
|
|
58
|
-
#
|
|
58
|
+
#iconEmpty = Icons.TOGGLE.STAR_BORDER;
|
|
59
59
|
#listeners = [];
|
|
60
|
-
#
|
|
60
|
+
#onChange = undefined;
|
|
61
61
|
#dragging = false;
|
|
62
62
|
#moved = false;
|
|
63
63
|
|
|
@@ -85,14 +85,14 @@ class Rating {
|
|
|
85
85
|
this.#name = options.name;
|
|
86
86
|
this.#label = options.label;
|
|
87
87
|
if (options.icon !== undefined) this.#icon = options.icon;
|
|
88
|
-
if (options.iconEmpty !== undefined) this.#
|
|
88
|
+
if (options.iconEmpty !== undefined) this.#iconEmpty = options.iconEmpty;
|
|
89
89
|
this.#max = Rating.#maxCount(options.max);
|
|
90
|
-
this.#
|
|
90
|
+
this.#onChange = options.onChange;
|
|
91
91
|
if (options.changeListener !== undefined) this.addChangeListener(options.changeListener);
|
|
92
92
|
this.#row.className = "rating_row";
|
|
93
|
-
this.#
|
|
93
|
+
this.#valueText.className = "rating_value";
|
|
94
94
|
// Текст значения дублирует aria-valuetext, поэтому от скринридера он скрыт
|
|
95
|
-
this.#
|
|
95
|
+
this.#valueText.setAttribute("aria-hidden", "true");
|
|
96
96
|
this.#track.className = "rating_track";
|
|
97
97
|
this.#track.addEventListener("keydown", this.#onKeyDown);
|
|
98
98
|
this.#track.addEventListener("pointerdown", this.#onPointerDown);
|
|
@@ -100,7 +100,7 @@ class Rating {
|
|
|
100
100
|
this.#track.addEventListener("pointerup", this.#onPointerUp);
|
|
101
101
|
this.#track.addEventListener("pointercancel", this.#onPointerUp);
|
|
102
102
|
this.#row.appendChild(this.#track);
|
|
103
|
-
this.#row.appendChild(this.#
|
|
103
|
+
this.#row.appendChild(this.#valueText);
|
|
104
104
|
this.#root.appendChild(this.#title);
|
|
105
105
|
this.#root.appendChild(this.#row);
|
|
106
106
|
if (options.title !== undefined) this.setTitle(options.title);
|
|
@@ -109,15 +109,15 @@ class Rating {
|
|
|
109
109
|
// Валидация: пустая оценка — это 0, поэтому required означает «оценку поставили»
|
|
110
110
|
Validate.installField(this, options, this.#root, undefined, () => this.#rawValue(), this.#row);
|
|
111
111
|
// Поле — не нативный контрол: aria-invalid ставится своему узлу, а не input
|
|
112
|
-
const
|
|
112
|
+
const baseSetError = this.setError;
|
|
113
113
|
this.setError = (message = String()) => {
|
|
114
|
-
|
|
114
|
+
baseSetError(message);
|
|
115
115
|
this.#track.setAttribute("aria-invalid", "true");
|
|
116
116
|
return this;
|
|
117
117
|
};
|
|
118
|
-
const
|
|
118
|
+
const baseClearError = this.clearError;
|
|
119
119
|
this.clearError = () => {
|
|
120
|
-
|
|
120
|
+
baseClearError();
|
|
121
121
|
this.#track.removeAttribute("aria-invalid");
|
|
122
122
|
return this;
|
|
123
123
|
};
|
|
@@ -137,7 +137,7 @@ class Rating {
|
|
|
137
137
|
}
|
|
138
138
|
|
|
139
139
|
getTitle() {
|
|
140
|
-
return this.#
|
|
140
|
+
return this.#titleText;
|
|
141
141
|
}
|
|
142
142
|
|
|
143
143
|
/** Оценка (0 — не поставлена) */
|
|
@@ -162,7 +162,7 @@ class Rating {
|
|
|
162
162
|
}
|
|
163
163
|
|
|
164
164
|
isReadOnly() {
|
|
165
|
-
return this.#
|
|
165
|
+
return this.#readOnly;
|
|
166
166
|
}
|
|
167
167
|
|
|
168
168
|
// SET
|
|
@@ -179,7 +179,7 @@ class Rating {
|
|
|
179
179
|
|
|
180
180
|
/** Подпись над звёздами; `setTitle(undefined)` её убирает */
|
|
181
181
|
setTitle(text = undefined) {
|
|
182
|
-
this.#
|
|
182
|
+
this.#titleText = text;
|
|
183
183
|
if (text === undefined || text === "") {
|
|
184
184
|
this.#title.hidden = true;
|
|
185
185
|
this.#title.innerText = "";
|
|
@@ -225,9 +225,9 @@ class Rating {
|
|
|
225
225
|
}
|
|
226
226
|
|
|
227
227
|
/** Режим показа: звёзды видны, но не принимают фокус и клики */
|
|
228
|
-
setReadOnly(
|
|
229
|
-
this.#
|
|
230
|
-
this.#root.classList.toggle("rating_readonly", this.#
|
|
228
|
+
setReadOnly(readOnly = Boolean()) {
|
|
229
|
+
this.#readOnly = readOnly === true;
|
|
230
|
+
this.#root.classList.toggle("rating_readonly", this.#readOnly);
|
|
231
231
|
this.#render();
|
|
232
232
|
return this;
|
|
233
233
|
}
|
|
@@ -248,7 +248,7 @@ class Rating {
|
|
|
248
248
|
|
|
249
249
|
/** Фокус на поле: `Form` зовёт это при ошибке валидации */
|
|
250
250
|
focus() {
|
|
251
|
-
if (!this.#
|
|
251
|
+
if (!this.#readOnly && !this.#disabled) this.#track.focus();
|
|
252
252
|
return this;
|
|
253
253
|
}
|
|
254
254
|
|
|
@@ -265,14 +265,14 @@ class Rating {
|
|
|
265
265
|
|
|
266
266
|
#accessibleName() {
|
|
267
267
|
if (this.#label !== undefined && this.#label !== "") return this.#label;
|
|
268
|
-
if (this.#
|
|
268
|
+
if (this.#titleText !== undefined && this.#titleText !== "") return this.#titleText;
|
|
269
269
|
return I18n.t("forms.ratingLabel");
|
|
270
270
|
}
|
|
271
271
|
|
|
272
272
|
#render() {
|
|
273
273
|
// Режим показа: не поле, а картинка с готовым значением
|
|
274
274
|
this.#track.innerHTML = "";
|
|
275
|
-
if (this.#
|
|
275
|
+
if (this.#readOnly) {
|
|
276
276
|
this.#track.removeAttribute("tabindex");
|
|
277
277
|
this.#track.removeAttribute("aria-valuemin");
|
|
278
278
|
this.#track.removeAttribute("aria-valuemax");
|
|
@@ -295,12 +295,12 @@ class Rating {
|
|
|
295
295
|
for (let index = 1; index <= this.#max; index++) {
|
|
296
296
|
const star = document.createElement("rating_star");
|
|
297
297
|
star.className = index <= this.#value ? "rating_star rating_star_filled" : "rating_star";
|
|
298
|
-
const glyph = new Icon(index <= this.#value ? this.#icon : this.#
|
|
298
|
+
const glyph = new Icon(index <= this.#value ? this.#icon : this.#iconEmpty, this.#iconSize()).set();
|
|
299
299
|
glyph.setAttribute("aria-hidden", "true");
|
|
300
300
|
star.appendChild(glyph);
|
|
301
301
|
this.#track.appendChild(star);
|
|
302
302
|
}
|
|
303
|
-
this.#
|
|
303
|
+
this.#valueText.innerText = this.getValueText();
|
|
304
304
|
}
|
|
305
305
|
|
|
306
306
|
#iconSize() {
|
|
@@ -316,11 +316,11 @@ class Rating {
|
|
|
316
316
|
|
|
317
317
|
#notify() {
|
|
318
318
|
for (const listener of [...this.#listeners]) listener(this.#value, this);
|
|
319
|
-
if (this.#
|
|
319
|
+
if (this.#onChange !== undefined) this.#onChange(this.#value, this);
|
|
320
320
|
}
|
|
321
321
|
|
|
322
322
|
#onKeyDown = (event) => {
|
|
323
|
-
if (this.#disabled || this.#
|
|
323
|
+
if (this.#disabled || this.#readOnly) return;
|
|
324
324
|
let next = this.#value;
|
|
325
325
|
switch (event.key) {
|
|
326
326
|
case "ArrowRight":
|
|
@@ -358,7 +358,7 @@ class Rating {
|
|
|
358
358
|
};
|
|
359
359
|
|
|
360
360
|
#onPointerDown = (event) => {
|
|
361
|
-
if (this.#disabled || this.#
|
|
361
|
+
if (this.#disabled || this.#readOnly) return;
|
|
362
362
|
event.preventDefault();
|
|
363
363
|
this.#dragging = true;
|
|
364
364
|
this.#moved = false;
|
|
@@ -5,10 +5,10 @@ chui_rating {
|
|
|
5
5
|
карточку. Токены переопределены у корня поля, поэтому действуют только внутри него
|
|
6
6
|
(тот же приём у полосы меню-бара). */
|
|
7
7
|
--control_padding: var(--control_padding_sm);
|
|
8
|
-
--
|
|
8
|
+
--block_padding: var(--block_padding_sm);
|
|
9
9
|
display: block;
|
|
10
10
|
width: -webkit-fill-available;
|
|
11
|
-
margin: var(--
|
|
11
|
+
margin: var(--block_margin);
|
|
12
12
|
color: var(--text_color);
|
|
13
13
|
font-size: var(--font_default_size);
|
|
14
14
|
}
|
|
@@ -16,7 +16,7 @@ chui_rating {
|
|
|
16
16
|
rating_title {
|
|
17
17
|
display: block;
|
|
18
18
|
width: max-content;
|
|
19
|
-
margin: 0 0 var(--
|
|
19
|
+
margin: 0 0 var(--block_margin);
|
|
20
20
|
color: var(--text_color);
|
|
21
21
|
font-size: var(--font_labels_size);
|
|
22
22
|
font-weight: 500;
|
|
@@ -7,16 +7,16 @@ const { Validate } = require("../../../modules/chui_validate/chui_validate");
|
|
|
7
7
|
|
|
8
8
|
class Select {
|
|
9
9
|
#id = require("randomstring").generate();
|
|
10
|
-
#
|
|
11
|
-
#
|
|
12
|
-
#
|
|
10
|
+
#idSb = require("randomstring").generate();
|
|
11
|
+
#SelectMain = document.createElement("chui_selectbox");
|
|
12
|
+
#SelectSecond = document.createElement("selectbox");
|
|
13
13
|
#label = document.createElement("label");
|
|
14
14
|
#input = document.createElement("input");
|
|
15
|
-
#
|
|
16
|
-
#
|
|
17
|
-
#
|
|
15
|
+
#buttonOpen = document.createElement("select_button_open");
|
|
16
|
+
#buttonOpenDisabled = document.createElement("select_button_open");
|
|
17
|
+
#disabledTrigger = false;
|
|
18
18
|
// Признак «вариант только что выбран мышью» — см. обработчик клика по полю
|
|
19
|
-
#
|
|
19
|
+
#chosenByMouse = false;
|
|
20
20
|
#dropdown = document.createElement("selectbox_dropdown");
|
|
21
21
|
#a11y = undefined;
|
|
22
22
|
// Слушатель окна храним полем, чтобы можно было снять в destroy()
|
|
@@ -24,8 +24,8 @@ class Select {
|
|
|
24
24
|
// `selectbox`: слой списка накрывает своё же поле, поэтому у настоящего щелчка по полю
|
|
25
25
|
// цель `mouseup` — слой, а `click` схлопывается до `<selectbox>` и прежняя проверка
|
|
26
26
|
// «цель — не ребёнок selectbox» принимала его за клик снаружи (список закрывался сразу)
|
|
27
|
-
#
|
|
28
|
-
if (!this.#
|
|
27
|
+
#windowClickEvent = (event) => {
|
|
28
|
+
if (!this.#SelectMain.contains(event.target)) this.#closeDropdown();
|
|
29
29
|
};
|
|
30
30
|
constructor(
|
|
31
31
|
options = {
|
|
@@ -37,51 +37,51 @@ class Select {
|
|
|
37
37
|
}
|
|
38
38
|
) {
|
|
39
39
|
require("../../../modules/chui_functions").setStyles(__dirname + "/styles.css", "chUiJS_Select");
|
|
40
|
-
if (options.width !== undefined) this.#
|
|
40
|
+
if (options.width !== undefined) this.#SelectMain.style.width = options.width;
|
|
41
41
|
if (options.placeholder !== undefined) this.#input.placeholder = options.placeholder;
|
|
42
42
|
if (options.title !== undefined) {
|
|
43
43
|
this.#label.classList.add("select_label");
|
|
44
44
|
this.#label.innerText = options.title;
|
|
45
|
-
this.#label.setAttribute("for", this.#
|
|
46
|
-
this.#
|
|
45
|
+
this.#label.setAttribute("for", this.#idSb);
|
|
46
|
+
this.#SelectMain.appendChild(this.#label);
|
|
47
47
|
}
|
|
48
48
|
if (options.required !== undefined) this.#input.required = options.required;
|
|
49
49
|
// Валидация: для списка required означает «есть выбранный вариант»
|
|
50
|
-
Validate.installField(this, options, this.#
|
|
51
|
-
this.#input.setAttribute("id", this.#
|
|
50
|
+
Validate.installField(this, options, this.#SelectSecond, undefined, () => this.getValue());
|
|
51
|
+
this.#input.setAttribute("id", this.#idSb);
|
|
52
52
|
this.#input.classList.add("selectbox_input");
|
|
53
53
|
this.#input.type = "text";
|
|
54
54
|
if (options.name !== undefined) this.#input.name = options.name;
|
|
55
55
|
this.#input.readOnly = true;
|
|
56
|
-
this.#
|
|
56
|
+
this.#buttonOpen.innerHTML = new Icon(
|
|
57
57
|
Icons.HARDWARE.KEYBOARD_ARROW_DOWN,
|
|
58
58
|
undefined,
|
|
59
59
|
"var(--blue_prime_background)"
|
|
60
60
|
).getHTML();
|
|
61
|
-
this.#
|
|
61
|
+
this.#buttonOpenDisabled.innerHTML = new Icon(
|
|
62
62
|
Icons.HARDWARE.KEYBOARD_ARROW_DOWN,
|
|
63
63
|
undefined,
|
|
64
64
|
"var(--text_color_disabled)"
|
|
65
65
|
).getHTML();
|
|
66
66
|
// Курсор выключенного поля даёт `.selectbox_disabled`: `cursor` наследуется
|
|
67
67
|
this.#dropdown.setAttribute("id", this.#id);
|
|
68
|
-
this.#
|
|
69
|
-
this.#
|
|
70
|
-
this.#
|
|
68
|
+
this.#SelectSecond.appendChild(this.#input);
|
|
69
|
+
this.#SelectSecond.appendChild(this.#buttonOpen);
|
|
70
|
+
this.#SelectSecond.appendChild(this.#dropdown);
|
|
71
71
|
//LISTENERS
|
|
72
72
|
this.#input.addEventListener("focus", () => this.#openDropdown());
|
|
73
73
|
this.#input.addEventListener("blur", () => this.#closeDropdown());
|
|
74
|
-
this.#
|
|
74
|
+
this.#SelectSecond.addEventListener("click", (event) => {
|
|
75
75
|
// Клик по полю или стрелке открывает список сам. Одного `focus` мало:
|
|
76
76
|
// если фокус уже в поле (повторный клик, диалог поставил фокус первым),
|
|
77
77
|
// событие `focus` не придёт и список не раскроется
|
|
78
78
|
const target = event.target;
|
|
79
79
|
if (!(target instanceof Element)) return;
|
|
80
|
-
if (target !== this.#input && !this.#
|
|
80
|
+
if (target !== this.#input && !this.#buttonOpen.contains(target)) return;
|
|
81
81
|
// Выбор варианта мышью закрывает список на `mousedown` варианта, а `mouseup`
|
|
82
82
|
// приходит уже по полю — без этой проверки щелчок по варианту раскрывал список заново
|
|
83
|
-
if (this.#
|
|
84
|
-
this.#
|
|
83
|
+
if (this.#chosenByMouse) {
|
|
84
|
+
this.#chosenByMouse = false;
|
|
85
85
|
return;
|
|
86
86
|
}
|
|
87
87
|
this.#input.focus();
|
|
@@ -90,10 +90,10 @@ class Select {
|
|
|
90
90
|
// Слой списка не забирает фокус: клик по его отступу не должен закрывать список
|
|
91
91
|
// (иначе поле теряло бы фокус на пустом месте слоя)
|
|
92
92
|
this.#dropdown.addEventListener("mousedown", (event) => event.preventDefault());
|
|
93
|
-
window.addEventListener("click", this.#
|
|
93
|
+
window.addEventListener("click", this.#windowClickEvent);
|
|
94
94
|
this.#input.addEventListener("input", (event) => {
|
|
95
|
-
|
|
96
|
-
for (
|
|
95
|
+
const dropdown = this.#dropdown;
|
|
96
|
+
for (const option of dropdown.childNodes) {
|
|
97
97
|
if (!option.getAttribute("option_value").includes(event.target.value)) {
|
|
98
98
|
option.style.display = "none";
|
|
99
99
|
} else {
|
|
@@ -102,7 +102,7 @@ class Select {
|
|
|
102
102
|
}
|
|
103
103
|
this.#a11y.refresh();
|
|
104
104
|
});
|
|
105
|
-
this.#
|
|
105
|
+
this.#SelectMain.appendChild(this.#SelectSecond);
|
|
106
106
|
// Клавиатура и aria: фокус в поле, стрелки/Home/End/Enter по опциям, Escape закрывает
|
|
107
107
|
this.#a11y = new ComboboxKeyboard(this.#input, {
|
|
108
108
|
dropdown: this.#dropdown,
|
|
@@ -112,9 +112,9 @@ class Select {
|
|
|
112
112
|
});
|
|
113
113
|
}
|
|
114
114
|
#openDropdown() {
|
|
115
|
-
if (this.#
|
|
115
|
+
if (this.#disabledTrigger) return;
|
|
116
116
|
this.#setOpenState(true);
|
|
117
|
-
new Animation(this.#dropdown).
|
|
117
|
+
new Animation(this.#dropdown).panelIn();
|
|
118
118
|
setOptionDisplay(this.#dropdown);
|
|
119
119
|
this.#setDropdownDirection();
|
|
120
120
|
this.#a11y.setExpanded(true);
|
|
@@ -126,7 +126,7 @@ class Select {
|
|
|
126
126
|
}
|
|
127
127
|
/** Полное удаление: снять слушатели окна и клавиатурный слой */
|
|
128
128
|
destroy() {
|
|
129
|
-
window.removeEventListener("click", this.#
|
|
129
|
+
window.removeEventListener("click", this.#windowClickEvent);
|
|
130
130
|
this.#a11y.destroy();
|
|
131
131
|
this.#closeDropdown();
|
|
132
132
|
}
|
|
@@ -138,7 +138,7 @@ class Select {
|
|
|
138
138
|
|
|
139
139
|
/** Значение выбранной опции; пустая строка — опция не выбрана */
|
|
140
140
|
getSelectedValue() {
|
|
141
|
-
const value = this.#
|
|
141
|
+
const value = this.#SelectMain.getAttribute("option_value");
|
|
142
142
|
return value === null ? "" : value;
|
|
143
143
|
}
|
|
144
144
|
|
|
@@ -168,8 +168,8 @@ class Select {
|
|
|
168
168
|
clear() {
|
|
169
169
|
this.#closeDropdown();
|
|
170
170
|
this.#input.value = "";
|
|
171
|
-
this.#
|
|
172
|
-
this.#
|
|
171
|
+
this.#SelectMain.removeAttribute("option_title");
|
|
172
|
+
this.#SelectMain.removeAttribute("option_value");
|
|
173
173
|
this.#markSelected(undefined);
|
|
174
174
|
return this;
|
|
175
175
|
}
|
|
@@ -200,14 +200,14 @@ class Select {
|
|
|
200
200
|
const title = option.getAttribute("option_title");
|
|
201
201
|
const value = option.getAttribute("option_value");
|
|
202
202
|
this.#input.value = title;
|
|
203
|
-
this.#
|
|
204
|
-
this.#
|
|
203
|
+
this.#SelectMain.setAttribute("option_title", title);
|
|
204
|
+
this.#SelectMain.setAttribute("option_value", value);
|
|
205
205
|
this.#markSelected(option);
|
|
206
206
|
if (silent) return;
|
|
207
207
|
// Выбор варианта закрывает список: клику по опции это уже не поручить —
|
|
208
208
|
// click схлопывается до общего предка (mousedown был в поле, mouseup — в слое)
|
|
209
209
|
this.#closeDropdown();
|
|
210
|
-
this.#
|
|
210
|
+
this.#SelectMain.dispatchEvent(
|
|
211
211
|
new CustomEvent("chui_select_option_changed", {
|
|
212
212
|
detail: {
|
|
213
213
|
title: title,
|
|
@@ -226,7 +226,7 @@ class Select {
|
|
|
226
226
|
option.addEventListener("mousedown", (event) => {
|
|
227
227
|
event.preventDefault();
|
|
228
228
|
// Признак «выбрано мышью»: гасит повторное раскрытие списка на `mouseup` по полю
|
|
229
|
-
this.#
|
|
229
|
+
this.#chosenByMouse = true;
|
|
230
230
|
this.#applyOption(option, false);
|
|
231
231
|
});
|
|
232
232
|
option.addEventListener("click", (event) => {
|
|
@@ -235,7 +235,7 @@ class Select {
|
|
|
235
235
|
});
|
|
236
236
|
}
|
|
237
237
|
addOption(title, value) {
|
|
238
|
-
|
|
238
|
+
const option = document.createElement(`selectbox_option`);
|
|
239
239
|
option.innerHTML = title;
|
|
240
240
|
option.setAttribute("option_title", title);
|
|
241
241
|
option.setAttribute("option_value", value);
|
|
@@ -244,8 +244,8 @@ class Select {
|
|
|
244
244
|
this.#a11y.refresh();
|
|
245
245
|
}
|
|
246
246
|
addOptions(...options) {
|
|
247
|
-
for (
|
|
248
|
-
|
|
247
|
+
for (const opt of options) {
|
|
248
|
+
const option = document.createElement(`selectbox_option`);
|
|
249
249
|
option.innerHTML = opt.title;
|
|
250
250
|
option.setAttribute("option_title", opt.title);
|
|
251
251
|
option.setAttribute("option_value", opt.value);
|
|
@@ -263,14 +263,14 @@ class Select {
|
|
|
263
263
|
*/
|
|
264
264
|
setDefaultOption(object = Object()) {
|
|
265
265
|
const wanted = object !== null && typeof object === "object" ? object.value : object;
|
|
266
|
-
|
|
266
|
+
const opt = this.#dropdown.getElementsByTagName("selectbox_option");
|
|
267
267
|
for (let i = 0; i < opt.length; i++) {
|
|
268
|
-
|
|
268
|
+
const test = opt.item(i);
|
|
269
269
|
if (test.getAttribute("option_value") === String(wanted)) test.click();
|
|
270
270
|
}
|
|
271
271
|
}
|
|
272
272
|
addValueChangeListener(listener = () => {}) {
|
|
273
|
-
this.#
|
|
273
|
+
this.#SelectMain.addEventListener("chui_select_option_changed", listener);
|
|
274
274
|
}
|
|
275
275
|
getName() {
|
|
276
276
|
return this.#input.name;
|
|
@@ -279,31 +279,31 @@ class Select {
|
|
|
279
279
|
return this.#input.value;
|
|
280
280
|
}
|
|
281
281
|
setDisabled(boolean = Boolean()) {
|
|
282
|
-
this.#
|
|
282
|
+
this.#disabledTrigger = boolean;
|
|
283
283
|
if (boolean) {
|
|
284
284
|
this.#setOpenState(false);
|
|
285
285
|
if (this.#a11y !== undefined) this.#a11y.setExpanded(false);
|
|
286
|
-
this.#
|
|
286
|
+
this.#SelectSecond.classList.add("selectbox_disabled");
|
|
287
287
|
this.#input.className = "selectbox_input_disabled";
|
|
288
288
|
this.#label.className = "select_label_disabled";
|
|
289
|
-
this.#
|
|
290
|
-
this.#
|
|
289
|
+
this.#buttonOpen.remove();
|
|
290
|
+
this.#SelectSecond.appendChild(this.#buttonOpenDisabled);
|
|
291
291
|
} else {
|
|
292
|
-
this.#
|
|
292
|
+
this.#SelectSecond.classList.remove("selectbox_disabled");
|
|
293
293
|
this.#input.className = "selectbox_input";
|
|
294
294
|
this.#label.className = "select_label";
|
|
295
|
-
this.#
|
|
296
|
-
this.#
|
|
295
|
+
this.#buttonOpenDisabled.remove();
|
|
296
|
+
this.#SelectSecond.appendChild(this.#buttonOpen);
|
|
297
297
|
}
|
|
298
298
|
}
|
|
299
299
|
#setOpenState(opened = Boolean()) {
|
|
300
300
|
// Рамку активного поля держит общее правило темы (`selectbox:focus-within`
|
|
301
301
|
// в global_style.css, вместе с кольцом), а не индайн компонента: индайновая рамка
|
|
302
302
|
// перебивала тему и мешала централизации состояний
|
|
303
|
-
this.#
|
|
303
|
+
this.#buttonOpen.style.transform = opened ? "rotate(180deg)" : "rotate(0deg)";
|
|
304
304
|
}
|
|
305
305
|
#setDropdownDirection() {
|
|
306
|
-
const placement = dropdownPlacement(this.#dropdown, this.#
|
|
306
|
+
const placement = dropdownPlacement(this.#dropdown, this.#SelectSecond);
|
|
307
307
|
// Зазор до поля держит CSS (`top: calc(100% + 4px)`), вверх — то же число через `bottom`:
|
|
308
308
|
// так список отстоит от поля на один зазор в обе стороны (вверх - `bottom`)
|
|
309
309
|
this.#dropdown.style.top = placement.up ? "auto" : "";
|
|
@@ -313,14 +313,14 @@ class Select {
|
|
|
313
313
|
else this.#dropdown.style.removeProperty("max-height");
|
|
314
314
|
}
|
|
315
315
|
set() {
|
|
316
|
-
return this.#
|
|
316
|
+
return this.#SelectMain;
|
|
317
317
|
}
|
|
318
318
|
}
|
|
319
319
|
|
|
320
320
|
function setOptionDisplay(element = new HTMLElement()) {
|
|
321
321
|
// Скрытый фильтром вариант показывается снятием инлайнового `display`:
|
|
322
322
|
// базовый вид строки (блок) задаёт CSS, а не этот обход
|
|
323
|
-
for (
|
|
323
|
+
for (const option of element.childNodes) {
|
|
324
324
|
option.style.removeProperty("display");
|
|
325
325
|
}
|
|
326
326
|
}
|
|
@@ -4,11 +4,11 @@ chui_selectbox {
|
|
|
4
4
|
карточку. Токены переопределены у корня поля, поэтому действуют только внутри него
|
|
5
5
|
(тот же приём у полосы меню-бара). */
|
|
6
6
|
--control_padding: var(--control_padding_sm);
|
|
7
|
-
--
|
|
7
|
+
--block_padding: var(--block_padding_sm);
|
|
8
8
|
display: flex;
|
|
9
9
|
flex-direction: column;
|
|
10
10
|
height: max-content;
|
|
11
|
-
margin: var(--
|
|
11
|
+
margin: var(--block_margin);
|
|
12
12
|
width: var(--control_width);
|
|
13
13
|
}
|
|
14
14
|
|
|
@@ -18,7 +18,7 @@ selectbox {
|
|
|
18
18
|
outline: none;
|
|
19
19
|
height: max-content;
|
|
20
20
|
width: -webkit-fill-available;
|
|
21
|
-
border-radius: var(--
|
|
21
|
+
border-radius: var(--radius_sm);
|
|
22
22
|
padding: 0;
|
|
23
23
|
font-size: var(--font_default_size);
|
|
24
24
|
color: var(--text_color);
|
|
@@ -32,7 +32,7 @@ selectbox {
|
|
|
32
32
|
display: block;
|
|
33
33
|
outline: none;
|
|
34
34
|
margin: 0;
|
|
35
|
-
padding: var(--control_padding) 0 var(--
|
|
35
|
+
padding: var(--control_padding) 0 var(--block_padding);
|
|
36
36
|
background: transparent;
|
|
37
37
|
color: var(--text_color);
|
|
38
38
|
text-align: start;
|
|
@@ -62,7 +62,7 @@ selectbox_dropdown {
|
|
|
62
62
|
position: absolute;
|
|
63
63
|
display: none;
|
|
64
64
|
height: max-content;
|
|
65
|
-
border-radius: var(--
|
|
65
|
+
border-radius: var(--radius_sm);
|
|
66
66
|
padding: var(--control_padding);
|
|
67
67
|
font-size: var(--font_default_size);
|
|
68
68
|
flex-direction: column;
|
|
@@ -76,7 +76,7 @@ selectbox_dropdown {
|
|
|
76
76
|
select_button_open {
|
|
77
77
|
cursor: pointer;
|
|
78
78
|
outline: none;
|
|
79
|
-
padding: var(--
|
|
79
|
+
padding: var(--block_padding);
|
|
80
80
|
}
|
|
81
81
|
|
|
82
82
|
selectbox_option {
|
|
@@ -92,7 +92,7 @@ selectbox_option {
|
|
|
92
92
|
text-align: start;
|
|
93
93
|
/* 5px отступа слоя + 6px строки = 11px — ровно отступ текста в самом поле */
|
|
94
94
|
padding: var(--control_padding) 6px;
|
|
95
|
-
border-radius: var(--
|
|
95
|
+
border-radius: var(--radius_sm);
|
|
96
96
|
color: var(--text_color);
|
|
97
97
|
/* Подпись держит одну строку (как у чипсов): длинный вариант усекается, а не растит список */
|
|
98
98
|
white-space: nowrap;
|
|
@@ -122,7 +122,7 @@ selectbox_option:active {
|
|
|
122
122
|
.select_label {
|
|
123
123
|
height: max-content;
|
|
124
124
|
width: max-content;
|
|
125
|
-
margin: 0 0 var(--
|
|
125
|
+
margin: 0 0 var(--block_margin);
|
|
126
126
|
font-size: var(--font_labels_size);
|
|
127
127
|
font-weight: 500;
|
|
128
128
|
color: var(--text_color);
|
|
@@ -139,7 +139,7 @@ selectbox_option:active {
|
|
|
139
139
|
cursor: not-allowed;
|
|
140
140
|
width: 100%;
|
|
141
141
|
margin: 0;
|
|
142
|
-
padding: var(--control_padding) 0 var(--
|
|
142
|
+
padding: var(--control_padding) 0 var(--block_padding);
|
|
143
143
|
background: transparent;
|
|
144
144
|
color: var(--text_color_disabled);
|
|
145
145
|
text-align: start;
|
|
@@ -160,7 +160,7 @@ selectbox_option:active {
|
|
|
160
160
|
cursor: not-allowed;
|
|
161
161
|
height: max-content;
|
|
162
162
|
width: max-content;
|
|
163
|
-
margin: 0 0 var(--
|
|
163
|
+
margin: 0 0 var(--block_margin);
|
|
164
164
|
font-size: var(--font_labels_size);
|
|
165
165
|
font-weight: 500;
|
|
166
166
|
color: var(--text_color_disabled);
|