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.
Files changed (292) hide show
  1. package/CHANGELOG.md +597 -0
  2. package/README.md +43 -644
  3. package/framework/appLayout/default/chui_app_layout.js +602 -496
  4. package/framework/appLayout/default/global_style.css +288 -97
  5. package/framework/appLayout/default/main_theme_style.css +188 -101
  6. package/framework/components/chui_accordion/accordion.js +38 -35
  7. package/framework/components/chui_accordion/styles.css +13 -12
  8. package/framework/components/chui_action_sheet/action_sheet.js +93 -64
  9. package/framework/components/chui_action_sheet/styles.css +12 -5
  10. package/framework/components/chui_actions_bar/actions_bar.js +338 -0
  11. package/framework/components/chui_actions_bar/styles.css +139 -0
  12. package/framework/components/chui_affix/affix.js +16 -11
  13. package/framework/components/chui_affix/styles.css +5 -0
  14. package/framework/components/chui_alert/alert.js +34 -19
  15. package/framework/components/chui_alert/styles.css +7 -0
  16. package/framework/components/chui_avatar/avatar.js +36 -35
  17. package/framework/components/chui_avatar/styles.css +1 -1
  18. package/framework/components/chui_avatar_group/avatar_group.js +25 -23
  19. package/framework/components/chui_avatar_group/styles.css +1 -1
  20. package/framework/components/chui_backtop/backtop.js +60 -21
  21. package/framework/components/chui_backtop/styles.css +21 -0
  22. package/framework/components/chui_badge/badge.js +30 -28
  23. package/framework/components/chui_badge/styles.css +6 -6
  24. package/framework/components/chui_banner/banner.js +222 -0
  25. package/framework/components/chui_banner/styles.css +170 -0
  26. package/framework/components/chui_breadcrumb/breadcrumb.js +15 -13
  27. package/framework/components/chui_breadcrumb/styles.css +1 -1
  28. package/framework/components/chui_button/button.js +52 -36
  29. package/framework/components/chui_button/styles.css +7 -7
  30. package/framework/components/chui_calendar/calendar.js +18 -16
  31. package/framework/components/chui_card/card.js +52 -32
  32. package/framework/components/chui_card_scroll/card_scroll.js +169 -0
  33. package/framework/components/chui_card_scroll/styles.css +86 -0
  34. package/framework/components/chui_chat/chat.js +140 -79
  35. package/framework/components/chui_chat/styles.css +18 -7
  36. package/framework/components/chui_clipboard_history/clipboard_history.js +53 -39
  37. package/framework/components/chui_clipboard_history/styles.css +13 -9
  38. package/framework/components/chui_code/code.js +10 -10
  39. package/framework/components/chui_code/styles.css +4 -4
  40. package/framework/components/chui_code_editor/code_editor.js +73 -57
  41. package/framework/components/chui_code_editor/styles.css +6 -5
  42. package/framework/components/chui_command_palette/command_palette.js +87 -64
  43. package/framework/components/chui_command_palette/styles.css +5 -5
  44. package/framework/components/chui_console/console.js +13 -13
  45. package/framework/components/chui_console/styles.css +6 -3
  46. package/framework/components/chui_content_block/content_block.js +35 -21
  47. package/framework/components/chui_content_block/styles.css +2 -2
  48. package/framework/components/chui_context_menu/context_menu.js +171 -58
  49. package/framework/components/chui_context_menu/styles.css +82 -8
  50. package/framework/components/chui_custom_element/custom_element.js +25 -18
  51. package/framework/components/chui_data_grid/data_grid.js +633 -471
  52. package/framework/components/chui_data_grid/styles.css +24 -22
  53. package/framework/components/chui_descriptions/descriptions.js +34 -17
  54. package/framework/components/chui_descriptions/styles.css +1 -1
  55. package/framework/components/chui_details/details.js +42 -36
  56. package/framework/components/chui_details/styles.css +12 -11
  57. package/framework/components/chui_diff_viewer/diff_viewer.js +172 -147
  58. package/framework/components/chui_diff_viewer/styles.css +10 -10
  59. package/framework/components/chui_divider/divider.js +19 -17
  60. package/framework/components/chui_divider/styles.css +2 -2
  61. package/framework/components/chui_drawer/drawer.js +63 -38
  62. package/framework/components/chui_drawer/styles.css +18 -4
  63. package/framework/components/chui_drop_zone/drop_zone.js +37 -27
  64. package/framework/components/chui_drop_zone/styles.css +10 -6
  65. package/framework/components/chui_empty_state/empty_state.js +20 -15
  66. package/framework/components/chui_fieldset/fieldset.js +40 -23
  67. package/framework/components/chui_fieldset/styles.css +6 -6
  68. package/framework/components/chui_file_explorer/file_explorer.js +260 -189
  69. package/framework/components/chui_file_explorer/styles.css +8 -7
  70. package/framework/components/chui_form/form.js +40 -28
  71. package/framework/components/chui_form/styles.css +1 -1
  72. package/framework/components/chui_gantt/gantt.js +102 -78
  73. package/framework/components/chui_gantt/styles.css +5 -5
  74. package/framework/components/chui_graphs/graphs.js +376 -239
  75. package/framework/components/chui_graphs/styles.css +27 -6
  76. package/framework/components/chui_hero/hero.js +98 -37
  77. package/framework/components/chui_hero/styles.css +176 -7
  78. package/framework/components/chui_html_block/html_block.js +8 -8
  79. package/framework/components/chui_html_block/styles.css +3 -3
  80. package/framework/components/chui_hx/hx.js +3 -3
  81. package/framework/components/chui_hx/styles.css +13 -6
  82. package/framework/components/chui_icons/icons.js +2115 -2115
  83. package/framework/components/chui_icons/styles.css +4 -3
  84. package/framework/components/chui_inputs/chui_check_box/check_box.js +31 -19
  85. package/framework/components/chui_inputs/chui_check_box/styles.css +30 -21
  86. package/framework/components/chui_inputs/chui_chips/chips.js +141 -70
  87. package/framework/components/chui_inputs/chui_chips/styles.css +32 -7
  88. package/framework/components/chui_inputs/chui_color_picker/color_picker.js +55 -38
  89. package/framework/components/chui_inputs/chui_color_picker/styles.css +7 -7
  90. package/framework/components/chui_inputs/chui_combo_box/combo_box.js +127 -109
  91. package/framework/components/chui_inputs/chui_combo_box/styles.css +23 -21
  92. package/framework/components/chui_inputs/chui_date/date.js +161 -127
  93. package/framework/components/chui_inputs/chui_date/styles.css +20 -19
  94. package/framework/components/chui_inputs/chui_date_range/date_range.js +61 -50
  95. package/framework/components/chui_inputs/chui_date_range/styles.css +3 -3
  96. package/framework/components/chui_inputs/chui_datetime/datetime.js +47 -39
  97. package/framework/components/chui_inputs/chui_datetime/styles.css +3 -3
  98. package/framework/components/chui_inputs/chui_email/email.js +48 -36
  99. package/framework/components/chui_inputs/chui_email/styles.css +11 -11
  100. package/framework/components/chui_inputs/chui_file/file.js +71 -44
  101. package/framework/components/chui_inputs/chui_file/styles.css +23 -19
  102. package/framework/components/chui_inputs/chui_hotkey/hotkey.js +101 -76
  103. package/framework/components/chui_inputs/chui_hotkey/styles.css +6 -6
  104. package/framework/components/chui_inputs/chui_masked/masked.js +83 -72
  105. package/framework/components/chui_inputs/chui_masked/styles.css +5 -5
  106. package/framework/components/chui_inputs/chui_mention/mention.js +87 -40
  107. package/framework/components/chui_inputs/chui_mention/styles.css +14 -8
  108. package/framework/components/chui_inputs/chui_multi_combo_box/multi_combo_box.js +242 -212
  109. package/framework/components/chui_inputs/chui_multi_combo_box/styles.css +23 -15
  110. package/framework/components/chui_inputs/chui_number/number.js +84 -70
  111. package/framework/components/chui_inputs/chui_number/styles.css +13 -13
  112. package/framework/components/chui_inputs/chui_otp/otp.js +71 -62
  113. package/framework/components/chui_inputs/chui_otp/styles.css +5 -5
  114. package/framework/components/chui_inputs/chui_password/password.js +72 -56
  115. package/framework/components/chui_inputs/chui_password/styles.css +15 -15
  116. package/framework/components/chui_inputs/chui_radio_button/radio_button.js +37 -25
  117. package/framework/components/chui_inputs/chui_radio_button/styles.css +22 -22
  118. package/framework/components/chui_inputs/chui_rating/rating.js +54 -50
  119. package/framework/components/chui_inputs/chui_rating/styles.css +3 -3
  120. package/framework/components/chui_inputs/chui_select_box/select_box.js +132 -108
  121. package/framework/components/chui_inputs/chui_select_box/styles.css +21 -21
  122. package/framework/components/chui_inputs/chui_slider/slider.js +41 -38
  123. package/framework/components/chui_inputs/chui_slider/styles.css +7 -5
  124. package/framework/components/chui_inputs/chui_text/styles.css +14 -14
  125. package/framework/components/chui_inputs/chui_text/text.js +69 -52
  126. package/framework/components/chui_inputs/chui_text_area/styles.css +14 -14
  127. package/framework/components/chui_inputs/chui_text_area/text_area.js +59 -36
  128. package/framework/components/chui_inputs/chui_time/styles.css +18 -20
  129. package/framework/components/chui_inputs/chui_time/time.js +71 -49
  130. package/framework/components/chui_inputs/chui_toggle/styles.css +13 -6
  131. package/framework/components/chui_inputs/chui_toggle/toggle.js +27 -27
  132. package/framework/components/chui_json_editor/json_editor.js +137 -127
  133. package/framework/components/chui_json_editor/styles.css +5 -5
  134. package/framework/components/chui_json_viewer/json_viewer.js +133 -114
  135. package/framework/components/chui_json_viewer/styles.css +9 -8
  136. package/framework/components/chui_kanban/kanban.js +78 -60
  137. package/framework/components/chui_kanban/styles.css +8 -4
  138. package/framework/components/chui_kbd/kbd.js +12 -10
  139. package/framework/components/chui_kbd/styles.css +1 -1
  140. package/framework/components/chui_label/label.js +31 -29
  141. package/framework/components/chui_label/styles.css +3 -3
  142. package/framework/components/chui_link/link.js +36 -29
  143. package/framework/components/chui_link/styles.css +11 -4
  144. package/framework/components/chui_list/list.js +42 -38
  145. package/framework/components/chui_list/styles.css +4 -3
  146. package/framework/components/chui_markdown_editor/markdown_editor.js +125 -109
  147. package/framework/components/chui_markdown_editor/styles.css +5 -5
  148. package/framework/components/chui_media/audio.js +457 -364
  149. package/framework/components/chui_media/audio_styles.css +74 -37
  150. package/framework/components/chui_media/image.js +99 -64
  151. package/framework/components/chui_media/image_compare.js +86 -55
  152. package/framework/components/chui_media/image_compare_styles.css +5 -5
  153. package/framework/components/chui_media/image_styles.css +4 -4
  154. package/framework/components/chui_media/video.js +264 -171
  155. package/framework/components/chui_media/video_styles.css +57 -24
  156. package/framework/components/chui_menu_bar/menu_bar.js +67 -65
  157. package/framework/components/chui_menu_bar/styles.css +14 -12
  158. package/framework/components/chui_message_bar/message_bar.js +551 -0
  159. package/framework/components/chui_message_bar/styles.css +248 -0
  160. package/framework/components/chui_modal/modal.js +81 -56
  161. package/framework/components/chui_modal/styles.css +3 -2
  162. package/framework/components/chui_notification/notification.js +107 -69
  163. package/framework/components/chui_notification/notification_download.js +28 -77
  164. package/framework/components/chui_notification/notification_download_card.js +115 -0
  165. package/framework/components/chui_notification/notification_download_progress.css +5 -4
  166. package/framework/components/chui_notification/notification_download_progress.js +73 -105
  167. package/framework/components/chui_notification/notification_update.js +44 -37
  168. package/framework/components/chui_notification/status_plate.css +3 -3
  169. package/framework/components/chui_notification/status_plate.js +2 -2
  170. package/framework/components/chui_notification/styles.css +6 -1
  171. package/framework/components/chui_notification/styles_download.css +2 -2
  172. package/framework/components/chui_notification/styles_update.css +3 -3
  173. package/framework/components/chui_org_chart/org_chart.js +101 -62
  174. package/framework/components/chui_org_chart/styles.css +2 -2
  175. package/framework/components/chui_pagination/pagination.js +65 -30
  176. package/framework/components/chui_pagination/styles.css +1 -1
  177. package/framework/components/chui_paragraph/paragraph.js +2 -2
  178. package/framework/components/chui_paragraph/styles.css +3 -3
  179. package/framework/components/chui_popover/popover.js +77 -50
  180. package/framework/components/chui_popover/styles.css +1 -1
  181. package/framework/components/chui_popups/popups.js +210 -181
  182. package/framework/components/chui_popups/styles.css +7 -7
  183. package/framework/components/chui_print_button/print_button.js +48 -33
  184. package/framework/components/chui_progress_bar/progress_bar.js +49 -19
  185. package/framework/components/chui_progress_bar/styles.css +6 -6
  186. package/framework/components/chui_progress_ring/progress_ring.js +32 -30
  187. package/framework/components/chui_progress_ring/styles.css +1 -1
  188. package/framework/components/chui_qrcode/qrcode.js +85 -41
  189. package/framework/components/chui_query_builder/query_builder.js +263 -170
  190. package/framework/components/chui_query_builder/styles.css +4 -4
  191. package/framework/components/chui_radio_group/radio_group.js +36 -26
  192. package/framework/components/chui_radio_group/styles.css +2 -2
  193. package/framework/components/chui_result/result.js +41 -31
  194. package/framework/components/chui_result/styles.css +3 -3
  195. package/framework/components/chui_scheduler/scheduler.js +126 -104
  196. package/framework/components/chui_scheduler/styles.css +11 -7
  197. package/framework/components/chui_screen_spinner/screen_spinner.js +167 -0
  198. package/framework/components/chui_screen_spinner/styles.css +49 -0
  199. package/framework/components/chui_segmented_control/segmented_control.js +90 -27
  200. package/framework/components/chui_segmented_control/styles.css +32 -6
  201. package/framework/components/chui_settings/settings.js +160 -87
  202. package/framework/components/chui_settings/styles.css +4 -4
  203. package/framework/components/chui_shortcut_help/shortcut_help.js +82 -61
  204. package/framework/components/chui_sidebar_nav/sidebar_nav.js +132 -53
  205. package/framework/components/chui_sidebar_nav/styles.css +9 -3
  206. package/framework/components/chui_skeleton/skeleton.js +29 -24
  207. package/framework/components/chui_slideshow/slideshow.js +122 -103
  208. package/framework/components/chui_slideshow/styles.css +22 -16
  209. package/framework/components/chui_spinner/spinner.js +17 -17
  210. package/framework/components/chui_spinner/styles.css +0 -1
  211. package/framework/components/chui_split_button/split_button.js +53 -30
  212. package/framework/components/chui_split_button/styles.css +22 -6
  213. package/framework/components/chui_splitter/splitter.js +46 -39
  214. package/framework/components/chui_splitter/styles.css +2 -2
  215. package/framework/components/chui_statistic/statistic.js +111 -84
  216. package/framework/components/chui_status_bar/status_bar.js +11 -9
  217. package/framework/components/chui_status_bar/styles.css +2 -2
  218. package/framework/components/chui_stepper/stepper.js +230 -54
  219. package/framework/components/chui_stepper/styles.css +79 -14
  220. package/framework/components/chui_sticky_bar/sticky_bar.js +53 -17
  221. package/framework/components/chui_sticky_bar/styles.css +11 -7
  222. package/framework/components/chui_tabs/chui_tabs.js +100 -46
  223. package/framework/components/chui_tabs/styles.css +43 -15
  224. package/framework/components/chui_text_editor/styles.css +24 -23
  225. package/framework/components/chui_text_editor/text_editor.js +103 -79
  226. package/framework/components/chui_text_editor/text_editor_panel.js +428 -367
  227. package/framework/components/chui_theme_toggle/theme_toggle.js +46 -25
  228. package/framework/components/chui_timeline/styles.css +3 -1
  229. package/framework/components/chui_timeline/timeline.js +14 -12
  230. package/framework/components/chui_toast_queue/styles.css +11 -11
  231. package/framework/components/chui_toast_queue/toast_queue.js +82 -73
  232. package/framework/components/chui_toolbar/styles.css +2 -2
  233. package/framework/components/chui_toolbar/toolbar.js +20 -13
  234. package/framework/components/chui_tooltip/styles.css +2 -2
  235. package/framework/components/chui_tooltip/tooltip.js +40 -27
  236. package/framework/components/chui_tour/styles.css +12 -7
  237. package/framework/components/chui_tour/tour.js +132 -98
  238. package/framework/components/chui_transfer/styles.css +8 -7
  239. package/framework/components/chui_transfer/transfer.js +143 -123
  240. package/framework/components/chui_tree_table/styles.css +4 -4
  241. package/framework/components/chui_tree_table/tree_table.js +88 -74
  242. package/framework/components/chui_tree_view/styles.css +14 -10
  243. package/framework/components/chui_tree_view/tree_view.js +298 -253
  244. package/framework/components/chui_user_bar/styles.css +145 -0
  245. package/framework/components/chui_user_bar/user_bar.js +402 -0
  246. package/framework/components/chui_user_list_bar/styles.css +173 -0
  247. package/framework/components/chui_user_list_bar/user_list_bar.js +485 -0
  248. package/framework/components/chui_watermark/watermark.js +41 -33
  249. package/framework/components/chui_webview/styles.css +2 -2
  250. package/framework/components/chui_webview/webview.js +64 -52
  251. package/framework/components/chui_write_bar/styles.css +172 -0
  252. package/framework/components/chui_write_bar/write_bar.js +320 -0
  253. package/framework/main_window.js +1234 -0
  254. package/framework/modules/chui_a11y/chui_a11y.js +153 -123
  255. package/framework/modules/chui_animations/animations.js +105 -43
  256. package/framework/modules/chui_animations/motion.js +120 -0
  257. package/framework/modules/chui_animations/styles.css +37 -4
  258. package/framework/modules/chui_bridge/preload.js +36 -25
  259. package/framework/modules/chui_functions.js +69 -63
  260. package/framework/modules/chui_highlight/chui_highlight.js +25 -22
  261. package/framework/modules/chui_highlight/styles.css +13 -10
  262. package/framework/modules/chui_i18n/chui_i18n.js +12 -10
  263. package/framework/modules/chui_i18n/locales/a11y.js +5 -5
  264. package/framework/modules/chui_i18n/locales/app_layout.js +5 -5
  265. package/framework/modules/chui_i18n/locales/calendar.js +3 -3
  266. package/framework/modules/chui_i18n/locales/common.js +3 -3
  267. package/framework/modules/chui_i18n/locales/data.js +36 -26
  268. package/framework/modules/chui_i18n/locales/editors.js +40 -13
  269. package/framework/modules/chui_i18n/locales/feedback.js +65 -3
  270. package/framework/modules/chui_i18n/locales/forms.js +8 -8
  271. package/framework/modules/chui_i18n/locales/graphics.js +8 -8
  272. package/framework/modules/chui_i18n/locales/media.js +4 -4
  273. package/framework/modules/chui_i18n/locales/navigation.js +12 -8
  274. package/framework/modules/chui_i18n/locales/validate.js +3 -3
  275. package/framework/modules/chui_json/chui_json.js +11 -11
  276. package/framework/modules/chui_layout/chui_layout.js +12 -10
  277. package/framework/modules/chui_logger/chui_logger.js +47 -28
  278. package/framework/modules/chui_page/page.js +39 -33
  279. package/framework/modules/chui_palette/palette.js +61 -0
  280. package/framework/modules/chui_qr/chui_qr.js +179 -88
  281. package/framework/modules/chui_scrollbar/chui_scrollbar.js +79 -68
  282. package/framework/modules/chui_scrollbar/styles.css +4 -2
  283. package/framework/modules/chui_services/chui_channels.js +27 -13
  284. package/framework/modules/chui_services/chui_services.js +47 -39
  285. package/framework/modules/chui_services/desktop.js +108 -101
  286. package/framework/modules/chui_sortable/chui_sortable.js +33 -28
  287. package/framework/modules/chui_validate/chui_validate.js +10 -7
  288. package/framework/tray_bar/chui_menu_items.js +136 -46
  289. package/index.d.ts +5046 -0
  290. package/index.js +199 -1254
  291. package/package.json +81 -68
  292. package/framework/components/telegram_bot/chui_telegram_bot.js +0 -184
