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
|
@@ -28,14 +28,14 @@ class Slider {
|
|
|
28
28
|
#root = document.createElement("chui_slider");
|
|
29
29
|
#header = document.createElement("slider_header");
|
|
30
30
|
#title = document.createElement("slider_title");
|
|
31
|
-
#
|
|
31
|
+
#valueLabel = document.createElement("slider_value");
|
|
32
32
|
#field = document.createElement("slider_field");
|
|
33
33
|
#track = document.createElement("slider_track");
|
|
34
34
|
#fill = document.createElement("slider_fill");
|
|
35
35
|
#thumbs = [];
|
|
36
36
|
#id = undefined;
|
|
37
37
|
#name = undefined;
|
|
38
|
-
#
|
|
38
|
+
#titleText = undefined;
|
|
39
39
|
#label = undefined;
|
|
40
40
|
#min = 0;
|
|
41
41
|
#max = 100;
|
|
@@ -44,8 +44,8 @@ class Slider {
|
|
|
44
44
|
#values = [0];
|
|
45
45
|
#disabled = false;
|
|
46
46
|
#format = undefined;
|
|
47
|
-
#
|
|
48
|
-
#
|
|
47
|
+
#changeListeners = [];
|
|
48
|
+
#inputListeners = [];
|
|
49
49
|
#dragging = undefined;
|
|
50
50
|
|
|
51
51
|
constructor(
|
|
@@ -88,13 +88,13 @@ class Slider {
|
|
|
88
88
|
}
|
|
89
89
|
this.#track.addEventListener("pointerdown", this.#onTrackPointerDown);
|
|
90
90
|
this.#header.appendChild(this.#title);
|
|
91
|
-
this.#header.appendChild(this.#
|
|
91
|
+
this.#header.appendChild(this.#valueLabel);
|
|
92
92
|
this.#root.appendChild(this.#header);
|
|
93
93
|
this.#root.appendChild(this.#field);
|
|
94
94
|
|
|
95
95
|
if (options.title !== undefined) this.setTitle(options.title);
|
|
96
96
|
else this.#header.hidden = true;
|
|
97
|
-
if (options.showValue === false) this.#
|
|
97
|
+
if (options.showValue === false) this.#valueLabel.hidden = true;
|
|
98
98
|
this.setValue(options.value === undefined ? (this.#range ? [this.#min, this.#max] : this.#min) : options.value);
|
|
99
99
|
if (options.disabled === true) this.setDisabled(true);
|
|
100
100
|
if (options.width !== undefined) this.setWidth(options.width);
|
|
@@ -153,7 +153,7 @@ class Slider {
|
|
|
153
153
|
}
|
|
154
154
|
|
|
155
155
|
setTitle(text = String()) {
|
|
156
|
-
this.#
|
|
156
|
+
this.#titleText = text;
|
|
157
157
|
this.#title.innerText = text;
|
|
158
158
|
this.#header.hidden = false;
|
|
159
159
|
this.#render();
|
|
@@ -189,7 +189,7 @@ class Slider {
|
|
|
189
189
|
|
|
190
190
|
/** Показывать ли читаемое значение рядом с заголовком */
|
|
191
191
|
setShowValue(show = Boolean()) {
|
|
192
|
-
this.#
|
|
192
|
+
this.#valueLabel.hidden = show === false;
|
|
193
193
|
return this;
|
|
194
194
|
}
|
|
195
195
|
|
|
@@ -223,13 +223,13 @@ class Slider {
|
|
|
223
223
|
// ПОДПИСКИ
|
|
224
224
|
/** Вызов на отпускание бегунка, клик по дорожке и ход с клавиатуры */
|
|
225
225
|
addChangeListener(listener = () => {}) {
|
|
226
|
-
this.#
|
|
226
|
+
this.#changeListeners.push(listener);
|
|
227
227
|
return this;
|
|
228
228
|
}
|
|
229
229
|
|
|
230
230
|
/** Вызов на каждое изменение во время перетаскивания */
|
|
231
231
|
addInputListener(listener = () => {}) {
|
|
232
|
-
this.#
|
|
232
|
+
this.#inputListeners.push(listener);
|
|
233
233
|
return this;
|
|
234
234
|
}
|
|
235
235
|
|
|
@@ -281,9 +281,9 @@ class Slider {
|
|
|
281
281
|
#thumbLabel(index = Number()) {
|
|
282
282
|
const base =
|
|
283
283
|
this.#label === undefined
|
|
284
|
-
? this.#
|
|
284
|
+
? this.#titleText === undefined
|
|
285
285
|
? I18n.t("forms.sliderValue")
|
|
286
|
-
: this.#
|
|
286
|
+
: this.#titleText
|
|
287
287
|
: this.#label;
|
|
288
288
|
if (!this.#range) return base;
|
|
289
289
|
return `${base}: ${index === 0 ? I18n.t("forms.sliderMin") : I18n.t("forms.sliderMax")}`;
|
|
@@ -309,7 +309,7 @@ class Slider {
|
|
|
309
309
|
if (this.#disabled) thumb.setAttribute("aria-disabled", "true");
|
|
310
310
|
else thumb.removeAttribute("aria-disabled");
|
|
311
311
|
});
|
|
312
|
-
this.#
|
|
312
|
+
this.#valueLabel.innerText = this.#range
|
|
313
313
|
? `${this.#valueText(low)} – ${this.#valueText(high)}`
|
|
314
314
|
: this.#valueText(low);
|
|
315
315
|
}
|
|
@@ -327,7 +327,7 @@ class Slider {
|
|
|
327
327
|
}
|
|
328
328
|
|
|
329
329
|
#emit(type = String()) {
|
|
330
|
-
const listeners = type === "input" ? this.#
|
|
330
|
+
const listeners = type === "input" ? this.#inputListeners : this.#changeListeners;
|
|
331
331
|
const value = this.getValue();
|
|
332
332
|
for (const listener of [...listeners]) listener(value);
|
|
333
333
|
}
|
|
@@ -4,12 +4,12 @@ chui_slider {
|
|
|
4
4
|
карточку. Токены переопределены у корня поля, поэтому действуют только внутри него
|
|
5
5
|
(тот же приём у полосы меню-бара). */
|
|
6
6
|
--control_padding: var(--control_padding_sm);
|
|
7
|
-
--
|
|
7
|
+
--block_padding: var(--block_padding_sm);
|
|
8
8
|
display: block;
|
|
9
9
|
/* fill-available учитывает собственный margin, 100% — нет: слайдер уезжал
|
|
10
10
|
вправо и вылезал за родителя на 6px */
|
|
11
11
|
width: -webkit-fill-available;
|
|
12
|
-
margin: var(--
|
|
12
|
+
margin: var(--block_margin);
|
|
13
13
|
font-size: var(--font_default_size);
|
|
14
14
|
color: var(--text_color);
|
|
15
15
|
}
|
|
@@ -81,11 +81,12 @@ slider_thumb {
|
|
|
81
81
|
border-radius: var(--radius_circle);
|
|
82
82
|
background: var(--blue_prime_background);
|
|
83
83
|
border: 2px solid var(--main_background);
|
|
84
|
-
box-shadow:
|
|
84
|
+
box-shadow: var(--box_shadow_control);
|
|
85
85
|
cursor: pointer;
|
|
86
86
|
outline: none;
|
|
87
87
|
touch-action: none;
|
|
88
|
-
|
|
88
|
+
/* Ползунок растёт на наведении и захвате: отклик с лёгким перелётом, а не линейный рост */
|
|
89
|
+
transition: transform var(--motion_base) var(--motion_spring);
|
|
89
90
|
}
|
|
90
91
|
|
|
91
92
|
slider_thumb:hover,
|
|
@@ -4,12 +4,12 @@ chui_text_input {
|
|
|
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
|
width: var(--control_width);
|
|
11
11
|
height: max-content;
|
|
12
|
-
margin: var(--
|
|
12
|
+
margin: var(--block_margin);
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
chui_text_main {
|
|
@@ -17,12 +17,12 @@ chui_text_main {
|
|
|
17
17
|
width: -webkit-fill-available;
|
|
18
18
|
height: max-content;
|
|
19
19
|
margin: 0;
|
|
20
|
-
border-radius: var(--
|
|
20
|
+
border-radius: var(--radius_sm);
|
|
21
21
|
background: var(--element_background);
|
|
22
22
|
color: var(--text_color);
|
|
23
23
|
align-items: center;
|
|
24
24
|
position: relative;
|
|
25
|
-
padding: var(--
|
|
25
|
+
padding: var(--block_padding);
|
|
26
26
|
border: 1px solid var(--border_color);
|
|
27
27
|
}
|
|
28
28
|
|
|
@@ -40,7 +40,7 @@ chui_text_main {
|
|
|
40
40
|
.input_label {
|
|
41
41
|
height: max-content;
|
|
42
42
|
width: max-content;
|
|
43
|
-
margin: 0 0 var(--
|
|
43
|
+
margin: 0 0 var(--block_margin);
|
|
44
44
|
font-size: var(--font_labels_size);
|
|
45
45
|
font-weight: 500;
|
|
46
46
|
color: var(--text_color);
|
|
@@ -50,7 +50,7 @@ error_message_text {
|
|
|
50
50
|
display: none;
|
|
51
51
|
height: max-content;
|
|
52
52
|
width: max-content;
|
|
53
|
-
margin: var(--
|
|
53
|
+
margin: var(--block_margin) var(--block_margin) 0 var(--block_margin);
|
|
54
54
|
font-size: var(--font_labels_size);
|
|
55
55
|
font-weight: 500;
|
|
56
56
|
color: var(--red_prime_background);
|
|
@@ -83,7 +83,7 @@ error_message_text {
|
|
|
83
83
|
cursor: not-allowed;
|
|
84
84
|
height: max-content;
|
|
85
85
|
width: max-content;
|
|
86
|
-
margin: 0 0 var(--
|
|
86
|
+
margin: 0 0 var(--block_margin);
|
|
87
87
|
font-size: var(--font_labels_size);
|
|
88
88
|
font-weight: 500;
|
|
89
89
|
color: var(--text_color_disabled);
|
|
@@ -4,13 +4,13 @@ const { Animation } = require("../../../modules/chui_animations/animations");
|
|
|
4
4
|
const { Validate } = require("../../../modules/chui_validate/chui_validate");
|
|
5
5
|
|
|
6
6
|
class TextInput {
|
|
7
|
-
#
|
|
8
|
-
#
|
|
7
|
+
#chuiTextMain = document.createElement("chui_text_main");
|
|
8
|
+
#chuiTextInput = document.createElement("chui_text_input");
|
|
9
9
|
#id = require("randomstring").generate();
|
|
10
10
|
#title = String();
|
|
11
11
|
#input = document.createElement("input");
|
|
12
12
|
#label = document.createElement("label");
|
|
13
|
-
#
|
|
13
|
+
#errorMessageText = document.createElement("error_message_text");
|
|
14
14
|
constructor(
|
|
15
15
|
options = {
|
|
16
16
|
name: String(),
|
|
@@ -38,33 +38,29 @@ class TextInput {
|
|
|
38
38
|
if (options.value !== undefined) this.#input.value = options.value;
|
|
39
39
|
if (options.required !== undefined) this.#input.required = options.required;
|
|
40
40
|
// Валидация и показ ошибки: правила из options (required/min/max/pattern/…)
|
|
41
|
-
Validate.installField(this, options, this.#
|
|
42
|
-
if (options.disableFocus !== undefined)
|
|
43
|
-
this.#input.addEventListener("mousedown", () => {
|
|
44
|
-
return false;
|
|
45
|
-
});
|
|
41
|
+
Validate.installField(this, options, this.#chuiTextMain, this.#errorMessageText, () => this.#input.value);
|
|
46
42
|
if (options.title !== undefined) {
|
|
47
43
|
this.#title = options.title;
|
|
48
44
|
this.#label.innerText = options.title;
|
|
49
45
|
this.#label.className = "input_label";
|
|
50
46
|
this.#label.setAttribute("for", this.#id);
|
|
51
|
-
this.#
|
|
47
|
+
this.#chuiTextInput.appendChild(this.#label);
|
|
52
48
|
}
|
|
53
|
-
if (options.width !== undefined) this.#
|
|
49
|
+
if (options.width !== undefined) this.#chuiTextInput.style.width = options.width;
|
|
54
50
|
if (options.placeholder !== undefined) this.#input.placeholder = options.placeholder;
|
|
55
51
|
// Опция `disableFocus`: поле не подсвечивается фокусом. Класс читает тема
|
|
56
52
|
// (`field_no_focus` рядом с общим правилом полей), а не сам компонент
|
|
57
|
-
if (options.disableFocus) this.#
|
|
53
|
+
if (options.disableFocus) this.#chuiTextMain.classList.add("field_no_focus");
|
|
58
54
|
// Рамку с кольцом при фокусе и подсказку при наведении рисует общее правило темы
|
|
59
55
|
// (`chui_text_main:hover`, `:focus-within` в global_style.css), а не компонент:
|
|
60
56
|
// прежде он ставил то же самое инлайном, а на `blur` снимал весь атрибут `style`
|
|
61
|
-
this.#
|
|
62
|
-
this.#
|
|
57
|
+
this.#chuiTextMain.appendChild(this.#input);
|
|
58
|
+
this.#chuiTextInput.appendChild(this.#chuiTextMain);
|
|
63
59
|
|
|
64
60
|
//
|
|
65
61
|
this.#input.addEventListener("input", () => {
|
|
66
62
|
this.clearError();
|
|
67
|
-
new Animation(this.#
|
|
63
|
+
new Animation(this.#errorMessageText).fadeOut();
|
|
68
64
|
});
|
|
69
65
|
}
|
|
70
66
|
addInputListener(listener = () => {}) {
|
|
@@ -91,11 +87,11 @@ class TextInput {
|
|
|
91
87
|
setDisabled(boolean = Boolean()) {
|
|
92
88
|
this.#input.disabled = boolean;
|
|
93
89
|
if (boolean) {
|
|
94
|
-
this.#
|
|
90
|
+
this.#chuiTextMain.classList.add("chui_text_main_disabled");
|
|
95
91
|
this.#input.className = "text_input_disabled";
|
|
96
92
|
this.#label.className = "input_label_disabled";
|
|
97
93
|
} else {
|
|
98
|
-
this.#
|
|
94
|
+
this.#chuiTextMain.classList.remove("chui_text_main_disabled");
|
|
99
95
|
this.#input.className = "text_input";
|
|
100
96
|
this.#label.className = "input_label";
|
|
101
97
|
}
|
|
@@ -104,7 +100,7 @@ class TextInput {
|
|
|
104
100
|
this.setError(message);
|
|
105
101
|
}
|
|
106
102
|
set() {
|
|
107
|
-
return this.#
|
|
103
|
+
return this.#chuiTextInput;
|
|
108
104
|
}
|
|
109
105
|
}
|
|
110
106
|
|
|
@@ -4,12 +4,12 @@ chui_area_input {
|
|
|
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
|
width: var(--control_width);
|
|
11
11
|
height: max-content;
|
|
12
|
-
margin: var(--
|
|
12
|
+
margin: var(--block_margin);
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
.resize_off {
|
|
@@ -19,8 +19,8 @@ chui_area_input {
|
|
|
19
19
|
.area_input {
|
|
20
20
|
height: inherit;
|
|
21
21
|
width: -webkit-fill-available;
|
|
22
|
-
border-radius: var(--
|
|
23
|
-
padding: var(--
|
|
22
|
+
border-radius: var(--radius_sm);
|
|
23
|
+
padding: var(--block_padding);
|
|
24
24
|
font-size: var(--font_default_size);
|
|
25
25
|
color: var(--text_color);
|
|
26
26
|
background: var(--element_background);
|
|
@@ -30,7 +30,7 @@ chui_area_input {
|
|
|
30
30
|
.textarea_label {
|
|
31
31
|
height: max-content;
|
|
32
32
|
width: max-content;
|
|
33
|
-
margin: 0 0 var(--
|
|
33
|
+
margin: 0 0 var(--block_margin);
|
|
34
34
|
font-size: var(--font_labels_size);
|
|
35
35
|
font-weight: 500;
|
|
36
36
|
color: var(--text_color);
|
|
@@ -41,8 +41,8 @@ chui_area_input {
|
|
|
41
41
|
cursor: not-allowed;
|
|
42
42
|
height: inherit;
|
|
43
43
|
width: -webkit-fill-available;
|
|
44
|
-
border-radius: var(--
|
|
45
|
-
padding: var(--
|
|
44
|
+
border-radius: var(--radius_sm);
|
|
45
|
+
padding: var(--block_padding);
|
|
46
46
|
font-size: var(--font_default_size);
|
|
47
47
|
color: var(--text_color_disabled);
|
|
48
48
|
background: var(--element_background_disabled);
|
|
@@ -53,7 +53,7 @@ chui_area_input {
|
|
|
53
53
|
cursor: not-allowed;
|
|
54
54
|
height: max-content;
|
|
55
55
|
width: max-content;
|
|
56
|
-
margin: 0 0 var(--
|
|
56
|
+
margin: 0 0 var(--block_margin);
|
|
57
57
|
font-size: var(--font_labels_size);
|
|
58
58
|
font-weight: 500;
|
|
59
59
|
color: var(--text_color_disabled);
|
|
@@ -2,8 +2,8 @@ const { Validate } = require("../../../modules/chui_validate/chui_validate");
|
|
|
2
2
|
|
|
3
3
|
class TextArea {
|
|
4
4
|
#id = require("randomstring").generate();
|
|
5
|
-
#
|
|
6
|
-
#
|
|
5
|
+
#chuiTextInput = document.createElement("chui_area_input");
|
|
6
|
+
#textArea = document.createElement("textarea");
|
|
7
7
|
#label = document.createElement("label");
|
|
8
8
|
#title = undefined;
|
|
9
9
|
constructor(
|
|
@@ -17,64 +17,64 @@ class TextArea {
|
|
|
17
17
|
}
|
|
18
18
|
) {
|
|
19
19
|
require("../../../modules/chui_functions").setStyles(__dirname + "/styles.css", "chUiJS_TextArea");
|
|
20
|
-
this.#
|
|
21
|
-
this.#
|
|
22
|
-
if (options.name !== undefined) this.#
|
|
23
|
-
if (options.required !== undefined) this.#
|
|
20
|
+
this.#textArea.classList.add("area_input", "resize_off");
|
|
21
|
+
this.#textArea.id = this.#id;
|
|
22
|
+
if (options.name !== undefined) this.#textArea.name = options.name;
|
|
23
|
+
if (options.required !== undefined) this.#textArea.required = options.required;
|
|
24
24
|
// Валидация и показ ошибки: правила из options. Текст ошибки — в корень поля
|
|
25
25
|
// (под областью ввода), а рамку получает само поле: иначе узел с текстом попал бы
|
|
26
26
|
// внутрь `<textarea>` и читался бы как его содержимое
|
|
27
27
|
Validate.installField(
|
|
28
28
|
this,
|
|
29
29
|
options,
|
|
30
|
-
this.#
|
|
30
|
+
this.#chuiTextInput,
|
|
31
31
|
undefined,
|
|
32
|
-
() => this.#
|
|
33
|
-
this.#
|
|
32
|
+
() => this.#textArea.value,
|
|
33
|
+
this.#textArea
|
|
34
34
|
);
|
|
35
35
|
if (options.title !== undefined) {
|
|
36
36
|
this.#title = options.title;
|
|
37
37
|
this.#label.innerText = options.title;
|
|
38
38
|
this.#label.classList.add("textarea_label");
|
|
39
39
|
this.#label.setAttribute("for", this.#id);
|
|
40
|
-
this.#
|
|
40
|
+
this.#chuiTextInput.appendChild(this.#label);
|
|
41
41
|
}
|
|
42
|
-
if (options.placeholder !== undefined) this.#
|
|
43
|
-
if (options.width !== undefined) this.#
|
|
44
|
-
if (options.height !== undefined) this.#
|
|
42
|
+
if (options.placeholder !== undefined) this.#textArea.placeholder = options.placeholder;
|
|
43
|
+
if (options.width !== undefined) this.#chuiTextInput.style.width = options.width;
|
|
44
|
+
if (options.height !== undefined) this.#chuiTextInput.style.height = options.height;
|
|
45
45
|
// Рамку с кольцом при фокусе рисует общее правило темы (`.area_input:hover`,
|
|
46
46
|
// `:focus-within`), а не компонент: прежде он ставил то же самое инлайном,
|
|
47
47
|
// а на `blur` снимал весь атрибут `style`
|
|
48
|
-
this.#
|
|
48
|
+
this.#chuiTextInput.appendChild(this.#textArea);
|
|
49
49
|
}
|
|
50
50
|
getName() {
|
|
51
|
-
return this.#
|
|
51
|
+
return this.#textArea.name;
|
|
52
52
|
}
|
|
53
53
|
getTitle() {
|
|
54
54
|
return this.#title;
|
|
55
55
|
}
|
|
56
56
|
getValue() {
|
|
57
|
-
return this.#
|
|
57
|
+
return this.#textArea.value;
|
|
58
58
|
}
|
|
59
59
|
setValue(text = String()) {
|
|
60
|
-
this.#
|
|
60
|
+
this.#textArea.value = text;
|
|
61
61
|
}
|
|
62
62
|
setDisabled(boolean = Boolean()) {
|
|
63
|
-
this.#
|
|
63
|
+
this.#textArea.disabled = boolean;
|
|
64
64
|
if (boolean) {
|
|
65
|
-
this.#
|
|
66
|
-
this.#
|
|
65
|
+
this.#textArea.classList.remove("area_input");
|
|
66
|
+
this.#textArea.classList.add("area_input_disabled");
|
|
67
67
|
this.#label.classList.remove("textarea_label");
|
|
68
68
|
this.#label.classList.add("textarea_label_disabled");
|
|
69
69
|
} else {
|
|
70
|
-
this.#
|
|
71
|
-
this.#
|
|
70
|
+
this.#textArea.classList.add("area_input");
|
|
71
|
+
this.#textArea.classList.remove("area_input_disabled");
|
|
72
72
|
this.#label.classList.add("textarea_label");
|
|
73
73
|
this.#label.classList.remove("textarea_label_disabled");
|
|
74
74
|
}
|
|
75
75
|
}
|
|
76
76
|
set() {
|
|
77
|
-
return this.#
|
|
77
|
+
return this.#chuiTextInput;
|
|
78
78
|
}
|
|
79
79
|
}
|
|
80
80
|
|
|
@@ -5,18 +5,18 @@ chui_time_input {
|
|
|
5
5
|
карточку. Токены переопределены у корня поля, поэтому действуют только внутри него
|
|
6
6
|
(тот же приём у полосы меню-бара). */
|
|
7
7
|
--control_padding: var(--control_padding_sm);
|
|
8
|
-
--
|
|
8
|
+
--block_padding: var(--block_padding_sm);
|
|
9
9
|
display: flex;
|
|
10
10
|
flex-direction: column;
|
|
11
11
|
width: max-content;
|
|
12
12
|
height: max-content;
|
|
13
|
-
margin: var(--
|
|
13
|
+
margin: var(--block_margin);
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
time_input_label {
|
|
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;
|
|
@@ -39,7 +39,7 @@ time_main_block {
|
|
|
39
39
|
width: max-content;
|
|
40
40
|
height: var(--control_height);
|
|
41
41
|
border: 1px solid var(--border_color);
|
|
42
|
-
border-radius: var(--
|
|
42
|
+
border-radius: var(--radius_sm);
|
|
43
43
|
background: var(--element_background);
|
|
44
44
|
color: var(--text_color);
|
|
45
45
|
}
|
|
@@ -134,7 +134,7 @@ input.time_input:disabled {
|
|
|
134
134
|
в прокрутку панели — иначе колонки часов и минут обрезались бы краем окна */
|
|
135
135
|
overflow: hidden auto;
|
|
136
136
|
border: 1px solid var(--border_color);
|
|
137
|
-
border-radius: var(--
|
|
137
|
+
border-radius: var(--radius_sm);
|
|
138
138
|
background: var(--header_background);
|
|
139
139
|
backdrop-filter: var(--global_blur);
|
|
140
140
|
-webkit-backdrop-filter: var(--global_blur);
|
|
@@ -144,18 +144,14 @@ input.time_input:disabled {
|
|
|
144
144
|
|
|
145
145
|
.time_dropdown_shown {
|
|
146
146
|
display: flex;
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
to {
|
|
156
|
-
opacity: 1;
|
|
157
|
-
transform: none;
|
|
158
|
-
}
|
|
147
|
+
/* Панель открывается общим кадром: свой у неё был тот же по смыслу (прозрачность и подъём),
|
|
148
|
+
но без роста, а кривая шла торможением вместо отклика */
|
|
149
|
+
animation: chui_panel_in var(--motion_base) var(--motion_spring);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/* Уход панели: она гаснет и сходит вверх, а класс показа снимается по концу кадра */
|
|
153
|
+
.time_dropdown_leaving {
|
|
154
|
+
animation: chui_leave_up var(--motion_fast) var(--motion_ease) forwards;
|
|
159
155
|
}
|
|
160
156
|
|
|
161
157
|
.time_list {
|
|
@@ -47,16 +47,16 @@ class TimeInput {
|
|
|
47
47
|
#minutes = document.createElement("time_list");
|
|
48
48
|
#id = undefined;
|
|
49
49
|
#name = undefined;
|
|
50
|
-
#
|
|
51
|
-
#
|
|
50
|
+
#titleText = undefined;
|
|
51
|
+
#labelText = undefined;
|
|
52
52
|
#step = 5;
|
|
53
53
|
#min = undefined;
|
|
54
54
|
#max = undefined;
|
|
55
55
|
#disabled = false;
|
|
56
|
-
#
|
|
56
|
+
#isOpen = false;
|
|
57
57
|
#listeners = [];
|
|
58
|
-
#
|
|
59
|
-
#
|
|
58
|
+
#onChange = undefined;
|
|
59
|
+
#windowClickEvent = (event) => {
|
|
60
60
|
if (!this.#block.contains(event.target)) this.#closeDropdown();
|
|
61
61
|
};
|
|
62
62
|
|
|
@@ -79,8 +79,8 @@ class TimeInput {
|
|
|
79
79
|
TimeInput.#counter += 1;
|
|
80
80
|
this.#id = options.id === undefined ? `chui_time_input_${TimeInput.#counter}` : options.id;
|
|
81
81
|
this.#name = options.name;
|
|
82
|
-
this.#
|
|
83
|
-
this.#
|
|
82
|
+
this.#labelText = options.label;
|
|
83
|
+
this.#onChange = options.onChange;
|
|
84
84
|
if (options.changeListener !== undefined) this.addChangeListener(options.changeListener);
|
|
85
85
|
this.#root.id = this.#id;
|
|
86
86
|
this.#input.type = "time";
|
|
@@ -116,7 +116,7 @@ class TimeInput {
|
|
|
116
116
|
this.#open.appendChild(glyph);
|
|
117
117
|
this.#open.addEventListener("click", () => {
|
|
118
118
|
if (this.#input.disabled) return;
|
|
119
|
-
if (this.#
|
|
119
|
+
if (this.#isOpen) this.#closeDropdown();
|
|
120
120
|
else this.#openDropdown();
|
|
121
121
|
});
|
|
122
122
|
this.#label.className = "time_input_label";
|
|
@@ -140,10 +140,10 @@ class TimeInput {
|
|
|
140
140
|
delete rules.min;
|
|
141
141
|
delete rules.max;
|
|
142
142
|
if (rules.pattern === undefined) rules.pattern = TIME_PATTERN;
|
|
143
|
-
const
|
|
143
|
+
const ownValidate = options.validate;
|
|
144
144
|
if (this.#min !== undefined || this.#max !== undefined) {
|
|
145
145
|
rules.validate = (value) => {
|
|
146
|
-
const custom =
|
|
146
|
+
const custom = ownValidate === undefined ? undefined : ownValidate(value);
|
|
147
147
|
if (custom !== undefined && custom !== null && custom !== true) return custom;
|
|
148
148
|
const parsed = TimeInput.parse(value);
|
|
149
149
|
if (parsed === undefined) return undefined;
|
|
@@ -162,7 +162,7 @@ class TimeInput {
|
|
|
162
162
|
);
|
|
163
163
|
if (options.value !== undefined) this.setValue(options.value);
|
|
164
164
|
this.setDisabled(options.disabled === true);
|
|
165
|
-
window.addEventListener("click", this.#
|
|
165
|
+
window.addEventListener("click", this.#windowClickEvent);
|
|
166
166
|
}
|
|
167
167
|
|
|
168
168
|
// GET
|
|
@@ -175,7 +175,7 @@ class TimeInput {
|
|
|
175
175
|
}
|
|
176
176
|
|
|
177
177
|
getTitle() {
|
|
178
|
-
return this.#
|
|
178
|
+
return this.#titleText;
|
|
179
179
|
}
|
|
180
180
|
|
|
181
181
|
/** Значение в виде «ЧЧ:ММ»; пустая строка — время не задано */
|
|
@@ -201,7 +201,7 @@ class TimeInput {
|
|
|
201
201
|
}
|
|
202
202
|
|
|
203
203
|
isOpen() {
|
|
204
|
-
return this.#
|
|
204
|
+
return this.#isOpen;
|
|
205
205
|
}
|
|
206
206
|
|
|
207
207
|
/**
|
|
@@ -245,7 +245,7 @@ class TimeInput {
|
|
|
245
245
|
|
|
246
246
|
/** Подпись над полем; `undefined` её убирает */
|
|
247
247
|
setTitle(text = undefined) {
|
|
248
|
-
this.#
|
|
248
|
+
this.#titleText = text;
|
|
249
249
|
if (text === undefined || text === "") {
|
|
250
250
|
this.#label.hidden = true;
|
|
251
251
|
this.#label.innerText = "";
|
|
@@ -264,8 +264,8 @@ class TimeInput {
|
|
|
264
264
|
|
|
265
265
|
/** Доступное имя поля, когда подписи в разметке нет */
|
|
266
266
|
setLabel(text = undefined) {
|
|
267
|
-
this.#
|
|
268
|
-
if (this.#
|
|
267
|
+
this.#labelText = text;
|
|
268
|
+
if (this.#titleText === undefined || this.#titleText === "") {
|
|
269
269
|
if (text === undefined) this.#input.removeAttribute("aria-label");
|
|
270
270
|
else this.#input.setAttribute("aria-label", String(text));
|
|
271
271
|
}
|
|
@@ -351,8 +351,8 @@ class TimeInput {
|
|
|
351
351
|
|
|
352
352
|
// === ПАНЕЛЬ ===
|
|
353
353
|
#accessibleName() {
|
|
354
|
-
if (this.#
|
|
355
|
-
if (this.#
|
|
354
|
+
if (this.#titleText !== undefined && this.#titleText !== "") return this.#titleText;
|
|
355
|
+
if (this.#labelText !== undefined && this.#labelText !== "") return this.#labelText;
|
|
356
356
|
return I18n.t("time.label");
|
|
357
357
|
}
|
|
358
358
|
|
|
@@ -425,11 +425,12 @@ class TimeInput {
|
|
|
425
425
|
|
|
426
426
|
#openDropdown() {
|
|
427
427
|
this.#renderOptions();
|
|
428
|
-
this.#
|
|
428
|
+
this.#isOpen = true;
|
|
429
429
|
this.#input.setAttribute("aria-expanded", "true");
|
|
430
430
|
// Показ — классом, а не общей `Animation`: её `animationend` снимает `display`,
|
|
431
431
|
// и панель, открытая поверх незавершённого закрытия, гасла бы сама.
|
|
432
432
|
// Класс назван иначе, чем у каретки: одно имя давало бы панели стили кнопки
|
|
433
|
+
this.#dropdown.classList.remove("time_dropdown_leaving");
|
|
433
434
|
this.#dropdown.classList.add("time_dropdown_shown");
|
|
434
435
|
this.#placeDropdown();
|
|
435
436
|
this.#focusSelected("hours");
|
|
@@ -448,10 +449,20 @@ class TimeInput {
|
|
|
448
449
|
}
|
|
449
450
|
|
|
450
451
|
#closeDropdown() {
|
|
451
|
-
if (!this.#
|
|
452
|
-
this.#
|
|
452
|
+
if (!this.#isOpen) return;
|
|
453
|
+
this.#isOpen = false;
|
|
453
454
|
this.#input.setAttribute("aria-expanded", "false");
|
|
454
|
-
|
|
455
|
+
// Уход идёт движением: класс показа снимается по концу кадра, а незавершённый уход
|
|
456
|
+
// отменяется при открытии — иначе панель погасла бы уже открытой
|
|
457
|
+
this.#dropdown.classList.add("time_dropdown_leaving");
|
|
458
|
+
const done = (event) => {
|
|
459
|
+
if (event.target !== this.#dropdown) return;
|
|
460
|
+
this.#dropdown.removeEventListener("animationend", done);
|
|
461
|
+
if (this.#dropdown.classList.contains("time_dropdown_leaving") === false) return;
|
|
462
|
+
this.#dropdown.classList.remove("time_dropdown_leaving");
|
|
463
|
+
this.#dropdown.classList.remove("time_dropdown_shown");
|
|
464
|
+
};
|
|
465
|
+
this.#dropdown.addEventListener("animationend", done);
|
|
455
466
|
}
|
|
456
467
|
|
|
457
468
|
#changed() {
|
|
@@ -459,7 +470,7 @@ class TimeInput {
|
|
|
459
470
|
this.#markOptions();
|
|
460
471
|
const value = this.getValue();
|
|
461
472
|
for (const listener of [...this.#listeners]) listener(value, this);
|
|
462
|
-
if (this.#
|
|
473
|
+
if (this.#onChange !== undefined) this.#onChange(value, this);
|
|
463
474
|
}
|
|
464
475
|
|
|
465
476
|
#moveOption(delta = Number()) {
|
|
@@ -550,7 +561,7 @@ class TimeInput {
|
|
|
550
561
|
|
|
551
562
|
/** Полное удаление: панель и слушатель окна */
|
|
552
563
|
destroy() {
|
|
553
|
-
window.removeEventListener("click", this.#
|
|
564
|
+
window.removeEventListener("click", this.#windowClickEvent);
|
|
554
565
|
this.#closeDropdown();
|
|
555
566
|
}
|
|
556
567
|
}
|