@ng-cn/core 1.0.11 → 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 (394) hide show
  1. package/package.json +2 -1
  2. package/schematics/ng-add/index.js +2 -2
  3. package/schematics/ng-add/index.ts +2 -2
  4. package/src/app/lib/components/ui/accordion/accordion-content.component.ts +53 -0
  5. package/src/app/lib/components/ui/accordion/accordion-context.ts +33 -0
  6. package/src/app/lib/components/ui/accordion/accordion-item.component.ts +86 -0
  7. package/src/app/lib/components/ui/accordion/accordion-trigger.component.ts +73 -0
  8. package/src/app/lib/components/ui/accordion/accordion.component.ts +197 -0
  9. package/src/app/lib/components/ui/accordion/index.ts +15 -0
  10. package/src/app/lib/components/ui/alert/alert-description.component.ts +33 -0
  11. package/src/app/lib/components/ui/alert/alert-title.component.ts +30 -0
  12. package/src/app/lib/components/ui/alert/alert-variants.ts +23 -0
  13. package/src/app/lib/components/ui/alert/alert.component.ts +50 -0
  14. package/src/app/lib/components/ui/alert/index.ts +5 -0
  15. package/src/app/lib/components/ui/alert-dialog/alert-dialog-action.component.ts +44 -0
  16. package/src/app/lib/components/ui/alert-dialog/alert-dialog-cancel.component.ts +45 -0
  17. package/src/app/lib/components/ui/alert-dialog/alert-dialog-content.component.ts +146 -0
  18. package/src/app/lib/components/ui/alert-dialog/alert-dialog-context.ts +14 -0
  19. package/src/app/lib/components/ui/alert-dialog/alert-dialog-description.component.ts +37 -0
  20. package/src/app/lib/components/ui/alert-dialog/alert-dialog-footer.component.ts +35 -0
  21. package/src/app/lib/components/ui/alert-dialog/alert-dialog-header.component.ts +35 -0
  22. package/src/app/lib/components/ui/alert-dialog/alert-dialog-title.component.ts +37 -0
  23. package/src/app/lib/components/ui/alert-dialog/alert-dialog-trigger.component.ts +44 -0
  24. package/src/app/lib/components/ui/alert-dialog/alert-dialog.component.ts +91 -0
  25. package/src/app/lib/components/ui/alert-dialog/index.ts +11 -0
  26. package/src/app/lib/components/ui/aspect-ratio/aspect-ratio.component.ts +63 -0
  27. package/src/app/lib/components/ui/aspect-ratio/index.ts +1 -0
  28. package/src/app/lib/components/ui/avatar/avatar-fallback.component.ts +34 -0
  29. package/src/app/lib/components/ui/avatar/avatar-image.component.ts +31 -0
  30. package/src/app/lib/components/ui/avatar/avatar.component.ts +37 -0
  31. package/src/app/lib/components/ui/avatar/index.ts +5 -0
  32. package/src/app/lib/components/ui/avatar/ui-avatar.component.ts +52 -0
  33. package/src/app/lib/components/ui/badge/badge-variants.ts +28 -0
  34. package/src/app/lib/components/ui/badge/badge.component.ts +50 -0
  35. package/src/app/lib/components/ui/badge/index.ts +3 -0
  36. package/src/app/lib/components/ui/breadcrumb/breadcrumb-ellipsis.component.ts +48 -0
  37. package/src/app/lib/components/ui/breadcrumb/breadcrumb-item.component.ts +28 -0
  38. package/src/app/lib/components/ui/breadcrumb/breadcrumb-link.component.ts +32 -0
  39. package/src/app/lib/components/ui/breadcrumb/breadcrumb-list.component.ts +31 -0
  40. package/src/app/lib/components/ui/breadcrumb/breadcrumb-page.component.ts +31 -0
  41. package/src/app/lib/components/ui/breadcrumb/breadcrumb-separator.component.ts +47 -0
  42. package/src/app/lib/components/ui/breadcrumb/breadcrumb.component.ts +43 -0
  43. package/src/app/lib/components/ui/breadcrumb/index.ts +8 -0
  44. package/src/app/lib/components/ui/button/button-variants.ts +38 -0
  45. package/src/app/lib/components/ui/button/button.component.ts +103 -0
  46. package/src/app/lib/components/ui/button/index.ts +3 -0
  47. package/src/app/lib/components/ui/button-group/button-group-variants.ts +24 -0
  48. package/src/app/lib/components/ui/button-group/button-group.component.ts +57 -0
  49. package/src/app/lib/components/ui/button-group/index.ts +6 -0
  50. package/src/app/lib/components/ui/calendar/calendar.component.ts +368 -0
  51. package/src/app/lib/components/ui/calendar/index.ts +1 -0
  52. package/src/app/lib/components/ui/card/card-action.component.ts +39 -0
  53. package/src/app/lib/components/ui/card/card-content.component.ts +31 -0
  54. package/src/app/lib/components/ui/card/card-description.component.ts +31 -0
  55. package/src/app/lib/components/ui/card/card-footer.component.ts +34 -0
  56. package/src/app/lib/components/ui/card/card-header.component.ts +37 -0
  57. package/src/app/lib/components/ui/card/card-title.component.ts +31 -0
  58. package/src/app/lib/components/ui/card/card.component.ts +41 -0
  59. package/src/app/lib/components/ui/card/index.ts +8 -0
  60. package/src/app/lib/components/ui/carousel/carousel-content.component.ts +38 -0
  61. package/src/app/lib/components/ui/carousel/carousel-context.ts +18 -0
  62. package/src/app/lib/components/ui/carousel/carousel-item.component.ts +32 -0
  63. package/src/app/lib/components/ui/carousel/carousel-next.component.ts +54 -0
  64. package/src/app/lib/components/ui/carousel/carousel-previous.component.ts +54 -0
  65. package/src/app/lib/components/ui/carousel/carousel.component.ts +125 -0
  66. package/src/app/lib/components/ui/carousel/index.ts +7 -0
  67. package/src/app/lib/components/ui/chart/chart-container.component.ts +81 -0
  68. package/src/app/lib/components/ui/chart/chart-context.ts +38 -0
  69. package/src/app/lib/components/ui/chart/chart-legend-content.component.ts +51 -0
  70. package/src/app/lib/components/ui/chart/chart-legend.component.ts +28 -0
  71. package/src/app/lib/components/ui/chart/chart-tooltip-content.component.ts +37 -0
  72. package/src/app/lib/components/ui/chart/chart-tooltip.component.ts +28 -0
  73. package/src/app/lib/components/ui/chart/chart.component.ts +308 -0
  74. package/src/app/lib/components/ui/chart/index.ts +16 -0
  75. package/src/app/lib/components/ui/checkbox/checkbox.component.ts +203 -0
  76. package/src/app/lib/components/ui/checkbox/index.ts +1 -0
  77. package/src/app/lib/components/ui/collapsible/collapsible-content.component.ts +58 -0
  78. package/src/app/lib/components/ui/collapsible/collapsible-context.ts +17 -0
  79. package/src/app/lib/components/ui/collapsible/collapsible-trigger.component.ts +56 -0
  80. package/src/app/lib/components/ui/collapsible/collapsible.component.ts +102 -0
  81. package/src/app/lib/components/ui/collapsible/index.ts +5 -0
  82. package/src/app/lib/components/ui/combobox/combobox-content.component.ts +59 -0
  83. package/src/app/lib/components/ui/combobox/combobox-context.ts +49 -0
  84. package/src/app/lib/components/ui/combobox/combobox-empty.component.ts +35 -0
  85. package/src/app/lib/components/ui/combobox/combobox-group.component.ts +32 -0
  86. package/src/app/lib/components/ui/combobox/combobox-input.component.ts +89 -0
  87. package/src/app/lib/components/ui/combobox/combobox-item.component.ts +129 -0
  88. package/src/app/lib/components/ui/combobox/combobox-list.component.ts +40 -0
  89. package/src/app/lib/components/ui/combobox/combobox-trigger.component.ts +53 -0
  90. package/src/app/lib/components/ui/combobox/combobox-value.component.ts +47 -0
  91. package/src/app/lib/components/ui/combobox/combobox.component.ts +290 -0
  92. package/src/app/lib/components/ui/combobox/index.ts +15 -0
  93. package/src/app/lib/components/ui/command/command-context.ts +24 -0
  94. package/src/app/lib/components/ui/command/command-dialog.component.ts +69 -0
  95. package/src/app/lib/components/ui/command/command-empty.component.ts +23 -0
  96. package/src/app/lib/components/ui/command/command-group.component.ts +66 -0
  97. package/src/app/lib/components/ui/command/command-input.component.ts +137 -0
  98. package/src/app/lib/components/ui/command/command-item.component.ts +148 -0
  99. package/src/app/lib/components/ui/command/command-list.component.ts +30 -0
  100. package/src/app/lib/components/ui/command/command-separator.component.ts +23 -0
  101. package/src/app/lib/components/ui/command/command-shortcut.component.ts +23 -0
  102. package/src/app/lib/components/ui/command/command.component.ts +105 -0
  103. package/src/app/lib/components/ui/command/index.ts +11 -0
  104. package/src/app/lib/components/ui/context-menu/context-menu-checkbox-item.component.ts +68 -0
  105. package/src/app/lib/components/ui/context-menu/context-menu-content.component.ts +213 -0
  106. package/src/app/lib/components/ui/context-menu/context-menu-context.ts +17 -0
  107. package/src/app/lib/components/ui/context-menu/context-menu-item.component.ts +63 -0
  108. package/src/app/lib/components/ui/context-menu/context-menu-label.component.ts +30 -0
  109. package/src/app/lib/components/ui/context-menu/context-menu-radio-group.component.ts +36 -0
  110. package/src/app/lib/components/ui/context-menu/context-menu-radio-item.component.ts +71 -0
  111. package/src/app/lib/components/ui/context-menu/context-menu-separator.component.ts +24 -0
  112. package/src/app/lib/components/ui/context-menu/context-menu-shortcut.component.ts +23 -0
  113. package/src/app/lib/components/ui/context-menu/context-menu-sub-content.component.ts +51 -0
  114. package/src/app/lib/components/ui/context-menu/context-menu-sub-trigger.component.ts +50 -0
  115. package/src/app/lib/components/ui/context-menu/context-menu-sub.component.ts +31 -0
  116. package/src/app/lib/components/ui/context-menu/context-menu-trigger.component.ts +51 -0
  117. package/src/app/lib/components/ui/context-menu/context-menu.component.ts +27 -0
  118. package/src/app/lib/components/ui/context-menu/index.ts +15 -0
  119. package/src/app/lib/components/ui/data-table/data-table-content.component.ts +226 -0
  120. package/src/app/lib/components/ui/data-table/data-table-context.ts +49 -0
  121. package/src/app/lib/components/ui/data-table/data-table-pagination.component.ts +138 -0
  122. package/src/app/lib/components/ui/data-table/data-table-search.component.ts +52 -0
  123. package/src/app/lib/components/ui/data-table/data-table-toolbar.component.ts +27 -0
  124. package/src/app/lib/components/ui/data-table/data-table-view-options.component.ts +92 -0
  125. package/src/app/lib/components/ui/data-table/data-table.component.ts +131 -0
  126. package/src/app/lib/components/ui/data-table/index.ts +16 -0
  127. package/src/app/lib/components/ui/date-picker/date-picker.component.ts +94 -0
  128. package/src/app/lib/components/ui/date-picker/index.ts +1 -0
  129. package/src/app/lib/components/ui/dialog/dialog-close.component.ts +31 -0
  130. package/src/app/lib/components/ui/dialog/dialog-content.component.ts +177 -0
  131. package/src/app/lib/components/ui/dialog/dialog-context.ts +15 -0
  132. package/src/app/lib/components/ui/dialog/dialog-description.component.ts +34 -0
  133. package/src/app/lib/components/ui/dialog/dialog-footer.component.ts +28 -0
  134. package/src/app/lib/components/ui/dialog/dialog-header.component.ts +28 -0
  135. package/src/app/lib/components/ui/dialog/dialog-title.component.ts +34 -0
  136. package/src/app/lib/components/ui/dialog/dialog-trigger.component.ts +38 -0
  137. package/src/app/lib/components/ui/dialog/dialog.component.ts +87 -0
  138. package/src/app/lib/components/ui/dialog/index.ts +10 -0
  139. package/src/app/lib/components/ui/drawer/drawer-close.component.ts +31 -0
  140. package/src/app/lib/components/ui/drawer/drawer-content.component.ts +143 -0
  141. package/src/app/lib/components/ui/drawer/drawer-context.ts +17 -0
  142. package/src/app/lib/components/ui/drawer/drawer-description.component.ts +33 -0
  143. package/src/app/lib/components/ui/drawer/drawer-footer.component.ts +28 -0
  144. package/src/app/lib/components/ui/drawer/drawer-header.component.ts +28 -0
  145. package/src/app/lib/components/ui/drawer/drawer-title.component.ts +33 -0
  146. package/src/app/lib/components/ui/drawer/drawer-trigger.component.ts +38 -0
  147. package/src/app/lib/components/ui/drawer/drawer.component.ts +93 -0
  148. package/src/app/lib/components/ui/drawer/index.ts +10 -0
  149. package/src/app/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-item.component.ts +68 -0
  150. package/src/app/lib/components/ui/dropdown-menu/dropdown-menu-content.component.ts +234 -0
  151. package/src/app/lib/components/ui/dropdown-menu/dropdown-menu-context.ts +15 -0
  152. package/src/app/lib/components/ui/dropdown-menu/dropdown-menu-group.component.ts +15 -0
  153. package/src/app/lib/components/ui/dropdown-menu/dropdown-menu-item.component.ts +56 -0
  154. package/src/app/lib/components/ui/dropdown-menu/dropdown-menu-label.component.ts +30 -0
  155. package/src/app/lib/components/ui/dropdown-menu/dropdown-menu-radio-group.component.ts +42 -0
  156. package/src/app/lib/components/ui/dropdown-menu/dropdown-menu-radio-item.component.ts +71 -0
  157. package/src/app/lib/components/ui/dropdown-menu/dropdown-menu-separator.component.ts +24 -0
  158. package/src/app/lib/components/ui/dropdown-menu/dropdown-menu-shortcut.component.ts +23 -0
  159. package/src/app/lib/components/ui/dropdown-menu/dropdown-menu-sub-content.component.ts +51 -0
  160. package/src/app/lib/components/ui/dropdown-menu/dropdown-menu-sub-trigger.component.ts +53 -0
  161. package/src/app/lib/components/ui/dropdown-menu/dropdown-menu-sub.component.ts +31 -0
  162. package/src/app/lib/components/ui/dropdown-menu/dropdown-menu-trigger.component.ts +45 -0
  163. package/src/app/lib/components/ui/dropdown-menu/dropdown-menu.component.ts +32 -0
  164. package/src/app/lib/components/ui/dropdown-menu/index.ts +16 -0
  165. package/src/app/lib/components/ui/empty/empty-action.component.ts +28 -0
  166. package/src/app/lib/components/ui/empty/empty-description.component.ts +31 -0
  167. package/src/app/lib/components/ui/empty/empty-icon.component.ts +31 -0
  168. package/src/app/lib/components/ui/empty/empty-title.component.ts +28 -0
  169. package/src/app/lib/components/ui/empty/empty.component.ts +53 -0
  170. package/src/app/lib/components/ui/empty/index.ts +6 -0
  171. package/src/app/lib/components/ui/form/form-context.ts +34 -0
  172. package/src/app/lib/components/ui/form/form-control.component.ts +137 -0
  173. package/src/app/lib/components/ui/form/form-description.component.ts +37 -0
  174. package/src/app/lib/components/ui/form/form-field.component.ts +84 -0
  175. package/src/app/lib/components/ui/form/form-item.component.ts +42 -0
  176. package/src/app/lib/components/ui/form/form-label.component.ts +58 -0
  177. package/src/app/lib/components/ui/form/form-message.component.ts +107 -0
  178. package/src/app/lib/components/ui/form/form.component.ts +123 -0
  179. package/src/app/lib/components/ui/form/index.ts +17 -0
  180. package/src/app/lib/components/ui/hover-card/hover-card-content.component.ts +203 -0
  181. package/src/app/lib/components/ui/hover-card/hover-card-context.ts +25 -0
  182. package/src/app/lib/components/ui/hover-card/hover-card-trigger.component.ts +160 -0
  183. package/src/app/lib/components/ui/hover-card/hover-card.component.ts +147 -0
  184. package/src/app/lib/components/ui/hover-card/index.ts +13 -0
  185. package/src/app/lib/components/ui/index.ts +551 -0
  186. package/src/app/lib/components/ui/input/index.ts +1 -0
  187. package/src/app/lib/components/ui/input/input.component.ts +165 -0
  188. package/src/app/lib/components/ui/input-group/index.ts +4 -0
  189. package/src/app/lib/components/ui/input-group/input-group-addon.component.ts +43 -0
  190. package/src/app/lib/components/ui/input-group/input-group-input.component.ts +33 -0
  191. package/src/app/lib/components/ui/input-group/input-group.component.ts +53 -0
  192. package/src/app/lib/components/ui/input-otp/index.ts +14 -0
  193. package/src/app/lib/components/ui/input-otp/input-otp-context.ts +31 -0
  194. package/src/app/lib/components/ui/input-otp/input-otp-group.component.ts +23 -0
  195. package/src/app/lib/components/ui/input-otp/input-otp-separator.component.ts +31 -0
  196. package/src/app/lib/components/ui/input-otp/input-otp-slot.component.ts +67 -0
  197. package/src/app/lib/components/ui/input-otp/input-otp.component.ts +240 -0
  198. package/src/app/lib/components/ui/kbd/index.ts +3 -0
  199. package/src/app/lib/components/ui/kbd/kbd-variants.ts +23 -0
  200. package/src/app/lib/components/ui/kbd/kbd.component.ts +50 -0
  201. package/src/app/lib/components/ui/label/index.ts +1 -0
  202. package/src/app/lib/components/ui/label/label.component.ts +139 -0
  203. package/src/app/lib/components/ui/menubar/index.ts +26 -0
  204. package/src/app/lib/components/ui/menubar/menubar-checkbox-item.component.ts +66 -0
  205. package/src/app/lib/components/ui/menubar/menubar-content.component.ts +236 -0
  206. package/src/app/lib/components/ui/menubar/menubar-context.ts +63 -0
  207. package/src/app/lib/components/ui/menubar/menubar-item.component.ts +60 -0
  208. package/src/app/lib/components/ui/menubar/menubar-label.component.ts +30 -0
  209. package/src/app/lib/components/ui/menubar/menubar-menu.component.ts +40 -0
  210. package/src/app/lib/components/ui/menubar/menubar-radio-group.component.ts +36 -0
  211. package/src/app/lib/components/ui/menubar/menubar-radio-item.component.ts +66 -0
  212. package/src/app/lib/components/ui/menubar/menubar-separator.component.ts +24 -0
  213. package/src/app/lib/components/ui/menubar/menubar-shortcut.component.ts +23 -0
  214. package/src/app/lib/components/ui/menubar/menubar-sub-content.component.ts +51 -0
  215. package/src/app/lib/components/ui/menubar/menubar-sub-trigger.component.ts +50 -0
  216. package/src/app/lib/components/ui/menubar/menubar-sub.component.ts +29 -0
  217. package/src/app/lib/components/ui/menubar/menubar-trigger.component.ts +132 -0
  218. package/src/app/lib/components/ui/menubar/menubar.component.ts +158 -0
  219. package/src/app/lib/components/ui/native-select/index.ts +6 -0
  220. package/src/app/lib/components/ui/native-select/native-select-variants.ts +23 -0
  221. package/src/app/lib/components/ui/native-select/native-select.component.ts +74 -0
  222. package/src/app/lib/components/ui/navigation-menu/index.ts +21 -0
  223. package/src/app/lib/components/ui/navigation-menu/navigation-menu-content.component.ts +66 -0
  224. package/src/app/lib/components/ui/navigation-menu/navigation-menu-context.ts +55 -0
  225. package/src/app/lib/components/ui/navigation-menu/navigation-menu-indicator.component.ts +28 -0
  226. package/src/app/lib/components/ui/navigation-menu/navigation-menu-item.component.ts +29 -0
  227. package/src/app/lib/components/ui/navigation-menu/navigation-menu-link.component.ts +43 -0
  228. package/src/app/lib/components/ui/navigation-menu/navigation-menu-list.component.ts +26 -0
  229. package/src/app/lib/components/ui/navigation-menu/navigation-menu-trigger-style.ts +7 -0
  230. package/src/app/lib/components/ui/navigation-menu/navigation-menu-trigger.component.ts +58 -0
  231. package/src/app/lib/components/ui/navigation-menu/navigation-menu-viewport.component.ts +26 -0
  232. package/src/app/lib/components/ui/navigation-menu/navigation-menu.component.ts +149 -0
  233. package/src/app/lib/components/ui/pagination/index.ts +8 -0
  234. package/src/app/lib/components/ui/pagination/pagination-content.component.ts +28 -0
  235. package/src/app/lib/components/ui/pagination/pagination-ellipsis.component.ts +47 -0
  236. package/src/app/lib/components/ui/pagination/pagination-item.component.ts +28 -0
  237. package/src/app/lib/components/ui/pagination/pagination-link.component.ts +46 -0
  238. package/src/app/lib/components/ui/pagination/pagination-next.component.ts +54 -0
  239. package/src/app/lib/components/ui/pagination/pagination-previous.component.ts +54 -0
  240. package/src/app/lib/components/ui/pagination/pagination.component.ts +48 -0
  241. package/src/app/lib/components/ui/popover/index.ts +14 -0
  242. package/src/app/lib/components/ui/popover/popover-anchor.component.ts +64 -0
  243. package/src/app/lib/components/ui/popover/popover-content.component.ts +231 -0
  244. package/src/app/lib/components/ui/popover/popover-context.ts +29 -0
  245. package/src/app/lib/components/ui/popover/popover-trigger.component.ts +100 -0
  246. package/src/app/lib/components/ui/popover/popover.component.ts +163 -0
  247. package/src/app/lib/components/ui/progress/index.ts +6 -0
  248. package/src/app/lib/components/ui/progress/progress.component.ts +212 -0
  249. package/src/app/lib/components/ui/radio-group/index.ts +10 -0
  250. package/src/app/lib/components/ui/radio-group/radio-group-context.ts +38 -0
  251. package/src/app/lib/components/ui/radio-group/radio-group-item.component.ts +298 -0
  252. package/src/app/lib/components/ui/radio-group/radio-group.component.ts +275 -0
  253. package/src/app/lib/components/ui/resizable/index.ts +5 -0
  254. package/src/app/lib/components/ui/resizable/resizable-context.ts +14 -0
  255. package/src/app/lib/components/ui/resizable/resizable-handle.component.ts +232 -0
  256. package/src/app/lib/components/ui/resizable/resizable-panel-group.component.ts +140 -0
  257. package/src/app/lib/components/ui/resizable/resizable-panel.component.ts +77 -0
  258. package/src/app/lib/components/ui/scroll-area/index.ts +8 -0
  259. package/src/app/lib/components/ui/scroll-area/scroll-area.component.ts +126 -0
  260. package/src/app/lib/components/ui/scroll-area/scroll-bar.component.ts +93 -0
  261. package/src/app/lib/components/ui/segmented/index.ts +13 -0
  262. package/src/app/lib/components/ui/segmented/segmented-context.ts +11 -0
  263. package/src/app/lib/components/ui/segmented/segmented-item.component.ts +72 -0
  264. package/src/app/lib/components/ui/segmented/segmented-variants.ts +40 -0
  265. package/src/app/lib/components/ui/segmented/segmented.component.ts +99 -0
  266. package/src/app/lib/components/ui/select/index.ts +19 -0
  267. package/src/app/lib/components/ui/select/select-content.component.ts +97 -0
  268. package/src/app/lib/components/ui/select/select-context.ts +53 -0
  269. package/src/app/lib/components/ui/select/select-group.component.ts +56 -0
  270. package/src/app/lib/components/ui/select/select-item.component.ts +163 -0
  271. package/src/app/lib/components/ui/select/select-label.component.ts +32 -0
  272. package/src/app/lib/components/ui/select/select-separator.component.ts +34 -0
  273. package/src/app/lib/components/ui/select/select-trigger.component.ts +164 -0
  274. package/src/app/lib/components/ui/select/select-value.component.ts +49 -0
  275. package/src/app/lib/components/ui/select/select.component.ts +263 -0
  276. package/src/app/lib/components/ui/separator/index.ts +6 -0
  277. package/src/app/lib/components/ui/separator/separator.component.ts +128 -0
  278. package/src/app/lib/components/ui/sheet/index.ts +11 -0
  279. package/src/app/lib/components/ui/sheet/sheet-close.component.ts +32 -0
  280. package/src/app/lib/components/ui/sheet/sheet-content.component.ts +157 -0
  281. package/src/app/lib/components/ui/sheet/sheet-context.ts +15 -0
  282. package/src/app/lib/components/ui/sheet/sheet-description.component.ts +34 -0
  283. package/src/app/lib/components/ui/sheet/sheet-footer.component.ts +28 -0
  284. package/src/app/lib/components/ui/sheet/sheet-header.component.ts +28 -0
  285. package/src/app/lib/components/ui/sheet/sheet-title.component.ts +34 -0
  286. package/src/app/lib/components/ui/sheet/sheet-trigger.component.ts +38 -0
  287. package/src/app/lib/components/ui/sheet/sheet-variants.ts +22 -0
  288. package/src/app/lib/components/ui/sheet/sheet.component.ts +97 -0
  289. package/src/app/lib/components/ui/sidebar/index.ts +41 -0
  290. package/src/app/lib/components/ui/sidebar/sidebar-content.component.ts +31 -0
  291. package/src/app/lib/components/ui/sidebar/sidebar-context.ts +33 -0
  292. package/src/app/lib/components/ui/sidebar/sidebar-footer.component.ts +28 -0
  293. package/src/app/lib/components/ui/sidebar/sidebar-group-action.component.ts +33 -0
  294. package/src/app/lib/components/ui/sidebar/sidebar-group-content.component.ts +28 -0
  295. package/src/app/lib/components/ui/sidebar/sidebar-group-label.component.ts +32 -0
  296. package/src/app/lib/components/ui/sidebar/sidebar-group.component.ts +28 -0
  297. package/src/app/lib/components/ui/sidebar/sidebar-header.component.ts +28 -0
  298. package/src/app/lib/components/ui/sidebar/sidebar-input.component.ts +31 -0
  299. package/src/app/lib/components/ui/sidebar/sidebar-inset.component.ts +31 -0
  300. package/src/app/lib/components/ui/sidebar/sidebar-menu-action.component.ts +56 -0
  301. package/src/app/lib/components/ui/sidebar/sidebar-menu-badge.component.ts +42 -0
  302. package/src/app/lib/components/ui/sidebar/sidebar-menu-button.component.ts +64 -0
  303. package/src/app/lib/components/ui/sidebar/sidebar-menu-item.component.ts +32 -0
  304. package/src/app/lib/components/ui/sidebar/sidebar-menu-skeleton.component.ts +39 -0
  305. package/src/app/lib/components/ui/sidebar/sidebar-menu-sub-button.component.ts +59 -0
  306. package/src/app/lib/components/ui/sidebar/sidebar-menu-sub-item.component.ts +25 -0
  307. package/src/app/lib/components/ui/sidebar/sidebar-menu-sub.component.ts +32 -0
  308. package/src/app/lib/components/ui/sidebar/sidebar-menu.component.ts +31 -0
  309. package/src/app/lib/components/ui/sidebar/sidebar-provider.component.ts +141 -0
  310. package/src/app/lib/components/ui/sidebar/sidebar-rail.component.ts +47 -0
  311. package/src/app/lib/components/ui/sidebar/sidebar-route-active.service.ts +124 -0
  312. package/src/app/lib/components/ui/sidebar/sidebar-separator.component.ts +28 -0
  313. package/src/app/lib/components/ui/sidebar/sidebar-trigger.component.ts +57 -0
  314. package/src/app/lib/components/ui/sidebar/sidebar.component.ts +130 -0
  315. package/src/app/lib/components/ui/skeleton/index.ts +1 -0
  316. package/src/app/lib/components/ui/skeleton/skeleton.component.ts +52 -0
  317. package/src/app/lib/components/ui/slider/index.ts +6 -0
  318. package/src/app/lib/components/ui/slider/slider.component.ts +477 -0
  319. package/src/app/lib/components/ui/spinner/index.ts +3 -0
  320. package/src/app/lib/components/ui/spinner/spinner-variants.ts +32 -0
  321. package/src/app/lib/components/ui/spinner/spinner.component.ts +77 -0
  322. package/src/app/lib/components/ui/switch/index.ts +6 -0
  323. package/src/app/lib/components/ui/switch/switch.component.ts +282 -0
  324. package/src/app/lib/components/ui/table/index.ts +9 -0
  325. package/src/app/lib/components/ui/table/table-body.component.ts +28 -0
  326. package/src/app/lib/components/ui/table/table-caption.component.ts +28 -0
  327. package/src/app/lib/components/ui/table/table-cell.component.ts +31 -0
  328. package/src/app/lib/components/ui/table/table-footer.component.ts +28 -0
  329. package/src/app/lib/components/ui/table/table-head.component.ts +36 -0
  330. package/src/app/lib/components/ui/table/table-header.component.ts +28 -0
  331. package/src/app/lib/components/ui/table/table-row.component.ts +34 -0
  332. package/src/app/lib/components/ui/table/table.component.ts +52 -0
  333. package/src/app/lib/components/ui/tabs/index.ts +14 -0
  334. package/src/app/lib/components/ui/tabs/tabs-content.component.ts +132 -0
  335. package/src/app/lib/components/ui/tabs/tabs-context.ts +33 -0
  336. package/src/app/lib/components/ui/tabs/tabs-list.component.ts +228 -0
  337. package/src/app/lib/components/ui/tabs/tabs-trigger.component.ts +167 -0
  338. package/src/app/lib/components/ui/tabs/tabs.component.ts +203 -0
  339. package/src/app/lib/components/ui/textarea/index.ts +1 -0
  340. package/src/app/lib/components/ui/textarea/textarea.component.ts +44 -0
  341. package/src/app/lib/components/ui/toast/index.ts +16 -0
  342. package/src/app/lib/components/ui/toast/toast-action.component.ts +77 -0
  343. package/src/app/lib/components/ui/toast/toast-description.component.ts +52 -0
  344. package/src/app/lib/components/ui/toast/toast-title.component.ts +52 -0
  345. package/src/app/lib/components/ui/toast/toast-variants.ts +24 -0
  346. package/src/app/lib/components/ui/toast/toast.component.ts +177 -0
  347. package/src/app/lib/components/ui/toast/toast.service.ts +202 -0
  348. package/src/app/lib/components/ui/toast/toaster.component.ts +128 -0
  349. package/src/app/lib/components/ui/toggle/index.ts +6 -0
  350. package/src/app/lib/components/ui/toggle/toggle-variants.ts +30 -0
  351. package/src/app/lib/components/ui/toggle/toggle.component.ts +199 -0
  352. package/src/app/lib/components/ui/toggle-group/index.ts +11 -0
  353. package/src/app/lib/components/ui/toggle-group/toggle-group-context.ts +48 -0
  354. package/src/app/lib/components/ui/toggle-group/toggle-group-item.component.ts +241 -0
  355. package/src/app/lib/components/ui/toggle-group/toggle-group.component.ts +288 -0
  356. package/src/app/lib/components/ui/tooltip/index.ts +14 -0
  357. package/src/app/lib/components/ui/tooltip/tooltip-content.component.ts +154 -0
  358. package/src/app/lib/components/ui/tooltip/tooltip-context.ts +29 -0
  359. package/src/app/lib/components/ui/tooltip/tooltip-provider.component.ts +95 -0
  360. package/src/app/lib/components/ui/tooltip/tooltip-trigger.component.ts +138 -0
  361. package/src/app/lib/components/ui/tooltip/tooltip.component.ts +159 -0
  362. package/src/app/lib/components/ui/typography/index.ts +13 -0
  363. package/src/app/lib/components/ui/typography/typography-blockquote.component.ts +31 -0
  364. package/src/app/lib/components/ui/typography/typography-h1.component.ts +32 -0
  365. package/src/app/lib/components/ui/typography/typography-h2.component.ts +32 -0
  366. package/src/app/lib/components/ui/typography/typography-h3.component.ts +29 -0
  367. package/src/app/lib/components/ui/typography/typography-h4.component.ts +29 -0
  368. package/src/app/lib/components/ui/typography/typography-inline-code.component.ts +31 -0
  369. package/src/app/lib/components/ui/typography/typography-large.component.ts +28 -0
  370. package/src/app/lib/components/ui/typography/typography-lead.component.ts +31 -0
  371. package/src/app/lib/components/ui/typography/typography-list.component.ts +31 -0
  372. package/src/app/lib/components/ui/typography/typography-muted.component.ts +28 -0
  373. package/src/app/lib/components/ui/typography/typography-p.component.ts +29 -0
  374. package/src/app/lib/components/ui/typography/typography-small.component.ts +28 -0
  375. package/src/app/lib/index.ts +7 -0
  376. package/src/app/lib/utils/accessibility/aria-id.service.ts +118 -0
  377. package/src/app/lib/utils/accessibility/click-outside.directive.ts +85 -0
  378. package/src/app/lib/utils/accessibility/focus-management.service.ts +231 -0
  379. package/src/app/lib/utils/accessibility/focus-trap.directive.ts +203 -0
  380. package/src/app/lib/utils/accessibility/index.ts +23 -0
  381. package/src/app/lib/utils/accessibility/keyboard-navigation.directive.ts +440 -0
  382. package/src/app/lib/utils/accessibility/live-region.directive.ts +260 -0
  383. package/src/app/lib/utils/accessibility/touch-target.directive.ts +81 -0
  384. package/src/app/lib/utils/accessibility/visually-hidden.component.ts +79 -0
  385. package/src/app/lib/utils/animation/animated.directive.ts +191 -0
  386. package/src/app/lib/utils/animation/animation-tokens.service.ts +88 -0
  387. package/src/app/lib/utils/animation/animation.types.ts +55 -0
  388. package/src/app/lib/utils/animation/animation.utils.ts +158 -0
  389. package/src/app/lib/utils/animation/index.ts +17 -0
  390. package/src/app/lib/utils/animation/presence.component.ts +168 -0
  391. package/src/app/lib/utils/animation/presence.directive.ts +169 -0
  392. package/src/app/lib/utils/cn.ts +15 -0
  393. package/src/app/lib/utils/index.ts +11 -0
  394. package/src/app/lib/utils/positioning/index.ts +218 -0