@@ -1,4 +1,5 @@
1
- const {SERVICES_CHANNELS, SERVICES_CALLS, SERVICES_SYNC_CALLS, APP_PATH_NAMES} = require("./chui_channels");
1
+ const { SERVICES_CHANNELS, SERVICES_CALLS, SERVICES_SYNC_CALLS, APP_PATH_NAMES } = require("./chui_channels");
2
+ const { crossFade } = require("../chui_animations/motion");
2
3
 
3
4
  /**
4
5
  * Десктоп-сервисы со стороны страницы: буфер обмена, последние документы, прогресс на иконке
@@ -43,25 +44,25 @@ class Desktop {
43
44
  remove: (target = undefined) => Desktop.#call("clipboardHistoryRemove", target),
44
45
  clear: () => Desktop.#call("clipboardHistoryClear"),
45
46
  /** Подписка на изменение истории; возвращает функцию отписки */
46
- onChange: (listener = () => {}) => Desktop.#subscribeHistory(listener)
47
- }
47
+ onChange: (listener = () => {}) => Desktop.#subscribeHistory(listener),
48
+ },
48
49
  };
49
50
 
50
51
  static recent = {
51
52
  add: (path = String(), name = undefined) => Desktop.#call("recentAdd", path, name),
52
53
  clear: () => Desktop.#call("recentClear"),
53
- list: () => Desktop.#call("recentList")
54
+ list: () => Desktop.#call("recentList"),
54
55
  };
