@ojiepermana/angular 22.1.14 → 22.2.1

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 (252) hide show
  1. package/README.md +8 -6
  2. package/SUPPORT.md +3 -3
  3. package/chart/README.md +1 -1
  4. package/component/README.md +2 -2
  5. package/component/calendar/README.md +3 -15
  6. package/component/drawer/README.md +1 -2
  7. package/fesm2022/ojiepermana-angular-chart-area.mjs +352 -137
  8. package/fesm2022/ojiepermana-angular-chart-bar.mjs +744 -524
  9. package/fesm2022/ojiepermana-angular-chart-core.mjs +1140 -1344
  10. package/fesm2022/ojiepermana-angular-chart-line.mjs +393 -147
  11. package/fesm2022/ojiepermana-angular-chart-pie.mjs +408 -179
  12. package/fesm2022/ojiepermana-angular-chart-primitives.mjs +1262 -920
  13. package/fesm2022/ojiepermana-angular-chart-radar.mjs +473 -205
  14. package/fesm2022/ojiepermana-angular-chart-radial.mjs +425 -182
  15. package/fesm2022/ojiepermana-angular-chart-scatter.mjs +386 -210
  16. package/fesm2022/ojiepermana-angular-chart.mjs +3 -19
  17. package/fesm2022/ojiepermana-angular-component-accordion.mjs +485 -243
  18. package/fesm2022/ojiepermana-angular-component-alert-dialog.mjs +963 -325
  19. package/fesm2022/ojiepermana-angular-component-alert.mjs +266 -103
  20. package/fesm2022/ojiepermana-angular-component-aspect-ratio.mjs +80 -35
  21. package/fesm2022/ojiepermana-angular-component-avatar.mjs +402 -135
  22. package/fesm2022/ojiepermana-angular-component-badge.mjs +109 -59
  23. package/fesm2022/ojiepermana-angular-component-breadcrumb.mjs +410 -142
  24. package/fesm2022/ojiepermana-angular-component-button-group.mjs +249 -96
  25. package/fesm2022/ojiepermana-angular-component-button.mjs +153 -75
  26. package/fesm2022/ojiepermana-angular-component-calendar.mjs +531 -418
  27. package/fesm2022/ojiepermana-angular-component-card.mjs +457 -171
  28. package/fesm2022/ojiepermana-angular-component-carousel.mjs +642 -272
  29. package/fesm2022/ojiepermana-angular-component-checkbox.mjs +312 -108
  30. package/fesm2022/ojiepermana-angular-component-collapsible.mjs +299 -115
  31. package/fesm2022/ojiepermana-angular-component-combobox.mjs +396 -183
  32. package/fesm2022/ojiepermana-angular-component-command.mjs +807 -347
  33. package/fesm2022/ojiepermana-angular-component-composer.mjs +807 -330
  34. package/fesm2022/ojiepermana-angular-component-context-menu.mjs +196 -161
  35. package/fesm2022/ojiepermana-angular-component-date-picker.mjs +650 -338
  36. package/fesm2022/ojiepermana-angular-component-dialog.mjs +710 -316
  37. package/fesm2022/ojiepermana-angular-component-drawer.mjs +1 -5
  38. package/fesm2022/ojiepermana-angular-component-dropdown-menu.mjs +1212 -646
  39. package/fesm2022/ojiepermana-angular-component-editor.mjs +987 -502
  40. package/fesm2022/ojiepermana-angular-component-empty.mjs +350 -137
  41. package/fesm2022/ojiepermana-angular-component-form.mjs +813 -434
  42. package/fesm2022/ojiepermana-angular-component-hover-card.mjs +486 -277
  43. package/fesm2022/ojiepermana-angular-component-icon.mjs +241 -140
  44. package/fesm2022/ojiepermana-angular-component-input-group.mjs +449 -176
  45. package/fesm2022/ojiepermana-angular-component-input-otp.mjs +891 -488
  46. package/fesm2022/ojiepermana-angular-component-input.mjs +86 -55
  47. package/fesm2022/ojiepermana-angular-component-item.mjs +713 -261
  48. package/fesm2022/ojiepermana-angular-component-kanban.mjs +714 -216
  49. package/fesm2022/ojiepermana-angular-component-kbd.mjs +124 -52
  50. package/fesm2022/ojiepermana-angular-component-label.mjs +82 -31
  51. package/fesm2022/ojiepermana-angular-component-menubar.mjs +479 -329
  52. package/fesm2022/ojiepermana-angular-component-native-select.mjs +167 -65
  53. package/fesm2022/ojiepermana-angular-component-navigation-menu.mjs +683 -380
  54. package/fesm2022/ojiepermana-angular-component-pagination.mjs +277 -94
  55. package/fesm2022/ojiepermana-angular-component-pillbox.mjs +1283 -607
  56. package/fesm2022/ojiepermana-angular-component-popover.mjs +291 -204
  57. package/fesm2022/ojiepermana-angular-component-progress.mjs +176 -53
  58. package/fesm2022/ojiepermana-angular-component-radio.mjs +449 -142
  59. package/fesm2022/ojiepermana-angular-component-resizable.mjs +659 -453
  60. package/fesm2022/ojiepermana-angular-component-scroll-area.mjs +117 -39
  61. package/fesm2022/ojiepermana-angular-component-segmented-control.mjs +351 -172
  62. package/fesm2022/ojiepermana-angular-component-select.mjs +475 -345
  63. package/fesm2022/ojiepermana-angular-component-separator.mjs +102 -35
  64. package/fesm2022/ojiepermana-angular-component-sheet.mjs +797 -347
  65. package/fesm2022/ojiepermana-angular-component-skeleton.mjs +62 -29
  66. package/fesm2022/ojiepermana-angular-component-slider.mjs +592 -376
  67. package/fesm2022/ojiepermana-angular-component-spinner.mjs +135 -38
  68. package/fesm2022/ojiepermana-angular-component-switch.mjs +315 -103
  69. package/fesm2022/ojiepermana-angular-component-table.mjs +440 -153
  70. package/fesm2022/ojiepermana-angular-component-tabs.mjs +590 -317
  71. package/fesm2022/ojiepermana-angular-component-textarea.mjs +85 -50
  72. package/fesm2022/ojiepermana-angular-component-timeline.mjs +609 -231
  73. package/fesm2022/ojiepermana-angular-component-toast.mjs +229 -243
  74. package/fesm2022/ojiepermana-angular-component-toggle-group.mjs +573 -288
  75. package/fesm2022/ojiepermana-angular-component-toggle.mjs +187 -78
  76. package/fesm2022/ojiepermana-angular-component-tooltip.mjs +798 -517
  77. package/fesm2022/ojiepermana-angular-component-utils-core.mjs +159 -292
  78. package/fesm2022/ojiepermana-angular-component-utils-overlay.mjs +46 -58
  79. package/fesm2022/ojiepermana-angular-component-utils-scale.mjs +76 -38
  80. package/fesm2022/ojiepermana-angular-component-utils.mjs +2 -8
  81. package/fesm2022/ojiepermana-angular-component.mjs +0 -10
  82. package/fesm2022/ojiepermana-angular-navigation-core.mjs +13 -23
  83. package/fesm2022/ojiepermana-angular-navigation-icon.mjs +35 -24
  84. package/fesm2022/ojiepermana-angular-navigation-navigation-badge-count.component-DYuysKVf.mjs +129 -0
  85. package/fesm2022/ojiepermana-angular-navigation-navigation-dockbar-menu.component-COiTaw34.mjs +812 -0
  86. package/fesm2022/{ojiepermana-angular-navigation-navigation-entry-grid.component-COQ-60DS.mjs → ojiepermana-angular-navigation-navigation-entry-grid.component-YIz0IsIb.mjs} +392 -207
  87. package/fesm2022/ojiepermana-angular-navigation-navigation-flyout-menu.component-D2vwEwBY.mjs +650 -0
  88. package/fesm2022/ojiepermana-angular-navigation-navigation-horizontal.component-B5D7yXfb.mjs +662 -0
  89. package/fesm2022/ojiepermana-angular-navigation-navigation-item.component-CUb68MZH.mjs +1219 -0
  90. package/fesm2022/ojiepermana-angular-navigation-navigation-list.component-CrK16trj.mjs +327 -0
  91. package/fesm2022/ojiepermana-angular-navigation-service.mjs +544 -724
  92. package/fesm2022/ojiepermana-angular-navigation-types.mjs +139 -56
  93. package/fesm2022/ojiepermana-angular-navigation.mjs +3256 -4
  94. package/fesm2022/ojiepermana-angular-sdk.mjs +91 -201
  95. package/fesm2022/ojiepermana-angular-theme-component-settings.mjs +1125 -737
  96. package/fesm2022/ojiepermana-angular-theme-layout-services.mjs +245 -328
  97. package/fesm2022/ojiepermana-angular-theme-layout-types.mjs +35 -38
  98. package/fesm2022/ojiepermana-angular-theme-layout-wrapper.mjs +1928 -553
  99. package/fesm2022/ojiepermana-angular-theme-layout.mjs +847 -496
  100. package/fesm2022/ojiepermana-angular-theme-page-core.mjs +288 -358
  101. package/fesm2022/ojiepermana-angular-theme-page-filter.mjs +362 -224
  102. package/fesm2022/ojiepermana-angular-theme-page-overview.mjs +88 -0
  103. package/fesm2022/ojiepermana-angular-theme-page-root.mjs +576 -254
  104. package/fesm2022/ojiepermana-angular-theme-page-side.mjs +317 -177
  105. package/fesm2022/ojiepermana-angular-theme-page-slots.mjs +256 -112
  106. package/fesm2022/ojiepermana-angular-theme-page.mjs +7 -12
  107. package/fesm2022/ojiepermana-angular-theme-shell-services.mjs +215 -326
  108. package/fesm2022/ojiepermana-angular-theme-shell-types.mjs +68 -129
  109. package/fesm2022/ojiepermana-angular-theme-shell.mjs +907 -378
  110. package/fesm2022/ojiepermana-angular-theme-styles.mjs +521 -720
  111. package/fesm2022/ojiepermana-angular-theme.mjs +0 -10
  112. package/fesm2022/ojiepermana-angular.mjs +5 -24
  113. package/navigation/README.md +69 -18
  114. package/package.json +16 -12
  115. package/sdk/README.md +1 -1
  116. package/sdk/src/writer/index.js +2 -2
  117. package/theme/README.md +1 -1
  118. package/theme/layout/README.md +2 -4
  119. package/theme/page/README.md +50 -0
  120. package/theme/styles/README.md +10 -10
  121. package/theme/styles/css/base/prefers-dark.css +1 -1
  122. package/theme/styles/css/base/status.css +1 -1
  123. package/theme/styles/css/color/amber.css +1 -1
  124. package/theme/styles/css/color/blue.css +1 -1
  125. package/theme/styles/css/color/cyan.css +1 -1
  126. package/theme/styles/css/color/emerald.css +1 -1
  127. package/theme/styles/css/color/fuchsia.css +1 -1
  128. package/theme/styles/css/color/green.css +1 -1
  129. package/theme/styles/css/color/indigo.css +1 -1
  130. package/theme/styles/css/color/lime.css +1 -1
  131. package/theme/styles/css/color/orange.css +1 -1
  132. package/theme/styles/css/color/pink.css +1 -1
  133. package/theme/styles/css/color/purple.css +1 -1
  134. package/theme/styles/css/color/red.css +1 -1
  135. package/theme/styles/css/color/rose.css +1 -1
  136. package/theme/styles/css/color/sky.css +1 -1
  137. package/theme/styles/css/color/teal.css +1 -1
  138. package/theme/styles/css/color/violet.css +1 -1
  139. package/theme/styles/css/color/yellow.css +1 -1
  140. package/theme/styles/css/neutral/gray.css +1 -1
  141. package/theme/styles/css/neutral/mauve.css +1 -1
  142. package/theme/styles/css/neutral/mist.css +1 -1
  143. package/theme/styles/css/neutral/neutral.css +1 -1
  144. package/theme/styles/css/neutral/olive.css +1 -1
  145. package/theme/styles/css/neutral/slate.css +1 -1
  146. package/theme/styles/css/neutral/stone.css +1 -1
  147. package/theme/styles/css/neutral/taupe.css +1 -1
  148. package/theme/styles/css/neutral/zinc.css +1 -1
  149. package/types/ojiepermana-angular-chart-area.d.ts +126 -63
  150. package/types/ojiepermana-angular-chart-bar.d.ts +244 -154
  151. package/types/ojiepermana-angular-chart-core.d.ts +409 -398
  152. package/types/ojiepermana-angular-chart-line.d.ts +141 -68
  153. package/types/ojiepermana-angular-chart-pie.d.ts +192 -121
  154. package/types/ojiepermana-angular-chart-primitives.d.ts +283 -214
  155. package/types/ojiepermana-angular-chart-radar.d.ts +189 -108
  156. package/types/ojiepermana-angular-chart-radial.d.ts +177 -106
  157. package/types/ojiepermana-angular-chart-scatter.d.ts +166 -110
  158. package/types/ojiepermana-angular-chart.d.ts +3 -2
  159. package/types/ojiepermana-angular-component-accordion.d.ts +135 -81
  160. package/types/ojiepermana-angular-component-alert-dialog.d.ts +271 -123
  161. package/types/ojiepermana-angular-component-alert.d.ts +69 -39
  162. package/types/ojiepermana-angular-component-aspect-ratio.d.ts +20 -12
  163. package/types/ojiepermana-angular-component-avatar.d.ts +103 -49
  164. package/types/ojiepermana-angular-component-badge.d.ts +36 -24
  165. package/types/ojiepermana-angular-component-breadcrumb.d.ts +79 -40
  166. package/types/ojiepermana-angular-component-button-group.d.ts +48 -24
  167. package/types/ojiepermana-angular-component-button.d.ts +44 -27
  168. package/types/ojiepermana-angular-component-calendar.d.ts +145 -107
  169. package/types/ojiepermana-angular-component-card.d.ts +112 -63
  170. package/types/ojiepermana-angular-component-carousel.d.ts +150 -81
  171. package/types/ojiepermana-angular-component-checkbox.d.ts +96 -38
  172. package/types/ojiepermana-angular-component-collapsible.d.ts +65 -39
  173. package/types/ojiepermana-angular-component-combobox.d.ts +100 -55
  174. package/types/ojiepermana-angular-component-command.d.ts +206 -121
  175. package/types/ojiepermana-angular-component-composer.d.ts +184 -84
  176. package/types/ojiepermana-angular-component-context-menu.d.ts +51 -41
  177. package/types/ojiepermana-angular-component-date-picker.d.ts +199 -109
  178. package/types/ojiepermana-angular-component-dialog.d.ts +200 -105
  179. package/types/ojiepermana-angular-component-drawer.d.ts +2 -1
  180. package/types/ojiepermana-angular-component-dropdown-menu.d.ts +324 -202
  181. package/types/ojiepermana-angular-component-editor.d.ts +215 -117
  182. package/types/ojiepermana-angular-component-empty.d.ts +80 -45
  183. package/types/ojiepermana-angular-component-form.d.ts +185 -121
  184. package/types/ojiepermana-angular-component-hover-card.d.ts +130 -72
  185. package/types/ojiepermana-angular-component-icon.d.ts +87 -57
  186. package/types/ojiepermana-angular-component-input-group.d.ts +93 -46
  187. package/types/ojiepermana-angular-component-input-otp.d.ts +243 -150
  188. package/types/ojiepermana-angular-component-input.d.ts +27 -17
  189. package/types/ojiepermana-angular-component-item.d.ts +160 -84
  190. package/types/ojiepermana-angular-component-kanban.d.ts +157 -62
  191. package/types/ojiepermana-angular-component-kbd.d.ts +24 -15
  192. package/types/ojiepermana-angular-component-label.d.ts +19 -11
  193. package/types/ojiepermana-angular-component-menubar.d.ts +120 -90
  194. package/types/ojiepermana-angular-component-native-select.d.ts +37 -24
  195. package/types/ojiepermana-angular-component-navigation-menu.d.ts +157 -98
  196. package/types/ojiepermana-angular-component-pagination.d.ts +78 -28
  197. package/types/ojiepermana-angular-component-pillbox.d.ts +361 -204
  198. package/types/ojiepermana-angular-component-popover.d.ts +94 -64
  199. package/types/ojiepermana-angular-component-progress.d.ts +45 -17
  200. package/types/ojiepermana-angular-component-radio.d.ts +129 -53
  201. package/types/ojiepermana-angular-component-resizable.d.ts +160 -112
  202. package/types/ojiepermana-angular-component-scroll-area.d.ts +33 -15
  203. package/types/ojiepermana-angular-component-segmented-control.d.ts +94 -50
  204. package/types/ojiepermana-angular-component-select.d.ts +94 -77
  205. package/types/ojiepermana-angular-component-separator.d.ts +26 -14
  206. package/types/ojiepermana-angular-component-sheet.d.ts +226 -116
  207. package/types/ojiepermana-angular-component-skeleton.d.ts +13 -10
  208. package/types/ojiepermana-angular-component-slider.d.ts +140 -75
  209. package/types/ojiepermana-angular-component-spinner.d.ts +31 -13
  210. package/types/ojiepermana-angular-component-switch.d.ts +97 -40
  211. package/types/ojiepermana-angular-component-table.d.ts +102 -50
  212. package/types/ojiepermana-angular-component-tabs.d.ts +174 -115
  213. package/types/ojiepermana-angular-component-textarea.d.ts +27 -17
  214. package/types/ojiepermana-angular-component-timeline.d.ts +141 -59
  215. package/types/ojiepermana-angular-component-toast.d.ts +51 -55
  216. package/types/ojiepermana-angular-component-toggle-group.d.ts +159 -88
  217. package/types/ojiepermana-angular-component-toggle.d.ts +47 -25
  218. package/types/ojiepermana-angular-component-tooltip.d.ts +222 -132
  219. package/types/ojiepermana-angular-component-utils-core.d.ts +81 -90
  220. package/types/ojiepermana-angular-component-utils-overlay.d.ts +7 -11
  221. package/types/ojiepermana-angular-component-utils-scale.d.ts +20 -12
  222. package/types/ojiepermana-angular-component-utils.d.ts +2 -2
  223. package/types/ojiepermana-angular-component.d.ts +1 -2
  224. package/types/ojiepermana-angular-navigation-core.d.ts +46 -50
  225. package/types/ojiepermana-angular-navigation-icon.d.ts +9 -12
  226. package/types/ojiepermana-angular-navigation-service.d.ts +112 -115
  227. package/types/ojiepermana-angular-navigation-types.d.ts +166 -125
  228. package/types/ojiepermana-angular-navigation.d.ts +708 -375
  229. package/types/ojiepermana-angular-sdk.d.ts +69 -71
  230. package/types/ojiepermana-angular-theme-component-settings.d.ts +120 -86
  231. package/types/ojiepermana-angular-theme-layout-services.d.ts +119 -124
  232. package/types/ojiepermana-angular-theme-layout-types.d.ts +27 -31
  233. package/types/ojiepermana-angular-theme-layout-wrapper.d.ts +446 -187
  234. package/types/ojiepermana-angular-theme-layout.d.ts +201 -113
  235. package/types/ojiepermana-angular-theme-page-core.d.ts +136 -142
  236. package/types/ojiepermana-angular-theme-page-filter.d.ts +112 -62
  237. package/types/ojiepermana-angular-theme-page-overview.d.ts +28 -0
  238. package/types/ojiepermana-angular-theme-page-root.d.ts +172 -88
  239. package/types/ojiepermana-angular-theme-page-side.d.ts +89 -49
  240. package/types/ojiepermana-angular-theme-page-slots.d.ts +58 -37
  241. package/types/ojiepermana-angular-theme-page.d.ts +7 -5
  242. package/types/ojiepermana-angular-theme-shell-services.d.ts +119 -125
  243. package/types/ojiepermana-angular-theme-shell-types.d.ts +38 -41
  244. package/types/ojiepermana-angular-theme-shell.d.ts +139 -61
  245. package/types/ojiepermana-angular-theme-styles.d.ts +184 -196
  246. package/types/ojiepermana-angular-theme.d.ts +1 -2
  247. package/types/ojiepermana-angular.d.ts +5 -5
  248. package/fesm2022/ojiepermana-angular-navigation-navigation-badge-count.component-Be3IqzG4.mjs +0 -91
  249. package/fesm2022/ojiepermana-angular-navigation-navigation-dockbar-menu.component-Bc7DWK3R.mjs +0 -522
  250. package/fesm2022/ojiepermana-angular-navigation-navigation-flyout-menu.component-DA8VPEn7.mjs +0 -404
  251. package/fesm2022/ojiepermana-angular-navigation-navigation-horizontal.component-U2TJTzlW.mjs +0 -466
  252. package/fesm2022/ojiepermana-angular-navigation-ojiepermana-angular-navigation-CIUhmytH.mjs +0 -2668
