@africanies/angular-web-sdk 0.1.6 → 0.1.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (167) hide show
  1. package/.nx/cache/{17491371155400585077 → 13466509747676776487}/dist/libs/africanies-core/fesm2022/africanies-africanies-core.mjs +139 -51
  2. package/.nx/cache/13466509747676776487/dist/libs/africanies-core/fesm2022/africanies-africanies-core.mjs.map +1 -0
  3. package/.nx/cache/{17491371155400585077 → 13466509747676776487}/dist/libs/africanies-core/types/africanies-africanies-core.d.ts +14 -11
  4. package/.nx/cache/{17499961385238663835 → 14995846848874973576}/dist/libs/africanies-ui/fesm2022/africanies-africanies-ui.mjs +83 -63
  5. package/.nx/cache/14995846848874973576/dist/libs/africanies-ui/fesm2022/africanies-africanies-ui.mjs.map +1 -0
  6. package/.nx/cache/{17499961385238663835 → 14995846848874973576}/dist/libs/africanies-ui/types/africanies-africanies-ui.d.ts +22 -19
  7. package/.nx/cache/{12276756491762927325 → 15302120112746851896}/dist/libs/africanies-theme/fesm2022/africanies-africanies-theme.mjs +34 -6
  8. package/.nx/cache/15302120112746851896/dist/libs/africanies-theme/fesm2022/africanies-africanies-theme.mjs.map +1 -0
  9. package/.nx/cache/{12276756491762927325 → 15302120112746851896}/dist/libs/africanies-theme/tailwind-preset.cjs +104 -19
  10. package/.nx/cache/{12276756491762927325 → 15302120112746851896}/dist/libs/africanies-theme/types/africanies-africanies-theme.d.ts +21 -2
  11. package/.nx/cache/18393832731522001121/dist/libs/africanies-core/README.md +85 -0
  12. package/.nx/cache/18393832731522001121/dist/libs/africanies-core/fesm2022/africanies-africanies-core.mjs +4634 -0
  13. package/.nx/cache/18393832731522001121/dist/libs/africanies-core/fesm2022/africanies-africanies-core.mjs.map +1 -0
  14. package/.nx/cache/18393832731522001121/dist/libs/africanies-core/package.json +31 -0
  15. package/.nx/cache/18393832731522001121/dist/libs/africanies-core/types/africanies-africanies-core.d.ts +2743 -0
  16. package/.nx/cache/5151121439688073678/dist/libs/africanies-icons/README.md +69 -0
  17. package/.nx/cache/5151121439688073678/dist/libs/africanies-icons/assets/icons.sprite.svg +1851 -0
  18. package/.nx/cache/5151121439688073678/dist/libs/africanies-icons/fesm2022/africanies-africanies-icons.mjs +833 -0
  19. package/.nx/cache/5151121439688073678/dist/libs/africanies-icons/fesm2022/africanies-africanies-icons.mjs.map +1 -0
  20. package/.nx/cache/5151121439688073678/dist/libs/africanies-icons/package.json +30 -0
  21. package/.nx/cache/5151121439688073678/dist/libs/africanies-icons/types/africanies-africanies-icons.d.ts +108 -0
  22. package/.nx/cache/{4082520855419352840 → 6673686859704879504}/dist/libs/africanies-theme/fesm2022/africanies-africanies-theme.mjs +12 -2
  23. package/.nx/cache/6673686859704879504/dist/libs/africanies-theme/fesm2022/africanies-africanies-theme.mjs.map +1 -0
  24. package/.nx/cache/{4082520855419352840 → 6673686859704879504}/dist/libs/africanies-theme/tailwind-preset.cjs +16 -7
  25. package/.nx/cache/{4082520855419352840 → 6673686859704879504}/dist/libs/africanies-theme/types/africanies-africanies-theme.d.ts +11 -3
  26. package/.nx/cache/877026836685850193/dist/libs/africanies-models/README.md +60 -0
  27. package/.nx/cache/877026836685850193/dist/libs/africanies-models/fesm2022/africanies-africanies-models.mjs +613 -0
  28. package/.nx/cache/877026836685850193/dist/libs/africanies-models/fesm2022/africanies-africanies-models.mjs.map +1 -0
  29. package/.nx/cache/877026836685850193/dist/libs/africanies-models/package.json +23 -0
  30. package/.nx/cache/877026836685850193/dist/libs/africanies-models/types/africanies-africanies-models.d.ts +1452 -0
  31. package/.nx/cache/{3314955264390318442 → 9406544675747598148}/dist/libs/africanies-ui/fesm2022/africanies-africanies-ui.mjs +866 -632
  32. package/.nx/cache/9406544675747598148/dist/libs/africanies-ui/fesm2022/africanies-africanies-ui.mjs.map +1 -0
  33. package/.nx/cache/{3314955264390318442 → 9406544675747598148}/dist/libs/africanies-ui/types/africanies-africanies-ui.d.ts +170 -130
  34. package/.nx/cache/run.json +42 -42
  35. package/.nx/cache/terminalOutputs/{17491371155400585077 → 13466509747676776487} +1 -1
  36. package/.nx/cache/terminalOutputs/14995846848874973576 +21 -0
  37. package/.nx/cache/terminalOutputs/{3017748574492080228 → 15149466893522345489} +16 -7
  38. package/.nx/cache/terminalOutputs/{4082520855419352840 → 15302120112746851896} +1 -1
  39. package/.nx/cache/terminalOutputs/{8648260256613557249 → 15835338512221847842} +18 -8
  40. package/.nx/cache/terminalOutputs/17960163310445607219 +6 -0
  41. package/.nx/cache/terminalOutputs/18393832731522001121 +21 -0
  42. package/.nx/cache/terminalOutputs/{3314955264390318442 → 5151121439688073678} +6 -6
  43. package/.nx/cache/terminalOutputs/{12276756491762927325 → 6673686859704879504} +2 -2
  44. package/.nx/cache/terminalOutputs/7462873189468732296 +17 -0
  45. package/.nx/cache/terminalOutputs/8032148447904822353 +185 -0
  46. package/.nx/cache/terminalOutputs/877026836685850193 +21 -0
  47. package/.nx/cache/terminalOutputs/9406544675747598148 +21 -0
  48. package/.nx/workspace-data/0091ABA9-5C90-580D-953C-8C94E763ADB5-v3.db +0 -0
  49. package/.nx/workspace-data/0091ABA9-5C90-580D-953C-8C94E763ADB5-v3.db-shm +0 -0
  50. package/.nx/workspace-data/0091ABA9-5C90-580D-953C-8C94E763ADB5-v3.db-wal +0 -0
  51. package/.nx/workspace-data/d/daemon.log +3962 -0
  52. package/.nx/workspace-data/d/server-process.json +2 -2
  53. package/.nx/workspace-data/file-map.json +3102 -3036
  54. package/.nx/workspace-data/nx_files.nxt +0 -0
  55. package/.nx/workspace-data/project-graph.json +7 -2
  56. package/apps/playground/src/app/pages/button-page.ts +5 -3
  57. package/apps/playground/src/app/pages/feedback-page.ts +1 -1
  58. package/apps/playground/src/app/pages/home-page.ts +1 -1
  59. package/apps/playground/src/app/pages/icons-page.ts +3 -3
  60. package/apps/playground/src/app/pages/lecture-page.ts +3 -3
  61. package/apps/playground/src/app/pages/models-page.ts +1 -1
  62. package/apps/playground/src/app/pages/overlay-demos.ts +1 -1
  63. package/apps/playground/src/app/pages/tokens-page.ts +29 -11
  64. package/apps/playground/src/app/pages/usecases/onboarding-login.page.ts +1 -1
  65. package/apps/playground/src/app/pages/usecases/onboarding-reset-password.page.ts +1 -1
  66. package/apps/playground/src/app/pages/usecases/shipment-detail.page.ts +1 -1
  67. package/apps/playground/src/app/pages/viewport-preview.component.ts +1 -1
  68. package/apps/playground/src/app/snippets/button.snippets.ts +4 -3
  69. package/apps/playground/src/app/snippets/filters.snippets.ts +10 -0
  70. package/apps/playground/src/index.html +6 -0
  71. package/apps/playground/src/styles.css +4 -5
  72. package/dist/libs/africanies-core/fesm2022/africanies-africanies-core.mjs +131 -8
  73. package/dist/libs/africanies-core/fesm2022/africanies-africanies-core.mjs.map +1 -1
  74. package/dist/libs/africanies-core/types/africanies-africanies-core.d.ts +8 -6
  75. package/dist/libs/africanies-icons/assets/icons.sprite.svg +7 -0
  76. package/dist/libs/africanies-icons/fesm2022/africanies-africanies-icons.mjs +1 -0
  77. package/dist/libs/africanies-icons/fesm2022/africanies-africanies-icons.mjs.map +1 -1
  78. package/dist/libs/africanies-icons/types/africanies-africanies-icons.d.ts +2 -2
  79. package/dist/libs/africanies-models/fesm2022/africanies-africanies-models.mjs +22 -8
  80. package/dist/libs/africanies-models/fesm2022/africanies-africanies-models.mjs.map +1 -1
  81. package/dist/libs/africanies-theme/fesm2022/africanies-africanies-theme.mjs +30 -8
  82. package/dist/libs/africanies-theme/fesm2022/africanies-africanies-theme.mjs.map +1 -1
  83. package/dist/libs/africanies-theme/tailwind-preset.cjs +89 -12
  84. package/dist/libs/africanies-theme/types/africanies-africanies-theme.d.ts +14 -4
  85. package/dist/libs/africanies-ui/fesm2022/africanies-africanies-ui.mjs +765 -615
  86. package/dist/libs/africanies-ui/fesm2022/africanies-africanies-ui.mjs.map +1 -1
  87. package/dist/libs/africanies-ui/types/africanies-africanies-ui.d.ts +148 -115
  88. package/libs/africanies-core/src/index.ts +1 -0
  89. package/libs/africanies-core/src/lib/notification/index.ts +1 -1
  90. package/libs/africanies-core/src/lib/notification/notification-link.spec.ts +40 -7
  91. package/libs/africanies-core/src/lib/notification/notification-link.ts +143 -7
  92. package/libs/africanies-icons/src/assets/icons.sprite.svg +7 -0
  93. package/libs/africanies-icons/src/lib/icon-name.ts +1 -0
  94. package/libs/africanies-models/src/lib/filters/configs/seed-configs.ts +22 -8
  95. package/libs/africanies-theme/src/lib/mode-color.safelist.ts +20 -2
  96. package/libs/africanies-theme/src/lib/mode-color.service.spec.ts +55 -0
  97. package/libs/africanies-theme/src/lib/mode-color.service.ts +23 -7
  98. package/libs/africanies-theme/tailwind-preset.cjs +89 -12
  99. package/libs/africanies-ui/src/lib/action-menu/action-menu.component.ts +3 -3
  100. package/libs/africanies-ui/src/lib/alert/alert.component.ts +4 -4
  101. package/libs/africanies-ui/src/lib/avatar/avatar-menu.component.ts +2 -2
  102. package/libs/africanies-ui/src/lib/button/button.component.spec.ts +7 -7
  103. package/libs/africanies-ui/src/lib/button/button.component.ts +10 -6
  104. package/libs/africanies-ui/src/lib/chip/chip.component.ts +4 -4
  105. package/libs/africanies-ui/src/lib/content-stack/content-stack.component.ts +1 -1
  106. package/libs/africanies-ui/src/lib/feedback/empty-state.component.ts +1 -1
  107. package/libs/africanies-ui/src/lib/feedback/error-indicator.component.ts +3 -3
  108. package/libs/africanies-ui/src/lib/feedback/error-state.component.ts +3 -3
  109. package/libs/africanies-ui/src/lib/filters/filter-drawer.panel.ts +44 -27
  110. package/libs/africanies-ui/src/lib/forms/checkbox/checkbox.component.ts +2 -1
  111. package/libs/africanies-ui/src/lib/forms/file-upload/file-preview.dialog.ts +2 -2
  112. package/libs/africanies-ui/src/lib/forms/file-upload/file-upload.component.ts +5 -5
  113. package/libs/africanies-ui/src/lib/forms/form-field.classes.ts +37 -7
  114. package/libs/africanies-ui/src/lib/forms/otp-input/otp-input.component.ts +2 -1
  115. package/libs/africanies-ui/src/lib/forms/radio/radio.component.ts +2 -1
  116. package/libs/africanies-ui/src/lib/forms/select/select.component.ts +2 -2
  117. package/libs/africanies-ui/src/lib/forms/toggle/toggle.component.ts +1 -1
  118. package/libs/africanies-ui/src/lib/image/image.component.ts +1 -1
  119. package/libs/africanies-ui/src/lib/info-popover/info-popover.component.ts +2 -2
  120. package/libs/africanies-ui/src/lib/layout/app-shell-content-header.component.ts +1 -1
  121. package/libs/africanies-ui/src/lib/layout/app-shell-header.component.ts +6 -6
  122. package/libs/africanies-ui/src/lib/layout/app-shell.component.html +2 -2
  123. package/libs/africanies-ui/src/lib/layout/app-shell.component.ts +5 -5
  124. package/libs/africanies-ui/src/lib/navigation/shipping-mode-switch/shipping-mode-switch.component.ts +4 -4
  125. package/libs/africanies-ui/src/lib/navigation/side-nav/africanies-side-nav.component.html +21 -13
  126. package/libs/africanies-ui/src/lib/navigation/side-nav/africanies-side-nav.component.ts +23 -13
  127. package/libs/africanies-ui/src/lib/notifications/notification-drawer.panel.ts +27 -14
  128. package/libs/africanies-ui/src/lib/overlay/confirm-dialog.component.ts +2 -2
  129. package/libs/africanies-ui/src/lib/overlay/drawer.service.ts +3 -3
  130. package/libs/africanies-ui/src/lib/overlay/modal.service.ts +4 -4
  131. package/libs/africanies-ui/src/lib/overlay/overlay-frame.component.ts +1 -1
  132. package/libs/africanies-ui/src/lib/pagination/pagination.component.ts +4 -4
  133. package/libs/africanies-ui/src/lib/stepper/stepper.component.ts +7 -7
  134. package/libs/africanies-ui/src/lib/table/table-column.ts +9 -0
  135. package/libs/africanies-ui/src/lib/table/table.component.spec.ts +99 -0
  136. package/libs/africanies-ui/src/lib/table/table.component.ts +75 -33
  137. package/libs/africanies-ui/src/lib/toast/toast-host.component.ts +4 -4
  138. package/libs/africanies-ui/src/lib/toast/toast-item.component.ts +7 -7
  139. package/package.json +1 -1
  140. package/svg/hand-coins.svg +9 -0
  141. package/.nx/cache/12276756491762927325/dist/libs/africanies-theme/fesm2022/africanies-africanies-theme.mjs.map +0 -1
  142. package/.nx/cache/17491371155400585077/dist/libs/africanies-core/fesm2022/africanies-africanies-core.mjs.map +0 -1
  143. package/.nx/cache/17499961385238663835/dist/libs/africanies-ui/fesm2022/africanies-africanies-ui.mjs.map +0 -1
  144. package/.nx/cache/3314955264390318442/dist/libs/africanies-ui/fesm2022/africanies-africanies-ui.mjs.map +0 -1
  145. package/.nx/cache/4082520855419352840/dist/libs/africanies-theme/fesm2022/africanies-africanies-theme.mjs.map +0 -1
  146. package/.nx/cache/terminalOutputs/17499961385238663835 +0 -21
  147. /package/.nx/cache/{17491371155400585077 → 13466509747676776487}/dist/libs/africanies-core/README.md +0 -0
  148. /package/.nx/cache/{17491371155400585077 → 13466509747676776487}/dist/libs/africanies-core/package.json +0 -0
  149. /package/.nx/cache/{17499961385238663835 → 14995846848874973576}/dist/libs/africanies-ui/README.md +0 -0
  150. /package/.nx/cache/{17499961385238663835 → 14995846848874973576}/dist/libs/africanies-ui/assets/brand/africanies-logo-mini.png +0 -0
  151. /package/.nx/cache/{17499961385238663835 → 14995846848874973576}/dist/libs/africanies-ui/assets/brand/africanies-logo.png +0 -0
  152. /package/.nx/cache/{17499961385238663835 → 14995846848874973576}/dist/libs/africanies-ui/assets/brand/africanies-logo.svg +0 -0
  153. /package/.nx/cache/{17499961385238663835 → 14995846848874973576}/dist/libs/africanies-ui/assets/carriers/dhl.svg +0 -0
  154. /package/.nx/cache/{17499961385238663835 → 14995846848874973576}/dist/libs/africanies-ui/package.json +0 -0
  155. /package/.nx/cache/{12276756491762927325 → 15302120112746851896}/dist/libs/africanies-theme/README.md +0 -0
  156. /package/.nx/cache/{12276756491762927325 → 15302120112746851896}/dist/libs/africanies-theme/package.json +0 -0
  157. /package/.nx/cache/{4082520855419352840 → 6673686859704879504}/dist/libs/africanies-theme/README.md +0 -0
  158. /package/.nx/cache/{4082520855419352840 → 6673686859704879504}/dist/libs/africanies-theme/package.json +0 -0
  159. /package/.nx/cache/{3314955264390318442 → 9406544675747598148}/dist/libs/africanies-ui/README.md +0 -0
  160. /package/.nx/cache/{3314955264390318442 → 9406544675747598148}/dist/libs/africanies-ui/assets/brand/africanies-logo-mini.png +0 -0
  161. /package/.nx/cache/{3314955264390318442 → 9406544675747598148}/dist/libs/africanies-ui/assets/brand/africanies-logo.png +0 -0
  162. /package/.nx/cache/{3314955264390318442 → 9406544675747598148}/dist/libs/africanies-ui/assets/brand/africanies-logo.svg +0 -0
  163. /package/.nx/cache/{3314955264390318442 → 9406544675747598148}/dist/libs/africanies-ui/assets/carriers/dhl.svg +0 -0
  164. /package/.nx/cache/{3314955264390318442 → 9406544675747598148}/dist/libs/africanies-ui/package.json +0 -0
  165. /package/.nx/cache/terminalOutputs/{16279119293212733518 → 14005735098959303198} +0 -0
  166. /package/.nx/cache/terminalOutputs/{7126777490381568487 → 1446890025183346611} +0 -0
  167. /package/.nx/cache/terminalOutputs/{9408529484792607601 → 6337357866566791975} +0 -0
