@rt-tools/ui-kit-v2 0.23.3 → 0.24.0

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 (354) hide show
  1. package/fesm2022/rt-tools-ui-kit-v2-accordion.mjs +142 -71
  2. package/fesm2022/rt-tools-ui-kit-v2-accordion.mjs.map +1 -1
  3. package/fesm2022/rt-tools-ui-kit-v2-action-bar.mjs +467 -231
  4. package/fesm2022/rt-tools-ui-kit-v2-action-bar.mjs.map +1 -1
  5. package/fesm2022/rt-tools-ui-kit-v2-ai-run-status.mjs +260 -91
  6. package/fesm2022/rt-tools-ui-kit-v2-ai-run-status.mjs.map +1 -1
  7. package/fesm2022/rt-tools-ui-kit-v2-aside-section.mjs +80 -46
  8. package/fesm2022/rt-tools-ui-kit-v2-aside-section.mjs.map +1 -1
  9. package/fesm2022/rt-tools-ui-kit-v2-aside.mjs +984 -697
  10. package/fesm2022/rt-tools-ui-kit-v2-aside.mjs.map +1 -1
  11. package/fesm2022/rt-tools-ui-kit-v2-autocomplete.mjs +452 -210
  12. package/fesm2022/rt-tools-ui-kit-v2-autocomplete.mjs.map +1 -1
  13. package/fesm2022/rt-tools-ui-kit-v2-bar-list.mjs +143 -52
  14. package/fesm2022/rt-tools-ui-kit-v2-bar-list.mjs.map +1 -1
  15. package/fesm2022/rt-tools-ui-kit-v2-bottom-sheet.mjs +158 -83
  16. package/fesm2022/rt-tools-ui-kit-v2-bottom-sheet.mjs.map +1 -1
  17. package/fesm2022/rt-tools-ui-kit-v2-breadcrumbs.mjs +335 -0
  18. package/fesm2022/rt-tools-ui-kit-v2-breadcrumbs.mjs.map +1 -0
  19. package/fesm2022/rt-tools-ui-kit-v2-button.mjs +437 -363
  20. package/fesm2022/rt-tools-ui-kit-v2-button.mjs.map +1 -1
  21. package/fesm2022/rt-tools-ui-kit-v2-calendar.mjs +430 -149
  22. package/fesm2022/rt-tools-ui-kit-v2-calendar.mjs.map +1 -1
  23. package/fesm2022/rt-tools-ui-kit-v2-card.mjs +155 -71
  24. package/fesm2022/rt-tools-ui-kit-v2-card.mjs.map +1 -1
  25. package/fesm2022/rt-tools-ui-kit-v2-carousel.mjs +155 -0
  26. package/fesm2022/rt-tools-ui-kit-v2-carousel.mjs.map +1 -0
  27. package/fesm2022/rt-tools-ui-kit-v2-checkbox.mjs +215 -110
  28. package/fesm2022/rt-tools-ui-kit-v2-checkbox.mjs.map +1 -1
  29. package/fesm2022/rt-tools-ui-kit-v2-collapsible-text.mjs +158 -75
  30. package/fesm2022/rt-tools-ui-kit-v2-collapsible-text.mjs.map +1 -1
  31. package/fesm2022/rt-tools-ui-kit-v2-color-palette.mjs +769 -0
  32. package/fesm2022/rt-tools-ui-kit-v2-color-palette.mjs.map +1 -0
  33. package/fesm2022/rt-tools-ui-kit-v2-confirm-popover.mjs +462 -253
  34. package/fesm2022/rt-tools-ui-kit-v2-confirm-popover.mjs.map +1 -1
  35. package/fesm2022/rt-tools-ui-kit-v2-container.mjs +1276 -1316
  36. package/fesm2022/rt-tools-ui-kit-v2-container.mjs.map +1 -1
  37. package/fesm2022/rt-tools-ui-kit-v2-copy-value.mjs +185 -80
  38. package/fesm2022/rt-tools-ui-kit-v2-copy-value.mjs.map +1 -1
  39. package/fesm2022/rt-tools-ui-kit-v2-core.mjs +2321 -2619
  40. package/fesm2022/rt-tools-ui-kit-v2-core.mjs.map +1 -1
  41. package/fesm2022/rt-tools-ui-kit-v2-counter-row.mjs +100 -44
  42. package/fesm2022/rt-tools-ui-kit-v2-counter-row.mjs.map +1 -1
  43. package/fesm2022/rt-tools-ui-kit-v2-counter.mjs +290 -155
  44. package/fesm2022/rt-tools-ui-kit-v2-counter.mjs.map +1 -1
  45. package/fesm2022/rt-tools-ui-kit-v2-data-list.mjs +2097 -858
  46. package/fesm2022/rt-tools-ui-kit-v2-data-list.mjs.map +1 -1
  47. package/fesm2022/rt-tools-ui-kit-v2-data-table.mjs +2247 -1176
  48. package/fesm2022/rt-tools-ui-kit-v2-data-table.mjs.map +1 -1
  49. package/fesm2022/rt-tools-ui-kit-v2-date-picker.mjs +1043 -705
  50. package/fesm2022/rt-tools-ui-kit-v2-date-picker.mjs.map +1 -1
  51. package/fesm2022/rt-tools-ui-kit-v2-date-range.mjs +810 -525
  52. package/fesm2022/rt-tools-ui-kit-v2-date-range.mjs.map +1 -1
  53. package/fesm2022/rt-tools-ui-kit-v2-delta-view.mjs +158 -138
  54. package/fesm2022/rt-tools-ui-kit-v2-delta-view.mjs.map +1 -1
  55. package/fesm2022/rt-tools-ui-kit-v2-detail-list.mjs +177 -67
  56. package/fesm2022/rt-tools-ui-kit-v2-detail-list.mjs.map +1 -1
  57. package/fesm2022/rt-tools-ui-kit-v2-dialog.mjs +550 -477
  58. package/fesm2022/rt-tools-ui-kit-v2-dialog.mjs.map +1 -1
  59. package/fesm2022/rt-tools-ui-kit-v2-dot-field.mjs +185 -168
  60. package/fesm2022/rt-tools-ui-kit-v2-dot-field.mjs.map +1 -1
  61. package/fesm2022/rt-tools-ui-kit-v2-download-link.mjs +116 -43
  62. package/fesm2022/rt-tools-ui-kit-v2-download-link.mjs.map +1 -1
  63. package/fesm2022/rt-tools-ui-kit-v2-draggable-tree.mjs +585 -0
  64. package/fesm2022/rt-tools-ui-kit-v2-draggable-tree.mjs.map +1 -0
  65. package/fesm2022/rt-tools-ui-kit-v2-dynamic-list.mjs +755 -259
  66. package/fesm2022/rt-tools-ui-kit-v2-dynamic-list.mjs.map +1 -1
  67. package/fesm2022/rt-tools-ui-kit-v2-dynamic-selector.mjs +3266 -1115
  68. package/fesm2022/rt-tools-ui-kit-v2-dynamic-selector.mjs.map +1 -1
  69. package/fesm2022/rt-tools-ui-kit-v2-empty-state.mjs +190 -55
  70. package/fesm2022/rt-tools-ui-kit-v2-empty-state.mjs.map +1 -1
  71. package/fesm2022/rt-tools-ui-kit-v2-expansion-panel.mjs +283 -103
  72. package/fesm2022/rt-tools-ui-kit-v2-expansion-panel.mjs.map +1 -1
  73. package/fesm2022/rt-tools-ui-kit-v2-field.mjs +393 -177
  74. package/fesm2022/rt-tools-ui-kit-v2-field.mjs.map +1 -1
  75. package/fesm2022/rt-tools-ui-kit-v2-file-card.mjs +399 -207
  76. package/fesm2022/rt-tools-ui-kit-v2-file-card.mjs.map +1 -1
  77. package/fesm2022/rt-tools-ui-kit-v2-file-drop.mjs +288 -212
  78. package/fesm2022/rt-tools-ui-kit-v2-file-drop.mjs.map +1 -1
  79. package/fesm2022/rt-tools-ui-kit-v2-file-input.mjs +262 -116
  80. package/fesm2022/rt-tools-ui-kit-v2-file-input.mjs.map +1 -1
  81. package/fesm2022/rt-tools-ui-kit-v2-file-list.mjs +57 -31
  82. package/fesm2022/rt-tools-ui-kit-v2-file-list.mjs.map +1 -1
  83. package/fesm2022/rt-tools-ui-kit-v2-filter-control.mjs +258 -90
  84. package/fesm2022/rt-tools-ui-kit-v2-filter-control.mjs.map +1 -1
  85. package/fesm2022/rt-tools-ui-kit-v2-form-control.mjs +249 -215
  86. package/fesm2022/rt-tools-ui-kit-v2-form-control.mjs.map +1 -1
  87. package/fesm2022/rt-tools-ui-kit-v2-header.mjs +199 -71
  88. package/fesm2022/rt-tools-ui-kit-v2-header.mjs.map +1 -1
  89. package/fesm2022/rt-tools-ui-kit-v2-hybrid-tree-selector.mjs +231 -0
  90. package/fesm2022/rt-tools-ui-kit-v2-hybrid-tree-selector.mjs.map +1 -0
  91. package/fesm2022/rt-tools-ui-kit-v2-hybrid-tree.mjs +336 -0
  92. package/fesm2022/rt-tools-ui-kit-v2-hybrid-tree.mjs.map +1 -0
  93. package/fesm2022/rt-tools-ui-kit-v2-icon-button.mjs +451 -162
  94. package/fesm2022/rt-tools-ui-kit-v2-icon-button.mjs.map +1 -1
  95. package/fesm2022/rt-tools-ui-kit-v2-icon.mjs +931 -686
  96. package/fesm2022/rt-tools-ui-kit-v2-icon.mjs.map +1 -1
  97. package/fesm2022/rt-tools-ui-kit-v2-image-cropper.mjs +664 -491
  98. package/fesm2022/rt-tools-ui-kit-v2-image-cropper.mjs.map +1 -1
  99. package/fesm2022/rt-tools-ui-kit-v2-image-upload.mjs +574 -222
  100. package/fesm2022/rt-tools-ui-kit-v2-image-upload.mjs.map +1 -1
  101. package/fesm2022/rt-tools-ui-kit-v2-info-item.mjs +150 -36
  102. package/fesm2022/rt-tools-ui-kit-v2-info-item.mjs.map +1 -1
  103. package/fesm2022/rt-tools-ui-kit-v2-inline-edit.mjs +606 -0
  104. package/fesm2022/rt-tools-ui-kit-v2-inline-edit.mjs.map +1 -0
  105. package/fesm2022/rt-tools-ui-kit-v2-input-number.mjs +461 -355
  106. package/fesm2022/rt-tools-ui-kit-v2-input-number.mjs.map +1 -1
  107. package/fesm2022/rt-tools-ui-kit-v2-input.mjs +338 -143
  108. package/fesm2022/rt-tools-ui-kit-v2-input.mjs.map +1 -1
  109. package/fesm2022/rt-tools-ui-kit-v2-live-badge.mjs +135 -48
  110. package/fesm2022/rt-tools-ui-kit-v2-live-badge.mjs.map +1 -1
  111. package/fesm2022/rt-tools-ui-kit-v2-logo.mjs +166 -92
  112. package/fesm2022/rt-tools-ui-kit-v2-logo.mjs.map +1 -1
  113. package/fesm2022/rt-tools-ui-kit-v2-markdown-text.mjs +118 -56
  114. package/fesm2022/rt-tools-ui-kit-v2-markdown-text.mjs.map +1 -1
  115. package/fesm2022/rt-tools-ui-kit-v2-menu.mjs +1054 -527
  116. package/fesm2022/rt-tools-ui-kit-v2-menu.mjs.map +1 -1
  117. package/fesm2022/rt-tools-ui-kit-v2-message.mjs +230 -104
  118. package/fesm2022/rt-tools-ui-kit-v2-message.mjs.map +1 -1
  119. package/fesm2022/rt-tools-ui-kit-v2-money-list.mjs +210 -70
  120. package/fesm2022/rt-tools-ui-kit-v2-money-list.mjs.map +1 -1
  121. package/fesm2022/rt-tools-ui-kit-v2-multiselect.mjs +532 -311
  122. package/fesm2022/rt-tools-ui-kit-v2-multiselect.mjs.map +1 -1
  123. package/fesm2022/rt-tools-ui-kit-v2-night-grid.mjs +125 -50
  124. package/fesm2022/rt-tools-ui-kit-v2-night-grid.mjs.map +1 -1
  125. package/fesm2022/rt-tools-ui-kit-v2-note.mjs +73 -43
  126. package/fesm2022/rt-tools-ui-kit-v2-note.mjs.map +1 -1
  127. package/fesm2022/rt-tools-ui-kit-v2-notifications-bell.mjs +161 -53
  128. package/fesm2022/rt-tools-ui-kit-v2-notifications-bell.mjs.map +1 -1
  129. package/fesm2022/rt-tools-ui-kit-v2-page-header.mjs +491 -310
  130. package/fesm2022/rt-tools-ui-kit-v2-page-header.mjs.map +1 -1
  131. package/fesm2022/rt-tools-ui-kit-v2-pagination.mjs +374 -174
  132. package/fesm2022/rt-tools-ui-kit-v2-pagination.mjs.map +1 -1
  133. package/fesm2022/rt-tools-ui-kit-v2-photo-viewer.mjs +202 -159
  134. package/fesm2022/rt-tools-ui-kit-v2-photo-viewer.mjs.map +1 -1
  135. package/fesm2022/rt-tools-ui-kit-v2-popover.mjs +438 -309
  136. package/fesm2022/rt-tools-ui-kit-v2-popover.mjs.map +1 -1
  137. package/fesm2022/rt-tools-ui-kit-v2-profile-menu.mjs +295 -0
  138. package/fesm2022/rt-tools-ui-kit-v2-profile-menu.mjs.map +1 -0
  139. package/fesm2022/rt-tools-ui-kit-v2-prompt-suggestion.mjs +135 -45
  140. package/fesm2022/rt-tools-ui-kit-v2-prompt-suggestion.mjs.map +1 -1
  141. package/fesm2022/rt-tools-ui-kit-v2-radio-button.mjs +293 -171
  142. package/fesm2022/rt-tools-ui-kit-v2-radio-button.mjs.map +1 -1
  143. package/fesm2022/rt-tools-ui-kit-v2-radius.mjs +62 -55
  144. package/fesm2022/rt-tools-ui-kit-v2-radius.mjs.map +1 -1
  145. package/fesm2022/rt-tools-ui-kit-v2-rich-editor.mjs +3379 -1466
  146. package/fesm2022/rt-tools-ui-kit-v2-rich-editor.mjs.map +1 -1
  147. package/fesm2022/rt-tools-ui-kit-v2-ripple.mjs +114 -116
  148. package/fesm2022/rt-tools-ui-kit-v2-ripple.mjs.map +1 -1
  149. package/fesm2022/rt-tools-ui-kit-v2-scroll-area.mjs +406 -299
  150. package/fesm2022/rt-tools-ui-kit-v2-scroll-area.mjs.map +1 -1
  151. package/fesm2022/rt-tools-ui-kit-v2-section-nav.mjs +137 -36
  152. package/fesm2022/rt-tools-ui-kit-v2-section-nav.mjs.map +1 -1
  153. package/fesm2022/rt-tools-ui-kit-v2-select.mjs +687 -468
  154. package/fesm2022/rt-tools-ui-kit-v2-select.mjs.map +1 -1
  155. package/fesm2022/rt-tools-ui-kit-v2-side-menu.mjs +2195 -1569
  156. package/fesm2022/rt-tools-ui-kit-v2-side-menu.mjs.map +1 -1
  157. package/fesm2022/rt-tools-ui-kit-v2-skeleton-wrapper.mjs +187 -48
  158. package/fesm2022/rt-tools-ui-kit-v2-skeleton-wrapper.mjs.map +1 -1
  159. package/fesm2022/rt-tools-ui-kit-v2-skeleton.mjs +242 -122
  160. package/fesm2022/rt-tools-ui-kit-v2-skeleton.mjs.map +1 -1
  161. package/fesm2022/rt-tools-ui-kit-v2-speed-menu.mjs +439 -0
  162. package/fesm2022/rt-tools-ui-kit-v2-speed-menu.mjs.map +1 -0
  163. package/fesm2022/rt-tools-ui-kit-v2-spinner.mjs +218 -69
  164. package/fesm2022/rt-tools-ui-kit-v2-spinner.mjs.map +1 -1
  165. package/fesm2022/rt-tools-ui-kit-v2-split-button.mjs +292 -91
  166. package/fesm2022/rt-tools-ui-kit-v2-split-button.mjs.map +1 -1
  167. package/fesm2022/rt-tools-ui-kit-v2-stat-tile.mjs +225 -138
  168. package/fesm2022/rt-tools-ui-kit-v2-stat-tile.mjs.map +1 -1
  169. package/fesm2022/rt-tools-ui-kit-v2-stepper.mjs +150 -116
  170. package/fesm2022/rt-tools-ui-kit-v2-stepper.mjs.map +1 -1
  171. package/fesm2022/rt-tools-ui-kit-v2-table.mjs +2462 -1583
  172. package/fesm2022/rt-tools-ui-kit-v2-table.mjs.map +1 -1
  173. package/fesm2022/rt-tools-ui-kit-v2-tabs.mjs +647 -346
  174. package/fesm2022/rt-tools-ui-kit-v2-tabs.mjs.map +1 -1
  175. package/fesm2022/rt-tools-ui-kit-v2-tag.mjs +335 -121
  176. package/fesm2022/rt-tools-ui-kit-v2-tag.mjs.map +1 -1
  177. package/fesm2022/rt-tools-ui-kit-v2-textarea.mjs +217 -84
  178. package/fesm2022/rt-tools-ui-kit-v2-textarea.mjs.map +1 -1
  179. package/fesm2022/rt-tools-ui-kit-v2-theme-toggle.mjs +151 -72
  180. package/fesm2022/rt-tools-ui-kit-v2-theme-toggle.mjs.map +1 -1
  181. package/fesm2022/rt-tools-ui-kit-v2-thread-list.mjs +697 -226
  182. package/fesm2022/rt-tools-ui-kit-v2-thread-list.mjs.map +1 -1
  183. package/fesm2022/rt-tools-ui-kit-v2-timeline.mjs +92 -38
  184. package/fesm2022/rt-tools-ui-kit-v2-timeline.mjs.map +1 -1
  185. package/fesm2022/rt-tools-ui-kit-v2-toast.mjs +752 -338
  186. package/fesm2022/rt-tools-ui-kit-v2-toast.mjs.map +1 -1
  187. package/fesm2022/rt-tools-ui-kit-v2-toggle-button-group.mjs +310 -129
  188. package/fesm2022/rt-tools-ui-kit-v2-toggle-button-group.mjs.map +1 -1
  189. package/fesm2022/rt-tools-ui-kit-v2-toggle-switch.mjs +286 -158
  190. package/fesm2022/rt-tools-ui-kit-v2-toggle-switch.mjs.map +1 -1
  191. package/fesm2022/rt-tools-ui-kit-v2-toolbar.mjs +270 -134
  192. package/fesm2022/rt-tools-ui-kit-v2-toolbar.mjs.map +1 -1
  193. package/fesm2022/rt-tools-ui-kit-v2-tooltip.mjs +322 -202
  194. package/fesm2022/rt-tools-ui-kit-v2-tooltip.mjs.map +1 -1
  195. package/fesm2022/rt-tools-ui-kit-v2-tree-selector.mjs +908 -0
  196. package/fesm2022/rt-tools-ui-kit-v2-tree-selector.mjs.map +1 -0
  197. package/fesm2022/rt-tools-ui-kit-v2-tree.mjs +785 -0
  198. package/fesm2022/rt-tools-ui-kit-v2-tree.mjs.map +1 -0
  199. package/fesm2022/rt-tools-ui-kit-v2-welcome-dialog.mjs +118 -63
  200. package/fesm2022/rt-tools-ui-kit-v2-welcome-dialog.mjs.map +1 -1
  201. package/fesm2022/rt-tools-ui-kit-v2-workspace-details.mjs +783 -262
  202. package/fesm2022/rt-tools-ui-kit-v2-workspace-details.mjs.map +1 -1
  203. package/fesm2022/rt-tools-ui-kit-v2-workspace.mjs +633 -294
  204. package/fesm2022/rt-tools-ui-kit-v2-workspace.mjs.map +1 -1
  205. package/fesm2022/rt-tools-ui-kit-v2.mjs +100 -103
  206. package/package.json +45 -1
  207. package/src/assets/icons/collapse-all.svg +9 -0
  208. package/src/assets/icons/expand-all.svg +9 -0
  209. package/src/assets/icons-material/collapse-all.fill.svg +5 -0
  210. package/src/assets/icons-material/collapse-all.svg +5 -0
  211. package/src/assets/icons-material/expand-all.fill.svg +5 -0
  212. package/src/assets/icons-material/expand-all.svg +5 -0
  213. package/src/assets/icons-material/undo.fill.svg +5 -0
  214. package/src/assets/icons-material/undo.svg +5 -0
  215. package/src/lib/components/bottom-sheet/CONTEXT.md +20 -2
  216. package/src/lib/components/bottom-sheet/rt-bottom-sheet.component.scss +36 -1
  217. package/src/lib/components/breadcrumbs/CONTEXT.md +37 -0
  218. package/src/lib/components/breadcrumbs/rt-breadcrumbs.component.scss +205 -0
  219. package/src/lib/components/carousel/CONTEXT.md +42 -0
  220. package/src/lib/components/carousel/rt-carousel.component.scss +117 -0
  221. package/src/lib/components/checkbox/CONTEXT.md +3 -0
  222. package/src/lib/components/checkbox/rt-checkbox.component.scss +9 -3
  223. package/src/lib/components/color-palette/CONTEXT.md +49 -0
  224. package/src/lib/components/color-palette/picker/rt-color-picker.component.scss +161 -0
  225. package/src/lib/components/color-palette/rt-color-palette.component.scss +132 -0
  226. package/src/lib/components/draggable-tree/CONTEXT.md +54 -0
  227. package/src/lib/components/draggable-tree/rt-draggable-tree.component.scss +219 -0
  228. package/src/lib/components/hybrid-tree/CONTEXT.md +31 -0
  229. package/src/lib/components/hybrid-tree-selector/CONTEXT.md +25 -0
  230. package/src/lib/components/icon-button/CONTEXT.md +3 -0
  231. package/src/lib/components/inline-edit/CONTEXT.md +41 -0
  232. package/src/lib/components/inline-edit/rt-inline-edit.component.scss +274 -0
  233. package/src/lib/components/popover/CONTEXT.md +3 -0
  234. package/src/lib/components/profile-menu/CONTEXT.md +32 -0
  235. package/src/lib/components/profile-menu/rt-profile-menu.component.scss +104 -0
  236. package/src/lib/components/speed-menu/CONTEXT.md +34 -0
  237. package/src/lib/components/speed-menu/rt-speed-menu.component.scss +118 -0
  238. package/src/lib/components/tag/rt-tag.component.scss +12 -0
  239. package/src/lib/components/thread-list/CONTEXT.md +1 -0
  240. package/src/lib/components/thread-list/rt-thread-list.component.scss +2 -1
  241. package/src/lib/components/toolbar/CONTEXT.md +9 -4
  242. package/src/lib/components/toolbar/rt-toolbar.component.scss +10 -2
  243. package/src/lib/components/tooltip/CONTEXT.md +8 -1
  244. package/src/lib/components/tree/CONTEXT.md +66 -0
  245. package/src/lib/components/tree/rt-tree.component.scss +313 -0
  246. package/src/lib/components/tree-selector/CONTEXT.md +47 -0
  247. package/src/lib/components/tree-selector/rt-tree-selector.component.scss +121 -0
  248. package/src/styles/_primitives.scss +4 -0
  249. package/src/styles/_semantic.scss +5 -0
  250. package/styles/tokens.css +43 -0
  251. package/types/rt-tools-ui-kit-v2-accordion.d.ts +31 -24
  252. package/types/rt-tools-ui-kit-v2-action-bar.d.ts +112 -91
  253. package/types/rt-tools-ui-kit-v2-ai-run-status.d.ts +64 -40
  254. package/types/rt-tools-ui-kit-v2-aside-section.d.ts +13 -10
  255. package/types/rt-tools-ui-kit-v2-aside.d.ts +268 -206
  256. package/types/rt-tools-ui-kit-v2-autocomplete.d.ts +102 -61
  257. package/types/rt-tools-ui-kit-v2-bar-list.d.ts +39 -27
  258. package/types/rt-tools-ui-kit-v2-bottom-sheet.d.ts +31 -20
  259. package/types/rt-tools-ui-kit-v2-breadcrumbs.d.ts +89 -0
  260. package/types/rt-tools-ui-kit-v2-button.d.ts +119 -59
  261. package/types/rt-tools-ui-kit-v2-calendar.d.ts +151 -86
  262. package/types/rt-tools-ui-kit-v2-card.d.ts +42 -21
  263. package/types/rt-tools-ui-kit-v2-carousel.d.ts +76 -0
  264. package/types/rt-tools-ui-kit-v2-checkbox.d.ts +48 -24
  265. package/types/rt-tools-ui-kit-v2-collapsible-text.d.ts +28 -20
  266. package/types/rt-tools-ui-kit-v2-color-palette.d.ts +208 -0
  267. package/types/rt-tools-ui-kit-v2-confirm-popover.d.ts +104 -47
  268. package/types/rt-tools-ui-kit-v2-container.d.ts +278 -221
  269. package/types/rt-tools-ui-kit-v2-copy-value.d.ts +39 -24
  270. package/types/rt-tools-ui-kit-v2-core.d.ts +862 -865
  271. package/types/rt-tools-ui-kit-v2-counter-row.d.ts +20 -12
  272. package/types/rt-tools-ui-kit-v2-counter.d.ts +70 -38
  273. package/types/rt-tools-ui-kit-v2-data-list.d.ts +429 -264
  274. package/types/rt-tools-ui-kit-v2-data-table.d.ts +500 -351
  275. package/types/rt-tools-ui-kit-v2-date-picker.d.ts +164 -138
  276. package/types/rt-tools-ui-kit-v2-date-range.d.ts +102 -84
  277. package/types/rt-tools-ui-kit-v2-delta-view.d.ts +16 -13
  278. package/types/rt-tools-ui-kit-v2-detail-list.d.ts +23 -16
  279. package/types/rt-tools-ui-kit-v2-dialog.d.ts +130 -101
  280. package/types/rt-tools-ui-kit-v2-dot-field.d.ts +10 -13
  281. package/types/rt-tools-ui-kit-v2-download-link.d.ts +22 -17
  282. package/types/rt-tools-ui-kit-v2-draggable-tree.d.ts +132 -0
  283. package/types/rt-tools-ui-kit-v2-dynamic-list.d.ts +185 -96
  284. package/types/rt-tools-ui-kit-v2-dynamic-selector.d.ts +904 -404
  285. package/types/rt-tools-ui-kit-v2-empty-state.d.ts +48 -19
  286. package/types/rt-tools-ui-kit-v2-expansion-panel.d.ts +67 -39
  287. package/types/rt-tools-ui-kit-v2-field.d.ts +90 -49
  288. package/types/rt-tools-ui-kit-v2-file-card.d.ts +115 -75
  289. package/types/rt-tools-ui-kit-v2-file-drop.d.ts +75 -48
  290. package/types/rt-tools-ui-kit-v2-file-input.d.ts +53 -36
  291. package/types/rt-tools-ui-kit-v2-file-list.d.ts +5 -8
  292. package/types/rt-tools-ui-kit-v2-filter-control.d.ts +83 -49
  293. package/types/rt-tools-ui-kit-v2-form-control.d.ts +102 -74
  294. package/types/rt-tools-ui-kit-v2-header.d.ts +40 -22
  295. package/types/rt-tools-ui-kit-v2-hybrid-tree-selector.d.ts +14 -0
  296. package/types/rt-tools-ui-kit-v2-hybrid-tree.d.ts +72 -0
  297. package/types/rt-tools-ui-kit-v2-icon-button.d.ts +190 -90
  298. package/types/rt-tools-ui-kit-v2-icon.d.ts +160 -129
  299. package/types/rt-tools-ui-kit-v2-image-cropper.d.ts +151 -111
  300. package/types/rt-tools-ui-kit-v2-image-upload.d.ts +159 -85
  301. package/types/rt-tools-ui-kit-v2-info-item.d.ts +26 -13
  302. package/types/rt-tools-ui-kit-v2-inline-edit.d.ts +194 -0
  303. package/types/rt-tools-ui-kit-v2-input-number.d.ts +102 -53
  304. package/types/rt-tools-ui-kit-v2-input.d.ts +82 -43
  305. package/types/rt-tools-ui-kit-v2-live-badge.d.ts +30 -17
  306. package/types/rt-tools-ui-kit-v2-logo.d.ts +49 -32
  307. package/types/rt-tools-ui-kit-v2-markdown-text.d.ts +26 -17
  308. package/types/rt-tools-ui-kit-v2-menu.d.ts +272 -155
  309. package/types/rt-tools-ui-kit-v2-message.d.ts +59 -33
  310. package/types/rt-tools-ui-kit-v2-money-list.d.ts +36 -18
  311. package/types/rt-tools-ui-kit-v2-multiselect.d.ts +114 -80
  312. package/types/rt-tools-ui-kit-v2-night-grid.d.ts +34 -25
  313. package/types/rt-tools-ui-kit-v2-note.d.ts +12 -9
  314. package/types/rt-tools-ui-kit-v2-notifications-bell.d.ts +37 -16
  315. package/types/rt-tools-ui-kit-v2-page-header.d.ts +218 -150
  316. package/types/rt-tools-ui-kit-v2-pagination.d.ts +99 -63
  317. package/types/rt-tools-ui-kit-v2-photo-viewer.d.ts +61 -66
  318. package/types/rt-tools-ui-kit-v2-popover.d.ts +116 -55
  319. package/types/rt-tools-ui-kit-v2-profile-menu.d.ts +103 -0
  320. package/types/rt-tools-ui-kit-v2-prompt-suggestion.d.ts +26 -16
  321. package/types/rt-tools-ui-kit-v2-radio-button.d.ts +85 -43
  322. package/types/rt-tools-ui-kit-v2-radius.d.ts +18 -15
  323. package/types/rt-tools-ui-kit-v2-rich-editor.d.ts +931 -590
  324. package/types/rt-tools-ui-kit-v2-ripple.d.ts +28 -25
  325. package/types/rt-tools-ui-kit-v2-scroll-area.d.ts +60 -58
  326. package/types/rt-tools-ui-kit-v2-section-nav.d.ts +32 -22
  327. package/types/rt-tools-ui-kit-v2-select.d.ts +182 -139
  328. package/types/rt-tools-ui-kit-v2-side-menu.d.ts +452 -349
  329. package/types/rt-tools-ui-kit-v2-skeleton-wrapper.d.ts +53 -20
  330. package/types/rt-tools-ui-kit-v2-skeleton.d.ts +55 -26
  331. package/types/rt-tools-ui-kit-v2-speed-menu.d.ts +131 -0
  332. package/types/rt-tools-ui-kit-v2-spinner.d.ts +56 -28
  333. package/types/rt-tools-ui-kit-v2-split-button.d.ts +96 -55
  334. package/types/rt-tools-ui-kit-v2-stat-tile.d.ts +88 -60
  335. package/types/rt-tools-ui-kit-v2-stepper.d.ts +50 -37
  336. package/types/rt-tools-ui-kit-v2-table.d.ts +631 -480
  337. package/types/rt-tools-ui-kit-v2-tabs.d.ts +198 -113
  338. package/types/rt-tools-ui-kit-v2-tag.d.ts +106 -53
  339. package/types/rt-tools-ui-kit-v2-textarea.d.ts +48 -25
  340. package/types/rt-tools-ui-kit-v2-theme-toggle.d.ts +28 -26
  341. package/types/rt-tools-ui-kit-v2-thread-list.d.ts +154 -94
  342. package/types/rt-tools-ui-kit-v2-timeline.d.ts +30 -28
  343. package/types/rt-tools-ui-kit-v2-toast.d.ts +174 -98
  344. package/types/rt-tools-ui-kit-v2-toggle-button-group.d.ts +132 -86
  345. package/types/rt-tools-ui-kit-v2-toggle-switch.d.ts +88 -50
  346. package/types/rt-tools-ui-kit-v2-toolbar.d.ts +30 -27
  347. package/types/rt-tools-ui-kit-v2-tooltip.d.ts +65 -41
  348. package/types/rt-tools-ui-kit-v2-tree-selector.d.ts +257 -0
  349. package/types/rt-tools-ui-kit-v2-tree.d.ts +282 -0
  350. package/types/rt-tools-ui-kit-v2-welcome-dialog.d.ts +21 -24
  351. package/types/rt-tools-ui-kit-v2-workspace-details.d.ts +195 -124
  352. package/types/rt-tools-ui-kit-v2-workspace.d.ts +122 -79
  353. package/types/rt-tools-ui-kit-v2.d.ts +100 -90
  354. package/fesm2022/rt-tools-ui-kit-v2.mjs.map +0 -1
