@rt-tools/ui-kit-v2 0.16.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 (321) hide show
  1. package/README.md +25 -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-rich-editor.mjs +96 -41
  125. package/fesm2022/rt-tools-ui-kit-v2-rich-editor.mjs.map +1 -1
  126. package/fesm2022/rt-tools-ui-kit-v2-ripple.mjs +118 -0
  127. package/fesm2022/rt-tools-ui-kit-v2-ripple.mjs.map +1 -0
  128. package/fesm2022/rt-tools-ui-kit-v2-scroll-area.mjs +290 -0
  129. package/fesm2022/rt-tools-ui-kit-v2-scroll-area.mjs.map +1 -0
  130. package/fesm2022/rt-tools-ui-kit-v2-section-nav.mjs +37 -0
  131. package/fesm2022/rt-tools-ui-kit-v2-section-nav.mjs.map +1 -0
  132. package/fesm2022/rt-tools-ui-kit-v2-select.mjs +495 -0
  133. package/fesm2022/rt-tools-ui-kit-v2-select.mjs.map +1 -0
  134. package/fesm2022/rt-tools-ui-kit-v2-side-menu.mjs +1493 -0
  135. package/fesm2022/rt-tools-ui-kit-v2-side-menu.mjs.map +1 -0
  136. package/fesm2022/rt-tools-ui-kit-v2-skeleton-wrapper.mjs +49 -0
  137. package/fesm2022/rt-tools-ui-kit-v2-skeleton-wrapper.mjs.map +1 -0
  138. package/fesm2022/rt-tools-ui-kit-v2-skeleton.mjs +123 -0
  139. package/fesm2022/rt-tools-ui-kit-v2-skeleton.mjs.map +1 -0
  140. package/fesm2022/rt-tools-ui-kit-v2-spinner.mjs +70 -0
  141. package/fesm2022/rt-tools-ui-kit-v2-spinner.mjs.map +1 -0
  142. package/fesm2022/rt-tools-ui-kit-v2-split-button.mjs +92 -0
  143. package/fesm2022/rt-tools-ui-kit-v2-split-button.mjs.map +1 -0
  144. package/fesm2022/rt-tools-ui-kit-v2-stat-tile.mjs +147 -0
  145. package/fesm2022/rt-tools-ui-kit-v2-stat-tile.mjs.map +1 -0
  146. package/fesm2022/rt-tools-ui-kit-v2-stepper.mjs +117 -0
  147. package/fesm2022/rt-tools-ui-kit-v2-stepper.mjs.map +1 -0
  148. package/fesm2022/rt-tools-ui-kit-v2-table.mjs +1636 -0
  149. package/fesm2022/rt-tools-ui-kit-v2-table.mjs.map +1 -0
  150. package/fesm2022/rt-tools-ui-kit-v2-tabs.mjs +350 -0
  151. package/fesm2022/rt-tools-ui-kit-v2-tabs.mjs.map +1 -0
  152. package/fesm2022/rt-tools-ui-kit-v2-tag.mjs +122 -0
  153. package/fesm2022/rt-tools-ui-kit-v2-tag.mjs.map +1 -0
  154. package/fesm2022/rt-tools-ui-kit-v2-textarea.mjs +85 -0
  155. package/fesm2022/rt-tools-ui-kit-v2-textarea.mjs.map +1 -0
  156. package/fesm2022/rt-tools-ui-kit-v2-theme-toggle.mjs +73 -0
  157. package/fesm2022/rt-tools-ui-kit-v2-theme-toggle.mjs.map +1 -0
  158. package/fesm2022/rt-tools-ui-kit-v2-thread-list.mjs +196 -0
  159. package/fesm2022/rt-tools-ui-kit-v2-thread-list.mjs.map +1 -0
  160. package/fesm2022/rt-tools-ui-kit-v2-timeline.mjs +39 -0
  161. package/fesm2022/rt-tools-ui-kit-v2-timeline.mjs.map +1 -0
  162. package/fesm2022/rt-tools-ui-kit-v2-toast.mjs +338 -0
  163. package/fesm2022/rt-tools-ui-kit-v2-toast.mjs.map +1 -0
  164. package/fesm2022/rt-tools-ui-kit-v2-toggle-button-group.mjs +132 -0
  165. package/fesm2022/rt-tools-ui-kit-v2-toggle-button-group.mjs.map +1 -0
  166. package/fesm2022/rt-tools-ui-kit-v2-toggle-switch.mjs +162 -0
  167. package/fesm2022/rt-tools-ui-kit-v2-toggle-switch.mjs.map +1 -0
  168. package/fesm2022/rt-tools-ui-kit-v2-toolbar.mjs +135 -0
  169. package/fesm2022/rt-tools-ui-kit-v2-toolbar.mjs.map +1 -0
  170. package/fesm2022/rt-tools-ui-kit-v2-tooltip.mjs +214 -0
  171. package/fesm2022/rt-tools-ui-kit-v2-tooltip.mjs.map +1 -0
  172. package/fesm2022/rt-tools-ui-kit-v2-welcome-dialog.mjs +64 -0
  173. package/fesm2022/rt-tools-ui-kit-v2-welcome-dialog.mjs.map +1 -0
  174. package/fesm2022/rt-tools-ui-kit-v2-workspace-details.mjs +263 -0
  175. package/fesm2022/rt-tools-ui-kit-v2-workspace-details.mjs.map +1 -0
  176. package/fesm2022/rt-tools-ui-kit-v2-workspace.mjs +296 -0
  177. package/fesm2022/rt-tools-ui-kit-v2-workspace.mjs.map +1 -0
  178. package/fesm2022/rt-tools-ui-kit-v2.mjs +91 -23164
  179. package/fesm2022/rt-tools-ui-kit-v2.mjs.map +1 -1
  180. package/package.json +349 -1
  181. package/rt-tools-ui-kit-v2-0.18.0.tgz +0 -0
  182. package/src/lib/components/action-bar/CONTEXT.md +5 -0
  183. package/src/lib/components/action-bar/rt-action-bar.component.scss +30 -16
  184. package/src/lib/components/aside/CONTEXT.md +9 -1
  185. package/src/lib/components/aside/footer/rt-aside-footer.component.scss +7 -8
  186. package/src/lib/components/aside/header/rt-aside-header.component.scss +16 -1
  187. package/src/lib/components/aside/rt-aside.component.scss +17 -1
  188. package/src/lib/components/button/CONTEXT.md +12 -11
  189. package/src/lib/components/button/rt-button.directive.scss +36 -0
  190. package/src/lib/components/data-list/settings/rt-data-list-settings-aside.component.scss +2 -2
  191. package/src/lib/components/data-table/cell/rt-data-table-cell.component.scss +1 -1
  192. package/src/lib/components/data-table/filter-cell/rt-data-table-filter-cell.component.scss +1 -1
  193. package/src/lib/components/data-table/rt-data-table.component.scss +1 -1
  194. package/src/lib/components/dialog/CONTEXT.md +9 -0
  195. package/src/lib/components/dialog/content/rt-dialog-content.component.scss +20 -0
  196. package/src/lib/components/dialog/footer/rt-dialog-footer.component.scss +18 -2
  197. package/src/lib/components/dialog/header/rt-dialog-header.component.scss +21 -3
  198. package/src/lib/components/dialog/rt-dialog.component.scss +9 -3
  199. package/src/lib/components/dot-field/CONTEXT.md +31 -0
  200. package/src/lib/components/dot-field/rt-dot-field.component.scss +20 -0
  201. package/src/lib/components/dot-field/stories/component/CONTEXT.md +14 -0
  202. package/src/lib/components/dot-field/stories/component/test-dot-field.component.scss +31 -0
  203. package/src/lib/components/dynamic-selector/CONTEXT.md +6 -0
  204. package/src/lib/components/field/CONTEXT.md +18 -2
  205. package/src/lib/components/header/CONTEXT.md +2 -2
  206. package/src/lib/components/icon/CONTEXT.md +11 -7
  207. package/src/lib/components/icon/rt-icon.component.scss +47 -0
  208. package/src/lib/components/icon-button/CONTEXT.md +27 -20
  209. package/src/lib/components/icon-button/rt-icon-button.component.scss +51 -25
  210. package/src/lib/components/image-upload/CONTEXT.md +20 -15
  211. package/src/lib/components/image-upload/rt-image-upload.component.scss +14 -2
  212. package/src/lib/components/pagination/rt-pagination.component.scss +1 -1
  213. package/src/lib/components/scroll-area/CONTEXT.md +2 -0
  214. package/src/lib/components/scroll-area/rt-scroll-area.component.scss +20 -3
  215. package/src/lib/components/select/rt-select.component.scss +4 -0
  216. package/src/lib/components/side-menu/CONTEXT.md +7 -2
  217. package/src/lib/components/spinner/CONTEXT.md +15 -8
  218. package/src/lib/components/spinner/rt-spinner.component.scss +108 -9
  219. package/src/lib/components/tag/rt-tag.component.scss +43 -23
  220. package/src/lib/components/toast/CONTEXT.md +8 -0
  221. package/src/lib/components/toast/rt-toast.component.scss +74 -15
  222. package/src/lib/components/toast/rt-toaster.component.scss +5 -1
  223. package/src/lib/components/toggle-button-group/rt-toggle-button-group.component.scss +35 -37
  224. package/src/lib/components/toggle-switch/CONTEXT.md +11 -3
  225. package/src/lib/components/toggle-switch/rt-toggle-switch.component.scss +53 -14
  226. package/src/lib/components/toolbar/rt-toolbar.component.scss +15 -4
  227. package/src/lib/components/tooltip/CONTEXT.md +5 -5
  228. package/src/rich-editor/lib/components/chat/CONTEXT.md +7 -2
  229. package/src/rich-editor/lib/components/chat/rt-chat.component.scss +25 -0
  230. package/src/styles/_semantic.scss +1 -1
  231. package/styles/tokens.css +43 -8
  232. package/types/rt-tools-ui-kit-v2-accordion.d.ts +30 -0
  233. package/types/rt-tools-ui-kit-v2-action-bar.d.ts +140 -0
  234. package/types/rt-tools-ui-kit-v2-aside-section.d.ts +25 -0
  235. package/types/rt-tools-ui-kit-v2-aside.d.ts +436 -0
  236. package/types/rt-tools-ui-kit-v2-autocomplete.d.ts +78 -0
  237. package/types/rt-tools-ui-kit-v2-bar-list.d.ts +41 -0
  238. package/types/rt-tools-ui-kit-v2-bottom-sheet.d.ts +20 -0
  239. package/types/rt-tools-ui-kit-v2-button.d.ts +76 -0
  240. package/types/rt-tools-ui-kit-v2-calendar.d.ts +96 -0
  241. package/types/rt-tools-ui-kit-v2-card.d.ts +38 -0
  242. package/types/rt-tools-ui-kit-v2-checkbox.d.ts +46 -0
  243. package/types/rt-tools-ui-kit-v2-collapsible-text.d.ts +20 -0
  244. package/types/rt-tools-ui-kit-v2-confirm-popover.d.ts +85 -0
  245. package/types/rt-tools-ui-kit-v2-container.d.ts +425 -0
  246. package/types/rt-tools-ui-kit-v2-core.d.ts +1222 -0
  247. package/types/rt-tools-ui-kit-v2-counter-row.d.ts +22 -0
  248. package/types/rt-tools-ui-kit-v2-counter.d.ts +70 -0
  249. package/types/rt-tools-ui-kit-v2-data-list.d.ts +334 -0
  250. package/types/rt-tools-ui-kit-v2-data-table.d.ts +494 -0
  251. package/types/rt-tools-ui-kit-v2-date-picker.d.ts +181 -0
  252. package/types/rt-tools-ui-kit-v2-date-range.d.ts +98 -0
  253. package/types/rt-tools-ui-kit-v2-delta-view.d.ts +20 -0
  254. package/types/rt-tools-ui-kit-v2-detail-list.d.ts +33 -0
  255. package/types/rt-tools-ui-kit-v2-dialog.d.ts +287 -0
  256. package/types/rt-tools-ui-kit-v2-dot-field.d.ts +17 -0
  257. package/types/rt-tools-ui-kit-v2-download-link.d.ts +17 -0
  258. package/types/rt-tools-ui-kit-v2-dynamic-list.d.ts +139 -0
  259. package/types/rt-tools-ui-kit-v2-dynamic-selector.d.ts +384 -0
  260. package/types/rt-tools-ui-kit-v2-empty-state.d.ts +29 -0
  261. package/types/rt-tools-ui-kit-v2-expansion-panel.d.ts +57 -0
  262. package/types/rt-tools-ui-kit-v2-field.d.ts +82 -0
  263. package/types/rt-tools-ui-kit-v2-file-card.d.ts +114 -0
  264. package/types/rt-tools-ui-kit-v2-file-drop.d.ts +75 -0
  265. package/types/rt-tools-ui-kit-v2-file-input.d.ts +48 -0
  266. package/types/rt-tools-ui-kit-v2-file-list.d.ts +13 -0
  267. package/types/rt-tools-ui-kit-v2-filter-control.d.ts +72 -0
  268. package/types/rt-tools-ui-kit-v2-form-control.d.ts +74 -0
  269. package/types/rt-tools-ui-kit-v2-header.d.ts +40 -0
  270. package/types/rt-tools-ui-kit-v2-icon-button.d.ts +113 -0
  271. package/types/rt-tools-ui-kit-v2-icon.d.ts +238 -0
  272. package/types/rt-tools-ui-kit-v2-image-cropper.d.ts +168 -0
  273. package/types/rt-tools-ui-kit-v2-image-upload.d.ts +102 -0
  274. package/types/rt-tools-ui-kit-v2-info-item.d.ts +13 -0
  275. package/types/rt-tools-ui-kit-v2-input-number.d.ts +67 -0
  276. package/types/rt-tools-ui-kit-v2-input.d.ts +54 -0
  277. package/types/rt-tools-ui-kit-v2-live-badge.d.ts +23 -0
  278. package/types/rt-tools-ui-kit-v2-logo.d.ts +58 -0
  279. package/types/rt-tools-ui-kit-v2-markdown-text.d.ts +30 -0
  280. package/types/rt-tools-ui-kit-v2-menu.d.ts +217 -0
  281. package/types/rt-tools-ui-kit-v2-message.d.ts +56 -0
  282. package/types/rt-tools-ui-kit-v2-money-list.d.ts +34 -0
  283. package/types/rt-tools-ui-kit-v2-multiselect.d.ts +93 -0
  284. package/types/rt-tools-ui-kit-v2-night-grid.d.ts +39 -0
  285. package/types/rt-tools-ui-kit-v2-note.d.ts +21 -0
  286. package/types/rt-tools-ui-kit-v2-notifications-bell.d.ts +23 -0
  287. package/types/rt-tools-ui-kit-v2-page-header.d.ts +173 -0
  288. package/types/rt-tools-ui-kit-v2-pagination.d.ts +64 -0
  289. package/types/rt-tools-ui-kit-v2-photo-viewer.d.ts +98 -0
  290. package/types/rt-tools-ui-kit-v2-popover.d.ts +79 -0
  291. package/types/rt-tools-ui-kit-v2-radio-button.d.ts +61 -0
  292. package/types/rt-tools-ui-kit-v2-radius.d.ts +37 -0
  293. package/types/rt-tools-ui-kit-v2-rich-editor.d.ts +16 -20
  294. package/types/rt-tools-ui-kit-v2-ripple.d.ts +39 -0
  295. package/types/rt-tools-ui-kit-v2-scroll-area.d.ts +91 -0
  296. package/types/rt-tools-ui-kit-v2-section-nav.d.ts +23 -0
  297. package/types/rt-tools-ui-kit-v2-select.d.ts +215 -0
  298. package/types/rt-tools-ui-kit-v2-side-menu.d.ts +483 -0
  299. package/types/rt-tools-ui-kit-v2-skeleton-wrapper.d.ts +32 -0
  300. package/types/rt-tools-ui-kit-v2-skeleton.d.ts +41 -0
  301. package/types/rt-tools-ui-kit-v2-spinner.d.ts +56 -0
  302. package/types/rt-tools-ui-kit-v2-split-button.d.ts +72 -0
  303. package/types/rt-tools-ui-kit-v2-stat-tile.d.ts +81 -0
  304. package/types/rt-tools-ui-kit-v2-stepper.d.ts +51 -0
  305. package/types/rt-tools-ui-kit-v2-table.d.ts +739 -0
  306. package/types/rt-tools-ui-kit-v2-tabs.d.ts +153 -0
  307. package/types/rt-tools-ui-kit-v2-tag.d.ts +70 -0
  308. package/types/rt-tools-ui-kit-v2-textarea.d.ts +36 -0
  309. package/types/rt-tools-ui-kit-v2-theme-toggle.d.ts +43 -0
  310. package/types/rt-tools-ui-kit-v2-thread-list.d.ts +111 -0
  311. package/types/rt-tools-ui-kit-v2-timeline.d.ts +35 -0
  312. package/types/rt-tools-ui-kit-v2-toast.d.ts +103 -0
  313. package/types/rt-tools-ui-kit-v2-toggle-button-group.d.ts +109 -0
  314. package/types/rt-tools-ui-kit-v2-toggle-switch.d.ts +85 -0
  315. package/types/rt-tools-ui-kit-v2-toolbar.d.ts +66 -0
  316. package/types/rt-tools-ui-kit-v2-tooltip.d.ts +74 -0
  317. package/types/rt-tools-ui-kit-v2-welcome-dialog.d.ts +33 -0
  318. package/types/rt-tools-ui-kit-v2-workspace-details.d.ts +128 -0
  319. package/types/rt-tools-ui-kit-v2-workspace.d.ts +84 -0
  320. package/types/rt-tools-ui-kit-v2.d.ts +87 -9290
  321. package/rt-tools-ui-kit-v2-0.16.0.tgz +0 -0
