@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,263 @@
1
+ import { cn } from '@/lib/utils';
2
+ import { AriaIdService } from '@/lib/utils/accessibility';
3
+ import {
4
+ ChangeDetectionStrategy,
5
+ Component,
6
+ computed,
7
+ effect,
8
+ ElementRef,
9
+ forwardRef,
10
+ inject,
11
+ input,
12
+ model,
13
+ output,
14
+ signal,
15
+ } from '@angular/core';
16
+ import { SELECT_CONTEXT, type SelectContext } from './select-context';
17
+
18
+ // ============================================================================
19
+ // Types
20
+ // ============================================================================
21
+
22
+ export type SelectState = 'open' | 'closed';
23
+
24
+ /**
25
+ * Props for the Select component
26
+ */
27
+ export interface SelectProps {
28
+ /** The value of the select when initially rendered.
29
+ * Use when you do not need to control the state of the select. */
30
+ defaultValue?: string;
31
+ /** The controlled value of the select.
32
+ * Should be used in conjunction with onValueChange. */
33
+ value?: string;
34
+ /** The controlled open state of the select.
35
+ * Must be used in conjunction with onOpenChange. */
36
+ open?: boolean;
37
+ /** When true, prevents the user from interacting with select.
38
+ * @default false */
39
+ disabled?: boolean;
40
+ /** The name of the select. Submitted with its owning form as part of a name/value pair. */
41
+ name?: string;
42
+ /** When true, indicates that the user must select a value before the owning form can be submitted.
43
+ * @default false */
44
+ required?: boolean;
45
+ /** Additional CSS classes */
46
+ class?: string;
47
+ }
48
+
49
+ // ============================================================================
50
+ // Component
51
+ // ============================================================================
52
+
53
+ /**
54
+ * @component Select
55
+ *
56
+ * Displays a list of options for the user to pick from—triggered by a button.
57
+ *
58
+ * @description
59
+ * Select provides a dropdown selection input that implements the WAI-ARIA
60
+ * listbox pattern with full keyboard navigation.
61
+ *
62
+ * ## Features
63
+ * - Full keyboard navigation
64
+ * - Supports controlled and uncontrolled usage
65
+ * - Groups and separators for organizing options
66
+ * - Disabled items and groups
67
+ * - Custom trigger and value display
68
+ * - Form submission with native hidden input
69
+ *
70
+ * ## Accessibility
71
+ * Implements the WAI-ARIA Listbox Pattern:
72
+ * - `role="listbox"` on content
73
+ * - `role="option"` on items
74
+ * - `aria-expanded` on trigger
75
+ * - `aria-labelledby` relationships
76
+ * - Roving tabindex for keyboard navigation
77
+ *
78
+ * ## Keyboard Navigation
79
+ * When focus is on the trigger:
80
+ * - `Enter` / `Space` / `ArrowDown` / `ArrowUp` - Open the select
81
+ *
82
+ * When focus is on an item:
83
+ * - `Enter` / `Space` - Select the focused item
84
+ * - `ArrowDown` - Focus next item
85
+ * - `ArrowUp` - Focus previous item
86
+ * - `Home` - Focus first item
87
+ * - `End` - Focus last item
88
+ * - `Escape` - Close the select
89
+ * - Type to search - Focus matching item
90
+ *
91
+ * @example Basic usage
92
+ * ```html
93
+ * <Select [(value)]="selectedFruit">
94
+ * <SelectTrigger class="w-[180px]">
95
+ * <SelectValue placeholder="Select a fruit" />
96
+ * </SelectTrigger>
97
+ * <SelectContent>
98
+ * <SelectItem value="apple">Apple</SelectItem>
99
+ * <SelectItem value="banana">Banana</SelectItem>
100
+ * <SelectItem value="orange">Orange</SelectItem>
101
+ * </SelectContent>
102
+ * </Select>
103
+ * ```
104
+ *
105
+ * @example With groups
106
+ * ```html
107
+ * <Select>
108
+ * <SelectTrigger>
109
+ * <SelectValue placeholder="Select a timezone" />
110
+ * </SelectTrigger>
111
+ * <SelectContent>
112
+ * <SelectGroup>
113
+ * <SelectLabel>North America</SelectLabel>
114
+ * <SelectItem value="est">Eastern Time</SelectItem>
115
+ * <SelectItem value="cst">Central Time</SelectItem>
116
+ * </SelectGroup>
117
+ * <SelectSeparator />
118
+ * <SelectGroup>
119
+ * <SelectLabel>Europe</SelectLabel>
120
+ * <SelectItem value="gmt">GMT</SelectItem>
121
+ * <SelectItem value="cet">Central European</SelectItem>
122
+ * </SelectGroup>
123
+ * </SelectContent>
124
+ * </Select>
125
+ * ```
126
+ *
127
+ * @example Form usage
128
+ * ```html
129
+ * <Select name="fruit" [required]="true">
130
+ * <SelectTrigger>
131
+ * <SelectValue placeholder="Required field" />
132
+ * </SelectTrigger>
133
+ * <SelectContent>
134
+ * <SelectItem value="apple">Apple</SelectItem>
135
+ * </SelectContent>
136
+ * </Select>
137
+ * ```
138
+ *
139
+ * @data-attributes
140
+ * - `data-state` - 'open' | 'closed'
141
+ * - `data-disabled` - Present when disabled
142
+ */
143
+ @Component({
144
+ selector: 'Select',
145
+ template: `<ng-content />`,
146
+ host: {
147
+ '[class]': 'computedClass()',
148
+ '[attr.data-state]': 'context.open() ? "open" : "closed"',
149
+ '[attr.data-disabled]': 'disabled() ? "" : null',
150
+ 'data-slot': 'select',
151
+ },
152
+ providers: [
153
+ {
154
+ provide: SELECT_CONTEXT,
155
+ useFactory: (component: Select) => component.context,
156
+ deps: [forwardRef(() => Select)],
157
+ },
158
+ ],
159
+ changeDetection: ChangeDetectionStrategy.OnPush,
160
+ })
161
+ export class Select {
162
+ private readonly elementRef = inject(ElementRef<HTMLElement>);
163
+ private readonly ariaIdService = inject(AriaIdService);
164
+ private readonly ariaIds = this.ariaIdService.generateMenuIds('select');
165
+
166
+ /** The controlled value of the select */
167
+ readonly value = model<string>('');
168
+
169
+ /** The controlled open state of the select */
170
+ readonly open = model<boolean>(false);
171
+
172
+ /** When true, prevents the user from interacting with select */
173
+ readonly disabled = input<boolean>(false);
174
+
175
+ /** The name of the select for form submission */
176
+ readonly name = input<string>('');
177
+
178
+ /** When true, indicates that the user must select a value */
179
+ readonly required = input<boolean>(false);
180
+
181
+ /** Additional CSS classes */
182
+ readonly class = input<string>('');
183
+
184
+ /** Event handler called when the value changes */
185
+ readonly valueChange = output<string>();
186
+
187
+ /** Event handler called when the open state changes */
188
+ readonly openChange = output<boolean>();
189
+
190
+ /** Internal signals for context */
191
+ private readonly _value = signal<string>('');
192
+ private readonly _open = signal<boolean>(false);
193
+ private readonly _disabled = signal<boolean>(false);
194
+
195
+ /** Context for child components */
196
+ readonly context: SelectContext = {
197
+ value: this._value,
198
+ open: this._open,
199
+ disabled: this._disabled,
200
+ placeholder: signal(''),
201
+ selectedLabel: signal(''),
202
+ contentId: this.ariaIds.contentId,
203
+ triggerElement: signal<HTMLElement | null>(null),
204
+ itemValues: signal<string[]>([]),
205
+ focusedIndex: signal(-1),
206
+ required: () => this.required(),
207
+ name: () => this.name(),
208
+ setValue: (value: string, label?: string) => {
209
+ this._value.set(value);
210
+ this.value.set(value);
211
+ this.valueChange.emit(value);
212
+ if (label) {
213
+ this.context.selectedLabel.set(label);
214
+ }
215
+ this._open.set(false);
216
+ this.open.set(false);
217
+ this.openChange.emit(false);
218
+ // Restore focus to trigger
219
+ const trigger = this.context.triggerElement();
220
+ if (trigger) {
221
+ setTimeout(() => trigger.focus());
222
+ }
223
+ },
224
+ focusItem: (index: number) => this.focusItemByIndex(index),
225
+ };
226
+
227
+ /** Computed class combining base styles and custom classes */
228
+ protected readonly computedClass = computed(() =>
229
+ cn('relative inline-block', this.class())
230
+ );
231
+
232
+ constructor() {
233
+ // Sync value input to internal signal
234
+ effect(() => {
235
+ this._value.set(this.value());
236
+ });
237
+
238
+ // Sync open input to internal signal
239
+ effect(() => {
240
+ this._open.set(this.open());
241
+ });
242
+
243
+ // Sync disabled input to internal signal
244
+ effect(() => {
245
+ this._disabled.set(this.disabled());
246
+ });
247
+ }
248
+
249
+ /** Focus an item by index */
250
+ private focusItemByIndex(index: number): void {
251
+ const values = this.context.itemValues();
252
+ if (index < 0 || index >= values.length) return;
253
+
254
+ this.context.focusedIndex.set(index);
255
+ const value = values[index];
256
+ const item = this.elementRef.nativeElement.querySelector(
257
+ `[data-slot="select-item"][data-value="${value}"]`
258
+ ) as HTMLElement;
259
+ if (item) {
260
+ item.focus();
261
+ }
262
+ }
263
+ }
@@ -0,0 +1,6 @@
1
+ export {
2
+ Separator,
3
+ type SeparatorOrientation,
4
+ type SeparatorProps
5
+ } from './separator.component';
6
+
@@ -0,0 +1,128 @@
1
+ import { cn } from '@/lib/utils';
2
+ import {
3
+ ChangeDetectionStrategy,
4
+ Component,
5
+ computed,
6
+ input,
7
+ } from '@angular/core';
8
+
9
+ // ============================================================================
10
+ // Types
11
+ // ============================================================================
12
+
13
+ export type SeparatorOrientation = 'horizontal' | 'vertical';
14
+
15
+ export type SeparatorProps = {
16
+ /** The orientation of the separator */
17
+ orientation?: SeparatorOrientation;
18
+ /**
19
+ * Whether the separator is purely decorative.
20
+ * When true, removes from accessibility tree (role="none").
21
+ * When false, uses role="separator" for screen readers.
22
+ */
23
+ decorative?: boolean;
24
+ /** Additional CSS classes to apply */
25
+ class?: string;
26
+ };
27
+
28
+ // ============================================================================
29
+ // Separator Component
30
+ // ============================================================================
31
+
32
+ /**
33
+ * Separator component creates a visual divider between content.
34
+ * Based on Radix UI Separator primitive with shadcn/ui styling.
35
+ *
36
+ * ## Features
37
+ * - Horizontal or vertical orientation
38
+ * - Decorative mode for purely visual separators
39
+ * - Semantic separator role for accessibility when not decorative
40
+ * - Full ARIA support
41
+ *
42
+ * ## Accessibility
43
+ * - Uses `role="separator"` for semantic meaning (unless decorative)
44
+ * - `aria-orientation` indicates the separator direction
45
+ * - Decorative separators are hidden from assistive technology
46
+ *
47
+ * @example
48
+ * <!-- Horizontal separator (default) -->
49
+ * <div class="space-y-4">
50
+ * <p>Some content above</p>
51
+ * <Separator />
52
+ * <p>Some content below</p>
53
+ * </div>
54
+ *
55
+ * @example
56
+ * <!-- Vertical separator -->
57
+ * <div class="flex h-5 items-center space-x-4 text-sm">
58
+ * <span>Blog</span>
59
+ * <Separator orientation="vertical" />
60
+ * <span>Docs</span>
61
+ * <Separator orientation="vertical" />
62
+ * <span>Source</span>
63
+ * </div>
64
+ *
65
+ * @example
66
+ * <!-- Decorative separator (hidden from screen readers) -->
67
+ * <Separator [decorative]="true" />
68
+ *
69
+ * @example
70
+ * <!-- With custom styling -->
71
+ * <Separator class="my-4 bg-primary/50" />
72
+ *
73
+ * @see {@link https://www.radix-ui.com/primitives/docs/components/separator Radix Separator}
74
+ * @see {@link https://ui.shadcn.com/docs/components/separator shadcn/ui Separator}
75
+ */
76
+ @Component({
77
+ selector: 'Separator',
78
+ template: ``,
79
+ host: {
80
+ '[class]': 'computedClass()',
81
+ '[attr.role]': 'role()',
82
+ '[attr.aria-orientation]': 'ariaOrientation()',
83
+ '[attr.data-orientation]': 'orientation()',
84
+ 'data-slot': 'separator',
85
+ },
86
+ changeDetection: ChangeDetectionStrategy.OnPush,
87
+ })
88
+ export class Separator {
89
+ /** The orientation of the separator */
90
+ readonly orientation = input<SeparatorOrientation>('horizontal');
91
+
92
+ /**
93
+ * Whether the separator is purely decorative.
94
+ * When true, removes from accessibility tree.
95
+ */
96
+ readonly decorative = input<boolean>(false);
97
+
98
+ /** Additional CSS classes to apply */
99
+ readonly class = input<string>('');
100
+
101
+ /** Computed role - none for decorative, separator otherwise */
102
+ protected readonly role = computed(() =>
103
+ this.decorative() ? 'none' : 'separator'
104
+ );
105
+
106
+ /**
107
+ * aria-orientation is only needed for non-decorative separators.
108
+ * Per WAI-ARIA, separators default to horizontal, so we only need
109
+ * to specify when vertical.
110
+ */
111
+ protected readonly ariaOrientation = computed(() => {
112
+ if (this.decorative()) return undefined;
113
+ // Only specify aria-orientation for vertical (horizontal is default)
114
+ return this.orientation() === 'vertical' ? 'vertical' : undefined;
115
+ });
116
+
117
+ /** Computed class based on orientation */
118
+ protected readonly computedClass = computed(() =>
119
+ cn(
120
+ // Base styles
121
+ 'bg-border shrink-0',
122
+ // Orientation-specific styles
123
+ this.orientation() === 'horizontal' ? 'h-px w-full' : 'h-full w-px',
124
+ // Custom classes
125
+ this.class()
126
+ )
127
+ );
128
+ }
@@ -0,0 +1,11 @@
1
+ export { SheetClose } from './sheet-close.component';
2
+ export { SheetContent } from './sheet-content.component';
3
+ export { SHEET_CONTEXT, type SheetContextValue } from './sheet-context';
4
+ export { SheetDescription } from './sheet-description.component';
5
+ export { SheetFooter } from './sheet-footer.component';
6
+ export { SheetHeader } from './sheet-header.component';
7
+ export { SheetTitle } from './sheet-title.component';
8
+ export { SheetTrigger } from './sheet-trigger.component';
9
+ export { sheetVariants, type SheetVariants } from './sheet-variants';
10
+ export { Sheet } from './sheet.component';
11
+
@@ -0,0 +1,32 @@
1
+ import {
2
+ ChangeDetectionStrategy,
3
+ Component,
4
+ inject,
5
+ input,
6
+ } from '@angular/core';
7
+ import { SHEET_CONTEXT } from './sheet-context';
8
+
9
+ /**
10
+ * SheetClose component - button that closes the sheet.
11
+ * Matches shadcn/ui React SheetClose exactly.
12
+ */
13
+ @Component({
14
+ selector: 'SheetClose',
15
+ template: `<ng-content />`,
16
+ host: {
17
+ class: 'contents',
18
+ '(click)': 'onClick($event)',
19
+ },
20
+ changeDetection: ChangeDetectionStrategy.OnPush,
21
+ })
22
+ export class SheetClose {
23
+ protected readonly context = inject(SHEET_CONTEXT);
24
+
25
+ /** Render as child */
26
+ readonly asChild = input<boolean>(false);
27
+
28
+ onClick(event: Event): void {
29
+ event.stopPropagation();
30
+ this.context.setOpen(false);
31
+ }
32
+ }
@@ -0,0 +1,157 @@
1
+ import { cn, Presence } from '@/lib/utils';
2
+ import { FocusTrapDirective } from '@/lib/utils/accessibility';
3
+ import {
4
+ ChangeDetectionStrategy,
5
+ Component,
6
+ computed,
7
+ effect,
8
+ inject,
9
+ input,
10
+ OnDestroy
11
+ } from '@angular/core';
12
+ import { SHEET_CONTEXT } from './sheet-context';
13
+ import { sheetVariants, type SheetVariants } from './sheet-variants';
14
+
15
+ /**
16
+ * SheetContent component - the content of the sheet panel.
17
+ * Matches shadcn/ui React SheetContent exactly.
18
+ * Includes focus trapping, focus restoration, proper ARIA relationships,
19
+ * and Radix-compatible exit animations via Presence component.
20
+ */
21
+ @Component({
22
+ selector: 'SheetContent',
23
+ imports: [FocusTrapDirective, Presence],
24
+ template: `
25
+ <Presence [present]="context.open()">
26
+ <!-- Overlay -->
27
+ <div
28
+ class="fixed inset-0 z-[100] bg-black/50 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0"
29
+ [attr.data-state]="context.open() ? 'open' : 'closed'"
30
+ (click)="onOverlayClick($event)"
31
+ aria-hidden="true"
32
+ ></div>
33
+ <!-- Content -->
34
+ <div
35
+ hlmFocusTrap
36
+ [trapFocus]="context.open()"
37
+ [autoFocus]="true"
38
+ [restoreFocus]="false"
39
+ [class]="computedClass()"
40
+ [attr.data-state]="context.open() ? 'open' : 'closed'"
41
+ [attr.data-side]="side()"
42
+ [attr.id]="context.contentId"
43
+ [attr.aria-labelledby]="context.titleId"
44
+ [attr.aria-describedby]="context.descriptionId"
45
+ role="dialog"
46
+ aria-modal="true"
47
+ (keydown.escape)="onEscapeKey()"
48
+ >
49
+ <ng-content />
50
+ <!-- Close button -->
51
+ <button
52
+ type="button"
53
+ class="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-secondary"
54
+ (click)="onClose()"
55
+ aria-label="Close sheet"
56
+ >
57
+ <svg
58
+ xmlns="http://www.w3.org/2000/svg"
59
+ width="24"
60
+ height="24"
61
+ viewBox="0 0 24 24"
62
+ fill="none"
63
+ stroke="currentColor"
64
+ stroke-width="2"
65
+ stroke-linecap="round"
66
+ stroke-linejoin="round"
67
+ class="h-4 w-4"
68
+ aria-hidden="true"
69
+ >
70
+ <path d="M18 6 6 18" />
71
+ <path d="m6 6 12 12" />
72
+ </svg>
73
+ <span class="sr-only">Close</span>
74
+ </button>
75
+ </div>
76
+ </Presence>
77
+ `,
78
+ host: {
79
+ class: 'contents',
80
+ },
81
+ changeDetection: ChangeDetectionStrategy.OnPush,
82
+ })
83
+ export class SheetContent implements OnDestroy {
84
+ protected readonly context = inject(SHEET_CONTEXT);
85
+
86
+ /** Side from which the sheet appears */
87
+ readonly side = input<SheetVariants['side']>('right');
88
+
89
+ /** Additional CSS classes */
90
+ readonly class = input<string>('');
91
+
92
+ /** Previous body overflow for restoration */
93
+ private previousBodyOverflow = '';
94
+
95
+ protected readonly computedClass = computed(() =>
96
+ cn(sheetVariants({ side: this.side() }), this.class())
97
+ );
98
+
99
+ constructor() {
100
+ // Handle body scroll lock based on open state (browser-only via effect + afterNextRender)
101
+ effect(() => {
102
+ const isOpen = this.context.open();
103
+ if (isOpen) {
104
+ this.lockBodyScroll();
105
+ } else {
106
+ this.unlockBodyScroll();
107
+ }
108
+ });
109
+ }
110
+
111
+ private lockBodyScroll(): void {
112
+ if (typeof document !== 'undefined') {
113
+ this.previousBodyOverflow = document.body.style.overflow;
114
+ document.body.style.overflow = 'hidden';
115
+ }
116
+ }
117
+
118
+ private unlockBodyScroll(): void {
119
+ if (typeof document !== 'undefined') {
120
+ document.body.style.overflow = this.previousBodyOverflow;
121
+ }
122
+ }
123
+
124
+ ngOnDestroy(): void {
125
+ // Restore body scroll
126
+ this.unlockBodyScroll();
127
+ // Restore focus to trigger element
128
+ this.restoreFocus();
129
+ }
130
+
131
+ onOverlayClick(event: Event): void {
132
+ event.stopPropagation();
133
+ this.close();
134
+ }
135
+
136
+ onEscapeKey(): void {
137
+ this.close();
138
+ }
139
+
140
+ onClose(): void {
141
+ this.close();
142
+ }
143
+
144
+ private close(): void {
145
+ this.restoreFocus();
146
+ this.context.setOpen(false);
147
+ }
148
+
149
+ private restoreFocus(): void {
150
+ const triggerEl = this.context.triggerElement();
151
+ if (triggerEl) {
152
+ setTimeout(() => {
153
+ triggerEl.focus();
154
+ }, 0);
155
+ }
156
+ }
157
+ }
@@ -0,0 +1,15 @@
1
+ import { InjectionToken, Signal, WritableSignal } from '@angular/core';
2
+
3
+ export interface SheetContextValue {
4
+ open: Signal<boolean>;
5
+ setOpen: (open: boolean) => void;
6
+ side: 'top' | 'right' | 'bottom' | 'left';
7
+ /** Unique IDs for ARIA relationships */
8
+ titleId: string;
9
+ descriptionId: string;
10
+ contentId: string;
11
+ /** Trigger element reference for focus restoration */
12
+ triggerElement: WritableSignal<HTMLElement | null>;
13
+ }
14
+
15
+ export const SHEET_CONTEXT = new InjectionToken<SheetContextValue>('SHEET_CONTEXT');
@@ -0,0 +1,34 @@
1
+ import { cn } from '@/lib/utils';
2
+ import {
3
+ ChangeDetectionStrategy,
4
+ Component,
5
+ computed,
6
+ inject,
7
+ input,
8
+ } from '@angular/core';
9
+ import { SHEET_CONTEXT } from './sheet-context';
10
+
11
+ /**
12
+ * SheetDescription component - description text of the sheet.
13
+ * Matches shadcn/ui React SheetDescription exactly.
14
+ * Automatically links to sheet via aria-describedby.
15
+ */
16
+ @Component({
17
+ selector: 'SheetDescription',
18
+ template: `<ng-content />`,
19
+ host: {
20
+ '[class]': 'computedClass()',
21
+ '[attr.id]': 'context.descriptionId',
22
+ },
23
+ changeDetection: ChangeDetectionStrategy.OnPush,
24
+ })
25
+ export class SheetDescription {
26
+ protected readonly context = inject(SHEET_CONTEXT);
27
+
28
+ /** Additional CSS classes */
29
+ readonly class = input<string>('');
30
+
31
+ protected readonly computedClass = computed(() =>
32
+ cn('text-sm text-muted-foreground', this.class())
33
+ );
34
+ }
@@ -0,0 +1,28 @@
1
+ import { cn } from '@/lib/utils';
2
+ import {
3
+ ChangeDetectionStrategy,
4
+ Component,
5
+ computed,
6
+ input,
7
+ } from '@angular/core';
8
+
9
+ /**
10
+ * SheetFooter component - footer area of the sheet.
11
+ * Matches shadcn/ui React SheetFooter exactly.
12
+ */
13
+ @Component({
14
+ selector: 'SheetFooter',
15
+ template: `<ng-content />`,
16
+ host: {
17
+ '[class]': 'computedClass()',
18
+ },
19
+ changeDetection: ChangeDetectionStrategy.OnPush,
20
+ })
21
+ export class SheetFooter {
22
+ /** Additional CSS classes */
23
+ readonly class = input<string>('');
24
+
25
+ protected readonly computedClass = computed(() =>
26
+ cn('flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2', this.class())
27
+ );
28
+ }