@africanies/angular-web-sdk 0.1.2 → 0.1.4

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 (86) hide show
  1. package/.nx/cache/12276756491762927325/dist/libs/africanies-theme/README.md +46 -0
  2. package/.nx/cache/12276756491762927325/dist/libs/africanies-theme/fesm2022/africanies-africanies-theme.mjs +215 -0
  3. package/.nx/cache/12276756491762927325/dist/libs/africanies-theme/fesm2022/africanies-africanies-theme.mjs.map +1 -0
  4. package/.nx/cache/12276756491762927325/dist/libs/africanies-theme/package.json +35 -0
  5. package/.nx/cache/12276756491762927325/dist/libs/africanies-theme/tailwind-preset.cjs +245 -0
  6. package/.nx/cache/12276756491762927325/dist/libs/africanies-theme/types/africanies-africanies-theme.d.ts +157 -0
  7. package/.nx/cache/17491371155400585077/dist/libs/africanies-core/README.md +85 -0
  8. package/.nx/cache/17491371155400585077/dist/libs/africanies-core/fesm2022/africanies-africanies-core.mjs +4546 -0
  9. package/.nx/cache/17491371155400585077/dist/libs/africanies-core/fesm2022/africanies-africanies-core.mjs.map +1 -0
  10. package/.nx/cache/17491371155400585077/dist/libs/africanies-core/package.json +31 -0
  11. package/.nx/cache/17491371155400585077/dist/libs/africanies-core/types/africanies-africanies-core.d.ts +2740 -0
  12. package/.nx/cache/17499961385238663835/dist/libs/africanies-ui/README.md +68 -0
  13. package/.nx/cache/17499961385238663835/dist/libs/africanies-ui/assets/brand/africanies-logo-mini.png +0 -0
  14. package/.nx/cache/17499961385238663835/dist/libs/africanies-ui/assets/brand/africanies-logo.png +0 -0
  15. package/.nx/cache/17499961385238663835/dist/libs/africanies-ui/assets/brand/africanies-logo.svg +5 -0
  16. package/.nx/cache/17499961385238663835/dist/libs/africanies-ui/assets/carriers/dhl.svg +7 -0
  17. package/.nx/cache/17499961385238663835/dist/libs/africanies-ui/fesm2022/africanies-africanies-ui.mjs +19375 -0
  18. package/.nx/cache/17499961385238663835/dist/libs/africanies-ui/fesm2022/africanies-africanies-ui.mjs.map +1 -0
  19. package/.nx/cache/17499961385238663835/dist/libs/africanies-ui/package.json +35 -0
  20. package/.nx/cache/17499961385238663835/dist/libs/africanies-ui/types/africanies-africanies-ui.d.ts +5490 -0
  21. package/.nx/cache/3314955264390318442/dist/libs/africanies-ui/README.md +68 -0
  22. package/.nx/cache/3314955264390318442/dist/libs/africanies-ui/assets/brand/africanies-logo-mini.png +0 -0
  23. package/.nx/cache/3314955264390318442/dist/libs/africanies-ui/assets/brand/africanies-logo.png +0 -0
  24. package/.nx/cache/3314955264390318442/dist/libs/africanies-ui/assets/brand/africanies-logo.svg +5 -0
  25. package/.nx/cache/3314955264390318442/dist/libs/africanies-ui/assets/carriers/dhl.svg +7 -0
  26. package/.nx/cache/3314955264390318442/dist/libs/africanies-ui/fesm2022/africanies-africanies-ui.mjs +19291 -0
  27. package/.nx/cache/3314955264390318442/dist/libs/africanies-ui/fesm2022/africanies-africanies-ui.mjs.map +1 -0
  28. package/.nx/cache/3314955264390318442/dist/libs/africanies-ui/package.json +35 -0
  29. package/.nx/cache/3314955264390318442/dist/libs/africanies-ui/types/africanies-africanies-ui.d.ts +5483 -0
  30. package/.nx/cache/4082520855419352840/dist/libs/africanies-theme/README.md +46 -0
  31. package/.nx/cache/4082520855419352840/dist/libs/africanies-theme/fesm2022/africanies-africanies-theme.mjs +221 -0
  32. package/.nx/cache/4082520855419352840/dist/libs/africanies-theme/fesm2022/africanies-africanies-theme.mjs.map +1 -0
  33. package/.nx/cache/4082520855419352840/dist/libs/africanies-theme/package.json +35 -0
  34. package/.nx/cache/4082520855419352840/dist/libs/africanies-theme/tailwind-preset.cjs +253 -0
  35. package/.nx/cache/4082520855419352840/dist/libs/africanies-theme/types/africanies-africanies-theme.d.ts +166 -0
  36. package/.nx/cache/run.json +19 -19
  37. package/.nx/cache/terminalOutputs/12276756491762927325 +21 -0
  38. package/.nx/cache/terminalOutputs/16279119293212733518 +6 -0
  39. package/.nx/cache/terminalOutputs/17491371155400585077 +21 -0
  40. package/.nx/cache/terminalOutputs/17499961385238663835 +21 -0
  41. package/.nx/cache/terminalOutputs/3017748574492080228 +28 -0
  42. package/.nx/cache/terminalOutputs/3314955264390318442 +21 -0
  43. package/.nx/cache/terminalOutputs/4082520855419352840 +21 -0
  44. package/.nx/cache/terminalOutputs/7126777490381568487 +32 -0
  45. package/.nx/cache/terminalOutputs/8648260256613557249 +173 -0
  46. package/.nx/cache/terminalOutputs/9408529484792607601 +6 -0
  47. package/.nx/workspace-data/0091ABA9-5C90-580D-953C-8C94E763ADB5-v3.db +0 -0
  48. package/.nx/workspace-data/0091ABA9-5C90-580D-953C-8C94E763ADB5-v3.db-shm +0 -0
  49. package/.nx/workspace-data/0091ABA9-5C90-580D-953C-8C94E763ADB5-v3.db-wal +0 -0
  50. package/.nx/workspace-data/d/daemon.log +3296 -0
  51. package/.nx/workspace-data/d/server-process.json +2 -2
  52. package/.nx/workspace-data/file-map.json +3422 -3408
  53. package/.nx/workspace-data/nx_files.nxt +0 -0
  54. package/.nx/workspace-data/project-graph.json +5 -5
  55. package/.nx/workspace-data/source-maps.json +0 -80
  56. package/apps/playground/src/app/snippets/action-menu.snippets.ts +1 -0
  57. package/dist/libs/africanies-core/fesm2022/africanies-africanies-core.mjs +1 -1
  58. package/dist/libs/africanies-core/fesm2022/africanies-africanies-core.mjs.map +1 -1
  59. package/dist/libs/africanies-core/package.json +3 -3
  60. package/dist/libs/africanies-theme/fesm2022/africanies-africanies-theme.mjs +6 -0
  61. package/dist/libs/africanies-theme/fesm2022/africanies-africanies-theme.mjs.map +1 -1
  62. package/dist/libs/africanies-theme/package.json +3 -3
  63. package/dist/libs/africanies-theme/tailwind-preset.cjs +15 -7
  64. package/dist/libs/africanies-theme/types/africanies-africanies-theme.d.ts +10 -1
  65. package/dist/libs/africanies-ui/fesm2022/africanies-africanies-ui.mjs +456 -169
  66. package/dist/libs/africanies-ui/fesm2022/africanies-africanies-ui.mjs.map +1 -1
  67. package/dist/libs/africanies-ui/package.json +5 -5
  68. package/dist/libs/africanies-ui/types/africanies-africanies-ui.d.ts +111 -31
  69. package/libs/africanies-core/package.json +3 -3
  70. package/libs/africanies-core/src/lib/payment-method/payment-method.mapper.spec.ts +15 -0
  71. package/libs/africanies-core/src/lib/payment-method/payment-method.mapper.ts +1 -2
  72. package/libs/africanies-theme/package.json +3 -3
  73. package/libs/africanies-theme/src/lib/mode-color.safelist.ts +4 -0
  74. package/libs/africanies-theme/src/lib/mode-color.service.ts +11 -0
  75. package/libs/africanies-theme/tailwind-preset.cjs +15 -7
  76. package/libs/africanies-ui/package.json +5 -5
  77. package/libs/africanies-ui/src/index.ts +6 -0
  78. package/libs/africanies-ui/src/lib/accordion/accordion.component.ts +135 -0
  79. package/libs/africanies-ui/src/lib/accordion/index.ts +7 -0
  80. package/libs/africanies-ui/src/lib/action-menu/action-menu.component.ts +84 -17
  81. package/libs/africanies-ui/src/lib/action-menu/menu-item.ts +19 -2
  82. package/libs/africanies-ui/src/lib/layout/header-weather.spec.ts +111 -6
  83. package/libs/africanies-ui/src/lib/layout/header-weather.ts +104 -8
  84. package/libs/africanies-ui/src/lib/modules/africanies-feedback.module.ts +3 -1
  85. package/libs/africanies-ui/src/lib/table/table.component.ts +67 -44
  86. package/package.json +1 -1
