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
|
@@ -58,8 +58,8 @@ class JsonViewer {
|
|
|
58
58
|
#title = document.createElement("json_viewer_title");
|
|
59
59
|
#head = document.createElement("json_viewer_head");
|
|
60
60
|
#search = document.createElement("input");
|
|
61
|
-
#
|
|
62
|
-
#
|
|
61
|
+
#searchBox = document.createElement("json_viewer_search_box");
|
|
62
|
+
#searchClear = document.createElement("button");
|
|
63
63
|
#expand = document.createElement("button");
|
|
64
64
|
#collapse = document.createElement("button");
|
|
65
65
|
#tree = document.createElement("json_viewer_tree");
|
|
@@ -68,17 +68,17 @@ class JsonViewer {
|
|
|
68
68
|
#status = document.createElement("json_viewer_status");
|
|
69
69
|
#id = undefined;
|
|
70
70
|
#value = undefined;
|
|
71
|
-
#
|
|
71
|
+
#hasValue = false;
|
|
72
72
|
#expanded = new Set();
|
|
73
|
-
#
|
|
73
|
+
#searchText = "";
|
|
74
74
|
#searchable = true;
|
|
75
75
|
#height = "320px";
|
|
76
|
-
#
|
|
77
|
-
#
|
|
78
|
-
#
|
|
79
|
-
#
|
|
80
|
-
#
|
|
81
|
-
#
|
|
76
|
+
#titleText = undefined;
|
|
77
|
+
#labelText = undefined;
|
|
78
|
+
#emptyText = undefined;
|
|
79
|
+
#errorObject = undefined;
|
|
80
|
+
#activePath = undefined;
|
|
81
|
+
#focusedPath = undefined;
|
|
82
82
|
|
|
83
83
|
constructor(
|
|
84
84
|
options = {
|
|
@@ -100,10 +100,10 @@ class JsonViewer {
|
|
|
100
100
|
this.#id = options.id === undefined ? `chui_json_viewer_${JsonViewer.#counter}` : options.id;
|
|
101
101
|
this.#root.id = this.#id;
|
|
102
102
|
this.#root.setAttribute("role", "group");
|
|
103
|
-
this.#
|
|
103
|
+
this.#labelText = options.label;
|
|
104
104
|
this.#searchable = options.searchable !== false;
|
|
105
|
-
if (options.emptyText !== undefined) this.#
|
|
106
|
-
else this.#
|
|
105
|
+
if (options.emptyText !== undefined) this.#emptyText = String(options.emptyText);
|
|
106
|
+
else this.#emptyText = I18n.t("jsonViewer.empty");
|
|
107
107
|
this.#title.className = "json_viewer_title";
|
|
108
108
|
this.#title.id = `${this.#id}_title`;
|
|
109
109
|
this.#head.className = "json_viewer_head";
|
|
@@ -130,20 +130,20 @@ class JsonViewer {
|
|
|
130
130
|
this.#status.setAttribute("role", "status");
|
|
131
131
|
this.#status.setAttribute("aria-live", "polite");
|
|
132
132
|
// Кнопка очистки — своя: системная кнопка очистки у `input[type=search]` скрыта (см. стили)
|
|
133
|
-
this.#
|
|
134
|
-
this.#
|
|
135
|
-
this.#
|
|
136
|
-
this.#
|
|
137
|
-
const
|
|
138
|
-
|
|
139
|
-
this.#
|
|
140
|
-
this.#
|
|
133
|
+
this.#searchBox.className = "json_viewer_search_box";
|
|
134
|
+
this.#searchClear.type = "button";
|
|
135
|
+
this.#searchClear.className = "json_viewer_search_clear";
|
|
136
|
+
this.#searchClear.setAttribute("aria-label", I18n.t("jsonViewer.clearSearch"));
|
|
137
|
+
const clearGlyph = new Icon(Icons.NAVIGATION.CLOSE, "16px").set();
|
|
138
|
+
clearGlyph.setAttribute("aria-hidden", "true");
|
|
139
|
+
this.#searchClear.appendChild(clearGlyph);
|
|
140
|
+
this.#searchClear.addEventListener("click", () => {
|
|
141
141
|
this.setSearch("");
|
|
142
142
|
this.#search.focus();
|
|
143
143
|
});
|
|
144
|
-
this.#
|
|
145
|
-
this.#
|
|
146
|
-
if (this.#searchable) this.#head.appendChild(this.#
|
|
144
|
+
this.#searchBox.appendChild(this.#search);
|
|
145
|
+
this.#searchBox.appendChild(this.#searchClear);
|
|
146
|
+
if (this.#searchable) this.#head.appendChild(this.#searchBox);
|
|
147
147
|
this.#syncClear();
|
|
148
148
|
this.#head.appendChild(this.#expand);
|
|
149
149
|
this.#head.appendChild(this.#collapse);
|
|
@@ -155,7 +155,7 @@ class JsonViewer {
|
|
|
155
155
|
this.#root.appendChild(this.#status);
|
|
156
156
|
if (options.title !== undefined) this.setTitle(options.title);
|
|
157
157
|
else this.#title.hidden = true;
|
|
158
|
-
this.setLabel(this.#
|
|
158
|
+
this.setLabel(this.#labelText === undefined ? I18n.t("jsonViewer.title") : this.#labelText);
|
|
159
159
|
// Высота из опций: без неё остаётся своя по умолчанию (320px, дерево прокручивается)
|
|
160
160
|
this.setHeight(options.height === undefined ? this.#height : options.height);
|
|
161
161
|
if (options.text !== undefined) this.setText(options.text);
|
|
@@ -177,11 +177,11 @@ class JsonViewer {
|
|
|
177
177
|
}
|
|
178
178
|
|
|
179
179
|
getTitle() {
|
|
180
|
-
return this.#
|
|
180
|
+
return this.#titleText;
|
|
181
181
|
}
|
|
182
182
|
|
|
183
183
|
getLabel() {
|
|
184
|
-
return this.#
|
|
184
|
+
return this.#labelText;
|
|
185
185
|
}
|
|
186
186
|
|
|
187
187
|
/** Данные как есть (без разбора и сериализации) */
|
|
@@ -191,11 +191,11 @@ class JsonViewer {
|
|
|
191
191
|
|
|
192
192
|
/** Компактный JSON текущих данных */
|
|
193
193
|
getText() {
|
|
194
|
-
return this.#
|
|
194
|
+
return this.#hasValue ? Json.minify(this.#value) : "";
|
|
195
195
|
}
|
|
196
196
|
|
|
197
197
|
hasValue() {
|
|
198
|
-
return this.#
|
|
198
|
+
return this.#hasValue;
|
|
199
199
|
}
|
|
200
200
|
|
|
201
201
|
/** Путь верхнего узла: `$`, дальше `$.ключ`, `$[0]` */
|
|
@@ -205,20 +205,20 @@ class JsonViewer {
|
|
|
205
205
|
|
|
206
206
|
/** Ошибка разбора текста (`text`): `{message, line?, column?, offset?}` или `undefined` */
|
|
207
207
|
getError() {
|
|
208
|
-
return this.#
|
|
208
|
+
return this.#errorObject;
|
|
209
209
|
}
|
|
210
210
|
|
|
211
211
|
/** Текст ошибки разбора словами (пустая строка, если разбор прошёл) */
|
|
212
212
|
getErrorText() {
|
|
213
|
-
return Json.errorText(this.#
|
|
213
|
+
return Json.errorText(this.#errorObject);
|
|
214
214
|
}
|
|
215
215
|
|
|
216
216
|
getSearch() {
|
|
217
|
-
return this.#
|
|
217
|
+
return this.#searchText;
|
|
218
218
|
}
|
|
219
219
|
|
|
220
220
|
isSearching() {
|
|
221
|
-
return this.#
|
|
221
|
+
return this.#searchText.trim() !== "";
|
|
222
222
|
}
|
|
223
223
|
|
|
224
224
|
isSearchable() {
|
|
@@ -232,14 +232,14 @@ class JsonViewer {
|
|
|
232
232
|
|
|
233
233
|
/** Пути совпадений поиска по всему документу */
|
|
234
234
|
getMatches() {
|
|
235
|
-
const query = this.#
|
|
235
|
+
const query = this.#searchText.trim().toLowerCase();
|
|
236
236
|
if (query === "") return [];
|
|
237
237
|
const matches = [];
|
|
238
238
|
const walk = (node) => {
|
|
239
239
|
if (this.#matchesNode(node, query)) matches.push(node.path);
|
|
240
240
|
for (const child of JsonViewer.#childrenOf(node)) walk(child);
|
|
241
241
|
};
|
|
242
|
-
if (this.#
|
|
242
|
+
if (this.#hasValue) walk(this.#rootNode());
|
|
243
243
|
return matches;
|
|
244
244
|
}
|
|
245
245
|
|
|
@@ -256,13 +256,13 @@ class JsonViewer {
|
|
|
256
256
|
}
|
|
257
257
|
|
|
258
258
|
getEmptyText() {
|
|
259
|
-
return this.#
|
|
259
|
+
return this.#emptyText;
|
|
260
260
|
}
|
|
261
261
|
|
|
262
262
|
/** Значение по пути (`$.a.b[2]`) или `undefined`, если такого узла нет */
|
|
263
263
|
getValueAt(path = String()) {
|
|
264
264
|
const segments = JsonViewer.#readPath(path);
|
|
265
|
-
if (segments === undefined || !this.#
|
|
265
|
+
if (segments === undefined || !this.#hasValue) return undefined;
|
|
266
266
|
let current = this.#value;
|
|
267
267
|
for (const segment of segments) {
|
|
268
268
|
if (current === null || current === undefined || typeof current !== "object") return undefined;
|
|
@@ -281,7 +281,7 @@ class JsonViewer {
|
|
|
281
281
|
}
|
|
282
282
|
|
|
283
283
|
setTitle(text = undefined) {
|
|
284
|
-
this.#
|
|
284
|
+
this.#titleText = text;
|
|
285
285
|
if (text === undefined || text === "") {
|
|
286
286
|
this.#title.hidden = true;
|
|
287
287
|
this.#title.innerText = "";
|
|
@@ -295,7 +295,7 @@ class JsonViewer {
|
|
|
295
295
|
}
|
|
296
296
|
|
|
297
297
|
setLabel(text = undefined) {
|
|
298
|
-
this.#
|
|
298
|
+
this.#labelText = text;
|
|
299
299
|
this.#syncLabel();
|
|
300
300
|
return this;
|
|
301
301
|
}
|
|
@@ -303,8 +303,8 @@ class JsonViewer {
|
|
|
303
303
|
/** Данные для показа: любой JSON-совместимый набор (без разбора текста) */
|
|
304
304
|
setValue(value = undefined) {
|
|
305
305
|
this.#value = value;
|
|
306
|
-
this.#
|
|
307
|
-
this.#
|
|
306
|
+
this.#hasValue = value !== undefined;
|
|
307
|
+
this.#errorObject = undefined;
|
|
308
308
|
this.#error.hidden = true;
|
|
309
309
|
this.#expanded = new Set([...this.#expanded].filter((path) => this.#hasPath(path)));
|
|
310
310
|
this.#render();
|
|
@@ -317,15 +317,15 @@ class JsonViewer {
|
|
|
317
317
|
const result = Json.parse(text === undefined || text === null ? "" : text);
|
|
318
318
|
if (!result.ok) {
|
|
319
319
|
this.#value = undefined;
|
|
320
|
-
this.#
|
|
321
|
-
this.#
|
|
320
|
+
this.#hasValue = false;
|
|
321
|
+
this.#errorObject = result.error;
|
|
322
322
|
this.#error.innerText = Json.errorText(result.error);
|
|
323
323
|
this.#error.hidden = false;
|
|
324
324
|
this.#render();
|
|
325
325
|
this.#announce();
|
|
326
326
|
return this;
|
|
327
327
|
}
|
|
328
|
-
this.#
|
|
328
|
+
this.#errorObject = undefined;
|
|
329
329
|
this.#error.hidden = true;
|
|
330
330
|
return this.setValue(result.value);
|
|
331
331
|
}
|
|
@@ -334,7 +334,7 @@ class JsonViewer {
|
|
|
334
334
|
expandDepth(depth = Number()) {
|
|
335
335
|
const limit = Number.isFinite(Number(depth)) ? Math.max(0, Math.floor(Number(depth))) : Infinity;
|
|
336
336
|
this.#expanded = new Set();
|
|
337
|
-
if (this.#
|
|
337
|
+
if (this.#hasValue) {
|
|
338
338
|
const walk = (node, level) => {
|
|
339
339
|
if (level >= limit) return;
|
|
340
340
|
if (!JsonViewer.#isContainer(node.value)) return;
|
|
@@ -363,7 +363,7 @@ class JsonViewer {
|
|
|
363
363
|
|
|
364
364
|
expandAll() {
|
|
365
365
|
this.#expanded = new Set();
|
|
366
|
-
if (this.#
|
|
366
|
+
if (this.#hasValue) {
|
|
367
367
|
const walk = (node) => {
|
|
368
368
|
if (!JsonViewer.#isContainer(node.value)) return;
|
|
369
369
|
this.#expanded.add(node.path);
|
|
@@ -390,8 +390,8 @@ class JsonViewer {
|
|
|
390
390
|
|
|
391
391
|
/** Поиск по ключам и значениям; пустая строка снимает поиск */
|
|
392
392
|
setSearch(query = String()) {
|
|
393
|
-
this.#
|
|
394
|
-
if (this.#search.value !== this.#
|
|
393
|
+
this.#searchText = query === undefined || query === null ? "" : String(query);
|
|
394
|
+
if (this.#search.value !== this.#searchText) this.#search.value = this.#searchText;
|
|
395
395
|
this.#syncClear();
|
|
396
396
|
this.#render();
|
|
397
397
|
this.#announce();
|
|
@@ -400,7 +400,7 @@ class JsonViewer {
|
|
|
400
400
|
|
|
401
401
|
/** Кнопка очистки видна, только когда есть что очищать */
|
|
402
402
|
#syncClear() {
|
|
403
|
-
this.#
|
|
403
|
+
this.#searchClear.hidden = this.#searchText === "";
|
|
404
404
|
return this;
|
|
405
405
|
}
|
|
406
406
|
|
|
@@ -422,7 +422,7 @@ class JsonViewer {
|
|
|
422
422
|
}
|
|
423
423
|
|
|
424
424
|
setEmptyText(text = String()) {
|
|
425
|
-
this.#
|
|
425
|
+
this.#emptyText = text === undefined ? "" : String(text);
|
|
426
426
|
this.#render();
|
|
427
427
|
return this;
|
|
428
428
|
}
|
|
@@ -527,7 +527,7 @@ class JsonViewer {
|
|
|
527
527
|
|
|
528
528
|
/** Есть ли такой путь в текущих данных (для чистки раскрытых путей после setValue) */
|
|
529
529
|
#hasPath(path = String()) {
|
|
530
|
-
if (path === this.getRootPath()) return this.#
|
|
530
|
+
if (path === this.getRootPath()) return this.#hasValue;
|
|
531
531
|
const segments = JsonViewer.#readPath(path);
|
|
532
532
|
return segments !== undefined && this.#valueAt(segments) !== undefined;
|
|
533
533
|
}
|
|
@@ -561,9 +561,9 @@ class JsonViewer {
|
|
|
561
561
|
|
|
562
562
|
/** Видимые узлы деревом: при поиске — совпадения с предками, без поиска — раскрытые ветки */
|
|
563
563
|
#visibleNodes() {
|
|
564
|
-
if (!this.#
|
|
564
|
+
if (!this.#hasValue) return [];
|
|
565
565
|
const list = [];
|
|
566
|
-
const query = this.#
|
|
566
|
+
const query = this.#searchText.trim().toLowerCase();
|
|
567
567
|
const walk = (node, level) => {
|
|
568
568
|
if (query !== "" && !this.#matchesTree(node, query)) return;
|
|
569
569
|
list.push({ node: node, level: level });
|
|
@@ -582,13 +582,13 @@ class JsonViewer {
|
|
|
582
582
|
}
|
|
583
583
|
|
|
584
584
|
#accessibleName() {
|
|
585
|
-
if (this.#
|
|
586
|
-
if (this.#
|
|
585
|
+
if (this.#titleText !== undefined && this.#titleText !== "") return this.#titleText;
|
|
586
|
+
if (this.#labelText !== undefined && this.#labelText !== "") return this.#labelText;
|
|
587
587
|
return I18n.t("jsonViewer.title");
|
|
588
588
|
}
|
|
589
589
|
|
|
590
590
|
#syncLabel() {
|
|
591
|
-
if (this.#
|
|
591
|
+
if (this.#titleText !== undefined && this.#titleText !== "") {
|
|
592
592
|
this.#root.setAttribute("aria-labelledby", this.#title.id);
|
|
593
593
|
this.#root.removeAttribute("aria-label");
|
|
594
594
|
} else {
|
|
@@ -626,7 +626,7 @@ class JsonViewer {
|
|
|
626
626
|
#rowNode(entry = Object()) {
|
|
627
627
|
const node = entry.node;
|
|
628
628
|
const container = JsonViewer.#isContainer(node.value);
|
|
629
|
-
const query = this.#
|
|
629
|
+
const query = this.#searchText.trim().toLowerCase();
|
|
630
630
|
const open = this.#isOpen(node, query);
|
|
631
631
|
const row = document.createElement("div");
|
|
632
632
|
row.className = "json_viewer_row";
|
|
@@ -666,18 +666,18 @@ class JsonViewer {
|
|
|
666
666
|
if (type === TYPE.OBJECT || type === TYPE.ARRAY) {
|
|
667
667
|
const wrap = document.createElement("span");
|
|
668
668
|
wrap.className = "json_viewer_container";
|
|
669
|
-
const [
|
|
669
|
+
const [openBrace, closeBrace] = type === TYPE.ARRAY ? ["[", "]"] : ["{", "}"];
|
|
670
670
|
const left = document.createElement("span");
|
|
671
671
|
left.className = "json_viewer_brace code_token_operator";
|
|
672
672
|
left.setAttribute("aria-hidden", "true");
|
|
673
|
-
left.innerText =
|
|
673
|
+
left.innerText = openBrace;
|
|
674
674
|
const summary = document.createElement("span");
|
|
675
675
|
summary.className = "json_viewer_summary";
|
|
676
676
|
summary.innerText = this.#summaryText(node.value);
|
|
677
677
|
const right = document.createElement("span");
|
|
678
678
|
right.className = "json_viewer_brace code_token_operator";
|
|
679
679
|
right.setAttribute("aria-hidden", "true");
|
|
680
|
-
right.innerText =
|
|
680
|
+
right.innerText = closeBrace;
|
|
681
681
|
wrap.appendChild(left);
|
|
682
682
|
wrap.appendChild(summary);
|
|
683
683
|
wrap.appendChild(right);
|
|
@@ -712,19 +712,19 @@ class JsonViewer {
|
|
|
712
712
|
}
|
|
713
713
|
|
|
714
714
|
#announce() {
|
|
715
|
-
const query = this.#
|
|
715
|
+
const query = this.#searchText.trim();
|
|
716
716
|
if (query !== "") {
|
|
717
717
|
const matches = this.getMatches().length;
|
|
718
718
|
this.#status.innerText =
|
|
719
719
|
matches === 0 ? I18n.t("common.nothingFound") : I18n.t("jsonViewer.found", { count: matches });
|
|
720
720
|
return this;
|
|
721
721
|
}
|
|
722
|
-
if (this.#
|
|
723
|
-
this.#status.innerText = Json.errorText(this.#
|
|
722
|
+
if (this.#errorObject !== undefined) {
|
|
723
|
+
this.#status.innerText = Json.errorText(this.#errorObject);
|
|
724
724
|
return this;
|
|
725
725
|
}
|
|
726
|
-
if (!this.#
|
|
727
|
-
this.#status.innerText = this.#
|
|
726
|
+
if (!this.#hasValue) {
|
|
727
|
+
this.#status.innerText = this.#emptyText;
|
|
728
728
|
return this;
|
|
729
729
|
}
|
|
730
730
|
this.#status.innerText = I18n.t("jsonViewer.visible", { count: this.#visibleNodes().length });
|
|
@@ -735,15 +735,15 @@ class JsonViewer {
|
|
|
735
735
|
// Узлы пересобираются, а фокус живёт на строке: запоминаем путь до перерисовки
|
|
736
736
|
const active = document.activeElement;
|
|
737
737
|
const focused = active === null || !this.#tree.contains(active) ? null : active.closest(".json_viewer_row");
|
|
738
|
-
if (focused !== null && focused.dataset.path !== undefined) this.#
|
|
738
|
+
if (focused !== null && focused.dataset.path !== undefined) this.#focusedPath = focused.dataset.path;
|
|
739
739
|
this.#tree.innerHTML = "";
|
|
740
740
|
const list = this.#visibleNodes();
|
|
741
741
|
for (const entry of list) this.#tree.appendChild(this.#rowNode(entry));
|
|
742
742
|
// Пояснение вместо дерева: пустые данные, ничего не найдено или ошибка разбора
|
|
743
|
-
const searching = this.#
|
|
743
|
+
const searching = this.#searchText.trim() !== "";
|
|
744
744
|
this.#tree.hidden = list.length === 0;
|
|
745
|
-
this.#empty.innerText = searching ? I18n.t("common.nothingFound") : this.#
|
|
746
|
-
this.#empty.hidden = list.length > 0 || this.#
|
|
745
|
+
this.#empty.innerText = searching ? I18n.t("common.nothingFound") : this.#emptyText;
|
|
746
|
+
this.#empty.hidden = list.length > 0 || this.#errorObject !== undefined;
|
|
747
747
|
this.#applyStop();
|
|
748
748
|
return this;
|
|
749
749
|
}
|
|
@@ -753,13 +753,13 @@ class JsonViewer {
|
|
|
753
753
|
const list = [...this.#tree.querySelectorAll(".json_viewer_row")];
|
|
754
754
|
if (list.length === 0) return;
|
|
755
755
|
const stop =
|
|
756
|
-
list.find((row) => row.dataset.path === this.#
|
|
757
|
-
list.find((row) => row.dataset.path === this.#
|
|
756
|
+
list.find((row) => row.dataset.path === this.#activePath) ??
|
|
757
|
+
list.find((row) => row.dataset.path === this.#focusedPath) ??
|
|
758
758
|
list[0];
|
|
759
|
-
this.#
|
|
759
|
+
this.#activePath = stop.dataset.path;
|
|
760
760
|
for (const row of list) row.setAttribute("tabindex", row === stop ? "0" : "-1");
|
|
761
|
-
if (this.#
|
|
762
|
-
this.#
|
|
761
|
+
if (this.#focusedPath !== undefined && stop.dataset.path === this.#focusedPath) {
|
|
762
|
+
this.#focusedPath = undefined;
|
|
763
763
|
stop.focus();
|
|
764
764
|
}
|
|
765
765
|
return this;
|
|
@@ -767,7 +767,7 @@ class JsonViewer {
|
|
|
767
767
|
|
|
768
768
|
#focusRow(row = undefined) {
|
|
769
769
|
if (row === undefined || row === null) return this;
|
|
770
|
-
this.#
|
|
770
|
+
this.#activePath = row.dataset.path;
|
|
771
771
|
for (const other of this.#tree.querySelectorAll(".json_viewer_row")) {
|
|
772
772
|
other.setAttribute("tabindex", other === row ? "0" : "-1");
|
|
773
773
|
}
|
|
@@ -808,7 +808,7 @@ class JsonViewer {
|
|
|
808
808
|
#onFocusIn = (event) => {
|
|
809
809
|
const row = event.target instanceof Element ? event.target.closest(".json_viewer_row") : null;
|
|
810
810
|
if (row === null || row.dataset.path === undefined) return;
|
|
811
|
-
this.#
|
|
811
|
+
this.#activePath = row.dataset.path;
|
|
812
812
|
};
|
|
813
813
|
|
|
814
814
|
#onSearch = () => {
|
|
@@ -825,7 +825,7 @@ class JsonViewer {
|
|
|
825
825
|
const list = this.#tree.querySelectorAll(".json_viewer_row");
|
|
826
826
|
if (list.length === 0) return;
|
|
827
827
|
// Нажатия на самой стрелке (настоящая кнопка) не перехватываем
|
|
828
|
-
const
|
|
828
|
+
const fromButton = event.target instanceof Element && event.target.closest("button") !== null;
|
|
829
829
|
const row = this.#currentRow(event.target instanceof Element ? event.target : undefined);
|
|
830
830
|
const path = row === null ? undefined : row.dataset.path;
|
|
831
831
|
const segments = path === undefined ? undefined : JsonViewer.#readPath(path);
|
|
@@ -849,14 +849,14 @@ class JsonViewer {
|
|
|
849
849
|
this.#focusRow(list[list.length - 1]);
|
|
850
850
|
return;
|
|
851
851
|
case "ArrowRight": {
|
|
852
|
-
if (
|
|
852
|
+
if (fromButton || !container) return;
|
|
853
853
|
event.preventDefault();
|
|
854
854
|
if (!this.#expanded.has(path)) this.expand(path);
|
|
855
855
|
else this.#step(row, 1);
|
|
856
856
|
return;
|
|
857
857
|
}
|
|
858
858
|
case "ArrowLeft": {
|
|
859
|
-
if (
|
|
859
|
+
if (fromButton || path === undefined) return;
|
|
860
860
|
event.preventDefault();
|
|
861
861
|
if (container && this.#expanded.has(path)) {
|
|
862
862
|
this.collapse(path);
|
|
@@ -868,7 +868,7 @@ class JsonViewer {
|
|
|
868
868
|
}
|
|
869
869
|
case "Enter":
|
|
870
870
|
case " ": {
|
|
871
|
-
if (
|
|
871
|
+
if (fromButton || !container) return;
|
|
872
872
|
event.preventDefault();
|
|
873
873
|
this.toggle(path);
|
|
874
874
|
return;
|
|
@@ -7,10 +7,10 @@ chui_json_viewer {
|
|
|
7
7
|
width: -webkit-fill-available;
|
|
8
8
|
max-width: 100%;
|
|
9
9
|
height: max-content;
|
|
10
|
-
margin: var(--
|
|
10
|
+
margin: var(--block_margin);
|
|
11
11
|
overflow: hidden;
|
|
12
12
|
border: 1px solid var(--border_color);
|
|
13
|
-
border-radius: var(--
|
|
13
|
+
border-radius: var(--radius_sm);
|
|
14
14
|
background: var(--element_background_2);
|
|
15
15
|
color: var(--text_color);
|
|
16
16
|
}
|
|
@@ -18,7 +18,7 @@ chui_json_viewer {
|
|
|
18
18
|
.json_viewer_title {
|
|
19
19
|
display: block;
|
|
20
20
|
width: max-content;
|
|
21
|
-
margin: var(--
|
|
21
|
+
margin: var(--block_margin);
|
|
22
22
|
font-size: var(--font_labels_size);
|
|
23
23
|
font-weight: 500;
|
|
24
24
|
}
|
|
@@ -37,7 +37,7 @@ chui_json_viewer {
|
|
|
37
37
|
border-bottom: 1px solid var(--border_color);
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
/* Строка поиска — как остальные поля: 35 px, --
|
|
40
|
+
/* Строка поиска — как остальные поля: 35 px, --radius_sm; кнопки рядом — той же высоты */
|
|
41
41
|
.json_viewer_search_box {
|
|
42
42
|
position: relative;
|
|
43
43
|
display: flex;
|
|
@@ -56,7 +56,7 @@ chui_json_viewer {
|
|
|
56
56
|
padding-block: 0 0;
|
|
57
57
|
padding-inline: 12px 40px;
|
|
58
58
|
border: 1px solid var(--border_color);
|
|
59
|
-
border-radius: var(--
|
|
59
|
+
border-radius: var(--radius_sm);
|
|
60
60
|
background: var(--element_background);
|
|
61
61
|
color: var(--text_color);
|
|
62
62
|
font-family: inherit;
|
|
@@ -120,7 +120,7 @@ chui_json_viewer {
|
|
|
120
120
|
margin: 0;
|
|
121
121
|
padding: 0 12px;
|
|
122
122
|
border: 1px solid var(--border_color);
|
|
123
|
-
border-radius: var(--
|
|
123
|
+
border-radius: var(--radius_sm);
|
|
124
124
|
background: var(--element_background);
|
|
125
125
|
color: var(--text_color);
|
|
126
126
|
font-family: inherit;
|
|
@@ -37,16 +37,16 @@ class Kanban {
|
|
|
37
37
|
static #counter = 0;
|
|
38
38
|
|
|
39
39
|
#root = document.createElement("chui_kanban");
|
|
40
|
-
#
|
|
40
|
+
#columnsBox = document.createElement("kanban_columns");
|
|
41
41
|
#status = document.createElement("kanban_status");
|
|
42
42
|
#id = undefined;
|
|
43
43
|
#columns = [];
|
|
44
44
|
#draggable = true;
|
|
45
45
|
#label = I18n.t("graphics.kanbanBoard");
|
|
46
|
-
#
|
|
47
|
-
#
|
|
48
|
-
#
|
|
49
|
-
#
|
|
46
|
+
#onCardMove = undefined;
|
|
47
|
+
#onCardClick = undefined;
|
|
48
|
+
#dragCard = undefined;
|
|
49
|
+
#dragColumn = undefined;
|
|
50
50
|
|
|
51
51
|
constructor(
|
|
52
52
|
options = {
|
|
@@ -65,14 +65,14 @@ class Kanban {
|
|
|
65
65
|
this.#root.setAttribute("role", "region");
|
|
66
66
|
this.#draggable = options.draggable !== false;
|
|
67
67
|
this.#root.classList.toggle("kanban_disabled", !this.#draggable);
|
|
68
|
-
this.#
|
|
69
|
-
this.#
|
|
68
|
+
this.#onCardMove = options.onCardMove;
|
|
69
|
+
this.#onCardClick = options.onCardClick;
|
|
70
70
|
this.setLabel(optionOr(options.label, this.#label));
|
|
71
71
|
this.#columns = Kanban.#normalize(options.columns);
|
|
72
72
|
this.#status.classList.add("chui_visually_hidden");
|
|
73
73
|
this.#status.setAttribute("role", "status");
|
|
74
74
|
this.#status.setAttribute("aria-live", "polite");
|
|
75
|
-
this.#root.appendChild(this.#
|
|
75
|
+
this.#root.appendChild(this.#columnsBox);
|
|
76
76
|
this.#root.appendChild(this.#status);
|
|
77
77
|
this.#root.addEventListener("click", this.#onClick);
|
|
78
78
|
this.#root.addEventListener("keydown", this.#onKeyDown);
|
|
@@ -219,7 +219,7 @@ class Kanban {
|
|
|
219
219
|
}
|
|
220
220
|
|
|
221
221
|
#emitMove(card = Object(), from = String(), to = String(), index = Number()) {
|
|
222
|
-
if (this.#
|
|
222
|
+
if (this.#onCardMove !== undefined) this.#onCardMove(card, { from: from, to: to, index: index });
|
|
223
223
|
}
|
|
224
224
|
|
|
225
225
|
#announce(text = String()) {
|
|
@@ -243,9 +243,9 @@ class Kanban {
|
|
|
243
243
|
}
|
|
244
244
|
|
|
245
245
|
#render() {
|
|
246
|
-
this.#
|
|
246
|
+
this.#columnsBox.innerHTML = "";
|
|
247
247
|
for (const column of this.#columns) {
|
|
248
|
-
this.#
|
|
248
|
+
this.#columnsBox.appendChild(this.#createColumn(column));
|
|
249
249
|
}
|
|
250
250
|
}
|
|
251
251
|
|
|
@@ -309,7 +309,7 @@ class Kanban {
|
|
|
309
309
|
const target = event.target instanceof Element ? event.target : null;
|
|
310
310
|
if (target === null) return undefined;
|
|
311
311
|
const node = target.closest("kanban_column");
|
|
312
|
-
if (node === null || !this.#
|
|
312
|
+
if (node === null || !this.#columnsBox.contains(node)) return undefined;
|
|
313
313
|
return { node: node, column: this.getColumn(node.dataset.column) };
|
|
314
314
|
}
|
|
315
315
|
|
|
@@ -318,7 +318,7 @@ class Kanban {
|
|
|
318
318
|
const target = event.target instanceof Element ? event.target : null;
|
|
319
319
|
if (target === null) return undefined;
|
|
320
320
|
const node = target.closest(".kanban_card");
|
|
321
|
-
if (node === null || !this.#
|
|
321
|
+
if (node === null || !this.#columnsBox.contains(node)) return undefined;
|
|
322
322
|
return node;
|
|
323
323
|
}
|
|
324
324
|
|
|
@@ -336,8 +336,8 @@ class Kanban {
|
|
|
336
336
|
#onDragStart = (event) => {
|
|
337
337
|
const node = this.#cardFromEvent(event);
|
|
338
338
|
if (node === null || node === undefined) return;
|
|
339
|
-
this.#
|
|
340
|
-
this.#
|
|
339
|
+
this.#dragCard = node;
|
|
340
|
+
this.#dragColumn = node.dataset.column;
|
|
341
341
|
node.classList.add("kanban_card_dragging");
|
|
342
342
|
if (event.dataTransfer === null) return;
|
|
343
343
|
event.dataTransfer.effectAllowed = "move";
|
|
@@ -345,10 +345,10 @@ class Kanban {
|
|
|
345
345
|
};
|
|
346
346
|
|
|
347
347
|
#onDragOver = (event) => {
|
|
348
|
-
if (this.#
|
|
348
|
+
if (this.#dragCard === undefined) return;
|
|
349
349
|
const target = this.#columnFromEvent(event);
|
|
350
350
|
if (target === undefined) return;
|
|
351
|
-
const source = this.getColumn(this.#
|
|
351
|
+
const source = this.getColumn(this.#dragColumn);
|
|
352
352
|
// Лимит: карточку из другой колонки в полную колонку не пускаем
|
|
353
353
|
if (
|
|
354
354
|
target.column.limit !== undefined &&
|
|
@@ -371,15 +371,15 @@ class Kanban {
|
|
|
371
371
|
*/
|
|
372
372
|
#moveToPoint(columnNode = new HTMLElement(), event = Object()) {
|
|
373
373
|
const body = columnNode.querySelector("kanban_column_body");
|
|
374
|
-
const reference = this.#referenceFor(body, event, this.#
|
|
374
|
+
const reference = this.#referenceFor(body, event, this.#dragCard);
|
|
375
375
|
const empty = body.querySelector("kanban_empty");
|
|
376
376
|
if (empty !== null) empty.remove();
|
|
377
|
-
if (reference === null) body.appendChild(this.#
|
|
378
|
-
else body.insertBefore(this.#
|
|
377
|
+
if (reference === null) body.appendChild(this.#dragCard);
|
|
378
|
+
else body.insertBefore(this.#dragCard, reference);
|
|
379
379
|
}
|
|
380
380
|
|
|
381
381
|
#onDropEvent = (event) => {
|
|
382
|
-
if (this.#
|
|
382
|
+
if (this.#dragCard === undefined) return;
|
|
383
383
|
const target = this.#columnFromEvent(event);
|
|
384
384
|
if (target === undefined) return;
|
|
385
385
|
event.preventDefault();
|
|
@@ -391,11 +391,11 @@ class Kanban {
|
|
|
391
391
|
};
|
|
392
392
|
|
|
393
393
|
#finishDrag() {
|
|
394
|
-
const card = this.#
|
|
395
|
-
const from = this.#
|
|
396
|
-
this.#
|
|
397
|
-
this.#
|
|
398
|
-
this.#
|
|
394
|
+
const card = this.#dragCard;
|
|
395
|
+
const from = this.#dragColumn;
|
|
396
|
+
this.#dragCard = undefined;
|
|
397
|
+
this.#dragColumn = undefined;
|
|
398
|
+
this.#columnsBox
|
|
399
399
|
.querySelectorAll(".kanban_column_reject")
|
|
400
400
|
.forEach((node) => node.classList.remove("kanban_column_reject"));
|
|
401
401
|
if (card === undefined) return;
|
|
@@ -427,7 +427,7 @@ class Kanban {
|
|
|
427
427
|
#onClick = (event) => {
|
|
428
428
|
const node = this.#cardFromEvent(event);
|
|
429
429
|
if (node === null || node === undefined) return;
|
|
430
|
-
if (this.#
|
|
430
|
+
if (this.#onCardClick !== undefined) this.#onCardClick(this.getCard(node.dataset.id), node);
|
|
431
431
|
};
|
|
432
432
|
|
|
433
433
|
#onKeyDown = (event) => {
|