@@ -1,1326 +1,1286 @@
1
- import { Overlay, ScrollStrategyOptions } from '@angular/cdk/overlay';
2
- import { TemplatePortal } from '@angular/cdk/portal';
3
- import { DOCUMENT, NgTemplateOutlet } from '@angular/common';
4
- import * as i0 from '@angular/core';
5
- import { signal, Injectable, Directive, inject, ElementRef, ViewContainerRef, RendererFactory2, contentChild, TemplateRef, input, output, computed, effect, ViewEncapsulation, ChangeDetectionStrategy, Component, DestroyRef, isSignal, Injector, viewChild } from '@angular/core';
6
- import { takeUntilDestroyed, outputToObservable, toObservable, toSignal } from '@angular/core/rxjs-interop';
7
- import { Subject, switchMap, merge, map, takeUntil, mergeMap, catchError, of, finalize, shareReplay, filter, take, startWith, exhaustMap, tap, defer } from 'rxjs';
8
- import { BlockDirective, ElemDirective, ModDirective } from '@rt-tools/core';
9
- import { carryThemeScope, materialPresetClassesOf, NotificationBus } from '@rt-tools/ui-kit-v2/core';
10
- import { RtToasterComponent } from '@rt-tools/ui-kit-v2/toast';
11
- import { Router, ActivatedRoute } from '@angular/router';
12
- import { RtAsideUnsavedDialogComponent, ERtAsideUnsavedOutcome, ERtAsideCloseIntent, resolveCloseIntent } from '@rt-tools/ui-kit-v2/aside';
13
- import { RtDialogService } from '@rt-tools/ui-kit-v2/dialog';
14
- import { PristineChangeEvent } from '@angular/forms';
15
-
16
- /**
17
- * Приватный signal-store для `rt-container`.
18
- *
19
- * Хранит open-state левой docked sidenav. Driver-директива
20
- * `[rtContainerLeftSidenavPanel]` пишет в `leftSidenavOpen`, шаблон
21
- * `RtContainerComponent` читает через signal-tracking.
22
- *
23
- * Provided component-level через `providers: [RtContainerStateService]` на
24
- * `RtContainerComponent` — per-instance state, без singleton'а. Pure signal IO
25
- * с автоматической reactivity.
26
- *
27
- * Правая sidenav (overlay) НЕ хранится здесь: её open-state живёт прямо в
28
- * `RtContainerComponent.rightOpen` сигнале и управляется через `openRight()` /
29
- * `closeRight()` методы + lifecycle outputs.
30
- */
31
- class RtContainerStateService {
32
- constructor() {
33
- this.leftSidenavOpen = signal(true, /* @ts-ignore */
34
- ...(ngDevMode ? [{ debugName: "leftSidenavOpen" }] : /* istanbul ignore next */ []));
35
- }
36
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: RtContainerStateService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
37
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: RtContainerStateService }); }
38
- }
39
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: RtContainerStateService, decorators: [{
40
- type: Injectable
41
- }] });
42
-
43
- /**
44
- * Маркеры слотов оболочки — своим файлом, а не рядом с панельными директивами.
45
- *
46
- * Панельные директивы берут сам компонент оболочки значением, а компонент объявляет маркеры в
47
- * своих импортах: вместе это круг «оболочка → директивы → оболочка». Маркеры пусты и не знают
48
- * об оболочке ничего, поэтому расходятся с ней без потерь.
49
- */
50
- /**
51
- * Маркер-директива для содержимого хедера `rt-container`.
52
- *
53
- * @example
54
- * ```html
55
- * <rt-container>
56
- * <ng-container *rtContainerHeader>
57
- * <rt-header />
58
- * </ng-container>
59
- * </rt-container>
60
- * ```
61
- */
62
- class RtContainerHeaderDirective {
63
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: RtContainerHeaderDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
64
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.1.6", type: RtContainerHeaderDirective, isStandalone: true, selector: "[rtContainerHeader]", ngImport: i0 }); }
65
- }
66
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: RtContainerHeaderDirective, decorators: [{
67
- type: Directive,
68
- args: [{
69
- selector: '[rtContainerHeader]',
70
- }]
71
- }] });
72
- /**
73
- * Маркер-директива для контента левой sidenav в `rt-container`.
74
- *
75
- * @example
76
- * ```html
77
- * <rt-container>
78
- * <ng-container *rtContainerLeftSidenav>
79
- * <router-outlet name="lo" />
80
- * </ng-container>
81
- * </rt-container>
82
- * ```
83
- */
84
- class RtContainerLeftSidenavDirective {
85
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: RtContainerLeftSidenavDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
86
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.1.6", type: RtContainerLeftSidenavDirective, isStandalone: true, selector: "[rtContainerLeftSidenav]", ngImport: i0 }); }
87
- }
88
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: RtContainerLeftSidenavDirective, decorators: [{
89
- type: Directive,
90
- args: [{
91
- selector: '[rtContainerLeftSidenav]',
92
- }]
93
- }] });
94
- /**
95
- * Маркер-директива для контента правой sidenav в `rt-container`.
96
- *
97
- * @example
98
- * ```html
99
- * <rt-container>
100
- * <ng-container *rtContainerRightSidenav>
101
- * <router-outlet name="ro" />
102
- * </ng-container>
103
- * </rt-container>
104
- * ```
105
- */
106
- class RtContainerRightSidenavDirective {
107
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: RtContainerRightSidenavDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
108
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.1.6", type: RtContainerRightSidenavDirective, isStandalone: true, selector: "[rtContainerRightSidenav]", ngImport: i0 }); }
109
- }
110
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: RtContainerRightSidenavDirective, decorators: [{
111
- type: Directive,
112
- args: [{
113
- selector: '[rtContainerRightSidenav]',
114
- }]
115
- }] });
116
- /**
117
- * Маркер-директива для контента в левой секции toolbar.
118
- *
119
- * @example
120
- * ```html
121
- * <rt-container>
122
- * <ng-container *rtContainerToolbarLeft>
123
- * <router-outlet name="lb" />
124
- * </ng-container>
125
- * </rt-container>
126
- * ```
127
- */
128
- class RtContainerToolbarLeftDirective {
129
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: RtContainerToolbarLeftDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
130
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.1.6", type: RtContainerToolbarLeftDirective, isStandalone: true, selector: "[rtContainerToolbarLeft]", ngImport: i0 }); }
131
- }
132
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: RtContainerToolbarLeftDirective, decorators: [{
133
- type: Directive,
134
- args: [{
135
- selector: '[rtContainerToolbarLeft]',
136
- }]
137
- }] });
138
- /**
139
- * Маркер-директива для контента в центральной секции toolbar.
140
- *
141
- * @example
142
- * ```html
143
- * <rt-container>
144
- * <ng-container *rtContainerToolbarCenter>
145
- * <router-outlet name="cb" />
146
- * </ng-container>
147
- * </rt-container>
148
- * ```
149
- */
150
- class RtContainerToolbarCenterDirective {
151
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: RtContainerToolbarCenterDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
152
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.1.6", type: RtContainerToolbarCenterDirective, isStandalone: true, selector: "[rtContainerToolbarCenter]", ngImport: i0 }); }
153
- }
154
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: RtContainerToolbarCenterDirective, decorators: [{
155
- type: Directive,
156
- args: [{
157
- selector: '[rtContainerToolbarCenter]',
158
- }]
159
- }] });
160
- /**
161
- * Маркер-директива для контента в правой секции toolbar.
162
- *
163
- * @example
164
- * ```html
165
- * <rt-container>
166
- * <ng-container *rtContainerToolbarRight>
167
- * <router-outlet name="rb" />
168
- * </ng-container>
169
- * </rt-container>
170
- * ```
171
- */
172
- class RtContainerToolbarRightDirective {
173
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: RtContainerToolbarRightDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
174
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.1.6", type: RtContainerToolbarRightDirective, isStandalone: true, selector: "[rtContainerToolbarRight]", ngImport: i0 }); }
175
- }
176
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: RtContainerToolbarRightDirective, decorators: [{
177
- type: Directive,
178
- args: [{
179
- selector: '[rtContainerToolbarRight]',
180
- }]
181
- }] });
182
- /**
183
- * Маркер-директива для основного контента `rt-container`.
184
- *
185
- * @example
186
- * ```html
187
- * <rt-container>
188
- * <ng-container *rtContainerContent>
189
- * <router-outlet />
190
- * </ng-container>
191
- * </rt-container>
192
- * ```
193
- */
194
- class RtContainerContentDirective {
195
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: RtContainerContentDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
196
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.1.6", type: RtContainerContentDirective, isStandalone: true, selector: "[rtContainerContent]", ngImport: i0 }); }
197
- }
198
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: RtContainerContentDirective, decorators: [{
199
- type: Directive,
200
- args: [{
201
- selector: '[rtContainerContent]',
202
- }]
203
- }] });
204
-
205
- /** Запас поверх длительности transition'а для страховочного таймера. */
1
+ import { Overlay, ScrollStrategyOptions } from "@angular/cdk/overlay";
2
+ import { TemplatePortal } from "@angular/cdk/portal";
3
+ import { DOCUMENT, NgTemplateOutlet } from "@angular/common";
4
+ import * as i0 from "@angular/core";
5
+ import { ChangeDetectionStrategy, Component, DestroyRef, Directive, ElementRef, Injectable, Injector, RendererFactory2, TemplateRef, ViewContainerRef, ViewEncapsulation, computed, contentChild, effect, inject, input, isSignal, output, signal, viewChild } from "@angular/core";
6
+ import { outputToObservable, takeUntilDestroyed, toObservable, toSignal } from "@angular/core/rxjs-interop";
7
+ import { Subject, catchError, defer, exhaustMap, filter, finalize, map, merge, mergeMap, of, shareReplay, startWith, switchMap, take, takeUntil, tap } from "rxjs";
8
+ import { BlockDirective, ElemDirective, ModDirective } from "@rt-tools/core";
9
+ import { NotificationBus, carryThemeScope, materialPresetClassesOf } from "@rt-tools/ui-kit-v2/core";
10
+ import { RtToasterComponent } from "@rt-tools/ui-kit-v2/toast";
11
+ import { ActivatedRoute, Router } from "@angular/router";
12
+ import { ERtAsideCloseIntent, ERtAsideUnsavedOutcome, RtAsideUnsavedDialogComponent, resolveCloseIntent } from "@rt-tools/ui-kit-v2/aside";
13
+ import { RtDialogService } from "@rt-tools/ui-kit-v2/dialog";
14
+ import { PristineChangeEvent } from "@angular/forms";
15
+ var RtContainerStateService = class RtContainerStateService {
16
+ constructor() {
17
+ this.leftSidenavOpen = signal(true, ...ngDevMode ? [{ debugName: "leftSidenavOpen" }] : /* istanbul ignore next */ []);
18
+ }
19
+ static {
20
+ this.ɵfac = i0.ɵɵngDeclareFactory({
21
+ minVersion: "12.0.0",
22
+ version: "22.2.2",
23
+ ngImport: i0,
24
+ type: RtContainerStateService,
25
+ deps: [],
26
+ target: i0.ɵɵFactoryTarget.Injectable
27
+ });
28
+ }
29
+ static {
30
+ this.ɵprov = i0.ɵɵngDeclareInjectable({
31
+ minVersion: "12.0.0",
32
+ version: "22.2.2",
33
+ ngImport: i0,
34
+ type: RtContainerStateService
35
+ });
36
+ }
37
+ };
38
+ i0.ɵɵngDeclareClassMetadata({
39
+ minVersion: "12.0.0",
40
+ version: "22.2.2",
41
+ ngImport: i0,
42
+ type: RtContainerStateService,
43
+ decorators: [{ type: Injectable }]
44
+ });
45
+ var RtContainerHeaderDirective = class RtContainerHeaderDirective {
46
+ static {
47
+ this.ɵfac = i0.ɵɵngDeclareFactory({
48
+ minVersion: "12.0.0",
49
+ version: "22.2.2",
50
+ ngImport: i0,
51
+ type: RtContainerHeaderDirective,
52
+ deps: [],
53
+ target: i0.ɵɵFactoryTarget.Directive
54
+ });
55
+ }
56
+ static {
57
+ this.ɵdir = i0.ɵɵngDeclareDirective({
58
+ minVersion: "14.0.0",
59
+ version: "22.2.2",
60
+ type: RtContainerHeaderDirective,
61
+ isStandalone: true,
62
+ selector: "[rtContainerHeader]",
63
+ ngImport: i0
64
+ });
65
+ }
66
+ };
67
+ i0.ɵɵngDeclareClassMetadata({
68
+ minVersion: "12.0.0",
69
+ version: "22.2.2",
70
+ ngImport: i0,
71
+ type: RtContainerHeaderDirective,
72
+ decorators: [{
73
+ type: Directive,
74
+ args: [{ selector: "[rtContainerHeader]" }]
75
+ }]
76
+ });
77
+ var RtContainerLeftSidenavDirective = class RtContainerLeftSidenavDirective {
78
+ static {
79
+ this.ɵfac = i0.ɵɵngDeclareFactory({
80
+ minVersion: "12.0.0",
81
+ version: "22.2.2",
82
+ ngImport: i0,
83
+ type: RtContainerLeftSidenavDirective,
84
+ deps: [],
85
+ target: i0.ɵɵFactoryTarget.Directive
86
+ });
87
+ }
88
+ static {
89
+ this.ɵdir = i0.ɵɵngDeclareDirective({
90
+ minVersion: "14.0.0",
91
+ version: "22.2.2",
92
+ type: RtContainerLeftSidenavDirective,
93
+ isStandalone: true,
94
+ selector: "[rtContainerLeftSidenav]",
95
+ ngImport: i0
96
+ });
97
+ }
98
+ };
99
+ i0.ɵɵngDeclareClassMetadata({
100
+ minVersion: "12.0.0",
101
+ version: "22.2.2",
102
+ ngImport: i0,
103
+ type: RtContainerLeftSidenavDirective,
104
+ decorators: [{
105
+ type: Directive,
106
+ args: [{ selector: "[rtContainerLeftSidenav]" }]
107
+ }]
108
+ });
109
+ var RtContainerRightSidenavDirective = class RtContainerRightSidenavDirective {
110
+ static {
111
+ this.ɵfac = i0.ɵɵngDeclareFactory({
112
+ minVersion: "12.0.0",
113
+ version: "22.2.2",
114
+ ngImport: i0,
115
+ type: RtContainerRightSidenavDirective,
116
+ deps: [],
117
+ target: i0.ɵɵFactoryTarget.Directive
118
+ });
119
+ }
120
+ static {
121
+ this.ɵdir = i0.ɵɵngDeclareDirective({
122
+ minVersion: "14.0.0",
123
+ version: "22.2.2",
124
+ type: RtContainerRightSidenavDirective,
125
+ isStandalone: true,
126
+ selector: "[rtContainerRightSidenav]",
127
+ ngImport: i0
128
+ });
129
+ }
130
+ };
131
+ i0.ɵɵngDeclareClassMetadata({
132
+ minVersion: "12.0.0",
133
+ version: "22.2.2",
134
+ ngImport: i0,
135
+ type: RtContainerRightSidenavDirective,
136
+ decorators: [{
137
+ type: Directive,
138
+ args: [{ selector: "[rtContainerRightSidenav]" }]
139
+ }]
140
+ });
141
+ var RtContainerToolbarLeftDirective = class RtContainerToolbarLeftDirective {
142
+ static {
143
+ this.ɵfac = i0.ɵɵngDeclareFactory({
144
+ minVersion: "12.0.0",
145
+ version: "22.2.2",
146
+ ngImport: i0,
147
+ type: RtContainerToolbarLeftDirective,
148
+ deps: [],
149
+ target: i0.ɵɵFactoryTarget.Directive
150
+ });
151
+ }
152
+ static {
153
+ this.ɵdir = i0.ɵɵngDeclareDirective({
154
+ minVersion: "14.0.0",
155
+ version: "22.2.2",
156
+ type: RtContainerToolbarLeftDirective,
157
+ isStandalone: true,
158
+ selector: "[rtContainerToolbarLeft]",
159
+ ngImport: i0
160
+ });
161
+ }
162
+ };
163
+ i0.ɵɵngDeclareClassMetadata({
164
+ minVersion: "12.0.0",
165
+ version: "22.2.2",
166
+ ngImport: i0,
167
+ type: RtContainerToolbarLeftDirective,
168
+ decorators: [{
169
+ type: Directive,
170
+ args: [{ selector: "[rtContainerToolbarLeft]" }]
171
+ }]
172
+ });
173
+ var RtContainerToolbarCenterDirective = class RtContainerToolbarCenterDirective {
174
+ static {
175
+ this.ɵfac = i0.ɵɵngDeclareFactory({
176
+ minVersion: "12.0.0",
177
+ version: "22.2.2",
178
+ ngImport: i0,
179
+ type: RtContainerToolbarCenterDirective,
180
+ deps: [],
181
+ target: i0.ɵɵFactoryTarget.Directive
182
+ });
183
+ }
184
+ static {
185
+ this.ɵdir = i0.ɵɵngDeclareDirective({
186
+ minVersion: "14.0.0",
187
+ version: "22.2.2",
188
+ type: RtContainerToolbarCenterDirective,
189
+ isStandalone: true,
190
+ selector: "[rtContainerToolbarCenter]",
191
+ ngImport: i0
192
+ });
193
+ }
194
+ };
195
+ i0.ɵɵngDeclareClassMetadata({
196
+ minVersion: "12.0.0",
197
+ version: "22.2.2",
198
+ ngImport: i0,
199
+ type: RtContainerToolbarCenterDirective,
200
+ decorators: [{
201
+ type: Directive,
202
+ args: [{ selector: "[rtContainerToolbarCenter]" }]
203
+ }]
204
+ });
205
+ var RtContainerToolbarRightDirective = class RtContainerToolbarRightDirective {
206
+ static {
207
+ this.ɵfac = i0.ɵɵngDeclareFactory({
208
+ minVersion: "12.0.0",
209
+ version: "22.2.2",
210
+ ngImport: i0,
211
+ type: RtContainerToolbarRightDirective,
212
+ deps: [],
213
+ target: i0.ɵɵFactoryTarget.Directive
214
+ });
215
+ }
216
+ static {
217
+ this.ɵdir = i0.ɵɵngDeclareDirective({
218
+ minVersion: "14.0.0",
219
+ version: "22.2.2",
220
+ type: RtContainerToolbarRightDirective,
221
+ isStandalone: true,
222
+ selector: "[rtContainerToolbarRight]",
223
+ ngImport: i0
224
+ });
225
+ }
226
+ };
227
+ i0.ɵɵngDeclareClassMetadata({
228
+ minVersion: "12.0.0",
229
+ version: "22.2.2",
230
+ ngImport: i0,
231
+ type: RtContainerToolbarRightDirective,
232
+ decorators: [{
233
+ type: Directive,
234
+ args: [{ selector: "[rtContainerToolbarRight]" }]
235
+ }]
236
+ });
237
+ var RtContainerContentDirective = class RtContainerContentDirective {
238
+ static {
239
+ this.ɵfac = i0.ɵɵngDeclareFactory({
240
+ minVersion: "12.0.0",
241
+ version: "22.2.2",
242
+ ngImport: i0,
243
+ type: RtContainerContentDirective,
244
+ deps: [],
245
+ target: i0.ɵɵFactoryTarget.Directive
246
+ });
247
+ }
248
+ static {
249
+ this.ɵdir = i0.ɵɵngDeclareDirective({
250
+ minVersion: "14.0.0",
251
+ version: "22.2.2",
252
+ type: RtContainerContentDirective,
253
+ isStandalone: true,
254
+ selector: "[rtContainerContent]",
255
+ ngImport: i0
256
+ });
257
+ }
258
+ };
259
+ i0.ɵɵngDeclareClassMetadata({
260
+ minVersion: "12.0.0",
261
+ version: "22.2.2",
262
+ ngImport: i0,
263
+ type: RtContainerContentDirective,
264
+ decorators: [{
265
+ type: Directive,
266
+ args: [{ selector: "[rtContainerContent]" }]
267
+ }]
268
+ });
206
269
  const ASIDE_TRANSITION_BUFFER_MS = 80;
