@africanies/angular-web-sdk 0.1.7 → 0.1.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.angular/cache/22.0.9/playground/.tsbuildinfo +1 -1
- package/.nx/cache/{4082520855419352840 → 15302120112746851896}/dist/libs/africanies-theme/fesm2022/africanies-africanies-theme.mjs +30 -8
- package/.nx/cache/15302120112746851896/dist/libs/africanies-theme/fesm2022/africanies-africanies-theme.mjs.map +1 -0
- package/.nx/cache/{4082520855419352840 → 15302120112746851896}/dist/libs/africanies-theme/tailwind-preset.cjs +89 -12
- package/.nx/cache/{4082520855419352840 → 15302120112746851896}/dist/libs/africanies-theme/types/africanies-africanies-theme.d.ts +14 -4
- package/.nx/cache/17289624717336768573/dist/libs/africanies-core/fesm2022/africanies-africanies-core.mjs +4639 -0
- package/.nx/cache/17289624717336768573/dist/libs/africanies-core/fesm2022/africanies-africanies-core.mjs.map +1 -0
- package/.nx/cache/17289624717336768573/dist/libs/africanies-core/types/africanies-africanies-core.d.ts +2748 -0
- package/.nx/cache/18393832731522001121/dist/libs/africanies-core/README.md +85 -0
- package/.nx/cache/{17491371155400585077 → 18393832731522001121}/dist/libs/africanies-core/fesm2022/africanies-africanies-core.mjs +139 -51
- package/.nx/cache/18393832731522001121/dist/libs/africanies-core/fesm2022/africanies-africanies-core.mjs.map +1 -0
- package/.nx/cache/18393832731522001121/dist/libs/africanies-core/package.json +31 -0
- package/.nx/cache/{17491371155400585077 → 18393832731522001121}/dist/libs/africanies-core/types/africanies-africanies-core.d.ts +14 -11
- package/.nx/cache/{3314955264390318442 → 3953970051755345887}/dist/libs/africanies-ui/fesm2022/africanies-africanies-ui.mjs +775 -566
- package/.nx/cache/3953970051755345887/dist/libs/africanies-ui/fesm2022/africanies-africanies-ui.mjs.map +1 -0
- package/.nx/cache/{17499961385238663835 → 3953970051755345887}/dist/libs/africanies-ui/types/africanies-africanies-ui.d.ts +150 -119
- package/.nx/cache/{12276756491762927325 → 4225324930345532464}/dist/libs/africanies-theme/fesm2022/africanies-africanies-theme.mjs +34 -6
- package/.nx/cache/4225324930345532464/dist/libs/africanies-theme/fesm2022/africanies-africanies-theme.mjs.map +1 -0
- package/.nx/cache/{12276756491762927325 → 4225324930345532464}/dist/libs/africanies-theme/tailwind-preset.cjs +104 -19
- package/.nx/cache/{12276756491762927325 → 4225324930345532464}/dist/libs/africanies-theme/types/africanies-africanies-theme.d.ts +21 -2
- package/.nx/cache/5151121439688073678/dist/libs/africanies-icons/README.md +69 -0
- package/.nx/cache/5151121439688073678/dist/libs/africanies-icons/assets/icons.sprite.svg +1851 -0
- package/.nx/cache/5151121439688073678/dist/libs/africanies-icons/fesm2022/africanies-africanies-icons.mjs +833 -0
- package/.nx/cache/5151121439688073678/dist/libs/africanies-icons/fesm2022/africanies-africanies-icons.mjs.map +1 -0
- package/.nx/cache/5151121439688073678/dist/libs/africanies-icons/package.json +30 -0
- package/.nx/cache/5151121439688073678/dist/libs/africanies-icons/types/africanies-africanies-icons.d.ts +108 -0
- package/.nx/cache/877026836685850193/dist/libs/africanies-models/README.md +60 -0
- package/.nx/cache/877026836685850193/dist/libs/africanies-models/fesm2022/africanies-africanies-models.mjs +613 -0
- package/.nx/cache/877026836685850193/dist/libs/africanies-models/fesm2022/africanies-africanies-models.mjs.map +1 -0
- package/.nx/cache/877026836685850193/dist/libs/africanies-models/package.json +23 -0
- package/.nx/cache/877026836685850193/dist/libs/africanies-models/types/africanies-africanies-models.d.ts +1452 -0
- package/.nx/cache/{17499961385238663835 → 9406544675747598148}/dist/libs/africanies-ui/fesm2022/africanies-africanies-ui.mjs +765 -615
- package/.nx/cache/9406544675747598148/dist/libs/africanies-ui/fesm2022/africanies-africanies-ui.mjs.map +1 -0
- package/.nx/cache/{3314955264390318442 → 9406544675747598148}/dist/libs/africanies-ui/types/africanies-africanies-ui.d.ts +170 -130
- package/.nx/cache/run.json +36 -36
- package/.nx/cache/terminalOutputs/{3017748574492080228 → 12565224028063674529} +16 -7
- package/.nx/cache/terminalOutputs/{8648260256613557249 → 13478445034325959094} +175 -172
- package/.nx/cache/terminalOutputs/{7126777490381568487 → 15149466893522345489} +10 -5
- package/.nx/cache/terminalOutputs/{4082520855419352840 → 15302120112746851896} +1 -1
- package/.nx/cache/terminalOutputs/15835338512221847842 +185 -0
- package/.nx/cache/terminalOutputs/{17491371155400585077 → 17289624717336768573} +1 -1
- package/.nx/cache/terminalOutputs/17571479482482478257 +35 -0
- package/.nx/cache/terminalOutputs/{9408529484792607601 → 17960163310445607219} +1 -1
- package/.nx/cache/terminalOutputs/18393832731522001121 +21 -0
- package/.nx/cache/terminalOutputs/3088264223473143358 +8 -0
- package/.nx/cache/terminalOutputs/{3314955264390318442 → 3953970051755345887} +1 -1
- package/.nx/cache/terminalOutputs/{12276756491762927325 → 4225324930345532464} +1 -1
- package/.nx/cache/terminalOutputs/4363587767476846758 +176 -0
- package/.nx/cache/terminalOutputs/5151121439688073678 +21 -0
- package/.nx/cache/terminalOutputs/7462873189468732296 +17 -0
- package/.nx/cache/terminalOutputs/8032148447904822353 +184 -182
- package/.nx/cache/terminalOutputs/8193462679279018087 +39 -0
- package/.nx/cache/terminalOutputs/877026836685850193 +21 -0
- package/.nx/cache/terminalOutputs/9406544675747598148 +21 -0
- package/.nx/workspace-data/0091ABA9-5C90-580D-953C-8C94E763ADB5-v3.db +0 -0
- package/.nx/workspace-data/0091ABA9-5C90-580D-953C-8C94E763ADB5-v3.db-shm +0 -0
- package/.nx/workspace-data/0091ABA9-5C90-580D-953C-8C94E763ADB5-v3.db-wal +0 -0
- package/.nx/workspace-data/d/daemon.log +6813 -0
- package/.nx/workspace-data/d/server-process.json +2 -2
- package/.nx/workspace-data/file-map.json +3490 -3432
- package/.nx/workspace-data/nx_files.nxt +0 -0
- package/.nx/workspace-data/project-graph.json +7 -2
- package/apps/playground/src/app/pages/tokens-page.ts +17 -13
- package/apps/playground/src/app/snippets/filters.snippets.ts +10 -0
- package/dist/libs/africanies-core/fesm2022/africanies-africanies-core.mjs +6 -1
- package/dist/libs/africanies-core/fesm2022/africanies-africanies-core.mjs.map +1 -1
- package/dist/libs/africanies-core/types/africanies-africanies-core.d.ts +6 -1
- package/dist/libs/africanies-icons/assets/icons.sprite.svg +7 -0
- package/dist/libs/africanies-icons/fesm2022/africanies-africanies-icons.mjs +1 -0
- package/dist/libs/africanies-icons/fesm2022/africanies-africanies-icons.mjs.map +1 -1
- package/dist/libs/africanies-icons/types/africanies-africanies-icons.d.ts +2 -2
- package/dist/libs/africanies-models/fesm2022/africanies-africanies-models.mjs +22 -8
- package/dist/libs/africanies-models/fesm2022/africanies-africanies-models.mjs.map +1 -1
- package/dist/libs/africanies-theme/fesm2022/africanies-africanies-theme.mjs +22 -10
- package/dist/libs/africanies-theme/fesm2022/africanies-africanies-theme.mjs.map +1 -1
- package/dist/libs/africanies-theme/tailwind-preset.cjs +84 -16
- package/dist/libs/africanies-theme/types/africanies-africanies-theme.d.ts +4 -2
- package/dist/libs/africanies-ui/fesm2022/africanies-africanies-ui.mjs +723 -618
- package/dist/libs/africanies-ui/fesm2022/africanies-africanies-ui.mjs.map +1 -1
- package/dist/libs/africanies-ui/types/africanies-africanies-ui.d.ts +142 -114
- package/libs/africanies-core/src/index.ts +1 -1
- package/libs/africanies-core/src/lib/notification/notification-link.ts +6 -1
- package/libs/africanies-icons/src/assets/icons.sprite.svg +7 -0
- package/libs/africanies-icons/src/lib/icon-name.ts +1 -0
- package/libs/africanies-models/src/lib/filters/configs/seed-configs.ts +22 -8
- package/libs/africanies-theme/src/lib/mode-color.safelist.ts +12 -0
- package/libs/africanies-theme/src/lib/mode-color.service.spec.ts +55 -0
- package/libs/africanies-theme/src/lib/mode-color.service.ts +11 -11
- package/libs/africanies-theme/tailwind-preset.cjs +84 -16
- package/libs/africanies-ui/src/lib/action-menu/action-menu.component.ts +3 -3
- package/libs/africanies-ui/src/lib/alert/alert.component.ts +4 -4
- package/libs/africanies-ui/src/lib/avatar/avatar-menu.component.ts +2 -2
- package/libs/africanies-ui/src/lib/button/button.component.spec.ts +7 -7
- package/libs/africanies-ui/src/lib/button/button.component.ts +5 -5
- package/libs/africanies-ui/src/lib/chip/chip.component.ts +4 -4
- package/libs/africanies-ui/src/lib/content-stack/content-stack.component.ts +1 -1
- package/libs/africanies-ui/src/lib/feedback/error-indicator.component.ts +3 -3
- package/libs/africanies-ui/src/lib/feedback/error-state.component.ts +2 -2
- package/libs/africanies-ui/src/lib/filters/filter-drawer.panel.ts +44 -27
- package/libs/africanies-ui/src/lib/forms/checkbox/checkbox.component.ts +2 -1
- package/libs/africanies-ui/src/lib/forms/file-upload/file-preview.dialog.ts +1 -1
- package/libs/africanies-ui/src/lib/forms/file-upload/file-upload.component.ts +1 -1
- package/libs/africanies-ui/src/lib/forms/form-field.classes.ts +36 -6
- package/libs/africanies-ui/src/lib/forms/otp-input/otp-input.component.ts +2 -1
- package/libs/africanies-ui/src/lib/forms/radio/radio.component.ts +2 -1
- package/libs/africanies-ui/src/lib/forms/select/select.component.ts +1 -1
- package/libs/africanies-ui/src/lib/forms/toggle/toggle.component.ts +1 -1
- package/libs/africanies-ui/src/lib/image/image.component.ts +1 -1
- package/libs/africanies-ui/src/lib/info-popover/info-popover.component.ts +2 -2
- package/libs/africanies-ui/src/lib/layout/app-shell-content-header.component.ts +1 -1
- package/libs/africanies-ui/src/lib/layout/app-shell-header.component.ts +14 -14
- package/libs/africanies-ui/src/lib/layout/app-shell.component.html +2 -2
- package/libs/africanies-ui/src/lib/layout/app-shell.component.ts +3 -3
- package/libs/africanies-ui/src/lib/layout/header-greeting.util.ts +0 -2
- package/libs/africanies-ui/src/lib/layout/header-weather.spec.ts +11 -40
- package/libs/africanies-ui/src/lib/layout/header-weather.ts +22 -63
- package/libs/africanies-ui/src/lib/navigation/shipping-mode-switch/shipping-mode-switch.component.ts +6 -6
- package/libs/africanies-ui/src/lib/navigation/side-nav/africanies-side-nav.component.html +21 -13
- package/libs/africanies-ui/src/lib/navigation/side-nav/africanies-side-nav.component.ts +13 -7
- package/libs/africanies-ui/src/lib/notifications/notification-drawer.panel.ts +6 -6
- package/libs/africanies-ui/src/lib/overlay/confirm-dialog.component.ts +2 -2
- package/libs/africanies-ui/src/lib/overlay/drawer.service.ts +2 -2
- package/libs/africanies-ui/src/lib/overlay/modal.service.ts +3 -3
- package/libs/africanies-ui/src/lib/overlay/overlay-frame.component.ts +1 -1
- package/libs/africanies-ui/src/lib/pagination/pagination.component.ts +1 -1
- package/libs/africanies-ui/src/lib/stepper/stepper.component.ts +7 -7
- package/libs/africanies-ui/src/lib/table/table-column.ts +9 -0
- package/libs/africanies-ui/src/lib/table/table.component.spec.ts +99 -0
- package/libs/africanies-ui/src/lib/table/table.component.ts +72 -30
- package/libs/africanies-ui/src/lib/toast/toast-item.component.ts +6 -6
- package/package.json +1 -1
- package/svg/hand-coins.svg +9 -0
- package/.nx/cache/12276756491762927325/dist/libs/africanies-theme/fesm2022/africanies-africanies-theme.mjs.map +0 -1
- package/.nx/cache/17491371155400585077/dist/libs/africanies-core/fesm2022/africanies-africanies-core.mjs.map +0 -1
- package/.nx/cache/17499961385238663835/dist/libs/africanies-ui/fesm2022/africanies-africanies-ui.mjs.map +0 -1
- package/.nx/cache/3314955264390318442/dist/libs/africanies-ui/fesm2022/africanies-africanies-ui.mjs.map +0 -1
- package/.nx/cache/4082520855419352840/dist/libs/africanies-theme/fesm2022/africanies-africanies-theme.mjs.map +0 -1
- package/.nx/cache/terminalOutputs/17499961385238663835 +0 -21
- /package/.nx/cache/{12276756491762927325 → 15302120112746851896}/dist/libs/africanies-theme/README.md +0 -0
- /package/.nx/cache/{12276756491762927325 → 15302120112746851896}/dist/libs/africanies-theme/package.json +0 -0
- /package/.nx/cache/{17491371155400585077 → 17289624717336768573}/dist/libs/africanies-core/README.md +0 -0
- /package/.nx/cache/{17491371155400585077 → 17289624717336768573}/dist/libs/africanies-core/package.json +0 -0
- /package/.nx/cache/{17499961385238663835 → 3953970051755345887}/dist/libs/africanies-ui/README.md +0 -0
- /package/.nx/cache/{17499961385238663835 → 3953970051755345887}/dist/libs/africanies-ui/assets/brand/africanies-logo-mini.png +0 -0
- /package/.nx/cache/{17499961385238663835 → 3953970051755345887}/dist/libs/africanies-ui/assets/brand/africanies-logo.png +0 -0
- /package/.nx/cache/{17499961385238663835 → 3953970051755345887}/dist/libs/africanies-ui/assets/brand/africanies-logo.svg +0 -0
- /package/.nx/cache/{17499961385238663835 → 3953970051755345887}/dist/libs/africanies-ui/assets/carriers/dhl.svg +0 -0
- /package/.nx/cache/{17499961385238663835 → 3953970051755345887}/dist/libs/africanies-ui/package.json +0 -0
- /package/.nx/cache/{4082520855419352840 → 4225324930345532464}/dist/libs/africanies-theme/README.md +0 -0
- /package/.nx/cache/{4082520855419352840 → 4225324930345532464}/dist/libs/africanies-theme/package.json +0 -0
- /package/.nx/cache/{3314955264390318442 → 9406544675747598148}/dist/libs/africanies-ui/README.md +0 -0
- /package/.nx/cache/{3314955264390318442 → 9406544675747598148}/dist/libs/africanies-ui/assets/brand/africanies-logo-mini.png +0 -0
- /package/.nx/cache/{3314955264390318442 → 9406544675747598148}/dist/libs/africanies-ui/assets/brand/africanies-logo.png +0 -0
- /package/.nx/cache/{3314955264390318442 → 9406544675747598148}/dist/libs/africanies-ui/assets/brand/africanies-logo.svg +0 -0
- /package/.nx/cache/{3314955264390318442 → 9406544675747598148}/dist/libs/africanies-ui/assets/carriers/dhl.svg +0 -0
- /package/.nx/cache/{3314955264390318442 → 9406544675747598148}/dist/libs/africanies-ui/package.json +0 -0
- /package/.nx/cache/terminalOutputs/{16279119293212733518 → 14005735098959303198} +0 -0
|
@@ -2,15 +2,12 @@ import type { IconName } from '@africanies/africanies-icons';
|
|
|
2
2
|
|
|
3
3
|
import type { HeaderWeather, HeaderWeatherKind } from './header-greeting.util';
|
|
4
4
|
|
|
5
|
-
/** Bump when cache shape or
|
|
6
|
-
const CACHE_KEY = 'africanies-header-weather-
|
|
5
|
+
/** Bump when cache shape or lookup strategy changes. */
|
|
6
|
+
const CACHE_KEY = 'africanies-header-weather-v5';
|
|
7
7
|
const FETCH_MS = 4_000;
|
|
8
8
|
const BROWSER_GEO_MS = 3_500;
|
|
9
|
-
/** IP fallback — city
|
|
9
|
+
/** IP fallback for coordinates only — city strings are often wrong. */
|
|
10
10
|
const GEO_URL = 'https://get.geojs.io/v1/ip/geo.json';
|
|
11
|
-
/** Client reverse-geocode so the label matches the forecast coordinates. */
|
|
12
|
-
const REVERSE_GEO_URL =
|
|
13
|
-
'https://api.bigdatacloud.net/data/reverse-geocode-client';
|
|
14
11
|
|
|
15
12
|
const WEATHER_LABELS: Record<HeaderWeatherKind, string> = {
|
|
16
13
|
clear: 'Clear',
|
|
@@ -26,21 +23,13 @@ interface CachedWeather {
|
|
|
26
23
|
hour: string;
|
|
27
24
|
kind: HeaderWeatherKind;
|
|
28
25
|
temperatureC?: number;
|
|
29
|
-
city?: string;
|
|
30
26
|
}
|
|
31
27
|
|
|
32
28
|
interface GeoJsPayload {
|
|
33
|
-
city?: string;
|
|
34
29
|
latitude?: string | number;
|
|
35
30
|
longitude?: string | number;
|
|
36
31
|
}
|
|
37
32
|
|
|
38
|
-
interface ReverseGeoPayload {
|
|
39
|
-
city?: string;
|
|
40
|
-
locality?: string;
|
|
41
|
-
principalSubdivision?: string;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
33
|
interface OpenMeteoPayload {
|
|
45
34
|
current?: {
|
|
46
35
|
weather_code?: number;
|
|
@@ -88,9 +77,16 @@ export function mapWmoWeatherCode(code: number): HeaderWeatherKind | null {
|
|
|
88
77
|
* Short condition label for the header weather chip.
|
|
89
78
|
*
|
|
90
79
|
* @param kind - Coarse forecast kind.
|
|
91
|
-
* @
|
|
80
|
+
* @param hour - Local hour; clear days show as Sunny, nights as Clear.
|
|
81
|
+
* @returns Display label such as `Rain` or `Sunny`.
|
|
92
82
|
*/
|
|
93
|
-
export function headerWeatherLabel(
|
|
83
|
+
export function headerWeatherLabel(
|
|
84
|
+
kind: HeaderWeatherKind,
|
|
85
|
+
hour = new Date().getHours(),
|
|
86
|
+
): string {
|
|
87
|
+
if (kind === 'clear') {
|
|
88
|
+
return hour >= 19 || hour < 6 ? 'Clear' : 'Sunny';
|
|
89
|
+
}
|
|
94
90
|
return WEATHER_LABELS[kind];
|
|
95
91
|
}
|
|
96
92
|
|
|
@@ -112,12 +108,12 @@ export function headerWeatherIcon(kind: HeaderWeatherKind, hour: number): IconNa
|
|
|
112
108
|
}
|
|
113
109
|
|
|
114
110
|
/**
|
|
115
|
-
*
|
|
111
|
+
* Local forecast via browser / IP coordinates + Open-Meteo (no API key).
|
|
116
112
|
*
|
|
117
|
-
* Coordinates prefer the browser Geolocation API (
|
|
118
|
-
*
|
|
119
|
-
*
|
|
120
|
-
*
|
|
113
|
+
* Coordinates prefer the browser Geolocation API (may prompt once).
|
|
114
|
+
* Otherwise IP geo is used for lat/lon only — city labels are not shown
|
|
115
|
+
* because IP and reverse-geocode cities are often wrong (e.g. NG IPs
|
|
116
|
+
* labelled Lagos).
|
|
121
117
|
*
|
|
122
118
|
* Fails closed: missing browser APIs, timeouts, and HTTP errors all return
|
|
123
119
|
* `null` so the greeting can stay time-of-day only. Cached per local hour
|
|
@@ -162,11 +158,8 @@ export async function loadHeaderWeather(
|
|
|
162
158
|
}
|
|
163
159
|
|
|
164
160
|
const temperatureC = asNumber(forecast?.current?.temperature_2m) ?? undefined;
|
|
165
|
-
const
|
|
166
|
-
|
|
167
|
-
coords.fallbackCity;
|
|
168
|
-
const weather: HeaderWeather = { kind, temperatureC, city };
|
|
169
|
-
writeCache({ hour, kind, temperatureC, city });
|
|
161
|
+
const weather: HeaderWeather = { kind, temperatureC };
|
|
162
|
+
writeCache({ hour, kind, temperatureC });
|
|
170
163
|
return weather;
|
|
171
164
|
} catch {
|
|
172
165
|
return null;
|
|
@@ -194,7 +187,6 @@ function readCache(hour: string): HeaderWeather | null {
|
|
|
194
187
|
return {
|
|
195
188
|
kind: parsed.kind,
|
|
196
189
|
temperatureC: parsed.temperatureC,
|
|
197
|
-
city: parsed.city,
|
|
198
190
|
};
|
|
199
191
|
} catch {
|
|
200
192
|
return null;
|
|
@@ -211,12 +203,11 @@ function writeCache(value: CachedWeather): void {
|
|
|
211
203
|
|
|
212
204
|
/**
|
|
213
205
|
* Prefer device coordinates when available (may prompt once); otherwise fall
|
|
214
|
-
* back to IP
|
|
215
|
-
* geocoding from these coordinates still depends on accurate lat/lon.
|
|
206
|
+
* back to IP lat/lon for the forecast only.
|
|
216
207
|
*/
|
|
217
208
|
async function resolveCoordinates(
|
|
218
209
|
fetchFn: typeof fetch,
|
|
219
|
-
): Promise<
|
|
210
|
+
): Promise<Coordinates | null> {
|
|
220
211
|
const browser = await tryBrowserGeolocation();
|
|
221
212
|
if (browser) {
|
|
222
213
|
return browser;
|
|
@@ -228,11 +219,7 @@ async function resolveCoordinates(
|
|
|
228
219
|
if (latitude === null || longitude === null) {
|
|
229
220
|
return null;
|
|
230
221
|
}
|
|
231
|
-
return {
|
|
232
|
-
latitude,
|
|
233
|
-
longitude,
|
|
234
|
-
fallbackCity: asCity(geo?.city),
|
|
235
|
-
};
|
|
222
|
+
return { latitude, longitude };
|
|
236
223
|
}
|
|
237
224
|
|
|
238
225
|
async function tryBrowserGeolocation(): Promise<Coordinates | null> {
|
|
@@ -266,23 +253,6 @@ async function tryBrowserGeolocation(): Promise<Coordinates | null> {
|
|
|
266
253
|
});
|
|
267
254
|
}
|
|
268
255
|
|
|
269
|
-
async function reverseGeocodeCity(
|
|
270
|
-
fetchFn: typeof fetch,
|
|
271
|
-
latitude: number,
|
|
272
|
-
longitude: number,
|
|
273
|
-
): Promise<string | undefined> {
|
|
274
|
-
const url =
|
|
275
|
-
`${REVERSE_GEO_URL}?latitude=${encodeURIComponent(String(latitude))}` +
|
|
276
|
-
`&longitude=${encodeURIComponent(String(longitude))}` +
|
|
277
|
-
`&localityLanguage=en`;
|
|
278
|
-
const payload = (await fetchJson(fetchFn, url)) as ReverseGeoPayload | null;
|
|
279
|
-
return (
|
|
280
|
-
asCity(payload?.city) ??
|
|
281
|
-
asCity(payload?.locality) ??
|
|
282
|
-
asCity(payload?.principalSubdivision)
|
|
283
|
-
);
|
|
284
|
-
}
|
|
285
|
-
|
|
286
256
|
function asNumber(value: unknown): number | null {
|
|
287
257
|
if (typeof value === 'number' && Number.isFinite(value)) {
|
|
288
258
|
return value;
|
|
@@ -294,17 +264,6 @@ function asNumber(value: unknown): number | null {
|
|
|
294
264
|
return null;
|
|
295
265
|
}
|
|
296
266
|
|
|
297
|
-
function asCity(value: unknown): string | undefined {
|
|
298
|
-
if (typeof value !== 'string') {
|
|
299
|
-
return undefined;
|
|
300
|
-
}
|
|
301
|
-
const trimmed = value.trim();
|
|
302
|
-
if (!trimmed || trimmed.toLowerCase() === 'n/a') {
|
|
303
|
-
return undefined;
|
|
304
|
-
}
|
|
305
|
-
return trimmed;
|
|
306
|
-
}
|
|
307
|
-
|
|
308
267
|
async function fetchJson(
|
|
309
268
|
fetchFn: typeof fetch,
|
|
310
269
|
url: string,
|
package/libs/africanies-ui/src/lib/navigation/shipping-mode-switch/shipping-mode-switch.component.ts
CHANGED
|
@@ -131,8 +131,8 @@ export class ShippingModeSwitchComponent {
|
|
|
131
131
|
/** Host padding / divider — tighter when the rail is collapsed. */
|
|
132
132
|
protected readonly hostClass = computed(() =>
|
|
133
133
|
this.collapsed()
|
|
134
|
-
? 'block shrink-0 border-t border-
|
|
135
|
-
: 'block shrink-0 border-t border-
|
|
134
|
+
? 'block shrink-0 border-t border-border px-1.5 py-3 dark:border-white/10'
|
|
135
|
+
: 'block shrink-0 border-t border-border px-2 py-3 dark:border-white/10',
|
|
136
136
|
);
|
|
137
137
|
|
|
138
138
|
/**
|
|
@@ -159,18 +159,18 @@ export class ShippingModeSwitchComponent {
|
|
|
159
159
|
const compact = this.collapsed();
|
|
160
160
|
const base =
|
|
161
161
|
'flex w-full cursor-pointer flex-col items-center justify-center gap-1 rounded-lg border text-center text-caption font-medium transition-colors ' +
|
|
162
|
-
'focus-visible:outline focus-visible:
|
|
162
|
+
'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-focus ' +
|
|
163
163
|
(compact ? 'min-h-9 px-1 py-1.5' : 'min-h-[4.5rem] px-1.5 py-2');
|
|
164
164
|
const idle =
|
|
165
|
-
'border-
|
|
165
|
+
'border-control bg-surface text-ink hover:bg-background-hover dark:border-white/15 dark:bg-ink-950 dark:text-white dark:hover:bg-white/10';
|
|
166
166
|
|
|
167
167
|
if (option === 'stn') {
|
|
168
168
|
return selected
|
|
169
|
-
? `${base} border-import bg-import text-white`
|
|
169
|
+
? `${base} border-import-strong bg-import-strong text-white dark:border-import dark:bg-import`
|
|
170
170
|
: `${base} ${idle}`;
|
|
171
171
|
}
|
|
172
172
|
return selected
|
|
173
|
-
? `${base} border-export bg-export text-white`
|
|
173
|
+
? `${base} border-export-strong bg-export-strong text-white dark:border-export dark:bg-export`
|
|
174
174
|
: `${base} ${idle}`;
|
|
175
175
|
}
|
|
176
176
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<aside
|
|
2
|
-
class="relative flex h-full flex-col overflow-visible border-r border-border bg-
|
|
2
|
+
class="relative flex h-full min-h-0 flex-col overflow-visible border-r border-border bg-surface transition-[width] duration-200 ease-out dark:border-white/10 dark:bg-ink-950"
|
|
3
3
|
[style.width]="collapsed() ? '3.75rem' : '15rem'"
|
|
4
4
|
[attr.aria-label]="ariaLabel()"
|
|
5
5
|
>
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
></div>
|
|
11
11
|
|
|
12
12
|
<div
|
|
13
|
-
class="flex shrink-0 items-center gap-2 border-b border-border py-3 dark:border-white/10"
|
|
13
|
+
class="sticky top-0 z-20 flex shrink-0 items-center gap-2 border-b border-border bg-surface py-3 dark:border-white/10 dark:bg-ink-950"
|
|
14
14
|
[class.flex-col]="collapsed()"
|
|
15
15
|
[class.px-3]="collapsed()"
|
|
16
16
|
[class.pl-4]="!collapsed()"
|
|
@@ -43,7 +43,8 @@
|
|
|
43
43
|
}
|
|
44
44
|
<button
|
|
45
45
|
type="button"
|
|
46
|
-
class="inline-flex size-8 shrink-0 cursor-pointer items-center justify-center rounded-md text-neutral-600 transition-colors hover:bg-background-
|
|
46
|
+
class="inline-flex size-8 shrink-0 cursor-pointer items-center justify-center rounded-md text-neutral-600 transition-colors hover:bg-background-hover hover:text-ink focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-focus dark:text-neutral-400 dark:hover:bg-white/10 dark:hover:text-white"
|
|
47
|
+
data-onboarding="nav-collapse"
|
|
47
48
|
[attr.aria-label]="
|
|
48
49
|
collapsed() ? 'Expand navigation' : 'Collapse navigation'
|
|
49
50
|
"
|
|
@@ -57,21 +58,28 @@
|
|
|
57
58
|
</button>
|
|
58
59
|
</div>
|
|
59
60
|
|
|
60
|
-
<nav
|
|
61
|
+
<nav
|
|
62
|
+
class="africanies-overlay-scroll relative min-h-0 flex-1 overflow-y-auto overflow-x-visible px-3 py-3"
|
|
63
|
+
>
|
|
61
64
|
@if (!collapsed() && expandParents() && hasOpenBranches()) {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
65
|
+
<!-- Zero-height sticky host: keeps the control pinned without reserving a row. -->
|
|
66
|
+
<div class="sticky top-0 z-10 h-0 overflow-visible">
|
|
67
|
+
<button
|
|
68
|
+
type="button"
|
|
69
|
+
class="absolute right-0 top-0 inline-flex size-7 cursor-pointer items-center justify-center rounded-md bg-surface text-neutral-600 shadow-sm ring-1 ring-border-strong transition-colors hover:bg-background-hover hover:text-ink focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-focus dark:bg-ink-950 dark:text-neutral-400 dark:ring-white/15 dark:hover:bg-white/10 dark:hover:text-white"
|
|
70
|
+
data-onboarding="nav-branches-collapse"
|
|
71
|
+
aria-label="Collapse all"
|
|
72
|
+
(click)="collapseAllBranches()"
|
|
73
|
+
>
|
|
74
|
+
<africanies-icon name="compress" [size]="14" />
|
|
75
|
+
</button>
|
|
76
|
+
</div>
|
|
70
77
|
}
|
|
71
78
|
<ul class="m-0 flex list-none flex-col gap-0.5 p-0">
|
|
72
79
|
@for (item of items(); track item.id) {
|
|
73
80
|
<li
|
|
74
|
-
class="relative overflow-visible"
|
|
81
|
+
class="relative overflow-visible last:mb-0"
|
|
82
|
+
[class.mb-3]="!collapsed() && !item.children?.length"
|
|
75
83
|
(mouseenter)="onItemEnter(item.id)"
|
|
76
84
|
(mouseleave)="onItemLeave(item.id)"
|
|
77
85
|
>
|
|
@@ -46,7 +46,8 @@ const DEFAULT_LINK_ACTIVE: IsActiveMatchOptions = {
|
|
|
46
46
|
* ## Parent items with children
|
|
47
47
|
* **Expanded rail:** branches start open by default (`expandBranchesByDefault`).
|
|
48
48
|
* Clicking a parent only opens/closes the branch (no route change). When any
|
|
49
|
-
* branch is open, a collapse-all control sits above the list (top right).
|
|
49
|
+
* branch is open, a sticky collapse-all control sits above the list (top right).
|
|
50
|
+
* The rail expand/collapse control stays pinned in the logo header.
|
|
50
51
|
* **Collapsed rail:** clicking a parent expands the rail, opens the
|
|
51
52
|
* branch, and activates the first enabled child (router or `activeId`).
|
|
52
53
|
*
|
|
@@ -73,7 +74,7 @@ const DEFAULT_LINK_ACTIVE: IsActiveMatchOptions = {
|
|
|
73
74
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
74
75
|
imports: [AfricaniesIconComponent, RouterLink, NgTemplateOutlet],
|
|
75
76
|
host: {
|
|
76
|
-
class: 'relative z-20 block h-full',
|
|
77
|
+
class: 'relative z-20 block h-full min-h-0',
|
|
77
78
|
},
|
|
78
79
|
styleUrl: './africanies-side-nav.component.css',
|
|
79
80
|
templateUrl: './africanies-side-nav.component.html',
|
|
@@ -197,10 +198,15 @@ export class SideNavComponent {
|
|
|
197
198
|
}
|
|
198
199
|
|
|
199
200
|
/** Fold every parent branch on the expanded rail. */
|
|
200
|
-
|
|
201
|
+
collapseAllBranches(): void {
|
|
201
202
|
this.openBranches.set(new Set());
|
|
202
203
|
}
|
|
203
204
|
|
|
205
|
+
/** Open every parent branch (e.g. so the collapse-all control is visible). */
|
|
206
|
+
expandAllBranches(): void {
|
|
207
|
+
this.openBranches.set(new Set(this.collectParentIds(this.items())));
|
|
208
|
+
}
|
|
209
|
+
|
|
204
210
|
protected onItemEnter(id: string): void {
|
|
205
211
|
if (this.collapsed()) {
|
|
206
212
|
this.hoverId.set(id);
|
|
@@ -239,7 +245,7 @@ export class SideNavComponent {
|
|
|
239
245
|
protected rowClass(item: AfricaniesSideNavItem): string {
|
|
240
246
|
const base =
|
|
241
247
|
'group relative flex w-full items-center gap-2 rounded-lg text-body-sm no-underline transition-colors ' +
|
|
242
|
-
'focus-visible:outline focus-visible:
|
|
248
|
+
'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-focus ' +
|
|
243
249
|
(this.collapsed() ? 'justify-center px-1.5 py-2' : 'px-3 py-2') +
|
|
244
250
|
(item.disabled ? ' cursor-not-allowed opacity-50' : ' cursor-pointer');
|
|
245
251
|
|
|
@@ -256,7 +262,7 @@ export class SideNavComponent {
|
|
|
256
262
|
return `${base} bg-transparent ${colors.text} font-semibold`;
|
|
257
263
|
}
|
|
258
264
|
return (
|
|
259
|
-
`${base} font-medium text-neutral-600 hover:bg-background-
|
|
265
|
+
`${base} font-medium text-neutral-600 hover:bg-background-hover hover:text-ink ` +
|
|
260
266
|
'dark:text-neutral-400 dark:hover:bg-white/10 dark:hover:text-white'
|
|
261
267
|
);
|
|
262
268
|
}
|
|
@@ -264,14 +270,14 @@ export class SideNavComponent {
|
|
|
264
270
|
protected childRowClass(item: AfricaniesSideNavItem): string {
|
|
265
271
|
const base =
|
|
266
272
|
'relative flex w-full items-center gap-2 rounded-lg px-3 py-1.5 text-body-sm no-underline transition-colors ' +
|
|
267
|
-
'focus-visible:outline focus-visible:
|
|
273
|
+
'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-focus ' +
|
|
268
274
|
(item.disabled ? 'cursor-not-allowed opacity-50 ' : 'cursor-pointer ');
|
|
269
275
|
|
|
270
276
|
if (this.isLeafActive(item)) {
|
|
271
277
|
return `${base} ${this.modeColor.classes().activeFill} font-semibold`;
|
|
272
278
|
}
|
|
273
279
|
return (
|
|
274
|
-
`${base} font-medium text-neutral-600 hover:bg-background-
|
|
280
|
+
`${base} font-medium text-neutral-600 hover:bg-background-hover hover:text-ink ` +
|
|
275
281
|
'dark:text-neutral-400 dark:hover:bg-white/10 dark:hover:text-white'
|
|
276
282
|
);
|
|
277
283
|
}
|
|
@@ -66,7 +66,7 @@ const MARK_ALL_CONFIRM_MS = 4000;
|
|
|
66
66
|
{{ title() }}
|
|
67
67
|
</h2>
|
|
68
68
|
@if (hasUnread()) {
|
|
69
|
-
<p class="m-0 text-caption text-neutral-
|
|
69
|
+
<p class="m-0 text-caption text-neutral-600 dark:text-neutral-400">
|
|
70
70
|
{{ unreadCount() }} unread
|
|
71
71
|
</p>
|
|
72
72
|
}
|
|
@@ -112,7 +112,7 @@ const MARK_ALL_CONFIRM_MS = 4000;
|
|
|
112
112
|
<africanies-icon
|
|
113
113
|
name="spinner"
|
|
114
114
|
[size]="24"
|
|
115
|
-
class="animate-spin text-neutral-
|
|
115
|
+
class="animate-spin text-neutral-600 dark:text-neutral-400"
|
|
116
116
|
/>
|
|
117
117
|
<p class="m-0 text-body-sm text-neutral-600 dark:text-neutral-400">
|
|
118
118
|
Loading notifications…
|
|
@@ -179,7 +179,7 @@ const MARK_ALL_CONFIRM_MS = 4000;
|
|
|
179
179
|
</h3>
|
|
180
180
|
@if (item.timestamp) {
|
|
181
181
|
<time
|
|
182
|
-
class="shrink-0 whitespace-nowrap text-[11px] tabular-nums text-neutral-
|
|
182
|
+
class="shrink-0 whitespace-nowrap text-[11px] tabular-nums text-neutral-600 dark:text-neutral-400"
|
|
183
183
|
[dateTime]="item.timestamp"
|
|
184
184
|
>
|
|
185
185
|
{{ formatTimestamp(item.timestamp) }}
|
|
@@ -258,7 +258,7 @@ const MARK_ALL_CONFIRM_MS = 4000;
|
|
|
258
258
|
>
|
|
259
259
|
@if (loadingMore()) {
|
|
260
260
|
<span
|
|
261
|
-
class="inline-flex items-center gap-2 text-caption text-neutral-
|
|
261
|
+
class="inline-flex items-center gap-2 text-caption text-neutral-600 dark:text-neutral-400"
|
|
262
262
|
aria-live="polite"
|
|
263
263
|
>
|
|
264
264
|
<africanies-icon name="spinner" [size]="14" class="animate-spin" />
|
|
@@ -290,9 +290,9 @@ export class NotificationDrawerPanel {
|
|
|
290
290
|
const base =
|
|
291
291
|
'inline-flex cursor-pointer items-center gap-1 self-start text-caption font-semibold underline underline-offset-[3px] transition-colors';
|
|
292
292
|
if (this.shipping.mode() === 'stn') {
|
|
293
|
-
return `${base} text-import decoration-import/35 hover:decoration-import dark:text-import-light dark:decoration-import-light/40 dark:hover:decoration-import-light`;
|
|
293
|
+
return `${base} text-import-strong decoration-import-strong/35 hover:decoration-import-strong dark:text-import-light dark:decoration-import-light/40 dark:hover:decoration-import-light`;
|
|
294
294
|
}
|
|
295
|
-
return `${base} text-export decoration-export/35 hover:decoration-export dark:text-export-light dark:decoration-export-light/40 dark:hover:decoration-export-light`;
|
|
295
|
+
return `${base} text-export-strong decoration-export-strong/35 hover:decoration-export-strong dark:text-export-light dark:decoration-export-light/40 dark:hover:decoration-export-light`;
|
|
296
296
|
});
|
|
297
297
|
|
|
298
298
|
protected readonly title = computed(() => this.data.title ?? 'Notifications');
|
|
@@ -161,8 +161,8 @@ export class ConfirmDialogComponent {
|
|
|
161
161
|
const well =
|
|
162
162
|
'inline-flex size-14 shrink-0 items-center justify-center rounded-2xl';
|
|
163
163
|
return this.options.danger
|
|
164
|
-
? `${well} bg-danger-subtle text-danger dark:bg-danger/20 dark:text-danger`
|
|
165
|
-
: `${well} bg-export-subtle text-export dark:bg-export/20 dark:text-export-light`;
|
|
164
|
+
? `${well} bg-danger-subtle text-danger-dark dark:bg-danger/20 dark:text-danger`
|
|
165
|
+
: `${well} bg-export-subtle text-export-strong dark:bg-export/20 dark:text-export-light`;
|
|
166
166
|
});
|
|
167
167
|
|
|
168
168
|
constructor() {
|
|
@@ -63,11 +63,11 @@ export class DrawerService implements OverlayOpener {
|
|
|
63
63
|
],
|
|
64
64
|
panelClass: [
|
|
65
65
|
'africanies-drawer-panel',
|
|
66
|
-
'bg-
|
|
66
|
+
'bg-surface',
|
|
67
67
|
'dark:bg-ink-950',
|
|
68
68
|
'text-ink',
|
|
69
69
|
'dark:text-white',
|
|
70
|
-
'shadow-
|
|
70
|
+
'shadow-floating',
|
|
71
71
|
'border-l',
|
|
72
72
|
'border-border',
|
|
73
73
|
'dark:border-white/15',
|
|
@@ -151,12 +151,12 @@ export class ModalService implements OverlayOpener {
|
|
|
151
151
|
],
|
|
152
152
|
panelClass: [
|
|
153
153
|
'africanies-modal-panel',
|
|
154
|
-
'bg-
|
|
154
|
+
'bg-surface',
|
|
155
155
|
'dark:bg-ink-950',
|
|
156
156
|
'text-ink',
|
|
157
157
|
'dark:text-white',
|
|
158
|
-
'rounded-
|
|
159
|
-
'shadow-
|
|
158
|
+
'rounded-panel',
|
|
159
|
+
'shadow-floating',
|
|
160
160
|
'border',
|
|
161
161
|
'border-border',
|
|
162
162
|
'dark:border-white/15',
|
|
@@ -83,7 +83,7 @@ export class OverlayFooterDirective {}
|
|
|
83
83
|
<ng-content select="[africaniesOverlayHeader]" />
|
|
84
84
|
</div>
|
|
85
85
|
<div
|
|
86
|
-
class="africanies-overlay-scroll min-h-0 flex-1 overflow-x-clip overflow-y-auto px-
|
|
86
|
+
class="africanies-overlay-scroll min-h-0 flex-1 overflow-x-clip overflow-y-auto px-1 -mx-1"
|
|
87
87
|
>
|
|
88
88
|
<ng-content />
|
|
89
89
|
</div>
|
|
@@ -144,7 +144,7 @@ type PageItem = number | 'ellipsis';
|
|
|
144
144
|
@for (item of pageItems(); track trackPageItem(item, $index)) {
|
|
145
145
|
@if (item === 'ellipsis') {
|
|
146
146
|
<span
|
|
147
|
-
class="inline-flex min-w-8 items-center justify-center text-body-sm text-neutral-
|
|
147
|
+
class="inline-flex min-w-8 items-center justify-center text-body-sm text-neutral-600 dark:text-neutral-400"
|
|
148
148
|
aria-hidden="true"
|
|
149
149
|
>
|
|
150
150
|
…
|
|
@@ -53,9 +53,9 @@ function prefersReducedMotion(): boolean {
|
|
|
53
53
|
.africanies-step-body {
|
|
54
54
|
min-width: 0;
|
|
55
55
|
overflow-x: clip;
|
|
56
|
-
/*
|
|
57
|
-
padding-inline:
|
|
58
|
-
margin-inline: -
|
|
56
|
+
/* 4 px breathing room so any remaining external focus rings are not clipped */
|
|
57
|
+
padding-inline: 4px;
|
|
58
|
+
margin-inline: -4px;
|
|
59
59
|
}
|
|
60
60
|
.africanies-step-pane {
|
|
61
61
|
min-width: 0;
|
|
@@ -66,7 +66,7 @@ function prefersReducedMotion(): boolean {
|
|
|
66
66
|
<div class="flex flex-col gap-5 text-ink dark:text-white">
|
|
67
67
|
<div class="flex flex-col gap-2">
|
|
68
68
|
<p
|
|
69
|
-
class="m-0 text-caption font-medium uppercase tracking-wide text-neutral-
|
|
69
|
+
class="m-0 text-caption font-medium uppercase tracking-wide text-neutral-600 dark:text-neutral-400"
|
|
70
70
|
>
|
|
71
71
|
Step {{ activeIndex() + 1 }} of {{ steps().length }}
|
|
72
72
|
<span
|
|
@@ -95,7 +95,7 @@ function prefersReducedMotion(): boolean {
|
|
|
95
95
|
<li class="flex min-w-0 shrink-0 items-center gap-1">
|
|
96
96
|
<button
|
|
97
97
|
type="button"
|
|
98
|
-
class="inline-flex max-w-38 items-center gap-2 rounded-lg px-2 py-1.5 text-left transition-colors focus-visible:outline-
|
|
98
|
+
class="inline-flex max-w-38 items-center gap-2 rounded-lg px-2 py-1.5 text-left transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ink disabled:cursor-not-allowed"
|
|
99
99
|
[class]="headerButtonClass(i)"
|
|
100
100
|
[attr.aria-current]="i === activeIndex() ? 'step' : null"
|
|
101
101
|
[disabled]="!canActivate(i)"
|
|
@@ -223,7 +223,7 @@ export class StepperComponent {
|
|
|
223
223
|
if (past) {
|
|
224
224
|
return 'cursor-pointer text-ink hover:bg-background-welcome dark:text-white dark:hover:bg-white/10';
|
|
225
225
|
}
|
|
226
|
-
return 'opacity-40 text-neutral-
|
|
226
|
+
return 'opacity-40 text-neutral-600 dark:text-neutral-400';
|
|
227
227
|
}
|
|
228
228
|
|
|
229
229
|
protected stepBadgeClass(index: number): string {
|
|
@@ -233,7 +233,7 @@ export class StepperComponent {
|
|
|
233
233
|
const c = this.modeColor.classes();
|
|
234
234
|
return `${base} ${c.border} ${c.bg} text-white`;
|
|
235
235
|
}
|
|
236
|
-
return `${base} border-
|
|
236
|
+
return `${base} border-control bg-surface text-neutral-600 dark:border-white/20 dark:bg-ink-950 dark:text-neutral-400`;
|
|
237
237
|
}
|
|
238
238
|
|
|
239
239
|
protected canActivate(index: number): boolean {
|
|
@@ -34,6 +34,15 @@ export interface TableColumn<T = unknown> {
|
|
|
34
34
|
*/
|
|
35
35
|
width?: string;
|
|
36
36
|
|
|
37
|
+
/**
|
|
38
|
+
* Optional CSS max-width (e.g. `'14rem'`).
|
|
39
|
+
*
|
|
40
|
+
* Caps growth for text-heavy columns without forcing a large minimum the
|
|
41
|
+
* way {@link width} can. Prefer this for Name / Description / Message when
|
|
42
|
+
* other columns should stay compact.
|
|
43
|
+
*/
|
|
44
|
+
maxWidth?: string;
|
|
45
|
+
|
|
37
46
|
/**
|
|
38
47
|
* Pin the column while the table scrolls horizontally.
|
|
39
48
|
*
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { Component, signal } from '@angular/core';
|
|
2
|
+
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
|
3
|
+
|
|
4
|
+
import { ShippingModeService } from '@africanies/africanies-core';
|
|
5
|
+
import type { ShippingMode } from '@africanies/africanies-models';
|
|
6
|
+
|
|
7
|
+
import { TableComponent } from './table.component';
|
|
8
|
+
import type { TableColumn } from './table-column';
|
|
9
|
+
|
|
10
|
+
interface Row {
|
|
11
|
+
id: number;
|
|
12
|
+
name: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
@Component({
|
|
16
|
+
standalone: true,
|
|
17
|
+
imports: [TableComponent],
|
|
18
|
+
template: `
|
|
19
|
+
<africanies-table
|
|
20
|
+
[columns]="columns"
|
|
21
|
+
[rows]="rows()"
|
|
22
|
+
[loading]="loading()"
|
|
23
|
+
[error]="error()"
|
|
24
|
+
loadingLabel="Loading page…"
|
|
25
|
+
/>
|
|
26
|
+
`,
|
|
27
|
+
})
|
|
28
|
+
class TableHostComponent {
|
|
29
|
+
readonly columns: TableColumn<Row>[] = [{ key: 'name', header: 'Name' }];
|
|
30
|
+
readonly rows = signal<Row[]>([]);
|
|
31
|
+
readonly loading = signal(false);
|
|
32
|
+
readonly error = signal<string | null>(null);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
describe('TableComponent keep-rows loading', () => {
|
|
36
|
+
let fixture: ComponentFixture<TableHostComponent>;
|
|
37
|
+
let host: TableHostComponent;
|
|
38
|
+
|
|
39
|
+
beforeEach(async () => {
|
|
40
|
+
const mode = signal<ShippingMode>('sfn');
|
|
41
|
+
await TestBed.configureTestingModule({
|
|
42
|
+
imports: [TableHostComponent],
|
|
43
|
+
providers: [
|
|
44
|
+
{
|
|
45
|
+
provide: ShippingModeService,
|
|
46
|
+
useValue: {
|
|
47
|
+
mode: mode.asReadonly(),
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
],
|
|
51
|
+
}).compileComponents();
|
|
52
|
+
|
|
53
|
+
fixture = TestBed.createComponent(TableHostComponent);
|
|
54
|
+
host = fixture.componentInstance;
|
|
55
|
+
fixture.detectChanges();
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
afterEach(() => {
|
|
59
|
+
fixture.destroy();
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it('shows a keep-rows overlay when loading with rows on screen', () => {
|
|
63
|
+
host.rows.set([{ id: 1, name: 'Ada' }]);
|
|
64
|
+
host.loading.set(true);
|
|
65
|
+
fixture.detectChanges();
|
|
66
|
+
|
|
67
|
+
const root = fixture.nativeElement as HTMLElement;
|
|
68
|
+
expect(
|
|
69
|
+
root.querySelector('[data-testid="africanies-table-keep-rows-loading"]'),
|
|
70
|
+
).not.toBeNull();
|
|
71
|
+
expect(root.textContent).toContain('Ada');
|
|
72
|
+
expect(root.textContent).toContain('Loading page…');
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it('uses the in-grid body loader on first load with no rows', () => {
|
|
76
|
+
host.rows.set([]);
|
|
77
|
+
host.loading.set(true);
|
|
78
|
+
fixture.detectChanges();
|
|
79
|
+
|
|
80
|
+
const root = fixture.nativeElement as HTMLElement;
|
|
81
|
+
expect(
|
|
82
|
+
root.querySelector('[data-testid="africanies-table-keep-rows-loading"]'),
|
|
83
|
+
).toBeNull();
|
|
84
|
+
expect(root.textContent).toContain('Loading page…');
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
it('shows a full-width stale error when rows remain after a failed fetch', () => {
|
|
88
|
+
host.rows.set([{ id: 1, name: 'Ada' }]);
|
|
89
|
+
host.error.set('Could not load page.');
|
|
90
|
+
fixture.detectChanges();
|
|
91
|
+
|
|
92
|
+
const root = fixture.nativeElement as HTMLElement;
|
|
93
|
+
const indicator = root.querySelector('africanies-error-indicator');
|
|
94
|
+
expect(indicator).not.toBeNull();
|
|
95
|
+
expect(indicator?.className).toContain('w-full');
|
|
96
|
+
expect(root.textContent).toContain('Could not load page.');
|
|
97
|
+
expect(root.textContent).toContain('Ada');
|
|
98
|
+
});
|
|
99
|
+
});
|