@@ -1,729 +1,549 @@
1
- import { DOCUMENT } from '@angular/common';
2
- import * as i0 from '@angular/core';
3
- import { inject, signal, computed, isDevMode, Service } from '@angular/core';
4
- import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
5
- import { DefaultUrlSerializer, UrlTree, PRIMARY_OUTLET, Router, NavigationEnd } from '@angular/router';
6
- import { documentLocalStorage } from '@ojiepermana/angular/component/utils/core';
7
-
8
- const DEFAULT_NAVIGATION_ID = 'default';
9
- const PERSISTED_NAVIGATION_ID = 'main';
1
+ import { DOCUMENT } from "@angular/common";
2
+ import * as i0 from "@angular/core";
3
+ import { Service, computed, inject, isDevMode, signal } from "@angular/core";
4
+ import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
5
+ import { DefaultUrlSerializer, NavigationEnd, PRIMARY_OUTLET, Router, UrlTree, containsTree } from "@angular/router";
6
+ import { documentLocalStorage } from "@ojiepermana/angular/component/utils/core";
7
+ const DEFAULT_NAVIGATION_ID = "default";
8
+ const PERSISTED_NAVIGATION_ID = "main";
10
9
  const INSTANCE_STORAGE_PROPERTIES = [
11
- 'orientation',
12
- 'appearance',
13
- 'position',
14
- 'collapsed',
15
- 'dockbar-mode',
10
+ "orientation",
11
+ "appearance",
12
+ "position",
13
+ "collapsed",
14
+ "dockbar-mode"
16
15
  ];