207
- const BEM_BLOCK = 'rt-container';
208
- /**
209
- * Multi-slot container с CSS-grid layout. Slot consumers wrap content в
210
- * `*rtContainerXxx` structural directives, контейнер подхватывает шаблоны через
211
- * `contentChild(..., { read: TemplateRef })` + рендерит через `*ngTemplateOutlet`.
212
- *
213
- * Slots: `header`, `leftSidenav`, `toolbarLeft/Center/Right`, `content` — живут в
214
- * CSS-grid. `rightSidenav` рендерится через CDK Overlay поверх grid'а (slide-in
215
- * side-sheet), а не как grid-cell — overlay переиспользует глобальные
216
- * `rt-aside-overlay` / `rt-aside-backdrop` классы из rt-aside, чтобы анимация и
217
- * backdrop вели себя идентично программно открываемым asides.
218
- *
219
- * Driver-directives (`[rtContainerLeftSidenavPanel/RightSidenavPanel]`) общаются с
220
- * контейнером через `RtContainerStateService` (для левой docked) и через
221
- * `openRight()/closeRight()` + lifecycle outputs (для правой overlay).
222
- */
223
- class RtContainerComponent {
224
- #overlay;
225
- #host;
226
- #vcr;
227
- #scrollStrategies;
228
- #blockScroll;
229
- #renderer;
230
- #window;
231
- #rightOverlaySource;
232
- #overlayRef;
233
- #overlayRefSignal;
234
- constructor() {
235
- this.#overlay = inject(Overlay);
236
- this.#host = inject(ElementRef);
237
- this.#vcr = inject(ViewContainerRef);
238
- this.#scrollStrategies = inject(ScrollStrategyOptions);
239
- this.#blockScroll = this.#scrollStrategies.block();
240
- this.#renderer = inject(RendererFactory2).createRenderer(null, null);
241
- this.#window = inject(DOCUMENT).defaultView;
242
- this.#rightOverlaySource = new Subject();
243
- this.#overlayRef = null;
244
- this.#overlayRefSignal = signal(null, /* @ts-ignore */
245
- ...(ngDevMode ? [{ debugName: "#overlayRefSignal" }] : /* istanbul ignore next */ []));
246
- this.headerTpl = contentChild(RtContainerHeaderDirective, { ...(ngDevMode ? { debugName: "headerTpl" } : /* istanbul ignore next */ {}), read: TemplateRef });
247
- this.leftSidenavTpl = contentChild(RtContainerLeftSidenavDirective, { ...(ngDevMode ? { debugName: "leftSidenavTpl" } : /* istanbul ignore next */ {}), read: TemplateRef });
248
- this.rightSidenavTpl = contentChild(RtContainerRightSidenavDirective, { ...(ngDevMode ? { debugName: "rightSidenavTpl" } : /* istanbul ignore next */ {}), read: TemplateRef });
249
- this.toolbarLeftTpl = contentChild(RtContainerToolbarLeftDirective, { ...(ngDevMode ? { debugName: "toolbarLeftTpl" } : /* istanbul ignore next */ {}), read: TemplateRef });
250
- this.toolbarCenterTpl = contentChild(RtContainerToolbarCenterDirective, { ...(ngDevMode ? { debugName: "toolbarCenterTpl" } : /* istanbul ignore next */ {}), read: TemplateRef });
251
- this.toolbarRightTpl = contentChild(RtContainerToolbarRightDirective, { ...(ngDevMode ? { debugName: "toolbarRightTpl" } : /* istanbul ignore next */ {}), read: TemplateRef });
252
- this.contentTpl = contentChild(RtContainerContentDirective, { ...(ngDevMode ? { debugName: "contentTpl" } : /* istanbul ignore next */ {}), read: TemplateRef });
253
- /**
254
- * Поведение левого sidenav на мобилке (<=768px): `keep` — остаётся боковой
255
- * колонкой (по умолчанию, десктоп-стиль); `bottom` — сворачивается в нижний
256
- * ряд grid'а (таб-бар), контент занимает всю ширину и скроллится над ним.
257
- */
258
- this.mobileLeftNav = input('keep', /* @ts-ignore */
259
- ...(ngDevMode ? [{ debugName: "mobileLeftNav" }] : /* istanbul ignore next */ []));
260
- /**
261
- * Высота контейнера: `auto` — растёт под контент, скроллится документ (по
262
- * умолчанию; на этом держится sticky-хедер); `viewport` — контейнер жёстко
263
- * равен вьюпорту, страница не скроллится вовсе, а скроллятся зоны внутри —
264
- * каждая сама по себе (app-shell раскладка, напр. чаты бот-панели).
265
- */
266
- this.height = input('auto', /* @ts-ignore */
267
- ...(ngDevMode ? [{ debugName: "height" }] : /* istanbul ignore next */ []));
268
- this.backdropClick = output();
269
- this.rightOpened = output();
270
- this.rightClosed = output();
271
- this.rightOpen = signal(false, /* @ts-ignore */
272
- ...(ngDevMode ? [{ debugName: "rightOpen" }] : /* istanbul ignore next */ []));
273
- /**
274
- * `true` когда CDK Overlay для правой sidenav создан и attache'нут (см.
275
- * effect в constructor'е). Дёргать panel.open() из консьюмера можно только
276
- * когда это true — иначе openRight() видит null overlayRef и early-return'ит,
277
- * --entering modifier остаётся, панель остаётся за экраном. Re-exposed на
278
- * driver через `panel.ready` для удобства route-driven dialog'ов.
279
- */
280
- this.rightOverlayReady = computed(() => this.#overlayRefSignal() !== null, /* @ts-ignore */
281
- ...(ngDevMode ? [{ debugName: "rightOverlayReady" }] : /* istanbul ignore next */ []));
282
- // Backdrop-click / ESC подписки правого overlay живут в одном
283
- // конструкторном стриме: #createRightOverlay эмитит созданный OverlayRef,
284
- // switchMap переключается на его event-стримы (предыдущий overlay к этому
285
- // моменту уже dispose'нут effect-cleanup'ом; `detachments()` терминирует
286
- // внутренний поток при dispose).
287
- this.#rightOverlaySource
288
- .pipe(switchMap((overlayRef) => merge(overlayRef.backdropClick().pipe(map(() => () => this.backdropClick.emit())), overlayRef.keydownEvents().pipe(map((event) => () => {
289
- if (event.key !== 'Escape' || !this.rightOpen()) {
290
- return;
291
- }
292
- event.preventDefault();
293
- this.backdropClick.emit();
294
- }))).pipe(takeUntil(overlayRef.detachments()))), takeUntilDestroyed())
295
- .subscribe((handleCloseIntent) => handleCloseIntent());
296
- // Persistent overlay: создаётся при появлении rightSidenavTpl и живёт
297
- // до уничтожения rt-container'а. Это нужно чтобы <router-outlet name="ro">
298
- // внутри slot template'а материализовался и мог активировать route.
299
- // Без auto-attach landmine: route не активируется → driver не вызывается
300
- // → ничего не открывается (chicken-and-egg).
301
- effect((onCleanup) => {
302
- const tpl = this.rightSidenavTpl();
303
- if (tpl === undefined || this.#overlayRef !== null) {
304
- return;
305
- }
306
- const overlayRef = this.#createRightOverlay(tpl);
307
- this.#overlayRef = overlayRef;
308
- this.#overlayRefSignal.set(overlayRef);
309
- onCleanup(() => {
310
- overlayRef.dispose();
311
- this.#overlayRef = null;
312
- this.#overlayRefSignal.set(null);
313
- });
314
- });
315
- }
316
- openRight() {
317
- const overlayRef = this.#overlayRef;
318
- if (overlayRef === null) {
319
- return;
320
- }
321
- this.#blockScroll.enable();
322
- // Коробка постоянная и лежит в конце страницы, а кусок темы вокруг контейнера мог смениться.
323
- carryThemeScope(overlayRef.overlayElement, this.#host.nativeElement);
324
- this.#renderer.removeClass(overlayRef.overlayElement, 'rt-aside-overlay--entering');
325
- this.#renderer.removeClass(overlayRef.overlayElement, 'rt-aside-overlay--leaving');
326
- const backdropEl = overlayRef.backdropElement;
327
- if (backdropEl !== null) {
328
- this.#renderer.addClass(backdropEl, 'rt-aside-backdrop--visible');
329
- this.#renderer.removeStyle(backdropEl, 'opacity');
330
- this.#renderer.removeStyle(backdropEl, 'pointer-events');
331
- }
332
- // Slide-in: на следующий paint добавляем --open.
333
- requestAnimationFrame(() => {
334
- this.#renderer.addClass(overlayRef.overlayElement, 'rt-aside-overlay--open');
335
- this.#listenTransitionEnd(overlayRef, () => this.rightOpened.emit());
336
- });
337
- this.rightOpen.set(true);
338
- }
339
- closeRight() {
340
- const overlayRef = this.#overlayRef;
341
- if (overlayRef === null || !this.rightOpen()) {
342
- return;
343
- }
344
- this.#renderer.removeClass(overlayRef.overlayElement, 'rt-aside-overlay--open');
345
- this.#renderer.addClass(overlayRef.overlayElement, 'rt-aside-overlay--leaving');
346
- const backdropEl = overlayRef.backdropElement;
347
- if (backdropEl !== null) {
348
- this.#renderer.removeClass(backdropEl, 'rt-aside-backdrop--visible');
349
- }
350
- this.#listenTransitionEnd(overlayRef, () => {
351
- this.#blockScroll.disable();
352
- // Объявления на узле возвращаются только после ухода: поставленные сразу, они
353
- // обрывают затухание подложки на первом же кадре.
354
- this.#hideBackdrop(overlayRef);
355
- this.rightOpen.set(false);
356
- this.rightClosed.emit();
357
- });
358
- }
359
- /**
360
- * Подложка закрытой панели: невидима и нажатий не ловит.
361
- *
362
- * Стилями этого не сделать. Правила кита живут в слое каскада, а CDK кладёт свои прямо на
363
- * страницу, вне слоя, — и `.cdk-overlay-backdrop-showing { opacity: 1 }` выигрывает у нашего
364
- * `opacity: 0` независимо от специфичности: неслоевое правило сильнее слоевого всегда.
365
- * Подложка при этом висит поверх страницы во весь экран — прозрачная и перехватывающая
366
- * нажатия, а панель ещё не открывали. Объявление на самом узле сильнее обоих правил.
367
- *
368
- * Держится это ровно до открытия: там объявления снимаются, и дальше видом подложки
369
- * заведуют классы.
370
- */
371
- #hideBackdrop(overlayRef) {
372
- const backdropEl = overlayRef.backdropElement;
373
- if (backdropEl === null) {
374
- return;
375
- }
376
- this.#renderer.setStyle(backdropEl, 'opacity', '0');
377
- this.#renderer.setStyle(backdropEl, 'pointer-events', 'none');
378
- }
379
- #createRightOverlay(tpl) {
380
- const positionStrategy = this.#overlay.position().global().right('0').top('0');
381
- const overlayConfig = {
382
- positionStrategy,
383
- // noop здесь, scroll-block управляется вручную через #blockScroll
384
- // в openRight/closeRight — иначе scroll заблокирован всегда
385
- // (overlay persistent), пока aside ещё не открыт.
386
- scrollStrategy: this.#overlay.scrollStrategies.noop(),
387
- hasBackdrop: true,
388
- backdropClass: 'rt-aside-backdrop',
389
- panelClass: [
390
- 'rt-aside-overlay',
391
- 'rt-aside-overlay--position-right',
392
- 'rt-aside-overlay--entering',
393
- ...materialPresetClassesOf(this.#host.nativeElement),
394
- ],
395
- disposeOnNavigation: false,
396
- };
397
- const overlayRef = this.#overlay.create(overlayConfig);
398
- const portal = new TemplatePortal(tpl, this.#vcr);
399
- overlayRef.attach(portal);
400
- this.#hideBackdrop(overlayRef);
401
- // Backdrop-click / ESC подписки объявлены один раз в конструкторе —
402
- // здесь только эмит созданного OverlayRef (см. #rightOverlaySource-стрим).
403
- this.#rightOverlaySource.next(overlayRef);
404
- return overlayRef;
405
- }
406
- // Слушаем именно transform-окончание: на overlay host'е могут анимироваться
407
- // и другие свойства (opacity backdrop'а, например) — это даст ложные срабатывания.
408
- #listenTransitionEnd(overlayRef, callback) {
409
- const element = overlayRef.overlayElement;
410
- // Нет анимации (reduced-motion / `transition: none`) → `transitionend` не
411
- // придёт; teardown-callback (навигация `ro:null`) отрабатываем синхронно.
412
- const durationMs = this.#transitionDurationMs(element);
413
- if (durationMs === 0) {
414
- callback();
415
- return;
416
- }
417
- // settled-гард делает transitionend и fallback-таймаут взаимно
418
- // идемпотентными — сработает и снимет listener только то, что раньше.
419
- let settled = false;
420
- const handler = (event) => {
421
- if (event.propertyName !== 'transform' || settled) {
422
- return;
423
- }
424
- settled = true;
425
- element.removeEventListener('transitionend', handler);
426
- callback();
427
- };
428
- element.addEventListener('transitionend', handler);
429
- // Страховка на случай пропущенного `transitionend` (лаг рендера).
430
- setTimeout(() => {
431
- if (settled) {
432
- return;
433
- }
434
- settled = true;
435
- element.removeEventListener('transitionend', handler);
436
- callback();
437
- }, durationMs + ASIDE_TRANSITION_BUFFER_MS);
438
- }
439
- // Максимальная длительность transition'а элемента в мс; `0` если анимации нет.
440
- #transitionDurationMs(element) {
441
- const durationCss = this.#window?.getComputedStyle(element).transitionDuration;
442
- if (durationCss === undefined || durationCss === '') {
443
- return 0;
444
- }
445
- const maxSeconds = durationCss.split(',').reduce((max, part) => {
446
- const trimmed = part.trim();
447
- const seconds = trimmed.endsWith('ms') ? Number.parseFloat(trimmed) / 1000 : Number.parseFloat(trimmed);
448
- return Number.isNaN(seconds) ? max : Math.max(max, seconds);
449
- }, 0);
450
- return maxSeconds * 1000;
451
- }
452
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: RtContainerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
453
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: RtContainerComponent, isStandalone: true, selector: "rt-container", inputs: { mobileLeftNav: { classPropertyName: "mobileLeftNav", publicName: "mobileLeftNav", isSignal: true, isRequired: false, transformFunction: null }, height: { classPropertyName: "height", publicName: "height", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { backdropClick: "backdropClick", rightOpened: "rightOpened", rightClosed: "rightClosed" }, host: { properties: { "class.rt-container--mobile-left-bottom": "mobileLeftNav() === 'bottom'", "class.rt-container--viewport": "height() === 'viewport'" }, classAttribute: "rt-container" }, providers: [RtContainerStateService], queries: [{ propertyName: "headerTpl", first: true, predicate: RtContainerHeaderDirective, descendants: true, read: TemplateRef, isSignal: true }, { propertyName: "leftSidenavTpl", first: true, predicate: RtContainerLeftSidenavDirective, descendants: true, read: TemplateRef, isSignal: true }, { propertyName: "rightSidenavTpl", first: true, predicate: RtContainerRightSidenavDirective, descendants: true, read: TemplateRef, isSignal: true }, { propertyName: "toolbarLeftTpl", first: true, predicate: RtContainerToolbarLeftDirective, descendants: true, read: TemplateRef, isSignal: true }, { propertyName: "toolbarCenterTpl", first: true, predicate: RtContainerToolbarCenterDirective, descendants: true, read: TemplateRef, isSignal: true }, { propertyName: "toolbarRightTpl", first: true, predicate: RtContainerToolbarRightDirective, descendants: true, read: TemplateRef, isSignal: true }, { propertyName: "contentTpl", first: true, predicate: RtContainerContentDirective, descendants: true, read: TemplateRef, isSignal: true }], ngImport: i0, template: "<ng-container rtBlock=\"rt-container\">\n @if (headerTpl(); as tpl) {\n <header rtElem=\"header\" qa-dataid=\"container-header\">\n <ng-container [ngTemplateOutlet]=\"tpl\" />\n </header>\n }\n\n @if (leftSidenavTpl(); as tpl) {\n <aside rtElem=\"left-sidenav\" qa-dataid=\"container-left-sidenav\">\n <ng-container [ngTemplateOutlet]=\"tpl\" />\n </aside>\n }\n\n @if (toolbarLeftTpl(); as tpl) {\n <div rtElem=\"toolbar\" qa-dataid=\"container-toolbar\" data-slot=\"left\" [rtMod]=\"{ slot: 'left' }\">\n <ng-container [ngTemplateOutlet]=\"tpl\" />\n </div>\n }\n\n @if (toolbarCenterTpl(); as tpl) {\n <div rtElem=\"toolbar\" qa-dataid=\"container-toolbar\" data-slot=\"center\" [rtMod]=\"{ slot: 'center' }\">\n <ng-container [ngTemplateOutlet]=\"tpl\" />\n </div>\n }\n\n @if (toolbarRightTpl(); as tpl) {\n <div rtElem=\"toolbar\" qa-dataid=\"container-toolbar\" data-slot=\"right\" [rtMod]=\"{ slot: 'right' }\">\n <ng-container [ngTemplateOutlet]=\"tpl\" />\n </div>\n }\n\n @if (contentTpl(); as tpl) {\n <main rtElem=\"content\" qa-dataid=\"container-content\">\n <ng-container [ngTemplateOutlet]=\"tpl\" />\n </main>\n }\n\n <rt-toaster position=\"bottom-center\" />\n</ng-container>\n", styles: ["@charset \"UTF-8\";@layer rt-kit.components{:root{--rt-aside-animation-duration: .2s;--rt-aside-backdrop-bg: var(--rt-color-bg-overlay);--rt-aside-backdrop-blur: 5px}.cdk-overlay-backdrop.rt-aside-backdrop{-webkit-backdrop-filter:blur(var(--rt-aside-backdrop-blur));backdrop-filter:blur(var(--rt-aside-backdrop-blur));background:var(--rt-aside-backdrop-bg);transition:opacity var(--rt-aside-animation-duration) ease}:is(.rt-preset-material,[data-preset=material]).cdk-overlay-backdrop.rt-aside-backdrop,[data-preset=material] .cdk-overlay-backdrop.rt-aside-backdrop{--rt-aside-backdrop-bg: var(--rt-color-bg-overlay);--rt-aside-backdrop-blur: 0}.rt-aside-overlay{height:100dvh;transition:transform var(--rt-aside-animation-duration) ease}.rt-aside-overlay.rt-aside-overlay--entering{transition:none}.rt-aside-overlay--position-right.rt-aside-overlay--entering,.rt-aside-overlay--position-right.rt-aside-overlay--leaving{transform:translate(100%)}.rt-aside-overlay--position-left.rt-aside-overlay--entering,.rt-aside-overlay--position-left.rt-aside-overlay--leaving{transform:translate(-100%)}.rt-aside-overlay--position-right.rt-aside-overlay--open,.rt-aside-overlay--position-left.rt-aside-overlay--open{transform:translate(0)}@media(width<=768px){.rt-aside-overlay{overflow:hidden;width:100dvw;max-width:100dvw}}@media(prefers-reduced-motion:reduce){.rt-aside-overlay{transition:none}}}.cdk-overlay-backdrop.rt-aside-backdrop{opacity:0;pointer-events:none}.cdk-overlay-backdrop.rt-aside-backdrop.rt-aside-backdrop--visible{opacity:1;pointer-events:auto}.rt-aside-overlay:not(.rt-aside-overlay--open){pointer-events:none}@layer rt-kit.components{.rt-container{--rt-container-border-width: var(--rt-border-width-thin);display:grid;min-height:100%;flex:1 1 auto;background-color:var(--rt-color-bg-page);color:var(--rt-color-text-primary);grid-template:\"header header\" auto \"left-sidenav toolbar\" auto \"left-sidenav content\" 1fr/auto 1fr}.rt-container__header{position:sticky;z-index:1;top:0;display:block;grid-area:header}.rt-container__header>.rt-page-header{margin:var(--rt-space-5) var(--rt-space-5) 0}.rt-container__left-sidenav{display:block;padding:var(--rt-space-md);border-right:var(--rt-container-border-width) solid var(--rt-color-border-subtle);background-color:var(--rt-color-bg-surface);grid-area:left-sidenav}.rt-container__toolbar{display:flex;align-items:center;padding:var(--rt-space-sm) var(--rt-space-md);border-bottom:var(--rt-container-border-width) solid var(--rt-color-border-subtle);background-color:var(--rt-color-bg-surface);grid-area:toolbar}.rt-container__toolbar--slot--left{justify-content:flex-start}.rt-container__toolbar--slot--center{justify-content:center}.rt-container__toolbar--slot--right{justify-content:flex-end}.rt-container__content{display:flex;overflow:auto;min-height:0;flex-direction:column;grid-area:content}.rt-container--viewport{block-size:100dvh;min-block-size:0}.rt-container--viewport .rt-container__content{overflow:hidden}.rt-container--viewport .rt-container__left-sidenav{overflow:auto}@media(width<=768px){.rt-container--mobile-left-bottom{grid-template:\"header\" auto \"toolbar\" auto \"content\" 1fr \"left-sidenav\" auto/1fr}.rt-container--mobile-left-bottom .rt-container__left-sidenav{padding:0;border-top:var(--rt-container-border-width) solid var(--rt-color-border-subtle);border-right:none}}}\n"], dependencies: [{ kind: "directive", type:
454
- // Angular
455
- NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type:
456
- // standalone components / directives
457
- RtToasterComponent, selector: "rt-toaster", inputs: ["position", "duration", "visibleToasts", "mode", "expand"] }, { kind: "directive", type: BlockDirective, selector: "[rtBlock]", inputs: ["rtMod"] }, { kind: "directive", type: ElemDirective, selector: "[rtElem]", inputs: ["rtMod"] }, { kind: "directive", type: ModDirective, selector: "[rtMod]" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
458
- }
459
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: RtContainerComponent, decorators: [{
460
- type: Component,
461
- args: [{ selector: 'rt-container', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [
462
- // Angular
463
- NgTemplateOutlet,
464
- // standalone components / directives
465
- RtToasterComponent,
466
- BlockDirective,
467
- ElemDirective,
468
- ModDirective,
469
- ], providers: [RtContainerStateService], host: {
470
- class: BEM_BLOCK,
471
- '[class.rt-container--mobile-left-bottom]': "mobileLeftNav() === 'bottom'",
472
- '[class.rt-container--viewport]': "height() === 'viewport'",
473
- }, template: "<ng-container rtBlock=\"rt-container\">\n @if (headerTpl(); as tpl) {\n <header rtElem=\"header\" qa-dataid=\"container-header\">\n <ng-container [ngTemplateOutlet]=\"tpl\" />\n </header>\n }\n\n @if (leftSidenavTpl(); as tpl) {\n <aside rtElem=\"left-sidenav\" qa-dataid=\"container-left-sidenav\">\n <ng-container [ngTemplateOutlet]=\"tpl\" />\n </aside>\n }\n\n @if (toolbarLeftTpl(); as tpl) {\n <div rtElem=\"toolbar\" qa-dataid=\"container-toolbar\" data-slot=\"left\" [rtMod]=\"{ slot: 'left' }\">\n <ng-container [ngTemplateOutlet]=\"tpl\" />\n </div>\n }\n\n @if (toolbarCenterTpl(); as tpl) {\n <div rtElem=\"toolbar\" qa-dataid=\"container-toolbar\" data-slot=\"center\" [rtMod]=\"{ slot: 'center' }\">\n <ng-container [ngTemplateOutlet]=\"tpl\" />\n </div>\n }\n\n @if (toolbarRightTpl(); as tpl) {\n <div rtElem=\"toolbar\" qa-dataid=\"container-toolbar\" data-slot=\"right\" [rtMod]=\"{ slot: 'right' }\">\n <ng-container [ngTemplateOutlet]=\"tpl\" />\n </div>\n }\n\n @if (contentTpl(); as tpl) {\n <main rtElem=\"content\" qa-dataid=\"container-content\">\n <ng-container [ngTemplateOutlet]=\"tpl\" />\n </main>\n }\n\n <rt-toaster position=\"bottom-center\" />\n</ng-container>\n", styles: ["@charset \"UTF-8\";@layer rt-kit.components{:root{--rt-aside-animation-duration: .2s;--rt-aside-backdrop-bg: var(--rt-color-bg-overlay);--rt-aside-backdrop-blur: 5px}.cdk-overlay-backdrop.rt-aside-backdrop{-webkit-backdrop-filter:blur(var(--rt-aside-backdrop-blur));backdrop-filter:blur(var(--rt-aside-backdrop-blur));background:var(--rt-aside-backdrop-bg);transition:opacity var(--rt-aside-animation-duration) ease}:is(.rt-preset-material,[data-preset=material]).cdk-overlay-backdrop.rt-aside-backdrop,[data-preset=material] .cdk-overlay-backdrop.rt-aside-backdrop{--rt-aside-backdrop-bg: var(--rt-color-bg-overlay);--rt-aside-backdrop-blur: 0}.rt-aside-overlay{height:100dvh;transition:transform var(--rt-aside-animation-duration) ease}.rt-aside-overlay.rt-aside-overlay--entering{transition:none}.rt-aside-overlay--position-right.rt-aside-overlay--entering,.rt-aside-overlay--position-right.rt-aside-overlay--leaving{transform:translate(100%)}.rt-aside-overlay--position-left.rt-aside-overlay--entering,.rt-aside-overlay--position-left.rt-aside-overlay--leaving{transform:translate(-100%)}.rt-aside-overlay--position-right.rt-aside-overlay--open,.rt-aside-overlay--position-left.rt-aside-overlay--open{transform:translate(0)}@media(width<=768px){.rt-aside-overlay{overflow:hidden;width:100dvw;max-width:100dvw}}@media(prefers-reduced-motion:reduce){.rt-aside-overlay{transition:none}}}.cdk-overlay-backdrop.rt-aside-backdrop{opacity:0;pointer-events:none}.cdk-overlay-backdrop.rt-aside-backdrop.rt-aside-backdrop--visible{opacity:1;pointer-events:auto}.rt-aside-overlay:not(.rt-aside-overlay--open){pointer-events:none}@layer rt-kit.components{.rt-container{--rt-container-border-width: var(--rt-border-width-thin);display:grid;min-height:100%;flex:1 1 auto;background-color:var(--rt-color-bg-page);color:var(--rt-color-text-primary);grid-template:\"header header\" auto \"left-sidenav toolbar\" auto \"left-sidenav content\" 1fr/auto 1fr}.rt-container__header{position:sticky;z-index:1;top:0;display:block;grid-area:header}.rt-container__header>.rt-page-header{margin:var(--rt-space-5) var(--rt-space-5) 0}.rt-container__left-sidenav{display:block;padding:var(--rt-space-md);border-right:var(--rt-container-border-width) solid var(--rt-color-border-subtle);background-color:var(--rt-color-bg-surface);grid-area:left-sidenav}.rt-container__toolbar{display:flex;align-items:center;padding:var(--rt-space-sm) var(--rt-space-md);border-bottom:var(--rt-container-border-width) solid var(--rt-color-border-subtle);background-color:var(--rt-color-bg-surface);grid-area:toolbar}.rt-container__toolbar--slot--left{justify-content:flex-start}.rt-container__toolbar--slot--center{justify-content:center}.rt-container__toolbar--slot--right{justify-content:flex-end}.rt-container__content{display:flex;overflow:auto;min-height:0;flex-direction:column;grid-area:content}.rt-container--viewport{block-size:100dvh;min-block-size:0}.rt-container--viewport .rt-container__content{overflow:hidden}.rt-container--viewport .rt-container__left-sidenav{overflow:auto}@media(width<=768px){.rt-container--mobile-left-bottom{grid-template:\"header\" auto \"toolbar\" auto \"content\" 1fr \"left-sidenav\" auto/1fr}.rt-container--mobile-left-bottom .rt-container__left-sidenav{padding:0;border-top:var(--rt-container-border-width) solid var(--rt-color-border-subtle);border-right:none}}}\n"] }]
474
- }], ctorParameters: () => [], propDecorators: { headerTpl: [{ type: i0.ContentChild, args: [i0.forwardRef(() => RtContainerHeaderDirective), { ...{
475
- read: TemplateRef,
476
- }, isSignal: true }] }], leftSidenavTpl: [{ type: i0.ContentChild, args: [i0.forwardRef(() => RtContainerLeftSidenavDirective), { ...{
477
- read: TemplateRef,
478
- }, isSignal: true }] }], rightSidenavTpl: [{ type: i0.ContentChild, args: [i0.forwardRef(() => RtContainerRightSidenavDirective), { ...{
479
- read: TemplateRef,
480
- }, isSignal: true }] }], toolbarLeftTpl: [{ type: i0.ContentChild, args: [i0.forwardRef(() => RtContainerToolbarLeftDirective), { ...{
481
- read: TemplateRef,
482
- }, isSignal: true }] }], toolbarCenterTpl: [{ type: i0.ContentChild, args: [i0.forwardRef(() => RtContainerToolbarCenterDirective), { ...{
483
- read: TemplateRef,
484
- }, isSignal: true }] }], toolbarRightTpl: [{ type: i0.ContentChild, args: [i0.forwardRef(() => RtContainerToolbarRightDirective), { ...{
485
- read: TemplateRef,
486
- }, isSignal: true }] }], contentTpl: [{ type: i0.ContentChild, args: [i0.forwardRef(() => RtContainerContentDirective), { ...{
487
- read: TemplateRef,
488
- }, isSignal: true }] }], mobileLeftNav: [{ type: i0.Input, args: [{ isSignal: true, alias: "mobileLeftNav", required: false }] }], height: [{ type: i0.Input, args: [{ isSignal: true, alias: "height", required: false }] }], backdropClick: [{ type: i0.Output, args: ["backdropClick"] }], rightOpened: [{ type: i0.Output, args: ["rightOpened"] }], rightClosed: [{ type: i0.Output, args: ["rightClosed"] }] } });
489
-
490
- /**
491
- * Driver-директива для управления левой sidenav через шаблонную ссылку.
492
- *
493
- * Пишет в component-scoped `RtContainerStateService.leftSidenavOpen` signal —
494
- * шаблон контейнера читает этот signal и применяет docked grid-cell состояние.
495
- *
496
- * @example
497
- * ```html
498
- * <ng-container rtContainerLeftSidenavPanel #left="containerLeftPanel">
499
- * <button (click)="left.toggle(true)">Open</button>
500
- * </ng-container>
501
- * ```
502
- */
503
- class RtContainerLeftSidenavPanelDirective {
504
- #state = inject(RtContainerStateService);
505
- open() {
506
- this.#state.leftSidenavOpen.set(true);
507
- }
508
- close() {
509
- this.#state.leftSidenavOpen.set(false);
510
- }
511
- toggle(isOpen) {
512
- this.#state.leftSidenavOpen.set(isOpen);
513
- }
514
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: RtContainerLeftSidenavPanelDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
515
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.1.6", type: RtContainerLeftSidenavPanelDirective, isStandalone: true, selector: "[rtContainerLeftSidenavPanel]", exportAs: ["containerLeftPanel"], ngImport: i0 }); }
516
- }
517
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: RtContainerLeftSidenavPanelDirective, decorators: [{
518
- type: Directive,
519
- args: [{
520
- selector: '[rtContainerLeftSidenavPanel]',
521
- exportAs: 'containerLeftPanel',
522
- }]
523
- }] });
524
- /**
525
- * Driver-директива правой sidenav: route-component вызывает `open()`/`close()`,
526
- * rt-container выполняет slide-in/slide-out через CSS transform. После завершения
527
- * анимации driver эмитит `(opened)` / `(closed)`; backdrop click и ESC контейнера
528
- * эмитятся через `(cancelled)` — консьюмер сам решает что делать (обычно `close()`).
529
- *
530
- * Sub'ы через `takeUntilDestroyed` снимаются при разрушении route-component'а.
531
- * При уничтожении с открытой панелью гарантирует cleanup overlay'я (см. `ngOnDestroy`),
532
- * иначе при hard-navigate без `panel.close()` overlay останется висеть.
533
- *
534
- * @example
535
- * ```html
536
- * <ng-container
537
- * rtContainerRightSidenavPanel
538
- * #right="rtContainerRightPanel"
539
- * (cancelled)="onClose()"
540
- * (closed)="onClosed()">
541
- * </ng-container>
542
- * ```
543
- */
544
- class RtContainerRightSidenavPanelDirective {
545
- #container;
546
- constructor() {
547
- this.#container = inject(RtContainerComponent);
548
- this.opened = output();
549
- this.closed = output();
550
- this.cancelled = output();
551
- /**
552
- * Re-export rt-container.rightOverlayReady — `true` когда CDK Overlay создан
553
- * и attache'нут. Консьюмер должен ждать этого signal'а в effect'е, перед
554
- * тем как вызывать `panel.open()` (иначе race: rt-container.effect ещё не
555
- * создал overlay → openRight() рано вернётся → --entering остаётся).
556
- */
557
- this.ready = this.#container.rightOverlayReady;
558
- const destroyRef = inject(DestroyRef);
559
- // `output()` возвращает OutputEmitterRef (нет .pipe) — оборачиваем через
560
- // outputToObservable, чтобы пристегнуть takeUntilDestroyed.
561
- outputToObservable(this.#container.backdropClick)
562
- .pipe(takeUntilDestroyed(destroyRef))
563
- .subscribe(() => this.cancelled.emit());
564
- outputToObservable(this.#container.rightOpened)
565
- .pipe(takeUntilDestroyed(destroyRef))
566
- .subscribe(() => this.opened.emit());
567
- outputToObservable(this.#container.rightClosed)
568
- .pipe(takeUntilDestroyed(destroyRef))
569
- .subscribe(() => this.closed.emit());
570
- }
571
- ngOnDestroy() {
572
- // Если route-component разрушается при открытой панели (hard-navigate без
573
- // явного close через panel.close) — гарантируем cleanup, иначе overlay
574
- // останется висеть после смены роута.
575
- if (this.#container.rightOpen()) {
576
- this.#container.closeRight();
577
- }
578
- }
579
- open() {
580
- this.#container.openRight();
581
- }
582
- close() {
583
- this.#container.closeRight();
584
- }
585
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: RtContainerRightSidenavPanelDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
586
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.1.6", type: RtContainerRightSidenavPanelDirective, isStandalone: true, selector: "[rtContainerRightSidenavPanel]", outputs: { opened: "opened", closed: "closed", cancelled: "cancelled" }, exportAs: ["rtContainerRightPanel"], ngImport: i0 }); }
587
- }
588
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: RtContainerRightSidenavPanelDirective, decorators: [{
589
- type: Directive,
590
- args: [{
591
- selector: '[rtContainerRightSidenavPanel]',
592
- exportAs: 'rtContainerRightPanel',
593
- }]
594
- }], ctorParameters: () => [], propDecorators: { opened: [{ type: i0.Output, args: ["opened"] }], closed: [{ type: i0.Output, args: ["closed"] }], cancelled: [{ type: i0.Output, args: ["cancelled"] }] } });
595
- /**
596
- * Driver-директива для основного content-региона `rt-container`.
597
- *
598
- * Объявляет 3 outputs (`scrolled/scrolledUp/scrolledDown`) — публичную поверхность
599
- * для будущих consumer'ов. Real-time wiring (scroll listeners → emit) отложено
600
- * до первого реального потребителя.
601
- *
602
- * @example
603
- * ```html
604
- * <ng-container
605
- * rtContainerContentPanel
606
- * (scrolled)="onScroll()"
607
- * >
608
- * <router-outlet />
609
- * </ng-container>
610
- * ```
611
- */
612
- class RtContainerContentPanelDirective {
613
- constructor() {
614
- this.scrolled = output();
615
- this.scrolledUp = output();
616
- this.scrolledDown = output();
617
- }
618
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: RtContainerContentPanelDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
619
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.1.6", type: RtContainerContentPanelDirective, isStandalone: true, selector: "[rtContainerContentPanel]", outputs: { scrolled: "scrolled", scrolledUp: "scrolledUp", scrolledDown: "scrolledDown" }, ngImport: i0 }); }
620
- }
621
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: RtContainerContentPanelDirective, decorators: [{
622
- type: Directive,
623
- args: [{
624
- selector: '[rtContainerContentPanel]',
625
- }]
626
- }], propDecorators: { scrolled: [{ type: i0.Output, args: ["scrolled"] }], scrolledUp: [{ type: i0.Output, args: ["scrolledUp"] }], scrolledDown: [{ type: i0.Output, args: ["scrolledDown"] }] } });
627
-
628
- /**
629
- * Правки, запущенные панелью.
630
- *
631
- * Подписка объявлена одна на панель, а не заводится на каждый вызов: каждая правка живёт
632
- * независимо от соседней, и отказ одной не уносит поток остальных. Приёмы удачи и отказа
633
- * приезжают вместе с работой — они замыкают доводы своего вызова.
634
- */
635
- class RtRouteAsideMutations {
636
- #mutationSource = new Subject();
637
- constructor(destroyRef) {
638
- this.#mutationSource
639
- .pipe(mergeMap((mutation) => mutation.op$.pipe(map(() => mutation.handleSuccess), catchError((error) => of(() => mutation.handleError(error))))), takeUntilDestroyed(destroyRef))
640
- .subscribe((handleResult) => handleResult());
641
- }
642
- /** Пускает правку в объявленный поток. */
643
- run(mutation) {
644
- this.#mutationSource.next(mutation);
645
- }
646
- }
647
-
648
- /**
649
- * Абсолютные команды приводятся к сегментам от корня: внутри объекта `outlets`
650
- * ведущий слэш отдельным сегментом не разбирается.
651
- *
652
- * Нужно это затем, что уход панели на связанную запись обязан снять её аутлет
653
- * той же навигацией. Абсолютные команды меняют только первичную ветку, поэтому
654
- * панель, открытая в корне приложения, переход переживает: адрес получается с
655
- * аутлетом, под который в корне маршрута нет, и роутер отклоняет навигацию
656
- * молча — адрес остаётся прежним, а приложение застревает на панели, которой на
657
- * экране уже нет.
658
- */
270
+ const BEM_BLOCK = "rt-container";
271
+ var RtContainerComponent = class RtContainerComponent {
272
+ #overlay;
273
+ #host;
274
+ #vcr;
275
+ #scrollStrategies;
276
+ #blockScroll;
277
+ #renderer;
278
+ #window;
279
+ #rightOverlaySource;
280
+ #overlayRef;
281
+ #overlayRefSignal;
282
+ constructor() {
283
+ this.#overlay = inject(Overlay);
284
+ this.#host = inject(ElementRef);
285
+ this.#vcr = inject(ViewContainerRef);
286
+ this.#scrollStrategies = inject(ScrollStrategyOptions);
287
+ this.#blockScroll = this.#scrollStrategies.block();
288
+ this.#renderer = inject(RendererFactory2).createRenderer(null, null);
289
+ this.#window = inject(DOCUMENT).defaultView;
290
+ this.#rightOverlaySource = new Subject();
291
+ this.#overlayRef = null;
292
+ this.#overlayRefSignal = signal(null, ...ngDevMode ? [{ debugName: "#overlayRefSignal" }] : /* istanbul ignore next */ []);
293
+ this.headerTpl = contentChild(RtContainerHeaderDirective, {
294
+ ...ngDevMode ? { debugName: "headerTpl" } : /* istanbul ignore next */ {},
295
+ read: TemplateRef
296
+ });
297
+ this.leftSidenavTpl = contentChild(RtContainerLeftSidenavDirective, {
298
+ ...ngDevMode ? { debugName: "leftSidenavTpl" } : /* istanbul ignore next */ {},
299
+ read: TemplateRef
300
+ });
301
+ this.rightSidenavTpl = contentChild(RtContainerRightSidenavDirective, {
302
+ ...ngDevMode ? { debugName: "rightSidenavTpl" } : /* istanbul ignore next */ {},
303
+ read: TemplateRef
304
+ });
305
+ this.toolbarLeftTpl = contentChild(RtContainerToolbarLeftDirective, {
306
+ ...ngDevMode ? { debugName: "toolbarLeftTpl" } : /* istanbul ignore next */ {},
307
+ read: TemplateRef
308
+ });
309
+ this.toolbarCenterTpl = contentChild(RtContainerToolbarCenterDirective, {
310
+ ...ngDevMode ? { debugName: "toolbarCenterTpl" } : /* istanbul ignore next */ {},
311
+ read: TemplateRef
312
+ });
313
+ this.toolbarRightTpl = contentChild(RtContainerToolbarRightDirective, {
314
+ ...ngDevMode ? { debugName: "toolbarRightTpl" } : /* istanbul ignore next */ {},
315
+ read: TemplateRef
316
+ });
317
+ this.contentTpl = contentChild(RtContainerContentDirective, {
318
+ ...ngDevMode ? { debugName: "contentTpl" } : /* istanbul ignore next */ {},
319
+ read: TemplateRef
320
+ });
321
+ this.mobileLeftNav = input("keep", ...ngDevMode ? [{ debugName: "mobileLeftNav" }] : /* istanbul ignore next */ []);
322
+ this.height = input("auto", ...ngDevMode ? [{ debugName: "height" }] : /* istanbul ignore next */ []);
323
+ this.backdropClick = output();
324
+ this.rightOpened = output();
325
+ this.rightClosed = output();
326
+ this.rightOpen = signal(false, ...ngDevMode ? [{ debugName: "rightOpen" }] : /* istanbul ignore next */ []);
327
+ this.rightOverlayReady = computed(() => this.#overlayRefSignal() !== null, ...ngDevMode ? [{ debugName: "rightOverlayReady" }] : /* istanbul ignore next */ []);
328
+ this.#rightOverlaySource.pipe(switchMap((overlayRef) => merge(overlayRef.backdropClick().pipe(map(() => () => this.backdropClick.emit())), overlayRef.keydownEvents().pipe(map((event) => () => {
329
+ if (event.key !== "Escape" || !this.rightOpen()) return;
330
+ event.preventDefault();
331
+ this.backdropClick.emit();
332
+ }))).pipe(takeUntil(overlayRef.detachments()))), takeUntilDestroyed()).subscribe((handleCloseIntent) => handleCloseIntent());
333
+ effect((onCleanup) => {
334
+ const tpl = this.rightSidenavTpl();
335
+ if (tpl === void 0 || this.#overlayRef !== null) return;
336
+ const overlayRef = this.#createRightOverlay(tpl);
337
+ this.#overlayRef = overlayRef;
338
+ this.#overlayRefSignal.set(overlayRef);
339
+ onCleanup(() => {
340
+ overlayRef.dispose();
341
+ this.#overlayRef = null;
342
+ this.#overlayRefSignal.set(null);
343
+ });
344
+ });
345
+ }
346
+ openRight() {
347
+ const overlayRef = this.#overlayRef;
348
+ if (overlayRef === null) return;
349
+ this.#blockScroll.enable();
350
+ carryThemeScope(overlayRef.overlayElement, this.#host.nativeElement);
351
+ this.#renderer.removeClass(overlayRef.overlayElement, "rt-aside-overlay--entering");
352
+ this.#renderer.removeClass(overlayRef.overlayElement, "rt-aside-overlay--leaving");
353
+ const backdropEl = overlayRef.backdropElement;
354
+ if (backdropEl !== null) {
355
+ this.#renderer.addClass(backdropEl, "rt-aside-backdrop--visible");
356
+ this.#renderer.removeStyle(backdropEl, "opacity");
357
+ this.#renderer.removeStyle(backdropEl, "pointer-events");
358
+ }
359
+ requestAnimationFrame(() => {
360
+ this.#renderer.addClass(overlayRef.overlayElement, "rt-aside-overlay--open");
361
+ this.#listenTransitionEnd(overlayRef, () => this.rightOpened.emit());
362
+ });
363
+ this.rightOpen.set(true);
364
+ }
365
+ closeRight() {
366
+ const overlayRef = this.#overlayRef;
367
+ if (overlayRef === null || !this.rightOpen()) return;
368
+ this.#renderer.removeClass(overlayRef.overlayElement, "rt-aside-overlay--open");
369
+ this.#renderer.addClass(overlayRef.overlayElement, "rt-aside-overlay--leaving");
370
+ const backdropEl = overlayRef.backdropElement;
371
+ if (backdropEl !== null) this.#renderer.removeClass(backdropEl, "rt-aside-backdrop--visible");
372
+ this.#listenTransitionEnd(overlayRef, () => {
373
+ this.#blockScroll.disable();
374
+ this.#hideBackdrop(overlayRef);
375
+ this.rightOpen.set(false);
376
+ this.rightClosed.emit();
377
+ });
378
+ }
379
+ #hideBackdrop(overlayRef) {
380
+ const backdropEl = overlayRef.backdropElement;
381
+ if (backdropEl === null) return;
382
+ this.#renderer.setStyle(backdropEl, "opacity", "0");
383
+ this.#renderer.setStyle(backdropEl, "pointer-events", "none");
384
+ }
385
+ #createRightOverlay(tpl) {
386
+ const overlayConfig = {
387
+ positionStrategy: this.#overlay.position().global().right("0").top("0"),
388
+ scrollStrategy: this.#overlay.scrollStrategies.noop(),
389
+ hasBackdrop: true,
390
+ backdropClass: "rt-aside-backdrop",
391
+ panelClass: [
392
+ "rt-aside-overlay",
393
+ "rt-aside-overlay--position-right",
394
+ "rt-aside-overlay--entering",
395
+ ...materialPresetClassesOf(this.#host.nativeElement)
396
+ ],
397
+ disposeOnNavigation: false
398
+ };
399
+ const overlayRef = this.#overlay.create(overlayConfig);
400
+ const portal = new TemplatePortal(tpl, this.#vcr);
401
+ overlayRef.attach(portal);
402
+ this.#hideBackdrop(overlayRef);
403
+ this.#rightOverlaySource.next(overlayRef);
404
+ return overlayRef;
405
+ }
406
+ #listenTransitionEnd(overlayRef, callback) {
407
+ const element = overlayRef.overlayElement;
408
+ const durationMs = this.#transitionDurationMs(element);
409
+ if (durationMs === 0) {
410
+ callback();
411
+ return;
412
+ }
413
+ let settled = false;
414
+ const handler = (event) => {
415
+ if (event.propertyName !== "transform" || settled) return;
416
+ settled = true;
417
+ element.removeEventListener("transitionend", handler);
418
+ callback();
419
+ };
420
+ element.addEventListener("transitionend", handler);
421
+ setTimeout(() => {
422
+ if (settled) return;
423
+ settled = true;
424
+ element.removeEventListener("transitionend", handler);
425
+ callback();
426
+ }, durationMs + ASIDE_TRANSITION_BUFFER_MS);
427
+ }
428
+ #transitionDurationMs(element) {
429
+ const durationCss = this.#window?.getComputedStyle(element).transitionDuration;
430
+ if (durationCss === void 0 || durationCss === "") return 0;
431
+ return durationCss.split(",").reduce((max, part) => {
432
+ const trimmed = part.trim();
433
+ const seconds = trimmed.endsWith("ms") ? Number.parseFloat(trimmed) / 1e3 : Number.parseFloat(trimmed);
434
+ return Number.isNaN(seconds) ? max : Math.max(max, seconds);
435
+ }, 0) * 1e3;
436
+ }
437
+ static {
438
+ this.ɵfac = i0.ɵɵngDeclareFactory({
439
+ minVersion: "12.0.0",
440
+ version: "22.2.2",
441
+ ngImport: i0,
442
+ type: RtContainerComponent,
443
+ deps: [],
444
+ target: i0.ɵɵFactoryTarget.Component
445
+ });
446
+ }
447
+ static {
448
+ this.ɵcmp = i0.ɵɵngDeclareComponent({
449
+ minVersion: "17.0.0",
450
+ version: "22.2.2",
451
+ type: RtContainerComponent,
452
+ isStandalone: true,
453
+ selector: "rt-container",
454
+ inputs: {
455
+ mobileLeftNav: {
456
+ classPropertyName: "mobileLeftNav",
457
+ publicName: "mobileLeftNav",
458
+ isSignal: true,
459
+ isRequired: false,
460
+ transformFunction: null
461
+ },
462
+ height: {
463
+ classPropertyName: "height",
464
+ publicName: "height",
465
+ isSignal: true,
466
+ isRequired: false,
467
+ transformFunction: null
468
+ }
469
+ },
470
+ outputs: {
471
+ backdropClick: "backdropClick",
472
+ rightOpened: "rightOpened",
473
+ rightClosed: "rightClosed"
474
+ },
475
+ host: {
476
+ properties: {
477
+ "class.rt-container--mobile-left-bottom": "mobileLeftNav() === 'bottom'",
478
+ "class.rt-container--viewport": "height() === 'viewport'"
479
+ },
480
+ classAttribute: "rt-container"
481
+ },
482
+ providers: [RtContainerStateService],
483
+ queries: [
484
+ {
485
+ propertyName: "headerTpl",
486
+ first: true,
487
+ predicate: RtContainerHeaderDirective,
488
+ descendants: true,
489
+ read: TemplateRef,
490
+ isSignal: true
491
+ },
492
+ {
493
+ propertyName: "leftSidenavTpl",
494
+ first: true,
495
+ predicate: RtContainerLeftSidenavDirective,
496
+ descendants: true,
497
+ read: TemplateRef,
498
+ isSignal: true
499
+ },
500
+ {
501
+ propertyName: "rightSidenavTpl",
502
+ first: true,
503
+ predicate: RtContainerRightSidenavDirective,
504
+ descendants: true,
505
+ read: TemplateRef,
506
+ isSignal: true
507
+ },
508
+ {
509
+ propertyName: "toolbarLeftTpl",
510
+ first: true,
511
+ predicate: RtContainerToolbarLeftDirective,
512
+ descendants: true,
513
+ read: TemplateRef,
514
+ isSignal: true
515
+ },
516
+ {
517
+ propertyName: "toolbarCenterTpl",
518
+ first: true,
519
+ predicate: RtContainerToolbarCenterDirective,
520
+ descendants: true,
521
+ read: TemplateRef,
522
+ isSignal: true
523
+ },
524
+ {
525
+ propertyName: "toolbarRightTpl",
526
+ first: true,
527
+ predicate: RtContainerToolbarRightDirective,
528
+ descendants: true,
529
+ read: TemplateRef,
530
+ isSignal: true
531
+ },
532
+ {
533
+ propertyName: "contentTpl",
534
+ first: true,
535
+ predicate: RtContainerContentDirective,
536
+ descendants: true,
537
+ read: TemplateRef,
538
+ isSignal: true
539
+ }
540
+ ],
541
+ ngImport: i0,
542
+ template: "<ng-container rtBlock=\"rt-container\">\n @if (headerTpl(); as tpl) {\n <header rtElem=\"header\" qa-dataid=\"container-header\">\n <ng-container [ngTemplateOutlet]=\"tpl\" />\n </header>\n }\n\n @if (leftSidenavTpl(); as tpl) {\n <aside rtElem=\"left-sidenav\" qa-dataid=\"container-left-sidenav\">\n <ng-container [ngTemplateOutlet]=\"tpl\" />\n </aside>\n }\n\n @if (toolbarLeftTpl(); as tpl) {\n <div rtElem=\"toolbar\" qa-dataid=\"container-toolbar\" data-slot=\"left\" [rtMod]=\"{ slot: 'left' }\">\n <ng-container [ngTemplateOutlet]=\"tpl\" />\n </div>\n }\n\n @if (toolbarCenterTpl(); as tpl) {\n <div rtElem=\"toolbar\" qa-dataid=\"container-toolbar\" data-slot=\"center\" [rtMod]=\"{ slot: 'center' }\">\n <ng-container [ngTemplateOutlet]=\"tpl\" />\n </div>\n }\n\n @if (toolbarRightTpl(); as tpl) {\n <div rtElem=\"toolbar\" qa-dataid=\"container-toolbar\" data-slot=\"right\" [rtMod]=\"{ slot: 'right' }\">\n <ng-container [ngTemplateOutlet]=\"tpl\" />\n </div>\n }\n\n @if (contentTpl(); as tpl) {\n <main rtElem=\"content\" qa-dataid=\"container-content\">\n <ng-container [ngTemplateOutlet]=\"tpl\" />\n </main>\n }\n\n <rt-toaster position=\"bottom-center\" />\n</ng-container>\n",
543
+ styles: ["@charset \"UTF-8\";@layer rt-kit.components{:root{--rt-aside-animation-duration: .2s;--rt-aside-backdrop-bg: var(--rt-color-bg-overlay);--rt-aside-backdrop-blur: 5px}.cdk-overlay-backdrop.rt-aside-backdrop{-webkit-backdrop-filter:blur(var(--rt-aside-backdrop-blur));backdrop-filter:blur(var(--rt-aside-backdrop-blur));background:var(--rt-aside-backdrop-bg);transition:opacity var(--rt-aside-animation-duration) ease}:is(.rt-preset-material,[data-preset=material]).cdk-overlay-backdrop.rt-aside-backdrop,[data-preset=material] .cdk-overlay-backdrop.rt-aside-backdrop{--rt-aside-backdrop-bg: var(--rt-color-bg-overlay);--rt-aside-backdrop-blur: 0}.rt-aside-overlay{height:100dvh;transition:transform var(--rt-aside-animation-duration) ease}.rt-aside-overlay.rt-aside-overlay--entering{transition:none}.rt-aside-overlay--position-right.rt-aside-overlay--entering,.rt-aside-overlay--position-right.rt-aside-overlay--leaving{transform:translate(100%)}.rt-aside-overlay--position-left.rt-aside-overlay--entering,.rt-aside-overlay--position-left.rt-aside-overlay--leaving{transform:translate(-100%)}.rt-aside-overlay--position-right.rt-aside-overlay--open,.rt-aside-overlay--position-left.rt-aside-overlay--open{transform:translate(0)}@media(width<=768px){.rt-aside-overlay{overflow:hidden;width:100dvw;max-width:100dvw}}@media(prefers-reduced-motion:reduce){.rt-aside-overlay{transition:none}}}.cdk-overlay-backdrop.rt-aside-backdrop{opacity:0;pointer-events:none}.cdk-overlay-backdrop.rt-aside-backdrop.rt-aside-backdrop--visible{opacity:1;pointer-events:auto}.rt-aside-overlay:not(.rt-aside-overlay--open){pointer-events:none}@layer rt-kit.components{.rt-container{--rt-container-border-width: var(--rt-border-width-thin);display:grid;min-height:100%;flex:1 1 auto;background-color:var(--rt-color-bg-page);color:var(--rt-color-text-primary);grid-template:\"header header\" auto \"left-sidenav toolbar\" auto \"left-sidenav content\" 1fr/auto 1fr}.rt-container__header{position:sticky;z-index:1;top:0;display:block;grid-area:header}.rt-container__header>.rt-page-header{margin:var(--rt-space-5) var(--rt-space-5) 0}.rt-container__left-sidenav{display:block;padding:var(--rt-space-md);border-right:var(--rt-container-border-width) solid var(--rt-color-border-subtle);background-color:var(--rt-color-bg-surface);grid-area:left-sidenav}.rt-container__toolbar{display:flex;align-items:center;padding:var(--rt-space-sm) var(--rt-space-md);border-bottom:var(--rt-container-border-width) solid var(--rt-color-border-subtle);background-color:var(--rt-color-bg-surface);grid-area:toolbar}.rt-container__toolbar--slot--left{justify-content:flex-start}.rt-container__toolbar--slot--center{justify-content:center}.rt-container__toolbar--slot--right{justify-content:flex-end}.rt-container__content{display:flex;overflow:auto;min-height:0;flex-direction:column;grid-area:content}.rt-container--viewport{block-size:100dvh;min-block-size:0}.rt-container--viewport .rt-container__content{overflow:hidden}.rt-container--viewport .rt-container__left-sidenav{overflow:auto}@media(width<=768px){.rt-container--mobile-left-bottom{grid-template:\"header\" auto \"toolbar\" auto \"content\" 1fr \"left-sidenav\" auto/1fr}.rt-container--mobile-left-bottom .rt-container__left-sidenav{padding:0;border-top:var(--rt-container-border-width) solid var(--rt-color-border-subtle);border-right:none}}}\n"],
544
+ dependencies: [
545
+ {
546
+ kind: "directive",
547
+ type: NgTemplateOutlet,
548
+ selector: "[ngTemplateOutlet]",
549
+ inputs: [
550
+ "ngTemplateOutletContext",
551
+ "ngTemplateOutlet",
552
+ "ngTemplateOutletInjector"
553
+ ]
554
+ },
555
+ {
556
+ kind: "component",
557
+ type: RtToasterComponent,
558
+ selector: "rt-toaster",
559
+ inputs: [
560
+ "position",
561
+ "duration",
562
+ "visibleToasts",
563
+ "mode",
564
+ "expand"
565
+ ]
566
+ },
567
+ {
568
+ kind: "directive",
569
+ type: BlockDirective,
570
+ selector: "[rtBlock]",
571
+ inputs: ["rtMod"]
572
+ },
573
+ {
574
+ kind: "directive",
575
+ type: ElemDirective,
576
+ selector: "[rtElem]",
577
+ inputs: ["rtMod"]
578
+ },
579
+ {
580
+ kind: "directive",
581
+ type: ModDirective,
582
+ selector: "[rtMod]"
583
+ }
584
+ ],
585
+ changeDetection: i0.ChangeDetectionStrategy.OnPush,
586
+ encapsulation: i0.ViewEncapsulation.None
587
+ });
588
+ }
589
+ };
590
+ i0.ɵɵngDeclareClassMetadata({
591
+ minVersion: "12.0.0",
592
+ version: "22.2.2",
593
+ ngImport: i0,
594
+ type: RtContainerComponent,
595
+ decorators: [{
596
+ type: Component,
597
+ args: [{
598
+ selector: "rt-container",
599
+ changeDetection: ChangeDetectionStrategy.OnPush,
600
+ encapsulation: ViewEncapsulation.None,
601
+ imports: [
602
+ NgTemplateOutlet,
603
+ RtToasterComponent,
604
+ BlockDirective,
605
+ ElemDirective,
606
+ ModDirective
607
+ ],
608
+ providers: [RtContainerStateService],
609
+ host: {
610
+ class: BEM_BLOCK,
611
+ "[class.rt-container--mobile-left-bottom]": "mobileLeftNav() === 'bottom'",
612
+ "[class.rt-container--viewport]": "height() === 'viewport'"
613
+ },
614
+ template: "<ng-container rtBlock=\"rt-container\">\n @if (headerTpl(); as tpl) {\n <header rtElem=\"header\" qa-dataid=\"container-header\">\n <ng-container [ngTemplateOutlet]=\"tpl\" />\n </header>\n }\n\n @if (leftSidenavTpl(); as tpl) {\n <aside rtElem=\"left-sidenav\" qa-dataid=\"container-left-sidenav\">\n <ng-container [ngTemplateOutlet]=\"tpl\" />\n </aside>\n }\n\n @if (toolbarLeftTpl(); as tpl) {\n <div rtElem=\"toolbar\" qa-dataid=\"container-toolbar\" data-slot=\"left\" [rtMod]=\"{ slot: 'left' }\">\n <ng-container [ngTemplateOutlet]=\"tpl\" />\n </div>\n }\n\n @if (toolbarCenterTpl(); as tpl) {\n <div rtElem=\"toolbar\" qa-dataid=\"container-toolbar\" data-slot=\"center\" [rtMod]=\"{ slot: 'center' }\">\n <ng-container [ngTemplateOutlet]=\"tpl\" />\n </div>\n }\n\n @if (toolbarRightTpl(); as tpl) {\n <div rtElem=\"toolbar\" qa-dataid=\"container-toolbar\" data-slot=\"right\" [rtMod]=\"{ slot: 'right' }\">\n <ng-container [ngTemplateOutlet]=\"tpl\" />\n </div>\n }\n\n @if (contentTpl(); as tpl) {\n <main rtElem=\"content\" qa-dataid=\"container-content\">\n <ng-container [ngTemplateOutlet]=\"tpl\" />\n </main>\n }\n\n <rt-toaster position=\"bottom-center\" />\n</ng-container>\n",
615
+ styles: ["@charset \"UTF-8\";@layer rt-kit.components{:root{--rt-aside-animation-duration: .2s;--rt-aside-backdrop-bg: var(--rt-color-bg-overlay);--rt-aside-backdrop-blur: 5px}.cdk-overlay-backdrop.rt-aside-backdrop{-webkit-backdrop-filter:blur(var(--rt-aside-backdrop-blur));backdrop-filter:blur(var(--rt-aside-backdrop-blur));background:var(--rt-aside-backdrop-bg);transition:opacity var(--rt-aside-animation-duration) ease}:is(.rt-preset-material,[data-preset=material]).cdk-overlay-backdrop.rt-aside-backdrop,[data-preset=material] .cdk-overlay-backdrop.rt-aside-backdrop{--rt-aside-backdrop-bg: var(--rt-color-bg-overlay);--rt-aside-backdrop-blur: 0}.rt-aside-overlay{height:100dvh;transition:transform var(--rt-aside-animation-duration) ease}.rt-aside-overlay.rt-aside-overlay--entering{transition:none}.rt-aside-overlay--position-right.rt-aside-overlay--entering,.rt-aside-overlay--position-right.rt-aside-overlay--leaving{transform:translate(100%)}.rt-aside-overlay--position-left.rt-aside-overlay--entering,.rt-aside-overlay--position-left.rt-aside-overlay--leaving{transform:translate(-100%)}.rt-aside-overlay--position-right.rt-aside-overlay--open,.rt-aside-overlay--position-left.rt-aside-overlay--open{transform:translate(0)}@media(width<=768px){.rt-aside-overlay{overflow:hidden;width:100dvw;max-width:100dvw}}@media(prefers-reduced-motion:reduce){.rt-aside-overlay{transition:none}}}.cdk-overlay-backdrop.rt-aside-backdrop{opacity:0;pointer-events:none}.cdk-overlay-backdrop.rt-aside-backdrop.rt-aside-backdrop--visible{opacity:1;pointer-events:auto}.rt-aside-overlay:not(.rt-aside-overlay--open){pointer-events:none}@layer rt-kit.components{.rt-container{--rt-container-border-width: var(--rt-border-width-thin);display:grid;min-height:100%;flex:1 1 auto;background-color:var(--rt-color-bg-page);color:var(--rt-color-text-primary);grid-template:\"header header\" auto \"left-sidenav toolbar\" auto \"left-sidenav content\" 1fr/auto 1fr}.rt-container__header{position:sticky;z-index:1;top:0;display:block;grid-area:header}.rt-container__header>.rt-page-header{margin:var(--rt-space-5) var(--rt-space-5) 0}.rt-container__left-sidenav{display:block;padding:var(--rt-space-md);border-right:var(--rt-container-border-width) solid var(--rt-color-border-subtle);background-color:var(--rt-color-bg-surface);grid-area:left-sidenav}.rt-container__toolbar{display:flex;align-items:center;padding:var(--rt-space-sm) var(--rt-space-md);border-bottom:var(--rt-container-border-width) solid var(--rt-color-border-subtle);background-color:var(--rt-color-bg-surface);grid-area:toolbar}.rt-container__toolbar--slot--left{justify-content:flex-start}.rt-container__toolbar--slot--center{justify-content:center}.rt-container__toolbar--slot--right{justify-content:flex-end}.rt-container__content{display:flex;overflow:auto;min-height:0;flex-direction:column;grid-area:content}.rt-container--viewport{block-size:100dvh;min-block-size:0}.rt-container--viewport .rt-container__content{overflow:hidden}.rt-container--viewport .rt-container__left-sidenav{overflow:auto}@media(width<=768px){.rt-container--mobile-left-bottom{grid-template:\"header\" auto \"toolbar\" auto \"content\" 1fr \"left-sidenav\" auto/1fr}.rt-container--mobile-left-bottom .rt-container__left-sidenav{padding:0;border-top:var(--rt-container-border-width) solid var(--rt-color-border-subtle);border-right:none}}}\n"]
616
+ }]
617
+ }],
618
+ ctorParameters: () => [],
619
+ propDecorators: {
620
+ headerTpl: [{
621
+ type: i0.ContentChild,
622
+ args: [i0.forwardRef(() => RtContainerHeaderDirective), {
623
+ read: TemplateRef,
624
+ isSignal: true
625
+ }]
626
+ }],
627
+ leftSidenavTpl: [{
628
+ type: i0.ContentChild,
629
+ args: [i0.forwardRef(() => RtContainerLeftSidenavDirective), {
630
+ read: TemplateRef,
631
+ isSignal: true
632
+ }]
633
+ }],
634
+ rightSidenavTpl: [{
635
+ type: i0.ContentChild,
636
+ args: [i0.forwardRef(() => RtContainerRightSidenavDirective), {
637
+ read: TemplateRef,
638
+ isSignal: true
639
+ }]
640
+ }],
641
+ toolbarLeftTpl: [{
642
+ type: i0.ContentChild,
643
+ args: [i0.forwardRef(() => RtContainerToolbarLeftDirective), {
644
+ read: TemplateRef,
645
+ isSignal: true
646
+ }]
647
+ }],
648
+ toolbarCenterTpl: [{
649
+ type: i0.ContentChild,
650
+ args: [i0.forwardRef(() => RtContainerToolbarCenterDirective), {
651
+ read: TemplateRef,
652
+ isSignal: true
653
+ }]
654
+ }],
655
+ toolbarRightTpl: [{
656
+ type: i0.ContentChild,
657
+ args: [i0.forwardRef(() => RtContainerToolbarRightDirective), {
658
+ read: TemplateRef,
659
+ isSignal: true
660
+ }]
661
+ }],
662
+ contentTpl: [{
663
+ type: i0.ContentChild,
664
+ args: [i0.forwardRef(() => RtContainerContentDirective), {
665
+ read: TemplateRef,
666
+ isSignal: true
667
+ }]
668
+ }],
669
+ mobileLeftNav: [{
670
+ type: i0.Input,
671
+ args: [{
672
+ isSignal: true,
673
+ alias: "mobileLeftNav",
674
+ required: false
675
+ }]
676
+ }],
677
+ height: [{
678
+ type: i0.Input,
679
+ args: [{
680
+ isSignal: true,
681
+ alias: "height",
682
+ required: false
683
+ }]
684
+ }],
685
+ backdropClick: [{
686
+ type: i0.Output,
687
+ args: ["backdropClick"]
688
+ }],
689
+ rightOpened: [{
690
+ type: i0.Output,
691
+ args: ["rightOpened"]
692
+ }],
693
+ rightClosed: [{
694
+ type: i0.Output,
695
+ args: ["rightClosed"]
696
+ }]
697
+ }
698
+ });
699
+ var RtContainerLeftSidenavPanelDirective = class RtContainerLeftSidenavPanelDirective {
700
+ #state = inject(RtContainerStateService);
701
+ open() {
702
+ this.#state.leftSidenavOpen.set(true);
703
+ }
704
+ close() {
705
+ this.#state.leftSidenavOpen.set(false);
706
+ }
707
+ toggle(isOpen) {
708
+ this.#state.leftSidenavOpen.set(isOpen);
709
+ }
710
+ static {
711
+ this.ɵfac = i0.ɵɵngDeclareFactory({
712
+ minVersion: "12.0.0",
713
+ version: "22.2.2",
714
+ ngImport: i0,
715
+ type: RtContainerLeftSidenavPanelDirective,
716
+ deps: [],
717
+ target: i0.ɵɵFactoryTarget.Directive
718
+ });
719
+ }
720
+ static {
721
+ this.ɵdir = i0.ɵɵngDeclareDirective({
722
+ minVersion: "14.0.0",
723
+ version: "22.2.2",
724
+ type: RtContainerLeftSidenavPanelDirective,
725
+ isStandalone: true,
726
+ selector: "[rtContainerLeftSidenavPanel]",
727
+ exportAs: ["containerLeftPanel"],
728
+ ngImport: i0
729
+ });
730
+ }
731
+ };
732
+ i0.ɵɵngDeclareClassMetadata({
733
+ minVersion: "12.0.0",
734
+ version: "22.2.2",
735
+ ngImport: i0,
736
+ type: RtContainerLeftSidenavPanelDirective,
737
+ decorators: [{
738
+ type: Directive,
739
+ args: [{
740
+ selector: "[rtContainerLeftSidenavPanel]",
741
+ exportAs: "containerLeftPanel"
742
+ }]
743
+ }]
744
+ });
745
+ var RtContainerRightSidenavPanelDirective = class RtContainerRightSidenavPanelDirective {
746
+ #container;
747
+ constructor() {
748
+ this.#container = inject(RtContainerComponent);
749
+ this.opened = output();
750
+ this.closed = output();
751
+ this.cancelled = output();
752
+ this.ready = this.#container.rightOverlayReady;
753
+ const destroyRef = inject(DestroyRef);
754
+ outputToObservable(this.#container.backdropClick).pipe(takeUntilDestroyed(destroyRef)).subscribe(() => this.cancelled.emit());
755
+ outputToObservable(this.#container.rightOpened).pipe(takeUntilDestroyed(destroyRef)).subscribe(() => this.opened.emit());
756
+ outputToObservable(this.#container.rightClosed).pipe(takeUntilDestroyed(destroyRef)).subscribe(() => this.closed.emit());
757
+ }
758
+ ngOnDestroy() {
759
+ if (this.#container.rightOpen()) this.#container.closeRight();
760
+ }
761
+ open() {
762
+ this.#container.openRight();
763
+ }
764
+ close() {
765
+ this.#container.closeRight();
766
+ }
767
+ static {
768
+ this.ɵfac = i0.ɵɵngDeclareFactory({
769
+ minVersion: "12.0.0",
770
+ version: "22.2.2",
771
+ ngImport: i0,
772
+ type: RtContainerRightSidenavPanelDirective,
773
+ deps: [],
774
+ target: i0.ɵɵFactoryTarget.Directive
775
+ });
776
+ }
777
+ static {
778
+ this.ɵdir = i0.ɵɵngDeclareDirective({
779
+ minVersion: "14.0.0",
780
+ version: "22.2.2",
781
+ type: RtContainerRightSidenavPanelDirective,
782
+ isStandalone: true,
783
+ selector: "[rtContainerRightSidenavPanel]",
784
+ outputs: {
785
+ opened: "opened",
786
+ closed: "closed",
787
+ cancelled: "cancelled"
788
+ },
789
+ exportAs: ["rtContainerRightPanel"],
790
+ ngImport: i0
791
+ });
792
+ }
793
+ };
794
+ i0.ɵɵngDeclareClassMetadata({
795
+ minVersion: "12.0.0",
796
+ version: "22.2.2",
797
+ ngImport: i0,
798
+ type: RtContainerRightSidenavPanelDirective,
799
+ decorators: [{
800
+ type: Directive,
801
+ args: [{
802
+ selector: "[rtContainerRightSidenavPanel]",
803
+ exportAs: "rtContainerRightPanel"
804
+ }]
805
+ }],
806
+ ctorParameters: () => [],
807
+ propDecorators: {
808
+ opened: [{
809
+ type: i0.Output,
810
+ args: ["opened"]
811
+ }],
812
+ closed: [{
813
+ type: i0.Output,
814
+ args: ["closed"]
815
+ }],
816
+ cancelled: [{
817
+ type: i0.Output,
818
+ args: ["cancelled"]
819
+ }]
820
+ }
821
+ });
822
+ var RtContainerContentPanelDirective = class RtContainerContentPanelDirective {
823
+ constructor() {
824
+ this.scrolled = output();
825
+ this.scrolledUp = output();
826
+ this.scrolledDown = output();
827
+ }
828
+ static {
829
+ this.ɵfac = i0.ɵɵngDeclareFactory({
830
+ minVersion: "12.0.0",
831
+ version: "22.2.2",
832
+ ngImport: i0,
833
+ type: RtContainerContentPanelDirective,
834
+ deps: [],
835
+ target: i0.ɵɵFactoryTarget.Directive
836
+ });
837
+ }
838
+ static {
839
+ this.ɵdir = i0.ɵɵngDeclareDirective({
840
+ minVersion: "14.0.0",
841
+ version: "22.2.2",
842
+ type: RtContainerContentPanelDirective,
843
+ isStandalone: true,
844
+ selector: "[rtContainerContentPanel]",
845
+ outputs: {
846
+ scrolled: "scrolled",
847
+ scrolledUp: "scrolledUp",
848
+ scrolledDown: "scrolledDown"
849
+ },
850
+ ngImport: i0
851
+ });
852
+ }
853
+ };
854
+ i0.ɵɵngDeclareClassMetadata({
855
+ minVersion: "12.0.0",
856
+ version: "22.2.2",
857
+ ngImport: i0,
858
+ type: RtContainerContentPanelDirective,
859
+ decorators: [{
860
+ type: Directive,
861
+ args: [{ selector: "[rtContainerContentPanel]" }]
862
+ }],
863
+ propDecorators: {
864
+ scrolled: [{
865
+ type: i0.Output,
866
+ args: ["scrolled"]
867
+ }],
868
+ scrolledUp: [{
869
+ type: i0.Output,
870
+ args: ["scrolledUp"]
871
+ }],
872
+ scrolledDown: [{
873
+ type: i0.Output,
874
+ args: ["scrolledDown"]
875
+ }]
876
+ }
877
+ });
878
+ var RtRouteAsideMutations = class {
879
+ #mutationSource = new Subject();
880
+ constructor(destroyRef) {
881
+ this.#mutationSource.pipe(mergeMap((mutation) => mutation.op$.pipe(map(() => mutation.handleSuccess), catchError((error) => of(() => mutation.handleError(error))))), takeUntilDestroyed(destroyRef)).subscribe((handleResult) => handleResult());
882
+ }
883
+ run(mutation) {
884
+ this.#mutationSource.next(mutation);
885
+ }
886
+ };
659
887
  function rootSegmentsOf(commands) {
660
- const [head, ...rest] = commands;
661
- if (typeof head !== 'string' || !head.startsWith('/')) {
662
- return [...commands];
663
- }
664
- return [...head.split('/').filter(Boolean), ...rest];
665
- }
666
-
667
- /**
668
- * Уходы панели по маршруту и разрешение на них.
669
- *
670
- * Разрешение выдаётся вплотную к вызову маршрутизатора и снимается итогом навигации:
671
- * между закрытием панели и уходом наложение доигрывает своё, и разрешение, выданное
672
- * раньше, досталось бы чужому уходу — тронутая форма уехала бы без вопроса. Читается оно
673
- * тоже один раз: иначе первое же закрытие после записи сняло бы вопрос о правках со всех
674
- * следующих уходов.
675
- */
676
- class RtRouteAsideNavigation {
677
- #router;
678
- #leaveAllowed = false;
679
- constructor(router) {
680
- this.#router = router;
681
- }
682
- /** Разрешение на этот уход. Читается один раз и снимается чтением. */
683
- consumeLeaveAllowance() {
684
- const allowed = this.#leaveAllowed;
685
- this.#leaveAllowed = false;
686
- return allowed;
687
- }
688
- /** Уход, начатый самой панелью: разрешение живёт ровно эту навигацию. */
689
- allowed(navigate) {
690
- this.#leaveAllowed = true;
691
- void navigate()
692
- .catch(() => false)
693
- .then(() => {
694
- this.#leaveAllowed = false;
695
- });
696
- }
697
- /**
698
- * Адрес, на который уходит панель. Свой аутлет она снимает тем же деревом: абсолютные
699
- * команды меняют только первичную ветку, и панель, открытая в корне приложения, переход
700
- * пережила бы — маршрута под неё в корне нет, а такую навигацию маршрутизатор отклоняет
701
- * молча, оставляя приложение на панели, которой на экране уже нет.
702
- */
703
- relatedTree(outlets, commands, queryParams = null) {
704
- return this.#router.createUrlTree([{ outlets: { ...outlets, primary: rootSegmentsOf(commands) } }], { queryParams });
705
- }
888
+ const [head, ...rest] = commands;
889
+ if (typeof head !== "string" || !head.startsWith("/")) return [...commands];
890
+ return [...head.split("/").filter(Boolean), ...rest];
706
891
  }
707
-
708
- /**
709
- * Вопрос о несохранённых правках, заданный уходу по маршруту.
710
- *
711
- * Окно открывается одно на все уходы, пришедшие пока оно висит: второе поставило бы поверх
712
- * первого наложение, убрать которое было бы некому. Ответ раздаётся всем спросившим, а после
713
- * закрытия окна следующий уход спрашивает заново.
714
- */
715
- class RtRouteAsideUnsavedPrompt {
716
- #dialog;
717
- #injector;
718
- #deps;
719
- /** Вопрос, который сейчас висит. `null` — окна нет, и следующий уход откроет своё. */
720
- #pendingAsk$ = null;
721
- constructor(dialog, injector, deps) {
722
- this.#dialog = dialog;
723
- this.#injector = injector;
724
- this.#deps = deps;
725
- }
726
- /** Отпускать ли уход. Пока окно висит, все спросившие получают один и тот же ответ. */
727
- ask() {
728
- const pending = this.#pendingAsk$;
729
- if (pending !== null) {
730
- return pending;
731
- }
732
- const ask$ = this.#dialog
733
- .open(RtAsideUnsavedDialogComponent)
734
- .afterClosed()
735
- .pipe(switchMap((outcome) => this.#deactivateAfter(outcome)), finalize(() => {
736
- this.#pendingAsk$ = null;
737
- }), shareReplay({ bufferSize: 1, refCount: false }));
738
- this.#pendingAsk$ = ask$;
739
- return ask$;
740
- }
741
- /**
742
- * Что делать с уходом после ответа человека. «Закрыть с сохранением» ждёт конца записи:
743
- * панель уступает место только удачной — иначе правки пропали бы вместе с отказом, о
744
- * котором человек ещё не знает.
745
- */
746
- #deactivateAfter(outcome) {
747
- if (outcome === ERtAsideUnsavedOutcome.Discard) {
748
- return of(true);
749
- }
750
- if (outcome !== ERtAsideUnsavedOutcome.Save) {
751
- return of(false);
752
- }
753
- this.#deps.save();
754
- // Запись могла и не начаться — например, черновик не годится
755
- if (!this.#deps.submitting()) {
756
- return of(false);
757
- }
758
- return toObservable(this.#deps.submitting, { injector: this.#injector }).pipe(filter((submitting) => !submitting), take(1), map(() => this.#deps.submitError() === null));
759
- }
760
- }
761
-
762
- /**
763
- * Признак нетронутой формы.
764
- *
765
- * Контрол принимается и сигналом: форма панели собрана директивой формы и до отрисовки
766
- * шаблона её ещё нет, поэтому запрос вида отдаёт её только сигналом. Нынешнее состояние
767
- * подставляется первым значением — события прошлого подписка не получит, и без него кнопка
768
- * записи осталась бы недоступной у формы, испачканной до подписки.
769
- *
770
- * Зовётся в контексте внедрения: `toObservable` и `toSignal` требуют его сами.
771
- */
892
+ var RtRouteAsideNavigation = class {
893
+ #router;
894
+ #leaveAllowed = false;
895
+ constructor(router) {
896
+ this.#router = router;
897
+ }
898
+ consumeLeaveAllowance() {
899
+ const allowed = this.#leaveAllowed;
900
+ this.#leaveAllowed = false;
901
+ return allowed;
902
+ }
903
+ allowed(navigate) {
904
+ this.#leaveAllowed = true;
905
+ navigate().catch(() => false).then(() => {
906
+ this.#leaveAllowed = false;
907
+ });
908
+ }
909
+ relatedTree(outlets, commands, queryParams = null) {
910
+ return this.#router.createUrlTree([{ outlets: {
911
+ ...outlets,
912
+ primary: rootSegmentsOf(commands)
913
+ } }], { queryParams });
914
+ }
915
+ };
916
+ var RtRouteAsideUnsavedPrompt = class {
917
+ #dialog;
918
+ #injector;
919
+ #deps;
920
+ #pendingAsk$ = null;
921
+ constructor(dialog, injector, deps) {
922
+ this.#dialog = dialog;
923
+ this.#injector = injector;
924
+ this.#deps = deps;
925
+ }
926
+ ask() {
927
+ const pending = this.#pendingAsk$;
928
+ if (pending !== null) return pending;
929
+ const ask$ = this.#dialog.open(RtAsideUnsavedDialogComponent).afterClosed().pipe(switchMap((outcome) => this.#deactivateAfter(outcome)), finalize(() => {
930
+ this.#pendingAsk$ = null;
931
+ }), shareReplay({
932
+ bufferSize: 1,
933
+ refCount: false
934
+ }));
935
+ this.#pendingAsk$ = ask$;
936
+ return ask$;
937
+ }
938
+ #deactivateAfter(outcome) {
939
+ if (outcome === ERtAsideUnsavedOutcome.Discard) return of(true);
940
+ if (outcome !== ERtAsideUnsavedOutcome.Save) return of(false);
941
+ this.#deps.save();
942
+ if (!this.#deps.submitting()) return of(false);
943
+ return toObservable(this.#deps.submitting, { injector: this.#injector }).pipe(filter((submitting) => !submitting), take(1), map(() => this.#deps.submitError() === null));
944
+ }
945
+ };
772
946
  function pristineOf(control) {
773
- const control$ = isSignal(control) ? toObservable(control) : of(control);
774
- return toSignal(control$.pipe(switchMap((current) => {
775
- if (current === undefined) {
776
- return of(true);
777
- }
778
- return current.events.pipe(filter((event) => event instanceof PristineChangeEvent), map((event) => event.pristine), startWith(current.pristine));
779
- })), { initialValue: true });
780
- }
781
-
782
- /**
783
- * Учёт панелей, стоящих на экране: из него роутерный гард узнаёт, кого спрашивать
784
- * о несохранённых правках.
785
- *
786
- * Спрашивать компонент, который роутер подставляет в гард, нельзя: когда
787
- * ro-маршрут объявлен под уровнем без своего компонента, Angular отдаёт детям
788
- * контекст родителя, и в гард приходит компонент первичного аутлета — экран
789
- * раздела, а не панель.
790
- *
791
- * Ключ записи — объявление маршрута, а не порядок постановки. Гард стоит на
792
- * каждом ro-маршруте, и одна навигация зовёт его за каждый уходящий маршрут
793
- * отдельно: учёт стеком дал бы ответ не той панели и два вопроса о правках
794
- * подряд. Объявление маршрута — та же ссылка на объект и у панели, и у снимка,
795
- * который роутер отдаёт гарду, поэтому два каркаса на экране не путаются даже
796
- * при одинаково названных аутлетах: маршруты у них разные.
797
- *
798
- * Служба корневая: гард живёт в инжекторе маршрута и до службы, поставленной на
799
- * уровне компонента, не дотянулся бы вовсе. Одного учёта на приложение хватает —
800
- * записи различает маршрут. Переменной уровня модуля учёт быть не может: та
801
- * пережила бы запрос при отдаче страницы сервером и оказалась бы общей на два
802
- * приложения, поднятых на одной странице.
803
- */
804
- class RtRouteAsideRegistry {
805
- #panels = new Map();
806
- /**
807
- * Панель встала на экран. Повторная постановка под тем же маршрутом заменяет
808
- * запись: аутлет держит одну панель, и отвечать должна нынешняя.
809
- */
810
- register(route, panel) {
811
- const key = route.routeConfig;
812
- if (key === null) {
813
- return;
814
- }
815
- this.#panels.set(key, panel);
816
- }
817
- /**
818
- * Панель ушла с экрана. Запись снимается только своя: пока уходящая панель
819
- * доигрывает уход, её место мог занять сосед, и снятие вслепую стёрло бы
820
- * запись того, кто на экране остался.
821
- */
822
- unregister(route, panel) {
823
- const key = route.routeConfig;
824
- if (key === null || this.#panels.get(key) !== panel) {
825
- return;
826
- }
827
- this.#panels.delete(key);
828
- }
829
- /** Снятие панели, чей ответ о правках отказал: спрашивать её больше нечем. */
830
- forget(panel) {
831
- for (const [key, registered] of this.#panels) {
832
- if (registered === panel) {
833
- this.#panels.delete(key);
834
- }
835
- }
836
- }
837
- /** Панель, отвечающая за уход с этого маршрута, или её отсутствие. */
838
- find(route) {
839
- const key = route.routeConfig;
840
- if (key === null) {
841
- return null;
842
- }
843
- return this.#panels.get(key) ?? null;
844
- }
845
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: RtRouteAsideRegistry, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
846
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: RtRouteAsideRegistry, providedIn: 'root' }); }
847
- }
848
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: RtRouteAsideRegistry, decorators: [{
849
- type: Injectable,
850
- args: [{ providedIn: 'root' }]
851
- }] });
852
-
853
- /**
854
- * Открытие ждёт `panel.ready()`, а не `ngAfterViewInit`: на F5 rt-container
855
- * создаёт overlay асинхронно, иначе `open()` гонится с ещё не готовым overlay.
856
- *
857
- * `@Directive()` без селектора — чтобы query/`inject`/lifecycle наследовались на
858
- * конкретный `@Component` (как `RtFormControlBase`).
859
- *
860
- * Закрытие всегда идёт через `onClose()`, куда сходятся все четыре пути: две
861
- * кнопки панели и — через `onCancel()` — нажатие мимо панели и Esc, которые ловит
862
- * `rt-container`. Панель, поставившая гард через `guardUnsavedChanges()`, на
863
- * тронутой форме получает вопрос о правках; панель без гарда закрывается сразу.
864
- */
865
- class RtRouteAsideComponent {
866
- #entity;
867
- #entityId;
868
- #isCreateMode;
869
- #resolving;
870
- #submitting;
871
- #mutations;
872
- #refreshSource;
873
- #closeIntentSource;
874
- #unsavedGuard;
875
- /** Связанная запись, на которую панель уйдёт, когда пользователь решит судьбу правок */
876
- #relatedCommands;
877
- /** Параметры адреса связанной записи: у события журнала ими задан отбор списка */
878
- #relatedQueryParams;
879
- #notificationBus;
880
- #dialog;
881
- #injector;
882
- #registry;
883
- /** Вопрос о правках, заданный уходу по маршруту: у кнопок панели свой путь. */
884
- #unsavedPrompt;
885
- #opened;
886
- #navigation;
887
- constructor() {
888
- this.#entity = signal(null, /* @ts-ignore */
889
- ...(ngDevMode ? [{ debugName: "#entity" }] : /* istanbul ignore next */ []));
890
- this.#entityId = signal(null, /* @ts-ignore */
891
- ...(ngDevMode ? [{ debugName: "#entityId" }] : /* istanbul ignore next */ []));
892
- this.#isCreateMode = signal(false, /* @ts-ignore */
893
- ...(ngDevMode ? [{ debugName: "#isCreateMode" }] : /* istanbul ignore next */ []));
894
- this.#resolving = signal(false, /* @ts-ignore */
895
- ...(ngDevMode ? [{ debugName: "#resolving" }] : /* istanbul ignore next */ []));
896
- this.#submitting = signal(false, /* @ts-ignore */
897
- ...(ngDevMode ? [{ debugName: "#submitting" }] : /* istanbul ignore next */ []));
898
- this.#mutations = new RtRouteAsideMutations(inject(DestroyRef));
899
- this.#refreshSource = new Subject();
900
- this.#closeIntentSource = new Subject();
901
- this.#unsavedGuard = signal(null, /* @ts-ignore */
902
- ...(ngDevMode ? [{ debugName: "#unsavedGuard" }] : /* istanbul ignore next */ []));
903
- /** Связанная запись, на которую панель уйдёт, когда пользователь решит судьбу правок */
904
- this.#relatedCommands = null;
905
- /** Параметры адреса связанной записи: у события журнала ими задан отбор списка */
906
- this.#relatedQueryParams = null;
907
- this.#notificationBus = inject(NotificationBus);
908
- this.#dialog = inject(RtDialogService);
909
- this.#injector = inject(Injector);
910
- this.#registry = inject(RtRouteAsideRegistry);
911
- /** Вопрос о правках, заданный уходу по маршруту: у кнопок панели свой путь. */
912
- this.#unsavedPrompt = new RtRouteAsideUnsavedPrompt(this.#dialog, this.#injector, {
913
- save: () => this.#unsavedGuard()?.save(),
914
- submitting: this.#submitting,
915
- submitError: computed(() => this.submitError()),
916
- });
917
- this.#opened = false;
918
- this.router = inject(Router);
919
- this.#navigation = new RtRouteAsideNavigation(this.router);
920
- this.route = inject(ActivatedRoute);
921
- this.destroyRef = inject(DestroyRef);
922
- this.panel = viewChild(RtContainerRightSidenavPanelDirective, /* @ts-ignore */
923
- ...(ngDevMode ? [{ debugName: "panel" }] : /* istanbul ignore next */ []));
924
- this.entity = this.#entity.asReadonly();
925
- /** id из route-параметра как есть (uuid/строка); числовые id консьюмер парсит сам. */
926
- this.entityId = this.#entityId.asReadonly();
927
- this.isCreateMode = this.#isCreateMode.asReadonly();
928
- this.submitting = this.#submitting.asReadonly();
929
- /**
930
- * Скелетоны биндятся на это, а не на пустоту `entity()`: та залипает после
931
- * первой загрузки и не ловит рефетч.
932
- */
933
- this.resolving = this.#resolving.asReadonly();
934
- this.busy = computed(() => this.#submitting() || this.#resolving(), /* @ts-ignore */
935
- ...(ngDevMode ? [{ debugName: "busy" }] : /* istanbul ignore next */ []));
936
- /**
937
- * Форма не тронута. Панель, которая не поставила гард закрытия, считается
938
- * нетронутой всегда — и закрывается без вопроса, как раньше.
939
- */
940
- this.pristine = computed(() => this.#unsavedGuard()?.pristine() ?? true, /* @ts-ignore */
941
- ...(ngDevMode ? [{ debugName: "pristine" }] : /* istanbul ignore next */ []));
942
- this.submitError = signal(null, /* @ts-ignore */
943
- ...(ngDevMode ? [{ debugName: "submitError" }] : /* istanbul ignore next */ []));
944
- /**
945
- * Удача мутации — тем же способом, что и отказ. Человек, работающий в панели,
946
- * смотрит в панель, а не на экран за её краем: тост об успехе всплывает там,
947
- * куда он в эту минуту не смотрит. Оба сигнала гасятся в начале каждой
948
- * попытки и гасят друг друга — это ответы на один вопрос, и двух сразу не
949
- * бывает.
950
- */
951
- this.submitSuccess = signal(null, /* @ts-ignore */
952
- ...(ngDevMode ? [{ debugName: "submitSuccess" }] : /* istanbul ignore next */ []));
953
- this.idParamName = 'id';
954
- /** id-only режим: нужен только id (например, смена пароля по userId), сущность не грузится. */
955
- this.idOnly = false;
956
- effect(() => {
957
- const panel = this.panel();
958
- if (panel === undefined || !panel.ready() || this.#opened) {
959
- return;
960
- }
961
- this.#opened = true;
962
- panel.open();
963
- // Панель встала в аутлет — с этого мгновения о правках спрашивают её,
964
- // а не тот компонент, который роутер подставит гарду.
965
- this.#registry.register(this.route.snapshot, this);
966
- });
967
- // Снятие с учёта идёт по уничтожению, а не по уходу с экрана: уход может и
968
- // не состояться — роутер отклоняет навигацию молча, — и панель, снятая с
969
- // учёта раньше времени, осталась бы на экране, не отвечая о своих правках.
970
- this.destroyRef.onDestroy(() => this.#registry.unregister(this.route.snapshot, this));
971
- // Рефетч сущности из #refreshEntity(): mergeMap — каждый запуск resolve
972
- // живёт независимо (как раньше — отдельная подписка на вызов).
973
- this.#refreshSource
974
- .pipe(mergeMap((id) => this.resolve(id)), takeUntilDestroyed(this.destroyRef))
975
- .subscribe((entity) => {
976
- this.#resolving.set(false);
977
- if (entity === null) {
978
- this.#navigateAway();
979
- return;
980
- }
981
- this.#entity.set(entity);
982
- this.onResolved();
983
- });
984
- // Вопрос о несохранённых правках: exhaustMap, а не switchMap — пока окно
985
- // открыто, повторное намерение закрыться игнорируется. switchMap отписался
986
- // бы от первого окна, не убрав его overlay, и на экране осталось бы два.
987
- this.#closeIntentSource
988
- .pipe(exhaustMap(() => this.#dialog
989
- .open(RtAsideUnsavedDialogComponent)
990
- .afterClosed()), takeUntilDestroyed(this.destroyRef))
991
- .subscribe((outcome) => this.#applyUnsavedOutcome(outcome));
992
- }
993
- ngOnInit() {
994
- this.route.paramMap
995
- .pipe(switchMap((params) => {
996
- const idParam = params.get(this.idParamName);
997
- if (idParam === null || idParam === '') {
998
- this.#isCreateMode.set(true);
999
- this.#entityId.set(null);
1000
- return of(null);
1001
- }
1002
- this.#isCreateMode.set(false);
1003
- this.#entityId.set(idParam);
1004
- if (this.idOnly) {
1005
- return of(null);
1006
- }
1007
- this.#resolving.set(true);
1008
- return this.resolve(idParam);
1009
- }), tap((entity) => {
1010
- this.#resolving.set(false);
1011
- if (entity === null) {
1012
- if (!this.#isCreateMode() && !this.idOnly) {
1013
- this.#navigateAway();
1014
- }
1015
- return;
1016
- }
1017
- this.#entity.set(entity);
1018
- this.onResolved();
1019
- }), takeUntilDestroyed(this.destroyRef))
1020
- .subscribe();
1021
- }
1022
- /**
1023
- * Панель уходит с экрана не сама: её место в аутлете занимает другая — лента
1024
- * событий из шапки или соседняя запись. Тронутая форма спрашивает о правках
1025
- * так же, как при закрытии; окно кнопок этот путь не ловит, потому что панель
1026
- * закрывает роутер.
1027
- *
1028
- * Гард ставится на ro-маршрут панели (`rtAsideUnsavedGuard`).
1029
- */
1030
- canDeactivate() {
1031
- const intent = this.#closeIntent();
1032
- // Признак идущей записи старше разрешения на уход: панель, выдавшая себе
1033
- // разрешение и не дождавшаяся ответа сервера, уходить не должна — исход
1034
- // записи решит её судьбу сам.
1035
- if (intent === ERtAsideCloseIntent.Ignore) {
1036
- return of(false);
1037
- }
1038
- // Уход начала сама панель: правки либо записаны секунду назад, либо их
1039
- // судьбу пользователь уже решил. Вопрос был бы задан про то, чего нет.
1040
- if (this.#navigation.consumeLeaveAllowance()) {
1041
- return of(true);
1042
- }
1043
- if (intent === ERtAsideCloseIntent.Close) {
1044
- return of(true);
1045
- }
1046
- return this.#unsavedPrompt.ask();
1047
- }
1048
- setEntity(entity) {
1049
- this.#entity.set(entity);
1050
- }
1051
- /** Признак нетронутой формы — тот же, что гейтит кнопку записи. */
1052
- pristineSignal(control) {
1053
- return pristineOf(control);
1054
- }
1055
- /**
1056
- * Ставит гард закрытия: пока форма тронута, любой из четырёх путей закрытия
1057
- * спрашивает, что сделать с правками, и исход «закрыть с сохранением» зовёт
1058
- * `save`. Признак нетронутости даёт `pristineSignal(control)` — тот же, что
1059
- * гейтит кнопку записи.
1060
- */
1061
- guardUnsavedChanges(guard) {
1062
- this.#unsavedGuard.set(guard);
1063
- }
1064
- /**
1065
- * Адрес связанной записи для атрибута `href`. Ссылка остаётся настоящей
1066
- * ссылкой: её открывают в новой вкладке и копируют, а обычное нажатие панель
1067
- * перехватывает и уводит сама.
1068
- */
1069
- relatedUrl(commands) {
1070
- return this.router.serializeUrl(this.#relatedTree(commands));
1071
- }
1072
- /**
1073
- * Уход на связанную запись. Он уводит с адреса панели так же, как её
1074
- * закрытие, поэтому идёт тем же путём: тронутая форма спрашивает, что
1075
- * сделать с правками, и на исходе «закрыть с сохранением» запись открывается
1076
- * после удачной записи.
1077
- */
1078
- openRelated(commands, queryParams = null) {
1079
- const intent = this.#closeIntent();
1080
- if (intent === ERtAsideCloseIntent.Ignore) {
1081
- return;
1082
- }
1083
- if (intent === ERtAsideCloseIntent.Close) {
1084
- this.#navigateRelated(commands, queryParams);
1085
- return;
1086
- }
1087
- this.#relatedQueryParams = queryParams;
1088
- this.#relatedCommands = commands;
1089
- // Подписка объявлена один раз в конструкторе (см. #closeIntentSource-стрим).
1090
- this.#closeIntentSource.next();
1091
- }
1092
- onResolved() {
1093
- // Хук для наследника: базовый асайд после разрешения данных ничего не делает.
1094
- }
1095
- closeOutlets() {
1096
- return { ro: null };
1097
- }
1098
- /**
1099
- * `successText` — готовый текст тоста об успехе. Он принадлежит конкретной
1100
- * мутации, а не панели: у снятия промокода и опроса подписки свой текст
1101
- * успеха, и один на панель показал бы не тот.
1102
- *
1103
- * Именно текст, а не ключ словаря: ключ принадлежал бы словарю приложения, а
1104
- * кит чужих словарей не знает — переводит приложение и передаёт готовое.
1105
- *
1106
- * `errorText` принимается и функцией: причина отказа известна только после
1107
- * него — стор кладёт её в свой сигнал, а панель без стора выводит из ответа
1108
- * сервера, — и готовой строкой на момент запуска мутации её не передать.
1109
- *
1110
- * `successMessage` — текст удачи, который панель показывает внутри себя,
1111
- * рядом с формой. Довод отделён от `successText` намеренно: переезд текста
1112
- * из тоста в панель сломал бы всякого потребителя, который тост и хотел, а
1113
- * сказать «мне нужен тост» ему после этого было бы нечем. Назван он по месту
1114
- * показа, а не по исходу: два довода с разницей в одном слоге читались бы
1115
- * как опечатка.
1116
- */
1117
- runMutation(op$, opts) {
1118
- this.#submitting.set(true);
1119
- this.submitError.set(null);
1120
- this.submitSuccess.set(null);
1121
- this.#mutations.run({
1122
- op$,
1123
- handleSuccess: () => {
1124
- this.#submitting.set(false);
1125
- if (opts?.successText) {
1126
- this.#notificationBus.success(opts.successText);
1127
- }
1128
- if (opts?.successMessage) {
1129
- this.submitSuccess.set(opts.successMessage);
1130
- }
1131
- // Пользователь шёл на связанную запись и по дороге согласился
1132
- // сохранить: панель уходит туда, куда он нажал.
1133
- const related = this.#relatedCommands;
1134
- if (related !== null) {
1135
- this.#navigateRelated(related);
1136
- return;
1137
- }
1138
- if (opts?.onSuccess) {
1139
- opts.onSuccess();
1140
- return;
1141
- }
1142
- // Закрытие после удачи идёт мимо обоих вопросов о правках: форма ещё
1143
- // тронута, а спрашивать про только что записанное не о чем — уходу по
1144
- // маршруту это закрывает разрешение на уход. Названный довод решает в обе
1145
- // стороны, а не названный считается по режиму: создавать в закрытой панели
1146
- // нечего.
1147
- if (opts?.closeOnSuccess ?? this.#isCreateMode()) {
1148
- this.#closePanel();
1149
- return;
1150
- }
1151
- if (opts?.refreshOnSuccess === true) {
1152
- this.#refreshEntity();
1153
- }
1154
- },
1155
- handleError: (error) => {
1156
- this.#submitting.set(false);
1157
- // Отказ снимает прежнюю удачу: иначе «сохранено» осталось бы на
1158
- // панели рядом со свежим отказом.
1159
- this.submitSuccess.set(null);
1160
- // Отказ оставляет человека в панели с его правками, поэтому
1161
- // намерение уйти на связанную запись снимается.
1162
- this.#relatedCommands = null;
1163
- const text = typeof opts?.errorText === 'function' ? opts.errorText(error) : opts?.errorText;
1164
- if (text) {
1165
- this.submitError.set(text);
1166
- }
1167
- },
1168
- });
1169
- }
1170
- /**
1171
- * Единственная точка закрытия панели. Через неё идут все четыре пути: кнопка
1172
- * в шапке, кнопка в футере и — через `onCancel()` — нажатие мимо панели и
1173
- * клавиша Esc, которые ловит `rt-container` и отдаёт панели одним выходом
1174
- * `cancelled`.
1175
- */
1176
- onClose() {
1177
- const intent = this.#closeIntent();
1178
- if (intent === ERtAsideCloseIntent.Ignore) {
1179
- return;
1180
- }
1181
- if (intent === ERtAsideCloseIntent.Close) {
1182
- this.#closePanel();
1183
- return;
1184
- }
1185
- // Подписка объявлена один раз в конструкторе (см. #closeIntentSource-стрим).
1186
- this.#closeIntentSource.next();
1187
- }
1188
- onCancel() {
1189
- this.onClose();
1190
- }
1191
- onClosed() {
1192
- this.#navigateAway();
1193
- }
1194
- #refreshEntity() {
1195
- const id = this.#entityId();
1196
- if (id === null || this.idOnly) {
1197
- return;
1198
- }
1199
- this.#resolving.set(true);
1200
- // Подписка объявлена один раз в конструкторе (см. #refreshSource-стрим).
1201
- this.#refreshSource.next(id);
1202
- }
1203
- /** Решение по намерению уйти с панели — одно на закрытие и на переход по связанной записи */
1204
- #closeIntent() {
1205
- return resolveCloseIntent({
1206
- submitting: this.#submitting(),
1207
- guarded: this.#unsavedGuard() !== null,
1208
- pristine: this.pristine(),
1209
- });
1210
- }
1211
- #closePanel() {
1212
- this.panel()?.close();
1213
- }
1214
- #navigateRelated(commands, queryParams = null) {
1215
- const params = queryParams ?? this.#relatedQueryParams;
1216
- this.#relatedCommands = null;
1217
- this.#relatedQueryParams = null;
1218
- this.#navigation.allowed(() => this.router.navigateByUrl(this.#relatedTree(commands, params)));
1219
- }
1220
- #relatedTree(commands, queryParams = null) {
1221
- return this.#navigation.relatedTree(this.closeOutlets(), commands, queryParams);
1222
- }
1223
- #applyUnsavedOutcome(outcome) {
1224
- const related = this.#relatedCommands;
1225
- if (outcome === ERtAsideUnsavedOutcome.Discard) {
1226
- if (related !== null) {
1227
- this.#navigateRelated(related);
1228
- return;
1229
- }
1230
- this.#closePanel();
1231
- return;
1232
- }
1233
- // Запись закрывает панель сама на успехе — иначе панель ушла бы с экрана
1234
- // раньше ответа, и отказ негде было бы показать. Уход на
1235
- // связанную запись ждёт того же успеха.
1236
- if (outcome === ERtAsideUnsavedOutcome.Save) {
1237
- this.#unsavedGuard()?.save();
1238
- // Запись могла и не начаться — например, черновик не годится. Тогда
1239
- // намерение уйти снимается вместе с ней, иначе панель ушла бы на
1240
- // связанную запись после следующей удачной записи.
1241
- if (!this.#submitting()) {
1242
- this.#relatedCommands = null;
1243
- }
1244
- return;
1245
- }
1246
- this.#relatedCommands = null;
1247
- }
1248
- /**
1249
- * Уход с адреса при закрытии.
1250
- *
1251
- * Параметры адреса переносятся нетронутыми: панель открыта поверх экрана, чьё состояние в
1252
- * них и живёт — страница списка, порядок, отбор. Без переноса закрытая панель возвращает
1253
- * экран к его первой странице без отбора, и человек, открывший запись со второй страницы
1254
- * отобранного списка, теряет её просмотром одной записи. Свои параметры панель называет
1255
- * `openRelated` явно, и на них перенос не действует.
1256
- */
1257
- #navigateAway() {
1258
- this.#navigation.allowed(() => this.router.navigate([{ outlets: this.closeOutlets() }], {
1259
- relativeTo: this.route.parent,
1260
- queryParamsHandling: 'preserve',
1261
- }));
1262
- }
1263
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: RtRouteAsideComponent, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
1264
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.2.0", version: "22.1.6", type: RtRouteAsideComponent, isStandalone: true, viewQueries: [{ propertyName: "panel", first: true, predicate: RtContainerRightSidenavPanelDirective, descendants: true, isSignal: true }], ngImport: i0 }); }
947
+ const control$ = isSignal(control) ? toObservable(control) : of(control);
948
+ return toSignal(control$.pipe(switchMap((current) => {
949
+ if (current === void 0) return of(true);
950
+ return current.events.pipe(filter((event) => event instanceof PristineChangeEvent), map((event) => event.pristine), startWith(current.pristine));
951
+ })), { initialValue: true });
1265
952
  }
