@ojiepermana/angular 21.2.4 → 21.3.3

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 (345) hide show
  1. package/README.md +155 -12
  2. package/component/accordion/package.json +4 -0
  3. package/component/alert/package.json +4 -0
  4. package/component/alert-dialog/package.json +4 -0
  5. package/component/aspect-ratio/package.json +4 -0
  6. package/component/avatar/package.json +4 -0
  7. package/component/badge/package.json +4 -0
  8. package/component/breadcrumb/package.json +4 -0
  9. package/component/button/package.json +4 -0
  10. package/component/button-group/package.json +4 -0
  11. package/component/calendar/package.json +4 -0
  12. package/component/card/package.json +4 -0
  13. package/component/carousel/package.json +4 -0
  14. package/component/chart/README.md +249 -0
  15. package/component/chart/area/package.json +4 -0
  16. package/component/chart/bar/package.json +4 -0
  17. package/component/chart/line/package.json +4 -0
  18. package/component/chart/package.json +4 -0
  19. package/component/chart/pie/package.json +4 -0
  20. package/component/chart/radar/package.json +4 -0
  21. package/component/chart/radial/package.json +4 -0
  22. package/component/chart/scatter/package.json +4 -0
  23. package/component/checkbox/package.json +4 -0
  24. package/component/collapsible/package.json +4 -0
  25. package/component/combobox/package.json +4 -0
  26. package/component/command/package.json +4 -0
  27. package/component/context-menu/package.json +4 -0
  28. package/component/date-picker/package.json +4 -0
  29. package/component/dialog/package.json +4 -0
  30. package/component/drawer/package.json +4 -0
  31. package/component/dropdown-menu/package.json +4 -0
  32. package/component/form/package.json +4 -0
  33. package/component/input/package.json +4 -0
  34. package/component/input-group/package.json +4 -0
  35. package/component/item/package.json +4 -0
  36. package/component/label/package.json +4 -0
  37. package/component/pagination/package.json +4 -0
  38. package/component/popover/package.json +4 -0
  39. package/component/progress/package.json +4 -0
  40. package/component/radio/package.json +4 -0
  41. package/component/scroll-area/package.json +4 -0
  42. package/component/select/package.json +4 -0
  43. package/component/separator/package.json +4 -0
  44. package/component/sheet/package.json +4 -0
  45. package/component/skeleton/package.json +4 -0
  46. package/component/slider/package.json +4 -0
  47. package/component/switch/package.json +4 -0
  48. package/component/table/package.json +4 -0
  49. package/component/tabs/package.json +4 -0
  50. package/component/textarea/package.json +4 -0
  51. package/component/toast/package.json +4 -0
  52. package/component/tooltip/package.json +4 -0
  53. package/component/utils/package.json +4 -0
  54. package/fesm2022/ojiepermana-angular-component-accordion.mjs +174 -0
  55. package/fesm2022/ojiepermana-angular-component-accordion.mjs.map +1 -0
  56. package/fesm2022/ojiepermana-angular-component-alert-dialog.mjs +242 -0
  57. package/fesm2022/ojiepermana-angular-component-alert-dialog.mjs.map +1 -0
  58. package/fesm2022/ojiepermana-angular-component-alert.mjs +90 -0
  59. package/fesm2022/ojiepermana-angular-component-alert.mjs.map +1 -0
  60. package/fesm2022/ojiepermana-angular-component-aspect-ratio.mjs +33 -0
  61. package/fesm2022/ojiepermana-angular-component-aspect-ratio.mjs.map +1 -0
  62. package/fesm2022/ojiepermana-angular-component-avatar.mjs +123 -0
  63. package/fesm2022/ojiepermana-angular-component-avatar.mjs.map +1 -0
  64. package/fesm2022/ojiepermana-angular-component-badge.mjs +47 -0
  65. package/fesm2022/ojiepermana-angular-component-badge.mjs.map +1 -0
  66. package/fesm2022/ojiepermana-angular-component-breadcrumb.mjs +186 -0
  67. package/fesm2022/ojiepermana-angular-component-breadcrumb.mjs.map +1 -0
  68. package/fesm2022/ojiepermana-angular-component-button-group.mjs +95 -0
  69. package/fesm2022/ojiepermana-angular-component-button-group.mjs.map +1 -0
  70. package/fesm2022/ojiepermana-angular-component-button.mjs +64 -0
  71. package/fesm2022/ojiepermana-angular-component-button.mjs.map +1 -0
  72. package/fesm2022/ojiepermana-angular-component-calendar.mjs +78 -0
  73. package/fesm2022/ojiepermana-angular-component-calendar.mjs.map +1 -0
  74. package/fesm2022/ojiepermana-angular-component-card.mjs +137 -0
  75. package/fesm2022/ojiepermana-angular-component-card.mjs.map +1 -0
  76. package/fesm2022/ojiepermana-angular-component-carousel.mjs +310 -0
  77. package/fesm2022/ojiepermana-angular-component-carousel.mjs.map +1 -0
  78. package/fesm2022/ojiepermana-angular-component-chart-area.mjs +6 -0
  79. package/fesm2022/ojiepermana-angular-component-chart-area.mjs.map +1 -0
  80. package/fesm2022/ojiepermana-angular-component-chart-bar.mjs +6 -0
  81. package/fesm2022/ojiepermana-angular-component-chart-bar.mjs.map +1 -0
  82. package/fesm2022/ojiepermana-angular-component-chart-line.mjs +6 -0
  83. package/fesm2022/ojiepermana-angular-component-chart-line.mjs.map +1 -0
  84. package/fesm2022/ojiepermana-angular-component-chart-pie.mjs +6 -0
  85. package/fesm2022/ojiepermana-angular-component-chart-pie.mjs.map +1 -0
  86. package/fesm2022/ojiepermana-angular-component-chart-radar.mjs +6 -0
  87. package/fesm2022/ojiepermana-angular-component-chart-radar.mjs.map +1 -0
  88. package/fesm2022/ojiepermana-angular-component-chart-radial.mjs +6 -0
  89. package/fesm2022/ojiepermana-angular-component-chart-radial.mjs.map +1 -0
  90. package/fesm2022/ojiepermana-angular-component-chart-scatter.mjs +6 -0
  91. package/fesm2022/ojiepermana-angular-component-chart-scatter.mjs.map +1 -0
  92. package/fesm2022/{ojiepermana-angular-chart.mjs → ojiepermana-angular-component-chart.mjs} +2 -2
  93. package/fesm2022/ojiepermana-angular-component-chart.mjs.map +1 -0
  94. package/fesm2022/ojiepermana-angular-component-checkbox.mjs +104 -0
  95. package/fesm2022/ojiepermana-angular-component-checkbox.mjs.map +1 -0
  96. package/fesm2022/ojiepermana-angular-component-collapsible.mjs +116 -0
  97. package/fesm2022/ojiepermana-angular-component-collapsible.mjs.map +1 -0
  98. package/fesm2022/ojiepermana-angular-component-combobox.mjs +263 -0
  99. package/fesm2022/ojiepermana-angular-component-combobox.mjs.map +1 -0
  100. package/fesm2022/ojiepermana-angular-component-command.mjs +268 -0
  101. package/fesm2022/ojiepermana-angular-component-command.mjs.map +1 -0
  102. package/fesm2022/ojiepermana-angular-component-context-menu.mjs +100 -0
  103. package/fesm2022/ojiepermana-angular-component-context-menu.mjs.map +1 -0
  104. package/fesm2022/ojiepermana-angular-component-date-picker.mjs +155 -0
  105. package/fesm2022/ojiepermana-angular-component-date-picker.mjs.map +1 -0
  106. package/fesm2022/ojiepermana-angular-component-dialog.mjs +262 -0
  107. package/fesm2022/ojiepermana-angular-component-dialog.mjs.map +1 -0
  108. package/fesm2022/ojiepermana-angular-component-drawer.mjs +6 -0
  109. package/fesm2022/ojiepermana-angular-component-drawer.mjs.map +1 -0
  110. package/fesm2022/ojiepermana-angular-component-dropdown-menu.mjs +458 -0
  111. package/fesm2022/ojiepermana-angular-component-dropdown-menu.mjs.map +1 -0
  112. package/fesm2022/ojiepermana-angular-component-form.mjs +208 -0
  113. package/fesm2022/ojiepermana-angular-component-form.mjs.map +1 -0
  114. package/fesm2022/ojiepermana-angular-component-input-group.mjs +164 -0
  115. package/fesm2022/ojiepermana-angular-component-input-group.mjs.map +1 -0
  116. package/fesm2022/ojiepermana-angular-component-input.mjs +43 -0
  117. package/fesm2022/ojiepermana-angular-component-input.mjs.map +1 -0
  118. package/fesm2022/ojiepermana-angular-component-item.mjs +241 -0
  119. package/fesm2022/ojiepermana-angular-component-item.mjs.map +1 -0
  120. package/fesm2022/ojiepermana-angular-component-label.mjs +30 -0
  121. package/fesm2022/ojiepermana-angular-component-label.mjs.map +1 -0
  122. package/fesm2022/ojiepermana-angular-component-pagination.mjs +192 -0
  123. package/fesm2022/ojiepermana-angular-component-pagination.mjs.map +1 -0
  124. package/fesm2022/ojiepermana-angular-component-popover.mjs +163 -0
  125. package/fesm2022/ojiepermana-angular-component-popover.mjs.map +1 -0
  126. package/fesm2022/ojiepermana-angular-component-progress.mjs +53 -0
  127. package/fesm2022/ojiepermana-angular-component-progress.mjs.map +1 -0
  128. package/fesm2022/ojiepermana-angular-component-radio.mjs +92 -0
  129. package/fesm2022/ojiepermana-angular-component-radio.mjs.map +1 -0
  130. package/fesm2022/ojiepermana-angular-component-scroll-area.mjs +48 -0
  131. package/fesm2022/ojiepermana-angular-component-scroll-area.mjs.map +1 -0
  132. package/fesm2022/ojiepermana-angular-component-select.mjs +131 -0
  133. package/fesm2022/ojiepermana-angular-component-select.mjs.map +1 -0
  134. package/fesm2022/ojiepermana-angular-component-separator.mjs +33 -0
  135. package/fesm2022/ojiepermana-angular-component-separator.mjs.map +1 -0
  136. package/fesm2022/ojiepermana-angular-component-sheet.mjs +235 -0
  137. package/fesm2022/ojiepermana-angular-component-sheet.mjs.map +1 -0
  138. package/fesm2022/ojiepermana-angular-component-skeleton.mjs +29 -0
  139. package/fesm2022/ojiepermana-angular-component-skeleton.mjs.map +1 -0
  140. package/fesm2022/ojiepermana-angular-component-slider.mjs +29 -0
  141. package/fesm2022/ojiepermana-angular-component-slider.mjs.map +1 -0
  142. package/fesm2022/ojiepermana-angular-component-switch.mjs +84 -0
  143. package/fesm2022/ojiepermana-angular-component-switch.mjs.map +1 -0
  144. package/fesm2022/ojiepermana-angular-component-table.mjs +139 -0
  145. package/fesm2022/ojiepermana-angular-component-table.mjs.map +1 -0
  146. package/fesm2022/ojiepermana-angular-component-tabs.mjs +252 -0
  147. package/fesm2022/ojiepermana-angular-component-tabs.mjs.map +1 -0
  148. package/fesm2022/ojiepermana-angular-component-textarea.mjs +37 -0
  149. package/fesm2022/ojiepermana-angular-component-textarea.mjs.map +1 -0
  150. package/fesm2022/ojiepermana-angular-component-toast.mjs +47 -0
  151. package/fesm2022/ojiepermana-angular-component-toast.mjs.map +1 -0
  152. package/fesm2022/ojiepermana-angular-component-tooltip.mjs +56 -0
  153. package/fesm2022/ojiepermana-angular-component-tooltip.mjs.map +1 -0
  154. package/fesm2022/ojiepermana-angular-component-utils.mjs +13 -0
  155. package/fesm2022/ojiepermana-angular-component-utils.mjs.map +1 -0
  156. package/fesm2022/ojiepermana-angular-generator-api.mjs +2 -1
  157. package/fesm2022/ojiepermana-angular-generator-api.mjs.map +1 -1
  158. package/fesm2022/ojiepermana-angular-layout-component.mjs +581 -0
  159. package/fesm2022/ojiepermana-angular-layout-component.mjs.map +1 -0
  160. package/fesm2022/ojiepermana-angular-layout-empty.mjs +49 -0
  161. package/fesm2022/ojiepermana-angular-layout-empty.mjs.map +1 -0
  162. package/fesm2022/ojiepermana-angular-layout-horizontal.mjs +119 -0
  163. package/fesm2022/ojiepermana-angular-layout-horizontal.mjs.map +1 -0
  164. package/fesm2022/ojiepermana-angular-layout-provider.mjs +21 -0
  165. package/fesm2022/ojiepermana-angular-layout-provider.mjs.map +1 -0
  166. package/fesm2022/ojiepermana-angular-layout-services.mjs +114 -0
  167. package/fesm2022/ojiepermana-angular-layout-services.mjs.map +1 -0
  168. package/fesm2022/ojiepermana-angular-layout-shell.mjs +48 -0
  169. package/fesm2022/ojiepermana-angular-layout-shell.mjs.map +1 -0
  170. package/fesm2022/ojiepermana-angular-layout-token-directive.mjs +27 -0
  171. package/fesm2022/ojiepermana-angular-layout-token-directive.mjs.map +1 -0
  172. package/fesm2022/ojiepermana-angular-layout-token.mjs +33 -0
  173. package/fesm2022/ojiepermana-angular-layout-token.mjs.map +1 -0
  174. package/fesm2022/ojiepermana-angular-layout-vertical.mjs +113 -0
  175. package/fesm2022/ojiepermana-angular-layout-vertical.mjs.map +1 -0
  176. package/fesm2022/ojiepermana-angular-layout.mjs +141 -137
  177. package/fesm2022/ojiepermana-angular-layout.mjs.map +1 -1
  178. package/fesm2022/ojiepermana-angular-navigation-demo-data.mjs +334 -0
  179. package/fesm2022/ojiepermana-angular-navigation-demo-data.mjs.map +1 -0
  180. package/fesm2022/ojiepermana-angular-navigation-icon.mjs +59 -0
  181. package/fesm2022/ojiepermana-angular-navigation-icon.mjs.map +1 -0
  182. package/fesm2022/ojiepermana-angular-navigation-item.mjs +548 -0
  183. package/fesm2022/ojiepermana-angular-navigation-item.mjs.map +1 -0
  184. package/fesm2022/ojiepermana-angular-navigation-service.mjs +204 -0
  185. package/fesm2022/ojiepermana-angular-navigation-service.mjs.map +1 -0
  186. package/fesm2022/ojiepermana-angular-navigation-sidebar.mjs +373 -0
  187. package/fesm2022/ojiepermana-angular-navigation-sidebar.mjs.map +1 -0
  188. package/fesm2022/ojiepermana-angular-navigation-topbar.mjs +433 -0
  189. package/fesm2022/ojiepermana-angular-navigation-topbar.mjs.map +1 -0
  190. package/fesm2022/ojiepermana-angular-navigation-types.mjs +4 -0
  191. package/fesm2022/ojiepermana-angular-navigation-types.mjs.map +1 -0
  192. package/fesm2022/ojiepermana-angular-theme-provider.mjs +35 -0
  193. package/fesm2022/ojiepermana-angular-theme-provider.mjs.map +1 -0
  194. package/fesm2022/ojiepermana-angular-theme-services.mjs +286 -0
  195. package/fesm2022/ojiepermana-angular-theme-services.mjs.map +1 -0
  196. package/fesm2022/ojiepermana-angular-theme-token.mjs +56 -0
  197. package/fesm2022/ojiepermana-angular-theme-token.mjs.map +1 -0
  198. package/fesm2022/ojiepermana-angular-theme.mjs +31 -56
  199. package/fesm2022/ojiepermana-angular-theme.mjs.map +1 -1
  200. package/fesm2022/ojiepermana-angular.mjs +7 -6
  201. package/fesm2022/ojiepermana-angular.mjs.map +1 -1
  202. package/generator/api/README.md +18 -15
  203. package/generator/api/bin/schematics/init/index.js +4 -2
  204. package/generator/api/bin/src/config/schema.js +2 -1
  205. package/generator/api/bin/src/emit/navigation.js +1 -1
  206. package/generator/api/bin/src/layout/per-domain.js +7 -3
  207. package/generator/api/sdk.config.example.json +4 -2
  208. package/layout/component/package.json +4 -0
  209. package/layout/empty/package.json +4 -0
  210. package/layout/horizontal/package.json +4 -0
  211. package/layout/provider/package.json +4 -0
  212. package/layout/services/package.json +4 -0
  213. package/layout/shell/package.json +4 -0
  214. package/layout/token/directive/package.json +4 -0
  215. package/layout/token/package.json +4 -0
  216. package/layout/vertical/package.json +4 -0
  217. package/navigation/demo-data/package.json +4 -0
  218. package/navigation/icon/package.json +4 -0
  219. package/navigation/item/package.json +4 -0
  220. package/navigation/service/package.json +4 -0
  221. package/navigation/sidebar/package.json +4 -0
  222. package/navigation/topbar/package.json +4 -0
  223. package/navigation/types/package.json +4 -0
  224. package/package.json +284 -16
  225. package/theme/README.md +67 -0
  226. package/theme/provider/package.json +4 -0
  227. package/theme/services/package.json +4 -0
  228. package/theme/styles/index.css +12 -7
  229. package/theme/token/package.json +4 -0
  230. package/types/ojiepermana-angular-component-accordion.d.ts +51 -0
  231. package/types/ojiepermana-angular-component-alert-dialog.d.ts +93 -0
  232. package/types/ojiepermana-angular-component-alert.d.ts +37 -0
  233. package/types/ojiepermana-angular-component-aspect-ratio.d.ts +12 -0
  234. package/types/ojiepermana-angular-component-avatar.d.ts +51 -0
  235. package/types/ojiepermana-angular-component-badge.d.ts +19 -0
  236. package/types/ojiepermana-angular-component-breadcrumb.d.ts +46 -0
  237. package/types/ojiepermana-angular-component-button-group.d.ts +26 -0
  238. package/types/ojiepermana-angular-component-button.d.ts +22 -0
  239. package/types/ojiepermana-angular-component-calendar.d.ts +33 -0
  240. package/types/ojiepermana-angular-component-card.d.ts +60 -0
  241. package/types/ojiepermana-angular-component-carousel.d.ts +86 -0
  242. package/types/ojiepermana-angular-component-chart-area.d.ts +1 -0
  243. package/types/ojiepermana-angular-component-chart-bar.d.ts +1 -0
  244. package/types/ojiepermana-angular-component-chart-line.d.ts +1 -0
  245. package/types/ojiepermana-angular-component-chart-pie.d.ts +1 -0
  246. package/types/ojiepermana-angular-component-chart-radar.d.ts +1 -0
  247. package/types/ojiepermana-angular-component-chart-radial.d.ts +1 -0
  248. package/types/ojiepermana-angular-component-chart-scatter.d.ts +1 -0
  249. package/types/{ojiepermana-angular-chart.d.ts → ojiepermana-angular-component-chart.d.ts} +15 -15
  250. package/types/ojiepermana-angular-component-checkbox.d.ts +35 -0
  251. package/types/ojiepermana-angular-component-collapsible.d.ts +42 -0
  252. package/types/ojiepermana-angular-component-combobox.d.ts +51 -0
  253. package/types/ojiepermana-angular-component-command.d.ts +99 -0
  254. package/types/ojiepermana-angular-component-context-menu.d.ts +35 -0
  255. package/types/ojiepermana-angular-component-date-picker.d.ts +41 -0
  256. package/types/ojiepermana-angular-component-dialog.d.ts +87 -0
  257. package/types/ojiepermana-angular-component-drawer.d.ts +1 -0
  258. package/types/ojiepermana-angular-component-dropdown-menu.d.ts +135 -0
  259. package/types/ojiepermana-angular-component-form.d.ts +92 -0
  260. package/types/ojiepermana-angular-component-input-group.d.ts +51 -0
  261. package/types/ojiepermana-angular-component-input.d.ts +16 -0
  262. package/types/ojiepermana-angular-component-item.d.ts +88 -0
  263. package/types/ojiepermana-angular-component-label.d.ts +11 -0
  264. package/types/ojiepermana-angular-component-pagination.d.ts +27 -0
  265. package/types/ojiepermana-angular-component-popover.d.ts +43 -0
  266. package/types/ojiepermana-angular-component-progress.d.ts +17 -0
  267. package/types/ojiepermana-angular-component-radio.d.ts +34 -0
  268. package/types/ojiepermana-angular-component-scroll-area.d.ts +19 -0
  269. package/types/ojiepermana-angular-component-select.d.ts +45 -0
  270. package/types/ojiepermana-angular-component-separator.d.ts +14 -0
  271. package/types/ojiepermana-angular-component-sheet.d.ts +74 -0
  272. package/types/ojiepermana-angular-component-skeleton.d.ts +10 -0
  273. package/types/ojiepermana-angular-component-slider.d.ts +16 -0
  274. package/types/ojiepermana-angular-component-switch.d.ts +30 -0
  275. package/types/ojiepermana-angular-component-table.d.ts +52 -0
  276. package/types/ojiepermana-angular-component-tabs.d.ts +92 -0
  277. package/types/ojiepermana-angular-component-textarea.d.ts +12 -0
  278. package/types/ojiepermana-angular-component-toast.d.ts +29 -0
  279. package/types/ojiepermana-angular-component-tooltip.d.ts +22 -0
  280. package/types/ojiepermana-angular-component-utils.d.ts +5 -0
  281. package/types/ojiepermana-angular-generator-api.d.ts +2 -1
  282. package/types/ojiepermana-angular-layout-component.d.ts +205 -0
  283. package/types/ojiepermana-angular-layout-empty.d.ts +22 -0
  284. package/types/ojiepermana-angular-layout-horizontal.d.ts +36 -0
  285. package/types/ojiepermana-angular-layout-provider.d.ts +6 -0
  286. package/types/ojiepermana-angular-layout-services.d.ts +25 -0
  287. package/types/ojiepermana-angular-layout-shell.d.ts +8 -0
  288. package/types/ojiepermana-angular-layout-token-directive.d.ts +13 -0
  289. package/types/ojiepermana-angular-layout-token.d.ts +36 -0
  290. package/types/ojiepermana-angular-layout-vertical.d.ts +38 -0
  291. package/types/ojiepermana-angular-layout.d.ts +27 -26
  292. package/types/ojiepermana-angular-navigation-demo-data.d.ts +5 -0
  293. package/types/ojiepermana-angular-navigation-icon.d.ts +17 -0
  294. package/types/ojiepermana-angular-navigation-item.d.ts +54 -0
  295. package/types/ojiepermana-angular-navigation-service.d.ts +77 -0
  296. package/types/ojiepermana-angular-navigation-sidebar.d.ts +75 -0
  297. package/types/ojiepermana-angular-navigation-topbar.d.ts +54 -0
  298. package/types/ojiepermana-angular-navigation-types.d.ts +129 -0
  299. package/types/ojiepermana-angular-theme-provider.d.ts +11 -0
  300. package/types/ojiepermana-angular-theme-services.d.ts +55 -0
  301. package/types/ojiepermana-angular-theme-token.d.ts +57 -0
  302. package/types/ojiepermana-angular-theme.d.ts +11 -66
  303. package/chart/README.md +0 -0
  304. package/chart/package.json +0 -4
  305. package/component/package.json +0 -4
  306. package/fesm2022/ojiepermana-angular-chart.mjs.map +0 -1
  307. package/fesm2022/ojiepermana-angular-component.mjs +0 -5774
  308. package/fesm2022/ojiepermana-angular-component.mjs.map +0 -1
  309. package/fesm2022/ojiepermana-angular-navigation.mjs +0 -2369
  310. package/fesm2022/ojiepermana-angular-navigation.mjs.map +0 -1
  311. package/navigation/package.json +0 -4
  312. package/types/ojiepermana-angular-component.d.ts +0 -1927
  313. package/types/ojiepermana-angular-navigation.d.ts +0 -393
  314. /package/theme/styles/{themes/library/_components.css → foundation/components.css} +0 -0
  315. /package/theme/styles/{themes/library/_layers.css → foundation/layers.css} +0 -0
  316. /package/theme/styles/{themes/library/_tokens.css → foundation/tokens.css} +0 -0
  317. /package/theme/styles/{themes/library/_material-overrides.css → integrations/material.css} +0 -0
  318. /package/theme/styles/{themes → integrations}/tailwind.css +0 -0
  319. /package/theme/styles/{themes/library → variants}/color/amber.css +0 -0
  320. /package/theme/styles/{themes/library → variants}/color/base.css +0 -0
  321. /package/theme/styles/{themes/library → variants}/color/blue.css +0 -0
  322. /package/theme/styles/{themes/library → variants}/color/cyan.css +0 -0
  323. /package/theme/styles/{themes/library → variants}/color/emerald.css +0 -0
  324. /package/theme/styles/{themes/library → variants}/color/fuchsia.css +0 -0
  325. /package/theme/styles/{themes/library → variants}/color/green.css +0 -0
  326. /package/theme/styles/{themes/library → variants}/color/index.css +0 -0
  327. /package/theme/styles/{themes/library → variants}/color/indigo.css +0 -0
  328. /package/theme/styles/{themes/library → variants}/color/lime.css +0 -0
  329. /package/theme/styles/{themes/library → variants}/color/orange.css +0 -0
  330. /package/theme/styles/{themes/library → variants}/color/pink.css +0 -0
  331. /package/theme/styles/{themes/library → variants}/color/purple.css +0 -0
  332. /package/theme/styles/{themes/library → variants}/color/red.css +0 -0
  333. /package/theme/styles/{themes/library → variants}/color/rose.css +0 -0
  334. /package/theme/styles/{themes/library → variants}/color/sky.css +0 -0
  335. /package/theme/styles/{themes/library → variants}/color/teal.css +0 -0
  336. /package/theme/styles/{themes/library → variants}/color/violet.css +0 -0
  337. /package/theme/styles/{themes/library → variants}/color/yellow.css +0 -0
  338. /package/theme/styles/{themes → variants}/mode/dark.css +0 -0
  339. /package/theme/styles/{themes → variants}/mode/index.css +0 -0
  340. /package/theme/styles/{themes → variants}/mode/light.css +0 -0
  341. /package/theme/styles/{themes/library → variants}/style/brutal.css +0 -0
  342. /package/theme/styles/{themes/library → variants}/style/default.css +0 -0
  343. /package/theme/styles/{themes/library → variants}/style/index.css +0 -0
  344. /package/theme/styles/{themes/library → variants}/style/sharp.css +0 -0
  345. /package/theme/styles/{themes/library → variants}/style/soft.css +0 -0