17
- const TYPE_MODE_STORAGE_KEY = 'nav-type-mode';
18
- /** Resolves and persists the small navigation state contract without owning UI state. */
19
- class NavigationPersistence {
20
- documentRef;
21
- /**
22
- * The same never-throwing localStorage wrapper the theme axes use. It lives in
23
- * `component/utils/core` rather than in the theme package precisely so this
24
- * class can share it: navigation must not depend on theme, which already
25
- * depends on navigation.
26
- */
27
- storageRef;
28
- constructor(documentRef) {
29
- this.documentRef = documentRef;
30
- this.storageRef = documentLocalStorage(documentRef);
31
- }
32
- resolveState(input) {
33
- const id = this.normalizeId(input.id);
34
- const orientation = input.orientation;
35
- const type = this.resolveType(id, orientation, input.type);
36
- return {
37
- id,
38
- orientation,
39
- type,
40
- position: this.resolvePosition(id, orientation, input.position),
41
- collapsed: this.resolveCollapsed(id, type, input.collapsed),
42
- dockbarMode: this.resolveDockbarMode(id, type, input.dockbarMode),
43
- };
44
- }
45
- persistState(state) {
46
- if (state.id !== PERSISTED_NAVIGATION_ID) {
47
- this.clearLegacyInstanceStorage(state.id);
48
- return;
49
- }
50
- this.writeStorage(this.persistedStorageKey('orientation'), state.orientation);
51
- this.writeStorage(this.persistedStorageKey('type'), state.type);
52
- this.writeStorage(this.persistedStorageKey('position'), state.position);
53
- this.writeStorage(TYPE_MODE_STORAGE_KEY, this.persistedTypeMode(state));
54
- }
55
- normalizeId(id) {
56
- return id.trim() || DEFAULT_NAVIGATION_ID;
57
- }
58
- resolveType(id, orientation, type) {
59
- if (this.isTypeForOrientation(type, orientation))
60
- return type;
61
- const stored = this.readInstanceStorage(id, 'type');
62
- if (this.isTypeForOrientation(stored, orientation))
63
- return stored;
64
- return orientation === 'vertical' ? 'sidebar' : 'navbar';
65
- }
66
- resolvePosition(id, orientation, position) {
67
- if (this.isPositionForOrientation(position, orientation))
68
- return position;
69
- const stored = this.readInstanceStorage(id, 'position');
70
- if (this.isPositionForOrientation(stored, orientation))
71
- return stored;
72
- return orientation === 'horizontal' ? 'top' : 'left';
73
- }
74
- resolveCollapsed(id, type, collapsed) {
75
- if (typeof collapsed === 'boolean')
76
- return collapsed;
77
- return type === 'sidebar' && this.readPersistedTypeMode(id) === 'collapsed';
78
- }
79
- resolveDockbarMode(id, type, mode) {
80
- if (this.isDockbarMode(mode))
81
- return mode;
82
- if (type !== 'dockbar')
83
- return 'sticky';
84
- const stored = this.readPersistedTypeMode(id);
85
- return this.isDockbarMode(stored) ? stored : 'sticky';
86
- }
87
- readStorage(key) {
88
- return this.storageRef.read(key);
89
- }
90
- readInstanceStorage(id, property) {
91
- return id === PERSISTED_NAVIGATION_ID
92
- ? this.readStorage(this.persistedStorageKey(property))
93
- : null;
94
- }
95
- readPersistedTypeMode(id) {
96
- if (id !== PERSISTED_NAVIGATION_ID)
97
- return null;
98
- const stored = this.readStorage(TYPE_MODE_STORAGE_KEY);
99
- return this.isPersistedTypeMode(stored) ? stored : null;
100
- }
101
- writeStorage(key, value) {
102
- this.storageRef.write(key, value);
103
- }
104
- removeStorage(key) {
105
- this.storageRef.remove(key);
106
- }
107
- clearLegacyInstanceStorage(id) {
108
- for (const property of INSTANCE_STORAGE_PROPERTIES) {
109
- this.removeStorage(`nav:${id}:${property}`);
110
- }
111
- }
112
- persistedStorageKey(property) {
113
- return `nav-${property}`;
114
- }
115
- persistedTypeMode(state) {
116
- if (state.type === 'dockbar')
117
- return state.dockbarMode;
118
- return state.collapsed ? 'collapsed' : 'default';
119
- }
120
- isPersistedTypeMode(value) {
121
- return value === 'default' || value === 'collapsed' || this.isDockbarMode(value);
122
- }
123
- isTypeForOrientation(value, orientation) {
124
- return orientation === 'vertical'
125
- ? value === 'sidebar' || value === 'dockbar'
126
- : value === 'navbar' || value === 'flyout';
127
- }
128
- isPositionForOrientation(value, orientation) {
129
- return orientation === 'vertical'
130
- ? value === 'left' || value === 'right'
131
- : value === 'top' || value === 'bottom';
132
- }
133
- isDockbarMode(value) {
134
- return value === 'drawer' || value === 'sticky';
135
- }
136
- }
137
-
138
- /**
139
- * Turns navigation items into `UrlTree`s and matches them against the active
140
- * URL. Both halves are memoized: the active URL is parsed once per walk, and an
141
- * item's own tree is cached against the item, because `Router.createUrlTree` is
142
- * the expensive half and a plain absolute link resolves to the same tree for the
143
- * life of that item. The cache is keyed by the normalized item, so it is
144
- * discarded with the item the moment `normalizeUiNavItems` runs again.
145
- */
146
- class NavigationActiveUrlResolver {
147
- router;
148
- urlSerializer = new DefaultUrlSerializer();
149
- itemUrlTrees = new WeakMap();
150
- activeUrlTree = null;
151
- constructor(router) {
152
- this.router = router;
153
- }
154
- match(activeUrl, routerUrl, relativeTo) {
155
- return { activeUrl, activeTree: this.parseActiveUrl(activeUrl), relativeTo, routerUrl };
156
- }
157
- matches(item, match, options) {
158
- const activeTree = match.activeTree;
159
- if (!item.link || item.externalLink || activeTree === null) {
160
- return false;
161
- }
162
- const itemTree = this.cachedItemUrlTree(item, match, activeTree);
163
- return itemTree === null ? false : containsNavigationUrlTree(activeTree, itemTree, options);
164
- }
165
- cachedItemUrlTree(item, match, activeTree) {
166
- if (match.relativeTo !== null) {
167
- return this.itemUrlTree(item, activeTree, match.relativeTo);
168
- }
169
- const key = this.dependsOnActiveUrl(item) ? `${match.activeUrl} ${match.routerUrl}` : null;
170
- const cached = this.itemUrlTrees.get(item);
171
- if (cached !== undefined && cached.key === key) {
172
- return cached.tree;
173
- }
174
- const tree = this.itemUrlTree(item, activeTree, null);
175
- this.itemUrlTrees.set(item, { key, tree });
176
- return tree;
177
- }
178
- /** A relative or query/fragment-inheriting link resolves against the live URL. */
179
- dependsOnActiveUrl(item) {
180
- if (item.preserveFragment === true ||
181
- item.queryParamsHandling === 'preserve' ||
182
- item.queryParamsHandling === 'merge') {
183
- return true;
184
- }
185
- const link = item.link;
186
- if (link instanceof UrlTree) {
187
- return false;
188
- }
189
- if (typeof link === 'string') {
190
- return !link.startsWith('/');
191
- }
192
- const first = Array.isArray(link) ? link[0] : undefined;
193
- return !(typeof first === 'string' && first.startsWith('/'));
194
- }
195
- parseActiveUrl(url) {
196
- if (this.activeUrlTree !== null && this.activeUrlTree.url === url) {
197
- return this.activeUrlTree.tree;
198
- }
199
- const tree = this.parseUrl(url);
200
- this.activeUrlTree = { url, tree };
201
- return tree;
202
- }
203
- itemUrlTree(item, activeTree, relativeTo) {
204
- const link = item.link;
205
- if (!link) {
206
- return null;
207
- }
208
- if (link instanceof UrlTree) {
209
- return link;
210
- }
211
- if (this.router !== null) {
212
- try {
213
- const commands = typeof link === 'string' ? [link] : Array.from(link);
214
- return this.router.createUrlTree(commands, {
215
- relativeTo,
216
- queryParams: item.queryParams,
217
- queryParamsHandling: item.queryParamsHandling,
218
- fragment: item.fragment,
219
- preserveFragment: item.preserveFragment,
220
- });
221
- }
222
- catch {
223
- return null;
224
- }
225
- }
226
- const baseTree = typeof link === 'string' ? this.parseUrl(link) : null;
227
- return baseTree === null ? null : this.applyRouteExtras(baseTree, item, activeTree);
228
- }
229
- applyRouteExtras(baseTree, item, activeTree) {
230
- const handling = item.queryParamsHandling ?? 'replace';
231
- let queryParams = baseTree.queryParams;
232
- if (handling === 'preserve') {
233
- queryParams = activeTree.queryParams;
234
- }
235
- else if (handling === 'merge') {
236
- queryParams = { ...activeTree.queryParams, ...(item.queryParams ?? {}) };
237
- }
238
- else if (item.queryParams !== undefined) {
239
- queryParams = item.queryParams ?? {};
240
- }
241
- const fragment = item.preserveFragment
242
- ? activeTree.fragment
243
- : (item.fragment ?? baseTree.fragment);
244
- try {
245
- // Serialize + parse normalizes numeric/array query values exactly as the
246
- // Router does before applying IsActiveMatchOptions.
247
- return this.urlSerializer.parse(this.urlSerializer.serialize(new UrlTree(baseTree.root, queryParams, fragment)));
248
- }
249
- catch {
250
- return null;
251
- }
252
- }
253
- parseUrl(url) {
254
- try {
255
- return this.router?.parseUrl(url) ?? this.urlSerializer.parse(url);
256
- }
257
- catch {
258
- return null;
259
- }
260
- }
261
- }
262
- /** Pure equivalent of Router's UrlTree containment semantics for an explicit active URL. */
16
+ const TYPE_MODE_STORAGE_KEY = "nav-type-mode";
17
+ var NavigationPersistence = class {
18
+ documentRef;
19
+ storageRef;
20
+ constructor(documentRef) {
21
+ this.documentRef = documentRef;
22
+ this.storageRef = documentLocalStorage(documentRef);
23
+ }
24
+ resolveState(input) {
25
+ const id = this.normalizeId(input.id);
26
+ const orientation = input.orientation;
27
+ const type = this.resolveType(id, orientation, input.type);
28
+ return {
29
+ id,
30
+ orientation,
31
+ type,
32
+ position: this.resolvePosition(id, orientation, input.position),
33
+ collapsed: this.resolveCollapsed(id, type, input.collapsed),
34
+ dockbarMode: this.resolveDockbarMode(id, type, input.dockbarMode)
35
+ };
36
+ }
37
+ persistState(state) {
38
+ if (state.id !== PERSISTED_NAVIGATION_ID) {
39
+ this.clearLegacyInstanceStorage(state.id);
40
+ return;
41
+ }
42
+ this.writeStorage(this.persistedStorageKey("orientation"), state.orientation);
43
+ this.writeStorage(this.persistedStorageKey("type"), state.type);
44
+ this.writeStorage(this.persistedStorageKey("position"), state.position);
45
+ this.writeStorage(TYPE_MODE_STORAGE_KEY, this.persistedTypeMode(state));
46
+ }
47
+ normalizeId(id) {
48
+ return id.trim() || "default";
49
+ }
50
+ resolveType(id, orientation, type) {
51
+ if (this.isTypeForOrientation(type, orientation)) return type;
52
+ const stored = this.readInstanceStorage(id, "type");
53
+ if (this.isTypeForOrientation(stored, orientation)) return stored;
54
+ return orientation === "vertical" ? "sidebar" : "navbar";
55
+ }
56
+ resolvePosition(id, orientation, position) {
57
+ if (this.isPositionForOrientation(position, orientation)) return position;
58
+ const stored = this.readInstanceStorage(id, "position");
59
+ if (this.isPositionForOrientation(stored, orientation)) return stored;
60
+ return orientation === "horizontal" ? "top" : "left";
61
+ }
62
+ resolveCollapsed(id, type, collapsed) {
63
+ if (typeof collapsed === "boolean") return collapsed;
64
+ return type === "sidebar" && this.readPersistedTypeMode(id) === "collapsed";
65
+ }
66
+ resolveDockbarMode(id, type, mode) {
67
+ if (this.isDockbarMode(mode)) return mode;
68
+ if (type !== "dockbar") return "sticky";
69
+ const stored = this.readPersistedTypeMode(id);
70
+ return this.isDockbarMode(stored) ? stored : "sticky";
71
+ }
72
+ readStorage(key) {
73
+ return this.storageRef.read(key);
74
+ }
75
+ readInstanceStorage(id, property) {
76
+ return id === PERSISTED_NAVIGATION_ID ? this.readStorage(this.persistedStorageKey(property)) : null;
77
+ }
78
+ readPersistedTypeMode(id) {
79
+ if (id !== PERSISTED_NAVIGATION_ID) return null;
80
+ const stored = this.readStorage(TYPE_MODE_STORAGE_KEY);
81
+ return this.isPersistedTypeMode(stored) ? stored : null;
82
+ }
83
+ writeStorage(key, value) {
84
+ this.storageRef.write(key, value);
85
+ }
86
+ removeStorage(key) {
87
+ this.storageRef.remove(key);
88
+ }
89
+ clearLegacyInstanceStorage(id) {
90
+ for (const property of INSTANCE_STORAGE_PROPERTIES) this.removeStorage(`nav:${id}:${property}`);
91
+ }
92
+ persistedStorageKey(property) {
93
+ return `nav-${property}`;
94
+ }
95
+ persistedTypeMode(state) {
96
+ if (state.type === "dockbar") return state.dockbarMode;
97
+ if (state.type === "minidock") return "default";
98
+ return state.collapsed ? "collapsed" : "default";
99
+ }
100
+ isPersistedTypeMode(value) {
101
+ return value === "default" || value === "collapsed" || this.isDockbarMode(value);
102
+ }
103
+ isTypeForOrientation(value, orientation) {
104
+ return orientation === "vertical" ? value === "sidebar" || value === "dockbar" || value === "minidock" : value === "navbar" || value === "flyout";
105
+ }
106
+ isPositionForOrientation(value, orientation) {
107
+ return orientation === "vertical" ? value === "left" || value === "right" : value === "top" || value === "bottom";
108
+ }
109
+ isDockbarMode(value) {
110
+ return value === "drawer" || value === "sticky";
111
+ }
112
+ };
113
+ var NavigationActiveUrlResolver = class {
114
+ router;
115
+ urlSerializer = new DefaultUrlSerializer();
116
+ itemUrlTrees = /* @__PURE__ */ new WeakMap();
117
+ activeUrlTree = null;
118
+ constructor(router) {
119
+ this.router = router;
120
+ }
121
+ match(activeUrl, routerUrl, relativeTo) {
122
+ return {
123
+ activeUrl,
124
+ activeTree: this.parseActiveUrl(activeUrl),
125
+ relativeTo,
126
+ routerUrl
127
+ };
128
+ }
129
+ matches(item, match, options) {
130
+ const activeTree = match.activeTree;
131
+ if (!item.link || item.externalLink || activeTree === null) return false;
132
+ const itemTree = this.cachedItemUrlTree(item, match, activeTree);
133
+ return itemTree === null ? false : containsNavigationUrlTree(activeTree, itemTree, options);
134
+ }
135
+ cachedItemUrlTree(item, match, activeTree) {
136
+ if (match.relativeTo !== null) return this.itemUrlTree(item, activeTree, match.relativeTo);
137
+ const key = this.dependsOnActiveUrl(item) ? `${match.activeUrl} ${match.routerUrl}` : null;
138
+ const cached = this.itemUrlTrees.get(item);
139
+ if (cached !== void 0 && cached.key === key) return cached.tree;
140
+ const tree = this.itemUrlTree(item, activeTree, null);
141
+ this.itemUrlTrees.set(item, {
142
+ key,
143
+ tree
144
+ });
145
+ return tree;
146
+ }
147
+ dependsOnActiveUrl(item) {
148
+ if (item.preserveFragment === true || item.queryParamsHandling === "preserve" || item.queryParamsHandling === "merge") return true;
149
+ const link = item.link;
150
+ if (link instanceof UrlTree) return false;
151
+ if (typeof link === "string") return !link.startsWith("/");
152
+ const first = Array.isArray(link) ? link[0] : void 0;
153
+ return !(typeof first === "string" && first.startsWith("/"));
154
+ }
155
+ parseActiveUrl(url) {
156
+ if (this.activeUrlTree !== null && this.activeUrlTree.url === url) return this.activeUrlTree.tree;
157
+ const tree = this.parseUrl(url);
158
+ this.activeUrlTree = {
159
+ url,
160
+ tree
161
+ };
162
+ return tree;
163
+ }
164
+ itemUrlTree(item, activeTree, relativeTo) {
165
+ const link = item.link;
166
+ if (!link) return null;
167
+ if (link instanceof UrlTree) return link;
168
+ if (this.router !== null) try {
169
+ const commands = typeof link === "string" ? [link] : Array.from(link);
170
+ return this.router.createUrlTree(commands, {
171
+ relativeTo,
172
+ queryParams: item.queryParams,
173
+ queryParamsHandling: item.queryParamsHandling,
174
+ fragment: item.fragment,
175
+ preserveFragment: item.preserveFragment
176
+ });
177
+ } catch {
178
+ return null;
179
+ }
180
+ const baseTree = typeof link === "string" ? this.parseUrl(link) : null;
181
+ return baseTree === null ? null : this.applyRouteExtras(baseTree, item, activeTree);
182
+ }
183
+ applyRouteExtras(baseTree, item, activeTree) {
184
+ const handling = item.queryParamsHandling ?? "replace";
185
+ let queryParams = baseTree.queryParams;
186
+ if (handling === "preserve") queryParams = activeTree.queryParams;
187
+ else if (handling === "merge") queryParams = {
188
+ ...activeTree.queryParams,
189
+ ...item.queryParams ?? {}
190
+ };
191
+ else if (item.queryParams !== void 0) queryParams = item.queryParams ?? {};
192
+ const fragment = item.preserveFragment ? activeTree.fragment : item.fragment ?? baseTree.fragment;
193
+ try {
194
+ return this.urlSerializer.parse(this.urlSerializer.serialize(new UrlTree(baseTree.root, queryParams, fragment)));
195
+ } catch {
196
+ return null;
197
+ }
198
+ }
199
+ parseUrl(url) {
200
+ try {
201
+ return this.router?.parseUrl(url) ?? this.urlSerializer.parse(url);
202
+ } catch {
203
+ return null;
204
+ }
205
+ }
206
+ };
263
207
  function containsNavigationUrlTree(container, containee, options) {
264
- return (segmentGroupsMatch(container.root, containee.root, options.paths, options.matrixParams) &&
265
- paramsMatch(container.queryParams, containee.queryParams, options.queryParams) &&
266
- (options.fragment === 'ignored' || container.fragment === containee.fragment));
267
- }
268
- function segmentGroupsMatch(container, containee, paths, matrixParams) {
269
- return paths === 'exact'
270
- ? equalSegmentGroups(container, containee, matrixParams)
271
- : containsSegmentGroup(container, containee, matrixParams);
272
- }
273
- function equalSegmentGroups(container, containee, matrixParams) {
274
- if (!equalPaths(container.segments, containee.segments) ||
275
- !matrixParamsMatch(container.segments, containee.segments, matrixParams) ||
276
- container.numberOfChildren !== containee.numberOfChildren) {
277
- return false;
278
- }
279
- return Object.entries(containee.children).every(([outlet, child]) => container.children[outlet] !== undefined &&
280
- equalSegmentGroups(container.children[outlet], child, matrixParams));
281
- }
282
- function containsSegmentGroup(container, containee, matrixParams) {
283
- return containsSegmentGroupPaths(container, containee, containee.segments, matrixParams);
284
- }
285
- function containsSegmentGroupPaths(container, containee, containeePaths, matrixParams) {
286
- if (container.segments.length > containeePaths.length) {
287
- const current = container.segments.slice(0, containeePaths.length);
288
- return (equalPaths(current, containeePaths) &&
289
- !containee.hasChildren() &&
290
- matrixParamsMatch(current, containeePaths, matrixParams));
291
- }
292
- if (container.segments.length === containeePaths.length) {
293
- if (!equalPaths(container.segments, containeePaths) ||
294
- !matrixParamsMatch(container.segments, containeePaths, matrixParams)) {
295
- return false;
296
- }
297
- return Object.entries(containee.children).every(([outlet, child]) => container.children[outlet] !== undefined &&
298
- containsSegmentGroup(container.children[outlet], child, matrixParams));
299
- }
300
- const current = containeePaths.slice(0, container.segments.length);
301
- const next = containeePaths.slice(container.segments.length);
302
- const primary = container.children[PRIMARY_OUTLET];
303
- return (equalPaths(container.segments, current) &&
304
- matrixParamsMatch(container.segments, current, matrixParams) &&
305
- primary !== undefined &&
306
- containsSegmentGroupPaths(primary, containee, next, matrixParams));
208
+ return containsTree(container, containee, options);
307
209
  }