1266
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: RtRouteAsideComponent, decorators: [{
1267
- type: Directive
1268
- }], ctorParameters: () => [], propDecorators: { panel: [{ type: i0.ViewChild, args: [i0.forwardRef(() => RtContainerRightSidenavPanelDirective), { isSignal: true }] }] } });
1269
-
1270
- // Объявление переехало к учёту панелей; здесь оно остаётся видимым прежним потребителям.
1271
- /**
1272
- * Панель с несохранёнными правками спрашивает о них и при смене маршрута, а не
1273
- * только при закрытии: аутлет `ro` занимает соседняя панель, и правки пропали бы
1274
- * молча.
1275
- *
1276
- * Ставится на каждый ro-маршрут: гард висит на кнопках, нажатии мимо и Esc, а
1277
- * смену маршрута ловит только роутер.
1278
- *
1279
- * Спрашивается панель, учтённая под маршрутом ухода, а не компонент, который
1280
- * подставил роутер. Компонент — не панель, когда ro-маршрут объявлен под уровнем
1281
- * без своего компонента: Angular отдаёт детям контекст родителя, и в гард
1282
- * приходит компонент первичного аутлета. Ответ такого компонента к правкам
1283
- * отношения не имеет, а вызов у него метода, которого нет, ронял навигацию — она
1284
- * падала необработанным отказом, адрес не менялся, и приложение оставалось
1285
- * запертым на панели.
1286
- *
1287
- * Компонент от роутера остаётся запасным путём: гард выведен наружу кита, и
1288
- * панель приложения может отвечать о правках, не наследуя базовый класс, — на
1289
- * учёт такая панель не встаёт никогда. Без запасного пути у неё вопрос о правках
1290
- * исчез бы молча, а это тихая потеря правок.
1291
- *
1292
- * Спрашивать некого — уступить место можно: роутер зовёт гард и для маршрута,
1293
- * чей компонент не создан. Без этого первая же такая навигация падает, а следом
1294
- * отказывает любая другая.
1295
- *
1296
- * Отказом навигации гард не отвечает никогда, в том числе когда ответ панели
1297
- * отказал: разрешить уход значило бы унести правки, о которых спросить не
1298
- * удалось, а отменить и оставить всё как есть — запереть приложение на панели
1299
- * навсегда. Поэтому уход отменяется один раз, а панель снимается с учёта, и
1300
- * следующий уход идёт запасным путём.
1301
- */
1302
- /** Компонент от роутера годится в ответчики, только если умеет отвечать. */
953
+ var RtRouteAsideRegistry = class RtRouteAsideRegistry {
954
+ #panels = /* @__PURE__ */ new Map();
955
+ register(route, panel) {
956
+ const key = route.routeConfig;
957
+ if (key === null) return;
958
+ this.#panels.set(key, panel);
959
+ }
960
+ unregister(route, panel) {
961
+ const key = route.routeConfig;
962
+ if (key === null || this.#panels.get(key) !== panel) return;
963
+ this.#panels.delete(key);
964
+ }
965
+ forget(panel) {
966
+ for (const [key, registered] of this.#panels) if (registered === panel) this.#panels.delete(key);
967
+ }
968
+ find(route) {
969
+ const key = route.routeConfig;
970
+ if (key === null) return null;
971
+ return this.#panels.get(key) ?? null;
972
+ }
973
+ static {
974
+ this.ɵfac = i0.ɵɵngDeclareFactory({
975
+ minVersion: "12.0.0",
976
+ version: "22.2.2",
977
+ ngImport: i0,
978
+ type: RtRouteAsideRegistry,
979
+ deps: [],
980
+ target: i0.ɵɵFactoryTarget.Injectable
981
+ });
982
+ }
983
+ static {
984
+ this.ɵprov = i0.ɵɵngDeclareInjectable({
985
+ minVersion: "12.0.0",
986
+ version: "22.2.2",
987
+ ngImport: i0,
988
+ type: RtRouteAsideRegistry,
989
+ providedIn: "root"
990
+ });
991
+ }
992
+ };
993
+ i0.ɵɵngDeclareClassMetadata({
994
+ minVersion: "12.0.0",
995
+ version: "22.2.2",
996
+ ngImport: i0,
997
+ type: RtRouteAsideRegistry,
998
+ decorators: [{
999
+ type: Injectable,
1000
+ args: [{ providedIn: "root" }]
1001
+ }]
1002
+ });
1003
+ var RtRouteAsideComponent = class RtRouteAsideComponent {
1004
+ #entity;
1005
+ #entityId;
1006
+ #isCreateMode;
1007
+ #resolving;
1008
+ #submitting;
1009
+ #mutations;
1010
+ #refreshSource;
1011
+ #closeIntentSource;
1012
+ #unsavedGuard;
1013
+ #relatedCommands;
1014
+ #relatedQueryParams;
1015
+ #notificationBus;
1016
+ #dialog;
1017
+ #injector;
1018
+ #registry;
1019
+ #unsavedPrompt;
1020
+ #opened;
1021
+ #navigation;
1022
+ constructor() {
1023
+ this.#entity = signal(null, ...ngDevMode ? [{ debugName: "#entity" }] : /* istanbul ignore next */ []);
1024
+ this.#entityId = signal(null, ...ngDevMode ? [{ debugName: "#entityId" }] : /* istanbul ignore next */ []);
1025
+ this.#isCreateMode = signal(false, ...ngDevMode ? [{ debugName: "#isCreateMode" }] : /* istanbul ignore next */ []);
1026
+ this.#resolving = signal(false, ...ngDevMode ? [{ debugName: "#resolving" }] : /* istanbul ignore next */ []);
1027
+ this.#submitting = signal(false, ...ngDevMode ? [{ debugName: "#submitting" }] : /* istanbul ignore next */ []);
1028
+ this.#mutations = new RtRouteAsideMutations(inject(DestroyRef));
1029
+ this.#refreshSource = new Subject();
1030
+ this.#closeIntentSource = new Subject();
1031
+ this.#unsavedGuard = signal(null, ...ngDevMode ? [{ debugName: "#unsavedGuard" }] : /* istanbul ignore next */ []);
1032
+ this.#relatedCommands = null;
1033
+ this.#relatedQueryParams = null;
1034
+ this.#notificationBus = inject(NotificationBus);
1035
+ this.#dialog = inject(RtDialogService);
1036
+ this.#injector = inject(Injector);
1037
+ this.#registry = inject(RtRouteAsideRegistry);
1038
+ this.#unsavedPrompt = new RtRouteAsideUnsavedPrompt(this.#dialog, this.#injector, {
1039
+ save: () => this.#unsavedGuard()?.save(),
1040
+ submitting: this.#submitting,
1041
+ submitError: computed(() => this.submitError())
1042
+ });
1043
+ this.#opened = false;
1044
+ this.router = inject(Router);
1045
+ this.#navigation = new RtRouteAsideNavigation(this.router);
1046
+ this.route = inject(ActivatedRoute);
1047
+ this.destroyRef = inject(DestroyRef);
1048
+ this.panel = viewChild(RtContainerRightSidenavPanelDirective, ...ngDevMode ? [{ debugName: "panel" }] : /* istanbul ignore next */ []);
1049
+ this.entity = this.#entity.asReadonly();
1050
+ this.entityId = this.#entityId.asReadonly();
1051
+ this.isCreateMode = this.#isCreateMode.asReadonly();
1052
+ this.submitting = this.#submitting.asReadonly();
1053
+ this.resolving = this.#resolving.asReadonly();
1054
+ this.busy = computed(() => this.#submitting() || this.#resolving(), ...ngDevMode ? [{ debugName: "busy" }] : /* istanbul ignore next */ []);
1055
+ this.pristine = computed(() => this.#unsavedGuard()?.pristine() ?? true, ...ngDevMode ? [{ debugName: "pristine" }] : /* istanbul ignore next */ []);
1056
+ this.submitError = signal(null, ...ngDevMode ? [{ debugName: "submitError" }] : /* istanbul ignore next */ []);
1057
+ this.submitSuccess = signal(null, ...ngDevMode ? [{ debugName: "submitSuccess" }] : /* istanbul ignore next */ []);
1058
+ this.idParamName = "id";
1059
+ this.idOnly = false;
1060
+ effect(() => {
1061
+ const panel = this.panel();
1062
+ if (panel === void 0 || !panel.ready() || this.#opened) return;
1063
+ this.#opened = true;
1064
+ panel.open();
1065
+ this.#registry.register(this.route.snapshot, this);
1066
+ });
1067
+ this.destroyRef.onDestroy(() => this.#registry.unregister(this.route.snapshot, this));
1068
+ this.#refreshSource.pipe(mergeMap((id) => this.resolve(id)), takeUntilDestroyed(this.destroyRef)).subscribe((entity) => {
1069
+ this.#resolving.set(false);
1070
+ if (entity === null) {
1071
+ this.#navigateAway();
1072
+ return;
1073
+ }
1074
+ this.#entity.set(entity);
1075
+ this.onResolved();
1076
+ });
1077
+ this.#closeIntentSource.pipe(exhaustMap(() => this.#dialog.open(RtAsideUnsavedDialogComponent).afterClosed()), takeUntilDestroyed(this.destroyRef)).subscribe((outcome) => this.#applyUnsavedOutcome(outcome));
1078
+ }
1079
+ ngOnInit() {
1080
+ this.route.paramMap.pipe(switchMap((params) => {
1081
+ const idParam = params.get(this.idParamName);
1082
+ if (idParam === null || idParam === "") {
1083
+ this.#isCreateMode.set(true);
1084
+ this.#entityId.set(null);
1085
+ return of(null);
1086
+ }
1087
+ this.#isCreateMode.set(false);
1088
+ this.#entityId.set(idParam);
1089
+ if (this.idOnly) return of(null);
1090
+ this.#resolving.set(true);
1091
+ return this.resolve(idParam);
1092
+ }), tap((entity) => {
1093
+ this.#resolving.set(false);
1094
+ if (entity === null) {
1095
+ if (!this.#isCreateMode() && !this.idOnly) this.#navigateAway();
1096
+ return;
1097
+ }
1098
+ this.#entity.set(entity);
1099
+ this.onResolved();
1100
+ }), takeUntilDestroyed(this.destroyRef)).subscribe();
1101
+ }
1102
+ canDeactivate() {
1103
+ const intent = this.#closeIntent();
1104
+ if (intent === ERtAsideCloseIntent.Ignore) return of(false);
1105
+ if (this.#navigation.consumeLeaveAllowance()) return of(true);
1106
+ if (intent === ERtAsideCloseIntent.Close) return of(true);
1107
+ return this.#unsavedPrompt.ask();
1108
+ }
1109
+ setEntity(entity) {
1110
+ this.#entity.set(entity);
1111
+ }
1112
+ pristineSignal(control) {
1113
+ return pristineOf(control);
1114
+ }
1115
+ guardUnsavedChanges(guard) {
1116
+ this.#unsavedGuard.set(guard);
1117
+ }
1118
+ relatedUrl(commands) {
1119
+ return this.router.serializeUrl(this.#relatedTree(commands));
1120
+ }
1121
+ openRelated(commands, queryParams = null) {
1122
+ const intent = this.#closeIntent();
1123
+ if (intent === ERtAsideCloseIntent.Ignore) return;
1124
+ if (intent === ERtAsideCloseIntent.Close) {
1125
+ this.#navigateRelated(commands, queryParams);
1126
+ return;
1127
+ }
1128
+ this.#relatedQueryParams = queryParams;
1129
+ this.#relatedCommands = commands;
1130
+ this.#closeIntentSource.next();
1131
+ }
1132
+ onResolved() {}
1133
+ closeOutlets() {
1134
+ return { ro: null };
1135
+ }
1136
+ runMutation(op$, opts) {
1137
+ this.#submitting.set(true);
1138
+ this.submitError.set(null);
1139
+ this.submitSuccess.set(null);
1140
+ this.#mutations.run({
1141
+ op$,
1142
+ handleSuccess: () => {
1143
+ this.#submitting.set(false);
1144
+ if (opts?.successText) this.#notificationBus.success(opts.successText);
1145
+ if (opts?.successMessage) this.submitSuccess.set(opts.successMessage);
1146
+ const related = this.#relatedCommands;
1147
+ if (related !== null) {
1148
+ this.#navigateRelated(related);
1149
+ return;
1150
+ }
1151
+ if (opts?.onSuccess) {
1152
+ opts.onSuccess();
1153
+ return;
1154
+ }
1155
+ if (opts?.closeOnSuccess ?? this.#isCreateMode()) {
1156
+ this.#closePanel();
1157
+ return;
1158
+ }
1159
+ if (opts?.refreshOnSuccess === true) this.#refreshEntity();
1160
+ },
1161
+ handleError: (error) => {
1162
+ this.#submitting.set(false);
1163
+ this.submitSuccess.set(null);
1164
+ this.#relatedCommands = null;
1165
+ const text = typeof opts?.errorText === "function" ? opts.errorText(error) : opts?.errorText;
1166
+ if (text) this.submitError.set(text);
1167
+ }
1168
+ });
1169
+ }
1170
+ onClose() {
1171
+ const intent = this.#closeIntent();
1172
+ if (intent === ERtAsideCloseIntent.Ignore) return;
1173
+ if (intent === ERtAsideCloseIntent.Close) {
1174
+ this.#closePanel();
1175
+ return;
1176
+ }
1177
+ this.#closeIntentSource.next();
1178
+ }
1179
+ onCancel() {
1180
+ this.onClose();
1181
+ }
1182
+ onClosed() {
1183
+ this.#navigateAway();
1184
+ }
1185
+ #refreshEntity() {
1186
+ const id = this.#entityId();
1187
+ if (id === null || this.idOnly) return;
1188
+ this.#resolving.set(true);
1189
+ this.#refreshSource.next(id);
1190
+ }
1191
+ #closeIntent() {
1192
+ return resolveCloseIntent({
1193
+ submitting: this.#submitting(),
1194
+ guarded: this.#unsavedGuard() !== null,
1195
+ pristine: this.pristine()
1196
+ });
1197
+ }
1198
+ #closePanel() {
1199
+ this.panel()?.close();
1200
+ }
1201
+ #navigateRelated(commands, queryParams = null) {
1202
+ const params = queryParams ?? this.#relatedQueryParams;
1203
+ this.#relatedCommands = null;
1204
+ this.#relatedQueryParams = null;
1205
+ this.#navigation.allowed(() => this.router.navigateByUrl(this.#relatedTree(commands, params)));
1206
+ }
1207
+ #relatedTree(commands, queryParams = null) {
1208
+ return this.#navigation.relatedTree(this.closeOutlets(), commands, queryParams);
1209
+ }
1210
+ #applyUnsavedOutcome(outcome) {
1211
+ const related = this.#relatedCommands;
1212
+ if (outcome === ERtAsideUnsavedOutcome.Discard) {
1213
+ if (related !== null) {
1214
+ this.#navigateRelated(related);
1215
+ return;
1216
+ }
1217
+ this.#closePanel();
1218
+ return;
1219
+ }
1220
+ if (outcome === ERtAsideUnsavedOutcome.Save) {
1221
+ this.#unsavedGuard()?.save();
1222
+ if (!this.#submitting()) this.#relatedCommands = null;
1223
+ return;
1224
+ }
1225
+ this.#relatedCommands = null;
1226
+ }
1227
+ #navigateAway() {
1228
+ this.#navigation.allowed(() => this.router.navigate([{ outlets: this.closeOutlets() }], {
1229
+ relativeTo: this.route.parent,
1230
+ queryParamsHandling: "preserve"
1231
+ }));
1232
+ }
1233
+ static {
1234
+ this.ɵfac = i0.ɵɵngDeclareFactory({
1235
+ minVersion: "12.0.0",
1236
+ version: "22.2.2",
1237
+ ngImport: i0,
1238
+ type: RtRouteAsideComponent,
1239
+ deps: [],
1240
+ target: i0.ɵɵFactoryTarget.Directive
1241
+ });
1242
+ }
1243
+ static {
1244
+ this.ɵdir = i0.ɵɵngDeclareDirective({
1245
+ minVersion: "17.2.0",
1246
+ version: "22.2.2",
1247
+ type: RtRouteAsideComponent,
1248
+ isStandalone: true,
1249
+ viewQueries: [{
1250
+ propertyName: "panel",
1251
+ first: true,
1252
+ predicate: RtContainerRightSidenavPanelDirective,
1253
+ descendants: true,
1254
+ isSignal: true
1255
+ }],
1256
+ ngImport: i0
1257
+ });
1258
+ }
1259
+ };
1260
+ i0.ɵɵngDeclareClassMetadata({
1261
+ minVersion: "12.0.0",
1262
+ version: "22.2.2",
1263
+ ngImport: i0,
1264
+ type: RtRouteAsideComponent,
1265
+ decorators: [{ type: Directive }],
1266
+ ctorParameters: () => [],
1267
+ propDecorators: { panel: [{
1268
+ type: i0.ViewChild,
1269
+ args: [i0.forwardRef(() => RtContainerRightSidenavPanelDirective), { isSignal: true }]
1270
+ }] }
1271
+ });
1303
1272
  function fallbackPanel(component) {
1304
- return typeof component?.canDeactivate === 'function' ? component : null;
1273
+ return typeof component?.canDeactivate === "function" ? component : null;
1305
1274
  }