@@ -0,0 +1,234 @@
1
+ import { cn, Presence } from '@/lib/utils';
2
+ import {
3
+ afterNextRender,
4
+ ChangeDetectionStrategy,
5
+ Component,
6
+ computed,
7
+ effect,
8
+ ElementRef,
9
+ inject,
10
+ input,
11
+ OnDestroy
12
+ } from '@angular/core';
13
+ import { DROPDOWN_MENU_CONTEXT } from './dropdown-menu-context';
14
+
15
+ /**
16
+ * DropdownMenuContent component - the content panel of the dropdown.
17
+ * Matches shadcn/ui React DropdownMenuContent exactly.
18
+ * Includes keyboard navigation with arrow keys, Home/End, and typeahead.
19
+ * Uses Presence component for proper exit animations.
20
+ */
21
+ @Component({
22
+ selector: 'DropdownMenuContent',
23
+ imports: [Presence],
24
+ template: `
25
+ <Presence [present]="context.open()">
26
+ <div
27
+ [class]="computedClass()"
28
+ [attr.id]="context.contentId"
29
+ [attr.aria-labelledby]="null"
30
+ [attr.data-state]="context.open() ? 'open' : 'closed'"
31
+ [attr.data-side]="side()"
32
+ [attr.data-align]="align()"
33
+ role="menu"
34
+ aria-orientation="vertical"
35
+ tabindex="-1"
36
+ (keydown)="onKeydown($event)"
37
+ >
38
+ <ng-content />
39
+ </div>
40
+ </Presence>
41
+ `,
42
+ host: {
43
+ class: 'contents',
44
+ '(document:click)': 'onDocumentClick($event)',
45
+ '(document:keydown.escape)': 'onEscapeKey()',
46
+ },
47
+ changeDetection: ChangeDetectionStrategy.OnPush,
48
+ })
49
+ export class DropdownMenuContent implements OnDestroy {
50
+ protected readonly context = inject(DROPDOWN_MENU_CONTEXT);
51
+ private readonly elementRef = inject(ElementRef);
52
+
53
+ /** Side of the trigger to place content */
54
+ readonly side = input<'top' | 'right' | 'bottom' | 'left'>('bottom');
55
+
56
+ /** Alignment of the content */
57
+ readonly align = input<'start' | 'center' | 'end'>('start');
58
+
59
+ /** Side offset */
60
+ readonly sideOffset = input<number>(4);
61
+
62
+ /** Additional CSS classes */
63
+ readonly class = input<string>('');
64
+
65
+ private menuItems: HTMLElement[] = [];
66
+ private typeaheadBuffer = '';
67
+ private typeaheadTimeout: ReturnType<typeof setTimeout> | null = null;
68
+
69
+ protected readonly computedClass = computed(() => {
70
+ const sideClasses = {
71
+ top: 'bottom-full mb-1',
72
+ bottom: 'top-full mt-1',
73
+ left: 'right-full mr-1',
74
+ right: 'left-full ml-1',
75
+ };
76
+
77
+ const alignClasses = {
78
+ start: 'left-0',
79
+ center: 'left-1/2 -translate-x-1/2',
80
+ end: 'right-0',
81
+ };
82
+
83
+ return cn(
84
+ 'absolute z-50 min-w-[12rem] overflow-hidden rounded-xl border bg-popover p-2 text-popover-foreground shadow-lg',
85
+ 'data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
86
+ sideClasses[this.side()],
87
+ alignClasses[this.align()],
88
+ this.class()
89
+ );
90
+ });
91
+
92
+ constructor() {
93
+ // Focus first item when menu opens
94
+ effect(() => {
95
+ if (this.context.open()) {
96
+ setTimeout(() => {
97
+ this.updateMenuItems();
98
+ const focusedIdx = this.context.focusedIndex();
99
+ if (focusedIdx >= 0 && this.menuItems[focusedIdx]) {
100
+ this.menuItems[focusedIdx].focus();
101
+ } else if (this.menuItems.length > 0) {
102
+ this.menuItems[0].focus();
103
+ this.context.focusedIndex.set(0);
104
+ }
105
+ }, 0);
106
+ }
107
+ });
108
+
109
+ // Initial menu items update (browser-only)
110
+ afterNextRender(() => {
111
+ this.updateMenuItems();
112
+ });
113
+ }
114
+
115
+ ngOnDestroy(): void {
116
+ if (this.typeaheadTimeout) {
117
+ clearTimeout(this.typeaheadTimeout);
118
+ }
119
+ }
120
+
121
+ private updateMenuItems(): void {
122
+ const content = this.elementRef.nativeElement.querySelector('[role="menu"]');
123
+ if (content) {
124
+ this.menuItems = Array.from(
125
+ content.querySelectorAll('[role="menuitem"]:not([aria-disabled="true"]):not([data-disabled])')
126
+ );
127
+ }
128
+ }
129
+
130
+ onKeydown(event: KeyboardEvent): void {
131
+ this.updateMenuItems();
132
+
133
+ switch (event.key) {
134
+ case 'ArrowDown':
135
+ event.preventDefault();
136
+ this.focusNext();
137
+ break;
138
+ case 'ArrowUp':
139
+ event.preventDefault();
140
+ this.focusPrevious();
141
+ break;
142
+ case 'Home':
143
+ event.preventDefault();
144
+ this.focusFirst();
145
+ break;
146
+ case 'End':
147
+ event.preventDefault();
148
+ this.focusLast();
149
+ break;
150
+ case 'Tab':
151
+ // Close menu and let tab continue naturally
152
+ this.close();
153
+ break;
154
+ default:
155
+ // Typeahead search
156
+ if (event.key.length === 1 && !event.ctrlKey && !event.metaKey) {
157
+ this.handleTypeahead(event.key);
158
+ }
159
+ break;
160
+ }
161
+ }
162
+
163
+ private focusNext(): void {
164
+ const currentIndex = this.context.focusedIndex();
165
+ const nextIndex = currentIndex < this.menuItems.length - 1 ? currentIndex + 1 : 0;
166
+ this.focusItem(nextIndex);
167
+ }
168
+
169
+ private focusPrevious(): void {
170
+ const currentIndex = this.context.focusedIndex();
171
+ const prevIndex = currentIndex > 0 ? currentIndex - 1 : this.menuItems.length - 1;
172
+ this.focusItem(prevIndex);
173
+ }
174
+
175
+ private focusFirst(): void {
176
+ this.focusItem(0);
177
+ }
178
+
179
+ private focusLast(): void {
180
+ this.focusItem(this.menuItems.length - 1);
181
+ }
182
+
183
+ private focusItem(index: number): void {
184
+ if (index >= 0 && index < this.menuItems.length) {
185
+ this.menuItems[index].focus();
186
+ this.context.focusedIndex.set(index);
187
+ }
188
+ }
189
+
190
+ private handleTypeahead(key: string): void {
191
+ this.typeaheadBuffer += key.toLowerCase();
192
+
193
+ if (this.typeaheadTimeout) {
194
+ clearTimeout(this.typeaheadTimeout);
195
+ }
196
+
197
+ this.typeaheadTimeout = setTimeout(() => {
198
+ this.typeaheadBuffer = '';
199
+ }, 500);
200
+
201
+ // Find first matching item
202
+ const matchIndex = this.menuItems.findIndex((item) =>
203
+ item.textContent?.toLowerCase().trim().startsWith(this.typeaheadBuffer)
204
+ );
205
+
206
+ if (matchIndex >= 0) {
207
+ this.focusItem(matchIndex);
208
+ }
209
+ }
210
+
211
+ protected onDocumentClick(event: MouseEvent): void {
212
+ const target = event.target as HTMLElement;
213
+ const hostElement = this.elementRef.nativeElement;
214
+ const parent = hostElement.closest('DropdownMenu');
215
+
216
+ if (parent && !parent.contains(target)) {
217
+ this.close();
218
+ }
219
+ }
220
+
221
+ protected onEscapeKey(): void {
222
+ this.close();
223
+ }
224
+
225
+ private close(): void {
226
+ this.context.open.set(false);
227
+ this.context.focusedIndex.set(-1);
228
+ // Restore focus to trigger
229
+ const triggerEl = this.context.triggerElement();
230
+ if (triggerEl) {
231
+ setTimeout(() => triggerEl.focus(), 0);
232
+ }
233
+ }
234
+ }
@@ -0,0 +1,15 @@
1
+ import { InjectionToken, type WritableSignal } from '@angular/core';
2
+
3
+ export interface DropdownMenuContextValue {
4
+ open: WritableSignal<boolean>;
5
+ /** ID for the menu content for ARIA */
6
+ contentId: string;
7
+ /** Reference to trigger element for focus restoration */
8
+ triggerElement: WritableSignal<HTMLElement | null>;
9
+ /** Currently focused item index for keyboard navigation */
10
+ focusedIndex: WritableSignal<number>;
11
+ }
12
+
13
+ export const DROPDOWN_MENU_CONTEXT = new InjectionToken<DropdownMenuContextValue>(
14
+ 'DROPDOWN_MENU_CONTEXT'
15
+ );
@@ -0,0 +1,15 @@
1
+ import { ChangeDetectionStrategy, Component } from '@angular/core';
2
+
3
+ /**
4
+ * DropdownMenuGroup component - groups related menu items.
5
+ * Matches shadcn/ui React DropdownMenuGroup exactly.
6
+ */
7
+ @Component({
8
+ selector: 'DropdownMenuGroup',
9
+ template: `<ng-content />`,
10
+ host: {
11
+ '[attr.role]': '"group"',
12
+ },
13
+ changeDetection: ChangeDetectionStrategy.OnPush,
14
+ })
15
+ export class DropdownMenuGroup {}
@@ -0,0 +1,56 @@
1
+ import { cn } from '@/lib/utils';
2
+ import { ChangeDetectionStrategy, Component, computed, inject, input, output } from '@angular/core';
3
+ import { DROPDOWN_MENU_CONTEXT } from './dropdown-menu-context';
4
+
5
+ /**
6
+ * DropdownMenuItem component - a single item in the dropdown menu.
7
+ * Matches shadcn/ui React DropdownMenuItem exactly.
8
+ */
9
+ @Component({
10
+ selector: 'DropdownMenuItem',
11
+ template: `<ng-content />`,
12
+ host: {
13
+ '[class]': 'computedClass()',
14
+ '[attr.role]': '"menuitem"',
15
+ '[attr.tabindex]': 'disabled() ? -1 : 0',
16
+ '[attr.aria-disabled]': 'disabled()',
17
+ '[attr.data-disabled]': 'disabled() ? "" : null',
18
+ '(click)': 'handleClick($event)',
19
+ '(keydown.enter)': 'handleClick($event)',
20
+ '(keydown.space)': 'handleClick($event)',
21
+ },
22
+ changeDetection: ChangeDetectionStrategy.OnPush,
23
+ })
24
+ export class DropdownMenuItem {
25
+ private readonly context = inject(DROPDOWN_MENU_CONTEXT);
26
+
27
+ /** Whether the item is disabled */
28
+ readonly disabled = input<boolean>(false);
29
+
30
+ /** Whether the item is inset (extra padding) */
31
+ readonly inset = input<boolean>(false);
32
+
33
+ /** Additional CSS classes */
34
+ readonly class = input<string>('');
35
+
36
+ /** Select event emitted when item is clicked */
37
+ readonly onSelect = output<void>();
38
+
39
+ protected readonly computedClass = computed(() =>
40
+ cn(
41
+ "relative flex cursor-default select-none items-center gap-3 rounded-md px-3 py-2.5 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&>svg]:size-4 [&>svg]:shrink-0 [&>lucide-icon]:size-4 [&>lucide-icon]:shrink-0 [&>lucide-icon]:text-muted-foreground",
42
+ this.inset() && 'pl-8',
43
+ !this.disabled() && 'cursor-pointer hover:bg-accent hover:text-accent-foreground',
44
+ this.class()
45
+ )
46
+ );
47
+
48
+ protected handleClick(event: Event): void {
49
+ if (this.disabled()) {
50
+ event.preventDefault();
51
+ return;
52
+ }
53
+ this.onSelect.emit();
54
+ this.context.open.set(false);
55
+ }
56
+ }
@@ -0,0 +1,30 @@
1
+ import { cn } from '@/lib/utils';
2
+ import { ChangeDetectionStrategy, Component, computed, input } from '@angular/core';
3
+
4
+ /**
5
+ * DropdownMenuLabel component - a label in the dropdown menu.
6
+ * Matches shadcn/ui React DropdownMenuLabel exactly.
7
+ */
8
+ @Component({
9
+ selector: 'DropdownMenuLabel',
10
+ template: `<ng-content />`,
11
+ host: {
12
+ '[class]': 'computedClass()',
13
+ },
14
+ changeDetection: ChangeDetectionStrategy.OnPush,
15
+ })
16
+ export class DropdownMenuLabel {
17
+ /** Whether the label is inset (extra padding) */
18
+ readonly inset = input<boolean>(false);
19
+
20
+ /** Additional CSS classes */
21
+ readonly class = input<string>('');
22
+
23
+ protected readonly computedClass = computed(() =>
24
+ cn(
25
+ 'px-3 py-2 text-sm font-semibold',
26
+ this.inset() && 'pl-8',
27
+ this.class()
28
+ )
29
+ );
30
+ }
@@ -0,0 +1,42 @@
1
+ import { ChangeDetectionStrategy, Component, InjectionToken, model, output, signal, type WritableSignal } from '@angular/core';
2
+
3
+ export interface DropdownMenuRadioGroupContext {
4
+ value: WritableSignal<string>;
5
+ setValue: (value: string) => void;
6
+ }
7
+
8
+ export const DROPDOWN_MENU_RADIO_GROUP_CONTEXT = new InjectionToken<DropdownMenuRadioGroupContext>(
9
+ 'DROPDOWN_MENU_RADIO_GROUP_CONTEXT'
10
+ );
11
+
12
+ /**
13
+ * DropdownMenuRadioGroup component - a group of radio items in the dropdown.
14
+ * Matches shadcn/ui React DropdownMenuRadioGroup exactly.
15
+ */
16
+ @Component({
17
+ selector: 'DropdownMenuRadioGroup',
18
+ template: `<ng-content />`,
19
+ providers: [
20
+ {
21
+ provide: DROPDOWN_MENU_RADIO_GROUP_CONTEXT,
22
+ useFactory: () => {
23
+ const internalValue = signal('');
24
+ return {
25
+ value: internalValue,
26
+ setValue: (newValue: string) => internalValue.set(newValue),
27
+ };
28
+ },
29
+ },
30
+ ],
31
+ host: {
32
+ '[attr.role]': '"group"',
33
+ },
34
+ changeDetection: ChangeDetectionStrategy.OnPush,
35
+ })
36
+ export class DropdownMenuRadioGroup {
37
+ /** The current value */
38
+ readonly value = model<string>('');
39
+
40
+ /** Value change event */
41
+ readonly onValueChange = output<string>();
42
+ }
@@ -0,0 +1,71 @@
1
+ import { cn } from '@/lib/utils';
2
+ import { ChangeDetectionStrategy, Component, computed, inject, input, output } from '@angular/core';
3
+ import { Circle, LucideAngularModule } from 'lucide-angular';
4
+ import { DROPDOWN_MENU_CONTEXT } from './dropdown-menu-context';
5
+ import { DROPDOWN_MENU_RADIO_GROUP_CONTEXT } from './dropdown-menu-radio-group.component';
6
+
7
+ /**
8
+ * DropdownMenuRadioItem component - a radio item in the dropdown.
9
+ * Matches shadcn/ui React DropdownMenuRadioItem exactly.
10
+ */
11
+ @Component({
12
+ selector: 'DropdownMenuRadioItem',
13
+ imports: [LucideAngularModule],
14
+ template: `
15
+ <span class="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
16
+ @if (isSelected()) {
17
+ <lucide-icon [img]="CircleIcon" class="h-2 w-2 fill-current" />
18
+ }
19
+ </span>
20
+ <ng-content />
21
+ `,
22
+ host: {
23
+ '[class]': 'computedClass()',
24
+ '[attr.role]': '"menuitemradio"',
25
+ '[attr.aria-checked]': 'isSelected()',
26
+ '[attr.tabindex]': 'disabled() ? -1 : 0',
27
+ '[attr.aria-disabled]': 'disabled()',
28
+ '[attr.data-disabled]': 'disabled() ? "" : null',
29
+ '[attr.data-state]': 'isSelected() ? "checked" : "unchecked"',
30
+ '(click)': 'handleClick($event)',
31
+ '(keydown.enter)': 'handleClick($event)',
32
+ '(keydown.space)': 'handleClick($event)',
33
+ },
34
+ changeDetection: ChangeDetectionStrategy.OnPush,
35
+ })
36
+ export class DropdownMenuRadioItem {
37
+ private readonly context = inject(DROPDOWN_MENU_CONTEXT);
38
+ private readonly radioGroupContext = inject(DROPDOWN_MENU_RADIO_GROUP_CONTEXT);
39
+ protected readonly CircleIcon = Circle;
40
+
41
+ /** The value of this radio item */
42
+ readonly value = input.required<string>();
43
+
44
+ /** Whether the item is disabled */
45
+ readonly disabled = input<boolean>(false);
46
+
47
+ /** Additional CSS classes */
48
+ readonly class = input<string>('');
49
+
50
+ /** Select event emitted when item is clicked */
51
+ readonly onSelect = output<void>();
52
+
53
+ protected readonly isSelected = computed(() => this.radioGroupContext.value() === this.value());
54
+
55
+ protected readonly computedClass = computed(() =>
56
+ cn(
57
+ "relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
58
+ !this.disabled() && 'cursor-pointer hover:bg-accent hover:text-accent-foreground',
59
+ this.class()
60
+ )
61
+ );
62
+
63
+ protected handleClick(event: Event): void {
64
+ if (this.disabled()) {
65
+ event.preventDefault();
66
+ return;
67
+ }
68
+ this.radioGroupContext.setValue(this.value());
69
+ this.onSelect.emit();
70
+ }
71
+ }
@@ -0,0 +1,24 @@
1
+ import { cn } from '@/lib/utils';
2
+ import { ChangeDetectionStrategy, Component, computed, input } from '@angular/core';
3
+
4
+ /**
5
+ * DropdownMenuSeparator component - a separator line in the dropdown.
6
+ * Matches shadcn/ui React DropdownMenuSeparator exactly.
7
+ */
8
+ @Component({
9
+ selector: 'DropdownMenuSeparator',
10
+ template: ``,
11
+ host: {
12
+ '[class]': 'computedClass()',
13
+ '[attr.role]': '"separator"',
14
+ },
15
+ changeDetection: ChangeDetectionStrategy.OnPush,
16
+ })
17
+ export class DropdownMenuSeparator {
18
+ /** Additional CSS classes */
19
+ readonly class = input<string>('');
20
+
21
+ protected readonly computedClass = computed(() =>
22
+ cn('-mx-2 my-2 h-px bg-border', this.class())
23
+ );
24
+ }
@@ -0,0 +1,23 @@
1
+ import { cn } from '@/lib/utils';
2
+ import { ChangeDetectionStrategy, Component, computed, input } from '@angular/core';
3
+
4
+ /**
5
+ * DropdownMenuShortcut component - displays keyboard shortcut hint.
6
+ * Matches shadcn/ui React DropdownMenuShortcut exactly.
7
+ */
8
+ @Component({
9
+ selector: 'DropdownMenuShortcut',
10
+ template: `<ng-content />`,
11
+ host: {
12
+ '[class]': 'computedClass()',
13
+ },
14
+ changeDetection: ChangeDetectionStrategy.OnPush,
15
+ })
16
+ export class DropdownMenuShortcut {
17
+ /** Additional CSS classes */
18
+ readonly class = input<string>('');
19
+
20
+ protected readonly computedClass = computed(() =>
21
+ cn('ml-auto text-xs tracking-widest opacity-60', this.class())
22
+ );
23
+ }
@@ -0,0 +1,51 @@
1
+ import { cn, Presence } from '@/lib/utils';
2
+ import { ChangeDetectionStrategy, Component, computed, inject, input } from '@angular/core';
3
+ import { DROPDOWN_MENU_SUB_CONTEXT } from './dropdown-menu-sub.component';
4
+
5
+ /**
6
+ * DropdownMenuSubContent component - content panel for submenu.
7
+ * Matches shadcn/ui React DropdownMenuSubContent exactly.
8
+ */
9
+ @Component({
10
+ selector: 'DropdownMenuSubContent',
11
+ imports: [Presence],
12
+ template: `
13
+ <Presence [present]="subContext.open()">
14
+ <div
15
+ [class]="computedClass()"
16
+ [attr.data-state]="subContext.open() ? 'open' : 'closed'"
17
+ role="menu"
18
+ >
19
+ <ng-content />
20
+ </div>
21
+ </Presence>
22
+ `,
23
+ host: {
24
+ class: 'contents',
25
+ '(mouseenter)': 'onMouseEnter()',
26
+ '(mouseleave)': 'onMouseLeave()',
27
+ },
28
+ changeDetection: ChangeDetectionStrategy.OnPush,
29
+ })
30
+ export class DropdownMenuSubContent {
31
+ protected readonly subContext = inject(DROPDOWN_MENU_SUB_CONTEXT);
32
+
33
+ /** Additional CSS classes */
34
+ readonly class = input<string>('');
35
+
36
+ protected readonly computedClass = computed(() =>
37
+ cn(
38
+ 'absolute left-full top-0 z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg',
39
+ 'data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
40
+ this.class()
41
+ )
42
+ );
43
+
44
+ protected onMouseEnter(): void {
45
+ this.subContext.open.set(true);
46
+ }
47
+
48
+ protected onMouseLeave(): void {
49
+ this.subContext.open.set(false);
50
+ }
51
+ }
@@ -0,0 +1,53 @@
1
+ import { cn } from '@/lib/utils';
2
+ import { ChangeDetectionStrategy, Component, computed, inject, input } from '@angular/core';
3
+ import { ChevronRight, LucideAngularModule } from 'lucide-angular';
4
+ import { DROPDOWN_MENU_SUB_CONTEXT } from './dropdown-menu-sub.component';
5
+
6
+ /**
7
+ * DropdownMenuSubTrigger component - trigger for submenu.
8
+ * Matches shadcn/ui React DropdownMenuSubTrigger exactly.
9
+ */
10
+ @Component({
11
+ selector: 'DropdownMenuSubTrigger',
12
+ imports: [LucideAngularModule],
13
+ template: `
14
+ <ng-content />
15
+ <lucide-icon [img]="ChevronRightIcon" class="ml-auto h-4 w-4" />
16
+ `,
17
+ host: {
18
+ '[class]': 'computedClass()',
19
+ '(mouseenter)': 'onMouseEnter()',
20
+ '(mouseleave)': 'onMouseLeave()',
21
+ '[attr.data-state]': 'subContext.open() ? "open" : "closed"',
22
+ },
23
+ changeDetection: ChangeDetectionStrategy.OnPush,
24
+ })
25
+ export class DropdownMenuSubTrigger {
26
+ protected readonly subContext = inject(DROPDOWN_MENU_SUB_CONTEXT);
27
+ protected readonly ChevronRightIcon = ChevronRight;
28
+
29
+ /** Whether the trigger is inset (extra padding) */
30
+ readonly inset = input<boolean>(false);
31
+
32
+ /** Additional CSS classes */
33
+ readonly class = input<string>('');
34
+
35
+ protected readonly computedClass = computed(() =>
36
+ cn(
37
+ 'flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent data-[state=open]:bg-accent [&>svg]:size-4 [&>svg]:shrink-0',
38
+ this.inset() && 'pl-8',
39
+ this.class()
40
+ )
41
+ );
42
+
43
+ protected onMouseEnter(): void {
44
+ this.subContext.open.set(true);
45
+ }
46
+
47
+ protected onMouseLeave(): void {
48
+ // Delay closing to allow mouse to move to sub-content
49
+ setTimeout(() => {
50
+ // Check if mouse is still outside both trigger and content
51
+ }, 100);
52
+ }
53
+ }
@@ -0,0 +1,31 @@
1
+ import { ChangeDetectionStrategy, Component, InjectionToken, signal, type WritableSignal } from '@angular/core';
2
+
3
+ export interface DropdownMenuSubContext {
4
+ open: WritableSignal<boolean>;
5
+ }
6
+
7
+ export const DROPDOWN_MENU_SUB_CONTEXT = new InjectionToken<DropdownMenuSubContext>(
8
+ 'DROPDOWN_MENU_SUB_CONTEXT'
9
+ );
10
+
11
+ /**
12
+ * DropdownMenuSub component - container for submenu.
13
+ * Matches shadcn/ui React DropdownMenuSub exactly.
14
+ */
15
+ @Component({
16
+ selector: 'DropdownMenuSub',
17
+ template: `<ng-content />`,
18
+ providers: [
19
+ {
20
+ provide: DROPDOWN_MENU_SUB_CONTEXT,
21
+ useFactory: (): DropdownMenuSubContext => ({
22
+ open: signal(false),
23
+ }),
24
+ },
25
+ ],
26
+ host: {
27
+ class: 'relative',
28
+ },
29
+ changeDetection: ChangeDetectionStrategy.OnPush,
30
+ })
31
+ export class DropdownMenuSub {}