308
- function matrixParamsMatch(container, containee, strategy) {
309
- return containee.every((segment, index) => paramsMatch(container[index]?.parameters ?? {}, segment.parameters, strategy));
310
- }
311
- function paramsMatch(container, containee, strategy) {
312
- if (strategy === 'ignored') {
313
- return true;
314
- }
315
- const containeeKeys = Object.keys(containee);
316
- if (strategy === 'exact' && Object.keys(container).length !== containeeKeys.length) {
317
- return false;
318
- }
319
- if (strategy === 'subset' && Object.keys(container).length < containeeKeys.length) {
320
- return false;
321
- }
322
- return containeeKeys.every((key) => equalParamValue(container[key], containee[key]));
323
- }
324
- function equalParamValue(left, right) {
325
- if (Array.isArray(left) && Array.isArray(right)) {
326
- if (left.length !== right.length) {
327
- return false;
328
- }
329
- const sortedLeft = [...left].sort();
330
- const sortedRight = [...right].sort();
331
- return sortedLeft.every((value, index) => value === sortedRight[index]);
332
- }
333
- return left === right;
334
- }
335
- function equalPaths(left, right) {
336
- return (left.length === right.length &&
337
- left.every((segment, index) => segment.path === right[index]?.path));
338
- }
339
-
340
- /** Referensi stabil untuk id yang belum punya data terdaftar (hindari array baru tiap evaluasi). */
341
210
  const EMPTY_NAV_DATA = Object.freeze([]);
