@africanies/angular-web-sdk 0.1.7 → 0.1.8

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 (133) hide show
  1. package/.nx/cache/{4082520855419352840 → 15302120112746851896}/dist/libs/africanies-theme/fesm2022/africanies-africanies-theme.mjs +30 -8
  2. package/.nx/cache/15302120112746851896/dist/libs/africanies-theme/fesm2022/africanies-africanies-theme.mjs.map +1 -0
  3. package/.nx/cache/{4082520855419352840 → 15302120112746851896}/dist/libs/africanies-theme/tailwind-preset.cjs +89 -12
  4. package/.nx/cache/{4082520855419352840 → 15302120112746851896}/dist/libs/africanies-theme/types/africanies-africanies-theme.d.ts +14 -4
  5. package/.nx/cache/{17491371155400585077 → 18393832731522001121}/dist/libs/africanies-core/fesm2022/africanies-africanies-core.mjs +139 -51
  6. package/.nx/cache/18393832731522001121/dist/libs/africanies-core/fesm2022/africanies-africanies-core.mjs.map +1 -0
  7. package/.nx/cache/{17491371155400585077 → 18393832731522001121}/dist/libs/africanies-core/types/africanies-africanies-core.d.ts +14 -11
  8. package/.nx/cache/5151121439688073678/dist/libs/africanies-icons/README.md +69 -0
  9. package/.nx/cache/5151121439688073678/dist/libs/africanies-icons/assets/icons.sprite.svg +1851 -0
  10. package/.nx/cache/5151121439688073678/dist/libs/africanies-icons/fesm2022/africanies-africanies-icons.mjs +833 -0
  11. package/.nx/cache/5151121439688073678/dist/libs/africanies-icons/fesm2022/africanies-africanies-icons.mjs.map +1 -0
  12. package/.nx/cache/5151121439688073678/dist/libs/africanies-icons/package.json +30 -0
  13. package/.nx/cache/5151121439688073678/dist/libs/africanies-icons/types/africanies-africanies-icons.d.ts +108 -0
  14. package/.nx/cache/877026836685850193/dist/libs/africanies-models/README.md +60 -0
  15. package/.nx/cache/877026836685850193/dist/libs/africanies-models/fesm2022/africanies-africanies-models.mjs +613 -0
  16. package/.nx/cache/877026836685850193/dist/libs/africanies-models/fesm2022/africanies-africanies-models.mjs.map +1 -0
  17. package/.nx/cache/877026836685850193/dist/libs/africanies-models/package.json +23 -0
  18. package/.nx/cache/877026836685850193/dist/libs/africanies-models/types/africanies-africanies-models.d.ts +1452 -0
  19. package/.nx/cache/{17499961385238663835 → 9406544675747598148}/dist/libs/africanies-ui/fesm2022/africanies-africanies-ui.mjs +765 -615
  20. package/.nx/cache/9406544675747598148/dist/libs/africanies-ui/fesm2022/africanies-africanies-ui.mjs.map +1 -0
  21. package/.nx/cache/{17499961385238663835 → 9406544675747598148}/dist/libs/africanies-ui/types/africanies-africanies-ui.d.ts +149 -116
  22. package/.nx/cache/run.json +40 -40
  23. package/.nx/cache/terminalOutputs/{7126777490381568487 → 15149466893522345489} +10 -5
  24. package/.nx/cache/terminalOutputs/{4082520855419352840 → 15302120112746851896} +1 -1
  25. package/.nx/cache/terminalOutputs/{8648260256613557249 → 15835338512221847842} +18 -8
  26. package/.nx/cache/terminalOutputs/{9408529484792607601 → 17960163310445607219} +1 -1
  27. package/.nx/cache/terminalOutputs/{17491371155400585077 → 18393832731522001121} +2 -2
  28. package/.nx/cache/terminalOutputs/{3314955264390318442 → 5151121439688073678} +6 -6
  29. package/.nx/cache/terminalOutputs/7462873189468732296 +17 -0
  30. package/.nx/cache/terminalOutputs/8032148447904822353 +184 -182
  31. package/.nx/cache/terminalOutputs/{12276756491762927325 → 877026836685850193} +7 -7
  32. package/.nx/cache/terminalOutputs/9406544675747598148 +21 -0
  33. package/.nx/workspace-data/0091ABA9-5C90-580D-953C-8C94E763ADB5-v3.db +0 -0
  34. package/.nx/workspace-data/0091ABA9-5C90-580D-953C-8C94E763ADB5-v3.db-shm +0 -0
  35. package/.nx/workspace-data/0091ABA9-5C90-580D-953C-8C94E763ADB5-v3.db-wal +0 -0
  36. package/.nx/workspace-data/d/daemon.log +2353 -0
  37. package/.nx/workspace-data/d/server-process.json +2 -2
  38. package/.nx/workspace-data/file-map.json +1802 -1736
  39. package/.nx/workspace-data/nx_files.nxt +0 -0
  40. package/.nx/workspace-data/project-graph.json +7 -2
  41. package/apps/playground/src/app/pages/tokens-page.ts +17 -13
  42. package/apps/playground/src/app/snippets/filters.snippets.ts +10 -0
  43. package/dist/libs/africanies-icons/assets/icons.sprite.svg +7 -0
  44. package/dist/libs/africanies-icons/fesm2022/africanies-africanies-icons.mjs +1 -0
  45. package/dist/libs/africanies-icons/fesm2022/africanies-africanies-icons.mjs.map +1 -1
  46. package/dist/libs/africanies-icons/types/africanies-africanies-icons.d.ts +2 -2
  47. package/dist/libs/africanies-models/fesm2022/africanies-africanies-models.mjs +22 -8
  48. package/dist/libs/africanies-models/fesm2022/africanies-africanies-models.mjs.map +1 -1
  49. package/dist/libs/africanies-theme/fesm2022/africanies-africanies-theme.mjs +22 -10
  50. package/dist/libs/africanies-theme/fesm2022/africanies-africanies-theme.mjs.map +1 -1
  51. package/dist/libs/africanies-theme/tailwind-preset.cjs +84 -16
  52. package/dist/libs/africanies-theme/types/africanies-africanies-theme.d.ts +4 -2
  53. package/dist/libs/africanies-ui/fesm2022/africanies-africanies-ui.mjs +555 -425
  54. package/dist/libs/africanies-ui/fesm2022/africanies-africanies-ui.mjs.map +1 -1
  55. package/dist/libs/africanies-ui/types/africanies-africanies-ui.d.ts +140 -110
  56. package/libs/africanies-icons/src/assets/icons.sprite.svg +7 -0
  57. package/libs/africanies-icons/src/lib/icon-name.ts +1 -0
  58. package/libs/africanies-models/src/lib/filters/configs/seed-configs.ts +22 -8
  59. package/libs/africanies-theme/src/lib/mode-color.safelist.ts +12 -0
  60. package/libs/africanies-theme/src/lib/mode-color.service.spec.ts +55 -0
  61. package/libs/africanies-theme/src/lib/mode-color.service.ts +11 -11
  62. package/libs/africanies-theme/tailwind-preset.cjs +84 -16
  63. package/libs/africanies-ui/src/lib/action-menu/action-menu.component.ts +3 -3
  64. package/libs/africanies-ui/src/lib/alert/alert.component.ts +4 -4
  65. package/libs/africanies-ui/src/lib/avatar/avatar-menu.component.ts +2 -2
  66. package/libs/africanies-ui/src/lib/button/button.component.spec.ts +7 -7
  67. package/libs/africanies-ui/src/lib/button/button.component.ts +5 -5
  68. package/libs/africanies-ui/src/lib/chip/chip.component.ts +4 -4
  69. package/libs/africanies-ui/src/lib/content-stack/content-stack.component.ts +1 -1
  70. package/libs/africanies-ui/src/lib/feedback/error-indicator.component.ts +3 -3
  71. package/libs/africanies-ui/src/lib/feedback/error-state.component.ts +2 -2
  72. package/libs/africanies-ui/src/lib/filters/filter-drawer.panel.ts +44 -27
  73. package/libs/africanies-ui/src/lib/forms/checkbox/checkbox.component.ts +2 -1
  74. package/libs/africanies-ui/src/lib/forms/file-upload/file-preview.dialog.ts +1 -1
  75. package/libs/africanies-ui/src/lib/forms/file-upload/file-upload.component.ts +1 -1
  76. package/libs/africanies-ui/src/lib/forms/form-field.classes.ts +36 -6
  77. package/libs/africanies-ui/src/lib/forms/otp-input/otp-input.component.ts +2 -1
  78. package/libs/africanies-ui/src/lib/forms/radio/radio.component.ts +2 -1
  79. package/libs/africanies-ui/src/lib/forms/select/select.component.ts +1 -1
  80. package/libs/africanies-ui/src/lib/forms/toggle/toggle.component.ts +1 -1
  81. package/libs/africanies-ui/src/lib/image/image.component.ts +1 -1
  82. package/libs/africanies-ui/src/lib/info-popover/info-popover.component.ts +2 -2
  83. package/libs/africanies-ui/src/lib/layout/app-shell-content-header.component.ts +1 -1
  84. package/libs/africanies-ui/src/lib/layout/app-shell-header.component.ts +5 -5
  85. package/libs/africanies-ui/src/lib/layout/app-shell.component.html +2 -2
  86. package/libs/africanies-ui/src/lib/layout/app-shell.component.ts +3 -3
  87. package/libs/africanies-ui/src/lib/navigation/shipping-mode-switch/shipping-mode-switch.component.ts +6 -6
  88. package/libs/africanies-ui/src/lib/navigation/side-nav/africanies-side-nav.component.html +21 -13
  89. package/libs/africanies-ui/src/lib/navigation/side-nav/africanies-side-nav.component.ts +13 -7
  90. package/libs/africanies-ui/src/lib/notifications/notification-drawer.panel.ts +6 -6
  91. package/libs/africanies-ui/src/lib/overlay/confirm-dialog.component.ts +2 -2
  92. package/libs/africanies-ui/src/lib/overlay/drawer.service.ts +2 -2
  93. package/libs/africanies-ui/src/lib/overlay/modal.service.ts +3 -3
  94. package/libs/africanies-ui/src/lib/overlay/overlay-frame.component.ts +1 -1
  95. package/libs/africanies-ui/src/lib/pagination/pagination.component.ts +1 -1
  96. package/libs/africanies-ui/src/lib/stepper/stepper.component.ts +7 -7
  97. package/libs/africanies-ui/src/lib/table/table-column.ts +9 -0
  98. package/libs/africanies-ui/src/lib/table/table.component.spec.ts +99 -0
  99. package/libs/africanies-ui/src/lib/table/table.component.ts +72 -30
  100. package/libs/africanies-ui/src/lib/toast/toast-item.component.ts +6 -6
  101. package/package.json +1 -1
  102. package/svg/hand-coins.svg +9 -0
  103. package/.nx/cache/12276756491762927325/dist/libs/africanies-theme/fesm2022/africanies-africanies-theme.mjs +0 -215
  104. package/.nx/cache/12276756491762927325/dist/libs/africanies-theme/fesm2022/africanies-africanies-theme.mjs.map +0 -1
  105. package/.nx/cache/12276756491762927325/dist/libs/africanies-theme/tailwind-preset.cjs +0 -245
  106. package/.nx/cache/12276756491762927325/dist/libs/africanies-theme/types/africanies-africanies-theme.d.ts +0 -157
  107. package/.nx/cache/17491371155400585077/dist/libs/africanies-core/fesm2022/africanies-africanies-core.mjs.map +0 -1
  108. package/.nx/cache/17499961385238663835/dist/libs/africanies-ui/fesm2022/africanies-africanies-ui.mjs.map +0 -1
  109. package/.nx/cache/3314955264390318442/dist/libs/africanies-ui/README.md +0 -68
  110. package/.nx/cache/3314955264390318442/dist/libs/africanies-ui/assets/brand/africanies-logo-mini.png +0 -0
  111. package/.nx/cache/3314955264390318442/dist/libs/africanies-ui/assets/brand/africanies-logo.png +0 -0
  112. package/.nx/cache/3314955264390318442/dist/libs/africanies-ui/assets/brand/africanies-logo.svg +0 -5
  113. package/.nx/cache/3314955264390318442/dist/libs/africanies-ui/assets/carriers/dhl.svg +0 -7
  114. package/.nx/cache/3314955264390318442/dist/libs/africanies-ui/fesm2022/africanies-africanies-ui.mjs +0 -19291
  115. package/.nx/cache/3314955264390318442/dist/libs/africanies-ui/fesm2022/africanies-africanies-ui.mjs.map +0 -1
  116. package/.nx/cache/3314955264390318442/dist/libs/africanies-ui/package.json +0 -35
  117. package/.nx/cache/3314955264390318442/dist/libs/africanies-ui/types/africanies-africanies-ui.d.ts +0 -5483
  118. package/.nx/cache/4082520855419352840/dist/libs/africanies-theme/README.md +0 -46
  119. package/.nx/cache/4082520855419352840/dist/libs/africanies-theme/fesm2022/africanies-africanies-theme.mjs.map +0 -1
  120. package/.nx/cache/4082520855419352840/dist/libs/africanies-theme/package.json +0 -35
  121. package/.nx/cache/terminalOutputs/17499961385238663835 +0 -21
  122. package/.nx/cache/terminalOutputs/3017748574492080228 +0 -28
  123. /package/.nx/cache/{12276756491762927325 → 15302120112746851896}/dist/libs/africanies-theme/README.md +0 -0
  124. /package/.nx/cache/{12276756491762927325 → 15302120112746851896}/dist/libs/africanies-theme/package.json +0 -0
  125. /package/.nx/cache/{17491371155400585077 → 18393832731522001121}/dist/libs/africanies-core/README.md +0 -0
  126. /package/.nx/cache/{17491371155400585077 → 18393832731522001121}/dist/libs/africanies-core/package.json +0 -0
  127. /package/.nx/cache/{17499961385238663835 → 9406544675747598148}/dist/libs/africanies-ui/README.md +0 -0
  128. /package/.nx/cache/{17499961385238663835 → 9406544675747598148}/dist/libs/africanies-ui/assets/brand/africanies-logo-mini.png +0 -0
  129. /package/.nx/cache/{17499961385238663835 → 9406544675747598148}/dist/libs/africanies-ui/assets/brand/africanies-logo.png +0 -0
  130. /package/.nx/cache/{17499961385238663835 → 9406544675747598148}/dist/libs/africanies-ui/assets/brand/africanies-logo.svg +0 -0
  131. /package/.nx/cache/{17499961385238663835 → 9406544675747598148}/dist/libs/africanies-ui/assets/carriers/dhl.svg +0 -0
  132. /package/.nx/cache/{17499961385238663835 → 9406544675747598148}/dist/libs/africanies-ui/package.json +0 -0
  133. /package/.nx/cache/terminalOutputs/{16279119293212733518 → 14005735098959303198} +0 -0
