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,5 +1,5 @@
|
|
|
1
|
-
const {RadioButton} = require("../chui_inputs/chui_radio_button/radio_button");
|
|
2
|
-
const {Validate} = require("../../modules/chui_validate/chui_validate");
|
|
1
|
+
const { RadioButton } = require("../chui_inputs/chui_radio_button/radio_button");
|
|
2
|
+
const { Validate } = require("../../modules/chui_validate/chui_validate");
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Группа радиокнопок из массива опций.
|
|
@@ -16,8 +16,8 @@ class RadioGroup {
|
|
|
16
16
|
static #FOCUSABLE = "input[type=radio]:not([disabled])";
|
|
17
17
|
#id = require("randomstring").generate();
|
|
18
18
|
#name = require("randomstring").generate();
|
|
19
|
-
#RadioGroup = document.createElement(
|
|
20
|
-
#groupForm = document.createElement(
|
|
19
|
+
#RadioGroup = document.createElement("chui_radio_group");
|
|
20
|
+
#groupForm = document.createElement("form");
|
|
21
21
|
#options = [];
|
|
22
22
|
#label = undefined;
|
|
23
23
|
#disabled = false;
|
|
@@ -27,23 +27,25 @@ class RadioGroup {
|
|
|
27
27
|
#align = undefined;
|
|
28
28
|
#justify = undefined;
|
|
29
29
|
#width = undefined;
|
|
30
|
-
constructor(
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
30
|
+
constructor(
|
|
31
|
+
options = {
|
|
32
|
+
styles: {
|
|
33
|
+
direction: undefined,
|
|
34
|
+
wrap: undefined,
|
|
35
|
+
align: undefined,
|
|
36
|
+
justify: undefined,
|
|
37
|
+
width: undefined,
|
|
38
|
+
},
|
|
39
|
+
label: String(),
|
|
40
|
+
name: String(),
|
|
41
|
+
}
|
|
42
|
+
) {
|
|
43
|
+
require("../../modules/chui_functions").setStyles(__dirname + "/styles.css", "chUiJS_RadioGroup");
|
|
42
44
|
// Правила (required/pattern/validate/…) читает общий модуль: группа — такое же поле, как input
|
|
43
45
|
Validate.installField(this, options, this.#RadioGroup, undefined, () => this.getValue());
|
|
44
46
|
// styles может не прийти вовсе: раньше обращение к options.styles.direction падало
|
|
45
47
|
const styles = options.styles === undefined ? {} : options.styles;
|
|
46
|
-
this.#groupForm.classList.add(
|
|
48
|
+
this.#groupForm.classList.add("radioGroupForm");
|
|
47
49
|
this.#direction = styles.direction;
|
|
48
50
|
this.#wrap = styles.wrap;
|
|
49
51
|
this.#align = styles.align;
|
|
@@ -63,11 +65,15 @@ class RadioGroup {
|
|
|
63
65
|
this.#RadioGroup.setAttribute("role", "radiogroup");
|
|
64
66
|
if (Validate.rulesFrom(options).required === true) this.#RadioGroup.setAttribute("aria-required", "true");
|
|
65
67
|
this.setLabel(options.label);
|
|
66
|
-
this.#RadioGroup.appendChild(this.#groupForm)
|
|
68
|
+
this.#RadioGroup.appendChild(this.#groupForm);
|
|
67
69
|
}
|
|
68
70
|
/** Имя группы: общее `name` всех флажков */
|
|
69
|
-
getName() {
|
|
70
|
-
|
|
71
|
+
getName() {
|
|
72
|
+
return this.#name;
|
|
73
|
+
}
|
|
74
|
+
getLabel() {
|
|
75
|
+
return this.#label;
|
|
76
|
+
}
|
|
71
77
|
setLabel(text = String()) {
|
|
72
78
|
this.#label = text === undefined || text === "" ? undefined : text;
|
|
73
79
|
if (this.#label === undefined) this.#RadioGroup.removeAttribute("aria-label");
|
|
@@ -75,7 +81,9 @@ class RadioGroup {
|
|
|
75
81
|
return this;
|
|
76
82
|
}
|
|
77
83
|
/** Описания добавленных вариантов (копии) */
|
|
78
|
-
getOptions() {
|
|
84
|
+
getOptions() {
|
|
85
|
+
return this.#options.map((option) => ({ ...option }));
|
|
86
|
+
}
|
|
79
87
|
addOptions(options = [{ name: String(), value: String(), disabled: Boolean(), checked: Boolean() }]) {
|
|
80
88
|
for (const option of options) {
|
|
81
89
|
const radio = new RadioButton({
|
|
@@ -83,16 +91,16 @@ class RadioGroup {
|
|
|
83
91
|
stringValue: option.value,
|
|
84
92
|
name: this.#name,
|
|
85
93
|
value: option.checked === true,
|
|
86
|
-
width: option.width
|
|
94
|
+
width: option.width,
|
|
87
95
|
});
|
|
88
96
|
if (option.disabled === true) radio.setDisabled(true);
|
|
89
97
|
this.#groupForm.appendChild(radio.set());
|
|
90
|
-
this.#options.push({name: option.name, value: option.value, disabled: option.disabled === true});
|
|
98
|
+
this.#options.push({ name: option.name, value: option.value, disabled: option.disabled === true });
|
|
91
99
|
}
|
|
92
100
|
return this;
|
|
93
101
|
}
|
|
94
102
|
addChangeListener(listener = () => {}) {
|
|
95
|
-
this.#groupForm.addEventListener("change", listener)
|
|
103
|
+
this.#groupForm.addEventListener("change", listener);
|
|
96
104
|
return this;
|
|
97
105
|
}
|
|
98
106
|
/** Выбранное значение или `undefined`, если не выбрано ничего */
|
|
@@ -115,7 +123,9 @@ class RadioGroup {
|
|
|
115
123
|
for (const input of this.#groupForm.querySelectorAll("input[type=radio]")) input.checked = false;
|
|
116
124
|
return this;
|
|
117
125
|
}
|
|
118
|
-
getDisabled() {
|
|
126
|
+
getDisabled() {
|
|
127
|
+
return this.#disabled;
|
|
128
|
+
}
|
|
119
129
|
setDisabled(boolean = Boolean()) {
|
|
120
130
|
this.#disabled = boolean === true;
|
|
121
131
|
// Индивидуальный запрет варианта не снимается: группа лишь добавляет свой
|
|
@@ -142,4 +152,4 @@ class RadioGroup {
|
|
|
142
152
|
}
|
|
143
153
|
}
|
|
144
154
|
|
|
145
|
-
exports.RadioGroup = RadioGroup
|
|
155
|
+
exports.RadioGroup = RadioGroup;
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
const {setStyles, optionOr} = require(
|
|
2
|
-
const {Icon, Icons} = require(
|
|
3
|
-
const {I18n} = require(
|
|
1
|
+
const { setStyles, optionOr } = require("../../modules/chui_functions");
|
|
2
|
+
const { Icon, Icons } = require("../chui_icons/icons");
|
|
3
|
+
const { I18n } = require("../../modules/chui_i18n/chui_i18n");
|
|
4
4
|
|
|
5
5
|
/** Значок состояния — та же семья, что у Alert, Toast и Notification */
|
|
6
6
|
const STYLE_ICONS = {
|
|
7
7
|
result_info: Icons.ACTIONS.INFO,
|
|
8
8
|
result_success: Icons.ACTIONS.CHECK_CIRCLE,
|
|
9
9
|
result_warning: Icons.ALERT.WARNING,
|
|
10
|
-
result_error: Icons.ALERT.ERROR
|
|
10
|
+
result_error: Icons.ALERT.ERROR,
|
|
11
11
|
};
|
|
12
12
|
|
|
13
13
|
/**
|
|
@@ -39,11 +39,11 @@ class Result {
|
|
|
39
39
|
INFO: "result_info",
|
|
40
40
|
SUCCESS: "result_success",
|
|
41
41
|
WARNING: "result_warning",
|
|
42
|
-
ERROR: "result_error"
|
|
42
|
+
ERROR: "result_error",
|
|
43
43
|
};
|
|
44
44
|
static SIZE = {
|
|
45
45
|
DEFAULT: "default",
|
|
46
|
-
COMPACT: "compact"
|
|
46
|
+
COMPACT: "compact",
|
|
47
47
|
};
|
|
48
48
|
static #counter = 0;
|
|
49
49
|
|
|
@@ -53,7 +53,7 @@ class Result {
|
|
|
53
53
|
result_info: I18n.t("feedback.resultInfo"),
|
|
54
54
|
result_success: I18n.t("feedback.resultSuccess"),
|
|
55
55
|
result_warning: I18n.t("feedback.resultWarning"),
|
|
56
|
-
result_error: I18n.t("feedback.resultError")
|
|
56
|
+
result_error: I18n.t("feedback.resultError"),
|
|
57
57
|
};
|
|
58
58
|
}
|
|
59
59
|
|
|
@@ -68,11 +68,18 @@ class Result {
|
|
|
68
68
|
#title_hidden = false;
|
|
69
69
|
#icon_custom = undefined;
|
|
70
70
|
|
|
71
|
-
constructor(
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
71
|
+
constructor(
|
|
72
|
+
options = {
|
|
73
|
+
id: String(),
|
|
74
|
+
style: String(),
|
|
75
|
+
icon: undefined,
|
|
76
|
+
title: undefined,
|
|
77
|
+
description: String(),
|
|
78
|
+
actions: [],
|
|
79
|
+
label: String(),
|
|
80
|
+
size: String(),
|
|
81
|
+
}
|
|
82
|
+
) {
|
|
76
83
|
setStyles(__dirname + "/styles.css", "chUiJS_Result");
|
|
77
84
|
Result.#counter += 1;
|
|
78
85
|
this.#id = optionOr(options.id, `chui_result_${Result.#counter}`);
|
|
@@ -156,9 +163,12 @@ class Result {
|
|
|
156
163
|
this.#renderStyleIcon();
|
|
157
164
|
return this;
|
|
158
165
|
}
|
|
159
|
-
this.#icon_custom =
|
|
160
|
-
|
|
161
|
-
|
|
166
|
+
this.#icon_custom =
|
|
167
|
+
typeof icon === "string"
|
|
168
|
+
? new Icon(icon, "36px").set()
|
|
169
|
+
: typeof icon.set === "function"
|
|
170
|
+
? icon.set()
|
|
171
|
+
: icon;
|
|
162
172
|
this.#icon.innerHTML = "";
|
|
163
173
|
this.#icon.appendChild(this.#icon_custom);
|
|
164
174
|
return this;
|
|
@@ -224,4 +234,4 @@ class Result {
|
|
|
224
234
|
}
|
|
225
235
|
}
|
|
226
236
|
|
|
227
|
-
exports.Result = Result
|
|
237
|
+
exports.Result = Result;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
const {setStyles, optionOr} = require(
|
|
2
|
-
const {I18n} = require(
|
|
1
|
+
const { setStyles, optionOr } = require("../../modules/chui_functions");
|
|
2
|
+
const { I18n } = require("../../modules/chui_i18n/chui_i18n");
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Расписание: сетка времени по дням с событиями.
|
|
@@ -36,7 +36,7 @@ const {I18n} = require('../../modules/chui_i18n/chui_i18n');
|
|
|
36
36
|
class Scheduler {
|
|
37
37
|
static VIEW = {
|
|
38
38
|
DAY: "day",
|
|
39
|
-
WEEK: "week"
|
|
39
|
+
WEEK: "week",
|
|
40
40
|
};
|
|
41
41
|
static DEFAULT_HOUR_HEIGHT = 48;
|
|
42
42
|
static DEFAULT_SLOT_MINUTES = 30;
|
|
@@ -67,22 +67,24 @@ class Scheduler {
|
|
|
67
67
|
#on_slot_click = undefined;
|
|
68
68
|
#on_period_change = undefined;
|
|
69
69
|
|
|
70
|
-
constructor(
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
70
|
+
constructor(
|
|
71
|
+
options = {
|
|
72
|
+
id: String(),
|
|
73
|
+
date: undefined,
|
|
74
|
+
view: String(),
|
|
75
|
+
events: [],
|
|
76
|
+
startHour: Number(),
|
|
77
|
+
endHour: Number(),
|
|
78
|
+
slotMinutes: Number(),
|
|
79
|
+
hourHeight: Number(),
|
|
80
|
+
firstDay: Number(),
|
|
81
|
+
height: String(),
|
|
82
|
+
label: String(),
|
|
83
|
+
onEventClick: undefined,
|
|
84
|
+
onSlotClick: undefined,
|
|
85
|
+
onPeriodChange: undefined,
|
|
86
|
+
}
|
|
87
|
+
) {
|
|
86
88
|
setStyles(__dirname + "/styles.css", "chUiJS_Scheduler");
|
|
87
89
|
Scheduler.#counter += 1;
|
|
88
90
|
this.#id = options.id === undefined ? `chui_scheduler_${Scheduler.#counter}` : options.id;
|
|
@@ -129,7 +131,7 @@ class Scheduler {
|
|
|
129
131
|
/** Начало и конец показанного периода (включительно) */
|
|
130
132
|
getRange() {
|
|
131
133
|
const days = this.#dayDates();
|
|
132
|
-
return {from: days[0], to: days[days.length - 1]};
|
|
134
|
+
return { from: days[0], to: days[days.length - 1] };
|
|
133
135
|
}
|
|
134
136
|
|
|
135
137
|
getEvents() {
|
|
@@ -250,7 +252,11 @@ class Scheduler {
|
|
|
250
252
|
}
|
|
251
253
|
|
|
252
254
|
static #sameDay(left = new Date(), right = new Date()) {
|
|
253
|
-
return
|
|
255
|
+
return (
|
|
256
|
+
left.getFullYear() === right.getFullYear() &&
|
|
257
|
+
left.getMonth() === right.getMonth() &&
|
|
258
|
+
left.getDate() === right.getDate()
|
|
259
|
+
);
|
|
254
260
|
}
|
|
255
261
|
|
|
256
262
|
static #eventDate(event = Object(), key = "start") {
|
|
@@ -268,7 +274,7 @@ class Scheduler {
|
|
|
268
274
|
#dayDates() {
|
|
269
275
|
const start = this.#startOfPeriod();
|
|
270
276
|
const count = this.#view === Scheduler.VIEW.DAY ? 1 : 7;
|
|
271
|
-
return Array.from({length: count}, (_, index) => {
|
|
277
|
+
return Array.from({ length: count }, (_, index) => {
|
|
272
278
|
const day = new Date(start);
|
|
273
279
|
day.setDate(start.getDate() + index);
|
|
274
280
|
return day;
|
|
@@ -318,7 +324,7 @@ class Scheduler {
|
|
|
318
324
|
from = Math.max(from, dayStart);
|
|
319
325
|
to = Math.min(to, dayEnd);
|
|
320
326
|
if (to <= from) continue;
|
|
321
|
-
items.push({event: event, index: this.#events.indexOf(event), start: from, end: to, lane: 0, lanes: 1});
|
|
327
|
+
items.push({ event: event, index: this.#events.indexOf(event), start: from, end: to, lane: 0, lanes: 1 });
|
|
322
328
|
}
|
|
323
329
|
items.sort((left, right) => left.start - right.start || left.end - right.end);
|
|
324
330
|
// Кластеры пересекающихся событий и дорожки внутри них
|
|
@@ -375,7 +381,10 @@ class Scheduler {
|
|
|
375
381
|
const views = document.createElement("scheduler_views");
|
|
376
382
|
views.setAttribute("role", "group");
|
|
377
383
|
views.setAttribute("aria-label", I18n.t("scheduler.view"));
|
|
378
|
-
for (const [view, label] of [
|
|
384
|
+
for (const [view, label] of [
|
|
385
|
+
[Scheduler.VIEW.DAY, I18n.t("scheduler.day")],
|
|
386
|
+
[Scheduler.VIEW.WEEK, I18n.t("scheduler.week")],
|
|
387
|
+
]) {
|
|
379
388
|
const button = document.createElement("button");
|
|
380
389
|
button.type = "button";
|
|
381
390
|
button.className = "scheduler_view";
|
|
@@ -396,9 +405,16 @@ class Scheduler {
|
|
|
396
405
|
const days = this.#dayDates();
|
|
397
406
|
const today = new Date();
|
|
398
407
|
this.#title.innerText = this.#periodTitle(days);
|
|
399
|
-
for (const [view, button] of this.#view_buttons)
|
|
400
|
-
|
|
401
|
-
this.#
|
|
408
|
+
for (const [view, button] of this.#view_buttons)
|
|
409
|
+
button.setAttribute("aria-pressed", view === this.#view ? "true" : "false");
|
|
410
|
+
this.#prev_button.setAttribute(
|
|
411
|
+
"aria-label",
|
|
412
|
+
this.#view === Scheduler.VIEW.DAY ? I18n.t("scheduler.previousDay") : I18n.t("scheduler.previousWeek")
|
|
413
|
+
);
|
|
414
|
+
this.#next_button.setAttribute(
|
|
415
|
+
"aria-label",
|
|
416
|
+
this.#view === Scheduler.VIEW.DAY ? I18n.t("scheduler.nextDay") : I18n.t("scheduler.nextWeek")
|
|
417
|
+
);
|
|
402
418
|
// Заголовки дней лежат вне области прокрутки и повторяют колонки сетки; ширина
|
|
403
419
|
// вертикальной полосы прокрутки компенсируется, иначе заголовки уехали бы вправо
|
|
404
420
|
const scrollbar = Math.max(0, this.#scroll.offsetWidth - this.#scroll.clientWidth);
|
|
@@ -412,7 +428,7 @@ class Scheduler {
|
|
|
412
428
|
const head = document.createElement("scheduler_day_head");
|
|
413
429
|
if (Scheduler.#sameDay(day, today)) head.classList.add("scheduler_today_head");
|
|
414
430
|
const name = document.createElement("scheduler_day_name");
|
|
415
|
-
name.innerText = day.toLocaleString(I18n.getLocale(), {weekday: "short"}).toUpperCase();
|
|
431
|
+
name.innerText = day.toLocaleString(I18n.getLocale(), { weekday: "short" }).toUpperCase();
|
|
416
432
|
const number = document.createElement("scheduler_day_number");
|
|
417
433
|
number.innerText = String(day.getDate());
|
|
418
434
|
head.appendChild(name);
|
|
@@ -486,20 +502,25 @@ class Scheduler {
|
|
|
486
502
|
}
|
|
487
503
|
|
|
488
504
|
static #dayText(day = new Date()) {
|
|
489
|
-
return day.toLocaleString(I18n.getLocale(), {weekday: "long", day: "numeric", month: "long"});
|
|
505
|
+
return day.toLocaleString(I18n.getLocale(), { weekday: "long", day: "numeric", month: "long" });
|
|
490
506
|
}
|
|
491
507
|
|
|
492
508
|
#periodTitle(days = []) {
|
|
493
509
|
const first = days[0];
|
|
494
510
|
const last = days[days.length - 1];
|
|
495
511
|
if (this.#view === Scheduler.VIEW.DAY) {
|
|
496
|
-
return first.toLocaleString(I18n.getLocale(), {
|
|
512
|
+
return first.toLocaleString(I18n.getLocale(), {
|
|
513
|
+
weekday: "long",
|
|
514
|
+
day: "numeric",
|
|
515
|
+
month: "long",
|
|
516
|
+
year: "numeric",
|
|
517
|
+
});
|
|
497
518
|
}
|
|
498
519
|
// Дата с числом даёт месяц в родительном падеже, поэтому диапазон собирается из дня
|
|
499
520
|
// и полной даты конца периода, а не из отдельного названия месяца
|
|
500
|
-
const until = last.toLocaleString(I18n.getLocale(), {day: "numeric", month: "long", year: "numeric"});
|
|
521
|
+
const until = last.toLocaleString(I18n.getLocale(), { day: "numeric", month: "long", year: "numeric" });
|
|
501
522
|
if (first.getMonth() === last.getMonth()) return `${first.getDate()} – ${until}`;
|
|
502
|
-
const from = first.toLocaleString(I18n.getLocale(), {day: "numeric", month: "long"});
|
|
523
|
+
const from = first.toLocaleString(I18n.getLocale(), { day: "numeric", month: "long" });
|
|
503
524
|
return `${from} – ${until}`;
|
|
504
525
|
}
|
|
505
526
|
|
|
@@ -523,7 +544,8 @@ class Scheduler {
|
|
|
523
544
|
const eventNode = target.closest(".scheduler_event");
|
|
524
545
|
if (eventNode !== null) {
|
|
525
546
|
const found = this.#events[Number(eventNode.dataset.index)];
|
|
526
|
-
if (this.#on_event_click !== undefined)
|
|
547
|
+
if (this.#on_event_click !== undefined)
|
|
548
|
+
this.#on_event_click(found === undefined ? undefined : found, eventNode);
|
|
527
549
|
return;
|
|
528
550
|
}
|
|
529
551
|
const dayNode = target.closest("scheduler_day");
|
|
@@ -534,7 +556,7 @@ class Scheduler {
|
|
|
534
556
|
const minutes = Math.round(raw / this.#slot_minutes) * this.#slot_minutes;
|
|
535
557
|
const date = this.#dayDates().find((day) => Scheduler.#key(day) === dayNode.dataset.day);
|
|
536
558
|
if (date !== undefined && this.#on_slot_click !== undefined) {
|
|
537
|
-
this.#on_slot_click({date: date, minutes: minutes, time: Scheduler.#timeText(minutes)});
|
|
559
|
+
this.#on_slot_click({ date: date, minutes: minutes, time: Scheduler.#timeText(minutes) });
|
|
538
560
|
}
|
|
539
561
|
}
|
|
540
562
|
};
|
|
@@ -563,4 +585,4 @@ class Scheduler {
|
|
|
563
585
|
}
|
|
564
586
|
}
|
|
565
587
|
|
|
566
|
-
exports.Scheduler = Scheduler
|
|
588
|
+
exports.Scheduler = Scheduler;
|
|
@@ -52,7 +52,10 @@ button.scheduler_view[aria-pressed="true"] {
|
|
|
52
52
|
color: var(--text_color_hover);
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
-
button.scheduler_nav:focus-visible,
|
|
55
|
+
button.scheduler_nav:focus-visible,
|
|
56
|
+
button.scheduler_today:focus-visible,
|
|
57
|
+
button.scheduler_view:focus-visible,
|
|
58
|
+
button.scheduler_event:focus-visible {
|
|
56
59
|
outline: var(--focus_outline);
|
|
57
60
|
outline-offset: var(--focus_outline_offset);
|
|
58
61
|
}
|
|
@@ -119,7 +122,8 @@ scheduler_times {
|
|
|
119
122
|
scheduler_hour {
|
|
120
123
|
display: block;
|
|
121
124
|
box-sizing: border-box;
|
|
122
|
-
padding-block: 2px 0;
|
|
125
|
+
padding-block: 2px 0;
|
|
126
|
+
padding-inline: 0 6px;
|
|
123
127
|
text-align: end;
|
|
124
128
|
color: var(--text_color_disabled);
|
|
125
129
|
font-size: 0.85em;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
const {setStyles, optionOr} = require("../../modules/chui_functions");
|
|
2
|
-
const {makeKeyboardButton} = require("../../modules/chui_a11y/chui_a11y");
|
|
1
|
+
const { setStyles, optionOr } = require("../../modules/chui_functions");
|
|
2
|
+
const { makeKeyboardButton } = require("../../modules/chui_a11y/chui_a11y");
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Сегментированный переключатель: один выбор из небольшого набора равнозначных вариантов
|
|
@@ -35,7 +35,7 @@ const {makeKeyboardButton} = require("../../modules/chui_a11y/chui_a11y");
|
|
|
35
35
|
class SegmentedControl {
|
|
36
36
|
static SIZE = {
|
|
37
37
|
SMALL: "small",
|
|
38
|
-
DEFAULT: "default"
|
|
38
|
+
DEFAULT: "default",
|
|
39
39
|
};
|
|
40
40
|
static #counter = 0;
|
|
41
41
|
|
|
@@ -51,16 +51,18 @@ class SegmentedControl {
|
|
|
51
51
|
#on_change = undefined;
|
|
52
52
|
#activate_on_focus = false;
|
|
53
53
|
|
|
54
|
-
constructor(
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
54
|
+
constructor(
|
|
55
|
+
options = {
|
|
56
|
+
id: String(),
|
|
57
|
+
options: [],
|
|
58
|
+
value: String(),
|
|
59
|
+
label: String(),
|
|
60
|
+
size: String(),
|
|
61
|
+
stretch: Boolean(),
|
|
62
|
+
activateOnFocus: Boolean(),
|
|
63
|
+
onChange: undefined,
|
|
64
|
+
}
|
|
65
|
+
) {
|
|
64
66
|
setStyles(__dirname + "/styles.css", "chUiJS_SegmentedControl");
|
|
65
67
|
SegmentedControl.#counter += 1;
|
|
66
68
|
this.#id = options.id === undefined ? `chui_segmented_control_${SegmentedControl.#counter}` : options.id;
|
|
@@ -94,7 +96,7 @@ class SegmentedControl {
|
|
|
94
96
|
getOptions() {
|
|
95
97
|
return this.#order.map((value) => {
|
|
96
98
|
const record = this.#options.get(value);
|
|
97
|
-
return {value: record.value, title: record.title};
|
|
99
|
+
return { value: record.value, title: record.title };
|
|
98
100
|
});
|
|
99
101
|
}
|
|
100
102
|
|
|
@@ -125,7 +127,8 @@ class SegmentedControl {
|
|
|
125
127
|
|
|
126
128
|
/** Размер вариантов: `SegmentedControl.SIZE.{SMALL, DEFAULT}` */
|
|
127
129
|
setSize(size = String()) {
|
|
128
|
-
this.#root.dataset.size =
|
|
130
|
+
this.#root.dataset.size =
|
|
131
|
+
size === SegmentedControl.SIZE.SMALL ? SegmentedControl.SIZE.SMALL : SegmentedControl.SIZE.DEFAULT;
|
|
129
132
|
return this;
|
|
130
133
|
}
|
|
131
134
|
|
|
@@ -154,7 +157,7 @@ class SegmentedControl {
|
|
|
154
157
|
}
|
|
155
158
|
|
|
156
159
|
/** Добавить вариант: `{value, title, icon, disabled}` */
|
|
157
|
-
addOption(option = {value: String(), title: String(), icon: undefined, disabled: Boolean()}) {
|
|
160
|
+
addOption(option = { value: String(), title: String(), icon: undefined, disabled: Boolean() }) {
|
|
158
161
|
this.#root.appendChild(this.#createOption(option));
|
|
159
162
|
this.#sync();
|
|
160
163
|
return this;
|
|
@@ -174,7 +177,8 @@ class SegmentedControl {
|
|
|
174
177
|
this.#value = undefined;
|
|
175
178
|
this.#active = undefined;
|
|
176
179
|
for (const option of list) this.#root.appendChild(this.#createOption(option));
|
|
177
|
-
if (previous !== undefined && this.#options.has(previous) && !this.#disabled.has(previous))
|
|
180
|
+
if (previous !== undefined && this.#options.has(previous) && !this.#disabled.has(previous))
|
|
181
|
+
this.#value = previous;
|
|
178
182
|
this.#sync();
|
|
179
183
|
return this;
|
|
180
184
|
}
|
|
@@ -229,11 +233,12 @@ class SegmentedControl {
|
|
|
229
233
|
makeKeyboardButton(node, "radio");
|
|
230
234
|
node.setAttribute("aria-checked", "false");
|
|
231
235
|
node.dataset.value = value;
|
|
232
|
-
if (option.icon !== undefined && option.icon !== null)
|
|
236
|
+
if (option.icon !== undefined && option.icon !== null)
|
|
237
|
+
node.insertAdjacentHTML("afterbegin", option.icon.getHTML());
|
|
233
238
|
const title = document.createElement("segmented_title");
|
|
234
239
|
title.innerText = option.title === undefined ? value : String(option.title);
|
|
235
240
|
node.appendChild(title);
|
|
236
|
-
this.#options.set(value, {value: value, title: title.innerText, node: node});
|
|
241
|
+
this.#options.set(value, { value: value, title: title.innerText, node: node });
|
|
237
242
|
this.#order.push(value);
|
|
238
243
|
// Запрет мог быть выставлен программно (setDisabled) и остаться после пересборки набора
|
|
239
244
|
if (option.disabled === true || this.#disabled.has(value)) this.setDisabled(value, true);
|
|
@@ -294,10 +299,11 @@ class SegmentedControl {
|
|
|
294
299
|
let next;
|
|
295
300
|
if (event.key === "Home") next = 0;
|
|
296
301
|
else if (event.key === "End") next = available.length - 1;
|
|
297
|
-
else if (event.key === "ArrowLeft" || event.key === "ArrowUp")
|
|
302
|
+
else if (event.key === "ArrowLeft" || event.key === "ArrowUp")
|
|
303
|
+
next = (current - 1 + available.length) % available.length;
|
|
298
304
|
else next = (current + 1) % available.length;
|
|
299
305
|
this.#focus(available[next]);
|
|
300
306
|
};
|
|
301
307
|
}
|
|
302
308
|
|
|
303
|
-
exports.SegmentedControl = SegmentedControl
|
|
309
|
+
exports.SegmentedControl = SegmentedControl;
|