@rt-tools/ui-kit-v2 0.17.0 → 0.18.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 (276) hide show
  1. package/README.md +18 -0
  2. package/fesm2022/rt-tools-ui-kit-v2-accordion.mjs +79 -0
  3. package/fesm2022/rt-tools-ui-kit-v2-accordion.mjs.map +1 -0
  4. package/fesm2022/rt-tools-ui-kit-v2-action-bar.mjs +227 -0
  5. package/fesm2022/rt-tools-ui-kit-v2-action-bar.mjs.map +1 -0
  6. package/fesm2022/rt-tools-ui-kit-v2-aside-section.mjs +47 -0
  7. package/fesm2022/rt-tools-ui-kit-v2-aside-section.mjs.map +1 -0
  8. package/fesm2022/rt-tools-ui-kit-v2-aside.mjs +702 -0
  9. package/fesm2022/rt-tools-ui-kit-v2-aside.mjs.map +1 -0
  10. package/fesm2022/rt-tools-ui-kit-v2-autocomplete.mjs +214 -0
  11. package/fesm2022/rt-tools-ui-kit-v2-autocomplete.mjs.map +1 -0
  12. package/fesm2022/rt-tools-ui-kit-v2-bar-list.mjs +53 -0
  13. package/fesm2022/rt-tools-ui-kit-v2-bar-list.mjs.map +1 -0
  14. package/fesm2022/rt-tools-ui-kit-v2-bottom-sheet.mjs +88 -0
  15. package/fesm2022/rt-tools-ui-kit-v2-bottom-sheet.mjs.map +1 -0
  16. package/fesm2022/rt-tools-ui-kit-v2-button.mjs +365 -0
  17. package/fesm2022/rt-tools-ui-kit-v2-button.mjs.map +1 -0
  18. package/fesm2022/rt-tools-ui-kit-v2-calendar.mjs +152 -0
  19. package/fesm2022/rt-tools-ui-kit-v2-calendar.mjs.map +1 -0
  20. package/fesm2022/rt-tools-ui-kit-v2-card.mjs +72 -0
  21. package/fesm2022/rt-tools-ui-kit-v2-card.mjs.map +1 -0
  22. package/fesm2022/rt-tools-ui-kit-v2-checkbox.mjs +111 -0
  23. package/fesm2022/rt-tools-ui-kit-v2-checkbox.mjs.map +1 -0
  24. package/fesm2022/rt-tools-ui-kit-v2-collapsible-text.mjs +76 -0
  25. package/fesm2022/rt-tools-ui-kit-v2-collapsible-text.mjs.map +1 -0
  26. package/fesm2022/rt-tools-ui-kit-v2-confirm-popover.mjs +255 -0
  27. package/fesm2022/rt-tools-ui-kit-v2-confirm-popover.mjs.map +1 -0
  28. package/fesm2022/rt-tools-ui-kit-v2-container.mjs +1326 -0
  29. package/fesm2022/rt-tools-ui-kit-v2-container.mjs.map +1 -0
  30. package/fesm2022/rt-tools-ui-kit-v2-core.mjs +2590 -0
  31. package/fesm2022/rt-tools-ui-kit-v2-core.mjs.map +1 -0
  32. package/fesm2022/rt-tools-ui-kit-v2-counter-row.mjs +45 -0
  33. package/fesm2022/rt-tools-ui-kit-v2-counter-row.mjs.map +1 -0
  34. package/fesm2022/rt-tools-ui-kit-v2-counter.mjs +158 -0
  35. package/fesm2022/rt-tools-ui-kit-v2-counter.mjs.map +1 -0
  36. package/fesm2022/rt-tools-ui-kit-v2-data-list.mjs +894 -0
  37. package/fesm2022/rt-tools-ui-kit-v2-data-list.mjs.map +1 -0
  38. package/fesm2022/rt-tools-ui-kit-v2-data-table.mjs +1217 -0
  39. package/fesm2022/rt-tools-ui-kit-v2-data-table.mjs.map +1 -0
  40. package/fesm2022/rt-tools-ui-kit-v2-date-picker.mjs +779 -0
  41. package/fesm2022/rt-tools-ui-kit-v2-date-picker.mjs.map +1 -0
  42. package/fesm2022/rt-tools-ui-kit-v2-date-range.mjs +573 -0
  43. package/fesm2022/rt-tools-ui-kit-v2-date-range.mjs.map +1 -0
  44. package/fesm2022/rt-tools-ui-kit-v2-delta-view.mjs +141 -0
  45. package/fesm2022/rt-tools-ui-kit-v2-delta-view.mjs.map +1 -0
  46. package/fesm2022/rt-tools-ui-kit-v2-detail-list.mjs +68 -0
  47. package/fesm2022/rt-tools-ui-kit-v2-detail-list.mjs.map +1 -0
  48. package/fesm2022/rt-tools-ui-kit-v2-dialog.mjs +478 -0
  49. package/fesm2022/rt-tools-ui-kit-v2-dialog.mjs.map +1 -0
  50. package/fesm2022/rt-tools-ui-kit-v2-dot-field.mjs +183 -0
  51. package/fesm2022/rt-tools-ui-kit-v2-dot-field.mjs.map +1 -0
  52. package/fesm2022/rt-tools-ui-kit-v2-download-link.mjs +44 -0
  53. package/fesm2022/rt-tools-ui-kit-v2-download-link.mjs.map +1 -0
  54. package/fesm2022/rt-tools-ui-kit-v2-dynamic-list.mjs +260 -0
  55. package/fesm2022/rt-tools-ui-kit-v2-dynamic-list.mjs.map +1 -0
  56. package/fesm2022/rt-tools-ui-kit-v2-dynamic-selector.mjs +937 -0
  57. package/fesm2022/rt-tools-ui-kit-v2-dynamic-selector.mjs.map +1 -0
  58. package/fesm2022/rt-tools-ui-kit-v2-empty-state.mjs +56 -0
  59. package/fesm2022/rt-tools-ui-kit-v2-empty-state.mjs.map +1 -0
  60. package/fesm2022/rt-tools-ui-kit-v2-expansion-panel.mjs +107 -0
  61. package/fesm2022/rt-tools-ui-kit-v2-expansion-panel.mjs.map +1 -0
  62. package/fesm2022/rt-tools-ui-kit-v2-field.mjs +183 -0
  63. package/fesm2022/rt-tools-ui-kit-v2-field.mjs.map +1 -0
  64. package/fesm2022/rt-tools-ui-kit-v2-file-card.mjs +219 -0
  65. package/fesm2022/rt-tools-ui-kit-v2-file-card.mjs.map +1 -0
  66. package/fesm2022/rt-tools-ui-kit-v2-file-drop.mjs +214 -0
  67. package/fesm2022/rt-tools-ui-kit-v2-file-drop.mjs.map +1 -0
  68. package/fesm2022/rt-tools-ui-kit-v2-file-input.mjs +117 -0
  69. package/fesm2022/rt-tools-ui-kit-v2-file-input.mjs.map +1 -0
  70. package/fesm2022/rt-tools-ui-kit-v2-file-list.mjs +32 -0
  71. package/fesm2022/rt-tools-ui-kit-v2-file-list.mjs.map +1 -0
  72. package/fesm2022/rt-tools-ui-kit-v2-filter-control.mjs +91 -0
  73. package/fesm2022/rt-tools-ui-kit-v2-filter-control.mjs.map +1 -0
  74. package/fesm2022/rt-tools-ui-kit-v2-form-control.mjs +220 -0
  75. package/fesm2022/rt-tools-ui-kit-v2-form-control.mjs.map +1 -0
  76. package/fesm2022/rt-tools-ui-kit-v2-header.mjs +72 -0
  77. package/fesm2022/rt-tools-ui-kit-v2-header.mjs.map +1 -0
  78. package/fesm2022/rt-tools-ui-kit-v2-icon-button.mjs +163 -0
  79. package/fesm2022/rt-tools-ui-kit-v2-icon-button.mjs.map +1 -0
  80. package/fesm2022/rt-tools-ui-kit-v2-icon.mjs +674 -0
  81. package/fesm2022/rt-tools-ui-kit-v2-icon.mjs.map +1 -0
  82. package/fesm2022/rt-tools-ui-kit-v2-image-cropper.mjs +540 -0
  83. package/fesm2022/rt-tools-ui-kit-v2-image-cropper.mjs.map +1 -0
  84. package/fesm2022/rt-tools-ui-kit-v2-image-upload.mjs +227 -0
  85. package/fesm2022/rt-tools-ui-kit-v2-image-upload.mjs.map +1 -0
  86. package/fesm2022/rt-tools-ui-kit-v2-info-item.mjs +37 -0
  87. package/fesm2022/rt-tools-ui-kit-v2-info-item.mjs.map +1 -0
  88. package/fesm2022/rt-tools-ui-kit-v2-input-number.mjs +361 -0
  89. package/fesm2022/rt-tools-ui-kit-v2-input-number.mjs.map +1 -0
  90. package/fesm2022/rt-tools-ui-kit-v2-input.mjs +143 -0
  91. package/fesm2022/rt-tools-ui-kit-v2-input.mjs.map +1 -0
  92. package/fesm2022/rt-tools-ui-kit-v2-live-badge.mjs +49 -0
  93. package/fesm2022/rt-tools-ui-kit-v2-live-badge.mjs.map +1 -0
  94. package/fesm2022/rt-tools-ui-kit-v2-logo.mjs +97 -0
  95. package/fesm2022/rt-tools-ui-kit-v2-logo.mjs.map +1 -0
  96. package/fesm2022/rt-tools-ui-kit-v2-markdown-text.mjs +57 -0
  97. package/fesm2022/rt-tools-ui-kit-v2-markdown-text.mjs.map +1 -0
  98. package/fesm2022/rt-tools-ui-kit-v2-menu.mjs +537 -0
  99. package/fesm2022/rt-tools-ui-kit-v2-menu.mjs.map +1 -0
  100. package/fesm2022/rt-tools-ui-kit-v2-message.mjs +105 -0
  101. package/fesm2022/rt-tools-ui-kit-v2-message.mjs.map +1 -0
  102. package/fesm2022/rt-tools-ui-kit-v2-money-list.mjs +71 -0
  103. package/fesm2022/rt-tools-ui-kit-v2-money-list.mjs.map +1 -0
  104. package/fesm2022/rt-tools-ui-kit-v2-multiselect.mjs +315 -0
  105. package/fesm2022/rt-tools-ui-kit-v2-multiselect.mjs.map +1 -0
  106. package/fesm2022/rt-tools-ui-kit-v2-night-grid.mjs +51 -0
  107. package/fesm2022/rt-tools-ui-kit-v2-night-grid.mjs.map +1 -0
  108. package/fesm2022/rt-tools-ui-kit-v2-note.mjs +44 -0
  109. package/fesm2022/rt-tools-ui-kit-v2-note.mjs.map +1 -0
  110. package/fesm2022/rt-tools-ui-kit-v2-notifications-bell.mjs +54 -0
  111. package/fesm2022/rt-tools-ui-kit-v2-notifications-bell.mjs.map +1 -0
  112. package/fesm2022/rt-tools-ui-kit-v2-page-header.mjs +339 -0
  113. package/fesm2022/rt-tools-ui-kit-v2-page-header.mjs.map +1 -0
  114. package/fesm2022/rt-tools-ui-kit-v2-pagination.mjs +187 -0
  115. package/fesm2022/rt-tools-ui-kit-v2-pagination.mjs.map +1 -0
  116. package/fesm2022/rt-tools-ui-kit-v2-photo-viewer.mjs +170 -0
  117. package/fesm2022/rt-tools-ui-kit-v2-photo-viewer.mjs.map +1 -0
  118. package/fesm2022/rt-tools-ui-kit-v2-popover.mjs +312 -0
  119. package/fesm2022/rt-tools-ui-kit-v2-popover.mjs.map +1 -0
  120. package/fesm2022/rt-tools-ui-kit-v2-radio-button.mjs +174 -0
  121. package/fesm2022/rt-tools-ui-kit-v2-radio-button.mjs.map +1 -0
  122. package/fesm2022/rt-tools-ui-kit-v2-radius.mjs +56 -0
  123. package/fesm2022/rt-tools-ui-kit-v2-radius.mjs.map +1 -0
  124. package/fesm2022/rt-tools-ui-kit-v2-ripple.mjs +118 -0
  125. package/fesm2022/rt-tools-ui-kit-v2-ripple.mjs.map +1 -0
  126. package/fesm2022/rt-tools-ui-kit-v2-scroll-area.mjs +290 -0
  127. package/fesm2022/rt-tools-ui-kit-v2-scroll-area.mjs.map +1 -0
  128. package/fesm2022/rt-tools-ui-kit-v2-section-nav.mjs +37 -0
  129. package/fesm2022/rt-tools-ui-kit-v2-section-nav.mjs.map +1 -0
  130. package/fesm2022/rt-tools-ui-kit-v2-select.mjs +495 -0
  131. package/fesm2022/rt-tools-ui-kit-v2-select.mjs.map +1 -0
  132. package/fesm2022/rt-tools-ui-kit-v2-side-menu.mjs +1493 -0
  133. package/fesm2022/rt-tools-ui-kit-v2-side-menu.mjs.map +1 -0
  134. package/fesm2022/rt-tools-ui-kit-v2-skeleton-wrapper.mjs +49 -0
  135. package/fesm2022/rt-tools-ui-kit-v2-skeleton-wrapper.mjs.map +1 -0
  136. package/fesm2022/rt-tools-ui-kit-v2-skeleton.mjs +123 -0
  137. package/fesm2022/rt-tools-ui-kit-v2-skeleton.mjs.map +1 -0
  138. package/fesm2022/rt-tools-ui-kit-v2-spinner.mjs +70 -0
  139. package/fesm2022/rt-tools-ui-kit-v2-spinner.mjs.map +1 -0
  140. package/fesm2022/rt-tools-ui-kit-v2-split-button.mjs +92 -0
  141. package/fesm2022/rt-tools-ui-kit-v2-split-button.mjs.map +1 -0
  142. package/fesm2022/rt-tools-ui-kit-v2-stat-tile.mjs +147 -0
  143. package/fesm2022/rt-tools-ui-kit-v2-stat-tile.mjs.map +1 -0
  144. package/fesm2022/rt-tools-ui-kit-v2-stepper.mjs +117 -0
  145. package/fesm2022/rt-tools-ui-kit-v2-stepper.mjs.map +1 -0
  146. package/fesm2022/rt-tools-ui-kit-v2-table.mjs +1636 -0
  147. package/fesm2022/rt-tools-ui-kit-v2-table.mjs.map +1 -0
  148. package/fesm2022/rt-tools-ui-kit-v2-tabs.mjs +350 -0
  149. package/fesm2022/rt-tools-ui-kit-v2-tabs.mjs.map +1 -0
  150. package/fesm2022/rt-tools-ui-kit-v2-tag.mjs +122 -0
  151. package/fesm2022/rt-tools-ui-kit-v2-tag.mjs.map +1 -0
  152. package/fesm2022/rt-tools-ui-kit-v2-textarea.mjs +85 -0
  153. package/fesm2022/rt-tools-ui-kit-v2-textarea.mjs.map +1 -0
  154. package/fesm2022/rt-tools-ui-kit-v2-theme-toggle.mjs +73 -0
  155. package/fesm2022/rt-tools-ui-kit-v2-theme-toggle.mjs.map +1 -0
  156. package/fesm2022/rt-tools-ui-kit-v2-thread-list.mjs +196 -0
  157. package/fesm2022/rt-tools-ui-kit-v2-thread-list.mjs.map +1 -0
  158. package/fesm2022/rt-tools-ui-kit-v2-timeline.mjs +39 -0
  159. package/fesm2022/rt-tools-ui-kit-v2-timeline.mjs.map +1 -0
  160. package/fesm2022/rt-tools-ui-kit-v2-toast.mjs +338 -0
  161. package/fesm2022/rt-tools-ui-kit-v2-toast.mjs.map +1 -0
  162. package/fesm2022/rt-tools-ui-kit-v2-toggle-button-group.mjs +132 -0
  163. package/fesm2022/rt-tools-ui-kit-v2-toggle-button-group.mjs.map +1 -0
  164. package/fesm2022/rt-tools-ui-kit-v2-toggle-switch.mjs +162 -0
  165. package/fesm2022/rt-tools-ui-kit-v2-toggle-switch.mjs.map +1 -0
  166. package/fesm2022/rt-tools-ui-kit-v2-toolbar.mjs +135 -0
  167. package/fesm2022/rt-tools-ui-kit-v2-toolbar.mjs.map +1 -0
  168. package/fesm2022/rt-tools-ui-kit-v2-tooltip.mjs +214 -0
  169. package/fesm2022/rt-tools-ui-kit-v2-tooltip.mjs.map +1 -0
  170. package/fesm2022/rt-tools-ui-kit-v2-welcome-dialog.mjs +64 -0
  171. package/fesm2022/rt-tools-ui-kit-v2-welcome-dialog.mjs.map +1 -0
  172. package/fesm2022/rt-tools-ui-kit-v2-workspace-details.mjs +263 -0
  173. package/fesm2022/rt-tools-ui-kit-v2-workspace-details.mjs.map +1 -0
  174. package/fesm2022/rt-tools-ui-kit-v2-workspace.mjs +296 -0
  175. package/fesm2022/rt-tools-ui-kit-v2-workspace.mjs.map +1 -0
  176. package/fesm2022/rt-tools-ui-kit-v2.mjs +91 -23819
  177. package/fesm2022/rt-tools-ui-kit-v2.mjs.map +1 -1
  178. package/package.json +349 -1
  179. package/rt-tools-ui-kit-v2-0.18.0.tgz +0 -0
  180. package/src/lib/components/dot-field/CONTEXT.md +31 -0
  181. package/src/lib/components/dot-field/rt-dot-field.component.scss +20 -0
  182. package/src/lib/components/dot-field/stories/component/CONTEXT.md +14 -0
  183. package/src/lib/components/dot-field/stories/component/test-dot-field.component.scss +31 -0
  184. package/src/lib/components/field/CONTEXT.md +18 -2
  185. package/src/lib/components/select/rt-select.component.scss +4 -0
  186. package/src/styles/_semantic.scss +1 -1
  187. package/styles/tokens.css +8 -8
  188. package/types/rt-tools-ui-kit-v2-accordion.d.ts +30 -0
  189. package/types/rt-tools-ui-kit-v2-action-bar.d.ts +140 -0
  190. package/types/rt-tools-ui-kit-v2-aside-section.d.ts +25 -0
  191. package/types/rt-tools-ui-kit-v2-aside.d.ts +436 -0
  192. package/types/rt-tools-ui-kit-v2-autocomplete.d.ts +78 -0
  193. package/types/rt-tools-ui-kit-v2-bar-list.d.ts +41 -0
  194. package/types/rt-tools-ui-kit-v2-bottom-sheet.d.ts +20 -0
  195. package/types/rt-tools-ui-kit-v2-button.d.ts +76 -0
  196. package/types/rt-tools-ui-kit-v2-calendar.d.ts +96 -0
  197. package/types/rt-tools-ui-kit-v2-card.d.ts +38 -0
  198. package/types/rt-tools-ui-kit-v2-checkbox.d.ts +46 -0
  199. package/types/rt-tools-ui-kit-v2-collapsible-text.d.ts +20 -0
  200. package/types/rt-tools-ui-kit-v2-confirm-popover.d.ts +85 -0
  201. package/types/rt-tools-ui-kit-v2-container.d.ts +425 -0
  202. package/types/rt-tools-ui-kit-v2-core.d.ts +1222 -0
  203. package/types/rt-tools-ui-kit-v2-counter-row.d.ts +22 -0
  204. package/types/rt-tools-ui-kit-v2-counter.d.ts +70 -0
  205. package/types/rt-tools-ui-kit-v2-data-list.d.ts +334 -0
  206. package/types/rt-tools-ui-kit-v2-data-table.d.ts +494 -0
  207. package/types/rt-tools-ui-kit-v2-date-picker.d.ts +181 -0
  208. package/types/rt-tools-ui-kit-v2-date-range.d.ts +98 -0
  209. package/types/rt-tools-ui-kit-v2-delta-view.d.ts +20 -0
  210. package/types/rt-tools-ui-kit-v2-detail-list.d.ts +33 -0
  211. package/types/rt-tools-ui-kit-v2-dialog.d.ts +287 -0
  212. package/types/rt-tools-ui-kit-v2-dot-field.d.ts +17 -0
  213. package/types/rt-tools-ui-kit-v2-download-link.d.ts +17 -0
  214. package/types/rt-tools-ui-kit-v2-dynamic-list.d.ts +139 -0
  215. package/types/rt-tools-ui-kit-v2-dynamic-selector.d.ts +384 -0
  216. package/types/rt-tools-ui-kit-v2-empty-state.d.ts +29 -0
  217. package/types/rt-tools-ui-kit-v2-expansion-panel.d.ts +57 -0
  218. package/types/rt-tools-ui-kit-v2-field.d.ts +82 -0
  219. package/types/rt-tools-ui-kit-v2-file-card.d.ts +114 -0
  220. package/types/rt-tools-ui-kit-v2-file-drop.d.ts +75 -0
  221. package/types/rt-tools-ui-kit-v2-file-input.d.ts +48 -0
  222. package/types/rt-tools-ui-kit-v2-file-list.d.ts +13 -0
  223. package/types/rt-tools-ui-kit-v2-filter-control.d.ts +72 -0
  224. package/types/rt-tools-ui-kit-v2-form-control.d.ts +74 -0
  225. package/types/rt-tools-ui-kit-v2-header.d.ts +40 -0
  226. package/types/rt-tools-ui-kit-v2-icon-button.d.ts +113 -0
  227. package/types/rt-tools-ui-kit-v2-icon.d.ts +238 -0
  228. package/types/rt-tools-ui-kit-v2-image-cropper.d.ts +168 -0
  229. package/types/rt-tools-ui-kit-v2-image-upload.d.ts +102 -0
  230. package/types/rt-tools-ui-kit-v2-info-item.d.ts +13 -0
  231. package/types/rt-tools-ui-kit-v2-input-number.d.ts +67 -0
  232. package/types/rt-tools-ui-kit-v2-input.d.ts +54 -0
  233. package/types/rt-tools-ui-kit-v2-live-badge.d.ts +23 -0
  234. package/types/rt-tools-ui-kit-v2-logo.d.ts +58 -0
  235. package/types/rt-tools-ui-kit-v2-markdown-text.d.ts +30 -0
  236. package/types/rt-tools-ui-kit-v2-menu.d.ts +217 -0
  237. package/types/rt-tools-ui-kit-v2-message.d.ts +56 -0
  238. package/types/rt-tools-ui-kit-v2-money-list.d.ts +34 -0
  239. package/types/rt-tools-ui-kit-v2-multiselect.d.ts +93 -0
  240. package/types/rt-tools-ui-kit-v2-night-grid.d.ts +39 -0
  241. package/types/rt-tools-ui-kit-v2-note.d.ts +21 -0
  242. package/types/rt-tools-ui-kit-v2-notifications-bell.d.ts +23 -0
  243. package/types/rt-tools-ui-kit-v2-page-header.d.ts +173 -0
  244. package/types/rt-tools-ui-kit-v2-pagination.d.ts +64 -0
  245. package/types/rt-tools-ui-kit-v2-photo-viewer.d.ts +98 -0
  246. package/types/rt-tools-ui-kit-v2-popover.d.ts +79 -0
  247. package/types/rt-tools-ui-kit-v2-radio-button.d.ts +61 -0
  248. package/types/rt-tools-ui-kit-v2-radius.d.ts +37 -0
  249. package/types/rt-tools-ui-kit-v2-ripple.d.ts +39 -0
  250. package/types/rt-tools-ui-kit-v2-scroll-area.d.ts +91 -0
  251. package/types/rt-tools-ui-kit-v2-section-nav.d.ts +23 -0
  252. package/types/rt-tools-ui-kit-v2-select.d.ts +215 -0
  253. package/types/rt-tools-ui-kit-v2-side-menu.d.ts +483 -0
  254. package/types/rt-tools-ui-kit-v2-skeleton-wrapper.d.ts +32 -0
  255. package/types/rt-tools-ui-kit-v2-skeleton.d.ts +41 -0
  256. package/types/rt-tools-ui-kit-v2-spinner.d.ts +56 -0
  257. package/types/rt-tools-ui-kit-v2-split-button.d.ts +72 -0
  258. package/types/rt-tools-ui-kit-v2-stat-tile.d.ts +81 -0
  259. package/types/rt-tools-ui-kit-v2-stepper.d.ts +51 -0
  260. package/types/rt-tools-ui-kit-v2-table.d.ts +739 -0
  261. package/types/rt-tools-ui-kit-v2-tabs.d.ts +153 -0
  262. package/types/rt-tools-ui-kit-v2-tag.d.ts +70 -0
  263. package/types/rt-tools-ui-kit-v2-textarea.d.ts +36 -0
  264. package/types/rt-tools-ui-kit-v2-theme-toggle.d.ts +43 -0
  265. package/types/rt-tools-ui-kit-v2-thread-list.d.ts +111 -0
  266. package/types/rt-tools-ui-kit-v2-timeline.d.ts +35 -0
  267. package/types/rt-tools-ui-kit-v2-toast.d.ts +103 -0
  268. package/types/rt-tools-ui-kit-v2-toggle-button-group.d.ts +109 -0
  269. package/types/rt-tools-ui-kit-v2-toggle-switch.d.ts +85 -0
  270. package/types/rt-tools-ui-kit-v2-toolbar.d.ts +66 -0
  271. package/types/rt-tools-ui-kit-v2-tooltip.d.ts +74 -0
  272. package/types/rt-tools-ui-kit-v2-welcome-dialog.d.ts +33 -0
  273. package/types/rt-tools-ui-kit-v2-workspace-details.d.ts +128 -0
  274. package/types/rt-tools-ui-kit-v2-workspace.d.ts +84 -0
  275. package/types/rt-tools-ui-kit-v2.d.ts +87 -9599
  276. package/rt-tools-ui-kit-v2-0.17.0.tgz +0 -0
