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
|
@@ -1,17 +1,94 @@
|
|
|
1
|
+
/* Шапка страницы: значок, заголовок, описание и строка статистики.
|
|
2
|
+
Украшение — из акцентов палитры, смешанных с нейтральной заливкой и рамкой
|
|
3
|
+
(`color-mix` над токенами), поэтому мимо таблицы цвет не заведён и обе схемы работают
|
|
4
|
+
сами. Движение — по системе движения: шапка приходит кадром появления из
|
|
5
|
+
`global_style.css`, знак и плитки встают со ступенькой задержки, а по подложке один
|
|
6
|
+
раз проходит блик. Непрерывных кадров нет намеренно: шапка — не индикатор ожидания,
|
|
7
|
+
а неподвижная поверхность, по которой не должно бегать движение. */
|
|
1
8
|
chui_hero {
|
|
9
|
+
position: relative;
|
|
2
10
|
display: flex;
|
|
3
11
|
flex-direction: column;
|
|
4
12
|
gap: 16px;
|
|
5
13
|
box-sizing: border-box;
|
|
6
14
|
width: -webkit-fill-available;
|
|
7
15
|
padding: 20px 22px;
|
|
16
|
+
/* Блик проходит по подложке и уходит за край — его и обрезает коробка */
|
|
17
|
+
overflow: hidden;
|
|
8
18
|
border: 1px solid var(--border_color);
|
|
9
19
|
border-radius: var(--radius_md);
|
|
10
|
-
|
|
20
|
+
/* Свечение акцентов лежит на нейтральной заливке: она читается и на карточке,
|
|
21
|
+
и на подложке (вложенная поверхность), а свечение даёт цвет там, где его не хватает */
|
|
22
|
+
background:
|
|
23
|
+
radial-gradient(
|
|
24
|
+
120% 100% at 100% 0%,
|
|
25
|
+
color-mix(in srgb, var(--blue_prime_background) 18%, transparent),
|
|
26
|
+
transparent 62%
|
|
27
|
+
),
|
|
28
|
+
radial-gradient(
|
|
29
|
+
100% 90% at 0% 100%,
|
|
30
|
+
color-mix(in srgb, var(--teal_prime_background) 16%, transparent),
|
|
31
|
+
transparent 66%
|
|
32
|
+
),
|
|
33
|
+
var(--element_background);
|
|
11
34
|
box-shadow: var(--box_shadow_main);
|
|
12
35
|
font-size: var(--font_default_size);
|
|
13
36
|
color: var(--text_color);
|
|
14
37
|
text-align: start;
|
|
38
|
+
animation: chui_appear_up var(--motion_base) var(--motion_ease) both;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/* Акцентная линия сверху: три акцента палитры одним градиентом — синий, циан, мята.
|
|
42
|
+
Без неё шапка читалась бы обычной карточкой. Линия не появляется готовой, а прочерчивается
|
|
43
|
+
слева направо: это первый кадр шапки, и он задаёт направление всему появлению */
|
|
44
|
+
chui_hero::before {
|
|
45
|
+
content: "";
|
|
46
|
+
position: absolute;
|
|
47
|
+
inset-inline: 0;
|
|
48
|
+
top: 0;
|
|
49
|
+
height: 3px;
|
|
50
|
+
background: linear-gradient(
|
|
51
|
+
90deg,
|
|
52
|
+
var(--blue_prime_background),
|
|
53
|
+
var(--cyan_prime_background) 55%,
|
|
54
|
+
var(--mint_prime_background)
|
|
55
|
+
);
|
|
56
|
+
transform-origin: left center;
|
|
57
|
+
animation: hero_line_in var(--motion_slow) var(--motion_ease) both;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
@keyframes hero_line_in {
|
|
61
|
+
from {
|
|
62
|
+
transform: scaleX(0);
|
|
63
|
+
}
|
|
64
|
+
to {
|
|
65
|
+
transform: scaleX(1);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/* Блик: один раз проходит по подложке и уходит за край. Цвет берётся из текста темы —
|
|
70
|
+
белая полоса на светлой схеме не видна вовсе */
|
|
71
|
+
chui_hero::after {
|
|
72
|
+
content: "";
|
|
73
|
+
position: absolute;
|
|
74
|
+
top: -20%;
|
|
75
|
+
bottom: -20%;
|
|
76
|
+
width: 42%;
|
|
77
|
+
background: linear-gradient(90deg, transparent, color-mix(in srgb, var(--text_color) 7%, transparent), transparent);
|
|
78
|
+
transform: translateX(-140%) skewX(-14deg);
|
|
79
|
+
pointer-events: none;
|
|
80
|
+
/* `both` держит конечное положение — блик остаётся за краем, а не возвращается назад.
|
|
81
|
+
Идёт последним: подложка к этому времени уже собралась, и блик не спорит с появлением */
|
|
82
|
+
animation: hero_shine var(--motion_slow) var(--motion_ease) calc(var(--motion_fast) * 2) both;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
@keyframes hero_shine {
|
|
86
|
+
from {
|
|
87
|
+
transform: translateX(-140%) skewX(-14deg);
|
|
88
|
+
}
|
|
89
|
+
to {
|
|
90
|
+
transform: translateX(240%) skewX(-14deg);
|
|
91
|
+
}
|
|
15
92
|
}
|
|
16
93
|
|
|
17
94
|
chui_hero hero_head {
|
|
@@ -28,8 +105,46 @@ chui_hero hero_badge {
|
|
|
28
105
|
width: 54px;
|
|
29
106
|
height: 54px;
|
|
30
107
|
border-radius: var(--radius_md);
|
|
31
|
-
|
|
32
|
-
|
|
108
|
+
/* Знак — единственная заливка во весь цвет: он и держит акцент, когда текст
|
|
109
|
+
читается цветом темы */
|
|
110
|
+
background: linear-gradient(135deg, var(--blue_prime_background), var(--indigo_prime_background));
|
|
111
|
+
box-shadow: 0 6px 18px color-mix(in srgb, var(--blue_prime_background) 35%, transparent);
|
|
112
|
+
animation: hero_badge_in var(--motion_base) var(--motion_spring) both;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/* Знак встаёт с лёгким перелётом и поворотом: он приходит первым в шапке */
|
|
116
|
+
@keyframes hero_badge_in {
|
|
117
|
+
from {
|
|
118
|
+
opacity: 0;
|
|
119
|
+
transform: scale(0.82) rotate(-8deg);
|
|
120
|
+
}
|
|
121
|
+
to {
|
|
122
|
+
opacity: 1;
|
|
123
|
+
transform: scale(1) rotate(0deg);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/* Отклик знака: от него один раз расходится кольцо — знак «встал на место».
|
|
128
|
+
Не по кругу: шапка — не индикатор ожидания, и непрерывного движения в ней быть не должно */
|
|
129
|
+
chui_hero hero_badge::after {
|
|
130
|
+
content: "";
|
|
131
|
+
position: absolute;
|
|
132
|
+
inset: 0;
|
|
133
|
+
border: 2px solid var(--blue_prime_background);
|
|
134
|
+
border-radius: var(--radius_md);
|
|
135
|
+
pointer-events: none;
|
|
136
|
+
animation: hero_badge_ring var(--motion_slow) var(--motion_ease) var(--motion_fast) both;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
@keyframes hero_badge_ring {
|
|
140
|
+
from {
|
|
141
|
+
opacity: 0.45;
|
|
142
|
+
transform: scale(0.86);
|
|
143
|
+
}
|
|
144
|
+
to {
|
|
145
|
+
opacity: 0;
|
|
146
|
+
transform: scale(1.5);
|
|
147
|
+
}
|
|
33
148
|
}
|
|
34
149
|
|
|
35
150
|
chui_hero hero_badge chui_icon {
|
|
@@ -51,7 +166,12 @@ chui_hero hero_title {
|
|
|
51
166
|
font-size: var(--font_title_size);
|
|
52
167
|
font-weight: 600;
|
|
53
168
|
letter-spacing: -0.02em;
|
|
169
|
+
/* Заголовок переносится по смыслу, а не по длине строки */
|
|
170
|
+
text-wrap: balance;
|
|
54
171
|
color: var(--text_color);
|
|
172
|
+
/* Ступенька: линия — знак — заголовок и дальше. Шаг — доля токена движения,
|
|
173
|
+
а не своё число */
|
|
174
|
+
animation: chui_appear_up var(--motion_base) var(--motion_ease) calc(var(--motion_fast) / 2) both;
|
|
55
175
|
}
|
|
56
176
|
|
|
57
177
|
chui_hero hero_description {
|
|
@@ -63,6 +183,7 @@ chui_hero hero_description {
|
|
|
63
183
|
/* Описание героя — обычный текст (было 13px, размера вне шкалы) */
|
|
64
184
|
font-size: var(--font_default_size);
|
|
65
185
|
color: var(--text_color_disabled);
|
|
186
|
+
animation: chui_appear_up var(--motion_base) var(--motion_ease) var(--motion_fast) both;
|
|
66
187
|
}
|
|
67
188
|
|
|
68
189
|
chui_hero hero_stats {
|
|
@@ -71,21 +192,69 @@ chui_hero hero_stats {
|
|
|
71
192
|
gap: 10px;
|
|
72
193
|
}
|
|
73
194
|
|
|
195
|
+
/* Плитка статистики. Свой акцент задаёт `data-accent` (его ставит компонент, ведя список
|
|
196
|
+
по кругу): цвет идёт заливкой, рамкой и полосой, а число читается цветом темы —
|
|
197
|
+
акцентный текст на тинте дал бы контраст ниже 3 даже для крупной строки */
|
|
74
198
|
chui_hero hero_stat {
|
|
199
|
+
--hero_accent: var(--blue_prime_background);
|
|
200
|
+
position: relative;
|
|
75
201
|
display: flex;
|
|
76
202
|
flex-direction: column;
|
|
77
203
|
gap: 1px;
|
|
78
204
|
min-width: 104px;
|
|
79
|
-
padding: 8px 14px;
|
|
80
|
-
border: 1px solid var(--border_color);
|
|
205
|
+
padding: 8px 14px 8px 18px;
|
|
206
|
+
border: 1px solid color-mix(in srgb, var(--hero_accent) 34%, var(--border_color));
|
|
81
207
|
border-radius: var(--radius_md);
|
|
82
|
-
background: var(--element_background_2);
|
|
208
|
+
background: color-mix(in srgb, var(--hero_accent) 12%, var(--element_background_2));
|
|
209
|
+
/* Плитки встают по очереди: номер ставит компонент переменной `--hero_stat_index`,
|
|
210
|
+
а ступенька считается от той же задержки, что у описания, поэтому порядок
|
|
211
|
+
появления один: линия, знак, заголовок, описание, плитки, блик */
|
|
212
|
+
animation: chui_appear_up var(--motion_base) var(--motion_ease) both;
|
|
213
|
+
animation-delay: calc(var(--motion_base) + var(--motion_fast) * var(--hero_stat_index, 0));
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/* Акцентная полоса слева: даже когда плиток много, их ряд читается цветным.
|
|
217
|
+
Она прочерчивается сверху вниз вместе с приходом своей плитки */
|
|
218
|
+
chui_hero hero_stat::before {
|
|
219
|
+
content: "";
|
|
220
|
+
position: absolute;
|
|
221
|
+
inset-block: 8px;
|
|
222
|
+
inset-inline-start: 8px;
|
|
223
|
+
width: 3px;
|
|
224
|
+
border-radius: var(--radius_pill);
|
|
225
|
+
background: var(--hero_accent);
|
|
226
|
+
transform-origin: top center;
|
|
227
|
+
animation: hero_stat_bar_in var(--motion_base) var(--motion_ease) both;
|
|
228
|
+
animation-delay: calc(var(--motion_base) + var(--motion_fast) * var(--hero_stat_index, 0));
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
@keyframes hero_stat_bar_in {
|
|
232
|
+
from {
|
|
233
|
+
transform: scaleY(0);
|
|
234
|
+
}
|
|
235
|
+
to {
|
|
236
|
+
transform: scaleY(1);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
chui_hero hero_stat[data-accent="purple"] {
|
|
241
|
+
--hero_accent: var(--purple_prime_background);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
chui_hero hero_stat[data-accent="green"] {
|
|
245
|
+
--hero_accent: var(--green_prime_background);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
chui_hero hero_stat[data-accent="orange"] {
|
|
249
|
+
--hero_accent: var(--orange_prime_background);
|
|
83
250
|
}
|
|
84
251
|
|
|
85
252
|
chui_hero hero_stat_value {
|
|
86
253
|
font-size: var(--font_lead_size);
|
|
87
254
|
font-weight: 600;
|
|
88
|
-
|
|
255
|
+
/* Числа не "плывут" при смене значения: ширины цифр равны */
|
|
256
|
+
font-variant-numeric: tabular-nums;
|
|
257
|
+
color: var(--text_color);
|
|
89
258
|
}
|
|
90
259
|
|
|
91
260
|
chui_hero hero_stat_label {
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
class HtmlBlock {
|
|
2
2
|
#id = require("randomstring").generate();
|
|
3
|
-
#
|
|
3
|
+
#htmlBlock = document.createElement("chui_html_block");
|
|
4
4
|
constructor(width = String()) {
|
|
5
5
|
require("../../modules/chui_functions").setStyles(__dirname + "/styles.css", "chUiJS_HtmlBlock");
|
|
6
|
-
this.#
|
|
7
|
-
this.#
|
|
6
|
+
this.#htmlBlock.setAttribute("id", this.#id);
|
|
7
|
+
this.#htmlBlock.style.width = width;
|
|
8
8
|
}
|
|
9
9
|
setHtml(html) {
|
|
10
|
-
this.#
|
|
10
|
+
this.#htmlBlock.innerHTML = html;
|
|
11
11
|
}
|
|
12
12
|
set() {
|
|
13
|
-
return this.#
|
|
13
|
+
return this.#htmlBlock;
|
|
14
14
|
}
|
|
15
15
|
}
|
|
16
16
|
|
|
@@ -6,12 +6,12 @@ h5,
|
|
|
6
6
|
h6 {
|
|
7
7
|
height: max-content;
|
|
8
8
|
/* Ширина по контейнеру: с max-content длинный заголовок не переносился,
|
|
9
|
-
а с margin: var(--
|
|
9
|
+
а с margin: var(--block_margin) уезжал вправо за край родителя */
|
|
10
10
|
width: -webkit-fill-available;
|
|
11
11
|
/* Слово шире строки разрывается, а не вылезает за заголовок */
|
|
12
12
|
overflow-wrap: break-word;
|
|
13
13
|
color: var(--text_color);
|
|
14
|
-
margin: var(--
|
|
14
|
+
margin: var(--block_margin);
|
|
15
15
|
font-weight: 500;
|
|
16
16
|
}
|
|
17
17
|
|
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
class Icon {
|
|
2
|
-
#
|
|
2
|
+
#chuiIcon = document.createElement("chui_icon");
|
|
3
3
|
constructor(name = String(), size = String(), color = String()) {
|
|
4
4
|
require("../../modules/chui_functions").setStyles(__dirname + "/styles.css", "chUiJS_Icons");
|
|
5
5
|
// Пустое имя — пустая иконка: без этого `innerHTML = undefined` рисовал лигатуру «undefined»
|
|
6
|
-
this.#
|
|
7
|
-
this.#
|
|
8
|
-
this.#
|
|
6
|
+
this.#chuiIcon.textContent = name === undefined || name === null ? "" : String(name);
|
|
7
|
+
this.#chuiIcon.style.fontSize = size === undefined ? "" : size;
|
|
8
|
+
this.#chuiIcon.style.color = color === undefined ? "" : color;
|
|
9
9
|
// Значок — украшение: его лигатура («table_chart», «expand_more») ничего не говорит
|
|
10
10
|
// скринридеру, поэтому по умолчанию он скрыт от дерева доступности, а имя даёт тот,
|
|
11
11
|
// кто значок поставил (подпись кнопки, пункта меню или скрытая подпись рядом).
|
|
12
12
|
// Значащий значок можно вернуть: `icon.set().removeAttribute("aria-hidden")`
|
|
13
|
-
this.#
|
|
13
|
+
this.#chuiIcon.setAttribute("aria-hidden", "true");
|
|
14
14
|
}
|
|
15
15
|
getHTML() {
|
|
16
|
-
return this.#
|
|
16
|
+
return this.#chuiIcon.outerHTML;
|
|
17
17
|
}
|
|
18
18
|
set() {
|
|
19
|
-
return this.#
|
|
19
|
+
return this.#chuiIcon;
|
|
20
20
|
}
|
|
21
21
|
}
|
|
22
22
|
|
|
@@ -10,5 +10,6 @@ chui_icon {
|
|
|
10
10
|
direction: ltr;
|
|
11
11
|
color: var(--text_color);
|
|
12
12
|
pointer-events: none;
|
|
13
|
-
|
|
13
|
+
/* Глиф меняет только цвет: `all` тянул бы за собой и вёрстку, если она когда-нибудь изменится */
|
|
14
|
+
transition: color var(--motion_fast) var(--motion_ease);
|
|
14
15
|
}
|
|
@@ -4,12 +4,12 @@ checkbox {
|
|
|
4
4
|
карточку. Токены переопределены у корня поля, поэтому действуют только внутри него
|
|
5
5
|
(тот же приём у полосы меню-бара). */
|
|
6
6
|
--control_padding: var(--control_padding_sm);
|
|
7
|
-
--
|
|
7
|
+
--block_padding: var(--block_padding_sm);
|
|
8
8
|
display: flex;
|
|
9
9
|
align-items: center;
|
|
10
10
|
justify-content: center;
|
|
11
11
|
font-size: var(--font_default_size);
|
|
12
|
-
margin: var(--
|
|
12
|
+
margin: var(--block_margin);
|
|
13
13
|
width: max-content;
|
|
14
14
|
}
|
|
15
15
|
|
|
@@ -44,7 +44,15 @@ checkbox {
|
|
|
44
44
|
box-shadow: 0 0 1px 0 var(--border_color);
|
|
45
45
|
background-repeat: no-repeat;
|
|
46
46
|
background-position: center center;
|
|
47
|
-
|
|
47
|
+
/* Галка прорастает из нуля: смена картинки мгновенная, а размер её растёт —
|
|
48
|
+
так отметка «попадает» в коробку, а не появляется готовой */
|
|
49
|
+
background-size: 0% 0%;
|
|
50
|
+
/* Свой список перехода заменяет общий, поэтому цвет и тень перечислены рядом */
|
|
51
|
+
transition:
|
|
52
|
+
background-color var(--motion_fast) var(--motion_ease),
|
|
53
|
+
color var(--motion_fast) var(--motion_ease),
|
|
54
|
+
box-shadow var(--motion_fast) var(--motion_ease),
|
|
55
|
+
background-size var(--motion_base) var(--motion_spring);
|
|
48
56
|
}
|
|
49
57
|
|
|
50
58
|
.checkbox:not(:disabled):not(:checked) + label:hover::before {
|
|
@@ -84,6 +92,7 @@ checkbox {
|
|
|
84
92
|
color: var(--text_color_hover);
|
|
85
93
|
border: none;
|
|
86
94
|
box-shadow: 0 0 1px 0 var(--blue_prime_background);
|
|
95
|
+
background-size: 50% 50%;
|
|
87
96
|
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3e%3c/svg%3e");
|
|
88
97
|
}
|
|
89
98
|
|
|
@@ -29,9 +29,11 @@ const { I18n } = require("../../../modules/chui_i18n/chui_i18n");
|
|
|
29
29
|
* Валидация: `Validate.installField` — для этого поля осмысленны `required` и границы
|
|
30
30
|
* **числа меток** (`min`, `max`), потому что проверяется количество, а не текст.
|
|
31
31
|
*
|
|
32
|
-
* Слушателей на `window`/`document` и таймеров нет,
|
|
33
|
-
*
|
|
34
|
-
*
|
|
32
|
+
* Слушателей на `window`/`document` и таймеров нет, но `destroy()` нужен: за шириной строки
|
|
33
|
+
* меток следит `ResizeObserver`, а пересчёт счётчика «+N» отложен в кадр
|
|
34
|
+
* (`requestAnimationFrame`). Прежний комментарий утверждал, что достаточно убрать узел из
|
|
35
|
+
* документа, — это неверно: наблюдатель держит цель живой, а отложенный кадр продолжал бы
|
|
36
|
+
* считать метки уже удалённого поля.
|
|
35
37
|
*
|
|
36
38
|
* ```javascript
|
|
37
39
|
* const tags = new Chips({name: 'tags', title: 'Теги', placeholder: 'Добавить тег',
|
|
@@ -50,8 +52,8 @@ class Chips {
|
|
|
50
52
|
#input = document.createElement("input");
|
|
51
53
|
#more = document.createElement("chips_more");
|
|
52
54
|
#dropdown = document.createElement("chips_dropdown");
|
|
53
|
-
#
|
|
54
|
-
#
|
|
55
|
+
#overflowFrame = undefined;
|
|
56
|
+
#overflowObserver = undefined;
|
|
55
57
|
#a11y = undefined;
|
|
56
58
|
#hint = document.createElement("chips_hint");
|
|
57
59
|
#status = document.createElement("chips_status");
|
|
@@ -61,11 +63,11 @@ class Chips {
|
|
|
61
63
|
#placeholder = I18n.t("forms.chipsPlaceholder");
|
|
62
64
|
#disabled = false;
|
|
63
65
|
#unique = true;
|
|
64
|
-
#
|
|
65
|
-
#
|
|
66
|
-
#
|
|
66
|
+
#allowCustom = true;
|
|
67
|
+
#commitOnBlur = false;
|
|
68
|
+
#maxChips = undefined;
|
|
67
69
|
#suggestions = [];
|
|
68
|
-
#
|
|
70
|
+
#changeListeners = [];
|
|
69
71
|
|
|
70
72
|
constructor(
|
|
71
73
|
options = {
|
|
@@ -97,9 +99,9 @@ class Chips {
|
|
|
97
99
|
this.#root.id = this.#id;
|
|
98
100
|
if (options.placeholder !== undefined) this.#placeholder = options.placeholder;
|
|
99
101
|
if (options.unique === false) this.#unique = false;
|
|
100
|
-
if (options.allowCustom === false) this.#
|
|
101
|
-
if (options.commitOnBlur === true) this.#
|
|
102
|
-
if (options.maxChips !== undefined) this.#
|
|
102
|
+
if (options.allowCustom === false) this.#allowCustom = false;
|
|
103
|
+
if (options.commitOnBlur === true) this.#commitOnBlur = true;
|
|
104
|
+
if (options.maxChips !== undefined) this.#maxChips = options.maxChips;
|
|
103
105
|
if (options.suggestions !== undefined) this.#suggestions = [...options.suggestions];
|
|
104
106
|
if (options.title !== undefined) this.setTitle(options.title);
|
|
105
107
|
else this.#title.hidden = true;
|
|
@@ -144,8 +146,8 @@ class Chips {
|
|
|
144
146
|
// Ширину строки задаёт вёрстка вокруг, поэтому о смене размера сообщает наблюдатель
|
|
145
147
|
// за самой строкой: поле может получить ширину уже после создания (ленивые разделы витрины)
|
|
146
148
|
if (typeof ResizeObserver === "function") {
|
|
147
|
-
this.#
|
|
148
|
-
this.#
|
|
149
|
+
this.#overflowObserver = new ResizeObserver(() => this.#scheduleOverflow());
|
|
150
|
+
this.#overflowObserver.observe(this.#row);
|
|
149
151
|
}
|
|
150
152
|
this.#syncFieldAria();
|
|
151
153
|
|
|
@@ -197,7 +199,7 @@ class Chips {
|
|
|
197
199
|
}
|
|
198
200
|
|
|
199
201
|
getMaxChips() {
|
|
200
|
-
return this.#
|
|
202
|
+
return this.#maxChips;
|
|
201
203
|
}
|
|
202
204
|
|
|
203
205
|
getSuggestions() {
|
|
@@ -236,7 +238,7 @@ class Chips {
|
|
|
236
238
|
}
|
|
237
239
|
|
|
238
240
|
setMaxChips(max = Number()) {
|
|
239
|
-
this.#
|
|
241
|
+
this.#maxChips = max;
|
|
240
242
|
this.#syncDisabledState();
|
|
241
243
|
return this;
|
|
242
244
|
}
|
|
@@ -280,7 +282,9 @@ class Chips {
|
|
|
280
282
|
if (index === -1) return this;
|
|
281
283
|
this.#chips.splice(index, 1);
|
|
282
284
|
const node = this.#list.children[index];
|
|
283
|
-
|
|
285
|
+
// Метка уходит движением: из строки она убирается по концу кадра, а счётчик «+N»
|
|
286
|
+
// пересчитывается заново — иначе он считал бы уходящую метку живой
|
|
287
|
+
if (node !== undefined) this.#leaveChip(node);
|
|
284
288
|
// Место в строке освободилось: прежде скрытые метки могут вернуться
|
|
285
289
|
this.#scheduleOverflow();
|
|
286
290
|
this.#renderSuggestions();
|
|
@@ -305,7 +309,7 @@ class Chips {
|
|
|
305
309
|
return this;
|
|
306
310
|
}
|
|
307
311
|
addChangeListener(listener = () => {}) {
|
|
308
|
-
this.#
|
|
312
|
+
this.#changeListeners.push(listener);
|
|
309
313
|
return this;
|
|
310
314
|
}
|
|
311
315
|
|
|
@@ -324,14 +328,27 @@ class Chips {
|
|
|
324
328
|
set() {
|
|
325
329
|
return this.#root;
|
|
326
330
|
}
|
|
331
|
+
|
|
332
|
+
/** Полное удаление: снять наблюдатель за строкой, отложенный кадр и клавиатурный слой */
|
|
333
|
+
destroy() {
|
|
334
|
+
if (this.#overflowObserver !== undefined) {
|
|
335
|
+
this.#overflowObserver.disconnect();
|
|
336
|
+
this.#overflowObserver = undefined;
|
|
337
|
+
}
|
|
338
|
+
if (this.#overflowFrame !== undefined) {
|
|
339
|
+
cancelAnimationFrame(this.#overflowFrame);
|
|
340
|
+
this.#overflowFrame = undefined;
|
|
341
|
+
}
|
|
342
|
+
if (this.#a11y !== undefined) this.#a11y.destroy();
|
|
343
|
+
}
|
|
327
344
|
// === ВНУТРЕННЕЕ ===
|
|
328
345
|
// Общая точка добавления: возвращает признак «метка действительно добавлена»
|
|
329
346
|
#tryAdd(text = String()) {
|
|
330
347
|
const value = String(text).trim();
|
|
331
348
|
if (value === "") return false;
|
|
332
349
|
if (this.#unique && this.#chips.includes(value)) return false;
|
|
333
|
-
if (this.#
|
|
334
|
-
if (!this.#
|
|
350
|
+
if (this.#maxChips !== undefined && this.#chips.length >= this.#maxChips) return false;
|
|
351
|
+
if (!this.#allowCustom && !this.#suggestions.includes(value)) return false;
|
|
335
352
|
this.#chips.push(value);
|
|
336
353
|
this.#appendChip(value);
|
|
337
354
|
this.#renderSuggestions();
|
|
@@ -342,6 +359,18 @@ class Chips {
|
|
|
342
359
|
return true;
|
|
343
360
|
}
|
|
344
361
|
|
|
362
|
+
/** Уход метки: она гаснет и сжимается, а из строки убирается по концу кадра */
|
|
363
|
+
#leaveChip(node) {
|
|
364
|
+
node.classList.add("chips_item_leaving");
|
|
365
|
+
const done = (event) => {
|
|
366
|
+
if (event.target !== node) return;
|
|
367
|
+
node.removeEventListener("animationend", done);
|
|
368
|
+
node.remove();
|
|
369
|
+
this.#scheduleOverflow();
|
|
370
|
+
};
|
|
371
|
+
node.addEventListener("animationend", done);
|
|
372
|
+
}
|
|
373
|
+
|
|
345
374
|
#appendChip(text = String()) {
|
|
346
375
|
const item = document.createElement("chips_item");
|
|
347
376
|
const label = document.createElement("chips_text");
|
|
@@ -358,6 +387,15 @@ class Chips {
|
|
|
358
387
|
if (this.#disabled) remove.disabled = true;
|
|
359
388
|
item.appendChild(remove);
|
|
360
389
|
this.#list.appendChild(item);
|
|
390
|
+
// Новая метка встаёт на место общим кадром появления, а не возникает рывком.
|
|
391
|
+
// Класс снимается по концу кадра: при пересборке списка метки его не переигрывают
|
|
392
|
+
item.classList.add("chips_item_appearing");
|
|
393
|
+
const appeared = (event) => {
|
|
394
|
+
if (event.target !== item) return;
|
|
395
|
+
item.removeEventListener("animationend", appeared);
|
|
396
|
+
item.classList.remove("chips_item_appearing");
|
|
397
|
+
};
|
|
398
|
+
item.addEventListener("animationend", appeared);
|
|
361
399
|
// Метка могла не поместиться в строку — пересчёт счётчика «+N»
|
|
362
400
|
this.#scheduleOverflow();
|
|
363
401
|
}
|
|
@@ -397,13 +435,31 @@ class Chips {
|
|
|
397
435
|
|
|
398
436
|
/** Пересчёт счётчика после текущего кадра: к этому моменту разметка меток уже уложена */
|
|
399
437
|
#scheduleOverflow() {
|
|
400
|
-
if (this.#
|
|
401
|
-
this.#
|
|
402
|
-
this.#
|
|
438
|
+
if (this.#overflowFrame !== undefined) return;
|
|
439
|
+
this.#overflowFrame = requestAnimationFrame(() => {
|
|
440
|
+
this.#overflowFrame = undefined;
|
|
403
441
|
this.#syncOverflow();
|
|
404
442
|
});
|
|
405
443
|
}
|
|
406
444
|
|
|
445
|
+
/**
|
|
446
|
+
* Уход списка идёт движением: `hidden` возвращается по концу кадра, поэтому список
|
|
447
|
+
* не пропадает рывком. Открытие за время ухода отменяет снятие — иначе список
|
|
448
|
+
* погас бы уже открытым.
|
|
449
|
+
*/
|
|
450
|
+
#hideDropdown() {
|
|
451
|
+
if (this.#dropdown.hidden === true) return;
|
|
452
|
+
this.#dropdown.classList.add("chips_dropdown_leaving");
|
|
453
|
+
const done = (event) => {
|
|
454
|
+
if (event.target !== this.#dropdown) return;
|
|
455
|
+
this.#dropdown.removeEventListener("animationend", done);
|
|
456
|
+
if (this.#dropdown.classList.contains("chips_dropdown_leaving") === false) return;
|
|
457
|
+
this.#dropdown.classList.remove("chips_dropdown_leaving");
|
|
458
|
+
this.#dropdown.hidden = true;
|
|
459
|
+
};
|
|
460
|
+
this.#dropdown.addEventListener("animationend", done);
|
|
461
|
+
}
|
|
462
|
+
|
|
407
463
|
// Список подсказок: свой выпадающий список в материале остальных дропдаунов
|
|
408
464
|
#renderSuggestions() {
|
|
409
465
|
// Уже добавленные метки в подсказках не нужны, набранный текст сужает список
|
|
@@ -435,8 +491,13 @@ class Chips {
|
|
|
435
491
|
this.#scheduleOverflow();
|
|
436
492
|
}
|
|
437
493
|
const visible = open === true && this.#disabled === false && this.#dropdown.childElementCount > 0;
|
|
438
|
-
|
|
439
|
-
|
|
494
|
+
if (visible === true) {
|
|
495
|
+
this.#dropdown.classList.remove("chips_dropdown_leaving");
|
|
496
|
+
this.#dropdown.hidden = false;
|
|
497
|
+
this.#placeDropdown();
|
|
498
|
+
} else {
|
|
499
|
+
this.#hideDropdown();
|
|
500
|
+
}
|
|
440
501
|
if (this.#a11y !== undefined) this.#a11y.setExpanded(visible);
|
|
441
502
|
return visible;
|
|
442
503
|
}
|
|
@@ -470,12 +531,12 @@ class Chips {
|
|
|
470
531
|
}
|
|
471
532
|
|
|
472
533
|
#syncDisabledState() {
|
|
473
|
-
const full = this.#
|
|
534
|
+
const full = this.#maxChips !== undefined && this.#chips.length >= this.#maxChips;
|
|
474
535
|
// Поле ввода остаётся доступным и при достигнутом пределе: иначе нельзя было бы
|
|
475
536
|
// убрать метку с клавиатуры, а причина отказа объясняется в статусе
|
|
476
537
|
this.#input.disabled = this.#disabled;
|
|
477
538
|
this.#input.placeholder = full
|
|
478
|
-
? I18n.t("forms.chipsLimitPlaceholder", { count: this.#
|
|
539
|
+
? I18n.t("forms.chipsLimitPlaceholder", { count: this.#maxChips })
|
|
479
540
|
: this.#placeholder;
|
|
480
541
|
for (const button of this.#list.querySelectorAll(".chips_remove")) button.disabled = this.#disabled;
|
|
481
542
|
}
|
|
@@ -486,7 +547,7 @@ class Chips {
|
|
|
486
547
|
|
|
487
548
|
#emit() {
|
|
488
549
|
const chips = this.getValue();
|
|
489
|
-
for (const listener of [...this.#
|
|
550
|
+
for (const listener of [...this.#changeListeners]) listener(chips);
|
|
490
551
|
}
|
|
491
552
|
|
|
492
553
|
#commitInput() {
|
|
@@ -499,8 +560,8 @@ class Chips {
|
|
|
499
560
|
return;
|
|
500
561
|
}
|
|
501
562
|
// Текст не теряем: либо он уже есть, либо метка не из подсказок, либо предел
|
|
502
|
-
if (this.#
|
|
503
|
-
this.#announce(I18n.t("forms.chipsLimitReached", { count: this.#
|
|
563
|
+
if (this.#maxChips !== undefined && this.#chips.length >= this.#maxChips) {
|
|
564
|
+
this.#announce(I18n.t("forms.chipsLimitReached", { count: this.#maxChips }));
|
|
504
565
|
return;
|
|
505
566
|
}
|
|
506
567
|
if (this.#unique && this.#chips.includes(value.trim()))
|
|
@@ -566,7 +627,7 @@ class Chips {
|
|
|
566
627
|
};
|
|
567
628
|
|
|
568
629
|
#onInputBlur = () => {
|
|
569
|
-
if (this.#
|
|
630
|
+
if (this.#commitOnBlur) this.#commitInput();
|
|
570
631
|
};
|
|
571
632
|
|
|
572
633
|
#onFieldClick = (event) => {
|