@@ -1,2369 +0,0 @@
1
- import { DOCUMENT, isPlatformBrowser, NgTemplateOutlet } from '@angular/common';
2
- import * as i0 from '@angular/core';
3
- import { inject, DestroyRef, signal, computed, effect, Injectable, PLATFORM_ID, input, ChangeDetectionStrategy, Component, ViewContainerRef, viewChild, ElementRef } from '@angular/core';
4
- import { Router, NavigationEnd, RouterLink, RouterLinkActive } from '@angular/router';
5
- import { takeUntilDestroyed, toSignal } from '@angular/core/rxjs-interop';
6
- import { filter, map } from 'rxjs/operators';
7
- import { MatTooltip } from '@angular/material/tooltip';
8
- import { clsx } from 'clsx';
9
- import { twMerge } from 'tailwind-merge';
10
- import { BreakpointObserver } from '@angular/cdk/layout';
11
- import { Overlay } from '@angular/cdk/overlay';
12
- import { TemplatePortal } from '@angular/cdk/portal';
13
- import { FocusTrapFactory } from '@angular/cdk/a11y';
14
- import { ScrollAreaComponent } from '@ojiepermana/angular/component';
15
- import { merge } from 'rxjs';
16
-
17
- /** Default registry key used when no id is specified. */
18
- const DEFAULT_NAVIGATION_ID = 'main';
19
- const SIDEBAR_COLLAPSE_STORAGE_KEY = 'sidebar-collapse';
20
- const LEGACY_SIDEBAR_APPEARANCE_STORAGE_KEY = 'sidebar-appearance';
21
- function parseSidebarCollapsed(value) {
22
- if (value === 'true')
23
- return true;
24
- if (value === 'false')
25
- return false;
26
- return null;
27
- }
28
- /**
29
- * Signal-based global state untuk navigation (sidebar/topbar).
30
- *
31
- * Items disimpan dalam registry ber-key. Key default adalah `'main'`.
32
- * Komponen `sidebar` / `topbar` memilih registry via input `navigationId`.
33
- */
34
- class NavigationService {
35
- doc = inject(DOCUMENT);
36
- router = inject(Router);
37
- destroyRef = inject(DestroyRef);
38
- persistedSidebarCollapsed = this.readPersistedSidebarCollapsed();
39
- /** Internal version counter — incremented on every registry mutation. */
40
- _version = signal(0, ...(ngDevMode ? [{ debugName: "_version" }] : /* istanbul ignore next */ []));
41
- /** Internal map of registered navigation trees. */
42
- _registry = new Map();
43
- _collapsed = signal(this.persistedSidebarCollapsed ?? false, ...(ngDevMode ? [{ debugName: "_collapsed" }] : /* istanbul ignore next */ []));
44
- _hasStoredSidebarCollapse = signal(this.persistedSidebarCollapsed !== null, ...(ngDevMode ? [{ debugName: "_hasStoredSidebarCollapse" }] : /* istanbul ignore next */ []));
45
- /**
46
- * Backward-compatible accessor — returns items for the default (`'main'`) key.
47
- * Prefer `getItems(id)` when working with named registries.
48
- */
49
- items = computed(() => this.getItems(DEFAULT_NAVIGATION_ID)(), ...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
50
- /** Sidebar appearance preference (`default` or `thin`). */
51
- sidebarAppearance = computed(() => (this._collapsed() ? 'thin' : 'default'), ...(ngDevMode ? [{ debugName: "sidebarAppearance" }] : /* istanbul ignore next */ []));
52
- hasStoredSidebarCollapse = this._hasStoredSidebarCollapse.asReadonly();
53
- /** Sidebar collapsed (default ↔ thin) toggle untuk desktop. */
54
- collapsed = this._collapsed.asReadonly();
55
- /** Sheet drawer terbuka di mobile. */
56
- mobileOpen = signal(false, ...(ngDevMode ? [{ debugName: "mobileOpen" }] : /* istanbul ignore next */ []));
57
- /** Set id grup / collapsable yang sedang terbuka. */
58
- openGroups = signal(new Set(), ...(ngDevMode ? [{ debugName: "openGroups" }] : /* istanbul ignore next */ []));
59
- /** URL aktif terakhir. Update otomatis dari Router `NavigationEnd`. */
60
- activeUrl = signal(this.router.url, ...(ngDevMode ? [{ debugName: "activeUrl" }] : /* istanbul ignore next */ []));
61
- /** Trail id item yang sedang match dengan URL aktif (across ALL registries). */
62
- activeTrail = computed(() => {
63
- this._version(); // track changes
64
- const url = this.activeUrl();
65
- const trail = new Set();
66
- const walk = (list, ancestors) => {
67
- let matched = false;
68
- for (const item of list) {
69
- const id = item.id;
70
- const link = 'link' in item ? item.link : undefined;
71
- let selfMatch = false;
72
- if (link) {
73
- selfMatch = url === link || url.startsWith(link + '/') || url.startsWith(link + '?');
74
- }
75
- const children = 'children' in item ? (item.children ?? []) : [];
76
- const nextAncestors = id ? [...ancestors, id] : ancestors;
77
- const childMatch = children.length > 0 && walk(children, nextAncestors);
78
- if (selfMatch || childMatch) {
79
- if (id)
80
- trail.add(id);
81
- for (const a of ancestors)
82
- trail.add(a);
83
- matched = true;
84
- }
85
- }
86
- return matched;
87
- };
88
- for (const items of this._registry.values()) {
89
- walk(items, []);
90
- }
91
- return trail;
92
- }, ...(ngDevMode ? [{ debugName: "activeTrail" }] : /* istanbul ignore next */ []));
93
- constructor() {
94
- effect(() => {
95
- if (!this._hasStoredSidebarCollapse()) {
96
- return;
97
- }
98
- this.persistSidebarCollapsed(this._collapsed());
99
- });
100
- this.router.events
101
- .pipe(filter((e) => e instanceof NavigationEnd), takeUntilDestroyed(this.destroyRef))
102
- .subscribe((e) => this.activeUrl.set(e.urlAfterRedirects));
103
- }
104
- registerItems(idOrItems, maybeItems) {
105
- const [id, items] = typeof idOrItems === 'string' ? [idOrItems, maybeItems] : [DEFAULT_NAVIGATION_ID, idOrItems];
106
- this._registry.set(id, items);
107
- this._version.update((v) => v + 1);
108
- }
109
- /** Remove a named registry entry. */
110
- removeItems(id) {
111
- this._registry.delete(id);
112
- this._version.update((v) => v + 1);
113
- }
114
- /**
115
- * Computed yang mengembalikan items untuk key tertentu.
116
- * Reactive terhadap perubahan registry.
117
- */
118
- getItems(id) {
119
- return computed(() => {
120
- this._version(); // track changes
121
- return this._registry.get(id) ?? [];
122
- });
123
- }
124
- setSidebarAppearance(value) {
125
- this.setCollapsed(value === 'thin');
126
- }
127
- toggleSidebarAppearance(currentAppearance = this.sidebarAppearance()) {
128
- this.setCollapsed(currentAppearance !== 'thin');
129
- }
130
- /** Toggle sidebar collapsed (default ↔ thin). */
131
- toggleCollapsed() {
132
- this.setCollapsed(!this._collapsed());
133
- }
134
- setCollapsed(value) {
135
- this._collapsed.set(value);
136
- this._hasStoredSidebarCollapse.set(true);
137
- }
138
- openMobile() {
139
- this.mobileOpen.set(true);
140
- }
141
- closeMobile() {
142
- this.mobileOpen.set(false);
143
- }
144
- toggleMobile() {
145
- this.mobileOpen.update((v) => !v);
146
- }
147
- isGroupOpen(id) {
148
- return this.openGroups().has(id);
149
- }
150
- toggleGroup(id) {
151
- const next = new Set(this.openGroups());
152
- if (next.has(id))
153
- next.delete(id);
154
- else
155
- next.add(id);
156
- this.openGroups.set(next);
157
- }
158
- setGroupOpen(id, open) {
159
- const next = new Set(this.openGroups());
160
- if (open)
161
- next.add(id);
162
- else
163
- next.delete(id);
164
- this.openGroups.set(next);
165
- }
166
- /** Apakah id termasuk dalam active trail saat ini. */
167
- isActive(id) {
168
- return !!id && this.activeTrail().has(id);
169
- }
170
- readPersistedSidebarCollapsed() {
171
- try {
172
- const storage = this.doc.defaultView?.localStorage;
173
- const collapsed = parseSidebarCollapsed(storage?.getItem(SIDEBAR_COLLAPSE_STORAGE_KEY));
174
- if (collapsed !== null) {
175
- return collapsed;
176
- }
177
- const legacyAppearance = storage?.getItem(LEGACY_SIDEBAR_APPEARANCE_STORAGE_KEY);
178
- if (legacyAppearance === 'thin') {
179
- return true;
180
- }
181
- if (legacyAppearance === 'default') {
182
- return false;
183
- }
184
- return null;
185
- }
186
- catch {
187
- return null;
188
- }
189
- }
190
- persistSidebarCollapsed(value) {
191
- try {
192
- const storage = this.doc.defaultView?.localStorage;
193
- storage?.setItem(SIDEBAR_COLLAPSE_STORAGE_KEY, String(value));
194
- storage?.removeItem(LEGACY_SIDEBAR_APPEARANCE_STORAGE_KEY);
195
- }
196
- catch {
197
- /* ignore */
198
- }
199
- }
200
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: NavigationService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
201
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: NavigationService, providedIn: 'root' });
202
- }
203
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: NavigationService, decorators: [{
204
- type: Injectable,
205
- args: [{ providedIn: 'root' }]
206
- }], ctorParameters: () => [] });
207
-
208
- const MATERIAL_SYMBOLS_FONT_ATTR = 'data-ui-nav-icon-font';
209
- const MATERIAL_SYMBOLS_FONT_ID = 'material-symbols-outlined';
210
- const MATERIAL_SYMBOLS_FONT_HREF = 'https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@24,400,0,0';
211
- /**
212
- * Material Symbols icon renderer.
213
- * Menyuntikkan stylesheet font sekali saat dipakai agar consumer tidak perlu
214
- * menambahkan `<link>` manual di `index.html`.
215
- */
216
- class UiNavIconComponent {
217
- doc = inject(DOCUMENT);
218
- platformId = inject(PLATFORM_ID);
219
- name = input('', ...(ngDevMode ? [{ debugName: "name" }] : /* istanbul ignore next */ []));
220
- class = input('', ...(ngDevMode ? [{ debugName: "class" }] : /* istanbul ignore next */ []));
221
- size = input(null, ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
222
- fontVariationSettings = '"FILL" 0, "wght" 400, "GRAD" 0, "opsz" 24';
223
- constructor() {
224
- this.ensureFontStylesheet();
225
- }
226
- classes = computed(() => {
227
- const base = 'material-symbols-outlined inline-flex items-center justify-center leading-none select-none';
228
- const extra = this.class();
229
- return extra ? `${base} ${extra}` : base;
230
- }, ...(ngDevMode ? [{ debugName: "classes" }] : /* istanbul ignore next */ []));
231
- ensureFontStylesheet() {
232
- if (!isPlatformBrowser(this.platformId) || !this.doc.head)
233
- return;
234
- const existing = this.doc.head.querySelector(`link[${MATERIAL_SYMBOLS_FONT_ATTR}="${MATERIAL_SYMBOLS_FONT_ID}"]`);
235
- if (existing)
236
- return;
237
- const link = this.doc.createElement('link');
238
- link.rel = 'stylesheet';
239
- link.href = MATERIAL_SYMBOLS_FONT_HREF;
240
- link.setAttribute(MATERIAL_SYMBOLS_FONT_ATTR, MATERIAL_SYMBOLS_FONT_ID);
241
- this.doc.head.appendChild(link);
242
- }
243
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: UiNavIconComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
244
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.14", type: UiNavIconComponent, isStandalone: true, selector: "ui-nav-icon", inputs: { name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "aria-hidden": "true", "translate": "no" }, properties: { "class": "classes()", "style.font-size.px": "size()", "style.font-variation-settings": "fontVariationSettings" } }, ngImport: i0, template: `{{ name() }}`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
245
- }
246
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: UiNavIconComponent, decorators: [{
247
- type: Component,
248
- args: [{
249
- selector: 'ui-nav-icon',
250
- changeDetection: ChangeDetectionStrategy.OnPush,
251
- host: {
252
- '[class]': 'classes()',
253
- '[style.font-size.px]': 'size()',
254
- '[style.font-variation-settings]': 'fontVariationSettings',
255
- 'aria-hidden': 'true',
256
- translate: 'no',
257
- },
258
- template: `{{ name() }}`,
259
- }]
260
- }], ctorParameters: () => [], propDecorators: { name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }], class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }] } });
261
-
262
- /** Concatenate and dedupe Tailwind class names. */
263
- function cn(...inputs) {
264
- return twMerge(clsx(inputs));
265
- }
266
-
267
- /**
268
- * Recursive navigation item renderer (vertical context).
269
- *
270
- * Menerima item polymorphic dan delegasi ke template sesuai `type`.
271
- * Mega dirender sebagai group biasa saat muncul di konteks vertical.
272
- */
273
- class UiNavItemComponent {
274
- nav = inject(NavigationService);
275
- cn = cn;
276
- item = input.required(...(ngDevMode ? [{ debugName: "item" }] : /* istanbul ignore next */ []));
277
- level = input(0, ...(ngDevMode ? [{ debugName: "level" }] : /* istanbul ignore next */ []));
278
- /** Compact / icon-only rendering (sidebar `thin`). */
279
- compact = input(false, ...(ngDevMode ? [{ debugName: "compact" }] : /* istanbul ignore next */ []));
280
- /** True when this branch sits inside a collapsable rail and can draw a connector back to it. */
281
- railConnector = input(false, ...(ngDevMode ? [{ debugName: "railConnector" }] : /* istanbul ignore next */ []));
282
- railConnectorDotClasses = 'pointer-events-none absolute -left-[11px] top-1/2 z-10 h-1 w-1 -translate-x-1/2 -translate-y-1/2 rounded-full bg-foreground/80';
283
- exactMatch = {
284
- exact: true,
285
- paths: 'exact',
286
- queryParams: 'exact',
287
- fragment: 'exact',
288
- matrixParams: 'exact',
289
- };
290
- inexactMatch = {
291
- paths: 'subset',
292
- queryParams: 'subset',
293
- fragment: 'ignored',
294
- matrixParams: 'ignored',
295
- };
296
- type = computed(() => this.item().type, ...(ngDevMode ? [{ debugName: "type" }] : /* istanbul ignore next */ []));
297
- groupItem = computed(() => this.item(), ...(ngDevMode ? [{ debugName: "groupItem" }] : /* istanbul ignore next */ []));
298
- collapsableItem = computed(() => this.item(), ...(ngDevMode ? [{ debugName: "collapsableItem" }] : /* istanbul ignore next */ []));
299
- megaItem = computed(() => this.item(), ...(ngDevMode ? [{ debugName: "megaItem" }] : /* istanbul ignore next */ []));
300
- asideItem = computed(() => this.item(), ...(ngDevMode ? [{ debugName: "asideItem" }] : /* istanbul ignore next */ []));
301
- basicItem = computed(() => this.item(), ...(ngDevMode ? [{ debugName: "basicItem" }] : /* istanbul ignore next */ []));
302
- headingId = computed(() => {
303
- const id = this.item().id ?? '';
304
- return `nav-group-${id}`;
305
- }, ...(ngDevMode ? [{ debugName: "headingId" }] : /* istanbul ignore next */ []));
306
- isGroupOpen() {
307
- const id = this.item().id;
308
- if (!id)
309
- return false;
310
- // auto-open when any descendant is active
311
- if (this.nav.isActive(id) && 'children' in this.item())
312
- return true;
313
- return this.nav.isGroupOpen(id);
314
- }
315
- isTrailActive() {
316
- return this.nav.isActive(this.item().id);
317
- }
318
- railConnectorClasses(active) {
319
- if (!active || !this.railConnector())
320
- return '';
321
- return ('relative after:pointer-events-none after:absolute after:-left-3 after:top-1/2 after:z-0 after:h-px ' +
322
- "after:w-3 after:-translate-y-1/2 after:rounded-full after:bg-primary/30 after:content-['']");
323
- }
324
- showRailConnector(active) {
325
- return active && this.railConnector();
326
- }
327
- toggleGroup() {
328
- const id = this.item().id;
329
- if (id)
330
- this.nav.toggleGroup(id);
331
- }
332
- runAction() {
333
- const item = this.item();
334
- if ('action' in item && typeof item.action === 'function') {
335
- item.action(item);
336
- }
337
- }
338
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: UiNavItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
339
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: UiNavItemComponent, isStandalone: true, selector: "ui-nav-item", inputs: { item: { classPropertyName: "item", publicName: "item", isSignal: true, isRequired: true, transformFunction: null }, level: { classPropertyName: "level", publicName: "level", isSignal: true, isRequired: false, transformFunction: null }, compact: { classPropertyName: "compact", publicName: "compact", isSignal: true, isRequired: false, transformFunction: null }, railConnector: { classPropertyName: "railConnector", publicName: "railConnector", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
340
- @switch (type()) {
341
- @case ('divider') {
342
- <hr class="my-2 border-t border-border" role="separator" />
343
- }
344
- @case ('spacer') {
345
- <div class="flex-1"></div>
346
- }
347
- @case ('group') {
348
- <div role="group" [attr.aria-labelledby]="headingId()">
349
- @if (!compact()) {
350
- <div class="sticky top-0 z-10 p-3 text-muted-foreground backdrop-blur-3xl bg-transparent">
351
- <div [id]="headingId()" [class]="cn('ui-nav-heading text-muted-foreground', item().classes?.title)">
352
- {{ item().title }}
353
- </div>
354
- </div>
355
- }
356
- <div class="flex flex-col gap-0.5">
357
- @for (child of groupItem().children; track child.id) {
358
- <ui-nav-item
359
- [item]="child"
360
- [level]="level() + 1"
361
- [compact]="compact()"
362
- [railConnector]="railConnector()" />
363
- }
364
- </div>
365
- </div>
366
- }
367
- @case ('collapsable') {
368
- @let id = collapsableItem().id ?? '';
369
- @let open = isGroupOpen();
370
- @let active = isTrailActive();
371
- <button
372
- type="button"
373
- [class]="
374
- cn(
375
- 'ui-nav-text ui-nav-hover-surface group/ni flex w-full items-center gap-3 rounded p-3 text-foreground/80 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring',
376
- active && 'text-primary',
377
- railConnectorClasses(active),
378
- item().classes?.wrapper
379
- )
380
- "
381
- [attr.aria-expanded]="open"
382
- [attr.aria-controls]="id + '-panel'"
383
- [disabled]="collapsableItem().disabled || null"
384
- [matTooltip]="compact() ? (collapsableItem().title ?? '') : ''"
385
- matTooltipPosition="right"
386
- [matTooltipDisabled]="!compact()"
387
- (click)="toggleGroup()">
388
- @if (showRailConnector(active)) {
389
- <span aria-hidden="true" data-nav-rail-dot [class]="railConnectorDotClasses"></span>
390
- }
391
- @if (collapsableItem().icon) {
392
- <span
393
- [class]="
394
- cn(
395
- 'inline-flex shrink-0 items-center justify-center',
396
- open && 'h-7 w-7 rounded-full border border-brand'
397
- )
398
- ">
399
- <ui-nav-icon [name]="collapsableItem().icon!" [size]="18" [class]="item().classes?.icon ?? ''" />
400
- </span>
401
- }
402
- @if (!compact()) {
403
- <span [class]="cn('flex-1 truncate text-left', item().classes?.title)">
404
- {{ collapsableItem().title }}
405
- </span>
406
- @if (collapsableItem().badge; as badge) {
407
- <span [class]="badge.classes ?? 'ui-nav-badge ml-auto'">{{ badge.title }}</span>
408
- }
409
- <ui-nav-icon
410
- [name]="'chevron_right'"
411
- [size]="18"
412
- [class]="cn('transition-transform duration-200', open && 'rotate-90')" />
413
- }
414
- </button>
415
- @if (!compact() && open) {
416
- <div
417
- [id]="id + '-panel'"
418
- role="region"
419
- class="relative ml-6.5 mt-0.5 flex flex-col gap-0.5 pl-3 before:absolute before:bottom-0 before:left-0 before:-top-3.5 before:w-px before:bg-primary/30 before:content-['']">
420
- @for (child of collapsableItem().children; track child.id) {
421
- <ui-nav-item [item]="child" [level]="level() + 1" [compact]="false" [railConnector]="true" />
422
- }
423
- </div>
424
- }
425
- }
426
- @case ('mega') {
427
- <!-- Mega direndahkan ke group saat berada di sidebar vertical. -->
428
- <div class="mt-4 py-3 first:mt-0" role="group">
429
- @if (!compact()) {
430
- <div class="ui-nav-heading sticky top-0 z-10 bg-background px-3 pb-1 text-muted-foreground">
431
- {{ item().title }}
432
- </div>
433
- }
434
- <div class="flex flex-col gap-0.5">
435
- @for (child of megaItem().children; track child.id) {
436
- <ui-nav-item
437
- [item]="child"
438
- [level]="level() + 1"
439
- [compact]="compact()"
440
- [railConnector]="railConnector()" />
441
- }
442
- </div>
443
- </div>
444
- }
445
- @case ('aside') {
446
- <a
447
- [class]="
448
- cn(
449
- 'ui-nav-text ui-nav-hover-surface flex items-center gap-3 rounded px-3 py-2 text-foreground/80 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring aria-[current=page]:text-primary',
450
- railConnectorClasses(rla.isActive),
451
- item().classes?.wrapper
452
- )
453
- "
454
- routerLinkActive="text-primary"
455
- #rla="routerLinkActive"
456
- [attr.aria-current]="rla.isActive ? 'page' : null"
457
- [routerLink]="asideItem().link"
458
- [queryParams]="asideItem().queryParams"
459
- [fragment]="asideItem().fragment ?? undefined"
460
- [target]="asideItem().target ?? undefined"
461
- [matTooltip]="compact() ? (asideItem().title ?? '') : ''"
462
- matTooltipPosition="right"
463
- [matTooltipDisabled]="!compact()">
464
- @if (showRailConnector(rla.isActive)) {
465
- <span aria-hidden="true" data-nav-rail-dot [class]="railConnectorDotClasses"></span>
466
- }
467
- @if (asideItem().icon) {
468
- <ui-nav-icon [name]="asideItem().icon!" [size]="18" />
469
- }
470
- @if (!compact()) {
471
- <span class="flex-1 truncate">{{ asideItem().title }}</span>
472
- }
473
- </a>
474
- }
475
- @default {
476
- <!-- basic -->
477
- @if (basicItem().link && !basicItem().externalLink) {
478
- <a
479
- [class]="
480
- cn(
481
- 'ui-nav-text ui-nav-hover-surface flex items-center gap-3 rounded px-3 py-2 text-foreground/80 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring aria-[current=page]:text-primary aria-disabled:pointer-events-none aria-disabled:opacity-50',
482
- railConnectorClasses(rla.isActive),
483
- item().classes?.wrapper
484
- )
485
- "
486
- routerLinkActive="text-primary"
487
- #rla="routerLinkActive"
488
- [routerLinkActiveOptions]="
489
- basicItem().isActiveMatchOptions ?? (basicItem().exactMatch ? exactMatch : inexactMatch)
490
- "
491
- [attr.aria-current]="rla.isActive ? 'page' : null"
492
- [attr.aria-disabled]="basicItem().disabled || null"
493
- [matTooltip]="compact() ? (basicItem().title ?? '') : ''"
494
- matTooltipPosition="right"
495
- [matTooltipDisabled]="!compact()"
496
- [routerLink]="basicItem().link"
497
- [queryParams]="basicItem().queryParams"
498
- [queryParamsHandling]="basicItem().queryParamsHandling ?? null"
499
- [fragment]="basicItem().fragment ?? undefined"
500
- [preserveFragment]="basicItem().preserveFragment ?? false"
501
- [target]="basicItem().target ?? undefined"
502
- (click)="runAction()">
503
- @if (showRailConnector(rla.isActive)) {
504
- <span aria-hidden="true" data-nav-rail-dot [class]="railConnectorDotClasses"></span>
505
- }
506
- @if (basicItem().icon) {
507
- <ui-nav-icon [name]="basicItem().icon!" [size]="18" [class]="item().classes?.icon ?? ''" />
508
- }
509
- @if (!compact()) {
510
- <span [class]="cn('flex-1 truncate', item().classes?.title)">{{ basicItem().title }}</span>
511
- @if (basicItem().badge; as badge) {
512
- <span [class]="badge.classes ?? 'ui-nav-badge ml-auto'">{{ badge.title }}</span>
513
- }
514
- }
515
- </a>
516
- } @else if (basicItem().link && basicItem().externalLink) {
517
- <a
518
- [class]="
519
- cn(
520
- 'ui-nav-text ui-nav-hover-surface flex items-center gap-3 rounded px-3 py-2 text-foreground/80 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring',
521
- item().classes?.wrapper
522
- )
523
- "
524
- [attr.href]="basicItem().link"
525
- [attr.target]="basicItem().target ?? '_blank'"
526
- rel="noopener noreferrer"
527
- [matTooltip]="compact() ? (basicItem().title ?? '') : ''"
528
- matTooltipPosition="right"
529
- [matTooltipDisabled]="!compact()">
530
- @if (basicItem().icon) {
531
- <ui-nav-icon [name]="basicItem().icon!" [size]="18" />
532
- }
533
- @if (!compact()) {
534
- <span class="flex-1 truncate">{{ basicItem().title }}</span>
535
- }
536
- </a>
537
- } @else {
538
- <button
539
- type="button"
540
- [class]="
541
- cn(
542
- 'ui-nav-text ui-nav-hover-surface flex w-full items-center gap-3 rounded px-3 py-2 text-left text-foreground/80 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50',
543
- item().classes?.wrapper
544
- )
545
- "
546
- [disabled]="basicItem().disabled || null"
547
- [matTooltip]="compact() ? (basicItem().title ?? '') : ''"
548
- matTooltipPosition="right"
549
- [matTooltipDisabled]="!compact()"
550
- (click)="runAction()">
551
- @if (basicItem().icon) {
552
- <ui-nav-icon [name]="basicItem().icon!" [size]="18" />
553
- }
554
- @if (!compact()) {
555
- <span class="flex-1 truncate">{{ basicItem().title }}</span>
556
- }
557
- </button>
558
- }
559
- }
560
- }
561
- `, isInline: true, dependencies: [{ kind: "component", type: UiNavItemComponent, selector: "ui-nav-item", inputs: ["item", "level", "compact", "railConnector"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: RouterLinkActive, selector: "[routerLinkActive]", inputs: ["routerLinkActiveOptions", "ariaCurrentWhenActive", "routerLinkActive"], outputs: ["isActiveChange"], exportAs: ["routerLinkActive"] }, { kind: "directive", type: MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: UiNavIconComponent, selector: "ui-nav-icon", inputs: ["name", "class", "size"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
562
- }
563
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: UiNavItemComponent, decorators: [{
564
- type: Component,
565
- args: [{
566
- selector: 'ui-nav-item',
567
- changeDetection: ChangeDetectionStrategy.OnPush,
568
- imports: [RouterLink, RouterLinkActive, MatTooltip, UiNavIconComponent],
569
- template: `
570
- @switch (type()) {
571
- @case ('divider') {
572
- <hr class="my-2 border-t border-border" role="separator" />
573
- }
574
- @case ('spacer') {
575
- <div class="flex-1"></div>
576
- }
577
- @case ('group') {
578
- <div role="group" [attr.aria-labelledby]="headingId()">
579
- @if (!compact()) {
580
- <div class="sticky top-0 z-10 p-3 text-muted-foreground backdrop-blur-3xl bg-transparent">
581
- <div [id]="headingId()" [class]="cn('ui-nav-heading text-muted-foreground', item().classes?.title)">
582
- {{ item().title }}
583
- </div>
584
- </div>
585
- }
586
- <div class="flex flex-col gap-0.5">
587
- @for (child of groupItem().children; track child.id) {
588
- <ui-nav-item
589
- [item]="child"
590
- [level]="level() + 1"
591
- [compact]="compact()"
592
- [railConnector]="railConnector()" />
593
- }
594
- </div>
595
- </div>
596
- }
597
- @case ('collapsable') {
598
- @let id = collapsableItem().id ?? '';
599
- @let open = isGroupOpen();
600
- @let active = isTrailActive();
601
- <button
602
- type="button"
603
- [class]="
604
- cn(
605
- 'ui-nav-text ui-nav-hover-surface group/ni flex w-full items-center gap-3 rounded p-3 text-foreground/80 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring',
606
- active && 'text-primary',
607
- railConnectorClasses(active),
608
- item().classes?.wrapper
609
- )
610
- "
611
- [attr.aria-expanded]="open"
612
- [attr.aria-controls]="id + '-panel'"
613
- [disabled]="collapsableItem().disabled || null"
614
- [matTooltip]="compact() ? (collapsableItem().title ?? '') : ''"
615
- matTooltipPosition="right"
616
- [matTooltipDisabled]="!compact()"
617
- (click)="toggleGroup()">
618
- @if (showRailConnector(active)) {
619
- <span aria-hidden="true" data-nav-rail-dot [class]="railConnectorDotClasses"></span>
620
- }
621
- @if (collapsableItem().icon) {
622
- <span
623
- [class]="
624
- cn(
625
- 'inline-flex shrink-0 items-center justify-center',
626
- open && 'h-7 w-7 rounded-full border border-brand'
627
- )
628
- ">
629
- <ui-nav-icon [name]="collapsableItem().icon!" [size]="18" [class]="item().classes?.icon ?? ''" />
630
- </span>
631
- }
632
- @if (!compact()) {
633
- <span [class]="cn('flex-1 truncate text-left', item().classes?.title)">
634
- {{ collapsableItem().title }}
635
- </span>
636
- @if (collapsableItem().badge; as badge) {
637
- <span [class]="badge.classes ?? 'ui-nav-badge ml-auto'">{{ badge.title }}</span>
638
- }
639
- <ui-nav-icon
640
- [name]="'chevron_right'"
641
- [size]="18"
642
- [class]="cn('transition-transform duration-200', open && 'rotate-90')" />
643
- }
644
- </button>
645
- @if (!compact() && open) {
646
- <div
647
- [id]="id + '-panel'"
648
- role="region"
649
- class="relative ml-6.5 mt-0.5 flex flex-col gap-0.5 pl-3 before:absolute before:bottom-0 before:left-0 before:-top-3.5 before:w-px before:bg-primary/30 before:content-['']">
650
- @for (child of collapsableItem().children; track child.id) {
651
- <ui-nav-item [item]="child" [level]="level() + 1" [compact]="false" [railConnector]="true" />
652
- }
653
- </div>
654
- }
655
- }
656
- @case ('mega') {
657
- <!-- Mega direndahkan ke group saat berada di sidebar vertical. -->
658
- <div class="mt-4 py-3 first:mt-0" role="group">
659
- @if (!compact()) {
660
- <div class="ui-nav-heading sticky top-0 z-10 bg-background px-3 pb-1 text-muted-foreground">
661
- {{ item().title }}
662
- </div>
663
- }
664
- <div class="flex flex-col gap-0.5">
665
- @for (child of megaItem().children; track child.id) {
666
- <ui-nav-item
667
- [item]="child"
668
- [level]="level() + 1"
669
- [compact]="compact()"
670
- [railConnector]="railConnector()" />
671
- }
672
- </div>
673
- </div>
674
- }
675
- @case ('aside') {
676
- <a
677
- [class]="
678
- cn(
679
- 'ui-nav-text ui-nav-hover-surface flex items-center gap-3 rounded px-3 py-2 text-foreground/80 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring aria-[current=page]:text-primary',
680
- railConnectorClasses(rla.isActive),
681
- item().classes?.wrapper
682
- )
683
- "
684
- routerLinkActive="text-primary"
685
- #rla="routerLinkActive"
686
- [attr.aria-current]="rla.isActive ? 'page' : null"
687
- [routerLink]="asideItem().link"
688
- [queryParams]="asideItem().queryParams"
689
- [fragment]="asideItem().fragment ?? undefined"
690
- [target]="asideItem().target ?? undefined"
691
- [matTooltip]="compact() ? (asideItem().title ?? '') : ''"
692
- matTooltipPosition="right"
693
- [matTooltipDisabled]="!compact()">
694
- @if (showRailConnector(rla.isActive)) {
695
- <span aria-hidden="true" data-nav-rail-dot [class]="railConnectorDotClasses"></span>
696
- }
697
- @if (asideItem().icon) {
698
- <ui-nav-icon [name]="asideItem().icon!" [size]="18" />
699
- }
700
- @if (!compact()) {
701
- <span class="flex-1 truncate">{{ asideItem().title }}</span>
702
- }
703
- </a>
704
- }
705
- @default {
706
- <!-- basic -->
707
- @if (basicItem().link && !basicItem().externalLink) {
708
- <a
709
- [class]="
710
- cn(
711
- 'ui-nav-text ui-nav-hover-surface flex items-center gap-3 rounded px-3 py-2 text-foreground/80 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring aria-[current=page]:text-primary aria-disabled:pointer-events-none aria-disabled:opacity-50',
712
- railConnectorClasses(rla.isActive),
713
- item().classes?.wrapper
714
- )
715
- "
716
- routerLinkActive="text-primary"
717
- #rla="routerLinkActive"
718
- [routerLinkActiveOptions]="
719
- basicItem().isActiveMatchOptions ?? (basicItem().exactMatch ? exactMatch : inexactMatch)
720
- "
721
- [attr.aria-current]="rla.isActive ? 'page' : null"
722
- [attr.aria-disabled]="basicItem().disabled || null"
723
- [matTooltip]="compact() ? (basicItem().title ?? '') : ''"
724
- matTooltipPosition="right"
725
- [matTooltipDisabled]="!compact()"
726
- [routerLink]="basicItem().link"
727
- [queryParams]="basicItem().queryParams"
728
- [queryParamsHandling]="basicItem().queryParamsHandling ?? null"
729
- [fragment]="basicItem().fragment ?? undefined"
730
- [preserveFragment]="basicItem().preserveFragment ?? false"
731
- [target]="basicItem().target ?? undefined"
732
- (click)="runAction()">
733
- @if (showRailConnector(rla.isActive)) {
734
- <span aria-hidden="true" data-nav-rail-dot [class]="railConnectorDotClasses"></span>
735
- }
736
- @if (basicItem().icon) {
737
- <ui-nav-icon [name]="basicItem().icon!" [size]="18" [class]="item().classes?.icon ?? ''" />
738
- }
739
- @if (!compact()) {
740
- <span [class]="cn('flex-1 truncate', item().classes?.title)">{{ basicItem().title }}</span>
741
- @if (basicItem().badge; as badge) {
742
- <span [class]="badge.classes ?? 'ui-nav-badge ml-auto'">{{ badge.title }}</span>
743
- }
744
- }
745
- </a>
746
- } @else if (basicItem().link && basicItem().externalLink) {
747
- <a
748
- [class]="
749
- cn(
750
- 'ui-nav-text ui-nav-hover-surface flex items-center gap-3 rounded px-3 py-2 text-foreground/80 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring',
751
- item().classes?.wrapper
752
- )
753
- "
754
- [attr.href]="basicItem().link"
755
- [attr.target]="basicItem().target ?? '_blank'"
756
- rel="noopener noreferrer"
757
- [matTooltip]="compact() ? (basicItem().title ?? '') : ''"
758
- matTooltipPosition="right"
759
- [matTooltipDisabled]="!compact()">
760
- @if (basicItem().icon) {
761
- <ui-nav-icon [name]="basicItem().icon!" [size]="18" />
762
- }
763
- @if (!compact()) {
764
- <span class="flex-1 truncate">{{ basicItem().title }}</span>
765
- }
766
- </a>
767
- } @else {
768
- <button
769
- type="button"
770
- [class]="
771
- cn(
772
- 'ui-nav-text ui-nav-hover-surface flex w-full items-center gap-3 rounded px-3 py-2 text-left text-foreground/80 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50',
773
- item().classes?.wrapper
774
- )
775
- "
776
- [disabled]="basicItem().disabled || null"
777
- [matTooltip]="compact() ? (basicItem().title ?? '') : ''"
778
- matTooltipPosition="right"
779
- [matTooltipDisabled]="!compact()"
780
- (click)="runAction()">
781
- @if (basicItem().icon) {
782
- <ui-nav-icon [name]="basicItem().icon!" [size]="18" />
783
- }
784
- @if (!compact()) {
785
- <span class="flex-1 truncate">{{ basicItem().title }}</span>
786
- }
787
- </button>
788
- }
789
- }
790
- }
791
- `,
792
- }]
793
- }], propDecorators: { item: [{ type: i0.Input, args: [{ isSignal: true, alias: "item", required: true }] }], level: [{ type: i0.Input, args: [{ isSignal: true, alias: "level", required: false }] }], compact: [{ type: i0.Input, args: [{ isSignal: true, alias: "compact", required: false }] }], railConnector: [{ type: i0.Input, args: [{ isSignal: true, alias: "railConnector", required: false }] }] } });
794
-
795
- /**
796
- * Vertical navigation (sidebar) — shadcn-styled.
797
- *
798
- * Variants:
799
- * - `default`: 17.5rem, label + icon
800
- * - `thin`: 4rem icon-only; hover memunculkan overlay expand (tidak push konten)
801
- *
802
- * Mobile (`< md`): saat `autoMobile=true` (default), host desktop disembunyikan
803
- * dan konten dirender lewat CDK Overlay drawer dengan focus trap. State buka
804
- * dikontrol lewat `NavigationService.mobileOpen`.
805
- */
806
- class SidebarComponent {
807
- nav = inject(NavigationService);
808
- bp = inject(BreakpointObserver);
809
- overlay = inject(Overlay);
810
- vcr = inject(ViewContainerRef);
811
- focusTrapFactory = inject(FocusTrapFactory);
812
- doc = inject(DOCUMENT);
813
- destroyRef = inject(DestroyRef);
814
- items = input([], ...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
815
- /** Registry key di `NavigationService`. Default `'main'`. */
816
- navigationId = input(DEFAULT_NAVIGATION_ID, ...(ngDevMode ? [{ debugName: "navigationId" }] : /* istanbul ignore next */ []));
817
- appearance = input('default', ...(ngDevMode ? [{ debugName: "appearance" }] : /* istanbul ignore next */ []));
818
- /** Desktop border can be owned by the sidebar or by the surrounding layout shell. */
819
- borderSource = input('component', ...(ngDevMode ? [{ debugName: "borderSource" }] : /* istanbul ignore next */ []));
820
- position = input('left', ...(ngDevMode ? [{ debugName: "position" }] : /* istanbul ignore next */ []));
821
- ariaLabel = input('Primary', ...(ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
822
- header = input(true, ...(ngDevMode ? [{ debugName: "header" }] : /* istanbul ignore next */ []));
823
- class = input('', ...(ngDevMode ? [{ debugName: "class" }] : /* istanbul ignore next */ []));
824
- /** Auto switch ke CDK overlay drawer saat viewport `< md`. */
825
- autoMobile = input(true, ...(ngDevMode ? [{ debugName: "autoMobile" }] : /* istanbul ignore next */ []));
826
- /** Auto-register `items` ke `NavigationService` agar `activeTrail` bekerja. */
827
- autoRegister = input(true, ...(ngDevMode ? [{ debugName: "autoRegister" }] : /* istanbul ignore next */ []));
828
- /** Resolved items: input jika disediakan, fallback ke registry NavigationService. */
829
- resolvedItems = computed(() => {
830
- const explicit = this.items();
831
- return explicit.length > 0 ? explicit : this.nav.getItems(this.navigationId())();
832
- }, ...(ngDevMode ? [{ debugName: "resolvedItems" }] : /* istanbul ignore next */ []));
833
- hovered = signal(false, ...(ngDevMode ? [{ debugName: "hovered" }] : /* istanbul ignore next */ []));
834
- suppressHoverUntilLeave = signal(false, ...(ngDevMode ? [{ debugName: "suppressHoverUntilLeave" }] : /* istanbul ignore next */ []));
835
- drawerTpl = viewChild.required('drawerTpl');
836
- drawerRef = null;
837
- focusTrap = null;
838
- previouslyFocused = null;
839
- /** True saat viewport `< md` (767.98px). */
840
- isMobileMedia = toSignal(this.bp.observe('(max-width: 767.98px)').pipe(map((s) => s.matches)), {
841
- initialValue: false,
842
- });
843
- isMobile = computed(() => this.autoMobile() && this.isMobileMedia(), ...(ngDevMode ? [{ debugName: "isMobile" }] : /* istanbul ignore next */ []));
844
- resolvedCollapsed = computed(() => {
845
- if (this.nav.hasStoredSidebarCollapse()) {
846
- return this.nav.collapsed();
847
- }
848
- return this.appearance() === 'thin';
849
- }, ...(ngDevMode ? [{ debugName: "resolvedCollapsed" }] : /* istanbul ignore next */ []));
850
- resolvedAppearance = computed(() => {
851
- return this.resolvedCollapsed() ? 'thin' : 'default';
852
- }, ...(ngDevMode ? [{ debugName: "resolvedAppearance" }] : /* istanbul ignore next */ []));
853
- hoverActive = computed(() => this.hovered() && !this.suppressHoverUntilLeave(), ...(ngDevMode ? [{ debugName: "hoverActive" }] : /* istanbul ignore next */ []));
854
- isExpanded = computed(() => !this.resolvedCollapsed() || this.hoverActive(), ...(ngDevMode ? [{ debugName: "isExpanded" }] : /* istanbul ignore next */ []));
855
- isCompact = computed(() => !this.isMobile() && this.resolvedCollapsed() && !this.hoverActive(), ...(ngDevMode ? [{ debugName: "isCompact" }] : /* istanbul ignore next */ []));
856
- toggleButtonLabel = computed(() => this.resolvedCollapsed() ? 'Expand sidebar' : 'Collapse sidebar', ...(ngDevMode ? [{ debugName: "toggleButtonLabel" }] : /* istanbul ignore next */ []));
857
- constructor() {
858
- // Auto-register items ke service untuk active trail (hanya jika input non-kosong).
859
- effect(() => {
860
- const explicit = this.items();
861
- if (this.autoRegister() && explicit.length > 0)
862
- this.nav.registerItems(this.navigationId(), explicit);
863
- });
864
- // Kelola overlay drawer berdasarkan mobileOpen + isMobile.
865
- effect(() => {
866
- const open = this.nav.mobileOpen();
867
- const mobile = this.isMobile();
868
- if (mobile && open)
869
- this.openDrawer();
870
- else
871
- this.closeDrawer();
872
- });
873
- this.destroyRef.onDestroy(() => this.closeDrawer());
874
- }
875
- hostClasses = computed(() => {
876
- const base = ['relative flex shrink-0 text-foreground', 'transition-[width] duration-200 ease-out'];
877
- if (this.resolvedCollapsed())
878
- base.push('w-16');
879
- else
880
- base.push('[width:17.5rem]');
881
- if (this.borderSource() === 'component') {
882
- if (this.position() === 'right')
883
- base.push('border-l', 'border-primary/30');
884
- else
885
- base.push('border-r', 'border-primary/30');
886
- }
887
- return [...base, this.class()].join(' ');
888
- }, ...(ngDevMode ? [{ debugName: "hostClasses" }] : /* istanbul ignore next */ []));
889
- headerClasses = computed(() => {
890
- const base = ['flex items-center gap-1 border-b border-primary/30'];
891
- if (this.isCompact()) {
892
- base.push('h-12', 'justify-center', 'px-2');
893
- }
894
- else {
895
- base.push('h-12', 'pr-2');
896
- }
897
- return base.join(' ');
898
- }, ...(ngDevMode ? [{ debugName: "headerClasses" }] : /* istanbul ignore next */ []));
899
- headerSlotClasses = computed(() => {
900
- const base = ['min-w-0'];
901
- if (this.isCompact()) {
902
- base.push('flex flex-1 items-center justify-center overflow-hidden', '[&>[sidebar-header]>*]:mx-auto', '[&>[sidebar-header]>*]:w-auto', '[&>[sidebar-header]>*]:max-w-full', '[&>[sidebar-header]>*]:justify-center', '[&>[sidebar-header]>*]:gap-0', '[&>[sidebar-header]>*]:px-0', '[&>[sidebar-header]>*]:shrink-0', '[&>[sidebar-header]>*>*:first-child]:mx-auto', '[&>[sidebar-header]>*>*:nth-child(n+2)]:hidden');
903
- }
904
- else {
905
- base.push('flex min-w-0 flex-1 items-center');
906
- }
907
- return base.join(' ');
908
- }, ...(ngDevMode ? [{ debugName: "headerSlotClasses" }] : /* istanbul ignore next */ []));
909
- navClasses = computed(() => {
910
- const base = ['min-h-full'];
911
- if (this.isCompact()) {
912
- base.push('px-2', '[&_.ui-nav-text]:mx-auto', '[&_.ui-nav-text]:w-10', '[&_.ui-nav-text]:justify-center', '[&_.ui-nav-text]:px-0');
913
- }
914
- return base.join(' ');
915
- }, ...(ngDevMode ? [{ debugName: "navClasses" }] : /* istanbul ignore next */ []));
916
- scrollViewportClasses = computed(() => 'overflow-y-auto overflow-x-hidden scrollbar-thin scrollbar-thumb-primary scrollbar-track-primary/10', ...(ngDevMode ? [{ debugName: "scrollViewportClasses" }] : /* istanbul ignore next */ []));
917
- footerClasses = computed(() => {
918
- const base = ['h-12 border-t border-primary/30'];
919
- if (this.isCompact()) {
920
- base.push('flex items-center justify-center px-2');
921
- }
922
- return base.join(' ');
923
- }, ...(ngDevMode ? [{ debugName: "footerClasses" }] : /* istanbul ignore next */ []));
924
- footerSlotClasses = computed(() => {
925
- const base = ['h-full'];
926
- if (this.isCompact()) {
927
- base.push('flex h-full items-center justify-center overflow-hidden', '[&>[sidebar-footer]>*]:mx-auto', '[&>[sidebar-footer]>*]:w-auto', '[&>[sidebar-footer]>*]:max-w-full', '[&>[sidebar-footer]>*]:justify-center', '[&>[sidebar-footer]>*]:gap-0', '[&>[sidebar-footer]>*]:px-0', '[&>[sidebar-footer]>*>*:first-child]:mx-auto', '[&>[sidebar-footer]>*>*:nth-child(n+2)]:hidden');
928
- }
929
- else {
930
- base.push('w-full');
931
- }
932
- return base.join(' ');
933
- }, ...(ngDevMode ? [{ debugName: "footerSlotClasses" }] : /* istanbul ignore next */ []));
934
- innerClasses = computed(() => {
935
- const overlayActive = this.resolvedCollapsed() && this.hoverActive();
936
- const base = ['flex h-full flex-col transition-[width] duration-200 ease-out'];
937
- if (this.resolvedCollapsed()) {
938
- base.push('bg-background');
939
- }
940
- if (overlayActive) {
941
- base.push('absolute inset-y-0 z-30 border-l border-r border-primary/30 shadow-xl [width:17.5rem]', this.position() === 'right' ? 'right-0' : 'left-0');
942
- }
943
- else {
944
- base.push('w-full');
945
- }
946
- return base.join(' ');
947
- }, ...(ngDevMode ? [{ debugName: "innerClasses" }] : /* istanbul ignore next */ []));
948
- onHoverEnter() {
949
- if (!this.resolvedCollapsed() || this.isMobile() || this.suppressHoverUntilLeave())
950
- return;
951
- this.hovered.set(true);
952
- }
953
- onHoverLeave() {
954
- this.suppressHoverUntilLeave.set(false);
955
- if (this.resolvedCollapsed())
956
- this.hovered.set(false);
957
- }
958
- toggleAppearance(event) {
959
- event.stopPropagation();
960
- const nextCollapsed = !this.resolvedCollapsed();
961
- this.nav.setCollapsed(nextCollapsed);
962
- this.hovered.set(false);
963
- this.suppressHoverUntilLeave.set(nextCollapsed);
964
- }
965
- /** Touch fallback: tap pada strip thin (ketika belum expanded) untuk expand. */
966
- onHostClick(event) {
967
- if (!this.resolvedCollapsed() || this.isMobile())
968
- return;
969
- if (this.hovered())
970
- return;
971
- const target = event.target;
972
- // Biarkan klik pada control interaktif terus propagate (tidak intercept).
973
- if (target && target.closest('a,button,[role="menuitem"]'))
974
- return;
975
- this.hovered.set(true);
976
- }
977
- openDrawer() {
978
- if (this.drawerRef)
979
- return;
980
- const side = this.position();
981
- const pos = this.overlay.position().global().top('0');
982
- if (side === 'right')
983
- pos.right('0');
984
- else
985
- pos.left('0');
986
- this.drawerRef = this.overlay.create({
987
- positionStrategy: pos,
988
- height: '100vh',
989
- hasBackdrop: true,
990
- backdropClass: 'cdk-overlay-dark-backdrop',
991
- scrollStrategy: this.overlay.scrollStrategies.block(),
992
- panelClass: ['sidebar-drawer'],
993
- });
994
- const portal = new TemplatePortal(this.drawerTpl(), this.vcr);
995
- const viewRef = this.drawerRef.attach(portal);
996
- viewRef.detectChanges();
997
- const root = this.drawerRef.overlayElement;
998
- this.focusTrap = this.focusTrapFactory.create(root);
999
- this.previouslyFocused = this.doc.activeElement;
1000
- queueMicrotask(() => this.focusTrap?.focusInitialElementWhenReady());
1001
- this.drawerRef
1002
- .backdropClick()
1003
- .pipe(takeUntilDestroyed(this.destroyRef))
1004
- .subscribe(() => this.nav.closeMobile());
1005
- this.drawerRef
1006
- .keydownEvents()
1007
- .pipe(filter((e) => e.key === 'Escape'), takeUntilDestroyed(this.destroyRef))
1008
- .subscribe(() => this.nav.closeMobile());
1009
- }
1010
- closeDrawer() {
1011
- if (!this.drawerRef)
1012
- return;
1013
- this.focusTrap?.destroy();
1014
- this.focusTrap = null;
1015
- this.drawerRef.dispose();
1016
- this.drawerRef = null;
1017
- this.previouslyFocused?.focus?.();
1018
- this.previouslyFocused = null;
1019
- }
1020
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: SidebarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1021
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: SidebarComponent, isStandalone: true, selector: "sidebar", inputs: { items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: false, transformFunction: null }, navigationId: { classPropertyName: "navigationId", publicName: "navigationId", isSignal: true, isRequired: false, transformFunction: null }, appearance: { classPropertyName: "appearance", publicName: "appearance", isSignal: true, isRequired: false, transformFunction: null }, borderSource: { classPropertyName: "borderSource", publicName: "borderSource", isSignal: true, isRequired: false, transformFunction: null }, position: { classPropertyName: "position", publicName: "position", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, header: { classPropertyName: "header", publicName: "header", isSignal: true, isRequired: false, transformFunction: null }, class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null }, autoMobile: { classPropertyName: "autoMobile", publicName: "autoMobile", isSignal: true, isRequired: false, transformFunction: null }, autoRegister: { classPropertyName: "autoRegister", publicName: "autoRegister", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "navigation" }, listeners: { "mouseenter": "onHoverEnter()", "mouseleave": "onHoverLeave()", "focusin": "onHoverEnter()", "click": "onHostClick($event)" }, properties: { "attr.aria-label": "ariaLabel()", "class": "hostClasses()", "attr.data-appearance": "resolvedAppearance()", "attr.data-position": "position()", "attr.data-expanded": "isExpanded()", "hidden": "isMobile()" } }, viewQueries: [{ propertyName: "drawerTpl", first: true, predicate: ["drawerTpl"], descendants: true, isSignal: true }], ngImport: i0, template: `
1022
- <div [class]="innerClasses()">
1023
- <ng-container [ngTemplateOutlet]="body" />
1024
- </div>
1025
-
1026
- <ng-template #body>
1027
- @if (header()) {
1028
- <div [class]="headerClasses()">
1029
- <div [class]="headerSlotClasses()">
1030
- <ng-content select="[sidebar-header]" />
1031
- </div>
1032
- @if (!isMobile() && !isCompact()) {
1033
- <button
1034
- type="button"
1035
- data-sidebar-toggle
1036
- class="inline-flex h-9 w-9 shrink-0 items-center justify-center rounded-lg text-muted-foreground transition-colors hover:bg-muted/50 hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background"
1037
- [attr.aria-label]="toggleButtonLabel()"
1038
- [attr.title]="toggleButtonLabel()"
1039
- [attr.aria-pressed]="resolvedAppearance() === 'thin'"
1040
- (click)="toggleAppearance($event)">
1041
- <ui-nav-icon name="view_sidebar" [size]="18" class="text-current" />
1042
- </button>
1043
- }
1044
- </div>
1045
- }
1046
- <ui-scroll-area class="min-h-0 flex-1" [viewportClass]="scrollViewportClasses()">
1047
- <nav [class]="navClasses()">
1048
- @for (item of resolvedItems(); track item.id) {
1049
- <ui-nav-item [item]="item" [compact]="isCompact()" />
1050
- }
1051
- </nav>
1052
- </ui-scroll-area>
1053
- <div [class]="footerClasses()">
1054
- <div [class]="footerSlotClasses()">
1055
- <ng-content select="[sidebar-footer]" />
1056
- </div>
1057
- </div>
1058
- </ng-template>
1059
-
1060
- <ng-template #drawerTpl>
1061
- <div
1062
- role="dialog"
1063
- aria-modal="true"
1064
- [attr.aria-label]="ariaLabel()"
1065
- class="flex h-full w-72 max-w-[85vw] flex-col border-primary/30 text-foreground shadow-xl"
1066
- [class.border-r]="position() === 'left'"
1067
- [class.border-l]="position() === 'right'"
1068
- [class.border-primary/30]="position() === 'left' || position() === 'right'">
1069
- <ng-container [ngTemplateOutlet]="body" />
1070
- </div>
1071
- </ng-template>
1072
- `, isInline: true, dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: ScrollAreaComponent, selector: "ui-scroll-area", inputs: ["class", "viewportClass", "viewportAriaLabel", "viewportTabIndex"] }, { kind: "component", type: UiNavIconComponent, selector: "ui-nav-icon", inputs: ["name", "class", "size"] }, { kind: "component", type: UiNavItemComponent, selector: "ui-nav-item", inputs: ["item", "level", "compact", "railConnector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1073
- }
1074
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: SidebarComponent, decorators: [{
1075
- type: Component,
1076
- args: [{
1077
- selector: 'sidebar',
1078
- changeDetection: ChangeDetectionStrategy.OnPush,
1079
- imports: [NgTemplateOutlet, ScrollAreaComponent, UiNavIconComponent, UiNavItemComponent],
1080
- host: {
1081
- role: 'navigation',
1082
- '[attr.aria-label]': 'ariaLabel()',
1083
- '[class]': 'hostClasses()',
1084
- '[attr.data-appearance]': 'resolvedAppearance()',
1085
- '[attr.data-position]': 'position()',
1086
- '[attr.data-expanded]': 'isExpanded()',
1087
- '[hidden]': 'isMobile()',
1088
- '(mouseenter)': 'onHoverEnter()',
1089
- '(mouseleave)': 'onHoverLeave()',
1090
- '(focusin)': 'onHoverEnter()',
1091
- '(click)': 'onHostClick($event)',
1092
- },
1093
- template: `
1094
- <div [class]="innerClasses()">
1095
- <ng-container [ngTemplateOutlet]="body" />
1096
- </div>
1097
-
1098
- <ng-template #body>
1099
- @if (header()) {
1100
- <div [class]="headerClasses()">
1101
- <div [class]="headerSlotClasses()">
1102
- <ng-content select="[sidebar-header]" />
1103
- </div>
1104
- @if (!isMobile() && !isCompact()) {
1105
- <button
1106
- type="button"
1107
- data-sidebar-toggle
1108
- class="inline-flex h-9 w-9 shrink-0 items-center justify-center rounded-lg text-muted-foreground transition-colors hover:bg-muted/50 hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background"
1109
- [attr.aria-label]="toggleButtonLabel()"
1110
- [attr.title]="toggleButtonLabel()"
1111
- [attr.aria-pressed]="resolvedAppearance() === 'thin'"
1112
- (click)="toggleAppearance($event)">
1113
- <ui-nav-icon name="view_sidebar" [size]="18" class="text-current" />
1114
- </button>
1115
- }
1116
- </div>
1117
- }
1118
- <ui-scroll-area class="min-h-0 flex-1" [viewportClass]="scrollViewportClasses()">
1119
- <nav [class]="navClasses()">
1120
- @for (item of resolvedItems(); track item.id) {
1121
- <ui-nav-item [item]="item" [compact]="isCompact()" />
1122
- }
1123
- </nav>
1124
- </ui-scroll-area>
1125
- <div [class]="footerClasses()">
1126
- <div [class]="footerSlotClasses()">
1127
- <ng-content select="[sidebar-footer]" />
1128
- </div>
1129
- </div>
1130
- </ng-template>
1131
-
1132
- <ng-template #drawerTpl>
1133
- <div
1134
- role="dialog"
1135
- aria-modal="true"
1136
- [attr.aria-label]="ariaLabel()"
1137
- class="flex h-full w-72 max-w-[85vw] flex-col border-primary/30 text-foreground shadow-xl"
1138
- [class.border-r]="position() === 'left'"
1139
- [class.border-l]="position() === 'right'"
1140
- [class.border-primary/30]="position() === 'left' || position() === 'right'">
1141
- <ng-container [ngTemplateOutlet]="body" />
1142
- </div>
1143
- </ng-template>
1144
- `,
1145
- }]
1146
- }], ctorParameters: () => [], propDecorators: { items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: false }] }], navigationId: [{ type: i0.Input, args: [{ isSignal: true, alias: "navigationId", required: false }] }], appearance: [{ type: i0.Input, args: [{ isSignal: true, alias: "appearance", required: false }] }], borderSource: [{ type: i0.Input, args: [{ isSignal: true, alias: "borderSource", required: false }] }], position: [{ type: i0.Input, args: [{ isSignal: true, alias: "position", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], header: [{ type: i0.Input, args: [{ isSignal: true, alias: "header", required: false }] }], class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }], autoMobile: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoMobile", required: false }] }], autoRegister: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoRegister", required: false }] }], drawerTpl: [{ type: i0.ViewChild, args: ['drawerTpl', { isSignal: true }] }] } });
1147
-
1148
- /**
1149
- * Horizontal navigation (topbar) — shadcn-styled.
1150
- */
1151
- class TopbarComponent {
1152
- nav = inject(NavigationService);
1153
- overlay = inject(Overlay);
1154
- vcr = inject(ViewContainerRef);
1155
- host = inject(ElementRef);
1156
- destroyRef = inject(DestroyRef);
1157
- items = input([], ...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
1158
- /** Registry key di `NavigationService`. Default `'main'`. */
1159
- navigationId = input(DEFAULT_NAVIGATION_ID, ...(ngDevMode ? [{ debugName: "navigationId" }] : /* istanbul ignore next */ []));
1160
- appearance = input('default', ...(ngDevMode ? [{ debugName: "appearance" }] : /* istanbul ignore next */ []));
1161
- ariaLabel = input('Primary', ...(ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
1162
- class = input('', ...(ngDevMode ? [{ debugName: "class" }] : /* istanbul ignore next */ []));
1163
- /** Auto-register `items` ke `NavigationService` agar `activeTrail` bekerja. */
1164
- autoRegister = input(true, ...(ngDevMode ? [{ debugName: "autoRegister" }] : /* istanbul ignore next */ []));
1165
- /** Tampilkan hamburger di `< md` yang men-toggle mobile drawer sidebar. */
1166
- showHamburger = input(true, ...(ngDevMode ? [{ debugName: "showHamburger" }] : /* istanbul ignore next */ []));
1167
- hamburgerLabel = input('Open navigation', ...(ngDevMode ? [{ debugName: "hamburgerLabel" }] : /* istanbul ignore next */ []));
1168
- /** Resolved items: input jika disediakan, fallback ke registry NavigationService. */
1169
- resolvedItems = computed(() => {
1170
- const explicit = this.items();
1171
- return explicit.length > 0 ? explicit : this.nav.getItems(this.navigationId())();
1172
- }, ...(ngDevMode ? [{ debugName: "resolvedItems" }] : /* istanbul ignore next */ []));
1173
- openId = signal(null, ...(ngDevMode ? [{ debugName: "openId" }] : /* istanbul ignore next */ []));
1174
- active = null;
1175
- dropdownTpl = viewChild.required('dropdownTpl');
1176
- constructor() {
1177
- effect(() => {
1178
- const explicit = this.items();
1179
- if (this.autoRegister() && explicit.length > 0)
1180
- this.nav.registerItems(this.navigationId(), explicit);
1181
- });
1182
- this.destroyRef.onDestroy(() => this.closeAll());
1183
- }
1184
- hostClasses = computed(() => {
1185
- return ['sticky top-0 z-20 flex h-11 w-full items-center', this.class()].join(' ');
1186
- }, ...(ngDevMode ? [{ debugName: "hostClasses" }] : /* istanbul ignore next */ []));
1187
- endSlotClasses = computed(() => {
1188
- const base = ['flex h-full shrink-0 items-center justify-end gap-2 overflow-hidden'];
1189
- base.push('[&>[topbar-end]]:flex', '[&>[topbar-end]]:min-w-0', '[&>[topbar-end]]:max-w-full', '[&>[topbar-end]]:items-center', '[&>[topbar-end]]:justify-end', '[&>[topbar-end]]:gap-2', '[&>[topbar-end]>*]:w-auto', '[&>[topbar-end]>*]:max-w-full', '[&>[topbar-end]>*]:justify-end', '[&>[topbar-end]>*]:gap-0', '[&>[topbar-end]>*]:px-2', '[&>[topbar-end]>*>*:first-child]:ml-auto', '[&>[topbar-end]>*>*:nth-child(n+2)]:hidden');
1190
- return base.join(' ');
1191
- }, ...(ngDevMode ? [{ debugName: "endSlotClasses" }] : /* istanbul ignore next */ []));
1192
- asBasic(i) {
1193
- return i;
1194
- }
1195
- asCollapsable(i) {
1196
- return i;
1197
- }
1198
- asGroup(i) {
1199
- return i;
1200
- }
1201
- isItemActive(id) {
1202
- return this.nav.isActive(id);
1203
- }
1204
- toggleDropdown(trigger, item) {
1205
- if (this.openId() === item.id)
1206
- this.closeAll();
1207
- else
1208
- this.openDropdown(trigger, item);
1209
- }
1210
- openDropdown(trigger, item) {
1211
- if (this.openId() === item.id)
1212
- return;
1213
- this.closeAll();
1214
- this.attach(trigger, item, this.dropdownTpl());
1215
- }
1216
- attach(trigger, item, tpl) {
1217
- const strategy = this.overlay
1218
- .position()
1219
- .flexibleConnectedTo(trigger)
1220
- .withFlexibleDimensions(false)
1221
- .withPush(false)
1222
- .withPositions([
1223
- {
1224
- originX: 'start',
1225
- originY: 'bottom',
1226
- overlayX: 'start',
1227
- overlayY: 'top',
1228
- offsetY: 4,
1229
- },
1230
- {
1231
- originX: 'start',
1232
- originY: 'top',
1233
- overlayX: 'start',
1234
- overlayY: 'bottom',
1235
- offsetY: -4,
1236
- },
1237
- ]);
1238
- const ref = this.overlay.create({
1239
- positionStrategy: strategy,
1240
- scrollStrategy: this.overlay.scrollStrategies.reposition(),
1241
- hasBackdrop: true,
1242
- backdropClass: 'cdk-overlay-transparent-backdrop',
1243
- panelClass: ['ui-dropdown-panel'],
1244
- });
1245
- const portal = new TemplatePortal(tpl, this.vcr, { $implicit: item });
1246
- ref.attach(portal);
1247
- this.active = { ref, id: item.id ?? '' };
1248
- this.openId.set(item.id ?? null);
1249
- merge(ref.backdropClick(), ref.keydownEvents().pipe(filter((e) => e.key === 'Escape')))
1250
- .pipe(takeUntilDestroyed(this.destroyRef))
1251
- .subscribe(() => {
1252
- this.closeAll();
1253
- trigger.focus();
1254
- });
1255
- }
1256
- closeAll() {
1257
- if (this.active) {
1258
- this.active.ref.dispose();
1259
- this.active = null;
1260
- }
1261
- this.openId.set(null);
1262
- }
1263
- /** Menubar keyboard navigation: ArrowLeft/Right antar trigger, Home/End, ArrowDown fokus panel. */
1264
- onMenubarKeydown(event) {
1265
- const key = event.key;
1266
- const root = this.host.nativeElement;
1267
- const triggers = Array.from(root.querySelectorAll('ul[role="menubar"] [role="menuitem"]')).filter((el) => !el.hasAttribute('disabled'));
1268
- if (triggers.length === 0)
1269
- return;
1270
- const currentIndex = triggers.indexOf(document.activeElement);
1271
- if (key === 'ArrowDown' && currentIndex !== -1) {
1272
- event.preventDefault();
1273
- // Jika open, fokus item pertama panel; jika belum, focus tetap (panel akan dibuka via click/mouseenter).
1274
- queueMicrotask(() => this.focusFirstInPanel());
1275
- return;
1276
- }
1277
- if (key !== 'ArrowLeft' && key !== 'ArrowRight' && key !== 'Home' && key !== 'End')
1278
- return;
1279
- let nextIndex = currentIndex;
1280
- if (key === 'ArrowRight')
1281
- nextIndex = (currentIndex + 1 + triggers.length) % triggers.length;
1282
- else if (key === 'ArrowLeft')
1283
- nextIndex = (currentIndex - 1 + triggers.length) % triggers.length;
1284
- else if (key === 'Home')
1285
- nextIndex = 0;
1286
- else if (key === 'End')
1287
- nextIndex = triggers.length - 1;
1288
- if (nextIndex !== currentIndex && triggers[nextIndex]) {
1289
- event.preventDefault();
1290
- triggers[nextIndex].focus();
1291
- }
1292
- }
1293
- /** Arrow-key navigation dalam dropdown panel. */
1294
- onPanelKeydown(event) {
1295
- const key = event.key;
1296
- if (key !== 'ArrowDown' &&
1297
- key !== 'ArrowUp' &&
1298
- key !== 'ArrowLeft' &&
1299
- key !== 'ArrowRight' &&
1300
- key !== 'Home' &&
1301
- key !== 'End')
1302
- return;
1303
- const panel = this.active?.ref.overlayElement;
1304
- if (!panel)
1305
- return;
1306
- const items = this.collectPanelFocusables(panel);
1307
- if (items.length === 0)
1308
- return;
1309
- const currentIndex = items.indexOf(document.activeElement);
1310
- let nextIndex = currentIndex;
1311
- if (key === 'ArrowDown' || key === 'ArrowRight')
1312
- nextIndex = (currentIndex + 1 + items.length) % items.length;
1313
- else if (key === 'ArrowUp' || key === 'ArrowLeft')
1314
- nextIndex = (currentIndex - 1 + items.length) % items.length;
1315
- else if (key === 'Home')
1316
- nextIndex = 0;
1317
- else if (key === 'End')
1318
- nextIndex = items.length - 1;
1319
- if (nextIndex !== currentIndex && items[nextIndex]) {
1320
- event.preventDefault();
1321
- items[nextIndex].focus();
1322
- }
1323
- }
1324
- collectPanelFocusables(root) {
1325
- return Array.from(root.querySelectorAll('a[href], button:not([disabled]), [tabindex]:not([tabindex="-1"])')).filter((el) => el.offsetParent !== null || el.getClientRects().length > 0);
1326
- }
1327
- focusFirstInPanel() {
1328
- const panel = this.active?.ref.overlayElement;
1329
- if (!panel)
1330
- return;
1331
- const items = this.collectPanelFocusables(panel);
1332
- items[0]?.focus();
1333
- }
1334
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: TopbarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1335
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: TopbarComponent, isStandalone: true, selector: "topbar", inputs: { items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: false, transformFunction: null }, navigationId: { classPropertyName: "navigationId", publicName: "navigationId", isSignal: true, isRequired: false, transformFunction: null }, appearance: { classPropertyName: "appearance", publicName: "appearance", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null }, autoRegister: { classPropertyName: "autoRegister", publicName: "autoRegister", isSignal: true, isRequired: false, transformFunction: null }, showHamburger: { classPropertyName: "showHamburger", publicName: "showHamburger", isSignal: true, isRequired: false, transformFunction: null }, hamburgerLabel: { classPropertyName: "hamburgerLabel", publicName: "hamburgerLabel", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "navigation" }, properties: { "attr.aria-label": "ariaLabel()", "class": "hostClasses()", "attr.data-appearance": "appearance()" } }, viewQueries: [{ propertyName: "dropdownTpl", first: true, predicate: ["dropdownTpl"], descendants: true, isSignal: true }], ngImport: i0, template: `
1336
- <div class="flex h-full w-full items-center gap-3 px-1">
1337
- <div data-topbar-slot="start" class="flex shrink-0 items-center gap-2">
1338
- @if (showHamburger()) {
1339
- <button
1340
- type="button"
1341
- class="inline-flex h-9 w-9 items-center justify-center rounded-md text-foreground/80 hover:bg-accent hover:text-accent-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring md:hidden"
1342
- [attr.aria-label]="hamburgerLabel()"
1343
- [attr.aria-expanded]="nav.mobileOpen()"
1344
- (click)="nav.toggleMobile()">
1345
- <ui-nav-icon name="menu" [size]="18" />
1346
- </button>
1347
- }
1348
- <ng-content select="[topbar-start]" />
1349
- </div>
1350
-
1351
- <div data-topbar-slot="nav" class="flex min-w-0 flex-1 items-center justify-center">
1352
- <ul
1353
- class="flex min-w-0 flex-1 items-center justify-center gap-1"
1354
- role="menubar"
1355
- (keydown)="onMenubarKeydown($event)">
1356
- @for (item of resolvedItems(); track item.id) {
1357
- <li role="none" class="relative">
1358
- @switch (item.type) {
1359
- @case ('basic') {
1360
- @let basic = asBasic(item);
1361
- <a
1362
- role="menuitem"
1363
- class="ui-nav-text inline-flex items-center gap-2 rounded-md px-3 py-2 text-foreground/80 hover:bg-accent hover:text-accent-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring aria-[current=page]:text-primary"
1364
- [routerLink]="basic.link"
1365
- routerLinkActive
1366
- #rla="routerLinkActive"
1367
- [class.text-primary]="rla.isActive"
1368
- [attr.aria-current]="rla.isActive ? 'page' : null"
1369
- [target]="basic.target ?? undefined">
1370
- @if (basic.icon) {
1371
- <ui-nav-icon [name]="basic.icon" [size]="18" />
1372
- }
1373
- <span>{{ basic.title }}</span>
1374
- </a>
1375
- }
1376
- @case ('collapsable') {
1377
- @let col = asCollapsable(item);
1378
- <button
1379
- #trigger
1380
- type="button"
1381
- role="menuitem"
1382
- class="ui-nav-text inline-flex items-center gap-2 rounded-md px-3 py-2 text-foreground/80 hover:bg-accent hover:text-accent-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
1383
- [class.text-primary]="isItemActive(col.id)"
1384
- [attr.aria-expanded]="openId() === col.id"
1385
- [attr.aria-haspopup]="'menu'"
1386
- (click)="toggleDropdown(trigger, item)"
1387
- (mouseenter)="openDropdown(trigger, item)">
1388
- @if (col.icon) {
1389
- <ui-nav-icon [name]="col.icon" [size]="18" />
1390
- }
1391
- <span>{{ col.title }}</span>
1392
- <ui-nav-icon name="expand_more" [size]="18" />
1393
- </button>
1394
- }
1395
- @case ('group') {
1396
- @let group = asGroup(item);
1397
- <button
1398
- #trigger
1399
- type="button"
1400
- role="menuitem"
1401
- class="ui-nav-text inline-flex items-center gap-2 rounded-md px-3 py-2 text-foreground/80 hover:bg-accent hover:text-accent-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
1402
- [class.text-primary]="isItemActive(group.id)"
1403
- [attr.aria-expanded]="openId() === group.id"
1404
- [attr.aria-haspopup]="'menu'"
1405
- (click)="toggleDropdown(trigger, item)"
1406
- (mouseenter)="openDropdown(trigger, item)">
1407
- @if (group.icon) {
1408
- <ui-nav-icon [name]="group.icon" [size]="18" />
1409
- }
1410
- <span>{{ group.title }}</span>
1411
- <ui-nav-icon name="expand_more" [size]="18" />
1412
- </button>
1413
- }
1414
- @default {
1415
- <span class="ui-nav-heading px-3 py-2 text-muted-foreground">
1416
- {{ item.title }}
1417
- </span>
1418
- }
1419
- }
1420
- </li>
1421
- }
1422
- </ul>
1423
- </div>
1424
-
1425
- <div data-topbar-slot="end" [class]="endSlotClasses()">
1426
- <ng-content select="[topbar-end]" />
1427
- </div>
1428
- </div>
1429
-
1430
- <!-- Dropdown template -->
1431
- <ng-template #dropdownTpl let-item>
1432
- <div role="menu" class="min-w-56 border border-brand bg-background/95 p-1" (keydown)="onPanelKeydown($event)">
1433
- @for (child of item.children; track child.id) {
1434
- <ui-nav-item [item]="child" />
1435
- }
1436
- </div>
1437
- </ng-template>
1438
- `, isInline: true, dependencies: [{ kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: RouterLinkActive, selector: "[routerLinkActive]", inputs: ["routerLinkActiveOptions", "ariaCurrentWhenActive", "routerLinkActive"], outputs: ["isActiveChange"], exportAs: ["routerLinkActive"] }, { kind: "component", type: UiNavIconComponent, selector: "ui-nav-icon", inputs: ["name", "class", "size"] }, { kind: "component", type: UiNavItemComponent, selector: "ui-nav-item", inputs: ["item", "level", "compact", "railConnector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1439
- }
1440
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: TopbarComponent, decorators: [{
1441
- type: Component,
1442
- args: [{
1443
- selector: 'topbar',
1444
- changeDetection: ChangeDetectionStrategy.OnPush,
1445
- imports: [RouterLink, RouterLinkActive, UiNavIconComponent, UiNavItemComponent],
1446
- host: {
1447
- role: 'navigation',
1448
- '[attr.aria-label]': 'ariaLabel()',
1449
- '[class]': 'hostClasses()',
1450
- '[attr.data-appearance]': 'appearance()',
1451
- },
1452
- template: `
1453
- <div class="flex h-full w-full items-center gap-3 px-1">
1454
- <div data-topbar-slot="start" class="flex shrink-0 items-center gap-2">
1455
- @if (showHamburger()) {
1456
- <button
1457
- type="button"
1458
- class="inline-flex h-9 w-9 items-center justify-center rounded-md text-foreground/80 hover:bg-accent hover:text-accent-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring md:hidden"
1459
- [attr.aria-label]="hamburgerLabel()"
1460
- [attr.aria-expanded]="nav.mobileOpen()"
1461
- (click)="nav.toggleMobile()">
1462
- <ui-nav-icon name="menu" [size]="18" />
1463
- </button>
1464
- }
1465
- <ng-content select="[topbar-start]" />
1466
- </div>
1467
-
1468
- <div data-topbar-slot="nav" class="flex min-w-0 flex-1 items-center justify-center">
1469
- <ul
1470
- class="flex min-w-0 flex-1 items-center justify-center gap-1"
1471
- role="menubar"
1472
- (keydown)="onMenubarKeydown($event)">
1473
- @for (item of resolvedItems(); track item.id) {
1474
- <li role="none" class="relative">
1475
- @switch (item.type) {
1476
- @case ('basic') {
1477
- @let basic = asBasic(item);
1478
- <a
1479
- role="menuitem"
1480
- class="ui-nav-text inline-flex items-center gap-2 rounded-md px-3 py-2 text-foreground/80 hover:bg-accent hover:text-accent-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring aria-[current=page]:text-primary"
1481
- [routerLink]="basic.link"
1482
- routerLinkActive
1483
- #rla="routerLinkActive"
1484
- [class.text-primary]="rla.isActive"
1485
- [attr.aria-current]="rla.isActive ? 'page' : null"
1486
- [target]="basic.target ?? undefined">
1487
- @if (basic.icon) {
1488
- <ui-nav-icon [name]="basic.icon" [size]="18" />
1489
- }
1490
- <span>{{ basic.title }}</span>
1491
- </a>
1492
- }
1493
- @case ('collapsable') {
1494
- @let col = asCollapsable(item);
1495
- <button
1496
- #trigger
1497
- type="button"
1498
- role="menuitem"
1499
- class="ui-nav-text inline-flex items-center gap-2 rounded-md px-3 py-2 text-foreground/80 hover:bg-accent hover:text-accent-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
1500
- [class.text-primary]="isItemActive(col.id)"
1501
- [attr.aria-expanded]="openId() === col.id"
1502
- [attr.aria-haspopup]="'menu'"
1503
- (click)="toggleDropdown(trigger, item)"
1504
- (mouseenter)="openDropdown(trigger, item)">
1505
- @if (col.icon) {
1506
- <ui-nav-icon [name]="col.icon" [size]="18" />
1507
- }
1508
- <span>{{ col.title }}</span>
1509
- <ui-nav-icon name="expand_more" [size]="18" />
1510
- </button>
1511
- }
1512
- @case ('group') {
1513
- @let group = asGroup(item);
1514
- <button
1515
- #trigger
1516
- type="button"
1517
- role="menuitem"
1518
- class="ui-nav-text inline-flex items-center gap-2 rounded-md px-3 py-2 text-foreground/80 hover:bg-accent hover:text-accent-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
1519
- [class.text-primary]="isItemActive(group.id)"
1520
- [attr.aria-expanded]="openId() === group.id"
1521
- [attr.aria-haspopup]="'menu'"
1522
- (click)="toggleDropdown(trigger, item)"
1523
- (mouseenter)="openDropdown(trigger, item)">
1524
- @if (group.icon) {
1525
- <ui-nav-icon [name]="group.icon" [size]="18" />
1526
- }
1527
- <span>{{ group.title }}</span>
1528
- <ui-nav-icon name="expand_more" [size]="18" />
1529
- </button>
1530
- }
1531
- @default {
1532
- <span class="ui-nav-heading px-3 py-2 text-muted-foreground">
1533
- {{ item.title }}
1534
- </span>
1535
- }
1536
- }
1537
- </li>
1538
- }
1539
- </ul>
1540
- </div>
1541
-
1542
- <div data-topbar-slot="end" [class]="endSlotClasses()">
1543
- <ng-content select="[topbar-end]" />
1544
- </div>
1545
- </div>
1546
-
1547
- <!-- Dropdown template -->
1548
- <ng-template #dropdownTpl let-item>
1549
- <div role="menu" class="min-w-56 border border-brand bg-background/95 p-1" (keydown)="onPanelKeydown($event)">
1550
- @for (child of item.children; track child.id) {
1551
- <ui-nav-item [item]="child" />
1552
- }
1553
- </div>
1554
- </ng-template>
1555
- `,
1556
- }]
1557
- }], ctorParameters: () => [], propDecorators: { items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: false }] }], navigationId: [{ type: i0.Input, args: [{ isSignal: true, alias: "navigationId", required: false }] }], appearance: [{ type: i0.Input, args: [{ isSignal: true, alias: "appearance", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }], autoRegister: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoRegister", required: false }] }], showHamburger: [{ type: i0.Input, args: [{ isSignal: true, alias: "showHamburger", required: false }] }], hamburgerLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "hamburgerLabel", required: false }] }], dropdownTpl: [{ type: i0.ViewChild, args: ['dropdownTpl', { isSignal: true }] }] } });
1558
-
1559
- const DemoNavigationData = [
1560
- {
1561
- id: 'documentation',
1562
- title: 'Documentation',
1563
- subtitle: 'Guides and getting started resources',
1564
- type: 'group',
1565
- icon: 'menu_book',
1566
- children: [
1567
- {
1568
- id: 'documentation-introduction',
1569
- title: 'Introduction',
1570
- type: 'basic',
1571
- icon: 'menu_book',
1572
- link: '/docs/introduction',
1573
- },
1574
- {
1575
- id: 'documentation-installation',
1576
- title: 'Installation',
1577
- type: 'basic',
1578
- icon: 'download',
1579
- link: '/docs/installation',
1580
- },
1581
- {
1582
- id: 'documentation-getting-started',
1583
- title: 'Getting started',
1584
- type: 'basic',
1585
- icon: 'rocket_launch',
1586
- link: '/docs/getting-started',
1587
- },
1588
- {
1589
- id: 'documentation-upgrade-guide',
1590
- title: 'Upgrade Guide',
1591
- type: 'basic',
1592
- icon: 'arrow_circle_up',
1593
- link: '/docs/upgrade-guide',
1594
- },
1595
- {
1596
- id: 'documentation-changelog',
1597
- title: 'Changelog',
1598
- type: 'basic',
1599
- icon: 'history',
1600
- link: '/docs/changelog',
1601
- },
1602
- {
1603
- id: 'documentation-icon-lucide',
1604
- title: 'Lucide Icons',
1605
- type: 'basic',
1606
- icon: 'star',
1607
- link: '/lucide-icons',
1608
- badge: {
1609
- title: 'Demo',
1610
- classes: 'ml-2 px-2 py-0.5 rounded-full text-xs bg-blue-500 text-white',
1611
- },
1612
- },
1613
- ],
1614
- },
1615
- {
1616
- id: 'user-interface',
1617
- title: 'User Interface',
1618
- subtitle: 'Components and design elements',
1619
- type: 'group',
1620
- icon: 'dashboard',
1621
- children: [
1622
- {
1623
- id: 'user-interface-material-components',
1624
- title: 'Material Components',
1625
- type: 'collapsable',
1626
- icon: 'deployed_code',
1627
- children: [
1628
- {
1629
- id: 'user-interface-material-components-inputs-forms',
1630
- title: 'Inputs & Forms',
1631
- type: 'collapsable',
1632
- icon: 'input',
1633
- children: [
1634
- {
1635
- id: 'user-interface-material-components-inputs-forms-autocomplete',
1636
- title: 'Autocomplete',
1637
- type: 'basic',
1638
- icon: 'search',
1639
- link: '/ui/material/autocomplete',
1640
- },
1641
- {
1642
- id: 'user-interface-material-components-inputs-forms-checkbox',
1643
- title: 'Checkbox',
1644
- type: 'basic',
1645
- icon: 'check_box',
1646
- link: '/ui/material/checkbox',
1647
- },
1648
- {
1649
- id: 'user-interface-material-components-inputs-forms-datepicker',
1650
- title: 'Datepicker',
1651
- type: 'basic',
1652
- icon: 'calendar_today',
1653
- link: '/ui/material/datepicker',
1654
- },
1655
- {
1656
- id: 'user-interface-material-components-inputs-forms-form-field',
1657
- title: 'Form field',
1658
- type: 'basic',
1659
- icon: 'text_fields',
1660
- link: '/ui/material/form-field',
1661
- },
1662
- {
1663
- id: 'user-interface-material-components-inputs-forms-input',
1664
- title: 'Input',
1665
- type: 'basic',
1666
- icon: 'text_fields',
1667
- link: '/ui/material/input',
1668
- },
1669
- {
1670
- id: 'user-interface-material-components-inputs-forms-radio-button',
1671
- title: 'Radio button',
1672
- type: 'basic',
1673
- icon: 'radio_button_checked',
1674
- link: '/ui/material/radio',
1675
- },
1676
- {
1677
- id: 'user-interface-material-components-inputs-forms-select',
1678
- title: 'Select',
1679
- type: 'basic',
1680
- icon: 'expand_more',
1681
- link: '/ui/material/select',
1682
- },
1683
- {
1684
- id: 'user-interface-material-components-inputs-forms-slider',
1685
- title: 'Slider',
1686
- type: 'basic',
1687
- icon: 'tune',
1688
- link: '/ui/material/slider',
1689
- },
1690
- {
1691
- id: 'user-interface-material-components-inputs-forms-slide-toggle',
1692
- title: 'Slide toggle',
1693
- type: 'basic',
1694
- icon: 'toggle_on',
1695
- link: '/ui/material/slide-toggle',
1696
- },
1697
- ],
1698
- },
1699
- {
1700
- id: 'user-interface-material-components-buttons-actions',
1701
- title: 'Buttons & Actions',
1702
- type: 'collapsable',
1703
- icon: 'ads_click',
1704
- children: [
1705
- {
1706
- id: 'user-interface-material-components-buttons-actions-button',
1707
- title: 'Button',
1708
- type: 'basic',
1709
- icon: 'crop_square',
1710
- link: '/ui/material/button',
1711
- },
1712
- {
1713
- id: 'user-interface-material-components-buttons-actions-button-toggle',
1714
- title: 'Button toggle',
1715
- type: 'basic',
1716
- icon: 'view_column',
1717
- link: '/ui/material/button-toggle',
1718
- },
1719
- {
1720
- id: 'user-interface-material-components-buttons-actions-chips',
1721
- title: 'Chips',
1722
- type: 'basic',
1723
- icon: 'label',
1724
- link: '/ui/material/chips',
1725
- badge: {
1726
- title: 'New',
1727
- classes: 'ml-2 px-2 py-0.5 rounded-full text-xs bg-green-500 text-white',
1728
- },
1729
- },
1730
- {
1731
- id: 'user-interface-material-components-buttons-actions-menu',
1732
- title: 'Menu',
1733
- type: 'basic',
1734
- icon: 'menu',
1735
- link: '/ui/material/menu',
1736
- },
1737
- {
1738
- id: 'user-interface-material-components-buttons-actions-ripples',
1739
- title: 'Ripples',
1740
- type: 'basic',
1741
- icon: 'waves',
1742
- link: '/ui/material/ripples',
1743
- },
1744
- ],
1745
- },
1746
- {
1747
- id: 'user-interface-material-components-layout-containers',
1748
- title: 'Layout & Containers',
1749
- type: 'collapsable',
1750
- icon: 'dashboard',
1751
- children: [
1752
- {
1753
- id: 'user-interface-material-components-layout-containers-card',
1754
- title: 'Card',
1755
- type: 'basic',
1756
- icon: 'credit_card',
1757
- link: '/ui/material/card',
1758
- },
1759
- {
1760
- id: 'user-interface-material-components-layout-containers-divider',
1761
- title: 'Divider',
1762
- type: 'basic',
1763
- icon: 'remove',
1764
- link: '/ui/material/divider',
1765
- },
1766
- {
1767
- id: 'user-interface-material-components-layout-containers-expansion-panel',
1768
- title: 'Expansion Panel',
1769
- type: 'basic',
1770
- icon: 'expand_more',
1771
- link: '/ui/material/expansion',
1772
- },
1773
- {
1774
- id: 'user-interface-material-components-layout-containers-grid-list',
1775
- title: 'Grid list',
1776
- type: 'basic',
1777
- icon: 'grid_view',
1778
- link: '/ui/material/grid-list',
1779
- },
1780
- {
1781
- id: 'user-interface-material-components-layout-containers-list',
1782
- title: 'List',
1783
- type: 'basic',
1784
- icon: 'list',
1785
- link: '/ui/material/list',
1786
- },
1787
- {
1788
- id: 'user-interface-material-components-layout-containers-sidenav',
1789
- title: 'Sidenav',
1790
- type: 'basic',
1791
- icon: 'view_sidebar',
1792
- link: '/ui/material/sidenav',
1793
- },
1794
- {
1795
- id: 'user-interface-material-components-layout-containers-tabs',
1796
- title: 'Tabs',
1797
- type: 'basic',
1798
- icon: 'tab',
1799
- link: '/ui/material/tabs',
1800
- },
1801
- {
1802
- id: 'user-interface-material-components-layout-containers-toolbar',
1803
- title: 'Toolbar',
1804
- type: 'basic',
1805
- icon: 'build',
1806
- link: '/ui/material/toolbar',
1807
- },
1808
- ],
1809
- },
1810
- {
1811
- id: 'user-interface-material-components-data-display',
1812
- title: 'Data & Display',
1813
- type: 'collapsable',
1814
- icon: 'bar_chart',
1815
- children: [
1816
- {
1817
- id: 'user-interface-material-components-data-display-badge',
1818
- title: 'Badge',
1819
- type: 'basic',
1820
- icon: 'verified',
1821
- link: '/ui/material/badge',
1822
- },
1823
- {
1824
- id: 'user-interface-material-components-data-display-icon',
1825
- title: 'Icon',
1826
- type: 'basic',
1827
- icon: 'star',
1828
- link: '/ui/material/icon',
1829
- },
1830
- {
1831
- id: 'user-interface-material-components-data-display-paginator',
1832
- title: 'Paginator',
1833
- type: 'basic',
1834
- icon: 'first_page',
1835
- link: '/ui/material/paginator',
1836
- },
1837
- {
1838
- id: 'user-interface-material-components-data-display-progress-bar',
1839
- title: 'Progress bar',
1840
- type: 'basic',
1841
- icon: 'hourglass_empty',
1842
- link: '/ui/material/progress-bar',
1843
- },
1844
- {
1845
- id: 'user-interface-material-components-data-display-progress-spinner',
1846
- title: 'Progress spinner',
1847
- type: 'basic',
1848
- icon: 'progress_activity',
1849
- link: '/ui/material/progress-spinner',
1850
- },
1851
- {
1852
- id: 'user-interface-material-components-data-display-sort',
1853
- title: 'Sort header',
1854
- type: 'basic',
1855
- icon: 'swap_vert',
1856
- link: '/ui/material/sort',
1857
- },
1858
- {
1859
- id: 'user-interface-material-components-data-display-table',
1860
- title: 'Table',
1861
- type: 'basic',
1862
- icon: 'table_chart',
1863
- link: '/ui/material/table',
1864
- },
1865
- {
1866
- id: 'user-interface-material-components-data-display-tree',
1867
- title: 'Tree',
1868
- type: 'basic',
1869
- icon: 'hub',
1870
- link: '/ui/material/tree',
1871
- },
1872
- ],
1873
- },
1874
- {
1875
- id: 'user-interface-material-components-overlays-modals',
1876
- title: 'Overlays & Modals',
1877
- type: 'collapsable',
1878
- icon: 'layers',
1879
- children: [
1880
- {
1881
- id: 'user-interface-material-components-overlays-modals-bottom-sheet',
1882
- title: 'Bottom Sheet',
1883
- type: 'basic',
1884
- icon: 'south',
1885
- link: '/ui/material/bottom-sheet',
1886
- },
1887
- {
1888
- id: 'user-interface-material-components-overlays-modals-dialog',
1889
- title: 'Dialog',
1890
- type: 'basic',
1891
- icon: 'chat',
1892
- link: '/ui/material/dialog',
1893
- },
1894
- {
1895
- id: 'user-interface-material-components-overlays-modals-snack-bar',
1896
- title: 'Snack-bar',
1897
- type: 'basic',
1898
- icon: 'notifications',
1899
- link: '/ui/material/snack-bar',
1900
- },
1901
- {
1902
- id: 'user-interface-material-components-overlays-modals-tooltip',
1903
- title: 'Tooltip',
1904
- type: 'basic',
1905
- icon: 'help',
1906
- link: '/ui/material/tooltip',
1907
- },
1908
- ],
1909
- },
1910
- {
1911
- id: 'user-interface-material-components-navigation-stepper',
1912
- title: 'Navigation & Steps',
1913
- type: 'collapsable',
1914
- icon: 'account_tree',
1915
- children: [
1916
- {
1917
- id: 'user-interface-material-components-navigation-stepper-stepper',
1918
- title: 'Stepper',
1919
- type: 'basic',
1920
- icon: 'account_tree',
1921
- link: '/ui/material/stepper',
1922
- },
1923
- ],
1924
- },
1925
- ],
1926
- },
1927
- {
1928
- id: 'user-interface-angular-cdk',
1929
- title: 'Angular CDK',
1930
- type: 'collapsable',
1931
- icon: 'widgets',
1932
- children: [
1933
- {
1934
- id: 'user-interface-angular-cdk-accessibility-navigation',
1935
- title: 'Accessibility & Navigation',
1936
- type: 'collapsable',
1937
- icon: 'accessibility',
1938
- children: [
1939
- {
1940
- id: 'user-interface-angular-cdk-accessibility-navigation-a11y',
1941
- title: 'Accessibility',
1942
- type: 'basic',
1943
- icon: 'accessibility',
1944
- link: '/ui/cdk/a11y',
1945
- },
1946
- {
1947
- id: 'user-interface-angular-cdk-accessibility-navigation-focus-trap',
1948
- title: 'Focus Trap',
1949
- type: 'basic',
1950
- icon: 'center_focus_strong',
1951
- link: '/ui/cdk/focus-trap',
1952
- },
1953
- {
1954
- id: 'user-interface-angular-cdk-accessibility-navigation-live-announcer',
1955
- title: 'Live Announcer',
1956
- type: 'basic',
1957
- icon: 'campaign',
1958
- link: '/ui/cdk/live-announcer',
1959
- },
1960
- {
1961
- id: 'user-interface-angular-cdk-accessibility-navigation-listbox',
1962
- title: 'Listbox',
1963
- type: 'basic',
1964
- icon: 'list',
1965
- link: '/ui/cdk/listbox',
1966
- },
1967
- {
1968
- id: 'user-interface-angular-cdk-accessibility-navigation-menu-cdk',
1969
- title: 'Menu',
1970
- type: 'basic',
1971
- icon: 'menu',
1972
- link: '/ui/cdk/menu',
1973
- },
1974
- ],
1975
- },
1976
- {
1977
- id: 'user-interface-angular-cdk-layout-positioning',
1978
- title: 'Layout & Positioning',
1979
- type: 'collapsable',
1980
- icon: 'dashboard',
1981
- children: [
1982
- {
1983
- id: 'user-interface-angular-cdk-layout-positioning-layout',
1984
- title: 'Layout',
1985
- type: 'basic',
1986
- icon: 'dashboard',
1987
- link: '/ui/cdk/layout',
1988
- },
1989
- {
1990
- id: 'user-interface-angular-cdk-layout-positioning-overlay',
1991
- title: 'Overlay',
1992
- type: 'basic',
1993
- icon: 'layers',
1994
- link: '/ui/cdk/overlay',
1995
- },
1996
- {
1997
- id: 'user-interface-angular-cdk-layout-positioning-portal',
1998
- title: 'Portal',
1999
- type: 'basic',
2000
- icon: 'radio_button_checked',
2001
- link: '/ui/cdk/portal',
2002
- },
2003
- {
2004
- id: 'user-interface-angular-cdk-layout-positioning-scrolling',
2005
- title: 'Scrolling',
2006
- type: 'basic',
2007
- icon: 'unfold_more',
2008
- link: '/ui/cdk/scrolling',
2009
- },
2010
- {
2011
- id: 'user-interface-angular-cdk-layout-positioning-virtual-scrolling',
2012
- title: 'Virtual Scrolling',
2013
- type: 'basic',
2014
- icon: 'view_agenda',
2015
- link: '/ui/cdk/virtual-scrolling',
2016
- },
2017
- ],
2018
- },
2019
- {
2020
- id: 'user-interface-angular-cdk-interaction-behavior',
2021
- title: 'Interaction & Behavior',
2022
- type: 'collapsable',
2023
- icon: 'pan_tool',
2024
- children: [
2025
- {
2026
- id: 'user-interface-angular-cdk-interaction-behavior-drag-drop',
2027
- title: 'Drag and Drop',
2028
- type: 'basic',
2029
- icon: 'open_with',
2030
- link: '/ui/cdk/drag-drop',
2031
- },
2032
- {
2033
- id: 'user-interface-angular-cdk-interaction-behavior-observers',
2034
- title: 'Observers',
2035
- type: 'basic',
2036
- icon: 'visibility',
2037
- link: '/ui/cdk/observers',
2038
- },
2039
- {
2040
- id: 'user-interface-angular-cdk-interaction-behavior-platform',
2041
- title: 'Platform',
2042
- type: 'basic',
2043
- icon: 'devices',
2044
- link: '/ui/cdk/platform',
2045
- },
2046
- {
2047
- id: 'user-interface-angular-cdk-interaction-behavior-stepper-cdk',
2048
- title: 'Stepper',
2049
- type: 'basic',
2050
- icon: 'account_tree',
2051
- link: '/ui/cdk/stepper',
2052
- },
2053
- ],
2054
- },
2055
- {
2056
- id: 'user-interface-angular-cdk-forms-data',
2057
- title: 'Forms & Data',
2058
- type: 'collapsable',
2059
- icon: 'storage',
2060
- children: [
2061
- {
2062
- id: 'user-interface-angular-cdk-forms-data-accordion',
2063
- title: 'Accordion',
2064
- type: 'basic',
2065
- icon: 'expand_more',
2066
- link: '/ui/cdk/accordion',
2067
- },
2068
- {
2069
- id: 'user-interface-angular-cdk-forms-data-table-cdk',
2070
- title: 'Table',
2071
- type: 'basic',
2072
- icon: 'table_chart',
2073
- link: '/ui/cdk/table',
2074
- },
2075
- {
2076
- id: 'user-interface-angular-cdk-forms-data-tree-cdk',
2077
- title: 'Tree',
2078
- type: 'basic',
2079
- icon: 'hub',
2080
- link: '/ui/cdk/tree',
2081
- },
2082
- ],
2083
- },
2084
- {
2085
- id: 'user-interface-angular-cdk-utilities-helpers',
2086
- title: 'Utilities & Helpers',
2087
- type: 'collapsable',
2088
- icon: 'build',
2089
- children: [
2090
- {
2091
- id: 'user-interface-angular-cdk-utilities-helpers-bidi',
2092
- title: 'Bidirectionality',
2093
- type: 'basic',
2094
- icon: 'swap_horiz',
2095
- link: '/ui/cdk/bidi',
2096
- },
2097
- {
2098
- id: 'user-interface-angular-cdk-utilities-helpers-clipboard',
2099
- title: 'Clipboard',
2100
- type: 'basic',
2101
- icon: 'content_paste',
2102
- link: '/ui/cdk/clipboard',
2103
- },
2104
- {
2105
- id: 'user-interface-angular-cdk-utilities-helpers-coercion',
2106
- title: 'Coercion',
2107
- type: 'basic',
2108
- icon: 'shuffle',
2109
- link: '/ui/cdk/coercion',
2110
- },
2111
- {
2112
- id: 'user-interface-angular-cdk-utilities-helpers-collections',
2113
- title: 'Collections',
2114
- type: 'basic',
2115
- icon: 'folder',
2116
- link: '/ui/cdk/collections',
2117
- },
2118
- {
2119
- id: 'user-interface-angular-cdk-utilities-helpers-keycodes',
2120
- title: 'Keycodes',
2121
- type: 'basic',
2122
- icon: 'keyboard',
2123
- link: '/ui/cdk/keycodes',
2124
- },
2125
- ],
2126
- },
2127
- {
2128
- id: 'user-interface-angular-cdk-testing-tools',
2129
- title: 'Testing Tools',
2130
- type: 'collapsable',
2131
- icon: 'bug_report',
2132
- children: [
2133
- {
2134
- id: 'user-interface-angular-cdk-testing-tools-component-harnesses',
2135
- title: 'Component Harnesses',
2136
- type: 'basic',
2137
- icon: 'science',
2138
- link: '/ui/cdk/testing',
2139
- },
2140
- {
2141
- id: 'user-interface-angular-cdk-testing-tools-test-harnesses',
2142
- title: 'Test Harnesses',
2143
- type: 'basic',
2144
- icon: 'science',
2145
- link: '/ui/cdk/test-harnesses',
2146
- },
2147
- ],
2148
- },
2149
- {
2150
- id: 'user-interface-angular-cdk-advanced-feature',
2151
- title: 'Advanced feature',
2152
- type: 'collapsable',
2153
- icon: 'settings',
2154
- children: [
2155
- {
2156
- id: 'user-interface-angular-cdk-advanced-feature-dialog-cdk',
2157
- title: 'Dialog',
2158
- type: 'basic',
2159
- icon: 'chat',
2160
- link: '/ui/cdk/dialog',
2161
- },
2162
- {
2163
- id: 'user-interface-angular-cdk-advanced-feature-text-field',
2164
- title: 'Text Field',
2165
- type: 'basic',
2166
- icon: 'text_fields',
2167
- link: '/ui/cdk/text-field',
2168
- },
2169
- ],
2170
- },
2171
- ],
2172
- },
2173
- {
2174
- id: 'user-interface-tailwind',
2175
- title: 'Tailwind CSS',
2176
- type: 'collapsable',
2177
- icon: 'air',
2178
- children: [
2179
- {
2180
- id: 'user-interface-tailwind-css-heading',
2181
- title: 'Heading',
2182
- type: 'basic',
2183
- icon: 'text_fields',
2184
- link: '/ui/tailwind/heading',
2185
- },
2186
- {
2187
- id: 'user-interface-tailwind-data-display',
2188
- title: 'Data Display',
2189
- type: 'basic',
2190
- icon: 'bar_chart',
2191
- link: '/ui/tailwind/data-display',
2192
- },
2193
- {
2194
- id: 'user-interface-tailwind-list',
2195
- title: 'List',
2196
- type: 'basic',
2197
- icon: 'list',
2198
- link: '/ui/tailwind/list',
2199
- },
2200
- {
2201
- id: 'user-interface-tailwind-form',
2202
- title: 'Form',
2203
- type: 'basic',
2204
- icon: 'dynamic_form',
2205
- link: '/ui/tailwind/form',
2206
- },
2207
- {
2208
- id: 'user-interface-tailwind-feedback',
2209
- title: 'Feedback',
2210
- type: 'basic',
2211
- icon: 'report',
2212
- link: '/ui/tailwind/feedback',
2213
- },
2214
- ],
2215
- },
2216
- ],
2217
- },
2218
- {
2219
- id: 'feature',
2220
- title: 'Features',
2221
- subtitle: 'Advanced functionality and customization options',
2222
- type: 'group',
2223
- icon: 'settings',
2224
- children: [
2225
- {
2226
- id: 'feature-theme',
2227
- title: 'Themes',
2228
- type: 'collapsable',
2229
- icon: 'palette',
2230
- children: [
2231
- {
2232
- id: 'feature-theme-dark-mode',
2233
- title: 'Dark Mode',
2234
- type: 'basic',
2235
- icon: 'dark_mode',
2236
- link: '/feature/theme/dark-mode',
2237
- },
2238
- {
2239
- id: 'feature-theme-color',
2240
- title: 'Color Schemes',
2241
- type: 'basic',
2242
- icon: 'palette',
2243
- link: '/feature/theme/color-schemes',
2244
- badge: {
2245
- title: 'Beta',
2246
- classes: 'ml-2 px-2 py-0.5 rounded-full text-xs bg-yellow-500 text-white',
2247
- },
2248
- },
2249
- {
2250
- id: 'feature-layout',
2251
- title: 'Layout',
2252
- type: 'collapsable',
2253
- icon: 'dashboard',
2254
- children: [
2255
- {
2256
- id: 'feature-layout-apps',
2257
- title: 'Application',
2258
- type: 'collapsable',
2259
- icon: 'web',
2260
- children: [
2261
- {
2262
- id: 'feature-layout-apps-vertical',
2263
- title: 'Vertical',
2264
- type: 'basic',
2265
- icon: 'view_sidebar',
2266
- link: '/feature/layout/application/vertical',
2267
- },
2268
- {
2269
- id: 'feature-layout-apps-horizontal',
2270
- title: 'Horizontal',
2271
- type: 'basic',
2272
- icon: 'view_column',
2273
- link: '/feature/layout/application/horizontal',
2274
- },
2275
- ],
2276
- },
2277
- {
2278
- id: 'feature-layout-page',
2279
- title: 'Pages',
2280
- type: 'collapsable',
2281
- icon: 'description',
2282
- children: [
2283
- {
2284
- id: 'feature-layout-page-page',
2285
- title: 'Page',
2286
- type: 'basic',
2287
- icon: 'description',
2288
- link: '/feature/layout/page/page',
2289
- },
2290
- {
2291
- id: 'feature-layout-page-content',
2292
- title: 'Content',
2293
- type: 'basic',
2294
- icon: 'description',
2295
- link: '/feature/layout/page/content',
2296
- },
2297
- ],
2298
- },
2299
- ],
2300
- },
2301
- ],
2302
- },
2303
- {
2304
- id: 'feature-navigation',
2305
- title: 'Navigation',
2306
- type: 'collapsable',
2307
- icon: 'navigation',
2308
- children: [
2309
- {
2310
- id: 'feature-navigation-horizontal-navigation',
2311
- title: 'Horizontal ',
2312
- type: 'basic',
2313
- icon: 'view_column',
2314
- link: '/feature/navigation/horizontal',
2315
- },
2316
- {
2317
- id: 'feature-navigation-vertical-navigation',
2318
- title: 'Vertical ',
2319
- type: 'collapsable',
2320
- icon: 'view_agenda',
2321
- children: [
2322
- {
2323
- id: 'feature-navigation-vertical-navigation-default',
2324
- title: 'Default',
2325
- type: 'basic',
2326
- icon: 'view_agenda',
2327
- link: '/feature/navigation/vertical/default',
2328
- },
2329
- {
2330
- id: 'feature-navigation-vertical-navigation-thin',
2331
- title: 'Thin',
2332
- type: 'basic',
2333
- icon: 'view_agenda',
2334
- link: '/feature/navigation/vertical/thin',
2335
- },
2336
- {
2337
- id: 'feature-navigation-vertical-navigation-compact',
2338
- title: 'Compact',
2339
- type: 'basic',
2340
- icon: 'view_agenda',
2341
- link: '/feature/navigation/vertical/compact',
2342
- },
2343
- {
2344
- id: 'feature-navigation-vertical-navigation-dense',
2345
- title: 'Dense',
2346
- type: 'basic',
2347
- icon: 'view_agenda',
2348
- link: '/feature/navigation/vertical/dense',
2349
- },
2350
- ],
2351
- },
2352
- ],
2353
- },
2354
- ],
2355
- },
2356
- ];
2357
-
2358
- /*
2359
- * Public API Surface of @ojiepermana/angular/navigation
2360
- */
2361
- // Core
2362
- const NAVIGATION_VERSION = '0.0.1';
2363
-
2364
- /**
2365
- * Generated bundle index. Do not edit.
2366
- */
2367
-
2368
- export { DEFAULT_NAVIGATION_ID, DemoNavigationData, NAVIGATION_VERSION, NavigationService, SidebarComponent, TopbarComponent, UiNavIconComponent, UiNavItemComponent };
2369
- //# sourceMappingURL=ojiepermana-angular-navigation.mjs.map