1306
1275
  const rtAsideUnsavedGuard = (component, currentRoute) => {
1307
- const registry = inject(RtRouteAsideRegistry);
1308
- const registered = registry.find(currentRoute);
1309
- const panel = registered ?? fallbackPanel(component);
1310
- if (panel === null) {
1311
- return of(true);
1312
- }
1313
- // defer: ответ панели может отказать и синхронным броском, а гард обязан
1314
- // пережить и его.
1315
- return defer(() => panel.canDeactivate()).pipe(catchError(() => {
1316
- registry.forget(panel);
1317
- return of(false);
1318
- }));
1276
+ const registry = inject(RtRouteAsideRegistry);
1277
+ const panel = registry.find(currentRoute) ?? fallbackPanel(component);
1278
+ if (panel === null) return of(true);
1279
+ return defer(() => panel.canDeactivate()).pipe(catchError(() => {
1280
+ registry.forget(panel);
1281
+ return of(false);
1282
+ }));
1319
1283
  };
1320
-
1321
- /**
1322
- * Generated bundle index. Do not edit.
1323
- */
1324
-
1325
1284
  export { RtContainerComponent, RtContainerContentDirective, RtContainerContentPanelDirective, RtContainerHeaderDirective, RtContainerLeftSidenavDirective, RtContainerLeftSidenavPanelDirective, RtContainerRightSidenavDirective, RtContainerRightSidenavPanelDirective, RtContainerStateService, RtContainerToolbarCenterDirective, RtContainerToolbarLeftDirective, RtContainerToolbarRightDirective, RtRouteAsideComponent, rtAsideUnsavedGuard };
1326
- //# sourceMappingURL=rt-tools-ui-kit-v2-container.mjs.map
1285
+
1286
+ //# sourceMappingURL=rt-tools-ui-kit-v2-container.mjs.map