@africanies/angular-web-sdk 0.1.3 → 0.1.5
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/.nx/cache/14876618240301288353/dist/libs/africanies-ui/README.md +68 -0
- package/.nx/cache/14876618240301288353/dist/libs/africanies-ui/assets/brand/africanies-logo-mini.png +0 -0
- package/.nx/cache/14876618240301288353/dist/libs/africanies-ui/assets/brand/africanies-logo.png +0 -0
- package/.nx/cache/14876618240301288353/dist/libs/africanies-ui/assets/brand/africanies-logo.svg +5 -0
- package/.nx/cache/14876618240301288353/dist/libs/africanies-ui/assets/carriers/dhl.svg +7 -0
- package/.nx/cache/14876618240301288353/dist/libs/africanies-ui/fesm2022/africanies-africanies-ui.mjs +19375 -0
- package/.nx/cache/14876618240301288353/dist/libs/africanies-ui/fesm2022/africanies-africanies-ui.mjs.map +1 -0
- package/.nx/cache/14876618240301288353/dist/libs/africanies-ui/package.json +35 -0
- package/.nx/cache/14876618240301288353/dist/libs/africanies-ui/types/africanies-africanies-ui.d.ts +5490 -0
- package/.nx/cache/17499961385238663835/dist/libs/africanies-ui/README.md +68 -0
- package/.nx/cache/17499961385238663835/dist/libs/africanies-ui/assets/brand/africanies-logo-mini.png +0 -0
- package/.nx/cache/17499961385238663835/dist/libs/africanies-ui/assets/brand/africanies-logo.png +0 -0
- package/.nx/cache/17499961385238663835/dist/libs/africanies-ui/assets/brand/africanies-logo.svg +5 -0
- package/.nx/cache/17499961385238663835/dist/libs/africanies-ui/assets/carriers/dhl.svg +7 -0
- package/.nx/cache/17499961385238663835/dist/libs/africanies-ui/fesm2022/africanies-africanies-ui.mjs +19375 -0
- package/.nx/cache/17499961385238663835/dist/libs/africanies-ui/fesm2022/africanies-africanies-ui.mjs.map +1 -0
- package/.nx/cache/17499961385238663835/dist/libs/africanies-ui/package.json +35 -0
- package/.nx/cache/17499961385238663835/dist/libs/africanies-ui/types/africanies-africanies-ui.d.ts +5490 -0
- package/.nx/cache/17626862048742598274/dist/libs/africanies-theme/README.md +46 -0
- package/.nx/cache/17626862048742598274/dist/libs/africanies-theme/fesm2022/africanies-africanies-theme.mjs +221 -0
- package/.nx/cache/17626862048742598274/dist/libs/africanies-theme/fesm2022/africanies-africanies-theme.mjs.map +1 -0
- package/.nx/cache/17626862048742598274/dist/libs/africanies-theme/package.json +35 -0
- package/.nx/cache/17626862048742598274/dist/libs/africanies-theme/tailwind-preset.cjs +253 -0
- package/.nx/cache/17626862048742598274/dist/libs/africanies-theme/types/africanies-africanies-theme.d.ts +166 -0
- package/.nx/cache/4082520855419352840/dist/libs/africanies-theme/README.md +46 -0
- package/.nx/cache/4082520855419352840/dist/libs/africanies-theme/fesm2022/africanies-africanies-theme.mjs +221 -0
- package/.nx/cache/4082520855419352840/dist/libs/africanies-theme/fesm2022/africanies-africanies-theme.mjs.map +1 -0
- package/.nx/cache/4082520855419352840/dist/libs/africanies-theme/package.json +35 -0
- package/.nx/cache/4082520855419352840/dist/libs/africanies-theme/tailwind-preset.cjs +253 -0
- package/.nx/cache/4082520855419352840/dist/libs/africanies-theme/types/africanies-africanies-theme.d.ts +166 -0
- package/.nx/cache/9040451482998546630/dist/libs/africanies-core/README.md +85 -0
- package/.nx/cache/9040451482998546630/dist/libs/africanies-core/fesm2022/africanies-africanies-core.mjs +4511 -0
- package/.nx/cache/9040451482998546630/dist/libs/africanies-core/fesm2022/africanies-africanies-core.mjs.map +1 -0
- package/.nx/cache/9040451482998546630/dist/libs/africanies-core/package.json +31 -0
- package/.nx/cache/9040451482998546630/dist/libs/africanies-core/types/africanies-africanies-core.d.ts +2741 -0
- package/.nx/cache/run.json +35 -35
- package/.nx/cache/terminalOutputs/13555699813138069787 +6 -0
- package/.nx/cache/terminalOutputs/14061940909886036014 +173 -0
- package/.nx/cache/terminalOutputs/14876618240301288353 +21 -0
- package/.nx/cache/terminalOutputs/16279119293212733518 +6 -0
- package/.nx/cache/terminalOutputs/17499961385238663835 +21 -0
- package/.nx/cache/terminalOutputs/17626862048742598274 +21 -0
- package/.nx/cache/terminalOutputs/4082520855419352840 +21 -0
- package/.nx/cache/terminalOutputs/7126777490381568487 +32 -0
- package/.nx/cache/terminalOutputs/7978448102466861029 +32 -0
- package/.nx/cache/terminalOutputs/9040451482998546630 +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 +3155 -0
- package/.nx/workspace-data/d/server-process.json +2 -2
- package/.nx/workspace-data/file-map.json +3340 -3375
- package/.nx/workspace-data/nx_files.nxt +0 -0
- package/.nx/workspace-data/project-graph.json +2 -2
- package/apps/playground/src/app/app.routes.ts +15 -4
- package/apps/playground/src/app/app.ts +2 -2
- package/apps/playground/src/app/pages/home-page.ts +14 -14
- package/dist/libs/africanies-core/fesm2022/africanies-africanies-core.mjs +8 -43
- 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 -5
- package/dist/libs/africanies-theme/fesm2022/africanies-africanies-theme.mjs +6 -0
- package/dist/libs/africanies-theme/fesm2022/africanies-africanies-theme.mjs.map +1 -1
- package/dist/libs/africanies-theme/tailwind-preset.cjs +15 -7
- package/dist/libs/africanies-theme/types/africanies-africanies-theme.d.ts +10 -1
- package/dist/libs/africanies-ui/fesm2022/africanies-africanies-ui.mjs +138 -54
- package/dist/libs/africanies-ui/fesm2022/africanies-africanies-ui.mjs.map +1 -1
- package/dist/libs/africanies-ui/types/africanies-africanies-ui.d.ts +32 -25
- package/libs/africanies-core/src/lib/http/api-client.ts +4 -18
- package/libs/africanies-core/src/lib/http/is-retryable-get-error.ts +8 -4
- package/libs/africanies-core/src/lib/query/provide-africanies-query-defaults.ts +5 -6
- package/libs/africanies-theme/src/lib/mode-color.safelist.ts +4 -0
- package/libs/africanies-theme/src/lib/mode-color.service.ts +11 -0
- package/libs/africanies-theme/tailwind-preset.cjs +15 -7
- package/libs/africanies-ui/src/lib/layout/header-weather.spec.ts +111 -6
- package/libs/africanies-ui/src/lib/layout/header-weather.ts +104 -8
- package/libs/africanies-ui/src/lib/table/table.component.ts +67 -44
- package/package.json +1 -1
|
@@ -484,7 +484,8 @@ interface ApiRequestOptions {
|
|
|
484
484
|
* - HTTP failures rethrown as `Error` whose `.message` is already
|
|
485
485
|
* user-facing ({@link formatApiErrorMessage}) — consumers do not need to
|
|
486
486
|
* parse `HttpErrorResponse` bodies
|
|
487
|
-
* -
|
|
487
|
+
* - **No automatic retry** — fail fast so UIs can show Select / table /
|
|
488
|
+
* error-state Retry instead of a stuck loading spinner
|
|
488
489
|
* - Optional per-GET TTL cache via `cacheTtlMs`
|
|
489
490
|
*
|
|
490
491
|
* @example
|
|
@@ -1066,8 +1067,8 @@ declare function listFetchKind(options: {
|
|
|
1066
1067
|
* (no caret/tilde): TanStack marks the Angular adapter experimental and
|
|
1067
1068
|
* breaking changes land without major bumps.
|
|
1068
1069
|
*
|
|
1069
|
-
*
|
|
1070
|
-
*
|
|
1070
|
+
* Query retries default to **0** to match {@link ApiClient} (fail fast;
|
|
1071
|
+
* screens use manual Retry). Apps can override per `QueryClient` if needed.
|
|
1071
1072
|
*/
|
|
1072
1073
|
/**
|
|
1073
1074
|
* Shape compatible with TanStack `QueryClient` `defaultOptions` without
|
|
@@ -1079,9 +1080,9 @@ interface AfricaniesQueryClientDefaults {
|
|
|
1079
1080
|
staleTime: number;
|
|
1080
1081
|
/** Unused-query garbage-collection time (ms). */
|
|
1081
1082
|
gcTime: number;
|
|
1082
|
-
/** Max failed-fetch retries for queries. */
|
|
1083
|
+
/** Max failed-fetch retries for queries (default 0 — fail fast). */
|
|
1083
1084
|
retry: number;
|
|
1084
|
-
/**
|
|
1085
|
+
/** Delay between retries when {@link AfricaniesQueryClientDefaults.queries.retry} > 0. */
|
|
1085
1086
|
retryDelay: (attemptIndex: number) => number;
|
|
1086
1087
|
};
|
|
1087
1088
|
mutations: {
|
|
@@ -17,10 +17,12 @@ import { STORAGE_TOKEN, AFRICANIES_THEME_KEY } from '@africanies/africanies-stor
|
|
|
17
17
|
* SFN (export / green):
|
|
18
18
|
* text-export bg-export bg-export-subtle bg-export-light border-export
|
|
19
19
|
* 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)]
|
|
20
21
|
*
|
|
21
22
|
* STN (import / orange):
|
|
22
23
|
* text-import bg-import bg-import-subtle bg-import-light border-import
|
|
23
24
|
* 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)]
|
|
24
26
|
*/
|
|
25
27
|
const MODE_COLOR_SAFELIST = [
|
|
26
28
|
'text-export',
|
|
@@ -32,6 +34,7 @@ const MODE_COLOR_SAFELIST = [
|
|
|
32
34
|
'hover:bg-export-subtle',
|
|
33
35
|
'dark:bg-export/15',
|
|
34
36
|
'dark:hover:bg-export/15',
|
|
37
|
+
'dark:bg-[color-mix(in_srgb,#1cbd5d_15%,#212529)]',
|
|
35
38
|
'text-import',
|
|
36
39
|
'bg-import',
|
|
37
40
|
'bg-import-subtle',
|
|
@@ -41,6 +44,7 @@ const MODE_COLOR_SAFELIST = [
|
|
|
41
44
|
'hover:bg-import-subtle',
|
|
42
45
|
'dark:bg-import/15',
|
|
43
46
|
'dark:hover:bg-import/15',
|
|
47
|
+
'dark:bg-[color-mix(in_srgb,#f08829_15%,#212529)]',
|
|
44
48
|
];
|
|
45
49
|
|
|
46
50
|
/**
|
|
@@ -76,6 +80,7 @@ class ModeColorService {
|
|
|
76
80
|
primary: 'bg-export text-white border-transparent hover:bg-export-light',
|
|
77
81
|
ghostPrimary: 'bg-transparent text-export border-transparent hover:bg-export-subtle dark:hover:bg-export/15',
|
|
78
82
|
soft: 'bg-export-subtle dark:bg-export/15',
|
|
83
|
+
softSolid: 'bg-export-subtle dark:bg-[color-mix(in_srgb,#1cbd5d_15%,#212529)]',
|
|
79
84
|
softHover: 'hover:bg-export-subtle dark:hover:bg-export/15',
|
|
80
85
|
};
|
|
81
86
|
}
|
|
@@ -87,6 +92,7 @@ class ModeColorService {
|
|
|
87
92
|
primary: 'bg-import text-white border-transparent hover:bg-import-light',
|
|
88
93
|
ghostPrimary: 'bg-transparent text-import border-transparent hover:bg-import-subtle dark:hover:bg-import/15',
|
|
89
94
|
soft: 'bg-import-subtle dark:bg-import/15',
|
|
95
|
+
softSolid: 'bg-import-subtle dark:bg-[color-mix(in_srgb,#f08829_15%,#212529)]',
|
|
90
96
|
softHover: 'hover:bg-import-subtle dark:hover:bg-import/15',
|
|
91
97
|
};
|
|
92
98
|
}, /* @ts-ignore */
|
|
@@ -1 +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 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 *\n * STN (import / orange):\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 */\nexport const MODE_COLOR_SAFELIST = [\n 'text-export',\n 'bg-export',\n 'bg-export-subtle',\n 'bg-export-light',\n 'border-export',\n 'hover:bg-export-light',\n 'hover:bg-export-subtle',\n 'dark:bg-export/15',\n 'dark:hover:bg-export/15',\n 'text-import',\n 'bg-import',\n 'bg-import-subtle',\n 'bg-import-light',\n 'border-import',\n 'hover:bg-import-light',\n 'hover:bg-import-subtle',\n 'dark:bg-import/15',\n 'dark:hover:bg-import/15',\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 /** Text color utility, e.g. `text-export`. */\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 */\n soft: string;\n /**\n * Soft hover highlight for menus and lists.\n */\n softHover: 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',\n bg: 'bg-export',\n bgSubtle: 'bg-export-subtle',\n border: 'border-export',\n primary:\n 'bg-export text-white border-transparent hover:bg-export-light',\n ghostPrimary:\n 'bg-transparent text-export border-transparent hover:bg-export-subtle dark:hover:bg-export/15',\n soft: 'bg-export-subtle dark:bg-export/15',\n softHover: 'hover:bg-export-subtle dark:hover:bg-export/15',\n };\n }\n return {\n text: 'text-import',\n bg: 'bg-import',\n bgSubtle: 'bg-import-subtle',\n border: 'border-import',\n primary:\n 'bg-import text-white border-transparent hover:bg-import-light',\n ghostPrimary:\n 'bg-transparent text-import border-transparent hover:bg-import-subtle dark:hover:bg-import/15',\n soft: 'bg-import-subtle dark:bg-import/15',\n softHover: 'hover:bg-import-subtle 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":";;;;;;AAAA;;;;;;;;;;;;;;;;;AAiBG;AACI,MAAM,mBAAmB,GAAG;IACjC,aAAa;IACb,WAAW;IACX,kBAAkB;IAClB,iBAAiB;IACjB,eAAe;IACf,uBAAuB;IACvB,wBAAwB;IACxB,mBAAmB;IACnB,yBAAyB;IACzB,aAAa;IACb,WAAW;IACX,kBAAkB;IAClB,iBAAiB;IACjB,eAAe;IACf,uBAAuB;IACvB,wBAAwB;IACxB,mBAAmB;IACnB,yBAAyB;;;ACG3B;;;;;;;;;;;;;;;;AAgBG;MAEU,gBAAgB,CAAA;AACV,IAAA,YAAY,GAAG,MAAM,CAAC,mBAAmB,CAAC;AAE3D;;AAEG;AACM,IAAA,OAAO,GAAG,QAAQ,CAAmB,MAAK;;QAEjD,IAAI,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,KAAK,KAAK,EAAE;YACtC,OAAO;AACL,gBAAA,IAAI,EAAE,aAAa;AACnB,gBAAA,EAAE,EAAE,WAAW;AACf,gBAAA,QAAQ,EAAE,kBAAkB;AAC5B,gBAAA,MAAM,EAAE,eAAe;AACvB,gBAAA,OAAO,EACL,+DAA+D;AACjE,gBAAA,YAAY,EACV,8FAA8F;AAChG,gBAAA,IAAI,EAAE,oCAAoC;AAC1C,gBAAA,SAAS,EAAE,gDAAgD;aAC5D;QACH;QACA,OAAO;AACL,YAAA,IAAI,EAAE,aAAa;AACnB,YAAA,EAAE,EAAE,WAAW;AACf,YAAA,QAAQ,EAAE,kBAAkB;AAC5B,YAAA,MAAM,EAAE,eAAe;AACvB,YAAA,OAAO,EACL,+DAA+D;AACjE,YAAA,YAAY,EACV,8FAA8F;AAChG,YAAA,IAAI,EAAE,oCAAoC;AAC1C,YAAA,SAAS,EAAE,gDAAgD;SAC5D;IACH,CAAC;gFAAC;uGAlCS,gBAAgB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,UAAA,EAAA,CAAA;AAAhB,IAAA,OAAA,KAAA,GAAA,EAAA,CAAA,qBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,QAAA,EAAA,EAAA,EAAA,IAAA,EAAA,gBAAgB,cADH,MAAM,EAAA,CAAA;;2FACnB,gBAAgB,EAAA,UAAA,EAAA,CAAA;kBAD5B,UAAU;mBAAC,EAAE,UAAU,EAAE,MAAM,EAAE;;;ACjDlC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiCG;MAEU,YAAY,CAAA;AACN,IAAA,OAAO,GAAG,MAAM,CAAC,aAAa,CAAC;AAC/B,IAAA,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC;AAE5C;;;AAGG;AACM,IAAA,KAAK,GAAG,MAAM,CAAQ,IAAI,CAAC,mBAAmB,EAAE;8EAAC;AAE1D,IAAA,WAAA,GAAA;QACE,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;IACpC;AAEA;;;;;AAKG;AACH,IAAA,QAAQ,CAAC,KAAY,EAAA;AACnB,QAAA,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC;AACrB,QAAA,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC;AAC3B,QAAA,IAAI;YACF,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,oBAAoB,EAAE,KAAK,CAAC;QAC/C;AAAE,QAAA,MAAM;;;QAGR;IACF;AAEA;;;;AAIG;IACH,MAAM,GAAA;AACJ,QAAA,MAAM,IAAI,GAAU,IAAI,CAAC,KAAK,EAAE,KAAK,OAAO,GAAG,MAAM,GAAG,OAAO;AAC/D,QAAA,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;AACnB,QAAA,OAAO,IAAI;IACb;IAEQ,mBAAmB,GAAA;AACzB,QAAA,IAAI;YACF,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAQ,oBAAoB,CAAC;YAC5D,IAAI,MAAM,KAAK,OAAO,IAAI,MAAM,KAAK,MAAM,EAAE;AAC3C,gBAAA,OAAO,MAAM;YACf;QACF;AAAE,QAAA,MAAM;;QAER;AACA,QAAA,OAAO,IAAI,CAAC,WAAW,EAAE,GAAG,MAAM,GAAG,OAAO;IAC9C;IAEQ,WAAW,GAAA;AACjB,QAAA,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,WAAW;QACrC,OAAO,CAAC,CAAC,GAAG,EAAE,UAAU,GAAG,8BAA8B,CAAC,CAAC,OAAO;IACpE;AAEQ,IAAA,eAAe,CAAC,KAAY,EAAA;AAClC,QAAA,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,eAAe;AAC1C,QAAA,IAAI,KAAK,KAAK,MAAM,EAAE;AACpB,YAAA,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC;QAC5B;aAAO;AACL,YAAA,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC;QAC/B;;AAEA,QAAA,IAAI,CAAC,KAAK,CAAC,WAAW,GAAG,KAAK;IAChC;uGApEW,YAAY,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,UAAA,EAAA,CAAA;AAAZ,IAAA,OAAA,KAAA,GAAA,EAAA,CAAA,qBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,QAAA,EAAA,EAAA,EAAA,IAAA,EAAA,YAAY,cADC,MAAM,EAAA,CAAA;;2FACnB,YAAY,EAAA,UAAA,EAAA,CAAA;kBADxB,UAAU;mBAAC,EAAE,UAAU,EAAE,MAAM,EAAE;;;ACzClC;;AAEG;;;;"}
|
|
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 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)]\n *\n * STN (import / orange):\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)]\n */\nexport const MODE_COLOR_SAFELIST = [\n 'text-export',\n 'bg-export',\n 'bg-export-subtle',\n 'bg-export-light',\n 'border-export',\n 'hover:bg-export-light',\n 'hover:bg-export-subtle',\n 'dark:bg-export/15',\n 'dark:hover:bg-export/15',\n 'dark:bg-[color-mix(in_srgb,#1cbd5d_15%,#212529)]',\n 'text-import',\n 'bg-import',\n 'bg-import-subtle',\n 'bg-import-light',\n 'border-import',\n 'hover:bg-import-light',\n 'hover:bg-import-subtle',\n 'dark:bg-import/15',\n 'dark:hover:bg-import/15',\n 'dark:bg-[color-mix(in_srgb,#f08829_15%,#212529)]',\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 /** Text color utility, e.g. `text-export`. */\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\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',\n bg: 'bg-export',\n bgSubtle: 'bg-export-subtle',\n border: 'border-export',\n primary:\n 'bg-export text-white border-transparent hover:bg-export-light',\n ghostPrimary:\n 'bg-transparent text-export border-transparent hover:bg-export-subtle 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 };\n }\n return {\n text: 'text-import',\n bg: 'bg-import',\n bgSubtle: 'bg-import-subtle',\n border: 'border-import',\n primary:\n 'bg-import text-white border-transparent hover:bg-import-light',\n ghostPrimary:\n 'bg-transparent text-import border-transparent hover:bg-import-subtle 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 };\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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"}
|
|
@@ -69,6 +69,11 @@ function africaniesInteractiveCursorPlugin({ addBase }) {
|
|
|
69
69
|
* (`white` / `ink-950`) and `-webkit-text-fill-color` keeps body text on
|
|
70
70
|
* `ink` / white. `.dark` matches `ThemeService` (`class` on `<html>`).
|
|
71
71
|
*
|
|
72
|
+
* WHY one selector per `addBase` key: joining autofill selectors with commas
|
|
73
|
+
* under a single `.dark ${list}` key only scopes the first selector — the rest
|
|
74
|
+
* leak into light mode. WHY no `color` in the long transition: delaying color
|
|
75
|
+
* freezes text when the user toggles light/dark.
|
|
76
|
+
*
|
|
72
77
|
* @param {import('tailwindcss/types/config').PluginAPI} api
|
|
73
78
|
*/
|
|
74
79
|
function africaniesAutofillPlugin({ addBase }) {
|
|
@@ -81,21 +86,24 @@ function africaniesAutofillPlugin({ addBase }) {
|
|
|
81
86
|
'textarea:-webkit-autofill:hover',
|
|
82
87
|
'textarea:-webkit-autofill:focus',
|
|
83
88
|
'textarea:-webkit-autofill:active',
|
|
84
|
-
]
|
|
89
|
+
];
|
|
85
90
|
|
|
86
|
-
|
|
87
|
-
|
|
91
|
+
/** @type {Record<string, Record<string, string>>} */
|
|
92
|
+
const rules = {};
|
|
93
|
+
for (const selector of autofillSelectors) {
|
|
94
|
+
rules[selector] = {
|
|
88
95
|
WebkitTextFillColor: '#212529',
|
|
89
96
|
caretColor: '#212529',
|
|
90
97
|
boxShadow: '0 0 0 1000px #ffffff inset',
|
|
91
98
|
transition: 'background-color 99999s ease-in-out 0s',
|
|
92
|
-
}
|
|
93
|
-
[`.dark ${
|
|
99
|
+
};
|
|
100
|
+
rules[`.dark ${selector}`] = {
|
|
94
101
|
WebkitTextFillColor: '#ffffff',
|
|
95
102
|
caretColor: '#ffffff',
|
|
96
103
|
boxShadow: '0 0 0 1000px #272729 inset',
|
|
97
|
-
}
|
|
98
|
-
}
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
addBase(rules);
|
|
99
107
|
}
|
|
100
108
|
|
|
101
109
|
/**
|
|
@@ -13,12 +13,14 @@ import * as i0 from '@angular/core';
|
|
|
13
13
|
* SFN (export / green):
|
|
14
14
|
* text-export bg-export bg-export-subtle bg-export-light border-export
|
|
15
15
|
* 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)]
|
|
16
17
|
*
|
|
17
18
|
* STN (import / orange):
|
|
18
19
|
* text-import bg-import bg-import-subtle bg-import-light border-import
|
|
19
20
|
* 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)]
|
|
20
22
|
*/
|
|
21
|
-
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", "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"];
|
|
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)]"];
|
|
22
24
|
|
|
23
25
|
/**
|
|
24
26
|
* Tailwind class bundle for the active shipping mode (SFN export / STN import).
|
|
@@ -47,8 +49,15 @@ interface ModeColorClasses {
|
|
|
47
49
|
ghostPrimary: string;
|
|
48
50
|
/**
|
|
49
51
|
* Soft highlight for selected / active rows (works in dark mode).
|
|
52
|
+
* Dark uses a translucent tint — fine over solid surfaces, not for
|
|
53
|
+
* sticky overlays (see {@link softSolid}).
|
|
50
54
|
*/
|
|
51
55
|
soft: string;
|
|
56
|
+
/**
|
|
57
|
+
* Opaque soft fill — same tint as {@link soft}, but dark mode mixes into
|
|
58
|
+
* ink so scrolled content cannot show through (sticky table headers/cells).
|
|
59
|
+
*/
|
|
60
|
+
softSolid: string;
|
|
52
61
|
/**
|
|
53
62
|
* Soft hover highlight for menus and lists.
|
|
54
63
|
*/
|
|
@@ -15995,9 +15995,14 @@ function hashString(value) {
|
|
|
15995
15995
|
return hash;
|
|
15996
15996
|
}
|
|
15997
15997
|
|
|
15998
|
-
|
|
15998
|
+
/** Bump when cache shape or city resolution strategy changes. */
|
|
15999
|
+
const CACHE_KEY = 'africanies-header-weather-v4';
|
|
15999
16000
|
const FETCH_MS = 4_000;
|
|
16001
|
+
const BROWSER_GEO_MS = 3_500;
|
|
16002
|
+
/** IP fallback — city string is often wrong (e.g. NG IPs labelled Lagos). */
|
|
16000
16003
|
const GEO_URL = 'https://get.geojs.io/v1/ip/geo.json';
|
|
16004
|
+
/** Client reverse-geocode so the label matches the forecast coordinates. */
|
|
16005
|
+
const REVERSE_GEO_URL = 'https://api.bigdatacloud.net/data/reverse-geocode-client';
|
|
16001
16006
|
const WEATHER_LABELS = {
|
|
16002
16007
|
clear: 'Clear',
|
|
16003
16008
|
cloudy: 'Cloudy',
|
|
@@ -16063,7 +16068,12 @@ function headerWeatherIcon(kind, hour) {
|
|
|
16063
16068
|
return 'cloud-o';
|
|
16064
16069
|
}
|
|
16065
16070
|
/**
|
|
16066
|
-
* City-level forecast via IP geolocation + Open-Meteo (no API key).
|
|
16071
|
+
* City-level forecast via browser / IP geolocation + Open-Meteo (no API key).
|
|
16072
|
+
*
|
|
16073
|
+
* Coordinates prefer the browser Geolocation API (accurate for travellers;
|
|
16074
|
+
* may prompt once). Otherwise IP geo is used. The city label is reverse-
|
|
16075
|
+
* geocoded from those coordinates — IP `city` strings are often wrong for
|
|
16076
|
+
* Nigeria (many networks resolve as Lagos).
|
|
16067
16077
|
*
|
|
16068
16078
|
* Fails closed: missing browser APIs, timeouts, and HTTP errors all return
|
|
16069
16079
|
* `null` so the greeting can stay time-of-day only. Cached per local hour
|
|
@@ -16083,14 +16093,12 @@ async function loadHeaderWeather(fetchFn) {
|
|
|
16083
16093
|
return cached;
|
|
16084
16094
|
}
|
|
16085
16095
|
try {
|
|
16086
|
-
const
|
|
16087
|
-
|
|
16088
|
-
const longitude = asNumber(geo?.longitude);
|
|
16089
|
-
if (latitude === null || longitude === null) {
|
|
16096
|
+
const coords = await resolveCoordinates(run);
|
|
16097
|
+
if (!coords) {
|
|
16090
16098
|
return null;
|
|
16091
16099
|
}
|
|
16092
16100
|
const forecastUrl = `https://api.open-meteo.com/v1/forecast` +
|
|
16093
|
-
`?latitude=${latitude}&longitude=${longitude}` +
|
|
16101
|
+
`?latitude=${coords.latitude}&longitude=${coords.longitude}` +
|
|
16094
16102
|
`¤t=weather_code,temperature_2m`;
|
|
16095
16103
|
const forecast = (await fetchJson(run, forecastUrl));
|
|
16096
16104
|
const code = asNumber(forecast?.current?.weather_code);
|
|
@@ -16102,7 +16110,8 @@ async function loadHeaderWeather(fetchFn) {
|
|
|
16102
16110
|
return null;
|
|
16103
16111
|
}
|
|
16104
16112
|
const temperatureC = asNumber(forecast?.current?.temperature_2m) ?? undefined;
|
|
16105
|
-
const city =
|
|
16113
|
+
const city = (await reverseGeocodeCity(run, coords.latitude, coords.longitude)) ??
|
|
16114
|
+
coords.fallbackCity;
|
|
16106
16115
|
const weather = { kind, temperatureC, city };
|
|
16107
16116
|
writeCache({ hour, kind, temperatureC, city });
|
|
16108
16117
|
return weather;
|
|
@@ -16145,6 +16154,60 @@ function writeCache(value) {
|
|
|
16145
16154
|
// Private mode / quota — greeting still works without cache.
|
|
16146
16155
|
}
|
|
16147
16156
|
}
|
|
16157
|
+
/**
|
|
16158
|
+
* Prefer device coordinates when available (may prompt once); otherwise fall
|
|
16159
|
+
* back to IP geo. IP city labels for Nigeria are often wrong — reverse
|
|
16160
|
+
* geocoding from these coordinates still depends on accurate lat/lon.
|
|
16161
|
+
*/
|
|
16162
|
+
async function resolveCoordinates(fetchFn) {
|
|
16163
|
+
const browser = await tryBrowserGeolocation();
|
|
16164
|
+
if (browser) {
|
|
16165
|
+
return browser;
|
|
16166
|
+
}
|
|
16167
|
+
const geo = (await fetchJson(fetchFn, GEO_URL));
|
|
16168
|
+
const latitude = asNumber(geo?.latitude);
|
|
16169
|
+
const longitude = asNumber(geo?.longitude);
|
|
16170
|
+
if (latitude === null || longitude === null) {
|
|
16171
|
+
return null;
|
|
16172
|
+
}
|
|
16173
|
+
return {
|
|
16174
|
+
latitude,
|
|
16175
|
+
longitude,
|
|
16176
|
+
fallbackCity: asCity(geo?.city),
|
|
16177
|
+
};
|
|
16178
|
+
}
|
|
16179
|
+
async function tryBrowserGeolocation() {
|
|
16180
|
+
if (typeof navigator === 'undefined' ||
|
|
16181
|
+
typeof navigator.geolocation?.getCurrentPosition !== 'function') {
|
|
16182
|
+
return null;
|
|
16183
|
+
}
|
|
16184
|
+
return await new Promise((resolve) => {
|
|
16185
|
+
const timer = setTimeout(() => resolve(null), BROWSER_GEO_MS);
|
|
16186
|
+
navigator.geolocation.getCurrentPosition((position) => {
|
|
16187
|
+
clearTimeout(timer);
|
|
16188
|
+
resolve({
|
|
16189
|
+
latitude: position.coords.latitude,
|
|
16190
|
+
longitude: position.coords.longitude,
|
|
16191
|
+
});
|
|
16192
|
+
}, () => {
|
|
16193
|
+
clearTimeout(timer);
|
|
16194
|
+
resolve(null);
|
|
16195
|
+
}, {
|
|
16196
|
+
enableHighAccuracy: false,
|
|
16197
|
+
maximumAge: 600_000,
|
|
16198
|
+
timeout: BROWSER_GEO_MS,
|
|
16199
|
+
});
|
|
16200
|
+
});
|
|
16201
|
+
}
|
|
16202
|
+
async function reverseGeocodeCity(fetchFn, latitude, longitude) {
|
|
16203
|
+
const url = `${REVERSE_GEO_URL}?latitude=${encodeURIComponent(String(latitude))}` +
|
|
16204
|
+
`&longitude=${encodeURIComponent(String(longitude))}` +
|
|
16205
|
+
`&localityLanguage=en`;
|
|
16206
|
+
const payload = (await fetchJson(fetchFn, url));
|
|
16207
|
+
return (asCity(payload?.city) ??
|
|
16208
|
+
asCity(payload?.locality) ??
|
|
16209
|
+
asCity(payload?.principalSubdivision));
|
|
16210
|
+
}
|
|
16148
16211
|
function asNumber(value) {
|
|
16149
16212
|
if (typeof value === 'number' && Number.isFinite(value)) {
|
|
16150
16213
|
return value;
|
|
@@ -17590,9 +17653,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
|
|
|
17590
17653
|
* **Sticky columns:** a column with `key: 'actions'` stays pinned to the
|
|
17591
17654
|
* right while the grid scrolls horizontally. The expand trigger column pins
|
|
17592
17655
|
* to the left when rows are expandable. Override with
|
|
17593
|
-
* {@link TableColumn.sticky}.
|
|
17656
|
+
* {@link TableColumn.sticky}. Sticky columns use a slightly thicker bottom
|
|
17657
|
+
* border (and opaque fill) so dividers stay visible while scrolling.
|
|
17594
17658
|
*/
|
|
17595
17659
|
class TableComponent {
|
|
17660
|
+
modeColor = inject(ModeColorService);
|
|
17596
17661
|
/**
|
|
17597
17662
|
* When false, hides row expansion even if {@link RowDetailDefDirective}
|
|
17598
17663
|
* templates are projected. Defaults to true.
|
|
@@ -17802,6 +17867,21 @@ class TableComponent {
|
|
|
17802
17867
|
cellContext(row) {
|
|
17803
17868
|
return { $implicit: row };
|
|
17804
17869
|
}
|
|
17870
|
+
/**
|
|
17871
|
+
* Header row chrome. Soft fill lives on each `th` ({@link headerSoftClass})
|
|
17872
|
+
* so sticky columns do not double-tint and paint over neighbor labels.
|
|
17873
|
+
* @returns Header row class list.
|
|
17874
|
+
*/
|
|
17875
|
+
headerRowClass() {
|
|
17876
|
+
return 'border-b border-border dark:border-white/10';
|
|
17877
|
+
}
|
|
17878
|
+
/**
|
|
17879
|
+
* Opaque mode soft fill for header cells (sticky-safe in dark mode).
|
|
17880
|
+
* @returns Soft solid background utilities.
|
|
17881
|
+
*/
|
|
17882
|
+
headerSoftClass() {
|
|
17883
|
+
return this.modeColor.classes().softSolid;
|
|
17884
|
+
}
|
|
17805
17885
|
/**
|
|
17806
17886
|
* Body row classes — row marker for hover styles, plus hide cell borders on
|
|
17807
17887
|
* the last / expanded row.
|
|
@@ -17812,7 +17892,7 @@ class TableComponent {
|
|
|
17812
17892
|
bodyRowClass(row, index) {
|
|
17813
17893
|
if (this.isExpandable() && this.isRowExpanded(row, index)) {
|
|
17814
17894
|
// Only the bottom edge — keep the top divider so the row still
|
|
17815
|
-
// separates from the row above.
|
|
17895
|
+
// separates from the row above. Detail panel owns the separator.
|
|
17816
17896
|
return 'africanies-table-row group [&>td]:border-b-0';
|
|
17817
17897
|
}
|
|
17818
17898
|
return 'africanies-table-row group last:[&>td]:border-b-0';
|
|
@@ -17838,21 +17918,27 @@ class TableComponent {
|
|
|
17838
17918
|
* @returns Header class list.
|
|
17839
17919
|
*/
|
|
17840
17920
|
expandHeaderClass() {
|
|
17841
|
-
return ('w-10 border-b border-border px-2 py-
|
|
17921
|
+
return ('w-10 border-b-[1.5px] border-border px-2 py-4 dark:border-white/10 ' +
|
|
17922
|
+
this.headerSoftClass() +
|
|
17923
|
+
' ' +
|
|
17842
17924
|
this.stickyPinClass('left', 'head'));
|
|
17843
17925
|
}
|
|
17844
17926
|
/**
|
|
17845
17927
|
* Body classes for the expand/collapse trigger column (pinned left).
|
|
17846
|
-
*
|
|
17847
|
-
*
|
|
17928
|
+
* Uses a slightly thicker bottom border than scrolling cells so the
|
|
17929
|
+
* sticky fill still reads a clear divider (no top-shadow fallback).
|
|
17848
17930
|
* @param index - Index within {@link rows}.
|
|
17849
17931
|
* @returns Body cell class list.
|
|
17850
17932
|
*/
|
|
17851
17933
|
expandBodyClass(index) {
|
|
17852
|
-
const
|
|
17853
|
-
const
|
|
17854
|
-
|
|
17855
|
-
|
|
17934
|
+
const row = this.rowList()[index];
|
|
17935
|
+
const expanded = row !== undefined && this.isRowExpanded(row, index);
|
|
17936
|
+
const border = expanded
|
|
17937
|
+
? ''
|
|
17938
|
+
: 'border-b-[1.5px] border-border dark:border-white/10 ';
|
|
17939
|
+
return ('w-10 px-2 py-4 align-middle ' +
|
|
17940
|
+
border +
|
|
17941
|
+
this.stickyPinClass('left', 'body'));
|
|
17856
17942
|
}
|
|
17857
17943
|
/**
|
|
17858
17944
|
* Header cell classes, including sticky pin when set.
|
|
@@ -17860,69 +17946,71 @@ class TableComponent {
|
|
|
17860
17946
|
* @returns Header class list.
|
|
17861
17947
|
*/
|
|
17862
17948
|
headerCellClass(col) {
|
|
17863
|
-
|
|
17949
|
+
const sticky = this.stickyEdge(col);
|
|
17950
|
+
const border = sticky
|
|
17951
|
+
? 'border-b-[1.5px] '
|
|
17952
|
+
: 'border-b ';
|
|
17953
|
+
return (border +
|
|
17954
|
+
'border-border whitespace-normal wrap-break-word px-[1.125rem] py-4 font-medium text-neutral-600 dark:border-white/10 dark:text-neutral-400 ' +
|
|
17955
|
+
this.headerSoftClass() +
|
|
17956
|
+
' ' +
|
|
17864
17957
|
this.stickySurfaceClass(col, 'head'));
|
|
17865
17958
|
}
|
|
17866
17959
|
/**
|
|
17867
17960
|
* Body cell classes, including sticky pin when set.
|
|
17868
|
-
* Sticky
|
|
17869
|
-
*
|
|
17870
|
-
* same pixel and read brighter (especially in dark mode).
|
|
17961
|
+
* Sticky expand/actions columns use a 1.5px bottom border; scrolling cells
|
|
17962
|
+
* stay at 1px. Expanded rows drop the bottom border (see {@link bodyRowClass}).
|
|
17871
17963
|
* @param col - Column definition.
|
|
17872
17964
|
* @param index - Index within {@link rows}.
|
|
17873
17965
|
* @returns Body cell class list.
|
|
17874
17966
|
*/
|
|
17875
17967
|
bodyCellClass(col, index) {
|
|
17876
|
-
const
|
|
17968
|
+
const row = this.rowList()[index];
|
|
17969
|
+
const expanded = row !== undefined && this.isRowExpanded(row, index);
|
|
17970
|
+
const sticky = this.stickyEdge(col);
|
|
17971
|
+
const rowLine = expanded
|
|
17877
17972
|
? ''
|
|
17878
|
-
:
|
|
17879
|
-
|
|
17880
|
-
|
|
17973
|
+
: sticky
|
|
17974
|
+
? 'border-b-[1.5px] border-border dark:border-white/10 '
|
|
17975
|
+
: 'border-b border-border dark:border-white/10 ';
|
|
17881
17976
|
const wrap = col.key === 'actions'
|
|
17882
17977
|
? 'whitespace-nowrap '
|
|
17883
17978
|
: 'whitespace-normal wrap-break-word ';
|
|
17884
17979
|
return (rowLine +
|
|
17885
|
-
'px-
|
|
17980
|
+
'px-[1.125rem] py-4 align-middle ' +
|
|
17886
17981
|
wrap +
|
|
17887
|
-
this.stickySurfaceClass(col, 'body'
|
|
17982
|
+
this.stickySurfaceClass(col, 'body'));
|
|
17888
17983
|
}
|
|
17889
17984
|
/**
|
|
17890
17985
|
* Sticky pin utilities for a known edge (expand column or data column).
|
|
17891
17986
|
* @param edge - Left or right pin.
|
|
17892
17987
|
* @param surface - Header vs body fill tokens.
|
|
17893
|
-
* @param index - Body row index; unused for the header.
|
|
17894
|
-
* @param afterExpanded - Previous row is expanded — skip the top shadow
|
|
17895
|
-
* divider so the sticky column stays flush under the detail panel.
|
|
17896
17988
|
* @returns Sticky utilities.
|
|
17897
17989
|
*/
|
|
17898
|
-
stickyPinClass(edge, surface
|
|
17990
|
+
stickyPinClass(edge, surface) {
|
|
17899
17991
|
// Expand (left) sits above scrolling cells; actions (right) match.
|
|
17900
17992
|
// Header needs a higher z so it stays above sticky body cells.
|
|
17901
17993
|
const side = edge === 'right' ? 'sticky right-0 z-[1]' : 'sticky left-0 z-[1]';
|
|
17902
17994
|
if (surface === 'head') {
|
|
17903
|
-
|
|
17995
|
+
// Fill comes from {@link headerSoftClass} on the cell — do not re-tint.
|
|
17996
|
+
return `${side} z-[2]`;
|
|
17904
17997
|
}
|
|
17905
|
-
const rowDivider = !afterExpanded && index > 0
|
|
17906
|
-
? 'shadow-[0_-1px_0_0_#c9d5e1] dark:shadow-[0_-1px_0_0_rgba(255,255,255,0.1)]'
|
|
17907
|
-
: '';
|
|
17908
17998
|
const fill = 'bg-white dark:bg-ink';
|
|
17909
|
-
return `${side} ${fill}
|
|
17999
|
+
return `${side} ${fill}`;
|
|
17910
18000
|
}
|
|
17911
18001
|
/**
|
|
17912
18002
|
* Sticky pin plus an opaque fill matching the table surface, so scrolled
|
|
17913
18003
|
* cells do not show through.
|
|
17914
18004
|
* @param col - Column definition.
|
|
17915
18005
|
* @param surface - Header vs body fill tokens.
|
|
17916
|
-
* @param index - Body row index; unused for the header.
|
|
17917
|
-
* @param afterExpanded - Previous row is expanded — skip the top shadow.
|
|
17918
18006
|
* @returns Sticky utilities, or empty when the column scrolls.
|
|
17919
18007
|
*/
|
|
17920
|
-
stickySurfaceClass(col, surface
|
|
18008
|
+
stickySurfaceClass(col, surface) {
|
|
17921
18009
|
const edge = this.stickyEdge(col);
|
|
17922
18010
|
if (!edge) {
|
|
17923
18011
|
return '';
|
|
17924
18012
|
}
|
|
17925
|
-
return this.stickyPinClass(edge, surface
|
|
18013
|
+
return this.stickyPinClass(edge, surface);
|
|
17926
18014
|
}
|
|
17927
18015
|
/**
|
|
17928
18016
|
* Stable id for a row — used for expand/collapse state.
|
|
@@ -18096,9 +18184,7 @@ class TableComponent {
|
|
|
18096
18184
|
<table
|
|
18097
18185
|
class="w-max min-w-full table-auto border-separate border-spacing-0 bg-inherit text-left text-body text-ink dark:text-white"
|
|
18098
18186
|
>
|
|
18099
|
-
<thead
|
|
18100
|
-
class="border-b border-border bg-background-welcome dark:border-white/10 dark:bg-ink-950"
|
|
18101
|
-
>
|
|
18187
|
+
<thead [class]="headerRowClass()">
|
|
18102
18188
|
<tr>
|
|
18103
18189
|
@if (isExpandable()) {
|
|
18104
18190
|
<th
|
|
@@ -18162,14 +18248,14 @@ class TableComponent {
|
|
|
18162
18248
|
@switch (bodyKind()) {
|
|
18163
18249
|
@case ('loading') {
|
|
18164
18250
|
<tr>
|
|
18165
|
-
<td class="px-
|
|
18251
|
+
<td class="px-[1.125rem] py-6" [attr.colspan]="colSpan()">
|
|
18166
18252
|
<africanies-loading-state [message]="loadingLabel()" />
|
|
18167
18253
|
</td>
|
|
18168
18254
|
</tr>
|
|
18169
18255
|
}
|
|
18170
18256
|
@case ('error') {
|
|
18171
18257
|
<tr>
|
|
18172
|
-
<td class="px-
|
|
18258
|
+
<td class="px-[1.125rem] py-6" [attr.colspan]="colSpan()">
|
|
18173
18259
|
<africanies-error-state
|
|
18174
18260
|
[message]="errorMessage()"
|
|
18175
18261
|
[refreshing]="refreshing()"
|
|
@@ -18180,7 +18266,7 @@ class TableComponent {
|
|
|
18180
18266
|
}
|
|
18181
18267
|
@case ('empty') {
|
|
18182
18268
|
<tr>
|
|
18183
|
-
<td class="px-
|
|
18269
|
+
<td class="px-[1.125rem] py-6" [attr.colspan]="colSpan()">
|
|
18184
18270
|
<africanies-empty-state
|
|
18185
18271
|
[message]="emptyMessage()"
|
|
18186
18272
|
[refreshing]="refreshing()"
|
|
@@ -18248,7 +18334,7 @@ class TableComponent {
|
|
|
18248
18334
|
class="min-h-0 overflow-hidden border-t border-border/70 bg-neutral-50 dark:border-white/10 dark:bg-white/[0.05]"
|
|
18249
18335
|
>
|
|
18250
18336
|
<dl
|
|
18251
|
-
class="m-0 grid gap-x-6 gap-y-3 px-
|
|
18337
|
+
class="m-0 grid gap-x-6 gap-y-3 px-[1.125rem] py-4 transition-opacity duration-200 ease-out motion-reduce:transition-none sm:grid-cols-2 lg:grid-cols-3"
|
|
18252
18338
|
[class.opacity-0]="!isRowExpanded(row, i)"
|
|
18253
18339
|
[class.opacity-100]="isRowExpanded(row, i)"
|
|
18254
18340
|
>
|
|
@@ -18390,9 +18476,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
|
|
|
18390
18476
|
<table
|
|
18391
18477
|
class="w-max min-w-full table-auto border-separate border-spacing-0 bg-inherit text-left text-body text-ink dark:text-white"
|
|
18392
18478
|
>
|
|
18393
|
-
<thead
|
|
18394
|
-
class="border-b border-border bg-background-welcome dark:border-white/10 dark:bg-ink-950"
|
|
18395
|
-
>
|
|
18479
|
+
<thead [class]="headerRowClass()">
|
|
18396
18480
|
<tr>
|
|
18397
18481
|
@if (isExpandable()) {
|
|
18398
18482
|
<th
|
|
@@ -18456,14 +18540,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
|
|
|
18456
18540
|
@switch (bodyKind()) {
|
|
18457
18541
|
@case ('loading') {
|
|
18458
18542
|
<tr>
|
|
18459
|
-
<td class="px-
|
|
18543
|
+
<td class="px-[1.125rem] py-6" [attr.colspan]="colSpan()">
|
|
18460
18544
|
<africanies-loading-state [message]="loadingLabel()" />
|
|
18461
18545
|
</td>
|
|
18462
18546
|
</tr>
|
|
18463
18547
|
}
|
|
18464
18548
|
@case ('error') {
|
|
18465
18549
|
<tr>
|
|
18466
|
-
<td class="px-
|
|
18550
|
+
<td class="px-[1.125rem] py-6" [attr.colspan]="colSpan()">
|
|
18467
18551
|
<africanies-error-state
|
|
18468
18552
|
[message]="errorMessage()"
|
|
18469
18553
|
[refreshing]="refreshing()"
|
|
@@ -18474,7 +18558,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
|
|
|
18474
18558
|
}
|
|
18475
18559
|
@case ('empty') {
|
|
18476
18560
|
<tr>
|
|
18477
|
-
<td class="px-
|
|
18561
|
+
<td class="px-[1.125rem] py-6" [attr.colspan]="colSpan()">
|
|
18478
18562
|
<africanies-empty-state
|
|
18479
18563
|
[message]="emptyMessage()"
|
|
18480
18564
|
[refreshing]="refreshing()"
|
|
@@ -18542,7 +18626,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
|
|
|
18542
18626
|
class="min-h-0 overflow-hidden border-t border-border/70 bg-neutral-50 dark:border-white/10 dark:bg-white/[0.05]"
|
|
18543
18627
|
>
|
|
18544
18628
|
<dl
|
|
18545
|
-
class="m-0 grid gap-x-6 gap-y-3 px-
|
|
18629
|
+
class="m-0 grid gap-x-6 gap-y-3 px-[1.125rem] py-4 transition-opacity duration-200 ease-out motion-reduce:transition-none sm:grid-cols-2 lg:grid-cols-3"
|
|
18546
18630
|
[class.opacity-0]="!isRowExpanded(row, i)"
|
|
18547
18631
|
[class.opacity-100]="isRowExpanded(row, i)"
|
|
18548
18632
|
>
|