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
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
const { setStyles, optionOr, markdownToHtml } = require("../../modules/chui_functions");
|
|
2
|
+
const { Icon } = require("../chui_icons/icons");
|
|
3
|
+
const { I18n } = require("../../modules/chui_i18n/chui_i18n");
|
|
4
|
+
const { makeKeyboardButton } = require("../../modules/chui_a11y/chui_a11y");
|
|
5
|
+
const { tokenTime } = require("../../modules/chui_animations/motion");
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Баннер — карточка-объявление: картинка или значок, заголовок с подзаголовком, действия
|
|
9
|
+
* и закрытие.
|
|
10
|
+
*
|
|
11
|
+
* Баннер стоит в потоке страницы, а не всплывает слоем: для модального сообщения есть
|
|
12
|
+
* `Popup`, для сообщения о состоянии — `Alert`, для всплывающего — `Toast`. От `Alert` он
|
|
13
|
+
* отличается задачей: там состояние (ошибка, предупреждение), здесь предложение — «попробуйте
|
|
14
|
+
* новое», «настройте», «посмотрите» — поэтому у баннера крупный материал, картинка и действия
|
|
15
|
+
* кнопками.
|
|
16
|
+
*
|
|
17
|
+
* Два вида (`mode`) и два размера (`size`):
|
|
18
|
+
* - `tint` — значок в цветной плашке, `image` — фотография; фото занимает кромку карточки
|
|
19
|
+
* целиком и не затемняется: текст лежит рядом, а не поверх снимка, поэтому подпись читается
|
|
20
|
+
* при любом кадре (всплывающие подписи поверх фото требуют затемнения на глаз — в тёмной
|
|
21
|
+
* и светлой схеме оно даёт разный результат);
|
|
22
|
+
* - `s` — строка: плашка слева, заголовок и подзаголовок рядом, действия справа;
|
|
23
|
+
* - `m` — карточка: картинка сверху во всю ширину, под ней заголовок, подзаголовок, текст
|
|
24
|
+
* и действия.
|
|
25
|
+
*
|
|
26
|
+
* Опции: `id`, `title`, `subtitle`, `text`, `markdownText`, `icon`, `image`, `mode`, `size`,
|
|
27
|
+
* `actions`, `closable`, `onClose`, `onClick`.
|
|
28
|
+
*
|
|
29
|
+
* Методы: `setTitle(text)`, `setSubtitle(text)`, `setText(text)`, `setMarkdownText(md)`,
|
|
30
|
+
* `setIcon(glyph)`, `setImage(src)`, `setMode(mode)`, `setSize(size)`, `addActions(...actions)`,
|
|
31
|
+
* `setClosable(bool)`, `close()`, `isClosed()`, `set()`, `destroy()`.
|
|
32
|
+
*/
|
|
33
|
+
class Banner {
|
|
34
|
+
static MODE = { TINT: "tint", IMAGE: "image" };
|
|
35
|
+
static SIZE = { S: "s", M: "m" };
|
|
36
|
+
|
|
37
|
+
#root = document.createElement("chui_banner");
|
|
38
|
+
#media = document.createElement("banner_media");
|
|
39
|
+
#content = document.createElement("banner_content");
|
|
40
|
+
#title = undefined;
|
|
41
|
+
#subtitle = undefined;
|
|
42
|
+
#text = undefined;
|
|
43
|
+
#actions = document.createElement("banner_actions");
|
|
44
|
+
#close = undefined;
|
|
45
|
+
#image = undefined;
|
|
46
|
+
#onClose = undefined;
|
|
47
|
+
#onClick = undefined;
|
|
48
|
+
#closed = false;
|
|
49
|
+
#removed = false;
|
|
50
|
+
|
|
51
|
+
constructor(options = {}) {
|
|
52
|
+
setStyles(__dirname + "/styles.css", "chUiJS_Banner");
|
|
53
|
+
if (options.id !== undefined) this.#root.id = options.id;
|
|
54
|
+
this.setSize(optionOr(options.size, Banner.SIZE.M));
|
|
55
|
+
this.setMode(optionOr(options.mode, Banner.MODE.TINT));
|
|
56
|
+
this.#onClose = typeof options.onClose === "function" ? options.onClose : undefined;
|
|
57
|
+
this.#onClick = typeof options.onClick === "function" ? options.onClick : undefined;
|
|
58
|
+
this.#root.append(this.#media, this.#content, this.#actions);
|
|
59
|
+
if (options.title !== undefined) this.setTitle(options.title);
|
|
60
|
+
if (options.subtitle !== undefined) this.setSubtitle(options.subtitle);
|
|
61
|
+
if (options.markdownText !== undefined) this.setMarkdownText(options.markdownText);
|
|
62
|
+
else if (options.text !== undefined) this.setText(options.text);
|
|
63
|
+
if (options.icon !== undefined) this.setIcon(options.icon);
|
|
64
|
+
if (options.image !== undefined) this.setImage(options.image);
|
|
65
|
+
if (Array.isArray(options.actions)) this.addActions(...options.actions);
|
|
66
|
+
if (options.closable === true) this.setClosable(true);
|
|
67
|
+
if (this.#onClick !== undefined) this.#makeClickable();
|
|
68
|
+
this.#syncName();
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// GET
|
|
72
|
+
isClosed() {
|
|
73
|
+
return this.#closed;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// SET
|
|
77
|
+
setTitle(text = String()) {
|
|
78
|
+
this.#title = this.#writeText(this.#title, "banner_title", text, "title");
|
|
79
|
+
this.#syncName();
|
|
80
|
+
return this;
|
|
81
|
+
}
|
|
82
|
+
setSubtitle(text = String()) {
|
|
83
|
+
this.#subtitle = this.#writeText(this.#subtitle, "banner_subtitle", text, "subtitle");
|
|
84
|
+
return this;
|
|
85
|
+
}
|
|
86
|
+
setText(text = String()) {
|
|
87
|
+
this.#text = this.#writeText(this.#text, "banner_text", text, "text");
|
|
88
|
+
return this;
|
|
89
|
+
}
|
|
90
|
+
/** Разметка в теле баннера: тот же приём, что у `Alert` — текст приходит готовым HTML */
|
|
91
|
+
setMarkdownText(markdown = String()) {
|
|
92
|
+
if (this.#text === undefined) this.#text = this.#insertText("banner_text", "text");
|
|
93
|
+
this.#text.innerHTML = markdownToHtml(String(markdown));
|
|
94
|
+
return this;
|
|
95
|
+
}
|
|
96
|
+
/** Значок в плашке: состояние `tint`. Прежняя картинка при этом уходит */
|
|
97
|
+
setIcon(glyph = String()) {
|
|
98
|
+
const icon = new Icon(String(glyph), "22px").set();
|
|
99
|
+
this.#media.replaceChildren(icon);
|
|
100
|
+
this.#root.dataset.mode = Banner.MODE.TINT;
|
|
101
|
+
this.#image = undefined;
|
|
102
|
+
return this;
|
|
103
|
+
}
|
|
104
|
+
/** Фотография на кромке карточки: состояние `image` */
|
|
105
|
+
setImage(src = String()) {
|
|
106
|
+
if (this.#image === undefined) {
|
|
107
|
+
this.#image = document.createElement("img");
|
|
108
|
+
// Картинка здесь украшение: смысл несёт заголовок, поэтому подпись пуста
|
|
109
|
+
this.#image.alt = "";
|
|
110
|
+
this.#image.loading = "lazy";
|
|
111
|
+
}
|
|
112
|
+
this.#image.src = String(src);
|
|
113
|
+
this.#media.replaceChildren(this.#image);
|
|
114
|
+
this.#root.dataset.mode = Banner.MODE.IMAGE;
|
|
115
|
+
return this;
|
|
116
|
+
}
|
|
117
|
+
setMode(mode = String()) {
|
|
118
|
+
this.#root.dataset.mode = mode === Banner.MODE.IMAGE ? Banner.MODE.IMAGE : Banner.MODE.TINT;
|
|
119
|
+
return this;
|
|
120
|
+
}
|
|
121
|
+
setSize(size = String()) {
|
|
122
|
+
this.#root.dataset.size = size === Banner.SIZE.S ? Banner.SIZE.S : Banner.SIZE.M;
|
|
123
|
+
return this;
|
|
124
|
+
}
|
|
125
|
+
/** Действия баннера: компоненты фреймворка (у них есть `set()`) или готовые узлы */
|
|
126
|
+
addActions(...actions) {
|
|
127
|
+
for (const action of actions) {
|
|
128
|
+
if (action === undefined || action === null) continue;
|
|
129
|
+
this.#actions.appendChild(typeof action.set === "function" ? action.set() : action);
|
|
130
|
+
}
|
|
131
|
+
return this;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Кнопка закрытия — настоящий `<button>`: у неё есть мышь, клавиатура и имя
|
|
135
|
+
* для скринридера (подписи в баннере нет, имя даёт словарь).
|
|
136
|
+
*/
|
|
137
|
+
setClosable(boolean = Boolean()) {
|
|
138
|
+
if (boolean !== true) {
|
|
139
|
+
if (this.#close !== undefined) this.#close.remove();
|
|
140
|
+
this.#close = undefined;
|
|
141
|
+
return this;
|
|
142
|
+
}
|
|
143
|
+
if (this.#close === undefined) {
|
|
144
|
+
this.#close = document.createElement("button");
|
|
145
|
+
this.#close.type = "button";
|
|
146
|
+
this.#close.className = "banner_close";
|
|
147
|
+
this.#close.innerHTML = new Icon("close", "16px").getHTML();
|
|
148
|
+
this.#close.setAttribute("aria-label", I18n.t("a11y.closeMessage"));
|
|
149
|
+
this.#close.setAttribute("title", I18n.t("common.close"));
|
|
150
|
+
this.#close.addEventListener("click", () => this.close());
|
|
151
|
+
this.#root.appendChild(this.#close);
|
|
152
|
+
}
|
|
153
|
+
return this;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Закрытие: баннер гаснет и сходит общим кадром ухода, а узел убирается по его концу.
|
|
158
|
+
* Слушатель одноразовый (проверка цели): иначе он поймал бы любой конец кадра на узле.
|
|
159
|
+
* Срок из токена страхует случай, когда кадр не проиграется вовсе — у скрытого узла
|
|
160
|
+
* `animationend` не приходит.
|
|
161
|
+
*/
|
|
162
|
+
close() {
|
|
163
|
+
if (this.#closed === true) return this;
|
|
164
|
+
this.#closed = true;
|
|
165
|
+
if (this.#onClose !== undefined) this.#onClose(this);
|
|
166
|
+
const finish = () => {
|
|
167
|
+
if (this.#removed === true) return;
|
|
168
|
+
this.#removed = true;
|
|
169
|
+
this.#root.removeEventListener("animationend", finish);
|
|
170
|
+
this.#root.remove();
|
|
171
|
+
};
|
|
172
|
+
this.#root.addEventListener("animationend", finish);
|
|
173
|
+
this.#root.classList.add("banner_leaving");
|
|
174
|
+
setTimeout(finish, tokenTime("--motion_fast"));
|
|
175
|
+
return this;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
set() {
|
|
179
|
+
return this.#root;
|
|
180
|
+
}
|
|
181
|
+
/** Узлы баннера уходят из документа вместе со своими слушателями; работа снимается явно */
|
|
182
|
+
destroy() {
|
|
183
|
+
this.#onClick = undefined;
|
|
184
|
+
this.#onClose = undefined;
|
|
185
|
+
this.#removed = true;
|
|
186
|
+
this.#root.remove();
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// === ВНУТРЕННЕЕ ===
|
|
190
|
+
#writeText(node = undefined, className = String(), text = String(), key = String()) {
|
|
191
|
+
const target = node === undefined ? this.#insertText(className, key) : node;
|
|
192
|
+
target.innerText = String(text);
|
|
193
|
+
return target;
|
|
194
|
+
}
|
|
195
|
+
#insertText(className = String(), key = String()) {
|
|
196
|
+
const node = document.createElement(`banner_${key}`);
|
|
197
|
+
node.className = className;
|
|
198
|
+
this.#content.appendChild(node);
|
|
199
|
+
return node;
|
|
200
|
+
}
|
|
201
|
+
/** Клик по всей карточке: роль кнопки, обход клавиатурой и активация Enter/Space */
|
|
202
|
+
#makeClickable() {
|
|
203
|
+
makeKeyboardButton(this.#root);
|
|
204
|
+
this.#root.addEventListener("click", () => {
|
|
205
|
+
if (this.#onClick !== undefined) this.#onClick(this);
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Имя баннера для скринридера: заголовок, а без него — общая подпись из словаря.
|
|
210
|
+
* У кликабельного баннера имя обязательно: без него роль кнопки читается как «кнопка».
|
|
211
|
+
*/
|
|
212
|
+
#syncName() {
|
|
213
|
+
const title = this.#title === undefined ? "" : this.#title.innerText.trim();
|
|
214
|
+
const name = title === "" ? I18n.t("feedback.banner") : title;
|
|
215
|
+
if (this.#onClick === undefined && this.#root.getAttribute("role") === null) {
|
|
216
|
+
this.#root.setAttribute("role", "region");
|
|
217
|
+
}
|
|
218
|
+
this.#root.setAttribute("aria-label", name);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
exports.Banner = Banner;
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
/* Баннер: карточка-объявление с кромкой (значок или фото), текстом и действиями.
|
|
2
|
+
Материал — как у карточки и `Alert`: своя подложка и волосяная рамка. Отдельных цветов
|
|
3
|
+
у компонента нет: состояние несут плашка значка, фото и кнопки. */
|
|
4
|
+
|
|
5
|
+
chui_banner {
|
|
6
|
+
position: relative;
|
|
7
|
+
display: flex;
|
|
8
|
+
flex-direction: row;
|
|
9
|
+
align-items: center;
|
|
10
|
+
gap: 12px;
|
|
11
|
+
/* Компонент сам задаёт ширину: в flex-колонке с `align-items: flex-start` карточка
|
|
12
|
+
без ширины получила бы `max-content` и вылезла за содержимое */
|
|
13
|
+
width: -webkit-fill-available;
|
|
14
|
+
box-sizing: border-box;
|
|
15
|
+
padding: 12px 14px;
|
|
16
|
+
border: 1px solid var(--border_color);
|
|
17
|
+
border-radius: var(--radius_md);
|
|
18
|
+
background: var(--element_background_2);
|
|
19
|
+
color: var(--text_color);
|
|
20
|
+
font-size: var(--font_default_size);
|
|
21
|
+
text-align: start;
|
|
22
|
+
/* Появление: карточка встаёт на место — общий кадр из global_style.css */
|
|
23
|
+
animation: chui_appear_up var(--motion_base) var(--motion_ease);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/* Уход: карточка гаснет и сходит вверх, узел убирается по концу кадра */
|
|
27
|
+
.banner_leaving {
|
|
28
|
+
animation: chui_leave_up var(--motion_fast) var(--motion_ease) forwards;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/* Крупный баннер — карточка: кромка сверху во всю ширину, текст и действия под ней */
|
|
32
|
+
chui_banner[data-size="m"] {
|
|
33
|
+
flex-direction: column;
|
|
34
|
+
align-items: stretch;
|
|
35
|
+
gap: 10px;
|
|
36
|
+
/* Кромка касается краёв карточки: свои отступы у неё снизу, у текста — по бокам */
|
|
37
|
+
padding: 0 0 12px;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
banner_media {
|
|
41
|
+
flex: none;
|
|
42
|
+
display: flex;
|
|
43
|
+
align-items: center;
|
|
44
|
+
justify-content: center;
|
|
45
|
+
box-sizing: border-box;
|
|
46
|
+
/* Кромка со значком — квадрат со строку текста (29 px у поля + воздух): в обоих
|
|
47
|
+
размерах она одного роста, а крупный вид с фотографией перекрывает этот размер ниже */
|
|
48
|
+
width: 44px;
|
|
49
|
+
height: 44px;
|
|
50
|
+
overflow: hidden;
|
|
51
|
+
border-radius: var(--radius_sm);
|
|
52
|
+
background: var(--element_background);
|
|
53
|
+
color: var(--blue_prime_background);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
chui_banner[data-mode="tint"] banner_media {
|
|
57
|
+
background: var(--blue_prime_background_tint);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/* Фото — состояние `image`: кромка тянется во всю ширину карточки */
|
|
61
|
+
chui_banner[data-mode="image"][data-size="m"] banner_media {
|
|
62
|
+
width: -webkit-fill-available;
|
|
63
|
+
height: 140px;
|
|
64
|
+
border-radius: var(--radius_md) var(--radius_md) 0 0;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/* Плашка со значком в крупном баннере остаётся плашкой: без картинки полоса во всю ширину
|
|
68
|
+
была бы пустой — объявление читалось бы полем без содержимого */
|
|
69
|
+
chui_banner[data-mode="tint"][data-size="m"] banner_media {
|
|
70
|
+
align-self: flex-start;
|
|
71
|
+
margin: 12px 14px 0;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
banner_media img {
|
|
75
|
+
display: block;
|
|
76
|
+
width: 100%;
|
|
77
|
+
height: 100%;
|
|
78
|
+
object-fit: cover;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
banner_content {
|
|
82
|
+
display: flex;
|
|
83
|
+
flex-direction: column;
|
|
84
|
+
gap: 2px;
|
|
85
|
+
flex: 1 1 auto;
|
|
86
|
+
min-width: 0;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/* В крупном баннере текст отходит от краёв карточки: кромка их уже заняла */
|
|
90
|
+
chui_banner[data-size="m"] banner_content {
|
|
91
|
+
padding-inline: 14px;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
banner_title {
|
|
95
|
+
font-weight: 600;
|
|
96
|
+
color: var(--text_color);
|
|
97
|
+
word-break: break-word;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
banner_subtitle {
|
|
101
|
+
color: var(--text_color_disabled);
|
|
102
|
+
font-size: var(--font_labels_size);
|
|
103
|
+
word-break: break-word;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
banner_text {
|
|
107
|
+
color: var(--text_color);
|
|
108
|
+
word-break: break-word;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
banner_text p {
|
|
112
|
+
margin: 0;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
banner_actions {
|
|
116
|
+
display: flex;
|
|
117
|
+
flex: none;
|
|
118
|
+
flex-wrap: wrap;
|
|
119
|
+
align-items: center;
|
|
120
|
+
gap: 8px;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/* Пустой блок действий места не занимает */
|
|
124
|
+
banner_actions:empty {
|
|
125
|
+
display: none;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
chui_banner[data-size="m"] banner_actions {
|
|
129
|
+
padding-inline: 14px;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/* Закрытие — круглая кнопка в углу карточки: в крупном баннере она лежит поверх кромки,
|
|
133
|
+
поэтому фон у неё есть всегда, иначе значок терялся бы на снимке */
|
|
134
|
+
.banner_close {
|
|
135
|
+
position: absolute;
|
|
136
|
+
top: 8px;
|
|
137
|
+
inset-inline-end: 8px;
|
|
138
|
+
cursor: pointer;
|
|
139
|
+
display: flex;
|
|
140
|
+
align-items: center;
|
|
141
|
+
justify-content: center;
|
|
142
|
+
box-sizing: border-box;
|
|
143
|
+
width: 26px;
|
|
144
|
+
height: 26px;
|
|
145
|
+
padding: 0;
|
|
146
|
+
border: none;
|
|
147
|
+
border-radius: var(--radius_circle);
|
|
148
|
+
background: var(--element_background);
|
|
149
|
+
color: var(--text_color_disabled);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
.banner_close:hover {
|
|
153
|
+
background: var(--element_background_hover);
|
|
154
|
+
color: var(--text_color);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
.banner_close chui_icon {
|
|
158
|
+
color: inherit;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/* В строке (размер `s`) кнопке хватает места в ряду: поверх кромки она не лежит */
|
|
162
|
+
chui_banner[data-size="s"] .banner_close {
|
|
163
|
+
position: static;
|
|
164
|
+
flex: none;
|
|
165
|
+
background: transparent;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
chui_banner[data-size="s"] .banner_close:hover {
|
|
169
|
+
background: var(--element_background_hover);
|
|
170
|
+
}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
const { Icon } = require("../chui_icons/icons");
|
|
2
2
|
|
|
3
3
|
class Button {
|
|
4
|
-
#
|
|
4
|
+
#chuiButton = document.createElement("chui_button");
|
|
5
5
|
#button = document.createElement("button");
|
|
6
|
-
#
|
|
7
|
-
#
|
|
8
|
-
#
|
|
6
|
+
#buttonText = document.createElement("button_text");
|
|
7
|
+
#buttonIcon = document.createElement("button_icon");
|
|
8
|
+
#labelText = undefined;
|
|
9
9
|
constructor(
|
|
10
10
|
options = {
|
|
11
11
|
reverse: Boolean(),
|
|
@@ -19,37 +19,34 @@ class Button {
|
|
|
19
19
|
require("../../modules/chui_functions").setStyles(__dirname + "/styles.css", "chUiJS_Button");
|
|
20
20
|
|
|
21
21
|
this.#button.className = "chui_button";
|
|
22
|
-
this.#
|
|
22
|
+
this.#buttonText.className = "chui_button_text";
|
|
23
23
|
// Иконка декоративна: иначе её глиф-имя («print», «delete»…) попадает в имя кнопки
|
|
24
|
-
this.#
|
|
24
|
+
this.#buttonIcon.setAttribute("aria-hidden", "true");
|
|
25
25
|
|
|
26
|
-
if (options.title !== undefined) this.#
|
|
26
|
+
if (options.title !== undefined) this.#buttonText.innerText = options.title;
|
|
27
27
|
if (options.icon !== undefined)
|
|
28
|
-
this.#
|
|
28
|
+
this.#buttonIcon.innerHTML = new Icon(options.icon, "var(--header_icon_size)").getHTML();
|
|
29
29
|
|
|
30
30
|
if (options.title !== undefined && options.icon === undefined) {
|
|
31
|
-
this.#button.appendChild(this.#
|
|
31
|
+
this.#button.appendChild(this.#buttonText);
|
|
32
32
|
} else if (options.title === undefined && options.icon !== undefined) {
|
|
33
33
|
// Квадратный отступ для кнопки только со значком: признак читает CSS
|
|
34
34
|
this.#button.dataset.icon_only = "true";
|
|
35
|
-
this.#button.appendChild(this.#
|
|
35
|
+
this.#button.appendChild(this.#buttonIcon);
|
|
36
36
|
} else {
|
|
37
37
|
// Порядок детей задаёт `reverse`, а зазор между значком и подписью —
|
|
38
38
|
// `gap` в CSS: инлайновые отступы здесь больше не нужны
|
|
39
39
|
if (options.reverse) {
|
|
40
|
-
this.#button.appendChild(this.#
|
|
41
|
-
this.#button.appendChild(this.#
|
|
40
|
+
this.#button.appendChild(this.#buttonIcon);
|
|
41
|
+
this.#button.appendChild(this.#buttonText);
|
|
42
42
|
} else {
|
|
43
|
-
this.#button.appendChild(this.#
|
|
44
|
-
this.#button.appendChild(this.#
|
|
43
|
+
this.#button.appendChild(this.#buttonText);
|
|
44
|
+
this.#button.appendChild(this.#buttonIcon);
|
|
45
45
|
}
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
if (options.clickEvent !== undefined) this.#button.addEventListener("click", options.clickEvent);
|
|
49
|
-
this.#
|
|
50
|
-
return false;
|
|
51
|
-
});
|
|
52
|
-
this.#chui_button.appendChild(this.#button);
|
|
49
|
+
this.#chuiButton.appendChild(this.#button);
|
|
53
50
|
// Доступное имя кнопки без надписи: значок декоративен (`aria-hidden`) и имени не даёт,
|
|
54
51
|
// поэтому кнопка только со значком оставалась бы без имени
|
|
55
52
|
if (options.label !== undefined) this.setLabel(options.label);
|
|
@@ -57,34 +54,33 @@ class Button {
|
|
|
57
54
|
if (options.disabled === true) this.setDisabled(true);
|
|
58
55
|
}
|
|
59
56
|
getText() {
|
|
60
|
-
return this.#
|
|
57
|
+
return this.#buttonText.innerText;
|
|
61
58
|
}
|
|
62
59
|
/** Новый текст. Пишем в `button_text`, а не в саму кнопку: запись в кнопку целиком
|
|
63
60
|
* затирала бы и значок, и его разметку (`aria-hidden`), а `getText()` читал бы старый узел */
|
|
64
61
|
setText(text = String()) {
|
|
65
|
-
this.#
|
|
62
|
+
this.#buttonText.innerText = text;
|
|
66
63
|
// Пустой узел в разметку не дописываем: кнопке только со значком он ничего не даёт
|
|
67
|
-
if (String(text) !== "" && !this.#button.contains(this.#
|
|
68
|
-
this.#button.appendChild(this.#button_text);
|
|
64
|
+
if (String(text) !== "" && !this.#button.contains(this.#buttonText)) this.#button.appendChild(this.#buttonText);
|
|
69
65
|
this.#syncLabel();
|
|
70
66
|
return this;
|
|
71
67
|
}
|
|
72
68
|
getLabel() {
|
|
73
|
-
return this.#
|
|
69
|
+
return this.#labelText;
|
|
74
70
|
}
|
|
75
71
|
/** Доступное имя кнопки без видимой надписи; `undefined` его убирает.
|
|
76
72
|
* Пока надпись есть, имя даёт она сама — `aria-label` тогда не ставится и не подменяет её */
|
|
77
73
|
setLabel(label = undefined) {
|
|
78
|
-
this.#
|
|
74
|
+
this.#labelText = label;
|
|
79
75
|
this.#syncLabel();
|
|
80
76
|
return this;
|
|
81
77
|
}
|
|
82
78
|
/** Имя кнопки: из видимой надписи, а если её нет — из `label` */
|
|
83
79
|
#syncLabel() {
|
|
84
|
-
const hasText = this.#button.contains(this.#
|
|
85
|
-
if (hasText || this.#
|
|
80
|
+
const hasText = this.#button.contains(this.#buttonText) && this.#buttonText.innerText.trim() !== "";
|
|
81
|
+
if (hasText || this.#labelText === undefined || this.#labelText === "")
|
|
86
82
|
this.#button.removeAttribute("aria-label");
|
|
87
|
-
else this.#button.setAttribute("aria-label", String(this.#
|
|
83
|
+
else this.#button.setAttribute("aria-label", String(this.#labelText));
|
|
88
84
|
}
|
|
89
85
|
addClickListener(listener = () => {}) {
|
|
90
86
|
this.#button.addEventListener("click", listener);
|
|
@@ -93,7 +89,7 @@ class Button {
|
|
|
93
89
|
this.#button.disabled = boolean;
|
|
94
90
|
}
|
|
95
91
|
set() {
|
|
96
|
-
return this.#
|
|
92
|
+
return this.#chuiButton;
|
|
97
93
|
}
|
|
98
94
|
}
|
|
99
95
|
|
|
@@ -2,19 +2,19 @@ chui_button {
|
|
|
2
2
|
cursor: pointer;
|
|
3
3
|
height: max-content;
|
|
4
4
|
width: max-content;
|
|
5
|
-
border-radius: var(--
|
|
6
|
-
margin: var(--
|
|
5
|
+
border-radius: var(--radius_sm);
|
|
6
|
+
margin: var(--block_margin);
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
.chui_button {
|
|
10
10
|
cursor: pointer;
|
|
11
11
|
height: max-content;
|
|
12
12
|
width: max-content;
|
|
13
|
-
border-radius: var(--
|
|
13
|
+
border-radius: var(--radius_sm);
|
|
14
14
|
/* Компактный шаг: 5px по вертикали дают 29px (значок 17 + отступы 10 + черта 2) —
|
|
15
|
-
как у кнопок шапки (30px). Прежде стояло --
|
|
15
|
+
как у кнопок шапки (30px). Прежде стояло --block_padding (8px 13px), и кнопка
|
|
16
16
|
выходила 35px, то есть ростом с поле ввода — самый крупный контроль в вёрстке. */
|
|
17
|
-
padding: var(--
|
|
17
|
+
padding: var(--block_padding_sm);
|
|
18
18
|
/* Зазор вместо `margin-left`, который ставил JS: отступ между значком и подписью
|
|
19
19
|
держит flex-контейнер, поэтому он не зависит от порядка детей (включая `reverse`). */
|
|
20
20
|
gap: var(--control_padding);
|
|
@@ -37,8 +37,8 @@ class Calendar {
|
|
|
37
37
|
second: 'numeric'
|
|
38
38
|
};*/
|
|
39
39
|
while (this.date.getMonth() === this.month) {
|
|
40
|
-
|
|
41
|
-
|
|
40
|
+
const dayToPush = this.date;
|
|
41
|
+
const days = [];
|
|
42
42
|
days.push(dayToPush.toLocaleString(I18n.getLocale(), { day: "numeric" }));
|
|
43
43
|
days.push(dayToPush.toLocaleString(I18n.getLocale(), { weekday: "short" }).toUpperCase());
|
|
44
44
|
days.push(dayToPush.toLocaleString(I18n.getLocale(), { month: "long" }).toUpperCase());
|
|
@@ -46,10 +46,10 @@ class Calendar {
|
|
|
46
46
|
this.list.push(days);
|
|
47
47
|
}
|
|
48
48
|
let index = 1;
|
|
49
|
-
for (
|
|
50
|
-
for (
|
|
51
|
-
|
|
52
|
-
if (day[1].includes(
|
|
49
|
+
for (const day of this.list) {
|
|
50
|
+
for (const nameDay of this.calendar[0]) {
|
|
51
|
+
const indexz = this.calendar[0].indexOf(nameDay);
|
|
52
|
+
if (day[1].includes(nameDay)) {
|
|
53
53
|
this.calendar[index][indexz] = day[0];
|
|
54
54
|
if (indexz === 6) {
|
|
55
55
|
index++;
|
|
@@ -2,7 +2,7 @@ const { Icon } = require("../chui_icons/icons");
|
|
|
2
2
|
const { optionOr } = require("../../modules/chui_functions");
|
|
3
3
|
|
|
4
4
|
class Card {
|
|
5
|
-
#
|
|
5
|
+
#chuiCard = document.createElement("chui_card");
|
|
6
6
|
#head;
|
|
7
7
|
#icon;
|
|
8
8
|
#titles;
|
|
@@ -22,12 +22,12 @@ class Card {
|
|
|
22
22
|
}
|
|
23
23
|
) {
|
|
24
24
|
require("../../modules/chui_functions").setStyles(__dirname + "/styles.css", "chUiJS_Card");
|
|
25
|
-
if (options.id !== undefined) this.#
|
|
25
|
+
if (options.id !== undefined) this.#chuiCard.id = options.id;
|
|
26
26
|
const style = optionOr(options.style, undefined);
|
|
27
|
-
if (style !== undefined) this.#
|
|
28
|
-
if (options.width !== undefined) this.#
|
|
29
|
-
if (options.height !== undefined) this.#
|
|
30
|
-
this.#
|
|
27
|
+
if (style !== undefined) this.#chuiCard.classList.add(style);
|
|
28
|
+
if (options.width !== undefined) this.#chuiCard.style.width = options.width;
|
|
29
|
+
if (options.height !== undefined) this.#chuiCard.style.height = options.height;
|
|
30
|
+
this.#chuiCard.appendChild(this.#body);
|
|
31
31
|
if (options.icon !== undefined) this.setIcon(options.icon);
|
|
32
32
|
if (options.title !== undefined) this.setTitle(options.title);
|
|
33
33
|
if (options.description !== undefined) this.setDescription(options.description);
|
|
@@ -35,7 +35,7 @@ class Card {
|
|
|
35
35
|
}
|
|
36
36
|
// GET
|
|
37
37
|
getId() {
|
|
38
|
-
return this.#
|
|
38
|
+
return this.#chuiCard.id;
|
|
39
39
|
}
|
|
40
40
|
getTitle() {
|
|
41
41
|
return this.#title === undefined ? "" : this.#title.innerText;
|
|
@@ -48,18 +48,18 @@ class Card {
|
|
|
48
48
|
}
|
|
49
49
|
// SET
|
|
50
50
|
setId(id = String()) {
|
|
51
|
-
this.#
|
|
51
|
+
this.#chuiCard.id = id;
|
|
52
52
|
}
|
|
53
53
|
// Пустая строка — «не задана»: `classList.add("")` бросает исключение
|
|
54
54
|
setStyle(style = String()) {
|
|
55
55
|
const known = optionOr(style, undefined);
|
|
56
|
-
if (known !== undefined) this.#
|
|
56
|
+
if (known !== undefined) this.#chuiCard.classList.add(known);
|
|
57
57
|
}
|
|
58
58
|
setWidth(width = String()) {
|
|
59
|
-
this.#
|
|
59
|
+
this.#chuiCard.style.width = width;
|
|
60
60
|
}
|
|
61
61
|
setHeight(height = String()) {
|
|
62
|
-
this.#
|
|
62
|
+
this.#chuiCard.style.height = height;
|
|
63
63
|
}
|
|
64
64
|
setIcon(icon = String()) {
|
|
65
65
|
if (this.#icon === undefined) {
|
|
@@ -84,7 +84,7 @@ class Card {
|
|
|
84
84
|
}
|
|
85
85
|
// FUNCTIONS
|
|
86
86
|
add(...components) {
|
|
87
|
-
for (
|
|
87
|
+
for (const component of components) this.#body.appendChild(component.set());
|
|
88
88
|
}
|
|
89
89
|
clear() {
|
|
90
90
|
this.#body.innerHTML = "";
|
|
@@ -93,7 +93,7 @@ class Card {
|
|
|
93
93
|
#headNode() {
|
|
94
94
|
if (this.#head === undefined) {
|
|
95
95
|
this.#head = document.createElement("card_head");
|
|
96
|
-
this.#
|
|
96
|
+
this.#chuiCard.prepend(this.#head);
|
|
97
97
|
}
|
|
98
98
|
return this.#head;
|
|
99
99
|
}
|
|
@@ -106,7 +106,7 @@ class Card {
|
|
|
106
106
|
}
|
|
107
107
|
// RENDER
|
|
108
108
|
set() {
|
|
109
|
-
return this.#
|
|
109
|
+
return this.#chuiCard;
|
|
110
110
|
}
|
|
111
111
|
}
|
|
112
112
|
|