55
56
 
56
57
  static progress = {
57
58
  /** `progress.set(0.4)` — 40%; `mode` — TaskbarProgress.MODE */
58
59
  set: (value = Number(), mode = "normal") => Desktop.#call("progressSet", value, mode),
59
- clear: () => Desktop.#call("progressClear")
60
+ clear: () => Desktop.#call("progressClear"),
60
61
  };
61
62
 
62
63
  static shell = {
63
64
  /** Открыть адрес в браузере по умолчанию; `false` — схема не разрешена */
64
- openExternal: (url = String()) => Desktop.#call("shellOpenExternal", String(url))
65
+ openExternal: (url = String()) => Desktop.#call("shellOpenExternal", String(url)),
65
66
  };
66
67
 
67
68
  /**
@@ -78,7 +79,7 @@ class Desktop {
78
79
  page: (options = {}) => Desktop.#call("printPage", options),
79
80
  html: (html = String(), options = {}) => Desktop.#call("printHtml", String(html), options),
80
81
  /** `{saved, path, canceled}`; с `options.path` диалог сохранения не открывается */
81
- pdf: (html = String(), options = {}) => Desktop.#call("printPdf", String(html), options)
82
+ pdf: (html = String(), options = {}) => Desktop.#call("printPdf", String(html), options),
82
83
  };
