chuijs 4.0.2 → 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 +597 -0
- package/README.md +43 -644
- package/framework/appLayout/default/chui_app_layout.js +602 -496
- package/framework/appLayout/default/global_style.css +288 -97
- package/framework/appLayout/default/main_theme_style.css +188 -101
- package/framework/components/chui_accordion/accordion.js +38 -35
- package/framework/components/chui_accordion/styles.css +13 -12
- package/framework/components/chui_action_sheet/action_sheet.js +93 -64
- package/framework/components/chui_action_sheet/styles.css +12 -5
- 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 +16 -11
- package/framework/components/chui_affix/styles.css +5 -0
- package/framework/components/chui_alert/alert.js +34 -19
- package/framework/components/chui_alert/styles.css +7 -0
- package/framework/components/chui_avatar/avatar.js +36 -35
- package/framework/components/chui_avatar/styles.css +1 -1
- package/framework/components/chui_avatar_group/avatar_group.js +25 -23
- package/framework/components/chui_avatar_group/styles.css +1 -1
- package/framework/components/chui_backtop/backtop.js +60 -21
- package/framework/components/chui_backtop/styles.css +21 -0
- package/framework/components/chui_badge/badge.js +30 -28
- 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/breadcrumb.js +15 -13
- package/framework/components/chui_breadcrumb/styles.css +1 -1
- package/framework/components/chui_button/button.js +52 -36
- package/framework/components/chui_button/styles.css +7 -7
- package/framework/components/chui_calendar/calendar.js +18 -16
- package/framework/components/chui_card/card.js +52 -32
- 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 +140 -79
- package/framework/components/chui_chat/styles.css +18 -7
- package/framework/components/chui_clipboard_history/clipboard_history.js +53 -39
- package/framework/components/chui_clipboard_history/styles.css +13 -9
- package/framework/components/chui_code/code.js +10 -10
- package/framework/components/chui_code/styles.css +4 -4
- package/framework/components/chui_code_editor/code_editor.js +73 -57
- package/framework/components/chui_code_editor/styles.css +6 -5
- package/framework/components/chui_command_palette/command_palette.js +87 -64
- package/framework/components/chui_command_palette/styles.css +5 -5
- package/framework/components/chui_console/console.js +13 -13
- package/framework/components/chui_console/styles.css +6 -3
- package/framework/components/chui_content_block/content_block.js +35 -21
- package/framework/components/chui_content_block/styles.css +2 -2
- package/framework/components/chui_context_menu/context_menu.js +171 -58
- package/framework/components/chui_context_menu/styles.css +82 -8
- package/framework/components/chui_custom_element/custom_element.js +25 -18
- package/framework/components/chui_data_grid/data_grid.js +633 -471
- package/framework/components/chui_data_grid/styles.css +24 -22
- package/framework/components/chui_descriptions/descriptions.js +34 -17
- package/framework/components/chui_descriptions/styles.css +1 -1
- package/framework/components/chui_details/details.js +42 -36
- package/framework/components/chui_details/styles.css +12 -11
- package/framework/components/chui_diff_viewer/diff_viewer.js +172 -147
- package/framework/components/chui_diff_viewer/styles.css +10 -10
- package/framework/components/chui_divider/divider.js +19 -17
- package/framework/components/chui_divider/styles.css +2 -2
- package/framework/components/chui_drawer/drawer.js +63 -38
- package/framework/components/chui_drawer/styles.css +18 -4
- package/framework/components/chui_drop_zone/drop_zone.js +37 -27
- package/framework/components/chui_drop_zone/styles.css +10 -6
- package/framework/components/chui_empty_state/empty_state.js +20 -15
- package/framework/components/chui_fieldset/fieldset.js +40 -23
- package/framework/components/chui_fieldset/styles.css +6 -6
- package/framework/components/chui_file_explorer/file_explorer.js +260 -189
- package/framework/components/chui_file_explorer/styles.css +8 -7
- package/framework/components/chui_form/form.js +40 -28
- package/framework/components/chui_form/styles.css +1 -1
- package/framework/components/chui_gantt/gantt.js +102 -78
- package/framework/components/chui_gantt/styles.css +5 -5
- package/framework/components/chui_graphs/graphs.js +376 -239
- package/framework/components/chui_graphs/styles.css +27 -6
- package/framework/components/chui_hero/hero.js +98 -37
- package/framework/components/chui_hero/styles.css +176 -7
- package/framework/components/chui_html_block/html_block.js +8 -8
- package/framework/components/chui_html_block/styles.css +3 -3
- package/framework/components/chui_hx/hx.js +3 -3
- package/framework/components/chui_hx/styles.css +13 -6
- package/framework/components/chui_icons/icons.js +2115 -2115
- package/framework/components/chui_icons/styles.css +4 -3
- package/framework/components/chui_inputs/chui_check_box/check_box.js +31 -19
- package/framework/components/chui_inputs/chui_check_box/styles.css +30 -21
- package/framework/components/chui_inputs/chui_chips/chips.js +141 -70
- package/framework/components/chui_inputs/chui_chips/styles.css +32 -7
- package/framework/components/chui_inputs/chui_color_picker/color_picker.js +55 -38
- package/framework/components/chui_inputs/chui_color_picker/styles.css +7 -7
- package/framework/components/chui_inputs/chui_combo_box/combo_box.js +127 -109
- package/framework/components/chui_inputs/chui_combo_box/styles.css +23 -21
- package/framework/components/chui_inputs/chui_date/date.js +161 -127
- package/framework/components/chui_inputs/chui_date/styles.css +20 -19
- package/framework/components/chui_inputs/chui_date_range/date_range.js +61 -50
- package/framework/components/chui_inputs/chui_date_range/styles.css +3 -3
- package/framework/components/chui_inputs/chui_datetime/datetime.js +47 -39
- package/framework/components/chui_inputs/chui_datetime/styles.css +3 -3
- package/framework/components/chui_inputs/chui_email/email.js +48 -36
- package/framework/components/chui_inputs/chui_email/styles.css +11 -11
- package/framework/components/chui_inputs/chui_file/file.js +71 -44
- package/framework/components/chui_inputs/chui_file/styles.css +23 -19
- package/framework/components/chui_inputs/chui_hotkey/hotkey.js +101 -76
- package/framework/components/chui_inputs/chui_hotkey/styles.css +6 -6
- package/framework/components/chui_inputs/chui_masked/masked.js +83 -72
- package/framework/components/chui_inputs/chui_masked/styles.css +5 -5
- package/framework/components/chui_inputs/chui_mention/mention.js +87 -40
- package/framework/components/chui_inputs/chui_mention/styles.css +14 -8
- package/framework/components/chui_inputs/chui_multi_combo_box/multi_combo_box.js +242 -212
- package/framework/components/chui_inputs/chui_multi_combo_box/styles.css +23 -15
- package/framework/components/chui_inputs/chui_number/number.js +84 -70
- package/framework/components/chui_inputs/chui_number/styles.css +13 -13
- package/framework/components/chui_inputs/chui_otp/otp.js +71 -62
- package/framework/components/chui_inputs/chui_otp/styles.css +5 -5
- package/framework/components/chui_inputs/chui_password/password.js +72 -56
- package/framework/components/chui_inputs/chui_password/styles.css +15 -15
- package/framework/components/chui_inputs/chui_radio_button/radio_button.js +37 -25
- package/framework/components/chui_inputs/chui_radio_button/styles.css +22 -22
- package/framework/components/chui_inputs/chui_rating/rating.js +54 -50
- package/framework/components/chui_inputs/chui_rating/styles.css +3 -3
- package/framework/components/chui_inputs/chui_select_box/select_box.js +132 -108
- package/framework/components/chui_inputs/chui_select_box/styles.css +21 -21
- package/framework/components/chui_inputs/chui_slider/slider.js +41 -38
- package/framework/components/chui_inputs/chui_slider/styles.css +7 -5
- package/framework/components/chui_inputs/chui_text/styles.css +14 -14
- package/framework/components/chui_inputs/chui_text/text.js +69 -52
- package/framework/components/chui_inputs/chui_text_area/styles.css +14 -14
- package/framework/components/chui_inputs/chui_text_area/text_area.js +59 -36
- package/framework/components/chui_inputs/chui_time/styles.css +18 -20
- package/framework/components/chui_inputs/chui_time/time.js +71 -49
- package/framework/components/chui_inputs/chui_toggle/styles.css +13 -6
- package/framework/components/chui_inputs/chui_toggle/toggle.js +27 -27
- package/framework/components/chui_json_editor/json_editor.js +137 -127
- package/framework/components/chui_json_editor/styles.css +5 -5
- package/framework/components/chui_json_viewer/json_viewer.js +133 -114
- package/framework/components/chui_json_viewer/styles.css +9 -8
- package/framework/components/chui_kanban/kanban.js +78 -60
- package/framework/components/chui_kanban/styles.css +8 -4
- package/framework/components/chui_kbd/kbd.js +12 -10
- package/framework/components/chui_kbd/styles.css +1 -1
- package/framework/components/chui_label/label.js +31 -29
- package/framework/components/chui_label/styles.css +3 -3
- package/framework/components/chui_link/link.js +36 -29
- package/framework/components/chui_link/styles.css +11 -4
- package/framework/components/chui_list/list.js +42 -38
- package/framework/components/chui_list/styles.css +4 -3
- package/framework/components/chui_markdown_editor/markdown_editor.js +125 -109
- package/framework/components/chui_markdown_editor/styles.css +5 -5
- package/framework/components/chui_media/audio.js +457 -364
- package/framework/components/chui_media/audio_styles.css +74 -37
- package/framework/components/chui_media/image.js +99 -64
- package/framework/components/chui_media/image_compare.js +86 -55
- package/framework/components/chui_media/image_compare_styles.css +5 -5
- package/framework/components/chui_media/image_styles.css +4 -4
- package/framework/components/chui_media/video.js +264 -171
- package/framework/components/chui_media/video_styles.css +57 -24
- package/framework/components/chui_menu_bar/menu_bar.js +67 -65
- package/framework/components/chui_menu_bar/styles.css +14 -12
- 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 +81 -56
- package/framework/components/chui_modal/styles.css +3 -2
- package/framework/components/chui_notification/notification.js +107 -69
- package/framework/components/chui_notification/notification_download.js +28 -77
- package/framework/components/chui_notification/notification_download_card.js +115 -0
- package/framework/components/chui_notification/notification_download_progress.css +5 -4
- package/framework/components/chui_notification/notification_download_progress.js +73 -105
- package/framework/components/chui_notification/notification_update.js +44 -37
- package/framework/components/chui_notification/status_plate.css +3 -3
- package/framework/components/chui_notification/status_plate.js +2 -2
- package/framework/components/chui_notification/styles.css +6 -1
- package/framework/components/chui_notification/styles_download.css +2 -2
- package/framework/components/chui_notification/styles_update.css +3 -3
- package/framework/components/chui_org_chart/org_chart.js +101 -62
- package/framework/components/chui_org_chart/styles.css +2 -2
- package/framework/components/chui_pagination/pagination.js +65 -30
- package/framework/components/chui_pagination/styles.css +1 -1
- package/framework/components/chui_paragraph/paragraph.js +2 -2
- package/framework/components/chui_paragraph/styles.css +3 -3
- package/framework/components/chui_popover/popover.js +77 -50
- package/framework/components/chui_popover/styles.css +1 -1
- package/framework/components/chui_popups/popups.js +210 -181
- package/framework/components/chui_popups/styles.css +7 -7
- package/framework/components/chui_print_button/print_button.js +48 -33
- package/framework/components/chui_progress_bar/progress_bar.js +49 -19
- package/framework/components/chui_progress_bar/styles.css +6 -6
- package/framework/components/chui_progress_ring/progress_ring.js +32 -30
- package/framework/components/chui_progress_ring/styles.css +1 -1
- package/framework/components/chui_qrcode/qrcode.js +85 -41
- package/framework/components/chui_query_builder/query_builder.js +263 -170
- package/framework/components/chui_query_builder/styles.css +4 -4
- package/framework/components/chui_radio_group/radio_group.js +36 -26
- package/framework/components/chui_radio_group/styles.css +2 -2
- package/framework/components/chui_result/result.js +41 -31
- package/framework/components/chui_result/styles.css +3 -3
- package/framework/components/chui_scheduler/scheduler.js +126 -104
- package/framework/components/chui_scheduler/styles.css +11 -7
- 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 +90 -27
- package/framework/components/chui_segmented_control/styles.css +32 -6
- package/framework/components/chui_settings/settings.js +160 -87
- package/framework/components/chui_settings/styles.css +4 -4
- package/framework/components/chui_shortcut_help/shortcut_help.js +82 -61
- package/framework/components/chui_sidebar_nav/sidebar_nav.js +132 -53
- package/framework/components/chui_sidebar_nav/styles.css +9 -3
- package/framework/components/chui_skeleton/skeleton.js +29 -24
- package/framework/components/chui_slideshow/slideshow.js +122 -103
- package/framework/components/chui_slideshow/styles.css +22 -16
- package/framework/components/chui_spinner/spinner.js +17 -17
- package/framework/components/chui_spinner/styles.css +0 -1
- package/framework/components/chui_split_button/split_button.js +53 -30
- package/framework/components/chui_split_button/styles.css +22 -6
- package/framework/components/chui_splitter/splitter.js +46 -39
- package/framework/components/chui_splitter/styles.css +2 -2
- package/framework/components/chui_statistic/statistic.js +111 -84
- package/framework/components/chui_status_bar/status_bar.js +11 -9
- package/framework/components/chui_status_bar/styles.css +2 -2
- package/framework/components/chui_stepper/stepper.js +230 -54
- package/framework/components/chui_stepper/styles.css +79 -14
- package/framework/components/chui_sticky_bar/sticky_bar.js +53 -17
- package/framework/components/chui_sticky_bar/styles.css +11 -7
- package/framework/components/chui_tabs/chui_tabs.js +100 -46
- package/framework/components/chui_tabs/styles.css +43 -15
- package/framework/components/chui_text_editor/styles.css +24 -23
- package/framework/components/chui_text_editor/text_editor.js +103 -79
- package/framework/components/chui_text_editor/text_editor_panel.js +428 -367
- package/framework/components/chui_theme_toggle/theme_toggle.js +46 -25
- package/framework/components/chui_timeline/styles.css +3 -1
- package/framework/components/chui_timeline/timeline.js +14 -12
- package/framework/components/chui_toast_queue/styles.css +11 -11
- package/framework/components/chui_toast_queue/toast_queue.js +82 -73
- package/framework/components/chui_toolbar/styles.css +2 -2
- package/framework/components/chui_toolbar/toolbar.js +20 -13
- package/framework/components/chui_tooltip/styles.css +2 -2
- package/framework/components/chui_tooltip/tooltip.js +40 -27
- package/framework/components/chui_tour/styles.css +12 -7
- package/framework/components/chui_tour/tour.js +132 -98
- package/framework/components/chui_transfer/styles.css +8 -7
- package/framework/components/chui_transfer/transfer.js +143 -123
- package/framework/components/chui_tree_table/styles.css +4 -4
- package/framework/components/chui_tree_table/tree_table.js +88 -74
- package/framework/components/chui_tree_view/styles.css +14 -10
- package/framework/components/chui_tree_view/tree_view.js +298 -253
- 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 +41 -33
- package/framework/components/chui_webview/styles.css +2 -2
- package/framework/components/chui_webview/webview.js +64 -52
- 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 +153 -123
- package/framework/modules/chui_animations/animations.js +105 -43
- package/framework/modules/chui_animations/motion.js +120 -0
- package/framework/modules/chui_animations/styles.css +37 -4
- package/framework/modules/chui_bridge/preload.js +36 -25
- package/framework/modules/chui_functions.js +69 -63
- package/framework/modules/chui_highlight/chui_highlight.js +25 -22
- package/framework/modules/chui_highlight/styles.css +13 -10
- package/framework/modules/chui_i18n/chui_i18n.js +12 -10
- 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 +65 -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 +12 -8
- package/framework/modules/chui_i18n/locales/validate.js +3 -3
- package/framework/modules/chui_json/chui_json.js +11 -11
- package/framework/modules/chui_layout/chui_layout.js +12 -10
- package/framework/modules/chui_logger/chui_logger.js +47 -28
- package/framework/modules/chui_page/page.js +39 -33
- package/framework/modules/chui_palette/palette.js +61 -0
- package/framework/modules/chui_qr/chui_qr.js +179 -88
- package/framework/modules/chui_scrollbar/chui_scrollbar.js +79 -68
- package/framework/modules/chui_scrollbar/styles.css +4 -2
- package/framework/modules/chui_services/chui_channels.js +27 -13
- package/framework/modules/chui_services/chui_services.js +47 -39
- package/framework/modules/chui_services/desktop.js +108 -101
- package/framework/modules/chui_sortable/chui_sortable.js +33 -28
- package/framework/modules/chui_validate/chui_validate.js +10 -7
- package/framework/tray_bar/chui_menu_items.js +136 -46
- package/index.d.ts +5046 -0
- package/index.js +199 -1254
- package/package.json +81 -68
- package/framework/components/telegram_bot/chui_telegram_bot.js +0 -184
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
const {setStyles} = require("../../modules/chui_functions");
|
|
2
|
-
const {Icon, Icons} = require("../chui_icons/icons");
|
|
3
|
-
const {installHighlightStyles} = require("../../modules/chui_highlight/chui_highlight");
|
|
4
|
-
const {Json} = require("../../modules/chui_json/chui_json");
|
|
5
|
-
const {I18n} = require("../../modules/chui_i18n/chui_i18n");
|
|
1
|
+
const { setStyles } = require("../../modules/chui_functions");
|
|
2
|
+
const { Icon, Icons } = require("../chui_icons/icons");
|
|
3
|
+
const { installHighlightStyles } = require("../../modules/chui_highlight/chui_highlight");
|
|
4
|
+
const { Json } = require("../../modules/chui_json/chui_json");
|
|
5
|
+
const { I18n } = require("../../modules/chui_i18n/chui_i18n");
|
|
6
6
|
|
|
7
7
|
/** Типы узлов JSON */
|
|
8
8
|
const TYPE = {
|
|
@@ -11,7 +11,7 @@ const TYPE = {
|
|
|
11
11
|
STRING: "string",
|
|
12
12
|
NUMBER: "number",
|
|
13
13
|
BOOLEAN: "boolean",
|
|
14
|
-
NULL: "null"
|
|
14
|
+
NULL: "null",
|
|
15
15
|
};
|
|
16
16
|
|
|
17
17
|
/**
|
|
@@ -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,40 +68,42 @@ 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
|
-
#
|
|
82
|
-
|
|
83
|
-
constructor(
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
76
|
+
#titleText = undefined;
|
|
77
|
+
#labelText = undefined;
|
|
78
|
+
#emptyText = undefined;
|
|
79
|
+
#errorObject = undefined;
|
|
80
|
+
#activePath = undefined;
|
|
81
|
+
#focusedPath = undefined;
|
|
82
|
+
|
|
83
|
+
constructor(
|
|
84
|
+
options = {
|
|
85
|
+
id: String(),
|
|
86
|
+
title: String(),
|
|
87
|
+
label: String(),
|
|
88
|
+
value: undefined,
|
|
89
|
+
text: String(),
|
|
90
|
+
expandDepth: Number(),
|
|
91
|
+
expanded: Array(),
|
|
92
|
+
searchable: Boolean(),
|
|
93
|
+
height: String(),
|
|
94
|
+
emptyText: String(),
|
|
95
|
+
}
|
|
96
|
+
) {
|
|
95
97
|
installHighlightStyles();
|
|
96
98
|
setStyles(__dirname + "/styles.css", "chUiJS_JsonViewer");
|
|
97
99
|
JsonViewer.#counter += 1;
|
|
98
100
|
this.#id = options.id === undefined ? `chui_json_viewer_${JsonViewer.#counter}` : options.id;
|
|
99
101
|
this.#root.id = this.#id;
|
|
100
102
|
this.#root.setAttribute("role", "group");
|
|
101
|
-
this.#
|
|
103
|
+
this.#labelText = options.label;
|
|
102
104
|
this.#searchable = options.searchable !== false;
|
|
103
|
-
if (options.emptyText !== undefined) this.#
|
|
104
|
-
else this.#
|
|
105
|
+
if (options.emptyText !== undefined) this.#emptyText = String(options.emptyText);
|
|
106
|
+
else this.#emptyText = I18n.t("jsonViewer.empty");
|
|
105
107
|
this.#title.className = "json_viewer_title";
|
|
106
108
|
this.#title.id = `${this.#id}_title`;
|
|
107
109
|
this.#head.className = "json_viewer_head";
|
|
@@ -128,20 +130,20 @@ class JsonViewer {
|
|
|
128
130
|
this.#status.setAttribute("role", "status");
|
|
129
131
|
this.#status.setAttribute("aria-live", "polite");
|
|
130
132
|
// Кнопка очистки — своя: системная кнопка очистки у `input[type=search]` скрыта (см. стили)
|
|
131
|
-
this.#
|
|
132
|
-
this.#
|
|
133
|
-
this.#
|
|
134
|
-
this.#
|
|
135
|
-
const
|
|
136
|
-
|
|
137
|
-
this.#
|
|
138
|
-
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", () => {
|
|
139
141
|
this.setSearch("");
|
|
140
142
|
this.#search.focus();
|
|
141
143
|
});
|
|
142
|
-
this.#
|
|
143
|
-
this.#
|
|
144
|
-
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);
|
|
145
147
|
this.#syncClear();
|
|
146
148
|
this.#head.appendChild(this.#expand);
|
|
147
149
|
this.#head.appendChild(this.#collapse);
|
|
@@ -153,7 +155,7 @@ class JsonViewer {
|
|
|
153
155
|
this.#root.appendChild(this.#status);
|
|
154
156
|
if (options.title !== undefined) this.setTitle(options.title);
|
|
155
157
|
else this.#title.hidden = true;
|
|
156
|
-
this.setLabel(this.#
|
|
158
|
+
this.setLabel(this.#labelText === undefined ? I18n.t("jsonViewer.title") : this.#labelText);
|
|
157
159
|
// Высота из опций: без неё остаётся своя по умолчанию (320px, дерево прокручивается)
|
|
158
160
|
this.setHeight(options.height === undefined ? this.#height : options.height);
|
|
159
161
|
if (options.text !== undefined) this.setText(options.text);
|
|
@@ -175,11 +177,11 @@ class JsonViewer {
|
|
|
175
177
|
}
|
|
176
178
|
|
|
177
179
|
getTitle() {
|
|
178
|
-
return this.#
|
|
180
|
+
return this.#titleText;
|
|
179
181
|
}
|
|
180
182
|
|
|
181
183
|
getLabel() {
|
|
182
|
-
return this.#
|
|
184
|
+
return this.#labelText;
|
|
183
185
|
}
|
|
184
186
|
|
|
185
187
|
/** Данные как есть (без разбора и сериализации) */
|
|
@@ -189,11 +191,11 @@ class JsonViewer {
|
|
|
189
191
|
|
|
190
192
|
/** Компактный JSON текущих данных */
|
|
191
193
|
getText() {
|
|
192
|
-
return this.#
|
|
194
|
+
return this.#hasValue ? Json.minify(this.#value) : "";
|
|
193
195
|
}
|
|
194
196
|
|
|
195
197
|
hasValue() {
|
|
196
|
-
return this.#
|
|
198
|
+
return this.#hasValue;
|
|
197
199
|
}
|
|
198
200
|
|
|
199
201
|
/** Путь верхнего узла: `$`, дальше `$.ключ`, `$[0]` */
|
|
@@ -203,20 +205,20 @@ class JsonViewer {
|
|
|
203
205
|
|
|
204
206
|
/** Ошибка разбора текста (`text`): `{message, line?, column?, offset?}` или `undefined` */
|
|
205
207
|
getError() {
|
|
206
|
-
return this.#
|
|
208
|
+
return this.#errorObject;
|
|
207
209
|
}
|
|
208
210
|
|
|
209
211
|
/** Текст ошибки разбора словами (пустая строка, если разбор прошёл) */
|
|
210
212
|
getErrorText() {
|
|
211
|
-
return Json.errorText(this.#
|
|
213
|
+
return Json.errorText(this.#errorObject);
|
|
212
214
|
}
|
|
213
215
|
|
|
214
216
|
getSearch() {
|
|
215
|
-
return this.#
|
|
217
|
+
return this.#searchText;
|
|
216
218
|
}
|
|
217
219
|
|
|
218
220
|
isSearching() {
|
|
219
|
-
return this.#
|
|
221
|
+
return this.#searchText.trim() !== "";
|
|
220
222
|
}
|
|
221
223
|
|
|
222
224
|
isSearchable() {
|
|
@@ -230,14 +232,14 @@ class JsonViewer {
|
|
|
230
232
|
|
|
231
233
|
/** Пути совпадений поиска по всему документу */
|
|
232
234
|
getMatches() {
|
|
233
|
-
const query = this.#
|
|
235
|
+
const query = this.#searchText.trim().toLowerCase();
|
|
234
236
|
if (query === "") return [];
|
|
235
237
|
const matches = [];
|
|
236
238
|
const walk = (node) => {
|
|
237
239
|
if (this.#matchesNode(node, query)) matches.push(node.path);
|
|
238
240
|
for (const child of JsonViewer.#childrenOf(node)) walk(child);
|
|
239
241
|
};
|
|
240
|
-
if (this.#
|
|
242
|
+
if (this.#hasValue) walk(this.#rootNode());
|
|
241
243
|
return matches;
|
|
242
244
|
}
|
|
243
245
|
|
|
@@ -254,13 +256,13 @@ class JsonViewer {
|
|
|
254
256
|
}
|
|
255
257
|
|
|
256
258
|
getEmptyText() {
|
|
257
|
-
return this.#
|
|
259
|
+
return this.#emptyText;
|
|
258
260
|
}
|
|
259
261
|
|
|
260
262
|
/** Значение по пути (`$.a.b[2]`) или `undefined`, если такого узла нет */
|
|
261
263
|
getValueAt(path = String()) {
|
|
262
264
|
const segments = JsonViewer.#readPath(path);
|
|
263
|
-
if (segments === undefined || !this.#
|
|
265
|
+
if (segments === undefined || !this.#hasValue) return undefined;
|
|
264
266
|
let current = this.#value;
|
|
265
267
|
for (const segment of segments) {
|
|
266
268
|
if (current === null || current === undefined || typeof current !== "object") return undefined;
|
|
@@ -279,7 +281,7 @@ class JsonViewer {
|
|
|
279
281
|
}
|
|
280
282
|
|
|
281
283
|
setTitle(text = undefined) {
|
|
282
|
-
this.#
|
|
284
|
+
this.#titleText = text;
|
|
283
285
|
if (text === undefined || text === "") {
|
|
284
286
|
this.#title.hidden = true;
|
|
285
287
|
this.#title.innerText = "";
|
|
@@ -293,7 +295,7 @@ class JsonViewer {
|
|
|
293
295
|
}
|
|
294
296
|
|
|
295
297
|
setLabel(text = undefined) {
|
|
296
|
-
this.#
|
|
298
|
+
this.#labelText = text;
|
|
297
299
|
this.#syncLabel();
|
|
298
300
|
return this;
|
|
299
301
|
}
|
|
@@ -301,8 +303,8 @@ class JsonViewer {
|
|
|
301
303
|
/** Данные для показа: любой JSON-совместимый набор (без разбора текста) */
|
|
302
304
|
setValue(value = undefined) {
|
|
303
305
|
this.#value = value;
|
|
304
|
-
this.#
|
|
305
|
-
this.#
|
|
306
|
+
this.#hasValue = value !== undefined;
|
|
307
|
+
this.#errorObject = undefined;
|
|
306
308
|
this.#error.hidden = true;
|
|
307
309
|
this.#expanded = new Set([...this.#expanded].filter((path) => this.#hasPath(path)));
|
|
308
310
|
this.#render();
|
|
@@ -315,15 +317,15 @@ class JsonViewer {
|
|
|
315
317
|
const result = Json.parse(text === undefined || text === null ? "" : text);
|
|
316
318
|
if (!result.ok) {
|
|
317
319
|
this.#value = undefined;
|
|
318
|
-
this.#
|
|
319
|
-
this.#
|
|
320
|
+
this.#hasValue = false;
|
|
321
|
+
this.#errorObject = result.error;
|
|
320
322
|
this.#error.innerText = Json.errorText(result.error);
|
|
321
323
|
this.#error.hidden = false;
|
|
322
324
|
this.#render();
|
|
323
325
|
this.#announce();
|
|
324
326
|
return this;
|
|
325
327
|
}
|
|
326
|
-
this.#
|
|
328
|
+
this.#errorObject = undefined;
|
|
327
329
|
this.#error.hidden = true;
|
|
328
330
|
return this.setValue(result.value);
|
|
329
331
|
}
|
|
@@ -332,7 +334,7 @@ class JsonViewer {
|
|
|
332
334
|
expandDepth(depth = Number()) {
|
|
333
335
|
const limit = Number.isFinite(Number(depth)) ? Math.max(0, Math.floor(Number(depth))) : Infinity;
|
|
334
336
|
this.#expanded = new Set();
|
|
335
|
-
if (this.#
|
|
337
|
+
if (this.#hasValue) {
|
|
336
338
|
const walk = (node, level) => {
|
|
337
339
|
if (level >= limit) return;
|
|
338
340
|
if (!JsonViewer.#isContainer(node.value)) return;
|
|
@@ -361,7 +363,7 @@ class JsonViewer {
|
|
|
361
363
|
|
|
362
364
|
expandAll() {
|
|
363
365
|
this.#expanded = new Set();
|
|
364
|
-
if (this.#
|
|
366
|
+
if (this.#hasValue) {
|
|
365
367
|
const walk = (node) => {
|
|
366
368
|
if (!JsonViewer.#isContainer(node.value)) return;
|
|
367
369
|
this.#expanded.add(node.path);
|
|
@@ -388,8 +390,8 @@ class JsonViewer {
|
|
|
388
390
|
|
|
389
391
|
/** Поиск по ключам и значениям; пустая строка снимает поиск */
|
|
390
392
|
setSearch(query = String()) {
|
|
391
|
-
this.#
|
|
392
|
-
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;
|
|
393
395
|
this.#syncClear();
|
|
394
396
|
this.#render();
|
|
395
397
|
this.#announce();
|
|
@@ -398,7 +400,7 @@ class JsonViewer {
|
|
|
398
400
|
|
|
399
401
|
/** Кнопка очистки видна, только когда есть что очищать */
|
|
400
402
|
#syncClear() {
|
|
401
|
-
this.#
|
|
403
|
+
this.#searchClear.hidden = this.#searchText === "";
|
|
402
404
|
return this;
|
|
403
405
|
}
|
|
404
406
|
|
|
@@ -420,7 +422,7 @@ class JsonViewer {
|
|
|
420
422
|
}
|
|
421
423
|
|
|
422
424
|
setEmptyText(text = String()) {
|
|
423
|
-
this.#
|
|
425
|
+
this.#emptyText = text === undefined ? "" : String(text);
|
|
424
426
|
this.#render();
|
|
425
427
|
return this;
|
|
426
428
|
}
|
|
@@ -471,7 +473,7 @@ class JsonViewer {
|
|
|
471
473
|
const match = /^\.("(?:\\.|[^"\\])*"|[^.[\]]+)/.exec(text.slice(index));
|
|
472
474
|
if (match === null) return undefined;
|
|
473
475
|
const raw = match[1];
|
|
474
|
-
segments.push(raw.startsWith("
|
|
476
|
+
segments.push(raw.startsWith('"') ? JSON.parse(raw) : raw);
|
|
475
477
|
index += match[0].length;
|
|
476
478
|
continue;
|
|
477
479
|
}
|
|
@@ -502,21 +504,30 @@ class JsonViewer {
|
|
|
502
504
|
|
|
503
505
|
static #childrenOf(node = Object()) {
|
|
504
506
|
if (Array.isArray(node.value)) {
|
|
505
|
-
return node.value.map((item, index) => ({
|
|
507
|
+
return node.value.map((item, index) => ({
|
|
508
|
+
path: `${node.path}[${index}]`,
|
|
509
|
+
key: String(index),
|
|
510
|
+
index: index,
|
|
511
|
+
value: item,
|
|
512
|
+
}));
|
|
506
513
|
}
|
|
507
514
|
if (JsonViewer.#typeOf(node.value) === TYPE.OBJECT) {
|
|
508
|
-
return Object.keys(node.value).map((key) => ({
|
|
515
|
+
return Object.keys(node.value).map((key) => ({
|
|
516
|
+
path: `${node.path}.${JsonViewer.#pathKey(key)}`,
|
|
517
|
+
key: key,
|
|
518
|
+
value: node.value[key],
|
|
519
|
+
}));
|
|
509
520
|
}
|
|
510
521
|
return [];
|
|
511
522
|
}
|
|
512
523
|
|
|
513
524
|
#rootNode() {
|
|
514
|
-
return {path: this.getRootPath(), key: undefined, value: this.#value};
|
|
525
|
+
return { path: this.getRootPath(), key: undefined, value: this.#value };
|
|
515
526
|
}
|
|
516
527
|
|
|
517
528
|
/** Есть ли такой путь в текущих данных (для чистки раскрытых путей после setValue) */
|
|
518
529
|
#hasPath(path = String()) {
|
|
519
|
-
if (path === this.getRootPath()) return this.#
|
|
530
|
+
if (path === this.getRootPath()) return this.#hasValue;
|
|
520
531
|
const segments = JsonViewer.#readPath(path);
|
|
521
532
|
return segments !== undefined && this.#valueAt(segments) !== undefined;
|
|
522
533
|
}
|
|
@@ -550,12 +561,12 @@ class JsonViewer {
|
|
|
550
561
|
|
|
551
562
|
/** Видимые узлы деревом: при поиске — совпадения с предками, без поиска — раскрытые ветки */
|
|
552
563
|
#visibleNodes() {
|
|
553
|
-
if (!this.#
|
|
564
|
+
if (!this.#hasValue) return [];
|
|
554
565
|
const list = [];
|
|
555
|
-
const query = this.#
|
|
566
|
+
const query = this.#searchText.trim().toLowerCase();
|
|
556
567
|
const walk = (node, level) => {
|
|
557
568
|
if (query !== "" && !this.#matchesTree(node, query)) return;
|
|
558
|
-
list.push({node: node, level: level});
|
|
569
|
+
list.push({ node: node, level: level });
|
|
559
570
|
if (!this.#isOpen(node, query)) return;
|
|
560
571
|
for (const child of JsonViewer.#childrenOf(node)) walk(child, level + 1);
|
|
561
572
|
};
|
|
@@ -571,13 +582,13 @@ class JsonViewer {
|
|
|
571
582
|
}
|
|
572
583
|
|
|
573
584
|
#accessibleName() {
|
|
574
|
-
if (this.#
|
|
575
|
-
if (this.#
|
|
585
|
+
if (this.#titleText !== undefined && this.#titleText !== "") return this.#titleText;
|
|
586
|
+
if (this.#labelText !== undefined && this.#labelText !== "") return this.#labelText;
|
|
576
587
|
return I18n.t("jsonViewer.title");
|
|
577
588
|
}
|
|
578
589
|
|
|
579
590
|
#syncLabel() {
|
|
580
|
-
if (this.#
|
|
591
|
+
if (this.#titleText !== undefined && this.#titleText !== "") {
|
|
581
592
|
this.#root.setAttribute("aria-labelledby", this.#title.id);
|
|
582
593
|
this.#root.removeAttribute("aria-label");
|
|
583
594
|
} else {
|
|
@@ -585,14 +596,14 @@ class JsonViewer {
|
|
|
585
596
|
this.#root.setAttribute("aria-label", this.#accessibleName());
|
|
586
597
|
}
|
|
587
598
|
// Дерево внутри тоже с ролью, поэтому ему нужно своё имя — оттуда же
|
|
588
|
-
this.#tree.setAttribute("aria-label", I18n.t("jsonViewer.dataTree", {name: this.#accessibleName()}));
|
|
599
|
+
this.#tree.setAttribute("aria-label", I18n.t("jsonViewer.dataTree", { name: this.#accessibleName() }));
|
|
589
600
|
return this;
|
|
590
601
|
}
|
|
591
602
|
|
|
592
603
|
#summaryText(value = undefined) {
|
|
593
604
|
// Форму числа выбирает словарь через `Intl.PluralRules` — русские склонения больше не в коде
|
|
594
|
-
if (Array.isArray(value)) return I18n.t("jsonViewer.elements", {count: value.length});
|
|
595
|
-
return I18n.t("jsonViewer.properties", {count: Object.keys(value).length});
|
|
605
|
+
if (Array.isArray(value)) return I18n.t("jsonViewer.elements", { count: value.length });
|
|
606
|
+
return I18n.t("jsonViewer.properties", { count: Object.keys(value).length });
|
|
596
607
|
}
|
|
597
608
|
|
|
598
609
|
#toggleNode(node = Object(), open = Boolean()) {
|
|
@@ -601,7 +612,10 @@ class JsonViewer {
|
|
|
601
612
|
toggle.className = "json_viewer_toggle";
|
|
602
613
|
// Стрелка не отдельная остановка: у дерева одна остановка на узел
|
|
603
614
|
toggle.setAttribute("tabindex", "-1");
|
|
604
|
-
toggle.setAttribute(
|
|
615
|
+
toggle.setAttribute(
|
|
616
|
+
"aria-label",
|
|
617
|
+
I18n.t(open ? "a11y.collapseNode" : "a11y.expandNode", { name: this.#nodeName(node) })
|
|
618
|
+
);
|
|
605
619
|
toggle.dataset.path = node.path;
|
|
606
620
|
const glyph = new Icon(Icons.NAVIGATION.CHEVRON_RIGHT, "18px").set();
|
|
607
621
|
glyph.setAttribute("aria-hidden", "true");
|
|
@@ -612,7 +626,7 @@ class JsonViewer {
|
|
|
612
626
|
#rowNode(entry = Object()) {
|
|
613
627
|
const node = entry.node;
|
|
614
628
|
const container = JsonViewer.#isContainer(node.value);
|
|
615
|
-
const query = this.#
|
|
629
|
+
const query = this.#searchText.trim().toLowerCase();
|
|
616
630
|
const open = this.#isOpen(node, query);
|
|
617
631
|
const row = document.createElement("div");
|
|
618
632
|
row.className = "json_viewer_row";
|
|
@@ -652,18 +666,18 @@ class JsonViewer {
|
|
|
652
666
|
if (type === TYPE.OBJECT || type === TYPE.ARRAY) {
|
|
653
667
|
const wrap = document.createElement("span");
|
|
654
668
|
wrap.className = "json_viewer_container";
|
|
655
|
-
const [
|
|
669
|
+
const [openBrace, closeBrace] = type === TYPE.ARRAY ? ["[", "]"] : ["{", "}"];
|
|
656
670
|
const left = document.createElement("span");
|
|
657
671
|
left.className = "json_viewer_brace code_token_operator";
|
|
658
672
|
left.setAttribute("aria-hidden", "true");
|
|
659
|
-
left.innerText =
|
|
673
|
+
left.innerText = openBrace;
|
|
660
674
|
const summary = document.createElement("span");
|
|
661
675
|
summary.className = "json_viewer_summary";
|
|
662
676
|
summary.innerText = this.#summaryText(node.value);
|
|
663
677
|
const right = document.createElement("span");
|
|
664
678
|
right.className = "json_viewer_brace code_token_operator";
|
|
665
679
|
right.setAttribute("aria-hidden", "true");
|
|
666
|
-
right.innerText =
|
|
680
|
+
right.innerText = closeBrace;
|
|
667
681
|
wrap.appendChild(left);
|
|
668
682
|
wrap.appendChild(summary);
|
|
669
683
|
wrap.appendChild(right);
|
|
@@ -691,26 +705,29 @@ class JsonViewer {
|
|
|
691
705
|
this.#render();
|
|
692
706
|
if (silent) return this;
|
|
693
707
|
const name = segments.length === 0 ? this.#accessibleName() : String(segments[segments.length - 1]);
|
|
694
|
-
this.#announce(
|
|
708
|
+
this.#announce(
|
|
709
|
+
value ? I18n.t("jsonViewer.expanded", { name: name }) : I18n.t("jsonViewer.collapsed", { name: name })
|
|
710
|
+
);
|
|
695
711
|
return this;
|
|
696
712
|
}
|
|
697
713
|
|
|
698
714
|
#announce() {
|
|
699
|
-
const query = this.#
|
|
715
|
+
const query = this.#searchText.trim();
|
|
700
716
|
if (query !== "") {
|
|
701
717
|
const matches = this.getMatches().length;
|
|
702
|
-
this.#status.innerText =
|
|
718
|
+
this.#status.innerText =
|
|
719
|
+
matches === 0 ? I18n.t("common.nothingFound") : I18n.t("jsonViewer.found", { count: matches });
|
|
703
720
|
return this;
|
|
704
721
|
}
|
|
705
|
-
if (this.#
|
|
706
|
-
this.#status.innerText = Json.errorText(this.#
|
|
722
|
+
if (this.#errorObject !== undefined) {
|
|
723
|
+
this.#status.innerText = Json.errorText(this.#errorObject);
|
|
707
724
|
return this;
|
|
708
725
|
}
|
|
709
|
-
if (!this.#
|
|
710
|
-
this.#status.innerText = this.#
|
|
726
|
+
if (!this.#hasValue) {
|
|
727
|
+
this.#status.innerText = this.#emptyText;
|
|
711
728
|
return this;
|
|
712
729
|
}
|
|
713
|
-
this.#status.innerText = I18n.t("jsonViewer.visible", {count: this.#visibleNodes().length});
|
|
730
|
+
this.#status.innerText = I18n.t("jsonViewer.visible", { count: this.#visibleNodes().length });
|
|
714
731
|
return this;
|
|
715
732
|
}
|
|
716
733
|
|
|
@@ -718,15 +735,15 @@ class JsonViewer {
|
|
|
718
735
|
// Узлы пересобираются, а фокус живёт на строке: запоминаем путь до перерисовки
|
|
719
736
|
const active = document.activeElement;
|
|
720
737
|
const focused = active === null || !this.#tree.contains(active) ? null : active.closest(".json_viewer_row");
|
|
721
|
-
if (focused !== null && focused.dataset.path !== undefined) this.#
|
|
738
|
+
if (focused !== null && focused.dataset.path !== undefined) this.#focusedPath = focused.dataset.path;
|
|
722
739
|
this.#tree.innerHTML = "";
|
|
723
740
|
const list = this.#visibleNodes();
|
|
724
741
|
for (const entry of list) this.#tree.appendChild(this.#rowNode(entry));
|
|
725
742
|
// Пояснение вместо дерева: пустые данные, ничего не найдено или ошибка разбора
|
|
726
|
-
const searching = this.#
|
|
743
|
+
const searching = this.#searchText.trim() !== "";
|
|
727
744
|
this.#tree.hidden = list.length === 0;
|
|
728
|
-
this.#empty.innerText = searching ? I18n.t("common.nothingFound") : this.#
|
|
729
|
-
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;
|
|
730
747
|
this.#applyStop();
|
|
731
748
|
return this;
|
|
732
749
|
}
|
|
@@ -736,13 +753,13 @@ class JsonViewer {
|
|
|
736
753
|
const list = [...this.#tree.querySelectorAll(".json_viewer_row")];
|
|
737
754
|
if (list.length === 0) return;
|
|
738
755
|
const stop =
|
|
739
|
-
list.find((row) => row.dataset.path === this.#
|
|
740
|
-
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) ??
|
|
741
758
|
list[0];
|
|
742
|
-
this.#
|
|
759
|
+
this.#activePath = stop.dataset.path;
|
|
743
760
|
for (const row of list) row.setAttribute("tabindex", row === stop ? "0" : "-1");
|
|
744
|
-
if (this.#
|
|
745
|
-
this.#
|
|
761
|
+
if (this.#focusedPath !== undefined && stop.dataset.path === this.#focusedPath) {
|
|
762
|
+
this.#focusedPath = undefined;
|
|
746
763
|
stop.focus();
|
|
747
764
|
}
|
|
748
765
|
return this;
|
|
@@ -750,7 +767,7 @@ class JsonViewer {
|
|
|
750
767
|
|
|
751
768
|
#focusRow(row = undefined) {
|
|
752
769
|
if (row === undefined || row === null) return this;
|
|
753
|
-
this.#
|
|
770
|
+
this.#activePath = row.dataset.path;
|
|
754
771
|
for (const other of this.#tree.querySelectorAll(".json_viewer_row")) {
|
|
755
772
|
other.setAttribute("tabindex", other === row ? "0" : "-1");
|
|
756
773
|
}
|
|
@@ -759,10 +776,12 @@ class JsonViewer {
|
|
|
759
776
|
}
|
|
760
777
|
|
|
761
778
|
#focusPath(path = String()) {
|
|
762
|
-
const row = [...this.#tree.querySelectorAll(".json_viewer_row")].find(
|
|
779
|
+
const row = [...this.#tree.querySelectorAll(".json_viewer_row")].find(
|
|
780
|
+
(node) => node.dataset.path === String(path)
|
|
781
|
+
);
|
|
763
782
|
if (row === undefined) return this;
|
|
764
783
|
this.#focusRow(row);
|
|
765
|
-
row.scrollIntoView({block: "nearest"});
|
|
784
|
+
row.scrollIntoView({ block: "nearest" });
|
|
766
785
|
return this;
|
|
767
786
|
}
|
|
768
787
|
|
|
@@ -789,7 +808,7 @@ class JsonViewer {
|
|
|
789
808
|
#onFocusIn = (event) => {
|
|
790
809
|
const row = event.target instanceof Element ? event.target.closest(".json_viewer_row") : null;
|
|
791
810
|
if (row === null || row.dataset.path === undefined) return;
|
|
792
|
-
this.#
|
|
811
|
+
this.#activePath = row.dataset.path;
|
|
793
812
|
};
|
|
794
813
|
|
|
795
814
|
#onSearch = () => {
|
|
@@ -806,7 +825,7 @@ class JsonViewer {
|
|
|
806
825
|
const list = this.#tree.querySelectorAll(".json_viewer_row");
|
|
807
826
|
if (list.length === 0) return;
|
|
808
827
|
// Нажатия на самой стрелке (настоящая кнопка) не перехватываем
|
|
809
|
-
const
|
|
828
|
+
const fromButton = event.target instanceof Element && event.target.closest("button") !== null;
|
|
810
829
|
const row = this.#currentRow(event.target instanceof Element ? event.target : undefined);
|
|
811
830
|
const path = row === null ? undefined : row.dataset.path;
|
|
812
831
|
const segments = path === undefined ? undefined : JsonViewer.#readPath(path);
|
|
@@ -830,14 +849,14 @@ class JsonViewer {
|
|
|
830
849
|
this.#focusRow(list[list.length - 1]);
|
|
831
850
|
return;
|
|
832
851
|
case "ArrowRight": {
|
|
833
|
-
if (
|
|
852
|
+
if (fromButton || !container) return;
|
|
834
853
|
event.preventDefault();
|
|
835
854
|
if (!this.#expanded.has(path)) this.expand(path);
|
|
836
855
|
else this.#step(row, 1);
|
|
837
856
|
return;
|
|
838
857
|
}
|
|
839
858
|
case "ArrowLeft": {
|
|
840
|
-
if (
|
|
859
|
+
if (fromButton || path === undefined) return;
|
|
841
860
|
event.preventDefault();
|
|
842
861
|
if (container && this.#expanded.has(path)) {
|
|
843
862
|
this.collapse(path);
|
|
@@ -849,7 +868,7 @@ class JsonViewer {
|
|
|
849
868
|
}
|
|
850
869
|
case "Enter":
|
|
851
870
|
case " ": {
|
|
852
|
-
if (
|
|
871
|
+
if (fromButton || !container) return;
|
|
853
872
|
event.preventDefault();
|
|
854
873
|
this.toggle(path);
|
|
855
874
|
return;
|
|
@@ -860,4 +879,4 @@ class JsonViewer {
|
|
|
860
879
|
};
|
|
861
880
|
}
|
|
862
881
|
|
|
863
|
-
exports.JsonViewer = JsonViewer
|
|
882
|
+
exports.JsonViewer = JsonViewer;
|
|
@@ -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;
|
|
@@ -53,9 +53,10 @@ chui_json_viewer {
|
|
|
53
53
|
height: var(--control_height);
|
|
54
54
|
margin: 0;
|
|
55
55
|
/* Место под кнопку очистки, чтобы текст не заезжал под неё */
|
|
56
|
-
padding-block: 0 0;
|
|
56
|
+
padding-block: 0 0;
|
|
57
|
+
padding-inline: 12px 40px;
|
|
57
58
|
border: 1px solid var(--border_color);
|
|
58
|
-
border-radius: var(--
|
|
59
|
+
border-radius: var(--radius_sm);
|
|
59
60
|
background: var(--element_background);
|
|
60
61
|
color: var(--text_color);
|
|
61
62
|
font-family: inherit;
|
|
@@ -119,7 +120,7 @@ chui_json_viewer {
|
|
|
119
120
|
margin: 0;
|
|
120
121
|
padding: 0 12px;
|
|
121
122
|
border: 1px solid var(--border_color);
|
|
122
|
-
border-radius: var(--
|
|
123
|
+
border-radius: var(--radius_sm);
|
|
123
124
|
background: var(--element_background);
|
|
124
125
|
color: var(--text_color);
|
|
125
126
|
font-family: inherit;
|
|
@@ -143,7 +144,7 @@ chui_json_viewer {
|
|
|
143
144
|
width: 100%;
|
|
144
145
|
overflow: auto;
|
|
145
146
|
padding: 4px 0;
|
|
146
|
-
font-family:
|
|
147
|
+
font-family: "chui_mono", monospace;
|
|
147
148
|
font-size: var(--font_default_size);
|
|
148
149
|
}
|
|
149
150
|
|