@@ -15,36 +15,54 @@ import { STORAGE_TOKEN, AFRICANIES_THEME_KEY } from '@africanies/africanies-stor
15
15
  * Do not rename these strings without updating ModeColorService and THEME.md.
16
16
  *
17
17
  * SFN (export / green):
18
+ * text-export-strong bg-export-strong hover:bg-export-hover border-export-strong
18
19
  * text-export bg-export bg-export-subtle bg-export-light border-export
19
20
  * hover:bg-export-light hover:bg-export-subtle dark:bg-export/15 dark:hover:bg-export/15
20
- * dark:bg-[color-mix(in_srgb,#1cbd5d_15%,#212529)]
21
+ * dark:bg-[color-mix(in_srgb,#1cbd5d_15%,#212529)] dark:bg-export dark:text-export dark:border-export
21
22
  *
22
23
  * STN (import / orange):
24
+ * text-import-strong bg-import-strong hover:bg-import-hover border-import-strong
23
25
  * text-import bg-import bg-import-subtle bg-import-light border-import
24
26
  * hover:bg-import-light hover:bg-import-subtle dark:bg-import/15 dark:hover:bg-import/15
25
- * dark:bg-[color-mix(in_srgb,#f08829_15%,#212529)]
27
+ * dark:bg-[color-mix(in_srgb,#f08829_15%,#212529)] dark:bg-import dark:text-import dark:border-import
26
28
  */
27
29
  const MODE_COLOR_SAFELIST = [
28
30
  'text-export',
31
+ 'text-export-strong',
29
32
  'bg-export',
33
+ 'bg-export-strong',
30
34
  'bg-export-subtle',
31
35
  'bg-export-light',
32
36
  'border-export',
37
+ 'border-export-strong',
38
+ 'hover:bg-export-hover',
33
39
  'hover:bg-export-light',
34
40
  'hover:bg-export-subtle',
35
41
  'dark:bg-export/15',
36
42
  'dark:hover:bg-export/15',
43
+ 'dark:hover:bg-export-light',
37
44
  'dark:bg-[color-mix(in_srgb,#1cbd5d_15%,#212529)]',
45
+ 'dark:bg-export',
46
+ 'dark:text-export',
47
+ 'dark:border-export',
38
48
  'text-import',
49
+ 'text-import-strong',
39
50
  'bg-import',
51
+ 'bg-import-strong',
40
52
  'bg-import-subtle',
41
53
  'bg-import-light',
42
54
  'border-import',
55
+ 'border-import-strong',
56
+ 'hover:bg-import-hover',
43
57
  'hover:bg-import-light',
44
58
  'hover:bg-import-subtle',
45
59
  'dark:bg-import/15',
46
60
  'dark:hover:bg-import/15',
61
+ 'dark:hover:bg-import-light',
47
62
  'dark:bg-[color-mix(in_srgb,#f08829_15%,#212529)]',
63
+ 'dark:bg-import',
64
+ 'dark:text-import',
65
+ 'dark:border-import',
48
66
  ];
49
67
 
50
68
  /**
@@ -73,27 +91,31 @@ class ModeColorService {
73
91
  // Literal strings required for Tailwind content detection — do not interpolate.
74
92
  if (this.shippingMode.mode() === 'sfn') {
75
93
  return {
76
- text: 'text-export',
94
+ text: 'text-export-strong dark:text-export',
77
95
  bg: 'bg-export',
78
96
  bgSubtle: 'bg-export-subtle',
79
97
  border: 'border-export',
80
- primary: 'bg-export text-white border-transparent hover:bg-export-light',
81
- ghostPrimary: 'bg-transparent text-export border-transparent hover:bg-export-subtle dark:hover:bg-export/15',
98
+ primary: 'bg-export-strong text-white border-transparent hover:bg-export-hover dark:bg-export dark:hover:bg-export-light',
99
+ ghostPrimary: 'bg-transparent text-export-strong border-transparent hover:bg-export-subtle dark:text-export dark:hover:bg-export/15',
82
100
  soft: 'bg-export-subtle dark:bg-export/15',
83
101
  softSolid: 'bg-export-subtle dark:bg-[color-mix(in_srgb,#1cbd5d_15%,#212529)]',
84
102
  softHover: 'hover:bg-export-subtle dark:hover:bg-export/15',
103
+ activeFill: 'bg-export-strong text-white border-transparent hover:bg-export-hover dark:bg-export dark:text-white dark:hover:bg-export-light',
104
+ stroked: 'bg-surface text-export-strong border-export-strong hover:bg-export-subtle dark:bg-ink-950 dark:text-export dark:border-export dark:hover:bg-export/15',
85
105
  };
86
106
  }
87
107
  return {
88
- text: 'text-import',
108
+ text: 'text-import-strong dark:text-import',
89
109
  bg: 'bg-import',
90
110
  bgSubtle: 'bg-import-subtle',
91
111
  border: 'border-import',
92
- primary: 'bg-import text-white border-transparent hover:bg-import-light',
93
- ghostPrimary: 'bg-transparent text-import border-transparent hover:bg-import-subtle dark:hover:bg-import/15',
112
+ primary: 'bg-import-strong text-white border-transparent hover:bg-import-hover dark:bg-import dark:hover:bg-import-light',
113
+ ghostPrimary: 'bg-transparent text-import-strong border-transparent hover:bg-import-subtle dark:text-import dark:hover:bg-import/15',
94
114
  soft: 'bg-import-subtle dark:bg-import/15',
95
115
  softSolid: 'bg-import-subtle dark:bg-[color-mix(in_srgb,#f08829_15%,#212529)]',
96
116
  softHover: 'hover:bg-import-subtle dark:hover:bg-import/15',
117
+ activeFill: 'bg-import-strong text-white border-transparent hover:bg-import-hover dark:bg-import dark:text-white dark:hover:bg-import-light',
118
+ stroked: 'bg-surface text-import-strong border-import-strong hover:bg-import-subtle dark:bg-ink-950 dark:text-import dark:border-import dark:hover:bg-import/15',
97
119
  };
98
120
  }, /* @ts-ignore */
99
121
  ...(ngDevMode ? [{ debugName: "classes" }] : /* istanbul ignore next */ []));
@@ -0,0 +1 @@
1
+ {"version":3,"file":"africanies-africanies-theme.mjs","sources":["../../../../libs/africanies-theme/src/lib/mode-color.safelist.ts","../../../../libs/africanies-theme/src/lib/mode-color.service.ts","../../../../libs/africanies-theme/src/lib/theme.service.ts","../../../../libs/africanies-theme/src/africanies-africanies-theme.ts"],"sourcesContent":["/**\n * Tailwind safelist side-effect for shipping-mode color utilities.\n *\n * WHY this file exists: JIT/content scanning only keeps class names that appear\n * as *literal strings* in scanned sources. {@link ModeColorService} already\n * returns these literals, but keeping a dedicated comment list makes the\n * contract obvious for consumers who configure `safelist` or purge plugins.\n *\n * Do not rename these strings without updating ModeColorService and THEME.md.\n *\n * SFN (export / green):\n * text-export-strong bg-export-strong hover:bg-export-hover border-export-strong\n * text-export bg-export bg-export-subtle bg-export-light border-export\n * hover:bg-export-light hover:bg-export-subtle dark:bg-export/15 dark:hover:bg-export/15\n * dark:bg-[color-mix(in_srgb,#1cbd5d_15%,#212529)] dark:bg-export dark:text-export dark:border-export\n *\n * STN (import / orange):\n * text-import-strong bg-import-strong hover:bg-import-hover border-import-strong\n * text-import bg-import bg-import-subtle bg-import-light border-import\n * hover:bg-import-light hover:bg-import-subtle dark:bg-import/15 dark:hover:bg-import/15\n * dark:bg-[color-mix(in_srgb,#f08829_15%,#212529)] dark:bg-import dark:text-import dark:border-import\n */\nexport const MODE_COLOR_SAFELIST = [\n 'text-export',\n 'text-export-strong',\n 'bg-export',\n 'bg-export-strong',\n 'bg-export-subtle',\n 'bg-export-light',\n 'border-export',\n 'border-export-strong',\n 'hover:bg-export-hover',\n 'hover:bg-export-light',\n 'hover:bg-export-subtle',\n 'dark:bg-export/15',\n 'dark:hover:bg-export/15',\n 'dark:hover:bg-export-light',\n 'dark:bg-[color-mix(in_srgb,#1cbd5d_15%,#212529)]',\n 'dark:bg-export',\n 'dark:text-export',\n 'dark:border-export',\n 'text-import',\n 'text-import-strong',\n 'bg-import',\n 'bg-import-strong',\n 'bg-import-subtle',\n 'bg-import-light',\n 'border-import',\n 'border-import-strong',\n 'hover:bg-import-hover',\n 'hover:bg-import-light',\n 'hover:bg-import-subtle',\n 'dark:bg-import/15',\n 'dark:hover:bg-import/15',\n 'dark:hover:bg-import-light',\n 'dark:bg-[color-mix(in_srgb,#f08829_15%,#212529)]',\n 'dark:bg-import',\n 'dark:text-import',\n 'dark:border-import',\n] as const;\n","import { computed, inject, Injectable } from '@angular/core';\n\nimport { ShippingModeService } from '@africanies/africanies-core';\n\n/**\n * Tailwind class bundle for the active shipping mode (SFN export / STN import).\n *\n * Use these for **primary** product chrome: CTAs, selected controls, progress,\n * and accent text. Semantic colors (danger / warning) stay mode-independent.\n */\nexport interface ModeColorClasses {\n /** Accessible accent text — `text-export-strong` in light, `text-export` in dark. */\n text: string;\n /** Solid background utility, e.g. `bg-export`. */\n bg: string;\n /** Soft background utility, e.g. `bg-export-subtle`. */\n bgSubtle: string;\n /** Border matching the mode accent, e.g. `border-export`. */\n border: string;\n /**\n * Filled primary CTA — `variant=\"primary\"` on buttons.\n * Includes hover utility as a literal so Tailwind keeps it.\n */\n primary: string;\n /**\n * Transparent / text-only CTA — `variant=\"ghost-primary\"` on buttons.\n * Mode accent text + soft hover fill.\n */\n ghostPrimary: string;\n /**\n * Soft highlight for selected / active rows (works in dark mode).\n * Dark uses a translucent tint — fine over solid surfaces, not for\n * sticky overlays (see {@link softSolid}).\n */\n soft: string;\n /**\n * Opaque soft fill — same tint as {@link soft}, but dark mode mixes into\n * ink so scrolled content cannot show through (sticky table headers/cells).\n */\n softSolid: string;\n /**\n * Soft hover highlight for menus and lists.\n */\n softHover: string;\n /**\n * Active nav leaf / collapsed rail — solid mode fill + white text.\n */\n activeFill: string;\n /**\n * Stroked secondary CTA — white fill, mode border + text (portal `.btn-stroked`).\n */\n stroked: string;\n}\n\n/**\n * Maps {@link ShippingModeService} to mode-accent Tailwind classes.\n *\n * - **SFN** → export green is primary\n * - **STN** → import orange is primary\n *\n * WHY literal class strings: Tailwind's scanner cannot see dynamically built\n * names like `` `text-${token}` ``. Returning full literals (`text-export`, …)\n * keeps utilities in the compiled CSS. See {@link MODE_COLOR_SAFELIST}.\n *\n * @example\n * ```html\n * @let colors = modeColor.classes();\n * <button type=\"button\" [class]=\"colors.primary\">Save</button>\n * <span [class]=\"colors.text\">Mode accent</span>\n * ```\n */\n@Injectable({ providedIn: 'root' })\nexport class ModeColorService {\n private readonly shippingMode = inject(ShippingModeService);\n\n /**\n * Mode-dependent utility classes. Recomputes when shipping mode changes.\n */\n readonly classes = computed<ModeColorClasses>(() => {\n // Literal strings required for Tailwind content detection — do not interpolate.\n if (this.shippingMode.mode() === 'sfn') {\n return {\n text: 'text-export-strong dark:text-export',\n bg: 'bg-export',\n bgSubtle: 'bg-export-subtle',\n border: 'border-export',\n primary:\n 'bg-export-strong text-white border-transparent hover:bg-export-hover dark:bg-export dark:hover:bg-export-light',\n ghostPrimary:\n 'bg-transparent text-export-strong border-transparent hover:bg-export-subtle dark:text-export dark:hover:bg-export/15',\n soft: 'bg-export-subtle dark:bg-export/15',\n softSolid:\n 'bg-export-subtle dark:bg-[color-mix(in_srgb,#1cbd5d_15%,#212529)]',\n softHover: 'hover:bg-export-subtle dark:hover:bg-export/15',\n activeFill:\n 'bg-export-strong text-white border-transparent hover:bg-export-hover dark:bg-export dark:text-white dark:hover:bg-export-light',\n stroked:\n 'bg-surface text-export-strong border-export-strong hover:bg-export-subtle dark:bg-ink-950 dark:text-export dark:border-export dark:hover:bg-export/15',\n };\n }\n return {\n text: 'text-import-strong dark:text-import',\n bg: 'bg-import',\n bgSubtle: 'bg-import-subtle',\n border: 'border-import',\n primary:\n 'bg-import-strong text-white border-transparent hover:bg-import-hover dark:bg-import dark:hover:bg-import-light',\n ghostPrimary:\n 'bg-transparent text-import-strong border-transparent hover:bg-import-subtle dark:text-import dark:hover:bg-import/15',\n soft: 'bg-import-subtle dark:bg-import/15',\n softSolid:\n 'bg-import-subtle dark:bg-[color-mix(in_srgb,#f08829_15%,#212529)]',\n softHover: 'hover:bg-import-subtle dark:hover:bg-import/15',\n activeFill:\n 'bg-import-strong text-white border-transparent hover:bg-import-hover dark:bg-import dark:text-white dark:hover:bg-import-light',\n stroked:\n 'bg-surface text-import-strong border-import-strong hover:bg-import-subtle dark:bg-ink-950 dark:text-import dark:border-import dark:hover:bg-import/15',\n };\n });\n}\n","import { DOCUMENT } from '@angular/common';\nimport { inject, Injectable, signal } from '@angular/core';\n\nimport { AFRICANIES_THEME_KEY, STORAGE_TOKEN } from '@africanies/africanies-storage';\n\nimport type { Theme } from './theme.types';\n\n/**\n * Application light/dark theme preference.\n *\n * WHY signals (not BehaviorSubject): theme is synchronous UI state read from\n * templates and other services; a signal avoids RxJS subscription boilerplate\n * and matches Angular 22 change detection. Persistence goes through\n * {@link STORAGE_TOKEN} so tests can swap storage without touching `localStorage`.\n *\n * Applies the Tailwind `darkMode: 'class'` contract by toggling `dark` on\n * `document.documentElement`, and sets `color-scheme` so native UI (date\n * pickers, scrollbars, form controls) matches the app theme — class-based\n * dark mode alone does not restyle browser chrome.\n *\n * @example\n * ```ts\n * // app.config.ts\n * import { inject, provideAppInitializer } from '@angular/core';\n * import { ThemeService } from '@africanies/africanies-theme';\n *\n * export const appConfig = {\n * providers: [\n * provideAppInitializer(() => {\n * inject(ThemeService); // applies stored / system theme once\n * }),\n * ],\n * };\n *\n * // In a component\n * const theme = inject(ThemeService);\n * theme.toggle();\n * theme.setTheme('dark');\n * const current = theme.theme(); // 'light' | 'dark'\n * ```\n */\n@Injectable({ providedIn: 'root' })\nexport class ThemeService {\n private readonly storage = inject(STORAGE_TOKEN);\n private readonly document = inject(DOCUMENT);\n\n /**\n * Current theme. Prefer reading via `theme()` in templates / computed values\n * rather than caching the string, so dark-class consumers stay in sync.\n */\n readonly theme = signal<Theme>(this.resolveInitialTheme());\n\n constructor() {\n this.applyToDocument(this.theme());\n }\n\n /**\n * Sets and persists the theme, updating the `dark` class and `color-scheme`\n * on `<html>`.\n *\n * @param theme - Absolute preference to store.\n */\n setTheme(theme: Theme): void {\n this.theme.set(theme);\n this.applyToDocument(theme);\n try {\n this.storage.set(AFRICANIES_THEME_KEY, theme);\n } catch {\n // Persistence failure must not block the in-session visual toggle —\n // private browsing / quota issues are transient for theme preference.\n }\n }\n\n /**\n * Flips between light and dark.\n *\n * @returns The theme after the toggle.\n */\n toggle(): Theme {\n const next: Theme = this.theme() === 'light' ? 'dark' : 'light';\n this.setTheme(next);\n return next;\n }\n\n private resolveInitialTheme(): Theme {\n try {\n const stored = this.storage.get<Theme>(AFRICANIES_THEME_KEY);\n if (stored === 'light' || stored === 'dark') {\n return stored;\n }\n } catch {\n // Fall through to system preference when storage is unavailable.\n }\n return this.prefersDark() ? 'dark' : 'light';\n }\n\n private prefersDark(): boolean {\n const win = this.document.defaultView;\n return !!win?.matchMedia?.('(prefers-color-scheme: dark)').matches;\n }\n\n private applyToDocument(theme: Theme): void {\n const root = this.document.documentElement;\n if (theme === 'dark') {\n root.classList.add('dark');\n } else {\n root.classList.remove('dark');\n }\n // Native date/time pickers follow `color-scheme`, not Tailwind's `dark` class.\n root.style.colorScheme = theme;\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
@@ -92,8 +92,8 @@ function africaniesAutofillPlugin({ addBase }) {
92
92
  const rules = {};
93
93
  for (const selector of autofillSelectors) {
94
94
  rules[selector] = {
95
- WebkitTextFillColor: '#212529',
96
- caretColor: '#212529',
95
+ WebkitTextFillColor: '#172033',
96
+ caretColor: '#172033',
97
97
  boxShadow: '0 0 0 1000px #ffffff inset',
98
98
  transition: 'background-color 99999s ease-in-out 0s',
99
99
  };
@@ -143,6 +143,36 @@ function africaniesOverlayStackPlugin({ addBase }) {
143
143
  });
144
144
  }
145
145
 
146
+ /**
147
+ * Shared elevated card shell so list/detail pages keep one light-theme recipe.
148
+ *
149
+ * @param {import('tailwindcss/types/config').PluginAPI} api
150
+ */
151
+ function africaniesSurfacePlugin({ addComponents }) {
152
+ addComponents({
153
+ '.africanies-card': {
154
+ borderRadius: '0.75rem',
155
+ borderWidth: '1px',
156
+ borderStyle: 'solid',
157
+ borderColor: '#dde3ea',
158
+ backgroundColor: '#ffffff',
159
+ padding: '1.25rem',
160
+ color: '#172033',
161
+ boxShadow:
162
+ '0 1px 2px rgb(23 32 51 / 0.04), 0 1px 3px rgb(23 32 51 / 0.06)',
163
+ '@media (min-width: 640px)': {
164
+ padding: '1.5rem',
165
+ },
166
+ },
167
+ '.dark .africanies-card': {
168
+ borderColor: 'rgba(255, 255, 255, 0.1)',
169
+ backgroundColor: '#272729',
170
+ color: '#ffffff',
171
+ boxShadow: 'none',
172
+ },
173
+ });
174
+ }
175
+
146
176
  /**
147
177
  * Keep overlay scrollbars off close buttons and other end-aligned chrome.
148
178
  *
@@ -186,6 +216,7 @@ module.exports = {
186
216
  africaniesSpinPlugin,
187
217
  africaniesOverlayStackPlugin,
188
218
  africaniesOverlayScrollPlugin,
219
+ africaniesSurfacePlugin,
189
220
  africaniesAutofillPlugin,
190
221
  ],
191
222
  theme: {
@@ -193,50 +224,86 @@ module.exports = {
193
224
  colors: {
194
225
  black: '#000000',
195
226
  white: '#ffffff',
227
+ surface: {
228
+ DEFAULT: '#ffffff',
229
+ subtle: '#f8fafc',
230
+ hover: '#e9eef5',
231
+ sunken: '#eef2f6',
232
+ },
196
233
  ink: {
197
- DEFAULT: '#212529',
234
+ // High-contrast cool navy for light-theme body and heading text.
235
+ DEFAULT: '#172033',
198
236
  blue: '#192a3e',
199
- brand: '#1c2b3f',
237
+ brand: '#172033',
238
+ // Previous ink DEFAULT — dark elevated cards / panels (`dark:bg-ink-surface`).
239
+ surface: '#212529',
200
240
  950: '#272729',
201
241
  },
202
242
  neutral: {
243
+ 50: '#f8fafc',
244
+ 100: '#eef2f6',
245
+ 200: '#dde3ea',
203
246
  300: '#c9d5e1',
247
+ // Keep 300/400 stable: they are the established dark-theme foregrounds.
204
248
  400: '#a9b5cb',
205
- 600: '#667185',
249
+ 500: '#667185',
250
+ 600: '#526071',
251
+ 700: '#3e4a59',
252
+ 800: '#2c3644',
253
+ 900: '#172033',
206
254
  },
207
255
  border: {
208
- // Light chrome on white match form field borders (`neutral-300`).
209
- // Previous `#f0f2f5` was too close to white and washed out.
210
- DEFAULT: '#c9d5e1',
256
+ // Quiet card/divider chrome. Controls use the stronger `control` token.
257
+ DEFAULT: '#dde3ea',
258
+ strong: '#c4cdd8',
211
259
  },
260
+ // 3.1:1 against white: visible enough for meaningful control boundaries.
261
+ control: '#8793a3',
262
+ focus: '#175cd3',
212
263
  background: {
213
- welcome: '#f9fafb',
264
+ // Cooler canvas and a clearer inset level beneath white surfaces.
265
+ chrome: '#f4f6f8',
266
+ // Nested wells inside white cards.
267
+ well: '#eef2f6',
268
+ // Auth / welcome / soft hover.
269
+ welcome: '#f8fafc',
270
+ hover: '#e9eef5',
214
271
  },
215
272
  export: {
216
273
  DEFAULT: '#1cbd5d',
217
274
  light: '#24dc6d',
218
275
  subtle: '#e4fff3',
219
276
  tint: '#f2fff8',
277
+ // Accessible normal-text / white-text-control foreground (5.43:1).
278
+ strong: '#0b7a3e',
279
+ hover: '#096833',
220
280
  },
221
281
  import: {
222
282
  DEFAULT: '#f08829',
223
283
  light: '#ffa95b',
224
284
  subtle: '#fffcef',
285
+ // Accessible normal-text / white-text-control foreground (6.20:1).
286
+ strong: '#9a4b0b',
287
+ hover: '#7f3e09',
225
288
  },
226
289
  danger: {
227
290
  DEFAULT: '#ff001c',
228
- dark: '#b41433',
291
+ dark: '#b4233c',
229
292
  strong: '#C00B19',
230
293
  subtle: '#FFF2F2',
231
294
  },
232
295
  warning: {
233
296
  DEFAULT: '#DBB316',
234
- dark: '#EF8833',
297
+ dark: '#8a5a00',
235
298
  subtle: '#FFF6E6',
236
299
  },
300
+ info: {
301
+ DEFAULT: '#175cd3',
302
+ subtle: '#eff6ff',
303
+ },
237
304
  },
238
305
  fontFamily: {
239
- sans: ['Arial', 'sans-serif'],
306
+ sans: ['Inter', 'system-ui', 'sans-serif'],
240
307
  },
241
308
  fontSize: {
242
309
  // PROVISIONAL — see THEME.md; sizes may tighten after design QA.
@@ -248,6 +315,16 @@ module.exports = {
248
315
  'body-sm': ['0.875rem', { lineHeight: 1.4, fontWeight: 400 }],
249
316
  caption: ['0.75rem', { lineHeight: 1.3, fontWeight: 400 }],
250
317
  },
318
+ borderRadius: {
319
+ control: '0.5rem',
320
+ panel: '0.75rem',
321
+ },
322
+ boxShadow: {
323
+ card:
324
+ '0 1px 2px rgb(23 32 51 / 0.04), 0 1px 3px rgb(23 32 51 / 0.06)',
325
+ floating:
326
+ '0 12px 32px rgb(23 32 51 / 0.12), 0 2px 8px rgb(23 32 51 / 0.06)',
327
+ },
251
328
  },
252
329
  },
253
330
  };
@@ -11,16 +11,18 @@ import * as i0 from '@angular/core';
11
11
  * Do not rename these strings without updating ModeColorService and THEME.md.
12
12
  *
13
13
  * SFN (export / green):
14
+ * text-export-strong bg-export-strong hover:bg-export-hover border-export-strong
14
15
  * text-export bg-export bg-export-subtle bg-export-light border-export
15
16
  * hover:bg-export-light hover:bg-export-subtle dark:bg-export/15 dark:hover:bg-export/15
16
- * dark:bg-[color-mix(in_srgb,#1cbd5d_15%,#212529)]
17
+ * dark:bg-[color-mix(in_srgb,#1cbd5d_15%,#212529)] dark:bg-export dark:text-export dark:border-export
17
18
  *
18
19
  * STN (import / orange):
20
+ * text-import-strong bg-import-strong hover:bg-import-hover border-import-strong
19
21
  * text-import bg-import bg-import-subtle bg-import-light border-import
20
22
  * hover:bg-import-light hover:bg-import-subtle dark:bg-import/15 dark:hover:bg-import/15
21
- * dark:bg-[color-mix(in_srgb,#f08829_15%,#212529)]
23
+ * dark:bg-[color-mix(in_srgb,#f08829_15%,#212529)] dark:bg-import dark:text-import dark:border-import
22
24
  */
23
- declare const MODE_COLOR_SAFELIST: readonly ["text-export", "bg-export", "bg-export-subtle", "bg-export-light", "border-export", "hover:bg-export-light", "hover:bg-export-subtle", "dark:bg-export/15", "dark:hover:bg-export/15", "dark:bg-[color-mix(in_srgb,#1cbd5d_15%,#212529)]", "text-import", "bg-import", "bg-import-subtle", "bg-import-light", "border-import", "hover:bg-import-light", "hover:bg-import-subtle", "dark:bg-import/15", "dark:hover:bg-import/15", "dark:bg-[color-mix(in_srgb,#f08829_15%,#212529)]"];
25
+ declare const MODE_COLOR_SAFELIST: readonly ["text-export", "text-export-strong", "bg-export", "bg-export-strong", "bg-export-subtle", "bg-export-light", "border-export", "border-export-strong", "hover:bg-export-hover", "hover:bg-export-light", "hover:bg-export-subtle", "dark:bg-export/15", "dark:hover:bg-export/15", "dark:hover:bg-export-light", "dark:bg-[color-mix(in_srgb,#1cbd5d_15%,#212529)]", "dark:bg-export", "dark:text-export", "dark:border-export", "text-import", "text-import-strong", "bg-import", "bg-import-strong", "bg-import-subtle", "bg-import-light", "border-import", "border-import-strong", "hover:bg-import-hover", "hover:bg-import-light", "hover:bg-import-subtle", "dark:bg-import/15", "dark:hover:bg-import/15", "dark:hover:bg-import-light", "dark:bg-[color-mix(in_srgb,#f08829_15%,#212529)]", "dark:bg-import", "dark:text-import", "dark:border-import"];
24
26
 
25
27
  /**
26
28
  * Tailwind class bundle for the active shipping mode (SFN export / STN import).
@@ -29,7 +31,7 @@ declare const MODE_COLOR_SAFELIST: readonly ["text-export", "bg-export", "bg-exp
29
31
  * and accent text. Semantic colors (danger / warning) stay mode-independent.
30
32
  */
31
33
  interface ModeColorClasses {
32
- /** Text color utility, e.g. `text-export`. */
34
+ /** Accessible accent text `text-export-strong` in light, `text-export` in dark. */
33
35
  text: string;
34
36
  /** Solid background utility, e.g. `bg-export`. */
35
37
  bg: string;
@@ -62,6 +64,14 @@ interface ModeColorClasses {
62
64
  * Soft hover highlight for menus and lists.
63
65
  */
64
66
  softHover: string;
67
+ /**
68
+ * Active nav leaf / collapsed rail — solid mode fill + white text.
69
+ */
70
+ activeFill: string;
71
+ /**
72
+ * Stroked secondary CTA — white fill, mode border + text (portal `.btn-stroked`).
73
+ */
74
+ stroked: string;
65
75
  }
66
76
  /**
67
77
  * Maps {@link ShippingModeService} to mode-accent Tailwind classes.
@@ -1,7 +1,7 @@
1
1
  import * as i0 from '@angular/core';
2
2
  import { InjectionToken, inject, Injector, signal, Injectable, makeEnvironmentProviders, provideAppInitializer } from '@angular/core';
3
3
  import { SessionStorageService, AFRICANIES_SHIPPING_MODE_KEY, STORAGE_TOKEN, AFRICANIES_MODE_CONFIG_KEY, provideLocalStorage, AFRICANIES_ACCESS_TOKEN_KEY } from '@africanies/africanies-storage';
4
- import { of, retry, throwError, timer, timeout, map as map$1, tap as tap$1, catchError, finalize, firstValueFrom, forkJoin } from 'rxjs';
4
+ import { of, timeout, throwError, map as map$1, tap as tap$1, catchError, finalize, firstValueFrom, forkJoin } from 'rxjs';
5
5
  import { HttpErrorResponse, HttpContextToken, HttpContext, HttpClient, HttpHeaders, HttpParams, provideHttpClient, withInterceptors } from '@angular/common/http';
6
6
  import { DEFAULT_PAGE_SIZE, NOTIFICATION_PAGE_SIZE } from '@africanies/africanies-models';
7
7
  import { take, tap, map } from 'rxjs/operators';
@@ -687,31 +687,6 @@ class HttpResponseCache {
687
687
  }
688
688
  }
689
689
 
690
- /**
691
- * Whether a failed GET should be retried by {@link ApiClient}.
692
- *
693
- * Retries transient failures only (network blips, timeouts, 408/429, 5xx).
694
- * Auth and other 4xx errors fail fast — retrying 401 does not help and causes
695
- * duplicate requests + toasts.
696
- * @param err
697
- */
698
- function isRetryableGetError(err) {
699
- if (err instanceof HttpErrorResponse) {
700
- if (err.status === 0) {
701
- return true;
702
- }
703
- if (err.status === 408 || err.status === 429) {
704
- return true;
705
- }
706
- if (err.status >= 500) {
707
- return true;
708
- }
709
- return false;
710
- }
711
- // Non-HTTP failures (e.g. timeout operator) may still be transient.
712
- return true;
713
- }
714
-
715
690
  /**
716
691
  * Per-request shipping-mode override for {@link shipmentModeInterceptor}.
717
692
  *
@@ -979,7 +954,8 @@ function mapResourcePayload(id, raw, mapOne, mapMany) {
979
954
  * - HTTP failures rethrown as `Error` whose `.message` is already
980
955
  * user-facing ({@link formatApiErrorMessage}) — consumers do not need to
981
956
  * parse `HttpErrorResponse` bodies
982
- * - Exponential-backoff retry (max 1) for **GET only**
957
+ * - **No automatic retry** fail fast so UIs can show Select / table /
958
+ * error-state Retry instead of a stuck loading spinner
983
959
  * - Optional per-GET TTL cache via `cacheTtlMs`
984
960
  *
985
961
  * @example
@@ -1121,18 +1097,8 @@ class ApiClient {
1121
1097
  req$ = this.http.delete(url, hasBody ? { ...httpOpts, body } : httpOpts);
1122
1098
  break;
1123
1099
  }
1124
- // Retry only idempotent GETs on transient failures never replay 401/404 etc.
1125
- if (method === 'GET') {
1126
- req$ = req$.pipe(retry({
1127
- count: 1,
1128
- delay: (err, retryCount) => {
1129
- if (!isRetryableGetError(err)) {
1130
- return throwError(() => err);
1131
- }
1132
- return timer(2 ** (retryCount - 1) * 1000);
1133
- },
1134
- }));
1135
- }
1100
+ // No automatic GET retry admin shells own Retry via UI
1101
+ // (`africanies-select` showRetry, table error→refreshClick, error-state).
1136
1102
  if (this.config.timeout != null) {
1137
1103
  req$ = req$.pipe(timeout({
1138
1104
  each: this.config.timeout,
@@ -1808,8 +1774,8 @@ function listFetchKind(options) {
1808
1774
  * (no caret/tilde): TanStack marks the Angular adapter experimental and
1809
1775
  * breaking changes land without major bumps.
1810
1776
  *
1811
- * Retry/backoff here mirrors {@link ApiClient}'s GET retry (max 3,
1812
- * exponential) so HTTP-layer and query-layer behavior stay aligned.
1777
+ * Query retries default to **0** to match {@link ApiClient} (fail fast;
1778
+ * screens use manual Retry). Apps can override per `QueryClient` if needed.
1813
1779
  */
1814
1780
  /**
1815
1781
  * Factory for TanStack `QueryClient` `defaultOptions`.
@@ -1859,8 +1825,7 @@ function createAfricaniesQueryClientDefaults() {
1859
1825
  queries: {
1860
1826
  staleTime: 60_000,
1861
1827
  gcTime: 5 * 60_000,
1862
- retry: 3,
1863
- // attemptIndex is 0-based in TanStack; match 1s, 2s, 4s style backoff.
1828
+ retry: 0,
1864
1829
  retryDelay: (attemptIndex) => Math.min(1000 * 2 ** attemptIndex, 30_000),
1865
1830
  },
1866
1831
  mutations: {
@@ -3800,22 +3765,58 @@ const SHIPMENT_APP_BY_MODE = {
3800
3765
  stn: 'shiptonaija',
3801
3766
  sfn: 'shipfromnaija',
3802
3767
  };
3768
+ const QUERY_SHIPMENT_APP = 'shipment_app';
3769
+ const LEGACY_PORTAL_HOST = /^(?:test-)?(?:admin|customer)-(?:export|import)\.africaniestest\.com$/i;
3770
+ /** Signed export downloads and other hosts that must not be rewritten in-app. */
3771
+ function isNotificationExternalLink(link) {
3772
+ const trimmed = decodeNotificationLink(link).trim();
3773
+ if (!trimmed) {
3774
+ return false;
3775
+ }
3776
+ try {
3777
+ const url = new URL(trimmed);
3778
+ if (/\.(xlsx|xls|csv)(\?|$)/i.test(url.pathname)) {
3779
+ return true;
3780
+ }
3781
+ if (/\.amazonaws\.com$/i.test(url.hostname)) {
3782
+ return true;
3783
+ }
3784
+ return !isLegacyPortalHost(url.hostname);
3785
+ }
3786
+ catch {
3787
+ return false;
3788
+ }
3789
+ }
3803
3790
  /**
3804
- * Rewrite a notification portal URL for the active {@link ShippingMode}.
3791
+ * Rewrite a notification href for the active {@link ShippingMode}.
3805
3792
  *
3806
- * Swaps `-export` / `-import` host segments and sets `shipment_app` to
3807
- * `shipfromnaija` (SFN) or `shiptonaija` (STN).
3808
- * @param link
3809
- * @param mode
3793
+ * - Export / download URLs (S3, spreadsheets) pass through unchanged (no `shipment_app`).
3794
+ * - Legacy portal hosts become relative `/portal/...` paths with query preserved.
3795
+ * - When the notification already includes `shipment_app`, it is kept as-is.
3796
+ * - Otherwise classic host / `shipment_app` rewriting applies for portal URLs.
3810
3797
  */
3811
3798
  function resolveNotificationLinkForMode(link, mode) {
3812
- const trimmed = asString(link).trim();
3799
+ const trimmed = decodeNotificationLink(asString(link)).trim();
3813
3800
  if (!trimmed) {
3814
3801
  return trimmed;
3815
3802
  }
3803
+ if (isNotificationExternalLink(trimmed)) {
3804
+ return stripShipmentAppFromLink(trimmed);
3805
+ }
3806
+ const relativePortal = toRelativePortalNotificationLink(trimmed);
3807
+ if (relativePortal && hasShipmentAppQuery(relativePortal)) {
3808
+ return relativePortal;
3809
+ }
3810
+ const relative = normalizeRelativePortalLink(trimmed);
3811
+ if (relative && hasShipmentAppQuery(relative)) {
3812
+ return relative;
3813
+ }
3816
3814
  try {
3817
3815
  const url = new URL(trimmed);
3818
- url.searchParams.set('shipment_app', SHIPMENT_APP_BY_MODE[mode]);
3816
+ if (url.searchParams.has(QUERY_SHIPMENT_APP)) {
3817
+ return trimmed;
3818
+ }
3819
+ url.searchParams.set(QUERY_SHIPMENT_APP, SHIPMENT_APP_BY_MODE[mode]);
3819
3820
  url.hostname = rewriteNotificationHostForMode(url.hostname, mode);
3820
3821
  return url.toString();
3821
3822
  }
@@ -3830,6 +3831,9 @@ function rewriteNotificationHostForMode(hostname, mode) {
3830
3831
  return hostname.replace(/-import/i, '-export');
3831
3832
  }
3832
3833
  function rewriteNotificationLinkFallback(link, mode) {
3834
+ if (hasShipmentAppQuery(link)) {
3835
+ return link;
3836
+ }
3833
3837
  let out = link.replace(/shipment_app=(?:shipfromnaija|shiptonaija)/gi, `shipment_app=${SHIPMENT_APP_BY_MODE[mode]}`);
3834
3838
  if (!/shipment_app=/i.test(out)) {
3835
3839
  const joiner = out.includes('?') ? '&' : '?';
@@ -3840,6 +3844,90 @@ function rewriteNotificationLinkFallback(link, mode) {
3840
3844
  }
3841
3845
  return out.replace(/-import/gi, '-export');
3842
3846
  }
3847
+ function toRelativePortalNotificationLink(link) {
3848
+ try {
3849
+ const url = new URL(link);
3850
+ if (!isLegacyPortalHost(url.hostname)) {
3851
+ return null;
3852
+ }
3853
+ let path = url.pathname.replace(/^\/+/, '');
3854
+ if (path.startsWith('ng/portal/')) {
3855
+ path = path.slice('ng/'.length);
3856
+ }
3857
+ if (!path.startsWith('portal/') && path !== 'portal') {
3858
+ return null;
3859
+ }
3860
+ const query = url.searchParams.toString();
3861
+ return `/${path}${query ? `?${query}` : ''}`;
3862
+ }
3863
+ catch {
3864
+ return null;
3865
+ }
3866
+ }
3867
+ function normalizeRelativePortalLink(link) {
3868
+ let path = link.split('?')[0]?.split('#')[0] ?? '';
3869
+ const query = link.includes('?') ? link.slice(link.indexOf('?')) : '';
3870
+ path = path.replace(/^\/+/, '');
3871
+ if (path.startsWith('ng/portal/')) {
3872
+ path = path.slice('ng/'.length);
3873
+ }
3874
+ if (!path.startsWith('portal/') && path !== 'portal') {
3875
+ return null;
3876
+ }
3877
+ return `/${path}${query}`;
3878
+ }
3879
+ function stripShipmentAppFromLink(link) {
3880
+ const trimmed = link.trim();
3881
+ if (!trimmed) {
3882
+ return trimmed;
3883
+ }
3884
+ try {
3885
+ const url = new URL(trimmed);
3886
+ if (!url.searchParams.has(QUERY_SHIPMENT_APP)) {
3887
+ return trimmed;
3888
+ }
3889
+ url.searchParams.delete(QUERY_SHIPMENT_APP);
3890
+ return url.toString();
3891
+ }
3892
+ catch {
3893
+ const params = new URLSearchParams(trimmed.includes('?') ? trimmed.slice(trimmed.indexOf('?') + 1) : '');
3894
+ if (!params.has(QUERY_SHIPMENT_APP)) {
3895
+ return trimmed;
3896
+ }
3897
+ params.delete(QUERY_SHIPMENT_APP);
3898
+ const query = params.toString();
3899
+ const base = trimmed.split('?')[0] ?? trimmed;
3900
+ return query ? `${base}?${query}` : base;
3901
+ }
3902
+ }
3903
+ function hasShipmentAppQuery(link) {
3904
+ try {
3905
+ const query = link.includes('?') ? link.slice(link.indexOf('?') + 1) : '';
3906
+ return new URLSearchParams(query).has(QUERY_SHIPMENT_APP);
3907
+ }
3908
+ catch {
3909
+ return /(?:^|[?&])shipment_app=/i.test(link);
3910
+ }
3911
+ }
3912
+ function decodeNotificationLink(link) {
3913
+ let value = (link ?? '').trim();
3914
+ if (!value.includes('%')) {
3915
+ return value;
3916
+ }
3917
+ try {
3918
+ const decoded = decodeURIComponent(value);
3919
+ if (decoded !== value) {
3920
+ value = decoded;
3921
+ }
3922
+ }
3923
+ catch {
3924
+ // Keep original when not valid URI encoding.
3925
+ }
3926
+ return value;
3927
+ }
3928
+ function isLegacyPortalHost(hostname) {
3929
+ return LEGACY_PORTAL_HOST.test(hostname);
3930
+ }
3843
3931
 
3844
3932
  /**
3845
3933
  * File utility reads (`POST /file/read`).
@@ -4542,5 +4630,5 @@ function downloadCsv(options) {
4542
4630
  * Generated bundle index. Do not edit.
4543
4631
  */
4544
4632
 
4545
- export { AFRICANIES_HTTP_TOAST, AFRICANIES_SDK_CONFIG, AUTH_FORGOT_PASSWORD_PATH, ApiClient, AuthService, AuthTokenService, COUNTRY_FLAG_CDN_BASE, COUNTRY_READ_PATH, CURRENCY_CREATE_PATH, CURRENCY_DELETE_PATH, CURRENCY_READ_PATH, CURRENCY_UPDATE_PATH, CountryService, CurrencyService, DOCUMENT_READ_PATH, DRAWER_SERVICE, DocumentService, FILE_READ_MULTIPLE_PARAM, FILE_READ_PATH, FileService, FilterOptionsResolver, HttpResponseCache, MODAL_SERVICE, MODE_CONFIG_PATH, ModeConfigService, NOTIFICATION_READ_PATH, NOTIFICATION_UPDATE_PATH, NotificationService, OVERLAY_ROUTE_CONFIGS, PAYMENT_METHOD_READ_PATH, PAYMENT_METHOD_UPDATE_PATH, PLAN_READ_PATH, PRODUCT_READ_PATH, PaymentMethodService, PlanService, ProductService, RouteOverlayService, SERVICE_READ_PATH, SHIPMENT_METHOD_READ_PATH, SHIPPING_MODE_OVERRIDE, ServiceService, ShipmentMethodService, ShippingModeService, TOAST_HTTP_OPTIONS, USER_CHANGE_PASSWORD_PATH, USER_LOGOUT_FROM_ALL_SESSIONS_PATH, USER_PATH, UserService, WAREHOUSE_READ_PATH, WarehouseService, ZONE_READ_PATH, ZoneService, asArray, asBoolean, asNullableBoolean, asNullableFlag01, asNullableNumber, asNullableString, asNumber, asRecord, asShippingMode$1 as asShippingMode, asString, authInterceptor, buildResourcePath, buildResourceQueryParams, collectFilterOptionsSources, collectResolvableSelectFields, copyToClipboard, countryFlagUrl, createAfricaniesQueryClientDefaults, csvCell, downloadCsv, fieldErrorsMap, formatApiErrorMessage, httpToastInterceptor, isLaravelValidationBag, isValidEmail, joinApiErrorMessages, listFetchKind, mapApiJsonList, mapApiJsonValue, mapArray, mapCountry, mapCountryList, mapCountrySelectOptions, mapCountryState, mapCurrency, mapCurrencyList, mapCurrencyPaymentMethod, mapCurrencyPaymentMethodPivot, mapDocument, mapDocumentList, mapFileRead, mapFileReadList, mapLaravelValidationBag, mapList, mapModeConfigData, mapNotification, mapNotificationInboxItem, mapNotificationList, mapNotificationPayload, mapPaymentMethod, mapPaymentMethodCurrency, mapPaymentMethodList, mapPlan, mapPlanList, mapPlanPackage, mapProduct, mapProductList, mapResourcePayload, mapService, mapServiceList, mapShipmentMethod, mapShipmentMethodFilterOptions, mapShipmentMethodList, mapShipmentMethodZoneLink, mapShipmentMethodZonePage, mapShipmentZone, mapUser, mapUserAccountManager, mapUserBusinessAccount, mapUserCountry, mapUserCountryState, mapUserGatewayPayload, mapUserPaymentPayload, mapUserPlan, mapUserPlanPackage, mapUserStateLabel, mapUserSubscription, mapWarehouse, mapWarehouseCountry, mapWarehouseFilterOptions, mapWarehouseList, mapWarehouseState, mapZone, mapZoneList, mergeFilterOptionLists, normalize, normalizePagination, provideAfricaniesHttpClient, provideAfricaniesQueryDefaults, provideAfricaniesSdk, provideModeConfig, provideOverlayRoutes, resolveModeRegionConfig, resolveNotificationLinkForMode, resourceCacheTtlMs, shipmentModeInterceptor, toCsvString, toCurrencyCreateBody, toCurrencyDeleteBody, toCurrencyFlag01, toCurrencyUpdateBody, toFlag01, toPaymentMethodFlag01, toPaymentMethodUpdateBody, unwrapLaravelPaginator, withShippingMode, withToast };
4633
+ export { AFRICANIES_HTTP_TOAST, AFRICANIES_SDK_CONFIG, AUTH_FORGOT_PASSWORD_PATH, ApiClient, AuthService, AuthTokenService, COUNTRY_FLAG_CDN_BASE, COUNTRY_READ_PATH, CURRENCY_CREATE_PATH, CURRENCY_DELETE_PATH, CURRENCY_READ_PATH, CURRENCY_UPDATE_PATH, CountryService, CurrencyService, DOCUMENT_READ_PATH, DRAWER_SERVICE, DocumentService, FILE_READ_MULTIPLE_PARAM, FILE_READ_PATH, FileService, FilterOptionsResolver, HttpResponseCache, MODAL_SERVICE, MODE_CONFIG_PATH, ModeConfigService, NOTIFICATION_READ_PATH, NOTIFICATION_UPDATE_PATH, NotificationService, OVERLAY_ROUTE_CONFIGS, PAYMENT_METHOD_READ_PATH, PAYMENT_METHOD_UPDATE_PATH, PLAN_READ_PATH, PRODUCT_READ_PATH, PaymentMethodService, PlanService, ProductService, RouteOverlayService, SERVICE_READ_PATH, SHIPMENT_METHOD_READ_PATH, SHIPPING_MODE_OVERRIDE, ServiceService, ShipmentMethodService, ShippingModeService, TOAST_HTTP_OPTIONS, USER_CHANGE_PASSWORD_PATH, USER_LOGOUT_FROM_ALL_SESSIONS_PATH, USER_PATH, UserService, WAREHOUSE_READ_PATH, WarehouseService, ZONE_READ_PATH, ZoneService, asArray, asBoolean, asNullableBoolean, asNullableFlag01, asNullableNumber, asNullableString, asNumber, asRecord, asShippingMode$1 as asShippingMode, asString, authInterceptor, buildResourcePath, buildResourceQueryParams, collectFilterOptionsSources, collectResolvableSelectFields, copyToClipboard, countryFlagUrl, createAfricaniesQueryClientDefaults, csvCell, downloadCsv, fieldErrorsMap, formatApiErrorMessage, httpToastInterceptor, isLaravelValidationBag, isNotificationExternalLink, isValidEmail, joinApiErrorMessages, listFetchKind, mapApiJsonList, mapApiJsonValue, mapArray, mapCountry, mapCountryList, mapCountrySelectOptions, mapCountryState, mapCurrency, mapCurrencyList, mapCurrencyPaymentMethod, mapCurrencyPaymentMethodPivot, mapDocument, mapDocumentList, mapFileRead, mapFileReadList, mapLaravelValidationBag, mapList, mapModeConfigData, mapNotification, mapNotificationInboxItem, mapNotificationList, mapNotificationPayload, mapPaymentMethod, mapPaymentMethodCurrency, mapPaymentMethodList, mapPlan, mapPlanList, mapPlanPackage, mapProduct, mapProductList, mapResourcePayload, mapService, mapServiceList, mapShipmentMethod, mapShipmentMethodFilterOptions, mapShipmentMethodList, mapShipmentMethodZoneLink, mapShipmentMethodZonePage, mapShipmentZone, mapUser, mapUserAccountManager, mapUserBusinessAccount, mapUserCountry, mapUserCountryState, mapUserGatewayPayload, mapUserPaymentPayload, mapUserPlan, mapUserPlanPackage, mapUserStateLabel, mapUserSubscription, mapWarehouse, mapWarehouseCountry, mapWarehouseFilterOptions, mapWarehouseList, mapWarehouseState, mapZone, mapZoneList, mergeFilterOptionLists, normalize, normalizePagination, provideAfricaniesHttpClient, provideAfricaniesQueryDefaults, provideAfricaniesSdk, provideModeConfig, provideOverlayRoutes, resolveModeRegionConfig, resolveNotificationLinkForMode, resourceCacheTtlMs, shipmentModeInterceptor, toCsvString, toCurrencyCreateBody, toCurrencyDeleteBody, toCurrencyFlag01, toCurrencyUpdateBody, toFlag01, toPaymentMethodFlag01, toPaymentMethodUpdateBody, unwrapLaravelPaginator, withShippingMode, withToast };
4546
4634
  //# sourceMappingURL=africanies-africanies-core.mjs.map