@@ -1,17 +1,17 @@
1
1
  import * as i0 from '@angular/core';
2
- import { inject, input, booleanAttribute, computed, ChangeDetectionStrategy, Component, output, signal, Injector, DestroyRef, Injectable, numberAttribute, Directive, viewChild, contentChild, makeEnvironmentProviders, provideAppInitializer, model, forwardRef, InjectionToken, effect, afterNextRender, viewChildren, TemplateRef, contentChildren, untracked, runInInjectionContext, afterRenderEffect, NgModule } from '@angular/core';
2
+ import { inject, input, booleanAttribute, computed, ChangeDetectionStrategy, Component, output, signal, Injector, DestroyRef, Injectable, numberAttribute, Directive, viewChild, contentChild, model, makeEnvironmentProviders, provideAppInitializer, forwardRef, InjectionToken, effect, afterNextRender, viewChildren, TemplateRef, contentChildren, untracked, runInInjectionContext, afterRenderEffect, NgModule } from '@angular/core';
3
3
  import { AfricaniesIconComponent } from '@africanies/africanies-icons';
4
4
  import { ModeColorService, ThemeService } from '@africanies/africanies-theme';
5
5
  import { copyToClipboard, AFRICANIES_HTTP_TOAST, FilterOptionsResolver, MODAL_SERVICE, DRAWER_SERVICE, ShippingModeService, resolveNotificationLinkForMode } from '@africanies/africanies-core';
6
6
  import { Overlay, CdkOverlayOrigin, CdkConnectedOverlay } from '@angular/cdk/overlay';
7
7
  import { ComponentPortal } from '@angular/cdk/portal';
8
+ import { Router, ActivatedRoute, RouterLink, NavigationEnd } from '@angular/router';
8
9
  import { EXPORT_DELIVERY_VENDORS, DELIVERY_VENDORS, normalizeDeliveryVendorForForm, isKnownDeliveryVendor, hasFilterParams, fromFilterParams, filterQueryKeys, toFilterParams, cloneFilterState, resetFilterState, PAGINATION_PAGE_SIZES, DEFAULT_PAGE_SIZE } from '@africanies/africanies-models';
9
10
  export { DEFAULT_FILTER_TRANSPORT, DEFAULT_PAGE_SIZE, FILTER_CONFIGS, FilterTransport, NOTIFICATION_PAGE_SIZE, PAGINATION_PAGE_SIZES, clearFilterField, cloneFilterState, emptyFilterState, filterQueryKeys, fromFilterParams, hasFilterParams, resetFilterState, resolveFilterTransport, shipmentTrackingItemFilterConfig, toFilterParams, trackShipmentsFilterConfig, updateShipmentsFilterConfig, usersFilterConfig } from '@africanies/africanies-models';
10
11
  import { HttpErrorResponse } from '@angular/common/http';
11
12
  import { takeUntilDestroyed, toSignal } from '@angular/core/rxjs-interop';
12
13
  import { Subject, take, isObservable, defer, throwError, of, from, map, timer, filter, startWith } from 'rxjs';
13
14
  import { NG_VALUE_ACCESSOR } from '@angular/forms';
14
- import { ActivatedRoute, Router, RouterLink, NavigationEnd } from '@angular/router';
15
15
  import { debounce, switchMap, distinctUntilChanged, tap, catchError } from 'rxjs/operators';
16
16
  import { NgTemplateOutlet, NgClass, DatePipe } from '@angular/common';
17
17
 
@@ -1303,6 +1303,84 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
1303
1303
  * Clipboard copy control (`africanies-copy`).
1304
1304
  */
1305
1305
 
1306
+ /**
1307
+ * Builds a {@link UrlTree} for an item’s `routerLink` / query / fragment.
1308
+ *
1309
+ * @param router - Consumer app router.
1310
+ * @param item - Nav item with a `routerLink`.
1311
+ * @returns UrlTree, or `null` when the item is not routed.
1312
+ */
1313
+ function navItemUrlTree(router, item) {
1314
+ if (item.routerLink == null) {
1315
+ return null;
1316
+ }
1317
+ const commands = Array.isArray(item.routerLink)
1318
+ ? [...item.routerLink]
1319
+ : [item.routerLink];
1320
+ return router.createUrlTree(commands, {
1321
+ queryParams: item.queryParams,
1322
+ fragment: item.fragment,
1323
+ });
1324
+ }
1325
+ /**
1326
+ * Whether the current router URL matches this item (cold load + navigations).
1327
+ *
1328
+ * @param router - Consumer app router.
1329
+ * @param item - Nav item with a `routerLink`.
1330
+ * @param options - Same shape as `RouterLinkActive` options.
1331
+ * @returns True when the current URL matches the item.
1332
+ */
1333
+ function isNavItemActive(router, item, options) {
1334
+ const tree = navItemUrlTree(router, item);
1335
+ if (!tree) {
1336
+ return false;
1337
+ }
1338
+ return router.isActive(tree, options);
1339
+ }
1340
+
1341
+ /**
1342
+ * Whether a click should leave navigation to the browser (new tab, etc.).
1343
+ * @param event - Mouse click from a routed nav control.
1344
+ * @returns True when the host should not call `preventDefault` / navigate.
1345
+ */
1346
+ function isModifiedClick(event) {
1347
+ return (event.button !== 0 ||
1348
+ event.metaKey ||
1349
+ event.ctrlKey ||
1350
+ event.shiftKey ||
1351
+ event.altKey);
1352
+ }
1353
+ /**
1354
+ * Serialized href for a routed nav item (for `<a href>` without RouterLink).
1355
+ * @param router - App router.
1356
+ * @param item - Nav item with `routerLink`.
1357
+ * @returns Path string, or `null` when the item is not routed.
1358
+ */
1359
+ function navItemHref(router, item) {
1360
+ const tree = navItemUrlTree(router, item);
1361
+ return tree ? router.serializeUrl(tree) : null;
1362
+ }
1363
+ /**
1364
+ * Navigate to a nav item without jumping the viewport to the top.
1365
+ *
1366
+ * Apps that enable `withInMemoryScrolling({ scrollPositionRestoration:
1367
+ * 'enabled' })` scroll to `[0, 0]` on every forward navigation. That is wrong
1368
+ * for in-page tabs/segments. Passing `{ scroll: 'manual' }` tells Angular's
1369
+ * RouterScroller to skip scrolling for this navigation.
1370
+ *
1371
+ * @param router - App router.
1372
+ * @param item - Nav item with `routerLink`.
1373
+ * @param keepScroll - When true (default for tabs/segments), skip router scroll.
1374
+ * @returns Navigation promise, or `null` when the item is not routed.
1375
+ */
1376
+ function navigateNavItem(router, item, keepScroll = true) {
1377
+ const tree = navItemUrlTree(router, item);
1378
+ if (!tree) {
1379
+ return null;
1380
+ }
1381
+ return router.navigateByUrl(tree, keepScroll ? { scroll: 'manual' } : undefined);
1382
+ }
1383
+
1306
1384
  /**
1307
1385
  * Marks projected content as the custom trigger for {@link ActionMenuComponent}.
1308
1386
  *
@@ -1358,6 +1436,9 @@ const MENU_PANEL_POSITIONS = [
1358
1436
  * clipped by table `overflow`. Default trigger is a ghost ellipsis button;
1359
1437
  * project a custom control with {@link ActionMenuTriggerDirective}.
1360
1438
  *
1439
+ * Items with {@link AfricaniesMenuItem.routerLink} render as anchors so users
1440
+ * can right-click / modified-click to open in a new tab.
1441
+ *
1361
1442
  * @example
1362
1443
  * ```html
1363
1444
  * <!-- Default icon trigger (table row) -->
@@ -1373,7 +1454,12 @@ const MENU_PANEL_POSITIONS = [
1373
1454
  * ```ts
1374
1455
  * rowActions(row: Shipment): AfricaniesMenuItem[] {
1375
1456
  * return [
1376
- * { label: 'Open', icon: 'eye', onClick: () => this.open(row) },
1457
+ * {
1458
+ * label: 'Open',
1459
+ * icon: 'eye',
1460
+ * routerLink: ['/shipments', row.id],
1461
+ * onClick: () => this.open(row),
1462
+ * },
1377
1463
  * { label: 'Edit', icon: 'edit', onClick: () => this.edit(row) },
1378
1464
  * {
1379
1465
  * label: 'Delete',
@@ -1387,6 +1473,7 @@ const MENU_PANEL_POSITIONS = [
1387
1473
  * ```
1388
1474
  */
