@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,275 @@
1
+ import { cn } from '@/lib/utils';
2
+ import {
3
+ ChangeDetectionStrategy,
4
+ Component,
5
+ computed,
6
+ ElementRef,
7
+ forwardRef,
8
+ inject,
9
+ input,
10
+ model,
11
+ output,
12
+ signal,
13
+ } from '@angular/core';
14
+ import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
15
+ import {
16
+ RADIO_GROUP_CONTEXT,
17
+ type RadioGroupContext,
18
+ type RadioGroupOrientation,
19
+ } from './radio-group-context';
20
+
21
+ // ============================================================================
22
+ // Types
23
+ // ============================================================================
24
+
25
+ export type RadioGroupProps = {
26
+ /** Current selected value */
27
+ value?: string;
28
+ /** Default value for uncontrolled mode */
29
+ defaultValue?: string;
30
+ /** Whether the group is disabled */
31
+ disabled?: boolean;
32
+ /** Whether the group is required */
33
+ required?: boolean;
34
+ /** The name for radio inputs */
35
+ name?: string;
36
+ /** Orientation for keyboard navigation */
37
+ orientation?: RadioGroupOrientation;
38
+ /** Whether to loop focus at boundaries */
39
+ loop?: boolean;
40
+ /** Additional CSS classes */
41
+ class?: string;
42
+ };
43
+
44
+ // ============================================================================
45
+ // RadioGroup Component
46
+ // ============================================================================
47
+
48
+ /**
49
+ * RadioGroup component for single selection from multiple options.
50
+ * Based on Radix UI RadioGroup primitive with shadcn/ui styling.
51
+ * Implements roving tabindex and arrow key navigation per WAI-ARIA radiogroup pattern.
52
+ *
53
+ * ## Features
54
+ * - Single selection from multiple radio items
55
+ * - Full keyboard navigation with arrow keys
56
+ * - Roving tabindex for efficient keyboard navigation
57
+ * - Angular Forms integration (ngModel, formControl)
58
+ * - Horizontal or vertical orientation
59
+ *
60
+ * ## Accessibility
61
+ * - Uses `role="radiogroup"` for grouping semantics
62
+ * - `aria-orientation` indicates layout direction
63
+ * - `aria-required` when required
64
+ * - Roving tabindex: only selected (or first) item is in tab order
65
+ * - Arrow keys navigate between items and select
66
+ *
67
+ * ## Keyboard Navigation
68
+ * - **ArrowRight/ArrowDown**: Focus and select next item
69
+ * - **ArrowLeft/ArrowUp**: Focus and select previous item
70
+ * - **Space**: Select current focused item (if not already selected)
71
+ *
72
+ * @example
73
+ * <RadioGroup [(value)]="selectedValue">
74
+ * <div class="flex items-center space-x-2">
75
+ * <RadioGroupItem value="option1" id="option1" />
76
+ * <Label for="option1">Option 1</Label>
77
+ * </div>
78
+ * <div class="flex items-center space-x-2">
79
+ * <RadioGroupItem value="option2" id="option2" />
80
+ * <Label for="option2">Option 2</Label>
81
+ * </div>
82
+ * </RadioGroup>
83
+ *
84
+ * @example
85
+ * <!-- With reactive forms -->
86
+ * <RadioGroup formControlName="preference">
87
+ * <RadioGroupItem value="a" id="pref-a" />
88
+ * <Label for="pref-a">Option A</Label>
89
+ * <RadioGroupItem value="b" id="pref-b" />
90
+ * <Label for="pref-b">Option B</Label>
91
+ * </RadioGroup>
92
+ *
93
+ * @example
94
+ * <!-- Horizontal orientation -->
95
+ * <RadioGroup orientation="horizontal" [(value)]="size">
96
+ * <div class="flex gap-4">
97
+ * <RadioGroupItem value="sm" />
98
+ * <RadioGroupItem value="md" />
99
+ * <RadioGroupItem value="lg" />
100
+ * </div>
101
+ * </RadioGroup>
102
+ *
103
+ * @see {@link https://www.radix-ui.com/primitives/docs/components/radio-group Radix RadioGroup}
104
+ * @see {@link https://ui.shadcn.com/docs/components/radio-group shadcn/ui RadioGroup}
105
+ */
106
+ @Component({
107
+ selector: 'RadioGroup',
108
+ template: `<ng-content />`,
109
+ host: {
110
+ '[class]': 'computedClass()',
111
+ role: 'radiogroup',
112
+ '[attr.aria-orientation]': 'orientation()',
113
+ '[attr.aria-required]': 'required() || null',
114
+ '[attr.data-disabled]': 'isDisabled() ? "" : null',
115
+ 'data-slot': 'radio-group',
116
+ },
117
+ providers: [
118
+ {
119
+ provide: RADIO_GROUP_CONTEXT,
120
+ useFactory: (component: RadioGroup) => component.context,
121
+ deps: [forwardRef(() => RadioGroup)],
122
+ },
123
+ {
124
+ provide: NG_VALUE_ACCESSOR,
125
+ useExisting: forwardRef(() => RadioGroup),
126
+ multi: true,
127
+ },
128
+ ],
129
+ changeDetection: ChangeDetectionStrategy.OnPush,
130
+ })
131
+ export class RadioGroup implements ControlValueAccessor {
132
+ private readonly elementRef = inject(ElementRef<HTMLElement>);
133
+
134
+ /** The current selected value */
135
+ readonly value = model<string>('');
136
+
137
+ /** Default value for uncontrolled mode */
138
+ readonly defaultValue = input<string>('');
139
+
140
+ /** Whether the radio group is disabled via input */
141
+ readonly disabled = input<boolean>(false);
142
+
143
+ /** Whether the radio group is required */
144
+ readonly required = input<boolean>(false);
145
+
146
+ /** The orientation of the radio group */
147
+ readonly orientation = input<RadioGroupOrientation>('vertical');
148
+
149
+ /** Whether to loop focus at boundaries */
150
+ readonly loop = input<boolean>(true);
151
+
152
+ /** The name attribute for the radio inputs */
153
+ readonly name = input<string>(
154
+ `radio-group-${Math.random().toString(36).substring(7)}`
155
+ );
156
+
157
+ /** Additional CSS classes to apply */
158
+ readonly class = input<string>('');
159
+
160
+ /** Emitted when value changes */
161
+ readonly valueChange = output<string>();
162
+
163
+ /** Whether disabled via forms */
164
+ private readonly formsDisabled = signal<boolean>(false);
165
+
166
+ /** Whether the group is disabled */
167
+ readonly isDisabled = computed(
168
+ () => this.disabled() || this.formsDisabled()
169
+ );
170
+
171
+ /** ControlValueAccessor callbacks */
172
+ private onChange: (value: string) => void = () => {};
173
+ private onTouched: () => void = () => {};
174
+
175
+ /** Context for child RadioGroupItem components */
176
+ readonly context: RadioGroupContext = {
177
+ value: signal(this.value()),
178
+ disabled: signal(this.disabled()),
179
+ name: signal(this.name()),
180
+ orientation: signal(this.orientation()),
181
+ loop: signal(this.loop()),
182
+ required: signal(this.required()),
183
+ itemValues: signal<string[]>([]),
184
+ setValue: (value: string) => {
185
+ if (!this.isDisabled()) {
186
+ this.value.set(value);
187
+ this.context.value.set(value);
188
+ this.onChange(value);
189
+ this.onTouched();
190
+ this.valueChange.emit(value);
191
+ }
192
+ },
193
+ focusNext: (currentValue: string) => this.focusItem(currentValue, 1),
194
+ focusPrevious: (currentValue: string) => this.focusItem(currentValue, -1),
195
+ focusFirst: () => this.focusItemByIndex(0),
196
+ focusLast: () =>
197
+ this.focusItemByIndex(this.context.itemValues().length - 1),
198
+ };
199
+
200
+ /** Computed class combining base styles and custom classes */
201
+ protected readonly computedClass = computed(() =>
202
+ cn(
203
+ 'grid gap-3',
204
+ this.orientation() === 'horizontal' && 'flex flex-row',
205
+ this.class()
206
+ )
207
+ );
208
+
209
+ ngOnChanges(): void {
210
+ this.context.value.set(this.value());
211
+ this.context.disabled.set(this.disabled());
212
+ this.context.name.set(this.name());
213
+ this.context.orientation.set(this.orientation());
214
+ this.context.loop.set(this.loop());
215
+ this.context.required.set(this.required());
216
+ }
217
+
218
+ // ControlValueAccessor implementation
219
+ writeValue(value: string): void {
220
+ const val = value ?? this.defaultValue();
221
+ this.value.set(val);
222
+ this.context.value.set(val);
223
+ }
224
+
225
+ registerOnChange(fn: (value: string) => void): void {
226
+ this.onChange = fn;
227
+ }
228
+
229
+ registerOnTouched(fn: () => void): void {
230
+ this.onTouched = fn;
231
+ }
232
+
233
+ setDisabledState(isDisabled: boolean): void {
234
+ this.formsDisabled.set(isDisabled);
235
+ this.context.disabled.set(this.isDisabled());
236
+ }
237
+
238
+ /** Focus a radio item relative to the current item */
239
+ private focusItem(currentValue: string, direction: number): void {
240
+ const values = this.context.itemValues();
241
+ const currentIndex = values.indexOf(currentValue);
242
+ if (currentIndex === -1) return;
243
+
244
+ const shouldLoop = this.loop();
245
+ let nextIndex = currentIndex + direction;
246
+
247
+ if (shouldLoop) {
248
+ // Wrap around
249
+ if (nextIndex < 0) nextIndex = values.length - 1;
250
+ if (nextIndex >= values.length) nextIndex = 0;
251
+ } else {
252
+ // Clamp to boundaries
253
+ if (nextIndex < 0 || nextIndex >= values.length) return;
254
+ }
255
+
256
+ this.focusItemByIndex(nextIndex);
257
+ }
258
+
259
+ /** Focus a radio item by index and select it */
260
+ private focusItemByIndex(index: number): void {
261
+ const values = this.context.itemValues();
262
+ if (index < 0 || index >= values.length) return;
263
+
264
+ const value = values[index];
265
+ const item = this.elementRef.nativeElement.querySelector(
266
+ `[data-slot="radio-group-item"][data-value="${value}"]`
267
+ ) as HTMLElement;
268
+
269
+ if (item) {
270
+ item.focus();
271
+ // Also select the item on focus (per ARIA spec for radio groups)
272
+ this.context.setValue(value);
273
+ }
274
+ }
275
+ }
@@ -0,0 +1,5 @@
1
+ export { RESIZABLE_CONTEXT, type ResizableContextValue } from './resizable-context';
2
+ export { ResizableHandle } from './resizable-handle.component';
3
+ export { ResizablePanelGroup } from './resizable-panel-group.component';
4
+ export { ResizablePanel } from './resizable-panel.component';
5
+
@@ -0,0 +1,14 @@
1
+ import { InjectionToken, InputSignal, WritableSignal } from '@angular/core';
2
+
3
+ export interface ResizableContextValue {
4
+ direction: InputSignal<'horizontal' | 'vertical'>;
5
+ registerPanel: (id: string, minSize?: number, maxSize?: number, defaultSize?: number) => void;
6
+ getPanelSize: (id: string) => number;
7
+ setPanelSize: (id: string, size: number) => void;
8
+ startResize: (handleId: string) => void;
9
+ onResize: (delta: number) => void;
10
+ endResize: () => void;
11
+ panelSizes: WritableSignal<Map<string, number>>;
12
+ }
13
+
14
+ export const RESIZABLE_CONTEXT = new InjectionToken<ResizableContextValue>('RESIZABLE_CONTEXT');
@@ -0,0 +1,232 @@
1
+ import { cn } from '@/lib/utils';
2
+ import {
3
+ ChangeDetectionStrategy,
4
+ Component,
5
+ computed,
6
+ inject,
7
+ input,
8
+ signal,
9
+ } from '@angular/core';
10
+ import { RESIZABLE_CONTEXT } from './resizable-context';
11
+
12
+ let handleIdCounter = 0;
13
+
14
+ /**
15
+ * ResizableHandle component - the draggable divider between panels.
16
+ * Matches shadcn/ui React ResizableHandle exactly.
17
+ *
18
+ * ACCESSIBILITY: Fully keyboard accessible with arrow keys.
19
+ * - Arrow keys resize in the direction of the handle
20
+ * - Shift+Arrow keys for larger resize steps
21
+ * - Home/End to set minimum/maximum sizes
22
+ *
23
+ * @example
24
+ * <ResizableHandle />
25
+ * <ResizableHandle withHandle />
26
+ */
27
+ @Component({
28
+ selector: 'ResizableHandle',
29
+ template: `
30
+ @if (withHandle()) {
31
+ <div class="z-10 flex h-4 w-3 items-center justify-center rounded-sm border bg-border">
32
+ <svg
33
+ xmlns="http://www.w3.org/2000/svg"
34
+ width="24"
35
+ height="24"
36
+ viewBox="0 0 24 24"
37
+ fill="none"
38
+ stroke="currentColor"
39
+ stroke-width="2"
40
+ stroke-linecap="round"
41
+ stroke-linejoin="round"
42
+ class="h-2.5 w-2.5"
43
+ aria-hidden="true"
44
+ >
45
+ <circle cx="12" cy="12" r="1" />
46
+ <circle cx="12" cy="5" r="1" />
47
+ <circle cx="12" cy="19" r="1" />
48
+ </svg>
49
+ </div>
50
+ }
51
+ `,
52
+ host: {
53
+ '[class]': 'computedClass()',
54
+ '[attr.data-panel-resize-handle]': 'true',
55
+ '[attr.data-panel-resize-handle-id]': 'handleId',
56
+ '[attr.role]': '"separator"',
57
+ '[attr.aria-valuenow]': 'ariaValueNow()',
58
+ '[attr.aria-valuemin]': '0',
59
+ '[attr.aria-valuemax]': '100',
60
+ '[attr.aria-orientation]': 'context.direction() === "horizontal" ? "vertical" : "horizontal"',
61
+ '[attr.aria-label]': '"Resize handle. Use arrow keys to resize."',
62
+ '[attr.tabindex]': 'disabled() ? -1 : 0',
63
+ '(mousedown)': 'onMouseDown($event)',
64
+ '(touchstart)': 'onTouchStart($event)',
65
+ '(keydown)': 'onKeyDown($event)',
66
+ '(focus)': 'onFocus()',
67
+ '(blur)': 'onBlur()',
68
+ },
69
+ changeDetection: ChangeDetectionStrategy.OnPush,
70
+ })
71
+ export class ResizableHandle {
72
+ protected readonly context = inject(RESIZABLE_CONTEXT);
73
+
74
+ /** Show a visible handle grip */
75
+ readonly withHandle = input<boolean>(false);
76
+
77
+ /** Whether the handle is disabled */
78
+ readonly disabled = input<boolean>(false);
79
+
80
+ /** Additional CSS classes */
81
+ readonly class = input<string>('');
82
+
83
+ /** Unique handle ID */
84
+ readonly handleId = `handle-${handleIdCounter++}`;
85
+
86
+ /** Whether dragging */
87
+ private isDragging = signal(false);
88
+
89
+ /** Whether focused for keyboard interaction */
90
+ private isFocused = signal(false);
91
+
92
+ /** Starting position */
93
+ private startPosition = 0;
94
+
95
+ /** ARIA value (approximate percentage) */
96
+ protected readonly ariaValueNow = signal(50);
97
+
98
+ protected readonly computedClass = computed(() =>
99
+ cn(
100
+ 'relative flex w-px items-center justify-center bg-border after:absolute after:inset-y-0 after:left-1/2 after:w-1 after:-translate-x-1/2 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1',
101
+ this.context.direction() === 'vertical' &&
102
+ 'h-px w-full after:left-0 after:h-1 after:w-full after:-translate-y-1/2 after:translate-x-0',
103
+ '[&[data-panel-group-direction=vertical]>div]:rotate-90',
104
+ this.isFocused() && 'ring-2 ring-ring',
105
+ this.class()
106
+ )
107
+ );
108
+
109
+ onFocus(): void {
110
+ this.isFocused.set(true);
111
+ }
112
+
113
+ onBlur(): void {
114
+ this.isFocused.set(false);
115
+ }
116
+
117
+ onKeyDown(event: KeyboardEvent): void {
118
+ if (this.disabled()) return;
119
+
120
+ const isHorizontal = this.context.direction() === 'horizontal';
121
+ const step = event.shiftKey ? 5 : 1; // Larger steps with Shift
122
+
123
+ let delta = 0;
124
+
125
+ switch (event.key) {
126
+ case 'ArrowLeft':
127
+ if (isHorizontal) {
128
+ event.preventDefault();
129
+ delta = -step;
130
+ }
131
+ break;
132
+ case 'ArrowRight':
133
+ if (isHorizontal) {
134
+ event.preventDefault();
135
+ delta = step;
136
+ }
137
+ break;
138
+ case 'ArrowUp':
139
+ if (!isHorizontal) {
140
+ event.preventDefault();
141
+ delta = -step;
142
+ }
143
+ break;
144
+ case 'ArrowDown':
145
+ if (!isHorizontal) {
146
+ event.preventDefault();
147
+ delta = step;
148
+ }
149
+ break;
150
+ case 'Home':
151
+ event.preventDefault();
152
+ delta = -100; // Go to minimum
153
+ break;
154
+ case 'End':
155
+ event.preventDefault();
156
+ delta = 100; // Go to maximum
157
+ break;
158
+ default:
159
+ return;
160
+ }
161
+
162
+ if (delta !== 0) {
163
+ this.context.startResize(this.handleId);
164
+ this.context.onResize(delta);
165
+ this.context.endResize();
166
+ this.updateAriaValue(delta);
167
+ }
168
+ }
169
+
170
+ private updateAriaValue(delta: number): void {
171
+ const current = this.ariaValueNow();
172
+ const newValue = Math.max(0, Math.min(100, current + delta));
173
+ this.ariaValueNow.set(newValue);
174
+ }
175
+
176
+ onMouseDown(event: MouseEvent): void {
177
+ if (this.disabled()) return;
178
+
179
+ event.preventDefault();
180
+ this.isDragging.set(true);
181
+ this.startPosition = this.context.direction() === 'horizontal' ? event.clientX : event.clientY;
182
+ this.context.startResize(this.handleId);
183
+
184
+ const onMouseMove = (e: MouseEvent) => {
185
+ if (!this.isDragging()) return;
186
+
187
+ const currentPosition = this.context.direction() === 'horizontal' ? e.clientX : e.clientY;
188
+ const delta = ((currentPosition - this.startPosition) / window.innerWidth) * 100;
189
+ this.context.onResize(delta);
190
+ this.startPosition = currentPosition;
191
+ };
192
+
193
+ const onMouseUp = () => {
194
+ this.isDragging.set(false);
195
+ this.context.endResize();
196
+ document.removeEventListener('mousemove', onMouseMove);
197
+ document.removeEventListener('mouseup', onMouseUp);
198
+ };
199
+
200
+ document.addEventListener('mousemove', onMouseMove);
201
+ document.addEventListener('mouseup', onMouseUp);
202
+ }
203
+
204
+ onTouchStart(event: TouchEvent): void {
205
+ if (this.disabled()) return;
206
+
207
+ const touch = event.touches[0];
208
+ this.isDragging.set(true);
209
+ this.startPosition = this.context.direction() === 'horizontal' ? touch.clientX : touch.clientY;
210
+ this.context.startResize(this.handleId);
211
+
212
+ const onTouchMove = (e: TouchEvent) => {
213
+ if (!this.isDragging()) return;
214
+
215
+ const currentTouch = e.touches[0];
216
+ const currentPosition = this.context.direction() === 'horizontal' ? currentTouch.clientX : currentTouch.clientY;
217
+ const delta = ((currentPosition - this.startPosition) / window.innerWidth) * 100;
218
+ this.context.onResize(delta);
219
+ this.startPosition = currentPosition;
220
+ };
221
+
222
+ const onTouchEnd = () => {
223
+ this.isDragging.set(false);
224
+ this.context.endResize();
225
+ document.removeEventListener('touchmove', onTouchMove);
226
+ document.removeEventListener('touchend', onTouchEnd);
227
+ };
228
+
229
+ document.addEventListener('touchmove', onTouchMove);
230
+ document.addEventListener('touchend', onTouchEnd);
231
+ }
232
+ }
@@ -0,0 +1,140 @@
1
+ import { cn } from '@/lib/utils';
2
+ import {
3
+ ChangeDetectionStrategy,
4
+ Component,
5
+ computed,
6
+ forwardRef,
7
+ input,
8
+ signal,
9
+ } from '@angular/core';
10
+ import { RESIZABLE_CONTEXT, type ResizableContextValue } from './resizable-context';
11
+
12
+ /**
13
+ * ResizablePanelGroup component - container for resizable panels.
14
+ * Matches shadcn/ui React ResizablePanelGroup exactly.
15
+ *
16
+ * @example
17
+ * <ResizablePanelGroup direction="horizontal" class="min-h-[200px] max-w-md rounded-lg border">
18
+ * <ResizablePanel defaultSize={50}>
19
+ * <div class="p-6">One</div>
20
+ * </ResizablePanel>
21
+ * <ResizableHandle />
22
+ * <ResizablePanel defaultSize={50}>
23
+ * <div class="p-6">Two</div>
24
+ * </ResizablePanel>
25
+ * </ResizablePanelGroup>
26
+ */
27
+ @Component({
28
+ selector: 'ResizablePanelGroup',
29
+ template: `<ng-content />`,
30
+ host: {
31
+ '[class]': 'computedClass()',
32
+ '[attr.data-panel-group]': 'true',
33
+ '[attr.data-panel-group-direction]': 'direction()',
34
+ },
35
+ providers: [
36
+ {
37
+ provide: RESIZABLE_CONTEXT,
38
+ useExisting: forwardRef(() => ResizablePanelGroup),
39
+ },
40
+ ],
41
+ changeDetection: ChangeDetectionStrategy.OnPush,
42
+ })
43
+ export class ResizablePanelGroup implements ResizableContextValue {
44
+ /** Direction of the panel group */
45
+ readonly direction = input<'horizontal' | 'vertical'>('horizontal');
46
+
47
+ /** Additional CSS classes */
48
+ readonly class = input<string>('');
49
+
50
+ /** Whether keyboard resize is disabled */
51
+ readonly keyboardResizeBy = input<number>(10);
52
+
53
+ /** Auto-save ID for persisting layout */
54
+ readonly autoSaveId = input<string | null>(null);
55
+
56
+ /** Panel sizes state */
57
+ readonly panelSizes = signal<Map<string, number>>(new Map());
58
+
59
+ /** Currently active resize handle */
60
+ private activeHandleId: string | null = null;
61
+
62
+ /** Panels metadata */
63
+ private panels = new Map<string, { minSize: number; maxSize: number; order: number }>();
64
+
65
+ /** Panel order counter */
66
+ private panelOrderCounter = 0;
67
+
68
+ protected readonly computedClass = computed(() =>
69
+ cn(
70
+ 'flex h-full w-full data-[panel-group-direction=vertical]:flex-col',
71
+ this.class()
72
+ )
73
+ );
74
+
75
+ registerPanel(id: string, minSize = 0, maxSize = 100, defaultSize?: number): void {
76
+ this.panels.set(id, { minSize, maxSize, order: this.panelOrderCounter++ });
77
+ if (defaultSize !== undefined) {
78
+ this.panelSizes.update(sizes => {
79
+ const newSizes = new Map(sizes);
80
+ newSizes.set(id, defaultSize);
81
+ return newSizes;
82
+ });
83
+ }
84
+ }
85
+
86
+ getPanelSize(id: string): number {
87
+ return this.panelSizes().get(id) ?? 50;
88
+ }
89
+
90
+ setPanelSize(id: string, size: number): void {
91
+ const panel = this.panels.get(id);
92
+ if (panel) {
93
+ const clampedSize = Math.max(panel.minSize, Math.min(panel.maxSize, size));
94
+ this.panelSizes.update(sizes => {
95
+ const newSizes = new Map(sizes);
96
+ newSizes.set(id, clampedSize);
97
+ return newSizes;
98
+ });
99
+ }
100
+ }
101
+
102
+ startResize(handleId: string): void {
103
+ this.activeHandleId = handleId;
104
+ }
105
+
106
+ onResize(delta: number): void {
107
+ if (!this.activeHandleId) return;
108
+
109
+ // Get panels on either side of the handle
110
+ const panelIds = Array.from(this.panels.entries())
111
+ .sort((a, b) => a[1].order - b[1].order)
112
+ .map(([id]) => id);
113
+
114
+ // Find the handle index (handles are between panels)
115
+ const handleIndex = parseInt(this.activeHandleId.replace('handle-', ''), 10);
116
+ const leftPanelId = panelIds[handleIndex];
117
+ const rightPanelId = panelIds[handleIndex + 1];
118
+
119
+ if (leftPanelId && rightPanelId) {
120
+ const leftSize = this.getPanelSize(leftPanelId);
121
+ const rightSize = this.getPanelSize(rightPanelId);
122
+
123
+ const leftPanel = this.panels.get(leftPanelId)!;
124
+ const rightPanel = this.panels.get(rightPanelId)!;
125
+
126
+ const newLeftSize = Math.max(leftPanel.minSize, Math.min(leftPanel.maxSize, leftSize + delta));
127
+ const newRightSize = Math.max(rightPanel.minSize, Math.min(rightPanel.maxSize, rightSize - delta));
128
+
129
+ // Only update if both constraints are satisfied
130
+ if (newLeftSize + newRightSize === leftSize + rightSize) {
131
+ this.setPanelSize(leftPanelId, newLeftSize);
132
+ this.setPanelSize(rightPanelId, newRightSize);
133
+ }
134
+ }
135
+ }
136
+
137
+ endResize(): void {
138
+ this.activeHandleId = null;
139
+ }
140
+ }