@@ -0,0 +1,937 @@
1
+ import * as i0 from '@angular/core';
2
+ import { inject, signal, input, booleanAttribute, output, ViewEncapsulation, ChangeDetectionStrategy, Component, TemplateRef, Directive, Injector, viewChild, ElementRef, contentChild, computed, afterNextRender, forwardRef, DestroyRef, viewChildren, model } from '@angular/core';
3
+ import * as i1 from '@angular/forms';
4
+ import { FormsModule } from '@angular/forms';
5
+ import { BlockDirective, ElemDirective, ModDirective } from '@rt-tools/core';
6
+ import { BreakpointsService, rtKitLabel, RtInfiniteScrollDirective } from '@rt-tools/ui-kit-v2/core';
7
+ import { RtButtonDirective } from '@rt-tools/ui-kit-v2/button';
8
+ import { RtEmptyStateComponent } from '@rt-tools/ui-kit-v2/empty-state';
9
+ import { RtFormControlBase } from '@rt-tools/ui-kit-v2/form-control';
10
+ import { RtInputComponent } from '@rt-tools/ui-kit-v2/input';
11
+ import { CdkDrag, CdkDragHandle, CdkDropList } from '@angular/cdk/drag-drop';
12
+ import { NgTemplateOutlet } from '@angular/common';
13
+ import { RtIconButtonComponent } from '@rt-tools/ui-kit-v2/icon-button';
14
+ import { RtTooltipDirective } from '@rt-tools/ui-kit-v2/tooltip';
15
+ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
16
+ import { RouterLink } from '@angular/router';
17
+ import { Subject, debounceTime } from 'rxjs';
18
+ import { RtCheckboxComponent } from '@rt-tools/ui-kit-v2/checkbox';
19
+ import { RtIconComponent } from '@rt-tools/ui-kit-v2/icon';
20
+ import { RtRadioButtonComponent } from '@rt-tools/ui-kit-v2/radio-button';
21
+ import { RtSpinnerComponent } from '@rt-tools/ui-kit-v2/spinner';
22
+ import { RtToggleSwitchComponent } from '@rt-tools/ui-kit-v2/toggle-switch';
23
+ import { RtPopoverDirective } from '@rt-tools/ui-kit-v2/popover';
24
+
25
+ const BEM_BLOCK$3 = 'rt-dynamic-selector-list';
26
+ /**
27
+ * Список выбранного семьи динамических селекторов: строки с удалением, ручкой перетаскивания и
28
+ * правкой, под ними полоса с кнопкой добавления вызывающего, сбросом и очисткой. Значения список
29
+ * не держит: он сообщает, что человек сделал, а селектор и поле списка строк решают, что из этого
30
+ * выходит.
31
+ */
32
+ class RtDynamicSelectorListComponent {
33
+ constructor() {
34
+ this.#breakpoints = inject(BreakpointsService);
35
+ /** На узком экране подсказки кнопок не показываются: наведения там нет. */
36
+ this.isNarrow = this.#breakpoints.narrow;
37
+ this.dragLabel = rtKitLabel('dynamicSelectorDrag');
38
+ this.removeLabel = rtKitLabel('dynamicSelectorRemove');
39
+ this.editLabel = rtKitLabel('dynamicSelectorEdit');
40
+ this.applyLabel = rtKitLabel('dynamicSelectorApply');
41
+ this.cancelLabel = rtKitLabel('uiCancel');
42
+ this.resetLabel = rtKitLabel('dynamicSelectorReset');
43
+ this.clearLabel = rtKitLabel('dynamicSelectorClear');
44
+ /** Строка, открытая для правки, и текст в её поле. */
45
+ this.editedIndex = signal(null, /* @ts-ignore */
46
+ ...(ngDevMode ? [{ debugName: "editedIndex" }] : /* istanbul ignore next */ []));
47
+ this.draft = signal('', /* @ts-ignore */
48
+ ...(ngDevMode ? [{ debugName: "draft" }] : /* istanbul ignore next */ []));
49
+ this.rows = input([], /* @ts-ignore */
50
+ ...(ngDevMode ? [{ debugName: "rows" }] : /* istanbul ignore next */ []));
51
+ this.draggable = input(false, { ...(ngDevMode ? { debugName: "draggable" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
52
+ this.editable = input(false, { ...(ngDevMode ? { debugName: "editable" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
53
+ this.disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
54
+ /** Полоса под строками; приглашение вызывающего встаёт на её место. */
55
+ this.actionsShown = input(true, { ...(ngDevMode ? { debugName: "actionsShown" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
56
+ /** Сброс и очистка в полосе; без них в полосе остаётся кнопка добавления. */
57
+ this.resetClearShown = input(true, { ...(ngDevMode ? { debugName: "resetClearShown" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
58
+ /** Корзина строк; без неё строки двигаются и правятся, но не убираются. */
59
+ this.removeShown = input(true, { ...(ngDevMode ? { debugName: "removeShown" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
60
+ this.resetDisabled = input(true, { ...(ngDevMode ? { debugName: "resetDisabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
61
+ this.clearDisabled = input(true, { ...(ngDevMode ? { debugName: "clearDisabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
62
+ /** Шаг скругления кнопок-иконок списка; по умолчанию они круглые. */
63
+ this.buttonRadius = input('full', /* @ts-ignore */
64
+ ...(ngDevMode ? [{ debugName: "buttonRadius" }] : /* istanbul ignore next */ []));
65
+ this.titleTpl = input(null, /* @ts-ignore */
66
+ ...(ngDevMode ? [{ debugName: "titleTpl" }] : /* istanbul ignore next */ []));
67
+ this.controlsTpl = input(null, /* @ts-ignore */
68
+ ...(ngDevMode ? [{ debugName: "controlsTpl" }] : /* istanbul ignore next */ []));
69
+ this.removed = output();
70
+ this.moved = output();
71
+ this.edited = output();
72
+ this.resetClicked = output();
73
+ this.cleared = output();
74
+ }
75
+ #breakpoints;
76
+ /** Строка, взятая из чужого списка, ничего не меняет; брошенная на своё место — тоже. */
77
+ onDrop(event) {
78
+ if (event.previousContainer !== event.container || event.previousIndex === event.currentIndex) {
79
+ return;
80
+ }
81
+ this.moved.emit({ from: event.previousIndex, to: event.currentIndex });
82
+ }
83
+ onRemove(row) {
84
+ if (!row.locked && !this.disabled()) {
85
+ this.removed.emit(row.key);
86
+ }
87
+ }
88
+ onEditStart(index, row) {
89
+ this.draft.set(row.label);
90
+ this.editedIndex.set(index);
91
+ }
92
+ onEditApply(row) {
93
+ this.edited.emit({ previous: row.label, next: this.draft() });
94
+ this.editedIndex.set(null);
95
+ }
96
+ onEditCancel() {
97
+ this.editedIndex.set(null);
98
+ }
99
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: RtDynamicSelectorListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
100
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: RtDynamicSelectorListComponent, isStandalone: true, selector: "rt-dynamic-selector-list", inputs: { rows: { classPropertyName: "rows", publicName: "rows", isSignal: true, isRequired: false, transformFunction: null }, draggable: { classPropertyName: "draggable", publicName: "draggable", isSignal: true, isRequired: false, transformFunction: null }, editable: { classPropertyName: "editable", publicName: "editable", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, actionsShown: { classPropertyName: "actionsShown", publicName: "actionsShown", isSignal: true, isRequired: false, transformFunction: null }, resetClearShown: { classPropertyName: "resetClearShown", publicName: "resetClearShown", isSignal: true, isRequired: false, transformFunction: null }, removeShown: { classPropertyName: "removeShown", publicName: "removeShown", isSignal: true, isRequired: false, transformFunction: null }, resetDisabled: { classPropertyName: "resetDisabled", publicName: "resetDisabled", isSignal: true, isRequired: false, transformFunction: null }, clearDisabled: { classPropertyName: "clearDisabled", publicName: "clearDisabled", isSignal: true, isRequired: false, transformFunction: null }, buttonRadius: { classPropertyName: "buttonRadius", publicName: "buttonRadius", isSignal: true, isRequired: false, transformFunction: null }, titleTpl: { classPropertyName: "titleTpl", publicName: "titleTpl", isSignal: true, isRequired: false, transformFunction: null }, controlsTpl: { classPropertyName: "controlsTpl", publicName: "controlsTpl", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { removed: "removed", moved: "moved", edited: "edited", resetClicked: "resetClicked", cleared: "cleared" }, host: { classAttribute: "rt-dynamic-selector-list" }, ngImport: i0, template: "<ng-container rtBlock=\"rt-dynamic-selector-list\">\n @if (rows().length > 0) {\n <div rtElem=\"rows\" cdkDropList qa-dataid=\"dynamic-selector-rows\" (cdkDropListDropped)=\"onDrop($event)\">\n @for (row of rows(); track row.key; let index = $index) {\n <div\n rtElem=\"row\"\n cdkDrag\n qa-dataid=\"dynamic-selector-row\"\n [rtMod]=\"{ locked: row.locked }\"\n [cdkDragDisabled]=\"!draggable() || disabled()\">\n @if (draggable()) {\n <span rtElem=\"handle\">\n <rt-icon-button\n cdkDragHandle\n qa-dataid=\"dynamic-selector-drag\"\n icon=\"arrows\"\n size=\"sm\"\n [radius]=\"buttonRadius()\"\n [ariaLabel]=\"dragLabel()\"\n [tooltip]=\"isNarrow() ? '' : dragLabel()\"\n [disabled]=\"disabled()\" />\n </span>\n }\n\n @if (editedIndex() === index) {\n <rt-input\n rtElem=\"field\"\n qa-dataid=\"dynamic-selector-edit-field\"\n [ngModel]=\"draft()\"\n (ngModelChange)=\"draft.set($event ?? '')\"\n (keydown.enter)=\"onEditApply(row)\" />\n } @else if (titleTpl(); as tpl) {\n <div rtElem=\"title\">\n <ng-container [ngTemplateOutlet]=\"tpl\" [ngTemplateOutletContext]=\"{ $implicit: row.item }\" />\n </div>\n } @else {\n <span rtElem=\"title\">{{ row.label }}</span>\n }\n\n <div rtElem=\"controls\">\n @if (controlsTpl(); as tpl) {\n <ng-container [ngTemplateOutlet]=\"tpl\" [ngTemplateOutletContext]=\"{ $implicit: row.item }\" />\n }\n\n @if (editable()) {\n @if (editedIndex() === index) {\n <rt-icon-button\n qa-dataid=\"dynamic-selector-edit-cancel\"\n icon=\"undo\"\n size=\"sm\"\n [radius]=\"buttonRadius()\"\n [ariaLabel]=\"cancelLabel()\"\n [tooltip]=\"isNarrow() ? '' : cancelLabel()\"\n (clicked)=\"onEditCancel()\" />\n <rt-icon-button\n qa-dataid=\"dynamic-selector-edit-apply\"\n icon=\"check\"\n size=\"sm\"\n [radius]=\"buttonRadius()\"\n [ariaLabel]=\"applyLabel()\"\n [tooltip]=\"isNarrow() ? '' : applyLabel()\"\n (clicked)=\"onEditApply(row)\" />\n } @else {\n <rt-icon-button\n qa-dataid=\"dynamic-selector-edit\"\n icon=\"pencil\"\n size=\"sm\"\n [radius]=\"buttonRadius()\"\n [ariaLabel]=\"editLabel()\"\n [tooltip]=\"isNarrow() ? '' : editLabel()\"\n [disabled]=\"disabled()\"\n (clicked)=\"onEditStart(index, row)\" />\n }\n }\n\n @if (removeShown()) {\n <rt-icon-button\n qa-dataid=\"dynamic-selector-remove\"\n icon=\"trash\"\n size=\"sm\"\n [radius]=\"buttonRadius()\"\n [iconColor]=\"row.locked || disabled() ? 'muted' : 'danger'\"\n [ariaLabel]=\"removeLabel()\"\n [tooltip]=\"isNarrow() ? '' : removeLabel()\"\n [disabled]=\"row.locked || disabled()\"\n (clicked)=\"onRemove(row)\" />\n }\n </div>\n </div>\n }\n </div>\n }\n\n @if (actionsShown()) {\n <div rtElem=\"actions\">\n <div rtElem=\"add\">\n <ng-content />\n </div>\n\n @if (resetClearShown()) {\n <rt-icon-button\n qa-dataid=\"dynamic-selector-reset\"\n icon=\"refresh\"\n size=\"sm\"\n [radius]=\"buttonRadius()\"\n [iconColor]=\"resetDisabled() || disabled() ? 'muted' : 'current'\"\n [ariaLabel]=\"resetLabel()\"\n [tooltip]=\"isNarrow() ? '' : resetLabel()\"\n [disabled]=\"resetDisabled() || disabled()\"\n (clicked)=\"resetClicked.emit()\" />\n <rt-icon-button\n qa-dataid=\"dynamic-selector-clear\"\n icon=\"close\"\n size=\"sm\"\n [radius]=\"buttonRadius()\"\n [iconColor]=\"clearDisabled() || disabled() ? 'muted' : 'danger'\"\n [ariaLabel]=\"clearLabel()\"\n [tooltip]=\"isNarrow() ? '' : clearLabel()\"\n [disabled]=\"clearDisabled() || disabled()\"\n (clicked)=\"cleared.emit()\" />\n }\n </div>\n }\n</ng-container>\n", styles: ["@charset \"UTF-8\";@layer rt-kit.components{.rt-dynamic-selector-list{--rt-dynamic-selector-list-row-bg: var(--rt-color-action-primary-subtle);--rt-dynamic-selector-list-row-radius: var(--rt-radius-sm);--rt-dynamic-selector-list-divider-width: var(--rt-border-width-thin);--rt-dynamic-selector-list-drag-shadow: var(--rt-shadow-md);--rt-dynamic-selector-list-drag-duration: var(--rt-duration-base);display:flex;flex-direction:column;gap:var(--rt-space-2xs)}.rt-dynamic-selector-list__rows{display:flex;flex-direction:column;gap:var(--rt-space-sm)}.rt-dynamic-selector-list__row{display:flex;min-height:var(--rt-control-height-lg);box-sizing:border-box;align-items:center;padding:var(--rt-space-2xs) var(--rt-space-2xs) var(--rt-space-2xs) var(--rt-space-sm);border-radius:var(--rt-dynamic-selector-list-row-radius);background:var(--rt-dynamic-selector-list-row-bg);color:var(--rt-color-text-primary);gap:var(--rt-space-sm)}.rt-dynamic-selector-list__handle{border-right:var(--rt-dynamic-selector-list-divider-width) solid var(--rt-color-border-default);cursor:grab;padding-inline-end:var(--rt-space-2xs)}.rt-dynamic-selector-list__title{min-width:0;flex:1 1 auto;font-size:var(--rt-text-md);overflow-wrap:anywhere}.rt-dynamic-selector-list__field{min-width:0;flex:1 1 auto}.rt-dynamic-selector-list__controls{display:flex;flex:0 0 auto;align-items:center;gap:var(--rt-space-2xs)}.rt-dynamic-selector-list__actions{display:flex;align-items:center;gap:var(--rt-space-2xs)}.rt-dynamic-selector-list__add{display:flex;min-width:0;flex:1 1 auto;align-items:center}.rt-dynamic-selector-list__row.cdk-drag-preview{--rt-dynamic-selector-list-row-bg: var(--rt-color-action-primary-subtle);--rt-dynamic-selector-list-row-radius: var(--rt-radius-sm);--rt-dynamic-selector-list-divider-width: var(--rt-border-width-thin);--rt-dynamic-selector-list-drag-shadow: var(--rt-shadow-md);box-shadow:var(--rt-dynamic-selector-list-drag-shadow)}.rt-dynamic-selector-list__row.cdk-drag-placeholder{opacity:0}.rt-dynamic-selector-list__row.cdk-drag-animating,.rt-dynamic-selector-list__rows.cdk-drop-list-dragging .rt-dynamic-selector-list__row:not(.cdk-drag-placeholder){transition:transform var(--rt-dynamic-selector-list-drag-duration) ease-out}}.rt-dynamic-selector-list__row.cdk-drag-preview{padding:var(--rt-space-2xs) var(--rt-space-2xs) var(--rt-space-2xs) var(--rt-space-sm);background-color:var(--rt-color-bg-surface);background-image:linear-gradient(var(--rt-dynamic-selector-list-row-bg),var(--rt-dynamic-selector-list-row-bg));color:var(--rt-color-text-primary)}\n"], dependencies: [{ kind: "ngmodule", type:
101
+ // Angular
102
+ FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type:
103
+ // CDK
104
+ CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: CdkDragHandle, selector: "[cdkDragHandle]", inputs: ["cdkDragHandleDisabled"] }, { kind: "directive", type: CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer", "cdkDropListHasAnchor"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type:
105
+ // standalone components / directives
106
+ BlockDirective, selector: "[rtBlock]", inputs: ["rtMod"] }, { kind: "directive", type: ElemDirective, selector: "[rtElem]", inputs: ["rtMod"] }, { kind: "directive", type: ModDirective, selector: "[rtMod]" }, { kind: "component", type: RtIconButtonComponent, selector: "rt-icon-button", inputs: ["icon", "glyph", "ariaLabel", "variant", "iconColor", "iconFill", "size", "iconSize", "type", "tooltip", "tabIndex", "loading", "disabled", "active", "indicator"], outputs: ["clicked"] }, { kind: "component", type: RtInputComponent, selector: "rt-input", inputs: ["appearance", "type", "placeholder", "iconLeft", "iconRight", "passwordToggle", "autocomplete"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
107
+ }
108
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: RtDynamicSelectorListComponent, decorators: [{
109
+ type: Component,
110
+ args: [{ selector: 'rt-dynamic-selector-list', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [
111
+ // Angular
112
+ FormsModule,
113
+ NgTemplateOutlet,
114
+ // CDK
115
+ CdkDrag,
116
+ CdkDragHandle,
117
+ CdkDropList,
118
+ // standalone components / directives
119
+ BlockDirective,
120
+ ElemDirective,
121
+ ModDirective,
122
+ RtIconButtonComponent,
123
+ RtInputComponent,
124
+ RtTooltipDirective,
125
+ ], host: { class: BEM_BLOCK$3 }, template: "<ng-container rtBlock=\"rt-dynamic-selector-list\">\n @if (rows().length > 0) {\n <div rtElem=\"rows\" cdkDropList qa-dataid=\"dynamic-selector-rows\" (cdkDropListDropped)=\"onDrop($event)\">\n @for (row of rows(); track row.key; let index = $index) {\n <div\n rtElem=\"row\"\n cdkDrag\n qa-dataid=\"dynamic-selector-row\"\n [rtMod]=\"{ locked: row.locked }\"\n [cdkDragDisabled]=\"!draggable() || disabled()\">\n @if (draggable()) {\n <span rtElem=\"handle\">\n <rt-icon-button\n cdkDragHandle\n qa-dataid=\"dynamic-selector-drag\"\n icon=\"arrows\"\n size=\"sm\"\n [radius]=\"buttonRadius()\"\n [ariaLabel]=\"dragLabel()\"\n [tooltip]=\"isNarrow() ? '' : dragLabel()\"\n [disabled]=\"disabled()\" />\n </span>\n }\n\n @if (editedIndex() === index) {\n <rt-input\n rtElem=\"field\"\n qa-dataid=\"dynamic-selector-edit-field\"\n [ngModel]=\"draft()\"\n (ngModelChange)=\"draft.set($event ?? '')\"\n (keydown.enter)=\"onEditApply(row)\" />\n } @else if (titleTpl(); as tpl) {\n <div rtElem=\"title\">\n <ng-container [ngTemplateOutlet]=\"tpl\" [ngTemplateOutletContext]=\"{ $implicit: row.item }\" />\n </div>\n } @else {\n <span rtElem=\"title\">{{ row.label }}</span>\n }\n\n <div rtElem=\"controls\">\n @if (controlsTpl(); as tpl) {\n <ng-container [ngTemplateOutlet]=\"tpl\" [ngTemplateOutletContext]=\"{ $implicit: row.item }\" />\n }\n\n @if (editable()) {\n @if (editedIndex() === index) {\n <rt-icon-button\n qa-dataid=\"dynamic-selector-edit-cancel\"\n icon=\"undo\"\n size=\"sm\"\n [radius]=\"buttonRadius()\"\n [ariaLabel]=\"cancelLabel()\"\n [tooltip]=\"isNarrow() ? '' : cancelLabel()\"\n (clicked)=\"onEditCancel()\" />\n <rt-icon-button\n qa-dataid=\"dynamic-selector-edit-apply\"\n icon=\"check\"\n size=\"sm\"\n [radius]=\"buttonRadius()\"\n [ariaLabel]=\"applyLabel()\"\n [tooltip]=\"isNarrow() ? '' : applyLabel()\"\n (clicked)=\"onEditApply(row)\" />\n } @else {\n <rt-icon-button\n qa-dataid=\"dynamic-selector-edit\"\n icon=\"pencil\"\n size=\"sm\"\n [radius]=\"buttonRadius()\"\n [ariaLabel]=\"editLabel()\"\n [tooltip]=\"isNarrow() ? '' : editLabel()\"\n [disabled]=\"disabled()\"\n (clicked)=\"onEditStart(index, row)\" />\n }\n }\n\n @if (removeShown()) {\n <rt-icon-button\n qa-dataid=\"dynamic-selector-remove\"\n icon=\"trash\"\n size=\"sm\"\n [radius]=\"buttonRadius()\"\n [iconColor]=\"row.locked || disabled() ? 'muted' : 'danger'\"\n [ariaLabel]=\"removeLabel()\"\n [tooltip]=\"isNarrow() ? '' : removeLabel()\"\n [disabled]=\"row.locked || disabled()\"\n (clicked)=\"onRemove(row)\" />\n }\n </div>\n </div>\n }\n </div>\n }\n\n @if (actionsShown()) {\n <div rtElem=\"actions\">\n <div rtElem=\"add\">\n <ng-content />\n </div>\n\n @if (resetClearShown()) {\n <rt-icon-button\n qa-dataid=\"dynamic-selector-reset\"\n icon=\"refresh\"\n size=\"sm\"\n [radius]=\"buttonRadius()\"\n [iconColor]=\"resetDisabled() || disabled() ? 'muted' : 'current'\"\n [ariaLabel]=\"resetLabel()\"\n [tooltip]=\"isNarrow() ? '' : resetLabel()\"\n [disabled]=\"resetDisabled() || disabled()\"\n (clicked)=\"resetClicked.emit()\" />\n <rt-icon-button\n qa-dataid=\"dynamic-selector-clear\"\n icon=\"close\"\n size=\"sm\"\n [radius]=\"buttonRadius()\"\n [iconColor]=\"clearDisabled() || disabled() ? 'muted' : 'danger'\"\n [ariaLabel]=\"clearLabel()\"\n [tooltip]=\"isNarrow() ? '' : clearLabel()\"\n [disabled]=\"clearDisabled() || disabled()\"\n (clicked)=\"cleared.emit()\" />\n }\n </div>\n }\n</ng-container>\n", styles: ["@charset \"UTF-8\";@layer rt-kit.components{.rt-dynamic-selector-list{--rt-dynamic-selector-list-row-bg: var(--rt-color-action-primary-subtle);--rt-dynamic-selector-list-row-radius: var(--rt-radius-sm);--rt-dynamic-selector-list-divider-width: var(--rt-border-width-thin);--rt-dynamic-selector-list-drag-shadow: var(--rt-shadow-md);--rt-dynamic-selector-list-drag-duration: var(--rt-duration-base);display:flex;flex-direction:column;gap:var(--rt-space-2xs)}.rt-dynamic-selector-list__rows{display:flex;flex-direction:column;gap:var(--rt-space-sm)}.rt-dynamic-selector-list__row{display:flex;min-height:var(--rt-control-height-lg);box-sizing:border-box;align-items:center;padding:var(--rt-space-2xs) var(--rt-space-2xs) var(--rt-space-2xs) var(--rt-space-sm);border-radius:var(--rt-dynamic-selector-list-row-radius);background:var(--rt-dynamic-selector-list-row-bg);color:var(--rt-color-text-primary);gap:var(--rt-space-sm)}.rt-dynamic-selector-list__handle{border-right:var(--rt-dynamic-selector-list-divider-width) solid var(--rt-color-border-default);cursor:grab;padding-inline-end:var(--rt-space-2xs)}.rt-dynamic-selector-list__title{min-width:0;flex:1 1 auto;font-size:var(--rt-text-md);overflow-wrap:anywhere}.rt-dynamic-selector-list__field{min-width:0;flex:1 1 auto}.rt-dynamic-selector-list__controls{display:flex;flex:0 0 auto;align-items:center;gap:var(--rt-space-2xs)}.rt-dynamic-selector-list__actions{display:flex;align-items:center;gap:var(--rt-space-2xs)}.rt-dynamic-selector-list__add{display:flex;min-width:0;flex:1 1 auto;align-items:center}.rt-dynamic-selector-list__row.cdk-drag-preview{--rt-dynamic-selector-list-row-bg: var(--rt-color-action-primary-subtle);--rt-dynamic-selector-list-row-radius: var(--rt-radius-sm);--rt-dynamic-selector-list-divider-width: var(--rt-border-width-thin);--rt-dynamic-selector-list-drag-shadow: var(--rt-shadow-md);box-shadow:var(--rt-dynamic-selector-list-drag-shadow)}.rt-dynamic-selector-list__row.cdk-drag-placeholder{opacity:0}.rt-dynamic-selector-list__row.cdk-drag-animating,.rt-dynamic-selector-list__rows.cdk-drop-list-dragging .rt-dynamic-selector-list__row:not(.cdk-drag-placeholder){transition:transform var(--rt-dynamic-selector-list-drag-duration) ease-out}}.rt-dynamic-selector-list__row.cdk-drag-preview{padding:var(--rt-space-2xs) var(--rt-space-2xs) var(--rt-space-2xs) var(--rt-space-sm);background-color:var(--rt-color-bg-surface);background-image:linear-gradient(var(--rt-dynamic-selector-list-row-bg),var(--rt-dynamic-selector-list-row-bg));color:var(--rt-color-text-primary)}\n"] }]
126
+ }], propDecorators: { rows: [{ type: i0.Input, args: [{ isSignal: true, alias: "rows", required: false }] }], draggable: [{ type: i0.Input, args: [{ isSignal: true, alias: "draggable", required: false }] }], editable: [{ type: i0.Input, args: [{ isSignal: true, alias: "editable", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], actionsShown: [{ type: i0.Input, args: [{ isSignal: true, alias: "actionsShown", required: false }] }], resetClearShown: [{ type: i0.Input, args: [{ isSignal: true, alias: "resetClearShown", required: false }] }], removeShown: [{ type: i0.Input, args: [{ isSignal: true, alias: "removeShown", required: false }] }], resetDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "resetDisabled", required: false }] }], clearDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearDisabled", required: false }] }], buttonRadius: [{ type: i0.Input, args: [{ isSignal: true, alias: "buttonRadius", required: false }] }], titleTpl: [{ type: i0.Input, args: [{ isSignal: true, alias: "titleTpl", required: false }] }], controlsTpl: [{ type: i0.Input, args: [{ isSignal: true, alias: "controlsTpl", required: false }] }], removed: [{ type: i0.Output, args: ["removed"] }], moved: [{ type: i0.Output, args: ["moved"] }], edited: [{ type: i0.Output, args: ["edited"] }], resetClicked: [{ type: i0.Output, args: ["resetClicked"] }], cleared: [{ type: i0.Output, args: ["cleared"] }] } });
127
+
128
+ /**
129
+ * Маркеры частей строки списка выбранного — своим файлом, как у соседних семей.
130
+ *
131
+ * Маркер держит свой шаблон и о списке не знает ничего: селектор и поле списка строк читают его
132
+ * среди своего содержимого и отдают шаблон списку. Удаление и ручка перетаскивания остаются
133
+ * за китом.
134
+ */
135
+ /**
136
+ * Свои кнопки у каждой строки: стоят перед кнопкой удаления.
137
+ *
138
+ * @example
139
+ * ```html
140
+ * <rt-dynamic-selector keyExp="id" displayExp="name" [entities]="people()">
141
+ * <ng-template rtDynamicSelectorRowControls let-person>
142
+ * <rt-icon-button icon="info" ariaLabel="About" (clicked)="open(person)" />
143
+ * </ng-template>
144
+ * </rt-dynamic-selector>
145
+ * ```
146
+ */
147
+ class RtDynamicSelectorRowControlsDirective {
148
+ constructor() {
149
+ this.templateRef = inject(TemplateRef);
150
+ }
151
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: RtDynamicSelectorRowControlsDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
152
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.1.6", type: RtDynamicSelectorRowControlsDirective, isStandalone: true, selector: "[rtDynamicSelectorRowControls]", ngImport: i0 }); }
153
+ }
154
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: RtDynamicSelectorRowControlsDirective, decorators: [{
155
+ type: Directive,
156
+ args: [{
157
+ selector: '[rtDynamicSelectorRowControls]',
158
+ }]
159
+ }] });
160
+ /** Своё название строки вместо подписи из поля записи. */
161
+ class RtDynamicSelectorRowTitleDirective {
162
+ constructor() {
163
+ this.templateRef = inject(TemplateRef);
164
+ }
165
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: RtDynamicSelectorRowTitleDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
166
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.1.6", type: RtDynamicSelectorRowTitleDirective, isStandalone: true, selector: "[rtDynamicSelectorRowTitle]", ngImport: i0 }); }
167
+ }
168
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: RtDynamicSelectorRowTitleDirective, decorators: [{
169
+ type: Directive,
170
+ args: [{
171
+ selector: '[rtDynamicSelectorRowTitle]',
172
+ }]
173
+ }] });
174
+
175
+ /** Подпись пункта строкой: число приводится, всё прочее подписью не считается. */
176
+ function dynamicSelectorLabel(item, labelOf) {
177
+ const label = labelOf(item);
178
+ return typeof label === 'string' || typeof label === 'number' ? String(label) : null;
179
+ }
180
+ /**
181
+ * Совпадает ли подпись с запросом. Запрос режется по пробелам, и каждое слово обязано найтись в
182
+ * подписи без учёта регистра: «отчёт март» находит «Март, отчёт по складу».
183
+ */
184
+ function dynamicSelectorMatches(label, query) {
185
+ const words = query.toLowerCase().trim().split(/\s+/).filter(Boolean);
186
+ const text = label.toLowerCase();
187
+ return words.every((word) => text.includes(word));
188
+ }
189
+ /**
190
+ * Пункты, которые можно выбрать: без уже выбранных, без пунктов без подписи и, если запрос есть,
191
+ * только совпавшие. Порядок — функция сортировки приложения, а без неё — по алфавиту подписи.
192
+ */
193
+ function selectableDynamicItems(items, chosenKeys, keyOf, labelOf, query, sortFn) {
194
+ const chosen = new Set(chosenKeys);
195
+ const found = items.filter((item) => {
196
+ const label = dynamicSelectorLabel(item, labelOf);
197
+ return label !== null && !chosen.has(keyOf(item)) && dynamicSelectorMatches(label, query);
198
+ });
199
+ return found.sort(sortFn ?? ((a, b) => (dynamicSelectorLabel(a, labelOf) ?? '').localeCompare(dynamicSelectorLabel(b, labelOf) ?? '')));
200
+ }
201
+ /** Ключ добавлен или снят. Повторно добавленный ключ не удваивается. */
202
+ function toggleDynamicKey(keys, key, checked) {
203
+ if (checked) {
204
+ return keys.includes(key) ? [...keys] : [...keys, key];
205
+ }
206
+ return keys.filter((item) => item !== key);
207
+ }
208
+ /** Состояние флажка «Выбрать всё» по видимым пунктам. */
209
+ function dynamicSelectAllState(visibleKeys, pickedKeys) {
210
+ const picked = visibleKeys.filter((key) => pickedKeys.includes(key)).length;
211
+ if (picked === 0) {
212
+ return 'none';
213
+ }
214
+ return picked === visibleKeys.length ? 'all' : 'some';
215
+ }
216
+ /**
217
+ * «Выбрать всё» добавляет к отмеченному все видимые пункты, снятие — убирает видимые и оставляет
218
+ * отмеченное вне запроса.
219
+ */
220
+ function selectAllDynamicKeys(visibleKeys, pickedKeys, checked) {
221
+ if (!checked) {
222
+ return pickedKeys.filter((key) => !visibleKeys.includes(key));
223
+ }
224
+ return [...pickedKeys, ...visibleKeys.filter((key) => !pickedKeys.includes(key))];
225
+ }
226
+ /** «Очистить» оставляет только ключи только для чтения, в их прежнем порядке. */
227
+ function clearDynamicKeys(keys, readonlyKeys) {
228
+ return keys.filter((key) => readonlyKeys.includes(key));
229
+ }
230
+ /** Строка перетащена на новое место. Индексы вне списка приводятся к его краям. */
231
+ function moveDynamicKey(keys, from, to) {
232
+ const list = [...keys];
233
+ const last = list.length - 1;
234
+ if (from < 0 || from > last) {
235
+ return list;
236
+ }
237
+ const moved = list.splice(from, 1);
238
+ list.splice(Math.min(Math.max(to, 0), last), 0, ...moved);
239
+ return list;
240
+ }
241
+ /** Совпадают ли два набора ключей с учётом порядка: так «Сбросить» узнаёт, что сбрасывать нечего. */
242
+ function sameDynamicKeys(a, b) {
243
+ return a.length === b.length && a.every((key, index) => key === b[index]);
244
+ }
245
+ /** Совпадают ли два набора ключей без учёта порядка: так «Очистить» узнаёт, что чистить нечего. */
246
+ function sameDynamicKeySet(a, b) {
247
+ const set = new Set(b);
248
+ return a.length === set.size && a.every((key) => set.has(key));
249
+ }
250
+ /** Строка поля списка строк: пустая и повторная не добавляются, пробелы по краям срезаются. */
251
+ function addDynamicText(values, raw) {
252
+ const text = (raw ?? '').trim();
253
+ return text === '' || values.includes(text) ? [...values] : [...values, text];
254
+ }
255
+ /**
256
+ * Строка поля списка строк исправлена на месте. Пустая правка и правка в уже существующую строку
257
+ * список не меняют: иначе строка пропала бы или удвоилась.
258
+ */
259
+ function renameDynamicText(values, previous, next) {
260
+ const text = (next ?? '').trim();
261
+ if (text === '' || text === previous || values.includes(text)) {
262
+ return [...values];
263
+ }
264
+ return values.map((value) => (value === previous ? text : value));
265
+ }
266
+ /** Ключ последней видимой закреплённой строки: под ней стоит разделитель. Порядок строк не меняется. */
267
+ function lastPinnedDynamicKey(rows, pinnedKeys, keyOf) {
268
+ for (let index = rows.length - 1; index >= 0; index -= 1) {
269
+ const key = keyOf(rows[index]);
270
+ if (pinnedKeys.includes(key)) {
271
+ return key;
272
+ }
273
+ }
274
+ return null;
275
+ }
276
+ /**
277
+ * Строки всплывающего выбора во время поиска: отмеченные раньше стоят над найденными и не пропадают
278
+ * оттого, что запрос перестал с ними совпадать. Без запроса отмеченные остаются на своих местах.
279
+ */
280
+ function dynamicPopupRows(offered, found, ticked, keyOf, query) {
281
+ if (query.trim() === '') {
282
+ return { ticked: [], found: [...found] };
283
+ }
284
+ const tickedRows = ticked
285
+ .map((key) => offered.find((item) => keyOf(item) === key))
286
+ .filter((item) => item !== undefined);
287
+ return { ticked: tickedRows, found: found.filter((item) => !ticked.includes(keyOf(item))) };
288
+ }
289
+
290
+ const BEM_BLOCK$2 = 'rt-dynamic-input';
291
+ /**
292
+ * Поле списка строк: строки человек набирает сам. Значение — массив строк в порядке списка.
293
+ * Enter или уход из поля добавляют срезанный по краям текст в конец; пустой и повторный не
294
+ * добавляются. Сброс, очистка, удаление строки и перетаскивание — те же, что у селектора.
295
+ *
296
+ * @example
297
+ * ```html
298
+ * <rt-dynamic-input editable [formControl]="tags" />
299
+ * ```
300
+ */
301
+ class RtDynamicInputComponent extends RtFormControlBase {
302
+ constructor() {
303
+ super(...arguments);
304
+ this.#injector = inject(Injector);
305
+ /** Последнее значение, записанное формой: к нему возвращает сброс. */
306
+ this.#initial = signal([], /* @ts-ignore */
307
+ ...(ngDevMode ? [{ debugName: "#initial" }] : /* istanbul ignore next */ []));
308
+ this.addLabel = rtKitLabel('dynamicSelectorAdd');
309
+ this.placeholderLabel = rtKitLabel('dynamicInputPlaceholder');
310
+ this.field = viewChild('field', { ...(ngDevMode ? { debugName: "field" } : /* istanbul ignore next */ {}), read: ElementRef });
311
+ this.rowControls = contentChild(RtDynamicSelectorRowControlsDirective, /* @ts-ignore */
312
+ ...(ngDevMode ? [{ debugName: "rowControls" }] : /* istanbul ignore next */ []));
313
+ this.controlsTpl = computed(() => this.rowControls()?.templateRef ?? null, /* @ts-ignore */
314
+ ...(ngDevMode ? [{ debugName: "controlsTpl" }] : /* istanbul ignore next */ []));
315
+ /** Поле набора открыто, и в нём текст. */
316
+ this.isFieldShown = signal(false, /* @ts-ignore */
317
+ ...(ngDevMode ? [{ debugName: "isFieldShown" }] : /* istanbul ignore next */ []));
318
+ this.draft = signal('', /* @ts-ignore */
319
+ ...(ngDevMode ? [{ debugName: "draft" }] : /* istanbul ignore next */ []));
320
+ /** Приглашение снимается нажатием его кнопки и до новой записи формы не возвращается. */
321
+ this.isInvitationDismissed = signal(false, /* @ts-ignore */
322
+ ...(ngDevMode ? [{ debugName: "isInvitationDismissed" }] : /* istanbul ignore next */ []));
323
+ this.rows = computed(() => {
324
+ const locked = this.readonlyKeys();
325
+ return this.value().map((text) => ({
326
+ item: text,
327
+ key: text,
328
+ label: text,
329
+ locked: locked.includes(text),
330
+ }));
331
+ }, /* @ts-ignore */
332
+ ...(ngDevMode ? [{ debugName: "rows" }] : /* istanbul ignore next */ []));
333
+ this.isInvitationShown = computed(() => this.invitation() && !this.isInvitationDismissed(), /* @ts-ignore */
334
+ ...(ngDevMode ? [{ debugName: "isInvitationShown" }] : /* istanbul ignore next */ []));
335
+ this.isAddShown = computed(() => !this.isFieldShown(), /* @ts-ignore */
336
+ ...(ngDevMode ? [{ debugName: "isAddShown" }] : /* istanbul ignore next */ []));
337
+ this.isKeysReset = computed(() => sameDynamicKeys(this.value(), this.#initial()), /* @ts-ignore */
338
+ ...(ngDevMode ? [{ debugName: "isKeysReset" }] : /* istanbul ignore next */ []));
339
+ this.isKeysClear = computed(() => clearDynamicKeys(this.value(), this.readonlyKeys()).length === this.value().length, /* @ts-ignore */
340
+ ...(ngDevMode ? [{ debugName: "isKeysClear" }] : /* istanbul ignore next */ []));
341
+ /** Правки в шаблоне строки держат сброс и очистку включёнными, даже когда строки не менялись. */
342
+ this.isResetDisabled = computed(() => !this.extraChanged() && this.isKeysReset(), /* @ts-ignore */
343
+ ...(ngDevMode ? [{ debugName: "isResetDisabled" }] : /* istanbul ignore next */ []));
344
+ this.isClearDisabled = computed(() => !this.extraChanged() && this.isKeysClear(), /* @ts-ignore */
345
+ ...(ngDevMode ? [{ debugName: "isClearDisabled" }] : /* istanbul ignore next */ []));
346
+ this.addTitle = computed(() => this.buttonTitle() || this.addLabel(), /* @ts-ignore */
347
+ ...(ngDevMode ? [{ debugName: "addTitle" }] : /* istanbul ignore next */ []));
348
+ this.fieldPlaceholder = computed(() => this.placeholder() || this.placeholderLabel(), /* @ts-ignore */
349
+ ...(ngDevMode ? [{ debugName: "fieldPlaceholder" }] : /* istanbul ignore next */ []));
350
+ this.hasValue = computed(() => this.value().length > 0, /* @ts-ignore */
351
+ ...(ngDevMode ? [{ debugName: "hasValue" }] : /* istanbul ignore next */ []));
352
+ this.buttonTitle = input('', /* @ts-ignore */
353
+ ...(ngDevMode ? [{ debugName: "buttonTitle" }] : /* istanbul ignore next */ []));
354
+ this.placeholder = input('', /* @ts-ignore */
355
+ ...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
356
+ /** Строки, которые нельзя убрать из списка. */
357
+ this.readonlyKeys = input([], /* @ts-ignore */
358
+ ...(ngDevMode ? [{ debugName: "readonlyKeys" }] : /* istanbul ignore next */ []));
359
+ this.draggable = input(false, { ...(ngDevMode ? { debugName: "draggable" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
360
+ /** Шаг скругления кнопок-иконок списка; по умолчанию они круглые. */
361
+ this.buttonRadius = input('full', /* @ts-ignore */
362
+ ...(ngDevMode ? [{ debugName: "buttonRadius" }] : /* istanbul ignore next */ []));
363
+ this.editable = input(false, { ...(ngDevMode ? { debugName: "editable" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
364
+ this.invitation = input(false, { ...(ngDevMode ? { debugName: "invitation" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
365
+ this.invitationIcon = input(null, /* @ts-ignore */
366
+ ...(ngDevMode ? [{ debugName: "invitationIcon" }] : /* istanbul ignore next */ []));
367
+ this.invitationDescription = input('', /* @ts-ignore */
368
+ ...(ngDevMode ? [{ debugName: "invitationDescription" }] : /* istanbul ignore next */ []));
369
+ /** Корзина строк; без неё строки убирает только очистка или сам вызывающий. */
370
+ this.removeShown = input(true, { ...(ngDevMode ? { debugName: "removeShown" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
371
+ /** Сброс и очистка под списком: `false` их убирает, кнопка добавления остаётся. */
372
+ this.listActionsShown = input(true, { ...(ngDevMode ? { debugName: "listActionsShown" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
373
+ /**
374
+ * Строки правлены в шаблоне вызывающего: сброс и очистка включены и тогда, когда строки прежние.
375
+ * Сброс сообщает `listReset`, очистка — `listCleared`, и вызывающий снимает свои правки.
376
+ */
377
+ this.extraChanged = input(false, { ...(ngDevMode ? { debugName: "extraChanged" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
378
+ this.listReset = output();
379
+ this.listCleared = output();
380
+ this.displayText = computed(() => this.value().join(', '), /* @ts-ignore */
381
+ ...(ngDevMode ? [{ debugName: "displayText" }] : /* istanbul ignore next */ []));
382
+ }
383
+ #injector;
384
+ /** Последнее значение, записанное формой: к нему возвращает сброс. */
385
+ #initial;
386
+ /** Записанное формой становится и списком, и значением для сброса; пустой массив список опустошает. */
387
+ writeValue(value) {
388
+ super.writeValue(value === null ? null : [...value]);
389
+ this.#initial.set([...this.value()]);
390
+ this.isInvitationDismissed.set(false);
391
+ }
392
+ onAdd() {
393
+ if (this.isDisabled()) {
394
+ return;
395
+ }
396
+ this.isInvitationDismissed.set(true);
397
+ this.draft.set('');
398
+ this.isFieldShown.set(true);
399
+ afterNextRender(() => this.field()?.nativeElement.querySelector('input')?.focus(), { injector: this.#injector });
400
+ }
401
+ /** Enter или уход из поля: пустой текст поле не закрывает, повторный закрывает без изменений. */
402
+ onCommit() {
403
+ if (!this.isFieldShown() || this.draft().trim() === '') {
404
+ return;
405
+ }
406
+ const next = addDynamicText(this.value(), this.draft());
407
+ this.draft.set('');
408
+ this.isFieldShown.set(false);
409
+ this.markTouched();
410
+ if (next.length !== this.value().length) {
411
+ this.#change(next);
412
+ }
413
+ }
414
+ onRemoved(key) {
415
+ if (!this.isDisabled() && typeof key === 'string' && !this.readonlyKeys().includes(key)) {
416
+ this.#change(this.value().filter((text) => text !== key));
417
+ }
418
+ }
419
+ onMoved(move) {
420
+ if (!this.isDisabled()) {
421
+ this.#change(moveDynamicKey(this.value(), move.from, move.to));
422
+ }
423
+ }
424
+ onEdited(edit) {
425
+ const next = renameDynamicText(this.value(), edit.previous, edit.next);
426
+ if (!this.isDisabled() && !sameDynamicKeys(next, this.value())) {
427
+ this.#change(next);
428
+ }
429
+ }
430
+ onReset() {
431
+ if (this.isDisabled() || this.isResetDisabled()) {
432
+ return;
433
+ }
434
+ // Строки прежние, а правки только в шаблоне: значение не трогаем, сообщаем о сбросе.
435
+ if (!this.isKeysReset()) {
436
+ this.#change([...this.#initial()]);
437
+ }
438
+ this.listReset.emit();
439
+ }
440
+ onCleared() {
441
+ if (this.isDisabled() || this.isClearDisabled()) {
442
+ return;
443
+ }
444
+ if (!this.isKeysClear()) {
445
+ this.#change(clearDynamicKeys(this.value(), this.readonlyKeys()));
446
+ }
447
+ this.listCleared.emit();
448
+ }
449
+ getEmptyValue() {
450
+ return [];
451
+ }
452
+ focusAfterClear() {
453
+ // Очистка крестиком у поля не ставится: фокус остаётся там, где был.
454
+ }
455
+ #change(values) {
456
+ this.value.set(values);
457
+ this.emitChange(values);
458
+ }
459
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: RtDynamicInputComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
460
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: RtDynamicInputComponent, isStandalone: true, selector: "rt-dynamic-input", inputs: { buttonTitle: { classPropertyName: "buttonTitle", publicName: "buttonTitle", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, readonlyKeys: { classPropertyName: "readonlyKeys", publicName: "readonlyKeys", isSignal: true, isRequired: false, transformFunction: null }, draggable: { classPropertyName: "draggable", publicName: "draggable", isSignal: true, isRequired: false, transformFunction: null }, buttonRadius: { classPropertyName: "buttonRadius", publicName: "buttonRadius", isSignal: true, isRequired: false, transformFunction: null }, editable: { classPropertyName: "editable", publicName: "editable", isSignal: true, isRequired: false, transformFunction: null }, invitation: { classPropertyName: "invitation", publicName: "invitation", isSignal: true, isRequired: false, transformFunction: null }, invitationIcon: { classPropertyName: "invitationIcon", publicName: "invitationIcon", isSignal: true, isRequired: false, transformFunction: null }, invitationDescription: { classPropertyName: "invitationDescription", publicName: "invitationDescription", isSignal: true, isRequired: false, transformFunction: null }, removeShown: { classPropertyName: "removeShown", publicName: "removeShown", isSignal: true, isRequired: false, transformFunction: null }, listActionsShown: { classPropertyName: "listActionsShown", publicName: "listActionsShown", isSignal: true, isRequired: false, transformFunction: null }, extraChanged: { classPropertyName: "extraChanged", publicName: "extraChanged", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { listReset: "listReset", listCleared: "listCleared" }, host: { classAttribute: "rt-dynamic-input" }, providers: [
461
+ // Алиас базового токена — для contentChild(RtFormControlBase) в rt-field.
462
+ { provide: RtFormControlBase, useExisting: forwardRef(() => RtDynamicInputComponent) },
463
+ ], queries: [{ propertyName: "rowControls", first: true, predicate: RtDynamicSelectorRowControlsDirective, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "field", first: true, predicate: ["field"], descendants: true, read: ElementRef, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<ng-container rtBlock=\"rt-dynamic-input\">\n <rt-dynamic-selector-list\n [rows]=\"rows()\"\n [draggable]=\"draggable()\"\n [buttonRadius]=\"buttonRadius()\"\n [editable]=\"editable()\"\n [disabled]=\"isDisabled()\"\n [actionsShown]=\"!isInvitationShown()\"\n [resetClearShown]=\"listActionsShown()\"\n [removeShown]=\"removeShown()\"\n [resetDisabled]=\"isResetDisabled()\"\n [clearDisabled]=\"isClearDisabled()\"\n [controlsTpl]=\"controlsTpl()\"\n (removed)=\"onRemoved($event)\"\n (moved)=\"onMoved($event)\"\n (edited)=\"onEdited($event)\"\n (resetClicked)=\"onReset()\"\n (cleared)=\"onCleared()\">\n @if (isAddShown()) {\n <button\n rtButton\n appearance=\"text\"\n type=\"button\"\n qa-dataid=\"dynamic-input-add\"\n [label]=\"addTitle()\"\n [attr.aria-label]=\"addTitle()\"\n [disabled]=\"isDisabled()\"\n (click)=\"onAdd()\"></button>\n }\n </rt-dynamic-selector-list>\n\n @if (isFieldShown()) {\n <rt-input\n #field\n rtElem=\"field\"\n qa-dataid=\"dynamic-input-field\"\n [placeholder]=\"fieldPlaceholder()\"\n [ngModel]=\"draft()\"\n (ngModelChange)=\"draft.set($event ?? '')\"\n (keydown.enter)=\"onCommit()\"\n (focusout)=\"onCommit()\" />\n }\n\n @if (isInvitationShown()) {\n <rt-empty-state\n rtElem=\"invitation\"\n qa-dataid=\"dynamic-input-invitation\"\n [icon]=\"invitationIcon()\"\n [description]=\"invitationDescription()\">\n <button\n rtButton\n appearance=\"outlined\"\n type=\"button\"\n qa-dataid=\"dynamic-input-invitation-add\"\n [label]=\"addTitle()\"\n [attr.aria-label]=\"addTitle()\"\n [disabled]=\"isDisabled()\"\n (click)=\"onAdd()\"></button>\n </rt-empty-state>\n }\n</ng-container>\n", styles: ["@charset \"UTF-8\";@layer rt-kit.components{.rt-dynamic-input{display:flex;width:100%;flex-direction:column;gap:var(--rt-space-sm)}.rt-dynamic-input__field,.rt-dynamic-input__invitation{display:block}}\n"], dependencies: [{ kind: "ngmodule", type:
464
+ // Angular
465
+ FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type:
466
+ // standalone components / directives
467
+ BlockDirective, selector: "[rtBlock]", inputs: ["rtMod"] }, { kind: "directive", type: ElemDirective, selector: "[rtElem]", inputs: ["rtMod"] }, { kind: "directive", type: RtButtonDirective, selector: "button[rtButton], a[rtButton]", inputs: ["label", "icon", "iconPos", "theme", "appearance", "size", "loading", "loadingIcon", "loadingLabel", "pressed"] }, { kind: "component", type: RtDynamicSelectorListComponent, selector: "rt-dynamic-selector-list", inputs: ["rows", "draggable", "editable", "disabled", "actionsShown", "resetClearShown", "removeShown", "resetDisabled", "clearDisabled", "buttonRadius", "titleTpl", "controlsTpl"], outputs: ["removed", "moved", "edited", "resetClicked", "cleared"] }, { kind: "component", type: RtEmptyStateComponent, selector: "rt-empty-state", inputs: ["icon", "glyph", "title", "description", "framed"] }, { kind: "component", type: RtInputComponent, selector: "rt-input", inputs: ["appearance", "type", "placeholder", "iconLeft", "iconRight", "passwordToggle", "autocomplete"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
468
+ }
469
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: RtDynamicInputComponent, decorators: [{
470
+ type: Component,
471
+ args: [{ selector: 'rt-dynamic-input', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [
472
+ // Angular
473
+ FormsModule,
474
+ // standalone components / directives
475
+ BlockDirective,
476
+ ElemDirective,
477
+ RtButtonDirective,
478
+ RtDynamicSelectorListComponent,
479
+ RtEmptyStateComponent,
480
+ RtInputComponent,
481
+ ], providers: [
482
+ // Алиас базового токена — для contentChild(RtFormControlBase) в rt-field.
483
+ { provide: RtFormControlBase, useExisting: forwardRef(() => RtDynamicInputComponent) },
484
+ ], host: { class: BEM_BLOCK$2 }, template: "<ng-container rtBlock=\"rt-dynamic-input\">\n <rt-dynamic-selector-list\n [rows]=\"rows()\"\n [draggable]=\"draggable()\"\n [buttonRadius]=\"buttonRadius()\"\n [editable]=\"editable()\"\n [disabled]=\"isDisabled()\"\n [actionsShown]=\"!isInvitationShown()\"\n [resetClearShown]=\"listActionsShown()\"\n [removeShown]=\"removeShown()\"\n [resetDisabled]=\"isResetDisabled()\"\n [clearDisabled]=\"isClearDisabled()\"\n [controlsTpl]=\"controlsTpl()\"\n (removed)=\"onRemoved($event)\"\n (moved)=\"onMoved($event)\"\n (edited)=\"onEdited($event)\"\n (resetClicked)=\"onReset()\"\n (cleared)=\"onCleared()\">\n @if (isAddShown()) {\n <button\n rtButton\n appearance=\"text\"\n type=\"button\"\n qa-dataid=\"dynamic-input-add\"\n [label]=\"addTitle()\"\n [attr.aria-label]=\"addTitle()\"\n [disabled]=\"isDisabled()\"\n (click)=\"onAdd()\"></button>\n }\n </rt-dynamic-selector-list>\n\n @if (isFieldShown()) {\n <rt-input\n #field\n rtElem=\"field\"\n qa-dataid=\"dynamic-input-field\"\n [placeholder]=\"fieldPlaceholder()\"\n [ngModel]=\"draft()\"\n (ngModelChange)=\"draft.set($event ?? '')\"\n (keydown.enter)=\"onCommit()\"\n (focusout)=\"onCommit()\" />\n }\n\n @if (isInvitationShown()) {\n <rt-empty-state\n rtElem=\"invitation\"\n qa-dataid=\"dynamic-input-invitation\"\n [icon]=\"invitationIcon()\"\n [description]=\"invitationDescription()\">\n <button\n rtButton\n appearance=\"outlined\"\n type=\"button\"\n qa-dataid=\"dynamic-input-invitation-add\"\n [label]=\"addTitle()\"\n [attr.aria-label]=\"addTitle()\"\n [disabled]=\"isDisabled()\"\n (click)=\"onAdd()\"></button>\n </rt-empty-state>\n }\n</ng-container>\n", styles: ["@charset \"UTF-8\";@layer rt-kit.components{.rt-dynamic-input{display:flex;width:100%;flex-direction:column;gap:var(--rt-space-sm)}.rt-dynamic-input__field,.rt-dynamic-input__invitation{display:block}}\n"] }]
485
+ }], propDecorators: { field: [{ type: i0.ViewChild, args: ['field', { ...{ read: ElementRef }, isSignal: true }] }], rowControls: [{ type: i0.ContentChild, args: [i0.forwardRef(() => RtDynamicSelectorRowControlsDirective), { isSignal: true }] }], buttonTitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "buttonTitle", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], readonlyKeys: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonlyKeys", required: false }] }], draggable: [{ type: i0.Input, args: [{ isSignal: true, alias: "draggable", required: false }] }], buttonRadius: [{ type: i0.Input, args: [{ isSignal: true, alias: "buttonRadius", required: false }] }], editable: [{ type: i0.Input, args: [{ isSignal: true, alias: "editable", required: false }] }], invitation: [{ type: i0.Input, args: [{ isSignal: true, alias: "invitation", required: false }] }], invitationIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "invitationIcon", required: false }] }], invitationDescription: [{ type: i0.Input, args: [{ isSignal: true, alias: "invitationDescription", required: false }] }], removeShown: [{ type: i0.Input, args: [{ isSignal: true, alias: "removeShown", required: false }] }], listActionsShown: [{ type: i0.Input, args: [{ isSignal: true, alias: "listActionsShown", required: false }] }], extraChanged: [{ type: i0.Input, args: [{ isSignal: true, alias: "extraChanged", required: false }] }], listReset: [{ type: i0.Output, args: ["listReset"] }], listCleared: [{ type: i0.Output, args: ["listCleared"] }] } });
486
+
487
+ const BEM_BLOCK$1 = 'rt-dynamic-selector-popup';
488
+ /** Сколько ждёт поиск на сервере после последней нажатой клавиши. */
489
+ const RT_DYNAMIC_SELECTOR_SEARCH_DEBOUNCE = 500;
490
+ /**
491
+ * Всплывающий выбор динамического селектора: поиск, флажки или переключатели, «Выбрать всё»,
492
+ * догрузка при прокрутке, «Отмена» и «Применить». Отметки живут в самом окне и уходят наружу
493
+ * только по «Применить»: окно создаётся заново при каждом открытии, и закрытие их сбрасывает.
494
+ */
495
+ class RtDynamicSelectorPopupComponent {
496
+ constructor() {
497
+ this.#destroyRef = inject(DestroyRef);
498
+ this.#searchSource = new Subject();
499
+ this.searchLabel = rtKitLabel('dynamicSelectorSearch');
500
+ this.selectAllLabel = rtKitLabel('uiSelectAll');
501
+ this.multiLabel = rtKitLabel('dynamicSelectorMulti');
502
+ this.multiHintLabel = rtKitLabel('dynamicSelectorMultiHint');
503
+ this.noResultsLabel = rtKitLabel('dynamicSelectorNoResults');
504
+ this.cancelLabel = rtKitLabel('uiCancel');
505
+ this.applyLabel = rtKitLabel('dynamicSelectorApply');
506
+ /** Отмеченные ключи — ещё не применённые. */
507
+ this.ticked = signal([], /* @ts-ignore */
508
+ ...(ngDevMode ? [{ debugName: "ticked" }] : /* istanbul ignore next */ []));
509
+ this.query = signal('', /* @ts-ignore */
510
+ ...(ngDevMode ? [{ debugName: "query" }] : /* istanbul ignore next */ []));
511
+ /** Выбор нескольких включён: без него простое нажатие оставляет одну отметку. */
512
+ this.isMultiOn = signal(false, /* @ts-ignore */
513
+ ...(ngDevMode ? [{ debugName: "isMultiOn" }] : /* istanbul ignore next */ []));
514
+ /** Найденные строки: местный поиск отбирает сам, серверный отдаёт запрос наружу. */
515
+ this.found = computed(() => {
516
+ const query = this.query();
517
+ if (!this.localSearch() || query.trim() === '') {
518
+ return [...this.entities()];
519
+ }
520
+ return this.entities().filter((item) => {
521
+ const label = dynamicSelectorLabel(item, (entity) => this.#labelOf(entity));
522
+ return label !== null && dynamicSelectorMatches(label, query);
523
+ });
524
+ }, /* @ts-ignore */
525
+ ...(ngDevMode ? [{ debugName: "found" }] : /* istanbul ignore next */ []));
526
+ this.rows = computed(() => dynamicPopupRows(this.entities(), this.found(), this.ticked(), (item) => this.#keyOf(item), this.query()), /* @ts-ignore */
527
+ ...(ngDevMode ? [{ debugName: "rows" }] : /* istanbul ignore next */ []));
528
+ this.visibleKeys = computed(() => [...this.rows().ticked, ...this.rows().found].map((item) => this.#keyOf(item)), /* @ts-ignore */
529
+ ...(ngDevMode ? [{ debugName: "visibleKeys" }] : /* istanbul ignore next */ []));
530
+ /** Строки для разметки: отмеченные раньше над разделителем, найденные — под ним. */
531
+ this.rowItems = computed(() => {
532
+ const ticked = this.ticked();
533
+ const lastPinned = this.lastPinnedKey();
534
+ const { ticked: above, found } = this.rows();
535
+ const toRow = (item, separated) => ({
536
+ entity: item,
537
+ key: this.#keyOf(item),
538
+ label: dynamicSelectorLabel(item, (entity) => this.#labelOf(entity)) ?? '',
539
+ ticked: ticked.includes(this.#keyOf(item)),
540
+ separated,
541
+ });
542
+ return [
543
+ ...above.map((item, index) => toRow(item, index === above.length - 1)),
544
+ ...found.map((item) => toRow(item, lastPinned !== null && this.#keyOf(item) === lastPinned)),
545
+ ];
546
+ }, /* @ts-ignore */
547
+ ...(ngDevMode ? [{ debugName: "rowItems" }] : /* istanbul ignore next */ []));
548
+ this.hasRows = computed(() => this.visibleKeys().length > 0, /* @ts-ignore */
549
+ ...(ngDevMode ? [{ debugName: "hasRows" }] : /* istanbul ignore next */ []));
550
+ this.selectAllState = computed(() => dynamicSelectAllState(this.visibleKeys(), this.ticked()), /* @ts-ignore */
551
+ ...(ngDevMode ? [{ debugName: "selectAllState" }] : /* istanbul ignore next */ []));
552
+ this.isSingle = computed(() => this.mode() === 'single', /* @ts-ignore */
553
+ ...(ngDevMode ? [{ debugName: "isSingle" }] : /* istanbul ignore next */ []));
554
+ this.isSelectAllShown = computed(() => !this.isSingle() && this.selectAllShown() && this.visibleKeys().length > 1 && !this.loading(), /* @ts-ignore */
555
+ ...(ngDevMode ? [{ debugName: "isSelectAllShown" }] : /* istanbul ignore next */ []));
556
+ this.isMultiToggleVisible = computed(() => !this.isSingle() && this.multiToggleShown() && this.visibleKeys().length > 1 && !this.loading(), /* @ts-ignore */
557
+ ...(ngDevMode ? [{ debugName: "isMultiToggleVisible" }] : /* istanbul ignore next */ []));
558
+ this.lastPinnedKey = computed(() => lastPinnedDynamicKey(this.rows().found, this.pinnedKeys(), (item) => this.#keyOf(item)), /* @ts-ignore */
559
+ ...(ngDevMode ? [{ debugName: "lastPinnedKey" }] : /* istanbul ignore next */ []));
560
+ this.isApplyDisabled = computed(() => this.ticked().length === 0 || this.loading(), /* @ts-ignore */
561
+ ...(ngDevMode ? [{ debugName: "isApplyDisabled" }] : /* istanbul ignore next */ []));
562
+ this.isNavShown = computed(() => !!this.navigateTitle() && !!this.navigateLink(), /* @ts-ignore */
563
+ ...(ngDevMode ? [{ debugName: "isNavShown" }] : /* istanbul ignore next */ []));
564
+ /** Предлагаемые записи: ещё не выбранные, отсортированные селектором. */
565
+ this.entities = input([], /* @ts-ignore */
566
+ ...(ngDevMode ? [{ debugName: "entities" }] : /* istanbul ignore next */ []));
567
+ this.keyExp = input.required(/* @ts-ignore */
568
+ ...(ngDevMode ? [{ debugName: "keyExp" }] : /* istanbul ignore next */ []));
569
+ this.displayExp = input.required(/* @ts-ignore */
570
+ ...(ngDevMode ? [{ debugName: "displayExp" }] : /* istanbul ignore next */ []));
571
+ this.mode = input('multi', /* @ts-ignore */
572
+ ...(ngDevMode ? [{ debugName: "mode" }] : /* istanbul ignore next */ []));
573
+ this.multiToggleShown = input(false, { ...(ngDevMode ? { debugName: "multiToggleShown" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
574
+ this.selectAllShown = input(true, { ...(ngDevMode ? { debugName: "selectAllShown" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
575
+ this.localSearch = input(true, { ...(ngDevMode ? { debugName: "localSearch" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
576
+ this.lazyLoad = input(false, { ...(ngDevMode ? { debugName: "lazyLoad" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
577
+ this.loading = input(false, { ...(ngDevMode ? { debugName: "loading" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
578
+ this.fetching = input(false, { ...(ngDevMode ? { debugName: "fetching" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
579
+ this.pinnedKeys = input([], /* @ts-ignore */
580
+ ...(ngDevMode ? [{ debugName: "pinnedKeys" }] : /* istanbul ignore next */ []));
581
+ this.navigateTitle = input('', /* @ts-ignore */
582
+ ...(ngDevMode ? [{ debugName: "navigateTitle" }] : /* istanbul ignore next */ []));
583
+ this.navigateLink = input('', /* @ts-ignore */
584
+ ...(ngDevMode ? [{ debugName: "navigateLink" }] : /* istanbul ignore next */ []));
585
+ /** Запрос, с которым выбор открывается; событием поиска он не уходит — вызывающий его знает. */
586
+ this.searchTerm = input('', /* @ts-ignore */
587
+ ...(ngDevMode ? [{ debugName: "searchTerm" }] : /* istanbul ignore next */ []));
588
+ /** Применённые ключи в порядке отметок. */
589
+ this.applied = output();
590
+ this.cancelled = output();
591
+ /** Запрос для поиска на сервере: через паузу после последней клавиши, стёртый — пустой строкой. */
592
+ this.searchChange = output();
593
+ this.loadMore = output();
594
+ /** Отмеченные записи: пустой список при открытии и текущие отметки после каждого поиска. */
595
+ this.temporaryChoiceChange = output();
596
+ }
597
+ #destroyRef;
598
+ #searchSource;
599
+ ngOnInit() {
600
+ // Выбор живёт в шаблоне и создаётся заново при каждом открытии: запрос начинается с входа.
601
+ this.query.set(this.searchTerm());
602
+ this.temporaryChoiceChange.emit([]);
603
+ this.#searchSource
604
+ .pipe(debounceTime(RT_DYNAMIC_SELECTOR_SEARCH_DEBOUNCE), takeUntilDestroyed(this.#destroyRef))
605
+ .subscribe((query) => this.searchChange.emit(query));
606
+ }
607
+ onQueryChange(value) {
608
+ const query = value ?? '';
609
+ this.query.set(query);
610
+ this.temporaryChoiceChange.emit(this.#tickedEntities());
611
+ if (!this.localSearch()) {
612
+ this.#searchSource.next(query);
613
+ }
614
+ }
615
+ /** Нажатие строки флажков: при выключенном выборе нескольких без Ctrl или Cmd остаётся одна отметка. */
616
+ onRowClick(event, item) {
617
+ const key = this.#keyOf(item);
618
+ const checked = !this.ticked().includes(key);
619
+ const addsToTicks = !this.multiToggleShown() || this.isMultiOn() || event.ctrlKey || event.metaKey;
620
+ this.ticked.update((keys) => toggleDynamicKey(addsToTicks ? keys : [], key, checked));
621
+ }
622
+ onRadioChange(item) {
623
+ this.ticked.set([this.#keyOf(item)]);
624
+ }
625
+ onSelectAll(checked) {
626
+ this.ticked.update((keys) => selectAllDynamicKeys(this.visibleKeys(), keys, checked));
627
+ }
628
+ onMultiToggle(value) {
629
+ this.isMultiOn.set(value);
630
+ }
631
+ onApply() {
632
+ if (!this.isApplyDisabled()) {
633
+ this.applied.emit([...this.ticked()]);
634
+ }
635
+ }
636
+ onCancel() {
637
+ this.cancelled.emit();
638
+ }
639
+ #tickedEntities() {
640
+ return this.ticked()
641
+ .map((key) => this.entities().find((item) => this.#keyOf(item) === key))
642
+ .filter((item) => item !== undefined);
643
+ }
644
+ /** Ключ записи — по имени поля, которое назвал вызывающий. */
645
+ #keyOf(item) {
646
+ return item[this.keyExp()];
647
+ }
648
+ /** Подпись записи — по имени поля, которое назвал вызывающий. */
649
+ #labelOf(item) {
650
+ return item[this.displayExp()];
651
+ }
652
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: RtDynamicSelectorPopupComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
653
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: RtDynamicSelectorPopupComponent, isStandalone: true, selector: "rt-dynamic-selector-popup", inputs: { entities: { classPropertyName: "entities", publicName: "entities", isSignal: true, isRequired: false, transformFunction: null }, keyExp: { classPropertyName: "keyExp", publicName: "keyExp", isSignal: true, isRequired: true, transformFunction: null }, displayExp: { classPropertyName: "displayExp", publicName: "displayExp", isSignal: true, isRequired: true, transformFunction: null }, mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null }, multiToggleShown: { classPropertyName: "multiToggleShown", publicName: "multiToggleShown", isSignal: true, isRequired: false, transformFunction: null }, selectAllShown: { classPropertyName: "selectAllShown", publicName: "selectAllShown", isSignal: true, isRequired: false, transformFunction: null }, localSearch: { classPropertyName: "localSearch", publicName: "localSearch", isSignal: true, isRequired: false, transformFunction: null }, lazyLoad: { classPropertyName: "lazyLoad", publicName: "lazyLoad", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, fetching: { classPropertyName: "fetching", publicName: "fetching", isSignal: true, isRequired: false, transformFunction: null }, pinnedKeys: { classPropertyName: "pinnedKeys", publicName: "pinnedKeys", isSignal: true, isRequired: false, transformFunction: null }, navigateTitle: { classPropertyName: "navigateTitle", publicName: "navigateTitle", isSignal: true, isRequired: false, transformFunction: null }, navigateLink: { classPropertyName: "navigateLink", publicName: "navigateLink", isSignal: true, isRequired: false, transformFunction: null }, searchTerm: { classPropertyName: "searchTerm", publicName: "searchTerm", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { applied: "applied", cancelled: "cancelled", searchChange: "searchChange", loadMore: "loadMore", temporaryChoiceChange: "temporaryChoiceChange" }, host: { classAttribute: "rt-dynamic-selector-popup" }, ngImport: i0, template: "<ng-container rtBlock=\"rt-dynamic-selector-popup\">\n <div rtElem=\"head\">\n <rt-input\n rtElem=\"search\"\n qa-dataid=\"dynamic-selector-search\"\n iconLeft=\"search\"\n [placeholder]=\"searchLabel()\"\n [ngModel]=\"query()\"\n (ngModelChange)=\"onQueryChange($event)\" />\n\n @if (isMultiToggleVisible() || isSelectAllShown()) {\n <div rtElem=\"controls\">\n @if (isMultiToggleVisible()) {\n <div rtElem=\"multi\">\n <rt-toggle-switch\n qa-dataid=\"dynamic-selector-multi\"\n [ariaLabel]=\"multiLabel()\"\n [ngModel]=\"isMultiOn()\"\n [ngModelOptions]=\"{ standalone: true }\"\n (ngModelChange)=\"onMultiToggle($event)\" />\n <span rtElem=\"multi-label\">{{ multiLabel() }}</span>\n <rt-icon rtElem=\"multi-hint-icon\" name=\"info-circle\" size=\"sm\" [rtTooltip]=\"multiHintLabel()\" />\n <span rtElem=\"multi-hint\">{{ multiHintLabel() }}</span>\n </div>\n }\n\n @if (isSelectAllShown()) {\n <rt-checkbox\n rtElem=\"select-all\"\n qa-dataid=\"dynamic-selector-select-all\"\n [indeterminate]=\"selectAllState() === 'some'\"\n [ngModel]=\"selectAllState() === 'all'\"\n [ngModelOptions]=\"{ standalone: true }\"\n (ngModelChange)=\"onSelectAll($event)\">\n {{ selectAllLabel() }}\n </rt-checkbox>\n }\n </div>\n }\n </div>\n\n @if (loading()) {\n <div rtElem=\"state\" qa-dataid=\"dynamic-selector-loading\">\n <rt-spinner [diameter]=\"24\" />\n </div>\n } @else if (hasRows()) {\n <div rtElem=\"list\" qa-dataid=\"dynamic-selector-options\">\n @for (row of rowItems(); track row.key) {\n <div rtElem=\"row\" [rtMod]=\"{ separated: row.separated }\">\n @if (isSingle()) {\n <rt-radio-button\n rtElem=\"option\"\n qa-dataid=\"dynamic-selector-option\"\n [value]=\"row.key\"\n [checked]=\"row.ticked\"\n [label]=\"row.label\"\n (checkedChange)=\"onRadioChange(row.entity)\" />\n } @else {\n <rt-checkbox\n rtElem=\"option\"\n qa-dataid=\"dynamic-selector-option\"\n [ngModel]=\"row.ticked\"\n [ngModelOptions]=\"{ standalone: true }\"\n (click)=\"onRowClick($event, row.entity)\">\n {{ row.label }}\n </rt-checkbox>\n }\n </div>\n }\n\n <div rtElem=\"sentinel\" rtInfiniteScroll [disabled]=\"!lazyLoad() || fetching()\" (loadMore)=\"loadMore.emit()\"></div>\n\n @if (fetching()) {\n <div rtElem=\"fetching\" qa-dataid=\"dynamic-selector-fetching\">\n <rt-spinner [diameter]=\"20\" />\n </div>\n }\n </div>\n } @else {\n <rt-empty-state rtElem=\"empty\" qa-dataid=\"dynamic-selector-no-results\" icon=\"search\" [title]=\"noResultsLabel()\" />\n }\n\n <div rtElem=\"foot\" [rtMod]=\"{ nav: isNavShown() }\">\n @if (isNavShown()) {\n <a rtElem=\"nav\" qa-dataid=\"dynamic-selector-nav\" [routerLink]=\"navigateLink()\" [rtTooltip]=\"navigateTitle()\">\n {{ navigateTitle() }}\n </a>\n }\n\n <div rtElem=\"actions\">\n <button\n rtButton\n appearance=\"text\"\n type=\"button\"\n qa-dataid=\"dynamic-selector-cancel\"\n [label]=\"cancelLabel()\"\n [attr.aria-label]=\"cancelLabel()\"\n (click)=\"onCancel()\"></button>\n <button\n rtButton\n type=\"button\"\n qa-dataid=\"dynamic-selector-apply\"\n [label]=\"applyLabel()\"\n [attr.aria-label]=\"applyLabel()\"\n [disabled]=\"isApplyDisabled()\"\n (click)=\"onApply()\"></button>\n </div>\n </div>\n</ng-container>\n", styles: ["@charset \"UTF-8\";@layer rt-kit.components{.rt-dynamic-selector-popup{--rt-dynamic-selector-popup-width: calc(var(--rt-size-40) * 2);--rt-dynamic-selector-popup-max-height: calc(var(--rt-size-100) + var(--rt-size-20));--rt-dynamic-selector-popup-radius: var(--rt-radius-md);--rt-dynamic-selector-popup-border-width: var(--rt-border-width-thin);--rt-dynamic-selector-popup-shadow: var(--rt-shadow-lg);display:flex;width:var(--rt-dynamic-selector-popup-width);max-width:calc(100vw - var(--rt-space-md) * 2);max-height:var(--rt-dynamic-selector-popup-max-height);box-sizing:border-box;flex-direction:column;border:var(--rt-dynamic-selector-popup-border-width) solid var(--rt-color-border-subtle);border-radius:var(--rt-dynamic-selector-popup-radius);background:var(--rt-color-bg-surface);box-shadow:var(--rt-dynamic-selector-popup-shadow);color:var(--rt-color-text-primary);gap:var(--rt-space-sm);padding-block:var(--rt-space-md)}.rt-dynamic-selector-popup__head{display:flex;flex-direction:column;gap:var(--rt-space-sm);padding-inline:var(--rt-space-md)}.rt-dynamic-selector-popup__search{display:block}.rt-dynamic-selector-popup__controls{display:flex;flex-direction:column;border-bottom:var(--rt-dynamic-selector-popup-border-width) solid var(--rt-color-border-subtle);gap:var(--rt-space-sm);padding-block-end:var(--rt-space-sm)}.rt-dynamic-selector-popup__multi{display:flex;flex-wrap:wrap;align-items:center;gap:var(--rt-space-2xs) var(--rt-space-sm)}.rt-dynamic-selector-popup__multi-label{font-size:var(--rt-text-sm)}.rt-dynamic-selector-popup__multi-hint-icon{color:var(--rt-color-text-muted)}.rt-dynamic-selector-popup__multi-hint{display:none;flex-basis:100%;color:var(--rt-color-text-muted);font-size:var(--rt-text-xs)}@media(width<=1080px){.rt-dynamic-selector-popup__multi-hint{display:block}.rt-dynamic-selector-popup__multi-hint-icon{display:none}}.rt-dynamic-selector-popup__select-all{display:block}.rt-dynamic-selector-popup__state{display:flex;align-items:center;justify-content:center;padding:var(--rt-space-md)}.rt-dynamic-selector-popup__list{display:flex;min-height:0;flex:1 1 auto;flex-direction:column;overflow-y:auto;padding-inline:var(--rt-space-md)}.rt-dynamic-selector-popup__row{display:block;padding-block:var(--rt-space-sm)}.rt-dynamic-selector-popup__row--separated{border-bottom:var(--rt-dynamic-selector-popup-border-width) solid var(--rt-color-border-subtle);margin-block-end:var(--rt-space-2xs);padding-block-end:var(--rt-space-sm)}.rt-dynamic-selector-popup__option{display:block;overflow-wrap:anywhere}.rt-dynamic-selector-popup__sentinel{min-height:var(--rt-size-1)}.rt-dynamic-selector-popup__fetching{display:flex;justify-content:center;padding-block:var(--rt-space-sm)}.rt-dynamic-selector-popup__empty{display:block;padding-inline:var(--rt-space-md)}.rt-dynamic-selector-popup__foot{display:flex;align-items:center;justify-content:flex-end;border-top:var(--rt-dynamic-selector-popup-border-width) solid var(--rt-color-border-subtle);gap:var(--rt-space-sm);padding-block-start:var(--rt-space-sm);padding-inline:var(--rt-space-md)}.rt-dynamic-selector-popup__foot--nav{justify-content:space-between}.rt-dynamic-selector-popup__nav{overflow:hidden;min-width:0;color:var(--rt-color-text-link);font-size:var(--rt-text-sm);text-overflow:ellipsis;white-space:nowrap}.rt-dynamic-selector-popup__nav:hover{color:var(--rt-color-text-link-hover)}.rt-dynamic-selector-popup__actions{display:flex;flex:0 0 auto;gap:var(--rt-space-sm)}}\n"], dependencies: [{ kind: "ngmodule", type:
654
+ // Angular
655
+ FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "browserUrl", "routerLink"] }, { kind: "directive", type:
656
+ // standalone components / directives
657
+ BlockDirective, selector: "[rtBlock]", inputs: ["rtMod"] }, { kind: "directive", type: ElemDirective, selector: "[rtElem]", inputs: ["rtMod"] }, { kind: "directive", type: ModDirective, selector: "[rtMod]" }, { kind: "directive", type: RtButtonDirective, selector: "button[rtButton], a[rtButton]", inputs: ["label", "icon", "iconPos", "theme", "appearance", "size", "loading", "loadingIcon", "loadingLabel", "pressed"] }, { kind: "component", type: RtCheckboxComponent, selector: "rt-checkbox", inputs: ["inputId", "ariaLabel", "disabled", "indeterminate"] }, { kind: "component", type: RtEmptyStateComponent, selector: "rt-empty-state", inputs: ["icon", "glyph", "title", "description", "framed"] }, { kind: "component", type: RtIconComponent, selector: "rt-icon", inputs: ["name", "glyph", "size", "color", "fill", "spin", "rotate"] }, { kind: "directive", type: RtInfiniteScrollDirective, selector: "[rtInfiniteScroll]", inputs: ["disabled", "rootMargin"], outputs: ["loadMore"] }, { kind: "component", type: RtInputComponent, selector: "rt-input", inputs: ["appearance", "type", "placeholder", "iconLeft", "iconRight", "passwordToggle", "autocomplete"] }, { kind: "component", type: RtRadioButtonComponent, selector: "rt-radio-button", inputs: ["value", "checked", "disabled", "card", "label", "description", "ariaLabel"], outputs: ["clickAction", "checkedChange"] }, { kind: "component", type: RtSpinnerComponent, selector: "rt-spinner", inputs: ["diameter", "color", "appearance", "overlay", "backdrop", "plate"] }, { kind: "component", type: RtToggleSwitchComponent, selector: "rt-toggle-switch", inputs: ["inputId", "ariaLabel", "label", "size", "iconOff", "iconOn", "disabled"] }, { kind: "directive", type: RtTooltipDirective, selector: "[rtTooltip]", inputs: ["rtTooltip", "rtTooltipPlacement", "rtTooltipWhenTruncated"], exportAs: ["rtTooltip"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
658
+ }
659
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: RtDynamicSelectorPopupComponent, decorators: [{
660
+ type: Component,
661
+ args: [{ selector: 'rt-dynamic-selector-popup', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [
662
+ // Angular
663
+ FormsModule,
664
+ RouterLink,
665
+ // standalone components / directives
666
+ BlockDirective,
667
+ ElemDirective,
668
+ ModDirective,
669
+ RtButtonDirective,
670
+ RtCheckboxComponent,
671
+ RtEmptyStateComponent,
672
+ RtIconComponent,
673
+ RtInfiniteScrollDirective,
674
+ RtInputComponent,
675
+ RtRadioButtonComponent,
676
+ RtSpinnerComponent,
677
+ RtToggleSwitchComponent,
678
+ RtTooltipDirective,
679
+ ], host: { class: BEM_BLOCK$1 }, template: "<ng-container rtBlock=\"rt-dynamic-selector-popup\">\n <div rtElem=\"head\">\n <rt-input\n rtElem=\"search\"\n qa-dataid=\"dynamic-selector-search\"\n iconLeft=\"search\"\n [placeholder]=\"searchLabel()\"\n [ngModel]=\"query()\"\n (ngModelChange)=\"onQueryChange($event)\" />\n\n @if (isMultiToggleVisible() || isSelectAllShown()) {\n <div rtElem=\"controls\">\n @if (isMultiToggleVisible()) {\n <div rtElem=\"multi\">\n <rt-toggle-switch\n qa-dataid=\"dynamic-selector-multi\"\n [ariaLabel]=\"multiLabel()\"\n [ngModel]=\"isMultiOn()\"\n [ngModelOptions]=\"{ standalone: true }\"\n (ngModelChange)=\"onMultiToggle($event)\" />\n <span rtElem=\"multi-label\">{{ multiLabel() }}</span>\n <rt-icon rtElem=\"multi-hint-icon\" name=\"info-circle\" size=\"sm\" [rtTooltip]=\"multiHintLabel()\" />\n <span rtElem=\"multi-hint\">{{ multiHintLabel() }}</span>\n </div>\n }\n\n @if (isSelectAllShown()) {\n <rt-checkbox\n rtElem=\"select-all\"\n qa-dataid=\"dynamic-selector-select-all\"\n [indeterminate]=\"selectAllState() === 'some'\"\n [ngModel]=\"selectAllState() === 'all'\"\n [ngModelOptions]=\"{ standalone: true }\"\n (ngModelChange)=\"onSelectAll($event)\">\n {{ selectAllLabel() }}\n </rt-checkbox>\n }\n </div>\n }\n </div>\n\n @if (loading()) {\n <div rtElem=\"state\" qa-dataid=\"dynamic-selector-loading\">\n <rt-spinner [diameter]=\"24\" />\n </div>\n } @else if (hasRows()) {\n <div rtElem=\"list\" qa-dataid=\"dynamic-selector-options\">\n @for (row of rowItems(); track row.key) {\n <div rtElem=\"row\" [rtMod]=\"{ separated: row.separated }\">\n @if (isSingle()) {\n <rt-radio-button\n rtElem=\"option\"\n qa-dataid=\"dynamic-selector-option\"\n [value]=\"row.key\"\n [checked]=\"row.ticked\"\n [label]=\"row.label\"\n (checkedChange)=\"onRadioChange(row.entity)\" />\n } @else {\n <rt-checkbox\n rtElem=\"option\"\n qa-dataid=\"dynamic-selector-option\"\n [ngModel]=\"row.ticked\"\n [ngModelOptions]=\"{ standalone: true }\"\n (click)=\"onRowClick($event, row.entity)\">\n {{ row.label }}\n </rt-checkbox>\n }\n </div>\n }\n\n <div rtElem=\"sentinel\" rtInfiniteScroll [disabled]=\"!lazyLoad() || fetching()\" (loadMore)=\"loadMore.emit()\"></div>\n\n @if (fetching()) {\n <div rtElem=\"fetching\" qa-dataid=\"dynamic-selector-fetching\">\n <rt-spinner [diameter]=\"20\" />\n </div>\n }\n </div>\n } @else {\n <rt-empty-state rtElem=\"empty\" qa-dataid=\"dynamic-selector-no-results\" icon=\"search\" [title]=\"noResultsLabel()\" />\n }\n\n <div rtElem=\"foot\" [rtMod]=\"{ nav: isNavShown() }\">\n @if (isNavShown()) {\n <a rtElem=\"nav\" qa-dataid=\"dynamic-selector-nav\" [routerLink]=\"navigateLink()\" [rtTooltip]=\"navigateTitle()\">\n {{ navigateTitle() }}\n </a>\n }\n\n <div rtElem=\"actions\">\n <button\n rtButton\n appearance=\"text\"\n type=\"button\"\n qa-dataid=\"dynamic-selector-cancel\"\n [label]=\"cancelLabel()\"\n [attr.aria-label]=\"cancelLabel()\"\n (click)=\"onCancel()\"></button>\n <button\n rtButton\n type=\"button\"\n qa-dataid=\"dynamic-selector-apply\"\n [label]=\"applyLabel()\"\n [attr.aria-label]=\"applyLabel()\"\n [disabled]=\"isApplyDisabled()\"\n (click)=\"onApply()\"></button>\n </div>\n </div>\n</ng-container>\n", styles: ["@charset \"UTF-8\";@layer rt-kit.components{.rt-dynamic-selector-popup{--rt-dynamic-selector-popup-width: calc(var(--rt-size-40) * 2);--rt-dynamic-selector-popup-max-height: calc(var(--rt-size-100) + var(--rt-size-20));--rt-dynamic-selector-popup-radius: var(--rt-radius-md);--rt-dynamic-selector-popup-border-width: var(--rt-border-width-thin);--rt-dynamic-selector-popup-shadow: var(--rt-shadow-lg);display:flex;width:var(--rt-dynamic-selector-popup-width);max-width:calc(100vw - var(--rt-space-md) * 2);max-height:var(--rt-dynamic-selector-popup-max-height);box-sizing:border-box;flex-direction:column;border:var(--rt-dynamic-selector-popup-border-width) solid var(--rt-color-border-subtle);border-radius:var(--rt-dynamic-selector-popup-radius);background:var(--rt-color-bg-surface);box-shadow:var(--rt-dynamic-selector-popup-shadow);color:var(--rt-color-text-primary);gap:var(--rt-space-sm);padding-block:var(--rt-space-md)}.rt-dynamic-selector-popup__head{display:flex;flex-direction:column;gap:var(--rt-space-sm);padding-inline:var(--rt-space-md)}.rt-dynamic-selector-popup__search{display:block}.rt-dynamic-selector-popup__controls{display:flex;flex-direction:column;border-bottom:var(--rt-dynamic-selector-popup-border-width) solid var(--rt-color-border-subtle);gap:var(--rt-space-sm);padding-block-end:var(--rt-space-sm)}.rt-dynamic-selector-popup__multi{display:flex;flex-wrap:wrap;align-items:center;gap:var(--rt-space-2xs) var(--rt-space-sm)}.rt-dynamic-selector-popup__multi-label{font-size:var(--rt-text-sm)}.rt-dynamic-selector-popup__multi-hint-icon{color:var(--rt-color-text-muted)}.rt-dynamic-selector-popup__multi-hint{display:none;flex-basis:100%;color:var(--rt-color-text-muted);font-size:var(--rt-text-xs)}@media(width<=1080px){.rt-dynamic-selector-popup__multi-hint{display:block}.rt-dynamic-selector-popup__multi-hint-icon{display:none}}.rt-dynamic-selector-popup__select-all{display:block}.rt-dynamic-selector-popup__state{display:flex;align-items:center;justify-content:center;padding:var(--rt-space-md)}.rt-dynamic-selector-popup__list{display:flex;min-height:0;flex:1 1 auto;flex-direction:column;overflow-y:auto;padding-inline:var(--rt-space-md)}.rt-dynamic-selector-popup__row{display:block;padding-block:var(--rt-space-sm)}.rt-dynamic-selector-popup__row--separated{border-bottom:var(--rt-dynamic-selector-popup-border-width) solid var(--rt-color-border-subtle);margin-block-end:var(--rt-space-2xs);padding-block-end:var(--rt-space-sm)}.rt-dynamic-selector-popup__option{display:block;overflow-wrap:anywhere}.rt-dynamic-selector-popup__sentinel{min-height:var(--rt-size-1)}.rt-dynamic-selector-popup__fetching{display:flex;justify-content:center;padding-block:var(--rt-space-sm)}.rt-dynamic-selector-popup__empty{display:block;padding-inline:var(--rt-space-md)}.rt-dynamic-selector-popup__foot{display:flex;align-items:center;justify-content:flex-end;border-top:var(--rt-dynamic-selector-popup-border-width) solid var(--rt-color-border-subtle);gap:var(--rt-space-sm);padding-block-start:var(--rt-space-sm);padding-inline:var(--rt-space-md)}.rt-dynamic-selector-popup__foot--nav{justify-content:space-between}.rt-dynamic-selector-popup__nav{overflow:hidden;min-width:0;color:var(--rt-color-text-link);font-size:var(--rt-text-sm);text-overflow:ellipsis;white-space:nowrap}.rt-dynamic-selector-popup__nav:hover{color:var(--rt-color-text-link-hover)}.rt-dynamic-selector-popup__actions{display:flex;flex:0 0 auto;gap:var(--rt-space-sm)}}\n"] }]
680
+ }], propDecorators: { entities: [{ type: i0.Input, args: [{ isSignal: true, alias: "entities", required: false }] }], keyExp: [{ type: i0.Input, args: [{ isSignal: true, alias: "keyExp", required: true }] }], displayExp: [{ type: i0.Input, args: [{ isSignal: true, alias: "displayExp", required: true }] }], mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: false }] }], multiToggleShown: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiToggleShown", required: false }] }], selectAllShown: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectAllShown", required: false }] }], localSearch: [{ type: i0.Input, args: [{ isSignal: true, alias: "localSearch", required: false }] }], lazyLoad: [{ type: i0.Input, args: [{ isSignal: true, alias: "lazyLoad", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], fetching: [{ type: i0.Input, args: [{ isSignal: true, alias: "fetching", required: false }] }], pinnedKeys: [{ type: i0.Input, args: [{ isSignal: true, alias: "pinnedKeys", required: false }] }], navigateTitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "navigateTitle", required: false }] }], navigateLink: [{ type: i0.Input, args: [{ isSignal: true, alias: "navigateLink", required: false }] }], searchTerm: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchTerm", required: false }] }], applied: [{ type: i0.Output, args: ["applied"] }], cancelled: [{ type: i0.Output, args: ["cancelled"] }], searchChange: [{ type: i0.Output, args: ["searchChange"] }], loadMore: [{ type: i0.Output, args: ["loadMore"] }], temporaryChoiceChange: [{ type: i0.Output, args: ["temporaryChoiceChange"] }] } });
681
+
682
+ const BEM_BLOCK = 'rt-dynamic-selector';
683
+ /**
684
+ * Динамический селектор: поле формы со списком выбранных записей. Значение — массив ключей в
685
+ * порядке списка. Записи добавляются всплывающим выбором, убираются корзиной строки, список
686
+ * возвращается к записанному формой сбросом и пустеет очисткой — кроме строк только для чтения.
687
+ *
688
+ * @example
689
+ * ```html
690
+ * <rt-dynamic-selector keyExp="id" displayExp="name" [entities]="people()" [formControl]="team" />
691
+ * ```
692
+ */
693
+ class RtDynamicSelectorComponent extends RtFormControlBase {
694
+ constructor() {
695
+ super(...arguments);
696
+ /** Последнее значение, записанное формой: к нему возвращает сброс. */
697
+ this.#initial = signal([], /* @ts-ignore */
698
+ ...(ngDevMode ? [{ debugName: "#initial" }] : /* istanbul ignore next */ []));
699
+ this.addLabel = rtKitLabel('dynamicSelectorAdd');
700
+ this.nothingToChooseLabel = rtKitLabel('dynamicSelectorNothingToChoose');
701
+ /** Всплывающий выбор открывается от нажатой кнопки добавления: у полосы и у приглашения — свой. */
702
+ this.popovers = viewChildren(RtPopoverDirective, /* @ts-ignore */
703
+ ...(ngDevMode ? [{ debugName: "popovers" }] : /* istanbul ignore next */ []));
704
+ this.rowTitle = contentChild(RtDynamicSelectorRowTitleDirective, /* @ts-ignore */
705
+ ...(ngDevMode ? [{ debugName: "rowTitle" }] : /* istanbul ignore next */ []));
706
+ this.rowControls = contentChild(RtDynamicSelectorRowControlsDirective, /* @ts-ignore */
707
+ ...(ngDevMode ? [{ debugName: "rowControls" }] : /* istanbul ignore next */ []));
708
+ this.titleTpl = computed(() => this.rowTitle()?.templateRef ?? null, /* @ts-ignore */
709
+ ...(ngDevMode ? [{ debugName: "titleTpl" }] : /* istanbul ignore next */ []));
710
+ this.controlsTpl = computed(() => this.rowControls()?.templateRef ?? null, /* @ts-ignore */
711
+ ...(ngDevMode ? [{ debugName: "controlsTpl" }] : /* istanbul ignore next */ []));
712
+ /** Выбранные записи в порядке значения; ключ, которого нет среди записей, строки не рисует. */
713
+ this.chosen = computed(() => this.#entitiesOf(this.value()), /* @ts-ignore */
714
+ ...(ngDevMode ? [{ debugName: "chosen" }] : /* istanbul ignore next */ []));
715
+ this.rows = computed(() => {
716
+ const locked = this.readonlyKeys();
717
+ return this.chosen().map((item) => ({
718
+ item,
719
+ key: this.#keyOf(item),
720
+ label: dynamicSelectorLabel(item, (entity) => this.#labelOf(entity)) ?? '',
721
+ locked: locked.includes(this.#keyOf(item)),
722
+ }));
723
+ }, /* @ts-ignore */
724
+ ...(ngDevMode ? [{ debugName: "rows" }] : /* istanbul ignore next */ []));
725
+ /** Что предлагает всплывающий выбор: ещё не выбранное, в порядке вызывающего или по алфавиту. */
726
+ this.offered = computed(() => selectableDynamicItems(this.entities(), this.value(), (item) => this.#keyOf(item), (item) => this.#labelOf(item), '', this.sortFn()), /* @ts-ignore */
727
+ ...(ngDevMode ? [{ debugName: "offered" }] : /* istanbul ignore next */ []));
728
+ this.hasOffer = computed(() => this.offered().length > 0 || !this.localSearch(), /* @ts-ignore */
729
+ ...(ngDevMode ? [{ debugName: "hasOffer" }] : /* istanbul ignore next */ []));
730
+ this.isNothingToChoose = computed(() => this.value().length === 0 && !this.hasOffer(), /* @ts-ignore */
731
+ ...(ngDevMode ? [{ debugName: "isNothingToChoose" }] : /* istanbul ignore next */ []));
732
+ this.isAddShown = computed(() => this.addShown() && this.hasOffer(), /* @ts-ignore */
733
+ ...(ngDevMode ? [{ debugName: "isAddShown" }] : /* istanbul ignore next */ []));
734
+ this.isKeysReset = computed(() => sameDynamicKeys(this.value(), this.#initial()), /* @ts-ignore */
735
+ ...(ngDevMode ? [{ debugName: "isKeysReset" }] : /* istanbul ignore next */ []));
736
+ this.isKeysClear = computed(() => clearDynamicKeys(this.value(), this.readonlyKeys()).length === this.value().length, /* @ts-ignore */
737
+ ...(ngDevMode ? [{ debugName: "isKeysClear" }] : /* istanbul ignore next */ []));
738
+ /** Правки в шаблоне строки держат сброс и очистку включёнными, даже когда ключи не менялись. */
739
+ this.isResetDisabled = computed(() => !this.extraChanged() && this.isKeysReset(), /* @ts-ignore */
740
+ ...(ngDevMode ? [{ debugName: "isResetDisabled" }] : /* istanbul ignore next */ []));
741
+ this.isClearDisabled = computed(() => !this.extraChanged() && this.isKeysClear(), /* @ts-ignore */
742
+ ...(ngDevMode ? [{ debugName: "isClearDisabled" }] : /* istanbul ignore next */ []));
743
+ this.addTitle = computed(() => this.buttonTitle() || this.addLabel(), /* @ts-ignore */
744
+ ...(ngDevMode ? [{ debugName: "addTitle" }] : /* istanbul ignore next */ []));
745
+ this.hasValue = computed(() => this.value().length > 0, /* @ts-ignore */
746
+ ...(ngDevMode ? [{ debugName: "hasValue" }] : /* istanbul ignore next */ []));
747
+ /** Записи, из которых выбирают; у каждой есть поле ключа и поле подписи. */
748
+ this.entities = input([], /* @ts-ignore */
749
+ ...(ngDevMode ? [{ debugName: "entities" }] : /* istanbul ignore next */ []));
750
+ this.keyExp = input.required(/* @ts-ignore */
751
+ ...(ngDevMode ? [{ debugName: "keyExp" }] : /* istanbul ignore next */ []));
752
+ this.displayExp = input.required(/* @ts-ignore */
753
+ ...(ngDevMode ? [{ debugName: "displayExp" }] : /* istanbul ignore next */ []));
754
+ this.mode = input('multi', /* @ts-ignore */
755
+ ...(ngDevMode ? [{ debugName: "mode" }] : /* istanbul ignore next */ []));
756
+ /** Название кнопки добавления; пустое — «Add» из словаря кита. */
757
+ this.buttonTitle = input('', /* @ts-ignore */
758
+ ...(ngDevMode ? [{ debugName: "buttonTitle" }] : /* istanbul ignore next */ []));
759
+ this.addShown = input(true, { ...(ngDevMode ? { debugName: "addShown" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
760
+ /** Корзина строк; без неё записи убирает только очистка или сам вызывающий. */
761
+ this.removeShown = input(true, { ...(ngDevMode ? { debugName: "removeShown" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
762
+ /** Сброс и очистка под списком: `false` их убирает, кнопка добавления остаётся. */
763
+ this.listActionsShown = input(true, { ...(ngDevMode ? { debugName: "listActionsShown" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
764
+ /**
765
+ * Строки правлены в шаблоне вызывающего: сброс и очистка включены и тогда, когда ключи прежние.
766
+ * Сброс сообщает `listReset`, очистка — `listCleared`, и вызывающий снимает свои правки.
767
+ */
768
+ this.extraChanged = input(false, { ...(ngDevMode ? { debugName: "extraChanged" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
769
+ /** Запрос, с которым открывается всплывающий выбор; событием поиска он не уходит. */
770
+ this.searchTerm = input('', /* @ts-ignore */
771
+ ...(ngDevMode ? [{ debugName: "searchTerm" }] : /* istanbul ignore next */ []));
772
+ /** Ключи, которые нельзя убрать из списка. */
773
+ this.readonlyKeys = input([], /* @ts-ignore */
774
+ ...(ngDevMode ? [{ debugName: "readonlyKeys" }] : /* istanbul ignore next */ []));
775
+ /** Ключи строк всплывающего выбора, под последней из которых стоит разделитель. */
776
+ this.pinnedKeys = input([], /* @ts-ignore */
777
+ ...(ngDevMode ? [{ debugName: "pinnedKeys" }] : /* istanbul ignore next */ []));
778
+ this.draggable = input(false, { ...(ngDevMode ? { debugName: "draggable" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
779
+ /** Шаг скругления кнопок-иконок списка; по умолчанию они круглые. */
780
+ this.buttonRadius = input('full', /* @ts-ignore */
781
+ ...(ngDevMode ? [{ debugName: "buttonRadius" }] : /* istanbul ignore next */ []));
782
+ /** Приглашение вместо полосы кнопок: значок, описание и кнопка добавления. */
783
+ this.invitation = input(false, { ...(ngDevMode ? { debugName: "invitation" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
784
+ this.invitationIcon = input(null, /* @ts-ignore */
785
+ ...(ngDevMode ? [{ debugName: "invitationIcon" }] : /* istanbul ignore next */ []));
786
+ this.invitationDescription = input('', /* @ts-ignore */
787
+ ...(ngDevMode ? [{ debugName: "invitationDescription" }] : /* istanbul ignore next */ []));
788
+ this.multiToggleShown = input(false, { ...(ngDevMode ? { debugName: "multiToggleShown" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
789
+ this.selectAllShown = input(true, { ...(ngDevMode ? { debugName: "selectAllShown" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
790
+ this.localSearch = input(true, { ...(ngDevMode ? { debugName: "localSearch" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
791
+ this.lazyLoad = input(false, { ...(ngDevMode ? { debugName: "lazyLoad" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
792
+ this.loading = input(false, { ...(ngDevMode ? { debugName: "loading" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
793
+ this.fetching = input(false, { ...(ngDevMode ? { debugName: "fetching" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
794
+ this.navigateTitle = input('', /* @ts-ignore */
795
+ ...(ngDevMode ? [{ debugName: "navigateTitle" }] : /* istanbul ignore next */ []));
796
+ this.navigateLink = input('', /* @ts-ignore */
797
+ ...(ngDevMode ? [{ debugName: "navigateLink" }] : /* istanbul ignore next */ []));
798
+ this.sortFn = input(null, /* @ts-ignore */
799
+ ...(ngDevMode ? [{ debugName: "sortFn" }] : /* istanbul ignore next */ []));
800
+ /** Выбранные записи: те же, что уходят событием изменения выбора. */
801
+ this.chosenEntities = model([], /* @ts-ignore */
802
+ ...(ngDevMode ? [{ debugName: "chosenEntities" }] : /* istanbul ignore next */ []));
803
+ this.selectionChange = output();
804
+ this.listReset = output();
805
+ this.listCleared = output();
806
+ /** Всплывающий выбор открылся или закрылся. */
807
+ this.popupOpenChange = output();
808
+ this.searchChange = output();
809
+ this.loadMore = output();
810
+ this.temporaryChoiceChange = output();
811
+ /** Открыт ли всплывающий выбор — от кнопки полосы или от кнопки приглашения. */
812
+ this.popupOpen = computed(() => this.popovers().some((popover) => popover.isOpen()), /* @ts-ignore */
813
+ ...(ngDevMode ? [{ debugName: "popupOpen" }] : /* istanbul ignore next */ []));
814
+ this.displayText = computed(() => this.rows()
815
+ .map((row) => row.label)
816
+ .join(', '), /* @ts-ignore */
817
+ ...(ngDevMode ? [{ debugName: "displayText" }] : /* istanbul ignore next */ []));
818
+ }
819
+ /** Последнее значение, записанное формой: к нему возвращает сброс. */
820
+ #initial;
821
+ /** Записанное формой становится и списком, и значением для сброса; пустой массив список опустошает. */
822
+ writeValue(value) {
823
+ super.writeValue(value === null ? null : [...value]);
824
+ this.#initial.set([...this.value()]);
825
+ }
826
+ onAdd(popover) {
827
+ if (!this.isDisabled()) {
828
+ popover.open();
829
+ }
830
+ }
831
+ onApplied(keys) {
832
+ this.#closePopup();
833
+ this.#change(this.mode() === 'single'
834
+ ? keys.slice(0, 1)
835
+ : [...this.value(), ...keys.filter((key) => !this.value().includes(key))]);
836
+ }
837
+ onCancelled() {
838
+ this.#closePopup();
839
+ }
840
+ onRemoved(key) {
841
+ if (!this.isDisabled() && !this.readonlyKeys().includes(key)) {
842
+ this.#change(this.value().filter((item) => item !== key));
843
+ }
844
+ }
845
+ onMoved(move) {
846
+ if (!this.isDisabled()) {
847
+ this.#change(moveDynamicKey(this.value(), move.from, move.to));
848
+ }
849
+ }
850
+ onReset() {
851
+ if (this.isDisabled() || this.isResetDisabled()) {
852
+ return;
853
+ }
854
+ // Ключи прежние, а правки только в строках: значение не трогаем, сообщаем о сбросе.
855
+ if (!this.isKeysReset()) {
856
+ this.#change([...this.#initial()]);
857
+ }
858
+ this.listReset.emit();
859
+ }
860
+ onCleared() {
861
+ if (this.isDisabled() || this.isClearDisabled()) {
862
+ return;
863
+ }
864
+ if (!this.isKeysClear()) {
865
+ this.#change(clearDynamicKeys(this.value(), this.readonlyKeys()));
866
+ }
867
+ this.listCleared.emit();
868
+ }
869
+ onOpened() {
870
+ this.popupOpenChange.emit(true);
871
+ }
872
+ onClosed() {
873
+ this.markTouched();
874
+ this.popupOpenChange.emit(false);
875
+ }
876
+ #closePopup() {
877
+ for (const popover of this.popovers()) {
878
+ popover.close();
879
+ }
880
+ }
881
+ getEmptyValue() {
882
+ return [];
883
+ }
884
+ focusAfterClear() {
885
+ // Очистка крестиком у поля не ставится: фокус остаётся там, где был.
886
+ }
887
+ #change(keys) {
888
+ const entities = this.#entitiesOf(keys);
889
+ this.value.set(keys);
890
+ this.emitChange(keys);
891
+ this.chosenEntities.set(entities);
892
+ this.selectionChange.emit(entities);
893
+ }
894
+ #entitiesOf(keys) {
895
+ return keys
896
+ .map((key) => this.entities().find((item) => this.#keyOf(item) === key))
897
+ .filter((item) => item !== undefined);
898
+ }
899
+ /** Ключ записи — по имени поля, которое назвал вызывающий. */
900
+ #keyOf(item) {
901
+ return item[this.keyExp()];
902
+ }
903
+ /** Подпись записи — по имени поля, которое назвал вызывающий. */
904
+ #labelOf(item) {
905
+ return item[this.displayExp()];
906
+ }
907
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: RtDynamicSelectorComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
908
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: RtDynamicSelectorComponent, isStandalone: true, selector: "rt-dynamic-selector", inputs: { entities: { classPropertyName: "entities", publicName: "entities", isSignal: true, isRequired: false, transformFunction: null }, keyExp: { classPropertyName: "keyExp", publicName: "keyExp", isSignal: true, isRequired: true, transformFunction: null }, displayExp: { classPropertyName: "displayExp", publicName: "displayExp", isSignal: true, isRequired: true, transformFunction: null }, mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null }, buttonTitle: { classPropertyName: "buttonTitle", publicName: "buttonTitle", isSignal: true, isRequired: false, transformFunction: null }, addShown: { classPropertyName: "addShown", publicName: "addShown", isSignal: true, isRequired: false, transformFunction: null }, removeShown: { classPropertyName: "removeShown", publicName: "removeShown", isSignal: true, isRequired: false, transformFunction: null }, listActionsShown: { classPropertyName: "listActionsShown", publicName: "listActionsShown", isSignal: true, isRequired: false, transformFunction: null }, extraChanged: { classPropertyName: "extraChanged", publicName: "extraChanged", isSignal: true, isRequired: false, transformFunction: null }, searchTerm: { classPropertyName: "searchTerm", publicName: "searchTerm", isSignal: true, isRequired: false, transformFunction: null }, readonlyKeys: { classPropertyName: "readonlyKeys", publicName: "readonlyKeys", isSignal: true, isRequired: false, transformFunction: null }, pinnedKeys: { classPropertyName: "pinnedKeys", publicName: "pinnedKeys", isSignal: true, isRequired: false, transformFunction: null }, draggable: { classPropertyName: "draggable", publicName: "draggable", isSignal: true, isRequired: false, transformFunction: null }, buttonRadius: { classPropertyName: "buttonRadius", publicName: "buttonRadius", isSignal: true, isRequired: false, transformFunction: null }, invitation: { classPropertyName: "invitation", publicName: "invitation", isSignal: true, isRequired: false, transformFunction: null }, invitationIcon: { classPropertyName: "invitationIcon", publicName: "invitationIcon", isSignal: true, isRequired: false, transformFunction: null }, invitationDescription: { classPropertyName: "invitationDescription", publicName: "invitationDescription", isSignal: true, isRequired: false, transformFunction: null }, multiToggleShown: { classPropertyName: "multiToggleShown", publicName: "multiToggleShown", isSignal: true, isRequired: false, transformFunction: null }, selectAllShown: { classPropertyName: "selectAllShown", publicName: "selectAllShown", isSignal: true, isRequired: false, transformFunction: null }, localSearch: { classPropertyName: "localSearch", publicName: "localSearch", isSignal: true, isRequired: false, transformFunction: null }, lazyLoad: { classPropertyName: "lazyLoad", publicName: "lazyLoad", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, fetching: { classPropertyName: "fetching", publicName: "fetching", isSignal: true, isRequired: false, transformFunction: null }, navigateTitle: { classPropertyName: "navigateTitle", publicName: "navigateTitle", isSignal: true, isRequired: false, transformFunction: null }, navigateLink: { classPropertyName: "navigateLink", publicName: "navigateLink", isSignal: true, isRequired: false, transformFunction: null }, sortFn: { classPropertyName: "sortFn", publicName: "sortFn", isSignal: true, isRequired: false, transformFunction: null }, chosenEntities: { classPropertyName: "chosenEntities", publicName: "chosenEntities", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { chosenEntities: "chosenEntitiesChange", selectionChange: "selectionChange", listReset: "listReset", listCleared: "listCleared", popupOpenChange: "popupOpenChange", searchChange: "searchChange", loadMore: "loadMore", temporaryChoiceChange: "temporaryChoiceChange" }, host: { classAttribute: "rt-dynamic-selector" }, providers: [
909
+ // Алиас базового токена — для contentChild(RtFormControlBase) в rt-field.
910
+ { provide: RtFormControlBase, useExisting: forwardRef(() => RtDynamicSelectorComponent) },
911
+ ], queries: [{ propertyName: "rowTitle", first: true, predicate: RtDynamicSelectorRowTitleDirective, descendants: true, isSignal: true }, { propertyName: "rowControls", first: true, predicate: RtDynamicSelectorRowControlsDirective, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "popovers", predicate: RtPopoverDirective, descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<ng-container rtBlock=\"rt-dynamic-selector\">\n @if (isNothingToChoose()) {\n <rt-empty-state rtElem=\"nothing\" qa-dataid=\"dynamic-selector-nothing\" icon=\"warning\" [title]=\"nothingToChooseLabel()\" />\n } @else {\n <div rtElem=\"content\">\n <rt-dynamic-selector-list\n [rows]=\"rows()\"\n [draggable]=\"draggable()\"\n [buttonRadius]=\"buttonRadius()\"\n [disabled]=\"isDisabled()\"\n [actionsShown]=\"!invitation()\"\n [resetClearShown]=\"listActionsShown()\"\n [removeShown]=\"removeShown()\"\n [resetDisabled]=\"isResetDisabled()\"\n [clearDisabled]=\"isClearDisabled()\"\n [titleTpl]=\"titleTpl()\"\n [controlsTpl]=\"controlsTpl()\"\n (removed)=\"onRemoved($event)\"\n (moved)=\"onMoved($event)\"\n (resetClicked)=\"onReset()\"\n (cleared)=\"onCleared()\">\n @if (isAddShown()) {\n <button\n rtButton\n theme=\"secondary\"\n appearance=\"text\"\n type=\"button\"\n qa-dataid=\"dynamic-selector-add\"\n rtPopoverTrigger=\"manual\"\n #addPopover=\"rtPopover\"\n [rtPopover]=\"popupTpl\"\n [rtPopoverDisabled]=\"isDisabled()\"\n [label]=\"addTitle()\"\n [attr.aria-label]=\"addTitle()\"\n [disabled]=\"isDisabled()\"\n (rtPopoverOpened)=\"onOpened()\"\n (rtPopoverClosed)=\"onClosed()\"\n (click)=\"onAdd(addPopover)\"></button>\n }\n </rt-dynamic-selector-list>\n\n @if (invitation()) {\n <rt-empty-state\n rtElem=\"invitation\"\n qa-dataid=\"dynamic-selector-invitation\"\n [icon]=\"invitationIcon()\"\n [description]=\"invitationDescription()\">\n @if (hasOffer()) {\n <button\n rtButton\n appearance=\"outlined\"\n type=\"button\"\n qa-dataid=\"dynamic-selector-invitation-add\"\n rtPopoverTrigger=\"manual\"\n #invitationPopover=\"rtPopover\"\n [rtPopover]=\"popupTpl\"\n [rtPopoverDisabled]=\"isDisabled()\"\n [label]=\"addTitle()\"\n [attr.aria-label]=\"addTitle()\"\n [disabled]=\"isDisabled()\"\n (rtPopoverOpened)=\"onOpened()\"\n (rtPopoverClosed)=\"onClosed()\"\n (click)=\"onAdd(invitationPopover)\"></button>\n }\n </rt-empty-state>\n }\n </div>\n }\n\n <ng-template #popupTpl>\n <rt-dynamic-selector-popup\n [entities]=\"offered()\"\n [keyExp]=\"keyExp()\"\n [displayExp]=\"displayExp()\"\n [mode]=\"mode()\"\n [multiToggleShown]=\"multiToggleShown()\"\n [selectAllShown]=\"selectAllShown()\"\n [localSearch]=\"localSearch()\"\n [lazyLoad]=\"lazyLoad()\"\n [loading]=\"loading()\"\n [fetching]=\"fetching()\"\n [pinnedKeys]=\"pinnedKeys()\"\n [navigateTitle]=\"navigateTitle()\"\n [navigateLink]=\"navigateLink()\"\n [searchTerm]=\"searchTerm()\"\n (applied)=\"onApplied($event)\"\n (cancelled)=\"onCancelled()\"\n (searchChange)=\"searchChange.emit($event)\"\n (loadMore)=\"loadMore.emit()\"\n (temporaryChoiceChange)=\"temporaryChoiceChange.emit($event)\" />\n </ng-template>\n</ng-container>\n", styles: ["@charset \"UTF-8\";@layer rt-kit.components{.rt-dynamic-selector{display:block;width:100%}.rt-dynamic-selector__content{display:flex;flex-direction:column;gap:var(--rt-space-sm)}.rt-dynamic-selector__invitation,.rt-dynamic-selector__nothing{display:block}}\n"], dependencies: [{ kind: "directive", type:
912
+ // standalone components / directives
913
+ BlockDirective, selector: "[rtBlock]", inputs: ["rtMod"] }, { kind: "directive", type: ElemDirective, selector: "[rtElem]", inputs: ["rtMod"] }, { kind: "directive", type: RtButtonDirective, selector: "button[rtButton], a[rtButton]", inputs: ["label", "icon", "iconPos", "theme", "appearance", "size", "loading", "loadingIcon", "loadingLabel", "pressed"] }, { kind: "component", type: RtDynamicSelectorListComponent, selector: "rt-dynamic-selector-list", inputs: ["rows", "draggable", "editable", "disabled", "actionsShown", "resetClearShown", "removeShown", "resetDisabled", "clearDisabled", "buttonRadius", "titleTpl", "controlsTpl"], outputs: ["removed", "moved", "edited", "resetClicked", "cleared"] }, { kind: "component", type: RtDynamicSelectorPopupComponent, selector: "rt-dynamic-selector-popup", inputs: ["entities", "keyExp", "displayExp", "mode", "multiToggleShown", "selectAllShown", "localSearch", "lazyLoad", "loading", "fetching", "pinnedKeys", "navigateTitle", "navigateLink", "searchTerm"], outputs: ["applied", "cancelled", "searchChange", "loadMore", "temporaryChoiceChange"] }, { kind: "component", type: RtEmptyStateComponent, selector: "rt-empty-state", inputs: ["icon", "glyph", "title", "description", "framed"] }, { kind: "directive", type: RtPopoverDirective, selector: "[rtPopover]", inputs: ["rtPopover", "rtPopoverTrigger", "rtPopoverWidth", "rtPopoverAlign", "rtPopoverFitViewport", "rtPopoverContext", "rtPopoverPanelClass", "rtPopoverDisabled", "rtPopoverOffsetY", "rtPopoverOffsetX"], outputs: ["rtPopoverOpened", "rtPopoverClosed"], exportAs: ["rtPopover"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
914
+ }
915
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: RtDynamicSelectorComponent, decorators: [{
916
+ type: Component,
917
+ args: [{ selector: 'rt-dynamic-selector', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [
918
+ // standalone components / directives
919
+ BlockDirective,
920
+ ElemDirective,
921
+ RtButtonDirective,
922
+ RtDynamicSelectorListComponent,
923
+ RtDynamicSelectorPopupComponent,
924
+ RtEmptyStateComponent,
925
+ RtPopoverDirective,
926
+ ], providers: [
927
+ // Алиас базового токена — для contentChild(RtFormControlBase) в rt-field.
928
+ { provide: RtFormControlBase, useExisting: forwardRef(() => RtDynamicSelectorComponent) },
929
+ ], host: { class: BEM_BLOCK }, template: "<ng-container rtBlock=\"rt-dynamic-selector\">\n @if (isNothingToChoose()) {\n <rt-empty-state rtElem=\"nothing\" qa-dataid=\"dynamic-selector-nothing\" icon=\"warning\" [title]=\"nothingToChooseLabel()\" />\n } @else {\n <div rtElem=\"content\">\n <rt-dynamic-selector-list\n [rows]=\"rows()\"\n [draggable]=\"draggable()\"\n [buttonRadius]=\"buttonRadius()\"\n [disabled]=\"isDisabled()\"\n [actionsShown]=\"!invitation()\"\n [resetClearShown]=\"listActionsShown()\"\n [removeShown]=\"removeShown()\"\n [resetDisabled]=\"isResetDisabled()\"\n [clearDisabled]=\"isClearDisabled()\"\n [titleTpl]=\"titleTpl()\"\n [controlsTpl]=\"controlsTpl()\"\n (removed)=\"onRemoved($event)\"\n (moved)=\"onMoved($event)\"\n (resetClicked)=\"onReset()\"\n (cleared)=\"onCleared()\">\n @if (isAddShown()) {\n <button\n rtButton\n theme=\"secondary\"\n appearance=\"text\"\n type=\"button\"\n qa-dataid=\"dynamic-selector-add\"\n rtPopoverTrigger=\"manual\"\n #addPopover=\"rtPopover\"\n [rtPopover]=\"popupTpl\"\n [rtPopoverDisabled]=\"isDisabled()\"\n [label]=\"addTitle()\"\n [attr.aria-label]=\"addTitle()\"\n [disabled]=\"isDisabled()\"\n (rtPopoverOpened)=\"onOpened()\"\n (rtPopoverClosed)=\"onClosed()\"\n (click)=\"onAdd(addPopover)\"></button>\n }\n </rt-dynamic-selector-list>\n\n @if (invitation()) {\n <rt-empty-state\n rtElem=\"invitation\"\n qa-dataid=\"dynamic-selector-invitation\"\n [icon]=\"invitationIcon()\"\n [description]=\"invitationDescription()\">\n @if (hasOffer()) {\n <button\n rtButton\n appearance=\"outlined\"\n type=\"button\"\n qa-dataid=\"dynamic-selector-invitation-add\"\n rtPopoverTrigger=\"manual\"\n #invitationPopover=\"rtPopover\"\n [rtPopover]=\"popupTpl\"\n [rtPopoverDisabled]=\"isDisabled()\"\n [label]=\"addTitle()\"\n [attr.aria-label]=\"addTitle()\"\n [disabled]=\"isDisabled()\"\n (rtPopoverOpened)=\"onOpened()\"\n (rtPopoverClosed)=\"onClosed()\"\n (click)=\"onAdd(invitationPopover)\"></button>\n }\n </rt-empty-state>\n }\n </div>\n }\n\n <ng-template #popupTpl>\n <rt-dynamic-selector-popup\n [entities]=\"offered()\"\n [keyExp]=\"keyExp()\"\n [displayExp]=\"displayExp()\"\n [mode]=\"mode()\"\n [multiToggleShown]=\"multiToggleShown()\"\n [selectAllShown]=\"selectAllShown()\"\n [localSearch]=\"localSearch()\"\n [lazyLoad]=\"lazyLoad()\"\n [loading]=\"loading()\"\n [fetching]=\"fetching()\"\n [pinnedKeys]=\"pinnedKeys()\"\n [navigateTitle]=\"navigateTitle()\"\n [navigateLink]=\"navigateLink()\"\n [searchTerm]=\"searchTerm()\"\n (applied)=\"onApplied($event)\"\n (cancelled)=\"onCancelled()\"\n (searchChange)=\"searchChange.emit($event)\"\n (loadMore)=\"loadMore.emit()\"\n (temporaryChoiceChange)=\"temporaryChoiceChange.emit($event)\" />\n </ng-template>\n</ng-container>\n", styles: ["@charset \"UTF-8\";@layer rt-kit.components{.rt-dynamic-selector{display:block;width:100%}.rt-dynamic-selector__content{display:flex;flex-direction:column;gap:var(--rt-space-sm)}.rt-dynamic-selector__invitation,.rt-dynamic-selector__nothing{display:block}}\n"] }]
930
+ }], propDecorators: { popovers: [{ type: i0.ViewChildren, args: [i0.forwardRef(() => RtPopoverDirective), { isSignal: true }] }], rowTitle: [{ type: i0.ContentChild, args: [i0.forwardRef(() => RtDynamicSelectorRowTitleDirective), { isSignal: true }] }], rowControls: [{ type: i0.ContentChild, args: [i0.forwardRef(() => RtDynamicSelectorRowControlsDirective), { isSignal: true }] }], entities: [{ type: i0.Input, args: [{ isSignal: true, alias: "entities", required: false }] }], keyExp: [{ type: i0.Input, args: [{ isSignal: true, alias: "keyExp", required: true }] }], displayExp: [{ type: i0.Input, args: [{ isSignal: true, alias: "displayExp", required: true }] }], mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: false }] }], buttonTitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "buttonTitle", required: false }] }], addShown: [{ type: i0.Input, args: [{ isSignal: true, alias: "addShown", required: false }] }], removeShown: [{ type: i0.Input, args: [{ isSignal: true, alias: "removeShown", required: false }] }], listActionsShown: [{ type: i0.Input, args: [{ isSignal: true, alias: "listActionsShown", required: false }] }], extraChanged: [{ type: i0.Input, args: [{ isSignal: true, alias: "extraChanged", required: false }] }], searchTerm: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchTerm", required: false }] }], readonlyKeys: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonlyKeys", required: false }] }], pinnedKeys: [{ type: i0.Input, args: [{ isSignal: true, alias: "pinnedKeys", required: false }] }], draggable: [{ type: i0.Input, args: [{ isSignal: true, alias: "draggable", required: false }] }], buttonRadius: [{ type: i0.Input, args: [{ isSignal: true, alias: "buttonRadius", required: false }] }], invitation: [{ type: i0.Input, args: [{ isSignal: true, alias: "invitation", required: false }] }], invitationIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "invitationIcon", required: false }] }], invitationDescription: [{ type: i0.Input, args: [{ isSignal: true, alias: "invitationDescription", required: false }] }], multiToggleShown: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiToggleShown", required: false }] }], selectAllShown: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectAllShown", required: false }] }], localSearch: [{ type: i0.Input, args: [{ isSignal: true, alias: "localSearch", required: false }] }], lazyLoad: [{ type: i0.Input, args: [{ isSignal: true, alias: "lazyLoad", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], fetching: [{ type: i0.Input, args: [{ isSignal: true, alias: "fetching", required: false }] }], navigateTitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "navigateTitle", required: false }] }], navigateLink: [{ type: i0.Input, args: [{ isSignal: true, alias: "navigateLink", required: false }] }], sortFn: [{ type: i0.Input, args: [{ isSignal: true, alias: "sortFn", required: false }] }], chosenEntities: [{ type: i0.Input, args: [{ isSignal: true, alias: "chosenEntities", required: false }] }, { type: i0.Output, args: ["chosenEntitiesChange"] }], selectionChange: [{ type: i0.Output, args: ["selectionChange"] }], listReset: [{ type: i0.Output, args: ["listReset"] }], listCleared: [{ type: i0.Output, args: ["listCleared"] }], popupOpenChange: [{ type: i0.Output, args: ["popupOpenChange"] }], searchChange: [{ type: i0.Output, args: ["searchChange"] }], loadMore: [{ type: i0.Output, args: ["loadMore"] }], temporaryChoiceChange: [{ type: i0.Output, args: ["temporaryChoiceChange"] }] } });
931
+
932
+ /**
933
+ * Generated bundle index. Do not edit.
934
+ */
935
+
936
+ export { RT_DYNAMIC_SELECTOR_SEARCH_DEBOUNCE, RtDynamicInputComponent, RtDynamicSelectorComponent, RtDynamicSelectorListComponent, RtDynamicSelectorPopupComponent, RtDynamicSelectorRowControlsDirective, RtDynamicSelectorRowTitleDirective };
937
+ //# sourceMappingURL=rt-tools-ui-kit-v2-dynamic-selector.mjs.map