1389
1475
  class ActionMenuComponent {
1476
+ router = inject(Router);
1390
1477
  panelPositions = MENU_PANEL_POSITIONS;
1391
1478
  panelRef = viewChild('panel', /* @ts-ignore */
1392
1479
  ...(ngDevMode ? [{ debugName: "panelRef" }] : /* istanbul ignore next */ []));
@@ -1412,7 +1499,7 @@ class ActionMenuComponent {
1412
1499
  }
1413
1500
  itemClass(item, index) {
1414
1501
  const active = this.activeIndex() === index;
1415
- const base = 'flex w-full cursor-pointer items-center gap-2 px-3 py-2 text-body-sm transition-colors ' +
1502
+ const base = 'flex w-full cursor-pointer items-center gap-2 px-3 py-2 text-body-sm no-underline transition-colors ' +
1416
1503
  'disabled:cursor-not-allowed disabled:opacity-50 ' +
1417
1504
  'focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-[-2px] focus-visible:outline-ink';
1418
1505
  if (item.danger) {
@@ -1426,6 +1513,9 @@ class ActionMenuComponent {
1426
1513
  ? 'bg-background-welcome dark:bg-white/10'
1427
1514
  : 'hover:bg-background-welcome dark:hover:bg-white/10'));
1428
1515
  }
1516
+ hrefFor(item) {
1517
+ return navItemHref(this.router, item);
1518
+ }
1429
1519
  onTriggerClick(event) {
1430
1520
  event.preventDefault();
1431
1521
  event.stopPropagation();
@@ -1500,11 +1590,35 @@ class ActionMenuComponent {
1500
1590
  onOverlayDetach() {
1501
1591
  this.open.set(false);
1502
1592
  }
1593
+ /**
1594
+ * Primary click on a routed item: in-app activate via {@link onClick} or
1595
+ * router. Modified clicks keep native link behaviour (new tab).
1596
+ */
1597
+ onRoutedItemClick(event, item) {
1598
+ if (item.disabled) {
1599
+ event.preventDefault();
1600
+ return;
1601
+ }
1602
+ if (isModifiedClick(event)) {
1603
+ this.close();
1604
+ return;
1605
+ }
1606
+ event.preventDefault();
1607
+ this.activateItem(item);
1608
+ }
1503
1609
  selectItem(item) {
1504
1610
  if (item.disabled) {
1505
1611
  return;
1506
1612
  }
1507
- item.onClick();
1613
+ this.activateItem(item);
1614
+ }
1615
+ activateItem(item) {
1616
+ if (item.onClick) {
1617
+ item.onClick();
1618
+ }
1619
+ else if (item.routerLink != null) {
1620
+ void navigateNavItem(this.router, item, false);
1621
+ }
1508
1622
  this.close();
1509
1623
  }
1510
1624
  toggle() {
@@ -1606,20 +1720,41 @@ class ActionMenuComponent {
1606
1720
  role="separator"
1607
1721
  ></div>
1608
1722
  }
1609
- <button
1610
- type="button"
1611
- role="menuitem"
1612
- [id]="itemDomId(i)"
1613
- [class]="itemClass(item, i)"
1614
- [disabled]="!!item.disabled"
1615
- (click)="selectItem(item)"
1616
- (mouseenter)="activeIndex.set(i)"
1617
- >
1618
- @if (item.icon; as icon) {
1619
- <africanies-icon [name]="icon" [size]="16" class="shrink-0" />
1620
- }
1621
- <span class="min-w-0 flex-1 truncate text-left">{{ item.label }}</span>
1622
- </button>
1723
+ @if (item.routerLink !== null && item.routerLink !== undefined) {
1724
+ <a
1725
+ role="menuitem"
1726
+ [id]="itemDomId(i)"
1727
+ [class]="itemClass(item, i)"
1728
+ [attr.href]="item.disabled ? null : hrefFor(item)"
1729
+ [attr.aria-disabled]="item.disabled ? true : null"
1730
+ (click)="onRoutedItemClick($event, item)"
1731
+ (mouseenter)="activeIndex.set(i)"
1732
+ >
1733
+ @if (item.icon; as icon) {
1734
+ <africanies-icon [name]="icon" [size]="16" class="shrink-0" />
1735
+ }
1736
+ <span class="min-w-0 flex-1 truncate text-left">{{
1737
+ item.label
1738
+ }}</span>
1739
+ </a>
1740
+ } @else {
1741
+ <button
1742
+ type="button"
1743
+ role="menuitem"
1744
+ [id]="itemDomId(i)"
1745
+ [class]="itemClass(item, i)"
1746
+ [disabled]="!!item.disabled"
1747
+ (click)="selectItem(item)"
1748
+ (mouseenter)="activeIndex.set(i)"
1749
+ >
1750
+ @if (item.icon; as icon) {
1751
+ <africanies-icon [name]="icon" [size]="16" class="shrink-0" />
1752
+ }
1753
+ <span class="min-w-0 flex-1 truncate text-left">{{
1754
+ item.label
1755
+ }}</span>
1756
+ </button>
1757
+ }
1623
1758
  }
1624
1759
  </div>
1625
1760
  </ng-template>
@@ -1702,20 +1837,41 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
1702
1837
  role="separator"
1703
1838
  ></div>
1704
1839
  }
1705
- <button
1706
- type="button"
1707
- role="menuitem"
1708
- [id]="itemDomId(i)"
1709
- [class]="itemClass(item, i)"
1710
- [disabled]="!!item.disabled"
1711
- (click)="selectItem(item)"
1712
- (mouseenter)="activeIndex.set(i)"
1713
- >
1714
- @if (item.icon; as icon) {
1715
- <africanies-icon [name]="icon" [size]="16" class="shrink-0" />
1716
- }
1717
- <span class="min-w-0 flex-1 truncate text-left">{{ item.label }}</span>
1718
- </button>
1840
+ @if (item.routerLink !== null && item.routerLink !== undefined) {
1841
+ <a
1842
+ role="menuitem"
1843
+ [id]="itemDomId(i)"
1844
+ [class]="itemClass(item, i)"
1845
+ [attr.href]="item.disabled ? null : hrefFor(item)"
1846
+ [attr.aria-disabled]="item.disabled ? true : null"
1847
+ (click)="onRoutedItemClick($event, item)"
1848
+ (mouseenter)="activeIndex.set(i)"
1849
+ >
1850
+ @if (item.icon; as icon) {
1851
+ <africanies-icon [name]="icon" [size]="16" class="shrink-0" />
1852
+ }
1853
+ <span class="min-w-0 flex-1 truncate text-left">{{
1854
+ item.label
1855
+ }}</span>
1856
+ </a>
1857
+ } @else {
1858
+ <button
1859
+ type="button"
1860
+ role="menuitem"
1861
+ [id]="itemDomId(i)"
1862
+ [class]="itemClass(item, i)"
1863
+ [disabled]="!!item.disabled"
1864
+ (click)="selectItem(item)"
1865
+ (mouseenter)="activeIndex.set(i)"
1866
+ >
1867
+ @if (item.icon; as icon) {
1868
+ <africanies-icon [name]="icon" [size]="16" class="shrink-0" />
1869
+ }
1870
+ <span class="min-w-0 flex-1 truncate text-left">{{
1871
+ item.label
1872
+ }}</span>
1873
+ </button>
1874
+ }
1719
1875
  }
1720
1876
  </div>
1721
1877
  </ng-template>
@@ -2384,6 +2540,128 @@ function isEmptyData(data) {
2384
2540
  * {@link AsyncStateComponent}) around tables and resource views.
2385
2541
  */
2386
2542
 
2543
+ /**
2544
+ * Bordered expandable panel with animated fold — the pattern used on
2545
+ * Manifest detail and Make Payment review.
2546
+ *
2547
+ * Parent owns open state via {@link open} (`model()` / `[(open)]`).
2548
+ *
2549
+ * @example
2550
+ * ```html
2551
+ * <africanies-accordion
2552
+ * title="Customer Information"
2553
+ * [open]="isOpen('customer')"
2554
+ * (openChange)="onOpenChange('customer', $event)"
2555
+ * >
2556
+ * <dl>…</dl>
2557
+ * </africanies-accordion>
2558
+ * ```
2559
+ */
2560
+ class AccordionComponent {
2561
+ /** Plain-text header. Prefer projected `[africaniesAccordionTitle]` for rich titles. */
2562
+ title = input('', /* @ts-ignore */
2563
+ ...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
2564
+ /** Whether the panel body is expanded. */
2565
+ open = model(false, /* @ts-ignore */
2566
+ ...(ngDevMode ? [{ debugName: "open" }] : /* istanbul ignore next */ []));
2567
+ /** Padding / chevron density. */
2568
+ size = input('md', /* @ts-ignore */
2569
+ ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
2570
+ chevronSize = computed(() => this.size() === 'sm' ? 14 : 16, /* @ts-ignore */
2571
+ ...(ngDevMode ? [{ debugName: "chevronSize" }] : /* istanbul ignore next */ []));
2572
+ shellClass = computed(() => this.size() === 'sm'
2573
+ ? 'rounded-lg border border-border dark:border-white/10'
2574
+ : 'rounded-xl border border-border dark:border-white/10', /* @ts-ignore */
2575
+ ...(ngDevMode ? [{ debugName: "shellClass" }] : /* istanbul ignore next */ []));
2576
+ triggerClass = computed(() => this.size() === 'sm'
2577
+ ? 'flex w-full items-center justify-between gap-3 px-3 py-2 text-left text-ink dark:text-white'
2578
+ : 'flex w-full items-center justify-between gap-3 px-4 py-3 text-left text-ink dark:text-white', /* @ts-ignore */
2579
+ ...(ngDevMode ? [{ debugName: "triggerClass" }] : /* istanbul ignore next */ []));
2580
+ bodyClass = computed(() => this.size() === 'sm'
2581
+ ? 'border-t border-border px-3 py-2 dark:border-white/10'
2582
+ : 'border-t border-border px-4 py-3 dark:border-white/10', /* @ts-ignore */
2583
+ ...(ngDevMode ? [{ debugName: "bodyClass" }] : /* istanbul ignore next */ []));
2584
+ toggle() {
2585
+ this.open.update((value) => !value);
2586
+ }
2587
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AccordionComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2588
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AccordionComponent, isStandalone: true, selector: "africanies-accordion", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { open: "openChange" }, host: { classAttribute: "block" }, ngImport: i0, template: `
2589
+ <div [class]="shellClass()">
2590
+ <button
2591
+ type="button"
2592
+ [class]="triggerClass()"
2593
+ [attr.aria-expanded]="open()"
2594
+ (click)="toggle()"
2595
+ >
2596
+ <span class="min-w-0 flex-1 font-medium">
2597
+ <ng-content select="[africaniesAccordionTitle]" />
2598
+ @if (title()) {
2599
+ {{ title() }}
2600
+ }
2601
+ </span>
2602
+ <africanies-icon
2603
+ name="chevron-down"
2604
+ class="shrink-0 transition-transform duration-200"
2605
+ [class.rotate-180]="open()"
2606
+ [size]="chevronSize()"
2607
+ />
2608
+ </button>
2609
+ <div
2610
+ class="africanies-accordion-fold"
2611
+ [class.africanies-accordion-fold-open]="open()"
2612
+ >
2613
+ <div class="africanies-accordion-fold-body">
2614
+ <div [class]="bodyClass()">
2615
+ <ng-content />
2616
+ </div>
2617
+ </div>
2618
+ </div>
2619
+ </div>
2620
+ `, isInline: true, styles: [".africanies-accordion-fold{display:grid;grid-template-rows:0fr;transition:grid-template-rows .2s ease}.africanies-accordion-fold-open{grid-template-rows:1fr}.africanies-accordion-fold-body{min-height:0;overflow:hidden}@media(prefers-reduced-motion:reduce){.africanies-accordion-fold{transition:none}}\n"], dependencies: [{ kind: "component", type: AfricaniesIconComponent, selector: "africanies-icon", inputs: ["name", "size"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2621
+ }
2622
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AccordionComponent, decorators: [{
2623
+ type: Component,
2624
+ args: [{ selector: 'africanies-accordion', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [AfricaniesIconComponent], host: {
2625
+ class: 'block',
2626
+ }, template: `
2627
+ <div [class]="shellClass()">
2628
+ <button
2629
+ type="button"
2630
+ [class]="triggerClass()"
2631
+ [attr.aria-expanded]="open()"
2632
+ (click)="toggle()"
2633
+ >
2634
+ <span class="min-w-0 flex-1 font-medium">
2635
+ <ng-content select="[africaniesAccordionTitle]" />
2636
+ @if (title()) {
2637
+ {{ title() }}
2638
+ }
2639
+ </span>
2640
+ <africanies-icon
2641
+ name="chevron-down"
2642
+ class="shrink-0 transition-transform duration-200"
2643
+ [class.rotate-180]="open()"
2644
+ [size]="chevronSize()"
2645
+ />
2646
+ </button>
2647
+ <div
2648
+ class="africanies-accordion-fold"
2649
+ [class.africanies-accordion-fold-open]="open()"
2650
+ >
2651
+ <div class="africanies-accordion-fold-body">
2652
+ <div [class]="bodyClass()">
2653
+ <ng-content />
2654
+ </div>
2655
+ </div>
2656
+ </div>
2657
+ </div>
2658
+ `, styles: [".africanies-accordion-fold{display:grid;grid-template-rows:0fr;transition:grid-template-rows .2s ease}.africanies-accordion-fold-open{grid-template-rows:1fr}.africanies-accordion-fold-body{min-height:0;overflow:hidden}@media(prefers-reduced-motion:reduce){.africanies-accordion-fold{transition:none}}\n"] }]
2659
+ }], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], open: [{ type: i0.Input, args: [{ isSignal: true, alias: "open", required: false }] }, { type: i0.Output, args: ["openChange"] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }] } });
2660
+
2661
+ /**
2662
+ * Expandable bordered panels (`africanies-accordion`).
2663
+ */
2664
+
2387
2665
  const DEFAULT_ICONS = {
2388
2666
  info: 'info-circle',
2389
2667
  success: 'check-circle',
@@ -12925,84 +13203,6 @@ function finalizeLeaf(crumbs, path) {
12925
13203
  return crumbs;
12926
13204
  }
12927
13205
 
12928
- /**
12929
- * Builds a {@link UrlTree} for an item’s `routerLink` / query / fragment.
12930
- *
12931
- * @param router - Consumer app router.
12932
- * @param item - Nav item with a `routerLink`.
12933
- * @returns UrlTree, or `null` when the item is not routed.
12934
- */
12935
- function navItemUrlTree(router, item) {
12936
- if (item.routerLink == null) {
12937
- return null;
12938
- }
12939
- const commands = Array.isArray(item.routerLink)
12940
- ? [...item.routerLink]
12941
- : [item.routerLink];
12942
- return router.createUrlTree(commands, {
12943
- queryParams: item.queryParams,
12944
- fragment: item.fragment,
12945
- });
12946
- }
12947
- /**
12948
- * Whether the current router URL matches this item (cold load + navigations).
12949
- *
12950
- * @param router - Consumer app router.
12951
- * @param item - Nav item with a `routerLink`.
12952
- * @param options - Same shape as `RouterLinkActive` options.
12953
- * @returns True when the current URL matches the item.
12954
- */
12955
- function isNavItemActive(router, item, options) {
12956
- const tree = navItemUrlTree(router, item);
12957
- if (!tree) {
12958
- return false;
12959
- }
12960
- return router.isActive(tree, options);
12961
- }
12962
-
12963
- /**
12964
- * Whether a click should leave navigation to the browser (new tab, etc.).
12965
- * @param event - Mouse click from a routed nav control.
12966
- * @returns True when the host should not call `preventDefault` / navigate.
12967
- */
12968
- function isModifiedClick(event) {
12969
- return (event.button !== 0 ||
12970
- event.metaKey ||
12971
- event.ctrlKey ||
12972
- event.shiftKey ||
12973
- event.altKey);
12974
- }
12975
- /**
12976
- * Serialized href for a routed nav item (for `<a href>` without RouterLink).
12977
- * @param router - App router.
12978
- * @param item - Nav item with `routerLink`.
12979
- * @returns Path string, or `null` when the item is not routed.
12980
- */
12981
- function navItemHref(router, item) {
12982
- const tree = navItemUrlTree(router, item);
12983
- return tree ? router.serializeUrl(tree) : null;
12984
- }
12985
- /**
12986
- * Navigate to a nav item without jumping the viewport to the top.
12987
- *
12988
- * Apps that enable `withInMemoryScrolling({ scrollPositionRestoration:
12989
- * 'enabled' })` scroll to `[0, 0]` on every forward navigation. That is wrong
12990
- * for in-page tabs/segments. Passing `{ scroll: 'manual' }` tells Angular's
12991
- * RouterScroller to skip scrolling for this navigation.
12992
- *
12993
- * @param router - App router.
12994
- * @param item - Nav item with `routerLink`.
12995
- * @param keepScroll - When true (default for tabs/segments), skip router scroll.
12996
- * @returns Navigation promise, or `null` when the item is not routed.
12997
- */
12998
- function navigateNavItem(router, item, keepScroll = true) {
12999
- const tree = navItemUrlTree(router, item);
13000
- if (!tree) {
13001
- return null;
13002
- }
13003
- return router.navigateByUrl(tree, keepScroll ? { scroll: 'manual' } : undefined);
13004
- }
13005
-
13006
13206
  const DEFAULT_LINK_ACTIVE$2 = {
13007
13207
  paths: 'exact',
13008
13208
  queryParams: 'exact',
@@ -15795,9 +15995,14 @@ function hashString(value) {
15795
15995
  return hash;
15796
15996
  }
15797
15997
 
15798
- const CACHE_KEY = 'africanies-header-weather-v3';
15998
+ /** Bump when cache shape or city resolution strategy changes. */
15999
+ const CACHE_KEY = 'africanies-header-weather-v4';
15799
16000
  const FETCH_MS = 4_000;
16001
+ const BROWSER_GEO_MS = 3_500;
16002
+ /** IP fallback — city string is often wrong (e.g. NG IPs labelled Lagos). */
15800
16003
  const GEO_URL = 'https://get.geojs.io/v1/ip/geo.json';
16004
+ /** Client reverse-geocode so the label matches the forecast coordinates. */
16005
+ const REVERSE_GEO_URL = 'https://api.bigdatacloud.net/data/reverse-geocode-client';
15801
16006
  const WEATHER_LABELS = {
15802
16007
  clear: 'Clear',
15803
16008
  cloudy: 'Cloudy',
@@ -15863,7 +16068,12 @@ function headerWeatherIcon(kind, hour) {
15863
16068
  return 'cloud-o';
15864
16069
  }
15865
16070
  /**
15866
- * City-level forecast via IP geolocation + Open-Meteo (no API key).
16071
+ * City-level forecast via browser / IP geolocation + Open-Meteo (no API key).
16072
+ *
16073
+ * Coordinates prefer the browser Geolocation API (accurate for travellers;
16074
+ * may prompt once). Otherwise IP geo is used. The city label is reverse-
16075
+ * geocoded from those coordinates — IP `city` strings are often wrong for
16076
+ * Nigeria (many networks resolve as Lagos).
15867
16077
  *
15868
16078
  * Fails closed: missing browser APIs, timeouts, and HTTP errors all return
15869
16079
  * `null` so the greeting can stay time-of-day only. Cached per local hour
@@ -15883,14 +16093,12 @@ async function loadHeaderWeather(fetchFn) {
15883
16093
  return cached;
15884
16094
  }
15885
16095
  try {
15886
- const geo = (await fetchJson(run, GEO_URL));
15887
- const latitude = asNumber(geo?.latitude);
15888
- const longitude = asNumber(geo?.longitude);
15889
- if (latitude === null || longitude === null) {
16096
+ const coords = await resolveCoordinates(run);
16097
+ if (!coords) {
15890
16098
  return null;
15891
16099
  }
15892
16100
  const forecastUrl = `https://api.open-meteo.com/v1/forecast` +
15893
- `?latitude=${latitude}&longitude=${longitude}` +
16101
+ `?latitude=${coords.latitude}&longitude=${coords.longitude}` +
15894
16102
  `&current=weather_code,temperature_2m`;
15895
16103
  const forecast = (await fetchJson(run, forecastUrl));
15896
16104
  const code = asNumber(forecast?.current?.weather_code);
@@ -15902,7 +16110,8 @@ async function loadHeaderWeather(fetchFn) {
15902
16110
  return null;
15903
16111
  }
15904
16112
  const temperatureC = asNumber(forecast?.current?.temperature_2m) ?? undefined;
15905
- const city = asCity(geo?.city);
16113
+ const city = (await reverseGeocodeCity(run, coords.latitude, coords.longitude)) ??
16114
+ coords.fallbackCity;
15906
16115
  const weather = { kind, temperatureC, city };
15907
16116
  writeCache({ hour, kind, temperatureC, city });
15908
16117
  return weather;
@@ -15945,6 +16154,60 @@ function writeCache(value) {
15945
16154
  // Private mode / quota — greeting still works without cache.
15946
16155
  }
15947
16156
  }
16157
+ /**
16158
+ * Prefer device coordinates when available (may prompt once); otherwise fall
16159
+ * back to IP geo. IP city labels for Nigeria are often wrong — reverse
16160
+ * geocoding from these coordinates still depends on accurate lat/lon.
16161
+ */
16162
+ async function resolveCoordinates(fetchFn) {
16163
+ const browser = await tryBrowserGeolocation();
16164
+ if (browser) {
16165
+ return browser;
16166
+ }
16167
+ const geo = (await fetchJson(fetchFn, GEO_URL));
16168
+ const latitude = asNumber(geo?.latitude);
16169
+ const longitude = asNumber(geo?.longitude);
16170
+ if (latitude === null || longitude === null) {
16171
+ return null;
16172
+ }
16173
+ return {
16174
+ latitude,
16175
+ longitude,
16176
+ fallbackCity: asCity(geo?.city),
16177
+ };
16178
+ }
16179
+ async function tryBrowserGeolocation() {
16180
+ if (typeof navigator === 'undefined' ||
16181
+ typeof navigator.geolocation?.getCurrentPosition !== 'function') {
16182
+ return null;
16183
+ }
16184
+ return await new Promise((resolve) => {
16185
+ const timer = setTimeout(() => resolve(null), BROWSER_GEO_MS);
16186
+ navigator.geolocation.getCurrentPosition((position) => {
16187
+ clearTimeout(timer);
16188
+ resolve({
16189
+ latitude: position.coords.latitude,
16190
+ longitude: position.coords.longitude,
16191
+ });
16192
+ }, () => {
16193
+ clearTimeout(timer);
16194
+ resolve(null);
16195
+ }, {
16196
+ enableHighAccuracy: false,
16197
+ maximumAge: 600_000,
16198
+ timeout: BROWSER_GEO_MS,
16199
+ });
16200
+ });
16201
+ }
16202
+ async function reverseGeocodeCity(fetchFn, latitude, longitude) {
16203
+ const url = `${REVERSE_GEO_URL}?latitude=${encodeURIComponent(String(latitude))}` +
16204
+ `&longitude=${encodeURIComponent(String(longitude))}` +
16205
+ `&localityLanguage=en`;
16206
+ const payload = (await fetchJson(fetchFn, url));
16207
+ return (asCity(payload?.city) ??
16208
+ asCity(payload?.locality) ??
16209
+ asCity(payload?.principalSubdivision));
16210
+ }
15948
16211
  function asNumber(value) {
15949
16212
  if (typeof value === 'number' && Number.isFinite(value)) {
15950
16213
  return value;
@@ -17390,9 +17653,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
17390
17653
  * **Sticky columns:** a column with `key: 'actions'` stays pinned to the
17391
17654
  * right while the grid scrolls horizontally. The expand trigger column pins
17392
17655
  * to the left when rows are expandable. Override with
17393
- * {@link TableColumn.sticky}.
17656
+ * {@link TableColumn.sticky}. Sticky columns use a slightly thicker bottom
17657
+ * border (and opaque fill) so dividers stay visible while scrolling.
17394
17658
  */
17395
17659
  class TableComponent {
17660
+ modeColor = inject(ModeColorService);
17396
17661
  /**
17397
17662
  * When false, hides row expansion even if {@link RowDetailDefDirective}
17398
17663
  * templates are projected. Defaults to true.
@@ -17602,6 +17867,21 @@ class TableComponent {
17602
17867
  cellContext(row) {
17603
17868
  return { $implicit: row };
17604
17869
  }
17870
+ /**
17871
+ * Header row chrome. Soft fill lives on each `th` ({@link headerSoftClass})
17872
+ * so sticky columns do not double-tint and paint over neighbor labels.
17873
+ * @returns Header row class list.
17874
+ */
17875
+ headerRowClass() {
17876
+ return 'border-b border-border dark:border-white/10';
17877
+ }
17878
+ /**
17879
+ * Opaque mode soft fill for header cells (sticky-safe in dark mode).
17880
+ * @returns Soft solid background utilities.
17881
+ */
17882
+ headerSoftClass() {
17883
+ return this.modeColor.classes().softSolid;
17884
+ }
17605
17885
  /**
17606
17886
  * Body row classes — row marker for hover styles, plus hide cell borders on
17607
17887
  * the last / expanded row.
@@ -17612,7 +17892,7 @@ class TableComponent {
17612
17892
  bodyRowClass(row, index) {
17613
17893
  if (this.isExpandable() && this.isRowExpanded(row, index)) {
17614
17894
  // Only the bottom edge — keep the top divider so the row still
17615
- // separates from the row above.
17895
+ // separates from the row above. Detail panel owns the separator.
17616
17896
  return 'africanies-table-row group [&>td]:border-b-0';
17617
17897
  }
17618
17898
  return 'africanies-table-row group last:[&>td]:border-b-0';
@@ -17638,21 +17918,27 @@ class TableComponent {
17638
17918
  * @returns Header class list.
17639
17919
  */
17640
17920
  expandHeaderClass() {
17641
- return ('w-10 border-b border-border px-2 py-3.5 dark:border-white/10 ' +
17921
+ return ('w-10 border-b-[1.5px] border-border px-2 py-4 dark:border-white/10 ' +
17922
+ this.headerSoftClass() +
17923
+ ' ' +
17642
17924
  this.stickyPinClass('left', 'head'));
17643
17925
  }
17644
17926
  /**
17645
17927
  * Body classes for the expand/collapse trigger column (pinned left).
17646
- * Omits `border-b` like other sticky cells so the opaque fill does not
17647
- * double-paint the row divider.
17928
+ * Uses a slightly thicker bottom border than scrolling cells so the
17929
+ * sticky fill still reads a clear divider (no top-shadow fallback).
17648
17930
  * @param index - Index within {@link rows}.
17649
17931
  * @returns Body cell class list.
17650
17932
  */
17651
17933
  expandBodyClass(index) {
17652
- const prev = index > 0 ? this.rowList()[index - 1] : undefined;
17653
- const afterExpanded = prev !== undefined && this.isRowExpanded(prev, index - 1);
17654
- return ('w-10 px-2 py-3.5 align-middle ' +
17655
- this.stickyPinClass('left', 'body', index, afterExpanded));
17934
+ const row = this.rowList()[index];
17935
+ const expanded = row !== undefined && this.isRowExpanded(row, index);
17936
+ const border = expanded
17937
+ ? ''
17938
+ : 'border-b-[1.5px] border-border dark:border-white/10 ';
17939
+ return ('w-10 px-2 py-4 align-middle ' +
17940
+ border +
17941
+ this.stickyPinClass('left', 'body'));
17656
17942
  }
17657
17943
  /**
17658
17944
  * Header cell classes, including sticky pin when set.
@@ -17660,69 +17946,71 @@ class TableComponent {
17660
17946
  * @returns Header class list.
17661
17947
  */
17662
17948
  headerCellClass(col) {
17663
- return ('border-b border-border whitespace-normal wrap-break-word px-3 py-3.5 font-medium text-neutral-600 dark:border-white/10 dark:text-neutral-400 ' +
17949
+ const sticky = this.stickyEdge(col);
17950
+ const border = sticky
17951
+ ? 'border-b-[1.5px] '
17952
+ : 'border-b ';
17953
+ return (border +
17954
+ 'border-border whitespace-normal wrap-break-word px-[1.125rem] py-4 font-medium text-neutral-600 dark:border-white/10 dark:text-neutral-400 ' +
17955
+ this.headerSoftClass() +
17956
+ ' ' +
17664
17957
  this.stickySurfaceClass(col, 'head'));
17665
17958
  }
17666
17959
  /**
17667
17960
  * Body cell classes, including sticky pin when set.
17668
- * Sticky cells omit `border-b`: their opaque fill sits in a higher stacking
17669
- * context, so a bottom border plus the next row's top shadow paint on the
17670
- * same pixel and read brighter (especially in dark mode).
17961
+ * Sticky expand/actions columns use a 1.5px bottom border; scrolling cells
17962
+ * stay at 1px. Expanded rows drop the bottom border (see {@link bodyRowClass}).
17671
17963
  * @param col - Column definition.
17672
17964
  * @param index - Index within {@link rows}.
17673
17965
  * @returns Body cell class list.
17674
17966
  */
17675
17967
  bodyCellClass(col, index) {
17676
- const rowLine = this.stickyEdge(col)
17968
+ const row = this.rowList()[index];
17969
+ const expanded = row !== undefined && this.isRowExpanded(row, index);
17970
+ const sticky = this.stickyEdge(col);
17971
+ const rowLine = expanded
17677
17972
  ? ''
17678
- : 'border-b border-border dark:border-white/10 ';
17679
- const prev = index > 0 ? this.rowList()[index - 1] : undefined;
17680
- const afterExpanded = prev !== undefined && this.isRowExpanded(prev, index - 1);
17973
+ : sticky
17974
+ ? 'border-b-[1.5px] border-border dark:border-white/10 '
17975
+ : 'border-b border-border dark:border-white/10 ';
17681
17976
  const wrap = col.key === 'actions'
17682
17977
  ? 'whitespace-nowrap '
17683
17978
  : 'whitespace-normal wrap-break-word ';
17684
17979
  return (rowLine +
17685
- 'px-3 py-3.5 align-middle ' +
17980
+ 'px-[1.125rem] py-4 align-middle ' +
17686
17981
  wrap +
17687
- this.stickySurfaceClass(col, 'body', index, afterExpanded));
17982
+ this.stickySurfaceClass(col, 'body'));
17688
17983
  }
17689
17984
  /**
17690
17985
  * Sticky pin utilities for a known edge (expand column or data column).
17691
17986
  * @param edge - Left or right pin.
17692
17987
  * @param surface - Header vs body fill tokens.
17693
- * @param index - Body row index; unused for the header.
17694
- * @param afterExpanded - Previous row is expanded — skip the top shadow
17695
- * divider so the sticky column stays flush under the detail panel.
17696
17988
  * @returns Sticky utilities.
17697
17989
  */
17698
- stickyPinClass(edge, surface, index = 0, afterExpanded = false) {
17990
+ stickyPinClass(edge, surface) {
17699
17991
  // Expand (left) sits above scrolling cells; actions (right) match.
17700
17992
  // Header needs a higher z so it stays above sticky body cells.
17701
17993
  const side = edge === 'right' ? 'sticky right-0 z-[1]' : 'sticky left-0 z-[1]';
17702
17994
  if (surface === 'head') {
17703
- return `${side} z-[2] bg-background-welcome dark:bg-ink-950`;
17995
+ // Fill comes from {@link headerSoftClass} on the cell — do not re-tint.
17996
+ return `${side} z-[2]`;
17704
17997
  }
17705
- const rowDivider = !afterExpanded && index > 0
17706
- ? 'shadow-[0_-1px_0_0_#c9d5e1] dark:shadow-[0_-1px_0_0_rgba(255,255,255,0.1)]'
17707
- : '';
17708
17998
  const fill = 'bg-white dark:bg-ink';
17709
- return `${side} ${fill} ${rowDivider}`;
17999
+ return `${side} ${fill}`;
17710
18000
  }
17711
18001
  /**
17712
18002
  * Sticky pin plus an opaque fill matching the table surface, so scrolled
17713
18003
  * cells do not show through.
17714
18004
  * @param col - Column definition.
17715
18005
  * @param surface - Header vs body fill tokens.
17716
- * @param index - Body row index; unused for the header.
17717
- * @param afterExpanded - Previous row is expanded — skip the top shadow.
17718
18006
  * @returns Sticky utilities, or empty when the column scrolls.
17719
18007
  */
17720
- stickySurfaceClass(col, surface, index = 0, afterExpanded = false) {
18008
+ stickySurfaceClass(col, surface) {
17721
18009
  const edge = this.stickyEdge(col);
17722
18010
  if (!edge) {
17723
18011
  return '';
17724
18012
  }
17725
- return this.stickyPinClass(edge, surface, index, afterExpanded);
18013
+ return this.stickyPinClass(edge, surface);
17726
18014
  }
17727
18015
  /**
17728
18016
  * Stable id for a row — used for expand/collapse state.
@@ -17896,9 +18184,7 @@ class TableComponent {
17896
18184
  <table
17897
18185
  class="w-max min-w-full table-auto border-separate border-spacing-0 bg-inherit text-left text-body text-ink dark:text-white"
17898
18186
  >
17899
- <thead
17900
- class="border-b border-border bg-background-welcome dark:border-white/10 dark:bg-ink-950"
17901
- >
18187
+ <thead [class]="headerRowClass()">
17902
18188
  <tr>
17903
18189
  @if (isExpandable()) {
17904
18190
  <th
@@ -17962,14 +18248,14 @@ class TableComponent {
17962
18248
  @switch (bodyKind()) {
17963
18249
  @case ('loading') {
17964
18250
  <tr>
17965
- <td class="px-3 py-6" [attr.colspan]="colSpan()">
18251
+ <td class="px-[1.125rem] py-6" [attr.colspan]="colSpan()">
17966
18252
  <africanies-loading-state [message]="loadingLabel()" />
17967
18253
  </td>
17968
18254
  </tr>
17969
18255
  }
17970
18256
  @case ('error') {
17971
18257
  <tr>
17972
- <td class="px-3 py-6" [attr.colspan]="colSpan()">
18258
+ <td class="px-[1.125rem] py-6" [attr.colspan]="colSpan()">
17973
18259
  <africanies-error-state
17974
18260
  [message]="errorMessage()"
17975
18261
  [refreshing]="refreshing()"
@@ -17980,7 +18266,7 @@ class TableComponent {
17980
18266
  }
17981
18267
  @case ('empty') {
17982
18268
  <tr>
17983
- <td class="px-3 py-6" [attr.colspan]="colSpan()">
18269
+ <td class="px-[1.125rem] py-6" [attr.colspan]="colSpan()">
17984
18270
  <africanies-empty-state
17985
18271
  [message]="emptyMessage()"
17986
18272
  [refreshing]="refreshing()"
@@ -18048,7 +18334,7 @@ class TableComponent {
18048
18334
  class="min-h-0 overflow-hidden border-t border-border/70 bg-neutral-50 dark:border-white/10 dark:bg-white/[0.05]"
18049
18335
  >
18050
18336
  <dl
18051
- class="m-0 grid gap-x-6 gap-y-3 px-3 py-3 transition-opacity duration-200 ease-out motion-reduce:transition-none sm:grid-cols-2 lg:grid-cols-3"
18337
+ class="m-0 grid gap-x-6 gap-y-3 px-[1.125rem] py-4 transition-opacity duration-200 ease-out motion-reduce:transition-none sm:grid-cols-2 lg:grid-cols-3"
18052
18338
  [class.opacity-0]="!isRowExpanded(row, i)"
18053
18339
  [class.opacity-100]="isRowExpanded(row, i)"
18054
18340
  >
@@ -18190,9 +18476,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
18190
18476
  <table
18191
18477
  class="w-max min-w-full table-auto border-separate border-spacing-0 bg-inherit text-left text-body text-ink dark:text-white"
18192
18478
  >
18193
- <thead
18194
- class="border-b border-border bg-background-welcome dark:border-white/10 dark:bg-ink-950"
18195
- >
18479
+ <thead [class]="headerRowClass()">
18196
18480
  <tr>
18197
18481
  @if (isExpandable()) {
18198
18482
  <th
@@ -18256,14 +18540,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
18256
18540
  @switch (bodyKind()) {
18257
18541
  @case ('loading') {
18258
18542
  <tr>
18259
- <td class="px-3 py-6" [attr.colspan]="colSpan()">
18543
+ <td class="px-[1.125rem] py-6" [attr.colspan]="colSpan()">
18260
18544
  <africanies-loading-state [message]="loadingLabel()" />
18261
18545
  </td>
18262
18546
  </tr>
18263
18547
  }
18264
18548
  @case ('error') {
18265
18549
  <tr>
18266
- <td class="px-3 py-6" [attr.colspan]="colSpan()">
18550
+ <td class="px-[1.125rem] py-6" [attr.colspan]="colSpan()">
18267
18551
  <africanies-error-state
18268
18552
  [message]="errorMessage()"
18269
18553
  [refreshing]="refreshing()"
@@ -18274,7 +18558,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
18274
18558
  }
18275
18559
  @case ('empty') {
18276
18560
  <tr>
18277
- <td class="px-3 py-6" [attr.colspan]="colSpan()">
18561
+ <td class="px-[1.125rem] py-6" [attr.colspan]="colSpan()">
18278
18562
  <africanies-empty-state
18279
18563
  [message]="emptyMessage()"
18280
18564
  [refreshing]="refreshing()"
@@ -18342,7 +18626,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
18342
18626
  class="min-h-0 overflow-hidden border-t border-border/70 bg-neutral-50 dark:border-white/10 dark:bg-white/[0.05]"
18343
18627
  >
18344
18628
  <dl
18345
- class="m-0 grid gap-x-6 gap-y-3 px-3 py-3 transition-opacity duration-200 ease-out motion-reduce:transition-none sm:grid-cols-2 lg:grid-cols-3"
18629
+ class="m-0 grid gap-x-6 gap-y-3 px-[1.125rem] py-4 transition-opacity duration-200 ease-out motion-reduce:transition-none sm:grid-cols-2 lg:grid-cols-3"
18346
18630
  [class.opacity-0]="!isRowExpanded(row, i)"
18347
18631
  [class.opacity-100]="isRowExpanded(row, i)"
18348
18632
  >
@@ -18763,6 +19047,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
18763
19047
  }] });
18764
19048
 
18765
19049
  const FEEDBACK = [
19050
+ AccordionComponent,
18766
19051
  LoadingStateComponent,
18767
19052
  ErrorStateComponent,
18768
19053
  ErrorIndicatorComponent,
@@ -18772,7 +19057,7 @@ const FEEDBACK = [
18772
19057
  ChipComponent,
18773
19058
  ];
18774
19059
  /**
18775
- * Async feedback states, inline alert, and status chips.
19060
+ * Async feedback states, accordion panels, inline alert, and status chips.
18776
19061
  *
18777
19062
  * Toast stays out of this module — register {@link provideAfricaniesToasts} instead.
18778
19063
  *
@@ -18786,13 +19071,15 @@ const FEEDBACK = [
18786
19071
  */
18787
19072
  class AfricaniesFeedbackModule {
18788
19073
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AfricaniesFeedbackModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
18789
- static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "22.0.8", ngImport: i0, type: AfricaniesFeedbackModule, imports: [LoadingStateComponent,
19074
+ static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "22.0.8", ngImport: i0, type: AfricaniesFeedbackModule, imports: [AccordionComponent,
19075
+ LoadingStateComponent,
18790
19076
  ErrorStateComponent,
18791
19077
  ErrorIndicatorComponent,
18792
19078
  EmptyStateComponent,
18793
19079
  AsyncStateComponent,
18794
19080
  AlertComponent,
18795
- ChipComponent], exports: [LoadingStateComponent,
19081
+ ChipComponent], exports: [AccordionComponent,
19082
+ LoadingStateComponent,
18796
19083
  ErrorStateComponent,
18797
19084
  ErrorIndicatorComponent,
18798
19085
  EmptyStateComponent,
@@ -19084,5 +19371,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
19084
19371
  * Generated bundle index. Do not edit.
19085
19372
  */
19086
19373
 
19087
- export { AFRICANIES_BRAND_LOGO_MINI_URL, AFRICANIES_BRAND_LOGO_URL, ActionMenuComponent, ActionMenuTriggerDirective, AddressInputComponent, AfricaniesActionsModule, AfricaniesFeedbackModule, AfricaniesFormsModule, AfricaniesInfoPopoverModule, AfricaniesNavigationModule, AfricaniesOverlayRef, AfricaniesStepperModule, AfricaniesTableModule, AfricaniesTooltipModule, AlertComponent, AppShellComponent, AppShellContentHeaderComponent, AppShellHeaderComponent, AppShellHeaderEndDirective, AppShellHeaderSlotDirective, AppShellHeaderStartDirective, AsyncStateComponent, AvatarComponent, AvatarMenuComponent, BrandLogoComponent, BreadcrumbComponent, ButtonComponent, CarrierLogoComponent, CellDefDirective, CheckboxComponent, ChipComponent, ConfirmDialogComponent, ConfirmService, ContentStackComponent, CopyButtonComponent, DatePickerComponent, DrawerService, EmptyStateComponent, ErrorIndicatorComponent, ErrorStateComponent, FileUploadComponent, FilterDrawerPanel, FilterDrawerService, FilterQueryService, GOOGLE_PLACES_CONFIG, GooglePlacesService, HeaderCellDefDirective, ImageComponent, InfoPopoverComponent, InfoPopoverContentDirective, InfoPopoverTriggerDirective, LoadingStateComponent, MODAL_SIZE_PANEL_CLASS, ModalService, NotificationDrawerPanel, NotificationDrawerService, NumberInputComponent, OVERLAY_DATA, OtpInputComponent, OverlayFooterDirective, OverlayFrameComponent, OverlayHeaderDirective, PageHeaderComponent, PaginationComponent, RadioComponent, RowDetailDefDirective, SearchComboboxComponent, SegmentComponent, SelectComponent, ShippingModeSwitchComponent, SideNavComponent, StepDefDirective, StepperComponent, TOAST_DURATION_MS, TOAST_ICONS, TabDefDirective, TableComponent, TabsComponent, TextInputComponent, TextareaComponent, ToastService, ToggleComponent, TooltipComponent, TooltipTriggerDirective, acceptLabels, buildBreadcrumbsFromSideNav, deliveryVendorOptionsForStoredValue, deliveryVendorSelectOptions, deliveryVendorSelected, fileExtensionLabel, fileMatchesAccept, headerGreetingFirstName, headerGreetingPeriod, isCatalogRootRoute, isNavItemActive, isNestedChildRoute, navItemUrlTree, normalizeCarrierLogoSlug, normalizeNavPath, pickHeaderGreeting, provideAfricaniesToasts, provideAfricaniesUiOverlays, provideGooglePlaces, resolveCatalogRootLink, resolveContentBackTarget, resolveHeaderBackTarget, resolveParentPathFromRootSnapshot, toastFingerprint };
19374
+ export { AFRICANIES_BRAND_LOGO_MINI_URL, AFRICANIES_BRAND_LOGO_URL, AccordionComponent, ActionMenuComponent, ActionMenuTriggerDirective, AddressInputComponent, AfricaniesActionsModule, AfricaniesFeedbackModule, AfricaniesFormsModule, AfricaniesInfoPopoverModule, AfricaniesNavigationModule, AfricaniesOverlayRef, AfricaniesStepperModule, AfricaniesTableModule, AfricaniesTooltipModule, AlertComponent, AppShellComponent, AppShellContentHeaderComponent, AppShellHeaderComponent, AppShellHeaderEndDirective, AppShellHeaderSlotDirective, AppShellHeaderStartDirective, AsyncStateComponent, AvatarComponent, AvatarMenuComponent, BrandLogoComponent, BreadcrumbComponent, ButtonComponent, CarrierLogoComponent, CellDefDirective, CheckboxComponent, ChipComponent, ConfirmDialogComponent, ConfirmService, ContentStackComponent, CopyButtonComponent, DatePickerComponent, DrawerService, EmptyStateComponent, ErrorIndicatorComponent, ErrorStateComponent, FileUploadComponent, FilterDrawerPanel, FilterDrawerService, FilterQueryService, GOOGLE_PLACES_CONFIG, GooglePlacesService, HeaderCellDefDirective, ImageComponent, InfoPopoverComponent, InfoPopoverContentDirective, InfoPopoverTriggerDirective, LoadingStateComponent, MODAL_SIZE_PANEL_CLASS, ModalService, NotificationDrawerPanel, NotificationDrawerService, NumberInputComponent, OVERLAY_DATA, OtpInputComponent, OverlayFooterDirective, OverlayFrameComponent, OverlayHeaderDirective, PageHeaderComponent, PaginationComponent, RadioComponent, RowDetailDefDirective, SearchComboboxComponent, SegmentComponent, SelectComponent, ShippingModeSwitchComponent, SideNavComponent, StepDefDirective, StepperComponent, TOAST_DURATION_MS, TOAST_ICONS, TabDefDirective, TableComponent, TabsComponent, TextInputComponent, TextareaComponent, ToastService, ToggleComponent, TooltipComponent, TooltipTriggerDirective, acceptLabels, buildBreadcrumbsFromSideNav, deliveryVendorOptionsForStoredValue, deliveryVendorSelectOptions, deliveryVendorSelected, fileExtensionLabel, fileMatchesAccept, headerGreetingFirstName, headerGreetingPeriod, isCatalogRootRoute, isNavItemActive, isNestedChildRoute, navItemUrlTree, normalizeCarrierLogoSlug, normalizeNavPath, pickHeaderGreeting, provideAfricaniesToasts, provideAfricaniesUiOverlays, provideGooglePlaces, resolveCatalogRootLink, resolveContentBackTarget, resolveHeaderBackTarget, resolveParentPathFromRootSnapshot, toastFingerprint };
19088
19375
  //# sourceMappingURL=africanies-africanies-ui.mjs.map