83
84
 
84
85
  static shortcuts = {
@@ -86,12 +87,16 @@ class Desktop {
86
87
  off: (accelerator = String(), handler = () => {}) => Desktop.#unsubscribe(accelerator, handler),
87
88
  offAll: () => Desktop.#unsubscribeAll(),
88
89
  /** Комбинации, на которые подписано это окно */
89
- get: () => [...Desktop.#shortcut_handlers.keys()]
90
+ get: () => [...Desktop.#shortcutHandlers.keys()],
90
91
  };
91
92
 
92
93
  /**
93
94
  * Тема приложения. Палитры в стилях разложены по `prefers-color-scheme`, поэтому смена
94
- * источника меняет цвета без правок в DOM.
95
+ * источника меняет цвета без правок в DOM: Chromium сам сообщает странице новое значение
96
+ * запроса. Смена идёт кроссфейдом (`crossFade` в `chui_animations/motion`) — обычный
97
+ * CSS-переход на изменение из запроса браузер не запускает, и без него тема переключалась бы
98
+ * кадром. Смену системной схемы при источнике «system» так показать нельзя: её присылает
99
+ * сама система, и снимка «до» в этот момент уже нет.
95
100
  *
96
101
  * ```javascript
97
102
  * await Desktop.theme.set(Desktop.theme.SOURCE.DARK); // 'dark' | 'light' | 'system'
@@ -99,14 +104,15 @@ class Desktop {
99
104
  * ```
100
105
  */
101
106
  static theme = {
102
- SOURCE: {SYSTEM: "system", LIGHT: "light", DARK: "dark"},
107
+ SOURCE: { SYSTEM: "system", LIGHT: "light", DARK: "dark" },
103
108
  /** @returns {Promise<{theme: string, source: string}>} фактическая тема и выбранный источник */
104
109
  get: () => Desktop.#call("themeGet"),
105
- set: (source = String()) => Desktop.#call("themeSet", String(source)),
110
+ set: (source = String()) =>
111
+ crossFade(() => Desktop.#call("themeSet", String(source)), { waitFor: "(prefers-color-scheme: dark)" }),
106
112
  /** Переключить светлую и тёмную */
107
- toggle: () => Desktop.#call("themeToggle"),
113
+ toggle: () => crossFade(() => Desktop.#call("themeToggle"), { waitFor: "(prefers-color-scheme: dark)" }),
108
114
  /** Подписка на смену темы; возвращает функцию отписки */
109
- onChange: (listener = () => {}) => Desktop.#subscribeTheme(listener)
115
+ onChange: (listener = () => {}) => Desktop.#subscribeTheme(listener),
110
116
  };
111
117
 
112
118
  /**
@@ -122,7 +128,7 @@ class Desktop {
122
128
  get: () => Desktop.#call("localeGet"),
123
129
  set: (locale = String()) => Desktop.#call("localeSet", String(locale)),
124
130
  /** Подписка на смену языка; возвращает функцию отписки */
125
- onChange: (listener = () => {}) => Desktop.#subscribeLocale(listener)
131
+ onChange: (listener = () => {}) => Desktop.#subscribeLocale(listener),
126
132
  };
127
133
 
128
134
  /**
@@ -194,7 +200,7 @@ class Desktop {
194
200
  * Отвечает значением, а не промисом (синхронный канал), как и `quit()`.
195
201
  * @returns {boolean} `true` — перезапуск начат
196
202
  */
197
- restart: () => Desktop.#callSync("appRestartSync")
203
+ restart: () => Desktop.#callSync("appRestartSync"),
198
204
  };
199
205
 
200
206
  /**
@@ -208,7 +214,7 @@ class Desktop {
208
214
  static dialog = {
209
215
  open: (options = Object()) => Desktop.#call("dialogOpen", options),
210
216
  save: (options = Object()) => Desktop.#call("dialogSave", options),
211
- message: (options = Object()) => Desktop.#call("dialogMessage", options)
217
+ message: (options = Object()) => Desktop.#call("dialogMessage", options),
212
218
  };
213
219
 
214
220
  /**
@@ -223,25 +229,25 @@ class Desktop {
223
229
  /** @returns {Promise<number>} размер кеша в байтах */
224
230
  getCacheSize: () => Desktop.#call("sessionCacheSize"),
225
231
  clearCache: () => Desktop.#call("sessionClearCache"),
226
- clearStorageData: (options = Object()) => Desktop.#call("sessionClearStorage", options)
232
+ clearStorageData: (options = Object()) => Desktop.#call("sessionClearStorage", options),
227
233
  };
228
234
 
229
235
  // accelerator → набор обработчиков этого окна
230
- static #shortcut_handlers = new Map();
231
- static #shortcut_event_bound = false;
232
- static #shortcut_bridge_unsubscribe = undefined;
233
- static #theme_handlers = new Set();
234
- static #theme_event_bound = false;
235
- static #theme_bridge_unsubscribe = undefined;
236
- static #locale_handlers = new Set();
237
- static #locale_event_bound = false;
238
- static #locale_bridge_unsubscribe = undefined;
239
- static #history_handlers = new Set();
240
- static #history_event_bound = false;
241
- static #history_bridge_unsubscribe = undefined;
236
+ static #shortcutHandlers = new Map();
237
+ static #shortcutEventBound = false;
238
+ static #shortcutBridgeUnsubscribe = undefined;
239
+ static #themeHandlers = new Set();
240
+ static #themeEventBound = false;
241
+ static #themeBridgeUnsubscribe = undefined;
242
+ static #localeHandlers = new Set();
243
+ static #localeEventBound = false;
244
+ static #localeBridgeUnsubscribe = undefined;
245
+ static #historyHandlers = new Set();
246
+ static #historyEventBound = false;
247
+ static #historyBridgeUnsubscribe = undefined;
242
248
  // Пути приложения, уже полученные значением: `sendSync` останавливает страницу на время
243
249
  // ответа, поэтому за одним и тем же именем в main ходят один раз
244
- static #app_paths = new Map();
250
+ static #appPaths = new Map();
245
251
 
246
252
  static #bridge() {
247
253
  if (typeof window === "undefined" || window.chui === undefined) return undefined;
@@ -252,7 +258,7 @@ class Desktop {
252
258
  static #call(method = String(), ...args) {
253
259
  const services = Desktop.#bridge();
254
260
  if (services !== undefined && typeof services[method] === "function") return services[method](...args);
255
- const {ipcRenderer} = require("electron");
261
+ const { ipcRenderer } = require("electron");
256
262
  return ipcRenderer.invoke(SERVICES_CALLS[method], ...args);
257
263
  }
258
264
 
@@ -263,9 +269,10 @@ class Desktop {
263
269
  */
264
270
  static #callSync(method = String(), ...args) {
265
271
  const services = Desktop.#bridge();
266
- const answer = services !== undefined && typeof services[method] === "function"
267
- ? services[method](...args)
268
- : require("electron").ipcRenderer.sendSync(SERVICES_SYNC_CALLS[method], ...args);
272
+ const answer =
273
+ services !== undefined && typeof services[method] === "function"
274
+ ? services[method](...args)
275
+ : require("electron").ipcRenderer.sendSync(SERVICES_SYNC_CALLS[method], ...args);
269
276
  if (answer === null || typeof answer !== "object") return answer;
270
277
  if (answer.error !== undefined) throw new Error(answer.error);
271
278
  return answer.value;
@@ -280,11 +287,9 @@ class Desktop {
280
287
  * страницы одним и тем же вызовом.
281
288
  */
282
289
  static #appPath(name = String()) {
283
- if (Desktop.#app_paths.has(name)) return Desktop.#app_paths.get(name);
284
- const value = Desktop.#inMainProcess()
285
- ? Desktop.#appPathInMain(name)
286
- : Desktop.#callSync("appPathSync", name);
287
- Desktop.#app_paths.set(name, value);
290
+ if (Desktop.#appPaths.has(name)) return Desktop.#appPaths.get(name);
291
+ const value = Desktop.#inMainProcess() ? Desktop.#appPathInMain(name) : Desktop.#callSync("appPathSync", name);
292
+ Desktop.#appPaths.set(name, value);
288
293
  return value;
289
294
  }
290
295
 
@@ -310,37 +315,39 @@ class Desktop {
310
315
  */
311
316
  static #electronObject(name = String()) {
312
317
  if (Desktop.#inMainProcess() === false) {
313
- throw new Error(`Desktop.app: сырой «${name}» доступен только в main-процессе — со страницы возьмите Desktop.app.info(), Desktop.session.* или свой канал из security.channels`);
318
+ throw new Error(
319
+ `Desktop.app: сырой «${name}» доступен только в main-процессе — со страницы возьмите Desktop.app.info(), Desktop.session.* или свой канал из security.channels`
320
+ );
314
321
  }
315
322
  return require("electron")[name];
316
323
  }
317
324
 
318
325
  static #subscribe(accelerator = String(), handler = () => {}) {
319
- const handlers = Desktop.#shortcut_handlers.get(accelerator) ?? new Set();
326
+ const handlers = Desktop.#shortcutHandlers.get(accelerator) ?? new Set();
320
327
  const first = handlers.size === 0;
321
328
  handlers.add(handler);
322
- Desktop.#shortcut_handlers.set(accelerator, handlers);
323
- if (!Desktop.#shortcut_event_bound) Desktop.#bindShortcutEvent();
329
+ Desktop.#shortcutHandlers.set(accelerator, handlers);
330
+ if (!Desktop.#shortcutEventBound) Desktop.#bindShortcutEvent();
324
331
  // В main клавиша регистрируется один раз на все окна, поэтому подписка — на первую
325
332
  if (first) Desktop.#call("shortcutSubscribe", accelerator);
326
333
  return () => Desktop.#unsubscribe(accelerator, handler);
327
334
  }
328
335
 
329
336
  static #unsubscribe(accelerator = String(), handler = () => {}) {
330
- const handlers = Desktop.#shortcut_handlers.get(accelerator);
337
+ const handlers = Desktop.#shortcutHandlers.get(accelerator);
331
338
  if (handlers === undefined) return Desktop;
332
339
  handlers.delete(handler);
333
340
  if (handlers.size === 0) {
334
- Desktop.#shortcut_handlers.delete(accelerator);
341
+ Desktop.#shortcutHandlers.delete(accelerator);
335
342
  Desktop.#call("shortcutUnsubscribe", accelerator);
336
343
  }
337
- if (Desktop.#shortcut_handlers.size === 0) Desktop.#unbindShortcutEvent();
344
+ if (Desktop.#shortcutHandlers.size === 0) Desktop.#unbindShortcutEvent();
338
345
  return Desktop;
339
346
  }
340
347
 
341
348
  static #unsubscribeAll() {
342
- for (const accelerator of [...Desktop.#shortcut_handlers.keys()]) {
343
- Desktop.#shortcut_handlers.delete(accelerator);
349
+ for (const accelerator of [...Desktop.#shortcutHandlers.keys()]) {
350
+ Desktop.#shortcutHandlers.delete(accelerator);
344
351
  Desktop.#call("shortcutUnsubscribe", accelerator);
345
352
  }
346
353
  Desktop.#unbindShortcutEvent();
@@ -349,31 +356,31 @@ class Desktop {
349
356
 
350
357
  /** Событие приходит из main: сработала глобальная клавиша */
351
358
  static #onShortcutEvent = (accelerator = String()) => {
352
- const handlers = Desktop.#shortcut_handlers.get(accelerator);
359
+ const handlers = Desktop.#shortcutHandlers.get(accelerator);
353
360
  if (handlers === undefined) return;
354
361
  for (const handler of [...handlers]) handler(accelerator);
355
362
  };
356
363
 
357
364
  static #bindShortcutEvent() {
358
- Desktop.#shortcut_event_bound = true;
365
+ Desktop.#shortcutEventBound = true;
359
366
  const services = Desktop.#bridge();
360
367
  if (services !== undefined && typeof services.onShortcut === "function") {
361
- Desktop.#shortcut_bridge_unsubscribe = services.onShortcut(Desktop.#onShortcutEvent);
368
+ Desktop.#shortcutBridgeUnsubscribe = services.onShortcut(Desktop.#onShortcutEvent);
362
369
  return;
363
370
  }
364
- const {ipcRenderer} = require("electron");
371
+ const { ipcRenderer } = require("electron");
365
372
  ipcRenderer.on(SERVICES_CHANNELS.SHORTCUT_EVENT, Desktop.#ipcShortcutEvent);
366
373
  }
367
374
 
368
375
  static #unbindShortcutEvent() {
369
- if (!Desktop.#shortcut_event_bound) return;
370
- Desktop.#shortcut_event_bound = false;
371
- if (Desktop.#shortcut_bridge_unsubscribe !== undefined) {
372
- Desktop.#shortcut_bridge_unsubscribe();
373
- Desktop.#shortcut_bridge_unsubscribe = undefined;
376
+ if (!Desktop.#shortcutEventBound) return;
377
+ Desktop.#shortcutEventBound = false;
378
+ if (Desktop.#shortcutBridgeUnsubscribe !== undefined) {
379
+ Desktop.#shortcutBridgeUnsubscribe();
380
+ Desktop.#shortcutBridgeUnsubscribe = undefined;
374
381
  return;
375
382
  }
376
- const {ipcRenderer} = require("electron");
383
+ const { ipcRenderer } = require("electron");
377
384
  ipcRenderer.removeListener(SERVICES_CHANNELS.SHORTCUT_EVENT, Desktop.#ipcShortcutEvent);
378
385
  }
379
386
 
@@ -382,43 +389,43 @@ class Desktop {
382
389
  };
383
390
 
384
391
  static #subscribeTheme(listener = () => {}) {
385
- Desktop.#theme_handlers.add(listener);
386
- if (!Desktop.#theme_event_bound) Desktop.#bindThemeEvent();
392
+ Desktop.#themeHandlers.add(listener);
393
+ if (!Desktop.#themeEventBound) Desktop.#bindThemeEvent();
387
394
  return () => Desktop.#unsubscribeTheme(listener);
388
395
  }
389
396
 
390
397
  static #unsubscribeTheme(listener = () => {}) {
391
- Desktop.#theme_handlers.delete(listener);
392
- if (Desktop.#theme_handlers.size === 0) Desktop.#unbindThemeEvent();
398
+ Desktop.#themeHandlers.delete(listener);
399
+ if (Desktop.#themeHandlers.size === 0) Desktop.#unbindThemeEvent();
393
400
  return Desktop;
394
401
  }
395
402
 
396
403
  /** Событие приходит из main: тема изменилась (системой или по выбору пользователя) */
397
404
  static #onThemeEvent = (theme = String()) => {
398
- for (const listener of [...Desktop.#theme_handlers]) listener(theme);
405
+ for (const listener of [...Desktop.#themeHandlers]) listener(theme);
399
406
  };
400
407
 
401
408
  static #bindThemeEvent() {
402
- Desktop.#theme_event_bound = true;
409
+ Desktop.#themeEventBound = true;
403
410
  const bridge = typeof window === "undefined" ? undefined : window.chui;
404
411
  const theme = bridge === undefined ? undefined : bridge.theme;
405
412
  if (theme !== undefined && typeof theme.onChange === "function") {
406
- Desktop.#theme_bridge_unsubscribe = theme.onChange(Desktop.#onThemeEvent);
413
+ Desktop.#themeBridgeUnsubscribe = theme.onChange(Desktop.#onThemeEvent);
407
414
  return;
408
415
  }
409
- const {ipcRenderer} = require("electron");
416
+ const { ipcRenderer } = require("electron");
410
417
  ipcRenderer.on(SERVICES_CHANNELS.THEME_EVENT, Desktop.#ipcThemeEvent);
411
418
  }
412
419
 
413
420
  static #unbindThemeEvent() {
414
- if (!Desktop.#theme_event_bound) return;
415
- Desktop.#theme_event_bound = false;
416
- if (Desktop.#theme_bridge_unsubscribe !== undefined) {
417
- Desktop.#theme_bridge_unsubscribe();
418
- Desktop.#theme_bridge_unsubscribe = undefined;
421
+ if (!Desktop.#themeEventBound) return;
422
+ Desktop.#themeEventBound = false;
423
+ if (Desktop.#themeBridgeUnsubscribe !== undefined) {
424
+ Desktop.#themeBridgeUnsubscribe();
425
+ Desktop.#themeBridgeUnsubscribe = undefined;
419
426
  return;
420
427
  }
421
- const {ipcRenderer} = require("electron");
428
+ const { ipcRenderer } = require("electron");
422
429
  ipcRenderer.removeListener(SERVICES_CHANNELS.THEME_EVENT, Desktop.#ipcThemeEvent);
423
430
  }
424
431
 
@@ -427,43 +434,43 @@ class Desktop {
427
434
  };
428
435
 
429
436
  static #subscribeLocale(listener = () => {}) {
430
- Desktop.#locale_handlers.add(listener);
431
- if (!Desktop.#locale_event_bound) Desktop.#bindLocaleEvent();
437
+ Desktop.#localeHandlers.add(listener);
438
+ if (!Desktop.#localeEventBound) Desktop.#bindLocaleEvent();
432
439
  return () => Desktop.#unsubscribeLocale(listener);
433
440
  }
434
441
 
435
442
  static #unsubscribeLocale(listener = () => {}) {
436
- Desktop.#locale_handlers.delete(listener);
437
- if (Desktop.#locale_handlers.size === 0) Desktop.#unbindLocaleEvent();
443
+ Desktop.#localeHandlers.delete(listener);
444
+ if (Desktop.#localeHandlers.size === 0) Desktop.#unbindLocaleEvent();
438
445
  return Desktop;
439
446
  }
440
447
 
441
448
  /** Событие приходит из main: приложение сменило язык */
442
449
  static #onLocaleEvent = (locale = String()) => {
443
- for (const listener of [...Desktop.#locale_handlers]) listener(locale);
450
+ for (const listener of [...Desktop.#localeHandlers]) listener(locale);
444
451
  };
445
452
 
446
453
  static #bindLocaleEvent() {
447
- Desktop.#locale_event_bound = true;
454
+ Desktop.#localeEventBound = true;
448
455
  const bridge = typeof window === "undefined" ? undefined : window.chui;
449
456
  const locale = bridge === undefined ? undefined : bridge.locale;
450
457
  if (locale !== undefined && typeof locale.onChange === "function") {
451
- Desktop.#locale_bridge_unsubscribe = locale.onChange(Desktop.#onLocaleEvent);
458
+ Desktop.#localeBridgeUnsubscribe = locale.onChange(Desktop.#onLocaleEvent);
452
459
  return;
453
460
  }
454
- const {ipcRenderer} = require("electron");
461
+ const { ipcRenderer } = require("electron");
455
462
  ipcRenderer.on(SERVICES_CHANNELS.LOCALE_EVENT, Desktop.#ipcLocaleEvent);
456
463
  }
457
464
 
458
465
  static #unbindLocaleEvent() {
459
- if (!Desktop.#locale_event_bound) return;
460
- Desktop.#locale_event_bound = false;
461
- if (Desktop.#locale_bridge_unsubscribe !== undefined) {
462
- Desktop.#locale_bridge_unsubscribe();
463
- Desktop.#locale_bridge_unsubscribe = undefined;
466
+ if (!Desktop.#localeEventBound) return;
467
+ Desktop.#localeEventBound = false;
468
+ if (Desktop.#localeBridgeUnsubscribe !== undefined) {
469
+ Desktop.#localeBridgeUnsubscribe();
470
+ Desktop.#localeBridgeUnsubscribe = undefined;
464
471
  return;
465
472
  }
466
- const {ipcRenderer} = require("electron");
473
+ const { ipcRenderer } = require("electron");
467
474
  ipcRenderer.removeListener(SERVICES_CHANNELS.LOCALE_EVENT, Desktop.#ipcLocaleEvent);
468
475
  }
469
476
 
@@ -472,41 +479,41 @@ class Desktop {
472
479
  };
473
480
 
474
481
  static #subscribeHistory(listener = () => {}) {
475
- Desktop.#history_handlers.add(listener);
476
- if (!Desktop.#history_event_bound) Desktop.#bindHistoryEvent();
482
+ Desktop.#historyHandlers.add(listener);
483
+ if (!Desktop.#historyEventBound) Desktop.#bindHistoryEvent();
477
484
  return () => Desktop.#unsubscribeHistory(listener);
478
485
  }
479
486
 
480
487
  static #unsubscribeHistory(listener = () => {}) {
481
- Desktop.#history_handlers.delete(listener);
482
- if (Desktop.#history_handlers.size === 0) Desktop.#unbindHistoryEvent();
488
+ Desktop.#historyHandlers.delete(listener);
489
+ if (Desktop.#historyHandlers.size === 0) Desktop.#unbindHistoryEvent();
483
490
  return Desktop;
484
491
  }
485
492
 
486
493
  static #onHistoryEvent = (items = []) => {
487
- for (const listener of [...Desktop.#history_handlers]) listener(items);
494
+ for (const listener of [...Desktop.#historyHandlers]) listener(items);
488
495
  };
489
496
 
490
497
  static #bindHistoryEvent() {
491
- Desktop.#history_event_bound = true;
498
+ Desktop.#historyEventBound = true;
492
499
  const services = Desktop.#bridge();
493
500
  if (services !== undefined && typeof services.onClipboardHistory === "function") {
494
- Desktop.#history_bridge_unsubscribe = services.onClipboardHistory(Desktop.#onHistoryEvent);
501
+ Desktop.#historyBridgeUnsubscribe = services.onClipboardHistory(Desktop.#onHistoryEvent);
495
502
  return;
496
503
  }
497
- const {ipcRenderer} = require("electron");
504
+ const { ipcRenderer } = require("electron");
498
505
  ipcRenderer.on(SERVICES_CHANNELS.CLIPBOARD_HISTORY_EVENT, Desktop.#ipcHistoryEvent);
499
506
  }
500
507
 
501
508
  static #unbindHistoryEvent() {
502
- if (!Desktop.#history_event_bound) return;
503
- Desktop.#history_event_bound = false;
504
- if (Desktop.#history_bridge_unsubscribe !== undefined) {
505
- Desktop.#history_bridge_unsubscribe();
506
- Desktop.#history_bridge_unsubscribe = undefined;
509
+ if (!Desktop.#historyEventBound) return;
510
+ Desktop.#historyEventBound = false;
511
+ if (Desktop.#historyBridgeUnsubscribe !== undefined) {
512
+ Desktop.#historyBridgeUnsubscribe();
513
+ Desktop.#historyBridgeUnsubscribe = undefined;
507
514
  return;
508
515
  }
509
- const {ipcRenderer} = require("electron");
516
+ const { ipcRenderer } = require("electron");
510
517
  ipcRenderer.removeListener(SERVICES_CHANNELS.CLIPBOARD_HISTORY_EVENT, Desktop.#ipcHistoryEvent);
511
518
  }
512
519
 
@@ -515,4 +522,4 @@ class Desktop {
515
522
  };
516
523
  }
517
524
 
518
- exports.Desktop = Desktop
525
+ exports.Desktop = Desktop;
@@ -1,4 +1,4 @@
1
- const {setStyles} = require("../chui_functions");
1
+ const { setStyles } = require("../chui_functions");
2
2
 
3
3
  /**
4
4
  * Перестановка элементов внутри контейнера: строки списка, карточки, пункты меню.
@@ -27,35 +27,38 @@ const {setStyles} = require("../chui_functions");
27
27
  class Sortable {
28
28
  static AXIS = {
29
29
  Y: "y",
30
- X: "x"
30
+ X: "x",
31
31
  };
32
32
 
33
33
  #container = undefined;
34
- #item_selector = undefined;
35
- #handle_selector = undefined;
34
+ #itemSelector = undefined;
35
+ #handleSelector = undefined;
36
36
  #axis = Sortable.AXIS.Y;
37
- #on_reorder = undefined;
37
+ #onReorder = undefined;
38
38
  #enabled = true;
39
39
  #source = undefined;
40
40
  #before = undefined;
41
- #order_before = [];
41
+ #orderBefore = [];
42
42
  // Точка отсчёта отмены: сюда возвращает cancel(), и только здесь, а не в каждой перестановке
43
43
  #baseline = [];
44
44
  #bound = false;
45
45
 
46
- constructor(container = new HTMLElement(), options = {
47
- itemSelector: String(),
48
- handleSelector: String(),
49
- axis: String(),
50
- enabled: Boolean(),
51
- onReorder: undefined
52
- }) {
46
+ constructor(
47
+ container = new HTMLElement(),
48
+ options = {
49
+ itemSelector: String(),
50
+ handleSelector: String(),
51
+ axis: String(),
52
+ enabled: Boolean(),
53
+ onReorder: undefined,
54
+ }
55
+ ) {
53
56
  setStyles(__dirname + "/styles.css", "chUiJS_Sortable");
54
57
  this.#container = container;
55
- this.#item_selector = options.itemSelector === undefined ? "*" : options.itemSelector;
56
- this.#handle_selector = options.handleSelector;
58
+ this.#itemSelector = options.itemSelector === undefined ? "*" : options.itemSelector;
59
+ this.#handleSelector = options.handleSelector;
57
60
  this.#axis = options.axis === undefined ? Sortable.AXIS.Y : options.axis;
58
- this.#on_reorder = options.onReorder;
61
+ this.#onReorder = options.onReorder;
59
62
  this.#enabled = options.enabled !== false;
60
63
  this.#container.addEventListener("dragstart", this.#onDragStart);
61
64
  this.#container.addEventListener("dragover", this.#onDragOver);
@@ -86,7 +89,7 @@ class Sortable {
86
89
 
87
90
  /** Порядок изменился после последней перестановки (или с момента refresh) */
88
91
  isChanged() {
89
- return !Sortable.#sameOrder(this.#order_before, this.#items());
92
+ return !Sortable.#sameOrder(this.#orderBefore, this.#items());
90
93
  }
91
94
 
92
95
  // SET
@@ -105,8 +108,8 @@ class Sortable {
105
108
  if (item.getAttribute("tabindex") === null) item.setAttribute("tabindex", "0");
106
109
  item.classList.add("sortable_item");
107
110
  }
108
- this.#order_before = this.#items();
109
- this.#baseline = [...this.#order_before];
111
+ this.#orderBefore = this.#items();
112
+ this.#baseline = [...this.#orderBefore];
110
113
  return this;
111
114
  }
112
115
 
@@ -115,7 +118,7 @@ class Sortable {
115
118
  // Возврат идёт к точке отсчёта refresh(), а не к порядку последней перестановки: иначе
116
119
  // отмена после перетаскивания ничего бы не делала (порядок сверялся бы сам с собой)
117
120
  for (const item of this.#baseline) this.#container.appendChild(item);
118
- this.#order_before = this.#items();
121
+ this.#orderBefore = this.#items();
119
122
  return this;
120
123
  }
121
124
 
@@ -137,15 +140,15 @@ class Sortable {
137
140
  // === ВНУТРЕННЕЕ ===
138
141
  // Только прямые дети контейнера: вложенные списки сортируются своим Sortable
139
142
  #items() {
140
- return [...this.#container.children].filter((child) => child.matches(this.#item_selector));
143
+ return [...this.#container.children].filter((child) => child.matches(this.#itemSelector));
141
144
  }
142
145
 
143
146
  #itemFromEvent(event) {
144
147
  const target = event.target instanceof Element ? event.target : null;
145
148
  if (target === null) return null;
146
- const item = target.closest(this.#item_selector);
149
+ const item = target.closest(this.#itemSelector);
147
150
  if (item === null || item.parentElement !== this.#container) return null;
148
- if (this.#handle_selector !== undefined && target.closest(this.#handle_selector) === null) return null;
151
+ if (this.#handleSelector !== undefined && target.closest(this.#handleSelector) === null) return null;
149
152
  return item;
150
153
  }
151
154
 
@@ -170,9 +173,9 @@ class Sortable {
170
173
  const before = this.#before;
171
174
  this.#source = undefined;
172
175
  this.#before = undefined;
173
- if (Sortable.#sameOrder(this.#order_before, this.#items())) return;
174
- this.#order_before = this.#items();
175
- if (this.#on_reorder !== undefined) this.#on_reorder(this.getOrder(), {source: source, before: before});
176
+ if (Sortable.#sameOrder(this.#orderBefore, this.#items())) return;
177
+ this.#orderBefore = this.#items();
178
+ if (this.#onReorder !== undefined) this.#onReorder(this.getOrder(), { source: source, before: before });
176
179
  }
177
180
 
178
181
  static #sameOrder(left = [], right = []) {
@@ -218,7 +221,9 @@ class Sortable {
218
221
  const forward = this.#axis === Sortable.AXIS.X ? "ArrowRight" : "ArrowDown";
219
222
  if (event.key !== backward && event.key !== forward) return;
220
223
  const items = this.#items();
221
- const current = items.findIndex((item) => item === document.activeElement || item.contains(document.activeElement));
224
+ const current = items.findIndex(
225
+ (item) => item === document.activeElement || item.contains(document.activeElement)
226
+ );
222
227
  if (current === -1) return;
223
228
  const next = event.key === backward ? current - 1 : current + 1;
224
229
  if (next < 0 || next >= items.length) return;
@@ -235,4 +240,4 @@ class Sortable {
235
240
  };
236
241
  }
237
242
 
238
- exports.Sortable = Sortable
243
+ exports.Sortable = Sortable;
@@ -15,7 +15,7 @@
15
15
  * Общие тексты берутся из словаря текущего языка (`I18n`), поэтому и они переводятся
16
16
  * вместе с интерфейсом; свои тексты поля (`messages`) задаются строками и не переводятся.
17
17
  */
18
- const {I18n} = require("../chui_i18n/chui_i18n");
18
+ const { I18n } = require("../chui_i18n/chui_i18n");
19
19
 
20
20
  /** Ключ словаря для каждого правила: значения-параметры подставляет `I18n.t` */
21
21
  const MESSAGE_KEYS = {
@@ -25,7 +25,7 @@ const MESSAGE_KEYS = {
25
25
  minLength: "validate.minLength",
26
26
  maxLength: "validate.maxLength",
27
27
  pattern: "validate.pattern",
28
- email: "validate.email"
28
+ email: "validate.email",
29
29
  };
30
30
 
31
31
  // Сборник общих сообщений остаётся доступен как прежде, но текст берётся из текущей локали:
@@ -34,7 +34,7 @@ const DEFAULT_MESSAGES = {};
34
34
  for (const rule of Object.keys(MESSAGE_KEYS)) {
35
35
  Object.defineProperty(DEFAULT_MESSAGES, rule, {
36
36
  enumerable: true,
37
- get: () => I18n.t(MESSAGE_KEYS[rule])
37
+ get: () => I18n.t(MESSAGE_KEYS[rule]),
38
38
  });
39
39
  }
40
40
 
@@ -63,7 +63,10 @@ const fail = (rule, rules) => ({ valid: false, rule: rule, message: messageFor(r
63
63
 
64
64
  /** Проверка значения по правилам: {valid, rule?, message?} */
65
65
  function check(value, rules = {}) {
66
- const empty = typeof value === "boolean" ? value === false : String(value === undefined || value === null ? "" : value).trim() === "";
66
+ const empty =
67
+ typeof value === "boolean"
68
+ ? value === false
69
+ : String(value === undefined || value === null ? "" : value).trim() === "";
67
70
  if (empty) {
68
71
  return rules.required === true ? fail("required", rules) : { valid: true };
69
72
  }
@@ -73,9 +76,9 @@ function check(value, rules = {}) {
73
76
  if (rules.max !== undefined && (Number.isNaN(number) || number > rules.max)) return fail("max", rules);
74
77
  if (rules.minLength !== undefined && text.length < rules.minLength) return fail("minLength", rules);
75
78
  if (rules.maxLength !== undefined && text.length > rules.maxLength) return fail("maxLength", rules);
76
- const is_email = rules.type === "email";
77
- const pattern = is_email ? EMAIL_PATTERN : rules.pattern;
78
- if (pattern !== undefined && !new RegExp(pattern).test(text)) return fail(is_email ? "email" : "pattern", rules);
79
+ const isEmail = rules.type === "email";
80
+ const pattern = isEmail ? EMAIL_PATTERN : rules.pattern;
81
+ if (pattern !== undefined && !new RegExp(pattern).test(text)) return fail(isEmail ? "email" : "pattern", rules);
79
82
  if (typeof rules.validate === "function") {
80
83
  const custom = rules.validate(value);
81
84
  if (custom !== undefined && custom !== null && custom !== true) {