@@ -0,0 +1,214 @@
1
+ import * as i0 from '@angular/core';
2
+ import { inject, DestroyRef, ElementRef, signal, computed, input, booleanAttribute, output, HostListener, ViewEncapsulation, ChangeDetectionStrategy, Component } from '@angular/core';
3
+ import { BlockDirective, ElemDirective, ModDirective } from '@rt-tools/core';
4
+ import { rtKitLabel } from '@rt-tools/ui-kit-v2/core';
5
+ import * as i1 from '@rt-tools/ui-kit-v2/radius';
6
+ import { RtRadiusDirective } from '@rt-tools/ui-kit-v2/radius';
7
+
8
+ const BEM_BLOCK = 'rt-file-drop';
9
+ /** Задержка скрытия оверлея: dragleave стреляет при переходе между дочерними
10
+ элементами, без debounce рамка мерцает. */
11
+ const DRAG_LEAVE_DEBOUNCE_MS = 80;
12
+ /**
13
+ * Зона перетаскивания файлов: оборачивает произвольный контент через
14
+ * content-projection и превращает его в drop-зону. При перетаскивании файла над
15
+ * областью рисует приглушающий оверлей-приглашение поверх контента, на drop —
16
+ * эмитит выброшенные файлы через `(filesDropped)`.
17
+ *
18
+ * Мультизонный режим: при непустом `zones` оверлей делится на вертикальную стопку
19
+ * равных зон с подписями; зона под курсором подсвечивается, drop эмитится через
20
+ * `(zoneFilesDropped)` с id зоны (а `(filesDropped)` в этом режиме НЕ эмитится).
21
+ * Зона курсора вычисляется по Y-координате против host-rect — оверлей остаётся
22
+ * pointer-events:none, drag-события продолжают идти в host-listener'ы.
23
+ *
24
+ * `accept` (формат как у нативного input[accept]) отфильтровывает неподходящие
25
+ * файлы до эмита — drop в обход файл-пикера не проносит запрещённые расширения;
26
+ * отбрасывание молчаливое, как у самого пикера.
27
+ *
28
+ * Слушает drag-события на собственном host'е (всплывают со всего спроецированного
29
+ * контента), гасит браузерный навигейт по файлу и принимает только перетаскивание
30
+ * файлов (а не внутренний drag элементов формы). Потребитель управляет приёмом
31
+ * через `[disabled]` (например «активна вкладка файлов и форма редактируема») и
32
+ * сам решает, что делать с файлами — компонент состояние файлов не хранит.
33
+ *
34
+ * Оверлей `pointer-events: none` — не перехватывает drag/drop, события доходят до
35
+ * host-listener'ов.
36
+ */
37
+ class RtFileDropComponent {
38
+ #destroyRef;
39
+ #host;
40
+ #t_uiFileDropOverlay;
41
+ #dragLeaveTimer;
42
+ constructor() {
43
+ this.#destroyRef = inject(DestroyRef);
44
+ this.#host = inject(ElementRef);
45
+ this.#t_uiFileDropOverlay = rtKitLabel('uiFileDropOverlay');
46
+ this.#dragLeaveTimer = null;
47
+ /** Активна ли подсветка drop-зоны (файл тащат над областью). */
48
+ this.isDragging = signal(false, /* @ts-ignore */
49
+ ...(ngDevMode ? [{ debugName: "isDragging" }] : /* istanbul ignore next */ []));
50
+ /** Зона под курсором в мультизонном режиме (id из `zones`). */
51
+ this.activeZoneId = signal(null, /* @ts-ignore */
52
+ ...(ngDevMode ? [{ debugName: "activeZoneId" }] : /* istanbul ignore next */ []));
53
+ this.hasZones = computed(() => this.zones().length > 0, /* @ts-ignore */
54
+ ...(ngDevMode ? [{ debugName: "hasZones" }] : /* istanbul ignore next */ []));
55
+ this.overlayText = computed(() => this.overlayLabel() || this.#t_uiFileDropOverlay(), /* @ts-ignore */
56
+ ...(ngDevMode ? [{ debugName: "overlayText" }] : /* istanbul ignore next */ []));
57
+ /** Приём drop'а выключен (потребитель решает по своему контексту). */
58
+ this.disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
59
+ /** Пусто — берётся переведённая подпись по умолчанию */
60
+ this.overlayLabel = input('', /* @ts-ignore */
61
+ ...(ngDevMode ? [{ debugName: "overlayLabel" }] : /* istanbul ignore next */ []));
62
+ /** Мультизонный режим: непустой список зон делит оверлей на стопку целей. */
63
+ this.zones = input([], /* @ts-ignore */
64
+ ...(ngDevMode ? [{ debugName: "zones" }] : /* istanbul ignore next */ []));
65
+ /** Фильтр расширений/MIME (формат нативного input[accept]); пусто — без фильтра. */
66
+ this.accept = input('', /* @ts-ignore */
67
+ ...(ngDevMode ? [{ debugName: "accept" }] : /* istanbul ignore next */ []));
68
+ this.filesDropped = output();
69
+ /** Drop в мультизонном режиме: файлы + id зоны, куда их бросили. */
70
+ this.zoneFilesDropped = output();
71
+ this.draggingChange = output();
72
+ this.#destroyRef.onDestroy(() => this.#clearLeaveTimer());
73
+ }
74
+ onDragOver(event) {
75
+ if (this.disabled() || !this.#isFileDrag(event)) {
76
+ return;
77
+ }
78
+ event.preventDefault();
79
+ event.stopPropagation();
80
+ if (event.dataTransfer) {
81
+ event.dataTransfer.dropEffect = 'copy';
82
+ }
83
+ this.#clearLeaveTimer();
84
+ this.#setDragging(true);
85
+ if (this.hasZones()) {
86
+ this.activeZoneId.set(this.#zoneIdAt(event.clientY));
87
+ }
88
+ }
89
+ onDragLeave(event) {
90
+ if (!this.isDragging()) {
91
+ return;
92
+ }
93
+ event.preventDefault();
94
+ this.#clearLeaveTimer();
95
+ this.#dragLeaveTimer = setTimeout(() => {
96
+ this.#dragLeaveTimer = null;
97
+ this.#setDragging(false);
98
+ }, DRAG_LEAVE_DEBOUNCE_MS);
99
+ }
100
+ onDrop(event) {
101
+ if (this.disabled() || !this.#isFileDrag(event)) {
102
+ return;
103
+ }
104
+ event.preventDefault();
105
+ event.stopPropagation();
106
+ this.#clearLeaveTimer();
107
+ this.#setDragging(false);
108
+ const files = Array.from(event.dataTransfer?.files ?? []).filter((file) => this.#matchesAccept(file));
109
+ if (files.length === 0) {
110
+ return;
111
+ }
112
+ if (!this.hasZones()) {
113
+ this.filesDropped.emit(files);
114
+ return;
115
+ }
116
+ const zoneId = this.#zoneIdAt(event.clientY);
117
+ if (zoneId === null) {
118
+ return;
119
+ }
120
+ this.zoneFilesDropped.emit({ zoneId, files });
121
+ }
122
+ /** Меняет dragging-флаг и эмитит изменение только при реальном переходе. */
123
+ #setDragging(value) {
124
+ if (this.isDragging() === value) {
125
+ return;
126
+ }
127
+ this.isDragging.set(value);
128
+ this.draggingChange.emit(value);
129
+ if (!value) {
130
+ this.activeZoneId.set(null);
131
+ }
132
+ }
133
+ /** Зона по Y-координате курсора: стопка равных по высоте полос host-rect. */
134
+ #zoneIdAt(clientY) {
135
+ const zones = this.zones();
136
+ if (zones.length === 0) {
137
+ return null;
138
+ }
139
+ const rect = this.#host.nativeElement.getBoundingClientRect();
140
+ if (rect.height <= 0) {
141
+ return zones[0].id;
142
+ }
143
+ const ratio = (clientY - rect.top) / rect.height;
144
+ const index = Math.min(zones.length - 1, Math.max(0, Math.floor(ratio * zones.length)));
145
+ return zones[index].id;
146
+ }
147
+ /** Файл проходит accept-фильтр (расширение `.pdf` / MIME `image/png` / `image/*`). */
148
+ #matchesAccept(file) {
149
+ const accept = this.accept().trim();
150
+ if (accept === '') {
151
+ return true;
152
+ }
153
+ const name = file.name.toLowerCase();
154
+ const mime = file.type.toLowerCase();
155
+ return accept.split(',').some((raw) => {
156
+ const token = raw.trim().toLowerCase();
157
+ if (token === '') {
158
+ return false;
159
+ }
160
+ if (token.startsWith('.')) {
161
+ return name.endsWith(token);
162
+ }
163
+ if (token.endsWith('/*')) {
164
+ return mime.startsWith(token.slice(0, -1));
165
+ }
166
+ return mime === token;
167
+ });
168
+ }
169
+ /** Перетаскивают именно файлы (а не внутренний drag элементов формы). */
170
+ #isFileDrag(event) {
171
+ const types = event.dataTransfer?.types;
172
+ return types?.includes('Files') ?? false;
173
+ }
174
+ #clearLeaveTimer() {
175
+ if (this.#dragLeaveTimer !== null) {
176
+ clearTimeout(this.#dragLeaveTimer);
177
+ this.#dragLeaveTimer = null;
178
+ }
179
+ }
180
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: RtFileDropComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
181
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: RtFileDropComponent, isStandalone: true, selector: "rt-file-drop", inputs: { disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, overlayLabel: { classPropertyName: "overlayLabel", publicName: "overlayLabel", isSignal: true, isRequired: false, transformFunction: null }, zones: { classPropertyName: "zones", publicName: "zones", isSignal: true, isRequired: false, transformFunction: null }, accept: { classPropertyName: "accept", publicName: "accept", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { filesDropped: "filesDropped", zoneFilesDropped: "zoneFilesDropped", draggingChange: "draggingChange" }, host: { listeners: { "dragenter": "onDragOver($event)", "dragover": "onDragOver($event)", "dragleave": "onDragLeave($event)", "drop": "onDrop($event)" }, classAttribute: "rt-file-drop" }, hostDirectives: [{ directive: i1.RtRadiusDirective, inputs: ["radius", "radius"] }], ngImport: i0, template: "<ng-container rtBlock=\"rt-file-drop\">\n <ng-content />\n\n @if (isDragging()) {\n <div rtElem=\"overlay\" qa-dataid=\"file-drop-overlay\" aria-hidden=\"true\" [rtMod]=\"{ zoned: hasZones() }\">\n @if (hasZones()) {\n @for (zone of zones(); track zone.id) {\n <div\n rtElem=\"zone\"\n qa-dataid=\"file-drop-zone\"\n [attr.data-zone]=\"zone.id\"\n [attr.data-active]=\"activeZoneId() === zone.id\"\n [rtMod]=\"{ active: activeZoneId() === zone.id }\">\n <span rtElem=\"label\" qa-dataid=\"file-drop-zone-label\">{{ zone.label }}</span>\n @if (zone.sublabel) {\n <span rtElem=\"sublabel\" qa-dataid=\"file-drop-zone-sublabel\">{{ zone.sublabel }}</span>\n }\n </div>\n }\n } @else {\n <div rtElem=\"frame\" qa-dataid=\"file-drop-frame\">\n <span rtElem=\"label\" qa-dataid=\"file-drop-label\">{{ overlayText() }}</span>\n </div>\n }\n </div>\n }\n</ng-container>\n", styles: ["@charset \"UTF-8\";@layer rt-kit.components{.rt-file-drop{--rt-file-drop-radius: var(--rt-radius-lg);--rt-file-drop-border-width: var(--rt-border-width-thin);--rt-file-drop-transition-duration: var(--rt-duration-fast);--rt-file-drop-frame-inset: var(--rt-space-lg);--rt-file-drop-frame-padding: var(--rt-space-md);--rt-file-drop-label-size: var(--rt-text-lg);position:relative;display:block;height:100%}.rt-file-drop__overlay{position:absolute;z-index:50;display:flex;overflow:hidden;align-items:center;justify-content:center;border-radius:var(--rt-file-drop-radius);-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);background:#00000073;container-type:size;inset:var(--rt-space-sm);pointer-events:none}.rt-file-drop__overlay--zoned{flex-direction:column;align-items:stretch;padding:var(--rt-space-md);gap:var(--rt-space-sm)}.rt-file-drop__frame{position:absolute;display:flex;box-sizing:border-box;align-items:center;justify-content:center;padding:var(--rt-file-drop-frame-padding);border:var(--rt-file-drop-border-width) dashed var(--rt-color-action-on-primary);border-radius:var(--rt-file-drop-radius);gap:var(--rt-space-sm);inset:var(--rt-file-drop-frame-inset);text-align:center}.rt-file-drop__zone{display:flex;min-height:0;box-sizing:border-box;flex:1 1 0;flex-direction:column;align-items:center;justify-content:center;padding:var(--rt-space-md);border:var(--rt-file-drop-border-width) dashed var(--rt-color-action-on-primary);border-radius:var(--rt-file-drop-radius);gap:var(--rt-space-2xs);text-align:center;transition:border-color var(--rt-file-drop-transition-duration) ease,background-color var(--rt-file-drop-transition-duration) ease}.rt-file-drop__zone--active{border-style:solid;border-color:var(--rt-color-action-primary);background:#ffffff1a}.rt-file-drop__label{color:var(--rt-color-action-on-primary);font-size:var(--rt-file-drop-label-size);font-weight:var(--rt-font-weight-semibold)}.rt-file-drop__sublabel{color:var(--rt-color-action-on-primary);font-size:var(--rt-text-sm);opacity:.8}.rt-file-drop[data-rt-radius=none]{--rt-file-drop-radius: var(--rt-radius-none)}.rt-file-drop[data-rt-radius=xs]{--rt-file-drop-radius: var(--rt-radius-xs)}.rt-file-drop[data-rt-radius=sm]{--rt-file-drop-radius: var(--rt-radius-sm)}.rt-file-drop[data-rt-radius=ms]{--rt-file-drop-radius: var(--rt-radius-ms)}.rt-file-drop[data-rt-radius=md]{--rt-file-drop-radius: var(--rt-radius-md)}.rt-file-drop[data-rt-radius=lg]{--rt-file-drop-radius: var(--rt-radius-lg)}.rt-file-drop[data-rt-radius=xl]{--rt-file-drop-radius: var(--rt-radius-xl)}.rt-file-drop[data-rt-radius=\"2xl\"]{--rt-file-drop-radius: var(--rt-radius-2xl)}.rt-file-drop[data-rt-radius=full]{--rt-file-drop-radius: var(--rt-radius-full)}@container (max-height: 6rem){.rt-file-drop__frame{--rt-file-drop-frame-inset: var(--rt-space-2xs);--rt-file-drop-frame-padding: var(--rt-space-2xs);--rt-file-drop-label-size: var(--rt-text-xs)}}}\n"], dependencies: [{ kind: "directive", type:
182
+ // standalone components / directives
183
+ BlockDirective, selector: "[rtBlock]", inputs: ["rtMod"] }, { kind: "directive", type: ElemDirective, selector: "[rtElem]", inputs: ["rtMod"] }, { kind: "directive", type: ModDirective, selector: "[rtMod]" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
184
+ }
185
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: RtFileDropComponent, decorators: [{
186
+ type: Component,
187
+ args: [{ selector: 'rt-file-drop', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [
188
+ // standalone components / directives
189
+ BlockDirective,
190
+ ElemDirective,
191
+ ModDirective,
192
+ ], hostDirectives: [{ directive: RtRadiusDirective, inputs: ['radius'] }], host: {
193
+ class: BEM_BLOCK,
194
+ }, template: "<ng-container rtBlock=\"rt-file-drop\">\n <ng-content />\n\n @if (isDragging()) {\n <div rtElem=\"overlay\" qa-dataid=\"file-drop-overlay\" aria-hidden=\"true\" [rtMod]=\"{ zoned: hasZones() }\">\n @if (hasZones()) {\n @for (zone of zones(); track zone.id) {\n <div\n rtElem=\"zone\"\n qa-dataid=\"file-drop-zone\"\n [attr.data-zone]=\"zone.id\"\n [attr.data-active]=\"activeZoneId() === zone.id\"\n [rtMod]=\"{ active: activeZoneId() === zone.id }\">\n <span rtElem=\"label\" qa-dataid=\"file-drop-zone-label\">{{ zone.label }}</span>\n @if (zone.sublabel) {\n <span rtElem=\"sublabel\" qa-dataid=\"file-drop-zone-sublabel\">{{ zone.sublabel }}</span>\n }\n </div>\n }\n } @else {\n <div rtElem=\"frame\" qa-dataid=\"file-drop-frame\">\n <span rtElem=\"label\" qa-dataid=\"file-drop-label\">{{ overlayText() }}</span>\n </div>\n }\n </div>\n }\n</ng-container>\n", styles: ["@charset \"UTF-8\";@layer rt-kit.components{.rt-file-drop{--rt-file-drop-radius: var(--rt-radius-lg);--rt-file-drop-border-width: var(--rt-border-width-thin);--rt-file-drop-transition-duration: var(--rt-duration-fast);--rt-file-drop-frame-inset: var(--rt-space-lg);--rt-file-drop-frame-padding: var(--rt-space-md);--rt-file-drop-label-size: var(--rt-text-lg);position:relative;display:block;height:100%}.rt-file-drop__overlay{position:absolute;z-index:50;display:flex;overflow:hidden;align-items:center;justify-content:center;border-radius:var(--rt-file-drop-radius);-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);background:#00000073;container-type:size;inset:var(--rt-space-sm);pointer-events:none}.rt-file-drop__overlay--zoned{flex-direction:column;align-items:stretch;padding:var(--rt-space-md);gap:var(--rt-space-sm)}.rt-file-drop__frame{position:absolute;display:flex;box-sizing:border-box;align-items:center;justify-content:center;padding:var(--rt-file-drop-frame-padding);border:var(--rt-file-drop-border-width) dashed var(--rt-color-action-on-primary);border-radius:var(--rt-file-drop-radius);gap:var(--rt-space-sm);inset:var(--rt-file-drop-frame-inset);text-align:center}.rt-file-drop__zone{display:flex;min-height:0;box-sizing:border-box;flex:1 1 0;flex-direction:column;align-items:center;justify-content:center;padding:var(--rt-space-md);border:var(--rt-file-drop-border-width) dashed var(--rt-color-action-on-primary);border-radius:var(--rt-file-drop-radius);gap:var(--rt-space-2xs);text-align:center;transition:border-color var(--rt-file-drop-transition-duration) ease,background-color var(--rt-file-drop-transition-duration) ease}.rt-file-drop__zone--active{border-style:solid;border-color:var(--rt-color-action-primary);background:#ffffff1a}.rt-file-drop__label{color:var(--rt-color-action-on-primary);font-size:var(--rt-file-drop-label-size);font-weight:var(--rt-font-weight-semibold)}.rt-file-drop__sublabel{color:var(--rt-color-action-on-primary);font-size:var(--rt-text-sm);opacity:.8}.rt-file-drop[data-rt-radius=none]{--rt-file-drop-radius: var(--rt-radius-none)}.rt-file-drop[data-rt-radius=xs]{--rt-file-drop-radius: var(--rt-radius-xs)}.rt-file-drop[data-rt-radius=sm]{--rt-file-drop-radius: var(--rt-radius-sm)}.rt-file-drop[data-rt-radius=ms]{--rt-file-drop-radius: var(--rt-radius-ms)}.rt-file-drop[data-rt-radius=md]{--rt-file-drop-radius: var(--rt-radius-md)}.rt-file-drop[data-rt-radius=lg]{--rt-file-drop-radius: var(--rt-radius-lg)}.rt-file-drop[data-rt-radius=xl]{--rt-file-drop-radius: var(--rt-radius-xl)}.rt-file-drop[data-rt-radius=\"2xl\"]{--rt-file-drop-radius: var(--rt-radius-2xl)}.rt-file-drop[data-rt-radius=full]{--rt-file-drop-radius: var(--rt-radius-full)}@container (max-height: 6rem){.rt-file-drop__frame{--rt-file-drop-frame-inset: var(--rt-space-2xs);--rt-file-drop-frame-padding: var(--rt-space-2xs);--rt-file-drop-label-size: var(--rt-text-xs)}}}\n"] }]
195
+ }], ctorParameters: () => [], propDecorators: { disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], overlayLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "overlayLabel", required: false }] }], zones: [{ type: i0.Input, args: [{ isSignal: true, alias: "zones", required: false }] }], accept: [{ type: i0.Input, args: [{ isSignal: true, alias: "accept", required: false }] }], filesDropped: [{ type: i0.Output, args: ["filesDropped"] }], zoneFilesDropped: [{ type: i0.Output, args: ["zoneFilesDropped"] }], draggingChange: [{ type: i0.Output, args: ["draggingChange"] }], onDragOver: [{
196
+ type: HostListener,
197
+ args: ['dragenter', ['$event']]
198
+ }, {
199
+ type: HostListener,
200
+ args: ['dragover', ['$event']]
201
+ }], onDragLeave: [{
202
+ type: HostListener,
203
+ args: ['dragleave', ['$event']]
204
+ }], onDrop: [{
205
+ type: HostListener,
206
+ args: ['drop', ['$event']]
207
+ }] } });
208
+
209
+ /**
210
+ * Generated bundle index. Do not edit.
211
+ */
212
+
213
+ export { RtFileDropComponent };
214
+ //# sourceMappingURL=rt-tools-ui-kit-v2-file-drop.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rt-tools-ui-kit-v2-file-drop.mjs","sources":["../../../projects/ui-kit-v2/src/lib/components/file-drop/rt-file-drop.component.ts","../../../projects/ui-kit-v2/src/lib/components/file-drop/rt-file-drop.component.html","../../../projects/ui-kit-v2/src/lib/components/file-drop/rt-tools-ui-kit-v2-file-drop.ts"],"sourcesContent":["import { BooleanInput } from '@angular/cdk/coercion';\nimport {\n booleanAttribute,\n ChangeDetectionStrategy,\n Component,\n computed,\n DestroyRef,\n ElementRef,\n HostListener,\n inject,\n input,\n InputSignal,\n InputSignalWithTransform,\n output,\n OutputEmitterRef,\n Signal,\n signal,\n ViewEncapsulation,\n WritableSignal,\n} from '@angular/core';\n\nimport { BlockDirective, ElemDirective, ModDirective } from '@rt-tools/core';\n\nimport { rtKitLabel } from '@rt-tools/ui-kit-v2/core';\nimport { RtRadiusDirective } from '@rt-tools/ui-kit-v2/radius';\nimport { IRtFileDrop } from './rt-file-drop.model';\n\nconst BEM_BLOCK: string = 'rt-file-drop';\n\n/** Задержка скрытия оверлея: dragleave стреляет при переходе между дочерними\n элементами, без debounce рамка мерцает. */\nconst DRAG_LEAVE_DEBOUNCE_MS: number = 80;\n\n/**\n * Зона перетаскивания файлов: оборачивает произвольный контент через\n * content-projection и превращает его в drop-зону. При перетаскивании файла над\n * областью рисует приглушающий оверлей-приглашение поверх контента, на drop —\n * эмитит выброшенные файлы через `(filesDropped)`.\n *\n * Мультизонный режим: при непустом `zones` оверлей делится на вертикальную стопку\n * равных зон с подписями; зона под курсором подсвечивается, drop эмитится через\n * `(zoneFilesDropped)` с id зоны (а `(filesDropped)` в этом режиме НЕ эмитится).\n * Зона курсора вычисляется по Y-координате против host-rect — оверлей остаётся\n * pointer-events:none, drag-события продолжают идти в host-listener'ы.\n *\n * `accept` (формат как у нативного input[accept]) отфильтровывает неподходящие\n * файлы до эмита — drop в обход файл-пикера не проносит запрещённые расширения;\n * отбрасывание молчаливое, как у самого пикера.\n *\n * Слушает drag-события на собственном host'е (всплывают со всего спроецированного\n * контента), гасит браузерный навигейт по файлу и принимает только перетаскивание\n * файлов (а не внутренний drag элементов формы). Потребитель управляет приёмом\n * через `[disabled]` (например «активна вкладка файлов и форма редактируема») и\n * сам решает, что делать с файлами — компонент состояние файлов не хранит.\n *\n * Оверлей `pointer-events: none` — не перехватывает drag/drop, события доходят до\n * host-listener'ов.\n */\n@Component({\n selector: 'rt-file-drop',\n templateUrl: './rt-file-drop.component.html',\n styleUrl: './rt-file-drop.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n // standalone components / directives\n BlockDirective,\n ElemDirective,\n ModDirective,\n ],\n hostDirectives: [{ directive: RtRadiusDirective, inputs: ['radius'] }],\n host: {\n class: BEM_BLOCK,\n },\n})\nexport class RtFileDropComponent {\n readonly #destroyRef: DestroyRef = inject(DestroyRef);\n\n readonly #host: ElementRef<HTMLElement> = inject(ElementRef);\n\n readonly #t_uiFileDropOverlay: Signal<string> = rtKitLabel('uiFileDropOverlay');\n\n #dragLeaveTimer: ReturnType<typeof setTimeout> | null = null;\n\n /** Активна ли подсветка drop-зоны (файл тащат над областью). */\n protected readonly isDragging: WritableSignal<boolean> = signal(false);\n\n /** Зона под курсором в мультизонном режиме (id из `zones`). */\n protected readonly activeZoneId: WritableSignal<string | null> = signal(null);\n\n protected readonly hasZones: Signal<boolean> = computed((): boolean => this.zones().length > 0);\n\n protected readonly overlayText: Signal<string> = computed((): string => this.overlayLabel() || this.#t_uiFileDropOverlay());\n\n /** Приём drop'а выключен (потребитель решает по своему контексту). */\n public readonly disabled: InputSignalWithTransform<boolean, BooleanInput> = input<boolean, BooleanInput>(false, {\n transform: booleanAttribute,\n });\n\n /** Пусто — берётся переведённая подпись по умолчанию */\n public readonly overlayLabel: InputSignal<string> = input<string>('');\n\n /** Мультизонный режим: непустой список зон делит оверлей на стопку целей. */\n public readonly zones: InputSignal<readonly IRtFileDrop.Zone[]> = input<readonly IRtFileDrop.Zone[]>([]);\n\n /** Фильтр расширений/MIME (формат нативного input[accept]); пусто — без фильтра. */\n public readonly accept: InputSignal<string> = input<string>('');\n\n public readonly filesDropped: OutputEmitterRef<File[]> = output<File[]>();\n\n /** Drop в мультизонном режиме: файлы + id зоны, куда их бросили. */\n public readonly zoneFilesDropped: OutputEmitterRef<IRtFileDrop.ZoneDrop> = output<IRtFileDrop.ZoneDrop>();\n\n public readonly draggingChange: OutputEmitterRef<boolean> = output<boolean>();\n\n constructor() {\n this.#destroyRef.onDestroy((): void => this.#clearLeaveTimer());\n }\n\n @HostListener('dragenter', ['$event'])\n @HostListener('dragover', ['$event'])\n protected onDragOver(event: DragEvent): void {\n if (this.disabled() || !this.#isFileDrag(event)) {\n return;\n }\n event.preventDefault();\n event.stopPropagation();\n if (event.dataTransfer) {\n event.dataTransfer.dropEffect = 'copy';\n }\n this.#clearLeaveTimer();\n this.#setDragging(true);\n if (this.hasZones()) {\n this.activeZoneId.set(this.#zoneIdAt(event.clientY));\n }\n }\n\n @HostListener('dragleave', ['$event'])\n protected onDragLeave(event: DragEvent): void {\n if (!this.isDragging()) {\n return;\n }\n event.preventDefault();\n this.#clearLeaveTimer();\n this.#dragLeaveTimer = setTimeout((): void => {\n this.#dragLeaveTimer = null;\n this.#setDragging(false);\n }, DRAG_LEAVE_DEBOUNCE_MS);\n }\n\n @HostListener('drop', ['$event'])\n protected onDrop(event: DragEvent): void {\n if (this.disabled() || !this.#isFileDrag(event)) {\n return;\n }\n event.preventDefault();\n event.stopPropagation();\n this.#clearLeaveTimer();\n this.#setDragging(false);\n\n const files: File[] = Array.from(event.dataTransfer?.files ?? []).filter((file: File): boolean => this.#matchesAccept(file));\n if (files.length === 0) {\n return;\n }\n if (!this.hasZones()) {\n this.filesDropped.emit(files);\n return;\n }\n const zoneId: string | null = this.#zoneIdAt(event.clientY);\n if (zoneId === null) {\n return;\n }\n this.zoneFilesDropped.emit({ zoneId, files });\n }\n\n /** Меняет dragging-флаг и эмитит изменение только при реальном переходе. */\n #setDragging(value: boolean): void {\n if (this.isDragging() === value) {\n return;\n }\n this.isDragging.set(value);\n this.draggingChange.emit(value);\n if (!value) {\n this.activeZoneId.set(null);\n }\n }\n\n /** Зона по Y-координате курсора: стопка равных по высоте полос host-rect. */\n #zoneIdAt(clientY: number): string | null {\n const zones: readonly IRtFileDrop.Zone[] = this.zones();\n if (zones.length === 0) {\n return null;\n }\n const rect: DOMRect = this.#host.nativeElement.getBoundingClientRect();\n if (rect.height <= 0) {\n return zones[0].id;\n }\n const ratio: number = (clientY - rect.top) / rect.height;\n const index: number = Math.min(zones.length - 1, Math.max(0, Math.floor(ratio * zones.length)));\n return zones[index].id;\n }\n\n /** Файл проходит accept-фильтр (расширение `.pdf` / MIME `image/png` / `image/*`). */\n #matchesAccept(file: File): boolean {\n const accept: string = this.accept().trim();\n if (accept === '') {\n return true;\n }\n const name: string = file.name.toLowerCase();\n const mime: string = file.type.toLowerCase();\n return accept.split(',').some((raw: string): boolean => {\n const token: string = raw.trim().toLowerCase();\n if (token === '') {\n return false;\n }\n if (token.startsWith('.')) {\n return name.endsWith(token);\n }\n if (token.endsWith('/*')) {\n return mime.startsWith(token.slice(0, -1));\n }\n return mime === token;\n });\n }\n\n /** Перетаскивают именно файлы (а не внутренний drag элементов формы). */\n #isFileDrag(event: DragEvent): boolean {\n const types: readonly string[] | undefined = event.dataTransfer?.types;\n return types?.includes('Files') ?? false;\n }\n\n #clearLeaveTimer(): void {\n if (this.#dragLeaveTimer !== null) {\n clearTimeout(this.#dragLeaveTimer);\n this.#dragLeaveTimer = null;\n }\n }\n}\n","<ng-container rtBlock=\"rt-file-drop\">\n <ng-content />\n\n @if (isDragging()) {\n <div rtElem=\"overlay\" qa-dataid=\"file-drop-overlay\" aria-hidden=\"true\" [rtMod]=\"{ zoned: hasZones() }\">\n @if (hasZones()) {\n @for (zone of zones(); track zone.id) {\n <div\n rtElem=\"zone\"\n qa-dataid=\"file-drop-zone\"\n [attr.data-zone]=\"zone.id\"\n [attr.data-active]=\"activeZoneId() === zone.id\"\n [rtMod]=\"{ active: activeZoneId() === zone.id }\">\n <span rtElem=\"label\" qa-dataid=\"file-drop-zone-label\">{{ zone.label }}</span>\n @if (zone.sublabel) {\n <span rtElem=\"sublabel\" qa-dataid=\"file-drop-zone-sublabel\">{{ zone.sublabel }}</span>\n }\n </div>\n }\n } @else {\n <div rtElem=\"frame\" qa-dataid=\"file-drop-frame\">\n <span rtElem=\"label\" qa-dataid=\"file-drop-label\">{{ overlayText() }}</span>\n </div>\n }\n </div>\n }\n</ng-container>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,117 @@
1
+ import * as i0 from '@angular/core';
2
+ import { viewChild, computed, input, booleanAttribute, forwardRef, ViewEncapsulation, ChangeDetectionStrategy, Component } from '@angular/core';
3
+ import { BlockDirective, ElemDirective, ModDirective } from '@rt-tools/core';
4
+ import { rtKitLabel } from '@rt-tools/ui-kit-v2/core';
5
+ import { RtButtonDirective } from '@rt-tools/ui-kit-v2/button';
6
+ import { RtFileCardComponent } from '@rt-tools/ui-kit-v2/file-card';
7
+ import { RtFileListComponent } from '@rt-tools/ui-kit-v2/file-list';
8
+ import { RtFormControlBase } from '@rt-tools/ui-kit-v2/form-control';
9
+
10
+ const BEM_BLOCK = 'rt-file-input';
11
+ /**
12
+ * Поле выбора файлов: кнопка «выбрать» + список выбранных файлов карточками
13
+ * `rt-file-card` (иконка типа, имя, размер, удаление). Скрывает нативный
14
+ * `<input type="file">`, value хранит как `File[]` (одиночный режим = максимум
15
+ * один файл). CVA через общий `RtFormControlBase`. Read-only представление —
16
+ * имена файлов через запятую.
17
+ *
18
+ * Без drag-drop (MVP). `accept` пробрасывается в нативный input, `multiple`
19
+ * включает множественный выбор.
20
+ */
21
+ class RtFileInputComponent extends RtFormControlBase {
22
+ constructor() {
23
+ super(...arguments);
24
+ this.#t_uiChooseFile = rtKitLabel('uiChooseFile');
25
+ this.fileEl = viewChild('fileEl', /* @ts-ignore */
26
+ ...(ngDevMode ? [{ debugName: "fileEl" }] : /* istanbul ignore next */ []));
27
+ this.buttonText = computed(() => this.buttonLabel() || this.#t_uiChooseFile(), /* @ts-ignore */
28
+ ...(ngDevMode ? [{ debugName: "buttonText" }] : /* istanbul ignore next */ []));
29
+ this.hasValue = computed(() => this.value().length > 0, /* @ts-ignore */
30
+ ...(ngDevMode ? [{ debugName: "hasValue" }] : /* istanbul ignore next */ []));
31
+ this.displayText = computed(() => this.value()
32
+ .map((f) => f.name)
33
+ .join(', '), /* @ts-ignore */
34
+ ...(ngDevMode ? [{ debugName: "displayText" }] : /* istanbul ignore next */ []));
35
+ this.multiple = input(false, { ...(ngDevMode ? { debugName: "multiple" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
36
+ this.accept = input(null, /* @ts-ignore */
37
+ ...(ngDevMode ? [{ debugName: "accept" }] : /* istanbul ignore next */ []));
38
+ /**
39
+ * Выбор каталога целиком вместо отдельных файлов. Браузер отдаёт
40
+ * относительные пути (`webkitRelativePath`), по ним вызывающая сторона
41
+ * восстанавливает структуру — иначе пользователю пришлось бы выбирать
42
+ * десятки файлов по одному.
43
+ */
44
+ this.directory = input(false, { ...(ngDevMode ? { debugName: "directory" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
45
+ /** Пусто — берётся переведённая подпись по умолчанию */
46
+ this.buttonLabel = input('', /* @ts-ignore */
47
+ ...(ngDevMode ? [{ debugName: "buttonLabel" }] : /* istanbul ignore next */ []));
48
+ }
49
+ #t_uiChooseFile;
50
+ getEmptyValue() {
51
+ return [];
52
+ }
53
+ focusAfterClear() {
54
+ // Скрытый native input фокусировать бессмысленно — фокус остаётся на кнопке.
55
+ }
56
+ openPicker() {
57
+ if (this.isDisabled()) {
58
+ return;
59
+ }
60
+ this.fileEl()?.nativeElement.click();
61
+ }
62
+ onFiles(event) {
63
+ const list = event.target.files;
64
+ const files = list ? Array.from(list) : [];
65
+ const next = this.multiple() ? files : files.slice(0, 1);
66
+ this.value.set(next);
67
+ this.emitChange(next);
68
+ this.markTouched();
69
+ }
70
+ removeFile(index) {
71
+ if (this.isDisabled()) {
72
+ return;
73
+ }
74
+ const next = this.value().filter((_, i) => i !== index);
75
+ this.value.set(next);
76
+ this.emitChange(next);
77
+ // Сбрасываем native input, иначе повторный выбор того же файла не сработает.
78
+ const el = this.fileEl()?.nativeElement;
79
+ if (el) {
80
+ el.value = '';
81
+ }
82
+ }
83
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: RtFileInputComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
84
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: RtFileInputComponent, isStandalone: true, selector: "rt-file-input", inputs: { multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null }, accept: { classPropertyName: "accept", publicName: "accept", isSignal: true, isRequired: false, transformFunction: null }, directory: { classPropertyName: "directory", publicName: "directory", isSignal: true, isRequired: false, transformFunction: null }, buttonLabel: { classPropertyName: "buttonLabel", publicName: "buttonLabel", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class.rt-file-input--disabled": "isDisabled()", "class.rt-file-input--invalid": "isInvalid()", "class.rt-file-input--readonly": "isReadonly()" }, classAttribute: "rt-file-input" }, providers: [
85
+ // Алиас базового токена — для contentChild(RtFormControlBase) в rt-field.
86
+ { provide: RtFormControlBase, useExisting: forwardRef(() => RtFileInputComponent) },
87
+ ], viewQueries: [{ propertyName: "fileEl", first: true, predicate: ["fileEl"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<ng-container rtBlock=\"rt-file-input\">\n @if (isReadonly()) {\n <span rtElem=\"readonly\" qa-dataid=\"file-input-readonly\" [rtMod]=\"{ empty: !displayText() }\">{{ displayText() || '\u2014' }}</span>\n } @else {\n <input\n #fileEl\n qa-dataid=\"file-input-native\"\n type=\"file\"\n hidden\n [multiple]=\"multiple()\"\n [disabled]=\"isDisabled()\"\n [attr.id]=\"effectiveControlId()\"\n [attr.accept]=\"accept()\"\n [attr.webkitdirectory]=\"directory() ? '' : null\"\n (change)=\"onFiles($event)\" />\n\n <button\n rtElem=\"trigger\"\n qa-dataid=\"file-input-trigger\"\n type=\"button\"\n rtButton\n appearance=\"outlined\"\n icon=\"ico-upload\"\n [label]=\"buttonText()\"\n [attr.aria-label]=\"buttonText()\"\n [disabled]=\"isDisabled()\"\n (click)=\"openPicker()\"></button>\n\n @if (value().length > 0) {\n <rt-file-list rtElem=\"list\" qa-dataid=\"file-input-list\">\n @for (file of value(); track $index) {\n <rt-file-card\n showRemove\n qa-dataid=\"file-input-file\"\n [name]=\"file.name\"\n [sizeBytes]=\"file.size\"\n [disabled]=\"isDisabled()\"\n (removed)=\"removeFile($index)\" />\n }\n </rt-file-list>\n }\n }\n</ng-container>\n", styles: ["@charset \"UTF-8\";@layer rt-kit.components{.rt-file-input{display:flex;flex-direction:column;align-items:flex-start;gap:var(--rt-space-sm)}.rt-file-input--disabled{opacity:var(--rt-input-disabled-opacity)}.rt-file-input__list{width:100%}.rt-file-input__readonly{color:var(--rt-field-value-color);font-size:var(--rt-field-value-font-size)}.rt-file-input__readonly--empty{color:var(--rt-field-value-empty-color)}}\n"], dependencies: [{ kind: "directive", type:
88
+ // standalone components / directives
89
+ RtButtonDirective, selector: "button[rtButton], a[rtButton]", inputs: ["label", "icon", "iconPos", "theme", "appearance", "size", "loading", "loadingIcon", "loadingLabel", "pressed"] }, { kind: "component", type: RtFileCardComponent, selector: "rt-file-card", inputs: ["name", "sizeBytes", "size", "showDownload", "showRemove", "showRename", "disabled"], outputs: ["download", "removed", "rename"] }, { kind: "component", type: RtFileListComponent, selector: "rt-file-list" }, { kind: "directive", type: BlockDirective, selector: "[rtBlock]", inputs: ["rtMod"] }, { kind: "directive", type: ElemDirective, selector: "[rtElem]", inputs: ["rtMod"] }, { kind: "directive", type: ModDirective, selector: "[rtMod]" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
90
+ }
91
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: RtFileInputComponent, decorators: [{
92
+ type: Component,
93
+ args: [{ selector: 'rt-file-input', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [
94
+ // standalone components / directives
95
+ RtButtonDirective,
96
+ RtFileCardComponent,
97
+ RtFileListComponent,
98
+ BlockDirective,
99
+ ElemDirective,
100
+ ModDirective,
101
+ ], providers: [
102
+ // Алиас базового токена — для contentChild(RtFormControlBase) в rt-field.
103
+ { provide: RtFormControlBase, useExisting: forwardRef(() => RtFileInputComponent) },
104
+ ], host: {
105
+ class: BEM_BLOCK,
106
+ '[class.rt-file-input--disabled]': 'isDisabled()',
107
+ '[class.rt-file-input--invalid]': 'isInvalid()',
108
+ '[class.rt-file-input--readonly]': 'isReadonly()',
109
+ }, template: "<ng-container rtBlock=\"rt-file-input\">\n @if (isReadonly()) {\n <span rtElem=\"readonly\" qa-dataid=\"file-input-readonly\" [rtMod]=\"{ empty: !displayText() }\">{{ displayText() || '\u2014' }}</span>\n } @else {\n <input\n #fileEl\n qa-dataid=\"file-input-native\"\n type=\"file\"\n hidden\n [multiple]=\"multiple()\"\n [disabled]=\"isDisabled()\"\n [attr.id]=\"effectiveControlId()\"\n [attr.accept]=\"accept()\"\n [attr.webkitdirectory]=\"directory() ? '' : null\"\n (change)=\"onFiles($event)\" />\n\n <button\n rtElem=\"trigger\"\n qa-dataid=\"file-input-trigger\"\n type=\"button\"\n rtButton\n appearance=\"outlined\"\n icon=\"ico-upload\"\n [label]=\"buttonText()\"\n [attr.aria-label]=\"buttonText()\"\n [disabled]=\"isDisabled()\"\n (click)=\"openPicker()\"></button>\n\n @if (value().length > 0) {\n <rt-file-list rtElem=\"list\" qa-dataid=\"file-input-list\">\n @for (file of value(); track $index) {\n <rt-file-card\n showRemove\n qa-dataid=\"file-input-file\"\n [name]=\"file.name\"\n [sizeBytes]=\"file.size\"\n [disabled]=\"isDisabled()\"\n (removed)=\"removeFile($index)\" />\n }\n </rt-file-list>\n }\n }\n</ng-container>\n", styles: ["@charset \"UTF-8\";@layer rt-kit.components{.rt-file-input{display:flex;flex-direction:column;align-items:flex-start;gap:var(--rt-space-sm)}.rt-file-input--disabled{opacity:var(--rt-input-disabled-opacity)}.rt-file-input__list{width:100%}.rt-file-input__readonly{color:var(--rt-field-value-color);font-size:var(--rt-field-value-font-size)}.rt-file-input__readonly--empty{color:var(--rt-field-value-empty-color)}}\n"] }]
110
+ }], propDecorators: { fileEl: [{ type: i0.ViewChild, args: ['fileEl', { isSignal: true }] }], multiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiple", required: false }] }], accept: [{ type: i0.Input, args: [{ isSignal: true, alias: "accept", required: false }] }], directory: [{ type: i0.Input, args: [{ isSignal: true, alias: "directory", required: false }] }], buttonLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "buttonLabel", required: false }] }] } });
111
+
112
+ /**
113
+ * Generated bundle index. Do not edit.
114
+ */
115
+
116
+ export { RtFileInputComponent };
117
+ //# sourceMappingURL=rt-tools-ui-kit-v2-file-input.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rt-tools-ui-kit-v2-file-input.mjs","sources":["../../../projects/ui-kit-v2/src/lib/components/file-input/rt-file-input.component.ts","../../../projects/ui-kit-v2/src/lib/components/file-input/rt-file-input.component.html","../../../projects/ui-kit-v2/src/lib/components/file-input/rt-tools-ui-kit-v2-file-input.ts"],"sourcesContent":["import { BooleanInput } from '@angular/cdk/coercion';\nimport {\n booleanAttribute,\n ChangeDetectionStrategy,\n Component,\n computed,\n ElementRef,\n forwardRef,\n input,\n InputSignal,\n InputSignalWithTransform,\n Signal,\n viewChild,\n ViewEncapsulation,\n} from '@angular/core';\n\nimport { BlockDirective, ElemDirective, ModDirective } from '@rt-tools/core';\n\nimport { rtKitLabel } from '@rt-tools/ui-kit-v2/core';\nimport { RtButtonDirective } from '@rt-tools/ui-kit-v2/button';\nimport { RtFileCardComponent } from '@rt-tools/ui-kit-v2/file-card';\nimport { RtFileListComponent } from '@rt-tools/ui-kit-v2/file-list';\nimport { RtFormControlBase } from '@rt-tools/ui-kit-v2/form-control';\n\nconst BEM_BLOCK: string = 'rt-file-input';\n\n/**\n * Поле выбора файлов: кнопка «выбрать» + список выбранных файлов карточками\n * `rt-file-card` (иконка типа, имя, размер, удаление). Скрывает нативный\n * `<input type=\"file\">`, value хранит как `File[]` (одиночный режим = максимум\n * один файл). CVA через общий `RtFormControlBase`. Read-only представление —\n * имена файлов через запятую.\n *\n * Без drag-drop (MVP). `accept` пробрасывается в нативный input, `multiple`\n * включает множественный выбор.\n */\n@Component({\n selector: 'rt-file-input',\n templateUrl: './rt-file-input.component.html',\n styleUrls: ['./rt-file-input.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n // standalone components / directives\n RtButtonDirective,\n RtFileCardComponent,\n RtFileListComponent,\n BlockDirective,\n ElemDirective,\n ModDirective,\n ],\n providers: [\n // Алиас базового токена — для contentChild(RtFormControlBase) в rt-field.\n { provide: RtFormControlBase, useExisting: forwardRef(() => RtFileInputComponent) },\n ],\n host: {\n class: BEM_BLOCK,\n '[class.rt-file-input--disabled]': 'isDisabled()',\n '[class.rt-file-input--invalid]': 'isInvalid()',\n '[class.rt-file-input--readonly]': 'isReadonly()',\n },\n})\nexport class RtFileInputComponent extends RtFormControlBase<File[]> {\n readonly #t_uiChooseFile: Signal<string> = rtKitLabel('uiChooseFile');\n\n protected readonly fileEl: Signal<ElementRef<HTMLInputElement> | undefined> = viewChild<ElementRef<HTMLInputElement>>('fileEl');\n\n protected readonly buttonText: Signal<string> = computed((): string => this.buttonLabel() || this.#t_uiChooseFile());\n\n protected readonly hasValue: Signal<boolean> = computed((): boolean => this.value().length > 0);\n\n public readonly displayText: Signal<string> = computed((): string =>\n this.value()\n .map((f: File): string => f.name)\n .join(', ')\n );\n\n public readonly multiple: InputSignalWithTransform<boolean, BooleanInput> = input<boolean, BooleanInput>(false, {\n transform: booleanAttribute,\n });\n public readonly accept: InputSignal<string | null> = input<string | null>(null);\n\n /**\n * Выбор каталога целиком вместо отдельных файлов. Браузер отдаёт\n * относительные пути (`webkitRelativePath`), по ним вызывающая сторона\n * восстанавливает структуру — иначе пользователю пришлось бы выбирать\n * десятки файлов по одному.\n */\n public readonly directory: InputSignalWithTransform<boolean, BooleanInput> = input<boolean, BooleanInput>(false, {\n transform: booleanAttribute,\n });\n /** Пусто — берётся переведённая подпись по умолчанию */\n public readonly buttonLabel: InputSignal<string> = input<string>('');\n\n protected getEmptyValue(): File[] {\n return [];\n }\n\n protected focusAfterClear(): void {\n // Скрытый native input фокусировать бессмысленно — фокус остаётся на кнопке.\n }\n\n protected openPicker(): void {\n if (this.isDisabled()) {\n return;\n }\n this.fileEl()?.nativeElement.click();\n }\n\n protected onFiles(event: Event): void {\n const list: FileList | null = (event.target as HTMLInputElement).files;\n const files: File[] = list ? Array.from(list) : [];\n const next: File[] = this.multiple() ? files : files.slice(0, 1);\n this.value.set(next);\n this.emitChange(next);\n this.markTouched();\n }\n\n protected removeFile(index: number): void {\n if (this.isDisabled()) {\n return;\n }\n const next: File[] = this.value().filter((_: File, i: number): boolean => i !== index);\n this.value.set(next);\n this.emitChange(next);\n // Сбрасываем native input, иначе повторный выбор того же файла не сработает.\n const el: HTMLInputElement | undefined = this.fileEl()?.nativeElement;\n if (el) {\n el.value = '';\n }\n }\n}\n","<ng-container rtBlock=\"rt-file-input\">\n @if (isReadonly()) {\n <span rtElem=\"readonly\" qa-dataid=\"file-input-readonly\" [rtMod]=\"{ empty: !displayText() }\">{{ displayText() || '—' }}</span>\n } @else {\n <input\n #fileEl\n qa-dataid=\"file-input-native\"\n type=\"file\"\n hidden\n [multiple]=\"multiple()\"\n [disabled]=\"isDisabled()\"\n [attr.id]=\"effectiveControlId()\"\n [attr.accept]=\"accept()\"\n [attr.webkitdirectory]=\"directory() ? '' : null\"\n (change)=\"onFiles($event)\" />\n\n <button\n rtElem=\"trigger\"\n qa-dataid=\"file-input-trigger\"\n type=\"button\"\n rtButton\n appearance=\"outlined\"\n icon=\"ico-upload\"\n [label]=\"buttonText()\"\n [attr.aria-label]=\"buttonText()\"\n [disabled]=\"isDisabled()\"\n (click)=\"openPicker()\"></button>\n\n @if (value().length > 0) {\n <rt-file-list rtElem=\"list\" qa-dataid=\"file-input-list\">\n @for (file of value(); track $index) {\n <rt-file-card\n showRemove\n qa-dataid=\"file-input-file\"\n [name]=\"file.name\"\n [sizeBytes]=\"file.size\"\n [disabled]=\"isDisabled()\"\n (removed)=\"removeFile($index)\" />\n }\n </rt-file-list>\n }\n }\n</ng-container>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ import * as i0 from '@angular/core';
2
+ import { ViewEncapsulation, ChangeDetectionStrategy, Component } from '@angular/core';
3
+ import { BlockDirective } from '@rt-tools/core';
4
+
5
+ const BEM_BLOCK = 'rt-file-list';
6
+ /**
7
+ * Вертикальный контейнер для карточек файлов (`rt-file-card`): задаёт отступы между
8
+ * карточками и растягивает их по ширине. Чисто презентационный — содержимое
9
+ * проецируется через `<ng-content />`, логику списка держит caller.
10
+ */
11
+ class RtFileListComponent {
12
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: RtFileListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
13
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.1.6", type: RtFileListComponent, isStandalone: true, selector: "rt-file-list", host: { classAttribute: "rt-file-list" }, ngImport: i0, template: "<ng-container rtBlock=\"rt-file-list\">\n <ng-content />\n</ng-container>\n", styles: ["@charset \"UTF-8\";@layer rt-kit.components{.rt-file-list{display:flex;width:100%;flex-direction:column;gap:var(--rt-space-sm)}}\n"], dependencies: [{ kind: "directive", type:
14
+ // standalone components / directives
15
+ BlockDirective, selector: "[rtBlock]", inputs: ["rtMod"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
16
+ }
17
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: RtFileListComponent, decorators: [{
18
+ type: Component,
19
+ args: [{ selector: 'rt-file-list', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [
20
+ // standalone components / directives
21
+ BlockDirective,
22
+ ], host: {
23
+ class: BEM_BLOCK,
24
+ }, template: "<ng-container rtBlock=\"rt-file-list\">\n <ng-content />\n</ng-container>\n", styles: ["@charset \"UTF-8\";@layer rt-kit.components{.rt-file-list{display:flex;width:100%;flex-direction:column;gap:var(--rt-space-sm)}}\n"] }]
25
+ }] });
26
+
27
+ /**
28
+ * Generated bundle index. Do not edit.
29
+ */
30
+
31
+ export { RtFileListComponent };
32
+ //# sourceMappingURL=rt-tools-ui-kit-v2-file-list.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rt-tools-ui-kit-v2-file-list.mjs","sources":["../../../projects/ui-kit-v2/src/lib/components/file-list/rt-file-list.component.ts","../../../projects/ui-kit-v2/src/lib/components/file-list/rt-file-list.component.html","../../../projects/ui-kit-v2/src/lib/components/file-list/rt-tools-ui-kit-v2-file-list.ts"],"sourcesContent":["import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';\n\nimport { BlockDirective } from '@rt-tools/core';\n\nconst BEM_BLOCK: string = 'rt-file-list';\n\n/**\n * Вертикальный контейнер для карточек файлов (`rt-file-card`): задаёт отступы между\n * карточками и растягивает их по ширине. Чисто презентационный — содержимое\n * проецируется через `<ng-content />`, логику списка держит caller.\n */\n@Component({\n selector: 'rt-file-list',\n templateUrl: './rt-file-list.component.html',\n styleUrls: ['./rt-file-list.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n // standalone components / directives\n BlockDirective,\n ],\n host: {\n class: BEM_BLOCK,\n },\n})\nexport class RtFileListComponent {}\n","<ng-container rtBlock=\"rt-file-list\">\n <ng-content />\n</ng-container>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;AAIA,MAAM,SAAS,GAAW,cAAc;AAExC;;;;AAIG;MAeU,mBAAmB,CAAA;8GAAnB,mBAAmB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA,CAAA;AAAnB,IAAA,SAAA,IAAA,CAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,mBAAmB,kHCzBhC,gFAGA,EAAA,MAAA,EAAA,CAAA,oIAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA;;gBDgBQ,cAAc,EAAA,QAAA,EAAA,WAAA,EAAA,MAAA,EAAA,CAAA,OAAA,CAAA,EAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,aAAA,EAAA,EAAA,CAAA,iBAAA,CAAA,IAAA,EAAA,CAAA,CAAA;;2FAMT,mBAAmB,EAAA,UAAA,EAAA,CAAA;kBAd/B,SAAS;+BACI,cAAc,EAAA,eAAA,EAGP,uBAAuB,CAAC,MAAM,iBAChC,iBAAiB,CAAC,IAAI,EAAA,OAAA,EAC5B;;wBAEL,cAAc;qBACjB,EAAA,IAAA,EACK;AACF,wBAAA,KAAK,EAAE,SAAS;AACnB,qBAAA,EAAA,QAAA,EAAA,gFAAA,EAAA,MAAA,EAAA,CAAA,oIAAA,CAAA,EAAA;;;AEvBL;;AAEG;;;;"}
@@ -0,0 +1,91 @@
1
+ import * as i0 from '@angular/core';
2
+ import { inject, computed, input, booleanAttribute, output, ViewEncapsulation, ChangeDetectionStrategy, Component } from '@angular/core';
3
+ import * as i1 from '@angular/forms';
4
+ import { FormsModule } from '@angular/forms';
5
+ import { BreakpointsService } from '@rt-tools/ui-kit-v2/core';
6
+ import { RtSelectComponent } from '@rt-tools/ui-kit-v2/select';
7
+ import { RtToggleButtonGroupComponent } from '@rt-tools/ui-kit-v2/toggle-button-group';
8
+
9
+ const BEM_BLOCK = 'rt-filter-control';
10
+ /**
11
+ * Адаптивный фильтр-контрол для тулбаров list-страниц.
12
+ *
13
+ * Один и тот же набор опций рендерится двумя способами по ширине вьюпорта:
14
+ * - десктоп (> 1080px) — развёрнутые сегменты `rt-toggle-button-group`;
15
+ * - узкий экран (≤ 1080px, `BreakpointsService.narrow`) — компактный
16
+ * `rt-select` с `clearable=false` (сброс — через явную опцию «Все»).
17
+ *
18
+ * API повторяет controlled-контракт rt-toggle-button-group (`[options]` /
19
+ * `[value]` / `(valueChange)`), поэтому миграция потребителя — смена селектора
20
+ * без правки хендлеров. Sentinel «нет фильтра» задаёт сам потребитель реальным
21
+ * значением опции («»/false), а не `null`/`undefined` — rt-select всегда
22
+ * показывает выбранную опцию.
23
+ *
24
+ * Generic `<T = string>` сохраняет типизацию по value (union'ы, enum'ы).
25
+ */
26
+ class RtFilterControlComponent {
27
+ constructor() {
28
+ this.#breakpoints = inject(BreakpointsService);
29
+ this.isNarrow = this.#breakpoints.narrow;
30
+ /** Проекция опций фильтра в форму rt-select (icon/title отбрасываются). */
31
+ this.selectOptions = computed(() => this.options().map((option) => ({
32
+ label: option.label,
33
+ value: option.value,
34
+ })), /* @ts-ignore */
35
+ ...(ngDevMode ? [{ debugName: "selectOptions" }] : /* istanbul ignore next */ []));
36
+ this.options = input.required(/* @ts-ignore */
37
+ ...(ngDevMode ? [{ debugName: "options" }] : /* istanbul ignore next */ []));
38
+ this.value = input(undefined, /* @ts-ignore */
39
+ ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
40
+ this.ariaLabel = input(null, /* @ts-ignore */
41
+ ...(ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
42
+ this.placeholder = input('', /* @ts-ignore */
43
+ ...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
44
+ /**
45
+ * Размер сегментов (десктоп). На узком экране select всегда рендерится в md,
46
+ * чтобы совпадать по высоте и ширине со строкой поиска list-страницы.
47
+ */
48
+ this.size = input('sm', /* @ts-ignore */
49
+ ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
50
+ this.disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
51
+ /** Растягивает сегменты на всю ширину контейнера (только десктоп-вариант). */
52
+ this.fullWidth = input(false, { ...(ngDevMode ? { debugName: "fullWidth" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
53
+ this.valueChange = output();
54
+ }
55
+ #breakpoints;
56
+ onValueChange(value) {
57
+ this.valueChange.emit(value);
58
+ }
59
+ onSelectionChange(value) {
60
+ // rt-select с clearable=false и явной опцией «Все» не эмитит null,
61
+ // но guard оставляем на случай программной очистки.
62
+ if (value !== null) {
63
+ this.valueChange.emit(value);
64
+ }
65
+ }
66
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: RtFilterControlComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
67
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: RtFilterControlComponent, isStandalone: true, selector: "rt-filter-control", inputs: { options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: true, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, fullWidth: { classPropertyName: "fullWidth", publicName: "fullWidth", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueChange: "valueChange" }, host: { classAttribute: "rt-filter-control" }, ngImport: i0, template: "@if (isNarrow()) {\n <rt-select\n qa-dataid=\"filter-control-select\"\n size=\"md\"\n [options]=\"selectOptions()\"\n [placeholder]=\"placeholder()\"\n [ariaLabel]=\"ariaLabel()\"\n [clearable]=\"false\"\n [disabled]=\"disabled()\"\n [ngModel]=\"value()\"\n (selectionChange)=\"onSelectionChange($event)\" />\n} @else {\n <rt-toggle-button-group\n qa-dataid=\"filter-control-group\"\n [options]=\"options()\"\n [value]=\"value()\"\n [ariaLabel]=\"ariaLabel()\"\n [size]=\"size()\"\n [disabled]=\"disabled()\"\n [fullWidth]=\"fullWidth()\"\n (valueChange)=\"onValueChange($event)\" />\n}\n", styles: ["@layer rt-kit.components{.rt-filter-control{display:inline-flex}@media(width<=1080px){.rt-filter-control{display:block}.rt-filter-control .rt-select{inline-size:100%;max-inline-size:var(--rt-input-max-width)}}@media(width<=768px){.rt-filter-control{inline-size:100%}}}\n"], dependencies: [{ kind: "ngmodule", type:
68
+ // Angular
69
+ 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: "component", type:
70
+ // standalone components / directives
71
+ RtSelectComponent, selector: "rt-select", inputs: ["appearance", "options", "placeholder", "iconLeft", "filter", "filterPlaceholder", "panelWidth", "panelMaxHeight"], outputs: ["selectionChange"] }, { kind: "component", type: RtToggleButtonGroupComponent, selector: "rt-toggle-button-group", inputs: ["options", "value", "multiple", "values", "ariaLabel", "size", "disabled", "fullWidth"], outputs: ["valueChange", "valuesChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
72
+ }
73
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: RtFilterControlComponent, decorators: [{
74
+ type: Component,
75
+ args: [{ selector: 'rt-filter-control', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [
76
+ // Angular
77
+ FormsModule,
78
+ // standalone components / directives
79
+ RtSelectComponent,
80
+ RtToggleButtonGroupComponent,
81
+ ], host: {
82
+ class: BEM_BLOCK,
83
+ }, template: "@if (isNarrow()) {\n <rt-select\n qa-dataid=\"filter-control-select\"\n size=\"md\"\n [options]=\"selectOptions()\"\n [placeholder]=\"placeholder()\"\n [ariaLabel]=\"ariaLabel()\"\n [clearable]=\"false\"\n [disabled]=\"disabled()\"\n [ngModel]=\"value()\"\n (selectionChange)=\"onSelectionChange($event)\" />\n} @else {\n <rt-toggle-button-group\n qa-dataid=\"filter-control-group\"\n [options]=\"options()\"\n [value]=\"value()\"\n [ariaLabel]=\"ariaLabel()\"\n [size]=\"size()\"\n [disabled]=\"disabled()\"\n [fullWidth]=\"fullWidth()\"\n (valueChange)=\"onValueChange($event)\" />\n}\n", styles: ["@layer rt-kit.components{.rt-filter-control{display:inline-flex}@media(width<=1080px){.rt-filter-control{display:block}.rt-filter-control .rt-select{inline-size:100%;max-inline-size:var(--rt-input-max-width)}}@media(width<=768px){.rt-filter-control{inline-size:100%}}}\n"] }]
84
+ }], propDecorators: { options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: true }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], fullWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "fullWidth", required: false }] }], valueChange: [{ type: i0.Output, args: ["valueChange"] }] } });
85
+
86
+ /**
87
+ * Generated bundle index. Do not edit.
88
+ */
89
+
90
+ export { RtFilterControlComponent };
91
+ //# sourceMappingURL=rt-tools-ui-kit-v2-filter-control.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rt-tools-ui-kit-v2-filter-control.mjs","sources":["../../../projects/ui-kit-v2/src/lib/components/filter-control/rt-filter-control.component.ts","../../../projects/ui-kit-v2/src/lib/components/filter-control/rt-filter-control.component.html","../../../projects/ui-kit-v2/src/lib/components/filter-control/rt-tools-ui-kit-v2-filter-control.ts"],"sourcesContent":["import { BooleanInput } from '@angular/cdk/coercion';\nimport {\n booleanAttribute,\n ChangeDetectionStrategy,\n Component,\n computed,\n inject,\n input,\n InputSignal,\n InputSignalWithTransform,\n output,\n OutputEmitterRef,\n Signal,\n ViewEncapsulation,\n} from '@angular/core';\nimport { FormsModule } from '@angular/forms';\n\nimport { BreakpointsService } from '@rt-tools/ui-kit-v2/core';\n\nimport { RtSelectComponent } from '@rt-tools/ui-kit-v2/select';\nimport { IRtSelect } from '@rt-tools/ui-kit-v2/select';\nimport { RtToggleButtonGroupComponent } from '@rt-tools/ui-kit-v2/toggle-button-group';\nimport { IRtFilterControl } from './rt-filter-control.model';\n\nconst BEM_BLOCK: string = 'rt-filter-control';\n\n/**\n * Адаптивный фильтр-контрол для тулбаров list-страниц.\n *\n * Один и тот же набор опций рендерится двумя способами по ширине вьюпорта:\n * - десктоп (> 1080px) — развёрнутые сегменты `rt-toggle-button-group`;\n * - узкий экран (≤ 1080px, `BreakpointsService.narrow`) — компактный\n * `rt-select` с `clearable=false` (сброс — через явную опцию «Все»).\n *\n * API повторяет controlled-контракт rt-toggle-button-group (`[options]` /\n * `[value]` / `(valueChange)`), поэтому миграция потребителя — смена селектора\n * без правки хендлеров. Sentinel «нет фильтра» задаёт сам потребитель реальным\n * значением опции («»/false), а не `null`/`undefined` — rt-select всегда\n * показывает выбранную опцию.\n *\n * Generic `<T = string>` сохраняет типизацию по value (union'ы, enum'ы).\n */\n@Component({\n selector: 'rt-filter-control',\n templateUrl: './rt-filter-control.component.html',\n styleUrls: ['./rt-filter-control.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n imports: [\n // Angular\n FormsModule,\n\n // standalone components / directives\n RtSelectComponent,\n RtToggleButtonGroupComponent,\n ],\n host: {\n class: BEM_BLOCK,\n },\n})\nexport class RtFilterControlComponent<T = string> {\n readonly #breakpoints: BreakpointsService = inject(BreakpointsService);\n\n protected readonly isNarrow: Signal<boolean> = this.#breakpoints.narrow;\n\n /** Проекция опций фильтра в форму rt-select (icon/title отбрасываются). */\n protected readonly selectOptions: Signal<ReadonlyArray<IRtSelect.Option<T>>> = computed((): ReadonlyArray<IRtSelect.Option<T>> =>\n this.options().map((option: IRtFilterControl.Option<T>): IRtSelect.Option<T> => ({\n label: option.label,\n value: option.value,\n }))\n );\n\n public readonly options: InputSignal<ReadonlyArray<IRtFilterControl.Option<T>>> =\n input.required<ReadonlyArray<IRtFilterControl.Option<T>>>();\n\n public readonly value: InputSignal<T | undefined> = input<T | undefined>(undefined);\n\n public readonly ariaLabel: InputSignal<string | null> = input<string | null>(null);\n\n public readonly placeholder: InputSignal<string> = input<string>('');\n\n /**\n * Размер сегментов (десктоп). На узком экране select всегда рендерится в md,\n * чтобы совпадать по высоте и ширине со строкой поиска list-страницы.\n */\n public readonly size: InputSignal<IRtFilterControl.Size> = input<IRtFilterControl.Size>('sm');\n\n public readonly disabled: InputSignalWithTransform<boolean, BooleanInput> = input<boolean, BooleanInput>(false, {\n transform: booleanAttribute,\n });\n\n /** Растягивает сегменты на всю ширину контейнера (только десктоп-вариант). */\n public readonly fullWidth: InputSignalWithTransform<boolean, BooleanInput> = input<boolean, BooleanInput>(false, {\n transform: booleanAttribute,\n });\n\n public readonly valueChange: OutputEmitterRef<T> = output<T>();\n\n protected onValueChange(value: T): void {\n this.valueChange.emit(value);\n }\n\n protected onSelectionChange(value: T | null): void {\n // rt-select с clearable=false и явной опцией «Все» не эмитит null,\n // но guard оставляем на случай программной очистки.\n if (value !== null) {\n this.valueChange.emit(value);\n }\n }\n}\n","@if (isNarrow()) {\n <rt-select\n qa-dataid=\"filter-control-select\"\n size=\"md\"\n [options]=\"selectOptions()\"\n [placeholder]=\"placeholder()\"\n [ariaLabel]=\"ariaLabel()\"\n [clearable]=\"false\"\n [disabled]=\"disabled()\"\n [ngModel]=\"value()\"\n (selectionChange)=\"onSelectionChange($event)\" />\n} @else {\n <rt-toggle-button-group\n qa-dataid=\"filter-control-group\"\n [options]=\"options()\"\n [value]=\"value()\"\n [ariaLabel]=\"ariaLabel()\"\n [size]=\"size()\"\n [disabled]=\"disabled()\"\n [fullWidth]=\"fullWidth()\"\n (valueChange)=\"onValueChange($event)\" />\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}