342
- class NavigationService {
343
- documentRef = inject(DOCUMENT, { optional: true });
344
- persistence = new NavigationPersistence(this.documentRef);
345
- router = inject(Router, { optional: true });
346
- urlResolver = new NavigationActiveUrlResolver(this.router);
347
- routerUrl = signal(this.router?.url ?? '/', /* @ts-ignore */
348
- ...(ngDevMode ? [{ debugName: "routerUrl" }] : /* istanbul ignore next */ []));
349
- states = signal({}, /* @ts-ignore */
350
- ...(ngDevMode ? [{ debugName: "states" }] : /* istanbul ignore next */ []));
351
- openPanelKeys = signal({}, /* @ts-ignore */
352
- ...(ngDevMode ? [{ debugName: "openPanelKeys" }] : /* istanbul ignore next */ []));
353
- drawerOpenState = signal({}, /* @ts-ignore */
354
- ...(ngDevMode ? [{ debugName: "drawerOpenState" }] : /* istanbul ignore next */ []));
355
- /** Data mentah per id, dipublikasikan oleh `<Navigation>` agar surface lain (mis. apps-launcher di `Page`) bisa membaca nav by id tanpa mendaftarkan ulang id yang sama. */
356
- dataById = signal({}, /* @ts-ignore */
357
- ...(ngDevMode ? [{ debugName: "dataById" }] : /* istanbul ignore next */ []));
358
- /** Semua publisher hidup per data id. Publisher terakhir menjadi sumber aktif; cleanup owner lama tidak boleh menghapus publisher baru. */
359
- dataPublishers = new Map();
360
- /** Token stabil untuk pemanggil legacy yang tidak mengirim owner. */
361
- ownerlessDataPublisher = {};
362
- /** id navigasi → token owner instance, untuk menjaga setiap id hanya dipakai satu <Navigation> hidup. */
363
- idOwners = new Map();
364
- openPanelKey = computed(() => this.openPanelKeys()[DEFAULT_NAVIGATION_ID] ?? null, /* @ts-ignore */
365
- ...(ngDevMode ? [{ debugName: "openPanelKey" }] : /* istanbul ignore next */ []));
366
- /** Route aktif yang sudah dinormalisasi untuk consumer dockbar route-aware. */
367
- routeContext = computed(() => {
368
- const url = this.routerUrl();
369
- return this.readRouteContext(url);
370
- }, /* @ts-ignore */
371
- ...(ngDevMode ? [{ debugName: "routeContext" }] : /* istanbul ignore next */ []));
372
- exactMatchOptions = {
373
- paths: 'exact',
374
- queryParams: 'exact',
375
- fragment: 'exact',
376
- matrixParams: 'exact',
377
- };
378
- subsetMatchOptions = {
379
- paths: 'subset',
380
- queryParams: 'subset',
381
- fragment: 'ignored',
382
- matrixParams: 'ignored',
383
- };
384
- constructor() {
385
- this.router?.events.pipe(takeUntilDestroyed()).subscribe((event) => {
386
- if (event instanceof NavigationEnd) {
387
- const previousUrl = this.routerUrl();
388
- this.routerUrl.set(event.urlAfterRedirects);
389
- if (this.urlPath(previousUrl) !== this.urlPath(event.urlAfterRedirects)) {
390
- this.releasePanelsAfterNavigation();
391
- }
392
- }
393
- });
394
- }
395
- /**
396
- * Panel eksplisit (klik trigger rail/navbar) adalah state telusur sementara.
397
- * Perpindahan path harus mengembalikan panel ke resolusi URL: tanpa pelepasan
398
- * ini, dockbar sticky terkunci pada group lama sampai browser di-refresh,
399
- * karena `resolveDockbarGroup` memprioritaskan panel key di atas pencocokan
400
- * URL. Navigasi yang hanya mengubah query/fragment tidak melepas panel agar
401
- * penelusuran group lain tidak tersentak oleh update background (mis. sort
402
- * state yang ditulis ke query params).
403
- */
404
- releasePanelsAfterNavigation() {
405
- this.openPanelKeys.update((state) => Object.values(state).some((key) => key !== null) ? {} : state);
406
- }
407
- urlPath(url) {
408
- const end = url.search(/[?#]/);
409
- return end === -1 ? url : url.slice(0, end);
410
- }
411
- readRouteContext(url) {
412
- let snapshot = this.router?.routerState.snapshot.root ?? null;
413
- let icon = null;
414
- let badge = null;
415
- let label = null;
416
- while (snapshot !== null) {
417
- const data = snapshot.data;
418
- if (Object.prototype.hasOwnProperty.call(data, 'navigationIcon')) {
419
- icon = this.optionalString(data.navigationIcon);
420
- }
421
- if (Object.prototype.hasOwnProperty.call(data, 'navigationBadge')) {
422
- badge = this.optionalString(data.navigationBadge);
423
- }
424
- if (Object.prototype.hasOwnProperty.call(data, 'navigationLabel')) {
425
- label = this.optionalString(data.navigationLabel);
426
- }
427
- else if (snapshot.title) {
428
- label = snapshot.title;
429
- }
430
- snapshot =
431
- snapshot.children.find((child) => child.outlet === PRIMARY_OUTLET) ??
432
- snapshot.firstChild ??
433
- null;
434
- }
435
- return { url, icon, badge, label };
436
- }
437
- optionalString(value) {
438
- return typeof value === 'string' && value.trim() ? value.trim() : null;
439
- }
440
- register(input, owner) {
441
- const state = this.persistence.resolveState(input);
442
- this.claimId(state.id, owner);
443
- this.states.update((states) => ({ ...states, [state.id]: state }));
444
- this.persistence.persistState(state);
445
- return state;
446
- }
447
- unregister(id, owner) {
448
- const navId = this.persistence.normalizeId(id);
449
- this.releaseId(navId, owner);
450
- this.states.update((states) => this.withoutKey(states, navId));
451
- this.openPanelKeys.update((state) => this.withoutKey(state, navId));
452
- this.drawerOpenState.update((state) => this.withoutKey(state, navId));
453
- }
454
- /**
455
- * Validasi keunikan id navigasi: setiap instance `<Navigation>` wajib memakai id unik.
456
- * `owner` adalah token unik per instance — klaim ulang oleh owner yang sama (mis. perubahan
457
- * input) diizinkan, tetapi dua instance hidup dengan id sama dianggap salah konfigurasi dan
458
- * melempar error di mode dev. Pemanggil tanpa owner (akses langsung service) dilewati.
459
- */
460
- claimId(id, owner) {
461
- if (owner === undefined) {
462
- return;
463
- }
464
- const currentOwner = this.idOwners.get(id);
465
- if (currentOwner !== undefined && currentOwner !== owner && isDevMode()) {
466
- throw new Error(`[Navigation] Duplikasi id navigasi "${id}". Setiap <Navigation> wajib memakai id unik. ` +
467
- `Id "main" dikhususkan untuk navigasi utama pada layout/shell (block-shell).`);
468
- }
469
- this.idOwners.set(id, owner);
470
- }
471
- releaseId(id, owner) {
472
- if (owner === undefined || this.idOwners.get(id) === owner) {
473
- this.idOwners.delete(id);
474
- }
475
- }
476
- state(id) {
477
- const navId = this.persistence.normalizeId(id);
478
- return computed(() => this.states()[navId] ?? null);
479
- }
480
- currentState(id) {
481
- return this.states()[this.persistence.normalizeId(id)] ?? null;
482
- }
483
- /** Data terdaftar untuk sebuah id sebagai signal; `[]` bila belum ada `<Navigation>` dengan id tersebut. */
484
- data(id) {
485
- const navId = this.persistence.normalizeId(id);
486
- return computed(() => this.dataById()[navId] ?? EMPTY_NAV_DATA);
487
- }
488
- /** Dipanggil `<Navigation>` untuk mempublikasikan datanya ke registry by id. */
489
- publishData(id, data, owner) {
490
- const navId = this.persistence.normalizeId(id);
491
- const publisher = owner ?? this.ownerlessDataPublisher;
492
- const publishers = this.dataPublishers.get(navId) ?? new Map();
493
- // Map mempertahankan insertion order. Re-publish oleh owner yang sama harus menjadi
494
- // publisher terbaru agar data input yang berubah langsung menjadi sumber aktif.
495
- publishers.delete(publisher);
496
- publishers.set(publisher, data);
497
- this.dataPublishers.set(navId, publishers);
498
- this.dataById.update((map) => ({ ...map, [navId]: data }));
499
- }
500
- /** Dipanggil `<Navigation>` saat destroy untuk melepas datanya dari registry. */
501
- clearData(id, owner) {
502
- const navId = this.persistence.normalizeId(id);
503
- const publisher = owner ?? this.ownerlessDataPublisher;
504
- const publishers = this.dataPublishers.get(navId);
505
- if (!publishers?.delete(publisher)) {
506
- return;
507
- }
508
- const remaining = Array.from(publishers.values());
509
- const fallback = remaining.at(-1);
510
- if (fallback) {
511
- this.dataById.update((map) => ({ ...map, [navId]: fallback }));
512
- return;
513
- }
514
- this.dataPublishers.delete(navId);
515
- this.dataById.update((map) => this.withoutKey(map, navId));
516
- }
517
- currentPanelKey(id) {
518
- return this.openPanelKeys()[this.persistence.normalizeId(id)] ?? null;
519
- }
520
- update(id, patch) {
521
- const navId = this.persistence.normalizeId(id);
522
- const current = this.states()[navId] ??
523
- this.persistence.resolveState({ id: navId, orientation: patch.orientation ?? 'vertical' });
524
- return this.register({
525
- id: navId,
526
- orientation: patch.orientation ?? current.orientation,
527
- type: patch.type ?? current.type,
528
- position: patch.position ?? current.position,
529
- collapsed: patch.collapsed ?? current.collapsed,
530
- dockbarMode: patch.dockbarMode ?? current.dockbarMode,
531
- });
532
- }
533
- setType(id, type) {
534
- return this.update(id, { type });
535
- }
536
- setPosition(id, position) {
537
- return this.update(id, { position });
538
- }
539
- setCollapsed(id, collapsed) {
540
- return this.update(id, { collapsed });
541
- }
542
- toggleCollapsed(id) {
543
- const navId = this.persistence.normalizeId(id);
544
- const current = this.states()[navId] ?? this.persistence.resolveState({ id: navId, orientation: 'vertical' });
545
- return this.setCollapsed(navId, !current.collapsed);
546
- }
547
- setDockbarMode(id, mode) {
548
- return this.update(id, { dockbarMode: mode });
549
- }
550
- isRouterItem(item) {
551
- return !!item.link && !item.externalLink;
552
- }
553
- hrefFor(item) {
554
- if (item.href) {
555
- return item.href;
556
- }
557
- if (item.externalLink && typeof item.link === 'string') {
558
- return item.link;
559
- }
560
- return null;
561
- }
562
- /**
563
- * A consumer `rel` is unioned with the safe default rather than replacing it:
564
- * returning `rel="external"` verbatim on a `_blank` link dropped `noopener`
565
- * and handed the opened page a live `window.opener`.
566
- */
567
- relFor(item) {
568
- const consumerTokens = item.rel?.split(/\s+/).filter(Boolean) ?? [];
569
- if (item.target !== '_blank' && !item.externalLink) {
570
- return consumerTokens.length > 0 ? consumerTokens.join(' ') : null;
571
- }
572
- const tokens = new Set(consumerTokens);
573
- tokens.add('noopener');
574
- tokens.add('noreferrer');
575
- return [...tokens].join(' ');
576
- }
577
- routerLinkActiveOptions(item) {
578
- return (item.isActiveMatchOptions ??
579
- (item.exactMatch ? this.exactMatchOptions : this.subsetMatchOptions));
580
- }
581
- itemRole(orientation, level) {
582
- void level;
583
- // Horizontal navs are menubars/menus (arrow-key roving) → menuitem. Vertical
584
- // navs are plain lists of links (tab navigation, no menu keyboard model), so
585
- // their items must NOT be menuitems — a menuitem inside a `list` is an invalid
586
- // ARIA parent (axe `aria-required-parent`).
587
- return orientation === 'horizontal' ? 'menuitem' : null;
588
- }
589
- compactLabel(item, compact) {
590
- return compact ? (item.tooltip ?? item.title ?? null) : null;
591
- }
592
- titleFor(item, compact) {
593
- return item.tooltip ?? (compact ? (item.title ?? null) : null);
594
- }
595
- compactFallback(item) {
596
- return (item.title ?? item.id ?? '?').trim().slice(0, 2);
597
- }
598
- iconContext(item, active, level, orientation) {
599
- return {
600
- $implicit: item.icon ?? '',
601
- icon: item.icon ?? '',
602
- item: item.source,
603
- active,
604
- orientation,
605
- level,
606
- };
607
- }
608
- isItemActive(item, activeIds, explicitActiveUrl) {
609
- return this.matchesActiveTreeDeep(item, activeIds, this.activeMatch(explicitActiveUrl, null));
610
- }
611
- /**
612
- * Pencocokan route murni untuk state dockbar berbasis Router. Berbeda dari
613
- * `isItemActive`, konfigurasi legacy `item.active` dan `activeIds` sengaja
614
- * tidak ikut menentukan group route aktif.
615
- */
616
- isItemRouteActive(item, explicitActiveUrl, relativeTo = null) {
617
- return this.matchesActiveTreeDeep(item, null, this.activeMatch(explicitActiveUrl, relativeTo));
618
- }
619
- matchesActiveTreeDeep(item, activeIds, match) {
620
- if (activeIds !== null &&
621
- (item.active || activeIds.has(item.stateId) || activeIds.has(item.key))) {
622
- return true;
623
- }
624
- if (this.matchesActiveTree(item, match)) {
625
- return true;
626
- }
627
- return item.children.some((child) => this.matchesActiveTreeDeep(child, activeIds, match));
628
- }
629
- /**
630
- * The active URL is parsed once per top-level call and handed down the
631
- * recursion; re-parsing it at every node turned one navigation into hundreds
632
- * of identical `parseUrl` calls.
633
- */
634
- activeMatch(explicitActiveUrl, relativeTo) {
635
- // Always read the signal so computed callers invalidate on NavigationEnd,
636
- // even when Router.url is the fresher synchronous value.
637
- const cachedUrl = this.routerUrl();
638
- const activeUrl = explicitActiveUrl ?? this.router?.url ?? cachedUrl;
639
- return this.urlResolver.match(activeUrl, this.router?.url ?? cachedUrl, relativeTo);
640
- }
641
- isPanelOpen(navIdOrItem, item) {
642
- const { navId, navItem } = this.resolvePanelArgs('isPanelOpen', navIdOrItem, item);
643
- return this.openPanelKeys()[navId] === navItem.key;
644
- }
645
- openPanel(navIdOrItem, item) {
646
- const { navId, navItem } = this.resolvePanelArgs('openPanel', navIdOrItem, item);
647
- if (navItem.disabled) {
648
- return;
649
- }
650
- this.openPanelKeys.update((state) => ({ ...state, [navId]: navItem.key }));
651
- }
652
- togglePanel(navIdOrItem, item) {
653
- const { navId, navItem } = this.resolvePanelArgs('togglePanel', navIdOrItem, item);
654
- if (navItem.disabled) {
655
- return;
656
- }
657
- this.openPanelKeys.update((state) => ({
658
- ...state,
659
- [navId]: state[navId] === navItem.key ? null : navItem.key,
660
- }));
661
- }
662
- closePanel(id = DEFAULT_NAVIGATION_ID) {
663
- const navId = this.persistence.normalizeId(id);
664
- this.openPanelKeys.update((state) => ({ ...state, [navId]: null }));
665
- }
666
- dockbarGroups(items) {
667
- return items.filter((item) => item.children.length > 0);
668
- }
669
- resolveDockbarGroup(id, items, mode, activeIds, activeUrl) {
670
- const groups = this.dockbarGroups(items);
671
- const panelKey = this.openPanelKeys()[this.persistence.normalizeId(id)] ?? null;
672
- if (panelKey !== null) {
673
- const explicit = groups.find((group) => group.key === panelKey);
674
- if (explicit) {
675
- return explicit;
676
- }
677
- }
678
- if (mode !== 'sticky') {
679
- return null;
680
- }
681
- return groups.find((group) => this.isItemActive(group, activeIds, activeUrl)) ?? null;
682
- }
683
- isDrawerOpen(id) {
684
- return this.drawerOpenState()[this.persistence.normalizeId(id)] ?? false;
685
- }
686
- openDrawer(id) {
687
- const navId = this.persistence.normalizeId(id);
688
- this.drawerOpenState.update((state) => ({ ...state, [navId]: true }));
689
- }
690
- toggleDrawer(id) {
691
- const navId = this.persistence.normalizeId(id);
692
- this.drawerOpenState.update((state) => ({ ...state, [navId]: !(state[navId] ?? false) }));
693
- }
694
- closeDrawer(id) {
695
- const navId = this.persistence.normalizeId(id);
696
- this.drawerOpenState.update((state) => ({ ...state, [navId]: false }));
697
- }
698
- matchesActiveTree(item, match) {
699
- return this.urlResolver.matches(item, match, this.routerLinkActiveOptions(item));
700
- }
701
- withoutKey(record, key) {
702
- const next = { ...record };
703
- delete next[key];
704
- return next;
705
- }
706
- resolvePanelArgs(method, navIdOrItem, item) {
707
- if (typeof navIdOrItem === 'string') {
708
- if (item === undefined) {
709
- throw new Error(`[Navigation] ${method}(navId, item) membutuhkan item navigasi sebagai argumen kedua.`);
710
- }
711
- return {
712
- navId: this.persistence.normalizeId(navIdOrItem),
713
- navItem: item,
714
- };
715
- }
716
- return { navId: DEFAULT_NAVIGATION_ID, navItem: navIdOrItem };
717
- }
718
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: NavigationService, deps: [], target: i0.ɵɵFactoryTarget.Service });
719
- static ɵprov = i0.ɵɵngDeclareService({ minVersion: "22.0.0", version: "22.1.6", ngImport: i0, type: NavigationService });
720
- }
721
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: NavigationService, decorators: [{
722
- type: Service
723
- }], ctorParameters: () => [] });
724
-
725
- /**
726
- * Generated bundle index. Do not edit.
727
- */
728
-
729
- export { NavigationService };
211
+ var NavigationService = class NavigationService {
212
+ documentRef = inject(DOCUMENT, { optional: true });
213
+ persistence = new NavigationPersistence(this.documentRef);
214
+ router = inject(Router, { optional: true });
215
+ urlResolver = new NavigationActiveUrlResolver(this.router);
216
+ routerUrl = signal(this.router?.url ?? "/", ...ngDevMode ? [{ debugName: "routerUrl" }] : /* istanbul ignore next */ []);
217
+ states = signal({}, ...ngDevMode ? [{ debugName: "states" }] : /* istanbul ignore next */ []);
218
+ openPanelKeys = signal({}, ...ngDevMode ? [{ debugName: "openPanelKeys" }] : /* istanbul ignore next */ []);
219
+ drawerOpenState = signal({}, ...ngDevMode ? [{ debugName: "drawerOpenState" }] : /* istanbul ignore next */ []);
220
+ dataById = signal({}, ...ngDevMode ? [{ debugName: "dataById" }] : /* istanbul ignore next */ []);
221
+ dataPublishers = /* @__PURE__ */ new Map();
222
+ ownerlessDataPublisher = {};
223
+ idOwners = /* @__PURE__ */ new Map();
224
+ openPanelKey = computed(() => this.openPanelKeys()["default"] ?? null, ...ngDevMode ? [{ debugName: "openPanelKey" }] : /* istanbul ignore next */ []);
225
+ routeContext = computed(() => {
226
+ const url = this.routerUrl();
227
+ return this.readRouteContext(url);
228
+ }, ...ngDevMode ? [{ debugName: "routeContext" }] : /* istanbul ignore next */ []);
229
+ exactMatchOptions = {
230
+ paths: "exact",
231
+ queryParams: "exact",
232
+ fragment: "exact",
233
+ matrixParams: "exact"
234
+ };
235
+ subsetMatchOptions = {
236
+ paths: "subset",
237
+ queryParams: "subset",
238
+ fragment: "ignored",
239
+ matrixParams: "ignored"
240
+ };
241
+ constructor() {
242
+ this.router?.events.pipe(takeUntilDestroyed()).subscribe((event) => {
243
+ if (event instanceof NavigationEnd) {
244
+ const previousUrl = this.routerUrl();
245
+ this.routerUrl.set(event.urlAfterRedirects);
246
+ if (this.urlPath(previousUrl) !== this.urlPath(event.urlAfterRedirects)) this.releasePanelsAfterNavigation();
247
+ }
248
+ });
249
+ }
250
+ releasePanelsAfterNavigation() {
251
+ this.openPanelKeys.update((state) => Object.values(state).some((key) => key !== null) ? {} : state);
252
+ }
253
+ urlPath(url) {
254
+ const end = url.search(/[?#]/);
255
+ return end === -1 ? url : url.slice(0, end);
256
+ }
257
+ readRouteContext(url) {
258
+ let snapshot = this.router?.routerState.snapshot.root ?? null;
259
+ let icon = null;
260
+ let badge = null;
261
+ let label = null;
262
+ while (snapshot !== null) {
263
+ const data = snapshot.data;
264
+ if (Object.prototype.hasOwnProperty.call(data, "navigationIcon")) icon = this.optionalString(data.navigationIcon);
265
+ if (Object.prototype.hasOwnProperty.call(data, "navigationBadge")) badge = this.optionalString(data.navigationBadge);
266
+ if (Object.prototype.hasOwnProperty.call(data, "navigationLabel")) label = this.optionalString(data.navigationLabel);
267
+ else if (snapshot.title) label = snapshot.title;
268
+ snapshot = snapshot.children.find((child) => child.outlet === PRIMARY_OUTLET) ?? snapshot.firstChild ?? null;
269
+ }
270
+ return {
271
+ url,
272
+ icon,
273
+ badge,
274
+ label
275
+ };
276
+ }
277
+ optionalString(value) {
278
+ return typeof value === "string" && value.trim() ? value.trim() : null;
279
+ }
280
+ register(input, owner) {
281
+ const state = this.persistence.resolveState(input);
282
+ this.claimId(state.id, owner);
283
+ this.states.update((states) => ({
284
+ ...states,
285
+ [state.id]: state
286
+ }));
287
+ this.persistence.persistState(state);
288
+ return state;
289
+ }
290
+ unregister(id, owner) {
291
+ const navId = this.persistence.normalizeId(id);
292
+ this.releaseId(navId, owner);
293
+ this.states.update((states) => this.withoutKey(states, navId));
294
+ this.openPanelKeys.update((state) => this.withoutKey(state, navId));
295
+ this.drawerOpenState.update((state) => this.withoutKey(state, navId));
296
+ }
297
+ claimId(id, owner) {
298
+ if (owner === void 0) return;
299
+ const currentOwner = this.idOwners.get(id);
300
+ if (currentOwner !== void 0 && currentOwner !== owner && isDevMode()) throw new Error(`[Navigation] Duplikasi id navigasi "${id}". Setiap <Navigation> wajib memakai id unik. Id "main" dikhususkan untuk navigasi utama pada layout/shell (block-shell).`);
301
+ this.idOwners.set(id, owner);
302
+ }
303
+ releaseId(id, owner) {
304
+ if (owner === void 0 || this.idOwners.get(id) === owner) this.idOwners.delete(id);
305
+ }
306
+ state(id) {
307
+ const navId = this.persistence.normalizeId(id);
308
+ return computed(() => this.states()[navId] ?? null);
309
+ }
310
+ currentState(id) {
311
+ return this.states()[this.persistence.normalizeId(id)] ?? null;
312
+ }
313
+ data(id) {
314
+ const navId = this.persistence.normalizeId(id);
315
+ return computed(() => this.dataById()[navId] ?? EMPTY_NAV_DATA);
316
+ }
317
+ publishData(id, data, owner) {
318
+ const navId = this.persistence.normalizeId(id);
319
+ const publisher = owner ?? this.ownerlessDataPublisher;
320
+ const publishers = this.dataPublishers.get(navId) ?? /* @__PURE__ */ new Map();
321
+ publishers.delete(publisher);
322
+ publishers.set(publisher, data);
323
+ this.dataPublishers.set(navId, publishers);
324
+ this.dataById.update((map) => ({
325
+ ...map,
326
+ [navId]: data
327
+ }));
328
+ }
329
+ clearData(id, owner) {
330
+ const navId = this.persistence.normalizeId(id);
331
+ const publisher = owner ?? this.ownerlessDataPublisher;
332
+ const publishers = this.dataPublishers.get(navId);
333
+ if (!publishers?.delete(publisher)) return;
334
+ const fallback = Array.from(publishers.values()).at(-1);
335
+ if (fallback) {
336
+ this.dataById.update((map) => ({
337
+ ...map,
338
+ [navId]: fallback
339
+ }));
340
+ return;
341
+ }
342
+ this.dataPublishers.delete(navId);
343
+ this.dataById.update((map) => this.withoutKey(map, navId));
344
+ }
345
+ currentPanelKey(id) {
346
+ return this.openPanelKeys()[this.persistence.normalizeId(id)] ?? null;
347
+ }
348
+ update(id, patch) {
349
+ const navId = this.persistence.normalizeId(id);
350
+ const current = this.states()[navId] ?? this.persistence.resolveState({
351
+ id: navId,
352
+ orientation: patch.orientation ?? "vertical"
353
+ });
354
+ return this.register({
355
+ id: navId,
356
+ orientation: patch.orientation ?? current.orientation,
357
+ type: patch.type ?? current.type,
358
+ position: patch.position ?? current.position,
359
+ collapsed: patch.collapsed ?? current.collapsed,
360
+ dockbarMode: patch.dockbarMode ?? current.dockbarMode
361
+ });
362
+ }
363
+ setType(id, type) {
364
+ return this.update(id, { type });
365
+ }
366
+ setPosition(id, position) {
367
+ return this.update(id, { position });
368
+ }
369
+ setCollapsed(id, collapsed) {
370
+ return this.update(id, { collapsed });
371
+ }
372
+ toggleCollapsed(id) {
373
+ const navId = this.persistence.normalizeId(id);
374
+ const current = this.states()[navId] ?? this.persistence.resolveState({
375
+ id: navId,
376
+ orientation: "vertical"
377
+ });
378
+ if (current.type === "minidock") return current;
379
+ return this.setCollapsed(navId, !current.collapsed);
380
+ }
381
+ setDockbarMode(id, mode) {
382
+ return this.update(id, { dockbarMode: mode });
383
+ }
384
+ isRouterItem(item) {
385
+ return !!item.link && !item.externalLink;
386
+ }
387
+ hrefFor(item) {
388
+ if (item.href) return item.href;
389
+ if (item.externalLink && typeof item.link === "string") return item.link;
390
+ return null;
391
+ }
392
+ relFor(item) {
393
+ const consumerTokens = item.rel?.split(/\s+/).filter(Boolean) ?? [];
394
+ if (item.target !== "_blank" && !item.externalLink) return consumerTokens.length > 0 ? consumerTokens.join(" ") : null;
395
+ const tokens = new Set(consumerTokens);
396
+ tokens.add("noopener");
397
+ tokens.add("noreferrer");
398
+ return [...tokens].join(" ");
399
+ }
400
+ routerLinkActiveOptions(item) {
401
+ return item.isActiveMatchOptions ?? (item.exactMatch ? this.exactMatchOptions : this.subsetMatchOptions);
402
+ }
403
+ itemRole(orientation, level) {
404
+ return orientation === "horizontal" ? "menuitem" : null;
405
+ }
406
+ compactLabel(item, compact) {
407
+ return compact ? item.tooltip ?? item.title ?? null : null;
408
+ }
409
+ titleFor(item, compact) {
410
+ return item.tooltip ?? (compact ? item.title ?? null : null);
411
+ }
412
+ compactFallback(item) {
413
+ return (item.title ?? item.id ?? "?").trim().slice(0, 2);
414
+ }
415
+ iconContext(item, active, level, orientation) {
416
+ return {
417
+ $implicit: item.icon ?? "",
418
+ icon: item.icon ?? "",
419
+ item: item.source,
420
+ active,
421
+ orientation,
422
+ level
423
+ };
424
+ }
425
+ isItemActive(item, activeIds, explicitActiveUrl) {
426
+ return this.matchesActiveTreeDeep(item, activeIds, this.activeMatch(explicitActiveUrl, null));
427
+ }
428
+ isItemRouteActive(item, explicitActiveUrl, relativeTo = null) {
429
+ return this.matchesActiveTreeDeep(item, null, this.activeMatch(explicitActiveUrl, relativeTo));
430
+ }
431
+ matchesActiveTreeDeep(item, activeIds, match) {
432
+ if (activeIds !== null && (item.active || activeIds.has(item.stateId) || activeIds.has(item.key))) return true;
433
+ if (this.matchesActiveTree(item, match)) return true;
434
+ return item.children.some((child) => this.matchesActiveTreeDeep(child, activeIds, match));
435
+ }
436
+ activeMatch(explicitActiveUrl, relativeTo) {
437
+ const cachedUrl = this.routerUrl();
438
+ const activeUrl = explicitActiveUrl ?? this.router?.url ?? cachedUrl;
439
+ return this.urlResolver.match(activeUrl, this.router?.url ?? cachedUrl, relativeTo);
440
+ }
441
+ isPanelOpen(navIdOrItem, item) {
442
+ const { navId, navItem } = this.resolvePanelArgs("isPanelOpen", navIdOrItem, item);
443
+ return this.openPanelKeys()[navId] === navItem.key;
444
+ }
445
+ openPanel(navIdOrItem, item) {
446
+ const { navId, navItem } = this.resolvePanelArgs("openPanel", navIdOrItem, item);
447
+ if (navItem.disabled) return;
448
+ this.openPanelKeys.update((state) => ({
449
+ ...state,
450
+ [navId]: navItem.key
451
+ }));
452
+ }
453
+ togglePanel(navIdOrItem, item) {
454
+ const { navId, navItem } = this.resolvePanelArgs("togglePanel", navIdOrItem, item);
455
+ if (navItem.disabled) return;
456
+ this.openPanelKeys.update((state) => ({
457
+ ...state,
458
+ [navId]: state[navId] === navItem.key ? null : navItem.key
459
+ }));
460
+ }
461
+ closePanel(id = DEFAULT_NAVIGATION_ID) {
462
+ const navId = this.persistence.normalizeId(id);
463
+ this.openPanelKeys.update((state) => ({
464
+ ...state,
465
+ [navId]: null
466
+ }));
467
+ }
468
+ dockbarGroups(items) {
469
+ return items.filter((item) => item.children.length > 0);
470
+ }
471
+ resolveDockbarGroup(id, items, mode, activeIds, activeUrl) {
472
+ const groups = this.dockbarGroups(items);
473
+ const panelKey = this.openPanelKeys()[this.persistence.normalizeId(id)] ?? null;
474
+ if (panelKey !== null) {
475
+ const explicit = groups.find((group) => group.key === panelKey);
476
+ if (explicit) return explicit;
477
+ }
478
+ if (mode !== "sticky") return null;
479
+ return groups.find((group) => this.isItemActive(group, activeIds, activeUrl)) ?? null;
480
+ }
481
+ isDrawerOpen(id) {
482
+ return this.drawerOpenState()[this.persistence.normalizeId(id)] ?? false;
483
+ }
484
+ openDrawer(id) {
485
+ const navId = this.persistence.normalizeId(id);
486
+ this.drawerOpenState.update((state) => ({
487
+ ...state,
488
+ [navId]: true
489
+ }));
490
+ }
491
+ toggleDrawer(id) {
492
+ const navId = this.persistence.normalizeId(id);
493
+ this.drawerOpenState.update((state) => ({
494
+ ...state,
495
+ [navId]: !(state[navId] ?? false)
496
+ }));
497
+ }
498
+ closeDrawer(id) {
499
+ const navId = this.persistence.normalizeId(id);
500
+ this.drawerOpenState.update((state) => ({
501
+ ...state,
502
+ [navId]: false
503
+ }));
504
+ }
505
+ matchesActiveTree(item, match) {
506
+ return this.urlResolver.matches(item, match, this.routerLinkActiveOptions(item));
507
+ }
508
+ withoutKey(record, key) {
509
+ const next = { ...record };
510
+ delete next[key];
511
+ return next;
512
+ }
513
+ resolvePanelArgs(method, navIdOrItem, item) {
514
+ if (typeof navIdOrItem === "string") {
515
+ if (item === void 0) throw new Error(`[Navigation] ${method}(navId, item) membutuhkan item navigasi sebagai argumen kedua.`);
516
+ return {
517
+ navId: this.persistence.normalizeId(navIdOrItem),
518
+ navItem: item
519
+ };
520
+ }
521
+ return {
522
+ navId: DEFAULT_NAVIGATION_ID,
523
+ navItem: navIdOrItem
524
+ };
525
+ }
526
+ static ɵfac = i0.ɵɵngDeclareFactory({
527
+ minVersion: "12.0.0",
528
+ version: "22.2.2",
529
+ ngImport: i0,
530
+ type: NavigationService,
531
+ deps: [],
532
+ target: i0.ɵɵFactoryTarget.Service
533
+ });
534
+ static ɵprov = i0.ɵɵngDeclareService({
535
+ minVersion: "22.0.0",
536
+ version: "22.2.2",
537
+ ngImport: i0,
538
+ type: NavigationService
539
+ });
540
+ };
541
+ i0.ɵɵngDeclareClassMetadata({
542
+ minVersion: "12.0.0",
543
+ version: "22.2.2",
544
+ ngImport: i0,
545
+ type: NavigationService,
546
+ decorators: [{ type: Service }],
547
+ ctorParameters: () => []
548
+ });
549
+ export { NavigationService };