@@ -147,16 +147,16 @@ export class ModalService implements OverlayOpener {
147
147
  'africanies-overlay-backdrop',
148
148
  'bg-ink/45',
149
149
  'backdrop-blur-sm',
150
- 'dark:bg-ink/60',
150
+ 'dark:bg-ink-950/60',
151
151
  ],
152
152
  panelClass: [
153
153
  'africanies-modal-panel',
154
- 'bg-white',
154
+ 'bg-surface',
155
155
  'dark:bg-ink-950',
156
156
  'text-ink',
157
157
  'dark:text-white',
158
- 'rounded-lg',
159
- 'shadow-xl',
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-[2px] -mx-[2px]"
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>
@@ -134,7 +134,7 @@ type PageItem = number | 'ellipsis';
134
134
  <button
135
135
  africanies-button
136
136
  type="button"
137
- variant="secondary"
137
+ variant="flat"
138
138
  size="sm"
139
139
  [disabled]="controlsDisabled() || !meta().has_previous_page"
140
140
  (click)="emitPage(meta().current_page - 1)"
@@ -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-500 dark:text-neutral-400"
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
 
@@ -155,7 +155,7 @@ type PageItem = number | 'ellipsis';
155
155
  type="button"
156
156
  size="sm"
157
157
  class="min-w-8"
158
- [variant]="item === meta().current_page ? 'primary' : 'secondary'"
158
+ [variant]="item === meta().current_page ? 'primary' : 'flat'"
159
159
  [disabled]="controlsDisabled()"
160
160
  [attr.aria-label]="'Page ' + item"
161
161
  [attr.aria-current]="
@@ -170,7 +170,7 @@ type PageItem = number | 'ellipsis';
170
170
  <button
171
171
  africanies-button
172
172
  type="button"
173
- variant="secondary"
173
+ variant="flat"
174
174
  size="sm"
175
175
  [disabled]="controlsDisabled() || !meta().has_next_page"
176
176
  (click)="emitPage(meta().current_page + 1)"
@@ -53,9 +53,9 @@ function prefersReducedMotion(): boolean {
53
53
  .africanies-step-body {
54
54
  min-width: 0;
55
55
  overflow-x: clip;
56
- /* 2 px breathing room so focus-outline rings on edge fields are not clipped */
57
- padding-inline: 2px;
58
- margin-inline: -2px;
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-500 dark:text-neutral-400"
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-2 focus-visible:outline-offset-2 focus-visible:outline-ink disabled:cursor-not-allowed"
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-500 dark:text-neutral-400';
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-border bg-white text-neutral-500 dark:border-white/20 dark:bg-ink-950 dark:text-neutral-400`;
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
+ });
@@ -39,11 +39,11 @@ import { TableColumn, TableSortChange } from './table-column';
39
39
  * Hidden while the body shows empty or error — those states expose Retry instead.
40
40
  * While {@link refreshing} is true the rows stay on screen — the refresh icon
41
41
  * spins (do not swap to a blocking loader). Use {@link loading} when the page
42
- * of data is changing (pagination / size): rows stay on screen and the built-in
43
- * pager shows a circular spinner beside the page controls; the body loader
44
- * appears only when there are no rows yet (first load) or the host cleared
45
- * rows for a shipping-mode switch (STN SFN). Toolbar and column headers stay
46
- * mounted.
42
+ * of data is changing (pagination / size): rows stay on screen, a keep-rows
43
+ * overlay covers the grid, and the built-in pager shows a circular spinner
44
+ * beside the page controls; the body loader appears only when there are no
45
+ * rows yet (first load) or the host cleared rows for a shipping-mode switch
46
+ * (STN ↔ SFN). Toolbar and column headers stay mounted.
47
47
  * top-right **Filters** then **Export** (`showFilter` / `showExport`). The table
48
48
  * does not own fetch, filter, or export logic — the host handles those events.
49
49
  *
@@ -102,6 +102,11 @@ import { TableColumn, TableSortChange } from './table-column';
102
102
  * to the left when rows are expandable. Override with
103
103
  * {@link TableColumn.sticky}. Sticky columns use a slightly thicker bottom
104
104
  * border (and opaque fill) so dividers stay visible while scrolling.
105
+ *
106
+ * **Sticky header (desktop):** when {@link stickyHeader} is true (default),
107
+ * large screens scroll the grid inside a capped viewport and keep `th` pinned
108
+ * to the top of that scrollport. Mobile keeps horizontal-only overflow so
109
+ * page scroll is unchanged.
105
110
  */
106
111
  @Component({
107
112
  selector: 'africanies-table',
@@ -124,7 +129,7 @@ import { TableColumn, TableSortChange } from './table-column';
124
129
  /* Full-row hover: sticky action cells use an opaque fill that would
125
130
  otherwise mask a <tr> background. Paint every cell the same way. */
126
131
  :host tr.africanies-table-row:hover > td {
127
- background-color: #eef2f6;
132
+ background-color: #e9eef5;
128
133
  }
129
134
  :host-context(.dark) tr.africanies-table-row:hover > td {
130
135
  background-color: #272729;
@@ -142,7 +147,7 @@ import { TableColumn, TableSortChange } from './table-column';
142
147
  <button
143
148
  africanies-button
144
149
  type="button"
145
- variant="secondary"
150
+ variant="flat"
146
151
  size="sm"
147
152
  [disabled]="loading() || refreshing()"
148
153
  [attr.aria-label]="refreshLabel()"
@@ -162,7 +167,7 @@ import { TableColumn, TableSortChange } from './table-column';
162
167
  <button
163
168
  africanies-button
164
169
  type="button"
165
- variant="secondary"
170
+ variant="flat"
166
171
  size="sm"
167
172
  [attr.aria-label]="filterLabel()"
168
173
  (click)="filterClick.emit()"
@@ -182,7 +187,7 @@ import { TableColumn, TableSortChange } from './table-column';
182
187
  <button
183
188
  africanies-button
184
189
  type="button"
185
- variant="secondary"
190
+ variant="flat"
186
191
  size="sm"
187
192
  [attr.aria-label]="exportLabel()"
188
193
  (click)="exportClick.emit()"
@@ -196,19 +201,19 @@ import { TableColumn, TableSortChange } from './table-column';
196
201
  }
197
202
 
198
203
  @if (staleError(); as staleMessage) {
199
- <div class="flex justify-end">
200
- <africanies-error-indicator
201
- class="max-w-[min(100%,20rem)]"
202
- [error]="staleMessage"
203
- retryText="Refresh"
204
- [refreshing]="refreshing()"
205
- (retry)="refreshClick.emit()"
206
- />
207
- </div>
204
+ <africanies-error-indicator
205
+ class="w-full"
206
+ [error]="staleMessage"
207
+ retryText="Refresh"
208
+ [refreshing]="refreshing()"
209
+ (retry)="refreshClick.emit()"
210
+ />
208
211
  }
209
212
 
210
213
  <div
211
- class="min-w-0 w-full overflow-x-auto rounded-md border border-border bg-white dark:border-white/10 dark:bg-ink"
214
+ class="relative min-w-0 w-full overflow-x-auto rounded-panel border border-border bg-surface dark:border-white/10 dark:bg-ink-surface"
215
+ [class.lg:max-h-[min(70dvh,calc(100dvh-12rem))]]="stickyHeader()"
216
+ [class.lg:overflow-auto]="stickyHeader()"
212
217
  >
213
218
  <table
214
219
  class="w-max min-w-full table-auto border-separate border-spacing-0 bg-inherit text-left text-body text-ink dark:text-white"
@@ -223,7 +228,7 @@ import { TableColumn, TableSortChange } from './table-column';
223
228
  @if (someRowsExpanded()) {
224
229
  <button
225
230
  type="button"
226
- class="inline-flex size-8 cursor-pointer items-center justify-center rounded-md text-neutral-600 transition-colors hover:bg-white hover:text-ink focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ink dark:text-neutral-400 dark:hover:bg-white/10 dark:hover:text-white"
231
+ class="inline-flex size-8 cursor-pointer items-center justify-center rounded-md text-neutral-600 transition-colors hover:bg-surface 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"
227
232
  aria-label="Collapse all"
228
233
  (click)="collapseAllRows()"
229
234
  >
@@ -232,7 +237,7 @@ import { TableColumn, TableSortChange } from './table-column';
232
237
  } @else {
233
238
  <button
234
239
  type="button"
235
- class="inline-flex size-8 cursor-pointer items-center justify-center rounded-md text-neutral-600 transition-colors hover:bg-white hover:text-ink focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ink disabled:cursor-not-allowed disabled:opacity-40 dark:text-neutral-400 dark:hover:bg-white/10 dark:hover:text-white"
240
+ class="inline-flex size-8 cursor-pointer items-center justify-center rounded-md text-neutral-600 transition-colors hover:bg-surface hover:text-ink focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-focus disabled:cursor-not-allowed disabled:opacity-40 dark:text-neutral-400 dark:hover:bg-white/10 dark:hover:text-white"
236
241
  aria-label="Expand all"
237
242
  [disabled]="rowList().length === 0"
238
243
  (click)="expandAllRows()"
@@ -246,7 +251,8 @@ import { TableColumn, TableSortChange } from './table-column';
246
251
  <th
247
252
  scope="col"
248
253
  [class]="headerCellClass(col)"
249
- [style.width]="col.width ?? null"
254
+ [style.width]="col.width ?? col.maxWidth ?? null"
255
+ [style.max-width]="col.maxWidth ?? null"
250
256
  >
251
257
  @if (headerTemplateFor(col.key); as headerTpl) {
252
258
  <ng-container
@@ -255,7 +261,7 @@ import { TableColumn, TableSortChange } from './table-column';
255
261
  } @else if (col.sortable) {
256
262
  <button
257
263
  type="button"
258
- class="inline-flex cursor-pointer items-center gap-1 rounded-sm font-medium text-neutral-600 hover:text-ink focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ink dark:text-neutral-400 dark:hover:text-white"
264
+ class="inline-flex cursor-pointer items-center gap-1 rounded-sm font-medium text-neutral-600 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:text-white"
259
265
  (click)="onSortHeaderClick(col.key)"
260
266
  >
261
267
  <span>{{ col.header }}</span>
@@ -311,7 +317,7 @@ import { TableColumn, TableSortChange } from './table-column';
311
317
  <td [class]="expandBodyClass(i)">
312
318
  <button
313
319
  type="button"
314
- class="inline-flex size-8 cursor-pointer items-center justify-center rounded-md text-neutral-600 transition-colors hover:bg-background-welcome hover:text-ink focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ink dark:text-neutral-400 dark:hover:bg-white/10 dark:hover:text-white"
320
+ class="inline-flex size-8 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"
315
321
  [attr.aria-label]="
316
322
  isRowExpanded(row, i)
317
323
  ? 'Collapse row details'
@@ -330,7 +336,8 @@ import { TableColumn, TableSortChange } from './table-column';
330
336
  @for (col of columns(); track col.key) {
331
337
  <td
332
338
  [class]="bodyCellClass(col, i)"
333
- [style.width]="col.width ?? null"
339
+ [style.width]="col.width ?? col.maxWidth ?? null"
340
+ [style.max-width]="col.maxWidth ?? null"
334
341
  >
335
342
  @if (templateFor(col.key); as tpl) {
336
343
  <ng-container
@@ -360,7 +367,7 @@ import { TableColumn, TableSortChange } from './table-column';
360
367
  [class.pointer-events-none]="!isRowExpanded(row, i)"
361
368
  >
362
369
  <div
363
- class="min-h-0 overflow-hidden border-t border-border/70 bg-neutral-50 dark:border-white/10 dark:bg-white/[0.05]"
370
+ class="min-h-0 overflow-hidden border-t border-border-strong bg-surface-sunken dark:border-white/10 dark:bg-white/[0.05]"
364
371
  >
365
372
  <dl
366
373
  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"
@@ -370,7 +377,7 @@ import { TableColumn, TableSortChange } from './table-column';
370
377
  @for (detail of rowDetailDefs(); track detail.label()) {
371
378
  <div class="min-w-0">
372
379
  <dt
373
- class="m-0 text-caption font-medium text-neutral-500 dark:text-neutral-400"
380
+ class="m-0 text-caption font-medium text-neutral-600 dark:text-neutral-400"
374
381
  >
375
382
  {{ detail.label() }}
376
383
  </dt>
@@ -395,6 +402,18 @@ import { TableColumn, TableSortChange } from './table-column';
395
402
  }
396
403
  </tbody>
397
404
  </table>
405
+ @if (paginationLoading()) {
406
+ <div
407
+ class="pointer-events-none absolute inset-0 z-[5] flex items-start justify-center bg-surface/70 px-4 pt-16 dark:bg-ink-950/70"
408
+ data-testid="africanies-table-keep-rows-loading"
409
+ aria-hidden="true"
410
+ >
411
+ <africanies-loading-state
412
+ mode="inline"
413
+ [message]="loadingLabel()"
414
+ />
415
+ </div>
416
+ }
398
417
  </div>
399
418
 
400
419
  @if (meta(); as pager) {
@@ -431,6 +450,13 @@ export class TableComponent<T = unknown> {
431
450
  /** Column definitions (header chrome + keys). */
432
451
  readonly columns = input.required<TableColumn<T>[]>();
433
452
 
453
+ /**
454
+ * When true (default), pin column headers while scrolling the grid on
455
+ * large screens (`lg+`). Uses a capped scrollport so sticky works with
456
+ * horizontal overflow. Set false to keep the previous unconstrained layout.
457
+ */
458
+ readonly stickyHeader = input(true, { transform: booleanAttribute });
459
+
434
460
  /**
435
461
  * Row records to render. Empty arrays show {@link EmptyStateComponent} in
436
462
  * the body unless {@link loading} or {@link error} is set. Missing `data`
@@ -463,9 +489,9 @@ export class TableComponent<T = unknown> {
463
489
 
464
490
  /**
465
491
  * Page of data is loading (first load, shipping-mode switch, pagination,
466
- * page size). When rows are already on screen, the pager shows a spinner
467
- * and rows stay visible; when there are no rows (first load or the host
468
- * dropped STN/SFN rows after a mode switch), the body shows
492
+ * page size). When rows are already on screen, a keep-rows overlay covers
493
+ * the grid and the pager shows a spinner; when there are no rows (first
494
+ * load or the host dropped STN/SFN rows after a mode switch), the body shows
469
495
  * {@link LoadingStateComponent}. Distinct from {@link refreshing}.
470
496
  */
471
497
  readonly loading = input(false, { transform: booleanAttribute });
@@ -754,10 +780,22 @@ export class TableComponent<T = unknown> {
754
780
  '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 ' +
755
781
  this.headerSoftClass() +
756
782
  ' ' +
757
- this.stickySurfaceClass(col, 'head')
783
+ this.stickySurfaceClass(col, 'head') +
784
+ (sticky ? '' : this.headerStickClass())
758
785
  );
759
786
  }
760
787
 
788
+ /**
789
+ * Vertical pin for scrolling header cells on desktop. Pinned left/right
790
+ * headers get `lg:top-0` from {@link stickyPinClass} instead.
791
+ */
792
+ protected headerStickClass(): string {
793
+ if (!this.stickyHeader()) {
794
+ return '';
795
+ }
796
+ return ' lg:sticky lg:top-0 lg:z-[3] print:static';
797
+ }
798
+
761
799
  /**
762
800
  * Body cell classes, including sticky pin when set.
763
801
  * Sticky expand/actions columns use a 1.5px bottom border; scrolling cells
@@ -804,9 +842,13 @@ export class TableComponent<T = unknown> {
804
842
  edge === 'right' ? 'sticky right-0 z-[1]' : 'sticky left-0 z-[1]';
805
843
  if (surface === 'head') {
806
844
  // Fill comes from {@link headerSoftClass} on the cell — do not re-tint.
807
- return `${side} z-[2]`;
845
+ // Corner pins also stick vertically on desktop when stickyHeader is on.
846
+ const vertical = this.stickyHeader()
847
+ ? ' z-[2] lg:top-0 lg:z-[4] print:static'
848
+ : ' z-[2]';
849
+ return `${side}${vertical}`;
808
850
  }
809
- const fill = 'bg-white dark:bg-ink';
851
+ const fill = 'bg-surface dark:bg-ink-surface';
810
852
  return `${side} ${fill}`;
811
853
  }
812
854
 
@@ -25,14 +25,14 @@ import { ToastItemComponent } from './toast-item.component';
25
25
  <div class="flex w-full flex-col gap-2">
26
26
  @if (toastService.showHostActions()) {
27
27
  <div
28
- class="sticky top-0 z-10 flex flex-wrap justify-end gap-2 bg-white/80 pb-1 backdrop-blur-sm dark:bg-ink/80"
28
+ class="sticky top-0 z-10 flex flex-wrap justify-end gap-2 bg-white/80 pb-1 backdrop-blur-sm dark:bg-ink-surface/80"
29
29
  >
30
30
  @if (toastService.hasStacks()) {
31
31
  @if (toastService.allStacksExpanded()) {
32
32
  <button
33
33
  africanies-button
34
34
  type="button"
35
- variant="secondary"
35
+ variant="flat"
36
36
  size="sm"
37
37
  class="!min-h-0 !rounded-full !bg-white !px-2.5 !py-1 !text-caption dark:!bg-ink"
38
38
  (click)="toastService.collapseAll()"
@@ -43,7 +43,7 @@ import { ToastItemComponent } from './toast-item.component';
43
43
  <button
44
44
  africanies-button
45
45
  type="button"
46
- variant="secondary"
46
+ variant="flat"
47
47
  size="sm"
48
48
  class="!min-h-0 !rounded-full !bg-white !px-2.5 !py-1 !text-caption dark:!bg-ink"
49
49
  (click)="toastService.expandAll()"
@@ -55,7 +55,7 @@ import { ToastItemComponent } from './toast-item.component';
55
55
  <button
56
56
  africanies-button
57
57
  type="button"
58
- variant="secondary"
58
+ variant="flat"
59
59
  size="sm"
60
60
  class="!min-h-0 !rounded-full !bg-white !px-2.5 !py-1 !text-caption dark:!bg-ink"
61
61
  (click)="toastService.clear()"
@@ -260,9 +260,9 @@ export class ToastItemComponent {
260
260
 
261
261
  protected readonly shellClass = computed(
262
262
  () =>
263
- 'africanies-toast-enter relative flex w-full overflow-hidden rounded-lg border border-border ' +
264
- 'bg-white/95 text-ink shadow-lg backdrop-blur-md ' +
265
- 'dark:border-white/15 dark:bg-ink/95 dark:text-white',
263
+ 'africanies-toast-enter relative flex w-full overflow-hidden rounded-panel border border-border ' +
264
+ 'bg-surface/95 text-ink shadow-floating backdrop-blur-md ' +
265
+ 'dark:border-white/15 dark:bg-ink-950/95 dark:text-white',
266
266
  );
267
267
 
268
268
  protected readonly accentClass = computed(
@@ -272,11 +272,11 @@ export class ToastItemComponent {
272
272
  protected readonly iconClass = computed(() => {
273
273
  switch (this.item().variant) {
274
274
  case 'success':
275
- return 'text-export dark:text-export-light';
275
+ return 'text-export-strong dark:text-export-light';
276
276
  case 'warning':
277
277
  return 'text-warning-dark dark:text-warning';
278
278
  case 'danger':
279
- return 'text-danger';
279
+ return 'text-danger-dark dark:text-danger';
280
280
  default:
281
281
  return 'text-ink-blue dark:text-neutral-300';
282
282
  }
@@ -286,11 +286,11 @@ export class ToastItemComponent {
286
286
  const base = 'm-0 break-words text-body-sm font-semibold';
287
287
  switch (this.item().variant) {
288
288
  case 'success':
289
- return `${base} text-export dark:text-export-light`;
289
+ return `${base} text-export-strong dark:text-export-light`;
290
290
  case 'warning':
291
291
  return `${base} text-warning-dark dark:text-warning`;
292
292
  case 'danger':
293
- return `${base} text-danger`;
293
+ return `${base} text-danger-dark dark:text-danger`;
294
294
  default:
295
295
  return `${base} text-ink dark:text-white`;
296
296
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@africanies/angular-web-sdk",
3
- "version": "0.1.6",
3
+ "version": "0.1.8",
4
4
  "packageManager": "pnpm@11.24.0",
5
5
  "license": "MIT",
6
6
  "contributors": [
@@ -0,0 +1,9 @@
1
+ <svg width="16" height="15" viewBox="0 0 16 15" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path
3
+ fill-rule="evenodd"
4
+ clip-rule="evenodd"
5
+ d="M0.142433 5.8125C0.142433 6.8115 0.394433 7.74975 0.836933 8.5695C0.62996 8.65739 0.447722 8.79474 0.30621 8.96949C0.164697 9.14424 0.0682364 9.35105 0.0252912 9.57178C-0.0176541 9.7925 -0.00577094 10.0204 0.0598977 10.2354C0.125566 10.4505 0.243013 10.6462 0.401933 10.8053L3.64643 14.049C3.95198 14.3546 4.32385 14.5858 4.73318 14.7244C5.14251 14.8631 5.57829 14.9055 6.00668 14.8485L10.4924 14.25H12.8924V15H15.5174V13.875H14.0174V8.25H15.5174V7.125H12.8924V7.875H11.3909C11.7249 6.99496 11.8402 6.04697 11.7269 5.11253C11.6135 4.17809 11.2749 3.28516 10.7402 2.51051C10.2054 1.73585 9.49058 1.10266 8.65704 0.665352C7.8235 0.228047 6.89622 -0.00028052 5.95493 2.58646e-07C4.41336 2.58646e-07 2.93493 0.612387 1.84488 1.70244C0.75482 2.7925 0.142433 4.27093 0.142433 5.8125ZM5.95493 1.125C5.0719 1.12517 4.20686 1.37472 3.45942 1.84492C2.71198 2.31512 2.11253 2.98685 1.73009 3.78277C1.34765 4.57869 1.19776 5.46644 1.29769 6.3438C1.39762 7.22116 1.7433 8.05247 2.29493 8.742L4.64768 9.7995C4.6685 9.54613 4.74629 9.30073 4.87525 9.08164C5.00421 8.86255 5.18101 8.67542 5.39243 8.53425V8.25H4.64243V7.125H6.14243C6.24189 7.125 6.33727 7.08549 6.4076 7.01517C6.47792 6.94484 6.51743 6.84946 6.51743 6.75C6.51743 6.65054 6.47792 6.55516 6.4076 6.48483C6.33727 6.41451 6.24189 6.375 6.14243 6.375H5.76743C5.40208 6.37536 5.04916 6.24237 4.77491 6.00099C4.50066 5.7596 4.32393 5.42642 4.2779 5.06398C4.23187 4.70155 4.3197 4.33477 4.52491 4.03249C4.73012 3.73022 5.03859 3.51323 5.39243 3.42225V2.625H6.51743V3.375H7.26743V4.5H5.76743C5.66798 4.5 5.57259 4.53951 5.50227 4.60984C5.43194 4.68016 5.39243 4.77554 5.39243 4.875C5.39243 4.97446 5.43194 5.06984 5.50227 5.14017C5.57259 5.21049 5.66798 5.25 5.76743 5.25H6.14243C6.50778 5.24964 6.8607 5.38263 7.13496 5.62402C7.40921 5.8654 7.58593 6.19858 7.63196 6.56102C7.67799 6.92345 7.59016 7.29023 7.38495 7.59251C7.17975 7.89478 6.87127 8.11177 6.51743 8.20275V8.25H9.23843L10.1249 7.9545C10.4921 7.23989 10.6693 6.44291 10.6398 5.64006C10.6102 4.8372 10.3748 4.05542 9.95615 3.36973C9.53748 2.68405 8.94961 2.11748 8.24894 1.72439C7.54827 1.33131 6.75833 1.12491 5.95493 1.125ZM5.62343 11.4705L1.47593 9.60675C1.42279 9.58303 1.36303 9.57868 1.30701 9.59444C1.25099 9.6102 1.20227 9.64509 1.16929 9.69304C1.13632 9.74098 1.12118 9.79897 1.1265 9.85691C1.13182 9.91486 1.15727 9.96911 1.19843 10.0103L4.44143 13.2533C4.6248 13.4368 4.84801 13.5756 5.09372 13.6588C5.33943 13.7421 5.60103 13.7675 5.85818 13.7333L10.4182 13.125H12.8924V9H10.5464L9.42143 9.375H6.32993C6.18075 9.375 6.03767 9.43426 5.93219 9.53975C5.8267 9.64524 5.76743 9.78832 5.76743 9.9375C5.76743 10.0867 5.8267 10.2298 5.93219 10.3352C6.03767 10.4407 6.18075 10.5 6.32993 10.5H9.56243L10.4774 11.415L9.68243 12.21L9.09743 11.625H6.32993C6.07793 11.625 5.83793 11.5695 5.62343 11.4705Z"
6
+ fill="#1C2E45"
7
+ fill-opacity="0.6"
8
+ />
9
+ </svg>
@@ -1 +0,0 @@
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":"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"}