chuijs 4.0.2 → 4.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +61 -0
- package/README.md +43 -644
- package/framework/appLayout/default/chui_app_layout.js +308 -260
- package/framework/appLayout/default/global_style.css +85 -48
- package/framework/components/chui_accordion/accordion.js +29 -26
- package/framework/components/chui_accordion/styles.css +6 -5
- package/framework/components/chui_action_sheet/action_sheet.js +59 -33
- package/framework/components/chui_action_sheet/styles.css +2 -1
- package/framework/components/chui_affix/affix.js +11 -6
- package/framework/components/chui_alert/alert.js +23 -14
- package/framework/components/chui_avatar/avatar.js +23 -22
- package/framework/components/chui_avatar_group/avatar_group.js +21 -19
- package/framework/components/chui_backtop/backtop.js +35 -19
- package/framework/components/chui_badge/badge.js +15 -13
- package/framework/components/chui_breadcrumb/breadcrumb.js +15 -13
- package/framework/components/chui_button/button.js +42 -22
- package/framework/components/chui_button/styles.css +2 -2
- package/framework/components/chui_calendar/calendar.js +12 -10
- package/framework/components/chui_card/card.js +43 -23
- package/framework/components/chui_chat/chat.js +72 -33
- package/framework/components/chui_clipboard_history/clipboard_history.js +30 -21
- package/framework/components/chui_clipboard_history/styles.css +4 -2
- package/framework/components/chui_code/code.js +2 -2
- package/framework/components/chui_code/styles.css +2 -2
- package/framework/components/chui_code_editor/code_editor.js +47 -31
- package/framework/components/chui_code_editor/styles.css +3 -2
- package/framework/components/chui_command_palette/command_palette.js +60 -37
- package/framework/components/chui_console/console.js +5 -5
- package/framework/components/chui_console/styles.css +1 -1
- package/framework/components/chui_content_block/content_block.js +33 -19
- package/framework/components/chui_content_block/styles.css +2 -2
- package/framework/components/chui_context_menu/context_menu.js +9 -4
- package/framework/components/chui_custom_element/custom_element.js +22 -15
- package/framework/components/chui_data_grid/data_grid.js +396 -234
- package/framework/components/chui_data_grid/styles.css +10 -8
- package/framework/components/chui_descriptions/descriptions.js +34 -17
- package/framework/components/chui_details/details.js +32 -26
- package/framework/components/chui_details/styles.css +5 -4
- package/framework/components/chui_diff_viewer/diff_viewer.js +91 -66
- package/framework/components/chui_diff_viewer/styles.css +1 -1
- package/framework/components/chui_divider/divider.js +13 -11
- package/framework/components/chui_drawer/drawer.js +27 -25
- package/framework/components/chui_drop_zone/drop_zone.js +31 -21
- package/framework/components/chui_empty_state/empty_state.js +20 -15
- package/framework/components/chui_fieldset/fieldset.js +37 -20
- package/framework/components/chui_fieldset/styles.css +1 -1
- package/framework/components/chui_file_explorer/file_explorer.js +157 -86
- package/framework/components/chui_file_explorer/styles.css +2 -1
- package/framework/components/chui_form/form.js +31 -19
- package/framework/components/chui_form/styles.css +1 -1
- package/framework/components/chui_gantt/gantt.js +64 -40
- package/framework/components/chui_graphs/graphs.js +301 -200
- package/framework/components/chui_graphs/styles.css +1 -1
- package/framework/components/chui_hero/hero.js +40 -22
- package/framework/components/chui_html_block/html_block.js +6 -6
- package/framework/components/chui_html_block/styles.css +2 -2
- package/framework/components/chui_hx/hx.js +3 -3
- package/framework/components/chui_hx/styles.css +11 -4
- package/framework/components/chui_icons/icons.js +2109 -2109
- package/framework/components/chui_icons/styles.css +2 -2
- package/framework/components/chui_inputs/chui_check_box/check_box.js +31 -19
- package/framework/components/chui_inputs/chui_check_box/styles.css +18 -18
- package/framework/components/chui_inputs/chui_chips/chips.js +50 -40
- package/framework/components/chui_inputs/chui_chips/styles.css +4 -2
- package/framework/components/chui_inputs/chui_color_picker/color_picker.js +36 -24
- package/framework/components/chui_inputs/chui_combo_box/combo_box.js +100 -82
- package/framework/components/chui_inputs/chui_combo_box/styles.css +14 -12
- package/framework/components/chui_inputs/chui_date/date.js +102 -66
- package/framework/components/chui_inputs/chui_date/styles.css +12 -11
- package/framework/components/chui_inputs/chui_date_range/date_range.js +40 -29
- package/framework/components/chui_inputs/chui_datetime/datetime.js +35 -27
- package/framework/components/chui_inputs/chui_email/email.js +43 -31
- package/framework/components/chui_inputs/chui_email/styles.css +5 -5
- package/framework/components/chui_inputs/chui_file/file.js +68 -41
- package/framework/components/chui_inputs/chui_file/styles.css +13 -12
- package/framework/components/chui_inputs/chui_hotkey/hotkey.js +61 -36
- package/framework/components/chui_inputs/chui_masked/masked.js +39 -28
- package/framework/components/chui_inputs/chui_mention/mention.js +77 -30
- package/framework/components/chui_inputs/chui_multi_combo_box/multi_combo_box.js +173 -153
- package/framework/components/chui_inputs/chui_multi_combo_box/styles.css +9 -7
- package/framework/components/chui_inputs/chui_number/number.js +58 -41
- package/framework/components/chui_inputs/chui_number/styles.css +7 -7
- package/framework/components/chui_inputs/chui_otp/otp.js +38 -29
- package/framework/components/chui_inputs/chui_password/password.js +58 -36
- package/framework/components/chui_inputs/chui_password/styles.css +8 -8
- package/framework/components/chui_inputs/chui_radio_button/radio_button.js +37 -25
- package/framework/components/chui_inputs/chui_radio_button/styles.css +20 -20
- package/framework/components/chui_inputs/chui_rating/rating.js +26 -22
- package/framework/components/chui_inputs/chui_select_box/select_box.js +102 -78
- package/framework/components/chui_inputs/chui_select_box/styles.css +11 -11
- package/framework/components/chui_inputs/chui_slider/slider.js +29 -26
- package/framework/components/chui_inputs/chui_slider/styles.css +2 -1
- package/framework/components/chui_inputs/chui_text/styles.css +8 -8
- package/framework/components/chui_inputs/chui_text/text.js +65 -44
- package/framework/components/chui_inputs/chui_text_area/styles.css +6 -6
- package/framework/components/chui_inputs/chui_text_area/text_area.js +51 -28
- package/framework/components/chui_inputs/chui_time/styles.css +5 -3
- package/framework/components/chui_inputs/chui_time/time.js +38 -27
- package/framework/components/chui_inputs/chui_toggle/styles.css +3 -3
- package/framework/components/chui_inputs/chui_toggle/toggle.js +16 -16
- package/framework/components/chui_json_editor/json_editor.js +53 -43
- package/framework/components/chui_json_viewer/json_viewer.js +52 -33
- package/framework/components/chui_json_viewer/styles.css +3 -2
- package/framework/components/chui_kanban/kanban.js +52 -34
- package/framework/components/chui_kbd/kbd.js +12 -10
- package/framework/components/chui_label/label.js +14 -12
- package/framework/components/chui_label/styles.css +2 -2
- package/framework/components/chui_link/link.js +27 -20
- package/framework/components/chui_list/list.js +31 -27
- package/framework/components/chui_list/styles.css +2 -1
- package/framework/components/chui_markdown_editor/markdown_editor.js +60 -44
- package/framework/components/chui_media/audio.js +326 -227
- package/framework/components/chui_media/audio_styles.css +40 -21
- package/framework/components/chui_media/image.js +70 -38
- package/framework/components/chui_media/image_compare.js +52 -21
- package/framework/components/chui_media/image_styles.css +3 -3
- package/framework/components/chui_media/video.js +155 -62
- package/framework/components/chui_media/video_styles.css +33 -16
- package/framework/components/chui_menu_bar/menu_bar.js +26 -24
- package/framework/components/chui_menu_bar/styles.css +4 -2
- package/framework/components/chui_modal/modal.js +44 -43
- package/framework/components/chui_modal/styles.css +3 -2
- package/framework/components/chui_notification/notification.js +50 -34
- package/framework/components/chui_notification/notification_download.js +31 -25
- package/framework/components/chui_notification/notification_download_progress.css +3 -2
- package/framework/components/chui_notification/notification_download_progress.js +47 -41
- package/framework/components/chui_notification/notification_update.js +23 -16
- package/framework/components/chui_notification/status_plate.js +2 -2
- package/framework/components/chui_notification/styles_download.css +1 -1
- package/framework/components/chui_notification/styles_update.css +1 -1
- package/framework/components/chui_org_chart/org_chart.js +74 -35
- package/framework/components/chui_pagination/pagination.js +62 -27
- package/framework/components/chui_paragraph/paragraph.js +2 -2
- package/framework/components/chui_paragraph/styles.css +1 -1
- package/framework/components/chui_popover/popover.js +49 -28
- package/framework/components/chui_popups/popups.js +137 -108
- package/framework/components/chui_popups/styles.css +2 -2
- package/framework/components/chui_print_button/print_button.js +33 -23
- package/framework/components/chui_progress_bar/progress_bar.js +23 -15
- package/framework/components/chui_progress_bar/styles.css +2 -2
- package/framework/components/chui_progress_ring/progress_ring.js +17 -15
- package/framework/components/chui_qrcode/qrcode.js +75 -31
- package/framework/components/chui_query_builder/query_builder.js +216 -123
- package/framework/components/chui_radio_group/radio_group.js +36 -26
- package/framework/components/chui_radio_group/styles.css +1 -1
- package/framework/components/chui_result/result.js +26 -16
- package/framework/components/chui_scheduler/scheduler.js +57 -35
- package/framework/components/chui_scheduler/styles.css +6 -2
- package/framework/components/chui_segmented_control/segmented_control.js +27 -21
- package/framework/components/chui_settings/settings.js +122 -48
- package/framework/components/chui_shortcut_help/shortcut_help.js +55 -32
- package/framework/components/chui_sidebar_nav/sidebar_nav.js +33 -23
- package/framework/components/chui_skeleton/skeleton.js +29 -24
- package/framework/components/chui_slideshow/slideshow.js +60 -41
- package/framework/components/chui_slideshow/styles.css +18 -12
- package/framework/components/chui_spinner/spinner.js +8 -8
- package/framework/components/chui_spinner/styles.css +0 -1
- package/framework/components/chui_split_button/split_button.js +23 -18
- package/framework/components/chui_split_button/styles.css +1 -1
- package/framework/components/chui_splitter/splitter.js +35 -28
- package/framework/components/chui_statistic/statistic.js +65 -38
- package/framework/components/chui_status_bar/status_bar.js +11 -9
- package/framework/components/chui_stepper/stepper.js +27 -22
- package/framework/components/chui_sticky_bar/sticky_bar.js +9 -4
- package/framework/components/chui_sticky_bar/styles.css +3 -1
- package/framework/components/chui_tabs/chui_tabs.js +28 -22
- package/framework/components/chui_tabs/styles.css +3 -3
- package/framework/components/chui_text_editor/styles.css +20 -19
- package/framework/components/chui_text_editor/text_editor.js +85 -61
- package/framework/components/chui_text_editor/text_editor_panel.js +346 -284
- package/framework/components/chui_theme_toggle/theme_toggle.js +27 -22
- package/framework/components/chui_timeline/timeline.js +14 -12
- package/framework/components/chui_toast_queue/toast_queue.js +52 -46
- package/framework/components/chui_toolbar/toolbar.js +20 -13
- package/framework/components/chui_tooltip/tooltip.js +37 -24
- package/framework/components/chui_tour/styles.css +8 -3
- package/framework/components/chui_tour/tour.js +61 -27
- package/framework/components/chui_transfer/styles.css +2 -1
- package/framework/components/chui_transfer/transfer.js +75 -42
- package/framework/components/chui_tree_table/tree_table.js +43 -29
- package/framework/components/chui_tree_view/styles.css +4 -2
- package/framework/components/chui_tree_view/tree_view.js +142 -99
- package/framework/components/chui_watermark/watermark.js +24 -16
- package/framework/components/chui_webview/styles.css +2 -2
- package/framework/components/chui_webview/webview.js +62 -50
- package/framework/components/telegram_bot/chui_telegram_bot.js +71 -64
- package/framework/modules/chui_a11y/chui_a11y.js +77 -46
- package/framework/modules/chui_animations/animations.js +42 -42
- package/framework/modules/chui_animations/styles.css +1 -1
- package/framework/modules/chui_bridge/preload.js +36 -25
- package/framework/modules/chui_functions.js +52 -50
- package/framework/modules/chui_highlight/chui_highlight.js +25 -22
- package/framework/modules/chui_i18n/chui_i18n.js +9 -7
- package/framework/modules/chui_i18n/locales/a11y.js +5 -5
- package/framework/modules/chui_i18n/locales/app_layout.js +5 -5
- package/framework/modules/chui_i18n/locales/calendar.js +3 -3
- package/framework/modules/chui_i18n/locales/common.js +3 -3
- package/framework/modules/chui_i18n/locales/data.js +36 -26
- package/framework/modules/chui_i18n/locales/editors.js +40 -13
- package/framework/modules/chui_i18n/locales/feedback.js +3 -3
- package/framework/modules/chui_i18n/locales/forms.js +8 -8
- package/framework/modules/chui_i18n/locales/graphics.js +8 -8
- package/framework/modules/chui_i18n/locales/media.js +4 -4
- package/framework/modules/chui_i18n/locales/navigation.js +8 -8
- package/framework/modules/chui_i18n/locales/validate.js +3 -3
- package/framework/modules/chui_json/chui_json.js +9 -9
- package/framework/modules/chui_layout/chui_layout.js +12 -10
- package/framework/modules/chui_logger/chui_logger.js +29 -25
- package/framework/modules/chui_page/page.js +33 -27
- package/framework/modules/chui_qr/chui_qr.js +158 -67
- package/framework/modules/chui_scrollbar/chui_scrollbar.js +35 -24
- package/framework/modules/chui_scrollbar/styles.css +3 -1
- package/framework/modules/chui_services/chui_channels.js +27 -13
- package/framework/modules/chui_services/chui_services.js +39 -31
- package/framework/modules/chui_services/desktop.js +32 -31
- package/framework/modules/chui_sortable/chui_sortable.js +17 -12
- package/framework/modules/chui_validate/chui_validate.js +7 -4
- package/framework/tray_bar/chui_menu_items.js +136 -46
- package/index.d.ts +4814 -0
- package/index.js +385 -292
- package/package.json +79 -68
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
const {Animation} = require(
|
|
2
|
-
const {Calendar} = require(
|
|
3
|
-
const {Icon, Icons} = require(
|
|
4
|
-
const {makeKeyboardButton} = require(
|
|
5
|
-
const {I18n} = require(
|
|
6
|
-
const {dropdownPlacement} = require(
|
|
7
|
-
const {Validate} = require(
|
|
1
|
+
const { Animation } = require("../../../modules/chui_animations/animations");
|
|
2
|
+
const { Calendar } = require("../../chui_calendar/calendar");
|
|
3
|
+
const { Icon, Icons } = require("../../chui_icons/icons");
|
|
4
|
+
const { makeKeyboardButton } = require("../../../modules/chui_a11y/chui_a11y");
|
|
5
|
+
const { I18n } = require("../../../modules/chui_i18n/chui_i18n");
|
|
6
|
+
const { dropdownPlacement } = require("../../../modules/chui_functions");
|
|
7
|
+
const { Validate } = require("../../../modules/chui_validate/chui_validate");
|
|
8
8
|
|
|
9
9
|
const MONTHS_IN_YEAR = 12;
|
|
10
10
|
/** Сколько лет на одной странице выбора года */
|
|
@@ -13,50 +13,65 @@ const isDayNumber = (cell) => /^\d+$/.test(String(cell).trim());
|
|
|
13
13
|
|
|
14
14
|
class DateInput {
|
|
15
15
|
#id = require("randomstring").generate();
|
|
16
|
-
#chui_date_input = document.createElement(
|
|
17
|
-
#date_main_block = document.createElement(
|
|
18
|
-
#input = document.createElement(
|
|
19
|
-
#label = document.createElement(
|
|
20
|
-
#date_dropdown_open = document.createElement(
|
|
21
|
-
#date_dropdown_open_disabled = document.createElement(
|
|
22
|
-
#dropdown = document.createElement(
|
|
16
|
+
#chui_date_input = document.createElement("chui_date_input");
|
|
17
|
+
#date_main_block = document.createElement("date_main_block");
|
|
18
|
+
#input = document.createElement("input");
|
|
19
|
+
#label = document.createElement("label");
|
|
20
|
+
#date_dropdown_open = document.createElement("date_dropdown_open");
|
|
21
|
+
#date_dropdown_open_disabled = document.createElement("date_dropdown_open");
|
|
22
|
+
#dropdown = document.createElement("date_select_dropdown");
|
|
23
23
|
// Слушатель окна храним полем, чтобы можно было снять в destroy()
|
|
24
24
|
#window_click_event = (event) => {
|
|
25
25
|
if (!this.#date_main_block.contains(event.target)) this.#closeDropdown();
|
|
26
26
|
};
|
|
27
27
|
#dropdown_id = require("randomstring").generate();
|
|
28
28
|
#date_now = new Date();
|
|
29
|
-
#date_month_list = document.createElement(
|
|
30
|
-
#date_year_list = document.createElement(
|
|
31
|
-
#date_calendar_title = document.createElement(
|
|
29
|
+
#date_month_list = document.createElement("date_month_list");
|
|
30
|
+
#date_year_list = document.createElement("date_year_list");
|
|
31
|
+
#date_calendar_title = document.createElement("date_calendar_title");
|
|
32
32
|
#calendar_year = this.#date_now.getFullYear();
|
|
33
33
|
#calendar_month = this.#date_now.getMonth();
|
|
34
34
|
// Экран календаря: месяцы (по умолчанию) или выбор года
|
|
35
35
|
#view = "months";
|
|
36
36
|
constructor(options = { name: String(), title: String(), required: Boolean() }) {
|
|
37
|
-
require(
|
|
38
|
-
this.#input.type =
|
|
37
|
+
require("../../../modules/chui_functions").setStyles(__dirname + "/styles.css", "chUiJS_DateInput");
|
|
38
|
+
this.#input.type = "date";
|
|
39
39
|
this.#input.className = "date_input";
|
|
40
40
|
this.#input.id = this.#id;
|
|
41
41
|
if (options.name !== undefined) this.#input.name = options.name;
|
|
42
42
|
if (options.required !== undefined) this.#input.required = options.required;
|
|
43
43
|
// Валидация и показ ошибки: правила из options (required/pattern/…). Текст ошибки — в корень
|
|
44
44
|
// поля (под контролом), рамку получает сам контрол: подпись и поле — две строки одной колонки
|
|
45
|
-
Validate.installField(
|
|
46
|
-
|
|
47
|
-
|
|
45
|
+
Validate.installField(
|
|
46
|
+
this,
|
|
47
|
+
options,
|
|
48
|
+
this.#chui_date_input,
|
|
49
|
+
undefined,
|
|
50
|
+
() => this.#input.value,
|
|
51
|
+
this.#date_main_block
|
|
52
|
+
);
|
|
53
|
+
this.#date_dropdown_open.innerHTML = new Icon(
|
|
54
|
+
Icons.HARDWARE.KEYBOARD_ARROW_DOWN,
|
|
55
|
+
undefined,
|
|
56
|
+
"var(--blue_prime_background)"
|
|
57
|
+
).getHTML();
|
|
58
|
+
this.#date_dropdown_open_disabled.innerHTML = new Icon(
|
|
59
|
+
Icons.HARDWARE.KEYBOARD_ARROW_DOWN,
|
|
60
|
+
undefined,
|
|
61
|
+
"var(--text_color_disabled)"
|
|
62
|
+
).getHTML();
|
|
48
63
|
// Курсор выключенного поля даёт его контейнер (`.date_main_block_disabled`),
|
|
49
64
|
// курсор наследуется и на стрелку
|
|
50
65
|
if (options.title !== undefined) {
|
|
51
|
-
this.#label.classList.add(
|
|
66
|
+
this.#label.classList.add("date_input_label");
|
|
52
67
|
this.#label.innerText = options.title;
|
|
53
|
-
this.#label.setAttribute(
|
|
68
|
+
this.#label.setAttribute("for", this.#id);
|
|
54
69
|
this.#chui_date_input.appendChild(this.#label);
|
|
55
70
|
}
|
|
56
71
|
// Рамку с кольцом при фокусе рисует общее правило темы (`date_main_block:hover`,
|
|
57
72
|
// `:focus-within`), а не компонент: прежде он ставил то же самое инлайном,
|
|
58
73
|
// а на `blur` снимал весь атрибут `style`
|
|
59
|
-
this.#dropdown.setAttribute(
|
|
74
|
+
this.#dropdown.setAttribute("id", this.#dropdown_id);
|
|
60
75
|
// Доступность: поле — combobox, календарь — диалог с состоянием раскрытия
|
|
61
76
|
this.#input.setAttribute("role", "combobox");
|
|
62
77
|
this.#input.setAttribute("aria-haspopup", "dialog");
|
|
@@ -67,10 +82,13 @@ class DateInput {
|
|
|
67
82
|
// Клавиатура календаря: стрелки по дням, Enter выбирает, Escape закрывает
|
|
68
83
|
this.#dropdown.addEventListener("keydown", (event) => {
|
|
69
84
|
// Заголовок и список годов — свои кнопки: у них своя обработка Enter/Space
|
|
70
|
-
if (
|
|
71
|
-
|
|
85
|
+
if (
|
|
86
|
+
event.target instanceof Element &&
|
|
87
|
+
(event.target === this.#date_calendar_title || event.target.closest("date_year") !== null)
|
|
88
|
+
)
|
|
89
|
+
return;
|
|
72
90
|
const days = this.#visibleDays();
|
|
73
|
-
const current = days.findIndex(day => day === document.activeElement);
|
|
91
|
+
const current = days.findIndex((day) => day === document.activeElement);
|
|
74
92
|
if (event.key === "Escape") {
|
|
75
93
|
event.preventDefault();
|
|
76
94
|
this.#closeDropdown();
|
|
@@ -103,38 +121,38 @@ class DateInput {
|
|
|
103
121
|
this.#buildYear(this.#calendar_year);
|
|
104
122
|
this.#showMonth(this.#calendar_month);
|
|
105
123
|
//LISTENERS
|
|
106
|
-
this.#chui_date_input.addEventListener(
|
|
124
|
+
this.#chui_date_input.addEventListener("click", (event) => {
|
|
107
125
|
if (!this.#input.disabled) {
|
|
108
126
|
if (event.target.parentNode === this.#date_main_block) {
|
|
109
|
-
this.#input.focus()
|
|
127
|
+
this.#input.focus();
|
|
110
128
|
this.#openDropdown();
|
|
111
129
|
}
|
|
112
130
|
}
|
|
113
131
|
});
|
|
114
|
-
window.addEventListener(
|
|
132
|
+
window.addEventListener("click", this.#window_click_event);
|
|
115
133
|
this.#date_main_block.appendChild(this.#input);
|
|
116
134
|
this.#date_main_block.appendChild(this.#date_dropdown_open);
|
|
117
135
|
this.#date_main_block.appendChild(this.#dropdown);
|
|
118
136
|
this.#chui_date_input.appendChild(this.#date_main_block);
|
|
119
137
|
}
|
|
120
138
|
#buildCalendarHeader() {
|
|
121
|
-
const header = document.createElement(
|
|
122
|
-
const previous = document.createElement(
|
|
139
|
+
const header = document.createElement("date_calendar_header");
|
|
140
|
+
const previous = document.createElement("date_calendar_nav");
|
|
123
141
|
previous.setAttribute("role", "button");
|
|
124
142
|
previous.setAttribute("tabindex", "0");
|
|
125
143
|
previous.setAttribute("aria-label", I18n.t("date.previous"));
|
|
126
144
|
previous.innerHTML = new Icon(Icons.HARDWARE.KEYBOARD_ARROW_LEFT, undefined, "var(--text_color)").getHTML();
|
|
127
|
-
previous.addEventListener(
|
|
145
|
+
previous.addEventListener("click", (event) => {
|
|
128
146
|
event.stopPropagation();
|
|
129
147
|
this.#goBack();
|
|
130
148
|
});
|
|
131
149
|
makeKeyboardButton(previous);
|
|
132
|
-
const next = document.createElement(
|
|
150
|
+
const next = document.createElement("date_calendar_nav");
|
|
133
151
|
next.setAttribute("role", "button");
|
|
134
152
|
next.setAttribute("tabindex", "0");
|
|
135
153
|
next.setAttribute("aria-label", I18n.t("date.next"));
|
|
136
154
|
next.innerHTML = new Icon(Icons.HARDWARE.KEYBOARD_ARROW_RIGHT, undefined, "var(--text_color)").getHTML();
|
|
137
|
-
next.addEventListener(
|
|
155
|
+
next.addEventListener("click", (event) => {
|
|
138
156
|
event.stopPropagation();
|
|
139
157
|
this.#goForward();
|
|
140
158
|
});
|
|
@@ -230,22 +248,22 @@ class DateInput {
|
|
|
230
248
|
this.#buildYears();
|
|
231
249
|
}
|
|
232
250
|
#buildYear(year) {
|
|
233
|
-
this.#date_month_list.innerHTML =
|
|
251
|
+
this.#date_month_list.innerHTML = "";
|
|
234
252
|
for (let i = 0; i < MONTHS_IN_YEAR; i++) {
|
|
235
253
|
const cal = new Calendar(year, i + 1);
|
|
236
|
-
const date_month_main = document.createElement(
|
|
237
|
-
date_month_main.setAttribute(
|
|
238
|
-
date_month_main.setAttribute(
|
|
239
|
-
date_month_main.style.width =
|
|
254
|
+
const date_month_main = document.createElement("date_month_main");
|
|
255
|
+
date_month_main.setAttribute("month-name", cal.getMonthName());
|
|
256
|
+
date_month_main.setAttribute("month-index", String(cal.getMonth()));
|
|
257
|
+
date_month_main.style.width = "fit-content";
|
|
240
258
|
for (let row of cal.getCalendar()) {
|
|
241
|
-
const date_week = document.createElement(
|
|
259
|
+
const date_week = document.createElement("date_week");
|
|
242
260
|
let index = 0;
|
|
243
261
|
for (let cell of row) {
|
|
244
|
-
const date_day = document.createElement(
|
|
262
|
+
const date_day = document.createElement("date_day");
|
|
245
263
|
if (cell !== undefined) {
|
|
246
264
|
date_day.innerText = cell;
|
|
247
265
|
if (isDayNumber(cell)) {
|
|
248
|
-
date_day.classList =
|
|
266
|
+
date_day.classList = "date_day";
|
|
249
267
|
date_day.setAttribute("tabindex", "-1");
|
|
250
268
|
date_day.setAttribute("role", "button");
|
|
251
269
|
date_day.addEventListener("click", () => {
|
|
@@ -254,7 +272,7 @@ class DateInput {
|
|
|
254
272
|
// Выбор в календаре — такое же изменение значения, как правка в поле:
|
|
255
273
|
// без события слушатели (в том числе составные поля вроде
|
|
256
274
|
// DateTimeInput и DateRangeInput) о нём не узнали бы
|
|
257
|
-
this.#input.dispatchEvent(new Event("change", {bubbles: true}));
|
|
275
|
+
this.#input.dispatchEvent(new Event("change", { bubbles: true }));
|
|
258
276
|
this.#closeDropdown();
|
|
259
277
|
});
|
|
260
278
|
}
|
|
@@ -295,23 +313,27 @@ class DateInput {
|
|
|
295
313
|
}
|
|
296
314
|
/** Полное удаление: снять слушатели окна */
|
|
297
315
|
destroy() {
|
|
298
|
-
window.removeEventListener(
|
|
316
|
+
window.removeEventListener("click", this.#window_click_event);
|
|
299
317
|
this.#closeDropdown();
|
|
300
318
|
}
|
|
301
319
|
// Дни текущего видимого месяца (по ним ходят стрелки)
|
|
302
320
|
#visibleDays() {
|
|
303
|
-
const month = this.#date_month_list.querySelector(
|
|
321
|
+
const month = this.#date_month_list.querySelector(
|
|
322
|
+
'date_month_main[month-index="' + this.#calendar_month + '"]'
|
|
323
|
+
);
|
|
304
324
|
if (month === null) return [];
|
|
305
|
-
return [...month.querySelectorAll("date_day")].filter(day => day.classList.contains("date_day"));
|
|
325
|
+
return [...month.querySelectorAll("date_day")].filter((day) => day.classList.contains("date_day"));
|
|
306
326
|
}
|
|
307
327
|
#showMonth(index) {
|
|
308
328
|
this.#calendar_month = index;
|
|
309
|
-
const months = this.#date_month_list.querySelectorAll(
|
|
329
|
+
const months = this.#date_month_list.querySelectorAll("date_month_main");
|
|
310
330
|
for (let month of months) {
|
|
311
|
-
month.style.display = Number(month.getAttribute(
|
|
331
|
+
month.style.display = Number(month.getAttribute("month-index")) === index ? "block" : "none";
|
|
312
332
|
}
|
|
313
|
-
this.#date_calendar_title.innerText =
|
|
314
|
-
.toLocaleString(I18n.getLocale(), {month:
|
|
333
|
+
this.#date_calendar_title.innerText =
|
|
334
|
+
new Date(this.#calendar_year, index).toLocaleString(I18n.getLocale(), { month: "long" }).toUpperCase() +
|
|
335
|
+
" " +
|
|
336
|
+
this.#calendar_year;
|
|
315
337
|
}
|
|
316
338
|
#goToMonth(delta) {
|
|
317
339
|
let month = this.#calendar_month + delta;
|
|
@@ -329,30 +351,44 @@ class DateInput {
|
|
|
329
351
|
}
|
|
330
352
|
this.#showMonth(month);
|
|
331
353
|
}
|
|
332
|
-
getName() {
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
354
|
+
getName() {
|
|
355
|
+
return this.#input.name;
|
|
356
|
+
}
|
|
357
|
+
getTitle() {
|
|
358
|
+
return this.#label.innerText;
|
|
359
|
+
}
|
|
360
|
+
getValue() {
|
|
361
|
+
return this.#input.value;
|
|
362
|
+
}
|
|
363
|
+
setValue(date = String()) {
|
|
364
|
+
this.#input.value = date;
|
|
365
|
+
}
|
|
336
366
|
setDisabled(boolean = Boolean()) {
|
|
337
|
-
this.#input.disabled = boolean
|
|
367
|
+
this.#input.disabled = boolean;
|
|
338
368
|
if (boolean) {
|
|
339
|
-
this.#date_main_block.classList.add("date_main_block_disabled")
|
|
340
|
-
this.#input.className = "date_input_disabled"
|
|
341
|
-
this.#label.className = "date_input_label_disabled"
|
|
369
|
+
this.#date_main_block.classList.add("date_main_block_disabled");
|
|
370
|
+
this.#input.className = "date_input_disabled";
|
|
371
|
+
this.#label.className = "date_input_label_disabled";
|
|
342
372
|
this.#date_dropdown_open.remove();
|
|
343
373
|
this.#date_main_block.appendChild(this.#date_dropdown_open_disabled);
|
|
344
374
|
} else {
|
|
345
|
-
this.#date_main_block.classList.remove("date_main_block_disabled")
|
|
346
|
-
this.#input.className = "date_input"
|
|
347
|
-
this.#label.className = "date_input_label"
|
|
375
|
+
this.#date_main_block.classList.remove("date_main_block_disabled");
|
|
376
|
+
this.#input.className = "date_input";
|
|
377
|
+
this.#label.className = "date_input_label";
|
|
348
378
|
this.#date_dropdown_open_disabled.remove();
|
|
349
379
|
this.#date_main_block.appendChild(this.#date_dropdown_open);
|
|
350
380
|
}
|
|
351
381
|
}
|
|
352
|
-
set() {
|
|
382
|
+
set() {
|
|
383
|
+
return this.#chui_date_input;
|
|
384
|
+
}
|
|
353
385
|
}
|
|
354
386
|
|
|
355
387
|
const formatLocalDate = (date) =>
|
|
356
|
-
date.getFullYear() +
|
|
388
|
+
date.getFullYear() +
|
|
389
|
+
"-" +
|
|
390
|
+
String(date.getMonth() + 1).padStart(2, "0") +
|
|
391
|
+
"-" +
|
|
392
|
+
String(date.getDate()).padStart(2, "0");
|
|
357
393
|
|
|
358
|
-
exports.DateInput = DateInput
|
|
394
|
+
exports.DateInput = DateInput;
|
|
@@ -15,13 +15,13 @@ chui_date_input {
|
|
|
15
15
|
/* Нативные части поля даты: индикатор календаря не нужен (календарь свой, значок — тоже),
|
|
16
16
|
а поля ввода даты собираются в одну строку. Правила только для своего поля: без области
|
|
17
17
|
они прятали бы чужие нативные поля ввода во всём приложении. */
|
|
18
|
-
chui_date_input input[type=date]::-webkit-calendar-picker-indicator {
|
|
19
|
-
display: none
|
|
18
|
+
chui_date_input input[type="date"]::-webkit-calendar-picker-indicator {
|
|
19
|
+
display: none;
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
chui_date_input input[type=date]::-webkit-datetime-edit-text {
|
|
22
|
+
chui_date_input input[type="date"]::-webkit-datetime-edit-text {
|
|
23
23
|
padding: 0;
|
|
24
|
-
width: 100
|
|
24
|
+
width: 100%;
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
date_select_dropdown {
|
|
@@ -137,7 +137,7 @@ date_day {
|
|
|
137
137
|
width: 20px;
|
|
138
138
|
border-radius: var(--border_radius);
|
|
139
139
|
padding: var(--control_padding);
|
|
140
|
-
text-align: center
|
|
140
|
+
text-align: center;
|
|
141
141
|
}
|
|
142
142
|
|
|
143
143
|
.date_day:hover {
|
|
@@ -154,12 +154,13 @@ date_dropdown_open {
|
|
|
154
154
|
cursor: pointer;
|
|
155
155
|
box-sizing: border-box;
|
|
156
156
|
height: 100%;
|
|
157
|
-
padding-block: 0 0;
|
|
157
|
+
padding-block: 0 0;
|
|
158
|
+
padding-inline: 0 10px;
|
|
158
159
|
margin: 0;
|
|
159
160
|
display: inline-flex;
|
|
160
161
|
justify-content: center;
|
|
161
162
|
align-items: center;
|
|
162
|
-
color: var(--badge_cancel_text)
|
|
163
|
+
color: var(--badge_cancel_text);
|
|
163
164
|
}
|
|
164
165
|
|
|
165
166
|
date_main_block {
|
|
@@ -196,8 +197,8 @@ date_main_block {
|
|
|
196
197
|
width: max-content;
|
|
197
198
|
margin: 0 0 var(--margin);
|
|
198
199
|
font-size: var(--font_labels_size);
|
|
199
|
-
font-weight:500;
|
|
200
|
-
color: var(--text_color)
|
|
200
|
+
font-weight: 500;
|
|
201
|
+
color: var(--text_color);
|
|
201
202
|
}
|
|
202
203
|
|
|
203
204
|
/* DISABLED STYLES */
|
|
@@ -214,7 +215,7 @@ date_main_block {
|
|
|
214
215
|
width: max-content;
|
|
215
216
|
margin: 0 0 var(--margin);
|
|
216
217
|
font-size: var(--font_labels_size);
|
|
217
|
-
font-weight:500
|
|
218
|
+
font-weight: 500;
|
|
218
219
|
}
|
|
219
220
|
|
|
220
221
|
.date_input_disabled {
|
|
@@ -230,4 +231,4 @@ date_main_block {
|
|
|
230
231
|
background: transparent;
|
|
231
232
|
border: none;
|
|
232
233
|
font-size: var(--font_default_size);
|
|
233
|
-
}
|
|
234
|
+
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
const {setStyles} = require(
|
|
2
|
-
const {DateInput} = require(
|
|
3
|
-
const {Icon, Icons} = require(
|
|
4
|
-
const {Validate} = require(
|
|
5
|
-
const {I18n} = require(
|
|
1
|
+
const { setStyles } = require("../../../modules/chui_functions");
|
|
2
|
+
const { DateInput } = require("../chui_date/date");
|
|
3
|
+
const { Icon, Icons } = require("../../chui_icons/icons");
|
|
4
|
+
const { Validate } = require("../../../modules/chui_validate/chui_validate");
|
|
5
|
+
const { I18n } = require("../../../modules/chui_i18n/chui_i18n");
|
|
6
6
|
|
|
7
7
|
// Значение пары для правил — «начало..конец»: так его видит `validate()`
|
|
8
8
|
const RANGE_PATTERN = "^[0-9]{4}-[0-9]{2}-[0-9]{2}\\.\\.[0-9]{4}-[0-9]{2}-[0-9]{2}$";
|
|
@@ -54,19 +54,21 @@ class DateRangeInput {
|
|
|
54
54
|
#listeners = [];
|
|
55
55
|
#on_change = undefined;
|
|
56
56
|
|
|
57
|
-
constructor(
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
57
|
+
constructor(
|
|
58
|
+
options = {
|
|
59
|
+
id: String(),
|
|
60
|
+
name: String(),
|
|
61
|
+
title: String(),
|
|
62
|
+
label: String(),
|
|
63
|
+
startTitle: String(),
|
|
64
|
+
endTitle: String(),
|
|
65
|
+
separator: undefined,
|
|
66
|
+
value: undefined,
|
|
67
|
+
disabled: Boolean(),
|
|
68
|
+
changeListener: undefined,
|
|
69
|
+
onChange: undefined,
|
|
70
|
+
}
|
|
71
|
+
) {
|
|
70
72
|
setStyles(__dirname + "/styles.css", "chUiJS_DateRangeInput");
|
|
71
73
|
DateRangeInput.#counter += 1;
|
|
72
74
|
this.#id = options.id === undefined ? `chui_date_range_input_${DateRangeInput.#counter}` : options.id;
|
|
@@ -74,15 +76,20 @@ class DateRangeInput {
|
|
|
74
76
|
this.#label_text = options.label;
|
|
75
77
|
this.#on_change = options.onChange;
|
|
76
78
|
if (options.changeListener !== undefined) this.addChangeListener(options.changeListener);
|
|
77
|
-
if (options.messages !== undefined && options.messages.validate !== undefined)
|
|
79
|
+
if (options.messages !== undefined && options.messages.validate !== undefined)
|
|
80
|
+
this.#ordering_message = String(options.messages.validate);
|
|
78
81
|
// Общий текст берётся из словаря: своё сообщение поля важнее перевода
|
|
79
82
|
if (this.#ordering_message === undefined) this.#ordering_message = I18n.t("dateRange.wrongOrder");
|
|
80
83
|
this.#root.id = this.#id;
|
|
81
84
|
this.#label.className = "date_range_label";
|
|
82
85
|
this.#row.className = "date_range_row";
|
|
83
86
|
this.#row.setAttribute("role", "group");
|
|
84
|
-
this.#start = new DateInput({
|
|
85
|
-
|
|
87
|
+
this.#start = new DateInput({
|
|
88
|
+
title: options.startTitle === undefined ? I18n.t("dateRange.start") : options.startTitle,
|
|
89
|
+
});
|
|
90
|
+
this.#end = new DateInput({
|
|
91
|
+
title: options.endTitle === undefined ? I18n.t("dateRange.end") : options.endTitle,
|
|
92
|
+
});
|
|
86
93
|
this.#separator.className = "date_range_separator";
|
|
87
94
|
this.#separator.setAttribute("aria-hidden", "true");
|
|
88
95
|
const glyph = new Icon(options.separator === undefined ? Icons.NAVIGATION.EAST : options.separator).set();
|
|
@@ -102,9 +109,13 @@ class DateRangeInput {
|
|
|
102
109
|
this.#root.appendChild(this.#label);
|
|
103
110
|
this.#root.appendChild(this.#row);
|
|
104
111
|
this.#root.appendChild(this.#status);
|
|
105
|
-
this.setLabel(
|
|
106
|
-
|
|
107
|
-
|
|
112
|
+
this.setLabel(
|
|
113
|
+
options.label === undefined
|
|
114
|
+
? options.title === undefined
|
|
115
|
+
? I18n.t("dateRange.label")
|
|
116
|
+
: options.title
|
|
117
|
+
: options.label
|
|
118
|
+
);
|
|
108
119
|
const rules = Validate.rulesFrom(options);
|
|
109
120
|
// У поля даты min/max — это не границы Validate, а порядок пары
|
|
110
121
|
delete rules.min;
|
|
@@ -144,7 +155,7 @@ class DateRangeInput {
|
|
|
144
155
|
|
|
145
156
|
/** Период: строки «ГГГГ-ММ-ДД», пустая строка — дата не выбрана */
|
|
146
157
|
getValue() {
|
|
147
|
-
return {start: this.#start.getValue(), end: this.#end.getValue()};
|
|
158
|
+
return { start: this.#start.getValue(), end: this.#end.getValue() };
|
|
148
159
|
}
|
|
149
160
|
|
|
150
161
|
getStart() {
|
|
@@ -161,8 +172,8 @@ class DateRangeInput {
|
|
|
161
172
|
const start = DateRangeInput.#display(value.start);
|
|
162
173
|
const end = DateRangeInput.#display(value.end);
|
|
163
174
|
if (start === "" && end === "") return I18n.t("dateRange.empty");
|
|
164
|
-
if (start === "") return I18n.t("dateRange.to", {end: end});
|
|
165
|
-
if (end === "") return I18n.t("dateRange.from", {start: start});
|
|
175
|
+
if (start === "") return I18n.t("dateRange.to", { end: end });
|
|
176
|
+
if (end === "") return I18n.t("dateRange.from", { start: start });
|
|
166
177
|
return `${start} — ${end}`;
|
|
167
178
|
}
|
|
168
179
|
|
|
@@ -215,7 +226,7 @@ class DateRangeInput {
|
|
|
215
226
|
this.#syncLimits();
|
|
216
227
|
return this;
|
|
217
228
|
}
|
|
218
|
-
const pair = Array.isArray(value) ? {start: value[0], end: value[1]} : value;
|
|
229
|
+
const pair = Array.isArray(value) ? { start: value[0], end: value[1] } : value;
|
|
219
230
|
const start = DateRangeInput.#parseDate(pair.start);
|
|
220
231
|
const end = DateRangeInput.#parseDate(pair.end);
|
|
221
232
|
if (start === undefined || end === undefined) {
|
|
@@ -319,4 +330,4 @@ class DateRangeInput {
|
|
|
319
330
|
}
|
|
320
331
|
}
|
|
321
332
|
|
|
322
|
-
exports.DateRangeInput = DateRangeInput
|
|
333
|
+
exports.DateRangeInput = DateRangeInput;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
const {setStyles} = require(
|
|
2
|
-
const {DateInput} = require(
|
|
3
|
-
const {TimeInput} = require(
|
|
4
|
-
const {Validate} = require(
|
|
5
|
-
const {I18n} = require(
|
|
1
|
+
const { setStyles } = require("../../../modules/chui_functions");
|
|
2
|
+
const { DateInput } = require("../chui_date/date");
|
|
3
|
+
const { TimeInput } = require("../chui_time/time");
|
|
4
|
+
const { Validate } = require("../../../modules/chui_validate/chui_validate");
|
|
5
|
+
const { I18n } = require("../../../modules/chui_i18n/chui_i18n");
|
|
6
6
|
|
|
7
7
|
// Значение поля — «ГГГГ-ММ-ДДTЧЧ:ММ»: тот же вид, что у нативного datetime-local,
|
|
8
8
|
// и такой же однозначный для сравнений (ширина всех частей постоянная)
|
|
@@ -51,21 +51,23 @@ class DateTimeInput {
|
|
|
51
51
|
#listeners = [];
|
|
52
52
|
#on_change = undefined;
|
|
53
53
|
|
|
54
|
-
constructor(
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
54
|
+
constructor(
|
|
55
|
+
options = {
|
|
56
|
+
id: String(),
|
|
57
|
+
name: String(),
|
|
58
|
+
title: String(),
|
|
59
|
+
label: String(),
|
|
60
|
+
dateTitle: String(),
|
|
61
|
+
timeTitle: String(),
|
|
62
|
+
value: undefined,
|
|
63
|
+
step: Number(),
|
|
64
|
+
min: String(),
|
|
65
|
+
max: String(),
|
|
66
|
+
disabled: Boolean(),
|
|
67
|
+
changeListener: undefined,
|
|
68
|
+
onChange: undefined,
|
|
69
|
+
}
|
|
70
|
+
) {
|
|
69
71
|
setStyles(__dirname + "/styles.css", "chUiJS_DateTimeInput");
|
|
70
72
|
DateTimeInput.#counter += 1;
|
|
71
73
|
this.#id = options.id === undefined ? `chui_datetime_input_${DateTimeInput.#counter}` : options.id;
|
|
@@ -80,7 +82,9 @@ class DateTimeInput {
|
|
|
80
82
|
this.#row.className = "datetime_row";
|
|
81
83
|
// Группа: у пары полей должно быть общее имя, иначе они читаются как два отдельных поля
|
|
82
84
|
this.#row.setAttribute("role", "group");
|
|
83
|
-
this.#date = new DateInput({
|
|
85
|
+
this.#date = new DateInput({
|
|
86
|
+
title: options.dateTitle === undefined ? I18n.t("date.label") : options.dateTitle,
|
|
87
|
+
});
|
|
84
88
|
this.#time = new TimeInput({
|
|
85
89
|
title: options.timeTitle === undefined ? I18n.t("time.label") : options.timeTitle,
|
|
86
90
|
step: options.step,
|
|
@@ -93,9 +97,13 @@ class DateTimeInput {
|
|
|
93
97
|
else this.#label.hidden = true;
|
|
94
98
|
this.#root.appendChild(this.#label);
|
|
95
99
|
this.#root.appendChild(this.#row);
|
|
96
|
-
this.setLabel(
|
|
97
|
-
|
|
98
|
-
|
|
100
|
+
this.setLabel(
|
|
101
|
+
options.label === undefined
|
|
102
|
+
? options.title === undefined
|
|
103
|
+
? I18n.t("dateTime.label")
|
|
104
|
+
: options.title
|
|
105
|
+
: options.label
|
|
106
|
+
);
|
|
99
107
|
// `min`/`max` как числа здесь не работают: у поля времени это окно, а не границы Validate
|
|
100
108
|
const rules = Validate.rulesFrom(options);
|
|
101
109
|
delete rules.min;
|
|
@@ -106,8 +114,8 @@ class DateTimeInput {
|
|
|
106
114
|
const custom = own_validate === undefined ? undefined : own_validate(value);
|
|
107
115
|
if (custom !== undefined && custom !== null && custom !== true) return custom;
|
|
108
116
|
const moment = String(value);
|
|
109
|
-
if (this.#min !== undefined && moment < this.#min) return I18n.t("dateTime.min", {min: this.#min});
|
|
110
|
-
if (this.#max !== undefined && moment > this.#max) return I18n.t("dateTime.max", {max: this.#max});
|
|
117
|
+
if (this.#min !== undefined && moment < this.#min) return I18n.t("dateTime.min", { min: this.#min });
|
|
118
|
+
if (this.#max !== undefined && moment > this.#max) return I18n.t("dateTime.max", { max: this.#max });
|
|
111
119
|
return undefined;
|
|
112
120
|
};
|
|
113
121
|
Validate.installField(this, rules, this.#root, undefined, () => this.#rawValue(), this.#row);
|
|
@@ -292,4 +300,4 @@ class DateTimeInput {
|
|
|
292
300
|
}
|
|
293
301
|
}
|
|
294
302
|
|
|
295
|
-
exports.DateTimeInput = DateTimeInput
|
|
303
|
+
exports.DateTimeInput = DateTimeInput;
|