@ojiepermana/angular-navigation 22.0.32 → 22.0.33

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.
package/README.md CHANGED
@@ -48,8 +48,7 @@ Type dipilih lewat komponen anak deklaratif — `NavigationSidebar`, `Navigation
48
48
 
49
49
  ## API Notes
50
50
 
51
- - `data` is the preferred source of navigation data.
52
- - `items` is still accepted as a compatibility alias while consumers migrate.
51
+ - `data` is the source of navigation data.
53
52
  - Type is declared by the child component: `NavigationSidebar`/`NavigationDockbar` (vertical), `NavigationNavbar`/`NavigationFlyout` (horizontal). Orientation is implied by the type child.
54
53
  - `id` identifies a navigation instance so multiple navs can keep distinct service state.
55
54
  - `position` on `NavigationSidebar`/`NavigationDockbar` accepts `left` or `right` (vertical).
@@ -59,7 +58,7 @@ Type dipilih lewat komponen anak deklaratif — `NavigationSidebar`, `Navigation
59
58
  - `label` on `NavigationFlyout` sets the single trigger label and defaults to `Menu`.
60
59
  - `icon` on `NavigationFlyout` renders a Material Symbols icon on the trigger; `icon-position` (`start`/`end`) sets its placement and `icon-only` hides the label visually while keeping it as the accessible name (compact mode is always icon-only and falls back to the `menu` icon).
61
60
  - `nav-position` on `NavigationNavbar`/`NavigationFlyout` accepts `top` (default) or `bottom`. With `bottom`, the navbar grid panel opens upward with squared bottom corners, and the flyout panel anchors to the container's bottom edge with the tab row docked at the bottom — seamless for bars placed below the content.
