@ng-cn/core 1.0.10 → 1.0.12

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 (392) hide show
  1. package/package.json +3 -2
  2. package/src/app/lib/components/ui/accordion/accordion-content.component.ts +53 -0
  3. package/src/app/lib/components/ui/accordion/accordion-context.ts +33 -0
  4. package/src/app/lib/components/ui/accordion/accordion-item.component.ts +86 -0
  5. package/src/app/lib/components/ui/accordion/accordion-trigger.component.ts +73 -0
  6. package/src/app/lib/components/ui/accordion/accordion.component.ts +197 -0
  7. package/src/app/lib/components/ui/accordion/index.ts +15 -0
  8. package/src/app/lib/components/ui/alert/alert-description.component.ts +33 -0
  9. package/src/app/lib/components/ui/alert/alert-title.component.ts +30 -0
  10. package/src/app/lib/components/ui/alert/alert-variants.ts +23 -0
  11. package/src/app/lib/components/ui/alert/alert.component.ts +50 -0
  12. package/src/app/lib/components/ui/alert/index.ts +5 -0
  13. package/src/app/lib/components/ui/alert-dialog/alert-dialog-action.component.ts +44 -0
  14. package/src/app/lib/components/ui/alert-dialog/alert-dialog-cancel.component.ts +45 -0
  15. package/src/app/lib/components/ui/alert-dialog/alert-dialog-content.component.ts +146 -0
  16. package/src/app/lib/components/ui/alert-dialog/alert-dialog-context.ts +14 -0
  17. package/src/app/lib/components/ui/alert-dialog/alert-dialog-description.component.ts +37 -0
  18. package/src/app/lib/components/ui/alert-dialog/alert-dialog-footer.component.ts +35 -0
  19. package/src/app/lib/components/ui/alert-dialog/alert-dialog-header.component.ts +35 -0
  20. package/src/app/lib/components/ui/alert-dialog/alert-dialog-title.component.ts +37 -0
  21. package/src/app/lib/components/ui/alert-dialog/alert-dialog-trigger.component.ts +44 -0
  22. package/src/app/lib/components/ui/alert-dialog/alert-dialog.component.ts +91 -0
  23. package/src/app/lib/components/ui/alert-dialog/index.ts +11 -0
  24. package/src/app/lib/components/ui/aspect-ratio/aspect-ratio.component.ts +63 -0
  25. package/src/app/lib/components/ui/aspect-ratio/index.ts +1 -0
  26. package/src/app/lib/components/ui/avatar/avatar-fallback.component.ts +34 -0
  27. package/src/app/lib/components/ui/avatar/avatar-image.component.ts +31 -0
  28. package/src/app/lib/components/ui/avatar/avatar.component.ts +37 -0
  29. package/src/app/lib/components/ui/avatar/index.ts +5 -0
  30. package/src/app/lib/components/ui/avatar/ui-avatar.component.ts +52 -0
  31. package/src/app/lib/components/ui/badge/badge-variants.ts +28 -0
  32. package/src/app/lib/components/ui/badge/badge.component.ts +50 -0
  33. package/src/app/lib/components/ui/badge/index.ts +3 -0
  34. package/src/app/lib/components/ui/breadcrumb/breadcrumb-ellipsis.component.ts +48 -0
  35. package/src/app/lib/components/ui/breadcrumb/breadcrumb-item.component.ts +28 -0
  36. package/src/app/lib/components/ui/breadcrumb/breadcrumb-link.component.ts +32 -0
  37. package/src/app/lib/components/ui/breadcrumb/breadcrumb-list.component.ts +31 -0
  38. package/src/app/lib/components/ui/breadcrumb/breadcrumb-page.component.ts +31 -0
  39. package/src/app/lib/components/ui/breadcrumb/breadcrumb-separator.component.ts +47 -0
  40. package/src/app/lib/components/ui/breadcrumb/breadcrumb.component.ts +43 -0
  41. package/src/app/lib/components/ui/breadcrumb/index.ts +8 -0
  42. package/src/app/lib/components/ui/button/button-variants.ts +38 -0
  43. package/src/app/lib/components/ui/button/button.component.ts +103 -0
  44. package/src/app/lib/components/ui/button/index.ts +3 -0
  45. package/src/app/lib/components/ui/button-group/button-group-variants.ts +24 -0
  46. package/src/app/lib/components/ui/button-group/button-group.component.ts +57 -0
  47. package/src/app/lib/components/ui/button-group/index.ts +6 -0
  48. package/src/app/lib/components/ui/calendar/calendar.component.ts +368 -0
  49. package/src/app/lib/components/ui/calendar/index.ts +1 -0
  50. package/src/app/lib/components/ui/card/card-action.component.ts +39 -0
  51. package/src/app/lib/components/ui/card/card-content.component.ts +31 -0
  52. package/src/app/lib/components/ui/card/card-description.component.ts +31 -0
  53. package/src/app/lib/components/ui/card/card-footer.component.ts +34 -0
  54. package/src/app/lib/components/ui/card/card-header.component.ts +37 -0
  55. package/src/app/lib/components/ui/card/card-title.component.ts +31 -0
  56. package/src/app/lib/components/ui/card/card.component.ts +41 -0
  57. package/src/app/lib/components/ui/card/index.ts +8 -0
  58. package/src/app/lib/components/ui/carousel/carousel-content.component.ts +38 -0
  59. package/src/app/lib/components/ui/carousel/carousel-context.ts +18 -0
  60. package/src/app/lib/components/ui/carousel/carousel-item.component.ts +32 -0
  61. package/src/app/lib/components/ui/carousel/carousel-next.component.ts +54 -0
  62. package/src/app/lib/components/ui/carousel/carousel-previous.component.ts +54 -0
  63. package/src/app/lib/components/ui/carousel/carousel.component.ts +125 -0
  64. package/src/app/lib/components/ui/carousel/index.ts +7 -0
  65. package/src/app/lib/components/ui/chart/chart-container.component.ts +81 -0
  66. package/src/app/lib/components/ui/chart/chart-context.ts +38 -0
  67. package/src/app/lib/components/ui/chart/chart-legend-content.component.ts +51 -0
  68. package/src/app/lib/components/ui/chart/chart-legend.component.ts +28 -0
  69. package/src/app/lib/components/ui/chart/chart-tooltip-content.component.ts +37 -0
  70. package/src/app/lib/components/ui/chart/chart-tooltip.component.ts +28 -0
  71. package/src/app/lib/components/ui/chart/chart.component.ts +308 -0
  72. package/src/app/lib/components/ui/chart/index.ts +16 -0
  73. package/src/app/lib/components/ui/checkbox/checkbox.component.ts +203 -0
  74. package/src/app/lib/components/ui/checkbox/index.ts +1 -0
  75. package/src/app/lib/components/ui/collapsible/collapsible-content.component.ts +58 -0
  76. package/src/app/lib/components/ui/collapsible/collapsible-context.ts +17 -0
  77. package/src/app/lib/components/ui/collapsible/collapsible-trigger.component.ts +56 -0
  78. package/src/app/lib/components/ui/collapsible/collapsible.component.ts +102 -0
  79. package/src/app/lib/components/ui/collapsible/index.ts +5 -0
  80. package/src/app/lib/components/ui/combobox/combobox-content.component.ts +59 -0
  81. package/src/app/lib/components/ui/combobox/combobox-context.ts +49 -0
  82. package/src/app/lib/components/ui/combobox/combobox-empty.component.ts +35 -0
  83. package/src/app/lib/components/ui/combobox/combobox-group.component.ts +32 -0
  84. package/src/app/lib/components/ui/combobox/combobox-input.component.ts +89 -0
  85. package/src/app/lib/components/ui/combobox/combobox-item.component.ts +129 -0
  86. package/src/app/lib/components/ui/combobox/combobox-list.component.ts +40 -0
  87. package/src/app/lib/components/ui/combobox/combobox-trigger.component.ts +53 -0
  88. package/src/app/lib/components/ui/combobox/combobox-value.component.ts +47 -0
  89. package/src/app/lib/components/ui/combobox/combobox.component.ts +290 -0
  90. package/src/app/lib/components/ui/combobox/index.ts +15 -0
  91. package/src/app/lib/components/ui/command/command-context.ts +24 -0
  92. package/src/app/lib/components/ui/command/command-dialog.component.ts +69 -0
  93. package/src/app/lib/components/ui/command/command-empty.component.ts +23 -0
  94. package/src/app/lib/components/ui/command/command-group.component.ts +66 -0
  95. package/src/app/lib/components/ui/command/command-input.component.ts +137 -0
  96. package/src/app/lib/components/ui/command/command-item.component.ts +148 -0
  97. package/src/app/lib/components/ui/command/command-list.component.ts +30 -0
  98. package/src/app/lib/components/ui/command/command-separator.component.ts +23 -0
  99. package/src/app/lib/components/ui/command/command-shortcut.component.ts +23 -0
  100. package/src/app/lib/components/ui/command/command.component.ts +105 -0
  101. package/src/app/lib/components/ui/command/index.ts +11 -0
  102. package/src/app/lib/components/ui/context-menu/context-menu-checkbox-item.component.ts +68 -0
  103. package/src/app/lib/components/ui/context-menu/context-menu-content.component.ts +213 -0
  104. package/src/app/lib/components/ui/context-menu/context-menu-context.ts +17 -0
  105. package/src/app/lib/components/ui/context-menu/context-menu-item.component.ts +63 -0
  106. package/src/app/lib/components/ui/context-menu/context-menu-label.component.ts +30 -0
  107. package/src/app/lib/components/ui/context-menu/context-menu-radio-group.component.ts +36 -0
  108. package/src/app/lib/components/ui/context-menu/context-menu-radio-item.component.ts +71 -0
  109. package/src/app/lib/components/ui/context-menu/context-menu-separator.component.ts +24 -0
  110. package/src/app/lib/components/ui/context-menu/context-menu-shortcut.component.ts +23 -0
  111. package/src/app/lib/components/ui/context-menu/context-menu-sub-content.component.ts +51 -0
  112. package/src/app/lib/components/ui/context-menu/context-menu-sub-trigger.component.ts +50 -0
  113. package/src/app/lib/components/ui/context-menu/context-menu-sub.component.ts +31 -0
  114. package/src/app/lib/components/ui/context-menu/context-menu-trigger.component.ts +51 -0
  115. package/src/app/lib/components/ui/context-menu/context-menu.component.ts +27 -0
  116. package/src/app/lib/components/ui/context-menu/index.ts +15 -0
  117. package/src/app/lib/components/ui/data-table/data-table-content.component.ts +226 -0
  118. package/src/app/lib/components/ui/data-table/data-table-context.ts +49 -0
  119. package/src/app/lib/components/ui/data-table/data-table-pagination.component.ts +138 -0
  120. package/src/app/lib/components/ui/data-table/data-table-search.component.ts +52 -0
  121. package/src/app/lib/components/ui/data-table/data-table-toolbar.component.ts +27 -0
  122. package/src/app/lib/components/ui/data-table/data-table-view-options.component.ts +92 -0
  123. package/src/app/lib/components/ui/data-table/data-table.component.ts +131 -0
  124. package/src/app/lib/components/ui/data-table/index.ts +16 -0
  125. package/src/app/lib/components/ui/date-picker/date-picker.component.ts +94 -0
  126. package/src/app/lib/components/ui/date-picker/index.ts +1 -0
  127. package/src/app/lib/components/ui/dialog/dialog-close.component.ts +31 -0
  128. package/src/app/lib/components/ui/dialog/dialog-content.component.ts +177 -0
  129. package/src/app/lib/components/ui/dialog/dialog-context.ts +15 -0
  130. package/src/app/lib/components/ui/dialog/dialog-description.component.ts +34 -0
  131. package/src/app/lib/components/ui/dialog/dialog-footer.component.ts +28 -0
  132. package/src/app/lib/components/ui/dialog/dialog-header.component.ts +28 -0
  133. package/src/app/lib/components/ui/dialog/dialog-title.component.ts +34 -0
  134. package/src/app/lib/components/ui/dialog/dialog-trigger.component.ts +38 -0
  135. package/src/app/lib/components/ui/dialog/dialog.component.ts +87 -0
  136. package/src/app/lib/components/ui/dialog/index.ts +10 -0
  137. package/src/app/lib/components/ui/drawer/drawer-close.component.ts +31 -0
  138. package/src/app/lib/components/ui/drawer/drawer-content.component.ts +143 -0
  139. package/src/app/lib/components/ui/drawer/drawer-context.ts +17 -0
  140. package/src/app/lib/components/ui/drawer/drawer-description.component.ts +33 -0
  141. package/src/app/lib/components/ui/drawer/drawer-footer.component.ts +28 -0
  142. package/src/app/lib/components/ui/drawer/drawer-header.component.ts +28 -0
  143. package/src/app/lib/components/ui/drawer/drawer-title.component.ts +33 -0
  144. package/src/app/lib/components/ui/drawer/drawer-trigger.component.ts +38 -0
  145. package/src/app/lib/components/ui/drawer/drawer.component.ts +93 -0
  146. package/src/app/lib/components/ui/drawer/index.ts +10 -0
  147. package/src/app/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-item.component.ts +68 -0
  148. package/src/app/lib/components/ui/dropdown-menu/dropdown-menu-content.component.ts +234 -0
  149. package/src/app/lib/components/ui/dropdown-menu/dropdown-menu-context.ts +15 -0
  150. package/src/app/lib/components/ui/dropdown-menu/dropdown-menu-group.component.ts +15 -0
  151. package/src/app/lib/components/ui/dropdown-menu/dropdown-menu-item.component.ts +56 -0
  152. package/src/app/lib/components/ui/dropdown-menu/dropdown-menu-label.component.ts +30 -0
  153. package/src/app/lib/components/ui/dropdown-menu/dropdown-menu-radio-group.component.ts +42 -0
  154. package/src/app/lib/components/ui/dropdown-menu/dropdown-menu-radio-item.component.ts +71 -0
  155. package/src/app/lib/components/ui/dropdown-menu/dropdown-menu-separator.component.ts +24 -0
  156. package/src/app/lib/components/ui/dropdown-menu/dropdown-menu-shortcut.component.ts +23 -0
  157. package/src/app/lib/components/ui/dropdown-menu/dropdown-menu-sub-content.component.ts +51 -0
  158. package/src/app/lib/components/ui/dropdown-menu/dropdown-menu-sub-trigger.component.ts +53 -0
  159. package/src/app/lib/components/ui/dropdown-menu/dropdown-menu-sub.component.ts +31 -0
  160. package/src/app/lib/components/ui/dropdown-menu/dropdown-menu-trigger.component.ts +45 -0
  161. package/src/app/lib/components/ui/dropdown-menu/dropdown-menu.component.ts +32 -0
  162. package/src/app/lib/components/ui/dropdown-menu/index.ts +16 -0
  163. package/src/app/lib/components/ui/empty/empty-action.component.ts +28 -0
  164. package/src/app/lib/components/ui/empty/empty-description.component.ts +31 -0
  165. package/src/app/lib/components/ui/empty/empty-icon.component.ts +31 -0
  166. package/src/app/lib/components/ui/empty/empty-title.component.ts +28 -0
  167. package/src/app/lib/components/ui/empty/empty.component.ts +53 -0
  168. package/src/app/lib/components/ui/empty/index.ts +6 -0
  169. package/src/app/lib/components/ui/form/form-context.ts +34 -0
  170. package/src/app/lib/components/ui/form/form-control.component.ts +137 -0
  171. package/src/app/lib/components/ui/form/form-description.component.ts +37 -0
  172. package/src/app/lib/components/ui/form/form-field.component.ts +84 -0
  173. package/src/app/lib/components/ui/form/form-item.component.ts +42 -0
  174. package/src/app/lib/components/ui/form/form-label.component.ts +58 -0
  175. package/src/app/lib/components/ui/form/form-message.component.ts +107 -0
  176. package/src/app/lib/components/ui/form/form.component.ts +123 -0
  177. package/src/app/lib/components/ui/form/index.ts +17 -0
  178. package/src/app/lib/components/ui/hover-card/hover-card-content.component.ts +203 -0
  179. package/src/app/lib/components/ui/hover-card/hover-card-context.ts +25 -0
  180. package/src/app/lib/components/ui/hover-card/hover-card-trigger.component.ts +160 -0
  181. package/src/app/lib/components/ui/hover-card/hover-card.component.ts +147 -0
  182. package/src/app/lib/components/ui/hover-card/index.ts +13 -0
  183. package/src/app/lib/components/ui/index.ts +551 -0
  184. package/src/app/lib/components/ui/input/index.ts +1 -0
  185. package/src/app/lib/components/ui/input/input.component.ts +165 -0
  186. package/src/app/lib/components/ui/input-group/index.ts +4 -0
  187. package/src/app/lib/components/ui/input-group/input-group-addon.component.ts +43 -0
  188. package/src/app/lib/components/ui/input-group/input-group-input.component.ts +33 -0
  189. package/src/app/lib/components/ui/input-group/input-group.component.ts +53 -0
  190. package/src/app/lib/components/ui/input-otp/index.ts +14 -0
  191. package/src/app/lib/components/ui/input-otp/input-otp-context.ts +31 -0
  192. package/src/app/lib/components/ui/input-otp/input-otp-group.component.ts +23 -0
  193. package/src/app/lib/components/ui/input-otp/input-otp-separator.component.ts +31 -0
  194. package/src/app/lib/components/ui/input-otp/input-otp-slot.component.ts +67 -0
  195. package/src/app/lib/components/ui/input-otp/input-otp.component.ts +240 -0
  196. package/src/app/lib/components/ui/kbd/index.ts +3 -0
  197. package/src/app/lib/components/ui/kbd/kbd-variants.ts +23 -0
  198. package/src/app/lib/components/ui/kbd/kbd.component.ts +50 -0
  199. package/src/app/lib/components/ui/label/index.ts +1 -0
  200. package/src/app/lib/components/ui/label/label.component.ts +139 -0
  201. package/src/app/lib/components/ui/menubar/index.ts +26 -0
  202. package/src/app/lib/components/ui/menubar/menubar-checkbox-item.component.ts +66 -0
  203. package/src/app/lib/components/ui/menubar/menubar-content.component.ts +236 -0
  204. package/src/app/lib/components/ui/menubar/menubar-context.ts +63 -0
  205. package/src/app/lib/components/ui/menubar/menubar-item.component.ts +60 -0
  206. package/src/app/lib/components/ui/menubar/menubar-label.component.ts +30 -0
  207. package/src/app/lib/components/ui/menubar/menubar-menu.component.ts +40 -0
  208. package/src/app/lib/components/ui/menubar/menubar-radio-group.component.ts +36 -0
  209. package/src/app/lib/components/ui/menubar/menubar-radio-item.component.ts +66 -0
  210. package/src/app/lib/components/ui/menubar/menubar-separator.component.ts +24 -0
  211. package/src/app/lib/components/ui/menubar/menubar-shortcut.component.ts +23 -0
  212. package/src/app/lib/components/ui/menubar/menubar-sub-content.component.ts +51 -0
  213. package/src/app/lib/components/ui/menubar/menubar-sub-trigger.component.ts +50 -0
  214. package/src/app/lib/components/ui/menubar/menubar-sub.component.ts +29 -0
  215. package/src/app/lib/components/ui/menubar/menubar-trigger.component.ts +132 -0
  216. package/src/app/lib/components/ui/menubar/menubar.component.ts +158 -0
  217. package/src/app/lib/components/ui/native-select/index.ts +6 -0
  218. package/src/app/lib/components/ui/native-select/native-select-variants.ts +23 -0
  219. package/src/app/lib/components/ui/native-select/native-select.component.ts +74 -0
  220. package/src/app/lib/components/ui/navigation-menu/index.ts +21 -0
  221. package/src/app/lib/components/ui/navigation-menu/navigation-menu-content.component.ts +66 -0
  222. package/src/app/lib/components/ui/navigation-menu/navigation-menu-context.ts +55 -0
  223. package/src/app/lib/components/ui/navigation-menu/navigation-menu-indicator.component.ts +28 -0
  224. package/src/app/lib/components/ui/navigation-menu/navigation-menu-item.component.ts +29 -0
  225. package/src/app/lib/components/ui/navigation-menu/navigation-menu-link.component.ts +43 -0
  226. package/src/app/lib/components/ui/navigation-menu/navigation-menu-list.component.ts +26 -0
  227. package/src/app/lib/components/ui/navigation-menu/navigation-menu-trigger-style.ts +7 -0
  228. package/src/app/lib/components/ui/navigation-menu/navigation-menu-trigger.component.ts +58 -0
  229. package/src/app/lib/components/ui/navigation-menu/navigation-menu-viewport.component.ts +26 -0
  230. package/src/app/lib/components/ui/navigation-menu/navigation-menu.component.ts +149 -0
  231. package/src/app/lib/components/ui/pagination/index.ts +8 -0
  232. package/src/app/lib/components/ui/pagination/pagination-content.component.ts +28 -0
  233. package/src/app/lib/components/ui/pagination/pagination-ellipsis.component.ts +47 -0
  234. package/src/app/lib/components/ui/pagination/pagination-item.component.ts +28 -0
  235. package/src/app/lib/components/ui/pagination/pagination-link.component.ts +46 -0
  236. package/src/app/lib/components/ui/pagination/pagination-next.component.ts +54 -0
  237. package/src/app/lib/components/ui/pagination/pagination-previous.component.ts +54 -0
  238. package/src/app/lib/components/ui/pagination/pagination.component.ts +48 -0
  239. package/src/app/lib/components/ui/popover/index.ts +14 -0
  240. package/src/app/lib/components/ui/popover/popover-anchor.component.ts +64 -0
  241. package/src/app/lib/components/ui/popover/popover-content.component.ts +231 -0
  242. package/src/app/lib/components/ui/popover/popover-context.ts +29 -0
  243. package/src/app/lib/components/ui/popover/popover-trigger.component.ts +100 -0
  244. package/src/app/lib/components/ui/popover/popover.component.ts +163 -0
  245. package/src/app/lib/components/ui/progress/index.ts +6 -0
  246. package/src/app/lib/components/ui/progress/progress.component.ts +212 -0
  247. package/src/app/lib/components/ui/radio-group/index.ts +10 -0
  248. package/src/app/lib/components/ui/radio-group/radio-group-context.ts +38 -0
  249. package/src/app/lib/components/ui/radio-group/radio-group-item.component.ts +298 -0
  250. package/src/app/lib/components/ui/radio-group/radio-group.component.ts +275 -0
  251. package/src/app/lib/components/ui/resizable/index.ts +5 -0
  252. package/src/app/lib/components/ui/resizable/resizable-context.ts +14 -0
  253. package/src/app/lib/components/ui/resizable/resizable-handle.component.ts +232 -0
  254. package/src/app/lib/components/ui/resizable/resizable-panel-group.component.ts +140 -0
  255. package/src/app/lib/components/ui/resizable/resizable-panel.component.ts +77 -0
  256. package/src/app/lib/components/ui/scroll-area/index.ts +8 -0
  257. package/src/app/lib/components/ui/scroll-area/scroll-area.component.ts +126 -0
  258. package/src/app/lib/components/ui/scroll-area/scroll-bar.component.ts +93 -0
  259. package/src/app/lib/components/ui/segmented/index.ts +13 -0
  260. package/src/app/lib/components/ui/segmented/segmented-context.ts +11 -0
  261. package/src/app/lib/components/ui/segmented/segmented-item.component.ts +72 -0
  262. package/src/app/lib/components/ui/segmented/segmented-variants.ts +40 -0
  263. package/src/app/lib/components/ui/segmented/segmented.component.ts +99 -0
  264. package/src/app/lib/components/ui/select/index.ts +19 -0
  265. package/src/app/lib/components/ui/select/select-content.component.ts +97 -0
  266. package/src/app/lib/components/ui/select/select-context.ts +53 -0
  267. package/src/app/lib/components/ui/select/select-group.component.ts +56 -0
  268. package/src/app/lib/components/ui/select/select-item.component.ts +163 -0
  269. package/src/app/lib/components/ui/select/select-label.component.ts +32 -0
  270. package/src/app/lib/components/ui/select/select-separator.component.ts +34 -0
  271. package/src/app/lib/components/ui/select/select-trigger.component.ts +164 -0
  272. package/src/app/lib/components/ui/select/select-value.component.ts +49 -0
  273. package/src/app/lib/components/ui/select/select.component.ts +263 -0
  274. package/src/app/lib/components/ui/separator/index.ts +6 -0
  275. package/src/app/lib/components/ui/separator/separator.component.ts +128 -0
  276. package/src/app/lib/components/ui/sheet/index.ts +11 -0
  277. package/src/app/lib/components/ui/sheet/sheet-close.component.ts +32 -0
  278. package/src/app/lib/components/ui/sheet/sheet-content.component.ts +157 -0
  279. package/src/app/lib/components/ui/sheet/sheet-context.ts +15 -0
  280. package/src/app/lib/components/ui/sheet/sheet-description.component.ts +34 -0
  281. package/src/app/lib/components/ui/sheet/sheet-footer.component.ts +28 -0
  282. package/src/app/lib/components/ui/sheet/sheet-header.component.ts +28 -0
  283. package/src/app/lib/components/ui/sheet/sheet-title.component.ts +34 -0
  284. package/src/app/lib/components/ui/sheet/sheet-trigger.component.ts +38 -0
  285. package/src/app/lib/components/ui/sheet/sheet-variants.ts +22 -0
  286. package/src/app/lib/components/ui/sheet/sheet.component.ts +97 -0
  287. package/src/app/lib/components/ui/sidebar/index.ts +41 -0
  288. package/src/app/lib/components/ui/sidebar/sidebar-content.component.ts +31 -0
  289. package/src/app/lib/components/ui/sidebar/sidebar-context.ts +33 -0
  290. package/src/app/lib/components/ui/sidebar/sidebar-footer.component.ts +28 -0
  291. package/src/app/lib/components/ui/sidebar/sidebar-group-action.component.ts +33 -0
  292. package/src/app/lib/components/ui/sidebar/sidebar-group-content.component.ts +28 -0
  293. package/src/app/lib/components/ui/sidebar/sidebar-group-label.component.ts +32 -0
  294. package/src/app/lib/components/ui/sidebar/sidebar-group.component.ts +28 -0
  295. package/src/app/lib/components/ui/sidebar/sidebar-header.component.ts +28 -0
  296. package/src/app/lib/components/ui/sidebar/sidebar-input.component.ts +31 -0
  297. package/src/app/lib/components/ui/sidebar/sidebar-inset.component.ts +31 -0
  298. package/src/app/lib/components/ui/sidebar/sidebar-menu-action.component.ts +56 -0
  299. package/src/app/lib/components/ui/sidebar/sidebar-menu-badge.component.ts +42 -0
  300. package/src/app/lib/components/ui/sidebar/sidebar-menu-button.component.ts +64 -0
  301. package/src/app/lib/components/ui/sidebar/sidebar-menu-item.component.ts +32 -0
  302. package/src/app/lib/components/ui/sidebar/sidebar-menu-skeleton.component.ts +39 -0
  303. package/src/app/lib/components/ui/sidebar/sidebar-menu-sub-button.component.ts +59 -0
  304. package/src/app/lib/components/ui/sidebar/sidebar-menu-sub-item.component.ts +25 -0
  305. package/src/app/lib/components/ui/sidebar/sidebar-menu-sub.component.ts +32 -0
  306. package/src/app/lib/components/ui/sidebar/sidebar-menu.component.ts +31 -0
  307. package/src/app/lib/components/ui/sidebar/sidebar-provider.component.ts +141 -0
  308. package/src/app/lib/components/ui/sidebar/sidebar-rail.component.ts +47 -0
  309. package/src/app/lib/components/ui/sidebar/sidebar-route-active.service.ts +124 -0
  310. package/src/app/lib/components/ui/sidebar/sidebar-separator.component.ts +28 -0
  311. package/src/app/lib/components/ui/sidebar/sidebar-trigger.component.ts +57 -0
  312. package/src/app/lib/components/ui/sidebar/sidebar.component.ts +130 -0
  313. package/src/app/lib/components/ui/skeleton/index.ts +1 -0
  314. package/src/app/lib/components/ui/skeleton/skeleton.component.ts +52 -0
  315. package/src/app/lib/components/ui/slider/index.ts +6 -0
  316. package/src/app/lib/components/ui/slider/slider.component.ts +477 -0
  317. package/src/app/lib/components/ui/spinner/index.ts +3 -0
  318. package/src/app/lib/components/ui/spinner/spinner-variants.ts +32 -0
  319. package/src/app/lib/components/ui/spinner/spinner.component.ts +77 -0
  320. package/src/app/lib/components/ui/switch/index.ts +6 -0
  321. package/src/app/lib/components/ui/switch/switch.component.ts +282 -0
  322. package/src/app/lib/components/ui/table/index.ts +9 -0
  323. package/src/app/lib/components/ui/table/table-body.component.ts +28 -0
  324. package/src/app/lib/components/ui/table/table-caption.component.ts +28 -0
  325. package/src/app/lib/components/ui/table/table-cell.component.ts +31 -0
  326. package/src/app/lib/components/ui/table/table-footer.component.ts +28 -0
  327. package/src/app/lib/components/ui/table/table-head.component.ts +36 -0
  328. package/src/app/lib/components/ui/table/table-header.component.ts +28 -0
  329. package/src/app/lib/components/ui/table/table-row.component.ts +34 -0
  330. package/src/app/lib/components/ui/table/table.component.ts +52 -0
  331. package/src/app/lib/components/ui/tabs/index.ts +14 -0
  332. package/src/app/lib/components/ui/tabs/tabs-content.component.ts +132 -0
  333. package/src/app/lib/components/ui/tabs/tabs-context.ts +33 -0
  334. package/src/app/lib/components/ui/tabs/tabs-list.component.ts +228 -0
  335. package/src/app/lib/components/ui/tabs/tabs-trigger.component.ts +167 -0
  336. package/src/app/lib/components/ui/tabs/tabs.component.ts +203 -0
  337. package/src/app/lib/components/ui/textarea/index.ts +1 -0
  338. package/src/app/lib/components/ui/textarea/textarea.component.ts +44 -0
  339. package/src/app/lib/components/ui/toast/index.ts +16 -0
  340. package/src/app/lib/components/ui/toast/toast-action.component.ts +77 -0
  341. package/src/app/lib/components/ui/toast/toast-description.component.ts +52 -0
  342. package/src/app/lib/components/ui/toast/toast-title.component.ts +52 -0
  343. package/src/app/lib/components/ui/toast/toast-variants.ts +24 -0
  344. package/src/app/lib/components/ui/toast/toast.component.ts +177 -0
  345. package/src/app/lib/components/ui/toast/toast.service.ts +202 -0
  346. package/src/app/lib/components/ui/toast/toaster.component.ts +128 -0
  347. package/src/app/lib/components/ui/toggle/index.ts +6 -0
  348. package/src/app/lib/components/ui/toggle/toggle-variants.ts +30 -0
  349. package/src/app/lib/components/ui/toggle/toggle.component.ts +199 -0
  350. package/src/app/lib/components/ui/toggle-group/index.ts +11 -0
  351. package/src/app/lib/components/ui/toggle-group/toggle-group-context.ts +48 -0
  352. package/src/app/lib/components/ui/toggle-group/toggle-group-item.component.ts +241 -0
  353. package/src/app/lib/components/ui/toggle-group/toggle-group.component.ts +288 -0
  354. package/src/app/lib/components/ui/tooltip/index.ts +14 -0
  355. package/src/app/lib/components/ui/tooltip/tooltip-content.component.ts +154 -0
  356. package/src/app/lib/components/ui/tooltip/tooltip-context.ts +29 -0
  357. package/src/app/lib/components/ui/tooltip/tooltip-provider.component.ts +95 -0
  358. package/src/app/lib/components/ui/tooltip/tooltip-trigger.component.ts +138 -0
  359. package/src/app/lib/components/ui/tooltip/tooltip.component.ts +159 -0
  360. package/src/app/lib/components/ui/typography/index.ts +13 -0
  361. package/src/app/lib/components/ui/typography/typography-blockquote.component.ts +31 -0
  362. package/src/app/lib/components/ui/typography/typography-h1.component.ts +32 -0
  363. package/src/app/lib/components/ui/typography/typography-h2.component.ts +32 -0
  364. package/src/app/lib/components/ui/typography/typography-h3.component.ts +29 -0
  365. package/src/app/lib/components/ui/typography/typography-h4.component.ts +29 -0
  366. package/src/app/lib/components/ui/typography/typography-inline-code.component.ts +31 -0
  367. package/src/app/lib/components/ui/typography/typography-large.component.ts +28 -0
  368. package/src/app/lib/components/ui/typography/typography-lead.component.ts +31 -0
  369. package/src/app/lib/components/ui/typography/typography-list.component.ts +31 -0
  370. package/src/app/lib/components/ui/typography/typography-muted.component.ts +28 -0
  371. package/src/app/lib/components/ui/typography/typography-p.component.ts +29 -0
  372. package/src/app/lib/components/ui/typography/typography-small.component.ts +28 -0
  373. package/src/app/lib/index.ts +7 -0
  374. package/src/app/lib/utils/accessibility/aria-id.service.ts +118 -0
  375. package/src/app/lib/utils/accessibility/click-outside.directive.ts +85 -0
  376. package/src/app/lib/utils/accessibility/focus-management.service.ts +231 -0
  377. package/src/app/lib/utils/accessibility/focus-trap.directive.ts +203 -0
  378. package/src/app/lib/utils/accessibility/index.ts +23 -0
  379. package/src/app/lib/utils/accessibility/keyboard-navigation.directive.ts +440 -0
  380. package/src/app/lib/utils/accessibility/live-region.directive.ts +260 -0
  381. package/src/app/lib/utils/accessibility/touch-target.directive.ts +81 -0
  382. package/src/app/lib/utils/accessibility/visually-hidden.component.ts +79 -0
  383. package/src/app/lib/utils/animation/animated.directive.ts +191 -0
  384. package/src/app/lib/utils/animation/animation-tokens.service.ts +88 -0
  385. package/src/app/lib/utils/animation/animation.types.ts +55 -0
  386. package/src/app/lib/utils/animation/animation.utils.ts +158 -0
  387. package/src/app/lib/utils/animation/index.ts +17 -0
  388. package/src/app/lib/utils/animation/presence.component.ts +168 -0
  389. package/src/app/lib/utils/animation/presence.directive.ts +169 -0
  390. package/src/app/lib/utils/cn.ts +15 -0
  391. package/src/app/lib/utils/index.ts +11 -0
  392. package/src/app/lib/utils/positioning/index.ts +218 -0
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Animation System Types - Radix-Ready Animation Layer for shadcn-angular
3
+ * Defines the animation lifecycle states and configuration
4
+ */
5
+
6
+ /**
7
+ * Animation lifecycle states
8
+ * Mirrors Radix UI's internal state management
9
+ */
10
+ export type AnimationState = 'closed' | 'entering' | 'open' | 'exiting';
11
+
12
+ /**
13
+ * Positional information for directional animations
14
+ */
15
+ export type AnimationSide = 'top' | 'bottom' | 'left' | 'right';
16
+ export type AnimationAlign = 'start' | 'center' | 'end';
17
+
18
+ /**
19
+ * Animation lifecycle configuration
20
+ */
21
+ export interface AnimationConfig {
22
+ /** Duration in milliseconds */
23
+ duration?: number;
24
+ /** Easing function */
25
+ easing?: string;
26
+ /** CSS class to apply during animation */
27
+ class?: string;
28
+ }
29
+
30
+ /**
31
+ * State exposure API - all animated components must expose these attributes
32
+ */
33
+ export interface AnimatedElementAttributes {
34
+ /** Current animation lifecycle state */
35
+ 'data-state': AnimationState;
36
+ /** Positional side (if applicable) */
37
+ 'data-side'?: AnimationSide;
38
+ /** Alignment (if applicable) */
39
+ 'data-align'?: AnimationAlign;
40
+ /** Motion phase for directional animations */
41
+ 'data-motion'?: 'from-start' | 'to-end';
42
+ }
43
+
44
+ /**
45
+ * Presence component token
46
+ * Keeps component in DOM until exit animation completes
47
+ */
48
+ export interface PresenceToken {
49
+ /** Unique identifier for presence tracking */
50
+ id: string;
51
+ /** Current animation state */
52
+ state: AnimationState;
53
+ /** Callback when animation completes */
54
+ onAnimationEnd?: () => void;
55
+ }
@@ -0,0 +1,158 @@
1
+ /**
2
+ * Animation Utility Functions
3
+ * Helper functions for managing animation states and CSS classes
4
+ */
5
+
6
+ import { signal, Signal } from '@angular/core';
7
+ import type { AnimationAlign, AnimationSide, AnimationState } from './animation.types';
8
+
9
+ /**
10
+ * Animation preset names matching shadcn/ui semantics
11
+ */
12
+ export const ANIMATION_PRESETS = {
13
+ // Fade animations
14
+ fadeIn: 'animate-in fade-in-0',
15
+ fadeOut: 'animate-out fade-out-0',
16
+
17
+ // Scale/Zoom animations
18
+ scaleIn: 'animate-in zoom-in-95',
19
+ scaleOut: 'animate-out zoom-out-95',
20
+
21
+ // Slide animations
22
+ slideInFromTop: 'animate-in slide-in-from-top-2',
23
+ slideOutToTop: 'animate-out slide-out-to-top-2',
24
+ slideInFromRight: 'animate-in slide-in-from-right-2',
25
+ slideOutToRight: 'animate-out slide-out-to-right-2',
26
+ slideInFromBottom: 'animate-in slide-in-from-bottom-2',
27
+ slideOutToBottom: 'animate-out slide-out-to-bottom-2',
28
+ slideInFromLeft: 'animate-in slide-in-from-left-2',
29
+ slideOutToLeft: 'animate-out slide-out-to-left-2',
30
+
31
+ // Combined animations (common patterns)
32
+ fadeScale: 'animate-in fade-in-0 zoom-in-95',
33
+ fadeScaleOut: 'animate-out fade-out-0 zoom-out-95',
34
+ } as const;
35
+
36
+ /**
37
+ * Create animation state signal
38
+ * Manages the 4-state animation lifecycle
39
+ */
40
+ export function createAnimationState(
41
+ initialState: AnimationState = 'closed'
42
+ ): Signal<AnimationState> {
43
+ return signal<AnimationState>(initialState);
44
+ }
45
+
46
+ /**
47
+ * Determine animation CSS classes based on state and direction
48
+ */
49
+ export function getAnimationClasses(
50
+ state: AnimationState,
51
+ direction?: AnimationSide,
52
+ animate: boolean = true
53
+ ): string {
54
+ if (!animate) return '';
55
+
56
+ const baseClasses = ['duration-200'];
57
+
58
+ switch (state) {
59
+ case 'closed':
60
+ return [...baseClasses, 'animate-out fade-out-0'].join(' ');
61
+
62
+ case 'entering':
63
+ return [...baseClasses, 'animate-in fade-in-0'].join(' ');
64
+
65
+ case 'open':
66
+ return [...baseClasses, 'animate-in fade-in-0'].join(' ');
67
+
68
+ case 'exiting':
69
+ return [...baseClasses, 'animate-out fade-out-0'].join(' ');
70
+
71
+ default:
72
+ return '';
73
+ }
74
+ }
75
+
76
+ /**
77
+ * Get slide animation classes based on direction
78
+ */
79
+ export function getSlideAnimationClasses(
80
+ state: AnimationState,
81
+ direction: AnimationSide
82
+ ): string {
83
+ const baseClasses = ['duration-200'];
84
+
85
+ const directionMap: Record<AnimationState, Record<AnimationSide, string>> = {
86
+ entering: {
87
+ top: 'animate-in slide-in-from-top-2',
88
+ bottom: 'animate-in slide-in-from-bottom-2',
89
+ left: 'animate-in slide-in-from-left-2',
90
+ right: 'animate-in slide-in-from-right-2',
91
+ },
92
+ open: {
93
+ top: 'animate-in slide-in-from-top-2',
94
+ bottom: 'animate-in slide-in-from-bottom-2',
95
+ left: 'animate-in slide-in-from-left-2',
96
+ right: 'animate-in slide-in-from-right-2',
97
+ },
98
+ exiting: {
99
+ top: 'animate-out slide-out-to-top-2',
100
+ bottom: 'animate-out slide-out-to-bottom-2',
101
+ left: 'animate-out slide-out-to-left-2',
102
+ right: 'animate-out slide-out-to-right-2',
103
+ },
104
+ closed: {
105
+ top: 'animate-out slide-out-to-top-2',
106
+ bottom: 'animate-out slide-out-to-bottom-2',
107
+ left: 'animate-out slide-out-to-left-2',
108
+ right: 'animate-out slide-out-to-right-2',
109
+ },
110
+ };
111
+
112
+ return [...baseClasses, directionMap[state]?.[direction] || ''].join(' ');
113
+ }
114
+
115
+ /**
116
+ * Build data attributes for animation state exposure
117
+ */
118
+ export function buildAnimationAttributes(
119
+ state: AnimationState,
120
+ side?: AnimationSide,
121
+ align?: AnimationAlign
122
+ ): Record<string, string | undefined> {
123
+ return {
124
+ 'data-state': state,
125
+ 'data-side': side,
126
+ 'data-align': align,
127
+ };
128
+ }
129
+
130
+ /**
131
+ * Wait for animation to complete
132
+ * Useful for coordinating multiple animations
133
+ */
134
+ export async function waitForAnimation(element: HTMLElement): Promise<void> {
135
+ return new Promise((resolve) => {
136
+ const handleAnimationEnd = () => {
137
+ element.removeEventListener('animationend', handleAnimationEnd);
138
+ resolve();
139
+ };
140
+
141
+ element.addEventListener('animationend', handleAnimationEnd);
142
+
143
+ // Timeout fallback (300ms for safety)
144
+ setTimeout(() => {
145
+ element.removeEventListener('animationend', handleAnimationEnd);
146
+ resolve();
147
+ }, 300);
148
+ });
149
+ }
150
+
151
+ /**
152
+ * Check if animations are enabled (respects prefers-reduced-motion)
153
+ */
154
+ export function areAnimationsEnabled(): boolean {
155
+ if (typeof window === 'undefined') return true;
156
+
157
+ return !window.matchMedia('(prefers-reduced-motion: reduce)').matches;
158
+ }
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Animation System Index
3
+ * Exports all animation utilities and services
4
+ */
5
+
6
+ export type { AnimatedElementAttributes, AnimationAlign, AnimationConfig, AnimationSide, AnimationState, PresenceToken } from './animation.types';
7
+
8
+ export { AnimatedDirective } from './animated.directive';
9
+ export { AnimationTokensService } from './animation-tokens.service';
10
+ export {
11
+ ANIMATION_PRESETS, areAnimationsEnabled, buildAnimationAttributes, createAnimationState,
12
+ getAnimationClasses,
13
+ getSlideAnimationClasses, waitForAnimation
14
+ } from './animation.utils';
15
+ export { Presence, type PresenceState } from './presence.component';
16
+ export { PresenceIfDirective, PresenceService } from './presence.directive';
17
+
@@ -0,0 +1,168 @@
1
+ /**
2
+ * Presence Component
3
+ * Angular version of Radix UI's Presence primitive
4
+ * Keeps DOM elements present until exit animations complete
5
+ *
6
+ * This is the critical component for proper exit animations in:
7
+ * - Dialog
8
+ * - Popover
9
+ * - Dropdown Menu
10
+ * - Tooltip
11
+ * - Sheet
12
+ * - Toast
13
+ */
14
+
15
+ import {
16
+ ChangeDetectionStrategy,
17
+ Component,
18
+ computed,
19
+ effect,
20
+ input,
21
+ OnDestroy,
22
+ signal
23
+ } from '@angular/core';
24
+
25
+ /**
26
+ * Presence state
27
+ */
28
+ export type PresenceState = 'mounted' | 'unmountSuspended' | 'unmounted';
29
+
30
+ /**
31
+ * Presence Component
32
+ * Wraps content and manages its presence in the DOM based on animation state
33
+ *
34
+ * Usage:
35
+ * <Presence [present]="isOpen()">
36
+ * <div class="animate-in data-[state=closed]:animate-out">
37
+ * Content here
38
+ * </div>
39
+ * </Presence>
40
+ */
41
+ @Component({
42
+ selector: 'Presence',
43
+ template: `
44
+ @if (shouldRender()) {
45
+ <ng-content />
46
+ }
47
+ `,
48
+ host: {
49
+ class: 'contents',
50
+ '[attr.data-presence-state]': 'presenceState()',
51
+ '(animationend)': 'handleAnimationEnd($event)',
52
+ '(animationcancel)': 'handleAnimationEnd($event)',
53
+ },
54
+ changeDetection: ChangeDetectionStrategy.OnPush,
55
+ })
56
+ export class Presence implements OnDestroy {
57
+ /** Whether the content should be present */
58
+ readonly present = input.required<boolean>();
59
+
60
+ /** Force presence (bypass animation waiting) */
61
+ readonly forceMount = input<boolean>(false);
62
+
63
+ /** Animation duration in ms (fallback if CSS animation doesn't fire) */
64
+ readonly exitDuration = input<number>(200);
65
+
66
+ /** Internal presence state */
67
+ private readonly state = signal<PresenceState>('unmounted');
68
+
69
+ /** Previous present value for change detection */
70
+ private prevPresent = false;
71
+
72
+ /** Timeout for fallback animation end */
73
+ private exitTimeout: ReturnType<typeof setTimeout> | null = null;
74
+
75
+ /** Whether to render content */
76
+ readonly shouldRender = computed(() => {
77
+ if (this.forceMount()) return true;
78
+
79
+ const currentState = this.state();
80
+ return currentState === 'mounted' || currentState === 'unmountSuspended';
81
+ });
82
+
83
+ /** Current presence state (exposed for debugging) */
84
+ readonly presenceState = computed(() => this.state());
85
+
86
+ constructor() {
87
+ // React to present changes
88
+ effect(() => {
89
+ const isPresent = this.present();
90
+
91
+ if (isPresent !== this.prevPresent) {
92
+ this.handlePresenceChange(isPresent);
93
+ this.prevPresent = isPresent;
94
+ }
95
+ });
96
+ }
97
+
98
+ ngOnDestroy(): void {
99
+ this.clearExitTimeout();
100
+ }
101
+
102
+ /**
103
+ * Handle presence change
104
+ */
105
+ private handlePresenceChange(isPresent: boolean): void {
106
+ this.clearExitTimeout();
107
+
108
+ if (isPresent) {
109
+ // Mount immediately
110
+ this.state.set('mounted');
111
+ } else {
112
+ // Start exit animation
113
+ this.state.set('unmountSuspended');
114
+
115
+ // Set fallback timeout in case animationend doesn't fire
116
+ this.exitTimeout = setTimeout(() => {
117
+ this.state.set('unmounted');
118
+ }, this.exitDuration());
119
+ }
120
+ }
121
+
122
+ /**
123
+ * Handle animation end
124
+ */
125
+ protected handleAnimationEnd(event: AnimationEvent): void {
126
+ // Only handle if we're in exit state
127
+ if (this.state() === 'unmountSuspended') {
128
+ // Check if this is an exit animation (based on animation name or state)
129
+ const target = event.target as HTMLElement;
130
+ const animationName = event.animationName;
131
+
132
+ // Exit animations typically contain 'exit' or 'out' in the name
133
+ if (
134
+ animationName.includes('exit') ||
135
+ animationName.includes('out') ||
136
+ animationName.includes('leave')
137
+ ) {
138
+ this.clearExitTimeout();
139
+ this.state.set('unmounted');
140
+ }
141
+ }
142
+ }
143
+
144
+ /**
145
+ * Clear exit timeout
146
+ */
147
+ private clearExitTimeout(): void {
148
+ if (this.exitTimeout) {
149
+ clearTimeout(this.exitTimeout);
150
+ this.exitTimeout = null;
151
+ }
152
+ }
153
+
154
+ /**
155
+ * Force unmount (skip animation)
156
+ */
157
+ forceUnmount(): void {
158
+ this.clearExitTimeout();
159
+ this.state.set('unmounted');
160
+ }
161
+
162
+ /**
163
+ * Check if currently animating exit
164
+ */
165
+ isExiting(): boolean {
166
+ return this.state() === 'unmountSuspended';
167
+ }
168
+ }
@@ -0,0 +1,169 @@
1
+ /**
2
+ * Presence Directive & Service
3
+ * Keeps DOM elements in the tree until animations complete
4
+ * Critical for exit animations in modals, tooltips, popovers, etc.
5
+ */
6
+
7
+ import {
8
+ DestroyRef,
9
+ Directive,
10
+ EmbeddedViewRef,
11
+ Injectable,
12
+ Input,
13
+ OnDestroy,
14
+ OnInit,
15
+ TemplateRef,
16
+ ViewContainerRef,
17
+ WritableSignal,
18
+ inject,
19
+ signal
20
+ } from '@angular/core';
21
+
22
+ /**
23
+ * Presence state for tracking animation lifecycle
24
+ */
25
+ interface PresenceState {
26
+ isPresent: boolean;
27
+ isAnimating: boolean;
28
+ }
29
+
30
+ /**
31
+ * Manages presence state for animated components
32
+ * Ensures DOM elements stay in tree during exit animations
33
+ */
34
+ @Injectable({
35
+ providedIn: 'root',
36
+ })
37
+ export class PresenceService {
38
+ private presenceMap = new Map<string, WritableSignal<PresenceState>>();
39
+
40
+ /**
41
+ * Register a presence element
42
+ */
43
+ register(id: string, initialState: boolean = false): WritableSignal<PresenceState> {
44
+ if (!this.presenceMap.has(id)) {
45
+ this.presenceMap.set(
46
+ id,
47
+ signal<PresenceState>({
48
+ isPresent: initialState,
49
+ isAnimating: false,
50
+ })
51
+ );
52
+ }
53
+ return this.presenceMap.get(id)!;
54
+ }
55
+
56
+ /**
57
+ * Unregister a presence element
58
+ */
59
+ unregister(id: string): void {
60
+ this.presenceMap.delete(id);
61
+ }
62
+
63
+ /**
64
+ * Update presence state
65
+ */
66
+ setState(id: string, state: Partial<PresenceState>): void {
67
+ const current = this.presenceMap.get(id);
68
+ if (current) {
69
+ current.update((prev) => ({ ...prev, ...state }));
70
+ }
71
+ }
72
+
73
+ /**
74
+ * Get current presence state
75
+ */
76
+ getState(id: string): PresenceState | undefined {
77
+ return this.presenceMap.get(id)?.();
78
+ }
79
+ }
80
+
81
+ /**
82
+ * Presence Directive
83
+ * Usage: <div *presenceIf="isVisible; duration: 300">Content</div>
84
+ *
85
+ * Keeps the element in DOM during exit animations, then removes it
86
+ * Properly handles animation completion before unmounting
87
+ */
88
+ @Directive({
89
+ selector: '[presenceIf]',
90
+ })
91
+ export class PresenceIfDirective<T> implements OnInit, OnDestroy {
92
+ private readonly viewContainer = inject(ViewContainerRef);
93
+ private readonly presenceService = inject(PresenceService);
94
+ private readonly destroyRef = inject(DestroyRef);
95
+
96
+ @Input() presenceIfTemplate?: TemplateRef<T>;
97
+ @Input() set presenceIf(show: boolean) {
98
+ this.handlePresenceChange(show);
99
+ }
100
+
101
+ @Input() presenceDuration: number = 200;
102
+
103
+ private viewRef: EmbeddedViewRef<T> | null = null;
104
+ private presenceId = `presence-${Math.random().toString(36).substr(2, 9)}`;
105
+ private isVisible = signal(false);
106
+
107
+ ngOnInit(): void {
108
+ this.presenceService.register(this.presenceId, false);
109
+
110
+ // Clean up on destroy
111
+ this.destroyRef.onDestroy(() => {
112
+ this.presenceService.unregister(this.presenceId);
113
+ });
114
+ }
115
+
116
+ ngOnDestroy(): void {
117
+ this.presenceService.unregister(this.presenceId);
118
+ if (this.viewRef) {
119
+ this.viewRef.destroy();
120
+ this.viewRef = null;
121
+ }
122
+ }
123
+
124
+ private handlePresenceChange(show: boolean): void {
125
+ if (show) {
126
+ this.showElement();
127
+ } else {
128
+ this.hideElement();
129
+ }
130
+ }
131
+
132
+ private showElement(): void {
133
+ if (!this.viewRef && this.presenceIfTemplate) {
134
+ this.viewRef = this.viewContainer.createEmbeddedView(this.presenceIfTemplate);
135
+ this.presenceService.setState(this.presenceId, {
136
+ isPresent: true,
137
+ isAnimating: true,
138
+ });
139
+
140
+ // Mark animation as complete after duration
141
+ setTimeout(() => {
142
+ this.presenceService.setState(this.presenceId, {
143
+ isAnimating: false,
144
+ });
145
+ }, this.presenceDuration);
146
+ }
147
+
148
+ this.isVisible.set(true);
149
+ }
150
+
151
+ private hideElement(): void {
152
+ this.isVisible.set(false);
153
+ this.presenceService.setState(this.presenceId, {
154
+ isAnimating: true,
155
+ });
156
+
157
+ // Remove from DOM after animation completes
158
+ setTimeout(() => {
159
+ if (this.viewRef) {
160
+ this.viewRef.destroy();
161
+ this.viewRef = null;
162
+ }
163
+ this.presenceService.setState(this.presenceId, {
164
+ isPresent: false,
165
+ isAnimating: false,
166
+ });
167
+ }, this.presenceDuration);
168
+ }
169
+ }
@@ -0,0 +1,15 @@
1
+ import { clsx, type ClassValue } from 'clsx';
2
+ import { twMerge } from 'tailwind-merge';
3
+
4
+ /**
5
+ * Utility function to merge Tailwind CSS classes with proper conflict resolution.
6
+ * Combines clsx for conditional classes with tailwind-merge for deduplication.
7
+ *
8
+ * @example
9
+ * cn('px-4 py-2', 'px-6') // => 'py-2 px-6'
10
+ * cn('bg-red-500', condition && 'bg-blue-500') // conditional classes
11
+ * cn('text-sm', ['font-bold', 'text-gray-500']) // array support
12
+ */
13
+ export function cn(...inputs: ClassValue[]): string {
14
+ return twMerge(clsx(inputs));
15
+ }
@@ -0,0 +1,11 @@
1
+ // Utility exports
2
+ export { cn } from './cn';
3
+
4
+ // Accessibility utilities
5
+ export * from './accessibility';
6
+
7
+ // Animation utilities
8
+ export * from './animation';
9
+
10
+ // Positioning utilities (collision detection)
11
+ export * from './positioning';