62
- - `nav-type-style` on `NavigationNavbar`/`NavigationFlyout` accepts `default` or `border-rail`. `border-rail` squares the panel (no rounding), frames entry icons with dimmed blueprint-style rail lines plus dashed center cross lines (instead of rounded boxes), renders the nested-collapse rail dashed, and replaces hover/active backgrounds with primary-colored text. `default` keeps the current visuals.
61
+ - `nav-appearance` on `NavigationNavbar`/`NavigationFlyout` accepts `flat` or `border-rail` (same vocabulary as the layout's `layout-appearance`). `border-rail` squares the panel (no rounding), frames entry icons with dimmed blueprint-style rail lines plus dashed center cross lines (instead of rounded boxes), renders the nested-collapse rail dashed, and replaces hover/active backgrounds with primary-colored text. `flat` keeps the current visuals.
63
62
  - The `navbar` type renders root items inline immediately; clicking a group (hover does not open it) opens a full-width grid panel below the bar with the same flyout-style entries, responsive columns, and nested collapse.
64
63
  - The `flyout` type renders one trigger button that opens a floating panel overlaying the parent container exactly (same top position and width, covering the trigger with no visible gap; `display: contents` wrappers are skipped when measuring the container). Root items with children become the horizontal navigation inside the panel (their `icon` renders in the row), their children render as title/subtitle entries in a responsive grid (1 column on mobile, 2 from `sm`, 3 from `md`, 4 from `lg` and up; `columns` caps the maximum at 1–4), and deeper children render as a vertical collapse below their entry — expanded by default every time the panel opens, collapsible per entry via the chevron, with the child icons aligned on the same vertical line as the parent entry icon. The panel closes on `Escape`, outside clicks, the close button, or leaf selection.
65
64
  - Items with children render a `chevron_right` icon pinned at the right edge and vertically centered: it points right by default and rotates down (in place, no layout shift) only while open — hover does not move it. This applies to flyout tabs and entries, navbar branch triggers, and collapsible items.
@@ -87,8 +86,7 @@ Inputs pada `<Navigation>` (container):
87
86
  | API | Type | Notes |
88
87
  | ----------------- | -------------------------------------------------- | ------------------------------------------------------------------------------- |
89
88
  | `id` | `string` | Navigation instance id. `main` is the only id persisted to `localStorage`. |
90
- | `data` | `readonly NavigationItem[]` | Preferred source of items. |
91
- | `items` | `readonly NavigationItem[]` | Compatibility alias for `data`. |
89
+ | `data` | `readonly NavigationItem[]` | Source of navigation items. |
92
90
  | `ariaLabel` | `string` | Accessible label on the host navigation landmark. |
93
91
  | `compact` | `boolean` | Compatibility alias for collapsed-rail item layout. |
94
92
  | `collapse-tree` | `stairs \| straight` | Controls nested connector styling for collapsible items. |
@@ -110,9 +108,9 @@ Inputs pada komponen type:
110
108
  | `NavigationSidebar` | `previewExpanded` | `boolean` | Forces a collapsed sidebar to render expanded for preview. |
111
109
  | `NavigationDockbar` | `mode` | `sticky \| drawer \| null` | Docked aside beside the rail, or overlay drawer. |
112
110
  | `NavigationDockbar` | `position` | `left \| right \| null` | Side the rail docks to. |
113
- | `NavigationNavbar` | `nav-type-style` | `default \| border-rail` | Style variant. `border-rail` = squared panel, dashed icon rails, no hover bg. |
111
+ | `NavigationNavbar` | `nav-appearance` | `flat \| border-rail` | Style variant. `border-rail` = squared panel, dashed icon rails, no hover bg. |
114
112
  | `NavigationFlyout` | `label` | `string` | Trigger label. Defaults to `Menu`. |
115
- | `NavigationFlyout` | `nav-type-style` | `default \| border-rail` | Style variant. `border-rail` = squared panel, dashed icon rails, no hover bg. |
113
+ | `NavigationFlyout` | `nav-appearance` | `flat \| border-rail` | Style variant. `border-rail` = squared panel, dashed icon rails, no hover bg. |
116
114
 
117
115
  Semua type juga menerima `class` untuk kelas tambahan pada elemen shell-nya.
118
116
 
@@ -201,7 +199,7 @@ Any other navigation id, such as `erp-navbar`, only keeps its state in memory fo
201
199
  Saat `item.icon` tersedia, `nav` akan merender Material Symbols secara default melalui `@ojiepermana/angular-component/icon`. Jalankan `provideUiTheme()` untuk preload global, atau biarkan `IconComponent` melakukan lazy-load saat icon pertama dipakai.
202
200
 
203
201
  ```html
204
- <Navigation [items]="items">
202
+ <Navigation [data]="items">
205
203
  <NavigationSidebar />
206
204
  </Navigation>
207
205
  ```
@@ -209,7 +207,7 @@ Saat `item.icon` tersedia, `nav` akan merender Material Symbols secara default m
209
207
  Gunakan template `NavigationIcon` hanya bila consumer ingin override renderer bawaan.
210
208
 
211
209
  ```html
212
- <Navigation [items]="items">
210
+ <Navigation [data]="items">
213
211
  <NavigationSidebar />
214
212
 
215
213
  <ng-template NavigationIcon let-icon let-item="item" let-active="active" let-level="level">
@@ -15,14 +15,6 @@ const DEFAULT_DOCKBAR_MODE = 'sticky';
15
15
  const INSTANCE_STORAGE_PROPERTIES = ['orientation', 'appearance', 'position', 'collapsed', 'dockbar-mode'];
16
16
  const PERSISTED_STORAGE_PROPERTIES = ['orientation', 'type', 'position'];
17
17
  const TYPE_MODE_STORAGE_KEY = 'nav-type-mode';
18
- /** Nama properti legacy untuk tiap properti persisted saat membaca key `nav:<id>:*` generasi lama. */
19
- const LEGACY_PROPERTY_NAMES = {
20
- orientation: 'orientation',
21
- type: 'appearance',
22
- position: 'position',
23
- };
24
- const LEGACY_NAV_STORAGE_KEYS = ['nav-appearance', 'nav-vertical-appearance', 'nav-horizontal-appearance'];
25
- const LEGACY_TYPE_MODE_STORAGE_KEYS = ['nav-appearance-mode', 'nav-collapsed', 'nav-dockbar-mode'];
26
18
  class NavigationService {
27
19
  documentRef = inject(DOCUMENT, { optional: true });
28
20
  router = inject(Router, { optional: true });
@@ -51,7 +43,6 @@ class NavigationService {
51
43
  matrixParams: 'ignored',
52
44
  };
53
45
  constructor() {
54
- this.cleanupLegacyStorage();
55
46
  this.router?.events.pipe(takeUntilDestroyed()).subscribe((event) => {
56
47
  if (event instanceof NavigationEnd) {
57
48
  this.routerUrl.set(event.urlAfterRedirects);
@@ -321,26 +312,6 @@ class NavigationService {
321
312
  defaultType(orientation) {
322
313
  return orientation === 'vertical' ? DEFAULT_VERTICAL_TYPE : DEFAULT_HORIZONTAL_TYPE;
323
314
  }
324
- cleanupLegacyStorage() {
325
- this.migrateLegacyPersistedStorage();
326
- for (const key of LEGACY_NAV_STORAGE_KEYS) {
327
- this.removeStorage(key);
328
- }
329
- for (const key of LEGACY_TYPE_MODE_STORAGE_KEYS) {
330
- this.removeStorage(key);
331
- }
332
- const storage = this.storage();
333
- const keysToRemove = [];
334
- for (let index = 0; index < (storage?.length ?? 0); index += 1) {
335
- const key = storage?.key(index);
336
- if (key && this.isLegacyInstanceStorageKey(key)) {
337
- keysToRemove.push(key);
338
- }
339
- }
340
- for (const key of keysToRemove) {
341
- this.removeStorage(key);
342
- }
343
- }
344
315
  storage() {
345
316
  try {
346
317
  return this.documentRef?.defaultView?.localStorage ?? null;
@@ -391,37 +362,6 @@ class NavigationService {
391
362
  this.removeStorage(this.instanceStorageKey(id, property));
392
363
  }
393
364
  }
394
- migrateLegacyPersistedStorage() {
395
- // Generasi sebelumnya memakai istilah "appearance" — salin nilainya ke key "type" baru.
396
- if (this.readStorage(this.persistedStorageKey('type')) === null) {
397
- const legacyType = this.readStorage('nav-appearance');
398
- if (legacyType !== null) {
399
- this.writeStorage(this.persistedStorageKey('type'), legacyType);
400
- }
401
- }
402
- if (this.readStorage(TYPE_MODE_STORAGE_KEY) === null) {
403
- const legacyTypeMode = this.readStorage('nav-appearance-mode');
404
- if (legacyTypeMode !== null) {
405
- this.writeStorage(TYPE_MODE_STORAGE_KEY, legacyTypeMode);
406
- }
407
- }
408
- for (const property of PERSISTED_STORAGE_PROPERTIES) {
409
- const nextKey = this.persistedStorageKey(property);
410
- const legacyKey = this.instanceStorageKey(PERSISTED_NAV_ID, LEGACY_PROPERTY_NAMES[property]);
411
- const nextValue = this.readStorage(nextKey);
412
- const legacyValue = this.readStorage(legacyKey);
413
- if (nextValue === null && legacyValue !== null) {
414
- this.writeStorage(nextKey, legacyValue);
415
- }
416
- }
417
- if (this.readStorage(TYPE_MODE_STORAGE_KEY) !== null) {
418
- return;
419
- }
420
- const migratedTypeMode = this.resolveLegacyTypeMode();
421
- if (migratedTypeMode !== null) {
422
- this.writeStorage(TYPE_MODE_STORAGE_KEY, migratedTypeMode);
423
- }
424
- }
425
365
  instanceStorageKey(id, property) {
426
366
  return `nav:${id}:${property}`;
427
367
  }
@@ -434,35 +374,9 @@ class NavigationService {
434
374
  }
435
375
  return state.collapsed ? 'collapsed' : 'default';
436
376
  }
437
- resolveLegacyTypeMode() {
438
- const type = this.readStorage(this.persistedStorageKey('type')) ??
439
- this.readStorage(this.instanceStorageKey(PERSISTED_NAV_ID, 'appearance'));
440
- const collapsed = this.readStorage('nav-collapsed') ?? this.readStorage(this.instanceStorageKey(PERSISTED_NAV_ID, 'collapsed'));
441
- const dockbarMode = this.readStorage('nav-dockbar-mode') ??
442
- this.readStorage(this.instanceStorageKey(PERSISTED_NAV_ID, 'dockbar-mode'));
443
- if (type === 'dockbar' && this.isDockbarMode(dockbarMode)) {
444
- return dockbarMode;
445
- }
446
- if (type === 'sidebar') {
447
- return collapsed === 'true' ? 'collapsed' : 'default';
448
- }
449
- if (this.isDockbarMode(dockbarMode)) {
450
- return dockbarMode;
451
- }
452
- if (collapsed === 'true') {
453
- return 'collapsed';
454
- }
455
- if (collapsed === 'false') {
456
- return 'default';
457
- }
458
- return null;
459
- }
460
377
  shouldPersistInstanceState(id) {
461
378
  return id === PERSISTED_NAV_ID;
462
379
  }
463
- isLegacyInstanceStorageKey(key) {
464
- return key.startsWith('nav:');
465
- }
466
380
  isPersistedTypeMode(value) {
467
381
  return value === 'default' || value === 'collapsed' || this.isDockbarMode(value);
468
382
  }